Skip to content

Commit 8ba3ab5

Browse files
authored
Release 0.1.23
Merge pull request #105 from PEtab-dev/release_0.1.23
2 parents fde0bf6 + 9b6633a commit 8ba3ab5

File tree

13 files changed

+248
-118
lines changed

13 files changed

+248
-118
lines changed

.github/workflows/ci_tests.yml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,18 @@ jobs:
2323
with:
2424
python-version: ${{ matrix.python-version }}
2525

26+
- name: Get pip cache directory
27+
id: pip_cache_dir
28+
run: |
29+
echo "::set-output name=dir::$(pip cache dir)"
30+
2631
- name: Cache
2732
uses: actions/cache@v1
2833
with:
29-
path: ~/.cache/pip
30-
key: ${{ runner.os }}-${{ hashFiles('**/.ci_pip_reqs.txt') }}-${{ hashFiles('**/setup.py') }}
34+
path: ${{ steps.pip_cache_dir.outputs.dir }}
35+
key: ${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('**/.ci_pip_reqs.txt') }}-${{ hashFiles('**/setup.py') }}
3136
restore-keys: |
32-
${{ runner.os }}-
37+
${{ runner.os }}-${{ matrix.python-version }}-
3338
3439
- name: Install dependencies
3540
run: |

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,22 @@
22

33
## 0.1 series
44

5+
### 0.1.23
6+
7+
* Added command line interface for plotting by @dweindl in
8+
https://github.com/PEtab-dev/libpetab-python/pull/98
9+
* Fixed petab.visualize.data_overview.create_report by @dweindl in
10+
https://github.com/PEtab-dev/libpetab-python/pull/96,
11+
https://github.com/PEtab-dev/libpetab-python/pull/104
12+
* Vis: Fixed cropped errorbars by @dweindl in
13+
https://github.com/PEtab-dev/libpetab-python/pull/99
14+
* Fixed pandas deprecation warning by @dweindl in
15+
https://github.com/PEtab-dev/libpetab-python/pull/103
16+
17+
... and other changes by @plakrisenko, @dweindl
18+
19+
**Full Changelog**: https://github.com/PEtab-dev/libpetab-python/compare/v0.1.22...v0.1.23
20+
521
### 0.1.22
622

723
* Allow zero bounds for log parameters by @FFroehlich in

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
include petab/petab_schema.yaml
2+
recursive-include petab/visualize/templates

doc/conf.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
'sphinx.ext.autosummary',
5151
'sphinx.ext.intersphinx',
5252
'sphinx.ext.viewcode',
53-
'recommonmark',
53+
'myst_parser',
5454
'sphinx_markdown_tables',
5555
'nbsphinx',
5656
]
@@ -99,10 +99,6 @@
9999
# ignore numpy warnings
100100
warnings.filterwarnings("ignore", message="numpy.dtype size changed")
101101
warnings.filterwarnings("ignore", message="numpy.ufunc size changed")
102-
# ignore recommonmark warnings
103-
# https://github.com/readthedocs/recommonmark/issues/177
104-
warnings.filterwarnings("ignore",
105-
message="Container node skipped: type=document")
106102

107103
# -- Options for HTML output -------------------------------------------------
108104

petab/core.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ def concat_tables(
209209
if isinstance(tmp_df, (str, Path)):
210210
tmp_df = file_parser(tmp_df)
211211

212-
df = df.append(tmp_df, sort=False,
212+
df = pd.concat([df, tmp_df], sort=False,
213213
ignore_index=isinstance(tmp_df.index, pd.RangeIndex))
214214

215215
return df

petab/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
"""PEtab library version"""
2-
__version__ = '0.1.22'
2+
__version__ = '0.1.23'

petab/visualize/cli.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
"""Command-line interface for visualization."""
2+
import argparse
3+
from pathlib import Path
4+
5+
import matplotlib.pyplot as plt
6+
7+
from .plot_data_and_simulation import plot_problem
8+
from .. import Problem, get_simulation_df, get_visualization_df
9+
10+
11+
def _parse_cli_args():
12+
"""Parse command-line arguments."""
13+
14+
parser = argparse.ArgumentParser(
15+
description='Create PEtab visualizations.')
16+
17+
parser.add_argument('-y', '--yaml', dest='yaml_file_name', required=True,
18+
help='PEtab problem YAML filename')
19+
parser.add_argument('-s', '--simulations', dest='simulation_file_name',
20+
required=False,
21+
help='PEtab simulation filename')
22+
parser.add_argument('-o', '--output-directory', dest='output_directory',
23+
required=True, help='Output directory')
24+
parser.add_argument('-v', '--visualizations', required=False,
25+
dest='visualization_file_name',
26+
help='PEtab visualization specification filename')
27+
parser.add_argument('--style', required=False,
28+
dest='style_file_name',
29+
help='Matplotlib style file')
30+
return parser.parse_args()
31+
32+
33+
def _petab_visualize_main():
34+
"""Entrypoint for visualization command-line interface."""
35+
args = _parse_cli_args()
36+
37+
petab_problem = Problem.from_yaml(args.yaml_file_name)
38+
simulations_df = None
39+
if args.simulation_file_name:
40+
simulations_df = get_simulation_df(args.simulation_file_name)
41+
42+
if args.visualization_file_name:
43+
petab_problem.visualization_df = get_visualization_df(
44+
args.visualization_file_name)
45+
46+
if args.style_file_name:
47+
plt.style.use(args.style_file_name)
48+
49+
# Avoid errors when plotting without X server
50+
plt.switch_backend('agg')
51+
52+
Path(args.output_directory).mkdir(exist_ok=True, parents=True)
53+
54+
plot_problem(
55+
petab_problem=petab_problem,
56+
simulations_df=simulations_df,
57+
subplot_dir=args.output_directory,
58+
)

petab/visualize/data_overview.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ def create_report(
3131
template_file = "report.html"
3232

3333
data_per_observable = get_data_per_observable(problem.measurement_df)
34-
num_conditions = (len(problem.condition_df.columns)
35-
- 1 * (CONDITION_NAME in problem.condition_df.columns))
34+
num_conditions = len(problem.condition_df.index)
3635

3736
# Setup template engine
3837
import jinja2
@@ -55,17 +54,18 @@ def get_data_per_observable(measurement_df: pd.DataFrame) -> pd.DataFrame:
5554
Arguments:
5655
measurement_df: PEtab measurement data frame
5756
Returns:
58-
data_per_observable:
59-
Pivot table with number of data points per observable and condition
57+
Pivot table with number of data points per observable and condition
6058
"""
6159

6260
my_measurements = measurement_df.copy()
63-
64-
my_measurements[PREEQUILIBRATION_CONDITION_ID].fillna('', inplace=True)
61+
index = [SIMULATION_CONDITION_ID]
62+
if PREEQUILIBRATION_CONDITION_ID in my_measurements:
63+
my_measurements[PREEQUILIBRATION_CONDITION_ID].fillna('', inplace=True)
64+
index.append(PREEQUILIBRATION_CONDITION_ID)
6565

6666
data_per_observable = pd.pivot_table(
6767
my_measurements, values=MEASUREMENT, aggfunc='count',
68-
index=[SIMULATION_CONDITION_ID, PREEQUILIBRATION_CONDITION_ID],
68+
index=index,
6969
columns=[OBSERVABLE_ID], fill_value=0)
7070

7171
# Add row and column sums

petab/visualize/plotter.py

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,26 @@ class MPLPlotter(Plotter):
4545
def __init__(self, figure: Figure, data_provider: DataProvider):
4646
super().__init__(figure, data_provider)
4747

48+
@staticmethod
49+
def _error_column_for_plot_type_data(plot_type_data: str) -> Optional[str]:
50+
"""Translate PEtab plotTypeData value to column name of internal
51+
data representation
52+
53+
Parameters
54+
----------
55+
plot_type_data: PEtab plotTypeData value
56+
Returns
57+
-------
58+
Name of corresponding column
59+
"""
60+
if plot_type_data == MEAN_AND_SD:
61+
return 'sd'
62+
if plot_type_data == MEAN_AND_SEM:
63+
return 'sem'
64+
if plot_type_data == PROVIDED:
65+
return 'noise_model'
66+
return None
67+
4868
def generate_lineplot(self, ax: 'matplotlib.pyplot.Axes',
4969
dataplot: DataPlot,
5070
plotTypeData: str) -> None:
@@ -67,14 +87,7 @@ def generate_lineplot(self, ax: 'matplotlib.pyplot.Axes',
6787
measurements_to_plot, simulations_to_plot = \
6888
self.data_provider.get_data_to_plot(dataplot,
6989
plotTypeData == PROVIDED)
70-
noise_col = None
71-
# set type of noise
72-
if plotTypeData == MEAN_AND_SD:
73-
noise_col = 'sd'
74-
elif plotTypeData == MEAN_AND_SEM:
75-
noise_col = 'sem'
76-
elif plotTypeData == PROVIDED:
77-
noise_col = 'noise_model'
90+
noise_col = self._error_column_for_plot_type_data(plotTypeData)
7891

7992
label_base = dataplot.legendEntry
8093

@@ -155,14 +168,7 @@ def generate_barplot(self, ax: 'matplotlib.pyplot.Axes',
155168
Specifies how replicates should be handled.
156169
"""
157170
# TODO: plotTypeData == REPLICATE?
158-
# set type of noise
159-
noise_col = None
160-
if plotTypeData == MEAN_AND_SD:
161-
noise_col = 'sd'
162-
elif plotTypeData == MEAN_AND_SEM:
163-
noise_col = 'sem'
164-
elif plotTypeData == PROVIDED:
165-
noise_col = 'noise_model'
171+
noise_col = self._error_column_for_plot_type_data(plotTypeData)
166172

167173
simu_colors = None
168174
measurements_to_plot, simulations_to_plot = \
@@ -222,7 +228,7 @@ def generate_scatterplot(self, ax: 'matplotlib.pyplot.Axes',
222228
ax.scatter(measurements_to_plot.data_to_plot['mean'],
223229
simulations_to_plot.data_to_plot['mean'],
224230
label=getattr(dataplot, LEGEND_ENTRY))
225-
ax = self._square_plot_equal_ranges(ax)
231+
self._square_plot_equal_ranges(ax)
226232

227233
def generate_subplot(self,
228234
ax,
@@ -278,11 +284,10 @@ def generate_subplot(self,
278284
elif subplot.xScale == 'order':
279285
ax.set_xscale("linear")
280286
# check if conditions are monotone decreasing or increasing
281-
if np.all(
282-
np.diff(subplot.conditions) < 0): # monot. decreasing
283-
xlabel = subplot.conditions[::-1] # reversing
284-
conditions = range(len(subplot.conditions))[
285-
::-1] # reversing
287+
if np.all(np.diff(subplot.conditions) < 0):
288+
# monot. decreasing -> reverse
289+
xlabel = subplot.conditions[::-1]
290+
conditions = range(len(subplot.conditions))[::-1]
286291
ax.set_xticks(range(len(conditions)), xlabel)
287292
elif np.all(np.diff(subplot.conditions) > 0):
288293
xlabel = subplot.conditions
@@ -305,21 +310,18 @@ def ticks(y, _):
305310
if subplot.yScale == LOG:
306311
ax.yaxis.set_major_formatter(mtick.FuncFormatter(ticks))
307312

308-
if not subplot.plotTypeSimulation == BAR_PLOT:
313+
if subplot.plotTypeSimulation != BAR_PLOT:
309314
ax.legend()
310315
ax.set_title(subplot.plotName)
311-
ax.relim()
312316
if subplot.xlim:
313317
ax.set_xlim(subplot.xlim)
314318
if subplot.ylim:
315319
ax.set_ylim(subplot.ylim)
316320
ax.autoscale_view()
317321

318322
# Beautify plots
319-
ax.set_xlabel(
320-
subplot.xLabel)
321-
ax.set_ylabel(
322-
subplot.yLabel)
323+
ax.set_xlabel(subplot.xLabel)
324+
ax.set_ylabel(subplot.yLabel)
323325

324326
def generate_figure(
325327
self,

petab/visualize/plotting.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,8 @@ def add_x_offset(self, offset) -> None:
7272
self.conditions += offset
7373

7474
def add_y_offset(self, offset):
75-
self.data_to_plot['mean'] = \
76-
self.data_to_plot['mean'] + offset
77-
self.data_to_plot['repl'] = \
78-
self.data_to_plot['repl'] + offset
75+
self.data_to_plot['mean'] += offset
76+
self.data_to_plot['repl'] += offset
7977

8078
def add_offsets(self, x_offset=0, y_offset=0) -> None:
8179
"""
@@ -348,9 +346,9 @@ def save_to_tsv(self, output_file_path: str = 'visuSpec.tsv') -> None:
348346
dataplot.__dict__ if key in
349347
VISUALIZATION_DF_SINGLE_PLOT_LEVEL_COLS}
350348
row = {**subplot_level, **dataset_level}
351-
for key in row:
349+
for key, value in row.items():
352350
if key in visu_dict:
353-
visu_dict[key].append(row[key])
351+
visu_dict[key].append(value)
354352
else:
355353
visu_dict[key] = [row[key]]
356354
visu_df = pd.DataFrame.from_dict(visu_dict)
@@ -596,7 +594,6 @@ def get_data_to_plot(self, dataplot: DataPlot, provided_noise: bool
596594
SIMULATION,
597595
dataplot,
598596
provided_noise)
599-
600597
return measurements_to_plot, simulations_to_plot
601598

602599

@@ -874,11 +871,12 @@ def _get_vis_spec_dependent_columns_dict(
874871
plot_id_column = ['plot%s' % str(ind + 1) for ind, inner_list in
875872
enumerate(dataset_id_list) for _ in inner_list]
876873

877-
columns_dict = {PLOT_ID: plot_id_column,
878-
DATASET_ID: dataset_id_column,
879-
LEGEND_ENTRY: dataset_label_column,
880-
Y_VALUES: yvalues_column}
881-
return columns_dict
874+
return {
875+
PLOT_ID: plot_id_column,
876+
DATASET_ID: dataset_id_column,
877+
LEGEND_ENTRY: dataset_label_column,
878+
Y_VALUES: yvalues_column
879+
}
882880

883881
def _create_legend(self, dataset_id: str) -> str:
884882
"""

0 commit comments

Comments
 (0)