Exemplo n.º 1
0
int bl_insert_unique_sorted(bl* list, const void* data,
							int (*compare)(const void* v1, const void* v2)) {
	// This is just straightforward binary search - really should
	// use the block structure...
	int lower, upper;
	lower = -1;
	upper = list->N;
	while (lower < (upper-1)) {
		int mid;
		int cmp;
		mid = (upper + lower) / 2;
		cmp = compare(data, bl_access(list, mid));
		if (cmp >= 0) {
			lower = mid;
		} else {
			upper = mid;
		}
	}

	if (lower >= 0) {
		if (compare(data, bl_access(list, lower)) == 0) {
			return -1;
		}
	}
	bl_insert(list, lower+1, data);
	return lower+1;
}
Exemplo n.º 2
0
int bl_check_sorted(bl* list,
					int (*compare)(const void* v1, const void* v2),
					int isunique) {
	int i, N;
	int nbad = 0;
	void* v2 = NULL;
	N = bl_size(list);
	if (N)
		v2 = bl_access(list, 0);
	for (i=1; i<N; i++) {
		void* v1;
		int cmp;
		v1 = v2;
		v2 = bl_access(list, i);
		cmp = compare(v1, v2);
		if (isunique) {
			if (cmp >= 0) {
				nbad++;
			}
		} else {
			if (cmp > 0) {
				nbad++;
			}
		}
	}
	if (nbad) {
		fprintf(stderr, "bl_check_sorted: %i are out of order.\n", nbad);
		return 1;
	}
	return 0;
}
Exemplo n.º 3
0
static void bl_find_ind_and_element(bl* list, const void* data,
									int (*compare)(const void* v1, const void* v2),
									void** presult, int* pindex) {
	int lower, upper;
	int cmp = -2;
	void* result;
	lower = -1;
	upper = list->N;
	while (lower < (upper-1)) {
		int mid;
		mid = (upper + lower) / 2;
		cmp = compare(data, bl_access(list, mid));
		if (cmp >= 0) {
			lower = mid;
		} else {
			upper = mid;
		}
	}
	if (lower == -1 || compare(data, (result = bl_access(list, lower)))) {
		*presult = NULL;
		*pindex = -1;
		return;
	}
	*presult = result;
	*pindex = lower;
}
Exemplo n.º 4
0
int opts_getopt(bl* opts, int argc, char** argv) {
    size_t i, j, N;
    char* optstring;
    int c;
    struct option* longoptions;

    N = bl_size(opts);
    // create the short options string.
    optstring = malloc(3 * N + 1);
    j = 0;
    for (i=0; i<N; i++) {
        an_option_t* opt = bl_access(opts, i);
        if (!opt->shortopt)
            continue;
        if (iscntrl((unsigned)(opt->shortopt)))
            continue;
        optstring[j] = opt->shortopt;
        j++;
        if (opt->has_arg == no_argument)
            continue;
        optstring[j] = ':';
        j++;
        if (opt->has_arg == required_argument)
            continue;
        optstring[j] = ':';
        j++;
    }
    optstring[j] = '\0';
    // create long options.
    longoptions = calloc(N+1, sizeof(struct option));
    j = 0;
    for (i=0; i<N; i++) {
        an_option_t* opt = bl_access(opts, i);
        if (!opt->shortopt)
            continue;
        //if (iscntrl(opt->shortopt))
        //continue;
        longoptions[j].name = opt->name;
        longoptions[j].has_arg = opt->has_arg;
        longoptions[j].val = opt->shortopt;
        j++;
    }

    // DEBUG
    //printf("%s\n", optstring);

    c = getopt_long(argc, argv, optstring, longoptions, NULL);

    free(optstring);
    free(longoptions);

    return c;
}
Exemplo n.º 5
0
void opts_print_help(bl* opts, FILE* fid,
                     void (*special_case)(an_option_t* opt, bl* allopts, int index,
                             FILE* fid, void* extra), void* extra) {
    int i;
    for (i=0; i<bl_size(opts); i++) {
        an_option_t* opt = bl_access(opts, i);
        int nw = 0;
        sl* words;
        int j;
        if (opt->help) {
            if ((opt->shortopt >= 'a' && opt->shortopt <= 'z') ||
                    (opt->shortopt >= 'A' && opt->shortopt <= 'Z') ||
                    (opt->shortopt >= '0' && opt->shortopt <= '9'))
                nw += fprintf(fid, "  -%c / --%s", opt->shortopt, opt->name);
            else
                nw += fprintf(fid, "  --%s", opt->name);
            if (opt->has_arg == optional_argument)
                nw += fprintf(fid, " [<%s>]", opt->argname);
            else if (opt->has_arg == required_argument)
                nw += fprintf(fid, " <%s>", opt->argname);
            nw += fprintf(fid, ": ");
            if (!opt->help)
                continue;
            words = split_long_string(opt->help, 80-nw, 70, NULL);
            for (j=0; j<sl_size(words); j++)
                fprintf(fid, "%s%s\n", (j==0 ? "" : "          "), sl_get(words, j));
        } else if (special_case)
            special_case(opt, opts, i, fid, extra);
    }
}
Exemplo n.º 6
0
int fitstable_write_one_column(fitstable_t* table, int colnum,
                               int rowoffset, int nrows,
                               const void* src, int src_stride) {
	anbool flip = TRUE;
    off_t foffset = 0;
    off_t start = 0;
    int i;
    char* buf = NULL;
    fitscol_t* col;
	int off;

	off = offset_of_column(table, colnum);
	if (!in_memory(table)) {
		foffset = ftello(table->fid);
		// jump to row start...
		start = get_row_offset(table, rowoffset) + off;
		if (fseeko(table->fid, start, SEEK_SET)) {
			SYSERROR("Failed to fseeko() to the start of the file.");
			return -1;
		}
	}

    col = getcol(table, colnum);
    if (col->fitstype != col->ctype) {
		int sz = col->fitssize * col->arraysize * nrows;
        buf = malloc(sz);
        fits_convert_data(buf, col->fitssize * col->arraysize, col->fitstype,
                          src, src_stride, col->ctype,
                          col->arraysize, nrows);
        src = buf;
        src_stride = col->fitssize * col->arraysize;
    }

	if (in_memory(table)) {
		for (i=0; i<nrows; i++) {
			memcpy(((char*)bl_access(table->rows, rowoffset + i)) + off,
				   src, col->fitssize * col->arraysize);
			src = ((const char*)src) + src_stride;
		}
	} else {
		for (i=0; i<nrows; i++) {
			if (fseeko(table->fid, start + i * table->table->tab_w, SEEK_SET) ||
				fits_write_data_array(table->fid, src, col->fitstype, col->arraysize, flip)) {
				SYSERROR("Failed to write row %i of column %i", rowoffset+i, colnum);
				return -1;
			}
			src = ((const char*)src) + src_stride;
		}
	}
    free(buf);

	if (!in_memory(table)) {
		if (fseeko(table->fid, foffset, SEEK_SET)) {
			SYSERROR("Failed to restore file offset.");
			return -1;
		}
	}
    return 0;
}
Exemplo n.º 7
0
void testit(int* wanted, int Nwanted, int dimquads, int (*compar)(const void *, const void *),
			anbool cxdx) {
	int i;
    solver_t* solver;
    index_t index;
    starxy_t* starxy;

	starxy = field1();
    quadlist = bl_new(16, dimquads*sizeof(int));
	ninv = 0;
    solver = solver_new();
    memset(&index, 0, sizeof(index_t));
    index.index_scale_lower = 1;
    index.index_scale_upper = 10;
	index.dimquads = dimquads;

	index.cx_less_than_dx = index.meanx_less_than_half = cxdx;

    solver->funits_lower = 0.1;
    solver->funits_upper = 10;

    solver_add_index(solver, &index);
    solver_set_field(solver, starxy);
    solver_preprocess_field(solver);

	printf("Found:\n");
    solver_run(solver);
	printf("\n");
	fflush(NULL);

    solver_free_field(solver);
    solver_free(solver);

    //
	bl_sort(quadlist, compar);

	qsort(wanted, Nwanted, dimquads*sizeof(int), compar);
	printf("\n\n");
	printf("Wanted:\n");
    for (i=0; i<Nwanted; i++) {
		int j;
		printf("{");
		for (j=0; j<dimquads; j++)
			printf("%s%i", (j?",":""), wanted[i*dimquads+j]);
		printf("}, ");
	}
	printf("\n");
	printf("N found: %i; N wanted: %i\n", bl_size(quadlist), Nwanted);
	printf("N obeying invariants: %i\n", ninv);
    assert(bl_size(quadlist) == Nwanted);
    for (i=0; i<bl_size(quadlist); i++) {
		//int* i1 = bl_access(quadlist, i);
		//int* i2 = wanted[i];
		//printf("[%i, %i, %i] vs [%i, %i, %i]\n", i1[0],i1[1],i1[2], i2[0],i2[1],i2[2]);
        assert(compar(bl_access(quadlist, i), wanted+i*dimquads) == 0);
    }
    bl_free(quadlist);
}
Exemplo n.º 8
0
static void bl_sort_with_userdata(bl* list,
								  int (*compare)(const void* v1, const void* v2, void* userdata),
								  void* userdata) {
	int ind;
	int N = list->N;
	if (N <= 1)
		return;
	// should do median-of-3/5/... to select pivot when N is large.
	ind = rand() % N;
	bl_sort_rec(list, bl_access(list, ind), compare, userdata);
}
Exemplo n.º 9
0
void test_bl_extend(CuTest *tc) {
	bl* list = bl_new(10, sizeof(int));
	CuAssertIntEquals(tc, bl_size(list), 0);
	int *new1 = bl_extend(list);
	CuAssertPtrNotNull(tc, new1);
	CuAssertIntEquals(tc, bl_size(list), 1);
	*new1 = 10;
	int *new2 = bl_access(list, 0);
	CuAssertPtrEquals(tc, new2, new1);
    bl_free(list);
}
Exemplo n.º 10
0
int fitstable_close(fitstable_t* tab) {
    int i;
    int rtn = 0;
    if (!tab) return 0;
	if (is_writing(tab)) {
        if (fclose(tab->fid)) {
            SYSERROR("Failed to close output file %s", tab->fn);
            rtn = -1;
        }
    }
	if (tab->anq) {
		anqfits_close(tab->anq);
	}
	if (tab->readfid) {
		fclose(tab->readfid);
	}
    if (tab->primheader)
        qfits_header_destroy(tab->primheader);
    if (tab->header)
        qfits_header_destroy(tab->header);
    if (tab->table)
        qfits_table_close(tab->table);
    free(tab->fn);
    for (i=0; i<ncols(tab); i++) {
        fitscol_t* col = getcol(tab, i);
        free(col->colname);
        free(col->units);
    }
    bl_free(tab->cols);
    if (tab->br) {
        buffered_read_free(tab->br);
        free(tab->br);
    }
	if (tab->rows) {
		bl_free(tab->rows);
	}
	if (tab->extensions) {
		for (i=0; i<bl_size(tab->extensions); i++) {
			fitsext_t* ext = bl_access(tab->extensions, i);
			if (ext->rows != tab->rows)
				bl_free(ext->rows);
			if (ext->header != tab->header)
				qfits_header_destroy(ext->header);
			if (ext->table != tab->table)
				qfits_table_close(ext->table);
		}
		bl_free(tab->extensions);
	}
    free(tab);
    return rtn;
}
Exemplo n.º 11
0
static void write_field(bl* agreeing,
						bl* leftover,
						int fieldfile,
						int fieldnum) {
	int i;

	if (!bl_size(agreeing))
		il_append(unsolved, fieldnum);
	else {
		il_append(solved, fieldnum);
		if (solvedserver)
			solvedclient_set(fieldfile, fieldnum);
		if (solvedfile) {
			char fn[256];
			sprintf(fn, solvedfile, fieldfile);
			solvedfile_set(fn, fieldnum);
		}
	}

	for (i=0; agreeing && i<bl_size(agreeing); i++) {
		MatchObj* mo = bl_access(agreeing, i);
		if (matchfile_write_match(agreemf, mo))
			fprintf(stderr, "Error writing an agreeing match.");
		fprintf(stderr, "Field %i: Logodds %g (%g)\n", fieldnum, mo->logodds, exp(mo->logodds));
	}

	if (leftover && bl_size(leftover)) {
		fprintf(stderr, "Field %i: writing %i leftovers...\n", fieldnum,
				bl_size(leftover));
		for (i=0; i<bl_size(leftover); i++) {
			MatchObj* mo = bl_access(leftover, i);
			if (matchfile_write_match(leftovermf, mo))
				fprintf(stderr, "Error writing a leftover match.");
		}
	}
}
Exemplo n.º 12
0
int fitstable_open_extension(fitstable_t* tab, int ext) {
	if (in_memory(tab)) {
		fitsext_t* theext;
		if (ext > bl_size(tab->extensions)) {
			ERROR("Table has only %zu extensions, but you requested #%i",
				  bl_size(tab->extensions), ext);
			return -1;
		}
		theext = bl_access(tab->extensions, ext-1);
		tab->table = theext->table;
		tab->header = theext->header;
		tab->rows = theext->rows;
		tab->extension = ext;

	} else {
		if (tab->table) {
			qfits_table_close(tab->table);
            tab->table = NULL;
		}

        assert(tab->anq);
        if (ext >= anqfits_n_ext(tab->anq)) {
            ERROR("Requested FITS extension %i in file %s, but there are only %i extensions.\n", ext, tab->fn, anqfits_n_ext(tab->anq));
            return -1;
        }
        tab->table = anqfits_get_table(tab->anq, ext);

		if (!tab->table) {
			ERROR("FITS extension %i in file %s is not a table (or there was an error opening the file)", ext, tab->fn);
			return -1;
		}
		if (tab->header) {
			qfits_header_destroy(tab->header);
		}

        tab->header = anqfits_get_header(tab->anq, ext);
		if (!tab->header) {
			ERROR("Couldn't get header for FITS extension %i in file %s", ext, tab->fn);
			return -1;
		}
		tab->extension = ext;
	}
    return 0;
}
Exemplo n.º 13
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);
}
Exemplo n.º 14
0
int bl_insert_sorted(bl* list, const void* data,
					 int (*compare)(const void* v1, const void* v2)) {
	int lower, upper;
	lower = -1;
	upper = list->N;
	while (lower < (upper-1)) {
		int mid;
		int cmp;
		mid = (upper + lower) / 2;
		cmp = compare(data, bl_access(list, mid));
		if (cmp >= 0) {
			lower = mid;
		} else {
			upper = mid;
		}
	}
	bl_insert(list, lower+1, data);
	return lower+1;
}
Exemplo n.º 15
0
int fitstable_read_nrows_data(fitstable_t* table, int row0, int nrows,
							  void* dest) {
	int R;
	off_t off;
	assert(table);
	assert(row0 >= 0);
	assert((row0 + nrows) <= fitstable_nrows(table));
	assert(dest);
	R = fitstable_row_size(table);
	if (in_memory(table)) {
		int i;
		char* cdest = dest;
		for (i=0; i<nrows; i++)
			memcpy(cdest, bl_access(table->rows, row0 + i), R);
		return 0;
	}
	if (!table->readfid) {
		table->readfid = fopen(table->fn, "rb");
		if (!table->readfid) {
			SYSERROR("Failed to open FITS table %s for reading", table->fn);
			return -1;
		}

        assert(table->anq);
        off_t start;
        start = anqfits_data_start(table->anq, table->extension);
        table->end_table_offset = start;
	}
	off = get_row_offset(table, row0);
	if (fseeko(table->readfid, off, SEEK_SET)) {
		SYSERROR("Failed to fseeko() to read a row");
		return -1;
	}
	if (fread(dest, 1, R*nrows, table->readfid) != (R*nrows)) {
		SYSERROR("Failed to read %i rows starting from %i, from %s", nrows, row0, table->fn);
		return -1;
	}
	return 0;
}
Exemplo n.º 16
0
/**
 If "inds" is non-NULL, it's a list of indices to read.
 */
static void* read_array_into(const fitstable_t* tab,
							 const char* colname, tfits_type ctype,
							 anbool array_ok,
							 int offset, const int* inds, int Nread,
							 void* dest, int deststride,
							 int desired_arraysize,
							 int* p_arraysize) {
    int colnum;
    qfits_col* col;
    int fitssize;
    int csize;
    int fitstype;
    int arraysize;

	char* tempdata = NULL;
    char* cdata;
	char* fitsdata;
	int cstride;
	int fitsstride;
    int N;

    colnum = fits_find_column(tab->table, colname);
    if (colnum == -1) {
        ERROR("Column \"%s\" not found in FITS table %s", colname, tab->fn);
        return NULL;
    }
    col = tab->table->col + colnum;
    if (!array_ok && (col->atom_nb != 1)) {
        ERROR("Column \"%s\" in FITS table %s is an array of size %i, not a scalar",
              colname, tab->fn, col->atom_nb);
        return NULL;
    }

    arraysize = col->atom_nb;
	if (p_arraysize)
		*p_arraysize = arraysize;
	if (desired_arraysize && arraysize != desired_arraysize) {
		ERROR("Column \"%s\" has array size %i but you wanted %i", colname, arraysize, desired_arraysize);
		return NULL;
	}
    fitstype = col->atom_type;
    fitssize = fits_get_atom_size(fitstype);
    csize = fits_get_atom_size(ctype);
    N = tab->table->nr;
    if (Nread == -1)
        Nread = N;
    if (offset == -1)
        offset = 0;

	if (dest)
		cdata = dest;
	else
		cdata = calloc(Nread * arraysize, csize);

	if (dest && deststride > 0)
		cstride = deststride;
	else
		cstride = csize * arraysize;

	fitsstride = fitssize * arraysize;
	if (csize < fitssize) {
		// Need to allocate a bigger temp array and down-convert the data.
		// HACK - could set data=tempdata and realloc after (if 'dest' is NULL)
		tempdata = calloc(Nread * arraysize, fitssize);
		fitsdata = tempdata;
	} else {
		// We'll read the data into the first fraction of the output array.
		fitsdata = cdata;
	}

	if (in_memory(tab)) {
		int i;
		int off;
		int sz;
		if (!tab->rows) {
			ERROR("No data has been written to this fitstable");
			return NULL;
		}
		if (offset + Nread > bl_size(tab->rows)) {
			ERROR("Number of data items requested exceeds number of rows: offset %i, n %i, nrows %zu", offset, Nread, bl_size(tab->rows));
			return NULL;
		}
		off = fits_offset_of_column(tab->table, colnum);
		sz = fitsstride;
		if (inds) {
			for (i=0; i<Nread; i++)
				memcpy(fitsdata + i * fitsstride,
					   ((char*)bl_access(tab->rows, inds[i])) + off,
					   sz);
		} else {
			for (i=0; i<Nread; i++)
				memcpy(fitsdata + i * fitsstride,
					   ((char*)bl_access(tab->rows, offset+i)) + off,
					   sz);
		}
	} else {
		int res;
		if (inds) {
			res = qfits_query_column_seq_to_array_inds(tab->table, colnum, inds, Nread,
													   (unsigned char*)fitsdata, fitsstride);
		} else {
			res = qfits_query_column_seq_to_array(tab->table, colnum, offset, Nread,
												  (unsigned char*)fitsdata, fitsstride);
		}
		if (res) {
			ERROR("Failed to read column from FITS file");
			// MEMLEAK!
			return NULL;
		}
	}

	if (fitstype != ctype) {
		if (csize <= fitssize) {
			// work forward
			fits_convert_data(cdata, cstride, ctype,
							  fitsdata, fitsstride, fitstype,
							  arraysize, Nread);
		} else {
			// work backward from the end of the array
            fits_convert_data(cdata + (((off_t)Nread*(off_t)arraysize)-1) * (off_t)csize,
							  -csize, ctype,
							  fitsdata + (((off_t)Nread*(off_t)arraysize)-1) * (off_t)fitssize,
							  -fitssize, fitstype,
							  1, Nread * arraysize);
		}
	}

	free(tempdata);
	return cdata;
}
Exemplo n.º 17
0
static fitscol_t* getcol(const fitstable_t* t, int i) {
    return bl_access(t->cols, i);
}
Exemplo n.º 18
0
static startree_t* my_open(const char* fn, anqfits_t* fits) {
    struct timeval tv1, tv2;
	startree_t* s;
    bl* chunks;
    int i;
    kdtree_fits_t* io;
    char* treename = STARTREE_NAME;
    const char* thefn = fn;

	assert(fn || fits);

    if (!thefn)
        thefn = fits->filename;

	s = startree_alloc();
	if (!s)
		return NULL;

    gettimeofday(&tv1, NULL);
	if (fn)
		io = kdtree_fits_open(fn);
	else
		io = kdtree_fits_open_fits(fits);

    gettimeofday(&tv2, NULL);
    debug("kdtree_fits_open() took %g ms\n", millis_between(&tv1, &tv2));
	if (!io) {
        ERROR("Failed to open FITS file \"%s\"", thefn);
        goto bailout;
    }

    gettimeofday(&tv1, NULL);
    if (!kdtree_fits_contains_tree(io, treename))
        treename = NULL;
    gettimeofday(&tv2, NULL);
    debug("kdtree_fits_contains_tree() took %g ms\n", millis_between(&tv1, &tv2));

    gettimeofday(&tv1, NULL);
    s->tree = kdtree_fits_read_tree(io, treename, &s->header);
    gettimeofday(&tv2, NULL);
    debug("kdtree_fits_read_tree() took %g ms\n", millis_between(&tv1, &tv2));
    if (!s->tree) {
        ERROR("Failed to read kdtree from file \"%s\"", thefn);
        goto bailout;
    }

    // Check the tree dimensionality.
    // (because code trees can be confused...)
    if (s->tree->ndim != 3) {
        logverb("File %s contains a kd-tree with dim %i (not 3), named %s\n",
                thefn, s->tree->ndim, treename);
        s->tree->io = NULL;
        goto bailout;
    }

    gettimeofday(&tv1, NULL);
    chunks = get_chunks(s, NULL);
    for (i=0; i<bl_size(chunks); i++) {
        fitsbin_chunk_t* chunk = bl_access(chunks, i);
        void** dest = chunk->userdata;
        kdtree_fits_read_chunk(io, chunk);
        *dest = chunk->data;
    }
    bl_free(chunks);
    gettimeofday(&tv2, NULL);
    debug("reading chunks took %g ms\n", millis_between(&tv1, &tv2));

    // kdtree_fits_t is a typedef of fitsbin_t
    fitsbin_close_fd(io);

	return s;

 bailout:
    kdtree_fits_io_close(io);
    startree_close(s);
	return NULL;
}
Exemplo n.º 19
0
int fitstable_read_structs(fitstable_t* tab, void* struc,
                           int strucstride, int offset, int N) {
    int i;
    void* tempdata = NULL;
    int highwater = 0;

    //printf("fitstable_read_structs: stride %i, offset %i, N %i\n",strucstride, offset, N);

    for (i=0; i<ncols(tab); i++) {
        void* dest;
        int stride;
        void* finaldest;
        int finalstride;
        fitscol_t* col = getcol(tab, i);
        if (col->col == -1)
            continue;
        if (!col->in_struct)
            continue;
        finaldest = ((char*)struc) + col->coffset;
        finalstride = strucstride;

        if (col->fitstype != col->ctype) {
            int NB = fitscolumn_get_size(col) * N;
            if (NB > highwater) {
                free(tempdata);
                tempdata = malloc(NB);
                highwater = NB;
            }
            dest = tempdata;
            stride = fitscolumn_get_size(col);
        } else {
            dest = finaldest;
            stride = finalstride;
        }

		if (in_memory(tab)) {
			int j;
			int off = offset_of_column(tab, i);
			int sz;
			if (!tab->rows) {
				ERROR("No data has been written to this fitstable");
				return -1;
			}
			if (offset + N > bl_size(tab->rows)) {
				ERROR("Number of data items requested exceeds number of rows: offset %i, n %i, nrows %zu", offset, N, bl_size(tab->rows));
				return -1;
			}

			//logverb("column %i: dest offset %i, stride %i, row offset %i, input offset %i, size %i (%ix%i)\n", i, (int)(dest - struc), stride, offset, off, fitscolumn_get_size(col), col->fitssize, col->arraysize);
			sz = fitscolumn_get_size(col);
			for (j=0; j<N; j++)
				memcpy(((char*)dest) + j * stride,
					   ((char*)bl_access(tab->rows, offset+j)) + off,
					   sz);
		} else {
			// Read from FITS file...
			qfits_query_column_seq_to_array(tab->table, col->col, offset, N, dest, stride);
		}

        if (col->fitstype != col->ctype) {
            fits_convert_data(finaldest, finalstride, col->ctype,
                              dest, stride, col->fitstype,
                              col->arraysize, N);
        }
    }
    free(tempdata);

    if (tab->postprocess_read_structs)
        return tab->postprocess_read_structs(tab, struc, strucstride, offset, N);

    return 0;
}
Exemplo n.º 20
0
void bl_get(bl* list, size_t n, void* dest) {
    assert(list->N > 0);
    char* src = bl_access(list, n);
    memcpy(dest, src, list->datasize);
}
Exemplo n.º 21
0
static int write_to_file(startree_t* s, const char* fn, anbool flipped,
						 FILE* fid) {
    bl* chunks;
    il* wordsizes = NULL;
    int i;
    kdtree_fits_t* io = NULL;

	// just haven't bothered...
	assert(!(flipped && fid));

	if (fn) {
		io = kdtree_fits_open_for_writing(fn);
		if (!io) {
			ERROR("Failed to open file \"%s\" for writing kdtree", fn);
			return -1;
		}
	}
    if (flipped) {
        if (kdtree_fits_write_tree_flipped(io, s->tree, s->header)) {
            ERROR("Failed to write (flipped) kdtree to file \"%s\"", fn);
            return -1;
        }
    } else {
		if (fid) {
			if (kdtree_fits_append_tree_to(s->tree, s->header, fid)) {
				ERROR("Failed to write star kdtree");
				return -1;
			}
		} else {
			if (kdtree_fits_write_tree(io, s->tree, s->header)) {
				ERROR("Failed to write kdtree to file \"%s\"", fn);
				return -1;
			}
		}
    }

    if (flipped)
        wordsizes = il_new(4);

    chunks = get_chunks(s, wordsizes);
    for (i=0; i<bl_size(chunks); i++) {
        fitsbin_chunk_t* chunk = bl_access(chunks, i);
        if (!chunk->data)
            continue;
        if (flipped)
            kdtree_fits_write_chunk_flipped(io, chunk, il_get(wordsizes, i));
        else {
			if (fid) {
				kdtree_fits_write_chunk_to(chunk, fid);
			} else {
				kdtree_fits_write_chunk(io, chunk);
			}
		}
		fitsbin_chunk_clean(chunk);
	}
	bl_free(chunks);

    if (flipped)
        il_free(wordsizes);
    
	if (io)
		kdtree_fits_io_close(io);
    return 0;
}
static void dualtree_rs_recurse(kdtree_t* xtree, kdtree_t* ytree,
								il* xnodes, il* xleaves,
								bl* xnodebbs, bl* xleafbbs,
								int ynode,
								ttype* ybb,
								double maxd2,
								rangesearch_callback cb, void* baton) {
	int leafmarker;
	il* childnodes;
	int i, N;
	ttype oldbbval;
	ttype splitval;
	uint8_t splitdim;

	// if the query node is a leaf...
	if (KD_IS_LEAF(ytree, ynode)) {
		// ... then run the result function on each x node
		/*
		 if (callbacks->start_results)
		 callbacks->start_results(callbacks->start_extra, ytree, ynode);
		 */
		if (cb) {
			// non-leaf nodes
			N = il_size(xnodes);
			for (i=0; i<N; i++)
				dtrs_nodes(xtree, ytree, il_get(xnodes, i), ynode, maxd2, cb, baton);
		    // leaf nodes
			N = il_size(xleaves);
			for (i=0; i<N; i++)
				dtrs_nodes(xtree, ytree, il_get(xleaves, i), ynode, maxd2, cb, baton);
		}
		/*
		 if (callbacks->end_results)
		 callbacks->end_results(callbacks->end_extra, ytree, ynode);
		 */
		return;
	}

	// if there are search leaves but no search nodes, run the result
	// function on each leaf.  (Note that the query node is not a leaf!)
	if (!il_size(xnodes)) {
		/*
		 result_function result = callbacks->result;
		 void* result_extra = callbacks->result_extra;
		 if (callbacks->start_results)
		 callbacks->start_results(callbacks->start_extra, ytree, ynode);
		 */
		// leaf nodes
		if (result) {
			N = il_size(xleaves);
			for (i=0; i<N; i++)
				dtrs_nodes(xtree, ytree, il_get(xleaves, i), ynode, maxd2, cb, baton);
			//result(result_extra, xtree, il_get(leaves, i), ytree, ynode);
		}
		/*
		 if (callbacks->end_results)
		 callbacks->end_results(callbacks->end_extra, ytree, ynode);
		 */
		return;
	}

	leafmarker = il_size(leaves);
	childnodes = il_new(256);

#define BBLO(bb, d) ((bb)[2*(d)])
#define BBHI(bb, d) ((bb)[(2*(d))+1])

	N = il_size(xnodes);
	for (i=0; i<N; i++) {
		int child1, child2;
		int xnode = il_get(xnodes, i);
		ttype* xbb = bl_access(xnodebbs, i);
		ttype* leftbb;
		ttype* rightbb;

		/*
		 node-node range...
		 if (!decision(decision_extra, xtree, xnode, ytree, ynode))
		 continue;
		 */
		split_dim_and_value(xtree, xnode, &splitdim, &splitval);
		child1 = KD_CHILD_LEFT(xnode);
		if (KD_IS_LEAF(xtree, child1)) {
			il_append(xleaves, child1);
			il_append(xleaves, child2);
			leftbb  = bl_append(xleafbbs, xbb);
			rightbb = bl_append(xleafbbs, xbb);
		} else {
			il_append(childnodes, child1);
			il_append(childnodes, child2);
			leftbb  = bl_append(xnodebbs, xbb);
			rightbb = bl_append(xnodebbs, xbb);
		}
		BBHI(leftbb,  splitdim) = splitval;
		BBLO(rightbb, splitdim) = splitval;
	}

	printf("dualtree: start left child of y node %i: %i\n", ynode, KD_CHILD_LEFT(ynode));
	// recurse on the Y children!
	split_dim_and_value(ytree, ynode, &splitdim, &splitval);
	// update y bb for the left child: max(splitdim) = splitval
	oldbbval = BBHI(ybb, splitdim);
	BBHI(ybb, splitdim) = splitval;
	dualtree_recurse(xtree, ytree, childnodes, leaves,
					 KD_CHILD_LEFT(ynode), callbacks);
	BBHI(ybb, splitdim) = oldbbval;
	printf("dualtree: done left child of y node %i: %i\n", ynode, KD_CHILD_LEFT(ynode));

	printf("dualtree: start right child of y node %i: %i\n", ynode, KD_CHILD_RIGHT(ynode));
	// update y bb for the right child: min(splitdim) = splitval
	oldbbval = BBLO(ybb, splitdim);
	BBLO(ybb, splitdim) = splitval;
	dualtree_recurse(xtree, ytree, childnodes, leaves,
					 KD_CHILD_RIGHT(ynode), callbacks);
	BBLO(ybb, splitdim) = oldbbval;
	printf("dualtree: done right child of y node %i: %i\n", ynode, KD_CHILD_LEFT(ynode));

	// put the "leaves" list back the way it was...
	il_remove_index_range(leaves, leafmarker, il_size(leaves)-leafmarker);
	il_free(childnodes);
}
Exemplo n.º 23
0
void test2() {
	int i;
    solver_t* solver;
    index_t index;
    starxy_t* starxy;
    int wanted[][3] = { { 0, 1, 3 },
						{ 0, 1, 4 },
						{ 0, 1, 5 },
						{ 0, 2, 3 },
						{ 0, 2, 4 },
						{ 0, 3, 4 },
						{ 0, 5, 4 },
						{ 0, 6, 4 },
						{ 0, 6, 5 },
						{ 1, 2, 3 },
						{ 1, 2, 4 },
						{ 1, 3, 4 },
						{ 1, 5, 4 },
						{ 1, 6, 4 },
						{ 1, 6, 5 },
						{ 2, 4, 3 },
						{ 2, 5, 0 },
						{ 2, 5, 1 },
						{ 2, 5, 3 },
						{ 2, 5, 4 },
						{ 2, 6, 0 },
						{ 2, 6, 1 },
						{ 2, 6, 3 },
						{ 2, 6, 4 },
						{ 2, 6, 5 },
						{ 3, 5, 4 },
						{ 3, 6, 0 },
						{ 3, 6, 1 },
						{ 3, 6, 4 },
						{ 3, 6, 5 },
						{ 4, 6, 5 },
	};

	starxy = field1();
    quadlist = bl_new(16, 3*sizeof(uint));
    solver = solver_new();
    memset(&index, 0, sizeof(index_t));
    index.index_scale_lower = 1;
    index.index_scale_upper = 10;
	index.dimquads = 3;

    solver->funits_lower = 0.1;
    solver->funits_upper = 10;

    solver_add_index(solver, &index);
    solver_set_field(solver, starxy);
    solver_preprocess_field(solver);

    solver_run(solver);

    solver_free_field(solver);
    solver_free(solver);

    //
    assert(bl_size(quadlist) == (sizeof(wanted) / (3*sizeof(uint))));
	bl_sort(quadlist, compare_tri);
    for (i=0; i<bl_size(quadlist); i++) {
        assert(compare_tri(bl_access(quadlist, i), wanted[i]) == 0);
    }
    bl_free(quadlist);
}
Exemplo n.º 24
0
static void plot_targets(cairo_t* cairo, plot_args_t* pargs, plotann_t* ann) {
	int i;
	double cra, cdec;
	plotstuff_get_radec_center_and_radius(pargs, &cra, &cdec, NULL);
	
	for (i=0; i<bl_size(ann->targets); i++) {
		target_t* tar = bl_access(ann->targets, i);
		double px,py;
		double cx,cy;
		double dx,dy, r;
		double ex,ey;
		double ly, ry, tx, bx;
		double distdeg;
		anbool okquadrant;
		char* txt;

		logverb("Target: \"%s\" at (%g,%g)\n", tar->name, tar->ra, tar->dec);
		okquadrant = plotstuff_radec2xy(pargs, tar->ra, tar->dec, &px, &py);
        px -= 1;
        py -= 1;

		if (okquadrant &&
			px >= 0 && px < pargs->W && py >= 0 && py < pargs->H) {
			// inside the image!
			logverb("Target \"%s\" is inside the image, at pixel (%g,%g)\n", tar->name, px, py);
			plotstuff_stack_marker(pargs, px, py);
			plotstuff_stack_text(pargs, cairo, tar->name, px, py);
			continue;
		}

		// outside the image: find intersection point.
		cx = pargs->W / 2.0;
		cy = pargs->H / 2.0;
		if (okquadrant) {
			logverb("Target \"%s\" is outside the image, at pixel (%g,%g)\n", tar->name, px, py);
			dx = px - cx;
			dy = py - cy;
		} else {
			double cxyz[3];
			double txyz[3];
			double vec[3];
			int j;
			double ra,dec;
			logverb("Target \"%s\" is way outside the image.\n", tar->name);
			// fallback.
			radecdeg2xyzarr(cra, cdec, cxyz);
			radecdeg2xyzarr(tar->ra, tar->dec, txyz);
			for (j=0; j<3; j++)
				vec[j] = cxyz[j] + 0.1 * txyz[j];
			normalize_3(vec);
			xyzarr2radecdeg(vec, &ra, &dec);
			okquadrant = plotstuff_radec2xy(pargs, ra, dec, &px, &py);
			assert(okquadrant);
			dx = px - cx;
			dy = py - cy;
			if ((dx*dx + dy*dy) < (cx*cx + cy*cy)) {
				double scale = 3.0 * sqrt(cx*cx + cy*cy) / sqrt(dx*dx + dy*dy);
				dx *= scale;
				dy *= scale;
			}
		}

		ly = (-(pargs->W/2.0) / dx) * dy + cy;
		ry = ( (pargs->W/2.0) / dx) * dy + cy;
		bx = (-(pargs->H/2.0) / dy) * dx + cx;
		tx = ( (pargs->H/2.0) / dy) * dx + cx;
		logverb("ly %g, ry %g, bx %g, tx %g\n", ly, ry, bx, tx);
		if (px < cx && ly >= 0 && ly < pargs->H) {
			ex = 0.0;
			ey = ly;
		} else if (px >= cx && ry >= 0 && ry < pargs->H) {
			ex = pargs->W - 1;
			ey = ry;
		} else if (py < cy && bx >= 0 && bx < pargs->W) {
			ex = bx;
			ey = 0;
		} else if (py >= cy && tx >= 0 && tx < pargs->W) {
			ex = tx;
			ey = pargs->H - 1;
		} else {
			logverb("None of the edges are in bounds: px,py=(%g,%g); ly=%g, ry=%g, bx=%g, tx=%g\n", px,py,ly,ry,bx,tx);
			continue;
		}
		dx = ex - cx;
		dy = ey - cy;
		r = sqrt(dx*dx + dy*dy);

		px = (r-100.0) / r * dx + cx;
		py = (r-100.0) / r * dy + cy;

		plotstuff_stack_arrow(pargs, px, py, ex, ey);
		logverb("Arrow from (%g,%g) to (%g,%g)\n", px, py, ex, ey);
		distdeg = deg_between_radecdeg(cra, cdec, tar->ra, tar->dec);
		asprintf_safe(&txt, "%s: %.1f deg", tar->name, distdeg);
		plotstuff_stack_text(pargs, cairo, txt, px, py);
	}
}
Exemplo n.º 25
0
int main(int argc, char** args) {
    int argchar;
	char* infn = NULL;
	char* outfn = NULL;
	unsigned int row;
	int bits;
	FILE* fid = stdin;
	FILE* fout = stdout;
	int loglvl = LOG_MSG;
	char* progname = args[0];
	int bzero = 0;
	int outformat;
	qfits_header* hdr;
	unsigned int plane;
	off_t datastart;
	anbool onepass = FALSE;
	bl* pixcache = NULL;

#if HAVE_NETPBM
	struct pam img;
	tuple * tuplerow;
#else
	void* rowbuf;
#endif
	int W, H, depth, maxval;

    while ((argchar = getopt (argc, args, OPTIONS)) != -1)
        switch (argchar) {
		case '?':
		case 'h':
			printHelp(progname);
			exit(0);
		case 'v':
			loglvl++;
			break;
		case 'q':
			loglvl--;
			break;
		case 'o':
			outfn = optarg;
			break;
		}

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

	if (optind == argc) {
		// ok, stdin to stdout.
	} else if (optind == argc-1) {
		infn = args[optind];
	} else if (optind == argc-2) {
		infn = args[optind];
		outfn = args[optind+1];
	} else {
		printHelp(progname);
		exit(-1);
	}

	if (infn && !streq(infn, "-")) {
		fid = fopen(infn, "rb");
		if (!fid) {
			SYSERROR("Failed to open input file %s", infn);
			exit(-1);
		}
	}
	if (outfn) {
		fout = fopen(outfn, "wb");
		if (!fid) {
			SYSERROR("Failed to open output file %s", outfn);
			exit(-1);
		}
	} else
		outfn = "stdout";

#if HAVE_NETPBM
	pm_init(args[0], 0);
	pnm_readpaminit(fid, &img, 
					// PAM_STRUCT_SIZE isn't defined until Netpbm 10.23 (July 2004)
#if defined(PAM_STRUCT_SIZE)
					PAM_STRUCT_SIZE(tuple_type)
#else
					sizeof(struct pam)
#endif
);
	W = img.width;
	H = img.height;
	depth = img.depth;
	maxval = img.maxval;

	tuplerow = pnm_allocpamrow(&img);
	bits = pm_maxvaltobits(img.maxval); 
	bits = (bits <= 8) ? 8 : 16;

#else // No NETPBM

	if (parse_pnm_header(fid, &W, &H, &depth, &maxval)) {
		ERROR("Failed to parse PNM header from file: %s\n", infn ? infn : "<stdin>");
		exit(-1);
	}
	bits = 8 * maxval_to_bytes(maxval);

	rowbuf = malloc(W * depth * (bits/8));

#endif

	logmsg("Read file %s: %i x %i pixels x %i color(s); maxval %i\n",
		   infn ? infn : "stdin", W, H, depth, maxval);
	if (bits == 8)
		outformat = BPP_8_UNSIGNED;
	else {
		outformat = BPP_16_SIGNED;
		if (maxval >= INT16_MAX)
			bzero = 0x8000;
	}
	logmsg("Using %i-bit output\n", bits);

	hdr = fits_get_header_for_image3(W, H, outformat, depth, NULL);
	if (bzero)
		fits_header_add_int(hdr, "BZERO", bzero, "Number that has been subtracted from pixel values");
	if (qfits_header_dump(hdr, fout)) {
		ERROR("Failed to write FITS header to file %s", outfn);
		exit(-1);
	}
	qfits_header_destroy(hdr);

	datastart = ftello(fid);
	// Figure out if we can seek backward in this input file...
	if ((fid == stdin) ||
		(fseeko(fid, 0, SEEK_SET) ||
		 fseeko(fid, datastart, SEEK_SET)))
		// Nope!
		onepass = TRUE;
	if (onepass && depth > 1) {
		logmsg("Reading in one pass\n");
		pixcache = bl_new(16384, bits/8);
	}

	for (plane=0; plane<depth; plane++) {
		if (plane > 0) {
			if (fseeko(fid, datastart, SEEK_SET)) {
				SYSERROR("Failed to seek back to start of image data");
				exit(-1);
			}
		}
		for (row = 0; row<H; row++) {
			unsigned int column;

#if HAVE_NETPBM
			pnm_readpamrow(&img, tuplerow);
#else
			read_pnm_row(fid, W, depth, maxval, rowbuf);
#endif

			for (column = 0; column<W; column++) {
				int rtn;
				int pixval;

#if HAVE_NETPBM
				pixval = tuplerow[column][plane];
#else
				pixval = (bits == 8 ?
						  ((uint8_t *)rowbuf)[column*depth + plane] :
						  ((uint16_t*)rowbuf)[column*depth + plane]);
#endif
				if (outformat == BPP_8_UNSIGNED)
					rtn = fits_write_data_B(fout, pixval);
				else
					rtn = fits_write_data_I(fout, pixval-bzero, TRUE);
				if (rtn) {
					ERROR("Failed to write FITS pixel");
					exit(-1);
				}
			}
			if (onepass && depth > 1) {
				for (column = 0; column<W; column++) {
					for (plane=1; plane<depth; plane++) {
						int pixval;
#if HAVE_NETPBM
						pixval = tuplerow[column][plane];
#else
						pixval = (bits == 8 ?
								  ((uint8_t *)rowbuf)[column*depth + plane] :
								  ((uint16_t*)rowbuf)[column*depth + plane]);
#endif
						if (outformat == BPP_8_UNSIGNED) {
							uint8_t pix = pixval;
							bl_append(pixcache, &pix);
						} else {
							int16_t pix = pixval - bzero;
							bl_append(pixcache, &pix);
						}
					}
				}
			}
		}
	}
	
#if HAVE_NETPBM
	pnm_freepamrow(tuplerow);
#else
	free(rowbuf);
#endif

	if (pixcache) {
		int i, j;
		int step = (depth - 1);
		logverb("Writing %zu queued pixels\n", bl_size(pixcache));
		for (plane=1; plane<depth; plane++) {
			j = (plane - 1);
			for (i=0; i<(W * H); i++) {
				int rtn;
				if (outformat == BPP_8_UNSIGNED) {
					uint8_t* pix = bl_access(pixcache, j);
					rtn = fits_write_data_B(fout, *pix);
				} else {
					int16_t* pix = bl_access(pixcache, j);
					rtn = fits_write_data_I(fout, *pix, TRUE);
				}
				if (rtn) {
					ERROR("Failed to write FITS pixel");
					exit(-1);
				}
				j += step;
			}
		}
		bl_free(pixcache);
	}

	if (fid != stdin)
		fclose(fid);

	if (fits_pad_file(fout)) {
		ERROR("Failed to pad output file \"%s\"", outfn);
		return -1;
	}

	if (fout != stdout)
		if (fclose(fout)) {
			SYSERROR("Failed to close output file %s", outfn);
			exit(-1);
		}

	return 0;
}
Exemplo n.º 26
0
void bl_get(bl* list, int n, void* dest) {
	char* src = bl_access(list, n);
	memcpy(dest, src, list->datasize);
}
Exemplo n.º 27
0
int plotstuff_plot_stack(plot_args_t* pargs, cairo_t* cairo) {
	int i, j;
	int layer;
	anbool morelayers;

	logverb("Plotting %zu stacked plot commands.\n", bl_size(pargs->cairocmds));
	morelayers = TRUE;
	for (layer=0;; layer++) {
		if (!morelayers)
			break;
		morelayers = FALSE;
		for (i=0; i<bl_size(pargs->cairocmds); i++) {
			cairocmd_t* cmd = bl_access(pargs->cairocmds, i);
			if (cmd->layer > layer)
				morelayers = TRUE;
			if (cmd->layer != layer)
				continue;
			cairo_set_rgba(cairo, cmd->rgba);
			switch (cmd->type) {
			case CIRCLE:
				cairo_move_to(cairo, cmd->x + cmd->radius, cmd->y);
				cairo_arc(cairo, cmd->x, cmd->y, cmd->radius, 0, 2*M_PI);
				break;
			case MARKER:
				{
					double oldmarkersize = pargs->markersize;
					int oldmarker = pargs->marker;
					pargs->markersize = cmd->markersize;
					pargs->marker = cmd->marker;
					plotstuff_marker(pargs, cmd->x, cmd->y);
					pargs->markersize = oldmarkersize;
					pargs->marker = oldmarker;
				}
				break;
			case TEXT:
				cairo_move_to(cairo, cmd->x, cmd->y);
				cairo_show_text(cairo, cmd->text);
				break;
			case LINE:
			case ARROW:
				plotstuff_move_to(pargs, cmd->x, cmd->y);
				plotstuff_line_to(pargs, cmd->x2, cmd->y2);
				{
					double dx = cmd->x - cmd->x2;
					double dy = cmd->y - cmd->y2;
					double angle = atan2(dy, dx);
					double dang = 30. * M_PI/180.0;
					double arrowlen = 20;
					plotstuff_line_to(pargs,
								  cmd->x2 + cos(angle+dang)*arrowlen,
								  cmd->y2 + sin(angle+dang)*arrowlen);
					plotstuff_move_to(pargs, cmd->x2, cmd->y2);
					plotstuff_line_to(pargs,
								  cmd->x2 + cos(angle-dang)*arrowlen,
								  cmd->y2 + sin(angle-dang)*arrowlen);
				}
				break;
			case RECTANGLE:
				ERROR("Unimplemented!");
				return -1;
			case POLYGON:
				if (!cmd->xy)
					break;
				for (j=0; j<dl_size(cmd->xy)/2; j++)
					(j == 0 ? cairo_move_to : cairo_line_to)(cairo, dl_get(cmd->xy, 2*j+0), dl_get(cmd->xy, 2*j+1));
				if (cmd->fill)
					cairo_fill(cairo);
				break;
			}
			cairo_stroke(cairo);
		}
	}
	for (i=0; i<bl_size(pargs->cairocmds); i++) {
		cairocmd_t* cmd = bl_access(pargs->cairocmds, i);
		cairocmd_clear(cmd);
	}
	bl_remove_all(pargs->cairocmds);

	return 0;
}
Exemplo n.º 28
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;
}
Exemplo n.º 29
0
int hpquads(startree_t* starkd,
			codefile_t* codes,
			quadfile_t* quads,
			int Nside,
			double scale_min_arcmin,
			double scale_max_arcmin,
			int dimquads,
			int passes,
			int Nreuses,
			int Nloosen,
			int id,
			anbool scanoccupied,

			void* sort_data,
			int (*sort_func)(const void*, const void*),
			int sort_size,
			
			char** args, int argc) {
	hpquads_t myhpquads;
	hpquads_t* me = &myhpquads;

	int i;
	int pass;
	anbool circle = TRUE;
	double radius2;
	il* hptotry;
	int Nhptotry = 0;
	int nquads;
	double hprad;
	double quadscale;

	int skhp, sknside;

	qfits_header* qhdr;
	qfits_header* chdr;

	int N;
	int dimcodes;
	int quadsize;
	int NHP;

	memset(me, 0, sizeof(hpquads_t));

	if (Nside > HP_MAX_INT_NSIDE) {
		ERROR("Error: maximum healpix Nside = %i", HP_MAX_INT_NSIDE);
		return -1;
	}
	if (Nreuses > 255) {
		ERROR("Error, reuse (-r) must be less than 256");
		return -1;
	}

	me->Nside = Nside;
	me->dimquads = dimquads;
	NHP = 12 * Nside * Nside;
	dimcodes = dimquad2dimcode(dimquads);
	quadsize = sizeof(unsigned int) * dimquads;

	logmsg("Nside=%i.  Nside^2=%i.  Number of healpixes=%i.  Healpix side length ~ %g arcmin.\n",
		   me->Nside, me->Nside*me->Nside, NHP, healpix_side_length_arcmin(me->Nside));

	me->sort_data = sort_data;
	me->sort_func = sort_func;
	me->sort_size = sort_size;

	tic();
	me->starkd = starkd;
	N = startree_N(me->starkd);
	logmsg("Star tree contains %i objects.\n", N);

	// get the "HEALPIX" header from the skdt...
	skhp = qfits_header_getint(startree_header(me->starkd), "HEALPIX", -1);
	if (skhp == -1) {
		if (!qfits_header_getboolean(startree_header(me->starkd), "ALLSKY", FALSE)) {
			logmsg("Warning: skdt does not contain \"HEALPIX\" header.  Code and quad files will not contain this header either.\n");
		}
	}
    // likewise "HPNSIDE"
	sknside = qfits_header_getint(startree_header(me->starkd), "HPNSIDE", 1);

    if (sknside && Nside % sknside) {
        logerr("Error: Nside (-n) must be a multiple of the star kdtree healpixelisation: %i\n", sknside);
		return -1;
    }

	if (!scanoccupied && (N*(skhp == -1 ? 1 : sknside*sknside*12) < NHP)) {
		logmsg("\n\n");
		logmsg("NOTE, your star kdtree is sparse (has only a fraction of the stars expected)\n");
		logmsg("  so you probably will get much faster results by setting the \"-E\" command-line\n");
		logmsg("  flag.\n");
		logmsg("\n\n");
	}

	quads->dimquads = me->dimquads;
	codes->dimcodes = dimcodes;
	quads->healpix = skhp;
	codes->healpix = skhp;
	quads->hpnside = sknside;
	codes->hpnside = sknside;
	if (id) {
		quads->indexid = id;
		codes->indexid = id;
	}

	qhdr = quadfile_get_header(quads);
	chdr = codefile_get_header(codes);

	add_headers(qhdr, args, argc, startree_header(me->starkd), circle, passes);
	add_headers(chdr, args, argc, startree_header(me->starkd), circle, passes);

    if (quadfile_write_header(quads)) {
        ERROR("Couldn't write headers to quad file");
		return -1;
    }
    if (codefile_write_header(codes)) {
        ERROR("Couldn't write headers to code file");
		return -1;
    }

    quads->numstars = codes->numstars = N;
	me->quad_dist2_upper = arcmin2distsq(scale_max_arcmin);
	me->quad_dist2_lower = arcmin2distsq(scale_min_arcmin);
    codes->index_scale_upper = quads->index_scale_upper = distsq2rad(me->quad_dist2_upper);
    codes->index_scale_lower = quads->index_scale_lower = distsq2rad(me->quad_dist2_lower);
	
	me->nuses = calloc(N, sizeof(unsigned char));

	// hprad = sqrt(2) * (healpix side length / 2.)
	hprad = arcmin2dist(healpix_side_length_arcmin(Nside)) * M_SQRT1_2;
	quadscale = 0.5 * sqrt(me->quad_dist2_upper);
	// 1.01 for a bit of safety.  we'll look at a few extra stars.
	radius2 = square(1.01 * (hprad + quadscale));
	me->radius2 = radius2;

	logmsg("Healpix radius %g arcsec, quad scale %g arcsec, total %g arcsec\n",
		   distsq2arcsec(hprad*hprad),
		   distsq2arcsec(quadscale*quadscale),
		   distsq2arcsec(radius2));

	hptotry = il_new(1024);

	if (scanoccupied) {
		logmsg("Scanning %i input stars...\n", N);
		for (i=0; i<N; i++) {
			double xyz[3];
			int j;
			if (startree_get(me->starkd, i, xyz)) {
				ERROR("Failed to get star %i", i);
				return -1;
			}
			j = xyzarrtohealpix(xyz, Nside);
			il_insert_unique_ascending(hptotry, j);
			if (log_get_level() > LOG_VERB) {
				double ra,dec;
				if (startree_get_radec(me->starkd, i, &ra, &dec)) {
					ERROR("Failed to get RA,Dec for star %i\n", i);
					return -1;
				}
				logdebug("star %i: RA,Dec %g,%g; xyz %g,%g,%g; hp %i\n",
						 i, ra, dec, xyz[0], xyz[1], xyz[2], j);
			}
		}
		logmsg("Will check %zu healpixes.\n", il_size(hptotry));
		if (log_get_level() > LOG_VERB) {
			logdebug("Checking healpixes: [ ");
			for (i=0; i<il_size(hptotry); i++)
				logdebug("%i ", il_get(hptotry, i));
			logdebug("]\n");
		}

	} else {
		if (skhp == -1) {
			// Try all healpixes.
			il_free(hptotry);
			hptotry = NULL;
			Nhptotry = NHP;
		} else {
			// The star kdtree may itself be healpixed
			int starhp, starx, stary;
			// In that case, the healpixes we are interested in form a rectangle
			// within a big healpix.  These are the coords (in [0, Nside)) of
			// that rectangle.
			int x0, x1, y0, y1;
			int x, y;

			healpix_decompose_xy(skhp, &starhp, &starx, &stary, sknside);
			x0 =  starx    * (Nside / sknside);
			x1 = (starx+1) * (Nside / sknside);
			y0 =  stary    * (Nside / sknside);
			y1 = (stary+1) * (Nside / sknside);

			for (y=y0; y<y1; y++) {
				for (x=x0; x<x1; x++) {
					int j = healpix_compose_xy(starhp, x, y, Nside);
					il_append(hptotry, j);
				}
			}
			assert(il_size(hptotry) == (Nside/sknside) * (Nside/sknside));
		}
	}
	if (hptotry)
		Nhptotry = il_size(hptotry);

	me->quadlist = bl_new(65536, quadsize);

	if (Nloosen)
		me->retryhps = il_new(1024);

	for (pass=0; pass<passes; pass++) {
		char key[64];
		int nthispass;

		logmsg("Pass %i of %i.\n", pass+1, passes);
		logmsg("Trying %i healpixes.\n", Nhptotry);

		nthispass = build_quads(me, Nhptotry, hptotry, Nreuses);

		logmsg("Made %i quads (out of %i healpixes) this pass.\n", nthispass, Nhptotry);
		logmsg("Made %i quads so far.\n", (me->bigquadlist ? bt_size(me->bigquadlist) : 0) + (int)bl_size(me->quadlist));

		sprintf(key, "PASS%i", pass+1);
		fits_header_mod_int(chdr, key, nthispass, "quads created in this pass");
		fits_header_mod_int(qhdr, key, nthispass, "quads created in this pass");

		logmsg("Merging quads...\n");
		if (!me->bigquadlist)
			me->bigquadlist = bt_new(quadsize, 256);
		for (i=0; i<bl_size(me->quadlist); i++) {
			void* q = bl_access(me->quadlist, i);
			bt_insert2(me->bigquadlist, q, FALSE, compare_quads, &me->dimquads);
		}
		bl_remove_all(me->quadlist);
	}

	il_free(hptotry);
	hptotry = NULL;

	if (Nloosen) {
		int R;
		for (R=Nreuses+1; R<=Nloosen; R++) {
			il* trylist;
			int nthispass;

			logmsg("Loosening reuse maximum to %i...\n", R);
			logmsg("Trying %zu healpixes.\n", il_size(me->retryhps));
			if (!il_size(me->retryhps))
				break;

			trylist = me->retryhps;
			me->retryhps = il_new(1024);
			nthispass = build_quads(me, il_size(trylist), trylist, R);
			logmsg("Made %i quads (out of %zu healpixes) this pass.\n", nthispass, il_size(trylist));
			il_free(trylist);
			for (i=0; i<bl_size(me->quadlist); i++) {
				void* q = bl_access(me->quadlist, i);
				bt_insert2(me->bigquadlist, q, FALSE, compare_quads, &me->dimquads);
			}
			bl_remove_all(me->quadlist);
		}
	}
	if (me->retryhps)
		il_free(me->retryhps);

	kdtree_free_query(me->res);
	me->res = NULL;
	me->inds = NULL;
	me->stars = NULL;
	free(me->nuses);
	me->nuses = NULL;

	logmsg("Writing quads...\n");

	// add the quads from the big-quadlist
	nquads = bt_size(me->bigquadlist);
	for (i=0; i<nquads; i++) {
		unsigned int* q = bt_access(me->bigquadlist, i);
		quad_write(codes, quads, q, me->starkd, me->dimquads, dimcodes);
	}
	// add the quads that were made during the final round.
	for (i=0; i<bl_size(me->quadlist); i++) {
		unsigned int* q = bl_access(me->quadlist, i);
		quad_write(codes, quads, q, me->starkd, me->dimquads, dimcodes);
	}

	// fix output file headers.
	if (quadfile_fix_header(quads)) {
		ERROR("Failed to fix quadfile headers");
		return -1;
	}
	if (codefile_fix_header(codes)) {
		ERROR("Failed to fix codefile headers");
		return -1;
	}

	bl_free(me->quadlist);
	bt_free(me->bigquadlist);

	toc();
	logmsg("Done.\n");
	return 0;
}
Exemplo n.º 30
0
void test_hd_1(CuTest* tc) {
    hd_catalog_t* hdcat;
    int* invperm;
    int* present;
    int ind, i, N;
    double xyz[3];
    double ra, dec;
    int strangehds[] = { 40142, 40441, 40672, 40746, 40763, 40764,
                         104176, 104193, 163635, 224698, 224699,
                         129371 };

    if (!file_readable("hd.fits")) {
        printf("File \"hd.fits\" does not exist; test skipped.\n");
        return;
    }

    hdcat = henry_draper_open("hd.fits");
    CuAssertPtrNotNull(tc, hdcat);

    N = hdcat->kd->ndata;
    invperm = calloc(N, sizeof(int));
    CuAssertPtrNotNull(tc, invperm);

    CuAssertIntEquals(tc, 0, kdtree_check(hdcat->kd));

    kdtree_inverse_permutation(hdcat->kd, invperm);

    present = calloc(N, sizeof(int));
    for (i=0; i<N; i++) {
        CuAssert(tc, "invperm in range", invperm[i] < N);
        present[invperm[i]]++;
    }

    for (i=0; i<N; i++) {
        CuAssertIntEquals(tc, 1, present[i]);
    }
    free(present);

    // Where is "HD n" ?
    for (i=0; i<10; i++) {
        bl* res;
        int j;

        ind = invperm[i];
        kdtree_copy_data_double(hdcat->kd, ind, 1, xyz);
        xyzarr2radecdeg(xyz, &ra, &dec);
        printf("HD %i: RA,Dec %g, %g\n", i+1, ra, dec);

        res = henry_draper_get(hdcat, ra, dec, 10.0);
        CuAssertPtrNotNull(tc, res);
        for (j=0; j<bl_size(res); j++) {
            hd_entry_t* hd = bl_access(res, j);
            printf("res %i: HD %i, RA, Dec %g, %g\n", j, hd->hd, hd->ra, hd->dec);
        }
        bl_free(res);
    }

    for (i=0; i<sizeof(strangehds)/sizeof(int); i++) {
        ind = invperm[strangehds[i]-1];
        kdtree_copy_data_double(hdcat->kd, ind, 1, xyz);
        xyzarr2radecdeg(xyz, &ra, &dec);
        printf("HD %i: RA,Dec %g, %g\n", strangehds[i], ra, dec);
    }
    free(invperm);

    henry_draper_close(hdcat);
}