From 0a6318a2c2b2d34ea2a6a16229fcf1c239aed755 Mon Sep 17 00:00:00 2001 From: Michael Sevestre Date: Wed, 22 Mar 2023 18:15:32 -0400 Subject: [PATCH] Fixes #2569 use individual building block and module from core --- .../PKSim.Assets.Images.csproj | 4 +- src/PKSim.Assets/PKSim.Assets.csproj | 4 +- src/PKSim.BatchTool/PKSim.BatchTool.csproj | 4 +- src/PKSim.CLI.Core/PKSim.CLI.Core.csproj | 4 +- src/PKSim.CLI/PKSim.CLI.csproj | 6 +- ...eToExpressionProfileBuildingBlockMapper.cs | 14 +- ...dividualToIndividualBuildingBlockMapper.cs | 33 +++- .../PathAndValueBuildingBlockMapper.cs | 51 +++--- src/PKSim.Core/Model/Individual.cs | 15 +- src/PKSim.Core/PKSim.Core.csproj | 8 +- .../PKSimParameterStartValuesCreator.cs | 36 +++-- .../PKSim.Infrastructure.csproj | 18 +-- src/PKSim.Matlab/PKSim.Matlab.csproj | 4 +- .../PKSim.Presentation.csproj | 6 +- src/PKSim.R/PKSim.R.csproj | 4 +- src/PKSim.UI.Starter/PKSim.UI.Starter.csproj | 8 +- src/PKSim.UI/PKSim.UI.csproj | 8 +- src/PKSim/PKSim.csproj | 6 +- .../PKSim.Matlab.Tests.csproj | 4 +- tests/PKSim.R.Tests/PKSim.R.Tests.csproj | 4 +- ...pressionProfileBuildingBlockMapperSpecs.cs | 14 +- ...ualToIndividualBuildingBlockMapperSpecs.cs | 56 +++++++ .../IntegrationTests/PartialProcessesSpecs.cs | 18 ++- .../SystemicProcessesSpecs.cs | 10 +- tests/PKSim.Tests/PKSim.Tests.csproj | 2 +- ...ualToIndividualBuildingBlockMapperSpecs.cs | 147 ------------------ tests/PKSim.UI.Tests/PKSim.UI.Tests.csproj | 6 +- 27 files changed, 235 insertions(+), 259 deletions(-) create mode 100644 tests/PKSim.Tests/IntegrationTests/IndividualToIndividualBuildingBlockMapperSpecs.cs delete mode 100644 tests/PKSim.Tests/Presentation/IndividualToIndividualBuildingBlockMapperSpecs.cs diff --git a/src/PKSim.Assets.Images/PKSim.Assets.Images.csproj b/src/PKSim.Assets.Images/PKSim.Assets.Images.csproj index 7a8e81c37..16057f9ef 100644 --- a/src/PKSim.Assets.Images/PKSim.Assets.Images.csproj +++ b/src/PKSim.Assets.Images/PKSim.Assets.Images.csproj @@ -26,8 +26,8 @@ - - + + diff --git a/src/PKSim.Assets/PKSim.Assets.csproj b/src/PKSim.Assets/PKSim.Assets.csproj index 9723b04ba..88f4ad359 100644 --- a/src/PKSim.Assets/PKSim.Assets.csproj +++ b/src/PKSim.Assets/PKSim.Assets.csproj @@ -26,8 +26,8 @@ - - + + diff --git a/src/PKSim.BatchTool/PKSim.BatchTool.csproj b/src/PKSim.BatchTool/PKSim.BatchTool.csproj index 94c06db82..b0ca27b4d 100644 --- a/src/PKSim.BatchTool/PKSim.BatchTool.csproj +++ b/src/PKSim.BatchTool/PKSim.BatchTool.csproj @@ -59,8 +59,8 @@ - - + + diff --git a/src/PKSim.CLI.Core/PKSim.CLI.Core.csproj b/src/PKSim.CLI.Core/PKSim.CLI.Core.csproj index 385dbbcda..d3992d1ff 100644 --- a/src/PKSim.CLI.Core/PKSim.CLI.Core.csproj +++ b/src/PKSim.CLI.Core/PKSim.CLI.Core.csproj @@ -27,9 +27,9 @@ - + - + diff --git a/src/PKSim.CLI/PKSim.CLI.csproj b/src/PKSim.CLI/PKSim.CLI.csproj index 610fe8bf2..96a27ab93 100644 --- a/src/PKSim.CLI/PKSim.CLI.csproj +++ b/src/PKSim.CLI/PKSim.CLI.csproj @@ -61,9 +61,9 @@ - - - + + + diff --git a/src/PKSim.Core/Mappers/ExpressionProfileToExpressionProfileBuildingBlockMapper.cs b/src/PKSim.Core/Mappers/ExpressionProfileToExpressionProfileBuildingBlockMapper.cs index 55b218c44..0ed9eca29 100644 --- a/src/PKSim.Core/Mappers/ExpressionProfileToExpressionProfileBuildingBlockMapper.cs +++ b/src/PKSim.Core/Mappers/ExpressionProfileToExpressionProfileBuildingBlockMapper.cs @@ -2,10 +2,12 @@ using OSPSuite.Core; using OSPSuite.Core.Domain; using OSPSuite.Core.Domain.Builder; +using OSPSuite.Core.Domain.Formulas; using OSPSuite.Core.Domain.Services; using PKSim.Assets; using PKSim.Core.Model; -using PKSim.Core.Services; +using static PKSim.Core.CoreConstants.CalculationMethod; +using IFormulaFactory = PKSim.Core.Model.IFormulaFactory; using ILazyLoadTask = OSPSuite.Core.Domain.Services.ILazyLoadTask; namespace PKSim.Core.Mappers @@ -16,11 +18,17 @@ public interface IExpressionProfileToExpressionProfileBuildingBlockMapper : IPat public class ExpressionProfileToExpressionProfileBuildingBlockMapper : PathAndValueBuildingBlockMapper, IExpressionProfileToExpressionProfileBuildingBlockMapper { - public ExpressionProfileToExpressionProfileBuildingBlockMapper(IObjectBaseFactory objectBaseFactory, IEntityPathResolver entityPathResolver, IApplicationConfiguration applicationConfiguration, ILazyLoadTask lazyLoadTask, ICloner cloner) : - base(objectBaseFactory, entityPathResolver, applicationConfiguration, lazyLoadTask, cloner) + public ExpressionProfileToExpressionProfileBuildingBlockMapper(IObjectBaseFactory objectBaseFactory, IEntityPathResolver entityPathResolver, IApplicationConfiguration applicationConfiguration, ILazyLoadTask lazyLoadTask, IFormulaFactory formulaFactory) : + base(objectBaseFactory, entityPathResolver, applicationConfiguration, lazyLoadTask, formulaFactory) { } + protected override IFormula TemplateFormulaFor(IParameter parameter, IFormulaCache formulaCache, ExpressionProfile expressionProfile) + { + //for expression profile, all formula are in the calculation method EXPRESSION_PARAMETERS + return _formulaFactory.RateFor(new RateKey(EXPRESSION_PARAMETERS, parameter.Formula.Name), formulaCache); + } + protected override IReadOnlyList AllParametersFor(ExpressionProfile expressionProfile) { return expressionProfile.GetAllChildren(); diff --git a/src/PKSim.Core/Mappers/IndividualToIndividualBuildingBlockMapper.cs b/src/PKSim.Core/Mappers/IndividualToIndividualBuildingBlockMapper.cs index d124bb5f5..19c45b18a 100644 --- a/src/PKSim.Core/Mappers/IndividualToIndividualBuildingBlockMapper.cs +++ b/src/PKSim.Core/Mappers/IndividualToIndividualBuildingBlockMapper.cs @@ -3,12 +3,14 @@ using OSPSuite.Core; using OSPSuite.Core.Domain; using OSPSuite.Core.Domain.Builder; +using OSPSuite.Core.Domain.Formulas; using OSPSuite.Core.Domain.Services; using OSPSuite.Utility.Extensions; using PKSim.Assets; using PKSim.Core.Model; using PKSim.Core.Repositories; using PKSim.Core.Services; +using IFormulaFactory = PKSim.Core.Model.IFormulaFactory; using ILazyLoadTask = OSPSuite.Core.Domain.Services.ILazyLoadTask; namespace PKSim.Core.Mappers @@ -21,12 +23,39 @@ public class IndividualToIndividualBuildingBlockMapper : PathAndValueBuildingBlo { private readonly IRepresentationInfoRepository _representationInfoRepository; private readonly ICalculationMethodCategoryRepository _calculationMethodCategoryRepository; + private readonly IParameterQuery _parameterQuery; - public IndividualToIndividualBuildingBlockMapper(IObjectBaseFactory objectBaseFactory, IEntityPathResolver entityPathResolver, IApplicationConfiguration applicationConfiguration, - ILazyLoadTask lazyLoadTask, IRepresentationInfoRepository representationInfoRepository, ICalculationMethodCategoryRepository calculationMethodCategoryRepository, ICloner cloner) : base(objectBaseFactory, entityPathResolver, applicationConfiguration, lazyLoadTask, cloner) + public IndividualToIndividualBuildingBlockMapper(IObjectBaseFactory objectBaseFactory, + IEntityPathResolver entityPathResolver, + IApplicationConfiguration applicationConfiguration, + ILazyLoadTask lazyLoadTask, + IRepresentationInfoRepository representationInfoRepository, + ICalculationMethodCategoryRepository calculationMethodCategoryRepository, + IFormulaFactory formulaFactory, + IParameterQuery parameterQuery) : base(objectBaseFactory, entityPathResolver, applicationConfiguration, lazyLoadTask, formulaFactory) { _representationInfoRepository = representationInfoRepository; _calculationMethodCategoryRepository = calculationMethodCategoryRepository; + _parameterQuery = parameterQuery; + } + + protected override IFormula TemplateFormulaFor(IParameter parameter, IFormulaCache formulaCache, Individual individual) + { + bool isMetaDataForParameter(ParameterMetaData p) => p.BuildingBlockType == PKSimBuildingBlockType.Individual && string.Equals(p.ParameterName, parameter.Name); + + + //for individual, the CM to use depends on the CM available in the origin data as well as the container where the parameter resides. + var calculationMethods = individual.OriginData.AllCalculationMethods().AllNames(); + + var parameterRate = _parameterQuery.ParameterRatesFor(parameter.ParentContainer, calculationMethods, isMetaDataForParameter).ToList(); + + //this is not possible? + if (parameterRate.Count != 1) + return null; + + var cloneFormula = _formulaFactory.RateFor(parameterRate[0], formulaCache); + cloneFormula.ObjectPaths.Each(x => x.Remove(Constants.ROOT)); + return cloneFormula; } protected override IReadOnlyList AllParametersFor(Individual individual) diff --git a/src/PKSim.Core/Mappers/PathAndValueBuildingBlockMapper.cs b/src/PKSim.Core/Mappers/PathAndValueBuildingBlockMapper.cs index 4f56b5092..d8c93f70a 100644 --- a/src/PKSim.Core/Mappers/PathAndValueBuildingBlockMapper.cs +++ b/src/PKSim.Core/Mappers/PathAndValueBuildingBlockMapper.cs @@ -6,11 +6,9 @@ using OSPSuite.Core.Domain.Formulas; using OSPSuite.Core.Domain.Services; using OSPSuite.Utility; -using OSPSuite.Utility.Collections; using OSPSuite.Utility.Extensions; using PKSim.Core.Model; -using PKSim.Core.Services; -using ILazyLoadTask = OSPSuite.Core.Domain.Services.ILazyLoadTask; +using IFormulaFactory = PKSim.Core.Model.IFormulaFactory; namespace PKSim.Core.Mappers { @@ -21,8 +19,8 @@ public interface IPathAndValueBuildingBlockMapper : IPathAndValueBuildingBlockMapper { /// - /// Map the parameter to the underlying builder parameter. - /// Note that formula or value will not be set. Only common parameter properties + /// Map the parameter to the underlying builder parameter. + /// Note that formula or value will not be set. Only common parameter properties /// TBuilder MapParameter(IParameter parameter); } @@ -35,24 +33,24 @@ public abstract class PathAndValueBuildingBlockMapper _formulaCache = new Cache(x => x.Name); + private readonly IFormulaCache _formulaCache = new BuildingBlockFormulaCache(); + protected readonly IFormulaFactory _formulaFactory; protected PathAndValueBuildingBlockMapper( IObjectBaseFactory objectBaseFactory, IEntityPathResolver entityPathResolver, IApplicationConfiguration applicationConfiguration, ILazyLoadTask lazyLoadTask, - ICloner cloner) + IFormulaFactory formulaFactory) { _objectBaseFactory = objectBaseFactory; _entityPathResolver = entityPathResolver; _applicationConfiguration = applicationConfiguration; _lazyLoadTask = lazyLoadTask; - _cloner = cloner; + _formulaFactory = formulaFactory; } protected TBuildingBlock CreateBaseObject(TPKSimBuildingBlock pkSimBuildingBlock) @@ -74,15 +72,16 @@ public virtual TBuilder MapParameter(IParameter parameter) return builderParameter; } - private TBuilder mapBuilderParameter(IParameter parameter) + private TBuilder mapBuilderParameter(IParameter parameter, TPKSimBuildingBlock pkSimBuildingBlock) { var builderParameter = MapParameter(parameter); // Add the formula to the building block formula cache if the formula can be cached var parameterValue = getParameterValue(parameter); var valueChanged = parameter.ValueDiffersFromDefault(); + var formula = parameter.Formula; - switch (parameter.Formula) + switch (formula) { case ConstantFormula _: builderParameter.Value = parameterValue; @@ -98,13 +97,10 @@ private TBuilder mapBuilderParameter(IParameter parameter) return builderParameter; default: - if (isFormulaCachable(parameter)) + if (formula.IsCachable()) { - if (!_formulaCache.Contains(parameter.Formula.Name)) - _formulaCache.Add(cloneFormulaForExport(parameter)); - - //Set the formula no matter what - builderParameter.Formula = _formulaCache[parameter.Formula.Name]; + var templateFormula = retrieveTemplateFormulaFromCache(parameter, pkSimBuildingBlock); + builderParameter.Formula = templateFormula; } // Only set the value of the parameter using a formula if it was indeed set @@ -115,17 +111,20 @@ private TBuilder mapBuilderParameter(IParameter parameter) } } - private IFormula cloneFormulaForExport(IParameter parameter) + private IFormula retrieveTemplateFormulaFromCache(IParameter parameter, TPKSimBuildingBlock pkSimBuildingBlock) { - var cloneFormula = _cloner.Clone(parameter.Formula); - cloneFormula.ObjectPaths.Each(x => x.Remove(Constants.ROOT)); - return cloneFormula; + var formulaName = parameter.Formula.Name; + if (_formulaCache.Contains(formulaName)) + return _formulaCache[formulaName]; + + //This will add the formula top the cache + var templateFormula = TemplateFormulaFor(parameter, _formulaCache, pkSimBuildingBlock); + //We need to remove the ROOT keyword when exporting to PKML structure + templateFormula?.ObjectPaths.Each(x => x.Remove(Constants.ROOT)); + return templateFormula; } - private static bool isFormulaCachable(IParameter parameter) - { - return parameter.Formula != null && parameter.Formula.IsCachable(); - } + protected abstract IFormula TemplateFormulaFor(IParameter parameter, IFormulaCache formulaCache, TPKSimBuildingBlock pkSimBuildingBlock); private static double getParameterValue(IParameter parameter) { @@ -134,7 +133,7 @@ private static double getParameterValue(IParameter parameter) protected void MapAllParameters(TPKSimBuildingBlock sourcePKSimBuildingBlock, TBuildingBlock buildingBlock) { - var allBuilderParameters = AllParametersFor(sourcePKSimBuildingBlock).Select(mapBuilderParameter); + var allBuilderParameters = AllParametersFor(sourcePKSimBuildingBlock).Select(x=>mapBuilderParameter(x, sourcePKSimBuildingBlock)); allBuilderParameters.Where(x => x != null).Each(buildingBlock.Add); //Formula cache already contains a clone of all formula. We can add as is diff --git a/src/PKSim.Core/Model/Individual.cs b/src/PKSim.Core/Model/Individual.cs index 3a79aa1ab..2dff669fe 100644 --- a/src/PKSim.Core/Model/Individual.cs +++ b/src/PKSim.Core/Model/Individual.cs @@ -67,13 +67,24 @@ public Individual() : base(PKSimBuildingBlockType.Individual) /// /// All defined molecules defined in the individual /// - public virtual IEnumerable AllDefinedMolecules() => AllMolecules().Where(x => !x.IsUndefinedMolecule()); + public virtual IEnumerable AllDefinedMolecules() => AllMolecules(x => !x.IsUndefinedMolecule()); + + /// + /// All defined molecules defined in the individual + /// + public virtual IEnumerable AllUndefinedMolecules() => AllMolecules(x => x.IsUndefinedMolecule()); + + /// + /// All protein of type in the individual + /// + /// Type of molecule to be retrieved + public virtual IEnumerable AllMolecules() where TMolecule : IndividualMolecule => AllMolecules(x => true); /// /// All protein of type in the individual /// /// Type of molecule to be retrieved - public virtual IEnumerable AllMolecules() where TMolecule : IndividualMolecule => GetChildren(); + public virtual IEnumerable AllMolecules(Func predicate) where TMolecule : IndividualMolecule => GetChildren(predicate); public ExpressionProfile ExpressionProfileFor(IndividualMolecule molecule) => AllExpressionProfiles().Find(x => string.Equals(x.MoleculeName, molecule.Name)); diff --git a/src/PKSim.Core/PKSim.Core.csproj b/src/PKSim.Core/PKSim.Core.csproj index 680b00f37..353fed92b 100644 --- a/src/PKSim.Core/PKSim.Core.csproj +++ b/src/PKSim.Core/PKSim.Core.csproj @@ -30,10 +30,10 @@ - - - - + + + + diff --git a/src/PKSim.Core/Services/PKSimParameterStartValuesCreator.cs b/src/PKSim.Core/Services/PKSimParameterStartValuesCreator.cs index 41be90eac..7b9eb40d4 100644 --- a/src/PKSim.Core/Services/PKSimParameterStartValuesCreator.cs +++ b/src/PKSim.Core/Services/PKSimParameterStartValuesCreator.cs @@ -30,10 +30,28 @@ public PKSimParameterStartValuesCreator( public ParameterStartValuesBuildingBlock CreateFor(SimulationConfiguration simulationConfiguration, Simulation simulation) { - //default default parameter start values matrix - _defaultStartValues = _objectBaseFactory.Create(); - updateSimulationParameters(simulation); - return _defaultStartValues.WithName(simulation.Name); + try + { + //default default parameter start values matrix + _defaultStartValues = _objectBaseFactory.Create(); + var individual = simulation.Individual; + + //set the relative expression values for each molecule undefined molecule of the individual (other will be done in expression profile) + individual.AllUndefinedMolecules().Each(molecule => updateMoleculeParametersValues(molecule, individual)); + + updateSimulationParameters(simulation); + return _defaultStartValues.WithName(simulation.Name); + } + finally + { + _defaultStartValues = null; + } + } + + private void updateMoleculeParametersValues(IndividualMolecule molecule, Individual individual) + { + var allMoleculeParameters = individual.AllMoleculeParametersFor(molecule); + allMoleculeParameters.Each(p => trySetValue(p)); } private void updateSimulationParameters(Simulation simulation) @@ -43,14 +61,10 @@ private void updateSimulationParameters(Simulation simulation) if (simulation.Model == null) return; + //TODO: Ensure that the formula will not become a constant after clone + //THis was done with psv.OverrideFormulaWithValue = false; var allSimulationParameters = simulation.Model.Root.GetAllChildren(isChangedSimulationParameter); - allSimulationParameters.Each(p => - { - var psv = trySetValue(p); - //Ensure that the formula will not become a constant after clone - //TODO -// psv.OverrideFormulaWithValue = false; - }); + allSimulationParameters.Each(p => trySetValue(p)); } private bool isChangedSimulationParameter(IParameter parameter) diff --git a/src/PKSim.Infrastructure/PKSim.Infrastructure.csproj b/src/PKSim.Infrastructure/PKSim.Infrastructure.csproj index 528752ad4..51a54ca35 100644 --- a/src/PKSim.Infrastructure/PKSim.Infrastructure.csproj +++ b/src/PKSim.Infrastructure/PKSim.Infrastructure.csproj @@ -41,15 +41,15 @@ - - - - - - - - - + + + + + + + + + diff --git a/src/PKSim.Matlab/PKSim.Matlab.csproj b/src/PKSim.Matlab/PKSim.Matlab.csproj index 2b260abbf..44debd2c3 100644 --- a/src/PKSim.Matlab/PKSim.Matlab.csproj +++ b/src/PKSim.Matlab/PKSim.Matlab.csproj @@ -26,9 +26,9 @@ - + - + diff --git a/src/PKSim.Presentation/PKSim.Presentation.csproj b/src/PKSim.Presentation/PKSim.Presentation.csproj index a08c91c78..4ae62ae64 100644 --- a/src/PKSim.Presentation/PKSim.Presentation.csproj +++ b/src/PKSim.Presentation/PKSim.Presentation.csproj @@ -27,11 +27,11 @@ - + - - + + diff --git a/src/PKSim.R/PKSim.R.csproj b/src/PKSim.R/PKSim.R.csproj index 1298b76bf..483c3539a 100644 --- a/src/PKSim.R/PKSim.R.csproj +++ b/src/PKSim.R/PKSim.R.csproj @@ -49,9 +49,9 @@ - + - + diff --git a/src/PKSim.UI.Starter/PKSim.UI.Starter.csproj b/src/PKSim.UI.Starter/PKSim.UI.Starter.csproj index c148301f6..1f6d019c7 100644 --- a/src/PKSim.UI.Starter/PKSim.UI.Starter.csproj +++ b/src/PKSim.UI.Starter/PKSim.UI.Starter.csproj @@ -23,10 +23,10 @@ - - - - + + + + diff --git a/src/PKSim.UI/PKSim.UI.csproj b/src/PKSim.UI/PKSim.UI.csproj index 4fdbaaee6..0caa4bd2b 100644 --- a/src/PKSim.UI/PKSim.UI.csproj +++ b/src/PKSim.UI/PKSim.UI.csproj @@ -60,14 +60,14 @@ - + - - - + + + diff --git a/src/PKSim/PKSim.csproj b/src/PKSim/PKSim.csproj index 79d3e0161..68d7654c9 100644 --- a/src/PKSim/PKSim.csproj +++ b/src/PKSim/PKSim.csproj @@ -76,14 +76,14 @@ - - + + - + diff --git a/tests/PKSim.Matlab.Tests/PKSim.Matlab.Tests.csproj b/tests/PKSim.Matlab.Tests/PKSim.Matlab.Tests.csproj index fa5260879..e8231961a 100644 --- a/tests/PKSim.Matlab.Tests/PKSim.Matlab.Tests.csproj +++ b/tests/PKSim.Matlab.Tests/PKSim.Matlab.Tests.csproj @@ -22,9 +22,9 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + - + diff --git a/tests/PKSim.R.Tests/PKSim.R.Tests.csproj b/tests/PKSim.R.Tests/PKSim.R.Tests.csproj index 7fe502d67..0076c3512 100644 --- a/tests/PKSim.R.Tests/PKSim.R.Tests.csproj +++ b/tests/PKSim.R.Tests/PKSim.R.Tests.csproj @@ -22,9 +22,9 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + - + diff --git a/tests/PKSim.Tests/Core/ExpressionProfileToExpressionProfileBuildingBlockMapperSpecs.cs b/tests/PKSim.Tests/Core/ExpressionProfileToExpressionProfileBuildingBlockMapperSpecs.cs index f7ad61f44..cd6f1d3bf 100644 --- a/tests/PKSim.Tests/Core/ExpressionProfileToExpressionProfileBuildingBlockMapperSpecs.cs +++ b/tests/PKSim.Tests/Core/ExpressionProfileToExpressionProfileBuildingBlockMapperSpecs.cs @@ -5,12 +5,9 @@ using OSPSuite.Core; using OSPSuite.Core.Domain; using OSPSuite.Core.Domain.Builder; -using OSPSuite.Core.Domain.Formulas; using OSPSuite.Core.Domain.Services; using PKSim.Core.Mappers; using PKSim.Core.Model; -using PKSim.Core.Services; -using ILazyLoadTask = OSPSuite.Core.Domain.Services.ILazyLoadTask; namespace PKSim.Core { @@ -23,7 +20,7 @@ public abstract class concern_for_ExpressionProfileToExpressionProfileBuildingBl protected ExpressionProfileBuildingBlock _result; private IApplicationConfiguration _applicationConfiguration; private ILazyLoadTask _lazyLoadTask; - private ICloner _cloner; + private IFormulaFactory _formulaFactory; protected override void Context() { @@ -31,14 +28,12 @@ protected override void Context() _objectBaseFactory = A.Fake(); _objectPathFactory = new EntityPathResolverForSpecs(); _lazyLoadTask = A.Fake(); - _cloner= A.Fake(); - //cloning formula always returns the same formula for testing - A.CallTo(() => _cloner.Clone(A._)).ReturnsLazily(x => x.GetArgument(0)); + _formulaFactory = A.Fake(); A.CallTo(() => _objectBaseFactory.Create()).Returns(new ExpressionProfileBuildingBlock()); A.CallTo(() => _objectBaseFactory.Create()).ReturnsLazily(() => new ExpressionParameter()); - sut = new ExpressionProfileToExpressionProfileBuildingBlockMapper(_objectBaseFactory, _objectPathFactory, _applicationConfiguration, _lazyLoadTask, _cloner); + sut = new ExpressionProfileToExpressionProfileBuildingBlockMapper(_objectBaseFactory, _objectPathFactory, _applicationConfiguration, _lazyLoadTask, _formulaFactory); } } @@ -86,7 +81,7 @@ protected override void Context() { base.Context(); _individual = DomainHelperForSpecs.CreateIndividual("TestSpecies"); - _individual.AddMolecule(new IndividualEnzyme { Name = "TestEnzyme" }); + _individual.AddMolecule(new IndividualEnzyme {Name = "TestEnzyme"}); _expressionProfile = new ExpressionProfile { Individual = _individual, @@ -121,7 +116,6 @@ public void resulting_building_block_should_have_the_correct_values() _result.MoleculeName.ShouldBeEqualTo("TestEnzyme"); _result.Type.DisplayName.ShouldBeEqualTo("Enzyme"); _result.Type.IconName.ShouldBeEqualTo("Enzyme"); - _result.FormulaCache.Count.ShouldBeEqualTo(2); } } } \ No newline at end of file diff --git a/tests/PKSim.Tests/IntegrationTests/IndividualToIndividualBuildingBlockMapperSpecs.cs b/tests/PKSim.Tests/IntegrationTests/IndividualToIndividualBuildingBlockMapperSpecs.cs new file mode 100644 index 000000000..0d5e370f4 --- /dev/null +++ b/tests/PKSim.Tests/IntegrationTests/IndividualToIndividualBuildingBlockMapperSpecs.cs @@ -0,0 +1,56 @@ +using OSPSuite.BDDHelper; +using OSPSuite.BDDHelper.Extensions; +using OSPSuite.Core.Domain; +using OSPSuite.Core.Domain.Builder; +using OSPSuite.Core.Extensions; +using PKSim.Core.Mappers; +using PKSim.Core.Model; +using PKSim.Infrastructure; + +namespace PKSim.IntegrationTests +{ + public abstract class concern_for_IndividualToIndividualBuildingBlockMapper : ContextForIntegration + { + protected Individual _individual; + + public override void GlobalContext() + { + base.GlobalContext(); + _individual = DomainFactoryForSpecs.CreateStandardIndividual(); + } + } + + public class When_mapping_building_block_from_individual : concern_for_IndividualToIndividualBuildingBlockMapper + { + private IndividualBuildingBlock _buildingBlock; + + protected override void Because() + { + _buildingBlock = sut.MapFrom(_individual); + } + + [Observation] + public void the_properties_of_the_building_block_should_match() + { + var allDataItems = _buildingBlock.OriginData.AllDataItems; + allDataItems.ExistsByName("Species").ShouldBeTrue(); + allDataItems.ExistsByName("Population").ShouldBeTrue(); + allDataItems.ExistsByName("Gender").ShouldBeTrue(); + allDataItems.ExistsByName("Weight").ShouldBeTrue(); + allDataItems.ExistsByName("Age").ShouldBeTrue(); + allDataItems.ExistsByName("Height").ShouldBeTrue(); + + //the following are not mapped because they are not defined in the default individual + allDataItems.ExistsByName("Gestational Age").ShouldBeFalse(); + allDataItems.ExistsByName("Disease State").ShouldBeFalse(); + } + + [Observation] + public void should_have_replaced_the_ROOT_key_element_path_in_all_formula() + { + var formula = _buildingBlock.FormulaCache.FindByName("PARAM_BW"); + formula.ObjectPaths.Count.ShouldBeEqualTo(2); + formula.ObjectPaths[0][0].ShouldBeEqualTo("Organism"); + } + } +} \ No newline at end of file diff --git a/tests/PKSim.Tests/IntegrationTests/PartialProcessesSpecs.cs b/tests/PKSim.Tests/IntegrationTests/PartialProcessesSpecs.cs index 29eb3159e..85a7ceaf7 100644 --- a/tests/PKSim.Tests/IntegrationTests/PartialProcessesSpecs.cs +++ b/tests/PKSim.Tests/IntegrationTests/PartialProcessesSpecs.cs @@ -38,6 +38,8 @@ public abstract class concern_for_PartialProcesses : ContextForSimulationIntegra protected IModelConfigurationRepository _modelConfigurationRepository; protected SimulationRunOptions _simulationRunOptions; protected ICache _allExpressionParameters; + private ExpressionProfile _expressionProfileForEnzyme; + private IMoleculeExpressionTask _moleculeExpressionTask; protected const double _relExpDuo = 0.2; protected const double _relExpBone = 0.3; @@ -50,11 +52,14 @@ public override void GlobalContext() _transporterFactory = IoC.Resolve(); _modelPropertiesTask = IoC.Resolve(); _modelConfigurationRepository = IoC.Resolve(); + _moleculeExpressionTask = IoC.Resolve>(); _compound = DomainFactoryForSpecs.CreateStandardCompound(); _individual = DomainFactoryForSpecs.CreateStandardIndividual(); _protocol = DomainFactoryForSpecs.CreateStandardIVBolusProtocol(); - _enzyme = _enzymeFactory.AddMoleculeTo(_individual, "CYP").DowncastTo(); - _allExpressionParameters = _individual.AllExpressionParametersFor(_enzyme); + _expressionProfileForEnzyme = DomainFactoryForSpecs.CreateExpressionProfile(); + _moleculeExpressionTask.AddExpressionProfile(_individual, _expressionProfileForEnzyme); + _enzyme = _expressionProfileForEnzyme.Molecule.DowncastTo(); + _allExpressionParameters = _expressionProfileForEnzyme.Individual.AllExpressionParametersFor(_enzyme); _allExpressionParameters[CoreConstants.Compartment.PLASMA].Value = _relExpPls; _allExpressionParameters[CoreConstants.Compartment.BLOOD_CELLS].Value = _relExpBloodCells; _allExpressionParameters[CoreConstants.Compartment.VASCULAR_ENDOTHELIUM].Value = _relExpVascEndo; @@ -93,6 +98,11 @@ public override void GlobalContext() [Observation] public void the_value_of_the_relative_expression_in_organ_should_have_been_set_to_the_value_defined_in_the_enzyme() { + + var allRelExp1 = _simulation.All() + .Where(x => x.Name.Equals(_enzyme.Name)) + .Select(x => x.Parameter(Constants.Parameters.REL_EXP)); + var allRelExp = _simulation.All() .Where(x => x.Name.Equals(_enzyme.Name)) .Where(x => x.ParentContainer.Name.Equals(CoreConstants.Compartment.INTRACELLULAR)) @@ -131,14 +141,14 @@ public void the_default_value_of_relative_expression_parameters_should_be_null() [Observation] public void the_reference_concentration_parameter_should_be_marked_as_can_be_varied_in_the_simulation() { - var refConc = _simulation.Model.Root.Container("CYP").Parameter(CoreConstants.Parameters.REFERENCE_CONCENTRATION); + var refConc = _simulation.Model.Root.Container(_enzyme.Name).Parameter(CoreConstants.Parameters.REFERENCE_CONCENTRATION); refConc.CanBeVaried.ShouldBeTrue(); refConc.CanBeVariedInPopulation.ShouldBeTrue(); } } public class - When_creating_a_simulation_with_an_individual_containing_an_enzyme_localized_in_intracellular_with_location_in_vasc_endothelium_is_interstial_and_a_partial_process_in_compound : + When_creating_a_simulation_with_an_individual_containing_an_enzyme_localized_in_intracellular_with_location_in_vasc_endothelium_is_interstitial_and_a_partial_process_in_compound : concern_for_PartialProcesses { public override void GlobalContext() diff --git a/tests/PKSim.Tests/IntegrationTests/SystemicProcessesSpecs.cs b/tests/PKSim.Tests/IntegrationTests/SystemicProcessesSpecs.cs index 3c7e2610a..91428af66 100644 --- a/tests/PKSim.Tests/IntegrationTests/SystemicProcessesSpecs.cs +++ b/tests/PKSim.Tests/IntegrationTests/SystemicProcessesSpecs.cs @@ -13,6 +13,8 @@ using OSPSuite.Core.Domain; using OSPSuite.Core.Domain.Services; using static OSPSuite.Core.Domain.Constants; +using static PKSim.Core.CoreConstants.Compartment; +using static PKSim.Core.CoreConstants.Organ; namespace PKSim.IntegrationTests { @@ -147,7 +149,7 @@ public void the_created_transport_should_reference_undefined_transport_concentra { var transport = biliaryClearancePeriportalCellToGallBladderTransport(); var undefinedTransportRef = transport.Formula.ObjectPaths.First(x => x.Alias == "CP"); - undefinedTransportRef.ShouldContain(CoreConstants.Organ.LIVER, CoreConstants.Compartment.PERIPORTAL); + undefinedTransportRef.ShouldContain(LIVER, PERIPORTAL); } private ITransport biliaryClearancePeriportalCellToGallBladderTransport() @@ -185,12 +187,12 @@ public void the_created_simulation_should_have_a_biliary_clearance_process_creat allProcessParameters.FindByName(ConverterConstants.Parameters.PlasmaClearance).Value.ShouldBeEqualTo(_liverClearance.Parameter(ConverterConstants.Parameters.PlasmaClearance).Value); } - + [Observation] public void the_created_process_kinetic_should_reference_an_undefined_enzyme_in_liver_whose_start_concentration_is_set_to_1_by_f_cell() { - var liver_periportal = _simulation.Model.Root.EntityAt(Constants.ORGANISM, CoreConstants.Organ.LIVER, CoreConstants.Compartment.PERIPORTAL); - var startConcentration = liver_periportal.EntityAt(CoreConstants.Compartment.INTRACELLULAR, CoreConstants.Molecule.UndefinedLiver, CoreConstants.Parameters.CONCENTRATION); + var liver_periportal = _simulation.Model.Root.EntityAt(ORGANISM, LIVER, PERIPORTAL); + var startConcentration = liver_periportal.EntityAt(INTRACELLULAR, CoreConstants.Molecule.UndefinedLiver, CoreConstants.Parameters.CONCENTRATION); var f_cell = liver_periportal.EntityAt(CoreConstants.Parameters.FRACTION_INTRACELLULAR); startConcentration.Value.ShouldBeEqualTo(1 / f_cell.Value); diff --git a/tests/PKSim.Tests/PKSim.Tests.csproj b/tests/PKSim.Tests/PKSim.Tests.csproj index 8e8127761..968c883d2 100644 --- a/tests/PKSim.Tests/PKSim.Tests.csproj +++ b/tests/PKSim.Tests/PKSim.Tests.csproj @@ -21,7 +21,7 @@ - + diff --git a/tests/PKSim.Tests/Presentation/IndividualToIndividualBuildingBlockMapperSpecs.cs b/tests/PKSim.Tests/Presentation/IndividualToIndividualBuildingBlockMapperSpecs.cs deleted file mode 100644 index a64e431c0..000000000 --- a/tests/PKSim.Tests/Presentation/IndividualToIndividualBuildingBlockMapperSpecs.cs +++ /dev/null @@ -1,147 +0,0 @@ -using System.Linq; -using FakeItEasy; -using OSPSuite.BDDHelper; -using OSPSuite.BDDHelper.Extensions; -using OSPSuite.Core; -using OSPSuite.Core.Domain; -using OSPSuite.Core.Domain.Builder; -using OSPSuite.Core.Domain.Formulas; -using OSPSuite.Core.Extensions; -using PKSim.Core; -using PKSim.Core.Mappers; -using PKSim.Core.Model; -using PKSim.Core.Repositories; -using PKSim.Core.Services; -using PKSim.Infrastructure; -using ILazyLoadTask = OSPSuite.Core.Domain.Services.ILazyLoadTask; - -namespace PKSim.Presentation -{ - public abstract class concern_for_IndividualToIndividualBuildingBlockMapper : ContextSpecification - { - protected Individual _individual; - private IObjectBaseFactory _objectBaseFactory; - private IApplicationConfiguration _applicationConfiguration; - private ILazyLoadTask _lazyLoadTask; - private EntityPathResolverForSpecs _objectPathFactory; - private ICalculationMethodCategoryRepository _calculationMethodCategoryRepository; - private static CalculationMethodCategory _category1; - private ICloner _cloner; - - protected override void Context() - { - _individual = DomainHelperForSpecs.CreateIndividual("Human"); - _lazyLoadTask = A.Fake(); - _applicationConfiguration = new PKSimConfiguration(); - _objectPathFactory = new EntityPathResolverForSpecs(); - _objectBaseFactory = A.Fake(); - _cloner = A.Fake(); - - //cloning formula always returns the same formula for testing - A.CallTo(() => _cloner.Clone(A._)).ReturnsLazily(x => x.GetArgument(0)); - - var representationInfoRepository = A.Fake(); - A.CallTo(representationInfoRepository).WithReturnType().Returns(new RepresentationInfo {DisplayName = "displayName"}); - - _calculationMethodCategoryRepository = A.Fake(); - updateIndividualForTest(_individual); - - A.CallTo(() => _objectBaseFactory.Create()).Returns(new IndividualBuildingBlock()); - A.CallTo(() => _objectBaseFactory.Create()).Returns(new IndividualParameter()); - sut = new IndividualToIndividualBuildingBlockMapper(_objectBaseFactory, _objectPathFactory, _applicationConfiguration, _lazyLoadTask, representationInfoRepository, _calculationMethodCategoryRepository, _cloner); - } - - private void updateIndividualForTest(Individual individual) - { - //add a parameter with a formula starting with ROOT so that we can test that this is being dealt with properly - var parameterWithFormula = DomainHelperForSpecs.ConstantParameterWithValue(0).WithName("FormulaParameter"); - parameterWithFormula.Formula = new ExplicitFormula("P2").WithName("FormulaParameterFormula"); - parameterWithFormula.Formula.AddObjectPath(new FormulaUsablePath("ROOT", "ORGANISM", "P2").WithAlias("P2")); - - //for this formula, we return a real one to make sure we have actually changed the ROOT - var cloneFormula = new ExplicitFormula("P2").WithName("FormulaParameterFormula"); - cloneFormula.AddObjectPath(new FormulaUsablePath("ROOT", "ORGANISM", "P2").WithAlias("P2")); - - A.CallTo(() => _cloner.Clone(parameterWithFormula.Formula)).Returns(cloneFormula); - individual.Organism.Add(parameterWithFormula); - - var originData = individual.OriginData; - originData.Gender.DisplayName = originData.Gender.Name; - originData.Population.DisplayName = originData.Population.Name; - originData.Age = new OriginDataParameter(1, "year", "Age"); - originData.GestationalAge = new OriginDataParameter(52, "weeks", "Gestational Age"); - - _category1 = new CalculationMethodCategory(); - - var calculationMethod = new CalculationMethod - { - DisplayName = "method1", - Category = "category1", - }; - calculationMethod.AddSpecies(_individual.Species.Name); - - originData.CalculationMethodCache.AddCalculationMethod(calculationMethod); - _category1.Add(calculationMethod); - - A.CallTo(() => _calculationMethodCategoryRepository.HasMoreThanOneOption(A._, _individual.Species)).WhenArgumentsMatch(x => x.Get(0).Category.Equals("category2")).Returns(false); - A.CallTo(() => _calculationMethodCategoryRepository.HasMoreThanOneOption(A._, _individual.Species)).WhenArgumentsMatch(x => x.Get(0).Category.Equals("category1")).Returns(true); - - calculationMethod = new CalculationMethod - { - DisplayName = "method2", - Category = "category1", - }; - calculationMethod.AddSpecies(_individual.Species.Name); - - _category1.Add(calculationMethod); - - calculationMethod = new CalculationMethod - { - Category = "category2", - Name = "calculationMethod1" - }; - originData.CalculationMethodCache.AddCalculationMethod(calculationMethod); - originData.DiseaseState = new DiseaseState - { - DisplayName = "A Disease" - }; - } - } - - public class When_mapping_building_block_from_individual : concern_for_IndividualToIndividualBuildingBlockMapper - { - private IndividualBuildingBlock _buildingBlock; - - protected override void Because() - { - _buildingBlock = sut.MapFrom(_individual); - } - - [Observation] - public void the_properties_of_the_building_block_should_match() - { - _buildingBlock.OriginData.AllDataItems.Count(x => x.Name.Equals("Species")).ShouldBeEqualTo(1); - _buildingBlock.OriginData.AllDataItems.Count(x => x.Name.Equals("Population")).ShouldBeEqualTo(1); - _buildingBlock.OriginData.AllDataItems.Count(x => x.Name.Equals("Gender")).ShouldBeEqualTo(1); - _buildingBlock.OriginData.AllDataItems.Count(x => x.Name.Equals("Weight")).ShouldBeEqualTo(1); - _buildingBlock.OriginData.AllDataItems.Count(x => x.Name.Equals("Age")).ShouldBeEqualTo(1); - _buildingBlock.OriginData.AllDataItems.Count(x => x.Name.Equals("Gestational Age")).ShouldBeEqualTo(1); - _buildingBlock.OriginData.AllDataItems.Count(x => x.Name.Equals("Disease State")).ShouldBeEqualTo(1); - - // the count is 0 here because we intentionally left these out to make sure only populated origin data would be mapped - _buildingBlock.OriginData.AllDataItems.Count(x => x.Name.Equals("Height")).ShouldBeEqualTo(0); - _buildingBlock.OriginData.AllDataItems.Count(x => x.Name.Equals("BMI")).ShouldBeEqualTo(0); - - _buildingBlock.OriginData.AllDataItems.Count(x => x.Name.Equals("displayName")).ShouldBeEqualTo(1); - _buildingBlock.OriginData.AllDataItems.Count.ShouldBeEqualTo(8); - } - - [Observation] - public void should_have_replaced_the_ROOT_key_element_path_in_all_formula() - { - var formula = _buildingBlock.FormulaCache.FindByName("FormulaParameterFormula"); - formula.ObjectPaths.Count.ShouldBeEqualTo(1); - formula.ObjectPaths[0].ToPathString().ShouldBeEqualTo("ORGANISM|P2"); - } - } -} \ No newline at end of file diff --git a/tests/PKSim.UI.Tests/PKSim.UI.Tests.csproj b/tests/PKSim.UI.Tests/PKSim.UI.Tests.csproj index 07d1c3390..75cd54203 100644 --- a/tests/PKSim.UI.Tests/PKSim.UI.Tests.csproj +++ b/tests/PKSim.UI.Tests/PKSim.UI.Tests.csproj @@ -29,10 +29,10 @@ - + - - + +