HlRadCirc.hxx

Go to the documentation of this file.
00001 
00002 
00003 
00004 //-----------------------------------------------------------------------------
00005 // SVN: $Id: HlRadCirc.hxx 6558 2010-01-19 18:38:52Z RossCollins $
00006 //-----------------------------------------------------------------------------
00007 #ifndef HLRADCIRC_H
00008 #define HLRADCIRC_H
00009 
00010 // We will make use of AST for operations involving WCS
00011 extern "C"
00012 {
00013   #include "slalib.h"
00014   #include "ast.h"
00015 }
00016 #include <float.h>
00017 
00018 #include <algorithm>
00019 #include "Constants.h"
00020 #include "DataMethod.hxx"
00021 #include "FitsFile.h"
00022 #include "StringOps.h"
00023 #include "Logger.h"
00024 #include "DataOps.h"
00025 #include "Converter.h"
00026 
00027 //-----------------------------------------------------------------------------
00032 template<typename DataType>
00033 class HlRadCirc : public DataMethod<DataType>
00034 {
00035 public:
00037     HlRadCirc(const FitsFile& aCatFile, const FitsFile& aFile)
00038       : mCatFile(aCatFile),mFile(aFile)
00039    {
00040      DataMethod<DataType>::methodName = "HlRadCirc";
00041    }
00042 
00044   virtual ~HlRadCirc() { }
00045 
00046   //---------------------------------------------------------------------------
00048   void setSource(IntMap& tbls, IntMap& cols, StringMap units)
00049   {
00050     afColNo[0]=0;
00051     afeColNo[0]=0;
00052 
00053     for (int i=0;i<NOAPERS-1;++i)
00054     {
00055       afColNo[i+1]  = cols[2*i];
00056       afeColNo[i+1] = cols[2*i+1];
00057     }
00058     pfColNo    = cols[26];
00059     extColNo   = cols[27];
00060 
00061     //xpsColNo   = cols[30]; // Both x and y?
00062     //ypsColNo   = cols[31];
00063 
00064 
00065   }
00066   //---------------------------------------------------------------------------
00068   void setTarget(IntMap& cols, StringMap units)
00069   {
00070     hlCircColNo   = cols[0];
00071     hlCErrColNo   = cols[1];
00072 
00073   }
00074   //---------------------------------------------------------------------------
00076   void doit(TableData<DataType>& data, int row1, int row2)
00077   {
00078     Logger log;
00079 
00080     double apertures[NOAPERS]={0.,0.5,sqrt(0.5),1.,sqrt(2.),2.,2.*sqrt(2.),4.,5.,6.,7.,8.,10.,12.}; // in arcsec -- use coreRadius to convert.
00081     double rCore[mCatFile.getNumHdus()];
00082     double crval1;
00083     double crval2;
00084     int npixx,npixy;
00085 
00086     double centre[2];
00087     double sizeFact[2];
00088     double pixelScale[mCatFile.getNumHdus()];
00089 
00090 
00091     // Set up AST
00092     astBegin;
00093     AstFitsChan *fitschan = astFitsChan(NULL, NULL, "%.*s", 0, "NULL");
00094 
00095     Converter conv;
00096     sizeFact[0]  = conv.getFactor("RADIANS", "Arcseconds");
00097     sizeFact[1]  = conv.getFactor("RADIANS", "Arcseconds");
00098 
00099     for (int hduNo = 2; hduNo <= mCatFile.getNumHdus(); ++hduNo)
00100     {
00101 
00102       int extNo = hduNo - 2;
00103 
00104 
00105       AstFrameSet *wcsinfo = 0;
00106 
00107       // Move to extension on the FITS file
00108       mCatFile.movabsHdu(hduNo);
00109       mFile.movabsHdu(hduNo);
00110       mCatFile.readKey("RCORE", rCore[extNo]);
00111 
00112       // Put all cards in the header of this extension into the AST
00113       // fits channel
00114       int ncards = mFile.getNumCards();
00115       for (int n = 0; n < ncards; ++n) {
00116           char card[80];
00117           mFile.readCard(n, card);
00118           astPutFits(fitschan, card, 0);
00119       }
00120 
00121 
00122       // Make AST wcsinfo object
00123       astClear( fitschan, "Card" );
00124 
00125       // Calc xpixSize,ypixSize
00126 
00127       mFile.readKey(FitsFile::CRVAL1, crval1);
00128       mFile.readKey(FitsFile::CRVAL2, crval2);
00129       if (crval1 == 0 && crval2 == 0) {
00130         log.addError("Could not read WCS info for " + mCatFile.getFileName());
00131       } else {
00132         wcsinfo = (AstFrameSet*)astRead(fitschan);
00133       }
00134 
00135       mCatFile.readKey("NXOUT", npixx);
00136       mCatFile.readKey("NYOUT", npixy);
00137       centre[0] = (double)npixx / 2;
00138       centre[1] = (double)npixy / 2;
00139       Numeric xPixSize,yPixSize;
00140 
00141       DataOps::calcPixSize(wcsinfo,centre,sizeFact,xPixSize,yPixSize);
00142       pixelScale[extNo]=sqrt(xPixSize*yPixSize);
00143 
00144     }
00145 
00146     for (int rowNo = row1; rowNo < row2; ++rowNo)
00147     {
00148       double extNum;
00149       data.value(extColNo, rowNo, extNum);
00150       int extNo=(int)(extNum-2);
00151 
00152       // Input aperture fluxes and errors
00153       double aperFlux[NOAPERS];
00154       double aperFluxErr[NOAPERS];
00155       //double xPixSize,yPixSize;
00156 
00157       double petroFlux;
00158       double totalFlux;
00159       // Use petrosian
00160       data.value(pfColNo, rowNo, petroFlux);
00161 
00162       double hlCirc=DefaultValues::realdef;
00163       double hlCErr=DefaultValues::realdef;
00164       // Get hlCirc
00165 
00166       // Put distort correction in magnitudes in separate
00167       // if no distortion correction in mags, none in radii
00168 
00169       // Get 5 nearest apertures
00170       // Fit quadratic using Least Squares
00171 
00172       if (petroFlux>0.)
00173       {
00174         int bestAper=0;
00175         bool isAperSet=false;
00176         totalFlux=petroFlux/0.9; // Over estimate for disks, under for ells
00177 
00178         for (int i=1;i<NOAPERS;++i)
00179         {
00180           data.value(afColNo[i], rowNo, aperFlux[i]);
00181           data.value(afeColNo[i], rowNo, aperFluxErr[i]);
00182           // Find radius where aperFlux~0.5*kronFlux
00183           if (aperFlux[i]>0.5*totalFlux && !isAperSet)
00184           {
00185             bestAper=i;
00186             isAperSet=true;
00187 
00188           }
00189 
00190         }
00191         aperFlux[0]=0.;
00192         aperFluxErr[0]=aperFluxErr[1];
00193         if (!isAperSet) bestAper=NOAPERS-1;
00194 
00195         // Find five best apertures
00196         int minAper = max(bestAper-int(floor(NDATAPNTS/2.)),0);
00197         int maxAper = min(minAper+NDATAPNTS,NOAPERS-1);
00198         if ((maxAper-minAper)<NDATAPNTS) minAper=maxAper-NDATAPNTS;
00199 
00200         // Now Get data, set up matrix for LSQ via SVN
00201         double matA[NDATAPNTS][NPOLY];
00202         double vecB[NDATAPNTS];
00203         double matW[NPOLY];
00204         double matV[NPOLY][NPOLY];
00205         double work[NPOLY];
00206         double xfit[NPOLY];
00207         double matC[NPOLY][NPOLY];
00208         int jstat;
00209         double minRadius=rCore[extNo]*apertures[minAper];
00210         double maxRadius=rCore[extNo]*apertures[minAper+NDATAPNTS-1];
00211 
00212 
00213         for (int j=0;j<NDATAPNTS;++j)
00214         {
00215 
00216             double radius;
00217             radius=rCore[extNo]*apertures[minAper+j];
00218             if (j==0) minRadius=radius;
00219             if (j==NDATAPNTS-1) maxRadius=radius;
00220             double frac=0.;
00221             double fracErr=1.;
00222 
00223             if (aperFlux[minAper+j]>=0.) {
00224                 frac=aperFlux[minAper+j]/totalFlux;
00225                 if (aperFluxErr[minAper+j]>0.) {
00226                     fracErr=aperFluxErr[minAper+j]/totalFlux;
00227                 }
00228             }
00229             double weight=1./fracErr;
00230             matA[j][0]=weight;
00231             vecB[j]=frac*weight;
00232             for (int k=0;k<NPOLY-1;++k) {
00233                 matA[j][k+1]=pow(radius,k+1)*weight;
00234             }
00235         }
00236 
00237          // Use SVD. Ax=0
00238         //
00239         cslaSvd(NDATAPNTS,NPOLY,NDATAPNTS,NPOLY, (double *) matA,matW, (double *) matV, work, &jstat);
00240          // @todo: set smallest SVD components to 0.
00241         // ratio should be no larger than 10^10 if dp.
00242         double maxSvd=*max_element(matW,matW+NPOLY);
00243         for (int j=0;j<NPOLY;++j)
00244         {
00245             if (matW[j]<=minSvdRatio*maxSvd) matW[j]=0;
00246 
00247         }
00248 
00249         cslaSvdsol(NDATAPNTS,NPOLY,NDATAPNTS,NPOLY,vecB,(double *) matA,matW,(double *) matV, work,xfit);
00250         cslaSvdcov(NPOLY,NPOLY,NPOLY,matW,(double *) matV, work, (double *) matC);
00251         //
00252         // Now get polynomial and find roots
00253         // Numerical recipes: zroots
00254         // Make sure roots are sensible
00255         double roots[2];
00256         // Find when polynomial fits data
00257         xfit[0]-=0.5;
00258         // Use Newton Raphson? --> general
00259         quadroots(xfit,roots); // replace by newraph
00260         // Find most likely root. Should be within range of data
00261         // Deblended objs and ones where there is a sudden turn down just
00262         // after half-light radius have larger hlradius than petroAper.
00263         // Do a few more checks
00264         bool hasMatch=false;
00265 
00266         for (int i=0;i<NPOLY-1;++i) {
00267           if (roots[i]>=minRadius && roots[i]<=maxRadius && !hasMatch) {
00268             hlCirc=roots[i];
00269             hasMatch=true;
00270           }
00271         }
00272         double sumCov=0.;
00273         double dfda[NPOLY];
00274         double dfdr=0;
00275         dfda[0]=1.;
00276 
00277         for (int i=0;i<NPOLY-1;++i)
00278         {
00279           dfda[i+1]=pow(hlCirc,i+1);
00280           dfdr+=pow(hlCirc,i)*(i+1)*xfit[i+1];
00281         }
00282         for (int i=0;i<NPOLY;++i) {
00283           for (int j=0;j<NPOLY;++j) {
00284               sumCov+=dfda[i]*dfda[j]*matC[i][j];
00285           }
00286         }
00287         double ferr=sqrt(sumCov);
00288         // Add pixel scale error in quarature
00289         if (hlCirc<0.) {
00290           hlCErr=DefaultValues::realdef;
00291         }  else if (abs(dfdr)>0.) {
00292           hlCirc=pixelScale[extNo]*hlCirc;
00293           hlCErr=pixelScale[extNo]*sqrt((ferr/dfdr)*(ferr/dfdr)+0.5*0.5);
00294         } else {
00295           hlCirc=pixelScale[extNo]*hlCirc;
00296           hlCErr=pixelScale[extNo]*0.5;
00297         }
00298 
00299 
00300       }
00301 
00302       data.assign(hlCircColNo, rowNo, hlCirc);
00303       data.assign(hlCErrColNo, rowNo, hlCErr);
00304 
00305     }
00306 
00307   }
00308 
00309   // No data from raw data included
00310   void doit2(TableData<DataType>& rawData, TableData<DataType>& data, int row1, int row2) { }
00311   //---------------------------------------------------------------------------
00312 
00313   void quadroots(double a[3], double roots[2]) {
00314     // Simple method to find quadratic roots
00315     double sq=a[1]*a[1]-4.*a[0]*a[2];
00316     if (sq>=0) {
00317         roots[0]=(-a[1]+sqrt(sq))/(2.*a[2]);
00318         roots[1]=(-a[1]-sqrt(sq))/(2.*a[2]);
00319     } else {
00320         roots[0]=DefaultValues::realdef;
00321         roots[1]=DefaultValues::realdef;
00322     }
00323   }
00324   //---------------------------------------------------------------------------
00325   double newrph(double poly[], double hlrE, double mnr, double mxr) {
00326     const double finalErr=1.0e-4;
00327     const int maxIter=5;
00328     double error=1.;
00329     int it=0;
00330     double hlr=hlrE;
00331     double dr=0;
00332     while (error>finalErr and it<maxIter) {
00333         double func=0;
00334         double dfdr=0;
00335         for (int i=0;i<NPOLY;++i) {
00336             func=poly[i]*pow(hlr,i);
00337             if (i>0) {
00338                 dfdr+=i*poly[i]*pow(hlr,(i-1));
00339             }
00340         }
00341         dr=func/dfdr;
00342         error=sqrt(func);
00343         hlr-=dr;
00344 
00345         it++;
00346     }
00347     // @todo: think about this
00348     if (hlr<mnr) hlr=mnr;
00349     if (hlr>mxr) hlr=mxr;
00350     return hlr;
00351   }
00352 private:
00353   const static unsigned short int NOAPERS=14;
00354   const static unsigned short int NDATAPNTS=5;
00355   const static unsigned short int NPOLY=3; // Quadratic
00356   const static double minSvdRatio=1.0e-10;
00357   FitsFile mCatFile;
00358   FitsFile mFile;
00359 
00360   int hlCircColNo;
00361   int hlCErrColNo;
00362   int afColNo[NOAPERS];
00363   int afeColNo[NOAPERS];
00364   int pfColNo;
00365   int extColNo;
00366 
00367 
00368 };
00369 //-----------------------------------------------------------------------------
00370 #endif
00371 //-----------------------------------------------------------------------------
00372 // Change log:
00373 //
00374 // 12-Nov-2009,  NJC: Original version.
Generated on Mon Oct 4 10:38:34 2010 for WfcamSrc by  doxygen 1.6.3