Skip to content

Commit

Permalink
Fixes #1970 add simulation builder (#1973)
Browse files Browse the repository at this point in the history
* Fixes #1970 add simulation builder

* Fixes #1970 add simulation builder
  • Loading branch information
msevestre authored Apr 12, 2023
1 parent c5826c5 commit d781297
Show file tree
Hide file tree
Showing 70 changed files with 808 additions and 690 deletions.
1 change: 1 addition & 0 deletions SolutionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
[assembly: AssemblyCopyright("Copyright © 2017 - present - Open Systems Pharmacology Community")]
[assembly: ComVisible(false)]
[assembly: InternalsVisibleTo("OSPSuite.Core.Tests")]
[assembly: InternalsVisibleTo("OSPSuite.HelperForTests")]
[assembly: InternalsVisibleTo("OSPSuite.UI.Tests")]
[assembly: InternalsVisibleTo("OSPSuite.Presentation.Tests")]
[assembly: InternalsVisibleTo("OSPSuite.R.Tests")]
Expand Down
16 changes: 13 additions & 3 deletions src/OSPSuite.Core/Domain/Builder/ModelConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
namespace OSPSuite.Core.Domain.Builder
{
public class ModelConfiguration
internal class ModelConfiguration
{
public SimulationBuilder SimulationBuilder { get; }
public IModel Model { get; }
public SimulationConfiguration SimulationConfiguration { get; }

public ModelConfiguration(IModel model, SimulationConfiguration simulationConfiguration)
public ModelConfiguration(IModel model, SimulationConfiguration simulationConfiguration, SimulationBuilder simulationBuilder)
{
Model = model;
SimulationConfiguration = simulationConfiguration;
SimulationBuilder = simulationBuilder;
}

public bool ShouldValidate => SimulationConfiguration.ShouldValidate;

public void Deconstruct(out IModel model, out SimulationConfiguration simulationConfiguration)
public void Deconstruct(out IModel model, out SimulationConfiguration simulationConfiguration, out SimulationBuilder simulationBuilder)
{
model = Model;
simulationConfiguration = SimulationConfiguration;
simulationBuilder = SimulationBuilder;
}


public void Deconstruct(out IModel model, out SimulationBuilder simulationBuilder)
{
model = Model;
simulationBuilder = SimulationBuilder;
}
}
}
109 changes: 109 additions & 0 deletions src/OSPSuite.Core/Domain/Builder/SimulationBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OSPSuite.Utility.Collections;

namespace OSPSuite.Core.Domain.Builder
{
public class SimulationBuilder
{
private readonly SimulationConfiguration _simulationConfiguration;

private readonly ObjectBaseCache<ITransportBuilder> _passiveTransports = new ObjectBaseCache<ITransportBuilder>();
private readonly ObjectBaseCache<IReactionBuilder> _reactions = new ObjectBaseCache<IReactionBuilder>();
private readonly ObjectBaseCache<IEventGroupBuilder> _eventGroups = new ObjectBaseCache<IEventGroupBuilder>();
private readonly ObjectBaseCache<IObserverBuilder> _observers = new ObjectBaseCache<IObserverBuilder>();
private readonly ObjectBaseCache<IMoleculeBuilder> _molecules = new ObjectBaseCache<IMoleculeBuilder>();
private readonly StartValueCache<ParameterStartValue> _parameterStartValues = new StartValueCache<ParameterStartValue>();
private readonly StartValueCache<MoleculeStartValue> _moleculeStartValues = new StartValueCache<MoleculeStartValue>();

private readonly Cache<IObjectBase, IObjectBase> _builderCache = new Cache<IObjectBase, IObjectBase>(onMissingKey: x => null);

public SimulationBuilder(SimulationConfiguration simulationConfiguration)
{
_simulationConfiguration = simulationConfiguration;
performMerge();
}

internal IObjectBase BuilderFor(IObjectBase modelObject) => _builderCache[modelObject];

internal void AddBuilderReference(IObjectBase modelObject, IObjectBase builder)
{
_builderCache[modelObject] = builder;
}

private IReadOnlyList<T> all<T>(Func<Module, T> propAccess) where T : IBuildingBlock =>
_simulationConfiguration.ModuleConfigurations.Select(x => propAccess(x.Module)).Where(x => x != null).ToList();

private IEnumerable<T> allBuilder<T>(Func<Module, IBuildingBlock<T>> propAccess) where T : IBuilder =>
all(propAccess).SelectMany(x => x);

private IEnumerable<T> allStartValueBuilder<T>(Func<ModuleConfiguration, IBuildingBlock<T>> propAccess) where T : IStartValue =>
_simulationConfiguration.ModuleConfigurations.Select(propAccess).Where(x => x != null).SelectMany(x => x);

internal IEnumerable<IMoleculeBuilder> AllPresentMolecules()
{
var moleculeNames = _moleculeStartValues
.Where(moleculeStartValue => moleculeStartValue.IsPresent)
.Select(moleculeStartValue => moleculeStartValue.MoleculeName)
.Distinct();


return moleculeNames.Select(x => _molecules[x]).Where(m => m != null);
}

internal IEnumerable<MoleculeStartValue> AllPresentMoleculeValues() =>
AllPresentMoleculeValuesFor(_molecules.Select(x => x.Name));

internal IEnumerable<MoleculeStartValue> AllPresentMoleculeValuesFor(IEnumerable<string> moleculeNames)
{
return _moleculeStartValues
.Where(msv => moleculeNames.Contains(msv.MoleculeName))
.Where(msv => msv.IsPresent);
}

internal IEnumerable<IMoleculeBuilder> AllFloatingMolecules() => Molecules.Where(x => x.IsFloating);

internal IReadOnlyList<string> AllPresentMoleculeNames() => AllPresentMoleculeNames(x => true);

//Uses toArray so that the marshaling to R works out of the box (array vs list)
internal IReadOnlyList<string> AllPresentMoleculeNames(Func<IMoleculeBuilder, bool> query) =>
AllPresentMolecules().Where(query).Select(x => x.Name).ToArray();

internal IReadOnlyList<string> AllPresentFloatingMoleculeNames() =>
AllPresentMoleculeNames(m => m.IsFloating);

internal IReadOnlyList<string> AllPresentStationaryMoleculeNames() =>
AllPresentMoleculeNames(m => !m.IsFloating);

internal IReadOnlyList<string> AllPresentXenobioticFloatingMoleculeNames() =>
AllPresentMoleculeNames(m => m.IsFloating && m.IsXenobiotic);

internal IReadOnlyList<string> AllPresentEndogenousStationaryMoleculeNames() =>
AllPresentMoleculeNames(m => !m.IsFloating && !m.IsXenobiotic);

internal IReadOnlyList<string> AllPresentEndogenousMoleculeNames() => AllPresentMoleculeNames(m => !m.IsXenobiotic);

private void performMerge()
{
_passiveTransports.AddRange(allBuilder(x => x.PassiveTransports));
_reactions.AddRange(allBuilder(x => x.Reactions));
_eventGroups.AddRange(allBuilder(x => x.EventGroups));
_observers.AddRange(allBuilder(x => x.Observers));
_molecules.AddRange(allBuilder(x => x.Molecules));
_parameterStartValues.AddRange(allStartValueBuilder(x => x.SelectedParameterStartValues));
_moleculeStartValues.AddRange(allStartValueBuilder(x => x.SelectedMoleculeStartValues));
}

internal IReadOnlyList<ISpatialStructure> SpatialStructures => all(x => x.SpatialStructure);
internal IReadOnlyCollection<ITransportBuilder> PassiveTransports => _passiveTransports;
internal IReadOnlyCollection<IReactionBuilder> Reactions => _reactions;
internal IReadOnlyCollection<IEventGroupBuilder> EventGroups => _eventGroups;
internal IReadOnlyCollection<IObserverBuilder> Observers => _observers;
internal IReadOnlyCollection<IMoleculeBuilder> Molecules => _molecules;
internal IReadOnlyCollection<ParameterStartValue> ParameterStartValues => _parameterStartValues;
internal IReadOnlyCollection<MoleculeStartValue> MoleculeStartValues => _moleculeStartValues;

internal IMoleculeBuilder MoleculeByName(string name) => _molecules[name];
}
}
116 changes: 3 additions & 113 deletions src/OSPSuite.Core/Domain/Builder/SimulationConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using OSPSuite.Core.Serialization.SimModel.Services;
using OSPSuite.Utility.Collections;
using OSPSuite.Utility.Extensions;
using OSPSuite.Utility.Visitor;

Expand All @@ -13,17 +11,6 @@ public class SimulationConfiguration : IVisitable<IVisitor>
private readonly List<ExpressionProfileBuildingBlock> _expressionProfiles = new List<ExpressionProfileBuildingBlock>();
private readonly List<ModuleConfiguration> _moduleConfigurations = new List<ModuleConfiguration>();
private readonly List<ICoreCalculationMethod> _allCalculationMethods = new List<ICoreCalculationMethod>();

//Temporary objects used for model construction only
private readonly Cache<IObjectBase, IObjectBase> _builderCache = new Cache<IObjectBase, IObjectBase>(onMissingKey: x => null);
private readonly ObjectBaseCache<ITransportBuilder> _passiveTransports = new ObjectBaseCache<ITransportBuilder>();
private readonly ObjectBaseCache<IReactionBuilder> _reactions = new ObjectBaseCache<IReactionBuilder>();
private readonly ObjectBaseCache<IEventGroupBuilder> _eventGroups = new ObjectBaseCache<IEventGroupBuilder>();
private readonly ObjectBaseCache<IObserverBuilder> _observers = new ObjectBaseCache<IObserverBuilder>();
private readonly ObjectBaseCache<IMoleculeBuilder> _molecules = new ObjectBaseCache<IMoleculeBuilder>();
private readonly StartValueCache<ParameterStartValue> _parameterStartValues = new StartValueCache<ParameterStartValue>();
private readonly StartValueCache<MoleculeStartValue> _moleculeStartValues = new StartValueCache<MoleculeStartValue>();

public SimModelExportMode SimModelExportMode { get; set; } = SimModelExportMode.Full;

public bool ShouldValidate { get; set; } = true;
Expand All @@ -43,113 +30,16 @@ public class SimulationConfiguration : IVisitable<IVisitor>

public virtual void AddCalculationMethod(ICoreCalculationMethod calculationMethodToAdd) => _allCalculationMethods.Add(calculationMethodToAdd);

public virtual IReadOnlyList<ISpatialStructure> SpatialStructures => all(x => x.SpatialStructure);
public virtual IReadOnlyCollection<ITransportBuilder> PassiveTransports => _passiveTransports;
public virtual IReadOnlyCollection<IReactionBuilder> Reactions => _reactions;
public virtual IReadOnlyCollection<IEventGroupBuilder> EventGroups => _eventGroups;
public virtual IReadOnlyCollection<IObserverBuilder> Observers => _observers;
public virtual IReadOnlyCollection<IMoleculeBuilder> Molecules => _molecules;
public virtual IReadOnlyCollection<ParameterStartValue> ParameterStartValues => _parameterStartValues;
public virtual IReadOnlyCollection<MoleculeStartValue> MoleculeStartValues => _moleculeStartValues;

public IMoleculeBuilder MoleculeByName(string name) => _molecules[name];

private IReadOnlyList<T> all<T>(Func<Module, T> propAccess) where T : IBuildingBlock =>
_moduleConfigurations.Select(x => propAccess(x.Module)).Where(x => x != null).ToList();

private IEnumerable<T> allBuilder<T>(Func<Module, IBuildingBlock<T>> propAccess) where T : IBuilder =>
all(propAccess).SelectMany(x => x);

private IEnumerable<T> allStartValueBuilder<T>(Func<ModuleConfiguration, IBuildingBlock<T>> propAccess) where T : IStartValue =>
_moduleConfigurations.Select(propAccess).Where(x => x != null).SelectMany(x => x);

public virtual IEnumerable<IMoleculeBuilder> AllPresentMolecules()
{
var moleculeNames = _moleculeStartValues
.Where(moleculeStartValue => moleculeStartValue.IsPresent)
.Select(moleculeStartValue => moleculeStartValue.MoleculeName)
.Distinct();


return moleculeNames.Select(x => _molecules[x]).Where(m => m != null);
}

public virtual IEnumerable<MoleculeStartValue> AllPresentMoleculeValues() =>
AllPresentMoleculeValuesFor(_molecules.Select(x => x.Name));

public virtual IEnumerable<MoleculeStartValue> AllPresentMoleculeValuesFor(IEnumerable<string> moleculeNames)
public IReadOnlyList<T> All<T>() where T : class, IBuildingBlock
{
return _moleculeStartValues
.Where(msv => moleculeNames.Contains(msv.MoleculeName))
.Where(msv => msv.IsPresent);
return ModuleConfigurations.Select(x=>x.BuildingBlock<T>()).Where(x=>x!=null).ToList();
}

public virtual IEnumerable<IMoleculeBuilder> AllFloatingMolecules() => Molecules.Where(x => x.IsFloating);

public virtual IReadOnlyList<string> AllPresentMoleculeNames() => AllPresentMoleculeNames(x => true);

//Uses toArray so that the marshaling to R works out of the box (array vs list)
public virtual IReadOnlyList<string> AllPresentMoleculeNames(Func<IMoleculeBuilder, bool> query) =>
AllPresentMolecules().Where(query).Select(x => x.Name).ToArray();

public virtual IReadOnlyList<string> AllPresentFloatingMoleculeNames() =>
AllPresentMoleculeNames(m => m.IsFloating);

public virtual IReadOnlyList<string> AllPresentStationaryMoleculeNames() =>
AllPresentMoleculeNames(m => !m.IsFloating);

public virtual IReadOnlyList<string> AllPresentXenobioticFloatingMoleculeNames() =>
AllPresentMoleculeNames(m => m.IsFloating && m.IsXenobiotic);

public virtual IReadOnlyList<string> AllPresentEndogenousStationaryMoleculeNames() =>
AllPresentMoleculeNames(m => !m.IsFloating && !m.IsXenobiotic);

public virtual IReadOnlyList<string> AllPresentEndogenousMoleculeNames() => AllPresentMoleculeNames(m => !m.IsXenobiotic);

public virtual IObjectBase BuilderFor(IObjectBase modelObject) => _builderCache[modelObject];

public virtual void AddBuilderReference(IObjectBase modelObject, IObjectBase builder)
{
_builderCache[modelObject] = builder;
}

//TODO clone? Update from?

public virtual void AcceptVisitor(IVisitor visitor)
{
ModuleConfigurations.Each(x => x.AcceptVisitor(visitor));
Individual?.AcceptVisitor(visitor);
_expressionProfiles.Each(x => x.AcceptVisitor(visitor));
}

//Internal because this should not be called outside of core.
internal void Freeze()
{
ClearCache();
_passiveTransports.AddRange(allBuilder(x => x.PassiveTransports));
_reactions.AddRange(allBuilder(x => x.Reactions));
_eventGroups.AddRange(allBuilder(x => x.EventGroups));
_observers.AddRange(allBuilder(x => x.Observers));
_molecules.AddRange(allBuilder(x => x.Molecules));
_parameterStartValues.AddRange(allStartValueBuilder(x => x.SelectedParameterStartValues));
_moleculeStartValues.AddRange(allStartValueBuilder(x => x.SelectedMoleculeStartValues));
}

internal void ClearCache()
{
ClearBuilderCache();
_passiveTransports.Clear();
_reactions.Clear();
_eventGroups.Clear();
_observers.Clear();
_molecules.Clear();
_parameterStartValues.Clear();
_moleculeStartValues.Clear();
}

public virtual void ClearBuilderCache()
{
_builderCache.Clear();
}
}
}
5 changes: 4 additions & 1 deletion src/OSPSuite.Core/Domain/CreationResult.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
using System.Linq;
using OSPSuite.Core.Domain.Builder;

namespace OSPSuite.Core.Domain
{
public class CreationResult
{
public virtual IModel Model { get; }
public SimulationBuilder SimulationBuilder { get; }
public virtual ValidationResult ValidationResult { get; private set; }

public CreationResult(IModel model)
public CreationResult(IModel model, SimulationBuilder simulationBuilder)
{
Model = model;
SimulationBuilder = simulationBuilder;
ValidationResult = new ValidationResult();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
using OSPSuite.Utility.Extensions;
using OSPSuite.Core.Domain.Builder;
using OSPSuite.Core.Domain.Builder;
using OSPSuite.Core.Domain.Services;
using OSPSuite.Utility.Extensions;

namespace OSPSuite.Core.Domain.Mappers
{
/// <summary>
/// Maps container used in a building block to model container <para></para>
/// At the moment, there is no special ContainerBuilder class, so the mapper <para></para>
/// will just create the clone of the input container
/// Maps container used in a building block to model container
/// <para></para>
/// At the moment, there is no special ContainerBuilder class, so the mapper
/// <para></para>
/// will just create the clone of the input container
/// </summary>
public interface IContainerBuilderToContainerMapper : IBuilderMapper<IContainer, IContainer>
{
}

public class ContainerBuilderToContainerMapper : IContainerBuilderToContainerMapper
internal class ContainerBuilderToContainerMapper : IContainerBuilderToContainerMapper
{
private readonly ICloneManagerForModel _cloneManagerForModel;

Expand All @@ -22,26 +24,26 @@ public ContainerBuilderToContainerMapper(ICloneManagerForModel cloneManagerForMo
_cloneManagerForModel = cloneManagerForModel;
}

public IContainer MapFrom(IContainer containerBuilder, SimulationConfiguration simulationConfiguration)
public IContainer MapFrom(IContainer containerBuilder, SimulationBuilder simulationBuilder)
{
var container= _cloneManagerForModel.Clone(containerBuilder);
addBuilderReference(container, containerBuilder, simulationConfiguration);
var container = _cloneManagerForModel.Clone(containerBuilder);
addBuilderReference(container, containerBuilder, simulationBuilder);
return container;
}

private void addBuilderReference(IContainer container, IContainer containerBuilder, SimulationConfiguration simulationConfiguration)
private void addBuilderReference(IContainer container, IContainer containerBuilder, SimulationBuilder simulationBuilder)
{
if (container == null || containerBuilder == null) return;

simulationConfiguration.AddBuilderReference(container, containerBuilder);
simulationBuilder.AddBuilderReference(container, containerBuilder);

foreach (var childBuilder in containerBuilder.Children)
{
var child = container.GetSingleChildByName(childBuilder.Name);
if(child.IsAnImplementationOf<IContainer>())
addBuilderReference(child.DowncastTo<IContainer>(), childBuilder as IContainer, simulationConfiguration);
if (child.IsAnImplementationOf<IContainer>())
addBuilderReference(child.DowncastTo<IContainer>(), childBuilder as IContainer, simulationBuilder);
else
simulationConfiguration.AddBuilderReference(child, childBuilder);
simulationBuilder.AddBuilderReference(child, childBuilder);
}
}
}
Expand Down
Loading

0 comments on commit d781297

Please sign in to comment.