summaryrefslogtreecommitdiffstats
path: root/tksao/frame/context.C
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2016-10-27 18:59:29 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2016-10-27 18:59:29 (GMT)
commitd4d595fa7fb12903db9227d33d48b2b00120dbd1 (patch)
tree7d18365de0d6d1b29399b6a17c7eb01c2eb3ed49 /tksao/frame/context.C
parent949f96e29bfe0bd8710d775ce220e597064e2589 (diff)
downloadblt-d4d595fa7fb12903db9227d33d48b2b00120dbd1.zip
blt-d4d595fa7fb12903db9227d33d48b2b00120dbd1.tar.gz
blt-d4d595fa7fb12903db9227d33d48b2b00120dbd1.tar.bz2
Initial commit
Diffstat (limited to 'tksao/frame/context.C')
-rw-r--r--tksao/frame/context.C3178
1 files changed, 3178 insertions, 0 deletions
diff --git a/tksao/frame/context.C b/tksao/frame/context.C
new file mode 100644
index 0000000..b21ca09
--- /dev/null
+++ b/tksao/frame/context.C
@@ -0,0 +1,3178 @@
+// Copyright (C) 1999-2016
+// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
+// For conditions of distribution and use, see copyright notice in "copyright"
+
+#include "context.h"
+#include "fitsimage.h"
+#include "fvcontour.h"
+
+#include "alloc.h"
+#include "allocgz.h"
+#include "channel.h"
+#include "colorscale.h"
+#include "mmap.h"
+#include "mmapincr.h"
+#include "share.h"
+#include "sshare.h"
+#include "socket.h"
+#include "socketgz.h"
+#include "var.h"
+
+#include "head.h"
+
+extern "C" {
+#include "tkbltVector.h"
+}
+
+// Contour Parser Stuff
+#undef yyFlexLexer
+#define yyFlexLexer ctFlexLexer
+#include <FlexLexer.h>
+
+void* ctlval;
+ctFlexLexer* ctlexx;
+extern int ctparse(Base*, ctFlexLexer*);
+
+int ctlex(void* vval, ctFlexLexer* ll)
+{
+ ctlval = vval;
+ ctlexx = ll;
+ return ll ? ll->yylex() : 0;
+}
+
+void cterror(Base* ct, ctFlexLexer* ll, const char* m)
+{
+ ct->error(m);
+ const char* cmd = ll ? ll->YYText() : (const char*)NULL;
+ if (cmd && cmd[0] != '\n') {
+ ct->error(": ");
+ ct->error(cmd);
+ }
+}
+
+typedef struct {
+ char* dest;
+ char** sjv;
+ int ww;
+ int hh;
+ int dd;
+ int bz;
+ int mm;
+} t_reorder_arg;
+
+ostream& operator<<(ostream& ss, const FitsZBound& bb)
+{
+ ss << bb.zmin << ' ' << bb.zmax;
+ return ss;
+}
+
+Context::Context()
+{
+ parent_ = NULL;
+
+ bfits_ =NULL;
+ fits =NULL;
+ cfits =NULL;
+
+ shareWCS_ =0;
+
+ manageAxes_ =0;
+ axesOrder_ =123;
+
+ loadInit(0, Base::NOMOSAIC, Coord::WCS);
+
+ binFunction_ = FitsHist::SUM;
+ binFactor_ = Vector(1,1);
+ binBufferSize_ = 1024;
+ binDepth_ = 1;
+
+ blockFactor_ = Vector(1,1);
+
+ doSmooth_ =0;
+ smoothFunction_ =GAUSSIAN;
+ smoothRadius_ =3;
+
+#ifndef __WIN32
+ thread_ =NULL;
+#endif
+}
+
+Context::~Context()
+{
+}
+
+#ifdef __WIN32
+
+void Context::analysis()
+{
+ if (DebugPerf)
+ cerr << "Context::analysis()" << endl;
+
+ FitsImage* ptr = fits;
+ while (ptr) {
+ FitsImage* sptr = ptr;
+ while (sptr) {
+ sptr->analysis(doSmooth_);
+ sptr = sptr->nextSlice();
+ }
+ ptr = ptr->nextMosaic();
+ }
+
+ clearHist();
+ updateClip();
+}
+
+#else
+
+void Context::analysis()
+{
+ if (DebugPerf)
+ cerr << "Context::analysis()" << endl;
+
+ if (thread_)
+ delete [] thread_;
+ thread_ = new pthread_t[parent_->nthreads_];
+ t_smooth_arg* targ = new t_smooth_arg[parent_->nthreads_];
+
+ int cnt =0;
+ FitsImage* ptr = fits;
+ while (ptr) {
+ FitsImage* sptr = ptr;
+ while (sptr) {
+ sptr->analysis(doSmooth_, &thread_[cnt], &targ[cnt]);
+
+ cnt++;
+ if (cnt == parent_->nthreads_) {
+ if (doSmooth_) {
+ for (int ii=0; ii<cnt; ii++) {
+ int rr = pthread_join(thread_[ii], NULL);
+ if (rr)
+ internalError("Unable to Join Thread");
+
+ if (targ[ii].kernel)
+ delete [] targ[ii].kernel;
+ if (targ[ii].src)
+ delete [] targ[ii].src;
+ }
+ }
+ cnt =0;
+ }
+ sptr = sptr->nextSlice();
+ }
+ ptr = ptr->nextMosaic();
+ }
+
+ if (doSmooth_) {
+ for (int ii=0; ii<cnt; ii++) {
+ int rr = pthread_join(thread_[ii], NULL);
+ if (rr)
+ internalError("Unable to Join Thread");
+
+ if (targ[ii].kernel)
+ delete [] targ[ii].kernel;
+ if (targ[ii].src)
+ delete [] targ[ii].src;
+ }
+ }
+
+ delete [] targ;
+ delete [] thread_;
+ thread_ =NULL;
+
+ clearHist();
+ updateClip();
+}
+
+#endif
+
+Matrix Context::bin(const Vector& vv)
+{
+ Matrix mm;
+ if (fits) {
+ mm = fits->bin(vv);
+ binFinish();
+ }
+ return mm;
+}
+
+Matrix Context::binCenter()
+{
+ Matrix mm;
+ if (fits) {
+ mm = fits->binCenter();
+ binFinish();
+ }
+ return mm;
+}
+
+Matrix Context::binCursor()
+{
+ Matrix mm;
+ if (fits) {
+ mm = fits->binCursor();
+ binFinish();
+ }
+ return mm;
+}
+
+void Context::binFinish()
+{
+ if (DebugPerf)
+ cerr << "Context::binFinish()" << endl;
+
+ if (!fits->isHist())
+ return;
+
+ // delete any previous slices
+ {
+ FitsImage* ptr = fits->nextSlice();
+ fits->setNextSlice(NULL);
+ while (ptr) {
+ FitsImage* tmp = ptr->nextSlice();
+ delete ptr;
+ ptr = tmp;
+ }
+ }
+
+ // finish bin
+ loadInit(1, Base::NOMOSAIC,Coord::WCS);
+ cfits = fits;
+
+ // bin data cube
+ int bd = binDepth_;
+ if (bd > 1) {
+ naxis_[2] =1; // first
+ shareWCS_ =1;
+ FitsImage* ptr = fits;
+ for (int ii=1; ii<bd; ii++) {
+ FitsImage* next = new FitsImageFitsNextHist(this, parent_->interp, fits, ptr->baseFile(), ii+1);
+ if (next->isValid()) {
+ ptr->setNextSlice(next);
+ ptr = next;
+ naxis_[2]++;
+ }
+ else {
+ delete next;
+ break;
+ }
+ }
+ }
+
+ // fix z params (in data coords)
+ iparams.set(0,naxis_[2]);
+ cparams.set(0,naxis_[2]);
+
+ resetSecMode();
+ loadFinish();
+}
+
+#ifdef __WIN32
+
+int Context::block()
+{
+ if (DebugPerf)
+ cerr << "Context::block()" << endl;
+
+ // primary
+ FitsImage* ptr = fits;
+ while (ptr) {
+ FitsImage* sptr = ptr;
+ while (sptr) {
+ sptr->block();
+ sptr = sptr->nextSlice();
+ }
+ ptr = ptr->nextMosaic();
+ }
+
+ resetSecMode();
+
+ int rr =1;
+ switch (mosaicType) {
+ case Base::IRAF:
+ case Base::WCSMOSAIC:
+ rr = processMosaicKeywords(fits);
+ break;
+ default:
+ break;
+ }
+
+ FitsMask* msk = mask.head();
+ if (msk) {
+ FitsImage* ptr = msk->mask();
+ while (ptr) {
+ FitsImage* sptr = ptr;
+ while (sptr) {
+ sptr->block();
+
+ switch (mosaicType) {
+ case Base::IRAF:
+ case Base::WCSMOSAIC:
+ rr &= processMosaicKeywords(ptr);
+ break;
+ default:
+ break;
+ }
+ sptr = sptr->nextSlice();
+ }
+ ptr = ptr->nextMosaic();
+ }
+ msk = msk->next();
+ }
+
+ return rr & blockMask();
+}
+
+int Context::blockMask()
+{
+ int rr =1;
+
+ FitsMask* msk = mask.head();
+ if (msk) {
+ FitsImage* ptr = msk->mask();
+ while (ptr) {
+ FitsImage* sptr = ptr;
+ while (sptr) {
+ sptr->block();
+
+ switch (mosaicType) {
+ case Base::IRAF:
+ case Base::WCSMOSAIC:
+ rr &= processMosaicKeywords(ptr);
+ break;
+ default:
+ break;
+ }
+ sptr = sptr->nextSlice();
+ }
+ ptr = ptr->nextMosaic();
+ }
+ msk = msk->next();
+ }
+
+ return rr;
+}
+
+#else
+
+int Context::block()
+{
+ if (DebugPerf)
+ cerr << "Context::block()" << endl;
+
+ int doBlock = (blockFactor_[0] != 1 && blockFactor_[1] != 1) ? 1 : 0;
+ int rr =1;
+
+ // primary
+ if (thread_)
+ delete [] thread_;
+ thread_ = new pthread_t[parent_->nthreads_];
+ {
+ int cnt =0;
+ FitsImage* ptr = fits;
+ while (ptr) {
+ FitsImage* sptr = ptr;
+ while (sptr) {
+ sptr->block(&thread_[cnt]);
+ cnt++;
+ if (cnt == parent_->nthreads_) {
+ if (doBlock) {
+ for (int ii=0; ii<cnt; ii++) {
+ int tt = pthread_join(thread_[ii], NULL);
+ if (tt) {
+ internalError("Unable to Join Thread");
+ rr =0;
+ }
+ }
+ }
+ cnt =0;
+ }
+ sptr = sptr->nextSlice();
+ }
+ ptr = ptr->nextMosaic();
+ }
+
+ if (doBlock) {
+ for (int ii=0; ii<cnt; ii++) {
+ int tt = pthread_join(thread_[ii], NULL);
+ if (tt) {
+ internalError("Unable to Join Thread");
+ rr =0;
+ }
+ }
+ }
+ }
+ delete [] thread_;
+ thread_ =NULL;
+
+ resetSecMode();
+
+ switch (mosaicType) {
+ case Base::IRAF:
+ case Base::WCSMOSAIC:
+ rr &= processMosaicKeywords(fits);
+ break;
+ default:
+ break;
+ }
+
+ return rr & blockMask();
+}
+
+int Context::blockMask()
+{
+ int doBlock = (blockFactor_[0] != 1 && blockFactor_[1] != 1) ? 1 : 0;
+ int rr =1;
+
+ if (thread_)
+ delete [] thread_;
+ thread_ = new pthread_t[parent_->nthreads_];
+ {
+ int cnt =0;
+
+ FitsMask* msk = mask.head();
+ if (msk) {
+ FitsImage* ptr = msk->mask();
+ while (ptr) {
+ FitsImage* sptr = ptr;
+ while (sptr) {
+ sptr->block(&thread_[cnt]);
+ cnt++;
+ if (cnt == parent_->nthreads_) {
+ if (doBlock) {
+ for (int ii=0; ii<cnt; ii++) {
+ int tt = pthread_join(thread_[ii], NULL);
+ if (tt) {
+ internalError("Unable to Join Thread");
+ rr =0;
+ }
+ }
+ }
+ cnt =0;
+ }
+ sptr = sptr->nextSlice();
+ }
+ ptr = ptr->nextMosaic();
+ }
+ msk = msk->next();
+ }
+
+ if (doBlock) {
+ for (int ii=0; ii<cnt; ii++) {
+ int tt = pthread_join(thread_[ii], NULL);
+ if (tt) {
+ internalError("Unable to Join Thread");
+ rr =0;
+ }
+ }
+ }
+ }
+ delete [] thread_;
+ thread_ =NULL;
+
+ {
+ FitsMask* msk = mask.head();
+ if (msk) {
+ FitsImage* ptr = msk->mask();
+ while (ptr) {
+ FitsImage* sptr = ptr;
+ while (sptr) {
+ switch (mosaicType) {
+ case Base::IRAF:
+ case Base::WCSMOSAIC:
+ rr &= processMosaicKeywords(ptr);
+ break;
+ default:
+ break;
+ }
+ sptr = sptr->nextSlice();
+ }
+ ptr = ptr->nextMosaic();
+ }
+ msk = msk->next();
+ }
+ }
+
+ return rr;
+}
+
+#endif
+
+void Context::bltHist(char* xname, char* yname, int num)
+{
+ if (!fits)
+ return;
+
+ switch (frScale.clipScope()) {
+ case FrScale::GLOBAL:
+ frScale.histogram(fits,num);
+ break;
+ case FrScale::LOCAL:
+ frScale.histogram(cfits,num);
+ break;
+ }
+
+ int nn = num+1;
+ double* x = frScale.histogramX();
+ double* y = frScale.histogramY();
+
+ Blt_Vector* xx;
+ Blt_GetVector(parent_->interp, xname, &xx);
+ Blt_ResetVector(xx, x, nn, nn*sizeof(double), TCL_VOLATILE);
+
+ Blt_Vector* yy;
+ Blt_GetVector(parent_->interp, yname, &yy);
+ Blt_ResetVector(yy, y, nn, nn*sizeof(double), TCL_VOLATILE);
+}
+
+int Context::calcSlice()
+{
+ int cnt =1;
+ for (int jj=3; jj<FTY_MAXAXES; jj++) {
+ int cc =1;
+ for (int ii=2; ii<jj; ii++)
+ cc *= naxis_[ii];
+ cnt += (slice_[jj]-1) * cc;
+ }
+
+ return cnt;
+}
+
+void Context::clearHist()
+{
+ frScale.clearHistogram();
+ frScale.clearHistequ();
+}
+
+void Context::contourAppendAux(ContourLevel* ct)
+{
+ auxcontours_.append(ct);
+}
+
+void Context::contourCreateFV(const char* color, int width, int dash,
+ FVContour::Method method, int numlevel,
+ int smooth,
+ FrScale::ColorScaleType colorScaleType,
+ float expo,
+ float clipMode, Vector limits,
+ const char* level)
+{
+ if (!isMosaic()) {
+ if (cfits)
+ fvcontour_.create(parent_, cfits, &frScale, color, width, dash, method, numlevel, smooth, level, colorScaleType, expo, clipMode, limits);
+ }
+ else {
+ if (fits) {
+ fvcontour_.create(parent_, fits, &frScale, color, width, dash, method, numlevel, smooth, level, colorScaleType, expo, clipMode, limits);
+
+ FitsImage* ptr = fits->nextMosaic();
+ while (ptr) {
+ fvcontour_.append(ptr);
+ ptr = ptr->nextMosaic();
+ }
+ }
+ }
+}
+
+void Context::contourDeleteFV()
+{
+ fvcontour_.lcontourlevel().deleteAll();
+}
+
+void Context::contourDeleteAux()
+{
+ auxcontours_.deleteAll();
+}
+
+void Context::contourListFV(ostream& str, Coord::CoordSystem sys,
+ Coord::SkyFrame sky)
+{
+ if (!cfits)
+ return;
+
+ contourList(str, sys, sky, fvcontour_.lcontourlevel());
+}
+
+void Context::contourListAux(ostream& str, Coord::CoordSystem sys,
+ Coord::SkyFrame sky)
+{
+ if (!cfits)
+ return;
+
+ contourList(str, sys, sky, auxcontours_);
+}
+
+void Context::contourList(ostream& str, Coord::CoordSystem sys,
+ Coord::SkyFrame sky, List<ContourLevel>& cl)
+{
+ if (cl.head()) {
+ str << "# Contour file format: DS9 version 7.5" << endl;
+
+ // just in case
+ cl.head();
+ str << "# levels=( ";
+ do
+ str << cl.current()->level() << ' ';
+ while (cl.next());
+ str << ')' << endl;
+ // reset
+ cl.head();
+
+ str << "global color=green width=1 dash=no dashlist=8 3" << endl;
+ coord.listCoordSystem(str, sys, sky, cfits);
+ str << endl;
+ do
+ cl.current()->list(str, cfits, sys, sky);
+ while (cl.next());
+ }
+}
+
+void Context::contourLoadAux(istream& str)
+{
+ if (!cfits)
+ return;
+
+ ctFlexLexer* ll = new ctFlexLexer(&str);
+ ctparse(parent_, ll);
+ delete ll;
+}
+
+void Context::contourLoadAux(istream& str, const char* color,
+ int width, int dash)
+{
+ if (!cfits)
+ return;
+
+ // remember where we are
+ int cnt = auxcontours_.count();
+
+ ctFlexLexer* ll = new ctFlexLexer(&str);
+ ctparse(parent_, ll);
+ delete ll;
+
+ // override line attributes
+ if (auxcontours_.head()) {
+ for (int ii=0; ii<cnt; ii++)
+ auxcontours_.next();
+
+ do {
+ auxcontours_.current()->setColor(color);
+ auxcontours_.current()->setLineWidth(width);
+ auxcontours_.current()->setDash(dash);
+ }
+ while (auxcontours_.next());
+ }
+}
+
+void Context::contourLoadAux(istream& str,
+ Coord::CoordSystem sys, Coord::SkyFrame sky,
+ const char* color, int width, int dash)
+{
+ if (!cfits)
+ return;
+
+ int dl[2];
+ dl[0] =8;
+ dl[1] =3;
+ ContourLevel* cl = new ContourLevel(parent_, 0, color, width, dash, dl);
+
+ Contour* cc = new Contour(cl);
+ while (!str.eof()) {
+ char buf[64];
+ str.getline(buf,64,'\n');
+ if (strlen(buf) > 0) {
+ Vector vv;
+ string x(buf);
+ istringstream sstr(x);
+
+ sstr >> vv[0] >> vv[1];
+ cc->lvertex().append(new Vertex(fits->mapToRef(vv, sys, sky)));
+ }
+ else {
+ cl->lcontour().append(cc);
+ cc = new Contour(cl);
+ }
+ }
+
+ auxcontours_.append(cl);
+}
+
+void Context::contourPS(Widget::PSColorSpace cs)
+{
+ if (!cfits)
+ return;
+
+ // render back to front
+ // aux contours
+ if (auxcontours_.tail())
+ do
+ auxcontours_.current()->ps(cs);
+ while (auxcontours_.previous());
+
+ List<ContourLevel>& cc = fvcontour_.lcontourlevel();
+ if (cc.head())
+ do
+ cc.current()->ps(cs);
+ while (cc.next());
+}
+
+void Context::contourX11(Pixmap pm, Coord::InternalSystem sys,
+ int width, int height)
+{
+ if (!cfits)
+ return;
+
+ // render back to front
+ // aux contours
+ if (auxcontours_.tail())
+ do
+ auxcontours_.current()->render(pm, sys, width, height);
+ while (auxcontours_.previous());
+
+ List<ContourLevel>& cc = fvcontour_.lcontourlevel();
+ if (cc.head())
+ do
+ cc.current()->render(pm, sys, width, height);
+ while (cc.next());
+}
+
+#ifdef MAC_OSX_TK
+void Context::contourMacOSX()
+{
+ if (!cfits)
+ return;
+
+ // render back to front
+ // aux contours
+ if (auxcontours_.tail())
+ do
+ auxcontours_.current()->macosx();
+ while (auxcontours_.previous());
+
+ List<ContourLevel>& cc = fvcontour_.lcontourlevel();
+ if (cc.head())
+ do
+ cc.current()->macosx();
+ while (cc.next());
+}
+#endif
+
+#ifdef __WIN32
+void Context::contourWin32()
+{
+ if (!cfits)
+ return;
+
+ // render back to front
+ // aux contours
+ if (auxcontours_.tail())
+ do
+ auxcontours_.current()->win32();
+ while (auxcontours_.previous());
+
+ List<ContourLevel>& cc = fvcontour_.lcontourlevel();
+ if (cc.head())
+ do
+ cc.current()->win32();
+ while (cc.next());
+}
+#endif
+
+int Context::fitsCount()
+{
+ int cnt =1;
+ for (int ii=2; ii<FTY_MAXAXES; ii++)
+ if (naxis_[ii])
+ cnt *= naxis_[ii];
+ return mosaicCount_ * cnt;
+}
+
+void Context::deleteFits(FitsImage* img)
+{
+ FitsImage* ptr = img;
+ while (ptr) {
+ FitsImage* sptr = ptr->nextSlice();
+ while (sptr) {
+ FitsImage* stmp = sptr->nextSlice();
+ delete sptr;
+ sptr = stmp;
+ }
+
+ FitsImage* tmp = ptr->nextMosaic();
+ delete ptr;
+ ptr = tmp;
+ }
+}
+
+Vector Context::getClip()
+{
+ return Vector(frScale.low(), frScale.high());
+}
+
+Vector Context::getClip(FrScale::ClipMode cm, float ac)
+{
+ if (DebugPerf)
+ cerr << "Context::getClip()" << endl;
+
+ // we already have the scale?
+ if (frScale.clipMode() == cm && frScale.autoCutPer() == ac)
+ return Vector(frScale.low(),frScale.high());
+
+ FrScale cl = frScale;
+ cl.setClipMode(cm);
+ cl.setAutoCutPer(ac);
+ updateClip(&cl);
+
+ // now reset
+ updateClip(&frScale);
+
+ return Vector(cl.low(),cl.high());
+}
+
+FitsZBound* Context::getDataParams(FrScale::SecMode which)
+{
+ switch (which) {
+ case FrScale::IMGSEC:
+ case FrScale::DATASEC:
+ return &iparams;
+ case FrScale::CROPSEC:
+ return &cparams;
+ }
+}
+
+Vector Context::getMinMax()
+{
+ return Vector(frScale.min(), frScale.max());
+}
+
+int Context::load(Base::MemType which, const char* fn,
+ FitsImage* img, Base::LayerType ll)
+{
+ if (!img || !img->isValid()) {
+ if (img)
+ delete img;
+
+ switch (ll) {
+ case Base::IMG:
+ unload();
+ return 0;
+ case Base::MASK:
+ return 0;
+ }
+ }
+
+ switch (ll) {
+ case Base::IMG:
+ bfits_ = img;
+ loadInit(1, Base::NOMOSAIC,Coord::WCS);
+ for (int ii=2; ii<FTY_MAXAXES; ii++) {
+ int nn = img->naxis(ii);
+ baxis_[ii] = nn ? nn : 1;
+ }
+
+ // fix z params (in data coords)
+ // do it here because of fits section
+ iparams.set(0,baxis_[2]);
+ cparams.set(0,baxis_[2]);
+ break;
+
+ case Base::MASK:
+ mask.append(new FitsMask(parent_, img, parent_->maskColorName, parent_->maskMark));
+ break;
+ }
+
+ if (img->isHist())
+ which = Base::HIST;
+ else if (img->isPost())
+ which = Base::POST;
+
+ if (img->nhdu() > 1)
+ shareWCS_ =1;
+
+ FitsImage* ptr = img;
+ for (int ii=1; ii<img->nhdu(); ii++) {
+ FitsImage* next = NULL;
+ switch (which) {
+ case Base::ALLOC:
+ next = new FitsImageFitsNextAlloc(this, parent_->interp, fn, ptr->fitsFile(), ii+1);
+ break;
+ case Base::ALLOCGZ:
+ next = new FitsImageFitsNextAllocGZ(this, parent_->interp, fn, ptr->fitsFile(), ii+1);
+ break;
+ case Base::CHANNEL:
+ next = new FitsImageFitsNextChannel(this, parent_->interp, fn, ptr->fitsFile(), ii+1);
+ break;
+ case Base::MMAP:
+ next = new FitsImageFitsNextMMap(this, parent_->interp, fn, ptr->fitsFile(), ii+1);
+ break;
+ case Base::SMMAP:
+ next = new FitsImageFitsNextSMMap(this, parent_->interp, fn, ptr->fitsFile(), ii+1);
+ break;
+ case Base::MMAPINCR:
+ next = new FitsImageFitsNextMMapIncr(this, parent_->interp, fn, ptr->fitsFile(), ii+1);
+ break;
+ case Base::SHARE:
+ next = new FitsImageFitsNextShare(this, parent_->interp, fn, ptr->fitsFile(), ii+1);
+ break;
+ case Base::SSHARE:
+ next = new FitsImageFitsNextSShare(this, parent_->interp, fn, ptr->fitsFile(), ii+1);
+ break;
+ case Base::SOCKET:
+ next = new FitsImageFitsNextSocket(this, parent_->interp, fn, ptr->fitsFile(), ii+1);
+ break;
+ case Base::SOCKETGZ:
+ next = new FitsImageFitsNextSocketGZ(this, parent_->interp, fn, ptr->fitsFile(), ii+1);
+ break;
+ case Base::VAR:
+ next = new FitsImageFitsNextVar(this, parent_->interp, fn, ptr->fitsFile(), ii+1);
+ break;
+ case Base::POST:
+ next = new FitsImageFitsNextPost(this, parent_->interp, img, ptr->baseFile(), ii+1);
+ break;
+ case Base::PHOTO:
+ next = new FitsImagePhotoCubeNext(this, parent_->interp, fn, ptr->baseFile(), ii+1);
+ break;
+ default:
+ // na
+ break;
+ }
+
+ if (next->isValid()) {
+ ptr->setNextSlice(next);
+ ptr = next;
+ }
+ else {
+ delete next;
+ break;
+ }
+ }
+
+ // finish up
+ img->close();
+
+ switch (ll) {
+ case Base::IMG:
+ loadFinish();
+ break;
+ case Base::MASK:
+ loadFinishMask();
+ break;
+ }
+
+ return 1;
+}
+
+int Context::loadExtCube(Base::MemType which, const char* fn, FitsImage* img)
+{
+ if (!img || !img->isValid()) {
+ if (img)
+ delete img;
+
+ unload();
+ return 0;
+ }
+
+ bfits_ = img;
+ loadInit(1, Base::NOMOSAIC,Coord::WCS);
+
+ // get the rest
+ FitsImage* ptr = img;
+ FitsImage* mptr = ptr;
+ FitsImage* tmp =NULL;
+ while (1) {
+ FitsImage* next = NULL;
+ switch (which) {
+ case Base::ALLOC:
+ next = new FitsImageMosaicNextAlloc(this, parent_->interp, fn, ptr->fitsFile(), FitsFile::NOFLUSH ,1);
+ break;
+ case Base::ALLOCGZ:
+ next = new FitsImageMosaicNextAllocGZ(this, parent_->interp,fn,ptr->fitsFile(), FitsFile::NOFLUSH ,1);
+ break;
+ case Base::CHANNEL:
+ next = new FitsImageMosaicNextChannel(this, parent_->interp,fn,ptr->fitsFile(), FitsFile::NOFLUSH, 1);
+ break;
+ case Base::MMAP:
+ next = new FitsImageMosaicNextMMap(this, parent_->interp, fn, ptr->fitsFile(), 1);
+ break;
+ case Base::MMAPINCR:
+ next = new FitsImageMosaicNextMMapIncr(this, parent_->interp, fn, ptr->fitsFile(), 1);
+ break;
+ case Base::SHARE:
+ next = new FitsImageMosaicNextShare(this, parent_->interp, fn, ptr->fitsFile(), 1);
+ break;
+ case Base::SOCKET:
+ next = new FitsImageMosaicNextSocket(this, parent_->interp, fn,ptr->fitsFile(), FitsFile::FLUSH,1 );
+ break;
+ case Base::SOCKETGZ:
+ next =new FitsImageMosaicNextSocketGZ(this, parent_->interp,fn,ptr->fitsFile(), FitsFile::FLUSH,1 );
+ break;
+ case Base::VAR:
+ next = new FitsImageMosaicNextVar(this, parent_->interp, fn, ptr->fitsFile(), 1);
+ break;
+ default:
+ // na
+ break;
+ }
+
+ // if previous was a unknown table, delete now, we're done with it
+ if (tmp) {
+ delete tmp;
+ tmp =NULL;
+ }
+
+ // first check if fits_ is a known extension, aka we loaded something
+ if (next->isImage() || next->isTable()) {
+ // now check to see if it resolved into an image, no event tables
+ // since any table can be a valid event table
+ if (next->isValid() && !next->isHist()) {
+ mptr->setNextSlice(next);
+ ptr = next;
+ mptr = ptr;
+ baxis_[2]++;
+ }
+ else {
+ // must be a unknown table, just ignore, and delete next time thru
+ ptr = next;
+ tmp = next;
+ }
+ }
+ else {
+ delete next;
+ break;
+ }
+ }
+
+ // finish up
+ img->close();
+
+ // fix z params (in data coords)
+ // must wait untill all loaded
+ iparams.set(0,baxis_[2]);
+ cparams.set(0,baxis_[2]);
+
+ loadFinish();
+ return 1;
+}
+
+void Context::loadInit(int cnt, Base::MosaicType type, Coord::CoordSystem sys)
+{
+ shareWCS_ =0;
+
+ mosaicCount_ = cnt;
+ mosaicType = type;
+ mosaicSystem = sys;
+ for (int ii=0; ii<FTY_MAXAXES; ii++) {
+ baxis_[ii] =1;
+ slice_[ii] =1;
+ }
+ naxis_ = baxis_;
+
+ // fix z params (in data coords)
+ iparams.set(0,1);
+ cparams.set(0,1);
+}
+
+int Context::loadMosaic(Base::MemType which, const char* fn,
+ FitsImage* img, Base::LayerType ll,
+ Base::MosaicType type, Coord::CoordSystem sys)
+{
+ if (!img || !img->isValid()) {
+ if (img)
+ delete img;
+ return 0;
+ }
+
+ switch (ll) {
+ case Base::IMG:
+ if (bfits_) {
+ FitsImage* ptr = bfits_;
+ while (ptr && ptr->nextMosaic())
+ ptr = ptr->nextMosaic();
+ ptr->setNextMosaic(img);
+ mosaicCount_++;
+ }
+ else {
+ bfits_ = img;
+ loadInit(1, type,sys);
+ for (int ii=2; ii<FTY_MAXAXES; ii++) {
+ int nn = img->naxis(ii);
+ baxis_[ii] = nn ? nn : 1;
+ }
+
+ // fix z params (in data coords)
+ // do it here because of fits section
+ iparams.set(0,baxis_[2]);
+ cparams.set(0,baxis_[2]);
+ }
+ break;
+
+ case Base::MASK:
+ FitsMask* msk = mask.tail();
+ if (msk) {
+ FitsImage* mskimg = msk->mask();
+ while (mskimg && mskimg->nextMosaic())
+ mskimg = mskimg->nextMosaic();
+ mskimg->setNextMosaic(img);
+ }
+ else
+ mask.append(new FitsMask(parent_, img, parent_->maskColorName, parent_->maskMark));
+ break;
+ }
+
+ if (img->isPost())
+ which = Base::POST;
+
+ // get the rest of slices
+ if (img->nhdu() > 1)
+ shareWCS_ =1;
+
+ FitsImage* sptr = img;
+ for (int ii=1; ii<img->nhdu(); ii++) {
+ FitsImage* next = NULL;
+ switch (which) {
+ case Base::ALLOC:
+ next = new FitsImageFitsNextAlloc(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::ALLOCGZ:
+ next = new FitsImageFitsNextAllocGZ(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::CHANNEL:
+ next = new FitsImageFitsNextChannel(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::MMAP:
+ next = new FitsImageFitsNextMMap(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::SMMAP:
+ next = new FitsImageFitsNextSMMap(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::MMAPINCR:
+ next = new FitsImageFitsNextMMapIncr(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::SHARE:
+ next = new FitsImageFitsNextShare(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::SSHARE:
+ next = new FitsImageFitsNextSShare(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::SOCKET:
+ next = new FitsImageFitsNextSocket(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::SOCKETGZ:
+ next = new FitsImageFitsNextSocketGZ(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::VAR:
+ next = new FitsImageFitsNextVar(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::POST:
+ next = new FitsImageFitsNextPost(this, parent_->interp, img, sptr->baseFile(), ii+1);
+ break;
+ case Base::PHOTO:
+ next = new FitsImagePhotoCubeNext(this, parent_->interp, fn, sptr->baseFile(), ii+1);
+ break;
+ default:
+ // na
+ break;
+ }
+
+ if (next->isValid()) {
+ sptr->setNextSlice(next);
+ sptr = next;
+ }
+ else {
+ delete next;
+ break;
+ }
+ }
+
+ // finish up
+ img->close();
+
+ switch (ll) {
+ case Base::IMG:
+ loadFinishMosaic(fits);
+ if (!loadFinish()) {
+ unload();
+ return 0;
+ }
+ break;
+ case Base::MASK:
+ if (!loadFinishMosaicMask())
+ return 0;
+ break;
+ }
+
+ return 1;
+}
+
+int Context::loadMosaicImage(Base::MemType which, const char* fn,
+ FitsImage* img, Base::LayerType ll,
+ Base::MosaicType type, Coord::CoordSystem sys)
+{
+ if (!img || !img->isValid()) {
+ if (img)
+ delete img;
+
+ switch (ll) {
+ case Base::IMG:
+ unload();
+ return 0;
+ case Base::MASK:
+ return 0;
+ }
+ }
+
+ switch (ll) {
+ case Base::IMG:
+ bfits_ = img;
+ loadInit(1, type,sys);
+ for (int ii=2; ii<FTY_MAXAXES; ii++) {
+ int nn = img->naxis(ii);
+ baxis_[ii] = nn ? nn : 1;
+ }
+
+ // fix z params (in data coords)
+ // do it here because of fits section
+ iparams.set(0,baxis_[2]);
+ cparams.set(0,baxis_[2]);
+
+ break;
+
+ case Base::MASK:
+ mask.append(new FitsMask(parent_, img, parent_->maskColorName, parent_->maskMark));
+ break;
+ }
+
+ Base::MemType sav = which;
+
+ // get the rest of slices
+ FitsImage* sptr = img;
+ if (img->isPost())
+ which = Base::POST;
+
+ if (img->nhdu() > 1)
+ shareWCS_ =1;
+
+ for (int ii=1; ii<img->nhdu(); ii++) {
+ FitsImage* next = NULL;
+ switch (which) {
+ case Base::ALLOC:
+ next = new FitsImageFitsNextAlloc(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::ALLOCGZ:
+ next = new FitsImageFitsNextAllocGZ(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::CHANNEL:
+ next = new FitsImageFitsNextChannel(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::MMAP:
+ next = new FitsImageFitsNextMMap(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::SMMAP:
+ next = new FitsImageFitsNextSMMap(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::MMAPINCR:
+ next = new FitsImageFitsNextMMapIncr(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::SHARE:
+ next = new FitsImageFitsNextShare(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::SSHARE:
+ next = new FitsImageFitsNextSShare(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::SOCKET:
+ next = new FitsImageFitsNextSocket(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::SOCKETGZ:
+ next = new FitsImageFitsNextSocketGZ(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::VAR:
+ next = new FitsImageFitsNextVar(this, parent_->interp, fn, sptr->fitsFile(), ii+1);
+ break;
+ case Base::POST:
+ next = new FitsImageFitsNextPost(this, parent_->interp, img, sptr->baseFile(), ii+1);
+ break;
+ default:
+ // na
+ break;
+ }
+
+ if (next->isValid()) {
+ sptr->setNextSlice(next);
+ sptr = next;
+ }
+ else {
+ delete next;
+ break;
+ }
+ }
+
+ // get the rest of mosaic
+ FitsImage* ptr = img;
+ FitsImage* tmp =NULL;
+ while (1) {
+ // restore which
+ which = sav;
+
+ FitsImage* next = NULL;
+ switch (which) {
+ case Base::ALLOC:
+ next = new FitsImageMosaicNextAlloc(this, parent_->interp, fn, ptr->fitsFile(), FitsFile::NOFLUSH, 1);
+ break;
+ case Base::ALLOCGZ:
+ next = new FitsImageMosaicNextAllocGZ(this, parent_->interp,fn,ptr->fitsFile(), FitsFile::NOFLUSH, 1);
+ break;
+ case Base::CHANNEL:
+ next = new FitsImageMosaicNextChannel(this, parent_->interp,fn,ptr->fitsFile(), FitsFile::NOFLUSH, 1);
+ break;
+ case Base::MMAP:
+ next = new FitsImageMosaicNextMMap(this, parent_->interp, fn, ptr->fitsFile(), 1);
+ break;
+ case Base::MMAPINCR:
+ next = new FitsImageMosaicNextMMapIncr(this, parent_->interp, fn, ptr->fitsFile(), 1);
+ break;
+ case Base::SHARE:
+ next = new FitsImageMosaicNextShare(this, parent_->interp, fn, ptr->fitsFile(), 1);
+ break;
+ case Base::SOCKET:
+ next = new FitsImageMosaicNextSocket(this, parent_->interp, fn,ptr->fitsFile(), FitsFile::FLUSH, 1);
+ break;
+ case Base::SOCKETGZ:
+ next = new FitsImageMosaicNextSocketGZ(this, parent_->interp,fn,ptr->fitsFile(), FitsFile::FLUSH, 1);
+ break;
+ case Base::VAR:
+ next = new FitsImageMosaicNextVar(this, parent_->interp, fn, ptr->fitsFile(), 1);
+ break;
+ default:
+ // na
+ break;
+ }
+
+ // if previous was a unknown table, delete now, we're done with it
+ if (tmp) {
+ delete tmp;
+ tmp =NULL;
+ }
+
+ // first check if fits_ is a known extension, aka we loaded something
+ if (!next->isImage() && !next->isTable()) {
+ // ok, we're done
+ delete next;
+ break;
+ }
+
+ // now check to see if it resolved into an image, no event tables
+ // since any table can be a valid event table
+ if (!next->isValid() || next->isHist()) {
+ // must be a unknown table, just ignore, and delete next time thru
+ ptr = next;
+ tmp = next;
+ }
+ else {
+ ptr->setNextMosaic(next);
+ ptr = next;
+
+ if (ll == Base::IMG)
+ mosaicCount_++;
+
+ if (img->isPost())
+ which = Base::POST;
+
+ // get rest of slices
+ for (int ii=1; ii<img->nhdu(); ii++) {
+ FitsImage* snext = NULL;
+ switch (which) {
+ case Base::ALLOC:
+ snext = new FitsImageFitsNextAlloc(this, parent_->interp, fn, next->fitsFile(),ii+1);
+ break;
+ case Base::ALLOCGZ:
+ snext = new FitsImageFitsNextAllocGZ(this, parent_->interp, fn, next->fitsFile(),ii+1);
+ break;
+ case Base::CHANNEL:
+ snext = new FitsImageFitsNextChannel(this, parent_->interp, fn, next->fitsFile(),ii+1);
+ break;
+ case Base::MMAP:
+ snext = new FitsImageFitsNextMMap(this, parent_->interp, fn, next->fitsFile(),ii+1);
+ break;
+ case Base::SMMAP:
+ snext = new FitsImageFitsNextSMMap(this, parent_->interp, fn, next->fitsFile(),ii+1);
+ break;
+ case Base::MMAPINCR:
+ snext = new FitsImageFitsNextMMapIncr(this, parent_->interp, fn, next->fitsFile(),ii+1);
+ break;
+ case Base::SHARE:
+ snext = new FitsImageFitsNextShare(this, parent_->interp, fn, next->fitsFile(),ii+1);
+ break;
+ case Base::SSHARE:
+ snext = new FitsImageFitsNextSShare(this, parent_->interp, fn, next->fitsFile(),ii+1);
+ break;
+ case Base::SOCKET:
+ snext = new FitsImageFitsNextSocket(this, parent_->interp, fn, next->fitsFile(),ii+1);
+ break;
+ case Base::SOCKETGZ:
+ snext = new FitsImageFitsNextSocketGZ(this, parent_->interp, fn, next->fitsFile(),ii+1);
+ break;
+ case Base::VAR:
+ snext = new FitsImageFitsNextVar(this, parent_->interp, fn, next->fitsFile(),ii+1);
+ break;
+ case Base::POST:
+ snext = new FitsImageFitsNextPost(this, parent_->interp, ptr, next->baseFile(),ii+1);
+ break;
+ default:
+ // na
+ break;
+ }
+
+ if (snext->isValid()) {
+ next->setNextSlice(snext);
+ next = snext;
+ }
+ else {
+ delete snext;
+ break;
+ }
+ }
+ }
+ }
+
+ // finish up
+ img->close();
+
+ switch (ll) {
+ case Base::IMG:
+ loadFinishMosaic(fits);
+ if (!loadFinish()) {
+ unload();
+ return 0;
+ }
+ break;
+ case Base::MASK:
+ if (!loadFinishMosaicMask())
+ return 0;
+ break;
+ }
+
+ return 1;
+}
+
+int Context::loadMosaicWFPC2(Base::MemType which, const char* fn,
+ FitsImage* img)
+{
+ if (!img || !img->isValid()) {
+ if (img)
+ delete img;
+
+ unload();
+ return 0;
+ }
+
+ // Its legal, save it
+ bfits_ = img;
+ loadInit(1, Base::WFPC2,Coord::WCS);
+
+ // remember in case of compress
+ Base::MemType sav = which;
+
+ if (img->isPost())
+ which = Base::POST;
+
+ // get the rest
+ {
+ FitsImage* ptr = img;
+ for (int i=1; i<4; i++) {
+ FitsImage* next = NULL;
+ switch (which) {
+ case Base::ALLOC:
+ next = new FitsImageFitsNextAlloc(this, parent_->interp, fn, ptr->fitsFile(), 1);
+ break;
+ case Base::ALLOCGZ:
+ next = new FitsImageFitsNextAllocGZ(this, parent_->interp, fn, ptr->fitsFile(), 1);
+ break;
+ case Base::CHANNEL:
+ next = new FitsImageFitsNextChannel(this, parent_->interp, fn, ptr->fitsFile(), 1);
+ break;
+ case Base::MMAP:
+ next = new FitsImageFitsNextMMap(this, parent_->interp, fn, ptr->fitsFile(), 1);
+ break;
+ case Base::MMAPINCR:
+ next = new FitsImageFitsNextMMapIncr(this, parent_->interp, fn, ptr->fitsFile(), 1);
+ break;
+ case Base::SHARE:
+ next = new FitsImageFitsNextShare(this, parent_->interp, fn, ptr->fitsFile(), 1);
+ break;
+ case Base::SOCKET:
+ next = new FitsImageFitsNextSocket(this, parent_->interp, fn, ptr->fitsFile(), 1);
+ break;
+ case Base::SOCKETGZ:
+ next = new FitsImageFitsNextSocketGZ(this, parent_->interp, fn, ptr->fitsFile(), 1);
+ break;
+ case Base::VAR:
+ next = new FitsImageFitsNextVar(this, parent_->interp, fn, ptr->fitsFile(), 1);
+ break;
+ case Base::POST:
+ next = new FitsImageFitsNextPost(this, parent_->interp, img, ptr->baseFile(), 1);
+ break;
+ default:
+ // na
+ break;
+ }
+
+ if (next->isValid()) {
+ ptr->setNextMosaic(next);
+ ptr = next;
+ mosaicCount_++;
+ }
+ else {
+ delete next;
+ break;
+ }
+ }
+ }
+
+ // restore which
+ which = sav;
+
+ // ok, do we have 4 images?
+ if (mosaicCount_ != 4) {
+ unload();
+ return 0;
+ }
+
+ // now, find WCS table
+ FitsFile* table =NULL;
+ switch (which) {
+ case Base::ALLOC:
+ table = new FitsMosaicNextAlloc(img->fitsFile(), FitsFile::NOFLUSH);
+ break;
+ case Base::ALLOCGZ:
+ table = new FitsMosaicNextAllocGZ(img->fitsFile(), FitsFile::NOFLUSH);
+ break;
+ case Base::CHANNEL:
+ table = new FitsMosaicNextChannel(img->fitsFile(), FitsFile::NOFLUSH);
+ break;
+ case Base::MMAP:
+ table = new FitsMosaicNextMMap(img->fitsFile());
+ break;
+ case Base::MMAPINCR:
+ table = new FitsMosaicNextMMapIncr(img->fitsFile());
+ break;
+ case Base::SHARE:
+ table = new FitsMosaicNextShare(img->fitsFile());
+ break;
+ case Base::SOCKET:
+ table = new FitsMosaicNextSocket(img->fitsFile(), FitsFile::FLUSH);
+ break;
+ case Base::SOCKETGZ:
+ table = new FitsMosaicNextSocketGZ(img->fitsFile(), FitsFile::FLUSH);
+ break;
+ case Base::VAR:
+ table = new FitsMosaicNextVar(img->fitsFile());
+ break;
+ default:
+ // na
+ break;
+ }
+
+ if (!table || !table->isValid() || !table->isAsciiTable()) {
+ if (table)
+ delete table;
+
+ unload();
+ return 0;
+ }
+
+ // read WCS from table
+ {
+ FitsHead* th = table->head();
+ if (th->naxes() != 2) {
+ if (table)
+ delete table;
+
+ unload();
+ return 0;
+ }
+
+ FitsTableHDU* thdu = (FitsTableHDU*)th->hdu();
+
+ FitsColumn* crval1 = thdu->find("CRVAL1");
+ FitsColumn* crval2 = thdu->find("CRVAL2");
+ FitsColumn* crpix1 = thdu->find("CRPIX1");
+ FitsColumn* crpix2 = thdu->find("CRPIX2");
+
+ FitsColumn* cd1_1 = thdu->find("CD1_1");
+ FitsColumn* cd1_2 = thdu->find("CD1_2");
+ FitsColumn* cd2_1 = thdu->find("CD2_1");
+ FitsColumn* cd2_2 = thdu->find("CD2_2");
+
+ FitsColumn* ctype1 = thdu->find("CTYPE1");
+ FitsColumn* ctype2 = thdu->find("CTYPE2");
+
+ char* tptr = (char*)table->data();
+ int rows = thdu->rows();
+ int rowlen = thdu->width();
+
+ if (rows != 4) {
+ unload();
+ return 0;
+ }
+
+ FitsImage* ptr = bfits_;
+
+ // reset count for processKeyWords()
+ mosaicCount_ =0;
+
+ for (int ii=0; ii<rows; ii++, tptr+=rowlen) {
+ istringstream istr(ios::in|ios::out);
+ ostream ostr(istr.rdbuf());
+ ostr << "CRVAL1 = " << crval1->str(tptr) << endl
+ << "CRVAL2 = " << crval2->str(tptr) << endl
+ << "CRPIX1 = " << crpix1->str(tptr) << endl
+ << "CRPIX2 = " << crpix2->str(tptr) << endl
+ << "CD1_1 = " << cd1_1->str(tptr) << endl
+ << "CD1_2 = " << cd1_2->str(tptr) << endl
+ << "CD2_1 = " << cd2_1->str(tptr) << endl
+ << "CD2_2 = " << cd2_2->str(tptr) << endl
+ << "CTYPE1 = " << '\'' << ctype1->str(tptr) << '\'' << endl
+ << "CTYPE2 = " << '\'' << ctype2->str(tptr) << '\'' << endl
+ << ends;
+
+ // fix fitsimage params
+ ptr->altWCS(istr);
+
+ Matrix mm = parent_->calcAlignWCS(bfits_, ptr, Coord::WCS,
+ Coord::WCS, Coord::FK5);
+ ptr->setwcsToRef(mm);
+
+ ptr = ptr->nextMosaic();
+ mosaicCount_++;
+ }
+ }
+
+ if (table)
+ delete table;
+
+ // finish up
+ img->close();
+
+ loadFinish();
+ return 1;
+}
+
+int Context::loadFinish()
+{
+ if (DebugPerf)
+ cerr << "Context::loadFinish()" << endl;
+
+ // just in case of 3d
+ parent_->cancelDetach();
+
+ if (manageAxes_) {
+ delete [] naxis_;
+ deleteFits(fits);
+ manageAxes_ =0;
+ }
+ fits = bfits_;
+ naxis_ = baxis_;
+
+ if (axesOrder_ != 123)
+ reorderAxes();
+
+ for (int ii=0; ii<FTY_MAXAXES; ii++)
+ slice_[ii] =1;
+ cfits = fits;
+
+ if (!block())
+ return 0;
+
+ FitsImage* ptr = fits;
+ while (ptr) {
+ FitsImage* sptr = ptr;
+ while (sptr) {
+ sptr->processKeywordsFitsSection();
+ sptr = sptr->nextSlice();
+ }
+ ptr = ptr->nextMosaic();
+ }
+
+ analysis();
+
+ return 1;
+}
+
+void Context::loadFinishMask()
+{
+ FitsMask* msk = mask.tail();
+ if (msk) {
+ FitsImage* mskimg = msk->mask();
+ mskimg->block();
+ }
+}
+
+void Context::loadFinishMosaic(FitsImage* ptr)
+{
+ while (ptr && ptr->nextMosaic()) {
+ int jj=0;
+ FitsImage* sptr = ptr;
+ while (sptr) {
+ if (sptr->nextMosaic() == NULL) {
+ // ok, let's figure out next inline
+ FitsImage* mptr = ptr->nextMosaic();
+ for (int nn=0; nn<jj; nn++)
+ mptr = mptr->nextSlice();
+ sptr->setNextMosaic(mptr);
+ }
+ jj++;
+ sptr = sptr->nextSlice();
+ }
+ ptr = ptr->nextMosaic();
+ }
+}
+
+int Context::loadFinishMosaicMask()
+{
+ FitsMask* msk = mask.tail();
+ if (msk)
+ loadFinishMosaic(msk->mask());
+
+ return blockMask();
+}
+
+int Context::loadSlice(Base::MemType which, const char* fn,
+ FitsImage* img)
+{
+ if (!img || !img->isValid()) {
+ if (img)
+ delete img;
+ return 0;
+ }
+
+ if (bfits_) {
+ FitsImage* ptr = bfits_;
+ while (ptr && ptr->nextSlice())
+ ptr = ptr->nextSlice();
+ ptr->setNextSlice(img);
+ baxis_[2]++;
+ }
+ else {
+ bfits_ = img;
+ loadInit(1, Base::NOMOSAIC,Coord::WCS);
+ }
+
+ // finish up
+ img->close();
+
+ // fix z params (in data coords)
+ // must wait untill all loaded
+ iparams.set(0,baxis_[2]);
+ cparams.set(0,baxis_[2]);
+
+ loadFinish();
+ return 1;
+}
+
+int Context::naxes()
+{
+ for (int ii=FTY_MAXAXES-1; ii>=2; ii--) {
+ if (naxis_[ii]>1)
+ return ii+1;
+ }
+ return 2;
+}
+
+int Context::nhdu()
+{
+ int dd =1;
+ for (int ii=2; ii<FTY_MAXAXES; ii++)
+ if (naxis_[ii]>1)
+ dd *= naxis_[ii];
+ return dd;
+}
+
+int Context::processMosaicKeywords(FitsImage* ptr)
+{
+ while (ptr) {
+ FitsImage* sptr = ptr;
+ while (sptr) {
+ switch (mosaicType) {
+ case Base::IRAF:
+ if (!sptr->processKeywordsIRAF(fits))
+ return 0;
+ break;
+ case Base::WCSMOSAIC:
+ {
+ if (!sptr->hasWCS(mosaicSystem))
+ return 0;
+
+ Matrix mm = parent_->calcAlignWCS(fits, sptr, mosaicSystem,
+ mosaicSystem, Coord::FK5);
+ sptr->setwcsToRef(mm);
+ }
+ break;
+ default:
+ // na
+ break;
+ }
+ sptr = sptr->nextSlice();
+ }
+ ptr = ptr->nextMosaic();
+ }
+
+ return 1;
+}
+
+void* reorder132(void* tt)
+{
+ t_reorder_arg* targ = (t_reorder_arg*)tt;
+ char* dest = targ->dest;
+ char** sjv = targ->sjv;
+ int ww = targ->ww;
+ // int hh = targ->hh;
+ int dd = targ->dd;
+ int bz = targ->bz;
+ int jj = targ->mm;
+
+ for (int kk=0; kk<dd; kk++) {
+ memcpy(dest, sjv[kk]+(jj*ww)*bz, ww*bz);
+ dest += ww*bz;
+ /*
+ for (int ii=0; ii<ww; ii++) {
+ memcpy(dest, sjv[kk]+(jj*ww+ii)*bz, bz);
+ dest += bz;
+ }
+ */
+ }
+ return NULL;
+}
+
+void* reorder213(void* tt)
+{
+ t_reorder_arg* targ = (t_reorder_arg*)tt;
+ char* dest = targ->dest;
+ char** sjv = targ->sjv;
+ int ww = targ->ww;
+ int hh = targ->hh;
+ // int dd = targ->dd;
+ int bz = targ->bz;
+ int kk = targ->mm;
+
+ for (int ii=0; ii<ww; ii++) {
+ for (int jj=0; jj<hh; jj++) {
+ memcpy(dest, sjv[kk]+(jj*ww+ii)*bz, bz);
+ dest += bz;
+ }
+ }
+ return NULL;
+}
+
+void* reorder231(void* tt)
+{
+ t_reorder_arg* targ = (t_reorder_arg*)tt;
+ char* dest = targ->dest;
+ char** sjv = targ->sjv;
+ int ww = targ->ww;
+ int hh = targ->hh;
+ int dd = targ->dd;
+ int bz = targ->bz;
+ int ii = targ->mm;
+
+ for (int kk=0; kk<dd; kk++) {
+ for (int jj=0; jj<hh; jj++) {
+ memcpy(dest, sjv[kk]+(jj*ww+ii)*bz, bz);
+ dest += bz;
+ }
+ }
+ return NULL;
+}
+
+void* reorder312(void* tt)
+{
+ t_reorder_arg* targ = (t_reorder_arg*)tt;
+ char* dest = targ->dest;
+ char** sjv = targ->sjv;
+ int ww = targ->ww;
+ // int hh = targ->hh;
+ int dd = targ->dd;
+ int bz = targ->bz;
+ int jj = targ->mm;
+
+ for (int ii=0; ii<ww; ii++) {
+ for (int kk=0; kk<dd; kk++) {
+ memcpy(dest, sjv[kk]+(jj*ww+ii)*bz, bz);
+ dest += bz;
+ }
+ }
+ return NULL;
+}
+
+void* reorder321(void* tt)
+{
+ t_reorder_arg* targ = (t_reorder_arg*)tt;
+ char* dest = targ->dest;
+ char** sjv = targ->sjv;
+ int ww = targ->ww;
+ int hh = targ->hh;
+ int dd = targ->dd;
+ int bz = targ->bz;
+ int ii = targ->mm;
+
+ for (int jj=0; jj<hh; jj++) {
+ for (int kk=0; kk<dd; kk++) {
+ memcpy(dest, sjv[kk]+(jj*ww+ii)*bz, bz);
+ dest += bz;
+ }
+ }
+ return NULL;
+}
+
+#ifdef __WIN32
+
+void Context::reorderAxis(char* data, char** sjv, int ww, int hh, int dd,
+ size_t bz)
+{
+ t_reorder_arg targ;
+
+ targ.sjv = sjv;
+ targ.ww = ww;
+ targ.hh = hh;
+ targ.dd = dd;
+ targ.bz = bz;
+
+ for (int mm=0; mm<naxis_[2]; mm++) {
+ targ.dest = data + (size_t)naxis_[0]*naxis_[1]*mm*targ.bz;
+ targ.mm = mm;
+
+ switch (axesOrder_) {
+ case 123:
+ return;
+ case 132:
+ naxis_[0] =ww;
+ naxis_[1] =dd;
+ naxis_[2] =hh;
+ reorder132(&targ);
+ break;
+ case 213:
+ naxis_[0] =hh;
+ naxis_[1] =ww;
+ naxis_[2] =dd;
+ reorder213(&targ);
+ break;
+ case 231:
+ naxis_[0] =hh;
+ naxis_[1] =dd;
+ naxis_[2] =ww;
+ reorder231(&targ);
+ break;
+ case 312:
+ naxis_[0] =dd;
+ naxis_[1] =ww;
+ naxis_[2] =hh;
+ reorder312(&targ);
+ break;
+ case 321:
+ naxis_[0] =dd;
+ naxis_[1] =hh;
+ naxis_[2] =ww;
+ reorder321(&targ);
+ break;
+ }
+ }
+}
+
+#else
+
+void Context::reorderThread(void* tt, char* data, void* proc(void*), int* cnt)
+{
+ t_reorder_arg* targ = (t_reorder_arg*)tt;
+
+ for (int mm=0; mm<naxis_[2]; mm++) {
+ targ[*cnt].dest = data + (size_t)naxis_[0]*naxis_[1]*mm*targ[*cnt].bz;
+ targ[*cnt].mm = mm;
+ if (pthread_create(&thread_[*cnt], NULL, proc, &targ[*cnt]))
+ internalError("Unable to Create Thread");
+
+ (*cnt)++;
+ if (*cnt == parent_->nthreads_) {
+ for (int pp=0; pp<*cnt; pp++) {
+ if (pthread_join(thread_[pp], NULL))
+ internalError("Unable to Join Thread");
+ }
+ *cnt =0;
+ }
+ }
+}
+
+void Context::reorderAxis(char* data, char** sjv, int ww, int hh, int dd,
+ size_t bz)
+{
+ if (thread_)
+ delete [] thread_;
+ thread_ = new pthread_t[parent_->nthreads_];
+ t_reorder_arg* targ = new t_reorder_arg[parent_->nthreads_];
+
+ for (int ii=0; ii<parent_->nthreads_; ii++) {
+ targ[ii].sjv = sjv;
+ targ[ii].ww = ww;
+ targ[ii].hh = hh;
+ targ[ii].dd = dd;
+ targ[ii].bz = bz;
+ }
+
+ int cnt =0;
+ switch (axesOrder_) {
+ case 123:
+ return;
+ case 132:
+ naxis_[0] =ww;
+ naxis_[1] =dd;
+ naxis_[2] =hh;
+ reorderThread(targ, data, reorder132, &cnt);
+ break;
+ case 213:
+ naxis_[0] =hh;
+ naxis_[1] =ww;
+ naxis_[2] =dd;
+ reorderThread(targ, data, reorder213, &cnt);
+ break;
+ case 231:
+ naxis_[0] =hh;
+ naxis_[1] =dd;
+ naxis_[2] =ww;
+ reorderThread(targ, data, reorder231, &cnt);
+ break;
+ case 312:
+ naxis_[0] =dd;
+ naxis_[1] =ww;
+ naxis_[2] =hh;
+ reorderThread(targ, data, reorder312, &cnt);
+ break;
+ case 321:
+ naxis_[0] =dd;
+ naxis_[1] =hh;
+ naxis_[2] =ww;
+ reorderThread(targ, data, reorder321, &cnt);
+ break;
+ }
+
+ for (int pp=0; pp<cnt; pp++)
+ if (pthread_join(thread_[pp], NULL))
+ internalError("Unable to Join Thread");
+
+ delete [] targ;
+ delete [] thread_;
+ thread_ =NULL;
+}
+
+#endif
+
+void Context::reorderAxes()
+{
+ if (DebugPerf)
+ cerr << "Context::reorderAxes()" << endl;
+
+ int bitpix = bfits_->baseFile()->head()->bitpix();
+ int bz = abs(bitpix)/8;
+
+ int ww = bfits_->baseFile()->head()->naxis(0);
+ int hh = bfits_->baseFile()->head()->naxis(1);
+ int dd = baxis_[2];
+ size_t sz = (size_t)ww*hh*dd*bz;
+
+ // Data
+ char* data = new char[sz];
+ if (!data)
+ return;
+ memset(data,sz,0);
+
+ naxis_ = new int[FTY_MAXAXES];
+ for (int ii=0; ii<FTY_MAXAXES; ii++)
+ naxis_[ii] =1;
+
+ // slice jump vector
+ char* sjv[dd];
+ FitsImage* sptr = bfits_;
+ int ii=0;
+ while (sptr) {
+ sjv[ii++] = (char*)sptr->basedata();
+ if (sptr)
+ sptr = sptr->nextSlice();
+ }
+
+ reorderAxis(data, sjv, ww, hh, dd, bz);
+
+ // Header
+ FitsHead* hdr = new FitsHead(*(bfits_->baseFile()->head()));
+ hdr->setInteger("NAXES", 3, "");
+ hdr->setInteger("NAXIS1", naxis_[0], "");
+ hdr->setInteger("NAXIS2", naxis_[1], "");
+ if (hdr->find("NAXIS3"))
+ hdr->setInteger("NAXIS3", naxis_[2], "");
+ else {
+ char* n2= hdr->find("NAXIS2");
+ hdr->insertInteger("NAXIS3", naxis_[2], "", n2);
+ }
+
+ for (int ii=0; ii<MULTWCS; ii++) {
+ char alt = (ii==0) ? ' ' : (char)('@'+ii);
+
+ reorderWCSi(hdr, (char*)"CROTA ", 5, alt); // real
+
+ reorderWCSi(hdr, (char*)"CRVAL ", 5, alt); // real
+ reorderWCSi(hdr, (char*)"CRPIX ", 5, alt); // real
+ reorderWCSi(hdr, (char*)"CDELT ", 5, alt); // real
+ reorderWCSi(hdr, (char*)"CTYPE ", 5, alt); // str
+ reorderWCSi(hdr, (char*)"CUNIT ", 5, alt); // str
+ reorderWCSi(hdr, (char*)"CRDER ", 5, alt); // real
+ reorderWCSi(hdr, (char*)"CSYER ", 5, alt); // real
+
+ reorderWCSij(hdr, (char*)"CD _ ", 2, alt); // real
+ reorderWCSij(hdr, (char*)"PC _ ", 2, alt); // real
+ reorderWCSij(hdr, (char*)"PV _ ", 2, alt); // real
+
+ reorderWCSi(hdr, (char*)"LTV ", 3, alt); // real
+ reorderWCSij(hdr, (char*)"LTM _ ", 3, alt); // real
+ reorderWCSi(hdr, (char*)"ATV ", 3, alt); // real
+ reorderWCSij(hdr, (char*)"ATM _ ", 3, alt); // real
+ reorderWCSi(hdr, (char*)"DTV ", 3, alt); // real
+ reorderWCSij(hdr, (char*)"DTM _ ", 3, alt); // real
+ }
+
+ // be sure to have CTYPE1/CTYPE2 or wcs will not process
+ if (!hdr->find("CTYPE1") && hdr->find("CTYPE2")) {
+ char* c2= hdr->find("CTYPE2");
+ hdr->insertString("CTYPE1", "LINEAR", "", c2);
+ }
+ else if (!hdr->find("CTYPE2") && hdr->find("CTYPE1")) {
+ char* c1= hdr->find("CTYPE1");
+ hdr->insertString("CTYPE2", "LINEAR", "", c1);
+ }
+
+ // Load it
+ fits = new FitsImageFitsOrder(this, parent_->interp, bfits_, hdr, data, sz, 1);
+ FitsImage* ptr = fits;
+ for (int ii=1; ii<naxis_[2]; ii++) {
+ FitsImage* next = new FitsImageFitsNextOrder(this, parent_->interp, fits, ptr->fitsFile(), ii+1);
+
+ if (next->isValid()) {
+ ptr->setNextSlice(next);
+ ptr = next;
+ }
+ else {
+ delete next;
+ break;
+ }
+ }
+
+ // fix z params (in data coords)
+ iparams.set(0,naxis_[2]);
+ cparams.set(0,naxis_[2]);
+
+ manageAxes_ =1;
+}
+
+void Context::reorderWCSi(FitsHead* hdr, char* kk, int ii, char ww)
+{
+ char key[8];
+ strcpy(key,kk);
+
+ key[ii+1] = ww;
+
+ key[ii] = '1';
+ char* c1 = hdr->find(key);
+ key[ii] = '2';
+ char* c2 = hdr->find(key);
+ key[ii] = '3';
+ char* c3 = hdr->find(key);
+
+ switch (axesOrder_) {
+ case 123:
+ return;
+ case 132:
+ {
+ if (c1) {
+ key[ii] = '1';
+ FitsCard(c1).setKey(key);
+ }
+ if (c2) {
+ key[ii] = '3';
+ FitsCard(c2).setKey(key);
+ }
+ if (c3) {
+ key[ii] = '2';
+ FitsCard(c3).setKey(key);
+ }
+ }
+ break;
+ case 213:
+ {
+ if (c1) {
+ key[ii] = '2';
+ FitsCard(c1).setKey(key);
+ }
+ if (c2) {
+ key[ii] = '1';
+ FitsCard(c2).setKey(key);
+ }
+ if (c3) {
+ key[ii] = '3';
+ FitsCard(c3).setKey(key);
+ }
+ }
+ break;
+ case 231:
+ {
+ if (c1) {
+ key[ii] = '3';
+ FitsCard(c1).setKey(key);
+ }
+ if (c2) {
+ key[ii] = '1';
+ FitsCard(c2).setKey(key);
+ }
+ if (c3) {
+ key[ii] = '2';
+ FitsCard(c3).setKey(key);
+ }
+ }
+ break;
+ case 312:
+ {
+ if (c1) {
+ key[ii] = '2';
+ FitsCard(c1).setKey(key);
+ }
+ if (c2) {
+ key[ii] = '3';
+ FitsCard(c2).setKey(key);
+ }
+ if (c3) {
+ key[ii] = '1';
+ FitsCard(c3).setKey(key);
+ }
+ }
+ break;
+ case 321:
+ {
+ if (c1) {
+ key[ii] = '3';
+ FitsCard(c1).setKey(key);
+ }
+ if (c2) {
+ key[ii] = '2';
+ FitsCard(c2).setKey(key);
+ }
+ if (c3) {
+ key[ii] = '1';
+ FitsCard(c3).setKey(key);
+ }
+ }
+ break;
+ }
+}
+
+void Context::reorderWCSij(FitsHead* hdr, char* kk, int ii, char ww)
+{
+ char key[8];
+ strcpy(key,kk);
+
+ key[ii+3] = ww;
+
+ key[ii] = '1';
+ key[ii+2] = '1';
+ char* c11 = hdr->find(key);
+ key[ii+2] = '2';
+ char* c12 = hdr->find(key);
+ key[ii+2] = '3';
+ char* c13 = hdr->find(key);
+
+ key[ii] = '2';
+ key[ii+2] = '1';
+ char* c21 = hdr->find(key);
+ key[ii+2] = '2';
+ char* c22 = hdr->find(key);
+ key[ii+2] = '3';
+ char* c23 = hdr->find(key);
+
+ key[ii] = '3';
+ key[ii+2] = '1';
+ char* c31 = hdr->find(key);
+ key[ii+2] = '2';
+ char* c32 = hdr->find(key);
+ key[ii+2] = '3';
+ char* c33 = hdr->find(key);
+
+ switch (axesOrder_) {
+ case 123:
+ return;
+ case 132:
+ {
+ if (c11) {
+ key[ii] = '1';
+ key[ii+2] = '1';
+ FitsCard(c11).setKey(key);
+ }
+ if (c12) {
+ key[ii] = '1';
+ key[ii+2] = '3';
+ FitsCard(c12).setKey(key);
+ }
+ if (c13) {
+ key[ii] = '1';
+ key[ii+2] = '2';
+ FitsCard(c13).setKey(key);
+ }
+
+ if (c21) {
+ key[ii] = '3';
+ key[ii+2] = '1';
+ FitsCard(c21).setKey(key);
+ }
+ if (c22) {
+ key[ii] = '3';
+ key[ii+2] = '3';
+ FitsCard(c22).setKey(key);
+ }
+ if (c23) {
+ key[ii] = '3';
+ key[ii+2] = '2';
+ FitsCard(c23).setKey(key);
+ }
+
+ if (c31) {
+ key[ii] = '2';
+ key[ii+2] = '1';
+ FitsCard(c31).setKey(key);
+ }
+ if (c32) {
+ key[ii] = '2';
+ key[ii+2] = '3';
+ FitsCard(c32).setKey(key);
+ }
+ if (c33) {
+ key[ii] = '2';
+ key[ii+2] = '2';
+ FitsCard(c33).setKey(key);
+ }
+ }
+ break;
+ case 213:
+ {
+ if (c11) {
+ key[ii] = '2';
+ key[ii+2] = '2';
+ FitsCard(c11).setKey(key);
+ }
+ if (c12) {
+ key[ii] = '2';
+ key[ii+2] = '1';
+ FitsCard(c12).setKey(key);
+ }
+ if (c13) {
+ key[ii] = '2';
+ key[ii+2] = '3';
+ FitsCard(c13).setKey(key);
+ }
+
+ if (c21) {
+ key[ii] = '1';
+ key[ii+2] = '2';
+ FitsCard(c21).setKey(key);
+ }
+ if (c22) {
+ key[ii] = '1';
+ key[ii+2] = '1';
+ FitsCard(c22).setKey(key);
+ }
+ if (c23) {
+ key[ii] = '1';
+ key[ii+2] = '3';
+ FitsCard(c23).setKey(key);
+ }
+
+ if (c31) {
+ key[ii] = '3';
+ key[ii+2] = '2';
+ FitsCard(c31).setKey(key);
+ }
+ if (c32) {
+ key[ii] = '3';
+ key[ii+2] = '1';
+ FitsCard(c32).setKey(key);
+ }
+ if (c33) {
+ key[ii] = '3';
+ key[ii+2] = '3';
+ FitsCard(c33).setKey(key);
+ }
+ }
+ break;
+ case 231:
+ {
+ if (c11) {
+ key[ii] = '3';
+ key[ii+2] = '3';
+ FitsCard(c11).setKey(key);
+ }
+ if (c12) {
+ key[ii] = '3';
+ key[ii+2] = '1';
+ FitsCard(c12).setKey(key);
+ }
+ if (c13) {
+ key[ii] = '3';
+ key[ii+2] = '2';
+ FitsCard(c13).setKey(key);
+ }
+
+ if (c21) {
+ key[ii] = '1';
+ key[ii+2] = '3';
+ FitsCard(c21).setKey(key);
+ }
+ if (c22) {
+ key[ii] = '1';
+ key[ii+2] = '1';
+ FitsCard(c22).setKey(key);
+ }
+ if (c23) {
+ key[ii] = '1';
+ key[ii+2] = '2';
+ FitsCard(c23).setKey(key);
+ }
+
+ if (c31) {
+ key[ii] = '2';
+ key[ii+2] = '3';
+ FitsCard(c31).setKey(key);
+ }
+ if (c32) {
+ key[ii] = '2';
+ key[ii+2] = '1';
+ FitsCard(c32).setKey(key);
+ }
+ if (c33) {
+ key[ii] = '2';
+ key[ii+2] = '2';
+ FitsCard(c33).setKey(key);
+ }
+ }
+ break;
+ case 312:
+ {
+ if (c11) {
+ key[ii] = '2';
+ key[ii+2] = '2';
+ FitsCard(c11).setKey(key);
+ }
+ if (c12) {
+ key[ii] = '2';
+ key[ii+2] = '3';
+ FitsCard(c12).setKey(key);
+ }
+ if (c13) {
+ key[ii] = '2';
+ key[ii+2] = '1';
+ FitsCard(c13).setKey(key);
+ }
+
+ if (c21) {
+ key[ii] = '3';
+ key[ii+2] = '2';
+ FitsCard(c21).setKey(key);
+ }
+ if (c22) {
+ key[ii] = '3';
+ key[ii+2] = '3';
+ FitsCard(c22).setKey(key);
+ }
+ if (c23) {
+ key[ii] = '3';
+ key[ii+2] = '1';
+ FitsCard(c23).setKey(key);
+ }
+
+ if (c31) {
+ key[ii] = '1';
+ key[ii+2] = '2';
+ FitsCard(c31).setKey(key);
+ }
+ if (c32) {
+ key[ii] = '1';
+ key[ii+2] = '3';
+ FitsCard(c32).setKey(key);
+ }
+ if (c33) {
+ key[ii] = '1';
+ key[ii+2] = '1';
+ FitsCard(c33).setKey(key);
+ }
+ }
+ break;
+ case 321:
+ {
+ if (c11) {
+ key[ii] = '3';
+ key[ii+2] = '3';
+ FitsCard(c11).setKey(key);
+ }
+ if (c12) {
+ key[ii] = '3';
+ key[ii+2] = '2';
+ FitsCard(c12).setKey(key);
+ }
+ if (c13) {
+ key[ii] = '3';
+ key[ii+2] = '1';
+ FitsCard(c13).setKey(key);
+ }
+
+ if (c21) {
+ key[ii] = '2';
+ key[ii+2] = '3';
+ FitsCard(c21).setKey(key);
+ }
+ if (c22) {
+ key[ii] = '2';
+ key[ii+2] = '2';
+ FitsCard(c22).setKey(key);
+ }
+ if (c23) {
+ key[ii] = '2';
+ key[ii+2] = '1';
+ FitsCard(c23).setKey(key);
+ }
+
+ if (c31) {
+ key[ii] = '1';
+ key[ii+2] = '3';
+ FitsCard(c31).setKey(key);
+ }
+ if (c32) {
+ key[ii] = '1';
+ key[ii+2] = '2';
+ FitsCard(c32).setKey(key);
+ }
+ if (c33) {
+ key[ii] = '1';
+ key[ii+2] = '1';
+ FitsCard(c33).setKey(key);
+ }
+ }
+ break;
+ }
+
+ hdr->buildIndex();
+}
+
+void Context::resetIIS()
+{
+ frScale.setClipMode(FrScale::MINMAX);
+ frScale.setMinMaxMode(FrScale::SCAN);
+ frScale.setULow(DEFAULTLOW);
+ frScale.setUHigh(DEFAULTHIGH);
+ frScale.setColorScaleType(FrScale::LINEARSCALE);
+}
+
+void Context::resetSecMode()
+{
+ frScale.resetSecMode();
+ clearHist();
+}
+
+void Context::setAxesOrder(int order)
+{
+ switch (order) {
+ case 123:
+ case 132:
+ case 213:
+ case 231:
+ case 312:
+ case 321:
+ axesOrder_ = order;
+ break;
+ default:
+ axesOrder_ = 123;
+ break;
+ }
+
+ if (bfits_)
+ loadFinish();
+}
+
+void Context::setBinFactor(const Vector& b) {
+ Vector bb = b;
+ binFactor_[0] *= bb[0] <= 0 ? 1 : bb[0];
+ binFactor_[1] *= bb[1] <= 0 ? 1 : bb[1];
+}
+
+void Context::setBinToFactor(const Vector& b) {
+ Vector bb = b;
+ binFactor_[0] = bb[0] <= 0 ? 1 : bb[0];
+ binFactor_[1] = bb[1] <= 0 ? 1 : bb[1];
+}
+
+Vector Context::setBlockFactor(const Vector& b) {
+ Vector bb = b;
+ Vector old = blockFactor_;
+ blockFactor_[0] *= bb[0] <= 0 ? 1 : bb[0];
+ blockFactor_[1] *= bb[1] <= 0 ? 1 : bb[1];
+
+ return Vector(old[0]/blockFactor_[0],old[1]/blockFactor_[1]);
+}
+
+Vector Context::setBlockToFactor(const Vector& b) {
+ Vector bb = b;
+ Vector old = blockFactor_;
+ blockFactor_[0] = bb[0] <= 0 ? 1 : bb[0];
+ blockFactor_[1] = bb[1] <= 0 ? 1 : bb[1];
+
+ return Vector(old[0]/blockFactor_[0],old[1]/blockFactor_[1]);
+}
+
+void Context::setCrop3dParams()
+{
+ // params is a BBOX in DATA coords 0-n
+ cparams = iparams;
+}
+
+void Context::setCrop3dParams(double z0, double z1)
+{
+ // params is a BBOX in DATA coords 0-n
+ double zmin = z0;
+ double zmax = z1;
+
+ // always have at least 1
+ if (zmin+1>zmax)
+ zmax = z0+1;
+
+ // round to int
+ cparams.set(int(zmin+.5), int(zmax+.5));
+}
+
+void Context::setCrop3dParams(int z0, int z1)
+{
+ // params is a BBOX in DATA coords 0-n
+ if (z0<iparams.zmin) {
+ z0=iparams.zmin;
+ if (z0+1>z1)
+ z1=z0+1;
+ }
+
+ if (z1>iparams.zmax) {
+ z1=iparams.zmax;
+ if (z0+1>z1)
+ z0=z1-1;
+ }
+
+ cparams.set(z0,z1);
+}
+
+void Context::setIIS()
+{
+ frScale.setClipMode(FrScale::USERCLIP);
+ frScale.setMinMaxMode(FrScale::SCAN);
+ frScale.setULow(0);
+ frScale.setUHigh(IISSIZE);
+ frScale.setColorScaleType(FrScale::IISSCALE);
+}
+
+void Context::setSecMode(FrScale::SecMode mode)
+{
+ frScale.setSecMode(mode);
+ clearHist();
+}
+
+void Context::unload()
+{
+ if (DebugPerf)
+ cerr << "Context::unload()" << endl;
+
+ deleteFits(bfits_);
+
+ if (manageAxes_) {
+ delete [] naxis_;
+ deleteFits(fits);
+ manageAxes_ =0;
+ }
+
+ bfits_ =NULL;
+ fits =NULL;
+ cfits =NULL;
+
+ loadInit(0, Base::NOMOSAIC, Coord::WCS);
+
+ mask.deleteAll();
+
+ fvcontour_.lcontourlevel().deleteAll();
+ auxcontours_.deleteAll();
+
+ resetSecMode();
+ updateClip();
+}
+
+void Context::updateClip()
+{
+ if (DebugPerf)
+ cerr << "Context::updateClip()" << endl;
+
+ updateClip(&frScale);
+}
+
+void Context::updateClip(FrScale* fr)
+{
+ if (DebugPerf)
+ cerr << "Context::updateClip(FrScale*)" << endl;
+
+ // no fits
+ if (!fits) {
+ if (fr->clipMode() != FrScale::USERCLIP) {
+ fr->setLow(DEFAULTLOW);
+ fr->setHigh(DEFAULTHIGH);
+ }
+ else {
+ fr->setLow(fr->ulow());
+ fr->setHigh(fr->uhigh());
+ }
+
+ return;
+ }
+
+ // find min/max
+ fr->setMin(DBL_MAX, Vector());
+ fr->setMax(-DBL_MAX, Vector());
+ fr->setLow(DBL_MAX);
+ fr->setHigh(-DBL_MAX);
+
+ switch (fr->clipScope()) {
+ case FrScale::GLOBAL:
+ updateClipGlobal(fr);
+ break;
+ case FrScale::LOCAL:
+ updateClipLocal(fr);
+ break;
+ }
+
+ if (DebugPerf)
+ cerr << *fr << endl;
+}
+
+#ifdef __WIN32
+
+void Context::updateClipGlobal(FrScale* fr)
+{
+ FitsImage* ptr = fits;
+ while (ptr) {
+ FitsImage* sptr = ptr;
+ while (sptr) {
+ sptr->updateClip(fr);
+ sptr = sptr->nextSlice();
+ }
+ ptr = ptr->nextMosaic();
+ }
+
+ // set min/max low/high
+ ptr = fits;
+ while (ptr) {
+ FitsImage* sptr = ptr;
+ while (sptr) {
+ if (fr->min() > sptr->min())
+ fr->setMin(sptr->min(), sptr->minXY());
+ if (fr->max() < sptr->max())
+ fr->setMax(sptr->max(), sptr->maxXY());
+
+ if (fr->low() > sptr->low())
+ fr->setLow(sptr->low());
+ if (fr->high() < sptr->high())
+ fr->setHigh(sptr->high());
+
+ sptr = sptr->nextSlice();
+ }
+
+ ptr = ptr->nextMosaic();
+ }
+
+ // sanity check
+ if (fr->min() == DBL_MAX && fr->max() == -DBL_MAX) {
+ fr->setMin(NAN, Vector());
+ fr->setMax(NAN, Vector());
+ }
+ if (fr->low() == DBL_MAX && fr->high() == -DBL_MAX) {
+ fr->setLow(NAN);
+ fr->setHigh(NAN);
+ }
+
+ ptr = fits;
+ while (ptr) {
+ FitsImage* sptr = ptr;
+ while (sptr) {
+ sptr->setClip(fr->low(), fr->high());
+ sptr = sptr->nextSlice();
+ }
+ ptr = ptr->nextMosaic();
+ }
+}
+
+void Context::updateClipLocal(FrScale* fr)
+{
+ FitsImage* ptr = cfits;
+ while (ptr) {
+ ptr->updateClip(fr);
+ ptr = ptr->nextMosaic();
+ }
+
+ // set min/max low/high
+ ptr = cfits;
+ while (ptr) {
+ if (fr->min() > ptr->min())
+ fr->setMin(ptr->min(), ptr->minXY());
+ if (fr->max() < ptr->max())
+ fr->setMax(ptr->max(), ptr->maxXY());
+
+ if (fr->low() > ptr->low())
+ fr->setLow(ptr->low());
+ if (fr->high() < ptr->high())
+ fr->setHigh(ptr->high());
+
+ ptr = ptr->nextMosaic();
+ }
+
+ // sanity check
+ if (fr->min() == DBL_MAX && fr->max() == -DBL_MAX) {
+ fr->setMin(NAN, Vector());
+ fr->setMax(NAN, Vector());
+ }
+ if (fr->low() == DBL_MAX && fr->high() == -DBL_MAX) {
+ fr->setLow(NAN);
+ fr->setHigh(NAN);
+ }
+}
+
+#else
+
+void Context::updateClipGlobal(FrScale* fr)
+{
+ if (thread_)
+ delete [] thread_;
+ thread_ = new pthread_t[parent_->nthreads_];
+ t_clip_arg* targ = new t_clip_arg[parent_->nthreads_];
+
+ int cnt =0;
+ FitsImage* ptr = fits;
+ while (ptr) {
+ FitsImage* sptr = ptr;
+ while (sptr) {
+ sptr->updateClip(fr, &thread_[cnt], &targ[cnt]);
+
+ cnt++;
+ if (cnt == parent_->nthreads_) {
+ for (int ii=0; ii<cnt; ii++) {
+ int rr = pthread_join(thread_[ii], NULL);
+ if (rr)
+ internalError("Unable to Join Thread");
+ }
+ cnt =0;
+ }
+ sptr = sptr->nextSlice();
+ }
+ ptr = ptr->nextMosaic();
+ }
+
+ for (int ii=0; ii<cnt; ii++) {
+ int rr = pthread_join(thread_[ii], NULL);
+ if (rr)
+ internalError("Unable to Join Thread");
+ }
+
+ delete [] targ;
+ delete [] thread_;
+ thread_ =NULL;
+
+ // set min/max low/high
+ ptr = fits;
+ while (ptr) {
+ FitsImage* sptr = ptr;
+ while (sptr) {
+ if (fr->min() > sptr->min())
+ fr->setMin(sptr->min(), sptr->minXY());
+ if (fr->max() < sptr->max())
+ fr->setMax(sptr->max(), sptr->maxXY());
+
+ if (fr->low() > sptr->low())
+ fr->setLow(sptr->low());
+ if (fr->high() < sptr->high())
+ fr->setHigh(sptr->high());
+
+ sptr = sptr->nextSlice();
+ }
+ ptr = ptr->nextMosaic();
+ }
+
+ // sanity check
+ if (fr->min() == DBL_MAX && fr->max() == -DBL_MAX) {
+ fr->setMin(NAN, Vector());
+ fr->setMax(NAN, Vector());
+ }
+ if (fr->low() == DBL_MAX && fr->high() == -DBL_MAX) {
+ fr->setLow(NAN);
+ fr->setHigh(NAN);
+ }
+
+ ptr = fits;
+ while (ptr) {
+ FitsImage* sptr = ptr;
+ while (sptr) {
+ sptr->setClip(fr->low(), fr->high());
+ sptr = sptr->nextSlice();
+ }
+ ptr = ptr->nextMosaic();
+ }
+}
+
+void Context::updateClipLocal(FrScale* fr)
+{
+ if (thread_)
+ delete [] thread_;
+ thread_ = new pthread_t[parent_->nthreads_];
+ t_clip_arg* targ = new t_clip_arg[parent_->nthreads_];
+
+ int cnt =0;
+ FitsImage* ptr = cfits;
+ while (ptr) {
+ ptr->updateClip(fr, &thread_[cnt], &targ[cnt]);
+
+ cnt++;
+ if (cnt == parent_->nthreads_) {
+ for (int ii=0; ii<cnt; ii++) {
+ int rr = pthread_join(thread_[ii], NULL);
+ if (rr)
+ internalError("Unable to Join Thread");
+ }
+ cnt =0;
+ }
+ ptr = ptr->nextMosaic();
+ }
+
+ for (int ii=0; ii<cnt; ii++) {
+ int rr = pthread_join(thread_[ii], NULL);
+ if (rr)
+ internalError("Unable to Join Thread");
+ }
+
+ delete [] targ;
+ delete [] thread_;
+ thread_ =NULL;
+
+ // set min/max low/high
+ ptr = cfits;
+ while (ptr) {
+ if (fr->min() > ptr->min())
+ fr->setMin(ptr->min(), ptr->minXY());
+ if (fr->max() < ptr->max())
+ fr->setMax(ptr->max(), ptr->maxXY());
+
+ if (fr->low() > ptr->low())
+ fr->setLow(ptr->low());
+ if (fr->high() < ptr->high())
+ fr->setHigh(ptr->high());
+
+ ptr = ptr->nextMosaic();
+ }
+
+ // sanity check
+ if (fr->min() == DBL_MAX && fr->max() == -DBL_MAX) {
+ fr->setMin(NAN, Vector());
+ fr->setMax(NAN, Vector());
+ }
+ if (fr->low() == DBL_MAX && fr->high() == -DBL_MAX) {
+ fr->setLow(NAN);
+ fr->setHigh(NAN);
+ }
+}
+
+#endif
+
+void Context::updateContours()
+{
+ fvcontour_.update(cfits);
+}
+
+void Context::updateContoursScale()
+{
+ fvcontour_.update(cfits,&frScale);
+}
+
+void Context::updateContours(const Matrix& mx)
+{
+ if (!cfits)
+ return;
+
+ // aux contours
+ if (auxcontours_.head())
+ do
+ auxcontours_.current()->updateCoords(mx);
+ while (auxcontours_.next());
+
+ List<ContourLevel>& cc = fvcontour_.lcontourlevel();
+ if (cc.head())
+ do
+ cc.current()->updateCoords(mx);
+ while (cc.next());
+}
+
+void Context::updateSlice(int id, int ss)
+{
+ // ranges 1-n
+ if (!fits)
+ return;
+
+ // check bounds
+ if (ss<1)
+ ss = 1;
+ else if (ss>naxis_[id])
+ ss = naxis_[id];
+
+ slice_[id] = ss;
+
+ int cnt =slice_[2];
+ for (int jj=3; jj<FTY_MAXAXES; jj++) {
+ int cc =1;
+ for (int ii=2; ii<jj; ii++)
+ cc *= naxis_[ii];
+ cnt += (slice_[jj]-1) * cc;
+ }
+
+ cfits = fits;
+ for (int ii=1; ii<cnt; ii++)
+ if (cfits)
+ cfits = cfits->nextSlice();
+}
+
+int Context::updateClipScope(FrScale::ClipScope ss)
+{
+ if (frScale.clipScope() != ss) {
+ frScale.setClipScope(ss);
+ return 1;
+ }
+ return 0;
+}
+
+int Context::updateClipMode(FrScale::ClipMode mm)
+{
+ if (frScale.clipMode() != mm) {
+ frScale.setClipMode(mm);
+ return 1;
+ }
+ return 0;
+}
+
+int Context::updateClipMode(float per)
+{
+ if (per == 100)
+ return updateClipMode(FrScale::MINMAX);
+ else {
+ if (frScale.clipMode() != FrScale::AUTOCUT || frScale.autoCutPer() != per) {
+ frScale.setClipMode(FrScale::AUTOCUT);
+ frScale.setAutoCutPer(per);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int Context::updateMinMax(FrScale::MinMaxMode mm, int ss)
+{
+ if (frScale.minmaxMode() != mm || frScale.minmaxSample() != ss) {
+ frScale.setMinMaxMode(mm);
+ frScale.setMinMaxSample(ss);
+ return 1;
+ }
+ return 0;
+}
+
+// backward compatibility backup
+int Context::updateMinMaxMode(FrScale::MinMaxMode mm)
+{
+ if (frScale.minmaxMode() != mm) {
+ frScale.setMinMaxMode(mm);
+ return 1;
+ }
+ return 0;
+}
+
+// backward compatibility backup
+int Context::updateMinMaxSample(int ss)
+{
+ if (frScale.minmaxSample() != ss) {
+ frScale.setMinMaxSample(ss);
+ return 1;
+ }
+ return 0;
+}
+
+int Context::updateUser(float ll, float hh)
+{
+ if (frScale.ulow() != ll || frScale.uhigh() != hh) {
+ frScale.setULow(ll);
+ frScale.setUHigh(hh);
+ return 1;
+ }
+ return 0;
+}
+
+int Context::updateZscale(float cc, int ss, int ll)
+{
+ if (frScale.zContrast() != cc ||
+ frScale.zSample() != ss ||
+ frScale.zLine() != ll) {
+ frScale.setZContrast(cc);
+ frScale.setZSample(ss);
+ frScale.setZLine(ll);
+ return 1;
+ }
+ return 0;
+}
+
+// backward compatibility backup
+int Context::updateZscaleContrast(float cc)
+{
+ if (frScale.zContrast() != cc) {
+ frScale.setZContrast(cc);
+ return 1;
+ }
+ return 0;
+}
+
+// backward compatibility backup
+int Context::updateZscaleSample(int ss)
+{
+ if (frScale.zSample() != ss) {
+ frScale.setZSample(ss);
+ return 1;
+ }
+ return 0;
+}
+
+// backward compatibility backup
+int Context::updateZscaleLine(int ll)
+{
+ if (frScale.zLine() != ll) {
+ frScale.setZLine(ll);
+ return 1;
+ }
+ return 0;
+}
+
+int Context::updateDataSec(int ii)
+{
+ if (frScale.datasec() != ii) {
+ frScale.setDataSec(ii);
+ return 1;
+ }
+ return 0;
+}
+
+int Context::updateExpo(double exp)
+{
+ if (frScale.expo() != exp) {
+ frScale.setExpo(exp);
+ return 1;
+ }
+ return 0;
+}