sys-bio / tellurium

Python Environment for Modeling and Simulating Biological Systems
http://tellurium.analogmachine.org/
Apache License 2.0
108 stars 36 forks source link

Issue with translating sedml to python #179

Closed kirichoi closed 7 years ago

kirichoi commented 7 years ago

Found this issue which might be coming from libSBML 5.15.0

I was testing phrasedml execution and found errors. Realized that the python script generated from sedml is different. Below is what I get for datagenerators:

__var__task1_____z = np.transpose(np.array([sim['z'] for sim in task1]))
if len(__var__task1_____z.shape) == 1:
     __var__task1_____z.shape += (1,)
plot_0_0_0 = log10()

# DataGenerator <plot_0_0_1>
__var__task1_____x = np.transpose(np.array([sim['x'] for sim in task1]))
if len(__var__task1_____x.shape) == 1:
     __var__task1_____x.shape += (1,)
plot_0_0_1 = log10()

This is what it should look like (generated from Windows version of Telluirum 1.3.6):

__var__task1_____z = np.transpose(np.array([sim['z'] for sim in task1]))
if len(__var__task1_____z.shape) == 1:
     __var__task1_____z.shape += (1,)
plot_0_0_0 = __var__task1_____z

# DataGenerator <plot_0_0_1>
__var__task1_____x = np.transpose(np.array([sim['x'] for sim in task1]))
if len(__var__task1_____x.shape) == 1:
     __var__task1_____x.shape += (1,)
plot_0_0_1 = __var__task1_____x

Note the difference (log10()), which is coming out of nowhere. I think this is coming out of tesedml.dataGeneratorToPython(). A line in this function calls mathml.evaluableMathML() which fills in the problematic line. I do not know whether this is from incorrect astnode getting passed, or incorrect output of libsbml.formulaToL3String() which is part of mathml.evaluableMathML().

hsauro commented 7 years ago

Lucian will know about the math side of things.

Herbert

On Fri, May 12, 2017 at 12:51 PM, Kiri Choi notifications@github.com wrote:

Found this issue which might be coming from libSBML 5.15.0

I was testing phrasedml execution and found errors. Realized that the python script generated from sedml is different. Below is what I get for datagenerators:

vartask1z = np.transpose(np.array([sim['z'] for sim in task1])) if len(vartask1z.shape) == 1: vartask1_____z.shape += (1,) plot_0_0_0 = log10()

DataGenerator

vartask1x = np.transpose(np.array([sim['x'] for sim in task1])) if len(vartask1x.shape) == 1: vartask1_____x.shape += (1,) plot_0_0_1 = log10()

This is what it should look like (generated from Windows version of Telluirum 1.3.6):

vartask1z = np.transpose(np.array([sim['z'] for sim in task1])) if len(vartask1z.shape) == 1: vartask1___z.shape += (1,) plot_0_0_0 = var__task1_____z

DataGenerator

vartask1x = np.transpose(np.array([sim['x'] for sim in task1])) if len(vartask1x.shape) == 1: vartask1___x.shape += (1,) plot_0_0_1 = var__task1_____x

Note the difference (log10()), which is coming out of nowhere. I think this is coming out of tesedml.dataGeneratorToPython(). A line in this function calls mathml.evaluableMathML() which fills in the problematic line. I do not know whether this is from incorrect astnode getting passed, or incorrect output of libsbml.formulaToL3String() which is part of mathml.evaluableMathML().

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/sys-bio/tellurium/issues/179, or mute the thread https://github.com/notifications/unsubscribe-auth/ABAZDrdePfHrCzdDIddsiJh6S6Q66Abcks5r5LhegaJpZM4NZtnq .

0u812 commented 7 years ago

@kirichoi you mentioned phrasedml in your comment. Is phrasedml the starting point, or is it a SED-ML file? Can you post the file you are using?

luciansmith commented 7 years ago

Yeah, I can't quite tell what I'm looking at, or how each bit was generated.

kirichoi commented 7 years ago

Phrasedml is the starting point. What I was working on was the lorenz attractor example for phrasedml paper.

import tellurium as te

antimonyStr = '''
model lorenz
  x' = sigma*(y - x);
  y' = x*(rho - z) - y;
  z' = x*y - beta*z;
  x = 0.96259;  y = 2.07272;  z = 18.65888;
  sigma = 10;  rho = 28; beta = 2.67;
end
'''

phrasedmlStr = '''
model1 = model "lorenz"
sim1 = simulate uniform(0,15,2000)
task1 = run sim1 on model1
plot "Lorenz Attractor" task1.z vs task1.x
'''

exp = te.experiment(antimonyStr, phrasedmlStr)
#exp.execute(phrasedmlStr)
exp.printPython()

However, I do not think this is a phrasedml issue.

This is the SED-ML generated from phrasedml string above:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Created by phraSED-ML version v1.0.4 with libSBML version 5.14.1. -->
<sedML xmlns="http://sed-ml.org/sed-ml/level1/version2" level="1" version="2">
  <listOfSimulations>
    <uniformTimeCourse id="sim1" initialTime="0" outputStartTime="0" outputEndTime="15" numberOfPoints="2000">
      <algorithm kisaoID="KISAO:0000019"/>
    </uniformTimeCourse>
  </listOfSimulations>
  <listOfModels>
    <model id="model1" language="urn:sedml:language:sbml.level-3.version-2" source="lorenz.xml"/>
  </listOfModels>
  <listOfTasks>
    <task id="task1" modelReference="model1" simulationReference="sim1"/>
  </listOfTasks>
  <listOfDataGenerators>
    <dataGenerator id="plot_0_0_0" name="task1.z">
      <listOfVariables>
        <variable id="task1_____z" target="/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='z']" taskReference="task1" modelReference="model1"/>
      </listOfVariables>
      <math xmlns="http://www.w3.org/1998/Math/MathML">
        <ci> task1_____z </ci>
      </math>
    </dataGenerator>
    <dataGenerator id="plot_0_0_1" name="task1.x">
      <listOfVariables>
        <variable id="task1_____x" target="/sbml:sbml/sbml:model/sbml:listOfParameters/sbml:parameter[@id='x']" taskReference="task1" modelReference="model1"/>
      </listOfVariables>
      <math xmlns="http://www.w3.org/1998/Math/MathML">
        <ci> task1_____x </ci>
      </math>
    </dataGenerator>
  </listOfDataGenerators>
  <listOfOutputs>
    <plot2D id="plot_0" name="Lorenz Attractor">
      <listOfCurves>
        <curve id="plot_0__plot_0_0_0__plot_0_0_1" logX="false" logY="false" xDataReference="plot_0_0_0" yDataReference="plot_0_0_1"/>
      </listOfCurves>
    </plot2D>
  </listOfOutputs>
</sedML>

Feeding this to sedmlToPython() somehow changes task1z and task1x (which are the same as variables) to log10().

luciansmith commented 7 years ago

The one connection between plots and logs is that you can plot things on a log scale or not. Since logX and logY are 'false', I can imagine some sort of bug in sedmlToPython where it is deciding whether to print 'x' or 'log10(x)', decides it doesn't want 'log10(x)', and then removes 'x' instead of removing 'log10'.

kirichoi commented 7 years ago

Reasons why I was suspicious with other packages are because:

  1. This code used to work fine. Nothing really changed in sedml to python translation.
  2. Currently, the way sedmlToPython() is implemented is that there are separate functions for translating simulations, tasks, datagenerators, etc. Thus, it's highly unlikely that calling log in output will have an effect.

Now, based on your suggestion, it seems like we need to make sure we change log10 to something Python can read (there are few of these already implemented, I believe), so that if someone wants log operations, it actually works. However, the problem here is that no log operations are instructed in SED-ML.

luciansmith commented 7 years ago

It does sound like a library change is the root cause of the problem, if the code hasn't changed, but now fails. But it may or may not be a bug in that library. Hard to say until we track down what's going on.

One option might be to change the libraries one at a time and see if the bug goes away again. Another thing would be to check out old versions of sedmlToPython() and see if known-to-have-worked versions still work or not.

0u812 commented 7 years ago

I don't get this problem on my pre-release build of tellurium 2.0.0, and I'm using and linking to libSBML 5.15.0 throughout. Here is the converted Python file:

"""
    tellurium 2.0.0

    auto-generated code
    sedmlDoc: L1V2
    workingDir: /var/folders/c7/p9f12_q129z8gx1s_4lbwmth0000gn/T/tmpteof9o98_sedml
    inputType: SEDML_FILE
"""
import tellurium as te
from roadrunner import Config
from tellurium.sedml.mathml import *
from tellurium.sedml.tesedml import process_trace
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d
import tesedml as libsedml
import pandas
import os.path
Config.LOADSBMLOPTIONS_RECOMPILE = True

workingDir = r'/var/folders/c7/p9f12_q129z8gx1s_4lbwmth0000gn/T/tmpteof9o98_sedml'

# --------------------------------------------------------
# Models
# --------------------------------------------------------
# Model <model1>
model1 = te.loadSBMLModel(os.path.join(workingDir, 'lorenz.xml'))
model1.conservedMoietyAnalysis = True

# --------------------------------------------------------
# Tasks
# --------------------------------------------------------
# Task <task1>
# Task: <task1>
task1 = [None]
model1.setIntegrator('cvode')
model1.timeCourseSelections = ['x', 'z']
task1[0] = model1.simulate(start=0.0, end=15.0, steps=2000)

# --------------------------------------------------------
# DataGenerators
# --------------------------------------------------------
# DataGenerator <plot_0_0_0>
__var__task1_____z = np.concatenate([process_trace(sim['z']) for sim in task1])
if len(__var__task1_____z.shape) == 1:
     __var__task1_____z.shape += (1,)
plot_0_0_0 = __var__task1_____z

# DataGenerator <plot_0_0_1>
__var__task1_____x = np.concatenate([process_trace(sim['x']) for sim in task1])
if len(__var__task1_____x.shape) == 1:
     __var__task1_____x.shape += (1,)
plot_0_0_1 = __var__task1_____x

# --------------------------------------------------------
# Outputs
# --------------------------------------------------------
# Output <plot_0>
stacked=False
if not stacked:
    fig = te.getPlottingEngine().newFigure(title='Lorenz Attractor')
else:
    fig = te.getPlottingEngine().newStackedFigure(title='Lorenz Attractor')
if plot_0_0_0.shape[1] > 1:
    for k in range(plot_0_0_0.shape[1]):
        if k == 0:
            fig.addXYDataset(plot_0_0_0[:,k], plot_0_0_1[:,k], color='C0', tag='tag0', name='task1.x')
        else:
            fig.addXYDataset(plot_0_0_0[:,k], plot_0_0_1[:,k], color='C0', tag='tag0')
else:
    for k in range(plot_0_0_0.shape[1]):
        if k == 0:
            fig.addXYDataset(plot_0_0_0[:,k], plot_0_0_1[:,k], color='C0', tag='tag0', name='task1.x')
        else:
            fig.addXYDataset(plot_0_0_0[:,k], plot_0_0_1[:,k], color='C0', tag='tag0')
fig.plot()
kirichoi commented 7 years ago

Hmm, so I guess it's fixed? Is tesedml a replacement for libsedml? This could also be something to do with particular libsedml I have compiled and using.

kirichoi commented 7 years ago

I am closing this issue since this seems to be at least not a problem at our end.