Commit 3b348a94 authored by Emmanuel Bertin's avatar Emmanuel Bertin
Browse files

Changed trunk directory name

parents
/*
filter.c
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* Part of: SExtractor
*
* Author: E.BERTIN (IAP)
*
* Contents: functions dealing with on-line filtering of the image
* (for detection).
*
* Last modify: 26/11/2003
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "define.h"
#include "globals.h"
#include "prefs.h"
#include "fits/fitscat.h"
#include "bpro.h"
#include "filter.h"
#include "image.h"
/******************************** convolve ***********************************/
/*
Convolve a scan line with an array.
*/
void convolve(picstruct *field, PIXTYPE *mscan)
{
int mw,mw2,m0,me,m,mx,dmx, y0,dy, sw,sh;
float *mask;
PIXTYPE *mscane, *s,*s0, *d,*de, mval;
sw = field->width;
sh = field->stripheight;
mw = thefilter->convw;
mw2 = mw/2;
mscane = mscan+sw;
y0 = field->y - (thefilter->convh/2);
if ((dy = field->ymin-y0) > 0)
{
m0 = mw*dy;
y0 = field->ymin;
}
else
m0 = 0;
if ((dy = field->ymax - y0) < thefilter->convh)
me = mw*dy;
else
me = mw*thefilter->convh;
memset(mscan, 0, sw*sizeof(PIXTYPE));
s0 = NULL; /* To avoid gcc -Wall warnings */
mask = thefilter->conv+m0;
for (m = m0, mx = 0; m<me; m++, mx++)
{
if (mx==mw)
mx = 0;
if (!mx)
s0 = field->strip+sw*((y0++)%sh);
if ((dmx = mx-mw2)>=0)
{
s = s0 + dmx;
d = mscan;
de = mscane - dmx;
}
else
{
s = s0;
d = mscan - dmx;
de = mscane;
}
mval = *(mask++);
while (d<de)
*(d++) += mval**(s++);
}
return;
}
/********************************* getconv **********************************/
/*
Read the convolution mask from a file.
*/
int getconv(char *filename)
{
FILE *file;
char str[MAXCHAR], *sstr, *null = NULL;
double sum, var, pix;
int i,j, n, normflag;
/* Open the file which may contain a convolution mask */
if (!(file = fopen(filename, "r")))
error(EXIT_FAILURE, "*Error*: cannot open ", filename);
/* Check it is a convolution mask. Otherwise, exit */
fgets(str,MAXCHAR,file);
if (strncmp(str,"CONV",4))
{
fclose(file);
return RETURN_ERROR;
}
if (strstr(str,"NORM"))
normflag = strstr(str,"NONORM")?0:1;
else
{
warning("No normalization info found in convolution file (old format?)\n",
"> => I will assume you want the mask to be normalized...");
normflag = 1;
}
/* Allocate memory for storing mask elements */
QMALLOC(thefilter->conv, float, MAXMASK);
for (i=0, n=0; fgets(str,MAXCHAR,file);)
{
j=0;
sstr = strtok(str, " \t\n");
if (sstr && sstr[0]!=(char)'#')
do
{
j++;
thefilter->conv[i++] = (float)atof(sstr);
if (i>MAXMASK)
error(EXIT_FAILURE, "*Error*: Convolution mask too large in ",
filename);
} while ((sstr = strtok(null, " \t\n")));
if (j>n)
n = j;
}
fclose(file);
if ((thefilter->convw = n)<1)
error(EXIT_FAILURE, "*Error*: unappropriate convolution mask width in ",
filename);
if (i%n)
error(EXIT_FAILURE, "*Error*: unappropriate convolution mask line in ",
filename);
QREALLOC(thefilter->conv, float, i);
thefilter->convh = i/n;
var = 0.0;
for (j=0, sum=0.0; j<i; j++)
{
sum += fabs(pix = thefilter->conv[j]);
var += pix*pix;
}
thefilter->varnorm = (float)(var=sqrt(var));
if (normflag)
{
if (sum == 0.0)
{
warning("Zero-sum filter: ", "Normalization switched to variance-mode");
sum = var;
}
for (j=0; j<i; j++)
thefilter->conv[j] /= sum;
}
thefilter->nconv = thefilter->convw*thefilter->convh;
return RETURN_OK;
}
/********************************* getfilter *********************************/
/*
Read either a convolution mask or an ANN file.
*/
void getfilter(char *filename)
{
QCALLOC(thefilter, filterstruct, 1);
if (getconv(filename) != RETURN_OK && getneurfilter(filename) != RETURN_OK)
error(EXIT_FAILURE, "*Error*: not a suitable filter in ", filename);
return;
}
/******************************** getneurfilter ******************************/
/*
Read an ANN RETINA-filter file.
*/
int getneurfilter(char *filename)
{
#define FILTEST(x) \
if (x != RETURN_OK) \
error(EXIT_FAILURE, "*Error*: incorrect filter header in ", filename)
catstruct *fcat;
tabstruct *ftab;
int ival;
/* We first map the catalog */
if (!(fcat = read_cat(filename)))
return RETURN_ERROR;
/* Test if the requested table is present */
if (!(ftab = name_to_tab(fcat, "BP-ANN", 0)))
error(EXIT_FAILURE, "*Error*: no BP-ANN info found in ", filename);
FILTEST(fitsread(ftab->headbuf, "BPTYPE ", gstr,H_STRING,T_STRING));
if (strcmp(gstr, "RETINA"))
error(EXIT_FAILURE, "*Error*: not a retina-filter in ", filename);
FILTEST(fitsread(ftab->headbuf, "RENAXIS ", &ival ,H_INT, T_LONG));
if (ival != 2)
error(EXIT_FAILURE, "*Error*: not a 2D retina in ", filename);
FILTEST(fitsread(ftab->headbuf, "RENAXIS1", &thefilter->convw ,H_INT,T_LONG));
FILTEST(fitsread(ftab->headbuf, "RENAXIS2", &thefilter->convh ,H_INT,T_LONG));
thefilter->nconv = thefilter->convw*thefilter->convh;
QMALLOC(thefilter->conv, float, thefilter->nconv);
thefilter->bpann = loadtab_bpann(ftab, filename);
close_cat(fcat);
free_cat(&fcat,1);
return RETURN_OK;
}
/********************************* endfilter *********************************/
/*
Terminate filtering procedures.
*/
void endfilter()
{
QFREE(thefilter->conv);
if (thefilter->bpann)
{
free_bpann(thefilter->bpann);
thefilter->bpann = NULL;
}
QFREE(thefilter);
return;
}
/********************************** filter ***********************************/
/*
Switch to the appropriate filtering routine.
*/
void filter(picstruct *field, PIXTYPE *mscan)
{
if (thefilter->bpann)
neurfilter(field, mscan);
else
convolve(field, mscan);
return;
}
/******************************** neurfilter *********************************/
/*
Filter a scan line using an artificial retina.
*/
void neurfilter(picstruct *field, PIXTYPE *mscan)
{
PIXTYPE cval;
float *pix, resp, sig, threshlow, threshhigh;
int i,x, tflag;
sig = field->backsig;
if ((tflag = (prefs.nfilter_thresh>0)))
{
threshlow = prefs.filter_thresh[0]*field->backsig;
threshhigh = (prefs.nfilter_thresh<2)?
BIG : prefs.filter_thresh[1]*field->backsig;
}
else
threshlow = threshhigh = 0.0; /* To avoid gcc -Wall warnings */
for (x=0;x<field->width;x++)
{
if (tflag)
{
cval = PIX(field, x, field->y);
if (cval<threshlow || cval>threshhigh)
{
*(mscan++) = cval;
continue;
}
}
/*-- Copy the surrounding image area to the retina */
copyimage(field, thefilter->conv, thefilter->convw, thefilter->convh,
x, field->y);
pix = thefilter->conv;
/*-- Apply a transform of the intensity scale */
for (i=thefilter->nconv; i--; pix++)
*pix = *pix>0.0?log(1+*pix/sig):-log(1-*pix/sig);
play_bpann(thefilter->bpann, thefilter->conv, &resp);
if (resp>70.0)
resp = 70.0;
else if (resp<-70.0)
resp = -70.0;
/*-- Recover the linear intensity scale */
*(mscan++) = resp>0.0?sig*(exp(resp)-1):sig*(exp(-resp)-1);
}
return;
}
/******************************* convolve_image ******************************/
/*
Convolve a vignet with an array.
*/
void convolve_image(picstruct *field, double *vig1,
double *vig2, int width, int height)
{
int mw,mw2,m0,me,m,mx,dmx, y, y0,dy;
float *mask;
double *mscane, *s,*s0, *vig3, *d,*de, mval, val;
/* If no filtering, just return a copy of the input data */
if (!thefilter || thefilter->bpann)
{
memcpy(vig2, vig1, width*height*sizeof(double));
return;
}
s0 = NULL; /* To avoid gcc -Wall warnings */
mw = thefilter->convw;
mw2 = mw/2;
memset(vig2, 0, width*height*sizeof(double));
vig3 = vig2;
for (y=0; y<height; y++, vig3+=width)
{
mscane = vig3+width;
y0 = y - (thefilter->convh/2);
if (y0 < 0)
{
m0 = -mw*y0;
y0 = 0;
}
else
m0 = 0;
if ((dy = height - y0) < thefilter->convh)
me = mw*dy;
else
me = mw*thefilter->convh;
mask = thefilter->conv+m0;
for (m = m0, mx = 0; m<me; m++, mx++)
{
if (mx==mw)
mx = 0;
if (!mx)
s0 = vig1+width*(y0++);
if ((dmx = mx-mw2)>=0)
{
s = s0 + dmx;
d = vig3;
de = mscane - dmx;
}
else
{
s = s0;
d = vig3 - dmx;
de = mscane;
}
mval = *(mask++);
while (d<de)
*(d++) += ((val = *(s++))>-BIG? mval*val:0.0);
}
}
return;
}
/*
filter.h
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* Part of: SExtractor
*
* Author: E.BERTIN, IAP/Leiden
*
* Contents: functions dealing with on-line filtering of the image
* (for detection).
*
* Last modify: 09/11/99
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
/*------------------------------- definitions -------------------------------*/
#define MAXMASK 1024 /* Maximum number of mask elements (=32x32) */
/*------------------------------- structures --------------------------------*/
typedef struct structfilter
{
/*---- convolution */
float *conv; /* pointer to the convolution mask */
int nconv; /* total number of elements */
int convw, convh; /* x,y size of the mask */
float varnorm;
/*---- neural filtering */
struct structbpann *bpann;
} filterstruct;
filterstruct *thefilter;
/*------------------------------- functions ---------------------------------*/
void convolve(picstruct *, PIXTYPE *),
convolve_image(picstruct *field, double *vig1,
double *vig2, int width, int height),
filter(picstruct *, PIXTYPE *),
neurfilter(picstruct *, PIXTYPE *),
endfilter(void),
getfilter(char *filename);
int getconv(char *filename),
getneurfilter(char *filename);
# Program Makefile for the FITScat library
# Copyright (C) 2002 Emmanuel Bertin.
noinst_LIBRARIES = libfits.a
libfits_a_SOURCES = fitsbody.c fitscat.c fitscheck.c fitscleanup.c \
fitsconv.c fitshead.c fitskey.c fitsmisc.c \
fitsread.c fitstab.c fitsutil.c fitswrite.c \
fitscat_defs.h fitscat.h
# Makefile.in generated by automake 1.9.4 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
SOURCES = $(libfits_a_SOURCES)
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ../..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
subdir = src/fits
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/acx_urbi_resolve_dir.m4 \
$(top_srcdir)/acx_prog_cc_optim.m4 \
$(top_srcdir)/acx_prog_cc_optim.m4 \
$(top_srcdir)/acx_urbi_resolve_dir.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(SHELL) $(top_srcdir)/autoconf/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
LIBRARIES = $(noinst_LIBRARIES)
AR = ar
ARFLAGS = cru
libfits_a_AR = $(AR) $(ARFLAGS)
libfits_a_LIBADD =
am_libfits_a_OBJECTS = fitsbody.$(OBJEXT) fitscat.$(OBJEXT) \
fitscheck.$(OBJEXT) fitscleanup.$(OBJEXT) fitsconv.$(OBJEXT) \
fitshead.$(OBJEXT) fitskey.$(OBJEXT) fitsmisc.$(OBJEXT) \
fitsread.$(OBJEXT) fitstab.$(OBJEXT) fitsutil.$(OBJEXT) \
fitswrite.$(OBJEXT)
libfits_a_OBJECTS = $(am_libfits_a_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/autoconf/depcomp
am__depfiles_maybe = depfiles
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
SOURCES = $(libfits_a_SOURCES)
DIST_SOURCES = $(libfits_a_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DATE2 = @DATE2@
DATE3 = @DATE3@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGER = @PACKAGER@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build_alias = @build_alias@
datadir = @datadir@
exec_prefix = @exec_prefix@
host_alias = @host_alias@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
# Program Makefile for the FITScat library
# Copyright (C) 2002 Emmanuel Bertin.
noinst_LIBRARIES = libfits.a
libfits_a_SOURCES = fitsbody.c fitscat.c fitscheck.c fitscleanup.c \
fitsconv.c fitshead.c fitskey.c fitsmisc.c \
fitsread.c fitstab.c fitsutil.c fitswrite.c \
fitscat_defs.h fitscat.h
all: all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/fits/Makefile'; \
cd $(top_srcdir) && \
$(AUTOMAKE) --foreign src/fits/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
libfits.a: $(libfits_a_OBJECTS) $(libfits_a_DEPENDENCIES)
-rm -f libfits.a
$(libfits_a_AR) libfits.a $(libfits_a_OBJECTS) $(libfits_a_LIBADD)
$(RANLIB) libfits.a
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fitsbody.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fitscat.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fitscheck.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fitscleanup.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fitsconv.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fitshead.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fitskey.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fitsmisc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fitsread.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fitstab.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fitsutil.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fitswrite.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
uninstall-info-am:
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkdir_p) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LIBRARIES)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
info: info-am
info-am:
install-data-am:
install-exec-am:
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-info-am
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-noinstLIBRARIES ctags distclean distclean-compile \
distclean-generic distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-exec install-exec-am install-info \
install-info-am install-man install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
uninstall-am uninstall-info-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
/*
fitsbody.c
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* Part of: The LDAC Tools
*
* Author: E.BERTIN (IAP)
*
* Contents: Handle memory allocation for FITS bodies.
*
* Last modify: 29/06/2006
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#include "fitscat_defs.h"
#include "fitscat.h"
size_t body_maxram = BODY_DEFRAM,
body_maxvram = BODY_DEFVRAM,
body_ramleft, body_vramleft, body_ramflag;
int body_vmnumber;
double bufdata0[DATA_BUFSIZE/sizeof(double)];
char body_swapdirname[MAXCHARS] = BODY_DEFSWAPDIR;
/******* alloc_body ***********************************************************
PROTO PIXTYPE *alloc_body(tabstruct *tab,
void (*func)(PIXTYPE *ptr, int npix))
PURPOSE Allocate memory for and read a FITS data body (read-only). If not
enough RAM is available, a swap file is created.
INPUT Table (tab) structure.
OUTPUT Pointer to the mapped data if OK, or NULL otherwise.
NOTES The file pointer must be positioned at the beginning of the data.
AUTHOR E. Bertin (IAP)
VERSION 05/05/2001
***/
PIXTYPE *alloc_body(tabstruct *tab, void (*func)(PIXTYPE *ptr, int npix))
{
FILE *file;
PIXTYPE *buffer;
size_t npix, size, sizeleft, spoonful;
if (!body_ramflag)
{
body_ramleft = body_maxram;
body_vramleft = body_maxvram;
body_ramflag = 1;
}
/* Return a NULL pointer if size is zero */
if (!tab->tabsize)
return (PIXTYPE *)NULL;
/* Check that there is a cat parent structure and that the file is open */
if (tab->cat && !tab->cat->file)
error(EXIT_FAILURE, "*Internal Error*: Cannot access table: ",
tab->extname);
/* Decide if the data will go in physical memory or on swap-space */
npix = tab->tabsize/tab->bytepix;
size = npix*sizeof(PIXTYPE);
if (size < body_ramleft)
{
/*-- There should be enough RAM left: try to do a malloc() */
if ((tab->bodybuf = malloc(size)))
{
QFSEEK(tab->cat->file, tab->bodypos, SEEK_SET, tab->cat->filename);
read_body(tab, (PIXTYPE *)tab->bodybuf, npix);
/*---- Apply pixel processing */
if (func)
(*func)((PIXTYPE *)tab->bodybuf, npix);
body_ramleft -= size;
return (PIXTYPE *)tab->bodybuf;
}
else
tab->bodybuf = NULL;
}
if (size < body_vramleft)
{
/*-- Convert and copy the data to a swap file, and mmap() it */
if (!(buffer = malloc(DATA_BUFSIZE)))
return NULL;
sprintf(tab->swapname, "%s/vm%05ld_%05x.tmp",
body_swapdirname, (long)getpid(),
(unsigned int)++body_vmnumber) ;
if (!(file=fopen(tab->swapname, "wb+")))
error(EXIT_FAILURE, "*Error*: cannot create swap-file ", tab->swapname);
add_cleanupfilename(tab->swapname);
spoonful = (size%DATA_BUFSIZE);
if (!spoonful)
spoonful = DATA_BUFSIZE;
QFSEEK(tab->cat->file, tab->bodypos, SEEK_SET, tab->cat->filename);
read_body(tab, buffer, spoonful/sizeof(PIXTYPE));
/*-- Apply pixel processing */
if (func)
(*func)(buffer, spoonful/sizeof(PIXTYPE));
QFWRITE(buffer, spoonful, file, tab->swapname);
for (sizeleft = size; sizeleft -= spoonful;)
{
read_body(tab, buffer, (spoonful=DATA_BUFSIZE)/sizeof(PIXTYPE));
/*--- Apply pixel processing */
if (func)
(*func)(buffer, spoonful/sizeof(PIXTYPE));
QFWRITE(buffer, spoonful, file, tab->swapname);
}
free(buffer);
tab->bodybuf = mmap(NULL,size,PROT_READ,MAP_SHARED,fileno(file),(off_t)0);
fclose(file);
tab->swapflag = 1;
body_vramleft -= size;
/*-- Memory mapping problem */
if (tab->bodybuf == (void *)-1)
return NULL;
return (PIXTYPE *)tab->bodybuf;
}
/* If no memory left at all: forget it! */
return NULL;
}
/******* free_body ************************************************************
PROTO void free_body(tabstruct *tab)
PURPOSE Free FITS body data.
INPUT Tab structure.
OUTPUT -.
NOTES .
AUTHOR E. Bertin (IAP)
VERSION 04/03/2000
***/
void free_body(tabstruct *tab)
{
size_t size;
/* Free the body! (if allocated) */
if (tab->bodybuf)
{
size = (tab->tabsize/tab->bytepix)*sizeof(PIXTYPE);
if (tab->swapflag)
{
if (munmap(tab->bodybuf, size))
warning("Can't unmap ", tab->cat->filename);
tab->swapflag = 0;
tab->bodybuf = NULL;
body_vramleft += size;
if (unlink(tab->swapname))
warning("Can't delete ", tab->swapname);
remove_cleanupfilename(tab->swapname);
*tab->swapname = '\0';
}
else
{
QFREE(tab->bodybuf);
body_ramleft += size;
}
}
/* Free the decompression buffer if allocated */
if (tab->compress_buf)
QFREE(tab->compress_buf);
return;
}
/******* read_body ************************************************************
PROTO read_body(tabstruct *tab, PIXTYPE *ptr, long size)
PURPOSE Read values from the body of a FITS table.
INPUT A pointer to the tab structure,
a pointer to the array in memory,
the number of elements to be read.
OUTPUT -.
NOTES .
AUTHOR E. Bertin (IAP)
VERSION 06/11/2003
***/
void read_body(tabstruct *tab, PIXTYPE *ptr, size_t size)
{
catstruct *cat;
unsigned char cuval, cublank;
char *bufdata,
cval, cblank;
unsigned short suval, sublank;
short val16, sval, sblank;
unsigned int iuval, iublank;
int curval, dval, blankflag, ival, iblank;
size_t i, bowl, spoonful, npix;
PIXTYPE bs,bz;
/* a NULL cat structure indicates that no data can be read */
if (!(cat = tab->cat))
return;
bs = (PIXTYPE)tab->bscale;
bz = (PIXTYPE)tab->bzero;
blankflag = tab->blankflag;
switch(tab->compress_type)
{
/*-- Uncompressed image */
case COMPRESS_NONE:
bowl = DATA_BUFSIZE/tab->bytepix;
spoonful = size<bowl?size:bowl;
for(; size>0; size -= spoonful)
{
if (spoonful>size)
spoonful = size;
bufdata = (char *)bufdata0;
QFREAD(bufdata, spoonful*tab->bytepix, cat->file, cat->filename);
switch(tab->bitpix)
{
case BP_BYTE:
if (blankflag)
{
if (tab->bitsgn)
{
cblank = (char)tab->blank;
for (i=spoonful; i--;)
*(ptr++) = ((cval = *(bufdata++)) == cblank)?
-BIG : cval*bs + bz;
}
else
{
cublank = (unsigned char)tab->blank;
for (i=spoonful; i--;)
*(ptr++) = ((cuval=*((unsigned char *)bufdata++))==cublank)?
-BIG : cuval*bs + bz;
}
}
else
{
if (tab->bitsgn)
for (i=spoonful; i--;)
*(ptr++) = *(bufdata++)*bs + bz;
else
for (i=spoonful; i--;)
*(ptr++) = *((unsigned char *)bufdata++)*bs + bz;
}
break;
case BP_SHORT:
if (bswapflag)
swapbytes(bufdata, 2, spoonful);
if (blankflag)
{
if (tab->bitsgn)
{
sblank = (short)tab->blank;
for (i=spoonful; i--; bufdata += sizeof(short))
*(ptr++) = ((sval = *((short *)bufdata)) == sblank)?
-BIG : sval*bs + bz;
}
else
{
sublank = (unsigned short)tab->blank;
for (i=spoonful; i--; bufdata += sizeof(unsigned short))
*(ptr++) = ((suval=*((unsigned short *)bufdata)) == sublank)?
-BIG : suval*bs + bz;
}
}
else
{
if (tab->bitsgn)
for (i=spoonful; i--; bufdata += sizeof(short))
*(ptr++) = *((short *)bufdata)*bs + bz;
else
for (i=spoonful; i--; bufdata += sizeof(unsigned short))
*(ptr++) = *((unsigned short *)bufdata)*bs + bz;
}
break;
case BP_LONG:
if (bswapflag)
swapbytes(bufdata, 4, spoonful);
if (blankflag)
{
if (tab->bitsgn)
{
iblank = (int)tab->blank;
for (i=spoonful; i--; bufdata += sizeof(int))
*(ptr++) = ((ival = *((int *)bufdata)) == iblank)?
-BIG : ival*bs + bz;
}
else
{
iublank = (unsigned int)tab->blank;
for (i=spoonful; i--; bufdata += sizeof(unsigned int))
*(ptr++) = ((iuval = *((unsigned int *)bufdata)) == iublank)?
-BIG : iuval*bs + bz;
}
}
else
{
if (tab->bitsgn)
for (i=spoonful; i--; bufdata += sizeof(int))
*(ptr++) = *((int *)bufdata)*bs + bz;
else
for (i=spoonful; i--; bufdata += sizeof(unsigned int))
*(ptr++) = *((unsigned int *)bufdata)*bs + bz;
}
break;
case BP_FLOAT:
if (bswapflag)
swapbytes(bufdata, 4, spoonful);
for (i=spoonful; i--; bufdata += sizeof(float))
*(ptr++) = ((0x7f800000&*(unsigned int *)bufdata) == 0x7f800000)?
-BIG : *((float *)bufdata)*bs + bz;
break;
case BP_DOUBLE:
if (bswapflag)
{
swapbytes(bufdata, 8, spoonful);
for (i=spoonful; i--; bufdata += sizeof(double))
*(ptr++) = ((0x7ff00000 & *(unsigned int *)(bufdata+4))
== 0x7ff00000)?
-BIG : *((double *)bufdata)*bs + bz;
}
else
{
for (i=spoonful; i--; bufdata += sizeof(double))
*(ptr++) = ((0x7ff00000 & *(unsigned int *)bufdata)
== 0x7ff00000)?
-BIG : *((double *)bufdata)*bs + bz;
}
break;
default:
error(EXIT_FAILURE,"*FATAL ERROR*: unknown BITPIX type in ",
"read_body()");
break;
}
}
break;
/*-- Compressed image */
case COMPRESS_BASEBYTE:
if (!tab->compress_buf)
QMALLOC(tab->compress_buf, char, FBSIZE);
bufdata = tab->compress_bufptr;
curval = tab->compress_curval;
npix = tab->compress_npix;
while (size--)
{
if (!(npix--))
{
if (curval != tab->compress_checkval)
error(EXIT_FAILURE, "*Error*: invalid BASEBYTE checksum in ",
cat->filename);
bufdata = tab->compress_buf;
QFREAD(bufdata, FBSIZE, cat->file, cat->filename);
curval = 0;
if (bswapflag)
swapbytes(bufdata, 4, 1);
tab->compress_checkval = *((int *)bufdata);
bufdata += 4;
if (bswapflag)
swapbytes(bufdata, 2, 1);
npix = (int)(*((short *)bufdata))-1;
bufdata+=2;
}
if ((dval=(int)*(bufdata++))==-128)
{
if (bswapflag)
swapbytes(bufdata, 2, 1);
memcpy(&val16, bufdata, 2);
dval = (int)val16;
if (dval==-32768)
{
bufdata += 2;
if (bswapflag)
swapbytes(bufdata, 4, 1);
memcpy(&dval,bufdata,4);
bufdata += 4;
}
else
bufdata += 2;
}
*(ptr++) = dval*bs + bz;
curval += dval;
}
tab->compress_curval = curval;
tab->compress_bufptr = bufdata;
tab->compress_npix = npix;
break;
case COMPRESS_PREVPIX:
if (!tab->compress_buf)
QMALLOC(tab->compress_buf, char, FBSIZE);
bufdata = tab->compress_bufptr;
curval = tab->compress_curval;
npix = tab->compress_npix;
while (size--)
{
if (!(npix--))
{
if (curval != tab->compress_checkval)
error(EXIT_FAILURE, "*Error*: invalid PREV_PIX checksum in ",
tab->cat->filename);
bufdata = tab->compress_buf;
QFREAD(bufdata, FBSIZE, cat->file, cat->filename);
if (bswapflag)
swapbytes(bufdata, 2, 3);
curval = (int)*(short *)bufdata;
npix = (int)*(short *)(bufdata+=2)-1;
tab->compress_checkval = (int)(*(short *)(bufdata+=2));
bufdata+=4;
}
if ((dval=(int)*(bufdata++))==-128)
{
if (bswapflag)
swapbytes(bufdata, 2, 1);
memcpy(&val16, bufdata, 2);
curval = (int)val16;
bufdata += 2;
}
else
curval += dval;
*(ptr++) = curval*bs + bz;
}
tab->compress_curval = curval;
tab->compress_bufptr = bufdata;
tab->compress_npix = npix;
break;
default:
error(EXIT_FAILURE,"*Internal Error*: unknown compression mode in ",
"read_body()");
}
return;
}
/******* write_body ***********************************************************
PROTO write_body(tabstruct *tab, PIXTYPE *ptr, long size)
PURPOSE Write values to a FITS body.
INPUT A pointer to the tab structure,
a pointer to the array in memory,
the number of elements to be written.
OUTPUT -.
NOTES .
AUTHOR E. Bertin (IAP)
VERSION 29/06/2006
***/
void write_body(tabstruct *tab, PIXTYPE *ptr, size_t size)
{
catstruct *cat;
char *cbufdata0;
size_t i, bowl, spoonful;
PIXTYPE bs,bz;
bs = (PIXTYPE)tab->bscale;
bz = (PIXTYPE)tab->bzero;
cat = tab->cat;
if (!cat)
error(EXIT_FAILURE, "*Internal Error*: no parent cat structure for table ",
tab->extname);
cbufdata0 = (char *)bufdata0; /* A trick to remove gcc aliasing warnings */
switch(tab->compress_type)
{
/*-- Uncompressed image */
case COMPRESS_NONE:
bowl = DATA_BUFSIZE/tab->bytepix;
spoonful = size<bowl?size:bowl;
for(; size>0; size -= spoonful)
{
if (spoonful>size)
spoonful = size;
switch(tab->bitpix)
{
case BP_BYTE:
if (tab->bitsgn)
{
char *bufdata = (char *)cbufdata0;
for (i=spoonful; i--;)
*(bufdata++) = (char)((*(ptr++)-bz)/bs+0.49999);
}
else
{
unsigned char *bufdata = (unsigned char *)cbufdata0;
for (i=spoonful; i--;)
*(bufdata++) = (unsigned char)((*(ptr++)-bz)/bs+0.49999);;
}
break;
case BP_SHORT:
if (tab->bitsgn)
{
short *bufdata = (short *)cbufdata0;
for (i=spoonful; i--;)
*(bufdata++) = (short)((*(ptr++)-bz)/bs+0.49999);
}
else
{
unsigned short *bufdata = (unsigned short *)cbufdata0;
for (i=spoonful; i--;)
*(bufdata++) = (unsigned short)((*(ptr++)-bz)/bs+0.49999);
}
if (bswapflag)
swapbytes(cbufdata0, 2, spoonful);
break;
case BP_LONG:
if (tab->bitsgn)
{
int *bufdata = (int *)cbufdata0;
for (i=spoonful; i--;)
*(bufdata++) = (int)((*(ptr++)-bz)/bs+0.49999);
}
else
{
unsigned int *bufdata = (unsigned int *)cbufdata0;
for (i=spoonful; i--;)
*(bufdata++) = (unsigned int)((*(ptr++)-bz)/bs+0.49999);
}
if (bswapflag)
swapbytes(cbufdata0, 4, spoonful);
break;
case BP_FLOAT:
{
float *bufdata = (float *)cbufdata0;
for (i=spoonful; i--;)
*(bufdata++) = (*(ptr++)-bz)/bs;
if (bswapflag)
swapbytes(cbufdata0, 4, spoonful);
}
break;
case BP_DOUBLE:
{
double *bufdata = (double *)cbufdata0;
for (i=spoonful; i--;)
*(bufdata++) = (double)(*(ptr++)-bz)/bs;
if (bswapflag)
swapbytes(cbufdata0, 8, spoonful);
}
break;
default:
error(EXIT_FAILURE,"*FATAL ERROR*: unknown BITPIX type in ",
"read_body()");
break;
}
QFWRITE(cbufdata0, spoonful*tab->bytepix, cat->file, cat->filename);
}
break;
/*-- Compressed image */
case COMPRESS_BASEBYTE:
break;
case COMPRESS_PREVPIX:
break;
default:
error(EXIT_FAILURE,"*Internal Error*: unknown compression mode in ",
"read_body()");
}
return;
}
/******* set_maxram ***********************************************************
PROTO int set_maxram(size_t maxram)
PURPOSE Set the maximum amount of silicon memory that can be allocated for
storing FITS body data.
INPUT The maximum amount of RAM (in bytes).
OUTPUT RETURN_OK if within limits, RETURN_ERROR otherwise.
NOTES .
AUTHOR E. Bertin (IAP)
VERSION 19/12/99
***/
int set_maxram(size_t maxram)
{
if (maxram<1)
return RETURN_ERROR;
body_maxram = maxram;
return RETURN_OK;
}
/******* set_maxvram **********************************************************
PROTO int set_maxvram(size_t maxram)
PURPOSE Set the maximum amount of total virtual memory that can be used for
storing FITS body data.
INPUT The maximum amount of VRAM (in bytes).
OUTPUT RETURN_OK if within limits, RETURN_ERROR otherwise.
NOTES .
AUTHOR E. Bertin (IAP)
VERSION 08/02/2000
***/
int set_maxvram(size_t maxvram)
{
if (maxvram<1)
return RETURN_ERROR;
body_maxvram = maxvram;
return RETURN_OK;
}
/******* set_swapdir **********************************************************
PROTO int set_swapdir(char *dirname)
PURPOSE Set the path name of the directory that will be used for storing
memory swap files.
INPUT The pointer to the path string.
OUTPUT RETURN_OK if path appropriate, RETURN_ERROR otherwise.
NOTES .
AUTHOR E. Bertin (IAP)
VERSION 19/12/99
***/
int set_swapdir(char *dirname)
{
if (!dirname)
return RETURN_ERROR;
strcpy(body_swapdirname, dirname);
return RETURN_OK;
}
/*
fitscat.c
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* Part of: The LDAC Tools
*
* Author: E.BERTIN (IAP)
*
* Contents: low-level functions for handling LDAC FITS catalogs.
*
* Last modify: 25/09/2004
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include "fitscat_defs.h"
#include "fitscat.h"
/****** about_cat **************************************************************
PROTO int about_cat(catstruct *cat, FILE *stream)
PURPOSE Print some info about a catalog.
INPUT Catalog structure,
output stream.
OUTPUT RETURN_OK if everything went as expected, RETURN_ERROR otherwise.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 19/03/2002
***/
int about_cat(catstruct *cat, FILE *stream)
{
tabstruct *tab;
int i;
fprintf(stream,"\n");
/*General info about the catalog itself*/
fprintf(stream,
"------------------Catalog information----------------\n");
fprintf(stream,
"Filename:..............%s\n", cat->filename);
fprintf(stream,
"Number of segments:....%d\n", cat->ntab);
fprintf(stream,"\n");
/*Now for each table*/
tab = cat->tab;
for (i=0; i<cat->ntab; i++)
{
fprintf(stream,
"****** Table #%d\n", i+1);
fprintf(stream,
" Extension type:.........%s\n",
tab->xtension[0]? tab->xtension: "(Primary HDU)");
fprintf(stream,
" Extension name:.........%s\n", tab->extname);
if (tab->naxis)
{
fprintf(stream,
" Number of dimensions:...%d\n", tab->naxis);
fprintf(stream,
" Number of elements:.....%d\n", tab->naxisn[1]);
if (tab->tfields)
fprintf(stream,
" Number of data fields...%d\n", tab->tfields);
fprintf(stream,
" Body size:..............%ld bytes\n",
(unsigned long)tab->tabsize);
}
fprintf(stream,"\n");
while (!(tab=tab->nexttab)->nseg);
}
fprintf(stream,"\n");
return RETURN_OK;
}
/****** addhistoryto_cat *******************************************************
PROTO int addhistoryto_cat(catstruct *cat, char *str)
PURPOSE Add a HISTORY line to a FITS catalog.
INPUT A pointer to catalog structure, and the character string to insert.
OUTPUT RETURN_OK if everything went as expected, RETURN_ERROR otherwise.
NOTES The pointer to the primary header might be reallocated if necessary.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 25/09/2004
***/
int addhistoryto_cat(catstruct *cat, char *str)
{
time_t thetime;
char str2[82];
tabstruct *tab;
int n, headpos;
tab = cat->tab;
n = tab->headnblock;
headpos = fitsfind(tab->headbuf, "END ");
if (headpos >= n*(FBSIZE/80) - 1)
{
QREALLOC(tab->headbuf, char, (n+1)*FBSIZE);
memset(&tab->headbuf[n*FBSIZE], ' ', FBSIZE);
tab->headnblock++;
}
if (time(&thetime)==-1)
warning("No time available for history","");
if (!strftime(str2, 16, "%d/%m/%Y %H:%M", localtime(&thetime)))
error(EXIT_FAILURE, "*Internal Error*: Time/date string too long in ",
"addhistoryto_cat()");
sprintf(str2, "%s %.65s", str2, str);
fitsadd(tab->headbuf, "HISTORY ", str2);
return RETURN_OK;
}
/****** close_cat **************************************************************
PROTO int close_cat(catstruct *cat)
PURPOSE Close a FITS catalog.
INPUT catalog structure.
OUTPUT RETURN_OK if everything went as expected, RETURN_ERROR otherwise.
NOTES the file structure member is set to NULL;
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 22/06/2001
***/
int close_cat(catstruct *cat)
{
if (cat->file && fclose(cat->file))
{
cat->file = NULL;
return RETURN_ERROR;
}
cat->file = NULL;
return RETURN_OK;
}
/****** free_cat ***************************************************************
PROTO void free_cat(catstruct **cat, int ncat)
PURPOSE Free all structures allocated for one or several FITS catalog.
INPUT Pointer to a catalog structure,
Number of catalogs.
OUTPUT -.
NOTES Unallocated pointers should have been put to NULL.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 05/06/2001
***/
void free_cat(catstruct **cat, int ncat)
{
catstruct **thecat;
int i;
/*--free memory allocated within each catalog */
thecat = cat;
for (i=ncat; i--;)
{
if ((*thecat)->file)
close_cat(*thecat);
remove_tabs(*(thecat++));
}
free(*cat);
return;
}
/****** inherit_cat ************************************************************
PROTO int inherit_cat(catstruct *catin, catstruct *catout)
PURPOSE Copy the primary table, and all other informations from one catalog
to another, except those related to the associated file itself
(filename, etc...),
INPUT A pointer to both catalog structures.
OUTPUT RETURN_OK if at least one table was copied, RETURN_ERROR otherwise.
NOTES The output catalog should be ``cleaned'' before call.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 13/06/2002
***/
int inherit_cat(catstruct *catin, catstruct *catout)
{
tabstruct *tabin, *tabout, *prevtabout;
int j;
catout->ntab = 1;
tabin = catin->tab;
/*copy only one table: well it could be simpler, but let's stay general!*/
prevtabout = NULL;
for (j=tabin->nseg; j--;)
{
QCALLOC(tabout, tabstruct, 1);
*tabout = *tabin;
if (tabin->naxis)
QMEMCPY(tabin->naxisn, tabout->naxisn, int, (size_t)tabin->naxis);
if (tabin->headbuf)
QMEMCPY(tabin->headbuf, tabout->headbuf, char,
tabin->headnblock*FBSIZE);
if (tabin->bodybuf)
QMEMCPY(tabin->bodybuf, tabout->bodybuf, char, (size_t)tabin->tabsize);
if (prevtabout)
{
tabout->prevtab = prevtabout;
prevtabout->nexttab = tabout;
}
else
{
catout->tab = tabout;
}
prevtabout = tabout;
tabin = tabin->nexttab;
}
if (prevtabout)
{
prevtabout->nexttab = catout->tab;
catout->tab->prevtab = prevtabout;
}
else
return RETURN_ERROR;
return RETURN_OK;
}
/****** init_cat ***************************************************************
PROTO int init_cat(catstruct *cat)
PURPOSE Initialize a catalog, "cleaning" any content if present
and adding the primary header "table".
INPUT A pointer to the catalog structure.
OUTPUT RETURN_OK if everything went as expected, RETURN_ERROR otherwise.
NOTES The output catalog should be ``cleaned'' before call.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 28/05/2001
***/
int init_cat(catstruct *cat)
{
static char bintabtemplate[][80] = {
"SIMPLE = T / This is a FITS file",
"BITPIX = 8 / ",
"NAXIS = 0 / ",
"EXTEND = T / This file may contain FITS extensions",
"END "};
tabstruct *tab;
char *buf;
int i;
/* Initialize the primary header itself */
QCALLOC(tab, tabstruct, 1);
tab->naxis = 0;
tab->bitpix = 8;
tab->bytepix = 1;
tab->pcount = 0;
tab->gcount = 1;
tab->seg = 1;
tab->nseg = 1;
/* Provide a new header*/
QCALLOC(tab->headbuf, char, FBSIZE);
memcpy(tab->headbuf, bintabtemplate, sizeof(bintabtemplate));
for (buf = tab->headbuf, i=0; i<FBSIZE; i++, buf++)
if (!*buf)
*buf = ' ';
tab->headnblock = 1;
/* Clean catalog and add the table to it */
remove_tabs(cat);
cat->tab = tab->prevtab = tab->nexttab = tab;
cat->ntab = 1;
return RETURN_OK;
}
/****** map_cat ****************************************************************
PROTO int map_cat(catstruct *cat)
PURPOSE Explores the whole FITS file
and gets information for each of the FITS tables it contains.
INPUT catalog structure.
OUTPUT RETURN_OK if at least one table was found, RETURN_ERROR otherwise.
NOTES Memory space for the array of fits structures is reallocated.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 14/12/2002
***/
int map_cat(catstruct *cat)
{
int ntab;
tabstruct *tab, *prevtab;
/*scan through the file until we reach the end*/
prevtab = NULL;
QCALLOC(tab, tabstruct, 1);
tab->cat = cat;
QFTELL(cat->file, tab->headpos, cat->filename);
for (ntab=0; !get_head(tab); ntab++)
{
readbasic_head(tab);
readbintabparam_head(tab);
QFTELL(cat->file, tab->bodypos, cat->filename);
tab->nseg = tab->seg = 1;
if (tab->tabsize)
QFSEEK(cat->file, PADTOTAL(tab->tabsize), SEEK_CUR, cat->filename);
if (prevtab)
{
tab->prevtab = prevtab;
prevtab->nexttab = tab;
}
else
cat->tab = tab;
prevtab = tab;
QCALLOC(tab, tabstruct, 1);
tab->cat = cat;
QFTELL(cat->file, tab->headpos, cat->filename);
}
cat->ntab = ntab;
free(tab);
if (prevtab)
{
prevtab->nexttab = cat->tab;
cat->tab->prevtab = prevtab;
}
else
return RETURN_ERROR;
/*rewind to the beginning*/
/*
QFSEEK(cat->file, 0, SEEK_SET, cat->filename);
*/
return RETURN_OK;
}
/****** new_cat ****************************************************************
PROTO catstruct *new_cat(int ncat)
PURPOSE Initialize a structure for a FITS catalog.
INPUT Number of catalogs.
OUTPUT A pointer to the catalog array.
NOTES All fields are initialized to 0.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 20/03/96
***/
catstruct *new_cat(int ncat)
{
catstruct *cat;
QCALLOC(cat, catstruct, ncat);
cat->access_type = WRITE_ONLY;
return cat;
}
/****** open_cat ***************************************************************
PROTO int open_cat(catstruct *cat, access_type at)
PURPOSE Open a FITS catalog with name filename.
INPUT catalog structure,
access type (can be WRITE_ONLY or READ_ONLY).
OUTPUT RETURN_OK if the cat is found, RETURN_ERROR otherwise.
NOTES If the file was already opened by this catalog, nothing is done.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 13/06/2002
***/
int open_cat(catstruct *cat, access_type at)
{
if (cat->access_type == READ_ONLY && at == WRITE_ONLY)
error(EXIT_FAILURE, "*Internal Error*: Trying to write to the "
"READ_ONLY catalog ", cat->filename);
if (!cat->file)
{
if ((cat->file = fopen(cat->filename, at==WRITE_ONLY?"wb":"rb")) == NULL)
return RETURN_ERROR;
cat->access_type = at;
}
return RETURN_OK;
}
/*
fitscat.h
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* Part of: The LDAC Tools
*
* Author: E.BERTIN, DeNIS/LDAC
*
* Contents: Simplified versin of the LDACTools: main include file
*
* Last modify: 11/06/2007
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
#ifndef _FITSCAT_H_
#define _FITSCAT_H_
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#define MAXCHARS 256 /* max. number of characters */
#define WARNING_NMAX 100 /* max. number of recorded warnings */
/*---------------------------- return messages ------------------------------*/
#ifndef RETURN_OK
#define RETURN_OK 0
#endif
#ifndef RETURN_ERROR
#define RETURN_ERROR (-1)
#endif
#ifndef RETURN_FATAL_ERROR
#define RETURN_FATAL_ERROR (-2)
#endif
/*--------------------------- FITS BitPix coding ----------------------------*/
#define BP_BYTE 8
#define BP_SHORT 16
#define BP_LONG 32
#define BP_FLOAT (-32)
#define BP_DOUBLE (-64)
/*-------------------------------- macros -----------------------------------*/
/* Standard FITS name suffix*/
#define FITS_SUFFIX ".fits"
/* size (in bytes) of one FITS block */
#define FBSIZE 2880L
/* FITS size after adding padding */
#define PADTOTAL(x) (((x-1)/FBSIZE+1)*FBSIZE)
/* extra size to add for padding */
#define PADEXTRA(x) ((FBSIZE - (x%FBSIZE))% FBSIZE)
/*--------------------------------- typedefs --------------------------------*/
typedef enum {H_INT, H_FLOAT, H_EXPO, H_BOOL, H_STRING, H_STRINGS,
H_COMMENT, H_HCOMMENT, H_KEY} h_type;
/* type of FITS-header data */
typedef enum {T_BYTE, T_SHORT, T_LONG, T_FLOAT, T_DOUBLE, T_STRING}
t_type; /* Type of data */
typedef enum {WRITE_ONLY, READ_ONLY}
access_type; /* Type of access */
typedef enum {SHOW_ASCII, SHOW_SKYCAT}
output_type; /* Type of output */
typedef float PIXTYPE; /* Pixel type */
#ifdef HAVE_UNSIGNED_LONG_LONG
typedef unsigned long long KINGSIZE_T; /* for large sizes */
#else
typedef size_t KINGSIZE_T; /* better than nothing */
#endif
#ifdef HAVE_LONG_LONG
typedef long long KINGLONG; /* for large sizes */
#else
typedef long KINGLONG; /* better than nothing */
#endif
#if _FILE_OFFSET_BITS
#define OFF_T off_t
#else
#define OFF_T KINGLONG
#endif
/*------------------------------- constants ---------------------------------*/
extern const int t_size[]; /* size in bytes per t_type (see fitshead.c) */
/*---------------------------------- key ------------------------------------*/
typedef struct structkey
{
char name[80]; /* name */
char comment[80]; /* a comment */
void *ptr; /* pointer to the data */
h_type htype; /* standard ``h_type'' (display) */
t_type ttype; /* standard ``t_type'' (storage) */
char printf[80]; /* printing format (C Convention) */
char unit[80]; /* physical unit */
char voucd[80]; /* VO ucd */
char vounit[80]; /* VO unit */
int naxis; /* number of dimensions */
int *naxisn; /* pointer to an array of dim. */
int nobj; /* number of objects */
int nbytes; /* number of bytes per element */
long pos; /* position within file */
struct structkey *prevkey; /* previous key within the chain */
struct structkey *nextkey; /* next key within the chain */
struct structtab *tab; /* (original) parent tab */
int allocflag; /* true if ptr dynamically allocated */
} keystruct;
/*------------------------------- catalog ---------------------------------*/
typedef struct structcat
{
char filename[MAXCHARS]; /* file name */
FILE *file; /* pointer to the file structure */
struct structtab *tab; /* pointer to the first table */
int ntab; /* number of tables included */
access_type access_type; /* READ_ONLY or WRITE_ONLY */
} catstruct;
/*-------------------------------- table ----------------------------------*/
typedef struct structtab
{
int bitpix; /* bits per element */
int bytepix; /* bytes per element */
int bitsgn; /* = 0 if unsigned data */
double bscale; /* data scale factor */
double bzero; /* data offset parameter */
int blank; /* integer code for undefined values */
int blankflag; /* set if a blank keyword was found */
enum {COMPRESS_NONE, COMPRESS_BASEBYTE, COMPRESS_PREVPIX}
compress_type; /* image compression type */
char *compress_buf; /* de-compression buffer */
char *compress_bufptr; /* present pixel in buffer */
int compress_curval; /* current pixel or checksum value */
int compress_checkval; /* foreseen pixel or checksum value */
size_t compress_npix; /* remaining pixels in buffer */
int naxis; /* number of dimensions */
int *naxisn; /* array of dimensions */
int tfields; /* number of fields */
int pcount, gcount; /* alignment of the data */
KINGSIZE_T tabsize; /* total table size (bytes) */
char xtension[82]; /* FITS extension type */
char extname[82]; /* FITS extension name */
char *headbuf; /* buffer containing the header */
int headnblock; /* number of FITS blocks */
char *bodybuf; /* buffer containing the body */
OFF_T bodypos; /* position of the body in the file */
OFF_T headpos; /* position of the head in the file */
struct structcat *cat; /* (original) parent catalog */
struct structtab *prevtab, *nexttab; /* previous and next tab in chain */
int seg; /* segment position */
int nseg; /* number of tab segments */
keystruct *key; /* pointer to keys */
int nkey; /* number of keys */
int swapflag; /* mapped to a swap file ? */
char swapname[MAXCHARS]; /* name of the swapfile */
unsigned int bodysum; /* Checksum of the FITS body */
} tabstruct;
/*------------------------------- functions ---------------------------------*/
extern catstruct *new_cat(int ncat),
*read_cat(char *filename),
*read_cats(char **filenames, int ncat);
extern tabstruct *asc2bin_tab(catstruct *catin, char *tabinname,
catstruct *catout, char *taboutname),
*init_readobj(tabstruct *tab, char **pbuf),
*name_to_tab(catstruct *cat, char *tabname, int seg),
*new_tab(char *tabname),
*pos_to_tab(catstruct *cat, int pos, int seg);
extern keystruct *name_to_key(tabstruct *tab, char *keyname),
*new_key(char *keyname),
*pos_to_key(tabstruct *tab, int pos),
*read_key(tabstruct *tab, char *keyname);
extern void add_cleanupfilename(char *filename),
cleanup_files(void),
copy_tab_fromptr(tabstruct *tabin, catstruct *catout, int pos),
encode_checksum(unsigned int sum, char *str),
end_readobj(tabstruct *keytab, tabstruct *tab, char *buf),
end_writeobj(catstruct *cat, tabstruct *tab, char *buf),
error(int, char *, char *),
error_installfunc(void (*func)(char *msg1, char *msg2)),
fixexponent(char *s),
free_body(tabstruct *tab),
free_cat(catstruct **cat, int ncat),
free_key(keystruct *key),
free_tab(tabstruct *tab),
init_writeobj(catstruct *cat, tabstruct *tab, char **pbuf),
install_cleanup(void (*func)(void)),
print_obj(FILE *stream, tabstruct *tab),
read_keys(tabstruct *tab, char **keynames, keystruct **keys,
int nkeys, unsigned char *mask),
read_basic(tabstruct *tab),
read_body(tabstruct *tab, PIXTYPE *ptr, size_t size),
readbasic_head(tabstruct *tab),
remove_cleanupfilename(char *filename),
save_cat(catstruct *cat, char *filename),
save_tab(catstruct *cat, tabstruct *tab),
show_keys(tabstruct *tab, char **keynames, keystruct **keys,
int nkeys, unsigned char *mask, FILE *stream,
int strflag,int banflag, int leadflag,
output_type o_type),
swapbytes(void *, int, int),
ttypeconv(void *ptrin, void *ptrout,
t_type ttypein, t_type ttypeout),
voprint_obj(FILE *stream, tabstruct *tab),
warning(char *, char *),
write_body(tabstruct *tab, PIXTYPE *ptr, size_t size),
write_checksum(tabstruct *tab);
extern char *tdisptoprintf(char *tdisp, char *str),
*printftotdisp(char *cprintf, char *str),
*fitsnfind(char *fitsbuf, char *str, int nblock),
**tabs_list(catstruct *cat, int *n),
**keys_list(tabstruct *tab, int *n),
*warning_history(void);
extern unsigned int
compute_blocksum(char *buf, unsigned int sum),
compute_bodysum(tabstruct *tab, unsigned int sum),
decode_checksum(char *str);
extern int about_cat(catstruct *cat, FILE *stream),
about_tab(catstruct *cat, char *tabname, FILE *stream),
addhistoryto_cat(catstruct *cat, char *str),
add_key(keystruct *key, tabstruct *tab, int pos),
addkeyto_head(tabstruct *tab, keystruct *key),
addkeywordto_head(tabstruct *tab, char *keyword,char *comment),
add_tab(tabstruct *tab, catstruct *cat, int pos),
blank_keys(tabstruct *tab),
close_cat(catstruct *cat),
copy_key(tabstruct *tabin, char *keyname, tabstruct *tabout,
int pos),
copy_tab(catstruct *catin, char *tabname, int seg,
catstruct *catout, int pos),
copy_tabs(catstruct *catin, catstruct *catout),
copy_tabs_blind(catstruct *catin, catstruct *catout),
ext_head(tabstruct *tab),
findkey(char *, char *, int),
findnkey(char *, char *, int, int),
fitsadd(char *fitsbuf, char *keyword, char *comment),
fitsfind(char *fitsbuf, char *keyword),
fitspick(char *fitsbuf, char *keyword, void *ptr,
h_type *htype, t_type *ttype, char *comment),
fitsread(char *fitsbuf, char *keyword, void *ptr,
h_type htype, t_type ttype),
fitsremove(char *fitsbuf, char *keyword),
fitswrite(char *fitsbuf, char *keyword, void *ptr,
h_type htype, t_type ttype),
get_head(tabstruct *tab),
inherit_cat(catstruct *catin, catstruct *catout),
init_cat(catstruct *cat),
map_cat(catstruct *cat),
open_cat(catstruct *cat, access_type at),
pad_tab(catstruct *cat, KINGSIZE_T size),
prim_head(tabstruct *tab),
readbintabparam_head(tabstruct *tab),
read_field(tabstruct *tab, char **keynames, keystruct **keys,
int nkeys, int field, tabstruct *ftab),
read_obj(tabstruct *keytab, tabstruct *tab, char *buf),
read_obj_at(tabstruct *keytab, tabstruct *tab, char *buf,
long pos),
remove_key(tabstruct *tab, char *keyname),
remove_keys(tabstruct *tab),
removekeywordfrom_head(tabstruct *tab, char *keyword),
remove_tab(catstruct *cat, char *tabname, int seg),
remove_tabs(catstruct *cat),
save_head(catstruct *cat, tabstruct *tab),
set_maxram(size_t maxram),
set_maxvram(size_t maxvram),
set_swapdir(char *dirname),
tab_row_len(char *, char *),
tformof(char *str, t_type ttype, int n),
tsizeof(char *str),
update_head(tabstruct *tab),
update_tab(tabstruct *tab),
verify_checksum(tabstruct *tab),
write_obj(tabstruct *tab, char *buf),
wstrncmp(char *, char *, int);
extern PIXTYPE *alloc_body(tabstruct *tab,
void (*func)(PIXTYPE *ptr, int npix));
extern t_type ttypeof(char *str);
extern void error(int, char *, char *),
swapbytes(void *ptr, int nb, int n),
warning(char *msg1, char *msg2);
int bswapflag;
#endif
/*
fitscat_defs.h
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* Part of: The LDAC Tools
*
* Author: E.BERTIN, DeNIS/LDAC
*
* Contents: Simplified version of the LDACTools: internal defs
*
* Last modify: 16/08/2004
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
/* Check if we are using a configure script here */
#ifndef HAVE_CONFIG_H
#define VERSION "2.0"
#define DATE "2003-x-x"
#define HAVE_SYS_MMAN_H 1
#endif
/*------------------------ what, who, when and where ------------------------*/
#define BANNER "LDACTools"
#define COPYRIGHT "Emmanuel BERTIN (bertin@iap.fr)"
#define INSTITUTE "IAP/Leiden"
/*----------------------------- External constants --------------------------*/
extern int bswapflag; /* != 0 if bytes are swapped/IEEE */
/*----------------------------- Internal constants --------------------------*/
#define OUTPUT stdout /* where all msgs are sent */
#define KBYTE 1024 /* 1 kbyte! */
#define MBYTE (1024*KBYTE) /* 1 Mbyte! */
#define GBYTE (1024*MBYTE) /* 1 Gbyte! */
#define DATA_BUFSIZE (4*MBYTE) /* data buffer size for I/O's */
#define BODY_DEFRAM (256*MBYTE) /* a fair number by 1999 standards */
#define BODY_DEFVRAM (1.9*GBYTE) /* a fair number by 1999 standards */
#define BODY_DEFSWAPDIR "/tmp" /* OK at least for Unix systems */
#define BIG 1e+30 /* a huge number */
#ifndef PI
#define PI 3.14159265359 /* never met before? */
#endif
/* NOTES:
We must have: MAXCHARS >= 16
DATA_BUFSIZE >= 2 although DATA_BUFSIZE >= 100000
is better!!
*/
/*--------------------- in case of missing constants ------------------------*/
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
#ifndef SEEK_CUR
#define SEEK_CUR 1
#endif
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif
#ifndef EXIT_FAILURE
#define EXIT_FAILURE -1
#endif
/*--------------------------------- typedefs --------------------------------*/
typedef unsigned char BYTE; /* a byte */
typedef int LONG; /* for DEC-Alpha... */
/*------------------------------- Other Macros -----------------------------*/
#if _LARGEFILE_SOURCE
#define FSEEKO fseeko
#define FTELLO ftello
#else
#define FSEEKO fseek
#define FTELLO ftell
#endif
#define QFREAD(ptr, size, file, fname) \
{if (fread(ptr, (size_t)(size), (size_t)1, file)!=1) \
error(EXIT_FAILURE, "*Error* while reading ", fname);;}
#define QFWRITE(ptr, size, file, fname) \
{if (fwrite(ptr, (size_t)(size), (size_t)1, file)!=1) \
error(EXIT_FAILURE, "*Error* while writing ", fname);;}
#define QFSEEK(file, offset, pos, fname) \
{if (FSEEKO(file, offset, pos)) \
error(EXIT_FAILURE,"*Error*: File positioning failed in ", \
fname);;}
#define QFTELL(file, pos, fname) \
{if ((pos=FTELLO(file))==-1) \
error(EXIT_FAILURE,"*Error*: File position unknown in ", \
fname);;}
#define QFREE(x) {free(x); x = NULL;}
#define QCALLOC(ptr, typ, nel) \
{if (!(ptr = (typ *)calloc((size_t)(nel),sizeof(typ)))) \
error(EXIT_FAILURE, "Not enough memory for ", \
#ptr " (" #nel " elements) !");;}
#define QMALLOC(ptr, typ, nel) \
{if (!(ptr = (typ *)malloc((size_t)(nel)*sizeof(typ)))) \
error(EXIT_FAILURE, "Not enough memory for ", \
#ptr " (" #nel " elements) !");;}
#define QMEMCPY(ptrin, ptrout, typ, nel) \
{if (!(ptrout = (typ *)malloc((size_t)(nel)*sizeof(typ)))) \
error(EXIT_FAILURE, "Not enough memory for ", \
#ptrout " (" #nel " elements) !"); \
memcpy(ptrout, ptrin, (size_t)(nel)*sizeof(typ));}
#define QREALLOC(ptr, typ, nel) \
{if (!(ptr = (typ *)realloc(ptr, (size_t)(nel)*sizeof(typ)))) \
error(EXIT_FAILURE, "Not enough memory for ", \
#ptr " (" #nel " elements) !");;}
#define RINT(x) (int)(floor(x+0.5))
#define QPRINTF if (qflag) fprintf
#define QFPRINTF(w,x) {if (qflag) \
fprintf(w, "\33[1M> %s\n\33[1A",x);;}
#define QGETKEY(tab, key, keyname, dest) \
{if (!(key = name_to_key(tab, keyname))) \
error(EXIT_FAILURE, "*Error*: No such parameter in catalog: ", \
keyname); \
dest = key->ptr;}
#define MIN(a,b) (a<b?a:b)
/*
fitscheck.c
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* Part of: The LDAC Tools
*
* Author: E.BERTIN (IAP)
*
* Contents: Functions related to file integrity
*
* Last modify: 15/08/2003
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fitscat_defs.h"
#include "fitscat.h"
#define ENCODE_OFFSET 0x30
unsigned int exclude[13] = {0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60};
/****** encode_checksum *****************************************************
PROTO void encode_checksum(unsigned int sum, char *str)
PURPOSE Encode a checksum to ASCII
INPUT Checksum,
Destination string.
OUTPUT -.
NOTES Straightforward copy of Seaman & Pence 1995
(ftp://iraf.noao.edu/misc/checksum/).
AUTHOR E. Bertin (IAP)
VERSION 08/05/2001
***/
void encode_checksum(unsigned int sum, char *str)
{
int ch[4],
i,j,k, byte, check;
for (i=0; i<4; i++)
{
/*-- Each byte becomes four */
byte = (sum << 8*i) >> 24;
ch[0] = (ch[1] = ch[2] = ch[3] = byte/4 + ENCODE_OFFSET) + (byte%4);
for (check=1; check;) /* avoid ASCII punctuation */
for (check=k=0; k<13; k++)
{
if (ch[0]==exclude[k] || ch[1]==exclude[k])
{
ch[0]++;
ch[1]--;
check++;
}
if (ch[2]==exclude[k] || ch[3]==exclude[k])
{
ch[2]++;
ch[3]--;
check++;
}
}
for (j=0; j<4; j++) /* assign the bytes */
str[(4*j+i+1)%16] = ch[j]; /* permute the bytes for FITS */
}
str[16] = 0;
return;
}
/****** decode_checksum *****************************************************
PROTO unsigned int decode_checksum(char *str)
PURPOSE Decode an ASCII checksum
INPUT Checksum string.
OUTPUT Checksum.
NOTES Straightforward copy of Seaman & Pence 1995
(ftp://iraf.noao.edu/misc/checksum/).
AUTHOR E. Bertin (IAP)
VERSION 08/05/2001
***/
unsigned int decode_checksum(char *str)
{
char cbuf[16];
unsigned short *sbuf,
los,his;
unsigned int hi,lo, hicarry,locarry;
int i;
/* Remove the permuted FITS byte alignment and the ASCII 0 offset */
for (i=0; i<16; i++)
cbuf[i] = str[(i+1)%16] - 0x30;
sbuf = (unsigned short *)cbuf;
hi = lo = 0;
if (bswapflag)
for (i=4; i--;)
{
his = *(sbuf++);
los = *(sbuf++);
hi += (*((unsigned char *)&his)<<8) + *((unsigned char *)&his+1);
lo += (*((unsigned char *)&los)<<8) + *((unsigned char *)&los+1);
}
else
for (i=4; i--;)
{
hi += *(sbuf++);
lo += *(sbuf++);
}
hicarry = hi>>16;
locarry = lo>>16;
while (hicarry || locarry)
{
hi = (hi & 0xffff) + locarry;
lo = (lo & 0xffff) + hicarry;
hicarry = hi >> 16;
locarry = lo >> 16;
}
return (hi<<16) + lo;
}
/****** compute_blocksum *****************************************************
PROTO unsigned int compute_blocksum(char *buf, unsigned int sum)
PURPOSE Compute the checksum of a FITS block (2880 bytes)
INPUT Pointer to the block,
The previous checksum.
OUTPUT The new computed checksum.
NOTES From Seaman & Pence 1995 (ftp://iraf.noao.edu/misc/checksum/). But
contrarily to what is stated by the authors, the original algorithm
depends on the endianity of the machine. The routine below adds
support for ix386-like processors (non-IEEE).
AUTHOR E. Bertin (IAP)
VERSION 08/05/2001
***/
unsigned int compute_blocksum(char *buf, unsigned int sum)
{
unsigned short *sbuf,
his,los;
unsigned int hi,lo, hicarry,locarry;
int i;
sbuf = (unsigned short *)buf;
hi = (sum >> 16);
lo = (sum << 16) >> 16;
if (bswapflag)
for (i=FBSIZE/4; i--;)
{
his = *(sbuf++);
los = *(sbuf++);
hi += (*((unsigned char *)&his)<<8) + *((unsigned char *)&his+1);
lo += (*((unsigned char *)&los)<<8) + *((unsigned char *)&los+1);
}
else
for (i=FBSIZE/4; i--;)
{
hi += *(sbuf++);
lo += *(sbuf++);
}
hicarry = hi>>16; /* fold carry bits in */
locarry = lo>>16;
while (hicarry || locarry)
{
hi = (hi & 0xFFFF) + locarry;
lo = (lo & 0xFFFF) + hicarry;
hicarry = hi >> 16;
locarry = lo >> 16;
}
return (hi << 16) + lo;
}
/****** compute_bodysum *****************************************************
PROTO unsigned int compute_bodysum(tabstruct *tab, unsigned int sum)
PURPOSE Compute the checksum of a FITS body
INPUT Pointer to the tab,
Checksum from a previous iteration.
OUTPUT The computed checksum.
NOTES -.
AUTHOR E. Bertin (IAP)
VERSION 15/08/2003
***/
unsigned int compute_bodysum(tabstruct *tab, unsigned int sum)
{
catstruct *cat;
char *buf;
KINGSIZE_T size;
int n, nblock;
/* FITS data are generally padded */
nblock = (tab->tabsize+FBSIZE-1)/FBSIZE;
/* 2 cases: either the data are in memory or still on disk */
if (tab->bodybuf)
{
/*-- In memory: they are probably not padded */
buf = (char *)tab->bodybuf;
for (n=nblock-1; n--; buf+=FBSIZE)
sum = compute_blocksum(buf, sum);
if ((size=PADEXTRA(tab->tabsize)))
{
QCALLOC(buf, char, FBSIZE);
size = FBSIZE-size;
memcpy(buf, (char *)tab->bodybuf+tab->tabsize-size, size);
sum = compute_blocksum(buf, sum);
free(buf);
}
}
else
{
/*-- On disk: they are padded */
/*-- We open the file (nothing is done if already open) */
if (!(cat=tab->cat))
{
warning("Cannot access file while computing the checksum in HDU ",
tab->extname);
return 0;
}
open_cat(cat, READ_ONLY);
QFSEEK(cat->file, tab->bodypos, SEEK_SET, cat->filename);
QMALLOC(buf, char, FBSIZE);
for (n=nblock; n--;)
{
QFREAD(buf, FBSIZE, cat->file, cat->filename);
/*---- No need to swap bytes */
sum = compute_blocksum(buf, sum);
}
}
return sum;
}
/****** write_checksum *****************************************************
PROTO void write_checksum(tabstruct *tab)
PURPOSE Compute and write the checksum to a FITS table
INPUT Pointer to the tab.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP)
VERSION 04/06/2001
***/
void write_checksum(tabstruct *tab)
{
char str[32],
*buf;
unsigned int sum;
int i;
/* Keep some margin */
QREALLOC(tab->headbuf, char, 80*(tab->headnblock*36+3));
/* Add or update keywords in the header */
fitsadd(tab->headbuf, "CHECKSUM", "ASCII 1's complement checksum");
fitswrite(tab->headbuf, "CHECKSUM", "0000000000000000",
H_STRING, T_STRING);
fitsadd(tab->headbuf, "DATASUM ", "Checksum of data records");
fitswrite(tab->headbuf, "DATASUM ", "0", H_STRING, T_STRING);
fitsadd(tab->headbuf, "CHECKVER", "Checksum version ID");
fitswrite(tab->headbuf, "CHECKVER", "COMPLEMENT", H_STRING, T_STRING);
/* Keep only what's necessary */
tab->headnblock = ((fitsfind(tab->headbuf, "END ")+36)*80)/FBSIZE;
QREALLOC(tab->headbuf, char, tab->headnblock*FBSIZE);
/* First: the data */
tab->bodysum = sum = compute_bodysum(tab, 0);
sprintf(str, "%u", sum);
fitswrite(tab->headbuf, "DATASUM ", str, H_STRING, T_STRING);
/* Now the header */
buf = tab->headbuf;
for (i=tab->headnblock; i--; buf+=FBSIZE)
sum = compute_blocksum(buf, sum);
/* Complement to 1 */
encode_checksum(~sum, str);
fitswrite(tab->headbuf, "CHECKSUM", str, H_STRING, T_STRING);
return;
}
/****** verify_checksum *****************************************************
PROTO int verify_checksum(tabstruct *tab)
PURPOSE Compute and check the checksum of a FITS table
INPUT Pointer to the tab.
OUTPUT RETURN_OK if the checksum is correct, RETURN_ERROR if it is
incorrect, or RETURN_FATAL_ERROR if no checksum found.
NOTES -.
AUTHOR E. Bertin (IAP)
VERSION 07/05/2001
***/
int verify_checksum(tabstruct *tab)
{
char *buf;
unsigned int sum;
int i;
if (fitsfind(tab->headbuf, "CHECKSUM")==RETURN_ERROR)
return RETURN_FATAL_ERROR;
/* First: the data */
sum = compute_bodysum(tab, 0);
/* Now the header */
buf = tab->headbuf;
for (i=tab->headnblock; i--; buf+=FBSIZE)
sum = compute_blocksum(buf, sum);
/* The result should sum to 0 */
sum = ~sum;
return sum? RETURN_ERROR : RETURN_OK;
}
/*
fitscleanup.c
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* Part of: The LDAC Tools
*
* Author: E.BERTIN (IAP)
*
* Contents: Signal-catching routines to clean-up temporary files
*
* Last modify: 10/01/2003
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fitscat_defs.h"
#include "fitscat.h"
#define CLEANUP_NFILES 64
void (*exit_func)(void);
char **cleanup_filename;
int cleanup_nfiles;
/****** cleanup_files ********************************************************
PROTO void cleanup_files(void)
PURPOSE Remove temporary files on exit.
INPUT -.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP)
VERSION 25/04/2002
***/
void cleanup_files(void)
{
char **filename;
int i;
filename = cleanup_filename;
for (i=cleanup_nfiles; i--;)
{
remove(*filename);
free(*(filename++));
}
if (cleanup_nfiles)
{
free(cleanup_filename);
cleanup_nfiles = 0;
}
return;
}
/****** add_cleanupfilename **************************************************
PROTO void add_cleanupfilename(char *filename)
PURPOSE Add a file name to the list of files to be cleaned up at exit.
INPUT pointer to filename char string.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP)
VERSION 10/01/2003
***/
void add_cleanupfilename(char *filename)
{
if (!cleanup_nfiles)
{
QMALLOC(cleanup_filename, char *, CLEANUP_NFILES);
}
else if (!(cleanup_nfiles%CLEANUP_NFILES))
{
QREALLOC(cleanup_filename, char *, cleanup_nfiles+CLEANUP_NFILES);
}
QMALLOC(cleanup_filename[cleanup_nfiles], char, MAXCHARS);
strcpy(cleanup_filename[cleanup_nfiles++], filename);
return;
}
/****** remove_cleanupfilename ***********************************************
PROTO void remove_cleanupfilename(char *filename)
PURPOSE remove a file name from the list of files to be cleaned up at exit.
INPUT pointer to filename char string.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP)
VERSION 21/08/2000
***/
void remove_cleanupfilename(char *filename)
{
char **filename2, **filename3;
int i, j;
if (!cleanup_nfiles)
return;
/* Search the cleanup filename list for a match */
filename2 = cleanup_filename;
for (i=cleanup_nfiles; i--;)
if (!strcmp(filename, *(filename2++)))
{
/* Match found: update the list and free memory is necessary*/
filename3 = filename2 - 1;
for (j=i; j--;)
*(filename3++) = *(filename2++);
if (!((--cleanup_nfiles)%CLEANUP_NFILES))
{
if (cleanup_nfiles)
{
filename2 = cleanup_filename + cleanup_nfiles;
for (i=CLEANUP_NFILES; i--;)
free(*(filename2++));
QREALLOC(cleanup_filename, char *, cleanup_nfiles);
}
else
{
free(*cleanup_filename);
free(cleanup_filename);
}
}
break;
}
return;
}
/****** install_cleanup ******************************************************
PROTO void install_cleanup(void (*func)(void))
PURPOSE Install the signal-catching and exit routines to start cleanup_files().
INPUT A pointer to a function to be executed on exit.
OUTPUT -.
NOTES Catches everything except STOP and KILL signals.
AUTHOR E. Bertin (IAP)
VERSION 25/04/2002
***/
void install_cleanup(void (*func)(void))
{
void signal_function(int signum);
exit_func = func;
atexit(cleanup_files);
/* Catch CTRL-Cs */
signal(SIGINT, signal_function);
/* Catch bus errors */
signal(SIGBUS, signal_function);
/* Catch segmentation faults */
signal(SIGSEGV, signal_function);
/* Catch floating exceptions */
signal(SIGFPE, signal_function);
return;
}
/****** signal_function ******************************************************
PROTO void signal_function(void)
PURPOSE The routine called when a signal is catched. Clean up temporary files
and execute a user-provided function.
INPUT signal number.
OUTPUT -.
NOTES .
AUTHOR E. Bertin (IAP)
VERSION 25/04/2002
***/
void signal_function(int signum)
{
cleanup_files();
if (exit_func)
exit_func();
switch(signum)
{
case SIGINT:
fprintf(stderr, "^C\n");
exit(-1);
case SIGBUS:
fprintf(stderr, "bus error\n");
exit(-1);
case SIGSEGV:
fprintf(stderr, "segmentation fault\n");
exit(-1);
case SIGFPE:
fprintf(stderr, "floating exception\n");
exit(-1);
default:
exit(-1);
}
return;
}
/*
fitsconv.c
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* Part of: The LDAC Tools
*
* Author: E.BERTIN, DeNIS/LDAC
*
* Contents: functions for converting LDAC FITS catalogs.
*
* Last modify: 25/09/2004
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fitscat_defs.h"
#include "fitscat.h"
/****** asc2bin_tab ***********************************************************
PROTO tabstruct *asc2bin_tab(catstruct *catin, char *tabinname,
catstruct *catout, char *taboutname)
PURPOSE Convert an ASCII table to a BINARY table
which is then stored in a destination catalog.
INPUT Pointer to the input catalog,
Name of the input ASCII table,
Pointer to the output catalog,
Name of the output binary table.
OUTPUT RETURN_OK if the ASCII table was transformed, and RETURN_ERROR
otherwise.
NOTES This function can be used to stick the binary translation of
similar ASCII tables.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 25/09/2004
***/
tabstruct *asc2bin_tab(catstruct *catin, char *tabinname, catstruct *catout,
char *taboutname)
{
catstruct *tabcat;
keystruct *key;
tabstruct *tabin,*tabout;
char comment[82], keyword[16], ptr[82];
h_type htype;
t_type ttype;
char *buf, *lptr;
int i;
/*Convert the table name to a pointer*/
if (!(tabin = name_to_tab(catin, tabinname, 0)))
return NULL;
/*Get the original catalog*/
tabcat = tabin->cat;
/*Create a new binary table*/
tabout = new_tab(taboutname);
/*Alloc. mem. for the whole ASCII table at once (should not be very large)*/
QMALLOC(buf, char, tabin->tabsize);
/*Now read all the elements from the original table*/
if (open_cat(tabcat, READ_ONLY) != RETURN_OK)
error(EXIT_FAILURE, "*Error*: Cannot access ", tabcat->filename);
QFSEEK(tabcat->file, tabin->bodypos, SEEK_SET, tabcat->filename);
QFREAD(buf, tabin->tabsize, tabcat->file, tabcat->filename);
if (close_cat(tabcat) != RETURN_OK)
error(EXIT_FAILURE, "*Error*: Problem while closing", tabcat->filename);
lptr = buf;
for (i=tabin->tabsize/80; i-- && strncmp(lptr, "END ", 8);)
{
/*Interprete the next FITS line */
if (fitspick(lptr, keyword, ptr, &htype, &ttype, comment) != RETURN_OK) {
char line[81];
int qflag=1;
strncpy(line, lptr, 80);
line[80] = '\0';
QFPRINTF(OUTPUT, line);
warning("*Warning*: incorrect FITS field will be ignored in ",
tabcat->filename);
}
if (htype != H_COMMENT)
{
/*----Create a new key and fill it with the right parameters*/
key = new_key(keyword);
strcpy(key->comment, comment+strspn(comment, " "));
key->htype = htype;
key->ttype = ttype;
key->nbytes = t_size[ttype];
/*----!!Temporary (?) solution for STRINGS*/
if (htype==H_STRING)
{
key->naxis = 1;
QMALLOC(key->naxisn, int, 1);
key->naxisn[0] = 32;
key->nbytes *= key->naxisn[0];
}
key->nobj = 1;
/*----Allocate memory and copy data in the same time*/
QMEMCPY(ptr, key->ptr, char, key->nbytes);
if (add_key(key, tabout, 0)==RETURN_ERROR)
{
sprintf(comment, "%s keyword found twice in ",
keyword);
warning(comment, tabcat->filename);
}
}
lptr += 80;
}
free(buf);
update_tab(tabout);
return tabout;
}
/****** ttypeconv ************************************************************
PROTO void ttypeconv(void *ptrin, void *ptrout,
t_type ttypein, t_type ttypeout)
PURPOSE Convert data from one type to another.
INPUT Pointer to element to convert,
destination pointer to the converted element,
t_type of the element to convert,
t_type of the converted element.
OUTPUT -.
NOTES ttypeconv does not yet handle arrays.
AUTHOR E. Bertin (IAP)
VERSION 25/09/2004
***/
void ttypeconv(void *ptrin, void *ptrout, t_type ttypein, t_type ttypeout)
{
union {char tbyte; short tshort; int tlong; float tfloat;
double tdouble; char tstring;} ival;
#define OUTCONV(x, y) \
switch(y) \
{ \
case T_BYTE: \
case T_STRING: \
*((char *)ptrout) = (char)x; \
break; \
case T_SHORT: \
*((short *)ptrout) = (short)x; \
break; \
case T_LONG: \
*((int *)ptrout) = (int)x; \
break; \
case T_FLOAT: \
*((float *)ptrout) = (float)x; \
break; \
case T_DOUBLE: \
*((double *)ptrout) = (double)x; \
break; \
default: \
break; \
}
switch(ttypein)
{
case T_BYTE:
case T_STRING:
ival.tbyte = *(char *)ptrin;
OUTCONV(ival.tbyte, ttypeout);
break;
case T_SHORT:
ival.tshort = *(short *)ptrin;
OUTCONV(ival.tshort, ttypeout);
break;
case T_LONG:
ival.tlong = *(int *)ptrin;
OUTCONV(ival.tlong, ttypeout);
break;
case T_FLOAT:
ival.tfloat = *(float *)ptrin;
OUTCONV(ival.tfloat, ttypeout);
break;
case T_DOUBLE:
ival.tdouble = *(double *)ptrin;
OUTCONV(ival.tdouble, ttypeout);
break;
default:
break;
}
return;
}
/*
fitshead.c
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* Part of: The LDAC Tools
*
* Author: E.BERTIN, DeNIS/LDAC
*
* Contents: general functions for handling FITS file headers.
*
* Last modify: 20/06/2007
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fitscat_defs.h"
#include "fitscat.h"
extern char histokeys[][12];
const int t_size[] = {1, 2, 4, 4, 8, 1}; /* size in bytes per t_type */
/******* get_head *************************************************************
PROTO int get_head(tabstruct *tab)
PURPOSE Read a FITS header.
INPUT Table structure.
OUTPUT RETURN_OK if a FITS header has been found and loaded, or RETURN_ERROR
otherwise.
NOTES The file must be opened, and the file pointer must be located at
the beginning of a header.
The headbuf pointer in the catstruct is reallocated.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 08/02/96
***/
int get_head(tabstruct *tab)
{
catstruct *cat;
int i;
char *buf;
buf = tab->headbuf;
if (!(cat = tab->cat))
error(EXIT_FAILURE, "*Internal Error*: Table has no parent catalog","!");
QFREE(buf);
QMALLOC(buf, char, FBSIZE);
/*Read the first block and check that it is FITS */
if (!fread(buf, FBSIZE, 1, cat->file))
{
QFREE(buf);
return RETURN_ERROR;
}
if (strncmp(buf, "SIMPLE ", 8) && strncmp(buf, "XTENSION", 8))
{
QFREE(buf);
return RETURN_ERROR;
}
/*Find the number of FITS blocks of the header while reading it */
for (i=1; !fitsnfind(buf,"END ", i); i++)
{
QREALLOC(buf, char, FBSIZE*(i+1));
QFREAD(&buf[FBSIZE*i], FBSIZE, cat->file, cat->filename);
}
tab->headnblock = i;
tab->headbuf = buf;
return RETURN_OK;
}
/****** readbasic_head ********************************************************
PROTO void readbasic_head(tabstruct *tab)
PURPOSE Read the current FITS header basic keywords.
INPUT pointer to catstruct.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP)
VERSION 25/09/2004
***/
void readbasic_head(tabstruct *tab)
{
char str[88];
char key[12], name[16],
*filename;
int i;
KINGSIZE_T tabsize;
filename = (tab->cat? tab->cat->filename : strcpy(name, "internal header"));
if (fitsread(tab->headbuf, "BITPIX ", &tab->bitpix, H_INT, T_LONG)
==RETURN_ERROR)
error(EXIT_FAILURE, "*Error*: Corrupted FITS header in ", filename);
tab->bytepix = tab->bitpix>0?(tab->bitpix/8):(-tab->bitpix/8);
if (fitsread(tab->headbuf, "NAXIS ", &tab->naxis, H_INT, T_LONG)
==RETURN_ERROR)
error(EXIT_FAILURE, "*Error*: Corrupted FITS header in ", filename);
tabsize = 0;
if (tab->naxis>0)
{
QFREE(tab->naxisn);
QMALLOC(tab->naxisn, int, tab->naxis);
/*--get the size of the array*/
tabsize = 1;
for (i=0; i<tab->naxis && i<999; i++)
{
sprintf(key,"NAXIS%-3d", i+1);
if (fitsread(tab->headbuf, key, &tab->naxisn[i], H_INT, T_LONG)
==RETURN_ERROR)
error(EXIT_FAILURE, "*Error*: incoherent FITS header in ", filename);
tabsize *= tab->naxisn[i];
}
}
/*random groups parameters (optional)*/
tab->pcount = 0;
fitsread(tab->headbuf, "PCOUNT ", &tab->pcount, H_INT, T_LONG);
tab->gcount = 1;
fitsread(tab->headbuf, "GCOUNT ", &tab->gcount, H_INT, T_LONG);
/*number of fields (only for tables)*/
tab->tfields = 0;
fitsread(tab->headbuf, "TFIELDS ", &tab->tfields, H_INT, T_LONG);
/*in case of a non-primary header*/
tab->xtension[0] = (char)'\0';
fitsread(tab->headbuf, "XTENSION", tab->xtension, H_STRING, T_STRING);
tab->extname[0] = (char)'\0';
fitsread(tab->headbuf, "EXTNAME ", tab->extname, H_STRING, T_STRING);
tab->tabsize = tab->bytepix*tab->gcount*((size_t)tab->pcount+tabsize);
/* Scaling parameters for basic FITS integer arrays */
tab->bscale = 1.0;
fitsread(tab->headbuf, "BSCALE ", &tab->bscale, H_FLOAT, T_DOUBLE);
tab->bzero = 0.0;
fitsread(tab->headbuf, "BZERO ", &tab->bzero, H_FLOAT, T_DOUBLE);
tab->blankflag =
(fitsread(tab->headbuf,"BLANK ",&tab->blank,H_INT,T_LONG) == RETURN_OK)?
1 : 0;
/* Custom basic FITS parameters */
tab->bitsgn = 1;
fitsread(tab->headbuf, "BITSGN ", &tab->bitsgn, H_INT, T_LONG);
if (fitsread(tab->headbuf, "IMAGECOD", str, H_STRING, T_STRING)==RETURN_OK)
{
if (!strcmp(str, "NONE"))
tab->compress_type = COMPRESS_NONE;
else if (!strcmp(str, "BASEBYTE"))
tab->compress_type = COMPRESS_BASEBYTE;
else if (!strcmp(str, "PREV_PIX"))
tab->compress_type = COMPRESS_PREVPIX;
else
warning("Compression skipped: unknown IMAGECOD parameter:", str);
}
/* Checksum */
if (fitsread(tab->headbuf, "DATASUM ", str, H_STRING, T_STRING)==RETURN_OK)
tab->bodysum = (unsigned int)atoi(str);
return;
}
/******* readbintabparam_head *************************************************
PROTO int readbintabparam_head(tabstruct *tab)
PURPOSE Read the current FITS header parameters concerning the binary-table.
INPUT pointer to tabstruct.
OUTPUT RETURN_OK if a binary table was found and mapped, RETURN_ERROR
otherwise.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 25/09/2004
***/
int readbintabparam_head(tabstruct *tab)
{
catstruct *cat;
keystruct *key, *prevkey;
char strf[88], strk[16];
char *str;
int naxisn[32];
int i,j, larray, nfields,narray, pos;
if (!(cat = tab->cat))
error(EXIT_FAILURE, "*Internal Error*: Table has no parent catalog","!");
/*We are expecting a 2D binary-table, and nothing else*/
if ((tab->naxis != 2)
|| (tab->bitpix!=8)
|| (tab->tfields == 0)
|| strncmp(tab->xtension, "BINTABLE", 8))
return RETURN_ERROR;
/*Size and number of lines in the binary table*/
larray = tab->naxisn[0];
nfields= tab->nkey = tab->tfields;
narray = tab->naxisn[1];
prevkey = NULL;
/*For each of the data fields...*/
pos = 0;
for (i=0; i<nfields; i++)
{
/*--manage the chaining of keys*/
QCALLOC(key, keystruct, 1);
if (prevkey)
{
prevkey->nextkey = key;
key->prevkey = prevkey;
}
else
tab->key = key;
prevkey = key;
/*--map binary-table fields*/
sprintf(strk, "TTYPE%-3d", i+1);
if (fitsread(tab->headbuf, strk, key->name, H_STRING, T_STRING)
!= RETURN_OK) {
error(EXIT_FAILURE,
"*Error*: Incorrect FITS binary-table header in ", cat->filename);
}
fitsread(tab->headbuf, strk, key->comment, H_HCOMMENT, T_STRING);
sprintf(strk, "TUNIT%-3d", i+1);
fitsread(tab->headbuf, strk, key->unit, H_STRING, T_STRING);
sprintf(strk, "TDISP%-3d", i+1);
fitsread(tab->headbuf, strk, key->printf, H_STRING, T_STRING);
if (*key->printf)
tdisptoprintf(key->printf, key->printf);
sprintf(strk, "TFORM%-3d", i+1);
if (fitsread(tab->headbuf, strk, strf, H_STRING, T_STRING) != RETURN_OK) {
error(EXIT_FAILURE,
"*Error*: Incorrect FITS binary-table header in ", cat->filename);
}
key->pos = pos;
pos += (key->nbytes = tsizeof(strf));
key->ttype = ttypeof(strf);
switch(key->ttype)
{
case T_BYTE:
case T_SHORT:
case T_LONG:
key->htype = H_INT;
break;
case T_FLOAT:
case T_DOUBLE:
key->htype = H_EXPO;
break;
case T_STRING:
key->htype = H_STRING;
break;
default:
error(EXIT_FAILURE, "*Internal Error*: Unkwown T_TYPE for ", str);
}
/*--handle the special case of multimensional arrays*/
if ((naxisn[0] = key->nbytes/t_size[key->ttype]) > 1)
{
sprintf(strk, "TDIM%-3d", i+1);
if (fitsread(tab->headbuf, strk, strf, H_STRING, T_STRING) == RETURN_OK)
{
str = strf;
for (j=0; (naxisn[j]=(int)strtol(str+1, &str, 10)); j++);
key->naxis = j;
}
else
key->naxis = 1;
QMALLOC(key->naxisn, int, key->naxis);
for (j=0; j<key->naxis; j++)
key->naxisn[j] = naxisn[j];
}
else
key->naxis = 0;
key->nobj = narray;
key->tab = tab;
}
if (pos != larray)
error(EXIT_FAILURE,
"*Error*: Malformed FITS binary-table header in ", cat->filename);
/*make both ends of the chain meet*/
prevkey->nextkey = tab->key;
tab->key->prevkey = prevkey;
return RETURN_OK;
}
/****** update_head ***********************************************************
PROTO int update_head(tabstruct *tab)
PURPOSE Update a FITS header according to what's in the table.
INPUT Table structure.
OUTPUT RETURN_OK if tab is a binary table, or RETURN_ERROR otherwise.
NOTES The headbuf pointer in the tabstruct might be reallocated.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 11/06/2007
***/
int update_head(tabstruct *tab)
{
keystruct *key;
tabstruct *ctab;
int i,j,n,naxis1;
char strk[88], str[88];
char *buf;
/*Update EXTNAME, the table name */
if (*tab->extname)
{
addkeywordto_head(tab, "EXTNAME ", "EXTENSION NAME");
fitswrite(tab->headbuf, "EXTNAME ", tab->extname, H_STRING, T_STRING);
}
/* If not a binary table, do only a few basic things */
if ((tab->naxis != 2)
|| (tab->bitpix!=8)
|| (tab->tfields == 0)
|| strncmp(tab->xtension, "BINTABLE", 8))
{
addkeywordto_head(tab, "BITPIX ", "BITS PER PIXEL");
fitswrite(tab->headbuf, "BITPIX ", &tab->bitpix, H_INT, T_LONG);
addkeywordto_head(tab, "NAXIS ", "NUMBER OF AXES");
fitswrite(tab->headbuf, "NAXIS ", &tab->naxis, H_INT, T_LONG);
for (i=0; i<tab->naxis; i++)
{
sprintf(strk, "NAXIS%-3d", i+1);
addkeywordto_head(tab, strk, "NUMBER OF ELEMENTS ALONG THIS AXIS");
fitswrite(tab->headbuf, strk, &tab->naxisn[i], H_INT, T_LONG);
}
return RETURN_ERROR;
}
/*First, remove all existing TTYPE, TFORM, etc...*/
removekeywordfrom_head(tab, "TTYPE???");
removekeywordfrom_head(tab, "TFORM???");
removekeywordfrom_head(tab, "TUNIT???");
removekeywordfrom_head(tab, "TZERO???");
removekeywordfrom_head(tab, "TSCAL???");
removekeywordfrom_head(tab, "TDIM???");
removekeywordfrom_head(tab, "TDISP???");
/*Change NAXIS1 in order to take into account changes in width*/
naxis1 = 0;
key = tab->key;
if (tab->nkey>1000) {
for (i=0; i<MIN(999,tab->nkey); i++) {
naxis1 += key->nbytes;
key = key->nextkey;
}
fitswrite(tab->headbuf, "NAXIS1 ", &naxis1, H_INT, T_LONG);
} else {
fitswrite(tab->headbuf, "NAXIS1 ", &tab->naxisn[0], H_INT, T_LONG);
}
/*Change NAXIS1 in the number of fields */
tab->tfields = MIN(999,tab->tfields);
fitswrite(tab->headbuf, "TFIELDS ", &tab->tfields, H_INT, T_LONG);
/*Changes in the number of elements (look for possible segments)*/
for (ctab = tab, n = ctab->naxisn[1];
(ctab=ctab->nexttab) && !ctab->nseg;)
n += ctab->naxisn[1];
fitswrite(tab->headbuf, "NAXIS2 ", &n, H_INT, T_LONG);
key = tab->key;
if (!key)
return RETURN_ERROR;
if (tab->nkey>1000)
warning("Too many output keys, trashing the ones bejond 999", "");
for (i=0; i<MIN(999,tab->nkey); i++)
{
sprintf(strk, "TTYPE%-3d", i+1);
addkeywordto_head(tab, strk, key->comment);
fitswrite(tab->headbuf, strk, key->name, H_STRING, T_STRING);
sprintf(strk, "TFORM%-3d", i+1);
addkeywordto_head(tab, strk, "");
tformof(str, key->ttype, key->nbytes/t_size[key->ttype]);
fitswrite(tab->headbuf, strk, str, H_STRING, T_STRING);
if (key->naxis>1)
{
char *str2, *str2lim;
sprintf(strk, "TDIM%-3d", i+1);
addkeywordto_head(tab, strk, "");
sprintf(str, "(");
str2 = str+1;
str2lim = str+70; /* Prevent an excessively large string */
for (n=0; n<key->naxis && str2<str2lim; n++)
{
sprintf(str2, n?", %d%n":"%d%n", key->naxisn[n],&j);
str2 += j;
}
sprintf(str2, ")");
fitswrite(tab->headbuf, strk, str, H_STRING, T_STRING);
}
if (*key->unit)
{
sprintf(strk, "TUNIT%-3d", i+1);
addkeywordto_head(tab, strk, "");
fitswrite(tab->headbuf, strk, key->unit, H_STRING, T_STRING);
}
if (*key->printf)
{
sprintf(strk, "TDISP%-3d", i+1);
addkeywordto_head(tab, strk, "");
fitswrite(tab->headbuf, strk, printftotdisp(key->printf, str),
H_STRING, T_STRING);
}
key = key->nextkey;
}
/*Finally re-compute CHECKSUM if present */
if (fitsfind(tab->headbuf, "CHECKSUM")==RETURN_OK)
{
unsigned int sum;
if (tab->bodysum)
{
sprintf(str, "%u", tab->bodysum);
fitswrite(tab->headbuf, "DATASUM ", str, H_STRING, T_STRING);
}
sum = tab->bodysum;
/*-- Now the header */
buf = tab->headbuf;
for (i=tab->headnblock; i--; buf+=FBSIZE)
sum = compute_blocksum(buf, sum);
/*-- Complement to 1 */
encode_checksum(~sum, str);
fitswrite(tab->headbuf, "CHECKSUM", str, H_STRING, T_STRING);
}
/*That may be enough for now; to be continued...*/
return RETURN_OK;
}
/****** prim_head *************************************************************
PROTO int prim_head(tabstruct *tab)
PURPOSE Update a FITS header to make it "primary" (not extension)
INPUT Table structure.
OUTPUT RETURN_OK if tab header was already primary, or RETURN_ERROR otherwise.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory) C. Marmo (IAP)
VERSION 11/06/2007
***/
int prim_head(tabstruct *tab)
{
if (!tab->headbuf)
return RETURN_ERROR;
if (!strncmp(tab->headbuf, "XTENSION",8))
{
strncpy(tab->headbuf, "SIMPLE = T "
"/ This is a FITS file ", 80);
/* fitsverify 4.13 (CFITSIO V3.002) return an error
if PCOUNT and GCOUNT are in a primary header (23/05/2007)*/
removekeywordfrom_head(tab, "PCOUNT");
removekeywordfrom_head(tab, "GCOUNT");
return RETURN_ERROR;
}
return RETURN_OK;
}
/****** ext_head *************************************************************
PROTO int ext_head(tabstruct *tab)
PURPOSE Update a FITS header to make it "extension" (not primary)
INPUT Table structure.
OUTPUT RETURN_OK if tab header was already extension, or RETURN_ERROR
otherwise.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory) C. Marmo (IAP)
VERSION 20/06/2007
***/
int ext_head(tabstruct *tab)
{
if (!tab->headbuf)
return RETURN_ERROR;
if (!strncmp(tab->headbuf, "SIMPLE ",8))
{
strncpy(tab->headbuf, "XTENSION= 'IMAGE ' "
"/ Image extension ", 80);
/* fitsverify 4.13 (CFITSIO V3.002) return an error
if EXTEND are in an extension header (20/06/2007)*/
removekeywordfrom_head(tab, "EXTEND");
/* fitsverify 4.13 (CFITSIO V3.002) return an error
if PCOUNT and GCOUNT are not in the extension header (23/05/2007) */
addkeywordto_head(tab, "PCOUNT ", "required keyword; must = 0");
addkeywordto_head(tab, "GCOUNT ", "required keyword; must = 1");
fitswrite(tab->headbuf,"PCOUNT ", &tab->pcount, H_INT, T_LONG);
fitswrite(tab->headbuf,"GCOUNT ", &tab->gcount, H_INT, T_LONG);
return RETURN_ERROR;
}
return RETURN_OK;
}
/****** addkeyto_head *********************************************************
PROTO int addkeyto_head(tabstruct *tab, keystruct *key)
PURPOSE Add a keyword and its value to a table header.
INPUT Table structure,
Key containing the keyword and its value.
OUTPUT Line position in the FITS header.
NOTES The headbuf pointer in the tabstruct might be reallocated.
Pre-existing keywords are overwritten (but not their comments).
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 11/05/2002
***/
int addkeyto_head(tabstruct *tab, keystruct *key)
{
int n;
n = addkeywordto_head(tab, key->name, key->comment);
fitswrite(tab->headbuf, key->name, key->ptr, key->htype, key->ttype);
return n;
}
/****** addkeywordto_head *****************************************************
PROTO int addkeywordto_head(tabstruct *tab, char *keyword, char *comment)
PURPOSE Add a keyword and a comment to a table header.
INPUT Table structure,
String containing the keyword,
String containing the comment.
OUTPUT Line position in the FITS header.
NOTES The headbuf pointer in the tabstruct might be reallocated.
Pre-existing keywords are overwritten (but not their comments).
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 21/04/2003
***/
int addkeywordto_head(tabstruct *tab, char *keyword, char *comment)
{
int n;
if ((fitsfind(tab->headbuf, keyword) == RETURN_ERROR
|| findkey(keyword, (char *)histokeys, 12)!=RETURN_ERROR)
&& (fitsfind(tab->headbuf, "END ")+1)*80 >= tab->headnblock*FBSIZE)
{
tab->headnblock++;
QREALLOC(tab->headbuf, char, tab->headnblock*FBSIZE);
memset(tab->headbuf + (tab->headnblock-1)*FBSIZE, ' ', FBSIZE);
}
n = fitsadd(tab->headbuf, keyword, comment);
return n;
}
/****** removekeywordfrom_head ************************************************
PROTO int removekeywordfrom_head(tabstruct *tab, char *keyword)
PURPOSE Remove a keyword from a table header.
INPUT Table structure,
String containing the keyword.
OUTPUT RETURN_OK if the keyword was found, RETURN_ERROR otherwise..
NOTES The headbuf pointer in the tabstruct might be reallocated.
'?' wildcard allowed; Don't remove the ``END'' keyword with this!!!
AUTHOR E. Bertin (IAP)
VERSION 11/06/2007
***/
int removekeywordfrom_head(tabstruct *tab, char *keyword)
{
int nb;
if (fitsremove(tab->headbuf, keyword) == RETURN_OK)
{
if ((nb=fitsfind(tab->headbuf, "END ")/(FBSIZE/80)+1) < tab->headnblock)
{
tab->headnblock = nb;
QREALLOC(tab->headbuf, char, tab->headnblock*FBSIZE);
}
return RETURN_OK;
}
else
return RETURN_ERROR;
}
/****** tformof ***************************************************************
PROTO int tformof(char *str, t_type ttype, int n)
PURPOSE Return the ``TFORM'' string corresponding to a t_type
and the number of elements.
INPUT a char pointer (to be filled with the T_FORM string),
t_type,
Number of elements.
OUTPUT RETURN_OK if everything went as expected, or RETURN_ERROR otherwise.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 08/02/96
***/
int tformof(char *str, t_type ttype, int n)
{
char t;
switch (ttype)
{
case T_BYTE: t = 'B';
break;
case T_SHORT: t = 'I';
break;
case T_LONG: t = 'J';
break;
case T_FLOAT: t = 'E';
break;
case T_DOUBLE: t = 'D';
break;
case T_STRING: t = 'A';
break;
default: return RETURN_ERROR;
}
sprintf(str, "%d%c", n, t);
return RETURN_OK;
}
/****** tsizeof ***************************************************************
PROTO int tsizeof(char *str)
PURPOSE Return the size of a binary-table field from its ``TFORM''.
INPUT TFORM string (see the FITS documentation).
OUTPUT size in bytes, or RETURN_ERROR if the TFORM is unknown.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 08/02/96
***/
int tsizeof(char *str)
{
int n;
char *str2;
str2 = str;
if (!(n = strtol(str, &str2, 10)))
n = 1;
switch ((int)*str2)
{
case 'L': case 'B': case 'A': return n;
case 'X': return (n-1)/8+1;
case 'I': return 2*n;
case 'J': case 'E': return 4*n;
case 'C': case 'D': case 'P': return 8*n;
case 'M': return 16*n;
default: return RETURN_ERROR;
}
}
/****** ttypeof ***************************************************************
PROTO t_type ttypeof(char *str)
PURPOSE Give the ``t_type'' of a binary-table field from its ``TFORM''.
INPUT TFORM string (see the FITS documentation).
OUTPUT size in bytes, or RETURN_ERROR if the TFORM is unknown.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 17/03/2002
***/
t_type ttypeof(char *str)
{
char *str2;
str2 = str;
strtol(str, &str2, 10);
switch ((int)*str2)
{
case 'L': case 'B': case 'X': return T_BYTE;
case 'I': return T_SHORT;
case 'J': return T_LONG;
case 'E': return T_FLOAT;
case 'D': return T_DOUBLE;
case 'A': return T_STRING;
default: return (t_type)RETURN_ERROR;
}
}
/****** tdisptoprintf *********************************************************
PROTO char *tdisptoprintf(char *tdisp, char *str)
PURPOSE Convert the ``TDISP'' FITS format to the printf() format.
INPUT TDISP format string (see the FITS documentation),
output string (allocated pointer).
OUTPUT printf() format string (see e.g. K&R).
NOTES The present conversion does not handle binary or engineer notations.
A NULL vector is returned if the conversion was unsuccessful.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 25/09/2004
***/
char *tdisptoprintf(char *tdisp, char *str)
{
char control[4];
int w,d, n;
w = d = 0;
n = 0;
n=sscanf(tdisp,"%[ALIBOZFENSGD]%d.%d", control, &w, &d)-1;
if (!w)
{
warning("Strange TDISP format: ", tdisp);
return NULL;
}
switch ((int)*control)
{
case 'A':
sprintf(str, "%%%dc",w);
break;
case 'L':
sprintf(str, "%%%dd",w);
break;
case 'I':
if (n>1)
sprintf(str, "%%%d.%dd",w,d);
else
sprintf(str, "%%%dd",w);
break;
case 'B': case 'Z':
if (n>1)
sprintf(str, "%%%d.%dx",w,d);
else
sprintf(str, "%%%dx",w);
break;
case 'O':
if (n>1)
sprintf(str, "%%%d.%do",w,d);
else
sprintf(str, "%%%do",w);
break;
case 'F':
if (n>1)
sprintf(str, "%%%d.%df",w,d);
else
sprintf(str, "%%%df",w);
break;
case 'E': case 'D':
if (n>1)
sprintf(str, "%%%d.%dE",w,d);
else
sprintf(str, "%%%dE",w);
break;
case 'G':
if (n>1)
sprintf(str, "%%%d.%dG",w,d);
else
sprintf(str, "%%%dG",w);
break;
default:
warning("Unknown TDISP format: ", tdisp);
return NULL;
}
return str;
}
/****** printftotdisp *********************************************************
PROTO char *printftotdisp(char *tdisp, char *str)
PURPOSE Convert the printf() format to the ``TDISP'' FITS format.
INPUT printf() format string (see e.g. K&R),
output string (allocated pointer).
OUTPUT TDISP format string (see the FITS documentation).
NOTES The handling of C string formatting does not include the precision.
NULL is returned in case of unsucessful conversion.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 25/09/2004
***/
char *printftotdisp(char *cprintf, char *str)
{
char *control;
int w,d,n;
*str = 0;
w = d = 0;
if (!(control = strpbrk(cprintf, "cdueERfFgGoOxXs")))
{
warning("Unknown printf() format: ", cprintf);
return NULL;
}
n = sscanf(cprintf,"%%%d.%d", &w, &d);
w = abs(w);
if (!n)
{
warning("Unconvertible printf() format: ", cprintf);
return NULL;
}
switch ((int)*control)
{
case 'c':
sprintf(str, "A%d",w);
break;
case 's':
sprintf(str, "A%d",w);
break;
case 'd': case 'u':
if (n>1)
sprintf(str, "I%d.%d",w,d);
else
sprintf(str, "I%d",w);
break;
case 'o': case 'O':
if (n>1)
sprintf(str, "O%d.%d",w,d);
else
sprintf(str, "O%d",w);
break;
case 'x': case 'X':
if (n>1)
sprintf(str, "Z%d.%d",w,d);
else
sprintf(str, "Z%d",w);
break;
case 'f': case 'F':
if (n>1)
sprintf(str, "F%d.%d",w,d);
else
sprintf(str, "F%d",w);
break;
case 'e': case 'E':
if (n>1)
sprintf(str, "E%d.%d",w,d);
else
sprintf(str, "E%d",w);
break;
case 'g': case 'G':
if (n>1)
sprintf(str, "G%d.%d",w,d);
else
sprintf(str, "G%d",w);
break;
default:
warning("Unknown printf() format: ", cprintf);
return NULL;
}
return str;
}
/*
fitskey.c
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* Part of: The LDAC Tools
*
* Author: E.BERTIN, DeNIS/LDAC
*
* Contents: Functions related to the management of keys.
*
* Last modify: 04/06/2007
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fitscat_defs.h"
#include "fitscat.h"
/****** add_key ****************************************************************
PROTO int add_key(keystruct *key, tabstruct *tab, int pos)
PURPOSE Copy a key from one table to another.
INPUT Pointer to the key,
Pointer to the table,
Pointer to the destination table,
Position (1= first, <=0 = at the end)
OUTPUT RETURN_OK if everything went as expected, and RETURN_ERROR otherwise.
NOTES A preexisting key in the destination table yields a RETURN_ERROR.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 26/03/96
***/
int add_key(keystruct *key, tabstruct *tab, int pos)
{
/*Check if a similar key doesn't already exist in the dest. cat */
if (name_to_key(tab, key->name))
return RETURN_ERROR;
/*Update links (portion of code similar to that of copy_key below) */
if ((key->nextkey = pos_to_key(tab, pos)))
{
(key->prevkey = key->nextkey->prevkey)->nextkey = key;
key->nextkey->prevkey = key;
/*--the first place has a special meaning*/
if (pos==1)
tab->key = key;
}
else
/*There was no no key before*/
tab->key = key->nextkey = key->prevkey = key;
tab->nkey++;
return RETURN_OK;
}
/****** blank_keys *************************************************************
PROTO int blank_keys(tabstruct *tab)
PURPOSE Put the array pointers from all keys in a table to NULL.
INPUT Pointer to the table.
OUTPUT RETURN_OK if keys were found, and RETURN_ERROR otherwise.
Notes: -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 25/04/97
***/
int blank_keys(tabstruct *tab)
{
keystruct *key;
int k;
if (!(key = tab->key))
return RETURN_ERROR;
for (k=tab->nkey; k--;)
{
key->ptr = NULL;
key = key->nextkey;
}
return RETURN_OK;
}
/****** copy_key ***************************************************************
PROTO int copy_key(tabstruct *tabin, char *keyname, tabstruct *tabout, int pos)
PURPOSE Copy a key from one table to another.
INPUT Pointer to the original table,
Name of the key,
Pointer to the destination table,
Position (1= first, <=0 = at the end)
OUTPUT RETURN_OK if everything went as expected, and RETURN_ERROR otherwise.
NOTES A preexisting key in the destination table yields a RETURN_ERROR,
the ptr member is NOT COPIED.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 19/08/96
***/
int copy_key(tabstruct *tabin, char *keyname, tabstruct *tabout, int pos)
{
keystruct *keyin, *keyout;
/*Convert the key name to a pointer*/
if (!(keyin = name_to_key(tabin, keyname)))
return RETURN_ERROR;
/*Check if a similar key doesn't already exist in the dest. cat */
if (name_to_key(tabout, keyname))
return RETURN_ERROR;
tabout->nkey++;
/*First, allocate memory and copy data */
QCALLOC(keyout, keystruct, 1);
*keyout = *keyin;
keyout->ptr = NULL;
if (keyin->naxis)
QMEMCPY(keyin->naxisn, keyout->naxisn, int, keyin->naxis);
/*Then, update the links */
if ((keyout->nextkey = pos_to_key(tabout, pos)))
{
(keyout->prevkey = keyout->nextkey->prevkey)->nextkey = keyout;
keyout->nextkey->prevkey = keyout;
/*--the first place has a special meaning*/
if (pos==1)
tabout->key = keyout;
}
else
/*There was no no key before*/
tabout->key = keyout->nextkey = keyout->prevkey = keyout;
return RETURN_OK;
}
/****** free_key ***************************************************************
PROTO void free_key(keystruct *key)
PURPOSE Free memory associated to a key ptr.
INPUT Pointer to the key.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 19/08/96
***/
void free_key(keystruct *key)
{
free(key->naxisn);
free(key->ptr);
free(key);
return;
}
/****** new_key ****************************************************************
PROTO keystruct *new_key(char *keyname)
PURPOSE Create a new key.
INPUT Name of the key.
OUTPUT A pointer to the new keystruct.
NOTES This function is only provided as a counterpart to new_tab() and
new_cat(): in order to be usable, other key parameters MUST be
handled by the user.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 26/03/96
***/
keystruct *new_key(char *keyname)
{
keystruct *key;
QCALLOC(key, keystruct, 1);
strcpy(key->name, keyname);
return key;
}
/****** read_key ***************************************************************
PROTO keystruct *read_key(tabstruct *tab, char *keyname)
PURPOSE Read one simple column from a FITS binary table.
INPUT pointer to the table,
name of the key,
OUTPUT A pointer to the relevant key, or NULL if the desired key is not
found in the table.
NOTES If key->ptr is not NULL, the function doesn't do anything.
AUTHOR E. Bertin (IAP & Leiden observatory)
E.R. Deul (Sterrewacht Leiden) (Added open_cat error checking)
VERSION 18/02/2000
***/
keystruct *read_key(tabstruct *tab, char *keyname)
{
catstruct *cat;
keystruct *key;
char *buf, *ptr, *fptr,*fptr0;
int i,j, larray,narray,size;
int esize;
if (!(key = name_to_key(tab, keyname)))
return NULL;
/*If ptr is not NULL, there is already something loaded there: let's free mem */
QFREE(key->ptr);
/*!! It is not necessarily the original table */
tab = key->tab;
cat = tab->cat;
/*We are expecting a 2D binary-table, and nothing else*/
if ((tab->naxis != 2)
|| (tab->bitpix!=8)
|| (tab->tfields == 0)
|| strncmp(tab->xtension, "BINTABLE", 8))
error(EXIT_FAILURE, "*Error*: No binary table in ", cat->filename);
/*Size and number of lines in the binary table*/
larray = tab->naxisn[0];
narray = tab->naxisn[1];
/*Positioning to the first element*/
if (open_cat(cat, READ_ONLY) == RETURN_ERROR)
error(EXIT_FAILURE, "*Error*: opening catalog ",cat->filename);
QFSEEK(cat->file, tab->bodypos , SEEK_SET, cat->filename);
/*allocate memory for the buffer where we put one line of data*/
QMALLOC(buf, char, larray);
fptr0 = buf+key->pos;
size = key->nbytes;
/*allocate memory for the array*/
QMALLOC(ptr, char, size*narray);
key->ptr = ptr;
/*read line by line*/
for (i=narray; i--;)
{
QFREAD(buf, larray, cat->file, cat->filename);
fptr = fptr0;
if (bswapflag)
{
esize = t_size[key->ttype];
swapbytes(fptr0, esize, size/esize);
}
for (j = size; j--;)
*(ptr++) = *(fptr++);
}
free(buf);
return key;
}
/****** read_keys **************************************************************
PURPOSE Read several columns from a FITS binary table.
INPUT pointer to the table,
pointer to an array of char *,
pointer to an array of keystruct * (memory must have been allocated),
number of keys to read,
an optional mask pointer.
OUTPUT -.
NOTES The array of pointers pointed by keys is filled with pointers
to the relevant keys (a NULL means NO key with such name was found).
A NULL keys pointer can be given (no info returned of course).
A NULL keynames pointer means read ALL keys belonging to the table.
A NULL mask pointer means NO selection for reading.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 18/02/2000
***/
void read_keys(tabstruct *tab, char **keynames, keystruct **keys, int nkeys,
BYTE *mask)
{
catstruct *cat;
keystruct *key, **ckeys;
BYTE *mask2;
char *buf, *ptr, *fptr;
int i,j,k,n, larray,narray, nb, kflag = 0, size;
int esize;
/*!! It is not necessarily the original table */
tab = tab->key->tab;
cat = tab->cat;
/*We are expecting a 2D binary-table, and nothing else*/
if ((tab->naxis != 2)
|| (tab->bitpix!=8)
|| (tab->tfields == 0)
|| strncmp(tab->xtension, "BINTABLE", 8))
error(EXIT_FAILURE, "*Error*: No binary table in ", cat->filename);
/*Size and number of lines in the binary table*/
larray = tab->naxisn[0];
narray = tab->naxisn[1];
nb = 0;
if ((mask2 = mask))
{
for (i=narray; i--;)
if (*(mask2++))
nb++;
}
if (!keynames)
nkeys = tab->nkey;
/*Allocate memory to store the list of keys to be read */
if (!keys)
{
QMALLOC(keys, keystruct *, nkeys);
kflag = 1;
}
/*allocate memory for the arrays*/
ckeys = keys;
if (keynames)
for (i=nkeys; i--;)
{
if ((key = name_to_key(tab, *(keynames++))))
{
QFREE(key->ptr);
if (nb)
key->nobj = nb;
else
nb=key->nobj;
QMALLOC(key->ptr, char, key->nbytes*nb);
*(ckeys++) = key;
}
else
*(ckeys++) = NULL;
}
else
{
key = tab->key;
for (i=nkeys; i--;)
{
QFREE(key->ptr);
if (nb)
key->nobj = nb;
else
nb=key->nobj;
QMALLOC(key->ptr, char, key->nbytes*nb);
*(ckeys++) = key;
key = key->nextkey;
}
}
/*allocate memory for the buffer where we put one line of data*/
QMALLOC(buf, char, larray);
/*Positioning to the first element*/
open_cat(cat, READ_ONLY);
QFSEEK(cat->file, tab->bodypos , SEEK_SET, cat->filename);
/*read line by line*/
n = 0;
mask2 = mask;
for (i=narray; i--;)
{
QFREAD(buf, larray, cat->file, cat->filename);
if (!mask || *(mask2++))
{
ckeys = keys;
for (j=nkeys; j--;)
if ((key = *(ckeys++)))
{
fptr = buf+key->pos;
ptr = (char *)key->ptr+n*(size=key->nbytes);
if (bswapflag)
{
esize = t_size[key->ttype];
swapbytes(fptr, esize, size/esize);
}
for (k = size; k--;)
*(ptr++) = *(fptr++);
}
n++;
}
}
free(buf);
if (kflag)
free(keys);
return;
}
/****** remove_key *************************************************************
PROTO int remove_key(tabstruct *tab, char *keyname)
PURPOSE Remove a key from a table.
INPUT Pointer to the table,
Name of the key.
OUTPUT RETURN_OK if everything went as expected, and RETURN_ERROR otherwise.
NOTES If keyname = "", the last key from the list is removed.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 15/01/97
***/
int remove_key(tabstruct *tab, char *keyname)
{
keystruct *key, *prevkey, *nextkey;
if (!keyname || !tab->nkey || !tab->key)
return RETURN_ERROR;
if (keyname[0])
{
/*--Convert the key name to a pointer*/
if (!(key = name_to_key(tab, keyname)))
return RETURN_ERROR;
}
else
key = tab->key->prevkey;
prevkey = key->prevkey;
/*Free memory*/
nextkey = key->nextkey;
if (tab->key==key)
tab->key = nextkey;
free_key(key);
if (--tab->nkey)
{
/*--update the links of neighbours*/
nextkey->prevkey = prevkey;
prevkey->nextkey = nextkey;
}
else
tab->key = NULL;
return RETURN_OK;
}
/****** remove_keys ************************************************************
PROTO int remove_keys(tabstruct *tab)
PURPOSE Remove all keys from a table.
INPUT Pointer to the table.
OUTPUT RETURN_OK if keys were found, and RETURN_ERROR otherwise.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 13/03/99
***/
int remove_keys(tabstruct *tab)
{
int k;
if (!tab->key)
return RETURN_ERROR;
for (k=tab->nkey; k--;)
remove_key(tab, "");
return RETURN_OK;
}
/****** name_to_key ************************************************************
PROTO keystruct *name_to_key(tabstruct *tab, char *keyname)
PURPOSE Name search of a key in a table.
INPUT Pointer to the table,
Key name.
OUTPUT The key pointer if the name was matched, and NULL otherwise.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 25/04/97
***/
keystruct *name_to_key(tabstruct *tab, char *keyname)
{
keystruct *key;
int i;
if (!(key=tab->key))
return NULL;
for (i=tab->nkey; strcmp(keyname, key->name) && i--; key=key->nextkey);
return i<0? NULL:key;
}
/****** keys_list **************************************************************
PROTO char **keys_list(catstruct *tab, int *n)
PURPOSE List all keys in a table.
INPUT Pointer to the table,
Pointer to the number of names in that list.
OUTPUT A list of all key names.
NOTES -.
AUTHOR E.R. Deul (Leiden observatory)
VERSION ??/??/96
***/
char **keys_list(tabstruct *tab, int *n)
{
keystruct *key;
int i;
char **names;
QCALLOC(names, char *, tab->nkey);
key = tab->key;
for (i=0; i<tab->nkey; i++) {
QCALLOC(names[i], char, MAXCHARS);
strcpy(names[i],key->name);
key = key->nextkey;
}
*n = tab->nkey;
return names;
}
/****** pos_to_key *************************************************************
PROTO keystruct *pos_to_key(tabstruct *tab, int pos)
PURPOSE Position search of a key in a table.
INPUT Pointer to the table,
Position of the key.
OUTPUT The key pointer if a key exists at the given position, and the
pointer to the first key otherwise.
NOTES pos = 0 or 1 means the first key.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 20/03/96
***/
keystruct *pos_to_key(tabstruct *tab, int pos)
{
keystruct *key;
int i;
if (!(key=tab->key))
return NULL;
if ((pos--)==1)
return tab->key;
for (i=0; i!=pos && i<tab->nkey; i++, key=key->nextkey);
return i<tab->nkey?key:tab->key;
}
/****** show_keys **************************************************************
PROTO void show_keys(tabstruct *tab, char **keynames,
keystruct **keys, int nkeys,
BYTE *mask, FILE *stream,
int strflag, int banflag, int leadflag,
output_type o_type)
PURPOSE Convert a binary table to an ASCII file.
INPUT pointer to the table,
pointer to an array of char *,
pointer to an array of keystruct * (memory must have been allocated),
number of keys to read,
an optional mask pointer,
a stream,
a flag to indicate if arrays should be displayed (0=NO),
a flag to indicate if a banner with keynames should be added (0=NO).
a flag to indicate if a leading row number should be added (0=NO).
the output type
OUTPUT -.
NOTES This is approximately the same code as for read_keys.
The array of pointers pointed by keys is filled with pointers
to the relevant keys (a NULL means NO key with such name was found).
A NULL keys pointer can be given (no info returned of course).
A NULL keynames pointer means read ALL keys belonging to the table.
A NULL mask pointer means NO selection for reading.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 04/06/2007
***/
void show_keys(tabstruct *tab, char **keynames, keystruct **keys, int nkeys,
BYTE *mask, FILE *stream,
int strflag, int banflag, int leadflag, output_type o_type)
{
catstruct *cat;
keystruct *key, **ckeys;
BYTE *mask2;
char *buf, *rfield, *ptr;
int i,j,k,n,c, larray,narray, nb, kflag, maxnbytes, nelem,
esize, *key_col;
typedef struct structreq_keyname
{
char oldname[80]; /* Name of the original pipeline key */
char newname[80]; /* Name of the skycat required key */
} req_keynamestruct;
req_keynamestruct objectmap[] =
{
{"SeqNr", "id"},
{"Ra", "ra"},
{"Dec", "dec"},
{"MAG_ISO", "Mag"},
{"", ""}
};
req_keynamestruct *map;
char skycathead[] = "QueryResult\n\n"
"# Config entry for original catalog server:\n"
"serv_type: catalog\n"
"long_name: ldactoskycat catalog\n"
"short_name: ldactoaskycat\n"
"symbol: id circle %4.1f\n"
"search_cols: mag {Brightest (min)} {Faintest (max)}\n"
"# End config entry\n\n";
char *t, skycattail[] = "";
/* !! It is not necessarily the original table */
if (tab->key)
tab = tab->key->tab;
cat = tab->cat;
/* We are expecting a 2D binary-table, and nothing else */
if ((tab->naxis != 2)
|| (tab->bitpix!=8)
|| (tab->tfields == 0)
|| strncmp(tab->xtension, "BINTABLE", 8))
error(EXIT_FAILURE, "*Error*: Not a binary table in ", cat->filename);
/* Size and number of lines in the binary table */
larray = tab->naxisn[0];
narray = tab->naxisn[1];
nb = 0;
if ((mask2 = mask))
{
for (i=narray; i--;)
if (*(mask2++))
nb++;
}
if (!keynames)
nkeys = tab->nkey;
QCALLOC(key_col, int, nkeys);
if (keynames) {
for (i=0;i<nkeys;i++)
if ((t=strchr(keynames[i], ')'))!=NULL) {
*t='\0';
t=strchr(keynames[i], '(');
*t='\0';
key_col[i] = atoi(++t);
}
}
/* Allocate memory to store the list of keys to be read */
kflag = 0;
if (!keys)
{
QMALLOC(keys, keystruct *, nkeys);
kflag = 1;
}
n=1;
switch (o_type) {
case SHOW_ASCII:
if (leadflag)
fprintf(stream, "# %3d %-15.15s %.47s\n", n++,
"(row_pos)", "running row");
break;
case SHOW_SKYCAT:
fprintf(stream, skycathead, 6.0);
break;
}
/* Allocate memory for the arrays */
maxnbytes = 0;
ckeys = keys;
if (keynames)
for (i=nkeys; i--;)
{
if ((key = name_to_key(tab, *(keynames++))))
{
for (map=objectmap; map->oldname[0]&&o_type == SHOW_SKYCAT; map++) {
if (strcmp(key->name, map->oldname) == 0) {
strcpy(key->name, map->newname);
}
}
*(ckeys++) = key;
switch (o_type) {
case SHOW_ASCII:
if (banflag)
{
if (*key->unit)
fprintf(stream, "# %3d %-15.15s %-47.47s [%s]\n",
n, key->name,key->comment, key->unit);
else
fprintf(stream, "# %3d %-15.15s %.47s\n",
n, key->name,key->comment);
n += key->nbytes/t_size[key->ttype];
}
break;
case SHOW_SKYCAT:
if (key->nbytes/t_size[key->ttype] > 1)
for (j=0;j<key->nbytes/t_size[key->ttype];j++)
fprintf(stream, "%s(%d)\t", key->name,j+1);
else
fprintf(stream, "%s\t", key->name);
break;
}
if (key->nbytes>maxnbytes)
maxnbytes = key->nbytes;
}
else
*(ckeys++) = NULL;
}
else
{
key = tab->key;
for (i=nkeys; i--; key = key->nextkey)
if (strflag || key->naxis==0)
{
for (map=objectmap; map->oldname[0]&&o_type == SHOW_SKYCAT; map++) {
if (strcmp(key->name, map->oldname) == 0) {
strcpy(key->name, map->newname);
}
}
*(ckeys++) = key;
switch (o_type) {
case SHOW_ASCII:
if (banflag)
{
if (*key->unit)
fprintf(stream, "# %3d %-15.15s %-47.47s [%s]\n",
n, key->name,key->comment, key->unit);
else
fprintf(stream, "# %3d %-15.15s %.47s\n",
n, key->name,key->comment);
n += key->nbytes/t_size[key->ttype];
}
break;
case SHOW_SKYCAT:
if (key->nbytes/t_size[key->ttype] > 1)
for (j=0;j<key->nbytes/t_size[key->ttype];j++)
fprintf(stream, "%s(%d)\t", key->name,j+1);
else
fprintf(stream, "%s\t", key->name);
break;
}
if (key->nbytes>maxnbytes)
maxnbytes = key->nbytes;
}
else
{
switch (o_type) {
case SHOW_ASCII:
if (*key->unit)
fprintf(stream, "# %-15.15s %-47.47s [%s]\n",
key->name,key->comment, key->unit);
else
fprintf(stream, "# %-15.15s %.47s\n",
key->name,key->comment);
break;
case SHOW_SKYCAT:
break;
}
*(ckeys++) = NULL;
}
}
if (o_type == SHOW_SKYCAT)
fprintf(stream, "\n------------------\n");
/* Allocate memory for the buffer where we put one line of data */
QMALLOC(buf, char, larray);
/* Allocate memory for the buffer where we put one element */
QMALLOC(rfield, char, maxnbytes);
/* Positioning to the first element */
open_cat(cat, READ_ONLY);
QFSEEK(cat->file, tab->bodypos , SEEK_SET, cat->filename);
/*read line by line*/
n = 0;
mask2 = mask;
for (i=narray; i--;)
{
QFREAD(buf, larray, cat->file, cat->filename);
if (!mask || *(mask2++))
{
ckeys = keys;
if (leadflag)
{
fprintf(stream, "%d", ++n);
if (nkeys)
putc(' ', stream);
}
for (k=0; k<nkeys; k++)
{
if ((key = *(ckeys++)) && (strflag || key->naxis==0))
{
ptr = memcpy(rfield, buf+key->pos, key->nbytes);
esize = t_size[key->ttype];
nelem = key->nbytes/esize;
if (bswapflag)
swapbytes(ptr, esize, nelem);
switch(key->ttype)
{
case T_SHORT:
for (j = 0; j<nelem; j++, ptr += esize)
{
if (key_col[k] == 0 || key_col[k] == j+1) {
fprintf(stream, *key->printf?key->printf:"%d",
*(short *)ptr);
if (j < nelem-1) {
switch (o_type) {
case SHOW_ASCII:
putc(' ', stream);
break;
case SHOW_SKYCAT:
putc('\t', stream);
break;
}
}
}
}
break;
case T_LONG:
for (j = 0; j<nelem; j++,ptr += esize)
{
if (key_col[k] == 0 || key_col[k] == j+1) {
fprintf(stream, *key->printf?key->printf:"%d",
*(int *)ptr);
if (j < nelem-1) {
switch (o_type) {
case SHOW_ASCII:
putc(' ', stream);
break;
case SHOW_SKYCAT:
putc('\t', stream);
break;
}
}
}
}
break;
case T_FLOAT:
for (j = 0; j<nelem; j++,ptr += esize)
{
if (key_col[k] == 0 || key_col[k] == j+1) {
fprintf(stream, *key->printf?key->printf:"%g",
*(float *)ptr);
if (j < nelem-1) {
switch (o_type) {
case SHOW_ASCII:
putc(' ', stream);
break;
case SHOW_SKYCAT:
putc('\t', stream);
break;
}
}
}
}
break;
case T_DOUBLE:
for (j = 0; j<nelem; j++,ptr += esize)
{
if (key_col[k] == 0 || key_col[k] == j+1) {
fprintf(stream, *key->printf?key->printf:"%f",
*(double *)ptr);
if (j < nelem-1) {
switch (o_type) {
case SHOW_ASCII:
putc(' ', stream);
break;
case SHOW_SKYCAT:
putc('\t', stream);
break;
}
}
}
}
break;
case T_BYTE:
if (key->htype==H_BOOL)
for (j = 0; j<nelem; j++,ptr += esize)
{
if (key_col[k] == 0 || key_col[k] == j+1) {
if (*(char *)ptr)
fprintf(stream, "T");
else
fprintf(stream, "F");
}
}
else
for (j = 0; j<nelem; j++,ptr += esize)
{
if (key_col[k] == 0 || key_col[k] == j+1) {
fprintf(stream, *key->printf?key->printf:"%d",
(int)*((unsigned char *)ptr));
if (j) {
switch (o_type) {
case SHOW_ASCII:
putc(' ', stream);
break;
case SHOW_SKYCAT:
putc('\t', stream);
break;
}
}
}
}
break;
case T_STRING:
for (j = nelem; j-- && (c=(int)*ptr); ptr += esize)
fprintf(stream, "%c", c);
break;
default:
error(EXIT_FAILURE, "*FATAL ERROR*: Unknown FITS type in ",
"show_keys()");
break;
}
if (k < nkeys - 1) {
switch (o_type) {
case SHOW_ASCII:
putc(' ', stream);
break;
case SHOW_SKYCAT:
putc('\t', stream);
break;
}
}
}
}
putc('\n', stream);
}
}
free(key_col);
free(buf);
if (kflag)
free(keys);
if (o_type == SHOW_SKYCAT)
fprintf(stream, skycattail);
return;
}
/*
fitsmisc.c
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* Part of: The LDAC Tools
*
* Author: E.BERTIN, DeNIS/LDAC
*
* Contents: miscellaneous functions.
*
* Last modify: 14/07/2006
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "fitscat_defs.h"
#include "fitscat.h"
static void (*errorfunc)(char *msg1, char *msg2) = NULL;
static char warning_historystr[WARNING_NMAX][192]={""};
static int nwarning = 0, nwarning_history = 0, nerror = 0;
/********************************* error ************************************/
/*
I hope it will never be used!
*/
void error(int num, char *msg1, char *msg2)
{
fprintf(stderr, "\n> %s%s\n\n",msg1,msg2);
if (num && errorfunc && !nerror)
{
nerror = 1;
errorfunc(msg1, msg2);
}
exit(num);
}
/**************************** error_installfunc *****************************/
/*
I hope it will never be used!
*/
void error_installfunc(void (*func)(char *msg1, char *msg2))
{
if (func)
errorfunc = func;
return;
}
/********************************* warning **********************************/
/*
Print a warning message on screen.
*/
void warning(char *msg1, char *msg2)
{
time_t warntime;
struct tm *tm;
warntime = time(NULL);
tm = localtime(&warntime);
fprintf(stderr, "\n> WARNING: %s%s\n\n",msg1,msg2);
sprintf(warning_historystr[(nwarning++)%WARNING_NMAX],
"%04d-%02d-%02d %02d:%02d:%02d : %.80s%.80s",
tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec,
msg1, msg2);
return;
}
/****************************** warning_history ******************************/
/*
Return warning.
*/
char *warning_history(void)
{
char *str;
if (nwarning_history >= WARNING_NMAX)
{
nwarning_history = 0; /* So it can be accessed later on */
return "";
}
str = warning_historystr[((nwarning>WARNING_NMAX? (nwarning%WARNING_NMAX):0)
+ nwarning_history++)%WARNING_NMAX];
if (!*str)
nwarning_history = 0; /* So it can be accessed later on */
return str;
}
/******************************* swapbytes **********************************/
/*
Swap bytes for doubles, longs and shorts (for DEC machines or PC for inst.).
*/
void swapbytes(void *ptr, int nb, int n)
{
char *cp;
int j;
cp = (char *)ptr;
if (nb&4)
{
for (j=n; j--; cp+=4)
{
cp[0] ^= (cp[3]^=(cp[0]^=cp[3]));
cp[1] ^= (cp[2]^=(cp[1]^=cp[2]));
}
return;
}
if (nb&2)
{
for (j=n; j--; cp+=2)
cp[0] ^= (cp[1]^=(cp[0]^=cp[1]));
return;
}
if (nb&1)
return;
if (nb&8)
{
for (j=n; j--; cp+=8)
{
cp[0] ^= (cp[7]^=(cp[0]^=cp[7]));
cp[1] ^= (cp[6]^=(cp[1]^=cp[6]));
cp[2] ^= (cp[5]^=(cp[2]^=cp[5]));
cp[3] ^= (cp[4]^=(cp[3]^=cp[4]));
}
return;
}
error(EXIT_FAILURE, "*Internal Error*: Unknown size in ", "swapbytes()");
return;
}
/****** wstrncmp ***************************************************************
PROTO int wstrncmp(char *cs, char *ct, int n)
PURPOSE simple wildcard strcmp.
INPUT character string 1,
character string 2,
maximum number of characters to be compared.
OUTPUT comparison integer (same meaning as strcmp).
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 15/02/96
***/
int wstrncmp(char *cs, char *ct, int n)
{
int diff,i;
i = n;
diff = 0;
do
{
diff = ((*cs=='?'&&*ct)||(*ct=='?'&&*cs))?0:*cs-*ct;
} while (!diff && --i && *(cs++) && *(ct++));
return diff;
}
/****** findkey ****************************************************************
PROTO int findkey(char *str, char *key, int size)
PURPOSE Find an item within a list of keywords.
INPUT character string,
an array of character strings containing the list of keywords,
offset (in char) between each keyword.
OUTPUT position in the list (0 = first) if keyword matched,
RETURN_ERROR otherwise.
NOTES the matching is case-sensitive.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 15/02/96
***/
int findkey(char *str, char *key, int size)
{
int i;
for (i=0; key[0]; i++, key += size)
if (!strcmp(str, key))
return i;
return RETURN_ERROR;
}
/********************************* findnkey **********************************
PROTO int findnkey(char *str, char *key, int size, int nkey)
PURPOSE Find an item within a list of nkey keywords.
INPUT character string,
an array of character strings containing the list of keywords,
offset (in char) between each keyword.
number of keywords.
OUTPUT position in the list (0 = first) if keyword matched,
RETURN_ERROR otherwise.
NOTES the matching is case-sensitive.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 15/02/96
***/
int findnkey(char *str, char *key, int size, int nkey)
{
int i;
for (i=0; i<nkey; i++, key += size)
if (!strcmp(str, key))
return i;
return RETURN_ERROR;
}
/*
fitsread.c
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* Part of: The LDAC Tools
*
* Author: E.BERTIN, DeNIS/LDAC
*
* Contents: low-level functions for reading LDAC FITS catalogs.
*
* Last modify: 26/09/2004
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fitscat_defs.h"
#include "fitscat.h"
char padbuf[FBSIZE];
/****** read_cat ***************************************************************
PROTO catstruct read_cat(char *filename)
PURPOSE ``Read'' a FITS catalog with name filename.
INPUT Filename,
OUTPUT catstruct pointer.
NOTES Returns NULL if no file with name \<filename\> is found.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 07/05/2002
***/
catstruct *read_cat(char *filename)
{
catstruct *cat;
if (!(cat = new_cat(1)))
error (EXIT_FAILURE, "Not enough memory to read ", filename);
strcpy(cat->filename, filename);
if (open_cat(cat, READ_ONLY) != RETURN_OK)
{
free_cat(&cat, 1);
return NULL;
}
if (map_cat(cat) != RETURN_OK)
{
free_cat(&cat, 1);
return NULL;
}
return cat;
}
/****** read_cats **************************************************************
PROTO read_cats(char **filenames, int ncat)
PURPOSE ``Read'' several FITS catalogs.
INPUT A pointer to pointers of char,
The number of catalogs.
OUTPUT catstruct pointer.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 25/04/97
***/
catstruct *read_cats(char **filenames, int ncat)
{
catstruct *cat, *ccat;
int i;
if (!(cat = new_cat(ncat)))
error (EXIT_FAILURE, "Not enough memory to read ", "catalogs");
for (i=ncat, ccat = cat; i--; ccat++, filenames++)
{
strcpy(ccat->filename, *filenames);
if (open_cat(ccat, READ_ONLY) != RETURN_OK)
error (EXIT_FAILURE, "Cannot open ", *filenames);
if (map_cat(ccat) != RETURN_OK)
error (EXIT_FAILURE, "Cannot map ", *filenames);
close_cat(ccat);
}
return cat;
}
/****** init_readobj **********************************************************
PROTO tabstruct *init_readobj(tabstruct *tab, char **pbuf)
PURPOSE Prepare the reading of individual sources in a FITS table
INPUT Table structure,
pointer to an array pointer to be used as a temporary buffer.
OUTPUT Pointer to the table structure from which the data will be read.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 26/09/2004
***/
tabstruct *init_readobj(tabstruct *tab, char **pbuf)
{
catstruct *tabcat;
tabstruct *keytab;
keystruct *key;
int k;
/* Scan keys to find the reference tab and other things*/
keytab = NULL;
tabcat = NULL;
key = tab->key;
for (k=tab->nkey; k--; key = key->nextkey)
if (!key->ptr)
{
keytab = key->tab;
tabcat = keytab->cat;
QMALLOC(key->ptr, char, key->nbytes);
}
else
key->pos = -1;
if (!keytab)
error(EXIT_FAILURE,"*Error*: no original table found among keys in table ",
tab->extname);
if (open_cat(tabcat, READ_ONLY) != RETURN_OK)
error(EXIT_FAILURE, "*Error*: Cannot access ", tabcat->filename);
QFSEEK(tabcat->file, keytab->bodypos, SEEK_SET, tabcat->filename);
/* Allocate memory for the input buffer */
QMALLOC(*pbuf, char, tab->naxisn[0]);
return keytab;
}
/****** read_obj **************************************************************
PROTO int read_obj(tabstruct *keytab, tabstruct *tab, char *buf)
PURPOSE Read one individual source at the current position in a FITS table.
INPUT Table which will be accessed from disk (provided by init_readobj()),
table containing the keys that will be read,
pointer to the temporary buffer.
OUTPUT The number of table lines that remain to be read.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 26/09/2004
***/
int read_obj(tabstruct *keytab, tabstruct *tab, char *buf)
{
keystruct *key;
char *pin, *pout;
int b,k;
int esize;
QFREAD(buf,keytab->naxisn[0],keytab->cat->file,keytab->cat->filename);
key = tab->key;
for (k=tab->nkey; k--; key = key->nextkey)
if (key->pos>=0)
{
pin = buf+key->pos;
pout = key->ptr;
if (bswapflag)
{
esize = t_size[key->ttype];
swapbytes(pin, esize, key->nbytes/esize);
}
for (b=key->nbytes; b--;)
*(pout++) = *(pin++);
}
return --keytab->naxisn[1];
}
/****** read_obj_at ***********************************************************
PROTO int read_obj_at(tabstruct *keytab, tabstruct *tab, char *buf, long pos)
PURPOSE Get one source at a specific position in a FITS table.
INPUT Table which will be accessed from disk (provided by init_readobj()),
table containing the keys that will be read.
pointer to the temporary buffer,
position number in table.
OUTPUT RETURN_OK if the object has been accessed, RETURN_ERROR otherwise.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 26/09/2004
***/
int read_obj_at(tabstruct *keytab, tabstruct *tab, char *buf, long pos)
{
keystruct *key;
char *pin, *pout;
size_t n;
int b,k;
int esize;
if ((n=keytab->naxisn[0]*pos) >= keytab->tabsize)
return RETURN_ERROR;
QFSEEK(keytab->cat->file,keytab->bodypos+n, SEEK_SET, keytab->cat->filename);
QFREAD(buf,keytab->naxisn[0],keytab->cat->file,keytab->cat->filename);
key = tab->key;
for (k=tab->nkey; k--; key = key->nextkey)
if (key->pos>=0)
{
pin = buf+key->pos;
pout = key->ptr;
if (bswapflag)
{
esize = t_size[key->ttype];
swapbytes(pin, esize, key->nbytes/esize);
}
for (b=key->nbytes; b--;)
*(pout++) = *(pin++);
}
return RETURN_OK;
}
/****** end_readobj **********************************************************
PROTO void end_readobj(tabstruct *keytab, tabstruct *tab, char *buf)
PURPOSE End the writing of individual sources in a FITS table
INPUT Table which will be accessed from disk (provided by init_readobj()),
table containing the keys that have been read,
pointer to the temporary buffer.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 26/09/2004
***/
void end_readobj(tabstruct *keytab, tabstruct *tab, char *buf)
{
if (close_cat(keytab->cat) != RETURN_OK)
error(EXIT_FAILURE,"*Error*: Problem while closing",keytab->cat->filename);
/* Recover the original state of the original table */
update_tab(keytab);
free(buf);
return;
}
/*
fitstab.c
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* Part of: The LDAC Tools
*
* Author: E.BERTIN, DeNIS/LDAC
*
* Contents: general functions for handling LDAC FITS catalogs.
*
* Last modify: 15/08/2003
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fitscat_defs.h"
#include "fitscat.h"
/****** about_tab **************************************************************
PROTO int about_tab(catstruct *cat, char *tabname, FILE *stream)
PURPOSE Print information concerning a tab structure.
INPUT Pointer to the input catalog,
table name,
an output stream.
OUTPUT RETURN_OK if the table was found, RETURN_ERROR otherwise.
NOTES -.
AUTHOR E.R. Deul(Leiden observatory),
E. Bertin (IAP & Leiden observatory): return value modified.
E.R. Deul(Leiden observatory): output units
VERSION 15/08/2003
***/
int about_tab(catstruct *cat, char *tabname, FILE *stream)
{
tabstruct *tab;
keystruct *key;
int i, j;
if ((tab = name_to_tab(cat, tabname, 0))) {
fprintf(stream, "Table %s\n", tabname);
for (i=0, key=tab->key; i<tab->nkey; i++,key=key->nextkey)
{
fprintf(stream,
"****** Key #%d\n", i+1);
fprintf(stream,
" Key name:...............%s\n", key->name);
fprintf(stream,
" Key comment:............%s\n", key->comment);
fprintf(stream,
" Key type:...............");
switch (key->ttype) {
case T_BYTE: fprintf(stream,"Byte"); break;
case T_SHORT: fprintf(stream,"Short Int"); break;
case T_LONG: fprintf(stream,"Long Int"); break;
case T_FLOAT: fprintf(stream,"Float"); break;
case T_DOUBLE: fprintf(stream,"Double"); break;
case T_STRING: fprintf(stream,"String"); break;
}
fprintf(stream,"\n");
fprintf(stream,
" Key dimension:..........%d ", key->naxis);
if (key->naxis) fprintf(stream, "(");
for (j=0;j<key->naxis;j++) {
if (j>0) fprintf(stream, " ");
fprintf(stream, "%d", key->naxisn[j]);
}
if (key->naxis) fprintf(stream, ")");
fprintf(stream, "\n");
if (key->unit[0] != '\0')
fprintf(stream,
" Key unit:...............%s\n", key->unit);
}
} else return RETURN_ERROR;
return RETURN_OK;
}
/****** add_tab ****************************************************************
PROTO int add_tab(tabstruct *tab, catstruct *cat, int pos)
PURPOSE Add a table to a catalog.
INPUT Pointer to the table,
Pointer to the destination catalog,
Position (1= first after the primary HDU, <=0 = at the end).
OUTPUT RETURN_OK if everything went as expected, and RETURN_ERROR otherwise.
NOTES Only 1-segment tables are accepted. To copy multi-segment tables,
use copy_tab() instead.
If a table with the same name and basic attributes already exists in
the destination catalog, then the new table is appended to it.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 15/08/2003
***/
int add_tab(tabstruct *tab, catstruct *cat, int pos)
{
tabstruct *outtab, *prevtab;
int i;
/*Check if a similar table doesn't already exist in the dest. cat */
if ((outtab = name_to_tab(cat, tab->extname, 0)))
{
if ((outtab->naxis != 2)
|| (outtab->bitpix!=8)
|| strcmp(outtab->xtension,tab->xtension)
|| (outtab->tfields != tab->tfields)
|| (outtab->naxisn[0] != tab->naxisn[0]))
return RETURN_ERROR;
prevtab = outtab;
for (i=outtab->nseg-1; i--;)
prevtab = prevtab->nexttab;
tab->seg = prevtab->seg+1;
tab->nseg = 0;
outtab->nseg++;
}
else
{
if ((prevtab = pos_to_tab(cat, pos, 0)))
prevtab = prevtab->prevtab;
else
tab->nexttab = tab->prevtab = prevtab = tab;
cat->ntab++;
}
(tab->nexttab = (tab->prevtab = prevtab)->nexttab)->prevtab = tab;
prevtab->nexttab = tab;
return RETURN_OK;
}
/****** copy_tab **************************************************************
PROTO int copy_tab(catstruct *catin, char *tabname, int seg,
catstruct *catout, int pos)
PURPOSE Copy a table from one catalog to another.
INPUT Pointer to the original catalog,
Name of the table,
Table segment (0 = all),
Pointer to the destination catalog,
Position (1= first after the primary HDU, <=0 = at the end)
OUTPUT RETURN_OK if everything went as expected, and RETURN_ERROR otherwise.
NOTES If a table with the same name and basic attributes already exists in
the destination catalog, then the original table is appended to it.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 15/08/2003
***/
int copy_tab(catstruct *catin, char *tabname, int seg,
catstruct *catout, int pos)
{
keystruct *key;
tabstruct *outtab, *prevtab, *nexttab, *tabin,*tabout;
int i,j, nseg;
/*Convert the table name to a pointer*/
if (!(tabin = name_to_tab(catin, tabname, seg)))
return RETURN_ERROR;
nseg = seg?1:tabin->nseg;
/*Check if a similar table doesn't already exist in the dest. cat */
if (*tabname && (outtab = name_to_tab(catout, tabname, 0)))
{
if ((outtab->naxis != 2)
|| (outtab->bitpix!=8)
|| strcmp(outtab->xtension,tabin->xtension)
|| (outtab->tfields != tabin->tfields)
|| (outtab->naxisn[0] != tabin->naxisn[0]))
return RETURN_ERROR;
prevtab = outtab;
for (i=0; i<outtab->nseg-1; i++)
prevtab = prevtab->nexttab;
nexttab = prevtab->nexttab;
outtab->nseg += nseg;
}
else
{
prevtab = nexttab = outtab = NULL;
catout->ntab++;
}
/*Now copy each segment of the original table*/
tabout = NULL; /* to satisfy gcc -Wall */
for (i=nseg; i--;)
{
/*---First, allocate memory and copy data */
QCALLOC(tabout, tabstruct, 1);
*tabout = *tabin;
if (tabin->naxis)
QMEMCPY(tabin->naxisn, tabout->naxisn, int, tabin->naxis);
if (tabin->headbuf)
QMEMCPY(tabin->headbuf, tabout->headbuf, char, tabin->headnblock*FBSIZE);
if (tabin->bodybuf)
QMEMCPY(tabin->bodybuf, tabout->bodybuf, char, tabin->tabsize);
key = tabin->key;
tabout->key = NULL;
tabout->nkey = 0;
for (j=tabin->nkey; j--;)
{
copy_key(tabin, key->name, tabout, 0);
key = key->nextkey;
}
/*---Then, update the links */
if (prevtab)
{
prevtab->nexttab = tabout;
tabout->prevtab = prevtab;
tabout->seg = prevtab->seg+1;
tabout->nseg = 0;
}
else
{
outtab = tabout;
outtab->prevtab = NULL;
tabout->seg = 1;
}
tabin = tabin->nexttab;
prevtab = tabout;
}
/*place the new chain of table-segments within the catalog (tricky, isn't it?)*/
if (!nexttab)
/*--if the table is new */
{
nexttab = pos_to_tab(catout, pos, 0);
if (!nexttab)
nexttab = catout->tab = tabout;
else
{
outtab->prevtab = nexttab->prevtab;
nexttab->prevtab->nexttab = outtab;
}
}
prevtab->nexttab = nexttab;
nexttab->prevtab = prevtab;
return RETURN_OK;
}
/****** copy_tab_fromptr ******************************************************
PROTO void copy_tab_fromptr(tabstruct *tabin, catstruct *catout, int pos)
PURPOSE Copy a table from one catalog to another.
INPUT Pointer to the original catalog,
Pointer to the table,
Pointer to the destination catalog,
Position (1= first after the primary HDU, <=0 = at the end)
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 22/06/2001
***/
void copy_tab_fromptr(tabstruct *tabin, catstruct *catout, int pos)
{
keystruct *key;
tabstruct *prevtab, *nexttab,*tabout;
int j;
catout->ntab++;
/* First, allocate memory and copy data */
QCALLOC(tabout, tabstruct, 1);
*tabout = *tabin;
if (tabin->naxis)
QMEMCPY(tabin->naxisn, tabout->naxisn, int, tabin->naxis);
if (tabin->headbuf)
QMEMCPY(tabin->headbuf, tabout->headbuf, char, tabin->headnblock*FBSIZE);
if (tabin->bodybuf)
QMEMCPY(tabin->bodybuf, tabout->bodybuf, char, tabin->tabsize);
key = tabin->key;
tabout->key = NULL;
tabout->nkey = 0;
for (j=tabin->nkey; j--;)
{
copy_key(tabin, key->name, tabout, 0);
key = key->nextkey;
}
/* Then, update the links */
tabout->prevtab = NULL;
tabout->seg = 1;
tabin = tabin->nexttab;
prevtab = tabout;
if (!(nexttab = pos_to_tab(catout, pos, 0)))
nexttab = catout->tab = tabout;
else
{
tabout->prevtab = nexttab->prevtab;
nexttab->prevtab->nexttab = tabout;
}
prevtab->nexttab = nexttab;
nexttab->prevtab = prevtab;
return;
}
/****** copy_tabs **************************************************************
PROTO int copy_tabs(catstruct *catin, catstruct *catout)
PURPOSE Copy all tables from one catalog to another.
INPUT Pointer to the original catalog,
Pointer to the destination catalog,
OUTPUT RETURN_OK if everything went as expected, and RETURN_ERROR otherwise
(for instance if there were tabs that were not binary-tables, and
therefore that were not copied).
NOTES If a table with the same name and basic attributes already exists in
the destination catalog, then the original table is appended to it.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 12/06/2001
***/
int copy_tabs(catstruct *catin, catstruct *catout)
{
tabstruct *tab;
int i, flag, ntab;
if (!catin->tab)
return RETURN_ERROR;
tab = catin->tab->nexttab; /* skip the primary header */
flag = RETURN_OK;
ntab = catin->ntab-1;
if (!ntab)
ntab = 1;
for (i=ntab; i--;)
{
flag |= copy_tab(catin, tab->extname, 0, catout, 0);
while (!(tab=tab->nexttab)->nseg);
}
return flag;
}
/****** copy_tabs_blind *******************************************************
PROTO int copy_tabs(catstruct *catin, catstruct *catout)
PURPOSE Copy all tables from one catalog to another, without trying to append.
INPUT Pointer to the original catalog,
Pointer to the destination catalog,
OUTPUT RETURN_OK if everything went as expected, and RETURN_ERROR otherwise.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 07/05/2002
***/
int copy_tabs_blind(catstruct *catin, catstruct *catout)
{
tabstruct *tab;
int i, ntab;
if (!catin->tab)
return RETURN_ERROR;
tab = catin->tab; /* don't skip the primary header */
ntab = catin->ntab;
for (i=ntab; i--;)
{
copy_tab_fromptr(tab, catout, 0);
tab=tab->nexttab;
}
return RETURN_OK;
}
/****** free_tab ***************************************************************
PROTO void free_tab(tabstruct *tab)
PURPOSE Free memory associated to a table pointer.
INPUT Pointer to the table.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 28/02/2000
***/
void free_tab(tabstruct *tab)
{
free_body(tab);
free(tab->naxisn);
free(tab->headbuf);
free(tab->compress_buf);
remove_keys(tab);
free(tab);
return;
}
/****** new_tab ****************************************************************
PROTO tabstruct *new_tab(char *tabname)
PURPOSE Create a new binary table.
INPUT Name.
OUTPUT A pointer to the new table.
NOTES A defaut header is also created.
No links are initialized.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 25/04/97
***/
tabstruct *new_tab(char *tabname)
{
static char bintabtemplate[][80] = {
"XTENSION= 'BINTABLE' / THIS IS A BINARY TABLE (FROM THE LDACTOOLS)",
"BITPIX = 8 / ",
"NAXIS = 2 / ",
"NAXIS1 = 0 / BYTES PER ROW",
"NAXIS2 = 0 / NUMBER OF ROWS",
"PCOUNT = 0 / RANDOM PARAMETER COUNT",
"GCOUNT = 1 / GROUP COUNT",
"TFIELDS = 0 / FIELDS PER ROWS",
"EXTNAME = 'WHOCARES' / TABLE NAME",
"END "};
tabstruct *tab;
char *buf;
int i;
QCALLOC(tab, tabstruct, 1);
strcpy(tab->xtension, "BINTABLE");
strcpy(tab->extname, tabname);
tab->naxis = 2;
QCALLOC(tab->naxisn, int, tab->naxis);
tab->bitpix = 8;
tab->bytepix = 1;
tab->pcount = 0;
tab->gcount = 1;
tab->seg = 1;
tab->nseg = 1;
/*Provide a new header*/
QCALLOC(tab->headbuf, char, FBSIZE);
memcpy(tab->headbuf, bintabtemplate, sizeof(bintabtemplate));
for (buf = tab->headbuf, i=FBSIZE; i--; buf++)
if (!*buf)
*buf = ' ';
tab->headnblock = 1;
return tab;
}
/****** remove_tab *************************************************************
PROTO int remove_tab(catstruct *cat, char *tabname, int seg)
PURPOSE Remove a table from a catalog.
INPUT Pointer to the catalog,
Name of the table,
Table segment (0 = all).
OUTPUT RETURN_OK if everything went as expected, and RETURN_ERROR otherwise.
NOTES If tabname = "", the last table from the list is removed.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 15/08/2003
***/
int remove_tab(catstruct *cat, char *tabname, int seg)
{
tabstruct *tab, *prevtab, *nexttab;
int i,nseg;
if (!tabname || !cat->ntab || !cat->tab)
return RETURN_ERROR;
if (tabname[0])
{
/*--Convert the table name to a pointer*/
if (!(tab = name_to_tab(cat, tabname, seg)))
return RETURN_ERROR;
/*--a small trick to simplify decisions afterwards*/
if (seg && tab->nseg==1)
seg = 0;
}
else
{
tab = cat->tab->prevtab;
if (!seg)
for (;!tab->nseg; tab = tab->prevtab);
}
prevtab = tab->prevtab;
nseg = seg?1:tab->nseg;
/*Free memory for each table segment*/
nexttab = NULL; /* to satisfy gcc -Wall */
for (i=nseg; i--;)
{
nexttab = tab->nexttab;
if (cat->tab == tab)
cat->tab = nexttab;
free_tab(tab);
tab = nexttab;
}
if (!seg)
if (!--cat->ntab)
{
cat->tab = NULL;
return RETURN_OK;
}
/*update the links of neighbours*/
nexttab->prevtab = prevtab;
prevtab->nexttab = nexttab;
if (seg)
/*--update status for each table segment*/
{
for (tab=prevtab;!tab->nseg; tab = tab->prevtab);
for (nexttab=tab->nexttab,i=2;!nexttab->nseg;nexttab=nexttab->nexttab,i++);
nexttab->seg = i;
tab->nseg = i;
tab->seg = 1;
}
return RETURN_OK;
}
/****** remove_tabs ************************************************************
PROTO int remove_tabs(catstruct *cat)
PURPOSE Remove all tables from a catalog.
INPUT Pointer to the catalog.
OUTPUT RETURN_OK if tabs were found, and RETURN_ERROR otherwise.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 25/05/97
***/
int remove_tabs(catstruct *cat)
{
int t;
if (!cat->tab)
return RETURN_ERROR;
for (t=cat->ntab; t--;)
remove_tab(cat, "",0);
return RETURN_OK;
}
/****** update_tab ************************************************************
PROTO int update_tab(tabstruct *tab)
PURPOSE Update a table according to what's in the keys.
INPUT Table structure.
OUTPUT RETURN_OK if tab is a binary table, or RETURN_ERROR otherwise.
NOTES The headbuf pointer in the catstruct might be reallocated.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 08/02/97
***/
int update_tab(tabstruct *tab)
{
tabstruct *keytab;
keystruct *key;
int i,j, nobj, nbytes;
/*Just pass if not a binary table*/
if ((tab->naxis != 2)
|| (tab->bitpix!=8)
|| strncmp(tab->xtension, "BINTABLE", 8))
return RETURN_ERROR;
/*Well, not much to do if there are no keys!*/
if (!(key = tab->key))
return RETURN_OK;
nobj = -1;
keytab = NULL;
nbytes = 0;
for (i=tab->nkey; i--;)
{
if (keytab && !key->ptr && key->tab != keytab)
error(EXIT_FAILURE, "*Error*: wrong reference table in ",
key->name);
if (nobj!=-1 && (nobj != key->nobj))
error(EXIT_FAILURE, "*Error*: wrong number of elements in key ",
key->name);
keytab = key->tab;
nobj = key->nobj;
/*-- If the number of bytes per element is not set, recover it */
if (!key->nbytes)
{
key->nbytes = t_size[key->ttype];
for (j=key->naxis; j--;)
key->nbytes *= key->naxisn[j];
}
nbytes += key->nbytes;
key = key->nextkey;
}
tab->tabsize = nobj*nbytes;
tab->naxisn[0] = nbytes;
tab->naxisn[1] = nobj;
tab->tfields = tab->nkey;
return RETURN_OK;
}
/****** name_to_tab ***********************************************************
PROTO tabstruct *name_to_tab(catstruct *cat, char *tabname, int seg)
PURPOSE Name search of a table in a catalog.
INPUT Pointer to the catalog,
Table name,
Table segment (0 = first).
OUTPUT The table pointer if the name was matched, and NULL otherwise.
NOTES -
VERSION 12/06/2001
***/
tabstruct *name_to_tab(catstruct *cat, char *tabname, int seg)
{
tabstruct *tab;
int i;
if (!(tab = cat->tab))
return NULL;
for (i=cat->ntab; strcmp(tabname,tab->extname) && i--;)
while (!(tab=tab->nexttab)->nseg);
if (i<0)
return NULL;
if (seg)
{
for (;tab->seg!=seg && !tab->nexttab->nseg; tab=tab->nexttab);
return tab->seg==seg?tab:NULL;
}
return tab;
}
/****** pos_to_tab *************************************************************
PROTO tabstruct *pos_to_tab(catstruct *cat, int pos, int seg)
PURPOSE Position search of a table in a catalog.
INPUT Pointer to the catalog,
Position of the table,
Table segment (0 = first).
OUTPUT The table pointer if the table exists at the given position, and the
pointer to the primary ``table'' otherwise.
NOTES pos = 1 means the first table after the primary one.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 15/02/96
***/
tabstruct *pos_to_tab(catstruct *cat, int pos, int seg)
{
tabstruct *tab;
int i;
tab = cat->tab;
for (i=0; i!=pos && i<cat->ntab; i++)
while (!(tab=tab->nexttab)->nseg);
if (seg)
for (;tab->seg!=seg && !tab->nexttab->nseg; tab=tab->nexttab);
return i<cat->ntab?tab:cat->tab;
}
/****** tabs_list **************************************************************
PROTO char **tabs_list(catstruct *cat, int *n)
PURPOSE List all tables in a catalog.
INPUT Pointer to the catalog,
Pointer to the number of names in that list.
OUTPUT A list of all table names.
NOTES -.
AUTHOR E.R. Deul (Leiden observatory)
VERSION ??/??/96
***/
char **tabs_list(catstruct *cat, int *n)
{
tabstruct *tab;
int i;
char **names;
tab = cat->tab;
QCALLOC(names, char *, cat->ntab);
for (i=0; i<cat->ntab; i++) {
QCALLOC(names[i], char, MAXCHARS);
strcpy(names[i],tab->extname);
while (!(tab=tab->nexttab)->nseg);
}
*n = cat->ntab;
return names;
}
/****** tabs_row_len ***********************************************************
PROTO int tab_row_len(char *file, char *tabname)
PURPOSE Return the row length in bytes of a given table in a given catalog.
INPUT File pointer.
OUTPUT Table size (bytes)
NOTES -.
AUTHOR E.R. Deul (Leiden observatory)
VERSION 05/06/200`
***/
int tab_row_len(char *file, char *tabname)
{
catstruct *tcat;
tabstruct *tab;
int retcode = -1;
if ((tcat = read_cat(file)) != NULL) {
if ((tab = name_to_tab(tcat, tabname, 0)) != NULL) {
retcode = tab->naxisn[0];
free_tab(tab);
}
close_cat(tcat);
free_cat(&tcat,1);
}
return retcode;
}
/*
fitsutil.c
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* Part of: The LDAC Tools
*
* Author: E.BERTIN, DeNIS/LDAC
*
* Contents: functions for handling FITS keywords.
*
* Last modify: 12/06/2007
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fitscat_defs.h"
#include "fitscat.h"
char histokeys[][12] = {"COMMENT ", "HISTORY ", " ", ""};
/****** fitsadd ***************************************************************
PROTO int fitsadd(char *fitsbuf, char *keyword, char *comment)
PURPOSE Write a FITS keyword in a fits header.
INPUT pointer to the FITS buffer,
name of the keyword to be created,
a comment to put beyond the slash, or next to a COMMENT or HISTORY.
OUTPUT line position or RETURN_ERROR if the keyword is invalid.
NOTES For all keywords except commentary ones (like COMMENT, HISTORY or
blank), it is checked that they do not exist already.
Enough memory should be provided for the FITS header to contain one
more line of 80 char.
AUTHOR E. Bertin (IAP & Leiden observatory) C. Marmo (IAP)
VERSION 13/06/2007
***/
int fitsadd(char *fitsbuf, char *keyword, char *comment)
{
char *key_ptr;
char str[82];
int headpos, headpos2, commentflag,
i, n;
if (strcspn(keyword, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 -_"))
return RETURN_ERROR;
commentflag = findkey(keyword, (char *)histokeys, 12)==RETURN_ERROR?0:1;
if (commentflag || (headpos = fitsfind(fitsbuf, keyword))==RETURN_ERROR)
{
headpos2 = headpos = fitsfind(fitsbuf, "END ");
/*-- Special case of NAXIS parameters */
if (!strncmp(keyword, "NAXIS", 5) && keyword[5] && keyword[5] != ' ')
{
sscanf(keyword, "NAXIS%d", &n);
/*---- Look for all previous NAXIS parameters */
for (i=n; i--;)
{
sprintf(str, "NAXIS%-3d", i);
headpos=fitsfind(fitsbuf, str);
if (headpos>0)
break;
}
if (headpos<0)
/*---- Most likely keyword is NAXIS1 */
headpos=fitsfind(fitsbuf, "NAXIS ");
if (headpos>0)
headpos++;
else
return RETURN_ERROR;
}
/*-- Special case of PCOUNT/GCOUNT parameters */
if (!strncmp(keyword, "PCOUNT", 6))
{
headpos=fitsfind(fitsbuf, "NAXIS ");
sscanf(fitsbuf+80*headpos, "NAXIS = %d", &n);
if (headpos>0)
headpos+=(n+1);
else
return RETURN_ERROR;
}
if (!strncmp(keyword, "GCOUNT", 6))
{
headpos=fitsfind(fitsbuf, "NAXIS ");
sscanf(fitsbuf+80*headpos, "NAXIS = %d", &n);
if (headpos>0)
headpos+=(n+2);
else
return RETURN_ERROR;
}
key_ptr = fitsbuf+80*headpos;
memmove(key_ptr+80, key_ptr, 80*(headpos2-headpos+1));
if (commentflag)
sprintf(str, "%-8.8s %-71.71s",
keyword, comment?comment:" ");
else if (comment && *comment)
sprintf(str, "%-8.8s= / %-47.47s",
keyword, comment);
else
sprintf(str, "%-8.8s= %-47.47s",
keyword, " ");
memcpy(key_ptr, str, 80);
}
return headpos;
}
/****** fitsfind **************************************************************
PROTO int fitsfind(char *fitsbuf, char *keyword)
PURPOSE Search for a FITS keyword in a FITS header.
INPUT pointer to the FITS buffer,
name of the keyword to search for.
OUTPUT position in lines of 80 char (0=first) of the keyword if it was
found, RETURN_ERROR otherwise.
NOTES The buffer MUST contain the ``END '' keyword.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 15/02/96
***/
int fitsfind(char *fitsbuf, char *keyword)
{
char *ptr;
int i, len;
len = strlen(keyword);
for (i=0; strncmp(ptr=&fitsbuf[80*i], "END ", 8); i++)
if (!wstrncmp(ptr, keyword, len))
return i;
if (strncmp(keyword, "END ", 8))
return RETURN_ERROR;
else
return i;
}
/****** fitsnfind *************************************************************
PROTO char *fitsnfind(char *fitsbuf, char *str, int nblock)
PURPOSE Search for a FITS keyword in a fits header of nblock blocks.
INPUT pointer to the FITS buffer,
name of the keyword to search for,
number of FITS blocks (2880 bytes each).
OUTPUT pointer at the keyword position if it was found, NULL otherwise.
NOTES No need for an ``END '' keyword.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 25/04/97
***/
char *fitsnfind(char *fitsbuf, char *str, int nblock)
{
int i;
for (i=36*nblock;i--; fitsbuf+=80)
if (!strncmp(fitsbuf, str, strlen(str)))
return fitsbuf;
return (char *)NULL;
}
/****** fitspick **************************************************************
PROTO int fitspick(char *fitsline, char *keyword, void *ptr, h_type *htype,
t_type *ttype, char *comment)
PURPOSE Pick up FITS keyword,content,type and comment in a fits header line.
INPUT pointer to the current line of FITS buffer,
pointer to a char * (where to put the keyword),
pointer to ``where to put the data'',
pointer to ``where to put the h_type'',
pointer to ``where to put the t_type'',
pointer to a char * (where to put the comment).
OUTPUT RETURN_OK if something was found, RETURN_ERROR otherwise.
NOTES -.
AUTHOR E. Bertin (IAP),
E.R. Deul - Handling of NaN
VERSION 04/06/2007
***/
int fitspick(char *fitsline, char *keyword, void *ptr, h_type *htype,
t_type *ttype, char *comment)
{
char *fptr, *cptr, c, *lastspace;
int i,j, toggle;
*((char *)ptr) = 0;
/*First, get the keyword*/
memcpy(keyword, fitsline, 8);
keyword[8] = 0;
/*Handle comments*/
if ((int)fitsline[8] != '=')
{
if (strncmp(keyword, "COMMENT ", 8)
&& strncmp(keyword, "HISTORY ", 8)
&& strncmp(keyword, "HIERARCH", 8)
&& strncmp(keyword, " ", 8))
return RETURN_ERROR;
memcpy(comment, fitsline+9, 71);
comment[71] = 0;
*htype = H_COMMENT;
*ttype = T_STRING;
return RETURN_OK;
}
for (j=10; j<80 && fitsline[j] == (char)' '; j++);
if (j==80 || fitsline[j] == '/')
{
*htype = H_COMMENT;
*ttype = T_STRING;
return RETURN_ERROR;
}
if ((int)fitsline[j] == '\'')
{
cptr = ptr;
for (fptr = fitsline + (i=j+1); i<80; i++)
{
if (*fptr==(char)'\'')
{
if (i++>=79 || *(fptr+1)!=(char)'\'')
break;
else
fptr++;
}
*cptr++ = *fptr++;
}
*cptr = 0;
/*-- Check if there is a trailing space */
*htype = (cptr != ptr && *(cptr-1)==' ') ? H_STRINGS: H_STRING;
*ttype = T_STRING;
}
else if (fitsline[j] == (char)'T' || fitsline[j] == (char)'F')
{
*((BYTE *)ptr) = fitsline[j]==(char)'T'?1:0;
*htype = H_BOOL;
*ttype = T_BYTE;
}
else if (!strncmp(fitsline+j, "NaN", 3))
{
*((double *)ptr) = BIG;
*htype = H_EXPO;
*ttype = T_DOUBLE;
}
else
{
for (i=j; i<80 && fitsline[i]!=(char)'/' && fitsline[i]!=(char)'.'; i++);
/*-- Handle floats*/
if (fitsline[i]==(char)'.')
{
fixexponent(fitsline);
*((double *)ptr) = atof(fitsline+j);
*htype = H_EXPO;
*ttype = T_DOUBLE;
}
else
/*---- Handle ints*/
{
*((int *)ptr) = atoi(fitsline+j);
*htype = H_INT;
*ttype = T_LONG;
}
}
/*Store comment if it is found*/
toggle = 0;
lastspace = NULL;
for (fptr = fitsline + (i=j); i<80; i++)
{
if (*fptr == (char)'\'')
toggle^=toggle;
if (*(fptr++) == (char)'/' && !toggle)
{
while (++i<80 && *fptr<=' ')
fptr++;
i--;
while (++i<80)
if ((c=*(fptr++))>= ' ')
{
*(comment++) = c;
if (c>' ')
lastspace = comment;
}
}
}
if (lastspace)
*lastspace = '\0';
else
*comment = '\0';
return RETURN_OK;
}
/****** fitsread **************************************************************
PROTO int fitsread(char *fitsbuf, char *keyword, void *ptr, h_type htype,
t_type ttype)
PURPOSE Read a FITS keyword in a fits header.
INPUT pointer to the FITS buffer,
name of the keyword to be read,
pointer where to put the read data,
h_type of the data to be read (see fitscat.h),
t_type of the data to be read (see fitscat.h).
OUTPUT RETURN_OK if the keyword was found, RETURN_ERROR otherwise.
NOTES The buffer MUST contain the ``END '' keyword.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 04/08/2004
***/
int fitsread(char *fitsbuf, char *keyword, void *ptr, h_type htype,
t_type ttype)
{
int i,pos;
char s[4], str[82];
char *st, *st2;
if ((pos = fitsfind(fitsbuf, keyword)) < 0)
return RETURN_ERROR;
strncpy(str,fitsbuf+80*pos,80);
str[80] = '\0';
switch(htype)
{
case H_INT: if (ttype == T_SHORT)
sscanf(str+10, " %hd", (short *)ptr);
else
sscanf(str+10, " %d", (LONG *)ptr);
break;
case H_FLOAT:
case H_EXPO: fixexponent(str);
if (ttype == T_DOUBLE)
sscanf(str+10, " %lf", (double *)ptr);
else
sscanf(str+10, " %f", (float *)ptr);
break;
case H_BOOL: sscanf(str+10, "%1s", s);
if (ttype == T_BYTE)
*(BYTE *)ptr = ((int)s[0] == 'T') ? 1 : 0;
else if (ttype == T_SHORT)
*(short *)ptr = ((int)s[0] == 'T') ? 1 : 0;
else
*(LONG *)ptr = ((int)s[0] == 'T') ? 1 : 0;
break;
case H_STRING: st = ptr;
st2= str+10;
for (i=70; i-- && *(st2++)!=(char)'\'';);
while (i-->0)
{
if (*st2 == '\'' && *(++st2) != '\'')
break;
*(st++) = *(st2++);
}
do
{
*(st--) = (char)'\0';
} while (st>(char *)ptr && (*st == (char)' '));
break;
case H_STRINGS: st = ptr;
st2= str+10;
for (i=70; i-- && *(st2++)!=(char)'\'';);
while (i-->0)
{
if (*st2 == '\'' && *(++st2) != '\'')
break;
*(st++) = *(st2++);
}
*st = (char)'\0';
break;
case H_COMMENT: strcpy(ptr,str+9);
break;
case H_HCOMMENT: strcpy(ptr,str+33);
break;
default: error(EXIT_FAILURE,
"*Internal Error*: Unknown FITS type in ",
"fitsread()");
break;
}
return RETURN_OK;
}
/****** fitsremove ************************************************************
PROTO int fitsremove(char *fitsbuf, char *keyword)
PURPOSE Remove one (or more) FITS keyword from a fits header.
INPUT pointer to the FITS buffer,
name of the keyword to be created.
OUTPUT RETURN_OK if the keyword was found, RETURN_ERROR otherwise.
NOTES '?' wildcard allowed;
Don't remove the ``END'' keyword with this!!!
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 08/04/99
***/
int fitsremove(char *fitsbuf, char *keyword)
{
char *cp1,*cp2;
int endpos,pos, i,n;
endpos = fitsfind(fitsbuf, "END ");
for (n=0; (pos = fitsfind(fitsbuf, keyword))>=0; n++, endpos--)
for (cp1=fitsbuf+80*(pos+1), cp2=fitsbuf+80*pos, i=80*(endpos - pos); i--;)
*(cp2++) = *(cp1++);
if (!n)
return RETURN_ERROR;
memset(fitsbuf+80*(endpos+1), ' ', 80*n);
return RETURN_OK;
}
/****** fitswrite *************************************************************
PROTO int fitswrite(char *fitsbuf, char *keyword, void *ptr, h_type htype,
t_type ttype)
PURPOSE Write a FITS keyword in a fits header.
INPUT pointer to the FITS buffer,
name of the keyword to be written,
pointer where to retrieve the data,
h_type of the data to be written (see fitscat.h),
t_type of the data to be written (see fitscat.h).
OUTPUT RETURN_OK if the keyword was found, RETURN_ERROR otherwise.
NOTES The buffer MUST contain the ``END '' keyword.
The keyword must already exist in the buffer (use fitsadd()).
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 21/09/2006
***/
int fitswrite(char *fitsbuf, char *keyword, void *ptr, h_type htype,
t_type ttype)
{
int i, l, pos, posoff, flag;
char str[81],str2[81];
char *cstr, *cstr1,*cstr2,
c;
/* Ignore HISTORY and COMMENTS */
if (findkey(keyword, (char *)histokeys, 12)!=RETURN_ERROR
|| (pos = fitsfind(fitsbuf, keyword)) < 0)
return RETURN_ERROR;
posoff = 10;
fitsbuf += 80*pos;
switch(htype)
{
case H_INT: sprintf(str, "%20d", (ttype==T_SHORT)?
*(short *)ptr: *(int *)ptr);
break;
case H_FLOAT: sprintf(str, " %12.4f", (ttype==T_DOUBLE)?
*(double *)ptr: *(float *)ptr);
break;
case H_EXPO: sprintf(str, " %16.9E", (ttype==T_DOUBLE)?
*(double *)ptr: *(float *)ptr);
break;
case H_BOOL: if ((ttype==T_SHORT)? *(short *)ptr :
((ttype==T_BYTE)? *(BYTE *)ptr : *(LONG *)ptr))
sprintf(str, " T");
else
sprintf(str, " F");
break;
case H_STRING: /* Handle the famous quote */
cstr1 = (char *)ptr;
cstr2 = str2;
for (i=0; i<80; i++)
if (!(c=*(cstr2++) = *(cstr1++)))
break;
else if (c == '\'')
{
*(cstr2++) = '\'';
i++;
}
if (strlen(str2)<=18)
{
sprintf(str, "'%-18.18s ", str2);
cstr = str+18;
i = 10;
}
else
{
sprintf(str, "'%-68.68s ", str2);
cstr = str+68;
i = 60;
}
for (; i-- && *cstr==(char)' '; cstr--);
*(++cstr) = (char)'\'';
if (i>9)
*(++cstr) = 0;
break;
case H_STRINGS: /* Handle the famous quote */
cstr1 = (char *)ptr;
cstr2 = str2;
for (i=0; i<80; i++)
if (!(c=*(cstr2++) = *(cstr1++)))
break;
else if (c == '\'')
{
*(cstr2++) = '\'';
i++;
}
sprintf(str, "'%s'", str2);
for (i+=2;i<20; i++)
str[i]=' ';
str[i] = '\0';
break;
case H_COMMENT: sprintf(str, "%-70s", (char *)ptr);
posoff = 9;
break;
/* Special case of ``half-comments'' */
case H_HCOMMENT: sprintf(str, " / %-47s", (char *)ptr);
posoff = 30;
break;
default: error(EXIT_FAILURE,
"*FATAL ERROR*: Unknown FITS type in ",
"fitswrite()");
break;
}
/* Now the tricky problem of (former) comments */
flag=1;
cstr = fitsbuf+10;
for (i=71; --i; cstr++)
{
if (*cstr=='\'')
flag ^= 1;
else if (flag && *cstr=='/')
break;
}
if (posoff==10 && i && (l=69-strlen(str))>0)
{
strncpy(str2, cstr, i);
str2[i] = 0;
strcat(str, " ");
strncat(str, str2, l);
}
memset(fitsbuf+9, ' ', 71);
fitsbuf += posoff;
/* Finally copy the result to the right place (except the trailing zero) */
for (cstr = str; *cstr; *(fitsbuf++) = *(cstr++));
return RETURN_OK;
}
/****** fixexponent ***********************************************************
PROTO void fixexponent(char *s)
PURPOSE Replaces the FORTRAN 'D' exponent sign to 'E' in a FITS line.
INPUT FITS line
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 25/04/97
***/
void fixexponent(char *s)
{
int i;
s += 9;
for (i=71; ((int)*s) && (int)*s != '/' && i--; s++)
if ((int)*s == 'D' || (int)*s == 'd')
*s = (char)'E';
return;
}
/*
fitswrite.c
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* Part of: The LDAC Tools
*
* Author: E.BERTIN, DeNIS/LDAC
*
* Contents: low-level functions for writing LDAC FITS catalogs.
*
* Last modify: 17/07/2006
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "fitscat_defs.h"
#include "fitscat.h"
/****** save_cat **************************************************************
PROTO void save_cat(catstruct *cat, char *filename)
PURPOSE Save a FITS catalog with name filename.
INPUT catalog structure,
filename.
OUTPUT -.
NOTES Any preexisting file with name filename is overwritten.
AUTHOR E. Bertin (IAP)
VERSION 09/09/2003
***/
void save_cat(catstruct *cat, char *filename)
{
tabstruct *tab;
int i;
strcpy(cat->filename, filename);
if (open_cat(cat, WRITE_ONLY) != RETURN_OK)
error(EXIT_FAILURE, "*Error*: cannot open for writing ", filename);
tab = cat->tab;
/*Go through each segment in the right order to save data*/
for (i=0; i<cat->ntab; i++)
{
/*-- Make sure that the tab header is primary or extension! */
if (i)
ext_head(tab);
else
prim_head(tab);
save_tab(cat, tab);
while (!((tab=tab->nexttab)->nseg));
}
if (close_cat(cat) != RETURN_OK)
error(EXIT_FAILURE, "*Error*: Problem while closing", cat->filename);
return;
}
/****** save_tab **************************************************************
PROTO void save_tab(catstruct *cat, tabstruct *tab)
PURPOSE Save a FITS table.
INPUT pointer to the catalog structure,
pointer to the table structure.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 09/09/2003
***/
void save_tab(catstruct *cat, tabstruct *tab)
{
catstruct *tabcat;
keystruct *key;
tabstruct *keytab;
KINGSIZE_T tabsize;
KINGLONG size;
int b,j,k,o, nbytes,nkey,nobj,spoonful,
tabflag, larrayin,larrayout;
char *buf, *inbuf, *outbuf, *fptr,*ptr;
int esize;
/* Make the table parameters reflect its content*/
update_tab(tab);
/* The header itself*/
tabflag = save_head(cat, tab)==RETURN_OK?1:0;
/* Allocate memory for the output buffer */
tabsize = 0;
tabcat = NULL; /* to satisfy gcc -Wall */
inbuf = NULL; /* to satisfy gcc -Wall */
if (tabflag)
{
/*-- If segment is a binary table, save it row by row */
QMALLOC(outbuf, char, (larrayout = tab->naxisn[0]));
nkey = tab->nkey;
tabsize = larrayin = 0;
for (j=tab->nseg; j--;)
{
update_tab(tab);
/*---- Scan keys to find the reference tab and other things*/
keytab = NULL;
key = tab->key;
for (k=nkey; k--; key = key->nextkey)
if (!key->ptr)
{
keytab = key->tab;
tabcat = keytab->cat;
}
/*---- If table contains some keys with no ptrs, we have to access a file */
if (keytab)
{
QMALLOC(inbuf, char, (larrayin = keytab->naxisn[0]));
if (open_cat(tabcat, READ_ONLY) != RETURN_OK)
error(EXIT_FAILURE, "*Error*: Cannot access ", tabcat->filename);
QFSEEK(tabcat->file, keytab->bodypos, SEEK_SET, tabcat->filename);
}
nobj = tab->naxisn[1];
for (o=0; o<nobj; o++)
{
if (keytab)
QFREAD(inbuf, larrayin, tabcat->file, tabcat->filename);
fptr = outbuf;
for (k=nkey; k--; key = key->nextkey)
{
nbytes = key->nbytes;
ptr = key->ptr? (char *)key->ptr+nbytes*o:inbuf+key->pos;
for (b=nbytes; b--;)
*(fptr++) = *(ptr++);
if (bswapflag)
if (key->ptr)
{
esize = t_size[key->ttype];
swapbytes(fptr-nbytes, esize, nbytes/esize);
}
}
QFWRITE(outbuf, larrayout, cat->file, cat->filename);
}
if (keytab)
{
free(inbuf);
if (close_cat(tabcat) != RETURN_OK)
error(EXIT_FAILURE, "*Error*: Problem while closing",
tabcat->filename);
}
tabsize += tab->tabsize;
tab = tab->nexttab;
}
free(outbuf);
}
else
{
/*-- If segment is not a binary table, save it ``as it is'' */
/*-- We use a limited-size buffer ``in case of'' */
size = tabsize = tab->tabsize;
if (tabsize)
{
if (tab->bodybuf)
{
/*------ A body is present in memory and needs to be written */
if (bswapflag)
swapbytes(tab->bodybuf, tab->bytepix, tabsize/tab->bytepix);
QFWRITE(tab->bodybuf, (size_t)tabsize, cat->file, cat->filename);
if (bswapflag)
swapbytes(tab->bodybuf, tab->bytepix, tabsize/tab->bytepix);
}
else
/*------ The body should be copied from the source tab */
{
tabcat = tab->cat;
spoonful = size<DATA_BUFSIZE?size:DATA_BUFSIZE;
QMALLOC(buf, char, spoonful);
if (open_cat(tabcat, READ_ONLY) != RETURN_OK)
error(EXIT_FAILURE, "*Error*: Cannot access ", tabcat->filename);
QFSEEK(tabcat->file, tab->bodypos, SEEK_SET, tabcat->filename);
for (;size>0; size -= spoonful)
{
if (spoonful>size)
spoonful = size;
QFREAD(buf, spoonful, tabcat->file, tabcat->filename);
QFWRITE(buf, spoonful, cat->file, cat->filename);
}
free(buf);
if (close_cat(tabcat) != RETURN_OK)
error(EXIT_FAILURE, "*Error*: Problem while closing",
tabcat->filename);
}
}
}
/* FITS padding*/
pad_tab(cat, tabsize);
return;
}
/****** save_head *************************************************************
PROTO int save_head(catstruct *cat, tabstruct *tab)
PURPOSE Save a FITS table header.
INPUT catalog structure,
table structure.
OUTPUT RETURN_OK if tab is a binary table, or RETURN_ERROR otherwise.
NOTES -.
AUTHOR E. Bertin (IAP)
VERSION 16/12/2004
***/
int save_head(catstruct *cat, tabstruct *tab)
{
int tabflag;
/* Make the table parameters reflect its content*/
update_tab(tab);
/* The header itself*/
tabflag = update_head(tab);
QFTELL(cat->file, tab->headpos, cat->filename);
QFWRITE(tab->headbuf, tab->headnblock*FBSIZE, cat->file, cat->filename);
return tabflag;
}
/******* pad_tab *************************************************************
PROTO int pad_tab(catstruct *cat, KINGSIZE_T size)
PURPOSE Pad the FITS body of a tab with 0's to FBSIZE.
INPUT A pointer to the cat structure,
the number of elements that have been written.
OUTPUT RETURN_OK if padding necessary, RETURN_ERROR otherwise.
NOTES .
AUTHOR E. Bertin (IAP)
VERSION 23/01/2003
***/
int pad_tab(catstruct *cat, KINGSIZE_T size)
{
static char padbuf[FBSIZE];
int padsize;
padsize = PADEXTRA(size);
if (padsize)
{
QFWRITE(padbuf, padsize, cat->file, cat->filename);
return RETURN_OK;
}
else
return RETURN_ERROR;
}
/****** init_writeobj *********************************************************
PROTO void init_writeobj(catstruct *cat, tabstruct *tab, char **pbuf)
PURPOSE Prepare the writing of individual sources in a FITS table
INPUT catalog structure,
table structure,
pointer to an array pointer to be used as a temporary buffer.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 26/09/2004
***/
void init_writeobj(catstruct *cat, tabstruct *tab, char **pbuf)
{
keystruct *key;
int k;
/* Make the table parameters reflect its content*/
update_tab(tab);
/* The header itself */
if (save_head(cat, tab) != RETURN_OK)
error(EXIT_FAILURE, "*Error*: Not a binary table: ", tab->extname);
/* Store the current position */
QFTELL(cat->file, tab->bodypos, cat->filename);
/* Allocate memory for the output buffer */
QMALLOC(*pbuf, char, tab->naxisn[0]);
/* Scan keys to check that memory has been allocated */
key = tab->key;
for (k=tab->nkey; k--; key = key->nextkey)
if (!key->ptr)
error(EXIT_FAILURE, "*Error*: no memory allocated for ", key->name);
/* No object written yet: initialize counter */
tab->naxisn[1] = 0;
return;
}
/****** write_obj *************************************************************
PROTO int write_obj(tabstruct *tab, char *buf)
PURPOSE Write one individual source in a FITS table
INPUT Table structure,
pointer to the temporary buffer.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 28/12/2004
***/
int write_obj(tabstruct *tab, char *buf)
{
keystruct *key;
char *pin, *pout, *pout2;
int b,k;
int esize;
key = tab->key;
pout = buf;
for (k=tab->nkey; k--; key = key->nextkey)
{
pin = key->ptr;
pout2 = pout;
for (b=key->nbytes; b--;)
*(pout++) = *(pin++);
if (bswapflag)
{
esize = t_size[key->ttype];
swapbytes(pout2, esize, key->nbytes/esize);
}
}
QFWRITE(buf, *tab->naxisn, tab->cat->file, tab->cat->filename);
return ++tab->naxisn[1];
}
/****** end_writeobj **********************************************************
PROTO void end_writeobj(catstruct *cat, tabstruct *tab, char *buf)
PURPOSE End the writing of individual sources in a FITS table
INPUT catalog structure,
table structure,
pointer to the temporary buffer.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 26/09/2004
***/
void end_writeobj(catstruct *cat, tabstruct *tab, char *buf)
{
keystruct *key;
OFF_T pos;
int k;
/* Make the table parameters reflect its content*/
key = tab->key;
for (k=tab->nkey; k--; key = key->nextkey)
key->nobj = tab->naxisn[1];
update_tab(tab);
/* The header itself */
if (update_head(tab) != RETURN_OK)
error(EXIT_FAILURE, "*Error*: Not a binary table: ", tab->extname);
/*--FITS padding*/
pad_tab(cat, tab->tabsize);
pos = ftell(cat->file);
QFTELL(cat->file, pos, cat->filename);
QFSEEK(cat->file, tab->headpos, SEEK_SET, cat->filename);
QFWRITE(tab->headbuf, FBSIZE*tab->headnblock, cat->file, cat->filename);
QFSEEK(cat->file, pos, SEEK_SET, cat->filename);
free(buf);
return;
}
/****** print_obj *************************************************************
PROTO void print_obj(FILE *stream, tabstruct *tab)
PURPOSE Print one individual source to the output stream.
INPUT Output stream
Table structure.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden observatory)
VERSION 12/07/2006
***/
void print_obj(FILE *stream, tabstruct *tab)
{
keystruct *key;
char *ptr;
int i,k, esize;
if (!(key = tab->key))
error(EXIT_FAILURE, "*Error*: no key to print in table ", tab->extname);
for (k=tab->nkey; k--; key = key->nextkey)
{
esize = t_size[key->ttype];
ptr = key->ptr;
for (i = key->nbytes/esize; i--; ptr += esize)
switch(key->ttype)
{
case T_FLOAT:
fprintf(stream, *key->printf?key->printf:"%g", *(float *)ptr);
if (i)
putc(' ', stream);
break;
case T_DOUBLE:
fprintf(stream, *key->printf?key->printf:"%f", *(double *)ptr);
if (i)
putc(' ', stream);
break;
case T_SHORT:
fprintf(stream, *key->printf?key->printf:"%d", *(short *)ptr);
if (i)
putc(' ', stream);
break;
case T_LONG:
fprintf(stream, *key->printf?key->printf:"%d", *(int *)ptr);
if (i)
putc(' ', stream);
break;
case T_BYTE:
if (key->htype==H_BOOL)
{
if (*ptr)
fprintf(stream, "T");
else
fprintf(stream, "F");
}
else
fprintf(stream, key->printf?key->printf:"%d", (int)*ptr);
if (i)
putc(' ', stream);
break;
case T_STRING:
fprintf(stream, "%c", (int)*ptr);
break;
default:
error(EXIT_FAILURE, "*FATAL ERROR*: Unknown FITS type in ",
"print_obj()");
}
if (k)
putc(' ', stream);
}
putc('\n', stream);
return;
}
/****** voprint_obj ***********************************************************
PROTO void voprint_obj(FILE *stream, tabstruct *tab)
PURPOSE Print one individual source to the output stream in VOTable format
INPUT Output stream
Table structure.
OUTPUT -.
NOTES -.
AUTHOR G. Tissier & E.Bertin (IAP)
VERSION 12/07/2006
***/
void voprint_obj(FILE *stream, tabstruct *tab)
{
keystruct *key;
char *ptr;
int i,k, esize;
if (!(key = tab->key))
error(EXIT_FAILURE, "*Error*: no key to print in table ", tab->extname);
fprintf(stream, " <TR>");
for (k=tab->nkey; k--; key = key->nextkey)
{
fprintf(stream, "<TD>");
esize = t_size[key->ttype];
ptr = key->ptr;
for (i = key->nbytes/esize; i--; ptr += esize)
switch(key->ttype)
{
case T_FLOAT:
fprintf(stream, *key->printf?key->printf:"%g", *(float *)ptr);
if (i)
putc(' ', stream);
break;
case T_DOUBLE:
fprintf(stream, *key->printf?key->printf:"%f", *(double *)ptr);
if (i)
putc(' ', stream);
break;
case T_SHORT:
fprintf(stream, *key->printf?key->printf:"%d", *(short *)ptr);
if (i)
putc(' ', stream);
break;
case T_LONG:
fprintf(stream, *key->printf?key->printf:"%d", *(int *)ptr);
if (i)
putc(' ', stream);
break;
case T_BYTE:
if (key->htype==H_BOOL)
{
if (*ptr)
fprintf(stream, "T");
else
fprintf(stream, "F");
}
else
fprintf(stream, key->printf?key->printf:"%d", (int)*ptr);
if (i)
putc(' ', stream);
break;
case T_STRING:
fprintf(stream, "%c", (int)*ptr);
break;
default:
error(EXIT_FAILURE, "*FATAL ERROR*: Unknown FITS type in ",
"voprint_obj()");
}
fprintf(stream, "</TD>");
}
fprintf(stream, "</TR>\n");
return;
}
/*
flag.c
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* Part of: SExtractor
*
* Author: E.BERTIN (IAP)
*
* Contents: Function related to external flagging.
*
* Last modify: 26/11/2003
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include "define.h"
#include "globals.h"
#include "prefs.h"
#include "plist.h"
#include "flag.h"
/********************************* getflags *********************************
PROTO void getflags(objstruct *obj, pliststruct *pixel)
PURPOSE Return the composited flags extracted from the flag-maps.
INPUT obj structure,
pixel list.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden & ESO)
VERSION 18/11/98
***/
void getflags(objstruct *obj, pliststruct *pixel)
{
pliststruct *pixt;
FLAGTYPE imaflag,cimaflag,
*flagstack, *fs;
int i,n,nmax,nc,nflag,nflag0,
*nflagstack, *nfs;
for (i=0; i<prefs.nimaisoflag; i++)
{
nmax = 0;
imaflag = 0;
switch(prefs.flag_type[i])
{
case FLAG_OR:
for (pixt=pixel+obj->firstpix;pixt>=pixel;
pixt=pixel+PLIST(pixt,nextpix))
if ((cimaflag = PLISTFLAG(pixt,flag[i])))
{
imaflag |= cimaflag;
nmax++;
}
break;
case FLAG_AND:
for (pixt=pixel+obj->firstpix;pixt>=pixel;
pixt=pixel+PLIST(pixt,nextpix))
if ((cimaflag = PLISTFLAG(pixt,flag[i])))
{
imaflag &= cimaflag;
nmax++;
}
break;
case FLAG_MIN:
imaflag = UINT_MAX;
for (pixt=pixel+obj->firstpix;pixt>=pixel;
pixt=pixel+PLIST(pixt,nextpix))
if ((cimaflag = PLISTFLAG(pixt,flag[i])))
{
if (cimaflag<imaflag)
{
imaflag = cimaflag;
nmax = 1;
}
else if (cimaflag==imaflag)
nmax++;
}
if (!nmax)
imaflag = 0;
break;
case FLAG_MAX:
imaflag = 0;
for (pixt=pixel+obj->firstpix;pixt>=pixel;
pixt=pixel+PLIST(pixt,nextpix))
if ((cimaflag = PLISTFLAG(pixt,flag[i])))
{
if (cimaflag>imaflag)
{
imaflag = cimaflag;
nmax = 1;
}
else if (cimaflag==imaflag)
nmax++;
}
if (!nmax)
imaflag = 0;
break;
case FLAG_MOST:
/*------ Allocate memory for the buffers */
nflag = FLAG_BUFSIZE;
QCALLOC(flagstack, FLAGTYPE, nflag);
QCALLOC(nflagstack, int, nflag);
/*------ Count flag values */
for (pixt=pixel+obj->firstpix;pixt>=pixel;
pixt=pixel+PLIST(pixt,nextpix))
if ((cimaflag = PLISTFLAG(pixt,flag[i])))
{
for (n=nflag, fs=flagstack, nfs=nflagstack; n-- && *nfs; nfs++)
if (*(fs++) == cimaflag)
{
(*nfs)++;
break;
}
if (n<0)
{
nflag0 = nflag;
nflag += FLAG_BUFSIZE;
QREALLOC(flagstack, FLAGTYPE, nflag)
fs = flagstack + nflag0;
memset(fs, 0, (size_t)FLAG_BUFSIZE*sizeof(FLAGTYPE));
QREALLOC(nflagstack, int, nflag)
nfs = nflagstack + nflag0;
memset(nfs, 0, (size_t)FLAG_BUFSIZE*sizeof(int));
}
if (!*nfs)
{
*fs = cimaflag;
*nfs = 1;
}
}
/*------ Explore the list we have built and search for most frequent flags */
for (n=nflag, fs=flagstack, nfs=nflagstack; n-- && *nfs; fs++)
if ((nc=*(nfs++))>nmax)
{
nmax = nc;
imaflag = *fs;
}
/*------ Free memory allocated for the buffers */
free(flagstack);
free(nflagstack);
break;
default:
error(EXIT_FAILURE, "*Internal Error*: Unknown FLAG_TYPE","");
}
if (i<prefs.imaflag_size)
obj->imaflag[i] = imaflag;
if (i<prefs.imanflag_size)
obj->imanflag[i] = nmax;
}
return;
}
/******************************* mergeflags *********************************
PROTO void mergeflags(objstruct *objmaster, objstruct *objslave)
PURPOSE Composite flag extracted from the flag-maps.
INPUT obj structure (,
pixel list.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP & Leiden & ESO)
VERSION 29/04/98
***/
void mergeflags(objstruct *objmaster, objstruct *objslave)
{
FLAGTYPE *masterflag,*slaveflag;
int i, *masternflag,*slavenflag;
masterflag = objmaster->imaflag;
masternflag = objmaster->imanflag;
slaveflag = objslave->imaflag;
slavenflag = objslave->imanflag;
for (i=0; i<prefs.nimaisoflag; i++,
masterflag++,masternflag++,slaveflag++,slavenflag++)
switch(prefs.flag_type[i])
{
case FLAG_OR:
*masterflag |= *slaveflag;
*masternflag += *slavenflag;
break;
case FLAG_AND:
*masterflag &= *slaveflag;
*masternflag += *slavenflag;
break;
case FLAG_MIN:
if (*slaveflag == *masterflag)
*masternflag += *slavenflag;
else if (*slaveflag<*masterflag)
{
*masterflag = *slaveflag;
*masternflag = *slavenflag;
}
break;
case FLAG_MAX:
if (*slaveflag == *masterflag)
*masternflag += *slavenflag;
else if (*slaveflag>*masterflag)
{
*masterflag = *slaveflag;
*masternflag = *slavenflag;
}
break;
case FLAG_MOST:
if (*slavenflag>*masternflag)
{
*masterflag = *slaveflag;
*masternflag = *slavenflag;
}
break;
default:
error(EXIT_FAILURE, "*Internal Error*: Unknown FLAG_TYPE","");
}
return;
}
/*
flag.h
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* Part of: SExtractor
*
* Author: E.BERTIN (IAP, Leiden observatory & ESO)
*
* Contents: include to flag.c (external flagging).
*
* Last modify: 28/04/98
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
/*--------------------------- Internal constants ----------------------------*/
#define FLAG_BUFSIZE 32 /* Flag-stacksize at start */
/*------------------------------- functions ---------------------------------*/
void getflags(objstruct *obj, pliststruct *pixel),
mergeflags(objstruct *objmaster, objstruct *objslave);
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment