37 #include "vircam_mods.h"
38 #include "vircam_utils.h"
39 #include "vircam_wcsutils.h"
40 #include "vircam_stats.h"
41 #include "vircam_pfits.h"
43 static double *work = NULL;
44 static unsigned char *iwork = NULL;
46 static int vircam_plate6(
double *xpos,
double *ypos,
double *xi,
double *eta,
47 unsigned char *flag,
int nstds,
double *a,
double *b,
48 double *c,
double *d,
double *e,
double *f);
49 static int vircam_plate4(
double *xpos,
double *ypos,
double *xi,
double *eta,
50 unsigned char *flag,
int nstds,
double *a,
double *b,
51 double *c,
double *d,
double *e,
double *f);
52 static void tidy(
void);
132 cpl_table *matchedstds,
int nconst,
int shiftan,
134 int nstds,nc2,i,niter,nrej,ngood,nreq=6,xcol,ycol;
136 const char *fctid =
"vircam_platesol";
138 double *xptr,*yptr,*xptr2,*yptr2,*ra,*dec,*xiptr,*etaptr,*wptr,averr;
139 double r1,r2,d1,d2,newcrval1,newcrval2,a,b,c,d,e,f,xifit,etafit,dxi,deta;
140 double crpix1,crpix2,xi,eta,rac_before,rac_after,decc_before,decc_after;
141 double xcen,ycen,oldtheta,scale,oldcrpix1,oldcrpix2;
142 const double *crdata;
143 unsigned char *isbad,*wptr2;
144 const char *reqcols[] = {
"X_coordinate",
"Y_coordinate",
"xpredict",
145 "ypredict",
"RA",
"Dec"};
149 const cpl_matrix *crm;
153 if (*status != VIR_OK)
158 if (nconst != 4 && nconst != 6) {
160 "Value of nconst = %" CPL_SIZE_FORMAT
" is unsupported",
167 nstds = (int)cpl_table_get_nrow(matchedstds);
171 "Too few standards (%" CPL_SIZE_FORMAT
") in table for %" CPL_SIZE_FORMAT
" coefficient fit",
172 (cpl_size)nstds,(cpl_size)nconst);
178 for (i = 0; i < nreq; i++) {
179 if (cpl_table_has_column(matchedstds,reqcols[i]) != 1) {
180 cpl_msg_error(fctid,
"Matched standards table missing column %s\n",
188 work = cpl_malloc(10*nstds*
sizeof(*work));
189 iwork = cpl_calloc(3*nstds,
sizeof(*isbad));
192 xptr2 = work + 2*nstds;
193 yptr2 = work + 3*nstds;
195 dec = work + 5*nstds;
196 xiptr = work + 6*nstds;
197 etaptr = work + 7*nstds;
198 wptr = work + 8*nstds;
200 wptr2 = iwork + nstds;
205 tptr = cpl_table_get_data_float(matchedstds,
"X_coordinate");
206 for (i = 0; i < nstds; i++)
207 xptr[i] = (
double)tptr[i];
208 tptr = cpl_table_get_data_float(matchedstds,
"Y_coordinate");
209 for (i = 0; i < nstds; i++)
210 yptr[i] = (
double)tptr[i];
211 tptr = cpl_table_get_data_float(matchedstds,
"xpredict");
212 for (i = 0; i < nstds; i++)
213 xptr2[i] = (
double)tptr[i];
214 tptr = cpl_table_get_data_float(matchedstds,
"ypredict");
215 for (i = 0; i < nstds; i++)
216 yptr2[i] = (
double)tptr[i];
217 tptr = cpl_table_get_data_float(matchedstds,
"RA");
218 for (i = 0; i < nstds; i++)
219 ra[i] = (
double)tptr[i];
220 tptr = cpl_table_get_data_float(matchedstds,
"Dec");
221 for (i = 0; i < nstds; i++)
222 dec[i] = (
double)tptr[i];
230 wcs = cpl_wcs_new_from_propertylist(plist);
231 cr = cpl_wcs_get_crval(wcs);
232 crdata = cpl_array_get_data_double_const(cr);
233 for (i = 0; i < nstds; i++) {
241 newcrval1 = crdata[0] + r1;
242 newcrval2 = crdata[1] + d1;
243 cpl_propertylist_update_double(plist,
"CRVAL1",newcrval1);
244 cpl_propertylist_update_double(plist,
"CRVAL2",newcrval2);
250 wcs = cpl_wcs_new_from_propertylist(plist);
253 cr = cpl_wcs_get_crpix(wcs);
254 crdata = cpl_array_get_data_double_const(cr);
255 oldcrpix1 = crdata[0];
256 oldcrpix2 = crdata[1];
257 xcen = 0.5*(double)n1;
258 ycen = 0.5*(double)n2;
263 for (i = 0; i < nstds; i++) {
279 *status = vircam_plate6(xptr,yptr,xiptr,etaptr,isbad,nstds,&a,&b,
283 *status = vircam_plate4(xptr,yptr,xiptr,etaptr,isbad,nstds,&a,&b,
287 *status = vircam_plate6(xptr,yptr,xiptr,etaptr,isbad,nstds,&a,&b,
291 if (*status != VIR_OK) {
292 cpl_msg_error(fctid,
"Plate constant solution failed");
299 for (i = 0; i < nstds; i++) {
300 xifit = xptr[i]*a + yptr[i]*b + c;
301 etafit = xptr[i]*d + yptr[i]*e + f;
302 dxi = fabs(xifit - xiptr[i]);
303 deta = fabs(etafit - etaptr[i]);
306 wptr2[i*2] = isbad[i];
307 wptr2[i*2+1] = isbad[i];
315 for (i = 0; i < nstds; i++) {
316 if (!isbad[i] && (wptr[i*2] > 3.0*averr || wptr[i*2+1] > 3.0*averr)) nrej++;
321 if (nrej == 0 || ngood < nconst)
323 for (i = 0; i < nstds; i++) {
324 if (!isbad[i] && (wptr[i*2] > 3.0*averr || wptr[i*2+1] > 3.0*averr)) isbad[i] = 1;
331 crpix1 = (e*c - b*f)/(d*b - e*a);
332 crpix2 = (a*f - d*c)/(d*b - e*a);
341 for (i = 0; i < nstds; i++)
344 averr *= DEGRAD*3600.0;
348 cpl_propertylist_update_double(plist,
"CRPIX1",crpix1);
349 cpl_propertylist_update_double(plist,
"CRPIX2",crpix2);
350 cpl_propertylist_update_double(plist,
"CD1_1",a);
351 cpl_propertylist_update_double(plist,
"CD1_2",b);
352 cpl_propertylist_update_double(plist,
"CD2_1",d);
353 cpl_propertylist_update_double(plist,
"CD2_2",e);
354 cpl_propertylist_update_int(plist,
"ESO DRS NUMBRMS",ngood);
355 cpl_propertylist_set_comment(plist,
"ESO DRS NUMBRMS",
356 "Number of stars in WCS fit");
357 cpl_propertylist_update_double(plist,
"ESO DRS STDCRMS",averr);
358 cpl_propertylist_set_comment(plist,
"ESO DRS STDCRMS",
359 "[arcsec] Average error in WCS fit");
363 crm = cpl_wcs_get_cd(wcs);
364 crdata = cpl_matrix_get_data_const(crm);
365 oldtheta = 0.5*(fabs(atan2(crdata[1],crdata[0])) +
366 fabs(atan2(crdata[2],crdata[3])));
368 wcs = cpl_wcs_new_from_propertylist(plist);
370 xcen = 3600.0*(rac_after - rac_before);
371 ycen = 3600.0*(decc_after - decc_before);
372 cpl_propertylist_update_double(plist,
"ESO DRS WCSRAOFF",xcen);
373 cpl_propertylist_set_comment(plist,
"ESO DRS WCSRAOFF",
374 "[arcsec] cenpix RA_after - RA_before)");
375 cpl_propertylist_update_double(plist,
"ESO DRS WCSDECOFF",ycen);
376 cpl_propertylist_set_comment(plist,
"ESO DRS WCSDECOFF",
377 "[arcsec] cenpix Dec_after - Dec_before)");
384 if (xcol != -1 && ycol != -1) {
385 snprintf(key,9,
"TCRPX%d",xcol);
386 cpl_propertylist_update_double(tlist,key,crpix1);
387 snprintf(key,9,
"TCRPX%d",ycol);
388 cpl_propertylist_update_double(tlist,key,crpix2);
390 snprintf(key,9,
"TCRVL%d",xcol);
391 cpl_propertylist_update_double(tlist,key,newcrval1);
392 snprintf(key,9,
"TCRVL%d",ycol);
393 cpl_propertylist_update_double(tlist,key,newcrval2);
395 snprintf(key,9,
"TC%d_%d",xcol,xcol);
396 cpl_propertylist_update_double(tlist,key,a);
397 snprintf(key,9,
"TC%d_%d",xcol,ycol);
398 cpl_propertylist_update_double(tlist,key,b);
399 snprintf(key,9,
"TC%d_%d",ycol,xcol);
400 cpl_propertylist_update_double(tlist,key,d);
401 snprintf(key,9,
"TC%d_%d",ycol,ycol);
402 cpl_propertylist_update_double(tlist,key,e);
403 cpl_propertylist_update_int(tlist,
"ESO DRS NUMBRMS",ngood);
404 cpl_propertylist_set_comment(tlist,
"ESO DRS NUMBRMS",
405 "Number of stars in WCS fit");
406 cpl_propertylist_update_double(tlist,
"ESO DRS STDCRMS",averr);
407 cpl_propertylist_set_comment(tlist,
"ESO DRS STDCRMS",
408 "[arcsec] Average error in WCS fit");
409 cpl_propertylist_update_double(tlist,
"ESO DRS WCSRAOFF",xcen);
410 cpl_propertylist_set_comment(tlist,
"ESO DRS WCSRAOFF",
411 "[arcsec] cenpix RA_after - RA_before)");
412 cpl_propertylist_update_double(tlist,
"ESO DRS WCSDECOFF",ycen);
413 cpl_propertylist_set_comment(tlist,
"ESO DRS WCSDECOFF",
414 "[arcsec] cenpix Dec_after - Dec_before)");
421 cr = cpl_wcs_get_crval(wcs);
422 crdata = cpl_array_get_data_double_const(cr);
424 rac_after -= crdata[0];
425 decc_after -= crdata[1];
426 cpl_propertylist_update_double(plist,
"ESO QC WCS_DCRVAL1",rac_after);
427 cpl_propertylist_set_comment(plist,
"ESO QC WCS_DCRVAL1",
428 "[deg] change in crval1");
429 cpl_propertylist_update_double(plist,
"ESO QC WCS_DCRVAL2",decc_after);
430 cpl_propertylist_set_comment(plist,
"ESO QC WCS_DCRVAL2",
431 "[deg] change in crval2");
435 crm = cpl_wcs_get_cd(wcs);
436 crdata = cpl_matrix_get_data_const(crm);
437 oldtheta = 0.5*(fabs(atan2(crdata[1],crdata[0])) +
438 fabs(atan2(crdata[2],crdata[3]))) - oldtheta;
440 cpl_propertylist_update_double(plist,
"ESO QC WCS_DTHETA",oldtheta);
441 cpl_propertylist_set_comment(plist,
"ESO QC WCS_DTHETA",
442 "[deg] change in rotation");
446 scale = 1800.0*(sqrt(pow(crdata[0],2.0) + pow(crdata[1],2.0)) +
447 sqrt(pow(crdata[2],2.0) + pow(crdata[3],2.0)));
448 cpl_propertylist_update_double(plist,
"ESO QC WCS_SCALE",scale);
449 cpl_propertylist_set_comment(plist,
"ESO QC WCS_SCALE",
450 "[arcsec] mean plate scale");
454 oldtheta = fabs(atan2(crdata[1],crdata[0])) -
455 fabs(atan2(crdata[2],crdata[3]));
456 cpl_propertylist_update_double(plist,
"ESO QC WCS_SHEAR",oldtheta);
457 cpl_propertylist_set_comment(plist,
"ESO QC WCS_SHEAR",
458 "[deg] abs(xrot) - abs(yrot)");
462 cpl_propertylist_update_double(plist,
"ESO QC WCS_RMS",averr);
463 cpl_propertylist_set_comment(plist,
"ESO QC WCS_RMS",
464 "[arcsec] Average error in WCS fit");
514 extern int vircam_platexy(cpl_table *matchedxy,
int nconst, cpl_array **coefs,
516 const char *fctid =
"vircam_platexy";
517 int nxy,nc2,i,niter,nrej,ngood;
518 unsigned char *isbad,*wptr2;
519 double *xptr1,*xptr2,*yptr1,*yptr2,*wptr,a,b,c,d,e,f,*cc,xfit,yfit;
523 const char *reqcols[] = {
"X_coordinate_1",
"Y_coordinate_1",
"X_coordinate_2",
529 if (*status != VIR_OK)
534 if (nconst != 4 && nconst != 6) {
536 "Value of nconst = %" CPL_SIZE_FORMAT
" is unsupported",
543 nxy = (int)cpl_table_get_nrow(matchedxy);
547 "Too few objects (%" CPL_SIZE_FORMAT
") in table for %" CPL_SIZE_FORMAT
" coefficient fit",
548 (cpl_size)nxy,(cpl_size)nconst);
554 for (i = 0; i < nreq; i++) {
555 if (cpl_table_has_column(matchedxy,reqcols[i]) != 1) {
556 cpl_msg_error(fctid,
"Input table missing column %s\n",reqcols[i]);
563 work = cpl_malloc(6*nxy*
sizeof(*work));
564 iwork = cpl_calloc(3*nxy,
sizeof(*isbad));
567 xptr2 = work + 2*nxy;
568 yptr2 = work + 3*nxy;
576 tptr = cpl_table_get_data_float(matchedxy,
"X_coordinate_1");
577 for (i = 0; i < nxy; i++)
578 xptr1[i] = (
double)tptr[i];
579 tptr = cpl_table_get_data_float(matchedxy,
"Y_coordinate_1");
580 for (i = 0; i < nxy; i++)
581 yptr1[i] = (
double)tptr[i];
582 tptr = cpl_table_get_data_float(matchedxy,
"X_coordinate_2");
583 for (i = 0; i < nxy; i++)
584 xptr2[i] = (
double)tptr[i];
585 tptr = cpl_table_get_data_float(matchedxy,
"Y_coordinate_2");
586 for (i = 0; i < nxy; i++)
587 yptr2[i] = (
double)tptr[i];
599 *status = vircam_plate6(xptr2,yptr2,xptr1,yptr1,isbad,nxy,&a,&b,
603 *status = vircam_plate4(xptr2,yptr2,xptr1,yptr1,isbad,nxy,&a,&b,
607 *status = vircam_plate6(xptr2,yptr2,xptr1,yptr1,isbad,nxy,&a,&b,
611 if (*status != VIR_OK) {
612 cpl_msg_error(fctid,
"Plate constant solution failed");
619 for (i = 0; i < nxy; i++) {
620 xfit = xptr2[i]*a + yptr2[i]*b + c;
621 yfit = xptr2[i]*d + yptr2[i]*e + f;
622 dx = fabs(xfit - xptr1[i]);
623 dy = fabs(yfit - yptr1[i]);
626 wptr2[i*2] = isbad[i];
627 wptr2[i*2+1] = isbad[i];
635 for (i = 0; i < nxy; i++) {
636 if (!isbad[i] && (wptr[i*2] > 3.0*averr || wptr[i*2+1] > 3.0*averr)) nrej++;
641 if (nrej == 0 || ngood < nconst)
643 for (i = 0; i < nxy; i++) {
644 if (!isbad[i] && (wptr[i*2] > 3.0*averr || wptr[i*2+1] > 3.0*averr)) isbad[i] = 1;
651 *coefs = cpl_array_new(6,CPL_TYPE_DOUBLE);
652 cc = cpl_array_get_data_double(*coefs);
702 static int vircam_plate6(
double *xpos,
double *ypos,
double *xi,
double *eta,
703 unsigned char *flag,
int nstds,
double *a,
double *b,
704 double *c,
double *d,
double *e,
double *f) {
705 double sx1sq,sy1sq,sx1y1,sx1x2,sy1x2;
706 double sy1y2,sx1y2,xposmean,yposmean,ximean,etamean,xx1,yy1,xx2,yy2;
712 ngood = nstds - nbad;
739 for (i = 0; i < nstds; i++) {
741 xx1 = xpos[i] - xposmean;
742 yy1 = ypos[i] - yposmean;
743 xx2 = xi[i] - ximean;
744 yy2 = eta[i] - etamean;
757 *a = (sx1y1*sy1x2 - sx1x2*sy1sq)/(sx1y1*sx1y1 - sx1sq*sy1sq);
758 *b = (sx1x2*sx1y1 - sx1sq*sy1x2)/(sx1y1*sx1y1 - sx1sq*sy1sq);
759 *c = -xposmean*(*a) - yposmean*(*b) + ximean;
763 *d = (sx1y1*sx1y2 - sy1y2*sx1sq)/(sx1y1*sx1y1 - sy1sq*sx1sq);
764 *e = (sy1y2*sx1y1 - sy1sq*sx1y2)/(sx1y1*sx1y1 - sy1sq*sx1sq);
765 *f = -xposmean*(*e) - yposmean*(*d) + etamean;
808 static int vircam_plate4(
double *xpos,
double *ypos,
double *xi,
double *eta,
809 unsigned char *flag,
int nstds,
double *a,
double *b,
810 double *c,
double *d,
double *e,
double *f) {
811 double sx1sq,sy1sq,sx1x2,sy1x2,sy1y2,sx1y2,xposmean,yposmean;
812 double ximean,etamean,xx1,yy1,xx2,yy2,det,num,denom,theta,mag;
813 double stheta,ctheta;
819 ngood = nstds - nbad;
845 for (i = 0; i < nstds; i++) {
847 xx1 = xpos[i] - xposmean;
848 yy1 = ypos[i] - yposmean;
849 xx2 = xi[i] - ximean;
850 yy2 = eta[i] - etamean;
862 det = sx1x2*sy1y2 - sy1x2*sx1y2;
865 denom = -sx1x2 + sy1y2;
868 denom = sx1x2 + sy1y2;
870 if (num == 0.0 && denom == 0.0) {
873 theta = atan2(num,denom);
875 theta += CPL_MATH_2PI;
882 num = denom*ctheta + num*stheta;
883 denom = sx1sq + sy1sq;
901 *c = -xposmean*(*a) - yposmean*(*b) + ximean;
902 *f = -xposmean*(*e) - yposmean*(*d) + etamean;
909 static void tidy(
void) {