Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #1970 add simulation builder #1973

Merged
merged 2 commits into from
Apr 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, cool. I didn't know about this before.

[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