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 |               87159 |            1e-16 |       8.7159e+06
    1 |                    ES backgr |             8602.84 |                0 |           860284
    2 |                   isomer all |                 0.5 |               -1 |                1
    3 |                   ES scaling |               87177 |            1e-16 |       8.7177e+06
    4 |                    ES backgr |             8604.19 |                0 |           860419
    5 |                   ES scaling |               87185 |            1e-16 |       8.7185e+06
    6 |                    ES backgr |             8604.69 |                0 |           860469
    7 |                   ES scaling |               87182 |            1e-16 |       8.7182e+06
    8 |                    ES backgr |             8600.63 |                0 |           860063
    9 |                   ES scaling |               87190 |            1e-16 |        8.719e+06
   10 |                    ES backgr |             8606.13 |                0 |           860613
   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.429313e+04, Final cost: 3.090389e+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 |            99219.2 |       798.158 |         87159 |        1e-16 |   8.7159e+06
    1 |                    ES backgr |            1156.36 |       682.626 |       8602.84 |            0 |       860284
    2 |                   isomer all |         0.00049078 |   0.000492938 |           0.5 |           -1 |            1
    3 |                   ES scaling |            99312.6 |       797.726 |         87177 |        1e-16 |   8.7177e+06
    4 |                    ES backgr |             1089.7 |       682.258 |       8604.19 |            0 |       860419
    5 |                   ES scaling |            99458.7 |         791.2 |         87185 |        1e-16 |   8.7185e+06
    6 |                    ES backgr |            970.047 |       676.672 |       8604.69 |            0 |       860469
    7 |                   ES scaling |            99464.4 |       768.868 |         87182 |        1e-16 |   8.7182e+06
    8 |                    ES backgr |            924.201 |       657.568 |       8600.63 |            0 |       860063
    9 |                   ES scaling |             100155 |       524.807 |         87190 |        1e-16 |    8.719e+06
   10 |                    ES backgr |            373.908 |       448.809 |       8606.13 |            0 |       860613
   11 |                           Tc |            1042.85 |      0.165413 |          1040 |         1000 |         1100
   12 |                          M_0 |            39.1217 |     0.0147747 |            40 |           30 |           50
   13 |                     exponent |            1.49983 |    0.00149505 |           1.2 |            1 |            2

    Values at boundaries:

Correlation matrix:

  no. |        0        1        2        3        4        5        6        7        8        9       10       11       12       13
 -----|------------------------------------------------------------------------------------------------------------------------------
    0 |    1.000   -1.000    0.001    0.000   -0.000   -0.000    0.000   -0.000    0.000    0.000   -0.000    0.001    0.005   -0.003
    1 |   -1.000    1.000   -0.001   -0.000    0.000    0.000   -0.000    0.000   -0.000   -0.000    0.000   -0.001   -0.005    0.003
    2 |    0.001   -0.001    1.000   -0.001    0.001    0.000   -0.000   -0.000    0.000   -0.000    0.000   -0.001   -0.000    0.000
    3 |    0.000   -0.000   -0.001    1.000   -1.000    0.000   -0.000    0.000   -0.000   -0.000    0.000   -0.002    0.000    0.002
    4 |   -0.000    0.000    0.001   -1.000    1.000   -0.000    0.000   -0.000    0.000    0.000   -0.000    0.002   -0.000   -0.002
    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.008
    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.008
    7 |   -0.000    0.000   -0.000    0.000   -0.000    0.000   -0.000    1.000   -1.000    0.001   -0.001    0.004   -0.005    0.005
    8 |    0.000   -0.000    0.000   -0.000    0.000   -0.000    0.000   -1.000    1.000   -0.001    0.001   -0.004    0.005   -0.005
    9 |    0.000   -0.000   -0.000   -0.000    0.000   -0.000    0.000    0.001   -0.001    1.000   -1.000    0.196    0.063   -0.104
   10 |   -0.000    0.000    0.000    0.000   -0.000    0.000   -0.000   -0.001    0.001   -1.000    1.000   -0.196   -0.063    0.104
   11 |    0.001   -0.001   -0.001   -0.002    0.002   -0.003    0.003    0.004   -0.004    0.196   -0.196    1.000    0.414   -0.635
   12 |    0.005   -0.005   -0.000    0.000   -0.000   -0.005    0.005   -0.005    0.005    0.063   -0.063    0.414    1.000   -0.902
   13 |   -0.003    0.003    0.000    0.002   -0.002    0.008   -0.008    0.005   -0.005   -0.104    0.104   -0.635   -0.902    1.000

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

  no. |                           id |               value
    0 |                   mag_at_200 |              35.835
    1 |                   mag_at_400 |              29.827
    2 |                   mag_at_600 |              22.047
    3 |                   mag_at_800 |              12.835
    4 |                  mag_at_1000 |               2.386

and 0 inequality constraint(s).

Total cost = 1.207e+00

cost for each FitMeasurement is:

  no. |                           id |                cost |                   %
    0 |                              |           2.254e-01 |              18.670
    1 |                              |           2.386e-01 |              19.761
    2 |                              |           2.399e-01 |              19.875
    3 |                              |           2.466e-01 |              20.428
    4 |                              |           2.567e-01 |              21.266

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