0
# Image Operations
1
2
FITS image data handling functionality providing efficient reading, writing, and manipulation of image HDUs with support for subsets, compression, various data types, and numpy-style array operations.
3
4
## Capabilities
5
6
### ImageHDU Class
7
8
Handler for FITS image extensions with support for reading, writing, compression, and array-like access patterns.
9
10
```python { .api }
11
class ImageHDU:
12
def read(self, **kwargs):
13
"""
14
Read image data.
15
16
Parameters:
17
- **kwargs: additional read options
18
19
Returns:
20
numpy array, image data
21
"""
22
23
def write(self, img, start=0):
24
"""
25
Write image data.
26
27
Parameters:
28
- img: array-like, image data to write
29
- start: int/tuple, starting position for writing subset
30
"""
31
32
def get_dims(self):
33
"""
34
Get image dimensions.
35
36
Returns:
37
tuple of int, image dimensions (NAXIS1, NAXIS2, ...)
38
"""
39
40
def reshape(self, dims):
41
"""
42
Change image dimensions on disk.
43
44
Parameters:
45
- dims: tuple of int, new dimensions
46
"""
47
48
def is_compressed(self):
49
"""
50
Check if image is tile-compressed.
51
52
Returns:
53
bool, True if tile-compressed
54
"""
55
56
def get_comptype(self):
57
"""
58
Get compression type.
59
60
Returns:
61
str, compression algorithm name
62
"""
63
64
def has_data(self):
65
"""
66
Check if HDU contains image data.
67
68
Returns:
69
bool, True if HDU has data
70
"""
71
72
def __getitem__(self, key):
73
"""
74
Access image data using numpy-style slicing.
75
76
Parameters:
77
- key: slice/tuple, numpy-style slice notation
78
79
Returns:
80
numpy array, image subset
81
"""
82
83
# Inherited from HDUBase
84
def get_info(self):
85
"""Get complete HDU information."""
86
87
def get_offsets(self):
88
"""Get byte offsets (header_start, data_start, data_end)."""
89
90
def get_extnum(self):
91
"""Get extension number."""
92
93
def get_extname(self):
94
"""Get extension name."""
95
96
def get_extver(self):
97
"""Get extension version."""
98
99
def get_exttype(self, num=False):
100
"""Get extension type."""
101
102
def read_header(self):
103
"""Read header as FITSHDR object."""
104
105
def write_key(self, name, value, comment=""):
106
"""Write single header keyword."""
107
108
def write_keys(self, records, clean=True):
109
"""Write multiple header keywords."""
110
111
def write_checksum(self):
112
"""Write DATASUM/CHECKSUM keywords."""
113
114
def verify_checksum(self):
115
"""Verify data integrity."""
116
```
117
118
### Image Writing with Compression
119
120
```python { .api }
121
def write(filename, data, compress=None, qlevel=None, qmethod=None,
122
hcomp_scale=None, **kwargs):
123
"""
124
Write image with compression options.
125
126
Parameters:
127
- filename: str, output file path
128
- data: array-like, image data
129
- compress: str, compression type ('rice', 'gzip', 'plio', 'hcompress')
130
- qlevel: float, quantization level (for lossy compression)
131
- qmethod: str, quantization method
132
- hcomp_scale: float, HCOMPRESS scale parameter
133
- **kwargs: additional options
134
"""
135
```
136
137
### Image Data Types
138
139
```python { .api }
140
# Supported numpy data types for images:
141
# - np.uint8, np.int8
142
# - np.uint16, np.int16
143
# - np.uint32, np.int32
144
# - np.uint64, np.int64
145
# - np.float32 (BITPIX = -32)
146
# - np.float64 (BITPIX = -64)
147
# - np.complex64, np.complex128
148
```
149
150
## Compression Constants
151
152
```python { .api }
153
NOCOMPRESS = 0
154
RICE_1 = 11 # Rice compression
155
GZIP_1 = 21 # GZIP compression level 1
156
GZIP_2 = 22 # GZIP compression level 2
157
PLIO_1 = 31 # PLIO compression
158
HCOMPRESS_1 = 41 # HCOMPRESS compression
159
160
# Quantization methods for lossy compression
161
NO_DITHER = -1
162
SUBTRACTIVE_DITHER_1 = 1
163
SUBTRACTIVE_DITHER_2 = 2
164
165
# Default compression parameters
166
DEFAULT_QLEVEL = 4.0
167
DEFAULT_QMETHOD = 'SUBTRACTIVE_DITHER_1'
168
DEFAULT_HCOMP_SCALE = 0.0
169
```
170
171
## Usage Examples
172
173
### Reading Images
174
175
```python
176
import fitsio
177
import numpy as np
178
179
# Read entire image
180
image = fitsio.read('image.fits')
181
print(f"Image shape: {image.shape}")
182
183
# Read specific HDU
184
image = fitsio.read('multi.fits', ext=1)
185
186
# Read with FITS object for more control
187
with fitsio.FITS('image.fits') as fits:
188
# Get image information
189
hdu = fits[0]
190
dims = hdu.get_dims()
191
is_compressed = hdu.is_compressed()
192
193
print(f"Dimensions: {dims}")
194
print(f"Compressed: {is_compressed}")
195
196
# Read entire image
197
full_image = hdu.read()
198
199
# Read image subsets using slicing
200
subset = hdu[100:200, 50:150] # 100x100 subset
201
row = hdu[500, :] # Single row
202
column = hdu[:, 300] # Single column
203
204
# Advanced slicing
205
every_other = hdu[::2, ::2] # Every other pixel
206
flipped = hdu[::-1, :] # Vertically flipped
207
```
208
209
### Writing Images
210
211
```python
212
import fitsio
213
import numpy as np
214
215
# Create sample image
216
image = np.random.random((512, 512)).astype(np.float32)
217
218
# Write uncompressed image
219
fitsio.write('output.fits', image)
220
221
# Write with compression
222
fitsio.write('compressed.fits', image, compress='rice')
223
224
# Write with compression options
225
fitsio.write('lossy.fits', image, compress='rice',
226
qlevel=8.0, qmethod='SUBTRACTIVE_DITHER_2')
227
228
# Write integer data with GZIP
229
int_image = (image * 1000).astype(np.int16)
230
fitsio.write('int_compressed.fits', int_image, compress='gzip')
231
232
# Write to specific HDU
233
with fitsio.FITS('multi.fits', 'rw', clobber=True) as fits:
234
fits.write(image, extname='IMAGE1')
235
fits.write(image * 2, extname='IMAGE2', compress='plio')
236
```
237
238
### Working with Large Images
239
240
```python
241
import fitsio
242
import numpy as np
243
244
# Create large image file
245
large_image = np.random.random((4096, 4096)).astype(np.float32)
246
fitsio.write('large.fits', large_image)
247
248
with fitsio.FITS('large.fits', 'rw') as fits:
249
hdu = fits[0]
250
251
# Read small regions without loading entire image
252
corner = hdu[0:100, 0:100]
253
center = hdu[2000:2100, 2000:2100]
254
255
# Write to subset of existing image
256
new_data = np.ones((50, 50), dtype=np.float32)
257
hdu.write(new_data, start=[1000, 1000])
258
259
# Modify image dimensions
260
hdu.reshape([2048, 8192]) # Reshape to different aspect ratio
261
```
262
263
### Image Compression Examples
264
265
```python
266
import fitsio
267
import numpy as np
268
269
# Test different compression methods
270
image = np.random.random((1024, 1024)).astype(np.float32)
271
272
# Lossless compression
273
fitsio.write('lossless_rice.fits', image, compress='rice', qlevel=None)
274
fitsio.write('lossless_gzip.fits', image, compress='gzip', qlevel=None)
275
276
# Lossy compression with quality control
277
fitsio.write('lossy_rice.fits', image, compress='rice',
278
qlevel=4.0, qmethod='SUBTRACTIVE_DITHER_1')
279
280
# HCOMPRESS for smooth images
281
smooth = np.outer(np.linspace(0, 1, 1024), np.linspace(0, 1, 1024))
282
fitsio.write('hcompress.fits', smooth, compress='hcompress',
283
hcomp_scale=2.0)
284
285
# Check compression ratios
286
import os
287
original_size = os.path.getsize('uncompressed.fits')
288
compressed_size = os.path.getsize('lossless_rice.fits')
289
ratio = original_size / compressed_size
290
print(f"Compression ratio: {ratio:.2f}")
291
```
292
293
### Data Type Handling
294
295
```python
296
import fitsio
297
import numpy as np
298
299
# Different data types
300
uint8_data = np.random.randint(0, 256, (100, 100), dtype=np.uint8)
301
int16_data = np.random.randint(-32768, 32767, (100, 100), dtype=np.int16)
302
float32_data = np.random.random((100, 100)).astype(np.float32)
303
float64_data = np.random.random((100, 100)).astype(np.float64)
304
305
# Write each type
306
fitsio.write('uint8.fits', uint8_data)
307
fitsio.write('int16.fits', int16_data)
308
fitsio.write('float32.fits', float32_data)
309
fitsio.write('float64.fits', float64_data)
310
311
# Read back and check types
312
data = fitsio.read('uint8.fits')
313
print(f"Data type: {data.dtype}") # Should be uint8
314
315
# Handle scaling (BSCALE/BZERO)
316
with fitsio.FITS('scaled.fits') as fits:
317
# Check for scaling keywords
318
header = fits[0].read_header()
319
if 'BSCALE' in header:
320
print(f"BSCALE: {header['BSCALE']}")
321
print(f"BZERO: {header.get('BZERO', 0.0)}")
322
323
# Data is automatically scaled on read
324
scaled_data = fits[0].read()
325
```
326
327
### Working with Multi-dimensional Images
328
329
```python
330
import fitsio
331
import numpy as np
332
333
# 3D data cube
334
cube = np.random.random((50, 256, 256)).astype(np.float32)
335
fitsio.write('cube.fits', cube)
336
337
with fitsio.FITS('cube.fits') as fits:
338
hdu = fits[0]
339
dims = hdu.get_dims()
340
print(f"Cube dimensions: {dims}") # (256, 256, 50) - FITS order
341
342
# Access slices
343
first_plane = hdu[:, :, 0] # First image plane
344
middle_plane = hdu[:, :, 25] # Middle plane
345
spectrum = hdu[128, 128, :] # Spectrum at center pixel
346
347
# 4D hypercube
348
hypercube = np.random.random((10, 20, 100, 100)).astype(np.float32)
349
fitsio.write('hypercube.fits', hypercube)
350
```
351
352
### Image Metadata and Information
353
354
```python
355
import fitsio
356
357
with fitsio.FITS('image.fits') as fits:
358
hdu = fits[0]
359
360
# Get complete HDU information
361
info = hdu.get_info()
362
print(f"HDU info: {info}")
363
364
# Check basic properties
365
has_data = hdu.has_data()
366
is_compressed = hdu.is_compressed()
367
comp_type = hdu.get_comptype() if is_compressed else None
368
369
# Get file offsets
370
offsets = hdu.get_offsets()
371
header_start, data_start, data_end = offsets
372
373
print(f"Header starts at byte: {header_start}")
374
print(f"Data starts at byte: {data_start}")
375
print(f"Data ends at byte: {data_end}")
376
```