Fitting#

The workflow of transport research is centered around fitting a model to experimental data. This package provides convenient tools for this exact task to make the process as smooth as possible.

Loading data#

First, you can load your data from various files separated by the different variables of the experiment. For example, for ADMR, suppose you have a file for every combination of field and azimuthal angle (\(\phi\)) and the polar angle (\(\theta\)) varies in each file. Then, your data folder structure should look something like this:

data/
    ADMR_10072025_phi=0_B=2.csv
    ADMR_10072025_phi=0_B=5.csv
    ADMR_11072025_phi=15_B=2.csv
    ADMR_11072025_phi=15_B=5.csv
    ADMR_12072025_phi=30_B=2.csv
    ADMR_12072025_phi=30_B=5.csv
    ADMR_12072025_phi=45_B=2.csv
    ADMR_12072025_phi=45_B=5.csv

It might also be separed into subfolders. The important thing is that the file names contain all the information about the experiment. With such data, you can use elecboltz.Loader to automatically load the data into arrays usable by the fitting functions of the package.

import elecboltz

loader = elecboltz.Loader(
    x_vary_label='theta', y_label='rho_zz',
    x_search={'phi': [0, 0, 15, 15, 30, 30, 45, 45],
              'B': [2, 5, 2, 5, 2, 5, 2, 5]})
loader.load("data/ADMR_NdLSCO", "ADMR_",
            x_columns=[0], y_columns=[1], y_units=1e-5)

You can also let the loader find the values by itself using the save_new_labels and save_new_values parameters.

Now, fitting all the data at once is goint to be very computationally expensive. Also, we might want to normalize the data first before fitting. We can do both using the interpolate method of the loader.

loader.interpolate(30, x_normalize=0)

This will interpolate each data set to 30 points, and normalize the data by the value at x=0. For our ADMR example, this would be at \(\theta=0^\circ\).

To learn more about the loader, check the Loader’s API documentation:.

Fitting Routine#

After loading the data, you can set the ranges and the initial parameters and feed it into the fitter.

init_params = {
    'a': 3.75,
    'b': 3.75,
    'c': 13.2,
    'energy_scale': 160,
    'band_params': {'mu':-0.82439881, 't': 1, 'tp':-0.13642799,
                    'tpp':0.06816836, 'tz':0.06512192},
    'domain_size': [1.0, 1.0, 2.0],
    'periodic': 2,
    'scattering_models': ['isotropic', 'cos2phi'],
    'scattering_params': {'gamma_0': 12, 'gamma_k': 60, 'power': 12},
    'resolution': 41,
}

bounds = {
    'band_params': {
        'tz': (0.01, 0.1)
    },
    'scattering_params': {
        'gamma_0': (5, 20),
        'gamma_k': (10, 200),
        'power': (1, 20)
    },
}

elecboltz.fit_model(
    loader.x_data, loader.y_data, init_params=init_params,
    bounds=bounds, save_path="fit", save_label="ADMR", workers=4)

That’s it! The output will be saved to the fit/ADMR.json file, and the logs will be saved to fit/ADMR.log and also printed to the console.

To learn more about the fitting routine, check the Fitter’s API documentation:.