diff --git a/src/PKSim.Core/Chart/ChartData.cs b/src/PKSim.Core/Chart/ChartData.cs index 381e37abe..40d462b91 100644 --- a/src/PKSim.Core/Chart/ChartData.cs +++ b/src/PKSim.Core/Chart/ChartData.cs @@ -5,7 +5,7 @@ namespace PKSim.Core.Chart { - public class ChartData : IComparer> where TX : IXValue where TY : IYValue + public class ChartData : IComparer> where TX : IXValue where TY : IYValue { private readonly IReadOnlyList> _fieldValueComparers; public AxisData Axis { get; private set; } @@ -14,14 +14,10 @@ public class ChartData : IComparer> where TX : IXValue private readonly Cache> _allPanes; public IReadOnlyList XFieldNames { get; private set; } - public IEnumerable> AllXValues - { - get { return _allXValues.All(); } - } + public IEnumerable> AllXValues => _allXValues.All(); - public ChartData(AxisData axis, IReadOnlyList> fieldValueComparers):this(axis, fieldValueComparers,new List(),null) + public ChartData(AxisData axis, IReadOnlyList> fieldValueComparers) : this(axis, fieldValueComparers, new List(), null) { - } public ChartData(AxisData axis, IReadOnlyList> fieldValueComparers, IReadOnlyList xFieldNames, IComparer xValueComparer) @@ -33,10 +29,7 @@ public ChartData(AxisData axis, IReadOnlyList> fieldValueCompa _allPanes = new Cache>(x => x.Id, x => null); } - public ICache> Panes - { - get { return _allPanes; } - } + public ICache> Panes => _allPanes; public int Compare(PaneData x, PaneData y) { @@ -48,7 +41,7 @@ public int Compare(PaneData x, PaneData y) public void CreatePaneOrder() { //without ToList sortedPanes is empty after Clear - var sortedPanes = _allPanes.OrderBy(x => x, this).ToList(); + var sortedPanes = _allPanes.OrderBy(x => x, this).ToList(); _allPanes.Clear(); _allPanes.AddRange(sortedPanes); } @@ -82,7 +75,7 @@ from curve in pane.Curves from xValue in curve.XValues select xValue; - public void AddPane(PaneData pane) + public void AddPane(PaneData pane) { _allPanes.Add(pane); pane.Chart = this; diff --git a/src/PKSim.Core/Mappers/BoxWhiskerChartDataToDataTableMapper.cs b/src/PKSim.Core/Mappers/BoxWhiskerChartDataToDataTableMapper.cs index 8ab7071de..561313a4c 100644 --- a/src/PKSim.Core/Mappers/BoxWhiskerChartDataToDataTableMapper.cs +++ b/src/PKSim.Core/Mappers/BoxWhiskerChartDataToDataTableMapper.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Data; -using PKSim.Core.Chart; using OSPSuite.Utility.Extensions; +using PKSim.Core.Chart; namespace PKSim.Core.Mappers { @@ -33,16 +33,18 @@ protected override IEnumerable AddSpecificChartValues(DataRow row, Curv for (var i = 0; i < curveData.XValues.Count; i++) { var newRow = row.Table.NewRow(); + var yValue = curveData.YValues[i]; newRow.ItemArray = row.ItemArray; newRow[_xValue] = curveData.XValues[i].ToString(curveData.XAxis); - newRow[_lowerWhisker] = ValueForDataTableFor(curveData.YAxis, curveData.YValues[i].LowerWhisker); - newRow[_lowerBox] = ValueForDataTableFor(curveData.YAxis, curveData.YValues[i].LowerBox); - newRow[_median] = ValueForDataTableFor(curveData.YAxis, curveData.YValues[i].Median); - newRow[_upperBox] = ValueForDataTableFor(curveData.YAxis, curveData.YValues[i].UpperBox); - newRow[_upperWhisker] = ValueForDataTableFor(curveData.YAxis, curveData.YValues[i].UpperWhisker); + newRow[_lowerWhisker] = yValueForDataTableFor(curveData, yValue.LowerWhisker); + newRow[_lowerBox] = yValueForDataTableFor(curveData, yValue.LowerBox); + newRow[_median] = yValueForDataTableFor(curveData, yValue.Median); + newRow[_upperBox] = yValueForDataTableFor(curveData, yValue.UpperBox); + newRow[_upperWhisker] = yValueForDataTableFor(curveData, yValue.UpperWhisker); newRow[_variable] = curveData.YAxis.Caption; newRows.Add(newRow); } + return newRows; } } diff --git a/src/PKSim.Core/Mappers/ChartDataToDataTableMapper.cs b/src/PKSim.Core/Mappers/ChartDataToDataTableMapper.cs index 54fe376bc..81409c3ef 100644 --- a/src/PKSim.Core/Mappers/ChartDataToDataTableMapper.cs +++ b/src/PKSim.Core/Mappers/ChartDataToDataTableMapper.cs @@ -2,12 +2,13 @@ using System.Collections.Generic; using System.Data; using System.Linq; +using OSPSuite.Core.Domain; +using OSPSuite.Core.Domain.UnitSystem; using OSPSuite.Utility; using OSPSuite.Utility.Data; using OSPSuite.Utility.Extensions; using PKSim.Core.Chart; -using OSPSuite.Core.Domain; -using OSPSuite.Core.Extensions; +using PKSim.Core.Extensions; namespace PKSim.Core.Mappers { @@ -73,6 +74,7 @@ private DataTable getRawTableDataBasedOn(ChartData chartData, AddPanesToTable(dataTable, pane, exportForPivot); AddObservedDataToTable(dataTable, pane, exportForPivot); } + dataTable.EndLoadData(); return dataTable; @@ -149,21 +151,22 @@ private CurveData firstCurveDefinedIn(ChartData curveData, bool exportForPivot); + protected abstract IEnumerable AddSpecificChartValues(DataRow row, CurveData curveData, bool exportForPivot); - protected virtual IReadOnlyList GetDataFields(CurveData curveData) - { - return new List(); - } + protected virtual IReadOnlyList GetDataFields(CurveData curveData) => new List(); - protected virtual IReadOnlyList GetRowFields(CurveData curveData) - { - return new List(); - } + protected virtual IReadOnlyList GetRowFields(CurveData curveData) => new List(); + + //For x values, we can use the dimension of the x axis right away as it is always the same for all curves + protected object xValueForDataTableFor(CurveData curveData, double value) where TX : IXValue where TY : IYValue => ValueForDataTableFor(curveData.XAxis, curveData.XAxis.Dimension, value); + + //For y values, we need to use the dimension specified for each curve as it may be a merged dimension + protected object yValueForDataTableFor(CurveData curveData, double value) where TX : IXValue where TY : IYValue => ValueForDataTableFor(curveData.YAxis, curveData.YDimension, value); - protected object ValueForDataTableFor(IWithDisplayUnit withDisplayUnit, double value) + protected object ValueForDataTableFor(IWithDisplayUnit objectWithTargetUnit, IDimension valueDimension, double value) { - return double.IsNaN(value) ? DBNull.Value : (object) withDisplayUnit.ConvertToDisplayUnit(value); + return double.IsNaN(value) ? DBNull.Value : (object) objectWithTargetUnit.DisplayValue(value, valueDimension); } } } \ No newline at end of file diff --git a/src/PKSim.Core/Mappers/RangeChartDataToDataTableMapper.cs b/src/PKSim.Core/Mappers/RangeChartDataToDataTableMapper.cs index 2da5aa1dc..18364c303 100644 --- a/src/PKSim.Core/Mappers/RangeChartDataToDataTableMapper.cs +++ b/src/PKSim.Core/Mappers/RangeChartDataToDataTableMapper.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Data; +using OSPSuite.Utility.Extensions; using PKSim.Assets; using PKSim.Core.Chart; -using OSPSuite.Utility.Extensions; namespace PKSim.Core.Mappers { @@ -42,16 +42,20 @@ protected override IEnumerable AddSpecificChartValues(DataRow row, Curv for (var i = 0; i < curveData.XValues.Count; i++) { var newRow = row.Table.NewRow(); + var xValue = curveData.XValues[i]; + var yValue = curveData.YValues[i]; + newRow.ItemArray = row.ItemArray; - newRow[_xMinimumColumn] = ValueForDataTableFor(curveData.XAxis, curveData.XValues[i].Minimum); - newRow[_xValueColumn] = ValueForDataTableFor(curveData.XAxis, curveData.XValues[i].X); - newRow[_xMaximumColumn] = ValueForDataTableFor(curveData.XAxis, curveData.XValues[i].Maximum); - newRow[_xNumberOfIndividualsColumn] = curveData.XValues[i].NumberOfItems; - newRow[_yLowerPercentileColumn] = ValueForDataTableFor(curveData.YAxis, curveData.YValues[i].LowerPercentile); - newRow[_yValueColumn] = ValueForDataTableFor(curveData.YAxis, curveData.YValues[i].Median); - newRow[_yUpperPercentileColumn] = ValueForDataTableFor(curveData.YAxis, curveData.YValues[i].UpperPercentile); + newRow[_xMinimumColumn] = xValueForDataTableFor(curveData, xValue.Minimum); + newRow[_xValueColumn] = xValueForDataTableFor(curveData, xValue.X); + newRow[_xMaximumColumn] = xValueForDataTableFor(curveData, xValue.Maximum); + newRow[_xNumberOfIndividualsColumn] = xValue.NumberOfItems; + newRow[_yLowerPercentileColumn] = yValueForDataTableFor(curveData, yValue.LowerPercentile); + newRow[_yValueColumn] = yValueForDataTableFor(curveData, yValue.Median); + newRow[_yUpperPercentileColumn] = yValueForDataTableFor(curveData, yValue.UpperPercentile); newRows.Add(newRow); } + return newRows; } } diff --git a/src/PKSim.Core/Mappers/ScatterChartDataToDataTableMapper.cs b/src/PKSim.Core/Mappers/ScatterChartDataToDataTableMapper.cs index ab1e37d7f..f09bcb5c2 100644 --- a/src/PKSim.Core/Mappers/ScatterChartDataToDataTableMapper.cs +++ b/src/PKSim.Core/Mappers/ScatterChartDataToDataTableMapper.cs @@ -21,8 +21,8 @@ protected override IEnumerable AddSpecificChartValues(DataRow row, Curv { var newRow = row.Table.NewRow(); newRow.ItemArray = row.ItemArray; - newRow[curveData.XAxis.Caption] = ValueForDataTableFor(curveData.XAxis, curveData.XValues[i].X); - newRow[curveData.YAxis.Caption] = ValueForDataTableFor(curveData.YAxis, curveData.YValues[i].Y); + newRow[curveData.XAxis.Caption] = xValueForDataTableFor(curveData, curveData.XValues[i].X); + newRow[curveData.YAxis.Caption] = yValueForDataTableFor(curveData, curveData.YValues[i].Y); newRows.Add(newRow); } return newRows; diff --git a/src/PKSim.Core/Mappers/TimeProfileChartDataToDataTableMapper.cs b/src/PKSim.Core/Mappers/TimeProfileChartDataToDataTableMapper.cs index 8f3f085af..0e56aa21f 100644 --- a/src/PKSim.Core/Mappers/TimeProfileChartDataToDataTableMapper.cs +++ b/src/PKSim.Core/Mappers/TimeProfileChartDataToDataTableMapper.cs @@ -36,9 +36,7 @@ protected override void AddSpecificChartColumns(DataTable dataTable, CurveData(_yUpperValueColumn); } - private IEnumerable addSpecificChartValues(DataRow row, CurveData curveData, bool exportForPivot) - where TX : TimeProfileXValue - where TY : ITimeProfileYValue + private IEnumerable addSpecificChartValues(DataRow row, CurveData curveData, bool exportForPivot) where TY: ITimeProfileYValue { var newRows = new List(); @@ -46,17 +44,17 @@ private IEnumerable addSpecificChartValues(DataRow row, CurveDa { var newRow = row.Table.NewRow(); newRow.ItemArray = row.ItemArray; - var xValue = ValueForDataTableFor(curveData.XAxis, curveData.XValues[i].X); - + var xValue = xValueForDataTableFor(curveData, curveData.XValues[i].X); + var yValue = curveData.YValues[i]; if (exportForPivot) newRow[_xValueColumn] = xValue.ConvertedTo(); else newRow[_xValueColumn] = xValue; - newRow[_yLowerValueColumn] = ValueForDataTableFor(curveData.YAxis, curveData.YValues[i].LowerValue); - newRow[_yValueColumn] = ValueForDataTableFor(curveData.YAxis, curveData.YValues[i].Y); - newRow[_yUpperValueColumn] = ValueForDataTableFor(curveData.YAxis, curveData.YValues[i].UpperValue); - newRows.Add(newRow); + newRow[_yLowerValueColumn] = yValueForDataTableFor(curveData, yValue.LowerValue); + newRow[_yValueColumn] = yValueForDataTableFor(curveData, yValue.Y); + newRow[_yUpperValueColumn] = yValueForDataTableFor(curveData, yValue.UpperValue); + newRows.Add(newRow); } return newRows; } @@ -68,7 +66,7 @@ protected override void PerformSpecificTransformationOnPivotedTable(DataTable pi return; var column = pivotTable.Columns[_xValueColumn]; - var xValueColumnAsString = string.Format("{0}AsString", _xValueColumn); + var xValueColumnAsString = $"{_xValueColumn}AsString"; column.ColumnName = xValueColumnAsString; //make the column the first column of the pivot table diff --git a/src/PKSim.Presentation/Presenters/PopulationAnalyses/PopulationAnalysisFieldDistributionPresenter.cs b/src/PKSim.Presentation/Presenters/PopulationAnalyses/PopulationAnalysisFieldDistributionPresenter.cs index e1bb273a1..bd3f6c199 100644 --- a/src/PKSim.Presentation/Presenters/PopulationAnalyses/PopulationAnalysisFieldDistributionPresenter.cs +++ b/src/PKSim.Presentation/Presenters/PopulationAnalyses/PopulationAnalysisFieldDistributionPresenter.cs @@ -59,12 +59,12 @@ public void Plot(IPopulationDataCollector populationDataCollector, PopulationAna public void Plot(IPopulationDataCollector populationDataCollector, QuantityPKParameter pkParameter, PopulationAnalysisPKParameterField pkParameterField) { - plotContinousData(populationDataCollector, pkParameter, pkParameterField, x => x.Plot); + plotContinuousData(populationDataCollector, pkParameter, pkParameterField, x => x.Plot); } public void Plot(IPopulationDataCollector populationDataCollector, IParameter parameter, PopulationAnalysisParameterField parameterField) { - plotContinousData(populationDataCollector, parameter, parameterField, x => x.Plot); + plotContinuousData(populationDataCollector, parameter, parameterField, x => x.Plot); } public void Plot(IPopulationDataCollector populationDataCollector, string covariateName) @@ -84,7 +84,7 @@ public void ResetPlot() _populationDistributionPresenter.ResetPlot(); } - private void plotContinousData(IPopulationDataCollector populationDataCollector, TObject objectToPlot, INumericValueField numericValueField, + private void plotContinuousData(IPopulationDataCollector populationDataCollector, TObject objectToPlot, INumericValueField numericValueField, Func> plotFunc) where TObject : class, IWithDimension diff --git a/tests/PKSim.Tests/Core/TimeProfileChartDataToDataTableMapperSpecs.cs b/tests/PKSim.Tests/Core/TimeProfileChartDataToDataTableMapperSpecs.cs index 55bacc978..126cee442 100644 --- a/tests/PKSim.Tests/Core/TimeProfileChartDataToDataTableMapperSpecs.cs +++ b/tests/PKSim.Tests/Core/TimeProfileChartDataToDataTableMapperSpecs.cs @@ -137,18 +137,20 @@ protected override void Context() var pane2 = new PaneData(_yAxis) {Caption = "Female"}; _chartData.AddPane(pane1); _chartData.AddPane(pane2); - var curve1 = new CurveData {Caption = "Liver"}; + var curve1 = new CurveData {Caption = "Liver", YDimension = concDimension }; curve1.Add(new TimeProfileXValue(1), new TimeProfileYValue {Y = 10}); curve1.Add(new TimeProfileXValue(2), new TimeProfileYValue {LowerValue = 20, UpperValue = 30}); pane1.AddCurve(curve1); - var curve2 = new CurveData {Caption = "Kidney"}; + var curve2 = new CurveData {Caption = "Kidney", YDimension = concDimension }; curve2.Add(new TimeProfileXValue(3), new TimeProfileYValue {Y = 40}); pane2.AddCurve(curve2); _observedData = DomainHelperForSpecs.ObservedData(); var displayPathMapper = A.Fake(); var dimensionRepository = A.Fake(); + //we need to make sure we return a real dimension as this will be use to convert the values + A.CallTo(() => dimensionRepository.MergedDimensionFor(_observedData.FirstDataColumn())).Returns(concDimension); var observedDataMapper = new DataRepositoryToObservedCurveDataMapper(displayPathMapper, dimensionRepository); var observedDataCurves = observedDataMapper.MapFrom(_observedData, new ObservedDataCollection()); observedDataCurves.Each(pane1.AddObservedCurve);