Skip to content

Commit 248bf73

Browse files
plakrisenkoMerktSimonPaulJonasJosterikadudki
authored
Visualization refactoring (#58)
* new structure draft for visualization * subplot part to figure * single plot knows its vis_spec * VisualizationSpec * not finished FirstPlot * SinglePlot * add test for VisualizationSpec * fix VisualizationSepc test * data provider and data_to_plot * add from_df method on VisulaizationSpec * full vis_spec class * figure class * basic test * typing, tests and fixes for VisualizationSpec.from_df() * add todo * some cleanup * DataToPlot, VisSpecParser * plotting from sim_cond_num_list and observable_num_list * plotting simulations * plotting only simulations * bar plot and plotting from vis spe with datasetids * colorblind palette set via matplotlib * provided noise and save to file * offsets * abc inheritance and classmethod decorator * bar plot legends and tick labels * create dataset_id list * minimal vis spec * replicates, seaborn dependancy removed * docstrings, wrappers, minimal data file * *_num_list options are not supported anymore * update tests * saving vis spec to a file * documentation update * further tidying up * tight layout * plot petab problem * add 'will be removed in future releases' warning * wrappers in tests * remove TypedDict for now * take into account DeprecationWarnings * checking for datasetId column both in measurement_df and simulation_df * vis spec expansion reworked, fixes #28 * allow setting axes limits * Update petab/visualize/helper_functions.py Co-authored-by: ErikaDudkin <[email protected]> * Update petab/visualize/helper_functions.py Co-authored-by: ErikaDudkin <[email protected]> * Update petab/visualize/plotting.py Co-authored-by: ErikaDudkin <[email protected]> * Update petab/visualize/plotting.py Co-authored-by: ErikaDudkin <[email protected]> * Update petab/visualize/plotting.py Co-authored-by: ErikaDudkin <[email protected]> * docstrings * warning message * Apply suggestions from code review Co-authored-by: ErikaDudkin <[email protected]> * Apply suggestions from code review Co-authored-by: ErikaDudkin <[email protected]> * docstrings * sphinx env variable * documentation Co-authored-by: MerktSimon <[email protected]> Co-authored-by: Paul Jonas Jost <[email protected]> Co-authored-by: ErikaDudkin <[email protected]>
1 parent 74838ec commit 248bf73

File tree

11 files changed

+1938
-12
lines changed

11 files changed

+1938
-12
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
plotId xOffset yScale
2+
figure_b 100 log
3+
figure_a 500 lin

petab/C.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,23 @@
124124
Y_SCALE = 'yScale'
125125
LEGEND_ENTRY = 'legendEntry'
126126

127+
VISUALIZATION_DF_REQUIRED_COLS = [PLOT_ID]
128+
129+
VISUALIZATION_DF_OPTIONAL_COLS = [
130+
PLOT_NAME, PLOT_TYPE_SIMULATION, PLOT_TYPE_DATA, X_VALUES, X_OFFSET,
131+
X_LABEL, X_SCALE, Y_VALUES, Y_OFFSET, Y_LABEL, Y_SCALE, LEGEND_ENTRY,
132+
DATASET_ID]
133+
134+
VISUALIZATION_DF_COLS = [
135+
*VISUALIZATION_DF_REQUIRED_COLS, *VISUALIZATION_DF_OPTIONAL_COLS]
136+
137+
VISUALIZATION_DF_SUBPLOT_LEVEL_COLS = [
138+
PLOT_ID, PLOT_NAME, PLOT_TYPE_SIMULATION, PLOT_TYPE_DATA,
139+
X_LABEL, X_SCALE, Y_LABEL, Y_SCALE]
140+
141+
VISUALIZATION_DF_SINGLE_PLOT_LEVEL_COLS = [
142+
X_VALUES, X_OFFSET, Y_VALUES, Y_OFFSET, LEGEND_ENTRY, DATASET_ID]
143+
127144
LINE_PLOT = 'LinePlot'
128145
BAR_PLOT = 'BarPlot'
129146
SCATTER_PLOT = 'ScatterPlot'

petab/visualize/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,16 @@
1010
from .plot_data_and_simulation import (plot_data_and_simulation,
1111
plot_petab_problem,
1212
plot_measurements_by_observable,
13+
plot_without_vis_spec,
14+
plot_with_vis_spec,
15+
plot_problem,
1316
save_vis_spec)
1417

1518
__all__ = ["plot_data_and_simulation",
1619
"plot_petab_problem",
1720
"plot_measurements_by_observable",
21+
"plot_without_vis_spec",
22+
"plot_with_vis_spec",
23+
"plot_problem",
1824
"save_vis_spec"
1925
]

petab/visualize/helper_functions.py

Lines changed: 107 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
from typing import Dict, List, Optional, Tuple, Union
2222

23-
sns.set()
23+
# sns.set() This messes up plotting settings if one just imports this file
2424

2525
# for typehints
2626
IdsList = List[str]
@@ -42,14 +42,16 @@ def import_from_files(
4242
"""
4343
Helper function for plotting data and simulations, which imports data
4444
from PEtab files. If `visualization_file_path` is not provided, the
45-
visualisation specification DataFrame will be generated automatically.
45+
visualization specification DataFrame will be generated automatically.
4646
4747
For documentation, see main function plot_data_and_simulation()
4848
4949
Returns:
5050
A tuple of experimental data, experimental conditions,
5151
visualization specification and simulation data DataFrames.
5252
"""
53+
warnings.warn("This function will be removed in future releases. ",
54+
DeprecationWarning)
5355

5456
# import measurement data and experimental condition
5557
exp_data = petab.get_measurement_df(data_file_path)
@@ -95,6 +97,8 @@ def check_vis_spec_consistency(
9597
group_by:
9698
Specifies the grouping of data to plot.
9799
"""
100+
warnings.warn("This function will be removed in future releases. ",
101+
DeprecationWarning)
98102

99103
# We have no vis_spec file. Check how data should be grouped
100104
group_by = ''
@@ -187,6 +191,9 @@ def create_dataset_id_list(
187191
188192
For additional documentation, see main function plot_data_and_simulation()
189193
"""
194+
warnings.warn("This function will be removed in future releases. ",
195+
DeprecationWarning)
196+
190197
# create a column of dummy datasetIDs and legend entries: preallocate
191198
dataset_id_column = []
192199
legend_dict = {}
@@ -197,7 +204,7 @@ def create_dataset_id_list(
197204
tmp_obs = list(exp_data[OBSERVABLE_ID])
198205
for ind, cond_id in enumerate(tmp_simcond):
199206
# create and add dummy datasetID
200-
dataset_id = tmp_simcond[ind] + '_' + tmp_obs[ind]
207+
dataset_id = cond_id + '_' + tmp_obs[ind]
201208
dataset_id_column.append(dataset_id)
202209

203210
# create nicer legend entries from condition names instead of IDs
@@ -272,6 +279,77 @@ def create_dataset_id_list(
272279
return exp_data, dataset_id_list, legend_dict, yvalues_dict
273280

274281

282+
def generate_dataset_id_col(exp_data: pd.DataFrame) -> List[str]:
283+
"""
284+
generate DATASET_ID column from condition_ids and observable_ids
285+
286+
Parameters
287+
----------
288+
exp_data
289+
290+
Returns
291+
-------
292+
293+
"""
294+
295+
# create a column of dummy datasetIDs and legend entries: preallocate
296+
dataset_id_column = []
297+
298+
# loop over experimental data table, create datasetId for each entry
299+
tmp_simcond = list(exp_data[SIMULATION_CONDITION_ID])
300+
tmp_obs = list(exp_data[OBSERVABLE_ID])
301+
302+
for ind, cond_id in enumerate(tmp_simcond):
303+
# create and add dummy datasetID
304+
dataset_id = cond_id + '_' + tmp_obs[ind]
305+
dataset_id_column.append(dataset_id)
306+
307+
return dataset_id_column
308+
309+
310+
def create_dataset_id_list_new(df: pd.DataFrame,
311+
group_by: str,
312+
id_list: List[IdsList]
313+
) -> List[IdsList]:
314+
"""
315+
Create dataset id list.
316+
317+
Parameters:
318+
df: measurements or simulations df
319+
group_by: defines grouping of data to plot
320+
id_list:
321+
322+
Returns:
323+
A list of datasetIds
324+
325+
"""
326+
if DATASET_ID not in df.columns:
327+
raise ValueError(f'{DATASET_ID} column must be in exp_data DataFrame')
328+
329+
dataset_id_list = []
330+
331+
if group_by == 'simulation':
332+
groupping_col = SIMULATION_CONDITION_ID
333+
elif group_by == 'observable':
334+
groupping_col = OBSERVABLE_ID
335+
if id_list is None:
336+
# this is the default case. If no grouping is specified,
337+
# all observables are plotted. One observable per plot.
338+
unique_obs_list = df[OBSERVABLE_ID].unique()
339+
id_list = [[obs_id] for obs_id in unique_obs_list]
340+
else:
341+
raise ValueError
342+
343+
for sublist in id_list:
344+
plot_id_list = []
345+
for cond_id in sublist:
346+
plot_id_list.extend(list(
347+
df[df[groupping_col] == cond_id][
348+
DATASET_ID].unique()))
349+
dataset_id_list.append(plot_id_list)
350+
return dataset_id_list
351+
352+
275353
def create_figure(
276354
uni_plot_ids: np.ndarray,
277355
plots_to_file: bool) -> Tuple[plt.Figure,
@@ -292,6 +370,8 @@ def create_figure(
292370
fig: Figure object of the created plot.
293371
ax: Axis object of the created plot.
294372
"""
373+
warnings.warn("This function will be removed in future releases. ",
374+
DeprecationWarning)
295375

296376
# Set Options for plots
297377
# possible options: see: plt.rcParams.keys()
@@ -415,6 +495,8 @@ def get_vis_spec_dependent_columns_dict(
415495
columns PLOT_ID, DATASET_ID, LEGEND_ENTRY, Y_VALUES for visualization
416496
specification file.
417497
"""
498+
warnings.warn("This function will be removed in future releases. ",
499+
DeprecationWarning)
418500

419501
# check consistency of settings
420502
group_by = check_vis_spec_consistency(
@@ -533,6 +615,9 @@ def create_or_update_vis_spec(
533615
A tuple of visualization specification DataFrame and experimental
534616
DataFrame.
535617
"""
618+
warnings.warn("This function will be removed in future releases. ",
619+
DeprecationWarning)
620+
536621
if vis_spec is None:
537622
# create dataframe
538623
exp_data, columns_dict = \
@@ -572,7 +657,9 @@ def create_or_update_vis_spec(
572657
vis_spec = expand_vis_spec_settings(vis_spec, columns_dict)
573658

574659
# if dataset_id is there, then nothing to expand?
575-
vis_spec[PLOT_TYPE_DATA] = plotted_noise
660+
661+
if PLOT_TYPE_DATA not in vis_spec.columns:
662+
vis_spec[PLOT_TYPE_DATA] = plotted_noise
576663

577664
# check columns, and add non-mandatory default columns
578665
vis_spec = check_ex_visu_columns(vis_spec, exp_data, exp_conditions)
@@ -589,6 +676,9 @@ def check_ex_visu_columns(vis_spec: pd.DataFrame,
589676
Returns:
590677
Updated visualization specification DataFrame
591678
"""
679+
warnings.warn("This function will be removed in future releases. ",
680+
DeprecationWarning)
681+
592682
if PLOT_NAME not in vis_spec.columns:
593683
vis_spec[PLOT_NAME] = ''
594684
if PLOT_TYPE_SIMULATION not in vis_spec.columns:
@@ -658,6 +748,9 @@ def check_ex_exp_columns(
658748
A tuple of experimental DataFrame, list of datasetIds and
659749
dictionary of plot legends, corresponding to the datasetIds
660750
"""
751+
warnings.warn("This function will be removed in future releases. ",
752+
DeprecationWarning)
753+
661754
data_type = MEASUREMENT
662755
if sim:
663756
data_type = SIMULATION
@@ -692,6 +785,7 @@ def check_ex_exp_columns(
692785
value='')
693786
legend_dict = {}
694787
if DATASET_ID not in exp_data.columns:
788+
# TODO: ?
695789
if dataset_id_list is not None:
696790
exp_data.insert(loc=4, column=DATASET_ID,
697791
value=dataset_id_list)
@@ -712,6 +806,7 @@ def check_ex_exp_columns(
712806
sim_cond_id_list, sim_cond_num_list, observable_id_list,
713807
observable_num_list, exp_data, exp_conditions, group_by)
714808

809+
# if DATASET_ID is in exp_data.columns, legend dict will be empty
715810
return exp_data, dataset_id_list, legend_dict
716811

717812

@@ -723,6 +818,9 @@ def handle_dataset_plot(plot_spec: pd.Series,
723818
"""
724819
Handle dataset plot
725820
"""
821+
warnings.warn("This function will be removed in future releases. ",
822+
DeprecationWarning)
823+
726824
# get datasetID and independent variable of first entry of plot1
727825
dataset_id = plot_spec[DATASET_ID]
728826
indep_var = plot_spec[X_VALUES]
@@ -795,6 +893,9 @@ def matches_plot_spec(df: pd.DataFrame,
795893
Boolean series that can be used for subsetting of the passed
796894
dataframe
797895
"""
896+
warnings.warn("This function will be removed in future releases. ",
897+
DeprecationWarning)
898+
798899
subset = (
799900
(df[col_id] == x_value) &
800901
(df[DATASET_ID] == plot_spec[DATASET_ID])
@@ -843,6 +944,8 @@ def get_data_to_plot(plot_spec: pd.Series,
843944
Contains the data which should be plotted
844945
(Mean and Std)
845946
"""
947+
warnings.warn("This function will be removed in future releases. ",
948+
DeprecationWarning)
846949

847950
# create empty dataframe for means and SDs
848951
data_to_plot = pd.DataFrame(

0 commit comments

Comments
 (0)