diff --git a/python/sdist/amici/petab/simulations.py b/python/sdist/amici/petab/simulations.py index 4078eff8fa..0f9aae3bfd 100644 --- a/python/sdist/amici/petab/simulations.py +++ b/python/sdist/amici/petab/simulations.py @@ -107,11 +107,14 @@ def simulate_petab( Experimental data. Parameters are inserted in-place for simulation. :param parameter_mapping: Optional precomputed PEtab parameter mapping for efficiency, as - generated by :py:func:`create_parameter_mapping`. + generated by :py:func:`create_parameter_mapping` with + ``scaled_parameters=True``. :param scaled_parameters: If ``True``, ``problem_parameters`` are assumed to be on the scale provided in the PEtab parameter table and will be unscaled. If ``False``, they are assumed to be in linear scale. + If `parameter_mapping` is provided, this must match the value of + `scaled_parameters` used to generate the mapping. :param log_level: Log level, see :mod:`amici.logging` module. :param num_threads: @@ -140,14 +143,6 @@ def simulate_petab( if solver is None: solver = amici_model.getSolver() - # Switch to scaled parameters. - problem_parameters = _default_scaled_parameters( - petab_problem=petab_problem, - problem_parameters=problem_parameters, - scaled_parameters=scaled_parameters, - ) - scaled_parameters = True - # number of amici simulations will be number of unique # (preequilibrationConditionId, simulationConditionId) pairs. # Can be optimized by checking for identical condition vectors. @@ -165,10 +160,35 @@ def simulate_petab( parameter_mapping = create_parameter_mapping( petab_problem=petab_problem, simulation_conditions=simulation_conditions, - scaled_parameters=scaled_parameters, + # we will always use scaled parameters internally + scaled_parameters=True, amici_model=amici_model, ) + if problem_parameters is None: + # scaled PEtab nominal values + problem_parameters = dict( + zip( + petab_problem.x_ids, + petab_problem.x_nominal_scaled, + ) + ) + # depending on `fill_fixed_parameters` for parameter mapping, the + # parameter mapping may contain values instead of symbols for fixed + # parameters. In this case, we need to filter them here to avoid + # warnings in `fill_in_parameters`. + free_parameters = parameter_mapping.free_symbols + problem_parameters = { + par_id: par_value + for par_id, par_value in problem_parameters.items() + if par_id in free_parameters + } + + elif not scaled_parameters: + problem_parameters = petab_problem.scale_parameters(problem_parameters) + + scaled_parameters = True + # Get edatas if edatas is None: # Generate ExpData with all condition-specific information @@ -461,41 +481,3 @@ def rdatas_to_simulation_df( ) return df.rename(columns={MEASUREMENT: SIMULATION}) - - -def _default_scaled_parameters( - petab_problem: petab.Problem, - problem_parameters: Optional[dict[str, float]] = None, - scaled_parameters: bool = False, -) -> Optional[dict[str, float]]: - """ - Helper method to handle an unscaled or unspecified parameter vector. - - The parameter vector defaults to the nominal values in the PEtab - parameter table. - - Unscaled parameter values are scaled. - - :param petab_problem: - The PEtab problem. - :param problem_parameters: - Keys are PEtab parameter IDs, values are parameter values on the scale - defined in the PEtab parameter table. Defaults to the nominal values in - the PEtab parameter table. - :param scaled_parameters: - Whether `problem_parameters` are on the scale defined in the PEtab - parameter table. - - :return: - The scaled parameter vector. - """ - if problem_parameters is None: - problem_parameters = dict( - zip( - petab_problem.x_ids, - petab_problem.x_nominal_scaled, - ) - ) - elif not scaled_parameters: - problem_parameters = petab_problem.scale_parameters(problem_parameters) - return problem_parameters