Пример #1
0
def create_parameter_mapping(
    petab_problem: petab.Problem,
    simulation_conditions: Union[pd.DataFrame, Dict],
    scaled_parameters: bool,
    amici_model: AmiciModel,
) -> ParameterMapping:
    """Generate AMICI specific parameter mapping.

    :param petab_problem:
        PEtab problem
    :param simulation_conditions:
        Result of `petab.get_simulation_conditions`. Can be provided to save
        time if this has been obtained before.
    :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.
    :param amici_model:
        AMICI model.

    :return:
        List of the parameter mappings.
    """
    if simulation_conditions is None:
        simulation_conditions = \
            petab_problem.get_simulation_conditions_from_measurement_df()

    # Because AMICI globalizes all local parameters during model import,
    # we need to do that here as well to prevent parameter mapping errors
    # (PEtab does currently not care about SBML LocalParameters)
    if petab_problem.sbml_document:
        converter_config = libsbml.SBMLLocalParameterConverter() \
            .getDefaultProperties()
        petab_problem.sbml_document.convert(converter_config)
    else:
        logger.debug("No petab_problem.sbml_document is set. Cannot convert "
                     "SBML LocalParameters. If the model contains "
                     "LocalParameters, parameter mapping will fail.")

    prelim_parameter_mapping = \
        petab_problem.get_optimization_to_simulation_parameter_mapping(
            warn_unmapped=False, scaled_parameters=scaled_parameters,
            allow_timepoint_specific_numeric_noise_parameters=
            not petab.lint.observable_table_has_nontrivial_noise_formula(
                petab_problem.observable_df
            )
        )

    parameter_mapping = ParameterMapping()
    for (_, condition), prelim_mapping_for_condition in \
            zip(simulation_conditions.iterrows(), prelim_parameter_mapping):
        mapping_for_condition = create_parameter_mapping_for_condition(
            prelim_mapping_for_condition, condition, petab_problem,
            amici_model)
        parameter_mapping.append(mapping_for_condition)

    return parameter_mapping
Пример #2
0
def create_parameter_table(problem: petab.Problem, nominal_parameters):
    """Create PEtab parameter table"""

    df = petab.create_parameter_df(problem.sbml_model,
                                   problem.condition_df,
                                   problem.observable_df,
                                   problem.measurement_df,
                                   include_optional=True,
                                   lower_bound=1e-3,
                                   upper_bound=1e5)

    df['hierarchicalOptimization'] = 0
    df.loc['scaling_x1_common', 'hierarchicalOptimization'] = 1
    df.loc['offset_x2_batch_0', 'hierarchicalOptimization'] = 1
    df.loc['offset_x2_batch_1', 'hierarchicalOptimization'] = 1
    df.loc['x1withsigma_sigma', 'hierarchicalOptimization'] = 1

    for pid, val in nominal_parameters.items():
        if pid in df.index:
            df.loc[pid, ptc.NOMINAL_VALUE] = val
            df.loc[pid, ptc.PARAMETER_SCALE] = ptc.LOG10
            df.loc[pid, ptc.ESTIMATE] = 1
        elif pid.startswith('noiseParameter') \
                or pid.startswith('observableParameter'):
            continue
        else:
            print("extra parameter", pid, val)

    # offsets can be negative: adapt scaling and bounds:
    offsets = df.index.str.startswith('offset_')
    df.loc[offsets, ptc.PARAMETER_SCALE] = ptc.LIN

    problem.parameter_df = df
Пример #3
0
def create_parameter_table(problem: petab.Problem, parameter_file,
                           nominal_parameters):
    """Create PEtab parameter table"""

    df = problem.create_parameter_df(lower_bound=-3, upper_bound=5)
    # TODO: move to peTAB
    df['hierarchicalOptimization'] = 0
    df.loc['scaling_x1_common', 'hierarchicalOptimization'] = 1
    df.loc['offset_x2_batch-0', 'hierarchicalOptimization'] = 1
    df.loc['offset_x2_batch-1', 'hierarchicalOptimization'] = 1
    df.loc['x1withsigma_sigma', 'hierarchicalOptimization'] = 1
    #df.parameterScale = 'lin'
    #df.estimate = 0

    print(nominal_parameters)

    for pid, val in nominal_parameters.items():
        if pid in df.index:
            df.loc[pid, 'nominalValue'] = val
            df.loc[pid, 'parameterScale'] = 'log10'
            df.loc[pid, 'estimate'] = 1
        elif pid.startswith('noiseParameter') \
            or pid.startswith('observableParameter'):
            continue
        else:
            print("extra parameter", pid, val)

    # offsets can be negative: adapt scaling and bounds:
    offsets = df.index.str.startswith('offset_')
    df.loc[offsets, 'parameterScale'] = 'lin'
    df.loc[offsets, 'lowerBound'] = np.power(10.0, df.loc[offsets,
                                                          'lowerBound'])
    df.loc[offsets, 'upperBound'] = np.power(10.0, df.loc[offsets,
                                                          'upperBound'])

    problem.parameter_df = df

    df.to_csv(parameter_file, sep="\t", index=True)
Пример #4
0
def get_summary(
        petab_problem: petab.Problem,
        petab_problem_id: str = None,
) -> Dict:
    """Get dictionary with stats for the given PEtab problem"""
    return {
        'petab_problem_id':
            petab_problem_id,
        'conditions':
            petab_problem.get_simulation_conditions_from_measurement_df().shape[0],
        'estimated_parameters':
            np.sum(petab_problem.parameter_df[petab.ESTIMATE]),
        'events':
            len(petab_problem.sbml_model.getListOfEvents()),
        'measurements':
            len(petab_problem.measurement_df.index),
        'observables':
            len(petab_problem.measurement_df[petab.OBSERVABLE_ID].unique()),
        'species':
            len(petab_problem.sbml_model.getListOfSpecies()),
        'reference_uris':
            get_reference_uris(petab_problem.sbml_model),
    }
Пример #5
0
def create_edatas(
        amici_model: AmiciModel,
        petab_problem: petab.Problem,
        simulation_conditions: Union[pd.DataFrame, Dict] = None,
) -> List[amici.ExpData]:
    """Create list of :class:`amici.amici.ExpData` objects for PEtab problem.

    :param amici_model:
        AMICI model.
    :param petab_problem:
        Underlying PEtab problem.
    :param simulation_conditions:
        Result of `petab.get_simulation_conditions`. Can be provided to save
        time if this has be obtained before.

    :return:
        List with one :class:`amici.amici.ExpData` per simulation condition,
        with filled in timepoints and data.
    """
    if simulation_conditions is None:
        simulation_conditions = \
            petab_problem.get_simulation_conditions_from_measurement_df()

    observable_ids = amici_model.getObservableIds()

    edatas = []
    for _, condition in simulation_conditions.iterrows():
        # Create amici.ExpData for each simulation
        edata = create_edata_for_condition(
            condition=condition,
            amici_model=amici_model,
            petab_problem=petab_problem,
            observable_ids=observable_ids,
        )
        edatas.append(edata)

    return edatas
Пример #6
0
def simulate_petab(
        petab_problem: petab.Problem,
        amici_model: AmiciModel,
        solver: Optional[amici.Solver] = None,
        problem_parameters: Optional[Dict[str, float]] = None,
        simulation_conditions: Union[pd.DataFrame, Dict] = None,
        edatas: List[AmiciExpData] = None,
        parameter_mapping: ParameterMapping = None,
        scaled_parameters: Optional[bool] = False,
        log_level: int = logging.WARNING
) -> Dict[str, Any]:
    """Simulate PEtab model.

    :param petab_problem:
        PEtab problem to work on.
    :param amici_model:
        AMICI Model assumed to be compatible with ``petab_problem``.
    :param solver:
        An AMICI solver. Will use default options if None.
    :param problem_parameters:
        Run simulation with these parameters. If None, PEtab `nominalValues`
        will be used). To be provided as dict,  mapping PEtab problem
        parameters to SBML IDs.
    :param simulation_conditions:
        Result of `petab.get_simulation_conditions`. Can be provided to save
        time if this has be obtained before.
        Not required if `edatas` and `parameter_mapping` are provided.
    :param edatas:
        Experimental data. Parameters are inserted in-place for simulation.
    :param parameter_mapping:
        Optional precomputed PEtab parameter mapping for efficiency, as
        generated by `create_parameter_mapping`.
    :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.
    :param log_level:
        Log level, see :mod:`amici.logging` module.

    :return:
        Dictionary of

        * cost function value (LLH),
        * const function sensitivity w.r.t. parameters (SLLH),
          (**NOTE**: Sensitivities are computed for the scaled parameters)
        * list of `ReturnData` (RDATAS),

        corresponding to the different simulation conditions.
        For ordering of simulation conditions, see
        :meth:`petab.Problem.get_simulation_conditions_from_measurement_df`.
    """
    logger.setLevel(log_level)

    if solver is None:
        solver = amici_model.getSolver()

    # Get parameters
    if problem_parameters is None:
        # Use PEtab nominal values as default
        problem_parameters = {t.Index: getattr(t, NOMINAL_VALUE) for t in
                              petab_problem.parameter_df.itertuples()}
        scaled_parameters = False

    # number of amici simulations will be number of unique
    # (preequilibrationConditionId, simulationConditionId) pairs.
    # Can be optimized by checking for identical condition vectors.
    if simulation_conditions is None and parameter_mapping is None \
            and edatas is None:
        simulation_conditions = \
            petab_problem.get_simulation_conditions_from_measurement_df()

    # Get parameter mapping
    if parameter_mapping is None:
        parameter_mapping = create_parameter_mapping(
            petab_problem=petab_problem,
            simulation_conditions=simulation_conditions,
            scaled_parameters=scaled_parameters,
            amici_model=amici_model)

    # Get edatas
    if edatas is None:
        # Generate ExpData with all condition-specific information
        edatas = create_edatas(
            amici_model=amici_model,
            petab_problem=petab_problem,
            simulation_conditions=simulation_conditions)

    # Fill parameters in ExpDatas (in-place)
    fill_in_parameters(
        edatas=edatas,
        problem_parameters=problem_parameters,
        scaled_parameters=scaled_parameters,
        parameter_mapping=parameter_mapping,
        amici_model=amici_model)

    # Simulate
    rdatas = amici.runAmiciSimulations(amici_model, solver, edata_list=edatas)

    # Compute total llh
    llh = sum(rdata['llh'] for rdata in rdatas)
    # Compute total sllh
    sllh = aggregate_sllh(amici_model=amici_model, rdatas=rdatas,
                          parameter_mapping=parameter_mapping)

    # Log results
    sim_cond = petab_problem.get_simulation_conditions_from_measurement_df()
    for i, rdata in enumerate(rdatas):
        logger.debug(f"Condition: {sim_cond.iloc[i, :].values}, status: "
                     f"{rdata['status']}, llh: {rdata['llh']}")

    return {
        LLH: llh,
        SLLH: sllh,
        RDATAS: rdatas
    }
Пример #7
0
def create_parameterized_edatas(
        amici_model: AmiciModel,
        petab_problem: petab.Problem,
        problem_parameters: Dict[str, numbers.Number],
        scaled_parameters: bool = False,
        parameter_mapping: ParameterMapping = None,
        simulation_conditions: Union[pd.DataFrame, Dict] = None,
) -> List[amici.ExpData]:
    """Create list of :class:amici.ExpData objects with parameters filled in.

    :param amici_model:
        AMICI Model assumed to be compatible with ``petab_problem``.
    :param petab_problem:
        PEtab problem to work on.
    :param problem_parameters:
        Run simulation with these parameters. If None, PEtab `nominalValues`
        will be used). To be provided as dict, mapping PEtab problem
        parameters to SBML IDs.
    :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.
    :param parameter_mapping:
        Optional precomputed PEtab parameter mapping for efficiency, as
        generated by `create_parameter_mapping`.
    :param simulation_conditions:
        Result of `petab.get_simulation_conditions`. Can be provided to save
        time if this has been obtained before.

    :return:
        List with one :class:`amici.amici.ExpData` per simulation condition,
        with filled in timepoints, data and parameters.
    """
    # number of amici simulations will be number of unique
    # (preequilibrationConditionId, simulationConditionId) pairs.
    # Can be optimized by checking for identical condition vectors.
    if simulation_conditions is None:
        simulation_conditions = \
            petab_problem.get_simulation_conditions_from_measurement_df()

    # Get parameter mapping
    if parameter_mapping is None:
        parameter_mapping = create_parameter_mapping(
            petab_problem=petab_problem,
            simulation_conditions=simulation_conditions,
            scaled_parameters=scaled_parameters,
            amici_model=amici_model)

    # Generate ExpData with all condition-specific information
    edatas = create_edatas(
        amici_model=amici_model,
        petab_problem=petab_problem,
        simulation_conditions=simulation_conditions)

    # Fill parameters in ExpDatas (in-place)
    fill_in_parameters(
        edatas=edatas,
        problem_parameters=problem_parameters,
        scaled_parameters=scaled_parameters,
        parameter_mapping=parameter_mapping,
        amici_model=amici_model)

    return edatas
Пример #8
0
def subset_petab_problem(
    petab_problem: petab.Problem,
    timecourse_id: str,
) -> Sequence[petab.Problem]:
    petab_problem = deepcopy(petab_problem)
    petab_problem.observable_df.loc[DUMMY_OBSERVABLE_ID] = \
        {
            OBSERVABLE_FORMULA: DUMMY_MEASUREMENT,
            NOISE_FORMULA: DUMMY_NOISE,
        }
    # TODO allow no specification of timecourse if only one timecourse in
    # problem. TODO raise error if multiple timecourses but no timecourse ID
    # specified
    petab_problem.measurement_df = petab_problem.measurement_df[
        petab_problem.measurement_df[SIMULATION_CONDITION_ID] == timecourse_id]
    timecourse = parse_timecourse_string(
        petab_problem.timecourse_df.loc[timecourse_id][TIMECOURSE], )
    # FIXME timepoints not necessarily float
    timecourse = [(float(_t), _id) for _t, _id in timecourse]
    petab_problems = []
    for index, (timepoint, condition_id) in enumerate(timecourse):
        petab_problems.append(deepcopy(petab_problem))
        petab_problems[-1].condition_df.loc[timecourse_id] = \
            petab_problems[-1].condition_df.loc[condition_id]
        # Drop other conditions
        # FIXME test how this affects other conditions or how to combine normal conditions + timecourses...
        #       or only allow timecourses?
        petab_problems[-1].condition_df = (
            petab_problems[-1].condition_df.loc[[timecourse_id]])
        petab_problems[-1].measurement_df = \
            petab_problems[-1].measurement_df[
                petab_problems[-1].measurement_df[TIME].astype(float)
                >= timepoint
            ]
        if index < len(timecourse) - 1:
            next_timepoint = timecourse[index + 1][0]
            petab_problems[-1].measurement_df = \
                petab_problems[-1].measurement_df[
                    petab_problems[-1].measurement_df[TIME].astype(float)
                    <= next_timepoint
                ]
            # Add dummy data to ensure endpoint is outputted.
            petab_problems[-1].measurement_df = \
                petab_problems[-1].measurement_df.append(
                    {
                        OBSERVABLE_ID: DUMMY_OBSERVABLE_ID,
                        SIMULATION_CONDITION_ID: timecourse_id,
                        TIME: next_timepoint,
                        MEASUREMENT: DUMMY_MEASUREMENT,
                    },
                    ignore_index=True,
                )
        # Remove condition parameters from the parameters table.
        condition_components = [
            c for c in petab_problems[-1].condition_df.loc[timecourse_id].index
            if c not in NON_COMPONENT_CONDITION_LABELS
        ]
        petab_problems[-1].parameter_df.drop(
            condition_components,
            inplace=True,
            errors='ignore',  # only parameters that are in the table are dropped
        )

        #for t in [timepoint, next_timepoint]:
        #    if not any(
        #            t == petab_problems[-1].measurement_df[TIME].astype(float)
        #    ):
        #        # FIXME add dummy data
        #        print(t)
        #        breakpoint()
        #        pass
    return petab_problems
Пример #9
0
def simulate_timecourse_objective(
    parent_petab_problem: petab.Problem,
    timecourse_id: str,
    problem_parameters: Dict[str, float],
    parameter_mapping,
    sensi_orders: Tuple[int, ...] = (0, ),
    return_all: bool = False,
    max_abs_grad: float = None,
    **kwargs,
):
    #unscaled_problem_parameters = unscale_parameters(
    #    scaled_parameters=problem_parameters,
    #    petab_problem=parent_petab_problem,
    #)
    unscaled_problem_parameters = parent_petab_problem.unscale_parameters(
        scaled_parameters=problem_parameters, )

    #print('in')
    results = simulate_timecourse(
        parent_petab_problem,
        timecourse_id,
        problem_parameters=unscaled_problem_parameters,
        parameter_mapping=parameter_mapping,
        sensi_orders=sensi_orders,
        **kwargs,
    )
    #print('out')
    if kwargs.get('initial_states', None) is not None:
        pass
        #breakpoint()

    #sensitivity_parameter_ids = results[0]['sllh'].keys()
    sensitivity_parameter_ids = problem_parameters.keys()
    #print('l1')
    #print(problem_parameters)
    #breakpoint()
    #sensitivity_parameter_ids = parent_petab_problem.x_ids
    for result in results:
        if result['sllh'].keys() != sensitivity_parameter_ids:
            # FIXME reimplement so this still holds?
            #raise NotImplementedError(
            #    'All conditions must provide sensitivities for the same set '
            #    'of parameters.'
            #)
            pass
    #print('l2')
    accumulated_result = {
        FVAL:
        sum(-result['llh'] for result in results),
        GRAD: [
            sum(-result['sllh'][k] for result in results
                if k in result['sllh']) for k in sensitivity_parameter_ids
            #if k in result['sllh']
        ]
        #GRAD: {
        #    k: sum(-result['sllh'][k] for result in results)
        #    for k in sensitivity_parameter_ids
        #}
    }
    #print('l3')
    if return_all:
        # TODO magic constant
        accumulated_result[FINAL_STATES] = \
            one(results[-1]['rdatas']).x[-1].flatten()
        #accumulated_result[RESULTS] = results
    #print('l4')
    #print(accumulated_result)
    #print(accumulated_result)
    #breakpoint()
    #print(accumulated_result)

    if max_abs_grad is not None:
        pass
        #accumulated_result[GRAD] = list(np.nan_to_num(
        #    np.array(accumulated_result[GRAD]),
        #    nan=np.nan,
        #    posinf=max_abs_grad,
        #    neginf=-max_abs_grad,
        #))
    #print(accumulated_result)

    return accumulated_result
Пример #10
0
def filter_observables(petab_problem: petab.Problem):
    petab_problem.measurement_df = petab_problem.measurement_df.loc[
        petab_problem.measurement_df[petab.OBSERVABLE_ID].apply(
            lambda x: x in petab_problem.observable_df.index
        ), :
    ]