github.com/astrogo/cfitsio@v0.1.0/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