.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/dev_guides/_01_pretrained_models.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_dev_guides__01_pretrained_models.py: Pretrained models and predefined Parameters =========================================== All mobgap algorithms are implemented as tpcp classes (see :class:`tpcp.Algorithm`). Hence, all there configuration is stored in the parameters of the class. Each algorithm already has sensible default parameters, which can be used for many applications. However, for some algorithms we have some known good parameters for specific use cases. For example, for the usage in specific clinical cohorts. Similarly, the machine learning based algorithms have a set of pretrained models that we provide with the package. For both cases, we need a good way to make these parameters and models available to the user. Below, we show the agreed upon way to do this. For reference about the discussion, see `GitHub Issue `_. The basic idea is to add a static inner class to the algorithm class, which contains the parameters and models. In the easiest case, these are just dictionaries. If more complex configuration is needed, we can use the ``property`` decorator to load these parameters from a file. In both cases we wrap the returned dictionaries in ``MappingProxyType`` to make them readonly, to make sure the user does not accidentally change the predefined parameters using the ``update`` method of the dict. The simple case --------------- For a real world implementation see :class:`mobgap.wba.WbAssembly`. For the simple case we just add a static inner class to the algorithm class. For the example we assume that the algorithm has two parameters ``param1`` and ``param2`` and we assume that we have two sets of predefined parameters for healthy and pathological gait. We will omit the algorithm implementation (aka the action method) here, as it is not relevant for the example. .. GENERATED FROM PYTHON SOURCE LINES 33-53 .. code-block:: default from types import MappingProxyType from typing import Optional import tpcp class MyAlgorithm(tpcp.Algorithm): param1: float param2: str def __init__(self, param1: float = 2, param2: str = "foo"): self.param1 = param1 self.param2 = param2 class PredefinedParameters: healthy = MappingProxyType({"param1": 1, "param2": "healthy"}) pathological = MappingProxyType({"param1": 3, "param2": "pathological"}) .. GENERATED FROM PYTHON SOURCE LINES 54-55 Now we can use the predefined parameters as follows: .. GENERATED FROM PYTHON SOURCE LINES 55-60 .. code-block:: default healthy_params = MyAlgorithm.PredefinedParameters.healthy algo_with_healthy_params = MyAlgorithm(**healthy_params) algo_with_healthy_params.get_params() .. rst-class:: sphx-glr-script-out .. code-block:: none {'param1': 1, 'param2': 'healthy'} .. GENERATED FROM PYTHON SOURCE LINES 61-64 This way, we can easily store a set of different parameters for different use cases. Users are still able to overwrite the parameters, if they want to. For example, only use the predefined parameters for some parameters and overwrite others: .. GENERATED FROM PYTHON SOURCE LINES 64-70 .. code-block:: default pathological_params = MyAlgorithm.PredefinedParameters.pathological algo_with_custom_pathological_params = MyAlgorithm( **dict(pathological_params, param2="bar") ) algo_with_custom_pathological_params.get_params() .. rst-class:: sphx-glr-script-out .. code-block:: none {'param1': 3, 'param2': 'bar'} .. GENERATED FROM PYTHON SOURCE LINES 71-72 Other possible syntax versions (based on preference): .. GENERATED FROM PYTHON SOURCE LINES 72-78 .. code-block:: default pathological_params = MyAlgorithm.PredefinedParameters.pathological algo_with_custom_pathological_params = MyAlgorithm( **{**pathological_params, "param2": "bar"} ) algo_with_custom_pathological_params.get_params() .. rst-class:: sphx-glr-script-out .. code-block:: none {'param1': 3, 'param2': 'bar'} .. GENERATED FROM PYTHON SOURCE LINES 79-80 Or .. GENERATED FROM PYTHON SOURCE LINES 80-86 .. code-block:: default pathological_params = MyAlgorithm.PredefinedParameters.pathological algo_with_custom_pathological_params = MyAlgorithm( **(pathological_params | dict(param2="bar")) ) algo_with_custom_pathological_params.get_params() .. rst-class:: sphx-glr-script-out .. code-block:: none {'param1': 3, 'param2': 'bar'} .. GENERATED FROM PYTHON SOURCE LINES 87-88 Or by using set params: .. GENERATED FROM PYTHON SOURCE LINES 88-93 .. code-block:: default algo_with_custom_pathological_params = MyAlgorithm(**pathological_params) algo_with_custom_pathological_params.set_params(param2="bar") algo_with_custom_pathological_params.get_params() .. rst-class:: sphx-glr-script-out .. code-block:: none {'param1': 3, 'param2': 'bar'} .. GENERATED FROM PYTHON SOURCE LINES 94-97 Depending on the specific case, we can also use one of the predefined parameters as default values for the constructor. We can use the :func:`tpcp.misc.set_defaults` function to do this easily. .. GENERATED FROM PYTHON SOURCE LINES 97-121 .. code-block:: default from tpcp.misc import set_defaults class MyAlgorithm(tpcp.Algorithm): param1: float param2: str class PredefinedParameters: healthy = MappingProxyType({"param1": 1, "param2": "healthy"}) pathological = MappingProxyType({"param1": 3, "param2": "pathological"}) @set_defaults(**PredefinedParameters.healthy) def __init__( self, param1: float, param2: str, ): self.param1 = param1 self.param2 = param2 algo = MyAlgorithm() algo.get_params() .. rst-class:: sphx-glr-script-out .. code-block:: none {'param1': 1, 'param2': 'healthy'} .. GENERATED FROM PYTHON SOURCE LINES 122-135 Loading parameters from a file (or other source) ------------------------------------------------ Sometimes, we have a lot of parameters, that we don't want to hardcode in the source code, or we want to include objects in the parameters that can not be easily hardcoded (e.g. a trained machine learning model). In this case, we can use the :class:`~tpcp.misc.classproperty`` decorator to load the parameters from a file (or any other source). As our parameter class is "just" a class, we can easily add such a property to it. Let's assume our algorithm has an additional parameter ``model`` that takes an optional pre-trained ML model. We will provide different versions of predefined parameters, that use different models. For the example, we will not actually load a model, but just use a string. .. GENERATED FROM PYTHON SOURCE LINES 135-178 .. code-block:: default from tpcp.misc import classproperty class MyAlgorithm(tpcp.Algorithm): param1: float param2: str model: Optional[str] class PredefinedParameters: @classmethod def _load_from_file(cls, model_name): # Load the model from a file here # We could even add a cashing mechanism here, if we want to avoid loading the model multiple times. print(f"Loading model {model_name} from file") return "model_" + model_name @classproperty def healthy(cls): # Load the model from a file here model = cls._load_from_file("healthy") return MappingProxyType( {"param1": 1, "param2": "healthy", "model": model} ) @classproperty def pathological(cls): # Load the model from a file here model = cls._load_from_file("pathological") return MappingProxyType( {"param1": 3, "param2": "pathological", "model": model} ) def __init__( self, param1: float = 2, param2: str = "foo", model: Optional[str] = None, ): self.param1 = param1 self.param2 = param2 self.model = model .. GENERATED FROM PYTHON SOURCE LINES 179-181 Now we can use the predefined parameters as before, but the file loading is only done when we actually use the parameters, and we avoid loading all the models into memory at the beginning. .. GENERATED FROM PYTHON SOURCE LINES 181-185 .. code-block:: default healthy_params = MyAlgorithm.PredefinedParameters.healthy healthy_params .. rst-class:: sphx-glr-script-out .. code-block:: none Loading model healthy from file mappingproxy({'param1': 1, 'param2': 'healthy', 'model': 'model_healthy'}) .. GENERATED FROM PYTHON SOURCE LINES 186-188 .. code-block:: default algo_with_healthy_params = MyAlgorithm(**healthy_params) algo_with_healthy_params.get_params() .. rst-class:: sphx-glr-script-out .. code-block:: none {'model': 'model_healthy', 'param1': 1, 'param2': 'healthy'} .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 1.689 seconds) **Estimated memory usage:** 9 MB .. _sphx_glr_download_auto_examples_dev_guides__01_pretrained_models.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: _01_pretrained_models.py <_01_pretrained_models.py>` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: _01_pretrained_models.ipynb <_01_pretrained_models.ipynb>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_