Skip to content

Commit

Permalink
Fixes #909 aging data for calculation (#910)
Browse files Browse the repository at this point in the history
* Fixes #909 aging data for calculation

* Fixes #909 aging data for calculation

* Fixes #909 aging data for calculation
  • Loading branch information
msevestre authored Mar 9, 2021
1 parent 5ac4791 commit b1d8da8
Show file tree
Hide file tree
Showing 10 changed files with 272 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using OSPSuite.Core.Domain.Data;
using OSPSuite.Core.Domain.SensitivityAnalyses;
using OSPSuite.Core.Domain.UnitSystem;
using OSPSuite.Core.Extensions;
using OSPSuite.Utility.Collections;
using OSPSuite.Utility.Extensions;
using static OSPSuite.Core.Domain.Constants.SimulationResults;
Expand Down Expand Up @@ -120,17 +121,15 @@ public DataTable SensitivityAnalysisResultsToDataTable(SensitivityAnalysisRunRes
foreach (var pkParameterSensitivity in sensitivityAnalysisRunResult.AllPKParameterSensitivities)
{
var row = dataTable.NewRow();
row[Constants.SensitivityAnalysisResults.QUANTITY_PATH] = inQuote(pkParameterSensitivity.QuantityPath);
row[Constants.SensitivityAnalysisResults.PARAMETER] = inQuote(pkParameterSensitivity.ParameterName);
row[Constants.SensitivityAnalysisResults.PK_PARAMETER] = inQuote(pkParameterSensitivity.PKParameterName);
row[Constants.SensitivityAnalysisResults.QUANTITY_PATH] = pkParameterSensitivity.QuantityPath.InQuotes();
row[Constants.SensitivityAnalysisResults.PARAMETER] = pkParameterSensitivity.ParameterName.InQuotes();
row[Constants.SensitivityAnalysisResults.PK_PARAMETER] = pkParameterSensitivity.PKParameterName.InQuotes();
row[Constants.SensitivityAnalysisResults.VALUE] = pkParameterSensitivity.Value.ConvertedTo<string>();
dataTable.Rows.Add(row);
}

dataTable.EndLoadData();
return dataTable;
}

private string inQuote(string text)=> $"\"{text}\"";
}
}
9 changes: 9 additions & 0 deletions src/OSPSuite.Core/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,14 @@ public static string StripUnit(this string stringToStrip)

return indexOfUnitStart == -1 ? stringToStrip : stringToStrip.Remove(indexOfUnitStart, stringToStrip.Length - indexOfUnitStart).TrimEnd();
}

/// <summary>
/// Returns the give text within quotes.
/// </summary>
/// <example>
/// InQuotes(test) => "test"
/// </example>
/// <param name="text">Text to encapsulate in quotes</param>
public static string InQuotes(this string text) => $"\"{text}\"";
}
}
57 changes: 57 additions & 0 deletions src/OSPSuite.R/Domain/AgingData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System.Data;
using OSPSuite.Core.Domain;
using OSPSuite.Utility.Extensions;

namespace OSPSuite.R.Domain
{
public class AgingData
{
public int[] IndividualIds { get; set; }
public string[] ParameterPaths { get; set; }
public double[] Times { get; set; }
public double[] Values { get; set; }

public DataTable ToDataTable()
{
verifyData();
var dataTable = new DataTable();
dataTable.AddColumn<int>(Constants.Population.INDIVIDUAL_ID_COLUMN);
dataTable.AddColumn<string>(Constants.Population.PARAMETER_PATH_COLUMN);
dataTable.AddColumn<double>(Constants.Population.TIME_COLUMN);
dataTable.AddColumn<double>(Constants.Population.VALUE_COLUMN);


for (var i = 0; i < IndividualIds.Length; i++)
{
var row = dataTable.NewRow();
row[Constants.Population.INDIVIDUAL_ID_COLUMN] = IndividualIds[i];
row[Constants.Population.PARAMETER_PATH_COLUMN] = ParameterPaths[i];
row[Constants.Population.TIME_COLUMN] = Times[i];
row[Constants.Population.VALUE_COLUMN] = Values[i];
dataTable.Rows.Add(row);
}

return dataTable;
}

private void verifyData()
{
if (IndividualIds == null)
raiseUndefinedError("IndividualIds");

if (ParameterPaths == null)
raiseUndefinedError("ParameterPaths");

if (Times == null)
raiseUndefinedError("Times");

if (Values == null)
raiseUndefinedError("Values");

if (IndividualIds.Length != ParameterPaths.Length || IndividualIds.Length != Times.Length || IndividualIds.Length != Values.Length)
throw new InvalidArgumentException($"AgingData values do not have the expected length ({IndividualIds.Length})");
}

private void raiseUndefinedError(string type) => throw new InvalidArgumentException($"'{type}' is undefined");
}
}
65 changes: 46 additions & 19 deletions src/OSPSuite.R/Services/SimulationRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,33 @@
using OSPSuite.Core.Domain.Services;
using OSPSuite.Core.Serialization.SimModel.Services;
using OSPSuite.Core.Services;
using OSPSuite.R.Domain;
using OSPSuite.Utility.Events;
using SimulationRunOptions = OSPSuite.R.Domain.SimulationRunOptions;

namespace OSPSuite.R.Services
{
public interface ISimulationRunner
public class SimulationRunArgs
{
Task<SimulationResults> RunAsync(IModelCoreSimulation simulation, SimulationRunOptions simulationRunOptions = null);
SimulationResults Run(IModelCoreSimulation simulation, SimulationRunOptions simulationRunOptions = null);
public IModelCoreSimulation Simulation { get; set; }
public SimulationRunOptions SimulationRunOptions { get; set; }
public IndividualValuesCache Population { get; set; }
public AgingData AgingData { get; set; }

SimulationResults Run(IModelCoreSimulation simulation, IndividualValuesCache population, SimulationRunOptions simulationRunOptions = null);
Task<SimulationResults> RunAsync(IModelCoreSimulation simulation, IndividualValuesCache population, SimulationRunOptions simulationRunOptions = null);
public void Deconstruct(out IModelCoreSimulation simulation, out IndividualValuesCache population, out AgingData agingData,
out SimulationRunOptions simulationRunOptions)
{
simulation = Simulation;
simulationRunOptions = SimulationRunOptions;
population = Population;
agingData = AgingData;
}
}

public interface ISimulationRunner
{
Task<SimulationResults> RunAsync(SimulationRunArgs simulationRunArgs);
SimulationResults Run(SimulationRunArgs simulationRunArgs);
}

public class SimulationRunner : ISimulationRunner
Expand Down Expand Up @@ -50,7 +64,8 @@ public SimulationRunner(

private void simulationProgress(object sender, MultipleSimulationsProgressEventArgs e)
{
_progressUpdater.ReportProgress(e.NumberOfCalculatedSimulation, e.NumberOfSimulations, Messages.CalculationPopulationSimulation(e.NumberOfCalculatedSimulation, e.NumberOfSimulations));
_progressUpdater.ReportProgress(e.NumberOfCalculatedSimulation, e.NumberOfSimulations,
Messages.CalculationPopulationSimulation(e.NumberOfCalculatedSimulation, e.NumberOfSimulations));
}

private void simulationTerminated()
Expand All @@ -65,24 +80,23 @@ private void terminated(object sender, EventArgs e)
_populationRunner.SimulationProgress -= simulationProgress;
}

public SimulationResults Run(IModelCoreSimulation simulation, SimulationRunOptions simulationRunOptions = null)
{
return RunAsync(simulation, simulationRunOptions).Result;
}

public SimulationResults Run(IModelCoreSimulation simulation, IndividualValuesCache population, SimulationRunOptions simulationRunOptions = null)
{
return RunAsync(simulation, population, simulationRunOptions).Result;
}

public async Task<SimulationResults> RunAsync(IModelCoreSimulation simulation, IndividualValuesCache population, SimulationRunOptions simulationRunOptions = null)
private async Task<SimulationResults> runAsync(
IModelCoreSimulation simulation,
IndividualValuesCache population,
AgingData agingData = null,
SimulationRunOptions simulationRunOptions = null)
{
var options = simulationRunOptions ?? new SimulationRunOptions();
initializeProgress(options);
_simulationPersistableUpdater.UpdateSimulationPersistable(simulation);
try
{
var populationRunResults = await _populationRunner.RunPopulationAsync(simulation, options, _populationTask.PopulationTableFrom(population, simulation));
var populationRunResults = await _populationRunner.RunPopulationAsync(
simulation,
options,
populationData: _populationTask.PopulationTableFrom(population, simulation),
agingData: agingData?.ToDataTable()
);
return populationRunResults.Results;
}
finally
Expand All @@ -98,7 +112,7 @@ private void initializeProgress(SimulationRunOptions options)
_progressUpdater = options.ShowProgress ? _progressManager.Create() : new NoneProgressUpdater();
}

public Task<SimulationResults> RunAsync(IModelCoreSimulation simulation, SimulationRunOptions simulationRunOptions = null)
private Task<SimulationResults> runAsync(IModelCoreSimulation simulation, SimulationRunOptions simulationRunOptions)
{
return Task.Run(() =>
{
Expand All @@ -117,5 +131,18 @@ private Core.Domain.SimulationRunOptions coreSimulationRunOptionsFrom(Simulation
SimModelExportMode = SimModelExportMode.Optimized
};
}

public Task<SimulationResults> RunAsync(SimulationRunArgs simulationRunArgs)
{
var (simulation, population, agingData, simulationRunOptions) = simulationRunArgs;
return population == null ?
runAsync(simulation, simulationRunOptions) :
runAsync(simulation, population, agingData, simulationRunOptions);
}

public SimulationResults Run(SimulationRunArgs simulationRunArgs)
{
return RunAsync(simulationRunArgs).Result;
}
}
}
9 changes: 9 additions & 0 deletions tests/OSPSuite.Core.Tests/Domain/StringExtensionsSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,13 @@ public void should_return_the_expected_string(string input, string result)
input.StripUnit().ShouldBeEqualTo(result);
}
}

public class When_returning_a_string_in_quotes : StaticContextSpecification
{
[Observation]
public void should_return_the_expected_string()
{
"text".InQuotes().ShouldBeEqualTo("\"text\"");
}
}
}
80 changes: 80 additions & 0 deletions tests/OSPSuite.R.Tests/Services/AgingDataSpecs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System.Data;
using OSPSuite.BDDHelper;
using OSPSuite.BDDHelper.Extensions;
using OSPSuite.Core.Domain;
using OSPSuite.Core.Extensions;
using OSPSuite.R.Domain;

namespace OSPSuite.R.Services
{
public abstract class concern_for_AgingData : ContextSpecification<AgingData>
{
protected override void Context()
{
sut = new AgingData();
}
}

public class When_converting_an_uninitialized_aging_data_to_data_table : concern_for_AgingData
{
[Observation]
public void should_thrown_an_exception()
{
The.Action(() => sut.ToDataTable()).ShouldThrowAn<InvalidArgumentException>();
}
}

public class When_converting_an_invalid_aging_data_to_data_table : concern_for_AgingData
{
protected override void Context()
{
base.Context();
sut.IndividualIds = new[] {1, 2};
sut.ParameterPaths = new[] {"Path1", "Path1"};
sut.Times = new[] {1.0, 2.0};
sut.Values = new[] {1.0, 2.0, 3.0};
}

[Observation]
public void should_thrown_an_exception()
{
The.Action(() => sut.ToDataTable()).ShouldThrowAn<InvalidArgumentException>();
}
}

public class When_converting_a_valid_aging_data_to_data_table : concern_for_AgingData
{
private DataTable _dataTable;

protected override void Context()
{
base.Context();
sut.IndividualIds = new[] {1, 2};
sut.ParameterPaths = new[] {"Path1", "Path2"};
sut.Times = new[] {1.0, 2.0};
sut.Values = new[] {3.0, 4.0};
}

protected override void Because()
{
_dataTable = sut.ToDataTable();
}

[Observation]
public void should_thrown_an_exception()
{
_dataTable.Columns.Count.ShouldBeEqualTo(4);
_dataTable.Rows[0].ValueAt<int>(Constants.Population.INDIVIDUAL_ID_COLUMN).ShouldBeEqualTo(1);
_dataTable.Rows[1].ValueAt<int>(Constants.Population.INDIVIDUAL_ID_COLUMN).ShouldBeEqualTo(2);

_dataTable.Rows[0].ValueAt<string>(Constants.Population.PARAMETER_PATH_COLUMN).ShouldBeEqualTo("Path1");
_dataTable.Rows[1].ValueAt<string>(Constants.Population.PARAMETER_PATH_COLUMN).ShouldBeEqualTo("Path2");

_dataTable.Rows[0].ValueAt<double>(Constants.Population.TIME_COLUMN).ShouldBeEqualTo(1.0);
_dataTable.Rows[1].ValueAt<double>(Constants.Population.TIME_COLUMN).ShouldBeEqualTo(2.0);

_dataTable.Rows[0].ValueAt<double>(Constants.Population.VALUE_COLUMN).ShouldBeEqualTo(3.0);
_dataTable.Rows[1].ValueAt<double>(Constants.Population.VALUE_COLUMN).ShouldBeEqualTo(4.0);
}
}
}
10 changes: 5 additions & 5 deletions tests/OSPSuite.R.Tests/Services/PKAnalysisTaskSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public class When_exporting_the_pk_analysis_to_data_frame_with_value_in_another_
protected override void Context()
{
base.Context();
_result = _simulationRunner.Run(_simulation);
_result = _simulationRunner.Run(new SimulationRunArgs { Simulation = _simulation });
_userDefinedPKParameter =
_pkParameterTask.CreateUserDefinedPKParameter("MyCmax", StandardPKParameter.C_max, displayName: null, displayUnit: "mg/l");
_pkParameterTask.AddUserDefinedPKParameter(_userDefinedPKParameter);
Expand Down Expand Up @@ -111,7 +111,7 @@ protected override void Context()
var simulationFile = HelperForSpecs.DataFile("multiple_dosing.pkml");
var simulationPersister = Api.GetSimulationPersister();
_simulation = simulationPersister.LoadSimulation(simulationFile);
_result = _simulationRunner.Run(_simulation);
_result = _simulationRunner.Run(new SimulationRunArgs { Simulation = _simulation });
}

protected override void Because()
Expand Down Expand Up @@ -141,7 +141,7 @@ public override void GlobalContext()
_population = populationTask.ImportPopulation(populationFile);
//negative volumes ensures that we have one simulation crashing
_population.SetValues("Organism|Liver|Volume", new[] {2.3, 2.3, 2.3, -10, 2.3});
_result = _simulationRunner.Run(_simulation, _population);
_result = _simulationRunner.Run(new SimulationRunArgs { Simulation = _simulation, Population = _population});
}

protected override void Because()
Expand Down Expand Up @@ -175,7 +175,7 @@ public override void GlobalContext()
_population.IndividualIds.AddRange(new []{ 2, 4, 6, 8, 10});
//negative volumes ensures that we have one simulation crashing
_population.SetValues("Organism|Liver|Volume", new[] { 2.3, 2.3, 2.3, -10, 2.3 });
_result = _simulationRunner.Run(_simulation, _population);
_result = _simulationRunner.Run(new SimulationRunArgs { Simulation = _simulation, Population = _population});
}

protected override void Because()
Expand Down Expand Up @@ -207,7 +207,7 @@ public override void GlobalContext()
_population = populationTask.ImportPopulation(populationFile);
//negative volumes ensures that we have one simulation crashing
_population.SetValues("Organism|Liver|Volume", new[] { 2.3, 2.3, 2.3, 2.3, -10 });
_result = _simulationRunner.Run(_simulation, _population);
_result = _simulationRunner.Run(new SimulationRunArgs { Simulation = _simulation, Population = _population});
}

protected override void Because()
Expand Down
4 changes: 2 additions & 2 deletions tests/OSPSuite.R.Tests/Services/SimulationResultsTaskSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ protected override void Context()
{
base.Context();
var simulationRunner = Api.GetSimulationRunner();
_results = simulationRunner.Run(_simulation);
_results = simulationRunner.Run(new SimulationRunArgs { Simulation = _simulation });
_csvFile = FileHelper.GenerateTemporaryFileName();
}

Expand Down Expand Up @@ -129,7 +129,7 @@ protected override void Context()
_simulation = _simulationPersister.LoadSimulation(simulationFile);

var simulationRunner = Api.GetSimulationRunner();
_results = simulationRunner.Run(_simulation);
_results = simulationRunner.Run(new SimulationRunArgs { Simulation = _simulation });
_csvFile = FileHelper.GenerateTemporaryFileName();
}

Expand Down
Loading

0 comments on commit b1d8da8

Please sign in to comment.