Export Algorithms to JSON#

This example demonstrates how to save algorithms including their configuration to json and load them again to ensure reproducibility.

The example will use StrideLevelParameter as example, but the same will work with all other algorithms (and Pipelines).

Warning

This json export only stores the Parameters of an algorithm and not any potential results!

Warning

While calling an Algorithms with the same parameters should produce the same results, you also need to ensure that the same version of gaitmap (and all other dependencies) is used to ensure full reproducibility. This means you should save the exact library version together with the json version of the used algorithms.

from pprint import pprint

To JSON#

In the following we will create an algorithm instance that itself has other nested algorithm objects. In the from the json output

from scipy.spatial.transform import Rotation

from gaitmap.base import BaseAlgorithm
from gaitmap.trajectory_reconstruction import ForwardBackwardIntegration, MadgwickAHRS, StrideLevelTrajectory

# Setting an initial orientation here, is pointless as it will be overwritten by StrideLevelTrajectory
# It is used here to demonstrate the ability to serialize Rotation objects.
custom_ori_method = MadgwickAHRS(beta=0.5, initial_orientation=Rotation.from_quat([0, 3, 3, 0]))
custom_pos_method = ForwardBackwardIntegration(turning_point=0.8)

slt = StrideLevelTrajectory(ori_method=custom_ori_method, pos_method=custom_pos_method, align_window_width=10)
pprint(slt.get_params())
{'align_window_width': 10,
 'ori_method': MadgwickAHRS(beta=0.5, initial_orientation=<scipy.spatial.transform._rotation.Rotation object at 0x7fee740d74e0>, memory=None),
 'ori_method__beta': 0.5,
 'ori_method__initial_orientation': <scipy.spatial.transform._rotation.Rotation object at 0x7fee740d74e0>,
 'ori_method__memory': None,
 'pos_method': ForwardBackwardIntegration(gravity=array([0.  , 0.  , 9.81]), level_assumption=True, steepness=0.08, turning_point=0.8),
 'pos_method__gravity': array([0.  , 0.  , 9.81]),
 'pos_method__level_assumption': True,
 'pos_method__steepness': 0.08,
 'pos_method__turning_point': 0.8,
 'trajectory_method': None}
{
    "_gaitmap_obj": "StrideLevelTrajectory",
    "params": {
        "align_window_width": 10,
        "ori_method": {
            "_gaitmap_obj": "MadgwickAHRS",
            "params": {
                "beta": 0.5,
                "initial_orientation": {
                    "_obj_type": "Rotation",
                    "quat": [
                        0.0,
                        0.7071067811865476,
                        0.7071067811865476,
                        0.0
                    ]
                },
                "memory": null
            }
        },
        "pos_method": {
            "_gaitmap_obj": "ForwardBackwardIntegration",
            "params": {
                "gravity": {
                    "_obj_type": "Array",
                    "array": [
                        0.0,
                        0.0,
                        9.81
                    ]
                },
                "level_assumption": true,
                "steepness": 0.08,
                "turning_point": 0.8
            }
        },
        "trajectory_method": null
    }
}

This output could now be stored in a file to document the exact parameters that were used for a specific analysis.

From JSON#

All algorithms can be loaded from json as well using the from_json method. This method can be called on any algorithm class and the Algorithm class specified in the json object is returned. To avoid confusion it is advisable to use either the exact algorithm class that was stored or BaseAlgorithm.

{'align_window_width': 10,
 'ori_method': MadgwickAHRS(beta=0.5, initial_orientation=<scipy.spatial.transform._rotation.Rotation object at 0x7fee740d7210>, memory=None),
 'ori_method__beta': 0.5,
 'ori_method__initial_orientation': <scipy.spatial.transform._rotation.Rotation object at 0x7fee740d7210>,
 'ori_method__memory': None,
 'pos_method': ForwardBackwardIntegration(gravity=array([0.  , 0.  , 9.81]), level_assumption=True, steepness=0.08, turning_point=0.8),
 'pos_method__gravity': array([0.  , 0.  , 9.81]),
 'pos_method__level_assumption': True,
 'pos_method__steepness': 0.08,
 'pos_method__turning_point': 0.8,
 'trajectory_method': None}

To show that you can call from_json from any Algorithm class we will perform the same import using the StrideLevelTrajectory.

{'align_window_width': 10,
 'ori_method': MadgwickAHRS(beta=0.5, initial_orientation=<scipy.spatial.transform._rotation.Rotation object at 0x7fee740d7b70>, memory=None),
 'ori_method__beta': 0.5,
 'ori_method__initial_orientation': <scipy.spatial.transform._rotation.Rotation object at 0x7fee740d7b70>,
 'ori_method__memory': None,
 'pos_method': ForwardBackwardIntegration(gravity=array([0.  , 0.  , 9.81]), level_assumption=True, steepness=0.08, turning_point=0.8),
 'pos_method__gravity': array([0.  , 0.  , 9.81]),
 'pos_method__level_assumption': True,
 'pos_method__steepness': 0.08,
 'pos_method__turning_point': 0.8,
 'trajectory_method': None}

Caching Support#

Note that the json export does not cover joblib.memory objects that some algorithms use to cache results. When you attempt to do this, you will get a warning with further information.

from gaitmap.stride_segmentation import BarthDtw

# Create a memory object. Usually you would pass the path to a cache dir.
mem = Memory()

instance = BarthDtw(memory=Memory())
pprint(instance.get_params())
{'conflict_resolution': True,
 'find_matches_method': 'find_peaks',
 'max_cost': 4.0,
 'max_match_length_s': 3.0,
 'max_signal_stretch_ms': None,
 'max_template_stretch_ms': None,
 'memory': Memory(location=None),
 'min_match_length_s': 0.6,
 'resample_template': True,
 'snap_to_min_axis': 'gyr_ml',
 'snap_to_min_win_ms': 300,
 'template': BarthOriginalTemplate(scaling=FixedScaler(offset=0, scale=500.0), use_cols=None),
 'template__scaling': FixedScaler(offset=0, scale=500.0),
 'template__scaling__offset': 0,
 'template__scaling__scale': 500.0,
 'template__use_cols': None}
/home/docs/checkouts/readthedocs.org/user_builds/gaitmap/checkouts/v2.5.0/gaitmap/base.py:77: UserWarning: Exporting `joblib.Memory` objects to json is not supported. The value will be replaced by `None` and caching needs to be reactivated after loading the object again. This can be using `instance.set_params(memory=Memory(...))`
  warnings.warn(
{
    "_gaitmap_obj": "BarthDtw",
    "params": {
        "conflict_resolution": true,
        "find_matches_method": "find_peaks",
        "max_cost": 4.0,
        "max_match_length_s": 3.0,
        "max_signal_stretch_ms": null,
        "max_template_stretch_ms": null,
        "memory": null,
        "min_match_length_s": 0.6,
        "resample_template": true,
        "snap_to_min_axis": "gyr_ml",
        "snap_to_min_win_ms": 300,
        "template": {
            "_gaitmap_obj": "BarthOriginalTemplate",
            "params": {
                "scaling": {
                    "_gaitmap_obj": "FixedScaler",
                    "params": {
                        "offset": 0,
                        "scale": 500.0
                    }
                },
                "use_cols": null
            }
        }
    }
}

If we now load the object again, the memory argument is empty. We need to set it again. If we use the same memory object or recreate a new memory object that points to the same cache-location, the same cache will be used as before.

loaded_instance = BarthDtw.from_json(json_str_cached)
print(loaded_instance.memory)
None

We can simply reactivate the memory.

{'conflict_resolution': True,
 'find_matches_method': 'find_peaks',
 'max_cost': 4.0,
 'max_match_length_s': 3.0,
 'max_signal_stretch_ms': None,
 'max_template_stretch_ms': None,
 'memory': Memory(location=None),
 'min_match_length_s': 0.6,
 'resample_template': True,
 'snap_to_min_axis': 'gyr_ml',
 'snap_to_min_win_ms': 300,
 'template': BarthOriginalTemplate(scaling=FixedScaler(offset=0, scale=500.0), use_cols=None),
 'template__scaling': FixedScaler(offset=0, scale=500.0),
 'template__scaling__offset': 0,
 'template__scaling__scale': 500.0,
 'template__use_cols': None}

Total running time of the script: ( 0 minutes 2.012 seconds)

Estimated memory usage: 9 MB

Gallery generated by Sphinx-Gallery