Skip to content

Commit 826e7f7

Browse files
authored
Merge pull request #468 from PEtab-dev/release_0.1.9
Release 0.1.9 Library: * Allow URL as filenames for YAML files and SBML models (Closes #187) (#459) * Allow model time in observable formulas (#445) * Make float parsing from CSV round-trip (#444) * Validator: Error message for missing IDs, with line numbers. (#467) * Validator: Detect duplicated observable IDs (#446) * Some documentation and CI fixes / updates * Visualization: Add option to save visualization specification (#457) * Visualization: Column XValue not mandatory anymore (#429) * Visualization: Add sorting of indices of dataframes for the correct sorting of x-values (#430) * Visualization: Default value for the column x_label in vis_spec (#431)
2 parents 768eb5b + 0d6ce54 commit 826e7f7

File tree

17 files changed

+278
-39
lines changed

17 files changed

+278
-39
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
name: PEtab specification changes
3+
about: Suggest a change to the PEtab specification (beyond fixes / clarifications)
4+
title: ''
5+
labels: file format
6+
assignees: ''
7+
8+
---
9+
10+
**Which problem would you like to address? Please describe.**
11+
A clear and concise description of which use case you want to address and, if applicable, why the current specifications do not fulfill your requirements.
12+
13+
**Describe the solution you would like**
14+
A clear and concise description of the changes you want to propose. Please describe any additional fields / files you would want to add, including allowed inputs and implications.
15+
16+
**Describe alternatives you have considered**
17+
A clear and concise description of any alternative solutions or features you have considered.
18+
19+
**Additional context**
20+
Add any other context about the request here.

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.9
6+
7+
Library:
8+
9+
* Allow URL as filenames for YAML files and SBML models (Closes #187) (#459)
10+
* Allow model time in observable formulas (#445)
11+
* Make float parsing from CSV round-trip (#444)
12+
* Validator: Error message for missing IDs, with line numbers. (#467)
13+
* Validator: Detect duplicated observable IDs (#446)
14+
* Some documentation and CI fixes / updates
15+
* Visualization: Add option to save visualization specification (#457)
16+
* Visualization: Column XValue not mandatory anymore (#429)
17+
* Visualization: Add sorting of indices of dataframes for the correct sorting
18+
of x-values (#430)
19+
* Visualization: Default value for the column x_label in vis_spec (#431)
20+
521

622
### 0.1.8
723

doc/compile_doc.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/sh
2+
3+
# Build a pdflatex document from the documentation
4+
5+
# format A3
6+
pandoc documentation_data_format.rst \
7+
-o documentation_data_format.pdf \
8+
-V geometry:margin=1.5in -V geometry:a3paper -V fontsize=10pt \
9+
--toc \
10+
--pdf-engine pdflatex
11+
12+
# format A2 landscape
13+
14+
# pandoc documentation_data_format.rst \
15+
# -o documentation_data_format.pdf \
16+
# -V geometry:margin=.5in -V geometry:a4paper -V geometry:landscape -V fontsize=10pt \
17+
# --toc \
18+
# --pdf-engine pdflatex

doc/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
# List of patterns, relative to source directory, that match files and
5050
# directories to ignore when looking for source files.
5151
# This pattern also affects html_static_path and html_extra_path.
52-
exclude_patterns = []
52+
exclude_patterns = ['build/doctrees', 'build/html']
5353

5454
master_doc = 'index'
5555

doc/documentation_data_format.rst

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ PEtab data format specification
33

44

55
Format version: 1
6-
-----------------
76

87
This document explains the PEtab data format.
98

@@ -90,7 +89,7 @@ This is specified as a tab-separated value file in the following way:
9089
+--------------+------------------+------------------------------------+-----+---------------------------------------+
9190
| conditionId2 | ... | ... | ... | ... |
9291
+--------------+------------------+------------------------------------+-----+---------------------------------------+
93-
|... | ... | ... | ... |... |
92+
| ... | ... | ... | ... | .. |
9493
+--------------+------------------+------------------------------------+-----+---------------------------------------+
9594

9695
Row- and column-ordering are arbitrary, although specifying ``conditionId``
@@ -428,9 +427,9 @@ One row per parameter with arbitrary order of rows and columns:
428427
+-------------+-----------------+-------------------------+-------------+------------+--------------+----------+-----+
429428
| parameterId | [parameterName] | parameterScale | lowerBound | upperBound | nominalValue | estimate | ... |
430429
+=============+=================+=========================+=============+============+==============+==========+=====+
431-
|STRING | [STRING] | log10\|lin\|log | NUMERIC | NUMERIC | NUMERIC | 0\|1 | ... |
430+
| STRING | [STRING] | log10\|lin\|log | NUMERIC | NUMERIC | NUMERIC | 0\|1 | ... |
432431
+-------------+-----------------+-------------------------+-------------+------------+--------------+----------+-----+
433-
| ... | ... | ... | ... | ... | ... | ... | ... |
432+
| ... | ... | ... | ... | ... | ... | ... | ... |
434433
+-------------+-----------------+-------------------------+-------------+------------+--------------+----------+-----+
435434

436435
*(wrapped for readability)*

petab/core.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ def flatten_timepoint_specific_output_overrides(
206206
) == 0).any():
207207
tmp = tmp_ + counter * "_" + str(i_noise + i_sc + 1)
208208
counter += 1
209-
if not tmp_.empty and not tmp_.empty:
209+
if not tmp_.empty:
210210
replacements[tmp.values[0]] = tmp_.values[0]
211211
df.loc[idxs == 0, OBSERVABLE_ID] = tmp
212212
# Append the result in a new df

petab/lint.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,8 @@ def is_valid_identifier(x: str) -> bool:
832832
Returns:
833833
``True`` if valid, ``False`` otherwise
834834
"""
835+
if pd.isna(x):
836+
return False
835837

836838
return re.match(r'^[a-zA-Z_]\w*$', x) is not None
837839

@@ -846,10 +848,16 @@ def check_ids(ids: Iterable[str], kind: str = '') -> None:
846848
Raises:
847849
ValueError - in case of invalid IDs
848850
"""
849-
invalids = []
850-
for _id in ids:
851-
if not is_valid_identifier(_id):
852-
invalids.append(_id)
851+
invalids = [(index, _id)
852+
for index, _id in enumerate(ids)
853+
if not is_valid_identifier(_id)]
853854

854855
if invalids:
855-
raise ValueError(f"Invalid {kind} ID(s): {invalids}")
856+
# The first row is the header row, and Python lists are zero-indexed,
857+
# hence need to add 2 for the correct line number.
858+
offset = 2
859+
error_output = '\n'.join([
860+
f'Line {index+offset}: ' +
861+
('Missing ID' if pd.isna(_id) else _id)
862+
for index, _id in invalids])
863+
raise ValueError(f"Invalid {kind} ID(s):\n{error_output}")

petab/problem.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,8 @@ def __setstate__(self, state):
7676
# load SBML model from pickled string
7777
sbml_string = state.pop('sbml_string', None)
7878
if sbml_string:
79-
self.sbml_reader = libsbml.SBMLReader()
80-
self.sbml_document = \
81-
self.sbml_reader.readSBMLFromString(sbml_string)
82-
self.sbml_model = self.sbml_document.getModel()
79+
self.sbml_reader, self.sbml_document, self.sbml_model = \
80+
sbml.load_sbml_from_string(sbml_string)
8381

8482
self.__dict__.update(state)
8583

@@ -119,9 +117,8 @@ def from_files(sbml_file: str = None,
119117
parameter_df = parameters.get_parameter_df(parameter_file)
120118

121119
if sbml_file:
122-
sbml_reader = libsbml.SBMLReader()
123-
sbml_document = sbml_reader.readSBML(sbml_file)
124-
sbml_model = sbml_document.getModel()
120+
sbml_reader, sbml_document, sbml_model = \
121+
sbml.get_sbml_model(sbml_file)
125122

126123
if visualization_files:
127124
# If there are multiple tables, we will merge them

petab/sbml.py

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
from warnings import warn
33
import logging
44
import re
5-
from typing import Dict, Any, List, Union
6-
5+
from typing import Dict, Any, List, Union, Tuple
76
import libsbml
87

98
logger = logging.getLogger(__name__)
@@ -406,3 +405,62 @@ def write_sbml(sbml_doc: libsbml.SBMLDocument, filename: str) -> None:
406405
if not ret:
407406
raise RuntimeError(f"libSBML reported error {ret} when trying to "
408407
f"create SBML file {filename}.")
408+
409+
410+
def get_sbml_model(
411+
filepath_or_buffer
412+
) -> Tuple[libsbml.SBMLReader, libsbml.SBMLDocument, libsbml.Model]:
413+
"""Get an SBML model from file or URL or file handle
414+
415+
:param filepath_or_buffer:
416+
File or URL or file handle to read the model from
417+
:return: The SBML document, model and reader
418+
"""
419+
420+
from pandas.io.common import get_filepath_or_buffer, is_url, is_file_like
421+
422+
if is_file_like(filepath_or_buffer) or is_url(filepath_or_buffer):
423+
buffer = get_filepath_or_buffer(filepath_or_buffer, mode='r')[0]
424+
if is_url(filepath_or_buffer):
425+
buffer = ''.join(line.decode('utf-8') for line in buffer)
426+
else:
427+
buffer = ''.join(line for line in buffer)
428+
429+
# URL or already opened file, we will load the model from a string
430+
431+
return load_sbml_from_string(buffer)
432+
433+
return load_sbml_from_file(filepath_or_buffer)
434+
435+
436+
def load_sbml_from_string(
437+
sbml_string: str
438+
) -> Tuple[libsbml.SBMLReader, libsbml.SBMLDocument, libsbml.Model]:
439+
"""Load SBML model from string
440+
441+
:param sbml_string: Model as XML string
442+
:return: The SBML document, model and reader
443+
"""
444+
445+
sbml_reader = libsbml.SBMLReader()
446+
sbml_document = \
447+
sbml_reader.readSBMLFromString(sbml_string)
448+
sbml_model = sbml_document.getModel()
449+
450+
return sbml_reader, sbml_document, sbml_model
451+
452+
453+
def load_sbml_from_file(
454+
sbml_file: str
455+
) -> Tuple[libsbml.SBMLReader, libsbml.SBMLDocument, libsbml.Model]:
456+
"""Load SBML model from file
457+
458+
:param sbml_file: Filename of the SBML file
459+
:return: The SBML document, model and reader
460+
"""
461+
462+
sbml_reader = libsbml.SBMLReader()
463+
sbml_document = sbml_reader.readSBML(sbml_file)
464+
sbml_model = sbml_document.getModel()
465+
466+
return sbml_reader, sbml_document, sbml_model

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.8'
2+
__version__ = '0.1.9'

0 commit comments

Comments
 (0)