teareduce 0.3.0__tar.gz → 0.3.6__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.
Files changed (28) hide show
  1. {teareduce-0.3.0/src/teareduce.egg-info → teareduce-0.3.6}/PKG-INFO +2 -1
  2. {teareduce-0.3.0 → teareduce-0.3.6}/pyproject.toml +2 -1
  3. {teareduce-0.3.0 → teareduce-0.3.6}/src/teareduce/__init__.py +1 -0
  4. {teareduce-0.3.0 → teareduce-0.3.6}/src/teareduce/imshow.py +5 -1
  5. teareduce-0.3.6/src/teareduce/numsplines.py +232 -0
  6. {teareduce-0.3.0 → teareduce-0.3.6}/src/teareduce/version.py +1 -1
  7. {teareduce-0.3.0 → teareduce-0.3.6/src/teareduce.egg-info}/PKG-INFO +2 -1
  8. {teareduce-0.3.0 → teareduce-0.3.6}/src/teareduce.egg-info/SOURCES.txt +1 -0
  9. {teareduce-0.3.0 → teareduce-0.3.6}/src/teareduce.egg-info/requires.txt +1 -0
  10. {teareduce-0.3.0 → teareduce-0.3.6}/LICENSE.txt +0 -0
  11. {teareduce-0.3.0 → teareduce-0.3.6}/README.md +0 -0
  12. {teareduce-0.3.0 → teareduce-0.3.6}/setup.cfg +0 -0
  13. {teareduce-0.3.0 → teareduce-0.3.6}/src/teareduce/avoid_astropy_warnings.py +0 -0
  14. {teareduce-0.3.0 → teareduce-0.3.6}/src/teareduce/correct_pincushion_distortion.py +0 -0
  15. {teareduce-0.3.0 → teareduce-0.3.6}/src/teareduce/cosmicrays.py +0 -0
  16. {teareduce-0.3.0 → teareduce-0.3.6}/src/teareduce/ctext.py +0 -0
  17. {teareduce-0.3.0 → teareduce-0.3.6}/src/teareduce/draw_rectangle.py +0 -0
  18. {teareduce-0.3.0 → teareduce-0.3.6}/src/teareduce/elapsed_time.py +0 -0
  19. {teareduce-0.3.0 → teareduce-0.3.6}/src/teareduce/peaks_spectrum.py +0 -0
  20. {teareduce-0.3.0 → teareduce-0.3.6}/src/teareduce/polfit.py +0 -0
  21. {teareduce-0.3.0 → teareduce-0.3.6}/src/teareduce/robust_std.py +0 -0
  22. {teareduce-0.3.0 → teareduce-0.3.6}/src/teareduce/sdistortion.py +0 -0
  23. {teareduce-0.3.0 → teareduce-0.3.6}/src/teareduce/sliceregion.py +0 -0
  24. {teareduce-0.3.0 → teareduce-0.3.6}/src/teareduce/statsummary.py +0 -0
  25. {teareduce-0.3.0 → teareduce-0.3.6}/src/teareduce/wavecal.py +0 -0
  26. {teareduce-0.3.0 → teareduce-0.3.6}/src/teareduce/zscale.py +0 -0
  27. {teareduce-0.3.0 → teareduce-0.3.6}/src/teareduce.egg-info/dependency_links.txt +0 -0
  28. {teareduce-0.3.0 → teareduce-0.3.6}/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.0
3
+ Version: 0.3.6
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
@@ -83,7 +83,11 @@ def imshow(fig=None, ax=None, data=None,
83
83
  xlabel = f'Wavelength ({cunitx})'
84
84
  aspect = 'auto'
85
85
  else:
86
- extent = None
86
+ if 'extent' in kwargs:
87
+ extent = kwargs['extent']
88
+ del kwargs['extent']
89
+ else:
90
+ extent = None
87
91
  if 'aspect' in kwargs:
88
92
  aspect = kwargs['aspect']
89
93
  del kwargs['aspect']
@@ -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
@@ -8,7 +8,7 @@
8
8
  # License-Filename: LICENSE.txt
9
9
  #
10
10
 
11
- version = '0.3.0'
11
+ version = '0.3.6'
12
12
 
13
13
 
14
14
  def main():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: teareduce
3
- Version: 0.3.0
3
+ Version: 0.3.6
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
@@ -9,6 +9,7 @@ src/teareduce/ctext.py
9
9
  src/teareduce/draw_rectangle.py
10
10
  src/teareduce/elapsed_time.py
11
11
  src/teareduce/imshow.py
12
+ src/teareduce/numsplines.py
12
13
  src/teareduce/peaks_spectrum.py
13
14
  src/teareduce/polfit.py
14
15
  src/teareduce/robust_std.py
@@ -1,5 +1,6 @@
1
1
  astropy
2
2
  importlib_resources
3
+ lmfit
3
4
  matplotlib
4
5
  numpy>=1.20
5
6
  scipy
File without changes
File without changes
File without changes