void test_compute_inverse(CuTest* tc) { double x,y, dx, dy; sip_t* wcs = sip_from_string(wcsfile, 0, NULL); CuAssertPtrNotNull(tc, wcs); printf("Read:\n"); sip_print_to(wcs, stdout); CuAssertIntEquals(tc, 4, wcs->a_order); CuAssertIntEquals(tc, 4, wcs->b_order); CuAssertIntEquals(tc, 0, wcs->ap_order); CuAssertIntEquals(tc, 0, wcs->bp_order); CuAssertIntEquals(tc, 0, sip_ensure_inverse_polynomials(wcs)); printf("After ensuring inverse:\n"); sip_print_to(wcs, stdout); CuAssertIntEquals(tc, 4, wcs->a_order); CuAssertIntEquals(tc, 4, wcs->b_order); CuAssertIntEquals(tc, 5, wcs->ap_order); CuAssertIntEquals(tc, 5, wcs->bp_order); dx = dy = 100; for (y=0; y<=sip_imageh(wcs); y+=dy) { for (x=0; x<=sip_imagew(wcs); x+=dx) { double ra,dec; double x2, y2; anbool ok; sip_pixelxy2radec(wcs, x, y, &ra, &dec); ok = sip_radec2pixelxy(wcs, ra, dec, &x2, &y2); CuAssertTrue(tc, ok); CuAssertDblEquals(tc, x, x2, 1e-2); CuAssertDblEquals(tc, y, y2, 1e-2); printf("x,y %g,%g --> error %g,%g\n", x,y, x2-x, y2-y); } } sip_free(wcs); }
void test_wcs_shift(CuTest* tc) { sip_t wcs; memset(&wcs, 0, sizeof(sip_t)); wcs.wcstan.crpix[0] = 324.867; wcs.wcstan.crpix[1] = 476.596; wcs.wcstan.crval[0] = 39.0268; wcs.wcstan.crval[1] = 65.0062; wcs.wcstan.cd[0][0] = 0.00061453; wcs.wcstan.cd[0][1] = -0.0035865; wcs.wcstan.cd[1][0] = -0.0035971; wcs.wcstan.cd[1][1] = -0.00061653; wcs.a[0][2] = 3.7161e-06; wcs.a[1][1] = 2.4926e-06; wcs.a[2][0] = -1.9189e-05; wcs.b[0][2] = -3.0798e-05; wcs.b[1][1] = 1.8929e-07; wcs.b[2][0] = 8.5835e-06; wcs.ap[0][1] = -3.7374e-05; wcs.ap[0][2] = -3.8391e-06; wcs.ap[1][0] = 3.582e-05; wcs.ap[1][1] = -2.5333e-06; wcs.ap[2][0] = 1.9578e-05; wcs.bp[0][1] = 0.00028454; wcs.bp[0][2] = 3.0996e-05; wcs.bp[1][0] = -1.0094e-05; wcs.bp[1][1] = -3.7012e-07; wcs.bp[2][0] = -8.7938e-06; wcs.wcstan.imagew = 1024; wcs.wcstan.imageh = 1024; wcs.a_order = wcs.b_order = 2; wcs.ap_order = wcs.bp_order = 2; sip_t wcs2; memset(&wcs2, 0, sizeof(sip_t)); memcpy(&(wcs2.wcstan), &(wcs.wcstan), sizeof(tan_t)); #if 0 //sip_t* newwcs = wcs_shift(&wcs, 2.52369e-05,1.38956e-05); sip_t* newwcs = wcs_shift(&wcs, 10., 10.); printf("New1:\n"); sip_print_to(newwcs, stdout); printf("\n"); #else wcs_shift(&(wcs.wcstan), 10., 10.); printf("New1:\n"); tan_print_to(&(wcs.wcstan), stdout); printf("\n"); #endif #if 0 sip_t* newwcs2 = wcs_shift(&wcs2, 10., 10.); printf("New2:\n"); sip_print_to(newwcs2, stdout); printf("\n"); #endif // 10,10: #if 0 tan_t* newtan = &(newwcs->wcstan); #else tan_t* newtan = &(wcs.wcstan); #endif CuAssertDblEquals(tc, 39.0973, newtan->crval[0], 1e-4); CuAssertDblEquals(tc, 65.0483, newtan->crval[1], 1e-4); CuAssertDblEquals(tc, 324.867, newtan->crpix[0], 1e-3); CuAssertDblEquals(tc, 476.596, newtan->crpix[1], 1e-3); CuAssertDblEquals(tc, 0.00061053, newtan->cd[0][0], 1e-8); CuAssertDblEquals(tc, -0.0035872, newtan->cd[0][1], 1e-7); CuAssertDblEquals(tc, -0.0035978, newtan->cd[1][0], 1e-7); CuAssertDblEquals(tc, -0.00061252, newtan->cd[1][1], 1e-8); /* 1,1 shift: TAN-SIP Structure: crval=(39.0338, 65.0104) crpix=(324.867, 476.596) CD = ( 0.00061413 -0.0035866 ) ( -0.0035972 -0.00061613 ) image size = (1024 x 1024) SIP order: A=2, B=2, AP=2, BP=2 A = 0 0 3.7161e-06 0 2.4926e-06 -1.9189e-05 B = 0 0 -3.0798e-05 0 1.8929e-07 8.5835e-06 AP = 0 -3.7374e-05 -3.8391e-06 3.582e-05 -2.5333e-06 1.9578e-05 BP = 0 0.00028454 3.0996e-05 -1.0094e-05 -3.7012e-07 -8.7938e-06 sqrt(det(CD))=13.119 [arcsec] . OK (1 test) TAN-SIP Structure: crval=(39.0268, 65.0062) crpix=(324.867, 476.596) CD = ( 0.00061453 -0.0035865 ) ( -0.0035971 -0.00061653 ) image size = (1024 x 1024) SIP order: A=2, B=2, AP=2, BP=2 A = 0 0 3.7161e-06 0 2.4926e-06 -1.9189e-05 B = 0 0 -3.0798e-05 0 1.8929e-07 8.5835e-06 AP = 0 -3.7374e-05 -3.8391e-06 3.582e-05 -2.5333e-06 1.9578e-05 BP = 0 0.00028454 3.0996e-05 -1.0094e-05 -3.7012e-07 -8.7938e-06 sqrt(det(CD))=13.119 [arcsec] . crval=(39.0268, 65.0062) crpix=(324.867, 476.596) CD = ( 0.00061453 -0.0035865 ) ( -0.0035971 -0.00061653 ) image size = (1024 x 1024) SIP order: A=2, B=2, AP=2, BP=2 A = 0 0 3.7161e-06 0 2.4926e-06 -1.9189e-05 B = 0 0 -3.0798e-05 0 1.8929e-07 8.5835e-06 AP = 0 -3.7374e-05 -3.8391e-06 3.582e-05 -2.5333e-06 1.9578e-05 BP = 0 0.00028454 3.0996e-05 -1.0094e-05 -3.7012e-07 -8.7938e-06 */ }
void sip_print(const sip_t* sip) { sip_print_to(sip, stderr); }
static sip_t* run_test(CuTest* tc, sip_t* sip, int N, double* xy, double* radec) { int i; starxy_t* sxy; tweak_t* t; sip_t* outsip; il* imcorr; il* refcorr; dl* weights; tan_t* tan = &(sip->wcstan); printf("Input SIP:\n"); sip_print_to(sip, stdout); fflush(NULL); sxy = starxy_new(N, FALSE, FALSE); starxy_set_xy_array(sxy, xy); imcorr = il_new(256); refcorr = il_new(256); weights = dl_new(256); for (i=0; i<N; i++) { il_append(imcorr, i); il_append(refcorr, i); dl_append(weights, 1.0); } t = tweak_new(); tweak_push_wcs_tan(t, tan); outsip = t->sip; outsip->a_order = outsip->b_order = sip->a_order; outsip->ap_order = outsip->bp_order = sip->ap_order; t->weighted_fit = TRUE; tweak_push_ref_ad_array(t, radec, N); tweak_push_image_xy(t, sxy); tweak_push_correspondence_indices(t, imcorr, refcorr, NULL, weights); tweak_skip_shift(t); // push correspondences // push image xy // push ref ra,dec // push ref xy (tan) // push tan tweak_go_to(t, TWEAK_HAS_LINEAR_CD); printf("Output SIP:\n"); sip_print_to(outsip, stdout); CuAssertDblEquals(tc, tan->imagew, outsip->wcstan.imagew, 1e-10); CuAssertDblEquals(tc, tan->imageh, outsip->wcstan.imageh, 1e-10); // should be exactly equal. CuAssertDblEquals(tc, tan->crpix[0], outsip->wcstan.crpix[0], 1e-10); CuAssertDblEquals(tc, tan->crpix[1], outsip->wcstan.crpix[1], 1e-10); t->sip = NULL; tweak_free(t); starxy_free(sxy); return outsip; }
sip_t* tweak2(const double* fieldxy, int Nfield, double fieldjitter, int W, int H, const double* indexradec, int Nindex, double indexjitter, const double* quadcenter, double quadR2, double distractors, double logodds_bail, int sip_order, int sip_invorder, const sip_t* startwcs, sip_t* destwcs, int** newtheta, double** newodds, double* crpix, double* p_logodds, int* p_besti, int* testperm, int startorder) { int order; sip_t* sipout; int* indexin; double* indexpix; double* fieldsigma2s; double* weights; double* matchxyz; double* matchxy; int i, Nin=0; double logodds = 0; int besti = -1; int* theta = NULL; double* odds = NULL; int* refperm = NULL; double qc[2]; memcpy(qc, quadcenter, 2*sizeof(double)); if (destwcs) sipout = destwcs; else sipout = sip_create(); indexin = malloc(Nindex * sizeof(int)); indexpix = malloc(2 * Nindex * sizeof(double)); fieldsigma2s = malloc(Nfield * sizeof(double)); weights = malloc(Nfield * sizeof(double)); matchxyz = malloc(Nfield * 3 * sizeof(double)); matchxy = malloc(Nfield * 2 * sizeof(double)); // FIXME --- hmmm, how do the annealing steps and iterating up to // higher orders interact? assert(startwcs); memcpy(sipout, startwcs, sizeof(sip_t)); logverb("tweak2: starting orders %i, %i\n", sipout->a_order, sipout->ap_order); if (!sipout->wcstan.imagew) sipout->wcstan.imagew = W; if (!sipout->wcstan.imageh) sipout->wcstan.imageh = H; logverb("Tweak2: starting from WCS:\n"); if (log_get_level() >= LOG_VERB) sip_print_to(sipout, stdout); for (order=startorder; order <= sip_order; order++) { int step; int STEPS = 100; // variance growth rate wrt radius. double gamma = 1.0; //logverb("Starting tweak2 order=%i\n", order); for (step=0; step<STEPS; step++) { double iscale; double ijitter; double ra, dec; double R2; int Nmatch; int nmatch, nconf, ndist; double pix2; double totalweight; // clean up from last round (we do it here so that they're // valid when we leave the loop) free(theta); free(odds); free(refperm); // Anneal gamma = pow(0.9, step); if (step == STEPS-1) gamma = 0.0; logverb("Annealing: order %i, step %i, gamma = %g\n", order, step, gamma); debug("Using input WCS:\n"); if (log_get_level() > LOG_VERB) sip_print_to(sipout, stdout); // Project reference sources into pixel space; keep the ones inside image bounds. Nin = 0; for (i=0; i<Nindex; i++) { anbool ok; double x,y; ra = indexradec[2*i + 0]; dec = indexradec[2*i + 1]; ok = sip_radec2pixelxy(sipout, ra, dec, &x, &y); if (!ok) continue; if (!sip_pixel_is_inside_image(sipout, x, y)) continue; indexpix[Nin*2+0] = x; indexpix[Nin*2+1] = y; indexin[Nin] = i; Nin++; } logverb("%i reference sources within the image.\n", Nin); //logverb("CRPIX is (%g,%g)\n", sip.wcstan.crpix[0], sip.wcstan.crpix[1]); if (Nin == 0) { sip_free(sipout); free(matchxy); free(matchxyz); free(weights); free(fieldsigma2s); free(indexpix); free(indexin); return NULL; } iscale = sip_pixel_scale(sipout); ijitter = indexjitter / iscale; //logverb("With pixel scale of %g arcsec/pixel, index adds jitter of %g pix.\n", iscale, ijitter); /* CHECK for (i=0; i<Nin; i++) { double x,y; int ii = indexin[i]; sip_radec2pixelxy(sipout, indexradec[2*ii+0], indexradec[2*ii+1], &x, &y); logverb("indexin[%i]=%i; (%.1f,%.1f) -- (%.1f,%.1f)\n", i, ii, indexpix[i*2+0], indexpix[i*2+1], x, y); } */ for (i=0; i<Nfield; i++) { R2 = distsq(qc, fieldxy + 2*i, 2); fieldsigma2s[i] = (square(fieldjitter) + square(ijitter)) * (1.0 + gamma * R2/quadR2); } if (order == 1 && step == 0 && TWEAK_DEBUG_PLOTS) { TWEAK_DEBUG_PLOT("init", W, H, Nfield, fieldxy, fieldsigma2s, Nin, indexpix, *p_besti, *newtheta, sipout->wcstan.crpix, testperm, qc); } /* logodds = verify_star_lists(indexpix, Nin, fieldxy, fieldsigma2s, Nfield, W*H, distractors, logodds_bail, HUGE_VAL, &besti, &odds, &theta, NULL, &testperm); */ pix2 = square(fieldjitter); logodds = verify_star_lists_ror(indexpix, Nin, fieldxy, fieldsigma2s, Nfield, pix2, gamma, qc, quadR2, W, H, distractors, logodds_bail, HUGE_VAL, &besti, &odds, &theta, NULL, &testperm, &refperm); logverb("Logodds: %g\n", logodds); verify_count_hits(theta, besti, &nmatch, &nconf, &ndist); logverb("%i matches, %i distractors, %i conflicts (at best log-odds); %i field sources, %i index sources\n", nmatch, ndist, nconf, Nfield, Nin); verify_count_hits(theta, Nfield-1, &nmatch, &nconf, &ndist); logverb("%i matches, %i distractors, %i conflicts (all sources)\n", nmatch, ndist, nconf); if (log_get_level() >= LOG_VERB) { matchobj_log_hit_miss(theta, testperm, besti+1, Nfield, LOG_VERB, "Hit/miss: "); } /* logverb("\nAfter verify():\n"); for (i=0; i<Nin; i++) { double x,y; int ii = indexin[refperm[i]]; sip_radec2pixelxy(sipout, indexradec[2*ii+0], indexradec[2*ii+1], &x, &y); logverb("indexin[%i]=%i; (%.1f,%.1f) -- (%.1f,%.1f)\n", i, ii, indexpix[i*2+0], indexpix[i*2+1], x, y); } */ if (TWEAK_DEBUG_PLOTS) { char name[32]; sprintf(name, "o%is%02ipre", order, step); TWEAK_DEBUG_PLOT(name, W, H, Nfield, fieldxy, fieldsigma2s, Nin, indexpix, besti, theta, sipout->wcstan.crpix, testperm, qc); } Nmatch = 0; debug("Weights:"); for (i=0; i<Nfield; i++) { double ra,dec; if (theta[i] < 0) continue; assert(theta[i] < Nin); int ii = indexin[refperm[theta[i]]]; assert(ii < Nindex); assert(ii >= 0); ra = indexradec[ii*2+0]; dec = indexradec[ii*2+1]; radecdeg2xyzarr(ra, dec, matchxyz + Nmatch*3); memcpy(matchxy + Nmatch*2, fieldxy + i*2, 2*sizeof(double)); weights[Nmatch] = verify_logodds_to_weight(odds[i]); debug(" %.2f", weights[Nmatch]); Nmatch++; /* logverb("match img (%.1f,%.1f) -- ref (%.1f, %.1f), odds %g, wt %.3f\n", fieldxy[i*2+0], fieldxy[i*2+1], indexpix[theta[i]*2+0], indexpix[theta[i]*2+1], odds[i], weights[Nmatch-1]); double xx,yy; sip_radec2pixelxy(sipout, ra, dec, &xx, &yy); logverb("check: (%.1f, %.1f)\n", xx, yy); */ } debug("\n"); if (Nmatch < 2) { logverb("No matches -- aborting tweak attempt\n"); free(theta); sip_free(sipout); free(matchxy); free(matchxyz); free(weights); free(fieldsigma2s); free(indexpix); free(indexin); return NULL; } // Update the "quad center" to be the weighted average matched star posn. qc[0] = qc[1] = 0.0; totalweight = 0.0; for (i=0; i<Nmatch; i++) { qc[0] += (weights[i] * matchxy[2*i+0]); qc[1] += (weights[i] * matchxy[2*i+1]); totalweight += weights[i]; } qc[0] /= totalweight; qc[1] /= totalweight; logverb("Moved quad center to (%.1f, %.1f)\n", qc[0], qc[1]); // sipout->a_order = sipout->b_order = order; sipout->ap_order = sipout->bp_order = sip_invorder; logverb("tweak2: setting orders %i, %i\n", sipout->a_order, sipout->ap_order); if (crpix) { tan_t temptan; logverb("Moving tangent point to given CRPIX (%g,%g)\n", crpix[0], crpix[1]); fit_tan_wcs_move_tangent_point_weighted(matchxyz, matchxy, weights, Nmatch, crpix, &sipout->wcstan, &temptan); fit_tan_wcs_move_tangent_point_weighted(matchxyz, matchxy, weights, Nmatch, crpix, &temptan, &sipout->wcstan); } int doshift = 1; fit_sip_wcs(matchxyz, matchxy, weights, Nmatch, &(sipout->wcstan), order, sip_invorder, doshift, sipout); debug("Got SIP:\n"); if (log_get_level() > LOG_VERB) sip_print_to(sipout, stdout); sipout->wcstan.imagew = W; sipout->wcstan.imageh = H; } } //logverb("Final logodds: %g\n", logodds); // Now, recompute final logodds after turning 'gamma' on again (?) // FIXME -- this counts the quad stars in the logodds... { double gamma = 1.0; double iscale; double ijitter; double ra, dec; double R2; int nmatch, nconf, ndist; double pix2; free(theta); free(odds); free(refperm); gamma = 1.0; // Project reference sources into pixel space; keep the ones inside image bounds. Nin = 0; for (i=0; i<Nindex; i++) { anbool ok; double x,y; ra = indexradec[2*i + 0]; dec = indexradec[2*i + 1]; ok = sip_radec2pixelxy(sipout, ra, dec, &x, &y); if (!ok) continue; if (!sip_pixel_is_inside_image(sipout, x, y)) continue; indexpix[Nin*2+0] = x; indexpix[Nin*2+1] = y; indexin[Nin] = i; Nin++; } logverb("%i reference sources within the image.\n", Nin); iscale = sip_pixel_scale(sipout); ijitter = indexjitter / iscale; for (i=0; i<Nfield; i++) { R2 = distsq(qc, fieldxy + 2*i, 2); fieldsigma2s[i] = (square(fieldjitter) + square(ijitter)) * (1.0 + gamma * R2/quadR2); } pix2 = square(fieldjitter); logodds = verify_star_lists_ror(indexpix, Nin, fieldxy, fieldsigma2s, Nfield, pix2, gamma, qc, quadR2, W, H, distractors, logodds_bail, HUGE_VAL, &besti, &odds, &theta, NULL, &testperm, &refperm); logverb("Logodds: %g\n", logodds); verify_count_hits(theta, besti, &nmatch, &nconf, &ndist); logverb("%i matches, %i distractors, %i conflicts (at best log-odds); %i field sources, %i index sources\n", nmatch, ndist, nconf, Nfield, Nin); verify_count_hits(theta, Nfield-1, &nmatch, &nconf, &ndist); logverb("%i matches, %i distractors, %i conflicts (all sources)\n", nmatch, ndist, nconf); if (log_get_level() >= LOG_VERB) { matchobj_log_hit_miss(theta, testperm, besti+1, Nfield, LOG_VERB, "Hit/miss: "); } if (TWEAK_DEBUG_PLOTS) { TWEAK_DEBUG_PLOT("final", W, H, Nfield, fieldxy, fieldsigma2s, Nin, indexpix, besti, theta, sipout->wcstan.crpix, testperm, qc); } } if (newtheta) { // undo the "indexpix" inside-image-bounds cut. (*newtheta) = malloc(Nfield * sizeof(int)); for (i=0; i<Nfield; i++) { int nt; if (theta[i] < 0) nt = theta[i]; else nt = indexin[refperm[theta[i]]]; (*newtheta)[i] = nt; } } free(theta); free(refperm); if (newodds) *newodds = odds; else free(odds); logverb("Tweak2: final WCS:\n"); if (log_get_level() >= LOG_VERB) sip_print_to(sipout, stdout); if (p_logodds) *p_logodds = logodds; if (p_besti) *p_besti = besti; free(indexin); free(indexpix); free(fieldsigma2s); free(weights); free(matchxyz); free(matchxy); return sipout; }