def get_parameter_names(self, target_scale: str = 'prior'): """Get meaningful parameter names, corrected for target scale.""" parameter_df = petab.normalize_parameter_df( self.petab_problem.parameter_df ) # scale if target_scale == C.LIN: target_scales = {key: C.LIN for key in self.prior_scales} elif target_scale == 'prior': target_scales = self.prior_scales elif target_scale == 'scaled': target_scales = self.scaled_scales else: raise ValueError(f"Did not recognize target scale {target_scale}") names = {} for _, row in parameter_df.reset_index().iterrows(): if row[C.ESTIMATE] == 0: continue key = row[C.PARAMETER_ID] name = str(key) if C.PARAMETER_NAME in parameter_df: if not petab.is_empty(row[C.PARAMETER_NAME]): name = str(row[C.PARAMETER_NAME]) target_scale = target_scales[key] if target_scale != C.LIN: # mini check whether the name might indicate the scale already if not name.startswith("log"): name = target_scale + "(" + name + ")" names[key] = name return names
def calculate_residuals_for_table(measurement_df: pd.DataFrame, simulation_df: pd.DataFrame, observable_df: pd.DataFrame, parameter_df: pd.DataFrame, normalize: bool = True, scale: bool = True) -> pd.DataFrame: """ Calculate residuals for a single measurement table. For the argumenets, see `calculate_residuals`. """ # create residual df as copy of measurement df, change column residual_df = measurement_df.copy(deep=True).rename( columns={MEASUREMENT: RESIDUAL}) # matching columns compared_cols = set(MEASUREMENT_DF_COLS) compared_cols -= {MEASUREMENT} compared_cols &= set(measurement_df.columns) compared_cols &= set(simulation_df.columns) # compute noise formulas for observables noise_formulas = get_symbolic_noise_formulas(observable_df) # iterate over measurements, find corresponding simulations for irow, row in measurement_df.iterrows(): measurement = row[MEASUREMENT] # look up in simulation df masks = [(simulation_df[col] == row[col]) | petab.is_empty(row[col]) for col in compared_cols] mask = reduce(lambda x, y: x & y, masks) simulation = simulation_df.loc[mask][SIMULATION].iloc[0] if scale: # apply scaling observable = observable_df.loc[row[OBSERVABLE_ID]] trafo = observable.get(OBSERVABLE_TRANSFORMATION, LIN) simulation = petab.scale(simulation, trafo) measurement = petab.scale(measurement, trafo) # non-normalized residual is just the difference residual = simulation - measurement noise_value = 1 if normalize: # look up noise standard deviation noise_value = evaluate_noise_formula(row, noise_formulas, parameter_df, simulation) residual /= noise_value # fill in value residual_df.loc[irow, RESIDUAL] = residual return residual_df
def calculate_llh_for_table(measurement_df: pd.DataFrame, simulation_df: pd.DataFrame, observable_df: pd.DataFrame, parameter_df: pd.DataFrame) -> float: """Calculate log-likelihood for one set of tables. For the arguments, see `calculate_llh`.""" llhs = [] # matching columns compared_cols = set(MEASUREMENT_DF_COLS) compared_cols -= {MEASUREMENT} compared_cols &= set(measurement_df.columns) compared_cols &= set(simulation_df.columns) # compute noise formulas for observables noise_formulas = get_symbolic_noise_formulas(observable_df) # iterate over measurements, find corresponding simulations for irow, row in measurement_df.iterrows(): measurement = row[MEASUREMENT] # look up in simulation df masks = [(simulation_df[col] == row[col]) | petab.is_empty(row[col]) for col in compared_cols] mask = reduce(lambda x, y: x & y, masks) simulation = simulation_df.loc[mask][SIMULATION].iloc[0] observable = observable_df.loc[row[OBSERVABLE_ID]] # get scale scale = observable.get(OBSERVABLE_TRANSFORMATION, LIN) # get noise standard deviation noise_value = evaluate_noise_formula(row, noise_formulas, parameter_df, petab.scale(simulation, scale)) # get noise distribution noise_distribution = observable.get(NOISE_DISTRIBUTION, NORMAL) llh = calculate_single_llh(measurement, simulation, scale, noise_distribution, noise_value) llhs.append(llh) llh = sum(llhs) return llh