diff options
Diffstat (limited to 'fitsy/head.C')
-rw-r--r-- | fitsy/head.C | 633 |
1 files changed, 633 insertions, 0 deletions
diff --git a/fitsy/head.C b/fitsy/head.C new file mode 100644 index 0000000..2a2250c --- /dev/null +++ b/fitsy/head.C @@ -0,0 +1,633 @@ +// Copyright (C) 1999-2018 +// Smithsonian Astrophysical Observatory, Cambridge, MA, USA +// For conditions of distribution and use, see copyright notice in "copyright" + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <sys/types.h> + +#ifndef __WIN32 +#include <sys/mman.h> +#include <sys/shm.h> +#endif + +#include "file.h" +#include "head.h" + +FitsHead::FitsHead(char* raw, size_t bytes, Memory mem) +{ + cards_ = raw; + mapdata_ = raw; + mapsize_ = bytes; + memory_ = mem; + ncard_ = 0; + acard_ = 0; + ccard_ = 0; + + index_ = NULL; + + valid_ = 0; + inherit_ = 0; + + hdu_ = NULL; + + char* c; + int i; + for (c = cards_, i=0; c < cards_+bytes; c+=FTY_CARDLEN, i++) { + // only compare 4 chars + if (!strncmp(c, "END ", 4)) { + ncard_ = i + 1; + acard_ = ((ncard_+FTY_CARDS-1)/FTY_CARDS) * FTY_CARDS; + valid_ = 1; + + buildIndex(); + updateHDU(); + return; + } + } +} + +FitsHead::FitsHead(char* raw, size_t bytes, char* mm, + size_t sz, Memory mem) +{ + cards_ = raw; + mapdata_ = mm; + mapsize_ = sz; + memory_ = mem; + ncard_ = 0; + acard_ = 0; + ccard_ = 0; + + index_ = NULL; + + valid_ = 0; + inherit_ = 0; + + hdu_ = NULL; + + char* c; + int i; + for (c = cards_, i=0; c < cards_+bytes; c+=FTY_CARDLEN, i++) { + // only compare 4 chars + if (!strncmp(c, "END ", 4)) { + ncard_ = i + 1; + acard_ = ((ncard_+FTY_CARDS-1)/FTY_CARDS) * FTY_CARDS; + valid_ = 1; + + buildIndex(); + updateHDU(); + return; + } + } +} + +// Create Image FitsHead + +FitsHead::FitsHead(int width, int height, int depth, int bitpix, char* xtension) +{ + cards_ = new char[FTY_BLOCK]; + memset(cards_, ' ', FTY_BLOCK); + memcpy(cards_, "END", 3); + + mapdata_ = NULL; + mapsize_ = 0; + memory_ = ALLOC; + + ncard_ = 1; + acard_ = FTY_CARDS; + ccard_ = 0; + + index_ = NULL; + + if (!xtension) + appendLogical("SIMPLE", 1, "Fits Standard"); + else + appendString("XTENSION", xtension, "Fits Standard"); + + appendInteger("BITPIX", bitpix, "Bits per pixel"); + appendInteger("NAXIS", depth>1 ? 3 : 2, "Number of axes"); + appendInteger("NAXIS1", width, "Axis Length"); + appendInteger("NAXIS2", height, "Axis Length"); + if (depth>1) + appendInteger("NAXIS3", depth, "Axis Length"); + + valid_ = 1; + inherit_ = 0; + + hdu_ = NULL; + + buildIndex(); + updateHDU(); +} + +FitsHead::FitsHead(int width, int height, int depth, int bitpix, + char* mm, size_t sz, Memory mem) +{ + cards_ = new char[FTY_BLOCK]; + memset(cards_, ' ', FTY_BLOCK); + memcpy(cards_, "END", 3); + + mapdata_ = mm; + mapsize_ = sz; + memory_ = mem; + + ncard_ = 1; + acard_ = FTY_CARDS; + ccard_ = 0; + + index_ = NULL; + + appendLogical("SIMPLE", 1, "Fits Standard"); + appendInteger("BITPIX", bitpix, "Bits per pixel"); + appendInteger("NAXIS", depth==1 ? 2 : 3, "Number of axes"); + appendInteger("NAXIS1", width, "Axis Length"); + appendInteger("NAXIS2", height, "Axis Length"); + if (depth>1) + appendInteger("NAXIS3", depth, "Axis Length"); + + valid_ = 1; + inherit_ = 0; + + hdu_ = NULL; + + buildIndex(); + updateHDU(); +} + +FitsHead::FitsHead(const FitsHead& a) +{ + cards_ = new char[a.acard_*FTY_CARDLEN]; + memmove(cards_, a.cards_, a.acard_*FTY_CARDLEN); + mapdata_ = NULL; + mapsize_ = 0; + memory_ = ALLOC; + + index_ = NULL; + acard_ = a.acard_; + ncard_ = a.ncard_; + ccard_ = a.ccard_; + + valid_ = 1; + inherit_ = 0; + + hdu_ = NULL; + + buildIndex(); + updateHDU(); +} + +FitsHead::~FitsHead() +{ + if (index_) + delete [] index_; + + if (hdu_) + delete hdu_; + + switch (memory_) { + case ALLOC: + if (cards_) + delete [] cards_; + break; + case MMAP: +#ifndef __WIN32 + if (mapdata_) + munmap((caddr_t)mapdata_, mapsize_); +#endif + break; + case SHARE: +#ifndef __WIN32 + if (mapdata_) + shmdt(mapdata_); +#endif + case EXTERNAL: + break; + } +} + +int FitsHead::isImage() +{ + // just look for SIMPLE, if present it may be of value 'F' + char* xtension = getString("XTENSION"); + char* simple = find("SIMPLE"); + int r = + (simple || (xtension && !strncmp(xtension, "IMAGE", 5))) && + naxes() > 0 && + naxis(0) > 0 && + naxis(1) > 0; + return r; +} + +int FitsHead::isTable() +{ + char* xtension = getString("XTENSION"); + int r = (xtension && (!strncmp(xtension, "TABLE", 5) || + !strncmp(xtension, "BINTABLE", 8))); + return r; +} + +int FitsHead::isAsciiTable() +{ + char* xtension = getString("XTENSION"); + int r = (xtension && (!strncmp(xtension, "TABLE", 5))); + return r; +} + +int FitsHead::isBinTable() +{ + char* xtension = getString("XTENSION"); + int r = (xtension && (!strncmp(xtension, "BINTABLE", 8))); + return r; +} + +int FitsHead::isHeap() +{ + return getInteger("PCOUNT",0) ? 1 : 0; +} + +void FitsHead::updateHDU() +{ + if (hdu_) + delete hdu_; + hdu_ = NULL; + + // just find simple, it might be present but of value 'F' + char* simple = find("SIMPLE"); + char* xtension = getString("XTENSION"); + + if (xtension) + inherit_ = getLogical("INHERIT",0); + + if (simple || (xtension && !strncmp(xtension, "IMAGE", 5))) + hdu_ = new FitsImageHDU(this); + + if (xtension && !strncmp(xtension, "TABLE", 5)) + hdu_ = new FitsAsciiTableHDU(this); + + if (xtension && !strncmp(xtension, "BINTABLE", 8)) + hdu_ = new FitsBinTableHDU(this); +} + +int FitsHead::getLogical(const char* name, int def) +{ + char* card = find(name); + if (card) { + FitsCard c(card); + return c.getLogical(); + } + else + return def; +} + +int FitsHead::getInteger(const char* name, int def) +{ + char* card = find(name); + if (card) { + FitsCard c(card); + return c.getInteger(); + } + else + return def; +} + +double FitsHead::getReal(const char* name, double def) +{ + char* card = find(name); + if (card) { + FitsCard c(card); + return c.getReal(); + } + else + return def; +} + +void FitsHead::getComplex(const char* name, double* real, double* img, + double rdef, double idef) +{ + char* card = find(name); + if (card) { + FitsCard c(card); + c.getComplex(real, img); + } + else { + *real = rdef; + *img = idef; + } +} + +char* FitsHead::getString(const char* name) +{ + char* card = find(name); + if (card) { + FitsCard c(card); + return c.getString(); + } + else + return NULL; +} + +char* FitsHead::getComment(const char* name) +{ + char* card = find(name); + if (card) { + FitsCard c(card); + return c.getComment(); + } + else + return NULL; +} + +char* FitsHead::getKeyword(const char* name) +{ + char* card = find(name); + if (card) { + FitsCard c(card); + return c.getKeyword(); + } + else + return NULL; +} + +char* FitsHead::setKey(const char* name, const char* value) +{ + char* card = find(name); + if (card) + FitsCard(card).setKey(value); + + buildIndex(); + return card; +} + +char* FitsHead::setLogical(const char* name, int value, const char* comm) +{ + char* card = find(name); + if (card) + FitsCard(card).setLogical(value, comm); + + return card; +} + +char* FitsHead::setInteger(const char* name, int value, const char* comm) +{ + char* card = find(name); + if (card) + FitsCard(card).setInteger(value, comm); + + return card; +} + +char* FitsHead::setReal(const char* name, double value, int prec, + const char* comm) +{ + char* card = find(name); + if (card) + FitsCard(card).setReal(value, prec, comm); + + return card; +} + +char* FitsHead::setComplex(const char* name, double real, double img, int prec, + const char* comm) +{ + char* card = find(name); + if (card) + FitsCard(card).setComplex(real, img, prec, comm); + + return card; +} + +char* FitsHead::setString(const char* name, const char* value, const char* comm) +{ + char* card = find(name); + if (card) + FitsCard(card).setString(value, comm); + + return card; +} + +char* FitsHead::setComment(const char* name, const char* value) +{ + char* card = find(name); + if (card) + FitsCard(card).setComment(value); + + return card; +} + +char* FitsHead::cardins(char* card, char* here) +{ + // do we need to allocate another block? + if (ncard_+1 > acard_) { + switch (memory_) { + case ALLOC: + { + char* old = cards_; + int oldsz = acard_*FTY_CARDLEN; + int sz = oldsz+FTY_BLOCK; + + acard_ = sz/FTY_CARDLEN; + cards_ = new char[sz]; + memset(cards_, ' ', sz); + memcpy(cards_, old, oldsz); + + // don't forget to redirect here if needed + if (here) { + size_t diff = here-old; + here = cards_+diff; + } + delete [] old; + } + break; + case MMAP: + case SHARE: + case EXTERNAL: + internalError("Fitsy++ head can't add card: readonly memory"); + return NULL; + } + } + + char* where = here ? here : cards_+((ncard_-1)*FTY_CARDLEN); + memmove(where+FTY_CARDLEN, where, (cards_+(ncard_*FTY_CARDLEN))-where); + memmove(where, card, FTY_CARDLEN); + ncard_++; + + buildIndex(); + + return where; +} + +char* FitsHead::carddel(const char* name) +{ + char* card = find(name); + if (card) { + char* next = card+FTY_CARDLEN; + char* last = cards_+((ncard_-1)*FTY_CARDLEN); + memmove(card, next, last-card); + memset(last,' ', FTY_CARDLEN); + } + + buildIndex(); + return card; +} + +char* FitsHead::cardclear(const char* name) +{ + char* card = find(name); + if (card) + FitsCard(card).clear(); + + buildIndex(); + return card; +} + +char* FitsHead::insertLogical(const char* name, int value, const char* comm, + const char* here) +{ + FitsCard key; + key.setLogical(name, value, comm); + return cardins(key.card(), (char*)here); +} + +char* FitsHead::insertInteger(const char* name, int value, const char* comm, + const char* here) +{ + FitsCard key; + key.setInteger(name, value, comm); + return cardins(key.card(), (char*)here); +} + +char* FitsHead::insertReal(const char* name, double value, int prec, + const char* comm, const char* here) +{ + FitsCard key; + key.setReal(name, value, prec, comm); + return cardins(key.card(), (char*)here); +} + +char* FitsHead::insertComplex(const char* name, double real, double img, + int prec, const char* comm, const char* here) +{ + FitsCard key; + key.setComplex(name, real, img, prec, comm); + return cardins(key.card(), (char*)here); +} + +char* FitsHead::insertString(const char* name, const char* value, + const char* comm, const char* here) +{ + FitsCard key; + key.setString(name, value, comm); + return cardins(key.card(), (char*)here); +} + +char* FitsHead::insertComment(const char* name, const char* value, + const char* here) +{ + FitsCard key; + key.setComment(name, value); + return cardins(key.card(), (char*)here); +} + +char* FitsHead::first() +{ + ccard_ = 0; + return (ccard_<ncard_) ? &cards_[ccard_*FTY_CARDLEN] : NULL; +} + +char* FitsHead::next() +{ + ccard_++; + return (ccard_<ncard_) ? &cards_[ccard_*FTY_CARDLEN] : NULL; +} + +char* FitsHead::find(const char* key) +{ + if (index_) + return findIndex(key); + else + return findSeq(key); +} + +char* FitsHead::findSeq(const char* key) +{ + if (key == NULL) + return NULL; + + char k[8]; + memset(k,' ',8); + int len = strlen(key); + + // convert to uppercase + int l = (len>8 ? 8 : len); + for (int i=0; i<l; i++) + k[i] = toupper(key[i]); + + for (char* card=cards_; card!=&cards_[ncard_*FTY_CARDLEN]; card+=FTY_CARDLEN) + if (!strncmp(k, card, 8)) + return card; + + return NULL; +} + +char* FitsHead::findIndex(const char* key) +{ + if (key == NULL) + return NULL; + + char k[8]; + memset(k,' ',8); + int len = strlen(key); + + // convert to uppercase + int l = (len>8 ? 8 : len); + for (int i=0; i<l; i++) + k[i] = toupper(key[i]); + + char** base = index_; + int length = ncard_; + + int lo = -1; + int hi = length; + int cut = length/2; + + while (hi-lo > 1) { + int i = strncmp(k, base[cut], 8); + if (!i) + return base[cut]; + + if (i < 0) { + hi = cut; + cut = (lo+hi)/2; + } + else { + lo = cut; + cut = (lo+hi)/2; + } + } + + if (!strncmp(k, base[cut], 8)) + return base[cut]; + + return NULL; +} + +static int compare(const void* a, const void* b) +{ + char** aa = (char**)a; + char** bb = (char**)b; + return strncmp(*aa, *bb, 8); +} + +void FitsHead::buildIndex() +{ + if (index_) + delete [] index_; + + index_ = new char*[ncard_]; + for (int i=0; i<ncard_; i++) + index_[i] = cards_ + (i*FTY_CARDLEN); + + qsort(index_, ncard_, sizeof(char**), compare); +} + |