-
Notifications
You must be signed in to change notification settings - Fork 0
/
General_Functions_ACJ.py
143 lines (118 loc) · 5.77 KB
/
General_Functions_ACJ.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import numpy as np
import matplotlib.pyplot as plt
import lmfit as lm
from lmfit.models import GaussianModel, LorentzianModel, VoigtModel, LinearModel, ExponentialModel
import os
import h5py as h5
def normalize_data(arr, by_mean=False, id1=None, id2=None):
""" Normalize ydata in an array/list to go from 0 to 1
Args:
arr (list/np.ndarray): array to normalize
Returns:
(np.ndarray) Scaled arr on range [0,1]
"""
arr = np.array(arr)
if by_mean:
return (arr-np.mean(arr[id1:id2]))/(np.max(arr)-np.mean(arr[id1:id2]))
else:
return (arr-np.min(arr))/(np.max(arr)-np.min(arr))
def find_idx(wv, arr):
"""
Find the closest index for a specific wavenumber/wavelength/energy in an array of wavenumber/wavelength/energies
Args:
wv (int or float): Value you want the index of
arr (np.ndarray): Array of wavenumber/wavelength/energies
Returns:
i (int): the nearest index
"""
i = (np.abs(arr - wv)).argmin()
return i
def wv_range(x, wv1, wv2):
"""
For a given array of energies, find index closest to specific start/stop points
Args:
x (np.ndarray) : array of energies
wv1 (float or int) : first energy in range
wv2 (float or int) : last energy in range
Returns:
start, stop (int): indices in x to get nearest to wv1, wv2
"""
start = np.argmin(np.abs(x - wv1))
stop = np.argmin(np.abs(x - wv2))
return start, stop
def custom_function( x:np.ndarray, y:np.ndarray, npeaks:int, peakfunction:lm.models, backgroundfunction:lm.models, centers:list | np.ndarray, peaktol:float | int=100, diffpeaks:bool=False):
""""
Function to build custom lmfit model for an arbitrary spectra given spectra data, number of peaks to fit,
function to fit background, function to fit peaks (currently all peaks fit with same function)
Args:
x: xdata / energies
y: ydata / spectra to fit
npeaks (int): Number of peaks to fit
peakfunction (lmfit.models): Model to fit all peaks, typically LorenzianModel, GaussianModel, VoigtModel
backgroundfuction (lmfit.models): Model to fit background, typically ExponentialModel, LinearModel
centers (list): Initial guess for peak centers
peaktol (int or float): Min/max range for peak center in fitting
diffpeaks (bool): If you want to fit each peak to specific lorentzian/gaussian/voigt model
Returns:
out (lmfit.model.ModelResult): Model result
"""
bg_pre_dir = {ExponentialModel:'bgexp_', LinearModel:'bglin_'}
model = backgroundfunction(prefix=bg_pre_dir[backgroundfunction])
pars = model.guess(y, x=x)
if diffpeaks == False:
pre_dir = {ExponentialModel:'exp', GaussianModel:'g', LorentzianModel:'l', VoigtModel:'v'}
pre = pre_dir[peakfunction]
for n in np.arange(npeaks):
mod = peakfunction(prefix=f'{pre}{n}_')
init_center = centers[n]
pars += mod.guess(y, x=x, center=init_center)
pars[f'{pre}{n}_amplitude'].min = 0
pars[f'{pre}{n}_center'].min = init_center - peaktol
pars[f'{pre}{n}_center'].max = init_center + peaktol
# other constraints
model += mod
out = model.fit(y, pars, x=x)
return out
def create_sample_dict(data_dir, date, settings_i_want=[]):
sorted_files = os.listdir(data_dir + date)
sorted_files = [f for f in sorted_files if '.tif' in f or '.h5' in f]
sorted_files.sort()
sample_dict = {}
for f in sorted_files:
fn = f'{data_dir}{date}/{f}'
time = fn.split('/')[-1].split('_')[1]
# date = fn.split('/')[-1].split('_')[0]
measurement = '_'.join(fn.replace('.h5', '').split('/')[-1].split('_')[2:])
if 'h5' in f:
try:
file = h5.File(fn)
name = dict(file['app/settings'].attrs.items())['sample']
# if measurement == 'thor_cam_capture':
# settings_i_want = ['axis_3_position', 'axis_4_position']
# if measurement == 'time_sweep':
# settings_i_want = ['mod_freq', 'time_constant', 'filter_order', 'lockin_read_time', 'switch_time', 'end_time', 'step_time_high', 'step_time_low',
# 'axis_3_position', 'axis_4_position']
if name not in sample_dict.keys():
sample_dict[name] = {fn:{'time':time, 'measurement':measurement, 'settings' : extract_h5_settings_HiP(file, settings_i_want, measurement)}}
else:
sample_dict[name][fn] = {'time':time, 'measurement':measurement, 'settings' : extract_h5_settings_HiP(file, settings_i_want, measurement)}
except OSError:
pass
return sample_dict
def extract_h5_settings_HiP(file, settings_i_want, measurement):
"""
Extract desired settings from an h5 file
"""
settings = {}
all_settings = dict(file[f'measurement/{measurement}/settings'].attrs.items())
# TDTR_Lockin_settings = dict(file['hardware/TDTR_Lockin/settings'].attrs.items())
# picomotor_settings = dict(file['hardware/picomotor/settings'].attrs.items())
# all_settings.update(TDTR_Lockin_settings)
# all_settings.update(picomotor_settings)
for i_want in settings_i_want:
settings[i_want] = all_settings[i_want]
return settings
def find_nearest(array, value):
array = np.asarray(array)
idx = (np.abs(array - value)).argmin()
return array[idx]