Project configurationΒΆ

Alternative configurations can also be used with projects. When using cutom configurations in the project environment, the name of the configuration is key as this will determine where any data is saved. The below example shows what happens when using different configurations with a project.

The dataset in this example has been provided for use by the SAMTEX consortium. For more information, please refer to [Jones2009]. Additional details about the dataset can be found at https://www.mtnet.info/data/kap03/kap03.html.

from pathlib import Path
import seedir as sd
import plotly
from resistics.config import Configuration
import resistics.letsgo as letsgo
from resistics.time import TimeReaderNumpy, InterpolateNans, RemoveMean, Multiply
from resistics.decimate import DecimationSetup
from resistics.window import WindowSetup

# The first thing to do is define the configuration to use.
myconfig = letsgo.Configuration(
    name="myconfig",
    time_readers=[TimeReaderNumpy()],
    time_processors=[
        InterpolateNans(),
        RemoveMean(),
        Multiply(multiplier={"Ex": -1, "Ey": -1}),
    ],
    dec_setup=DecimationSetup(n_levels=7, per_level=3),
    win_setup=WindowSetup(min_size=64, min_olap=16),
)
myconfig.summary()

Out:

{
    'name': 'myconfig',
    'time_readers': [
        {
            'name': 'TimeReaderNumpy',
            'apply_scalings': True,
            'extension': '.npy'
        }
    ],
    'time_processors': [
        {'name': 'InterpolateNans'},
        {'name': 'RemoveMean'},
        {'name': 'Multiply', 'multiplier': {'Ex': -1.0, 'Ey': -1.0}}
    ],
    'dec_setup': {
        'name': 'DecimationSetup',
        'n_levels': 7,
        'per_level': 3,
        'min_samples': 256,
        'div_factor': 2,
        'eval_freqs': None
    },
    'decimator': {
        'name': 'Decimator',
        'resample': True,
        'max_single_factor': 3
    },
    'win_setup': {
        'name': 'WindowSetup',
        'min_size': 64,
        'min_olap': 16,
        'win_factor': 4,
        'olap_proportion': 0.25,
        'min_n_wins': 5,
        'win_sizes': None,
        'olap_sizes': None
    },
    'windower': {'name': 'Windower'},
    'fourier': {
        'name': 'FourierTransform',
        'win_fnc': ['kaiser', 14],
        'detrend': 'linear',
        'workers': -2
    },
    'spectra_processors': [],
    'evals': {'name': 'EvaluationFreqs'},
    'sensor_calibrator': {
        'name': 'SensorCalibrator',
        'chans': None,
        'readers': [
            {
                'name': 'SensorCalibrationJSON',
                'extension': '.json',
                'file_str': 'IC_$sensor$extension'
            }
        ]
    },
    'tf': {
        'name': 'ImpedanceTensor',
        'variation': 'default',
        'out_chans': ['Ex', 'Ey'],
        'in_chans': ['Hx', 'Hy'],
        'cross_chans': ['Hx', 'Hy'],
        'n_out': 2,
        'n_in': 2,
        'n_cross': 2
    },
    'regression_preparer': {'name': 'RegressionPreparerGathered'},
    'solver': {
        'name': 'SolverScikitTheilSen',
        'fit_intercept': False,
        'normalize': False,
        'n_jobs': -2,
        'max_subpopulation': 2000,
        'n_subsamples': None
    }
}

Save the configuration to a file. This is to imitate scenarios where users have an existing configuration file that they want to load in and use.

myconfig_path = Path("..", "..", "data", "config", "myconfig.json")
with myconfig_path.open("w") as f:
    f.write(myconfig.json())

Let’s remind ourselves of the project contents. Note that some processing with default parameters has already taken place.

project_path = Path("..", "..", "data", "project", "kap03")
sd.seedir(str(project_path), style="emoji")

Out:

πŸ“ kap03/
β”œβ”€πŸ“ images/
β”œβ”€πŸ“ time/
β”‚ β”œβ”€πŸ“ kap163/
β”‚ β”‚ β””β”€πŸ“ meas01/
β”‚ β”‚   β”œβ”€πŸ“„ data.npy
β”‚ β”‚   β””β”€πŸ“„ metadata.json
β”‚ β”œβ”€πŸ“ kap160/
β”‚ β”‚ β””β”€πŸ“ meas01/
β”‚ β”‚   β”œβ”€πŸ“„ data.npy
β”‚ β”‚   β””β”€πŸ“„ metadata.json
β”‚ β””β”€πŸ“ kap172/
β”‚   β””β”€πŸ“ meas01/
β”‚     β”œβ”€πŸ“„ data.npy
β”‚     β””β”€πŸ“„ metadata.json
β”œβ”€πŸ“„ resistics.json
β”œβ”€πŸ“ results/
β”‚ β””β”€πŸ“ kap160/
β”‚   β””β”€πŸ“ default/
β”‚     β””β”€πŸ“„ 0_200000_impedancetensor_default.json
β”œβ”€πŸ“ calibrate/
β”œβ”€πŸ“ evals/
β”‚ β””β”€πŸ“ kap160/
β”‚   β””β”€πŸ“ default/
β”‚     β””β”€πŸ“ meas01/
β”‚       β”œβ”€πŸ“„ data.npz
β”‚       β””β”€πŸ“„ metadata.json
β”œβ”€πŸ“ masks/
β”œβ”€πŸ“ spectra/
β””β”€πŸ“ features/

Now load our configuration and the project with myconfig.

config = Configuration.parse_file(myconfig_path)
resenv = letsgo.load(project_path, config=config)
resenv.config.summary()

Out:

{
    'name': 'myconfig',
    'time_readers': [
        {
            'name': 'TimeReaderNumpy',
            'apply_scalings': True,
            'extension': '.npy'
        }
    ],
    'time_processors': [
        {'name': 'InterpolateNans'},
        {'name': 'RemoveMean'},
        {'name': 'Multiply', 'multiplier': {'Ex': -1.0, 'Ey': -1.0}}
    ],
    'dec_setup': {
        'name': 'DecimationSetup',
        'n_levels': 7,
        'per_level': 3,
        'min_samples': 256,
        'div_factor': 2,
        'eval_freqs': None
    },
    'decimator': {
        'name': 'Decimator',
        'resample': True,
        'max_single_factor': 3
    },
    'win_setup': {
        'name': 'WindowSetup',
        'min_size': 64,
        'min_olap': 16,
        'win_factor': 4,
        'olap_proportion': 0.25,
        'min_n_wins': 5,
        'win_sizes': None,
        'olap_sizes': None
    },
    'windower': {'name': 'Windower'},
    'fourier': {
        'name': 'FourierTransform',
        'win_fnc': ['kaiser', 14.0],
        'detrend': 'linear',
        'workers': -2
    },
    'spectra_processors': [],
    'evals': {'name': 'EvaluationFreqs'},
    'sensor_calibrator': {
        'name': 'SensorCalibrator',
        'chans': None,
        'readers': [
            {
                'name': 'SensorCalibrationJSON',
                'extension': '.json',
                'file_str': 'IC_$sensor$extension'
            }
        ]
    },
    'tf': {
        'name': 'ImpedanceTensor',
        'variation': 'default',
        'out_chans': ['Ex', 'Ey'],
        'in_chans': ['Hx', 'Hy'],
        'cross_chans': ['Hx', 'Hy'],
        'n_out': 2,
        'n_in': 2,
        'n_cross': 2
    },
    'regression_preparer': {'name': 'RegressionPreparerGathered'},
    'solver': {
        'name': 'SolverScikitTheilSen',
        'fit_intercept': False,
        'normalize': False,
        'n_jobs': -2,
        'max_subpopulation': 2000,
        'n_subsamples': None
    }
}

Now calculate the evaluation frequency spectral data and view the directory structure. This shows how resistics handles saving data for different configurations. The data is placed in a new folder with the same name as the the configuration. This is why the configuration name is important.

site = resenv.proj["kap160"]
for meas in site:
    letsgo.process_time_to_evals(resenv, "kap160", meas.name)
sd.seedir(str(project_path), style="emoji")

Out:

πŸ“ kap03/
β”œβ”€πŸ“ images/
β”œβ”€πŸ“ time/
β”‚ β”œβ”€πŸ“ kap163/
β”‚ β”‚ β””β”€πŸ“ meas01/
β”‚ β”‚   β”œβ”€πŸ“„ data.npy
β”‚ β”‚   β””β”€πŸ“„ metadata.json
β”‚ β”œβ”€πŸ“ kap160/
β”‚ β”‚ β””β”€πŸ“ meas01/
β”‚ β”‚   β”œβ”€πŸ“„ data.npy
β”‚ β”‚   β””β”€πŸ“„ metadata.json
β”‚ β””β”€πŸ“ kap172/
β”‚   β””β”€πŸ“ meas01/
β”‚     β”œβ”€πŸ“„ data.npy
β”‚     β””β”€πŸ“„ metadata.json
β”œβ”€πŸ“„ resistics.json
β”œβ”€πŸ“ results/
β”‚ β””β”€πŸ“ kap160/
β”‚   β””β”€πŸ“ default/
β”‚     β””β”€πŸ“„ 0_200000_impedancetensor_default.json
β”œβ”€πŸ“ calibrate/
β”œβ”€πŸ“ evals/
β”‚ β””β”€πŸ“ kap160/
β”‚   β”œβ”€πŸ“ default/
β”‚   β”‚ β””β”€πŸ“ meas01/
β”‚   β”‚   β”œβ”€πŸ“„ data.npz
β”‚   β”‚   β””β”€πŸ“„ metadata.json
β”‚   β””β”€πŸ“ myconfig/
β”‚     β””β”€πŸ“ meas01/
β”‚       β”œβ”€πŸ“„ data.npz
β”‚       β””β”€πŸ“„ metadata.json
β”œβ”€πŸ“ masks/
β”œβ”€πŸ“ spectra/
β””β”€πŸ“ features/

Let’s calculate the impedance tensor with this configuration. The sampling frequency to process is 0.2 (Hz)

letsgo.process_evals_to_tf(resenv, 0.2, "kap160")
sd.seedir(str(project_path), style="emoji")

Out:

  0%|          | 0/21 [00:00<?, ?it/s]
 10%|9         | 2/21 [00:00<00:01, 14.49it/s]
 19%|#9        | 4/21 [00:00<00:01, 16.99it/s]
 52%|#####2    | 11/21 [00:00<00:00, 38.44it/s]
100%|##########| 21/21 [00:00<00:00, 58.99it/s]

  0%|          | 0/21 [00:00<?, ?it/s]
  5%|4         | 1/21 [00:03<01:01,  3.08s/it]
 10%|9         | 2/21 [00:06<00:58,  3.06s/it]
 14%|#4        | 3/21 [00:09<00:55,  3.06s/it]
 19%|#9        | 4/21 [00:10<00:41,  2.47s/it]
 24%|##3       | 5/21 [00:12<00:34,  2.14s/it]
 29%|##8       | 6/21 [00:13<00:29,  1.95s/it]
 33%|###3      | 7/21 [00:14<00:20,  1.46s/it]
 38%|###8      | 8/21 [00:14<00:14,  1.14s/it]
 43%|####2     | 9/21 [00:15<00:11,  1.07it/s]
 48%|####7     | 10/21 [00:15<00:07,  1.38it/s]
 52%|#####2    | 11/21 [00:15<00:05,  1.72it/s]
 57%|#####7    | 12/21 [00:16<00:04,  2.09it/s]
 62%|######1   | 13/21 [00:16<00:03,  2.66it/s]
 67%|######6   | 14/21 [00:16<00:02,  3.27it/s]
 71%|#######1  | 15/21 [00:16<00:01,  3.90it/s]
 76%|#######6  | 16/21 [00:16<00:01,  4.64it/s]
 81%|########  | 17/21 [00:16<00:00,  5.35it/s]
 86%|########5 | 18/21 [00:16<00:00,  5.97it/s]
 90%|######### | 19/21 [00:16<00:00,  6.74it/s]
 95%|#########5| 20/21 [00:17<00:00,  7.38it/s]
100%|##########| 21/21 [00:17<00:00,  7.88it/s]
100%|##########| 21/21 [00:17<00:00,  1.23it/s]
πŸ“ kap03/
β”œβ”€πŸ“ images/
β”œβ”€πŸ“ time/
β”‚ β”œβ”€πŸ“ kap163/
β”‚ β”‚ β””β”€πŸ“ meas01/
β”‚ β”‚   β”œβ”€πŸ“„ data.npy
β”‚ β”‚   β””β”€πŸ“„ metadata.json
β”‚ β”œβ”€πŸ“ kap160/
β”‚ β”‚ β””β”€πŸ“ meas01/
β”‚ β”‚   β”œβ”€πŸ“„ data.npy
β”‚ β”‚   β””β”€πŸ“„ metadata.json
β”‚ β””β”€πŸ“ kap172/
β”‚   β””β”€πŸ“ meas01/
β”‚     β”œβ”€πŸ“„ data.npy
β”‚     β””β”€πŸ“„ metadata.json
β”œβ”€πŸ“„ resistics.json
β”œβ”€πŸ“ results/
β”‚ β””β”€πŸ“ kap160/
β”‚   β”œβ”€πŸ“ default/
β”‚   β”‚ β””β”€πŸ“„ 0_200000_impedancetensor_default.json
β”‚   β””β”€πŸ“ myconfig/
β”‚     β””β”€πŸ“„ 0_200000_impedancetensor_default.json
β”œβ”€πŸ“ calibrate/
β”œβ”€πŸ“ evals/
β”‚ β””β”€πŸ“ kap160/
β”‚   β”œβ”€πŸ“ default/
β”‚   β”‚ β””β”€πŸ“ meas01/
β”‚   β”‚   β”œβ”€πŸ“„ data.npz
β”‚   β”‚   β””β”€πŸ“„ metadata.json
β”‚   β””β”€πŸ“ myconfig/
β”‚     β””β”€πŸ“ meas01/
β”‚       β”œβ”€πŸ“„ data.npz
β”‚       β””β”€πŸ“„ metadata.json
β”œβ”€πŸ“ masks/
β”œβ”€πŸ“ spectra/
β””β”€πŸ“ features/

Finally, let’s plot our the impedance tensor for this configuration

soln = letsgo.get_solution(
    resenv,
    "kap160",
    resenv.config.name,
    0.2,
    resenv.config.tf.name,
    resenv.config.tf.variation,
)
fig = soln.tf.plot(
    soln.freqs,
    soln.components,
    to_plot=["ExHy", "EyHx"],
    x_lim=[1, 5],
    res_lim=[1, 4],
    phs_lim=[0, 100],
    legend="128",
    symbol="circle",
)
fig.update_layout(height=900)
plotly.io.show(fig)

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

Gallery generated by Sphinx-Gallery