void test_plot_wcs1(CuTest* tc) { plot_args_t myargs; plot_args_t* pargs = &myargs; int W, H; plotxy_t* xy; //plotimage_t* img; log_init(LOG_VERB); W = H = 5; plotstuff_init(pargs); plotstuff_set_size(pargs, W, H); pargs->outformat = PLOTSTUFF_FORMAT_PNG; pargs->outfn = "test-out1.png"; plotstuff_set_color(pargs, "black"); plotstuff_run_command(pargs, "fill"); plotstuff_output(pargs); plotstuff_free(pargs); // perfectly centered circle. plotstuff_init(pargs); plotstuff_set_size(pargs, W, H); pargs->outformat = PLOTSTUFF_FORMAT_PNG; pargs->outfn = "test-out2.png"; plotstuff_set_color(pargs, "black"); plotstuff_run_command(pargs, "fill"); xy = plotstuff_get_config(pargs, "xy"); plot_xy_vals(xy, 3, 3); plotstuff_set_color(pargs, "white"); plotstuff_set_marker(pargs, "circle"); plotstuff_set_markersize(pargs, 1); plotstuff_run_command(pargs, "xy"); plotstuff_output(pargs); plotstuff_free(pargs); // perfectly centered circle. plotstuff_init(pargs); plotstuff_set_size(pargs, W, H); pargs->outformat = PLOTSTUFF_FORMAT_PNG; pargs->outfn = "test-out3.png"; plotstuff_set_color(pargs, "black"); plotstuff_run_command(pargs, "fill"); xy = plotstuff_get_config(pargs, "xy"); plot_xy_vals(xy, 2, 2); plot_xy_set_offsets(xy, 0, 0); plotstuff_set_color(pargs, "white"); plotstuff_set_marker(pargs, "circle"); plotstuff_set_markersize(pargs, 1); plotstuff_run_command(pargs, "xy"); plotstuff_output(pargs); plotstuff_free(pargs); { unsigned char* img; int ww, hh; int i; img = cairoutils_read_png("test-out2.png", &ww, &hh); CuAssertPtrNotNull(tc, img); CuAssertIntEquals(tc, W, ww); CuAssertIntEquals(tc, H, hh); printf("image:\n"); for (i=0; i<W*H; i++) { printf("%02x ", (int)img[i*4]); if (i%W == (W-1)) printf("\n"); } printf("\n"); /* 00 00 00 00 00 00 80 e8 80 00 00 f3 44 f3 00 00 7c e8 7c 00 00 00 00 00 00 */ } }
int main(int argc, char** args) { int c; char* xylsfn = NULL; char* wcsfn = NULL; char* rdlsfn = NULL; xylist_t* xyls = NULL; rdlist_t* rdls = NULL; sip_t sip; int i, j; int W, H; //double xyzcenter[3]; //double fieldrad2; double pixeljitter = 1.0; int loglvl = LOG_MSG; double wcsscale; char* bgfn = NULL; //double nsigma = 3.0; fits_use_error_system(); while ((c = getopt(argc, args, OPTIONS)) != -1) { switch (c) { case 'I': bgfn = optarg; break; case 'j': pixeljitter = atof(optarg); break; case 'h': print_help(args[0]); exit(0); case 'r': rdlsfn = optarg; break; case 'x': xylsfn = optarg; break; case 'w': wcsfn = optarg; break; case 'v': loglvl++; break; } } if (optind != argc) { print_help(args[0]); exit(-1); } if (!xylsfn || !wcsfn || !rdlsfn) { print_help(args[0]); exit(-1); } log_init(loglvl); // read WCS. logmsg("Trying to parse SIP header from %s...\n", wcsfn); if (!sip_read_header_file(wcsfn, &sip)) { logmsg("Failed to parse SIP header from %s.\n", wcsfn); } // image W, H W = sip.wcstan.imagew; H = sip.wcstan.imageh; if ((W == 0.0) || (H == 0.0)) { logmsg("WCS file %s didn't contain IMAGEW and IMAGEH headers.\n", wcsfn); // FIXME - use bounds of xylist? exit(-1); } wcsscale = sip_pixel_scale(&sip); logmsg("WCS scale: %g arcsec/pixel\n", wcsscale); // read XYLS. xyls = xylist_open(xylsfn); if (!xyls) { logmsg("Failed to read an xylist from file %s.\n", xylsfn); exit(-1); } // read RDLS. rdls = rdlist_open(rdlsfn); if (!rdls) { logmsg("Failed to read an rdlist from file %s.\n", rdlsfn); exit(-1); } // Find field center and radius. /* sip_pixelxy2xyzarr(&sip, W/2, H/2, xyzcenter); fieldrad2 = arcsec2distsq(sip_pixel_scale(&sip) * hypot(W/2, H/2)); */ { // (x,y) positions of field stars. double* fieldpix; int Nfield; double* indexpix; starxy_t* xy; rd_t* rd; int Nindex; xy = xylist_read_field(xyls, NULL); if (!xy) { logmsg("Failed to read xyls entries.\n"); exit(-1); } Nfield = starxy_n(xy); fieldpix = starxy_to_xy_array(xy, NULL); logmsg("Found %i field objects\n", Nfield); // Project RDLS into pixel space. rd = rdlist_read_field(rdls, NULL); if (!rd) { logmsg("Failed to read rdls entries.\n"); exit(-1); } Nindex = rd_n(rd); logmsg("Found %i indx objects\n", Nindex); indexpix = malloc(2 * Nindex * sizeof(double)); for (i=0; i<Nindex; i++) { anbool ok; double ra = rd_getra(rd, i); double dec = rd_getdec(rd, i); ok = sip_radec2pixelxy(&sip, ra, dec, indexpix + i*2, indexpix + i*2 + 1); assert(ok); } logmsg("CRPIX is (%g,%g)\n", sip.wcstan.crpix[0], sip.wcstan.crpix[1]); /* // ?? // Look for index-field pairs that are (a) close together; and (b) close to CRPIX. // Split the image into 3x3, 5x5 or so, and in each, look for a // (small) rotation and log(scale), then (bigger) shift, using histogram // cross-correlation. // Are the rotations and scales really going to be big enough that this // is required, or can we get away with doing shift first, then fine-tuning // rotation and scale? { // NxN blocks int NB = 3; int b; // HACK - use histogram2d machinery to split image into blocks. histogram2d* blockhist = histogram2d_new_nbins(0, W, NB, 0, H, NB); int* fieldi = malloc(Nfield * sizeof(int)); int* indexi = malloc(Nindex * sizeof(int)); // rotation bins int NR = 100; // scale bins (ie, log(radius) bins) double minrad = 1.0; double maxrad = 200.0; int NS = 100; histogram2d* rsfield = histogram2d_new_nbins(-M_PI, M_PI, NR, log(minrad), log(maxrad), NS); histogram2d* rsindex = histogram2d_new_nbins(-M_PI, M_PI, NR, log(minrad), log(maxrad), NS); histogram2d_set_y_edges(rsfield, HIST2D_DISCARD); histogram2d_set_y_edges(rsindex, HIST2D_DISCARD); for (b=0; b<(NB*NB); b++) { int bin; int NF, NI; double dx, dy; NF = NI = 0; for (i=0; i<Nfield; i++) { bin = histogram2d_add(blockhist, fieldpix[2*i], fieldpix[2*i+1]); if (bin != b) continue; fieldi[NF] = i; NF++; } for (i=0; i<Nindex; i++) { bin = histogram2d_add(blockhist, indexpix[2*i], indexpix[2*i+1]); if (bin != b) continue; indexi[NI] = i; NI++; } logmsg("bin %i has %i field and %i index stars.\n", b, NF, NI); logmsg("histogramming field rotation/scale\n"); for (i=0; i<NF; i++) { for (j=0; j<i; j++) { dx = fieldpix[2*fieldi[i]] - fieldpix[2*fieldi[j]]; dy = fieldpix[2*fieldi[i]+1] - fieldpix[2*fieldi[j]+1]; histogram2d_add(rsfield, atan2(dy, dx), log(sqrt(dx*dx + dy*dy))); } } logmsg("histogramming index rotation/scale\n"); for (i=0; i<NI; i++) { for (j=0; j<i; j++) { dx = indexpix[2*indexi[i]] - fieldpix[2*indexi[j]]; dy = indexpix[2*indexi[i]+1] - fieldpix[2*indexi[j]+1]; histogram2d_add(rsindex, atan2(dy, dx), log(sqrt(dx*dx + dy*dy))); } } } histogram2d_free(rsfield); histogram2d_free(rsindex); free(fieldi); free(indexi); histogram2d_free(blockhist); } */ { double* fieldsigma2s = malloc(Nfield * sizeof(double)); int besti; int* theta; double logodds; double Q2, R2; double qc[2]; double gamma; // HACK -- quad radius-squared Q2 = square(100.0); qc[0] = sip.wcstan.crpix[0]; qc[1] = sip.wcstan.crpix[1]; // HACK -- variance growth rate wrt radius. gamma = 1.0; for (i=0; i<Nfield; i++) { R2 = distsq(qc, fieldpix + 2*i, 2); fieldsigma2s[i] = square(pixeljitter) * (1.0 + gamma * R2/Q2); } logodds = verify_star_lists(indexpix, Nindex, fieldpix, fieldsigma2s, Nfield, W*H, 0.25, log(1e-100), log(1e100), &besti, NULL, &theta, NULL, NULL); logmsg("Logodds: %g\n", logodds); if (bgfn) { plot_args_t pargs; plotimage_t* img; cairo_t* cairo; char outfn[32]; j = 0; plotstuff_init(&pargs); pargs.outformat = PLOTSTUFF_FORMAT_PNG; sprintf(outfn, "tweak-%03i.png", j); pargs.outfn = outfn; img = plotstuff_get_config(&pargs, "image"); //img->format = PLOTSTUFF_FORMAT_JPG; // guess plot_image_set_filename(img, bgfn); plot_image_setsize(&pargs, img); plotstuff_run_command(&pargs, "image"); cairo = pargs.cairo; // red circles around every field star. cairo_set_color(cairo, "red"); for (i=0; i<Nfield; i++) { cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_CIRCLE, fieldpix[2*i+0], fieldpix[2*i+1], 2.0 * sqrt(fieldsigma2s[i])); cairo_stroke(cairo); } // green crosshairs at every index star. cairo_set_color(cairo, "green"); for (i=0; i<Nindex; i++) { cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_XCROSSHAIR, indexpix[2*i+0], indexpix[2*i+1], 3); cairo_stroke(cairo); } // thick white circles for corresponding field stars. cairo_set_line_width(cairo, 2); for (i=0; i<Nfield; i++) { if (theta[i] < 0) continue; cairo_set_color(cairo, "white"); cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_CIRCLE, fieldpix[2*i+0], fieldpix[2*i+1], 2.0 * sqrt(fieldsigma2s[i])); cairo_stroke(cairo); // thick cyan crosshairs for corresponding index stars. cairo_set_color(cairo, "cyan"); cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_XCROSSHAIR, indexpix[2*theta[i]+0], indexpix[2*theta[i]+1], 3); cairo_stroke(cairo); } plotstuff_output(&pargs); } free(theta); free(fieldsigma2s); } free(fieldpix); free(indexpix); } if (xylist_close(xyls)) { logmsg("Failed to close XYLS file.\n"); } return 0; }
int main(int argc, char** args) { int c; char* xylsfn = NULL; char* wcsfn = NULL; char* rdlsfn = NULL; char* plotfn = NULL; xylist_t* xyls = NULL; rdlist_t* rdls = NULL; sip_t sip; int i; int W, H; double pixeljitter = 1.0; int loglvl = LOG_MSG; double wcsscale; fits_use_error_system(); while ((c = getopt(argc, args, OPTIONS)) != -1) { switch (c) { case 'p': plotfn = optarg; break; case 'j': pixeljitter = atof(optarg); break; case 'h': print_help(args[0]); exit(0); case 'r': rdlsfn = optarg; break; case 'x': xylsfn = optarg; break; case 'w': wcsfn = optarg; break; case 'v': loglvl++; break; } } if (optind != argc) { print_help(args[0]); exit(-1); } if (!xylsfn || !wcsfn || !rdlsfn) { print_help(args[0]); exit(-1); } log_init(loglvl); // read WCS. logmsg("Trying to parse SIP header from %s...\n", wcsfn); if (!sip_read_header_file(wcsfn, &sip)) { logmsg("Failed to parse SIP header from %s.\n", wcsfn); } // image W, H W = sip.wcstan.imagew; H = sip.wcstan.imageh; if ((W == 0.0) || (H == 0.0)) { logmsg("WCS file %s didn't contain IMAGEW and IMAGEH headers.\n", wcsfn); // FIXME - use bounds of xylist? exit(-1); } wcsscale = sip_pixel_scale(&sip); logmsg("WCS scale: %g arcsec/pixel\n", wcsscale); // read XYLS. xyls = xylist_open(xylsfn); if (!xyls) { logmsg("Failed to read an xylist from file %s.\n", xylsfn); exit(-1); } // read RDLS. rdls = rdlist_open(rdlsfn); if (!rdls) { logmsg("Failed to read an rdlist from file %s.\n", rdlsfn); exit(-1); } { // (x,y) positions of field stars. double* fieldpix; int Nfield; double* indexpix; starxy_t* xy; rd_t* rd; int Nindex; xy = xylist_read_field(xyls, NULL); if (!xy) { logmsg("Failed to read xyls entries.\n"); exit(-1); } Nfield = starxy_n(xy); fieldpix = starxy_to_xy_array(xy, NULL); logmsg("Found %i field objects\n", Nfield); // Project RDLS into pixel space. rd = rdlist_read_field(rdls, NULL); if (!rd) { logmsg("Failed to read rdls entries.\n"); exit(-1); } Nindex = rd_n(rd); logmsg("Found %i indx objects\n", Nindex); indexpix = malloc(2 * Nindex * sizeof(double)); for (i=0; i<Nindex; i++) { anbool ok; double ra = rd_getra(rd, i); double dec = rd_getdec(rd, i); ok = sip_radec2pixelxy(&sip, ra, dec, indexpix + i*2, indexpix + i*2 + 1); assert(ok); } logmsg("CRPIX is (%g,%g)\n", sip.wcstan.crpix[0], sip.wcstan.crpix[1]); { double* fieldsigma2s = malloc(Nfield * sizeof(double)); int besti; int* theta; double logodds; double Q2, R2; double qc[2]; double gamma; // HACK -- quad radius-squared Q2 = square(100.0); qc[0] = sip.wcstan.crpix[0]; qc[1] = sip.wcstan.crpix[1]; // HACK -- variance growth rate wrt radius. gamma = 1.0; for (i=0; i<Nfield; i++) { R2 = distsq(qc, fieldpix + 2*i, 2); fieldsigma2s[i] = square(pixeljitter) * (1.0 + gamma * R2/Q2); } logodds = verify_star_lists(indexpix, Nindex, fieldpix, fieldsigma2s, Nfield, W*H, 0.25, log(1e-100), log(1e100), &besti, NULL, &theta, NULL); logmsg("Logodds: %g\n", logodds); if (TRUE) { for (i=0; i<Nfield; i++) { if (theta[i] < 0) continue; printf("%g %g %g %g\n", fieldpix[2*i+0], fieldpix[2*i+1], rd_getra(rd, theta[i]), rd_getdec(rd, theta[i])); } } if (plotfn) { plot_args_t pargs; plotimage_t* img; cairo_t* cairo; plotstuff_init(&pargs); pargs.outformat = PLOTSTUFF_FORMAT_PNG; pargs.outfn = plotfn; img = plotstuff_get_config(&pargs, "image"); img->format = PLOTSTUFF_FORMAT_JPG; plot_image_set_filename(img, "1.jpg"); plot_image_setsize(&pargs, img); plotstuff_run_command(&pargs, "image"); cairo = pargs.cairo; // red circles around every field star. cairo_set_color(cairo, "red"); for (i=0; i<Nfield; i++) { cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_CIRCLE, fieldpix[2*i+0], fieldpix[2*i+1], 2.0 * sqrt(fieldsigma2s[i])); cairo_stroke(cairo); } // green crosshairs at every index star. cairo_set_color(cairo, "green"); for (i=0; i<Nindex; i++) { cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_XCROSSHAIR, indexpix[2*i+0], indexpix[2*i+1], 3); cairo_stroke(cairo); } // thick white circles for corresponding field stars. cairo_set_line_width(cairo, 2); for (i=0; i<Nfield; i++) { if (theta[i] < 0) continue; cairo_set_color(cairo, "white"); cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_CIRCLE, fieldpix[2*i+0], fieldpix[2*i+1], 2.0 * sqrt(fieldsigma2s[i])); cairo_stroke(cairo); // thick cyan crosshairs for corresponding index stars. cairo_set_color(cairo, "cyan"); cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_XCROSSHAIR, indexpix[2*theta[i]+0], indexpix[2*theta[i]+1], 3); cairo_stroke(cairo); } plotstuff_output(&pargs); } free(theta); free(fieldsigma2s); } free(fieldpix); free(indexpix); } if (xylist_close(xyls)) { logmsg("Failed to close XYLS file.\n"); } return 0; }
int main(int argc, char *args[]) { int argchar; char* progname = args[0]; plot_args_t pargs; plotxy_t* xy; plotimage_t* img; int loglvl = LOG_MSG; // log errors to stderr, not stdout. errors_log_to(stderr); plotstuff_init(&pargs); pargs.fout = stdout; pargs.outformat = PLOTSTUFF_FORMAT_PNG; xy = plotstuff_get_config(&pargs, "xy"); img = plotstuff_get_config(&pargs, "image"); assert(xy); assert(img); plotstuff_set_color(&pargs, "white"); plotstuff_set_bgcolor(&pargs, "black"); img->format = PLOTSTUFF_FORMAT_PPM; while ((argchar = getopt(argc, args, OPTIONS)) != -1) switch (argchar) { case 'v': loglvl++; break; case 'C': plotstuff_set_color(&pargs, optarg); break; case 'b': plotstuff_set_bgcolor(&pargs, "optarg"); break; case 'o': pargs.outfn = optarg; break; case 'X': plot_xy_set_xcol(xy, optarg); break; case 'Y': plot_xy_set_ycol(xy, optarg); break; case 'P': pargs.outformat = PLOTSTUFF_FORMAT_PPM; break; case 'J': pargs.outformat = PLOTSTUFF_FORMAT_PDF; break; case 'p': img->format = PLOTSTUFF_FORMAT_PNG; break; case 'I': plot_image_set_filename(img, optarg); break; case 'S': xy->scale = atof(optarg); break; case 'i': plot_xy_set_filename(xy, optarg); break; case 'x': xy->xoff = atof(optarg); break; case 'y': xy->yoff = atof(optarg); break; case 'W': pargs.W = atoi(optarg); break; case 'H': pargs.H = atoi(optarg); break; case 'n': xy->firstobj = atoi(optarg); break; case 'N': xy->nobjs = atoi(optarg); break; case 'e': xy->ext = atoi(optarg); break; case 'r': pargs.markersize = atof(optarg); break; case 'w': pargs.lw = atof(optarg); break; case 's': plotstuff_set_marker(&pargs, optarg); break; case 'h': printHelp(progname); exit(0); case '?': default: printHelp(progname); exit(-1); } if (optind != argc) { printHelp(progname); exit(-1); } if (!xy->fn) { printHelp(progname); exit(-1); } log_init(loglvl); log_to(stderr); fits_use_error_system(); if (img->fn) { if (plot_image_setsize(&pargs, img)) { ERROR("Failed to set plot size from image"); exit(-1); } plotstuff_run_command(&pargs, "image"); } else { if (pargs.W == 0 || pargs.H == 0) { if (plot_xy_setsize(&pargs, xy)) { ERROR("Failed to set plot size from xylist"); exit(-1); } } } plotstuff_run_command(&pargs, "xy"); plotstuff_output(&pargs); plotstuff_free(&pargs); return 0; }
int main(int argc, char *args[]) { int loglvl = LOG_MSG; int argchar; char* progname = args[0]; plot_args_t pargs; plotstuff_init(&pargs); pargs.fout = stdout; pargs.outformat = PLOTSTUFF_FORMAT_PNG; while ((argchar = getopt(argc, args, OPTIONS)) != -1) switch (argchar) { case 'v': loglvl++; break; case 'o': pargs.outfn = optarg; break; case 'P': pargs.outformat = PLOTSTUFF_FORMAT_PPM; break; case 'j': pargs.outformat = PLOTSTUFF_FORMAT_JPG; break; case 'J': pargs.outformat = PLOTSTUFF_FORMAT_PDF; break; case 'W': pargs.W = atoi(optarg); break; case 'H': pargs.H = atoi(optarg); break; case 'h': printHelp(progname); exit(0); case '?': default: printHelp(progname); exit(-1); } if (optind != argc) { printHelp(progname); exit(-1); } log_init(loglvl); // log errors to stderr, not stdout. errors_log_to(stderr); fits_use_error_system(); for (;;) { if (plotstuff_read_and_run_command(&pargs, stdin)) break; } if (plotstuff_output(&pargs)) exit(-1); plotstuff_free(&pargs); return 0; }
static void makeplot(const char* plotfn, char* bgimgfn, int W, int H, int Nfield, double* fieldpix, double* fieldsigma2s, int Nindex, double* indexpix, int besti, int* theta, double* crpix, int* testperm, double * qc) { int i; plot_args_t pargs; plotimage_t* img; cairo_t* cairo; int ti; logmsg("Creating plot %s\n", plotfn); plotstuff_init(&pargs); pargs.outformat = PLOTSTUFF_FORMAT_PNG; pargs.outfn = plotfn; pargs.fontsize = 12; if (bgimgfn) { img = plotstuff_get_config(&pargs, "image"); img->format = PLOTSTUFF_FORMAT_JPG; plot_image_set_filename(img, bgimgfn); plot_image_setsize(&pargs, img); plotstuff_run_command(&pargs, "image"); } else { float rgba[4] = {0, 0, 0.1, 1.0}; plotstuff_set_size(&pargs, W, H); //plotstuff_init2(&pargs); plotstuff_set_rgba(&pargs, rgba); plotstuff_run_command(&pargs, "fill"); } cairo = pargs.cairo; // red circles around every field star. cairo_set_color(cairo, "gray"); for (i=0; i<Nfield; i++) { cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_CIRCLE, fieldpix[2*i+0], fieldpix[2*i+1], 2.0 * sqrt(fieldsigma2s[i])); cairo_stroke(cairo); } // green crosshairs at every index star. cairo_set_color(cairo, "green"); for (i=0; i<Nindex; i++) { cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_XCROSSHAIR, indexpix[2*i+0], indexpix[2*i+1], 3); cairo_stroke(cairo); } // thick white circles for corresponding field stars. cairo_set_line_width(cairo, 2); for (ti=0; ti<=besti; ti++) { if (testperm) i = testperm[ti]; else i = ti; //printf("field %i -> index %i\n", i, theta[i]); if (theta[i] < 0) continue; cairo_set_color(cairo, "white"); cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_CIRCLE, fieldpix[2*i+0], fieldpix[2*i+1], 2.0 * sqrt(fieldsigma2s[i])); cairo_stroke(cairo); // thick cyan crosshairs for corresponding index stars. cairo_set_color(cairo, "cyan"); cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_XCROSSHAIR, indexpix[2*theta[i]+0], indexpix[2*theta[i]+1], 3); cairo_stroke(cairo); } cairo_set_line_width(cairo, 2); //for (i=0; i<=besti; i++) { for (ti=0; ti<Nfield; ti++) { anbool mark = TRUE; if (testperm) i = testperm[ti]; else i = ti; switch (theta[i]) { case THETA_DISTRACTOR: cairo_set_color(cairo, "red"); break; case THETA_CONFLICT: cairo_set_color(cairo, "yellow"); break; case THETA_FILTERED: cairo_set_color(cairo, "orange"); break; default: if (theta[i] < 0) { cairo_set_color(cairo, "gray"); } else { cairo_set_color(cairo, "white"); } mark = FALSE; } if (mark) { cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_CIRCLE, fieldpix[2*i+0], fieldpix[2*i+1], 2.0 * sqrt(fieldsigma2s[i])); cairo_stroke(cairo); } if (ti <= MAX(besti, 10)) { char label[32]; sprintf(label, "%i", i); plotstuff_text_xy(&pargs, fieldpix[2*i+0], fieldpix[2*i+1], label); } if (i == besti) { cairo_set_line_width(cairo, 1); } } if (crpix) { cairo_set_color(cairo, "yellow"); cairo_set_line_width(cairo, 4); cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_CROSSHAIR, crpix[0], crpix[1], 10); cairo_stroke(cairo); } if (qc) { cairo_set_color(cairo, "skyblue"); cairo_set_line_width(cairo, 4); cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_CROSSHAIR, qc[0], qc[1], 10); cairo_stroke(cairo); } plotstuff_output(&pargs); logmsg("Wrote plot %s\n", plotfn); }