示例#1
0
static void plotquad(cairo_t* cairo, plot_args_t* pargs, plotindex_t* args, index_t* index, int quadnum, int DQ) {
	int k;
	unsigned int stars[DQMAX];
	double ra, dec;
	double px, py;
	double xy[DQMAX*2];
	int N;

	quadfile_get_stars(index->quads, quadnum, stars);
	N = 0;
	for (k=0; k<DQ; k++) {
		if (startree_get_radec(index->starkd, stars[k], &ra, &dec)) {
			ERROR("Failed to get RA,Dec for star %i\n", stars[k]);
			continue;
		}
		if (!plotstuff_radec2xy(pargs, ra, dec, &px, &py)) {
			ERROR("Failed to convert RA,Dec %g,%g to pixels for quad %i\n", ra, dec, quadnum);
			continue;
		}
		xy[2*k + 0] = px;
		xy[2*k + 1] = py;
		N++;
	}
	if (N < 3)
		return;
	plot_quad_xy(cairo, xy, N);
	if (args->fill)
		cairo_fill(cairo);
	else
		cairo_stroke(cairo);
}
示例#2
0
int main(int argc, char *argv[]) {
	int argidx, argchar;
	char *qidxfname = NULL;
	char *quadfname = NULL;
	quadfile* quad;
	qidxfile* qidx;
	int q, s;
	int dimquads;
	
	while ((argchar = getopt (argc, argv, OPTIONS)) != -1)
		switch (argchar) {
		case 'f':
			qidxfname = mk_qidxfn(optarg);
			quadfname = mk_quadfn(optarg);
			break;
		case '?':
			fprintf(stderr, "Unknown option `-%c'.\n", optopt);
		case 'h':
			fprintf(stderr, HelpString);
			return (HELP_ERR);
		default:
			return (OPT_ERR);
		}

	if (optind < argc) {
		for (argidx = optind; argidx < argc; argidx++)
			fprintf (stderr, "Non-option argument %s\n", argv[argidx]);
		fprintf(stderr, HelpString);
		return (OPT_ERR);
	}

	quad = quadfile_open(quadfname, 0);
	if (!quad) {
		fprintf(stderr, "Couldn't open quads file %s.\n", quadfname);
		exit(-1);
	}

	qidx = qidxfile_open(qidxfname, 0);
	if (!qidx) {
		fprintf(stderr, "Couldn't open qidx file %s.\n", qidxfname);
		exit(-1);
	}

	if (quad->numquads != qidx->numquads) {
		fprintf(stderr, "Number of quads does not agree: %i vs %i\n",
				quad->numquads, qidx->numquads);
		exit(-1);
	}

	dimquads = quadfile_dimquads(quad);

	printf("Checking stars...\n");
	for (s=0; s<qidx->numstars; s++) {
		uint32_t* quads;
		int nquads;
		int j;
		qidxfile_get_quads(qidx, s, &quads, &nquads);
		for (j=0; j<nquads; j++) {
			int star[dimquads];
			int k, n;
			quadfile_get_stars(quad, quads[j], star);
			n = 0;
			for (k=0; k<dimquads; k++) {
				if (star[k] == s)
					n++;
			}
			if (n != 1) {
				fprintf(stderr, "Star %i, quad %i: found %i instances of the quad in the qidx (not 1)\n",
						s, quads[j], n);
				fprintf(stderr, "  found: ");
				for (k=0; k<dimquads; k++) {
					fprintf(stderr, "%i ", star[k]);
				}
				fprintf(stderr, "\n");
			}
		}
	}

	printf("Checking quads...\n");
	for (q=0; q<quad->numquads; q++) {
		int star[dimquads];
		uint32_t* quads;
		int nquads;
		int j;
		quadfile_get_stars(quad, q, star);
		for (j=0; j<dimquads; j++) {
			int k;
			int n;
			qidxfile_get_quads(qidx, star[j], &quads, &nquads);
			n = 0;
			for (k=0; k<nquads; k++) {
				if (quads[k] == q)
					n++;
			}
			if (n != 1) {
				fprintf(stderr, "Quad %i, star %i: found %i instances of the quad in the qidx (not 1)\n",
						q, star[j], n);
				fprintf(stderr, "  found: ");
				for (k=0; k<nquads; k++) {
					fprintf(stderr, "%i ", quads[k]);
				}
				fprintf(stderr, "\n");
			}
		}
	}

	quadfile_close(quad);
	qidxfile_close(qidx);

	return 0;
}
示例#3
0
int unpermute_stars(startree_t* treein, quadfile_t* qfin,
					startree_t** p_treeout, quadfile_t* qfout,
					anbool dosweeps, anbool check,
					char** args, int argc) {
	startree_t* treeout;
	int i;
	int N;
	int healpix = -1;
    int hpnside = 0;
	int starhp = -1;
	int lastgrass;
	qfits_header* qouthdr;
	qfits_header* qinhdr;
	anbool allsky;

	assert(p_treeout);
	N = startree_N(treein);
	allsky = qfits_header_getboolean(startree_header(treein), "ALLSKY", 0);
	if (allsky)
		logverb("Star kd-tree is all-sky\n");
	else {
		starhp = qfits_header_getint(startree_header(treein), "HEALPIX", -1);
		if (starhp == -1)
			ERROR("Warning, input star kdtree didn't have a HEALPIX header.\n");
		hpnside = qfits_header_getint(startree_header(treein), "HPNSIDE", 1);
		healpix = starhp;
		logverb("Star kd-tree covers healpix %i, nside %i\n", healpix, hpnside);
	}

	qfout->healpix = healpix;
    qfout->hpnside = hpnside;
	qfout->numstars          = qfin->numstars;
	qfout->dimquads          = qfin->dimquads;
	qfout->index_scale_upper = qfin->index_scale_upper;
	qfout->index_scale_lower = qfin->index_scale_lower;
	qfout->indexid           = qfin->indexid;

	qouthdr = quadfile_get_header(qfout);
	qinhdr  = quadfile_get_header(qfin);

	an_fits_copy_header(qinhdr, qouthdr, "ALLSKY");

	BOILERPLATE_ADD_FITS_HEADERS(qouthdr);
	qfits_header_add(qouthdr, "HISTORY", "This file was created by the program \"unpermute-stars\".", NULL, NULL);
	qfits_header_add(qouthdr, "HISTORY", "unpermute-stars command line:", NULL, NULL);
	fits_add_args(qouthdr, args, argc);
	qfits_header_add(qouthdr, "HISTORY", "(end of unpermute-stars command line)", NULL, NULL);
	qfits_header_add(qouthdr, "HISTORY", "** unpermute-stars: history from input:", NULL, NULL);
	fits_copy_all_headers(qinhdr, qouthdr, "HISTORY");
	qfits_header_add(qouthdr, "HISTORY", "** unpermute-stars: end of history from input.", NULL, NULL);
	qfits_header_add(qouthdr, "COMMENT", "** unpermute-stars: comments from input:", NULL, NULL);
	fits_copy_all_headers(qinhdr, qouthdr, "COMMENT");
	qfits_header_add(qouthdr, "COMMENT", "** unpermute-stars: end of comments from input.", NULL, NULL);

	if (quadfile_write_header(qfout)) {
		ERROR("Failed to write quadfile header.\n");
		return -1;
	}

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

	startree_compute_inverse_perm(treein);

	if (check) {
		logmsg("Running quadfile_check()...\n");
		if (quadfile_check(qfin)) {
			ERROR("quadfile_check() failed");
			return -1;
		}
		logmsg("Check passed.\n");

		logmsg("Checking inverse permutation...\n");
		if (startree_check_inverse_perm(treein)) {
			ERROR("check failed!");
			return -1;
		}

		logmsg("Running startree kdtree_check()...\n");
		if (kdtree_check(treein->tree)) {
			ERROR("kdtree_check() failed");
			return -1;
		}
		logmsg("Check passed.\n");
	}


	lastgrass = 0;
	for (i=0; i<qfin->numquads; i++) {
		int j;
		unsigned int stars[qfin->dimquads];
		if (i*80/qfin->numquads != lastgrass) {
			logmsg(".");
			fflush(stdout);
			lastgrass = i*80/qfin->numquads;
		}
		if (quadfile_get_stars(qfin, i, stars)) {
			ERROR("Failed to read quadfile entry.\n");
			return -1;
        }
		for (j=0; j<qfin->dimquads; j++)
			stars[j] = treein->inverse_perm[stars[j]];
		if (quadfile_write_quad(qfout, stars)) {
			ERROR("Failed to write quadfile entry.\n");
			return -1;
		}
	}
	logmsg("\n");


	if (quadfile_fix_header(qfout)) {
		ERROR("Failed to fix quadfile header");
		return -1;
	}

	treeout = startree_new();
	treeout->tree = malloc(sizeof(kdtree_t));
	memcpy(treeout->tree, treein->tree, sizeof(kdtree_t));
	treeout->tree->perm = NULL;

	an_fits_copy_header(startree_header(treein), startree_header(treeout), "HEALPIX");
	an_fits_copy_header(startree_header(treein), startree_header(treeout), "HPNSIDE");
	an_fits_copy_header(startree_header(treein), startree_header(treeout), "ALLSKY");
	an_fits_copy_header(startree_header(treein), startree_header(treeout), "JITTER");
	an_fits_copy_header(startree_header(treein), startree_header(treeout), "CUTNSIDE");
	an_fits_copy_header(startree_header(treein), startree_header(treeout), "CUTMARG");
	an_fits_copy_header(startree_header(treein), startree_header(treeout), "CUTBAND");
	an_fits_copy_header(startree_header(treein), startree_header(treeout), "CUTDEDUP");
	an_fits_copy_header(startree_header(treein), startree_header(treeout), "CUTNSWEP");
	an_fits_copy_header(startree_header(treein), startree_header(treeout), "CUTMINMG");
	an_fits_copy_header(startree_header(treein), startree_header(treeout), "CUTMAXMG");

	qfits_header_add(startree_header(treeout), "HISTORY", "unpermute-stars command line:", NULL, NULL);
	fits_add_args(startree_header(treeout), args, argc);
	qfits_header_add(startree_header(treeout), "HISTORY", "(end of unpermute-stars command line)", NULL, NULL);
	qfits_header_add(startree_header(treeout), "HISTORY", "** unpermute-stars: history from input:", NULL, NULL);
	fits_copy_all_headers(startree_header(treein), startree_header(treeout), "HISTORY");
	qfits_header_add(startree_header(treeout), "HISTORY", "** unpermute-stars: end of history from input.", NULL, NULL);
	qfits_header_add(startree_header(treeout), "COMMENT", "** unpermute-stars: comments from input:", NULL, NULL);
	fits_copy_all_headers(startree_header(treein), startree_header(treeout), "COMMENT");
	qfits_header_add(startree_header(treeout), "COMMENT", "** unpermute-stars: end of comments from input.", NULL, NULL);

	if (dosweeps) {
		// copy sweepX headers.
		for (i=1;; i++) {
			char key[16];
			int n;
			sprintf(key, "SWEEP%i", i);
			n = qfits_header_getint(treein->header, key, -1);
			if (n == -1)
				break;
			an_fits_copy_header(treein->header, treeout->header, key);
		}

		// compute sweep array.
		treeout->sweep = malloc(N * sizeof(uint8_t));
		for (i=0; i<N; i++) {
			int ind = treein->tree->perm[i];
			// Stars are sorted first by sweep and then by brightness within
			// the sweep.  Instead of just storing the sweep number, we can
			// store a quantization of the total-ordered rank.
			treeout->sweep[i] = (uint8_t)floor((float)256.0 * (float)ind / (float)N);
		}
	}

	*p_treeout = treeout;
	return 0;
}
int main(int argc, char** args) {
    int argchar;
	char* basename;
	char* outfn = NULL;
	index_t* index;
	quadfile* qf;
    rdlist_t* rdls;
	startree_t* skdt = NULL;
    anbool addradius = FALSE;
	int i;
    int radcolumn = -1;

    while ((argchar = getopt (argc, args, OPTIONS)) != -1)
        switch (argchar) {
        case 'R':
            addradius = TRUE;
            break;
		case 'r':
			outfn = optarg;
			break;
		case 'h':
			print_help(args[0]);
			exit(0);
		}

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

    rdls = rdlist_open_for_writing(outfn);
    if (!rdls) {
        fprintf(stderr, "Failed to open RDLS file %s for output.\n", outfn);
        exit(-1);
    }
    if (rdlist_write_primary_header(rdls)) {
        fprintf(stderr, "Failed to write RDLS header.\n");
        exit(-1);
    }

    if (addradius) {
        radcolumn = rdlist_add_tagalong_column(rdls, fitscolumn_double_type(),
                                               1, fitscolumn_double_type(),
                                               "QUADRADIUS", "deg");
    }

	for (; optind<argc; optind++) {
		//int Nstars;
        int dimquads;

		basename = args[optind];
		printf("Reading files with basename %s\n", basename);

		index = index_load(basename, 0, NULL);
		if (!index) {
			fprintf(stderr, "Failed to read index with base name \"%s\"\n", basename);
			exit(-1);
		}

		qf = index->quads;
        skdt = index->starkd;
        //Nstars = startree_N(skdt);
        
        if (rdlist_write_header(rdls)) {
            fprintf(stderr, "Failed to write new RDLS field header.\n");
            exit(-1);
        }

        dimquads = quadfile_dimquads(qf);

		printf("Reading quads...\n");
		for (i=0; i<qf->numquads; i++) {
			unsigned int stars[dimquads];
            double axyz[3], bxyz[3];
            double midab[3];
            double radec[2];
			if (!(i % 200000)) {
				printf(".");
				fflush(stdout);
			}
			quadfile_get_stars(qf, i, stars);
            startree_get(skdt, stars[0], axyz);
            startree_get(skdt, stars[1], bxyz);
            star_midpoint(midab, axyz, bxyz);
            xyzarr2radecdegarr(midab, radec);

            if (rdlist_write_one_radec(rdls, radec[0], radec[1])) {
                fprintf(stderr, "Failed to write a RA,Dec entry.\n");
                exit(-1);
            }

            if (addradius) {
                double rad = arcsec2deg(distsq2arcsec(distsq(midab, axyz, 3)));
                if (rdlist_write_tagalong_column(rdls, radcolumn, i, 1, &rad, 0)) {
                    fprintf(stderr, "Failed to write quad radius.\n");
                    exit(-1);
                }
            }
		}
		printf("\n");

		index_close(index);

        if (rdlist_fix_header(rdls)) {
            fprintf(stderr, "Failed to fix RDLS field header.\n");
            exit(-1);
        }

		rdlist_next_field(rdls);
	}

    if (rdlist_fix_primary_header(rdls) ||
        rdlist_close(rdls)) {
        fprintf(stderr, "Failed to close RDLS file.\n");
        exit(-1);
    }

	return 0;
}
示例#5
0
int unpermute_quads(quadfile* quadin, codetree* treein,
					quadfile* quadout, codetree** p_treeout,
					char** args, int argc) {
	int i;
	qfits_header* codehdr;
	qfits_header* hdr;
	int healpix;
	int hpnside;
	int codehp = -1;
	qfits_header* qouthdr;
	qfits_header* qinhdr;
	codetree* treeout;
	anbool allsky;

	codehdr = codetree_header(treein);
	healpix = quadin->healpix;
	hpnside = quadin->hpnside;

	allsky = qfits_header_getboolean(codehdr, "ALLSKY", 0);
	if (allsky)
		logverb("Index is all-sky\n");
	else {
		codehp = qfits_header_getint(codehdr, "HEALPIX", -1);
		if (codehp == -1)
			ERROR("Warning, input code kdtree didn't have a HEALPIX header");
		else if (codehp != healpix) {
			ERROR("Quadfile says it's healpix %i, but code kdtree says %i",
				  healpix, codehp);
			return -1;
		}
	}

	quadout->healpix = healpix;
	quadout->hpnside = hpnside;
	quadout->indexid = quadin->indexid;
	quadout->numstars = quadin->numstars;
	quadout->dimquads = quadin->dimquads;
	quadout->index_scale_upper = quadin->index_scale_upper;
	quadout->index_scale_lower = quadin->index_scale_lower;

	qouthdr = quadfile_get_header(quadout);
	qinhdr  = quadfile_get_header(quadin);

	boilerplate_add_fits_headers(qouthdr);
	qfits_header_add(qouthdr, "HISTORY", "This file was created by the program \"unpermute-quads\".", NULL, NULL);
	qfits_header_add(qouthdr, "HISTORY", "unpermute-quads command line:", NULL, NULL);
	fits_add_args(qouthdr, args, argc);
	qfits_header_add(qouthdr, "HISTORY", "(end of unpermute-quads command line)", NULL, NULL);
	qfits_header_add(qouthdr, "HISTORY", "** unpermute-quads: history from input:", NULL, NULL);
	fits_copy_all_headers(qinhdr, qouthdr, "HISTORY");
	qfits_header_add(qouthdr, "HISTORY", "** unpermute-quads end of history from input.", NULL, NULL);
	qfits_header_add(qouthdr, "COMMENT", "** unpermute-quads: comments from input:", NULL, NULL);
	fits_copy_all_headers(qinhdr, qouthdr, "COMMENT");
	qfits_header_add(qouthdr, "COMMENT", "** unpermute-quads: end of comments from input.", NULL, NULL);
	fits_copy_header(qinhdr, qouthdr, "CXDX");
	fits_copy_header(qinhdr, qouthdr, "CXDXLT1");
	fits_copy_header(qinhdr, qouthdr, "CIRCLE");
	fits_copy_header(qinhdr, qouthdr, "ALLSKY");

	if (quadfile_write_header(quadout)) {
		ERROR("Failed to write quadfile header");
		return -1;
	}

	for (i=0; i<codetree_N(treein); i++) {
		unsigned int stars[quadin->dimquads];
		int ind = codetree_get_permuted(treein, i);
		if (quadfile_get_stars(quadin, ind, stars)) {
			ERROR("Failed to read quad entry");
			return -1;
        }
		if (quadfile_write_quad(quadout, stars)) {
			ERROR("Failed to write quad entry");
			return -1;
		}
	}

	if (quadfile_fix_header(quadout)) {
		ERROR("Failed to fix quadfile header");
		return -1;
	}

	treeout = codetree_new();
	treeout->tree = malloc(sizeof(kdtree_t));
	memcpy(treeout->tree, treein->tree, sizeof(kdtree_t));
	treeout->tree->perm = NULL;

	hdr = codetree_header(treeout);
	fits_copy_header(qinhdr, hdr, "HEALPIX");
	fits_copy_header(qinhdr, hdr, "HPNSIDE");
	fits_copy_header(qinhdr, hdr, "ALLSKY");
	boilerplate_add_fits_headers(hdr);
	qfits_header_add(hdr, "HISTORY", "This file was created by the program \"unpermute-quads\".", NULL, NULL);
	qfits_header_add(hdr, "HISTORY", "unpermute-quads command line:", NULL, NULL);
	fits_add_args(hdr, args, argc);
	qfits_header_add(hdr, "HISTORY", "(end of unpermute-quads command line)", NULL, NULL);
	qfits_header_add(hdr, "HISTORY", "** unpermute-quads: history from input ckdt:", NULL, NULL);
	fits_copy_all_headers(codehdr, hdr, "HISTORY");
	qfits_header_add(hdr, "HISTORY", "** unpermute-quads end of history from input ckdt.", NULL, NULL);
	qfits_header_add(hdr, "COMMENT", "** unpermute-quads: comments from input ckdt:", NULL, NULL);
	fits_copy_all_headers(codehdr, hdr, "COMMENT");
	qfits_header_add(hdr, "COMMENT", "** unpermute-quads: end of comments from input ckdt.", NULL, NULL);
	fits_copy_header(codehdr, hdr, "CXDX");
	fits_copy_header(codehdr, hdr, "CXDXLT1");
	fits_copy_header(codehdr, hdr, "CIRCLE");

	*p_treeout = treeout;
	return 0;
}
示例#6
0
int main(int argc, char *argv[]) {
    int argchar;
	char* progname = argv[0];
    index_t* index;
    fitstable_t* table;
	char* indexfn = NULL;
	char* outfn = NULL;
	int i, D, N;

    while ((argchar = getopt (argc, argv, OPTIONS)) != -1) {
		switch (argchar) {
		case 'i':
			indexfn = optarg;
			break;
		case 'o':
			outfn = optarg;
			break;
		default:
		case 'h':
			printHelp(progname);
			exit(0);
		}
	}

	if (!(indexfn && outfn)) {
		printHelp(progname);
		exit(-1);
	}

    index = index_load(indexfn, 0, NULL);
    if (!index) {
        ERROR("Failed to open index");
        exit(-1);
    }

    table = fitstable_open_for_writing(outfn);
    if (!table) {
        ERROR("Failed to open output file for writing");
        exit(-1);
    }
    D = index_get_quad_dim(index);
    fitstable_add_write_column_array(table, fitscolumn_i32_type(), D,
                                     "quads", "");
    if (fitstable_write_primary_header(table) ||
        fitstable_write_header(table)) {
        ERROR("Failed to write headers");
        exit(-1);
    }

    N = index_nquads(index);
    for (i=0; i<N; i++) {
        unsigned int quad[D];
        quadfile_get_stars(index->quads, i, quad);
        if (fitstable_write_row(table, quad)) {
            ERROR("Failed to write quad %i", i);
            exit(-1);
        }
    }

    if (fitstable_fix_header(table)) {
        ERROR("Failed to fix quad header");
        exit(-1);
    }

    fitstable_next_extension(table);
    fitstable_clear_table(table);

    // write star RA,Dec s.
    fitstable_add_write_column(table, fitscolumn_double_type(), "RA", "deg");
    fitstable_add_write_column(table, fitscolumn_double_type(), "Dec", "deg");

    if (fitstable_write_header(table)) {
        ERROR("Failed to write star header");
        exit(-1);
    }

    N = index_nstars(index);
    for (i=0; i<N; i++) {
        double xyz[3];
        double ra, dec;
        startree_get(index->starkd, i, xyz);
        xyzarr2radecdeg(xyz, &ra, &dec);
        if (fitstable_write_row(table, &ra, &dec)) {
            ERROR("Failed to write star %i", i);
            exit(-1);
        }
    }

    if (fitstable_fix_header(table) ||
        fitstable_close(table)) {
        ERROR("Failed to fix star header and close");
        exit(-1);
    }
    

    index_close(index);

	return 0;
}
示例#7
0
int main(int argc, char *argv[]) {
	char* progname = argv[0];
	int argidx, argchar;
	char *idxfname = NULL;
	char *quadfname = NULL;
	il** quadlist;
	quadfile* quads;
	qidxfile* qidx;
	int q;
	int i;
	int numused;
	qfits_header* quadhdr;
	qfits_header* qidxhdr;
	int dimquads;
	anbool check = FALSE;
	int loglvl = LOG_MSG;
	
	if (argc <= 2) {
		printHelp(progname);
		exit(-1);
	}

	while ((argchar = getopt (argc, argv, OPTIONS)) != -1)
		switch (argchar) {
		case 'c':
			check = TRUE;
			break;
		case 'v':
			loglvl++;
			break;
        case 'i':
            quadfname = optarg;
            break;
        case 'o':
            idxfname = optarg;
            break;
		case '?':
			fprintf(stderr, "Unknown option `-%c'.\n", optopt);
		case 'h':
			printHelp(progname);
			exit(-1);
		default:
			return (OPT_ERR);
		}

	log_init(loglvl);

	if (optind < argc) {
		for (argidx = optind; argidx < argc; argidx++)
			fprintf (stderr, "Non-option argument %s\n", argv[argidx]);
		printHelp(progname);
		exit(-1);
	}

	logmsg("quadidx: indexing quads in \"%s\"...\n", quadfname);
	logmsg("will write to file \"%s\".\n", idxfname);

	quads = quadfile_open(quadfname);
	if (!quads) {
		ERROR("Couldn't open quads file \"%s\"", quadfname);
		exit(-1);
	}
	logmsg("%u quads, %u stars.\n", quads->numquads, quads->numstars);

	if (check) {
		logmsg("Running quadfile_check()...\n");
		if (quadfile_check(quads)) {
			ERROR("quadfile_check() failed");
			exit(-1);
		}
		logmsg("Check passed.\n");
	}

	quadlist = calloc(quads->numstars, sizeof(il*));
	if (!quadlist) {
		SYSERROR("Failed to allocate list of quad contents");
		exit(-1);
	}

	dimquads = quadfile_dimquads(quads);
	for (q=0; q<quads->numquads; q++) {
		unsigned int inds[dimquads];
		quadfile_get_stars(quads, q, inds);

		// append this quad index to the lists of each of its stars.
		for (i=0; i<dimquads; i++) {
			il* list;
			int starind = inds[i];
			list = quadlist[starind];
			// create the list if necessary
			if (!list) {
				list = il_new(10);
				quadlist[starind] = list;
			}
			il_append(list, q);
		}
	}
	
	// first count numused:
	// how many stars are members of quads.
	numused = 0;
	for (i=0; i<quads->numstars; i++) {
		il* list = quadlist[i];
		if (!list) continue;
		numused++;
	}
	logmsg("%u stars used\n", numused);

	qidx = qidxfile_open_for_writing(idxfname, quads->numstars, quads->numquads);
	if (!qidx) {
 		logmsg("Couldn't open outfile qidx file %s.\n", idxfname);
		exit(-1);
	}

	quadhdr = quadfile_get_header(quads);
	qidxhdr = qidxfile_get_header(qidx);

	an_fits_copy_header(quadhdr, qidxhdr, "INDEXID");
	an_fits_copy_header(quadhdr, qidxhdr, "HEALPIX");

	BOILERPLATE_ADD_FITS_HEADERS(qidxhdr);
	qfits_header_add(qidxhdr, "HISTORY", "This file was created by the program \"quadidx\".", NULL, NULL);
	qfits_header_add(qidxhdr, "HISTORY", "quadidx command line:", NULL, NULL);
	fits_add_args(qidxhdr, argv, argc);
	qfits_header_add(qidxhdr, "HISTORY", "(end of quadidx command line)", NULL, NULL);

	qfits_header_add(qidxhdr, "HISTORY", "** History entries copied from the input file:", NULL, NULL);
	fits_copy_all_headers(quadhdr, qidxhdr, "HISTORY");
	qfits_header_add(qidxhdr, "HISTORY", "** End of history entries.", NULL, NULL);

	if (qidxfile_write_header(qidx)) {
 		logmsg("Couldn't write qidx header (%s).\n", idxfname);
		exit(-1);
	}

	for (i=0; i<quads->numstars; i++) {
		int thisnumq;
		//int thisstar;
		int* stars; // bad variable name - list of quads this star is in.
		il* list = quadlist[i];
		if (list) {
			thisnumq = (uint)il_size(list);
			stars = malloc(thisnumq * sizeof(uint));
			il_copy(list, 0, thisnumq, (int*)stars);
		} else {
			thisnumq = 0;
			stars = NULL;
		}
		//thisstar = i;

		if (qidxfile_write_star(qidx,  stars, thisnumq)) {
			logmsg("Couldn't write star to qidx file (%s).\n", idxfname);
			exit(-1);
		}

		if (list) {
			free(stars);
			il_free(list);
			quadlist[i] = NULL;
		}
	}
	free(quadlist);
	quadfile_close(quads);

	if (qidxfile_close(qidx)) {
		logmsg("Failed to close qidx file.\n");
		exit(-1);
	}

	logmsg("  done.\n");
	return 0;
}