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 #2260 - including "Global" PK-Parameters into the box-plot/scatter plot #2359

Merged
merged 4 commits into from
Oct 18, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
19 changes: 14 additions & 5 deletions src/PKSim.Core/Model/PopulationSimulation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using OSPSuite.Core.Extensions;
using OSPSuite.Core.Maths.Random;
using OSPSuite.Utility.Extensions;
using PKSim.Core.Extensions;
using PKSim.Core.Repositories;

namespace PKSim.Core.Model
Expand Down Expand Up @@ -280,27 +279,37 @@ private DataColumn medianAggregateDataColumns(IReadOnlyList<DataColumn> columns)
return new DataColumn(column.Id, column.Dimension, column.BaseGrid)
{
Values = Enumerable.Range(0, column.Values.Count).Select(i =>
IndexedValuesFromColumns(columns, i).Median()
indexedValuesFromColumns(columns, i).Median()
).ToList()
};
}

private static IReadOnlyList<float> IndexedValuesFromColumns(IReadOnlyList<DataColumn> columns, int i)
private static IReadOnlyList<float> indexedValuesFromColumns(IReadOnlyList<DataColumn> columns, int i)
{
return columns.Select(x => x.Values[i]).ToList();
}

public override DataColumn PeripheralVenousBloodColumn(string compoundName)
{
return medianAggregateDataColumns(drugColumnFor(CoreConstants.Organ.PERIPHERAL_VENOUS_BLOOD, CoreConstants.Observer.PLASMA_PERIPHERAL_VENOUS_BLOOD, CoreConstants.Observer.PLASMA_PERIPHERAL_VENOUS_BLOOD, compoundName));
return medianAggregateDataColumns(PeripheralVenousBloodColumns(compoundName));
}

public IReadOnlyList<DataColumn> PeripheralVenousBloodColumns(string compoundName)
Copy link
Member

Choose a reason for hiding this comment

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

why is this public?

Copy link
Member Author

Choose a reason for hiding this comment

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

GlobalPKAnalysisTask needs to get access to all the columns for PeripheralVenousBlood and VenousBlood

{
return drugColumnFor(CoreConstants.Organ.PERIPHERAL_VENOUS_BLOOD, CoreConstants.Observer.PLASMA_PERIPHERAL_VENOUS_BLOOD, CoreConstants.Observer.PLASMA_PERIPHERAL_VENOUS_BLOOD, compoundName);
}

/// <summary>
/// tries to find venous blood plasma if defined in the repository. returns null otherwise
/// </summary>
public override DataColumn VenousBloodColumn(string compoundName)
{
return medianAggregateDataColumns(drugColumnFor(CoreConstants.Organ.VENOUS_BLOOD, CoreConstants.Compartment.PLASMA, CoreConstants.Observer.CONCENTRATION_IN_CONTAINER, compoundName));
return medianAggregateDataColumns(VenousBloodColumns(compoundName));
}

public IReadOnlyList<DataColumn> VenousBloodColumns(string compoundName)
Copy link
Member

Choose a reason for hiding this comment

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

why is this public?

{
return drugColumnFor(CoreConstants.Organ.VENOUS_BLOOD, CoreConstants.Compartment.PLASMA, CoreConstants.Observer.CONCENTRATION_IN_CONTAINER, compoundName);
}

public override DataColumn FabsOral(string compoundName)
Expand Down
260 changes: 175 additions & 85 deletions src/PKSim.Core/Services/GlobalPKAnalysisTask.cs

Large diffs are not rendered by default.

35 changes: 9 additions & 26 deletions src/PKSim.Core/Services/PKAnalysesTask.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using OSPSuite.Core.Domain;
using OSPSuite.Core.Domain.Data;
using OSPSuite.Core.Domain.PKAnalyses;
Expand Down Expand Up @@ -58,35 +57,34 @@ public interface IPKAnalysesTask : OSPSuite.Core.Domain.Services.IPKAnalysesTask
public class PKAnalysesTask : OSPSuite.Core.Domain.Services.PKAnalysesTask, IPKAnalysesTask
{
private readonly ILazyLoadTask _lazyLoadTask;
private readonly IEntityPathResolver _entityPathResolver;
private readonly IPKValuesCalculator _pkValuesCalculator;
private readonly IPKValuesToPKAnalysisMapper _pkMapper;
private readonly IDimensionRepository _dimensionRepository;
private readonly IPKCalculationOptionsFactory _pkCalculationOptionsFactory;
protected readonly IPKCalculationOptionsFactory _pkCalculationOptionsFactory;
private readonly IPKParameterRepository _pkParameterRepository;
private readonly Regex _rangeRegex = new Regex(@"^(.*)Range (\d*)% to (\d*)%");
private readonly IStatisticalDataCalculator _statisticalDataCalculator;
private readonly IRepresentationInfoRepository _representationInfoRepository;
private readonly IPopulationSimulationBodyWeightUpdater _populationSimulationBodyWeightUpdater;

public PKAnalysesTask(ILazyLoadTask lazyLoadTask,
IPKValuesCalculator pkValuesCalculator,
IPKParameterRepository pkParameterRepository,
IPKCalculationOptionsFactory pkCalculationOptionsFactory,
IEntityPathResolver entityPathResolver,
IPKValuesToPKAnalysisMapper pkMapper,
IDimensionRepository dimensionRepository,
IStatisticalDataCalculator statisticalDataCalculator,
IRepresentationInfoRepository representationInfoRepository) : base(lazyLoadTask, pkValuesCalculator, pkParameterRepository, pkCalculationOptionsFactory)
IRepresentationInfoRepository representationInfoRepository,
IPopulationSimulationBodyWeightUpdater populationSimulationBodyWeightUpdater) : base(lazyLoadTask, pkValuesCalculator, pkParameterRepository, pkCalculationOptionsFactory)
{
_lazyLoadTask = lazyLoadTask;
_entityPathResolver = entityPathResolver;
_pkMapper = pkMapper;
_dimensionRepository = dimensionRepository;
_pkValuesCalculator = pkValuesCalculator;
_pkCalculationOptionsFactory = pkCalculationOptionsFactory;
_pkParameterRepository = pkParameterRepository;
_statisticalDataCalculator = statisticalDataCalculator;
_representationInfoRepository = representationInfoRepository;
_populationSimulationBodyWeightUpdater = populationSimulationBodyWeightUpdater;
}

public PopulationSimulationPKAnalyses CalculateFor(PopulationSimulation populationSimulation)
Expand All @@ -95,17 +93,15 @@ public PopulationSimulationPKAnalyses CalculateFor(PopulationSimulation populati
if (!populationSimulation.HasResults)
return new NullPopulationSimulationPKAnalyses();

var bodyWeightParameter = populationSimulation.BodyWeight;
var bodyWeightParameterPath = bodyWeightParameterPathFrom(bodyWeightParameter);
var allBodyWeights = populationSimulation.AllValuesFor(bodyWeightParameterPath);


try
{
return base.CalculateFor(populationSimulation, populationSimulation.Results, (individualId) => { updateBodyWeightFromCurrentIndividual(bodyWeightParameter, allBodyWeights, individualId); });
return base.CalculateFor(populationSimulation, populationSimulation.Results, (individualId) => { _populationSimulationBodyWeightUpdater.UpdateBodyWeightForIndividual(populationSimulation, individualId); });
}
finally
{
bodyWeightParameter?.ResetToDefault();
_populationSimulationBodyWeightUpdater.ResetBodyWeightParameter(populationSimulation);
}
}

Expand All @@ -117,7 +113,7 @@ public IEnumerable<PopulationPKAnalysis> CalculateFor(IPopulationDataCollector p
return pkAnalyses; // there are no analyses to calculate

var allColumns = timeProfileChartData.Panes.SelectMany(x => x.Curves).SelectMany(x =>
columnsFor(x, populationDataCollector).Select(column => new { curveData = x, column = column }))
columnsFor(x, populationDataCollector).Select(column => new { curveData = x, column }))
.Where(c => c.column.IsConcentration());

var columnsByMolecules = allColumns.GroupBy(x => x.column.MoleculeName());
Expand Down Expand Up @@ -259,19 +255,6 @@ private IBusinessRule warningRule(string warning) =>
.WithRule((param, value) => false)
.WithError((param, value) => warning);

private string bodyWeightParameterPathFrom(IParameter bodyWeightParameter)
{
return bodyWeightParameter != null ? _entityPathResolver.PathFor(bodyWeightParameter) : string.Empty;
}

private void updateBodyWeightFromCurrentIndividual(IParameter bodyWeightParameter, IReadOnlyList<double> allBodyWeights, int individualId)
{
if (bodyWeightParameter == null)
return;

bodyWeightParameter.Value = allBodyWeights.Count > individualId ? allBodyWeights[individualId] : double.NaN;
}

public PKAnalysis CreatePKAnalysisFromValues(PKValues pkValues, Simulation simulation, Compound compound)
{
var options = _pkCalculationOptionsFactory.CreateFor(simulation, compound.Name);
Expand Down
44 changes: 44 additions & 0 deletions src/PKSim.Core/Services/PopulationSimulationBodyWeightUpdater.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using OSPSuite.Core.Domain;
using OSPSuite.Core.Domain.Services;
using PKSim.Core.Model;

namespace PKSim.Core.Services
{
public interface IPopulationSimulationBodyWeightUpdater
{
void UpdateBodyWeightForIndividual(PopulationSimulation populationSimulation, int individualId);
void ResetBodyWeightParameter(PopulationSimulation populationSimulation);
}

public class PopulationSimulationBodyWeightUpdater : IPopulationSimulationBodyWeightUpdater
{
private readonly IEntityPathResolver _entityPathResolver;

public PopulationSimulationBodyWeightUpdater(IEntityPathResolver entityPathResolver)
{
_entityPathResolver = entityPathResolver;
}

public void UpdateBodyWeightForIndividual(PopulationSimulation populationSimulation, int individualId)
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason why this was moved out of the PK Stuff? Because you are doing line 24 to 26 now for EAch individual as opposed to one time.

Copy link
Member Author

Choose a reason for hiding this comment

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

The only reason for it was that originally I was reproducing the scaling logic in a second location. I think it makes sense to put it back now.

{
var bodyWeightParameter = populationSimulation.BodyWeight;
var bodyWeightParameterPath = bodyWeightParameterPathFrom(bodyWeightParameter);
var allBodyWeights = populationSimulation.AllValuesFor(bodyWeightParameterPath);

if (bodyWeightParameter == null)
return;

bodyWeightParameter.Value = allBodyWeights.Count > individualId ? allBodyWeights[individualId] : double.NaN;
}

public void ResetBodyWeightParameter(PopulationSimulation populationSimulation)
{
populationSimulation.BodyWeight?.ResetToDefault();
}

private string bodyWeightParameterPathFrom(IParameter bodyWeightParameter)
{
return bodyWeightParameter != null ? _entityPathResolver.PathFor(bodyWeightParameter) : string.Empty;
}
}
}
11 changes: 7 additions & 4 deletions src/PKSim.Core/Services/SimulationResultsSynchronizer.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System.Linq;
using OSPSuite.Core.Domain;
using OSPSuite.Core.Domain.Data;
using OSPSuite.Core.Extensions;
using OSPSuite.Core.Services;
using OSPSuite.Utility.Collections;
using OSPSuite.Utility.Extensions;
Expand Down Expand Up @@ -37,17 +35,20 @@ public class SimulationResultsSynchronizer : ISimulationResultsSynchronizer
private readonly ISimulationResultsCreator _simulationResultsCreator;
private readonly IDisplayUnitUpdater _displayUnitUpdater;
private readonly IDataRepositoryFromResultsCreator _dataRepositoryFromResultsCreator;
private readonly IGlobalPKAnalysisTask _globalPKAnalysisTask;

public SimulationResultsSynchronizer(
IPKAnalysesTask populationPKAnalysesTask,
ISimulationResultsCreator simulationResultsCreator,
IDisplayUnitUpdater displayUnitUpdater,
IDataRepositoryFromResultsCreator dataRepositoryFromResultsCreator)
IDisplayUnitUpdater displayUnitUpdater,
IDataRepositoryFromResultsCreator dataRepositoryFromResultsCreator,
IGlobalPKAnalysisTask globalPKAnalysisTask)
{
_populationPKAnalysesTask = populationPKAnalysesTask;
_simulationResultsCreator = simulationResultsCreator;
_displayUnitUpdater = displayUnitUpdater;
_dataRepositoryFromResultsCreator = dataRepositoryFromResultsCreator;
_globalPKAnalysisTask = globalPKAnalysisTask;
}

public void Synchronize(IndividualSimulation simulation, DataRepository newResults)
Expand All @@ -71,6 +72,8 @@ public void Synchronize(PopulationSimulation populationSimulation, SimulationRes
{
populationSimulation.Results = newResults;
populationSimulation.PKAnalyses = _populationPKAnalysesTask.CalculateFor(populationSimulation);

_globalPKAnalysisTask.CalculateQuantityPKForPopulationSimulation(populationSimulation).Each(populationSimulation.PKAnalyses.AddPKAnalysis);
}

private void updateSequence(DataRepository results)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.Linq;
using PKSim.Core.Model;
using PKSim.Core.Services;
using PKSim.Presentation.DTO.Mappers;
using PKSim.Presentation.DTO.PopulationAnalyses;

using PKSim.Presentation.Presenters.Populations;
Expand All @@ -13,6 +12,7 @@
using OSPSuite.Core.Domain.PKAnalyses;
using OSPSuite.Presentation.Mappers;
using OSPSuite.Presentation.Presenters;
using OSPSuite.Utility.Extensions;

namespace PKSim.Presentation.Presenters.PopulationAnalyses
{
Expand Down Expand Up @@ -69,6 +69,16 @@ private void createAvailableQuantitiesListBasedOn(IPopulationDataCollector popul
{
_allPKParameters.Clear();
_allPKParameters.AddRange(_entitiesInContainerRetriever.OutputsFrom(populationDataCollector).SelectMany(availablePKParametersFor));

populationDataCollector.Compounds.Select(x => x.Name).Each(compoundName =>
Copy link
Member

Choose a reason for hiding this comment

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

Extension method AllNames

{
_allPKParameters.AddRange(populationDataCollector.AllPKParametersFor(compoundName).Select(globalPKParameters));
});
}

private QuantityPKParameterDTO globalPKParameters(QuantityPKParameter globalPKParameter)
{
return mapFrom(globalPKParameter, globalPKParameter.QuantityPath);
}

public IEnumerable<QuantityPKParameter> SelectedPKParameters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ private PopulationAnalysisPKParameterField createFieldFrom(QuantityPKParameter p
{
var quantity = _allQuantities[pkParameter.QuantityPath];
if (quantity == null)
return null;
return _populationAnalysisFieldFactory.CreateFor(pkParameter, QuantityType.Drug | QuantityType.Observer, quantityDisplayPath);
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure here. Clearly the quantity is not going to be found in the _allQuantities cache. But I'm not sure how get around this. Should there be additional values added int _allQuantities?

Copy link
Member

Choose a reason for hiding this comment

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

I think this is ok but this requires a comment explaining that this parameter is not found because it is a global PK Parameter (can we actually check if this is one?). It cil;d also be the the quantity was removed somehow (thinking about mobi models imported etc..)


return _populationAnalysisFieldFactory.CreateFor(pkParameter, quantity.QuantityType, quantityDisplayPath);
}
Expand Down
Loading