pyTEMlib 0.2025.4.2__py3-none-any.whl → 0.2025.9.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyTEMlib might be problematic. Click here for more details.
- build/lib/pyTEMlib/__init__.py +33 -0
- build/lib/pyTEMlib/animation.py +640 -0
- build/lib/pyTEMlib/atom_tools.py +238 -0
- build/lib/pyTEMlib/config_dir.py +31 -0
- build/lib/pyTEMlib/crystal_tools.py +1219 -0
- build/lib/pyTEMlib/diffraction_plot.py +756 -0
- build/lib/pyTEMlib/dynamic_scattering.py +293 -0
- build/lib/pyTEMlib/eds_tools.py +826 -0
- build/lib/pyTEMlib/eds_xsections.py +432 -0
- build/lib/pyTEMlib/eels_tools/__init__.py +44 -0
- build/lib/pyTEMlib/eels_tools/core_loss_tools.py +751 -0
- build/lib/pyTEMlib/eels_tools/eels_database.py +134 -0
- build/lib/pyTEMlib/eels_tools/low_loss_tools.py +655 -0
- build/lib/pyTEMlib/eels_tools/peak_fit_tools.py +175 -0
- build/lib/pyTEMlib/eels_tools/zero_loss_tools.py +264 -0
- build/lib/pyTEMlib/file_reader.py +274 -0
- build/lib/pyTEMlib/file_tools.py +811 -0
- build/lib/pyTEMlib/get_bote_salvat.py +69 -0
- build/lib/pyTEMlib/graph_tools.py +1153 -0
- build/lib/pyTEMlib/graph_viz.py +599 -0
- build/lib/pyTEMlib/image/__init__.py +37 -0
- build/lib/pyTEMlib/image/image_atoms.py +270 -0
- build/lib/pyTEMlib/image/image_clean.py +197 -0
- build/lib/pyTEMlib/image/image_distortion.py +299 -0
- build/lib/pyTEMlib/image/image_fft.py +277 -0
- build/lib/pyTEMlib/image/image_graph.py +926 -0
- build/lib/pyTEMlib/image/image_registration.py +316 -0
- build/lib/pyTEMlib/image/image_utilities.py +309 -0
- build/lib/pyTEMlib/image/image_window.py +421 -0
- build/lib/pyTEMlib/image_tools.py +699 -0
- build/lib/pyTEMlib/interactive_image.py +1 -0
- build/lib/pyTEMlib/kinematic_scattering.py +1196 -0
- build/lib/pyTEMlib/microscope.py +61 -0
- build/lib/pyTEMlib/probe_tools.py +906 -0
- build/lib/pyTEMlib/sidpy_tools.py +153 -0
- build/lib/pyTEMlib/simulation_tools.py +104 -0
- build/lib/pyTEMlib/test.py +437 -0
- build/lib/pyTEMlib/utilities.py +314 -0
- build/lib/pyTEMlib/version.py +5 -0
- build/lib/pyTEMlib/xrpa_x_sections.py +20976 -0
- pyTEMlib/__init__.py +25 -3
- pyTEMlib/animation.py +31 -22
- pyTEMlib/atom_tools.py +29 -34
- pyTEMlib/config_dir.py +2 -28
- pyTEMlib/crystal_tools.py +129 -165
- pyTEMlib/eds_tools.py +559 -342
- pyTEMlib/eds_xsections.py +432 -0
- pyTEMlib/eels_tools/__init__.py +44 -0
- pyTEMlib/eels_tools/core_loss_tools.py +751 -0
- pyTEMlib/eels_tools/eels_database.py +134 -0
- pyTEMlib/eels_tools/low_loss_tools.py +655 -0
- pyTEMlib/eels_tools/peak_fit_tools.py +175 -0
- pyTEMlib/eels_tools/zero_loss_tools.py +264 -0
- pyTEMlib/file_reader.py +274 -0
- pyTEMlib/file_tools.py +260 -1130
- pyTEMlib/get_bote_salvat.py +69 -0
- pyTEMlib/graph_tools.py +101 -174
- pyTEMlib/graph_viz.py +150 -0
- pyTEMlib/image/__init__.py +37 -0
- pyTEMlib/image/image_atoms.py +270 -0
- pyTEMlib/image/image_clean.py +197 -0
- pyTEMlib/image/image_distortion.py +299 -0
- pyTEMlib/image/image_fft.py +277 -0
- pyTEMlib/image/image_graph.py +926 -0
- pyTEMlib/image/image_registration.py +316 -0
- pyTEMlib/image/image_utilities.py +309 -0
- pyTEMlib/image/image_window.py +421 -0
- pyTEMlib/image_tools.py +154 -928
- pyTEMlib/kinematic_scattering.py +1 -1
- pyTEMlib/probe_tools.py +1 -1
- pyTEMlib/test.py +437 -0
- pyTEMlib/utilities.py +314 -0
- pyTEMlib/version.py +2 -3
- pyTEMlib/xrpa_x_sections.py +14 -10
- {pytemlib-0.2025.4.2.dist-info → pytemlib-0.2025.9.1.dist-info}/METADATA +13 -16
- pytemlib-0.2025.9.1.dist-info/RECORD +86 -0
- {pytemlib-0.2025.4.2.dist-info → pytemlib-0.2025.9.1.dist-info}/WHEEL +1 -1
- pytemlib-0.2025.9.1.dist-info/top_level.txt +6 -0
- pyTEMlib/core_loss_widget.py +0 -721
- pyTEMlib/eels_dialog.py +0 -754
- pyTEMlib/eels_dialog_utilities.py +0 -1199
- pyTEMlib/eels_tools.py +0 -2359
- pyTEMlib/file_tools_qt.py +0 -193
- pyTEMlib/image_dialog.py +0 -158
- pyTEMlib/image_dlg.py +0 -146
- pyTEMlib/info_widget.py +0 -1086
- pyTEMlib/info_widget3.py +0 -1120
- pyTEMlib/low_loss_widget.py +0 -479
- pyTEMlib/peak_dialog.py +0 -1129
- pyTEMlib/peak_dlg.py +0 -286
- pytemlib-0.2025.4.2.dist-info/RECORD +0 -38
- pytemlib-0.2025.4.2.dist-info/top_level.txt +0 -1
- {pytemlib-0.2025.4.2.dist-info → pytemlib-0.2025.9.1.dist-info}/entry_points.txt +0 -0
- {pytemlib-0.2025.4.2.dist-info → pytemlib-0.2025.9.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
"""
|
|
2
|
+
# ###############################################################
|
|
3
|
+
# Utility Functions for spectroscopy data in pyTEMlib
|
|
4
|
+
# ################################################################
|
|
5
|
+
"""
|
|
6
|
+
import typing
|
|
7
|
+
import numpy as np
|
|
8
|
+
from numba import jit
|
|
9
|
+
import scipy
|
|
10
|
+
import sidpy
|
|
11
|
+
|
|
12
|
+
from .xrpa_x_sections import x_sections
|
|
13
|
+
|
|
14
|
+
ELECTRON_REST_ENERGY = 5.10998918e5 # electron rest energy in eV
|
|
15
|
+
|
|
16
|
+
major_edges = ['K1', 'L3', 'M5', 'N5']
|
|
17
|
+
|
|
18
|
+
all_edges = ['K1', 'L1', 'L2', 'L3', 'M1', 'M2', 'M3', 'M4', 'M5',
|
|
19
|
+
'N1', 'N2', 'N3', 'N4', 'N5', 'N6', 'N7', 'O1', 'O2',
|
|
20
|
+
'O3', 'O4', 'O5', 'O6', 'O7', 'P1', 'P2', 'P3']
|
|
21
|
+
|
|
22
|
+
shell_occupancy = {'K1': 2, 'L1': 2, 'L2': 2, 'L3': 4, 'M1': 2, 'M2': 2, 'M3': 4, 'M4': 4, 'M5': 6,
|
|
23
|
+
'N1': 2, 'N2': 2, 'N3': 4, 'N4': 4, 'N5': 6, 'N6': 6, 'N7': 8, 'O1': 2, 'O2': 2,
|
|
24
|
+
'O3': 4, 'O4': 4, 'O5': 6, 'O6': 6, 'O7': 8, 'O8': 8, 'O9': 10}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
first_close_edges = ['K1', 'L3', 'M5', 'M3', 'N5', 'N3']
|
|
28
|
+
|
|
29
|
+
elements = [' ', 'H', 'He', 'Li', 'Be', 'B', 'C', 'N', 'O', 'F', 'Ne', 'Na',
|
|
30
|
+
'Mg', 'Al', 'Si', 'P', 'S', 'Cl', 'Ar', 'K', 'Ca', 'Sc', 'Ti', 'V',
|
|
31
|
+
'Cr', 'Mn', 'Fe', 'Co', 'Ni', 'Cu', 'Zn', 'Ga', 'Ge', 'As', 'Se', 'Br',
|
|
32
|
+
'Kr', 'Rb', 'Sr', 'Y', 'Zr', 'Nb', 'Mo', 'Tc', 'Ru', 'Rh', 'Pd', 'Ag',
|
|
33
|
+
'Cd', 'In', 'Sn', 'Sb', 'Te', 'I', 'Xe', 'Cs', 'Ba', 'La', 'Ce', 'Pr',
|
|
34
|
+
'Nd', 'Pm', 'Sm', 'Eu', 'Gd', 'Tb', 'Dy', 'Ho', 'Er', 'Tm', 'Yb', 'Lu',
|
|
35
|
+
'Hf', 'Ta', 'W', 'Re', 'Os', 'Ir', 'Pt', 'Au', 'Hg', 'Tl', 'Pb', 'Bi']
|
|
36
|
+
|
|
37
|
+
def get_wave_length(e0: float) -> float:
|
|
38
|
+
"""get deBroglie wavelength of electron accelerated by energy (in eV) e0"""
|
|
39
|
+
ev = scipy.constants.e * e0
|
|
40
|
+
m_e = scipy.constants.m_e
|
|
41
|
+
c = scipy.constants.c
|
|
42
|
+
h = scipy.constants.h
|
|
43
|
+
return h / np.sqrt(2 * m_e * ev * (1 + ev / (2 * m_e * c**2)))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def effective_collection_angle(energy_scale: np.ndarray,
|
|
47
|
+
alpha: float,
|
|
48
|
+
beta: float,
|
|
49
|
+
beam_ev: float) -> float:
|
|
50
|
+
"""Calculates the effective collection angle in mrad:
|
|
51
|
+
|
|
52
|
+
Translate from original Fortran program
|
|
53
|
+
Calculates the effective collection angle in mrad:
|
|
54
|
+
Parameter
|
|
55
|
+
---------
|
|
56
|
+
energy_scale: numpy array
|
|
57
|
+
first and last energy loss of spectrum in eV
|
|
58
|
+
alpha: float
|
|
59
|
+
convergence angle in mrad
|
|
60
|
+
beta: float
|
|
61
|
+
collection angle in mrad
|
|
62
|
+
beamKV: float
|
|
63
|
+
acceleration voltage in V
|
|
64
|
+
|
|
65
|
+
Returns
|
|
66
|
+
-------
|
|
67
|
+
eff_beta: float
|
|
68
|
+
effective collection angle in mrad
|
|
69
|
+
|
|
70
|
+
# function y = effbeta(ene, alpha, beta, beam_kv) Note Pierre uses keV
|
|
71
|
+
#
|
|
72
|
+
# This program computes etha(alpha,beta), that is the collection
|
|
73
|
+
# efficiency associated to the following geometry :
|
|
74
|
+
#
|
|
75
|
+
# alpha = half angle of illumination (0 -> pi/2)
|
|
76
|
+
# beta = half angle of collection (0 -> pi/2)
|
|
77
|
+
# (pi/2 = 1570.795 mrad)
|
|
78
|
+
#
|
|
79
|
+
# A constant angular distribution of incident electrons is assumed
|
|
80
|
+
# for any incident angle (-alpha,alpha). These electrons imping the
|
|
81
|
+
# target and a single energy-loss event occurs, with a characteristic
|
|
82
|
+
# angle theta-e (relativistic). The angular distribution of the
|
|
83
|
+
# electrons after the target is analytically derived.
|
|
84
|
+
# This program integrates this distribution from theta=0 up to
|
|
85
|
+
# theta=beta with an adjustable angular step.
|
|
86
|
+
# This program also computes beta* which is the theoretical
|
|
87
|
+
# collection angle which would give the same value of etha(alpha,beta)
|
|
88
|
+
# with a parallel incident beam.
|
|
89
|
+
#
|
|
90
|
+
# subroutines and function subprograms required
|
|
91
|
+
# ---------------------------------------------
|
|
92
|
+
# none
|
|
93
|
+
#
|
|
94
|
+
# comments
|
|
95
|
+
# --------
|
|
96
|
+
#
|
|
97
|
+
# The following parameters are asked as input :
|
|
98
|
+
# accelerating voltage (kV), energy loss range (eV) for the study,
|
|
99
|
+
# energy loss step (eV) in this range, alpha (mrad), beta (mrad).
|
|
100
|
+
# The program returns for each energy loss step :
|
|
101
|
+
# alpha (mrad), beta (mrad), theta-e (relativistic) (mrad),
|
|
102
|
+
# energy loss (eV), etha (#), beta * (mrad)
|
|
103
|
+
#
|
|
104
|
+
# author :
|
|
105
|
+
# --------
|
|
106
|
+
# Pierre TREBBIA
|
|
107
|
+
# US 41 : "Microscopie Electronique Analytique Quantitative"
|
|
108
|
+
# Laboratoire de Physique des Solides, Bat. 510
|
|
109
|
+
# Universite Paris-Sud, F91405 ORSAY Cedex
|
|
110
|
+
# Phone : (33-1) 69 41 53 68
|
|
111
|
+
#
|
|
112
|
+
"""
|
|
113
|
+
if beam_ev == 0:
|
|
114
|
+
beam_ev = 100.0 * 1e3
|
|
115
|
+
|
|
116
|
+
if alpha == 0:
|
|
117
|
+
return beta
|
|
118
|
+
|
|
119
|
+
if beta == 0:
|
|
120
|
+
return alpha
|
|
121
|
+
|
|
122
|
+
alpha = alpha * 0.001 # rad
|
|
123
|
+
beta = beta * 0.001 # rad
|
|
124
|
+
z7 = 500.0 # number of integration steps to be modified at will
|
|
125
|
+
|
|
126
|
+
# main loop on energy loss
|
|
127
|
+
for zx in range(int(energy_scale[0]), int(energy_scale[-1]), 100):
|
|
128
|
+
# ! zx = current energy loss
|
|
129
|
+
eta = 0.0
|
|
130
|
+
# x0 = relativistic theta-e
|
|
131
|
+
x0 = float(zx) * (beam_ev + 511060.) / (beam_ev * (beam_ev + 1022120.))
|
|
132
|
+
dtheta = (beta - 0.1 * np.sqrt((x0**2 + alpha**2))) / 500 # integration steps
|
|
133
|
+
#
|
|
134
|
+
# calculation of the analytical expression
|
|
135
|
+
#
|
|
136
|
+
for zi in range(1, int(z7)):
|
|
137
|
+
theta = 0.1 * np.sqrt((x0**2 + alpha**2)) + dtheta * float(zi)
|
|
138
|
+
x5 = theta**2
|
|
139
|
+
x6 = 4. * x5 * x0 * x0
|
|
140
|
+
x7 = (x0**2 + alpha**2) - x5
|
|
141
|
+
eta += 2. * theta * dtheta * np.log((np.sqrt(x7**2 + x6) + x7) / (2. * x0**2))
|
|
142
|
+
# addition of the central contribution
|
|
143
|
+
eta = eta + (x0**2 + alpha**2) / 100. * np.log(1. + alpha**2/x0**2)
|
|
144
|
+
# normalisation
|
|
145
|
+
eta = eta / alpha * alpha * np.log(1. + np.pi**2 / (4. * x0**2))
|
|
146
|
+
#
|
|
147
|
+
# correction by geometrical factor (beta/alpha)**2
|
|
148
|
+
#
|
|
149
|
+
if beta < alpha:
|
|
150
|
+
x5 = alpha / beta
|
|
151
|
+
eta = eta * x5**2
|
|
152
|
+
|
|
153
|
+
# etha2 = eta * 100.
|
|
154
|
+
#
|
|
155
|
+
# calculation of beta *
|
|
156
|
+
#
|
|
157
|
+
x6 = np.power((1. + (1. + np.pi**2 / (4. * x0**2))), eta)
|
|
158
|
+
x7 = x0 * np.sqrt(x6 - 1.)
|
|
159
|
+
beta = x7 * 1000. # in mrad
|
|
160
|
+
|
|
161
|
+
return beta
|
|
162
|
+
|
|
163
|
+
def set_default_metadata(current_dataset: sidpy.Dataset) -> None:
|
|
164
|
+
"""sets default metadata for the dataset"""
|
|
165
|
+
|
|
166
|
+
if 'experiment' not in current_dataset.metadata:
|
|
167
|
+
current_dataset.metadata['experiment'] = {}
|
|
168
|
+
if 'convergence_angle' not in current_dataset.metadata['experiment']:
|
|
169
|
+
current_dataset.metadata['experiment']['convergence_angle'] = 30
|
|
170
|
+
if 'collection_angle' not in current_dataset.metadata['experiment']:
|
|
171
|
+
current_dataset.metadata['experiment']['collection_angle'] = 50
|
|
172
|
+
if 'acceleration_voltage' not in current_dataset.metadata['experiment']:
|
|
173
|
+
current_dataset.metadata['experiment']['acceleration_voltage'] = 200000
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def lorentz(x, center, amplitude, width):
|
|
177
|
+
""" Lorentzian Function """
|
|
178
|
+
lorentz_peak = 0.5 * width / np.pi / ((x - center)**2 + (width / 2)**2)
|
|
179
|
+
return amplitude * lorentz_peak / lorentz_peak.max()
|
|
180
|
+
|
|
181
|
+
@jit
|
|
182
|
+
def gauss(x, p): # p[0]==mean, p[1]= amplitude p[2]==fwhm,
|
|
183
|
+
"""Gaussian Function
|
|
184
|
+
|
|
185
|
+
p[0]==mean, p[1]= amplitude p[2]==fwhm
|
|
186
|
+
area = np.sqrt(2* np.pi)* p[1] * np.abs(p[2] / 2.3548)
|
|
187
|
+
FWHM = 2 * np.sqrt(2 np.log(2)) * sigma = 2.3548 * sigma
|
|
188
|
+
sigma = FWHM/3548
|
|
189
|
+
"""
|
|
190
|
+
if p[2] == 0:
|
|
191
|
+
return x * 0.
|
|
192
|
+
return p[1] * np.exp(-(x - p[0])**2 / (2.0 * (p[2] / 2.3548)**2))
|
|
193
|
+
|
|
194
|
+
def get_atomic_number(z):
|
|
195
|
+
"""Returns the atomic number independent of input as a string or number"""
|
|
196
|
+
return get_z(z)
|
|
197
|
+
|
|
198
|
+
def get_z(z: typing.Union[int, str]) -> int:
|
|
199
|
+
"""Returns the atomic number independent of input as a string or number
|
|
200
|
+
|
|
201
|
+
Parameter
|
|
202
|
+
---------
|
|
203
|
+
z: int, str
|
|
204
|
+
atomic number of chemical symbol (0 if not valid)
|
|
205
|
+
Return:
|
|
206
|
+
------
|
|
207
|
+
z_out: int
|
|
208
|
+
atomic number
|
|
209
|
+
"""
|
|
210
|
+
z_out = 0
|
|
211
|
+
if str(z).isdigit():
|
|
212
|
+
z_out = int(z)
|
|
213
|
+
elif isinstance(z, str):
|
|
214
|
+
z_out = elements.index(z)
|
|
215
|
+
else:
|
|
216
|
+
raise TypeError('A valid element string or number is required')
|
|
217
|
+
return z_out
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def get_x_sections(z: int=0) -> dict:
|
|
221
|
+
"""Reads X-ray fluorescent cross-sections from a dictionary.
|
|
222
|
+
|
|
223
|
+
Parameters
|
|
224
|
+
----------
|
|
225
|
+
z: int
|
|
226
|
+
atomic number if zero all cross-sections will be returned
|
|
227
|
+
|
|
228
|
+
Returns
|
|
229
|
+
-------
|
|
230
|
+
dictionary
|
|
231
|
+
cross-section of an element or of all elements if z = 0
|
|
232
|
+
"""
|
|
233
|
+
if z < 1:
|
|
234
|
+
return x_sections
|
|
235
|
+
z = str(z)
|
|
236
|
+
if z in x_sections:
|
|
237
|
+
return x_sections[z]
|
|
238
|
+
return {}
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def get_spectrum(dataset, x=0, y=0, bin_x=1, bin_y=1):
|
|
242
|
+
"""
|
|
243
|
+
Extracts a spectrum from a sidpy.Dataset object
|
|
244
|
+
Parameter
|
|
245
|
+
---------
|
|
246
|
+
dataset: sidpy.Dataset object
|
|
247
|
+
contains spectrum or spectrum image
|
|
248
|
+
x: int default = 0
|
|
249
|
+
x position of spectrum image
|
|
250
|
+
y: int default = 0
|
|
251
|
+
y position of spectrum
|
|
252
|
+
bin_x: int default = 1
|
|
253
|
+
binning of spectrum image in x-direction
|
|
254
|
+
bin_y: int default = 1
|
|
255
|
+
binning of spectrum image in y-direction
|
|
256
|
+
|
|
257
|
+
Returns:
|
|
258
|
+
--------
|
|
259
|
+
spectrum: sidpy.Dataset object
|
|
260
|
+
|
|
261
|
+
"""
|
|
262
|
+
if dataset.data_type.name == 'SPECTRUM':
|
|
263
|
+
spectrum = dataset.copy()
|
|
264
|
+
else:
|
|
265
|
+
image_dims = dataset.get_image_dims()
|
|
266
|
+
x = min(x, dataset.shape[image_dims[0]] - bin_x)
|
|
267
|
+
y = min(y, dataset.shape[image_dims[1]] - bin_y)
|
|
268
|
+
selection = []
|
|
269
|
+
dimensions = dataset.get_dimension_types()
|
|
270
|
+
for dim, dimension_type in enumerate(dimensions):
|
|
271
|
+
# print(dim, axis.dimension_type)
|
|
272
|
+
if dimension_type == 'SPATIAL':
|
|
273
|
+
if dim == image_dims[0]:
|
|
274
|
+
selection.append(slice(x, x + bin_x))
|
|
275
|
+
else:
|
|
276
|
+
selection.append(slice(y, y + bin_y))
|
|
277
|
+
elif dimension_type == 'SPECTRAL':
|
|
278
|
+
selection.append(slice(None))
|
|
279
|
+
elif dimension_type == 'CHANNEL':
|
|
280
|
+
selection.append(slice(None))
|
|
281
|
+
else:
|
|
282
|
+
selection.append(slice(0, 1))
|
|
283
|
+
spectrum = dataset[tuple(selection)].mean(axis=tuple(image_dims))
|
|
284
|
+
spectrum.squeeze().compute()
|
|
285
|
+
spectrum.data_type = 'Spectrum'
|
|
286
|
+
return spectrum
|
|
287
|
+
|
|
288
|
+
def second_derivative(dataset: sidpy.Dataset) -> None:
|
|
289
|
+
"""Calculates second derivative of a sidpy.dataset"""
|
|
290
|
+
energy_scale = dataset.get_spectral_dims(return_axis=True)[0]
|
|
291
|
+
if dataset.data_type.name == 'SPECTRAL_IMAGE':
|
|
292
|
+
spectrum = dataset.view.get_spectrum()
|
|
293
|
+
else:
|
|
294
|
+
spectrum = np.array(dataset)
|
|
295
|
+
spec = scipy.ndimage.gaussian_filter(spectrum, 3)
|
|
296
|
+
dispersion = energy_scale.slope
|
|
297
|
+
second_dif = np.roll(spec, -3) - 2 * spec + np.roll(spec, +3)
|
|
298
|
+
second_dif[:3] = 0
|
|
299
|
+
second_dif[-3:] = 0
|
|
300
|
+
|
|
301
|
+
# find if there is a strong edge at high energy_scale
|
|
302
|
+
noise_level = 2. * np.std(second_dif[3:50])
|
|
303
|
+
[indices, _] = scipy.signal.find_peaks(second_dif, noise_level)
|
|
304
|
+
width = max(50 / dispersion, 50)
|
|
305
|
+
start_end_noise = int(len(energy_scale) - width)
|
|
306
|
+
for index in indices[::-1]:
|
|
307
|
+
if index > start_end_noise:
|
|
308
|
+
start_end_noise = index - 70
|
|
309
|
+
|
|
310
|
+
# noise_level_start = sensitivity * np.std(second_dif[3:50])
|
|
311
|
+
# noise_level_end = sensitivity * np.std(second_dif[start_end_noise: start_end_noise + 50])
|
|
312
|
+
# slope = (noise_level_end - noise_level_start) / (len(energy_scale) - 400)
|
|
313
|
+
# noise_level = noise_level_start #+ np.arange(len(energy_scale)) * slope
|
|
314
|
+
return second_dif , noise_level
|