teareduce 0.4.6__py3-none-any.whl → 0.4.7__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.
teareduce/sliceregion.py CHANGED
@@ -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)
@@ -32,6 +32,7 @@ def test_slice_region_creation():
32
32
  assert region3d.python == (slice(1, 10, None), slice(2, 20, None), slice(3, 30, None))
33
33
  assert region3d.fits_section == '[4:30,3:20,2:10]'
34
34
 
35
+
35
36
  def test_slice_values():
36
37
  """Test the values of the slices in different modes."""
37
38
 
@@ -47,3 +48,69 @@ def test_slice_values():
47
48
  array3d = np.arange(24).reshape(3, 4, 2)
48
49
  region3d = SliceRegion3D(np.s_[1:3, 2:4, 1:2], mode='python')
49
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
teareduce/version.py CHANGED
@@ -9,7 +9,7 @@
9
9
  #
10
10
  """Module to define the version of the teareduce package."""
11
11
 
12
- VERSION = '0.4.6'
12
+ VERSION = '0.4.7'
13
13
 
14
14
 
15
15
  def main():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: teareduce
3
- Version: 0.4.6
3
+ Version: 0.4.7
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
@@ -14,18 +14,18 @@ teareduce/polfit.py,sha256=CGsrRsz_Du2aKxOcgXi36lpAZO04JyqCCUaxhC0C-Mk,14281
14
14
  teareduce/robust_std.py,sha256=dk1G3VgiplZzmSfL7qWniEZ-5c3novHnBpRPCM77u84,1084
15
15
  teareduce/sdistortion.py,sha256=5ZsZn4vD5Sw2aoqO8-NIOH7H89Zmh7ZDkow6YbAotHU,5916
16
16
  teareduce/simulateccdexposure.py,sha256=cdbpca6GVuM3d7R1LGzlIZZvjTq_jzrlkk_Cli7aouQ,24636
17
- teareduce/sliceregion.py,sha256=VFhIUqEF4dH5IhIBrdvmYjvgkxCKNWRxJR10oypVbBY,14973
17
+ teareduce/sliceregion.py,sha256=AbkBqY7YaMYTvg-5BCdEoCB8NhIYsSMGcadXioCQfzo,18356
18
18
  teareduce/statsummary.py,sha256=VTNAnBV8z6suqiyB2Lhw3YjUUOjlmwUPX3enkOKRF54,5422
19
- teareduce/version.py,sha256=Pzgc2GKYwBL3pvjKHigKM9Jks22zwuhw5gwWxoxQO7Q,419
19
+ teareduce/version.py,sha256=YfSDOnYOawt4dVMMDQzqFv1P8lf52tpIIDIBbNnrZW0,419
20
20
  teareduce/wavecal.py,sha256=2MewWz5Y3ms41c305UtWOM_LaLNdk1mugDXCtzf-fSw,68586
21
21
  teareduce/write_array_to_fits.py,sha256=kWDrEH9coJ1yIu56oQJpWtDqJL4c8HGmssE9jle4e94,617
22
22
  teareduce/zscale.py,sha256=SDgmcDD2N5GvDn46JADCgTQJPBF_N_jSKMHoeTz9Nsw,1152
23
23
  teareduce/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
- teareduce/tests/test_sliceregion.py,sha256=25dhS7yJ1z_3tgFLw21uOkNKuugyVA-8L1ehafSQjFg,1769
24
+ teareduce/tests/test_sliceregion.py,sha256=S7Zoh2eEBFIEbfsXgWBEMCf7pottjw2oLhqlZJQkAwg,3785
25
25
  teareduce/tests/test_version.py,sha256=mKLnbXyvVNc1pATq5PxR8qeoFMPAFL_GilFV6IHLOi0,172
26
- teareduce-0.4.6.dist-info/licenses/LICENSE.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
27
- teareduce-0.4.6.dist-info/METADATA,sha256=pyykAUteD0AIMJO3mfiokQAfypsYB6bnxd520_fOX5o,3017
28
- teareduce-0.4.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
29
- teareduce-0.4.6.dist-info/entry_points.txt,sha256=0ovOBIllSl9nN65mVOVVh--Gdd4AE2JebKuFk2YQ0wk,57
30
- teareduce-0.4.6.dist-info/top_level.txt,sha256=7OkwtX9zNRkGJ7ACgjk4ESgC74qUYcS5O2qcO0v-Si4,10
31
- teareduce-0.4.6.dist-info/RECORD,,
26
+ teareduce-0.4.7.dist-info/licenses/LICENSE.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
27
+ teareduce-0.4.7.dist-info/METADATA,sha256=ylCxvLo5-wbLkWnlz1ve_c4THv-q6VHfB8RG2FUK1Ac,3017
28
+ teareduce-0.4.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
29
+ teareduce-0.4.7.dist-info/entry_points.txt,sha256=0ovOBIllSl9nN65mVOVVh--Gdd4AE2JebKuFk2YQ0wk,57
30
+ teareduce-0.4.7.dist-info/top_level.txt,sha256=7OkwtX9zNRkGJ7ACgjk4ESgC74qUYcS5O2qcO0v-Si4,10
31
+ teareduce-0.4.7.dist-info/RECORD,,