Skip to content

Commit

Permalink
Create standard/schema for Problem (#132)
Browse files Browse the repository at this point in the history
* update docs

* test problem load/save round-trip

* remove unused constant, update doc example

* add `ModelSubspace.to_definition`

* `ProblemStandard`

* handle predecessor model relative path on load

* add more repro info to test case 0009

* fix cli `start_iteration`

* bump mkstd req

* change pypesto test tolerance; add test for pypesto+cli

---------

Co-authored-by: Daniel Weindl <[email protected]>
  • Loading branch information
dilpath and dweindl authored Jan 6, 2025
1 parent 8843834 commit d4fce46
Show file tree
Hide file tree
Showing 34 changed files with 522 additions and 407 deletions.
2 changes: 1 addition & 1 deletion doc/examples/model_selection/model_space.tsv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
model_subspace_id petab_yaml k1 k2 k3
model_subspace_id model_subspace_petab_yaml k1 k2 k3
M1_0 petab_problem.yaml 0 0 0
M1_1 petab_problem.yaml 0.2 0.1 estimate
M1_2 petab_problem.yaml 0.2 estimate 0
Expand Down
3 changes: 2 additions & 1 deletion doc/examples/model_selection/petab_select_problem.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
version: beta_1
format_version: 1.0.0
criterion: AIC
method: forward
model_space_files:
- model_space.tsv
candidate_space_arguments: {}
26 changes: 20 additions & 6 deletions doc/problem_definition.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ Model selection problems for PEtab Select are defined by the following files:
#. a specification of the model space, and
#. (optionally) a specification of the initial candidate model.

The different file formats are described below. Each file format is a YAML file
and comes with a YAML-formatted JSON schema, such that these files can be
The different file formats are described below. The YAML file formats
come with a YAML-formatted JSON schema, such that these files can be
easily worked with independently of the PEtab Select library.

1. Selection problem
Expand All @@ -34,14 +34,23 @@ A YAML file with a description of the model selection problem.
- ``candidate_space_arguments``: Additional arguments used to generate
candidate models during model selection. For example, an initial candidate
model can be specified with the following code, where
``predecessor_model.yaml`` is a valid model file. Additional arguments are
provided in the documentation of the ``CandidateSpace`` class.
``predecessor_model.yaml`` is a valid :ref:`model file <section-model-yaml>`. Additional arguments are
provided in the documentation of the ``CandidateSpace`` class, and an example is provided in
`test case 0009 <https://github.com/PEtab-dev/petab_select/blob/main/test_cases/0009/petab_select_problem.yaml>`_.

.. code-block:: yaml
candidate_space_arguments:
predecessor_model: predecessor_model.yaml
Schema
^^^^^^

The schema is provided as `YAML-formatted JSON schema <_static/problem.yaml>`_, which enables easy validation with various third-party tools.

.. literalinclude:: standard/problem.yaml
:language: yaml

2. Model space
--------------

Expand All @@ -54,7 +63,7 @@ all parameters.
:header-rows: 1

* - ``model_subspace_id``
- ``petab_yaml``
- ``model_subspace_petab_yaml``
- ``parameter_id_1``
- ...
- ``parameter_id_n``
Expand All @@ -65,7 +74,7 @@ all parameters.
- ...

- ``model_subspace_id``: An ID for the model subspace.
- ``petab_yaml``: The PEtab YAML filename that serves as the basis of all
- ``model_subspace_petab_yaml``: The YAML filename of the PEtab problem that serves as the basis of all
models in this subspace.
- ``parameter_id_1`` ... ``parameter_id_n``: Specify the values that a
parameter can take in the model subspace. For example, this could be:
Expand All @@ -81,6 +90,9 @@ all parameters.
- ``0.0;1.1;estimate`` (the parameter can take the values ``0.0`` or
``1.1``, or be estimated)

Example of concise specification
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Using the ``;``-delimited list format, a model subspace that has two parameters
(``p1, p2``) and six models:

Expand All @@ -105,6 +117,8 @@ can be specified like
- 0;estimate
- 10;20;estimate

.. _section-model-yaml:

3. Model(s) (Predecessor models / model interchange / report)
-------------------------------------------------------------

Expand Down
2 changes: 2 additions & 0 deletions doc/standard/make_schemas.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from petab_select.model import ModelStandard
from petab_select.models import ModelsStandard
from petab_select.problem import ProblemStandard

ModelStandard.save_schema("model.yaml")
ModelsStandard.save_schema("models.yaml")
ProblemStandard.save_schema("problem.yaml")
35 changes: 35 additions & 0 deletions doc/standard/problem.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
description: "Handle everything related to the model selection problem.\n\nAttributes:\n\
\ model_space:\n The model space.\n calibrated_models:\n Calibrated\
\ models. Will be used to augment the model selection\n problem (e.g. by\
\ excluding them from the model space).\n candidate_space_arguments:\n \
\ Arguments are forwarded to the candidate space constructor.\n compare:\n \
\ A method that compares models by selection criterion. See\n :func:`petab_select.model.default_compare`\
\ for an example.\n criterion:\n The criterion used to compare models.\n\
\ method:\n The method used to search the model space.\n version:\n\
\ The version of the PEtab Select format.\n yaml_path:\n The location\
\ of the selection problem YAML file. Used for relative\n paths that exist\
\ in e.g. the model space files."
properties:
format_version:
default: 1.0.0
title: Format Version
type: string
criterion:
type: string
method:
type: string
model_space_files:
items:
format: path
type: string
title: Model Space Files
type: array
candidate_space_arguments:
title: Candidate Space Arguments
type: object
required:
- criterion
- method
- model_space_files
title: Problem
type: object
18 changes: 12 additions & 6 deletions petab_select/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,14 @@

from . import ui
from .candidate_space import CandidateSpace
from .constants import CANDIDATE_SPACE, MODELS, PETAB_YAML, PROBLEM, TERMINATE
from .constants import (
CANDIDATE_SPACE,
MODELS,
PETAB_YAML,
PROBLEM,
TERMINATE,
UNCALIBRATED_MODELS,
)
from .model import ModelHash
from .models import Models, models_to_yaml_list
from .problem import Problem
Expand Down Expand Up @@ -183,7 +190,7 @@ def start_iteration(
ModelHash.from_hash(hash_str) for hash_str in excluded_model_hashes
]

ui.start_iteration(
result = ui.start_iteration(
problem=problem,
candidate_space=candidate_space,
limit=limit,
Expand All @@ -201,9 +208,8 @@ def start_iteration(
)

# Save candidate models
models_to_yaml_list(
models=candidate_space.models,
output_yaml=uncalibrated_models_yaml,
result[UNCALIBRATED_MODELS].to_yaml(
filename=uncalibrated_models_yaml,
relative_paths=relative_paths,
)

Expand Down Expand Up @@ -495,7 +501,7 @@ def get_best(
models=models,
criterion=criterion,
)
best_model.to_yaml(output, paths_relative_to=paths_relative_to)
best_model.to_yaml(output)


cli.add_command(start_iteration)
Expand Down
5 changes: 0 additions & 5 deletions petab_select/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ class Criterion(str, Enum):
# Problem
MODEL_SPACE_FILES = "model_space_files"
PROBLEM = "problem"
PROBLEM_ID = "problem_id"
VERSION = "version"

# Candidate space
Expand Down Expand Up @@ -174,10 +173,6 @@ class Method(str, Enum):
# PEtab Select model report format.
HASH = "hash"

# MODEL_SPACE_FILE_NON_PARAMETER_COLUMNS = [MODEL_ID, PETAB_YAML]
MODEL_SPACE_FILE_NON_PARAMETER_COLUMNS = [MODEL_SUBSPACE_ID, PETAB_YAML]

# COMPARED_MODEL_ID = 'compared_'+MODEL_ID
YAML_FILENAME = "yaml"

# DISTANCES = {
Expand Down
48 changes: 18 additions & 30 deletions petab_select/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,23 @@
import copy
import warnings
from os.path import relpath
from pathlib import Path
from typing import TYPE_CHECKING, Any, ClassVar, Literal

import mkstd
import petab.v1 as petab
from mkstd import Path
from petab.v1.C import NOMINAL_VALUE
from pydantic import (
BaseModel,
Field,
PrivateAttr,
ValidationInfo,
ValidatorFunctionWrapHandler,
field_serializer,
field_validator,
model_serializer,
model_validator,
)

from .constants import (
ESTIMATE,
Expand Down Expand Up @@ -41,29 +52,14 @@
if TYPE_CHECKING:
from .problem import Problem


from pydantic import (
BaseModel,
PrivateAttr,
ValidationInfo,
ValidatorFunctionWrapHandler,
)

__all__ = [
"Model",
"default_compare",
"ModelHash",
"VIRTUAL_INITIAL_MODEL",
"ModelStandard",
]

from pydantic import (
Field,
field_serializer,
field_validator,
model_serializer,
model_validator,
)


class ModelHash(BaseModel):
"""The model hash.
Expand Down Expand Up @@ -331,9 +327,7 @@ def _fix_relative_paths(
return data
model = handler(data)

root_path = None
if ROOT_PATH in data:
root_path = data.pop(ROOT_PATH)
root_path = data.pop(ROOT_PATH, None)
if root_path is None:
return model

Expand Down Expand Up @@ -685,17 +679,11 @@ def get_parameter_values(
]

@staticmethod
def from_yaml(
filename: str | Path,
) -> Model:
"""Load a model from a YAML file.
Args:
filename:
Location of the YAML file.
"""
def from_yaml(filename: str | Path) -> Model:
"""Load a model from a YAML file."""
model = ModelStandard.load_data(
filename=filename, root_path=Path(filename).parent
filename=filename,
root_path=Path(filename).parent,
)
return model

Expand Down
Loading

0 comments on commit d4fce46

Please sign in to comment.