vircam_platesol.c

00001 /* $Id: vircam_platesol.c,v 1.31 2012/01/15 17:40:09 jim Exp $
00002  *
00003  * This file is part of the VIRCAM Pipeline
00004  * Copyright (C) 2005 Cambridge Astronomy Survey Unit
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: jim $
00023  * $Date: 2012/01/15 17:40:09 $
00024  * $Revision: 1.31 $
00025  * $Name: vcam-1_3_2 $
00026  */
00027 
00028 /* Includes */
00029 
00030 #ifdef HAVE_CONFIG_H
00031 #include <config.h>
00032 #endif
00033 
00034 #include <cpl.h>
00035 #include <math.h>
00036 
00037 #include "vircam_mods.h"
00038 #include "vircam_utils.h"
00039 #include "vircam_wcsutils.h"
00040 #include "vircam_stats.h"
00041 #include "vircam_pfits.h"
00042 
00043 static double *work = NULL;
00044 static unsigned char *iwork = NULL;
00045 
00046 static int vircam_plate6(double *xpos, double *ypos, double *xi, double *eta,
00047                          unsigned char *flag, int nstds, double *a, double *b,
00048                          double *c, double *d, double *e, double *f);
00049 static int vircam_plate4(double *xpos, double *ypos, double *xi, double *eta,
00050                          unsigned char *flag, int nstds, double *a, double *b,
00051                          double *c, double *d, double *e, double *f);
00052 static void tidy(void);
00053 
00056 /*---------------------------------------------------------------------------*/
00129 /*---------------------------------------------------------------------------*/
00130 
00131 extern int vircam_platesol(cpl_propertylist *plist, cpl_propertylist *tlist,
00132                            cpl_table *matchedstds, int nconst, int shiftan, 
00133                            int *status) {
00134     int nstds,nc2,i,niter,nrej,ngood,nreq=6,xcol,ycol;
00135     long n1,n2;
00136     const char *fctid = "vircam_platesol";
00137     float *tptr;
00138     double *xptr,*yptr,*xptr2,*yptr2,*ra,*dec,*xiptr,*etaptr,*wptr,averr;
00139     double r1,r2,d1,d2,newcrval1,newcrval2,a,b,c,d,e,f,xifit,etafit,dxi,deta;
00140     double crpix1,crpix2,xi,eta,rac_before,rac_after,decc_before,decc_after;
00141     double xcen,ycen,oldtheta,scale,oldcrpix1,oldcrpix2;
00142     const double *crdata;
00143     unsigned char *isbad,*wptr2;
00144     const char *reqcols[] = {"X_coordinate","Y_coordinate","xpredict",
00145                              "ypredict","RA","Dec"};
00146     char key[9];
00147     cpl_wcs *wcs;
00148     const cpl_array *cr;
00149     const cpl_matrix *crm;
00150 
00151     /* Inherited status */
00152 
00153     if (*status != VIR_OK)
00154         return(*status);
00155 
00156     /* Check the value of nconst */
00157 
00158     if (nconst != 4 && nconst != 6) {
00159         cpl_msg_error(fctid,
00160                       "Value of nconst = %" CPL_SIZE_FORMAT " is unsupported",
00161                       (cpl_size)nconst);
00162         FATAL_ERROR
00163     }
00164 
00165     /* How many standards are in the input matched standards table? */
00166 
00167     nstds = (int)cpl_table_get_nrow(matchedstds);
00168     nc2 = nconst/2;
00169     if (nstds < nc2) {
00170         cpl_msg_error(fctid,
00171                       "Too few standards (%" CPL_SIZE_FORMAT ") in table for %" CPL_SIZE_FORMAT " coefficient fit",
00172                       (cpl_size)nstds,(cpl_size)nconst);
00173         FATAL_ERROR
00174     }
00175 
00176     /* Check that the matched standards table has all the required columns */
00177 
00178     for (i = 0; i < nreq; i++) {
00179         if (cpl_table_has_column(matchedstds,reqcols[i]) != 1) {
00180             cpl_msg_error(fctid,"Matched standards table missing column %s\n",
00181                           reqcols[i]);
00182             FATAL_ERROR
00183         }
00184     }
00185             
00186     /* Get some workspace now */
00187 
00188     work = cpl_malloc(10*nstds*sizeof(*work));
00189     iwork = cpl_calloc(3*nstds,sizeof(*isbad));
00190     xptr = work;
00191     yptr = work + nstds;
00192     xptr2 = work + 2*nstds;
00193     yptr2 = work + 3*nstds;
00194     ra = work + 4*nstds;
00195     dec = work + 5*nstds;
00196     xiptr = work + 6*nstds;
00197     etaptr = work + 7*nstds;
00198     wptr = work + 8*nstds;
00199     isbad = iwork;
00200     wptr2 = iwork + nstds;
00201     
00202     /* Get the data from the table and put it all into double precision
00203        arrays */
00204 
00205     tptr = cpl_table_get_data_float(matchedstds,"X_coordinate");
00206     for (i = 0; i < nstds; i++)
00207         xptr[i] = (double)tptr[i];
00208     tptr = cpl_table_get_data_float(matchedstds,"Y_coordinate");
00209     for (i = 0; i < nstds; i++)
00210         yptr[i] = (double)tptr[i];
00211     tptr = cpl_table_get_data_float(matchedstds,"xpredict");
00212     for (i = 0; i < nstds; i++)
00213         xptr2[i] = (double)tptr[i];
00214     tptr = cpl_table_get_data_float(matchedstds,"ypredict");
00215     for (i = 0; i < nstds; i++)
00216         yptr2[i] = (double)tptr[i];
00217     tptr = cpl_table_get_data_float(matchedstds,"RA");
00218     for (i = 0; i < nstds; i++)
00219         ra[i] = (double)tptr[i];
00220     tptr = cpl_table_get_data_float(matchedstds,"Dec");
00221     for (i = 0; i < nstds; i++)
00222         dec[i] = (double)tptr[i];
00223 
00224     /* If you want to shift the RA and Dec of the tangent point, then
00225        do that now */
00226 
00227     newcrval1 = 0.0;
00228     newcrval2 = 0.0;
00229     if (shiftan) {
00230         wcs = cpl_wcs_new_from_propertylist(plist);
00231         cr = cpl_wcs_get_crval(wcs);
00232         crdata = cpl_array_get_data_double_const(cr);
00233         for (i = 0; i < nstds; i++) {
00234             vircam_xytoradec(wcs,xptr[i],yptr[i],&r1,&d1);
00235             vircam_xytoradec(wcs,xptr2[i],yptr2[i],&r2,&d2);
00236             xiptr[i] = r2 - r1;
00237             etaptr[i] = d2 - d1;
00238         }
00239         r1 = vircam_dmed(xiptr,NULL,nstds);
00240         d1 = vircam_dmed(etaptr,NULL,nstds);
00241         newcrval1 = crdata[0] + r1;
00242         newcrval2 = crdata[1] + d1;
00243         cpl_propertylist_update_double(plist,"CRVAL1",newcrval1);
00244         cpl_propertylist_update_double(plist,"CRVAL2",newcrval2);
00245         cpl_wcs_delete(wcs);
00246     }
00247 
00248     /* Calculate the central RA and Dec */
00249 
00250     wcs = cpl_wcs_new_from_propertylist(plist);
00251     (void)vircam_pfits_get_naxis1(plist,&n1);
00252     (void)vircam_pfits_get_naxis2(plist,&n2);
00253     cr = cpl_wcs_get_crpix(wcs);
00254     crdata = cpl_array_get_data_double_const(cr);
00255     oldcrpix1 = crdata[0];
00256     oldcrpix2 = crdata[1];
00257     xcen = 0.5*(double)n1;
00258     ycen = 0.5*(double)n2;
00259     vircam_xytoradec(wcs,xcen,ycen,&rac_before,&decc_before);
00260 
00261     /* Right, calculate xi and eta for each of the standards */
00262 
00263     for (i = 0; i < nstds; i++) {
00264         vircam_radectoxieta(wcs,ra[i],dec[i],&xi,&eta);
00265         xiptr[i] = xi;
00266         etaptr[i] = eta;
00267     }
00268 
00269     /* Right, now loop for maximum number of iterations or until
00270        convergence */
00271 
00272     niter = 0;
00273     while (niter >= 0) {
00274 
00275         /* Do a plate solution */
00276 
00277         switch (nconst) {
00278         case 6:
00279             *status = vircam_plate6(xptr,yptr,xiptr,etaptr,isbad,nstds,&a,&b,
00280                                     &c,&e,&d,&f);
00281             break;
00282         case 4:
00283             *status = vircam_plate4(xptr,yptr,xiptr,etaptr,isbad,nstds,&a,&b,
00284                                     &c,&e,&d,&f);
00285             break;
00286         default:
00287             *status = vircam_plate6(xptr,yptr,xiptr,etaptr,isbad,nstds,&a,&b,
00288                                     &c,&e,&d,&f);
00289             break;
00290         }
00291         if (*status != VIR_OK) {
00292             cpl_msg_error(fctid,"Plate constant solution failed");
00293             tidy();
00294             FATAL_ERROR
00295         }
00296 
00297         /* Now look at the residuals and see if any should be rejected */
00298 
00299         for (i = 0; i < nstds; i++) {
00300             xifit = xptr[i]*a + yptr[i]*b + c;
00301             etafit = xptr[i]*d + yptr[i]*e + f;
00302             dxi = fabs(xifit - xiptr[i]);
00303             deta = fabs(etafit - etaptr[i]);
00304             wptr[i*2] = dxi;
00305             wptr[i*2+1] = deta;
00306             wptr2[i*2] = isbad[i];
00307             wptr2[i*2+1] = isbad[i];
00308         }
00309         averr = vircam_dmed(wptr,wptr2,2*nstds);
00310         averr *= 1.48;
00311         if (niter == 3)
00312             break;
00313         nrej = 0;
00314         ngood = 0;
00315         for (i = 0; i < nstds; i++) {
00316             if (!isbad[i] && (wptr[i*2] > 3.0*averr || wptr[i*2+1] > 3.0*averr))                nrej++;
00317             if (!isbad[i])
00318                 ngood++;
00319         }
00320         ngood -= nrej;
00321         if (nrej == 0 || ngood < nconst)
00322             break;
00323         for (i = 0; i < nstds; i++) {
00324             if (!isbad[i] && (wptr[i*2] > 3.0*averr || wptr[i*2+1] > 3.0*averr))                isbad[i] = 1;
00325         }
00326         niter++;
00327     }
00328 
00329     /* Convert values to degrees now */
00330 
00331     crpix1 = (e*c - b*f)/(d*b - e*a);
00332     crpix2 = (a*f - d*c)/(d*b - e*a);
00333     a *= DEGRAD;
00334     b *= DEGRAD;
00335     d *= DEGRAD;
00336     e *= DEGRAD;
00337 
00338     /* Number of good points fit and average error in arcsec*/
00339 
00340     ngood = 0;
00341     for (i = 0; i < nstds; i++)
00342         if (! isbad[i])
00343             ngood++;
00344     averr *= DEGRAD*3600.0;
00345 
00346     /* Right, now update the header */
00347 
00348     cpl_propertylist_update_double(plist,"CRPIX1",crpix1);
00349     cpl_propertylist_update_double(plist,"CRPIX2",crpix2);
00350     cpl_propertylist_update_double(plist,"CD1_1",a);
00351     cpl_propertylist_update_double(plist,"CD1_2",b);
00352     cpl_propertylist_update_double(plist,"CD2_1",d);
00353     cpl_propertylist_update_double(plist,"CD2_2",e);
00354     cpl_propertylist_update_int(plist,"ESO DRS NUMBRMS",ngood);
00355     cpl_propertylist_set_comment(plist,"ESO DRS NUMBRMS",
00356                                  "Number of stars in WCS fit");
00357     cpl_propertylist_update_float(plist,"ESO DRS STDCRMS",(float)averr);
00358     cpl_propertylist_set_comment(plist,"ESO DRS STDCRMS",
00359                                  "[arcsec] Average error in WCS fit");
00360 
00361     /* Calculate the central RA and Dec again */
00362 
00363     crm = cpl_wcs_get_cd(wcs);
00364     crdata = cpl_matrix_get_data_const(crm);
00365     oldtheta = 0.5*(fabs(atan2(crdata[1],crdata[0])) + 
00366                     fabs(atan2(crdata[2],crdata[3])));
00367     cpl_wcs_delete(wcs);
00368     wcs = cpl_wcs_new_from_propertylist(plist);
00369     vircam_xytoradec(wcs,xcen,ycen,&rac_after,&decc_after);
00370     xcen = 3600.0*(rac_after - rac_before);
00371     ycen = 3600.0*(decc_after - decc_before);
00372     cpl_propertylist_update_float(plist,"ESO DRS WCSRAOFF",(float)xcen);
00373     cpl_propertylist_set_comment(plist,"ESO DRS WCSRAOFF",
00374                                  "[arcsec] cenpix RA_after - RA_before)");
00375     cpl_propertylist_update_float(plist,"ESO DRS WCSDECOFF",(float)ycen);
00376     cpl_propertylist_set_comment(plist,"ESO DRS WCSDECOFF",
00377                                  "[arcsec] cenpix Dec_after - Dec_before)");
00378 
00379     /* Update the table header */
00380 
00381     if (tlist != NULL) {
00382         xcol = vircam_findcol(tlist,"X");
00383         ycol = vircam_findcol(tlist,"Y");
00384         if (xcol != -1 && ycol != -1) {
00385             snprintf(key,9,"TCRPX%d",xcol);
00386             cpl_propertylist_update_double(tlist,key,crpix1);
00387             snprintf(key,9,"TCRPX%d",ycol);
00388             cpl_propertylist_update_double(tlist,key,crpix2);
00389             if (shiftan) {
00390                 snprintf(key,9,"TCRVL%d",xcol);
00391                 cpl_propertylist_update_double(tlist,key,newcrval1);
00392                 snprintf(key,9,"TCRVL%d",ycol);
00393                 cpl_propertylist_update_double(tlist,key,newcrval2);
00394             }
00395             snprintf(key,9,"TC%d_%d",xcol,xcol);
00396             cpl_propertylist_update_double(tlist,key,a);
00397             snprintf(key,9,"TC%d_%d",xcol,ycol);
00398             cpl_propertylist_update_double(tlist,key,b);
00399             snprintf(key,9,"TC%d_%d",ycol,xcol);
00400             cpl_propertylist_update_double(tlist,key,d);
00401             snprintf(key,9,"TC%d_%d",ycol,ycol);
00402             cpl_propertylist_update_double(tlist,key,e);
00403             cpl_propertylist_update_int(tlist,"ESO DRS NUMBRMS",ngood);
00404             cpl_propertylist_set_comment(tlist,"ESO DRS NUMBRMS",
00405                                          "Number of stars in WCS fit");
00406             cpl_propertylist_update_float(tlist,"ESO DRS STDCRMS",(float)averr);
00407             cpl_propertylist_set_comment(tlist,"ESO DRS STDCRMS",
00408                                          "[arcsec] Average error in WCS fit");
00409             cpl_propertylist_update_float(tlist,"ESO DRS WCSRAOFF",(float)xcen);
00410             cpl_propertylist_set_comment(tlist,"ESO DRS WCSRAOFF",
00411                                          "[arcsec] cenpix RA_after - RA_before)");
00412             cpl_propertylist_update_float(tlist,"ESO DRS WCSDECOFF",(float)ycen);
00413             cpl_propertylist_set_comment(tlist,"ESO DRS WCSDECOFF",
00414                                          "[arcsec] cenpix Dec_after - Dec_before)");
00415         }
00416     }
00417 
00418     /* Back-calculate a crval for the old value of crpix. Compare to the 
00419        WCS crval and write to QC header */
00420 
00421     cr = cpl_wcs_get_crval(wcs);
00422     crdata = cpl_array_get_data_double_const(cr);
00423     vircam_xytoradec(wcs,oldcrpix1,oldcrpix2,&rac_after,&decc_after);
00424     rac_after -= crdata[0];
00425     decc_after -= crdata[1];
00426     cpl_propertylist_update_float(plist,"ESO QC WCS_DCRVAL1",(float)rac_after);
00427     cpl_propertylist_set_comment(plist,"ESO QC WCS_DCRVAL1",
00428                                  "[deg] change in crval1");
00429     cpl_propertylist_update_float(plist,"ESO QC WCS_DCRVAL2",(float)decc_after);
00430     cpl_propertylist_set_comment(plist,"ESO QC WCS_DCRVAL2",
00431                                  "[deg] change in crval2");
00432 
00433     /* Work out the change in the rotation */
00434 
00435     crm = cpl_wcs_get_cd(wcs);
00436     crdata = cpl_matrix_get_data_const(crm);
00437     oldtheta = 0.5*(fabs(atan2(crdata[1],crdata[0])) + 
00438                     fabs(atan2(crdata[2],crdata[3]))) - oldtheta;
00439     oldtheta *= DEGRAD;
00440     cpl_propertylist_update_float(plist,"ESO QC WCS_DTHETA",(float)oldtheta);
00441     cpl_propertylist_set_comment(plist,"ESO QC WCS_DTHETA",
00442                                  "[deg] change in rotation");
00443     
00444     /* Work out the mean plate scale */
00445 
00446     scale = 1800.0*(sqrt(pow(crdata[0],2.0) +  pow(crdata[1],2.0)) + 
00447                     sqrt(pow(crdata[2],2.0) +  pow(crdata[3],2.0)));
00448     cpl_propertylist_update_float(plist,"ESO QC WCS_SCALE",(float)scale);
00449     cpl_propertylist_set_comment(plist,"ESO QC WCS_SCALE",
00450                                  "[arcsec] mean plate scale");
00451 
00452     /* Work out the shear of this new WCS */
00453 
00454     oldtheta = fabs(atan2(crdata[1],crdata[0])) - 
00455         fabs(atan2(crdata[2],crdata[3]));
00456     cpl_propertylist_update_float(plist,"ESO QC WCS_SHEAR",(float)oldtheta);
00457     cpl_propertylist_set_comment(plist,"ESO QC WCS_SHEAR",
00458                                  "[deg] abs(xrot) - abs(yrot)");
00459 
00460     /* Now just add in the RMS */
00461 
00462     cpl_propertylist_update_float(plist,"ESO QC WCS_RMS",(float)averr);
00463     cpl_propertylist_set_comment(plist,"ESO QC WCS_RMS",
00464                                  "[arcsec] Average error in WCS fit");
00465 
00466     /* Right, get out of here now... */
00467 
00468     cpl_wcs_delete(wcs);
00469     tidy();
00470     GOOD_STATUS
00471 }
00472 
00473 /*---------------------------------------------------------------------------*/
00512 /*---------------------------------------------------------------------------*/
00513 
00514 extern int vircam_platexy(cpl_table *matchedxy, int nconst, cpl_array **coefs, 
00515                           int *status) {
00516     const char *fctid = "vircam_platexy";
00517     int nxy,nc2,i,niter,nrej,ngood;
00518     unsigned char *isbad,*wptr2;
00519     double *xptr1,*xptr2,*yptr1,*yptr2,*wptr,a,b,c,d,e,f,*cc,xfit,yfit;
00520     double dx,dy,averr;
00521     float *tptr;
00522     int nreq = 4;
00523     const char *reqcols[] = {"X_coordinate_1","Y_coordinate_1","X_coordinate_2",
00524                              "Y_coordinate_2"};
00525 
00526     /* Inherited status */
00527 
00528     *coefs = NULL;
00529     if (*status != VIR_OK)
00530         return(*status);
00531 
00532     /* Check the value of nconst */
00533 
00534     if (nconst != 4 && nconst != 6) {
00535         cpl_msg_error(fctid,
00536                       "Value of nconst = %" CPL_SIZE_FORMAT " is unsupported",
00537                       (cpl_size)nconst);
00538         FATAL_ERROR
00539     }
00540 
00541     /* How many objects are in the input table? */
00542 
00543     nxy = (int)cpl_table_get_nrow(matchedxy);
00544     nc2 = nconst/2;
00545     if (nxy < nc2) {
00546         cpl_msg_error(fctid,
00547                       "Too few objects (%" CPL_SIZE_FORMAT ") in table for %" CPL_SIZE_FORMAT " coefficient fit",
00548                       (cpl_size)nxy,(cpl_size)nconst);
00549         FATAL_ERROR
00550     }
00551 
00552     /* Check that the matched standards table has all the required columns */
00553 
00554     for (i = 0; i < nreq; i++) {
00555         if (cpl_table_has_column(matchedxy,reqcols[i]) != 1) {
00556             cpl_msg_error(fctid,"Input table missing column %s\n",reqcols[i]);
00557             FATAL_ERROR
00558         }
00559     }
00560             
00561     /* Get some workspace now */
00562 
00563     work = cpl_malloc(6*nxy*sizeof(*work));
00564     iwork = cpl_calloc(3*nxy,sizeof(*isbad));
00565     xptr1 = work;
00566     yptr1 = work + nxy;
00567     xptr2 = work + 2*nxy;
00568     yptr2 = work + 3*nxy;
00569     wptr = work + 4*nxy;
00570     isbad = iwork;
00571     wptr2 = iwork + nxy;
00572     
00573     /* Get the data from the table and put it all into double precision
00574        arrays */
00575 
00576     tptr = cpl_table_get_data_float(matchedxy,"X_coordinate_1");
00577     for (i = 0; i < nxy; i++)
00578         xptr1[i] = (double)tptr[i];
00579     tptr = cpl_table_get_data_float(matchedxy,"Y_coordinate_1");
00580     for (i = 0; i < nxy; i++)
00581         yptr1[i] = (double)tptr[i];
00582     tptr = cpl_table_get_data_float(matchedxy,"X_coordinate_2");
00583     for (i = 0; i < nxy; i++)
00584         xptr2[i] = (double)tptr[i];
00585     tptr = cpl_table_get_data_float(matchedxy,"Y_coordinate_2");
00586     for (i = 0; i < nxy; i++)
00587         yptr2[i] = (double)tptr[i];
00588 
00589     /* Right, now loop for maximum number of iterations or until
00590        convergence */
00591 
00592     niter = 0;
00593     while (niter >= 0) {
00594 
00595         /* Do a plate solution */
00596 
00597         switch (nconst) {
00598         case 6:
00599             *status = vircam_plate6(xptr2,yptr2,xptr1,yptr1,isbad,nxy,&a,&b,
00600                                     &c,&e,&d,&f);
00601             break;
00602         case 4:
00603             *status = vircam_plate4(xptr2,yptr2,xptr1,yptr1,isbad,nxy,&a,&b,
00604                                     &c,&e,&d,&f);
00605             break;
00606         default:
00607             *status = vircam_plate6(xptr2,yptr2,xptr1,yptr1,isbad,nxy,&a,&b,
00608                                     &c,&e,&d,&f);
00609             break;
00610         }
00611         if (*status != VIR_OK) {
00612             cpl_msg_error(fctid,"Plate constant solution failed");
00613             tidy();
00614             FATAL_ERROR
00615         }
00616 
00617         /* Now look at the residuals and see if any should be rejected */
00618 
00619         for (i = 0; i < nxy; i++) {
00620             xfit = xptr2[i]*a + yptr2[i]*b + c;
00621             yfit = xptr2[i]*d + yptr2[i]*e + f;
00622             dx = fabs(xfit - xptr1[i]);
00623             dy = fabs(yfit - yptr1[i]);
00624             wptr[i*2] = dx;
00625             wptr[i*2+1] = dy;
00626             wptr2[i*2] = isbad[i];
00627             wptr2[i*2+1] = isbad[i];
00628         }
00629         averr = vircam_dmed(wptr,wptr2,2*nxy);
00630         averr *= 1.48;
00631         if (niter == 3)
00632             break;
00633         nrej = 0;
00634         ngood = 0;
00635         for (i = 0; i < nxy; i++) {
00636             if (!isbad[i] && (wptr[i*2] > 3.0*averr || wptr[i*2+1] > 3.0*averr))                nrej++;
00637             if (!isbad[i])
00638                 ngood++;
00639         }
00640         ngood -= nrej;
00641         if (nrej == 0 || ngood < nconst)
00642             break;
00643         for (i = 0; i < nxy; i++) {
00644             if (!isbad[i] && (wptr[i*2] > 3.0*averr || wptr[i*2+1] > 3.0*averr))                isbad[i] = 1;
00645         }
00646         niter++;
00647     }
00648 
00649     /* Set the output array */
00650 
00651     *coefs = cpl_array_new(6,CPL_TYPE_DOUBLE);
00652     cc = cpl_array_get_data_double(*coefs);
00653     cc[0] = a;
00654     cc[1] = b;
00655     cc[2] = c;
00656     cc[3] = d;
00657     cc[4] = e;
00658     cc[5] = f;
00659 
00660     /* Right, get out of here now... */
00661 
00662     tidy();
00663     GOOD_STATUS
00664 }
00665 
00666 /*---------------------------------------------------------------------------*/
00700 /*---------------------------------------------------------------------------*/
00701 
00702 static int vircam_plate6(double *xpos, double *ypos, double *xi, double *eta,
00703                          unsigned char *flag, int nstds, double *a, double *b,
00704                          double *c, double *d, double *e, double *f) {
00705     double sx1sq,sy1sq,sx1y1,sx1x2,sy1x2;
00706     double sy1y2,sx1y2,xposmean,yposmean,ximean,etamean,xx1,yy1,xx2,yy2;
00707     int i,ngood,nbad;
00708 
00709     /* Is it worthwhile even being here? */
00710 
00711     (void)vircam_sumbpm(flag,nstds,&nbad);
00712     ngood = nstds - nbad;
00713     if (ngood < 2)
00714         return(VIR_FATAL);
00715 
00716     /* Initialise all the counters and summations */
00717 
00718     sx1sq = 0.0;
00719     sy1sq = 0.0;
00720     sx1y1 = 0.0;
00721     sx1x2 = 0.0;
00722     sy1x2 = 0.0;
00723     sy1y2 = 0.0;
00724     sx1y2 = 0.0;
00725     xposmean = 0.0;
00726     yposmean = 0.0;
00727     ximean = 0.0;
00728     etamean = 0.0;
00729 
00730     /* Find means in each coordinate system */
00731 
00732     xposmean = vircam_dmean(xpos,flag,nstds);
00733     yposmean = vircam_dmean(ypos,flag,nstds);
00734     ximean = vircam_dmean(xi,flag,nstds);
00735     etamean = vircam_dmean(eta,flag,nstds);
00736 
00737     /* Now accumulate the sums */
00738 
00739     for (i = 0; i < nstds; i++) {
00740         if (!flag[i]) {
00741             xx1 = xpos[i] - xposmean;
00742             yy1 = ypos[i] - yposmean;
00743             xx2 = xi[i] - ximean;
00744             yy2 = eta[i] - etamean;
00745             sx1sq += xx1*xx1;
00746             sy1sq += yy1*yy1;
00747             sx1y1 += xx1*yy1;
00748             sx1x2 += xx1*xx2;
00749             sy1x2 += yy1*xx2;
00750             sy1y2 += yy1*yy2;
00751             sx1y2 += xx1*yy2;
00752         }
00753     }
00754 
00755     /* Do solution for X */
00756 
00757     *a = (sx1y1*sy1x2 - sx1x2*sy1sq)/(sx1y1*sx1y1 - sx1sq*sy1sq);
00758     *b = (sx1x2*sx1y1 - sx1sq*sy1x2)/(sx1y1*sx1y1 - sx1sq*sy1sq);
00759     *c = -xposmean*(*a) - yposmean*(*b) + ximean;
00760 
00761     /* Now the solution for Y */
00762 
00763     *d = (sx1y1*sx1y2 - sy1y2*sx1sq)/(sx1y1*sx1y1 - sy1sq*sx1sq);
00764     *e = (sy1y2*sx1y1 - sy1sq*sx1y2)/(sx1y1*sx1y1 - sy1sq*sx1sq);
00765     *f = -xposmean*(*e) - yposmean*(*d) + etamean;
00766 
00767     /* Get outta here */
00768 
00769     return(VIR_OK);
00770 }
00771 
00772 /*---------------------------------------------------------------------------*/
00806 /*---------------------------------------------------------------------------*/
00807 
00808 static int vircam_plate4(double *xpos, double *ypos, double *xi, double *eta,
00809                          unsigned char *flag, int nstds, double *a, double *b,
00810                          double *c, double *d, double *e, double *f) {
00811     double sx1sq,sy1sq,sx1x2,sy1x2,sy1y2,sx1y2,xposmean,yposmean;
00812     double ximean,etamean,xx1,yy1,xx2,yy2,det,num,denom,theta,mag;
00813     double stheta,ctheta;
00814     int i,ngood,nbad;
00815 
00816     /* Is it worthwhile even being here? */
00817 
00818     (void)vircam_sumbpm(flag,nstds,&nbad);
00819     ngood = nstds - nbad;
00820     if (ngood < 2)
00821         return(VIR_FATAL);
00822 
00823     /* Initialise all the counters and summations */
00824 
00825     sx1sq = 0.0;
00826     sy1sq = 0.0;
00827     sx1x2 = 0.0;
00828     sy1x2 = 0.0;
00829     sy1y2 = 0.0;
00830     sx1y2 = 0.0;
00831     xposmean = 0.0;
00832     yposmean = 0.0;
00833     ximean = 0.0;
00834     etamean = 0.0;
00835 
00836     /* Find means in each coordinate system */
00837 
00838     xposmean = vircam_dmean(xpos,flag,nstds);
00839     yposmean = vircam_dmean(ypos,flag,nstds);
00840     ximean = vircam_dmean(xi,flag,nstds);
00841     etamean = vircam_dmean(eta,flag,nstds);
00842 
00843     /* Now accumulate the sums */
00844 
00845     for (i = 0; i < nstds; i++) {
00846         if (!flag[i]) {
00847             xx1 = xpos[i] - xposmean;
00848             yy1 = ypos[i] - yposmean;
00849             xx2 = xi[i] - ximean;
00850             yy2 = eta[i] - etamean;
00851             sx1sq += xx1*xx1;
00852             sy1sq += yy1*yy1;
00853             sx1x2 += xx1*xx2;
00854             sy1x2 += yy1*xx2;
00855             sy1y2 += yy1*yy2;
00856             sx1y2 += xx1*yy2;
00857         }
00858     }
00859 
00860     /* Compute the rotation angle */
00861 
00862     det = sx1x2*sy1y2 - sy1x2*sx1y2;
00863     if (det < 0.0) {
00864         num = sy1x2 + sx1y2;
00865         denom = -sx1x2 + sy1y2;
00866     } else {
00867         num = sy1x2 - sx1y2;
00868         denom = sx1x2 + sy1y2;
00869     }
00870     if (num == 0.0 && denom == 0.0) {
00871         theta = 0.0;
00872     } else {
00873         theta = atan2(num,denom);
00874         if (theta < 0.0)
00875             theta += CPL_MATH_2PI;
00876     }
00877 
00878     /* Compute magnification factor */
00879 
00880     ctheta = cos(theta);
00881     stheta = sin(theta);
00882     num = denom*ctheta  + num*stheta;
00883     denom = sx1sq + sy1sq;
00884     if (denom <= 0.0) {
00885         mag = 1.0;
00886     } else {
00887         mag = num/denom;
00888     }
00889 
00890     /* Compute coeffs */
00891 
00892     if (det < 0.0) {
00893         *a = -mag*ctheta;
00894         *e = mag*stheta;
00895     } else {
00896         *a = mag*ctheta;
00897         *e = -mag*stheta;
00898     }
00899     *b = mag*stheta;
00900     *d = mag*ctheta;
00901     *c = -xposmean*(*a) - yposmean*(*b) + ximean;
00902     *f = -xposmean*(*e) - yposmean*(*d) + etamean;
00903 
00904     /* Get outta here */
00905 
00906     return(VIR_OK);
00907 }
00908 
00909 static void tidy(void) {
00910 
00911     freespace(work);
00912     freespace(iwork);
00913 }
00914 
00918 /*
00919 
00920 $Log: vircam_platesol.c,v $
00921 Revision 1.31  2012/01/15 17:40:09  jim
00922 Minor modifications to take into accout the changes in cpl API for v6
00923 
00924 Revision 1.30  2010/06/30 12:42:00  jim
00925 A few fixes to stop compiler compaints
00926 
00927 Revision 1.29  2010/06/07 12:42:40  jim
00928 Modifications to get rid of compiler gripes
00929 
00930 Revision 1.28  2009/12/11 06:53:35  jim
00931 Minor changes to documentation
00932 
00933 Revision 1.27  2009/09/09 09:47:55  jim
00934 uses CPL defined macros for constants
00935 
00936 Revision 1.26  2009/05/20 12:21:01  jim
00937 Fixed to update TCRVL values when the tangent point is shifted
00938 
00939 Revision 1.25  2008/11/25 06:22:33  jim
00940 Added prologue for vircam_platexy
00941 
00942 Revision 1.24  2008/11/21 10:12:10  jim
00943 Added vircam_platexy
00944 
00945 Revision 1.23  2008/10/21 08:42:28  jim
00946 Fixed some declarations to make them constant
00947 
00948 Revision 1.22  2008/07/10 13:05:53  jim
00949 Modified to use v4.2 version of cpl_wcs
00950 
00951 Revision 1.21  2008/05/06 08:40:10  jim
00952 Modified to use cpl_wcs interface
00953 
00954 Revision 1.20  2008/01/22 19:46:10  jim
00955 Fixed sign error in plate4
00956 
00957 Revision 1.19  2007/10/25 17:34:01  jim
00958 Modified to remove lint warnings
00959 
00960 Revision 1.18  2007/05/03 11:15:33  jim
00961 Fixed little problem with table wcs
00962 
00963 Revision 1.17  2007/05/02 09:12:30  jim
00964 Modified to update table header WCS keywords
00965 
00966 Revision 1.16  2007/03/29 12:19:39  jim
00967 Little changes to improve documentation
00968 
00969 Revision 1.15  2007/03/01 12:42:42  jim
00970 Modified slightly after code checking
00971 
00972 Revision 1.14  2007/01/17 23:54:01  jim
00973 Plugged some memory leaks
00974 
00975 Revision 1.13  2007/01/08 19:12:03  jim
00976 Fixed shear comment so that it doesn't overflow
00977 
00978 Revision 1.12  2006/10/02 13:43:50  jim
00979 Added missing .h file
00980 
00981 Revision 1.11  2006/08/11 12:45:41  jim
00982 Modified to use wcslib
00983 
00984 Revision 1.10  2006/06/14 14:33:31  jim
00985 Fixed units of WCS_SCALE
00986 
00987 Revision 1.9  2006/06/13 14:09:38  jim
00988 Made some of the QC header values single precision
00989 
00990 Revision 1.8  2006/06/09 11:26:26  jim
00991 Small changes to keep lint happy
00992 
00993 Revision 1.7  2006/05/26 15:05:46  jim
00994 Fixed column names for input table
00995 
00996 Revision 1.6  2006/03/23 21:18:53  jim
00997 Minor changes mainly to comment headers
00998 
00999 Revision 1.5  2006/03/22 14:05:37  jim
01000 fixed a little bug
01001 
01002 Revision 1.4  2006/03/22 13:58:32  jim
01003 Cosmetic fixes to keep lint happy
01004 
01005 Revision 1.3  2006/03/15 10:43:41  jim
01006 Fixed a few things
01007 
01008 Revision 1.2  2006/02/22 14:19:52  jim
01009 Modified to check for the existence of the columns in the matched standards
01010 table.
01011 
01012 Revision 1.1  2006/02/18 11:52:34  jim
01013 new file
01014 
01015 
01016 */

Generated on 5 Mar 2013 for VIRCAM Pipeline by  doxygen 1.6.1