From 28f5a8303e098ffa5446297bb40f10f76f7eb000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abdel=20Rodr=C3=ADguez?= Date: Wed, 6 Oct 2021 21:23:14 +0200 Subject: [PATCH 1/9] WIP --- src/MoBi.Engine/Sbml/SpeciesImporter.cs | 17 ++++++++++++----- src/MoBi.Presentation/Tasks/ProjectTask.cs | 1 + 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/MoBi.Engine/Sbml/SpeciesImporter.cs b/src/MoBi.Engine/Sbml/SpeciesImporter.cs index 98a8b2a9a..c50770191 100644 --- a/src/MoBi.Engine/Sbml/SpeciesImporter.cs +++ b/src/MoBi.Engine/Sbml/SpeciesImporter.cs @@ -48,7 +48,6 @@ protected override void Import(Model model) CreateMoleculeFromSpecies(model.getSpecies(i)); } CheckMoleculeNameContainer(); - CreateDummySpecies(); CreateMoleculeStartValueBuildingBlock(model); SetMoleculeStartValues(model); SetDummyMSVs(); @@ -211,15 +210,23 @@ 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); + msv.Formula = _context.Create($"{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); + + /*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); + molInfo.SetDimension(newDim);*/ } else { diff --git a/src/MoBi.Presentation/Tasks/ProjectTask.cs b/src/MoBi.Presentation/Tasks/ProjectTask.cs index 66b7ec410..ae64a1663 100644 --- a/src/MoBi.Presentation/Tasks/ProjectTask.cs +++ b/src/MoBi.Presentation/Tasks/ProjectTask.cs @@ -163,6 +163,7 @@ public void OpenSBMLModel() if (fileName.IsNullOrEmpty()) return; _context.NewProject(); + //_context.CurrentProject.ReactionDimensionMode _context.AddToHistory(_sbmlTask.ImportModelFromSbml(fileName, _context.CurrentProject)); notifyProjectLoaded(); } From ac30b83b98b222851c6eaa22f70f95190209a724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abdel=20Rodr=C3=ADguez?= Date: Thu, 7 Oct 2021 04:40:46 +0200 Subject: [PATCH 2/9] Properly create the ObjectPaths --- src/MoBi.Engine/Sbml/SpeciesImporter.cs | 12 ++---------- src/MoBi.Presentation/Tasks/ProjectTask.cs | 1 - 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/MoBi.Engine/Sbml/SpeciesImporter.cs b/src/MoBi.Engine/Sbml/SpeciesImporter.cs index c50770191..034537641 100644 --- a/src/MoBi.Engine/Sbml/SpeciesImporter.cs +++ b/src/MoBi.Engine/Sbml/SpeciesImporter.cs @@ -210,23 +210,15 @@ 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 = _context.Create($"{msv.Name}_0").WithDimension(amountDimension).WithFormulaString($"{baseValue.value} * {Constants.VOLUME_ALIAS}"); + 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}") + 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); - - /*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);*/ } else { diff --git a/src/MoBi.Presentation/Tasks/ProjectTask.cs b/src/MoBi.Presentation/Tasks/ProjectTask.cs index ae64a1663..66b7ec410 100644 --- a/src/MoBi.Presentation/Tasks/ProjectTask.cs +++ b/src/MoBi.Presentation/Tasks/ProjectTask.cs @@ -163,7 +163,6 @@ public void OpenSBMLModel() if (fileName.IsNullOrEmpty()) return; _context.NewProject(); - //_context.CurrentProject.ReactionDimensionMode _context.AddToHistory(_sbmlTask.ImportModelFromSbml(fileName, _context.CurrentProject)); notifyProjectLoaded(); } From e0c727e46fe69e072693ea7ee30b87d1a89daaeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abdel=20Rodr=C3=ADguez?= Date: Thu, 7 Oct 2021 05:06:14 +0200 Subject: [PATCH 3/9] Testing logic --- tests/MoBi.Tests/Core/SBML/SpeciesImporterSpecs.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) 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 From 13148bd355c9795e75e81aa5c32e05a0f8099d3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abdel=20Rodr=C3=ADguez?= Date: Thu, 7 Oct 2021 05:27:38 +0200 Subject: [PATCH 4/9] Testing that reactions are based on concentrations --- .../Core/SBML/ReactionImporterSpecs.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/MoBi.Tests/Core/SBML/ReactionImporterSpecs.cs b/tests/MoBi.Tests/Core/SBML/ReactionImporterSpecs.cs index 855cf5e0a..878f165e7 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 ShouldParseUserDefinedFunctions() + { + var gkReaction = _moBiProject.ReactionBlockCollection.First().First(); + var glucosePath = gkReaction.Formula.ObjectPaths.ElementAt(1); + glucosePath.Last().ShouldBeEqualTo("Concentration"); + } + } } \ No newline at end of file From a8ab325af8acbc3ad06165221ae73080f102b1e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abdel=20Rodr=C3=ADguez?= Date: Thu, 7 Oct 2021 05:55:38 +0200 Subject: [PATCH 5/9] Reacting to concentration based reactions when importing the reactions --- src/MoBi.Engine/EngineRegister.cs | 2 ++ src/MoBi.Engine/Sbml/ReactionImporter.cs | 5 ++++- src/MoBi.Engine/Sbml/SBMLImporterRepository.cs | 4 ++-- src/MoBi.Engine/Sbml/SpeciesImporter.cs | 18 +++++++++++++++--- 4 files changed, 23 insertions(+), 6 deletions(-) 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/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 034537641..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(); @@ -219,6 +225,7 @@ private void SetMoleculeStartValues(Model model) _moleculeStartValuesBuildingBlock.AddFormula(msv.Formula); msv.Dimension = amountDimension; molInfo.SetDimension(amountDimension); + UseConcentrations = true; } else { @@ -351,5 +358,10 @@ private void SetDummyMSVs() } } } + + public void Start() + { + UseConcentrations = false; + } } } From 7d2bcf294d12826a714834696d44158db0ab29fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abdel=20Rodr=C3=ADguez?= Date: Thu, 7 Oct 2021 05:59:37 +0200 Subject: [PATCH 6/9] Missing file in last commit --- src/MoBi.Engine/Sbml/ASTHandler.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) 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)) From d6830f4e97c9e3bfbcd29943032f6b331bbf7932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abdel=20Rodr=C3=ADguez?= Date: Thu, 7 Oct 2021 06:02:52 +0200 Subject: [PATCH 7/9] As discussed with Pavel, makes sense to allow for negative values --- src/MoBi.Engine/Sbml/SpeciesImporter.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/MoBi.Engine/Sbml/SpeciesImporter.cs b/src/MoBi.Engine/Sbml/SpeciesImporter.cs index 0a3c41b2f..aef257260 100644 --- a/src/MoBi.Engine/Sbml/SpeciesImporter.cs +++ b/src/MoBi.Engine/Sbml/SpeciesImporter.cs @@ -196,6 +196,7 @@ private void SetMoleculeStartValues(Model model) if (molInfo.GetContainer().Any(x => x.Name == msv.ContainerPath.LastOrDefault())) { msv.IsPresent = true; + msv.NegativeValuesAllowed = true; var sbmlSpecies = molInfo.GetSpeciesIfOne(); if (sbmlSpecies == null) return; var sbmlUnit = GetUnit(sbmlSpecies, model); From 6c0d48484e734c4a3cdd4d4716b8a7244216f17a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abdel=20Rodr=C3=ADguez?= Date: Thu, 7 Oct 2021 12:25:55 +0200 Subject: [PATCH 8/9] Revert "As discussed with Pavel, makes sense to allow for negative values" This reverts commit d6830f4e97c9e3bfbcd29943032f6b331bbf7932. --- src/MoBi.Engine/Sbml/SpeciesImporter.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/MoBi.Engine/Sbml/SpeciesImporter.cs b/src/MoBi.Engine/Sbml/SpeciesImporter.cs index aef257260..0a3c41b2f 100644 --- a/src/MoBi.Engine/Sbml/SpeciesImporter.cs +++ b/src/MoBi.Engine/Sbml/SpeciesImporter.cs @@ -196,7 +196,6 @@ private void SetMoleculeStartValues(Model model) if (molInfo.GetContainer().Any(x => x.Name == msv.ContainerPath.LastOrDefault())) { msv.IsPresent = true; - msv.NegativeValuesAllowed = true; var sbmlSpecies = molInfo.GetSpeciesIfOne(); if (sbmlSpecies == null) return; var sbmlUnit = GetUnit(sbmlSpecies, model); From c7ef2fecc3c96307b5c2a8e300317f74fc1068bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abdel=20Rodr=C3=ADguez?= Date: Thu, 7 Oct 2021 16:43:33 +0200 Subject: [PATCH 9/9] Michael feedback --- tests/MoBi.Tests/Core/SBML/ReactionImporterSpecs.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/MoBi.Tests/Core/SBML/ReactionImporterSpecs.cs b/tests/MoBi.Tests/Core/SBML/ReactionImporterSpecs.cs index 878f165e7..034b02d15 100644 --- a/tests/MoBi.Tests/Core/SBML/ReactionImporterSpecs.cs +++ b/tests/MoBi.Tests/Core/SBML/ReactionImporterSpecs.cs @@ -248,11 +248,11 @@ protected override void Because() } [Observation] - public void ShouldParseUserDefinedFunctions() + public void should_parse_user_defined_functions() { var gkReaction = _moBiProject.ReactionBlockCollection.First().First(); var glucosePath = gkReaction.Formula.ObjectPaths.ElementAt(1); - glucosePath.Last().ShouldBeEqualTo("Concentration"); + glucosePath.Last().ShouldBeEqualTo(Constants.Parameters.CONCENTRATION); } } } \ No newline at end of file