/
FITSIO.jl
226 lines (196 loc) · 6.42 KB
/
FITSIO.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
module FITSIO
export FITS,
HDU,
ImageHDU,
TableHDU,
ASCIITableHDU,
FITSHeader,
read_key,
write_key,
read_header,
get_comment,
set_comment!,
copy_section,
default_header
import Base: getindex,
setindex!,
length,
show,
read,
read!,
write,
close,
ndims,
size,
getkey,
haskey,
keys,
values
# Deal with compatibility issues.
using Printf
import Base: iterate, lastindex
# Libcfitsio submodule
## Have to manually import while deprecating `libcfitsio_version`.
## After removing that, can return to using CFITSIO
import CFITSIO: FITSFile,
FITSMemoryHandle,
fits_open_file,
fits_create_file,
fits_assert_open,
fits_create_img,
fits_close_file,
fits_write_pix,
fits_get_num_hdus,
fits_movabs_hdu,
fits_get_img_size,
fits_get_img_type,
fits_get_img_equivtype,
type_from_bitpix,
fits_read_pix,
fits_read_subset,
fits_copy_image_section,
fits_file_name,
fits_get_img_dim,
fits_read_tdim,
fits_write_tdim,
fits_read_col,
fits_write_col,
fits_get_num_cols,
fits_get_num_rows,
fits_get_colnum,
fits_get_eqcoltype,
fits_read_descript,
fits_update_key,
fits_write_comment,
fits_write_history,
fits_get_hdrspace,
fits_hdr2str,
fits_read_keyword,
fits_read_keyn,
fits_open_memfile
# There are a few direct `ccall`s to libcfitsio in this module. For this, we
# need a few non-exported things from Libcfitsio: the shared library handle,
# and a helper function for raising errors.
import CFITSIO: libcfitsio,
fits_assert_ok,
fits_assert_isascii
import CFITSIO
@deprecate libcfitsio_version CFITSIO.libcfitsio_version
## DEPRECATED
module Libcfitsio
using Reexport
@reexport using CFITSIO
end
# HDU Types
abstract type HDU end
mutable struct ImageHDU <: HDU
fitsfile::FITSFile
ext::Int
end
mutable struct TableHDU <: HDU
fitsfile::FITSFile
ext::Int
end
mutable struct ASCIITableHDU <: HDU
fitsfile::FITSFile
ext::Int
end
# FITS
#
# The FITS type represents a FITS file. It holds a reference to a
# FITSFile object (basically the low-level CFITSIO pointer). It also
# holds a reference to all of the previously accessed HDU
# objects. This is so that only a single HDU object is created for
# each extension in the file. It also allows a FITS object to tell
# previously created HDUs about events that happen to the file, such
# as deleting extensions. This could be done by, e.g., setting ext=-1
# in the HDU object.
"""
FITS(filename::String, mode::String="r")
Open or create a FITS file. `mode` can be one of `"r"` (read-only),
`"r+"` (read-write) or `"w"` (write). In "write" mode, any existing
file of the same name is overwritten.
A `FITS` object is a collection of "Header-Data Units" (HDUs) and
supports the following operations:
* `f[i]`: Return the `i`-th HDU.
* `f[name]` or `f[name, ver]`: Return the HDU containing the given the
given EXTNAME (or HDUNAME) keyword (a String), and optionally the
given EXTVER (or HDUVER) number (an Integer).
* Iteration:
```
for hdu in f
...
end
```
"""
mutable struct FITS
fitsfile::FITSFile
filename::AbstractString
mode::AbstractString
hdus::Dict{Int, HDU}
# Hold on to memory if backed by a julia buffer
memhandle::FITSMemoryHandle
hidden::Any
function FITS(filename::AbstractString, mode::AbstractString="r")
f = (mode == "r" ? fits_open_file(filename, 0) :
mode == "r+" && isfile(filename) ? fits_open_file(filename, 1) :
mode == "r+" ? fits_create_file(filename) :
mode == "w" ? fits_create_file("!"*filename) :
error("invalid open mode: $mode"))
new(f, filename, mode, Dict{Int, HDU}(), FITSMemoryHandle(), nothing)
end
function FITS(data::Vector{UInt8}, mode::AbstractString="r", filename = "")
@assert mode == "r"
f, handle = fits_open_memfile(data, 0)
new(f, filename, mode, Dict{Int, HDU}(), handle, data)
end
end
"""
FITS(f::Function, args...)
Apply the function `f` to the result of `FITS(args...)` and close the
resulting file descriptor upon completion.
"""
function FITS(f::Function, args...)
io = FITS(args...)
try
f(io)
finally
close(io)
end
end
"""
FITSHeader(keys::Vector{String}, values::Vector, comments::Vector{String})
An in-memory representation of the header of an HDU. It stores the
(key, value, comment) information for each 80-character "card" in a header.
Note that this structure is not linked to a FITS file in any way; it
is just a convenient structure for storing the header contents after
reading from a file. (This is similar to how an `Array` returned by
`read(f[1])` is not linked to the FITS file `f`.) Manipulating a
`FITSHeader` will therefore have no immediate impact on any file, even
if it was created by `read_header(::HDU)`. You can, however, write a
`FITSHeader` to a file using the `write(::FITS, ...)` methods that
append a new HDU to a file.
"""
mutable struct FITSHeader
keys::Vector{String}
values::Vector{Any}
comments::Vector{String}
map::Dict{String, Int}
function FITSHeader(keys::Vector{String}, values::Vector,
comments::Vector{String})
if ((length(keys) != length(values)) ||
(length(keys) != length(comments)))
error("keys, values, comments must be same length")
end
map = Dict{String, Int}()
for i in 1:length(keys)
map[keys[i]] = i
end
new(keys, Vector{Any}(values), comments, map)
end
end
include("fits.jl") # FITS methods
include("header.jl") # FITSHeader methods
include("image.jl") # ImageHDU methods
include("table.jl") # TableHDU & ASCIITableHDU methods
end # module