int MANGLE(kdtree_dualtree_rangesearch)(kdtree_t* kd1, kdtree_t* kd2, double maxdist, rangesearch_callback callback, void* baton) { int xnode, ynode; il* nodes; il* leaves; if (kdtree_treetype(kd1) != kdtree_treetype(kd2)) { ERROR("Trees must be the same type."); return -1; } if (!kd1->split.any || !kd2->split.any) { ERROR("This function only supports splitting-plane trees.\n"); return -1; } nodes = il_new(256); leaves = il_new(256); // root nodes. xnode = ynode = 0; if (KD_IS_LEAF(xtree, xnode)) il_append(leaves, xnode); else il_append(nodes, xnode); dualtree_recurse(xtree, ytree, nodes, leaves, ynode, callbacks); il_free(nodes); il_free(leaves); return 0; }
int parse_depth_string(il* depths, const char* str) { unsigned int lasthi = 0; unsigned int lo, hi; while (str && *str) { int nread; char div[2]; lo = 0; hi = 0; // 10-20 if (sscanf(str, "%u-%u", &lo, &hi) == 2) { sscanf(str, "%*u-%*u%n", &nread); if (lo > hi) { logerr("Depth range %i to %i is invalid: max must be >= min!\n", lo, hi); return -1; } if (lo == 0) { logerr("Depth lower limit %i is invalid: depths must be >= 1.\n", lo); return -1; } // 30- } else if (sscanf(str, "%u%1[-]", &lo, div) == 2) { sscanf(str, "%*u%*1[-]%n", &nread); if (lo == 0) { logerr("Depth lower limit %i is invalid: depths must be >= 1.\n", lo); return -1; } // -100 } else if (sscanf(str, "-%u", &hi) == 1) { sscanf(str, "-%*u%n", &nread); if (hi == 0) { logerr("Depth upper limit %i is invalid: depths must be >= 1.\n", hi); return -1; } lo = 1; // 7 } else if (sscanf(str, "%u", &hi) == 1) { sscanf(str, "%*u%n", &nread); if (hi == 0) { logerr("Depth %i is invalid: depths must be >= 1.\n", hi); return -1; } lo = lasthi + 1; } else { logerr("Failed to parse depth range: \"%s\"\n", str); return -1; } il_append(depths, lo); il_append(depths, hi); lasthi = hi; str += nread; while ((*str == ',') || isspace((unsigned)(*str))) str++; } return 0; }
void test_il_sorted(CuTest* tc) { int vals[] = {34951,34950,34949,35049,35149,29951,29950,29949,34999,34998,5099,5199,39849,39949,4999,35249,29952,34952,5299,35349,29953,34953,5399,35449,29954,34954,5499,35549,29955,34955,5599,35649,29956,34956,5699,35749,29957,34957,5799,35849,29958,34958,5899,35949,29959,34959,5999,36049,29960,34960,6099,36149,29961,34961,6199,36249,29962,34962,6299,36349,29963,34963,6399,36449,29964,34964,6499,36549,29965,34965,6599,36649,29966,34966,6699,36749,29967,34967,6799,36849,29968,34968,6899,36949,29969,34969,6999,37049,29970,34970,7099,37149,29971,34971,7199,37249,29972,34972,7299,37349,29973,34973,7399,37449,29974,34974,7499,37549,29975,34975,7599,37649,29976,34976,7699,37749,29977,34977,7799,37849,29978,34978,7899,37949,29979,34979,7999,38049,29980,34980,8099,38149,29981,34981,8199,38249,29982,34982,8299,38349,29983,34983,8399,38449,29984,34984,8499,38549,29985,34985,8599,38649,29986,34986,8699,38749,29987,34987,8799,38849,29988,34988,8899,38949,29989,34989,8999,39049,29990,34990,9099,39149,29991,34991,9199,39249,29992,34992,9299,39349,29993,34993,9399,39449,29994,34994,9499,39549,29995,34995,9599,39649,29996,34996,9699,39749,29997,34997,9799,29998,9899,29999,9999}; int i, N; il* lst; N = sizeof(vals)/sizeof(int); lst = il_new(256); for (i=0; i<N; i++) il_append(lst, vals[i]); CuAssertIntEquals(tc, N, il_size(lst)); for (i=0; i<N; i++) CuAssertIntEquals(tc, vals[i], il_get(lst, i)); printf("Before sorting:\n"); il_print(lst); il_sort(lst, TRUE); printf("After sorting:\n"); il_print(lst); CuAssertIntEquals(tc, 0, il_check_consistency(lst)); CuAssertIntEquals(tc, 0, il_check_sorted_ascending(lst, TRUE)); for (i=1; i<N; i++) CuAssertTrue(tc, il_get(lst, i-1) < il_get(lst, i)); for (i=0; i<N; i++) CuAssertIntEquals(tc, 1, il_sorted_contains(lst, vals[i])); }
il* constellations_get_lines(int c) { il* list; const int* lines; int i; check_const_num(c); list = il_new(16); lines = constellation_lines[c]; for (i=0; i<2*constellation_nlines[c]; i++) { il_append(list, lines[i]); } return list; }
il* solvedclient_get_fields(int filenum, int firstfield, int lastfield, int maxnfields) { char* buf; int bufsize; il* list; char* cptr; int fld; int nchars; if (connect_to_server()) return NULL; bufsize = 100 + 10 * (maxnfields ? maxnfields : (1 + lastfield - firstfield)); buf = malloc(bufsize); nchars = sprintf(buf, "getall %i %i %i %i\n", filenum, firstfield, lastfield, maxnfields); if ((fwrite(buf, 1, nchars, fserver) != nchars) || fflush(fserver)) { fprintf(stderr, "Failed to send command (%s) to solvedserver: %s\n", buf, strerror(errno)); return NULL; } // wait for response. if (!fgets(buf, bufsize, fserver)) { fprintf(stderr, "Couldn't read response: %s\n", strerror(errno)); fclose(fserver); fserver = NULL; free(buf); return NULL; } if (sscanf(buf, "unsolved %i%n", &fld, &nchars) != 1) { fprintf(stderr, "Couldn't parse response: %s\n", buf); free(buf); return NULL; } if (fld != filenum) { fprintf(stderr, "Expected file number %i, not %i.\n", filenum, fld); free(buf); return NULL; } cptr = buf + nchars; list = il_new(256); while (*cptr && *cptr != '\n') { if (sscanf(cptr, " %i%n", &fld, &nchars) != 1) { fprintf(stderr, "Couldn't parse response: %s\n", buf); il_free(list); free(buf); return NULL; } cptr += nchars; il_append(list, fld); } free(buf); return list; }
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."); } } }
void test_il_remove_index_range_1(CuTest* tc) { il* lst = il_new(4); il_append(lst, 0); il_append(lst, 1); il_append(lst, 2); il_append(lst, 3); il_append(lst, 4); il_append(lst, 5); il_remove_index_range(lst, 2, 2); // [0 1 2 3 4 5] -> [0 1 4 5] CuAssertIntEquals(tc, 4, il_size(lst)); CuAssertIntEquals(tc, 4, il_get(lst, 2)); }
static bl* get_chunks(startree_t* s, il* wordsizes) { bl* chunks = bl_new(4, sizeof(fitsbin_chunk_t)); fitsbin_chunk_t chunk; kdtree_t* kd = s->tree; fitsbin_chunk_init(&chunk); chunk.tablename = "sweep"; chunk.forced_type = fitscolumn_u8_type(); chunk.itemsize = sizeof(uint8_t); chunk.nrows = kd->ndata; chunk.data = s->sweep; chunk.userdata = &(s->sweep); chunk.required = FALSE; bl_append(chunks, &chunk); if (wordsizes) il_append(wordsizes, sizeof(uint8_t)); fitsbin_chunk_clean(&chunk); return chunks; }
static int build_quads(hpquads_t* me, int Nhptotry, il* hptotry, int R) { int nthispass = 0; int lastgrass = 0; int i; for (i=0; i<Nhptotry; i++) { anbool ok; int hp; if ((i * 80 / Nhptotry) != lastgrass) { printf("."); fflush(stdout); lastgrass = i * 80 / Nhptotry; } if (hptotry) hp = il_get(hptotry, i); else hp = i; me->hp = hp; me->quad_created = FALSE; ok = find_stars(me, me->radius2, R); if (ok) create_quad(me, TRUE); if (me->quad_created) nthispass++; else { if (R && me->Nstars && me->retryhps) // there were some stars, and we're counting how many times stars are used. //il_insert_unique_ascending(me->retryhps, hp); // we don't mind hps showing up multiple times because we want to make up for the lost // passes during loosening... il_append(me->retryhps, hp); // FIXME -- could also track which hps are worth visiting in a future pass } } printf("\n"); return nthispass; }
// okay just make a bfs and then add in like an extra counter // that counts number of things added to list and then short circuit il* limited_bfs(graph *g, unsigned int start_key, unsigned int max_steps) { // check for errors if (start_key>=g->n_vertices) { fprintf(stderr,"bfs: no such vertex (%u)\n",start_key); exit(1); } il *prev_reached, *reached; reached = NULL; iq *q = iq_new(); int curr; int list_elements = 0; enqueue(q, start_key); while (q->n > 0) { curr = dequeue(q); if (g->vs[curr]->done) continue; g->vs[curr]->done = 1; prev_reached = reached; reached = il_append(prev_reached,il_singleton(curr)); il_free(prev_reached); list_elements++; if (list_elements >= max_steps) { iq_free(q); return reached; } il *neighbors = g->es[curr]; while (neighbors != NULL) { int n = neighbors->n; enqueue(q,n); neighbors = neighbors->next; } } iq_free(q); return reached; }
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; }
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; }
int main(int argc, char** args) { char* filename = NULL; int npoints; int i, j; int* healpixes; int argchar; char* progname = args[0]; il** lists; anbool quiet = FALSE; rdlist* rdls; int Nside = 1; int N; while ((argchar = getopt (argc, args, OPTIONS)) != -1) switch (argchar) { case 'N': Nside = atoi(optarg); break; case 'f': filename = optarg; break; case 'h': printHelp(progname); exit(0); case 'q': quiet = TRUE; break; case '?': fprintf(stderr, "Unknown option `-%c'.\n", optopt); default: exit(-1); } if (!filename) { printHelp(progname); exit(-1); } fprintf(stderr, "Opening RDLS file %s...\n", filename); rdls = rdlist_open(filename); if (!rdls) { fprintf(stderr, "Failed to open RDLS file.\n"); exit(-1); } N = 12 * Nside * Nside; healpixes = malloc(N * sizeof(int)); lists = calloc(N, sizeof(il*)); /* for (i=0; i<N; i++) { lists[i] = il_new(256); } */ for (j=1; j<=rdls_n_fields(rdls); j++) { rd* points; points = rdlist_get_field(rdls, j); if (!points) { fprintf(stderr, "error reading field %i\n", j); break; } memset(healpixes, 0, N * sizeof(int)); npoints = rd_size(points); for (i=0; i<npoints; i++) { double ra, dec; int hp; ra = deg2rad(rd_refra (points, i)); dec = deg2rad(rd_refdec(points, i)); if (Nside > 1) hp = radectohealpix_nside(ra, dec, Nside); else hp = radectohealpix(ra, dec); if ((hp < 0) || (hp >= N)) { printf("hp=%i\n", hp); continue; } healpixes[hp] = 1; } if (!quiet) { printf("Field %i: healpixes ", j); for (i=0; i<N; i++) { if (healpixes[i]) printf("%i ", i); } printf("\n"); fflush(stdout); } for (i=0; i<N; i++) if (healpixes[i]) { if (!lists[i]) lists[i] = il_new(256); il_append(lists[i], j); } free_rd(points); } for (i=0; i<N; i++) { int N; if (!lists[i]) continue; printf("HP %i: ", i); N = il_size(lists[i]); for (j=0; j<N; j++) printf("%i ", il_get(lists[i], j)); il_free(lists[i]); printf("\n"); } free(lists); free(healpixes); rdlist_close(rdls); return 0; }
void verify_get_all_matches(const double* refxys, int NR, const double* testxys, const double* testsigma2s, int NT, double effective_area, double distractors, double nsigma, double limit, il*** p_reflist, dl*** p_problist) { double* refcopy; kdtree_t* rtree; int Nleaf = 10; int i,j; double logd; double logbg; double loglimit; il** reflist; dl** problist; reflist = calloc(NT, sizeof(il*)); problist = calloc(NT, sizeof(dl*)); // Build a tree out of the index stars in pixel space... // kdtree scrambles the data array so make a copy first. refcopy = malloc(2 * NR * sizeof(double)); memcpy(refcopy, refxys, 2 * NR * sizeof(double)); rtree = kdtree_build(NULL, refcopy, NR, 2, Nleaf, KDTT_DOUBLE, KD_BUILD_SPLIT); logbg = log(1.0 / effective_area); logd = log(distractors / effective_area); loglimit = log(distractors / effective_area * limit); for (i=0; i<NT; i++) { const double* testxy; double sig2; kdtree_qres_t* res; testxy = testxys + 2*i; sig2 = testsigma2s[i]; logverb("\n"); logverb("test star %i: (%.1f,%.1f), sigma: %.1f\n", i, testxy[0], testxy[1], sqrt(sig2)); // find all ref stars within nsigma. res = kdtree_rangesearch_options(rtree, testxy, sig2*nsigma*nsigma, KD_OPTIONS_SORT_DISTS | KD_OPTIONS_SMALL_RADIUS); if (res->nres == 0) { kdtree_free_query(res); continue; } reflist[i] = il_new(4); problist[i] = dl_new(4); for (j=0; j<res->nres; j++) { double d2; int refi; double loggmax, logfg; d2 = res->sdists[j]; refi = res->inds[j]; // peak value of the Gaussian loggmax = log((1.0 - distractors) / (2.0 * M_PI * sig2 * NR)); // value of the Gaussian logfg = loggmax - d2 / (2.0 * sig2); if (logfg < loglimit) continue; logverb(" ref star %i, dist %.2f, sigmas: %.3f, logfg: %.1f (%.1f above distractor, %.1f above bg, %.1f above keep-limit)\n", refi, sqrt(d2), sqrt(d2 / sig2), logfg, logfg - logd, logfg - logbg, logfg - loglimit); il_append(reflist[i], refi); dl_append(problist[i], logfg); } kdtree_free_query(res); } kdtree_free(rtree); free(refcopy); *p_reflist = reflist; *p_problist = problist; }
int uniformize_catalog(fitstable_t* intable, fitstable_t* outtable, const char* racol, const char* deccol, const char* sortcol, anbool sort_ascending, double sort_min_cut, // ? Or do this cut in a separate process? int bighp, int bignside, int nmargin, // uniformization nside. int Nside, double dedup_radius, int nsweeps, char** args, int argc) { anbool allsky; intmap_t* starlists; int NHP; anbool dense = FALSE; double dedupr2 = 0.0; tfits_type dubl; int N; int* inorder = NULL; int* outorder = NULL; int outi; double *ra = NULL, *dec = NULL; il* myhps = NULL; int i,j,k; int nkeep = nsweeps; int noob = 0; int ndup = 0; struct oh_token token; int* npersweep = NULL; qfits_header* outhdr = NULL; double *sortval = NULL; if (bignside == 0) bignside = 1; allsky = (bighp == -1); if (Nside % bignside) { ERROR("Fine healpixelization Nside must be a multiple of the coarse healpixelization Nside"); return -1; } if (Nside > HP_MAX_INT_NSIDE) { ERROR("Error: maximum healpix Nside = %i", HP_MAX_INT_NSIDE); return -1; } NHP = 12 * Nside * Nside; logverb("Healpix Nside: %i, # healpixes on the whole sky: %i\n", Nside, NHP); if (!allsky) { logverb("Creating index for healpix %i, nside %i\n", bighp, bignside); logverb("Number of healpixes: %i\n", ((Nside/bignside)*(Nside/bignside))); } logverb("Healpix side length: %g arcmin.\n", healpix_side_length_arcmin(Nside)); dubl = fitscolumn_double_type(); if (!racol) racol = "RA"; ra = fitstable_read_column(intable, racol, dubl); if (!ra) { ERROR("Failed to find RA column (%s) in table", racol); return -1; } if (!deccol) deccol = "DEC"; dec = fitstable_read_column(intable, deccol, dubl); if (!dec) { ERROR("Failed to find DEC column (%s) in table", deccol); free(ra); return -1; } N = fitstable_nrows(intable); logverb("Have %i objects\n", N); // FIXME -- argsort and seek around the input table, and append to // starlists in order; OR read from the input table in sequence and // sort in the starlists? if (sortcol) { logverb("Sorting by %s...\n", sortcol); sortval = fitstable_read_column(intable, sortcol, dubl); if (!sortval) { ERROR("Failed to read sorting column \"%s\"", sortcol); free(ra); free(dec); return -1; } inorder = permuted_sort(sortval, sizeof(double), sort_ascending ? compare_doubles_asc : compare_doubles_desc, NULL, N); if (sort_min_cut > -HUGE_VAL) { logverb("Cutting to %s > %g...\n", sortcol, sort_min_cut); // Cut objects with sortval < sort_min_cut. if (sort_ascending) { // skipped objects are at the front -- find the first obj // to keep for (i=0; i<N; i++) if (sortval[inorder[i]] > sort_min_cut) break; // move the "inorder" indices down. if (i) memmove(inorder, inorder+i, (N-i)*sizeof(int)); N -= i; } else { // skipped objects are at the end -- find the last obj to keep. for (i=N-1; i>=0; i--) if (sortval[inorder[i]] > sort_min_cut) break; N = i+1; } logverb("Cut to %i objects\n", N); } //free(sortval); } token.nside = bignside; token.finenside = Nside; token.hp = bighp; if (!allsky && nmargin) { int bigbighp, bighpx, bighpy; //int ninside; il* seeds = il_new(256); logverb("Finding healpixes in range...\n"); healpix_decompose_xy(bighp, &bigbighp, &bighpx, &bighpy, bignside); //ninside = (Nside/bignside)*(Nside/bignside); // Prime the queue with the fine healpixes that are on the // boundary of the big healpix. for (i=0; i<((Nside / bignside) - 1); i++) { // add (i,0), (i,max), (0,i), and (0,max) healpixes int xx = i + bighpx * (Nside / bignside); int yy = i + bighpy * (Nside / bignside); int y0 = bighpy * (Nside / bignside); // -1 prevents us from double-adding the corners. int y1 =(1 + bighpy)* (Nside / bignside) - 1; int x0 = bighpx * (Nside / bignside); int x1 =(1 + bighpx)* (Nside / bignside) - 1; assert(xx < Nside); assert(yy < Nside); assert(x0 < Nside); assert(x1 < Nside); assert(y0 < Nside); assert(y1 < Nside); il_append(seeds, healpix_compose_xy(bigbighp, xx, y0, Nside)); il_append(seeds, healpix_compose_xy(bigbighp, xx, y1, Nside)); il_append(seeds, healpix_compose_xy(bigbighp, x0, yy, Nside)); il_append(seeds, healpix_compose_xy(bigbighp, x1, yy, Nside)); } logmsg("Number of boundary healpixes: %zu (Nside/bignside = %i)\n", il_size(seeds), Nside/bignside); myhps = healpix_region_search(-1, seeds, Nside, NULL, NULL, outside_healpix, &token, nmargin); logmsg("Number of margin healpixes: %zu\n", il_size(myhps)); il_free(seeds); il_sort(myhps, TRUE); // DEBUG il_check_consistency(myhps); il_check_sorted_ascending(myhps, TRUE); } dedupr2 = arcsec2distsq(dedup_radius); starlists = intmap_new(sizeof(int32_t), nkeep, 0, dense); logverb("Placing stars in grid cells...\n"); for (i=0; i<N; i++) { int hp; bl* lst; int32_t j32; anbool oob; if (inorder) { j = inorder[i]; //printf("Placing star %i (%i): sort value %s = %g, RA,Dec=%g,%g\n", i, j, sortcol, sortval[j], ra[j], dec[j]); } else j = i; hp = radecdegtohealpix(ra[j], dec[j], Nside); //printf("HP %i\n", hp); // in bounds? oob = FALSE; if (myhps) { oob = (outside_healpix(hp, &token) && !il_sorted_contains(myhps, hp)); } else if (!allsky) { oob = (outside_healpix(hp, &token)); } if (oob) { //printf("out of bounds.\n"); noob++; continue; } lst = intmap_find(starlists, hp, TRUE); /* printf("list has %i existing entries.\n", bl_size(lst)); for (k=0; k<bl_size(lst); k++) { bl_get(lst, k, &j32); printf(" %i: index %i, %s = %g\n", k, j32, sortcol, sortval[j32]); } */ // is this list full? if (nkeep && (bl_size(lst) >= nkeep)) { // Here we assume we're working in sorted order: once the list is full we're done. //printf("Skipping: list is full.\n"); continue; } if ((dedupr2 > 0.0) && is_duplicate(hp, ra[j], dec[j], Nside, starlists, ra, dec, dedupr2)) { //printf("Skipping: duplicate\n"); ndup++; continue; } // Add the new star (by index) j32 = j; bl_append(lst, &j32); } logverb("%i outside the healpix\n", noob); logverb("%i duplicates\n", ndup); il_free(myhps); myhps = NULL; free(inorder); inorder = NULL; free(ra); ra = NULL; free(dec); dec = NULL; outorder = malloc(N * sizeof(int)); outi = 0; npersweep = calloc(nsweeps, sizeof(int)); for (k=0; k<nsweeps; k++) { int starti = outi; int32_t j32; for (i=0;; i++) { bl* lst; int hp; if (!intmap_get_entry(starlists, i, &hp, &lst)) break; if (bl_size(lst) <= k) continue; bl_get(lst, k, &j32); outorder[outi] = j32; //printf("sweep %i, cell #%i, hp %i, star %i, %s = %g\n", k, i, hp, j32, sortcol, sortval[j32]); outi++; } logmsg("Sweep %i: %i stars\n", k+1, outi - starti); npersweep[k] = outi - starti; if (sortcol) { // Re-sort within this sweep. permuted_sort(sortval, sizeof(double), sort_ascending ? compare_doubles_asc : compare_doubles_desc, outorder + starti, npersweep[k]); /* for (i=0; i<npersweep[k]; i++) { printf(" within sweep %i: star %i, j=%i, %s=%g\n", k, i, outorder[starti + i], sortcol, sortval[outorder[starti + i]]); } */ } } intmap_free(starlists); starlists = NULL; ////// free(sortval); sortval = NULL; logmsg("Total: %i stars\n", outi); N = outi; outhdr = fitstable_get_primary_header(outtable); if (allsky) qfits_header_add(outhdr, "ALLSKY", "T", "All-sky catalog.", NULL); BOILERPLATE_ADD_FITS_HEADERS(outhdr); qfits_header_add(outhdr, "HISTORY", "This file was generated by the command-line:", NULL, NULL); fits_add_args(outhdr, args, argc); qfits_header_add(outhdr, "HISTORY", "(end of command line)", NULL, NULL); fits_add_long_history(outhdr, "uniformize-catalog args:"); fits_add_long_history(outhdr, " RA,Dec columns: %s,%s", racol, deccol); fits_add_long_history(outhdr, " sort column: %s", sortcol); fits_add_long_history(outhdr, " sort direction: %s", sort_ascending ? "ascending" : "descending"); if (sort_ascending) fits_add_long_history(outhdr, " (ie, for mag-like sort columns)"); else fits_add_long_history(outhdr, " (ie, for flux-like sort columns)"); fits_add_long_history(outhdr, " uniformization nside: %i", Nside); fits_add_long_history(outhdr, " (ie, side length ~ %g arcmin)", healpix_side_length_arcmin(Nside)); fits_add_long_history(outhdr, " deduplication scale: %g arcsec", dedup_radius); fits_add_long_history(outhdr, " number of sweeps: %i", nsweeps); fits_header_add_int(outhdr, "NSTARS", N, "Number of stars."); fits_header_add_int(outhdr, "HEALPIX", bighp, "Healpix covered by this catalog, with Nside=HPNSIDE"); fits_header_add_int(outhdr, "HPNSIDE", bignside, "Nside of HEALPIX."); fits_header_add_int(outhdr, "CUTNSIDE", Nside, "uniformization scale (healpix nside)"); fits_header_add_int(outhdr, "CUTMARG", nmargin, "margin size, in healpixels"); //qfits_header_add(outhdr, "CUTBAND", cutband, "band on which the cut was made", NULL); fits_header_add_double(outhdr, "CUTDEDUP", dedup_radius, "deduplication radius [arcsec]"); fits_header_add_int(outhdr, "CUTNSWEP", nsweeps, "number of sweeps"); //fits_header_add_double(outhdr, "CUTMINMG", minmag, "minimum magnitude"); //fits_header_add_double(outhdr, "CUTMAXMG", maxmag, "maximum magnitude"); for (k=0; k<nsweeps; k++) { char key[64]; sprintf(key, "SWEEP%i", (k+1)); fits_header_add_int(outhdr, key, npersweep[k], "# stars added"); } free(npersweep); if (fitstable_write_primary_header(outtable)) { ERROR("Failed to write primary header"); return -1; } // Write output. fitstable_add_fits_columns_as_struct2(intable, outtable); if (fitstable_write_header(outtable)) { ERROR("Failed to write output table header"); return -1; } logmsg("Writing output...\n"); logverb("Row size: %i\n", fitstable_row_size(intable)); if (fitstable_copy_rows_data(intable, outorder, N, outtable)) { ERROR("Failed to copy rows from input table to output"); return -1; } if (fitstable_fix_header(outtable)) { ERROR("Failed to fix output table header"); return -1; } free(outorder); return 0; }
int main(int argc, char** args) { int argchar; char* progname = args[0]; char* outfn = NULL; char* outwcsfn = NULL; int outwcsext = 0; anwcs_t* outwcs; sl* inimgfns = sl_new(16); sl* inwcsfns = sl_new(16); sl* inwtfns = sl_new(16); il* inimgexts = il_new(16); il* inwcsexts = il_new(16); il* inwtexts = il_new(16); int i; int loglvl = LOG_MSG; int order = 3; coadd_t* coadd; lanczos_args_t largs; double sigma = 0.0; anbool nearest = FALSE; anbool divweight = FALSE; int plane = 0; while ((argchar = getopt(argc, args, OPTIONS)) != -1) switch (argchar) { case '?': case 'h': printHelp(progname); exit(0); case 'D': divweight = TRUE; break; case 'p': plane = atoi(optarg); break; case 'N': nearest = TRUE; break; case 's': sigma = atof(optarg); break; case 'v': loglvl++; break; case 'e': outwcsext = atoi(optarg); break; case 'w': outwcsfn = optarg; break; case 'o': outfn = optarg; break; case 'O': order = atoi(optarg); break; } log_init(loglvl); fits_use_error_system(); args += optind; argc -= optind; if (argc == 0 || argc % 6) { printHelp(progname); exit(-1); } for (i=0; i<argc/6; i++) { sl_append(inimgfns, args[6*i+0]); il_append(inimgexts, atoi(args[6*i+1])); sl_append(inwtfns, args[6*i+2]); il_append(inwtexts, atoi(args[6*i+3])); sl_append(inwcsfns, args[6*i+4]); il_append(inwcsexts, atoi(args[6*i+5])); } logmsg("Reading output WCS file %s\n", outwcsfn); outwcs = anwcs_open(outwcsfn, outwcsext); if (!outwcs) { ERROR("Failed to read WCS from file: %s ext %i\n", outwcsfn, outwcsext); exit(-1); } logmsg("Output image will be %i x %i\n", (int)anwcs_imagew(outwcs), (int)anwcs_imageh(outwcs)); coadd = coadd_new(anwcs_imagew(outwcs), anwcs_imageh(outwcs)); coadd->wcs = outwcs; if (nearest) { coadd->resample_func = nearest_resample_f; coadd->resample_token = NULL; } else { coadd->resample_func = lanczos_resample_f; largs.order = order; coadd->resample_token = &largs; } for (i=0; i<sl_size(inimgfns); i++) { anqfits_t* anq; anqfits_t* wanq; float* img; float* wt = NULL; anwcs_t* inwcs; char* fn; int ext; float overallwt = 1.0; int W, H; fn = sl_get(inimgfns, i); ext = il_get(inimgexts, i); logmsg("Reading input image \"%s\" ext %i\n", fn, ext); anq = anqfits_open(fn); if (!anq) { ERROR("Failed to open file \"%s\"\n", fn); exit(-1); } img = anqfits_readpix(anq, ext, 0, 0, 0, 0, plane, PTYPE_FLOAT, NULL, &W, &H); if (!img) { ERROR("Failed to read image from ext %i of %s\n", ext, fn); exit(-1); } anqfits_close(anq); logmsg("Read image: %i x %i.\n", W, H); if (sigma > 0.0) { int k0, nk; float* kernel; logmsg("Smoothing by Gaussian with sigma=%g\n", sigma); kernel = convolve_get_gaussian_kernel_f(sigma, 4, &k0, &nk); convolve_separable_f(img, W, H, kernel, k0, nk, img, NULL); free(kernel); } fn = sl_get(inwcsfns, i); ext = il_get(inwcsexts, i); logmsg("Reading input WCS file \"%s\" ext %i\n", fn, ext); inwcs = anwcs_open(fn, ext); if (!inwcs) { ERROR("Failed to read WCS from file \"%s\" ext %i\n", fn, ext); exit(-1); } if (anwcs_pixel_scale(inwcs) == 0) { ERROR("Pixel scale from the WCS file is zero. Usually this means the image has no valid WCS header.\n"); exit(-1); } if (anwcs_imagew(inwcs) != W || anwcs_imageh(inwcs) != H) { ERROR("Size mismatch between image and WCS!"); exit(-1); } fn = sl_get(inwtfns, i); ext = il_get(inwtexts, i); if (streq(fn, "none")) { logmsg("Not using weight image.\n"); wt = NULL; } else if (file_exists(fn)) { logmsg("Reading input weight image \"%s\" ext %i\n", fn, ext); wanq = anqfits_open(fn); if (!wanq) { ERROR("Failed to open file \"%s\"\n", fn); exit(-1); } int wtW, wtH; wt = anqfits_readpix(anq, ext, 0, 0, 0, 0, 0, PTYPE_FLOAT, NULL, &wtW, &wtH); if (!wt) { ERROR("Failed to read image from ext %i of %s\n", ext, fn); exit(-1); } anqfits_close(wanq); logmsg("Read image: %i x %i.\n", wtW, wtH); if (wtW != W || wtH != H) { ERROR("Size mismatch between image and weight!"); exit(-1); } } else { char* endp; overallwt = strtod(fn, &endp); if (endp == fn) { ERROR("Weight: \"%s\" is neither a file nor a double.\n", fn); exit(-1); } logmsg("Parsed weight value \"%g\"\n", overallwt); } if (divweight && wt) { int j; logmsg("Dividing image by weight image...\n"); for (j=0; j<(W*H); j++) img[j] /= wt[j]; } coadd_add_image(coadd, img, wt, overallwt, inwcs); anwcs_free(inwcs); free(img); if (wt) free(wt); } // logmsg("Writing output: %s\n", outfn); coadd_divide_by_weight(coadd, 0.0); /* if (fits_write_float_image_hdr(coadd->img, coadd->W, coadd->H, outfn)) { ERROR("Failed to write output image %s", outfn); exit(-1); } */ /* if (fits_write_float_image(coadd->img, coadd->W, coadd->H, outfn)) { ERROR("Failed to write output image %s", outfn); exit(-1); } */ { qfitsdumper qoutimg; qfits_header* hdr; hdr = anqfits_get_header2(outwcsfn, outwcsext); if (!hdr) { ERROR("Failed to read WCS file \"%s\" ext %i\n", outwcsfn, outwcsext); exit(-1); } fits_header_mod_int(hdr, "NAXIS", 2, NULL); fits_header_set_int(hdr, "NAXIS1", coadd->W, "image width"); fits_header_set_int(hdr, "NAXIS2", coadd->H, "image height"); fits_header_modf(hdr, "BITPIX", "-32", "32-bit floats"); memset(&qoutimg, 0, sizeof(qoutimg)); qoutimg.filename = outfn; qoutimg.npix = coadd->W * coadd->H; qoutimg.fbuf = coadd->img; qoutimg.ptype = PTYPE_FLOAT; qoutimg.out_ptype = BPP_IEEE_FLOAT; if (fits_write_header_and_image(NULL, &qoutimg, coadd->W)) { ERROR("Failed to write FITS image to file \"%s\"", outfn); exit(-1); } qfits_header_destroy(hdr); } coadd_free(coadd); sl_free2(inimgfns); sl_free2(inwcsfns); sl_free2(inwtfns); il_free(inimgexts); il_free(inwcsexts); il_free(inwtexts); anwcs_free(outwcs); return 0; }
int main(int argc, char** args) { int c; char* rdlsfn = NULL; char* wcsfn = NULL; char* xylsfn = NULL; char* rcol = NULL; char* dcol = NULL; anbool forcetan = FALSE; il* fields; int ext = 0; double ra=HUGE_VAL, dec=HUGE_VAL; anbool wcslib = FALSE; int loglvl = LOG_MSG; fields = il_new(16); while ((c = getopt(argc, args, OPTIONS)) != -1) { switch (c) { case 'v': loglvl++; break; case 'L': wcslib = TRUE; break; case 'r': ra = atof(optarg); break; case 'd': dec = atof(optarg); break; case 'e': ext = atoi(optarg); break; case 'h': print_help(args[0]); exit(0); case 't': forcetan = TRUE; break; case 'o': xylsfn = optarg; break; case 'i': rdlsfn = optarg; break; case 'w': wcsfn = optarg; break; case 'f': il_append(fields, atoi(optarg)); break; case 'R': rcol = optarg; break; case 'D': dcol = optarg; break; } } log_init(loglvl); if (optind != argc) { print_help(args[0]); exit(-1); } if (!(wcsfn && ((rdlsfn && xylsfn) || ((ra != HUGE_VAL) && (dec != HUGE_VAL))))) { print_help(args[0]); exit(-1); } if (!rdlsfn) { double x,y; anwcs_t* wcs = NULL; // read WCS. if (wcslib) { wcs = anwcs_open_wcslib(wcsfn, ext); } else if (forcetan) { wcs = anwcs_open_tan(wcsfn, ext); } else { wcs = anwcs_open(wcsfn, ext); } if (!wcs) { ERROR("Failed to read WCS file"); exit(-1); } logverb("Read WCS:\n"); if (log_get_level() >= LOG_VERB) { anwcs_print(wcs, log_get_fid()); } // convert immediately. if (anwcs_radec2pixelxy(wcs, ra, dec, &x, &y)) { ERROR("The given RA,Dec is on the opposite side of the sky."); exit(-1); } printf("RA,Dec (%.10f, %.10f) -> pixel (%.10f, %.10f)\n", ra, dec, x, y); anwcs_free(wcs); exit(0); } if (wcs_rd2xy(wcsfn, ext, rdlsfn, xylsfn, rcol, dcol, forcetan, wcslib, fields)) { ERROR("wcs-rd2xy failed"); exit(-1); } return 0; }
int main(int argc, char** args) { int c; FILE* fconst = NULL; uint32_t nstars; size_t mapsize; void* map; unsigned char* hip; FILE* fhip = NULL; int i; pl* cstars; il* alluniqstars; sl* shortnames; while ((c = getopt(argc, args, OPTIONS)) != -1) { switch (c) { case 'h': print_help(args[0]); exit(0); } } if (optind != argc) { print_help(args[0]); exit(-1); } for (i=0; i<sizeof(const_dirs)/sizeof(char*); i++) { char fn[256]; snprintf(fn, sizeof(fn), "%s/%s", const_dirs[i], constfn); fprintf(stderr, "render_constellation: Trying file: %s\n", fn); fconst = fopen(fn, "rb"); if (fconst) break; } if (!fconst) { fprintf(stderr, "render_constellation: couldn't open any constellation files.\n"); return -1; } for (i=0; i<sizeof(hip_dirs)/sizeof(char*); i++) { char fn[256]; snprintf(fn, sizeof(fn), "%s/%s", hip_dirs[i], hipparcos_fn); fprintf(stderr, "render_constellation: Trying hip file: %s\n", fn); fhip = fopen(fn, "rb"); if (fhip) break; } if (!fhip) { fprintf(stderr, "render_constellation: unhip\n"); return -1; } // first 32-bit int: if (fread(&nstars, 4, 1, fhip) != 1) { fprintf(stderr, "render_constellation: failed to read nstars.\n"); return -1; } v32_letoh(&nstars); fprintf(stderr, "render_constellation: Found %i Hipparcos stars\n", nstars); mapsize = nstars * HIP_SIZE + HIP_OFFSET; map = mmap(0, mapsize, PROT_READ, MAP_SHARED, fileno(fhip), 0); hip = ((unsigned char*)map) + HIP_OFFSET; // for each constellation, its il* of lines. cstars = pl_new(16); alluniqstars = il_new(16); shortnames = sl_new(16); for (c=0;; c++) { char shortname[16]; int nlines; int i; il* stars; if (feof(fconst)) break; if (fscanf(fconst, "%s %d ", shortname, &nlines) != 2) { fprintf(stderr, "failed to parse name+nlines (constellation %i)\n", c); fprintf(stderr, "file offset: %i (%x)\n", (int)ftello(fconst), (int)ftello(fconst)); return -1; } //fprintf(stderr, "Name: %s. Nlines %i.\n", shortname, nlines); stars = il_new(16); sl_append(shortnames, shortname); pl_append(cstars, stars); for (i=0; i<nlines; i++) { int star1, star2; if (fscanf(fconst, " %d %d", &star1, &star2) != 2) { fprintf(stderr, "failed parse star1+star2\n"); return -1; } il_insert_unique_ascending(alluniqstars, star1); il_insert_unique_ascending(alluniqstars, star2); il_append(stars, star1); il_append(stars, star2); } fscanf(fconst, "\n"); } fprintf(stderr, "render_constellations: Read %i constellations.\n", c); printf("static const int constellations_N = %i;\n", sl_size(shortnames)); /* for (c=0; c<sl_size(shortnames); c++) { printf("static const char* shortname_%i = \"%s\";\n", c, sl_get(shortnames, c)); } printf("static const char* shortnames[] = {"); for (c=0; c<sl_size(shortnames); c++) { printf("shortname_%i,", c); } printf("};\n"); */ printf("static const char* shortnames[] = {"); for (c=0; c<sl_size(shortnames); c++) { printf("\"%s\",", sl_get(shortnames, c)); } printf("};\n"); printf("static const int constellation_nlines[] = {"); for (c=0; c<pl_size(cstars); c++) { il* stars = pl_get(cstars, c); printf("%i,", il_size(stars)/2); } printf("};\n"); for (c=0; c<pl_size(cstars); c++) { il* stars = pl_get(cstars, c); printf("static const int constellation_lines_%i[] = {", c); for (i=0; i<il_size(stars); i++) { int s = il_get(stars, i); int ms = il_index_of(alluniqstars, s); printf("%s%i", (i?",":""), ms); } printf("};\n"); } printf("static const int* constellation_lines[] = {"); for (c=0; c<pl_size(cstars); c++) { printf("constellation_lines_%i,", c); } printf("};\n"); printf("static const int stars_N = %i;\n", il_size(alluniqstars)); printf("static const double star_positions[] = {"); for (i=0; i<il_size(alluniqstars); i++) { int s = il_get(alluniqstars, i); double ra, dec; hip_get_radec(hip, s, &ra, &dec); printf("%g,%g,", ra, dec); } printf("};\n"); munmap(map, mapsize); fclose(fconst); fclose(fhip); return 0; }
int wcs_rd2xy(const char* wcsfn, int wcsext, const char* rdlsfn, const char* xylsfn, const char* racol, const char* deccol, anbool forcetan, anbool forcewcslib, il* fields) { xylist_t* xyls = NULL; rdlist_t* rdls = NULL; anwcs_t* wcs = NULL; int i; anbool alloced_fields = FALSE; int rtn = -1; // read WCS. if (forcewcslib) { wcs = anwcs_open_wcslib(wcsfn, wcsext); } else if (forcetan) { wcs = anwcs_open_tan(wcsfn, wcsext); } else { wcs = anwcs_open(wcsfn, wcsext); } if (!wcs) { ERROR("Failed to read WCS file \"%s\", extension %i", wcsfn, wcsext); return -1; } // read RDLS. rdls = rdlist_open(rdlsfn); if (!rdls) { ERROR("Failed to read an RA,Dec list from file %s", rdlsfn); goto bailout; } if (racol) rdlist_set_raname(rdls, racol); if (deccol) rdlist_set_decname(rdls, deccol); // write XYLS. xyls = xylist_open_for_writing(xylsfn); if (!xyls) { ERROR("Failed to open file %s to write XYLS", xylsfn); goto bailout; } if (xylist_write_primary_header(xyls)) { ERROR("Failed to write header to XYLS file %s", xylsfn); goto bailout; } if (!fields) { alloced_fields = TRUE; fields = il_new(16); } if (!il_size(fields)) { // add all fields. int NF = rdlist_n_fields(rdls); for (i=1; i<=NF; i++) il_append(fields, i); } for (i=0; i<il_size(fields); i++) { int fieldnum = il_get(fields, i); int j; starxy_t xy; rd_t rd; if (!rdlist_read_field_num(rdls, fieldnum, &rd)) { ERROR("Failed to read rdls file \"%s\" field %i", rdlsfn, fieldnum); goto bailout; } starxy_alloc_data(&xy, rd_n(&rd), FALSE, FALSE); if (xylist_write_header(xyls)) { ERROR("Failed to write xyls field header"); goto bailout; } for (j=0; j<rd_n(&rd); j++) { double x, y, ra, dec; ra = rd_getra (&rd, j); dec = rd_getdec(&rd, j); if (anwcs_radec2pixelxy(wcs, ra, dec, &x, &y)) { ERROR("Point RA,Dec = (%g,%g) projects to the opposite side of the sphere", ra, dec); starxy_set(&xy, j, NAN, NAN); continue; } starxy_set(&xy, j, x, y); } if (xylist_write_field(xyls, &xy)) { ERROR("Failed to write xyls field"); goto bailout; } if (xylist_fix_header(xyls)) { ERROR("Failed to fix xyls field header"); goto bailout; } xylist_next_field(xyls); starxy_free_data(&xy); rd_free_data(&rd); } if (xylist_fix_primary_header(xyls) || xylist_close(xyls)) { ERROR("Failed to fix header of XYLS file"); goto bailout; } xyls = NULL; if (rdlist_close(rdls)) { ERROR("Failed to close RDLS file"); goto bailout; } rdls = NULL; rtn = 0; bailout: if (alloced_fields) il_free(fields); if (rdls) rdlist_close(rdls); if (xyls) xylist_close(xyls); if (wcs) anwcs_free(wcs); return rtn; }
int main(int argc, char** args) { int c; char* rdlsfn = NULL; char* wcsfn = NULL; char* xylsfn = NULL; char* xcol = NULL; char* ycol = NULL; anbool forcetan = FALSE; anbool forcewcslib = FALSE; anbool forcewcstools = FALSE; anbool printhms = FALSE; il* fields; int ext = 0; double x, y; int loglvl = LOG_MSG; x = y = HUGE_VAL; fields = il_new(16); while ((c = getopt(argc, args, OPTIONS)) != -1) { switch (c) { case 'v': loglvl++; break; case 's': printhms = TRUE; break; case 'L': forcewcslib = TRUE; break; case 'T': forcewcstools = TRUE; break; case 'x': x = atof(optarg); break; case 'y': y = atof(optarg); break; case 'e': ext = atoi(optarg); break; case 'h': print_help(args[0]); exit(0); case 't': forcetan = TRUE; break; case 'o': rdlsfn = optarg; break; case 'i': xylsfn = optarg; break; case 'w': wcsfn = optarg; break; case 'f': il_append(fields, atoi(optarg)); break; case 'X': xcol = optarg; break; case 'Y': ycol = optarg; break; } } log_init(loglvl); if (optind != argc) { print_help(args[0]); exit(-1); } if (!(wcsfn && ((rdlsfn && xylsfn) || ((x != HUGE_VAL) && (y != HUGE_VAL))))) { print_help(args[0]); exit(-1); } if (!xylsfn) { double ra,dec; anwcs_t* wcs = NULL; // read WCS. if (forcewcslib) { wcs = anwcs_open_wcslib(wcsfn, ext); } else if (forcewcstools) { wcs = anwcs_open_wcstools(wcsfn, ext); } else if (forcetan) { wcs = anwcs_open_tan(wcsfn, ext); } else { wcs = anwcs_open(wcsfn, ext); } if (!wcs) { ERROR("Failed to read WCS file \"%s\", extension %i", wcsfn, ext); exit(-1); } logverb("Read WCS:\n"); if (log_get_level() >= LOG_VERB) { anwcs_print(wcs, log_get_fid()); } // convert immediately. anwcs_pixelxy2radec(wcs, x, y, &ra, &dec); printf("Pixel (%.10f, %.10f) -> RA,Dec (%.10f, %.10f)\n", x, y, ra, dec); if (printhms) { char str[32]; ra2hmsstring(ra, str); printf(" RA,Dec (%20s, ", str); dec2dmsstring(dec, str); printf("%20s)\n", str); } anwcs_free(wcs); exit(0); } if (wcs_xy2rd(wcsfn, ext, xylsfn, rdlsfn, xcol, ycol, forcetan, forcewcslib, fields)) { ERROR("wcs-xy2rd failed"); exit(-1); } 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); }
int DFIND2(const IMGTYPE* image, int nx, int ny, int* object, int* pnobjects) { int ix, iy, i; int maxgroups = initial_max_groups; label_t *equivs = malloc(sizeof(label_t) * maxgroups); int maxlabel = 0; /* Keep track of 'on' pixels to avoid later rescanning */ il* on_pixels = il_new(256); /* Find blobs and track equivalences */ for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { int thislabel, thislabelmin; object[nx*iy+ix] = -1; if (!image[nx*iy+ix]) continue; /* Store location of each 'on' pixel. */ il_append(on_pixels, nx * iy + ix); /* If the pixel to the left [exists and] is on, this pixel joins its group. */ if (ix && image[nx*iy+ix-1]) { /* Old group */ object[nx*iy+ix] = object[nx*iy+ix-1]; } else { /* New blob */ // FIXME this part should become uf_new_group() if (maxlabel >= maxgroups) { maxgroups *= 2; equivs = realloc(equivs, sizeof(label_t) * maxgroups); assert(equivs); } object[nx*iy+ix] = maxlabel; equivs[maxlabel] = maxlabel; maxlabel++; if (maxlabel == LABEL_MAX) { logverb("Ran out of labels. Relabelling...\n"); maxlabel = relabel_image(on_pixels, maxlabel, equivs, object); logverb("After relabelling, we need %i labels\n", maxlabel); if (maxlabel == LABEL_MAX) { ERROR("Ran out of labels."); exit(-1); } } } thislabel = object[nx*iy + ix]; /* Compute minimum equivalence label for this pixel */ thislabelmin = collapsing_find_minlabel(thislabel, equivs); if (iy == 0) continue; /* Check three pixels above this one which are 'neighbours' */ for (i = MAX(0, ix - 1); i <= MIN(ix + 1, nx - 1); i++) { if (image[nx*(iy-1)+i]) { int otherlabel = object[nx*(iy-1) + i]; /* Find min of the other */ int otherlabelmin = collapsing_find_minlabel(otherlabel, equivs); /* Merge groups if necessary */ if (thislabelmin != otherlabelmin) { int oldlabelmin = MAX(thislabelmin, otherlabelmin); int newlabelmin = MIN(thislabelmin, otherlabelmin); thislabelmin = newlabelmin; equivs[oldlabelmin] = newlabelmin; equivs[thislabel] = newlabelmin; /* Update other pixel too */ object[nx*(iy-1) + i] = newlabelmin; } } } object[nx*iy + ix] = thislabelmin; } } /* Re-label the groups before returning */ maxlabel = relabel_image(on_pixels, maxlabel, equivs, object); //logverb("After final relabelling, %i labels were used.\n", maxlabel); if (pnobjects) *pnobjects = maxlabel; free(equivs); il_free(on_pixels); return 1; }
// lastfield = 0 for no limit. static il* solvedfile_getall_val(char* fn, int firstfield, int lastfield, int maxfields, int val) { FILE* f; off_t end; int fields = 0; il* list; int i; unsigned char* map; list = il_new(256); f = fopen(fn, "rb"); if (!f) { // if file doesn't exist, assume no fields are solved. if (val == 0) { for (i=firstfield; i<=lastfield; i++) { il_append(list, i); fields++; if (fields == maxfields) break; } } return list; } if (fseek(f, 0, SEEK_END) || ((end = ftello(f)) == -1)) { fprintf(stderr, "Error: seeking to end of file %s: %s\n", fn, strerror(errno)); fclose(f); il_free(list); return NULL; } // 1-index firstfield--; lastfield--; if (end <= firstfield) { fclose(f); return list; } map = mmap(NULL, end, PROT_READ, MAP_SHARED, fileno(f), 0); fclose(f); if (map == MAP_FAILED) { fprintf(stderr, "Error: couldn't mmap file %s: %s\n", fn, strerror(errno)); il_free(list); return NULL; } for (i=firstfield; ((lastfield == -1) || (i<=lastfield)) && (i < end); i++) { if (map[i] == val) { // 1-index il_append(list, i+1); if (il_size(list) == maxfields) break; } } munmap(map, end); if (val == 0) { // fields larger than the file size are unsolved. for (i=end; i<=lastfield; i++) { if (il_size(list) == maxfields) break; // 1-index il_append(list, i+1); } } return list; }
void test_big_list(CuTest* tc) { // Test size_t sizes and indices of bl's. // Test ptrdiff_t as -1 or index CuAssertTrue(tc, -1 == BL_NOT_FOUND); CuAssertTrue(tc, BL_NOT_FOUND < 0); CuAssertTrue(tc, sizeof(size_t) == sizeof(ptrdiff_t)); // Create a fake list so we don't have to allocate 16 GB of list to test. int blocksize = 1048576; il* big = il_new(blocksize); // that's 1<<20 ~ 1e6 elements per block // now need 1<<12 ~ 4096 blocks to overflow a 32-bit int int i; int N = 4096; bl_node* nodes = calloc(N, sizeof(bl_node)); for (i=1; i<N; i++) { nodes[i-1].next = nodes+i; nodes[i-1].N = blocksize; } nodes[N-1].N = blocksize; big->head = nodes; big->tail = nodes + (N-1); big->N = (size_t)blocksize * (size_t)N; bl_print_structure(big); printf("N %zu\n", il_size(big)); printf("check: %s\n", (bl_check_consistency(big) ? "bad" : "ok")); int* p = il_append(big, 42); printf("appended: %i\n", *p); CuAssertIntEquals(tc, 42, *p); CuAssertTrue(tc, 4294967297L == il_size(big)); size_t index = 4294967296L; int v = il_get(big, index); CuAssertIntEquals(tc, 42, v); big->last_access = NULL; big->last_access_n = 0; v = il_get(big, index); CuAssertIntEquals(tc, 42, v); for (i=0; i<blocksize*2; i++) { il_push(big, i); } il* split = il_new(1024); bl_split(big, split, (size_t)blocksize * (size_t)N); printf("split: %zu, %zu\n", il_size(big), il_size(split)); CuAssertIntEquals(tc, 42, il_get(split, 0)); CuAssertIntEquals(tc, 3, il_get(split, 4)); il_append_list(big, split); CuAssertTrue(tc, 4297064449L == il_size(big)); int* arr = calloc(1024, sizeof(int)); bl_copy(big, (size_t)blocksize * (size_t)N, 1024, arr); CuAssertIntEquals(tc, 42, arr[0]); CuAssertIntEquals(tc, 3, arr[4]); }
int wcs_xy2rd(const char* wcsfn, int ext, const char* xylsfn, const char* rdlsfn, const char* xcol, const char* ycol, int forcetan, int forcewcslib, il* fields) { rdlist_t* rdls = NULL; xylist_t* xyls = NULL; anwcs_t* wcs = NULL; int i; int rtn = -1; anbool alloced_fields = FALSE; // read WCS. if (forcewcslib) { wcs = anwcs_open_wcslib(wcsfn, ext); } else if (forcetan) { wcs = anwcs_open_tan(wcsfn, ext); } else { wcs = anwcs_open(wcsfn, ext); } if (!wcs) { ERROR("Failed to read WCS file \"%s\", extension %i", wcsfn, ext); return -1; } // read XYLS. xyls = xylist_open(xylsfn); if (!xyls) { ERROR("Failed to read an xylist from file %s", xylsfn); goto bailout; } xylist_set_include_flux(xyls, FALSE); xylist_set_include_background(xyls, FALSE); if (xcol) xylist_set_xname(xyls, xcol); if (ycol) xylist_set_yname(xyls, ycol); // write RDLS. rdls = rdlist_open_for_writing(rdlsfn); if (!rdls) { ERROR("Failed to open file %s to write RDLS.\n", rdlsfn); goto bailout; } if (rdlist_write_primary_header(rdls)) { ERROR("Failed to write header to RDLS file %s.\n", rdlsfn); goto bailout; } if (!fields) { alloced_fields = TRUE; fields = il_new(16); } if (!il_size(fields)) { // add all fields. int NF = xylist_n_fields(xyls); for (i=1; i<=NF; i++) il_append(fields, i); } logverb("Processing %zu extensions...\n", il_size(fields)); for (i=0; i<il_size(fields); i++) { int fieldind = il_get(fields, i); starxy_t xy; rd_t rd; int j; if (!xylist_read_field_num(xyls, fieldind, &xy)) { ERROR("Failed to read xyls file %s, field %i", xylsfn, fieldind); goto bailout; } if (rdlist_write_header(rdls)) { ERROR("Failed to write rdls field header to %s", rdlsfn); goto bailout; } rd_alloc_data(&rd, starxy_n(&xy)); for (j=0; j<starxy_n(&xy); j++) { double x, y, ra, dec; x = starxy_getx(&xy, j); y = starxy_gety(&xy, j); anwcs_pixelxy2radec(wcs, x, y, &ra, &dec); rd_setra (&rd, j, ra); rd_setdec(&rd, j, dec); } if (rdlist_write_field(rdls, &rd)) { ERROR("Failed to write rdls field to %s", rdlsfn); goto bailout; } rd_free_data(&rd); starxy_free_data(&xy); if (rdlist_fix_header(rdls)) { ERROR("Failed to fix rdls field header for %s", rdlsfn); goto bailout; } rdlist_next_field(rdls); } if (rdlist_fix_primary_header(rdls) || rdlist_close(rdls)) { ERROR("Failed to fix header of RDLS file %s", rdlsfn); goto bailout; } rdls = NULL; if (xylist_close(xyls)) { ERROR("Failed to close XYLS file %s", xylsfn); goto bailout; } xyls = NULL; rtn = 0; bailout: if (alloced_fields) il_free(fields); if (rdls) rdlist_close(rdls); if (xyls) xylist_close(xyls); if (wcs) anwcs_free(wcs); return rtn; }
int wcs_pv2sip(const char* wcsinfn, int ext, const char* wcsoutfn, anbool scamp_head_file, double* xy, int Nxy, int imageW, int imageH, anbool forcetan) { qfits_header* hdr = NULL; double* radec = NULL; int rtn = -1; tan_t tanwcs; double x,y, px,py; double xyz[3]; double* xorig = NULL; double* yorig = NULL; double* rddist = NULL; int i, j; // 1 x y r x2 xy y2 x3 x2y xy2 y3 r3 x4 x3y x2y2 xy3 y4 // x5 x4y x3y2 x2y3 xy4 y5 r5 x6 x5y x4y2, x3y3 x2y4 xy5 y6 // x7 x6y x5y2 x4y3 x3y4 x2y5 xy6 y7 r7 int xp[] = { 0, 1, 0, 0, 2, 1, 0, 3, 2, 1, 0, 0, 4, 3, 2, 1, 0, 5, 4, 3, 2, 1, 5, 0, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 0}; int yp[] = { 0, 0, 1, 0, 0, 1, 2, 0, 1, 2, 3, 0, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 0, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7, 0}; int rp[] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7}; double xpows[8]; double ypows[8]; double rpows[8]; double pv1[40]; double pv2[40]; double r; if (scamp_head_file) { size_t sz = 0; char* txt; char* prefix; int np; int nt; unsigned char* txthdr; sl* lines; int i; txt = file_get_contents(wcsinfn, &sz, TRUE); if (!txt) { ERROR("Failed to read file %s", wcsinfn); goto bailout; } lines = sl_split(NULL, txt, "\n"); prefix = "SIMPLE = T / Standard FITS file " "BITPIX = 8 / ASCII or bytes array " "NAXIS = 0 / Minimal header " "EXTEND = T / There may be FITS ext " "WCSAXES = 2 / "; np = strlen(prefix); nt = np + FITS_LINESZ * sl_size(lines); txthdr = malloc(nt); memset(txthdr, ' ', np + FITS_LINESZ * sl_size(lines)); memcpy(txthdr, prefix, np); for (i=0; i<sl_size(lines); i++) memcpy(txthdr + np + i*FITS_LINESZ, sl_get(lines, i), strlen(sl_get(lines, i))); sl_free2(lines); hdr = qfits_header_read_hdr_string(txthdr, nt); free(txthdr); free(txt); } else { char* ct; hdr = anqfits_get_header2(wcsinfn, ext); ct = fits_get_dupstring(hdr, "CTYPE1"); if ((ct && streq(ct, "RA---TPV")) || forcetan) { // http://iraf.noao.edu/projects/ccdmosaic/tpv.html logmsg("Replacing CTYPE1 = %s header with RA---TAN\n", ct); fits_update_value(hdr, "CTYPE1", "RA---TAN"); } ct = fits_get_dupstring(hdr, "CTYPE2"); if ((ct && streq(ct, "DEC--TPV")) || forcetan) { logmsg("Replacing CTYPE2 = %s header with DEC--TAN\n", ct); fits_update_value(hdr, "CTYPE2", "DEC--TAN"); } } if (!hdr) { ERROR("Failed to read header: file %s, ext %i\n", wcsinfn, ext); goto bailout; } tan_read_header(hdr, &tanwcs); for (i=0; i<sizeof(pv1)/sizeof(double); i++) { char key[10]; sprintf(key, "PV1_%i", i); pv1[i] = qfits_header_getdouble(hdr, key, 0.0); sprintf(key, "PV2_%i", i); pv2[i] = qfits_header_getdouble(hdr, key, 0.0); } xorig = malloc(Nxy * sizeof(double)); yorig = malloc(Nxy * sizeof(double)); rddist = malloc(2 * Nxy * sizeof(double)); for (j=0; j<Nxy; j++) { xorig[j] = xy[2*j+0]; yorig[j] = xy[2*j+1]; tan_pixelxy2iwc(&tanwcs, xorig[j], yorig[j], &x, &y); r = sqrt(x*x + y*y); xpows[0] = ypows[0] = rpows[0] = 1.0; for (i=1; i<sizeof(xpows)/sizeof(double); i++) { xpows[i] = xpows[i-1]*x; ypows[i] = ypows[i-1]*y; rpows[i] = rpows[i-1]*r; } px = py = 0; for (i=0; i<sizeof(xp)/sizeof(int); i++) { px += pv1[i] * xpows[xp[i]] * ypows[yp[i]] * rpows[rp[i]]; py += pv2[i] * ypows[xp[i]] * xpows[yp[i]] * rpows[rp[i]]; } tan_iwc2xyzarr(&tanwcs, px, py, xyz); xyzarr2radecdeg(xyz, rddist+2*j, rddist+2*j+1); } // { starxy_t sxy; tweak_t* t; il* imgi; il* refi; int sip_order = 5; int sip_inv_order = 5; sxy.N = Nxy; sxy.x = xorig; sxy.y = yorig; imgi = il_new(256); refi = il_new(256); for (i=0; i<Nxy; i++) { il_append(imgi, i); il_append(refi, i); } t = tweak_new(); t->sip->a_order = t->sip->b_order = sip_order; t->sip->ap_order = t->sip->bp_order = sip_inv_order; tweak_push_wcs_tan(t, &tanwcs); tweak_push_ref_ad_array(t, rddist, Nxy); tweak_push_image_xy(t, &sxy); tweak_push_correspondence_indices(t, imgi, refi, NULL, NULL); tweak_go_to(t, TWEAK_HAS_LINEAR_CD); if (imageW) t->sip->wcstan.imagew = imageW; if (imageH) t->sip->wcstan.imageh = imageH; sip_write_to_file(t->sip, wcsoutfn); tweak_free(t); } rtn = 0; bailout: free(xorig); free(yorig); free(rddist); qfits_header_destroy(hdr); free(radec); return rtn; }
int main(int argc, char** args) { int c; dl* xys = dl_new(16); dl* radecs = dl_new(16); dl* otherradecs = dl_new(16); double* xy; double* xyz; int i, N; tan_t tan, tan2, tan3; int W=0, H=0; double crpix[] = { HUGE_VAL, HUGE_VAL }; int loglvl = LOG_MSG; FILE* logstream = stderr; int order = 1; while ((c = getopt(argc, args, OPTIONS)) != -1) { switch (c) { case 'v': loglvl++; break; case 'h': exit(0); case 'o': order = atoi(optarg); break; case 'W': W = atoi(optarg); break; case 'H': H = atoi(optarg); break; case 'X': crpix[0] = atof(optarg); break; case 'Y': crpix[1] = atof(optarg); break; } } if (optind != argc) { exit(-1); } log_init(loglvl); log_to(logstream); errors_log_to(logstream); if (W == 0 || H == 0) { logerr("Need -W, -H\n"); exit(-1); } if (crpix[0] == HUGE_VAL) crpix[0] = W/2.0; if (crpix[1] == HUGE_VAL) crpix[1] = H/2.0; while (1) { double x,y,ra,dec; if (fscanf(stdin, "%lf %lf %lf %lf\n", &x, &y, &ra, &dec) < 4) break; if (x == -1 && y == -1) { dl_append(otherradecs, ra); dl_append(otherradecs, dec); } else { dl_append(xys, x); dl_append(xys, y); dl_append(radecs, ra); dl_append(radecs, dec); } } logmsg("Read %i x,y,ra,dec tuples\n", dl_size(xys)/2); N = dl_size(xys)/2; xy = dl_to_array(xys); xyz = malloc(3 * N * sizeof(double)); for (i=0; i<N; i++) radecdeg2xyzarr(dl_get(radecs, 2*i), dl_get(radecs, 2*i+1), xyz + i*3); dl_free(xys); dl_free(radecs); fit_tan_wcs(xyz, xy, N, &tan, NULL); tan.imagew = W; tan.imageh = H; logmsg("Computed TAN WCS:\n"); tan_print_to(&tan, logstream); sip_t* sip; { tweak_t* t = tweak_new(); starxy_t* sxy = starxy_new(N, FALSE, FALSE); il* imginds = il_new(256); il* refinds = il_new(256); for (i=0; i<N; i++) { starxy_set_x(sxy, i, xy[2*i+0]); starxy_set_y(sxy, i, xy[2*i+1]); } tweak_init(t); tweak_push_ref_xyz(t, xyz, N); tweak_push_image_xy(t, sxy); for (i=0; i<N; i++) { il_append(imginds, i); il_append(refinds, i); } // unweighted; no dist2s tweak_push_correspondence_indices(t, imginds, refinds, NULL, NULL); tweak_push_wcs_tan(t, &tan); t->sip->a_order = t->sip->b_order = t->sip->ap_order = t->sip->bp_order = order; for (i=0; i<10; i++) { // go to TWEAK_HAS_LINEAR_CD -> do_sip_tweak // t->image has the indices of corresponding image stars // t->ref has the indices of corresponding catalog stars tweak_go_to(t, TWEAK_HAS_LINEAR_CD); logmsg("\n"); sip_print(t->sip); t->state &= ~TWEAK_HAS_LINEAR_CD; } tan_write_to_file(&t->sip->wcstan, "kt1.wcs"); sip = t->sip; } for (i=0; i<dl_size(otherradecs)/2; i++) { double ra, dec, x,y; ra = dl_get(otherradecs, 2*i); dec = dl_get(otherradecs, 2*i+1); if (!sip_radec2pixelxy(sip, ra, dec, &x, &y)) { logerr("Not in tangent plane: %g,%g\n", ra, dec); exit(-1); //continue; } printf("%g %g\n", x, y); } /* blind_wcs_move_tangent_point(xyz, xy, N, crpix, &tan, &tan2); blind_wcs_move_tangent_point(xyz, xy, N, crpix, &tan2, &tan3); logmsg("Moved tangent point to (%g,%g):\n", crpix[0], crpix[1]); tan_print_to(&tan3, logstream); tan_write_to_file(&tan, "kt1.wcs"); tan_write_to_file(&tan3, "kt2.wcs"); */ dl_free(otherradecs); free(xy); free(xyz); return 0; }
static sip_t* run_test(CuTest* tc, sip_t* sip, int N, double* xy, double* radec) { int i; starxy_t* sxy; tweak_t* t; sip_t* outsip; il* imcorr; il* refcorr; dl* weights; tan_t* tan = &(sip->wcstan); printf("Input SIP:\n"); sip_print_to(sip, stdout); fflush(NULL); sxy = starxy_new(N, FALSE, FALSE); starxy_set_xy_array(sxy, xy); imcorr = il_new(256); refcorr = il_new(256); weights = dl_new(256); for (i=0; i<N; i++) { il_append(imcorr, i); il_append(refcorr, i); dl_append(weights, 1.0); } t = tweak_new(); tweak_push_wcs_tan(t, tan); outsip = t->sip; outsip->a_order = outsip->b_order = sip->a_order; outsip->ap_order = outsip->bp_order = sip->ap_order; t->weighted_fit = TRUE; tweak_push_ref_ad_array(t, radec, N); tweak_push_image_xy(t, sxy); tweak_push_correspondence_indices(t, imcorr, refcorr, NULL, weights); tweak_skip_shift(t); // push correspondences // push image xy // push ref ra,dec // push ref xy (tan) // push tan tweak_go_to(t, TWEAK_HAS_LINEAR_CD); printf("Output SIP:\n"); sip_print_to(outsip, stdout); CuAssertDblEquals(tc, tan->imagew, outsip->wcstan.imagew, 1e-10); CuAssertDblEquals(tc, tan->imageh, outsip->wcstan.imageh, 1e-10); // should be exactly equal. CuAssertDblEquals(tc, tan->crpix[0], outsip->wcstan.crpix[0], 1e-10); CuAssertDblEquals(tc, tan->crpix[1], outsip->wcstan.crpix[1], 1e-10); t->sip = NULL; tweak_free(t); starxy_free(sxy); return outsip; }
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** args) { int argchar; kdtree_t* kd; int Nleaf = 25; char* infn = NULL; char* outfn = NULL; char* tychofn = NULL; char* crossfn = NULL; char* progname = args[0]; FILE* f; tycstar_t* tycstars = NULL; int Ntyc = 0; int exttype = KDT_EXT_DOUBLE; int datatype = KDT_DATA_U32; int treetype = KDT_TREE_U32; int tt; int buildopts = 0; int i, N, D; dl* ras; dl* decs; dl* hds; fl* mag1s; fl* mag2s; fl* mag3s; int nbad = 0; int nox = 0; int* hd; double* xyz; qfits_header* hdr; while ((argchar = getopt (argc, args, OPTIONS)) != -1) switch (argchar) { case 'T': tychofn = optarg; break; case 'X': crossfn = optarg; break; case 'R': Nleaf = (int)strtoul(optarg, NULL, 0); break; case 't': treetype = kdtree_kdtype_parse_tree_string(optarg); break; case 'd': datatype = kdtree_kdtype_parse_data_string(optarg); break; case 'b': buildopts |= KD_BUILD_BBOX; break; case 's': buildopts |= KD_BUILD_SPLIT; break; case 'S': buildopts |= KD_BUILD_SPLITDIM; break; case '?': fprintf(stderr, "Unknown option `-%c'.\n", optopt); case 'h': printHelp(progname); return 0; default: return -1; } if (optind != argc - 2) { printHelp(progname); exit(-1); } infn = args[optind]; outfn = args[optind+1]; if (!(buildopts & (KD_BUILD_BBOX | KD_BUILD_SPLIT))) { printf("You need bounding-boxes or splitting planes!\n"); printHelp(progname); exit(-1); } if (tychofn || crossfn) { if (!(tychofn && crossfn)) { printf("You need both -T <Tycho2> and -X <Crossref> to do cross-referencing.\n"); exit(-1); } } if (tychofn) { int i, N; tycho2_fits* tyc; FILE* f; int nx, nox; int lastgrass = 0; tyc = tycho2_fits_open(tychofn); if (!tyc) { ERROR("Failed to open Tycho-2 catalog."); exit(-1); } printf("Reading Tycho-2 catalog...\n"); N = tycho2_fits_count_entries(tyc); tycstars = calloc(N, sizeof(tycstar_t)); for (i=0; i<N; i++) { tycho2_entry* te; int grass = (i*80 / N); if (grass != lastgrass) { printf("."); fflush(stdout); lastgrass = grass; } te = tycho2_fits_read_entry(tyc); tycstars[i].tyc1 = te->tyc1; tycstars[i].tyc2 = te->tyc2; tycstars[i].tyc3 = te->tyc3; tycstars[i].ra = te->ra; tycstars[i].dec = te->dec; tycstars[i].mag_BT = te->mag_BT; tycstars[i].mag_VT = te->mag_VT; tycstars[i].mag_HP = te->mag_HP; } tycho2_fits_close(tyc); printf("Sorting...\n"); qsort(tycstars, N, sizeof(tycstar_t), compare_tycs); Ntyc = N; f = fopen(crossfn, "rb"); if (!f) { SYSERROR("Failed to open cross-reference file %s", crossfn); exit(-1); } nx = 0; nox = 0; while (TRUE) { char buf[1024]; int tyc1, tyc2, tyc3, hd, nhd, ntyc; char ftyc, sptype0, sptype1, sptype2; tycstar_t* s; if (!fgets(buf, sizeof(buf), f)) { if (ferror(f)) { SYSERROR("Failed to read a line of text from the cross-reference file"); exit(-1); } break; } if (sscanf(buf, " %d %d %d%c %d %c%c%c %d %d", &tyc1, &tyc2, &tyc3, &ftyc, &hd, &sptype0, &sptype1, &sptype2, &nhd, &ntyc) != 10) { ERROR("Failed to parse line: \"%s\"", buf); } //printf("%i %i %i %i %i %i\n", tyc1, tyc2, tyc3, hd, nhd, ntyc); s = find_tycho(tycstars, Ntyc, tyc1, tyc2, tyc3); if (!s) { ERROR("Failed to find Tycho-2 star %i-%i-%i", tyc1, tyc2, tyc3); nox++; } else { s->hd = hd; s->ntyc = ntyc; } nx++; } fclose(f); printf("Read %i cross-references.\n", nx); printf("Failed to find %i cross-referenced Tycho-2 stars.\n", nox); printf("Sorting...\n"); qsort(tycstars, N, sizeof(tycstar_t), compare_hds); } f = fopen(infn, "rb"); if (!f) { SYSERROR("Failed to open input file %s", infn); exit(-1); } ras = dl_new(1024); decs = dl_new(1024); hds = il_new(1024); mag1s = fl_new(1024); mag2s = fl_new(1024); mag3s = fl_new(1024); printf("Reading HD catalog...\n"); for (;;) { char buf[1024]; double ra, dec; int hd; float mag1, mag2, mag3; mag1 = mag2 = mag3 = 0.0; if (!fgets(buf, sizeof(buf), f)) { if (ferror(f)) { SYSERROR("Failed to read a line of text from the input file"); exit(-1); } break; } if (buf[0] == '#') continue; if (buf[0] == '\n') continue; if (sscanf(buf, " %lf| %lf| %d", &ra, &dec, &hd) < 3) { // ignore three invalid lines if (nbad > 3) { ERROR("Failed to parse line: \"%s\"", buf); } nbad++; } else { if (tycstars) { tycstar_t* s = find_hd(tycstars, Ntyc, hd); if (!s) { //printf("Failed to find cross-ref for HD %i\n", hd); nox++; } else { ra = s->ra; dec = s->dec; mag1 = s->mag_VT; mag2 = s->mag_BT; mag3 = s->mag_HP; } } dl_append(ras, ra); dl_append(decs, dec); il_append(hds, hd); fl_append(mag1s, mag1); fl_append(mag2s, mag2); fl_append(mag3s, mag3); } } fclose(f); N = dl_size(ras); printf("Read %i entries and %i bad lines.\n", N, nbad); if (dl_size(ras) != HD_NENTRIES) { printf("WARNING: expected %i Henry Draper catalog entries.\n", HD_NENTRIES); } if (nox) { printf("Found %i HD entries with no cross-reference (expect this to be about 1%%)\n", nox); } hd = malloc(sizeof(int) * N); il_copy(hds, 0, N, hd); il_free(hds); for (i=0; i<N; i++) if (hd[i] != i+1) { printf("Line %i is HD %i\n", i+1, hd[i]); break; } // HACK - don't allocate 'em in the first place... free(hd); xyz = malloc(sizeof(double) * 3 * N); for (i=0; i<N; i++) { radecdeg2xyzarr(dl_get(ras, i), dl_get(decs, i), xyz + 3*i); } dl_free(ras); dl_free(decs); tt = kdtree_kdtypes_to_treetype(exttype, treetype, datatype); D = 3; { // limits of the kdtree... double lo[] = {-1.0, -1.0, -1.0}; double hi[] = { 1.0, 1.0, 1.0}; kd = kdtree_new(N, D, Nleaf); kdtree_set_limits(kd, lo, hi); } printf("Building tree...\n"); kd = kdtree_build(kd, xyz, N, D, Nleaf, tt, buildopts); hdr = qfits_header_default(); qfits_header_add(hdr, "AN_FILE", "HDTREE", "Henry Draper catalog kdtree", NULL); BOILERPLATE_ADD_FITS_HEADERS(hdr); fits_add_long_history(hdr, "This file was created by the following command-line:"); fits_add_args(hdr, args, argc); if (kdtree_fits_write(kd, outfn, hdr)) { ERROR("Failed to write kdtree"); exit(-1); } // Write mags as tag-along table. { fitstable_t* tag; tag = fitstable_open_for_appending(outfn); if (!tag) { ERROR("Failed to open kd-tree file for appending"); exit(-1); } fitstable_add_write_column(tag, fitscolumn_float_type(), "MAG_VT", ""); fitstable_add_write_column(tag, fitscolumn_float_type(), "MAG_BT", ""); fitstable_add_write_column(tag, fitscolumn_float_type(), "MAG_HP", ""); if (fitstable_write_header(tag)) { ERROR("Failed to write tag-along header"); exit(-1); } for (i=0; i<N; i++) { fitstable_write_row(tag, fl_get(mag1s, i), fl_get(mag2s, i), fl_get(mag3s, i)); } if (fitstable_fix_header(tag)) { ERROR("Failed to fix tag-along header"); exit(-1); } if (fitstable_close(tag)) { ERROR("Failed to close tag-along data"); exit(-1); } } fl_free(mag1s); fl_free(mag2s); fl_free(mag3s); printf("Done.\n"); qfits_header_destroy(hdr); free(xyz); kdtree_free(kd); free(tycstars); return 0; }