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; }
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 allquads_open_outputs(allquads_t* aq) { int hp, hpnside; qfits_header* hdr; printf("Reading star kdtree %s ...\n", aq->skdtfn); aq->starkd = startree_open(aq->skdtfn); if (!aq->starkd) { ERROR("Failed to open star kdtree %s\n", aq->skdtfn); return -1; } printf("Star tree contains %i objects.\n", startree_N(aq->starkd)); printf("Will write to quad file %s and code file %s\n", aq->quadfn, aq->codefn); aq->quads = quadfile_open_for_writing(aq->quadfn); if (!aq->quads) { ERROR("Couldn't open file %s to write quads.\n", aq->quadfn); return -1; } aq->codes = codefile_open_for_writing(aq->codefn); if (!aq->codes) { ERROR("Couldn't open file %s to write codes.\n", aq->quadfn); return -1; } aq->quads->dimquads = aq->dimquads; aq->codes->dimcodes = aq->dimcodes; if (aq->id) { aq->quads->indexid = aq->id; aq->codes->indexid = aq->id; } // get the "HEALPIX" header from the skdt and put it in the code and quad headers. hp = qfits_header_getint(startree_header(aq->starkd), "HEALPIX", -1); if (hp == -1) { logmsg("Warning: skdt does not contain \"HEALPIX\" header. Code and quad files will not contain this header either.\n"); } aq->quads->healpix = hp; aq->codes->healpix = hp; // likewise "HPNSIDE" hpnside = qfits_header_getint(startree_header(aq->starkd), "HPNSIDE", 1); aq->quads->hpnside = hpnside; aq->codes->hpnside = hpnside; hdr = quadfile_get_header(aq->quads); qfits_header_add(hdr, "CXDX", "T", "All codes have the property cx<=dx.", NULL); qfits_header_add(hdr, "CXDXLT1", "T", "All codes have the property cx+dx<=1.", NULL); qfits_header_add(hdr, "MIDHALF", "T", "All codes have the property cx+dx<=1.", NULL); qfits_header_add(hdr, "CIRCLE", "T", "Codes live in the circle, not the box.", NULL); hdr = codefile_get_header(aq->codes); qfits_header_add(hdr, "CXDX", "T", "All codes have the property cx<=dx.", NULL); qfits_header_add(hdr, "CXDXLT1", "T", "All codes have the property cx+dx<=1.", NULL); qfits_header_add(hdr, "MIDHALF", "T", "All codes have the property cx+dx<=1.", NULL); qfits_header_add(hdr, "CIRCLE", "T", "Codes live in the circle, not the box.", NULL); if (quadfile_write_header(aq->quads)) { ERROR("Couldn't write headers to quads file %s\n", aq->quadfn); return -1; } if (codefile_write_header(aq->codes)) { ERROR("Couldn't write headers to code file %s\n", aq->codefn); return -1; } if (!aq->use_d2_lower) aq->quad_d2_lower = 0.0; if (!aq->use_d2_upper) aq->quad_d2_upper = 10.0; aq->codes->numstars = startree_N(aq->starkd); aq->codes->index_scale_upper = distsq2rad(aq->quad_d2_upper); aq->codes->index_scale_lower = distsq2rad(aq->quad_d2_lower); aq->quads->numstars = aq->codes->numstars; aq->quads->index_scale_upper = aq->codes->index_scale_upper; aq->quads->index_scale_lower = aq->codes->index_scale_lower; return 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; }
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; }