int qidxfile_close(qidxfile* qf) { int rtn; if (!qf) return 0; if (fitsbin_get_fid(qf->fb)) fits_pad_file(fitsbin_get_fid(qf->fb)); rtn = fitsbin_close(qf->fb); free(qf); return rtn; }
void fitstable_next_extension(fitstable_t* tab) { if (is_writing(tab)) fits_pad_file(tab->fid); if (in_memory(tab)) { fitsext_t ext; if (!tab->table) return; // update NAXIS2 fitstable_fix_header(tab); ext.table = tab->table; ext.header = tab->header; ext.rows = tab->rows; bl_append(tab->extensions, &ext); tab->rows = NULL; } else { qfits_table_close(tab->table); qfits_header_destroy(tab->header); } tab->extension++; tab->table = NULL; tab->header = NULL; }
int main(int argc, char *argv[]) { int argchar; char* infn = NULL; char* outfn = NULL; FILE* fin = NULL; FILE* fout = NULL; pl* cols; char* progname = argv[0]; int nextens; int ext; int NC; int start, size; anqfits_t* anq = NULL; qfits_table* outtable; unsigned char* buffer; cols = pl_new(16); while ((argchar = getopt (argc, argv, OPTIONS)) != -1) switch (argchar) { case 'c': pl_append(cols, optarg); break; case 'i': infn = optarg; break; case 'o': outfn = optarg; break; case '?': case 'h': printHelp(progname); return 0; default: return -1; } if (!infn || !outfn || !pl_size(cols)) { printHelp(progname); exit(-1); } fin = fopen(infn, "rb"); if (!fin) { ERROR("Failed to open input file %s: %s\n", infn, strerror(errno)); exit(-1); } fout = fopen(outfn, "wb"); if (!fout) { ERROR("Failed to open output file %s: %s\n", outfn, strerror(errno)); exit(-1); } // copy the main header exactly. anq = anqfits_open(infn); if (!anq) { ERROR("Failed to read \"%s\"", infn); exit(-1); } start = anqfits_header_start(anq, 0); size = anqfits_header_size (anq, 0); if (pipe_file_offset(fin, start, size, fout)) { ERROR("Failed to copy primary header.\n"); exit(-1); } NC = pl_size(cols); nextens = anqfits_n_ext(anq); printf("Translating %i extensions.\n", nextens); buffer = NULL; for (ext=1; ext<nextens; ext++) { int c2, c; int columns[NC]; int sizes[NC]; int offsets[NC]; int offset = 0; int off, n; int totalsize = 0; const int BLOCK=1000; qfits_table* table; qfits_header* header; qfits_header* tablehdr; if (ext%100 == 0) { printf("Extension %i.\n", ext); fflush(stdout); } if (!anqfits_is_table(anq, ext)) { ERROR("extention %i isn't a table.\n", ext); // HACK - just copy it. return -1; } table = anqfits_get_table(anq, ext); if (!table) { ERROR("failed to open table: file %s, extension %i.\n", infn, ext); return -1; } header = anqfits_get_header(anq, ext); if (!header) { ERROR("failed to read header: extension %i\n", ext); exit(-1); } outtable = qfits_table_new(outfn, QFITS_BINTABLE, 0, NC, table->nr); outtable->tab_w = 0; for (c=0; c<pl_size(cols); c++) { columns[c] = -1; } for (c=0; c<pl_size(cols); c++) { char* colname = pl_get(cols, c); qfits_col* col; c2 = fits_find_column(table, colname); if (c2 == -1) { ERROR("Extension %i: failed to find column named %s\n", ext, colname); exit(-1); } col = table->col + c2; columns[c] = c2; sizes[c] = col->atom_nb * col->atom_size; offsets[c] = offset; offset += sizes[c]; qfits_col_fill(outtable->col + c, col->atom_nb, col->atom_dec_nb, col->atom_size, col->atom_type, col->tlabel, col->tunit, col->nullval, col->tdisp, col->zero_present, col->zero, col->scale_present, col->scale, outtable->tab_w); outtable->tab_w += sizes[c]; } totalsize = offset; tablehdr = qfits_table_ext_header_default(outtable); // add any headers from the original table that aren't part of the BINTABLE extension. fits_copy_non_table_headers(tablehdr, header); qfits_header_dump(tablehdr, fout); qfits_header_destroy(tablehdr); buffer = realloc(buffer, totalsize * BLOCK); for (off=0; off<table->nr; off+=n) { if (off + BLOCK > table->nr) n = table->nr - off; else n = BLOCK; for (c=0; c<pl_size(cols); c++) qfits_query_column_seq_to_array_no_endian_swap (table, columns[c], off, n, buffer + offsets[c], totalsize); if (fwrite(buffer, totalsize, n, fout) != n) { ERROR("Error writing a block of data: ext %i: %s\n", ext, strerror(errno)); exit(-1); } } qfits_table_close(outtable); fits_pad_file(fout); qfits_header_destroy(header); qfits_table_close(table); } free(buffer); if (fclose(fout)) { ERROR("Error closing output file: %s\n", strerror(errno)); } fclose(fin); anqfits_close(anq); pl_free(cols); return 0; }
int resort_xylist(const char* infn, const char* outfn, const char* fluxcol, const char* backcol, anbool ascending) { FILE* fin = NULL; FILE* fout = NULL; double *flux = NULL, *back = NULL; int *perm1 = NULL, *perm2 = NULL; anbool *used = NULL; int start, size, nextens, ext; int (*compare)(const void*, const void*); fitstable_t* tab = NULL; anqfits_t* anq = NULL; if (ascending) compare = compare_doubles_asc; else compare = compare_doubles_desc; if (!fluxcol) fluxcol = "FLUX"; if (!backcol) backcol = "BACKGROUND"; fin = fopen(infn, "rb"); if (!fin) { SYSERROR("Failed to open input file %s", infn); return -1; } fout = fopen(outfn, "wb"); if (!fout) { SYSERROR("Failed to open output file %s", outfn); goto bailout; } // copy the main header exactly. anq = anqfits_open(infn); if (!anq) { ERROR("Failed to open file \"%s\"", infn); goto bailout; } start = anqfits_header_start(anq, 0); size = anqfits_header_size (anq, 0); if (pipe_file_offset(fin, start, size, fout)) { ERROR("Failed to copy primary FITS header."); goto bailout; } nextens = anqfits_n_ext(anq); tab = fitstable_open(infn); if (!tab) { ERROR("Failed to open FITS table in file %s", infn); goto bailout; } for (ext=1; ext<nextens; ext++) { int hdrstart, hdrsize, datstart; int i, N; int rowsize; hdrstart = anqfits_header_start(anq, ext); hdrsize = anqfits_header_size (anq, ext); datstart = anqfits_data_start (anq, ext); if (!anqfits_is_table(anq, ext)) { ERROR("Extention %i isn't a table. Skipping", ext); continue; } // Copy the header as-is. if (pipe_file_offset(fin, hdrstart, hdrsize, fout)) { ERROR("Failed to copy the header of extension %i", ext); goto bailout; } if (fitstable_read_extension(tab, ext)) { ERROR("Failed to read FITS table from extension %i", ext); goto bailout; } rowsize = fitstable_row_size(tab); // read FLUX column as doubles. flux = fitstable_read_column(tab, fluxcol, TFITS_BIN_TYPE_D); if (!flux) { ERROR("Failed to read FLUX column from extension %i", ext); goto bailout; } // BACKGROUND back = fitstable_read_column(tab, backcol, TFITS_BIN_TYPE_D); if (!back) { ERROR("Failed to read BACKGROUND column from extension %i", ext); goto bailout; } debug("First 10 rows of input table:\n"); for (i=0; i<10; i++) debug("flux %g, background %g\n", flux[i], back[i]); N = fitstable_nrows(tab); // set back = flux + back (ie, non-background-subtracted flux) for (i=0; i<N; i++) back[i] += flux[i]; // Sort by flux... perm1 = permuted_sort(flux, sizeof(double), compare, NULL, N); // Sort by non-background-subtracted flux... perm2 = permuted_sort(back, sizeof(double), compare, NULL, N); used = malloc(N * sizeof(anbool)); memset(used, 0, N * sizeof(anbool)); // Check sort... for (i=0; i<N-1; i++) { if (ascending) { assert(flux[perm1[i]] <= flux[perm1[i+1]]); assert(back[perm2[i]] <= back[perm2[i+1]]); } else { assert(flux[perm1[i]] >= flux[perm1[i+1]]); assert(back[perm2[i]] >= back[perm2[i+1]]); } } for (i=0; i<N; i++) { int j; int inds[] = { perm1[i], perm2[i] }; for (j=0; j<2; j++) { int index = inds[j]; assert(index < N); if (used[index]) continue; used[index] = TRUE; debug("adding index %i: %s %g\n", index, j==0 ? "flux" : "bgsub", j==0 ? flux[index] : back[index]); if (pipe_file_offset(fin, datstart + index * rowsize, rowsize, fout)) { ERROR("Failed to copy row %i", index); goto bailout; } } } for (i=0; i<N; i++) assert(used[i]); if (fits_pad_file(fout)) { ERROR("Failed to add padding to extension %i", ext); goto bailout; } free(flux); flux = NULL; free(back); back = NULL; free(perm1); perm1 = NULL; free(perm2); perm2 = NULL; free(used); used = NULL; } fitstable_close(tab); tab = NULL; if (fclose(fout)) { SYSERROR("Failed to close output file %s", outfn); return -1; } fclose(fin); return 0; bailout: if (tab) fitstable_close(tab); if (fout) fclose(fout); if (fin) fclose(fin); free(flux); free(back); free(perm1); free(perm2); free(used); return -1; }
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 tabsort(const char* infn, const char* outfn, const char* colname, int descending) { FILE* fin; FILE* fout; int ext, nextens; off_t start, size; void* data = NULL; int* perm = NULL; unsigned char* map = NULL; size_t mapsize = 0; anqfits_t* anq = NULL; fin = fopen(infn, "rb"); if (!fin) { SYSERROR("Failed to open input file %s", infn); return -1; } fout = fopen(outfn, "wb"); if (!fout) { SYSERROR("Failed to open output file %s", outfn); goto bailout; } // copy the main header exactly. anq = anqfits_open(infn); if (!anq) { ERROR("Failed to open \"%s\"", infn); goto bailout; } start = anqfits_header_start(anq, 0); size = anqfits_header_size (anq, 0); if (pipe_file_offset(fin, start, size, fout)) { ERROR("Failed to copy primary FITS header."); goto bailout; } nextens = anqfits_n_ext(anq); //logverb("Sorting %i extensions.\n", nextens); for (ext=1; ext<nextens; ext++) { int c; qfits_table* table; qfits_col* col; int mgap; off_t mstart; size_t msize; int atomsize; int (*sort_func)(const void*, const void*); unsigned char* tabledata; unsigned char* tablehdr; off_t hdrstart, hdrsize, datsize, datstart; int i; hdrstart = anqfits_header_start(anq, ext); hdrsize = anqfits_header_size (anq, ext); datstart = anqfits_data_start (anq, ext); datsize = anqfits_data_size (anq, ext); if (!anqfits_is_table(anq, ext)) { ERROR("Extension %i isn't a table. Skipping.\n", ext); continue; } table = anqfits_get_table(anq, ext); if (!table) { ERROR("Failed to open table: file %s, extension %i. Skipping.", infn, ext); continue; } c = fits_find_column(table, colname); if (c == -1) { ERROR("Couldn't find column named \"%s\" in extension %i. Skipping.", colname, ext); continue; } col = table->col + c; switch (col->atom_type) { case TFITS_BIN_TYPE_D: data = realloc(data, table->nr * sizeof(double)); if (descending) sort_func = compare_doubles_desc; else sort_func = compare_doubles_asc; break; case TFITS_BIN_TYPE_E: data = realloc(data, table->nr * sizeof(float)); if (descending) sort_func = compare_floats_desc; else sort_func = compare_floats_asc; break; case TFITS_BIN_TYPE_K: data = realloc(data, table->nr * sizeof(int64_t)); if (descending) sort_func = compare_int64_desc; else sort_func = compare_int64_asc; break; default: ERROR("Column %s is neither FITS type D, E, nor K. Skipping.", colname); continue; } // Grab the sort column. atomsize = fits_get_atom_size(col->atom_type); printf("Reading sort column \"%s\"\n", colname); qfits_query_column_seq_to_array(table, c, 0, table->nr, data, atomsize); // Sort it. printf("Sorting sort column\n"); perm = permuted_sort(data, atomsize, sort_func, NULL, table->nr); // mmap the input file. printf("mmapping input file\n"); start = hdrstart; size = hdrsize + datsize; get_mmap_size(start, size, &mstart, &msize, &mgap); mapsize = msize; map = mmap(NULL, mapsize, PROT_READ, MAP_SHARED, fileno(fin), mstart); if (map == MAP_FAILED) { SYSERROR("Failed to mmap input file %s", infn); map = NULL; goto bailout; } tabledata = map + (off_t)mgap + (datstart - hdrstart); tablehdr = map + (off_t)mgap; // Copy the table header without change. printf("Copying table header.\n"); if (fwrite(tablehdr, 1, hdrsize, fout) != hdrsize) { SYSERROR("Failed to write FITS table header"); goto bailout; } for (i=0; i<table->nr; i++) { unsigned char* rowptr; if (i % 100000 == 0) printf("Writing row %i\n", i); rowptr = tabledata + (off_t)(perm[i]) * (off_t)table->tab_w; if (fwrite(rowptr, 1, table->tab_w, fout) != table->tab_w) { SYSERROR("Failed to write FITS table row"); goto bailout; } } munmap(map, mapsize); map = NULL; free(perm); perm = NULL; if (fits_pad_file(fout)) { ERROR("Failed to add padding to extension %i", ext); goto bailout; } qfits_table_close(table); } free(data); if (fclose(fout)) { SYSERROR("Error closing output file"); fout = NULL; goto bailout; } fclose(fin); anqfits_close(anq); printf("Done\n"); return 0; bailout: free(data); free(perm); if (fout) fclose(fout); fclose(fin); if (map) munmap(map, mapsize); return -1; }
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; }
int new_wcs(const char* infn, int extension, const char* wcsfn, const char* outfn, anbool copydata) { FILE* outfid = NULL; int i, N; int e; regex_t re1[NE1]; regex_t re2[NE2]; qfits_header *inhdr=NULL, *outhdr=NULL, *wcshdr=NULL; char key[FITS_LINESZ + 1]; char newkey[FITS_LINESZ + 1]; char val[FITS_LINESZ + 1]; char comment[FITS_LINESZ + 1]; int imatch = -1; // how many REs have successfully been compiled. int n1=0, n2=0; outfid = fopen(outfn, "wb"); if (!outfid) { SYSERROR("Failed to open output file \"%s\"", outfn); goto bailout; } inhdr = anqfits_get_header2(infn, extension); if (!inhdr) { ERROR("Failed to read FITS header from input file \"%s\" ext %i", infn, extension); goto bailout; } wcshdr = anqfits_get_header2(wcsfn, 0); if (!wcshdr) { ERROR("Failed to read FITS header from WCS file \"%s\"", wcsfn); goto bailout; } outhdr = qfits_header_new(); if (!outhdr) { ERROR("Failed to allocate new output FITS header."); goto bailout; } // Compile regular expressions... for (e=0; e<NE1; e++) { int errcode; errcode = regcomp(re1 + e, exclude_input[e], REG_EXTENDED); if (errcode) { char err[256]; regerror(errcode, re1 + e, err, sizeof(err)); ERROR("Failed to compile regular expression \"%s\": %s", exclude_input[e], err); goto bailout; } n1++; } for (e=0; e<NE2; e++) { int errcode; errcode = regcomp(re2 + e, exclude_wcs[e], REG_EXTENDED); if (errcode) { char err[256]; regerror(errcode, re2 + e, err, sizeof(err)); ERROR("Failed to compile regular expression \"%s\": %s", exclude_wcs[e], err); goto bailout; } n2++; } logverb("Reading input file FITS headers...\n"); if (extension) { // Copy the primary header unchanged qfits_header* phdr = anqfits_get_header2(infn, 0); if (!phdr) { ERROR("Failed to read primary FITS header from input file \"%s\n", infn); goto bailout; } if (qfits_header_dump(phdr, outfid) || fits_pad_file(outfid)) { SYSERROR("Failed to write primary header to file %s", outfn); goto bailout; } qfits_header_destroy(phdr); } N = qfits_header_n(inhdr); for (i=0; i<N; i++) { anbool added_newkey = FALSE; char line[FITS_LINESZ + 1]; if (qfits_header_getitem(inhdr, i, key, val, comment, line)) { ERROR("Failed to read FITS header card %i from input file", i); goto bailout; } logverb("Read input header line: \"%s\"\n", line); if (key_matches(key, re1, exclude_input, NE1, &imatch)) { logverb("Regular expression matched: \"%s\", key \"%s\".\n", exclude_input[imatch], key); snprintf(newkey, FITS_LINESZ+1, "Original key: \"%s\"", key); qfits_header_append(outhdr, "COMMENT", newkey, NULL, NULL); // Completely skip the END card, since _ND is not a valid line. if (streq(key, "END")) continue; snprintf(newkey, FITS_LINESZ+1, "_%.7s", key+1); logverb("New key: \"%s\"\n", newkey); strcpy(key, newkey); line[0] = '_'; added_newkey = TRUE; } // If the header already contains this new (starting-with-"_") // key, add three comment cards instead. if (starts_with(key, "_") && (qfits_header_getstr(inhdr, key) || qfits_header_getstr(outhdr, key))) { logverb("Key \"%s\" already exists; adding COMMENT cards for value and comment instead\n", key); if (!added_newkey) { snprintf(newkey, FITS_LINESZ+1, "Original key: \"%s\"", key); qfits_header_append(outhdr, "COMMENT", newkey, NULL, NULL); } snprintf(newkey, FITS_LINESZ+1, " = %s", val); qfits_header_append(outhdr, "COMMENT", newkey, NULL, NULL); snprintf(newkey, FITS_LINESZ+1, " / %s", comment); qfits_header_append(outhdr, "COMMENT", newkey, NULL, NULL); continue; } qfits_header_append(outhdr, key, val, comment, line); } qfits_header_destroy(inhdr); inhdr = NULL; logverb("Reading WCS file FITS headers...\n"); qfits_header_append(outhdr, "COMMENT", "", NULL, NULL); qfits_header_append(outhdr, "COMMENT", "--Start of Astrometry.net WCS solution--", NULL, NULL); qfits_header_append(outhdr, "COMMENT", "--Put in by the new-wcs program--", NULL, NULL); qfits_header_append(outhdr, "COMMENT", "", NULL, NULL); N = qfits_header_n(wcshdr); for (i=0; i<N; i++) { char line[FITS_LINESZ + 1]; if (qfits_header_getitem(wcshdr, i, key, val, comment, line)) { ERROR("Failed to read FITS header card %i from WCS file.", i); goto bailout; } if (key_matches(key, re2, exclude_wcs, NE2, &imatch)) { logverb("Regular expression matched: \"%s\", key \"%s\".\n", exclude_wcs[imatch], key); // These don't really need to appear in the output file... /* snprintf(newkey, FITS_LINESZ+1, "Original WCS key: \"%s\"", key); qfits_header_append(outhdr, "COMMENT", newkey, NULL, NULL); snprintf(newkey, FITS_LINESZ+1, "_%.7s", key); strcpy(key, newkey); */ continue; } if (streq(key, "DATE") && qfits_header_getstr(outhdr, key)) { // If the input header already had a DATE card, snprintf(newkey, FITS_LINESZ+1, "Original WCS key: \"%s\"", key); qfits_header_append(outhdr, "COMMENT", newkey, NULL, NULL); snprintf(newkey, FITS_LINESZ+1, "_%.7s", key); strcpy(key, newkey); line[0] = '_'; } qfits_header_append(outhdr, key, val, comment, line); } qfits_header_destroy(wcshdr); wcshdr = NULL; qfits_header_append(outhdr, "COMMENT", "", NULL, NULL); qfits_header_append(outhdr, "COMMENT", "--End of Astrometry.net WCS--", NULL, NULL); qfits_header_append(outhdr, "COMMENT", "--(Put in by the new-wcs program)--", NULL, NULL); qfits_header_append(outhdr, "COMMENT", "", NULL, NULL); qfits_header_append(outhdr, "END", NULL, NULL, NULL); if (qfits_header_dump(outhdr, outfid) || fits_pad_file(outfid)) { SYSERROR("Failed to write output header to file %s", outfn); goto bailout; } qfits_header_destroy(outhdr); outhdr = NULL; if (copydata) { int datsize, datstart; FILE* infid = NULL; anqfits_t* anq = NULL; anq = anqfits_open(infn); if (!anq) { ERROR("Failed to open file \"%s\"", infn); goto bailout; } datstart = anqfits_data_start(anq, extension); datsize = anqfits_data_size (anq, extension); infid = fopen(infn, "rb"); if (!infid) { SYSERROR("Failed to open input file \"%s\"", infn); anqfits_close(anq); goto bailout; } logverb("Copying from offset %i to offset %i (length %i) of the input file to the output.\n", datstart, datstart + datsize, datsize); if (pipe_file_offset(infid, datstart, datsize, outfid)) { ERROR("Failed to copy the data block"); fclose(infid); anqfits_close(anq); goto bailout; } fclose(infid); if (fits_pad_file(outfid)) { ERROR("Failed to pad FITS file \"%s\"", outfn); anqfits_close(anq); goto bailout; } anqfits_close(anq); anq = NULL; } if (fclose(outfid)) { SYSERROR("Failed to close output file \"%s\"", outfn); goto bailout; } // Free regular expressions... for (e=0; e<NE1; e++) regfree(re1 + e); for (e=0; e<NE2; e++) regfree(re2 + e); return 0; bailout: if (outfid) fclose(outfid); if (inhdr) qfits_header_destroy(inhdr); if (outhdr) qfits_header_destroy(outhdr); if (wcshdr) qfits_header_destroy(wcshdr); for (i=0; i<n1; i++) regfree(re1 + i); for (i=0; i<n2; i++) regfree(re2 + i); return -1; }
int merge_index(quadfile* quad, codetree* code, startree_t* star, const char* indexfn) { FILE* fout; fitstable_t* tag = NULL; fout = fopen(indexfn, "wb"); if (!fout) { SYSERROR("Failed to open output file"); return -1; } if (quadfile_write_header_to(quad, fout)) { ERROR("Failed to write quadfile header to index file %s", indexfn); return -1; } if (quadfile_write_all_quads_to(quad, fout)) { ERROR("Failed to write quads to index file %s", indexfn); return -1; } if (fits_pad_file(fout)) { ERROR("Failed to pad index file %s", indexfn); return -1; } if (codetree_append_to(code, fout)) { ERROR("Failed to write code kdtree to index file %s", indexfn); return -1; } if (fits_pad_file(fout)) { ERROR("Failed to pad index file %s", indexfn); return -1; } if (startree_append_to(star, fout)) { ERROR("Failed to write star kdtree to index file %s", indexfn); return -1; } if (fits_pad_file(fout)) { ERROR("Failed to pad index file %s", indexfn); return -1; } if (startree_has_tagalong(star)) tag = startree_get_tagalong(star); if (tag) { if (fitstable_append_to(tag, fout)) { ERROR("Failed to write star kdtree tag-along data to index file %s", indexfn); return -1; } if (fits_pad_file(fout)) { ERROR("Failed to pad index file %s", indexfn); return -1; } } if (fclose(fout)) { SYSERROR("Failed to close index file %s", indexfn); return -1; } return 0; }