xarpes 0.2.3__tar.gz → 0.2.4__tar.gz
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.
- {xarpes-0.2.3 → xarpes-0.2.4}/PKG-INFO +2 -1
- {xarpes-0.2.3 → xarpes-0.2.4}/pyproject.toml +1 -0
- {xarpes-0.2.3 → xarpes-0.2.4}/xarpes/__init__.py +1 -1
- {xarpes-0.2.3 → xarpes-0.2.4}/xarpes/band_map.py +30 -34
- {xarpes-0.2.3 → xarpes-0.2.4}/xarpes/distributions.py +7 -15
- {xarpes-0.2.3 → xarpes-0.2.4}/xarpes/functions.py +18 -16
- {xarpes-0.2.3 → xarpes-0.2.4}/xarpes/plotting.py +0 -1
- {xarpes-0.2.3 → xarpes-0.2.4}/LICENSE +0 -0
- {xarpes-0.2.3 → xarpes-0.2.4}/README.md +0 -0
- {xarpes-0.2.3 → xarpes-0.2.4}/xarpes/.ipynb_checkpoints/__init__-checkpoint.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: xarpes
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Extraction from angle resolved photoemission spectra
|
|
5
5
|
Author: xARPES Developers
|
|
6
6
|
Requires-Python: >=3.7.0
|
|
@@ -15,6 +15,7 @@ Requires-Dist: numpy
|
|
|
15
15
|
Requires-Dist: scipy
|
|
16
16
|
Requires-Dist: lmfit
|
|
17
17
|
Requires-Dist: xarray
|
|
18
|
+
Requires-Dist: pyqt5
|
|
18
19
|
Project-URL: Documentation, https://xarpes.github.io
|
|
19
20
|
|
|
20
21
|

|
|
@@ -17,7 +17,6 @@ from .plotting import get_ax_fig_plt, add_fig_kwargs
|
|
|
17
17
|
from .functions import fit_leastsq
|
|
18
18
|
from .distributions import fermi_dirac
|
|
19
19
|
|
|
20
|
-
|
|
21
20
|
class MDCs():
|
|
22
21
|
r"""
|
|
23
22
|
"""
|
|
@@ -33,14 +32,12 @@ class MDCs():
|
|
|
33
32
|
# """
|
|
34
33
|
# return 0
|
|
35
34
|
|
|
36
|
-
|
|
37
35
|
# @add_fig_kwargs
|
|
38
36
|
# def fit_fermi_edge(self, hnuminphi_guess, background_guess=0.0,
|
|
39
|
-
# integrated_weight_guess=1.0, angle_min=-np.
|
|
40
|
-
# angle_max=np.
|
|
41
|
-
# ekin_max=np.
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
# integrated_weight_guess=1.0, angle_min=-np.inf,
|
|
38
|
+
# angle_max=np.inf, ekin_min=-np.inf,
|
|
39
|
+
# ekin_max=np.inf, ax=None, **kwargs):
|
|
40
|
+
|
|
44
41
|
@add_fig_kwargs
|
|
45
42
|
def plot(self, ax=None, **kwargs):
|
|
46
43
|
r"""
|
|
@@ -48,12 +45,11 @@ class MDCs():
|
|
|
48
45
|
ax, fig, plt = get_ax_fig_plt(ax=ax)
|
|
49
46
|
|
|
50
47
|
ax.scatter(self.angles, self.intensities)
|
|
51
|
-
|
|
52
|
-
ax.set_xlabel(
|
|
48
|
+
|
|
49
|
+
ax.set_xlabel('Angle ($\degree$)')
|
|
53
50
|
ax.set_ylabel('Counts (-)')
|
|
54
|
-
|
|
51
|
+
|
|
55
52
|
return fig
|
|
56
|
-
|
|
57
53
|
|
|
58
54
|
class band_map():
|
|
59
55
|
r"""Class for the band map from the ARPES experiment.
|
|
@@ -158,7 +154,6 @@ class band_map():
|
|
|
158
154
|
Minimum angle of integration interval [degrees]
|
|
159
155
|
angle_max : float
|
|
160
156
|
Maximum angle of integration interval [degrees]
|
|
161
|
-
|
|
162
157
|
|
|
163
158
|
Returns
|
|
164
159
|
-------
|
|
@@ -166,25 +161,25 @@ class band_map():
|
|
|
166
161
|
Array of size n containing the angular values
|
|
167
162
|
energy_range : ndarray
|
|
168
163
|
Array of size m containing the energy values
|
|
169
|
-
mdcs :
|
|
164
|
+
mdcs :
|
|
170
165
|
Array of size nxm containing the MDC intensities
|
|
171
166
|
"""
|
|
172
|
-
|
|
173
|
-
energy_index = np.abs(self.ekin-energy_value).argmin()
|
|
174
|
-
angle_min_index = np.abs(self.angles-angle_min).argmin()
|
|
175
|
-
angle_max_index = np.abs(self.angles-angle_max).argmin()
|
|
176
|
-
|
|
177
|
-
angle_range = self.angles[angle_min_index:angle_max_index+1]
|
|
167
|
+
|
|
168
|
+
energy_index = np.abs(self.ekin - energy_value).argmin()
|
|
169
|
+
angle_min_index = np.abs(self.angles - angle_min).argmin()
|
|
170
|
+
angle_max_index = np.abs(self.angles - angle_max).argmin()
|
|
171
|
+
|
|
172
|
+
angle_range = self.angles[angle_min_index:angle_max_index + 1]
|
|
178
173
|
energy_range = self.ekin[energy_index]
|
|
179
|
-
mdcs = self.intensities[energy_index,
|
|
174
|
+
mdcs = self.intensities[energy_index,
|
|
175
|
+
angle_min_index:angle_max_index + 1]
|
|
180
176
|
|
|
181
177
|
return mdcs, angle_range, energy_range, self.angular_resolution
|
|
182
178
|
|
|
183
|
-
|
|
184
179
|
@add_fig_kwargs
|
|
185
180
|
def plot_band_map(self, ax=None, **kwargs):
|
|
186
181
|
r"""Plots the band map.
|
|
187
|
-
|
|
182
|
+
|
|
188
183
|
Parameters
|
|
189
184
|
----------
|
|
190
185
|
|
|
@@ -192,29 +187,30 @@ class band_map():
|
|
|
192
187
|
----------------
|
|
193
188
|
**kwargs : dict, optional
|
|
194
189
|
Additional arguments passed on to add_fig_kwargs. See the keyword
|
|
195
|
-
table below.
|
|
190
|
+
table below.
|
|
196
191
|
|
|
197
192
|
Returns
|
|
198
193
|
-------
|
|
199
194
|
fig : Matplotlib-Figure
|
|
200
195
|
Figure containing the Fermi edge fit
|
|
201
|
-
"""
|
|
196
|
+
"""
|
|
202
197
|
ax, fig, plt = get_ax_fig_plt(ax=ax)
|
|
203
198
|
|
|
204
199
|
Angl, Ekin = np.meshgrid(self.angles, self.ekin)
|
|
205
|
-
mesh = ax.pcolormesh(Angl, Ekin, self.intensities, shading=
|
|
200
|
+
mesh = ax.pcolormesh(Angl, Ekin, self.intensities, shading='auto',
|
|
201
|
+
cmap=plt.get_cmap('bone').reversed())
|
|
206
202
|
cbar = plt.colorbar(mesh, ax=ax)
|
|
207
|
-
|
|
208
|
-
ax.set_xlabel(
|
|
209
|
-
ax.set_ylabel(
|
|
210
|
-
|
|
203
|
+
|
|
204
|
+
ax.set_xlabel('Angle ($\degree$)')
|
|
205
|
+
ax.set_ylabel('$E_{\mathrm{kin}}$ (eV)')
|
|
206
|
+
|
|
211
207
|
return fig
|
|
212
|
-
|
|
208
|
+
|
|
213
209
|
@add_fig_kwargs
|
|
214
210
|
def fit_fermi_edge(self, hnuminphi_guess, background_guess=0.0,
|
|
215
|
-
integrated_weight_guess=1.0, angle_min=-np.
|
|
216
|
-
angle_max=np.
|
|
217
|
-
ekin_max=np.
|
|
211
|
+
integrated_weight_guess=1.0, angle_min=-np.inf,
|
|
212
|
+
angle_max=np.inf, ekin_min=-np.inf,
|
|
213
|
+
ekin_max=np.inf, ax=None, **kwargs):
|
|
218
214
|
r"""Fits the Fermi edge of the band map and plots the result.
|
|
219
215
|
Also sets hnuminphi, the kinetic energy minus the work function in eV.
|
|
220
216
|
The fitting includes an energy convolution with an abscissa range
|
|
@@ -303,4 +299,4 @@ class band_map():
|
|
|
303
299
|
|
|
304
300
|
ax.legend()
|
|
305
301
|
|
|
306
|
-
return fig
|
|
302
|
+
return fig
|
|
@@ -29,7 +29,6 @@ class distribution:
|
|
|
29
29
|
"""
|
|
30
30
|
return self._name
|
|
31
31
|
|
|
32
|
-
|
|
33
32
|
class unique_distribution(distribution):
|
|
34
33
|
r"""Parent class for unique distributions, to be used one at a time, e.g.,
|
|
35
34
|
during the background of an MDC fit or the Fermi-Dirac distribution.
|
|
@@ -56,7 +55,6 @@ class unique_distribution(distribution):
|
|
|
56
55
|
"""
|
|
57
56
|
return self._label
|
|
58
57
|
|
|
59
|
-
|
|
60
58
|
class constant(unique_distribution):
|
|
61
59
|
r"""Child class for constant distributions, used e.g., during MDC fitting.
|
|
62
60
|
The constant class is unique, only one instance should be used per task.
|
|
@@ -92,7 +90,6 @@ class constant(unique_distribution):
|
|
|
92
90
|
"""
|
|
93
91
|
self._offset = x
|
|
94
92
|
|
|
95
|
-
|
|
96
93
|
class linear(unique_distribution):
|
|
97
94
|
r"""Child cass for for linear distributions, used e.g., during MDC fitting.
|
|
98
95
|
The constant class is unique, only one instance should be used per task.
|
|
@@ -153,7 +150,6 @@ class linear(unique_distribution):
|
|
|
153
150
|
"""
|
|
154
151
|
self._slope = x
|
|
155
152
|
|
|
156
|
-
|
|
157
153
|
class fermi_dirac(unique_distribution):
|
|
158
154
|
r"""Child class for Fermi-Dirac (FD) distributions, used e.g., during Fermi
|
|
159
155
|
edge fitting. The FD class is unique, only one instance should be used
|
|
@@ -302,7 +298,7 @@ class fermi_dirac(unique_distribution):
|
|
|
302
298
|
1D array of the energy-convolved FD distribution [counts]
|
|
303
299
|
"""
|
|
304
300
|
from scipy.ndimage import gaussian_filter
|
|
305
|
-
|
|
301
|
+
|
|
306
302
|
sigma_extend = 5 # Extend data range by "5 sigma"
|
|
307
303
|
# Conversion from FWHM to standard deviation [-]
|
|
308
304
|
fwhm_to_std = np.sqrt(8 * np.log(2))
|
|
@@ -332,7 +328,7 @@ class fermi_dirac(unique_distribution):
|
|
|
332
328
|
-------
|
|
333
329
|
evalf : ndarray
|
|
334
330
|
1D array of the evaluated FD distribution [counts]
|
|
335
|
-
"""
|
|
331
|
+
"""
|
|
336
332
|
k_B = 8.617e-5 # Boltzmann constant [eV/K]
|
|
337
333
|
k_BT = self.temperature * k_B
|
|
338
334
|
evalf = (self.integrated_weight
|
|
@@ -359,7 +355,7 @@ class fermi_dirac(unique_distribution):
|
|
|
359
355
|
1D array of the energy-convolved FD distribution [counts]
|
|
360
356
|
"""
|
|
361
357
|
from scipy.ndimage import gaussian_filter
|
|
362
|
-
|
|
358
|
+
|
|
363
359
|
sigma_extend = 5 # Extend data range by "5 sigma"
|
|
364
360
|
# Conversion from FWHM to standard deviation [-]
|
|
365
361
|
fwhm_to_std = np.sqrt(8 * np.log(2))
|
|
@@ -373,7 +369,6 @@ class fermi_dirac(unique_distribution):
|
|
|
373
369
|
sigma=estep)[enumb:-enumb]
|
|
374
370
|
return evalf
|
|
375
371
|
|
|
376
|
-
|
|
377
372
|
class non_unique_distribution(distribution):
|
|
378
373
|
r"""Parent class for unique distributions, to be used one at a time, e.g.,
|
|
379
374
|
during the background of an MDC fit or the Fermi-Dirac distribution.
|
|
@@ -400,7 +395,6 @@ class non_unique_distribution(distribution):
|
|
|
400
395
|
"""
|
|
401
396
|
return self._label
|
|
402
397
|
|
|
403
|
-
|
|
404
398
|
class dispersion(distribution):
|
|
405
399
|
r"""Dispersions are assumed to be unique, so they need an index.
|
|
406
400
|
"""
|
|
@@ -453,13 +447,12 @@ class dispersion(distribution):
|
|
|
453
447
|
"""
|
|
454
448
|
self._broadening = x
|
|
455
449
|
|
|
456
|
-
|
|
457
450
|
# class spectral_linear(dispersion):
|
|
458
451
|
# r"""Class for the linear dispersion spectral function"""
|
|
459
452
|
# def __init__(self, amplitude, center, broadening, name, index):
|
|
460
453
|
# super().__init__(amplitude=amplitude, center=center,
|
|
461
454
|
# broadening=broadening, name=name, index=index)
|
|
462
|
-
|
|
455
|
+
|
|
463
456
|
# def result(self, x):
|
|
464
457
|
# r"""
|
|
465
458
|
# """
|
|
@@ -468,10 +461,9 @@ class dispersion(distribution):
|
|
|
468
461
|
# - np.sin(self.center*dtor))**2 + self.broadening**2)
|
|
469
462
|
# return evalf
|
|
470
463
|
|
|
471
|
-
|
|
472
464
|
# class spectral_linear(dispersion):
|
|
473
465
|
# r"""Class for the linear dispersion spectral function"""
|
|
474
|
-
# def __init__(self, amplitude, center, broadening, bottom, side, name,
|
|
466
|
+
# def __init__(self, amplitude, center, broadening, bottom, side, name,
|
|
475
467
|
# index):
|
|
476
468
|
# super()__init__(amplitude=amplitude, center=center,
|
|
477
469
|
# broadening=broadening, name=name, index=index)
|
|
@@ -495,11 +487,11 @@ class dispersion(distribution):
|
|
|
495
487
|
# r"""
|
|
496
488
|
# """
|
|
497
489
|
# return self._side
|
|
498
|
-
|
|
490
|
+
|
|
499
491
|
# def result(self, x):
|
|
500
492
|
# r"""
|
|
501
493
|
# """
|
|
502
494
|
# dtor = np.pi/180
|
|
503
495
|
# evalf = self.amplitude / np.pi * self.broadening / (((np.sin(x*dtor)
|
|
504
496
|
# - np.sin(self.bottom*dtor))**2 - np.sin(self.center*dtor)**2)**2
|
|
505
|
-
# + self.broadening**2)
|
|
497
|
+
# + self.broadening**2)
|
|
@@ -29,7 +29,6 @@ def error_function(p, xdata, ydata, function, extra_args):
|
|
|
29
29
|
residual = function(xdata, *p, extra_args) - ydata
|
|
30
30
|
return residual
|
|
31
31
|
|
|
32
|
-
|
|
33
32
|
def fit_leastsq(p0, xdata, ydata, function, extra_args):
|
|
34
33
|
r"""Wrapper arround scipy.optimize.leastsq.
|
|
35
34
|
|
|
@@ -54,7 +53,7 @@ def fit_leastsq(p0, xdata, ydata, function, extra_args):
|
|
|
54
53
|
Covariance matrix of the optimized parameters
|
|
55
54
|
"""
|
|
56
55
|
from scipy.optimize import leastsq
|
|
57
|
-
|
|
56
|
+
|
|
58
57
|
pfit, pcov, infodict, errmsg, success = leastsq(
|
|
59
58
|
error_function, p0, args=(xdata, ydata, function, extra_args),
|
|
60
59
|
full_output=1)
|
|
@@ -76,12 +75,11 @@ def fit_leastsq(p0, xdata, ydata, function, extra_args):
|
|
|
76
75
|
perr_leastsq = np.array(error)
|
|
77
76
|
|
|
78
77
|
return pfit_leastsq, perr_leastsq
|
|
79
|
-
|
|
80
78
|
|
|
81
79
|
def download_examples():
|
|
82
80
|
"""Downloads the examples folder from the xARPES code only if it does not
|
|
83
81
|
already exist. Prints executed steps and a final cleanup/failure message.
|
|
84
|
-
|
|
82
|
+
|
|
85
83
|
Returns
|
|
86
84
|
-------
|
|
87
85
|
0, 1 : int
|
|
@@ -92,22 +90,23 @@ def download_examples():
|
|
|
92
90
|
import os
|
|
93
91
|
import shutil
|
|
94
92
|
import io
|
|
95
|
-
|
|
93
|
+
|
|
96
94
|
repo_url = 'https://github.com/xARPES/xARPES_examples'
|
|
97
|
-
output_dir = '.'
|
|
98
|
-
|
|
95
|
+
output_dir = '.' # Directory from which the function is called
|
|
96
|
+
|
|
99
97
|
# Check if 'examples' directory already exists
|
|
100
98
|
final_examples_path = os.path.join(output_dir, 'examples')
|
|
101
99
|
if os.path.exists(final_examples_path):
|
|
102
|
-
print("Warning: 'examples' folder already exists.
|
|
100
|
+
print("Warning: 'examples' folder already exists. \
|
|
101
|
+
No download will be performed.")
|
|
103
102
|
return 1 # Exit the function if 'examples' directory exists
|
|
104
103
|
|
|
105
104
|
# Proceed with download if 'examples' directory does not exist
|
|
106
|
-
repo_parts = repo_url.replace(
|
|
107
|
-
zip_url = f
|
|
105
|
+
repo_parts = repo_url.replace('https://github.com/', '').rstrip('/')
|
|
106
|
+
zip_url = f'https://github.com/{repo_parts}/archive/refs/heads/main.zip'
|
|
108
107
|
|
|
109
108
|
# Make the HTTP request to download the zip file
|
|
110
|
-
print(f
|
|
109
|
+
print(f'Downloading {zip_url}')
|
|
111
110
|
response = requests.get(zip_url)
|
|
112
111
|
if response.status_code == 200:
|
|
113
112
|
zip_file_bytes = io.BytesIO(response.content)
|
|
@@ -116,10 +115,12 @@ def download_examples():
|
|
|
116
115
|
zip_ref.extractall(output_dir)
|
|
117
116
|
|
|
118
117
|
# Path to the extracted main folder
|
|
119
|
-
main_folder_path = os.path.join(output_dir,
|
|
118
|
+
main_folder_path = os.path.join(output_dir,
|
|
119
|
+
repo_parts.split('/')[-1]
|
|
120
|
+
+ '-main')
|
|
120
121
|
examples_path = os.path.join(main_folder_path, 'examples')
|
|
121
122
|
|
|
122
|
-
# Move the 'examples' directory to the target location
|
|
123
|
+
# Move the 'examples' directory to the target location
|
|
123
124
|
if os.path.exists(examples_path):
|
|
124
125
|
shutil.move(examples_path, final_examples_path)
|
|
125
126
|
print(f"'examples' subdirectory moved to {final_examples_path}")
|
|
@@ -128,8 +129,9 @@ def download_examples():
|
|
|
128
129
|
|
|
129
130
|
# Remove the rest of the extracted content
|
|
130
131
|
shutil.rmtree(main_folder_path)
|
|
131
|
-
print(f
|
|
132
|
+
print(f'Cleaned up temporary files in {main_folder_path}')
|
|
132
133
|
return 0
|
|
133
134
|
else:
|
|
134
|
-
print(f
|
|
135
|
-
|
|
135
|
+
print(f'Failed to download the repository. Status code: \
|
|
136
|
+
{response.status_code}')
|
|
137
|
+
return 1
|
|
@@ -26,7 +26,6 @@ def plot_settings(name='default'):
|
|
|
26
26
|
mpl.rcParams['xtick.major.width'] = 0.8
|
|
27
27
|
mpl.rcParams.update({'font.size': 16})
|
|
28
28
|
mpl.use('Qt5Agg') # Backend for showing plots in terminal
|
|
29
|
-
|
|
30
29
|
|
|
31
30
|
def get_ax_fig_plt(ax=None, **kwargs):
|
|
32
31
|
r"""Helper function used in plot functions supporting an optional `Axes`
|
|
File without changes
|
|
File without changes
|
|
File without changes
|