def get_experiment(experiment, **kwargs): """Returns the specified experiment. :param experiment: experiment name or index :type experiment: int or str or COPASI.CExperiment :param kwargs: - | `model`: to specify the data model to be used (if not specified | the one from :func:`.get_current_model` will be taken) :return: the experiment or an error if none existent """ if not isinstance(experiment, COPASI.CExperiment): model = model_io.get_model_from_dict_or_default(kwargs) assert (isinstance(model, COPASI.CDataModel)) task = model.getTask(TASK_PARAMETER_ESTIMATION) assert (isinstance(task, COPASI.CFitTask)) problem = task.getProblem() assert (isinstance(problem, COPASI.CFitProblem)) exp_set = problem.getExperimentSet() if type(experiment) is int and experiment >= exp_set.size(): raise ValueError('Experiment index out of bounds') exp = exp_set.getExperiment(experiment) if exp is not None: experiment = exp else: raise ValueError('No experiment for: {0}'.format(experiment)) return experiment
def get_opt_statistic(**kwargs): """Return information about the last optimization run. :param kwargs: - | `model`: to specify the data model to be used (if not specified | the one from :func:`.get_current_model` will be taken) :return: dictionary with the statistic :rtype: {} """ dm = model_io.get_model_from_dict_or_default(kwargs) task = dm.getTask(basico.T.OPTIMIZATION) assert (isinstance(task, COPASI.COptTask)) problem = task.getProblem() assert (isinstance(problem, COPASI.COptProblem)) result = { 'obj': problem.getSolutionValue(), 'f_evals': problem.getFunctionEvaluations(), 'failed_evals_exception': problem.getFailedEvaluationsExc(), 'failed_evals_nan': problem.getFailedEvaluationsNaN(), 'cpu_time': problem.getExecutionTime(), } result['evals_per_sec'] = result['cpu_time'] / result['f_evals'] return result
def get_experiment_names(**kwargs): """Returns the list of experiment names :param kwargs: - | `model`: to specify the data model to be used (if not specified | the one from :func:`.get_current_model` will be taken) :return: list of experiment names defined :rtype: [str] """ model = model_io.get_model_from_dict_or_default(kwargs) assert (isinstance(model, COPASI.CDataModel)) task = model.getTask(TASK_PARAMETER_ESTIMATION) assert (isinstance(task, COPASI.CFitTask)) problem = task.getProblem() assert (isinstance(problem, COPASI.CFitProblem)) result = [] for i in range(problem.getExperimentSet().size()): experiment = problem.getExperimentSet().getExperiment(i) result.append(experiment.getObjectName()) return result
def get_fit_statistic(**kwargs): """Return information about the last fit. :param kwargs: - | `model`: to specify the data model to be used (if not specified | the one from :func:`.get_current_model` will be taken) :return: dictionary with the fit statistic :rtype: {} """ dm = model_io.get_model_from_dict_or_default(kwargs) task = dm.getTask(TASK_PARAMETER_ESTIMATION) assert (isinstance(task, COPASI.CFitTask)) problem = task.getProblem() assert (isinstance(problem, COPASI.CFitProblem)) experiments = problem.getExperimentSet() assert (isinstance(experiments, COPASI.CExperimentSet)) result = { 'obj': problem.getSolutionValue(), 'rms': problem.getRMS(), 'sd': problem.getStdDeviation(), 'f_evals': problem.getFunctionEvaluations(), 'failed_evals_exception': problem.getFailedEvaluationsExc(), 'failed_evals_nan': problem.getFailedEvaluationsNaN(), 'cpu_time': problem.getExecutionTime(), 'data_points': experiments.getDataPointCount(), 'valid_data_points': experiments.getValidValueCount(), } result['evals_per_sec'] = result['cpu_time'] / result['f_evals'] return result
def run_optimization(expression=None, output=None, settings=None, **kwargs): """Runs the optimization :param expression: optional objective function to be used :param settings: optional settings dictionary :param output: optional list of output to collect :param kwargs: optional arguments :return: pandas data frame of the specified output, or the resulting solution for the parameters """ model = model_io.get_model_from_dict_or_default(kwargs) task = model.getTask(basico.T.OPTIMIZATION) assert (isinstance(task, COPASI.COptTask)) problem = task.getProblem() assert (isinstance(problem, COPASI.COptProblem)) if 'method' in kwargs: method = kwargs['method'] if isinstance(method, dict): set_opt_settings({method}, model=model) elif isinstance(method, int): task.setMethodType(method) else: set_opt_settings({'method': {'name': method}}, model=model) if settings: set_opt_settings(settings, model) if expression: set_objective_function(expression, model) dh = None cols = [] if output: dh, cols = basico.task_timecourse.create_data_handler(output, after=output, model=model) model.addInterface(dh) if not task.initializeRaw(COPASI.CCopasiTask.OUTPUT_UI): logging.warning("Couldn't initialize optimization task") use_initial_values = kwargs.get('use_initial_values', True) if not task.processRaw(use_initial_values): logging.warning("Couldn't process optimization task") if dh: model.removeInterface(dh) data = basico.task_timecourse.get_data_from_data_handler(dh, cols) del dh dh = None return data return get_opt_solution(model=model)
def _get_experiment_keys(**kwargs): model = model_io.get_model_from_dict_or_default(kwargs) assert (isinstance(model, COPASI.CDataModel)) task = model.getTask(TASK_PARAMETER_ESTIMATION) assert (isinstance(task, COPASI.CFitTask)) problem = task.getProblem() assert (isinstance(problem, COPASI.CFitProblem)) result = [] for i in range(problem.getExperimentSet().size()): experiment = problem.getExperimentSet().getExperiment(i) result.append(experiment.getKey()) return result
def remove_fit_parameters(**kwargs): """Removes all fit items :param kwargs: - | `model`: to specify the data model to be used (if not specified | the one from :func:`.get_current_model` will be taken) :return: None """ dm = model_io.get_model_from_dict_or_default(kwargs) pe_task = dm.getTask(TASK_PARAMETER_ESTIMATION) problem = pe_task.getProblem() assert (isinstance(problem, COPASI.CFitProblem)) while problem.getOptItemSize() > 0: problem.removeOptItem(0)
def num_validations_files(**kwargs): """Returns the number of cross validation experiment files :param kwargs: - | `model`: to specify the data model to be used (if not specified | the one from :func:`.get_current_model` will be taken) :return: number of cross validation experiment files :rtype: int """ model = model_io.get_model_from_dict_or_default(kwargs) assert (isinstance(model, COPASI.CDataModel)) task = model.getTask(TASK_PARAMETER_ESTIMATION) assert (isinstance(task, COPASI.CFitTask)) problem = task.getProblem() assert (isinstance(problem, COPASI.CFitProblem)) return problem.getCrossValidationSet().size()
def remove_experiments(**kwargs): """Removes all experiments from the model :param kwargs: - | `model`: to specify the data model to be used (if not specified | the one from :func:`.get_current_model` will be taken) :return: None """ dm = model_io.get_model_from_dict_or_default(kwargs) task = dm.getTask(TASK_PARAMETER_ESTIMATION) assert (isinstance(task, COPASI.CFitTask)) problem = task.getProblem() assert (isinstance(problem, COPASI.CFitProblem)) experiments = problem.getExperimentSet() assert (isinstance(experiments, COPASI.CExperimentSet)) for _ in range(experiments.size()): experiments.removeExperiment(0)
def get_simulation_results(values_only=False, **kwargs): """Runs the current solution statistics and returns result of simulation and experimental data :param values_only: if true, only time points at the measurements will be returned :type values_only: bool :param kwargs: - | `model`: to specify the data model to be used (if not specified | the one from :func:`.get_current_model` will be taken) - | `solution`: a solution data frame to use, if not specified a current solution statistic will be computed :return: tuple of lists of experiment data, and a list of simulation data :rtype: ([pandas.DataFrame],[pandas.DataFrame]) """ import basico dm = model_io.get_model_from_dict_or_default(kwargs) task = dm.getTask(TASK_PARAMETER_ESTIMATION) assert (isinstance(task, COPASI.CFitTask)) problem = task.getProblem() assert (isinstance(problem, COPASI.CFitProblem)) experiments = problem.getExperimentSet() assert (isinstance(experiments, COPASI.CExperimentSet)) result = [] num_experiments = experiments.getExperimentCount() if num_experiments == 0: return result if 'solution' in kwargs: solution = kwargs['solution'] else: solution = run_parameter_estimation( method='Current Solution Statistics') model = dm.getModel() exp_data = [] sim_data = [] for i in range(num_experiments): change_set = COPASI.DataObjectSet() experiment = experiments.getExperiment(i) exp_name = experiment.getObjectName() df = get_data_from_experiment(experiment, rename_headers=True) columns = df.columns.to_list() mapping = get_experiment_mapping(experiment) # set independent values for that experiment independent = mapping[mapping.type == 'independent'] num_independent = independent.shape[0] for j in range(num_independent): name = independent.iloc[j].mapping cn = independent.iloc[j].cn if name not in columns: # independent value is not found in df continue value = df.iloc[0][name] obj = dm.getObject(COPASI.CCommonName(cn)) if obj is None: # not found skip logging.debug( 'independent object not found for cn: {0}'.format(cn)) continue if obj.getObjectName() == 'InitialConcentration': obj.getObjectParent().setInitialConcentration(value) else: obj.getObjectParent().setInitialValue(value) change_set.append(obj) logging.debug('set independent "{0}" to "{1}"'.format(cn, value)) if change_set.size() > 0: model.updateInitialValues(change_set) _update_fit_parameters_from(dm, solution, exp_name) if experiment.getExperimentType() == COPASI.CTaskEnum.Task_steadyState: # run steady state basico.run_steadystate(model=dm) data = basico.model_info._collect_data(cns=mapping[ mapping.type == 'dependent']['cn'].to_list()).transpose() else: # run time course duration = df.iloc[-1].Time if values_only: data = basico.run_time_course(values=df.Time.to_list(), start_time=df.iloc[0].Time) else: data = basico.run_time_course(duration=duration) exp_data.append(df) sim_data.append(data) return exp_data, sim_data
def run_parameter_estimation(**kwargs): """Runs the parameter estimation task as specified: The following are valid methods to be used for the parameter estimation task. Current Solution: * `Current Solution Statistics`, Global Methods: * `Random Search`, * `Simulated Annealing`, * `Differential Evolution`, * `Scatter Search`, * `Genetic Algorithm`, * `Evolutionary Programming`, * `Genetic Algorithm SR`, * `Evolution Strategy (SRES)`, * `Particle Swarm`, Local Methods: * `Levenberg - Marquardt`, * `Hooke & Jeeves`, * `Nelder - Mead`, * `Steepest Descent`, * `NL2SOL`, * `Praxis`, * `Truncated Newton`, :param kwargs: - | `model`: to specify the data model to be used (if not specified | the one from :func:`.get_current_model` will be taken) - | `method` (str): one of the strings from above - | `randomize_start_values` (bool): if true, parameters will be randomized before starting otherwise the | parameters starting value will be taken. - | `calculate_statistics` (bool): if true, the statistics will be calculated at the end of the task - | `create_parametersets` (bool): if true, parameter sets will be created for all experiments - `use_initial_values` (bool): whether to use initial values - `scheduled` (bool): sets whether the task is scheduled or not - `update_model` (bool): sets whether the model should be updated, or reset to initial conditions. - `settings` (dict): a dictionary with settings to use, in the same format as the ones obtained from :func:`.get_task_settings` :return: the solution for the fit parameters see :func:`get_parameters_solution`. :rtype: pandas.DataFrame """ model = model_io.get_model_from_dict_or_default(kwargs) assert (isinstance(model, COPASI.CDataModel)) task = model.getTask(TASK_PARAMETER_ESTIMATION) assert (isinstance(task, COPASI.CFitTask)) problem = task.getProblem() assert (isinstance(problem, COPASI.CFitProblem)) if problem.getOptItemSize() == 0: logging.warning( 'No fit parameters defined, skipping parameter estimation run') return get_parameters_solution(model) if 'scheduled' in kwargs: task.setScheduled(kwargs['scheduled']) if 'update_model' in kwargs: task.setUpdateModel(kwargs['update_model']) old_create_parameter_sets = problem.getCreateParameterSets() # old_calculate_statistics = problem.getCalculateStatistics() # old_randomize_start_values = problem.getRandomizeStartValues() problem.setCreateParameterSets(True) if 'method' in kwargs: method = kwargs['method'] if isinstance(method, int): task.setMethodType(method) else: task.setMethodType(COPASI.CCopasiMethod_TypeNameToEnum(method)) if 'randomize_start_values' in kwargs: problem.setRandomizeStartValues(bool(kwargs['randomize_start_values'])) if 'calculate_statistics' in kwargs: problem.setCalculateStatistics(bool(kwargs['calculate_statistics'])) if 'create_parametersets' in kwargs: problem.setCreateParameterSets(bool(kwargs['create_parametersets'])) use_initial_values = kwargs.get('use_initial_values', True) if 'settings' in kwargs: basico.set_task_settings(task, kwargs['settings']) result = task.initializeRaw(COPASI.CCopasiTask.OUTPUT_UI) if not result: logging.error("Error while initializing parameter estimation: " + COPASI.CCopasiMessage.getLastMessage().getText()) else: result = task.processRaw(use_initial_values) if not result: logging.error("Error while running parameter estimation: " + COPASI.CCopasiMessage.getLastMessage().getText()) problem.setCreateParameterSets(old_create_parameter_sets) return get_parameters_solution(model)
def add_experiment(name, data, **kwargs): """Adds a new experiment to the model. This method adds a new experiment file to the parameter estimation task. The provided data frame will be written into the current directory as `experiment_name.txt` unless a filename has been provided. The mapping between the columns and the model elements should be done by having the columns of the data frame be model element names in question. So for example `[A]` to note that the transient concentrations of a species `A` is to be mapped as dependent variable. or `[A]_0` to note that the initial concentration of a species `A` is to be mapped as independent variable. :param name: the name of the experiment :type name: str :param data: the data frame with the experimental data :type data: pandas.DataFrame :param kwargs: - | `model`: to specify the data model to be used (if not specified | the one from :func:`.get_current_model` will be taken) - | `file_name` (str): the file name to save the experimental data to (otherwise it will be name.txt) :return: the filename of the generated data file :rtype: str """ model = model_io.get_model_from_dict_or_default(kwargs) assert (isinstance(model, COPASI.CDataModel)) task = model.getTask(TASK_PARAMETER_ESTIMATION) assert (isinstance(task, COPASI.CFitTask)) problem = task.getProblem() assert (isinstance(problem, COPASI.CFitProblem)) exp_set = problem.getExperimentSet() assert (isinstance(exp_set, COPASI.CExperimentSet)) exp = exp_set.getExperiment(name) if exp is not None: logging.error( 'An experiment with the name {0} already exists'.format(name)) return None # save data as tsv file_name = os.path.abspath(os.path.join(os.path.curdir, name + '.txt')) if 'file_name' in kwargs: file_name = os.path.abspath(kwargs['file_name']) assert (isinstance(data, pd.DataFrame)) data.to_csv(file_name, sep='\t', header=True, index=False) # create experiment exp = COPASI.CExperiment(model) exp = exp_set.addExperiment(exp) info = COPASI.CExperimentFileInfo(exp_set) info.setFileName(file_name) info.sync() exp.setObjectName(name) exp.setFileName(file_name) exp.setHeaderRow(1) exp.setFirstRow(1) exp.setLastRow(len(data) + 1) columns = data.columns.to_list() if 'time' in [col.lower() for col in columns]: exp.setExperimentType(COPASI.CTaskEnum.Task_timeCourse) else: exp.setExperimentType(COPASI.CTaskEnum.Task_steadyState) obj_map = exp.getObjectMap() num_cols = len(columns) obj_map.setNumCols(num_cols) for i in range(num_cols): role = COPASI.CExperiment.ignore current = columns[i] if current.lower() == 'time': role = COPASI.CExperiment.time else: obj = model.findObjectByDisplayName(current) if obj is None: logging.warning( "Can't find model element for {0}".format(current)) else: assert (isinstance(obj, COPASI.CDataObject)) if obj.getObjectType() != 'Reference': try: obj = obj.getValueReference() except AttributeError: logging.warning( "Cannot map the element {0}".format(current)) role = _get_role_for_reference(obj.getObjectName()) obj_map.setObjectCN(i, obj.getCN()) obj_map.setRole(i, role) exp.calculateWeights() exp_set.compile(model.getModel().getMathContainer()) return file_name
def plot_per_dependent_variable(**kwargs): """ This function creates a figure for each dependent variable, with traces for all experiments. :param kwargs: - | `model`: to specify the data model to be used (if not specified | the one from :func:`.get_current_model` will be taken) :return: array of tuples (fig, ax) for each figure created """ dm = model_io.get_model_from_dict_or_default(kwargs) task = dm.getTask(TASK_PARAMETER_ESTIMATION) assert (isinstance(task, COPASI.CFitTask)) problem = task.getProblem() assert (isinstance(problem, COPASI.CFitProblem)) experiments = problem.getExperimentSet() assert (isinstance(experiments, COPASI.CExperimentSet)) result = [] num_experiments = experiments.getExperimentCount() if num_experiments == 0: return result exp_data, sim_data = get_simulation_results(**kwargs) dependent_variables = {} for i in range(num_experiments): experiment = experiments.getExperiment(i) mapping = get_experiment_mapping(experiment) # set independent values for that experiment dependent = mapping[mapping.type == 'dependent'] num_dependent = dependent.shape[0] for j in range(num_dependent): name = dependent.iloc[j].mapping if name not in dependent_variables: dependent_variables[name] = [] dependent_variables[name].append(i) for dependent in dependent_variables: fig, ax = plt.subplots() cycler = plt.cycler("color", plt.cm.tab20c.colors)() ax.set_title(dependent) experiment_indices = dependent_variables[dependent] for i in experiment_indices: experiment = experiments.getExperiment(i) exp_name = experiment.getObjectName() nextval = next(cycler)['color'] name = dependent if name not in sim_data[i].columns: name = name[1:-1] sim_data[i].reset_index().plot(x='Time', y=name, label="{0} Fit".format(exp_name), ax=ax, color=nextval) exp_data[i].plot.scatter(x='Time', y=dependent, ax=ax, color=nextval, label='{0} Measured'.format(exp_name)) result.append((fig, ax)) return result