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

1972 how are we going to merge spatial structure #1978

Merged
merged 6 commits into from
Apr 14, 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
8 changes: 7 additions & 1 deletion src/OSPSuite.Assets/UIConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1367,6 +1367,8 @@ public static class Error
public static readonly string FoldValueMustBeGreaterThanOne = "Fold value must be a number greater than one.";
public static readonly string ImporterEmptyFile = "The file you are trying to load is empty.";

public static string CannotFindParentContainerWithPath(string parentPath, string containerName)=> $"Cannot find parent container '{parentPath}' defined as target of container '{containerName}'";

public static string NoUnitColumnValues(string mappingName) => $"No values for the unit were found in the excel column mapped for '{mappingName}' \n";

public static string ParseErrorMessage(IEnumerable<string> errors) => $"There were errors while parsing your data: {string.Join(". ", errors)}";
Expand Down Expand Up @@ -1708,7 +1710,7 @@ public static string SimulationPKAnalysesFileDoesNotHaveTheExpectedFormat
}
}

public static string SimulationDidNotProduceResults = "Simulation did not produce results";
public const string SimulationDidNotProduceResults = "Simulation did not produce results";

public static string DuplicatedIndividualResultsForId(int individualId) => $"Individual results for individual with id '{individualId}' were defined more than once!";

Expand Down Expand Up @@ -1741,6 +1743,10 @@ public static string TimeArrayValuesDoesNotMatchFirstIndividual(int id, int inde

public static string CouldNotFindNeighborhoodBetween(string container1, string container2) => $"Could not find neighborhood between '{container1}' and '{container2}'";

public static string FirstNeighborNotDefinedFor(string neighborhoodName) => $"First neighbor is undefined for neighborhood '{neighborhoodName}'";

public static string SecondNeighborNotDefinedFor(string neighborhoodName) => $"Second neighbor is undefined for neighborhood '{neighborhoodName}'";

public const string InParentTagCanOnlyBeUsedWithAndOperator = "IN PARENT tag can only be used with AND operator";

public static class SensitivityAnalysis
Expand Down
67 changes: 42 additions & 25 deletions src/OSPSuite.Core/Domain/Builder/NeighborhoodBuilderFactory.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,53 @@
namespace OSPSuite.Core.Domain.Builder
{
/// <summary>
/// Factory class to create well defined new <see cref="NeighborhoodBuilder"/>
/// Factory class to create well defined new <see cref="NeighborhoodBuilder" />
/// </summary>
public interface INeighborhoodBuilderFactory
{
/// <summary>
/// Creates a new instance of a <see cref="NeighborhoodBuilder"/>.
/// Creates a new instance of a <see cref="NeighborhoodBuilder" />.
/// </summary>
///<returns> the new <see cref="NeighborhoodBuilder"/></returns>
/// <returns> the new <see cref="NeighborhoodBuilder" /></returns>
NeighborhoodBuilder Create();

/// <summary>
/// Creates a new <see cref="NeighborhoodBuilder"/> between <paramref name="firstNeighbor"/> and <paramref name="secondNeighbor"/>.
/// Creates a new <see cref="NeighborhoodBuilder" /> between <paramref name="firstNeighbor" /> and
/// <paramref name="secondNeighbor" />.
/// </summary>
/// <param name="firstNeighbor">The first neighbor.</param>
/// <param name="secondNeighbor">The second neighbor.</param>
///<returns> the new <see cref="NeighborhoodBuilder"/></returns>
NeighborhoodBuilder CreateBetween(IContainer firstNeighbor, IContainer secondNeighbor);
/// <param name="parentPath">
/// Optional parent path that will be added to the path created for first and second neighbor
/// (useful for dynamic structure)
/// </param>
/// <returns> the new <see cref="NeighborhoodBuilder" /></returns>
NeighborhoodBuilder CreateBetween(IContainer firstNeighbor, IContainer secondNeighbor, ObjectPath parentPath = null);

/// <summary>
/// Creates a new <see cref="NeighborhoodBuilder" /> between <paramref name="firstNeighborPath" /> and
/// <paramref name="secondNeighborPath" />.
/// </summary>
/// <param name="firstNeighborPath">The first neighbor path.</param>
/// <param name="secondNeighborPath">The second neighbor path.</param>
/// <param name="parentPath">
/// Optional parent path that will be added to the path created for first and second neighbor
/// (useful for dynamic structure)
/// </param>
/// <returns> the new <see cref="NeighborhoodBuilder" /></returns>
NeighborhoodBuilder CreateBetween(ObjectPath firstNeighborPath, ObjectPath secondNeighborPath, ObjectPath parentPath = null);
}

/// <summary>
/// Factory class to create well defined new <see cref="NeighborhoodBuilder"/>
/// Factory class to create well defined new <see cref="NeighborhoodBuilder" />
/// </summary>
public class NeighborhoodBuilderFactory : INeighborhoodBuilderFactory
{
private readonly IObjectBaseFactory _objectBaseFactory;
private readonly IObjectPathFactory _objectPathFactory;

/// <summary>
/// Initializes a new instance of the <see cref="NeighborhoodBuilderFactory"/> class.
/// Initializes a new instance of the <see cref="NeighborhoodBuilderFactory" /> class.
/// </summary>
public NeighborhoodBuilderFactory(IObjectBaseFactory objectBaseFactory, IObjectPathFactory objectPathFactory)
{
Expand All @@ -37,9 +56,9 @@ public NeighborhoodBuilderFactory(IObjectBaseFactory objectBaseFactory, IObjectP
}

/// <summary>
/// Creates a new instance of a <see cref="NeighborhoodBuilder"/>.
/// Creates a new instance of a <see cref="NeighborhoodBuilder" />.
/// </summary>
///<returns> the new <see cref="NeighborhoodBuilder"/></returns>
/// <returns> the new <see cref="NeighborhoodBuilder" /></returns>
public NeighborhoodBuilder Create()
{
var neighborhoodBuilder = CreateNeighborhoodBuilder().WithMode(ContainerMode.Logical);
Expand All @@ -52,28 +71,26 @@ public NeighborhoodBuilder Create()
return neighborhoodBuilder;
}

protected NeighborhoodBuilder CreateNeighborhoodBuilder()
{
return _objectBaseFactory.Create<NeighborhoodBuilder>();
}
protected NeighborhoodBuilder CreateNeighborhoodBuilder() => _objectBaseFactory.Create<NeighborhoodBuilder>();

protected IContainer CreateMoleculeProperties() => _objectBaseFactory.Create<IContainer>();

protected IContainer CreateMoleculeProperties()
public NeighborhoodBuilder CreateBetween(IContainer firstNeighbor, IContainer secondNeighbor, ObjectPath parentPath = null)
{
return _objectBaseFactory.Create<IContainer>();
return CreateBetween(_objectPathFactory.CreateAbsoluteObjectPath(firstNeighbor), _objectPathFactory.CreateAbsoluteObjectPath(secondNeighbor), parentPath);
}

/// <summary>
/// Creates a new <see cref="NeighborhoodBuilder"/> between <paramref name="firstNeighbor"/> and <paramref name="secondNeighbor"/>.
/// </summary>
/// <param name="firstNeighbor">The first neighbor.</param>
/// <param name="secondNeighbor">The second neighbor.</param>
///<returns> the new <see cref="NeighborhoodBuilder"/></returns>
public NeighborhoodBuilder CreateBetween(IContainer firstNeighbor, IContainer secondNeighbor)
public NeighborhoodBuilder CreateBetween(ObjectPath firstNeighborPath, ObjectPath secondNeighborPath, ObjectPath parentPath = null)
{
var neighborhoodBuilder = Create();
neighborhoodBuilder.FirstNeighborPath = _objectPathFactory.CreateAbsoluteObjectPath(firstNeighbor);
neighborhoodBuilder.SecondNeighborPath = _objectPathFactory.CreateAbsoluteObjectPath(secondNeighbor);
neighborhoodBuilder.FirstNeighborPath = mergePath(parentPath, firstNeighborPath);
neighborhoodBuilder.SecondNeighborPath = mergePath(parentPath, secondNeighborPath) ;
return neighborhoodBuilder;
}

private ObjectPath mergePath(ObjectPath parentPath, ObjectPath objectPath)
{
return parentPath == null ? objectPath : new ObjectPath(parentPath, objectPath);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ public IContainer MapFrom(ModelConfiguration modelConfiguration)

var moleculeNamesCopyProperties = simulationBuilder.AllPresentXenobioticFloatingMoleculeNames();

simulationBuilder.SpatialStructures.SelectMany(x => x.Neighborhoods).Each(nb =>
neighborhoodsParentContainer.Add(_neighborhoodMapper.MapFrom(nb,
moleculeNamesFor(nb, startValuesForFloatingMolecules),
moleculeNamesCopyProperties, modelConfiguration)));
//we use a cache to ensure that we are replacing neighborhoods defined in multiple structures
var neighborhoodCache = new ObjectBaseCache<Neighborhood>();
Copy link
Member Author

Choose a reason for hiding this comment

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

Usage of cache here by name to ensure that the last neighborhood wins

var allNeighborhoodBuilder = simulationBuilder.SpatialStructures.SelectMany(x => x.Neighborhoods);
neighborhoodCache.AddRange(allNeighborhoodBuilder.Select(nb =>
_neighborhoodMapper.MapFrom(nb, moleculeNamesFor(nb, startValuesForFloatingMolecules), moleculeNamesCopyProperties, modelConfiguration)));

neighborhoodsParentContainer.AddChildren(neighborhoodCache);
return neighborhoodsParentContainer;
}

Expand Down
2 changes: 1 addition & 1 deletion src/OSPSuite.Core/Domain/ObjectPath.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public ObjectPath() : this(new List<string>())
{
}

public ObjectPath(ObjectPath from) : this(from._pathEntries)
public ObjectPath(params ObjectPath[] from) : this(from.SelectMany(x=>x._pathEntries))
{
}

Expand Down
59 changes: 25 additions & 34 deletions src/OSPSuite.Core/Domain/Services/ModelConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.Linq;
using OSPSuite.Assets;
using OSPSuite.Core.Domain.Builder;
using OSPSuite.Core.Domain.Descriptors;
using OSPSuite.Core.Domain.Mappers;
using OSPSuite.Core.Services;
using OSPSuite.Utility.Events;
Expand All @@ -18,13 +17,11 @@ public interface IModelConstructor

internal class ModelConstructor : IModelConstructor
{
private readonly IContainerBuilderToContainerMapper _containerMapper;
private readonly IMoleculePropertiesContainerTask _moleculePropertiesContainerTask;
private readonly IMoleculeBuilderToMoleculeAmountMapper _moleculeMapper;
private readonly IObjectBaseFactory _objectBaseFactory;
private readonly IObserverBuilderTask _observerBuilderTask;
private readonly IReactionCreator _reactionCreator;
private readonly INeighborhoodCollectionToContainerMapper _neighborhoodsMapper;
private readonly IReferencesResolver _referencesResolver;
private readonly IEventBuilderTask _eventBuilderTask;
private readonly IKeywordReplacerTask _keywordReplacerTask;
Expand All @@ -37,14 +34,13 @@ internal class ModelConstructor : IModelConstructor
private readonly IQuantityValuesUpdater _quantityValuesUpdater;
private readonly IModelValidatorFactory _modelValidatorFactory;
private readonly ICircularReferenceChecker _circularReferenceChecker;
private readonly ISpatialStructureMerger _spatialStructureMerger;

public ModelConstructor(
IObjectBaseFactory objectBaseFactory,
IObserverBuilderTask observerBuilderTask,
IReactionCreator reactionCreator,
IMoleculePropertiesContainerTask moleculePropertiesContainerTask,
IContainerBuilderToContainerMapper containerMapper,
INeighborhoodCollectionToContainerMapper neighborhoodsMapper,
IMoleculeBuilderToMoleculeAmountMapper moleculeMapper,
IReferencesResolver referencesResolver,
IEventBuilderTask eventBuilderTask,
Expand All @@ -57,19 +53,19 @@ public ModelConstructor(
IParameterBuilderToParameterMapper parameterMapper,
IQuantityValuesUpdater quantityValuesUpdater,
IModelValidatorFactory modelValidatorFactory,
ICircularReferenceChecker circularReferenceChecker)
ICircularReferenceChecker circularReferenceChecker,
ISpatialStructureMerger spatialStructureMerger)
{
_objectBaseFactory = objectBaseFactory;
_simulationConfigurationValidator = simulationConfigurationValidator;
_parameterMapper = parameterMapper;
_quantityValuesUpdater = quantityValuesUpdater;
_modelValidatorFactory = modelValidatorFactory;
_circularReferenceChecker = circularReferenceChecker;
_spatialStructureMerger = spatialStructureMerger;
_observerBuilderTask = observerBuilderTask;
_reactionCreator = reactionCreator;
_moleculePropertiesContainerTask = moleculePropertiesContainerTask;
_containerMapper = containerMapper;
_neighborhoodsMapper = neighborhoodsMapper;
_moleculeMapper = moleculeMapper;
_referencesResolver = referencesResolver;
_eventBuilderTask = eventBuilderTask;
Expand Down Expand Up @@ -203,10 +199,10 @@ private ValidationResult checkSimulationConfiguration(ModelConfiguration modelCo
private ValidationResult createModelStructure(ModelConfiguration modelConfiguration)
{
// copy spatial structure with neighborhoods
copySpatialStructure(modelConfiguration);
var spatialStructureValidation = copySpatialStructure(modelConfiguration);

// add molecules with IsPresent=true
var moleculeMessages = createMoleculeAmounts(modelConfiguration);
var moleculeAmountValidation = createMoleculeAmounts(modelConfiguration);

// create local molecule properties container in the spatial structure
addLocalParametersToMolecule(modelConfiguration);
Expand All @@ -217,10 +213,14 @@ private ValidationResult createModelStructure(ModelConfiguration modelConfigurat
// create calculation methods dependent formula and parameters
createMoleculeCalculationMethodsFormula(modelConfiguration);

// replace all keywords define in the model structure
_keywordReplacerTask.ReplaceIn(modelConfiguration.Model.Root);
var validation = new ValidationResult(spatialStructureValidation, moleculeAmountValidation);
if (validation.ValidationState != ValidationState.Invalid)
{
// replace all keywords define in the model structure
_keywordReplacerTask.ReplaceIn(modelConfiguration.Model.Root);
}

return new ValidationResult(moleculeMessages);
return validation;
}

private ValidationResult validateModelName(ModelConfiguration modelConfiguration)
Expand Down Expand Up @@ -262,25 +262,13 @@ private ValidationResult validate<TValidationVisitor>(ModelConfiguration modelCo
return _modelValidatorFactory.Create<TValidationVisitor>().Validate(modelConfiguration);
}

private void copySpatialStructure(ModelConfiguration modelConfiguration)
private ValidationResult copySpatialStructure(ModelConfiguration modelConfiguration)
{
var (model, simulationConfiguration) = modelConfiguration;
// Create Root Container for the model with the name of the model
model.Root = _objectBaseFactory.Create<IContainer>()
.WithName(model.Name)
.WithMode(ContainerMode.Logical)
.WithContainerType(ContainerType.Simulation);

model.Root.AddTag(new Tag(Constants.ROOT_CONTAINER_TAG));
var model = modelConfiguration.Model;
model.Root = _spatialStructureMerger.MergeContainerStructure(modelConfiguration);
model.Neighborhoods = _spatialStructureMerger.MergeNeighborhoods(modelConfiguration);

//Add each container defined in the spatial structure and direct child of the root container
foreach (var topContainer in simulationConfiguration.SpatialStructures.SelectMany(x => x.TopContainers))
{
model.Root.Add(_containerMapper.MapFrom(topContainer, simulationConfiguration));
}

// Add the neighborhoods
model.Neighborhoods = _neighborhoodsMapper.MapFrom(modelConfiguration);
return validate<SpatialStructureValidator>(modelConfiguration);
}

private ValidationResult checkCircularReferences(ModelConfiguration modelConfiguration)
Expand Down Expand Up @@ -369,15 +357,16 @@ private void addLocalStructureMoleculeParametersToMoleculeAmount(IEnumerable<str
}
}

private IEnumerable<ValidationMessage> createMoleculeAmounts(ModelConfiguration modelConfiguration)
private ValidationResult createMoleculeAmounts(ModelConfiguration modelConfiguration)
{
var (_, simulationBuilder) = modelConfiguration;
var presentMolecules = allPresentMoleculesInContainers(modelConfiguration).ToList();

var moleculesWithPhysicalContainers = presentMolecules.Where(containerIsPhysical);
moleculesWithPhysicalContainers.Each(x => { addMoleculeToContainer(simulationBuilder, x.Container, simulationBuilder.MoleculeByName(x.MoleculeStartValue.MoleculeName)); });

return new MoleculeBuildingBlockValidator().Validate(simulationBuilder.Molecules).Messages.Concat(createValidationMessagesForPresentMolecules(presentMolecules));
return new MoleculeBuildingBlockValidator().Validate(simulationBuilder.Molecules)
.AddMessagesFrom(createValidationMessagesForPresentMolecules(presentMolecules));
}

private static bool containerIsPhysical(StartValueAndContainer startValueAndContainer)
Expand All @@ -390,13 +379,15 @@ private void addMoleculeToContainer(SimulationBuilder simulationBuilder, IContai
container.Add(_moleculeMapper.MapFrom(moleculeBuilder, container, simulationBuilder));
}

private IEnumerable<ValidationMessage> createValidationMessagesForPresentMolecules(List<StartValueAndContainer> presentMolecules)
private ValidationResult createValidationMessagesForPresentMolecules(List<StartValueAndContainer> presentMolecules)
{
var moleculesWithoutPhysicalContainers = presentMolecules.Where(x => !containerIsPhysical(x));
return moleculesWithoutPhysicalContainers.Select(x =>
var messages = moleculesWithoutPhysicalContainers.Select(x =>
x.Container == null
? createValidationMessageForNullContainer(x)
: createValidationMessageForMoleculesWithNonPhysicalContainer(x));

return new ValidationResult(messages);
}

private ValidationMessage createValidationMessageForMoleculesWithNonPhysicalContainer(StartValueAndContainer startValueAndContainer)
Expand Down
Loading