External variable - Bloch example

[1]:
import nexus as nx
import numpy as np
import matplotlib.pyplot as plt
[2]:
vel_1000, int_1000 = nx.data.Load("spectrum_1000K.txt", x_index = 0, intensity_index = 1)
vel_800, int_800 = nx.data.Load("spectrum_800K.txt", x_index = 0, intensity_index = 1)
vel_600, int_600 = nx.data.Load("spectrum_600K.txt", x_index = 0, intensity_index = 1)
vel_400, int_400 = nx.data.Load("spectrum_400K.txt", x_index = 0, intensity_index = 1)
vel_200, int_200 = nx.data.Load("spectrum_200K.txt", x_index = 0, intensity_index = 1)
[3]:
plt.plot(vel_1000, int_1000, label = "1000 K")
plt.plot(vel_800, int_800 + 4e3, label = "800 K")
plt.plot(vel_600, int_600 + 8e3, label = "600 K")
plt.plot(vel_400, int_400 + 12e3, label = "400 K")
plt.plot(vel_200, int_200 + 16e3, label = "200 K")
plt.legend()
plt.show()
../../_images/tutorial_optimization_nb_fit_external_variable_Bloch_3_0.png
[4]:
# create external fit parameters
Tc = nx.Var(1040, min = 1000, max= 1100, fit = True, id = "Tc")
M_0 = nx.Var(40, min = 30, max= 50, fit = True, id ="M_0")
exponent = nx.Var(1.2, min = 1, max= 2, fit = True,id = "exponent")

# create a Bloch model function
# M(T) = M(0)* (1-(T/Tc)^3/2)
# we want to be able to fit all parameters
# Only the temperature T is known from the experiment
def Bloch(T):
    # return a magnetic field value in Tesla
    return M_0.value * (1 - (T/Tc.value)**(exponent.value))

#check the function call
print(Bloch(100))
37.59220236152488
[5]:
# create the experiment in a for loop
# we assume that the oterh hyperfine parameters do not change individually
# we also want to fit the isomer shift as a common variable to all measurements
isomer_shift = nx.Var(0.5, min = -1, max = 1, fit = True, id = "isomer all")

# It is also possible to create additional Vars
# either in the function to be fit individually

# we can use the same beam object in each experient
beam = nx.Beam()
beam.Unpolarized()

# because the hyperfine parameters change we have to create new samples for each temperature
# also we have to pass the parameters of the experiment T and velocity and intensity data
def setup_specturm(temperature, velocity_data, intensity_data):
    site = nx.Hyperfine(weight=1,
                        isomer = isomer_shift,
                        # now assign the external function to the magnetic field of each experiment
                        # given by the Bloch function and the set temperature
                        magnetic_field = nx.Var(0, id="mag_at_"+str(temperature), equality = lambda: Bloch(temperature)),
                        isotropic = True)

    mat_Fe = nx.Material.Template(nx.lib.material.Fe)

    mat_Fe.hyperfine_sites = [site]

    layer_Fe = nx.Layer(id = "Fe",
                        material = mat_Fe,
                        thickness = 3000)

    sample = nx.Sample(layers = [layer_Fe])

    exp = nx.Experiment(beam = beam,
                        objects = [sample],
                        isotope = nx.lib.moessbauer.Fe57)

    spectrum = nx.MoessbauerSpectrum(experiment = exp,
                                     velocity = velocity_data,
                                     intensity_data = intensity_data)

    return spectrum
[6]:
# create list to loop over
temps = [200, 400, 600, 800, 1000]
vels = [vel_200, vel_400, vel_600, vel_800, vel_1000]
dats = [int_200, int_400, int_600, int_800, int_1000]
measurements = []

# create all spectra
for t, v, d in zip(temps, vels, dats):
    measurements.append(setup_specturm(t,v,d))
[7]:
fit = nx.Fit(measurements = measurements,
             id = "Bloch fit",
             external_fit_variables = [Tc, M_0, exponent])
[8]:
fit()

Run Fit instance with id: Bloch fit

Starting fit with 5 measurement data set(s) and 14 fit parameter(s):

  no. |                           id |       initial value |              min |              max
    0 |                   ES scaling |               87188 |                0 |       8.7188e+06
    1 |                    ES backgr |             8601.76 |                0 |           860176
    2 |                   isomer all |                 0.5 |               -1 |                1
    3 |                   ES scaling |               87193 |                0 |       8.7193e+06
    4 |                    ES backgr |             8603.46 |                0 |           860346
    5 |                   ES scaling |               87191 |                0 |       8.7191e+06
    6 |                    ES backgr |             8603.12 |                0 |           860312
    7 |                   ES scaling |               87188 |                0 |       8.7188e+06
    8 |                    ES backgr |             8600.74 |                0 |           860074
    9 |                   ES scaling |               87195 |                0 |       8.7195e+06
   10 |                    ES backgr |             8604.11 |                0 |           860411
   11 |                           Tc |                1040 |             1000 |             1100
   12 |                          M_0 |                  40 |               30 |               50
   13 |                     exponent |                 1.2 |                1 |                2

Using 5 equality constraint(s) on parameter(s):

  no. |                           id |               value
    0 |                   mag_at_200 |             34.4683
    1 |                   mag_at_400 |             27.2916
    2 |                   mag_at_600 |             19.3271
    3 |                   mag_at_800 |             10.8037
    4 |                  mag_at_1000 |             1.83898

Using 0 inequality constraint(s).


Calling ceres solver with fit method LevMar

Ceres Solver Report: Iterations: 23, Initial cost: 4.705323e+04, Final cost: 3.320816e+02, Termination: CONVERGENCE

Gradient error analysis.


Fit performed with algorithm:
LevMar
Error analysis:
Gradient

Using 14 fit parameter(s):

  no. |                           id |          fit value |   +/- std dev | initial value |          min |          max
    0 |                   ES scaling |             100264 |       745.629 |         87188 |            0 |   8.7188e+06
    1 |                    ES backgr |            270.396 |        637.54 |       8601.76 |            0 |       860176
    2 |                   isomer all |        -5.7666e-05 |   0.000458523 |           0.5 |           -1 |            1
    3 |                   ES scaling |             100756 |       745.619 |         87193 |            0 |   8.7193e+06
    4 |                    ES backgr |                  0 |       637.542 |       8603.46 |            0 |       860346
    5 |                   ES scaling |            99723.4 |       743.001 |         87191 |            0 |   8.7191e+06
    6 |                    ES backgr |            746.095 |       635.292 |       8603.12 |            0 |       860312
    7 |                   ES scaling |             100510 |       731.155 |         87188 |            0 |   8.7188e+06
    8 |                    ES backgr |            49.4251 |        625.16 |       8600.74 |            0 |       860074
    9 |                   ES scaling |             100510 |       502.502 |         87195 |            0 |   8.7195e+06
   10 |                    ES backgr |             66.952 |       429.619 |       8604.11 |            0 |       860411
   11 |                           Tc |            1043.14 |      0.153928 |          1040 |         1000 |         1100
   12 |                          M_0 |            39.1343 |     0.0137397 |            40 |           30 |           50
   13 |                     exponent |            1.49903 |    0.00139095 |           1.2 |            1 |            2

Correlation matrix:

  no. |        0        1        2        3        4        5        6        7        8        9       10       11       12       13
 -----|------------------------------------------------------------------------------------------------------------------------------
    0 |    1.000   -1.000    0.000    0.000   -0.000   -0.000    0.000   -0.000    0.000    0.000   -0.000    0.001    0.007   -0.005
    1 |   -1.000    1.000   -0.000   -0.000    0.000    0.000   -0.000    0.000   -0.000   -0.000    0.000   -0.001   -0.007    0.005
    2 |    0.000   -0.000    1.000    0.000   -0.000   -0.000    0.000    0.000   -0.000    0.000   -0.000    0.000    0.000   -0.000
    3 |    0.000   -0.000    0.000    1.000   -1.000    0.000   -0.000    0.000   -0.000   -0.000    0.000   -0.001    0.000    0.001
    4 |   -0.000    0.000   -0.000   -1.000    1.000   -0.000    0.000   -0.000    0.000    0.000   -0.000    0.001   -0.000   -0.001
    5 |   -0.000    0.000   -0.000    0.000   -0.000    1.000   -1.000    0.000   -0.000   -0.000    0.000   -0.003   -0.005    0.007
    6 |    0.000   -0.000    0.000   -0.000    0.000   -1.000    1.000   -0.000    0.000    0.000   -0.000    0.003    0.005   -0.007
    7 |   -0.000    0.000    0.000    0.000   -0.000    0.000   -0.000    1.000   -1.000    0.001   -0.001    0.003   -0.004    0.004
    8 |    0.000   -0.000   -0.000   -0.000    0.000   -0.000    0.000   -1.000    1.000   -0.001    0.001   -0.003    0.004   -0.004
    9 |    0.000   -0.000    0.000   -0.000    0.000   -0.000    0.000    0.001   -0.001    1.000   -1.000    0.198    0.063   -0.105
   10 |   -0.000    0.000   -0.000    0.000   -0.000    0.000   -0.000   -0.001    0.001   -1.000    1.000   -0.198   -0.063    0.105
   11 |    0.001   -0.001    0.000   -0.001    0.001   -0.003    0.003    0.003   -0.003    0.198   -0.198    1.000    0.416   -0.636
   12 |    0.007   -0.007    0.000    0.000   -0.000   -0.005    0.005   -0.004    0.004    0.063   -0.063    0.416    1.000   -0.902
   13 |   -0.005    0.005   -0.000    0.001   -0.001    0.007   -0.007    0.004   -0.004   -0.105    0.105   -0.636   -0.902    1.000

Using 5 equality constraint(s) on parameter(s):

  no. |                           id |               value
    0 |                   mag_at_200 |              35.844
    1 |                   mag_at_400 |              29.833
    2 |                   mag_at_600 |              22.054
    3 |                   mag_at_800 |              12.844
    4 |                  mag_at_1000 |               2.401

and 0 inequality constraint(s).

Total cost = 3.253e+02

cost for each FitMeasurement is:

  no. |                           id |                cost |                   %
    0 |                              |           6.117e+01 |              18.806
    1 |                              |           7.623e+01 |              23.435
    2 |                              |           6.012e+01 |              18.483
    3 |                              |           6.580e+01 |              20.229
    4 |                              |           6.196e+01 |              19.048

Fit instance with id "Bloch fit" finished.

[9]:
offset = 0
for t, v, d, m in zip(temps, vels, dats, measurements):
    int = m.Calculate()
    offset += max(int) * 0.05
    plt.plot(v, d + offset, label = str(t)+" K", marker='o', markersize = 2, linewidth=0)
    plt.plot(v, int + offset, color='grey')

plt.legend()
plt.show()
../../_images/tutorial_optimization_nb_fit_external_variable_Bloch_9_0.png