static int plot_annotations(augment_xylist_t* axy, const char* me, anbool verbose, const char* annfn, double plotscale, const char* bgfn) { sl* cmdline = sl_new(16); char* cmd; sl* lines; char* imgfn; imgfn = axy->pnmfn; if (bgfn) { append_executable(cmdline, "jpegtopnm", me); append_escape(cmdline, bgfn); sl_append(cmdline, "|"); imgfn = "-"; } else if (axy->imagefn && plotscale != 1.0) { append_executable(cmdline, "pnmscale", me); sl_appendf(cmdline, "%f", plotscale); append_escape(cmdline, axy->pnmfn); sl_append(cmdline, "|"); imgfn = "-"; } append_executable(cmdline, "plot-constellations", me); if (verbose) sl_append(cmdline, "-v"); sl_append(cmdline, "-w"); assert(axy->wcsfn); append_escape(cmdline, axy->wcsfn); sl_append(cmdline, "-i"); append_escape(cmdline, imgfn); if (plotscale != 1.0) { sl_append(cmdline, "-s"); sl_appendf(cmdline, "%f", plotscale); } sl_append(cmdline, "-N"); sl_append(cmdline, "-B"); sl_append(cmdline, "-C"); sl_append(cmdline, "-o"); assert(annfn); append_escape(cmdline, annfn); cmd = sl_implode(cmdline, " "); sl_free2(cmdline); logverb("Running:\n %s\n", cmd); if (run_command_get_outputs(cmd, &lines, NULL)) { ERROR("plot-constellations failed"); return -1; } free(cmd); if (lines && sl_size(lines)) { int i; if (strlen(sl_get(lines, 0))) { logmsg("Your field contains:\n"); for (i=0; i<sl_size(lines); i++) logmsg(" %s\n", sl_get(lines, i)); } } if (lines) sl_free2(lines); return 0; }
vio_err_t vio_partition_val(vio_ctx *ctx, vio_val *v, vio_val *q, vio_val **out_rets, vio_val **out_parts) { vio_err_t err = 0; struct partition *p = NULL; struct partition_item *it = NULL; vio_val *ret; sl_skiplist parts; sl_init(&parts, cmp_vals, ctx, NULL, NULL); for (uint32_t i = 0; i < v->vlen; ++i) { VIO__ERRIF(ctx->sp >= VIO_STACK_SIZE, VE_STACK_OVERFLOW); ctx->stack[ctx->sp++] = v->vv[i]; vio_exec(ctx, q->bc); ret = ctx->stack[--ctx->sp]; if (!sl_find(&parts, ret, &p)) { VIO__ERRIF((p = (struct partition *)malloc(sizeof(struct partition))) == NULL, VE_ALLOC_FAIL); p->last = NULL; p->size = 0; sl_insert(&parts, ret, p, NULL); } VIO__ERRIF((it = (struct partition_item *)malloc(sizeof(struct partition_item))) == NULL, VE_ALLOC_FAIL); it->next = p->last; it->v = v->vv[i]; p->last = it; ++p->size; } VIO__CHECK(vio_vec(ctx, out_rets, sl_size(&parts), NULL)); VIO__CHECK(vio_vec(ctx, out_parts, sl_size(&parts), NULL)); struct part_data pd = { .i = 0, .rets = *out_rets, .parts = *out_parts, .ctx = ctx }; sl_iter(&parts, fill_partitions_and_free, &pd); sl_free(&parts); return 0; error: sl_iter(&parts, gotta_free_em_all, NULL); sl_free(&parts); return err; } vio_err_t vio_partition(vio_ctx *ctx) { vio_err_t err = 0; vio_val *q, *vec, *rets, *parts; VIO__RAISEIF(ctx->sp < 2, VE_STACK_EMPTY, "Partition context requires a quotation and vector, but the " "stack doesnt't have enough values."); VIO__CHECK(vio_coerce(ctx, ctx->stack[--ctx->sp], &q, vv_quot)); VIO__CHECK(vio_coerce(ctx, ctx->stack[--ctx->sp], &vec, vv_vec)); VIO__CHECK(vio_partition_val(ctx, vec, q, &rets, &parts)); ctx->stack[ctx->sp++] = rets; ctx->stack[ctx->sp++] = parts; return 0; error: return err; }
void sl_remove_duplicates(sl* lst) { int i, j; for (i=0; i<sl_size(lst); i++) { const char* s1 = sl_get(lst, i); for (j=i+1; j<sl_size(lst); j++) { const char* s2 = sl_get(lst, j); if (strcmp(s1, s2) == 0) { sl_remove(lst, j); j--; } } } }
void sl_free2(sl* list) { int i; if (!list) return; for (i=0; i<sl_size(list); i++) free(sl_get(list, i)); bl_free(list); }
void sl_remove_all(sl* list) { int i; if (!list) return; for (i=0; i<sl_size(list); i++) free(pl_get(list, i)); bl_remove_all(list); }
int plot_annotations_command(const char* cmd, const char* cmdargs, plot_args_t* pargs, void* baton) { plotann_t* ann = (plotann_t*)baton; if (streq(cmd, "annotations_no_ngc")) { ann->NGC = FALSE; } else if (streq(cmd, "annotations_no_bright")) { ann->bright = FALSE; } else if (streq(cmd, "annotations_ngc_size")) { ann->ngc_fraction = atof(cmdargs); } else if (streq(cmd, "annotations_target")) { sl* args = sl_split(NULL, cmdargs, " "); double ra, dec; char* name; if (sl_size(args) != 3) { ERROR("Need RA,Dec,name"); return -1; } ra = atof(sl_get(args, 0)); dec = atof(sl_get(args, 1)); name = sl_get(args, 2); plot_annotations_add_target(ann, ra, dec, name); } else if (streq(cmd, "annotations_targetname")) { const char* name = cmdargs; return plot_annotations_add_named_target(ann, name); } else { ERROR("Unknown command \"%s\"", cmd); return -1; } return 0; }
void opts_print_help(bl* opts, FILE* fid, void (*special_case)(an_option_t* opt, bl* allopts, int index, FILE* fid, void* extra), void* extra) { int i; for (i=0; i<bl_size(opts); i++) { an_option_t* opt = bl_access(opts, i); int nw = 0; sl* words; int j; if (opt->help) { if ((opt->shortopt >= 'a' && opt->shortopt <= 'z') || (opt->shortopt >= 'A' && opt->shortopt <= 'Z') || (opt->shortopt >= '0' && opt->shortopt <= '9')) nw += fprintf(fid, " -%c / --%s", opt->shortopt, opt->name); else nw += fprintf(fid, " --%s", opt->name); if (opt->has_arg == optional_argument) nw += fprintf(fid, " [<%s>]", opt->argname); else if (opt->has_arg == required_argument) nw += fprintf(fid, " <%s>", opt->argname); nw += fprintf(fid, ": "); if (!opt->help) continue; words = split_long_string(opt->help, 80-nw, 70, NULL); for (j=0; j<sl_size(words); j++) fprintf(fid, "%s%s\n", (j==0 ? "" : " "), sl_get(words, j)); } else if (special_case) special_case(opt, opts, i, fid, extra); } }
int fitstable_add_fits_columns_as_struct3(const fitstable_t* intab, fitstable_t* outtab, const sl* colnames, int c_offset) { int i, NC; int noc = ncols(outtab); NC = sl_size(colnames); for (i=0; i<NC; i++) { const qfits_col* qcol; fitscol_t* col; const char* name = sl_get_const(colnames, i); int j = fits_find_column(intab->table, name); int off; if (j == -1) { ERROR("Failed to find FITS column \"%s\"", name); return -1; } qcol = qfits_table_get_col(intab->table, j); // We give the offset of the column in the *input* table, so that // the resulting "outtab" can handle raw data from the "intab". off = fits_offset_of_column(intab->table, j); fitstable_add_read_column_struct(outtab, qcol->atom_type, qcol->atom_nb, c_offset + off, qcol->atom_type, qcol->tlabel, TRUE); // set the FITS column number. col = getcol(outtab, ncols(outtab)-1); col->col = noc + i; } return 0; }
static char* sljoin(sl* list, const char* join, int forward) { int start, end, inc; int len = 0; int i, N; char* rtn; int offset; int JL; if (sl_size(list) == 0) return strdup(""); // step through the list forward or backward? if (forward) { start = 0; end = sl_size(list); inc = 1; } else { start = sl_size(list) - 1; end = -1; inc = -1; } JL = strlen(join); N = sl_size(list); for (i=0; i<N; i++) len += strlen(sl_get(list, i)); len += ((N-1) * JL); rtn = malloc(len + 1); if (!rtn) return rtn; offset = 0; for (i=start; i!=end; i+= inc) { char* str = sl_get(list, i); int L = strlen(str); if (i != start) { memcpy(rtn + offset, join, JL); offset += JL; } memcpy(rtn + offset, str, L); offset += L; } assert(offset == len); rtn[offset] = '\0'; return rtn; }
int plotstuff_append_doubles(const char* str, dl* lst) { int i; sl* strs = sl_split(NULL, str, " "); for (i=0; i<sl_size(strs); i++) dl_append(lst, atof(sl_get(strs, i))); sl_free2(strs); return 0; }
void test_log_ts(CuTest* tc) { pthread_t t1, t2; FILE *f1, *f2; char *fn1, *fn2; sl* lst; log_init(LOG_VERB); logmsg("Logging initialized.\n"); log_set_thread_specific(); logmsg("Logging set thread specific.\n"); fn1 = create_temp_file("log", "/tmp"); fn2 = create_temp_file("log", "/tmp"); logmsg("File 1 is %s\n", fn1); logmsg("File 2 is %s\n", fn2); f1 = fopen(fn1, "w"); f2 = fopen(fn2, "w"); CuAssertIntEquals(tc, 0, pthread_create(&t1, NULL, thread1, f1)); CuAssertIntEquals(tc, 0, pthread_create(&t2, NULL, thread2, f2)); CuAssertIntEquals(tc, 0, pthread_join(t1, NULL)); CuAssertIntEquals(tc, 0, pthread_join(t2, NULL)); fclose(f1); fclose(f2); lst = file_get_lines(fn1, FALSE); CuAssertIntEquals(tc, 0, strcmp(sl_get(lst, 0), STRING1A)); CuAssertIntEquals(tc, 1, sl_size(lst)); sl_free2(lst); lst = file_get_lines(fn2, FALSE); CuAssertIntEquals(tc, 0, strcmp(sl_get(lst, 0), STRING2A)); CuAssertIntEquals(tc, 0, strcmp(sl_get(lst, 1), STRING2B)); CuAssertIntEquals(tc, 2, sl_size(lst)); sl_free2(lst); unlink(fn1); unlink(fn2); free(fn1); free(fn2); }
ptrdiff_t sl_last_index_of(sl* lst, const char* str) { ptrdiff_t i; for (i=sl_size(lst)-1; i>=0; i--) { char* s = sl_get(lst, i); if (strcmp(s, str) == 0) return i; } return BL_NOT_FOUND; }
ptrdiff_t sl_index_of(sl* lst, const char* str) { size_t i; for (i=0; i<sl_size(lst); i++) { char* s = sl_get(lst, i); if (strcmp(s, str) == 0) return i; } return BL_NOT_FOUND; }
void sl_append_contents(sl* dest, sl* src) { int i; if (!src) return; for (i=0; i<sl_size(src); i++) { char* str = sl_get(src, i); sl_append(dest, str); } }
int sl_index_of(sl* lst, const char* str) { int i; for (i=0; i<sl_size(lst); i++) { char* s = sl_get(lst, i); if (strcmp(s, str) == 0) return i; } return -1; }
int sl_last_index_of(sl* lst, const char* str) { int i; for (i=sl_size(lst)-1; i>=0; i--) { char* s = sl_get(lst, i); if (strcmp(s, str) == 0) return i; } return -1; }
void test_sl_split_2(CuTest* tc) { int i; sl* s = sl_split(NULL, "hello world this is a test ", " "); CuAssertPtrNotNull(tc, s); printf("got: "); for (i=0; i<sl_size(s); i++) printf("/%s/ ", sl_get(s, i)); printf("\n"); CuAssertIntEquals(tc, 8, sl_size(s)); CuAssertIntEquals(tc, 0, strcmp(sl_get(s, 0), "hello")); CuAssertIntEquals(tc, 0, strcmp(sl_get(s, 1), "world")); CuAssertIntEquals(tc, 0, strcmp(sl_get(s, 2), "this")); CuAssertIntEquals(tc, 0, strcmp(sl_get(s, 3), "is")); CuAssertIntEquals(tc, 0, strcmp(sl_get(s, 4), "a")); CuAssertIntEquals(tc, 0, strcmp(sl_get(s, 5), "test")); CuAssertIntEquals(tc, 0, strcmp(sl_get(s, 6), "")); CuAssertIntEquals(tc, 0, strcmp(sl_get(s, 7), " ")); sl_free2(s); }
void test_sl_split_1(CuTest* tc) { sl* s = sl_split(NULL, "hello world this is a test", " "); CuAssertPtrNotNull(tc, s); CuAssertIntEquals(tc, 6, sl_size(s)); CuAssertIntEquals(tc, 0, strcmp(sl_get(s, 0), "hello")); CuAssertIntEquals(tc, 0, strcmp(sl_get(s, 1), "world")); CuAssertIntEquals(tc, 0, strcmp(sl_get(s, 2), "this")); CuAssertIntEquals(tc, 0, strcmp(sl_get(s, 3), "is")); CuAssertIntEquals(tc, 0, strcmp(sl_get(s, 4), "a")); CuAssertIntEquals(tc, 0, strcmp(sl_get(s, 5), "test")); sl_free2(s); }
ptrdiff_t sl_remove_string_byval(sl* list, const char* string) { size_t N = sl_size(list); size_t i; for (i=0; i<N; i++) { char* str = sl_get(list, i); if (strcmp(str, string) == 0) { sl_remove(list, i); return i; } } return BL_NOT_FOUND; }
int sl_remove_string_byval(sl* list, const char* string) { int N = sl_size(list); int i; for (i=0; i<N; i++) { char* str = sl_get(list, i); if (strcmp(str, string) == 0) { sl_remove(list, i); return i; } } return -1; }
static void delete_temp_files(sl* tempfiles, sl* tempdirs) { int i; if (tempfiles) { for (i=0; i<sl_size(tempfiles); i++) { char* fn = sl_get(tempfiles, i); logverb("Deleting temp file %s\n", fn); if (unlink(fn)) SYSERROR("Failed to delete temp file \"%s\"", fn); } sl_remove_all(tempfiles); } if (tempdirs) { for (i=0; i<sl_size(tempdirs); i++) { char* fn = sl_get(tempdirs, i); logverb("Deleting temp dir %s\n", fn); if (rmdir(fn)) SYSERROR("Failed to delete temp dir \"%s\"", fn); } sl_remove_all(tempdirs); } }
char* sl_remove_string_bycaseval(sl* list, const char* string) { int N = sl_size(list); int i; for (i=0; i<N; i++) { char* str = sl_get(list, i); if (strcasecmp(str, string) == 0) { char* s = sl_get(list, i); sl_remove(list, i); return s; } } return NULL; }
/* device_mover_setup() *========================================================================== * RETURNS TRUE - SUCCESS * FALSE- ERROR! ( probably memory allocation ) */ void device_mover_setup( DEV_PTR list_ptr, int font_count, int base, int slider, int up, int down, int first_obj, int last_obj, int base_obj, int start_index, int num_slits ) { int i; dhdptr = list_ptr; Total = font_count; Mbase = base; Mslider = slider; Mup = up; Mdown = down; First_Obj = first_obj; Base_Obj = base_obj; Obj_Beg = first_obj; Obj_End = last_obj; MAX_SLITS = num_slits; for( i = 0; i < MAX_SLITS;i++ ) { Deselect( First_Obj + ( i * 6 ) + 5 ); Device_Slit[i] = NULL; TedText( First_Obj + ( i * 6 ) + 2 ) = fblank3; HideObj( First_Obj + ( i * 6 ) + 3 ); HideObj( First_Obj + ( i * 6 ) + 4 ); } if( Total > MAX_SLITS ) { if( start_index > Total - MAX_SLITS ) start_index = Total - MAX_SLITS; } else start_index = 0; device_offset_adjust( dhdptr, start_index, Device_Slit ); if( start_index ) start_index = Get_Device_Index( dhdptr, Device_Slit[0] ); Old_Slit = Cur_Slit = start_index; sl_size( tree, Mbase, Mslider, Total, MAX_SLITS, VERTICAL, 0 ); sl_y( tree, Mbase, Mslider, Cur_Slit, max( Total - MAX_SLITS, 0 ), 0, NULLFUNC ); }
void test_sl_split_3(CuTest* tc) { sl* s, *s2; s = sl_new(1); sl_append(s, "guard"); s2 = sl_split(s, "XYhelloXYworldXYXY", "XY"); CuAssertPtrNotNull(tc, s2); CuAssertPtrEquals(tc, s, s2); CuAssertIntEquals(tc, 5, sl_size(s)); CuAssertIntEquals(tc, 0, strcmp(sl_get(s, 0), "guard")); CuAssertIntEquals(tc, 0, strcmp(sl_get(s, 1), "")); CuAssertIntEquals(tc, 0, strcmp(sl_get(s, 2), "hello")); CuAssertIntEquals(tc, 0, strcmp(sl_get(s, 3), "world")); CuAssertIntEquals(tc, 0, strcmp(sl_get(s, 4), "")); sl_free2(s); }
/* mover_setup() *========================================================================== * RETURNS TRUE - SUCCESS * FALSE- ERROR! ( probably memory allocation ) */ void mover_setup( HDEVICE_PTR list_ptr, int font_count, int base, int slider, int up, int down, int first_obj, int last_obj, int base_obj, int start_index, int num_slits ) { int i; hdptr = list_ptr; Total = font_count; Mbase = base; Mslider = slider; Mup = up; Mdown = down; First_Obj = first_obj; Base_Obj = base_obj; Obj_Beg = first_obj; Obj_End = last_obj; MAX_SLITS = num_slits; for( i = 0; i < MAX_SLITS;i++ ) { Active_Slit[i] = NULL; TedText( First_Obj + i ) = fblank; } if( Total > MAX_SLITS ) { if( start_index > Total - MAX_SLITS ) start_index = Total - MAX_SLITS; } else start_index = 0; slit_offset_adjust( hdptr, start_index, Active_Slit ); if( start_index ) start_index = Get_Findex( hdptr, Active_Slit[0] ); Old_Slit = Cur_Slit = start_index; sl_size( tree, Mbase, Mslider, Total, MAX_SLITS, VERTICAL, 0 ); sl_y( tree, Mbase, Mslider, Cur_Slit, max( Total - MAX_SLITS, 0 ), 0, NULLFUNC ); }
int main(int argc, char *argv[]) { char* progname = argv[0]; int argchar; char* infn; sl* methods = NULL; dl* scales = NULL; int i; int loglvl = LOG_MSG; while ((argchar = getopt (argc, argv, OPTIONS)) != -1) switch (argchar) { case '?': case 'h': printHelp(progname); return 0; case 'v': loglvl++; break; default: return -1; } if (optind != (argc - 1)) { printHelp(progname); exit(-1); } infn = argv[optind]; log_init(loglvl); fits_use_error_system(); if (fits_guess_scale(infn, &methods, &scales)) exit(-1); for (i=0; i<sl_size(methods); i++) { printf("scale %s %g\n", sl_get(methods, i), dl_get(scales, i)); } sl_free2(methods); dl_free(scales); return 0; }
multiindex_t* multiindex_open(const char* skdtfn, const sl* indfns, int flags) { multiindex_t* mi = multiindex_new(skdtfn); if (!mi) return NULL; int i; for (i=0; i<sl_size(indfns); i++) { const char* fn = sl_get_const(indfns, i); if (multiindex_add_index(mi, fn, flags)) { goto bailout; } } if (flags & INDEX_ONLY_LOAD_METADATA) { multiindex_unload_starkd(mi); } return mi; bailout: multiindex_free(mi); return NULL; }
int main(int argc, char** args) { char* default_configfn = "astrometry.cfg"; char* default_config_path = "../etc"; int c; char* configfn = NULL; int i; engine_t* engine; char* mydir = NULL; char* basedir = NULL; char* me; anbool help = FALSE; sl* strings = sl_new(4); char* cancelfn = NULL; char* solvedfn = NULL; int loglvl = LOG_MSG; anbool tostderr = FALSE; char* infn = NULL; FILE* fin = NULL; anbool fromstdin = FALSE; bl* opts = opts_from_array(myopts, sizeof(myopts)/sizeof(an_option_t), NULL); sl* inds = sl_new(4); char* datalog = NULL; engine = engine_new(); while (1) { c = opts_getopt(opts, argc, args); if (c == -1) break; switch (c) { case 'D': datalog = optarg; break; case 'p': engine->inparallel = TRUE; break; case 'i': sl_append(inds, optarg); break; case 'd': basedir = optarg; break; case 'f': infn = optarg; fromstdin = streq(infn, "-"); break; case 'E': tostderr = TRUE; break; case 'h': help = TRUE; break; case 'v': loglvl++; break; case 's': solvedfn = optarg; case 'C': cancelfn = optarg; break; case 'c': configfn = strdup(optarg); break; case '?': break; default: printf("Unknown flag %c\n", c); exit( -1); } } if (optind == argc && !infn) { // Need extra args: filename printf("You must specify at least one input file!\n\n"); help = TRUE; } if (help) { print_help(args[0], opts); exit(0); } bl_free(opts); gslutils_use_error_system(); log_init(loglvl); if (tostderr) log_to(stderr); if (datalog) { datalogfid = fopen(datalog, "wb"); if (!datalogfid) { SYSERROR("Failed to open data log file \"%s\" for writing", datalog); return -1; } atexit(close_datalogfid); data_log_init(100); data_log_enable_all(); data_log_to(datalogfid); data_log_start(); } if (infn) { logverb("Reading input filenames from %s\n", (fromstdin ? "stdin" : infn)); if (!fromstdin) { fin = fopen(infn, "rb"); if (!fin) { ERROR("Failed to open file %s for reading input filenames", infn); exit(-1); } } else fin = stdin; } // directory containing the 'engine' executable: me = find_executable(args[0], NULL); if (!me) me = strdup(args[0]); mydir = sl_append(strings, dirname(me)); free(me); // Read config file if (!configfn) { int i; sl* trycf = sl_new(4); sl_appendf(trycf, "%s/%s/%s", mydir, default_config_path, default_configfn); // if I'm in /usr/bin, look for config file in /etc if (streq(mydir, "/usr/bin")) { sl_appendf(trycf, "/etc/%s", default_configfn); } sl_appendf(trycf, "%s/%s", mydir, default_configfn); sl_appendf(trycf, "./%s", default_configfn); sl_appendf(trycf, "./%s/%s", default_config_path, default_configfn); for (i=0; i<sl_size(trycf); i++) { char* cf = sl_get(trycf, i); if (file_exists(cf)) { configfn = strdup(cf); logverb("Using config file \"%s\"\n", cf); break; } else { logverb("Config file \"%s\" doesn't exist.\n", cf); } } if (!configfn) { char* cflist = sl_join(trycf, "\n "); logerr("Couldn't find config file: tried:\n %s\n", cflist); free(cflist); } sl_free2(trycf); } if (!streq(configfn, "none")) { if (engine_parse_config_file(engine, configfn)) { logerr("Failed to parse (or encountered an error while interpreting) config file \"%s\"\n", configfn); exit( -1); } } if (sl_size(inds)) { // Expand globs. for (i=0; i<sl_size(inds); i++) { char* s = sl_get(inds, i); glob_t myglob; int flags = GLOB_TILDE | GLOB_BRACE; if (glob(s, flags, NULL, &myglob)) { SYSERROR("Failed to expand wildcards in index-file path \"%s\"", s); exit(-1); } for (c=0; c<myglob.gl_pathc; c++) { if (engine_add_index(engine, myglob.gl_pathv[c])) { ERROR("Failed to add index \"%s\"", myglob.gl_pathv[c]); exit(-1); } } globfree(&myglob); } } if (!pl_size(engine->indexes)) { logerr("\n\n" "---------------------------------------------------------------------\n" "You must list at least one index in the config file (%s)\n\n" "See http://astrometry.net/use.html about how to get some index files.\n" "---------------------------------------------------------------------\n" "\n", configfn); exit(-1); } if (engine->minwidth <= 0.0 || engine->maxwidth <= 0.0) { logerr("\"minwidth\" and \"maxwidth\" in the config file %s must be positive!\n", configfn); exit(-1); } free(configfn); if (!il_size(engine->default_depths)) { parse_depth_string(engine->default_depths, "10 20 30 40 50 60 70 80 90 100 " "110 120 130 140 150 160 170 180 190 200"); } engine->cancelfn = cancelfn; engine->solvedfn = solvedfn; i = optind; while (1) { char* jobfn; job_t* job; struct timeval tv1, tv2; if (infn) { // Read name of next input file to be read. logverb("\nWaiting for next input filename...\n"); jobfn = read_string_terminated(fin, "\n\r\0", 3, FALSE); if (strlen(jobfn) == 0) break; } else { if (i == argc) break; jobfn = args[i]; i++; } gettimeofday(&tv1, NULL); logmsg("Reading file \"%s\"...\n", jobfn); job = engine_read_job_file(engine, jobfn); if (!job) { ERROR("Failed to read job file \"%s\"", jobfn); exit(-1); } if (basedir) { logverb("Setting job's output base directory to %s\n", basedir); job_set_output_base_dir(job, basedir); } if (engine_run_job(engine, job)) logerr("Failed to run_job()\n"); job_free(job); gettimeofday(&tv2, NULL); logverb("Spent %g seconds on this field.\n", millis_between(&tv1, &tv2)/1000.0); } engine_free(engine); sl_free2(strings); sl_free2(inds); if (fin && !fromstdin) fclose(fin); return 0; }
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; }