dsc: only use low temperature to baseline correct calibration without enthalpy

This commit is contained in:
Dominik Demuth 2023-05-16 19:22:50 +02:00
parent 753cd06dd1
commit b127cc15e2

View File

@ -5,6 +5,8 @@ import re
from collections import namedtuple from collections import namedtuple
import numpy as np import numpy as np
from matplotlib import pyplot as plt
from scipy.stats import linregress
try: try:
from scipy.integrate import simpson from scipy.integrate import simpson
@ -200,35 +202,24 @@ class DSCCalibrator:
high_border = np.argmin(np.abs(measurement[0] - t_high_lim)) high_border = np.argmin(np.abs(measurement[0] - t_high_lim))
ref_zoom = measurement[:, low_border:high_border] ref_zoom = measurement[:, low_border:high_border]
x_val = np.array([[ref_zoom[0, 0], 1], [ref_zoom[0, -1], 1]])
y_val = np.array([ref_zoom[1, 0], ref_zoom[1, -1]])
sol = np.linalg.solve(x_val, y_val)
ref_zoom[1] -= (ref_zoom[0] * sol[0] + sol[1])
ref_grad = np.gradient(ref_zoom[1])
crossing = np.where(np.diff(np.sign(np.abs(ref_grad)-0.001)))[0]
almost_flat = np.sort(crossing-np.argmax(ref_zoom[1]))
integ_limit = (almost_flat[np.where((almost_flat < -20))[0][-1]]+np.argmax(ref_zoom[1]),
almost_flat[np.where((almost_flat > 20))[0][0]]+np.argmax(ref_zoom[1]))
# subtract baseline around reference peak
sol = self.solve_linear_eq(integ_limit, ref_zoom)
ref_zoom[1] -= (ref_zoom[0] * sol[0] + sol[1])
# calculate onset slope (use points at position of maximum gradient - 100/rate (+50/rate))
ref_grad = np.gradient(ref_zoom[1])
max_grad = np.argmax(ref_grad)
grad_pos = max_grad-max(1, int(160 / rate)), max_grad
sol = self.solve_linear_eq(grad_pos, ref_zoom)
onset = sol[0] * ref_zoom[0] + sol[1]
melts.append(-sol[1] / sol[0])
if enthalpy is not None: if enthalpy is not None:
x_val = np.array([[ref_zoom[0, 0], 1], [ref_zoom[0, -1], 1]])
y_val = np.array([ref_zoom[1, 0], ref_zoom[1, -1]])
sol = np.linalg.solve(x_val, y_val)
ref_zoom[1] -= (ref_zoom[0] * sol[0] + sol[1])
ref_grad = np.gradient(ref_zoom[1])
crossing = np.where(np.diff(np.sign(np.abs(ref_grad)-0.001)))[0]
almost_flat = np.sort(crossing-np.argmax(ref_zoom[1]))
integ_limit = (almost_flat[np.where((almost_flat < -40))[0][-1]]+np.argmax(ref_zoom[1]),
almost_flat[np.where((almost_flat > 40))[0][0]]+np.argmax(ref_zoom[1]))
# subtract baseline around reference peak
sol = self.solve_linear_eq(integ_limit, ref_zoom)
ref_zoom[1] -= (ref_zoom[0] * sol[0] + sol[1])
# integrate over peak to calibrate y axis # integrate over peak to calibrate y axis
# delta H in J/g: Integrate Peak over time and divide by weight # delta H in J/g: Integrate Peak over time and divide by weight
area = simpson(ref_zoom[1, integ_limit[0]:integ_limit[1]], area = simpson(ref_zoom[1, integ_limit[0]:integ_limit[1]],
@ -236,6 +227,23 @@ class DSCCalibrator:
even='avg') * 1e-3 even='avg') * 1e-3
calib_y.append(enthalpy / (area / data.weight)) calib_y.append(enthalpy / (area / data.weight))
else:
ref_grad = np.gradient(ref_zoom[1])
res = linregress(ref_zoom[0, :len(ref_grad)//5], ref_zoom[1, :len(ref_grad)//5])
ref_zoom[1] -= (res.slope*ref_zoom[0] + res.intercept)
# calculate onset slope (use points at position of maximum gradient - 100/rate (+50/rate))
ref_grad = np.gradient(ref_zoom[1])
max_grad = np.argmax(ref_grad)
grad_pos = max_grad - max(1, int(160 / rate)), max_grad
sol = self.solve_linear_eq(grad_pos, ref_zoom)
onset = sol[0] * ref_zoom[0] + sol[1]
melts.append(-sol[1] / sol[0])
results.append([ref_zoom, onset, ref_zoom[:, grad_pos]]) results.append([ref_zoom, onset, ref_zoom[:, grad_pos]])
if len(melts) > 1: if len(melts) > 1: