int main(int argc, char** args) { int c; int Nside = 1; int HP, hp; int i; double* radecs; double markersize = 20.0; double fontsize = 10.0; anbool do_neighbours = FALSE; int mode = MODE_XY; while ((c = getopt(argc, args, OPTIONS)) != -1) { switch (c) { case '?': case 'h': print_help(args[0]); exit(0); case 'N': Nside = atoi(optarg); break; case 'n': do_neighbours = TRUE; break; case 'M': markersize = atof(optarg); break; case 'F': fontsize = atof(optarg); break; case 'r': mode = MODE_RING; break; case 'R': mode = MODE_RING_D; break; case 'e': mode = MODE_NESTED; break; } } HP = 12 * Nside * Nside; printf("Nside=%i;\n", Nside); radecs = malloc(HP * 2 * sizeof(double)); for (hp=0; hp<HP; hp++) { double xyz[3]; double ra, dec; healpix_to_xyzarr(hp, Nside, 0.5, 0.5, xyz); xyzarr2radec(xyz, &ra, &dec); radecs[2*hp] = ra; radecs[2*hp+1] = dec; } printf("figure(1);\n"); printf("clf;\n"); printf("xmargin=0.5; ymargin=0.1;\n"); printf("axis([0-xmargin, 2*pi+xmargin, -pi/2-ymargin, pi/2+ymargin]);\n"); printf("texts=[];\n"); printf("lines=[];\n"); // draw the large-healpix boundaries. for (hp=0; hp<12; hp++) { double xyz[3]; double crd[6*2]; double xy[] = { 0.0,0.001, 0.0,1.0, 0.999,1.0, 1.0,0.999, 1.0,0.0, 0.001,0.0 }; for (i=0; i<6; i++) { healpix_to_xyzarr(hp, 1, xy[i*2], xy[i*2+1], xyz); xyzarr2radec(xyz, crd+i*2+0, crd+i*2+1); } printf("xy=["); for (i=0; i<7; i++) printf("%g,%g;", crd[(i%6)*2+0], crd[(i%6)*2+1]); printf("];\n"); printf("[la, lb] = wrapline(xy(:,1),xy(:,2));\n"); printf("set(la, 'Color', 'b');\n"); printf("set(lb, 'Color', 'b');\n"); } if (do_neighbours) { for (hp=0; hp<HP; hp++) { uint neigh[8]; uint nn; nn = healpix_get_neighbours(hp, neigh, Nside); for (i=0; i<nn; i++) { printf("[la,lb]=wrapline([%g,%g],[%g,%g]);\n", radecs[2*hp], radecs[2*neigh[i]], radecs[2*hp+1], radecs[2*neigh[i]+1]); printf("set([la,lb], " "'Color', [0.5,0.5,0.5], " "'Marker', 'o', " "'MarkerEdgeColor', 'k', " //"'MarkerFaceColor', 'none', " "'MarkerFaceColor', 'white', " "'MarkerSize', %g);\n", markersize); printf("set(lb, 'LineStyle', '--');\n"); } } } for (hp=0; hp<HP; hp++) { printf("texts(%i)=text(%g, %g, '", hp+1, radecs[2*hp], radecs[2*hp+1]); switch (mode) { case MODE_XY: printf("%i", hp); break; case MODE_XY_D: { uint bighp, x, y; healpix_decompose_xy(hp, &bighp, &x, &y, Nside); printf("%i,%i,%i", bighp, x, y); } break; case MODE_RING: printf("%i", healpix_xy_to_ring(hp, Nside)); break; case MODE_RING_D: { uint ring; uint ringnum, longind; ring = healpix_xy_to_ring(hp, Nside); healpix_decompose_ring(ring, Nside, &ringnum, &longind); printf("%i,%i", ringnum, longind); } break; case MODE_NESTED: printf("%i", healpix_xy_to_nested(hp, Nside)); break; } printf("', 'HorizontalAlignment', 'center', 'FontSize', %g);\n", fontsize); } // Verify decompose / compose RING. for (hp=0; hp<HP; hp++) { uint ring, longind; int hp2; healpix_decompose_ring(hp, Nside, &ring, &longind); hp2 = healpix_compose_ring(ring, longind, Nside); if (hp2 != hp) { fprintf(stderr, "Error: %i -> ring %i, longind %i -> %i.\n", hp, ring, longind, hp2); } } // Verify XY -> RING -> XY for (hp=0; hp<HP; hp++) { int ring, hp2; ring = healpix_xy_to_ring(hp, Nside); hp2 = healpix_ring_to_xy(ring, Nside); if (hp2 != hp) { uint bighp, x, y; uint bighp2, x2, y2; uint ringind, longind; healpix_decompose_xy(hp, &bighp, &x, &y, Nside); healpix_decompose_xy(hp2, &bighp2, &x2, &y2, Nside); healpix_decompose_ring(ring, Nside, &ringind, &longind); fprintf(stderr, "Error: hp %i (bighp %i, x %i, y %i) -> ring %i (ring %i, long %i) -> hp %i (bighp %i, x %i, y %i).\n", hp, bighp, x, y, ring, ringind, longind, hp2, bighp2, x2, y2); } } free(radecs); return 0; }
static anbool find_stars(hpquads_t* me, double radius2, int R) { int d, j, N; int destind; double centre[3]; int* perm; healpix_to_xyzarr(me->hp, me->Nside, 0.5, 0.5, centre); me->res = kdtree_rangesearch_options_reuse(me->starkd->tree, me->res, centre, radius2, KD_OPTIONS_RETURN_POINTS); // here we could check whether stars are in the box defined by the // healpix boundaries plus quad scale, rather than just the circle // containing that box. N = me->res->nres; me->Nstars = N; if (N < me->dimquads) return FALSE; // FIXME -- could merge this step with the sorting step... // remove stars that have been used up. if (R) { destind = 0; for (j=0; j<N; j++) { if (me->nuses[me->res->inds[j]] >= R) continue; me->res->inds[destind] = me->res->inds[j]; for (d=0; d<3; d++) me->res->results.d[destind*3+d] = me->res->results.d[j*3+d]; destind++; } N = destind; if (N < me->dimquads) return FALSE; } // sort the stars in increasing order of index - assume // that this corresponds to decreasing order of brightness. // UNLESS another sorting is provided! if (me->sort_data && me->sort_func && me->sort_size) { /* Two levels of indirection here! me->res->inds are indices into the "sort_data" array (since kdtree is assumed to be un-permuted) We want to produce "perm", which permutes me->res->inds to make sort_data sorted; need to do this because we also want to permute results.d. Alternatively, we could re-fetch the results.d ... */ int k; char* tempdata = malloc(me->sort_size * N); for (k=0; k<N; k++) memcpy(tempdata + k*me->sort_size, ((char*)me->sort_data) + me->sort_size * me->res->inds[k], me->sort_size); perm = permuted_sort(tempdata, me->sort_size, me->sort_func, NULL, N); free(tempdata); } else { // find permutation that sorts by index... perm = permuted_sort(me->res->inds, sizeof(int), compare_ints_asc, NULL, N); } // apply the permutation... permutation_apply(perm, N, me->res->inds, me->res->inds, sizeof(int)); permutation_apply(perm, N, me->res->results.d, me->res->results.d, 3 * sizeof(double)); free(perm); me->inds = (int*)me->res->inds; me->stars = me->res->results.d; me->Nstars = N; return TRUE; }
int main(int argc, char *argv[]) { int argchar; char* progname = argv[0]; sl* infns = sl_new(16); char* outfnpat = NULL; char* racol = "RA"; char* deccol = "DEC"; char* tempdir = "/tmp"; anbool gzip = FALSE; sl* cols = sl_new(16); int loglvl = LOG_MSG; int nside = 1; double margin = 0.0; int NHP; double md; char* backref = NULL; fitstable_t* intable; fitstable_t** outtables; char** myargs; int nmyargs; int i; while ((argchar = getopt (argc, argv, OPTIONS)) != -1) switch (argchar) { case 'b': backref = optarg; break; case 't': tempdir = optarg; break; case 'c': sl_append(cols, optarg); break; case 'g': gzip = TRUE; break; case 'o': outfnpat = optarg; break; case 'r': racol = optarg; break; case 'd': deccol = optarg; break; case 'n': nside = atoi(optarg); break; case 'm': margin = atof(optarg); break; case 'v': loglvl++; break; case '?': fprintf(stderr, "Unknown option `-%c'.\n", optopt); case 'h': printHelp(progname); return 0; default: return -1; } if (sl_size(cols) == 0) { sl_free2(cols); cols = NULL; } nmyargs = argc - optind; myargs = argv + optind; for (i=0; i<nmyargs; i++) sl_append(infns, myargs[i]); if (!sl_size(infns)) { printHelp(progname); printf("Need input filenames!\n"); exit(-1); } log_init(loglvl); fits_use_error_system(); NHP = 12 * nside * nside; logmsg("%i output healpixes\n", NHP); outtables = calloc(NHP, sizeof(fitstable_t*)); assert(outtables); md = deg2dist(margin); /** About the mincaps/maxcaps: These have a center and radius-squared, describing the region inside a small circle on the sphere. The "mincaps" describe the regions that are definitely owned by a single healpix -- ie, more than MARGIN distance from any edge. That is, the mincap is the small circle centered at (0.5, 0.5) in the healpix and with radius = the distance to the closest healpix boundary, MINUS the margin distance. Below, we first check whether a new star is within the "mincap" of any healpix. If so, we stick it in that healpix and continue. Otherwise, we check all the "maxcaps" -- these are the healpixes it could *possibly* be in. We then refine with healpix_within_range_of_xyz. The maxcap distance is the distance to the furthest boundary point, PLUS the margin distance. */ cap_t* mincaps = malloc(NHP * sizeof(cap_t)); cap_t* maxcaps = malloc(NHP * sizeof(cap_t)); for (i=0; i<NHP; i++) { // center double r2; double xyz[3]; double* cxyz; double step = 1e-3; double v; double r2b, r2a; cxyz = mincaps[i].xyz; healpix_to_xyzarr(i, nside, 0.5, 0.5, mincaps[i].xyz); memcpy(maxcaps[i].xyz, cxyz, 3 * sizeof(double)); logverb("Center of HP %i: (%.3f, %.3f, %.3f)\n", i, cxyz[0], cxyz[1], cxyz[2]); // radius-squared: // max is the easy one: max of the four corners (I assume) r2 = 0.0; healpix_to_xyzarr(i, nside, 0.0, 0.0, xyz); logverb(" HP %i corner 1: (%.3f, %.3f, %.3f), distsq %.3f\n", i, xyz[0], xyz[1], xyz[2], distsq(xyz, cxyz, 3)); r2 = MAX(r2, distsq(xyz, cxyz, 3)); healpix_to_xyzarr(i, nside, 1.0, 0.0, xyz); logverb(" HP %i corner 1: (%.3f, %.3f, %.3f), distsq %.3f\n", i, xyz[0], xyz[1], xyz[2], distsq(xyz, cxyz, 3)); r2 = MAX(r2, distsq(xyz, cxyz, 3)); healpix_to_xyzarr(i, nside, 0.0, 1.0, xyz); logverb(" HP %i corner 1: (%.3f, %.3f, %.3f), distsq %.3f\n", i, xyz[0], xyz[1], xyz[2], distsq(xyz, cxyz, 3)); r2 = MAX(r2, distsq(xyz, cxyz, 3)); healpix_to_xyzarr(i, nside, 1.0, 1.0, xyz); logverb(" HP %i corner 1: (%.3f, %.3f, %.3f), distsq %.3f\n", i, xyz[0], xyz[1], xyz[2], distsq(xyz, cxyz, 3)); r2 = MAX(r2, distsq(xyz, cxyz, 3)); logverb(" max distsq: %.3f\n", r2); logverb(" margin dist: %.3f\n", md); maxcaps[i].r2 = square(sqrt(r2) + md); logverb(" max cap distsq: %.3f\n", maxcaps[i].r2); r2a = r2; r2 = 1.0; r2b = 0.0; for (v=0; v<=1.0; v+=step) { healpix_to_xyzarr(i, nside, 0.0, v, xyz); r2 = MIN(r2, distsq(xyz, cxyz, 3)); r2b = MAX(r2b, distsq(xyz, cxyz, 3)); healpix_to_xyzarr(i, nside, 1.0, v, xyz); r2 = MIN(r2, distsq(xyz, cxyz, 3)); r2b = MAX(r2b, distsq(xyz, cxyz, 3)); healpix_to_xyzarr(i, nside, v, 0.0, xyz); r2 = MIN(r2, distsq(xyz, cxyz, 3)); r2b = MAX(r2b, distsq(xyz, cxyz, 3)); healpix_to_xyzarr(i, nside, v, 1.0, xyz); r2 = MIN(r2, distsq(xyz, cxyz, 3)); r2b = MAX(r2b, distsq(xyz, cxyz, 3)); } mincaps[i].r2 = square(MAX(0, sqrt(r2) - md)); logverb("\nhealpix %i: min rad %g\n", i, sqrt(r2)); logverb("healpix %i: max rad %g\n", i, sqrt(r2a)); logverb("healpix %i: max rad(b) %g\n", i, sqrt(r2b)); assert(r2a >= r2b); } if (backref) { fitstable_t* tab = fitstable_open_for_writing(backref); int maxlen = 0; char* buf; for (i=0; i<sl_size(infns); i++) { char* infn = sl_get(infns, i); maxlen = MAX(maxlen, strlen(infn)); } fitstable_add_write_column_array(tab, fitscolumn_char_type(), maxlen, "filename", NULL); fitstable_add_write_column(tab, fitscolumn_i16_type(), "index", NULL); if (fitstable_write_primary_header(tab) || fitstable_write_header(tab)) { ERROR("Failed to write header of backref table \"%s\"", backref); exit(-1); } buf = malloc(maxlen+1); assert(buf); for (i=0; i<sl_size(infns); i++) { char* infn = sl_get(infns, i); int16_t ind; memset(buf, 0, maxlen); strcpy(buf, infn); ind = i; if (fitstable_write_row(tab, buf, &ind)) { ERROR("Failed to write row %i of backref table: %s = %i", i, buf, ind); exit(-1); } } if (fitstable_fix_header(tab) || fitstable_close(tab)) { ERROR("Failed to fix header & close backref table"); exit(-1); } logmsg("Wrote backref table %s\n", backref); free(buf); } for (i=0; i<sl_size(infns); i++) { char* infn = sl_get(infns, i); char* originfn = infn; int r, NR; tfits_type any, dubl; il* hps = NULL; bread_t* rowbuf; int R; char* tempfn = NULL; char* padrowdata = NULL; int ii; logmsg("Reading input \"%s\"...\n", infn); if (gzip) { char* cmd; int rtn; tempfn = create_temp_file("hpsplit", tempdir); asprintf_safe(&cmd, "gunzip -cd %s > %s", infn, tempfn); logmsg("Running: \"%s\"\n", cmd); rtn = run_command_get_outputs(cmd, NULL, NULL); if (rtn) { ERROR("Failed to run command: \"%s\"", cmd); exit(-1); } free(cmd); infn = tempfn; } intable = fitstable_open(infn); if (!intable) { ERROR("Couldn't read catalog %s", infn); exit(-1); } NR = fitstable_nrows(intable); logmsg("Got %i rows\n", NR); any = fitscolumn_any_type(); dubl = fitscolumn_double_type(); fitstable_add_read_column_struct(intable, dubl, 1, 0, any, racol, TRUE); fitstable_add_read_column_struct(intable, dubl, 1, sizeof(double), any, deccol, TRUE); fitstable_use_buffered_reading(intable, 2*sizeof(double), 1000); R = fitstable_row_size(intable); rowbuf = buffered_read_new(R, 1000, NR, refill_rowbuffer, intable); if (fitstable_read_extension(intable, 1)) { ERROR("Failed to find RA and DEC columns (called \"%s\" and \"%s\" in the FITS file)", racol, deccol); exit(-1); } for (r=0; r<NR; r++) { int hp = -1; double ra, dec; int j; double* rd; void* rowdata; void* rdata; if (r && ((r % 100000) == 0)) { logmsg("Reading row %i of %i\n", r, NR); } //printf("reading RA,Dec for row %i\n", r); rd = fitstable_next_struct(intable); ra = rd[0]; dec = rd[1]; logverb("row %i: ra,dec %g,%g\n", r, ra, dec); if (margin == 0) { hp = radecdegtohealpix(ra, dec, nside); logverb(" --> healpix %i\n", hp); } else { double xyz[3]; anbool gotit = FALSE; double d2; if (!hps) hps = il_new(4); radecdeg2xyzarr(ra, dec, xyz); for (j=0; j<NHP; j++) { d2 = distsq(xyz, mincaps[j].xyz, 3); if (d2 <= mincaps[j].r2) { logverb(" -> in mincap %i (dist %g vs %g)\n", j, sqrt(d2), sqrt(mincaps[j].r2)); il_append(hps, j); gotit = TRUE; break; } } if (!gotit) { for (j=0; j<NHP; j++) { d2 = distsq(xyz, maxcaps[j].xyz, 3); if (d2 <= maxcaps[j].r2) { logverb(" -> in maxcap %i (dist %g vs %g)\n", j, sqrt(d2), sqrt(maxcaps[j].r2)); if (healpix_within_range_of_xyz(j, nside, xyz, margin)) { logverb(" -> and within range.\n"); il_append(hps, j); } } } } //hps = healpix_rangesearch_radec(ra, dec, margin, nside, hps); logverb(" --> healpixes: ["); for (j=0; j<il_size(hps); j++) logverb(" %i", il_get(hps, j)); logverb(" ]\n"); } //printf("Reading rowdata for row %i\n", r); rowdata = buffered_read(rowbuf); assert(rowdata); j=0; while (1) { if (hps) { if (j >= il_size(hps)) break; hp = il_get(hps, j); j++; } assert(hp < NHP); assert(hp >= 0); if (!outtables[hp]) { char* outfn; fitstable_t* out; // MEMLEAK the output filename. You'll live. asprintf_safe(&outfn, outfnpat, hp); logmsg("Opening output file \"%s\"...\n", outfn); out = fitstable_open_for_writing(outfn); if (!out) { ERROR("Failed to open output table \"%s\"", outfn); exit(-1); } // Set the output table structure. if (cols) { fitstable_add_fits_columns_as_struct3(intable, out, cols, 0); } else fitstable_add_fits_columns_as_struct2(intable, out); if (backref) { tfits_type i16type; tfits_type i32type; // R = fitstable_row_size(intable); int off = R; i16type = fitscolumn_i16_type(); i32type = fitscolumn_i32_type(); fitstable_add_read_column_struct(out, i16type, 1, off, i16type, "backref_file", TRUE); off += sizeof(int16_t); fitstable_add_read_column_struct(out, i32type, 1, off, i32type, "backref_index", TRUE); } //printf("Output table:\n"); //fitstable_print_columns(out); if (fitstable_write_primary_header(out) || fitstable_write_header(out)) { ERROR("Failed to write output file headers for \"%s\"", outfn); exit(-1); } outtables[hp] = out; } if (backref) { int16_t brfile; int32_t brind; if (!padrowdata) { padrowdata = malloc(R + sizeof(int16_t) + sizeof(int32_t)); assert(padrowdata); } // convert to FITS endian brfile = htons(i); brind = htonl(r); // add backref data to rowdata memcpy(padrowdata, rowdata, R); memcpy(padrowdata + R, &brfile, sizeof(int16_t)); memcpy(padrowdata + R + sizeof(int16_t), &brind, sizeof(int32_t)); rdata = padrowdata; } else { rdata = rowdata; } if (cols) { if (fitstable_write_struct_noflip(outtables[hp], rdata)) { ERROR("Failed to copy a row of data from input table \"%s\" to output healpix %i", infn, hp); } } else { if (fitstable_write_row_data(outtables[hp], rdata)) { ERROR("Failed to copy a row of data from input table \"%s\" to output healpix %i", infn, hp); } } if (!hps) break; } if (hps) il_remove_all(hps); } buffered_read_free(rowbuf); // wack... buffered_read_free() just frees its internal buffer, // not the "rowbuf" struct itself. // who wrote this crazy code? Oh, me of 5 years ago. Jerk. free(rowbuf); fitstable_close(intable); il_free(hps); if (tempfn) { logverb("Removing temp file %s\n", tempfn); if (unlink(tempfn)) { SYSERROR("Failed to unlink() temp file \"%s\"", tempfn); } tempfn = NULL; } // fix headers so that the files are valid at this point. for (ii=0; ii<NHP; ii++) { if (!outtables[ii]) continue; off_t offset = ftello(outtables[ii]->fid); if (fitstable_fix_header(outtables[ii])) { ERROR("Failed to fix header for healpix %i after reading input file \"%s\"", ii, originfn); exit(-1); } fseeko(outtables[ii]->fid, offset, SEEK_SET); } if (padrowdata) { free(padrowdata); padrowdata = NULL; } } for (i=0; i<NHP; i++) { if (!outtables[i]) continue; if (fitstable_fix_header(outtables[i]) || fitstable_fix_primary_header(outtables[i]) || fitstable_close(outtables[i])) { ERROR("Failed to close output table for healpix %i", i); exit(-1); } } free(outtables); sl_free2(infns); sl_free2(cols); free(mincaps); free(maxcaps); return 0; }