Menu

#20 Support XMLChanges

1.0
wont-fix
nobody
None
2016-03-25
2016-03-23
No

Hi Lucian,

it would be very good to support the XMLChanges in phrasedml. You already have some proposed syntax in the tutorial. With the XMLChanges we would support the full L1V2 specification with the phrasedml, antimony, tellurium stack.
see also https://github.com/sys-bio/tellurium/issues/115

I already have some use cases where I need the XMLChanges:
- changing the species boundaryCondition from True to False and const from True to False (to test how model behaves if I let the species go)
- replacing a const=true parameter with const=false and adding rule for calculation of the parameter to the model

Like mentioned in
https://github.com/sys-bio/tellurium/issues/114#issuecomment-197400001
it would be very nice to have some helper functions in libsbml for this kind of manipulation. This would make handling these things reproducible and easy for the user.

getElement(s)ByXPath(xpath)   # gets Element(s) from xpath
addXML(xpath, xml)               # adds xml to the element specified by xpath
changeXML(xpath, xml)               # changes xml 
removeXML(xpath)                # remove xml at xpath

I will implement the tellurium part of the XMLChanges in mid/end of April.
Matthias

Discussion

  • Lucian Smith

    Lucian Smith - 2016-03-23

    As a workaround, I would suggest doing this with modular Antimony:

    model one()
    const species S1=3
    end

    model two()
    A: one()
    var species S1
    A.S1 is S1
    end


    model one()
    x=3
    end

    model two()
    A: one()
    A.x is x
    x := time+2
    end

    As a bonus, this will end up being much more exchangeable, since few tools implement XMLChange support, I think.

     
  • Matthias König

    Matthias König - 2016-03-24

    Hi Lucian,
    this works great for the given example.

    I tried a bit more complex case and got into trouble. I mainly want to modify an existing SBML model, so I do the following
    - load SBML
    - convert to antimony
    - define antimony change model (bitsandpieces)
    - combine the two antimony strings
    - load the combined antimony model
    - strangly the changes are not applied to the model (do I have to define a master model or something? what does the * in front of the model id mean? is this an indicator for that?)
    I looked some time for obvious errors, but not sure why the following is not working.

    from __future__ import print_function, division
    import tellurium as te
    
    # Load an SBML model
    r = te.loads("Koenig_demo_10.xml")
    antDemo = r.getAntimony()
    
    # Simulate unmodified model
    sr = r.simulate(0, 10, 101)
    r.plot(sr)
    
    # Change Km_A value over time 
    antMod1 = """
    model Mod1()
        A: Koenig_demo_10();
        A.Km_A is Km_A;
        Km_A := 1.1+sin(time);
    end
    """
    
    # Simulate the modified model (original model is required as part of antimony string)
    antDemoMod1 = antDemo + antMod1
    rMod1 = te.loada(antDemoMod1)
    sMod1 = rMod1.simulate(0, 10, 101)
    rMod1.plot(sMod1)
    
    print('*** Modified Antimony model ***')
    print(antDemoMod1)
    print('*** Modified SBML model ***')
    print(rMod1.getSBML())
    

    The created antimony and sbml via antimony are attached below. The antimony string contains the changes, the SBML does not have the changed Km_A ?
    How do I load an SBML model and modify it?

    *** Modified Antimony model ***
    // Created by libAntimony v2.9.0
    model *Koenig_demo_10()
    
      // Compartments and Species:
      compartment e, c;
      species e__A in e, e__C in e, e__B in e, c__C in c, c__B in c, c__A in c;
    
      // Reactions:
      bA: e__A => c__A; scale_f*(Vmax_bA/Km_A)*(e__A - c__A)/(1 dimensionless + e__A/Km_A + c__A/Km_A);
      bB: c__B => e__B; scale_f*(Vmax_bB/Km_B)*(c__B - e__B)/(1 dimensionless + e__B/Km_B + c__B/Km_B);
      bC: c__C => e__C; scale_f*(Vmax_bC/Km_C)*(c__C - e__C)/(1 dimensionless + e__C/Km_C + c__C/Km_C);
      v1 in c: c__A => c__B; (scale_f*Vmax_v1/Km_A)*(c__A - (1 dimensionless/Keq_v1)*c__B);
      v2 in c: c__A => c__C; (scale_f*Vmax_v2/Km_A)*c__A;
      v3 in c: c__C => c__A; (scale_f*Vmax_v3/Km_A)*c__C;
      v4 in c: c__C => c__B; (scale_f*Vmax_v4/Km_A)*(c__C - (1 dimensionless/Keq_v4)*c__B);
    
      // Species initializations:
      e__A = 10;
      e__A has mM;
      e__C = 0;
      e__C has mM;
      e__B = 0;
      e__B has mM;
      c__C = 0;
      c__C has mM;
      c__B = 0;
      c__B has mM;
      c__A = 0;
      c__A has mM;
    
      // Compartment initializations:
      e = 1e-06;
      e has m3;
      c = 1e-06;
      c has m3;
    
      // Variable initializations:
      Km_C = 3;
      Km_C has mM;
      scale_f = 1e-06;
      scale_f has dimensionless;
      Vmax_bB = 2;
      Vmax_bB has mole_per_s;
      Vmax_bC = 2;
      Vmax_bC has mole_per_s;
      Vmax_bA = 5;
      Vmax_bA has mole_per_s;
      Vmax_v2 = 0.5;
      Vmax_v2 has mole_per_s;
      Vmax_v3 = 0.5;
      Vmax_v3 has mole_per_s;
      Vmax_v1 = 1;
      Vmax_v1 has mole_per_s;
      Km_A = 1;
      Km_A has mM;
      Vmax_v4 = 0.5;
      Vmax_v4 has mole_per_s;
      Km_B = 0.5;
      Km_B has mM;
      Keq_v4 = 2;
      Keq_v4 has dimensionless;
      Keq_v1 = 10;
      Keq_v1 has dimensionless;
    
      // Other declarations:
      var e, c;
      const Km_C, scale_f, Vmax_bB, Vmax_bC, Vmax_bA, Vmax_v2, Vmax_v3, Vmax_v1;
      const Km_A, Vmax_v4, Km_B, Keq_v4, Keq_v1;
    
      // Unit definitions:
      unit kg = kilogram;
      unit mM = mole / metre^3;
      unit m = metre;
      unit s = second;
      unit m3 = metre^3;
      unit m2 = metre^2;
      unit mole_per_s = mole / second;
      unit length = m;
      unit area = m2;
      unit volume = m3;
      unit substance = mole;
      unit extent = mole;
      unit time_unit = s;
    
      // Display Names:
      m is "plasma membrane";
      e is "external compartment";
      c is "cell compartment";
      e__A is "A";
      e__C is "C";
      e__B is "B";
      c__C is "C";
      c__B is "B";
      c__A is "A";
      scale_f is "metabolic scaling factor";
      bA is "bA (A import)";
      bB is "bB (B export)";
      bC is "bC (C export)";
      v1 is "v1 (A -> B)";
      v2 is "v2 (A -> C)";
      v3 is "v3 (C -> A)";
      v4 is "v4 (C -> B)";
    end
    
    model Mod1()
        A: Koenig_demo_10();
        A.Km_A is Km_A;
        Km_A := 1.1+sin(time);
    end
    
    *** Modified SBML model ***
    <?xml version="1.0" encoding="UTF-8"?>
    <!-- Created by libAntimony version v2.9.0 with libSBML version 5.12.1. -->
    <sbml xmlns="http://www.sbml.org/sbml/level3/version1/core" level="3" version="1">
      <model id="Koenig_demo_10" name="Koenig_demo_10" substanceUnits="substance" timeUnits="time_unit" volumeUnits="volume" areaUnits="area" lengthUnits="length" extentUnits="extent">
        <listOfUnitDefinitions>
          <unitDefinition id="mM">
            <listOfUnits>
              <unit kind="mole" exponent="1" scale="0" multiplier="1"/>
              <unit kind="metre" exponent="-3" scale="0" multiplier="1"/>
            </listOfUnits>
          </unitDefinition>
          <unitDefinition id="m3">
            <listOfUnits>
              <unit kind="metre" exponent="3" scale="0" multiplier="1"/>
            </listOfUnits>
          </unitDefinition>
          <unitDefinition id="mole_per_s">
            <listOfUnits>
              <unit kind="mole" exponent="1" scale="0" multiplier="1"/>
              <unit kind="second" exponent="-1" scale="0" multiplier="1"/>
            </listOfUnits>
          </unitDefinition>
          <unitDefinition id="kg">
            <listOfUnits>
              <unit kind="kilogram" exponent="1" scale="0" multiplier="1"/>
            </listOfUnits>
          </unitDefinition>
          <unitDefinition id="m" name="plasma membrane">
            <listOfUnits>
              <unit kind="metre" exponent="1" scale="0" multiplier="1"/>
            </listOfUnits>
          </unitDefinition>
          <unitDefinition id="s">
            <listOfUnits>
              <unit kind="second" exponent="1" scale="0" multiplier="1"/>
            </listOfUnits>
          </unitDefinition>
          <unitDefinition id="m2">
            <listOfUnits>
              <unit kind="metre" exponent="2" scale="0" multiplier="1"/>
            </listOfUnits>
          </unitDefinition>
          <unitDefinition id="length">
            <listOfUnits>
              <unit kind="metre" exponent="1" scale="0" multiplier="1"/>
            </listOfUnits>
          </unitDefinition>
          <unitDefinition id="area">
            <listOfUnits>
              <unit kind="metre" exponent="2" scale="0" multiplier="1"/>
            </listOfUnits>
          </unitDefinition>
          <unitDefinition id="volume">
            <listOfUnits>
              <unit kind="metre" exponent="3" scale="0" multiplier="1"/>
            </listOfUnits>
          </unitDefinition>
          <unitDefinition id="substance">
            <listOfUnits>
              <unit kind="mole" exponent="1" scale="0" multiplier="1"/>
            </listOfUnits>
          </unitDefinition>
          <unitDefinition id="extent">
            <listOfUnits>
              <unit kind="mole" exponent="1" scale="0" multiplier="1"/>
            </listOfUnits>
          </unitDefinition>
          <unitDefinition id="time_unit">
            <listOfUnits>
              <unit kind="second" exponent="1" scale="0" multiplier="1"/>
            </listOfUnits>
          </unitDefinition>
        </listOfUnitDefinitions>
        <listOfCompartments>
          <compartment id="e" name="external compartment" spatialDimensions="3" size="1e-06" units="m3" constant="false"/>
          <compartment id="c" name="cell compartment" spatialDimensions="3" size="1e-06" units="m3" constant="false"/>
        </listOfCompartments>
        <listOfSpecies>
          <species id="e__A" name="A" compartment="e" initialConcentration="10" substanceUnits="mole" hasOnlySubstanceUnits="false" boundaryCondition="false" constant="false"/>
          <species id="e__C" name="C" compartment="e" initialConcentration="0" substanceUnits="mole" hasOnlySubstanceUnits="false" boundaryCondition="false" constant="false"/>
          <species id="e__B" name="B" compartment="e" initialConcentration="0" substanceUnits="mole" hasOnlySubstanceUnits="false" boundaryCondition="false" constant="false"/>
          <species id="c__C" name="C" compartment="c" initialConcentration="0" substanceUnits="mole" hasOnlySubstanceUnits="false" boundaryCondition="false" constant="false"/>
          <species id="c__B" name="B" compartment="c" initialConcentration="0" substanceUnits="mole" hasOnlySubstanceUnits="false" boundaryCondition="false" constant="false"/>
          <species id="c__A" name="A" compartment="c" initialConcentration="0" substanceUnits="mole" hasOnlySubstanceUnits="false" boundaryCondition="false" constant="false"/>
        </listOfSpecies>
        <listOfParameters>
          <parameter id="scale_f" name="metabolic scaling factor" value="1e-06" units="dimensionless" constant="true"/>
          <parameter id="Vmax_bA" value="5" units="mole_per_s" constant="true"/>
          <parameter id="Km_A" value="1" units="mM" constant="true"/>
          <parameter id="Vmax_bB" value="2" units="mole_per_s" constant="true"/>
          <parameter id="Km_B" value="0.5" units="mM" constant="true"/>
          <parameter id="Vmax_bC" value="2" units="mole_per_s" constant="true"/>
          <parameter id="Km_C" value="3" units="mM" constant="true"/>
          <parameter id="Vmax_v1" value="1" units="mole_per_s" constant="true"/>
          <parameter id="Keq_v1" value="10" units="dimensionless" constant="true"/>
          <parameter id="Vmax_v2" value="0.5" units="mole_per_s" constant="true"/>
          <parameter id="Vmax_v3" value="0.5" units="mole_per_s" constant="true"/>
          <parameter id="Vmax_v4" value="0.5" units="mole_per_s" constant="true"/>
          <parameter id="Keq_v4" value="2" units="dimensionless" constant="true"/>
        </listOfParameters>
        <listOfReactions>
          <reaction id="bA" name="bA (A import)" reversible="false" fast="false">
            <listOfReactants>
              <speciesReference species="e__A" stoichiometry="1" constant="true"/>
            </listOfReactants>
            <listOfProducts>
              <speciesReference species="c__A" stoichiometry="1" constant="true"/>
            </listOfProducts>
            <kineticLaw>
              <math xmlns="http://www.w3.org/1998/Math/MathML" xmlns:sbml="http://www.sbml.org/sbml/level3/version1/core">
                <apply>
                  <divide/>
                  <apply>
                    <times/>
                    <ci> scale_f </ci>
                    <apply>
                      <divide/>
                      <ci> Vmax_bA </ci>
                      <ci> Km_A </ci>
                    </apply>
                    <apply>
                      <minus/>
                      <ci> e__A </ci>
                      <ci> c__A </ci>
                    </apply>
                  </apply>
                  <apply>
                    <plus/>
                    <cn sbml:units="dimensionless" type="integer"> 1 </cn>
                    <apply>
                      <divide/>
                      <ci> e__A </ci>
                      <ci> Km_A </ci>
                    </apply>
                    <apply>
                      <divide/>
                      <ci> c__A </ci>
                      <ci> Km_A </ci>
                    </apply>
                  </apply>
                </apply>
              </math>
            </kineticLaw>
          </reaction>
          <reaction id="bB" name="bB (B export)" reversible="false" fast="false">
            <listOfReactants>
              <speciesReference species="c__B" stoichiometry="1" constant="true"/>
            </listOfReactants>
            <listOfProducts>
              <speciesReference species="e__B" stoichiometry="1" constant="true"/>
            </listOfProducts>
            <kineticLaw>
              <math xmlns="http://www.w3.org/1998/Math/MathML" xmlns:sbml="http://www.sbml.org/sbml/level3/version1/core">
                <apply>
                  <divide/>
                  <apply>
                    <times/>
                    <ci> scale_f </ci>
                    <apply>
                      <divide/>
                      <ci> Vmax_bB </ci>
                      <ci> Km_B </ci>
                    </apply>
                    <apply>
                      <minus/>
                      <ci> c__B </ci>
                      <ci> e__B </ci>
                    </apply>
                  </apply>
                  <apply>
                    <plus/>
                    <cn sbml:units="dimensionless" type="integer"> 1 </cn>
                    <apply>
                      <divide/>
                      <ci> e__B </ci>
                      <ci> Km_B </ci>
                    </apply>
                    <apply>
                      <divide/>
                      <ci> c__B </ci>
                      <ci> Km_B </ci>
                    </apply>
                  </apply>
                </apply>
              </math>
            </kineticLaw>
          </reaction>
          <reaction id="bC" name="bC (C export)" reversible="false" fast="false">
            <listOfReactants>
              <speciesReference species="c__C" stoichiometry="1" constant="true"/>
            </listOfReactants>
            <listOfProducts>
              <speciesReference species="e__C" stoichiometry="1" constant="true"/>
            </listOfProducts>
            <kineticLaw>
              <math xmlns="http://www.w3.org/1998/Math/MathML" xmlns:sbml="http://www.sbml.org/sbml/level3/version1/core">
                <apply>
                  <divide/>
                  <apply>
                    <times/>
                    <ci> scale_f </ci>
                    <apply>
                      <divide/>
                      <ci> Vmax_bC </ci>
                      <ci> Km_C </ci>
                    </apply>
                    <apply>
                      <minus/>
                      <ci> c__C </ci>
                      <ci> e__C </ci>
                    </apply>
                  </apply>
                  <apply>
                    <plus/>
                    <cn sbml:units="dimensionless" type="integer"> 1 </cn>
                    <apply>
                      <divide/>
                      <ci> e__C </ci>
                      <ci> Km_C </ci>
                    </apply>
                    <apply>
                      <divide/>
                      <ci> c__C </ci>
                      <ci> Km_C </ci>
                    </apply>
                  </apply>
                </apply>
              </math>
            </kineticLaw>
          </reaction>
          <reaction id="v1" name="v1 (A -&gt; B)" reversible="false" fast="false" compartment="c">
            <listOfReactants>
              <speciesReference species="c__A" stoichiometry="1" constant="true"/>
            </listOfReactants>
            <listOfProducts>
              <speciesReference species="c__B" stoichiometry="1" constant="true"/>
            </listOfProducts>
            <kineticLaw>
              <math xmlns="http://www.w3.org/1998/Math/MathML" xmlns:sbml="http://www.sbml.org/sbml/level3/version1/core">
                <apply>
                  <times/>
                  <apply>
                    <divide/>
                    <apply>
                      <times/>
                      <ci> scale_f </ci>
                      <ci> Vmax_v1 </ci>
                    </apply>
                    <ci> Km_A </ci>
                  </apply>
                  <apply>
                    <minus/>
                    <ci> c__A </ci>
                    <apply>
                      <times/>
                      <apply>
                        <divide/>
                        <cn sbml:units="dimensionless" type="integer"> 1 </cn>
                        <ci> Keq_v1 </ci>
                      </apply>
                      <ci> c__B </ci>
                    </apply>
                  </apply>
                </apply>
              </math>
            </kineticLaw>
          </reaction>
          <reaction id="v2" name="v2 (A -&gt; C)" reversible="false" fast="false" compartment="c">
            <listOfReactants>
              <speciesReference species="c__A" stoichiometry="1" constant="true"/>
            </listOfReactants>
            <listOfProducts>
              <speciesReference species="c__C" stoichiometry="1" constant="true"/>
            </listOfProducts>
            <kineticLaw>
              <math xmlns="http://www.w3.org/1998/Math/MathML">
                <apply>
                  <times/>
                  <apply>
                    <divide/>
                    <apply>
                      <times/>
                      <ci> scale_f </ci>
                      <ci> Vmax_v2 </ci>
                    </apply>
                    <ci> Km_A </ci>
                  </apply>
                  <ci> c__A </ci>
                </apply>
              </math>
            </kineticLaw>
          </reaction>
          <reaction id="v3" name="v3 (C -&gt; A)" reversible="false" fast="false" compartment="c">
            <listOfReactants>
              <speciesReference species="c__C" stoichiometry="1" constant="true"/>
            </listOfReactants>
            <listOfProducts>
              <speciesReference species="c__A" stoichiometry="1" constant="true"/>
            </listOfProducts>
            <kineticLaw>
              <math xmlns="http://www.w3.org/1998/Math/MathML">
                <apply>
                  <times/>
                  <apply>
                    <divide/>
                    <apply>
                      <times/>
                      <ci> scale_f </ci>
                      <ci> Vmax_v3 </ci>
                    </apply>
                    <ci> Km_A </ci>
                  </apply>
                  <ci> c__C </ci>
                </apply>
              </math>
            </kineticLaw>
          </reaction>
          <reaction id="v4" name="v4 (C -&gt; B)" reversible="false" fast="false" compartment="c">
            <listOfReactants>
              <speciesReference species="c__C" stoichiometry="1" constant="true"/>
            </listOfReactants>
            <listOfProducts>
              <speciesReference species="c__B" stoichiometry="1" constant="true"/>
            </listOfProducts>
            <kineticLaw>
              <math xmlns="http://www.w3.org/1998/Math/MathML" xmlns:sbml="http://www.sbml.org/sbml/level3/version1/core">
                <apply>
                  <times/>
                  <apply>
                    <divide/>
                    <apply>
                      <times/>
                      <ci> scale_f </ci>
                      <ci> Vmax_v4 </ci>
                    </apply>
                    <ci> Km_A </ci>
                  </apply>
                  <apply>
                    <minus/>
                    <ci> c__C </ci>
                    <apply>
                      <times/>
                      <apply>
                        <divide/>
                        <cn sbml:units="dimensionless" type="integer"> 1 </cn>
                        <ci> Keq_v4 </ci>
                      </apply>
                      <ci> c__B </ci>
                    </apply>
                  </apply>
                </apply>
              </math>
            </kineticLaw>
          </reaction>
        </listOfReactions>
      </model>
    </sbml>
    
     
  • Lucian Smith

    Lucian Smith - 2016-03-24

    As you suspected, the issue is with the asterisk, which means 'Use this model as the default model in this file.' If you load an Antimony string and then ask it for 'the SBML model' (i.e. give it an argument of 'NULL', which tellurium does behind the scenes), it will give you the default model.

    If no model is marked with an asterisk, it will give you the '__main" model if there is such a thing (i.e. the model not wrapped in 'model foo() ... end'), and otherwise will give you the model you defined last.

    Fortunately in this case, if you define two different models with an asterisk, it will use the last one defined in the input as the default. This lets us change your script to the following, which works:

    from __future__ import print_function, division
    import tellurium as te
    
    # Load an SBML model
    r = te.loads("Koenig_demo_10.xml")
    antDemo = r.getAntimony()
    
    # Simulate unmodified model
    sr = r.simulate(0, 10, 101)
    r.plot(sr)
    
    # Change Km_A value over time 
    antMod1 = """
    model *Mod1()
        A: Koenig_demo_10();
        A.Km_A is Km_A;
        Km_A := 1.1+sin(time);
    end
    """
    
    # Simulate the modified model (original model is required as part of antimony string)
    antDemoMod1 = antDemo + antMod1
    rMod1 = te.loada(antDemoMod1)
    sMod1 = rMod1.simulate(0, 10, 101)
    rMod1.plot(sMod1)
    
    print('*** Modified Antimony model ***')
    print(antDemoMod1)
    print('*** Modified SBML model ***')
    print(rMod1.getSBML())
    
     
  • Matthias König

    Matthias König - 2016-03-25

    Perfect.

    So in my opinion we should drop XMLChange support in tellurium/phrasedml completely than.
    We have the alternative method of providing derived models and using them directly in the SEDML. This provides a mean to encode all of the "useful" model changes, i.e. changes which create another useful/working model afterwards. This is so much cleaner and error-free than any of the XMLChanges directly in SEDML which will never guarantee that a useful/valid model comes out of it. In addition it does not require manipulation of the XML Dom.

    I will create a handful of standard model changes/deletions/insertions people would want to perform. I think with the derived model syntax most (all?) use cases can be handled.
    We should recommend this approach to any manipulations via XMLChanges/Removals/Additions.

     
  • Lucian Smith

    Lucian Smith - 2016-03-25

    That certainly works for me!

    A further argument in favor of not trying to support this is that there is no parallel standard simulator command they correspond to: you can say r.S1=3 and change the value of S1, but nobody even thinks about the possibility of having 'r.insert("S1:=time+2")'. Those sorts of manipulations are carried out at the modeling level

     
  • Lucian Smith

    Lucian Smith - 2016-03-25
    • status: open --> wont-fix
     
  • Lucian Smith

    Lucian Smith - 2016-03-25

    Closing this as 'wontfix', since we're encouraging people to use alternate methods of accomplishing the same thing.

     

Log in to post a comment.