00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
00152
00153 if (*status != VIR_OK)
00154 return(*status);
00155
00156
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
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
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
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
00203
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
00225
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
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
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
00270
00271
00272 niter = 0;
00273 while (niter >= 0) {
00274
00275
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
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
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
00339
00340 ngood = 0;
00341 for (i = 0; i < nstds; i++)
00342 if (! isbad[i])
00343 ngood++;
00344 averr *= DEGRAD*3600.0;
00345
00346
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
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
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
00419
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
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
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
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
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
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
00527
00528 *coefs = NULL;
00529 if (*status != VIR_OK)
00530 return(*status);
00531
00532
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
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
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
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
00574
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
00590
00591
00592 niter = 0;
00593 while (niter >= 0) {
00594
00595
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
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
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
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
00710
00711 (void)vircam_sumbpm(flag,nstds,&nbad);
00712 ngood = nstds - nbad;
00713 if (ngood < 2)
00714 return(VIR_FATAL);
00715
00716
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
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
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
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
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
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
00817
00818 (void)vircam_sumbpm(flag,nstds,&nbad);
00819 ngood = nstds - nbad;
00820 if (ngood < 2)
00821 return(VIR_FATAL);
00822
00823
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
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
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
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
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
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
00905
00906 return(VIR_OK);
00907 }
00908
00909 static void tidy(void) {
00910
00911 freespace(work);
00912 freespace(iwork);
00913 }
00914
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016