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,"Value of nconst = %d is unsupported",nconst);
00160 FATAL_ERROR
00161 }
00162
00163
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
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
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
00201
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
00223
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
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
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
00268
00269
00270 niter = 0;
00271 while (niter >= 0) {
00272
00273
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
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
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
00337
00338 ngood = 0;
00339 for (i = 0; i < nstds; i++)
00340 if (! isbad[i])
00341 ngood++;
00342 averr *= DEGRAD*3600.0;
00343
00344
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
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
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
00417
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
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
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
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
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
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
00525
00526 *coefs = NULL;
00527 if (*status != VIR_OK)
00528 return(*status);
00529
00530
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
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
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
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
00570
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
00586
00587
00588 niter = 0;
00589 while (niter >= 0) {
00590
00591
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
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
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
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
00706
00707 (void)vircam_sumbpm(flag,nstds,&nbad);
00708 ngood = nstds - nbad;
00709 if (ngood < 2)
00710 return(VIR_FATAL);
00711
00712
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
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
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
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
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
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
00813
00814 (void)vircam_sumbpm(flag,nstds,&nbad);
00815 ngood = nstds - nbad;
00816 if (ngood < 2)
00817 return(VIR_FATAL);
00818
00819
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
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
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
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
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
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
00901
00902 return(VIR_OK);
00903 }
00904
00905 static void tidy(void) {
00906
00907 freespace(work);
00908 freespace(iwork);
00909 }
00910
00914
00915
00916
00917
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