diff --git a/README.md b/README.md index ad2b0a3..461f83a 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ However, you still need to clone the GrainLearning repository to run the tutoria 1. Linear regression with the [`run_sim`](tutorials/simple_regression/linear_regression/python_linear_regression_solve.py#L14) - callback function of the [`DynamicSystem`](grainlearning/dynamic_systems.py) + callback function of the [`BayesianCalibration`](grainlearning/bayesian_calibration.py) class, in [python_linear_regression_solve.py](tutorials/simple_regression/linear_regression/python_linear_regression_solve.py) diff --git a/docs/source/bayesian_filtering.rst b/docs/source/bayesian_filtering.rst index 03c7e33..773a4ab 100644 --- a/docs/source/bayesian_filtering.rst +++ b/docs/source/bayesian_filtering.rst @@ -234,7 +234,7 @@ The essential steps include 1. Generating the initial samples using :attr:`a low-discrepancy sequence <.IterativeBayesianFilter.initialize>`, 2. Running the instances of the predictive (forward) model via a user-defined :ref:`callback function `, 3. Estimating the time evolution of :attr:`the posterior distribution <.IterativeBayesianFilter.run_inference>`, -4. Generateing new samples from :attr:`the proposal density <.IterativeBayesianFilter.run_sampling>`, trained with the previous ensemble (i.e., samples and associated weights), +4. Generating new samples from :attr:`the proposal density <.IterativeBayesianFilter.run_sampling>`, trained with the previous ensemble (i.e., samples and associated weights), 5. Check whether the posterior expecation of the model parameters has converged to a certain value, and stop the iteration if so. 6. If not, repeating step 1--5 (combined into the function :attr:`.IterativeBayesianFilter.solve`) diff --git a/docs/source/dynamic_systems.rst b/docs/source/dynamic_systems.rst index 25f1a6f..0d447ad 100644 --- a/docs/source/dynamic_systems.rst +++ b/docs/source/dynamic_systems.rst @@ -40,7 +40,7 @@ We consider both errors together in the covariance matrix :attr:`.SMC.cov_matric Interact with third-party software via callback function -------------------------------------------------------- -Interaction with an external "software" model can be done via the callback function of :class:`.DynamicSystem` or :class:`.IODynamicSystem`. +Interaction with an external "software" model can be done via the callback function of :class:`.BayesianCalibration`. You can define your own callback function and pass *samples* (combinations of parameters) to the **model implemented in Python** or to the software from the **command line**. The figure below shows how the callback function is called in the execution loop of :class:`.BayesianCalibration`. @@ -71,8 +71,8 @@ The following code snippet shows how to define a callback function that runs a l system.set_sim_data(data) -The function `run_sim` is assigned to the :attr:`.DynamicSystem.callback` attribute of the :class:`.DynamicSystem` class -and is is called every time the :attr:`.DynamicSystem.run` function is called (see :ref:`the figure ` above). +The function `run_sim` is assigned to the `callback` parameter of the :class:`.BayesianCalibration` class +and is is called every time the :attr:`.BayesianCalibration.run_callback` function is called (see :ref:`the figure ` above). Interact with non-Python software @@ -80,8 +80,7 @@ Interact with non-Python software The :class:`.IODynamicSystem` class inherits from :class:`.DynamicSystem` and is intended to work with external software packages via the command line. -The :attr:`.IODynamicSystem.run` function overrides the :attr:`.DynamicSystem.run` function of the :class:`.DynamicSystem` class. -Parameter samples are written into a text file and used by :attr:`.IODynamicSystem.callback` to execute the third-party software. +Parameter samples are written into a text file and used by :attr:`.BayesianCalibration.run_callback` to execute the third-party software. Users only need to write a for-loop to pass each parameter sample to this external software, e.g., as command-line arguments (see the example below). .. code-block:: python diff --git a/docs/source/introduction.rst b/docs/source/introduction.rst index 61e2a1a..9e912dc 100644 --- a/docs/source/introduction.rst +++ b/docs/source/introduction.rst @@ -37,7 +37,7 @@ The following figure shows the main modules of GrainLearning and their interconn :width: 400 :alt: GrainLearning modules -Users only need to write a :attr:`callback function <.IODynamicSystem.callback>` +Users only need to write a callback function and pass it to :class:`.BayesianCalibration` where parameter samples are sent to an external "software" or Python model. Examples of this can be found for :ref:`YADE ` (`Yet Another Dynamic Engine `_). diff --git a/docs/source/rnn.rst b/docs/source/rnn.rst index 4cc824c..f16dbd2 100644 --- a/docs/source/rnn.rst +++ b/docs/source/rnn.rst @@ -383,7 +383,7 @@ How does it work? A simple example can be found in `tutorials `_. Such tutorial has three main parts: 1. **Prepare the pre-trained model:** Load a model using ``grainlearning.rnn.predict.get_pretrained_model()``. -2. **Create a callback function to link to `DynamicSystem`:** Function in which the predictions are going to be drawn. +2. **Create a callback function to link to `BayesianCalibration`:** Function in which the predictions are going to be drawn. 3. **GrainLearning calibration loop.** In this case, `synthetic data` was considered: we took one example from our triaxial compression DEM simulations. diff --git a/docs/source/tutorials.rst b/docs/source/tutorials.rst index b98d323..21d3471 100644 --- a/docs/source/tutorials.rst +++ b/docs/source/tutorials.rst @@ -20,7 +20,7 @@ Linear regression with a Python model ````````````````````````````````````` To work with GrainLearning in the Python environment, -we need to write a callback function of the :class:`.DynamicSystem` where the model :math:`y = a\times{x}+b` is called. +we need to write a callback function of the :class:`.BayesianCalibration` class where the model :math:`y = a\times{x}+b` is called. .. code-block:: python @@ -64,6 +64,7 @@ Check out the documentation of :class:`.BayesianCalibration` for more details. calibration = BayesianCalibration.from_dict( { "num_iter": 10, + "callback": run_sim, "system": { "param_min": [0.1, 0.1], "param_max": [1, 10], @@ -71,7 +72,6 @@ Check out the documentation of :class:`.BayesianCalibration` for more details. "num_samples": 20, "obs_data": y_obs, "ctrl_data": x_obs, - "callback": run_sim, }, "calibration": { "inference": {"ess_target": 0.3}, @@ -106,7 +106,7 @@ Linear regression with a "software" model Linking GrainLearning with external software is done with the :class:`.IODynamicSystem` Now let us look at the same example, using the :class:`.IODynamicSystem` and a linear function implemented in a separate file :download:`linear_model.py <../../tutorials/simple_regression/linear_regression/linear_model.py>`. -This Python "software" will be run from command line by the callback function of a :class:`.IODynamicSystem` object +This Python "software" will be run from command line by the callback function of :class:`.BayesianCalibration` and take the command-line arguments as model parameters. Download :download:`this script <../../tutorials/simple_regression/linear_regression/linear_model.py>` and :download:`the observation data <../../tutorials/simple_regression/linear_regression/linear_obs.dat>`, @@ -155,6 +155,7 @@ Now let us define the calibration tool. Note that the system type is changed :cl calibration = BayesianCalibration.from_dict( { "num_iter": 10, + "callback": run_sim, "system": { "system_type": IODynamicSystem, "param_min": [0.1, 0.1], @@ -167,7 +168,6 @@ Now let us define the calibration tool. Note that the system type is changed :cl "sim_name": 'linear', "sim_data_dir": './sim_data/', "sim_data_file_ext": '.txt', - "callback": run_sim, }, "calibration": { "inference": {"ess_target": 0.3}, @@ -291,6 +291,7 @@ and then create a new `calibration` object using :class:`.DynamicSystem`. calibration = BayesianCalibration.from_dict( { "num_iter": 0, + "callback": None, "system": { "system_type": DynamicSystem, "param_min": [0.1, 0.1], @@ -303,7 +304,6 @@ and then create a new `calibration` object using :class:`.DynamicSystem`. "obs_names": ['f'], "sim_name": 'linear', "sim_data": sim_data, - "callback": None, }, "calibration": { "inference": {"ess_target": 0.3}, diff --git a/grainlearning/bayesian_calibration.py b/grainlearning/bayesian_calibration.py index 9792e31..fa4115f 100644 --- a/grainlearning/bayesian_calibration.py +++ b/grainlearning/bayesian_calibration.py @@ -77,6 +77,7 @@ class BayesianCalibration: :param num_iter: Number of iteration steps :param curr_iter: Current iteration step :param save_fig: Flag for skipping (-1), showing (0), or saving (1) the figures + :param callback: A callback function that runs the external software and passes the parameter sample to generate outputs """ def __init__( self,