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 #2439 Misleading info in global POP PK Analysis if no parameter… #2459

Merged
merged 2 commits into from
Dec 7, 2022
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: 5 additions & 3 deletions src/PKSim.Core/Model/SchemaItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@ public string TargetOrgan

public bool NeedsFormulation => ApplicationType.NeedsFormulation;

public bool IsOral => ApplicationType==ApplicationTypes.Oral;
public bool IsOral => ApplicationType == ApplicationTypes.Oral;

public bool IsUserDefined => ApplicationType == ApplicationTypes.UserDefined;

public bool IsIV => ApplicationType == ApplicationTypes.Intravenous || ApplicationType == ApplicationTypes.IntravenousBolus;

public bool IsUserDefined => ApplicationType==ApplicationTypes.UserDefined;

public virtual IParameter StartTime => this.Parameter(Constants.Parameters.START_TIME);

public virtual IParameter Dose => this.Parameter(CoreConstants.Parameters.INPUT_DOSE);
Expand Down
43 changes: 20 additions & 23 deletions src/PKSim.Core/Services/PKAnalysesTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@
using static PKSim.Core.CoreConstants.PKAnalysis;
using static PKSim.Core.CoreConstants.Species;
using static PKSim.Core.CoreConstants.Units;
using Compound = PKSim.Core.Model.Compound;
using IParameterFactory = PKSim.Core.Model.IParameterFactory;
using PKAnalysis = PKSim.Core.Model.PKAnalysis;

namespace PKSim.Core.Services
{
Expand Down Expand Up @@ -110,7 +108,7 @@ public PKAnalysesTask(ILazyLoadTask lazyLoadTask,
IStatisticalDataCalculator statisticalDataCalculator,
IRepresentationInfoRepository representationInfoRepository,
IParameterFactory parameterFactory, IProtocolToSchemaItemsMapper protocolToSchemaItemsMapper, IProtocolFactory protocolFactory,
IGlobalPKAnalysisRunner globalPKAnalysisRunner, IVSSCalculator vssCalculator, IInteractionTask interactionTask, ICloner cloner, IEntityPathResolver entityPathResolver) :
IGlobalPKAnalysisRunner globalPKAnalysisRunner, IVSSCalculator vssCalculator, IInteractionTask interactionTask, ICloner cloner, IEntityPathResolver entityPathResolver) :
base(lazyLoadTask, pkValuesCalculator, pkParameterRepository, pkCalculationOptionsFactory)
{
_lazyLoadTask = lazyLoadTask;
Expand Down Expand Up @@ -145,10 +143,7 @@ public PopulationSimulationPKAnalyses CalculateFor(PopulationSimulation populati
{
var globalPKAnalysesForIndividuals = new Cache<int, GlobalPKAnalysis>();
var analyses = base.CalculateFor(populationSimulation, populationSimulation.Results,
individualId =>
{
updateBodyWeightForIndividual(bodyWeightParameter, allBodyWeights, individualId);
},
individualId => { updateBodyWeightForIndividual(bodyWeightParameter, allBodyWeights, individualId); },
(individualId, options, compoundName) =>
{
var globalPKAnalysis = globalPkAnalysisForIndividual(globalPKAnalysesForIndividuals, individualId);
Expand Down Expand Up @@ -234,6 +229,7 @@ private static CompoundPKContext createCompoundPKContext(Compound compound, Indi
compoundPK.AddDDIAucInf(individualId, individualSimulation.AucDDI[compound.Name]);
compoundPK.AddDDICMax(individualId, individualSimulation.CMaxDDI[compound.Name]);
}

return compoundPKContext;
}

Expand All @@ -247,7 +243,7 @@ private Container createCompoundContainer(PopulationSimulation populationSimulat
var compoundContainer = new Container().WithName(compoundName);
populationSimulation.PKAnalyses.AllPKParametersFor(compoundName).Each(quantityPKParameter =>
{
double? defaultValue = new SortedFloatArray(quantityPKParameter.ValuesAsArray, alreadySorted:false).Median();
double? defaultValue = new SortedFloatArray(quantityPKParameter.ValuesAsArray, alreadySorted: false).Median();
if (double.IsNaN(defaultValue.Value))
defaultValue = null;

Expand Down Expand Up @@ -319,7 +315,7 @@ private IContainer calculateGlobalPKAnalysisFor(Simulation simulation, Compound
var vssPlasmaOverF = createParameter(VssPlasmaOverF, bloodPlasmaPK[Vss], VolumePerBodyWeight);
var vdPlasma = createParameter(VdPlasma, bloodPlasmaPK[Vd], VolumePerBodyWeight);
var vdPlasmaOverF = createParameter(VdPlasmaOverF, bloodPlasmaPK[Vd], VolumePerBodyWeight);
if(simulation is IndividualSimulation)
if (simulation is IndividualSimulation)
vssPhysChem = createParameter(VssPhysChem, calculateVSSPhysChemFor(simulation, compoundName), VolumePerBodyWeight);

var totalPlasmaCL = createParameter(TotalPlasmaCL, bloodPlasmaPK[PKParameters.CL], FlowPerWeight);
Expand All @@ -346,7 +342,7 @@ private IContainer calculateGlobalPKAnalysisFor(Simulation simulation, Compound
if (isIntravenous(schemaItem))
{
container.AddChildren(vssPlasma, vdPlasma, totalPlasmaCL);
if(vssPhysChem != null)
if (vssPhysChem != null)
container.Add(vssPhysChem);

return container;
Expand Down Expand Up @@ -530,9 +526,8 @@ public void CalculateBioavailabilityFor(Simulation simulation, string compoundNa
// We know this is a valid cast because it is cloned from simulation
var populationSimulation = simulation.DowncastTo<PopulationSimulation>();
CalculateFor(ivPopulationSimulation, ivCompoundPKContext);
var contextForPopulationSimulation = createContextForPopulationSimulation(ivCompoundPKContext, mapFromBioavailabilityCompoundPK, compoundName, populationSimulation, new []{Bioavailability});
var contextForPopulationSimulation = createContextForPopulationSimulation(ivCompoundPKContext, mapFromBioavailabilityCompoundPK, compoundName, populationSimulation, new[] { Bioavailability });
populationSimulation.PKAnalyses = CalculateFor(populationSimulation, contextForPopulationSimulation);

}
else if (ivSimulation is IndividualSimulation ivIndividualSimulation)
{
Expand Down Expand Up @@ -648,20 +643,20 @@ private bool isMultipleOral(Simulation simulation, Compound compound)
return allSchemaItems.Any() && allSchemaItems.All(isOral);
}

private static bool isOral(ISchemaItem schemaItem)
private static bool isOral(SchemaItem schemaItem)
Copy link
Member

Choose a reason for hiding this comment

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

Why this chnage from Interface to not interface?

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 implemented a bool property on SchemaItem that matches 'IsOral' and 'IsUserDefined' (IsIV) and like those ones, I did not pull them up to interface. I'm pretty sure all those conversions are local in this class.

Copy link
Member

Choose a reason for hiding this comment

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

I am wondering if we need the ISchemaItem at all. Another day

{
if (schemaItem == null)
return false;

return schemaItem.ApplicationType == ApplicationTypes.Oral;
}

private static bool isIntravenous(ISchemaItem schemaItem)
private static bool isIntravenous(SchemaItem schemaItem)
{
if (schemaItem == null)
return false;

return schemaItem.ApplicationType == ApplicationTypes.Intravenous || schemaItem.ApplicationType == ApplicationTypes.IntravenousBolus;
return schemaItem.IsIV;
}

private ApplicationType applicationTypeFor(Simulation simulation, Compound compound)
Expand All @@ -673,17 +668,17 @@ private ApplicationType applicationTypeFor(Simulation simulation, Compound compo
return numberOfApplications > 1 ? ApplicationType.Multiple : ApplicationType.Empty;
}

private ISchemaItem singleDosingItem(Simulation simulation, Compound compound)
private SchemaItem singleDosingItem(Simulation simulation, Compound compound)
{
//this may be null for compound created by metabolization process only
return schemaItemsFrom(simulation, compound).FirstOrDefault();
}

private IReadOnlyList<ISchemaItem> schemaItemsFrom(Simulation simulation, Compound compound)
private IReadOnlyList<SchemaItem> schemaItemsFrom(Simulation simulation, Compound compound)
{
var protocol = simulation.CompoundPropertiesFor(compound).ProtocolProperties.Protocol;
if (protocol == null)
return new List<ISchemaItem>();
return new List<SchemaItem>();

return _protocolToSchemaItemsMapper.MapFrom(protocol);
}
Expand Down Expand Up @@ -778,8 +773,8 @@ private IEnumerable<DataColumn> columnsFor(CurveData<TimeProfileXValue, TimeProf
new DataColumn(curveData.Caption, curveData.YAxis.Dimension, baseGrid)
{
Values = curveData.YValues.Select(y => y.Y).ToList(),
DataInfo = {MolWeight = populationDataCollector.MolWeightFor(curveData.QuantityPath)},
QuantityInfo = {Path = curveData.QuantityPath.ToPathArray()}
DataInfo = { MolWeight = populationDataCollector.MolWeightFor(curveData.QuantityPath) },
QuantityInfo = { Path = curveData.QuantityPath.ToPathArray() }
}
};
}
Expand Down Expand Up @@ -857,11 +852,13 @@ public PKAnalysis CreatePKAnalysisFromValues(PKValues pkValues, Simulation simul
}

/// <summary>
/// Returns the range strings when the <paramref name="text"/> contains 'Range 2.5% to 97.5%' language
/// Returns the range strings when the <paramref name="text" /> contains 'Range 2.5% to 97.5%' language
/// </summary>
/// <param name="text">The text being split</param>
/// <returns>The individual range descriptions as a tuple containing low range and high range.
/// If the string cannot be split on 'Range', returns the original text in both members of the tuple</returns>
/// <returns>
/// The individual range descriptions as a tuple containing low range and high range.
/// If the string cannot be split on 'Range', returns the original text in both members of the tuple
/// </returns>
private (string lowerRange, string upperRange) rangeDescriptions(string text)
{
var splitStrings = text.Split(new[] { "Range" }, StringSplitOptions.None);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using PKSim.Assets;
using OSPSuite.Core.Domain;
using OSPSuite.Core.Domain.UnitSystem;
using OSPSuite.Core.Services;
using OSPSuite.Presentation.Core;
using OSPSuite.Presentation.Presenters;
using OSPSuite.Presentation.Services;
using OSPSuite.Utility.Extensions;
using PKSim.Assets;
using PKSim.Core;
using PKSim.Core.Mappers;
using PKSim.Core.Model;
using PKSim.Core.Repositories;
using PKSim.Core.Services;
using PKSim.Presentation.DTO.Mappers;
using PKSim.Presentation.DTO.Simulations;
using PKSim.Presentation.Views.Simulations;
using OSPSuite.Core.Domain;
using OSPSuite.Core.Domain.UnitSystem;
using OSPSuite.Core.Services;
using OSPSuite.Presentation.Core;
using OSPSuite.Presentation.Presenters;
using OSPSuite.Presentation.Services;

namespace PKSim.Presentation.Presenters.Simulations
{
Expand All @@ -29,6 +30,7 @@ public interface IGlobalPKAnalysisPresenter : IPresenter<IGlobalPKAnalysisView>,
void CalculateDDIRatioFor(string compoundName);
string DisplayNameFor(string parameterName);
bool HasParameters();
bool CanCalculateGlobalPK();
}

public class GlobalPKAnalysisPresenter : AbstractSubPresenter<IGlobalPKAnalysisView, IGlobalPKAnalysisPresenter>, IGlobalPKAnalysisPresenter
Expand All @@ -43,15 +45,17 @@ public class GlobalPKAnalysisPresenter : AbstractSubPresenter<IGlobalPKAnalysisV
private GlobalPKAnalysisDTO _globalPKAnalysisDTO;
private DefaultPresentationSettings _settings;
private readonly IPresentationSettingsTask _presentationSettingsTask;
private readonly IProtocolToSchemaItemsMapper _protocolToSchemaItemsMapper;

public GlobalPKAnalysisPresenter(IGlobalPKAnalysisView view, IPKAnalysesTask pkAnalysesTask,
IGlobalPKAnalysisToGlobalPKAnalysisDTOMapper globalPKAnalysisDTOMapper, IHeavyWorkManager heavyWorkManager, IRepresentationInfoRepository representationInfoRepository, IPresentationSettingsTask presentationSettingsTask) : base(view)
IGlobalPKAnalysisToGlobalPKAnalysisDTOMapper globalPKAnalysisDTOMapper, IHeavyWorkManager heavyWorkManager, IRepresentationInfoRepository representationInfoRepository, IPresentationSettingsTask presentationSettingsTask, IProtocolToSchemaItemsMapper protocolToSchemaItemsMapper) : base(view)
{
_pkAnalysesTask = pkAnalysesTask;
_globalPKAnalysisDTOMapper = globalPKAnalysisDTOMapper;
_heavyWorkManager = heavyWorkManager;
_representationInfoRepository = representationInfoRepository;
_presentationSettingsTask = presentationSettingsTask;
_protocolToSchemaItemsMapper = protocolToSchemaItemsMapper;
_settings = new DefaultPresentationSettings();
}

Expand All @@ -78,7 +82,7 @@ public bool ShouldCalculateDDIRatio(string compoundName, string parameterName)
shouldCalculateGlobalPKParameter(compoundName, parameterName, CoreConstants.PKAnalysis.C_maxRatio);
}

private bool shouldCalculateGlobalPKParameter(string compoundName, string parameterName,string globalPKParameterName)
private bool shouldCalculateGlobalPKParameter(string compoundName, string parameterName, string globalPKParameterName)
{
if (!string.Equals(parameterName, globalPKParameterName))
return false;
Expand Down Expand Up @@ -119,10 +123,7 @@ private void loadPreferredUnitsForPKAnalysis()

private void updateParameterDisplayUnits(string parameterName)
{
GlobalPKAnalysis.PKParameters(parameterName).Each(parameter =>
{
parameter.DisplayUnit = parameter.Dimension.Unit(_settings.GetSetting(parameterName, DisplayUnitFor(parameterName).Name));
});
GlobalPKAnalysis.PKParameters(parameterName).Each(parameter => { parameter.DisplayUnit = parameter.Dimension.Unit(_settings.GetSetting(parameterName, DisplayUnitFor(parameterName).Name)); });
}

private Simulation firstSimulation => _simulations.FirstOrDefault();
Expand Down Expand Up @@ -164,6 +165,18 @@ public bool HasParameters()
return false;
}

public bool CanCalculateGlobalPK()
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 ran resharper to auto-format so there's some noise in this PR. The gist is we need to calculate when a simulation contains only multiple IV applications of all compounds. If there's only single IV, oral, or a mix we want to show the global panel.

Copy link
Member

Choose a reason for hiding this comment

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

it this how it was doen for individual simulation?

Copy link
Member Author

Choose a reason for hiding this comment

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

for individual, the global is calculated on demand, so if it can calculate a global, the presenter just indicates that the datatable has rows and the view should show the panel.

For populations, you might have to re-run if the results are from an older version because the global would not have been calculated, and will not be calculated just because you show it.

{
return firstSimulation.Compounds.Any(compound =>
{
var schemaItems = _protocolToSchemaItemsMapper.MapFrom(firstSimulation.CompoundPropertiesFor(compound).ProtocolProperties.Protocol);
return !isMultipleIV(schemaItems);
});
}

private bool isMultipleIV(IReadOnlyList<SchemaItem> schemaItems) => schemaItems.Count(schemaItem => schemaItem.IsIV) > 1;


public void LoadSettingsForSubject(IWithId subject)
{
_settings = _presentationSettingsTask.PresentationSettingsFor<DefaultPresentationSettings>(this, subject);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
using System.Collections.Generic;
using System.Linq;
using OSPSuite.Core.Chart;
using OSPSuite.Core.Domain;
using OSPSuite.Core.Domain.Data;
using OSPSuite.Core.Domain.PKAnalyses;
using OSPSuite.Presentation.Presenters;
using OSPSuite.Presentation.Services;
using OSPSuite.Utility.Collections;
using OSPSuite.Utility.Extensions;
using PKSim.Core.Extensions;
Expand All @@ -8,12 +14,6 @@
using PKSim.Presentation.DTO.Mappers;
using PKSim.Presentation.Services;
using PKSim.Presentation.Views.Simulations;
using OSPSuite.Core.Chart;
using OSPSuite.Core.Domain;
using OSPSuite.Core.Domain.Data;
using OSPSuite.Core.Domain.PKAnalyses;
using OSPSuite.Presentation.Presenters;
using OSPSuite.Presentation.Services;

namespace PKSim.Presentation.Presenters.Simulations
{
Expand All @@ -30,20 +30,16 @@ public class IndividualPKAnalysisPresenter : PKAnalysisPresenter<IIndividualPKAn
private IReadOnlyList<Simulation> _simulations;
private readonly ICache<DataColumn, Curve> _curveCache;
private List<DataColumn> _allColumns;
private readonly IGlobalPKAnalysisPresenter _globalPKAnalysisPresenter;
private readonly IIndividualPKAnalysisToPKAnalysisDTOMapper _pKAnalysisToDTOMapper;

public IndividualPKAnalysisPresenter(IIndividualPKAnalysisView view, IPKAnalysesTask pkAnalysesTask, IPKAnalysisExportTask exportTask,
IGlobalPKAnalysisPresenter globalPKAnalysisPresenter, IIndividualPKAnalysisToPKAnalysisDTOMapper pKAnalysisToDTOMapper,
IPKParameterRepository pkParameterRepository, IPresentationSettingsTask presentationSettingsTask) : base(view, pkParameterRepository, presentationSettingsTask)
IPKParameterRepository pkParameterRepository, IPresentationSettingsTask presentationSettingsTask) : base(view, pkParameterRepository, presentationSettingsTask, globalPKAnalysisPresenter)
{
_pkAnalysesTask = pkAnalysesTask;
_globalPKAnalysisPresenter = globalPKAnalysisPresenter;
_exportTask = exportTask;
_view.ShowControls = false;
_curveCache = new Cache<DataColumn, Curve>(onMissingKey: x => null);
AddSubPresenters(_globalPKAnalysisPresenter);
_view.AddGlobalPKAnalysisView(_globalPKAnalysisPresenter.View);
_pKAnalysisToDTOMapper = pKAnalysisToDTOMapper;
}

Expand All @@ -61,7 +57,7 @@ public void ShowPKAnalysis(IEnumerable<Simulation> simulations, IEnumerable<Curv
createColumnsWithPKAnalysesFrom(curveList);
_allColumns = _curveCache.Keys.ToList();
_allPKAnalysis = _pkAnalysesTask.CalculateFor(_simulations, _allColumns, globalPKAnalysis).ToList();

_view.GlobalPKVisible = _globalPKAnalysisPresenter.HasParameters();

_view.ShowControls = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
using System.Collections.Generic;
using System.Linq;
using OSPSuite.Utility.Extensions;
using PKSim.Core.Model;
using OSPSuite.Core.Domain;
using OSPSuite.Core.Domain.PKAnalyses;
using OSPSuite.Core.Domain.UnitSystem;
using OSPSuite.Presentation.Core;
using OSPSuite.Presentation.Presenters;
using OSPSuite.Presentation.Services;
using OSPSuite.Presentation.Views;
using OSPSuite.Utility.Extensions;
using PKSim.Core.Model;
using PKSim.Presentation.Views.Simulations;

namespace PKSim.Presentation.Presenters.Simulations
{
Expand All @@ -20,21 +21,25 @@ public interface IPKAnalysisPresenter : IUnitsInColumnPresenter<string>, IPresen
}

public abstract class PKAnalysisPresenter<TView, TPresenter> : AbstractSubPresenter<TView, TPresenter>, IPKAnalysisPresenter
where TView : IView<TPresenter>
where TView : IView<TPresenter>, IPKAnalysisView
where TPresenter : IPresenter
{
private readonly IPKParameterRepository _pkParameterRepository;
private readonly IParameter _undefinedPKParameter;
private DefaultPresentationSettings _settings;
private readonly IPresentationSettingsTask _presentationSettingsTask;
protected IGlobalPKAnalysisPresenter _globalPKAnalysisPresenter;

protected PKAnalysisPresenter(TView view, IPKParameterRepository pkParameterRepository, IPresentationSettingsTask presentationSettingsTask)
protected PKAnalysisPresenter(TView view, IPKParameterRepository pkParameterRepository, IPresentationSettingsTask presentationSettingsTask, IGlobalPKAnalysisPresenter globalPKAnalysisPresenter)
: base(view)
{
_pkParameterRepository = pkParameterRepository;
_presentationSettingsTask = presentationSettingsTask;
_undefinedPKParameter = new PKSimParameter {Dimension = Constants.Dimension.NO_DIMENSION};
_undefinedPKParameter = new PKSimParameter { Dimension = Constants.Dimension.NO_DIMENSION };
_settings = new DefaultPresentationSettings();
_globalPKAnalysisPresenter = globalPKAnalysisPresenter;
AddSubPresenters(_globalPKAnalysisPresenter);
_view.AddGlobalPKAnalysisView(_globalPKAnalysisPresenter.View);
}

public void ChangeUnit(string pkParameterName, Unit newUnit)
Expand Down
Loading