github.com/lenartj/cfitsio@v0.0.0-20210325092924-ef692a403eb8/header.go (about) 1 package cfitsio 2 3 // #include "go-cfitsio.h" 4 // #include "go-cfitsio-utils.h" 5 import "C" 6 import ( 7 "fmt" 8 "unsafe" 9 ) 10 11 type Header struct { 12 slice []Card 13 cards map[string]int 14 htype HDUType // header type 15 bitpix int64 // character information 16 axes []int64 // dimensions of image data array 17 } 18 19 // NewHeader creates a Header from a set of Cards, HDUType, bitpix and axes. 20 func NewHeader(cards []Card, htype HDUType, bitpix int64, axes []int64) Header { 21 hdr := Header{ 22 slice: make([]Card, 0, len(cards)), 23 cards: make(map[string]int, len(cards)), 24 htype: htype, 25 bitpix: bitpix, 26 axes: make([]int64, len(axes)), 27 } 28 copy(hdr.axes, axes) 29 hdr.Append(cards...) 30 return hdr 31 } 32 33 // NewDefaultHeader creates a Header with CFITSIO default Cards, of type IMAGE_HDU and 34 // bitpix=8, no axes. 35 func NewDefaultHeader() Header { 36 return NewHeader( 37 []Card{}, 38 IMAGE_HDU, 39 8, 40 []int64{}, 41 ) 42 } 43 44 func (h *Header) AddComment(v string) { 45 panic("not implemented") 46 } 47 48 func (h *Header) AddHistory(v string) { 49 panic("not implemented") 50 } 51 52 // Append appends a set of Cards to this Header 53 func (h *Header) Append(cards ...Card) *Header { 54 h.slice = append(h.slice, cards...) 55 for i := range h.slice { 56 h.cards[h.slice[i].Name] = i 57 } 58 return h 59 } 60 61 // Clear resets the Header to the default state. 62 func (h *Header) Clear() { 63 h.slice = make([]Card, 0) 64 h.cards = make(map[string]int) 65 h.bitpix = 0 66 h.axes = make([]int64, 0) 67 } 68 69 // Get returns the Card with name n or nil if it doesn't exist. 70 func (h *Header) Get(n string) *Card { 71 idx, ok := h.cards[n] 72 if ok { 73 return &h.slice[idx] 74 } 75 return nil 76 } 77 78 // Comment returns the whole comment string for this Header. 79 func (h *Header) Comment() string { 80 card := h.Get("COMMENT") 81 if card != nil { 82 return card.Value.(string) 83 } 84 return "" 85 } 86 87 // History returns the whole history string for this Header. 88 func (h *Header) History() string { 89 card := h.Get("HISTORY") 90 if card != nil { 91 return card.Value.(string) 92 } 93 return "" 94 } 95 96 // Bitpix returns the bitpix value. 97 func (h *Header) Bitpix() int64 { 98 return h.bitpix 99 } 100 101 // Axes returns the axes for this Header. 102 func (h *Header) Axes() []int64 { 103 return h.axes 104 } 105 106 // Index returns the index of the Card with name n, or -1 if it doesn't exist 107 func (h *Header) Index(n string) int { 108 idx, ok := h.cards[n] 109 if ok { 110 return idx 111 } 112 return -1 113 } 114 115 // Keys returns the name of all the Cards of this Header. 116 func (h *Header) Keys() []string { 117 keys := make([]string, 0, len(h.slice)) 118 for i := range h.slice { 119 keys = append(keys, h.slice[i].Name) 120 } 121 return keys 122 } 123 124 // Set modifies the value and comment of a Card with name n. 125 func (h *Header) Set(n string, v interface{}, comment string) { 126 card := h.Get(n) 127 if card == nil { 128 h.Append(Card{ 129 Name: n, 130 Value: v, 131 Comment: comment, 132 }) 133 } else { 134 card.Value = v 135 card.Comment = comment 136 } 137 } 138 139 // readHeader returns the Header i from file f 140 func readHeader(f *File, i int) (Header, error) { 141 var err error 142 var hdr Header 143 144 htype, err := f.seekHDU(i, 0) 145 if err != nil { 146 return hdr, err 147 } 148 149 var bitpix int64 150 var axes []int64 151 152 switch htype { 153 case IMAGE_HDU: 154 // do not try to read BITPIX or NAXIS directly. 155 // if this is a compressed image, the relevant information will need 156 // to come from ZBITPX and ZNAXIS. 157 c_status := C.int(0) 158 c_val := C.int(0) 159 C.fits_get_img_type(f.c, &c_val, &c_status) 160 if c_status > 0 { 161 return hdr, to_err(c_status) 162 } 163 bitpix = int64(c_val) 164 165 c_val = 0 166 C.fits_get_img_dim(f.c, &c_val, &c_status) 167 if c_status > 0 { 168 return hdr, to_err(c_status) 169 } 170 naxes := int(c_val) 171 if naxes > 0 { 172 axes = make([]int64, naxes) 173 c_status := C.int(0) 174 c_axes := (*C.long)(unsafe.Pointer(&axes[0])) 175 C.fits_get_img_size(f.c, C.int(naxes), c_axes, &c_status) 176 if c_status > 0 { 177 return hdr, to_err(c_status) 178 } 179 } 180 default: 181 bitpix = 8 182 // read NAXIS keyword 183 c_status := C.int(0) 184 c_val := C.long(0) 185 c_key := C.CString("NAXIS") 186 defer C.free(unsafe.Pointer(c_key)) 187 var c_comment *C.char = nil 188 C.fits_read_key_lng(f.c, c_key, &c_val, c_comment, &c_status) 189 if c_status > 0 { 190 return hdr, to_err(c_status) 191 } 192 naxes := int(c_val) 193 if naxes > 0 { 194 axes = make([]int64, naxes) 195 for i := range axes { 196 c_status := C.int(0) 197 c_key := C.CString(fmt.Sprintf("NAXIS%d", i+1)) 198 defer C.free(unsafe.Pointer(c_key)) 199 c_axis := (*C.long)(unsafe.Pointer(&axes[i])) 200 C.fits_read_key_lng(f.c, c_key, c_axis, c_comment, &c_status) 201 if c_status > 0 { 202 return hdr, to_err(c_status) 203 } 204 } 205 } 206 } 207 208 c_status := C.int(0) 209 c_n := C.int(0) 210 c_dummy := C.int(0) 211 212 C.fits_get_hdrpos(f.c, &c_n, &c_dummy, &c_status) 213 if c_status > 0 { 214 return hdr, to_err(c_status) 215 } 216 217 hdr = Header{ 218 slice: make([]Card, 0, int(c_n)), 219 cards: make(map[string]int), 220 htype: htype, 221 bitpix: bitpix, 222 axes: axes, 223 } 224 for i := 0; i <= int(c_n); i++ { 225 // if the reading of a particular Card fails (most likely 226 // due to an undefined value) simple skip and continue to next Card 227 card, e := newCard(f, i) 228 if e != nil { 229 continue 230 } 231 hdr.Append(card) 232 } 233 return hdr, err 234 } 235 236 // EOf