teareduce 0.3.0__tar.gz → 0.3.5__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.
- {teareduce-0.3.0/src/teareduce.egg-info → teareduce-0.3.5}/PKG-INFO +2 -1
- {teareduce-0.3.0 → teareduce-0.3.5}/pyproject.toml +2 -1
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce/__init__.py +1 -0
- teareduce-0.3.5/src/teareduce/numsplines.py +232 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce/version.py +1 -1
- {teareduce-0.3.0 → teareduce-0.3.5/src/teareduce.egg-info}/PKG-INFO +2 -1
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce.egg-info/SOURCES.txt +1 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce.egg-info/requires.txt +1 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/LICENSE.txt +0 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/README.md +0 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/setup.cfg +0 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce/avoid_astropy_warnings.py +0 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce/correct_pincushion_distortion.py +0 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce/cosmicrays.py +0 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce/ctext.py +0 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce/draw_rectangle.py +0 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce/elapsed_time.py +0 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce/imshow.py +0 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce/peaks_spectrum.py +0 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce/polfit.py +0 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce/robust_std.py +0 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce/sdistortion.py +0 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce/sliceregion.py +0 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce/statsummary.py +0 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce/wavecal.py +0 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce/zscale.py +0 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce.egg-info/dependency_links.txt +0 -0
- {teareduce-0.3.0 → teareduce-0.3.5}/src/teareduce.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: teareduce
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.5
|
|
4
4
|
Summary: Utilities for astronomical data reduction
|
|
5
5
|
Author-email: Nicolás Cardiel <cardiel@ucm.es>
|
|
6
6
|
License: GPL-3.0-or-later
|
|
@@ -22,6 +22,7 @@ Description-Content-Type: text/markdown
|
|
|
22
22
|
License-File: LICENSE.txt
|
|
23
23
|
Requires-Dist: astropy
|
|
24
24
|
Requires-Dist: importlib_resources
|
|
25
|
+
Requires-Dist: lmfit
|
|
25
26
|
Requires-Dist: matplotlib
|
|
26
27
|
Requires-Dist: numpy>=1.20
|
|
27
28
|
Requires-Dist: scipy
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# (include packages imported in the different modules; otherwise
|
|
4
4
|
# a ModuleNotFoundError is raised when using $ pip install -e .)
|
|
5
5
|
requires = ["setuptools >= 43.0.0", "wheel", "numpy",
|
|
6
|
-
"astropy", "matplotlib", "scipy", "tqdm"]
|
|
6
|
+
"astropy", "matplotlib", "scipy", "lmfit", "tqdm"]
|
|
7
7
|
build-backend = "setuptools.build_meta"
|
|
8
8
|
|
|
9
9
|
[project]
|
|
@@ -33,6 +33,7 @@ classifiers = [
|
|
|
33
33
|
dependencies = [
|
|
34
34
|
"astropy",
|
|
35
35
|
"importlib_resources", # required with python < 3.9
|
|
36
|
+
"lmfit",
|
|
36
37
|
"matplotlib",
|
|
37
38
|
"numpy >= 1.20",
|
|
38
39
|
"scipy",
|
|
@@ -14,6 +14,7 @@ from .ctext import ctext
|
|
|
14
14
|
from .draw_rectangle import draw_rectangle
|
|
15
15
|
from .elapsed_time import elapsed_time
|
|
16
16
|
from .imshow import imshow
|
|
17
|
+
from .numsplines import AdaptiveLSQUnivariateSpline
|
|
17
18
|
from .peaks_spectrum import find_peaks_spectrum, refine_peaks_spectrum
|
|
18
19
|
from .polfit import polfit_residuals, polfit_residuals_with_sigma_rejection
|
|
19
20
|
from .robust_std import robust_std
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright 2019-2024 Universidad Complutense de Madrid
|
|
3
|
+
#
|
|
4
|
+
# This file is part of teareduce
|
|
5
|
+
#
|
|
6
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
7
|
+
# License-Filename: LICENSE.txt
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
"""Numerical spline fit using different strategies."""
|
|
11
|
+
|
|
12
|
+
from lmfit import Minimizer, Parameters
|
|
13
|
+
import numpy as np
|
|
14
|
+
from scipy.interpolate import LSQUnivariateSpline
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def fun_residuals(params, xnor, ynor, w, bbox, k, ext):
|
|
18
|
+
"""Compute fit residuals"""
|
|
19
|
+
|
|
20
|
+
spl = LSQUnivariateSpline(
|
|
21
|
+
x=xnor,
|
|
22
|
+
y=ynor,
|
|
23
|
+
t=[item.value for item in params.values()],
|
|
24
|
+
w=w,
|
|
25
|
+
bbox=bbox,
|
|
26
|
+
k=k,
|
|
27
|
+
ext=ext,
|
|
28
|
+
check_finite=False
|
|
29
|
+
)
|
|
30
|
+
return spl.get_residual()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class AdaptiveLSQUnivariateSpline(LSQUnivariateSpline):
|
|
34
|
+
"""Extend scipy.interpolate.LSQUnivariateSpline.
|
|
35
|
+
|
|
36
|
+
One-dimensional spline with explicit internal knots.
|
|
37
|
+
|
|
38
|
+
This is actually a wrapper of
|
|
39
|
+
`scipy.interpolate.LSQUnivariateSpline`
|
|
40
|
+
with the addition of using adaptive knot location determined
|
|
41
|
+
numerically (after normalising the x and y arrays before
|
|
42
|
+
the minimisation process).
|
|
43
|
+
|
|
44
|
+
Parameters
|
|
45
|
+
----------
|
|
46
|
+
x : (N,) array_like
|
|
47
|
+
Input dimension of data points -- must be increasing
|
|
48
|
+
y : (N,) array_like
|
|
49
|
+
Input dimension of data points
|
|
50
|
+
t : (M,) array_like or int
|
|
51
|
+
When integer it indicates the number of equidistant
|
|
52
|
+
interior knots. When array_like it provides the location
|
|
53
|
+
of the interior knots of the spline; must be in ascending
|
|
54
|
+
order and::
|
|
55
|
+
|
|
56
|
+
bbox[0] < t[0] < ... < t[-1] < bbox[-1]
|
|
57
|
+
|
|
58
|
+
w : (N,) array_like, optional
|
|
59
|
+
weights for spline fitting. Must be positive.
|
|
60
|
+
If None (default), weights are all equal.
|
|
61
|
+
bbox : (2,) array_like, optional
|
|
62
|
+
2-sequence specifying the boundary of the approximation
|
|
63
|
+
interval. If None (default), ``bbox = [x[0], x[-1]]``.
|
|
64
|
+
k : int, optional
|
|
65
|
+
Degree of the smoothing spline. Must be 1 <= `k` <= 5.
|
|
66
|
+
Default is k=3, a cubic spline.
|
|
67
|
+
ext : int or str, optional
|
|
68
|
+
Controls the extrapolation mode for elements
|
|
69
|
+
not in the interval defined by the knot sequence.
|
|
70
|
+
|
|
71
|
+
* if ext=0 or 'extrapolate', return the extrapolated value.
|
|
72
|
+
* if ext=1 or 'zeros', return 0
|
|
73
|
+
* if ext=2 or 'raise', raise a ValueError
|
|
74
|
+
* if ext=3 of 'const', return the boundary value.
|
|
75
|
+
|
|
76
|
+
The default value is 0.
|
|
77
|
+
|
|
78
|
+
check_finite : bool, optional
|
|
79
|
+
Whether to check that the input arrays contain only finite
|
|
80
|
+
numbers, that the x array is increasing and that the
|
|
81
|
+
x and y arrays are 1-D and with the same length.
|
|
82
|
+
Disabling may give a performance gain, but may
|
|
83
|
+
result in problems (crashes, non-termination or non-sensical
|
|
84
|
+
results) if the inputs do contain infinities or NaNs.
|
|
85
|
+
Default is True.
|
|
86
|
+
adaptive : bool, optional
|
|
87
|
+
Whether to optimise knot location following the procedure
|
|
88
|
+
described in Cardiel (2009); see:
|
|
89
|
+
http://cdsads.u-strasbg.fr/abs/2009MNRAS.396..680C
|
|
90
|
+
Default is True.
|
|
91
|
+
tolerance : float, optional
|
|
92
|
+
Tolerance for Nelder-Mead minimisation process.
|
|
93
|
+
|
|
94
|
+
Attributes
|
|
95
|
+
----------
|
|
96
|
+
_params : instance of Parameters()
|
|
97
|
+
Initial parameters before minimisation.
|
|
98
|
+
_result : Minimizer output
|
|
99
|
+
Result of the minimisation process.
|
|
100
|
+
|
|
101
|
+
See also
|
|
102
|
+
--------
|
|
103
|
+
LSQUnivariateSpline : Superclass
|
|
104
|
+
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
def __init__(self, x, y, t, w=None, bbox=(None, None),
|
|
108
|
+
k=3, ext=0, check_finite=False, adaptive=True,
|
|
109
|
+
tolerance=1E-7):
|
|
110
|
+
"""One-dimensional spline with explicit internal knots."""
|
|
111
|
+
|
|
112
|
+
if check_finite:
|
|
113
|
+
# check here the arrays instead of in the base class
|
|
114
|
+
# (note that in the call to super(...).__init(...) the
|
|
115
|
+
# parameter check_finite is set to False)
|
|
116
|
+
w_finite = np.isfinite(x).all() if w is not None else True
|
|
117
|
+
if not np.isfinite(x).all() or not np.isfinite(y).all() or \
|
|
118
|
+
not w_finite:
|
|
119
|
+
raise ValueError('Input(s) must not contain '
|
|
120
|
+
'NaNs or infs.')
|
|
121
|
+
|
|
122
|
+
if np.asarray(x).ndim != 1:
|
|
123
|
+
raise ValueError('x array must have dimension 1')
|
|
124
|
+
|
|
125
|
+
if np.asarray(y).ndim != 1:
|
|
126
|
+
raise ValueError('y array must have dimension 1')
|
|
127
|
+
|
|
128
|
+
if np.asarray(x).shape != np.asarray(y).shape:
|
|
129
|
+
raise ValueError('x and y arrays must have the same length')
|
|
130
|
+
|
|
131
|
+
if not all(np.diff(x) > 0.0):
|
|
132
|
+
raise ValueError('x array must be strictly increasing')
|
|
133
|
+
|
|
134
|
+
# initial inner knot location (equidistant or fixed)
|
|
135
|
+
try:
|
|
136
|
+
nknots = int(t)
|
|
137
|
+
if nknots > 0:
|
|
138
|
+
xmin = x[0]
|
|
139
|
+
xmax = x[-1]
|
|
140
|
+
deltax = (xmax - xmin) / float(nknots + 1)
|
|
141
|
+
xknot = np.zeros(nknots)
|
|
142
|
+
for i in range(nknots):
|
|
143
|
+
xknot[i] = (xmin + float(i + 1) * deltax)
|
|
144
|
+
else:
|
|
145
|
+
xknot = np.array([])
|
|
146
|
+
except (ValueError, TypeError):
|
|
147
|
+
xknot = np.asarray(t)
|
|
148
|
+
if check_finite:
|
|
149
|
+
if not np.isfinite(xknot).all():
|
|
150
|
+
raise ValueError('Interior knots must not contain '
|
|
151
|
+
'NaNs or infs.')
|
|
152
|
+
if xknot.ndim != 1:
|
|
153
|
+
raise ValueError('t array must have dimension 1')
|
|
154
|
+
nknots = len(xknot)
|
|
155
|
+
|
|
156
|
+
# adaptive knots
|
|
157
|
+
if nknots > 0 and adaptive:
|
|
158
|
+
xknot_backup = xknot.copy()
|
|
159
|
+
|
|
160
|
+
# normalise the x and y arrays to the [-1, +1] interval
|
|
161
|
+
xmin = x[0]
|
|
162
|
+
xmax = x[-1]
|
|
163
|
+
ymin = np.min(y)
|
|
164
|
+
ymax = np.max(y)
|
|
165
|
+
bx = 2.0 / (xmax - xmin)
|
|
166
|
+
cx = (xmin + xmax) / (xmax - xmin)
|
|
167
|
+
by = 2.0 / (ymax - ymin)
|
|
168
|
+
cy = (ymin + ymax) / (ymax - ymin)
|
|
169
|
+
xnor = bx * np.asarray(x) - cx
|
|
170
|
+
ynor = by * np.asarray(y) - cy
|
|
171
|
+
xknotnor = bx * xknot - cx
|
|
172
|
+
params = Parameters()
|
|
173
|
+
for i in range(nknots):
|
|
174
|
+
if i == 0:
|
|
175
|
+
xminknot = bx * x[0] - cx
|
|
176
|
+
xmaxknot = (xknotnor[i] + xknotnor[i+1]) / 2.0
|
|
177
|
+
elif i == nknots - 1:
|
|
178
|
+
xminknot = (xknotnor[i-1] + xknotnor[i]) / 2.0
|
|
179
|
+
xmaxknot = bx * x[-1] - cx
|
|
180
|
+
else:
|
|
181
|
+
xminknot = (xknotnor[i-1] + xknotnor[i]) / 2.0
|
|
182
|
+
xmaxknot = (xknotnor[i] + xknotnor[i+1]) / 2.0
|
|
183
|
+
params.add(
|
|
184
|
+
name=f'xknot{i:03d}',
|
|
185
|
+
value=xknotnor[i],
|
|
186
|
+
min=xminknot,
|
|
187
|
+
max=xmaxknot,
|
|
188
|
+
vary=True
|
|
189
|
+
)
|
|
190
|
+
self._params = params.copy()
|
|
191
|
+
fitter = Minimizer(
|
|
192
|
+
userfcn=fun_residuals,
|
|
193
|
+
params=params,
|
|
194
|
+
fcn_args=(xnor, ynor, w, bbox, k, ext)
|
|
195
|
+
)
|
|
196
|
+
try:
|
|
197
|
+
self._result = fitter.scalar_minimize(
|
|
198
|
+
method='Nelder-Mead',
|
|
199
|
+
tol=tolerance
|
|
200
|
+
)
|
|
201
|
+
xknot = [item.value for item in self._result.params.values()]
|
|
202
|
+
xknot = (np.asarray(xknot) + cx) / bx
|
|
203
|
+
except ValueError:
|
|
204
|
+
print('Error when fitting adaptive splines. '
|
|
205
|
+
'Reverting to initial knot location.')
|
|
206
|
+
xknot = xknot_backup.copy()
|
|
207
|
+
self._result = None
|
|
208
|
+
else:
|
|
209
|
+
self._params = None
|
|
210
|
+
self._result = None
|
|
211
|
+
|
|
212
|
+
# final fit
|
|
213
|
+
super(AdaptiveLSQUnivariateSpline, self).__init__(
|
|
214
|
+
x=x,
|
|
215
|
+
y=y,
|
|
216
|
+
t=xknot,
|
|
217
|
+
w=w,
|
|
218
|
+
bbox=bbox,
|
|
219
|
+
k=k,
|
|
220
|
+
ext=ext,
|
|
221
|
+
check_finite=False
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
def get_params(self):
|
|
225
|
+
"""Return initial parameters for minimisation process."""
|
|
226
|
+
|
|
227
|
+
return self._params
|
|
228
|
+
|
|
229
|
+
def get_result(self):
|
|
230
|
+
"""Return result of minimisation process."""
|
|
231
|
+
|
|
232
|
+
return self._result
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: teareduce
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.5
|
|
4
4
|
Summary: Utilities for astronomical data reduction
|
|
5
5
|
Author-email: Nicolás Cardiel <cardiel@ucm.es>
|
|
6
6
|
License: GPL-3.0-or-later
|
|
@@ -22,6 +22,7 @@ Description-Content-Type: text/markdown
|
|
|
22
22
|
License-File: LICENSE.txt
|
|
23
23
|
Requires-Dist: astropy
|
|
24
24
|
Requires-Dist: importlib_resources
|
|
25
|
+
Requires-Dist: lmfit
|
|
25
26
|
Requires-Dist: matplotlib
|
|
26
27
|
Requires-Dist: numpy>=1.20
|
|
27
28
|
Requires-Dist: scipy
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|