Skip to content

Commit 50ccca1

Browse files
authored
Merge pull request #58 from JuliaAstro/from_header
Convert from `FITSHeader` to `WCSTransform`
2 parents a24cde1 + 8cfb836 commit 50ccca1

File tree

8 files changed

+196
-16
lines changed

8 files changed

+196
-16
lines changed

Project.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,14 @@ projects = ["test", "docs"]
99
ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
1010
WCS_jll = "550c8279-ae0e-5d1b-948f-937f2608a23e"
1111

12+
[weakdeps]
13+
FITSIO = "525bcba6-941b-5504-bd06-fd0dc1a4d2eb"
14+
15+
[extensions]
16+
FITSIOExt = "FITSIO"
17+
1218
[compat]
1319
ConstructionBase = "1"
20+
FITSIO = "0.17.5"
1421
WCS_jll = "7"
1522
julia = "1.10"

docs/Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
[deps]
22
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
3+
DocumenterInterLinks = "d12716ef-a0f6-4df4-a9f1-a5a34e75c656"
4+
FITSIO = "525bcba6-941b-5504-bd06-fd0dc1a4d2eb"
35
WCS = "15f3aee2-9e10-537f-b834-a6fb8bdb944d"
46

57
[compat]

docs/make.jl

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
using WCS
2-
using Documenter
2+
using Documenter, DocumenterInterLinks
33
using Documenter.Remotes: GitHub
44

5+
using FITSIO: FITSIO, read_header # Precompile package extensions
6+
57
DocMeta.setdocmeta!(WCS, :DocTestSetup, :(using WCS); recursive = true)
68

9+
links = InterLinks(
10+
"FITSIO" => "https://juliaastro.org/FITSIO/stable/",
11+
)
12+
713
makedocs(;
8-
modules = [WCS],
14+
modules = [WCS, Base.get_extension(WCS, :FITSIOExt)],
915
authors = "JuliaAstro contributors",
1016
repo = GitHub("JuliaAstro/WCS.jl"),
1117
sitename = "WCS.jl",
@@ -15,7 +21,8 @@ makedocs(;
1521
),
1622
pages = [
1723
"Home" => "index.md",
18-
]
24+
],
25+
plugins = [links],
1926
)
2027

2128
# CI only: deploy docs

docs/src/index.md

Lines changed: 130 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,140 @@ julia> wcs = WCSTransform(2;
4848
WCSTransform(naxis=2, cdelt=[-0.066667, 0.066667], crval=[0.0, -90.0], crpix=[-234.75, 8.3393])
4949
```
5050

51-
We can also create one from a FITS `header` loaded into our environment if it contains the appropriate keywords:
51+
We can also create one directly from a header loaded from [FITSIO.jl](@extref) if it contains the appropriate keywords:
5252

53-
```julia-repl
54-
julia> wcs_array = WCS.from_header(header)
53+
```jldoctest wcs
54+
julia> using FITSIO: read_header
55+
56+
julia> using Downloads: download
5557
56-
julia> wcs_array[1];
58+
julia> header = (read_header ∘ download)("https://fits.gsfc.nasa.gov/nrao_data/samples/wcs/m82rad.fits");
59+
60+
julia> WCS.from_header(header; ignore_rejected = true)
61+
1-element Vector{WCSTransform}:
62+
WCSTransform(naxis=4, cdelt=[-0.0002247777738, 0.0002273333375, 5.0e7, 1.0], crval=[147.927100003, 69.9079999924, 1.49e9, 0.0], crpix=[0.0, 0.0, 0.0, 1.0])
5763
```
5864

65+
!!! details "header file"
66+
```jldoctest wcs
67+
julia> typeof(header)
68+
FITSIO.FITSHeader
69+
70+
julia> header
71+
SIMPLE = T
72+
BITPIX = 16
73+
NAXIS = 4
74+
NAXIS1 = 558
75+
NAXIS2 = 262
76+
NAXIS3 = 1
77+
NAXIS4 = 1
78+
EXTEND = T / Tables following main image
79+
BLOCKED = T / Tape may be blocked
80+
OBJECT = 'U05322 '
81+
TELESCOP= 'VLA '
82+
INSTRUME= 'VLA '
83+
OBSERVER= 'AC243 '
84+
DATE-OBS= '06/02/89'
85+
DATE-MAP= '13/09/94'
86+
BSCALE = 1.95069823037e-6 / REAL = TAPE * BSCALE + BZERO
87+
BZERO = 0.0548100471497
88+
BUNIT = 'JY/BEAM '
89+
EPOCH = 1950.0 / EPOCH OF RA DEC
90+
BLANK = -32768 / Blanked pixel tape value
91+
VELREF = 3 / >256 RADIO, 1 LSR 2 HEL 3 OBS
92+
ALTRVAL = 100000.0 / ALTENATE FREQ/VEL REF VALUE
93+
ALTRPIX = 1.0 / ALTENATE FREQ/VEL REF PIXEL
94+
YSHIFT = 1.421085472e-14 / NET SHIFT OF PHASE CENTER INY
95+
DATAMAX = 0.1187149212 / MAX PIXEL VALUE
96+
DATAMIN = -0.009094826877 / MIN PIXEL VALUE
97+
CTYPE1 = 'RA---ARC'
98+
CRVAL1 = 147.927100003
99+
CDELT1 = -0.0002247777738
100+
CRPIX1 = 301.5
101+
CROTA1 = 0.0
102+
CTYPE2 = 'DEC--ARC'
103+
CRVAL2 = 69.9079999924
104+
CDELT2 = 0.0002273333375
105+
CRPIX2 = 95.5
106+
CROTA2 = 24.26000023
107+
CTYPE3 = 'FREQ '
108+
CRVAL3 = 1.49e9
109+
CDELT3 = 5.0e7
110+
CRPIX3 = 1.0
111+
CROTA3 = 0.0
112+
CTYPE4 = 'STOKES '
113+
CRVAL4 = 1.0
114+
CDELT4 = 1.0
115+
CRPIX4 = 1.0
116+
CROTA4 = 0.0
117+
HISTORY --------------------------------------------------------------------
118+
HISTORY /Begin "HISTORY" information found in fits tape header by IMLOD
119+
HISTORY BLOCKED = T /Tape may be blocked
120+
HISTORY --------------------------------------------------------------------
121+
HISTORY /Begin "HISTORY" information found in fits tape header by IMLOD
122+
HISTORY BLOCKED = T /Tape may be blocked
123+
HISTORY AIPS IMNAME='NGC3034 ' IMCLASS='SUBIM ' IMSEQ= 1 /
124+
HISTORY AIPS USERNO= 135 /
125+
HISTORY AIPS CLEAN BMAJ= 5.0000E-04 BMIN= 5.0000E-04 BPA= 0.00
126+
HISTORY AIPS CLEAN NITER= 2000 PRODUCT=1 / NORMAL
127+
HISTORY /END FITS tape header "HISTORY" information
128+
HISTORY --------------------------------------------------------------------
129+
HISTORY IMLOD OUTNAME ='
130+
HISTORY IMLOD OUTSEQ = 0 INTAPE = 1 OUTDISK= 2
131+
HISTORY IMLOD INFILE = 'FITS2:NGC3034.A '
132+
HISTORY IMLOD RELEASE = '15JUL94'
133+
HISTORY SUBIM RELEASE ='15JUL94 ' /********* Start 25-MAR-1994 09:37:01
134+
HISTORY SUBIM INNAME='M82 in radio' INCLASS='SUBIM '
135+
HISTORY SUBIM INSEQ= 1 INDISK= 2
136+
HISTORY SUBIM INTYPE ='MA' USERID= 103
137+
HISTORY SUBIM OUTNAME='M82 in radio' OUTCLASS='SUBIM '
138+
HISTORY SUBIM OUTSEQ= 2 OUTDISK= 2
139+
HISTORY SUBIM BLC = 1, 1, 1, 1, 1, 1, 1
140+
HISTORY SUBIM TRC = 256, 256, 1, 1, 1, 1, 1
141+
HISTORY SUBIM XINC = 2 YINC = 2
142+
HISTORY SUBIM OPCODE = 'AVE '
143+
HISTORY HGEOM RELEASE ='15JUL94 ' /********* Start 25-MAR-1994 09:37:24
144+
HISTORY HGEOM INNAME='M82 in radio' INCLASS='SUBIM '
145+
HISTORY HGEOM INSEQ= 2 INDISK= 2
146+
HISTORY HGEOM IN2NAME='M82 in blue ' IN2CLASS='SUBIM '
147+
HISTORY HGEOM IN2SEQ= 1 IN2DISK= 2
148+
HISTORY HGEOM OUTNAME='M82 in radio' OUTCLASS=' '
149+
HISTORY HGEOM OUTSEQ= 1 OUTDISK= 2
150+
HISTORY HGEOM BLC = 1, 1, 1, 1, 1, 1, 1
151+
HISTORY HGEOM TRC = 128, 128, 1, 1, 1, 1, 1
152+
HISTORY HGEOM IMSIZE = 558, 263 / Output image size
153+
HISTORY HGEOM / Interpolation order used was BiCubic
154+
HISTORY HGEOM / Indeterminate pixels filled with magic values
155+
HISTORY HGEOM / 131164 Pixels blanked due to memory limits or geometry
156+
HISTORY HGEOM / 0 Pixels blanked due to input blanked pixels
157+
HISTORY AIPS IMNAME='M82 in radio' IMCLASS='HGEOM ' IMSEQ= 1 /
158+
HISTORY AIPS USERNO= 103 /
159+
HISTORY AIPS CLEAN BMAJ= 5.0000E-04 BMIN= 5.0000E-04 BPA= 0.00
160+
HISTORY AIPS CLEAN NITER= 2000 PRODUCT=1 / NORMAL
161+
HISTORY /END FITS tape header "HISTORY" information
162+
HISTORY --------------------------------------------------------------------
163+
HISTORY IMLOD OUTNAME ='
164+
HISTORY IMLOD OUTSEQ = 0 INTAPE = 1 OUTDISK= 4
165+
HISTORY IMLOD INFILE = 'FITS2:M82RADIO.FITS '
166+
HISTORY IMLOD RELEASE = '15JAN95'
167+
HISTORY SUBIM RELEASE ='15JAN95 ' /********* Start 13-SEP-1994 13:00:09
168+
HISTORY SUBIM INNAME='M82 in radio' INCLASS='HGEOM '
169+
HISTORY SUBIM INSEQ= 1 INDISK= 4
170+
HISTORY SUBIM INTYPE ='MA' USERID= 103
171+
HISTORY SUBIM OUTNAME='M82 ' OUTCLASS='Radio '
172+
HISTORY SUBIM OUTSEQ= 3 OUTDISK= 4
173+
HISTORY SUBIM BLC = 1, 1, 1, 1, 1, 1, 1
174+
HISTORY SUBIM TRC = 558, 262, 1, 1, 1, 1, 1
175+
HISTORY SUBIM XINC = 1 YINC = 1
176+
HISTORY SUBIM OPCODE = ' '
177+
ORIGIN = 'AIPSGorilla (NRAOCV IPX) 15JAN95'
178+
DATE = '13/09/94' / File written on dd/mm/yy
179+
HISTORY AIPS IMNAME='M82 ' IMCLASS='Radio ' IMSEQ= 3 /
180+
HISTORY AIPS USERNO= 103 /
181+
HISTORY AIPS CLEAN BMAJ= 5.0000E-04 BMIN= 5.0000E-04 BPA= 0.00
182+
HISTORY AIPS CLEAN NITER= 2000 PRODUCT=1 / NORMAL
183+
```
184+
59185
Now we can do conversions between pixel and world coordinates.
60186

61187
!!! note

ext/FITSIOExt.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module FITSIOExt
2+
3+
using FITSIO: FITSHeader
4+
5+
import WCS: from_header
6+
7+
"""
8+
from_header(h::FITSHeader; kwargs...)
9+
10+
Parse a [`FITSHeader`](@extref FITSIO.FITSHeader) `header` from [FITSIO.jl](@extref), returning a `Vector{WCSTransform}` giving all the transforms defined in the header. Keyword arguments are passed to [`from_header(header::String)`](@ref).
11+
"""
12+
from_header(header::FITSHeader; kwargs...) = from_header(string(header); kwargs...)
13+
14+
end # module

src/WCS.jl

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -825,16 +825,20 @@ function from_header(header::String; relax::Integer = HDR_ALL, ctrl::Integer = 0
825825
status = lock(wcs_lock) do
826826
if table
827827
colsel = convert(Ptr{Cint}, C_NULL)
828-
status = ccall((:wcsbth, libwcs), Cint,
829-
(Ptr{UInt8}, Cint, Cint, Cint, Cint, Ptr{Cint},
830-
Ref{Cint}, Ref{Cint}, Ref{Ptr{WCSTransform}}),
831-
header, nkeyrec, relax, ctrl, keysel, colsel,
832-
nreject, nwcs, wcsptr)
828+
status = redirect_stdio(; stdout = devnull, stderr = devnull) do
829+
ccall((:wcsbth, libwcs), Cint,
830+
(Ptr{UInt8}, Cint, Cint, Cint, Cint, Ptr{Cint},
831+
Ref{Cint}, Ref{Cint}, Ref{Ptr{WCSTransform}}),
832+
header, nkeyrec, relax, ctrl, keysel, colsel,
833+
nreject, nwcs, wcsptr)
834+
end
833835
else
834-
status = ccall((:wcspih, libwcs), Cint,
835-
(Ptr{UInt8}, Cint, Cint, Cint, Ref{Cint}, Ref{Cint},
836-
Ref{Ptr{WCSTransform}}),
837-
header, nkeyrec, relax, ctrl, nreject, nwcs, wcsptr)
836+
status = redirect_stdio(; stdout = devnull, stderr = devnull) do
837+
ccall((:wcspih, libwcs), Cint,
838+
(Ptr{UInt8}, Cint, Cint, Cint, Ref{Cint}, Ref{Cint},
839+
Ref{Ptr{WCSTransform}}),
840+
header, nkeyrec, relax, ctrl, nreject, nwcs, wcsptr)
841+
end
838842
end
839843
return status
840844
end

test/Project.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
[deps]
22
ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
33
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
4+
Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
5+
FITSIO = "525bcba6-941b-5504-bd06-fd0dc1a4d2eb"
46
ParallelTestRunner = "d3525ed8-44d0-4b2c-a655-542cee43accc"
57
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
68
WCS = "15f3aee2-9e10-537f-b834-a6fb8bdb944d"
79

10+
[sources]
11+
WCS = {path = ".."}
12+
813
[compat]
914
ConstructionBase = "1"

test/test_fitsio.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using WCS: WCSTransform, from_header
2+
using FITSIO: FITSHeader
3+
4+
@testset "interface" begin
5+
header = FITSHeader(
6+
["CRPIX1", "CRVAL1", "CDELT1", "CRPIX2", "CRVAL2", "CDELT2"],
7+
[500.5, 170.014, -0.00065, 500.5, 55.9909, 0.00065],
8+
["", "", "", "", "", ""]
9+
)
10+
11+
wcs = from_header(header; ignore_rejected = true)
12+
13+
@test length(wcs) == 1
14+
@test wcs[1] isa WCSTransform
15+
end

0 commit comments

Comments
 (0)