1
0
Fork 0

More bits from qfits

qfits
Jeff Moe 2022-08-06 21:03:09 -06:00
parent 28dd111b0f
commit 953d2cb3ec
31 changed files with 8485 additions and 0 deletions

View File

@ -0,0 +1,55 @@
#
# qfits tools Makefile
#
#
# General definitions
#
include ../config.make
RM = rm -f
CP = cp
MV = mv
BINDIR = ../bin
COMPF = $(CFLAGS) -I../include
LINKF = $(LFLAGS) -L../lib -lqfits
default: all
PROGS= $(BINDIR)/dtfits \
$(BINDIR)/flipx \
$(BINDIR)/dfits \
$(BINDIR)/frameq \
$(BINDIR)/replacekey \
$(BINDIR)/qextract
all: $(PROGS)
veryclean:
@(echo "cleaning qfits programs...")
@($(RM) $(PROGS))
$(BINDIR)/dfits: dfits.c
$(CC) $(COMPF) -o $(BINDIR)/dfits dfits.c $(LINKF)
$(BINDIR)/dtfits: dtfits.c
$(CC) $(COMPF) -o $(BINDIR)/dtfits dtfits.c $(LINKF)
$(BINDIR)/flipx: flipx.c
$(CC) $(COMPF) -o $(BINDIR)/flipx flipx.c $(LINKF)
$(BINDIR)/frameq: frameq.c
$(CC) $(COMPF) -o $(BINDIR)/frameq frameq.c $(LINKF)
$(BINDIR)/replacekey: replacekey.c
$(CC) $(COMPF) -o $(BINDIR)/replacekey replacekey.c $(LINKF)
$(BINDIR)/qextract: qextract.c
$(CC) $(COMPF) -o $(BINDIR)/qextract qextract.c $(LINKF)

319
qfits/main/dfits.c 100644
View File

@ -0,0 +1,319 @@
/*----------------------------------------------------------------------------*/
/**
@file dfits.c
@author Nicolas Devillard
@date 30 Mar 2000
@version $Revision: 1.3 $
@brief FITS header display
*/
/*----------------------------------------------------------------------------*/
/*
$Id: dfits.c,v 1.3 2005/07/19 15:38:52 yjung Exp $
$Author: yjung $
$Date: 2005/07/19 15:38:52 $
$Revision: 1.3 $
*/
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "qfits.h"
/*-----------------------------------------------------------------------------
Define
-----------------------------------------------------------------------------*/
#define BLOCK_SIZE 2880
#define LGTH 80
#define MAGIC "SIMPLE ="
/* If compiled against zlib, include support for gzipped files */
#if HAVE_ZLIB
#include "zlib.h"
#define FILE gzFile
#define fopen gzopen
#define fclose gzclose
#define fread(b,s,n,f) gzread(f,b,n*s)
#endif
/*-----------------------------------------------------------------------------
Function prototypes
-----------------------------------------------------------------------------*/
void usage(char * pname) ;
void parse_cmd_line(int, char **, int *, int *, int *) ;
int dump_fits_filter(FILE *, int) ;
int dump_fits(char *, int) ;
char * rstrip(char *) ;
/*-----------------------------------------------------------------------------
Main
-----------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
int xtnum ;
int c_arg ;
int filter ;
int err ;
/* No arguments prints out a usage message */
if (argc<2) usage(argv[0]);
/* Parse command-line options */
parse_cmd_line(argc, argv, &xtnum, &filter, &c_arg);
/* Filter mode: process data received from stdin */
if (filter) {
#if HAVE_ZLIB
printf("filter mode does not support gzipped files\n");
printf("use: gunzip -c file.fits | dfits -\n");
return 1 ;
#else
return dump_fits_filter(stdin, xtnum);
#endif
}
/* Normal mode: loop on all file names given on command-line */
err = 0 ;
while (c_arg < argc) {
err += dump_fits(argv[c_arg], xtnum);
c_arg++;
}
return err ; /* Returns number of errors during process */
}
void usage(char * pname)
{
printf(
"\n\n"
"usage: %s [-x xtnum] <list of FITS files>\n"
"usage: %s [-x xtnum] -\n"
"\n"
"The former version expects file names.\n"
"The latter expects data coming in from stdin.\n"
"\n"
"-x xtnum specifies the extension header to print\n"
"-x 0 specifies main header + all extensions\n"
"\n\n",
pname, pname);
#if HAVE_ZLIB
printf(
"This program was compiled against zlib %s\n"
"This means you can use it with gzipped FITS files\n"
"as with uncompressed FITS files.\n"
"NB: this does not apply to the '-' option (input from stdin)\n"
"\n\n", ZLIB_VERSION);
#endif
exit(1) ;
}
void parse_cmd_line(
int argc,
char ** argv,
int * xtnum,
int * filter,
int * c_arg)
{
*filter = 0 ;
*xtnum = -1 ;
*c_arg = argc-1 ;
/* If '-' is on the command-line, it must be the last argument */
if (!strcmp(argv[argc-1], "-")) *filter = 1 ;
/* If -x xtnum is on the command-line, it must be the first two arguments */
if (!strcmp(argv[1], "-x")) {
*xtnum = atoi(argv[2]);
*c_arg = 3 ;
} else {
*c_arg = 1 ;
}
return ;
}
/* Strip off all blank characters in a string from the right-side. */
char * rstrip(char * s)
{
int len ;
if (s==NULL) return s ;
len = strlen(s);
if (len<1) return s ;
len -- ;
while (s[len]== ' ') {
s[len]=(char)0 ;
len --;
if (len<0) break ;
}
return s ;
}
/* Dump the requested header (main or extension) from a filename. */
int dump_fits(char * name, int xtnum)
{
FILE * in ;
int err ;
if ((in=fopen(name, "r"))==NULL) {
fprintf(stderr, "error: cannot open file [%s]\n", name);
return 1 ;
}
printf("====> file %s (main) <====\n", name) ;
err = dump_fits_filter(in, xtnum);
fclose(in);
return err ;
}
/* Dump the requested header (main or extension) from a FILE * */
int dump_fits_filter(FILE * in, int xtnum)
{
int n_xt ;
char buf[LGTH+1];
int err ;
int data_bytes, naxis ;
char * read_val ;
int skip_blocks ;
int seeked ;
/* Try getting the first 80 chars */
memset(buf, 0, LGTH+1);
if (fread(buf, sizeof(char), LGTH, in)!=LGTH) {
fprintf(stderr, "error reading input\n");
return 1;
}
/* Check that it is indeed FITS */
if (strncmp(buf, MAGIC, strlen(MAGIC))) {
fprintf(stderr, "not a FITS file\n");
return 1 ;
}
naxis = 0 ;
data_bytes = 1 ;
if (xtnum<1) {
/* Output main header */
printf("%s\n", rstrip(buf));
data_bytes = 1 ;
naxis = 0 ;
while ((err=fread(buf, sizeof(char), LGTH, in))==LGTH) {
printf("%s\n", rstrip(buf));
/* Look for BITPIX keyword */
if (buf[0]=='B' &&
buf[1]=='I' &&
buf[2]=='T' &&
buf[3]=='P' &&
buf[4]=='I' &&
buf[5]=='X' &&
buf[6]==' ') {
read_val = qfits_getvalue(buf);
data_bytes *= (int)atoi(read_val) / 8 ;
if (data_bytes<0) data_bytes *= -1 ;
} else
/* Look for NAXIS keyword */
if (buf[0]=='N' &&
buf[1]=='A' &&
buf[2]=='X' &&
buf[3]=='I' &&
buf[4]=='S') {
if (buf[5]==' ') {
/* NAXIS keyword */
read_val = qfits_getvalue(buf);
naxis = (int)atoi(read_val);
} else {
/* NAXIS?? keyword (axis size) */
read_val = qfits_getvalue(buf);
data_bytes *= (int)atoi(read_val);
}
} else
/* Look for END keyword */
if (buf[0]=='E' &&
buf[1]=='N' &&
buf[2]=='D') {
break ;
}
}
if (err!=LGTH) return 1 ;
}
if (xtnum<0) return 0 ;
n_xt=0 ;
while (1) {
/*
* Skip the previous data section if pixels were declared
*/
if (naxis>0) {
/* Skip as many blocks as there are declared pixels */
skip_blocks = data_bytes/BLOCK_SIZE ;
if ((data_bytes % BLOCK_SIZE)!=0) skip_blocks ++ ;
seeked = fseek(in, skip_blocks*BLOCK_SIZE, SEEK_CUR);
if (seeked<0) return -1 ;
}
/* Look for next XTENSION keyword */
while ((err=fread(buf, sizeof(char), LGTH, in))==LGTH) {
if (buf[0]=='X' &&
buf[1]=='T' &&
buf[2]=='E' &&
buf[3]=='N' &&
buf[4]=='S' &&
buf[5]=='I' &&
buf[6]=='O' &&
buf[7]=='N') break ;
}
if (err==0) break ;
if (err!=LGTH) return 1 ;
n_xt++ ;
if (xtnum==0 || xtnum==n_xt) {
printf("===> xtension %d\n", n_xt) ;
printf("%s\n", rstrip(buf));
}
data_bytes = 1 ;
naxis = 0 ;
while ((err=fread(buf, sizeof(char), LGTH, in))==LGTH) {
if (xtnum==0 || xtnum==n_xt) printf("%s\n", rstrip(buf));
/* Look for BITPIX keyword */
if (buf[0]=='B' &&
buf[1]=='I' &&
buf[2]=='T' &&
buf[3]=='P' &&
buf[4]=='I' &&
buf[5]=='X' &&
buf[6]==' ') {
read_val = qfits_getvalue(buf);
data_bytes *= (int)atoi(read_val) / 8 ;
if (data_bytes<0) data_bytes *= -1 ;
} else
/* Look for NAXIS keyword */
if (buf[0]=='N' &&
buf[1]=='A' &&
buf[2]=='X' &&
buf[3]=='I' &&
buf[4]=='S') {
if (buf[5]==' ') {
/* NAXIS keyword */
read_val = qfits_getvalue(buf);
naxis = (int)atoi(read_val);
} else {
/* NAXIS?? keyword (axis size) */
read_val = qfits_getvalue(buf);
data_bytes *= (int)atoi(read_val);
}
} else
/* Look for END keyword */
if (buf[0]=='E' &&
buf[1]=='N' &&
buf[2]=='D') break ;
}
if (n_xt==xtnum) break ;
}
return 0 ;
}

542
qfits/main/dtfits.c 100644
View File

@ -0,0 +1,542 @@
/*----------------------------------------------------------------------------*/
/**
@file dtfits.c
@date July 1999
@version $Revision: 1.14 $
@brief FITS table dump
*/
/*----------------------------------------------------------------------------*/
/*
$Id: dtfits.c,v 1.14 2005/07/20 14:25:16 yjung Exp $
$Author: yjung $
$Date: 2005/07/20 14:25:16 $
$Revision: 1.14 $
*/
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include "qfits.h"
#include "xmemory.h"
/*-----------------------------------------------------------------------------
Define
-----------------------------------------------------------------------------*/
#define ELEMENT_MAX_DISP_SIZE 50
#define DISP_SIZE_INT 5
#define DISP_SIZE_DOUBLE 8
#define DISP_SIZE_FLOAT 7
#define DISP_SIZE_CHAR 1
/*-----------------------------------------------------------------------------
Function prototypes
-----------------------------------------------------------------------------*/
static int dump_extension_bin(qfits_table *, FILE *, void **, char, int,
int) ;
static int dump_extension_ascii(qfits_table *, FILE *, void **, char,
int, int) ;
static int dump_extension(qfits_table *, FILE *, char, int, int) ;
static void qfits_dump(char *, char *, int, char, int);
static void usage(char * pname) ;
static char prog_desc[] = "FITS table dump" ;
/*-----------------------------------------------------------------------------
Main
-----------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
char name_i[FILENAMESZ] ;
char name_o[FILENAMESZ] ;
int i ;
int data_only ;
char separator ;
int ext ;
/* Initialize */
data_only = 0 ;
separator = '|' ;
ext = -1 ;
i=1 ;
if (argc<2) usage(argv[0]);
while (i<argc) {
if (!strcmp(argv[i], "--help") ||
!strcmp(argv[i], "-h")) {
usage(argv[0]);
} else if (!strcmp(argv[i], "-d")) {
data_only=1 ;
} else if (!strcmp(argv[i], "-s")) {
if ((i+1)>=argc) {
fprintf(stderr, "option -s needs an argument\n");
return -1 ;
}
i++ ;
separator = argv[i][0] ;
} else if (!strcmp(argv[i], "-x")) {
if ((i+1)>=argc) {
fprintf(stderr, "option -x needs an argument\n");
return -1 ;
}
i++ ;
ext = atoi(argv[i]) ;
} else {
break ;
}
i++ ;
}
if ((argc-i)<1) {
fprintf(stderr, "missing input file name\n");
return -1 ;
}
strcpy(name_i, argv[i]);
i++ ;
if ((argc-i)<1) name_o[0] = 0 ;
else strcpy(name_o, argv[i]);
qfits_dump(name_i, name_o, data_only, separator, ext);
return 0 ;
}
static void usage(char * pname)
{
printf("%s -- %s\n", pname, prog_desc);
printf(
"use : %s [options] <FITS table> [out]\n"
"options are:\n"
"\t-d to dump data only (no headers)\n"
"\t-s <char> to output data with separator <char>\n"
"\n",
pname);
exit(0) ;
}
static void qfits_dump(
char * name_i,
char * name_o,
int data_only,
char separator,
int ext)
{
qfits_table * tdesc ;
FILE * out ;
int xtnum_start, xtnum_stop ;
int n_ext ;
int i ;
/* Set where to send the output */
if (name_o[0]==(char)0) {
out = stdout ;
} else {
if ((out = fopen(name_o, "w"))==NULL) {
fprintf(stderr, "cannot create output file [%s]\n", name_o);
return ;
}
}
if (!data_only) {
fprintf(out, "#\n");
fprintf(out, "# file %s\n", name_i);
}
/* Query number of extensions in the file */
n_ext = qfits_query_n_ext(name_i);
if (!data_only) {
fprintf(out, "# extensions %d\n", n_ext);
}
/* If no extension, bail out */
if (n_ext<1) {
if (out!=stdout) fclose(out) ;
return ;
}
/* 1 extension required or all */
if (ext < 1) {
xtnum_start = 1 ;
xtnum_stop = n_ext ;
} else if (ext > n_ext) {
fprintf(out, "# requested extension does not exist %d\n", ext) ;
if (out!=stdout) fclose(out) ;
return ;
} else {
xtnum_start = xtnum_stop = ext ;
}
/* Loop over all extensions */
for (i=xtnum_start ; i<=xtnum_stop ; i++) {
if (!data_only) {
fprintf(out, "# --------------------------------------------\n");
fprintf(out, "# XTENSION %d\n", i);
}
if ((tdesc = qfits_table_open(name_i, i)) == NULL) {
printf("cannot open table [%s]:[%d]\n", name_i, i);
if (out!=stdout) fclose(out);
return ;
}
dump_extension(tdesc, out, separator, data_only, 1) ;
qfits_table_close(tdesc);
}
fclose(out) ;
return ;
}
static int dump_extension(
qfits_table * tdesc,
FILE * out,
char separator,
int data_only,
int use_zero_scale)
{
void ** cols ;
int i, j ;
if (!data_only) {
fprintf(out, "# Number of columns %d\n", tdesc->nc);
fprintf(out, "#\n");
}
/* First read the columns in memory */
cols = malloc(tdesc->nc * sizeof(void*)) ;
for (i=0 ; i<tdesc->nc ; i++) {
cols[i] = qfits_query_column_data(tdesc, i, NULL, NULL) ;
if (cols[i] == NULL) {
fprintf(out, "# Cannot load column nb %d\n", i+1) ;
}
}
switch (tdesc->tab_t) {
case QFITS_BINTABLE:
dump_extension_bin(tdesc, out, cols, separator, data_only,
use_zero_scale) ;
break ;
case QFITS_ASCIITABLE:
dump_extension_ascii(tdesc, out, cols, separator, data_only,
use_zero_scale) ;
break ;
default:
fprintf(out, "Table type not recognized") ;
break ;
}
for (i=0 ; i<tdesc->nc ; i++) if (cols[i]) free(cols[i]) ;
free(cols) ;
return 0 ;
}
static int dump_extension_bin(
qfits_table * tdesc,
FILE * out,
void ** cols,
char separator,
int data_only,
int use_zero_scale)
{
int * col_sizes ;
qfits_col * col ;
char * ccol ;
unsigned char * ucol ;
double * dcol ;
float * fcol ;
short * scol ;
int * icol ;
int size ;
int field_size ;
char * str ;
char ctmp[512];
int i, j, k ;
/* GET THE FIELDS SIZES */
col_sizes = calloc(tdesc->nc, sizeof(int)) ;
for (i=0 ; i<tdesc->nc ; i++) {
col = tdesc->col + i ;
col_sizes[i] = (int)strlen(col->tlabel) ;
switch(col->atom_type) {
case TFITS_BIN_TYPE_A:
size = col->atom_size * col->atom_nb ;
break ;
case TFITS_BIN_TYPE_B:
size = col->atom_nb * (DISP_SIZE_INT + 2) ;
break ;
case TFITS_BIN_TYPE_D:
case TFITS_BIN_TYPE_M:
size = col->atom_nb * (DISP_SIZE_DOUBLE + 2) ;
break ;
case TFITS_BIN_TYPE_E:
case TFITS_BIN_TYPE_C:
size = col->atom_nb * (DISP_SIZE_FLOAT + 2) ;
break ;
case TFITS_BIN_TYPE_I:
size = col->atom_nb * (DISP_SIZE_INT + 2) ;
break ;
case TFITS_BIN_TYPE_J:
size = col->atom_nb * (DISP_SIZE_INT + 2) ;
break ;
case TFITS_BIN_TYPE_L:
size = col->atom_nb * (DISP_SIZE_CHAR + 2) ;
break ;
case TFITS_BIN_TYPE_X:
size = col->atom_nb * (DISP_SIZE_INT + 2) ;
break ;
case TFITS_BIN_TYPE_P:
size = col->atom_nb * (DISP_SIZE_INT + 2) ;
break ;
default:
fprintf(out, "Type not recognized") ;
break ;
}
if (size > col_sizes[i]) col_sizes[i] = size ;
}
/* Print out the column names */
if (!data_only) {
for (i=0 ; i<tdesc->nc ; i++) {
col = tdesc->col + i ;
fprintf(out, "%*s", col_sizes[i], col->tlabel);
if (i!=(tdesc->nc-1)) printf("%c", separator);
}
fprintf(out, "\n");
}
/* Get the string to write according to the type */
for (j=0 ; j<tdesc->nr ; j++) {
for (i=0 ; i<tdesc->nc ; i++) {
if (cols[i] == NULL) continue ;
col = tdesc->col + i ;
field_size = col->atom_nb * ELEMENT_MAX_DISP_SIZE ;
str = malloc(field_size * sizeof(char)) ;
str[0] = (char)0 ;
switch(col->atom_type) {
case TFITS_BIN_TYPE_A:
ccol = (char*)(cols[i]) ;
ccol += col->atom_size * col->atom_nb * j ;
strncpy(ctmp, ccol, col->atom_size * col->atom_nb) ;
ctmp[col->atom_size*col->atom_nb] = (char)0 ;
strcpy(str, ctmp) ;
break ;
case TFITS_BIN_TYPE_B:
ucol = (unsigned char*)(cols[i]) ;
ucol += col->atom_nb * j ;
/* For each atom of the column */
for (k=0 ; k<col->atom_nb-1 ; k++) {
sprintf(ctmp, "%d, ", (int)ucol[k]) ;
strcat(str, ctmp) ;
}
/* Handle the last atom differently: no ',' */
sprintf(ctmp,"%d",(int)ucol[col->atom_nb-1]);
strcat(str, ctmp) ;
break ;
case TFITS_BIN_TYPE_D:
case TFITS_BIN_TYPE_M:
dcol = (double*)(cols[i]) ;
dcol += col->atom_nb * j ;
/* For each atom of the column */
for (k=0 ; k<col->atom_nb-1 ; k++) {
sprintf(ctmp, "%g, ", dcol[k]) ;
strcat(str, ctmp) ;
}
/* Handle the last atom differently: no ',' */
sprintf(ctmp, "%g", dcol[col->atom_nb-1]) ;
strcat(str, ctmp) ;
break ;
case TFITS_BIN_TYPE_E:
case TFITS_BIN_TYPE_C:
fcol = (float*)(cols[i]) ;
fcol += col->atom_nb * j ;
/* For each atom of the column */
for (k=0 ; k<col->atom_nb-1 ; k++) {
sprintf(ctmp, "%f, ", fcol[k]) ;
strcat(str, ctmp) ;
}
/* Handle the last atom differently: no ',' */
sprintf(ctmp, "%f", fcol[col->atom_nb-1]) ;
strcat(str, ctmp) ;
break ;
case TFITS_BIN_TYPE_I:
scol = (short*)(cols[i]) ;
scol += col->atom_nb * j ;
/* For each atom of the column */
for (k=0 ; k<col->atom_nb-1 ; k++) {
sprintf(ctmp, "%d, ", scol[k]) ;
strcat(str, ctmp) ;
}
/* Handle the last atom differently: no ',' */
sprintf(ctmp, "%d", scol[col->atom_nb-1]) ;
strcat(str, ctmp) ;
break ;
case TFITS_BIN_TYPE_J:
icol = (int*)(cols[i]) ;
icol += col->atom_nb * j ;
/* For each atom of the column */
for (k=0 ; k<col->atom_nb-1 ; k++) {
sprintf(ctmp, "%d, ", icol[k]) ;
strcat(str, ctmp) ;
}
/* Handle the last atom differently: no ',' */
sprintf(ctmp, "%d", icol[col->atom_nb-1]) ;
strcat(str, ctmp) ;
break ;
case TFITS_BIN_TYPE_L:
ccol = (char*)(cols[i]) ;
ccol += col->atom_nb * j ;
/* For each atom of the column */
for (k=0 ; k<col->atom_nb-1 ; k++) {
sprintf(ctmp, "%c, ", ccol[k]) ;
strcat(str, ctmp) ;
}
/* Handle the last atom differently: no ',' */
sprintf(ctmp, "%c", ccol[col->atom_nb-1]) ;
strcat(str, ctmp) ;
break ;
case TFITS_BIN_TYPE_X:
ucol = (unsigned char*)(cols[i]) ;
ucol += col->atom_nb * j ;
/* For each atom of the column */
for (k=0 ; k<col->atom_nb-1 ; k++) {
sprintf(ctmp, "%d, ", ucol[k]) ;
strcat(str, ctmp) ;
}
/* Handle the last atom differently: no ',' */
sprintf(ctmp, "%d", ucol[col->atom_nb-1]) ;
strcat(str, ctmp) ;
break ;
case TFITS_BIN_TYPE_P:
icol = (int*)(cols[i]) ;
icol += col->atom_nb * j ;
/* For each atom of the column */
for (k=0 ; k<col->atom_nb-1 ; k++) {
sprintf(ctmp, "%d, ", icol[k]) ;
strcat(str, ctmp) ;
}
/* Handle the last atom differently: no ',' */
sprintf(ctmp, "%d", icol[col->atom_nb-1]) ;
strcat(str, ctmp) ;
break ;
default:
fprintf(out, "Type not recognized") ;
break ;
}
fprintf(out, "%*s", col_sizes[i], str);
if (i!=(tdesc->nc-1)) printf("%c", separator);
free(str) ;
}
fprintf(out, "\n");
}
return 0 ;
}
static int dump_extension_ascii(
qfits_table * tdesc,
FILE * out,
void ** cols,
char separator,
int data_only,
int use_zero_scale)
{
int * col_sizes ;
qfits_col * col ;
char * ccol ;
double * dcol ;
float * fcol ;
int * icol ;
int size ;
int field_size ;
char * str ;
char ctmp[512];
int i, j, k ;
/* GET THE FIELDS SIZES */
col_sizes = calloc(tdesc->nc, sizeof(int)) ;
for (i=0 ; i<tdesc->nc ; i++) {
col = tdesc->col + i ;
col_sizes[i] = (int)strlen(col->tlabel) ;
switch(col->atom_type) {
case TFITS_ASCII_TYPE_A:
size = col->atom_nb ;
break ;
case TFITS_ASCII_TYPE_I:
size = DISP_SIZE_INT ;
break ;
case TFITS_ASCII_TYPE_E:
case TFITS_ASCII_TYPE_F:
size = DISP_SIZE_FLOAT ;
break ;
case TFITS_ASCII_TYPE_D:
size = DISP_SIZE_DOUBLE ;
break ;
default:
fprintf(out, "Type not recognized") ;
break ;
}
if (size > col_sizes[i]) col_sizes[i] = size ;
}
/* Print out the column names */
if (!data_only) {
for (i=0 ; i<tdesc->nc ; i++) {
col = tdesc->col + i ;
fprintf(out, "%*s", col_sizes[i], col->tlabel);
if (i!=(tdesc->nc-1)) printf("%c", separator);
}
fprintf(out, "\n");
}
/* Get the string to write according to the type */
for (j=0 ; j<tdesc->nr ; j++) {
for (i=0 ; i<tdesc->nc ; i++) {
if (cols[i] == NULL) continue ;
col = tdesc->col + i ;
field_size = col->atom_nb * ELEMENT_MAX_DISP_SIZE ;
str = malloc(field_size * sizeof(char)) ;
str[0] = (char)0 ;
switch(col->atom_type) {
case TFITS_ASCII_TYPE_A:
ccol = (char*)(cols[i]) ;
ccol += col->atom_nb * j ;
strncpy(ctmp, ccol, col->atom_nb) ;
ctmp[col->atom_nb] = (char)0 ;
strcpy(str, ctmp) ;
break ;
case TFITS_ASCII_TYPE_I:
icol = (int*)(cols[i]) ;
icol += j ;
sprintf(ctmp, "%d", icol[0]) ;
strcat(str, ctmp) ;
break ;
case TFITS_ASCII_TYPE_E:
case TFITS_ASCII_TYPE_F:
fcol = (float*)(cols[i]) ;
fcol += j ;
sprintf(ctmp, "%f", fcol[0]) ;
strcat(str, ctmp) ;
break ;
case TFITS_ASCII_TYPE_D:
dcol = (double*)(cols[i]) ;
dcol += j ;
sprintf(ctmp, "%g", dcol[0]) ;
strcat(str, ctmp) ;
break ;
default:
fprintf(out, "Type not recognized") ;
break ;
}
fprintf(out, "%*s", col_sizes[i], str);
if (i!=(tdesc->nc-1)) printf("%c", separator);
free(str) ;
}
fprintf(out, "\n");
}
return 0 ;
}

168
qfits/main/flipx.c 100644
View File

@ -0,0 +1,168 @@
/*----------------------------------------------------------------------------*/
/**
@file flipx.c
@author N. Devillard
@date July 2001
@version $Revision: 1.5 $
@brief flip x axis in a FITS image
*/
/*----------------------------------------------------------------------------*/
/*
$Id: flipx.c,v 1.5 2002/12/04 13:28:25 yjung Exp $
$Author: yjung $
$Date: 2002/12/04 13:28:25 $
$Revision: 1.5 $
*/
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include "qfits.h"
/*-----------------------------------------------------------------------------
Private functions
-----------------------------------------------------------------------------*/
/*
* Swap pixels between position p1 and p2, regardless of the pixel
* type and endian-ness of the local host.
*/
static void swap_pix(char * buf, int p1, int p2, int psize)
{
int i ;
char c ;
for (i=0 ; i<psize ; i++) {
c = buf[p1+i] ;
buf[p1+i] = buf[p2+i];
buf[p2+i] = c ;
}
}
/*
* Main processing function. It expects one only file name
* and will flip pixels on the input frame.
*/
static int fits_flip(char * pname, char * filename)
{
char * sval ;
int dstart;
int lx, ly ;
int bpp ;
int i, j ;
char * buf ;
char * fbuf ;
int psize;
struct stat fileinfo ;
int fd ;
printf("%s: processing %s\n", pname, filename);
if (stat(filename, &fileinfo)!=0) {
return -1 ;
}
if (fileinfo.st_size<1) {
printf("cannot stat file\n");
return -1 ;
}
/* Retrieve image attributes */
if (is_fits_file(filename)!=1) {
printf("not a FITS file\n");
return -1 ;
}
sval = qfits_query_hdr(filename, "NAXIS1");
if (sval==NULL) {
printf("cannot read NAXIS1\n");
return -1 ;
}
lx = atoi(sval);
sval = qfits_query_hdr(filename, "NAXIS2");
if (sval==NULL) {
printf("cannot read NAXIS2\n");
return -1 ;
}
ly = atoi(sval);
sval = qfits_query_hdr(filename, "BITPIX");
if (sval==NULL) {
printf("cannot read BITPIX\n");
return -1 ;
}
bpp = atoi(sval);
psize = bpp/8 ;
if (psize<0) psize=-psize ;
/* Retrieve start of first data section */
if (qfits_get_hdrinfo(filename, 0, &dstart, NULL)!=0) {
printf("reading header information\n");
return -1 ;
}
/* Map the input file in read/write mode (input file is modified) */
if ((fd=open(filename, O_RDWR))==-1) {
perror("open");
printf("reading file\n");
return -1 ;
}
fbuf = (char*)mmap(0,
fileinfo.st_size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
0);
if (fbuf==(char*)-1) {
perror("mmap");
printf("mapping file\n");
return -1 ;
}
buf = fbuf + dstart ;
/* Double loop */
for (j=0 ; j<ly ; j++) {
for (i=0 ; i<lx/2 ; i++) {
/* Swap bytes */
swap_pix(buf, i*psize, (lx-i-1)*psize, psize);
}
buf += lx * psize ;
}
if (munmap(fbuf, fileinfo.st_size)!=0) {
printf("unmapping file\n");
return -1 ;
}
return 0 ;
}
/*-----------------------------------------------------------------------------
Main
-----------------------------------------------------------------------------*/
int main(int argc, char * argv[])
{
int i ;
int err ;
if (argc<2) {
printf("use: %s <list of FITS files...>\n", argv[0]);
return 1 ;
}
err=0 ;
for (i=1 ; i<argc ; i++) {
err += fits_flip(argv[0], argv[i]) ;
}
if (err>0) {
fprintf(stderr, "%s: %d error(s) occurred\n", argv[0], err);
return -1 ;
}
return 0 ;
}

461
qfits/main/frameq.c 100644
View File

@ -0,0 +1,461 @@
/*----------------------------------------------------------------------------*/
/**
@file frameq.c
@author N. Devillard
@date Aug 2000
@version $Revision: 1.7 $
@brief Classify frames
*/
/*----------------------------------------------------------------------------*/
/*
$Id: frameq.c,v 1.7 2004/07/21 16:03:21 yjung Exp $
$Author: yjung $
$Date: 2004/07/21 16:03:21 $
$Revision: 1.7 $
*/
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <glob.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "qfits.h"
/*-----------------------------------------------------------------------------
New types
-----------------------------------------------------------------------------*/
/* Frame informations needed to classify it */
typedef struct _framei {
char * name ;
char * tplid ;
char * origfile ;
int expno ;
int nexp ;
struct _framei * next ;
} framei ;
/* Frame queue: is mostly a pointer to a list of frame information objects */
typedef struct _frameq {
framei * first ;
int n ;
} frameq ;
/*-----------------------------------------------------------------------------
Global variables
-----------------------------------------------------------------------------*/
/* List of strings to identify unwanted templates. */
char * tpl_filter[] = {
"_acq_",
"_CheckAoCorrection",
NULL
};
/*-----------------------------------------------------------------------------
Functions code
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief Build a new framei object
@param filename FITS file name
@return A newly allocated framei obj. NULL in error case
*/
/*----------------------------------------------------------------------------*/
static framei * framei_new(char * filename)
{
framei * fi ;
char * sval ;
char * sval2 ;
int i ;
fi = malloc(sizeof(framei));
fi->name = strdup(filename);
sval = qfits_query_hdr(filename, "tpl.id");
if (sval!=NULL) {
/* Filter out unwanted template IDs */
i=0 ;
while (tpl_filter[i]!=NULL) {
if (strstr(sval, tpl_filter[i])!=NULL) return NULL ;
i++ ;
}
fi->tplid = strdup(qfits_pretty_string(sval)) ;
} else {
fi->tplid = NULL ;
}
sval = qfits_query_hdr(filename, "origfile");
if (sval!=NULL) {
sval2 = qfits_pretty_string(sval) ;
fi->origfile = strdup(qfits_get_root_name(sval2)) ;
} else {
fi->origfile = NULL ;
}
sval = qfits_query_hdr(filename, "tpl.expno");
if (sval!=NULL) fi->expno = (int)atoi(sval);
else fi->expno = -1 ;
sval = qfits_query_hdr(filename, "tpl.nexp");
if (sval!=NULL) fi->nexp = (int)atoi(sval);
else fi->nexp = -1 ;
fi->next = NULL ;
return fi ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Delete a framei object
@param fi Object to delete
*/
/*----------------------------------------------------------------------------*/
static void framei_del(framei * fi)
{
if (fi==NULL) return ;
if (fi->name!=NULL)
free(fi->name);
if (fi->tplid!=NULL) {
free(fi->tplid);
}
if (fi->origfile!=NULL) {
free(fi->origfile);
}
free(fi);
}
/*----------------------------------------------------------------------------*/
/**
@brief Create a frameq object
@return A newly allocated empty frameq object
*/
/*----------------------------------------------------------------------------*/
frameq * frameq_new(void)
{
frameq * fq ;
fq = malloc(sizeof(frameq));
fq->first = NULL ;
fq->n = 0 ;
return fq ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Delete a frameq object
@param fq The object to delete
*/
/*----------------------------------------------------------------------------*/
void frameq_del(frameq * fq)
{
framei * fi ;
framei * fin ;
if (fq==NULL) return ;
fi = fq->first ;
while (fi!=NULL) {
fin = fi->next ;
framei_del(fi);
fi = fin ;
}
free(fq);
return ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Append a new frame to an existing frame queue
@param fq The existing frame queue
@param filename The file to append name
*/
/*----------------------------------------------------------------------------*/
void frameq_append(frameq * fq, char * filename)
{
framei * fi ;
framei * fn ;
if (fq==NULL || filename==NULL) return ;
fi = framei_new(filename);
if (fi==NULL)
return ;
if (fq->n==0) {
fq->first = fi ;
fq->n = 1 ;
return ;
}
fn = fq->first ;
while (fn->next!=NULL)
fn = fn->next ;
fn->next = fi ;
fq->n ++ ;
return ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Pop a frame out of the queue
@param fq The frame queue
*/
/*----------------------------------------------------------------------------*/
void frameq_pop(frameq * fq)
{
framei * first ;
first = fq->first->next ;
framei_del(fq->first);
fq->first = first ;
fq->n -- ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Dump a frame queue in a file
@param fq Frame queue to dump
@param out File where the queue is dumped
*/
/*----------------------------------------------------------------------------*/
void frameq_dump(frameq * fq, FILE * out)
{
int i ;
framei * fi ;
fi = fq->first ;
for (i=0 ; i<fq->n ; i++) {
fprintf(out,
"%s %s %02d/%02d\n",
fi->name,
fi->tplid,
fi->expno,
fi->nexp);
fi = fi->next ;
}
}
/*----------------------------------------------------------------------------*/
/**
@brief Create a frame queue from a directory
@param dirname Directory name
@return A newly allocated frame queue
*/
/*----------------------------------------------------------------------------*/
frameq * frameq_load(char * dirname)
{
frameq * fq ;
int i ;
glob_t pglob ;
char filename[FILENAMESZ];
/* Look for *.fits *.FITS *.fits.gz *.FITS.gz */
sprintf(filename, "%s/*.fits", dirname);
glob(filename, GLOB_MARK, NULL, &pglob);
sprintf(filename, "%s/*.FITS", dirname);
glob(filename, GLOB_APPEND, NULL, &pglob);
sprintf(filename, "%s/*.fits.gz", dirname);
glob(filename, GLOB_APPEND, NULL, &pglob);
sprintf(filename, "%s/*.FITS.gz", dirname);
glob(filename, GLOB_APPEND, NULL, &pglob);
if (pglob.gl_pathc<1) {
printf("found no frame\n");
return NULL ;
}
/* Build frame queue */
fq = frameq_new();
for (i=0 ; i<pglob.gl_pathc ; i++) {
printf("\radding %d of %d", i+1, pglob.gl_pathc);
fflush(stdout);
frameq_append(fq, pglob.gl_pathv[i]);
}
printf("\n");
globfree(&pglob);
return fq ;
}
static int stringsort(const void * e1, const void * e2)
{
return strcmp(*(char**)e1, *(char**)e2);
}
/*----------------------------------------------------------------------------*/
/**
@brief Get TPL.ID keywords from a frame queue
@param fq The frame queue
@param n Number of values in output
@return List of n strings
*/
/*----------------------------------------------------------------------------*/
char ** frameq_get_tplid(frameq * fq, int * n)
{
framei * fn ;
char ** tplid_all ;
char ** tplid ;
int i, j ;
int ntplid ;
/* Get all possible values for tplid */
tplid_all = malloc(fq->n * sizeof(char*));
fn = fq->first ;
for (i=0 ; i<fq->n ; i++) {
if (fn->tplid==NULL) {
tplid_all[i] = strdup("none");
} else {
tplid_all[i] = strdup(fn->tplid);
}
fn = fn->next ;
}
/* Sort all tplid's */
qsort(tplid_all, fq->n, sizeof(char*), stringsort);
/* Compute how many different tplid's can be found */
ntplid=1 ;
for (i=1 ; i<fq->n ; i++) {
if (strcmp(tplid_all[i], tplid_all[i-1])) {
ntplid++ ;
}
}
tplid = malloc(ntplid * sizeof(char*));
tplid[0] = tplid_all[0] ;
tplid_all[0] = NULL ;
j=0 ;
for (i=1 ; i<fq->n ; i++) {
if (strcmp(tplid_all[i], tplid[j])) {
j++ ;
tplid[j] = tplid_all[i] ;
} else {
free(tplid_all[i]);
}
tplid_all[i] = NULL ;
}
free(tplid_all);
*n = ntplid ;
return tplid ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Get the setting number
@param dirname Directory name
@return Setting number
*/
/*----------------------------------------------------------------------------*/
int frameq_getsetnum(char * dirname)
{
char pattern[FILENAMESZ];
glob_t pglob ;
int i ;
int max ;
int num ;
sprintf(pattern, "%s/set*", dirname);
glob(pattern, GLOB_MARK, NULL, &pglob);
if (pglob.gl_pathc<1) {
max=0 ;
} else {
sprintf(pattern, "%s/set%%02d", dirname);
max=0 ;
for (i=0 ; i<pglob.gl_pathc ; i++) {
sscanf(pglob.gl_pathv[i], pattern, &num);
if (num>max)
max=num ;
}
}
globfree(&pglob);
return max+1 ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Classify the frames
@param fq Frame queue
*/
/*----------------------------------------------------------------------------*/
void frameq_makelists(frameq * fq)
{
FILE * list ;
char filename[FILENAMESZ];
framei * fi ;
int setnum ;
int count ;
int batches ;
/* Count # of batches in input */
fi = fq->first ;
batches=0 ;
while (fi!=NULL) {
if (fi->expno==1)
batches++ ;
fi = fi->next ;
}
fi = fq->first ;
count=0 ;
list=NULL ;
while (fi!=NULL) {
printf("\rclassifying batches: %d of %d", count, batches);
fflush(stdout);
if (fi->expno<0) {
fi=fi->next ;
continue ;
}
if (fi->expno==1) {
count++ ;
if (list!=NULL) {
fclose(list);
}
if (fi->tplid == NULL) {
printf("No TPL ID - abort\n") ;
return ;
}
if (fi->origfile == NULL) {
printf("No ORIGFILE - abort\n") ;
return ;
}
mkdir(fi->tplid, 0755);
setnum = frameq_getsetnum(fi->tplid);
sprintf(filename, "%s/%s_%02d", fi->tplid, fi->origfile, fi->nexp);
mkdir(filename, 0755);
sprintf(filename, "%s/%s_%02d/IN", fi->tplid,fi->origfile,fi->nexp);
list = fopen(filename, "w");
fprintf(list,"# TPL.ID= %s\n", fi->tplid);
fprintf(list,"# NEXP = %02d\n", fi->nexp);
}
if (list) fprintf(list, "%s\n", fi->name);
fi = fi->next ;
}
printf("\n");
return ;
}
/*-----------------------------------------------------------------------------
Main
-----------------------------------------------------------------------------*/
int main(int argc, char * argv[])
{
frameq * fq ;
if (argc<2) {
printf("use: %s <dirname>\n", argv[0]);
return 1 ;
}
printf("loading frames from %s...\n", argv[1]);
fq = frameq_load(argv[1]);
printf("processing lists...\n");
frameq_makelists(fq);
frameq_del(fq);
printf("done\n");
return 0 ;
}

View File

@ -0,0 +1,267 @@
/*----------------------------------------------------------------------------*/
/**
@file qextract.c
@author Y. Jung
@date Nov, 2002
@version $Revision: 1.5 $
@brief Extract a FITS extension and write it in a new FITS file
*/
/*----------------------------------------------------------------------------*/
/*
$Id: qextract.c,v 1.5 2005/06/29 15:14:50 yjung Exp $
$Author: yjung $
$Date: 2005/06/29 15:14:50 $
$Revision: 1.5 $
*/
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include "qfits.h"
/*-----------------------------------------------------------------------------
Function prototypes
-----------------------------------------------------------------------------*/
static int textract_write_ext(char *, int) ;
static int iextract_write_ext(char *, int) ;
static char prog_desc[] = "Extract and write FITS extensions" ;
static void usage(char *) ;
/*-----------------------------------------------------------------------------
Main
-----------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
char * name_in ;
int ext ;
int nb_ext ;
int ext_type ;
if (argc<3) usage(argv[0]) ;
/* Get input file name and extension number */
name_in = strdup(argv[1]) ;
ext = (int)atoi(argv[2]) ;
/* Check if the file is a FITS file */
if (!is_fits_file(name_in)) {
printf("[%s] is not a FITS file\n", name_in) ;
free(name_in) ;
return -1 ;
}
/* Check if the extension is valid */
nb_ext = qfits_query_n_ext(name_in) ;
if (nb_ext < ext) {
printf("Only %d extensions in this file\n", nb_ext) ;
free(name_in) ;
return -1 ;
}
/* Check if it's a table or an image */
ext_type = qfits_is_table(name_in, ext) ;
switch (ext_type) {
case QFITS_BINTABLE:
case QFITS_ASCIITABLE:
if (textract_write_ext(name_in, ext) == -1) {
printf("cannot read-write extension no %d\n", ext) ;
free(name_in) ;
return -1 ;
}
break ;
case QFITS_INVALIDTABLE:
if (iextract_write_ext(name_in, ext) == -1) {
printf("cannot read-write extension no %d\n", ext) ;
free(name_in) ;
return -1 ;
}
break ;
default:
printf("Unrecognized FITS type\n") ;
free(name_in) ;
return -1 ;
}
free(name_in) ;
return 0 ;
}
/*-----------------------------------------------------------------------------
Functions code
-----------------------------------------------------------------------------*/
static void usage(char * pname)
{
printf("%s : %s\n", pname, prog_desc) ;
printf(
"use : %s <in> <extension>\n"
"\n", pname) ;
exit(0) ;
}
static int textract_write_ext(
char * in,
int ext)
{
qfits_table * th ;
void ** array ;
qfits_header * fh ;
int array_size ;
int i ;
/* Get the table infos */
if ((th = qfits_table_open(in, ext)) == NULL) {
printf("cannot read extension: %d\n", ext) ;
return -1 ;
}
/* Compute array_size */
array_size = 0 ;
for (i=0 ; i<th->nc ; i++) {
switch (th->col[i].atom_type) {
case TFITS_ASCII_TYPE_A:
case TFITS_ASCII_TYPE_I:
case TFITS_ASCII_TYPE_E:
case TFITS_ASCII_TYPE_F:
case TFITS_ASCII_TYPE_D:
case TFITS_BIN_TYPE_A:
case TFITS_BIN_TYPE_L:
case TFITS_BIN_TYPE_B:
case TFITS_BIN_TYPE_X:
array_size += sizeof(char*) ;
break ;
case TFITS_BIN_TYPE_I:
array_size += sizeof(short*) ;
break ;
case TFITS_BIN_TYPE_J:
case TFITS_BIN_TYPE_E:
array_size += sizeof(int*) ;
break ;
case TFITS_BIN_TYPE_C:
case TFITS_BIN_TYPE_P:
array_size += sizeof(float*) ;
break ;
case TFITS_BIN_TYPE_D:
case TFITS_BIN_TYPE_M:
array_size += sizeof(double*) ;
break ;
default:
return -1 ;
}
}
/* Allocate memory for array */
array = malloc(array_size) ;
/* Load columns in array */
for (i=0 ; i<th->nc ; i++) {
array[i] = qfits_query_column_data(th, i, NULL, NULL) ;
if (array[i] == NULL) {
printf("cannot read column %d\n", i+1) ;
}
}
/* Update th : filename */
sprintf(th->filename, "ext%d.tfits", ext) ;
/* Get fits primary header */
if ((fh = qfits_header_read(in)) == NULL) {
for (i=0 ; i<th->nc ; i++) if (array[i] != NULL) free(array[i]) ;
qfits_table_close(th) ;
free(array) ;
printf("cannot read fits header\n") ;
return -1 ;
}
if (ext != 0) {
/* No data in primary HDU */
qfits_header_mod(fh, "NAXIS", "0", NULL) ;
qfits_header_del(fh, "NAXIS1") ;
qfits_header_del(fh, "NAXIS2") ;
}
/* Write the tfits file */
if (qfits_save_table_hdrdump((void **)array, th, fh) == -1) {
qfits_header_destroy(fh) ;
for (i=0 ; i<th->nc ; i++) if (array[i] != NULL) free(array[i]) ;
qfits_table_close(th) ;
free(array) ;
printf("cannot write fits table\n") ;
return -1 ;
}
/* Free and return */
qfits_header_destroy(fh) ;
for (i=0 ; i<th->nc ; i++) if (array[i] != NULL) free(array[i]) ;
qfits_table_close(th) ;
free(array) ;
return 0 ;
}
static int iextract_write_ext(
char * in,
int ext)
{
qfitsloader ql ;
qfitsdumper qd ;
qfits_header * fh ;
char outname[1024] ;
FILE * out ;
sprintf(outname, "ext%d.fits", ext) ;
/* Initialize a FITS loader */
ql.filename = in ;
ql.xtnum = ext ;
ql.pnum = 0 ;
ql.map = 1 ;
ql.ptype = PTYPE_DOUBLE ;
if (qfitsloader_init(&ql)!=0) return -1 ;
/* Load the primary header */
if ((fh = qfits_header_read(ql.filename)) == NULL) return -1 ;
if (ext != 0) {
/* No data in primary HDU */
qfits_header_mod(fh, "NAXIS", "0", NULL) ;
qfits_header_del(fh, "NAXIS1") ;
qfits_header_del(fh, "NAXIS2") ;
}
/* Dump the primary header */
if ((out = fopen(outname, "w")) == NULL) return -1 ;
qfits_header_dump(fh, out);
qfits_header_destroy(fh) ;
if (ext != 0) {
/* Load the extension header */
if ((fh = qfits_header_readext(ql.filename, ext)) == NULL) return -1 ;
/* Dump the extension header */
qfits_header_dump(fh, out);
qfits_header_destroy(fh) ;
}
fclose(out) ;
/* Load the FITS image */
if (qfits_loadpix(&ql)!=0) return -1 ;
/* Write the FITS image */
qd.filename = outname ;
qd.npix = ql.lx * ql.ly ;
qd.ptype = PTYPE_DOUBLE ;
qd.dbuf = ql.dbuf ;
qd.out_ptype = ql.bitpix ;
if (qfits_pixdump(&qd)!=0) return -1 ;
/* qfits_zeropad(outname) ; */
free(ql.dbuf) ;
return 0 ;
}

View File

@ -0,0 +1,212 @@
/*----------------------------------------------------------------------------*/
/**
@file replacekey.c
@author N. Devillard
@date July 14th, 1998
@version $Revision: 1.6 $
@brief Search & Replace operations in FITS headers
*/
/*----------------------------------------------------------------------------*/
/*
$Id: replacekey.c,v 1.6 2003/08/21 10:44:32 yjung Exp $
$Author: yjung $
$Date: 2003/08/21 10:44:32 $
$Revision: 1.6 $
*/
/*-----------------------------------------------------------------------------
Include
-----------------------------------------------------------------------------*/
#include "qfits.h"
/*-----------------------------------------------------------------------------
Define
-----------------------------------------------------------------------------*/
#define NM_SIZ 512
/*-----------------------------------------------------------------------------
Functions prototypes
-----------------------------------------------------------------------------*/
static char prog_desc[] = "replace keyword in a FITS header" ;
static void usage(char *) ;
/*-----------------------------------------------------------------------------
Main
-----------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
char * name_in ;
char * card ;
char * place ;
char * key ;
char * key_tmp ;
char * val ;
char * val_tmp ;
char * com ;
char * com_tmp ;
int keep_com ;
int numeric ;
char * stmp ;
int i ;
char card_tmp[NM_SIZ] ;
if (argc<2) usage(argv[0]) ;
/* Initialize */
name_in = NULL ;
card = NULL ;
place = NULL ;
key = NULL ;
val = NULL ;
com = NULL ;
keep_com = 0 ;
numeric = 0 ;
/* Command line handling */
i=1 ;
while (i<argc) {
if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) {
usage(argv[0]);
} else if (!strcmp(argv[i], "-p")) {
if ((i+1)>=argc) {
fprintf(stderr, "option -p needs an argument\n");
return -1 ;
}
i++ ;
place = strdup(argv[i]);
} else if (!strcmp(argv[i], "-k")) {
if ((i+1)>=argc) {
fprintf(stderr, "option -k needs an argument\n");
return -1 ;
}
i++ ;
key = strdup(argv[i]);
} else if (!strcmp(argv[i], "-v")) {
if ((i+1)>=argc) {
fprintf(stderr, "option -v needs an argument\n");
return -1 ;
}
i++ ;
val = strdup(argv[i]);
} else if (!strcmp(argv[i], "-c")) {
if ((i+1)>=argc) {
fprintf(stderr, "option -c needs an argument\n");
return -1 ;
}
i++ ;
com = strdup(argv[i]);
} else if (!strcmp(argv[i], "-C")) {
keep_com = 1 ;
} else if (!strcmp(argv[i], "-n")) {
numeric = 1 ;
} else {
break ;
}
i++ ;
}
/* Check options coherence */
if ((keep_com == 1) && (com != NULL)) {
fprintf(stderr, "options -c and -C should not be used together\n") ;
if (place) free(place) ;
if (key) free(key) ;
if (val) free(val) ;
free(com) ;
return -1 ;
}
if (place == NULL) {
fprintf(stderr, "options -p has to be used\n") ;
if (key) free(key) ;
if (val) free(val) ;
if (com) free(com) ;
return -1 ;
}
/* Get input file name */
if ((argc-i)<1) {
fprintf(stderr, "missing input file name\n");
return -1 ;
}
/* Loop on the input files */
while (argc-i >= 1) {
name_in = strdup(argv[i]) ;
/* Set keyword to write */
key_tmp = NULL ;
if (key==NULL) key_tmp = strdup(place) ;
else key_tmp = strdup(key) ;
/* Set value to write */
val_tmp = NULL ;
if (val==NULL) {
card = qfits_query_card(name_in, place) ;
if (card!= NULL) {
stmp = qfits_getvalue(card) ;
val_tmp = strdup(stmp) ;
}
} else val_tmp = strdup(val) ;
com_tmp = NULL ;
/* Set comment to write */
if ((com == NULL) && (keep_com == 1)) {
if (card == NULL) card = qfits_query_card(name_in, place) ;
if (card != NULL) {
stmp = qfits_getcomment(card) ;
com_tmp = strdup(stmp) ;
}
} else if (com != NULL) com_tmp = strdup(com) ;
if (card != NULL) free(card) ;
card = NULL ;
printf("DEBUG: %s\n", key_tmp) ;
/* Create the card */
keytuple2str(card_tmp, key_tmp, val_tmp, com_tmp) ;
if (key_tmp) free(key_tmp) ;
if (val_tmp) free(val_tmp) ;
if (com_tmp) free(com_tmp) ;
card = strdup(card_tmp) ;
/* Display what will be written where */
printf("File %s\n", name_in) ;
printf("\tcard : \n\t\t%s\n", card) ;
printf("\tplace : \n\t\t%s\n", place) ;
/* Try to replace the first key */
if (qfits_replace_card(name_in, place, card) == -1) {
fprintf(stderr, "cannot replace the key %s\n", place) ;
}
free(name_in);
free(card) ;
card = NULL ;
i++ ;
}
if (val) free(val) ;
if (com) free(com) ;
if (key) free(key) ;
free(place) ;
/* Free and return */
return 0 ;
}
static void usage(char * pname)
{
printf("%s : %s\n", pname, prog_desc) ;
printf(
"use : %s [options] <in>\n"
"options are:\n"
"\t-p place gives the keyword to write over (required).\n"
"\t-k key gives the new keyword name (optional).\n"
"\t-v val gives the value to write (optional).\n"
"\t-c com gives the comment to write (optional).\n"
"\t-C flag to keep comment\n"
"\n", pname) ;
exit(0) ;
}

View File

@ -0,0 +1,41 @@
# General definitions
#
include ../config.make
RM = rm -f
CP = cp
MV = mv
BINDIR = ../bin
default: all
PROGS = $(BINDIR)/fitsort \
$(BINDIR)/hierarch28 \
$(BINDIR)/iofits \
$(BINDIR)/fitsmd5
all: $(PROGS)
veryclean:
@(echo "cleaning saft programs...")
@($(RM) $(PROGS))
$(BINDIR)/fitsort: fitsort.c
@(echo "building $@ ...")
@($(CC) $(CFLAGS) $(LFLAGS) -o $(BINDIR)/fitsort fitsort.c)
$(BINDIR)/hierarch28: hierarch28.c
@(echo "building $@ ...")
@($(CC) $(CFLAGS) $(LFLAGS) -o $(BINDIR)/hierarch28 hierarch28.c)
$(BINDIR)/iofits: iofits.c
@(echo "building $@ ...")
@($(CC) $(CFLAGS) $(LFLAGS) -o $(BINDIR)/iofits iofits.c)
$(BINDIR)/fitsmd5: fitsmd5.c
@(echo "building $@ ...")
@($(CC) $(CFLAGS) $(LFLAGS) -o $(BINDIR)/fitsmd5 fitsmd5.c)

View File

@ -0,0 +1,790 @@
/*----------------------------------------------------------------------------*/
/**
@file fitsmd5.c
@author N. Devillard
@date May 2001
@version $Revision: 1.5 $
@brief Display/Add/Update the DATAMD5 keyword/value
This is a stand-alone utility. Compile it with any ANSI C compiler:
% cc -o fitsmd5 fitsmd5.c [optional optimization options]
*/
/*----------------------------------------------------------------------------*/
/*
$Id: fitsmd5.c,v 1.5 2003/07/04 15:08:04 yjung Exp $
$Author: yjung $
$Date: 2003/07/04 15:08:04 $
$Revision: 1.5 $
*/
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
/*-----------------------------------------------------------------------------
Support for gzipped files if linked against zlib.
-----------------------------------------------------------------------------*/
#if HAVE_ZLIB
#include "zlib.h"
#define FILE gzFile
#define fopen gzopen
#define fclose gzclose
#define fread(b,s,n,f) gzread(f,b,n*s)
#define GZIP_MAGIC1 0x1f
#define GZIP_MAGIC2 0x8b
static is_gzipped(char * filename)
{
FILE * in ;
unsigned char b1, b2 ;
int r1, r2 ;
if ((in=fopen(filename, "r"))==NULL) {
return -1 ;
}
r1 = fread(&b1, 1, 1, in);
r2 = fread(&b2, 1, 1, in);
fclose(in);
if (r1!=1 || r2!=1)
return 0 ;
if ((int)b1!=GZIP_MAGIC1 || (int)b2!=GZIP_MAGIC2) {
return 0 ;
}
return 1 ;
}
#endif
/*-----------------------------------------------------------------------------
Define
-----------------------------------------------------------------------------*/
/* Definitions related to FITS */
#define FITSLINESZ 80 /* a FITS line is 80 chars */
#define FITSCARDS 36 /* 36 cards per block */
#define FITSBLOCKSZ (FITSLINESZ*FITSCARDS) /* FITS block size=2880 */
/* Definitions related to MD5 */
#define MD5HASHSZ 32 /* an MD5 key length is 32 bytes = 128 bits */
/* FITS keyword used to store MD5 key */
#define FITSMD5KEY "DATAMD5 "
/*-----------------------------------------------------------------------------
New types
-----------------------------------------------------------------------------*/
/* The following types defined for MD5 computation only */
typedef unsigned int word32 ;
struct MD5Context {
word32 buf[4];
word32 bits[2];
unsigned char in[64];
};
/*-----------------------------------------------------------------------------
Private function prototypes
-----------------------------------------------------------------------------*/
static void MD5Init(struct MD5Context *);
static void MD5Update(struct MD5Context *, unsigned char *, unsigned);
static void MD5Final(unsigned char *, struct MD5Context *);
static void MD5Transform(word32 *, word32 *);
static void byteReverse(unsigned char *, unsigned);
static int fits_md5_check(char *, int);
static char * fits_pretty_string(char *);
static char * fits_getvalue(char *);
static void usage(void);
/*-----------------------------------------------------------------------------
Global variables
-----------------------------------------------------------------------------*/
static char * pname = NULL ;
static char prog_desc[] = "Compute/Update the DATAMD5 keyword/value" ;
static int silent_process=0 ;
/*-----------------------------------------------------------------------------
MD5 function code
-----------------------------------------------------------------------------*/
/* Reverse bytes in a 32-bit word. Harmless on little endian machines */
static void byteReverse(unsigned char *buf, unsigned longs)
{
word32 t;
do {
t = (word32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
((unsigned) buf[1] << 8 | buf[0]);
*(word32 *) buf = t;
buf += 4;
} while (--longs);
}
/* Start MD5 accumulation. Set bit count to 0 and buffer to MD5 init. const. */
static void MD5Init(struct MD5Context *ctx)
{
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->bits[0] = 0;
ctx->bits[1] = 0;
}
/* Update to reflect the concatenation of another buffer full of bytes. */
static void MD5Update(struct MD5Context *ctx, unsigned char *buf, unsigned len)
{
register word32 t;
/* Update bitcount */
t = ctx->bits[0];
if ((ctx->bits[0] = t + ((word32) len << 3)) < t)
ctx->bits[1]++; /* Carry from low to high */
ctx->bits[1] += len >> 29;
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if (t) {
unsigned char *p = (unsigned char *) ctx->in + t;
t = 64 - t;
if (len < t) {
memmove(p, buf, len);
return;
}
memmove(p, buf, t);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (word32 *) ctx->in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
while (len >= 64) {
memmove(ctx->in, buf, 64);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (word32 *) ctx->in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
memmove(ctx->in, buf, len);
}
/* Final wrapup - pad to 64-byte boundary with the bit pattern 1 0* */
/* (64-bit count of bits processed, MSB-first) */
static void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
{
unsigned int count ;
unsigned char * p ;
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (word32 *) ctx->in);
/* Now fill the next block with 56 bytes */
memset(ctx->in, 0, 56);
} else {
/* Pad block to 56 bytes */
memset(p, 0, count - 8);
}
byteReverse(ctx->in, 14);
/* Append length in bits and transform */
((word32 *) ctx->in)[14] = ctx->bits[0];
((word32 *) ctx->in)[15] = ctx->bits[1];
MD5Transform(ctx->buf, (word32 *) ctx->in);
byteReverse((unsigned char *) ctx->buf, 4);
memmove(digest, ctx->buf, 16);
memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
}
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
static void MD5Transform(word32 buf[4], word32 in[16])
{
register word32 a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
/*-----------------------------------------------------------------------------
FITS-related functions
-----------------------------------------------------------------------------*/
/* Pretty-print a FITS string value */
static char * fits_pretty_string(char * s)
{
static char pretty[FITSLINESZ+1] ;
int i,j ;
if (s==NULL) return NULL ;
pretty[0] = (char)0 ;
if (s[0]!='\'') return s ;
/* skip first quote */
i=1 ;
j=0 ;
/* trim left-side blanks */
while (s[i]==' ') {
if (i==(int)strlen(s)) break ;
i++ ;
}
if (i>=(int)(strlen(s)-1)) return pretty ;
/* copy string, changing double quotes to single ones */
while (i<(int)strlen(s)) {
if (s[i]=='\'') i++ ;
pretty[j]=s[i];
i++ ;
j++ ;
}
/* NULL-terminate the pretty string */
pretty[j+1]=(char)0;
/* trim right-side blanks */
j = (int)strlen(pretty)-1;
while (pretty[j]==' ') j-- ;
pretty[j+1]=(char)0;
return pretty;
}
/* Get the FITS value in a FITS card */
static char * fits_getvalue(char * line)
{
static char value[FITSLINESZ+1] ;
int from, to ;
int inq ;
int i ;
if (line==NULL) return NULL ;
memset(value, 0, FITSLINESZ+1);
/* Get past the keyword */
i=0 ;
while (line[i]!='=' && i<FITSLINESZ) i++ ;
if (i>FITSLINESZ) return NULL ;
i++ ;
while (line[i]==' ' && i<FITSLINESZ) i++ ;
if (i>FITSLINESZ) return NULL ;
from=i;
/* Now in the value section */
/* Look for the first slash '/' outside of a string */
inq = 0 ;
while (i<FITSLINESZ) {
if (line[i]=='\'') inq=!inq ;
if (line[i]=='/') if (!inq) break ;
i++;
}
i-- ;
/* Backtrack on blanks */
while (line[i]==' ' && i>=0) i-- ;
if (i<0) return NULL ;
to=i ;
if (to<from) return NULL ;
/* Copy relevant characters into output buffer */
strncpy(value, line+from, to-from+1);
/* Null-terminate the string */
value[to-from+1] = (char)0;
/*
* Make it pretty: remove head and tail quote, change double
* quotes to simple ones.
*/
strcpy(value, fits_pretty_string(value));
return value ;
}
/* Replace the MD5 card in the input header */
static int fits_replace_card(char * filename, int off_md5, char * datamd5)
{
char * buf ;
int fd ;
struct stat sta ;
char card[FITSLINESZ];
int i ;
int err ;
/* Get file size */
if (stat(filename, &sta)==-1) {
fprintf(stderr, "%s: cannot stat file [%s]: no update done\n",
pname,
filename);
return 1 ;
}
/* Open file */
fd = open(filename, O_RDWR);
if (fd==-1) {
fprintf(stderr,
"%s: cannot open file [%s] for modification: no update done\n",
pname,
filename);
return 1 ;
}
/* Memory-map the file */
buf = (char*)mmap(0,
sta.st_size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
0);
if (buf==(char*)-1 || buf==NULL) {
perror("mmap");
close(fd);
return 1 ;
}
/* sprintf should be safe, the MD5 signature size is 32 chars */
sprintf(card, "%s= '%s' / data MD5 signature", FITSMD5KEY, datamd5);
i=FITSLINESZ-1 ;
while (card[i]!='e') {
card[i]=' ';
i-- ;
}
/* Copy card into file */
memcpy(buf+off_md5, card, FITSLINESZ);
/* flush output, unmap buffer, close file and quit */
err=0 ;
sync();
if (close(fd)==-1) {
fprintf(stderr, "%s: error closing modified file [%s]",
pname,
filename);
err++ ;
}
if (munmap(buf, sta.st_size)==-1) {
perror("munmap");
err++ ;
}
return err;
}
/* Display or modify the DATAMD5 value. Returns the number of errors. */
static int fits_md5_check(char * filename, int update_header)
{
FILE * in ;
char buf[FITSBLOCKSZ];
char * buf_c ;
int i ;
int in_header ;
char * hdrmd5 ;
struct MD5Context ctx ;
unsigned char digest[16] ;
static char datamd5[MD5HASHSZ+1];
int off_md5 ;
int cur_off ;
int md5keysz ;
int err ;
int check_fits ;
struct stat sta ;
if (filename==NULL) return 1 ;
/* Try to stat file */
if (stat(filename, &sta)!=0) {
fprintf(stderr, "%s: cannot stat file %s\n", pname, filename);
return 1 ;
}
/* See if this is a regular file */
if (!S_ISREG(sta.st_mode)) {
fprintf(stderr, "%s: not a regular file: %s\n", pname, filename);
return 1 ;
}
/* Open input file */
if ((in=fopen(filename, "r"))==NULL) {
fprintf(stderr, "%s: cannot open file [%s]\n", pname, filename);
return 1 ;
}
/* Initialize all variables */
MD5Init(&ctx);
in_header=1 ;
hdrmd5=NULL ;
off_md5=0;
cur_off=0;
md5keysz = (int)strlen(FITSMD5KEY) ;
check_fits=0 ;
/* Loop over input file */
while (fread(buf, 1, FITSBLOCKSZ, in)==FITSBLOCKSZ) {
/* First time in the loop: check the file is FITS */
if (check_fits==0) {
/* Examine first characters in block */
if (buf[0]!='S' ||
buf[1]!='I' ||
buf[2]!='M' ||
buf[3]!='P' ||
buf[4]!='L' ||
buf[5]!='E' ||
buf[6]!=' ' ||
buf[7]!=' ' ||
buf[8]!='=') {
fprintf(stderr, "%s: file [%s] is not FITS\n",
pname,
filename);
fclose(in);
return 1 ;
} else {
check_fits=1 ;
}
}
/* If current block is a header block */
if (in_header) {
buf_c = buf ;
for (i=0 ; i<FITSCARDS ; i++) {
/* Try to locate MD5 keyword if not located already */
if (hdrmd5==NULL) {
if (!strncmp(buf_c, FITSMD5KEY, md5keysz)) {
hdrmd5 = fits_getvalue(buf_c) ;
off_md5 = cur_off ;
}
}
/* Try to locate an END key */
if (buf_c[0]=='E' &&
buf_c[1]=='N' &&
buf_c[2]=='D' &&
buf_c[3]==' ') {
in_header=0 ;
break ;
}
buf_c += FITSLINESZ ;
cur_off += FITSLINESZ ;
}
} else {
/* If current block is a data block */
/* Try to locate an extension header */
if (buf[0]=='X' &&
buf[1]=='T' &&
buf[2]=='E' &&
buf[3]=='N' &&
buf[4]=='S' &&
buf[5]=='I' &&
buf[6]=='O' &&
buf[7]=='N' &&
buf[8]=='=') {
in_header=1 ;
buf_c = buf ;
for (i=0 ; i<FITSCARDS ; i++) {
/* Try to find an END marker in this block */
if (buf_c[0]=='E' &&
buf_c[1]=='N' &&
buf_c[2]=='D' &&
buf_c[3]==' ') {
/* Found END marker in same block as XTENSION */
in_header=0 ;
break ;
}
buf_c += FITSLINESZ ;
}
} else {
/* Data block: accumulate for MD5 */
MD5Update(&ctx, (unsigned char *)buf, FITSBLOCKSZ);
}
}
}
fclose(in);
if (check_fits==0) {
/* Never went through the read loop: file is not FITS */
fprintf(stderr, "%s: file [%s] is not FITS\n",
pname,
filename);
return 1 ;
}
/* Got to the end of file: summarize */
MD5Final(digest, &ctx);
/* Write digest into a string */
sprintf(datamd5,
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
digest[ 0], digest[ 1], digest[ 2], digest[ 3], digest[ 4],
digest[ 5], digest[ 6], digest[ 7], digest[ 8], digest[ 9],
digest[10], digest[11], digest[12], digest[13], digest[14],
digest[15]);
if (!silent_process) {
printf("%s %s", datamd5, filename);
if (hdrmd5) {
if (!strcmp(hdrmd5, datamd5)) {
printf(" (header Ok)");
} else {
printf(" (header is wrong)");
}
}
printf("\n");
}
/* Update header if requested */
err=0 ;
if (update_header) {
if (hdrmd5==NULL) {
fprintf(stderr, "%s: cannot update header: missing %s\n",
pname,
FITSMD5KEY);
return 1 ;
}
#if HAVE_ZLIB
if (is_gzipped(filename)) {
fprintf(stderr, "%s: cannot update header in gzipped file\n");
return 1 ;
}
#endif
err = fits_replace_card(filename, off_md5, datamd5);
}
return err ;
}
/* Compute MD5 sum on the whole file and print out results on stdout */
static int compute_md5(char * filename)
{
struct MD5Context ctx ;
unsigned char digest[16] ;
struct stat sta ;
int fd ;
unsigned char * buf ;
/* Try to stat file */
if (stat(filename, &sta)!=0) {
fprintf(stderr, "%s: cannot stat file %s\n", pname, filename);
return 1 ;
}
/* See if this is a regular file */
if (!S_ISREG(sta.st_mode)) {
fprintf(stderr, "%s: not a regular file: %s\n", pname, filename);
return 1 ;
}
/* Open file */
if ((fd = open(filename, O_RDONLY))==-1) {
fprintf(stderr, "%s: cannot open file %s\n", pname, filename);
return 1 ;
}
/* Memory-map the file */
buf = (unsigned char*)mmap(0, sta.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (buf==(unsigned char*)-1 || buf==NULL) {
perror("mmap");
close(fd);
return 1 ;
}
/* Initialize MD5 context */
MD5Init(&ctx);
/* Compute MD5 on all bits in the file */
MD5Update(&ctx, buf, sta.st_size);
/* Finalize and print results */
close(fd);
munmap((char*)buf, sta.st_size);
MD5Final(digest, &ctx);
printf(
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x %s\n",
digest[ 0], digest[ 1], digest[ 2], digest[ 3], digest[ 4],
digest[ 5], digest[ 6], digest[ 7], digest[ 8], digest[ 9],
digest[10], digest[11], digest[12], digest[13], digest[14],
digest[15],
filename);
return 0 ;
}
static void usage(void)
{
printf(
"%s -- %s\n"
"version: $Revision: 1.5 $\n",
pname,
prog_desc);
printf(
"\n"
"use : %s [-u] [-s] [-a] <FITS files...>\n"
"options are:\n"
"\t-u update MD5 keyword in the file: %s\n"
"\t-s silent mode\n"
"\n"
"\t-a compute MD5 sum of the complete file (incl.header)\n"
"\n"
"This utility computes the MD5 checksum of all data sections\n"
"in a given FITS file, and compares it against the value\n"
"declared in DATAMD5 if present. It can also update the value\n"
"of this keyword (if present) with its own computed MD5 sum.\n"
"\n", pname, FITSMD5KEY) ;
printf(
"You can also use it with the -a option to compute the MD5 sum\n"
"on the complete file (all bits). In this case, the file needs\n"
"not be FITS. This option is only provided to check this program\n"
"against other MD5 computation tools.\n"
"NB: Other options cannot be used together with -a.\n"
"\n");
#if HAVE_ZLIB
printf(
"\n"
"This program was compiled against zlib %s\n"
"which allows to process gzipped FITS files\n"
"as if they were normal FITS files.\n"
"Notice that you cannot use the -u option on\n"
"gzipped files, though.\n"
"\n"
"\n",
ZLIB_VERSION
);
#endif
exit(0) ;
}
/*-----------------------------------------------------------------------------
Main
-----------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
int i ;
int update_header ;
int total_md5 ;
int err ;
/* Initialize */
pname=argv[0];
update_header = 0 ;
total_md5 = 0 ;
if (argc<2) usage();
/* Parse arguments for options */
for (i=1 ; i<argc ; i++) {
if (!strcmp(argv[i], "-u")) {
update_header=1 ;
} else if (!strcmp(argv[i], "-s")) {
silent_process=1;
} else if (!strcmp(argv[i], "-a")) {
total_md5=1 ;
}
}
/* Loop on input file names */
err=0 ;
for (i=1 ; i<argc ; i++) {
/* If not a command-line option */
if (strcmp(argv[i], "-u") &&
strcmp(argv[i], "-s") &&
strcmp(argv[i], "-a")) {
/* Launch MD5 process on this file */
if (total_md5) {
err+=compute_md5(argv[i]);
} else {
err += fits_md5_check(argv[i], update_header);
}
}
}
if (err>0) {
fprintf(stderr, "%s: %d error(s) during process\n", pname, err);
}
return err ;
}

View File

@ -0,0 +1,373 @@
/*----------------------------------------------------------------------------*/
/**
@file fitsort.c
@author Nicolas Devillard
@date May 1st, 1996
@version $Revision: 1.4 $
@brief Sorts out FITS keywords
The input is a succession of FITS headers delivered through stdin by
'dfits'. On the command line, specify which keywords you wish to display, the
output contains for each file, the file name and the keyword values in
column format. Example:
dfits *.fits | fitsort BITPIX NAXIS NAXIS1 NAXIS2 NAXIS3
The output would be like:
File BITPIX NAXIS NAXIS1 NAXIS2 NAXIS3
image1.fits 32 2 256 256
image2.fits -32 3 128 128 40
Using 'fitsort -d ...' would prevent printing the first line (filename and
keyword names).
The output format is simple: values are separated by tabs, records by
linefeeds. When no value is present (no keyword in this header), only a tab
is printed out. Example:
file1.fits contains NAXIS1=100 NAXIS2=200
file2.fits contains NAXIS1=20
dfits file1.fits file2.fits | fitsort NAXIS2 NAXIS1
would litterally print out (\t stands for tab, \n for linefeed):
file1.fits\t200\t100\n
file2.fits\t\t20\n
*/
/*----------------------------------------------------------------------------*/
/*
$Id: fitsort.c,v 1.4 2005/07/04 14:21:31 yjung Exp $
$Author: yjung $
$Date: 2005/07/04 14:21:31 $
$Revision: 1.4 $
*/
/*-----------------------------------------------------------------------------
Include
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/*-----------------------------------------------------------------------------
Define
-----------------------------------------------------------------------------*/
#define MAX_STRING 128
#define MAX_KEY 512
#define FMT_STRING "%%-%ds\t"
/*-----------------------------------------------------------------------------
New types
-----------------------------------------------------------------------------*/
/* This holds a keyword value and a flag to indicate its presence */
typedef struct _KEYWORD_ {
char value[MAX_STRING] ;
int present ;
} keyword ;
/* Each detected file in input has such an associated structure */
typedef struct _RECORD_ {
char filename[MAX_STRING] ;
keyword listkw[MAX_KEY] ;
} record ;
/*-----------------------------------------------------------------------------
Function prototypes
-----------------------------------------------------------------------------*/
static int isfilename(char *string) ;
static void getfilename(char *line, char *word) ;
static char * expand_hierarch_keyword(char *, char *) ;
static int isdetectedkeyword(char *line, char *keywords[], int nkeys) ;
static void getkeywordvalue(char *line, char *word) ;
/*-----------------------------------------------------------------------------
Main
-----------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
char curline[MAX_STRING] ;
char word[MAX_STRING] ;
int i, j ;
int nfiles ;
record *allrecords ;
int kwnum ;
int len ;
int max_width[MAX_KEY] ;
int max_filnam ;
char fmt[8] ;
int flag ;
int printnames ;
int print_hdr ;
if (argc<2) {
printf("\n\nuse : %s [-d] KEY1 KEY2 ... KEYn\n", argv[0]) ;
printf("Input data is received from stdin\n") ;
printf("See man page for more details and examples\n\n") ;
return 0 ;
}
/* Initialize */
printnames = 0 ;
print_hdr = 1 ;
nfiles = 0 ;
allrecords = (record*)calloc(1, sizeof(record));
if (!strcmp(argv[1], "-d")) {
print_hdr = 0;
argv++ ;
argc-- ;
}
argv++ ;
/* Uppercase all inputs */
for (i=0 ; i<(argc-1) ; i++) {
j=0 ;
while (argv[i][j]!=0) {
argv[i][j] = toupper(argv[i][j]);
j++ ;
}
}
while (fgets(curline, MAX_STRING, stdin) != (char*)NULL) {
flag=isfilename(curline) ;
if (flag == 1) {
/* New file name is detected, get the new file name */
printnames = 1 ;
getfilename(curline, allrecords[nfiles].filename) ;
nfiles++ ;
/* Initialize a new record structure to store data for this file. */
allrecords = (record*)realloc(allrecords,(nfiles+1)*sizeof(record));
for (i=0 ; i<MAX_KEY ; i++) allrecords[nfiles].listkw[i].present=0;
} else if (flag==0) {
/* Is not a file name, is it a searched keyword? */
if ((kwnum = isdetectedkeyword( curline, argv, argc-1)) != -1) {
/* Is there anything allocated yet to store this? */
if (nfiles>0) {
/* It has been detected as a searched keyword. */
/* Get its value, store it, present flag up */
getkeywordvalue(curline, word) ;
strcpy(allrecords[nfiles-1].listkw[kwnum].value, word) ;
allrecords[nfiles-1].listkw[kwnum].present ++ ;
}
}
}
}
for (i=0 ; i<argc-1 ; i++) max_width[i] = (int)strlen(argv[i]) ;
/* Record the maximum width for each column */
max_filnam = 0 ;
for (i=0 ; i<nfiles ; i++) {
len = (int)strlen(allrecords[i].filename) ;
if (len>max_filnam) max_filnam=len ;
for (kwnum=0 ; kwnum<argc-1 ; kwnum++) {
if (allrecords[i].listkw[kwnum].present) {
len = (int)strlen(allrecords[i].listkw[kwnum].value) ;
} else {
len = 0 ;
}
if (len>max_width[kwnum]) max_width[kwnum] = len ;
}
}
/* Print out header line */
if (print_hdr) {
sprintf(fmt, FMT_STRING, max_filnam) ;
if (printnames) printf(fmt, "FILE");
for (i=0 ; i<argc-1 ; i++) {
sprintf(fmt, FMT_STRING, max_width[i]) ;
printf(fmt, argv[i]) ;
}
printf("\n") ;
}
/* Now print out stored data */
if (nfiles<1) {
printf("*** error: no input data corresponding to dfits output\n");
return -1 ;
}
for (i=0 ; i<nfiles ; i++) {
if (printnames) {
sprintf(fmt, FMT_STRING, max_filnam) ;
printf(fmt, allrecords[i].filename) ;
}
for (kwnum=0 ; kwnum<argc-1 ; kwnum++) {
sprintf(fmt, FMT_STRING, max_width[kwnum]);
if (allrecords[i].listkw[kwnum].present)
printf(fmt, allrecords[i].listkw[kwnum].value) ;
else printf(fmt, " ");
}
printf("\n") ;
}
free(allrecords) ;
return 0 ;
}
/*-----------------------------------------------------------------------------
Functions code
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief find out if an input line contains a file name or a FITS magic nb.
@param string dfits output line
@return int (see below)
Filename recognition is based on 'dfits' output. The function returns 1 if
the line contains a valid file name as produced by dfits, 2 if it is for an
extension, 0 otherwise.
*/
/*----------------------------------------------------------------------------*/
static int isfilename(char * string)
{
if (!strncmp(string, "====>", 5)) return 1 ;
if (!strncmp(string, "===>", 4)) return 2 ;
return 0 ;
}
/*----------------------------------------------------------------------------*/
/**
@brief returns a file name from a dfits output line
@param line dfits output line
@param word file name
@return a file name from a dfits output line
This is dfits dependent.
*/
/*----------------------------------------------------------------------------*/
static void getfilename(char * line, char * word)
{
/* get filename from a dfits output */
sscanf(line, "%*s %*s %s", word) ;
return ;
}
/*----------------------------------------------------------------------------*/
/**
@brief detects a if a keyword is present in a FITS line
@param line FITS line
@param keywords set of keywords
@param nkeys number of kw in the set
@return keyword rank, -1 if unidentified
Feed this function a FITS line, a set of keywords in the *argv[] fashion
(*keywords[]). If the provided line appears to contain one of the keywords
registered in the list, the rank of the keyword in the list is returned,
otherwise, -1 is returned.
*/
/*----------------------------------------------------------------------------*/
static int isdetectedkeyword(
char * line,
char * keywords[],
int nkeys)
{
char kw[MAX_STRING] ;
char esokw[MAX_STRING] ;
int i ;
/* The keyword is up to the equal character, with trailing blanks removed */
strcpy(kw, line) ;
strtok(kw, "=") ;
/* Now remove all trailing blanks (if any) */
i = (int)strlen(kw) -1 ;
while (kw[i] == ' ') i -- ;
kw[i+1] = (char)0 ;
/* Now compare what we got with what's available */
for (i=0 ; i<nkeys ; i++) {
if (strstr(keywords[i], ".")!=NULL) {
/*
* keyword contains a dot, it is a hierarchical keyword that
* must be expanded. Pattern is:
* A.B.C... becomes HIERARCH ESO A B C ...
*/
expand_hierarch_keyword(keywords[i], esokw) ;
if (!strcmp(kw, esokw)) {
return i ;
}
} else if (!strcmp(kw, keywords[i])) {
return i ;
}
}
/* Keyword not found */
return -1 ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Expand a HIERARCH keyword in format A.B.C to HIERARCH ESO A B C
@param dotkey Keyword
@param hierarchy HIERARCH
@return char *, pointer to second input string (modified)
*/
/*----------------------------------------------------------------------------*/
static char * expand_hierarch_keyword(
char * dotkey,
char * hierarchy)
{
char * token ;
char ws[MAX_STRING] ;
sprintf(hierarchy, "HIERARCH ESO");
strcpy(ws, dotkey) ;
token = strtok(ws, ".") ;
while (token!=NULL) {
strcat(hierarchy, " ") ;
strcat(hierarchy, token) ;
token = strtok(NULL, ".");
}
return hierarchy ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Get a keyword value within a FITS line
@param line FITS line to process
@param word char string to return result
@return void, result returned in word
No complex value is recognized
*/
/*----------------------------------------------------------------------------*/
static void getkeywordvalue(
char * line,
char * word)
{
int c, w ;
char tmp[MAX_STRING] ;
char *begin, *end ;
int length ;
int quote = 0 ;
int search = 1 ;
memset(tmp, (char)0, MAX_STRING) ;
memset(word, (char)0, MAX_STRING) ;
c = w = 0;
/* Parse the line till the equal '=' sign is found */
while (line[c] != '=') c++ ;
c++ ;
/* Copy the line till the slash '/' sign or the end of data is found. */
while (search == 1) {
if (c>=80) search = 0 ;
else if ((line[c] == '/') && (quote == 0)) search = 0 ;
if (line[c] == '\'') quote = !quote ;
tmp[w++] = line[c++] ;
}
/* NULL termination of the string */
tmp[--w] = (char)0 ;
/* Return the keyword only : a diff is made between text fields and nbs. */
if ((begin = strchr(tmp, '\'')) != (char*)NULL) {
/* A quote has been found: it is a string value */
begin++ ;
end = strrchr(tmp, '\'') ;
length = (int)strlen(begin) - (int)strlen(end) ;
strncpy(word, begin, length) ;
} else {
/* No quote, just get the value (only one, no complex supported) */
sscanf(tmp, "%s", word) ;
}
return ;
}

View File

@ -0,0 +1,603 @@
/*----------------------------------------------------------------------------*/
/**
@file hierarch28.c
@author N. Devillard
@date July 14th, 1998
@version $Revision: 1.6 $
@brief header conversion from ESO-FITS to standard FITS
*/
/*----------------------------------------------------------------------------*/
/*
$Id: hierarch28.c,v 1.6 2005/06/29 15:14:50 yjung Exp $
$Author: yjung $
$Date: 2005/06/29 15:14:50 $
$Revision: 1.6 $
*/
/*-----------------------------------------------------------------------------
Include
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <string.h>
#include <ctype.h>
/*-----------------------------------------------------------------------------
Define
-----------------------------------------------------------------------------*/
#define NM_SIZ 512
#define FITS_LINE 80
/*-----------------------------------------------------------------------------
Function prototypes
-----------------------------------------------------------------------------*/
static char prog_desc[] = "header conversion from ESO to standard FITS" ;
static void usage(char *) ;
static int convert_eso_to_std_FITS(char *, char *) ;
static void free_keys(char **, int n) ;
static void strip_beg_end(char *) ;
static int search_and_replace_kw(char *, int, char **, char **, int) ;
static void search_rep(char *, char *, char *);
static void generate_default_convtab(void);
static char * convert_deg_to_str(double deg) ;
/*-----------------------------------------------------------------------------
Static variables
-----------------------------------------------------------------------------*/
static char CONVTAB_DEFAULT1[] =
"#\n"
"# Example of conversion table for hierarch28\n"
"#\n"
"# A note about this file's format:\n"
"# Any blank line or line starting with a hash is ignored.\n"
"# Declare the keyword names to search and replace with:\n"
"#\n"
"# OLDKEYWORD = NEWKEYWORD\n"
"#\n"
"# Spaces are allowed within keyword names, to allow e.g.:\n"
"#\n"
"# HIERARCH ESO DET NDIT = DET NDIT\n"
"#\n"
"# The most important restriction is that new keywords shall not be\n"
"# longer than the keywords they replace.\n"
"#\n" ;
static char CONVTAB_DEFAULT2[] =
"#\n"
"# Translation table for basic keywords used by IRAF\n"
"# -------------------------------------------------\n"
"#\n"
"# Note: hierarch28 will replace keywords in the main header\n"
"# and also in extensions.\n"
"#\n"
"# Disclaimer:\n"
"# this table has been compiled to best knowledge of present\n"
"# IRAF packages. Please let us know of any addition/change.\n"
"#\n"
"\n" ;
static char CONVTAB_DEFAULT3[] =
"UTC = UT\n"
"LST = ST\n"
"RA = RA\n"
"DEC = DEC\n"
"\n"
"HIERARCH ESO TEL AIRM START = AIRMASS\n"
"HIERARCH ESO DPR TYPE = IMAGETYP\n"
"HIERARCH ESO INS FILT1 NAME = FILTER1\n"
"HIERARCH ESO INS SLIT2 NAME = SLIT\n"
"HIERARCH ESO INS GRIS1 NAME = GRISM\n"
"HIERARCH ESO INS GRAT NAME = GRAT\n"
"HIERARCH ESO INS GRAT1 NAME = GRAT1\n"
"HIERARCH ESO INS GRAT2 NAME = GRAT2\n"
"HIERARCH ESO INS GRAT WLEN = WLEN\n"
"HIERARCH ESO INS GRAT1 WLEN = WLEN1\n"
"HIERARCH ESO INS GRAT2 WLEN = WLEN2\n"
"HIERARCH ESO INS GRAT ORDER = ORDER\n"
"\n" ;
static char CONVTAB_DEFAULT4[] =
"#\n"
"# A note for IRAF users:\n"
"# Be aware also that the ESO convention names the keywords UTC and\n"
"# LST, whereas the IRAF convention is 'UT' and 'ST'.\n"
"#\n"
"# The ESO standard (see http://archive.eso.org/dicb) defines these\n"
"# keywords as floating point values with the units degrees for RA/DEC\n"
"# and elapsed seconds since midnight for UT/ST.\n"
"#\n"
"# In order to have this tranlation performed, add\n"
"# RA = RA\n"
"# DEC = DEC\n"
"# UTC = UT\n"
"# LST = ST\n"
"# to the conversion table.\n"
"#\n";
/*-----------------------------------------------------------------------------
Main
-----------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
char name_conv[NM_SIZ] ;
char name_in[NM_SIZ] ;
if (argc<2) usage(argv[0]) ;
if (!strcmp(argv[1], "-g")) {
generate_default_convtab() ;
return 0 ;
}
strcpy(name_in, argv[1]) ;
if (argc==3) {
strcpy(name_conv, argv[2]) ;
} else {
strcpy(name_conv, "table.conv") ;
}
if (convert_eso_to_std_FITS(name_in, name_conv) != 0) {
fprintf(stderr, "error during conversion: aborting\n") ;
}
return 0 ;
}
static void usage(char * pname)
{
printf(
"\n\n"
"hierarch28 (hierarch-to-eight)\n"
"%s : %s\n"
"use : %s [options] <in> [table]\n"
"options are:\n"
"\t-g generates a generic table\n"
"\n"
"default conversion table name is 'table.conv'\n"
"\n"
"More help can be found in the comments included in the default\n"
"conversion table. Generate one with the -g option and read it.\n"
"\n\n",
pname, prog_desc, pname);
exit(0) ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Search and replace FITS keywords in main/extension headers.
@param name_in File to modify.
@param name_conv Conversion table name.
@return int 0 if Ok, non-zero if error occurred.
The input file is modified in place. Keyword names are replaced
according to the input conversion table. In some special cases, the
keyword values are also modified to follow the IRAF convention.
*/
/*----------------------------------------------------------------------------*/
static int convert_eso_to_std_FITS(char * name_in, char * name_conv)
{
FILE * convtab ;
int nkeys ;
int i ;
char ** key_in ;
char ** key_out ;
int fd ;
char * buf ;
char line[NM_SIZ] ;
char kw1[FITS_LINE],
kw2[FITS_LINE] ;
int lineno ;
int fs ;
struct stat fileinfo ;
/* Read conversion table and translate it to key_in, key_out */
if ((convtab = fopen(name_conv, "r")) == NULL) {
fprintf(stderr, "cannot open conversion table: %s\n", name_conv) ;
return -1 ;
}
/* First, count how many keywords we need to translate */
nkeys = 0 ;
while (fgets(line, FITS_LINE, convtab)!=NULL) {
if ((line[0] != '#') && (line[0] != '\n')) {
nkeys ++ ;
}
}
rewind(convtab) ;
/* Allocate space to store keyword info */
key_in = malloc(nkeys * sizeof(char*)) ;
key_out = malloc(nkeys * sizeof(char*)) ;
/* Now read the file through and get the keywords */
i = 0 ;
lineno = 0 ;
while (fgets(line, FITS_LINE, convtab)!=NULL) {
lineno++ ;
if ((line[0]!='#') && (line[0]!='\n')) {
if (sscanf(line, "%[^=] = %[^;#]", kw1, kw2)!=2) {
fprintf(stderr,
"*** error parsing table file %s\n", name_conv);
fprintf(stderr, "line: %d\n", lineno) ;
free_keys(key_in, i) ;
free_keys(key_out, i) ;
fclose(convtab) ;
return -1 ;
}
strip_beg_end(kw1) ;
strip_beg_end(kw2) ;
if (strlen(kw2)>strlen(kw1)) {
fprintf(stderr,
"*** error in conversion table %s (line %d)\n",
name_conv, lineno);
fprintf(stderr,
"*** error: dest keyword is longer than original\n");
fprintf(stderr, "orig: [%s] dest: [%s]\n", kw1, kw2);
fclose(convtab) ;
free_keys(key_in, i) ;
free_keys(key_out, i) ;
return -1 ;
}
key_in[i] = strdup(kw1) ;
key_out[i] = strdup(kw2) ;
i++ ;
}
}
fclose(convtab) ;
/* Print out some information about what is being done */
printf("\n\n") ;
printf("*** hierarch28\n") ;
printf("\n") ;
printf("searching %s and replacing the following keywords:\n", name_in) ;
for (i=0 ; i<nkeys ; i++) {
printf("\t[%s]\t=>\t[%s]\n", key_in[i], key_out[i]) ;
}
printf("\n\n") ;
/* mmap the input file entirely */
if (stat(name_in, &fileinfo)!=0) {
fprintf(stderr, "*** error: accessing file [%s]\n", name_in);
free_keys(key_in, nkeys) ;
free_keys(key_out, nkeys) ;
return -1 ;
}
fs = (int)fileinfo.st_size ;
if (fs < 1) {
fprintf(stderr, "error getting FITS header size for %s\n", name_in);
free_keys(key_in, nkeys) ;
free_keys(key_out, nkeys) ;
return -1 ;
}
fd = open(name_in, O_RDWR) ;
if (fd == -1) {
fprintf(stderr, "cannot open %s: aborting\n", name_in) ;
free_keys(key_in, nkeys) ;
free_keys(key_out, nkeys) ;
return -1 ;
}
buf = (char*)mmap(0,
fs,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
0) ;
if (buf == (char*)-1) {
perror("mmap") ;
fprintf(stderr, "cannot mmap file: %s\n", name_in) ;
free_keys(key_in, nkeys) ;
free_keys(key_out, nkeys) ;
close(fd) ;
return -1 ;
}
/* Apply search and replace for the input keyword lists */
if (search_and_replace_kw(buf, fs, key_in, key_out, nkeys) != 0) {
fprintf(stderr, "error while doing search and replace\n") ;
}
free_keys(key_in, nkeys) ;
free_keys(key_out, nkeys) ;
close(fd) ;
munmap(buf, fs) ;
return 0 ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Strips out blank characters off a character string.
@param s NULL-terminated string to process.
@return void
This function removes heading and trailing blanks from a
NULL-terminated character string. The input string is modified. The
input string is assumed to contain only blanks or alphanumeric
characters (like FITS keywords).
*/
/*----------------------------------------------------------------------------*/
static void strip_beg_end(char * s)
{
int beg, len ;
beg = 0 ;
while (!isalnum((unsigned char)(s[beg]))) beg++ ;
len = (int)strlen(s) -1 ;
while (!isalnum((unsigned char)(s[len]))) len -- ;
strncpy(s, s+beg, len-beg+1) ;
s[len-beg+1] = (char)0 ;
return ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Free memory associated to an array of keys.
@param keyt Key table.
@param n Number of keys in the table.
@return void
Memory was initially allocated using strdup(). This frees all the
keys and the master table pointer.
*/
/*----------------------------------------------------------------------------*/
static void free_keys(char ** keyt, int n)
{
int i ;
if (n<1) return ;
for (i=0 ; i<n ; i++) free(keyt[i]) ;
free(keyt) ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Search keywords and replace them over a whole buffer.
@param buf Buffer to modify.
@param bufsize Buffer size in bytes.
@param key_in Input key table.
@param key_out Output key table.
@param nk Number of keys in each table (same).
@return int 0 if Ok, non-zero if error occurred.
Main replace function: it browses through the entire file to support
keyword changes in extensions too. Heavily optimized for speed.
*/
/*----------------------------------------------------------------------------*/
static int search_and_replace_kw(
char * buf,
int bufsize,
char ** key_in,
char ** key_out,
int nk)
{
char * w ;
int i, j ;
int in_header ;
int match_flag ;
int * keysizes ;
/* Pre-compute key sizes to gain time */
keysizes = malloc(nk * sizeof(int));
for (i=0 ; i<nk ; i++) keysizes[i] = (int)strlen(key_in[i]);
/* Browse through file line by line */
w = buf ;
in_header=1 ;
while ((w-buf+FITS_LINE)<bufsize) {
if (in_header) { /* Currently browsing a header */
if (w[0]=='E' &&
w[1]=='N' &&
w[2]=='D' &&
w[3]==' ') {
/* Found an END keyword: exit from header */
in_header=0 ;
} else {
/* Compare the current line with all searched keys */
for (i=0 ; i<nk ; i++) {
match_flag=1 ;
for (j=0 ; j<=keysizes[i] ; j++) {
if (j<keysizes[i]) {
if (key_in[i][j]!=w[j]) {
match_flag=0 ;
break ;
}
} else {
if ((w[j] != '=') && (w[j] != ' ')) {
match_flag=0 ;
break ;
}
}
}
if (match_flag) {
search_rep(w, key_in[i], key_out[i]);
}
}
}
} else {
/* Currently out of header, look for next extension */
if (w[0]=='X' &&
w[1]=='T' &&
w[2]=='E' &&
w[3]=='N' &&
w[4]=='S' &&
w[5]=='I' &&
w[6]=='O' &&
w[7]=='N') {
/* Found a header start */
in_header=1 ;
}
}
w+=FITS_LINE ;
}
free(keysizes);
return 0 ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Atomic keyword replacement.
@param line Line to work on.
@param key_i Input key.
@param key_o Output key.
@return void
Replace in 'line' the keyword name 'key_i' by 'key_o'. In some
special cases, the value is also modified to reflect the IRAF
conventions.
*/
/*----------------------------------------------------------------------------*/
static void search_rep(char * line, char * key_i, char * key_o)
{
int i, j ;
char * equal ;
int to_copy ;
char * p ;
char tmp[FITS_LINE+1];
char comment[FITS_LINE+1];
equal = strstr(line, "=");
to_copy = FITS_LINE - (equal-line);
for (i=0 ; i<(int)strlen(key_o) ; i++) {
line[i] = key_o[i] ;
}
if (strlen(key_o)<=8) {
/* Blank-pad until equal sign is reached */
for ( ; i<8 ; i++) {
line[i]=' ';
}
/* Add equal sign */
line[i] = '=' ;
i++ ;
/* Handle special cases: the value also needs conversion */
if(!strcmp(key_o, "RA")) {
if (*(equal+2)!='\'') {
/* out key is RA, translate to ' HH:MM:SS.SSS' */
p = strchr(line+i, '/');
if (p)
strncpy(comment, p, line+FITS_LINE-p);
sprintf(tmp, " %-29.29s %-40.40s",
convert_deg_to_str(atof(equal+1)/15.),
(p)? comment : "/ Right Ascension");
memcpy(line+i, tmp, 71);
}
} else if(!strcmp(key_o, "DEC")) {
if( *(equal+2)!='\'') {
/* out key is DEC, translate to '+DD:MM:SS.SSS' */
p = strchr(line+i, '/');
if (p)
strncpy(comment, p, line+FITS_LINE-p);
sprintf(tmp, " %-29.29s %-40.40s",
convert_deg_to_str(atof(equal+1)),
(p)? comment : "/ Declination");
memcpy(line+i, tmp, 71);
}
} else if(!strcmp(key_o, "UT")) {
if( *(equal+2)!='\'') {
/* out key is UT, translate to ' HH:MM:SS.SSS' */
p = strchr(line+i, '/');
if (p)
strncpy(comment, p, line+FITS_LINE-p);
sprintf(tmp, " %-29.29s %-40.40s",
convert_deg_to_str(atof(equal+1)/3600.),
(p)? comment : "/ UT");
memcpy(line+i, tmp, 71);
}
} else if(!strcmp(key_o, "ST")) {
if( *(equal+2)!='\'') {
/* out key is ST, translate to ' HH:MM:SS.SSS' */
p = strchr(line+i, '/');
if (p)
strncpy(comment, p, line+FITS_LINE-p);
sprintf(tmp, " %-29.29s %-40.40s",
convert_deg_to_str(atof(equal+1)/3600.),
(p)? comment : "/ ST");
memcpy(line+i, tmp, 71);
}
} else {
/* Copy line from first char after real equal sign */
for (j=0 ; j<to_copy ; j++) {
line[i+j] = equal[j+1];
}
i+=to_copy-1 ;
/* Blank padding */
for ( ; i<FITS_LINE ; i++) {
line[i]=' ';
}
}
} else {
/* Blank padding */
for (i=(int)strlen(key_o) ; i<(int)strlen(key_i) ; i++) {
line[i]=' ';
}
}
return ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Create a default conversion table.
@param ins Table name.
@return void
Creates a translation table for the requested instrument. If no
instrument is specified (ins==NULL) a default table is generated.
*/
/*----------------------------------------------------------------------------*/
static void generate_default_convtab(void)
{
FILE * convtab ;
if ((convtab = fopen("table.conv", "w")) == NULL) {
fprintf(stderr, "*** error: cannot create table.conv: aborting\n") ;
return ;
}
fprintf(convtab, CONVTAB_DEFAULT1);
fprintf(convtab, CONVTAB_DEFAULT2);
fprintf(convtab, CONVTAB_DEFAULT3);
fprintf(convtab, CONVTAB_DEFAULT4);
fclose(convtab) ;
return ;
}
/*----------------------------------------------------------------------------*/
/**
@brief Convert decimal degrees to ASCII representation.
@param d Double value, decimal degrees in [-90 ; +90].
@return Pointer to statically allocated character string.
Converts an angle value from degrees to ASCII representation
following the IRAF convention. Do not free or modify the returned
string.
*/
/*----------------------------------------------------------------------------*/
static char * convert_deg_to_str( double deg )
{
int d, m;
double s;
int sign;
static char buf[13];
sign = 1;
if(deg < 0.) sign = -1;
deg *= sign;
d = (int)deg;
m = (int)( (deg - d) * 60);
s = (deg - d) * 3600. - m * 60;
sprintf(buf, "'%c%02d:%02d:%06.3f'", (sign<0)? '-' : ' ', d, m, s);
return(buf);
}

1374
qfits/saft/iofits.c 100644

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,340 @@
/*----------------------------------------------------------------------------*/
/**
@file stripfits.c
@author N. Devillard
@date January 1999
@version $Revision: 1.2 $
@brief Dumps all the pixels from a FITS header into another file.
This is a stand-alone tool, compile it with:
gcc -o stripfits stripfits.c -O
This program dumps all the pixels from a FITS header into another file.
It has been written in less than 10 minutes (reusing most of the code
from iofits.c) to help the guys working on the ISAAC detector that day.
Since it is a good example of how to write a stand-alone FITS command, I
leave it here in the distribution.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: stripfits.c,v 1.2 2002/11/21 14:18:18 yjung Exp $
$Author: yjung $
$Date: 2002/11/21 14:18:18 $
$Revision: 1.2 $
*/
/*-----------------------------------------------------------------------------
Include
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <string.h>
#include <ctype.h>
/*-----------------------------------------------------------------------------
Define
-----------------------------------------------------------------------------*/
#define NM_SIZ 512
#define FITS_BLSZ 2880
#define ONE_MEGABYTE (1024 * 1024)
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
/*-----------------------------------------------------------------------------
Function prototypes
-----------------------------------------------------------------------------*/
static int dump_pix(char*, char*);
static int get_FITS_header_size(char *) ;
static int filesize(char*) ;
static int get_bitpix(char*) ;
static int get_npix(char*) ;
/*-----------------------------------------------------------------------------
Main
-----------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
if (argc<3) {
printf("\n\n") ;
printf("use: %s <in> <out>\n", argv[0]) ;
printf("\n") ;
printf("\t<in> is a valid FITS file in the current directory\n") ;
printf("\t<out> is the name of the output file\n") ;
printf("\n\n") ;
return 0 ;
}
if (!strcmp(argv[1], argv[2])) {
fprintf(stderr, "cannot convert a file to itself\n") ;
fprintf(stderr, "specify another name for the output\n") ;
return -1 ;
}
return dump_pix(argv[1], argv[2]);
}
/*----------------------------------------------------------------------------*/
/**
@brief dump pixels from a FITS file to a binary file
@param name_in Input file name
@param name_out Output file name
@return int 0 if Ok, anything else otherwise
Heavy use of mmap() to speed up the process
*/
/*----------------------------------------------------------------------------*/
static int dump_pix(
char * name_in,
char * name_out)
{
int fd_in,
fd_out ;
char * buf_in ;
char * buf_out ;
int fsize_in,
fsize_out,
header_size ;
int npix ;
/*
* Open input file and get information we need:
* - pixel depth
* - number of pixels
*/
fsize_in = filesize(name_in) ;
header_size = get_FITS_header_size(name_in) ;
if ((fd_in = open(name_in, O_RDONLY)) == -1) {
fprintf(stderr, "cannot open file %s: aborting\n", name_in) ;
return -1 ;
}
buf_in = (char*)mmap(0, fsize_in, PROT_READ, MAP_SHARED, fd_in, 0) ;
if (buf_in == (char*)-1) {
perror("mmap") ;
fprintf(stderr, "cannot mmap file: %s\n", name_in) ;
close(fd_in) ;
return -1 ;
}
if (get_bitpix(buf_in) != -32) {
fprintf(stderr, "only 32-bit IEEE floating point format supported\n");
close(fd_in) ; munmap(buf_in, fsize_in) ;
return -1 ;
}
/*
* Compute the size of the output file
* same header size, + pixel area + blank padding
*/
npix = get_npix(buf_in) ;
if (npix < 1) {
fprintf(stderr, "cannot compute number of pixels\n");
close(fd_in) ;
munmap(buf_in, fsize_in) ;
return -1 ;
}
fsize_out = npix * 4 ;
/*
* Now create the output file and fill it with zeros, then mmap it.
* The permissions are rw-rw-r-- by default.
*/
if ((fd_out=creat(name_out,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH))==-1){
perror("creat") ;
fprintf(stderr, "cannot create file %s: aborting\n", name_out) ;
close(fd_in) ; munmap(buf_in, fsize_in) ;
return -1 ;
}
buf_out = malloc(fsize_out) ;
if (buf_out == NULL) {
fprintf(stderr, "not enough memory\n");
fprintf(stderr, "failed to allocate %d bytes\n", fsize_out);
close(fd_in) ; munmap(buf_in, fsize_in) ;
return -1;
}
write(fd_out, buf_out, fsize_out);
close(fd_out);
free(buf_out);
fd_out = open(name_out, O_RDWR);
if (fd_out==-1) {
fprintf(stderr, "error opening file %s\n", name_out);
close(fd_in) ; munmap(buf_in, fsize_in) ;
return -1;
}
buf_out = (char*)mmap(0,
fsize_out,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd_out,
0) ;
if (buf_out == (char*)-1) {
perror("mmap") ;
fprintf(stderr, "cannot mmap file: %s\n", name_out) ;
munmap(buf_in, fsize_in) ; close(fd_in) ; close(fd_out) ;
return -1 ;
}
/*
* Copy FITS header from input to output, modify BITPIX
*/
memcpy(buf_out, buf_in+header_size, fsize_out) ;
/*
* Close, unmap, goodbye
*/
close(fd_in) ;
close(fd_out) ;
munmap(buf_in, fsize_in) ;
munmap(buf_out, fsize_out) ;
return 0 ;
}
/*----------------------------------------------------------------------------*/
/**
@brief compute the size (in bytes) of a FITS header
@param name FITS file name
@return unsigned long
Should always be a multiple of 2880. This implementation assumes only that
80 characters are found per line.
*/
/*----------------------------------------------------------------------------*/
static int get_FITS_header_size(char * name)
{
FILE * in ;
char line[81] ;
int found = 0 ;
int count ;
int hs ;
if ((in = fopen(name, "r")) == NULL) {
fprintf(stderr, "cannot open %s: aborting\n", name) ;
return 0 ;
}
count = 0 ;
while (!found) {
if (fread(line, 1, 80, in)!=80) {
break ;
}
count ++ ;
if (!strncmp(line, "END ", 4)) {
found = 1 ;
}
}
fclose(in);
if (!found) return 0 ;
/*
* The size is the number of found cards times 80,
* rounded to the closest higher multiple of 2880.
*/
hs = count * 80 ;
if ((hs % FITS_BLSZ) != 0) {
hs = (1+(hs/FITS_BLSZ)) * FITS_BLSZ ;
}
return hs ;
}
/*----------------------------------------------------------------------------*/
/**
@brief how many bytes can I read from this file
@param filename File name
@return size of the file in bytes
Strongly non portable. Only on Unix systems!
*/
/*----------------------------------------------------------------------------*/
static int filesize(char *filename)
{
int size ;
struct stat fileinfo ;
/* POSIX compliant */
if (stat(filename, &fileinfo) != 0) {
size = (int)0 ;
} else {
size = (int)fileinfo.st_size ;
}
return size ;
}
/*----------------------------------------------------------------------------*/
/**
@brief gets the value of BITPIX from a FITS header
@param buf allocated char buffer containing the whole FITS header
@return int 8 16 32 -32 or -64 or 0 if cannot find it
*/
/*----------------------------------------------------------------------------*/
static int get_bitpix(char * buf)
{
int bitpix ;
char * where ;
where = strstr(buf, "BITPIX") ;
if (where == NULL) {
fprintf(stderr, "cannot find BITPIX in header: aborting\n") ;
return 0 ;
}
sscanf(where, "%*[^=] = %d", &bitpix) ;
/*
* Check the returned value makes sense
*/
if ((bitpix != 8) &&
(bitpix != 16) &&
(bitpix != 32) &&
(bitpix != -32) &&
(bitpix != -64)) {
bitpix = 0 ;
}
return bitpix ;
}
/*----------------------------------------------------------------------------*/
/**
@brief retrieves how many pixels in a FITS file from the header
@param buf allocated char buffer containing the whole FITS header
@return unsigned long: # of pixels in the file
Does not support extensions!
*/
/*----------------------------------------------------------------------------*/
static int get_npix(char * buf)
{
int naxes ;
int npix ;
int naxis ;
char * where ;
char lookfor[80] ;
int i ;
where = strstr(buf, "NAXIS") ;
if (where == NULL) {
fprintf(stderr, "cannot find NAXIS in header: aborting\n") ;
return 0 ;
}
sscanf(where, "%*[^=] = %d", &naxes) ;
if ((naxes<1) || (naxes>999)) {
fprintf(stderr, "illegal value for %s: %d\n", lookfor, naxes) ;
return 0 ;
}
npix = 1 ;
for (i=1 ; i<=naxes ; i++) {
sprintf(lookfor, "NAXIS%d", i) ;
where = strstr(buf, lookfor) ;
if (where == NULL) {
fprintf(stderr, "cannot find %s in header: aborting\n",
lookfor) ;
return 0 ;
}
sscanf(where, "%*[^=] = %d", &naxis) ;
if (naxis<1) {
fprintf(stderr, "error: found %s=%d\n", lookfor, naxis);
return 0 ;
}
npix *= (int)naxis ;
}
return npix ;
}

122
qfits/src/cache.h 100644
View File

@ -0,0 +1,122 @@
/*----------------------------------------------------------------------------*/
/**
@file cache.h
@author N. Devillard
@date Mar 2001
@version $Revision: 1.5 $
@brief FITS caching capabilities
This modules implements a cache for FITS access routines.
The first time a FITS file is seen by the library, all corresponding
pointers are cached here. This speeds up multiple accesses to large
files by magnitudes.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: cache.h,v 1.5 2003/11/24 09:44:53 yjung Exp $
$Author: yjung $
$Date: 2003/11/24 09:44:53 $
$Revision: 1.5 $
*/
#ifndef CACHE_H
#define CACHE_H
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
/*-----------------------------------------------------------------------------
Defines
-----------------------------------------------------------------------------*/
/** Query the number of extensions */
#define QFITS_QUERY_N_EXT (1<<30)
/** Query the offset to header start */
#define QFITS_QUERY_HDR_START (1<<29)
/** Query the offset to data start */
#define QFITS_QUERY_DAT_START (1<<28)
/** Query header size in bytes */
#define QFITS_QUERY_HDR_SIZE (1<<27)
/** Query data size in bytes */
#define QFITS_QUERY_DAT_SIZE (1<<26)
/* <dox> */
/*----------------------------------------------------------------------------*/
/**
@brief Purge the qfits cache.
@return void
This function is useful for programs running for a long period,
to clean up the cache. Ideally in a daemon, it should be called
by a timer at regular intervals. Notice that since the cache is
fairly small, you should not need to care too much about this.
*/
/*----------------------------------------------------------------------------*/
void qfits_cache_purge(void);
/* </dox> */
/*----------------------------------------------------------------------------*/
/**
@brief Query a FITS file offset from the cache.
@param filename Name of the file to examine.
@param what What should be queried (see below).
@return an integer offset, or -1 if an error occurred.
This function queries the cache for FITS offset information. If the
requested file name has never been seen before, it is completely parsed
to extract all offset informations, which are then stored in the cache.
The next query will get the informations from the cache, avoiding
a complete re-parsing of the file. This is especially useful for large
FITS files with lots of extensions, because querying the extensions
is an expensive operation.
This operation has side-effects: the cache is an automatically
allocated structure in memory, that can only grow. Every request
on a new FITS file will make it grow. The structure is pretty
light-weight in memory, but nonetheless this is an issue for daemon-type
programs which must run over long periods. The solution is to clean
the cache using qfits_cache_purge() at regular intervals. This is left
to the user of this library.
To request information about a FITS file, you must pass an integer
built from the following symbols:
- @c QFITS_QUERY_N_EXT
- @c QFITS_QUERY_HDR_START
- @c QFITS_QUERY_DAT_START
- @c QFITS_QUERY_HDR_SIZE
- @c QFITS_QUERY_DAT_SIZE
Querying the number of extensions present in a file is done
simply with:
@code
next = qfits_query(filename, QFITS_QUERY_N_EXT);
@endcode
Querying the offset to the i-th extension header is done with:
@code
off = qfits_query(filename, QFITS_QUERY_HDR_START | i);
@endcode
i.e. you must OR (|) the extension number with the
@c QFITS_QUERY_HDR_START symbol. Requesting offsets to extension data is
done in the same way:
@code
off = qfits_query(filename, QFITS_QUERY_DAT_START | i);
@endcode
Notice that extension 0 is the main header and main data part
of the FITS file.
*/
/*----------------------------------------------------------------------------*/
int qfits_query(char * filename, int what);
#endif
/* vim: set ts=4 et sw=4 tw=75 */

20
qfits/src/config.h 100644
View File

@ -0,0 +1,20 @@
/* This file automatically generated */
#ifndef _CONFIG_H_
#define _CONFIG_H_
#define SIZEOF_CHAR 1
#define SIZEOF_SHORT 2
#define SIZEOF_INT 4
#define SIZEOF_LONG 8
#define SIZEOF_FLOAT 4
#define SIZEOF_DOUBLE 8
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif
#define OS_LINUX 1
#endif

53
qfits/src/expkey.h 100644
View File

@ -0,0 +1,53 @@
/*----------------------------------------------------------------------------*/
/**
@file expkey.h
@author N. Devillard
@date Feb 2001
@version $Revisions$
@brief Expand keyword from shortFITS to HIERARCH notation
This module offers a function that is reused in a number of different
places.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: expkey.h,v 1.6 2005/05/18 14:38:01 yjung Exp $
$Author: yjung $
$Date: 2005/05/18 14:38:01 $
$Revision: 1.6 $
*/
#ifndef EXPKEY_H
#define EXPKEY_H
/*-----------------------------------------------------------------------------
Function prototypes
-----------------------------------------------------------------------------*/
/* <dox> */
/*----------------------------------------------------------------------------*/
/**
@brief Expand a keyword from shortFITS to HIERARCH notation.
@param keyword Keyword to expand.
@return 1 pointer to statically allocated string.
This function expands a given keyword from shortFITS to HIERARCH
notation, bringing it to uppercase at the same time.
Examples:
@verbatim
det.dit expands to HIERARCH ESO DET DIT
ins.filt1.id expands to HIERARCH ESO INS FILT1 ID
@endverbatim
If the input keyword is a regular FITS keyword (i.e. it contains
not dots '.') the result is identical to the input.
*/
/*----------------------------------------------------------------------------*/
char * qfits_expand_keyword(const char * keyword);
/* </dox> */
#endif
/* vim: set ts=4 et sw=4 tw=75 */

475
qfits/src/fits_h.h 100644
View File

@ -0,0 +1,475 @@
/*----------------------------------------------------------------------------*/
/**
@file fits_h.h
@author N. Devillard
@date Mar 2000
@version $Revision: 1.13 $
@brief FITS header handling
This file contains definition and related methods for the FITS header
structure. This structure is meant to remain opaque to the user, who
only accesses it through the dedicated functions offered in this module.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: fits_h.h,v 1.13 2005/05/18 14:38:01 yjung Exp $
$Author: yjung $
$Date: 2005/05/18 14:38:01 $
$Revision: 1.13 $
*/
#ifndef FITS_HEADER_H
#define FITS_HEADER_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/*-----------------------------------------------------------------------------
New types
-----------------------------------------------------------------------------*/
/* <dox> */
/*----------------------------------------------------------------------------*/
/**
@brief FITS header object
This structure represents a FITS header in memory. It is actually no
more than a thin layer on top of the keytuple object. No field in this
structure should be directly modifiable by the user, only through
accessor functions.
*/
/*----------------------------------------------------------------------------*/
typedef struct qfits_header {
void * first ; /* Pointer to list start */
void * last ; /* Pointer to list end */
int n ; /* Number of cards in list */
} qfits_header ;
/*-----------------------------------------------------------------------------
Function ANSI prototypes
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief FITS header constructor
@return 1 newly allocated (empty) FITS header object.
This is the main constructor for a qfits_header object. It returns
an allocated linked-list handler with an empty card list.
*/
/*----------------------------------------------------------------------------*/
qfits_header * qfits_header_new(void) ;
/*----------------------------------------------------------------------------*/
/**
@brief FITS header default constructor.
@return 1 newly allocated qfits_header object.
This is a secondary constructor for a qfits_header object. It returns
an allocated linked-list handler containing two cards: the first one
(SIMPLE=T) and the last one (END).
*/
/*----------------------------------------------------------------------------*/
qfits_header * qfits_header_default(void) ;
/*----------------------------------------------------------------------------*/
/**
@brief Add a new card to a FITS header
@param hdr qfits_header object to modify
@param key FITS key
@param val FITS value
@param com FITS comment
@param lin FITS original line if exists
@return void
This function adds a new card into a header, at the one-before-last
position, i.e. the entry just before the END entry if it is there.
The key must always be a non-NULL string, all other input parameters
are allowed to get NULL values.
*/
/*----------------------------------------------------------------------------*/
void qfits_header_add(
qfits_header * hdr,
char * key,
char * val,
char * com,
char * lin) ;
/*----------------------------------------------------------------------------*/
/**
@brief add a new card to a FITS header
@param hdr qfits_header object to modify
@param after Key to specify insertion place
@param key FITS key
@param val FITS value
@param com FITS comment
@param lin FITS original line if exists
@return void
Adds a new card to a FITS header, after the specified key. Nothing
happens if the specified key is not found in the header. All fields
can be NULL, except after and key.
*/
/*----------------------------------------------------------------------------*/
void qfits_header_add_after(
qfits_header * hdr,
char * after,
char * key,
char * val,
char * com,
char * lin) ;
/*----------------------------------------------------------------------------*/
/**
@brief Append a new card to a FITS header.
@param hdr qfits_header object to modify
@param key FITS key
@param val FITS value
@param com FITS comment
@param lin FITS original line if exists
@return void
Adds a new card in a FITS header as the last one. All fields can be
NULL except key.
*/
/*----------------------------------------------------------------------------*/
void qfits_header_append(
qfits_header * hdr,
const char * key,
const char * val,
const char * com,
const char * lin) ;
/*----------------------------------------------------------------------------*/
/**
@brief Delete a card in a FITS header.
@param hdr qfits_header to modify
@param key specifies which card to remove
@return void
Removes a card from a FITS header. The first found card that matches
the key is removed.
*/
/*----------------------------------------------------------------------------*/
void qfits_header_del(qfits_header * hdr, char * key) ;
/*----------------------------------------------------------------------------*/
/**
@brief Modifies a FITS card.
@param hdr qfits_header to modify
@param key FITS key
@param val FITS value
@param com FITS comment
@return void
Finds the first card in the header matching 'key', and replaces its
value and comment fields by the provided values. The initial FITS
line is set to NULL in the card.
*/
/*----------------------------------------------------------------------------*/
void qfits_header_mod(qfits_header * hdr, char * key, char * val, char * com) ;
/*----------------------------------------------------------------------------*/
/**
@brief Sort a FITS header
@param hdr Header to sort (modified)
@return -1 in error case, 0 otherwise
*/
/*----------------------------------------------------------------------------*/
int qfits_header_sort(qfits_header ** hdr) ;
/*----------------------------------------------------------------------------*/
/**
@brief Copy a FITS header
@param src Header to replicate
@return Pointer to newly allocated qfits_header object.
Makes a strict copy of all information contained in the source
header. The returned header must be freed using qfits_header_destroy.
*/
/*----------------------------------------------------------------------------*/
qfits_header * qfits_header_copy(qfits_header * src) ;
/*----------------------------------------------------------------------------*/
/**
@brief Touch all cards in a FITS header
@param hdr qfits_header to modify
@return void
Touches all cards in a FITS header, i.e. all original FITS lines are
freed and set to NULL. Useful when a header needs to be reformatted.
*/
/*----------------------------------------------------------------------------*/
void qfits_header_touchall(qfits_header * hdr) ;
/*----------------------------------------------------------------------------*/
/**
@brief Dump a FITS header to stdout
@param hdr qfits_header to dump
@return void
Dump a FITS header to stdout. Mostly for debugging purposes.
*/
/*----------------------------------------------------------------------------*/
void qfits_header_consoledump(qfits_header * hdr) ;
/*----------------------------------------------------------------------------*/
/**
@brief qfits_header destructor
@param hdr qfits_header to deallocate
@return void
Frees all memory associated to a given qfits_header object.
*/
/*----------------------------------------------------------------------------*/
void qfits_header_destroy(qfits_header * hdr) ;
/*----------------------------------------------------------------------------*/
/**
@brief Return the value associated to a key, as a string
@param hdr qfits_header to parse
@param key key to find
@return pointer to statically allocated string
Finds the value associated to the given key and return it as a
string. The returned pointer is statically allocated, so do not
modify its contents or try to free it.
Returns NULL if no matching key is found or no value is attached.
*/
/*----------------------------------------------------------------------------*/
char * qfits_header_getstr(qfits_header * hdr, const char * key) ;
/*----------------------------------------------------------------------------*/
/**
@brief Find a matching key in a header.
@param hdr qfits_header to parse
@param key Key prefix to match
@return pointer to statically allocated string.
This function finds the first keyword in the given header for
which the given 'key' is a prefix, and returns the full name
of the matching key (NOT ITS VALUE). This is useful to locate
any keyword starting with a given prefix. Careful with HIERARCH
keywords, the shortFITS notation is not likely to be accepted here.
Examples:
@verbatim
s = qfits_header_findmatch(hdr, "SIMP") returns "SIMPLE"
s = qfits_header_findmatch(hdr, "HIERARCH ESO DET") returns
the first detector keyword among the HIERACH keys.
@endverbatim
*/
/*----------------------------------------------------------------------------*/
char * qfits_header_findmatch(qfits_header * hdr, char * key) ;
/*----------------------------------------------------------------------------*/
/**
@brief Return the i-th key/val/com/line tuple in a header.
@param hdr Header to consider
@param idx Index of the requested card
@param key Output key
@param val Output value
@param com Output comment
@param lin Output initial line
@return int 0 if Ok, -1 if error occurred.
This function is useful to browse a FITS header object card by card.
By iterating on the number of cards (available in the 'n' field of
the qfits_header struct), you can retrieve the FITS lines and their
components one by one. Indexes run from 0 to n-1. You can pass NULL
values for key, val, com or lin if you are not interested in a
given field.
@code
int i ;
char key[FITS_LINESZ+1] ;
char val[FITS_LINESZ+1] ;
char com[FITS_LINESZ+1] ;
char lin[FITS_LINESZ+1] ;
for (i=0 ; i<hdr->n ; i++) {
qfits_header_getitem(hdr, i, key, val, com, lin);
printf("card[%d] key[%s] val[%s] com[%s]\n", i, key, val, com);
}
@endcode
This function has primarily been written to interface a qfits_header
object to other languages (C++/Python). If you are working within a
C program, you should use the other header manipulation routines
available in this module.
*/
/*----------------------------------------------------------------------------*/
int qfits_header_getitem(
qfits_header * hdr,
int idx,
char * key,
char * val,
char * com,
char * lin) ;
/*----------------------------------------------------------------------------*/
/**
@brief Return the FITS line associated to a key, as a string
@param hdr qfits_header to parse
@param key key to find
@return pointer to statically allocated string
Finds the FITS line associated to the given key and return it as a
string. The returned pointer is statically allocated, so do not
modify its contents or try to free it.
Returns NULL if no matching key is found or no line is attached.
*/
/*----------------------------------------------------------------------------*/
char * qfits_header_getline(qfits_header * hdr, char * key) ;
/*----------------------------------------------------------------------------*/
/**
@brief Return the comment associated to a key, as a string
@param hdr qfits_header to parse
@param key key to find
@return pointer to statically allocated string
@doc
Finds the comment associated to the given key and return it as a
string. The returned pointer is statically allocated, so do not
modify its contents or try to free it.
Returns NULL if no matching key is found or no comment is attached.
*/
/*----------------------------------------------------------------------------*/
char * qfits_header_getcom(qfits_header * hdr, char * key) ;
/*----------------------------------------------------------------------------*/
/**
@brief Return the value associated to a key, as an int
@param hdr qfits_header to parse
@param key key to find
@param errval default value to return if nothing is found
@return int
Finds the value associated to the given key and return it as an
int. Returns errval if no matching key is found or no value is
attached.
*/
/*----------------------------------------------------------------------------*/
int qfits_header_getint(qfits_header * hdr, const char * key, int errval) ;
/*----------------------------------------------------------------------------*/
/**
@brief Return the value associated to a key, as a double
@param hdr qfits_header to parse
@param key key to find
@param errval default value to return if nothing is found
@return double
Finds the value associated to the given key and return it as a
double. Returns errval if no matching key is found or no value is
attached.
*/
/*----------------------------------------------------------------------------*/
double qfits_header_getdouble(qfits_header * hdr, const char * key, double errval) ;
/*----------------------------------------------------------------------------*/
/**
@brief Return the value associated to a key, as a boolean (int).
@param hdr qfits_header to parse
@param key key to find
@param errval default value to return if nothing is found
@return int
Finds the value associated to the given key and return it as a
boolean. Returns errval if no matching key is found or no value is
attached. A boolean is here understood as an int taking the value 0
or 1. errval can be set to any other integer value to reflect that
nothing was found.
errval is returned if no matching key is found or no value is
attached.
A true value is any character string beginning with a 'y' (yes), a
't' (true) or the digit '1'. A false value is any character string
beginning with a 'n' (no), a 'f' (false) or the digit '0'.
*/
/*----------------------------------------------------------------------------*/
int qfits_header_getboolean(qfits_header * hdr, const char * key, int errval) ;
/*----------------------------------------------------------------------------*/
/**
@brief Write out a key tuple to a string on 80 chars.
@param line Allocated output character buffer.
@param key Key to write.
@param val Value to write.
@param com Comment to write.
@return void
Write out a key, value and comment into an allocated character buffer.
The buffer must be at least 80 chars to receive the information.
Formatting is done according to FITS standard.
*/
/*----------------------------------------------------------------------------*/
void keytuple2str(char * line, char * key, char * val, char * com) ;
/*----------------------------------------------------------------------------*/
/**
@brief Dump a FITS header to an opened file.
@param hdr FITS header to dump
@param out Opened file pointer
@return int 0 if Ok, -1 otherwise
Dumps a FITS header to an opened file pointer.
*/
/*----------------------------------------------------------------------------*/
int qfits_header_dump(qfits_header * hdr, FILE * out) ;
/*----------------------------------------------------------------------------*/
/**
@brief Dump a FITS header to an opened file (one card per line).
@param hdr FITS header to dump
@param out Opened file pointer
@return int 0 if Ok, -1 otherwise
@see qfits_header_dump()
Dumps a FITS header to an opened file pointer.
This function is meant to create hdr files.
*/
/*----------------------------------------------------------------------------*/
int qfits_header_dump_hdr(qfits_header * hdr, FILE * out) ;
/*----------------------------------------------------------------------------*/
/**
@brief Dump a fits header into a memory block.
@param fh FITS header to dump
@param hsize Size of the returned header, in bytes (output).
@return 1 newly allocated memory block containing the FITS header.
This function dumps a FITS header structure into a newly allocated
memory block. The block is composed of characters, just as they would
appear in a FITS file. This function is useful to make a FITS header
in memory.
The returned block size is indicated in the passed output variable
'hsize'. The returned block must be deallocated using free().
*/
/*----------------------------------------------------------------------------*/
char * qfits_header_to_memblock(qfits_header * fh, int * hsize) ;
/* </dox> */
#ifdef __cplusplus
}
#endif
#endif
/* vim: set ts=4 et sw=4 tw=75 */

View File

@ -0,0 +1,56 @@
/*----------------------------------------------------------------------------*/
/**
@file fits_md5.h
@author N. Devillard
@date May 2001
@version $Revision: 1.5 $
@brief FITS data block MD5 computation routine.
This module offers MD5 computation over all data areas of a FITS file.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: fits_md5.h,v 1.5 2003/11/24 09:44:53 yjung Exp $
$Author: yjung $
$Date: 2003/11/24 09:44:53 $
$Revision: 1.5 $
*/
#ifndef FITS_MD5_H
#define FITS_MD5_H
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*-----------------------------------------------------------------------------
Function ANSI prototypes
-----------------------------------------------------------------------------*/
/* <dox> */
/*----------------------------------------------------------------------------*/
/**
@brief Compute the MD5 hash of data zones in a FITS file.
@param filename Name of the FITS file to examine.
@return 1 statically allocated character string, or NULL.
This function expects the name of a FITS file.
It will compute the MD5 hash on all data blocks in the main data section
and possibly extensions (including zero-padding blocks if necessary) and
return it as a string suitable for inclusion into a FITS keyword.
The returned string is statically allocated inside this function,
so do not free it or modify it. This function returns NULL in case
of error.
*/
/*----------------------------------------------------------------------------*/
char * qfits_datamd5(char * filename);
/* </dox> */
#endif
/* vim: set ts=4 et sw=4 tw=75 */

80
qfits/src/fits_p.h 100644
View File

@ -0,0 +1,80 @@
/*----------------------------------------------------------------------------*/
/**
@file fits_p.h
@author N. Devillard
@date Mar 2000
@version $Revision: 1.5 $
@brief FITS parser for a single card
This module contains various routines to help parsing a single FITS
card into its components: key, value, comment.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: fits_p.h,v 1.5 2003/11/24 09:44:53 yjung Exp $
$Author: yjung $
$Date: 2003/11/24 09:44:53 $
$Revision: 1.5 $
*/
#ifndef FITSEP_H
#define FITSEP_H
#ifdef __cplusplus
extern "C" {
#endif
/* <dox> */
/*-----------------------------------------------------------------------------
Function ANSI C prototypes
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief Find the keyword in a key card (80 chars)
@param line allocated 80-char line from a FITS header
@return statically allocated char *
Find out the part of a FITS line corresponding to the keyword.
Returns NULL in case of error. The returned pointer is statically
allocated in this function, so do not modify or try to free it.
*/
/*----------------------------------------------------------------------------*/
char * qfits_getkey(char * line) ;
/*----------------------------------------------------------------------------*/
/**
@brief Find the value in a key card (80 chars)
@param line allocated 80-char line from a FITS header
@return statically allocated char *
Find out the part of a FITS line corresponding to the value.
Returns NULL in case of error, or if no value can be found. The
returned pointer is statically allocated in this function, so do not
modify or try to free it.
*/
/*----------------------------------------------------------------------------*/
char * qfits_getvalue(char * line) ;
/*----------------------------------------------------------------------------*/
/**
@brief Find the comment in a key card (80 chars)
@param line allocated 80-char line from a FITS header
@return statically allocated char *
Find out the part of a FITS line corresponding to the comment.
Returns NULL in case of error, or if no comment can be found. The
returned pointer is statically allocated in this function, so do not
modify or try to free it.
*/
/*----------------------------------------------------------------------------*/
char * qfits_getcomment(char * line) ;
/* </dox> */
#ifdef __cplusplus
}
#endif
#endif
/* vim: set ts=4 et sw=4 tw=75 */

135
qfits/src/fits_rw.h 100644
View File

@ -0,0 +1,135 @@
/*----------------------------------------------------------------------------*/
/**
@file fits_rw.h
@author N. Devillard
@date Mar 2000
@version $Revision: 1.11 $
@brief FITS header reading/writing.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: fits_rw.h,v 1.11 2004/06/03 15:42:06 yjung Exp $
$Author: yjung $
$Date: 2004/06/03 15:42:06 $
$Revision: 1.11 $
*/
#ifndef FITS_RW_H
#define FITS_RW_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include "fits_std.h"
#include "fits_h.h"
/*-----------------------------------------------------------------------------
Function ANSI prototypes
-----------------------------------------------------------------------------*/
/* <dox> */
/*----------------------------------------------------------------------------*/
/**
@brief Read a FITS header from a file to an internal structure.
@param filename Name of the file to be read
@return Pointer to newly allocated qfits_header or NULL in error case.
This function parses a FITS (main) header, and returns an allocated
qfits_header object. The qfits_header object contains a linked-list of
key "tuples". A key tuple contains:
- A keyword
- A value
- A comment
- An original FITS line (as read from the input file)
Direct access to the structure is not foreseen, use accessor
functions in fits_h.h
Value, comment, and original line might be NULL pointers.
*/
/*----------------------------------------------------------------------------*/
qfits_header * qfits_header_read(char * filename) ;
/*----------------------------------------------------------------------------*/
/**
@brief Read a FITS header from a 'hdr' file.
@param filename Name of the file to be read
@return Pointer to newly allocated qfits_header or NULL in error case
This function parses a 'hdr' file, and returns an allocated qfits_header
object. A hdr file is an ASCII format were the header is written with a
carriage return after each line. The command dfits typically displays
a hdr file.
*/
/*----------------------------------------------------------------------------*/
qfits_header * qfits_header_read_hdr(char * filename) ;
/*----------------------------------------------------------------------------*/
/**
@brief Read a FITS header from a 'hdr' string
@param hdr_str String containing the hdr file
@param nb_char Number of characters in the string
@return Pointer to newly allocated qfits_header or NULL in error case
This function parses a 'hdr' string, and returns an allocated qfits_header
object.
*/
/*----------------------------------------------------------------------------*/
qfits_header * qfits_header_read_hdr_string(
unsigned char * hdr_str,
int nb_char) ;
/*----------------------------------------------------------------------------*/
/**
@brief Read an extension header from a FITS file.
@param filename Name of the FITS file to read
@param xtnum Extension number to read, starting from 0.
@return Newly allocated qfits_header structure.
Strictly similar to qfits_header_read() but reads headers from
extensions instead. If the requested xtension is 0, this function
calls qfits_header_read() to return the main header.
Returns NULL in case of error.
*/
/*----------------------------------------------------------------------------*/
qfits_header * qfits_header_readext(char * filename, int xtnum) ;
/*----------------------------------------------------------------------------*/
/**
@brief Pad an existing file with zeros to a multiple of 2880.
@param filename Name of the file to pad.
@return void
This function simply pads an existing file on disk with enough zeros
for the file size to reach a multiple of 2880, as required by FITS.
*/
/*----------------------------------------------------------------------------*/
void qfits_zeropad(char * filename) ;
/*----------------------------------------------------------------------------*/
/**
@brief Identify if a file is a FITS file.
@param filename name of the file to check
@return int 0, 1, or -1
Returns 1 if the file name looks like a valid FITS file. Returns
0 else. If the file does not exist, returns -1.
*/
/*----------------------------------------------------------------------------*/
int is_fits_file(char *filename) ;
/* </dox> */
#ifdef __cplusplus
}
#endif
#endif
/* vim: set ts=4 et sw=4 tw=75 */

View File

@ -0,0 +1,69 @@
/*----------------------------------------------------------------------------*/
/**
@file fits_std.h
@author N. Devillard
@date November 2001
@version $Revision: 1.5 $
@brief
This header file gathers a number of definitions strictly related
to the FITS format. Include it if you need to get definitions for
a FITS line size, header metrics, and other FITS-only symbols.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: fits_std.h,v 1.5 2003/11/24 09:44:53 yjung Exp $
$Author: yjung $
$Date: 2003/11/24 09:44:53 $
$Revision: 1.5 $
*/
#ifndef FITS_STD_H
#define FITS_STD_H
/*-----------------------------------------------------------------------------
Defines
-----------------------------------------------------------------------------*/
/* <dox> */
/* FITS header constants */
/** FITS block size */
#define FITS_BLOCK_SIZE (2880)
/** FITS number of cards per block */
#define FITS_NCARDS (36)
/** FITS size of each line in bytes */
#define FITS_LINESZ (80)
/** FITS magic number */
#define FITS_MAGIC "SIMPLE"
/** Size of the FITS magic number */
#define FITS_MAGIC_SZ 6
/* FITS pixel depths */
/** FITS BITPIX=8 */
#define BPP_8_UNSIGNED (8)
/** FITS BITPIX=16 */
#define BPP_16_SIGNED (16)
/** FITS BITPIX=32 */
#define BPP_32_SIGNED (32)
/** FITS BITPIX=-32 */
#define BPP_IEEE_FLOAT (-32)
/** FITS BITPIX=-64 */
#define BPP_IEEE_DOUBLE (-64)
/** Default BITPIX for output */
#define BPP_DEFAULT BPP_IEEE_FLOAT
/** Compute the number of bytes per pixel for a given BITPIX value */
#define BYTESPERPIXEL(x) ( ((x) == BPP_8_UNSIGNED) ? 1 : \
((x) == BPP_16_SIGNED) ? 2 : \
((x) == BPP_32_SIGNED) ? 4 : \
((x) == BPP_IEEE_FLOAT) ? 4 : \
((x) == BPP_IEEE_DOUBLE) ? 8 : 0 )
/* </dox> */
#endif
/* vim: set ts=4 et sw=4 tw=75 */

View File

@ -0,0 +1,155 @@
/*----------------------------------------------------------------------------*/
/**
@file get_name.h
@author Y. Jung
@date Jan 2004
@version $Revision: 1.4 $
@brief Get various names (filenames, dir names, login name, etc...)
*/
/*----------------------------------------------------------------------------*/
/*
$Id: get_name.h,v 1.4 2004/01/20 15:05:55 yjung Exp $
$Author: yjung $
$Date: 2004/01/20 15:05:55 $
$Revision: 1.4 $
*/
#ifndef GET_NAME_H
#define GET_NAME_H
#ifdef __cplusplus
extern "C" {
#endif
/* <dox> */
/*-----------------------------------------------------------------------------
Function ANSI C prototypes
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief Find the directory name in the given string.
@param filename Full path name to scan.
@return Pointer to statically allocated string.
Provide a full path name and you get in return a pointer to a statically
allocated string containing the name of the directory only, without trailing
slash. If the input string does not contain a slash (i.e. it is not a full
path), the returned string is '.', corresponding to the current working
directory. Since the returned string is statically allocated, do not try to
free it or modify it.
This function does not check for the existence of the path or the file.
Examples:
@verbatim
get_dir_name("/cdrom/data/image.fits") returns "/cdrom/data"
get_dir_name("filename.fits") returns "."
@endverbatim
*/
/*----------------------------------------------------------------------------*/
char * qfits_get_dir_name(char * filename) ;
/*----------------------------------------------------------------------------*/
/**
@brief Find out the base name of a file (i.e. without prefix path)
@param filename Full path name to scan.
@return Pointer to char within the input string.
Provide a full path name and you get in return a pointer to a statically
allocated string containing the name of the file only, without prefixing
directory names. If the input string does not contain a slash (i.e. it is
not a full path), the returned string is a copy of the input string.
This function does not check for the existence of the path or the file.
Examples:
@verbatim
qfits_get_base_name("/cdrom/data/image.fits") returns "image.fits"
qfits_get_base_name("filename.fits") returns "filename.fits"
@endverbatim
*/
/*----------------------------------------------------------------------------*/
char * qfits_get_base_name(const char *filename) ;
/*----------------------------------------------------------------------------*/
/**
@brief Find out the root part of a basename (name without extension).
@param filename File name to scan.
@return Pointer to statically allocated string.
Find out the root part of a file name, i.e. the file name without extension.
Since in Unix a file name can have several dots, only a number of extensions
are supported. This includes:
- .fits and .FITS
- .tfits and .TFITS
- .paf and .PAF
- .ascii and .ASCII
- .dat and .DAT
This function does not check for the existence of the path or the file.
Examples:
@verbatim
get_root_name("/cdrom/filename.fits") returns "/cdrom/filename"
get_root_name("filename.paf") returns "filename"
get_root_name("filename") returns "filename"
get_root_name("filename.ext") returns "filename.ext"
@endverbatim
Since the returned string is statically allocated in this module, do not try
to free it or modify its contents.
*/
/*----------------------------------------------------------------------------*/
char * qfits_get_root_name(char * filename) ;
/*----------------------------------------------------------------------------*/
/**
@brief Find out the extension of a file name
@param filename File name without path prefix.
@return Pointer to char within the input string.
Find out the extension of a given file name. Notice that the input character
string must not contain a path prefix (typically, you feed in the output of
@c qfits_get_base_name).
Works with all kinds of extensions: returns the part of the string after the
last dot. If no dot is found in the input string, NULL is returned.
Examples:
@verbatim
get_ext_name("filename.fits") returns "fits"
get_ext_name("hello.c") returns "c"
get_ext_name("readme") returns NULL
@endverbatim
*/
/*----------------------------------------------------------------------------*/
char * qfits_get_ext_name(char * filename) ;
/*----------------------------------------------------------------------------*/
/**
@brief Returns the user login name.
@return Pointer to statically allocated character string.
Finds out what the login name of the current user is. The result is
placed in a static character string inside this module and a pointer
to the first character in this string is returned. Do not modify or
free the returned string!
If the user name cannot be determined, the returned pointer will
point to a string which first character is a null character.
*/
/*----------------------------------------------------------------------------*/
char * qfits_get_login_name(void) ;
/* </dox> */
#ifdef __cplusplus
}
#endif
#endif
/* vim: set ts=4 et sw=4 tw=75 */

View File

@ -0,0 +1,104 @@
/*----------------------------------------------------------------------------*/
/**
@file ieeefp-compat.h
@author N. Devillard
@date Feb 2002
@version $Revision: 2.11 $
@brief This module implements the isnan() and isinf() macros.
The isnan() and isinf() macros are unfortunately not yet part of
the standard C math library everywhere. They can usually be found
in different places, if they are offered at all, and require the
application to link against the math library. To avoid portability
problems and linking against -lm, this module implements a fast
and portable way of finding out whether a floating-point value
(float or double) is a NaN or an Inf.
Instead of calling isnan() and isinf(), the programmer including
this file should call qfits_isnan() and qfits_isinf().
*/
/*----------------------------------------------------------------------------*/
/*
$Id: ieeefp-compat.h,v 2.11 2003/11/24 09:44:53 yjung Exp $
$Author: yjung $
$Date: 2003/11/24 09:44:53 $
$Revision: 2.11 $
*/
#ifndef IEEEFP_COMPAT_H
#define IEEEFP_COMPAT_H
/*-----------------------------------------------------------------------------
Macros
-----------------------------------------------------------------------------*/
/* <dox> */
/*----------------------------------------------------------------------------*/
/**
@brief Test a floating-point variable for NaN value.
@param n Number to test (float or double)
@return 1 if n is NaN, 0 else.
This macro is needed to support both float and double variables
as input parameter. It checks on the size of the input variable
to branch to the float or double version.
Portability is an issue for this function which is present on
most Unixes but not all, under various libraries (C lib on BSD,
Math lib on Linux, sunmath on Solaris, ...). Integrating the
code for this function makes qfits independent from any math
library.
*/
/*----------------------------------------------------------------------------*/
#define qfits_isnan(n) ((sizeof(n)==sizeof(float)) ? _qfits_isnanf(n) : \
(sizeof(n)==sizeof(double)) ? _qfits_isnand(n) : -1)
/*----------------------------------------------------------------------------*/
/**
@brief Test a floating-point variable for Inf value.
@param n Number to test (float or double)
@return 1 if n is Inf or -Inf, 0 else.
This macro is needed to support both float and double variables
as input parameter. It checks on the size of the input variable
to branch to the float or double version.
Portability is an issue for this function which is missing on most
Unixes. Most of the time, another function called finite() is
offered to perform the opposite task, but it is not consistent
among platforms and found in various libraries. Integrating the
code for this function makes qfits independent from any math
library.
*/
/*----------------------------------------------------------------------------*/
#define qfits_isinf(n) ((sizeof(n)==sizeof(float)) ? _qfits_isinff(n) : \
(sizeof(n)==sizeof(double)) ? _qfits_isinfd(n) : -1)
/*-----------------------------------------------------------------------------
Function prototypes
-----------------------------------------------------------------------------*/
/**
* Test a float variable for NaN value.
* Do not call directly, call qfits_isnan().
*/
int _qfits_isnanf(float f);
/**
* Test a float variable for Inf value.
* Do not call directly, call qfits_isinf().
*/
int _qfits_isinff(float f);
/**
* Test a double variable for NaN value.
* Do not call directly, call qfits_isnan().
*/
int _qfits_isnand(double d);
/**
* Test a double variable for Inf value.
* Do not call directly, call qfits_isinf().
*/
int _qfits_isinfd(double d);
/* </dox> */
#endif
/* vim: set ts=4 et sw=4 tw=75 */

24
qfits/src/md5.h 100644
View File

@ -0,0 +1,24 @@
#ifndef MD5_H
#define MD5_H
typedef unsigned int word32 ;
struct MD5Context {
word32 buf[4];
word32 bits[2];
unsigned char in[64];
};
void MD5Init(struct MD5Context *context);
void MD5Update(struct MD5Context *context, unsigned char const *buf,
unsigned len);
void MD5Final(unsigned char digest[16], struct MD5Context *context);
void MD5Transform(word32 buf[4], word32 const in[16]);
/*
* This is needed to make RSAREF happy on some MS-DOS compilers.
*/
typedef struct MD5Context MD5_CTX;
#endif /* !MD5_H */
/* vim: set ts=4 et sw=4 tw=75 */

110
qfits/src/pafs.h 100644
View File

@ -0,0 +1,110 @@
/*----------------------------------------------------------------------------*/
/**
@file pafs.h
@author N. Devillard
@date Feb 1999
@version $Revision: 1.4 $
@brief PAF format I/O.
This module contains various routines related to PAF file I/O.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: pafs.h,v 1.4 2003/11/24 09:44:53 yjung Exp $
$Author: yjung $
$Date: 2003/11/24 09:44:53 $
$Revision: 1.4 $
*/
#ifndef PAFS_H
#define PAFS_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------
Includes
---------ii------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "static_sz.h"
/* <dox> */
/*-----------------------------------------------------------------------------
Function prototypes
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief Open a new PAF file, output a default header.
@param filename Name of the file to create.
@param paf_id PAF identificator.
@param paf_desc PAF description.
@param login_name Login name
@param datetime Date
@return Opened file pointer.
This function creates a new PAF file with the requested file name.
If another file already exists with the same name, it will be
overwritten (if the file access rights allow it).
A default header is produced according to the VLT DICB standard. You
need to provide an identificator (paf_id) of the producer of the
file. Typically, something like "ISAAC/zero_point".
The PAF description (paf_desc) is meant for humans. Typically,
something like "Zero point computation results".
This function returns an opened file pointer, ready to receive more
data through fprintf's. The caller is responsible for fclose()ing
the file.
*/
/*----------------------------------------------------------------------------*/
FILE * qfits_paf_print_header(
char * filename,
char * paf_id,
char * paf_desc,
char * login_name,
char * datetime) ;
/*----------------------------------------------------------------------------*/
/**
@brief Query a PAF file for a value.
@param filename Name of the PAF to query.
@param key Name of the key to query.
@return 1 pointer to statically allocated string, or NULL.
This function parses a PAF file and returns the value associated to a
given key, as a pointer to an internal statically allocated string.
Do not try to free or modify the contents of the returned string!
If the key is not found, this function returns NULL.
*/
/*----------------------------------------------------------------------------*/
char * qfits_paf_query(
char * filename,
char * key) ;
/*----------------------------------------------------------------------------*/
/**
@brief returns 1 if file is in PAF format, 0 else
@param filename name of the file to check
@return int 0, 1, or -1
Returns 1 if the file name corresponds to a valid PAF file. Returns
0 else. If the file does not exist, returns -1. Validity of the PAF file
is checked with the presence of PAF.HDR.START at the beginning
*/
/*----------------------------------------------------------------------------*/
int qfits_is_paf_file(char * filename) ;
/* </dox> */
#ifdef __cplusplus
}
#endif
#endif

448
qfits/src/pixio.h 100644
View File

@ -0,0 +1,448 @@
/*----------------------------------------------------------------------------*/
/**
@file pixload.h
@author N. Devillard
@date Nov 2001
@version $Revision: 1.12 $
@brief Pixel loader for FITS images.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: pixio.h,v 1.12 2003/11/24 09:44:53 yjung Exp $
$Author: yjung $
$Date: 2003/11/24 09:44:53 $
$Revision: 1.12 $
*/
#ifndef PIXLOAD_H
#define PIXLOAD_H
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "xmemory.h"
#include "fits_std.h"
/* <dox> */
/*-----------------------------------------------------------------------------
Defines
-----------------------------------------------------------------------------*/
/** Symbol to set returned pixel type to float */
#define PTYPE_FLOAT 0
/** Symbol to set returned pixel type to int */
#define PTYPE_INT 1
/** Symbol to set returned pixel type to double */
#define PTYPE_DOUBLE 2
/*-----------------------------------------------------------------------------
New types
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief Alias for unsigned char
A 'byte' is just an alias for an unsigned char. It is only defined
for readability.
*/
/*----------------------------------------------------------------------------*/
typedef unsigned char byte ;
/*----------------------------------------------------------------------------*/
/**
@brief qfits loader control object
This structure serves two purposes: input and output for the qfits
pixel loading facility. To request pixels from a FITS file, you
need to allocate (statically or dynamically) such a structure and
fill up the input fields (filename, xtension number, etc.) to specify
the pixels you want from the file.
Before performing the actual load, you must pass the initialized
structure to qfitsloader_init() which will check whether the operation
is feasible or not (check its returned value).
If the operation was deemed feasible, you can proceed to load the pixels,
passing the same structure to qfits_loadpix() which will fill up the
output fields of the struct. Notice that a pixel buffer will have been
allocated (through malloc or mmap) and placed into the structure. You
need to call free() on this pointer when you are done with it,
typically in the image or cube destructor.
The qfitsloader_init() function is also useful to probe a FITS file
for useful informations, like getting the size of images in the file,
the pixel depth, or data offset.
Example of a code that prints out various informations about
a plane to load, without actually loading it:
@code
int main(int argc, char * argv[])
{
qfitsloader ql ;
ql.filename = argv[1] ;
ql.xtnum = 0 ;
ql.pnum = 0 ;
if (qfitsloader_init(&ql)!=0) {
printf("cannot read info about %s\n", argv[1]);
return -1 ;
}
printf( "file : %s\n"
"xtnum : %d\n"
"pnum : %d\n"
"# xtensions : %d\n"
"size X : %d\n"
"size Y : %d\n"
"planes : %d\n"
"bitpix : %d\n"
"datastart : %d\n"
"datasize : %d\n"
"bscale : %g\n"
"bzero : %g\n",
ql.filename,
ql.xtnum,
ql.pnum,
ql.exts,
ql.lx,
ql.ly,
ql.np,
ql.bitpix,
ql.seg_start,
ql.seg_size,
ql.bscale,
ql.bzero);
return 0 ;
}
@endcode
*/
/*----------------------------------------------------------------------------*/
typedef struct qfitsloader {
/** Private field to see if structure has been initialized */
int _init ;
/** input: Name of the file you want to read pixels from */
char * filename ;
/** input: xtension number you want to read */
int xtnum ;
/** input: Index of the plane you want, from 0 to np-1 */
int pnum ;
/** input: Pixel type you want (PTYPE_FLOAT, PTYPE_INT or PTYPE_DOUBLE) */
int ptype ;
/** input: Guarantee file copy or allow file mapping */
int map ;
/** output: Total number of extensions found in file */
int exts ;
/** output: Size in X of the requested plane */
int lx ;
/** output: Size in Y of the requested plane */
int ly ;
/** output: Number of planes present in this extension */
int np ;
/** output: BITPIX for this extension */
int bitpix ;
/** output: Start of the data segment (in bytes) for your request */
int seg_start ;
/** output: Size of the data segment (in bytes) for your request */
int seg_size ;
/** output: BSCALE found for this extension */
double bscale ;
/** output: BZERO found for this extension */
double bzero ;
/** output: Pointer to pixel buffer loaded as integer values */
int * ibuf ;
/** output: Pointer to pixel buffer loaded as float values */
float * fbuf ;
/** output: Pointer to pixel buffer loaded as double values */
double * dbuf ;
} qfitsloader ;
/*----------------------------------------------------------------------------*/
/**
@brief qfits dumper control object
This structure offers various control parameters to dump a pixel
buffer to a FITS file. The buffer will be dumped as requested
to the requested file in append mode. Of course, the requested file
must be writeable for the operation to succeed.
The following example demonstrates how to save a linear ramp sized
100x100 to a FITS file with BITPIX=16. Notice that this code only
dumps the pixel buffer, no header information is provided in this
case.
@code
int i, j ;
int * ibuf ;
qfitsdumper qd ;
// Fill a buffer with 100x100 int pixels
ibuf = malloc(100 * 100 * sizeof(int));
for (j=0 ; j<100 ; j++) {
for (i=0 ; i<100 ; i++) {
ibuf[i+j*100] = i+j ;
}
}
qd.filename = "out.fits" ; // Output file name
qd.npix = 100 * 100 ; // Number of pixels
qd.ptype = PTYPE_INT ; // Input buffer type
qd.ibuf = ibuf ; // Set buffer pointer
qd.out_ptype = BPP_16_SIGNED ; // Save with BITPIX=16
// Dump buffer to file (error checking omitted for clarity)
qfits_pixdump(&qd);
free(ibuf);
@endcode
If the provided output file name is "STDOUT" (all capitals), the
function will dump the pixels to the stdout steam (usually the console,
could have been re-directed).
*/
/*----------------------------------------------------------------------------*/
typedef struct qfitsdumper {
/** Name of the file to dump to, "STDOUT" to dump to stdout */
char * filename ;
/** Number of pixels in the buffer to dump */
int npix ;
/** Buffer type: PTYPE_FLOAT, PTYPE_INT or PTYPE_DOUBLE */
int ptype ;
/** Pointer to input integer pixel buffer */
int * ibuf ;
/** Pointer to input float pixel buffer */
float * fbuf ;
/** Pointer to input double pixel buffer */
double * dbuf ;
/** Requested BITPIX in output FITS file */
int out_ptype ;
} qfitsdumper ;
/*-----------------------------------------------------------------------------
Function prototypes
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief Initialize a qfitsloader control object.
@param ql qfitsloader object to initialize.
@return int 0 if Ok, -1 if error occurred.
This function expects a qfitsloader object with a number of input
fields correctly filled in. The minimum fields to set are:
- filename: Name of the file to examine.
- xtnum: Extension number to examine (0 for main section).
- pnum: Plane number in the requested extension.
You can go ahead with these fields only if you only want to get
file information for this plane in this extension. If you want
to later load the plane, you must additionally fill the 'ptype'
field to a correct value (PTYPE_INT, PTYPE_FLOAT, PTYPE_DOUBLE)
before calling qfits_loadpix() so that it knows which conversion
to perform.
This function is basically a probe sent on a FITS file to ask
qfits if loading these data would be Ok or not. The actual loading
is performed by qfits_loadpix() afterwards.
*/
/*----------------------------------------------------------------------------*/
int qfitsloader_init(qfitsloader * ql);
/*----------------------------------------------------------------------------*/
/**
@brief Load a pixel buffer for one image.
@param ql Allocated and initialized qfitsloader control object.
@return int 0 if Ok, -1 if error occurred.
This function performs a load of a pixel buffer into memory. It
expects an allocated and initialized qfitsloader object in input.
See qfitsloader_init() about initializing the object.
This function will fill up the ibuf/fbuf/dbuf field, depending
on the requested pixel type (resp. int, float or double).
The returned buffer has been allocated using one of the special
memory operators present in xmemory.c. To deallocate the buffer,
you must call the version of free() offered by xmemory, not the
usual system free(). It is enough to include "xmemory.h" in your
code before you make calls to the pixel loader here.
*/
/*----------------------------------------------------------------------------*/
int qfits_loadpix(qfitsloader * ql);
/*----------------------------------------------------------------------------*/
/**
@brief Load a pixel buffer as floats.
@param p_source Pointer to source buffer (as bytes).
@param npix Number of pixels to load.
@param bitpix FITS BITPIX in original file.
@param bscale FITS BSCALE in original file.
@param bzero FITS BZERO in original file.
@return 1 pointer to a newly allocated buffer of npix floats.
This function takes in input a pointer to a byte buffer as given
in the original FITS file (big-endian format). It converts the
buffer to an array of float (whatever representation is used for
floats by this platform is used) and returns the newly allocated
buffer, or NULL if an error occurred.
The returned buffer must be deallocated using the free() offered
by xmemory. It is enough to #include "xmemory.h" before calling
free on the returned pointer.
*/
/*----------------------------------------------------------------------------*/
float * qfits_pixin_float (byte *, int, int, double, double);
/*----------------------------------------------------------------------------*/
/**
@brief Load a pixel buffer as ints.
@param p_source Pointer to source buffer (as bytes).
@param npix Number of pixels to load.
@param bitpix FITS BITPIX in original file.
@param bscale FITS BSCALE in original file.
@param bzero FITS BZERO in original file.
@return 1 pointer to a newly allocated buffer of npix ints.
This function takes in input a pointer to a byte buffer as given
in the original FITS file (big-endian format). It converts the
buffer to an array of int (whatever representation is used for
int by this platform is used) and returns the newly allocated
buffer, or NULL if an error occurred.
The returned buffer must be deallocated using the free() offered
by xmemory. It is enough to #include "xmemory.h" before calling
free on the returned pointer.
*/
/*----------------------------------------------------------------------------*/
int * qfits_pixin_int (byte *, int, int, double, double);
/*----------------------------------------------------------------------------*/
/**
@brief Load a pixel buffer as doubles.
@param p_source Pointer to source buffer (as bytes).
@param npix Number of pixels to load.
@param bitpix FITS BITPIX in original file.
@param bscale FITS BSCALE in original file.
@param bzero FITS BZERO in original file.
@return 1 pointer to a newly allocated buffer of npix doubles.
This function takes in input a pointer to a byte buffer as given
in the original FITS file (big-endian format). It converts the
buffer to an array of double (whatever representation is used for
int by this platform is used) and returns the newly allocated
buffer, or NULL if an error occurred.
The returned buffer must be deallocated using the free() offered
by xmemory. It is enough to #include "xmemory.h" before calling
free on the returned pointer.
*/
/*----------------------------------------------------------------------------*/
double * qfits_pixin_double(byte *, int, int, double, double);
/*----------------------------------------------------------------------------*/
/**
@brief Dump a pixel buffer to an output FITS file in append mode.
@param qd qfitsdumper control object.
@return int 0 if Ok, -1 otherwise.
This function takes in input a qfitsdumper control object. This object
must be allocated beforehand and contain valid references to the data
to save, and how to save it.
The minimum fields to fill are:
- filename: Name of the FITS file to dump to.
- npix: Number of pixels in the buffer to be dumped.
- ptype: Type of the passed buffer (PTYPE_FLOAT, PTYPE_INT, PTYPE_DOUBLE)
- out_ptype: Requested FITS BITPIX for the output.
One of the following fields must point to the corresponding pixel
buffer:
- ibuf for an int pixel buffer (ptype=PTYPE_INT)
- fbuf for a float pixel buffer (ptype=PTYPE_FLOAT)
- dbuf for a double pixel buffer (ptype=PTYPE_DOUBLE)
This is a fairly low-level function, in the sense that it does not
check that the output file already contains a proper header or even
that the file it is appending to is indeed a FITS file. It will
convert the pixel buffer to the requested BITPIX type and append
the data to the file, without padding with zeros. See qfits_zeropad()
about padding.
If the given output file name is "STDOUT" (all caps), the dump
will be performed to stdout.
*/
/*----------------------------------------------------------------------------*/
int qfits_pixdump(qfitsdumper * qd) ;
/*----------------------------------------------------------------------------*/
/**
@brief Convert a float pixel buffer to a byte buffer.
@param buf Input float buffer.
@param npix Number of pixels in the input buffer.
@param ptype Requested output BITPIX type.
@return 1 pointer to a newly allocated byte buffer.
This function converts the given float buffer to a buffer of bytes
suitable for dumping to a FITS file (i.e. big-endian, in the
requested pixel type). The returned pointer must be deallocated
using the free() function offered by xmemory.
*/
/*----------------------------------------------------------------------------*/
byte * qfits_pixdump_float(float * buf, int npix, int ptype);
/*----------------------------------------------------------------------------*/
/**
@brief Convert an int pixel buffer to a byte buffer.
@param buf Input int buffer.
@param npix Number of pixels in the input buffer.
@param ptype Requested output BITPIX type.
@return 1 pointer to a newly allocated byte buffer.
This function converts the given int buffer to a buffer of bytes
suitable for dumping to a FITS file (i.e. big-endian, in the
requested pixel type). The returned pointer must be deallocated
using the free() function offered by xmemory.
*/
/*----------------------------------------------------------------------------*/
byte * qfits_pixdump_int(int * buf, int npix, int ptype);
/*----------------------------------------------------------------------------*/
/**
@brief Convert a double pixel buffer to a byte buffer.
@param buf Input double buffer.
@param npix Number of pixels in the input buffer.
@param ptype Requested output BITPIX type.
@return 1 pointer to a newly allocated byte buffer.
This function converts the given double buffer to a buffer of bytes
suitable for dumping to a FITS file (i.e. big-endian, in the
requested pixel type). The returned pointer must be deallocated
using the free() function offered by xmemory.
*/
/*----------------------------------------------------------------------------*/
byte * qfits_pixdump_double(double * buf, int npix, int ptype);
/* </dox> */
#endif
/* vim: set ts=4 et sw=4 tw=75 */

97
qfits/src/qerror.h 100644
View File

@ -0,0 +1,97 @@
/*----------------------------------------------------------------------------*/
/**
@file qerror.h
@author N. Devillard
@date Nov 2001
@version $Revision: 1.8 $
@brief qfits error handling
*/
/*----------------------------------------------------------------------------*/
/*
$Id: qerror.h,v 1.8 2005/05/18 14:38:01 yjung Exp $
$Author: yjung $
$Date: 2005/05/18 14:38:01 $
$Revision: 1.8 $
*/
#ifndef QERROR_H
#define QERROR_H
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdarg.h>
/*-----------------------------------------------------------------------------
Function prototypes
-----------------------------------------------------------------------------*/
/* <dox> */
/*----------------------------------------------------------------------------*/
/**
@brief Get the current status of error display.
@return int 1 if error display is active, 0 if not.
This function returns the current error display status. If it returns 1,
it means that all calls to qfits_error/qfits_warning will display
messages using the registered functions, otherwise they do nothing.
*/
/*----------------------------------------------------------------------------*/
int qfits_err_statget(void);
/*----------------------------------------------------------------------------*/
/**
@brief Set the current status of error display.
@param sta New status to be set.
@return int giving the previous display status.
This function sets the current error display status to the required
value, and returns the previous value. It is useful to store the
previous value, in view of restoring it afterwards, e.g. to make a
function silent on all its errors. Example:
\begin{verbatim}
int prev_stat = qfits_err_statset(0) ;
function_call() ;
qfits_err_statset(prev_stat);
\end{verbatim}
*/
/*----------------------------------------------------------------------------*/
int qfits_err_statset(int sta);
/*----------------------------------------------------------------------------*/
/**
@brief Register a function to display error/warning messages.
@param dispfn Display function (see doc below).
@return int 0 if function was registered, -1 if not.
This function registers a display function into the error-handling
module. Display functions have the following prototype:
@code
void display_function(char * msg);
@endcode
They are simple functions that expect a ready-made error message
and return void. They can do whatever they want with the message
(log it to a file, send it to a GUI, to the syslog, ...). The
message is built using a printf-like statement in qfits_error and
qfits_warning, then passed to all registered display functions.
A maximum of QFITS_ERR_MAXERRDISP can be registered (see source code).
If the limit has been reached, this function will signal it by
returning -1.
*/
/*----------------------------------------------------------------------------*/
int qfits_err_register( void (*dispfn)(char*) ) ;
/* </dox> */
/* Public warning/error functions */
void qfits_warning(const char *fmt, ...);
void qfits_error(const char *fmt, ...);
#endif
/* vim: set ts=4 et sw=4 tw=75 */

311
qfits/src/simple.h 100644
View File

@ -0,0 +1,311 @@
/*----------------------------------------------------------------------------*/
/**
@file simple.h
@author N. Devillard
@date Jan 1999
@version $Revision: 1.12 $
@brief Simple FITS access routines.
This module offers a number of very basic low-level FITS access
routines.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: simple.h,v 1.12 2005/05/18 14:38:01 yjung Exp $
$Author: yjung $
$Date: 2005/05/18 14:38:01 $
$Revision: 1.12 $
*/
#ifndef SIMPLE_H
#define SIMPLE_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* <dox> */
/*-----------------------------------------------------------------------------
Defines
-----------------------------------------------------------------------------*/
/** Unknown type for FITS value */
#define QFITS_UNKNOWN 0
/** Boolean type for FITS value */
#define QFITS_BOOLEAN 1
/** Int type for FITS value */
#define QFITS_INT 2
/** Float type for FITS value */
#define QFITS_FLOAT 3
/** Complex type for FITS value */
#define QFITS_COMPLEX 4
/** String type for FITS value */
#define QFITS_STRING 5
/*-----------------------------------------------------------------------------
Function codes
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief Retrieve the value of a key in a FITS header
@param filename Name of the FITS file to browse
@param keyword Name of the keyword to find
@return pointer to statically allocated character string
Provide the name of a FITS file and a keyword to look for. The input
file is memory-mapped and the first keyword matching the requested one is
located. The value corresponding to this keyword is copied to a
statically allocated area, so do not modify it or free it.
The input keyword is first converted to upper case and expanded to
the HIERARCH scheme if given in the shortFITS notation.
This function is pretty fast due to the mmapping. Due to buffering
on most Unixes, it is possible to call many times this function in a
row on the same file and do not suffer too much from performance
problems. If the file contents are already in the cache, the file
will not be re-opened every time.
It is possible, though, to modify this function to perform several
searches in a row. See the source code.
Returns NULL in case the requested keyword cannot be found.
*/
/*----------------------------------------------------------------------------*/
char * qfits_query_hdr(char * filename, const char * keyword) ;
/*----------------------------------------------------------------------------*/
/**
@brief Retrieve the value of a keyin a FITS extension header.
@param filename name of the FITS file to browse.
@param keyword name of the FITS key to look for.
@param xtnum xtension number
@return pointer to statically allocated character string
Same as qfits_query_hdr but for extensions. xtnum starts from 1 to
the number of extensions. If xtnum is zero, this function is
strictly identical to qfits_query_hdr().
*/
/*----------------------------------------------------------------------------*/
char * qfits_query_ext(char * filename, const char * keyword, int xtnum) ;
/*----------------------------------------------------------------------------*/
/**
@brief Counts the number of extensions in a FITS file
@param filename Name of the FITS file to browse.
@return int
Counts how many extensions are in the file. Returns 0 if no
extension is found, and -1 if an error occurred.
*/
/*----------------------------------------------------------------------------*/
int qfits_query_n_ext(char * filename) ;
/*----------------------------------------------------------------------------*/
/**
@brief Counts the number of planes in a FITS extension.
@param filename Name of the FITS file to browse.
@param exnum Extensin number
@return int
Counts how many planes are in the extension. Returns 0 if no plane is found,
and -1 if an error occurred.
*/
/*----------------------------------------------------------------------------*/
int qfits_query_nplanes(char * filename, int extnum) ;
/*----------------------------------------------------------------------------*/
/**
@brief Clean out a FITS string value.
@param s pointer to allocated FITS value string.
@return pointer to statically allocated character string
From a string FITS value like 'marvin o''hara', remove head and tail
quotes, replace double '' with simple ', trim blanks on each side,
and return the result in a statically allocated area.
Examples:
- ['o''hara'] becomes [o'hara]
- [' H '] becomes [H]
- ['1.0 '] becomes [1.0]
*/
/*----------------------------------------------------------------------------*/
char * qfits_pretty_string(char * s) ;
/*----------------------------------------------------------------------------*/
/**
@brief Identify if a FITS value is boolean
@param s FITS value as a string
@return int 0 or 1
Identifies if a FITS value is boolean.
*/
/*----------------------------------------------------------------------------*/
int qfits_is_boolean(char * s) ;
/*----------------------------------------------------------------------------*/
/**
@brief Identify if a FITS value is an int.
@param s FITS value as a string
@return int 0 or 1
Identifies if a FITS value is an integer.
*/
/*----------------------------------------------------------------------------*/
int qfits_is_int(char * s) ;
/*----------------------------------------------------------------------------*/
/**
@brief Identify if a FITS value is float.
@param s FITS value as a string
@return int 0 or 1
Identifies if a FITS value is float.
*/
/*----------------------------------------------------------------------------*/
int qfits_is_float(char * s) ;
/*----------------------------------------------------------------------------*/
/**
@brief Identify if a FITS value is complex.
@param s FITS value as a string
@return int 0 or 1
Identifies if a FITS value is complex.
*/
/*----------------------------------------------------------------------------*/
int qfits_is_complex(char * s) ;
/*----------------------------------------------------------------------------*/
/**
@brief Identify if a FITS value is string.
@param s FITS value as a string
@return int 0 or 1
Identifies if a FITS value is a string.
*/
/*----------------------------------------------------------------------------*/
int qfits_is_string(char * s) ;
/*----------------------------------------------------------------------------*/
/**
@brief Identify the type of a FITS value given as a string.
@param s FITS value as a string
@return integer naming the FITS type
Returns the following value:
- QFITS_UNKNOWN (0) for an unknown type.
- QFITS_BOOLEAN (1) for a boolean type.
- QFITS_INT (2) for an integer type.
- QFITS_FLOAT (3) for a floating-point type.
- QFITS_COMPLEX (4) for a complex number.
- QFITS_STRING (5) for a FITS string.
*/
/*----------------------------------------------------------------------------*/
int qfits_get_type(char * s) ;
/*----------------------------------------------------------------------------*/
/**
@brief Retrieve offset to start and size of a header in a FITS file.
@param filename Name of the file to examine
@param xtnum Extension number (0 for main)
@param seg_start Segment start in bytes (output)
@param seg_size Segment size in bytes (output)
@return int 0 if Ok, -1 otherwise.
This function retrieves the two most important informations about
a header in a FITS file: the offset to its beginning, and the size
of the header in bytes. Both values are returned in the passed
pointers to ints. It is Ok to pass NULL for any pointer if you do
not want to retrieve the associated value.
You must provide an extension number for the header, 0 meaning the
main header in the file.
*/
/*----------------------------------------------------------------------------*/
int qfits_get_hdrinfo(
char * filename,
int xtnum,
int * seg_start,
int * seg_size) ;
/*----------------------------------------------------------------------------*/
/**
@brief Retrieve offset to start and size of a data section in a file.
@param filename Name of the file to examine.
@param xtnum Extension number (0 for main).
@param seg_start Segment start in bytes (output).
@param seg_size Segment size in bytes (output).
@return int 0 if Ok, -1 otherwise.
This function retrieves the two most important informations about
a data section in a FITS file: the offset to its beginning, and the size
of the section in bytes. Both values are returned in the passed
pointers to ints. It is Ok to pass NULL for any pointer if you do
not want to retrieve the associated value.
You must provide an extension number for the header, 0 meaning the
main header in the file.
*/
/*----------------------------------------------------------------------------*/
int qfits_get_datinfo(
char * filename,
int xtnum,
int * seg_start,
int * seg_size) ;
/*----------------------------------------------------------------------------*/
/**
@brief Query a card in a FITS (main) header by a given key
@param filename Name of the FITS file to check.
@param keyword Where to read a card in the header.
@return Allocated string containing the card or NULL
*/
/*----------------------------------------------------------------------------*/
char * qfits_query_card(
char * filename,
char * keyword) ;
/*----------------------------------------------------------------------------*/
/**
@brief Replace a card in a FITS (main) header by a given card
@param filename Name of the FITS file to modify.
@param keyword Where to substitute a card in the header.
@param substitute What to replace the line with.
@return int 0 if Ok, -1 otherwise
Replaces a whole card (80 chars) in a FITS header by a given FITS
line (80 chars). The replacing line is assumed correctly formatted
and containing at least 80 characters. The file is modified: it must
be accessible in read/write mode.
The input keyword is first converted to upper case and expanded to
the HIERARCH scheme if given in the shortFITS notation.
Returns 0 if everything worked Ok, -1 otherwise.
*/
/*----------------------------------------------------------------------------*/
int qfits_replace_card(
char * filename,
const char * keyword,
char * substitute) ;
/* </dox> */
#ifdef __cplusplus
}
#endif
#endif
/* vim: set ts=4 et sw=4 tw=75 */

View File

@ -0,0 +1,42 @@
/*----------------------------------------------------------------------------*/
/**
@file static_sz.h
@author N. Devillard
@date Dec 1999
@version $Revision: 1.5 $
@brief Definitions for various fixed sizes.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: static_sz.h,v 1.5 2003/11/24 09:44:53 yjung Exp $
$Author: yjung $
$Date: 2003/11/24 09:44:53 $
$Revision: 1.5 $
*/
#ifndef STATIC_SZ_H
#define STATIC_SZ_H
#ifdef __cplusplus
extern "C" {
#endif
/* <dox> */
/*-----------------------------------------------------------------------------
Defines
-----------------------------------------------------------------------------*/
/** Maximum supported file name size */
#define FILENAMESZ 512
/** Maximum number of characters per line in an ASCII file */
#define ASCIILINESZ 1024
/* </dox> */
#ifdef __cplusplus
}
#endif
#endif
/* vim: set ts=4 et sw=4 tw=75 */

View File

@ -0,0 +1,93 @@
/*----------------------------------------------------------------------------*/
/**
@file t_iso8601.h
@author N. Devillard
@date Aug 1999
@version $Revision: 1.8 $
@brief Get date/time, possibly in ISO8601 format.
This module contains various utilities to get the current date/time,
and possibly format it according to the ISO 8601 format.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: t_iso8601.h,v 1.8 2004/01/20 11:47:59 yjung Exp $
$Author: yjung $
$Date: 2004/01/20 11:47:59 $
$Revision: 1.8 $
*/
#ifndef T_ISO8601_H
#define T_ISO8601_H
#ifdef __cplusplus
extern "C" {
#endif
/* <dox> */
/*-----------------------------------------------------------------------------
Function ANSI C prototypes
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief Returns the current date as a long (CCYYMMDD).
@return The current date as a long number.
Returns the current date as a long value (CCYYMMDD). Since most
system clocks do not return a century, this function assumes that
all years 80 and above are in the 20th century, and all years 00 to
79 are in the 21st century. For best results, consume before 1 Jan
2080.
Example: 19 Oct 2000 is returned as 20001019
*/
/*----------------------------------------------------------------------------*/
long qfits_date_now (void);
/*----------------------------------------------------------------------------*/
/**
@brief Returns the current time as a long (HHMMSSCC).
@return The current time as a long number.
Returns the current time as a long value (HHMMSSCC). If the system
clock does not return centiseconds, these are set to zero.
Example: 15:36:12.84 is returned as 15361284
*/
/*----------------------------------------------------------------------------*/
long qfits_time_now(void);
/*----------------------------------------------------------------------------*/
/**
@brief Returns the current date as a static string.
@return Pointer to statically allocated string.
Build and return a string containing the date of today in ISO8601
format. The returned pointer points to a statically allocated string
in the function, so no need to free it.
*/
/*----------------------------------------------------------------------------*/
char * qfits_get_date_iso8601(void);
/*----------------------------------------------------------------------------*/
/**
@brief Returns the current date and time as a static string.
@return Pointer to statically allocated string
Build and return a string containing the date of today and the
current time in ISO8601 format. The returned pointer points to a
statically allocated string in the function, so no need to free it.
*/
/*----------------------------------------------------------------------------*/
char * qfits_get_datetime_iso8601(void);
/* </dox> */
#ifdef __cplusplus
}
#endif
#endif
/* vim: set ts=4 et sw=4 tw=75 */

546
qfits/src/tfits.h 100644
View File

@ -0,0 +1,546 @@
/*----------------------------------------------------------------------------*/
/**
@file tfits.h
@author Yves Jung
@date July 1999
@version $Revision: 1.25 $
@brief FITS table handling
*/
/*----------------------------------------------------------------------------*/
/*
$Id: tfits.h,v 1.25 2003/11/24 09:44:53 yjung Exp $
$Author: yjung $
$Date: 2003/11/24 09:44:53 $
$Revision: 1.25 $
*/
#ifndef TFITS_H
#define TFITS_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------------------------
Includes
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "fits_h.h"
#include "static_sz.h"
/* <dox> */
/*-----------------------------------------------------------------------------
Defines
-----------------------------------------------------------------------------*/
/* The following defines the maximum acceptable size for a FITS value */
#define FITSVALSZ 60
#define QFITS_INVALIDTABLE 0
#define QFITS_BINTABLE 1
#define QFITS_ASCIITABLE 2
/*-----------------------------------------------------------------------------
New types
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief Column data type
*/
/*----------------------------------------------------------------------------*/
typedef enum _TFITS_DATA_TYPE_ {
TFITS_ASCII_TYPE_A,
TFITS_ASCII_TYPE_D,
TFITS_ASCII_TYPE_E,
TFITS_ASCII_TYPE_F,
TFITS_ASCII_TYPE_I,
TFITS_BIN_TYPE_A,
TFITS_BIN_TYPE_B,
TFITS_BIN_TYPE_C,
TFITS_BIN_TYPE_D,
TFITS_BIN_TYPE_E,
TFITS_BIN_TYPE_I,
TFITS_BIN_TYPE_J,
TFITS_BIN_TYPE_L,
TFITS_BIN_TYPE_M,
TFITS_BIN_TYPE_P,
TFITS_BIN_TYPE_X,
TFITS_BIN_TYPE_UNKNOWN
} tfits_type ;
/*----------------------------------------------------------------------------*/
/**
@brief Column object
This structure contains all information needed to read a column in a table.
These informations come from the header.
The qfits_table object contains a list of qfits_col objects.
This structure has to be created from scratch and filled if one want to
generate a FITS table.
*/
/*----------------------------------------------------------------------------*/
typedef struct qfits_col
{
/**
Number of atoms in one field.
In ASCII tables, it is the number of characters in the field as defined
in TFORM%d keyword.
In BIN tables, it is the number of atoms in each field. For type 'A',
it is the number of characters. A field with two complex object will
have atom_nb = 4.
*/
int atom_nb ;
/**
Number of decimals in a ASCII field.
This value is always 0 for BIN tables
*/
int atom_dec_nb ;
/**
Size of one element in bytes. In ASCII tables, atom_size is the size
of the element once it has been converted in its 'destination' type.
For example, if "123" is contained in an ASCII table in a column
defined as I type, atom_nb=3, atom_size=4.
In ASCII tables:
- type 'A' : atom_size = atom_nb = number of chars
- type 'I', 'F' or 'E' : atom_size = 4
- type 'D' : atom_size = 8
In BIN tables :
- type 'A', 'L', 'X', 'B': atom_size = 1
- type 'I' : atom_size = 2
- type 'E', 'J', 'C', 'P' : atom_size = 4
- type 'D', 'M' : atom_size = 8
In ASCII table, there is one element per field. The size in bytes and
in number of characters is atom_nb, and the size in bytes after
conversion of the field is atom_size.
In BIN tables, the size in bytes of a field is always atom_nb*atom_size.
*/
int atom_size ;
/**
Type of data in the column as specified in TFORM keyword
In ASCII tables : TFITS_ASCII_TYPE_* with *=A, I, F, E or D
In BIN tables : TFITS_BIN_TYPE_* with *=L, X, B, I, J, A, E, D, C, M or P
*/
tfits_type atom_type ;
/** Label of the column */
char tlabel[FITSVALSZ] ;
/** Unit of the data */
char tunit[FITSVALSZ] ;
/** Null value */
char nullval[FITSVALSZ] ;
/** Display format */
char tdisp[FITSVALSZ] ;
/**
zero and scale are used when the quantity in the field does not
represent a true physical quantity. Basically, thez should be used
when they are present: physical_value = zero + scale * field_value
They are read from TZERO and TSCAL in the header
*/
int zero_present ;
float zero ;
int scale_present ;
float scale ;
/** Offset between the beg. of the table and the beg. of the column. */
int off_beg ;
/** Flag to know if the column is readable. An empty col is not readable */
int readable ;
} qfits_col ;
/*----------------------------------------------------------------------------*/
/**
@brief Table object
This structure contains all information needed to read a FITS table.
These information come from the header. The object is created by
qfits_open().
To read a FITS table, here is a code example:
@code
int main(int argc, char* argv[])
{
qfits_table * table ;
int n_ext ;
int i ;
// Query the number of extensions
n_ext = qfits_query_n_ext(argv[1]) ;
// For each extension
for (i=0 ; i<n_ext ; i++) {
// Read all the infos about the current table
table = qfits_table_open(argv[1], i+1) ;
// Display the current table
dump_extension(table, stdout, '|', 1, 1) ;
}
return ;
}
@endcode
*/
/*----------------------------------------------------------------------------*/
typedef struct qfits_table
{
/**
Name of the file the table comes from or it is intended to end to
*/
char filename[FILENAMESZ] ;
/**
Table type.
Possible values: QFITS_INVALIDTABLE, QFITS_BINTABLE, QFITS_ASCIITABLE
*/
int tab_t ;
/** Width in bytes of the table */
int tab_w ;
/** Number of columns */
int nc ;
/** Number of raws */
int nr ;
/** Array of qfits_col objects */
qfits_col * col ;
} qfits_table ;
/*-----------------------------------------------------------------------------
Function prototypes
-----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
@brief Identify a file as containing a FITS table in extension.
@param filename Name of the FITS file to examine.
@param xtnum Extension number to check (starting from 1).
@return int 1 if the extension contains a table, 0 else.
Examines the requested extension and identifies the presence of a
FITS table.
*/
/*----------------------------------------------------------------------------*/
int qfits_is_table(char * filename, int xtnum) ;
/*----------------------------------------------------------------------------*/
/**
@brief Generate a default primary header to store tables
@return the header object
*/
/*----------------------------------------------------------------------------*/
qfits_header * qfits_table_prim_header_default(void) ;
/*----------------------------------------------------------------------------*/
/**
@brief Generate a default extension header to store tables
@return the header object
*/
/*----------------------------------------------------------------------------*/
qfits_header * qfits_table_ext_header_default(qfits_table *) ;
/*----------------------------------------------------------------------------*/
/**
@brief Table object constructor
@param filename Name of the FITS file associated to the table
@param table_type Type of the table (QFITS_ASCIITABLE or QFITS_BINTABLE)
@param table_width Width in bytes of the table
@param nb_cols Number of columns
@param nb_raws Number of raws
@return The table object
The columns are also allocated. The object has to be freed with
qfits_table_close()
*/
/*----------------------------------------------------------------------------*/
qfits_table * qfits_table_new(
char * filename,
int table_type,
int table_width,
int nb_cols,
int nb_raws) ;
/*----------------------------------------------------------------------------*/
/**
@brief Fill a column object with some provided informations
@param qc Pointer to the column that has to be filled
@param unit Unit of the data
@param label Label of the column
@param disp Way to display the data
@param nullval Null value
@param atom_nb Number of atoms per field. According to the type, an atom
is a double, an int, a char, ...
@param atom_dec_nb Number of decimals as specified in TFORM
@param atom_size Size in bytes of the field for ASCII tables, and of
an atom for BIN tables. ASCII tables only contain 1
atom per field (except for A type where you can of
course have more than one char per field)
@param atom_type Type of data (11 types for BIN, 5 for ASCII)
@param zero_present Flag to use or not zero
@param zero Zero value
@param scale_present Flag to use or not scale
@param scale Scale value
@param offset_beg Gives the position of the column
@return -1 in error case, 0 otherwise
*/
/*----------------------------------------------------------------------------*/
int qfits_col_fill(
qfits_col * qc,
int atom_nb,
int atom_dec_nb,
int atom_size,
tfits_type atom_type,
char * label,
char * unit,
char * nullval,
char * disp,
int zero_present,
float zero,
int scale_present,
float scale,
int offset_beg) ;
/*----------------------------------------------------------------------------*/
/**
@brief Read a FITS extension.
@param filename Name of the FITS file to examine.
@param xtnum Extension number to read (starting from 1).
@return Pointer to newly allocated qfits_table structure.
Read a FITS table from a given file name and extension, and return a
newly allocated qfits_table structure.
*/
/*----------------------------------------------------------------------------*/
qfits_table * qfits_table_open(
char * filename,
int xtnum) ;
/*----------------------------------------------------------------------------*/
/**
@brief Free a FITS table and associated pointers
@param t qfits_table to free
@return void
Frees all memory associated to a qfits_table structure.
*/
/*----------------------------------------------------------------------------*/
void qfits_table_close(qfits_table * t) ;
/*----------------------------------------------------------------------------*/
/**
@brief Extract data from a column in a FITS table
@param th Allocated qfits_table
@param colnum Number of the column to extract (from 0 to colnum-1)
@param selection boolean array to define the selected rows
@return unsigned char array
If selection is NULL, select the complete column.
Extract a column from a FITS table and return the data as a bytes
array. The returned array type and size are determined by the
column object in the qfits_table and by the selection parameter.
Returned array size in bytes is:
nbselected * col->natoms * col->atom_size
Numeric types are correctly understood and byte-swapped if needed,
to be converted to the local machine type.
NULL values have to be handled by the caller.
The returned buffer has been allocated using one of the special memory
operators present in xmemory.c. To deallocate the buffer, you must call
the version of free() offered by xmemory, not the usual system free(). It
is enough to include "xmemory.h" in your code before you make calls to
the pixel loader here.
*/
/*----------------------------------------------------------------------------*/
unsigned char * qfits_query_column(
qfits_table * th,
int colnum,
int * selection) ;
/*----------------------------------------------------------------------------*/
/**
@brief Extract consequtive values from a column in a FITS table
@param th Allocated qfits_table
@param colnum Number of the column to extract (from 0 to colnum-1)
@param start_ind Index of the first row (0 for the first)
@param nb_rows Number of rows to extract
@return unsigned char array
Does the same as qfits_query_column() but on a consequtive sequence of rows
Spares the overhead of the selection object allocation
*/
/*----------------------------------------------------------------------------*/
unsigned char * qfits_query_column_seq(
qfits_table * th,
int colnum,
int start_ind,
int nb_rows) ;
/*----------------------------------------------------------------------------*/
/**
@brief Compute the table width in bytes from the columns infos
@param th Allocated qfits_table
@return the width (-1 in error case)
*/
/*----------------------------------------------------------------------------*/
int qfits_compute_table_width(qfits_table * th) ;
/*----------------------------------------------------------------------------*/
/**
@brief Extract binary data from a column in a FITS table
@param th Allocated qfits_table
@param colnum Number of the column to extract (from 0 to colnum-1)
@param selection bollean array to identify selected rows
@param null_value Value to return when a NULL value comes
@return Pointer to void *
Extract a column from a FITS table and return the data as a generic
void* array. The returned array type and size are determined by the
column object in the qfits_table.
Returned array size in bytes is:
nb_selected * col->atom_nb * col->atom_size
NULL values are recognized and replaced by the specified value.
The returned buffer has been allocated using one of the special memory
operators present in xmemory.c. To deallocate the buffer, you must call
the version of free() offered by xmemory, not the usual system free(). It
is enough to include "xmemory.h" in your code before you make calls to
the pixel loader here.
*/
/*----------------------------------------------------------------------------*/
void * qfits_query_column_data(
qfits_table * th,
int colnum,
int * selection,
void * null_value) ;
/*----------------------------------------------------------------------------*/
/**
@brief Extract binary data from a column in a FITS table
@param th Allocated qfits_table
@param colnum Number of the column to extract (from 0 to colnum-1)
@param start_ind Index of the first row (0 for the first)
@param nb_rows Number of rows to extract
@param null_value Value to return when a NULL value comes
@return Pointer to void *
Does the same as qfits_query_column_data() but on a consequtive sequence
of rows. Spares the overhead of the selection object allocation
*/
/*----------------------------------------------------------------------------*/
void * qfits_query_column_seq_data(
qfits_table * th,
int colnum,
int start_ind,
int nb_rows,
void * null_value) ;
/*----------------------------------------------------------------------------*/
/**
@brief Detect NULL values in a column
@param th Allocated qfits_table
@param colnum Number of the column to check (from 0 to colnum-1)
@param selection Array to identify selected rows
@param nb_vals Gives the size of the output array
@param nb_nulls Gives the number of detected null values
@return array with 1 for NULLs and 0 for non-NULLs
*/
/*----------------------------------------------------------------------------*/
int * qfits_query_column_nulls(
qfits_table * th,
int colnum,
int * selection,
int * nb_vals,
int * nb_nulls) ;
/*----------------------------------------------------------------------------*/
/**
@brief Save a table to a FITS file with a given FITS header.
@param array Data array.
@param table table
@param fh FITS header to insert in the output file.
@return -1 in error case, 0 otherwise
*/
/*----------------------------------------------------------------------------*/
int qfits_save_table_hdrdump(
void ** array,
qfits_table * table,
qfits_header * fh) ;
/*----------------------------------------------------------------------------*/
/**
@brief Appends a std extension header + data to a FITS table file.
@param outfile Pointer to (opened) file ready for writing.
@param t Pointer to qfits_table
@param data Table data to write
@return int 0 if Ok, -1 otherwise
Dumps a FITS table to a file. The whole table described by qfits_table, and
the data arrays contained in 'data' are dumped to the file. An extension
header is produced with all keywords needed to describe the table, then the
data is dumped to the file.
The output is then padded to reach a multiple of 2880 bytes in size.
Notice that no main header is produced, only the extension part.
*/
/*----------------------------------------------------------------------------*/
int qfits_table_append_xtension(
FILE * outfile,
qfits_table * t,
void ** data) ;
/*----------------------------------------------------------------------------*/
/**
@brief Appends a specified extension header + data to a FITS table file.
@param outfile Pointer to (opened) file ready for writing.
@param t Pointer to qfits_table
@param data Table data to write
@param hdr Specified extension header
@return int 0 if Ok, -1 otherwise
Dumps a FITS table to a file. The whole table described by qfits_table, and
the data arrays contained in 'data' are dumped to the file following the
specified fits header.
The output is then padded to reach a multiple of 2880 bytes in size.
Notice that no main header is produced, only the extension part.
*/
/*----------------------------------------------------------------------------*/
int qfits_table_append_xtension_hdr(
FILE * outfile,
qfits_table * t,
void ** data,
qfits_header * hdr) ;
/*----------------------------------------------------------------------------*/
/**
@brief given a col and a row, find out the string to write for display
@param table table structure
@param col_id col id (0 -> nbcol-1)
@param row_id row id (0 -> nrow-1)
@param use_zero_scale Flag to use or not zero and scale
@return the string to write
*/
/*----------------------------------------------------------------------------*/
char * qfits_table_field_to_string(
qfits_table * table,
int col_id,
int row_id,
int use_zero_scale) ;
/* </dox> */
#ifdef __cplusplus
}
#endif
#endif
/* vim: set ts=4 et sw=4 tw=75 */