diff --git a/src/MoBi.Engine/EngineRegister.cs b/src/MoBi.Engine/EngineRegister.cs index bce5d30e5..8a0054f9a 100644 --- a/src/MoBi.Engine/EngineRegister.cs +++ b/src/MoBi.Engine/EngineRegister.cs @@ -13,12 +13,14 @@ public override void RegisterInContainer(IContainer container) x.AssemblyContainingType(); x.WithConvention(new OSPSuiteRegistrationConvention(registerConcreteType: true)); x.ExcludeType(); + x.ExcludeType(); x.ExcludeType(); }); container.Register(); container.Register(); container.Register(LifeStyle.Singleton); + container.Register(LifeStyle.Singleton); container.Register(LifeStyle.Singleton); } } diff --git a/src/MoBi.Engine/Sbml/ASTHandler.cs b/src/MoBi.Engine/Sbml/ASTHandler.cs index cb8f1459f..fd44403ea 100644 --- a/src/MoBi.Engine/Sbml/ASTHandler.cs +++ b/src/MoBi.Engine/Sbml/ASTHandler.cs @@ -17,6 +17,7 @@ public class ASTHandler private IMoBiProject _sbmlProject; public List FunctionDefinitions { get; set; } public bool NeedAbsolutePath { get; set; } + public bool UseConcentrations { get; set; } = false; private readonly IObjectPathFactory _objectPathFactory; private readonly IObjectBaseFactory _objectBaseFactory; @@ -808,13 +809,14 @@ private string parseLog(ASTNode rootNode) /// /// Checks if a object path for the given objectName is already existant and creates a new one if not. /// - private string getObjectPathName(string parentContainer, string objectName) + private string getObjectPathName(string parentContainer, string objectName, bool useConcentration = false) { if (objectPathExistent(objectName)) return objectName; var alias = createAliasFrom(objectName); - _objectPaths.Add(_objectPathFactory.CreateFormulaUsablePathFrom(parentContainer, objectName).WithAlias(alias)); + var usablePath = useConcentration ? _objectPathFactory.CreateFormulaUsablePathFrom(parentContainer, objectName, Constants.Parameters.CONCENTRATION) : _objectPathFactory.CreateFormulaUsablePathFrom(parentContainer, objectName); + _objectPaths.Add(usablePath.WithAlias(alias)); return alias; } @@ -905,7 +907,7 @@ private string getObjectPathNameOfMolecule(IMoleculeBuilder molecule, Species sp //reaction if (NeedAbsolutePath == false) { - return getObjectPathName(ObjectPath.PARENT_CONTAINER, molecule.Name); + return getObjectPathName(ObjectPath.PARENT_CONTAINER, molecule.Name, UseConcentrations); } if (_sbmlInformation.MoleculeInformation.All(info => info.GetMoleculeBuilderName() != molecule.Name)) diff --git a/src/MoBi.Engine/Sbml/ReactionImporter.cs b/src/MoBi.Engine/Sbml/ReactionImporter.cs index 7b3b8d77d..e6837afb7 100644 --- a/src/MoBi.Engine/Sbml/ReactionImporter.cs +++ b/src/MoBi.Engine/Sbml/ReactionImporter.cs @@ -26,8 +26,9 @@ public class ReactionImporter : SBMLImporter private readonly IPassiveTransportBuildingBlock _passiveTransportBuildingBlock; private readonly IDimensionFactory _dimensionFactory; private readonly IFunctionDefinitionImporter _functionDefinitionImporter; + private readonly ISpeciesImporter _speciesImporter; - public ReactionImporter(IObjectPathFactory objectPathFactory, IObjectBaseFactory objectBaseFactory, IMoBiDimensionFactory moBiDimensionFactory, ASTHandler astHandler, IMoBiContext context, IReactionBuildingBlockFactory reactionBuildingBlockFactory, IFunctionDefinitionImporter functionDefinitionImporter) + public ReactionImporter(IObjectPathFactory objectPathFactory, IObjectBaseFactory objectBaseFactory, IMoBiDimensionFactory moBiDimensionFactory, ASTHandler astHandler, IMoBiContext context, IReactionBuildingBlockFactory reactionBuildingBlockFactory, IFunctionDefinitionImporter functionDefinitionImporter, ISpeciesImporter speciesImporter) : base(objectPathFactory, objectBaseFactory, astHandler, context) { _dimensionFactory = moBiDimensionFactory; @@ -37,6 +38,7 @@ public ReactionImporter(IObjectPathFactory objectPathFactory, IObjectBaseFactory _passiveTransportBuildingBlock = ObjectBaseFactory.Create() .WithName(SBMLConstants.SBML_PASSIVETRANSPORTS_BB); _functionDefinitionImporter = functionDefinitionImporter; + _speciesImporter = speciesImporter; } /// @@ -45,6 +47,7 @@ public ReactionImporter(IObjectPathFactory objectPathFactory, IObjectBaseFactory protected override void Import(Model model) { _astHandler.FunctionDefinitions = _functionDefinitionImporter.FunctionDefinitions; + _astHandler.UseConcentrations = _speciesImporter.UseConcentrations; for (long i = 0; i < model.getNumReactions(); i++) { CreateReaction(model.getReaction(i), model); diff --git a/src/MoBi.Engine/Sbml/SBMLImporterRepository.cs b/src/MoBi.Engine/Sbml/SBMLImporterRepository.cs index 732b212d5..f1cd46b35 100644 --- a/src/MoBi.Engine/Sbml/SBMLImporterRepository.cs +++ b/src/MoBi.Engine/Sbml/SBMLImporterRepository.cs @@ -17,7 +17,7 @@ public IEnumerable All() { yield return _container.Resolve(); yield return _container.Resolve(); - yield return _container.Resolve(); + yield return _container.Resolve(); yield return _container.Resolve(); yield return _container.Resolve(); yield return _container.Resolve(); @@ -30,7 +30,7 @@ public IEnumerable AllFor(Model sbmlModel) yield return _container.Resolve(); yield return _container.Resolve(); if (sbmlModel.getNumSpecies() != 0) - yield return _container.Resolve(); + yield return _container.Resolve(); if (sbmlModel.getNumParameters() != 0) yield return _container.Resolve(); if (sbmlModel.getNumFunctionDefinitions() != 0) diff --git a/src/MoBi.Engine/Sbml/SpeciesImporter.cs b/src/MoBi.Engine/Sbml/SpeciesImporter.cs index 98a8b2a9a..0a3c41b2f 100644 --- a/src/MoBi.Engine/Sbml/SpeciesImporter.cs +++ b/src/MoBi.Engine/Sbml/SpeciesImporter.cs @@ -11,12 +11,18 @@ using OSPSuite.Core.Domain.Formulas; using OSPSuite.Core.Domain.Services; using OSPSuite.Core.Domain.UnitSystem; +using OSPSuite.Utility; using Model = libsbmlcs.Model; using Unit = OSPSuite.Core.Domain.UnitSystem.Unit; namespace MoBi.Engine.Sbml { - public class SpeciesImporter : SBMLImporter + public interface ISpeciesImporter : ISBMLImporter + { + bool UseConcentrations { get; } + } + + public class SpeciesImporter : SBMLImporter, IStartable, ISpeciesImporter { private readonly IMoleculeStartValuesCreator _moleculeStartValuesCreator; internal IMoleculeBuildingBlock MoleculeBuildingBlock; @@ -25,7 +31,6 @@ public class SpeciesImporter : SBMLImporter private readonly IMoBiDimensionFactory _moBiDimensionFactory; private readonly Dictionary _dimensionDictionary; private IUnitDefinitionImporter _unitDefinitionImporter; - private IFormulaFactory _formulaFactory; private int _counter; public SpeciesImporter(IObjectPathFactory objectPathFactory, IObjectBaseFactory objectBaseFactory, IMoleculeBuilderFactory moleculeBuilderFactory, IMoleculeStartValuesCreator moleculeStartValuesCreator, IMoBiDimensionFactory moBiDimensionFactory, ASTHandler astHandler, IMoBiContext context, IUnitDefinitionImporter unitDefinitionImporter, IFormulaFactory formulaFactory) @@ -37,9 +42,10 @@ public SpeciesImporter(IObjectPathFactory objectPathFactory, IObjectBaseFactory _counter = 1; _dimensionDictionary = new Dictionary(); _unitDefinitionImporter = unitDefinitionImporter; - _formulaFactory = formulaFactory; } + public bool UseConcentrations { get; private set; } + protected override void Import(Model model) { CreateMoleculeBuildingBlock(); @@ -48,7 +54,6 @@ protected override void Import(Model model) CreateMoleculeFromSpecies(model.getSpecies(i)); } CheckMoleculeNameContainer(); - CreateDummySpecies(); CreateMoleculeStartValueBuildingBlock(model); SetMoleculeStartValues(model); SetDummyMSVs(); @@ -211,15 +216,16 @@ private void SetMoleculeStartValues(Model model) //unit is {unit of amount}/{unit of size} var baseValue = _unitDefinitionImporter.ToMobiBaseUnit(sbmlUnit, sbmlSpecies.getInitialConcentration()); msv.StartValue = baseValue.value; - msv.Formula = _formulaFactory.ConstantFormula(baseValue.value, baseValue.dimension); - - var sizeDimension = GetSizeDimensionFromCompartment(sbmlSpecies, model); - if (amountDimension == null) continue; - if (sizeDimension == null) continue; - - var newDim = _moBiDimensionFactory.DimensionForUnit($"{amountDimension.BaseUnit.Name}/{sizeDimension.BaseUnit.Name}") ?? CreateNewDimension(amountDimension, sizeDimension); - msv.Dimension = newDim; - molInfo.SetDimension(newDim); + msv.Formula = _context.Create($"{msv.Name}_0").WithName($"{msv.Name}_0").WithDimension(amountDimension).WithFormulaString($"{baseValue.value} * {Constants.VOLUME_ALIAS}"); + msv.Formula.AddObjectPath( + ObjectPathFactory.CreateFormulaUsablePathFrom(ObjectPath.PARENT_CONTAINER, Constants.Parameters.VOLUME) + .WithAlias(Constants.VOLUME_ALIAS) + .WithDimension(_moBiDimensionFactory.Dimension(Constants.Dimension.VOLUME)) + ); + _moleculeStartValuesBuildingBlock.AddFormula(msv.Formula); + msv.Dimension = amountDimension; + molInfo.SetDimension(amountDimension); + UseConcentrations = true; } else { @@ -352,5 +358,10 @@ private void SetDummyMSVs() } } } + + public void Start() + { + UseConcentrations = false; + } } } diff --git a/tests/MoBi.Tests/Core/SBML/ReactionImporterSpecs.cs b/tests/MoBi.Tests/Core/SBML/ReactionImporterSpecs.cs index 855cf5e0a..034b02d15 100644 --- a/tests/MoBi.Tests/Core/SBML/ReactionImporterSpecs.cs +++ b/tests/MoBi.Tests/Core/SBML/ReactionImporterSpecs.cs @@ -233,4 +233,26 @@ public void ShouldCreateAliases() _moBiProject.ReactionBlockCollection.First().ElementAt(7).Formula.ObjectPaths.Where(op => op.Alias == "Ct").ShouldNotBeEmpty(); } } + + public class ConcentrationBasedReactionImporterTests : ReactionImporterSpecs + { + protected override void Context() + { + base.Context(); + _fileName = Helper.TestFileFullPath("tiny_example_12.xml"); + } + + protected override void Because() + { + _sbmlTask.ImportModelFromSbml(_fileName, _moBiProject); + } + + [Observation] + public void should_parse_user_defined_functions() + { + var gkReaction = _moBiProject.ReactionBlockCollection.First().First(); + var glucosePath = gkReaction.Formula.ObjectPaths.ElementAt(1); + glucosePath.Last().ShouldBeEqualTo(Constants.Parameters.CONCENTRATION); + } + } } \ No newline at end of file diff --git a/tests/MoBi.Tests/Core/SBML/SpeciesImporterSpecs.cs b/tests/MoBi.Tests/Core/SBML/SpeciesImporterSpecs.cs index bf3f56515..ba77f5810 100644 --- a/tests/MoBi.Tests/Core/SBML/SpeciesImporterSpecs.cs +++ b/tests/MoBi.Tests/Core/SBML/SpeciesImporterSpecs.cs @@ -105,7 +105,19 @@ protected override void Context() public void should_understand_litre_as_unit() { var msvbb = _moBiProject.MoleculeStartValueBlockCollection.FirstOrDefault(); - msvbb.FirstOrDefault().Dimension.Name.ShouldBeEqualTo("Concentration (molar)"); + msvbb.FirstOrDefault().Dimension.Name.ShouldBeEqualTo("Amount"); + } + + [Observation] + public void should_assign_molecule_start_values_as_concentrations() + { + var msvbb = _moBiProject.MoleculeStartValueBlockCollection.FirstOrDefault(); + var glucose = msvbb.First(); + glucose.Formula.ToString().ShouldBeEqualTo("5000 * V"); + var volumePath = glucose.Formula.ObjectPaths.First(); + volumePath.ToString().ShouldBeEqualTo("..|Volume"); + volumePath.Alias.ShouldBeEqualTo("V"); + volumePath.Count.ShouldBeEqualTo(2); } } } \ No newline at end of file