diff --git a/basico/model_info.py b/basico/model_info.py index ba66ba8..3056c26 100644 --- a/basico/model_info.py +++ b/basico/model_info.py @@ -5113,13 +5113,24 @@ def _get_cn_string(cn): return cn.getString() return str(cn) -def _collect_data(names=None, cns=None, **kwargs): +def collect_data(names=None, cns=None, **kwargs): """Collects data from the model, returning it as dataframe - :param names: list of names of elements to return + :param names: list of display names of elements to return :type names: list or None + :param cns: list of common names of references for which to return the results :type cns: list or None + + :param kwargs: optional parameters + + - | `model`: to specify the data model to be used (if not specified + | the one from :func:`.get_current_model` will be taken) + + - `preserve_names`: if set to True, the names will be preserved in the output + otherwise the display name of the object will be used. Default is True + for names. It does not apply to cns. + :return: data frame with the results :rtype: pd.DataFrame """ @@ -5143,8 +5154,18 @@ def _collect_data(names=None, cns=None, **kwargs): data.append({'name': obj.getObjectDisplayName(), 'value': value}) if names: + preseve_names = kwargs.get('preserve_names', True) for name in names: - obj = model.findObjectByDisplayName(name) + obj = None + if name == '[Time]': + # workaround for a bug in the python bindings + # where Time would always return the models time instead of potentially + # existing species called Time + obj = model.getModel().getMetabolite(name[1:-1]) + + if obj is None: + obj = model.findObjectByDisplayName(name) + if obj is None: # couldn't find that object in the model logger.warning('No object for name: {0}'.format(name)) @@ -5165,7 +5186,7 @@ def _collect_data(names=None, cns=None, **kwargs): else: value = None - data.append({'name': obj.getObjectDisplayName(), 'value': value}) + data.append({'name': name if preseve_names else obj.getObjectDisplayName(), 'value': value}) return pandas.DataFrame(data=data).set_index('name') diff --git a/basico/task_parameterestimation.py b/basico/task_parameterestimation.py index 33e6f4b..d490f2d 100644 --- a/basico/task_parameterestimation.py +++ b/basico/task_parameterestimation.py @@ -1300,7 +1300,7 @@ def get_simulation_results(values_only=False, update_parameters=True, **kwargs): # run steady state steady_state_task.initializeRaw(COPASI.CCopasiTask.OUTPUT_UI) steady_state_task.processRaw(True) - data = basico.model_info._collect_data(cns=mapping[mapping.type == 'dependent']['cn'].to_list()).transpose() + data = basico.model_info.collect_data(cns=mapping[mapping.type == 'dependent']['cn'].to_list()).transpose() for j in range(1, num_independent_points): container.applyInitialValues() @@ -1314,7 +1314,7 @@ def get_simulation_results(values_only=False, update_parameters=True, **kwargs): _update_fit_parameters_from(dm, solution, exp_name) steady_state_task.processRaw(True) - new_row = basico.model_info._collect_data( + new_row = basico.model_info.collect_data( cns=mapping[mapping.type == 'dependent']['cn'].to_list()).transpose() data = pd.concat([data, new_row], ignore_index=True) diff --git a/tests/test_basico_info.py b/tests/test_basico_info.py index 6496539..d3a26a3 100644 --- a/tests/test_basico_info.py +++ b/tests/test_basico_info.py @@ -181,7 +181,7 @@ def test_collect_data(self): mod = basico.get_current_model().getModel() assert (isinstance(mod, COPASI.CModel)) mod.applyInitialValues() - data = basico.model_info._collect_data(cns=[ + data = basico.model_info.collect_data(cns=[ 'CN=Root,Model=The Brusselator,Reference=Time', 'CN=Root,Model=The Brusselator,Vector=Compartments[compartment],Reference=InitialVolume', 'CN=Root,Model=The Brusselator,Vector=Compartments[compartment],Reference=Rate', @@ -200,7 +200,7 @@ def test_collect_data(self): 'CN=Root,Model=The Brusselator,Vector=Reactions[R1],ParameterGroup=Parameters,Parameter=k1,Reference=Value' ]) - data2 = basico.model_info._collect_data(names=[ + data2 = basico.model_info.collect_data(names=[ 'Time', 'Compartments[compartment].InitialVolume', 'Compartments[compartment].Rate', @@ -643,6 +643,12 @@ def test_multiple_elements_with_same_name(self): result2 = basico.run_time_course_with_output(['Time', '[Time]']) self.assertListEqual(result2.columns.tolist(), ['Time', '[Time]']) + # test using collect: + data = basico.model_info.collect_data(names=['Time', '[Time]']) + self.assertTrue(data is not None) + self.assertListEqual(data.index.to_list(), ['Time', '[Time]']) + + names = basico.model_info._get_name_map(dm) self.assertGreater(len(names['Time']), 1) @@ -651,6 +657,7 @@ def test_multiple_elements_with_same_name(self): names2 = basico.model_info._get_name_map(dm) self.assertEqual(len(names2['Time']), 1) + basico.remove_datamodel(dm);