ActiveCalibrationModel

lumicks.pylake.ActiveCalibrationModel

class ActiveCalibrationModel(driving_data, force_voltage_data, sample_rate, bead_diameter, driving_frequency_guess, viscosity=None, temperature=20, num_windows=5, hydrodynamically_correct=False, distance_to_surface=None, rho_sample=None, rho_bead=1060.0, fast_sensor=False, *, driving_sample_rate=None)

Model to fit data acquired during active calibration.

In active calibration, we oscillate the stage with a known frequency and amplitude. This introduces an extra peak in the power spectrum which allows the trap to be calibrated with fewer assumptions. This trades some precision for accuracy.

The power spectrum calibration algorithm implemented here is based on [1] [2] [3] [4] [5] [6]. Please refer to the theory section and tutorial on force calibration for more information on the calibration methods implemented.

Parameters:
  • driving_data (numpy.ndarray) – Array of driving data.

  • force_voltage_data (numpy.ndarray) – Uncalibrated force data in volts.

  • sample_rate (float) – Sample rate at which the signals were acquired.

  • bead_diameter (float) – Bead diameter [um].

  • driving_frequency_guess (float) – Guess of the driving frequency.

  • viscosity (float, optional) – Liquid viscosity [Pa*s]. When omitted, the temperature will be used to look up the viscosity of water at that particular temperature.

  • temperature (float, optional) – Liquid temperature [Celsius].

  • num_windows (int, optional) – Number of oscillations per window. Using a larger number of oscillations reduces the spectral scalloping loss, but comes at the cost of SNR (due to less averaging taking place).

  • hydrodynamically_correct (bool, optional) – Enable hydrodynamically correct model.

  • distance_to_surface (float, optional) – Distance from bead center to the surface [um] When specifying None, the model will use an approximation which is only suitable for measurements performed deep in bulk.

  • rho_sample (float, optional) – Density of the sample [kg/m**3]. Only used when using hydrodynamically correct model.

  • rho_bead (float, optional) – Density of the bead [kg/m**3]. Only used when using hydrodynamically correct model.

  • fast_sensor (bool) – Fast sensor? Fast sensors do not have the diode effect included in the model.

  • driving_sample_rate (float, optional) – Sample rate at which the driving frequency is sampled. When omitted the sample rate of the force data will be used (default: None).

driving_frequency

Estimated driving frequency [Hz].

Type:

float

driving_amplitude

Estimated driving amplitude [m].

Type:

float

viscosity

Liquid viscosity [Pa*s].

Type:

float, optional

Raises:
  • ValueError – If physical parameters are provided that are outside their sensible range.

  • ValueError – If the distance from the bead center to the surface is set smaller than the bead radius.

  • ValueError – If the hydrodynamically correct model is enabled, but the distance to the surface is specified below 0.75 times the bead diameter (this model is not valid so close to the surface).

  • NotImplementedError – If the hydrodynamically correct model is selected in conjunction with axial force calibration.

  • RuntimeError – If the driving peak can’t be found near the guess of its frequency.

References

Examples

f = lk.File("near_surface_active_calibration.h5")

force_slice = f.force1x

# Decalibrate existing data
volts = force_slice / force_slice.calibration[0]["Response (pN/V)"]

power_spectrum = lk.calculate_power_spectrum(
    volts.data,
    sample_rate=volts.sample_rate,
    excluded_ranges=[[4400, 4500]],  # Exclude a noise peak
    num_points_per_block=350,
)

model = lk.ActiveCalibrationModel(
    f["Nanostage position"]["X"].data,  # Driving data
    volts.data,  # Position sensitive detector data
    temperature=25,
    sample_rate=volts.sample_rate,
    bead_diameter=4.89,
    driving_frequency_guess=37,  # Have to provide a guess for the frequency
    hydrodynamically_correct=True,  # Big bead, so use hydrodynamic model
    distance_to_surface=10,  # Experiment performed 10 microns from surface
    driving_sample_rate=f["Nanostage position"]["X"].sample_rate,
)

print(model.driving_frequency)  # Verify correct frequency determination

fit = lk.fit_power_spectrum(power_spectrum, model)
fit.plot()
__call__(f, fc, diffusion_constant, *filter_params) ndarray

Call self as a function.

calibration_results(fc, diffusion_constant_volts, filter_params, fc_err, diffusion_constant_volts_err, filter_params_err) dict

Compute active calibration parameters from cutoff frequency and diffusion constant.

Parameters:
  • fc (float) – Corner frequency, in Hz.

  • diffusion_constant_volts (float) – Diffusion constant, in V^2/s

  • filter_params (list of float) – Parameters for the filter model.

  • fc_err (float) – Corner frequency standard error, in Hz

  • diffusion_constant_volts_err (float) – Diffusion constant standard error, in Hz

  • filter_params_err (list of float) – Standard errors for the filter model