Example #1
0
static
fitstable_t* _fitstable_open(const char* fn) {
    fitstable_t* tab;
    tab = fitstable_new();
    if (!tab) {
		ERROR("Failed to allocate new FITS table structure");
        goto bailout;
	}
    tab->extension = 1;
    tab->fn = strdup_safe(fn);

	tab->anq = anqfits_open(fn);
	if (!tab->anq) {
		ERROR("Failed to open FITS file \"%s\"", fn);
		goto bailout;
	}
	tab->primheader = anqfits_get_header(tab->anq, 0);
    if (!tab->primheader) {
        ERROR("Failed to read primary FITS header from %s", fn);
        goto bailout;
    }
    return tab;
 bailout:
    if (tab) {
        fitstable_close(tab);
    }
    return NULL;
}
Example #2
0
int multiindex_add_index(multiindex_t* mi, const char* fn, int flags) {
	anqfits_t* fits;
	quadfile_t* quads = NULL;
	codetree_t* codes = NULL;
	index_t* ind = NULL;
	logverb("Reading index file \"%s\"...\n", fn);
    fits = anqfits_open(fn);
	if (!fits) {
		ERROR("Failed to open FITS file \"%s\"", fn);
		goto bailout;
	}
	logverb("Reading quads from file \"%s\"...\n", fn);
	quads = quadfile_open_fits(fits);
	if (!quads) {
		ERROR("Failed to read quads from file \"%s\"", fn);
		anqfits_close(fits);
		goto bailout;
	}
	logverb("Reading codes from file \"%s\"...\n", fn);
	codes = codetree_open_fits(fits);
	if (!codes) {
		ERROR("Failed to read quads from file \"%s\"", fn);
		quadfile_close(quads);
		anqfits_close(fits);
		goto bailout;
	}
	
	ind = index_build_from(codes, quads, mi->starkd);
	ind->fits = fits;
	if (!ind->indexname)
		ind->indexname = strdup(fn);
    // shouldn't be needed, but set anyway
    ind->quadfn = strdup(fn);
    ind->codefn = strdup(fn);

	pl_append(mi->inds, ind);

    if (flags & INDEX_ONLY_LOAD_METADATA) {
        // don't let it unload the starkd!
        ind->starkd = NULL;
        index_unload(ind);
        ind->starkd = mi->starkd;
    }

	return 0;
 bailout:
	if (quads) {
		quadfile_close(quads);
	}
	if (codes) {
		codetree_close(codes);
	}
	if (fits) {
		anqfits_close(fits);
	}
	return -1;
}
Example #3
0
qfits_header* anqfits_get_header2(const char* fn, int ext) {
    qfits_header* hdr;
    anqfits_t* anq = anqfits_open(fn);
    if (!anq) {
        qfits_error("Failed to read FITS file \"%s\"", fn);
        return NULL;
    }
    hdr = anqfits_get_header(anq, ext);
    anqfits_close(anq);
    return hdr;
}
Example #4
0
multiindex_t* multiindex_new(const char* skdtfn) {
	multiindex_t* mi = calloc(1, sizeof(multiindex_t));
	logverb("Reading star KD tree from %s...\n", skdtfn);
	mi->fits = anqfits_open(skdtfn);
	if (!mi->fits) {
		ERROR("Failed to open multiindex file \"%s\"", skdtfn);
        goto bailout;
	}
	mi->inds = pl_new(16);
    if (multiindex_reload_starkd(mi)) {
		ERROR("Failed to open multiindex star kd-tree \"%s\"", skdtfn);
		goto bailout;
	}
	return mi;
bailout:
	multiindex_free(mi);
	return NULL;
}
Example #5
0
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;
}
Example #6
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;
}
Example #7
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;
}
Example #8
0
int main(int argc, char** args) {
    int argchar;
	char* progname = args[0];

	char* outfn = NULL;
	char* outwcsfn = NULL;
	int outwcsext = 0;

	anwcs_t* outwcs;

	sl* inimgfns = sl_new(16);
	sl* inwcsfns = sl_new(16);
	sl* inwtfns = sl_new(16);
	il* inimgexts = il_new(16);
	il* inwcsexts = il_new(16);
	il* inwtexts = il_new(16);

	int i;
	int loglvl = LOG_MSG;
	int order = 3;

	coadd_t* coadd;
	lanczos_args_t largs;

	double sigma = 0.0;
	anbool nearest = FALSE;
	anbool divweight = FALSE;

	int plane = 0;

    while ((argchar = getopt(argc, args, OPTIONS)) != -1)
        switch (argchar) {
		case '?':
        case 'h':
			printHelp(progname);
			exit(0);
		case 'D':
			divweight = TRUE;
			break;
		case 'p':
			plane = atoi(optarg);
			break;
		case 'N':
			nearest = TRUE;
			break;
		case 's':
			sigma = atof(optarg);
			break;
		case 'v':
			loglvl++;
			break;
		case 'e':
			outwcsext = atoi(optarg);
			break;
		case 'w':
			outwcsfn = optarg;
			break;
		case 'o':
			outfn = optarg;
			break;
		case 'O':
			order = atoi(optarg);
			break;
		}

	log_init(loglvl);
	fits_use_error_system();

	args += optind;
	argc -= optind;
	if (argc == 0 || argc % 6) {
		printHelp(progname);
		exit(-1);
	}

	for (i=0; i<argc/6; i++) {
		sl_append(inimgfns, args[6*i+0]);
		il_append(inimgexts, atoi(args[6*i+1]));
		sl_append(inwtfns, args[6*i+2]);
		il_append(inwtexts, atoi(args[6*i+3]));
		sl_append(inwcsfns, args[6*i+4]);
		il_append(inwcsexts, atoi(args[6*i+5]));
	}

	logmsg("Reading output WCS file %s\n", outwcsfn);
	outwcs = anwcs_open(outwcsfn, outwcsext);
	if (!outwcs) {
		ERROR("Failed to read WCS from file: %s ext %i\n", outwcsfn, outwcsext);
		exit(-1);
	}

	logmsg("Output image will be %i x %i\n", (int)anwcs_imagew(outwcs), (int)anwcs_imageh(outwcs));

	coadd = coadd_new(anwcs_imagew(outwcs), anwcs_imageh(outwcs));

	coadd->wcs = outwcs;

	if (nearest) {
		coadd->resample_func = nearest_resample_f;
		coadd->resample_token = NULL;
	} else {
		coadd->resample_func = lanczos_resample_f;
		largs.order = order;
		coadd->resample_token = &largs;
	}

	for (i=0; i<sl_size(inimgfns); i++) {
        anqfits_t* anq;
        anqfits_t* wanq;
		float* img;
		float* wt = NULL;
		anwcs_t* inwcs;
		char* fn;
		int ext;
		float overallwt = 1.0;
        int W, H;

		fn = sl_get(inimgfns, i);
		ext = il_get(inimgexts, i);
		logmsg("Reading input image \"%s\" ext %i\n", fn, ext);

        anq = anqfits_open(fn);
        if (!anq) {
            ERROR("Failed to open file \"%s\"\n", fn);
            exit(-1);
        }

        img = anqfits_readpix(anq, ext, 0, 0, 0, 0, plane,
                              PTYPE_FLOAT, NULL, &W, &H);
        if (!img) {
            ERROR("Failed to read image from ext %i of %s\n", ext, fn);
            exit(-1);
        }
        anqfits_close(anq);
		logmsg("Read image: %i x %i.\n", W, H);

		if (sigma > 0.0) {
			int k0, nk;
			float* kernel;
			logmsg("Smoothing by Gaussian with sigma=%g\n", sigma);
			kernel = convolve_get_gaussian_kernel_f(sigma, 4, &k0, &nk);
			convolve_separable_f(img, W, H, kernel, k0, nk, img, NULL);
			free(kernel);
		}

		fn = sl_get(inwcsfns, i);
		ext = il_get(inwcsexts, i);
		logmsg("Reading input WCS file \"%s\" ext %i\n", fn, ext);

		inwcs = anwcs_open(fn, ext);
		if (!inwcs) {
			ERROR("Failed to read WCS from file \"%s\" ext %i\n", fn, ext);
			exit(-1);
		}
		if (anwcs_pixel_scale(inwcs) == 0) {
			ERROR("Pixel scale from the WCS file is zero.  Usually this means the image has no valid WCS header.\n");
			exit(-1);
		}
		if (anwcs_imagew(inwcs) != W || anwcs_imageh(inwcs) != H) {
			ERROR("Size mismatch between image and WCS!");
			exit(-1);
		}

		fn = sl_get(inwtfns, i);
		ext = il_get(inwtexts, i);
		if (streq(fn, "none")) {
			logmsg("Not using weight image.\n");
			wt = NULL;
		} else if (file_exists(fn)) {
			logmsg("Reading input weight image \"%s\" ext %i\n", fn, ext);
            wanq = anqfits_open(fn);
            if (!wanq) {
                ERROR("Failed to open file \"%s\"\n", fn);
                exit(-1);
            }
            int wtW, wtH;
            wt = anqfits_readpix(anq, ext, 0, 0, 0, 0, 0,
                              PTYPE_FLOAT, NULL, &wtW, &wtH);
            if (!wt) {
                ERROR("Failed to read image from ext %i of %s\n", ext, fn);
                exit(-1);
            }
            anqfits_close(wanq);
			logmsg("Read image: %i x %i.\n", wtW, wtH);
			if (wtW != W || wtH != H) {
				ERROR("Size mismatch between image and weight!");
				exit(-1);
			}
		} else {
			char* endp;
			overallwt = strtod(fn, &endp);
			if (endp == fn) {
				ERROR("Weight: \"%s\" is neither a file nor a double.\n", fn);
				exit(-1);
			}
			logmsg("Parsed weight value \"%g\"\n", overallwt);
		}

		if (divweight && wt) {
			int j;
			logmsg("Dividing image by weight image...\n");
			for (j=0; j<(W*H); j++)
				img[j] /= wt[j];
		}

		coadd_add_image(coadd, img, wt, overallwt, inwcs);

		anwcs_free(inwcs);
        free(img);
		if (wt)
			free(wt);
	}

	//
	logmsg("Writing output: %s\n", outfn);

	coadd_divide_by_weight(coadd, 0.0);

	/*
	 if (fits_write_float_image_hdr(coadd->img, coadd->W, coadd->H, outfn)) {
	 ERROR("Failed to write output image %s", outfn);
	 exit(-1);
	 }
	 */
	/*
	 if (fits_write_float_image(coadd->img, coadd->W, coadd->H, outfn)) {
	 ERROR("Failed to write output image %s", outfn);
	 exit(-1);
	 }
	 */
	{
		qfitsdumper qoutimg;
		qfits_header* hdr;
		hdr = anqfits_get_header2(outwcsfn, outwcsext);
		if (!hdr) {
			ERROR("Failed to read WCS file \"%s\" ext %i\n", outwcsfn, outwcsext);
			exit(-1);
		}
		fits_header_mod_int(hdr, "NAXIS", 2, NULL);
		fits_header_set_int(hdr, "NAXIS1", coadd->W, "image width");
		fits_header_set_int(hdr, "NAXIS2", coadd->H, "image height");
		fits_header_modf(hdr, "BITPIX", "-32", "32-bit floats");
		memset(&qoutimg, 0, sizeof(qoutimg));
		qoutimg.filename = outfn;
		qoutimg.npix = coadd->W * coadd->H;
		qoutimg.fbuf = coadd->img;
		qoutimg.ptype = PTYPE_FLOAT;
		qoutimg.out_ptype = BPP_IEEE_FLOAT;
		if (fits_write_header_and_image(NULL, &qoutimg, coadd->W)) {
			ERROR("Failed to write FITS image to file \"%s\"", outfn);
			exit(-1);
		}
		qfits_header_destroy(hdr);
	}

	coadd_free(coadd);
	sl_free2(inimgfns);
	sl_free2(inwcsfns);
	sl_free2(inwtfns);
	il_free(inimgexts);
	il_free(inwcsexts);
	il_free(inwtexts);
	anwcs_free(outwcs);


	return 0;
}
Example #9
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;
}
Example #10
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;
}
Example #11
0
int main(int argc, char *argv[]) {
  int argchar;

  char* infn = NULL;
  char* outfn = NULL;
  anbool tostdout = FALSE;
  FILE* fin = NULL;
  FILE* fout = NULL;
  il* exts;
  int i;
  char* progname = argv[0];
  anbool inblocks = FALSE;
  anbool inmegs = FALSE;
  int allexts = 0;
  int Next = -1;
  anbool dataonly = FALSE;
  anbool headeronly = FALSE;
  anqfits_t* anq = NULL;
  int loglvl = LOG_MSG;

  exts = il_new(16);

  while ((argchar = getopt (argc, argv, OPTIONS)) != -1)
    switch (argchar) {
    case 'v':
        loglvl++;
        break;
    case 'D':
      dataonly = TRUE;
      break;
    case 'H':
      headeronly = TRUE;
      break;
    case 'a':
      allexts = 1;
      break;
    case 'b':
      inblocks = TRUE;
      break;
    case 'M':
      inmegs = TRUE;
      break;
    case 'e':
      il_append(exts, atoi(optarg));
      break;
    case 'i':
      infn = optarg;
      break;
    case 'o':
      outfn = optarg;
      break;
    case '?':
    case 'h':
      printHelp(progname);
      return 0;
    default:
      return -1;
    }

  if (headeronly && dataonly) {
    fprintf(stderr, "Can't write data blocks only AND header blocks only!\n");
    exit(-1);
  }

  if (inblocks && inmegs) {
    fprintf(stderr, "Can't write sizes in FITS blocks and megabytes.\n");
    exit(-1);
  }

  fits_use_error_system();
  log_init(loglvl);
  log_to(stderr);
  errors_log_to(stderr);

  if (infn) {
    anq = anqfits_open(infn);
    if (!anq) {
      ERROR("Failed to open input file \"%s\"", infn);
      exit(-1);
    }
    Next = anqfits_n_ext(anq);
    fprintf(stderr, "File %s contains %i FITS extensions.\n", infn, Next);
  }

  if (infn && !outfn) {
    for (i=0; i<Next; i++) {
      off_t hdrstart, hdrlen, datastart, datalen;

      hdrstart  = anqfits_header_start(anq, i);
      hdrlen    = anqfits_header_size(anq, i);
      datastart = anqfits_data_start(anq, i);
      datalen   = anqfits_data_size(anq, i);

      if (inblocks) {
	off_t block = (off_t)FITS_BLOCK_SIZE;
	fprintf(stderr, "Extension %i : header start %zu , length %zu ; data start %zu , length %zu blocks.\n",
			i, (size_t)(hdrstart / block), (size_t)(hdrlen / block), (size_t)(datastart / block), (size_t)(datalen / block));
      } else if (inmegs) {
	off_t meg = 1024*1024;
	fprintf(stderr, "Extension %i : header start %zu , length %zu ; data start %zu , length %zu megabytes.\n",
			i, (size_t)(hdrstart/meg), (size_t)(hdrlen/meg), (size_t)(datastart/meg), (size_t)(datalen/meg));
      } else {
	fprintf(stderr, "Extension %i : header start %zu , length %zu ; data start %zu , length %zu .\n",
			i, (size_t)hdrstart, (size_t)hdrlen, (size_t)datastart, (size_t)datalen);
      }
    }
    anqfits_close(anq);
    exit(0);
  }

  if (!infn || !outfn || !(il_size(exts) || allexts)) {
    printHelp(progname);
    exit(-1);
  }

  if (!strcmp(outfn, "-")) {
    tostdout = TRUE;
    if (allexts) {
      fprintf(stderr, "Specify all extensions (-a) and outputting to stdout (-o -) doesn't make much sense...\n");
      exit(-1);
    }
  }

  if (infn) {
    fin = fopen(infn, "rb");
    if (!fin) {
      fprintf(stderr, "Failed to open input file %s: %s\n", infn, strerror(errno));
      exit(-1);
    }
  }

  if (tostdout)
    fout = stdout;
  else {
    if (allexts)
      for (i=0; i<Next; i++)
	il_append(exts, i);
    else {
      // open the (single) output file.
      fout = fopen(outfn, "wb");
      if (!fout) {
	fprintf(stderr, "Failed to open output file %s: %s\n", outfn, strerror(errno));
	exit(-1);
      }
    }
  }

  for (i=0; i<il_size(exts); i++) {
    off_t hdrstart, hdrlen, datastart, datalen;
    int ext = il_get(exts, i);

    if (allexts) {
      char fn[256];
      snprintf(fn, sizeof(fn), outfn, ext);
      fout = fopen(fn, "wb");
      if (!fout) {
	fprintf(stderr, "Failed to open output file %s: %s\n", fn, strerror(errno));
	exit(-1);
      }
    }

    hdrstart  = anqfits_header_start(anq, ext);
    hdrlen    = anqfits_header_size(anq, ext);
    datastart = anqfits_data_start(anq, ext);
    datalen   = anqfits_data_size(anq, ext);

    if (inblocks) {
      off_t block = (off_t)FITS_BLOCK_SIZE;
      fprintf(stderr, "Writing extension %i : header start %zu , length %zu ; data start %zu , length %zu blocks.\n",
			  ext, (size_t)(hdrstart / block), (size_t)(hdrlen / block), (size_t)(datastart / block), (size_t)(datalen / block));
    } else if (inmegs) {
      off_t meg = 1024*1024;
      fprintf(stderr, "Writing extension %i : header start %zu , length %zu ; data start %zu , length %zu megabytes.\n",
			  ext, (size_t)(hdrstart/meg), (size_t)(hdrlen/meg), (size_t)(datastart/meg), (size_t)(datalen/meg));
    } else {
      fprintf(stderr, "Writing extension %i : header start %zu , length %zu ; data start %zu , length %zu .\n",
	      ext, (size_t)hdrstart, (size_t)hdrlen, (size_t)datastart, (size_t)datalen);
    }

    if (hdrlen && !dataonly) {
      if (pipe_file_offset(fin, hdrstart, hdrlen, fout)) {
	fprintf(stderr, "Failed to write header for extension %i: %s\n", ext, strerror(errno));
	exit(-1);
      }
    }
    if (datalen && !headeronly) {
      if (pipe_file_offset(fin, datastart, datalen, fout)) {
	fprintf(stderr, "Failed to write data for extension %i: %s\n", ext, strerror(errno));
	exit(-1);
      }
    }

    if (allexts)
      if (fclose(fout)) {
	fprintf(stderr, "Failed to close output file: %s\n", strerror(errno));
	exit(-1);
      }
  }

  fclose(fin);
  if (!allexts && !tostdout)
    fclose(fout);
  il_free(exts);
  anqfits_close(anq);
  return 0;
}
Example #12
0
int main(int argc, char *argv[]) {
    int argchar;
    char* infn = NULL;
    char* outfn = NULL;
    anbool tostdout = FALSE;
    FILE* fin = NULL;
    FILE* fout = NULL;
    il* exts;
    il* sizes;
    int i;
    char* progname = argv[0];
    int Next;
    anqfits_t* anq;

    exts = il_new(16);
    sizes = il_new(16);

    while ((argchar = getopt (argc, argv, OPTIONS)) != -1)
        switch (argchar) {
        case 'e':
            il_append(exts, atoi(optarg));
            break;
        case 's':
            il_append(sizes, atoi(optarg));
            break;
        case 'i':
            infn = optarg;
            break;
        case 'o':
            outfn = optarg;
            break;
        case '?':
        case 'h':
            printHelp(progname);
            return 0;
        default:
            return -1;
        }

    log_init(LOG_MSG);

    if (!infn || !outfn || !il_size(exts) || (il_size(exts) != il_size(sizes))) {
        printHelp(progname);
        exit(-1);
    }

    if (infn) {
        fin = fopen(infn, "rb");
        if (!fin) {
            SYSERROR("Failed to open input file %s", infn);
            exit(-1);
        }
    }
    
    anq = anqfits_open(infn);
    if (!anq) {
        ERROR("Failed to open input file %s", infn);
        exit(-1);
    }
    Next = anqfits_n_ext(anq);
    if (Next == -1) {
        ERROR("Couldn't determine how many extensions are in file %s", infn);
        exit(-1);
    } else {
        logverb("File %s contains %i FITS extensions.\n", infn, Next);
    }

    for (i=0; i<il_size(exts); i++) {
        int e = il_get(exts, i);
        int s = il_get(sizes, i);
        if (e < 0 || e >= Next) {
            logerr("Extension %i is not valid: must be in [%i, %i]\n", e, 0, Next);
            exit(-1);
        }
        if (s != 2 && s != 4 && s != 8) {
            logerr("Invalid byte size %i: must be 2, 4, or 8.\n", s);
            exit(-1);
        }
    }

    if (!strcmp(outfn, "-"))
        tostdout = TRUE;

    if (tostdout)
        fout = stdout;
    else {
        fout = fopen(outfn, "wb");
        if (!fout) {
            SYSERROR("Failed to open output file %s", outfn);
            exit(-1);
        }
    }

    for (i=0; i<Next; i++) {
        int hdrstart, hdrlen, datastart, datalen;
        int ind;
        int size;
        ind = il_index_of(exts, i);
        if (ind == -1) {
            size = 0;
        } else {
            size = il_get(sizes, ind);
        }

        hdrstart = anqfits_header_start(anq, i);
        hdrlen   = anqfits_header_size (anq, i);
        datastart = anqfits_data_start(anq, i);
        datalen   = anqfits_data_size (anq, i);

        if (hdrlen) {
            if (pipe_file_offset(fin, hdrstart, hdrlen, fout)) {
                ERROR("Failed to write header for extension %i", i);
                exit(-1);
            }
        }
        if (!datalen)
            continue;

        if (size) {
            int Nitems = datalen / size;
            int j;
            char buf[size];
            logmsg("Extension %i: flipping words of length %i bytes.\n", i, size);
            for (j=0; j<Nitems; j++) {
                if (fread(buf, size, 1, fin) != 1) {
                    SYSERROR("Failed to read data element %i from extension %i", j, i);
                    exit(-1);
                }
                endian_swap(buf, size);
                if (fwrite(buf, size, 1, fout) != 1) {
                    SYSERROR("Failed to write data element %i to extension %i", j, i);
                    exit(-1);
                }
            }
        } else {
            logmsg("Extension %i: copying verbatim.\n", i);
            // passthrough
            if (pipe_file_offset(fin, datastart, datalen, fout)) {
                ERROR("Failed to write data for extension %i", i);
                exit(-1);
            }
        }
    }
    fclose(fin);
    anqfits_close(anq);
    if (!tostdout)
        fclose(fout);
    il_free(exts);
    il_free(sizes);
    return 0;
}