Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Barplots and Replicates with Simulation data #214

Merged
merged 15 commits into from
Jan 23, 2020
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ ignored-classes=optparse.Values,thread._local,_thread._local
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis). It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=
ignored-modules=matplotlib

# Show a hint with possible names when a member name was not found. The aspect
# of finding the hint is based on edit distance.
Expand Down
12 changes: 9 additions & 3 deletions petab/visualize/helper_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,14 +221,16 @@ def create_dataset_id_list(simcond_id_list,
return exp_data, dataset_id_list, legend_dict


def create_figure(uni_plot_ids):
def create_figure(uni_plot_ids, plots_to_file):
"""
Helper function for plotting data and simulations, open figure and axes

Parameters
----------
uni_plot_ids: ndarray
Array with unique plot indices
plots_to_file: bool
Indicator if plots are saved to file

Returns
-------
Expand All @@ -248,6 +250,11 @@ def create_figure(uni_plot_ids):
# Set Colormap
sns.set(style="ticks", palette="colorblind")

# Check if plots are saved to file and return single subplot axis
if plots_to_file:
fig, ax = plt.subplots(1, 1, squeeze=False)
return fig, ax, 1, 1

# Initiate subplots
num_subplot = len(uni_plot_ids)

Expand Down Expand Up @@ -392,8 +399,7 @@ def get_data_to_plot(vis_spec: pd.DataFrame,
i_visu_spec: int,
col_id: str):
"""
group the data, which should be plotted and save it in pd.dataframe called
'ms'.
group the data, which should be plotted and return it as dataframe.

Parameters:
vis_spec:
Expand Down
91 changes: 59 additions & 32 deletions petab/visualize/plot_data_and_simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import petab

from typing import Union, Optional, List
import matplotlib.pyplot as plt


IdsList = List[str]
NumList = List[int]
Expand All @@ -16,14 +18,15 @@
def plot_data_and_simulation(
exp_data: Union[str, pd.DataFrame],
exp_conditions: Union[str, pd.DataFrame],
visualization_file_path: str = '',
vis_spec: Optional[Union[str, pd.DataFrame]] = '',
sim_data: Optional[Union[str, pd.DataFrame]] = None,
dataset_id_list: Optional[List[IdsList]] = None,
sim_cond_id_list: Optional[List[IdsList]] = None,
sim_cond_num_list: Optional[List[NumList]] = None,
observable_id_list: Optional[List[IdsList]] = None,
observable_num_list: Optional[List[NumList]] = None,
plotted_noise: Optional[str] = 'MeanAndSD'):
plotted_noise: Optional[str] = 'MeanAndSD',
subplot_file_path: str = ''):
"""
Main function for plotting data and simulations.

Expand All @@ -38,42 +41,47 @@ def plot_data_and_simulation(
----------
exp_data:
measurement DataFrame in the PEtab format or path to the data file.
exp_conditions: str
exp_conditions:
condition DataFrame in the PEtab format or path to the condition file.
visualization_file_path: str (optional)
Path to the visualization specification file.
sim_data: str (optional)
vis_spec: str or pandas.Dataframe (optional)
Visualization specification DataFrame in the PEtab format or path to
visualization file.
sim_data:
simulation DataFrame in the PEtab format
or path to the simulation output data file.
dataset_id_list: list (optional)
dataset_id_list:
A list of lists. Each sublist corresponds to a plot, each subplot
contains the datasetIds for this plot.
Only to be used if no visualization file was available.
sim_cond_id_list: list (optional)
sim_cond_id_list:
A list of lists. Each sublist corresponds to a plot, each subplot
contains the simulationConditionIds for this plot.
Only to be used if no visualization file was available.
sim_cond_num_list: list (optional)
sim_cond_num_list:
A list of lists. Each sublist corresponds to a plot, each subplot
contains the numbers corresponding to the simulationConditionIds for
this plot.
Only to be used if no visualization file was available.
observable_id_list: list (optional)
observable_id_list:
A list of lists. Each sublist corresponds to a plot, each subplot
contains the observableIds for this plot.
Only to be used if no visualization file was available.
observable_num_list: list (optional)
observable_num_list:
A list of lists. Each sublist corresponds to a plot, each subplot
contains the numbers corresponding to the observableIds for
this plot.
Only to be used if no visualization file was available.
plotted_noise: str (optional)
plotted_noise:
String indicating how noise should be visualized:
['MeanAndSD' (default), 'MeanAndSEM', 'replicate', 'provided']
subplot_file_path:
String which is taken as file path to which single subplots are saved.
PlotIDs will be taken as file names.

Returns
-------
ax: Axis object of the created plot.
None: In case subplots are save to file
"""

if isinstance(exp_data, str):
Expand All @@ -84,18 +92,20 @@ def plot_data_and_simulation(
exp_conditions = petab.get_condition_df(exp_conditions)

# import visualization specification, if file was specified
if visualization_file_path != '':
vis_spec = petab.get_visualization_df(visualization_file_path)
else:
# create them based on simulation conditions
vis_spec, exp_data = get_default_vis_specs(exp_data,
exp_conditions,
dataset_id_list,
sim_cond_id_list,
sim_cond_num_list,
observable_id_list,
observable_num_list,
plotted_noise)
if isinstance(vis_spec, str):
if vis_spec != '':
vis_spec = pd.read_csv(vis_spec, sep="\t",
index_col=None)
else:
# create them based on simulation conditions
vis_spec, exp_data = get_default_vis_specs(exp_data,
exp_conditions,
dataset_id_list,
sim_cond_id_list,
sim_cond_num_list,
observable_id_list,
observable_num_list,
plotted_noise)

# import simulation file, if file was specified
if isinstance(sim_data, str):
Expand All @@ -104,14 +114,25 @@ def plot_data_and_simulation(
# get unique plotIDs
uni_plot_ids, _ = np.unique(vis_spec.plotId, return_index=True)

fig, ax, num_row, num_col = create_figure(uni_plot_ids)
# Switch saving plots to file on or get axes
plots_to_file = False
if subplot_file_path != '':
plots_to_file = True
else:
fig, ax, _, num_col = create_figure(uni_plot_ids, plots_to_file)

# loop over unique plotIds
for i_plot_id, var_plot_id in enumerate(uni_plot_ids):

# setting axis indices
i_row = int(np.ceil((i_plot_id + 1) / num_col)) - 1
i_col = int(((i_plot_id + 1) - i_row * num_col)) - 1
if plots_to_file:
fig, ax, _, num_col = create_figure(uni_plot_ids,
plots_to_file)
i_row = 0
i_col = 0
else:
# setting axis indices
i_row = int(np.ceil((i_plot_id + 1) / num_col)) - 1
i_col = int(((i_plot_id + 1) - i_row * num_col)) - 1

# get indices for specific plotId
ind_plot = (vis_spec['plotId'] == var_plot_id)
Expand All @@ -122,12 +143,18 @@ def plot_data_and_simulation(
ax = handle_dataset_plot(i_visu_spec, ind_plot, ax, i_row, i_col,
exp_data, exp_conditions, vis_spec,
sim_data)
if plots_to_file:
sns.despine()
plt.xticks(rotation=45, ha="right")
plt.tight_layout()
plt.savefig(f'{subplot_file_path}/{var_plot_id}.png')
plt.close()

# finalize figure
fig.tight_layout()
sns.despine()

return ax
if not plots_to_file:
fig.tight_layout()
sns.despine()
return ax


def plot_petab_problem(petab_problem: petab.problem.Problem,
Expand Down
39 changes: 22 additions & 17 deletions petab/visualize/plotting_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,42 +72,42 @@ def plot_lowlevel(vis_spec: pd.DataFrame,
# add xOffset
conditions = conditions + vis_spec.xOffset[i_visu_spec]

# TODO sort mean and sd/sem by x values (as for simulatedData below)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

# to avoid crazy lineplots in case x values are not sorted by default.
# cf issue #207
#
# construct errorbar-plots: Mean and standard deviation
label_base = vis_spec[ind_plot].legendEntry[i_visu_spec]
if vis_spec.plotTypeData[i_visu_spec] == 'MeanAndSD':
p = ax[axx, axy].errorbar(
conditions, ms['mean'], ms['sd'], linestyle='-.', marker='.',
label=label_base)
colors = p[0].get_color()
if plot_sim:
ax[axx, axy].plot(
conditions, ms['sim'], linestyle='-', marker='o',
label=label_base + " simulation", color=colors)

# construct errorbar-plots: Mean and standard error of mean
elif vis_spec.plotTypeData[i_visu_spec] == 'MeanAndSEM':
ax[axx, axy].errorbar(
p = ax[axx, axy].errorbar(
conditions, ms['mean'], ms['sem'], linestyle='-.', marker='.',
label=label_base)

# plotting all measurement data
elif vis_spec.plotTypeData[i_visu_spec] == 'replicate':
for ii in range(0, len(ms['repl'])):
for k in range(0, len(ms.repl[ii])):
ax[axx, axy].plot(
conditions[conditions.index.values[ii]],
ms.repl[ii][ms.repl[ii].index.values[k]], 'x')
p = ax[axx, axy].plot(
conditions[conditions.index.values],
ms.repl[ms.repl.index.values], 'x',
label=label_base)

# construct errorbar-plots: Mean and noise provided in measurement file
elif vis_spec.plotTypeData[i_visu_spec] == 'provided':
p = ax[axx, axy].errorbar(
conditions, ms['mean'], ms['noise_model'],
linestyle='-.', marker='.', label=label_base)
colors = p[0].get_color()
if plot_sim:
ax[axx, axy].plot(
conditions, ms['sim'], linestyle='-', marker='o',
label=label_base + " simulation", color=colors)
# construct simulation plot
colors = p[0].get_color()
if plot_sim:
xs, ys = zip(*sorted(zip(conditions, ms['sim'])))
ax[axx, axy].plot(
xs, ys, linestyle='-', marker='o',
label=label_base + " simulation", color=colors)

ax[axx, axy].legend()
ax[axx, axy].set_title(vis_spec.plotName[i_visu_spec])
Expand All @@ -116,7 +116,12 @@ def plot_lowlevel(vis_spec: pd.DataFrame,

x_name = vis_spec[ind_plot].legendEntry[i_visu_spec]

ax[axx, axy].bar(x_name, ms['mean'], yerr=ms['sd'])
p = ax[axx, axy].bar(x_name, ms['mean'], yerr=ms['sd'])
ax[axx, axy].set_title(vis_spec.plotName[i_visu_spec])

if plot_sim:
colors = p[0].get_facecolor()
ax[axx, axy].bar(x_name + " simulation", ms['sim'], color='white',
edgecolor=colors)

return ax