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

Refactor model.from_dict to parse megacomplex_type from dict and add simple_generator for testing #807

Merged
merged 24 commits into from
Sep 16, 2021
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9ebb8c1
Refactor model.from_dict to use kwargs only for override
jsnel Sep 11, 2021
8281976
Refactor a simple DecayModel used in testing
jsnel Sep 11, 2021
6c8bc9c
✨🧪 Added plugin registry monkeypatch context managers for testing
s-weigand Sep 12, 2021
ae4e9e3
♻️ Refactored by Sourcery
Sep 12, 2021
47a4c3a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 12, 2021
16e307c
Added simple generator for model and parameters
jsnel Sep 12, 2021
69175d9
♻️ Refactored by Sourcery
jsnel Sep 12, 2021
edc863d
🔧Add rich dependency
jsnel Sep 12, 2021
b84a7ce
👌 Fix codacy issues
jsnel Sep 12, 2021
dce7f0b
Fix ThreeComponentParallel to be actually parallel
jsnel Sep 13, 2021
30f4732
🩹 Fix simple generator not handling empty defaults in rates
jsnel Sep 13, 2021
ed6806d
♻️ Showing equivalence between hard coded and generated models
jsnel Sep 13, 2021
c4fd7c4
♻️🧹 Cleanup ThreeComponentParallel using simple_generator
jsnel Sep 13, 2021
f7c408d
🧹♻️ Cleanup refactor and added tests
jsnel Sep 13, 2021
8b4d3bf
🔧🩹 Fixed pydocstyle and darglint not picking up the testing module
s-weigand Sep 14, 2021
df34f6c
🩹 Fixed issues with docstrings in plugin_system testing code
s-weigand Sep 14, 2021
20eec59
♻️🧹 Moved 'test_plugin_system.py' from 'tests' to 'test' folder
s-weigand Sep 14, 2021
50327a8
🩹 Fixed broken test after renaming monkeypatch_plugin_registry_full
s-weigand Sep 14, 2021
b46146c
Apply suggestions from code review
jsnel Sep 14, 2021
63ee381
Combine _rates and _validate_rates and simplify exceptions
jsnel Sep 14, 2021
ffc4f85
Minor typing corrections
jsnel Sep 14, 2021
c18f791
♻️ Renamed module and cleaned up docstrings
jsnel Sep 15, 2021
e057dd9
🩹Adapted pytest benchmarks to new monkeypatch_plugin_registry
jsnel Sep 15, 2021
d6a31e6
🩹 Ignore Codacy issue W0622 redefining built-in
jsnel Sep 15, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ repos:
rev: 6.1.1
hooks:
- id: pydocstyle
files: "^glotaran/(plugin_system|utils|deprecation)"
files: "^glotaran/(plugin_system|utils|deprecation|testing)"
exclude: "docs|tests?"
# this is needed due to the following issue:
# https://github.com/PyCQA/pydocstyle/issues/368
Expand All @@ -87,14 +87,14 @@ repos:
rev: v1.8.0
hooks:
- id: darglint
files: "^glotaran/(plugin_system|utils|deprecation)"
files: "^glotaran/(plugin_system|utils|deprecation|testing)"
exclude: "docs|tests?"

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.910
hooks:
- id: mypy
files: "^glotaran/(plugin_system|utils|deprecation)"
files: "^glotaran/(plugin_system|utils|deprecation|testing)"
exclude: "docs"
additional_dependencies: [types-all]

Expand Down
14 changes: 1 addition & 13 deletions glotaran/builtin/io/yml/yml.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
from glotaran.io import save_dataset
from glotaran.io import save_parameters
from glotaran.model import Model
from glotaran.model import get_megacomplex
from glotaran.parameter import ParameterGroup
from glotaran.project import SavingOptions
from glotaran.project import Scheme
Expand Down Expand Up @@ -66,18 +65,7 @@ def load_model(self, file_name: str) -> Model:
if "megacomplex" not in spec:
raise ValueError("No megacomplex defined in model")

megacomplex_types = {
m["type"]: get_megacomplex(m["type"])
for m in spec["megacomplex"].values()
if "type" in m
}
if default_megacomplex is not None:
megacomplex_types[default_megacomplex] = get_megacomplex(default_megacomplex)
del spec["default-megacomplex"]

return Model.from_dict(
spec, megacomplex_types=megacomplex_types, default_megacomplex_type=default_megacomplex
)
return Model.from_dict(spec, megacomplex_types=None, default_megacomplex_type=None)

def load_parameters(self, file_name: str) -> ParameterGroup:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@

from glotaran.analysis.optimize import optimize
from glotaran.analysis.simulation import simulate
from glotaran.builtin.megacomplexes.decay import DecayMegacomplex
from glotaran.model import Megacomplex
from glotaran.model import Model
from glotaran.parameter import ParameterGroup
from glotaran.project import Scheme
from glotaran.testing.simple_generator import SimpleGenerator


def _create_gaussian_clp(labels, amplitudes, centers, widths, axis):
Expand All @@ -28,20 +27,9 @@ class DecayModel(Model):
def from_dict(
cls,
model_dict,
*,
megacomplex_types: dict[str, type[Megacomplex]] | None = None,
default_megacomplex_type: str | None = None,
):
defaults: dict[str, type[Megacomplex]] = {
"decay": DecayMegacomplex,
}
if megacomplex_types is not None:
defaults.update(megacomplex_types)
return super().from_dict(
model_dict,
megacomplex_types=defaults,
default_megacomplex_type=default_megacomplex_type,
)
model_dict = {**model_dict, "default-megacomplex": "decay"}
return super().from_dict(model_dict)


class OneComponentOneChannel:
Expand Down Expand Up @@ -136,62 +124,16 @@ class OneComponentOneChannelGaussianIrf:


class ThreeComponentParallel:
model = DecayModel.from_dict(
{
"initial_concentration": {
"j1": {"compartments": ["s1", "s2", "s3"], "parameters": ["j.1", "j.1", "j.1"]},
},
"megacomplex": {
"mc1": {"k_matrix": ["k1"]},
},
"k_matrix": {
"k1": {
"matrix": {
("s2", "s1"): "kinetic.1",
("s3", "s2"): "kinetic.2",
("s3", "s3"): "kinetic.3",
}
}
},
"irf": {
"irf1": {
"type": "multi-gaussian",
"center": ["irf.center"],
"width": ["irf.width"],
},
},
"dataset": {
"dataset1": {
"initial_concentration": "j1",
"irf": "irf1",
"megacomplex": ["mc1"],
},
},
}
generator = SimpleGenerator(
rates=[300e-3, 500e-4, 700e-5],
irf={"center": 1.3, "width": 7.8},
k_matrix="parallel",
)
model, initial_parameters = generator.model_and_parameters

generator.rates = [301e-3, 502e-4, 705e-5]
wanted_parameters = generator.parameters

initial_parameters = ParameterGroup.from_dict(
{
"kinetic": [
["1", 300e-3],
["2", 500e-4],
["3", 700e-5],
],
"irf": [["center", 1.3], ["width", 7.8]],
"j": [["1", 1, {"vary": False, "non-negative": False}]],
}
)
wanted_parameters = ParameterGroup.from_dict(
{
"kinetic": [
["1", 301e-3],
["2", 502e-4],
["3", 705e-5],
],
"irf": [["center", 1.3], ["width", 7.8]],
"j": [["1", 1, {"vary": False, "non-negative": False}]],
}
)
time = np.arange(-10, 100, 1.5)
pixel = np.arange(600, 750, 10)

Expand Down
24 changes: 21 additions & 3 deletions glotaran/model/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from __future__ import annotations

import copy
from typing import Any
from typing import List
from warnings import warn

Expand All @@ -17,6 +18,7 @@
from glotaran.model.weight import Weight
from glotaran.parameter import Parameter
from glotaran.parameter import ParameterGroup
from glotaran.plugin_system.megacomplex_registration import get_megacomplex
from glotaran.utils.ipython import MarkdownStr

default_model_items = {
Expand Down Expand Up @@ -56,18 +58,34 @@ def __init__(
@classmethod
def from_dict(
cls,
model_dict: dict,
model_dict: dict[str, Any],
*,
megacomplex_types: dict[str, type[Megacomplex]],
megacomplex_types: dict[str, type[Megacomplex]] | None = None,
default_megacomplex_type: str | None = None,
) -> Model:
"""Creates a model from a dictionary.

Parameters
----------
model_dict :
model_dict: dict[str, Any]
Dictionary containing the model.
megacomplex_types: dict[str, type[Megacomplex]] | None
Overwrite 'megacomplex_types' in ``model_dict`` for testing.
default_megacomplex_type: str | None
Overwrite 'default-megacomplex' in ``model_dict`` for testing.
"""
if default_megacomplex_type is None:
default_megacomplex_type = model_dict.get("default-megacomplex")

if megacomplex_types is None:
megacomplex_types = {
m["type"]: get_megacomplex(m["type"])
for m in model_dict["megacomplex"].values()
if "type" in m
}
if default_megacomplex_type is not None:
megacomplex_types[default_megacomplex_type] = get_megacomplex(default_megacomplex_type)
del model_dict["default-megacomplex"]

model = cls(
megacomplex_types=megacomplex_types, default_megacomplex_type=default_megacomplex_type
Expand Down
1 change: 1 addition & 0 deletions glotaran/testing/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Testing framework package for glotaran itself and plugins."""
Loading