Example #1
0
void plotstuff_stack_text(plot_args_t* pargs, cairo_t* cairo,
						  const char* txt, double px, double py) {
	cairocmd_t cmd;
	cairocmd_init(&cmd);
	set_cmd_args(pargs, &cmd);
	get_text_position(pargs, cairo, txt, &px, &py);
	cmd.type = TEXT;

	if (pargs->bg_rgba[3] > 0) {
		int dx, dy;
		logverb("Background text RGB [%g, %g, %g] alpha %g\n",
				pargs->bg_rgba[0], pargs->bg_rgba[1], 
				pargs->bg_rgba[2], pargs->bg_rgba[3]);
		cmd.layer = pargs->text_bg_layer;
		memcpy(cmd.rgba, pargs->bg_rgba, sizeof(cmd.rgba));
		for (dy=-1; dy<=1; dy++) {
			for (dx=-1; dx<=1; dx++) {
				cmd.text = strdup(txt);
				cmd.x = px + dx;
				cmd.y = py + dy;
				add_cmd(pargs, &cmd);
			}
		}
	} else
		logverb("No background behind text\n");

	cmd.layer = pargs->text_fg_layer;
	memcpy(cmd.rgba, pargs->rgba, sizeof(cmd.rgba));
	cmd.text = strdup(txt);
    cmd.x = px;
	cmd.y = py;
	add_cmd(pargs, &cmd);
}
Example #2
0
int multiindex_add_index(multiindex_t* mi, const char* fn, int flags) {
	anqfits_t* fits;
	quadfile_t* quads = NULL;
	codetree_t* codes = NULL;
	index_t* ind = NULL;
	logverb("Reading index file \"%s\"...\n", fn);
    fits = anqfits_open(fn);
	if (!fits) {
		ERROR("Failed to open FITS file \"%s\"", fn);
		goto bailout;
	}
	logverb("Reading quads from file \"%s\"...\n", fn);
	quads = quadfile_open_fits(fits);
	if (!quads) {
		ERROR("Failed to read quads from file \"%s\"", fn);
		anqfits_close(fits);
		goto bailout;
	}
	logverb("Reading codes from file \"%s\"...\n", fn);
	codes = codetree_open_fits(fits);
	if (!codes) {
		ERROR("Failed to read quads from file \"%s\"", fn);
		quadfile_close(quads);
		anqfits_close(fits);
		goto bailout;
	}
	
	ind = index_build_from(codes, quads, mi->starkd);
	ind->fits = fits;
	if (!ind->indexname)
		ind->indexname = strdup(fn);
    // shouldn't be needed, but set anyway
    ind->quadfn = strdup(fn);
    ind->codefn = strdup(fn);

	pl_append(mi->inds, ind);

    if (flags & INDEX_ONLY_LOAD_METADATA) {
        // don't let it unload the starkd!
        ind->starkd = NULL;
        index_unload(ind);
        ind->starkd = mi->starkd;
    }

	return 0;
 bailout:
	if (quads) {
		quadfile_close(quads);
	}
	if (codes) {
		codetree_close(codes);
	}
	if (fits) {
		anqfits_close(fits);
	}
	return -1;
}
Example #3
0
static int plot_annotations(augment_xylist_t* axy, const char* me, anbool verbose,
                            const char* annfn, double plotscale, const char* bgfn) {
    sl* cmdline = sl_new(16);
    char* cmd;
    sl* lines;
	char* imgfn;

	imgfn = axy->pnmfn;
	if (bgfn) {
		append_executable(cmdline, "jpegtopnm", me);
		append_escape(cmdline, bgfn);
		sl_append(cmdline, "|");
		imgfn = "-";
	} else if (axy->imagefn && plotscale != 1.0) {
		append_executable(cmdline, "pnmscale", me);
		sl_appendf(cmdline, "%f", plotscale);
        append_escape(cmdline, axy->pnmfn);
		sl_append(cmdline, "|");
		imgfn = "-";
	}

    append_executable(cmdline, "plot-constellations", me);
    if (verbose)
        sl_append(cmdline, "-v");
    sl_append(cmdline, "-w");
	assert(axy->wcsfn);
    append_escape(cmdline, axy->wcsfn);

	sl_append(cmdline, "-i");
	append_escape(cmdline, imgfn);
	if (plotscale != 1.0) {
		sl_append(cmdline, "-s");
		sl_appendf(cmdline, "%f", plotscale);
	}
    sl_append(cmdline, "-N");
    sl_append(cmdline, "-B");
    sl_append(cmdline, "-C");
    sl_append(cmdline, "-o");
	assert(annfn);
    append_escape(cmdline, annfn);
    cmd = sl_implode(cmdline, " ");
    sl_free2(cmdline);
    logverb("Running:\n  %s\n", cmd);
    if (run_command_get_outputs(cmd, &lines, NULL)) {
        ERROR("plot-constellations failed");
        return -1;
    }
    free(cmd);
    if (lines && sl_size(lines)) {
        int i;
        if (strlen(sl_get(lines, 0))) {
            logmsg("Your field contains:\n");
            for (i=0; i<sl_size(lines); i++)
                logmsg("  %s\n", sl_get(lines, i));
        }
    }
    if (lines)
        sl_free2(lines);
    return 0;
}
Example #4
0
static int wcslib_pixelxy2radec(const anwcslib_t* anwcslib, double px, double py, double* ra, double* dec) {
	double pix[2];
	double world[2];
	double phi;
	double theta;
	double imgcrd[2];
	int status = 0;
	int code;
	struct wcsprm* wcs = anwcslib->wcs;
	pix[0] = px;
	pix[1] = py;
	code = wcsp2s(wcs, 1, 0, pix, imgcrd, &phi, &theta, world, &status);
	/*
	 int wcsp2s(struct wcsprm *wcs, int ncoord, int nelem, const double pixcrd[],
	 double imgcrd[], double phi[], double theta[], double world[],
	 int stat[]);
	 */
	if (code) {
		//ERROR("Wcslib's wcsp2s() failed: code=%i, status=%i (%s); (x,y)=(%g,%g)", code, status, wcs_errmsg[status], px, py);
        logverb("Wcslib's wcsp2s() failed: code=%i, status=%i (%s); (x,y)=(%g,%g)", code, status, wcs_errmsg[status], px, py);
		return -1;
	}
	if (ra)  *ra  = world[wcs->lng];
	if (dec) *dec = world[wcs->lat];
	return 0;
}
int main(int argc, char** args) {
    pthread_t thread1;
    pthread_t thread2;
    pthread_attr_t attr;
    char* job1 = "job1.axy";
    char* job2 = "job2.axy";

    fits_use_error_system();
    
    log_init(LOG_VERB);
    log_set_thread_specific();

	logverb("Hello world!\n");

    be = engine_new();
    engine_parse_config_file(be, "astrometry.cfg");

    pthread_mutex_init(&read_job_mutex, NULL);

    pthread_attr_init(&attr);
    pthread_create(&thread1, &attr, threadfunc, job1);
    pthread_create(&thread2, &attr, threadfunc, job2);

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    pthread_mutex_destroy(&read_job_mutex);

    engine_free(be);

    return 0;
}
Example #6
0
int coadd_add_image(coadd_t* ca, const number* img,
					const number* weightimg,
					number weight, const anwcs_t* wcs) {
	int W, H;
	int i, j;
	int xlo,xhi,ylo,yhi;
	check_bounds_t cb;

	W = anwcs_imagew(wcs);
	H = anwcs_imageh(wcs);

	// if check_bounds:
	cb.xlo = W;
	cb.xhi = 0;
	cb.ylo = H;
	cb.yhi = 0;
	cb.wcs = ca->wcs;
	anwcs_walk_image_boundary(wcs, 50, check_bounds, &cb);
	xlo = MAX(0,     floor(cb.xlo));
	xhi = MIN(ca->W,  ceil(cb.xhi)+1);
	ylo = MAX(0,     floor(cb.ylo));
	yhi = MIN(ca->H,  ceil(cb.yhi)+1);
	logmsg("Image projects to output image region: [%i,%i), [%i,%i)\n", xlo, xhi, ylo, yhi);

	for (i=ylo; i<yhi; i++) {
		for (j=xlo; j<xhi; j++) {
			double ra, dec;
			double px, py;
			double wt;
			double val;

			// +1 for FITS
			if (anwcs_pixelxy2radec(ca->wcs, j+1, i+1, &ra, &dec)) {
				ERROR("Failed to project pixel (%i,%i) through output WCS\n", j, i);
				continue;
			}
			if (anwcs_radec2pixelxy(wcs, ra, dec, &px, &py)) {
				ERROR("Failed to project pixel (%i,%i) through input WCS\n", j, i);
				continue;
			}
			// -1 for FITS
			px -= 1;
			py -= 1;

			if (px < 0 || px >= W)
				continue;
			if (py < 0 || py >= H)
				continue;

			val = ca->resample_func(px, py, img, weightimg, W, H, &wt,
									ca->resample_token);
			ca->img[i*ca->W + j] += val * weight;
			ca->weight[i*ca->W + j] += wt * weight;
		}
		logverb("Row %i of %i\n", i+1, ca->H);
	}
	return 0;
}
Example #7
0
void* thread2(void* v) {
    FILE* flog = v;
    logmsg("I'm thread 2.\n");
    log_set_level(LOG_VERB);
    log_to(flog);
    logmsg("%s\n", STRING2A);
    logverb("%s\n", STRING2B);
    return NULL;
}
Example #8
0
static void plot_hd(cairo_t* cairo, plot_args_t* pargs, plotann_t* ann) {
	int i, N;
	hd_catalog_t* hdcat = NULL;
	double ra,dec,rad;
	bl* hdlist = NULL;

	if (!ann->hd_catalog)
		return;
	hdcat = henry_draper_open(ann->hd_catalog);
	if (!hdcat) {
		ERROR("Failed to open Henry Draper catalog file \"%s\"", ann->hd_catalog);
		return;
	}
	if (plotstuff_get_radec_center_and_radius(pargs, &ra, &dec, &rad)) {
		ERROR("Failed to get RA,Dec,radius from plotstuff");
		return;
	}
	hdlist = henry_draper_get(hdcat, ra, dec, deg2arcsec(rad));
	logverb("Got %zu Henry Draper stars\n", bl_size(hdlist));
	
	N = bl_size(hdlist);
	for (i=0; i<N; i++) {
		hd_entry_t* entry = bl_access(hdlist, i);
		double px, py;
		char label[16];
		if (!plotstuff_radec2xy(pargs, entry->ra, entry->dec, &px, &py))
			continue;
        px -= 1;
        py -= 1;

		if (px < 1 || py < 1 || px > pargs->W || py > pargs->H)
			continue;
		logverb("HD %i at RA,Dec (%g,%g) -> xy (%g, %g)\n", entry->hd, entry->ra, entry->dec, px, py);

		plotstuff_stack_marker(pargs, px, py);
        if (ann->HD_labels) {
          sprintf(label, "HD %i", entry->hd);
          plotstuff_stack_text(pargs, cairo, label, px, py);
        }
	}
	bl_free(hdlist);
	henry_draper_close(hdcat);
}
Example #9
0
void* thread1(void* v) {
    FILE* flog = v;
    logmsg("I'm thread 1.\n");
    log_set_level(LOG_MSG);
    log_to(flog);
    logmsg("%s\n", STRING1A);
    sleep(1);
    logverb("%s\n", STRING1B);
    return NULL;
}
Example #10
0
static void add_quad(quadbuilder_t* qb, unsigned int* quad, void* token) {
	allquads_t* aq = token;
	if (log_get_level() > LOG_VERB) {
		int k;
		debug("quad: ");
		for (k=0; k<qb->dimquads; k++)
			debug("%-6i ", quad[k]);
		logverb("\n");
	}
	quad_write_const(aq->codes, aq->quads, quad, aq->starkd, qb->dimquads, aq->dimcodes);
}
Example #11
0
static void delete_temp_files(sl* tempfiles, sl* tempdirs) {
	int i;
    if (tempfiles) {
        for (i=0; i<sl_size(tempfiles); i++) {
            char* fn = sl_get(tempfiles, i);
            logverb("Deleting temp file %s\n", fn);
            if (unlink(fn))
                SYSERROR("Failed to delete temp file \"%s\"", fn);
        }
        sl_remove_all(tempfiles);
    }
    if (tempdirs) {
        for (i=0; i<sl_size(tempdirs); i++) {
            char* fn = sl_get(tempdirs, i);
            logverb("Deleting temp dir %s\n", fn);
            if (rmdir(fn))
                SYSERROR("Failed to delete temp dir \"%s\"", fn);
        }
        sl_remove_all(tempdirs);
    }
}
Example #12
0
int plotstuff_read_and_run_command(plot_args_t* pargs, FILE* f) {
	char* cmd;
	int rtn;
	cmd = read_string_terminated(stdin, "\n\r\0", 3, FALSE);
	logverb("command: \"%s\"\n", cmd);
	if (!cmd || feof(f)) {
		free(cmd);
		return -1;
	}
	rtn = plotstuff_run_command(pargs, cmd);
	free(cmd);
	return rtn;
}
Example #13
0
static void run_engine(sl* engineargs) {
	char* cmd;
	cmd = sl_implode(engineargs, " ");
	logmsg("Solving...\n");
	logverb("Running:\n  %s\n", cmd);
	fflush(NULL);
	if (run_command_get_outputs(cmd, NULL, NULL)) {
		ERROR("engine failed.  Command that failed was:\n  %s", cmd);
		exit(-1);
	}
	free(cmd);
	fflush(NULL);
}
Example #14
0
void* threadfunc(void* arg) {
    char* jobfn = arg;

	logverb("Hello from thread-land!\n");
    
    //pthread_mutex_lock(&read_job_mutex);
    job_t* job = engine_read_job_file(be, jobfn);
    //pthread_mutex_unlock(&read_job_mutex);

    engine_run_job(be, job);
    job_free(job);
    return NULL;
}
Example #15
0
int startree_write_tagalong_table(fitstable_t* intab, fitstable_t* outtab,
								  const char* racol, const char* deccol) {
	int i, R, NB, N;
	char* buf;
	qfits_header* hdr;
	
	fitstable_clear_table(intab);
	fitstable_add_fits_columns_as_struct(intab);
	fitstable_copy_columns(intab, outtab);
	if (!racol)
		racol = "RA";
	if (!deccol)
		deccol = "DEC";
	fitstable_remove_column(outtab, racol);
	fitstable_remove_column(outtab, deccol);
    fitstable_read_extension(intab, 1);
	hdr = fitstable_get_header(outtab);
	qfits_header_add(hdr, "AN_FILE", AN_FILETYPE_TAGALONG, "Extra data for stars", NULL);
	if (fitstable_write_header(outtab)) {
		ERROR("Failed to write tag-along data header");
		return -1;
	}
	R = fitstable_row_size(intab);
	NB = 1000;
	logverb("Input row size: %i, output row size: %i\n", R, fitstable_row_size(outtab));
	buf = malloc(NB * R);
	N = fitstable_nrows(intab);
	
	for (i=0; i<N; i+=NB) {
		int nr = NB;
		if (i+NB > N)
			nr = N - i;
		if (fitstable_read_structs(intab, buf, R, i, nr)) {
			ERROR("Failed to read tag-along data from catalog");
			return -1;
		}
		if (fitstable_write_structs(outtab, buf, R, nr)) {
			ERROR("Failed to write tag-along data");
			return -1;
		}
	}
	free(buf);
	if (fitstable_fix_header(outtab)) {
		ERROR("Failed to fix tag-along data header");
		return -1;
	}
	return 0;
}
Example #16
0
int plotstuff_init2(plot_args_t* pargs) {
	int i;

	logverb("Creating drawing surface (%ix%i)\n", pargs->W, pargs->H);
	// Allocate cairo surface
	switch (pargs->outformat) {
	case PLOTSTUFF_FORMAT_PDF:
		if (pargs->outfn) {
			pargs->fout = fopen(pargs->outfn, "wb");
			if (!pargs->fout) {
				SYSERROR("Failed to open output file \"%s\"", pargs->outfn);
				return -1;
			}
		}
		pargs->target = cairo_pdf_surface_create_for_stream(cairoutils_file_write_func, pargs->fout, pargs->W, pargs->H);
		break;
	case PLOTSTUFF_FORMAT_JPG:
	case PLOTSTUFF_FORMAT_PPM:
	case PLOTSTUFF_FORMAT_PNG:
	case PLOTSTUFF_FORMAT_MEMIMG:
		pargs->target = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, pargs->W, pargs->H);
		break;
	default:
		ERROR("Unknown output format %i", pargs->outformat);
		return -1;
		break;
	}
	pargs->cairo = cairo_create(pargs->target);

	/* D'oh, this flips the coord sys, but not text!
	 // Flip the cairo reference frame (make 0,0 the bottom-left)
	 cairo_scale(pargs->cairo, 1.0, -1.0);
	 // FIXME -- could deal with 0.5 issues here!
	 cairo_translate(pargs->cairo, 0.0, -pargs->H);
	 */

	for (i=0; i<pargs->NP; i++) {
		if (pargs->plotters[i].init2 &&
			pargs->plotters[i].init2(pargs, pargs->plotters[i].baton)) {
			ERROR("Plot initializer failed");
			exit(-1);
		}
	}

	return 0;
}
Example #17
0
multiindex_t* multiindex_new(const char* skdtfn) {
	multiindex_t* mi = calloc(1, sizeof(multiindex_t));
	logverb("Reading star KD tree from %s...\n", skdtfn);
	mi->fits = anqfits_open(skdtfn);
	if (!mi->fits) {
		ERROR("Failed to open multiindex file \"%s\"", skdtfn);
        goto bailout;
	}
	mi->inds = pl_new(16);
    if (multiindex_reload_starkd(mi)) {
		ERROR("Failed to open multiindex star kd-tree \"%s\"", skdtfn);
		goto bailout;
	}
	return mi;
bailout:
	multiindex_free(mi);
	return NULL;
}
Example #18
0
static void plot_brightstars(cairo_t* cairo, plot_args_t* pargs, plotann_t* ann) {
	int i, N;

    // Get plot center, to use in trimming bright stars
    double rc,dc,radius;
    plotstuff_get_radec_center_and_radius(pargs, &rc, &dc, &radius);

	N = bright_stars_n();
	for (i=0; i<N; i++) {
		double px, py;
		char* label;
		const brightstar_t* bs = bright_stars_get(i);
		// skip unnamed
		if (!strlen(bs->name) && !strlen(bs->common_name))
			continue;
        // skip stars too far away
        if (deg_between_radecdeg(rc, dc, bs->ra, bs->dec) > radius * 1.2)
            continue;
		if (!plotstuff_radec2xy(pargs, bs->ra, bs->dec, &px, &py))
			continue;
		logverb("Bright star %s/%s at RA,Dec (%g,%g) -> xy (%g, %g)\n",
                bs->name, bs->common_name, bs->ra, bs->dec, px, py);
		if (px < 1 || py < 1 || px > pargs->W || py > pargs->H)
			continue;
        px -= 1;
        py -= 1;
        if (ann->bright_pastel) {
            float r,g,b;
            color_for_radec(bs->ra, bs->dec, &r,&g,&b);
            plotstuff_set_rgba2(pargs, r,g,b, 0.8);
            plotstuff_builtin_apply(cairo, pargs);
        }

		plotstuff_stack_marker(pargs, px, py);
        if (ann->bright_labels) {
          label = (strlen(bs->common_name) ? bs->common_name : bs->name);
          plotstuff_stack_text(pargs, cairo, label, px, py);
        }
	}
}
Example #19
0
static int run_command(const char* cmd, anbool* ctrlc) {
	int rtn;
    logverb("Running: %s\n", cmd);
    fflush(NULL);
	rtn = system(cmd);
    fflush(NULL);
	if (rtn == -1) {
		SYSERROR("Failed to run command \"%s\"", cmd);
		return -1;
	}
	if (WIFSIGNALED(rtn)) {
        if (ctrlc && (WTERMSIG(rtn) == SIGTERM))
            *ctrlc = TRUE;
		return -1;
	}
	rtn = WEXITSTATUS(rtn);
	if (rtn) {
		ERROR("Command exited with exit status %i", rtn);
        ERROR("Command was: \"%s\"\n", cmd);
    }
	return rtn;
}
Example #20
0
int plotstuff_line_constant_ra(plot_args_t* pargs, double ra, double dec1, double dec2,
							   anbool startwithmove) {
	double decstep;
	double dec;
	double s;
	double pixscale;
	anbool lastok = FALSE;
	if (!startwithmove)
		lastok = TRUE;
	assert(pargs->wcs);
	pixscale = anwcs_pixel_scale(pargs->wcs);
	assert(pixscale > 0.0);
	decstep = arcsec2deg(pixscale * pargs->linestep);
	logverb("plotstuff_line_constant_ra: RA=%g, Dec=[%g,%g], pixscale %g, decstep %g\n",
			ra, dec1, dec2, anwcs_pixel_scale(pargs->wcs), decstep);
	//printf("plotstuff_line_constant_ra: RA=%g, Dec=[%g,%g], pixscale %g, decstep %g\n",
	//ra, dec1, dec2, anwcs_pixel_scale(pargs->wcs), decstep);
	s = 1.0;
	if (dec1 > dec2)
		s = -1;
	for (dec=dec1; (s*dec)<=(s*dec2); dec+=(decstep*s)) {
		double x, y;
		//logverb("  line_constant_ra: RA,Dec %g,%g\n", ra, dec);
		//printf("  line_constant_ra: RA,Dec %g,%g\n", ra, dec);
		if (anwcs_radec2pixelxy(pargs->wcs, ra, dec, &x, &y)) {
			printf("  bad xy\n");
			lastok = FALSE;
			continue;
		}
		//printf("  x,y %.1f, %.1f\n", x, y);
		if (lastok)
			plotstuff_line_to(pargs, x, y);
		else
			plotstuff_move_to(pargs, x, y);
		lastok = TRUE;
	}
	return 0;
}
Example #21
0
int plot_index_plot(const char* command,
					cairo_t* cairo, plot_args_t* pargs, void* baton) {
	plotindex_t* args = (plotindex_t*)baton;
	int i;
	double ra, dec, radius;
	double xyz[3];
	double r2;

	pad_qidxes(args);

	plotstuff_builtin_apply(cairo, pargs);

	if (plotstuff_get_radec_center_and_radius(pargs, &ra, &dec, &radius)) {
		ERROR("Failed to get RA,Dec center and radius");
		return -1;
	}
	radecdeg2xyzarr(ra, dec, xyz);
	r2 = deg2distsq(radius);
	logmsg("Field RA,Dec,radius = (%g,%g), %g deg\n", ra, dec, radius);
	logmsg("distsq: %g\n", r2);

	for (i=0; i<pl_size(args->indexes); i++) {
		index_t* index = pl_get(args->indexes, i);
		int j, N;
		int DQ;
		double px,py;

		if (args->stars) {
			// plot stars
			double* radecs = NULL;
			startree_search_for(index->starkd, xyz, r2, NULL, &radecs, NULL, &N);
			if (N) {
				assert(radecs);
			}
			logmsg("Found %i stars in range in index %s\n", N, index->indexname);
			for (j=0; j<N; j++) {
				logverb("  RA,Dec (%g,%g) -> x,y (%g,%g)\n", radecs[2*j], radecs[2*j+1], px, py);
				if (!plotstuff_radec2xy(pargs, radecs[j*2], radecs[j*2+1], &px, &py)) {
					ERROR("Failed to convert RA,Dec %g,%g to pixels\n", radecs[j*2], radecs[j*2+1]);
					continue;
				}
				cairoutils_draw_marker(cairo, pargs->marker, px, py, pargs->markersize);
				cairo_stroke(cairo);
			}
			free(radecs);
		}
		if (args->quads) {
			DQ = index_get_quad_dim(index);
			qidxfile* qidx = pl_get(args->qidxes, i);
			if (qidx) {
				int* stars;
				int Nstars;
				il* quadlist = il_new(256);

				// find stars in range.
				startree_search_for(index->starkd, xyz, r2, NULL, NULL, &stars, &Nstars);
				logmsg("Found %i stars in range of index %s\n", N, index->indexname);
				logmsg("Using qidx file.\n");
				// find quads that each star is a member of.
				for (j=0; j<Nstars; j++) {
					uint32_t* quads;
					int Nquads;
					int k;
					if (qidxfile_get_quads(qidx, stars[j], &quads, &Nquads)) {
						ERROR("Failed to get quads for star %i\n", stars[j]);
						return -1;
					}
					for (k=0; k<Nquads; k++)
						il_insert_unique_ascending(quadlist, quads[k]);
				}
				for (j=0; j<il_size(quadlist); j++) {
					plotquad(cairo, pargs, args, index, il_get(quadlist, j), DQ);
				}

			} else {
				// plot quads
				N = index_nquads(index);
				for (j=0; j<N; j++) {
					plotquad(cairo, pargs, args, index, j, DQ);
				}
			}
		}
	}
	return 0;
}
void fits_guess_scale_hdr(const qfits_header* hdr,
                          sl** p_methods, dl** p_scales) {
	sip_t sip;
	double val;
	anbool gotsip = FALSE;
    char* errstr;

    sl* methods = NULL;
    dl* scales = NULL;

    if (p_methods) {
        if (!*p_methods)
            *p_methods = sl_new(4);
        methods = *p_methods;
    }
    if (p_scales) {
        if (!*p_scales)
            *p_scales = dl_new(4);
        scales = *p_scales;
    }

	memset(&sip, 0, sizeof(sip_t));

    errors_start_logging_to_string();

	if (sip_read_header(hdr, &sip)) {
        val = sip_pixel_scale(&sip);
        if (val != 0.0) {
            addscale(methods, scales, "sip", val);
            gotsip = TRUE;
		}
	}
    errstr = errors_stop_logging_to_string("\n  ");
    logverb("fits-guess-scale: failed to read SIP/TAN header:\n  %s\n", errstr);
    free(errstr);

	if (!gotsip) {
		// it might have a correct CD matrix but be missing other parts (eg CRVAL)
		double cd11, cd12, cd21, cd22;
		double errval = -HUGE_VAL;
		cd11 = qfits_header_getdouble(hdr, "CD1_1", errval);
		cd12 = qfits_header_getdouble(hdr, "CD1_2", errval);
		cd21 = qfits_header_getdouble(hdr, "CD2_1", errval);
		cd22 = qfits_header_getdouble(hdr, "CD2_2", errval);
		if ((cd11 != errval) && (cd12 != errval) && (cd21 != errval) && (cd22 != errval)) {
			val = cd11 * cd22 - cd12 * cd21;
			if (val != 0.0)
                addscale(methods, scales, "cd", sqrt(fabs(val)));
		}
	}

	val = qfits_header_getdouble(hdr, "PIXSCALE", -1.0);
	if (val != -1.0)
        addscale(methods, scales, "pixscale", val);

    /* Why all this?
     val = qfits_header_getdouble(hdr, "PIXSCAL1", -1.0);
     if (val != -1.0) {
     if (val != 0.0) {
     printf("scale pixscal1 %g\n", val);
     } else {
     val = atof(qfits_pretty_string(qfits_header_getstr(hdr, "PIXSCAL1")));
     if (val != 0.0) {
     printf("scale pixscal1 %g\n", val);
     }
     }
     }
     */

     val = qfits_header_getdouble(hdr, "PIXSCAL1", 0.0);
     if (val != 0.0)
         addscale(methods, scales, "pixscal1", val);

     val = qfits_header_getdouble(hdr, "PIXSCAL2", 0.0);
     if (val != 0.0)
         addscale(methods, scales, "pixscal2", val);

     val = qfits_header_getdouble(hdr, "PLATESC", 0.0);
     if (val != 0.0)
         addscale(methods, scales, "platesc", val);

	val = qfits_header_getdouble(hdr, "CCDSCALE", 0.0);
     if (val != 0.0)
         addscale(methods, scales, "ccdscale", val);

	val = qfits_header_getdouble(hdr, "CDELT1", 0.0);
     if (val != 0.0)
         addscale(methods, scales, "cdelt1", 3600.0 * fabs(val));
}
Example #23
0
int main(int argc, char *argv[]) {
    int argchar;
	char* progname = argv[0];
	sl* infns = sl_new(16);
	char* outfnpat = NULL;
	char* racol = "RA";
	char* deccol = "DEC";
	char* tempdir = "/tmp";
	anbool gzip = FALSE;
	sl* cols = sl_new(16);
	int loglvl = LOG_MSG;
	int nside = 1;
	double margin = 0.0;
	int NHP;
	double md;
	char* backref = NULL;
	
	fitstable_t* intable;
	fitstable_t** outtables;

	char** myargs;
	int nmyargs;
	int i;

    while ((argchar = getopt (argc, argv, OPTIONS)) != -1)
        switch (argchar) {
		case 'b':
			backref = optarg;
			break;
		case 't':
			tempdir = optarg;
			break;
		case 'c':
			sl_append(cols, optarg);
			break;
		case 'g':
			gzip = TRUE;
			break;
		case 'o':
			outfnpat = optarg;
			break;
		case 'r':
			racol = optarg;
			break;
		case 'd':
			deccol = optarg;
			break;
		case 'n':
			nside = atoi(optarg);
			break;
		case 'm':
			margin = atof(optarg);
			break;
		case 'v':
			loglvl++;
			break;
        case '?':
            fprintf(stderr, "Unknown option `-%c'.\n", optopt);
        case 'h':
			printHelp(progname);
            return 0;
        default:
            return -1;
        }

	if (sl_size(cols) == 0) {
		sl_free2(cols);
		cols = NULL;
	}

	nmyargs = argc - optind;
	myargs = argv + optind;

	for (i=0; i<nmyargs; i++)
		sl_append(infns, myargs[i]);
	
	if (!sl_size(infns)) {
		printHelp(progname);
		printf("Need input filenames!\n");
		exit(-1);
	}
	log_init(loglvl);
	fits_use_error_system();

	NHP = 12 * nside * nside;
	logmsg("%i output healpixes\n", NHP);
	outtables = calloc(NHP, sizeof(fitstable_t*));
	assert(outtables);

	md = deg2dist(margin);

	/**
	 About the mincaps/maxcaps:

	 These have a center and radius-squared, describing the region
	 inside a small circle on the sphere.

	 The "mincaps" describe the regions that are definitely owned by a
	 single healpix -- ie, more than MARGIN distance from any edge.
	 That is, the mincap is the small circle centered at (0.5, 0.5) in
	 the healpix and with radius = the distance to the closest healpix
	 boundary, MINUS the margin distance.

	 Below, we first check whether a new star is within the "mincap"
	 of any healpix.  If so, we stick it in that healpix and continue.

	 Otherwise, we check all the "maxcaps" -- these are the healpixes
	 it could *possibly* be in.  We then refine with
	 healpix_within_range_of_xyz.  The maxcap distance is the distance
	 to the furthest boundary point, PLUS the margin distance.
	 */


	cap_t* mincaps = malloc(NHP * sizeof(cap_t));
	cap_t* maxcaps = malloc(NHP * sizeof(cap_t));
	for (i=0; i<NHP; i++) {
		// center
		double r2;
		double xyz[3];
		double* cxyz;
		double step = 1e-3;
		double v;
		double r2b, r2a;

		cxyz = mincaps[i].xyz;
		healpix_to_xyzarr(i, nside, 0.5, 0.5, mincaps[i].xyz);
		memcpy(maxcaps[i].xyz, cxyz, 3 * sizeof(double));
		logverb("Center of HP %i: (%.3f, %.3f, %.3f)\n", i, cxyz[0], cxyz[1], cxyz[2]);

		// radius-squared:
		// max is the easy one: max of the four corners (I assume)
		r2 = 0.0;
		healpix_to_xyzarr(i, nside, 0.0, 0.0, xyz);
		logverb("  HP %i corner 1: (%.3f, %.3f, %.3f), distsq %.3f\n", i, xyz[0], xyz[1], xyz[2], distsq(xyz, cxyz, 3));
		r2 = MAX(r2, distsq(xyz, cxyz, 3));
		healpix_to_xyzarr(i, nside, 1.0, 0.0, xyz);
		logverb("  HP %i corner 1: (%.3f, %.3f, %.3f), distsq %.3f\n", i, xyz[0], xyz[1], xyz[2], distsq(xyz, cxyz, 3));
		r2 = MAX(r2, distsq(xyz, cxyz, 3));
		healpix_to_xyzarr(i, nside, 0.0, 1.0, xyz);
		logverb("  HP %i corner 1: (%.3f, %.3f, %.3f), distsq %.3f\n", i, xyz[0], xyz[1], xyz[2], distsq(xyz, cxyz, 3));
		r2 = MAX(r2, distsq(xyz, cxyz, 3));
		healpix_to_xyzarr(i, nside, 1.0, 1.0, xyz);
		logverb("  HP %i corner 1: (%.3f, %.3f, %.3f), distsq %.3f\n", i, xyz[0], xyz[1], xyz[2], distsq(xyz, cxyz, 3));
		r2 = MAX(r2, distsq(xyz, cxyz, 3));
		logverb("  max distsq: %.3f\n", r2);
		logverb("  margin dist: %.3f\n", md);
		maxcaps[i].r2 = square(sqrt(r2) + md);
		logverb("  max cap distsq: %.3f\n", maxcaps[i].r2);
		r2a = r2;

		r2 = 1.0;
		r2b = 0.0;
		for (v=0; v<=1.0; v+=step) {
			healpix_to_xyzarr(i, nside, 0.0, v, xyz);
			r2 = MIN(r2, distsq(xyz, cxyz, 3));
			r2b = MAX(r2b, distsq(xyz, cxyz, 3));
			healpix_to_xyzarr(i, nside, 1.0, v, xyz);
			r2 = MIN(r2, distsq(xyz, cxyz, 3));
			r2b = MAX(r2b, distsq(xyz, cxyz, 3));
			healpix_to_xyzarr(i, nside, v, 0.0, xyz);
			r2 = MIN(r2, distsq(xyz, cxyz, 3));
			r2b = MAX(r2b, distsq(xyz, cxyz, 3));
			healpix_to_xyzarr(i, nside, v, 1.0, xyz);
			r2 = MIN(r2, distsq(xyz, cxyz, 3));
			r2b = MAX(r2b, distsq(xyz, cxyz, 3));
		}
		mincaps[i].r2 = square(MAX(0, sqrt(r2) - md));
		logverb("\nhealpix %i: min rad    %g\n", i, sqrt(r2));
		logverb("healpix %i: max rad    %g\n", i, sqrt(r2a));
		logverb("healpix %i: max rad(b) %g\n", i, sqrt(r2b));
		assert(r2a >= r2b);
	}

	if (backref) {
		fitstable_t* tab = fitstable_open_for_writing(backref);
		int maxlen = 0;
		char* buf;
		for (i=0; i<sl_size(infns); i++) {
			char* infn = sl_get(infns, i);
			maxlen = MAX(maxlen, strlen(infn));
		}
		fitstable_add_write_column_array(tab, fitscolumn_char_type(), maxlen,
										 "filename", NULL);
		fitstable_add_write_column(tab, fitscolumn_i16_type(), "index", NULL);
		if (fitstable_write_primary_header(tab) ||
			fitstable_write_header(tab)) {
			ERROR("Failed to write header of backref table \"%s\"", backref);
			exit(-1);
		}
		buf = malloc(maxlen+1);
		assert(buf);

		for (i=0; i<sl_size(infns); i++) {
			char* infn = sl_get(infns, i);
			int16_t ind;
			memset(buf, 0, maxlen);
			strcpy(buf, infn);
			ind = i;
			if (fitstable_write_row(tab, buf, &ind)) {
				ERROR("Failed to write row %i of backref table: %s = %i",
					  i, buf, ind);
				exit(-1);
			}
		}
		if (fitstable_fix_header(tab) ||
			fitstable_close(tab)) {
			ERROR("Failed to fix header & close backref table");
			exit(-1);
		}
		logmsg("Wrote backref table %s\n", backref);
		free(buf);
	}

	for (i=0; i<sl_size(infns); i++) {
		char* infn = sl_get(infns, i);
		char* originfn = infn;
		int r, NR;
		tfits_type any, dubl;
		il* hps = NULL;
		bread_t* rowbuf;
		int R;
		char* tempfn = NULL;
		char* padrowdata = NULL;
		int ii;

		logmsg("Reading input \"%s\"...\n", infn);

		if (gzip) {
			char* cmd;
			int rtn;
			tempfn = create_temp_file("hpsplit", tempdir);
			asprintf_safe(&cmd, "gunzip -cd %s > %s", infn, tempfn);
			logmsg("Running: \"%s\"\n", cmd);
			rtn = run_command_get_outputs(cmd, NULL, NULL);
			if (rtn) {
				ERROR("Failed to run command: \"%s\"", cmd);
				exit(-1);
			}
			free(cmd);
			infn = tempfn;
		}

		intable = fitstable_open(infn);
		if (!intable) {
			ERROR("Couldn't read catalog %s", infn);
			exit(-1);
		}
		NR = fitstable_nrows(intable);
		logmsg("Got %i rows\n", NR);

		any = fitscolumn_any_type();
		dubl = fitscolumn_double_type();

		fitstable_add_read_column_struct(intable, dubl, 1, 0, any, racol, TRUE);
		fitstable_add_read_column_struct(intable, dubl, 1, sizeof(double), any, deccol, TRUE);

		fitstable_use_buffered_reading(intable, 2*sizeof(double), 1000);

		R = fitstable_row_size(intable);
		rowbuf = buffered_read_new(R, 1000, NR, refill_rowbuffer, intable);

		if (fitstable_read_extension(intable, 1)) {
			ERROR("Failed to find RA and DEC columns (called \"%s\" and \"%s\" in the FITS file)", racol, deccol);
			exit(-1);
		}

		for (r=0; r<NR; r++) {
			int hp = -1;
			double ra, dec;
			int j;
			double* rd;
			void* rowdata;
			void* rdata;

			if (r && ((r % 100000) == 0)) {
			  logmsg("Reading row %i of %i\n", r, NR);
			}

			//printf("reading RA,Dec for row %i\n", r);
			rd = fitstable_next_struct(intable);
			ra = rd[0];
			dec = rd[1];

			logverb("row %i: ra,dec %g,%g\n", r, ra, dec);
			if (margin == 0) {
				hp = radecdegtohealpix(ra, dec, nside);
				logverb("  --> healpix %i\n", hp);
			} else {

				double xyz[3];
				anbool gotit = FALSE;
				double d2;
				if (!hps)
					hps = il_new(4);
				radecdeg2xyzarr(ra, dec, xyz);
				for (j=0; j<NHP; j++) {
					d2 = distsq(xyz, mincaps[j].xyz, 3);
					if (d2 <= mincaps[j].r2) {
						logverb("  -> in mincap %i  (dist %g vs %g)\n", j, sqrt(d2), sqrt(mincaps[j].r2));
						il_append(hps, j);
						gotit = TRUE;
						break;
					}
				}
				if (!gotit) {
					for (j=0; j<NHP; j++) {
						d2 = distsq(xyz, maxcaps[j].xyz, 3);
						if (d2 <= maxcaps[j].r2) {
							logverb("  -> in maxcap %i  (dist %g vs %g)\n", j, sqrt(d2), sqrt(maxcaps[j].r2));
							if (healpix_within_range_of_xyz(j, nside, xyz, margin)) {
								logverb("  -> and within range.\n");
								il_append(hps, j);
							}
						}
					}
				}

				//hps = healpix_rangesearch_radec(ra, dec, margin, nside, hps);

				logverb("  --> healpixes: [");
				for (j=0; j<il_size(hps); j++)
					logverb(" %i", il_get(hps, j));
				logverb(" ]\n");
			}

			//printf("Reading rowdata for row %i\n", r);
			rowdata = buffered_read(rowbuf);
			assert(rowdata);


			j=0;
			while (1) {
				if (hps) {
					if (j >= il_size(hps))
						break;
					hp = il_get(hps, j);
					j++;
				}
				assert(hp < NHP);
				assert(hp >= 0);

				if (!outtables[hp]) {
					char* outfn;
					fitstable_t* out;

					// MEMLEAK the output filename.  You'll live.
					asprintf_safe(&outfn, outfnpat, hp);
					logmsg("Opening output file \"%s\"...\n", outfn);
					out = fitstable_open_for_writing(outfn);
					if (!out) {
						ERROR("Failed to open output table \"%s\"", outfn);
						exit(-1);
					}
					// Set the output table structure.
					if (cols) {
					  fitstable_add_fits_columns_as_struct3(intable, out, cols, 0);
					} else
						fitstable_add_fits_columns_as_struct2(intable, out);

					if (backref) {
						tfits_type i16type;
						tfits_type i32type;
						// R = fitstable_row_size(intable);
						int off = R;
						i16type = fitscolumn_i16_type();
						i32type = fitscolumn_i32_type();
						fitstable_add_read_column_struct(out, i16type, 1, off,
														 i16type, "backref_file", TRUE);
						off += sizeof(int16_t);
						fitstable_add_read_column_struct(out, i32type, 1, off,
														 i32type, "backref_index", TRUE);
					}

					//printf("Output table:\n");
					//fitstable_print_columns(out);

					if (fitstable_write_primary_header(out) ||
						fitstable_write_header(out)) {
						ERROR("Failed to write output file headers for \"%s\"", outfn);
						exit(-1);
					}
					outtables[hp] = out;
				}

				if (backref) {
					int16_t brfile;
					int32_t brind;
					if (!padrowdata) {
						padrowdata = malloc(R + sizeof(int16_t) + sizeof(int32_t));
						assert(padrowdata);
					}
					// convert to FITS endian
					brfile = htons(i);
					brind  = htonl(r);
					// add backref data to rowdata
					memcpy(padrowdata, rowdata, R);
					memcpy(padrowdata + R, &brfile, sizeof(int16_t));
					memcpy(padrowdata + R + sizeof(int16_t), &brind, sizeof(int32_t));
					rdata = padrowdata;
				} else {
					rdata = rowdata;
				}

				if (cols) {
				  if (fitstable_write_struct_noflip(outtables[hp], rdata)) {
				    ERROR("Failed to copy a row of data from input table \"%s\" to output healpix %i", infn, hp);
				  }
				} else {
				  if (fitstable_write_row_data(outtables[hp], rdata)) {
				    ERROR("Failed to copy a row of data from input table \"%s\" to output healpix %i", infn, hp);
				  }
				}

				if (!hps)
					break;
			}
			if (hps)
				il_remove_all(hps);

		}
		buffered_read_free(rowbuf);
		// wack... buffered_read_free() just frees its internal buffer,
		// not the "rowbuf" struct itself.
		// who wrote this crazy code?  Oh, me of 5 years ago.  Jerk.
		free(rowbuf);

		fitstable_close(intable);
		il_free(hps);

		if (tempfn) {
			logverb("Removing temp file %s\n", tempfn);
			if (unlink(tempfn)) {
				SYSERROR("Failed to unlink() temp file \"%s\"", tempfn);
			}
			tempfn = NULL;
		}

		// fix headers so that the files are valid at this point.
		for (ii=0; ii<NHP; ii++) {
		  if (!outtables[ii])
		    continue;
		  off_t offset = ftello(outtables[ii]->fid);
		  if (fitstable_fix_header(outtables[ii])) {
		    ERROR("Failed to fix header for healpix %i after reading input file \"%s\"", ii, originfn);
		    exit(-1);
		  }
		  fseeko(outtables[ii]->fid, offset, SEEK_SET);
		}

		if (padrowdata) {
			free(padrowdata);
			padrowdata = NULL;
		}

	}

	for (i=0; i<NHP; i++) {
		if (!outtables[i])
			continue;
		if (fitstable_fix_header(outtables[i]) ||
			fitstable_fix_primary_header(outtables[i]) ||
			fitstable_close(outtables[i])) {
			ERROR("Failed to close output table for healpix %i", i);
			exit(-1);
		}
	}

	free(outtables);
	sl_free2(infns);
	sl_free2(cols);

	free(mincaps);
	free(maxcaps);

    return 0;
}
Example #24
0
int main(int argc, char *argv[]) {
    int argchar;
	char* outfn = NULL;
	char* infn;
	int overwrite = 0;
    int loglvl = LOG_MSG;
    anbool do_u8 = TRUE;
    int downsample = 0;
    int downsample_as_reqd = 0;
    int extension = 0;
	int plane = 0;

	simplexy_t sparams;
	simplexy_t* params = &sparams;

    memset(params, 0, sizeof(simplexy_t));

    while ((argchar = getopt (argc, argv, OPTIONS)) != -1)
        switch (argchar) {
		case 'L':
			params->Lorder = atoi(optarg);
			break;
		case 'w':
			params->dpsf = atof(optarg);
			break;
		case 'a':
			params->saddle = atof(optarg);
			break;
		case 'm':
			params->maxsize = atoi(optarg);
			break;
		case 'g':
			params->sigma = atof(optarg);
			break;
		case 'b':
			params->nobgsub = TRUE;
			break;
		case 'G':
			params->nobgsub = TRUE;
			params->globalbg = atof(optarg);
			break;
		case 'P':
			plane = atoi(optarg);
			break;
		case 's':
			params->halfbox = atoi(optarg);
			break;
		case 'p':
			params->plim = atof(optarg);
			break;
		case 'B':
			params->bgimgfn = optarg;
			break;
		case 'S':
			params->bgsubimgfn = optarg;
			break;
		case 'M':
			params->maskimgfn = optarg;
			break;
		case 'U':
			params->smoothimgfn = optarg;
			break;
		case 'C':
			params->blobimgfn = optarg;
			break;
        case 'e':
            extension = atoi(optarg);
            break;
        case 'D':
            downsample_as_reqd = atoi(optarg);
            break;
        case 'H':
            downsample = 2;
            break;
        case 'd':
            downsample = atoi(optarg);
            break;
        case '8':
            do_u8 = FALSE;
            break;
        case 'v':
            loglvl++;
            break;
		case 'O':
			overwrite = 1;
			break;
		case 'o':
			outfn = strdup(optarg);
			break;
		case '?':
		case 'h':
			printHelp();
			exit(0);
		}

	if (optind != argc - 1) {
		printHelp();
		exit(-1);
	}

	infn = argv[optind];

    log_init(loglvl);
    logverb("infile=%s\n", infn);

	if (!outfn) {
		// Create xylist filename (by trimming '.fits')
		asprintf_safe(&outfn, "%.*s.xy.fits", (int)(strlen(infn)-5), infn);
        logverb("outfile=%s\n", outfn);
	}

	if (overwrite && file_exists(outfn)) {
        logverb("Deleting existing output file \"%s\"...\n", outfn);
        if (unlink(outfn)) {
            SYSERROR("Failed to delete existing output file \"%s\"", outfn);
            exit(-1);
        }
	}

    if (downsample)
        logverb("Downsampling by %i\n", downsample);

    if (image2xy_files(infn, outfn, do_u8, downsample, downsample_as_reqd,
					   extension, plane, params)) {
        ERROR("image2xy failed.");
        exit(-1);
    }
    free(outfn);
	return 0;
}
int main(int argc, char** args) {
    char* default_configfn = "astrometry.cfg";
    char* default_config_path = "../etc";

	int c;
	char* configfn = NULL;
	int i;
	engine_t* engine;
    char* mydir = NULL;
    char* basedir = NULL;
    char* me;
    anbool help = FALSE;
    sl* strings = sl_new(4);
    char* cancelfn = NULL;
    char* solvedfn = NULL;
    int loglvl = LOG_MSG;
    anbool tostderr = FALSE;
    char* infn = NULL;
    FILE* fin = NULL;
    anbool fromstdin = FALSE;

	bl* opts = opts_from_array(myopts, sizeof(myopts)/sizeof(an_option_t), NULL);
	sl* inds = sl_new(4);

	char* datalog = NULL;

	engine = engine_new();

	while (1) {
		c = opts_getopt(opts, argc, args);
		if (c == -1)
			break;
		switch (c) {
		case 'D':
			datalog = optarg;
			break;
		case 'p':
			engine->inparallel = TRUE;
			break;
		case 'i':
			sl_append(inds, optarg);
			break;
		case 'd':
		  basedir = optarg;
		  break;
        case 'f':
            infn = optarg;
            fromstdin = streq(infn, "-");
            break;
        case 'E':
            tostderr = TRUE;
            break;
		case 'h':
            help = TRUE;
			break;
        case 'v':
            loglvl++;
            break;
		case 's':
		  solvedfn = optarg;
        case 'C':
            cancelfn = optarg;
            break;
		case 'c':
			configfn = strdup(optarg);
			break;
		case '?':
			break;
		default:
            printf("Unknown flag %c\n", c);
			exit( -1);
		}
	}

	if (optind == argc && !infn) {
		// Need extra args: filename
		printf("You must specify at least one input file!\n\n");
		help = TRUE;
	}
	if (help) {
		print_help(args[0], opts);
		exit(0);
	}
	bl_free(opts);

	gslutils_use_error_system();

    log_init(loglvl);
    if (tostderr)
        log_to(stderr);

	if (datalog) {
		datalogfid = fopen(datalog, "wb");
		if (!datalogfid) {
			SYSERROR("Failed to open data log file \"%s\" for writing", datalog);
			return -1;
		}
		atexit(close_datalogfid);
		data_log_init(100);
		data_log_enable_all();
		data_log_to(datalogfid);
		data_log_start();
	}

    if (infn) {
        logverb("Reading input filenames from %s\n", (fromstdin ? "stdin" : infn));
        if (!fromstdin) {
            fin = fopen(infn, "rb");
            if (!fin) {
                ERROR("Failed to open file %s for reading input filenames", infn);
                exit(-1);
            }
        } else
            fin = stdin;
    }

    // directory containing the 'engine' executable:
    me = find_executable(args[0], NULL);
    if (!me)
        me = strdup(args[0]);
    mydir = sl_append(strings, dirname(me));
    free(me);

	// Read config file
    if (!configfn) {
        int i;
        sl* trycf = sl_new(4);
        sl_appendf(trycf, "%s/%s/%s", mydir, default_config_path, default_configfn);
        // if I'm in /usr/bin, look for config file in /etc
        if (streq(mydir, "/usr/bin")) {
            sl_appendf(trycf, "/etc/%s", default_configfn);
        }
        sl_appendf(trycf, "%s/%s", mydir, default_configfn);
        sl_appendf(trycf, "./%s", default_configfn);
        sl_appendf(trycf, "./%s/%s", default_config_path, default_configfn);
        for (i=0; i<sl_size(trycf); i++) {
            char* cf = sl_get(trycf, i);
            if (file_exists(cf)) {
                configfn = strdup(cf);
                logverb("Using config file \"%s\"\n", cf);
                break;
            } else {
                logverb("Config file \"%s\" doesn't exist.\n", cf);
            }
        }
        if (!configfn) {
            char* cflist = sl_join(trycf, "\n  ");
            logerr("Couldn't find config file: tried:\n  %s\n", cflist);
            free(cflist);
        }
        sl_free2(trycf);
    }

	if (!streq(configfn, "none")) {
		if (engine_parse_config_file(engine, configfn)) {
			logerr("Failed to parse (or encountered an error while interpreting) config file \"%s\"\n", configfn);
			exit( -1);
		}
	}

	if (sl_size(inds)) {
		// Expand globs.
		for (i=0; i<sl_size(inds); i++) {
			char* s = sl_get(inds, i);
			glob_t myglob;
			int flags = GLOB_TILDE | GLOB_BRACE;
			if (glob(s, flags, NULL, &myglob)) {
				SYSERROR("Failed to expand wildcards in index-file path \"%s\"", s);
				exit(-1);
			}
			for (c=0; c<myglob.gl_pathc; c++) {
				if (engine_add_index(engine, myglob.gl_pathv[c])) {
					ERROR("Failed to add index \"%s\"", myglob.gl_pathv[c]);
					exit(-1);
				}
			}
			globfree(&myglob);
		}
	}

	if (!pl_size(engine->indexes)) {
		logerr("\n\n"
			   "---------------------------------------------------------------------\n"
			   "You must list at least one index in the config file (%s)\n\n"
			   "See http://astrometry.net/use.html about how to get some index files.\n"
			   "---------------------------------------------------------------------\n"
			   "\n", configfn);
		exit(-1);
	}

	if (engine->minwidth <= 0.0 || engine->maxwidth <= 0.0) {
		logerr("\"minwidth\" and \"maxwidth\" in the config file %s must be positive!\n", configfn);
		exit(-1);
	}

    free(configfn);

    if (!il_size(engine->default_depths)) {
        parse_depth_string(engine->default_depths,
                           "10 20 30 40 50 60 70 80 90 100 "
                           "110 120 130 140 150 160 170 180 190 200");
    }

    engine->cancelfn = cancelfn;
    engine->solvedfn = solvedfn;

    i = optind;
    while (1) {
		char* jobfn;
        job_t* job;
		struct timeval tv1, tv2;

        if (infn) {
            // Read name of next input file to be read.
            logverb("\nWaiting for next input filename...\n");
            jobfn = read_string_terminated(fin, "\n\r\0", 3, FALSE);
            if (strlen(jobfn) == 0)
                break;
        } else {
            if (i == argc)
                break;
            jobfn = args[i];
            i++;
        }
        gettimeofday(&tv1, NULL);
        logmsg("Reading file \"%s\"...\n", jobfn);
        job = engine_read_job_file(engine, jobfn);
        if (!job) {
            ERROR("Failed to read job file \"%s\"", jobfn);
            exit(-1);
        }

	if (basedir) {
	  logverb("Setting job's output base directory to %s\n", basedir);
	  job_set_output_base_dir(job, basedir);
	}

		if (engine_run_job(engine, job))
			logerr("Failed to run_job()\n");

		job_free(job);
        gettimeofday(&tv2, NULL);
		logverb("Spent %g seconds on this field.\n", millis_between(&tv1, &tv2)/1000.0);
	}

	engine_free(engine);
    sl_free2(strings);
	sl_free2(inds);

    if (fin && !fromstdin)
        fclose(fin);

    return 0;
}
Example #26
0
int wcs_xy2rd(const char* wcsfn, int ext,
			  const char* xylsfn, const char* rdlsfn,
              const char* xcol, const char* ycol,
			  int forcetan,
			  int forcewcslib,
              il* fields) {
	rdlist_t* rdls = NULL;
	xylist_t* xyls = NULL;
	anwcs_t* wcs = NULL;
	int i;
    int rtn = -1;
    anbool alloced_fields = FALSE;

	// read WCS.
	if (forcewcslib) {
		wcs = anwcs_open_wcslib(wcsfn, ext);
	} else if (forcetan) {
		wcs = anwcs_open_tan(wcsfn, ext);
	} else {
		wcs = anwcs_open(wcsfn, ext);
	}
	if (!wcs) {
		ERROR("Failed to read WCS file \"%s\", extension %i", wcsfn, ext);
		return -1;
	}

	// read XYLS.
	xyls = xylist_open(xylsfn);
	if (!xyls) {
		ERROR("Failed to read an xylist from file %s", xylsfn);
		goto bailout;
	}
    xylist_set_include_flux(xyls, FALSE);
    xylist_set_include_background(xyls, FALSE);
	if (xcol)
		xylist_set_xname(xyls, xcol);
	if (ycol)
		xylist_set_yname(xyls, ycol);

	// write RDLS.
	rdls = rdlist_open_for_writing(rdlsfn);
	if (!rdls) {
		ERROR("Failed to open file %s to write RDLS.\n", rdlsfn);
		goto bailout;
	}
	if (rdlist_write_primary_header(rdls)) {
		ERROR("Failed to write header to RDLS file %s.\n", rdlsfn);
		goto bailout;
	}

    if (!fields) {
        alloced_fields = TRUE;
        fields = il_new(16);
    }
	if (!il_size(fields)) {
		// add all fields.
		int NF = xylist_n_fields(xyls);
		for (i=1; i<=NF; i++)
			il_append(fields, i);
	}

	logverb("Processing %zu extensions...\n", il_size(fields));
	for (i=0; i<il_size(fields); i++) {
		int fieldind = il_get(fields, i);
        starxy_t xy;
        rd_t rd;
		int j;

        if (!xylist_read_field_num(xyls, fieldind, &xy)) {
			ERROR("Failed to read xyls file %s, field %i", xylsfn, fieldind);
			goto bailout;
        }

		if (rdlist_write_header(rdls)) {
			ERROR("Failed to write rdls field header to %s", rdlsfn);
			goto bailout;
		}

        rd_alloc_data(&rd, starxy_n(&xy));

		for (j=0; j<starxy_n(&xy); j++) {
            double x, y, ra, dec;
            x = starxy_getx(&xy, j);
            y = starxy_gety(&xy, j);
			anwcs_pixelxy2radec(wcs, x, y, &ra, &dec);
            rd_setra (&rd, j, ra);
            rd_setdec(&rd, j, dec);
		}

        if (rdlist_write_field(rdls, &rd)) {
            ERROR("Failed to write rdls field to %s", rdlsfn);
			goto bailout;
        }
        rd_free_data(&rd);
        starxy_free_data(&xy);

		if (rdlist_fix_header(rdls)) {
			ERROR("Failed to fix rdls field header for %s", rdlsfn);
			goto bailout;
		}

        rdlist_next_field(rdls);
	}

	if (rdlist_fix_primary_header(rdls) ||
		rdlist_close(rdls)) {
		ERROR("Failed to fix header of RDLS file %s", rdlsfn);
		goto bailout;
	}
	rdls = NULL;

	if (xylist_close(xyls)) {
		ERROR("Failed to close XYLS file %s", xylsfn);
		goto bailout;
	}
	xyls = NULL;
	rtn = 0;

 bailout:
    if (alloced_fields)
        il_free(fields);
    if (rdls)
        rdlist_close(rdls);
    if (xyls)
        xylist_close(xyls);
	if (wcs)
		anwcs_free(wcs);
    return rtn;
}
Example #27
0
int fit_sip_wcs(const double* starxyz,
                const double* fieldxy,
                const double* weights,
                int M,
                const tan_t* tanin1,
                int sip_order,
                int inv_order,
                sip_t* sipout) {
	int sip_coeffs;
	double xyzcrval[3];
	double cdinv[2][2];
	double sx, sy, sU, sV, su, sv;
	int N;
	int i, j, p, q, order;
	double totalweight;
	int rtn;
	gsl_matrix *mA;
	gsl_vector *b1, *b2, *x1, *x2;
	gsl_vector *r1=NULL, *r2=NULL;
    tan_t tanin2;
    int ngood;
    const tan_t* tanin = &tanin2;
	// We need at least the linear terms to compute CD.
	if (sip_order < 1)
		sip_order = 1;

    // convenience: allow the user to call like:
    //    fit_sip_wcs(... &(sipout.wcstan), ..., sipout);
    memcpy(&tanin2, tanin1, sizeof(tan_t));

    memset(sipout, 0, sizeof(sip_t));
    memcpy(&(sipout->wcstan), tanin, sizeof(tan_t));
    sipout->a_order  = sipout->b_order  = sip_order;
    sipout->ap_order = sipout->bp_order = inv_order;

	// The SIP coefficients form an (order x order) upper triangular
	// matrix missing the 0,0 element.
	sip_coeffs = (sip_order + 1) * (sip_order + 2) / 2;
	N = sip_coeffs;

    if (M < N) {
        ERROR("Too few correspondences for the SIP order specified (%i < %i)\n", M, N);
        return -1;
    }

	mA = gsl_matrix_alloc(M, N);
	b1 = gsl_vector_alloc(M);
	b2 = gsl_vector_alloc(M);
	assert(mA);
	assert(b1);
	assert(b2);

	/*
     *  We use a clever trick to estimate CD, A, and B terms in two
     *  seperated least squares fits, then finding A and B by multiplying
     *  the found parameters by CD inverse.
     * 
     *  Rearranging the SIP equations (see sip.h) we get the following
     *  matrix operation to compute x and y in world intermediate
     *  coordinates, which is convienently written in a way which allows
     *  least squares estimation of CD and terms related to A and B.
     * 
     *  First use the x's to find the first set of parametetrs
     * 
     *     +--------------------- Intermediate world coordinates in DEGREES
     *     |          +--------- Pixel coordinates u and v in PIXELS
     *     |          |     +--- Polynomial u,v terms in powers of PIXELS
     *     v          v     v
     *   ( x1 )   ( 1 u1 v1 p1 )   (sx              )
     *   ( x2 ) = ( 1 u2 v2 p2 ) * (cd11            ) :
     *   ( x3 )   ( 1 u3 v3 p3 )   (cd12            ) :
     *   ( ...)   (   ...    )     (cd11*A + cd12*B ) :
     * cd11 is a scalar, degrees per pixel
     * cd12 is a scalar, degrees per pixel
     * cd11*A and cs12*B are mixture of SIP terms (A,B) and CD matrix
     *   (cd11,cd12)
     * 
     *  Then find cd21 and cd22 with the y's
     * 
     *   ( y1 )   ( 1 u1 v1 p1 )   (sy              )
     *   ( y2 ) = ( 1 u2 v2 p2 ) * (cd21            ) :
     *   ( y3 )   ( 1 u3 v3 p3 )   (cd22            ) :
     *   ( ...)   (   ...    )     (cd21*A + cd22*B ) : (Y4)
     *  y2: scalar, degrees per pixel
     *  y3: scalar, degrees per pixel
     *  Y4: mixture of SIP terms (A,B) and CD matrix (cd21,cd22)
     * 
     *  These are both standard least squares problems which we solve with
     *  QR decomposition, ie
     *      min_{cd,A,B} || x - [1,u,v,p]*[s;cd;cdA+cdB]||^2 with
     *  x reference, cd,A,B unrolled parameters.
     * 
     *  We get back (for x) a vector of optimal
     *    [sx;cd11;cd12; cd11*A + cd12*B]
     *  Now we can pull out sx, cd11 and cd12 from the beginning of this vector,
     *  and call the rest of the vector [cd11*A] + [cd12*B];
     *  similarly for the y fit, we get back a vector of optimal
     *    [sy;cd21;cd22; cd21*A + cd22*B]
     *  once we have all those we can figure out A and B as follows
     *                   -1
     *    A' = [cd11 cd12]    *  [cd11*A' + cd12*B']
     *    B'   [cd21 cd22]       [cd21*A' + cd22*B']
     * 
     *  which recovers the A and B's.
     *
     */

	/*
     *  Dustin's interpretation of the above:
     *  We want to solve:
     * 
     *     min || b[M-by-1] - A[M-by-N] x[N-by-1] ||_2
     * 
     *  M = the number of correspondences.
     *  N = the number of SIP terms.
     *
     * And we want an overdetermined system, so M >= N.
     * 
     *           [ 1  u_1   v_1  u_1^2  u_1 v_1  v_1^2  ... ]
     *    mA  =  [ 1  u_2   v_2  u_2^2  u_2 v_2  v_2^2  ... ]
     *           [           ......                         ]
	 *
	 * Where (u_i, v_i) are *undistorted* pixel positions minus CRPIX.
	 *
     *  The answers we want are:
     *
     *         [ sx                  ]
     *    x1 = [ cd11                ]
     *         [ cd12                ]
	 *         [      (A)        (B) ]
     *         [ cd11*(A) + cd12*(B) ]
	 *         [      (A)        (B) ]
     *
     *         [ sy                  ]
     *    x2 = [ cd21                ]
     *         [ cd22                ]
	 *         [      (A)        (B) ]
     *         [ cd21*(A) + cd22*(B) ]
	 *         [      (A)        (B) ]
	 *
	 * And the target vectors are the intermediate world coords of the
	 * reference stars, in degrees.
     *
     *         [ ix_1 ]
     *    b1 = [ ix_2 ]
     *         [ ...  ]
     *
     *         [ iy_1 ]
     *    b2 = [ iy_2 ]
     *         [ ...  ]
     *
     *
     *  (where A and B are tall vectors of SIP coefficients of order 2
     *  and above)
     *
     */

	// Fill in matrix mA:
	radecdeg2xyzarr(tanin->crval[0], tanin->crval[1], xyzcrval);
	totalweight = 0.0;
    ngood = 0;
	for (i=0; i<M; i++) {
        double x=0, y=0;
        double weight = 1.0;
        double u;
        double v;
        Unused anbool ok;

        u = fieldxy[2*i + 0] - tanin->crpix[0];
        v = fieldxy[2*i + 1] - tanin->crpix[1];

        // B contains Intermediate World Coordinates (in degrees)
		// tangent-plane projection
        ok = star_coords(starxyz + 3*i, xyzcrval, TRUE, &x, &y);
        if (!ok) {
            logverb("Skipping star that cannot be projected to tangent plane\n");
            continue;
        }

        gsl_vector_set(b1, ngood, weight * rad2deg(x));
        gsl_vector_set(b2, ngood, weight * rad2deg(y));

        if (weights) {
            weight = weights[i];
            assert(weight >= 0.0);
            assert(weight <= 1.0);
            totalweight += weight;
            if (weight == 0.0)
                continue;
        }

        /* The coefficients are stored in this order:
         *   p q
         *  (0,0) = 1     <- order 0
         *  (1,0) = u     <- order 1
         *  (0,1) = v
         *  (2,0) = u^2   <- order 2
         *  (1,1) = uv
         *  (0,2) = v^2
         *  ...
         */

        j = 0;
        for (order=0; order<=sip_order; order++) {
            for (q=0; q<=order; q++) {
                p = order - q;
                assert(j >= 0);
                assert(j < N);
                assert(p >= 0);
                assert(q >= 0);
                assert(p + q <= sip_order);
                gsl_matrix_set(mA, ngood, j,
                               weight * pow(u, (double)p) * pow(v, (double)q));
                j++;
            }
        }
        assert(j == N);

        // The shift - aka (0,0) - SIP coefficient must be 1.
        assert(gsl_matrix_get(mA, i, 0) == 1.0 * weight);
        assert(fabs(gsl_matrix_get(mA, i, 1) - u * weight) < 1e-12);
        assert(fabs(gsl_matrix_get(mA, i, 2) - v * weight) < 1e-12);

        ngood++;
    }

    if (ngood == 0) {
        ERROR("No stars projected within the image\n");
        return -1;
    }

	if (weights)
		logverb("Total weight: %g\n", totalweight);

    if (ngood < M) {
        _gsl_vector_view sub_b1 = gsl_vector_subvector(b1, 0, ngood);
        _gsl_vector_view sub_b2 = gsl_vector_subvector(b2, 0, ngood);
        _gsl_matrix_view sub_mA = gsl_matrix_submatrix(mA, 0, 0, ngood, N);

        rtn = gslutils_solve_leastsquares_v(&(sub_mA.matrix), 2,
                                            &(sub_b1.vector), &x1, NULL,
                                            &(sub_b2.vector), &x2, NULL);

    } else {
        // Solve the equation.
        rtn = gslutils_solve_leastsquares_v(mA, 2, b1, &x1, NULL, b2, &x2, NULL);
    }
	if (rtn) {
        ERROR("Failed to solve SIP matrix equation!");
        return -1;
    }

	// Row 0 of X are the shift (p=0, q=0) terms.
	// Row 1 of X are the terms that multiply "u".
	// Row 2 of X are the terms that multiply "v".

	// Grab CD.
	sipout->wcstan.cd[0][0] = gsl_vector_get(x1, 1);
	sipout->wcstan.cd[0][1] = gsl_vector_get(x1, 2);
	sipout->wcstan.cd[1][0] = gsl_vector_get(x2, 1);
	sipout->wcstan.cd[1][1] = gsl_vector_get(x2, 2);

	// Compute inv(CD)
	i = invert_2by2_arr((const double*)(sipout->wcstan.cd),
                        (double*)cdinv);
	assert(i == 0);

	// Grab the shift.
	sx = gsl_vector_get(x1, 0);
	sy = gsl_vector_get(x2, 0);

	// Extract the SIP coefficients.
	//  (this includes the 0 and 1 order terms, which we later overwrite)
	j = 0;
	for (order=0; order<=sip_order; order++) {
		for (q=0; q<=order; q++) {
			p = order - q;
			assert(j >= 0);
			assert(j < N);
			assert(p >= 0);
			assert(q >= 0);
			assert(p + q <= sip_order);

			sipout->a[p][q] =
				cdinv[0][0] * gsl_vector_get(x1, j) +
				cdinv[0][1] * gsl_vector_get(x2, j);

			sipout->b[p][q] =
				cdinv[1][0] * gsl_vector_get(x1, j) +
				cdinv[1][1] * gsl_vector_get(x2, j);
			j++;
		}
	}
	assert(j == N);

	// We have already dealt with the shift and linear terms, so zero them out
	// in the SIP coefficient matrix.
	sipout->a[0][0] = 0.0;
	sipout->a[0][1] = 0.0;
	sipout->a[1][0] = 0.0;
	sipout->b[0][0] = 0.0;
	sipout->b[0][1] = 0.0;
	sipout->b[1][0] = 0.0;

	sip_compute_inverse_polynomials(sipout, 0, 0, 0, 0, 0, 0);

    sU =
        cdinv[0][0] * sx +
        cdinv[0][1] * sy;
    sV =
        cdinv[1][0] * sx +
        cdinv[1][1] * sy;
    logverb("Applying shift of sx,sy = %g,%g deg (%g,%g pix) to CRVAL and CD.\n",
            sx, sy, sU, sV);

    sip_calc_inv_distortion(sipout, sU, sV, &su, &sv);

    debug("sx = %g, sy = %g\n", sx, sy);
    debug("sU = %g, sV = %g\n", sU, sV);
    debug("su = %g, sv = %g\n", su, sv);

    wcs_shift(&(sipout->wcstan), -su, -sv);

	if (r1)
		gsl_vector_free(r1);
	if (r2)
		gsl_vector_free(r2);

	gsl_matrix_free(mA);
	gsl_vector_free(b1);
	gsl_vector_free(b2);
	gsl_vector_free(x1);
	gsl_vector_free(x2);

    return 0;
}
Example #28
0
int plot_healpix_plot(const char* command,
					  cairo_t* cairo, plot_args_t* pargs, void* baton) {
	plothealpix_t* args = (plothealpix_t*)baton;
	double ra,dec,rad;
	il* hps;
	int i;
	double hpstep;
	int minx[12], maxx[12], miny[12], maxy[12];

	plotstuff_builtin_apply(cairo, pargs);

	if (plotstuff_get_radec_center_and_radius(pargs, &ra, &dec, &rad)) {
		ERROR("Failed to get RA,Dec center and radius");
		return -1;
	}
	hps = healpix_rangesearch_radec(ra, dec, rad, args->nside, NULL);
	logmsg("Found %zu healpixes in range.\n", il_size(hps));
	hpstep = args->nside * args->stepsize * plotstuff_pixel_scale(pargs) / 60.0 / healpix_side_length_arcmin(args->nside);
	hpstep = MIN(1, hpstep);
	logmsg("Taking steps of %g in healpix space\n", hpstep);

	// For each of the 12 top-level healpixes, find the range of healpixes covered by this image.
	for (i=0; i<12; i++) {
		maxx[i] = maxy[i] = -1;
		minx[i] = miny[i] = args->nside+1;
	}
	for (i=0; i<il_size(hps); i++) {
		int hp = il_get(hps, i);
		int hpx, hpy;
		int bighp;
		healpix_decompose_xy(hp, &bighp, &hpx, &hpy, args->nside);
		logverb("  hp %i: bighp %i, x,y (%i,%i)\n", i, bighp, hpx, hpy);
		minx[bighp] = MIN(minx[bighp], hpx);
		maxx[bighp] = MAX(maxx[bighp], hpx);
		miny[bighp] = MIN(miny[bighp], hpy);
		maxy[bighp] = MAX(maxy[bighp], hpy);
	}
	il_free(hps);

	for (i=0; i<12; i++) {
		int hx,hy;
		int hp;
		double d, frac;
		double x,y;

		if (maxx[i] == -1)
			continue;
		logverb("Big healpix %i: x range [%i, %i], y range [%i, %i]\n",
			   i, minx[i], maxx[i], miny[i], maxy[i]);

		for (hy = miny[i]; hy <= maxy[i]; hy++) {
			logverb("  y=%i\n", hy);
			for (d=minx[i]; d<=maxx[i]; d+=hpstep) {
				hx = floor(d);
				frac = d - hx;
				hp = healpix_compose_xy(i, hx, hy, args->nside);
				healpix_to_radecdeg(hp, args->nside, frac, 0.0, &ra, &dec);
				if (!plotstuff_radec2xy(pargs, ra, dec, &x, &y))
					continue;
				if (d == minx[i])
					cairo_move_to(pargs->cairo, x, y);
				else
					cairo_line_to(pargs->cairo, x, y);
			}
			cairo_stroke(pargs->cairo);
		}
		for (hx = minx[i]; hx <= maxx[i]; hx++) {
			for (d=miny[i]; d<=maxy[i]; d+=hpstep) {
				hy = floor(d);
				frac = d - hy;
				hp = healpix_compose_xy(i, hx, hy, args->nside);
				healpix_to_radecdeg(hp, args->nside, 0.0, frac, &ra, &dec);
				if (!plotstuff_radec2xy(pargs, ra, dec, &x, &y))
					continue;
				if (d == miny[i])
					cairo_move_to(pargs->cairo, x, y);
				else
					cairo_line_to(pargs->cairo, x, y);
			}
			cairo_stroke(pargs->cairo);
		}
	}
	return 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;
}
Example #30
0
int main(int argc, char** argv) {
    int argchar;
    allquads_t* aq;
    int loglvl = LOG_MSG;
    int i, N;
    char* catfn = NULL;

    startree_t* starkd;
    fitstable_t* cat;

    char* racol = NULL;
    char* deccol = NULL;
    int datatype = KDT_DATA_DOUBLE;
    int treetype = KDT_TREE_DOUBLE;
    int buildopts = 0;
    int Nleaf = 0;

    char* indexfn = NULL;
    //index_params_t* p;

    aq = allquads_init();
    aq->skdtfn = "allquads.skdt";
    aq->codefn = "allquads.code";
    aq->quadfn = "allquads.quad";

    while ((argchar = getopt (argc, argv, OPTIONS)) != -1)
        switch (argchar) {
        case 'v':
            loglvl++;
            break;
        case 'd':
            aq->dimquads = atoi(optarg);
            break;
        case 'I':
            aq->id = atoi(optarg);
            break;
        case 'h':
            print_help(argv[0]);
            exit(0);
        case 'i':
            catfn = optarg;
            break;
        case 'o':
            indexfn = optarg;
            break;
        case 'u':
            aq->quad_d2_upper = arcmin2distsq(atof(optarg));
            aq->use_d2_upper = TRUE;
            break;
        case 'l':
            aq->quad_d2_lower = arcmin2distsq(atof(optarg));
            aq->use_d2_lower = TRUE;
            break;
        default:
            return -1;
        }

    log_init(loglvl);

    if (!catfn || !indexfn) {
        printf("Specify in & out filenames, bonehead!\n");
        print_help(argv[0]);
        exit( -1);
    }

    if (optind != argc) {
        print_help(argv[0]);
        printf("\nExtra command-line args were given: ");
        for (i=optind; i<argc; i++) {
            printf("%s ", argv[i]);
        }
        printf("\n");
        exit(-1);
    }

    if (!aq->id)
        logmsg("Warning: you should set the unique-id for this index (with -I).\n");

    if (aq->dimquads > DQMAX) {
        ERROR("Quad dimension %i exceeds compiled-in max %i.\n", aq->dimquads, DQMAX);
        exit(-1);
    }
    aq->dimcodes = dimquad2dimcode(aq->dimquads);

    // Read reference catalog, write star kd-tree
    logmsg("Building star kdtree: reading %s, writing to %s\n", catfn, aq->skdtfn);
    
    logverb("Reading star catalogue...");
    cat = fitstable_open(catfn);
    if (!cat) {
        ERROR("Couldn't read catalog");
        exit(-1);
    }
    logmsg("Got %i stars\n", fitstable_nrows(cat));
    starkd = startree_build(cat, racol, deccol, datatype, treetype,
                            buildopts, Nleaf, argv, argc);
    if (!starkd) {
        ERROR("Failed to create star kdtree");
        exit(-1);
    }

    logmsg("Star kd-tree contains %i data points in dimension %i\n",
           startree_N(starkd), startree_D(starkd));
    N = startree_N(starkd);
    for (i=0; i<N; i++) {
        double ra,dec;
        int ok;
        ok = startree_get_radec(starkd, i, &ra, &dec);
        logmsg("  data %i: ok %i, RA,Dec %g, %g\n", i, ok, ra, dec);
    }

    if (startree_write_to_file(starkd, aq->skdtfn)) {
        ERROR("Failed to write star kdtree");
        exit(-1);
    }
    startree_close(starkd);
    fitstable_close(cat);
    logmsg("Wrote star kdtree to %s\n", aq->skdtfn);

    logmsg("Running allquads...\n");
    if (allquads_open_outputs(aq)) {
        exit(-1);
    }

    if (allquads_create_quads(aq)) {
        exit(-1);
    }

    if (allquads_close(aq)) {
        exit(-1);
    }

    logmsg("allquads: wrote %s, %s\n", aq->quadfn, aq->codefn);

    // build-index:
    //build_index_defaults(&p);

    // codetree
    /*
     if (step_codetree(p, codes, &codekd,
     codefn, &ckdtfn, tempfiles))
     return -1;
     */
    char* ckdtfn=NULL;
    char* tempdir = NULL;

    ckdtfn = create_temp_file("ckdt", tempdir);
    logmsg("Creating code kdtree, reading %s, writing to %s\n", aq->codefn, ckdtfn);
    if (codetree_files(aq->codefn, ckdtfn, 0, 0, 0, 0, argv, argc)) {
        ERROR("codetree failed");
        return -1;
    }

    char* skdt2fn=NULL;
    char* quad2fn=NULL;

    // unpermute-stars
    logmsg("Unpermute-stars...\n");
    skdt2fn = create_temp_file("skdt2", tempdir);
    quad2fn = create_temp_file("quad2", tempdir);

    logmsg("Unpermuting stars from %s and %s to %s and %s\n",
           aq->skdtfn, aq->quadfn, skdt2fn, quad2fn);
    if (unpermute_stars_files(aq->skdtfn, aq->quadfn, skdt2fn, quad2fn,
                              TRUE, FALSE, argv, argc)) {
        ERROR("Failed to unpermute-stars");
        return -1;
    }

    allquads_free(aq);

    // unpermute-quads
    /*
     if (step_unpermute_quads(p, quads2, codekd, &quads3, &codekd2,
     quad2fn, ckdtfn, &quad3fn, &ckdt2fn, tempfiles))
     return -1;
     */
    char* quad3fn=NULL;
    char* ckdt2fn=NULL;

    ckdt2fn = create_temp_file("ckdt2", tempdir);
    quad3fn = create_temp_file("quad3", tempdir);
    logmsg("Unpermuting quads from %s and %s to %s and %s\n",
           quad2fn, ckdtfn, quad3fn, ckdt2fn);
    if (unpermute_quads_files(quad2fn, ckdtfn,
                              quad3fn, ckdt2fn, argv, argc)) {
        ERROR("Failed to unpermute-quads");
        return -1;
    }

    // index
    /*
     if (step_merge_index(p, codekd2, quads3, starkd2, p_index,
     ckdt2fn, quad3fn, skdt2fn, indexfn))
     return -1;
     */
    quadfile_t* quad;
    codetree_t* code;
    startree_t* star;

    logmsg("Merging %s and %s and %s to %s\n",
           quad3fn, ckdt2fn, skdt2fn, indexfn);
    if (merge_index_open_files(quad3fn, ckdt2fn, skdt2fn,
                               &quad, &code, &star)) {
        ERROR("Failed to open index files for merging");
        return -1;
    }
    if (merge_index(quad, code, star, indexfn)) {
        ERROR("Failed to write merged index");
        return -1;
    }
    codetree_close(code);
    startree_close(star);
    quadfile_close(quad);

    printf("Done.\n");

    free(ckdtfn);
    free(skdt2fn);
    free(quad2fn);
    free(ckdt2fn);
    free(quad3fn);

    return 0;
}