Skip to content

Commit

Permalink
handle previously calibrated models completely in petab select
Browse files Browse the repository at this point in the history
  • Loading branch information
dilpath committed Mar 28, 2024
1 parent 925d2c5 commit 640014c
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 11 deletions.
51 changes: 51 additions & 0 deletions petab_select/candidate_space.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,57 @@ def __init__(
if self.previous_predecessor_model is None:
self.previous_predecessor_model = self.predecessor_model

self.set_previously_calibrated_models({})

def set_previously_calibrated_models(
self, models: dict[str, Model]
) -> None:
"""Set the previously-calibrated models.
This allows previously-calibrated model results, e.g. from a previous
model selection job, to be re-used in this job. Calibrated models are
stored here between model selection iterations, while the calibration
tool calibrates the uncalibrated models of the iteration. The models
are then combined as the full model calibration results for the
iteration.
Args:
models:
The previously-calibrated models. Keys are model hashes, values
are models.
"""
self.previously_calibrated_models = models

def get_combined_calibrated_models(
self, newly_calibrated_models: dict[str, Model], reset: bool = False
) -> dict[str, Model]:
"""Get the full list of calibrated models for the latest iteration.
The full list of models identified for calibration in an iteration of
model selection may include models for which calibration results are
already available. This combines the newly calibrated models with the
models that were already calibrated, to produce the full list of models
that were identified for calibration in the latest iteration.
Args:
newly_calibrated_models:
The newly calibrated models. Keys are model hashes, values are
models.
reset:
Whether to remove the previously calibrated models from the
candidate space, after they are used to produce the full list
of calibrated models.
Returns:
The full list of calibrated models.
"""
combined_calibrated_models = (
self.previously_calibrated_models | newly_calibrated_models
)
if reset:
self.set_previously_calibrated_models(models={})
return combined_calibrated_models

def write_summary_tsv(self, row):
if self.summary_tsv is None:
return
Expand Down
43 changes: 32 additions & 11 deletions petab_select/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,15 @@ def candidates(
calibrated_models = {}
if newly_calibrated_models is None:
newly_calibrated_models = {}
calibrated_models.update(newly_calibrated_models)
if criterion is None:
criterion = problem.criterion
if candidate_space is None:
candidate_space = problem.new_candidate_space(limit=limit)
newly_calibrated_models = candidate_space.get_combined_calibrated_models(
newly_calibrated_models=newly_calibrated_models,
reset=True,
)
calibrated_models.update(newly_calibrated_models)
candidate_space.exclude_hashes(calibrated_models)

# Set the predecessor model to the previous predecessor model.
Expand Down Expand Up @@ -222,36 +226,53 @@ def candidates(

candidate_space.previous_predecessor_model = predecessor_model

replace_user_calibrated_candidates(
remove_user_calibrated_candidates(
candidate_space=candidate_space,
user_calibrated_models=user_calibrated_models,
criterion=criterion,
)
return candidate_space


def replace_user_calibrated_candidates(
def remove_user_calibrated_candidates(
candidate_space: CandidateSpace,
user_calibrated_models: Optional[dict[str, Model]],
criterion: Criterion,
) -> None:
"""Substitute models in the candidate space with calibrated models.
"""Remove previously-calibrated models from the uncalibrated models.
Args:
candidate_space:
The candidate space.
user_calibrated_models:
The calibrated models.
"""
models = []
for model0 in candidate_space.models:
model = model0
uncalibrated_models = []
previously_calibrated_models = {}
for model in candidate_space.models:
if (
user_model := user_calibrated_models.get(model0.get_hash())
user_model := user_calibrated_models.get(model.get_hash())
is not None
) and (
user_model.get_criterion(criterion, raise_on_failure=False)
is not None
):
logging.info(f'Using user-supplied result for: {model.get_hash()}')
model = user_model
models.append(model)
candidate_space.models = models
user_model_copy = copy.deepcopy(user_model)
user_model_copy.predecessor_model_hash = (
candidate_space.predecessor_model.get_hash()
if isinstance(candidate_space.predecessor_model, Model)
else candidate_space.predecessor_model
)
previously_calibrated_models[
user_model_copy.get_hash()
] = user_model_copy
else:
uncalibrated_models.append(model)
candidate_space.set_previously_calibrated_models(
models=previously_calibrated_models
)
candidate_space.models = uncalibrated_models


def model_to_petab(
Expand Down

0 comments on commit 640014c

Please sign in to comment.