|
| 1 | +module WCSExt |
| 2 | + |
| 3 | +using WCS: WCSTransform, to_header |
| 4 | +import FITSIO: FITSIO, FITSHeader |
| 5 | + |
| 6 | +""" |
| 7 | + FITSHeader(wcs::WCS.WCSTransform) |
| 8 | +
|
| 9 | +Construct a [`FITSHeader`](@ref) from a [`WCSTransform`](@extref WCS.WCSTransform) supplied by [WCS.jl](@extref). |
| 10 | +
|
| 11 | +# Examples |
| 12 | +
|
| 13 | +```jldoctest |
| 14 | +julia> using FITSIO, WCS |
| 15 | +
|
| 16 | +julia> wcs = WCSTransform(2; |
| 17 | + cdelt = [-0.066667, 0.066667], |
| 18 | + ctype = ["RA---AIR", "DEC--AIR"], |
| 19 | + crpix = [-234.75, 8.3393], |
| 20 | + crval = [0., -90], |
| 21 | + pv = [(2, 1, 45.0)], |
| 22 | + ) |
| 23 | +WCSTransform(naxis=2, cdelt=[-0.066667, 0.066667], crval=[0.0, -90.0], crpix=[-234.75, 8.3393]) |
| 24 | +
|
| 25 | +julia> FITSHeader(wcs) |
| 26 | +WCSAXES = '2 ' / Number of coordinate axes |
| 27 | +CRPIX1 = '-234.7500' / Pixel coordinate of reference point |
| 28 | +CRPIX2 = '8.3393 ' / Pixel coordinate of reference point |
| 29 | +CDELT1 = '-0.066667' / [deg] Coordinate increment at reference point |
| 30 | +CDELT2 = '0.066667' / [deg] Coordinate increment at reference point |
| 31 | +CUNIT1 = 'deg ' / Units of coordinate increment and value |
| 32 | +CUNIT2 = 'deg ' / Units of coordinate increment and value |
| 33 | +CTYPE1 = 'RA---AIR' / Right ascension, Airys zenithal projection |
| 34 | +CTYPE2 = 'DEC--AIR' / Declination, Airys zenithal projection |
| 35 | +CRVAL1 = '0.0 ' / [deg] Coordinate value at reference point |
| 36 | +CRVAL2 = '-90.0 ' / [deg] Coordinate value at reference point |
| 37 | +PV2_1 = '45.0 ' / AIR projection parameter |
| 38 | +LONPOLE = '180.0 ' / [deg] Native longitude of celestial pole |
| 39 | +LATPOLE = '-90.0 ' / [deg] Native latitude of celestial pole |
| 40 | +MJDREF = '0.0 ' / [d] MJD of fiducial time |
| 41 | +RADESYS = 'ICRS ' / Equatorial coordinate system |
| 42 | +COMMENT WCS header keyrecords produced by WCSLIB 7.7 |
| 43 | +``` |
| 44 | +""" |
| 45 | +function FITSIO.FITSHeader(wcs::WCSTransform) |
| 46 | + # Split string into 80-character card images |
| 47 | + card_images = Iterators.partition(to_header(wcs), 80) |
| 48 | + |
| 49 | + # Remove any blank lines |
| 50 | + is_empty = isempty ∘ strip |
| 51 | + card_images = Iterators.filter(card_images) do card_image |
| 52 | + !is_empty(card_image) |
| 53 | + end |
| 54 | + |
| 55 | + # Split each of those card images into their (key, value, comment) parts |
| 56 | + card_image_parts = map(card_images) do card_image |
| 57 | + card_image = replace(card_image, "'" => "") # Remove single quotes |
| 58 | + map(strip, split(card_image, ['=', '/' ])) |
| 59 | + end |
| 60 | + |
| 61 | + # Deal with the special comment case |
| 62 | + comment_card = (first ∘ pop!)(card_image_parts) |
| 63 | + comment = (strip ∘ last)(split(comment_card, "COMMENT")) |
| 64 | + push!(card_image_parts, ["COMMENT", "", comment]) |
| 65 | + |
| 66 | + # Store |
| 67 | + k, v, c = eachcol(stack(card_image_parts; dims = 1)) |
| 68 | + return FITSHeader(string.(k), string.(v), string.(c)) |
| 69 | +end |
| 70 | + |
| 71 | +end # module |
0 commit comments