vircam_platesol.c

00001 /* $Id: vircam_platesol.c,v 1.22 2008/07/10 13:05:53 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: 2008/07/10 13:05:53 $
00024  * $Revision: 1.22 $
00025  * $Name:  $
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,*crdata;
00142     unsigned char *isbad,*wptr2;
00143     const char *reqcols[] = {"X_coordinate","Y_coordinate","xpredict",
00144                              "ypredict","RA","Dec"};
00145     char key[9];
00146     cpl_wcs *wcs;
00147     cpl_array *cr;
00148     cpl_matrix *crm;
00149 
00150     /* Inherited status */
00151 
00152     if (*status != VIR_OK)
00153         return(*status);
00154 
00155     /* Check the value of nconst */
00156 
00157     if (nconst != 4 && nconst != 6) {
00158         cpl_msg_error(fctid,"Value of nconst = %d is unsupported",nconst);
00159         FATAL_ERROR
00160     }
00161 
00162     /* How many standards are in the input matched standards table? */
00163 
00164     nstds = cpl_table_get_nrow(matchedstds);
00165     nc2 = nconst/2;
00166     if (nstds < nc2) {
00167         cpl_msg_error(fctid,
00168                       "Too few standards (%d) in table for %d coefficient fit",
00169                       nstds,nconst);
00170         FATAL_ERROR
00171     }
00172 
00173     /* Check that the matched standards table has all the required columns */
00174 
00175     for (i = 0; i < nreq; i++) {
00176         if (cpl_table_has_column(matchedstds,reqcols[i]) != 1) {
00177             cpl_msg_error(fctid,"Matched standards table missing column %s\n",
00178                           reqcols[i]);
00179             FATAL_ERROR
00180         }
00181     }
00182             
00183     /* Get some workspace now */
00184 
00185     work = cpl_malloc(10*nstds*sizeof(*work));
00186     iwork = cpl_calloc(3*nstds,sizeof(*isbad));
00187     xptr = work;
00188     yptr = work + nstds;
00189     xptr2 = work + 2*nstds;
00190     yptr2 = work + 3*nstds;
00191     ra = work + 4*nstds;
00192     dec = work + 5*nstds;
00193     xiptr = work + 6*nstds;
00194     etaptr = work + 7*nstds;
00195     wptr = work + 8*nstds;
00196     isbad = iwork;
00197     wptr2 = iwork + nstds;
00198     
00199     /* Get the data from the table and put it all into double precision
00200        arrays */
00201 
00202     tptr = cpl_table_get_data_float(matchedstds,"X_coordinate");
00203     for (i = 0; i < nstds; i++)
00204         xptr[i] = (double)tptr[i];
00205     tptr = cpl_table_get_data_float(matchedstds,"Y_coordinate");
00206     for (i = 0; i < nstds; i++)
00207         yptr[i] = (double)tptr[i];
00208     tptr = cpl_table_get_data_float(matchedstds,"xpredict");
00209     for (i = 0; i < nstds; i++)
00210         xptr2[i] = (double)tptr[i];
00211     tptr = cpl_table_get_data_float(matchedstds,"ypredict");
00212     for (i = 0; i < nstds; i++)
00213         yptr2[i] = (double)tptr[i];
00214     tptr = cpl_table_get_data_float(matchedstds,"RA");
00215     for (i = 0; i < nstds; i++)
00216         ra[i] = (double)tptr[i];
00217     tptr = cpl_table_get_data_float(matchedstds,"Dec");
00218     for (i = 0; i < nstds; i++)
00219         dec[i] = (double)tptr[i];
00220 
00221     /* If you want to shift the RA and Dec of the tangent point, then
00222        do that now */
00223 
00224     if (shiftan) {
00225         wcs = cpl_wcs_new_from_propertylist(plist);
00226         cr = cpl_wcs_get_crval(wcs);
00227         crdata = cpl_array_get_data_double(cr);
00228         for (i = 0; i < nstds; i++) {
00229             vircam_xytoradec(wcs,xptr[i],yptr[i],&r1,&d1);
00230             vircam_xytoradec(wcs,xptr2[i],yptr2[i],&r2,&d2);
00231             xiptr[i] = r2 - r1;
00232             etaptr[i] = d2 - d1;
00233         }
00234         r1 = vircam_dmed(xiptr,NULL,nstds);
00235         d1 = vircam_dmed(etaptr,NULL,nstds);
00236         newcrval1 = crdata[0] + r1;
00237         newcrval2 = crdata[1] + d1;
00238         cpl_propertylist_update_double(plist,"CRVAL1",newcrval1);
00239         cpl_propertylist_update_double(plist,"CRVAL2",newcrval2);
00240         cpl_wcs_delete(wcs);
00241     }
00242 
00243     /* Calculate the central RA and Dec */
00244 
00245     wcs = cpl_wcs_new_from_propertylist(plist);
00246     (void)vircam_pfits_get_naxis1(plist,&n1);
00247     (void)vircam_pfits_get_naxis2(plist,&n2);
00248     cr = cpl_wcs_get_crpix(wcs);
00249     crdata = cpl_array_get_data_double(cr);
00250     oldcrpix1 = crdata[0];
00251     oldcrpix2 = crdata[1];
00252     xcen = 0.5*(double)n1;
00253     ycen = 0.5*(double)n2;
00254     vircam_xytoradec(wcs,xcen,ycen,&rac_before,&decc_before);
00255 
00256     /* Right, calculate xi and eta for each of the standards */
00257 
00258     for (i = 0; i < nstds; i++) {
00259         vircam_radectoxieta(wcs,ra[i],dec[i],&xi,&eta);
00260         xiptr[i] = xi;
00261         etaptr[i] = eta;
00262     }
00263 
00264     /* Right, now loop for maximum number of iterations or until
00265        convergence */
00266 
00267     niter = 0;
00268     while (niter >= 0) {
00269 
00270         /* Do a plate solution */
00271 
00272         switch (nconst) {
00273         case 6:
00274             *status = vircam_plate6(xptr,yptr,xiptr,etaptr,isbad,nstds,&a,&b,
00275                                     &c,&e,&d,&f);
00276             break;
00277         case 4:
00278             *status = vircam_plate4(xptr,yptr,xiptr,etaptr,isbad,nstds,&a,&b,
00279                                     &c,&e,&d,&f);
00280             break;
00281         default:
00282             *status = vircam_plate6(xptr,yptr,xiptr,etaptr,isbad,nstds,&a,&b,
00283                                     &c,&e,&d,&f);
00284             break;
00285         }
00286         if (*status != VIR_OK) {
00287             cpl_msg_error(fctid,"Plate constant solution failed");
00288             tidy();
00289             FATAL_ERROR
00290         }
00291 
00292         /* Now look at the residuals and see if any should be rejected */
00293 
00294         for (i = 0; i < nstds; i++) {
00295             xifit = xptr[i]*a + yptr[i]*b + c;
00296             etafit = xptr[i]*d + yptr[i]*e + f;
00297             dxi = fabs(xifit - xiptr[i]);
00298             deta = fabs(etafit - etaptr[i]);
00299             wptr[i*2] = dxi;
00300             wptr[i*2+1] = deta;
00301             wptr2[i*2] = isbad[i];
00302             wptr2[i*2+1] = isbad[i];
00303         }
00304         averr = vircam_dmed(wptr,wptr2,2*nstds);
00305         averr *= 1.48;
00306         if (niter == 3)
00307             break;
00308         nrej = 0;
00309         ngood = 0;
00310         for (i = 0; i < nstds; i++) {
00311             if (!isbad[i] && (wptr[i*2] > 3.0*averr || wptr[i*2+1] > 3.0*averr))                nrej++;
00312             if (!isbad[i])
00313                 ngood++;
00314         }
00315         ngood -= nrej;
00316         if (nrej == 0 || ngood < nconst)
00317             break;
00318         for (i = 0; i < nstds; i++) {
00319             if (!isbad[i] && (wptr[i*2] > 3.0*averr || wptr[i*2+1] > 3.0*averr))                isbad[i] = 1;
00320         }
00321         niter++;
00322     }
00323 
00324     /* Convert values to degrees now */
00325 
00326     crpix1 = (e*c - b*f)/(d*b - e*a);
00327     crpix2 = (a*f - d*c)/(d*b - e*a);
00328     a *= DEGRAD;
00329     b *= DEGRAD;
00330     d *= DEGRAD;
00331     e *= DEGRAD;
00332 
00333     /* Number of good points fit and average error in arcsec*/
00334 
00335     ngood = 0;
00336     for (i = 0; i < nstds; i++)
00337         if (! isbad[i])
00338             ngood++;
00339     averr *= DEGRAD*3600.0;
00340 
00341     /* Right, now update the header */
00342 
00343     cpl_propertylist_update_double(plist,"CRPIX1",crpix1);
00344     cpl_propertylist_update_double(plist,"CRPIX2",crpix2);
00345     cpl_propertylist_update_double(plist,"CD1_1",a);
00346     cpl_propertylist_update_double(plist,"CD1_2",b);
00347     cpl_propertylist_update_double(plist,"CD2_1",d);
00348     cpl_propertylist_update_double(plist,"CD2_2",e);
00349     cpl_propertylist_update_int(plist,"ESO DRS NUMBRMS",ngood);
00350     cpl_propertylist_set_comment(plist,"ESO DRS NUMBRMS",
00351                                  "Number of stars in WCS fit");
00352     cpl_propertylist_update_float(plist,"ESO DRS STDCRMS",(float)averr);
00353     cpl_propertylist_set_comment(plist,"ESO DRS STDCRMS",
00354                                  "[arcsec] Average error in WCS fit");
00355 
00356     /* Calculate the central RA and Dec again */
00357 
00358     crm = cpl_wcs_get_cd(wcs);
00359     crdata = cpl_matrix_get_data(crm);
00360     oldtheta = 0.5*(fabs(atan2(crdata[1],crdata[0])) + 
00361                     fabs(atan2(crdata[2],crdata[3])));
00362     cpl_wcs_delete(wcs);
00363     wcs = cpl_wcs_new_from_propertylist(plist);
00364     vircam_xytoradec(wcs,xcen,ycen,&rac_after,&decc_after);
00365     xcen = 3600.0*(rac_after - rac_before);
00366     ycen = 3600.0*(decc_after - decc_before);
00367     cpl_propertylist_update_float(plist,"ESO DRS WCSRAOFF",(float)xcen);
00368     cpl_propertylist_set_comment(plist,"ESO DRS WCSRAOFF",
00369                                  "[arcsec] cenpix RA_after - RA_before)");
00370     cpl_propertylist_update_float(plist,"ESO DRS WCSDECOFF",(float)ycen);
00371     cpl_propertylist_set_comment(plist,"ESO DRS WCSDECOFF",
00372                                  "[arcsec] cenpix Dec_after - Dec_before)");
00373 
00374     /* Update the table header */
00375 
00376     if (tlist != NULL) {
00377         xcol = vircam_findcol(tlist,"X");
00378         ycol = vircam_findcol(tlist,"Y");
00379         if (xcol != -1 && ycol != -1) {
00380             snprintf(key,9,"TCRPX%d",xcol);
00381             cpl_propertylist_update_double(tlist,key,crpix1);
00382             snprintf(key,9,"TCRPX%d",ycol);
00383             cpl_propertylist_update_double(tlist,key,crpix2);
00384             snprintf(key,9,"TC%d_%d",xcol,xcol);
00385             cpl_propertylist_update_double(tlist,key,a);
00386             snprintf(key,9,"TC%d_%d",xcol,ycol);
00387             cpl_propertylist_update_double(tlist,key,b);
00388             snprintf(key,9,"TC%d_%d",ycol,xcol);
00389             cpl_propertylist_update_double(tlist,key,d);
00390             snprintf(key,9,"TC%d_%d",ycol,ycol);
00391             cpl_propertylist_update_double(tlist,key,e);
00392             cpl_propertylist_update_int(tlist,"ESO DRS NUMBRMS",ngood);
00393             cpl_propertylist_set_comment(tlist,"ESO DRS NUMBRMS",
00394                                          "Number of stars in WCS fit");
00395             cpl_propertylist_update_float(tlist,"ESO DRS STDCRMS",(float)averr);
00396             cpl_propertylist_set_comment(tlist,"ESO DRS STDCRMS",
00397                                          "[arcsec] Average error in WCS fit");
00398             cpl_propertylist_update_float(tlist,"ESO DRS WCSRAOFF",(float)xcen);
00399             cpl_propertylist_set_comment(tlist,"ESO DRS WCSRAOFF",
00400                                          "[arcsec] cenpix RA_after - RA_before)");
00401             cpl_propertylist_update_float(tlist,"ESO DRS WCSDECOFF",(float)ycen);
00402             cpl_propertylist_set_comment(tlist,"ESO DRS WCSDECOFF",
00403                                          "[arcsec] cenpix Dec_after - Dec_before)");
00404         }
00405     }
00406 
00407     /* Back-calculate a crval for the old value of crpix. Compare to the 
00408        WCS crval and write to QC header */
00409 
00410     cr = cpl_wcs_get_crval(wcs);
00411     crdata = cpl_array_get_data_double(cr);
00412     vircam_xytoradec(wcs,oldcrpix1,oldcrpix2,&rac_after,&decc_after);
00413     rac_after -= crdata[0];
00414     decc_after -= crdata[1];
00415     cpl_propertylist_update_float(plist,"ESO QC WCS_DCRVAL1",(float)rac_after);
00416     cpl_propertylist_set_comment(plist,"ESO QC WCS_DCRVAL1",
00417                                  "[deg] change in crval1");
00418     cpl_propertylist_update_float(plist,"ESO QC WCS_DCRVAL2",(float)decc_after);
00419     cpl_propertylist_set_comment(plist,"ESO QC WCS_DCRVAL2",
00420                                  "[deg] change in crval2");
00421 
00422     /* Work out the change in the rotation */
00423 
00424     crm = cpl_wcs_get_cd(wcs);
00425     crdata = cpl_matrix_get_data(crm);
00426     oldtheta = 0.5*(fabs(atan2(crdata[1],crdata[0])) + 
00427                     fabs(atan2(crdata[2],crdata[3]))) - oldtheta;
00428     oldtheta *= DEGRAD;
00429     cpl_propertylist_update_float(plist,"ESO QC WCS_DTHETA",(float)oldtheta);
00430     cpl_propertylist_set_comment(plist,"ESO QC WCS_DTHETA",
00431                                  "[deg] change in rotation");
00432     
00433     /* Work out the mean plate scale */
00434 
00435     scale = 1800.0*(sqrt(pow(crdata[0],2.0) +  pow(crdata[1],2.0)) + 
00436                     sqrt(pow(crdata[2],2.0) +  pow(crdata[3],2.0)));
00437     cpl_propertylist_update_float(plist,"ESO QC WCS_SCALE",(float)scale);
00438     cpl_propertylist_set_comment(plist,"ESO QC WCS_SCALE",
00439                                  "[arcsec] mean plate scale");
00440 
00441     /* Work out the shear if this new WCS */
00442 
00443     oldtheta = fabs(atan2(crdata[1],crdata[0])) - 
00444         fabs(atan2(crdata[2],crdata[3]));
00445     cpl_propertylist_update_float(plist,"ESO QC WCS_SHEAR",(float)oldtheta);
00446     cpl_propertylist_set_comment(plist,"ESO QC WCS_SHEAR",
00447                                  "[deg] abs(xrot) - abs(yrot)");
00448 
00449     /* Now just add in the RMS */
00450 
00451     cpl_propertylist_update_float(plist,"ESO QC WCS_RMS",(float)averr);
00452     cpl_propertylist_set_comment(plist,"ESO QC WCS_RMS",
00453                                  "[arcsec] Average error in WCS fit");
00454 
00455     /* Right, get out of here now... */
00456 
00457     cpl_wcs_delete(wcs);
00458     tidy();
00459     GOOD_STATUS
00460 }
00461 
00462 /*---------------------------------------------------------------------------*/
00496 /*---------------------------------------------------------------------------*/
00497 
00498 static int vircam_plate6(double *xpos, double *ypos, double *xi, double *eta,
00499                          unsigned char *flag, int nstds, double *a, double *b,
00500                          double *c, double *d, double *e, double *f) {
00501     double sx1sq,sy1sq,sx1y1,sx1x2,sy1x2;
00502     double sy1y2,sx1y2,xposmean,yposmean,ximean,etamean,xx1,yy1,xx2,yy2;
00503     int i,ngood,nbad;
00504 
00505     /* Is it worthwhile even being here? */
00506 
00507     (void)vircam_sumbpm(flag,nstds,&nbad);
00508     ngood = nstds - nbad;
00509     if (ngood < 2)
00510         return(VIR_FATAL);
00511 
00512     /* Initialise all the counters and summations */
00513 
00514     sx1sq = 0.0;
00515     sy1sq = 0.0;
00516     sx1y1 = 0.0;
00517     sx1x2 = 0.0;
00518     sy1x2 = 0.0;
00519     sy1y2 = 0.0;
00520     sx1y2 = 0.0;
00521     xposmean = 0.0;
00522     yposmean = 0.0;
00523     ximean = 0.0;
00524     etamean = 0.0;
00525 
00526     /* Find means in each coordinate system */
00527 
00528     xposmean = vircam_dmean(xpos,flag,nstds);
00529     yposmean = vircam_dmean(ypos,flag,nstds);
00530     ximean = vircam_dmean(xi,flag,nstds);
00531     etamean = vircam_dmean(eta,flag,nstds);
00532 
00533     /* Now accumulate the sums */
00534 
00535     for (i = 0; i < nstds; i++) {
00536         if (!flag[i]) {
00537             xx1 = xpos[i] - xposmean;
00538             yy1 = ypos[i] - yposmean;
00539             xx2 = xi[i] - ximean;
00540             yy2 = eta[i] - etamean;
00541             sx1sq += xx1*xx1;
00542             sy1sq += yy1*yy1;
00543             sx1y1 += xx1*yy1;
00544             sx1x2 += xx1*xx2;
00545             sy1x2 += yy1*xx2;
00546             sy1y2 += yy1*yy2;
00547             sx1y2 += xx1*yy2;
00548         }
00549     }
00550 
00551     /* Do solution for X */
00552 
00553     *a = (sx1y1*sy1x2 - sx1x2*sy1sq)/(sx1y1*sx1y1 - sx1sq*sy1sq);
00554     *b = (sx1x2*sx1y1 - sx1sq*sy1x2)/(sx1y1*sx1y1 - sx1sq*sy1sq);
00555     *c = -xposmean*(*a) - yposmean*(*b) + ximean;
00556 
00557     /* Now the solution for Y */
00558 
00559     *d = (sx1y1*sx1y2 - sy1y2*sx1sq)/(sx1y1*sx1y1 - sy1sq*sx1sq);
00560     *e = (sy1y2*sx1y1 - sy1sq*sx1y2)/(sx1y1*sx1y1 - sy1sq*sx1sq);
00561     *f = -xposmean*(*e) - yposmean*(*d) + etamean;
00562 
00563     /* Get outta here */
00564 
00565     return(VIR_OK);
00566 }
00567 
00568 /*---------------------------------------------------------------------------*/
00602 /*---------------------------------------------------------------------------*/
00603 
00604 static int vircam_plate4(double *xpos, double *ypos, double *xi, double *eta,
00605                          unsigned char *flag, int nstds, double *a, double *b,
00606                          double *c, double *d, double *e, double *f) {
00607     double sx1sq,sy1sq,sx1x2,sy1x2,sy1y2,sx1y2,xposmean,yposmean;
00608     double ximean,etamean,xx1,yy1,xx2,yy2,det,num,denom,theta,mag;
00609     double stheta,ctheta;
00610     int i,ngood,nbad;
00611 
00612     /* Is it worthwhile even being here? */
00613 
00614     (void)vircam_sumbpm(flag,nstds,&nbad);
00615     ngood = nstds - nbad;
00616     if (ngood < 2)
00617         return(VIR_FATAL);
00618 
00619     /* Initialise all the counters and summations */
00620 
00621     sx1sq = 0.0;
00622     sy1sq = 0.0;
00623     sx1x2 = 0.0;
00624     sy1x2 = 0.0;
00625     sy1y2 = 0.0;
00626     sx1y2 = 0.0;
00627     xposmean = 0.0;
00628     yposmean = 0.0;
00629     ximean = 0.0;
00630     etamean = 0.0;
00631 
00632     /* Find means in each coordinate system */
00633 
00634     xposmean = vircam_dmean(xpos,flag,nstds);
00635     yposmean = vircam_dmean(ypos,flag,nstds);
00636     ximean = vircam_dmean(xi,flag,nstds);
00637     etamean = vircam_dmean(eta,flag,nstds);
00638 
00639     /* Now accumulate the sums */
00640 
00641     for (i = 0; i < nstds; i++) {
00642         if (!flag[i]) {
00643             xx1 = xpos[i] - xposmean;
00644             yy1 = ypos[i] - yposmean;
00645             xx2 = xi[i] - ximean;
00646             yy2 = eta[i] - etamean;
00647             sx1sq += xx1*xx1;
00648             sy1sq += yy1*yy1;
00649             sx1x2 += xx1*xx2;
00650             sy1x2 += yy1*xx2;
00651             sy1y2 += yy1*yy2;
00652             sx1y2 += xx1*yy2;
00653         }
00654     }
00655 
00656     /* Compute the rotation angle */
00657 
00658     det = sx1x2*sy1y2 - sy1x2*sx1y2;
00659     if (det < 0.0) {
00660         num = sy1x2 + sx1y2;
00661         denom = -sx1x2 + sy1y2;
00662     } else {
00663         num = sy1x2 - sx1y2;
00664         denom = sx1x2 + sy1y2;
00665     }
00666     if (num == 0.0 && denom == 0.0) {
00667         theta = 0.0;
00668     } else {
00669         theta = atan2(num,denom);
00670         if (theta < 0.0)
00671             theta += M_TWOPI;
00672     }
00673 
00674     /* Compute magnification factor */
00675 
00676     ctheta = cos(theta);
00677     stheta = sin(theta);
00678     num = denom*ctheta  + num*stheta;
00679     denom = sx1sq + sy1sq;
00680     if (denom <= 0.0) {
00681         mag = 1.0;
00682     } else {
00683         mag = num/denom;
00684     }
00685 
00686     /* Compute coeffs */
00687 
00688     if (det < 0.0) {
00689         *a = -mag*ctheta;
00690         *e = mag*stheta;
00691     } else {
00692         *a = mag*ctheta;
00693         *e = -mag*stheta;
00694     }
00695     *b = mag*stheta;
00696     *d = mag*ctheta;
00697     *c = -xposmean*(*a) - yposmean*(*b) + ximean;
00698     *f = -xposmean*(*e) - yposmean*(*d) + etamean;
00699 
00700     /* Get outta here */
00701 
00702     return(VIR_OK);
00703 }
00704 
00705 static void tidy(void) {
00706 
00707     freespace(work);
00708     freespace(iwork);
00709 }
00710 
00714 /*
00715 
00716 $Log: vircam_platesol.c,v $
00717 Revision 1.22  2008/07/10 13:05:53  jim
00718 Modified to use v4.2 version of cpl_wcs
00719 
00720 Revision 1.21  2008/05/06 08:40:10  jim
00721 Modified to use cpl_wcs interface
00722 
00723 Revision 1.20  2008/01/22 19:46:10  jim
00724 Fixed sign error in plate4
00725 
00726 Revision 1.19  2007/10/25 17:34:01  jim
00727 Modified to remove lint warnings
00728 
00729 Revision 1.18  2007/05/03 11:15:33  jim
00730 Fixed little problem with table wcs
00731 
00732 Revision 1.17  2007/05/02 09:12:30  jim
00733 Modified to update table header WCS keywords
00734 
00735 Revision 1.16  2007/03/29 12:19:39  jim
00736 Little changes to improve documentation
00737 
00738 Revision 1.15  2007/03/01 12:42:42  jim
00739 Modified slightly after code checking
00740 
00741 Revision 1.14  2007/01/17 23:54:01  jim
00742 Plugged some memory leaks
00743 
00744 Revision 1.13  2007/01/08 19:12:03  jim
00745 Fixed shear comment so that it doesn't overflow
00746 
00747 Revision 1.12  2006/10/02 13:43:50  jim
00748 Added missing .h file
00749 
00750 Revision 1.11  2006/08/11 12:45:41  jim
00751 Modified to use wcslib
00752 
00753 Revision 1.10  2006/06/14 14:33:31  jim
00754 Fixed units of WCS_SCALE
00755 
00756 Revision 1.9  2006/06/13 14:09:38  jim
00757 Made some of the QC header values single precision
00758 
00759 Revision 1.8  2006/06/09 11:26:26  jim
00760 Small changes to keep lint happy
00761 
00762 Revision 1.7  2006/05/26 15:05:46  jim
00763 Fixed column names for input table
00764 
00765 Revision 1.6  2006/03/23 21:18:53  jim
00766 Minor changes mainly to comment headers
00767 
00768 Revision 1.5  2006/03/22 14:05:37  jim
00769 fixed a little bug
00770 
00771 Revision 1.4  2006/03/22 13:58:32  jim
00772 Cosmetic fixes to keep lint happy
00773 
00774 Revision 1.3  2006/03/15 10:43:41  jim
00775 Fixed a few things
00776 
00777 Revision 1.2  2006/02/22 14:19:52  jim
00778 Modified to check for the existence of the columns in the matched standards
00779 table.
00780 
00781 Revision 1.1  2006/02/18 11:52:34  jim
00782 new file
00783 
00784 
00785 */

Generated on Wed Apr 10 04:01:56 2013 for VIRCAM Pipeline by  doxygen 1.5.1