// Copyright (C) 1999-2018 // Smithsonian Astrophysical Observatory, Cambridge, MA, USA // For conditions of distribution and use, see copyright notice in "copyright" #include "base.h" #include "context.h" #include "fitsimage.h" #include "projection.h" extern "C" { #include "tkbltVector.h" } #include "sigbus.h" static int dCompare(const void* a, const void* b) { double* aa = (double*)a; double* bb = (double*)b; if (*aa < *bb) return -1; if (*aa > *bb) return 1; return 0; } void Base::markerAnalysisHistogram(Marker* pp, double** x, double** y, const BBox& bb, int num) { // does not extend across mosaic boundries // uses currentContext FitsImage* ptr = isInCFits(pp->getCenter(),Coord::REF,NULL); if (!ptr) ptr = currentContext->cfits; int srcw = ptr->width(); FitsBound* params = ptr->getDataParams(currentContext->secMode()); double min =DBL_MAX; double max =-DBL_MAX; // take the bbox and extend to lower/upper pixel boundaries Vector ll = (bb.ll*ptr->refToData).floor(); Vector ur = (bb.ur*ptr->refToData).ceil(); int msize = int(ur[1]-ll[1])*int(ur[0]-ll[0]); double* marr = new double[msize]; int* mask = new int[msize]; memset(marr,0,msize*sizeof(double)); memset(mask,0,msize*sizeof(int)); // main loop SETSIGBUS int cnt =0; for (int jj=ll[1]; jj=params->xmin && iixmax && jj>=params->ymin && jjymax) { // shift to center of pixel in DATA Vector rr = Vector(ii,jj)+Vector(.5,.5); Vector ss = rr*ptr->dataToRef; if (pp->isIn(ss,Coord::REF)) { double val =ptr->getValueDouble(long(jj)*srcw+long(ii)); // check for nan if (isfinite(val)) { marr[cnt] =val; mask[cnt] =1; if (valmax) max =val; } } } } } CLEARSIGBUS // sanity check if (num<1) num = 1; // we need one extra max,0 value at the end int nn = num+1; *x = (double*)malloc(nn*sizeof(double)); *y = (double*)malloc(nn*sizeof(double)); memset(*x,0,nn*sizeof(double)); memset(*y,0,nn*sizeof(double)); double diff = max-min; int last = num-1; double* xx = *x; double* yy = *y; // check if we have any data if (!isfinite(diff)) goto end; if (diff>0) { for (int ii=0; ii=min && val<=max) yy[(int)((val-min)/diff*last+.5)]++; } } } else { for (int ii=0; iicfits; FitsBound* params = sptr->getDataParams(currentContext->secMode()); if (width==0) width =1; // main loop SETSIGBUS for (int ii=0; iicfits; params = sptr->getDataParams(currentContext->secMode()); } do { Vector zz = tt * sptr->refToData; if (zz[0]>=params->xmin && zz[0]xmax && zz[1]>=params->ymin && zz[1]ymax) { if (!found) { Vector tv = sptr->mapFromRef(tt, sys, sky); (*xc)[ii] = tv[0]; (*yc)[ii] = tv[1]; found =1; } // check for nan double dd = sptr->getValueDouble(zz); if (isfinite(dd)) { (*y)[ii] += dd; cnt[ii]++; } break; } else { if (mosaic) { sptr = sptr->nextMosaic(); if (sptr) params = sptr->getDataParams(currentContext->secMode()); } } } while (mosaic && sptr); } } CLEARSIGBUS // average if needed if (method == Marker::AVERAGE) for (long ii=0; iigetCenter(),Coord::REF,NULL); if (!ptr) ptr = currentContext->fits; // if more than 3 axes, walk it forward int num = currentContext->calcSlice(); for (int ii=1; iinextSlice(); FitsBound* params = ptr->getDataParams(currentContext->secMode()); FitsZBound* zparams=currentContext->getDataParams(currentContext->secMode()); int srcw = ptr->width(); int srcd = zparams->zmax - zparams->zmin; // slice jump vector FitsImage* sjv[srcd]; FitsImage* sptr = ptr; for (int ii=0; iizmin; ii++) sptr = sptr->nextSlice(); for (int ii=0; iinextSlice(); } // init *x = (double*)malloc(srcd*sizeof(double)); *y = (double*)malloc(srcd*sizeof(double)); memset(*x,0,srcd*sizeof(double)); memset(*y,0,srcd*sizeof(double)); int* cnt = new int[srcd]; memset(cnt,0,srcd*sizeof(int)); // take the bbox and extend to lower/upper pixel boundaries Vector ll = (bb.ll*ptr->refToData).floor(); Vector ur = (bb.ur*ptr->refToData).ceil(); // mask int ss = (ur[0]-ll[0])*(ur[1]-ll[1]); bool* msk = new bool[ss]; long* idx = new long[ss]; memset(msk,0,ss*sizeof(bool)); memset(idx,0,ss*sizeof(long)); bool* mptr=msk; long* iptr=idx; if (!pp->isFixed()) { Matrix bck = pp->bckMatrix(); for (int jj=ll[1]; jj=params->xmin && iixmax && jj>=params->ymin && jjymax) { // shift to center of pixel in DATA Vector rr = Vector(ii,jj)+Vector(.5,.5); if (pp->isIn(rr*ptr->dataToRef,bck)) { *mptr=1; *iptr=long(jj)*srcw+long(ii); } } } } } else { for (int jj=ll[1]; jj=params->xmin && iixmax && jj>=params->ymin && jjymax) { // shift to center of pixel in DATA Vector rr = Vector(ii,jj)+Vector(.5,.5); if (pp->isIn(rr*ptr->dataToRef,Coord::REF)) { *mptr=1; *iptr=long(jj)*srcw+long(ii); } } } } } // main loop SETSIGBUS for (int kk=0; kkzmin; Vector3d dd = Vector3d(ptr->center(),tt) * Translate3d(-.5,-.5,-.5); Vector3d out = ptr->mapFromRef(dd,sys,Coord::FK5); (*x)[kk] = out[2]; bool* mptr=msk; long* iptr=idx; for (int ll=0; llgetValueDouble(*iptr); // check for nan if (isfinite(val)) { (*y)[kk] += val; cnt[kk]++; } } } } CLEARSIGBUS // average if needed if (method == Marker::AVERAGE) for (long kk=0; kkgetCenter(),Coord::REF,NULL); if (!ptr) ptr = currentContext->cfits; int srcw = ptr->width(); FitsBound* params = ptr->getDataParams(currentContext->secMode()); double sum[num]; memset(sum,0,num*sizeof(double)); int cnt[num]; memset(cnt,0,num*sizeof(int)); for (int kk=0; kkrefToData).floor(); Vector ur = (bb[kk+1].ur*ptr->refToData).ceil(); // main loop SETSIGBUS for (int jj=ll[1]; jj=params->xmin && iixmax && jj>=params->ymin && jjymax) { // shift to center of pixel in DATA Vector rr = Vector(ii,jj)+Vector(.5,.5); Vector ss = rr*ptr->dataToRef; if (pp->isIn(ss,Coord::REF,kk+1) && !pp->isIn(ss,Coord::REF,kk)) { double val =ptr->getValueDouble(long(jj)*srcw+long(ii)); // check for nan if (isfinite(val)) { sum[kk] += val; cnt[kk]++; } } } } } CLEARSIGBUS } *x = (double*)malloc(num*sizeof(double)); *y = (double*)malloc(num*sizeof(double)); *e = (double*)malloc(num*sizeof(double)); int unit =0; double xaxis =1; if (ptr->hasWCS(sys)) { double ll = ptr->getWCSSize(sys); if (ptr->hasWCSCel(sys)) { unit =1; xaxis = ll*60*60; } else { unit =2; xaxis = ll; } } double rr = ptr->getWCSSize(sys); double aa = rr*rr; for (int kk=0; kkgetCenter(),Coord::REF,NULL); if (!ptr) ptr = currentContext->cfits; int srcw = ptr->width(); FitsBound* params = ptr->getDataParams(currentContext->secMode()); double sum[num]; memset(sum,0,num*sizeof(double)); int cnt[num]; memset(cnt,0,num*sizeof(int)); for (int kk=0; kkrefToData).floor(); Vector ur = (bb[kk+1].ur*ptr->refToData).ceil(); // main loop SETSIGBUS for (int jj=ll[1]; jj=params->xmin && iixmax && jj>=params->ymin && jjymax) { // shift to center of pixel in DATA Vector rr = Vector(ii,jj)+Vector(.5,.5); Vector ss = rr*ptr->dataToRef; if (pp->isIn(ss,Coord::REF,kk+1,angnum) && !pp->isIn(ss,Coord::REF,kk,angnum)) { double val =ptr->getValueDouble(long(jj)*srcw+long(ii)); // check for nan if (isfinite(val)) { sum[kk] += val; cnt[kk]++; } } } } } CLEARSIGBUS } *x = (double*)malloc(num*sizeof(double)); *y = (double*)malloc(num*sizeof(double)); *e = (double*)malloc(num*sizeof(double)); int unit =0; double xaxis =1; if (ptr->hasWCS(sys)) { double ll = ptr->getWCSSize(sys); if (ptr->hasWCSCel(sys)) { unit =1; xaxis = ll*60*60; } else { unit =2; xaxis = ll; } } double rr = ptr->getWCSSize(sys); double aa = rr*rr; for (int kk=0; kkgetCenter(),Coord::REF,NULL); if (!ptr) ptr = currentContext->cfits; int srcw = ptr->width(); FitsBound* params = ptr->getDataParams(currentContext->secMode()); double sum =0; double sum2 =0; int cnt =0; double min =DBL_MAX; double max =-DBL_MAX; // take the bbox and extend to lower/upper pixel boundaries Vector ll = (bb.ll*ptr->refToData).floor(); Vector ur = (bb.ur*ptr->refToData).ceil(); int msize = int(ur[1]-ll[1])*int(ur[0]-ll[0]); double* marr = new double[msize]; memset(marr,0,msize*sizeof(double)); // main loop SETSIGBUS for (int jj=ll[1]; jj=params->xmin && iixmax && jj>=params->ymin && jjymax) { // shift to center of pixel in DATA Vector rr = Vector(ii,jj)+Vector(.5,.5); Vector ss = rr*ptr->dataToRef; if (pp->isIn(ss,Coord::REF)) { double val =ptr->getValueDouble(long(jj)*srcw+long(ii)); // check for nan if (isfinite(val)) { sum += val; sum2 += val*val; if (cntmax) max =val; cnt++; } } } } } CLEARSIGBUS qsort((void*)marr,cnt,sizeof(double),dCompare); double median = marr[int(cnt/2.)]; if (marr) delete [] marr; int unit = markerAnalysisStats1(pp,ptr,str,sys,sky); if (cnt) markerAnalysisStats2(ptr,str,sys,0,cnt,sum,unit); markerAnalysisStats3(str); if (cnt) markerAnalysisStats4(str,0,cnt,sum,sum2,median,min,max); } // for annulus regions void Base::markerAnalysisStats(Marker* pp, ostream& str, int num, BBox* bb, Coord::CoordSystem sys, Coord::SkyFrame sky) { // does not extend across mosaic boundries // uses currentContext FitsImage* ptr = isInCFits(pp->getCenter(),Coord::REF,NULL); if (!ptr) ptr = currentContext->cfits; int srcw = ptr->width(); FitsBound* params = ptr->getDataParams(currentContext->secMode()); double sum[num]; memset(sum,0,num*sizeof(double)); double sum2[num]; memset(sum2,0,num*sizeof(double)); int cnt[num]; memset(cnt,0,num*sizeof(int)); double min[num]; double max[num]; for (int ii=0; iirefToData).floor(); Vector ur = (bb[kk+1].ur*ptr->refToData).ceil(); int msize = int(ur[1]-ll[1])*int(ur[0]-ll[0]); double* marr = new double[msize]; memset(marr,0,msize*sizeof(double)); // main loop SETSIGBUS for (int jj=ll[1]; jj=params->xmin && iixmax && jj>=params->ymin && jjymax) { // shift to center of pixel in DATA Vector rr = Vector(ii,jj)+Vector(.5,.5); Vector ss = rr*ptr->dataToRef; if (pp->isIn(ss,Coord::REF,kk+1) && !pp->isIn(ss,Coord::REF,kk)) { double val =ptr->getValueDouble(long(jj)*srcw+long(ii)); // check for nan if (isfinite(val)) { sum[kk] += val; sum2[kk] += val*val; if (cnt[kk]max[kk]) max[kk] =val; cnt[kk]++; } } } } } CLEARSIGBUS qsort((void*)marr,cnt[kk],sizeof(double),dCompare); median[kk] = marr[int(cnt[kk]/2.)]; if (marr) delete [] marr; } int unit = markerAnalysisStats1(pp,ptr,str,sys,sky); for (int kk=0; kkgetCenter(),Coord::REF,NULL); if (!ptr) ptr = currentContext->cfits; int srcw = ptr->width(); FitsBound* params = ptr->getDataParams(currentContext->secMode()); double sum[num][na]; memset(sum,0,num*na*sizeof(double)); double sum2[num][na]; memset(sum2,0,num*na*sizeof(double)); int cnt[num][na]; memset(cnt,0,num*na*sizeof(int)); double min[num][na]; double max[num][na]; for (int ii=0; iirefToData).floor(); Vector ur = (bb[kk+1].ur*ptr->refToData).ceil(); int msize = int(ur[1]-ll[1])*int(ur[0]-ll[0]); double* marr = new double[msize]; // main loop SETSIGBUS for (int qq=0; qq=params->xmin && iixmax && jj>=params->ymin && jjymax) { // shift to center of pixel in DATA Vector rr = Vector(ii,jj)+Vector(.5,.5); Vector ss = rr*ptr->dataToRef; if (pp->isIn(ss,Coord::REF,kk+1,qq) && !pp->isIn(ss,Coord::REF,kk,qq)) { double val =ptr->getValueDouble(long(jj)*srcw+long(ii)); // check for nan if (isfinite(val)) { sum[kk][qq] += val; sum2[kk][qq] += val*val; if (cnt[kk][qq]max[kk][qq]) max[kk][qq] = val; cnt[kk][qq]++; } } } } } qsort((void*)marr,cnt[kk][qq],sizeof(double),dCompare); median[kk][qq] = marr[int(cnt[kk][qq]/2.)]; } CLEARSIGBUS if (marr) delete [] marr; } int unit = markerAnalysisStats1(pp,ptr,str,sys,sky); for (int kk=0; kkgetWCSSize(sys); if (ptr->hasWCSCel(sys)) { str << "1 pixel = "<< ll*60*60 << " arcsec"; str << endl << endl; str << "reg\t" << "sum\t\t" << "error\t" << "area\t\t" << "surf_bri\t\t" << "surf_err" << endl << "\t" << "\t" << "\t\t" << "(arcsec**2)\t\t" << "(sum/arcsec**2)\t" << "(sum/arcsec**2)" << endl << "---\t" << "---\t\t" << "-----\t" << "-----------\t\t" << "---------------\t" << "---------------" << endl; return 1; } else { str << "1 pixel = "<< ll; str << endl << endl; str << "reg\t" << "sum\t\t" << "error\t" << "area\t\t" << "surf_bri\t\t" << "surf_err" << endl << "\t" << "\t" << "\t\t" << "(pix**2)\t\t" << "(sum/pix**2)\t\t" << "(sum/pix**2)" << endl << "---\t" << "---\t\t" << "-----\t" << "--------\t\t" << "------------\t\t" << "------------" << endl; return 2; } } break; } } void Base::markerAnalysisStats2(FitsImage* ptr, ostream& str, Coord::CoordSystem sys, int kk, int cnt, double sum, int unit) { double area =0; switch (unit) { case 0: // pixels area = cnt; break; case 1: { // Cel WCS double rr = ptr->getWCSSize(sys); double aa = rr*rr; area = aa*60*60*60*60*cnt; } break; case 2: { // Linear WCS double rr = ptr->getWCSSize(sys); double aa = rr*rr; area = aa*cnt; } break; } double err = sqrt(fabs(sum)); double bri = sum/area; double brierr = err/area; str << kk+1 << '\t' << setprecision(8) << sum << "\t\t" << setprecision(6) << err << "\t" << area << "\t\t" << bri << "\t\t" << brierr << endl; } void Base::markerAnalysisStats3(ostream& str) { str << endl << "reg\t" << "sum\t" << "npix\t" << "mean\t" << "median\t" << "min\t" << "max\t" << "var\t" << "stddev\t" << "rms\t" << endl << "---\t" << "---\t" << "----\t" << "----\t" << "------\t" << "---\t" << "---\t" << "---\t" << "------\t" << "---\t" << endl; } void Base::markerAnalysisStats4(ostream& str, int kk, double cnt, double sum, double sum2, double median, double min, double max) { // up cast int cnt to double to avoid int overflow double mean =0; double std =0; double var =0; double rms =0; if (cnt) { mean = sum/cnt; var = fabs(sum2/cnt - (sum*sum)/(cnt*cnt)); std = sqrt(var); rms = sqrt(sum2/cnt); } str << kk+1 << '\t' << setprecision(8) << sum << '\t' << cnt << '\t' << setprecision(6) << mean << '\t' << median << '\t' << min << '\t' << max << '\t' << var << '\t' << std << '\t' << rms << '\t' << endl; } void Base::bltCut(char* xname, char* yname, Coord::Orientation axis, const Vector& rr, int thick, Base::CutMethod method) { int size; if (axis == Coord::XX) size = options->width; else size = options->height; long length = (size+1) * 2; double* xx = (double*)malloc(sizeof(double)*length); double* yy = (double*)malloc(sizeof(double)*length); // check for data or undefined low()/high() if (!currentContext->cfits || !isfinite(currentContext->low())) { for (int ii=0; ii<=size; ii++) { xx[ii*2] = ii; xx[ii*2+1] = ii; yy[ii*2] = 0; yy[ii*2+1] = 0; } } else bltCutFits(xx, yy, size, axis, rr, thick, method); Blt_Vector* xv; if (Blt_GetVector(interp, xname, &xv) != TCL_OK) goto error; if (Blt_ResetVector(xv, xx, length, length*sizeof(double), TCL_DYNAMIC) != TCL_OK) goto error; Blt_Vector* yv; if (Blt_GetVector(interp, yname, &yv) != TCL_OK) goto error; if (Blt_ResetVector(yv, yy, length, length*sizeof(double), TCL_DYNAMIC) != TCL_OK) goto error; return; error: result = TCL_ERROR; return; } void Base::bltCutFits(double* xx, double* yy, int size, Coord::Orientation axis, const Vector& r, int thick, Base::CutMethod method) { Vector rr = r * refToWidget; FitsImage* sptr = currentContext->cfits; FitsBound* params = sptr->getDataParams(currentContext->secMode()); int mosaic = isMosaic(); double prev = currentContext->low(); // main loop SETSIGBUS for (int ii=0; ii<=size; ii++) { double vv =0; int cnt =0; Vector img; int ww = thick/2; for (int jj=0; jjcfits; params = sptr->getDataParams(currentContext->secMode()); } do { if (axis == Coord::XX) img = Vector(1+ii,rr[1]-ww+jj) * sptr->widgetToData; else img = Vector(rr[0]-ww+jj,1+ii) * sptr->widgetToData; if (img[0]>=params->xmin && img[0]xmax && img[1]>=params->ymin && img[1]ymax) { double value = sptr->getValueDouble(img); if (isfinite(value)) { vv += value; cnt +=1; } break; } else { if (mosaic) { sptr = sptr->nextMosaic(); if (sptr) params = sptr->getDataParams(currentContext->secMode()); } } } while (mosaic && sptr); } xx[2*ii] = ii; xx[2*ii +1] = ii; yy[2*ii] = prev; switch (method) { case Base::AVERAGE: if (cnt) yy[2*ii +1] = prev = vv/cnt; else yy[2*ii +1] = prev = currentContext->low(); break; case Base::SUM: yy[2*ii +1] = prev = vv; break; } } CLEARSIGBUS }