Skip to content

Commit

Permalink
add the functionality to evaluate the model using boundry values of p… (
Browse files Browse the repository at this point in the history
#355)

* add the functionality to evaluate the model using boundry values of parameter

* fix flake8 issues

* fix additional flake8 issues

* add test case

* flake8 fixes

* flake8 fixes

* flake8 fixes

* flake8 fixes

* flake8 fixes

* black fixes

* Update test_external.py

Use correct comparison operator.

---------

Co-authored-by: Yannik Schälte <[email protected]>
Co-authored-by: Stephan Grein <[email protected]>
Co-authored-by: Stephan Grein <[email protected]>
  • Loading branch information
4 people authored Nov 10, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 46ef9ae commit d689b20
Showing 3 changed files with 103 additions and 0 deletions.
81 changes: 81 additions & 0 deletions pyabc/external/base.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import copy
import logging
import os
import subprocess # noqa: S404
import tempfile
from typing import List

import numpy as np
import pandas as pd

from ..model import Model
from ..parameters import Parameter
from .utils import timethis

logger = logging.getLogger("ABC.External")

@@ -242,6 +245,84 @@ def __call__(self, pars: Parameter):
def sample(self, pars):
return self(pars)

@timethis
def sample_timing(self, pars):
return self(pars)

def eval_param_limits(self, limits):
"""
evaluate single parameter's boundary value on computation time.
Parameters
----------
limits: dict
the lower and upper boundary values of parameters. The key would
be the parameter name and the value would be a list of the lower
and upper limit of parameter value, e.g., [lower, upper].
Returns
-------
time_eval_dict: dict
a dictionary that contains the parameter names as key and a list
as a value. The list contains the computation time when using
lower and upper limits, e.g., [lower, upper].
"""
time_eval_dict = {}
for key, val in limits.items():
lower_bound = self.sample_timing({key: val[0]})
upper_bound = self.sample_timing({key: val[1]})
time_eval_dict[key] = [lower_bound, upper_bound]
return time_eval_dict

def eval_param_limits_matrix(self, limits):
"""
evaluate two paramters' boundary values on computation time.
Parameters
----------
limits: dict
the lower and upper boundary values of parameters. The key would
be the parameter name and the value would be a list of the lower
and upper limit of parameter value, e.g., [lower, upper].
Returns
-------
time_eval_mat_df_lower: df
a dataframe for the computation time measured when using the lower
limit value of parameters.
time_eval_mat_df_upper: df
a dataframe for the computation time measured when using the upper
limit value of parameters.
"""
time_eval_mat = np.zeros(shape=(len(limits), len(limits)))
time_eval_mat_df_lower = pd.DataFrame(
time_eval_mat,
columns=[list(limits.keys())],
index=[list(limits.keys())],
)
time_eval_mat_df_upper = copy.deepcopy(time_eval_mat_df_lower)
for i, (key_col, val_col) in enumerate(limits.items(), 0):
for j, (key_row, val_row) in enumerate(limits.items(), 0):
if i < j:
time_eval_mat_df_lower.loc[[key_col], [key_row]] = 0
time_eval_mat_df_upper.loc[[key_col], [key_row]] = 0

if key_col == key_row:
lower_bound = self.sample_timing({key_col: val_col[0]})
upper_bound = self.sample_timing({key_col: val_col[1]})

else:
lower_bound = self.sample_timing(
{key_col: val_col[0], key_row: val_row[0]}
)
lower_bound = self.sample_timing(
{key_col: val_col[1], key_row: val_row[1]}
)
time_eval_mat_df_lower.loc[[key_col], [key_row]] = lower_bound
time_eval_mat_df_upper.loc[[key_col], [key_row]] = upper_bound

return time_eval_mat_df_lower, time_eval_mat_df_upper


class ExternalSumStat:
"""
13 changes: 13 additions & 0 deletions pyabc/external/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import time
from functools import wraps


def timethis(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
func(*args, **kwargs)
end = time.time()
return end - start

return wrapper
9 changes: 9 additions & 0 deletions test/external/test_external.py
Original file line number Diff line number Diff line change
@@ -74,3 +74,12 @@ def test_external_handler():
eh.create_folder = True
loc = eh.create_loc()
assert os.path.exists(loc) and os.path.isdir(loc)


def test_eval_param_limits():
folder = "doc/examples/rmodel/"
executable = "Rscript"
model = pyabc.external.ExternalModel(executable, folder + "model.r")
limits = {"meanX": (1, 5), "meanY": (1, 5.5)}
evaluation = pyabc.external.ExternalModel.eval_param_limits(model, limits)
assert type(evaluation) is dict

0 comments on commit d689b20

Please sign in to comment.