Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Hysteresis Processing walkthrough notebook

This notebook provides a step-by-step walk through of the processing of hysteresis loops. Each processing step is illustrated and described. This walk through can enable more granular data processing and illustrates the decision tree that is automatically implemented in the hysteresis_processing.ipynb.

Install and import packages

import pmagpy.rockmag as rmag
import pmagpy.ipmag as ipmag
import pmagpy.contribution_builder as cb

from bokeh.plotting import figure, show
from bokeh.io import output_notebook
output_notebook(hide_banner=True)
Loading...

Import local data in MagIC format

In this demonstration we will be using local data.

The data is from the following publication:

  • Swanson-Hysell, N. L., Avery, M. S., Zhang, Y., Hodgin, E. B., Sherwood, R. J., Apen, F. E., et al. (2021). The paleogeography of Laurentia in its early years: New constraints from the Paleoproterozoic East-Central Minnesota Batholith. Tectonics, 40, e2021TC006751. https://doi.org/10.1029/2021TC006751

# set the dir_path to the directory where the measurements.txt file is located
dir_path = '../example_data/ECMB'

# set the name of the MagIC file
ipmag.unpack_magic('magic_contribution_20213.txt', 
                     dir_path = dir_path,
                     input_dir_path = dir_path,
                     print_progress=False)

# create a contribution object from the tables in the directory
contribution = cb.Contribution(dir_path)
measurements = contribution.tables['measurements'].df
1  records written to file  /Users/penokean/0000_GitHub/RockmagPy-notebooks/example_data/ECMB/contribution.txt
1  records written to file  /Users/penokean/0000_GitHub/RockmagPy-notebooks/example_data/ECMB/locations.txt
90  records written to file  /Users/penokean/0000_GitHub/RockmagPy-notebooks/example_data/ECMB/sites.txt
312  records written to file  /Users/penokean/0000_GitHub/RockmagPy-notebooks/example_data/ECMB/samples.txt
1574  records written to file  /Users/penokean/0000_GitHub/RockmagPy-notebooks/example_data/ECMB/specimens.txt
17428  records written to file  /Users/penokean/0000_GitHub/RockmagPy-notebooks/example_data/ECMB/measurements.txt
-I- Using online data model
-I- Getting method codes from earthref.org
-I- Importing controlled vocabularies from https://earthref.org

Get hysteresis data from the measurements dataframe

The method codes relevant to hysteresis loops are:

  • LP-HYS for regular hysteresis loops

  • LP-HYS-O for hysteresis loops as a function of orientation

  • LP-HYS-T for hysteresis loops as a function of temperature

Inspect the original measurement level data

  • Below we investigate all the available specimens that have hysteresis data in the database for this contribution.

  • We extract the experimental data for an individual specimen.

measurements = measurements[measurements['method_codes'] == 'LP-HYS']
measurements.specimen.unique()
<StringArray> ['NED1-5c', 'NED18-2c', 'NED2-8c', 'NED4-1c', 'NED6-6c'] Length: 5, dtype: str
# filter and isolate specimen specific hysteresis loop data by specimen name
NED1_5c_hyst = measurements[measurements['specimen'] == 'NED1-5c'].reset_index(drop=True)
NED18_2c_hyst = measurements[measurements['specimen'] == 'NED18-2c'].reset_index(drop=True)
NED2_8c_hyst = measurements[measurements['specimen'] == 'NED2-8c'].reset_index(drop=True)
NED4_1c_hyst = measurements[measurements['specimen'] == 'NED4-1c'].reset_index(drop=True)
NED6_6c_hyst = measurements[measurements['specimen'] == 'NED6-6c'].reset_index(drop=True)

Let’s take a look at the columns relevant to hysteresis data processing

  • magn_mass is mass normalized magnetization (in Am^2/kg)

  • meas_field_dc is the applied DC field (in T)

NED18_2c_hyst[['magn_mass', 'meas_field_dc']]
Loading...

Visualize the raw data with plot_hyst_loop

  • The function returns a Bokeh plot object which can be further customized before displaying

NED18_2c_plot = rmag.plot_hyst_loop(NED18_2c_hyst['meas_field_dc'], NED18_2c_hyst['magn_mass'], 
                                          'NED18-2c', line_color='orange', line_width=1, label='NED18-2c', return_figure=True)
Loading...
Loading...

Loop processing

rockmagpy calculates the hysteresis loop parameters as available in the IRMDB software. Summary parameters can then be exported into the MagIC specimen data table.

Description of the image

The processing functions implement the protocol of Jackson and Solheid (2010) as realized in the hysteresis processing software of the Institute for Rock Magnetism (IRM). Paterson et al. (2018) present a related treatment of hysteresis data processing (implemented in HystLab) that is a complementary resource. This flowchart shows the decision tree for data processing.

Description of the image

Interpolate the raw data and re-grid them into an upper and a lower branch with exactly the same and symmetric field steps

  • The applied DC field values through the upper and lower branches during experiments are usually not exactly symmetric about the origin. We need to correct for the slight mismatching between the field steps by splitting the loop into an upper branch and a lower branch, interpolating the branches and unifying their field axis to be the same and be symmetric about 0.

  • The function rmag.grid_hyst_loop accomplishes this task.

NED18_2c_hyst_grid_field, NED18_2c_hyst_grid_magnetization = rmag.grid_hyst_loop(NED18_2c_hyst['meas_field_dc'], 
                                                                                       NED18_2c_hyst['magn_mass'])

NED18_2c_plot_grid = rmag.plot_hyst_loop(NED18_2c_hyst_grid_field, NED18_2c_hyst_grid_magnetization, specimen_name='NED18-2c', 
                                               p=NED18_2c_plot, line_color='goldenrod', label='NED18-2c gridded', legend_location='top_left', return_figure=True)
Loading...
Loading...

Perform linearity test on the whole loop

  • If the whole loop is linear, the sample is dominated by paramagnetic or diamagnetic materials and no ferromagnetic parameters can be estimated (the high-field slope is the result to report).

  • If the whole loop is not linear, we should move on to further processing.

  • The FNL statistic is a lack-of-fit F ratio from an ANOVA partition in which the upper branch and the inverted lower branch are treated as replicate measurements (Jackson and Solheid, 2010). FNL values above ~1.25 reject whole-loop linearity at 95% confidence for typical loop sizes.

  • The resulting stats dictionary from the hyst_linearity_test function has a key loop_is_linear with a boolean value that signals whether the loop is linear or not.

  • process_hyst_loop implements this as a decision-tree exit: a statistically linear loop terminates with only χHF reported (from the whole-loop regression) and the ferromagnetic parameters as NaN. Passing fit_linear_loop=True overrides the exit and processes the loop in full, which can be useful when a weak ferromagnetic signal near the noise level is of interest.

loop_linearity = rmag.hyst_linearity_test(NED18_2c_hyst_grid_field, NED18_2c_hyst_grid_magnetization)
loop_linearity
{'SST': 31.31588187151477, 'SSR': 29.911856290407343, 'SSD': 1.404025581107423, 'R_squared': 0.9551657019633689, 'SSPE': 0.000117113729198881, 'SSLF': 1.403908467378224, 'MSPE': 2.927843229972025e-07, 'MSLF': 0.0035274082094930255, 'MSR': 29.911856290407343, 'MSD': 0.0017594305527661941, 'FL': 17000.87351750237, 'FNL': 12047.804245061063, 'slope': 0.33421603926557925, 'intercept': 3.292628865865779e-05, 'loop_is_linear': False}

Loop centering

  • In the example case, the loop is not linear, so we need to isolate the ferromagnetic component from the paramagnetic component.

  • We need to center the loop to remove any offset in the field and moment axes that could be present in the data.

centering_results = rmag.hyst_loop_centering(NED18_2c_hyst_grid_field, NED18_2c_hyst_grid_magnetization)
NED18_2c_hyst_centered_H, NED18_2c_hyst_centered_M = centering_results['centered_H'], centering_results['centered_M']
NED18_2c_plot_centered = rmag.plot_hyst_loop(NED18_2c_hyst_centered_H, NED18_2c_hyst_centered_M, specimen_name='NED18-2c', p=NED18_2c_plot_grid, line_color='red', label='NED18-2c offset corrected', legend_location='top_left', return_figure=True)
Loading...
Loading...

Quality factor Q

Once the loop has been centered, the quality factor Q can be calculated. Following Jackson and Solheid (2010), Q is the decimal log of the signal/noise ratio, where the noise is quantified from the mean square mismatch between symmetrically equivalent moments of the offset-corrected loop. The convention used is Q=log10(1/1R2)Q = \log_{10}(1/\sqrt{1-R^2}), matching the IRM’s processing software and HystLab (Paterson et al., 2018, eq. 4); note that the corresponding equation as printed in Jackson and Solheid (2010) omits the square root, although the values reported in that paper include it (see Paterson et al., 2018). A higher value indicates better quality data. Note this value can deviate from that currently calculated in the IRM VSM Ferret as that value is estimated from the FNL statistic.

High Q values (e.g., 2 or greater) indicate that deviations from inversion symmetry due to all possible sources (noise, drift, and inherent asymmetry) are small. Conversely, low values indicate that at least one of these is significant. When Q falls below ~0.3 (signal/noise ~2) it becomes difficult to compute meaningful parameters for the loop, and when Q < 2 the automated processing skips the horizontal (field) offset correction because it cannot be robustly determined.

centering_results['Q']
2.4287561471446177

Loop drift correction

  • Sometimes spurious changes occur in measured signal strength on time scales comparable to that of the loop measurement. Drift is typically manifested by failure of loops to close, by lack of even symmetry in Mrh, and/or by failure of Mrh to decrease to zero in large (positive or negative) fields.

  • In many cases a correction is not strictly necessary as the drift signal is small. The default approach is to examine the smoothed error curve Me (the mismatch between the upper branch and the inverted lower branch) and determine whether a high-field drift correction or an upper branch drift correction is appropriate.

  • If you zoom in on the ~1 T region of the loop above, you will find that there is a slight difference between the beginning and end points.

  • The Me_drift_correction function corrects the drift by subtracting a smoothed Me curve either in the high-field region (when the largest errors occur above 75% of the maximum field) or over the entire upper branch of the loop.

NED18_2c_hyst_drift_corr_magnetization = rmag.Me_drift_correction(NED18_2c_hyst_centered_H, NED18_2c_hyst_centered_M)
NED18_2c_plot_drift_corr = rmag.plot_hyst_loop(NED18_2c_hyst_centered_H, NED18_2c_hyst_drift_corr_magnetization, specimen_name='NED18-2c', p=NED18_2c_plot_centered, line_color='blue', label='NED18-2c drift corrected', legend_location='top_left', return_figure=True)
Loading...
Loading...

Calculate the Mr (remanent magnetization), Mrh (remanence component), Mih (induced component), Me (error), Brh (field corresponding to 1/2 Mr)

  • The function calc_Mr_Mrh_Mih_Brh calculates these values and curves.

  • Mrh = (M+ - M-)/2 and Mih = (M+ + M-)/2 where M+ and M- are the upper and lower branches; for a well-behaved loop, Mrh is an even function of field and Mih is odd (Jackson and Solheid, 2010).

  • Below we print out the Mr value and Brh value.

H, Mr, Mrh, Mih, Me, Brh = rmag.calc_Mr_Mrh_Mih_Brh(NED18_2c_hyst_centered_H, NED18_2c_hyst_drift_corr_magnetization)
print('Mr: ', Mr, 'Brh: ', Brh)
Mr:  0.013721758647117336 Brh:  0.03653374612762557
NED18_2c_plot_drift_corr.line(H, Mrh, line_color='green', legend_label='Mrh', line_width=1)
NED18_2c_plot_drift_corr.line(H, Mih, line_color='purple', legend_label='Mih', line_width=1)
NED18_2c_plot_drift_corr.line(H, Me, line_color='brown', legend_label='Me', line_width=1)
show(NED18_2c_plot_drift_corr)
Loading...
Loading...

Test loop closure

  • When there are significant high coercivity components in the sample such as hematite or goethite, the hysteresis branches will not be overlapping at the highest applied fields.

  • In that case, hysteresis processing stops as we are not able to estimate Ms: the ferromagnetic and linear contributions cannot be separated, so process_hyst_loop reports the slope-independent parameters (Mr and Brh, computed from Mrh in which any linear-in-field contribution cancels) together with the data quality statistics (FNL, FNL60/70/80, Q, SNR, HAR), while Ms, χHF, and Bc are reported as NaN. Passing fit_open_loop=True (or NL_fit=True, which implies it) forces the high-field fit anyway---useful if residual instrument drift, rather than a genuinely open loop, trips the test.

  • If the loop is closed, we move on to the next step of testing loop saturation.

  • The loop_closure_test function tests loop closure using H, Mrh, and Me: the signal is the field-reflection average of Mrh in the high-field window (Mrh is an even function of field for a well-behaved loop, so this average estimates the true remanent hysteretic signal), and the noise is estimated from the high-field portion of the error curve Me, following the implementation in HystLab (Paterson et al., 2018, section 4.5). The loop is judged closed when the high-field signal-to-noise ratio is below 8 dB or the ratio of high-field to total Mrh area is below -48 dB.

loop_closure_test = rmag.loop_closure_test(H, Mrh, Me)
loop_closure_test['loop_is_closed']
False

Test loop saturation (high-field linearity test)

  • In the example case, the loop is closed, so we proceed to test the loop saturation. This test allows us to determine the appropriate approach for fitting the high-field portion of the loop and determining Ms.

  • The lack of saturation can cause a loop to deviate from linearity at high fields. Although such a deviation from linearity can be subtle to the eye, it can have a significant effect on estimates of Ms. As developed in Jackson and Solheid (2010), a linearity test is conducted over high-field windows starting at 60%, 70%, and 80% of the maximum field. If the loop statistically deviates from linearity in all of these windows (FNL > 2.5), it would be inappropriate to use a linear fit to the high-field data to correct for the paramagnetic or diamagnetic slope, and an approach-to-saturation fit is required. Otherwise, a linear fit is applied over the window starting at the lowest field fraction that is statistically linear (the saturation_cutoff).

  • In the example case, the loop is not saturated at 60%, 70%, and 80% of the maximum field range. Therefore, an approach to saturation fit needs to be used for isolating the ferromagnetic loop and then calculating the Ms and the high field susceptibility values.

loop_saturation_test_result = rmag.hyst_loop_saturation_test(NED18_2c_hyst_centered_H, NED18_2c_hyst_drift_corr_magnetization)
loop_saturation_test_result
{'FNL60': 98.71245833061079, 'FNL70': 25.24999808936752, 'FNL80': 17.47848462911585, 'saturation_cutoff': 0.92, 'loop_is_saturated': False}

Fit high-field slope and get the intercept as Ms

  • In this case, the loop is not saturated at high fields and we should use an approach to saturation fit to calculate the Ms value.

  • But to show the difference between a linear fit and a saturation fit, we will also perform a linear fit on the high-field data and use it to correct the loop.

  • We use the linear_HF_fit function to estimate the high-field susceptibility (and the Ms intercept in the case where the loop is saturated). Note that the returned chi_HF is the fitted slope converted to SI units (multiplied by μ0=4π×107\mu_0 = 4\pi \times 10^{-7}).

  • We then use the resultant chi_HF to correct the loop using the hyst_slope_correction function (which applies the inverse unit conversion internally).

chi_HF, Ms = rmag.linear_HF_fit(NED18_2c_hyst_centered_H, NED18_2c_hyst_drift_corr_magnetization, loop_saturation_test_result['saturation_cutoff'])

NED18_2c_hyst_linear_ferro_M = rmag.hyst_slope_correction(NED18_2c_hyst_centered_H, NED18_2c_hyst_drift_corr_magnetization, chi_HF)

print('Ms based on linear fitting: ', Ms)
Ms based on linear fitting:  0.11376164642895595
NED18_2c_plot_linear_ferro = rmag.plot_hyst_loop(NED18_2c_hyst_centered_H, NED18_2c_hyst_linear_ferro_M, 
                                                       specimen_name='NED18-2c', p=NED18_2c_plot_drift_corr, 
                                                       line_color='dodgerblue', label='NED18-2c linear high-field corrected', return_figure=True)
Loading...
Loading...

Perform approach-to-saturation fit and estimate a more appropriate Ms

  • In this example case, a linear fit would underestimate the Ms value.

  • A more appropriate Ms value can be estimated using a nonlinear approach-to-saturation fit with the hyst_HF_nonlinear_optimization function.

  • By default (fit_type='IRM'), the model used at the IRM is fit:

    M=χHFH+Ms+a1H1+a2H2M = \chi_{HF} H + M_s + a_1 H^{-1} + a_2 H^{-2}

    Alternative model forms of M=χHFH+Ms+αHβM = \chi_{HF} H + M_s + \alpha H^{\beta} (Fabian, 2006) are available with fit_type='Fabian' (free β\beta) and fit_type='Fabian_fixed_beta' (β=2\beta = -2).

  • The returned Fnl_lin statistic (Jackson and Solheid, 2010, eq. 21) tests whether the nonlinear fit significantly improves on a linear fit; values above ~3-3.5 indicate a significant improvement.

NL_fit_result = rmag.hyst_HF_nonlinear_optimization(NED18_2c_hyst_centered_H, NED18_2c_hyst_drift_corr_magnetization, 
                                                    HF_cutoff=0.6, fit_type='IRM')

NL_fit_result
{'chi_HF': 2.0311887043509852e-07, 'Ms': 0.1208155437705446, 'a_1': -1.8446127659932517e-21, 'a_2': -0.0016026252474735587, 'Fnl_lin': 150.88409867832559}

Now let’s use the approach-to-saturation fit result to correct the loop.

NED18_2c_hyst_NL_ferro_M = rmag.hyst_slope_correction(NED18_2c_hyst_centered_H, NED18_2c_hyst_drift_corr_magnetization, 
                                                      NL_fit_result['chi_HF'])

Plot the ferromagnetic component together with the previous intermediate products

  • You may click on the legend items to hide the curves

  • The preferred final ferromagnetic component is shown in pink

NED18_2c_plot_NL_ferro = rmag.plot_hyst_loop(NED18_2c_hyst_centered_H, NED18_2c_hyst_NL_ferro_M, 
                                                   specimen_name='NED18-2c', p=NED18_2c_plot_drift_corr, 
                                                   line_color='pink', label='NED18-2c non-linear high-field correction', 
                                                   legend_location='bottom_right', return_figure=True)
Loading...
Loading...

Inspect the differences between applying a linear high field slope fit vs. an approach-to-saturation fit

high_field_fit_inspection_plot = rmag.plot_hyst_loop(NED18_2c_hyst_centered_H, NED18_2c_hyst_NL_ferro_M, 
                                                   specimen_name='NED18-2c', 
                                                   line_color='pink', label='NED18-2c non-linear high-field correction', 
                                                   legend_location='bottom_right')
high_field_fit_inspection_plot = rmag.plot_hyst_loop(NED18_2c_hyst_centered_H, NED18_2c_hyst_linear_ferro_M, 
                                                       specimen_name='NED18-2c', p=high_field_fit_inspection_plot, 
                                                       line_color='dodgerblue', label='NED18-2c linear high-field corrected', return_figure=True)
Loading...
Loading...
Loading...
Loading...

Calculate the quality factor of the ferromagnetic component loop

Qf is the quality factor Q recomputed on the slope-corrected (ferromagnetic component) loop (the QfQ_f of Jackson and Solheid, 2010). The high-field slope correction affects the mean square signal strength but not the noise, so Qf quantifies the signal/noise of the isolated ferromagnetic loop.

M_sn_f, Qf = rmag.calc_Q(NED18_2c_hyst_centered_H, NED18_2c_hyst_NL_ferro_M)
print('Qf: ', Qf)
Qf:  3.4359428570949433

Calculate Bc

  • This calculation is based on the ferromagnetic component loop.

  • There will be a difference if you use the loops before high-field slope correction.

  • The Bc value is calculated as the average of the lower and upper branch.

  • The value shown is in unit of Tesla.

Bc = rmag.calc_Bc(NED18_2c_hyst_centered_H, NED18_2c_hyst_NL_ferro_M)
print('Bc: ', Bc)
Bc:  0.010038809582344791

The process_hyst_loop function

The process_hyst_loop function applies all of the above steps using the decision tree to process the data. The summary table includes the parameters developed above as well as the hysteresis shape parameter σhys=ln[Ehys/(4BcMs)]\sigma_{hys} = \ln[E_{hys}/(4 B_c M_s)] of Fabian (2003), where EhysE_{hys} is the area of the ferromagnetic loop. Options include NL_fit=True to force an approach-to-saturation fit, centering_protocol='iterative' for weak ferromagnetic loops superimposed on a strong linear background, and the decision-tree overrides fit_open_loop=True (proceed with the high-field fitting for a loop the closure test flags as open; implied by NL_fit=True) and fit_linear_loop=True (fully process a loop that passes the whole-loop linearity test).

NED18_2c_hyst_process_result = rmag.process_hyst_loop(NED18_2c_hyst['meas_field_dc'].values, NED18_2c_hyst['magn_mass'].values, 'NED18-2c')
Loading...
Loading...
Loading...
Loading...

References

Fabian, K. (2003). Some additional parameters to estimate domain state from isothermal magnetization measurements. Earth and Planetary Science Letters, 213(3-4), 337–345. https://doi.org/10.1016/S0012-821X(03)00329-7

Fabian, K. (2006). Approach to saturation analysis of hysteresis measurements in rock magnetism and evidence for stress dominated magnetic anisotropy in young mid-ocean ridge basalt. Physics of the Earth and Planetary Interiors, 154, 299–307. Fabian (2006)

Jackson, M., & Solheid, P. (2010). On the quantitative analysis and evaluation of magnetic hysteresis data. Geochemistry, Geophysics, Geosystems, 11(4), Q04Z15. Jackson & Solheid (2010)

Paterson, G. A., Zhao, X., Jackson, M., & Heslop, D. (2018). Measuring, processing, and analyzing hysteresis data. Geochemistry, Geophysics, Geosystems, 19(7), 1925–1945. Paterson et al. (2018)

Swanson-Hysell, N. L., Avery, M. S., Zhang, Y., Hodgin, E. B., Sherwood, R. J., Apen, F. E., et al. (2021). The paleogeography of Laurentia in its early years: New constraints from the Paleoproterozoic East-Central Minnesota Batholith. Tectonics, 40, e2021TC006751. Swanson‐Hysell et al. (2021)

References
  1. Fabian, K. (2006). Approach to saturation analysis of hysteresis measurements in rock magnetism and evidence for stress dominated magnetic anisotropy in young mid-ocean ridge basalt. Physics of the Earth and Planetary Interiors, 154(3–4), 299–307. 10.1016/j.pepi.2005.06.016
  2. Jackson, M., & Solheid, P. (2010). On the quantitative analysis and evaluation of magnetic hysteresis data. Geochemistry, Geophysics, Geosystems, 11(4). 10.1029/2009gc002932
  3. Paterson, G. A., Zhao, X., Jackson, M., & Heslop, D. (2018). Measuring, Processing, and Analyzing Hysteresis Data. Geochemistry, Geophysics, Geosystems, 19(7), 1925–1945. 10.1029/2018gc007620
  4. Swanson‐Hysell, N. L., Avery, M. S., Zhang, Y., Hodgin, E. B., Sherwood, R. J., Apen, F. E., Boerboom, T. J., Keller, C. B., & Cottle, J. M. (2021). The Paleogeography of Laurentia in Its Early Years: New Constraints From the Paleoproterozoic East‐Central Minnesota Batholith. Tectonics, 40(5). 10.1029/2021tc006751