diff --git a/pypesto/hierarchical/inner_calculator_collector.py b/pypesto/hierarchical/inner_calculator_collector.py index 0d2fe3f79..07e220538 100644 --- a/pypesto/hierarchical/inner_calculator_collector.py +++ b/pypesto/hierarchical/inner_calculator_collector.py @@ -112,7 +112,6 @@ def __init__( def initialize(self): """Initialize.""" - self.best_fval = np.inf for calculator in self.inner_calculators: calculator.initialize() @@ -125,7 +124,6 @@ def construct_inner_calculators( ): """Construct inner calculators for each data type.""" self.necessary_par_dummy_values = {} - self.best_fval = np.inf if RELATIVE in self.data_types: relative_inner_problem = RelativeInnerProblem.from_petab_amici( @@ -382,9 +380,6 @@ def __call__( parameter_mapping=parameter_mapping, fim_for_hess=fim_for_hess, ) - # only return inner parameters if the objective value improved - if ret[FVAL] > self.best_fval: - ret[INNER_PARAMETERS] = None return filter_return_dict(ret) # get dimension of outer problem @@ -517,16 +512,12 @@ def __call__( RDATAS: rdatas, } - # Add inner parameters to return dict - # only if the objective value improved. - if ret[FVAL] < self.best_fval: - ret[SPLINE_KNOTS] = spline_knots - ret[INNER_PARAMETERS] = ( - interpretable_inner_pars - if len(interpretable_inner_pars) > 0 - else None - ) - self.best_fval = ret[FVAL] + ret[INNER_PARAMETERS] = ( + interpretable_inner_pars + if len(interpretable_inner_pars) > 0 + else None + ) + ret[SPLINE_KNOTS] = spline_knots return filter_return_dict(ret) diff --git a/pypesto/objective/amici/amici.py b/pypesto/objective/amici/amici.py index 90d7f2cac..b424f002d 100644 --- a/pypesto/objective/amici/amici.py +++ b/pypesto/objective/amici/amici.py @@ -10,11 +10,9 @@ from ...C import ( FVAL, - INNER_PARAMETERS, MODE_FUN, MODE_RES, RDATAS, - SPLINE_KNOTS, SUFFIXES_CSV, SUFFIXES_HDF5, ModeType, @@ -233,10 +231,6 @@ def __init__( # `set_custom_timepoints` method for more information. self.custom_timepoints = None - # Initialize the list for saving of inner parameter values. - self.inner_parameters: list[float] = None - self.spline_knots: list[list[list[float]]] = None - def get_config(self) -> dict: """Return basic information of the objective configuration.""" info = super().get_config() @@ -503,11 +497,6 @@ def call_unprocessed( nllh = ret[FVAL] rdatas = ret[RDATAS] - if ret.get(INNER_PARAMETERS, None) is not None: - self.inner_parameters = ret[INNER_PARAMETERS] - - if ret.get(SPLINE_KNOTS, None) is not None: - self.spline_knots = ret[SPLINE_KNOTS] # check whether we should update data for preequilibration guesses if ( diff --git a/pypesto/optimize/optimizer.py b/pypesto/optimize/optimizer.py index 671b6a1aa..5625e1dfe 100644 --- a/pypesto/optimize/optimizer.py +++ b/pypesto/optimize/optimizer.py @@ -14,7 +14,7 @@ from ..C import FVAL, GRAD, INNER_PARAMETERS, MODE_FUN, MODE_RES, SPLINE_KNOTS from ..history import HistoryOptions, NoHistory, OptimizerHistory from ..objective import Objective -from ..problem import Problem +from ..problem import HierarchicalProblem, Problem from ..result import OptimizerResult from .load import fill_result_from_history from .options import OptimizeOptions @@ -61,18 +61,17 @@ def wrapped_minimize( optimize_options=optimize_options, ) - # add inner parameters - if ( - hasattr(problem.objective, INNER_PARAMETERS) - and problem.objective.inner_parameters is not None - ): - result[INNER_PARAMETERS] = problem.objective.inner_parameters - - if ( - hasattr(problem.objective, SPLINE_KNOTS) - and problem.objective.spline_knots is not None - ): - result[SPLINE_KNOTS] = problem.objective.spline_knots + if isinstance(problem, HierarchicalProblem): + # Call the objective to obtain inner parameters of + # the optimal outer optimization parameters + return_dict = problem.objective( + result.x, + return_dict=True, + ) + if INNER_PARAMETERS in return_dict: + result[INNER_PARAMETERS] = return_dict[INNER_PARAMETERS] + if SPLINE_KNOTS in return_dict: + result[SPLINE_KNOTS] = return_dict[SPLINE_KNOTS] return result @@ -239,8 +238,8 @@ def minimize_decorator_collection(minimize): @wraps(minimize) @fix_decorator @time_decorator - @history_decorator @hierarchical_decorator + @history_decorator def wrapped_minimize( self, problem: Problem, diff --git a/pypesto/visualize/model_fit.py b/pypesto/visualize/model_fit.py index 9dec63b33..26d296d1d 100644 --- a/pypesto/visualize/model_fit.py +++ b/pypesto/visualize/model_fit.py @@ -17,9 +17,8 @@ from petab.visualize import plot_problem from ..C import CENSORED, ORDINAL, RDATAS, SEMIQUANTITATIVE -from ..hierarchical.relative.calculator import RelativeAmiciCalculator from ..petab.importer import get_petab_non_quantitative_data_types -from ..problem import Problem +from ..problem import HierarchicalProblem, Problem from ..result import Result from .ordinal_categories import plot_categories_from_pypesto_result from .spline_approximation import _add_spline_mapped_simulations_to_model_fit @@ -241,7 +240,7 @@ def _get_simulation_rdatas( parameters = problem.get_reduced_vector(parameters) # simulate with custom timepoints for hierarchical model - if isinstance(problem.objective.calculator, RelativeAmiciCalculator): + if isinstance(problem, HierarchicalProblem): # get parameter dictionary x_dct = dict( zip(problem.x_names, result.optimize_result.list[start_index].x) @@ -253,8 +252,10 @@ def _get_simulation_rdatas( ) # update parameter dictionary with inner parameters - inner_parameters = ret["inner_parameters"] - x_dct.update(inner_parameters) + inner_parameter_dict = dict( + zip(problem.inner_x_names, ret["inner_parameters"]) + ) + x_dct.update(inner_parameter_dict) parameter_mapping = problem.objective.parameter_mapping edatas = copy.deepcopy(problem.objective.edatas)