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 #1967 add origin #1968

Merged
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
25 changes: 24 additions & 1 deletion src/OSPSuite.Core/Domain/Builder/IndividualParameter.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,29 @@
namespace OSPSuite.Core.Domain.Builder
using OSPSuite.Core.Domain.Formulas;
using OSPSuite.Core.Domain.Services;

namespace OSPSuite.Core.Domain.Builder
{
public class IndividualParameter : PathAndValueEntity
{
public ParameterOrigin Origin { get; set; }

public ParameterInfo Info { get; set; }

/// <summary>
/// Only set for a parameter that is a distributed parameter.
/// This is required in order to be able to create distributed parameter dynamically in the simulation
/// </summary>
public DistributionType? DistributionType { get; set; }

public override void UpdatePropertiesFrom(IUpdatable source, ICloneManager cloneManager)
{
base.UpdatePropertiesFrom(source, cloneManager);
var sourceIndividualParameter = source as IndividualParameter;
if (sourceIndividualParameter == null) return;

DistributionType = sourceIndividualParameter.DistributionType;
Info = sourceIndividualParameter.Info?.Clone();
Origin = sourceIndividualParameter.Origin?.Clone();
}
}
}
14 changes: 2 additions & 12 deletions src/OSPSuite.Core/Domain/Builder/PathAndValueEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,6 @@ public abstract class PathAndValueEntity : Entity, IUsingFormula, IWithDisplayUn
private IDimension _dimension;
private double? _value;

/// <summary>
/// Only set for a parameter that is a distributed parameter.
/// This is required in order to be able to create distributed parameter dynamically in the simulation
/// </summary>
public DistributionType? DistributionType { get; set; }


//Reference to building block containing this entity. This does not have to be serialized
public IBuildingBlock BuildingBlock { get; set; }

Expand Down Expand Up @@ -72,7 +65,6 @@ public Unit DisplayUnit
set => SetProperty(ref _displayUnit, value);
}


public ObjectPath Path
{
get => ContainerPath.Clone<ObjectPath>().AndAdd(Name);
Expand All @@ -98,8 +90,7 @@ protected bool IsEquivalentTo(PathAndValueEntity target)
NullableEqualsCheck(Dimension, target.Dimension, x => x.ToString()) &&
NullableEqualsCheck(Icon, target.Icon) &&
NullableEqualsCheck(Description, target.Description) &&
NullableEqualsCheck(Name, target.Name) &&
DistributionType.GetValueOrDefault().Equals(target.DistributionType.GetValueOrDefault());
NullableEqualsCheck(Name, target.Name);
}

/// <summary>
Expand Down Expand Up @@ -145,7 +136,6 @@ public override void UpdatePropertiesFrom(IUpdatable source, ICloneManager clone
ContainerPath = sourcePathAndValueEntity.ContainerPath.Clone<ObjectPath>();
DisplayUnit = sourcePathAndValueEntity.DisplayUnit;
Dimension = sourcePathAndValueEntity.Dimension;
DistributionType = sourcePathAndValueEntity.DistributionType;
Formula = cloneManager.Clone(sourcePathAndValueEntity.Formula);
ValueOrigin.UpdateAllFrom(sourcePathAndValueEntity.ValueOrigin);
}
Expand All @@ -158,7 +148,7 @@ public void UpdateValueOriginFrom(ValueOrigin sourceValueOrigin)
ValueOrigin.UpdateFrom(sourceValueOrigin);
OnPropertyChanged(() => ValueOrigin);
}

public override string ToString() => $"Path={ContainerPath}, Name={Name}";
}
}
3 changes: 2 additions & 1 deletion src/OSPSuite.Core/Domain/Builder/StartValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ public interface IStartValue : IUsingFormula, IWithDisplayUnit, IWithPath, IWith

public abstract class StartValueBase : PathAndValueEntity, IStartValue
{
public double? StartValue {
public double? StartValue
{
get => Value;
set => Value = value;
}
Expand Down
19 changes: 10 additions & 9 deletions src/OSPSuite.Core/Domain/Parameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public interface IParameter : IQuantity, IWithDefaultState
/// <summary>
/// Meta Information for this parameter
/// </summary>
ParameterInfo Info { get; set; }
ParameterInfo Info { get; }

/// <summary>
/// PK-Sim Building block type of building block in which this parameter is defined.
Expand Down Expand Up @@ -95,7 +95,8 @@ public interface IParameter : IQuantity, IWithDefaultState
void ClearRHSFormula();

/// <summary>
/// Criteria for containers where parameter should be created. This is only useful in builder and is not used in parameter instances
/// Criteria for containers where parameter should be created. This is only useful in builder and is not used in
/// parameter instances
/// </summary>
DescriptorCriteria ContainerCriteria { set; get; }
}
Expand All @@ -104,8 +105,8 @@ public class Parameter : Quantity, IParameter
{
public virtual ParameterBuildMode BuildMode { get; set; }
public virtual IFormula RHSFormula { get; set; }
public virtual ParameterInfo Info { get; set; }
public virtual ParameterOrigin Origin { get; private set; }
public virtual ParameterInfo Info { get; } = new ParameterInfo();
public virtual ParameterOrigin Origin { get; } = new ParameterOrigin();
public virtual double? DefaultValue { get; set; }

public DescriptorCriteria ContainerCriteria { set; get; }
Expand All @@ -118,9 +119,7 @@ public Parameter()
Persistable = false;
BuildMode = ParameterBuildMode.Local;
QuantityType = QuantityType.Parameter;
Info = new ParameterInfo();
Icon = IconNames.PARAMETER;
Origin = new ParameterOrigin();
Rules.AddRange(ParameterRules.All());
NegativeValuesAllowed = true;
}
Expand All @@ -138,10 +137,12 @@ public override void UpdatePropertiesFrom(IUpdatable source, ICloneManager clone
{
base.UpdatePropertiesFrom(source, cloneManager);
var sourceParameter = source as IParameter;
if (sourceParameter == null) return;
if (sourceParameter == null)
return;

BuildMode = sourceParameter.BuildMode;
Info = sourceParameter.Info.Clone();
Origin = sourceParameter.Origin.Clone();
Info.UpdatePropertiesFrom(sourceParameter.Info);
Origin.UpdatePropertiesFrom(sourceParameter.Origin);
DefaultValue = sourceParameter.DefaultValue;
IsDefault = sourceParameter.IsDefault;
ContainerCriteria = sourceParameter.ContainerCriteria?.Clone();
Expand Down
14 changes: 13 additions & 1 deletion src/OSPSuite.Core/Domain/ParameterOrigin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,19 @@ public ParameterOrigin()

public ParameterOrigin Clone()
{
return new ParameterOrigin {BuilingBlockId = BuilingBlockId, ParameterId = ParameterId, SimulationId = SimulationId};
var clone = new ParameterOrigin();
clone.UpdatePropertiesFrom(this);
return clone;
}

public void UpdatePropertiesFrom(ParameterOrigin parameterOrigin)
{
if (parameterOrigin == null)
return;

BuilingBlockId = parameterOrigin.BuilingBlockId;
SimulationId = parameterOrigin.SimulationId;
ParameterId = parameterOrigin.ParameterId;
}
}
}
48 changes: 30 additions & 18 deletions src/OSPSuite.Core/Domain/Services/QuantityValuesUpdater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,61 +59,73 @@ public void UpdateQuantitiesValues(ModelConfiguration modelConfiguration)

private void updateParameterFromExpressionProfiles(ModelConfiguration modelConfiguration)
{
modelConfiguration.SimulationConfiguration.ExpressionProfiles?.SelectMany(x => x).Each(x => updateParameterValueFromStartValue(modelConfiguration, x));
modelConfiguration.SimulationConfiguration.ExpressionProfiles?.SelectMany(x => x).Each(x => updateParameterValueFromStartValue(modelConfiguration, x, getParameter));
}

private void updateParameterFromIndividualValues(ModelConfiguration modelConfiguration)
{
//Order by distribution to ensure that distributed parameter are loaded BEFORE their sub parameters.
//not use descending otherwise parameter without distribution are returned fist
modelConfiguration.SimulationConfiguration.Individual?.OrderByDescending(x => x.DistributionType)
.Each(x => updateParameterValueFromStartValue(modelConfiguration, x, canCreateParameter: true));
.Each(x => updateParameterValueFromStartValue(modelConfiguration, x, getOrAddModelParameter));
}

private void updateParameterValueFromParameterStartValues(ModelConfiguration modelConfiguration)
{
modelConfiguration.SimulationConfiguration.ParameterStartValues.SelectMany(x => x)
.Each(psv => updateParameterValueFromStartValue(modelConfiguration, psv));
.Each(psv => updateParameterValueFromStartValue(modelConfiguration, psv, getParameter));
}

private IParameter getOrAddModelParameter(ModelConfiguration modelConfiguration, PathAndValueEntity pathAndValueEntity, bool canCreateParameter)
private IParameter getOrAddModelParameter(ModelConfiguration modelConfiguration, IndividualParameter individualParameter)
{
var (model, simulationConfiguration) = modelConfiguration;
var pathInModel = _keywordReplacerTask.CreateModelPathFor(pathAndValueEntity.Path, model.Root);
var parameter = pathInModel.Resolve<IParameter>(model.Root);
if (parameter != null || !canCreateParameter)
var parameter = getParameter(modelConfiguration, individualParameter);
if (parameter != null)
return parameter;

var (model, simulationConfiguration) = modelConfiguration;
//Parameter does not exist in the model. We will create it if possible
var parentContainerPathInModel = _keywordReplacerTask.CreateModelPathFor(pathAndValueEntity.ContainerPath, model.Root);
var parentContainerPathInModel = _keywordReplacerTask.CreateModelPathFor(individualParameter.ContainerPath, model.Root);
var parentContainer = parentContainerPathInModel.Resolve<IContainer>(model.Root);

//container does not exist, we do not add new structure to the existing model. Only parameters
if (parentContainer == null)
return null;

var dimension = pathAndValueEntity.Dimension;
var name = pathAndValueEntity.Name;
var displayUnit = pathAndValueEntity.DisplayUnit;
var distributionType = pathAndValueEntity.DistributionType;
var value = pathAndValueEntity.Value;
var name = individualParameter.Name;
var dimension = individualParameter.Dimension;
var displayUnit = individualParameter.DisplayUnit;
var distributionType = individualParameter.DistributionType;

//if the distribution is undefined or the value is set, we create a default parameter to ensure that the value will take precedence.
//Otherwise, we create a distributed parameter and assume that required sub-parameters will be created as well
parameter = distributionType == null || value != null ? _parameterFactory.CreateParameter(name, dimension: dimension, displayUnit: displayUnit) : _parameterFactory.CreateDistributedParameter(name, distributionType.Value, dimension: dimension, displayUnit: displayUnit);
parameter = distributionType == null || individualParameter.Value != null ?
_parameterFactory.CreateParameter(name, dimension: dimension, displayUnit: displayUnit) :
_parameterFactory.CreateDistributedParameter(name, distributionType.Value, dimension: dimension, displayUnit: displayUnit);

simulationConfiguration.AddBuilderReference(parameter, pathAndValueEntity);
//Update meta properties if defined
parameter.Origin.UpdatePropertiesFrom(individualParameter.Origin);
parameter.Info.UpdatePropertiesFrom(individualParameter.Info);

simulationConfiguration.AddBuilderReference(parameter, individualParameter);
return parameter.WithParentContainer(parentContainer);
}

private void updateParameterValueFromStartValue(ModelConfiguration modelConfiguration, PathAndValueEntity pathAndValueEntity, bool canCreateParameter = false)
private IParameter getParameter(ModelConfiguration modelConfiguration, PathAndValueEntity pathAndValueEntity)
{
var parameter = getOrAddModelParameter(modelConfiguration, pathAndValueEntity, canCreateParameter);
var (model, _) = modelConfiguration;
var pathInModel = _keywordReplacerTask.CreateModelPathFor(pathAndValueEntity.Path, model.Root);
return pathInModel.Resolve<IParameter>(model.Root);
}

private void updateParameterValueFromStartValue<T>(ModelConfiguration modelConfiguration, T pathAndValueEntity, Func<ModelConfiguration, T, IParameter> getParameterFunc) where T : PathAndValueEntity
{
var parameter = getParameterFunc(modelConfiguration, pathAndValueEntity);
//this can happen if the parameter does not exist in the model
if (parameter == null)
return;

var (model, _) = modelConfiguration;

//Formula is defined, we update in the parameter instance
if (pathAndValueEntity.Formula != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,12 @@ namespace OSPSuite.Core.Serialization.Xml
{
public class IndividualParameterXmlSerializer : PathAndValueEntityXmlSerializer<IndividualParameter>
{
public override void PerformMapping()
{
base.PerformMapping();
Map(x => x.DistributionType);
Map(x => x.Origin);
Map(x => x.Info);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ public override void PerformMapping()
Map(x => x.ContainerPath);
MapReference(x => x.Formula);
Map(x => x.Value);
Map(x => x.DistributionType);
}
}
}
29 changes: 26 additions & 3 deletions tests/OSPSuite.Core.Tests/Domain/IndividualBuildingBlockSpecs.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Linq;
using System;
using System.Linq;
using OSPSuite.BDDHelper;
using OSPSuite.BDDHelper.Extensions;
using OSPSuite.Core.Domain.Builder;
using OSPSuite.Core.Domain.Formulas;
using OSPSuite.Core.Domain.Services;
using OSPSuite.Core.Domain.UnitSystem;
using OSPSuite.Helpers;
Expand Down Expand Up @@ -36,7 +38,20 @@ protected override void Context()
_cloneManager = new CloneManagerForBuildingBlock(_objectBaseFactory, _repositoryTask);
_sourceIndividualBuildingBlock.Name = "An Individual";
_sourceIndividualBuildingBlock.PKSimVersion = "11.1";
_sourceIndividualBuildingBlock.Add(new IndividualParameter().WithName("name1"));
var individualParameter = new IndividualParameter().WithName("name1");
individualParameter.DistributionType = DistributionType.Discrete;
individualParameter.Origin = new ParameterOrigin
{
SimulationId = "SimId",
BuilingBlockId = "BbId",
ParameterId = "ParamId"
};
individualParameter.Info = new ParameterInfo
{
ReadOnly = true
};

_sourceIndividualBuildingBlock.Add(individualParameter);
_originDataItem = new ExtendedProperty<string>()
{
Description = "Description",
Expand All @@ -53,11 +68,19 @@ protected override void Because()
}

[Observation]
public void the_updated_expression_profile_should_have_properties_set()
public void the_updated_individual_should_have_properties_set()
{
sut.Name.ShouldBeEqualTo("An Individual");
sut.PKSimVersion.ShouldBeEqualTo("11.1");
sut.Count().ShouldBeEqualTo(1);

var clonedIndividualParameter = sut.First();
clonedIndividualParameter.DistributionType.ShouldBeEqualTo(DistributionType.Discrete);
clonedIndividualParameter.Origin.SimulationId.ShouldBeEqualTo("SimId");
clonedIndividualParameter.Origin.BuilingBlockId.ShouldBeEqualTo("BbId");
clonedIndividualParameter.Origin.ParameterId.ShouldBeEqualTo("ParamId");
clonedIndividualParameter.Info.ReadOnly.ShouldBeTrue();

sut.OriginData.All.Length.ShouldBeEqualTo(1);
var clonedOriginDataItem = sut.OriginData.All.First();

Expand Down