pyimcom 1.2.1__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.
- pyimcom/__init__.py +1 -0
- pyimcom/_version.py +24 -0
- pyimcom/analysis.py +1480 -0
- pyimcom/coadd.py +2331 -0
- pyimcom/compress/__init__.py +0 -0
- pyimcom/compress/compressutils.py +506 -0
- pyimcom/compress/compressutils_wrapper.py +116 -0
- pyimcom/compress/i24.py +514 -0
- pyimcom/config.py +1245 -0
- pyimcom/diagnostics/__init__.py +0 -0
- pyimcom/diagnostics/context_figure.py +58 -0
- pyimcom/diagnostics/dynrange.py +274 -0
- pyimcom/diagnostics/layer_diagnostics.py +208 -0
- pyimcom/diagnostics/mosaicimage.py +80 -0
- pyimcom/diagnostics/noise/stability.py +126 -0
- pyimcom/diagnostics/noise_diagnostics.py +709 -0
- pyimcom/diagnostics/outimage_utils/__init__.py +0 -0
- pyimcom/diagnostics/outimage_utils/helper.py +82 -0
- pyimcom/diagnostics/report.py +366 -0
- pyimcom/diagnostics/run.py +64 -0
- pyimcom/diagnostics/starcube_nonoise.py +264 -0
- pyimcom/diagnostics/starcube_nonoise_coldescr.txt +24 -0
- pyimcom/diagnostics/stars.py +469 -0
- pyimcom/imdestripe.py +2454 -0
- pyimcom/lakernel.py +805 -0
- pyimcom/layer.py +1439 -0
- pyimcom/layer_wrapper.py +96 -0
- pyimcom/meta/__init__.py +0 -0
- pyimcom/meta/distortimage.py +748 -0
- pyimcom/meta/ginterp.py +340 -0
- pyimcom/pictures/__init__.py +0 -0
- pyimcom/pictures/genpic.py +229 -0
- pyimcom/psfutil.py +2199 -0
- pyimcom/routine.py +588 -0
- pyimcom/splitpsf/__init__.py +0 -0
- pyimcom/splitpsf/imsubtract.py +793 -0
- pyimcom/splitpsf/imsubtract_wrapper.py +107 -0
- pyimcom/splitpsf/splitpsf.py +497 -0
- pyimcom/splitpsf/splitpsf_wrapper.py +161 -0
- pyimcom/splitpsf/update_cube.py +136 -0
- pyimcom/truthcats.py +396 -0
- pyimcom/utils/__init__.py +0 -0
- pyimcom/utils/compareutils.py +207 -0
- pyimcom/utils/piffutils.py +223 -0
- pyimcom/wcsutil.py +839 -0
- pyimcom-1.2.1.dist-info/METADATA +67 -0
- pyimcom-1.2.1.dist-info/RECORD +52 -0
- pyimcom-1.2.1.dist-info/WHEEL +5 -0
- pyimcom-1.2.1.dist-info/licenses/LICENSE +21 -0
- pyimcom-1.2.1.dist-info/scm_file_list.json +285 -0
- pyimcom-1.2.1.dist-info/scm_version.json +8 -0
- pyimcom-1.2.1.dist-info/top_level.txt +1 -0
pyimcom/compress/i24.py
ADDED
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
"""Functions to compress float arrays to 24 bit integers.
|
|
2
|
+
|
|
3
|
+
Functions
|
|
4
|
+
---------
|
|
5
|
+
lsbf_fwd
|
|
6
|
+
Least significant bits moved first.
|
|
7
|
+
lsbf_rev
|
|
8
|
+
Inverse of `lsbf_fwd`.
|
|
9
|
+
diff_fwd
|
|
10
|
+
Replaces an image with an array of differences.
|
|
11
|
+
diff_rev
|
|
12
|
+
Inverse of `diff_fwd`.
|
|
13
|
+
smallnum_fwd
|
|
14
|
+
Re-maps numbers of small absolute value to be near 0 when unsigned.
|
|
15
|
+
smallnum_rev
|
|
16
|
+
Inverse of `smallnum_fwd`.
|
|
17
|
+
i24compress
|
|
18
|
+
Compresses an array using the 'I24' scheme.
|
|
19
|
+
i24decompress
|
|
20
|
+
Decompresses an array using the 'I24' scheme.
|
|
21
|
+
|
|
22
|
+
Classes
|
|
23
|
+
-------
|
|
24
|
+
I24Cube
|
|
25
|
+
Object that can be reformatted as floating point, integer, or compressed integer
|
|
26
|
+
in the 'I24' scheme.
|
|
27
|
+
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
import copy
|
|
31
|
+
|
|
32
|
+
import numpy as np
|
|
33
|
+
from astropy.io import fits
|
|
34
|
+
|
|
35
|
+
# Compression scheme table
|
|
36
|
+
i24_recognized_schemes = ["I24A", "I24B"]
|
|
37
|
+
|
|
38
|
+
### Utilities for reorganizing uint8 cubes ###
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def lsbf_fwd(im):
|
|
42
|
+
"""
|
|
43
|
+
Takes a 2D uint8 image and swaps the bits so that the least significant
|
|
44
|
+
bit goes first, then the next, etc. and the most significant bit goes last.
|
|
45
|
+
|
|
46
|
+
If given a 3D image, then does each 2D slice. The intent would be to use
|
|
47
|
+
this on objects with a shape of (3,ny,nx); it will work for any number of slices,
|
|
48
|
+
but it will be slow if the number of slices (3 in this case) is large.
|
|
49
|
+
|
|
50
|
+
Parameters
|
|
51
|
+
----------
|
|
52
|
+
im : np.array of uint8
|
|
53
|
+
2D or 3D image.
|
|
54
|
+
|
|
55
|
+
Returns
|
|
56
|
+
-------
|
|
57
|
+
out_im : np.array of uint8
|
|
58
|
+
2D or 3D bit-swapped image. Same shape as `im`.
|
|
59
|
+
|
|
60
|
+
See Also
|
|
61
|
+
--------
|
|
62
|
+
lsbf_rev : Inverse function.
|
|
63
|
+
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
# 3D images are done one slice at a time
|
|
67
|
+
if len(np.shape(im)) == 3:
|
|
68
|
+
out_im = np.zeros_like(im)
|
|
69
|
+
for j in range(np.shape(im)[0]):
|
|
70
|
+
out_im[j, :, :] = lsbf_fwd(im[j, :, :])
|
|
71
|
+
return out_im
|
|
72
|
+
|
|
73
|
+
# now we have a 2D image
|
|
74
|
+
ny, nx = np.shape(im)
|
|
75
|
+
return np.packbits(
|
|
76
|
+
np.transpose(np.unpackbits(im, bitorder="little").reshape((ny, nx, 8)), axes=(2, 0, 1)).reshape(
|
|
77
|
+
(ny, nx, 8)
|
|
78
|
+
),
|
|
79
|
+
bitorder="little",
|
|
80
|
+
).reshape((ny, nx))
|
|
81
|
+
bits = np.zeros((8, ny, nx), dtype=bool)
|
|
82
|
+
for j in range(8):
|
|
83
|
+
bits[j, :, :] = (im >> j) % 2 == 1
|
|
84
|
+
bits = bits.reshape((ny, nx, 8))
|
|
85
|
+
out_im = np.zeros_like(im)
|
|
86
|
+
for j in range(8):
|
|
87
|
+
out_im += (2**j * bits[:, :, j]).astype(np.uint8)
|
|
88
|
+
return out_im
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def lsbf_rev(im):
|
|
92
|
+
"""Inverse of the bit-swapping function lsbf_fwd.
|
|
93
|
+
|
|
94
|
+
Parameters
|
|
95
|
+
----------
|
|
96
|
+
im : np.array of uint8
|
|
97
|
+
2D or 3D image.
|
|
98
|
+
|
|
99
|
+
Returns
|
|
100
|
+
-------
|
|
101
|
+
out_im : np.array of uint8
|
|
102
|
+
2D or 3D bit-swapped image. Same shape as `im`.
|
|
103
|
+
|
|
104
|
+
See Also
|
|
105
|
+
--------
|
|
106
|
+
lsbf_fwd : Forward function.
|
|
107
|
+
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
# 3D images are done one slice at a time
|
|
111
|
+
if len(np.shape(im)) == 3:
|
|
112
|
+
out_im = np.zeros_like(im)
|
|
113
|
+
for j in range(np.shape(im)[0]):
|
|
114
|
+
out_im[j, :, :] = lsbf_rev(im[j, :, :])
|
|
115
|
+
return out_im
|
|
116
|
+
|
|
117
|
+
# now we have a 2D image
|
|
118
|
+
ny, nx = np.shape(im)
|
|
119
|
+
return np.packbits(
|
|
120
|
+
np.transpose(np.unpackbits(im, bitorder="little").reshape((8, ny, nx)), axes=(1, 2, 0)),
|
|
121
|
+
bitorder="little",
|
|
122
|
+
).reshape((ny, nx))
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
### Utilities for differencing integer cubes ###
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def diff_fwd(im, bitkeep):
|
|
129
|
+
"""
|
|
130
|
+
Replace an int32 image with differences of the same shape.
|
|
131
|
+
|
|
132
|
+
Parameters
|
|
133
|
+
----------
|
|
134
|
+
im : np.array of int32
|
|
135
|
+
A 2D input image.
|
|
136
|
+
bitkeep : int
|
|
137
|
+
Number of bits to keep. The maximum is 31.
|
|
138
|
+
|
|
139
|
+
Returns
|
|
140
|
+
-------
|
|
141
|
+
np.array of int32
|
|
142
|
+
The image of differences, same shape as `im`.
|
|
143
|
+
|
|
144
|
+
See Also
|
|
145
|
+
--------
|
|
146
|
+
diff_rev : Inverse function.
|
|
147
|
+
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
ny, nx = np.shape(im)
|
|
151
|
+
c = im.flatten()
|
|
152
|
+
c[1:] = c[1:] - c[:-1]
|
|
153
|
+
c = (2**bitkeep + c) % 2**bitkeep
|
|
154
|
+
return c.reshape((ny, nx)).astype(np.int32)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def diff_rev(im, bitkeep):
|
|
158
|
+
"""Reconstruct an image from differences. Inverse function of diff_fwd.
|
|
159
|
+
|
|
160
|
+
Parameters
|
|
161
|
+
----------
|
|
162
|
+
im : np.array of int32
|
|
163
|
+
A 2D input image of differences.
|
|
164
|
+
bitkeep : int
|
|
165
|
+
Number of bits to keep. The maximum is 31.
|
|
166
|
+
|
|
167
|
+
Returns
|
|
168
|
+
-------
|
|
169
|
+
np.array of int32
|
|
170
|
+
The original image, same shape as `im`.
|
|
171
|
+
|
|
172
|
+
See Also
|
|
173
|
+
--------
|
|
174
|
+
diff_fwd : Forward function.
|
|
175
|
+
|
|
176
|
+
"""
|
|
177
|
+
|
|
178
|
+
ny, nx = np.shape(im)
|
|
179
|
+
c = im.astype(np.uint32).flatten()
|
|
180
|
+
c = np.cumsum(c) & np.uint32(2**bitkeep - 1)
|
|
181
|
+
return c.reshape((ny, nx)).astype(np.int32)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
### Utilities for packaging small numbers together ###
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def smallnum_fwd(im, bitkeep):
|
|
188
|
+
"""
|
|
189
|
+
Remapping to package small differences of either sign near 0.
|
|
190
|
+
|
|
191
|
+
Works on an int32 image with bitkeep bits used
|
|
192
|
+
and negative numbers rolling over as ``-j --> 2**bitkeep-j``.
|
|
193
|
+
|
|
194
|
+
Parameters
|
|
195
|
+
----------
|
|
196
|
+
im : np.array of int32
|
|
197
|
+
A 2D input image.
|
|
198
|
+
bitkeep : int
|
|
199
|
+
Number of bits to keep. The maximum is 31.
|
|
200
|
+
|
|
201
|
+
Returns
|
|
202
|
+
-------
|
|
203
|
+
np.array of int32
|
|
204
|
+
Re-mapped image, same shape as `im`.
|
|
205
|
+
|
|
206
|
+
See Also
|
|
207
|
+
--------
|
|
208
|
+
smallnum_rev : Inverse function.
|
|
209
|
+
|
|
210
|
+
"""
|
|
211
|
+
|
|
212
|
+
return np.where(im >= 2 ** (bitkeep - 1), 2 * (2**bitkeep - im) - 1, 2 * im)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def smallnum_rev(im, bitkeep):
|
|
216
|
+
"""
|
|
217
|
+
Reconstructs images that have been re-mapped. Inverse of smallnum_fwd.
|
|
218
|
+
|
|
219
|
+
Parameters
|
|
220
|
+
----------
|
|
221
|
+
im : np.array of int32
|
|
222
|
+
A 2D input image that has been re-mapped.
|
|
223
|
+
bitkeep : int
|
|
224
|
+
Number of bits to keep. The maximum is 31.
|
|
225
|
+
|
|
226
|
+
Returns
|
|
227
|
+
-------
|
|
228
|
+
np.array of int32
|
|
229
|
+
Original image, same shape as `im`.
|
|
230
|
+
|
|
231
|
+
See Also
|
|
232
|
+
--------
|
|
233
|
+
smallnum_fwd : Forward function.
|
|
234
|
+
|
|
235
|
+
"""
|
|
236
|
+
|
|
237
|
+
return np.where(im % 2, 2**bitkeep - 1 - im // 2, im // 2)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
class I24Cube:
|
|
241
|
+
"""
|
|
242
|
+
Class to compress a float cube to int24 with scaling, and reconstruct the original image.
|
|
243
|
+
|
|
244
|
+
Parameters
|
|
245
|
+
----------
|
|
246
|
+
inarray : np.array
|
|
247
|
+
The input array. Options are
|
|
248
|
+
* 2D float32 (original image)
|
|
249
|
+
* 2D int32 (intermediate step: leading byte not used)
|
|
250
|
+
* 3D uint8 (compressed form)
|
|
251
|
+
pars : dict
|
|
252
|
+
Parameters for the compression scheme. The possible keys are
|
|
253
|
+
VMIN, VMAX, SOFTBIAS, DIFF, ALPHA, BITKEEP, and REORDER.
|
|
254
|
+
overflow : astropy.io.fits.BinTableHDU or None, optional
|
|
255
|
+
Overflow table (y,x,value). Needed if a compressed image is given as input.
|
|
256
|
+
|
|
257
|
+
Attributes
|
|
258
|
+
----------
|
|
259
|
+
ny : int
|
|
260
|
+
Height of image
|
|
261
|
+
nx : int
|
|
262
|
+
Width of image
|
|
263
|
+
pars : dict
|
|
264
|
+
Compression parameters specified when constructed.
|
|
265
|
+
data : np.array
|
|
266
|
+
Current image data.
|
|
267
|
+
mode : str
|
|
268
|
+
Current image type. One of 'float32', 'int32', or 'uint8'.
|
|
269
|
+
vmin : float
|
|
270
|
+
Minimum of compression range.
|
|
271
|
+
vmax : float
|
|
272
|
+
Maximum of compression range.
|
|
273
|
+
alpha : float
|
|
274
|
+
Power law index of compression (1=linear).
|
|
275
|
+
bitkeep : int
|
|
276
|
+
Number of bits to keep (maximum=24).
|
|
277
|
+
reorder : bool
|
|
278
|
+
Implement bit reordering?
|
|
279
|
+
softbias : int
|
|
280
|
+
Integer in [0,2**24) to add (to avoid slight negative fluctuations being 111111).
|
|
281
|
+
If -1, uses smallnum compression instead.
|
|
282
|
+
diff : bool
|
|
283
|
+
Use difference of successive pixels?
|
|
284
|
+
overflow : astropy.io.fits.BinTableHDU or None
|
|
285
|
+
Overflow table (y,x,value).
|
|
286
|
+
reorder = use bit reordering? (boolean)
|
|
287
|
+
|
|
288
|
+
Methods
|
|
289
|
+
--------
|
|
290
|
+
__init__
|
|
291
|
+
Constructor.
|
|
292
|
+
to_mode
|
|
293
|
+
Change image format to a different (often compressed) storage mode.
|
|
294
|
+
|
|
295
|
+
"""
|
|
296
|
+
|
|
297
|
+
def __init__(self, inarray, pars, overflow=None):
|
|
298
|
+
# figure out what we have
|
|
299
|
+
self.pars = copy.copy(pars)
|
|
300
|
+
s = np.shape(inarray)
|
|
301
|
+
self.ny, self.nx = s[-2:]
|
|
302
|
+
self.data = copy.copy(inarray)
|
|
303
|
+
d = len(s)
|
|
304
|
+
|
|
305
|
+
# get the mode
|
|
306
|
+
if d == 2 and inarray.dtype.name == "float32":
|
|
307
|
+
self.mode = "float32"
|
|
308
|
+
elif d == 2 and inarray.dtype.name == "int32":
|
|
309
|
+
self.mode = "int32"
|
|
310
|
+
elif d == 3 and inarray.dtype.name == "uint8":
|
|
311
|
+
self.mode = "uint8"
|
|
312
|
+
else:
|
|
313
|
+
raise TypeError("Can't initialize I24Cube: unrecognized data type or dimension.")
|
|
314
|
+
|
|
315
|
+
# extract minimum and maximum (these need to be provided)
|
|
316
|
+
self.vmin = float(pars["VMIN"])
|
|
317
|
+
self.vmax = float(pars["VMAX"])
|
|
318
|
+
if "SOFTBIAS" in pars:
|
|
319
|
+
self.softbias = int(pars["SOFTBIAS"])
|
|
320
|
+
else:
|
|
321
|
+
self.softbias = 0
|
|
322
|
+
if "DIFF" in pars:
|
|
323
|
+
self.diff = bool(pars["DIFF"])
|
|
324
|
+
else:
|
|
325
|
+
self.diff = False
|
|
326
|
+
if "ALPHA" in pars:
|
|
327
|
+
self.alpha = float(pars["ALPHA"])
|
|
328
|
+
else:
|
|
329
|
+
self.alpha = 1.0
|
|
330
|
+
if "BITKEEP" in pars:
|
|
331
|
+
self.bitkeep = int(pars["BITKEEP"])
|
|
332
|
+
if self.bitkeep >= 24 or self.bitkeep <= 0:
|
|
333
|
+
raise ValueError(f"Can't keep {self.bitkeep:d} bits")
|
|
334
|
+
else:
|
|
335
|
+
self.bitkeep = 24
|
|
336
|
+
if "REORDER" in pars:
|
|
337
|
+
self.reorder = bool(pars["REORDER"])
|
|
338
|
+
else:
|
|
339
|
+
self.reorder = True
|
|
340
|
+
|
|
341
|
+
# overflow
|
|
342
|
+
self.overflow = overflow
|
|
343
|
+
|
|
344
|
+
def to_mode(self, mode):
|
|
345
|
+
"""
|
|
346
|
+
Converts to the given mode.
|
|
347
|
+
|
|
348
|
+
Parameters
|
|
349
|
+
----------
|
|
350
|
+
mode : str
|
|
351
|
+
Options are 'float32', 'int32', and 'uint8'.
|
|
352
|
+
|
|
353
|
+
Returns
|
|
354
|
+
-------
|
|
355
|
+
None
|
|
356
|
+
|
|
357
|
+
"""
|
|
358
|
+
|
|
359
|
+
if mode not in ["float32", "int32", "uint8"]:
|
|
360
|
+
raise Exception(f"Unrecognized mode: {mode:s}")
|
|
361
|
+
|
|
362
|
+
# nothing to do if there's no conversion
|
|
363
|
+
if self.mode == mode:
|
|
364
|
+
return
|
|
365
|
+
|
|
366
|
+
# need to convert float32->int32
|
|
367
|
+
if self.mode == "float32":
|
|
368
|
+
posy, posx = np.where(np.logical_or(self.data < self.vmin, self.data > self.vmax))
|
|
369
|
+
self.overflow = fits.BinTableHDU.from_columns(
|
|
370
|
+
[
|
|
371
|
+
fits.Column(name="y", format="J", array=posy),
|
|
372
|
+
fits.Column(name="x", format="J", array=posx),
|
|
373
|
+
fits.Column(name="value", format="E", array=np.copy(self.data[posy, posx])),
|
|
374
|
+
]
|
|
375
|
+
)
|
|
376
|
+
y = (np.clip(self.data, self.vmin, self.vmax) - self.vmin) / (self.vmax - self.vmin)
|
|
377
|
+
y = 2**self.bitkeep * y**self.alpha
|
|
378
|
+
self.data = np.clip(np.floor(y).astype(np.int32), 0, 2**self.bitkeep - 1)
|
|
379
|
+
del y
|
|
380
|
+
if self.diff:
|
|
381
|
+
self.data = diff_fwd(self.data, self.bitkeep)
|
|
382
|
+
if self.softbias > 0:
|
|
383
|
+
self.data = ((self.softbias + self.data) % 2**self.bitkeep).astype(np.int32)
|
|
384
|
+
elif self.softbias == -1:
|
|
385
|
+
self.data = smallnum_fwd(self.data, self.bitkeep)
|
|
386
|
+
self.mode = "int32"
|
|
387
|
+
|
|
388
|
+
# need to convert uint8->int32
|
|
389
|
+
if self.mode == "uint8":
|
|
390
|
+
if self.reorder:
|
|
391
|
+
x = lsbf_rev(self.data).astype(np.int32)
|
|
392
|
+
else:
|
|
393
|
+
x = copy.copy(self.data.astype(np.int32))
|
|
394
|
+
self.data = np.zeros((self.ny, self.nx), dtype=np.int32)
|
|
395
|
+
for j in range(np.shape(x)[0]):
|
|
396
|
+
self.data += x[j, :, :] << (8 * j)
|
|
397
|
+
self.mode = "int32"
|
|
398
|
+
|
|
399
|
+
# if we're done
|
|
400
|
+
if self.mode == mode:
|
|
401
|
+
return
|
|
402
|
+
|
|
403
|
+
# if we still need to convert, we are starting from int32
|
|
404
|
+
|
|
405
|
+
# need to convert int32->float32
|
|
406
|
+
if mode == "float32":
|
|
407
|
+
# note transformations are in the opposite order to float32->int32
|
|
408
|
+
if self.softbias > 0:
|
|
409
|
+
self.data = (2**self.bitkeep - self.softbias + self.data) % 2**self.bitkeep
|
|
410
|
+
elif self.softbias == -1:
|
|
411
|
+
self.data = smallnum_rev(self.data, self.bitkeep)
|
|
412
|
+
if self.diff:
|
|
413
|
+
self.data = diff_rev(self.data, self.bitkeep)
|
|
414
|
+
y = (0.5 + self.data) / 2**self.bitkeep
|
|
415
|
+
self.data = (self.vmin + (self.vmax - self.vmin) * y ** (1 / self.alpha)).astype(np.float32)
|
|
416
|
+
if self.overflow is not None:
|
|
417
|
+
posy = np.array(self.overflow.data["y"])
|
|
418
|
+
posx = np.array(self.overflow.data["x"])
|
|
419
|
+
self.data[posy, posx] = self.overflow.data["value"]
|
|
420
|
+
self.mode = "float32"
|
|
421
|
+
|
|
422
|
+
# need to convert int32->uint8
|
|
423
|
+
if mode == "uint8":
|
|
424
|
+
# make the first axis however big it needs to be
|
|
425
|
+
newarray = np.zeros(((self.bitkeep + 7) // 8, self.ny, self.nx), dtype=np.uint8)
|
|
426
|
+
newarray[0, :, :] = self.data % 256
|
|
427
|
+
if self.bitkeep > 8:
|
|
428
|
+
self.data >>= 8
|
|
429
|
+
newarray[1, :, :] = self.data % 256
|
|
430
|
+
if self.bitkeep > 16:
|
|
431
|
+
self.data >>= 8
|
|
432
|
+
newarray[2, :, :] = self.data % 256
|
|
433
|
+
if self.reorder:
|
|
434
|
+
self.data = lsbf_fwd(newarray)
|
|
435
|
+
else:
|
|
436
|
+
self.data = newarray
|
|
437
|
+
self.mode = "uint8"
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
# stand-alone functions
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
def i24compress(im, scheme, pars):
|
|
444
|
+
"""
|
|
445
|
+
Compresses an image.
|
|
446
|
+
|
|
447
|
+
Parameters
|
|
448
|
+
----------
|
|
449
|
+
im : np.array of uint8
|
|
450
|
+
2D or 3D image.
|
|
451
|
+
scheme : str
|
|
452
|
+
Compression scheme (right now supports 'I24A', 'I24B').
|
|
453
|
+
pars : dict
|
|
454
|
+
Parameters to pass to compression algorithm.
|
|
455
|
+
|
|
456
|
+
Returns
|
|
457
|
+
-------
|
|
458
|
+
data : np.array
|
|
459
|
+
The compressed data cube.
|
|
460
|
+
overflow : astropy.io.fits.BinTableHDU
|
|
461
|
+
The table of values that overflowed the quantization range.
|
|
462
|
+
|
|
463
|
+
See Also
|
|
464
|
+
--------
|
|
465
|
+
pyimcom.compress.i24.I24Cube : Compression class; see for possible keys in `pars`.
|
|
466
|
+
|
|
467
|
+
"""
|
|
468
|
+
|
|
469
|
+
if scheme not in i24_recognized_schemes:
|
|
470
|
+
return im, None # unrecognized scheme
|
|
471
|
+
|
|
472
|
+
cube = I24Cube(im, pars)
|
|
473
|
+
if scheme == "I24A":
|
|
474
|
+
cube.to_mode("int32")
|
|
475
|
+
elif scheme == "I24B":
|
|
476
|
+
cube.to_mode("uint8")
|
|
477
|
+
|
|
478
|
+
return cube.data, cube.overflow
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
def i24decompress(im, scheme, pars, overflow=None):
|
|
482
|
+
"""
|
|
483
|
+
Decompresses an image.
|
|
484
|
+
|
|
485
|
+
Parameters
|
|
486
|
+
----------
|
|
487
|
+
im : np.array of uint8
|
|
488
|
+
2D or 3D image.
|
|
489
|
+
scheme : str
|
|
490
|
+
Compression scheme (right now supports 'I24A', 'I24B').
|
|
491
|
+
pars : dict
|
|
492
|
+
Parameters to pass to compression algorithm.
|
|
493
|
+
overflow: astropy.io.fits.BinTableHDU or None, optional
|
|
494
|
+
Overflow table (y,x,value). Needed if a compressed image is given as input.
|
|
495
|
+
|
|
496
|
+
Returns
|
|
497
|
+
-------
|
|
498
|
+
data : np.array
|
|
499
|
+
The de-compressed data cube.
|
|
500
|
+
|
|
501
|
+
See Also
|
|
502
|
+
--------
|
|
503
|
+
pyimcom.compress.i24.I24Cube : Compression class; see for possible keys in `pars`.
|
|
504
|
+
|
|
505
|
+
"""
|
|
506
|
+
|
|
507
|
+
if scheme not in i24_recognized_schemes:
|
|
508
|
+
return im # unrecognized scheme
|
|
509
|
+
|
|
510
|
+
cube = I24Cube(im, pars, overflow=overflow)
|
|
511
|
+
if scheme == "I24A" or scheme == "I24B":
|
|
512
|
+
cube.to_mode("float32")
|
|
513
|
+
|
|
514
|
+
return cube.data
|