void testit(int* wanted, int Nwanted, int dimquads, int (*compar)(const void *, const void *), anbool cxdx) { int i; solver_t* solver; index_t index; starxy_t* starxy; starxy = field1(); quadlist = bl_new(16, dimquads*sizeof(int)); ninv = 0; solver = solver_new(); memset(&index, 0, sizeof(index_t)); index.index_scale_lower = 1; index.index_scale_upper = 10; index.dimquads = dimquads; index.cx_less_than_dx = index.meanx_less_than_half = cxdx; solver->funits_lower = 0.1; solver->funits_upper = 10; solver_add_index(solver, &index); solver_set_field(solver, starxy); solver_preprocess_field(solver); printf("Found:\n"); solver_run(solver); printf("\n"); fflush(NULL); solver_free_field(solver); solver_free(solver); // bl_sort(quadlist, compar); qsort(wanted, Nwanted, dimquads*sizeof(int), compar); printf("\n\n"); printf("Wanted:\n"); for (i=0; i<Nwanted; i++) { int j; printf("{"); for (j=0; j<dimquads; j++) printf("%s%i", (j?",":""), wanted[i*dimquads+j]); printf("}, "); } printf("\n"); printf("N found: %i; N wanted: %i\n", bl_size(quadlist), Nwanted); printf("N obeying invariants: %i\n", ninv); assert(bl_size(quadlist) == Nwanted); for (i=0; i<bl_size(quadlist); i++) { //int* i1 = bl_access(quadlist, i); //int* i2 = wanted[i]; //printf("[%i, %i, %i] vs [%i, %i, %i]\n", i1[0],i1[1],i1[2], i2[0],i2[1],i2[2]); assert(compar(bl_access(quadlist, i), wanted+i*dimquads) == 0); } bl_free(quadlist); }
void test_bl_extend(CuTest *tc) { bl* list = bl_new(10, sizeof(int)); CuAssertIntEquals(tc, bl_size(list), 0); int *new1 = bl_extend(list); CuAssertPtrNotNull(tc, new1); CuAssertIntEquals(tc, bl_size(list), 1); *new1 = 10; int *new2 = bl_access(list, 0); CuAssertPtrEquals(tc, new2, new1); bl_free(list); }
int bl_check_sorted(bl* list, int (*compare)(const void* v1, const void* v2), int isunique) { int i, N; int nbad = 0; void* v2 = NULL; N = bl_size(list); if (N) v2 = bl_access(list, 0); for (i=1; i<N; i++) { void* v1; int cmp; v1 = v2; v2 = bl_access(list, i); cmp = compare(v1, v2); if (isunique) { if (cmp >= 0) { nbad++; } } else { if (cmp > 0) { nbad++; } } } if (nbad) { fprintf(stderr, "bl_check_sorted: %i are out of order.\n", nbad); 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); } }
static anbool is_duplicate(int hp, double ra, double dec, int Nside, intmap_t* starlists, double* ras, double* decs, double dedupr2) { double xyz[3]; int neigh[9]; int nn; double xyz2[3]; int k; size_t j; radecdeg2xyzarr(ra, dec, xyz); // Check this healpix... neigh[0] = hp; // Check neighbouring healpixes... (+1 is to skip over this hp) nn = 1 + healpix_get_neighbours(hp, neigh+1, Nside); for (k=0; k<nn; k++) { int otherhp = neigh[k]; bl* lst = intmap_find(starlists, otherhp, FALSE); if (!lst) continue; for (j=0; j<bl_size(lst); j++) { int otherindex; bl_get(lst, j, &otherindex); radecdeg2xyzarr(ras[otherindex], decs[otherindex], xyz2); if (!distsq_exceeds(xyz, xyz2, 3, dedupr2)) return TRUE; } } return FALSE; }
static void ensure_row_list_exists(fitstable_t* table) { if (!table->rows) { // how big are the rows? int rowsize = offset_of_column(table, bl_size(table->cols)); table->rows = bl_new(1024, rowsize); } }
int fs_create(char* file_name) { /*Uso de livre para indicar primeira entrada livre no diretório Uso de bloco_livre para indicar primeiro bloco_livre no disco*/ int i, livre=-1, bloco_livre=-1; /*Verificação de file_name que não pode ser maior que 24 caracteres*/ if(sizeof(file_name)>24){ printf("Nome maior que 24 caracteres."); return 0; } /*Verifica se não há arquivo de mesmo nome no diretório e sai, caso contrário também verifica a primeira entrada livre do diretório */ for(i=0; i<128; i++){ if(!strcmp(file_name, dir[i].name){ printf("O arquivo já existe!\n"); return 0; } if(dir[i].used == 0 && livre == -1){ livre = i; } } /*Se livre é -1, então o diretório está cheio*/ if(livre == -1){ printf("Diretório cheio!\n"); return 0; } /*Procura na lista da FAT o primeiro bloco_livre (que está com valor 1)*/ for(i=0; i<(bl_size()/8); i++){ if(fat[i] == 1 && bloco_livre == -1){ bloco_livre = i; } } /*Se bloco_livre é -1, então o disco está cheio*/ if(bloco_livre == -1){ printf("Disco cheio!\n"); return 0; } /*Criação da entrada no diretório de fato*/ dir[livre].used = 1; /*Primeiro bloco é primeiro bloco_livre*/ dir[livre].first_block = bloco_livre; strcpy(dir[livre].name, file_name); /*Tamanho é 0 como na especificação*/ dir[livre].size = 0; /*Bloco não está mais livre, então é 2 e o bloco final, se o arquivo tem tamanho 0, então o arquivo não passará de um bloco*/ fat[bloco_livre] = 2; /*Escreve as modificações no disco*/ flush(); return 1; }
int fs_free() { int i, cont=0; /*Conta os blocos livres do disco*/ for(i=33;i<(bl_size()/8);i++){ if(fat[i]==1)cont++; } /*Retorna o número de entradas livres multiplicado pelo tamanho de um bloco*/ return cont*CLUSTERSIZE; }
int fs_create(char* file_name) { //printf("Função não implementada: fs_create\n"); int i; //procura por arquivo existente for ( i = 0; i < 128; i++){ if(!strcmp(file_name, dir[i].name) && dir[i].used == 'T'){ printf("Arquivo ja existe.\n"); return 0; } } i =0; while( i < 128 && dir[i].used != 'F'){ i++; } if(i == 128){ printf("Disco cheio\n"); return 0; } int marca_dir = i; i = 33; while( (i < bl_size()/8) && fat[i]== 1){ i++; } if(i == (bl_size()/8)){ printf("Fat cheio\n"); return 0; } int marca_fat = i; //insere valores na primeira posicao vazia encontrada dir[marca_dir].used = 'T'; dir[marca_dir].first_block = marca_fat; strcpy(dir[marca_dir].name, file_name); dir[marca_dir].size = 0; //marca fat como usado fat[marca_fat] = 2; fat_write(); //retorno arquivo criado com sucesso return 1; }
int fitstable_open_extension(fitstable_t* tab, int ext) { if (in_memory(tab)) { fitsext_t* theext; if (ext > bl_size(tab->extensions)) { ERROR("Table has only %zu extensions, but you requested #%i", bl_size(tab->extensions), ext); return -1; } theext = bl_access(tab->extensions, ext-1); tab->table = theext->table; tab->header = theext->header; tab->rows = theext->rows; tab->extension = ext; } else { if (tab->table) { qfits_table_close(tab->table); tab->table = NULL; } assert(tab->anq); if (ext >= anqfits_n_ext(tab->anq)) { ERROR("Requested FITS extension %i in file %s, but there are only %i extensions.\n", ext, tab->fn, anqfits_n_ext(tab->anq)); return -1; } tab->table = anqfits_get_table(tab->anq, ext); if (!tab->table) { ERROR("FITS extension %i in file %s is not a table (or there was an error opening the file)", ext, tab->fn); return -1; } if (tab->header) { qfits_header_destroy(tab->header); } tab->header = anqfits_get_header(tab->anq, ext); if (!tab->header) { ERROR("Couldn't get header for FITS extension %i in file %s", ext, tab->fn); return -1; } tab->extension = ext; } return 0; }
static void plot_hd(cairo_t* cairo, plot_args_t* pargs, plotann_t* ann) { int i, N; hd_catalog_t* hdcat = NULL; double ra,dec,rad; bl* hdlist = NULL; if (!ann->hd_catalog) return; hdcat = henry_draper_open(ann->hd_catalog); if (!hdcat) { ERROR("Failed to open Henry Draper catalog file \"%s\"", ann->hd_catalog); return; } if (plotstuff_get_radec_center_and_radius(pargs, &ra, &dec, &rad)) { ERROR("Failed to get RA,Dec,radius from plotstuff"); return; } hdlist = henry_draper_get(hdcat, ra, dec, deg2arcsec(rad)); logverb("Got %zu Henry Draper stars\n", bl_size(hdlist)); N = bl_size(hdlist); for (i=0; i<N; i++) { hd_entry_t* entry = bl_access(hdlist, i); double px, py; char label[16]; if (!plotstuff_radec2xy(pargs, entry->ra, entry->dec, &px, &py)) continue; px -= 1; py -= 1; if (px < 1 || py < 1 || px > pargs->W || py > pargs->H) continue; logverb("HD %i at RA,Dec (%g,%g) -> xy (%g, %g)\n", entry->hd, entry->ra, entry->dec, px, py); plotstuff_stack_marker(pargs, px, py); if (ann->HD_labels) { sprintf(label, "HD %i", entry->hd); plotstuff_stack_text(pargs, cairo, label, px, py); } } bl_free(hdlist); henry_draper_close(hdcat); }
int opts_getopt(bl* opts, int argc, char** argv) { size_t i, j, N; char* optstring; int c; struct option* longoptions; N = bl_size(opts); // create the short options string. optstring = malloc(3 * N + 1); j = 0; for (i=0; i<N; i++) { an_option_t* opt = bl_access(opts, i); if (!opt->shortopt) continue; if (iscntrl((unsigned)(opt->shortopt))) continue; optstring[j] = opt->shortopt; j++; if (opt->has_arg == no_argument) continue; optstring[j] = ':'; j++; if (opt->has_arg == required_argument) continue; optstring[j] = ':'; j++; } optstring[j] = '\0'; // create long options. longoptions = calloc(N+1, sizeof(struct option)); j = 0; for (i=0; i<N; i++) { an_option_t* opt = bl_access(opts, i); if (!opt->shortopt) continue; //if (iscntrl(opt->shortopt)) //continue; longoptions[j].name = opt->name; longoptions[j].has_arg = opt->has_arg; longoptions[j].val = opt->shortopt; j++; } // DEBUG //printf("%s\n", optstring); c = getopt_long(argc, argv, optstring, longoptions, NULL); free(optstring); free(longoptions); return c; }
int fitstable_close(fitstable_t* tab) { int i; int rtn = 0; if (!tab) return 0; if (is_writing(tab)) { if (fclose(tab->fid)) { SYSERROR("Failed to close output file %s", tab->fn); rtn = -1; } } if (tab->anq) { anqfits_close(tab->anq); } if (tab->readfid) { fclose(tab->readfid); } if (tab->primheader) qfits_header_destroy(tab->primheader); if (tab->header) qfits_header_destroy(tab->header); if (tab->table) qfits_table_close(tab->table); free(tab->fn); for (i=0; i<ncols(tab); i++) { fitscol_t* col = getcol(tab, i); free(col->colname); free(col->units); } bl_free(tab->cols); if (tab->br) { buffered_read_free(tab->br); free(tab->br); } if (tab->rows) { bl_free(tab->rows); } if (tab->extensions) { for (i=0; i<bl_size(tab->extensions); i++) { fitsext_t* ext = bl_access(tab->extensions, i); if (ext->rows != tab->rows) bl_free(ext->rows); if (ext->header != tab->header) qfits_header_destroy(ext->header); if (ext->table != tab->table) qfits_table_close(ext->table); } bl_free(tab->extensions); } free(tab); return rtn; }
int fs_free() { //printf("Função não implementada: fs_free\n"); int i; int tam_bloco; int pos_livres =0; tam_bloco = bl_size() / 8; // verifica posicoes livres na fat for(i = 33; i < tam_bloco; i++){ if(fat[i] ==1) pos_livres++; } return pos_livres * 4096;//retorna posicoes livres * o tamanho }
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."); } } }
int plot_annotations_plot(const char* cmd, cairo_t* cairo, plot_args_t* pargs, void* baton) { plotann_t* ann = (plotann_t*)baton; // Set fonts, etc, before calling plotting routines plotstuff_builtin_apply(cairo, pargs); if (ann->NGC) plot_ngc(cairo, pargs, ann); if (ann->bright) plot_brightstars(cairo, pargs, ann); if (ann->HD) plot_hd(cairo, pargs, ann); if (ann->constellations) plot_constellations(cairo, pargs, ann); if (bl_size(ann->targets)) plot_targets(cairo, pargs, ann); return plotstuff_plot_stack(pargs, cairo); }
int hpquads(startree_t* starkd, codefile_t* codes, quadfile_t* quads, int Nside, double scale_min_arcmin, double scale_max_arcmin, int dimquads, int passes, int Nreuses, int Nloosen, int id, anbool scanoccupied, void* sort_data, int (*sort_func)(const void*, const void*), int sort_size, char** args, int argc) { hpquads_t myhpquads; hpquads_t* me = &myhpquads; int i; int pass; anbool circle = TRUE; double radius2; il* hptotry; int Nhptotry = 0; int nquads; double hprad; double quadscale; int skhp, sknside; qfits_header* qhdr; qfits_header* chdr; int N; int dimcodes; int quadsize; int NHP; memset(me, 0, sizeof(hpquads_t)); if (Nside > HP_MAX_INT_NSIDE) { ERROR("Error: maximum healpix Nside = %i", HP_MAX_INT_NSIDE); return -1; } if (Nreuses > 255) { ERROR("Error, reuse (-r) must be less than 256"); return -1; } me->Nside = Nside; me->dimquads = dimquads; NHP = 12 * Nside * Nside; dimcodes = dimquad2dimcode(dimquads); quadsize = sizeof(unsigned int) * dimquads; logmsg("Nside=%i. Nside^2=%i. Number of healpixes=%i. Healpix side length ~ %g arcmin.\n", me->Nside, me->Nside*me->Nside, NHP, healpix_side_length_arcmin(me->Nside)); me->sort_data = sort_data; me->sort_func = sort_func; me->sort_size = sort_size; tic(); me->starkd = starkd; N = startree_N(me->starkd); logmsg("Star tree contains %i objects.\n", N); // get the "HEALPIX" header from the skdt... skhp = qfits_header_getint(startree_header(me->starkd), "HEALPIX", -1); if (skhp == -1) { if (!qfits_header_getboolean(startree_header(me->starkd), "ALLSKY", FALSE)) { logmsg("Warning: skdt does not contain \"HEALPIX\" header. Code and quad files will not contain this header either.\n"); } } // likewise "HPNSIDE" sknside = qfits_header_getint(startree_header(me->starkd), "HPNSIDE", 1); if (sknside && Nside % sknside) { logerr("Error: Nside (-n) must be a multiple of the star kdtree healpixelisation: %i\n", sknside); return -1; } if (!scanoccupied && (N*(skhp == -1 ? 1 : sknside*sknside*12) < NHP)) { logmsg("\n\n"); logmsg("NOTE, your star kdtree is sparse (has only a fraction of the stars expected)\n"); logmsg(" so you probably will get much faster results by setting the \"-E\" command-line\n"); logmsg(" flag.\n"); logmsg("\n\n"); } quads->dimquads = me->dimquads; codes->dimcodes = dimcodes; quads->healpix = skhp; codes->healpix = skhp; quads->hpnside = sknside; codes->hpnside = sknside; if (id) { quads->indexid = id; codes->indexid = id; } qhdr = quadfile_get_header(quads); chdr = codefile_get_header(codes); add_headers(qhdr, args, argc, startree_header(me->starkd), circle, passes); add_headers(chdr, args, argc, startree_header(me->starkd), circle, passes); if (quadfile_write_header(quads)) { ERROR("Couldn't write headers to quad file"); return -1; } if (codefile_write_header(codes)) { ERROR("Couldn't write headers to code file"); return -1; } quads->numstars = codes->numstars = N; me->quad_dist2_upper = arcmin2distsq(scale_max_arcmin); me->quad_dist2_lower = arcmin2distsq(scale_min_arcmin); codes->index_scale_upper = quads->index_scale_upper = distsq2rad(me->quad_dist2_upper); codes->index_scale_lower = quads->index_scale_lower = distsq2rad(me->quad_dist2_lower); me->nuses = calloc(N, sizeof(unsigned char)); // hprad = sqrt(2) * (healpix side length / 2.) hprad = arcmin2dist(healpix_side_length_arcmin(Nside)) * M_SQRT1_2; quadscale = 0.5 * sqrt(me->quad_dist2_upper); // 1.01 for a bit of safety. we'll look at a few extra stars. radius2 = square(1.01 * (hprad + quadscale)); me->radius2 = radius2; logmsg("Healpix radius %g arcsec, quad scale %g arcsec, total %g arcsec\n", distsq2arcsec(hprad*hprad), distsq2arcsec(quadscale*quadscale), distsq2arcsec(radius2)); hptotry = il_new(1024); if (scanoccupied) { logmsg("Scanning %i input stars...\n", N); for (i=0; i<N; i++) { double xyz[3]; int j; if (startree_get(me->starkd, i, xyz)) { ERROR("Failed to get star %i", i); return -1; } j = xyzarrtohealpix(xyz, Nside); il_insert_unique_ascending(hptotry, j); if (log_get_level() > LOG_VERB) { double ra,dec; if (startree_get_radec(me->starkd, i, &ra, &dec)) { ERROR("Failed to get RA,Dec for star %i\n", i); return -1; } logdebug("star %i: RA,Dec %g,%g; xyz %g,%g,%g; hp %i\n", i, ra, dec, xyz[0], xyz[1], xyz[2], j); } } logmsg("Will check %zu healpixes.\n", il_size(hptotry)); if (log_get_level() > LOG_VERB) { logdebug("Checking healpixes: [ "); for (i=0; i<il_size(hptotry); i++) logdebug("%i ", il_get(hptotry, i)); logdebug("]\n"); } } else { if (skhp == -1) { // Try all healpixes. il_free(hptotry); hptotry = NULL; Nhptotry = NHP; } else { // The star kdtree may itself be healpixed int starhp, starx, stary; // In that case, the healpixes we are interested in form a rectangle // within a big healpix. These are the coords (in [0, Nside)) of // that rectangle. int x0, x1, y0, y1; int x, y; healpix_decompose_xy(skhp, &starhp, &starx, &stary, sknside); x0 = starx * (Nside / sknside); x1 = (starx+1) * (Nside / sknside); y0 = stary * (Nside / sknside); y1 = (stary+1) * (Nside / sknside); for (y=y0; y<y1; y++) { for (x=x0; x<x1; x++) { int j = healpix_compose_xy(starhp, x, y, Nside); il_append(hptotry, j); } } assert(il_size(hptotry) == (Nside/sknside) * (Nside/sknside)); } } if (hptotry) Nhptotry = il_size(hptotry); me->quadlist = bl_new(65536, quadsize); if (Nloosen) me->retryhps = il_new(1024); for (pass=0; pass<passes; pass++) { char key[64]; int nthispass; logmsg("Pass %i of %i.\n", pass+1, passes); logmsg("Trying %i healpixes.\n", Nhptotry); nthispass = build_quads(me, Nhptotry, hptotry, Nreuses); logmsg("Made %i quads (out of %i healpixes) this pass.\n", nthispass, Nhptotry); logmsg("Made %i quads so far.\n", (me->bigquadlist ? bt_size(me->bigquadlist) : 0) + (int)bl_size(me->quadlist)); sprintf(key, "PASS%i", pass+1); fits_header_mod_int(chdr, key, nthispass, "quads created in this pass"); fits_header_mod_int(qhdr, key, nthispass, "quads created in this pass"); logmsg("Merging quads...\n"); if (!me->bigquadlist) me->bigquadlist = bt_new(quadsize, 256); for (i=0; i<bl_size(me->quadlist); i++) { void* q = bl_access(me->quadlist, i); bt_insert2(me->bigquadlist, q, FALSE, compare_quads, &me->dimquads); } bl_remove_all(me->quadlist); } il_free(hptotry); hptotry = NULL; if (Nloosen) { int R; for (R=Nreuses+1; R<=Nloosen; R++) { il* trylist; int nthispass; logmsg("Loosening reuse maximum to %i...\n", R); logmsg("Trying %zu healpixes.\n", il_size(me->retryhps)); if (!il_size(me->retryhps)) break; trylist = me->retryhps; me->retryhps = il_new(1024); nthispass = build_quads(me, il_size(trylist), trylist, R); logmsg("Made %i quads (out of %zu healpixes) this pass.\n", nthispass, il_size(trylist)); il_free(trylist); for (i=0; i<bl_size(me->quadlist); i++) { void* q = bl_access(me->quadlist, i); bt_insert2(me->bigquadlist, q, FALSE, compare_quads, &me->dimquads); } bl_remove_all(me->quadlist); } } if (me->retryhps) il_free(me->retryhps); kdtree_free_query(me->res); me->res = NULL; me->inds = NULL; me->stars = NULL; free(me->nuses); me->nuses = NULL; logmsg("Writing quads...\n"); // add the quads from the big-quadlist nquads = bt_size(me->bigquadlist); for (i=0; i<nquads; i++) { unsigned int* q = bt_access(me->bigquadlist, i); quad_write(codes, quads, q, me->starkd, me->dimquads, dimcodes); } // add the quads that were made during the final round. for (i=0; i<bl_size(me->quadlist); i++) { unsigned int* q = bl_access(me->quadlist, i); quad_write(codes, quads, q, me->starkd, me->dimquads, dimcodes); } // fix output file headers. if (quadfile_fix_header(quads)) { ERROR("Failed to fix quadfile headers"); return -1; } if (codefile_fix_header(codes)) { ERROR("Failed to fix codefile headers"); return -1; } bl_free(me->quadlist); bt_free(me->bigquadlist); toc(); logmsg("Done.\n"); return 0; }
int main(int argc, char** 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; }
/** If "inds" is non-NULL, it's a list of indices to read. */ static void* read_array_into(const fitstable_t* tab, const char* colname, tfits_type ctype, anbool array_ok, int offset, const int* inds, int Nread, void* dest, int deststride, int desired_arraysize, int* p_arraysize) { int colnum; qfits_col* col; int fitssize; int csize; int fitstype; int arraysize; char* tempdata = NULL; char* cdata; char* fitsdata; int cstride; int fitsstride; int N; colnum = fits_find_column(tab->table, colname); if (colnum == -1) { ERROR("Column \"%s\" not found in FITS table %s", colname, tab->fn); return NULL; } col = tab->table->col + colnum; if (!array_ok && (col->atom_nb != 1)) { ERROR("Column \"%s\" in FITS table %s is an array of size %i, not a scalar", colname, tab->fn, col->atom_nb); return NULL; } arraysize = col->atom_nb; if (p_arraysize) *p_arraysize = arraysize; if (desired_arraysize && arraysize != desired_arraysize) { ERROR("Column \"%s\" has array size %i but you wanted %i", colname, arraysize, desired_arraysize); return NULL; } fitstype = col->atom_type; fitssize = fits_get_atom_size(fitstype); csize = fits_get_atom_size(ctype); N = tab->table->nr; if (Nread == -1) Nread = N; if (offset == -1) offset = 0; if (dest) cdata = dest; else cdata = calloc(Nread * arraysize, csize); if (dest && deststride > 0) cstride = deststride; else cstride = csize * arraysize; fitsstride = fitssize * arraysize; if (csize < fitssize) { // Need to allocate a bigger temp array and down-convert the data. // HACK - could set data=tempdata and realloc after (if 'dest' is NULL) tempdata = calloc(Nread * arraysize, fitssize); fitsdata = tempdata; } else { // We'll read the data into the first fraction of the output array. fitsdata = cdata; } if (in_memory(tab)) { int i; int off; int sz; if (!tab->rows) { ERROR("No data has been written to this fitstable"); return NULL; } if (offset + Nread > bl_size(tab->rows)) { ERROR("Number of data items requested exceeds number of rows: offset %i, n %i, nrows %zu", offset, Nread, bl_size(tab->rows)); return NULL; } off = fits_offset_of_column(tab->table, colnum); sz = fitsstride; if (inds) { for (i=0; i<Nread; i++) memcpy(fitsdata + i * fitsstride, ((char*)bl_access(tab->rows, inds[i])) + off, sz); } else { for (i=0; i<Nread; i++) memcpy(fitsdata + i * fitsstride, ((char*)bl_access(tab->rows, offset+i)) + off, sz); } } else { int res; if (inds) { res = qfits_query_column_seq_to_array_inds(tab->table, colnum, inds, Nread, (unsigned char*)fitsdata, fitsstride); } else { res = qfits_query_column_seq_to_array(tab->table, colnum, offset, Nread, (unsigned char*)fitsdata, fitsstride); } if (res) { ERROR("Failed to read column from FITS file"); // MEMLEAK! return NULL; } } if (fitstype != ctype) { if (csize <= fitssize) { // work forward fits_convert_data(cdata, cstride, ctype, fitsdata, fitsstride, fitstype, arraysize, Nread); } else { // work backward from the end of the array fits_convert_data(cdata + (((off_t)Nread*(off_t)arraysize)-1) * (off_t)csize, -csize, ctype, fitsdata + (((off_t)Nread*(off_t)arraysize)-1) * (off_t)fitssize, -fitssize, fitstype, 1, Nread * arraysize); } } free(tempdata); return cdata; }
static int ncols(const fitstable_t* t) { return bl_size(t->cols); }
int fitstable_read_structs(fitstable_t* tab, void* struc, int strucstride, int offset, int N) { int i; void* tempdata = NULL; int highwater = 0; //printf("fitstable_read_structs: stride %i, offset %i, N %i\n",strucstride, offset, N); for (i=0; i<ncols(tab); i++) { void* dest; int stride; void* finaldest; int finalstride; fitscol_t* col = getcol(tab, i); if (col->col == -1) continue; if (!col->in_struct) continue; finaldest = ((char*)struc) + col->coffset; finalstride = strucstride; if (col->fitstype != col->ctype) { int NB = fitscolumn_get_size(col) * N; if (NB > highwater) { free(tempdata); tempdata = malloc(NB); highwater = NB; } dest = tempdata; stride = fitscolumn_get_size(col); } else { dest = finaldest; stride = finalstride; } if (in_memory(tab)) { int j; int off = offset_of_column(tab, i); int sz; if (!tab->rows) { ERROR("No data has been written to this fitstable"); return -1; } if (offset + N > bl_size(tab->rows)) { ERROR("Number of data items requested exceeds number of rows: offset %i, n %i, nrows %zu", offset, N, bl_size(tab->rows)); return -1; } //logverb("column %i: dest offset %i, stride %i, row offset %i, input offset %i, size %i (%ix%i)\n", i, (int)(dest - struc), stride, offset, off, fitscolumn_get_size(col), col->fitssize, col->arraysize); sz = fitscolumn_get_size(col); for (j=0; j<N; j++) memcpy(((char*)dest) + j * stride, ((char*)bl_access(tab->rows, offset+j)) + off, sz); } else { // Read from FITS file... qfits_query_column_seq_to_array(tab->table, col->col, offset, N, dest, stride); } if (col->fitstype != col->ctype) { fits_convert_data(finaldest, finalstride, col->ctype, dest, stride, col->fitstype, col->arraysize, N); } } free(tempdata); if (tab->postprocess_read_structs) return tab->postprocess_read_structs(tab, struc, strucstride, offset, N); return 0; }
void test_hd_1(CuTest* tc) { hd_catalog_t* hdcat; int* invperm; int* present; int ind, i, N; double xyz[3]; double ra, dec; int strangehds[] = { 40142, 40441, 40672, 40746, 40763, 40764, 104176, 104193, 163635, 224698, 224699, 129371 }; if (!file_readable("hd.fits")) { printf("File \"hd.fits\" does not exist; test skipped.\n"); return; } hdcat = henry_draper_open("hd.fits"); CuAssertPtrNotNull(tc, hdcat); N = hdcat->kd->ndata; invperm = calloc(N, sizeof(int)); CuAssertPtrNotNull(tc, invperm); CuAssertIntEquals(tc, 0, kdtree_check(hdcat->kd)); kdtree_inverse_permutation(hdcat->kd, invperm); present = calloc(N, sizeof(int)); for (i=0; i<N; i++) { CuAssert(tc, "invperm in range", invperm[i] < N); present[invperm[i]]++; } for (i=0; i<N; i++) { CuAssertIntEquals(tc, 1, present[i]); } free(present); // Where is "HD n" ? for (i=0; i<10; i++) { bl* res; int j; ind = invperm[i]; kdtree_copy_data_double(hdcat->kd, ind, 1, xyz); xyzarr2radecdeg(xyz, &ra, &dec); printf("HD %i: RA,Dec %g, %g\n", i+1, ra, dec); res = henry_draper_get(hdcat, ra, dec, 10.0); CuAssertPtrNotNull(tc, res); for (j=0; j<bl_size(res); j++) { hd_entry_t* hd = bl_access(res, j); printf("res %i: HD %i, RA, Dec %g, %g\n", j, hd->hd, hd->ra, hd->dec); } bl_free(res); } for (i=0; i<sizeof(strangehds)/sizeof(int); i++) { ind = invperm[strangehds[i]-1]; kdtree_copy_data_double(hdcat->kd, ind, 1, xyz); xyzarr2radecdeg(xyz, &ra, &dec); printf("HD %i: RA,Dec %g, %g\n", strangehds[i], ra, dec); } free(invperm); henry_draper_close(hdcat); }
int plotstuff_plot_stack(plot_args_t* pargs, cairo_t* cairo) { int i, j; int layer; anbool morelayers; logverb("Plotting %zu stacked plot commands.\n", bl_size(pargs->cairocmds)); morelayers = TRUE; for (layer=0;; layer++) { if (!morelayers) break; morelayers = FALSE; for (i=0; i<bl_size(pargs->cairocmds); i++) { cairocmd_t* cmd = bl_access(pargs->cairocmds, i); if (cmd->layer > layer) morelayers = TRUE; if (cmd->layer != layer) continue; cairo_set_rgba(cairo, cmd->rgba); switch (cmd->type) { case CIRCLE: cairo_move_to(cairo, cmd->x + cmd->radius, cmd->y); cairo_arc(cairo, cmd->x, cmd->y, cmd->radius, 0, 2*M_PI); break; case MARKER: { double oldmarkersize = pargs->markersize; int oldmarker = pargs->marker; pargs->markersize = cmd->markersize; pargs->marker = cmd->marker; plotstuff_marker(pargs, cmd->x, cmd->y); pargs->markersize = oldmarkersize; pargs->marker = oldmarker; } break; case TEXT: cairo_move_to(cairo, cmd->x, cmd->y); cairo_show_text(cairo, cmd->text); break; case LINE: case ARROW: plotstuff_move_to(pargs, cmd->x, cmd->y); plotstuff_line_to(pargs, cmd->x2, cmd->y2); { double dx = cmd->x - cmd->x2; double dy = cmd->y - cmd->y2; double angle = atan2(dy, dx); double dang = 30. * M_PI/180.0; double arrowlen = 20; plotstuff_line_to(pargs, cmd->x2 + cos(angle+dang)*arrowlen, cmd->y2 + sin(angle+dang)*arrowlen); plotstuff_move_to(pargs, cmd->x2, cmd->y2); plotstuff_line_to(pargs, cmd->x2 + cos(angle-dang)*arrowlen, cmd->y2 + sin(angle-dang)*arrowlen); } break; case RECTANGLE: ERROR("Unimplemented!"); return -1; case POLYGON: if (!cmd->xy) break; for (j=0; j<dl_size(cmd->xy)/2; j++) (j == 0 ? cairo_move_to : cairo_line_to)(cairo, dl_get(cmd->xy, 2*j+0), dl_get(cmd->xy, 2*j+1)); if (cmd->fill) cairo_fill(cairo); break; } cairo_stroke(cairo); } } for (i=0; i<bl_size(pargs->cairocmds); i++) { cairocmd_t* cmd = bl_access(pargs->cairocmds, i); cairocmd_clear(cmd); } bl_remove_all(pargs->cairocmds); return 0; }
int fitstable_get_struct_size(const fitstable_t* table) { int rowsize = offset_of_column(table, bl_size(table->cols)); return rowsize; }
void test2() { int i; solver_t* solver; index_t index; starxy_t* starxy; int wanted[][3] = { { 0, 1, 3 }, { 0, 1, 4 }, { 0, 1, 5 }, { 0, 2, 3 }, { 0, 2, 4 }, { 0, 3, 4 }, { 0, 5, 4 }, { 0, 6, 4 }, { 0, 6, 5 }, { 1, 2, 3 }, { 1, 2, 4 }, { 1, 3, 4 }, { 1, 5, 4 }, { 1, 6, 4 }, { 1, 6, 5 }, { 2, 4, 3 }, { 2, 5, 0 }, { 2, 5, 1 }, { 2, 5, 3 }, { 2, 5, 4 }, { 2, 6, 0 }, { 2, 6, 1 }, { 2, 6, 3 }, { 2, 6, 4 }, { 2, 6, 5 }, { 3, 5, 4 }, { 3, 6, 0 }, { 3, 6, 1 }, { 3, 6, 4 }, { 3, 6, 5 }, { 4, 6, 5 }, }; starxy = field1(); quadlist = bl_new(16, 3*sizeof(uint)); solver = solver_new(); memset(&index, 0, sizeof(index_t)); index.index_scale_lower = 1; index.index_scale_upper = 10; index.dimquads = 3; solver->funits_lower = 0.1; solver->funits_upper = 10; solver_add_index(solver, &index); solver_set_field(solver, starxy); solver_preprocess_field(solver); solver_run(solver); solver_free_field(solver); solver_free(solver); // assert(bl_size(quadlist) == (sizeof(wanted) / (3*sizeof(uint)))); bl_sort(quadlist, compare_tri); for (i=0; i<bl_size(quadlist); i++) { assert(compare_tri(bl_access(quadlist, i), wanted[i]) == 0); } bl_free(quadlist); }
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; }
static startree_t* my_open(const char* fn, anqfits_t* fits) { struct timeval tv1, tv2; startree_t* s; bl* chunks; int i; kdtree_fits_t* io; char* treename = STARTREE_NAME; const char* thefn = fn; assert(fn || fits); if (!thefn) thefn = fits->filename; s = startree_alloc(); if (!s) return NULL; gettimeofday(&tv1, NULL); if (fn) io = kdtree_fits_open(fn); else io = kdtree_fits_open_fits(fits); gettimeofday(&tv2, NULL); debug("kdtree_fits_open() took %g ms\n", millis_between(&tv1, &tv2)); if (!io) { ERROR("Failed to open FITS file \"%s\"", thefn); goto bailout; } gettimeofday(&tv1, NULL); if (!kdtree_fits_contains_tree(io, treename)) treename = NULL; gettimeofday(&tv2, NULL); debug("kdtree_fits_contains_tree() took %g ms\n", millis_between(&tv1, &tv2)); gettimeofday(&tv1, NULL); s->tree = kdtree_fits_read_tree(io, treename, &s->header); gettimeofday(&tv2, NULL); debug("kdtree_fits_read_tree() took %g ms\n", millis_between(&tv1, &tv2)); if (!s->tree) { ERROR("Failed to read kdtree from file \"%s\"", thefn); goto bailout; } // Check the tree dimensionality. // (because code trees can be confused...) if (s->tree->ndim != 3) { logverb("File %s contains a kd-tree with dim %i (not 3), named %s\n", thefn, s->tree->ndim, treename); s->tree->io = NULL; goto bailout; } gettimeofday(&tv1, NULL); chunks = get_chunks(s, NULL); for (i=0; i<bl_size(chunks); i++) { fitsbin_chunk_t* chunk = bl_access(chunks, i); void** dest = chunk->userdata; kdtree_fits_read_chunk(io, chunk); *dest = chunk->data; } bl_free(chunks); gettimeofday(&tv2, NULL); debug("reading chunks took %g ms\n", millis_between(&tv1, &tv2)); // kdtree_fits_t is a typedef of fitsbin_t fitsbin_close_fd(io); return s; bailout: kdtree_fits_io_close(io); startree_close(s); return NULL; }
static int write_to_file(startree_t* s, const char* fn, anbool flipped, FILE* fid) { bl* chunks; il* wordsizes = NULL; int i; kdtree_fits_t* io = NULL; // just haven't bothered... assert(!(flipped && fid)); if (fn) { io = kdtree_fits_open_for_writing(fn); if (!io) { ERROR("Failed to open file \"%s\" for writing kdtree", fn); return -1; } } if (flipped) { if (kdtree_fits_write_tree_flipped(io, s->tree, s->header)) { ERROR("Failed to write (flipped) kdtree to file \"%s\"", fn); return -1; } } else { if (fid) { if (kdtree_fits_append_tree_to(s->tree, s->header, fid)) { ERROR("Failed to write star kdtree"); return -1; } } else { if (kdtree_fits_write_tree(io, s->tree, s->header)) { ERROR("Failed to write kdtree to file \"%s\"", fn); return -1; } } } if (flipped) wordsizes = il_new(4); chunks = get_chunks(s, wordsizes); for (i=0; i<bl_size(chunks); i++) { fitsbin_chunk_t* chunk = bl_access(chunks, i); if (!chunk->data) continue; if (flipped) kdtree_fits_write_chunk_flipped(io, chunk, il_get(wordsizes, i)); else { if (fid) { kdtree_fits_write_chunk_to(chunk, fid); } else { kdtree_fits_write_chunk(io, chunk); } } fitsbin_chunk_clean(chunk); } bl_free(chunks); if (flipped) il_free(wordsizes); if (io) kdtree_fits_io_close(io); return 0; }
static void plot_targets(cairo_t* cairo, plot_args_t* pargs, plotann_t* ann) { int i; double cra, cdec; plotstuff_get_radec_center_and_radius(pargs, &cra, &cdec, NULL); for (i=0; i<bl_size(ann->targets); i++) { target_t* tar = bl_access(ann->targets, i); double px,py; double cx,cy; double dx,dy, r; double ex,ey; double ly, ry, tx, bx; double distdeg; anbool okquadrant; char* txt; logverb("Target: \"%s\" at (%g,%g)\n", tar->name, tar->ra, tar->dec); okquadrant = plotstuff_radec2xy(pargs, tar->ra, tar->dec, &px, &py); px -= 1; py -= 1; if (okquadrant && px >= 0 && px < pargs->W && py >= 0 && py < pargs->H) { // inside the image! logverb("Target \"%s\" is inside the image, at pixel (%g,%g)\n", tar->name, px, py); plotstuff_stack_marker(pargs, px, py); plotstuff_stack_text(pargs, cairo, tar->name, px, py); continue; } // outside the image: find intersection point. cx = pargs->W / 2.0; cy = pargs->H / 2.0; if (okquadrant) { logverb("Target \"%s\" is outside the image, at pixel (%g,%g)\n", tar->name, px, py); dx = px - cx; dy = py - cy; } else { double cxyz[3]; double txyz[3]; double vec[3]; int j; double ra,dec; logverb("Target \"%s\" is way outside the image.\n", tar->name); // fallback. radecdeg2xyzarr(cra, cdec, cxyz); radecdeg2xyzarr(tar->ra, tar->dec, txyz); for (j=0; j<3; j++) vec[j] = cxyz[j] + 0.1 * txyz[j]; normalize_3(vec); xyzarr2radecdeg(vec, &ra, &dec); okquadrant = plotstuff_radec2xy(pargs, ra, dec, &px, &py); assert(okquadrant); dx = px - cx; dy = py - cy; if ((dx*dx + dy*dy) < (cx*cx + cy*cy)) { double scale = 3.0 * sqrt(cx*cx + cy*cy) / sqrt(dx*dx + dy*dy); dx *= scale; dy *= scale; } } ly = (-(pargs->W/2.0) / dx) * dy + cy; ry = ( (pargs->W/2.0) / dx) * dy + cy; bx = (-(pargs->H/2.0) / dy) * dx + cx; tx = ( (pargs->H/2.0) / dy) * dx + cx; logverb("ly %g, ry %g, bx %g, tx %g\n", ly, ry, bx, tx); if (px < cx && ly >= 0 && ly < pargs->H) { ex = 0.0; ey = ly; } else if (px >= cx && ry >= 0 && ry < pargs->H) { ex = pargs->W - 1; ey = ry; } else if (py < cy && bx >= 0 && bx < pargs->W) { ex = bx; ey = 0; } else if (py >= cy && tx >= 0 && tx < pargs->W) { ex = tx; ey = pargs->H - 1; } else { logverb("None of the edges are in bounds: px,py=(%g,%g); ly=%g, ry=%g, bx=%g, tx=%g\n", px,py,ly,ry,bx,tx); continue; } dx = ex - cx; dy = ey - cy; r = sqrt(dx*dx + dy*dy); px = (r-100.0) / r * dx + cx; py = (r-100.0) / r * dy + cy; plotstuff_stack_arrow(pargs, px, py, ex, ey); logverb("Arrow from (%g,%g) to (%g,%g)\n", px, py, ex, ey); distdeg = deg_between_radecdeg(cra, cdec, tar->ra, tar->dec); asprintf_safe(&txt, "%s: %.1f deg", tar->name, distdeg); plotstuff_stack_text(pargs, cairo, txt, px, py); } }
int main(int argc, char** args) { int argchar; char* infn = NULL; char* outfn = NULL; unsigned int row; int bits; FILE* fid = stdin; FILE* fout = stdout; int loglvl = LOG_MSG; char* progname = args[0]; int bzero = 0; int outformat; qfits_header* hdr; unsigned int plane; off_t datastart; anbool onepass = FALSE; bl* pixcache = NULL; #if HAVE_NETPBM struct pam img; tuple * tuplerow; #else void* rowbuf; #endif int W, H, depth, maxval; while ((argchar = getopt (argc, args, OPTIONS)) != -1) switch (argchar) { case '?': case 'h': printHelp(progname); exit(0); case 'v': loglvl++; break; case 'q': loglvl--; break; case 'o': outfn = optarg; break; } log_init(loglvl); log_to(stderr); fits_use_error_system(); if (optind == argc) { // ok, stdin to stdout. } else if (optind == argc-1) { infn = args[optind]; } else if (optind == argc-2) { infn = args[optind]; outfn = args[optind+1]; } else { printHelp(progname); exit(-1); } if (infn && !streq(infn, "-")) { fid = fopen(infn, "rb"); if (!fid) { SYSERROR("Failed to open input file %s", infn); exit(-1); } } if (outfn) { fout = fopen(outfn, "wb"); if (!fid) { SYSERROR("Failed to open output file %s", outfn); exit(-1); } } else outfn = "stdout"; #if HAVE_NETPBM pm_init(args[0], 0); pnm_readpaminit(fid, &img, // PAM_STRUCT_SIZE isn't defined until Netpbm 10.23 (July 2004) #if defined(PAM_STRUCT_SIZE) PAM_STRUCT_SIZE(tuple_type) #else sizeof(struct pam) #endif ); W = img.width; H = img.height; depth = img.depth; maxval = img.maxval; tuplerow = pnm_allocpamrow(&img); bits = pm_maxvaltobits(img.maxval); bits = (bits <= 8) ? 8 : 16; #else // No NETPBM if (parse_pnm_header(fid, &W, &H, &depth, &maxval)) { ERROR("Failed to parse PNM header from file: %s\n", infn ? infn : "<stdin>"); exit(-1); } bits = 8 * maxval_to_bytes(maxval); rowbuf = malloc(W * depth * (bits/8)); #endif logmsg("Read file %s: %i x %i pixels x %i color(s); maxval %i\n", infn ? infn : "stdin", W, H, depth, maxval); if (bits == 8) outformat = BPP_8_UNSIGNED; else { outformat = BPP_16_SIGNED; if (maxval >= INT16_MAX) bzero = 0x8000; } logmsg("Using %i-bit output\n", bits); hdr = fits_get_header_for_image3(W, H, outformat, depth, NULL); if (bzero) fits_header_add_int(hdr, "BZERO", bzero, "Number that has been subtracted from pixel values"); if (qfits_header_dump(hdr, fout)) { ERROR("Failed to write FITS header to file %s", outfn); exit(-1); } qfits_header_destroy(hdr); datastart = ftello(fid); // Figure out if we can seek backward in this input file... if ((fid == stdin) || (fseeko(fid, 0, SEEK_SET) || fseeko(fid, datastart, SEEK_SET))) // Nope! onepass = TRUE; if (onepass && depth > 1) { logmsg("Reading in one pass\n"); pixcache = bl_new(16384, bits/8); } for (plane=0; plane<depth; plane++) { if (plane > 0) { if (fseeko(fid, datastart, SEEK_SET)) { SYSERROR("Failed to seek back to start of image data"); exit(-1); } } for (row = 0; row<H; row++) { unsigned int column; #if HAVE_NETPBM pnm_readpamrow(&img, tuplerow); #else read_pnm_row(fid, W, depth, maxval, rowbuf); #endif for (column = 0; column<W; column++) { int rtn; int pixval; #if HAVE_NETPBM pixval = tuplerow[column][plane]; #else pixval = (bits == 8 ? ((uint8_t *)rowbuf)[column*depth + plane] : ((uint16_t*)rowbuf)[column*depth + plane]); #endif if (outformat == BPP_8_UNSIGNED) rtn = fits_write_data_B(fout, pixval); else rtn = fits_write_data_I(fout, pixval-bzero, TRUE); if (rtn) { ERROR("Failed to write FITS pixel"); exit(-1); } } if (onepass && depth > 1) { for (column = 0; column<W; column++) { for (plane=1; plane<depth; plane++) { int pixval; #if HAVE_NETPBM pixval = tuplerow[column][plane]; #else pixval = (bits == 8 ? ((uint8_t *)rowbuf)[column*depth + plane] : ((uint16_t*)rowbuf)[column*depth + plane]); #endif if (outformat == BPP_8_UNSIGNED) { uint8_t pix = pixval; bl_append(pixcache, &pix); } else { int16_t pix = pixval - bzero; bl_append(pixcache, &pix); } } } } } } #if HAVE_NETPBM pnm_freepamrow(tuplerow); #else free(rowbuf); #endif if (pixcache) { int i, j; int step = (depth - 1); logverb("Writing %zu queued pixels\n", bl_size(pixcache)); for (plane=1; plane<depth; plane++) { j = (plane - 1); for (i=0; i<(W * H); i++) { int rtn; if (outformat == BPP_8_UNSIGNED) { uint8_t* pix = bl_access(pixcache, j); rtn = fits_write_data_B(fout, *pix); } else { int16_t* pix = bl_access(pixcache, j); rtn = fits_write_data_I(fout, *pix, TRUE); } if (rtn) { ERROR("Failed to write FITS pixel"); exit(-1); } j += step; } } bl_free(pixcache); } if (fid != stdin) fclose(fid); if (fits_pad_file(fout)) { ERROR("Failed to pad output file \"%s\"", outfn); return -1; } if (fout != stdout) if (fclose(fout)) { SYSERROR("Failed to close output file %s", outfn); exit(-1); } return 0; }