vircam_platesol.c

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

Generated on 7 Feb 2011 for VIRCAM Pipeline by  doxygen 1.6.1