diff --git a/src/PKSim.Assets.Images/PKSim.Assets.Images.csproj b/src/PKSim.Assets.Images/PKSim.Assets.Images.csproj index 90ff11eec..dd2e5db54 100644 --- a/src/PKSim.Assets.Images/PKSim.Assets.Images.csproj +++ b/src/PKSim.Assets.Images/PKSim.Assets.Images.csproj @@ -26,10 +26,8 @@ - - - - + + diff --git a/src/PKSim.Assets/PKSim.Assets.csproj b/src/PKSim.Assets/PKSim.Assets.csproj index b53049c6d..96be4a81b 100644 --- a/src/PKSim.Assets/PKSim.Assets.csproj +++ b/src/PKSim.Assets/PKSim.Assets.csproj @@ -26,10 +26,8 @@ - - - - + + diff --git a/src/PKSim.Assets/PKSimConstants.cs b/src/PKSim.Assets/PKSimConstants.cs index 3d5a1dade..2c7a7dd51 100644 --- a/src/PKSim.Assets/PKSimConstants.cs +++ b/src/PKSim.Assets/PKSimConstants.cs @@ -906,6 +906,9 @@ public static string MapToSnapshotNotSupportedWithoutContext(string snapshotType public static string CannotFindSimulationInSnapshot(string simulationName, string project) => CannotFindBuildingBlockInSnapshot(ObjectTypes.Simulation, simulationName, project); + public static string SimulationUsedInPlotsAreNotExported(IReadOnlyList simulationNames, string project) + => $"{ObjectTypes.Simulation.PluralizeIf(simulationNames)} {simulationNames.ToString(", ", "'")} used in plots {"is".PluralizeIf(simulationNames)} not found in the list of exported simulations for {ObjectTypes.Project} {project}"; + public static string CannotFindSimulationParameterInSnapshot(string parameterPath, string simulationName, string project) => $"Could not find {ObjectTypes.Parameter} with path '{parameterPath}' in {ObjectTypes.Simulation} '{simulationName}' defined in snapshot {project}."; diff --git a/src/PKSim.BatchTool/PKSim.BatchTool.csproj b/src/PKSim.BatchTool/PKSim.BatchTool.csproj index 02d124a65..c9e5a53b6 100644 --- a/src/PKSim.BatchTool/PKSim.BatchTool.csproj +++ b/src/PKSim.BatchTool/PKSim.BatchTool.csproj @@ -63,8 +63,7 @@ - - + diff --git a/src/PKSim.CLI.Core/PKSim.CLI.Core.csproj b/src/PKSim.CLI.Core/PKSim.CLI.Core.csproj index 2265c46fe..9b5aaaced 100644 --- a/src/PKSim.CLI.Core/PKSim.CLI.Core.csproj +++ b/src/PKSim.CLI.Core/PKSim.CLI.Core.csproj @@ -28,8 +28,7 @@ - - + diff --git a/src/PKSim.CLI.Core/RunOptions/QualificationRunOptions.cs b/src/PKSim.CLI.Core/RunOptions/QualificationRunOptions.cs index 483256110..84d896239 100644 --- a/src/PKSim.CLI.Core/RunOptions/QualificationRunOptions.cs +++ b/src/PKSim.CLI.Core/RunOptions/QualificationRunOptions.cs @@ -16,5 +16,10 @@ public class QualificationRunOptions /// Should simulation be performed as part of the run? /// public bool Run { get; set; } + + /// + /// Specifies if project files (snapshot and PK-Sim project file should be exported) + /// + public bool ExportProjectFiles { get; set; } } } \ No newline at end of file diff --git a/src/PKSim.CLI.Core/Services/QualificationRunner.cs b/src/PKSim.CLI.Core/Services/QualificationRunner.cs index 1e625dda6..872aeabdb 100644 --- a/src/PKSim.CLI.Core/Services/QualificationRunner.cs +++ b/src/PKSim.CLI.Core/Services/QualificationRunner.cs @@ -102,7 +102,9 @@ public async Task RunBatchAsync(QualificationRunOptions runOptions) { OutputFolder = projectOutputFolder, //We run the output, this is for the old matlab implementation where we need xml. Otherwise, we only need pkml export - ExportMode = runOptions.Run ? SimulationExportMode.Xml | SimulationExportMode.Csv : SimulationExportMode.Pkml + ExportMode = runOptions.Run ? SimulationExportMode.Xml | SimulationExportMode.Csv : SimulationExportMode.Pkml, + + Simulations = config.Simulations }; //Using absolute path for simulation folder. We need them to be relative @@ -124,13 +126,16 @@ public async Task RunBatchAsync(QualificationRunOptions runOptions) await _jsonSerializer.Serialize(mapping, config.MappingFile); _logger.AddDebug($"Project mapping for '{project.Name}' exported to '{config.MappingFile}'", project.Name); - var projectFile = Path.Combine(config.TempFolder, $"{project.Name}{CoreConstants.Filter.PROJECT_EXTENSION}"); - _workspacePersistor.SaveSession(_workspace, projectFile); - _logger.AddDebug($"Project saved to '{projectFile}'", project.Name); + if (runOptions.ExportProjectFiles) + { + var projectFile = Path.Combine(config.TempFolder, $"{project.Name}{CoreConstants.Filter.PROJECT_EXTENSION}"); + _workspacePersistor.SaveSession(_workspace, projectFile); + _logger.AddDebug($"Project saved to '{projectFile}'", project.Name); - var snapshotFile = Path.Combine(config.TempFolder, $"{project.Name}{Constants.Filter.JSON_EXTENSION}"); - await _snapshotTask.ExportModelToSnapshotAsync(project, snapshotFile); - _logger.AddDebug($"Project snapshot saved to '{snapshotFile}'", project.Name); + var snapshotFile = Path.Combine(config.TempFolder, $"{project.Name}{Constants.Filter.JSON_EXTENSION}"); + await _snapshotTask.ExportModelToSnapshotAsync(project, snapshotFile); + _logger.AddDebug($"Project snapshot saved to '{snapshotFile}'", project.Name); + } var end = DateTime.UtcNow; var timeSpent = end - begin; @@ -140,7 +145,15 @@ public async Task RunBatchAsync(QualificationRunOptions runOptions) private PlotMapping[] retrievePlotDefinitionsFrom(Project snapshotProject, QualifcationConfiguration configuration) { var plotMappings = configuration.SimulationPlots?.SelectMany(x => retrievePlotDefinitionsForSimulation(x, snapshotProject)); - return plotMappings?.ToArray() ?? Array.Empty(); + var plotMappingsArray = plotMappings?.ToArray() ?? Array.Empty(); + var exportedSimulations = configuration.Simulations?.ToArray() ?? Array.Empty(); + var unmappedSimulations = plotMappingsArray.Select(x => x.Simulation).Distinct().Where(x => !exportedSimulations.Contains(x)).ToList(); + + //All simulations referenced in the the plot mapping are also exported. We are good + if (!unmappedSimulations.Any()) + return plotMappingsArray; + + throw new QualificationRunException(SimulationUsedInPlotsAreNotExported(unmappedSimulations, snapshotProject.Name)); } private void validateInputs(Project snapshotProject, QualifcationConfiguration configuration) diff --git a/src/PKSim.CLI/Commands/QualificationRunCommand.cs b/src/PKSim.CLI/Commands/QualificationRunCommand.cs index caf6b2905..d2b77104e 100644 --- a/src/PKSim.CLI/Commands/QualificationRunCommand.cs +++ b/src/PKSim.CLI/Commands/QualificationRunCommand.cs @@ -19,13 +19,17 @@ public class QualificationRunCommand : CLICommand [Option('r', "run", Required = false, HelpText = "Should the qualification runner also run the simulation or simply export the qualification report for further processing. Default is false")] public bool Run { get; set; } = false; + [Option('e', "exp", Required = false, HelpText = "Should the qualification runner also export the project files (snapshot and PK-Sim project file). Default is false")] + public bool ExportProjectFiles { get; set; } = false; + public override QualificationRunOptions ToRunOptions() { return new QualificationRunOptions { ConfigurationFile = ConfigurationFile, Validate = Validate, - Run = Run + Run = Run, + ExportProjectFiles = ExportProjectFiles }; } @@ -35,7 +39,8 @@ public override string ToString() LogDefaultOptions(sb); sb.AppendLine($"Validate: {Validate}"); sb.AppendLine($"Configuration file: {ConfigurationFile}"); - sb.AppendLine($"Run Simulations: {Run}"); + sb.AppendLine($"Run simulations: {Run}"); + sb.AppendLine($"Export project files: {ExportProjectFiles}"); return sb.ToString(); } } diff --git a/src/PKSim.CLI/PKSim.CLI.csproj b/src/PKSim.CLI/PKSim.CLI.csproj index e645e56b9..77cc6de7f 100644 --- a/src/PKSim.CLI/PKSim.CLI.csproj +++ b/src/PKSim.CLI/PKSim.CLI.csproj @@ -61,10 +61,8 @@ - - - - + + diff --git a/src/PKSim.Core/PKSim.Core.csproj b/src/PKSim.Core/PKSim.Core.csproj index 7ad2d6955..06d878d5b 100644 --- a/src/PKSim.Core/PKSim.Core.csproj +++ b/src/PKSim.Core/PKSim.Core.csproj @@ -30,14 +30,10 @@ - - - - - - - - + + + + diff --git a/src/PKSim.Infrastructure/PKSim.Infrastructure.csproj b/src/PKSim.Infrastructure/PKSim.Infrastructure.csproj index f8d0940f3..9a559b26a 100644 --- a/src/PKSim.Infrastructure/PKSim.Infrastructure.csproj +++ b/src/PKSim.Infrastructure/PKSim.Infrastructure.csproj @@ -41,22 +41,14 @@ - - - - - - - - - - - - - - - - + + + + + + + + diff --git a/src/PKSim.Infrastructure/Services/ImportObservedDataTask.cs b/src/PKSim.Infrastructure/Services/ImportObservedDataTask.cs index 07d580b90..96fb87d0b 100644 --- a/src/PKSim.Infrastructure/Services/ImportObservedDataTask.cs +++ b/src/PKSim.Infrastructure/Services/ImportObservedDataTask.cs @@ -306,13 +306,13 @@ public IEnumerable PredefinedValuesFor(string name) return Enumerable.Empty(); } - public IReadOnlyList DefaultMetaDataCategories => CoreConstants.ObservedData.DefaultProperties; + public IReadOnlyList DefaultMetaDataCategories { get; } = CoreConstants.ObservedData.DefaultProperties; - public IReadOnlyList ReadOnlyMetaDataCategories => new List { }; + public IReadOnlyList ReadOnlyMetaDataCategories { get; } = new List { }; + + public bool MolWeightAlwaysEditable { get; } = false; - public bool MolWeightEditable => false; - - public bool MolWeightVisible => true; + public bool MolWeightVisible { get; }= true; private IEnumerable predefinedGenders => predefinedValuesFor(addPredefinedGenderValues); diff --git a/src/PKSim.Matlab/PKSim.Matlab.csproj b/src/PKSim.Matlab/PKSim.Matlab.csproj index ac39f4af9..db0390e73 100644 --- a/src/PKSim.Matlab/PKSim.Matlab.csproj +++ b/src/PKSim.Matlab/PKSim.Matlab.csproj @@ -27,8 +27,7 @@ - - + diff --git a/src/PKSim.Presentation/PKSim.Presentation.csproj b/src/PKSim.Presentation/PKSim.Presentation.csproj index e434a160d..d7726e3e4 100644 --- a/src/PKSim.Presentation/PKSim.Presentation.csproj +++ b/src/PKSim.Presentation/PKSim.Presentation.csproj @@ -29,10 +29,8 @@ - - - - + + diff --git a/src/PKSim.R/PKSim.R.csproj b/src/PKSim.R/PKSim.R.csproj index ba55d079f..34fde684f 100644 --- a/src/PKSim.R/PKSim.R.csproj +++ b/src/PKSim.R/PKSim.R.csproj @@ -50,8 +50,7 @@ - - + diff --git a/src/PKSim.UI/PKSim.UI.csproj b/src/PKSim.UI/PKSim.UI.csproj index 565dbfdff..02ff3ab5b 100644 --- a/src/PKSim.UI/PKSim.UI.csproj +++ b/src/PKSim.UI/PKSim.UI.csproj @@ -51,12 +51,9 @@ - - - - - - + + + diff --git a/src/PKSim/PKSim.csproj b/src/PKSim/PKSim.csproj index 343a7574d..d8ee2c083 100644 --- a/src/PKSim/PKSim.csproj +++ b/src/PKSim/PKSim.csproj @@ -76,15 +76,13 @@ - - + - - + diff --git a/tests/PKSim.Matlab.Tests/PKSim.Matlab.Tests.csproj b/tests/PKSim.Matlab.Tests/PKSim.Matlab.Tests.csproj index a886c0dfa..5d3be46c9 100644 --- a/tests/PKSim.Matlab.Tests/PKSim.Matlab.Tests.csproj +++ b/tests/PKSim.Matlab.Tests/PKSim.Matlab.Tests.csproj @@ -23,8 +23,7 @@ - - + diff --git a/tests/PKSim.R.Tests/PKSim.R.Tests.csproj b/tests/PKSim.R.Tests/PKSim.R.Tests.csproj index 1a9945a01..679927edc 100644 --- a/tests/PKSim.R.Tests/PKSim.R.Tests.csproj +++ b/tests/PKSim.R.Tests/PKSim.R.Tests.csproj @@ -23,8 +23,7 @@ - - + diff --git a/tests/PKSim.Tests/CLI/QualificationRunnerSpecs.cs b/tests/PKSim.Tests/CLI/QualificationRunnerSpecs.cs index f5c2d13b6..15f6e3591 100644 --- a/tests/PKSim.Tests/CLI/QualificationRunnerSpecs.cs +++ b/tests/PKSim.Tests/CLI/QualificationRunnerSpecs.cs @@ -18,7 +18,6 @@ using PKSim.Core.Services; using PKSim.Core.Snapshots; using PKSim.Core.Snapshots.Services; -using PKSim.Presentation.Core; using DataRepository = OSPSuite.Core.Domain.Data.DataRepository; using Individual = PKSim.Core.Snapshots.Individual; using Simulation = PKSim.Core.Snapshots.Simulation; @@ -202,7 +201,7 @@ protected override async Task Context() _input = new Input {Project = PROJECT_NAME, Name = _simulationName, SectionId = 2, Type = PKSimBuildingBlockType.Simulation, SectionLevel = 5}; _expectedSimulationPath = Path.Combine(_expectedOutputPath, _simulationName); - _simulationExport = new SimulationMapping { Project = PROJECT_NAME, Simulation = _simulationName, Path = _expectedSimulationPath}; + _simulationExport = new SimulationMapping {Project = PROJECT_NAME, Simulation = _simulationName, Path = _expectedSimulationPath}; _simulationExports = new[] {_simulationExport}; A.CallTo(() => _exportSimulationRunner.ExportSimulationsIn(_project, A._)) .Invokes(x => _exportOptions = x.GetArgument(1)) @@ -221,6 +220,7 @@ protected override async Task Context() _project.AddBuildingBlock(_individualSimulation); _qualificationConfiguration.Inputs = new[] {_input}; + _qualificationConfiguration.Simulations = new[] {_simulationName,}; _runOptions.Run = true; } @@ -254,6 +254,12 @@ public void should_load_the_project_from_snapshot_and_export_its_simulations_to_ _exportOptions.ExportMode.ShouldBeEqualTo(SimulationExportMode.Csv | SimulationExportMode.Xml); } + [Observation] + public void should_only_export_the_simulation_required_for_the_qualification() + { + _exportOptions.Simulations.ShouldBeEqualTo(_qualificationConfiguration.Simulations); + } + [Observation] public void should_export_the_mapping_to_the_specified_mapping_file() { @@ -685,7 +691,7 @@ protected override async Task Context() }; _projectSnapshot.Simulations = new[] {simulation}; _qualificationConfiguration.SimulationPlots = new[] {_simulationPlot}; - + _qualificationConfiguration.Simulations = new[] {simulation.Name}; A.CallTo(() => _jsonSerializer.Serialize(A._, _qualificationConfiguration.MappingFile)) .Invokes(x => _mapping = x.GetArgument(0)); } @@ -720,6 +726,35 @@ public void should_create_an_empty_array_for_inputs_if_no_input_were_exported() } } + public class When_running_the_qualification_runner_with_a_configuration_defining_charts_for_a_simulation_that_is_not_exported : concern_for_QualificationRunnerWithValidConfiguration + { + private SimulationPlot _simulationPlot; + private CurveChart _curveChart; + + protected override async Task Context() + { + await base.Context(); + var simulation = new Simulation().WithName("Sim"); + + + _curveChart = new CurveChart(); + simulation.IndividualAnalyses = new[] {_curveChart}; + _simulationPlot = new SimulationPlot + { + SectionId = 2, + Simulation = simulation.Name + }; + _projectSnapshot.Simulations = new[] {simulation}; + _qualificationConfiguration.SimulationPlots = new[] {_simulationPlot}; + } + + [Observation] + public void should_throw_an_exception() + { + The.Action(() => sut.RunBatchAsync(_runOptions)).ShouldThrowAn(); + } + } + public class When_running_the_qualification_runner_with_a_configuration_without_any_mapping_created : concern_for_QualificationRunnerWithValidConfiguration { private QualificationMapping _mapping; diff --git a/tests/PKSim.Tests/PKSim.Tests.csproj b/tests/PKSim.Tests/PKSim.Tests.csproj index d60b963a3..536cb75b5 100644 --- a/tests/PKSim.Tests/PKSim.Tests.csproj +++ b/tests/PKSim.Tests/PKSim.Tests.csproj @@ -21,8 +21,7 @@ - - + diff --git a/tests/PKSim.UI.Starter/PKSim.UI.Starter.csproj b/tests/PKSim.UI.Starter/PKSim.UI.Starter.csproj index e016e03f9..b663ee8a0 100644 --- a/tests/PKSim.UI.Starter/PKSim.UI.Starter.csproj +++ b/tests/PKSim.UI.Starter/PKSim.UI.Starter.csproj @@ -56,15 +56,13 @@ - - + - - + diff --git a/tests/PKSim.UI.Tests/PKSim.UI.Tests.csproj b/tests/PKSim.UI.Tests/PKSim.UI.Tests.csproj index 86a038139..01556d317 100644 --- a/tests/PKSim.UI.Tests/PKSim.UI.Tests.csproj +++ b/tests/PKSim.UI.Tests/PKSim.UI.Tests.csproj @@ -18,10 +18,8 @@ - - - - + +