FITS structure

Introduction

The Application Programming Interface (API) for CamiFITS is based on 6 FITS-object structs with dedicated object-casting procedures to enforce the FITS standard . The API elements are typically called internally by one of the Basic tools but is made available in the documentation to provide insight in the structure of CamiFITS.

FITS-objects

CamiFITS.FITSType
FITS

Object to hold a single .fits file.

The fields are

  • .filnam:: the .fits filename (:String)
  • .hdu: the collection of header-data-unit objects (::Vector{FITS_HDU}`)
source
CamiFITS.FITS_filnamType
FITS_filnam

mutable FITS object to hold the decomposed name of a .fits file.

The fields are: " .value: for p#.fits this is p#.fits (::String)

  • .name: for p#.fits this is p# (::String)
  • .prefix: for p#.fits this is p (::String)
  • .numerator: for p#.fits this is #, a serial number (e.g., '3') or a range (e.g., '3-7') (::String)
  • .extension: for p#.fits this is .fits (::String)
source
CamiFITS.FITS_HDUType
FITS_HDU

Object to hold a single "Header and Data Unit" (HDU).

The fields are

  • .hduindex:: identifier (a file may contain more than one HDU) (:Int)
  • .header: the header object (::FITS_header)
  • .dataobject: the data object (::FITS_dataobject)

NB. An empty data block (.dataobject = nothing) conforms to the standard.

source
CamiFITS.FITS_headerType
FITS_header

Object to hold the header information of a FITS_HDU.

The fields are:

  • .card: the array of cards (::Vector{FITS_card})
  • .map: Dictionary keyword => recordindex (::Dict{String, Int})
  • .size: length in bytes (::Int)
source
CamiFITS.FITS_cardType
FITS_card

Object to hold the card information of the FITS_header object.

The fields are:

  • .cardindex: identifier of the header record (::Int)
  • .record: the full record on the card (::String)
  • .keyword: name of the corresponding header record (::String)
  • .val: value of the corresponding header record (::Any)
  • .comment: comment on the corresponding header record (::String)
source
CamiFITS.FITS_dataobjectType
FITS_dataobject

Object to hold the data of the FITS_HDU of given hdutype.

The fields are:

  • .hdutype: accepted types are 'PRIMARY', 'IMAGE' and 'TABLE' (::String)
  • .data: in the from appropriate for the hdutype (::Any)
source
CamiFITS.PtrsType
Ptrs

Pointer object holding startandstop`values for reading/writingIOStream`.

The fields are:

  • .start: startofIOStream (::Int)
  • .stop: endofIOStream (::Int)
source
CamiFITS.HDU_ptrType
HDU_ptr

Object holding header and data Ptrs objects.

The fields are:

  • .header: IO pointing object (::Ptrs)
  • .data: IO data object (::Ptrs)
source
CamiFITS.FITS_pointerType
FITS_pointer

Object holding an array of HDU_ptr objects.

The fields are:

  • .nblock : block count (::Int)
  • .nhdu : hdu count (::Int)
  • .block_start: start-of-block pointers: (::Tuple(Vector{Int}))
  • .block_stop: end-of-block pointers: (::Tuple(Vector{Int}))
  • .hdu_start: start-of-hdu pointers: (::Tuple(Vector{Int}))
  • .hdu_stop: end-of-hdu pointers: (::Tuple(Vector{Int}))
  • .hdr_start: start-of-header pointers: (::Tuple(Vector{Int}))
  • .hdr_stop: end-of-header pointers: (::Tuple(Vector{Int})))
  • .data_start: start-of-data pointers: (::Tuple(Vector{Int}))
  • .data_stop: end-of-data pointers: (::Tuple(Vector{Int}))
source

FITS-object casting

The ordering of the FITS-object casting procedures is illustrated in the flow diagram below.

Image

The use of the casting procedures is recommended over direct application of the FITS-object strucs to ensure conformance to the FITS standard .

CamiFITS.cast_FITS_filnamMethod
cast_FITS_filnam(filnam::String)

Create the FITS_filnam object to decompose filnam into its name, prefix, numerator and extension.

Example:

julia> filnam = "T23.01.fits";

julia> n = cast_FITS_filnam(filnam);

julia> n.name, n.prefix, n.numerator, n.extension
("T23.01", "T23.", "01", ".fits")
source
CamiFITS.cast_FITS_dataobjectMethod
cast_FITS_dataobject(hdutype::String, data)

Create the FITS_dataobject object for given hduindex constructed from the data in accordance to the specified hdutype: PRIMARY, IMAGE, ARRAY, TABLE (ASCII table) or BINTABLE (binary table).

Example:

julia> data = [11,21,31,12,22,23,13,23,33];

julia> data = reshape(data,(3,3));

julia> d = cast_FITS_dataobject("image", data)
FITS_dataobject("'IMAGE   '", [11 12 13; 21 22 23; 31 23 33])

julia> d.data
3×3 Matrix{Int64}:
 11  12  13
 21  22  23
 31  23  33

julia> d.hdutype
"'IMAGE   '"
source
CamiFITS.cast_FITS_headerMethod
cast_FITS_header(dataobject::FITS_dataobject)

Create the FITS_header object from the dataobject. The dataobject-input mode is used by fits_create to ceate the header object as part of creating the FITS object starting from Julia data input.

Example:

julia> data = [11 21 31; 12 22 23; 13 23 33];

julia> d = cast_FITS_dataobject("image", data);

julia> h = cast_FITS_header(d);

julia> h.map
Dict{String, Int64} with 7 entries:
  "BITPIX"   => 2
  "NAXIS2"   => 5
  "XTENSION" => 1
  "NAXIS1"   => 4
  ""         => 36
  "NAXIS"    => 3
  "END"      => 6
cast_FITS_header(record::Vector{String})

Create the FITS_header object from a block of (a multiple of) 36 single-record strings (of 80 printable ASCII characters). The record-input mode is used by fits_read after reading the header records from disk (see casting diagram above).

Example:

julia> record = [rpad("KEYWORD$i",8) * "'" * rpad("$i",70) * "'" for i=1:3];

julia> blanks = [repeat(' ', 80) for i = 1:36-length(record)];

julia> append!(record, blanks);         # to conform to the FITS standard

julia> h = cast_FITS_header(record);

julia> h.map
Dict{String, Int64} with 4 entries:
  "KEYWORD3" => 3
  "KEYWORD2" => 2
  "KEYWORD1" => 144
  ""         => 36
source
CamiFITS.cast_FITS_cardMethod
cast_FITS_card(cardindex::Int, record::String)

Create the FITS_card object for record with index cardindex.

Example:

julia> record = "SIMPLE  =                    T / file does conform to FITS standard             ";

julia> card = cast_FITS_card(1, record);

julia> card.cardindex, card.keyword, card.value, card.comment
(1, "SIMPLE", true, "file does conform to FITS standard             ")
source
CamiFITS.cast_FITS_HDUMethod
cast_FITS_HDU(hduindex::Int, header::FITS_header, data::FITS_dataobject)

Create the FITS_HDU object for given hduindex, header and data.

Example:

julia> data = [11 21 31; 12 22 23; 13 23 33];

julia> d = cast_FITS_dataobject("image", data);

julia> h = cast_FITS_header(d);

julia> hdu = cast_FITS_HDU(1, h, d);

julia> hdu.dataobject.data
3×3 Matrix{Int64}:
 11  21  31
 12  22  23
 13  23  33
source
CamiFITS.cast_FITSMethod
FITS(filnam::String, hdu::Vector{FITS_HDU})

Object to hold a single .fits file.

The fields are

  • .filnam: filename of the corresponding .fits file (::String)
  • .hdu: array of FITS_HDUs (::Vector{FITS_HDU})

Example:

julia> data = [11 21 31; 12 22 23; 13 23 33];

julia> d = cast_FITS_dataobject("image", data);

julia> h = cast_FITS_header(d);

julia> hdu = cast_FITS_HDU(1, h, d);

julia> f = cast_FITS("test.fits", [hdu]);

julia> f.hdu[1].dataobject.data
3×3 Matrix{Int64}:
 11  21  31
 12  22  23
 13  23  33
source
CamiFITS.cast_FITS_pointerMethod
cast_FITS_pointer(o::IO)

Prefered method to construct a FITS_pointer object.

Example:

julia> filnam = "foo.fits";

julia> data = [0x0000043e, 0x0000040c, 0x0000041f];

julia> f = fits_create(filnam, data; protect=false);

julia> fits_extend(f, data; hdutype="'IMAGE   '");

julia> fits_extend(f, data; hdutype="'IMAGE   '");

julia> o = IORead(filnam);

julia> p = cast_FITS_pointer(o);

 julia> p.nblock, p.nhdu, p.block_start, p.block_stop, p.hdu_start, p.hdr_stop
 (6, 3, (0, 2880, 5760, 8640, 11520, 14400), (2880, 5760, 8640, 11520, 14400, 17280), (0, 5760, 11520), (2880, 8640, 14400))
    
 julia> p.hdr_start, p.hdr_stop, p.data_start, p.data_stop
 ((0, 5760, 11520), (2880, 8640, 14400), (2880, 8640, 14400), (8640, 14400, 17280))
source
CamiFITS.cast_FITS_ptrMethod
cast_FITS_ptr(o::IO [; msg=false])
cast_FITS_ptr(p::FITS_pointer)

Prefered method to construct a FITS_ptr object.

Example:

julia> filnam = "foo.fits";
julia> data = [0x0000043e, 0x0000040c, 0x0000041f];
julia> f = fits_create(filnam, data; protect=false);
julia> fits_extend(f, data; hdutype="'IMAGE   '");
julia> fits_extend(f, data; hdutype="'IMAGE   '");
julia> o = IORead(filnam);

julia> ptr = cast_FITS_ptr(o; msg=true)
             block count: 6
               hdu count: 3
 start-of-block pointers: [0, 2880, 5760, 8640, 11520, 14400]
   end-of-block pointers: [2880, 5760, 8640, 11520, 14400, 17280]
   start-of-hdu pointers: [0, 5760, 11520]
     end-of-hdu pointers: [5760, 11520, 17280]
start-of-header pointers: [0, 5760, 11520]
  end-of-header pointers: [2880, 8640, 14400]
  start-of-data pointers: [2880, 8640, 14400]
    end-of-data pointers: [8640, 14400, 17280]

FITS_ptr(HDU_ptr[HDU_ptr(Ptrs(0, 2880), Ptrs(2880, 8640)), HDU_ptr(Ptrs(5760, 8640), Ptrs(8640, 14400)), HDU_ptr(Ptrs(11520, 14400), Ptrs(14400, 17280))])

julia> p.hdu[2].header.start, p.hdu[2].data.start
(5760, 8640)
source

FITS methods

CamiFITS.fits_pointerMethod
fits_pointer(filnam::String)
fits_pointer(f::FITS)

FITS_pointer object of the file filnam or its FITS object f.

Examples:

julia> filnam = "foo.fits";

julia> f = fits_create(filnam, data; protect=false);

julia> fits_extend(f; hdutype="'IMAGE   '");

julia> fits_extend(filnam, data; hdutype="'IMAGE   '");

julia> p = fits_pointer(f);

julia> p.nblock
5
source
CamiFITS.fits_pointersMethod
fits_pointers(filnam::String)
fits_pointers(f::FITS)

summary of the pointers internally used by CamiFITS

Examples:

julia> filnam = "foo.fits";

julia> data = [0x0000043e, 0x0000040c, 0x0000041f];

julia> f = fits_create(filnam, data; protect=false);

julia> fits_extend(f);

julia> fits_extend(filnam, data; hdutype="'IMAGE   '");

julia> foreach(println, fits_pointers(filnam))
             block count: 5
               hdu count: 3
 start-of-block pointers: (0, 2880, 5760, 8640, 11520)
   end-of-block pointers: (2880, 5760, 8640, 11520, 14400)
   start-of-hdu pointers: (0, 5760, 8640)
     end-of-hdu pointers: (2880, 8640, 11520)
start-of-header pointers: (0, 5760, 8640)
  end-of-header pointers: (2880, 8640, 11520)
  start-of-data pointers: (2880, 8640, 11520)
    end-of-data pointers: (5760, 8640, 14400)
source
CamiFITS.fits_zero_offsetMethod
fits_zero_offset(T::Type)

Zero offset a as used in linear scaling equation

f(x) = a + b x,

where b is the scaling factor.

The default value is a = 0.0 for Real numeric types. For non-real types a = nothing.

Example:

julia> T = Type[Any, Bool, Int8, UInt8, Int16, UInt16, Int32, UInt32,
                  Int64, UInt64, Float16, Float32, Float64];

julia> o = (0.0, 0.0, -128, 0.0, 0.0, 32768,
                   0.0, 2147483648, 0.0, 9223372036854775808, 0.0, 0.0, 0.0);

julia> sum([fits_zero_offset(T[i]) == o[i] for i ∈ eachindex(T)]) == 13
true
source
CamiFITS.fits_apply_zero_offsetMethod
fits_apply_zero_offset(data)

Shift the UInt range of values onto the Int range by substracting from the data the appropriate integer offset value as specified by the BZERO keyword.

NB. Since the FITS format does not support a native unsigned integer data type (except UInt8), unsigned values of the types UInt16, UInt32 and UInt64, are stored as native signed integers of the types Int16, Int32 and Int64, respectively, after substracting the appropriate integer offset specified by the (positive) BZERO keyword value. For the byte data type (UInt8), the converse technique can be used to store signed byte values (Int8) as native unsigned values (UInt) after subtracting the (negative) BZERO offset value.

This method is included and used in storing of data to ensure backward compatibility with software not supporting native values of the types Int8, UInt16, UInt32 and UInt64.

Example:

julia> fits_apply_zero_offset(UInt32[0])
1-element Vector{Int32}:
 -2147483648

julia> fits_apply_zero_offset(Int8[0])
1-element Vector{UInt8}:
 0x80

julia> Int(0x80)
128
source
CamiFITS.fits_remove_zero_offsetMethod
fits_remove_zero_offset(data)

Shift the Int range of values onto the UInt range by adding to the data the appropriate integer offset value as specified by the BZERO keyword.

NB. Since the FITS format does not support a native unsigned integer data type (except UInt8), unsigned values of the types UInt16, UInt32 and UInt64, are recovered from stored native signed integers of the types Int16, Int32 and Int64, respectively, by adding the appropriate integer offset specified by the (positive) BZERO keyword value. For the byte data type (UInt8), the converse technique can be used to recover the signed byte values (Int8) from the stored native unsigned values (UInt) by adding the (negative) BZERO offset value.

This method is included and used in reading stored data to ensure backward compatibility with software not supporting native values of the types Int8, UInt16, UInt32 and UInt64.

Example:

julia> fits_remove_zero_offset(Int32[-2147483648])
1-element Vector{UInt32}:
 0x00000000

julia> Int(0x00000000)
0

julia> fits_remove_zero_offset(UInt8[128])
1-element Vector{Int8}:
 0
source

Fortran objects

CamiFITS.FORTRAN_formatType
FORTRAN_format

Object to hold a FORTRAN format specifier decomposed in its fields.

Accepted datatype specifiers are: Aw, Iw, Fw.d, Ew.d, Dw.d

Accepted output formating specifiers are: Aw, Iw.m, Bw.m, Ow.m, Zw.m, Fw.d, Ew.dEe, ENw.d, ESw.d, Gw.dEe, Dw.dEe. Notation: w - width, m (optional) - minimum number of digits, d - number of digits to right of decimal, e - number of digits in exponent N/S (optional) indicates engineering/scientific formating of the E type.

The fields are:

  • .datatype: primary FORTRAN datatype (::String)
  • .char: primary FORTRAN datatype character (::Char)
  • .EngSci: secundary datatype character - N for engineering/ S for scientific (::Union{Char,Nothing})
  • .width: width of numeric field (::Int)
  • .nmin: minimum number of digits displayed (::Int)
  • .ndec: number of digits to right of decimal (::Int)
  • .nexp: number of digits in exponent (::Int)
source

Fortran-object casting

CamiFITS.cast_FORTRAN_formatMethod
cast_FORTRAN_format(format::String)

Decompose the format specifier format into its fields and cast this into the FORTRAN_format object. Allowed format specifiers are of the types: Aw, Iw.m, Bw.m, Ow.m, Zw.m, Fw.d, Ew.dEe, ENw.d, ESw.d, Gw.dEe, Dw.dEe, with: w - width, m(optional) - minimum number of digits, d - number of digits to right of decimal, e - number of digits in exponent; N/S (optional) indicates engineering/scientific formating of the E type.

Examples:

julia> cast_FORTRAN_format("I10")
FORTRAN_format("Iw", 'I', nothing, 10, 0, 0, 0)

julia> cast_FORTRAN_format("I10.12")
FORTRAN_format("Iw.m", 'I', nothing, 10, 12, 0, 0)

julia> F = cast_FORTRAN_format("E10.5E3")
FORTRAN_format("Ew.dEe", 'E', nothing, 10, 0, 5, 3)

julia> F.Type, F.TypeChar, F.EngSci, F.width, F.nmin, F.ndec, F.nexp
("Ew.dEe", 'E', nothing, 10, 0, 5, 3)  
source
CamiFITS.FORTRAN_eltype_charMethod
FORTRAN_eltype_char(T::Type)

FORTRAN datatype description character for julia type T:

Bool => 'L', UInt8 => 'B', Int16 => 'I', UInt16 => 'I', Int32 => 'J', UInt32 => 'J', Int64 => 'K', UInt64 => 'K', Float32 => 'E', Float64 => 'D', ComplexF32 => 'C', ComplexF64 => 'M'

The character '-' is returned for non-primitive FORTRAN datatypes and for primitive datatypes not included in the FITS standard.

Examples:

julia> T = Type[Bool, Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64];

julia> print([FORTRAN_eltype_char(T[i]) for i ∈ eachindex(T)])
Int8: datatype not part of the FITS standard
['L', '-', 'B', 'I', 'I', 'J', 'J', 'K', 'K']

julia> T = [Float16, Float32, Float64, ComplexF32, ComplexF64];

julia> print([FORTRAN_eltype_char(T[i]) for i ∈ eachindex(T)])
Float16: datatype not part of the FITS standard
['-', 'E', 'D', 'C', 'M']

julia> T = [String, Vector{Char}, FITS];

julia> print([FORTRAN_eltype_char(T[i]) for i ∈ eachindex(T)])
Vector{Char}: not a FORTRAN datatype
FITS: not a FORTRAN datatype
['A', 'A', '-', '-']
source

Plotting

CamiFITS.step125Method
step125(x)

Step used for deviding the number x in steps according to 1-2-5 scheme

Examples:

step125.([5,10,21.3,50,100.1])
5-element Vector{Int64}:
  1
  2
  5
 10
 20
source
CamiFITS.select125Method
select125(x)

Select elements of the collection x by index according to 1-2-5 scheme

Examples:

x = [1,2,4,6,8,10,13,16,18,20,40,60,80,100]
select125(x)
 [2, 6, 10, 16, 20, 60, 100]

x = string.(x)
select125(x)
 ["2", "6", "10", "16", "20", "60", "100"]

x = 1:100
select125(x)
 [20, 40, 60, 80, 100]
source
CamiFITS.stepsMethod
steps(x)

Heatmap range transformation for steplength specification vector x

Examples:

x = [4,2,6]
steps(x)
 [0, 4, 6, 12]
source
CamiFITS.stepcentersMethod
stepcenters(x)

Stepcenter positions for steplength specification vector x

Examples:

x = [4,2,6]
stepcenters(x)
 [2.0, 5.0, 9.0]
source
CamiFITS.stepedgesMethod
stepedges(x)

Stepedges for steplength specification vector x

Examples:

x = [4,2,6]
stepedges(x)
 [0, 4, 6, 12]
source
CamiFITS.edgesFunction
edges(px [, Δx[, x0]])

Heatmap range transformation from pixel coordinates to physical coordinates, with pixelsize Δx and offset x0, both in physical units.

Examples:

px = 1:5
Δx = 2.5
x0 = 2.5
edges(px)
 [0.5, 1.5, 2.5, 3.5, 4.5]

edges(px, Δx)
 [1.25, 3.75, 6.25, 8.75, 11.25]

edges(px, Δx, x0)
 [-1.25, 1.25, 3.75, 6.25, 8.75]
source