summaryrefslogtreecommitdiffstats
path: root/fitsy/hist.C
diff options
context:
space:
mode:
Diffstat (limited to 'fitsy/hist.C')
-rw-r--r--fitsy/hist.C686
1 files changed, 686 insertions, 0 deletions
diff --git a/fitsy/hist.C b/fitsy/hist.C
new file mode 100644
index 0000000..afd71aa
--- /dev/null
+++ b/fitsy/hist.C
@@ -0,0 +1,686 @@
+// Copyright (C) 1999-2018
+// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
+// For conditions of distribution and use, see copyright notice in "copyright"
+
+#include <string.h>
+#include <ctype.h>
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+using namespace std;
+
+#include "hist.h"
+#include "util.h"
+
+#include "fitsy.h"
+#include "filter.h"
+
+#ifdef __CYGWIN__
+// limit size, cygwin pipe to 64K / (4 args x 4 bytes)
+#define FILTERSIZE 2048
+#else
+#define FILTERSIZE 65536
+#endif
+#define MULTWCS 27
+
+char *gerrorstring(void);
+
+static const char* reservedKeywords[] = {
+ "SIMPLE","XTENSION","ZSIMPLE","ZTENSION","ZIMAGE","ZTABLE",
+ "BITPIX","ZBITPIX",
+ "NAXIS","ZNAXIS",
+ "NAXIS.","ZNAXIS.",
+ "END",
+ "PCOUNT","ZPCOUNT",
+ "GCOUNT","ZGCOUNT",
+ "CHECKSUM","ZHECKSUM",
+ "DATASUM","ZDATASUM",
+ /* "OBJECT", */
+ "INHERIT",
+ "BSCALE",
+ "BZERO","TZERO.",
+ /* "BUNIT", */ "TUNIT.",
+ "BLANK",
+ "DATAMAX","TDMAX.","TLMAX.",
+ "DATAMIN","TDMIN.","TLMIN.",
+ "BLOCKED","ZBLOCKED",
+ "EXTENDED","ZEXTEND",
+
+ "EXTNAME","ZNAME.",
+ "EXTVER",
+ "EXTLEVEL",
+
+ "TFIELDS",
+ "TFORM.","ZFORM.",
+ "TBCOL.",
+
+ "ZCMPTYPE","ZCTYP.","ZTILELEN","ZTILE.","ZVAL.",
+ "ZMASKCMP","ZQUANTIZ","ZDITHER0","ZTHEAP",
+ "TSCAL.","TNULL.","TTYPE.","TDISP.", "TDIM.","THEAP",
+ "FZTILELN","FZALGOR","FZALG.",
+ "PTYPE.","PSCAL.","PZERO.",
+
+ "WCSAXES.","WCSAX.?",
+ /* "CTYPE.?", */ ".CTYP.",".CTY.?","TCTYP.","TCTY.?",
+ /* "CUNIT.?", */ ".CUNI.",".CUN.?","TCUNI.","TCUN.?",
+ /* "CRVAL.?", */ ".CRVL.",".CRV.?","TCRVL.","TCRV.?",
+ /* "CDELT.?", */ ".CDLT.",".CDE.?","TCDLT.","TCDE.?",
+ /* "CRPIX.?", */ ".CRPX.",".CRP.?","TCRPX.","TCRP.?",
+ /* "CROTA.", */ ".CROT.","TCROT.",
+ /* "PC._.?", */ "..PC.?","TPC._.?","TP._.?",
+ /* "CD._.?", */ "..CD.?","TCD._.?","TC._.?",
+ "PV._.?",".PV._.?",".V._.?","TPV._.?","TV._.?",
+ ".V._X?",
+ "PS._.?",".PS._.?",".S._.?","TPS._.?","TS._.?",
+ "WCSNAME?","WCSN.?","WCS.?","TWCS.?",
+ "CNAME.?",".CNA.?","TCNA.?",
+ "CRDER.?",".CRD.?","TCRD.?",
+ "CSYER.?",".CSY.?","TCSY.?",
+ "WCST.?",
+ "WCSX.?",
+ /* "LONPOLE?", */ "LONP.?",
+ /* "LATPOLE?", */ "LATP.?",
+ /* "EQUINOX?", */ "EQUI.?",
+ /* "EPOCH", */
+ /* "RADESYS", */ "REDE.?",
+ "RESTFRQ?","RFRQ.?",
+ "RESTWAV?","RWAV.?",
+ "SPECSYS?","SPEC.?",
+ "SSYSOBS?","SOBS.?",
+ "SSYSSRC?","SSRC.?",
+ "OBSGEO-X","OBSGX.",
+ "OBSGEO-Y","OBSGY.",
+ "OBSGEO-Z","OBSGZ.",
+ "VELOSYS?","VSYS.?",
+ "ZSOURCE?","ZSOU.?",
+ "VELANGL?","VANG.?",
+
+ /* "DATE",*/
+ /* "DATE-OBS", */ "DOBS.",
+ /* "MJD-OBS", */ "MJDOB.",
+ "BEPOCH",
+ "JEPOCH",
+ /* "DATE-AVE", */ "DAVG.",
+ /* "MJD-AVG", */ "MJDA.",
+ /* "DATE-BEG", */
+ /* "MJD-BEG", */
+ /* "TSTART", "TSTOP", */
+ /* "DATE-END", */
+ /* "MJD-END", */
+ "XPOSURE",
+ "TELAPSE",
+ /* "TIMESYS",*/
+ /* "MJDREF",*/
+ /* "JDREF",*/
+ /* "DATEREF",*/
+ "TREFPOS","TRPOS.",
+ "TREFDIR","TRDIR.",
+ "PLEPHEM",
+ /* "TIMEUNIT",*/
+ /* "TIMEOFFS",*/
+ /* "TIMSYER",*/
+ /* "TIMRDER",*/
+ /* "TIMEDEL",*/
+ /* "TIMEPIXR",*/
+ "CZPHS",".CZPH.",".CZP.?","TCZPH.","TCZP.?",
+ "CPERI",".CPER.",".CPR.?","TCPER.","TCPR.?"
+};
+
+FitsHist::FitsHist(FitsFile* fits, int w, int h, int d,
+ Matrix& m, Function func, Vector block)
+ : width_(w), height_(h), depth_(d)
+{
+ size_ = (size_t)width_*height_*depth_;
+
+ xcol_ = NULL;
+ ycol_ = NULL;
+ zcol_ = NULL;
+
+ fitsy_ = NULL;
+ filter_ = NULL;
+
+ valid_ = 0;
+
+ if (!initHeader(fits))
+ return;
+
+ // we need to translate by another .5 for the offset from Data to Image
+ Matrix mm = m * Translate(.5,.5);
+
+ initLTMV(mm);
+ initWCS(fits, mm, block);
+
+ initFilter(fits);
+ bin(fits, m, func, block);
+
+ if (byteswap_)
+ swap();
+
+ deleteFilter();
+ valid_ = 1;
+}
+
+FitsHist::~FitsHist()
+{
+ if (data_)
+ delete [] (float*)data_;
+}
+
+int FitsHist::initHeader(FitsFile* fits)
+{
+ FitsHead* srcHead = fits->head();
+ FitsTableHDU* srcHDU = (FitsTableHDU*)(srcHead->hdu());
+
+ // make sure we have a table with columns, X, Y
+ if (!fits->isBinTable())
+ return 0;
+
+ // make sure we have rows and cols
+ if (!srcHDU->width() || !srcHDU->rows())
+ return 0;
+
+ // get X column
+ if (fits->pBinX())
+ xcol_ = srcHDU->find(fits->pBinX());
+
+ if (!xcol_)
+ return 0;
+
+ // get Y column
+ if (fits->pBinY())
+ ycol_ = srcHDU->find(fits->pBinY());
+
+ if (!ycol_)
+ return 0;
+
+ // get Z column (if specified)
+ if (fits->pBinZ() && depth_ > 1)
+ zcol_ = srcHDU->find(fits->pBinZ());
+ else
+ zcol_ = NULL;
+
+ // create header
+ head_ = new FitsHead(width_, height_, depth_, -32);
+ if (!head_->isValid())
+ return 0;
+
+ // now screen other KEYWORDS for addition
+ char* cc = srcHead->first();
+ while (cc) {
+ if (screenKeyword(cc))
+ head_->cardins(cc, (char*)NULL);
+ cc = srcHead->next();
+ }
+
+ // MJD-OBJ deprecated
+ double rr = srcHead->getReal("MJD_OBS",0);
+ if (rr)
+ head_->appendReal("MJD-OBS", rr, 10, NULL);
+
+ // we added cards
+ head_->updateHDU();
+
+ return 1;
+}
+
+static int mstrcmp(const char* s1, const char* s2)
+{
+ const char* p1 = s1;
+ const char* p2 = s2;
+ while (*p1 != '\0') {
+ if (*p1 == '?')
+ return 0;
+
+ if (*p2=='\0')
+ return 1;
+ if (*p1 != '.') {
+ if (*p2>*p1)
+ return -1;
+ if (*p2<*p1)
+ return 1;
+ }
+ else {
+ if (*p2<'0' || *p2>'9')
+ return 1;
+ p2++;
+ if (*p2<'0' || *p2>'9')
+ p2--;
+ }
+
+ p1++;
+ p2++;
+ }
+
+ if (*p2 != '\0')
+ return -1;
+
+ return 0;
+}
+
+int FitsHist::screenKeyword(const char* cc)
+{
+ int cnt= sizeof(reservedKeywords)/sizeof(const char*);
+
+ char key[9];
+ memset(key,0,9);
+ strncpy(key,cc,8);
+ for (int ii=8; ii>=0; ii--)
+ if (key[ii]==' ')
+ key[ii] = '\0';
+
+ const char** ptr = reservedKeywords;
+ for (int ii=0; ii<cnt; ii++) {
+ if (!mstrcmp(*ptr,key))
+ return 0;
+ ptr++;
+ }
+
+ return 1;
+}
+
+void FitsHist::initFilter(FitsFile* fits)
+{
+ FitsHead* srcHead = fits->head();
+
+ const char* filtstr = fits->pFilter();
+ if (filtstr && *filtstr) {
+
+ ostringstream str;
+ str << "bincols=(" << fits->pBinX() << ',' << fits->pBinY() << ')';
+
+ if (byteswap_)
+ str << ",convert=true";
+ str << ends;
+
+ if (!(fitsy_ = ft_headinit(srcHead->cards(), srcHead->headbytes())))
+ internalError("Fitsy++ hist bad filter head");
+ else {
+ if (!(filter_ = FilterOpen((FITSHead)fitsy_, (char*)filtstr,
+ (char*)str.str().c_str()))){
+ internalError("Fitsy++ hist unable to build filter");
+ }
+ }
+ }
+}
+
+void FitsHist::deleteFilter()
+{
+ if (filter_) {
+ FilterClose((Filter)filter_);
+ filter_ = NULL;
+ }
+
+ if (fitsy_) {
+ ft_headfree((FITSHead)fitsy_,0);
+ fitsy_ = NULL;
+ }
+}
+
+void FitsHist::bin(FitsFile* fits, Matrix& m, Function func, Vector block)
+{
+ FitsHead* srcHead = fits->head();
+ FitsTableHDU* srcHDU = (FitsTableHDU*)(srcHead->hdu());
+
+ // create image space
+ float* dest = new float[size_];
+ memset(dest, 0, size_*sizeof(float));
+
+ // bin it up
+ char* ptr = (char*)fits->data();
+ int rowlen = srcHDU->width();
+ int rows = srcHDU->rows();
+
+ // third dimension
+ double zmin;
+ double zlength;
+ if (zcol_) {
+ zmin = zcol_->getMin();
+ zlength = zcol_->getMax() - zcol_->getMin();
+ }
+
+ // filter
+ int goodincr = 0;
+ int goodindex = FILTERSIZE;
+ int* good = NULL;
+ if (filter_)
+ good = new int[FILTERSIZE];
+
+ // matrix
+ register double m00 = m.matrix(0,0);
+ register double m10 = m.matrix(1,0);
+ register double m20 = m.matrix(2,0);
+ register double m01 = m.matrix(0,1);
+ register double m11 = m.matrix(1,1);
+ register double m21 = m.matrix(2,1);
+
+ for (int ii=0; ii<rows; ii++, ptr+=rowlen, goodindex++) {
+
+ // incr filter block, if needed
+ if (good && (goodindex>=FILTERSIZE)) {
+ // for memory models that support internal paging
+ // need at lease FILTERSIZE rows
+ ptr = fits->page(ptr, rowlen*FILTERSIZE);
+
+ int diff = srcHDU->rows() - (goodincr * FILTERSIZE);
+ if (FilterEvents((Filter)filter_, ptr, srcHDU->width(),
+ (diff<FILTERSIZE) ? diff : FILTERSIZE, good)) {
+ goodincr++;
+ goodindex = 0;
+ }
+ else {
+ if (good)
+ delete [] good;
+ good = NULL;
+ internalError("Fitsy++ hist filter failed");
+ }
+ }
+ else {
+ // for memory models that support internal paging
+ // all we need is just one row
+ ptr = fits->page(ptr, rowlen);
+ }
+
+ if (!good || (good && good[goodindex])) {
+ register double x = xcol_->value(ptr);
+ register double y = ycol_->value(ptr);
+
+ register double X = x*m00 + y*m10 + m20;
+ register double Y = x*m01 + y*m11 + m21;
+
+ if (X >= 0 && X < width_ && Y >= 0 && Y < height_) {
+ if (!zcol_)
+ dest[((int)Y)*width_ + (int)X]++;
+ else {
+ int zz = (int)((zcol_->value(ptr)-zmin)/zlength*depth_);
+ if (zz>=0 && zz<depth_)
+ dest[(zz*width_*height_) + ((int)Y)*width_ + (int)X]++;
+ }
+ }
+ }
+ }
+
+ // for memory models that support internal paging
+ fits->resetpage();
+
+ // Average
+ if (func==AVERAGE)
+ for (size_t kk=0; kk<size_; kk++)
+ dest[kk] /= (block[0]*block[1]);
+
+ if (good)
+ delete [] good;
+
+ data_ = dest;
+
+ dataSize_ = size_;
+ dataSkip_ = 0;
+}
+
+void FitsHist::swap()
+{
+ if (!data_)
+ return;
+
+ // we now need to byteswap back to native form
+ float* dest = (float*)data_;
+ for (size_t ii=0; ii<size_; ii++) {
+ const char* p = (char*)(dest+ii);
+ union {
+ char c[4];
+ float f;
+ } u;
+ u.c[3] = *p++;
+ u.c[2] = *p++;
+ u.c[1] = *p++;
+ u.c[0] = *p;
+ dest[ii] = u.f;
+ }
+}
+
+void FitsHist::initLTMV(Matrix& m)
+{
+ head_->appendReal("LTM1_1", m[0][0], 10, NULL);
+ head_->appendReal("LTM1_2", m[0][1], 10, NULL);
+ head_->appendReal("LTM2_1", m[1][0], 10, NULL);
+ head_->appendReal("LTM2_2", m[1][1], 10, NULL);
+ head_->appendReal("LTV1" , m[2][0], 10, NULL);
+ head_->appendReal("LTV2" , m[2][1], 10, NULL);
+}
+
+void FitsHist::mapWCSString(FitsHead* head, char* w,
+ const char* out, const char* prim)
+{
+ ostringstream istr;
+ istr << prim << xcol_->index() << w << ends;
+
+ if (head->find(istr.str().c_str())) {
+ char* str = head->getString(istr.str().c_str());
+ head_->appendString(out, str, NULL);
+ }
+}
+
+void FitsHist::mapWCSString(FitsHead* head, char* w,
+ const char* out, const char* prim, const char* alt)
+{
+ ostringstream istr1, istr2, istr3;
+ if (!w[0]) {
+ istr1 << prim << xcol_->index() << w << ends;
+ istr2 << prim << ycol_->index() << w << ends;
+ if (zcol_)
+ istr3 << prim << zcol_->index() << w << ends;
+ }
+ else {
+ istr1 << alt << xcol_->index() << w << ends;
+ istr2 << alt << ycol_->index() << w << ends;
+ if (zcol_)
+ istr3 << alt << zcol_->index() << w << ends;
+ }
+ ostringstream ostr1, ostr2, ostr3;
+ ostr1 << out << "1" << w << ends;
+ ostr2 << out << "2" << w << ends;
+ if (zcol_)
+ ostr3 << out << "3" << w << ends;
+
+ if (head->find(istr1.str().c_str())) {
+ char* cc1 = head->getString(istr1.str().c_str());
+ head_->appendString(ostr1.str().c_str(), cc1, NULL);
+ }
+ if (head->find(istr2.str().c_str())) {
+ char* cc2 = head->getString(istr2.str().c_str());
+ head_->appendString(ostr2.str().c_str(), cc2, NULL);
+ }
+ if (zcol_) {
+ if (head->find(istr3.str().c_str())) {
+ char* cc3 = head->getString(istr3.str().c_str());
+ head_->appendString(ostr3.str().c_str(), cc3, NULL);
+ }
+ }
+}
+
+void FitsHist::mapWCSReal(FitsHead* head, const char* out, const char* in)
+{
+ ostringstream istr;
+ istr << in << xcol_->index() << ends;
+
+ if (head->find(istr.str().c_str())) {
+ float cc = head->getReal(istr.str().c_str(), 0);
+ head_->appendReal(out, cc, 10, NULL);
+ }
+}
+
+void FitsHist::mapWCSReal(FitsHead* head, char* w,
+ const char* out, const char* in)
+{
+ ostringstream istr;
+ istr << in << xcol_->index() << w << ends;
+
+ if (head->find(istr.str().c_str())) {
+ float cc = head->getReal(istr.str().c_str(), 0);
+ head_->appendReal(out, cc, 10, NULL);
+ }
+}
+
+void FitsHist::mapWCSReal(FitsHead* head, char* w,
+ const char* out, const char* prim, const char* alt,
+ Matrix mm)
+{
+ ostringstream istr1, istr2, istr3;
+ if (!w[0]) {
+ istr1 << prim << xcol_->index() << w << ends;
+ istr2 << prim << ycol_->index() << w << ends;
+ if (zcol_)
+ istr3 << prim << zcol_->index() << w << ends;
+ }
+ else {
+ istr1 << alt << xcol_->index() << w << ends;
+ istr2 << alt << ycol_->index() << w << ends;
+ if (zcol_)
+ istr3 << alt << zcol_->index() << w << ends;
+ }
+ ostringstream ostr1, ostr2, ostr3;
+ ostr1 << out << "1" << w << ends;
+ ostr2 << out << "2" << w << ends;
+ if (zcol_)
+ ostr3 << out << "3" << w << ends;
+
+ if (head->find(istr1.str().c_str()) || head->find(istr2.str().c_str())) {
+ float cc1 = head->getReal(istr1.str().c_str(),0);
+ float cc2 = head->getReal(istr2.str().c_str(),0);
+ Vector cc = Vector(cc1,cc2) * mm;
+
+ head_->appendReal(ostr1.str().c_str(), cc[0], 10, NULL);
+ head_->appendReal(ostr2.str().c_str(), cc[1], 10, NULL);
+ }
+
+ if (zcol_) {
+ if (head->find(istr3.str().c_str())) {
+ float cc3 = head->getReal(istr3.str().c_str(),0);
+ head_->appendReal(ostr3.str().c_str(), cc3, 10, NULL);
+ }
+ }
+}
+
+void FitsHist::mapWCSMatrix(FitsHead* head, char* w,
+ const char* out, const char* in,
+ Vector vv)
+{
+ ostringstream istr1, istr2, istr3, istr4;
+ istr1 << in << xcol_->index() << "_" << xcol_->index() << w << ends;
+ istr2 << in << xcol_->index() << "_" << ycol_->index() << w << ends;
+ istr3 << in << ycol_->index() << "_" << xcol_->index() << w << ends;
+ istr4 << in << ycol_->index() << "_" << ycol_->index() << w << ends;
+
+ ostringstream ostr1, ostr2, ostr3, ostr4;
+ ostr1 << out << "1_1" << w << ends;
+ ostr2 << out << "1_2" << w << ends;
+ ostr3 << out << "2_1" << w << ends;
+ ostr4 << out << "2_2" << w << ends;
+
+ if (head->find(istr1.str().c_str()) ||
+ head->find(istr2.str().c_str()) ||
+ head->find(istr3.str().c_str()) ||
+ head->find(istr4.str().c_str())) {
+ float cc11 = head->getReal(istr1.str().c_str(), 0);
+ float cc12 = head->getReal(istr2.str().c_str(), 0);
+ float cc21 = head->getReal(istr3.str().c_str(), 0);
+ float cc22 = head->getReal(istr4.str().c_str(), 0);
+ Matrix cc = Matrix(cc11*vv[0], cc12*vv[0],
+ cc21*vv[1], cc22*vv[1],
+ 0, 0);
+ head_->appendReal(ostr1.str().c_str(), cc[0][0], 10, NULL);
+ head_->appendReal(ostr2.str().c_str(), cc[0][1], 10, NULL);
+ head_->appendReal(ostr3.str().c_str(), cc[1][0], 10, NULL);
+ head_->appendReal(ostr4.str().c_str(), cc[1][1], 10, NULL);
+ }
+}
+
+void FitsHist::mapWCSVector(FitsHead* head, char* w,
+ const char* out, const char* in)
+{
+ for (int ii=0; ii<=9; ii++) {
+ ostringstream istr1, istr2;
+ istr1 << in << xcol_->index() << "_" << ii << w << ends;
+ istr2 << in << ycol_->index() << "_" << ii << w << ends;
+
+ ostringstream ostr1, ostr2;
+ ostr1 << out << "1_" << ii << ends;
+ ostr2 << out << "2_" << ii << ends;
+
+ if (head->find(istr1.str().c_str()) ||
+ head->find(istr2.str().c_str())) {
+ float cc1 = head->getReal(istr1.str().c_str(), 0);
+ float cc2 = head->getReal(istr2.str().c_str(), 0);
+ head_->appendReal(ostr1.str().c_str(), cc1, 10, NULL);
+ head_->appendReal(ostr2.str().c_str(), cc2, 10, NULL);
+ }
+ }
+}
+
+void FitsHist::initWCS(FitsFile* fits, Matrix& mm, Vector block)
+{
+ FitsHead* srcHead = fits->head();
+ char w[2];
+ w[1] = '\0';
+
+ for (int i=0; i<MULTWCS; i++) {
+ if (!i)
+ w[0] = '\0';
+ else
+ w[0] = '@'+i;
+
+ mapWCSString(srcHead, w, "CTYPE", "TCTYP", "TCTY");
+ mapWCSString(srcHead, w, "CUNIT", "TCUNI", "TCUN");
+ mapWCSReal(srcHead, w, "CRVAL", "TCRVL", "TCRV", Matrix());
+ mapWCSReal(srcHead, w, "CDELT", "TCDLT", "TCDE", Scale(block));
+ mapWCSReal(srcHead, w, "CRPIX", "TCRPX", "TCRP", mm);
+ mapWCSReal(srcHead, w, "CROTA", "TCROT", "TCRO", Matrix());
+
+ mapWCSMatrix(srcHead, w, "PC", "TP", Vector(1,1));
+ mapWCSMatrix(srcHead, w, "CD", "TC", block);
+ mapWCSVector(srcHead, w, "PV", "TV");
+ mapWCSVector(srcHead, w, "PS", "TS");
+ mapWCSString(srcHead, w, "WCSNAME", "TWCS");
+
+ // alt
+ mapWCSMatrix(srcHead, w, "PC", "TPC", Vector(1,1));
+ mapWCSMatrix(srcHead, w, "CD", "TCD", block);
+ mapWCSVector(srcHead, w, "PV", "TPV");
+ mapWCSVector(srcHead, w, "PS", "TPS");
+ mapWCSString(srcHead, w, "WCSNAME", "WCS");
+
+ mapWCSReal(srcHead, w, "LONPOLE", "LONP");
+ mapWCSReal(srcHead, w, "LATPOLE", "LATP");
+ if (!head_->find("EQUINOX"))
+ mapWCSReal(srcHead, w, "EQUINOX", "EQUI");
+ if (!head_->find("MJD-OBS"))
+ mapWCSReal(srcHead, "MJD-OBS", "MJDOB");
+ if (!head_->find("RADESYS"))
+ mapWCSString(srcHead, w, "RADESYS", "RADE");
+
+ // general
+ mapWCSString(srcHead, w, "BUNIT", "TUNIT");
+ }
+}
+
+FitsHistNext::FitsHistNext(FitsFile* prev)
+{
+ primary_ = prev->primary();
+ managePrimary_ = 0;
+
+ head_ = prev->head();
+ manageHead_ = 0;
+
+ FitsImageHDU* hdu = (FitsImageHDU*)head_->hdu();
+ data_ = (char*)prev->data() + hdu->imgbytes();
+ dataSize_ = 0;
+ dataSkip_ = 0;
+
+ ext_ = prev->ext();
+ inherit_ = prev->inherit();
+ byteswap_ = prev->byteswap();
+ endian_ = prev->endian();
+ valid_ = 1;
+
+ return;
+}