teareduce 0.4.6__tar.gz → 0.4.7__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.4.6/src/teareduce.egg-info → teareduce-0.4.7}/PKG-INFO +1 -1
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/sliceregion.py +73 -3
- teareduce-0.4.7/src/teareduce/tests/test_sliceregion.py +116 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/version.py +1 -1
- {teareduce-0.4.6 → teareduce-0.4.7/src/teareduce.egg-info}/PKG-INFO +1 -1
- teareduce-0.4.6/src/teareduce/tests/test_sliceregion.py +0 -49
- {teareduce-0.4.6 → teareduce-0.4.7}/LICENSE.txt +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/README.md +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/pyproject.toml +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/setup.cfg +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/__init__.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/avoid_astropy_warnings.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/cleanest.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/correct_pincushion_distortion.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/cosmicrays.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/ctext.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/draw_rectangle.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/elapsed_time.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/histogram1d.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/imshow.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/numsplines.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/peaks_spectrum.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/polfit.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/robust_std.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/sdistortion.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/simulateccdexposure.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/statsummary.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/tests/__init__.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/tests/test_version.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/wavecal.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/write_array_to_fits.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce/zscale.py +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce.egg-info/SOURCES.txt +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce.egg-info/dependency_links.txt +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce.egg-info/entry_points.txt +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce.egg-info/requires.txt +0 -0
- {teareduce-0.4.6 → teareduce-0.4.7}/src/teareduce.egg-info/top_level.txt +0 -0
|
@@ -43,7 +43,7 @@ class SliceRegion1D:
|
|
|
43
43
|
Check if slice 'other' is within the parent slice.
|
|
44
44
|
"""
|
|
45
45
|
|
|
46
|
-
def __init__(self, region, mode=None):
|
|
46
|
+
def __init__(self, region, mode=None, naxis1=None):
|
|
47
47
|
"""Initialize SliceRegion1D.
|
|
48
48
|
|
|
49
49
|
Parameters
|
|
@@ -54,6 +54,9 @@ class SliceRegion1D:
|
|
|
54
54
|
mode : str
|
|
55
55
|
Convention mode employed to define the slice.
|
|
56
56
|
The two possible modes are 'fits' and 'python'.
|
|
57
|
+
naxis1 : int
|
|
58
|
+
The axis 1 size (length) of the data being sliced.
|
|
59
|
+
If provided, it is used to validate the slice region.
|
|
57
60
|
"""
|
|
58
61
|
if isinstance(region, str):
|
|
59
62
|
pattern = r'^\s*\[\s*\d+\s*:\s*\d+\s*\]\s*$'
|
|
@@ -93,6 +96,12 @@ class SliceRegion1D:
|
|
|
93
96
|
else:
|
|
94
97
|
raise ValueError(errmsg)
|
|
95
98
|
|
|
99
|
+
if naxis1 is not None:
|
|
100
|
+
if not (1 <= self.fits.start <= naxis1):
|
|
101
|
+
raise ValueError(f'Invalid start={self.fits.start} for naxis1={naxis1}')
|
|
102
|
+
if not (1 <= self.fits.stop <= naxis1+1):
|
|
103
|
+
raise ValueError(f'Invalid stop={self.fits.stop} for naxis1={naxis1}')
|
|
104
|
+
|
|
96
105
|
s = self.fits
|
|
97
106
|
self.fits_section = f'[{s.start}:{s.stop}]'
|
|
98
107
|
|
|
@@ -137,6 +146,10 @@ class SliceRegion1D:
|
|
|
137
146
|
result = True
|
|
138
147
|
return result
|
|
139
148
|
|
|
149
|
+
def length(self):
|
|
150
|
+
"""Return the length of the slice."""
|
|
151
|
+
return self.python.stop - self.python.start
|
|
152
|
+
|
|
140
153
|
|
|
141
154
|
class SliceRegion2D:
|
|
142
155
|
"""Store indices for slicing of 2D regions.
|
|
@@ -163,7 +176,7 @@ class SliceRegion2D:
|
|
|
163
176
|
within(other)
|
|
164
177
|
Check if slice 'other' is within the parent slice."""
|
|
165
178
|
|
|
166
|
-
def __init__(self, region, mode=None):
|
|
179
|
+
def __init__(self, region, mode=None, naxis1=None, naxis2=None):
|
|
167
180
|
"""Initialize SliceRegion2D.
|
|
168
181
|
|
|
169
182
|
Parameters
|
|
@@ -175,6 +188,14 @@ class SliceRegion2D:
|
|
|
175
188
|
mode : str
|
|
176
189
|
Convention mode employed to define the slice.
|
|
177
190
|
The two possible modes are 'fits' and 'python'.
|
|
191
|
+
naxis1 : int
|
|
192
|
+
The axis 1 size (length) of the data being sliced,
|
|
193
|
+
assuming the FITS convention.
|
|
194
|
+
If provided, it is used to validate the slice region.
|
|
195
|
+
naxis2 : int
|
|
196
|
+
The axis 2 size (length) of the data being sliced,
|
|
197
|
+
assuming the FITS convention.
|
|
198
|
+
If provided, it is used to validate the slice region.
|
|
178
199
|
"""
|
|
179
200
|
if isinstance(region, str):
|
|
180
201
|
pattern = r'^\s*\[\s*\d+\s*:\s*\d+\s*,\s*\d+\s*:\s*\d+\s*\]\s*$'
|
|
@@ -224,6 +245,17 @@ class SliceRegion2D:
|
|
|
224
245
|
s1, s2 = self.fits
|
|
225
246
|
self.fits_section = f'[{s1.start}:{s1.stop},{s2.start}:{s2.stop}]'
|
|
226
247
|
|
|
248
|
+
if naxis1 is not None:
|
|
249
|
+
if not (1 <= s1.start <= naxis1):
|
|
250
|
+
raise ValueError(f'Invalid start={s1.start} for naxis1={naxis1}')
|
|
251
|
+
if not (1 <= s1.stop <= naxis1):
|
|
252
|
+
raise ValueError(f'Invalid stop={s1.stop} for naxis1={naxis1}')
|
|
253
|
+
if naxis2 is not None:
|
|
254
|
+
if not (1 <= s2.start <= naxis2):
|
|
255
|
+
raise ValueError(f'Invalid start={s2.start} for naxis2={naxis2}')
|
|
256
|
+
if not (1 <= s2.stop <= naxis2):
|
|
257
|
+
raise ValueError(f'Invalid stop={s2.stop} for naxis2={naxis2}')
|
|
258
|
+
|
|
227
259
|
def __eq__(self, other):
|
|
228
260
|
return self.fits == other.fits and self.python == other.python
|
|
229
261
|
|
|
@@ -269,6 +301,11 @@ class SliceRegion2D:
|
|
|
269
301
|
result = True
|
|
270
302
|
return result
|
|
271
303
|
|
|
304
|
+
def area(self):
|
|
305
|
+
"""Return the area of the slice."""
|
|
306
|
+
s1, s2 = self.python
|
|
307
|
+
return (s1.stop - s1.start) * (s2.stop - s2.start)
|
|
308
|
+
|
|
272
309
|
|
|
273
310
|
class SliceRegion3D:
|
|
274
311
|
"""Store indices for slicing of 3D regions.
|
|
@@ -295,7 +332,7 @@ class SliceRegion3D:
|
|
|
295
332
|
within(other)
|
|
296
333
|
Check if slice 'other' is within the parent slice."""
|
|
297
334
|
|
|
298
|
-
def __init__(self, region, mode=None):
|
|
335
|
+
def __init__(self, region, mode=None, naxis1=None, naxis2=None, naxis3=None):
|
|
299
336
|
"""Initialize SliceRegion3D.
|
|
300
337
|
|
|
301
338
|
Parameters
|
|
@@ -307,6 +344,18 @@ class SliceRegion3D:
|
|
|
307
344
|
mode : str
|
|
308
345
|
Convention mode employed to define the slice.
|
|
309
346
|
The two possible modes are 'fits' and 'python'.
|
|
347
|
+
naxis1 : int
|
|
348
|
+
The axis 1 size (length) of the data being sliced,
|
|
349
|
+
assuming the FITS convention.
|
|
350
|
+
If provided, it is used to validate the slice region.
|
|
351
|
+
naxis2 : int
|
|
352
|
+
The axis 2 size (length) of the data being sliced,
|
|
353
|
+
assuming the FITS convention.
|
|
354
|
+
If provided, it is used to validate the slice region.
|
|
355
|
+
naxis3 : int
|
|
356
|
+
The axis 3 size (length) of the data being sliced,
|
|
357
|
+
assuming the FITS convention.
|
|
358
|
+
If provided, it is used to validate the slice region.
|
|
310
359
|
"""
|
|
311
360
|
if isinstance(region, str):
|
|
312
361
|
pattern = r'^\s*\[\s*\d+\s*:\s*\d+\s*,\s*\d+\s*:\s*\d+\s*,\s*\d+\s*:\s*\d+\s*\]\s*$'
|
|
@@ -360,6 +409,22 @@ class SliceRegion3D:
|
|
|
360
409
|
s1, s2, s3 = self.fits
|
|
361
410
|
self.fits_section = f'[{s1.start}:{s1.stop},{s2.start}:{s2.stop},{s3.start}:{s3.stop}]'
|
|
362
411
|
|
|
412
|
+
if naxis1 is not None:
|
|
413
|
+
if not (1 <= s1.start <= naxis1):
|
|
414
|
+
raise ValueError(f'Invalid start={s1.start} for naxis1={naxis1}')
|
|
415
|
+
if not (1 <= s1.stop <= naxis1):
|
|
416
|
+
raise ValueError(f'Invalid stop={s1.stop} for naxis1={naxis1}')
|
|
417
|
+
if naxis2 is not None:
|
|
418
|
+
if not (1 <= s2.start <= naxis2):
|
|
419
|
+
raise ValueError(f'Invalid start={s2.start} for naxis2={naxis2}')
|
|
420
|
+
if not (1 <= s2.stop <= naxis2):
|
|
421
|
+
raise ValueError(f'Invalid stop={s2.stop} for naxis2={naxis2}')
|
|
422
|
+
if naxis3 is not None:
|
|
423
|
+
if not (1 <= s3.start <= naxis3):
|
|
424
|
+
raise ValueError(f'Invalid start={s3.start} for naxis3={naxis3}')
|
|
425
|
+
if not (1 <= s3.stop <= naxis3):
|
|
426
|
+
raise ValueError(f'Invalid stop={s3.stop} for naxis3={naxis3}')
|
|
427
|
+
|
|
363
428
|
def __eq__(self, other):
|
|
364
429
|
return self.fits == other.fits and self.python == other.python
|
|
365
430
|
|
|
@@ -408,3 +473,8 @@ class SliceRegion3D:
|
|
|
408
473
|
return result
|
|
409
474
|
result = True
|
|
410
475
|
return result
|
|
476
|
+
|
|
477
|
+
def volume(self):
|
|
478
|
+
"""Return the volume of the slice."""
|
|
479
|
+
s1, s2, s3 = self.python
|
|
480
|
+
return (s1.stop - s1.start) * (s2.stop - s2.start) * (s3.stop - s3.start)
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright 2025 Universidad Complutense de Madrid
|
|
4
|
+
#
|
|
5
|
+
# This file is part of teareduce
|
|
6
|
+
#
|
|
7
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
8
|
+
# License-Filename: LICENSE.txt
|
|
9
|
+
#
|
|
10
|
+
"""Tests for the SliceRegion class."""
|
|
11
|
+
|
|
12
|
+
import numpy as np
|
|
13
|
+
|
|
14
|
+
from ..sliceregion import SliceRegion1D, SliceRegion2D, SliceRegion3D
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_slice_region_creation():
|
|
18
|
+
"""Test the creation of a SliceRegion."""
|
|
19
|
+
|
|
20
|
+
region1d = SliceRegion1D(np.s_[1:10], mode='python')
|
|
21
|
+
assert region1d.fits == slice(2, 10, None)
|
|
22
|
+
assert region1d.python == slice(1, 10, None)
|
|
23
|
+
assert region1d.fits_section == '[2:10]'
|
|
24
|
+
|
|
25
|
+
region2d = SliceRegion2D(np.s_[1:10, 2:20], mode='python')
|
|
26
|
+
assert region2d.fits == (slice(3, 20, None), slice(2, 10, None))
|
|
27
|
+
assert region2d.python == (slice(1, 10, None), slice(2, 20, None))
|
|
28
|
+
assert region2d.fits_section == '[3:20,2:10]'
|
|
29
|
+
|
|
30
|
+
region3d = SliceRegion3D(np.s_[1:10, 2:20, 3:30], mode='python')
|
|
31
|
+
assert region3d.fits == (slice(4, 30, None), slice(3, 20, None), slice(2, 10, None))
|
|
32
|
+
assert region3d.python == (slice(1, 10, None), slice(2, 20, None), slice(3, 30, None))
|
|
33
|
+
assert region3d.fits_section == '[4:30,3:20,2:10]'
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_slice_values():
|
|
37
|
+
"""Test the values of the slices in different modes."""
|
|
38
|
+
|
|
39
|
+
array1d = np.arange(10)
|
|
40
|
+
|
|
41
|
+
region1d = SliceRegion1D(np.s_[1:3], mode='python')
|
|
42
|
+
assert np.all(array1d[region1d.python] == np.array([1, 2]))
|
|
43
|
+
|
|
44
|
+
array2d = np.arange(12).reshape(3, 4)
|
|
45
|
+
region2d = SliceRegion2D(np.s_[1:3, 2:3], mode='python')
|
|
46
|
+
assert np.all(array2d[region2d.python] == np.array([[6], [10]]))
|
|
47
|
+
|
|
48
|
+
array3d = np.arange(24).reshape(3, 4, 2)
|
|
49
|
+
region3d = SliceRegion3D(np.s_[1:3, 2:4, 1:2], mode='python')
|
|
50
|
+
assert np.all(array3d[region3d.python] == np.array([[[13], [15]], [[21], [23]]]))
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_wrong_number_of_dimensions():
|
|
54
|
+
"""Test the creation of a SliceRegion with wrong slices."""
|
|
55
|
+
|
|
56
|
+
try:
|
|
57
|
+
SliceRegion1D(np.s_[1:3, 2:4], mode='python')
|
|
58
|
+
assert False, "Expected ValueError for 1D slice with 2D input"
|
|
59
|
+
except ValueError:
|
|
60
|
+
pass
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
SliceRegion2D(np.s_[1:3], mode='python')
|
|
64
|
+
assert False, "Expected ValueError for 2D slice with 1D input"
|
|
65
|
+
except ValueError:
|
|
66
|
+
pass
|
|
67
|
+
|
|
68
|
+
try:
|
|
69
|
+
SliceRegion3D(np.s_[1:3, 2:4], mode='python')
|
|
70
|
+
assert False, "Expected ValueError for 3D slice with 2D input"
|
|
71
|
+
except ValueError:
|
|
72
|
+
pass
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_wrong_limits_order():
|
|
76
|
+
"""Test the creation of a SliceRegion with wrong limits."""
|
|
77
|
+
|
|
78
|
+
try:
|
|
79
|
+
SliceRegion1D(np.s_[10:5], mode='python')
|
|
80
|
+
assert False, "Expected ValueError for 1D slice with start > stop"
|
|
81
|
+
except ValueError:
|
|
82
|
+
pass
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
SliceRegion2D(np.s_[1:3, 5:2], mode='python')
|
|
86
|
+
assert False, "Expected ValueError for 2D slice with start > stop in second dimension"
|
|
87
|
+
except ValueError:
|
|
88
|
+
pass
|
|
89
|
+
|
|
90
|
+
try:
|
|
91
|
+
SliceRegion3D(np.s_[1:3, 2:4, 6:1], mode='python')
|
|
92
|
+
assert False, "Expected ValueError for 3D slice with start > stop in third dimension"
|
|
93
|
+
except ValueError:
|
|
94
|
+
pass
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def test_limits_out_of_range():
|
|
98
|
+
"""Test the creation of a SliceRegion with limits out of range."""
|
|
99
|
+
|
|
100
|
+
try:
|
|
101
|
+
SliceRegion1D(np.s_[-1:5], mode='python', naxis1=10)
|
|
102
|
+
assert False, "Expected ValueError for 1D slice with negative start"
|
|
103
|
+
except ValueError:
|
|
104
|
+
pass
|
|
105
|
+
|
|
106
|
+
try:
|
|
107
|
+
SliceRegion2D(np.s_[1:3, 2:25], mode='python', naxis1=10, naxis2=20)
|
|
108
|
+
assert False, "Expected ValueError for 2D slice with stop > naxis in second dimension"
|
|
109
|
+
except ValueError:
|
|
110
|
+
pass
|
|
111
|
+
|
|
112
|
+
try:
|
|
113
|
+
SliceRegion3D(np.s_[1:3, 2:4, 3:35], mode='python', naxis1=10, naxis2=20, naxis3=30)
|
|
114
|
+
assert False, "Expected ValueError for 3D slice with stop > naxis in third dimension"
|
|
115
|
+
except ValueError:
|
|
116
|
+
pass
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
#
|
|
3
|
-
# Copyright 2025 Universidad Complutense de Madrid
|
|
4
|
-
#
|
|
5
|
-
# This file is part of teareduce
|
|
6
|
-
#
|
|
7
|
-
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
8
|
-
# License-Filename: LICENSE.txt
|
|
9
|
-
#
|
|
10
|
-
"""Tests for the SliceRegion class."""
|
|
11
|
-
|
|
12
|
-
import numpy as np
|
|
13
|
-
|
|
14
|
-
from ..sliceregion import SliceRegion1D, SliceRegion2D, SliceRegion3D
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def test_slice_region_creation():
|
|
18
|
-
"""Test the creation of a SliceRegion."""
|
|
19
|
-
|
|
20
|
-
region1d = SliceRegion1D(np.s_[1:10], mode='python')
|
|
21
|
-
assert region1d.fits == slice(2, 10, None)
|
|
22
|
-
assert region1d.python == slice(1, 10, None)
|
|
23
|
-
assert region1d.fits_section == '[2:10]'
|
|
24
|
-
|
|
25
|
-
region2d = SliceRegion2D(np.s_[1:10, 2:20], mode='python')
|
|
26
|
-
assert region2d.fits == (slice(3, 20, None), slice(2, 10, None))
|
|
27
|
-
assert region2d.python == (slice(1, 10, None), slice(2, 20, None))
|
|
28
|
-
assert region2d.fits_section == '[3:20,2:10]'
|
|
29
|
-
|
|
30
|
-
region3d = SliceRegion3D(np.s_[1:10, 2:20, 3:30], mode='python')
|
|
31
|
-
assert region3d.fits == (slice(4, 30, None), slice(3, 20, None), slice(2, 10, None))
|
|
32
|
-
assert region3d.python == (slice(1, 10, None), slice(2, 20, None), slice(3, 30, None))
|
|
33
|
-
assert region3d.fits_section == '[4:30,3:20,2:10]'
|
|
34
|
-
|
|
35
|
-
def test_slice_values():
|
|
36
|
-
"""Test the values of the slices in different modes."""
|
|
37
|
-
|
|
38
|
-
array1d = np.arange(10)
|
|
39
|
-
|
|
40
|
-
region1d = SliceRegion1D(np.s_[1:3], mode='python')
|
|
41
|
-
assert np.all(array1d[region1d.python] == np.array([1, 2]))
|
|
42
|
-
|
|
43
|
-
array2d = np.arange(12).reshape(3, 4)
|
|
44
|
-
region2d = SliceRegion2D(np.s_[1:3, 2:3], mode='python')
|
|
45
|
-
assert np.all(array2d[region2d.python] == np.array([[6], [10]]))
|
|
46
|
-
|
|
47
|
-
array3d = np.arange(24).reshape(3, 4, 2)
|
|
48
|
-
region3d = SliceRegion3D(np.s_[1:3, 2:4, 1:2], mode='python')
|
|
49
|
-
assert np.all(array3d[region3d.python] == np.array([[[13], [15]], [[21], [23]]]))
|
|
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
|
|
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
|