コード例 #1
0
ファイル: tweak-main.c プロジェクト: Carl4/astrometry.net
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;
}
コード例 #2
0
ファイル: verify-main.c プロジェクト: dstndstn/astrometry.net
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;
}
コード例 #3
0
int main(int argc, char** args) {
    int c;
    char* wcsfn = NULL;
    char* outfn = NULL;
    char* infn = NULL;
    sip_t sip;
    double scale = 1.0;
    anbool pngformat = TRUE;

    char* hdpath = NULL;
    anbool HD = FALSE;

    cairos_t thecairos;
    cairos_t* cairos = &thecairos;

    cairo_surface_t* target = NULL;
    cairo_t* cairot = NULL;

    cairo_surface_t* surfbg = NULL;
    cairo_t* cairobg = NULL;

    cairo_surface_t* surfshapes = NULL;
    cairo_t* cairoshapes = NULL;

    cairo_surface_t* surfshapesmask = NULL;
    cairo_t* cairoshapesmask = NULL;

    cairo_surface_t* surffg = NULL;
    cairo_t* cairo = NULL;

    double lw = 2.0;
    // circle linewidth.
    double cw = 2.0;

    double ngc_fraction = 0.02;

    // NGC linewidth
    double nw = 2.0;

    // leave a gap short of connecting the points.
    double endgap = 5.0;
    // circle radius.
    double crad = endgap;

    double fontsize = 14.0;

    double label_offset = 15.0;

    int W = 0, H = 0;
    unsigned char* img = NULL;

    anbool NGC = FALSE, constell = FALSE;
    anbool bright = FALSE;
    anbool common_only = FALSE;
    anbool print_common_only = FALSE;
    int Nbright = 0;
    double ra, dec, px, py;
    int i, N;
    anbool justlist = FALSE;
    anbool only_messier = FALSE;

    anbool grid = FALSE;
    double gridspacing = 0.0;
    double gridcolor[3] = { 0.2, 0.2, 0.2 };

    int loglvl = LOG_MSG;

	char halign = 'L';
	char valign = 'C';
    sl* json = NULL;

    anbool whitetext = FALSE;

    while ((c = getopt(argc, args, OPTIONS)) != -1) {
        switch (c) {
		case 'V':
			valign = optarg[0];
			break;
		case 'O':
			halign = optarg[0];
			break;
        case 'F':
            ngc_fraction = atof(optarg);
            break;
        case 'h':
            print_help(args[0]);
            exit(0);
        case 'J':
            json = sl_new(4);
            break;
        case 'G':
            gridspacing = atof(optarg);
            break;
        case 'g':
            {
            char *tail = NULL;
            gridcolor[0] = strtod(optarg,&tail);
            if (*tail) { tail++; gridcolor[1] = strtod(tail,&tail); }
            if (*tail) { tail++; gridcolor[2] = strtod(tail,&tail); }
            }
            break;
        case 'D':
            HD = TRUE;
            break;
        case 'd':
            hdpath = optarg;
            break;
        case 'M':
            only_messier = TRUE;
            break;
        case 'n':
            nw = atof(optarg);
            break;
        case 'f':
            fontsize = atof(optarg);
            break;
        case 'L':
            justlist = TRUE;
            outfn = NULL;
            break;
        case 'x':
        	whitetext = TRUE;
        	break;
        case 'v':
            loglvl++;
            break;
            break;
        case 'j':
            print_common_only = TRUE;
            break;
        case 'c':
            common_only = TRUE;
            break;
        case 'b':
            Nbright = atoi(optarg);
            break;
        case 'B':
            bright = TRUE;
            break;
        case 'N':
            NGC = TRUE;
            break;
        case 'C':
            constell = TRUE;
            break;
        case 'p':
            pngformat = FALSE;
            break;
        case 's':
            scale = atof(optarg);
            break;
        case 'o':
            outfn = optarg;
            break;
        case 'i':
            infn = optarg;
            break;
        case 'w':
            wcsfn = optarg;
            break;
        case 'W':
            W = atoi(optarg);
            break;
        case 'H':
            H = atoi(optarg);
            break;
        }
    }

    log_init(loglvl);
    log_to(stderr);
    fits_use_error_system();

    if (optind != argc) {
        print_help(args[0]);
        exit(-1);
    }

    if (!(outfn || justlist) || !wcsfn) {
        logerr("Need (-o or -L) and -w args.\n");
        print_help(args[0]);
        exit(-1);
    }

    // read WCS.
    logverb("Trying to parse SIP/TAN header from %s...\n", wcsfn);
    if (!file_exists(wcsfn)) {
        ERROR("No such file: \"%s\"", wcsfn);
        exit(-1);
    }
    if (sip_read_header_file(wcsfn, &sip)) {
        logverb("Got SIP header.\n");
    } else {
        ERROR("Failed to parse SIP/TAN header from %s", wcsfn);
        exit(-1);
    }

    if (!(NGC || constell || bright || HD || grid)) {
        logerr("Neither constellations, bright stars, HD nor NGC/IC overlays selected!\n");
        print_help(args[0]);
        exit(-1);
    }

    if (gridspacing > 0.0)
        grid = TRUE;

    // adjust for scaling...
    lw /= scale;
    cw /= scale;
    nw /= scale;
    crad /= scale;
    endgap /= scale;
    fontsize /= scale;
    label_offset /= scale;

    if (!W || !H) {
        W = sip.wcstan.imagew;
        H = sip.wcstan.imageh;
    }
    if (!(infn || (W && H))) {
        logerr("Image width/height unspecified, and no input image given.\n");
        exit(-1);
    }


    if (infn) {
		cairoutils_fake_ppm_init();
        img = cairoutils_read_ppm(infn, &W, &H);
        if (!img) {
            ERROR("Failed to read input image %s", infn);
            exit(-1);
        }
        cairoutils_rgba_to_argb32(img, W, H);
    } else if (!justlist) {
        // Allocate a black image.
        img = calloc(4 * W * H, 1);
        if (!img) {
            SYSERROR("Failed to allocate a blank image on which to plot!");
            exit(-1);
        }
    }

    if (HD && !hdpath) {
        logerr("If you specify -D (plot Henry Draper objs), you also have to give -d (path to Henry Draper catalog)\n");
        exit(-1);
    }

    if (!justlist) {
        /*
         Cairo layers:

         -background: surfbg / cairobg
         --> gets drawn first, in black, masked by surfshapesmask

         -shapes: surfshapes / cairoshapes
         --> gets drawn second, masked by surfshapesmask

         -foreground/text: surffg / cairo
         --> gets drawn last.
         */
        surffg = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, W, H);
        cairo = cairo_create(surffg);
        cairo_set_line_join(cairo, CAIRO_LINE_JOIN_BEVEL);
        cairo_set_antialias(cairo, CAIRO_ANTIALIAS_GRAY);
        cairo_set_source_rgba(cairo, 1.0, 1.0, 1.0, 1.0);
        cairo_scale(cairo, scale, scale);
        //cairo_select_font_face(cairo, "helvetica", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
        cairo_select_font_face(cairo, "DejaVu Sans Mono Book", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
        cairo_set_font_size(cairo, fontsize);

        surfshapes = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, W, H);
        cairoshapes = cairo_create(surfshapes);
        cairo_set_line_join(cairoshapes, CAIRO_LINE_JOIN_BEVEL);
        cairo_set_antialias(cairoshapes, CAIRO_ANTIALIAS_GRAY);
        cairo_set_source_rgba(cairoshapes, 1.0, 1.0, 1.0, 1.0);
        cairo_scale(cairoshapes, scale, scale);
        cairo_select_font_face(cairoshapes, "DejaVu Sans Mono Book", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
        cairo_set_font_size(cairoshapes, fontsize);

        surfshapesmask = cairo_image_surface_create(CAIRO_FORMAT_A8, W, H);
        cairoshapesmask = cairo_create(surfshapesmask);
        cairo_set_line_join(cairoshapesmask, CAIRO_LINE_JOIN_BEVEL);
        cairo_set_antialias(cairoshapesmask, CAIRO_ANTIALIAS_GRAY);
        cairo_set_source_rgba(cairoshapesmask, 1.0, 1.0, 1.0, 1.0);
        cairo_scale(cairoshapesmask, scale, scale);
        cairo_select_font_face(cairoshapesmask, "DejaVu Sans Mono Book", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
        cairo_set_font_size(cairoshapesmask, fontsize);
        cairo_paint(cairoshapesmask);
        cairo_stroke(cairoshapesmask);

        surfbg = cairo_image_surface_create(CAIRO_FORMAT_A8, W, H);
        cairobg = cairo_create(surfbg);
        cairo_set_line_join(cairobg, CAIRO_LINE_JOIN_BEVEL);
        cairo_set_antialias(cairobg, CAIRO_ANTIALIAS_GRAY);
        cairo_set_source_rgba(cairobg, 0, 0, 0, 1);
        cairo_scale(cairobg, scale, scale);
        cairo_select_font_face(cairobg, "DejaVu Sans Mono Book", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
        cairo_set_font_size(cairobg, fontsize);

        cairos->bg = cairobg;
        cairos->fg = cairo;
        cairos->shapes = cairoshapes;
        cairos->shapesmask = cairoshapesmask;
        cairos->imgW = (float)W/scale;
        cairos->imgH = (float)H/scale;
//    }

    if (grid) {
        double ramin, ramax, decmin, decmax;
        double ra, dec;
        double rastep = gridspacing / 60.0;
        double decstep = gridspacing / 60.0;
        // how many line segments
        int N = 10;
        double px, py;
        int i;

        cairo_set_source_rgba(cairo, gridcolor[0], gridcolor[1], gridcolor[2], 1.0);

        sip_get_radec_bounds(&sip, 100, &ramin, &ramax, &decmin, &decmax);
		logverb("Plotting grid lines from RA=%g to %g in steps of %g; Dec=%g to %g in steps of %g\n",
				ramin, ramax, rastep, decmin, decmax, decstep);
        for (dec = decstep * floor(decmin / decstep); dec<=decmax; dec+=decstep) {
			logverb("  dec=%g\n", dec);
            for (i=0; i<=N; i++) {
                ra = ramin + ((double)i / (double)N) * (ramax - ramin);
                if (!sip_radec2pixelxy(&sip, ra, dec, &px, &py))
                    continue;
                // first time, move_to; else line_to
                ((ra == ramin) ? cairo_move_to : cairo_line_to)(cairo, px, py);
            }
            cairo_stroke(cairo);
        }
        for (ra = rastep * floor(ramin / rastep); ra <= ramax; ra += rastep) {
            //for (dec=decmin; dec<=decmax; dec += (decmax - decmin)/(double)N) {
			logverb("  ra=%g\n", ra);
            for (i=0; i<=N; i++) {
                dec = decmin + ((double)i / (double)N) * (decmax - decmin);
                if (!sip_radec2pixelxy(&sip, ra, dec, &px, &py))
                    continue;
                // first time, move_to; else line_to
                ((dec == decmin) ? cairo_move_to : cairo_line_to)(cairo, px, py);
            }
            cairo_stroke(cairo);
        }

        cairo_set_source_rgba(cairo, 1.0, 1.0, 1.0, 1.0);
    }
  }

    if (constell) {
        N = constellations_n();

        logverb("Checking %i constellations.\n", N);
        for (c=0; c<N; c++) {
            const char* shortname = NULL;
            const char* longname;
            il* lines;
            il* uniqstars;
            il* inboundstars;
            float r,g,b;
            int Ninbounds;
            int Nunique;
            cairo_text_extents_t textents;
            double cmass[3];

            uniqstars = constellations_get_unique_stars(c);
            inboundstars = il_new(16);

            Nunique = il_size(uniqstars);
            debug("%s: %zu unique stars.\n", shortname, il_size(uniqstars));

            // Count the number of unique stars belonging to this contellation
            // that are within the image bounds
            Ninbounds = 0;
            for (i=0; i<il_size(uniqstars); i++) {
                int star;
                star = il_get(uniqstars, i);
                constellations_get_star_radec(star, &ra, &dec);
                debug("star %i: ra,dec (%g,%g)\n", il_get(uniqstars, i), ra, dec);
                if (!sip_radec2pixelxy(&sip, ra, dec, &px, &py))
                    continue;
                if (px < 0 || py < 0 || px*scale > W || py*scale > H)
                    continue;
                Ninbounds++;
                il_append(inboundstars, star);
            }
            il_free(uniqstars);
            debug("%i are in-bounds.\n", Ninbounds);
            // Only draw this constellation if at least 2 of its stars
            // are within the image bounds.
            if (Ninbounds < 2) {
                il_free(inboundstars);
                continue;
            }

            // Set the color based on the location of the first in-bounds star.
            // This is a hack -- we have two different constellation
            // definitions with different numbering schemes!
            if (!justlist && (il_size(inboundstars) > 0)) {
                // This is helpful for videos: ensuring that the same
                // color is chosen for a constellation in each frame.
                int star = il_get(inboundstars, 0);
                constellations_get_star_radec(star, &ra, &dec);
                if (whitetext) {
                	r = g = b = 1;
                } else {
                	color_for_radec(ra, dec, &r, &g, &b);
                }
                cairo_set_source_rgba(cairoshapes, r,g,b,0.8);
                cairo_set_line_width(cairoshapes, cw);
                cairo_set_source_rgba(cairo, r,g,b,0.8);
                cairo_set_line_width(cairo, cw);
            }

            // Draw circles around each star.
            // Find center of mass (of the in-bounds stars)
            cmass[0] = cmass[1] = cmass[2] = 0.0;
            for (i=0; i<il_size(inboundstars); i++) {
                double xyz[3];
                int star = il_get(inboundstars, i);
                constellations_get_star_radec(star, &ra, &dec);
                if (!sip_radec2pixelxy(&sip, ra, dec, &px, &py))
                    continue;
                if (px < 0 || py < 0 || px*scale > W || py*scale > H)
                    continue;
                if (!justlist) {
                    cairo_arc(cairobg, px, py, crad+1.0, 0.0, 2.0*M_PI);
                    cairo_stroke(cairobg);
                    cairo_arc(cairoshapes, px, py, crad, 0.0, 2.0*M_PI);
                    cairo_stroke(cairoshapes);
                }
                radecdeg2xyzarr(ra, dec, xyz);
                cmass[0] += xyz[0];
                cmass[1] += xyz[1];
                cmass[2] += xyz[2];
            }
            cmass[0] /= il_size(inboundstars);
            cmass[1] /= il_size(inboundstars);
            cmass[2] /= il_size(inboundstars);
            xyzarr2radecdeg(cmass, &ra, &dec);

            il_free(inboundstars);

            if (!sip_radec2pixelxy(&sip, ra, dec, &px, &py))
                continue;

            shortname = constellations_get_shortname(c);
            longname = constellations_get_longname(c);
            assert(shortname && longname);

            logverb("%s at (%g, %g)\n", longname, px, py);

            if (Ninbounds == Nunique) {
                printf("The constellation %s (%s)\n", longname, shortname);
            } else {
                printf("Part of the constellation %s (%s)\n", longname, shortname);
            }

            if (justlist)
                continue;

            // If the label will be off-screen, move it back on.
            cairo_text_extents(cairo, shortname, &textents);
			
            if (px < 0)
                px = 0;
            if (py < textents.height)
                py = textents.height;
            if ((px + textents.width)*scale > W)
                px = W/scale - textents.width;
            if ((py+textents.height)*scale > H)
                py = H/scale - textents.height;
            logverb("%s at (%g, %g)\n", shortname, px, py);

            add_text(cairos, longname, px, py, halign, valign);

            // Draw the lines.
            cairo_set_line_width(cairo, lw);
            lines = constellations_get_lines(c);
            for (i=0; i<il_size(lines)/2; i++) {
                int star1, star2;
                double ra1, dec1, ra2, dec2;
                double px1, px2, py1, py2;
                double dx, dy;
                double dist;
                double gapfrac;
                star1 = il_get(lines, i*2+0);
                star2 = il_get(lines, i*2+1);
                constellations_get_star_radec(star1, &ra1, &dec1);
                constellations_get_star_radec(star2, &ra2, &dec2);
                if (!sip_radec2pixelxy(&sip, ra1, dec1, &px1, &py1) ||
                    !sip_radec2pixelxy(&sip, ra2, dec2, &px2, &py2))
                    continue;
                dx = px2 - px1;
                dy = py2 - py1;
                dist = hypot(dx, dy);
                gapfrac = endgap / dist;
                cairo_move_to(cairoshapes, px1 + dx*gapfrac, py1 + dy*gapfrac);
                cairo_line_to(cairoshapes, px1 + dx*(1.0-gapfrac), py1 + dy*(1.0-gapfrac));
                cairo_stroke(cairoshapes);
            }
            il_free(lines);
        }
        logverb("done constellations.\n");
    }

    if (bright) {
        double dy = 0;
        cairo_font_extents_t extents;
        pl* brightstars = pl_new(16);

        if (!justlist) {
            cairo_set_source_rgba(cairoshapes, 0.75, 0.75, 0.75, 0.8);
            cairo_font_extents(cairo, &extents);
            dy = extents.ascent * 0.5;
            cairo_set_line_width(cairoshapes, cw);
        }

        N = bright_stars_n();
        logverb("Checking %i bright stars.\n", N);

        for (i=0; i<N; i++) {
            const brightstar_t* bs = bright_stars_get(i);

            if (!sip_radec2pixelxy(&sip, bs->ra, bs->dec, &px, &py))
                continue;
            if (px < 0 || py < 0 || px*scale > W || py*scale > H)
                continue;
            if (!(bs->name && strlen(bs->name)))
                continue;
            if (common_only && !(bs->common_name && strlen(bs->common_name)))
                continue;

            if (strcmp(bs->common_name, "Maia") == 0)
                continue;

            pl_append(brightstars, bs);
        }

        // keep only the Nbright brightest?
        if (Nbright && (pl_size(brightstars) > Nbright)) {
            pl_sort(brightstars, sort_by_mag);
            pl_remove_index_range(brightstars, Nbright, pl_size(brightstars)-Nbright);
        }

        for (i=0; i<pl_size(brightstars); i++) {
            char* text;
            const brightstar_t* bs = pl_get(brightstars, i);

            if (!sip_radec2pixelxy(&sip, bs->ra, bs->dec, &px, &py))
                continue;
            if (bs->common_name && strlen(bs->common_name))
                if (print_common_only || common_only)
                    text = strdup(bs->common_name);
                else
                    asprintf_safe(&text, "%s (%s)", bs->common_name, bs->name);
            else
                text = strdup(bs->name);

            logverb("%s at (%g, %g)\n", text, px, py);

            if (json) {
                sl* names = sl_new(4);
                char* namearr;
                if (bs->common_name && strlen(bs->common_name))
                    sl_append(names, bs->common_name);
                if (bs->name)
					sl_append(names, bs->name);
				
                namearr = sl_join(names, "\", \"");

                sl_appendf(json,
                           "{ \"type\"  : \"star\", "
                           "  \"pixelx\": %g,       "
                           "  \"pixely\": %g,       "
                           "  \"name\"  : \"%s\",   "
                           "  \"names\" : [ \"%s\" ] } "
                           , px, py,
                           (bs->common_name && strlen(bs->common_name)) ? bs->common_name : bs->name,
                           namearr);
                free(namearr);
                sl_free2(names);
            }

            if (bs->common_name && strlen(bs->common_name))
                printf("The star %s (%s)\n", bs->common_name, bs->name);
            else
                printf("The star %s\n", bs->name);

            if (!justlist) {
                float r,g,b;
                // set color based on RA,Dec to match constellations above.
                if (whitetext) {
                	r = g = b = 1;
                } else {
                	color_for_radec(bs->ra, bs->dec, &r, &g, &b);
                }
                cairo_set_source_rgba(cairoshapes, r,g,b,0.8);
                cairo_set_source_rgba(cairo, r,g,b, 0.8);
            }

            if (!justlist)
                add_text(cairos, text, px + label_offset, py + dy,
						 halign, valign);

            free(text);

            if (!justlist) {
                // plot a black circle behind the light circle...
                cairo_arc(cairobg, px, py, crad+1.0, 0.0, 2.0*M_PI);
                cairo_stroke(cairobg);

                cairo_arc(cairoshapes, px, py, crad, 0.0, 2.0*M_PI);
                cairo_stroke(cairoshapes);
            }
        }
        pl_free(brightstars);
    }

    if (NGC) {
        double imscale;
        double imsize;
        double dy = 0;
        cairo_font_extents_t extents;

        if (!justlist) {
            cairo_set_source_rgb(cairoshapes, 1.0, 1.0, 1.0);
            cairo_set_source_rgb(cairo, 1.0, 1.0, 1.0);
            cairo_set_line_width(cairo, nw);
            cairo_font_extents(cairo, &extents);
            dy = extents.ascent * 0.5;
        }

        // arcsec/pixel
        imscale = sip_pixel_scale(&sip);
        // arcmin
        imsize = imscale * (imin(W, H) / scale) / 60.0;
        N = ngc_num_entries();

        logverb("Checking %i NGC/IC objects.\n", N);

        for (i=0; i<N; i++) {
            ngc_entry* ngc = ngc_get_entry(i);
            sl* str;
            sl* names;
            double pixsize;
            float ara, adec;
            char* text;

            if (!ngc)
                break;
            if (ngc->size < imsize * ngc_fraction)
                continue;

            if (ngcic_accurate_get_radec(ngc->is_ngc, ngc->id, &ara, &adec) == 0) {
                ngc->ra = ara;
                ngc->dec = adec;
            }

            if (!sip_radec2pixelxy(&sip, ngc->ra, ngc->dec, &px, &py))
                continue;
            if (px < 0 || py < 0 || px*scale > W || py*scale > H)
                continue;

            str = sl_new(4);
            //sl_appendf(str, "%s %i", (ngc->is_ngc ? "NGC" : "IC"), ngc->id);
            names = ngc_get_names(ngc, NULL);
            if (names) {
                int n;
                for (n=0; n<sl_size(names); n++) {
                    if (only_messier && strncmp(sl_get(names, n), "M ", 2))
                        continue;
                    sl_append(str, sl_get(names, n));
                }
            }
            sl_free2(names);

            text = sl_implode(str, " / ");

            printf("%s\n", text);

            pixsize = ngc->size * 60.0 / imscale;

            if (!justlist) {
                // black circle behind the white one...
                cairo_arc(cairobg, px, py, pixsize/2.0+1.0, 0.0, 2.0*M_PI);
                cairo_stroke(cairobg);

                cairo_move_to(cairoshapes, px + pixsize/2.0, py);
                cairo_arc(cairoshapes, px, py, pixsize/2.0, 0.0, 2.0*M_PI);
                debug("size: %f arcsec, pixsize: %f pixels\n", ngc->size, pixsize);
                cairo_stroke(cairoshapes);

                add_text(cairos, text, px + label_offset, py + dy,
						 halign, valign);
            }

            if (json) {
                char* namelist = sl_implode(str, "\", \"");
                sl_appendf(json,
                           "{ \"type\"   : \"ngc\", "
                           "  \"names\"  : [ \"%s\" ], "
                           "  \"pixelx\" : %g, "
                           "  \"pixely\" : %g, "
                           "  \"radius\" : %g }"
                           , namelist, px, py, pixsize/2.0);
                free(namelist);
            }

            free(text);
            sl_free2(str);
        }
    }

    if (HD) {
        double rac, decc, ra2, dec2;
        double arcsec;
        hd_catalog_t* hdcat;
        bl* hdlist;
        int i;

        if (!justlist)
            cairo_set_source_rgb(cairo, 1.0, 1.0, 1.0);

		logverb("Reading HD catalog: %s\n", hdpath);
        hdcat = henry_draper_open(hdpath);
        if (!hdcat) {
            ERROR("Failed to open HD catalog");
            exit(-1);
        }
		logverb("Got %i HD stars\n", henry_draper_n(hdcat));

        sip_pixelxy2radec(&sip, W/(2.0*scale), H/(2.0*scale), &rac, &decc);
        sip_pixelxy2radec(&sip, 0.0, 0.0, &ra2, &dec2);
        arcsec = arcsec_between_radecdeg(rac, decc, ra2, dec2);
        // Fudge
        arcsec *= 1.1;
        hdlist = henry_draper_get(hdcat, rac, decc, arcsec);
		logverb("Found %zu HD stars within range (%g arcsec of RA,Dec %g,%g)\n", bl_size(hdlist), arcsec, rac, decc);

        for (i=0; i<bl_size(hdlist); i++) {
            double px, py;
            char* txt;
            hd_entry_t* hd = bl_access(hdlist, i);
            if (!sip_radec2pixelxy(&sip, hd->ra, hd->dec, &px, &py)) {
                continue;
			}
            if (px < 0 || py < 0 || px*scale > W || py*scale > H) {
				logverb("  HD %i at RA,Dec (%g, %g) -> pixel (%.1f, %.1f) is out of bounds\n",
						hd->hd, hd->ra, hd->dec, px, py);
                continue;
			}
            asprintf_safe(&txt, "HD %i", hd->hd);
            if (!justlist) {
                cairo_text_extents_t textents;
                cairo_text_extents(cairo, txt, &textents);
                cairo_arc(cairobg, px, py, crad+1.0, 0.0, 2.0*M_PI);
                cairo_stroke(cairobg);
                cairo_arc(cairoshapes, px, py, crad, 0.0, 2.0*M_PI);
                cairo_stroke(cairoshapes);

                px -= (textents.width * 0.5);
                py -= (crad + 4.0);

                add_text(cairos, txt, px, py, halign, valign);
            }

            if (json)
                sl_appendf(json,
                           "{ \"type\"  : \"hd\","
                           "  \"pixelx\": %g, "
                           "  \"pixely\": %g, "
                           "  \"name\"  : \"HD %i\" }"
                           , px, py, hd->hd);

            printf("%s\n", txt);
            free(txt);
        }
        bl_free(hdlist);
        henry_draper_close(hdcat);
    }

    if (json) {
        FILE* fout = stderr;
        char* annstr = sl_implode(json, ",\n");
        fprintf(fout, "{ \n");
        fprintf(fout, "  \"status\": \"solved\",\n");
        fprintf(fout, "  \"git-revision\": %s,\n", AN_GIT_REVISION);
        fprintf(fout, "  \"git-date\": \"%s\",\n", AN_GIT_DATE);
        fprintf(fout, "  \"annotations\": [\n%s\n]\n", annstr);
        fprintf(fout, "}\n");
        free(annstr);
    }
    sl_free2(json);
    json = NULL;

    if (justlist)
        return 0;

    target = cairo_image_surface_create_for_data(img, CAIRO_FORMAT_ARGB32, W, H, W*4);
    cairot = cairo_create(target);
    cairo_set_source_rgba(cairot, 0, 0, 0, 1);

    // Here's where you set the background surface's properties...
    cairo_set_source_surface(cairot, surfbg, 0, 0);
    cairo_mask_surface(cairot, surfshapesmask, 0, 0);
    cairo_stroke(cairot);

    // Add on the shapes.
    cairo_set_source_surface(cairot, surfshapes, 0, 0);
    //cairo_mask_surface(cairot, surfshapes, 0, 0);
    cairo_mask_surface(cairot, surfshapesmask, 0, 0);
    cairo_stroke(cairot);

    // Add on the foreground.
    cairo_set_source_surface(cairot, surffg, 0, 0);
    cairo_mask_surface(cairot, surffg, 0, 0);
    cairo_stroke(cairot);

    // Convert image for output...
    cairoutils_argb32_to_rgba(img, W, H);

    if (pngformat) {
        if (cairoutils_write_png(outfn, img, W, H)) {
            ERROR("Failed to write PNG");
            exit(-1);
        }
    } else {
        if (cairoutils_write_ppm(outfn, img, W, H)) {
            ERROR("Failed to write PPM");
            exit(-1);
        }
    }

    cairo_surface_destroy(target);
    cairo_surface_destroy(surfshapesmask);
    cairo_surface_destroy(surffg);
    cairo_surface_destroy(surfbg);
    cairo_surface_destroy(surfshapes);
    cairo_destroy(cairo);
    cairo_destroy(cairot);
    cairo_destroy(cairobg);
    cairo_destroy(cairoshapes);
    cairo_destroy(cairoshapesmask);
    free(img);

    return 0;
}
コード例 #4
0
ファイル: solve-field.c プロジェクト: Carl4/astrometry.net
// This runs after "astrometry-engine" is run on the file.
static void after_solved(augment_xylist_t* axy,
						 solve_field_args_t* sf,
						 anbool makeplots,
						 const char* me,
						 anbool verbose,
						 const char* tempdir,
						 sl* tempdirs,
						 sl* tempfiles,
						 double plotscale,
						 const char* bgfn) {
	sip_t wcs;
	double ra, dec, fieldw, fieldh;
	char rastr[32], decstr[32];
	char* fieldunits;

	// print info about the field.
	logmsg("Field: %s\n", axy->imagefn ? axy->imagefn : axy->xylsfn);
	if (file_exists(axy->wcsfn)) {
		double orient;
		if (axy->wcs_last_mod) {
			time_t t = file_get_last_modified_time(axy->wcsfn);
			if (t == axy->wcs_last_mod) {
				logmsg("Warning: there was already a WCS file, and its timestamp has not changed.\n");
			}
		}
		if (!sip_read_header_file(axy->wcsfn, &wcs)) {
			ERROR("Failed to read WCS header from file %s", axy->wcsfn);
			exit(-1);
		}
		sip_get_radec_center(&wcs, &ra, &dec);
		sip_get_radec_center_hms_string(&wcs, rastr, decstr);
		sip_get_field_size(&wcs, &fieldw, &fieldh, &fieldunits);
		orient = sip_get_orientation(&wcs);
		logmsg("Field center: (RA,Dec) = (%3.6f, %3.6f) deg.\n", ra, dec);
		logmsg("Field center: (RA H:M:S, Dec D:M:S) = (%s, %s).\n", rastr, decstr);
		logmsg("Field size: %g x %g %s\n", fieldw, fieldh, fieldunits);
		logmsg("Field rotation angle: up is %g degrees E of N\n", orient);
	} else {
		logmsg("Did not solve (or no WCS file was written).\n");
	}

	// create new FITS file...
	if (axy->fitsimgfn && sf->newfitsfn && file_exists(axy->wcsfn)) {
		logmsg("Creating new FITS file \"%s\"...\n", sf->newfitsfn);
		if (new_wcs(axy->fitsimgfn, axy->wcsfn, sf->newfitsfn, TRUE)) {
			ERROR("Failed to create FITS image with new WCS headers");
			exit(-1);
		}
	}

	// write list of index stars in image coordinates
	if (sf->indxylsfn && file_exists(axy->wcsfn) && file_exists(axy->rdlsfn)) {
		assert(axy->wcsfn);
		assert(axy->rdlsfn);
		// index rdls to xyls.
		if (wcs_rd2xy(axy->wcsfn, 0, axy->rdlsfn, sf->indxylsfn,
					  NULL, NULL, FALSE, FALSE, NULL)) {
			ERROR("Failed to project index stars into field coordinates using wcs-rd2xy");
			exit(-1);
		}
	}

	if (makeplots && file_exists(sf->indxylsfn) && file_readable(axy->matchfn) && file_readable(axy->wcsfn)) {
		logmsg("Creating index object overlay plot...\n");
		if (plot_index_overlay(axy, me, sf->indxylsfn, sf->redgreenfn, plotscale, bgfn)) {
			ERROR("Plot index overlay failed.");
		}
	}

	if (makeplots && file_readable(axy->wcsfn)) {
		logmsg("Creating annotation plot...\n");
		if (plot_annotations(axy, me, verbose, sf->ngcfn, plotscale, bgfn)) {
			ERROR("Plot annotations failed.");
		}
	}

	if (axy->imagefn && sf->kmzfn && file_exists(axy->wcsfn)) {
		logmsg("Writing kmz file...\n");
		if (write_kmz(axy, sf->kmzfn, tempdir, tempdirs, tempfiles)) {
			ERROR("Failed to write KMZ.");
			exit(-1);
		}
	}

	if (sf->scampfn && file_exists(axy->wcsfn)) {
		//char* hdrfile = NULL;
		qfits_header* imageheader = NULL;
		starxy_t* xy;
		xylist_t* xyls;

		xyls = xylist_open(axy->axyfn);
		if (!xyls) {
			ERROR("Failed to read xylist to write SCAMP catalog");
			exit(-1);
		}
		if (axy->xcol)
			xylist_set_xname(xyls, axy->xcol);
		if (axy->ycol)
			xylist_set_yname(xyls, axy->ycol);
		//xylist_set_include_flux(xyls, FALSE);
		xylist_set_include_background(xyls, FALSE);
		xy = xylist_read_field(xyls, NULL);
		xylist_close(xyls);

		if (axy->fitsimgfn) {
			//hdrfile = axy->fitsimgfn;
			imageheader = anqfits_get_header2(axy->fitsimgfn, 0);
		}
		if (axy->xylsfn) {
			char val[32];
			//hdrfile = axy->xylsfn;
			imageheader = anqfits_get_header2(axy->xylsfn, 0);
			// Set NAXIS=2, NAXIS1=IMAGEW, NAXIS2=IMAGEH
			fits_header_mod_int(imageheader, "NAXIS", 2, NULL);
			sprintf(val, "%i", axy->W);
			qfits_header_add_after(imageheader, "NAXIS",  "NAXIS1", val, "image width", NULL);
			sprintf(val, "%i", axy->H);
			qfits_header_add_after(imageheader, "NAXIS1", "NAXIS2", val, "image height", NULL);
			//fits_header_add_int(imageheader, "NAXIS1", axy->W, NULL);
			//fits_header_add_int(imageheader, "NAXIS2", axy->H, NULL);
			logverb("Using NAXIS 1,2 = %i,%i\n", axy->W, axy->H);
		}

		if (scamp_write_field(imageheader, &wcs, xy, sf->scampfn)) {
			ERROR("Failed to write SCAMP catalog");
			exit(-1);
		}
		starxy_free(xy);
		if (imageheader)
			qfits_header_destroy(imageheader);
	}

	if (sf->scampconfigfn) {
		if (scamp_write_config_file(axy->scampfn, sf->scampconfigfn)) {
			ERROR("Failed to write SCAMP config file snippet to %s", sf->scampconfigfn);
			exit(-1);
		}
	}
}