qidxfile* qidxfile_open_for_writing(const char* fn, int nstars, int nquads) { qidxfile* qf; qfits_header* hdr; qf = new_qidxfile(fn, TRUE); if (!qf) goto bailout; qf->numstars = nstars; qf->numquads = nquads; hdr = fitsbin_get_primary_header(qf->fb); fits_add_endian(hdr); fits_header_add_int(hdr, "NSTARS", qf->numstars, "Number of stars used."); fits_header_add_int(hdr, "NQUADS", qf->numquads, "Number of quads used."); qfits_header_add(hdr, "AN_FILE", "QIDX", "This is a quad index file.", NULL); qfits_header_add(hdr, "COMMENT", "The data table of this file has two parts:", NULL, NULL); qfits_header_add(hdr, "COMMENT", " -the index", NULL, NULL); qfits_header_add(hdr, "COMMENT", " -the heap", NULL, NULL); fits_add_long_comment(hdr, "The index contains two uint32 values for each star: the offset and " "length, in the heap, of the list of quads to which it belongs. " "The offset and length are in units of uint32s, not bytes. " "Offset 0 is the first uint32 in the heap. " "The heap is ordered and tightly packed. " "The heap is a flat list of quad indices (uint32s)."); return qf; bailout: if (qf) qidxfile_close(qf); return NULL; }
static codefile_t* open_for_writing(const char* fn) { codefile_t* cf; qfits_header* hdr; if (fn) cf = new_codefile(fn, TRUE, FALSE); else cf = new_codefile(fn, TRUE, TRUE); if (!cf) goto bailout; // default cf->dimcodes = 4; // add default values to header hdr = codefile_get_header(cf); fits_add_endian(hdr); qfits_header_add(hdr, "AN_FILE", "CODE", "This file lists the code for each quad.", NULL); qfits_header_add(hdr, "NCODES", "0", "", NULL); qfits_header_add(hdr, "NSTARS", "0", "", NULL); fits_header_add_int(hdr, "DIMCODES", cf->dimcodes, ""); qfits_header_add(hdr, "SCALE_U", "0.0", "", NULL); qfits_header_add(hdr, "SCALE_L", "0.0", "", NULL); qfits_header_add(hdr, "INDEXID", "0", "", NULL); qfits_header_add(hdr, "HEALPIX", "-1", "", NULL); qfits_header_add(hdr, "HPNSIDE", "1", "", NULL); fits_add_long_comment(hdr, "The first extension contains the codes " "stored as %i native-endian doubles. " "(the quad location in %i-D code space)", cf->dimcodes, cf->dimcodes); return cf; bailout: if (cf) codefile_close(cf); return NULL; }
void sip_add_to_header(qfits_header* hdr, const sip_t* sip) { wcs_hdr_common(hdr, &(sip->wcstan)); if (sip->wcstan.sin) { qfits_header_add_after(hdr, "WCSAXES", "CTYPE2", "DEC--SIN-SIP", "SIN projection + SIP distortions", NULL); qfits_header_add_after(hdr, "WCSAXES", "CTYPE1", "RA---SIN-SIP", "SIN projection + SIP distortions", NULL); } else { qfits_header_add_after(hdr, "WCSAXES", "CTYPE2", "DEC--TAN-SIP", "TAN (gnomic) projection + SIP distortions", NULL); qfits_header_add_after(hdr, "WCSAXES", "CTYPE1", "RA---TAN-SIP", "TAN (gnomic) projection + SIP distortions", NULL); } fits_header_add_int(hdr, "A_ORDER", sip->a_order, "Polynomial order, axis 1"); add_polynomial(hdr, "A_%i_%i", sip->a_order, (double*)sip->a, SIP_MAXORDER); fits_header_add_int(hdr, "B_ORDER", sip->b_order, "Polynomial order, axis 2"); add_polynomial(hdr, "B_%i_%i", sip->b_order, (double*)sip->b, SIP_MAXORDER); fits_header_add_int(hdr, "AP_ORDER", sip->ap_order, "Inv polynomial order, axis 1"); add_polynomial(hdr, "AP_%i_%i", sip->ap_order, (double*)sip->ap, SIP_MAXORDER); fits_header_add_int(hdr, "BP_ORDER", sip->bp_order, "Inv polynomial order, axis 2"); add_polynomial(hdr, "BP_%i_%i", sip->bp_order, (double*)sip->bp, SIP_MAXORDER); }
int main(int argc, char** args) { char* outfn = "ucac4_%03i.fits"; int c; int startoptind; int nrecords, nfiles; int Nside = 9; ucac4_fits** ucacs; int i, HP; int slicecounts[1800]; while ((c = getopt(argc, args, OPTIONS)) != -1) { switch (c) { case '?': case 'h': print_help(args[0]); exit(0); case 'N': Nside = atoi(optarg); break; case 'o': outfn = optarg; break; } } log_init(LOG_MSG); if (!outfn || (optind == argc)) { print_help(args[0]); exit(-1); } if (Nside < 1) { fprintf(stderr, "Nside must be >= 1.\n"); print_help(args[0]); exit(-1); } HP = 12 * Nside * Nside; printf("Nside = %i, using %i healpixes.\n", Nside, HP); ucacs = calloc(HP, sizeof(ucac4_fits*)); memset(slicecounts, 0, 1800 * sizeof(uint)); nrecords = 0; nfiles = 0; startoptind = optind; for (; optind<argc; optind++) { char* infn; FILE* fid; BZFILE* bzfid; int bzerr; int i; infn = args[optind]; printf("Reading %s\n", infn); if ((optind > startoptind) && ((optind - startoptind) % 100 == 0)) { printf("\nReading file %i of %i: %s\n", optind - startoptind, argc - startoptind, infn); } fflush(stdout); fid = fopen(infn, "rb"); if (!fid) { SYSERROR("Couldn't open input file \"%s\"", infn); exit(-1); } // MAGIC 1: bzip verbosity: [0=silent, 4=debug] // 0: small -- don't use less memory bzfid = BZ2_bzReadOpen(&bzerr, fid, 1, 0, NULL, 0); CHECK_BZERR(); for (i=0;; i++) { ucac4_entry entry; int hp; char buf[UCAC4_RECORD_SIZE]; int nr; anbool eof = 0; nr = BZ2_bzRead(&bzerr, bzfid, buf, UCAC4_RECORD_SIZE); if ((bzerr == BZ_STREAM_END) && (nr == UCAC4_RECORD_SIZE)) eof = TRUE; else CHECK_BZERR(); if (ucac4_parse_entry(&entry, buf)) { ERROR("Failed to parse UCAC4 entry %i in file \"%s\".", i, infn); exit(-1); } hp = radecdegtohealpix(entry.ra, entry.dec, Nside); if (!ucacs[hp]) { char fn[256]; sprintf(fn, outfn, hp); ucacs[hp] = ucac4_fits_open_for_writing(fn); if (!ucacs[hp]) { ERROR("Failed to initialize FITS file %i (filename %s)", hp, fn); exit(-1); } fits_header_add_int(ucacs[hp]->header, "HEALPIX", hp, "The healpix number of this catalog."); fits_header_add_int(ucacs[hp]->header, "NSIDE", Nside, "The healpix resolution."); BOILERPLATE_ADD_FITS_HEADERS(ucacs[hp]->header); qfits_header_add(ucacs[hp]->header, "HISTORY", "Created by the program \"ucac4tofits\"", NULL, NULL); qfits_header_add(ucacs[hp]->header, "HISTORY", "ucac4tofits command line:", NULL, NULL); fits_add_args(ucacs[hp]->header, args, argc); qfits_header_add(ucacs[hp]->header, "HISTORY", "(end of command line)", NULL, NULL); if (ucac4_fits_write_headers(ucacs[hp])) { ERROR("Failed to write header for FITS file %s", fn); exit(-1); } } if (ucac4_fits_write_entry(ucacs[hp], &entry)) { ERROR("Failed to write FITS entry"); exit(-1); } nrecords++; if (eof) break; } BZ2_bzReadClose(&bzerr, bzfid); fclose(fid); nfiles++; printf("\n"); } printf("\n"); // close all the files... for (i=0; i<HP; i++) { if (!ucacs[i]) continue; if (ucac4_fits_fix_headers(ucacs[i]) || ucac4_fits_close(ucacs[i])) { ERROR("Failed to close file %i", i); } } printf("Read %u files, %u records.\n", nfiles, nrecords); free(ucacs); return 0; }
int uniformize_catalog(fitstable_t* intable, fitstable_t* outtable, const char* racol, const char* deccol, const char* sortcol, anbool sort_ascending, double sort_min_cut, // ? Or do this cut in a separate process? int bighp, int bignside, int nmargin, // uniformization nside. int Nside, double dedup_radius, int nsweeps, char** args, int argc) { anbool allsky; intmap_t* starlists; int NHP; anbool dense = FALSE; double dedupr2 = 0.0; tfits_type dubl; int N; int* inorder = NULL; int* outorder = NULL; int outi; double *ra = NULL, *dec = NULL; il* myhps = NULL; int i,j,k; int nkeep = nsweeps; int noob = 0; int ndup = 0; struct oh_token token; int* npersweep = NULL; qfits_header* outhdr = NULL; double *sortval = NULL; if (bignside == 0) bignside = 1; allsky = (bighp == -1); if (Nside % bignside) { ERROR("Fine healpixelization Nside must be a multiple of the coarse healpixelization Nside"); return -1; } if (Nside > HP_MAX_INT_NSIDE) { ERROR("Error: maximum healpix Nside = %i", HP_MAX_INT_NSIDE); return -1; } NHP = 12 * Nside * Nside; logverb("Healpix Nside: %i, # healpixes on the whole sky: %i\n", Nside, NHP); if (!allsky) { logverb("Creating index for healpix %i, nside %i\n", bighp, bignside); logverb("Number of healpixes: %i\n", ((Nside/bignside)*(Nside/bignside))); } logverb("Healpix side length: %g arcmin.\n", healpix_side_length_arcmin(Nside)); dubl = fitscolumn_double_type(); if (!racol) racol = "RA"; ra = fitstable_read_column(intable, racol, dubl); if (!ra) { ERROR("Failed to find RA column (%s) in table", racol); return -1; } if (!deccol) deccol = "DEC"; dec = fitstable_read_column(intable, deccol, dubl); if (!dec) { ERROR("Failed to find DEC column (%s) in table", deccol); free(ra); return -1; } N = fitstable_nrows(intable); logverb("Have %i objects\n", N); // FIXME -- argsort and seek around the input table, and append to // starlists in order; OR read from the input table in sequence and // sort in the starlists? if (sortcol) { logverb("Sorting by %s...\n", sortcol); sortval = fitstable_read_column(intable, sortcol, dubl); if (!sortval) { ERROR("Failed to read sorting column \"%s\"", sortcol); free(ra); free(dec); return -1; } inorder = permuted_sort(sortval, sizeof(double), sort_ascending ? compare_doubles_asc : compare_doubles_desc, NULL, N); if (sort_min_cut > -HUGE_VAL) { logverb("Cutting to %s > %g...\n", sortcol, sort_min_cut); // Cut objects with sortval < sort_min_cut. if (sort_ascending) { // skipped objects are at the front -- find the first obj // to keep for (i=0; i<N; i++) if (sortval[inorder[i]] > sort_min_cut) break; // move the "inorder" indices down. if (i) memmove(inorder, inorder+i, (N-i)*sizeof(int)); N -= i; } else { // skipped objects are at the end -- find the last obj to keep. for (i=N-1; i>=0; i--) if (sortval[inorder[i]] > sort_min_cut) break; N = i+1; } logverb("Cut to %i objects\n", N); } //free(sortval); } token.nside = bignside; token.finenside = Nside; token.hp = bighp; if (!allsky && nmargin) { int bigbighp, bighpx, bighpy; //int ninside; il* seeds = il_new(256); logverb("Finding healpixes in range...\n"); healpix_decompose_xy(bighp, &bigbighp, &bighpx, &bighpy, bignside); //ninside = (Nside/bignside)*(Nside/bignside); // Prime the queue with the fine healpixes that are on the // boundary of the big healpix. for (i=0; i<((Nside / bignside) - 1); i++) { // add (i,0), (i,max), (0,i), and (0,max) healpixes int xx = i + bighpx * (Nside / bignside); int yy = i + bighpy * (Nside / bignside); int y0 = bighpy * (Nside / bignside); // -1 prevents us from double-adding the corners. int y1 =(1 + bighpy)* (Nside / bignside) - 1; int x0 = bighpx * (Nside / bignside); int x1 =(1 + bighpx)* (Nside / bignside) - 1; assert(xx < Nside); assert(yy < Nside); assert(x0 < Nside); assert(x1 < Nside); assert(y0 < Nside); assert(y1 < Nside); il_append(seeds, healpix_compose_xy(bigbighp, xx, y0, Nside)); il_append(seeds, healpix_compose_xy(bigbighp, xx, y1, Nside)); il_append(seeds, healpix_compose_xy(bigbighp, x0, yy, Nside)); il_append(seeds, healpix_compose_xy(bigbighp, x1, yy, Nside)); } logmsg("Number of boundary healpixes: %zu (Nside/bignside = %i)\n", il_size(seeds), Nside/bignside); myhps = healpix_region_search(-1, seeds, Nside, NULL, NULL, outside_healpix, &token, nmargin); logmsg("Number of margin healpixes: %zu\n", il_size(myhps)); il_free(seeds); il_sort(myhps, TRUE); // DEBUG il_check_consistency(myhps); il_check_sorted_ascending(myhps, TRUE); } dedupr2 = arcsec2distsq(dedup_radius); starlists = intmap_new(sizeof(int32_t), nkeep, 0, dense); logverb("Placing stars in grid cells...\n"); for (i=0; i<N; i++) { int hp; bl* lst; int32_t j32; anbool oob; if (inorder) { j = inorder[i]; //printf("Placing star %i (%i): sort value %s = %g, RA,Dec=%g,%g\n", i, j, sortcol, sortval[j], ra[j], dec[j]); } else j = i; hp = radecdegtohealpix(ra[j], dec[j], Nside); //printf("HP %i\n", hp); // in bounds? oob = FALSE; if (myhps) { oob = (outside_healpix(hp, &token) && !il_sorted_contains(myhps, hp)); } else if (!allsky) { oob = (outside_healpix(hp, &token)); } if (oob) { //printf("out of bounds.\n"); noob++; continue; } lst = intmap_find(starlists, hp, TRUE); /* printf("list has %i existing entries.\n", bl_size(lst)); for (k=0; k<bl_size(lst); k++) { bl_get(lst, k, &j32); printf(" %i: index %i, %s = %g\n", k, j32, sortcol, sortval[j32]); } */ // is this list full? if (nkeep && (bl_size(lst) >= nkeep)) { // Here we assume we're working in sorted order: once the list is full we're done. //printf("Skipping: list is full.\n"); continue; } if ((dedupr2 > 0.0) && is_duplicate(hp, ra[j], dec[j], Nside, starlists, ra, dec, dedupr2)) { //printf("Skipping: duplicate\n"); ndup++; continue; } // Add the new star (by index) j32 = j; bl_append(lst, &j32); } logverb("%i outside the healpix\n", noob); logverb("%i duplicates\n", ndup); il_free(myhps); myhps = NULL; free(inorder); inorder = NULL; free(ra); ra = NULL; free(dec); dec = NULL; outorder = malloc(N * sizeof(int)); outi = 0; npersweep = calloc(nsweeps, sizeof(int)); for (k=0; k<nsweeps; k++) { int starti = outi; int32_t j32; for (i=0;; i++) { bl* lst; int hp; if (!intmap_get_entry(starlists, i, &hp, &lst)) break; if (bl_size(lst) <= k) continue; bl_get(lst, k, &j32); outorder[outi] = j32; //printf("sweep %i, cell #%i, hp %i, star %i, %s = %g\n", k, i, hp, j32, sortcol, sortval[j32]); outi++; } logmsg("Sweep %i: %i stars\n", k+1, outi - starti); npersweep[k] = outi - starti; if (sortcol) { // Re-sort within this sweep. permuted_sort(sortval, sizeof(double), sort_ascending ? compare_doubles_asc : compare_doubles_desc, outorder + starti, npersweep[k]); /* for (i=0; i<npersweep[k]; i++) { printf(" within sweep %i: star %i, j=%i, %s=%g\n", k, i, outorder[starti + i], sortcol, sortval[outorder[starti + i]]); } */ } } intmap_free(starlists); starlists = NULL; ////// free(sortval); sortval = NULL; logmsg("Total: %i stars\n", outi); N = outi; outhdr = fitstable_get_primary_header(outtable); if (allsky) qfits_header_add(outhdr, "ALLSKY", "T", "All-sky catalog.", NULL); BOILERPLATE_ADD_FITS_HEADERS(outhdr); qfits_header_add(outhdr, "HISTORY", "This file was generated by the command-line:", NULL, NULL); fits_add_args(outhdr, args, argc); qfits_header_add(outhdr, "HISTORY", "(end of command line)", NULL, NULL); fits_add_long_history(outhdr, "uniformize-catalog args:"); fits_add_long_history(outhdr, " RA,Dec columns: %s,%s", racol, deccol); fits_add_long_history(outhdr, " sort column: %s", sortcol); fits_add_long_history(outhdr, " sort direction: %s", sort_ascending ? "ascending" : "descending"); if (sort_ascending) fits_add_long_history(outhdr, " (ie, for mag-like sort columns)"); else fits_add_long_history(outhdr, " (ie, for flux-like sort columns)"); fits_add_long_history(outhdr, " uniformization nside: %i", Nside); fits_add_long_history(outhdr, " (ie, side length ~ %g arcmin)", healpix_side_length_arcmin(Nside)); fits_add_long_history(outhdr, " deduplication scale: %g arcsec", dedup_radius); fits_add_long_history(outhdr, " number of sweeps: %i", nsweeps); fits_header_add_int(outhdr, "NSTARS", N, "Number of stars."); fits_header_add_int(outhdr, "HEALPIX", bighp, "Healpix covered by this catalog, with Nside=HPNSIDE"); fits_header_add_int(outhdr, "HPNSIDE", bignside, "Nside of HEALPIX."); fits_header_add_int(outhdr, "CUTNSIDE", Nside, "uniformization scale (healpix nside)"); fits_header_add_int(outhdr, "CUTMARG", nmargin, "margin size, in healpixels"); //qfits_header_add(outhdr, "CUTBAND", cutband, "band on which the cut was made", NULL); fits_header_add_double(outhdr, "CUTDEDUP", dedup_radius, "deduplication radius [arcsec]"); fits_header_add_int(outhdr, "CUTNSWEP", nsweeps, "number of sweeps"); //fits_header_add_double(outhdr, "CUTMINMG", minmag, "minimum magnitude"); //fits_header_add_double(outhdr, "CUTMAXMG", maxmag, "maximum magnitude"); for (k=0; k<nsweeps; k++) { char key[64]; sprintf(key, "SWEEP%i", (k+1)); fits_header_add_int(outhdr, key, npersweep[k], "# stars added"); } free(npersweep); if (fitstable_write_primary_header(outtable)) { ERROR("Failed to write primary header"); return -1; } // Write output. fitstable_add_fits_columns_as_struct2(intable, outtable); if (fitstable_write_header(outtable)) { ERROR("Failed to write output table header"); return -1; } logmsg("Writing output...\n"); logverb("Row size: %i\n", fitstable_row_size(intable)); if (fitstable_copy_rows_data(intable, outorder, N, outtable)) { ERROR("Failed to copy rows from input table to output"); return -1; } if (fitstable_fix_header(outtable)) { ERROR("Failed to fix output table header"); return -1; } free(outorder); return 0; }
int main(int argc, char** args) { char* outfn = NULL; int c; int startoptind; int nrecords, nobs, nfiles; int Nside = 8; usnob_fits** usnobs; int i, HP; int slicecounts[180]; while ((c = getopt(argc, args, OPTIONS)) != -1) { switch (c) { case '?': case 'h': print_help(args[0]); exit(0); case 'N': Nside = atoi(optarg); break; case 'o': outfn = optarg; break; } } if (!outfn || (optind == argc)) { print_help(args[0]); exit(-1); } if (Nside < 1) { fprintf(stderr, "Nside must be >= 1.\n"); print_help(args[0]); exit(-1); } HP = 12 * Nside * Nside; printf("Nside = %i, using %i healpixes.\n", Nside, HP); { struct rlimit lim; getrlimit(RLIMIT_NOFILE, &lim); printf("Maximum number of files that can be opened: %li soft, %li hard\n", (long int)lim.rlim_cur, (long int)lim.rlim_max); if (lim.rlim_cur < HP) { printf("\n\nWARNING: This process is likely to fail - probably after working for many hours!\n\n\n"); sleep(5); } } usnobs = calloc(HP, sizeof(usnob_fits*)); memset(slicecounts, 0, 180 * sizeof(uint)); nrecords = 0; nobs = 0; nfiles = 0; printf("Reading USNO files... "); fflush(stdout); startoptind = optind; for (; optind<argc; optind++) { char* infn; FILE* fid; unsigned char* map; size_t map_size; int i; int lastgrass; infn = args[optind]; fid = fopen(infn, "rb"); if (!fid) { fprintf(stderr, "Couldn't open input file %s: %s\n", infn, strerror(errno)); exit(-1); } printf("Reading file %i of %i: %s\n", optind - startoptind, argc - startoptind, infn); if (fseeko(fid, 0, SEEK_END)) { fprintf(stderr, "Couldn't seek to end of input file %s: %s\n", infn, strerror(errno)); exit(-1); } map_size = ftello(fid); fseeko(fid, 0, SEEK_SET); map = mmap(NULL, map_size, PROT_READ, MAP_SHARED, fileno(fid), 0); if (map == MAP_FAILED) { fprintf(stderr, "Couldn't mmap input file %s: %s\n", infn, strerror(errno)); exit(-1); } fclose(fid); if (map_size % USNOB_RECORD_SIZE) { fprintf(stderr, "Warning, input file %s has size %u which is not divisible into %i-byte records.\n", infn, (unsigned int)map_size, USNOB_RECORD_SIZE); } lastgrass = 0; for (i=0; i<map_size; i+=USNOB_RECORD_SIZE) { usnob_entry entry; int hp; int slice; if ((i * 80 / map_size) != lastgrass) { printf("."); fflush(stdout); lastgrass = i * 80 / map_size; } if (usnob_parse_entry(map + i, &entry)) { fprintf(stderr, "Failed to parse USNOB entry: offset %i in file %s.\n", i, infn); exit(-1); } // compute the usnob_id based on its DEC slice and index. slice = (int)(entry.dec + 90.0); assert(slice < 180); assert((slicecounts[slice] & 0xff000000) == 0); entry.usnob_id = (slice << 24) | (slicecounts[slice]); slicecounts[slice]++; hp = radectohealpix(deg2rad(entry.ra), deg2rad(entry.dec), Nside); if (!usnobs[hp]) { char fn[256]; qfits_header* hdr; sprintf(fn, outfn, hp); usnobs[hp] = usnob_fits_open_for_writing(fn); if (!usnobs[hp]) { fprintf(stderr, "Failed to initialized FITS file %i (filename %s).\n", hp, fn); exit(-1); } if (usnob_fits_remove_an_diffraction_spike_column(usnobs[hp])) { fprintf(stderr, "Failed to remove the AN_DIFFRACTION_SPIKE column.\n"); exit(-1); } hdr = usnob_fits_get_header(usnobs[hp]); assert(hdr); // header remarks... fits_header_add_int(hdr, "HEALPIX", hp, "The healpix number of this catalog."); fits_header_add_int(hdr, "NSIDE", Nside, "The healpix resolution."); BOILERPLATE_ADD_FITS_HEADERS(hdr); qfits_header_add(hdr, "HISTORY", "Created by the program \"usnobtofits\"", NULL, NULL); qfits_header_add(hdr, "HISTORY", "usnobtofits command line:", NULL, NULL); fits_add_args(hdr, args, argc); qfits_header_add(hdr, "HISTORY", "(end of command line)", NULL, NULL); if (usnob_fits_write_headers(usnobs[hp])) { fprintf(stderr, "Failed to write header for FITS file %s.\n", fn); exit(-1); } } if (usnob_fits_write_entry(usnobs[hp], &entry)) { fprintf(stderr, "Failed to write FITS entry.\n"); exit(-1); } nrecords++; nobs += (entry.ndetections == 0 ? 1 : entry.ndetections); } munmap(map, map_size); nfiles++; printf("\n"); } // close all the files... for (i=0; i<HP; i++) { if (!usnobs[i]) continue; if (usnob_fits_fix_headers(usnobs[i]) || usnob_fits_close(usnobs[i])) { fprintf(stderr, "Failed to close file %i: %s\n", i, strerror(errno)); } } printf("Read %u files, %u records, %u observations.\n", nfiles, nrecords, nobs); free(usnobs); return 0; }
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; }
int main(int argc, char *argv[]) { int argchar; char* infn = NULL; char* outfn = NULL; FILE* fout; anbool tostdout = FALSE; anqfits_t* anq; int W, H; qfits_header* hdr; const anqfits_image_t* animg; float* img; int loglvl = LOG_MSG; int scale = 2; int winw; int winh; int plane; int out_bitpix = -32; float* outimg; int outw, outh; int edge = EDGE_TRUNCATE; int ext = 0; int npixout = 0; while ((argchar = getopt (argc, argv, OPTIONS)) != -1) switch (argchar) { case 'v': loglvl++; break; case 's': scale = atoi(optarg); break; case 'e': ext = atoi(optarg); break; case '?': case 'h': printHelp(argv[0]); return 0; default: return -1; } log_init(loglvl); log_to(stderr); errors_log_to(stderr); fits_use_error_system(); if (argc - optind != 2) { logerr("Need two arguments: input and output files.\n"); printHelp(argv[0]); exit(-1); } infn = argv[optind]; outfn = argv[optind+1]; if (streq(outfn, "-")) { tostdout = TRUE; fout = stdout; } else { fout = fopen(outfn, "wb"); if (!fout) { SYSERROR("Failed to open output file \"%s\"", outfn); exit(-1); } } anq = anqfits_open(infn); if (!anq) { ERROR("Failed to open input file \"%s\"", infn); exit(-1); } animg = anqfits_get_image_const(anq, ext); W = (int)animg->width; H = (int)animg->height; if (!animg) { ERROR("Failde to read image from \"%s\"", infn); exit(-1); } /* if (tostdout) dump.filename = "STDOUT"; else dump.filename = outfn; dump.ptype = PTYPE_FLOAT; dump.out_ptype = out_bitpix; */ get_output_image_size(W % scale, H % scale, scale, edge, &outw, &outh); outw += (W / scale); outh += (H / scale); hdr = qfits_header_default(); fits_header_add_int(hdr, "BITPIX", out_bitpix, "bits per pixel"); if (animg->planes > 1) fits_header_add_int(hdr, "NAXIS", 3, "number of axes"); else fits_header_add_int(hdr, "NAXIS", 2, "number of axes"); fits_header_add_int(hdr, "NAXIS1", outw, "image width"); fits_header_add_int(hdr, "NAXIS2", outh, "image height"); if (animg->planes > 1) fits_header_add_int(hdr, "NAXIS3", animg->planes, "number of planes"); if (qfits_header_dump(hdr, fout)) { ERROR("Failed to write FITS header to \"%s\"", outfn); exit(-1); } qfits_header_destroy(hdr); winw = W; winh = (int)ceil(ceil(1024*1024 / (float)winw) / (float)scale) * scale; outimg = malloc((int)ceil(winw/scale)*(int)ceil(winh/scale) * sizeof(float)); logmsg("Image is %i x %i x %i\n", W, H, (int)animg->planes); logmsg("Output will be %i x %i x %i\n", outw, outh, (int)animg->planes); logverb("Reading in blocks of %i x %i\n", winw, winh); for (plane=0; plane<animg->planes; plane++) { int bx, by; int nx, ny; for (by=0; by<(int)ceil(H / (float)winh); by++) { for (bx=0; bx<(int)ceil(W / (float)winw); bx++) { int i; int lox, loy, hix, hiy, outw, outh; nx = MIN(winw, W - bx*winw); ny = MIN(winh, H - by*winh); lox = bx*winw; loy = by*winh; hix = lox + nx; hiy = loy + ny; logverb(" reading %i,%i + %i,%i\n", lox, loy, nx, ny); img = anqfits_readpix(anq, ext, lox, hix, loy, hiy, plane, PTYPE_FLOAT, NULL, &W, &H); if (!img) { ERROR("Failed to load pixel window: x=[%i, %i), y=[%i,%i), plane %i\n", lox, hix, loy, hiy, plane); exit(-1); } average_image_f(img, nx, ny, scale, edge, &outw, &outh, outimg); free(img); logverb(" writing %i x %i\n", outw, outh); if (outw * outh == 0) continue; for (i=0; i<outw*outh; i++) { int nbytes = abs(out_bitpix)/8; char buf[nbytes]; if (qfits_pixel_ctofits(PTYPE_FLOAT, out_bitpix, outimg + i, buf)) { ERROR("Failed to convert pixel to FITS type\n"); exit(-1); } if (fwrite(buf, nbytes, 1, fout) != 1) { ERROR("Failed to write pixels\n"); exit(-1); } } npixout += outw*outh; } } } free(outimg); anqfits_close(anq); if (tostdout) { // pad. int N; char pad[2880]; N = (npixout * (abs(out_bitpix) / 8)) % 2880; memset(pad, 0, 2880); fwrite(pad, 1, N, fout); } else { if (fits_pad_file(fout)) { ERROR("Failed to pad output file"); exit(-1); } if (fclose(fout)) { SYSERROR("Failed to close output file"); exit(-1); } } logverb("Done!\n"); return 0; }