From da596ba5df9a0da221ba20991b9d9b39ecc9275e Mon Sep 17 00:00:00 2001 From: PaulJonasJost Date: Sun, 31 Mar 2024 20:55:47 -0600 Subject: [PATCH 1/6] Added deepcpy functionality and small test. --- pypesto/objective/roadrunner/road_runner.py | 21 ++++++++++++++ test/base/test_roadrunner.py | 32 ++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/pypesto/objective/roadrunner/road_runner.py b/pypesto/objective/roadrunner/road_runner.py index c711944e4..d2e28a5f8 100644 --- a/pypesto/objective/roadrunner/road_runner.py +++ b/pypesto/objective/roadrunner/road_runner.py @@ -2,6 +2,7 @@ Currently does not support sensitivities. """ +import copy from collections import OrderedDict from typing import Optional, Sequence, Tuple, Union @@ -69,6 +70,26 @@ def __init__( self.solver_options = solver_options super().__init__(x_names=x_names) + def __deepcopy__( + self, memodict: Optional[dict] = None + ) -> "RoadRunnerObjective": + """Deepcopy function for RoadRunner objective. + + Needed for e.g. profiling. + """ + import roadrunner + + other_dict = {} + + for key in {"edatas", "parameter_mapping", "petab_problem"}: + other_dict[key] = copy.deepcopy(self.__dict__[key]) + other_dict["x_names"] = self._x_names + other_rr = roadrunner.RoadRunner() + state = self.roadrunner_instance.saveStateS() + other_rr.loadStateS(state=state) + + return RoadRunnerObjective(rr=other_rr, **other_dict) + def get_config(self) -> dict: """Return basic information of the objective configuration.""" info = super().get_config() diff --git a/test/base/test_roadrunner.py b/test/base/test_roadrunner.py index 43fd3cd16..71e2a431c 100644 --- a/test/base/test_roadrunner.py +++ b/test/base/test_roadrunner.py @@ -1,7 +1,9 @@ """Test the roadrunner interface.""" - +import copy import logging +import os +import benchmark_models_petab as models import petab import petabtests import pytest @@ -104,3 +106,31 @@ def _execute_case_rr(case, model_type, version): ) logger.info(f"Case {version}/{model_type}/{case} passed.") + + +def test_deepcopy(): + "Test that deepcopy works as intended" + model_name = "Boehm_JProteomeRes2014" + petab_problem = petab.Problem.from_yaml( + os.path.join(models.MODELS_DIR, model_name, model_name + ".yaml") + ) + petab_problem.model_name = model_name + importer = objective_rr.PetabImporterRR(petab_problem) + problem_parameters = petab_problem.x_nominal_scaled + + obj = importer.create_objective() + + copied_objective = copy.deepcopy(obj) + + assert obj(problem_parameters) == copied_objective(problem_parameters) + + # !!not adviced, only done here for testing purposes!! + obj.roadrunner_instance.removeParameter( + "pSTAT5A_rel", forceRegenerate=False + ) + obj.roadrunner_instance.addParameter("pSTAT5A_rel", 0.0, False) + obj.roadrunner_instance.addAssignmentRule( + "pSTAT5A_rel", "(100 * pApB + 200 * pApA * specC17)" + ) + + assert obj(problem_parameters) != copied_objective(problem_parameters) From 60b126dcda726ec48be1bb220605615416752928 Mon Sep 17 00:00:00 2001 From: PaulJonasJost Date: Tue, 2 Apr 2024 11:20:36 +0200 Subject: [PATCH 2/6] Better test and better deepcopy --- pypesto/objective/roadrunner/road_runner.py | 10 +++++----- test/base/test_roadrunner.py | 8 +++++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/pypesto/objective/roadrunner/road_runner.py b/pypesto/objective/roadrunner/road_runner.py index d2e28a5f8..447a5efd4 100644 --- a/pypesto/objective/roadrunner/road_runner.py +++ b/pypesto/objective/roadrunner/road_runner.py @@ -79,16 +79,16 @@ def __deepcopy__( """ import roadrunner - other_dict = {} + other = self.__class__.__new__(self.__class__) - for key in {"edatas", "parameter_mapping", "petab_problem"}: - other_dict[key] = copy.deepcopy(self.__dict__[key]) - other_dict["x_names"] = self._x_names + for key in set(self.__dict__.keys()) - {"roadrunner_instance"}: + other.__dict__[key] = copy.deepcopy(self.__dict__[key]) other_rr = roadrunner.RoadRunner() state = self.roadrunner_instance.saveStateS() other_rr.loadStateS(state=state) + other.roadrunner_instance = other_rr - return RoadRunnerObjective(rr=other_rr, **other_dict) + return other def get_config(self) -> dict: """Return basic information of the objective configuration.""" diff --git a/test/base/test_roadrunner.py b/test/base/test_roadrunner.py index 71e2a431c..40f79d1ed 100644 --- a/test/base/test_roadrunner.py +++ b/test/base/test_roadrunner.py @@ -116,11 +116,13 @@ def test_deepcopy(): ) petab_problem.model_name = model_name importer = objective_rr.PetabImporterRR(petab_problem) - problem_parameters = petab_problem.x_nominal_scaled + problem_parameters = petab_problem.x_nominal_free_scaled - obj = importer.create_objective() + problem = importer.create_problem() + obj = problem.objective - copied_objective = copy.deepcopy(obj) + problem_copied = copy.deepcopy(problem) + copied_objective = problem_copied.objective assert obj(problem_parameters) == copied_objective(problem_parameters) From 8908a3c823408b2924e4c5ab5422fcaf741529b3 Mon Sep 17 00:00:00 2001 From: Paul Jonas Jost <70631928+PaulJonasJost@users.noreply.github.com> Date: Wed, 3 Apr 2024 09:52:53 +0200 Subject: [PATCH 3/6] Update pypesto/objective/roadrunner/road_runner.py Co-authored-by: Daniel Weindl --- pypesto/objective/roadrunner/road_runner.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pypesto/objective/roadrunner/road_runner.py b/pypesto/objective/roadrunner/road_runner.py index 447a5efd4..0fadeca2b 100644 --- a/pypesto/objective/roadrunner/road_runner.py +++ b/pypesto/objective/roadrunner/road_runner.py @@ -73,10 +73,7 @@ def __init__( def __deepcopy__( self, memodict: Optional[dict] = None ) -> "RoadRunnerObjective": - """Deepcopy function for RoadRunner objective. - - Needed for e.g. profiling. - """ + """Deepcopy function for RoadRunner objective.""" import roadrunner other = self.__class__.__new__(self.__class__) From 55a94ea19344b759190ba54c662859e351e1ef6d Mon Sep 17 00:00:00 2001 From: PaulJonasJost Date: Fri, 5 Apr 2024 11:09:33 +0200 Subject: [PATCH 4/6] Removed deepcopy from base function as it should be similar to defaultbehaviour. --- pypesto/objective/base.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pypesto/objective/base.py b/pypesto/objective/base.py index 0f9cc982a..e5212b31c 100644 --- a/pypesto/objective/base.py +++ b/pypesto/objective/base.py @@ -56,13 +56,6 @@ def __init__( self.pre_post_processor = PrePostProcessor() self.history = NoHistory() - def __deepcopy__(self, memodict=None) -> "ObjectiveBase": - """Create deepcopy of objective object.""" - other = type(self)() # maintain type for derived classes - for attr, val in self.__dict__.items(): - other.__dict__[attr] = copy.deepcopy(val) - return other - # The following has_ properties can be used to find out what values # the objective supports. @property From 3fe81dc36ea424f08dcbd51b5b994bace0fd181b Mon Sep 17 00:00:00 2001 From: PaulJonasJost Date: Fri, 5 Apr 2024 11:25:34 +0200 Subject: [PATCH 5/6] Also removed deepcopy functionality. --- pypesto/objective/roadrunner/road_runner.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/pypesto/objective/roadrunner/road_runner.py b/pypesto/objective/roadrunner/road_runner.py index 2efdab96e..98a9a9e7e 100644 --- a/pypesto/objective/roadrunner/road_runner.py +++ b/pypesto/objective/roadrunner/road_runner.py @@ -2,7 +2,6 @@ Currently does not support sensitivities. """ -import copy from collections import OrderedDict from collections.abc import Sequence from typing import Optional, Union @@ -71,23 +70,6 @@ def __init__( self.solver_options = solver_options super().__init__(x_names=x_names) - def __deepcopy__( - self, memodict: Optional[dict] = None - ) -> "RoadRunnerObjective": - """Deepcopy function for RoadRunner objective.""" - import roadrunner - - other = self.__class__.__new__(self.__class__) - - for key in set(self.__dict__.keys()) - {"roadrunner_instance"}: - other.__dict__[key] = copy.deepcopy(self.__dict__[key]) - other_rr = roadrunner.RoadRunner() - state = self.roadrunner_instance.saveStateS() - other_rr.loadStateS(state=state) - other.roadrunner_instance = other_rr - - return other - def get_config(self) -> dict: """Return basic information of the objective configuration.""" info = super().get_config() From 219596df5142fca513df3068f885fcb23681bd0d Mon Sep 17 00:00:00 2001 From: Paul Jonas Jost <70631928+PaulJonasJost@users.noreply.github.com> Date: Fri, 5 Apr 2024 11:31:57 +0200 Subject: [PATCH 6/6] Update test/base/test_roadrunner.py Co-authored-by: Daniel Weindl --- test/base/test_roadrunner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/base/test_roadrunner.py b/test/base/test_roadrunner.py index 40f79d1ed..bbff88ff7 100644 --- a/test/base/test_roadrunner.py +++ b/test/base/test_roadrunner.py @@ -109,7 +109,7 @@ def _execute_case_rr(case, model_type, version): def test_deepcopy(): - "Test that deepcopy works as intended" + """Test that deepcopy works as intended""" model_name = "Boehm_JProteomeRes2014" petab_problem = petab.Problem.from_yaml( os.path.join(models.MODELS_DIR, model_name, model_name + ".yaml")