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); }
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 main(int argc, char** argv) { int argchar; allquads_t* aq; int loglvl = LOG_MSG; int i, N; char* catfn = NULL; startree_t* starkd; fitstable_t* cat; char* racol = NULL; char* deccol = NULL; int datatype = KDT_DATA_DOUBLE; int treetype = KDT_TREE_DOUBLE; int buildopts = 0; int Nleaf = 0; char* indexfn = NULL; //index_params_t* p; aq = allquads_init(); aq->skdtfn = "allquads.skdt"; aq->codefn = "allquads.code"; aq->quadfn = "allquads.quad"; while ((argchar = getopt (argc, argv, OPTIONS)) != -1) switch (argchar) { case 'v': loglvl++; break; case 'd': aq->dimquads = atoi(optarg); break; case 'I': aq->id = atoi(optarg); break; case 'h': print_help(argv[0]); exit(0); case 'i': catfn = optarg; break; case 'o': indexfn = optarg; break; case 'u': aq->quad_d2_upper = arcmin2distsq(atof(optarg)); aq->use_d2_upper = TRUE; break; case 'l': aq->quad_d2_lower = arcmin2distsq(atof(optarg)); aq->use_d2_lower = TRUE; break; default: return -1; } log_init(loglvl); if (!catfn || !indexfn) { printf("Specify in & out filenames, bonehead!\n"); print_help(argv[0]); exit( -1); } if (optind != argc) { print_help(argv[0]); printf("\nExtra command-line args were given: "); for (i=optind; i<argc; i++) { printf("%s ", argv[i]); } printf("\n"); exit(-1); } if (!aq->id) logmsg("Warning: you should set the unique-id for this index (with -I).\n"); if (aq->dimquads > DQMAX) { ERROR("Quad dimension %i exceeds compiled-in max %i.\n", aq->dimquads, DQMAX); exit(-1); } aq->dimcodes = dimquad2dimcode(aq->dimquads); // Read reference catalog, write star kd-tree logmsg("Building star kdtree: reading %s, writing to %s\n", catfn, aq->skdtfn); logverb("Reading star catalogue..."); cat = fitstable_open(catfn); if (!cat) { ERROR("Couldn't read catalog"); exit(-1); } logmsg("Got %i stars\n", fitstable_nrows(cat)); starkd = startree_build(cat, racol, deccol, datatype, treetype, buildopts, Nleaf, argv, argc); if (!starkd) { ERROR("Failed to create star kdtree"); exit(-1); } logmsg("Star kd-tree contains %i data points in dimension %i\n", startree_N(starkd), startree_D(starkd)); N = startree_N(starkd); for (i=0; i<N; i++) { double ra,dec; int ok; ok = startree_get_radec(starkd, i, &ra, &dec); logmsg(" data %i: ok %i, RA,Dec %g, %g\n", i, ok, ra, dec); } if (startree_write_to_file(starkd, aq->skdtfn)) { ERROR("Failed to write star kdtree"); exit(-1); } startree_close(starkd); fitstable_close(cat); logmsg("Wrote star kdtree to %s\n", aq->skdtfn); logmsg("Running allquads...\n"); if (allquads_open_outputs(aq)) { exit(-1); } if (allquads_create_quads(aq)) { exit(-1); } if (allquads_close(aq)) { exit(-1); } logmsg("allquads: wrote %s, %s\n", aq->quadfn, aq->codefn); // build-index: //build_index_defaults(&p); // codetree /* if (step_codetree(p, codes, &codekd, codefn, &ckdtfn, tempfiles)) return -1; */ char* ckdtfn=NULL; char* tempdir = NULL; ckdtfn = create_temp_file("ckdt", tempdir); logmsg("Creating code kdtree, reading %s, writing to %s\n", aq->codefn, ckdtfn); if (codetree_files(aq->codefn, ckdtfn, 0, 0, 0, 0, argv, argc)) { ERROR("codetree failed"); return -1; } char* skdt2fn=NULL; char* quad2fn=NULL; // unpermute-stars logmsg("Unpermute-stars...\n"); skdt2fn = create_temp_file("skdt2", tempdir); quad2fn = create_temp_file("quad2", tempdir); logmsg("Unpermuting stars from %s and %s to %s and %s\n", aq->skdtfn, aq->quadfn, skdt2fn, quad2fn); if (unpermute_stars_files(aq->skdtfn, aq->quadfn, skdt2fn, quad2fn, TRUE, FALSE, argv, argc)) { ERROR("Failed to unpermute-stars"); return -1; } allquads_free(aq); // unpermute-quads /* if (step_unpermute_quads(p, quads2, codekd, &quads3, &codekd2, quad2fn, ckdtfn, &quad3fn, &ckdt2fn, tempfiles)) return -1; */ char* quad3fn=NULL; char* ckdt2fn=NULL; ckdt2fn = create_temp_file("ckdt2", tempdir); quad3fn = create_temp_file("quad3", tempdir); logmsg("Unpermuting quads from %s and %s to %s and %s\n", quad2fn, ckdtfn, quad3fn, ckdt2fn); if (unpermute_quads_files(quad2fn, ckdtfn, quad3fn, ckdt2fn, argv, argc)) { ERROR("Failed to unpermute-quads"); return -1; } // index /* if (step_merge_index(p, codekd2, quads3, starkd2, p_index, ckdt2fn, quad3fn, skdt2fn, indexfn)) return -1; */ quadfile_t* quad; codetree_t* code; startree_t* star; logmsg("Merging %s and %s and %s to %s\n", quad3fn, ckdt2fn, skdt2fn, indexfn); if (merge_index_open_files(quad3fn, ckdt2fn, skdt2fn, &quad, &code, &star)) { ERROR("Failed to open index files for merging"); return -1; } if (merge_index(quad, code, star, indexfn)) { ERROR("Failed to write merged index"); return -1; } codetree_close(code); startree_close(star); quadfile_close(quad); printf("Done.\n"); free(ckdtfn); free(skdt2fn); free(quad2fn); free(ckdt2fn); free(quad3fn); return 0; }