aboutsummaryrefslogtreecommitdiff
path: root/src/analysis
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2015-03-04 21:21:30 -0500
committerJoseph Hunkeler <jhunkeler@gmail.com>2015-03-04 21:21:30 -0500
commitd54fe7c1f704a63824c5bfa0ece65245572e9b27 (patch)
treeafc52015ffc2c74e0266653eecef1c8ef8ba5d91 /src/analysis
downloadcalfuse-d54fe7c1f704a63824c5bfa0ece65245572e9b27.tar.gz
Initial commit
Diffstat (limited to 'src/analysis')
-rw-r--r--src/analysis/Makefile.Linux.orig142
-rw-r--r--src/analysis/Makefile.Linux64.orig141
-rw-r--r--src/analysis/Makefile.MacOSX.orig145
-rw-r--r--src/analysis/Makefile.Solaris.orig147
-rw-r--r--src/analysis/Makefile.orig.orig147
-rw-r--r--src/analysis/bpm_combine.c548
-rw-r--r--src/analysis/cf_arith.c2154
-rw-r--r--src/analysis/cf_coadd.c192
-rw-r--r--src/analysis/cf_combine.c544
-rwxr-xr-xsrc/analysis/cf_make_900_obs.csh193
-rw-r--r--src/analysis/cf_make_all_exp.c91
-rwxr-xr-xsrc/analysis/cf_make_all_obs.csh555
-rw-r--r--src/analysis/cf_nvo.c497
-rw-r--r--src/analysis/cf_pack.c270
-rw-r--r--src/analysis/cf_reflux.c148
-rw-r--r--src/analysis/cf_ttag_to_hist.c463
-rw-r--r--src/analysis/cf_wrspec7.c58
-rw-r--r--src/analysis/cf_wrspec_cf2.c120
-rw-r--r--src/analysis/cf_xcorr.c303
-rw-r--r--src/analysis/extract_jitter.c198
-rw-r--r--src/analysis/get_shift.c164
-rw-r--r--src/analysis/gethmjd.c98
-rw-r--r--src/analysis/idf_combine.c945
-rw-r--r--src/analysis/idf_cut.c977
-rw-r--r--src/analysis/idf_screen.c339
-rw-r--r--src/analysis/mjd2hjd.c129
-rw-r--r--src/analysis/modhead.c114
-rw-r--r--src/analysis/remove_target_orbital_motion.c503
-rw-r--r--src/analysis/ttag_combine.c520
-rw-r--r--src/analysis/ttag_lightcurve.c398
-rw-r--r--src/analysis/ttag_lightcurve_channel_sum.c183
-rw-r--r--src/analysis/ttag_lightcurve_combine.c182
-rw-r--r--src/analysis/ttag_lightcurve_mjd2hmjd.c151
-rw-r--r--src/analysis/ttag_lightcurve_periodogram.c294
34 files changed, 12053 insertions, 0 deletions
diff --git a/src/analysis/Makefile.Linux.orig b/src/analysis/Makefile.Linux.orig
new file mode 100644
index 0000000..b1786ef
--- /dev/null
+++ b/src/analysis/Makefile.Linux.orig
@@ -0,0 +1,142 @@
+
+FITSVER= 2.470
+CALFUSEDIR= ${PWD}/../..
+
+# Symbols for include directories
+FUSEINCLDIR= -I${CALFUSEDIR}/include
+
+# Symbols used for compiling
+CC= cc
+OPT= -g -Wall -DCFORTRAN -Dg77Fortran -Df2cFortran
+CFLAGS= ${OPT} ${FUSEINCLDIR}
+
+# Symbols used for creating shared binaries
+FUSEBINDIR= ${CALFUSEDIR}/bin
+FUSELIBDIR= -L${CALFUSEDIR}/lib
+LIBDIR= -L/opt/SUNWspro/lib
+FUSELIBS= -lsla -lcfitsio-${FITSVER} -lcf
+LIBS= -lc -lm -lnsl -ldl -lgfortran
+LDFLAGS= -Wl,-R${CALFUSEDIR}/lib
+
+# Binaries to be made
+
+BINS= cf_ttag_to_hist get_shift mjd2hjd cf_reflux \
+ idf_screen extract_jitter modhead \
+ cf_arith cf_combine cf_nvo cf_pack cf_xcorr \
+ idf_combine bpm_combine ttag_combine \
+ cf_coadd cf_make_all_exp \
+ remove_target_orbital_motion idf_cut \
+ ttag_lightcurve \
+ ttag_lightcurve_channel_sum \
+ ttag_lightcurve_mjd2hmjd \
+ ttag_lightcurve_combine \
+ ttag_lightcurve_periodogram
+
+all: ${BINS}
+ chmod g+rw ${BINS}
+
+install: all
+ /bin/cp ${BINS} cf_make_all_obs.csh cf_make_900_obs.csh ${FUSEBINDIR}
+
+clean:
+ /bin/rm -f *.o ${BINS}
+
+distclean:
+ /bin/rm -f *.o ${BINS}
+ cd ../../bin; /bin/rm -f ${BINS}
+
+cf_arith: cf_arith.c cf_wrspec7.c cf_wrspec_cf2.c
+ ${CC} ${CFLAGS} -o cf_arith cf_arith.c cf_wrspec7.c cf_wrspec_cf2.c\
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_coadd: cf_coadd.c
+ ${CC} ${CFLAGS} -o cf_coadd cf_coadd.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_combine: cf_combine.c cf_wrspec7.c
+ ${CC} ${CFLAGS} -o cf_combine cf_combine.c cf_wrspec7.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_make_all_exp:
+ ${CC} ${CFLAGS} -o cf_make_all_exp cf_make_all_exp.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_ttag_to_hist:
+ ${CC} ${CFLAGS} -o cf_ttag_to_hist cf_ttag_to_hist.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_combine:
+ ${CC} ${CFLAGS} -o ttag_combine ttag_combine.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+idf_combine:
+ ${CC} ${CFLAGS} -o idf_combine idf_combine.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+bpm_combine:
+ ${CC} ${CFLAGS} -o bpm_combine bpm_combine.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+get_shift:
+ ${CC} ${CFLAGS} -o get_shift get_shift.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_pack:
+ ${CC} ${CFLAGS} -o cf_pack cf_pack.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_nvo:
+ ${CC} ${CFLAGS} -o cf_nvo cf_nvo.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_reflux:
+ ${CC} ${CFLAGS} -o cf_reflux cf_reflux.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_xcorr:
+ ${CC} ${CFLAGS} -o cf_xcorr cf_xcorr.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+modhead:
+ ${CC} ${CFLAGS} -o modhead modhead.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve:
+ ${CC} ${CFLAGS} -o ttag_lightcurve ttag_lightcurve.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve_periodogram:
+ ${CC} ${CFLAGS} -o ttag_lightcurve_periodogram ttag_lightcurve_periodogram.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+mjd2hjd: mjd2hjd.c gethmjd.c
+ ${CC} ${CFLAGS} -o mjd2hjd mjd2hjd.c gethmjd.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve_channel_sum:
+ ${CC} ${CFLAGS} -o ttag_lightcurve_channel_sum ttag_lightcurve_channel_sum.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve_mjd2hmjd : ttag_lightcurve_mjd2hmjd.c gethmjd.c
+ ${CC} ${CFLAGS} -o ttag_lightcurve_mjd2hmjd ttag_lightcurve_mjd2hmjd.c gethmjd.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve_combine:
+ ${CC} ${CFLAGS} -o ttag_lightcurve_combine ttag_lightcurve_combine.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+idf_screen:
+ ${CC} ${CFLAGS} -o idf_screen idf_screen.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+remove_target_orbital_motion: remove_target_orbital_motion.c gethmjd.c
+ ${CC} ${CFLAGS} -o remove_target_orbital_motion remove_target_orbital_motion.c gethmjd.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+idf_cut:
+ ${CC} ${CFLAGS} -o idf_cut idf_cut.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+extract_jitter:
+ ${CC} ${CFLAGS} -o extract_jitter extract_jitter.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
diff --git a/src/analysis/Makefile.Linux64.orig b/src/analysis/Makefile.Linux64.orig
new file mode 100644
index 0000000..2ef8094
--- /dev/null
+++ b/src/analysis/Makefile.Linux64.orig
@@ -0,0 +1,141 @@
+
+CALFUSEDIR= ${PWD}/../..
+
+# Symbols for include directories
+FUSEINCLDIR= -I${CALFUSEDIR}/include
+
+# Symbols used for compiling
+CC= cc
+OPT= -g -Wall -DCFORTRAN -Dg77Fortran -Df2cFortran
+CFLAGS= ${OPT} ${FUSEINCLDIR}
+
+# Symbols used for creating shared binaries
+FUSEBINDIR= ${CALFUSEDIR}/bin
+FUSELIBDIR= -L${CALFUSEDIR}/lib
+LIBDIR= -L/opt/SUNWspro/lib
+FUSELIBS= -lsla -lcf
+LIBS= -lc -lm -lnsl -ldl -lgfortran -lcfitsio
+LDFLAGS= -Wl,-R${CALFUSEDIR}/lib
+
+# Binaries to be made
+
+BINS= cf_ttag_to_hist get_shift mjd2hjd cf_reflux \
+ idf_screen extract_jitter modhead \
+ cf_arith cf_combine cf_nvo cf_pack cf_xcorr \
+ idf_combine bpm_combine ttag_combine \
+ cf_coadd cf_make_all_exp \
+ remove_target_orbital_motion idf_cut \
+ ttag_lightcurve \
+ ttag_lightcurve_channel_sum \
+ ttag_lightcurve_mjd2hmjd \
+ ttag_lightcurve_combine \
+ ttag_lightcurve_periodogram
+
+all: ${BINS}
+ chmod g+rw ${BINS}
+
+install: all
+ /bin/cp ${BINS} cf_make_all_obs.csh cf_make_900_obs.csh ${FUSEBINDIR}
+
+clean:
+ /bin/rm -f *.o ${BINS}
+
+distclean:
+ /bin/rm -f *.o ${BINS}
+ cd ../../bin; /bin/rm -f ${BINS}
+
+cf_arith: cf_arith.c cf_wrspec7.c cf_wrspec_cf2.c
+ ${CC} ${CFLAGS} -o cf_arith cf_arith.c cf_wrspec7.c cf_wrspec_cf2.c\
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_coadd: cf_coadd.c
+ ${CC} ${CFLAGS} -o cf_coadd cf_coadd.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_combine: cf_combine.c cf_wrspec7.c
+ ${CC} ${CFLAGS} -o cf_combine cf_combine.c cf_wrspec7.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_make_all_exp:
+ ${CC} ${CFLAGS} -o cf_make_all_exp cf_make_all_exp.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_ttag_to_hist:
+ ${CC} ${CFLAGS} -o cf_ttag_to_hist cf_ttag_to_hist.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_combine:
+ ${CC} ${CFLAGS} -o ttag_combine ttag_combine.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+idf_combine:
+ ${CC} ${CFLAGS} -o idf_combine idf_combine.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+bpm_combine:
+ ${CC} ${CFLAGS} -o bpm_combine bpm_combine.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+get_shift:
+ ${CC} ${CFLAGS} -o get_shift get_shift.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_pack:
+ ${CC} ${CFLAGS} -o cf_pack cf_pack.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_nvo:
+ ${CC} ${CFLAGS} -o cf_nvo cf_nvo.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_reflux:
+ ${CC} ${CFLAGS} -o cf_reflux cf_reflux.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_xcorr:
+ ${CC} ${CFLAGS} -o cf_xcorr cf_xcorr.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+modhead:
+ ${CC} ${CFLAGS} -o modhead modhead.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve:
+ ${CC} ${CFLAGS} -o ttag_lightcurve ttag_lightcurve.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve_periodogram:
+ ${CC} ${CFLAGS} -o ttag_lightcurve_periodogram ttag_lightcurve_periodogram.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+mjd2hjd: mjd2hjd.c gethmjd.c
+ ${CC} ${CFLAGS} -o mjd2hjd mjd2hjd.c gethmjd.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve_channel_sum:
+ ${CC} ${CFLAGS} -o ttag_lightcurve_channel_sum ttag_lightcurve_channel_sum.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve_mjd2hmjd : ttag_lightcurve_mjd2hmjd.c gethmjd.c
+ ${CC} ${CFLAGS} -o ttag_lightcurve_mjd2hmjd ttag_lightcurve_mjd2hmjd.c gethmjd.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve_combine:
+ ${CC} ${CFLAGS} -o ttag_lightcurve_combine ttag_lightcurve_combine.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+idf_screen:
+ ${CC} ${CFLAGS} -o idf_screen idf_screen.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+remove_target_orbital_motion: remove_target_orbital_motion.c gethmjd.c
+ ${CC} ${CFLAGS} -o remove_target_orbital_motion remove_target_orbital_motion.c gethmjd.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+idf_cut:
+ ${CC} ${CFLAGS} -o idf_cut idf_cut.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+extract_jitter:
+ ${CC} ${CFLAGS} -o extract_jitter extract_jitter.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
diff --git a/src/analysis/Makefile.MacOSX.orig b/src/analysis/Makefile.MacOSX.orig
new file mode 100644
index 0000000..5e40b35
--- /dev/null
+++ b/src/analysis/Makefile.MacOSX.orig
@@ -0,0 +1,145 @@
+
+FITSVER= 2.470
+CALFUSEDIR= ${PWD}/../..
+MACOSX_DEPLOYMENT_TARGET= 10.2
+
+# Symbols for include directories
+FUSEINCLDIR= -I${CALFUSEDIR}/include
+
+# Symbols used for compiling
+CC= cc
+OPT= -O3 -Wall -DCFORTRAN -Dg77Fortran -Df2cFortran
+CFLAGS= ${OPT} ${FUSEINCLDIR}
+
+# Symbols used for creating shared binaries
+FUSEBINDIR= ${CALFUSEDIR}/bin
+FUSELIBDIR= -L${CALFUSEDIR}/lib
+# FUSELIBS= -lsla -lcfitsio-${FITSVER} -lcf
+FUSELIBS= -lsla -lcfitsio -lcf
+LIBS= -lc -lm -ldl -L/sw/lib/ -lgfortran
+
+# Binaries to be made
+
+BINS= cf_ttag_to_hist get_shift mjd2hjd cf_reflux \
+ idf_screen extract_jitter modhead \
+ cf_arith cf_combine cf_nvo cf_pack cf_xcorr \
+ idf_combine bpm_combine ttag_combine \
+ cf_coadd cf_make_all_exp \
+ remove_target_orbital_motion idf_cut \
+ ttag_lightcurve \
+ ttag_lightcurve_channel_sum \
+ ttag_lightcurve_mjd2hmjd \
+ ttag_lightcurve_combine \
+ ttag_lightcurve_periodogram
+
+all: ${BINS}
+ chmod g+rw ${BINS}
+
+install:
+ MACOSX_DEPLOYMENT_TARGET="${MACOSX_DEPLOYMENT_TARGET}"; \
+ export MACOSX_DEPLOYMENT_TARGET; \
+ make all
+ /bin/cp ${BINS} cf_make_all_obs.csh cf_make_900_obs.csh ${FUSEBINDIR}
+
+clean:
+ /bin/rm -f *.o ${BINS}
+
+distclean:
+ /bin/rm -f *.o ${BINS}
+ cd ../../bin; /bin/rm -f ${BINS}
+
+cf_arith: cf_arith.c cf_wrspec7.c cf_wrspec_cf2.c
+ ${CC} ${CFLAGS} -o cf_arith cf_arith.c cf_wrspec7.c cf_wrspec_cf2.c\
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_coadd: cf_coadd.c
+ ${CC} ${CFLAGS} -o cf_coadd cf_coadd.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_combine: cf_combine.c cf_wrspec7.c
+ ${CC} ${CFLAGS} -o cf_combine cf_combine.c cf_wrspec7.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_make_all_exp:
+ ${CC} ${CFLAGS} -o cf_make_all_exp cf_make_all_exp.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_ttag_to_hist:
+ ${CC} ${CFLAGS} -o cf_ttag_to_hist cf_ttag_to_hist.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_combine:
+ ${CC} ${CFLAGS} -o ttag_combine ttag_combine.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+idf_combine:
+ ${CC} ${CFLAGS} -o idf_combine idf_combine.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+bpm_combine:
+ ${CC} ${CFLAGS} -o bpm_combine bpm_combine.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+get_shift:
+ ${CC} ${CFLAGS} -o get_shift get_shift.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_pack:
+ ${CC} ${CFLAGS} -o cf_pack cf_pack.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_nvo:
+ ${CC} ${CFLAGS} -o cf_nvo cf_nvo.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_reflux:
+ ${CC} ${CFLAGS} -o cf_reflux cf_reflux.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_xcorr:
+ ${CC} ${CFLAGS} -o cf_xcorr cf_xcorr.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+modhead:
+ ${CC} ${CFLAGS} -o modhead modhead.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve:
+ ${CC} ${CFLAGS} -o ttag_lightcurve ttag_lightcurve.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve_periodogram:
+ ${CC} ${CFLAGS} -o ttag_lightcurve_periodogram ttag_lightcurve_periodogram.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+mjd2hjd: mjd2hjd.c gethmjd.c
+ ${CC} ${CFLAGS} -o mjd2hjd mjd2hjd.c gethmjd.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve_channel_sum:
+ ${CC} ${CFLAGS} -o ttag_lightcurve_channel_sum ttag_lightcurve_channel_sum.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve_mjd2hmjd : ttag_lightcurve_mjd2hmjd.c gethmjd.c
+ ${CC} ${CFLAGS} -o ttag_lightcurve_mjd2hmjd ttag_lightcurve_mjd2hmjd.c gethmjd.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve_combine:
+ ${CC} ${CFLAGS} -o ttag_lightcurve_combine ttag_lightcurve_combine.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+idf_screen:
+ ${CC} ${CFLAGS} -o idf_screen idf_screen.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+remove_target_orbital_motion: remove_target_orbital_motion.c gethmjd.c
+ ${CC} ${CFLAGS} -o remove_target_orbital_motion remove_target_orbital_motion.c gethmjd.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+idf_cut:
+ ${CC} ${CFLAGS} -o idf_cut idf_cut.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+extract_jitter:
+ ${CC} ${CFLAGS} -o extract_jitter extract_jitter.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
diff --git a/src/analysis/Makefile.Solaris.orig b/src/analysis/Makefile.Solaris.orig
new file mode 100644
index 0000000..52fb31b
--- /dev/null
+++ b/src/analysis/Makefile.Solaris.orig
@@ -0,0 +1,147 @@
+
+FITSVER= 2.470
+CALFUSEDIR= ${PWD}/../..
+
+# Symbols for include directories
+FUSEINCLDIR= -I${CALFUSEDIR}/include
+
+# Symbols used for compiling
+CC= cc
+# Romelfanger's optimizations
+# OPT= -fast -xO5 -xtarget=ultra2 -xarch=v8plusa
+#
+# SunWorld's optimizations
+# OPT= -p -v -xO2 -xdepend -xchip=ultra -xarch=generic
+OPT= -O -DCFORTRAN -KPIC -DSOLARIS
+CFLAGS= ${OPT} ${FUSEINCLDIR}
+
+# Symbols used for creating shared binaries
+FUSEBINDIR= ${CALFUSEDIR}/bin
+FUSELIBDIR= -L${CALFUSEDIR}/lib
+LIBDIR= -L/opt/SUNWspro/lib
+FUSELIBS= -lsla -lcfitsio-${FITSVER} -lcf
+LIBS= -lc -lm -lnsl -ldl -lsocket -lsunmath -lM77 -lF77
+LDFLAGS= -Wl,-R${CALFUSEDIR}/lib
+
+# Binaries to be made
+
+BINS= cf_ttag_to_hist get_shift mjd2hjd cf_reflux \
+ idf_screen extract_jitter modhead \
+ cf_arith cf_combine cf_nvo cf_pack cf_xcorr \
+ idf_combine bpm_combine ttag_combine \
+ cf_coadd cf_make_all_exp \
+ remove_target_orbital_motion idf_cut \
+ ttag_lightcurve \
+ ttag_lightcurve_channel_sum \
+ ttag_lightcurve_mjd2hmjd \
+ ttag_lightcurve_combine \
+ ttag_lightcurve_periodogram
+
+all: ${BINS}
+ chmod g+rw ${BINS}
+
+install: all
+ /bin/cp ${BINS} cf_make_all_obs.csh cf_make_900_obs.csh ${FUSEBINDIR}
+
+clean:
+ /bin/rm -f *.o ${BINS}
+
+distclean:
+ /bin/rm -f *.o ${BINS}
+ cd ../../bin; /bin/rm -f ${BINS}
+
+cf_arith: cf_arith.c cf_wrspec7.c cf_wrspec_cf2.c
+ ${CC} ${CFLAGS} -o cf_arith cf_arith.c cf_wrspec7.c cf_wrspec_cf2.c\
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_coadd: cf_coadd.c
+ ${CC} ${CFLAGS} -o cf_coadd cf_coadd.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_combine: cf_combine.c cf_wrspec7.c
+ ${CC} ${CFLAGS} -o cf_combine cf_combine.c cf_wrspec7.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_make_all_exp:
+ ${CC} ${CFLAGS} -o cf_make_all_exp cf_make_all_exp.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_ttag_to_hist:
+ ${CC} ${CFLAGS} -o cf_ttag_to_hist cf_ttag_to_hist.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_combine:
+ ${CC} ${CFLAGS} -o ttag_combine ttag_combine.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+idf_combine:
+ ${CC} ${CFLAGS} -o idf_combine idf_combine.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+bpm_combine:
+ ${CC} ${CFLAGS} -o bpm_combine bpm_combine.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+get_shift:
+ ${CC} ${CFLAGS} -o get_shift get_shift.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_pack:
+ ${CC} ${CFLAGS} -o cf_pack cf_pack.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_nvo:
+ ${CC} ${CFLAGS} -o cf_nvo cf_nvo.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_reflux:
+ ${CC} ${CFLAGS} -o cf_reflux cf_reflux.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_xcorr:
+ ${CC} ${CFLAGS} -o cf_xcorr cf_xcorr.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+modhead:
+ ${CC} ${CFLAGS} -o modhead modhead.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve:
+ ${CC} ${CFLAGS} -o ttag_lightcurve ttag_lightcurve.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve_periodogram:
+ ${CC} ${CFLAGS} -o ttag_lightcurve_periodogram ttag_lightcurve_periodogram.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+mjd2hjd: mjd2hjd.c gethmjd.c
+ ${CC} ${CFLAGS} -o mjd2hjd mjd2hjd.c gethmjd.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve_channel_sum:
+ ${CC} ${CFLAGS} -o ttag_lightcurve_channel_sum ttag_lightcurve_channel_sum.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve_mjd2hmjd : ttag_lightcurve_mjd2hmjd.c gethmjd.c
+ ${CC} ${CFLAGS} -o ttag_lightcurve_mjd2hmjd ttag_lightcurve_mjd2hmjd.c gethmjd.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve_combine:
+ ${CC} ${CFLAGS} -o ttag_lightcurve_combine ttag_lightcurve_combine.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+idf_screen:
+ ${CC} ${CFLAGS} -o idf_screen idf_screen.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+remove_target_orbital_motion: remove_target_orbital_motion.c gethmjd.c
+ ${CC} ${CFLAGS} -o remove_target_orbital_motion remove_target_orbital_motion.c gethmjd.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+idf_cut:
+ ${CC} ${CFLAGS} -o idf_cut idf_cut.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+extract_jitter:
+ ${CC} ${CFLAGS} -o extract_jitter extract_jitter.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
diff --git a/src/analysis/Makefile.orig.orig b/src/analysis/Makefile.orig.orig
new file mode 100644
index 0000000..52fb31b
--- /dev/null
+++ b/src/analysis/Makefile.orig.orig
@@ -0,0 +1,147 @@
+
+FITSVER= 2.470
+CALFUSEDIR= ${PWD}/../..
+
+# Symbols for include directories
+FUSEINCLDIR= -I${CALFUSEDIR}/include
+
+# Symbols used for compiling
+CC= cc
+# Romelfanger's optimizations
+# OPT= -fast -xO5 -xtarget=ultra2 -xarch=v8plusa
+#
+# SunWorld's optimizations
+# OPT= -p -v -xO2 -xdepend -xchip=ultra -xarch=generic
+OPT= -O -DCFORTRAN -KPIC -DSOLARIS
+CFLAGS= ${OPT} ${FUSEINCLDIR}
+
+# Symbols used for creating shared binaries
+FUSEBINDIR= ${CALFUSEDIR}/bin
+FUSELIBDIR= -L${CALFUSEDIR}/lib
+LIBDIR= -L/opt/SUNWspro/lib
+FUSELIBS= -lsla -lcfitsio-${FITSVER} -lcf
+LIBS= -lc -lm -lnsl -ldl -lsocket -lsunmath -lM77 -lF77
+LDFLAGS= -Wl,-R${CALFUSEDIR}/lib
+
+# Binaries to be made
+
+BINS= cf_ttag_to_hist get_shift mjd2hjd cf_reflux \
+ idf_screen extract_jitter modhead \
+ cf_arith cf_combine cf_nvo cf_pack cf_xcorr \
+ idf_combine bpm_combine ttag_combine \
+ cf_coadd cf_make_all_exp \
+ remove_target_orbital_motion idf_cut \
+ ttag_lightcurve \
+ ttag_lightcurve_channel_sum \
+ ttag_lightcurve_mjd2hmjd \
+ ttag_lightcurve_combine \
+ ttag_lightcurve_periodogram
+
+all: ${BINS}
+ chmod g+rw ${BINS}
+
+install: all
+ /bin/cp ${BINS} cf_make_all_obs.csh cf_make_900_obs.csh ${FUSEBINDIR}
+
+clean:
+ /bin/rm -f *.o ${BINS}
+
+distclean:
+ /bin/rm -f *.o ${BINS}
+ cd ../../bin; /bin/rm -f ${BINS}
+
+cf_arith: cf_arith.c cf_wrspec7.c cf_wrspec_cf2.c
+ ${CC} ${CFLAGS} -o cf_arith cf_arith.c cf_wrspec7.c cf_wrspec_cf2.c\
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_coadd: cf_coadd.c
+ ${CC} ${CFLAGS} -o cf_coadd cf_coadd.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_combine: cf_combine.c cf_wrspec7.c
+ ${CC} ${CFLAGS} -o cf_combine cf_combine.c cf_wrspec7.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_make_all_exp:
+ ${CC} ${CFLAGS} -o cf_make_all_exp cf_make_all_exp.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_ttag_to_hist:
+ ${CC} ${CFLAGS} -o cf_ttag_to_hist cf_ttag_to_hist.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_combine:
+ ${CC} ${CFLAGS} -o ttag_combine ttag_combine.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+idf_combine:
+ ${CC} ${CFLAGS} -o idf_combine idf_combine.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+bpm_combine:
+ ${CC} ${CFLAGS} -o bpm_combine bpm_combine.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+get_shift:
+ ${CC} ${CFLAGS} -o get_shift get_shift.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_pack:
+ ${CC} ${CFLAGS} -o cf_pack cf_pack.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_nvo:
+ ${CC} ${CFLAGS} -o cf_nvo cf_nvo.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_reflux:
+ ${CC} ${CFLAGS} -o cf_reflux cf_reflux.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_xcorr:
+ ${CC} ${CFLAGS} -o cf_xcorr cf_xcorr.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+modhead:
+ ${CC} ${CFLAGS} -o modhead modhead.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve:
+ ${CC} ${CFLAGS} -o ttag_lightcurve ttag_lightcurve.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve_periodogram:
+ ${CC} ${CFLAGS} -o ttag_lightcurve_periodogram ttag_lightcurve_periodogram.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+mjd2hjd: mjd2hjd.c gethmjd.c
+ ${CC} ${CFLAGS} -o mjd2hjd mjd2hjd.c gethmjd.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve_channel_sum:
+ ${CC} ${CFLAGS} -o ttag_lightcurve_channel_sum ttag_lightcurve_channel_sum.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve_mjd2hmjd : ttag_lightcurve_mjd2hmjd.c gethmjd.c
+ ${CC} ${CFLAGS} -o ttag_lightcurve_mjd2hmjd ttag_lightcurve_mjd2hmjd.c gethmjd.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+ttag_lightcurve_combine:
+ ${CC} ${CFLAGS} -o ttag_lightcurve_combine ttag_lightcurve_combine.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+idf_screen:
+ ${CC} ${CFLAGS} -o idf_screen idf_screen.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+remove_target_orbital_motion: remove_target_orbital_motion.c gethmjd.c
+ ${CC} ${CFLAGS} -o remove_target_orbital_motion remove_target_orbital_motion.c gethmjd.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+idf_cut:
+ ${CC} ${CFLAGS} -o idf_cut idf_cut.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+extract_jitter:
+ ${CC} ${CFLAGS} -o extract_jitter extract_jitter.c \
+ ${FUSELIBDIR} ${LIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
diff --git a/src/analysis/bpm_combine.c b/src/analysis/bpm_combine.c
new file mode 100644
index 0000000..86ec7d0
--- /dev/null
+++ b/src/analysis/bpm_combine.c
@@ -0,0 +1,548 @@
+
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSEbpm_combine
+ *****************************************************************************
+ *
+ * Synopsis: bpm_combine output_bpm_file combined_idf_file
+ *
+ *
+ * Description: Creates a bpm file associated with a combined idf file
+ * It gets the names of the idf files from the combined idf
+ * file header. It gets the name of the bpm files from the idf
+ * files header. These bpm files are then combined using the
+ * offset information provided in the combined idf file header.
+ * The BPM_CAL keyword is updated in the combined idf file
+ * header.
+ *
+ * WARNING: all the single exposure IDF files (who took part in
+ * the creation of the idf_file) and their associated BPM files
+ * must be in the working directory.
+ *
+ *
+ * History: 12/03/03 bjg v1.0 Begin work.
+ * 12/05/03 bjg First version that compiles
+ *
+ * 12/10/03 bjg Accept now only idf as parameter
+ * Updated NSPEC keyword and
+ * SPECxxx, WOFFLxxx, WOFFSxxx
+ * keywords
+ * Removed paths in filenames
+ * written into header.
+ * 04/05/04 bjg Remove unused variables
+ * Change formats to match arg
+ * types in printf
+ * 05/25/04 bjg Skip when BPM_CAL unpopulated
+ * or not present.
+ * 04/13/05 wvd v2.0 combined_idf_file may be
+ * replaced by a file containing
+ * a list of BPM files. The first
+ * line of this file must contain
+ * the number of entries that
+ * follow.
+ *
+ ****************************************************************************/
+
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include "calfuse.h"
+
+typedef char filename[FLEN_CARD];
+
+
+
+static char CF_PRGM_ID[]= "bpm_combine";
+static char CF_VER_NUM[]= "2.0";
+
+int main(int argc,char *argv[]){
+
+ char date[FLEN_CARD]={'\0'};
+ char rootname[FLEN_CARD];
+ char *corrected_filename;
+ char *string_pointer;
+
+ int felem_hdu2;
+
+ char stime[FLEN_CARD],keyword[FLEN_CARD];
+
+
+
+ time_t vtime;
+
+ fitsfile *infits,*outfits,*idffits;
+ char *has_bpm_list;
+ filename *filelist;
+ double *expstartlist;
+ double *expendlist;
+ long *neventslist;
+ double *sicshiftlist;
+ double *lifshiftlist;
+ double *exptimelist;
+
+ double delta_t;
+
+ filename tempstring,tempstring2;
+ double tempdouble;
+ long templong;
+ float tempfloat;
+ char tempchar;
+
+ double minexpstart;
+ int minindex;
+
+ int nfiles;
+
+ int intnull=0,anynull;
+ int ncol;
+
+ int status=0;
+ int hdutype=0;
+ int tref = 0;
+
+ long nevents=0;
+ long n_real_events=0;
+ long i,j,istart;
+
+
+ float * xfield,*yfield,*weightfield,*lambdafield;
+ char *channelfield;
+
+ char fmt_byte[FLEN_CARD],fmt_float[FLEN_CARD],fmt_short[FLEN_CARD];
+
+ double totalexptime=0, rawtime=0;
+ long neventscreened=0, neventscreenedpha=0;
+ float timescreened=0, timesaa=0, timelowlimbangle=0, timeburst=0, timejitter=0,timenight=0;
+
+
+
+ int hdu2_tfields=5;
+
+ char hdu2_extname[]="POTHOLE_DATA"; /* Name of this extension */
+
+ char *hdu2_ttype[]={"X", "Y", "CHANNEL", "WEIGHT", "LAMBDA"};
+
+ char *hdu2_tform[5]; /* We'll assign values when we know
+ the number of elements in the data set. */
+
+
+ char *hdu2_tunit[]={"PIXELS", "PIXELS", "UNITLESS", "UNITLESS", "ANGSTROMS"};
+
+
+ FILE *fp=NULL;
+ char line[FLEN_FILENAME];
+ int maxline=FLEN_FILENAME;
+
+
+ if (argc != 3) {
+ printf("Incorrect number of arguments.\n");
+ printf("Calling sequence:bpm_combine bpm_file combined_idf_file\n");
+ printf("Final argument may be the name of a file containing a list of BPM files.\n");
+ printf("First line must be number of BPM files in list.\n");
+ exit(1);
+ }
+
+ /* Initialize error checking. */
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Started execution.");
+
+ /* get and display time */
+ vtime = time(NULL) ;
+ strcpy(stime,ctime(&vtime));
+
+ fits_open_file(&idffits,argv[2],READONLY,&status);
+ if (status) {
+ status = 0;
+ if ((fp = fopen(argv[2], "r")) == NULL) {
+ printf("Can't open file %s\n", argv[2]);
+ return 1;
+ }
+ if ((fgets(line, maxline, fp)) == NULL) {
+ printf("Error reading file %s\n", argv[2]);
+ return 1;
+ }
+ sscanf(line,"%d",&nfiles);
+ }
+ else FITS_read_key(idffits,TINT,"NSPEC",&nfiles,NULL,&status);
+
+ filelist = (filename *)malloc(nfiles*sizeof(filename));
+ neventslist = (long *)malloc(nfiles*sizeof(long));
+ sicshiftlist = (double *)calloc((size_t)nfiles,sizeof(double));
+ lifshiftlist = (double *)calloc((size_t)nfiles,sizeof(double));
+ expstartlist = (double *)malloc(nfiles*sizeof(double));
+ expendlist = (double *)malloc(nfiles*sizeof(double));
+ exptimelist = (double *)malloc(nfiles*sizeof(double));
+ has_bpm_list = (char *)malloc(nfiles*sizeof(char));
+
+ for (i=0; i<nfiles;i++) {
+
+ has_bpm_list[i]=1;
+
+ if (fp != NULL) {
+ if((fgets(line, maxline, fp)) == NULL) {
+ printf("Error reading %s\n", argv[2]);
+ return 1;
+ }
+ sscanf(line, "%s", filelist[i]);
+ }
+ else {
+ /* Read name of individual IDF file from combined file header. */
+ sprintf(tempstring, "SPEC%.3ld", i+1);
+ FITS_read_key(idffits,TSTRING,tempstring,tempstring2,NULL,&status);
+ /* Open individual IDF file and read name of associated BPM file. */
+ FITS_open_file(&infits,tempstring2,READONLY,&status);
+ fits_read_key(infits,TSTRING,"BPM_CAL",filelist[i],NULL,&status);
+ if (status) {
+ status=0;
+ FITS_close_file(infits,&status);
+ printf("BPM_CAL keyword not found in IDF %s; skipping.\n",tempstring2);
+ has_bpm_list[i]=0;
+ filelist[i][0]='\0';
+ continue;
+ }
+ /* Close individual IDF file. */
+ FITS_close_file(infits,&status);
+
+ /* These keywords don't apply to a user-provided list of BPM files. */
+ sprintf(tempstring, "WOFFL%.3ld", i+1);
+ FITS_read_key(idffits,TDOUBLE,tempstring,&lifshiftlist[i],NULL,&status);
+
+ sprintf(tempstring, "WOFFS%.3ld", i+1);
+ FITS_read_key(idffits,TDOUBLE,tempstring,&sicshiftlist[i],NULL,&status);
+ }
+
+ /* Open individual BPM file. */
+ fits_open_file(&infits,filelist[i],READONLY,&status);
+ if (status) {
+ status=0;
+ printf("Could not open BPM %s for IDF %s; BPM_CAL keyword may be incorrectly populated; skipping.\n",filelist[i],tempstring2);
+ has_bpm_list[i]=0;
+ filelist[i][0]='\0';
+ continue;
+ }
+
+ FITS_read_key(infits,TDOUBLE,"EXPSTART",&(expstartlist[i]),NULL,&status);
+ FITS_read_key(infits,TDOUBLE,"EXPEND",&(expendlist[i]),NULL,&status);
+
+ FITS_read_key(infits,TDOUBLE,"EXPTIME",&(exptimelist[i]),NULL,&status);
+ totalexptime+=exptimelist[i];
+
+ FITS_read_key(infits,TDOUBLE,"RAWTIME",&(tempdouble),NULL,&status);
+ rawtime+=tempdouble;
+
+ FITS_read_key(infits,TLONG,"NBADEVNT",&templong,NULL,&status);
+ neventscreened+=templong;
+ FITS_read_key(infits,TLONG,"NBADPHA",&templong,NULL,&status);
+ neventscreenedpha+=templong;
+
+ FITS_read_key(infits,TFLOAT,"EXP_BAD",&tempfloat,NULL,&status);
+ timescreened+=tempfloat;
+ FITS_read_key(infits,TFLOAT,"EXP_SAA",&tempfloat,NULL,&status);
+ timesaa+=tempfloat;
+ FITS_read_key(infits,TFLOAT,"EXP_LIM",&tempfloat,NULL,&status);
+ timelowlimbangle+=tempfloat;
+ FITS_read_key(infits,TFLOAT,"EXP_BRST",&tempfloat,NULL,&status);
+ timeburst+=tempfloat;
+ FITS_read_key(infits,TFLOAT,"EXP_JITR",&tempfloat,NULL,&status);
+ timejitter+=tempfloat;
+ FITS_read_key(infits,TFLOAT,"EXPNIGHT",&tempfloat,NULL,&status);
+ timenight+=tempfloat;
+
+ FITS_read_key(infits,TFLOAT,"NEVENTS",&templong,NULL,&status);
+ n_real_events+=templong;
+
+
+ FITS_movabs_hdu(infits,2,&hdutype,&status);
+
+ FITS_read_key(infits,TSTRING,"TFORM1",&tempstring,NULL,&status);
+ sscanf(tempstring,"%ld%c",&neventslist[i],&tempchar);
+ nevents+=neventslist[i];
+
+ FITS_close_file(infits,&status);
+
+ }
+
+ if (fp != NULL) fclose(fp);
+ else FITS_close_file(idffits,&status);
+
+
+
+
+
+
+ printf("---SORTING INPUT FILES IN TIME ORDER---\n") ;
+
+ for (i=0; i<nfiles-1;i++) {
+ if (!(has_bpm_list[i])) continue;
+ minexpstart=expstartlist[i];
+ minindex=i;
+ for (j=i+1; j<nfiles;j++) {
+ if (!(has_bpm_list[j])) continue;
+ if (expstartlist[j]<minexpstart){
+ minexpstart=expstartlist[j];
+ minindex=j;
+ }
+ }
+
+ strcpy(tempstring,filelist[minindex]);
+ strcpy(filelist[minindex],filelist[i]);
+ strcpy(filelist[i],tempstring);
+
+ tempdouble=expstartlist[minindex];
+ expstartlist[minindex]=expstartlist[i];
+ expstartlist[i]=tempdouble;
+
+ tempdouble=expendlist[minindex];
+ expendlist[minindex]=expendlist[i];
+ expendlist[i]=tempdouble;
+
+ tempdouble=exptimelist[minindex];
+ exptimelist[minindex]=exptimelist[i];
+ exptimelist[i]=tempdouble;
+
+ templong=neventslist[minindex];
+ neventslist[minindex]=neventslist[i];
+ neventslist[i]=templong;
+
+ tempdouble=lifshiftlist[minindex];
+ lifshiftlist[minindex]=lifshiftlist[i];
+ lifshiftlist[i]=tempdouble;
+
+ tempdouble=sicshiftlist[minindex];
+ sicshiftlist[minindex]=sicshiftlist[i];
+ sicshiftlist[i]=tempdouble;
+
+ }
+
+ istart=-1;
+
+ for (i=0; i<nfiles;i++) {
+ if (!(has_bpm_list[i])) continue;
+ printf("%s %7.1f %7.1f %4ld %f %f\n",filelist[i],expstartlist[i],expendlist[i],neventslist[i],lifshiftlist[i],sicshiftlist[i]);
+ if (istart==-1) istart=i;
+ }
+ printf("\n");
+
+ if (istart==-1) {
+ printf("No BPM files found. Exiting\n");
+ exit(0);
+ }
+
+
+
+
+ printf("--------CREATING OUTPUT FILE-----\n");
+
+ FITS_open_file(&infits,filelist[istart],READONLY,&status);
+ FITS_create_file(&outfits,argv[1],&status);
+
+
+
+
+ printf("--------WRITING MAIN HEADER-----\n");
+
+ FITS_copy_hdu(infits,outfits,0,&status);
+
+ FITS_read_key(infits,TSTRING,"ROOTNAME",rootname,NULL,&status);
+
+ rootname[8]='9';
+ rootname[9]='9';
+ rootname[10]='9';
+
+ FITS_update_key(outfits,TSTRING,"ROOTNAME",rootname,NULL,&status);
+
+ string_pointer=strrchr(argv[1],'/');
+ if (string_pointer==NULL) corrected_filename=argv[1];
+ else corrected_filename=&(string_pointer[1]);
+
+ FITS_update_key(outfits,TSTRING,"FILENAME",corrected_filename,NULL,&status);
+
+ FITS_update_key(outfits,TSTRING,"EXP_ID","999",NULL,&status);
+
+ string_pointer=strrchr(argv[2],'/');
+ if (string_pointer==NULL) corrected_filename=argv[2];
+ else corrected_filename=&(string_pointer[1]);
+
+
+ if (fp == NULL)
+ FITS_update_key(outfits,TSTRING,"IDF_FILE",corrected_filename,NULL,&status);
+
+
+
+
+ fits_get_system_time(date, &tref, &status);
+
+ FITS_update_key(outfits,TSTRING,"DATE",date,NULL,&status);
+
+ FITS_update_key(outfits,TDOUBLE,"EXPEND",&expendlist[nfiles-1],NULL,&status);
+ FITS_update_key(outfits,TDOUBLE,"EXPTIME",&totalexptime,NULL,&status);
+ FITS_update_key(outfits,TDOUBLE,"RAWTIME",&rawtime,NULL,&status);
+ FITS_update_key(outfits,TLONG,"NEVENTS",&n_real_events,NULL,&status);
+ FITS_update_key(outfits,TLONG,"NBADEVNT",&neventscreened,NULL,&status);
+ FITS_update_key(outfits,TLONG,"NBADPHA",&neventscreenedpha,NULL,&status);
+ FITS_update_key(outfits,TFLOAT,"EXP_BAD",&(timescreened),NULL,&status);
+ FITS_update_key(outfits,TFLOAT,"EXP_SAA",&(timesaa),NULL,&status);
+ FITS_update_key(outfits,TFLOAT,"EXP_LIM",&(timelowlimbangle),NULL,&status);
+ FITS_update_key(outfits,TFLOAT,"EXP_BRST",&(timeburst),NULL,&status);
+ FITS_update_key(outfits,TFLOAT,"EXP_JITR",&(timejitter),NULL,&status);
+ FITS_update_key(outfits,TFLOAT,"EXPNIGHT",&(timenight),NULL,&status);
+
+ fits_write_history(outfits," COMBINED WITH BPM_COMBINE ",&status);
+
+ FITS_update_key(outfits,TINT,"NSPEC",&nfiles,NULL,&status);
+
+ for (i=0;i<nfiles;i++){
+
+ if (!(has_bpm_list[i])) continue;
+
+ string_pointer=strrchr(filelist[i],'/');
+ if (string_pointer==NULL) corrected_filename=filelist[i];
+ else corrected_filename=&(string_pointer[1]);
+
+ sprintf(keyword, "SPEC%.3ld", i+1);
+ FITS_update_key(outfits,TSTRING,keyword,corrected_filename,NULL,&status);
+ sprintf(keyword, "WOFFL%.3ld", i+1);
+ FITS_update_key(outfits,TFLOAT,keyword,&lifshiftlist[i],NULL,&status);
+ sprintf(keyword, "WOFFS%.3ld", i+1);
+ FITS_update_key(outfits,TFLOAT,keyword,&sicshiftlist[i],NULL,&status);
+
+
+
+ }
+
+
+
+
+ FITS_close_file(infits,&status);
+
+ printf("--------PREPARING EVENTS LIST HDU-----\n");
+
+ /* Generate the tform array */
+ sprintf(fmt_byte, "%ldB", nevents);
+ sprintf(fmt_float, "%ldE", nevents);
+ sprintf(fmt_short, "%ldI", nevents);
+
+ hdu2_tform[0] = fmt_float;
+ hdu2_tform[1] = fmt_float;
+ hdu2_tform[2] = fmt_byte;
+ hdu2_tform[3] = fmt_float;
+ hdu2_tform[4] = fmt_float;
+
+
+
+ /* Append a new empty binary table to the output file */
+ FITS_create_tbl(outfits, BINARY_TBL, 1, hdu2_tfields, hdu2_ttype, hdu2_tform,
+ hdu2_tunit, hdu2_extname, &status);
+
+
+
+
+
+
+
+ printf("--------COMBINING HDU-----\n");
+ felem_hdu2=1;
+ for (i=0;i<nfiles;i++){
+ if (!(has_bpm_list[i])) continue;
+
+
+ delta_t=(expstartlist[i]-expstartlist[0])*3600*24;
+
+ FITS_open_file(&infits,filelist[i],READONLY,&status);
+
+
+ FITS_movabs_hdu(infits, 2, &hdutype, &status);
+ FITS_movabs_hdu(outfits, 2, &hdutype, &status);
+ printf("Processing file %s\n",filelist[i]);
+
+ xfield=(float *)malloc(neventslist[i]*sizeof(float));
+ yfield=(float *)malloc(neventslist[i]*sizeof(float));
+ channelfield=(char *)malloc(neventslist[i]*sizeof(char));
+ weightfield=(float *)malloc(neventslist[i]*sizeof(float));
+ lambdafield=(float *)malloc(neventslist[i]*sizeof(float));
+
+
+ FITS_get_colnum(infits, TRUE, "X", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, neventslist[i], &intnull,
+ xfield, &anynull, &status);
+
+
+ FITS_get_colnum(infits, TRUE, "Y", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, neventslist[i], &intnull,
+ yfield, &anynull, &status);
+
+
+ FITS_get_colnum(infits, TRUE, "CHANNEL", &ncol, &status);
+ FITS_read_col(infits, TBYTE, ncol, 1, 1, neventslist[i], &intnull,
+ channelfield, &anynull, &status);
+
+
+ FITS_get_colnum(infits, TRUE, "WEIGHT", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, neventslist[i], &intnull,
+ weightfield, &anynull, &status);
+
+
+ FITS_get_colnum(infits, TRUE, "LAMBDA", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, neventslist[i], &intnull,
+ lambdafield, &anynull, &status);
+
+
+
+
+ for (j=0;j<neventslist[i];j++){
+ if (channelfield[j]<5) lambdafield[j]=lambdafield[j]+lifshiftlist[i];
+ if (channelfield[j]>4) lambdafield[j]=lambdafield[j]+sicshiftlist[i];
+ weightfield[j]=weightfield[j]*exptimelist[i]/totalexptime;
+ }
+
+
+
+ FITS_write_col(outfits, TFLOAT, 1, 1, felem_hdu2, neventslist[i], xfield, &status);
+ FITS_write_col(outfits, TFLOAT, 2, 1, felem_hdu2, neventslist[i], yfield, &status);
+ FITS_write_col(outfits, TBYTE, 3, 1, felem_hdu2, neventslist[i], channelfield, &status);
+ FITS_write_col(outfits, TFLOAT, 4, 1, felem_hdu2, neventslist[i], weightfield, &status);
+ FITS_write_col(outfits, TFLOAT, 5, 1, felem_hdu2, neventslist[i], lambdafield, &status);
+
+
+ free(xfield);
+ free(yfield);
+ free(channelfield);
+ free(weightfield);
+ free(lambdafield);
+
+ felem_hdu2+=neventslist[i];
+
+ FITS_close_file(infits,&status);
+
+
+ }
+
+ printf("--------CLOSING OUTPUT FILE-----\n");
+
+
+ FITS_close_file(outfits,&status);
+
+
+ if (fp == NULL) {
+ FITS_open_file(&idffits,argv[2],READWRITE,&status);
+
+ string_pointer=strrchr(argv[1],'/');
+ if (string_pointer==NULL) corrected_filename=argv[1];
+ else corrected_filename=&(string_pointer[1]);
+
+ FITS_update_key(idffits,TSTRING,"BPM_CAL",corrected_filename,NULL,&status);
+ FITS_close_file(idffits,&status);
+ }
+
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Finished execution.");
+ return EXIT_SUCCESS;
+
+}
+
+
diff --git a/src/analysis/cf_arith.c b/src/analysis/cf_arith.c
new file mode 100644
index 0000000..94e40e9
--- /dev/null
+++ b/src/analysis/cf_arith.c
@@ -0,0 +1,2154 @@
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: cf_arith infile1 op infile2 outfile
+ *
+ * Description: This is a generic utility program that performs arithmetic
+ * operations on two FUSE FITS files. The files must
+ * contain extracted FUSE spectra.
+ * Input files are assumed to have 6 columns in a binary
+ * table in the first extension (wavelength, flux, error, quality,
+ * counts, counts_error). Files with 4 columns (no counts or
+ * counts_error) are also handled for compatibility with
+ * pipeline output written prior to 12/1/99.
+ *
+ * (The next paragraph is included for completeness, but is
+ * not expected to be applicable to most users).
+ * If infile1 and infile2 have the same number of extensions,
+ * the specified operation is performed for each extension
+ * (outfile_ext_i = infile1_ext_i op infile2_ext_i).
+ * If infile2 has a single extension, the operation is performed
+ * for each extension in infile1 with the extension in infile2
+ * (outfile_ext_i = infile1_ext_i op infile2_ext_1).
+ *
+ * infile1 and infile2 must have the same number of elements
+ * in each binary table (ie. binned by the same factor).
+ * infile2 may be a numeric string instead of a file.
+ * The header in outfile will be the same as for infile1,
+ * plus some HISTORY lines.
+ * No check is performed that the wavelengths in infile2 match
+ * those in infile1.
+ * It is assumed that error arrays contain errors, not variances.
+ *
+ * If infile2 is the string "EXPTIME" (without the quotes)
+ * operand 2 is set to the exposure time in the header of infile1.
+ *
+ * valid choices for the operation "op" are:
+ * +, -, *, /, avg_t, avg_s, repl_d, repl_e, boxcar, delta,
+ * min, max, shift, bin, deriv, addnoise
+ *
+ * avg_t = average weighted by exposure time
+ * avg_s = average weighted by sigma (errors)
+ * avg_t, avg_s valid only if infile2 is a fits file.
+ * repl_d = replace data in operand1 with data from operand2
+ * repl_e = replace errors in operand1 with errors from operand2
+ * boxcar = smooth data in operand1 with moving boxcar
+ * of width operand2. If operand2 is a FITS file,
+ * the "FLUX" column is used as the width. This
+ * permits application of variable smoothing.
+ * delta = adds delta functions to operand 1 every 100 pixels;
+ * height is equal to operand 2 (must be a scalar).
+ * Used only for creating test spectra.
+ * shift = shift data by the specified number of pixels. Operand2
+ * must be an integer. A positive shift moves the data
+ * to higher pixel numbers.
+ * bin = bin data by the specified number of pixels. Operand2
+ * must be an integer. The flux column is averaged, the
+ * counts column is summed.
+ * deriv = take derivative of input: out[i] = in[i+1] - in[i]
+ * operand 2 is ignored for this!
+ * addnoise = a uniformly distributed random number in the range
+ * +/-operand2 is added pixel-by-pixel to the flux
+ * Used only for creating test spectra.
+ *
+ * If op = "+" and the second operand is a file (not a scalar),
+ * or if op = "avg_t" or if op = "avg_s", the exposure
+ * time in the output is the sum of the exposure times
+ * in the input files.
+ *
+ * For op1 min op2 out: op1 is replaced by op2 if op1 < op2.
+ * (op2 sets a min value for the flux)
+ * For op1 max op2 out: op1 is replaced by op2 if op1 > op2.
+ * (op2 sets a max value for the flux)
+ *
+ * The same operations are performed on the counts/countserr
+ * columns as on the flux/fluxerr columns. In most cases this
+ * leads to reasonable results. However, in a few cases, such
+ * as addition or subtraction of a scalar, the result is likely
+ * to be meaningless for either the flux or counts columns.
+ * Exceptions: MIN, MAX, REPL_D, REPL_E, DELTA, only affect
+ * the flux and fluxerr columns. The counts and countserror
+ * columns are unaffected.
+ *
+ * Note that avg_t and avg_s also average the counts; in some
+ * cases the user may have really wanted the counts to be summed!
+ *
+ * NOTE: Must enclose * in quotes (ie. "*") or the shell
+ * will expand it into filenames in the pwd!
+ *
+ *
+ * History: 08/15/99 jwk started work
+ * 10/25/99 v1.1 jwk avg_t,_s sum exp times in output
+ * 11/30/99 jwk handle either 4 or 6-column files
+ * 01/06/00 v1.2 jwk add bin option
+ * 05/01/00 v1.3 jwk handle byte or short quality flags
+ * 09/20/00 v1.4 jwk add derivative operation
+ * 10/11/00 v1.5 jwk update FILENAME keyword in output file
+ * 12/11/00 v1.6 jwk improve numeric accuracy of error prop.
+ * 01/23/01 v1.7 jwk smooth quality rather than sum when
+ * doing BOXCAR, to avoid overflow of
+ * short datasize.
+ * 10/10/01 v1.8 jwk add handling of eff area files
+ * 05/30/03 v1.9 jwk change timeval from long to time_t; put
+ * ifdef SOLARIS/endif around ieee_retro
+ * spec field width for final timestamp
+ * (make consistent with calfuse version)
+ * 02/04/04 v2.0 jwk implement addnoise option
+ * 02/25/04 v2.1 jwk check for zero errors in avg_s code
+ * 03/06/04 v3.0 jwk add support for calfuse 3.0 files
+ * 04/05/04 v3.1 bjg Declarations for cf_wrspec7 and
+ * cf_wrspec_cf2
+ * Include ctype.h
+ * Correct formats to match argument
+ * types in printf
+ * Remove unused variable long npix
+ * Casting to char * arg of setstate
+ * Remove local definitions of
+ * initstate() and setstate()
+ * Correct use of cf_wrspec7
+ * 08/26/05 v3.2 wvd Change name from cf_arith3 to cf_arith.
+ * If no arguments, don't return error.
+ * Just print message and exit.\
+ * 08/27/07 v3.3 bot Added L to long l.399 and 537
+ *
+ ****************************************************************************/
+
+#include <time.h>
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include "calfuse.h"
+#include <ctype.h>
+
+#define PLUS 1
+#define MINUS 2
+#define MULT 3
+#define DIV 4
+#define AVG_T 5
+#define AVG_S 6
+#define REPL_D 7
+#define REPL_E 8
+#define BOXCAR 9
+#define DELTA 10
+#define MIN 11
+#define MAX 12
+#define SHIFT 13
+#define BIN 14
+#define DERIV 15
+#define ADDNOISE 16
+
+/* arbitrary value for error when no data is present */
+#define DEF_ERROR 1.e-3
+
+#define MAX_RAND 0x7fffffff
+
+static char CF_PRGM_ID[] = "cf_arith";
+static char CF_VER_NUM[] = "3.3";
+
+
+void cf_wrspec7(fitsfile *outfits, long npts, float *wave, float *flux,
+ float *error, long *counts, float *weights,
+ float *bkgd,short *pothole);
+void cf_wrspec_cf2(fitsfile *outfits, int npts, float *wave,
+ float *spec, float *errs, short *qual,
+ float *counts, float *cntserr, int ncol,
+ int areaflag);
+
+
+
+
+int main(int argc, char *argv[])
+{
+ char *timestr;
+ time_t timeval;
+ char infile1[80], infile2[80], outfile[80];
+ char comment[FLEN_CARD];
+ char expt_comment[FLEN_CARD];
+ char errstr[80];
+ char datatype[20];
+ int areaflag;
+ int nbin;
+ int next_1, next_2;
+ int status=0, anynull=0, intnull=0;
+ int hdutype_1, hdutype_2, hdutype_o;
+ int hdunum_1, hdunum_2, hdunum_o;
+ long npix_1, npix_2, npix_o;
+ long naxis2_1, naxis2_2;
+ int fluxcol, wavecol, errorcol, qualcol, cntscol, cntserrcol;
+ int bkgdcol, wgtscol;
+ int tfields_1, tfields_2;
+ int opcode;
+ int cf_version;
+ long i, j, k, k1, k2;
+ int arg2_scalar;
+ int p_shift;
+ float arg2_val;
+ float swave, sflux, sferr, scnts, scerr, spix;
+ float sbkgd, swgts;
+ long lqual, slcts;
+ short squal;
+ short *qual1, *qual2, *qual_o;
+ float *wave1, *flux1, *flxerr1, *cnts1, *cntserr1;
+ float *flux2, *flxerr2, *cnts2, *cntserr2;
+ float *flux_o, *flxerr_o, *cnts_o, *cntserr_o;
+ float *wave_o;
+ float *wgts1, *wgts2, *wgts_o;
+ float *bkgd1, *bkgd2, *bkgd_o;
+ long *lcts1, *lcts2, *lcts_o;
+ char tformstr[FLEN_CARD];
+ char key_str[FLEN_CARD];
+ char qual_lbl[FLEN_CARD];
+ float f1, f2, fn;
+ float tmp1, tmp2, tmp3, tmp4;
+ float exptime_1, exptime_2, exptime_o;
+ fitsfile *infits_1, *infits_2, *outfits;
+ int chkop();
+ int check_num();
+ void padstr();
+ /* following items used by random number generator */
+ clock_t clock(); /* system clock function */
+ int ns; /* used by random # generator */
+ unsigned long seed; /* random # generator seed */
+ /* char *initstate(), *setstate(); */
+ double rand1();
+
+/* Initialize random number generator state array. */
+ static unsigned long state1[32] = { 3, 0x9a319039,
+ 0x32d9c024, 0x9b663182, 0x5da1f342, 0x7449e56b,
+ 0xbeb1dbb0, 0xab5c5918, 0x946554fd, 0x8c2e680f,
+ 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a,
+ 0x1588ca88, 0xe369735d, 0x904f35f7, 0xd7158fd6,
+ 0x6fa6f051, 0x616e6b96, 0xac94efdc, 0xde3b81e0,
+ 0xdf0a6fb5, 0xf103bc02, 0x48f340fb, 0x36413f93,
+ 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e,
+ 0x8999220b, 0x27fb47b9 };
+
+
+ /* perform an initial call to clock() - clock() returns the elapsed time
+ * since the first call, so in order to use it for a random # generator
+ * seed later we have to get it started here. Subsequent calls follow
+ * opening of the first file, so that should provide some run-to-run
+ * variations.
+ */
+ seed = clock();
+
+ /* Enter a timestamp into the log. */
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Begin Processing");
+
+ /* Initialize error checking */
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+
+ /* check command line */
+ if (argc != 5) {
+ printf("Usage: cf_arith infile1 op infile2 outfile\n");
+ return 1;
+ }
+
+ strcpy (infile1, argv[1]);
+ strcpy (infile2, argv[3]);
+ strcpy (outfile, argv[4]);
+
+ if ((opcode = chkop (argv[2])) == 0)
+ {
+ sprintf (comment,"Undefined operation: %s\n", argv[2]);
+ cf_if_error (comment);
+ }
+
+ /* Open input file(s) */
+
+ FITS_open_file(&infits_1, infile1, READONLY, &status);
+
+ /* get number of extensions in operand1 */
+ FITS_get_num_hdus (infits_1, &next_1, &status);
+ next_1--;
+
+ /* get exposure time in case we need it later. */
+ ffgky(infits_1, TFLOAT, "EXPTIME", &exptime_1, expt_comment, &status);
+ if (status)
+ {
+ fprintf (stderr, "Keyword EXPTIME not found; set exptime_1=1.0\n");
+ exptime_1 = 1.0;
+ status = 0;
+ }
+ exptime_o = exptime_1;
+
+ /* check nature of second operand: is it a number? */
+ /* can have leading sign, and may contain E,e,D,d and additional sign */
+ arg2_scalar = check_num (argv[3]);
+ if (arg2_scalar)
+ arg2_val = atof (argv[3]);
+
+ /* Also allow the possibility of having argv[3] = "EXPTIME": */
+ if (!strcmp (argv[3], "EXPTIME"))
+ {
+ arg2_scalar = TRUE;
+ arg2_val = exptime_1;
+ }
+
+ /* check for valid operand if operation is SHIFT: */
+ p_shift = 0;
+ if (opcode == SHIFT)
+ {
+ if (!arg2_scalar)
+ cf_if_error ("SHIFT requires scalar argument!\n");
+
+ /* convert argument to an integer */
+ p_shift = (int) strtol (argv[3], (char **)NULL, 10);
+ }
+
+ /* check for valid operand if operation is BIN: */
+ nbin = 1;
+ if (opcode == BIN)
+ {
+ if (!arg2_scalar)
+ cf_if_error ("BIN requires scalar argument!\n");
+
+ /* convert argument to an integer */
+ nbin = (int) strtol (argv[3], (char **)NULL, 10);
+ if (nbin < 1)
+ {
+ sprintf (errstr, "bin factor = %d; must be >0!\n", nbin);
+ cf_if_error (errstr);
+ }
+ }
+
+ /* Check for valid operand if operation is ADDNOISE:
+ * I suppose we could relax this and take a pixel-by-pixel amplitude
+ * from a spectrum, but let's keep it simple for now.
+ * Also initialize random number generator.
+ */
+ if (opcode == ADDNOISE)
+ {
+ if (!arg2_scalar)
+ cf_if_error ("ADDNOISE requires scalar argument!\n");
+
+ /* initialize random number generator */
+ /* the local clock function doesn't change rapidly enough to be
+ * useful, even though it is nominally at microsecond resolution */
+ /* seed = 2 * (clock() & 0x0ffff) + 1; */
+ time (&timeval);
+ seed = 2 * timeval + 1;
+
+ ns = 128;
+ initstate (seed, (char *) state1, ns);
+ setstate ((char *)state1);
+ }
+
+ /* bypass operand2 if op= derivative; we ignore op2 in this case*/
+ if (opcode == DERIV)
+ arg2_scalar = TRUE;
+
+ if (!arg2_scalar)
+ {
+ FITS_open_file (&infits_2, infile2, READONLY, &status);
+ FITS_get_num_hdus (infits_2, &next_2, &status);
+ next_2--;
+
+ if ((next_2 != next_1) && (next_2 != 1))
+ {
+ fprintf (stderr, "file %s has %d extensions.\n", infile1, next_1);
+ fprintf (stderr, "file %s has %d extensions.\n", infile2, next_2);
+ cf_if_error ("Illegal combination, aborting!\n");
+ }
+ ffgky(infits_2, TFLOAT, "EXPTIME", &exptime_2, expt_comment, &status);
+ if (status)
+ {
+ fprintf (stderr, "Keyword EXPTIME not found; set exptime_2=1.0\n");
+ exptime_2 = 1.0;
+ status = 0;
+ }
+ }
+
+ /* open output file */
+
+ remove(outfile); /*In case the old file name exists*/
+ FITS_create_file (&outfits, outfile, &status);
+
+ /* Copy header from first operand. The output file will have the same
+ * number of extensions as operand1.
+ */
+ /* cf_cp_hdr(infits_1, 1, outfits, 1); */
+ FITS_copy_header (infits_1, outfits, &status);
+
+ /* Loop over extensions */
+ for ( i = 1; i <= next_1; i++ )
+ {
+ hdunum_1=i+1;
+
+ FITS_movabs_hdu(infits_1, hdunum_1, &hdutype_1, &status);
+ /* for Calfuse 2 and before, array length is specified by NAXIS2.
+ * For Calfuse 3, need to get it from TFORM1.
+ */
+ FITS_read_key(infits_1, TLONG, "NAXIS2", &naxis2_1, NULL, &status);
+ if (naxis2_1 > 1L)
+ npix_1 = naxis2_1;
+ else
+ {
+ FITS_read_key(infits_1, TSTRING, "TFORM1", tformstr, NULL, &status);
+ sscanf (tformstr, "%ldE", &npix_1);
+ }
+
+
+ /* need to figure out what kind of data we have.
+ * tfields=4 implies very old calfuse files, or effective area files;
+ * tfields=6 implies calfuse 1.8 or 2.x
+ * tfields=7 implies calfuse 3.x
+ * Each has different types of data columns.
+ */
+ FITS_read_key(infits_1, TINT, "TFIELDS", &tfields_1, NULL, &status);
+
+ if ((tfields_1 == 4) || (tfields_1 == 6))
+ cf_version = 2;
+ else if (tfields_1 == 7)
+ cf_version = 3;
+ else
+ {
+ sprintf (errstr, "Expecting 4,6 or 7 cols, found %d\n", tfields_1);
+ cf_if_error (errstr);
+ }
+
+ /* Allocate data arrays */
+ wave1 = (float *) cf_malloc(sizeof(float) * npix_1);
+ flux1 = (float *) cf_malloc(sizeof(float) * npix_1);
+ flxerr1 = (float *) cf_malloc(sizeof(float) * npix_1);
+ qual1 = (short *) cf_malloc(sizeof(short) * npix_1);
+
+ if (cf_version == 2)
+ {
+ cnts1 = (float *) cf_malloc(sizeof(float) * npix_1);
+ cntserr1 = (float *) cf_malloc(sizeof(float) * npix_1);
+ }
+ else
+ {
+ lcts1 = (long *) cf_malloc(sizeof(long) * npix_1);
+ bkgd1 = (float *) cf_malloc(sizeof(float) * npix_1);
+ wgts1 = (float *) cf_malloc(sizeof(float) * npix_1);
+ }
+
+ /* Get the column numbers from file 1 */
+ FITS_read_key(infits_1, TSTRING, "TTYPE2", datatype, NULL, &status);
+ if (!strcmp(datatype, "FLUX"))
+ {
+ areaflag = FALSE;
+ FITS_get_colnum(infits_1, TRUE, "FLUX", &fluxcol, &status);
+ }
+ else
+ {
+ areaflag = TRUE;
+ FITS_get_colnum(infits_1, TRUE, "AREA", &fluxcol, &status);
+ }
+
+ FITS_get_colnum(infits_1, TRUE, "WAVE", &wavecol, &status);
+ FITS_get_colnum(infits_1, TRUE, "ERROR", &errorcol, &status);
+
+ /* don't know at present if calfuse 3.x will use "QUALITY" or
+ * "POTHOLE", so check both.
+ */
+ if (cf_version == 2)
+ FITS_get_colnum(infits_1, TRUE, "QUALITY", &qualcol, &status);
+ else
+ {
+ qualcol = 0;
+ for (j=1; j<=tfields_1; j++)
+ {
+ sprintf (key_str, "TTYPE%1ld", j);
+ FITS_read_key(infits_1, TSTRING, key_str,datatype, NULL, &status);
+ if (!strcmp (datatype, "QUALITY") || !strcmp(datatype,"POTHOLE"))
+ {
+ strcpy (qual_lbl, datatype);
+ qualcol = j;
+ }
+ }
+ if (qualcol == 0)
+ cf_if_error ("QUALITY column not found!");
+ }
+
+ if (tfields_1 == 6)
+ {
+ FITS_get_colnum(infits_1, TRUE, "COUNTS", &cntscol, &status);
+ FITS_get_colnum(infits_1, TRUE, "CNTSERR", &cntserrcol, &status);
+ }
+
+ if (tfields_1 == 7)
+ {
+ FITS_get_colnum(infits_1, TRUE, "COUNTS", &cntscol, &status);
+ FITS_get_colnum(infits_1, TRUE, "WEIGHTS", &wgtscol, &status);
+ FITS_get_colnum(infits_1, TRUE, "BKGD", &bkgdcol, &status);
+ }
+
+ FITS_read_col(infits_1, TFLOAT, fluxcol, 1L, 1L, npix_1,
+ &intnull, flux1, &anynull, &status);
+ FITS_read_col(infits_1, TFLOAT, wavecol, 1L, 1L, npix_1,
+ &intnull, wave1, &anynull, &status);
+ FITS_read_col(infits_1, TFLOAT, errorcol, 1L, 1L, npix_1,
+ &intnull, flxerr1, &anynull, &status);
+ FITS_read_col(infits_1, TSHORT, qualcol, 1L, 1L, npix_1,
+ &intnull, qual1, &anynull, &status);
+
+ if (tfields_1 == 6)
+ {
+ FITS_read_col(infits_1, TFLOAT, cntscol, 1L, 1L, npix_1,
+ &intnull, cnts1, &anynull, &status);
+ FITS_read_col(infits_1, TFLOAT, cntserrcol, 1L, 1L, npix_1,
+ &intnull, cntserr1, &anynull, &status);
+ }
+ else if (tfields_1 == 7)
+ {
+ FITS_read_col(infits_1, TLONG, cntscol, 1L, 1L, npix_1,
+ &intnull, lcts1, &anynull, &status);
+ FITS_read_col(infits_1, TFLOAT, wgtscol, 1L, 1L, npix_1,
+ &intnull, wgts1, &anynull, &status);
+ FITS_read_col(infits_1, TFLOAT, bkgdcol, 1L, 1L, npix_1,
+ &intnull, bkgd1, &anynull, &status);
+ }
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ cnts1[j] = 0.;
+ cntserr1[j] = 0.001;
+ }
+ }
+
+ if (!arg2_scalar)
+ {
+ /* for file2, stop at first extension if that is all there is */
+ if (i <= next_2)
+ {
+ hdunum_2 = i + 1;
+ FITS_movabs_hdu(infits_2, hdunum_2, &hdutype_2, &status);
+ FITS_read_key(infits_2, TLONG,"NAXIS2",&naxis2_2,NULL,&status);
+ if (naxis2_2 > 1L)
+ npix_2 = naxis2_2;
+ else
+ {
+ FITS_read_key(infits_2, TSTRING, "TFORM1", tformstr, NULL,
+ &status);
+ sscanf (tformstr, "%ldE", &npix_2);
+ }
+
+ FITS_read_key(infits_2, TINT, "TFIELDS", &tfields_2, NULL,
+ &status);
+
+ if (tfields_2 != tfields_1)
+ {
+ sprintf (errstr, "File1 has %d cols; File 2 has %d cols!\n",
+ tfields_1, tfields_2);
+ cf_if_error (errstr);
+ }
+
+ if (npix_2 != npix_1)
+ {
+ fprintf (stderr, "npix1 = %ld, npix2 = %ld\n", npix_1, npix_2);
+ cf_if_error ("Aborting");
+ }
+
+ /* Allocate data arrays */
+ flux2 = (float *) cf_malloc(sizeof(float) * npix_2);
+ flxerr2 = (float *) cf_malloc(sizeof(float) * npix_2);
+ qual2 = (short *) cf_malloc(sizeof(short) * npix_2);
+ if (cf_version == 2)
+ {
+ cnts2 = (float *) cf_malloc(sizeof(float) * npix_2);
+ cntserr2 = (float *) cf_malloc(sizeof(float) * npix_2);
+ }
+ else
+ {
+ lcts2 = (long *) cf_malloc(sizeof(long) * npix_2);
+ wgts2 = (float *) cf_malloc(sizeof(float) * npix_2);
+ bkgd2 = (float *) cf_malloc(sizeof(float) * npix_2);
+ }
+
+ /* Read the data from file 2 */
+
+ if (areaflag)
+ FITS_get_colnum(infits_2, TRUE, "AREA", &fluxcol, &status);
+ else
+ FITS_get_colnum(infits_2, TRUE, "FLUX", &fluxcol, &status);
+
+ FITS_get_colnum(infits_2, TRUE, "ERROR", &errorcol, &status);
+
+ /* don't know at present if calfuse 3.x will use "QUALITY" or
+ * "POTHOLE", so check both.
+ * (there may also be a mix of files present!)
+ */
+ if (cf_version == 2)
+ FITS_get_colnum(infits_2, TRUE, "QUALITY", &qualcol,&status);
+ else
+ {
+ qualcol = 0;
+ for (j=1; j<=tfields_2; j++)
+ {
+ sprintf (key_str, "TTYPE%1ld", j);
+ FITS_read_key(infits_2, TSTRING, key_str,datatype, NULL,
+ &status);
+ if (!strcmp (datatype, "QUALITY") ||
+ !strcmp(datatype,"POTHOLE"))
+ {
+ strcpy (qual_lbl, datatype);
+ qualcol = j;
+ }
+ }
+ if (qualcol == 0)
+ cf_if_error ("QUALITY column not found!");
+ }
+
+ if (tfields_2 == 6)
+ {
+ FITS_get_colnum(infits_2, TRUE, "COUNTS", &cntscol, &status);
+ FITS_get_colnum(infits_2, TRUE, "CNTSERR", &cntserrcol,
+ &status);
+ }
+
+ if (tfields_2 == 7)
+ {
+ FITS_get_colnum(infits_2,TRUE, "COUNTS", &cntscol, &status);
+ FITS_get_colnum(infits_2,TRUE, "WEIGHTS", &wgtscol, &status);
+ FITS_get_colnum(infits_2,TRUE, "BKGD", &bkgdcol, &status);
+ }
+
+ FITS_read_col(infits_2, TFLOAT, fluxcol, 1L, 1L, npix_2,
+ &intnull, flux2, &anynull, &status);
+ FITS_read_col(infits_2, TFLOAT, errorcol, 1L, 1L, npix_2,
+ &intnull, flxerr2, &anynull, &status);
+ FITS_read_col(infits_2, TSHORT, qualcol, 1L, 1L, npix_2,
+ &intnull, qual2, &anynull, &status);
+
+ if (tfields_2 == 6)
+ {
+ FITS_read_col(infits_2, TFLOAT, cntscol, 1L, 1L, npix_2,
+ &intnull, cnts2, &anynull, &status);
+ FITS_read_col(infits_2, TFLOAT, cntserrcol, 1L, 1L, npix_2,
+ &intnull, cntserr2, &anynull, &status);
+ }
+ else if (tfields_1 == 7)
+ {
+ FITS_read_col(infits_2, TLONG, cntscol, 1L, 1L, npix_2,
+ &intnull, lcts2, &anynull, &status);
+ FITS_read_col(infits_2, TFLOAT, wgtscol, 1L, 1L, npix_2,
+ &intnull, wgts2, &anynull, &status);
+ FITS_read_col(infits_2, TFLOAT, bkgdcol, 1L, 1L, npix_2,
+ &intnull, bkgd2, &anynull, &status);
+ }
+ else
+ {
+ for (j=0; j<npix_2; j++)
+ {
+ cnts2[j] = 0.;
+ cntserr2[j] = 0.001;
+ }
+ }
+
+ } /* end of if (i<=next_2) */
+ } /* end of if(!arg2_scalar) */
+
+ if ((opcode == BIN) && (nbin > 1))
+ {
+ if (nbin > npix_1)
+ {
+ sprintf (errstr, "bin factor = %d; must be < npix!\n", nbin);
+ cf_if_error (errstr);
+ }
+ npix_o = npix_1 / nbin;
+ }
+ else
+ npix_o = npix_1;
+
+ /* make space for output arrays */
+ flux_o = (float *) cf_malloc(sizeof(float) * npix_o);
+ flxerr_o = (float *) cf_malloc(sizeof(float) * npix_o);
+ qual_o = (short *) cf_malloc(sizeof(short) * npix_o);
+
+ if (cf_version == 2)
+ {
+ cnts_o = (float *) cf_malloc(sizeof(float) * npix_o);
+ cntserr_o = (float *) cf_malloc(sizeof(float) * npix_o);
+ }
+ else
+ {
+ lcts_o = (long *) cf_malloc(sizeof(long) * npix_o);
+ wgts_o = (float *) cf_malloc(sizeof(float) * npix_o);
+ bkgd_o = (float *) cf_malloc(sizeof(float) * npix_o);
+ }
+
+ if (opcode == BIN)
+ wave_o = (float *) cf_malloc(sizeof(float) * npix_o);
+ else
+ wave_o = wave1;
+
+ /********* perform arithmetic operations here *********/
+ switch (opcode)
+ {
+ case PLUS:
+ if (arg2_scalar)
+ {
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j] + arg2_val;
+ flxerr_o[j] = flxerr1[j];
+ cnts_o[j] = cnts1[j];
+ cntserr_o[j] = cntserr1[j];
+ qual_o[j] = qual1[j];
+ }
+ }
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j] + arg2_val;
+ flxerr_o[j] = flxerr1[j];
+ lcts_o[j] = lcts1[j];
+ qual_o[j] = qual1[j];
+ bkgd_o[j] = bkgd1[j];
+ wgts_o[j] = wgts1[j];
+ }
+ }
+ } /* end if(arg2_scalar) */
+ else
+ {
+ exptime_o = exptime_1 + exptime_2;
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j] + flux2[j];
+ tmp1 = flxerr1[j]*flxerr1[j];
+ tmp2 = flxerr2[j]*flxerr2[j];
+ flxerr_o[j] = sqrt (tmp1 + tmp2);
+ cnts_o[j] = cnts1[j] + cnts2[j];
+ tmp1 = cntserr1[j]*cntserr1[j];
+ tmp2 = cntserr2[j]*cntserr2[j];
+ cntserr_o[j] = sqrt (tmp1 + tmp2);
+ if ((qual1[j] == 0) || (qual2[j] == 0))
+ qual_o[j] = 0;
+ else
+ qual_o[j] = qual1[j];
+ }
+ }
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j] + flux2[j];
+ tmp1 = flxerr1[j]*flxerr1[j];
+ tmp2 = flxerr2[j]*flxerr2[j];
+ flxerr_o[j] = sqrt (tmp1 + tmp2);
+ lcts_o[j] = lcts1[j] + lcts2[j];
+ if ((qual1[j] == 0) || (qual2[j] == 0))
+ qual_o[j] = 0;
+ else
+ qual_o[j] = (qual1[j] + qual2[j])/2;
+ bkgd_o[j] = bkgd1[j] + bkgd2[j];
+ wgts_o[j] = wgts1[j] + wgts2[j];
+ }
+ }
+ }
+ break;
+
+ case MINUS:
+ if (arg2_scalar)
+ {
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j] - arg2_val;
+ flxerr_o[j] = flxerr1[j];
+ cnts_o[j] = cnts1[j];
+ cntserr_o[j] = cntserr1[j];
+ qual_o[j] = qual1[j];
+ }
+ }
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j] - arg2_val;
+ flxerr_o[j] = flxerr1[j];
+ lcts_o[j] = lcts1[j];
+ qual_o[j] = qual1[j];
+ bkgd_o[j] = bkgd1[j];
+ wgts_o[j] = wgts1[j];
+ }
+ }
+ }
+ else
+ {
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j] - flux2[j];
+ tmp1 = flxerr1[j]*flxerr1[j];
+ tmp2 = flxerr2[j]*flxerr2[j];
+ flxerr_o[j] = sqrt (tmp1 + tmp2);
+ cnts_o[j] = cnts1[j] - cnts2[j];
+ tmp1 = cntserr1[j]*cntserr1[j];
+ tmp2 = cntserr2[j]*cntserr2[j];
+ cntserr_o[j] = sqrt (tmp1 + tmp2);
+ if ((qual1[j] == 0) || (qual2[j] == 0))
+ qual_o[j] = 0;
+ else
+ qual_o[j] = qual1[j];
+ }
+ }
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j] - flux2[j];
+ tmp1 = flxerr1[j]*flxerr1[j];
+ tmp2 = flxerr2[j]*flxerr2[j];
+ flxerr_o[j] = sqrt (tmp1 + tmp2);
+ lcts_o[j] = lcts1[j] - lcts2[j];
+ if ((qual1[j] == 0) || (qual2[j] == 0))
+ qual_o[j] = 0;
+ else
+ qual_o[j] = (qual1[j] + qual2[j])/2;
+ bkgd_o[j] = bkgd1[j] - bkgd2[j];
+ wgts_o[j] = wgts1[j] - wgts2[j];
+ }
+ }
+ }
+ break;
+
+ case MULT:
+ if (arg2_scalar)
+ {
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j] * arg2_val;
+ flxerr_o[j] = flxerr1[j] * arg2_val;
+ cnts_o[j] = cnts1[j];
+ cntserr_o[j] = cntserr1[j];
+ qual_o[j] = qual1[j];
+ }
+ }
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j] * arg2_val;
+ flxerr_o[j] = flxerr1[j] * arg2_val;
+ lcts_o[j] = lcts1[j];
+ qual_o[j] = qual1[j];
+ bkgd_o[j] = bkgd1[j];
+ wgts_o[j] = wgts1[j];
+ }
+ } /* end cf_version == 3 */
+ } /* end if arg2_scalar */
+ else
+ {
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j] * flux2[j];
+ if (flux1[j] == 0.)
+ {
+ flxerr_o[j] = fabs (flux2[j] * flxerr1[j]);
+ }
+ else if (flux2[j] == 0.)
+ {
+ flxerr_o[j] = fabs (flux1[j] * flxerr2[j]);
+ }
+ else
+ {
+ tmp1 = flxerr1[j] / flux1[j];
+ tmp2 = flxerr2[j] / flux2[j];
+ tmp3 = tmp1 * tmp1 + tmp2 * tmp2;
+ flxerr_o[j] = fabs (flux_o[j]) * sqrt (tmp3);
+ }
+ cnts_o[j] = cnts1[j] * cnts2[j];
+ tmp1 = cnts2[j] * cnts2[j] * cntserr1[j]*cntserr1[j];
+ tmp2 = cnts1[j] * cnts1[j] * cntserr2[j]*cntserr2[j];
+ cntserr_o[j] = sqrt (tmp1 + tmp2);
+ if ((qual1[j] == 0) || (qual2[j] == 0))
+ qual_o[j] = 0;
+ else
+ qual_o[j] = qual1[j];
+ } /* end loop over j */
+ } /* end cf_version == 2 */
+ else
+ { /* start cf_version == 3 */
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j] * flux2[j];
+ if (flux1[j] == 0.)
+ {
+ flxerr_o[j] = fabs (flux2[j] * flxerr1[j]);
+ }
+ else if (flux2[j] == 0.)
+ {
+ flxerr_o[j] = fabs (flux1[j] * flxerr2[j]);
+ }
+ else
+ {
+ tmp1 = flxerr1[j] / flux1[j];
+ tmp2 = flxerr2[j] / flux2[j];
+ tmp3 = tmp1 * tmp1 + tmp2 * tmp2;
+ flxerr_o[j] = fabs (flux_o[j]) * sqrt (tmp3);
+ }
+ lcts_o[j] = lcts1[j] * lcts2[j];
+ wgts_o[j] = wgts1[j] * wgts2[j];
+ bkgd_o[j] = bkgd1[j] * bkgd2[j];
+ if ((qual1[j] == 0) || (qual2[j] == 0))
+ qual_o[j] = 0;
+ else
+ qual_o[j] = (qual1[j] + qual2[j])/2;
+ } /* end loop over j */
+ } /* end cf_version == 3 */
+ } /* end !arg2_scalar */
+ break;
+
+ case DIV:
+ if (arg2_scalar)
+ {
+ if (arg2_val == 0.)
+ cf_if_error ("Commanded division by 0!");
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j] / arg2_val;
+ flxerr_o[j] = flxerr1[j] / arg2_val;
+ cnts_o[j] = cnts1[j];
+ cntserr_o[j] = cntserr1[j];
+ qual_o[j] = qual1[j];
+ }
+ }
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j] / arg2_val;
+ flxerr_o[j] = flxerr1[j] / arg2_val;
+ lcts_o[j] = lcts1[j];
+ qual_o[j] = qual1[j];
+ bkgd_o[j] = bkgd1[j];
+ wgts_o[j] = wgts1[j];
+ }
+ }
+ }
+ else
+ {
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ if (flux2[j] !=0.)
+ {
+ flux_o[j] = flux1[j] / flux2[j];
+ if (flux1[j] != 0.)
+ {
+ tmp1 = flxerr1[j] / flux1[j];
+ tmp2 = flxerr2[j] / flux2[j];
+ tmp3 = tmp1 * tmp1;
+ tmp4 = tmp2 * tmp2;
+ flxerr_o[j] = fabs (flux_o[j]) * sqrt (tmp3 + tmp4);
+ }
+ else
+ flxerr_o[j] = flxerr1[j] / flux2[j];
+ if ((qual1[j] == 0) || (qual2[j] == 0))
+ qual_o[j] = 0;
+ else
+ qual_o[j] = qual1[j];
+ }
+ else
+ {
+ flux_o[j] = 0.;
+ flxerr_o[j] = flxerr1[j];
+ qual_o[j] = 0;
+ }
+ if (cnts2[j] != 0.)
+ {
+ cnts_o[j] = cnts1[j] / cnts2[j];
+ if (cnts1[j] != 0.)
+ tmp1 = cntserr1[j] / cnts1[j];
+ else
+ tmp1 = 0.;
+ tmp2 = cntserr2[j] / cnts2[j];
+ tmp3 = tmp1 * tmp1;
+ tmp4 = tmp2 * tmp2;
+ cntserr_o[j] = fabs (cnts_o[j]) * sqrt (tmp3 + tmp4);
+ }
+ else
+ {
+ cnts_o[j] = 0.;
+ cntserr_o[j] = cntserr1[j];
+ }
+ } /* end loop over j */
+ } /* end cf_version == 2 */
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ if (flux2[j] !=0.)
+ {
+ flux_o[j] = flux1[j] / flux2[j];
+ if (flux1[j] != 0.)
+ {
+ tmp1 = flxerr1[j] / flux1[j];
+ tmp2 = flxerr2[j] / flux2[j];
+ tmp3 = tmp1 * tmp1;
+ tmp4 = tmp2 * tmp2;
+ flxerr_o[j] = fabs (flux_o[j]) * sqrt (tmp3 + tmp4);
+ }
+ else
+ flxerr_o[j] = flxerr1[j] / flux2[j];
+ if ((qual1[j] == 0) || (qual2[j] == 0))
+ qual_o[j] = 0;
+ else
+ qual_o[j] = (qual1[j] + qual2[j])/2;
+ }
+ else
+ {
+ flux_o[j] = 0.;
+ flxerr_o[j] = flxerr1[j];
+ qual_o[j] = 0;
+ }
+
+ if (lcts2[j] != 0.)
+ lcts_o[j] = lcts1[j] / lcts2[j];
+ else
+ lcts_o[j] = 0.;
+
+ if (wgts2[j] != 0.)
+ wgts_o[j] = wgts1[j] / wgts2[j];
+ else
+ wgts_o[j] = 0.;
+
+ if (bkgd2[j] != 0.)
+ bkgd_o[j] = bkgd1[j] / bkgd2[j];
+ else
+ bkgd_o[j] = 0.;
+
+ } /* end loop over j */
+ } /* end cf_version == 3 */
+ } /* end !arg2_scalar */
+ break;
+
+ case AVG_T:
+ if (arg2_scalar)
+ {
+ cf_if_error ("Illegal operation with scalar operand!");
+ }
+ else
+ {
+ if (cf_version == 2)
+ {
+ f1 = exptime_1 / (exptime_1 + exptime_2);
+ f2 = exptime_2 / (exptime_1 + exptime_2);
+ exptime_o = exptime_1 + exptime_2;
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = f1 * flux1[j] + f2 * flux2[j];
+ tmp1 = f1 * f1 * flxerr1[j]*flxerr1[j];
+ tmp2 = f2 * f2 * flxerr2[j]*flxerr2[j];
+ flxerr_o[j] = sqrt (tmp1 + tmp2);
+ cnts_o[j] = f1 * cnts1[j] + f2 * cnts2[j];
+ tmp1 = f1 * f1 * cntserr1[j]*cntserr1[j];
+ tmp2 = f2 * f2 * cntserr2[j]*cntserr2[j];
+ cntserr_o[j] = sqrt (tmp1 + tmp2);
+ if ((qual1[j] == 0) || (qual2[j] == 0))
+ qual_o[j] = 0;
+ else
+ qual_o[j] = qual1[j];
+ }
+ }
+ else
+ {
+ f1 = exptime_1 / (exptime_1 + exptime_2);
+ f2 = exptime_2 / (exptime_1 + exptime_2);
+ exptime_o = exptime_1 + exptime_2;
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = f1 * flux1[j] + f2 * flux2[j];
+ tmp1 = f1 * f1 * flxerr1[j]*flxerr1[j];
+ tmp2 = f2 * f2 * flxerr2[j]*flxerr2[j];
+ flxerr_o[j] = sqrt (tmp1 + tmp2);
+ lcts_o[j] = lcts1[j] + lcts2[j];
+ wgts_o[j] = wgts1[j] + wgts2[j];
+ bkgd_o[j] = bkgd1[j] + bkgd2[j];
+ if ((qual1[j] == 0) || (qual2[j] == 0))
+ qual_o[j] = 0;
+ else
+ qual_o[j] = (qual1[j] + qual2[j])/2;
+ }
+ }
+ }
+ break;
+
+ case AVG_S:
+ if (arg2_scalar)
+ {
+ cf_if_error ("Illegal operation with scalar operand!");
+ }
+ else
+ {
+ exptime_o = exptime_1 + exptime_2;
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ if ((flxerr1[j] > 0.) && (flxerr2[j] > 0.))
+ {
+ f1 = 1. / (flxerr1[j] * flxerr1[j]);
+ f2 = 1. / (flxerr2[j] * flxerr2[j]);
+ }
+ else
+ f1 = f2 = 1.;
+ fn = f1 + f2;
+ flux_o[j] = (f1 * flux1[j] + f2 * flux2[j]) / fn;
+ flxerr_o[j] = sqrt (1./fn);
+ if ((cntserr1[j] > 0.) && (cntserr2[j] > 0.))
+ {
+ f1 = 1. / (cntserr1[j] * cntserr1[j]);
+ f2 = 1. / (cntserr2[j] * cntserr2[j]);
+ }
+ else
+ f1 = f2 = 1.;
+ fn = f1 + f2;
+ cnts_o[j] = (f1 * cnts1[j] + f2 * cnts2[j]) / fn;
+ cntserr_o[j] = sqrt (1./fn);
+ if ((qual1[j] == 0) || (qual2[j] == 0))
+ qual_o[j] = 0;
+ else
+ qual_o[j] = qual1[j];
+ }
+ } /* end if cf_version == 2 */
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ if ((flxerr1[j] > 0.) && (flxerr2[j] > 0.))
+ {
+ f1 = 1. / (flxerr1[j] * flxerr1[j]);
+ f2 = 1. / (flxerr2[j] * flxerr2[j]);
+ }
+ else
+ f1 = f2 = 1.;
+ fn = f1 + f2;
+ flux_o[j] = (f1 * flux1[j] + f2 * flux2[j]) / fn;
+ flxerr_o[j] = sqrt (1./fn);
+ lcts_o[j] = (f1 * lcts1[j] + f2 * lcts2[j]) / fn;
+ wgts_o[j] = (f1 * wgts1[j] + f2 * wgts2[j]) / fn;
+ bkgd_o[j] = (f1 * bkgd1[j] + f2 * bkgd2[j]) / fn;
+ if ((qual1[j] == 0) || (qual2[j] == 0))
+ qual_o[j] = 0;
+ else
+ qual_o[j] = (f1*qual1[j] + f2*qual2[j]) / fn;
+ }
+ }
+ }
+ break;
+
+ case REPL_D:
+ if (arg2_scalar)
+ {
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = arg2_val;
+ flxerr_o[j] = flxerr1[j];
+ cnts_o[j] = cnts1[j];
+ cntserr_o[j] = cntserr1[j];
+ qual_o[j] = qual1[j];
+ }
+ }
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = arg2_val;
+ flxerr_o[j] = flxerr1[j];
+ lcts_o[j] = lcts1[j];
+ qual_o[j] = qual1[j];
+ wgts_o[j] = wgts1[j];
+ bkgd_o[j] = bkgd1[j];
+ }
+ }
+ }
+ else
+ {
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux2[j];
+ flxerr_o[j] = flxerr1[j];
+ cnts_o[j] = cnts1[j];
+ cntserr_o[j] = cntserr1[j];
+ if ((qual1[j] == 0) || (qual2[j] == 0))
+ qual_o[j] = 0;
+ else
+ qual_o[j] = qual1[j];
+ }
+ }
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux2[j];
+ flxerr_o[j] = flxerr1[j];
+ lcts_o[j] = lcts1[j];
+ wgts_o[j] = wgts1[j];
+ bkgd_o[j] = bkgd1[j];
+ if ((qual1[j] == 0) || (qual2[j] == 0))
+ qual_o[j] = 0;
+ else
+ qual_o[j] = qual1[j];
+ }
+ }
+ }
+ break;
+
+ case REPL_E:
+ if (arg2_scalar)
+ {
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j];
+ flxerr_o[j] = arg2_val;
+ cnts_o[j] = cnts1[j];
+ cntserr_o[j] = cntserr1[j];
+ qual_o[j] = qual1[j];
+ }
+ }
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j];
+ flxerr_o[j] = arg2_val;
+ lcts_o[j] = lcts1[j];
+ qual_o[j] = qual1[j];
+ wgts_o[j] = wgts1[j];
+ bkgd_o[j] = bkgd1[j];
+ }
+ }
+ }
+ else
+ {
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j];
+ flxerr_o[j] = flxerr2[j];
+ cnts_o[j] = cnts1[j];
+ cntserr_o[j] = cntserr1[j];
+ if ((qual1[j] == 0) || (qual2[j] == 0))
+ qual_o[j] = 0;
+ else
+ qual_o[j] = qual1[j];
+ }
+ }
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j];
+ flxerr_o[j] = flxerr2[j];
+ lcts_o[j] = lcts1[j];
+ wgts_o[j] = wgts1[j];
+ bkgd_o[j] = bkgd1[j];
+ if ((qual1[j] == 0) || (qual2[j] == 0))
+ qual_o[j] = 0;
+ else
+ qual_o[j] = qual1[j];
+ }
+ }
+ }
+ break;
+
+ case DELTA:
+ /* start by copying input file to output */
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j];
+ flxerr_o[j] = flxerr1[j];
+ cnts_o[j] = cnts1[j];
+ cntserr_o[j] = cntserr1[j];
+ qual_o[j] = qual1[j];
+ }
+ }
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j];
+ flxerr_o[j] = flxerr1[j];
+ lcts_o[j] = lcts1[j];
+ qual_o[j] = qual1[j];
+ wgts_o[j] = wgts1[j];
+ bkgd_o[j] = bkgd1[j];
+ }
+ }
+ if (arg2_scalar)
+ {
+ for (j=100; j<npix_1; j+=100)
+ {
+ flux_o[j] += arg2_val;
+ if (flux1[j] != 0)
+ {
+ flxerr_o[j] *= fabs (flux_o[j] / flux1[j]);
+ }
+ else
+ {
+ flxerr_o[j] += 0.1 * fabs (flux_o[j]);
+ }
+ }
+ }
+ else
+ {
+ for (j=100; j<npix_1; j+=100)
+ {
+ flux_o[j] += flux2[j];
+ if (flux1[j] != 0)
+ {
+ flxerr_o[j] *= fabs (flux_o[j] / flux1[j]);
+ }
+ else
+ {
+ flxerr_o[j] += 0.1 * fabs (flux_o[j]);
+ }
+ }
+ }
+ break;
+
+ case BOXCAR:
+ if (arg2_scalar)
+ {
+ /* if width is <= 1, just copy input to output */
+ if (arg2_val <= 1.)
+ {
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j];;
+ flxerr_o[j] = flxerr1[j];
+ cnts_o[j] = cnts1[j];
+ cntserr_o[j] = cntserr1[j];
+ qual_o[j] = qual1[j];
+ }
+ } /* end if_cf_version == 2 */
+ else
+ { /* cf_version == 3 */
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j];;
+ flxerr_o[j] = flxerr1[j];
+ lcts_o[j] = lcts1[j];
+ qual_o[j] = qual1[j];
+ wgts_o[j] = wgts1[j];
+ bkgd_o[j] = bkgd1[j];
+ }
+ } /* end if cf_version == 3 */
+ } /* end if arg2_val <=1 */
+ else
+ {
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ k1 = j - arg2_val / 2. + 0.5;
+ k2 = j + arg2_val / 2. + 0.5;
+ if (k1 < 0)
+ k1 = 0;
+ if (k2 > npix_1-1)
+ k2 = npix_1-1;
+ sflux = 0.;
+ sferr = 0.;
+ scnts = 0.;
+ scerr = 0.;
+ lqual = 0;
+ for (k=k1; k<=k2; k++)
+ {
+ sflux += flux1[k];
+ sferr += flxerr1[k] * flxerr1[k];
+ scnts += cnts1[k];
+ scerr += cntserr1[k] * cntserr1[k];
+ lqual += (long) qual1[k];
+ }
+ spix = (float)(k2 - k1 + 1);
+ flux_o[j] = sflux / spix;
+ flxerr_o[j] = sqrt (sferr) / spix;
+ cnts_o[j] = scnts / spix;
+ cntserr_o[j] = sqrt (scerr) / spix;
+ qual_o[j] = (short) (lqual / spix);
+ } /* end of for j... */
+ } /* end if cf_version == 2 */
+ else
+ { /* start cf_version == 3 for scalar smoothing > 1 */
+ for (j=0; j<npix_1; j++)
+ {
+ k1 = j - arg2_val / 2. + 0.5;
+ k2 = j + arg2_val / 2. + 0.5;
+ if (k1 < 0)
+ k1 = 0;
+ if (k2 > npix_1-1)
+ k2 = npix_1-1;
+ sflux = 0.;
+ sferr = 0.;
+ slcts = 0;
+ sbkgd = 0.;
+ swgts = 0.;
+ lqual = 0;
+ for (k=k1; k<=k2; k++)
+ {
+ sflux += flux1[k];
+ sferr += flxerr1[k] * flxerr1[k];
+ slcts += lcts1[k];
+ swgts += wgts1[k];
+ sbkgd += bkgd1[k];
+ lqual += (long) qual1[k];
+ }
+ spix = (float)(k2 - k1 + 1);
+ flux_o[j] = sflux / spix;
+ flxerr_o[j] = sqrt (sferr) / spix;
+ lcts_o[j] = slcts / spix;
+ bkgd_o[j] = sbkgd / spix;
+ wgts_o[j] = swgts / spix;
+ qual_o[j] = (short) (lqual / spix);
+ } /* end of for j... */
+ } /* end cf_version == 3 */
+ } /* end of arg2_scalar > 1 */
+ } /* end of if (arg2_scalar) */
+ else
+ {
+ /* allow the smoothing width to vary pixel-by-pixel */
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ arg2_val = flux2[j];
+ if (arg2_val < 1.)
+ {
+ flux_o[j] = flux1[j];
+ flxerr_o[j] = flxerr1[j];
+ cnts_o[j] = cnts1[j];
+ cntserr_o[j] = cntserr1[j];
+ qual_o[j] = qual1[j];
+ }
+ else
+ {
+ k1 = j - arg2_val / 2. + 0.5;
+ k2 = j + arg2_val / 2. + 0.5;
+ if (k1 < 0)
+ k1 = 0;
+ if (k2 > npix_1-1)
+ k2 = npix_1-1;
+ sflux = 0.;
+ sferr = 0.;
+ scnts = 0.;
+ scerr = 0.;
+ lqual = 0;
+ for (k=k1; k<=k2; k++)
+ {
+ sflux += flux1[k];
+ sferr += flxerr1[k] * flxerr1[k];
+ scnts += cnts1[k];
+ scerr += cntserr1[k] * cntserr1[k];
+ lqual += (long) qual1[k];
+ }
+ spix = (float)(k2 - k1 + 1);
+ flux_o[j] = sflux / spix;
+ flxerr_o[j] = sqrt (sferr) / spix;
+ cnts_o[j] = scnts / spix;
+ cntserr_o[j] = sqrt (scerr) / spix;
+ qual_o[j] = (short) (lqual / spix);
+ } /* end of arg2_val > 1 */
+ } /* end of for j... */
+ } /* end if cf_version == 2 */
+ else
+ { /* cf_version == 3 */
+ for (j=0; j<npix_1; j++)
+ {
+ arg2_val = flux2[j];
+ if (arg2_val < 1.)
+ {
+ flux_o[j] = flux1[j];
+ flxerr_o[j] = flxerr1[j];
+ lcts_o[j] = lcts1[j];
+ wgts_o[j] = wgts1[j];
+ bkgd_o[j] = bkgd1[j];
+ qual_o[j] = qual1[j];
+ }
+ else
+ {
+ k1 = j - arg2_val / 2. + 0.5;
+ k2 = j + arg2_val / 2. + 0.5;
+ if (k1 < 0)
+ k1 = 0;
+ if (k2 > npix_1-1)
+ k2 = npix_1-1;
+ sflux = 0.;
+ sferr = 0.;
+ slcts = 0;
+ sbkgd = 0.;
+ swgts = 0.;
+ lqual = 0;
+ for (k=k1; k<=k2; k++)
+ {
+ sflux += flux1[k];
+ sferr += flxerr1[k] * flxerr1[k];
+ slcts += lcts1[k];
+ swgts += wgts1[k];
+ sbkgd += bkgd1[k];
+ lqual += (long) qual1[k];
+ }
+ spix = (float)(k2 - k1 + 1);
+ flux_o[j] = sflux / spix;
+ flxerr_o[j] = sqrt (sferr) / spix;
+ lcts_o[j] = slcts / spix;
+ wgts_o[j] = swgts / spix;
+ bkgd_o[j] = sbkgd / spix;
+ qual_o[j] = (short) (lqual / spix);
+ } /* end of arg2_val > 1 */
+ } /* end of for j... */
+ } /* end if cf_version == 3 */
+ } /* end of if (!arg2_scalar) */
+ break; /* end of case BOXCAR */
+
+ case MIN:
+ if (arg2_scalar)
+ {
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ if (flux1[j] < arg2_val)
+ flux_o[j] = arg2_val;
+ else
+ flux_o[j] = flux1[j];
+ flxerr_o[j] = flxerr1[j];
+ cnts_o[j] = cnts1[j];
+ cntserr_o[j] = cntserr1[j];
+ qual_o[j] = qual1[j];
+ }
+ }
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ if (flux1[j] < arg2_val)
+ flux_o[j] = arg2_val;
+ else
+ flux_o[j] = flux1[j];
+ flxerr_o[j] = flxerr1[j];
+ lcts_o[j] = lcts1[j];
+ wgts_o[j] = wgts1[j];
+ bkgd_o[j] = bkgd1[j];
+ qual_o[j] = qual1[j];
+ }
+ }
+ }
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ if (flux1[j] < flux2[j])
+ {
+ flux_o[j] = flux2[j];
+ flxerr_o[j] = flxerr2[j];
+ }
+ else
+ {
+ flux_o[j] = flux1[j];
+ flxerr_o[j] = flxerr1[j];
+ }
+ if ((qual1[j] == 0) || (qual2[j] == 0))
+ qual_o[j] = 0;
+ else
+ qual_o[j] = qual1[j];
+ }
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ cnts_o[j] = cnts1[j];
+ cntserr_o[j] = cntserr1[j];
+ }
+ }
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ lcts_o[j] = lcts1[j];
+ wgts_o[j] = wgts1[j];
+ bkgd_o[j] = bkgd1[j];
+ }
+ }
+ }
+ break;
+
+ case MAX:
+ if (arg2_scalar)
+ {
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ if (flux1[j] > arg2_val)
+ flux_o[j] = arg2_val;
+ else
+ flux_o[j] = flux1[j];
+ flxerr_o[j] = flxerr1[j];
+ cnts_o[j] = cnts1[j];
+ cntserr_o[j] = cntserr1[j];
+ qual_o[j] = qual1[j];
+ }
+ }
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ if (flux1[j] > arg2_val)
+ flux_o[j] = arg2_val;
+ else
+ flux_o[j] = flux1[j];
+ flxerr_o[j] = flxerr1[j];
+ lcts_o[j] = lcts1[j];
+ wgts_o[j] = wgts1[j];
+ bkgd_o[j] = bkgd1[j];
+ qual_o[j] = qual1[j];
+ }
+ }
+ }
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ if (flux1[j] > flux2[j])
+ {
+ flux_o[j] = flux2[j];
+ flxerr_o[j] = flxerr2[j];
+ }
+ else
+ {
+ flux_o[j] = flux1[j];
+ flxerr_o[j] = flxerr1[j];
+ }
+ if ((qual1[j] == 0) || (qual2[j] == 0))
+ qual_o[j] = 0;
+ else
+ qual_o[j] = qual1[j];
+ }
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ cnts_o[j] = cnts1[j];
+ cntserr_o[j] = cntserr1[j];
+ }
+ }
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ lcts_o[j] = lcts1[j];
+ wgts_o[j] = wgts1[j];
+ bkgd_o[j] = bkgd1[j];
+ }
+ }
+ }
+ break;
+
+ case SHIFT:
+ if (cf_version == 2)
+ {
+ if (p_shift > 0)
+ {
+ for (j=0; j<p_shift; j++)
+ {
+ flux_o[j] = 0.;
+ flxerr_o[j] = DEF_ERROR;
+ cnts_o[j] = 0.;
+ cntserr_o[j] = DEF_ERROR;
+ qual_o[j] = 0;
+ }
+ for (j=p_shift; j<npix_1; j++)
+ {
+ k = j - p_shift;
+ flux_o[j] = flux1[k];
+ flxerr_o[j] = flxerr1[k];
+ cnts_o[j] = cnts1[k];
+ cntserr_o[j] = cntserr1[k];
+ qual_o[j] = qual1[k];
+ }
+ }
+ if (p_shift <= 0)
+ {
+ for (j=npix_1+p_shift; j<npix_1; j++)
+ {
+ flux_o[j] = 0.;
+ flxerr_o[j] = DEF_ERROR;
+ cnts_o[j] = 0.;
+ cntserr_o[j] = DEF_ERROR;
+ qual_o[j] = 0;
+ }
+ for (j=0; j<npix_1+p_shift; j++)
+ {
+ k = j - p_shift;
+ flux_o[j] = flux1[k];
+ flxerr_o[j] = flxerr1[k];
+ cnts_o[j] = cnts1[k];
+ cntserr_o[j] = cntserr1[k];
+ qual_o[j] = qual1[k];
+ }
+ }
+ } /* end if cf_version == 2 */
+ else
+ {
+ if (p_shift > 0)
+ {
+ for (j=0; j<p_shift; j++)
+ {
+ flux_o[j] = 0.;
+ flxerr_o[j] = DEF_ERROR;
+ lcts_o[j] = 0;
+ qual_o[j] = 0;
+ wgts_o[j] = 0.;
+ bkgd_o[j] = 0.;
+ }
+ for (j=p_shift; j<npix_1; j++)
+ {
+ k = j - p_shift;
+ flux_o[j] = flux1[k];
+ flxerr_o[j] = flxerr1[k];
+ lcts_o[j] = lcts1[k];
+ wgts_o[j] = wgts1[k];
+ bkgd_o[j] = bkgd1[k];
+ qual_o[j] = qual1[k];
+ }
+ }
+ if (p_shift <= 0)
+ {
+ for (j=npix_1+p_shift; j<npix_1; j++)
+ {
+ flux_o[j] = 0.;
+ flxerr_o[j] = DEF_ERROR;
+ lcts_o[j] = 0;
+ wgts_o[j] = 0.;
+ bkgd_o[j] = 0.;
+ qual_o[j] = 0;
+ }
+ for (j=0; j<npix_1+p_shift; j++)
+ {
+ k = j - p_shift;
+ flux_o[j] = flux1[k];
+ flxerr_o[j] = flxerr1[k];
+ lcts_o[j] = lcts1[k];
+ wgts_o[j] = wgts1[k];
+ bkgd_o[j] = bkgd1[k];
+ qual_o[j] = qual1[k];
+ }
+ }
+ }
+ break;
+
+ case BIN:
+ /* if nbin = 1, just copy input to output */
+ if (nbin == 1)
+ {
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_o; j++)
+ {
+ wave_o[j] = wave1[j];
+ flux_o[j] = flux1[j];;
+ flxerr_o[j] = flxerr1[j];
+ cnts_o[j] = cnts1[j];
+ cntserr_o[j] = cntserr1[j];
+ qual_o[j] = qual1[j];
+ }
+ }
+ else
+ {
+ for (j=0; j<npix_o; j++)
+ {
+ wave_o[j] = wave1[j];
+ flux_o[j] = flux1[j];;
+ flxerr_o[j] = flxerr1[j];
+ lcts_o[j] = lcts1[j];
+ wgts_o[j] = wgts1[j];
+ bkgd_o[j] = bkgd1[j];
+ qual_o[j] = qual1[j];
+ }
+ } /* end cf_version == 3 */
+ } /* end nbin == 1 */
+ else
+ {
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_o; j++)
+ {
+ k1 = j * nbin;
+ k2 = k1 + nbin;
+ if (k2 > npix_1)
+ k2 = npix_1;
+ swave = 0.;
+ sflux = 0.;
+ sferr = 0.;
+ scnts = 0.;
+ scerr = 0.;
+ squal = 0;
+ spix = 0;
+ for (k=k1; k<k2; k++)
+ {
+ swave += wave1[k];
+ if (qual1[k] > 0)
+ {
+ sflux += flux1[k];
+ sferr += flxerr1[k] * flxerr1[k];
+ scnts += cnts1[k];
+ scerr += cntserr1[k] * cntserr1[k];
+ squal += qual1[k];
+ spix++;
+ }
+ }
+ if (spix == 0)
+ spix = 1;
+ wave_o[j] = swave / (float)(k2 - k1);
+ flux_o[j] = sflux / spix;
+ flxerr_o[j] = sqrt (sferr) / spix;
+ cnts_o[j] = scnts;
+ cntserr_o[j] = sqrt (scerr);
+ qual_o[j] = squal;
+ } /* end of for j... */
+ } /* end cf_version == 2 */
+ else
+ {
+ for (j=0; j<npix_o; j++)
+ {
+ k1 = j * nbin;
+ k2 = k1 + nbin;
+ if (k2 > npix_1)
+ k2 = npix_1;
+ swave = 0.;
+ sflux = 0.;
+ sferr = 0.;
+ slcts = 0;
+ swgts = 0.;
+ sbkgd = 0.;
+ squal = 0;
+ spix = 0;
+ for (k=k1; k<k2; k++)
+ {
+ swave += wave1[k];
+ if (qual1[k] > 0)
+ {
+ sflux += flux1[k];
+ sferr += flxerr1[k] * flxerr1[k];
+ slcts += lcts1[k];
+ swgts += wgts1[k];
+ sbkgd += bkgd1[k];
+ squal += qual1[k];
+ spix++;
+ }
+ }
+ if (spix == 0)
+ spix = 1;
+ wave_o[j] = swave / (float)(k2 - k1);
+ flux_o[j] = sflux / spix;
+ flxerr_o[j] = sqrt (sferr) / spix;
+ lcts_o[j] = slcts;
+ qual_o[j] = squal / spix;
+ wgts_o[j] = swgts / spix;
+ bkgd_o[j] = sbkgd;
+ } /* end of for j... */
+ } /* end cf_version == 3 */
+ } /* end of nbin > 1 */
+ break;
+
+ case DERIV:
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1-1; j++)
+ {
+ flux_o[j] = flux1[j+1] - flux1[j];
+ tmp1 = flxerr1[j+1]*flxerr1[j+1];
+ tmp2 = flxerr1[j]*flxerr1[j];
+ flxerr_o[j] = sqrt (tmp1 + tmp2);
+ tmp1 = cntserr1[j+1]*cntserr1[j+1];
+ tmp2 = cntserr1[j]*cntserr1[j];
+ cnts_o[j] = cnts1[j+1] - cnts1[j];
+ cntserr_o[j] = sqrt (tmp1 + tmp2);
+ qual_o[j] = qual1[j];
+ }
+ flux_o[npix_1-1] = flux_o[npix_1-2];
+ flxerr_o[npix_1-1] = flxerr_o[npix_1-2];
+ cnts_o[npix_1-1] = cnts_o[npix_1-2];
+ cntserr_o[npix_1-1] = cntserr_o[npix_1-2];
+ } /* end cf_version == 2 */
+ else
+ {
+ for (j=0; j<npix_1-1; j++)
+ {
+ flux_o[j] = flux1[j+1] - flux1[j];
+ tmp1 = flxerr1[j+1]*flxerr1[j+1];
+ tmp2 = flxerr1[j]*flxerr1[j];
+ flxerr_o[j] = sqrt (tmp1 + tmp2);
+ lcts_o[j] = lcts1[j+1] - lcts1[j];
+ qual_o[j] = qual1[j];
+ wgts_o[j] = wgts1[j];
+ bkgd_o[j] = bkgd1[j];
+ }
+ flux_o[npix_1-1] = flux_o[npix_1-2];
+ flxerr_o[npix_1-1] = flxerr_o[npix_1-2];
+ lcts_o[npix_1-1] = lcts_o[npix_1-2];
+ } /* end cf_version == 3 */
+ break;
+
+ case ADDNOISE:
+ if (cf_version == 2)
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j] + arg2_val * rand1();
+ flxerr_o[j] = flxerr1[j];
+ cnts_o[j] = cnts1[j];
+ cntserr_o[j] = cntserr1[j];
+ qual_o[j] = qual1[j];
+ }
+ }
+ else
+ {
+ for (j=0; j<npix_1; j++)
+ {
+ flux_o[j] = flux1[j] + arg2_val * rand1();
+ flxerr_o[j] = flxerr1[j];
+ lcts_o[j] = lcts1[j];
+ wgts_o[j] = wgts1[j];
+ bkgd_o[j] = bkgd1[j];
+ qual_o[j] = qual1[j];
+ }
+ }
+ break;
+
+ default:
+ cf_if_error ("Illegal opcode; should never get here!");
+ break;
+
+ } /* end switch (opcode) */
+
+ /* write the extension containing the results as a binary table */
+ hdunum_o=i+1;
+
+ /* cf_write_spec creates the new extension and sets the pointer
+ * to it.
+ */
+ if (tfields_1 < 7)
+ cf_wrspec_cf2 (outfits, npix_o, wave_o, flux_o, flxerr_o, qual_o,
+ cnts_o, cntserr_o, tfields_1, areaflag);
+ else
+ cf_wrspec7 (outfits, npix_o, wave_o, flux_o, flxerr_o,
+ lcts_o, wgts_o, bkgd_o, qual_o);
+
+
+ if (wave_o != wave1)
+ free(wave_o);
+ free(wave1);
+ free(flux1);
+ free(flxerr1);
+ free(qual1);
+ free(flux_o);
+ free(flxerr_o);
+ free(qual_o);
+ if (cf_version == 2)
+ {
+ free(cnts1);
+ free(cntserr1);
+ free(cnts_o);
+ free(cntserr_o);
+ }
+ else
+ {
+ free(lcts1);
+ free(bkgd1);
+ free(wgts1);
+ free(lcts_o);
+ free(bkgd_o);
+ free(wgts_o);
+ }
+
+ /* is there only 1 extension in operand 2, so that we need to keep
+ * the data we've read in, or do we need to make space to read the
+ * next extension?
+ */
+ if (!arg2_scalar && (i < next_2))
+ {
+ free(flux2);
+ free(flxerr2);
+ free(qual2);
+ if (cf_version == 2)
+ {
+ free(cnts2);
+ free(cntserr2);
+ }
+ else
+ {
+ free(lcts2);
+ free(wgts2);
+ free(bkgd2);
+ }
+ }
+
+ } /* end of loop over next_1 */
+
+ /* add HISTORY lines to output file */
+ hdunum_o = 1;
+ FITS_movabs_hdu (outfits, hdunum_o, &hdutype_o, &status);
+
+ sprintf (comment, "cf_arith: operation = %s", argv[2]);
+ FITS_write_history (outfits, comment, &status);
+ sprintf (comment, "cf_arith: operand1 = %s", infile1);
+ FITS_write_history (outfits, comment, &status);
+ sprintf (comment, "cf_arith: operand2 = %s", infile2);
+ FITS_write_history (outfits, comment, &status);
+
+ /* update exposure time in output header if necessary */
+ if (exptime_o != exptime_1)
+ {
+ FITS_update_key (outfits, TFLOAT, "EXPTIME", &exptime_o, expt_comment,
+ &status);
+ sprintf (comment, "cf_arith: EXPTIME = EXPTIME1 + EXPTIME2");
+ FITS_write_history (outfits, comment, &status);
+ }
+
+ /* update FILENAME keyword in output file */
+ FITS_update_key (outfits, TSTRING, "FILENAME", outfile, NULL, &status);
+
+ time (&timeval);
+ timestr = ctime (&timeval);
+ sprintf (comment, "cf_arith: completed at %.24s", timestr);
+ /* over-write the trailing \n in timestr */
+/* following not needed when field width is specified as 24 above
+ comment[strlen(comment)-1] = '\0';
+ padstr (comment, FLEN_CARD);
+*/
+ FITS_write_history (outfits, comment, &status);
+
+ /* Close the files. */
+
+ FITS_close_file(infits_1, &status);
+ if (!arg2_scalar)
+ FITS_close_file(infits_2, &status);
+ FITS_close_file(outfits, &status);
+
+ /* Enter a timestamp into the log. */
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Done processing");
+#ifdef SOLARIS
+ ieee_retrospective(stdout);
+#endif
+ return 0;
+}
+
+int chkop (opstr)
+char *opstr;
+{
+ if (!strcmp (opstr, "+"))
+ return (PLUS);
+ else if (!strcmp (opstr, "-"))
+ return (MINUS);
+ else if (!strcmp (opstr, "*"))
+ return (MULT);
+ else if (!strcmp (opstr, "/"))
+ return (DIV);
+ else if (!strcmp (opstr, "avg_t"))
+ return (AVG_T);
+ else if (!strcmp (opstr, "avg_s"))
+ return (AVG_S);
+ else if (!strcmp (opstr, "repl_d"))
+ return (REPL_D);
+ else if (!strcmp (opstr, "repl_e"))
+ return (REPL_E);
+ else if (!strcmp (opstr, "boxcar"))
+ return (BOXCAR);
+ else if (!strcmp (opstr, "delta"))
+ return (DELTA);
+ else if (!strcmp (opstr, "min"))
+ return (MIN);
+ else if (!strcmp (opstr, "max"))
+ return (MAX);
+ else if (!strcmp (opstr, "shift"))
+ return (SHIFT);
+ else if (!strcmp (opstr, "bin"))
+ return (BIN);
+ else if (!strcmp (opstr, "deriv"))
+ return (DERIV);
+ else if (!strcmp (opstr, "addnoise"))
+ return (ADDNOISE);
+ else
+ return (0);
+}
+
+/* check_num (in_str) returns TRUE if in_str is a string representation of
+ * a valid number, FALSE otherwise.
+ * This is a simple-minded check: just see if first char is +,-,digit.
+ */
+int check_num (in_str)
+char *in_str;
+{
+ if ((in_str[0] == '+') || (in_str[0] == '-'))
+ {
+ if (isdigit (in_str[1]))
+ return (TRUE);
+ else
+ return (FALSE);
+ }
+ if (isdigit (in_str[0]))
+ return (TRUE);
+
+ return (FALSE);
+}
+
+void padstr (pstr, len)
+char *pstr;
+int len;
+{
+ int i, slen;
+
+ slen = strlen (pstr);
+ for (i=slen; i<len; i++)
+ *(pstr + i) = ' ';
+
+ return;
+}
+/* return a random number in range -1 -> 1 */
+double rand1 ()
+{
+ long random();
+ double r;
+
+ r = 2. * (double) random() / (double)MAX_RAND - 1.;
+ return (r);
+}
+
diff --git a/src/analysis/cf_coadd.c b/src/analysis/cf_coadd.c
new file mode 100644
index 0000000..eaa5fe2
--- /dev/null
+++ b/src/analysis/cf_coadd.c
@@ -0,0 +1,192 @@
+/******************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ ******************************************************************************
+ *
+ * Synopsis: cf_coadd root_name
+ *
+ * This program calls the routines that produce the exposure-level
+ * all files and the observation-level all, ano, and nvo files.
+ *
+ * 03/29/04 v0.1 bjg Begin work.
+ * 04/05/04 v0.2 bjg Remove unused variables
+ * Include unistd.h
+ * 06/07/04 v0.3 bjg Updated some keywords
+ * 08/12/04 v0.4 bjg Keywords QIK_COR and COMB_COR
+ * now set to COMPLETE.
+ * 08/26/04 v0.5 bjg Handle case aperture=RFPT
+ * 03/17/05 v0.6 tc Rename EXPTIME to OBSTIME in all extensions
+ * 08/22/05 v1.0 wvd Completely re-write for CalFUSE v3.1.7.
+ * Calls cf_make_all_exp for each exposure and
+ * cf_make_all_obs.csh only once.
+ * 08/27/07 v1.1 bot Changed i from int to long to match n
+ * Added L to corresponding values
+ *
+ *****************************************************************************/
+
+
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "calfuse.h"
+
+static char CF_PRGM_ID[] = "cf_coadd";
+static char CF_VER_NUM[] = "1.1";
+
+
+/*********************************************************************/
+
+int main(int argc, char *argv[])
+{
+
+ char asnf_file[120], filename[120], instmode[100], aper_string[100], aper_num[100];
+ fitsfile *asnf_fits_ptr, *infits;
+ long n;
+ int status = 0;
+ long i;
+ int anynull;
+ FILE * ffile;
+
+
+ char command0[256];
+
+
+ char memname[120], *memname_ptr;
+ char memtype[120], *memtype_ptr;
+ char ** memname_ptr2;
+ char ** memtype_ptr2;
+
+ char NULL_STR[] = {'\0'};
+
+ char file_present;
+ char expo_num_string[10];
+ int expo_num;
+
+ char know=0;
+
+ /* Enter a timestamp into the log. */
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Begin Processing");
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+
+ memname_ptr=memname;
+ memtype_ptr=memtype;
+
+ memname_ptr2=&memname_ptr;
+ memtype_ptr2=&memtype_ptr;
+
+
+ /* Input Parameters */
+ if (argc != 2)
+ cf_if_error("Usage: cf_coadd rootname");
+
+ /*Open association file*/
+
+ strcpy(asnf_file, argv[1]);
+ strcat(asnf_file, "asnf.fit");
+ FITS_open_file(&asnf_fits_ptr, asnf_file, READONLY, &status);
+ FITS_movabs_hdu(asnf_fits_ptr, 2, NULL, &status);
+
+
+ FITS_read_key(asnf_fits_ptr, TLONG, "NAXIS2", &n, NULL, &status);
+
+
+ for (i=0L;i<n;i++){
+
+ cf_if_fits_error(fits_read_col_str(asnf_fits_ptr, 1, i+1L, 1,1, NULL_STR,
+ memname_ptr2, &anynull, &status));
+
+ cf_if_fits_error(fits_read_col_str(asnf_fits_ptr, 2, i+1L, 1,1, NULL_STR,
+ memtype_ptr2, &anynull, &status));
+
+ cf_if_fits_error(fits_read_col_log(asnf_fits_ptr, 3, i+1L, 1, 1, 0,
+ &file_present, &anynull, &status));
+
+ if (file_present == FALSE) continue;
+ if (strncasecmp(memtype,"EXPOSURE",8)) continue;
+
+ strncpy(expo_num_string,&memname[8],3);
+ expo_num=atoi(expo_num_string);
+
+ if (expo_num==701) continue;
+
+ strcpy(filename,memname);
+ strcat(filename,"1ahistfraw.fit");
+ strcpy(instmode,"hist");
+ ffile=fopen(filename,"r");
+ if (ffile == NULL) {
+ strcpy(instmode,"ttag");
+ strcpy(filename,memname);
+ strcat(filename,"1attagfraw.fit");
+ ffile=fopen(filename,"r");
+ if (ffile == NULL) {
+ printf("Warning: Expo %s not present\n",expo_num_string);
+ continue;
+ }
+ fclose(ffile);
+ }
+ else {
+ fclose(ffile);
+ }
+
+
+ if (!know) {
+
+ FITS_open_file(&infits, filename, READONLY, &status);
+ FITS_read_key(infits, TSTRING, "APERTURE", aper_string, NULL, &status);
+
+ if (!strncasecmp(aper_string,"LWRS",4)) strcpy(aper_num,"4");
+ if (!strncasecmp(aper_string,"MDRS",4)) strcpy(aper_num,"2");
+ if (!strncasecmp(aper_string,"HIRS",4)) strcpy(aper_num,"3");
+ if (!strncasecmp(aper_string,"PINH",4)) strcpy(aper_num,"1");
+ if (!strncasecmp(aper_string,"RFPT",4)) strcpy(aper_num,"4");
+
+ FITS_close_file(infits, &status);
+ know=1;
+ }
+
+
+ strcpy(command0,"cf_make_all_exp ");
+ strcat(command0,memname);
+ strcat(command0,"00all");
+ strcat(command0,aper_num);
+ strcat(command0,instmode);
+ strcat(command0,"fcal.fit ");
+ strcat(command0,memname);
+ strcat(command0,"1alif");
+ strcat(command0,aper_num);
+ strcat(command0,instmode);
+ strcat(command0,"fcal.fit ");
+ strcat(command0,memname);
+ strcat(command0,"1blif");
+ strcat(command0,aper_num);
+ strcat(command0,instmode);
+ strcat(command0,"fcal.fit ");
+ strcat(command0,memname);
+ strcat(command0,"2alif");
+ strcat(command0,aper_num);
+ strcat(command0,instmode);
+ strcat(command0,"fcal.fit ");
+ strcat(command0,memname);
+ strcat(command0,"2blif");
+ strcat(command0,aper_num);
+ strcat(command0,instmode);
+ strcat(command0,"fcal.fit ");
+
+ system(command0);
+
+ }
+
+ FITS_close_file(asnf_fits_ptr,&status);
+
+ sprintf(command0,"cf_make_all_obs.csh %s", asnf_file);
+ system(command0);
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Done Processing");
+
+ return(EXIT_SUCCESS);
+
+}
diff --git a/src/analysis/cf_combine.c b/src/analysis/cf_combine.c
new file mode 100644
index 0000000..0b91009
--- /dev/null
+++ b/src/analysis/cf_combine.c
@@ -0,0 +1,544 @@
+/*******************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: cf_combine [-ahk] [-v level] file_list output_idf_file
+ *
+ * Description: This is a utility program that combines a series of
+ * FUSE spectra in the form of FITS binary tables as produced
+ * by the CalFUSE pipeline. The files are combined by taking
+ * the exposure-weighted mean of the fluxes and flux errors
+ * and summing the counts.
+ * It is assumed that the error arrays contain standard
+ * deviations, not variances.
+ *
+ *
+ * History: 01/04/00 jwk started work
+ * 05/01/00 v1.2 jwk handle SHORT qual arrays
+ * 09/11/00 v1.3 jwk remove include <sunmath.h>
+ * 10/11/00 v1.4 jwk update FILENAME keyword in output file
+ * 10/27/00 v1.5 peb #ifdef ieee_retrospective
+ * 04/18/01 v1.6 wvd Change declaration of timeval from
+ * long to time_t
+ * 10/29/02 v1.7 wvd Correct error in history line.
+ * 05/19/03 v1.8 wvd Two updates from jwk:
+ * Close each input file in initial loop;
+ * without this cfitsio crashes upon
+ * opening the 60th file.
+ * Weight each pixel by exposure time
+ * after excluding 'bad' pixels.
+ * 12/15/03 v1.9 bjg Changed to work on CalFUSE 3 spectrum
+ * data format
+ * 01/12/04 v1.10 bjg npix_1 is now correct
+ * copy header of 1st file instead of 2nd
+ * Updated the name of some FITS cols that
+ * were still using 2.4 format
+ * 03/09/04 v1.11 wvd Change POTHOLE to QUALITY throughout.
+ * 04/05/04 - bjg Declarations for cf_wrspec7 and
+ * cf_wrspec_cf2
+ * Remove unused variables
+ * 06/07/04 v1.12 bjg Update some keywords (plantime,
+ * rawtime, exp_saa, nbadevnt ...)
+ * 04/07/05 v1.13 tc Read 1D|2D spectrum format. Clean unused
+ * variables. Allows one to shift a 2D
+ * spectrum (2nd column in the filelist).
+ * Use calloc rather than malloc. The
+ * quality value is now the nearest short.
+ * Update ROOTNAME keyword. Change EXP to
+ * OBS if "-k" (optional). Proper use of
+ * fclose() and rewind()
+ * 04/16/05 v1.14 tc Use cf_read_col()
+ * 05/02/05 v1.15 wvd Write NSPEC, SPEC###, WOFF### to
+ * output file header (primary HDU).
+ * 06/03/05 v1.16 wvd Delete unused variables.
+ * 07/06/05 v1.17 wvd Use fgets to read input file.
+ * Change pix_shift to type int.
+ * 07/21/05 v1.18 wvd Adopt the sign convention for spectral
+ * shifts used by FUSE_REGISTER.
+ * 08/26/05 v1.19 wvd Without arguments, don't return an
+ * error. Just print help and exit.
+ * 08/29/05 v1.20 wvd If input list contains only file
+ * names, assume shifts are zero.
+ * 01/31/06 v1.21 wvd Revise creation date of output file.
+ * 05/19/06 v1.22 wvd Use same options as idf_combine.
+ * Ignore spectra with EXP_STAT != 0.
+ * Override with -a option.
+ * 05/22/06 v1.23 wvd Rewrite program using a single while
+ * loop.
+ * 05/23/06 v1.24 wvd Properly normalize quality array.
+ * 05/26/06 v1.25 wvd Include unistd.h
+ * 07/12/06 v1.26 wvd Clean up i/o.
+ * 08/14/06 v1.27 wvd Count SPEC### and WAVE### using ngood,
+ * not nfiles.
+ * 05/04/07 v1.28 wvd If the input file list contains a
+ * blank line, skip to the next line.
+ * 08/27/07 v1.29 bot Changed TINT to TLONG l.412
+ * Added L to long l.125 to 136, 351, 378
+ * 04/04/08 v1.30 wvd If -a flag is set, include files with
+ * positive values of EXP_STAT, but not
+ * those with negative values.
+ * 07/25/08 v1.31 wvd Set output EXP_STAT keyword to lowest
+ * non-negative value among input files.
+ *
+ ****************************************************************************/
+
+#include <time.h>
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "calfuse.h"
+
+void cf_wrspec7(fitsfile *outfits, long npts, float *wave, float *flux,
+ float *error, long *counts, float *weights,
+ float *bkgd,short *quality);
+void cf_wrspec_cf2(fitsfile *outfits, int npts, float *wave,
+ float *spec, float *errs, short *qual,
+ float *counts, float *cntserr, int ncol,
+ int areaflag);
+
+static char CF_PRGM_ID[] = "cf_combine";
+static char CF_VER_NUM[] = "1.31";
+
+int main(int argc, char *argv[])
+{
+ char *timestr;
+ time_t timeval;
+ char flist[80], infile[80], line[FLEN_CARD], outfile[80], string0[100];
+ char comment[FLEN_CARD];
+ char errstr[80];
+ int nargs, nfiles, ngood;
+ int status=0;
+ int hdutype_1, hdutype_o;
+ int hdunum_1, hdunum_o;
+ long npix_1;
+ int tfields_1, delta = 0;
+ long j;
+ short *quality1;
+ float *wave1, *flux1, *error1, *weights1, *bkgd1;
+
+ double *flux_o, *error_o, *quality_o;
+ float *weights_o, *bkgd_o;
+ long *counts_o, *counts1;
+ float *exptime_p;
+ float f1, shift, wpc;
+
+ float exptime_1, exptime_o = 0.;
+ float rawtime_1, rawtime_o = 0.;
+ long plantime_1, plantime_o = 0L;
+ long nbadevnt_1, nbadevnt_o = 0L;
+ long nbadpha_1 , nbadpha_o = 0L;
+ long exp_bad_1 , exp_bad_o = 0L;
+ long exp_brst_1, exp_brst_o = 0L;
+ long exp_hv_1, exp_hv_o = 0L;
+ long exp_jitr_1, exp_jitr_o = 0L;
+ long exp_lim_1 , exp_lim_o = 0L;
+ long exp_saa_1 , exp_saa_o = 0L;
+ long expnight_1, expnight_o = 0L;
+
+ long nevents_1, nevents_o = 0L;
+ long exp_stat, exp_stat_out=999;
+
+ double mjd_start, mjd_end;
+ double mjd_start_o = 99999., mjd_end_o = 0.;
+ fitsfile *infits_1, *outfits;
+ FILE *ifp;
+ char keyword[FLEN_KEYWORD], root_name[32];
+ int k_flag = 0;
+
+ float *temp_float;
+ short *temp_short;
+ long *temp_long;
+
+ /* Function prototypes*/
+ void getnshift_float(float*, float*, long, int);
+ void getnshift_short(short*, short*, long, int);
+ void getnshift_long(long*, long*, long, int);
+
+ int optc;
+ int ignore_exp_stat=TRUE;
+
+ char opts[] = "ahkv:";
+ char usage[] =
+ "Usage:\n"
+ " cf_combine [-ahk] [-v level] file_list output_idf_file\n";
+ char option[] =
+ "Options:\n"
+ " -h: this help message\n"
+ " -v: verbosity level (=1; 0 is silent)\n"
+ " -a: ignore EXP_STAT keyword\n"
+ " -k: Change EXP keywords to OBS\n";
+
+ verbose_level = 1;
+
+ /* Check number of options and arguments */
+ while ((optc = getopt(argc, argv, opts)) != -1) {
+ switch(optc) {
+
+ case 'h':
+ printf("%s\n%s", usage, option);
+ return 0;
+ case 'a':
+ ignore_exp_stat=FALSE;
+ break;
+ case 'v':
+ verbose_level = atoi(optarg);
+ break;
+ case 'k':
+ k_flag=1;
+ break;
+ }
+ }
+
+ /* Enter a timestamp into the log. */
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Begin Processing");
+
+ /* Initialize error checking */
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+ if (argc < optind+2) {
+ printf("%s", usage);
+ return 1;
+ }
+
+ strcpy (flist, argv[optind]);
+ strcpy (outfile, argv[optind+1]);
+
+ if ((ifp = fopen (flist, "r")) == NULL)
+ {
+ sprintf (errstr, "Unable to open file %s\n", flist);
+ cf_if_error (errstr);
+ }
+
+ if (ignore_exp_stat)
+ cf_verbose(1,"Will include only files with EXP_STAT=0") ;
+ else
+ cf_verbose(1,"Will include only files with EXP_STAT >= 0") ;
+
+ nfiles = ngood = 0;
+
+ /* BIG LOOP THROUGH INPUT FILES */
+ while (fgets(line, FLEN_CARD, ifp) != NULL) {
+ nargs = sscanf(line, "%s %d", infile, &delta);
+ if (nargs == EOF) continue;
+ if (nargs == 1) delta = 0;
+ nfiles++;
+ cf_verbose (3, "Input file loop: nfiles = %d, file = %s", nfiles, infile);
+
+ /* Open input file */
+ FITS_open_file(&infits_1, infile, READONLY, &status);
+ FITS_read_key(infits_1, TLONG, "EXP_STAT", &exp_stat, NULL, &status);
+ FITS_read_key(infits_1, TDOUBLE, "EXPSTART", &mjd_start, NULL, &status);
+ FITS_read_key(infits_1, TDOUBLE, "EXPEND" , &mjd_end , NULL, &status);
+ FITS_read_key(infits_1, TFLOAT, "EXPTIME" , &exptime_1 , NULL, &status);
+ FITS_read_key(infits_1, TLONG, "NEVENTS", &nevents_1, NULL, &status);
+ FITS_read_key(infits_1, TFLOAT, "RAWTIME" , &rawtime_1 , NULL, &status);
+ FITS_read_key(infits_1, TLONG, "PLANTIME", &plantime_1, NULL, &status);
+ nevents_o += nevents_1;
+ rawtime_o += rawtime_1;
+ plantime_o += plantime_1;
+
+ if (mjd_start < mjd_start_o) mjd_start_o = mjd_start;
+ if (mjd_end > mjd_end_o) mjd_end_o = mjd_end;
+
+ /* Create output file, copy the header from the input file */
+ if (nfiles==1)
+ {
+ /* open output file */
+ remove(outfile); /* In case the old file name exists */
+ FITS_create_file (&outfits, outfile, &status);
+ FITS_copy_header(infits_1, outfits, &status);
+ FITS_write_date(outfits, &status);
+
+ FITS_read_key(infits_1, TFLOAT, "WPC" , &wpc , NULL, &status);
+
+ /* Now go to the second HDU and figure out how long the arrays are. */
+ hdunum_1 = 2;
+ FITS_movabs_hdu(infits_1, hdunum_1, &hdutype_1, &status);
+ FITS_read_key(infits_1, TINT, "TFIELDS", &tfields_1, NULL, &status);
+
+ if (tfields_1 != 7)
+ {
+ sprintf (errstr, "Expecting 7 cols, found %d\n", tfields_1);
+ cf_if_error (errstr);
+ }
+
+ npix_1 = cf_read_col(infits_1, TFLOAT, "WAVE", (void **) &wave1);
+
+ /* Allocate data arrays (calloc initializes to 0 by default). */
+ exptime_p = (float *) cf_calloc(npix_1, sizeof(float));
+
+ flux1 = (float *) cf_calloc(npix_1, sizeof(float));
+ error1 = (float *) cf_calloc(npix_1, sizeof(float));
+ counts1 = (long *) cf_calloc(npix_1, sizeof(long));
+ weights1 = (float *) cf_calloc(npix_1, sizeof(float));
+ bkgd1 = (float *) cf_calloc(npix_1, sizeof(float));
+ quality1 = (short *) cf_calloc(npix_1, sizeof(short));
+
+ flux_o = (double *) cf_calloc(npix_1, sizeof(double));
+ error_o = (double *) cf_calloc(npix_1, sizeof(double));
+ counts_o = (long *) cf_calloc(npix_1, sizeof(long));
+ weights_o = (float *) cf_calloc(npix_1, sizeof(float));
+ bkgd_o = (float *) cf_calloc(npix_1, sizeof(float));
+ quality_o = (double *) cf_calloc(npix_1, sizeof(double));
+
+ hdunum_1 = 1;
+ FITS_movabs_hdu(infits_1, hdunum_1, &hdutype_1, &status);
+
+ } /* end of if(nfiles==1) */
+
+ /* Set EXP_STAT to lowest non-negative value in input files. */
+ if (exp_stat_out > exp_stat && exp_stat >= 0) exp_stat_out = exp_stat;
+
+ /* Skip files with EXP_TIME = 0 or EXP_STAT != 0. */
+ if (ignore_exp_stat && exp_stat != 0) {
+ cf_if_warning("File %s rejected. EXP_STAT not equal to zero. Use -a flag to override.",
+ infile) ;
+ FITS_close_file(infits_1,&status);
+ continue;
+ }
+
+ /* Never include files with negative values of EXP_STAT. */
+ else if (exp_stat < 0) {
+ cf_if_warning("File %s rejected. EXP_STAT less than zero.", infile) ;
+ FITS_close_file(infits_1,&status);
+ continue;
+ }
+
+ if (exptime_1 < 1.) {
+ cf_verbose (3, "Rejecting file %s: EXPTIME = %f", infile, exptime_1);
+ FITS_close_file(infits_1,&status);
+ continue;
+ }
+ ngood++;
+
+ FITS_read_key(infits_1, TLONG, "NBADEVNT", &nbadevnt_1, NULL, &status);
+ FITS_read_key(infits_1, TLONG, "NBADPHA" , &nbadpha_1 , NULL, &status);
+ FITS_read_key(infits_1, TLONG, "EXP_BAD" , &exp_bad_1 , NULL, &status);
+ FITS_read_key(infits_1, TLONG, "EXP_BRST", &exp_brst_1, NULL, &status);
+ FITS_read_key(infits_1, TLONG, "EXP_HV", &exp_hv_1, NULL, &status);
+ FITS_read_key(infits_1, TLONG, "EXP_JITR", &exp_jitr_1, NULL, &status);
+ FITS_read_key(infits_1, TLONG, "EXP_LIM" , &exp_lim_1 , NULL, &status);
+ FITS_read_key(infits_1, TLONG, "EXP_SAA" , &exp_saa_1 , NULL, &status);
+ FITS_read_key(infits_1, TLONG, "EXPNIGHT", &expnight_1, NULL, &status);
+
+ exptime_o += exptime_1;
+ nbadevnt_o += nbadevnt_1;
+ nbadpha_o += nbadpha_1;
+ exp_bad_o += exp_bad_1;
+ exp_saa_o += exp_saa_1;
+ exp_lim_o += exp_lim_1;
+ exp_brst_o += exp_brst_1;
+ exp_hv_o += exp_hv_1;
+ exp_jitr_o += exp_jitr_1;
+ expnight_o += expnight_1;
+
+ /* Read the data from input file (HDU 2) */
+ hdunum_1 = 2;
+ FITS_movabs_hdu(infits_1, hdunum_1, &hdutype_1, &status);
+
+ (void) cf_read_col(infits_1, TFLOAT, "FLUX", (void **) &temp_float);
+ getnshift_float(flux1, temp_float, npix_1, delta);
+ free(temp_float);
+
+ (void) cf_read_col(infits_1, TFLOAT, "ERROR", (void **) &temp_float);
+ getnshift_float(error1, temp_float, npix_1, delta);
+ free(temp_float);
+
+ (void) cf_read_col(infits_1, TSHORT, "QUALITY", (void **) &temp_short);
+ getnshift_short(quality1, temp_short, npix_1, delta);
+ free(temp_short);
+
+ (void) cf_read_col(infits_1, TLONG, "COUNTS", (void **) &temp_long);
+ getnshift_long(counts1, temp_long, npix_1, delta);
+ free(temp_long);
+
+ (void) cf_read_col(infits_1, TFLOAT, "WEIGHTS", (void **) &temp_float);
+ getnshift_float(weights1, temp_float, npix_1, delta);
+ free(temp_float);
+
+ (void) cf_read_col(infits_1, TFLOAT, "BKGD", (void **) &temp_float);
+ getnshift_float(bkgd1, temp_float, npix_1, delta);
+ free(temp_float);
+
+ /* Average fluxes, weighting by exposure time; add counts. */
+ /* Include only pixels with non-zero quality flags. */
+ for (j=0L; j<npix_1; j++) {
+ if (quality1[j] > 0) {
+ f1 = exptime_1;
+ exptime_p[j] += f1;
+ flux_o[j] += f1 * flux1[j];
+ error_o[j] += f1 * f1 * (double) error1[j]*error1[j];
+ counts_o[j] += counts1[j];
+ weights_o[j] += weights1[j];
+ bkgd_o[j] += bkgd1[j];
+ quality_o[j] += f1 * (double) quality1[j];
+ }
+ }
+
+ FITS_close_file(infits_1, &status);
+
+ /* Write input file name and spectral shift to output file header. */
+ sprintf(keyword, "SPEC%03d", ngood);
+ FITS_update_key(outfits, TSTRING, keyword, infile, NULL, &status);
+ sprintf(keyword, "WOFF%03d", ngood);
+ shift = delta * wpc;
+ FITS_update_key(outfits, TFLOAT, keyword, &shift, "[A]", &status);
+
+
+ } /* end of loop over input files */
+
+ /* Convert variances back to sigma. Normalize flux, error, and quality by EXPTIME.
+ Convert from doubles to floats. */
+ for (j=0L; j<npix_1; j++) if (exptime_p[j] > 0.) {
+ flux1[j] = flux_o[j] / exptime_p[j];
+ error1[j] = sqrt(error_o[j]) / exptime_p[j];
+ quality1[j] = cf_nint(quality_o[j] / exptime_p[j]);
+ }
+ else {
+ flux1[j] = error1[j] = 0.;
+ quality1[j] = 0;
+ }
+
+ /* Write the output file (in multi-row format). */
+ cf_wrspec7 (outfits, npix_1, wave1, flux1, error1, counts_o, weights_o, bkgd_o, quality1);
+
+ free(exptime_p);
+ free(wave1);
+ free(flux1);
+ free(error1);
+ free(bkgd1);
+ free(counts1);
+ free(weights1);
+ free(quality1);
+ free(flux_o);
+ free(error_o);
+ free(quality_o);
+ free(bkgd_o);
+ free(counts_o);
+ free(weights_o);
+
+ hdunum_o = 1;
+ FITS_movabs_hdu (outfits, hdunum_o, &hdutype_o, &status);
+
+ /* update output header keywords*/
+
+ FITS_update_key(outfits, TLONG, "EXP_STAT", &exp_stat_out, NULL, &status);
+ FITS_update_key(outfits, TDOUBLE, "EXPSTART", &mjd_start_o, NULL, &status);
+ FITS_update_key(outfits, TDOUBLE, "EXPEND", &mjd_end_o , NULL, &status);
+ FITS_update_key(outfits, TFLOAT, "EXPTIME", &exptime_o , NULL, &status);
+ FITS_update_key(outfits, TLONG, "NEVENTS", &nevents_o, NULL, &status);
+ FITS_update_key(outfits, TFLOAT, "RAWTIME", &rawtime_o , NULL, &status);
+ FITS_update_key(outfits, TLONG, "PLANTIME", &plantime_o, NULL, &status);
+ FITS_update_key(outfits, TLONG, "NBADEVNT", &nbadevnt_o, NULL, &status);
+ FITS_update_key(outfits, TLONG, "NBADPHA" , &nbadpha_o , NULL, &status);
+ FITS_update_key(outfits, TLONG, "EXP_BAD" , &exp_bad_o , NULL, &status);
+ FITS_update_key(outfits, TLONG, "EXP_BRST", &exp_brst_o, NULL, &status);
+ FITS_update_key(outfits, TLONG, "EXP_HV", &exp_hv_o, NULL, &status);
+ FITS_update_key(outfits, TLONG, "EXP_JITR", &exp_jitr_o, NULL, &status);
+ FITS_update_key(outfits, TLONG, "EXP_LIM" , &exp_lim_o , NULL, &status);
+ FITS_update_key(outfits, TLONG, "EXP_SAA" , &exp_saa_o , NULL, &status);
+ FITS_update_key(outfits, TLONG, "EXPNIGHT", &expnight_o, NULL, &status);
+
+ /* update FILENAME keyword in output file */
+ FITS_update_key(outfits, TSTRING, "FILENAME", outfile, NULL, &status);
+
+ strcpy(string0, "COMBINED SPECTRA");
+ FITS_update_key(outfits, TSTRING, "FILETYPE", string0, NULL, &status);
+
+ sprintf(string0, "000");
+ FITS_update_key(outfits, TSTRING, "EXP_ID", string0, NULL, &status);
+
+ FITS_read_key(outfits, TSTRING, "ROOTNAME", root_name, NULL, &status);
+ sprintf(string0, "%.8s000", root_name);
+ FITS_update_key(outfits, TSTRING, "ROOTNAME", string0, NULL, &status);
+
+ FITS_update_key(outfits, TINT, "NSPEC", &ngood,
+ "Number of combined spectral files", &status);
+
+ if (k_flag)
+ {
+ cf_if_fits_error(fits_modify_name(outfits, "EXP_STAT", "OBS_STAT", &status));
+ cf_if_fits_error(fits_modify_name(outfits, "EXPSTART", "OBSSTART", &status));
+ cf_if_fits_error(fits_modify_name(outfits, "EXPEND", "OBSEND", &status));
+ cf_if_fits_error(fits_modify_name(outfits, "EXPTIME", "OBSTIME", &status));
+ cf_if_fits_error(fits_modify_name(outfits, "EXPNIGHT", "OBSNIGHT", &status));
+ }
+ else {
+ /* Add HISTORY lines to output file */
+ if (ignore_exp_stat) {
+ sprintf (comment, "cf_combine: Including only files with EXP_STAT=0");
+ FITS_write_history (outfits, comment, &status);
+ }
+
+ else {
+ sprintf (comment, "cf_combine: Including only files with EXP_STAT >= 0");
+ FITS_write_history (outfits, comment, &status);
+ }
+
+ sprintf (comment, "cf_combine: File list = %s", flist);
+ FITS_write_history (outfits, comment, &status);
+
+ time (&timeval);
+ timestr = ctime (&timeval);
+ sprintf (comment, "cf_combine: Completed on %.24s", timestr);
+ FITS_write_history (outfits, comment, &status);
+ }
+
+ /* Close the files. */
+ fclose(ifp);
+ FITS_close_file(outfits, &status);
+
+ /* Enter a timestamp into the log. */
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Done processing");
+#ifdef SOLARIS
+ ieee_retrospective(stdout);
+#endif
+ return 0;
+}
+
+
+void getnshift_float (float *out_vect, float *in_vect, long n, int delta)
+{
+ long k, ind;
+
+ for (k = 0; k < n; k++)
+ {
+ ind = k - delta;
+ if((ind >= 0) && (ind < n))
+ out_vect[k] = in_vect[ind];
+ else
+ out_vect[k] = 0;
+ }
+}
+
+void getnshift_short (short *out_vect, short *in_vect, long n, int delta)
+{
+ long k, ind;
+
+ for (k = 0; k < n; k++)
+ {
+ ind = k - delta;
+ if((ind >= 0) && (ind < n))
+ out_vect[k] = in_vect[ind];
+ else
+ out_vect[k] = 0;
+ }
+}
+
+void getnshift_long (long *out_vect, long *in_vect, long n, int delta)
+{
+ long k, ind;
+
+ for (k = 0; k < n; k++)
+ {
+ ind = k - delta;
+ if((ind >= 0) && (ind < n))
+ out_vect[k] = in_vect[ind];
+ else
+ out_vect[k] = 0;
+ }
+}
diff --git a/src/analysis/cf_make_900_obs.csh b/src/analysis/cf_make_900_obs.csh
new file mode 100755
index 0000000..9edbc70
--- /dev/null
+++ b/src/analysis/cf_make_900_obs.csh
@@ -0,0 +1,193 @@
+#!/usr/local/bin/tcsh -f
+
+#******************************************************************************
+#* Johns Hopkins University
+#* Center For Astrophysical Sciences
+#* FUSE
+#******************************************************************************
+#*
+#* Synopsis: cf_make_900_obs.csh association_file
+#*
+#* Description: This routine is derived from cf_make_all_obs.csh, but modified
+#* to consider only 900+ (airglow) files. Output is a single
+#* quick-look image of the airglow spactrum.
+#*
+#* Extracted spectra are combined, not IDF files.
+#*
+#* When an expected data set is missing, the script stops, cleans
+#* the directory, and returns 1.
+#*
+#* History: 08/08/08 1.00 wvd Create separate quick-look image
+#* for 900+ (airglow) exposures.
+#* Always combine extracted spectra. If
+#* cf_xcorr fails, combine with no shift.
+#* 08/08/08 1.01 wvd Rename airglow quick-look file to
+#* M112580100000airgttagf.gif
+#*
+#*****************************************************************************/
+
+# Delete files after processing? (Default is no.)
+#set DELETE_IDF # Delete intermediate data files
+set DELETE_BPM # Delete bad-pixel map files
+
+# Set program path
+set rm = "/bin/rm -f"
+
+set cf_xcorr = cf_xcorr
+set cf_combine = cf_combine
+set cf_pack = cf_pack
+set cf_nvo = cf_nvo
+set idl_obsplot = idl_obsplot.pl
+set modhead = modhead
+
+# Init var list
+set detector = (1a 2b)
+set channel = (lif sic)
+set resolution = (2 3 4)
+set obsmod = (hist ttag)
+
+# Determine the root name and the program ID
+set asnf = $1
+set rn = ${asnf:s/000asnf.fit//}
+set pid = `echo $rn | awk '{print substr($1, 1, 4)}'`
+
+# Determine the object class
+set tmp_file = `ls ${rn}*fcal.fit | awk '{if (NR == 1) print}'`
+set tmp_buf = `$modhead $tmp_file OBJCLASS`
+set objclass = $tmp_buf[2]
+
+# Clean tmp files that the script will create (safe)
+$rm tmp_xcorr.res tmp_combine.lis
+$rm tmp_good_exp.lis tmp_exp.lis tmp_seg_dn.lis
+$rm DN_${rn}*.fit
+
+foreach om ($obsmod)
+ foreach res ($resolution)
+ foreach chan ($channel)
+ foreach det ($detector)
+
+ set ignore_exp_stat = ''
+ if ($om == hist) set ignore_exp_stat = -a
+ if ($pid == S100) set ignore_exp_stat = -a
+ if ($pid == M106) set ignore_exp_stat = -a
+
+ # Find exposures that match the current segment
+ set seg = $det$chan$res$om
+ set readfiles = 0
+ ls ${rn}9[0-9][0-9]${seg}fcal.fit |& grep -v 000${seg} > tmp_exp.lis # Keep only "9xx" exposures
+ if ($? == 0) then
+ set readfiles = 2
+ set ignore_exp_stat = -a
+ endif
+
+ if ($readfiles >= 1) then # There are one or more exposures
+
+ echo " "
+ echo "*** Processing: $seg ***"
+ # [1a][lif] -> [1b][lif], [2b][lif] -> [2a][lif] etc...
+ if ($det == 1a) set det2 = 1b
+ if ($det == 2b) set det2 = 2a
+ set seg2 = $det2$chan$res$om
+
+ echo "----- cf_xcorr input -----"
+ cat tmp_exp.lis
+ echo "----------------------------"
+ $cf_xcorr tmp_exp.lis tmp_xcorr.res # Compute shift and sigma_shift
+ echo "----- cf_xcorr results -----"
+ cat tmp_xcorr.res
+ echo "----------------------------"
+
+ awk '{if ($3 >= 0) {print $6, $2} else {print $6}}' tmp_xcorr.res > tmp_good_exp.lis
+
+ #
+ # --- Path 1: Optimize resolution ---
+ #
+
+ echo "Optimize resolution..."
+ set n_good = `cat tmp_good_exp.lis | wc -l`
+
+ # Extract [Day + Night] spectra
+ set s = DN_${rn}900${seg}fcal.fit
+ awk '{print "'$rn'"$1"'$seg'fcal.fit",$2}' tmp_good_exp.lis > tmp_combine.lis # Combine $seg [dn]
+ # echo "----- Combining Files ----- "
+ # cat tmp_combine.lis
+ # echo "Output: " $s
+ $cf_combine -k $ignore_exp_stat tmp_combine.lis $s
+ # $modhead "${s}[1]" NUM_EXP $n_good
+ $modhead "${s}[1]" COMBMETH XCORR
+ echo $s >> tmp_seg_dn.lis
+
+ set s = DN_${rn}900${seg2}fcal.fit
+ awk '{print "'$rn'"$1"'$seg2'fcal.fit",$2}' tmp_good_exp.lis > tmp_combine.lis # Combine $seg2 [dn]
+ # echo "----- Combining Files ----- "
+ # cat tmp_combine.lis
+ # echo "Output: " $s
+ $cf_combine -k $ignore_exp_stat tmp_combine.lis $s
+ # $modhead "${s}[1]" NUM_EXP $n_good
+ $modhead "${s}[1]" COMBMETH XCORR
+ echo $s >> tmp_seg_dn.lis
+
+ endif
+ end
+
+ $rm tmp_xcorr.res tmp_combine.lis
+ $rm tmp_good_exp.lis tmp_exp.lis
+
+ end
+
+ # Pack the 8 [detector][channel] pairs together
+ if (-e tmp_seg_dn.lis) then
+
+ set fcal_all = ${rn}00900all$res${om}fcal.fit # Final output name
+ $rm $fcal_all # Clean (safe)
+ set n_segs = `cat tmp_seg_dn.lis | wc -l`
+
+ if (!($n_segs == 8)) then
+
+ @ mseg = 8 - $n_segs
+ echo "ERROR: $mseg (day + night) segments are missing"
+ $rm tmp_seg_dn.lis
+ goto crash
+
+ else
+
+ $cf_pack tmp_seg_dn.lis $fcal_all
+ $rm tmp_seg_dn.lis
+
+ # Plot figures, delete unwanted files
+ $idl_obsplot {$rn} airglow
+ mv ${rn}00900spec${om}f.gif ${rn}00000airg${om}f.gif
+ $rm ${rn}00900lif*.gif ${rn}00900sic*.gif
+ $rm $fcal_all
+
+ endif
+ endif
+ end
+end
+
+# Clean [dn] files.
+$rm DN_${rn}*.fit
+
+# Delete IDF files
+if $?DELETE_IDF then
+ echo "NOTE: Deleting intermediate data files."
+ $rm ${rn}*idf.fit
+endif
+
+# Delete bad-pixel-map (bpm) files
+if $?DELETE_BPM then
+ echo "NOTE: Deleting bad pixel map (bpm) files."
+ $rm ${rn}*bpm.fit
+endif
+
+exit(0)
+
+crash: # Procedure when script crashes
+
+# Clean directory
+$rm tmp_xcorr.res tmp_combine.lis
+$rm tmp_good_exp.lis tmp_exp.lis tmp_seg_dn.lis
+$rm DN_*.fit
+
+# Return 1
+exit(1)
diff --git a/src/analysis/cf_make_all_exp.c b/src/analysis/cf_make_all_exp.c
new file mode 100644
index 0000000..926ac2c
--- /dev/null
+++ b/src/analysis/cf_make_all_exp.c
@@ -0,0 +1,91 @@
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: cf_make_all_exp output_filename input1 input2 input3 input4
+ *
+ * Description: For a single exposure, copies header of channel with largest
+ * value of EXPTIME into an otherwise empty "all" file.
+ * Input files should represent each of the four FUSE channels.
+ *
+ *
+ * History: 08/11/05 wvd v1.0 Based on cf_quicklook.
+ *
+ ****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "calfuse.h"
+
+static char CF_PRGM_ID[]= "cf_make_all_exp";
+static char CF_VER_NUM[]= "1.0";
+
+int main(int argc,char *argv[]){
+
+ char *corrected_filename, *string_pointer;
+ char comment[FLEN_CARD], datestr[FLEN_CARD];
+ int i, nextend=0, ref_file=2, timeref;
+ int status=0;
+ float exptime, max_exptime;
+
+ fitsfile *infits,*outfits;
+
+ if (argc != 6) {
+ printf("Incorrect number of arguments.\n");
+ printf("Calling sequence: cf_make_all_exp output_filename "
+ "input1 input2 input3 input4\n");
+ exit(1);
+ }
+
+ /* Initialize error checking. */
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Started execution.");
+
+ /* Determine the channel with the longest exposure time */
+
+ max_exptime = 0;
+ for (i = 0; i < 4; i++) {
+ FITS_open_file(&infits, argv[2+i], READONLY, &status);
+ FITS_read_key(infits, TFLOAT, "EXPTIME", &exptime, NULL, &status);
+ if (exptime >= max_exptime) {
+ ref_file = 2 + i;
+ max_exptime = exptime;
+ }
+ FITS_close_file(infits, &status);
+ }
+
+ /* Copy header from the reference file to the exposure-level "all" file. */
+
+ FITS_open_file(&infits, argv[ref_file], READONLY, &status);
+ FITS_create_file(&outfits, argv[1], &status);
+ FITS_copy_hdu(infits, outfits, 0, &status);
+
+ /* Modify a few header keywords. */
+ string_pointer = strrchr(argv[1],'/');
+ if (string_pointer == NULL) corrected_filename = argv[1];
+ else corrected_filename = &(string_pointer[1]);
+ FITS_update_key(outfits, TINT, "NEXTEND", &nextend, NULL, &status);
+ FITS_write_date(outfits, &status);
+ FITS_update_key(outfits, TSTRING, "FILENAME", corrected_filename, NULL, &status);
+ FITS_update_key(outfits, TSTRING, "FILETYPE", "EXPOSURE-LEVEL STATUS FILE", NULL, &status);
+
+ /* Add a note warning that this file contains no data. */
+ FITS_write_comment(outfits, " ", &status);
+ FITS_write_comment(outfits,
+ "This file contains no data.", &status);
+ FITS_write_comment(outfits,
+ "Its header keywords are used by the DADS cataloging software.", &status);
+ fits_get_system_time(datestr, &timeref, &status);
+ sprintf(comment, "CalFUSE v%s %.10s", CALFUSE_VERSION, datestr);
+ FITS_write_comment(outfits, comment, &status);
+ FITS_write_comment(outfits, " ", &status);
+
+
+ FITS_close_file(infits, &status);
+ FITS_close_file(outfits,&status);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/analysis/cf_make_all_obs.csh b/src/analysis/cf_make_all_obs.csh
new file mode 100755
index 0000000..2a97247
--- /dev/null
+++ b/src/analysis/cf_make_all_obs.csh
@@ -0,0 +1,555 @@
+#!/usr/local/bin/tcsh -f
+
+#******************************************************************************
+#* Johns Hopkins University
+#* Center For Astrophysical Sciences
+#* FUSE
+#******************************************************************************
+#*
+#* Synopsis: cf_make_all_obs.csh association_file
+#*
+#* Description: Creates 3 files from Calfuse output (properly run):
+#*
+#* 1) An "all" file containing 1 extension per detector (= 8).
+#* Each extension contains a combined spectrum from the set
+#* of exposures, using "Xcorr" or "Background" method.
+#* 2) In the case of TTAG data, creates an "ano" file. Same as
+#* the "all" file but considering "night only" exposure time.
+#* 3) A National Virtual Observatory "nvo" file. One extension
+#* containing wavelengths that span the whole FUSE range.
+#*
+#* The Xcorr method consists of co-adding spectra, the latter
+#* being corrected for a possible shift. The Background method
+#* consists of combining all the IDF files.
+#*
+#* The Xcorr test is performed on 4 (detector, channel) pairs, the
+#* method of other pairs are given by them:
+#* LiF 1a -> Lif 1b
+#* LiF 2b -> LiF 2a
+#* SiC 1a -> Sic 1b
+#* Sic 2b -> Sic 2a
+#* In the script, the left segments are referred as to $seg (or
+#* $det) and the right segments are referred as to $seg2 (or
+#* $det2).
+#*
+#* When an expected data set is missing, the script stops, cleans
+#* the directory, and returns 1.
+#*
+#* History: 04/15/05 1.0 tc First release
+#* 08/22/05 1.1 wvd Argument is name of association file.
+#* 10/20/05 1.2 wvd Use idl_obsplot.pl to call cf_obsplot.
+#* 10/25/05 1.3 wvd Add option to delete BPM or IDF files.
+#* 03/21/06 1.4 wvd If there's only one exposure, always
+#* follow the cross-correlation path.
+#* Don't check the number of night-only
+#* spectra before calling cf_pack.
+#* 03/28/06 1.5 wvd If there's no good time in any exposure,
+#* follow the cross-correlation path.
+#* 04/27/06 1.6 wvd Be smarter when discarding 000 files.
+#* Always use cross-corr for HIST data.
+#* 05/23/06 1.7 wvd Move -k to proper spot after cf_combine.
+#* 06/02/06 1.8 wvd If OBJCLASS = 7 (Sky Background)
+#* always combine IDF files.
+#* 06/22/06 1.9 wvd Call idf_combine with -z flag.
+#* 05/24/07 1.10 bot If only 900+ spectra are available,
+#* use them.
+#* 04/04/08 1.11 bot Ignore EXP_STAT in cf_combine for HIST
+#* data.
+#* 07/25/08 1.12 wvd Ignore EXP_STAT in cf_combine and
+#* idf_combine for BR-EARTH observations
+#* (S100, M106, and 900+ exposures).
+#* 08/08/08 1.13 wvd Don't ignore EXP_STAT for 900+ exposures.
+#* 08/15/08 1.14 wvd Call cf_make_900_obs.csh
+#* to make quick-look airglow plot.
+#*
+#*****************************************************************************/
+
+# Delete files after processing? (Default is no.)
+#set DELETE_IDF # Delete intermediate data files
+#set DELETE_BPM # Delete bad-pixel map files
+
+# Set program path
+set rm = "/bin/rm -f"
+
+set cf_xcorr = cf_xcorr
+set cf_combine = cf_combine
+set cf_pack = cf_pack
+set cf_nvo = cf_nvo
+set idl_obsplot = idl_obsplot.pl
+set modhead = modhead
+
+#set cf_xcorr = /home/vela/civeit/Work/CalFuse/Xcorr/New/cf_xcorr
+#set cf_combine = /home/vela/civeit/Work/CalFuse/Shiftexp/cf_combine
+#set cf_pack = /home/vela/civeit/Work/CalFuse/Pack/cf_pack
+#set cf_nvo = /home/vela/civeit/Work/CalFuse/Nvo/cf_nvo
+#set modhead = /home/vela/civeit/local/bin/modhead
+
+#set cf_obsplot = /data1/fuse/calfuse/v3.1/idl/cf_obsplot.pro
+
+# Init var list
+set detector = (1a 2b)
+set channel = (lif sic)
+set resolution = (2 3 4)
+set obsmod = (hist ttag)
+
+# Determine the root name and the program ID
+set asnf = $1
+set rn = ${asnf:s/000asnf.fit//}
+set pid = `echo $rn | awk '{print substr($1, 1, 4)}'`
+
+# Determine the object class
+set tmp_file = `ls ${rn}*fcal.fit | awk '{if (NR == 1) print}'`
+set tmp_buf = `$modhead $tmp_file OBJCLASS`
+set objclass = $tmp_buf[2]
+
+# Clean tmp files that the script will create (safe)
+$rm tmp_xcorr.res tmp_bpm1.lis tmp_bpm2.lis tmp_combine.lis tmp_night_exp.lis
+$rm tmp_all_night_exp.lis tmp_good_exp.lis tmp_exp.lis tmp_seg_dn.lis tmp_seg_no.lis
+$rm DN_${rn}*.fit NO_${rn}*.fit
+
+foreach om ($obsmod)
+ foreach res ($resolution)
+ foreach chan ($channel)
+ foreach det ($detector)
+
+ set ignore_exp_stat = ''
+ if ($om == hist) set ignore_exp_stat = -a
+ if ($pid == S100) set ignore_exp_stat = -a
+ if ($pid == M106) set ignore_exp_stat = -a
+
+ # Find exposures that match the current segment
+ set seg = $det$chan$res$om
+ set readfiles = 0
+ ls ${rn}[0-8][0-9][0-9]${seg}fcal.fit |& grep -v 000${seg} > tmp_exp.lis # Reject EXP "9xx" and "000"
+
+ if ($? == 0) then
+ set readfiles = 1
+ else
+ ls ${rn}9[0-9][0-9]${seg}fcal.fit |& grep -v 000${seg} > tmp_exp.lis # Keep only "9xx" exposures
+ if ($? == 0) set readfiles = 2
+ endif
+
+ if ($readfiles >= 1) then # There are one or more exposures
+
+ echo " "
+ echo "*** Processing: $seg ***"
+ # [1a][lif] -> [1b][lif], [2b][lif] -> [2a][lif] etc...
+ if ($det == 1a) set det2 = 1b
+ if ($det == 2b) set det2 = 2a
+ set seg2 = $det2$chan$res$om
+
+ echo "----- cf_xcorr input -----"
+ cat tmp_exp.lis
+ echo "----------------------------"
+ $cf_xcorr tmp_exp.lis tmp_xcorr.res # Compute shift and sigma_shift
+ echo "----- cf_xcorr results -----"
+ cat tmp_xcorr.res
+ echo "----------------------------"
+
+ awk '{if ($5 > 0) print $6, $4, $5}' tmp_xcorr.res > tmp_all_night_exp.lis
+ awk '{if ($3 >= 0) print $6, $2}' tmp_xcorr.res > tmp_good_exp.lis
+ awk '{if (($3 >= 0) && ($5 > 0)) print $6, $2, $4, $5}' tmp_xcorr.res > tmp_night_exp.lis
+ set time_good = `awk 'BEGIN{$t = 0} {if ($3 >= 0) $t = $t + $4} END{print $t}' tmp_xcorr.res`
+ set time_bad = `awk 'BEGIN{$t = 0} {if ($3 < 0) $t = $t + $4} END{print $t}' tmp_xcorr.res`
+ echo "Xcorr time: $time_good - Background time: $time_bad"
+ set n_exp = `cat tmp_xcorr.res | wc -l`
+
+ if (($time_good > 2 * $time_bad && $objclass != 7) || ($time_good == 0 && $time_bad == 0) || $n_exp == 1 || $om == hist) then
+
+ #
+ # --- Path 1: Optimize resolution ---
+ #
+
+ echo "Optimize resolution..."
+ set n_good = `cat tmp_good_exp.lis | wc -l`
+
+ # Extract [Day + Night] spectra
+ set s = DN_${rn}000${seg}fcal.fit
+ awk '{print "'$rn'"$1"'$seg'fcal.fit",$2}' tmp_good_exp.lis > tmp_combine.lis # Combine $seg [dn]
+ # echo "----- Combining Files ----- "
+ # cat tmp_combine.lis
+ # echo "Output: " $s
+ $cf_combine -k $ignore_exp_stat tmp_combine.lis $s
+ # $modhead "${s}[1]" NUM_EXP $n_good
+ $modhead "${s}[1]" COMBMETH XCORR
+ echo $s >> tmp_seg_dn.lis
+
+ set s = DN_${rn}000${seg2}fcal.fit
+ awk '{print "'$rn'"$1"'$seg2'fcal.fit",$2}' tmp_good_exp.lis > tmp_combine.lis # Combine $seg2 [dn]
+ # echo "----- Combining Files ----- "
+ # cat tmp_combine.lis
+ # echo "Output: " $s
+ $cf_combine -k $ignore_exp_stat tmp_combine.lis $s
+ # $modhead "${s}[1]" NUM_EXP $n_good
+ $modhead "${s}[1]" COMBMETH XCORR
+ echo $s >> tmp_seg_dn.lis
+
+ set n_night = `cat tmp_night_exp.lis | wc -l`
+ if ($om == ttag && $n_night > 0) then # Create and combine night only files
+
+ echo "*** Creating night only files ***"
+ set exp_nums = `awk '{print $1}' tmp_night_exp.lis`
+
+ foreach exp ($exp_nums)
+
+ # Create night-only BPM and FCAL files if they do not already exist.
+ set bno1 = NO_$rn$exp$det${om}fbpm.fit # Bad-pixel maps
+ set bno2 = NO_$rn$exp$det2${om}fbpm.fit
+ set cno1 = NO_$rn$exp${seg}fcal.fit # Extracted spectra
+ set cno2 = NO_$rn$exp${seg2}fcal.fit
+
+ set etime = `egrep "^$exp" tmp_night_exp.lis | awk '{print $3}'`
+ set ntime = `egrep "^$exp" tmp_night_exp.lis | awk '{print $4}'`
+ set ratio = `egrep "^$exp" tmp_night_exp.lis | awk '{printf "%.0f", 0.5+$4/$3*10.}'`
+
+ if (!(-e $cno1)) then
+ if ($etime == $ntime) then
+ echo "$cno1 is a symbolic link to $rn$exp${seg}fcal.fit"
+ ln -s $rn$exp${seg}fcal.fit $cno1
+ else
+
+ set idf_file = $rn$exp$det${om}fidf.fit
+ if (!(-e $bno1)) then
+ if ($ratio > 9) then
+ echo "$bno1 is a symbolic link to $rn$exp$det${om}fbpm.fit"
+ ln -s $rn$exp$det${om}fbpm.fit $bno1
+ else
+ echo "Creating BPM: $bno1 ..."
+ cf_bad_pixels -n $bno1 $idf_file
+ endif
+ endif
+
+ echo "Creating (LiF + SiC) FCAL: $cno1 ..."
+ cf_extract_spectra -n $bno1 -r NO_$rn$exp $idf_file # Existence of $bno1 is not required
+ endif
+ endif
+
+ if (!(-e $cno2)) then
+ if ($etime == $ntime) then
+ echo "Using a symbolic link to $cno2"
+ ln -s $rn$exp${seg2}fcal.fit NO_$rn$exp${seg2}fcal.fit
+ else
+
+ set idf_file = $rn$exp$det2${om}fidf.fit
+ if (!(-e $bno2)) then
+ if ($ratio > 9) then
+ echo "Using a symbolic link to $bno2"
+ ln -s $rn$exp$det2${om}fbpm.fit NO_$rn$exp$det2${om}fbpm.fit
+ else
+ echo "Creating BPM: $bno2 ..."
+ cf_bad_pixels -n $bno2 $idf_file
+ endif
+ endif
+
+ echo "Creating (LiF + SiC) FCAL: $cno2 ..."
+ cf_extract_spectra -n $bno2 -r NO_$rn$exp $idf_file # Existence of $bno2 is not required
+ endif
+ endif
+
+ end
+
+ # Combine exposures into a single spectrum.
+ set s = NO_${rn}000${seg}fcal.fit
+ awk '{print "NO_'$rn'"$1"'$seg'fcal.fit",$2}' tmp_night_exp.lis > tmp_combine.lis # Combine $seg [no]
+ $cf_combine -k $ignore_exp_stat tmp_combine.lis $s
+ # $modhead "${s}[1]" NUM_EXP $n_night
+ $modhead "${s}[0]" DAYNIGHT NIGHT
+ $modhead "${s}[1]" COMBMETH XCORR
+ echo $s >> tmp_seg_no.lis
+
+ set s = NO_${rn}000${seg2}fcal.fit
+ awk '{print "NO_'$rn'"$1"'$seg2'fcal.fit",$2}' tmp_night_exp.lis > tmp_combine.lis # Combine $seg2 [no]
+ $cf_combine -k $ignore_exp_stat tmp_combine.lis $s
+ # $modhead "${s}[1]" NUM_EXP $n_night
+ $modhead "${s}[0]" DAYNIGHT NIGHT
+ $modhead "${s}[1]" COMBMETH XCORR
+ echo $s >> tmp_seg_no.lis
+
+ endif
+
+ else
+
+ #
+ # --- Path 2: Optimize background ---
+ #
+
+ echo "Optimize background..."
+
+ # Combine IDF files
+ set idf1_all = DN_${rn}000$det${om}fidf.fit # Same for [dn] and [no]
+ set idf2_all = DN_${rn}000$det2${om}fidf.fit
+
+ if (!(-e $idf1_all)) then
+ echo "Creating IDF: $idf1_all ..."
+ if ($readfiles == 1) then
+ ls ${rn}[0-8][0-9][0-9]$det${om}fidf.fit |& grep -v 000${det} > tmp_idf.lis # Reject EXP "9xx" and "000"
+ else
+ ls ${rn}9[0-9][0-9]$det${om}fidf.fit |& grep -v 000${det} > tmp_idf.lis # Consider only airglow
+ endif
+ if ($? == 0) then # IDF files exist
+
+ set idf_lis = `awk '{printf "%s ",$1}' tmp_idf.lis`
+ # echo "Combining IDF files: " $idf_lis
+ idf_combine -cz $ignore_exp_stat $idf1_all $idf_lis # Create combined IDF file for $seg
+ $rm tmp_idf.lis
+
+ else
+
+ echo "ERROR: IDF files are missing"
+ $rm tmp_idf.lis
+ goto crash
+
+ endif
+ endif
+
+ if (!(-e $idf2_all)) then
+ echo "Creating IDF: $idf2_all ..."
+ if ($readfiles == 1) then
+ ls ${rn}[0-8][0-9][0-9]$det2${om}fidf.fit |& grep -v 000${det2} > tmp_idf.lis # Reject EXP "9xx" and "000"
+ else
+ ls ${rn}9[0-9][0-9]$det2${om}fidf.fit |& grep -v 000${det2} > tmp_idf.lis # Consider only airglow
+ endif
+ if ($? == 0) then # IDF files exist
+
+ set idf_lis = `awk '{printf "%s ",$1}' tmp_idf.lis`
+ # echo "Combining IDF files: " $idf_lis
+ idf_combine -cz $ignore_exp_stat $idf2_all $idf_lis # Create combined IDF file for $seg2
+ $rm tmp_idf.lis
+
+ else
+
+ echo "ERROR: IDF files are missing"
+ $rm tmp_idf.lis
+ goto crash
+
+ endif
+ endif
+
+ # Get the number of (valid) combined IDF files
+ set tmp_buf = `$modhead $idf1_all NSPEC`
+ set n_comb1 = $tmp_buf[3]
+ set tmp_buf = `$modhead $idf1_all SPEC001`
+ set idf1_1 = $tmp_buf[3]
+ set tmp_buf = `$modhead $idf2_all NSPEC`
+ set n_comb2 = $tmp_buf[3]
+ set tmp_buf = `$modhead $idf2_all SPEC001`
+ set idf2_1 = $tmp_buf[3]
+
+ # Combine BPM files
+ set bpm1_all = DN_${rn}000$det${om}fbpm.fit
+ set bpm2_all = DN_${rn}000$det2${om}fbpm.fit
+
+ if (!(-e $bpm1_all)) then
+ echo "Combine all BPM (from IDF): $bpm1_all ..."
+ bpm_combine $bpm1_all $idf1_all # Create combined BPM file [dn] for $seg
+ endif
+
+ if (!(-e $bpm2_all)) then
+ echo "Combine all BPM (from IDF): $bpm2_all ..."
+ bpm_combine $bpm2_all $idf2_all # Idem for $seg2
+ endif
+
+ # Extract [Day + Night] spectra
+ set s = DN_${rn}000${seg}fcal.fit
+ set xxx = DN_${rn}xxx${seg}fcal.fit
+ if (!(-e $xxx)) cf_extract_spectra -r DN_${rn}xxx $idf1_all # Avoid overwrite LiF | SiC
+ echo $xxx > tmp_combine.lis
+ $cf_combine -k $ignore_exp_stat tmp_combine.lis $s
+ $modhead "${s}[0]" NSPEC $n_comb1
+ $modhead "${s}[0]" SPEC001 $idf1_1
+ $modhead "${s}[1]" COMBMETH BACKGRND
+ echo $s >> tmp_seg_dn.lis
+
+ set s = DN_${rn}000${seg2}fcal.fit
+ set xxx = DN_${rn}xxx${seg2}fcal.fit
+ if (!(-e $xxx)) cf_extract_spectra -r DN_${rn}xxx $idf2_all # Avoid overwrite LiF | SiC
+ echo $xxx > tmp_combine.lis
+ $cf_combine -k $ignore_exp_stat tmp_combine.lis $s
+ $modhead "${s}[0]" NSPEC $n_comb2
+ $modhead "${s}[0]" SPEC001 $idf2_1
+ $modhead "${s}[1]" COMBMETH BACKGRND
+ echo $s >> tmp_seg_dn.lis
+
+ set n_night = `cat tmp_all_night_exp.lis | wc -l`
+ if ($om == ttag && $n_night > 0) then # Create and combine night only files
+
+ echo "*** Creating night only files ***"
+ set exp_nums = `awk '{print $1}' tmp_all_night_exp.lis`
+ $rm tmp_bpm1.lis tmp_bpm2.lis
+
+ foreach exp ($exp_nums)
+
+ # Create bpm night only files (if they do not exist yet)
+ set bno1 = NO_$rn$exp$det${om}fbpm.fit
+ set bno2 = NO_$rn$exp$det2${om}fbpm.fit
+
+ set idf_file = $rn$exp$det${om}fidf.fit
+ if (!(-e $bno1)) then
+ echo "Creating BPM: $bno1 ..."
+ cf_bad_pixels -n $bno1 $idf_file
+ endif
+ if (-e $bno1) echo $bno1 >> tmp_bpm1.lis # If valid, add in $seg list
+
+ set idf_file = $rn$exp$det2${om}fidf.fit
+ if (!(-e $bno2)) then
+ echo "Creating BPM: $bno2 ..."
+ cf_bad_pixels -n $bno2 $idf_file
+ endif
+ if (-e $bno2) echo $bno2 >> tmp_bpm2.lis # If valid, add in $seg2 list
+
+ end
+
+
+ # Combine BPM for $seg and extract spectra
+
+ set bpm1_all = NO_${rn}000$det${om}fbpm.fit
+ set n_bpm = `cat tmp_bpm1.lis | wc -l`
+ echo "Number of valid BPM files: $n_bpm"
+
+ if ($n_bpm > 0) then
+
+ echo $n_bpm > tmp_bpm.lis
+ cat tmp_bpm1.lis >> tmp_bpm.lis
+
+ if (!(-e $bpm1_all)) then
+ echo "Combine all BPM (from list): $bpm1_all ..."
+ bpm_combine $bpm1_all tmp_bpm.lis # Create combined BPM file [no] for $seg
+ endif
+ $rm tmp_bpm.lis
+
+ endif
+
+ # Extract [Night only] spectra. The existence of $bpm1_all is not required
+ set s = NO_${rn}000${seg}fcal.fit
+ set xxx = NO_${rn}xxx${seg}fcal.fit
+ if (!(-e $xxx)) cf_extract_spectra -n $bpm1_all -r NO_${rn}xxx $idf1_all # Avoid overwrite LiF | SiC
+ echo $xxx > tmp_combine.lis
+ $cf_combine -k $ignore_exp_stat tmp_combine.lis $s
+ $modhead "${s}[0]" NSPEC $n_comb1
+ $modhead "${s}[0]" SPEC001 $idf1_1
+ $modhead "${s}[1]" COMBMETH BACKGRND
+ echo $s >> tmp_seg_no.lis
+
+
+ # Combine BPM for $seg2 and extract spectra
+
+ set bpm2_all = NO_${rn}000$det2${om}fbpm.fit
+ set n_bpm = `cat tmp_bpm2.lis | wc -l`
+ echo "Number of valid BPM files: $n_bpm"
+
+ if ($n_bpm > 0) then
+
+ echo $n_bpm > tmp_bpm.lis
+ cat tmp_bpm2.lis >> tmp_bpm.lis
+
+ if (!(-e $bpm2_all)) then
+ echo "Combine all BPM (from list): $bpm2_all ..."
+ bpm_combine $bpm2_all tmp_bpm.lis # Create combined BPM file [no] for $seg2
+ endif
+ $rm tmp_bpm.lis
+
+ endif
+
+ # Extract [Night only] spectra. The existence of $bpm2_all is not required
+ set s = NO_${rn}000${seg2}fcal.fit
+ set xxx = NO_${rn}xxx${seg2}fcal.fit
+ if (!(-e $xxx)) cf_extract_spectra -n $bpm2_all -r NO_${rn}xxx $idf2_all # Avoid overwrite LiF | SiC
+ echo $xxx > tmp_combine.lis
+ $cf_combine -k $ignore_exp_stat tmp_combine.lis $s
+ $modhead "${s}[0]" NSPEC $n_comb2
+ $modhead "${s}[0]" SPEC001 $idf2_1
+ $modhead "${s}[1]" COMBMETH BACKGRND
+ echo $s >> tmp_seg_no.lis
+
+ endif
+ endif
+ endif
+ end
+
+ $rm tmp_xcorr.res tmp_bpm1.lis tmp_bpm2.lis tmp_combine.lis
+ $rm tmp_all_night_exp.lis tmp_good_exp.lis tmp_exp.lis tmp_night_exp.lis
+
+ end
+
+ # Pack the 8 [detector][channel] pairs together ([dn] and [no] for ttag)
+ if (-e tmp_seg_dn.lis) then
+
+ set fcal_all = ${rn}00000all$res${om}fcal.fit # Final output name
+ $rm $fcal_all # Clean (safe)
+ set n_segs = `cat tmp_seg_dn.lis | wc -l`
+
+ if (!($n_segs == 8)) then
+
+ @ mseg = 8 - $n_segs
+ echo "ERROR: $mseg (day + night) segments are missing"
+ $rm tmp_seg_dn.lis
+ goto crash
+
+ else
+
+ $cf_pack tmp_seg_dn.lis $fcal_all
+ $rm tmp_seg_dn.lis
+
+ # Plot figures
+ $idl_obsplot {$rn}
+
+ # Create National Virtual Observatory file
+ set nvo_file = ${rn}00000nvo$res${om}fcal.fit
+ $rm $nvo_file # Clean (safe)
+ $cf_nvo $fcal_all $nvo_file # Create file
+
+ if (-e tmp_seg_no.lis) then
+
+ set fcal_all = ${rn}00000ano$res${om}fcal.fit # Final output name
+ $rm $fcal_all # Clean (safe)
+ set n_segs = `cat tmp_seg_no.lis | wc -l`
+
+ # if (!($n_segs == 8)) then
+ #
+ # @ mseg = 8 - $n_segs
+ # echo "ERROR: $mseg (night only) segments are missing"
+ # $rm tmp_seg_no.lis
+ # # goto crash
+ #
+ # else
+
+ $cf_pack tmp_seg_no.lis $fcal_all
+ $rm tmp_seg_no.lis
+
+ # endif
+
+ endif
+ endif
+ endif
+ end
+end
+
+# Clean [dn] and [no] files. Just keep all, (ano) and nvo
+$rm DN_${rn}*.fit NO_${rn}*.fit
+
+# Delete IDF files
+if $?DELETE_IDF then
+ echo "NOTE: Deleting intermediate data files."
+ $rm ${rn}*idf.fit
+endif
+
+# Delete bad-pixel-map (bpm) files
+if $?DELETE_BPM then
+ echo "NOTE: Deleting bad pixel map (bpm) files."
+ $rm ${rn}*bpm.fit
+endif
+
+# Call routine to make quick-look airglow plot.
+cf_make_900_obs.csh $1
+
+exit(0)
+
+crash: # Procedure when script crashes
+
+# Clean directory
+$rm tmp_xcorr.res tmp_bpm1.lis tmp_bpm2.lis tmp_combine.lis tmp_night_exp.lis
+$rm tmp_all_night_exp.lis tmp_good_exp.lis tmp_exp.lis tmp_seg_dn.lis tmp_seg_no.lis
+$rm DN_*.fit NO_*.fit
+
+# Return 1
+exit(1)
diff --git a/src/analysis/cf_nvo.c b/src/analysis/cf_nvo.c
new file mode 100644
index 0000000..4dd9771
--- /dev/null
+++ b/src/analysis/cf_nvo.c
@@ -0,0 +1,497 @@
+/*******************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *******************************************************************************
+ *
+ * Usage: cf_nvo all_segments.fit nvo_file.fit
+ *
+ * Description: Write a National Virtual Observatory (nvo) file. The program
+ * uses the file created by cf_pack, which contains one spectrum
+ * per extension, each corresponding to a detector channel.
+ *
+ * History: 04/11/05 tc v1.0 First release
+ * 05/16/2005 wvd v1.1 Check mean flux of each segment.
+ * If preferred channel is missing,
+ * replace it with another.
+ * 05/19/2005 wvd v1.2 Shift each channel to match
+ * LiF1A between 1045 and 1070 A.
+ * 05/20/2005 wvd v1.3 For emission-line sources,
+ * cross-correlate on O VI lines.
+ * 05/23/2005 wvd v1.4 Don't assume that sides A and B
+ * have the same shift.
+ * 06/01/2005 wvd v1.5 Do assume that sides A and B
+ * have the same shift.
+ * 06/03/2005 wvd v1.6 Delete unused variables.
+ * 06/08/2005 wvd v1.7 Define MAXFLOAT if needed.
+ * 06/16/2005 wvd v1.8 Include values.h
+ * 07/06/2005 wvd v1.9 If FESCENT = FES B, use LiF 2B
+ * as wavelength standard.
+ * 07/12/2005 wvd v1.10 Give up on use of MAXFLOAT.
+ * 08/11/2005 wvd v1.11 Set keyword NEXTEND = 1.
+ * 03/22/2006 wvd v1.12 Allow use of SiC data for
+ * 1000-1100 A region.
+ * Don't cross-correlate segments
+ * with OBSTIME = 0.
+ * 05/16/2006 wvd v1.13 Use Lyman beta to align
+ * background exposures.
+ * Use O VI and C II to align WD's.
+ * 05/19/2006 wvd v1.14 In copy_spec(), test index to
+ * prevent extending past the edge.
+ * For BKGD targets, omit flux
+ * comparison when deciding which
+ * regions to use.
+ * Delete index to the file
+ * extensions from the primary HDU.
+ * Compute mean flux over same
+ * wavelength region for each band.
+ * 05/24/2006 wvd v1.16 For PC targets, don't include
+ * O VI in calculation of mean flux
+ * 12/19/2006 wvd v1.17 Reject segments with
+ * OBSTIME < 10 seconds when full
+ * exposure is longer than 100 s.
+ * 02/19/2008 bot v1.18 Fixed indexing problem in
+ * copy_spec due to shift and n_copy
+ *
+ ******************************************************************************/
+
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "calfuse.h"
+
+#define MAXSHIFT 30
+#define N_SHIFT 61
+#define NVO_MIN 900
+#define NVO_MAX 1190
+
+static char CF_PRGM_ID[] = "cf_nvo";
+static char CF_VER_NUM[] = "1.18";
+
+static int
+compute_shift(fitsfile *pt_fits, int hdu_ref, int hdu, float wmin, float wdelta,
+ float wpc, int *shift, int *quality)
+{
+ char comb[FLEN_VALUE], ref_comb[FLEN_VALUE];
+ int hdutype, status = 0;
+ int ind_chi2_min, nchi;
+ long i, k, n_rows, ref_start, start, n_pix;
+ float *error, *flux, *wave, *ref_error, *ref_flux, *ref_wave;
+ float chi_square[N_SHIFT], chi_square_min, chi_square_max;
+ float ref_obstime, obstime;
+ double scale, sum, var1, var2;
+
+ /* Don't need to shift reference spectrum. */
+ if (hdu_ref == hdu) {
+ *shift = 0;
+ *quality = TRUE;
+ return(0);
+ }
+
+ /* Read data for reference and data channels. */
+ FITS_movabs_hdu(pt_fits, hdu_ref, &hdutype, &status);
+ FITS_read_key(pt_fits, TSTRING, "COMBMETH", &ref_comb, NULL, &status);
+ FITS_read_key(pt_fits, TFLOAT, "OBSTIME", &ref_obstime, NULL, &status);
+ n_rows = cf_read_col(pt_fits, TFLOAT, "WAVE", (void **) &ref_wave);
+ n_rows = cf_read_col(pt_fits, TFLOAT, "FLUX", (void **) &ref_flux);
+ n_rows = cf_read_col(pt_fits, TFLOAT, "ERROR", (void **) &ref_error);
+
+ FITS_movabs_hdu(pt_fits, hdu, &hdutype, &status);
+ FITS_read_key(pt_fits, TSTRING, "COMBMETH", &comb, NULL, &status);
+ FITS_read_key(pt_fits, TFLOAT, "OBSTIME", &obstime, NULL, &status);
+ n_rows = cf_read_col(pt_fits, TFLOAT, "WAVE", (void **) &wave);
+ n_rows = cf_read_col(pt_fits, TFLOAT, "FLUX", (void **) &flux);
+ n_rows = cf_read_col(pt_fits, TFLOAT, "ERROR", (void **) &error);
+
+ /* If either channel was not constructed using cross-correlation,
+ * return a shift of 0. */
+ if (strncmp(ref_comb,"X",1) || strncmp(comb,"X",1)) {
+ *shift = 0;
+ *quality = FALSE;
+ printf("hdu = %d, hdu_ref = %d, COMBMETH != XCORR\n",
+ hdu, hdu_ref);
+ return(0);
+ }
+
+ /* If either channel has OBSTIME = 0, return a shift of 0. */
+ if (ref_obstime < 1 || obstime < 1) {
+ *shift = 0;
+ *quality = FALSE;
+ if (ref_obstime < 1)
+ printf("hdu_ref = %d, OBSTIME = %f\n", hdu_ref, ref_obstime);
+ if (obstime < 1) printf("hdu = %d, OBSTIME = %f\n", hdu, obstime);
+ return(0);
+ }
+
+ /* Compute chi-squared for shifts between +/- MAXSHIFT pixels. */
+ ref_start = cf_nlong((wmin - ref_wave[0]) / wpc) + MAXSHIFT;
+ start = cf_nlong((wmin - wave[0]) / wpc);
+ n_pix = cf_nlong(wdelta / wpc) - (N_SHIFT - 1);
+
+ for (k = 0; k < N_SHIFT; k++) {
+ nchi = 0;
+ sum = 0;
+ for (i = 0; i < n_pix; i++) {
+ var1 = ref_error[ref_start + i] * ref_error[ref_start + i];
+ var2 = error[start + i + k] * error[start + i + k];
+ if ((var1 + var2) > 0.) {
+ sum += (ref_flux[ref_start + i] - flux[start + i + k]) *
+ (ref_flux[ref_start + i] - flux[start + i + k]) /
+ (var1 + var2);
+ nchi++;
+ }
+ }
+ scale = (double) nchi / n_pix;
+ chi_square[k] = sum / scale;
+ }
+
+ /* If chi-squared changes by less than 20% over range of shifts, abort.
+ * Otherwise, return shift corresponding to lowest value of chi-square.
+ */
+ ind_chi2_min = 0;
+ chi_square_min = 1E5;
+ chi_square_max = -1E5;
+ for (k = 0; k < N_SHIFT; k++) {
+ if (chi_square[k] < chi_square_min)
+ {
+ chi_square_min = chi_square[k];
+ ind_chi2_min = k;
+ }
+ else if (chi_square[k] > chi_square_max)
+ chi_square_max = chi_square[k];
+ }
+
+ if (chi_square_max / chi_square_min < 1.2) {
+ *shift = 0;
+ *quality = FALSE;
+ printf("hdu = %d, hdu_ref = %d. Chi-square dist is flat.\n",
+ hdu, hdu_ref);
+ }
+ else {
+ *shift = ind_chi2_min - MAXSHIFT;
+ *quality = TRUE;
+ }
+
+ free(ref_error);
+ free(ref_flux);
+ free(ref_wave);
+ free(error);
+ free(flux);
+ free(wave);
+
+ return(0);
+}
+
+
+static int
+copy_spec(fitsfile *pt_fits, int hdu, float w_min, float w_max, float wpc,
+ int shift, float *flux_nvo, float *error_nvo, long n_nvo)
+{
+ int hdutype, status = 0;
+ long i, i0, n_rows, nvo_start, start, n_copy, n_copy0;
+ float *error, *flux, w0;
+
+ FITS_movabs_hdu(pt_fits, hdu, &hdutype, &status);
+ FITS_read_key(pt_fits, TFLOAT, "W0", &w0, NULL, &status);
+ n_rows = cf_read_col(pt_fits, TFLOAT, "FLUX", (void **) &flux);
+ n_rows = cf_read_col(pt_fits, TFLOAT, "ERROR", (void **) &error);
+
+ nvo_start = cf_nlong(((double) w_min - NVO_MIN) / wpc);
+ start = cf_nlong(((double) w_min - w0) / wpc);
+ n_copy = cf_nlong(((double) w_max - w_min) / wpc) + 1;
+ if (nvo_start + n_copy > n_nvo) {
+ printf ("HDU = %d, w_min = %.1f, w_max = %.1f, wpc = %5.3f\n",
+ hdu, w_min, w_max, wpc);
+ printf ("n_nvo = %ld, nvo_start = %ld, start = %ld, n_copy = %ld\n",
+ n_nvo, nvo_start, start, n_copy);
+ cf_if_error("Can't create NVO array.");
+ }
+
+ n_copy0 = n_copy;
+ if (start + shift + n_copy > n_rows) {
+ n_copy = n_rows - (start + shift);
+ if (hdu == 3) for (i = n_copy; i < n_copy0; i++) {
+ flux_nvo[i+nvo_start] = 0.0;
+ error_nvo[i+nvo_start] = 0.0;
+ }
+ }
+
+ i0 = 0;
+ if (start + shift < 0) {
+ i0 = -(start + shift);
+ for (i = 0; i < i0; i++) {
+ flux_nvo[i+nvo_start] = 0.0;
+ error_nvo[i+nvo_start] = 0.0;
+ }
+ }
+
+ for (i = i0; i < n_copy; i++) {
+ flux_nvo[i+nvo_start] = flux[i+start+shift];
+ error_nvo[i+nvo_start] = error[i+start+shift];
+ }
+
+ free(error);
+ free(flux);
+ return(0);
+}
+
+
+int main(int argc, char *argv[])
+{
+ /* Variables */
+ char program[FLEN_VALUE];
+ double mean_flux[8], sum_flux;
+ float *wave, *flux, w0, wpc, hdu_wpc;
+ float *wave_nvo, *flux_nvo, *error_nvo;
+ float max_obstime, wmin, wdelta;
+ long n_rows, n_nvo;
+ int ref, i, nextend=1, n_hdus, shift[8], quality[8];
+ int bkgd_obs=FALSE, objclass;
+ int nkeys, morekeys=0;
+ long k, n_elem;
+
+ char *ttype[] = { "WAVE", "FLUX", "ERROR" };
+ char *tform[] = { "1E", "1E", "1E" };
+ char *tunit[] = { "ANGSTROMS", "ERG/CM2/S/A", "ERG/CM2/S/A" };
+
+ /* HDU numbers must be consistent with output of cf_pack. */
+ char *extname[] = { "1ASIC", "2BSIC", "1ALIF", "2BLIF", "1BSIC", "2ASIC", "1BLIF", "2ALIF" };
+ int hdu[] = { 6, 8, 2, 4, 7, 9, 3 , 5 };
+ float w_min[] = { 997, 1010, 990, 990, 904, 917.5, 1094 , 1090 };
+ float w_max[] = { 1090, 1104, 1080, 1074, 992, 998, 1190 , 1180 };
+
+ /* Regions to use when computing mean flux. */
+ float *region;
+ float region_array[8][6] = {
+ {0, 0, 1030, 1039, 1045, 1070}, /* 1ASIC */
+ {0, 0, 1030, 1039, 1045, 1070}, /* 2BSIC */
+ {0, 0, 1030, 1039, 1045, 1070}, /* 1ALIF */
+ {0, 0, 1030, 1039, 1045, 1070}, /* 2BLIF */
+ {912, 935, 955, 970, 980, 985}, /* 1BSIC */
+ {912, 935, 955, 970, 980, 985}, /* 2ASIC */
+ {1095, 1130, 1140, 1165, 1170, 1180}, /* 1BLIF */
+ {1095, 1130, 1140, 1165, 1170, 1180} /* 2ALIF */
+ };
+
+ char in_name[80], out_name[80];
+ char extname_key[80], src_type[FLEN_VALUE], sp_type[FLEN_VALUE], fescent[FLEN_VALUE];
+ fitsfile *pt_fits, *pt_fits_out;
+ int status = 0, hdutype;
+
+
+ /***********************************
+ ** Enter a timestamp into the log **
+ ***********************************/
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Begin Processing");
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+
+ /***********************************************************
+ ** Check for proper command-line usage and read arguments **
+ ***********************************************************/
+ if (argc != 3)
+ cf_if_error("Usage: cf_nvo all_segments.fit nvo_file.fit");
+
+ strcpy(in_name, argv[1]);
+ strcpy(out_name, "!");
+ strcat(out_name, argv[2]); /* Force overwrite */
+
+ /*******************************************
+ ** Open input file, read header keywords. **
+ *******************************************/
+ FITS_open_file(&pt_fits, in_name, READONLY, &status);
+ FITS_read_key(pt_fits, TSTRING, "PRGRM_ID", &program, NULL, &status);
+ FITS_read_key(pt_fits, TINT, "OBJCLASS", &objclass, NULL, &status);
+ FITS_read_key(pt_fits, TSTRING, "SP_TYPE", &sp_type, NULL, &status);
+ FITS_read_key(pt_fits, TSTRING, "SRC_TYPE", &src_type, NULL, &status);
+ FITS_read_key(pt_fits, TFLOAT, "OBSTIME", &max_obstime, NULL, &status);
+ FITS_read_key(pt_fits, TFLOAT, "WPC", &wpc, NULL, &status);
+ FITS_read_key(pt_fits, TSTRING, "FESCENT", &fescent, NULL, &status);
+ ref = 2; /* LiF 1A */
+ if (!strncmp(fescent, "FES B", 5)) ref = 3; /* LiF 2B */
+
+ /****************************************************************
+ ** If SRC_TYPE = PC, exclude O VI in calculation of mean flux. **
+ ****************************************************************/
+ if (!strncmp(src_type, "PC", 2))
+ for (i = 0; i < 4; i++)
+ region_array[i][2] = region_array[i][3] = 0;
+
+ /***************************************
+ ** Compute mean flux in each channel. **
+ ***************************************/
+ FITS_get_num_hdus(pt_fits, &n_hdus, &status);
+ if (n_hdus != 9)
+ cf_if_error("Input file must have 9 extensions (%d found)", n_hdus);
+
+ for (i = 0; i < 8; i++) {
+ float obstime;
+ FITS_movabs_hdu(pt_fits, hdu[i], &hdutype, &status);
+ FITS_read_key(pt_fits, TSTRING, "EXTNAME", extname_key, NULL, &status);
+ if (strcmp(extname_key, extname[i]))
+ cf_if_error("Extension %d's name does not match (%s)",
+ hdu[i], extname[i]);
+ FITS_read_key(pt_fits, TFLOAT, "WPC", &hdu_wpc, NULL, &status);
+ if (hdu_wpc != wpc)
+ cf_if_error("Extension %d's WPC does not match primary HDU",
+ hdu[i]);
+ FITS_read_key(pt_fits, TFLOAT, "OBSTIME", &obstime, NULL, &status);
+ if (obstime < 1. || (obstime < 10 && max_obstime > 100))
+ mean_flux[i] = -1;
+ else {
+ n_rows = cf_read_col(pt_fits, TFLOAT, "WAVE", (void **) &wave);
+ n_rows = cf_read_col(pt_fits, TFLOAT, "FLUX", (void **) &flux);
+
+ sum_flux = n_elem = 0;
+ region = region_array[i];
+ for (k = 0; k < n_rows; k++)
+ {
+ if ((wave[k] > region[0] && wave[k] < region[1]) ||
+ (wave[k] > region[2] && wave[k] < region[3]) ||
+ (wave[k] > region[4] && wave[k] < region[5])) {
+ sum_flux += flux[k];
+ n_elem ++;
+ }
+ }
+
+ mean_flux[i] = sum_flux / n_elem;
+ free(wave);
+ free(flux);
+ }
+
+ printf("%s\tmean_flux = %g\n", extname_key, mean_flux[i]);
+ }
+
+ /*******************************************************************
+ * If FESCENT = FES A, compute shifts relative to LiF 1A.
+ * If FESCENT = FES B, use LiF 2B.
+ * For background targets, compare Lyman beta lines.
+ * For other emission-line targets, compare O VI lines.
+ * For white dwarfs, use O VI and C II.
+ * For other continuum sources, use the region between 1045 and 1070 A
+ * for the four 1000-1100 A channels.
+ ******************************************************************/
+
+ if (src_type[1] == 'E') { /* Emission-line source */
+ /* Use Lyman beta to align background observations. */
+ if (objclass == 7 || (program[0] == 'S' && program[2] == '0' && program[3] == '5')) {
+ printf("Assuming background observation.\n");
+ wmin = 1024.;
+ wdelta = 6.;
+ } else { /* Use O VI emission for everything else. */
+ printf("SRC_TYPE = %s. Emission-line target.\n", src_type);
+ wmin = 1030.;
+ wdelta = 9.;
+ }
+ }
+ /* Continuum source */
+ else if (objclass == 17 || objclass == 29 || objclass == 37) {
+ /* Use O VI and C II to align white dwarf spectra. */
+ printf("OBJCLASS = %d. Assuming nearby white dwarf.\n", objclass);
+ wmin = 1030.;
+ wdelta = 9.;
+ }
+ else { /* Use 1045-1070 A region for all other continuum sources. */
+ printf("SRC_TYPE = %s. Continuum target.\n", src_type);
+ wmin = 1045.;
+ wdelta = 25.;
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (mean_flux[i] > -1)
+ compute_shift(pt_fits, hdu[ref], hdu[i], wmin, wdelta, wpc, shift+i, quality+i);
+ else
+ shift[i] = 0;
+ shift[i+4] = shift[i];
+ printf("hdu = %d, hdu_ref = %d, shift = %d\n", hdu[i], hdu[ref], shift[i]);
+ }
+
+ /**************************
+ ** Set up output arrays. **
+ **************************/
+ n_nvo = cf_nlong((double) (NVO_MAX - NVO_MIN) / wpc) + 1;
+ wave_nvo = (float *) cf_calloc(n_nvo, sizeof(float));
+ for (i = 0; i < n_nvo; i++) wave_nvo[i] = NVO_MIN + (double) wpc * i;
+ flux_nvo = (float *) cf_calloc(n_nvo, sizeof(float));
+ error_nvo = (float *) cf_calloc(n_nvo, sizeof(float));
+
+ for (i = 0; i < n_nvo; i++) {
+ flux_nvo[i] = 0.0;
+ error_nvo[i] = 0.0;
+ }
+
+ /**************************************************************
+ ** In each wave band, copy best data set into output arrays. **
+ **************************************************************/
+ /* For BKGD targets, omit flux comparison when selecting which
+ regions to use. */
+ if (objclass == 7 || !strncmp(sp_type, "BKGD", 4)) bkgd_obs = TRUE;
+
+ /* First fill in the 1010-1104 A region with SiC 2B. */
+ copy_spec(pt_fits, hdu[1], w_min[1], w_max[1], wpc, shift[1], flux_nvo, error_nvo, n_nvo);
+
+ /* Replace with SiC 1A if possible. It has a higher S/N, but extends only to 1090 A. */
+ if ((bkgd_obs && mean_flux[0] > -1) || (mean_flux[0] > 0.9 * mean_flux[1]))
+ copy_spec(pt_fits, hdu[0], w_min[0], w_max[0], wpc, shift[0], flux_nvo, error_nvo, n_nvo);
+
+ /* Next overlay the region between 990 and 1080 A with LiF 1A or LiF 2B, if available. */
+ if ((bkgd_obs && mean_flux[2] > -1) || ((mean_flux[2] > 0.9 * mean_flux[3]) &&
+ (mean_flux[2] > 0.7 * mean_flux[0]) && (mean_flux[2] > 0.7 * mean_flux[1])))
+ copy_spec(pt_fits, hdu[2], w_min[2], w_max[2], wpc, shift[2], flux_nvo, error_nvo, n_nvo);
+ else if ((bkgd_obs && mean_flux[3] > -1) ||
+ ((mean_flux[3] > 0.7 * mean_flux[0]) && (mean_flux[3] > 0.7 * mean_flux[1])))
+ copy_spec(pt_fits, hdu[3], w_min[3], w_max[3], wpc, shift[3], flux_nvo, error_nvo, n_nvo);
+ else
+ w_max[5] = 1010, w_min[6] = w_min[7] = 1104;
+ /* If no LiF data, adopt limits of SiC spectra. */
+
+ /* Use SiC 1B to populate the shortest wavelengths. */
+ copy_spec(pt_fits, hdu[4], w_min[4], w_max[4], wpc, shift[4], flux_nvo, error_nvo, n_nvo);
+
+ /* If SiC 2A is good, use it for the main part of 900 - 1000 A. */
+ if ((bkgd_obs && mean_flux[5] > -1) || (mean_flux[5] > 0.9 * mean_flux[4]))
+ copy_spec(pt_fits, hdu[5], w_min[5], w_max[5], wpc, shift[5], flux_nvo, error_nvo, n_nvo);
+
+ /* Use LiF 1B to populate the longest wavelengths. */
+ copy_spec(pt_fits, hdu[6], w_min[6], w_max[6], wpc, shift[6], flux_nvo, error_nvo, n_nvo);
+
+ /* If LiF 2A is good, use it for the main part of 1100 - 1180 A. */
+ if ((bkgd_obs && mean_flux[7] > -1) || (mean_flux[7] > 0.9 * mean_flux[6]))
+ copy_spec(pt_fits, hdu[7], w_min[7], w_max[7], wpc, shift[7], flux_nvo, error_nvo, n_nvo);
+
+
+ for (i = 0; i < n_nvo; i++) {
+ if (flux_nvo[i] >= 1 || error_nvo[i] >= 1) cf_if_error("Bad values in NVO array.");
+ }
+
+ /*********************
+ ** Create NVO file. **
+ *********************/
+ FITS_create_file(&pt_fits_out, out_name, &status);
+ FITS_movabs_hdu(pt_fits, 1, &hdutype, &status);
+ FITS_copy_header(pt_fits, pt_fits_out, &status);
+ FITS_update_key(pt_fits_out, TINT, "NEXTEND", &nextend, NULL, &status);
+ FITS_update_key(pt_fits_out, TSTRING, "FILENAME", (out_name + 1), NULL, &status);
+ FITS_update_key(pt_fits_out, TSTRING, "FILETYPE", "NVO SPECTRUM", NULL, &status);
+ w0 = NVO_MIN;
+ FITS_update_key(pt_fits_out, TFLOAT, "W0", &w0, NULL, &status);
+
+ /* Delete index to file extensions from the primary HDU. */
+ fits_get_hdrspace(pt_fits_out, &nkeys, &morekeys, &status);
+ for (i = nkeys; i > nkeys-12; i--) fits_delete_record(pt_fits_out, i, &status);
+
+ FITS_create_tbl(pt_fits_out, BINARY_TBL, n_nvo, 3, ttype, tform, tunit, "FUSE_SPECTRUM", &status);
+ FITS_write_col(pt_fits_out, TFLOAT, 1, 1L, 1L, n_nvo, wave_nvo, &status);
+ FITS_write_col(pt_fits_out, TFLOAT, 2, 1L, 1L, n_nvo, flux_nvo, &status);
+ FITS_write_col(pt_fits_out, TFLOAT, 3, 1L, 1L, n_nvo, error_nvo, &status);
+
+ free(wave_nvo);
+ free(flux_nvo);
+ free(error_nvo);
+
+ FITS_close_file(pt_fits_out, &status);
+ FITS_close_file(pt_fits, &status);
+
+ return(0);
+}
diff --git a/src/analysis/cf_pack.c b/src/analysis/cf_pack.c
new file mode 100644
index 0000000..a823c22
--- /dev/null
+++ b/src/analysis/cf_pack.c
@@ -0,0 +1,270 @@
+/*******************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *******************************************************************************
+ *
+ * Usage: cf_pack combined_exposure_list out_file_name.fit
+ *
+ * Description: Write the 8 segments (1alif, 1blif etc...) into a single fits
+ * file with 8 extensions (in addition to the primary array).
+ *
+ * History: 04/08/05 tc v1.0 First release
+ * 05/02/05 wvd v1.1 Copy SPEC and WOFF keywords to
+ * output file.
+ * 06/03/05 wvd v1.2 Delete unused variables.
+ * 06/29/05 wvd v1.3 Set keyword COMB_COR = COMPLETE.
+ * 09/30/05 wvd v1.4 Update archive search keywords.
+ * 03/23/06 wvd v1.5 If a segment is missing, write
+ * an empty image extension.
+ * 05/19/06 wvd v1.6 Write an index to the file
+ * extensions to the primary HDU.
+ * 05/24/06 wvd v1.7 Remove SPEC* keywords from
+ * primary HDU.
+ * 05/29/06 wvd v1.8 Use while construction to
+ * delete WOFF* keywords.
+ * 06/22/06 wvd v1.9 Truncate APER_ACT from (for
+ * example) MDRS_LIF to MDRS.
+ * 08/14/06 wvd v1.10 Tinker with code to copy SPEC
+ * keywords to new file header.
+ * 04/07/07 wvd v1.11 Clean up compiler warnings.
+ * 08/27/07 bot v1.12 Changed TINT to TLONG l.163,214,
+ * and 215 ; added L to every number
+ * occurence related to i and j ;
+ * Changed i to k l.123 to 131 to
+ * keep an int in this case
+ *
+ ******************************************************************************/
+
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "calfuse.h"
+
+/* Calfuse variables */
+static char CF_PRGM_ID[] = "cf_pack";
+static char CF_VER_NUM[] = "1.12";
+
+int main(int argc, char *argv[])
+{
+ /* Variables */
+ float obstime, obstime_max, woffset;
+ float w0, wpc;
+ int wave_cnum, flux_cnum, error_cnum;
+ int n_spec, n_best_spec;
+ long i, j, num_exp, n_rows;
+ int k;
+
+ char *ttype[] = { "WAVE", "FLUX", "ERROR" };
+ char *tform[] = { "1E", "1E", "1E" };
+ char *tunit[] = { "ANGSTROMS", "ERG/CM2/S/A", "ERG/CM2/S/A" };
+ char *extname[] = { "1ALIF", "1BLIF", "2BLIF", "2ALIF", "1ASIC", "1BSIC", "2BSIC", "2ASIC" };
+ char spec_list[][80] = { "NULL", "NULL", "NULL", "NULL", "NULL", "NULL", "NULL", "NULL" };
+
+ /* New values for archive search keywords */
+ float bandwid = 285.;
+ float centrwv = 1046.;
+ float wavemin = 904.;
+ float wavemax = 1189.;
+
+ FILE *pt_file;
+ char comment[FLEN_COMMENT], spec_lis[80], out_name[80], spec_name[80];
+ char aper_act[80], detector[80], segment[80];
+ char err_str[80], aper_key[8], combmeth_key[9];
+ char keyname[FLEN_KEYWORD], keyvalue[FLEN_VALUE];
+ fitsfile *pt_fits, *pt_fits_out;
+ int status = 0, hdutype = 0;
+ int nextend_key = 8;
+ float obstime_key = 0;
+
+
+ /***********************************
+ ** Enter a timestamp into the log **
+ ***********************************/
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Begin Processing");
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+
+ /***********************************************************
+ ** Check for proper command-line usage and read arguments **
+ ***********************************************************/
+ if (argc != 3)
+ cf_if_error("Usage: cf_pack combined_exposure_list out_file_name.fit\n");
+
+ strcpy(spec_lis, argv[1]);
+ strcpy(out_name, "!");
+ strcat(out_name, argv[2]); /* Force overwrite */
+
+ /********************
+ ** Open input list **
+ ********************/
+ if ((pt_file = fopen(spec_lis, "r")) == NULL)
+ {
+ sprintf(err_str, "Unable to open file %s\n", spec_lis);
+ cf_if_error(err_str);
+ }
+
+ /* ***********************************************
+ ** Determine which spectrum has maximum OBSTIME **
+ ** Write input file list to spec_list array. **
+ *************************************************/
+ n_best_spec = -1;
+ n_spec = 0;
+ obstime_max = -1;
+
+ while (fscanf(pt_file, "%80s", spec_name) != EOF)
+ {
+ FITS_open_file(&pt_fits, spec_name, READONLY, &status);
+ FITS_read_key(pt_fits, TFLOAT, "OBSTIME" , &obstime, NULL, &status);
+ FITS_read_key(pt_fits, TSTRING, "DETECTOR" , &detector, NULL, &status);
+ FITS_read_key(pt_fits, TSTRING, "APER_ACT" , &aper_act, NULL, &status);
+ FITS_close_file(pt_fits, &status);
+
+ sprintf(segment, "%2s%3s", detector, aper_act+5);
+ for (k=0; k<8; k++)
+ if (!strcmp(segment, extname[k])) {
+ strcpy(spec_list[k], spec_name);
+ break;
+ }
+ if (obstime_max < obstime) {
+ n_best_spec = k;
+ obstime_max = obstime;
+ }
+ n_spec++;
+ }
+ fclose(pt_file);
+ if (n_spec == 0) cf_if_error("No valid segments provided");
+ if (n_spec != 8) cf_if_warning("Combining fewer than 8 segments");
+
+ /* ***************************************************
+ ** Copy header of reference spectrum to output file **
+ ** Update a few header keywords. **
+ *****************************************************/
+
+ FITS_open_file(&pt_fits, spec_list[n_best_spec], READONLY, &status);
+ FITS_create_file(&pt_fits_out, out_name, &status);
+ FITS_copy_header(pt_fits, pt_fits_out, &status);
+ FITS_close_file(pt_fits, &status);
+
+ FITS_update_key(pt_fits_out, TSTRING, "FILENAME", (out_name + 1), NULL, &status);
+ FITS_update_key(pt_fits_out, TSTRING, "DETECTOR", "ALL", NULL, &status);
+ FITS_update_key(pt_fits_out, TSTRING, "COMB_COR", "COMPLETE", NULL, &status);
+
+ sprintf(aper_key, "%4s", aper_act);
+ FITS_update_key(pt_fits_out, TSTRING, "APER_ACT", aper_key, NULL, &status);
+ FITS_update_key(pt_fits_out, TINT, "NEXTEND", &nextend_key, NULL, &status);
+
+ FITS_update_key(pt_fits_out, TFLOAT, "BANDWID", &bandwid, NULL, &status);
+ FITS_update_key(pt_fits_out, TFLOAT, "CENTRWV", &centrwv, NULL, &status);
+ FITS_update_key(pt_fits_out, TFLOAT, "WAVEMIN", &wavemin, NULL, &status);
+ FITS_update_key(pt_fits_out, TFLOAT, "WAVEMAX", &wavemax, NULL, &status);
+
+ FITS_read_key(pt_fits_out, TLONG, "NSPEC", &num_exp, NULL, &status);
+ FITS_delete_key(pt_fits_out, "NSPEC", &status);
+ for (i = 0L; i < num_exp; i++) {
+ sprintf(keyname, "SPEC%03ld", i+1L);
+ FITS_delete_key(pt_fits_out, keyname, &status);
+ sprintf(keyname, "WOFF*%03ld", i+1L);
+ FITS_delete_key(pt_fits_out, keyname, &status);
+ fits_delete_key(pt_fits_out, keyname, &status);
+ if (status != 0) status = 0;
+ }
+
+
+ /* ***************************************************
+ ** Step through detector segments.
+ ** Copy spectra into extensions of output file.
+ *****************************************************/
+ for (i = 0L; i < 8L; i++) {
+
+ if (!strncmp(spec_list[i], "NULL", 4)) {
+ n_rows = 0L;
+ FITS_create_tbl(pt_fits_out, BINARY_TBL, n_rows, 3, ttype, tform,
+ tunit, extname[i], &status);
+ FITS_write_comment(pt_fits_out, "Extension is empty. No data available.", &status);
+ }
+ else {
+ FITS_open_file(&pt_fits, spec_list[i], READONLY, &status);
+
+ FITS_movabs_hdu(pt_fits, 2, &hdutype, &status);
+ FITS_get_colnum(pt_fits, TRUE, "WAVE", &wave_cnum, &status);
+ FITS_get_colnum(pt_fits, TRUE, "FLUX", &flux_cnum, &status);
+ FITS_get_colnum(pt_fits, TRUE, "ERROR", &error_cnum, &status);
+ FITS_get_num_rows(pt_fits, &n_rows, &status);
+
+ FITS_create_tbl(pt_fits_out, BINARY_TBL, n_rows, 3, ttype, tform,
+ tunit, extname[i], &status);
+
+ FITS_copy_col(pt_fits, pt_fits_out, wave_cnum, 1, FALSE, &status);
+ FITS_copy_col(pt_fits, pt_fits_out, flux_cnum, 2, FALSE, &status);
+ FITS_copy_col(pt_fits, pt_fits_out, error_cnum, 3, FALSE, &status);
+
+ /* Copy various header keywords */
+ FITS_read_key(pt_fits, TSTRING, "COMBMETH", combmeth_key, NULL, &status);
+ FITS_update_key(pt_fits_out, TSTRING, "COMBMETH", combmeth_key, NULL, &status);
+
+ FITS_movabs_hdu(pt_fits, 1, &hdutype, &status);
+ FITS_read_key(pt_fits, TFLOAT, "W0", &w0, NULL, &status);
+ FITS_update_key(pt_fits_out, TFLOAT, "W0", &w0, NULL, &status);
+ FITS_read_key(pt_fits, TFLOAT, "WPC", &wpc, NULL, &status);
+ FITS_update_key(pt_fits_out, TFLOAT, "WPC", &wpc, NULL, &status);
+ FITS_read_key(pt_fits, TFLOAT, "OBSTIME", &obstime_key, NULL, &status);
+ FITS_update_key(pt_fits_out, TFLOAT, "OBSTIME", &obstime_key, NULL, &status);
+ FITS_read_key(pt_fits, TLONG, "NSPEC", &num_exp, NULL, &status);
+ FITS_update_key(pt_fits_out, TLONG, "NSPEC", &num_exp, NULL, &status);
+
+ for (j = 0L; j < num_exp; j++) {
+ sprintf(keyname, "SPEC%03ld", j+1L);
+ FITS_read_key(pt_fits, TSTRING, keyname, keyvalue, NULL, &status);
+ FITS_update_key(pt_fits_out, TSTRING, keyname, keyvalue, NULL, &status);
+ sprintf(keyname, "WOFF%03ld", j+1L);
+ fits_read_key(pt_fits, TFLOAT, keyname, &woffset, comment, &status);
+ if (status) {
+ status = 0;
+ woffset = 0.;
+ sprintf(comment, "[A]");
+ }
+ FITS_update_key(pt_fits_out, TFLOAT, keyname, &woffset, comment, &status);
+ }
+ FITS_close_file(pt_fits, &status);
+ }
+ }
+ if (n_spec != 8) {
+ char datestr[FLEN_CARD];
+ int timeref;
+ FITS_movabs_hdu(pt_fits_out, 1, &hdutype, &status);
+ FITS_write_comment(pt_fits_out, " ", &status);
+ sprintf(comment, "Segments");
+ for (i=0L; i<8L; i++) if (!strncmp(spec_list[i], "NULL", 4))
+ sprintf(comment, "%s %s", comment, extname[i]);
+ sprintf(comment, "%s are missing.", comment);
+ FITS_write_comment(pt_fits_out, comment, &status);
+ sprintf(comment, "Extensions");
+ for (i=0L; i<8L; i++) if (!strncmp(spec_list[i], "NULL", 4))
+ sprintf(comment, "%s %ld", comment, i+1L);
+ sprintf(comment, "%s of this file contain no data.", comment);
+ FITS_write_comment(pt_fits_out, comment, &status);
+ fits_get_system_time(datestr, &timeref, &status);
+ sprintf(comment, "CalFUSE v%s %.10s", CALFUSE_VERSION, datestr);
+ FITS_write_comment(pt_fits_out, comment, &status);
+ FITS_write_comment(pt_fits_out, " ", &status);
+ }
+
+ /* Add an index to the file extensions. */
+ FITS_movabs_hdu(pt_fits_out, 1, &hdutype, &status);
+ FITS_write_comment(pt_fits_out, " ", &status);
+ sprintf(comment, "Index to file extensions:");
+ FITS_write_comment(pt_fits_out, comment, &status);
+ sprintf(comment, "Extension 0 This Header");
+ FITS_write_comment(pt_fits_out, comment, &status);
+ for (i=0L; i<8L; i++) {
+ sprintf(comment, "Extension %ld %s", i+1L, extname[i]);
+ FITS_write_comment(pt_fits_out, comment, &status);
+ }
+ FITS_write_comment(pt_fits_out, " ", &status);
+
+ FITS_close_file(pt_fits_out, &status);
+
+ return(0);
+}
diff --git a/src/analysis/cf_reflux.c b/src/analysis/cf_reflux.c
new file mode 100644
index 0000000..1a2511f
--- /dev/null
+++ b/src/analysis/cf_reflux.c
@@ -0,0 +1,148 @@
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *
+ * Synopsis: cf_reflux input_file output_file aeff_cal1 [aeff_cal2]
+ *
+ * Description: Program applies a new flux calibration to an extracted
+ * spectral file. If two effective-area files are given,
+ * program interpolates between them based on the MDJ
+ * of the exposure.
+ * Program writes a history line to output file header.
+ *
+ * Arguments: input_file FUSE extracted spectral file (fcal.fit)
+ * output_file Copy of input file with modified flux cal.
+ * aeff_cal1 Effective-area curve
+ * aeff_cal2 Optional effective-area curve, needed only
+ * if you wish to interpolate.
+ *
+ * Returns: none
+ *
+ * History: 06/02/05 1.1 wvd Based on programs cf_uninterp and
+ * cf_extract_spectra.
+ *
+ ****************************************************************************/
+
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "calfuse.h"
+
+static char CF_PRGM_ID[] = "cf_reflux";
+static char CF_VER_NUM[] = "1.1";
+
+int main(int argc, char *argv[])
+{
+ char aper_act[FLEN_VALUE], datestr[FLEN_VALUE];
+ int status=0, hdutype;
+ int aperture, timeref;
+ long i, frow=1, felement=1, nout;
+ float exptime, wpc;
+ float *wave, *flux, *error, *weights, *bkgd;
+ unsigned char *channel;
+ fitsfile *infits, *outfits;
+
+ /* Enter a timestamp into the log. */
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Begin Processing");
+
+ /* Initialize error checking */
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+ if (argc < 4) {
+ printf("Usage: cf_reflux input_file output_file aeff_cal1 [aeff_cal2]\n");
+ return 0;
+ }
+
+ /* Copy input spectral file to output. Close input file. */
+ FITS_open_file(&infits, argv[1], READONLY, &status);
+ FITS_create_file(&outfits, argv[2], &status);
+ FITS_copy_hdu(infits, outfits, 0, &status);
+ FITS_movrel_hdu(infits, 1, &hdutype, &status);
+ FITS_copy_hdu(infits, outfits, 0, &status);
+ FITS_close_file(infits, &status);
+
+ /* Modify output file keywords. */
+ FITS_movabs_hdu(outfits, 1, &hdutype, &status);
+ FITS_update_key(outfits, TSTRING, "FILENAME", argv[2], NULL, &status);
+ FITS_update_key(outfits, TSTRING, "AEFF1CAL", argv[3], NULL, &status);
+ if (argc == 5)
+ FITS_update_key(outfits, TSTRING, "AEFF2CAL", argv[4], NULL, &status);
+ else
+ FITS_update_key(outfits, TSTRING, "AEFF2CAL", argv[3], NULL, &status);
+
+ /* Add HISTORY lines to the output file */
+ fits_get_system_time(datestr, &timeref, &status);
+ strcat(datestr, " File recalibrated using cf_reflux");
+ FITS_write_history(outfits, datestr, &status);
+
+ /* Through which aperture was this spectrum obtained? */
+ FITS_read_key(outfits, TSTRING, "APER_ACT", aper_act, NULL, &status);
+ if (!strcmp(aper_act, "HIRS_LIF")) aperture = 1;
+ else if (!strcmp(aper_act, "MDRS_LIF")) aperture = 2;
+ else if (!strcmp(aper_act, "LWRS_LIF")) aperture = 3;
+ else if (!strcmp(aper_act, "HIRS_SIC")) aperture = 5;
+ else if (!strcmp(aper_act, "MDRS_SIC")) aperture = 6;
+ else if (!strcmp(aper_act, "LWRS_SIC")) aperture = 7;
+ else {
+ printf("Unable to interpret header keyword APER_ACT = %s\n", aper_act);
+ FITS_close_file(outfits, &status);
+ return 0;
+ }
+
+ /* Read WAVE, FLUX, ERROR, WEIGHTS, and BKGD arrays */
+ FITS_movabs_hdu(outfits, 2, &hdutype, &status);
+ nout = cf_read_col(outfits, TFLOAT, "WAVE", (void **) &wave);
+ nout = cf_read_col(outfits, TFLOAT, "FLUX", (void **) &flux);
+ nout = cf_read_col(outfits, TFLOAT, "ERROR", (void **) &error);
+ nout = cf_read_col(outfits, TFLOAT, "WEIGHTS", (void **) &weights);
+ nout = cf_read_col(outfits, TFLOAT, "BKGD", (void **) &bkgd);
+ channel = (unsigned char *) cf_malloc(sizeof(unsigned char) * nout);
+
+ /* Compute inputs to flux-calibration routine */
+ for (i = 0; i < nout; i++) {
+ channel[i] = (unsigned char) aperture;
+ if (flux[i] != 0.) error[i] /= flux[i]; /* Relative error */
+ flux[i] = weights[i] - bkgd[i]; /* Units are counts */
+ }
+
+ /* Apply flux calibration */
+ FITS_movabs_hdu(outfits, 1, &hdutype, &status);
+ FITS_update_key(outfits, TSTRING, "FLUX_COR", "PERFORM", NULL, &status) ;
+ cf_convert_to_ergs(outfits, nout, flux, flux, channel, wave);
+
+ /* Convert flux and error arrays to units of erg/cm2/s/A. */
+ FITS_movabs_hdu(outfits, 1, &hdutype, &status);
+ FITS_read_key(outfits, TFLOAT, "EXPTIME", &exptime, NULL, &status);
+ FITS_read_key(outfits, TFLOAT, "WPC", &wpc, NULL, &status);
+ if (exptime < 1) {
+ printf ("EXPTIME = %g. Exiting.\n", exptime);
+ FITS_close_file(outfits, &status);
+ return 0;
+ }
+ for (i = 0; i < nout; i++) {
+ flux[i] /= exptime * wpc;
+ error[i] *= flux[i];
+ }
+
+ /* Write new flux and error arrays to the output file. */
+ FITS_movabs_hdu(outfits, 2, &hdutype, &status);
+ FITS_write_col(outfits, TFLOAT, 2, frow, felement, nout, flux, &status);
+ FITS_write_col(outfits, TFLOAT, 3, frow, felement, nout, error, &status);
+
+ /* Close output file. */
+ FITS_close_file(outfits, &status);
+
+ /* Free memory. */
+ free(wave);
+ free(flux);
+ free(error);
+ free(weights);
+ free(bkgd);
+ free(channel);
+
+ /* Enter a timestamp into the log. */
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Done processing");
+ return 0;
+}
diff --git a/src/analysis/cf_ttag_to_hist.c b/src/analysis/cf_ttag_to_hist.c
new file mode 100644
index 0000000..070a1a6
--- /dev/null
+++ b/src/analysis/cf_ttag_to_hist.c
@@ -0,0 +1,463 @@
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: cf_ttag_to_hist input_file output_file
+ *
+ * Description: Creates a FITS 2D image from a time-tagged data file (FITS
+ * binary table of photon address data). The 2D SIA table is
+ * written to the first extension (HDU=1) and the other four
+ * extensions contain the two apertures and stim-lamp pulses.
+ *
+ *
+ * Arguments: input_file Input raw time-tagged FITS file name
+ * output_file Output raw histogram FITS file name
+ *
+ * Returns: none
+ *
+ * History: 03/28/00 1.01 peb Begin work
+ * 12/21/00 1.03 peb Fixed type mismatched in cfitsio
+ * calls
+ *
+ ****************************************************************************/
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "calfuse.h"
+
+#define STIMX 2048
+
+static char CF_PRGM_ID[] = "cf_ttag_to_hist";
+static char CF_VER_NUM[] = "1.03";
+
+int main(int argc, char *argv[])
+{
+ fitsfile *infits, *outfits;
+ char buffer[FLEN_CARD], *siabuf;
+ int status = 0, intnull, anynull, hdutype, fcol, begkey=5, endkey;
+ int j, k1, kx1, ky1, k2, kx2, ky2, k3, kx3, ky3, k4, kx4, ky4;
+ int naxis, naxis1, naxis2, naxis3, naxis4;
+ int *posx, *posy, npixel, fpixel=1, frow, felem, nrow;
+ int begx1, begy1, begx2, begy2, begx3, begy3, begx4, begy4;
+ int rcnt1, rcnt2, rcnt3, rcnt4, min1, min2, min3, min4;
+ int max1, max2, max3, max4, binx, biny;
+ int keynum, nextend=4, extver=0, bzero=32768, bscale=1;
+ short *outbuf1, *outbuf2, *outbuf3, *outbuf4;
+ long naxes[2], naxes1[2], naxes2[2], naxes3[2], naxes4[2];
+ float fzero=0.0;
+ double ra_targ, dec_targ, pa_aper, equinox;
+
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+ /*
+ * Open input ttag data file and create output file.
+ */
+ FITS_open_file(&infits, argv[1], READONLY, &status);
+ FITS_create_file(&outfits, argv[2], &status);
+ /*
+ * Create primary image header
+ */
+ naxis = 2; naxes[0] = 8; naxes[1] = 64;
+ FITS_create_img(outfits, BYTE_IMG, naxis, naxes, &status);
+ /*
+ * Copy header from primary HDU of the input file to the output file,
+ * but leave the primary HDU data array empty.
+ */
+ FITS_read_key(infits, TINT, "SPECBINX", &binx, buffer, &status);
+ FITS_read_key(infits, TINT, "SPECBINY", &biny, buffer, &status);
+ FITS_get_hdrpos(infits, &endkey, &keynum, &status);
+ for (j = begkey; j <= endkey; j++) {
+ FITS_read_record(infits, j, buffer, &status);
+ FITS_write_record(outfits, buffer, &status);
+ }
+ FITS_update_key(outfits, TINT, "NEXTEND", &nextend, NULL, &status);
+ FITS_update_key(outfits, TSTRING, "FILETYPE", "RAW HISTOGRAM",
+ NULL, &status);
+ FITS_update_key(outfits, TSTRING, "INSTMODE", "HIST", NULL, &status);
+ /*
+ * Populate primary data or SIA table.
+ */
+ npixel = naxes[0]*naxes[1];
+ siabuf = cf_malloc(npixel);
+ memset(siabuf, 1, npixel);
+ FITS_write_img(outfits, TBYTE, fpixel, npixel, siabuf, &status);
+ free(siabuf);
+ /*
+ * Move to the 1st HDU of the input file and read the binary table.
+ */
+ FITS_movabs_hdu(infits, 2, &hdutype, &status);
+ if(hdutype != BINARY_TBL) {
+ cf_if_error("Error: This HDU is not a binary table!");
+ }
+ FITS_read_key(infits, TINT, "NAXIS2", &nrow, buffer, &status);
+ FITS_read_key(infits, TDOUBLE, "RA_TARG", &ra_targ, buffer, &status);
+ FITS_read_key(infits, TDOUBLE, "DEC_TARG", &dec_targ, buffer, &status);
+ FITS_read_key(infits, TDOUBLE, "PA_APER", &pa_aper, buffer, &status);
+ FITS_read_key(infits, TDOUBLE, "EQUINOX", &equinox, buffer, &status);
+ /*
+ * Allocate memory for X, Y photon event arrays
+ */
+ posx = cf_malloc(sizeof(int) * nrow);
+ posy = cf_malloc(sizeof(int) * nrow);
+ /*
+ * Read X and Y from table
+ */
+ frow = felem = 1; intnull = anynull = 0;
+
+ FITS_get_colnum(infits, TRUE, "X", &fcol, &status);
+ FITS_read_col(infits, TINT, fcol, frow, felem, nrow, &intnull,
+ posx, &anynull, &status);
+ FITS_get_colnum(infits, TRUE, "Y", &fcol, &status);
+ FITS_read_col(infits, TINT, fcol, frow, felem, nrow, &intnull,
+ posy, &anynull, &status);
+ /*
+ * Create buffers (outbufn) to hold binned images, and
+ * initialize them.
+ */
+ naxis1 = 2; naxes1[0] = NXMAX; naxes1[1] = 20;
+ begx1 = 0; begy1 = 48; rcnt1 = 56; min1 = max1 = 0;
+ outbuf1 = cf_calloc(naxes1[0]*naxes1[1], sizeof(short));
+
+ naxis2 = 2; naxes2[0] = NXMAX; naxes2[1] = 20;
+ begx2 = 0; begy2 = 76; rcnt2 = 57; min2 = max2 = 0;
+ outbuf2 = cf_calloc(naxes2[0]*naxes2[1], sizeof(short));
+
+ naxis3 = 2; naxes3[0] = STIMX; naxes3[1] = 2;
+ begx3 = 0; begy3 = 76; rcnt3 = 1; min3 = max3 = 0;
+ outbuf3 = cf_calloc(naxes3[0]*naxes3[1], sizeof(short));
+
+ naxis4 = 2; naxes4[0] = STIMX; naxes4[1] = 2;
+ begx4 = 14336; begy4 = 78; rcnt4 = 1; min4 = max4 = 0;
+ outbuf4 = cf_calloc(naxes4[0]*naxes4[1], sizeof(short));
+
+ for(j = 0; j < nrow; j++) {
+ kx1 = posx[j]/binx-begx1;
+ ky1 = posy[j]/biny-begy1;
+ if (kx1 >= 0 && kx1 < naxes1[0] && ky1 >= 0 && ky1 < naxes1[1]) {
+ k1 = naxes1[0]*ky1 + kx1;
+ outbuf1[k1] += 1;
+ if (outbuf1[k1] < min1)
+ min1 = outbuf1[k1];
+ if (outbuf1[k1] > max1)
+ max1 = outbuf1[k1];
+ }
+ kx2 = posx[j]/binx-begx2;
+ ky2 = posy[j]/biny-begy2;
+ if (kx2 >= 0 && kx2 < naxes2[0] && ky2 >= 0 && ky2 < naxes2[1]) {
+ k2 = naxes2[0]*ky2 + kx2;
+ outbuf2[k2] += 1;
+ if (outbuf2[k2] < min2)
+ min2 = outbuf2[k2];
+ if (outbuf2[k2] > max2)
+ max2 = outbuf2[k2];
+ }
+ kx3 = posx[j]/binx-begx3;
+ ky3 = posy[j]/biny-begy3;
+ if (kx3 >= 0 && kx3 < naxes3[0] && ky3 >= 0 && ky3 < naxes3[1]) {
+ k3 = naxes3[0]*ky3 + kx3;
+ outbuf3[k3] += 1;
+ if (outbuf3[k3] < min3)
+ min3 = outbuf3[k3];
+ if (outbuf3[k3] > max3)
+ max3 = outbuf3[k3];
+ }
+ kx4 = posx[j]/binx-begx4;
+ ky4 = posy[j]/biny-begy4;
+ if (kx4 >= 0 && kx4 < naxes4[0] && ky4 >= 0 && ky4 < naxes4[1]) {
+ k4 = naxes4[0]*ky4 + kx4;
+ outbuf4[k4] += 1;
+ if (outbuf4[k4] < min4)
+ min4 = outbuf4[k4];
+ if (outbuf4[k4] > max4)
+ max4 = outbuf4[k4];
+ }
+ }
+ /*
+ * Extension 1
+ */
+ FITS_create_img(outfits, SHORT_IMG, naxis1, naxes1, &status);
+ extver = 1;
+
+ FITS_write_key(outfits, TSTRING, "EXTNAME", "HISTOGRAM",
+ "name of this extension", &status);
+ FITS_write_key(outfits, TINT, "EXTVER" , &extver,
+ "extension version number", &status);
+ FITS_write_key(outfits, TINT, "BZERO" , &bzero,
+ "image brightness offset", &status);
+ FITS_write_key(outfits, TINT, "BSCALE" , &bscale,
+ "image brightness scale", &status);
+
+ FITS_write_comment(outfits, " ", &status);
+ FITS_write_comment(outfits, " ", &status);
+ FITS_write_comment(outfits,
+ " World Coordinate System and Related Parameters",
+ &status);
+ FITS_write_comment(outfits, " ", &status);
+
+ FITS_write_key(outfits, TFLOAT, "CRPIX1", &fzero,
+ "x-coordinate of reference pixel", &status);
+ FITS_write_key(outfits, TFLOAT, "CRPIX2", &fzero,
+ "y-coordinate of reference pixel", &status);
+ FITS_write_key(outfits, TFLOAT, "CRVAL1", &fzero,
+ "first axis value at reference pixel", &status);
+ FITS_write_key(outfits, TFLOAT, "CRVAL2", &fzero,
+ "second axis value at reference pixel", &status);
+ FITS_write_key(outfits, TSTRING, "CTYPE1", "LAMBDA",
+ "the coordinate type for the first axis", &status);
+ FITS_write_key(outfits, TSTRING, "CYTPE2", "ANGLE",
+ "the coordinate type for the second axis", &status);
+ FITS_write_key(outfits, TFLOAT, "CD1_1", &fzero,
+ "partial of first axis coordinate w.r.t. x", &status);
+ FITS_write_key(outfits, TFLOAT, "CD1_2", &fzero,
+ "partial of first axis coordinate w.r.t. y", &status);
+ FITS_write_key(outfits, TFLOAT, "CD2_1", &fzero,
+ "partial of second axis coordinate w.r.t. x", &status);
+ FITS_write_key(outfits, TFLOAT, "CD2_2", &fzero,
+ "partial of second axis coordinate w.r.t. y", &status);
+ FITS_write_key(outfits, TDOUBLE, "RA_TARG", &ra_targ,
+ "RA of reference aperture center", &status);
+ FITS_write_key(outfits, TDOUBLE, "DEC_TARG", &dec_targ,
+ "Declination of reference aperture center", &status);
+ FITS_write_key(outfits, TDOUBLE, "PA_APER", &pa_aper,
+ "Position Angle of reference aperture center", &status);
+ FITS_write_key(outfits, TDOUBLE, "EQUINOX", &equinox,
+ "equinox of celestial coord. system", &status);
+
+ FITS_write_comment(outfits, " ", &status);
+ FITS_write_comment(outfits, " HISTOGRAM REGION PARAMETERS", &status);
+ FITS_write_comment(outfits, " ", &status);
+
+ FITS_write_key(outfits, TINT, "XORIGIN", &begx1,
+ "offset of this region in the x dimension", &status);
+ FITS_write_key(outfits, TINT, "YORIGIN", &begy1,
+ "offset of this region in the y dimension", &status);
+ FITS_write_key(outfits, TINT, "RCOUNT", &rcnt1,
+ "count of rectangles in this region", &status);
+ FITS_write_key(outfits, TINT, "MINVAL", &min1,
+ "minimum value within rectangles", &status);
+ FITS_write_key(outfits, TINT, "MAXVAL", &max1,
+ "maximum value within rectangles", &status);
+
+ FITS_write_img(outfits, TSHORT, fpixel, naxes1[0]*naxes1[1],
+ outbuf1, &status);
+ /*
+ * Extension 2
+ */
+ FITS_create_img(outfits, SHORT_IMG, naxis2, naxes2, &status);
+ extver = 2;
+
+ FITS_write_key(outfits, TSTRING, "EXTNAME", "HISTOGRAM",
+ "name of this extension", &status);
+ FITS_write_key(outfits, TINT, "EXTVER" , &extver,
+ "extension version number", &status);
+ FITS_write_key(outfits, TINT, "BZERO" , &bzero,
+ "image brightness offset", &status);
+ FITS_write_key(outfits, TINT, "BSCALE" , &bscale,
+ "image brightness scale", &status);
+
+ FITS_write_comment(outfits, " ", &status);
+ FITS_write_comment(outfits, " ", &status);
+ FITS_write_comment(outfits,
+ " World Coordinate System and Related Parameters",
+ &status);
+ FITS_write_comment(outfits, " ", &status);
+
+ FITS_write_key(outfits, TFLOAT, "CRPIX1", &fzero,
+ "x-coordinate of reference pixel", &status);
+ FITS_write_key(outfits, TFLOAT, "CRPIX2", &fzero,
+ "y-coordinate of reference pixel", &status);
+ FITS_write_key(outfits, TFLOAT, "CRVAL1", &fzero,
+ "first axis value at reference pixel", &status);
+ FITS_write_key(outfits, TFLOAT, "CRVAL2", &fzero,
+ "second axis value at reference pixel", &status);
+ FITS_write_key(outfits, TSTRING, "CTYPE1", "LAMBDA",
+ "the coordinate type for the first axis", &status);
+ FITS_write_key(outfits, TSTRING, "CYTPE2", "ANGLE",
+ "the coordinate type for the second axis", &status);
+ FITS_write_key(outfits, TFLOAT, "CD1_1", &fzero,
+ "partial of first axis coordinate w.r.t. x", &status);
+ FITS_write_key(outfits, TFLOAT, "CD1_2", &fzero,
+ "partial of first axis coordinate w.r.t. y", &status);
+ FITS_write_key(outfits, TFLOAT, "CD2_1", &fzero,
+ "partial of second axis coordinate w.r.t. x", &status);
+ FITS_write_key(outfits, TFLOAT, "CD2_2", &fzero,
+ "partial of second axis coordinate w.r.t. y", &status);
+ FITS_write_key(outfits, TDOUBLE, "RA_TARG", &ra_targ,
+ "RA of reference aperture center", &status);
+ FITS_write_key(outfits, TDOUBLE, "DEC_TARG", &dec_targ,
+ "Declination of reference aperture center", &status);
+ FITS_write_key(outfits, TDOUBLE, "PA_APER", &pa_aper,
+ "Position Angle of reference aperture center", &status);
+ FITS_write_key(outfits, TDOUBLE, "EQUINOX", &equinox,
+ "equinox of celestial coord. system", &status);
+
+ FITS_write_comment(outfits, " ", &status);
+ FITS_write_comment(outfits, " HISTOGRAM REGION PARAMETERS", &status);
+ FITS_write_comment(outfits, " ", &status);
+
+ FITS_write_key(outfits, TINT, "XORIGIN", &begx2,
+ "offset of this region in the x dimension", &status);
+ FITS_write_key(outfits, TINT, "YORIGIN", &begy2,
+ "offset of this region in the y dimension", &status);
+ FITS_write_key(outfits, TINT, "RCOUNT", &rcnt2,
+ "count of rectangles in this region", &status);
+ FITS_write_key(outfits, TINT, "MINVAL", &min2,
+ "minimum value within rectangles", &status);
+ FITS_write_key(outfits, TINT, "MAXVAL", &max2,
+ "maximum value within rectangles", &status);
+
+ FITS_write_img(outfits, TSHORT, fpixel, naxes2[0]*naxes2[1],
+ outbuf2, &status);
+ /*
+ * Extension 3
+ */
+ FITS_create_img(outfits, SHORT_IMG, naxis3, naxes3, &status);
+ extver = 3;
+
+ FITS_write_key(outfits, TSTRING, "EXTNAME", "HISTOGRAM",
+ "name of this extension", &status);
+ FITS_write_key(outfits, TINT, "EXTVER" , &extver,
+ "extension version number", &status);
+ FITS_write_key(outfits, TINT, "BZERO" , &bzero,
+ "image brightness offset", &status);
+ FITS_write_key(outfits, TINT, "BSCALE" , &bscale,
+ "image brightness scale", &status);
+
+ FITS_write_comment(outfits, " ", &status);
+ FITS_write_comment(outfits, " ", &status);
+ FITS_write_comment(outfits,
+ " World Coordinate System and Related Parameters",
+ &status);
+ FITS_write_comment(outfits, " ", &status);
+
+ FITS_write_key(outfits, TFLOAT, "CRPIX1", &fzero,
+ "x-coordinate of reference pixel", &status);
+ FITS_write_key(outfits, TFLOAT, "CRPIX2", &fzero,
+ "y-coordinate of reference pixel", &status);
+ FITS_write_key(outfits, TFLOAT, "CRVAL1", &fzero,
+ "first axis value at reference pixel", &status);
+ FITS_write_key(outfits, TFLOAT, "CRVAL2", &fzero,
+ "second axis value at reference pixel", &status);
+ FITS_write_key(outfits, TSTRING, "CTYPE1", "LAMBDA",
+ "the coordinate type for the first axis", &status);
+ FITS_write_key(outfits, TSTRING, "CYTPE2", "ANGLE",
+ "the coordinate type for the second axis", &status);
+ FITS_write_key(outfits, TFLOAT, "CD1_1", &fzero,
+ "partial of first axis coordinate w.r.t. x", &status);
+ FITS_write_key(outfits, TFLOAT, "CD1_2", &fzero,
+ "partial of first axis coordinate w.r.t. y", &status);
+ FITS_write_key(outfits, TFLOAT, "CD2_1", &fzero,
+ "partial of second axis coordinate w.r.t. x", &status);
+ FITS_write_key(outfits, TFLOAT, "CD2_2", &fzero,
+ "partial of second axis coordinate w.r.t. y", &status);
+ FITS_write_key(outfits, TDOUBLE, "RA_TARG", &ra_targ,
+ "RA of reference aperture center", &status);
+ FITS_write_key(outfits, TDOUBLE, "DEC_TARG", &dec_targ,
+ "Declination of reference aperture center", &status);
+ FITS_write_key(outfits, TDOUBLE, "PA_APER", &pa_aper,
+ "Position Angle of reference aperture center", &status);
+ FITS_write_key(outfits, TDOUBLE, "EQUINOX", &equinox,
+ "equinox of celestial coord. system", &status);
+
+ FITS_write_comment(outfits, " ", &status);
+ FITS_write_comment(outfits, " HISTOGRAM REGION PARAMETERS", &status);
+ FITS_write_comment(outfits, " ", &status);
+
+ FITS_write_key(outfits, TINT, "XORIGIN", &begx3,
+ "offset of this region in the x dimension", &status);
+ FITS_write_key(outfits, TINT, "YORIGIN", &begy3,
+ "offset of this region in the y dimension", &status);
+ FITS_write_key(outfits, TINT, "RCOUNT", &rcnt3,
+ "count of rectangles in this region", &status);
+ FITS_write_key(outfits, TINT, "MINVAL", &min3,
+ "minimum value within rectangles", &status);
+ FITS_write_key(outfits, TINT, "MAXVAL", &max3,
+ "maximum value within rectangles", &status);
+
+ FITS_write_img(outfits, TSHORT, fpixel, naxes3[0]*naxes3[1],
+ outbuf3, &status);
+ /*
+ * Extension 4
+ */
+ FITS_create_img(outfits, SHORT_IMG, naxis4, naxes4, &status);
+ extver = 4;
+
+ FITS_write_key(outfits, TSTRING, "EXTNAME", "HISTOGRAM",
+ "name of this extension", &status);
+ FITS_write_key(outfits, TINT, "EXTVER" , &extver,
+ "extension version number", &status);
+ FITS_write_key(outfits, TINT, "BZERO" , &bzero,
+ "image brightness offset", &status);
+ FITS_write_key(outfits, TINT, "BSCALE" , &bscale,
+ "image brightness scale", &status);
+
+ FITS_write_comment(outfits, " ", &status);
+ FITS_write_comment(outfits, " ", &status);
+ FITS_write_comment(outfits,
+ " World Coordinate System and Related Parameters",
+ &status);
+ FITS_write_comment(outfits, " ", &status);
+
+ FITS_write_key(outfits, TFLOAT, "CRPIX1", &fzero,
+ "x-coordinate of reference pixel", &status);
+ FITS_write_key(outfits, TFLOAT, "CRPIX2", &fzero,
+ "y-coordinate of reference pixel", &status);
+ FITS_write_key(outfits, TFLOAT, "CRVAL1", &fzero,
+ "first axis value at reference pixel", &status);
+ FITS_write_key(outfits, TFLOAT, "CRVAL2", &fzero,
+ "second axis value at reference pixel", &status);
+ FITS_write_key(outfits, TSTRING, "CTYPE1", "LAMBDA",
+ "the coordinate type for the first axis", &status);
+ FITS_write_key(outfits, TSTRING, "CYTPE2", "ANGLE",
+ "the coordinate type for the second axis", &status);
+ FITS_write_key(outfits, TFLOAT, "CD1_1", &fzero,
+ "partial of first axis coordinate w.r.t. x", &status);
+ FITS_write_key(outfits, TFLOAT, "CD1_2", &fzero,
+ "partial of first axis coordinate w.r.t. y", &status);
+ FITS_write_key(outfits, TFLOAT, "CD2_1", &fzero,
+ "partial of second axis coordinate w.r.t. x", &status);
+ FITS_write_key(outfits, TFLOAT, "CD2_2", &fzero,
+ "partial of second axis coordinate w.r.t. y", &status);
+ FITS_write_key(outfits, TDOUBLE, "RA_TARG", &ra_targ,
+ "RA of reference aperture center", &status);
+ FITS_write_key(outfits, TDOUBLE, "DEC_TARG", &dec_targ,
+ "Declination of reference aperture center", &status);
+ FITS_write_key(outfits, TDOUBLE, "PA_APER", &pa_aper,
+ "Position Angle of reference aperture center", &status);
+ FITS_write_key(outfits, TDOUBLE, "EQUINOX", &equinox,
+ "equinox of celestial coord. system", &status);
+
+ FITS_write_comment(outfits, " ", &status);
+ FITS_write_comment(outfits, " HISTOGRAM REGION PARAMETERS", &status);
+ FITS_write_comment(outfits, " ", &status);
+
+ FITS_write_key(outfits, TINT, "XORIGIN", &begx4,
+ "offset of this region in the x dimension", &status);
+ FITS_write_key(outfits, TINT, "YORIGIN", &begy4,
+ "offset of this region in the y dimension", &status);
+ FITS_write_key(outfits, TINT, "RCOUNT", &rcnt4,
+ "count of rectangles in this region", &status);
+ FITS_write_key(outfits, TINT, "MINVAL", &min4,
+ "minimum value within rectangles", &status);
+ FITS_write_key(outfits, TINT, "MAXVAL", &max4,
+ "maximum value within rectangles", &status);
+
+ FITS_write_img(outfits, TSHORT, fpixel, naxes4[0]*naxes4[1],
+ outbuf4, &status);
+ /*
+ * Free memory and close the input and output files
+ */
+ free(outbuf1);
+ free(outbuf2);
+ free(outbuf3);
+ free(outbuf4);
+ free(posx);
+ free(posy);
+
+ FITS_close_file(outfits, &status);
+ FITS_close_file(infits, &status);
+
+ return 0;
+}
diff --git a/src/analysis/cf_wrspec7.c b/src/analysis/cf_wrspec7.c
new file mode 100644
index 0000000..979046b
--- /dev/null
+++ b/src/analysis/cf_wrspec7.c
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *******************************************************************************
+ *
+ * Synopsis: cf_wrspec7(fitsfile *outfits, long npts, float *wave, float *flux,
+ * float *error, long *counts, float *weights,
+ * float *bkgd,short *pothole)
+ *
+ * Description: Write a file containing a FUSE 2D spectrum.
+ *
+ * Arguments: fitsfile *fname Output FITS file structure
+ *
+ * Returns: none
+ *
+ * History: 12/15/03 bjg Begin work from cf_wrspec4.
+ * 01/12/04 bjg Call to fits_create_tbl with nrow=1
+ * instead of npts
+ * 03/22/04 bjg Change POTHOLE to QUALITY
+ * 03/25/04 bjg Moved time stamp writing to beginning
+ * of routine
+ * 04/07/05 v1.1 tc Create a multi-rows table rather than
+ * a unique vector in a cell
+ *
+ ******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "calfuse.h"
+
+static char CF_PRGM_ID[] = "cf_wrspec7";
+static char CF_VER_NUM[] = "1.1";
+
+void cf_wrspec7(fitsfile *outfits, long npts, float *wave, float *flux,
+ float *error, long *counts, float *weights,float *bkgd,short *pothole)
+{
+ char *ttype[] = {"WAVE", "FLUX", "ERROR", "COUNTS", "WEIGHTS", "BKGD", "QUALITY" };
+ char *tform[] = {"1E", "1E", "1E", "1J", "1E", "1E", "1I"};
+ char *tunit[] = {"ANGSTROMS", "ERG/CM2/S/A", "ERG/CM2/S/A", "COUNTS", "COUNTS", "COUNTS", "UNITLESS"};
+ char extname[] = "FUSE 2D Spectrum";
+ int tfields = 7, status = 0;
+
+ /* Write time stamp to log file. */
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "");
+
+ fits_create_tbl(outfits, BINARY_TBL, 1, tfields, ttype, tform, tunit, extname, &status);
+
+ /* Write out the data. */
+ FITS_write_col(outfits, TFLOAT, 1, 1L, 1L, npts, wave, &status);
+ FITS_write_col(outfits, TFLOAT, 2, 1L, 1L, npts, flux, &status);
+ FITS_write_col(outfits, TFLOAT, 3, 1L, 1L, npts, error, &status );
+ FITS_write_col(outfits, TLONG, 4, 1L, 1L, npts, counts, &status);
+ FITS_write_col(outfits, TFLOAT, 5, 1L, 1L, npts, weights, &status);
+ FITS_write_col(outfits, TFLOAT, 6, 1L, 1L, npts, bkgd, &status);
+ FITS_write_col(outfits, TSHORT, 7, 1L, 1L, npts, pothole, &status);
+
+}
diff --git a/src/analysis/cf_wrspec_cf2.c b/src/analysis/cf_wrspec_cf2.c
new file mode 100644
index 0000000..883c3d5
--- /dev/null
+++ b/src/analysis/cf_wrspec_cf2.c
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *******************************************************************************
+ *
+ * Synopsis: cf_wrspec_cf2(fitsfile *outfits, int npts, float *wave,
+ * float *spec, float *errs, short *qual,
+ * float *counts, float *cntserr, int ncol,
+ * int areaflag);
+ *
+ * Description: Write a file containing a FUSE 1D spectrum, in a format
+ * compatible with Calfuse 2.4 and earlier.
+ *
+ * Arguments: char *fname Output file name
+ * float *wave wavelengths
+ * float *spec spectrum
+ * float *errs associated 1-sigma error bars
+ * short *qual associated quality flags
+ * float *counts total counts in column
+ * float *cntserr 1-sigma error bar on total counts
+ * int ncol specifies 4 or 6 column format
+ * int areaflag 0 if spectrum column is FLUX
+ * 1 if spectrum column is AREA
+ *
+ * Returns: none
+ *
+ * History: 05/04/98 gak Begin work.
+ * 04/20/99 emm Added FITS_ error checking routines,
+ * converted qual flags to BYTE.
+ * 06/07/99 1.2 peb Added reporting of version number.
+ * 10/22/99 1.3 emm Added total counts column.
+ * 10/22/99 1.4 emm Added total counts errors column.
+ * 10/22/99 1.5 emm totcnts and errors are just duplicates
+ * of flux and error for now
+ * 10/29/99 1.6 emm counts and cntserr are now read in
+ * from calling program.
+ * 12/21/99 1.7 emm Quality flags now short (1I) instead
+ * of byte char (1B).
+ * 11/30/01 1.8 wvd Don't write timestamp to log file.
+ * 03/08/04 1.9 jwk allow tfields=4 or 6, and option to
+ * change "FLUX" col to "AREA"; for use
+ * with cf_arith
+ * 04/05/04 bjg Include string.h
+ * Write timestamp
+ *
+ ******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "calfuse.h"
+
+static char CF_PRGM_ID[] = "cf_wrspec_cf2";
+static char CF_VER_NUM[] = "1.9";
+
+void cf_wrspec_cf2(fitsfile *outfits, int npts, float *wave, float *spec,
+ float *errs, short *qual, float *counts, float *cntserr,
+ int ncol, int areaflag)
+{
+ char *ttype[] = {"WAVE", "FLUX", "ERROR", "QUALITY", "COUNTS","CNTSERR"};
+ char *tform[] = {"1E", "1E", "1E", "1I", "1E", "1E"};
+ char *tunit[] = {"ANGSTROMS", "ERG/CM2/S/A", "ERG/CM2/S/A", " ","COUNTS","COUNTS"};
+ char extname[] = "FUSE 1D Spectrum";
+ int tfields = 6,
+ status = 0;
+ long felem = 1,
+ frow = 1;
+
+/* Write time stamp to log file. */
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "");
+
+
+/* Create the extension for the data in the output file.
+ Columns will be
+ WAVE 1E
+ FLUX 1E
+ ERROR 1E
+ QUALITY 1B
+ TOTAL COUNTS 1E Same as FLUX column for now
+ COUNTS ERRORS 1E Same as ERROR column for now
+*/
+
+ if (ncol == 4)
+ {
+ tfields = 4;
+ if (areaflag)
+ {
+ strcpy(ttype[1], "AREA");
+ strcpy(tunit[1], "CM^2");
+ strcpy(tunit[2], "CM^2");
+ }
+ }
+
+ fits_create_tbl (outfits, BINARY_TBL, (long)npts, tfields, ttype,
+ tform, tunit, extname, &status);
+
+/* Write out the data. */
+ FITS_write_col(outfits, TFLOAT, 1, frow, felem, (long)npts,
+ wave, &status);
+
+ FITS_write_col(outfits, TFLOAT, 2, frow, felem, (long)npts,
+ spec, &status);
+
+ FITS_write_col(outfits, TFLOAT, 3, frow, felem, (long)npts,
+ errs, &status );
+
+ FITS_write_col(outfits, TSHORT, 4, frow, felem, (long)npts,
+ qual, &status);
+
+ if (tfields == 6)
+ {
+ FITS_write_col(outfits, TFLOAT, 5, frow, felem, (long)npts,
+ counts, &status);
+
+ FITS_write_col(outfits, TFLOAT, 6, frow, felem, (long)npts,
+ cntserr, &status);
+ }
+
+}
diff --git a/src/analysis/cf_xcorr.c b/src/analysis/cf_xcorr.c
new file mode 100644
index 0000000..383f281
--- /dev/null
+++ b/src/analysis/cf_xcorr.c
@@ -0,0 +1,303 @@
+/*******************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *******************************************************************************
+ *
+ * Usage: cf_xcorr exposure_list exp_shift_list
+ *
+ * Description: Determine pixel shifts between exposures. The
+ * reference spectrum is the one having the longest exposure
+ * time. The input list (ASCII) is the set of exposures to process,
+ * the output list (ASCII) has 3 columns: exposure name, shift and
+ * sigma_shift. Sigma_shift = -1 corresponds to non-detected shift.
+ * Sigma_shift = 1 indicates a valid shift value.
+ * The reference exposure always has shift and sigma_shift of 0.
+ *
+ * History: 04/07/05 tc v1.0 First release
+ * 04/15/05 tc v1.1 Use cf_read_col
+ * 04/27/05 wvd v1.2 Use variance arrays properly.
+ * Use QUALITY array to identify
+ * bad data.
+ * Change spec array to type INT.
+ * Use chi2, not reduced chi2,
+ * to set error bars.
+ * 05/20/05 wvd v1.3 For continuum spectra, use
+ * single region between 1045 and
+ * 1070 A. For emission-line
+ * targets, use O VI lines.
+ * 06/03/05 wvd v1.4 Delete unused variables.
+ * 07/21/05 wvd v1.5 Adopt the sign convention for
+ * spectral shifts used by
+ * FUSE_REGISTER.
+ * 08/01/05 wvd v1.6 Store EXPNIGHT of reference
+ * spectrum in ref_expnight.
+ * 09/13/05 wvd v1.7 If called with no arguments,
+ * return calling info, not error.
+ * 04/27/06 wvd v1.8 Scale each spectrum to match
+ * mean of reference spectrum.
+ * 05/16/06 wvd v1.9 Use Lyman beta to align
+ * background exposures.
+ * Use O VI and C II to align WD's.
+ * 03/28/08 wvd v1.10 Write value of NORM to output.
+ * For HIST data only: if XCORRR
+ * fails, but NORM > 0.5, then
+ * set shift and sigma to 0.
+ * 08/15/08 wvd v1.11 If EXP_STAT = 2, treat as
+ * background observation.
+ *
+ ******************************************************************************/
+
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "calfuse.h"
+
+/* Calfuse variables */
+static char CF_PRGM_ID[] = "cf_xcorr";
+static char CF_VER_NUM[] = "1.11";
+
+/* Parameters */
+#define MAXSHIFT 20
+#define N_SHIFT 41
+
+int main(int argc, char *argv[])
+{
+ /* Variables */
+ char *spec_lis, *out_name, src_type[FLEN_VALUE];
+ char spec_name[FLEN_FILENAME], ref_spec_name[FLEN_FILENAME];
+ char program[FLEN_VALUE];
+ char instmode[FLEN_CARD] ;
+ double *ref_flux, *ref_error, *flux, *error;
+ double scale, sum, variance, norm, ref_tot, total;
+ float chi_square[N_SHIFT], chi_square_min, chi_square_max;
+ float exptime, exptime_max;
+ float *wave, w0, wpc, wmin, wdelta;
+ int ly_beta=FALSE, exp_stat, objclass, shift, sigma;
+ int ind_chi2_min, N, N_tmp, nchi, n_spec, ind_ref_spec=0;
+ long expnight, ref_expnight, i, k, n_pix, ref_start, start;
+
+ FILE *pt_file, *pt_file_out;
+ fitsfile *in_fits;
+ int status = 0, hdutype = 0;
+
+ /***********************************
+ ** Enter a timestamp into the log **
+ ***********************************/
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Begin Processing");
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+
+ /***********************************************************
+ ** Check for proper command-line usage and read arguments **
+ ***********************************************************/
+ if (argc != 3) {
+ printf("Usage: cf_xcorr exposure_list exp_shift_list\n");
+ return(0);
+ }
+
+ spec_lis = argv[1];
+ out_name = argv[2];
+
+ /********************************************
+ ** Open input list and create output file **
+ ********************************************/
+ if ((pt_file = fopen(spec_lis, "r")) == NULL)
+ {
+ cf_if_error("Unable to open file %s", spec_lis);
+ }
+ pt_file_out = fopen(out_name, "w");
+
+ /********************************************************************
+ ** Set the reference spectrum to the one which has maximum EXPTIME **
+ ********************************************************************/
+ n_spec = 0;
+ exptime_max = -1;
+
+ while (fscanf(pt_file, "%80s", spec_name) != EOF)
+ {
+ FITS_open_file(&in_fits, spec_name, READONLY, &status);
+ FITS_read_key(in_fits, TFLOAT, "EXPTIME", &exptime, NULL, &status);
+ FITS_read_key(in_fits, TLONG, "EXPNIGHT", &expnight, NULL, &status);
+ FITS_close_file(in_fits, &status);
+ if (exptime > exptime_max)
+ {
+ exptime_max = exptime;
+ ind_ref_spec = n_spec;
+ strcpy(ref_spec_name, spec_name);
+ }
+ n_spec++;
+ }
+
+ if (n_spec == 0) cf_if_error("At least one spectrum is required");
+
+ if (n_spec == 1)
+ {
+ fprintf(pt_file_out, "%s %2d %2d %5.0f %5ld %c%c%c 1.0\n", ref_spec_name, 0, 0,
+ exptime_max, expnight, ref_spec_name[8], ref_spec_name[9], ref_spec_name[10]);
+ fclose(pt_file_out);
+ return(0);
+ }
+ printf("n_spec: %d, max exptime: %g, ind_ref: %d, ref_name: %s\n",
+ n_spec, exptime_max, ind_ref_spec, ref_spec_name);
+
+ /* Read source type and set XCORR limits accordingly. */
+ FITS_open_file(&in_fits, ref_spec_name, READONLY, &status);
+ FITS_read_key(in_fits, TINT, "EXP_STAT", &exp_stat, NULL, &status);
+ FITS_read_key(in_fits, TSTRING, "PRGRM_ID", &program, NULL, &status);
+ FITS_read_key(in_fits, TINT, "OBJCLASS", &objclass, NULL, &status);
+ FITS_read_key(in_fits, TSTRING, "SRC_TYPE", &src_type, NULL, &status);
+ FITS_read_key(in_fits, TSTRING, "INSTMODE", instmode, NULL, &status) ;
+ FITS_read_key(in_fits, TFLOAT, "W0", &w0, NULL, &status);
+ FITS_read_key(in_fits, TFLOAT, "WPC", &wpc, NULL, &status);
+ if (src_type[1] == 'E') { /* Emission-line source */
+ /* Use Lyman beta to align background observations. */
+ if (exp_stat == (int) TEMPORAL_LIMB ||
+ objclass == 1 || objclass == 7 || objclass == 90) {
+ printf("Assuming background observation.\n");
+ wmin = 1024.;
+ wdelta = 6.;
+ ly_beta = TRUE;
+ } else { /* Use O VI emission for everything else. */
+ printf("SRC_TYPE = %s. Emission-line target.\n", src_type);
+ wmin = 1030.;
+ wdelta = 9.;
+ }
+ }
+ else if (objclass == 17 || objclass == 29 || objclass == 37) {
+ /* Use O VI and C II to align white dwarf spectra. */
+ printf("OBJCLASS = %d. Assuming nearby white dwarf.\n", objclass);
+ wmin = 1030.;
+ wdelta = 9.;
+ }
+ else { /* Use 1045-1070 A region for all other continuum sources. */
+ printf("SRC_TYPE = %s. Assuming continuum target.\n", src_type);
+ wmin = 1045.;
+ wdelta = 25.;
+ }
+ start = cf_nlong((wmin - w0) / wpc);
+ ref_start = start + MAXSHIFT;
+ n_pix = cf_nlong(wdelta / wpc) - (N_SHIFT - 1);
+
+ /* Read wave, flux, and error arrays from reference exposure. */
+ FITS_read_key(in_fits, TLONG, "EXPNIGHT" , &ref_expnight, NULL, &status);
+ FITS_movabs_hdu(in_fits, 2, &hdutype, &status);
+ if (hdutype != BINARY_TBL) cf_if_error("FITS files must contain BINARY TABLE in HDU #2");
+ N = cf_read_col(in_fits, TFLOAT, "WAVE", (void **) &wave);
+ N = cf_read_col(in_fits, TDOUBLE, "FLUX", (void **) &ref_flux);
+ N = cf_read_col(in_fits, TDOUBLE, "ERROR", (void **) &ref_error);
+ FITS_close_file(in_fits, &status);
+
+ /* Compute total flux of reference spectrum in region of interest. */
+ ref_tot = 0.;
+ for (i = 0; i < n_pix; i++) ref_tot += ref_flux[start+i];
+
+ /*****************************************************************
+ ** Compute the shift of each spectrum relative to the reference **
+ ******************************************************************/
+ n_spec = 0;
+ rewind(pt_file);
+
+ while (fscanf(pt_file, "%80s", spec_name) != EOF)
+ {
+ /* Do nothing if the current spectrum is the reference. */
+ if (n_spec++ == ind_ref_spec) {
+ fprintf(pt_file_out, "%s %3d %2d %5.0f %5ld %c%c%c 1.0\n",
+ ref_spec_name, 0, 0, exptime_max, ref_expnight,
+ ref_spec_name[8], ref_spec_name[9], ref_spec_name[10]);
+ continue;
+ }
+
+ /* Read the next spectrum */
+ FITS_open_file(&in_fits, spec_name, READONLY, &status);
+ FITS_read_key(in_fits, TFLOAT, "EXPTIME", &exptime, NULL, &status);
+ FITS_read_key(in_fits, TLONG, "EXPNIGHT", &expnight, NULL, &status);
+ FITS_movabs_hdu(in_fits, 2, &hdutype, &status);
+ if (hdutype != BINARY_TBL) cf_if_error("FITS files must contain BINARY TABLE in HDU #2");
+ N_tmp = cf_read_col(in_fits, TDOUBLE, "FLUX", (void **) &flux);
+ N_tmp = cf_read_col(in_fits, TDOUBLE, "ERROR", (void **) &error);
+ if (N_tmp != N) cf_if_error("Tables must have the same number of elements");
+ FITS_close_file(in_fits, &status);
+
+ /* If EXPTIME < 1, move on to the next data file. */
+ if (exptime < 1) {
+ fprintf(pt_file_out, "%s %3d %2d %5.0f %5ld %c%c%c 0.0\n",
+ spec_name, 0, -1, exptime, expnight,
+ spec_name[8], spec_name[9], spec_name[10]);
+ continue;
+ }
+
+ /* Compute total flux of data spectrum in region of interest. */
+ norm = 1.;
+ if (!ly_beta) { /* Don't rescale if aligning on airglow. */
+ total = 0.;
+ for (i = 0; i < n_pix; i++) total += flux[start+i];
+ norm = ref_tot / total;
+ }
+
+ /* Compute chi-squared for shifts between +/- MAXSHIFT pixels. */
+ for (k = 0; k < N_SHIFT; k++) {
+ nchi = 0;
+ sum = 0;
+ for (i = 0; i < n_pix; i++) {
+ variance = ref_error[ref_start + i] * ref_error[ref_start + i] +
+ norm * norm * error[start + i + k] * error[start + i + k];
+ if (variance > 0) {
+ sum += (ref_flux[ref_start + i] - norm * flux[start + i + k]) *
+ (ref_flux[ref_start + i] - norm * flux[start + i + k]) / variance;
+ nchi++;
+ }
+ }
+ scale = (double) nchi / n_pix;
+ chi_square[k] = sum / scale;
+ }
+
+ /* Compute min and max values of chi-squared. */
+ ind_chi2_min = 0;
+ chi_square_min = 1E5;
+ chi_square_max = -1E5;
+ for (k = 0; k < N_SHIFT; k++) {
+ if (chi_square[k] < chi_square_min)
+ {
+ chi_square_min = chi_square[k];
+ ind_chi2_min = k;
+ }
+ else if (chi_square[k] > chi_square_max)
+ chi_square_max = chi_square[k];
+ }
+ shift = MAXSHIFT - ind_chi2_min;
+
+ /* If chi-squared changes by less than 20% over range of shifts, bail out.
+ * Otherwise, return shift corresponding to lowest value of chi-square. */
+ if (chi_square_max / chi_square_min < 1.2)
+ sigma = -1;
+ else
+ sigma = 1;
+
+
+ /* If we're in HIST mode and sigma = -1 and NORM < 2,
+ * then set shift = sigma = 0. */
+ if (!(strncasecmp(instmode, "HIST", 4)) && sigma == -1 && norm < 2.0)
+ shift = sigma = 0;
+
+ /* printf ("shift = %d\tchi_square_max / chi_square_min = %g\n",
+ ind_chi2_min - MAXSHIFT, chi_square_max / chi_square_min); */
+
+ fprintf(pt_file_out, "%s %3d %2d %5.0f %5ld %c%c%c %f\n",
+ spec_name, shift, sigma, exptime, expnight,
+ spec_name[8], spec_name[9], spec_name[10], norm);
+
+ free(flux);
+ free(error);
+ }
+
+ free(wave);
+ free(ref_flux);
+ free(ref_error);
+
+ fclose(pt_file);
+ fclose(pt_file_out);
+
+ return(0);
+}
diff --git a/src/analysis/extract_jitter.c b/src/analysis/extract_jitter.c
new file mode 100644
index 0000000..a4ceb4d
--- /dev/null
+++ b/src/analysis/extract_jitter.c
@@ -0,0 +1,198 @@
+
+/*************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *************************************************************************
+ *
+ *
+ * Usage:
+ * extract_jitter [-h] [-v level] input_file
+ *
+ *
+ *
+ * Arguments:
+ * input_file : jitter file
+ *
+ *
+ *
+ *
+ *
+ *
+ * Options:
+ * -h: this help message
+ * -v: verbosity level (=1; 0 is silent)
+ *
+ *
+ *
+ *
+ * History: 11/04/2004 v1.0 bjg
+ * 06/03/2005 v1.1 wvd Fix bug that set expstart=expend.
+ * Delete unused variables.
+ *
+ ***************************************************************************/
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "calfuse.h"
+
+
+static char CF_PRGM_ID[]= "extract_jitter";
+static char CF_VER_NUM[]= "1.0";
+
+
+int main(int argc,char *argv[]){
+
+
+
+ char input_filename[FLEN_CARD];
+ char output_filename_x[FLEN_CARD];
+ char output_filename_y[FLEN_CARD];
+
+ FILE * output_file_x;
+ FILE * output_file_y;
+
+ fitsfile * infits;
+
+
+
+ int intnull=0,anynull;
+ int status=0;
+ int hdutype=0;
+
+ long i, N;
+ int ncol;
+
+ double * hdu2_time;
+ double * hdu2_dx;
+ double * hdu2_dy;
+ int * hdu2_trkflg;
+
+
+
+ double mjd,dx,dy;
+
+ int trkflg;
+
+ double expstart, expend;
+
+ int optc;
+
+ char opts[] = "hfv:";
+ char usage[] =
+ "Usage:\n"
+ " extract_jitter [-h] [-v level] input_file\n\n"
+ "Arguments:\n"
+ " input_file : jitter file (FITS)\n\n";
+ char option[] =
+ "Options:\n"
+ " -h: this help message \n"
+ " -v: verbosity level (=1; 0 is silent) \n";
+
+ verbose_level = 1;
+
+
+ /* Check number of options and arguments */
+ while ((optc = getopt(argc, argv, opts)) != -1) {
+ switch(optc) {
+ case 'h':
+ printf("%s\n%s", usage, option);
+ return EXIT_SUCCESS;
+ case 'v':
+ verbose_level = atoi(optarg);
+ break;
+ }
+ }
+
+ /* Initialize error checking. */
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+ if (argc != optind+1)
+ cf_if_error("%s\nIncorrect number of program arguments", usage);
+
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Started execution.");
+
+ strcpy(input_filename,argv[optind]);
+
+
+
+ strcpy(output_filename_x,input_filename);
+ strcpy(output_filename_y,input_filename);
+ strcat(output_filename_x,".jtx");
+ strcat(output_filename_y,".jty");
+
+
+ /* Create the output file */
+ output_file_x = fopen(output_filename_x,"w");
+ output_file_y = fopen(output_filename_y,"w");
+
+
+
+ FITS_open_file(&infits,input_filename,READONLY,&status);
+
+ FITS_read_key(infits,TDOUBLE,"EXPSTART",&expstart,NULL,&status);
+ FITS_read_key(infits,TDOUBLE,"EXPEND",&expend,NULL,&status);
+
+ FITS_movabs_hdu(infits,2,&hdutype,&status);
+
+ FITS_read_key(infits,TLONG,"NAXIS2",&N,NULL,&status);
+
+ hdu2_time=(double *)malloc(N*sizeof(double));
+ hdu2_dx=(double *)malloc(N*sizeof(double));
+ hdu2_dy=(double *)malloc(N*sizeof(double));
+ hdu2_trkflg=(int *)malloc(N*sizeof(int));
+
+ FITS_get_colnum(infits, TRUE, "TIME", &ncol, &status);
+ FITS_read_col(infits, TDOUBLE, ncol, 1, 1, N, &intnull,
+ hdu2_time, &anynull, &status);
+
+ FITS_get_colnum(infits, TRUE, "DX", &ncol, &status);
+ FITS_read_col(infits, TDOUBLE, ncol, 1, 1, N, &intnull,
+ hdu2_dx, &anynull, &status);
+
+ FITS_get_colnum(infits, TRUE, "DY", &ncol, &status);
+ FITS_read_col(infits, TDOUBLE, ncol, 1, 1, N, &intnull,
+ hdu2_dy, &anynull, &status);
+
+ FITS_get_colnum(infits, TRUE, "TRKFLG", &ncol, &status);
+ FITS_read_col(infits, TINT, ncol, 1, 1, N, &intnull,
+ hdu2_trkflg, &anynull, &status);
+
+
+ for (i=0;i<N-100;i++){
+ mjd=expstart+(hdu2_time[i])/(3600.0*24.0);
+ dx=hdu2_dx[i];
+ dy=hdu2_dy[i];
+ trkflg=hdu2_trkflg[i];
+
+ if ((mjd>=expstart) && (mjd<=expend) && (trkflg==5)){
+ fprintf(output_file_x,"%15lf %15lf\n",mjd,dx);
+ fprintf(output_file_y,"%15lf %15lf\n",mjd,dy);
+ }
+ }
+
+
+
+ free(hdu2_time);
+ free(hdu2_dx);
+ free(hdu2_dy);
+ free(hdu2_trkflg);
+
+
+
+ FITS_close_file(infits,&status);
+
+ fclose(output_file_x);
+ fclose(output_file_y);
+
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Finished execution.");
+ return EXIT_SUCCESS;
+
+}
diff --git a/src/analysis/get_shift.c b/src/analysis/get_shift.c
new file mode 100644
index 0000000..a4c2b70
--- /dev/null
+++ b/src/analysis/get_shift.c
@@ -0,0 +1,164 @@
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: getshift spec1 spec2 w1 w2
+ *
+ * Description: Computes the wavelength shift between the spectra from two
+ * different exposures spec1 and spec2 using a cross-correlation
+ * in the wavelength window defined by w1 and w2
+ *
+ *
+ * History: 01/08/04 bjg 1.0 begin work
+ * 04/05/04 bjg 1.1 Return EXIT_SUCCESS
+ * Correct formats to match
+ * argument types in printf
+ * 08/26/05 wvd 1.2 If given no arguments, don't return error.
+ * Just print message and exit.
+ *
+ ****************************************************************************/
+
+#include <time.h>
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "calfuse.h"
+
+
+#define MAXSHIFT 25
+#define SMOOTH_PAR 4
+
+
+static char CF_PRGM_ID[] = "get_shift";
+static char CF_VER_NUM[] = "1.2";
+
+
+int wave_search(float *table, int i, int j, float elmt){
+
+ int k;
+
+ if (i>=j) return i;
+ if (elmt==table[i]) return i;
+ if (elmt==table[j]) return j;
+ k=(i+j)/2;
+ if (elmt==table[k]) return k;
+ if ((elmt-table[i])*(elmt-table[k])<0) return wave_search(table,i,k,elmt);
+ return wave_search(table,k+1,j,elmt);
+}
+
+int main(int argc, char *argv[])
+{
+
+ int status=0;
+ int hdutype=0;
+
+ long n,n1,n2,laux,i,j,k;
+
+ float *wave, *flux1, *flux2, *flux1s, *flux2s;
+
+ float w1,w2;
+
+ fitsfile *infits1, *infits2;
+
+ float correl[2*MAXSHIFT+1];
+
+
+ /* Enter a timestamp into the log. */
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Begin Processing");
+
+ /* Initialize error checking */
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+
+ /* check command line */
+ if (argc != 5) {
+ printf("Usage: getshift spec1 spec2 w1 w2 \n");
+ return 1;
+ }
+
+
+ FITS_open_file(&infits1, argv[1], READONLY, &status);
+ FITS_open_file(&infits2, argv[2], READONLY, &status);
+
+ sscanf(argv[3],"%f",&w1);
+ sscanf(argv[4],"%f",&w2);
+
+
+ FITS_movabs_hdu(infits1, 2, &hdutype, &status);
+ FITS_movabs_hdu(infits2, 2, &hdutype, &status);
+
+
+ n=cf_read_col(infits1,TFLOAT,"WAVE",(void **) &wave);
+ n=cf_read_col(infits1,TFLOAT,"FLUX",(void **) &flux1);
+ n=cf_read_col(infits2,TFLOAT,"FLUX",(void **) &flux2);
+
+
+ flux1s=(float*)malloc(n*sizeof(float));
+ flux2s=(float*)malloc(n*sizeof(float));
+
+
+ for (i=0;i<n;i++){
+ flux1s[i]=0;
+ flux2s[i]=0;
+ k=0;
+ for (j=i-SMOOTH_PAR;j<=i+SMOOTH_PAR;j++){
+ if ((j>=0)&&(j<n)) {
+ flux1s[i]+=flux1[j];
+ flux2s[i]+=flux2[j];
+ k=k+1;
+ }
+ }
+ flux1s[i]/=k;
+ flux2s[i]/=k;
+
+
+ }
+
+
+
+ if ((w1-wave[0])*(w1-wave[n-1])>0)
+ cf_if_error("Wavelength parameters out of range\n");
+
+ if ((w2-wave[0])*(w2-wave[n-1])>0)
+ cf_if_error("Wavelength parameters out of range\n");
+
+ n1=wave_search(wave,0,n-1,w1);
+ n2=wave_search(wave,0,n-1,w2);
+
+
+ if (n1>n2) {
+ laux=n2;
+ n2=n1;
+ n1=laux;
+ }
+
+ if ((n1-MAXSHIFT<0)||(n2+MAXSHIFT>=n))
+ cf_if_error("Wavelength parameters too close to bounds\n");
+
+ k=0;
+
+ for (i=0;i<=2*MAXSHIFT;i++){
+ correl[i]=0;
+ for (j=n1;j<=n2;j++){
+ correl[i]=correl[i]+flux1s[j]*flux2s[j+i-MAXSHIFT];
+ }
+ if (correl[i]>correl[k]) k=i;
+ }
+
+
+
+ FITS_close_file(infits1, &status);
+ FITS_close_file(infits2, &status);
+
+ /* Enter a timestamp into the log. */
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Done processing");
+
+ printf("Shift is %ld steps.\n",k-MAXSHIFT);
+
+ return EXIT_SUCCESS;
+
+
+}
diff --git a/src/analysis/gethmjd.c b/src/analysis/gethmjd.c
new file mode 100644
index 0000000..dcb3cdb
--- /dev/null
+++ b/src/analysis/gethmjd.c
@@ -0,0 +1,98 @@
+
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ *
+ * From Modified Julian Day and RA,DEC of target,
+ * computes Heliocentic Modified Julian Day
+ *
+ * Uses slalib to compute the light time delay along the target direction.
+ *
+ *
+ * History: 10/06/04 bjg
+ *
+ ****************************************************************************/
+
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <math.h>
+
+#ifdef CFORTRAN
+#include "cfortran.h"
+
+PROTOCCALLSFSUB6(SLA_DJCL, sla_djcl, DOUBLE, PINT, PINT, PINT, PDOUBLE, \
+ PINT)
+#define slaDjcl(DJM, IY, IM, ID, FD, J) \
+ CCALLSFSUB6(SLA_DJCL, sla_djcl, DOUBLE, PINT, PINT, PINT, PDOUBLE, \
+ PINT, DJM, IY, IM, ID, FD, J)
+
+
+PROTOCCALLSFSUB6(SLA_CALYD, sla_calyd, INT, INT, INT, PINT, PINT, \
+ PINT)
+#define slaCalyd(IY, IM, ID, NY, ND, J) \
+ CCALLSFSUB6(SLA_CALYD, sla_calyd, INT, INT, INT, PINT, PINT, \
+ PINT, IY, IM, ID, NY, ND, J)
+
+PROTOCCALLSFSUB7(SLA_ECOR, sla_ecor, FLOAT, FLOAT, INT, INT, FLOAT, PFLOAT, \
+ PFLOAT)
+#define slaEcor(RM, DM, IY, ID, FD, RV, TL) \
+ CCALLSFSUB7(SLA_ECOR, sla_ecor, FLOAT, FLOAT, INT, INT, FLOAT, PFLOAT, \
+ PFLOAT, RM, DM, IY, ID, FD, RV, TL)
+
+#else
+#include "slalib.h"
+#include "slamac.h"
+#endif
+
+
+#include "calfuse.h"
+
+
+#define DEG2RAD (M_PI/180.0f)
+
+double gethmjd(double mjd, int ra_h, int ra_m, float ra_s, int dec_d, int dec_m, float dec_s){
+
+
+ int status;
+
+ int year, month, day;
+ int jyear, jday;
+ double frac;
+
+
+ float ra, dec;
+ float lt, v;
+
+ ra = ( ra_h + ra_m/60.0 + ra_s/3600.0 ) * 15.0 * DEG2RAD;
+ dec = ( dec_d + dec_m/60.0 + dec_s/3600.0 ) * DEG2RAD;
+
+
+#ifdef CFORTRAN
+ slaDjcl(mjd, year, month, day, frac, status);
+#else
+ slaDjcl(mjd, &year, &month, &day, &frac, &status);
+#endif
+
+#ifdef CFORTRAN
+ slaCalyd(year, month, day, jyear, jday, status);
+#else
+ slaCalyd(year, month, day, &jyear, &jday, &status);
+#endif
+
+#ifdef CFORTRAN
+ slaEcor(ra, dec, jyear, jday, (float) frac, v, lt);
+#else
+ slaEcor(ra, dec, jyear, jday, (float) frac, &v, &lt);
+#endif
+
+ return (double) (mjd+lt/(3600.0*24.0));
+
+}
diff --git a/src/analysis/idf_combine.c b/src/analysis/idf_combine.c
new file mode 100644
index 0000000..3f1a678
--- /dev/null
+++ b/src/analysis/idf_combine.c
@@ -0,0 +1,945 @@
+
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: idf_combine outfile file1 file2 file3 file4 file5 ...
+ *
+ * Description: Reads multiple contiguous idf files and concatenates them
+ * into a single file.
+ *
+ * History: 08/11/03 bjg Begin work from ttag_combine.c
+ * sort the input files in time order
+ * 08/12/03 bjg v1.0 First usable version
+ * 08/13/03 bjg Some minor changes
+ * 08/14/03 bjg Fixed some important keywords
+ * in the main HDU
+ * 08/20/03 bjg v1.1 Changed the way the binary tables
+ * are read, created and written
+ * (same as cf_ttag_init)
+ * 09/09/03 bjg v1.2 Fixed some keywords
+ * 10/29/03 bjg Changed the scaling format for
+ * output timeline to conform the
+ * new IDF formatting.
+ * 11/17/03 bjg v1.3 Now warns users if the Focal
+ * Plane Assembly has moved between
+ * exposures.
+ * 11/22/03 bjg Now prints the name of the
+ * included files in the main
+ * header.
+ * 12/10/03 bjg Updated NSPEC keyword and
+ * SPECxxx, WOFFLxxx, WOFFSxxx keywords
+ * Removed path in filenames written
+ * into header.
+ * 02/25/04 bjg Bug fix
+ * 03/25/04 bjg Added TZERO and TSCALE values for
+ * AIC and FEC countrates
+ * 04/05/04 bjg Remove unused variables
+ * Change formats to match arg types
+ * in printf
+ * Remove static keyword in struct key
+ * definition
+ * Add braces in TSCAL and TZERO
+ * definitions
+ * 06/08/04 bjg Changes to handle EXP_STAT keyword
+ * 08/13/04 bjg v1.4 Recalculates Y centroid on demand
+ * 10/06/04 bjg v1.5 Added option -b to store
+ * ORBITAL_VEL in a float
+ * 10/26/04 bjg v1.6 Cosmetic change
+ * 01/28/2005 bjg v1.7 Fixed crash within CFITSIO with
+ * with IDF files having empty tables
+ * 02/16/2005 wvd v1.8 Double TSCALE and TZERO
+ * for the AIC_CNT_RATE array.
+ * 03/22/2005 wvd v1.9 Read and write TIME_SUNRISE
+ * and TIME_SUNSET as shorts.
+ * 04/15/2005 tc v1.10 Update PLANTIME keyword
+ * 06/08/2005 tc v1.11 Comment out warning if FPA has
+ * shifted. Pipeline corrects for this.
+ * 09/19/2005 wvd v1.12 Don't even read FPA positions.
+ * 05/22/2006 wvd v1.13 Change most header keyword
+ * types from float to long.
+ * 06/22/2006 wvd v1.14 Add -z flag to force creation of
+ * an output file, even if empty.
+ * 11/10/2006 wvd v1.15 Add comment fields to WOFFS and
+ * WOFFL keywords.
+ * 08/27/2007 bot v1.16 Changed long for int l.138
+ * 07/25/2008 wvd v1.17 Set output EXP_STAT keyword to lowest
+ * non-negative value among input files.
+ * 08/22/2008 wvd v1.18 If -a flag is set, include files with
+ * positive values of EXP_STAT, but not
+ * those with negative values.
+ *
+ ****************************************************************************/
+
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include "calfuse.h"
+
+typedef char filename[FLEN_CARD];
+
+struct key {
+ char keyword[FLEN_KEYWORD];
+ float value;
+};
+
+static char CF_PRGM_ID[]= "idf_combine";
+static char CF_VER_NUM[]= "1.18";
+
+int main(int argc,char *argv[]){
+
+ char date[FLEN_CARD]={'\0'};
+ char rootname[FLEN_CARD];
+ char comment[FLEN_COMMENT];
+
+ int felem_hdu2,felem_hdu4,frow_hdu3;
+
+ char stime[FLEN_CARD],keyword[FLEN_CARD],card[FLEN_CARD];
+
+ char fmt_byte[FLEN_CARD],fmt_float[FLEN_CARD],fmt_short[FLEN_CARD];
+
+ char *corrected_filename;
+ char *string_pointer;
+ char string0[100], string1[100];
+
+ time_t vtime;
+
+ fitsfile *infits,*outfits;
+
+ filename *filelist;
+ double *expstartlist;
+ double *expendlist;
+ long *neventslist;
+ long *nrecordslist;
+ long *ngtislist;
+
+ double delta_t;
+
+ float zero=0.0;
+
+ filename tempstring;
+ double tempdouble;
+ long templong;
+ float tempfloat;
+ char tempchar;
+
+ double minexpstart;
+ int minindex;
+
+ int nfiles;
+
+ int intnull=0,anynull;
+ int ncol;
+
+ int status=0;
+ int hdutype=0;
+ int tref = 0;
+
+ int n2;
+
+ int exp_stat, exp_stat_out=99;
+
+ long nevents=0, nrecords=0, ngtis=0;
+ long n_real_events=0;
+
+ long i,j;
+
+ float *floatlist;
+ short *shortlist;
+ char *charlist;
+ double *doublelist;
+
+ float exptime=0, rawtime=0;
+ long neventscreened=0, neventscreenedpha=0, plantime=0, timehv=0;
+ long timescreened=0, timesaa=0, timelowlimbangle=0, timeburst=0,
+ timejitter=0,timenight=0;
+
+ /* float fpasx0, fpasx, fpalx0, fpalx, dfpasx, dfpalx ; */
+ /* int fpa_split = FALSE; */
+
+ int hdu2_tfields=14;
+
+ char hdu2_extname[]="TTAG DATA"; /* Name of this extension */
+
+ char *hdu2_ttype[]={"TIME", "XRAW", "YRAW", "PHA", "WEIGHT", "XFARF",
+ "YFARF", "X", "Y", "CHANNEL", "TIMEFLGS",
+ "LOC_FLGS", "LAMBDA", "ERGCM2" };
+
+ char *hdu2_tform[14]; /* We'll assign values when we know
+ the number of elements in the data set. */
+
+
+ char *hdu2_tunit[]={"SECONDS", "PIXELS", "PIXELS", "UNITLESS", "UNITLESS",
+ "PIXELS", "PIXELS", "PIXELS", "PIXELS", "UNITLESS",
+ "UNITLESS", "UNITLESS", "ANGSTROMS", "ERG CM^-2"};
+
+ struct key hdu2_tscal[] = {{"TSCAL6", 0.25}, {"TSCAL7", 0.1},
+ {"TSCAL8", 0.25}, {"TSCAL9", 0.1}};
+
+ struct key hdu2_tzero[] = {{"TZERO6", 8192.}, {"TZERO7", 0.},
+ {"TZERO8", 8192.}, {"TZERO9", 0.}};
+
+
+
+
+ int hdu3_tfields=2;
+
+ char hdu3_extname[]="GTI"; /* Name of this extension */
+
+ char *hdu3_ttype[]={"START", "STOP" };
+
+ char *hdu3_tform[2]={"1D", "1D" }; /* We'll assign values when we know
+ the number of elements in the data set. */
+
+
+ char *hdu3_tunit[]={"seconds", "seconds"};
+
+ struct key hdu4_tscal[16];
+ struct key hdu4_tzero[16];
+
+ char hdu4_extname[]="TIMELINE";
+ int hdu4_tfields=16; /* output table will have 16 columns */
+ char *hdu4_ttype[]={"TIME", "STATUS_FLAGS", "TIME_SUNRISE", "TIME_SUNSET",
+ "LIMB_ANGLE", "LONGITUDE", "LATITUDE", "ORBITAL_VEL",
+ "HIGH_VOLTAGE", "LIF_CNT_RATE", "SIC_CNT_RATE",
+ "FEC_CNT_RATE", "AIC_CNT_RATE", "BKGD_CNT_RATE",
+ "YCENT_LIF","YCENT_SIC"};
+
+ char *hdu4_tform[16]; /* we will define tform later, when the number
+ of photons is known */
+
+ char *hdu4_tunit[]={"seconds", "unitless", "seconds", "seconds", "degrees",
+ "degrees", "degrees", "km/s", "unitless", "counts/sec",
+ "counts/sec", "counts/sec", "counts/sec", "counts/sec",
+ "pixels","pixels" };
+
+
+ int ignore_exp_stat=0;
+ int do_ycent=0;
+ int big_vel=0;
+ int do_empty=FALSE, empty_output=FALSE;
+
+ float *x=NULL, *y=NULL, *weight=NULL;
+ unsigned char *channel=NULL, *timeflags=NULL, *locflags=NULL;
+
+ int optc;
+
+ char opts[] = "hacbv:z";
+ char usage[] =
+ "Usage:\n"
+ " idf_combine [-ahbcz] [-v level] output_idf_file input_idf_files\n";
+ char option[] =
+ "Options:\n"
+ " -h: this help message\n"
+ " -v: verbosity level (=1; 0 is silent)\n"
+ " -a: ignore EXP_STAT keyword \n"
+ " -c: recalculates Y centroids (use target events) \n"
+ " -b: store ORBITAL_VEL in a float \n"
+ " -z: if no good data, generate empty output file\n";
+
+ verbose_level = 1;
+
+ /* Check number of options and arguments */
+ while ((optc = getopt(argc, argv, opts)) != -1) {
+ switch(optc) {
+
+ case 'h':
+ printf("%s\n%s", usage, option);
+ return 0;
+ case 'a':
+ ignore_exp_stat=1;
+ break;
+ case 'v':
+ verbose_level = atoi(optarg);
+ break;
+ case 'c':
+ do_ycent=1;
+ break;
+ case 'b':
+ big_vel=1;
+ break;
+ case 'z':
+ do_empty=TRUE;
+ break;
+ }
+ }
+
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+ if (argc < optind+2) {
+ printf("%s", usage);
+ return 1;
+ }
+
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Started execution.");
+
+ /* get and display time */
+ vtime = time(NULL) ;
+ strcpy(stime,ctime(&vtime));
+
+
+ nfiles=argc-optind-1;
+
+ filelist = (filename *)cf_calloc(nfiles, sizeof(filename));
+ expstartlist = (double *)cf_calloc(nfiles, sizeof(double));
+ expendlist = (double *)cf_calloc(nfiles, sizeof(double));
+ neventslist = (long *)cf_calloc(nfiles, sizeof(long));
+ nrecordslist = (long *)cf_calloc(nfiles, sizeof(long));
+ ngtislist = (long *)cf_calloc(nfiles, sizeof(long));
+
+ if (!ignore_exp_stat)
+ cf_verbose(1,"Will include only files with EXP_STAT=0") ;
+ else
+ cf_verbose(1,"Will include only files with EXP_STAT >= 0") ;
+
+ cf_verbose(1,"GETTING INFORMATION ON INPUT FILES") ;
+
+ n2=0;
+
+ for (i=0; i<nfiles;i++) {
+
+ FITS_open_file(&infits,argv[optind+i+1],READONLY,&status);
+
+ FITS_read_key(infits,TINT,"EXP_STAT",&exp_stat,NULL,&status);
+
+ strcpy(filelist[n2],argv[optind+i+1]);
+ FITS_read_key(infits,TDOUBLE,"EXPSTART",&(expstartlist[n2]),NULL,&status);
+ FITS_read_key(infits,TDOUBLE,"EXPEND",&(expendlist[n2]),NULL,&status);
+
+ /* Set EXP_STAT to lowest non-negative value in input files. */
+ if (exp_stat_out > exp_stat && exp_stat >= 0) exp_stat_out = exp_stat;
+
+ /* Skip files with bad values of EXP_STAT. */
+ if (!ignore_exp_stat && exp_stat != 0) {
+ cf_if_warning("File %s rejected. EXP_STAT not equal to zero. Use -a flag to override.",
+ argv[optind+i+1]) ;
+ FITS_close_file(infits,&status);
+ continue;
+ }
+ /* Never include files with negative values of EXP_STAT. */
+ else if (exp_stat < 0) {
+ cf_if_warning("File %s rejected. EXP_STAT less than zero.", argv[optind+i+1]) ;
+ FITS_close_file(infits,&status);
+ continue;
+ }
+
+ FITS_read_key(infits,TFLOAT,"EXPTIME",&(tempfloat),NULL,&status);
+ exptime+=tempfloat;
+ FITS_read_key(infits,TLONG,"NEVENTS",&templong,NULL,&status);
+ n_real_events+=templong;
+ FITS_read_key(infits,TFLOAT,"RAWTIME",&(tempfloat),NULL,&status);
+ rawtime+=tempfloat;
+ FITS_read_key(infits,TLONG,"PLANTIME",&(templong),NULL,&status);
+ plantime+=tempfloat;
+
+ FITS_read_key(infits,TLONG,"NBADEVNT",&templong,NULL,&status);
+ neventscreened+=templong;
+ FITS_read_key(infits,TLONG,"NBADPHA",&templong,NULL,&status);
+ neventscreenedpha+=templong;
+
+ FITS_read_key(infits,TLONG,"EXP_BAD",&templong,NULL,&status);
+ timescreened+=templong;
+ FITS_read_key(infits,TLONG,"EXP_BRST",&templong,NULL,&status);
+ timeburst+=templong;
+ FITS_read_key(infits,TLONG,"EXP_HV",&templong,NULL,&status);
+ timehv+=templong;
+ FITS_read_key(infits,TLONG,"EXP_JITR",&templong,NULL,&status);
+ timejitter+=templong;
+ FITS_read_key(infits,TLONG,"EXP_LIM",&templong,NULL,&status);
+ timelowlimbangle+=templong;
+ FITS_read_key(infits,TLONG,"EXP_SAA",&templong,NULL,&status);
+ timesaa+=templong;
+ FITS_read_key(infits,TLONG,"EXPNIGHT",&templong,NULL,&status);
+ timenight+=templong;
+
+ FITS_movabs_hdu(infits,2,&hdutype,&status);
+ FITS_read_key(infits,TSTRING,"TFORM1",&tempstring,NULL,&status);
+ sscanf(tempstring,"%ld%c",&neventslist[n2],&tempchar);
+ nevents+=neventslist[n2];
+
+ FITS_movabs_hdu(infits,3,&hdutype,&status);
+ FITS_read_key(infits,TLONG,"NAXIS2",&(ngtislist[n2]),NULL,&status);
+ ngtis+=ngtislist[n2];
+
+ FITS_movabs_hdu(infits,4,&hdutype,&status);
+ FITS_read_key(infits,TSTRING,"TFORM1",&tempstring,NULL,&status);
+ sscanf(tempstring,"%ld%c",&nrecordslist[n2],&tempchar);
+ nrecords+=nrecordslist[n2];
+
+ FITS_close_file(infits,&status);
+
+ n2++;
+ }
+
+ nfiles=n2;
+
+ if (nfiles==0){
+ if (do_empty) {
+ cf_verbose(1,"No files to combine. Generating empty output file.");
+ do_ycent = FALSE;
+ empty_output = TRUE;
+ expendlist[0]=expstartlist[0];
+ nfiles = 1;
+ }
+ else {
+ cf_verbose(1,"No files to combine. Exiting.");
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Finished execution.");
+ exit(0);
+ }
+ }
+
+ cf_verbose(1,"SORTING INPUT FILES IN TIME ORDER") ;
+
+ for (i=0; i<nfiles-1;i++) {
+ minexpstart=expstartlist[i];
+ minindex=i;
+ for (j=i+1; j<nfiles;j++) {
+ if (expstartlist[j]<minexpstart){
+ minexpstart=expstartlist[j];
+ minindex=j;
+ }
+ }
+
+ strcpy(tempstring,filelist[minindex]);
+ strcpy(filelist[minindex],filelist[i]);
+ strcpy(filelist[i],tempstring);
+
+ tempdouble=expstartlist[minindex];
+ expstartlist[minindex]=expstartlist[i];
+ expstartlist[i]=tempdouble;
+
+ tempdouble=expendlist[minindex];
+ expendlist[minindex]=expendlist[i];
+ expendlist[i]=tempdouble;
+
+ templong=neventslist[minindex];
+ neventslist[minindex]=neventslist[i];
+ neventslist[i]=templong;
+
+ templong=nrecordslist[minindex];
+ nrecordslist[minindex]=nrecordslist[i];
+ nrecordslist[i]=templong;
+
+ templong=ngtislist[minindex];
+ ngtislist[minindex]=ngtislist[i];
+ ngtislist[i]=templong;
+ }
+
+ cf_verbose(2,
+ "N: Filename ExpStart ExpEnd NEvents NGTIs NSeconds");
+
+ for (i=0; i<nfiles;i++) {
+ cf_verbose(2,"%ld: %s %7.1f %7.1f %4ld %2ld %5ld",i,filelist[i],
+ expstartlist[i],expendlist[i],neventslist[i],ngtislist[i],
+ nrecordslist[i]);
+
+ }
+
+ cf_verbose(1,"CREATING OUTPUT FILE");
+
+ FITS_open_file(&infits,filelist[0],READONLY,&status);
+ FITS_create_file(&outfits,argv[optind],&status);
+
+
+ cf_verbose(1,"WRITING MAIN HEADER");
+
+ FITS_copy_hdu(infits,outfits,0,&status);
+
+ FITS_read_key(infits,TSTRING,"ROOTNAME",rootname,NULL,&status);
+
+ rootname[8]='9';
+ rootname[9]='9';
+ rootname[10]='9';
+
+ FITS_update_key(outfits,TSTRING,"ROOTNAME",rootname,NULL,&status);
+
+ string_pointer=strrchr(argv[optind],'/');
+ if (string_pointer==NULL) corrected_filename=argv[optind];
+ else corrected_filename=&(string_pointer[1]);
+
+ FITS_update_key(outfits,TINT,"EXP_STAT",&exp_stat_out,NULL,&status);
+
+ FITS_update_key(outfits,TSTRING,"FILENAME",corrected_filename,NULL,&status);
+
+ FITS_update_key(outfits,TSTRING,"EXP_ID","999",NULL,&status);
+
+ fits_get_system_time(date, &tref, &status);
+
+ FITS_update_key(outfits,TSTRING,"DATE",date,NULL,&status);
+
+ FITS_update_key(outfits,TDOUBLE,"EXPEND",&expendlist[nfiles-1],NULL,&status);
+ FITS_update_key(outfits,TFLOAT,"EXPTIME",&exptime,NULL,&status);
+ FITS_update_key(outfits,TLONG,"NEVENTS",&n_real_events,NULL,&status);
+ FITS_update_key(outfits,TFLOAT,"RAWTIME",&rawtime,NULL,&status);
+ FITS_update_key(outfits,TLONG,"PLANTIME",&plantime,NULL,&status);
+ FITS_update_key(outfits,TLONG,"NBADEVNT",&neventscreened,NULL,&status);
+ FITS_update_key(outfits,TLONG,"NBADPHA",&neventscreenedpha,NULL,&status);
+ FITS_update_key(outfits,TLONG,"EXP_BAD",&(timescreened),NULL,&status);
+ FITS_update_key(outfits,TLONG,"EXP_BRST",&(timeburst),NULL,&status);
+ FITS_update_key(outfits,TLONG,"EXP_HV",&(timehv),NULL,&status);
+ FITS_update_key(outfits,TLONG,"EXP_JITR",&(timejitter),NULL,&status);
+ FITS_update_key(outfits,TLONG,"EXP_LIM",&(timelowlimbangle),NULL,&status);
+ FITS_update_key(outfits,TLONG,"EXP_SAA",&(timesaa),NULL,&status);
+ FITS_update_key(outfits,TLONG,"EXPNIGHT",&(timenight),NULL,&status);
+
+ if (do_ycent) {
+ strcpy(string0,"PERFORM");
+ FITS_update_key(outfits, TSTRING, "YCNT_COR", string0, NULL, &status);
+
+ for (i = 1; i < 8; i++) {
+ if (i == 4) continue;
+ sprintf(string1, "YQUAL%1ld", i);
+ strcpy(string0,"HIGH");
+ FITS_update_key(outfits, TSTRING, string1, string0, NULL, &status);
+ }
+ }
+
+ /* reset BPM_CAL */
+ fits_read_key(outfits,TSTRING,"BPM_CAL",string0,NULL,&status);
+ if (status!=0) {
+ status = 0;
+ }
+ else {
+ strcpy(string0,"");
+ FITS_update_key(outfits,TSTRING,"BPM_CAL",string0,NULL,&status);
+ }
+
+
+ if (empty_output) {
+ fits_write_history(outfits,"FILE CONTAINS NO DATA.",&status);
+ n2=0;
+ FITS_update_key(outfits,TINT,"NSPEC",&n2,NULL,&status);
+ }
+ else
+ FITS_update_key(outfits,TINT,"NSPEC",&nfiles,NULL,&status);
+
+ fits_write_history(outfits," COMBINED WITH IDF_COMBINE ",&status);
+
+ for (i=0;i<nfiles;i++){
+
+ string_pointer=strrchr(filelist[i],'/');
+ if (string_pointer==NULL) corrected_filename=filelist[i];
+ else corrected_filename=&(string_pointer[1]);
+
+
+ sprintf(keyword, "SPEC%.3ld", i+1);
+ FITS_update_key(outfits,TSTRING,keyword,corrected_filename,NULL,&status);
+ sprintf(keyword, "WOFFL%.3ld", i+1);
+ sprintf(comment, "[Angstroms] Shift applied to LiF spectrum");
+ FITS_update_key(outfits,TFLOAT,keyword,&zero,comment,&status);
+ sprintf(keyword, "WOFFS%.3ld", i+1);
+ sprintf(comment, "[Angstroms] Shift applied to SiC spectrum");
+ FITS_update_key(outfits,TFLOAT,keyword,&zero,comment,&status);
+ }
+
+ FITS_close_file(infits,&status);
+
+ cf_verbose(1,"PREPARING EVENTS LIST HDU");
+
+ /* Generate the tform array */
+ sprintf(fmt_byte, "%ldB", nevents);
+ sprintf(fmt_float, "%ldE", nevents);
+ sprintf(fmt_short, "%ldI", nevents);
+
+ hdu2_tform[0] = fmt_float;
+ hdu2_tform[1] = fmt_short;
+ hdu2_tform[2] = fmt_short;
+ hdu2_tform[3] = fmt_byte;
+ hdu2_tform[4] = fmt_float;
+ for (i=5; i<9; i++)
+ hdu2_tform[i] = fmt_short;
+ for ( ; i<12; i++)
+ hdu2_tform[i] = fmt_byte;
+ hdu2_tform[12] = fmt_float;
+ hdu2_tform[13] = fmt_float;
+
+
+ /* Append a new empty binary table to the output file */
+ FITS_create_tbl(outfits, BINARY_TBL, 1, hdu2_tfields, hdu2_ttype, hdu2_tform,
+ hdu2_tunit, hdu2_extname, &status);
+
+ /* Write TSCALE and TZERO entries to header */
+ for (i=0; i<4; i++) {
+ sprintf(keyword, "TUNIT%ld", i+6);
+ if (fits_read_keyword(outfits, keyword, card, NULL, &status))
+ cf_if_fits_error(status);
+ FITS_insert_key_flt(outfits, hdu2_tscal[i].keyword, hdu2_tscal[i].value,
+ -2, NULL, &status);
+ FITS_insert_key_flt(outfits, hdu2_tzero[i].keyword, hdu2_tzero[i].value,
+ -4, NULL, &status);
+ }
+
+
+
+ cf_verbose(1,"PREPARING GTIs LIST HDU");
+
+ /* Append a new empty binary table to the output file */
+ FITS_create_tbl(outfits, BINARY_TBL, ngtis, hdu3_tfields, hdu3_ttype, hdu3_tform,
+ hdu3_tunit, hdu3_extname, &status);
+
+
+ cf_verbose(1,"PREPARING TIMELINE HDU");
+
+ /* Generate the tform array */
+ sprintf(fmt_byte, "%ldB", nrecords);
+ sprintf(fmt_float, "%ldE", nrecords);
+ sprintf(fmt_short, "%ldI", nrecords);
+
+
+
+ hdu4_tform[0] = fmt_float;
+ hdu4_tform[1] = fmt_byte;
+
+ for (i=2; i<hdu4_tfields; i++) hdu4_tform[i] = fmt_short;
+
+ /* Set TSCALE and TZERO values */
+ /* Not all of these will be used; see below. */
+ for (i=2; i<hdu4_tfields; i++) {
+ sprintf(hdu4_tscal[i].keyword, "TSCAL%ld", i+1);
+ hdu4_tscal[i].value = 0.1;
+ sprintf(hdu4_tzero[i].keyword, "TZERO%ld", i+1);
+ hdu4_tzero[i].value = 0.;
+ }
+
+ /* Let's keep three significant figures for vorb. */
+ hdu4_tscal[7].value = 0.01;
+
+ /* FEC_CNT_RATE and AIC_CNT_RATE can get big, so we
+ use TZERO AND TSCALE to compress them. */
+ hdu4_tscal[11].value = 1;
+ hdu4_tscal[12].value = 2;
+ hdu4_tzero[11].value = 32768;
+ hdu4_tzero[12].value = 65536;
+
+ if (big_vel) hdu4_tform[7]=fmt_float;
+
+ /* Append a new empty binary table to the output file */
+ FITS_create_tbl(outfits, BINARY_TBL, 1, hdu4_tfields, hdu4_ttype, hdu4_tform,
+ hdu4_tunit, hdu4_extname, &status);
+
+
+ /* Write TSCALE and TZERO entries to header */
+ for (i=2; i<hdu4_tfields; i++) {
+
+ if ((i==7)&&(big_vel)) continue;
+
+ /* Omit TSCALE and TZERO for these six arrays. */
+ if (i == 2) continue; /* TIME_SUNRISE */
+ if (i == 3) continue; /* TIME_SUNSET */
+ if (i == 8) continue; /* HIGH_VOLTAGE */
+ if (i == 9) continue; /* LIF_CNT_RATE */
+ if (i == 10) continue; /* SIC_CNT_RATE */
+ if (i == 13) continue; /* BKGD_CNT_RATE */
+
+
+ sprintf(keyword, "TUNIT%ld", i+1);
+ if (fits_read_keyword(outfits, keyword, card, NULL, &status))
+ cf_if_fits_error(status);
+ FITS_insert_key_flt(outfits, hdu4_tscal[i].keyword, hdu4_tscal[i].value,
+ -1, NULL, &status);
+ FITS_insert_key_flt(outfits, hdu4_tzero[i].keyword, hdu4_tzero[i].value,
+ -5, NULL, &status);
+
+ }
+
+
+
+
+
+
+ felem_hdu2=1; frow_hdu3=1; felem_hdu4=1;
+
+
+ cf_verbose(1,"COMBINING HDU");
+
+ for (i=0;i<nfiles;i++){
+
+ cf_verbose(2,"PROCESSING FILE %ld EVENTS LIST",i);
+
+ delta_t=(expstartlist[i]-expstartlist[0])*3600*24;
+
+ FITS_open_file(&infits,filelist[i],READONLY,&status);
+
+ FITS_movabs_hdu(infits, 2, &hdutype, &status);
+ FITS_movabs_hdu(outfits, 2, &hdutype, &status);
+
+ if (neventslist[i]>0){
+ floatlist=(float *)malloc(neventslist[i]*sizeof(float));
+ shortlist=(short *)malloc(neventslist[i]*sizeof(short));
+ charlist=(char *)malloc(neventslist[i]*sizeof(char));
+
+ FITS_get_colnum(infits, TRUE, "TIME", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, neventslist[i], &intnull,
+ floatlist, &anynull, &status);
+ for (j=0;j<neventslist[i];j++) floatlist[j]+=delta_t;
+ FITS_write_col(outfits, TFLOAT, 1, 1, felem_hdu2, neventslist[i], floatlist, &status);
+
+
+
+ FITS_get_colnum(infits, TRUE, "XRAW", &ncol, &status);
+ FITS_read_col(infits, TSHORT, ncol, 1, 1, neventslist[i], &intnull,
+ shortlist, &anynull, &status);
+ FITS_write_col(outfits, TSHORT, 2, 1, felem_hdu2, neventslist[i], shortlist, &status);
+
+
+
+ FITS_get_colnum(infits, TRUE, "YRAW", &ncol, &status);
+ FITS_read_col(infits, TSHORT, ncol, 1, 1, neventslist[i], &intnull,
+ shortlist, &anynull, &status);
+ FITS_write_col(outfits, TSHORT, 3, 1, felem_hdu2, neventslist[i], shortlist, &status);
+
+
+
+ FITS_get_colnum(infits, TRUE, "PHA", &ncol, &status);
+ FITS_read_col(infits, TBYTE, ncol, 1, 1, neventslist[i], &intnull,
+ charlist, &anynull, &status);
+ FITS_write_col(outfits, TBYTE, 4, 1, felem_hdu2, neventslist[i], charlist, &status);
+
+
+
+ FITS_get_colnum(infits, TRUE, "WEIGHT", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, neventslist[i], &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 5, 1, felem_hdu2, neventslist[i], floatlist, &status);
+
+
+
+ FITS_get_colnum(infits, TRUE, "XFARF", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, neventslist[i], &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 6, 1, felem_hdu2, neventslist[i], floatlist, &status);
+
+
+
+ FITS_get_colnum(infits, TRUE, "YFARF", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, neventslist[i], &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 7, 1, felem_hdu2, neventslist[i], floatlist, &status);
+
+
+
+ FITS_get_colnum(infits, TRUE, "X", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, neventslist[i], &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 8, 1, felem_hdu2, neventslist[i], floatlist, &status);
+
+
+
+ FITS_get_colnum(infits, TRUE, "Y", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, neventslist[i], &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 9, 1, felem_hdu2, neventslist[i], floatlist, &status);
+
+
+
+ FITS_get_colnum(infits, TRUE, "CHANNEL", &ncol, &status);
+ FITS_read_col(infits, TBYTE, ncol, 1, 1, neventslist[i], &intnull,
+ charlist, &anynull, &status);
+ FITS_write_col(outfits, TBYTE, 10, 1, felem_hdu2, neventslist[i], charlist, &status);
+
+
+
+ FITS_get_colnum(infits, TRUE, "TIMEFLGS", &ncol, &status);
+ FITS_read_col(infits, TBYTE, ncol, 1, 1, neventslist[i], &intnull,
+ charlist, &anynull, &status);
+ FITS_write_col(outfits, TBYTE, 11, 1, felem_hdu2, neventslist[i], charlist, &status);
+
+
+
+ FITS_get_colnum(infits, TRUE, "LOC_FLGS", &ncol, &status);
+ FITS_read_col(infits, TBYTE, ncol, 1, 1, neventslist[i], &intnull,
+ charlist, &anynull, &status);
+ FITS_write_col(outfits, TBYTE, 12, 1, felem_hdu2, neventslist[i], charlist, &status);
+
+
+
+ FITS_get_colnum(infits, TRUE, "LAMBDA", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, neventslist[i], &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 13, 1, felem_hdu2, neventslist[i], floatlist, &status);
+
+
+
+ FITS_get_colnum(infits, TRUE, "ERGCM2", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, neventslist[i], &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 14, 1, felem_hdu2, neventslist[i], floatlist, &status);
+
+
+ free(floatlist);
+ free(charlist);
+ free(shortlist);
+ }
+
+ cf_verbose(2,"PROCESSING FILE %ld GTIs LIST",i);
+
+ FITS_movabs_hdu(infits, 3, &hdutype, &status);
+ FITS_movabs_hdu(outfits, 3, &hdutype, &status);
+
+ if (ngtislist[i]>0){
+ doublelist=(double *)malloc(ngtislist[i]*sizeof(double));
+
+ FITS_get_colnum(infits, TRUE, "START", &ncol, &status);
+ FITS_read_col(infits, TDOUBLE, ncol, 1, 1, ngtislist[i], &intnull,
+ doublelist, &anynull, &status);
+ for (j=0;j<ngtislist[i];j++) doublelist[j]+=delta_t;
+ FITS_write_col(outfits, TDOUBLE, 1, frow_hdu3, 1, ngtislist[i], doublelist, &status);
+
+ FITS_get_colnum(infits, TRUE, "STOP", &ncol, &status);
+ FITS_read_col(infits, TDOUBLE, ncol, 1, 1, ngtislist[i], &intnull,
+ doublelist, &anynull, &status);
+ for (j=0;j<ngtislist[i];j++) doublelist[j]+=delta_t;
+ FITS_write_col(outfits, TDOUBLE, 2, frow_hdu3, 1, ngtislist[i], doublelist, &status);
+
+
+ free(doublelist);
+ }
+
+ cf_verbose(2,"PROCESSING FILE %ld TIMELINE",i);
+
+ FITS_movabs_hdu(infits, 4, &hdutype, &status);
+ FITS_movabs_hdu(outfits, 4, &hdutype, &status);
+
+ if (nrecordslist[i]>0){
+ floatlist=(float *)malloc(nrecordslist[i]*sizeof(float));
+ shortlist=(short *)malloc(nrecordslist[i]*sizeof(short));
+ charlist=(char *)malloc(nrecordslist[i]*sizeof(char));
+
+
+ FITS_get_colnum(infits, TRUE, "TIME", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecordslist[i], &intnull,
+ floatlist, &anynull, &status);
+ for (j=0;j<nrecordslist[i];j++) floatlist[j]+=delta_t;
+ FITS_write_col(outfits, TFLOAT, 1, 1, felem_hdu4, nrecordslist[i], floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "STATUS_FLAGS", &ncol, &status);
+ FITS_read_col(infits, TBYTE, ncol, 1, 1, nrecordslist[i], &intnull,
+ charlist, &anynull, &status);
+ FITS_write_col(outfits, TBYTE, 2, 1, felem_hdu4, nrecordslist[i], charlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "TIME_SUNRISE", &ncol, &status);
+ FITS_read_col(infits, TSHORT, ncol, 1, 1, nrecordslist[i], &intnull,
+ shortlist, &anynull, &status);
+ FITS_write_col(outfits, TSHORT, 3, 1, felem_hdu4, nrecordslist[i], shortlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "TIME_SUNSET", &ncol, &status);
+ FITS_read_col(infits, TSHORT, ncol, 1, 1, nrecordslist[i], &intnull,
+ shortlist, &anynull, &status);
+ FITS_write_col(outfits, TSHORT, 4, 1, felem_hdu4, nrecordslist[i], shortlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "LIMB_ANGLE", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecordslist[i], &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 5, 1, felem_hdu4, nrecordslist[i], floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "LONGITUDE", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecordslist[i], &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 6, 1, felem_hdu4, nrecordslist[i], floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "LATITUDE", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecordslist[i], &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 7, 1, felem_hdu4, nrecordslist[i], floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "ORBITAL_VEL", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecordslist[i], &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 8, 1, felem_hdu4, nrecordslist[i], floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "HIGH_VOLTAGE", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecordslist[i], &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 9, 1, felem_hdu4, nrecordslist[i], floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "LIF_CNT_RATE", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecordslist[i], &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 10, 1, felem_hdu4, nrecordslist[i], floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "SIC_CNT_RATE", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecordslist[i], &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 11, 1, felem_hdu4, nrecordslist[i], floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "FEC_CNT_RATE", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecordslist[i], &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 12, 1, felem_hdu4, nrecordslist[i], floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "AIC_CNT_RATE", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecordslist[i], &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 13, 1, felem_hdu4, nrecordslist[i], floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "BKGD_CNT_RATE", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecordslist[i], &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 14, 1, felem_hdu4, nrecordslist[i], floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "YCENT_LIF", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecordslist[i], &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 15, 1, felem_hdu4, nrecordslist[i], floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "YCENT_SIC", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecordslist[i], &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 16, 1, felem_hdu4, nrecordslist[i], floatlist, &status);
+
+
+
+
+ free(floatlist);
+ free(charlist);
+ free(shortlist);
+ }
+
+
+ felem_hdu2+=neventslist[i];
+ frow_hdu3+=ngtislist[i];
+ felem_hdu4+=nrecordslist[i];
+ FITS_close_file(infits,&status);
+
+
+ }
+
+/*
+ if (fpa_split)
+ cf_if_warning("FPA motion detected. Resolution may be compromised.");
+*/
+
+ if (do_ycent){
+ FITS_movabs_hdu(outfits, 2, &hdutype, &status);
+ nevents = cf_read_col(outfits, TFLOAT, "X", (void **) &x);
+ nevents = cf_read_col(outfits, TFLOAT, "Y", (void **) &y);
+ nevents = cf_read_col(outfits, TFLOAT, "WEIGHT", (void **) &weight);
+ nevents = cf_read_col(outfits, TBYTE, "TIMEFLGS", (void **) &timeflags);
+ nevents = cf_read_col(outfits, TBYTE, "LOC_FLGS", (void **) &locflags);
+ nevents = cf_read_col(outfits, TBYTE, "CHANNEL", (void **) &channel);
+
+ FITS_movabs_hdu(outfits, 1, &hdutype, &status);
+
+ /* Compute centroids. */
+ cf_calculate_y_centroid(outfits, nevents, weight, x, y, channel,
+ timeflags, locflags);
+ }
+
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+ cf_verbose(1,"CLOSING OUTPUT FILE");
+
+ FITS_close_file(outfits,&status);
+
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Finished execution.");
+ return EXIT_SUCCESS;
+
+}
+
+
diff --git a/src/analysis/idf_cut.c b/src/analysis/idf_cut.c
new file mode 100644
index 0000000..b302c60
--- /dev/null
+++ b/src/analysis/idf_cut.c
@@ -0,0 +1,977 @@
+
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Usage:
+ * idf_cut [-hm] [-v level] idf_file RefTime Period Nout
+ * Arguments:
+ * RefTime : Reference Time in seconds since EXPSTART
+ * Period : Period in seconds
+ * Nout : Number of output files.
+ * Options:
+ * -m : interprets RefTime as MJD
+ * -h : this help message
+ * -v : verbosity level (=1; 0 is silent)
+ *
+ * Description:
+ *
+ * Cuts the IDF file into several smaller IDF files, sorting the
+ * events according to their phase. The GTIs table and timeline get
+ * also cut.
+ * From the input IDF file, idf_cut generates Nout IDF files named
+ * {input_idf_filename}.p{X}.fit with X=0..Nout-1. An event in the
+ * input file is sorted in output file X if it happens in the interval
+ * [RefTime+(k+X/Nout)*Period,RefTime+(k+(X+1)/Nout)*Period[
+ * with k an integer.
+ *
+ * History: 10/08/04 bjg v1.0
+ * 10/26/04 bjg v1.1 Now updates the GTIs table
+ * Fixed EXPNIGHT computation
+ * Added -m switch.
+ * + some cosmetic changes
+ * 12/01/04 bjg v1.2 Free allocated memory in the
+ * subroutines
+ * 12/02/04 bjg v1.3 Fixed bug in make_gtitab
+ * 06/03/05 wvd v1.4 Change nevents and nseconds to longs.
+ * 01/18/06 wvd v1.5 Read arrays with cf_read_col.
+ *
+ ****************************************************************************/
+
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <math.h>
+
+#include "calfuse.h"
+
+#define _MIN(a,b) (((a)<(b))?(a):(b))
+
+typedef char filename[FLEN_CARD];
+
+struct key {
+ char keyword[FLEN_KEYWORD];
+ float value;
+};
+
+static char CF_PRGM_ID[]= "idf_cut";
+static char CF_VER_NUM[]= "1.1";
+
+
+static int _isinphase(double t, double RefTime, double Period, double vinf, double vsup){
+
+ float v;
+
+ v=fmod(t-RefTime,Period);
+ if (v<0) v+=Period;
+
+ return ((v>=vinf)&&(v<vsup));
+}
+
+static double _getphasenextstart(double t, double RefTime, double Period, double vinf, double vsup){
+
+ float v;
+
+ v=fmod(t-RefTime,Period);
+ if (v<0) v+=Period;
+
+ if (v>vinf) return t-v+vinf+Period;
+ else return t-v+vinf;
+
+}
+static double _getphasenextstop(double t, double RefTime, double Period, double vinf, double vsup){
+
+ float v;
+
+ v=fmod(t-RefTime,Period);
+ if (v<0) v+=Period;
+
+ if (v>vsup) return t-v+vsup+Period;
+ else return t-v+vsup;
+}
+
+struct _gti{
+ double start;
+ double stop;
+ struct _gti *next;
+};
+
+typedef struct{
+ struct _gti * gtilist;
+ long N;
+} _tempgtis;
+
+static void _pushgti(double a, double b, _tempgtis * tempgtis){
+ struct _gti *aux;
+
+ aux=tempgtis->gtilist;
+
+ tempgtis->gtilist=malloc(sizeof(struct _gti));
+ tempgtis->N++;
+ tempgtis->gtilist->start=a;
+ tempgtis->gtilist->stop=b;
+ tempgtis->gtilist->next=aux;
+}
+
+static void _popgti(double * a, double * b, _tempgtis * tempgtis){
+ struct _gti *aux;
+
+ *a=tempgtis->gtilist->start;
+ *b=tempgtis->gtilist->stop;
+
+ aux=tempgtis->gtilist;
+ tempgtis->gtilist=tempgtis->gtilist->next;
+ free(aux);
+ tempgtis->N--;
+}
+
+static _tempgtis * _makegtis(){
+ _tempgtis * tempgtis;
+
+ tempgtis=malloc(sizeof(_tempgtis));
+ tempgtis->gtilist=NULL;
+ tempgtis->N=0;
+ return tempgtis;
+}
+
+static void _deletegtis(_tempgtis * tempgtis){
+ double a,b;
+ while (tempgtis->gtilist!=NULL) _popgti(&a,&b,tempgtis);
+ free(tempgtis);
+ tempgtis=NULL;
+}
+
+static long _ngtis(_tempgtis * tempgtis){
+ return tempgtis->N;
+}
+
+
+/****************************************************************************/
+
+long make_evlist(fitsfile *infits,fitsfile *outfits,
+ double RefTime,double Period, long Nout,
+ long phase,char * daynight,
+ long * nbadevnt,long * nbadpha){
+
+
+ int status=0;
+
+ char pha;
+ char loc_flgs;
+ char timeflgs;
+ char time_test;
+
+ char keyword[FLEN_CARD],card[FLEN_CARD];
+
+ char fmt_byte[FLEN_CARD],fmt_float[FLEN_CARD],fmt_short[FLEN_CARD];
+
+ int tfields=14;
+
+ char extname[]="TTAG DATA"; /* Name of this extension */
+
+ char *ttype[]={"TIME", "XRAW", "YRAW", "PHA", "WEIGHT", "XFARF",
+ "YFARF", "X", "Y", "CHANNEL", "TIMEFLGS",
+ "LOC_FLGS", "LAMBDA", "ERGCM2" };
+
+ char *tform[14]; /* We'll assign values when we know
+ the number of elements in the data set. */
+
+
+ char *tunit[]={"SECONDS", "PIXELS", "PIXELS", "UNITLESS", "UNITLESS",
+ "PIXELS", "PIXELS", "PIXELS", "PIXELS", "UNITLESS",
+ "UNITLESS", "UNITLESS", "ANGSTROMS", "ERG CM^-2"};
+
+ struct key tscal[] = {{"TSCAL6", 0.25}, {"TSCAL7", 0.1},
+ {"TSCAL8", 0.25}, {"TSCAL9", 0.1}};
+
+ struct key tzero[] = {{"TZERO6", 8192.}, {"TZERO7", 0.},
+ {"TZERO8", 8192.}, {"TZERO9", 0.}};
+
+ float *i_time;
+ short *i_xraw;
+ short *i_yraw;
+ char *i_pha;
+ float *i_weight;
+ float *i_xfarf;
+ float *i_yfarf;
+ float *i_x;
+ float *i_y;
+ char *i_channel;
+ char *i_timeflgs;
+ char *i_loc_flgs;
+ float *i_lambda;
+ float *i_ergcm2;
+
+
+ float *o_time;
+ short *o_xraw;
+ short *o_yraw;
+ char *o_pha;
+ float *o_weight;
+ float *o_xfarf;
+ float *o_yfarf;
+ float *o_x;
+ float *o_y;
+ char *o_channel;
+ char *o_timeflgs;
+ char *o_loc_flgs;
+ float *o_lambda;
+ float *o_ergcm2;
+
+ long npts;
+
+ long i;
+
+ float vinf,vsup;
+
+ long nevents=0;
+
+ *nbadevnt=0;
+ *nbadpha=0;
+
+
+ npts = cf_read_col(infits, TFLOAT, "TIME", (void **) &i_time);
+ npts = cf_read_col(infits, TSHORT, "XRAW", (void **) &i_xraw);
+ npts = cf_read_col(infits, TSHORT, "YRAW", (void **) &i_yraw);
+ npts = cf_read_col(infits, TBYTE, "PHA", (void **) &i_pha);
+ npts = cf_read_col(infits, TFLOAT, "WEIGHT", (void **) &i_weight);
+ npts = cf_read_col(infits, TFLOAT, "XFARF", (void **) &i_xfarf);
+ npts = cf_read_col(infits, TFLOAT, "YFARF", (void **) &i_yfarf);
+ npts = cf_read_col(infits, TFLOAT, "X", (void **) &i_x);
+ npts = cf_read_col(infits, TFLOAT, "Y", (void **) &i_y);
+ npts = cf_read_col(infits, TBYTE, "CHANNEL", (void **) &i_channel);
+ npts = cf_read_col(infits, TBYTE, "TIMEFLGS", (void **) &i_timeflgs);
+ npts = cf_read_col(infits, TBYTE, "LOC_FLGS", (void **) &i_loc_flgs);
+ npts = cf_read_col(infits, TFLOAT, "LAMBDA", (void **) &i_lambda);
+ npts = cf_read_col(infits, TFLOAT, "ERGCM2", (void **) &i_ergcm2);
+
+
+ o_time = (float *) malloc(npts*sizeof(float));
+ o_xraw = (short *) malloc(npts*sizeof(short));
+ o_yraw = (short *) malloc(npts*sizeof(short));
+ o_pha = (char *) malloc(npts*sizeof(char));
+ o_weight = (float *) malloc(npts*sizeof(float));
+ o_xfarf = (float *) malloc(npts*sizeof(float));
+ o_yfarf = (float *) malloc(npts*sizeof(float));
+ o_x = (float *) malloc(npts*sizeof(float));
+ o_y = (float *) malloc(npts*sizeof(float));
+ o_channel = (char *) malloc(npts*sizeof(char));
+ o_timeflgs = (char *) malloc(npts*sizeof(char));
+ o_loc_flgs = (char *) malloc(npts*sizeof(char));
+ o_lambda = (float *) malloc(npts*sizeof(float));
+ o_ergcm2 = (float *) malloc(npts*sizeof(float));
+
+ vinf=(phase*Period)/((float)Nout);
+ vsup=((phase+1)*Period)/((float)Nout);
+
+
+ for (i=0;i<npts;i++){
+
+ if (_isinphase(i_time[i], RefTime, Period, vinf, vsup)) {
+
+ o_time[nevents] = i_time[i];
+ o_xraw[nevents] = i_xraw[i];
+ o_yraw[nevents] = i_yraw[i];
+ o_pha[nevents] = i_pha[i];
+ o_weight[nevents] = i_weight[i];
+ o_xfarf[nevents] = i_xfarf[i];
+ o_yfarf[nevents] = i_yfarf[i];
+ o_x[nevents] = i_x[i];
+ o_y[nevents] = i_y[i];
+ o_channel[nevents] = i_channel[i];
+ o_timeflgs[nevents] = i_timeflgs[i];
+ o_loc_flgs[nevents] = i_loc_flgs[i];
+ o_lambda[nevents] = i_lambda[i];
+ o_ergcm2[nevents] = i_ergcm2[i];
+
+ pha=i_pha[i];
+ loc_flgs=i_loc_flgs[i];
+ timeflgs=i_timeflgs[i];
+
+ switch(daynight[0]) {
+ case 'D':
+ time_test=timeflgs^TEMPORAL_DAY;
+ break;
+ case 'N':
+ time_test=timeflgs;
+ break;
+ default:
+ time_test=timeflgs&(~TEMPORAL_DAY);
+ }
+
+ if (loc_flgs&LOCATION_PHA){
+ *nbadpha++;
+ }
+
+ if ((loc_flgs&~LOCATION_AIR) || (time_test)) {
+ *nbadevnt++;
+ }
+
+
+ nevents++;
+
+ }
+
+
+ }
+
+
+
+
+ /* Generate the tform array */
+ sprintf(fmt_byte, "%ldB", nevents);
+ sprintf(fmt_float, "%ldE", nevents);
+ sprintf(fmt_short, "%ldI", nevents);
+
+ tform[0] = fmt_float;
+ tform[1] = fmt_short;
+ tform[2] = fmt_short;
+ tform[3] = fmt_byte;
+ tform[4] = fmt_float;
+ for (i=5; i<9; i++)
+ tform[i] = fmt_short;
+ for ( ; i<12; i++)
+ tform[i] = fmt_byte;
+ tform[12] = fmt_float;
+ tform[13] = fmt_float;
+
+
+ /* Append a new empty binary table to the output file */
+ FITS_create_tbl(outfits, BINARY_TBL, 1, tfields, ttype, tform,
+ tunit, extname, &status);
+
+ /* Write TSCALE and TZERO entries to header */
+ for (i=0; i<4; i++) {
+ sprintf(keyword, "TUNIT%ld", i+6);
+ if (fits_read_keyword(outfits, keyword, card, NULL, &status))
+ cf_if_fits_error(status);
+ FITS_insert_key_flt(outfits, tscal[i].keyword, tscal[i].value,
+ -2, NULL, &status);
+ FITS_insert_key_flt(outfits, tzero[i].keyword, tzero[i].value,
+ -4, NULL, &status);
+ }
+
+ if (nevents > 0) {
+
+ FITS_write_col(outfits, TFLOAT, 1, 1, 1, nevents, o_time, &status);
+ FITS_write_col(outfits, TSHORT, 2, 1, 1, nevents, o_xraw, &status);
+ FITS_write_col(outfits, TSHORT, 3, 1, 1, nevents, o_yraw, &status);
+ FITS_write_col(outfits, TBYTE , 4, 1, 1, nevents, o_pha, &status);
+ FITS_write_col(outfits, TFLOAT, 5, 1, 1, nevents, o_weight, &status);
+ FITS_write_col(outfits, TFLOAT, 6, 1, 1, nevents, o_xfarf, &status);
+ FITS_write_col(outfits, TFLOAT, 7, 1, 1, nevents, o_yfarf, &status);
+ FITS_write_col(outfits, TFLOAT, 8, 1, 1, nevents, o_x, &status);
+ FITS_write_col(outfits, TFLOAT, 9, 1, 1, nevents, o_y, &status);
+ FITS_write_col(outfits, TBYTE , 10, 1, 1, nevents, o_channel, &status);
+ FITS_write_col(outfits, TBYTE , 11, 1, 1, nevents, o_timeflgs, &status);
+ FITS_write_col(outfits, TBYTE , 12, 1, 1, nevents, o_loc_flgs, &status);
+ FITS_write_col(outfits, TFLOAT, 13, 1, 1, nevents, o_lambda, &status);
+ FITS_write_col(outfits, TFLOAT, 14, 1, 1, nevents, o_ergcm2, &status);
+ }
+
+ free(o_time);
+ free(o_xraw );
+ free(o_yraw);
+ free(o_pha);
+ free(o_weight);
+ free(o_xfarf);
+ free(o_yfarf);
+ free(o_x);
+ free(o_y);
+ free(o_channel);
+ free(o_timeflgs);
+ free(o_loc_flgs);
+ free(o_lambda);
+ free(o_ergcm2);
+
+ free(i_time);
+ free(i_xraw );
+ free(i_yraw);
+ free(i_pha);
+ free(i_weight);
+ free(i_xfarf);
+ free(i_yfarf);
+ free(i_x);
+ free(i_y);
+ free(i_channel);
+ free(i_timeflgs);
+ free(i_loc_flgs);
+ free(i_lambda);
+ free(i_ergcm2);
+
+ return nevents;
+}
+
+/****************************************************************************/
+long make_gtitab(fitsfile * infits, fitsfile * outfits,
+ double RefTime, double Period, long Nout,
+ long phase){
+
+
+
+ int status=0;
+
+ int tfields=2;
+ char extname[]="GTI"; /* Name of this extension */
+ char *ttype[]={"START", "STOP" };
+ char *tform[2]={"1D", "1D" };
+ char *tunit[]={"seconds", "seconds"};
+
+ double *i_start;
+ double *i_stop;
+ double *o_start;
+ double *o_stop;
+
+ _tempgtis * tempgtis;
+
+ long npts=0;
+ long ngtis=0;
+ long i;
+
+ float vinf,vsup;
+
+ double a,b;
+ double _start, _stop;
+
+ npts = cf_read_col(infits, TDOUBLE, "START", (void **) &i_start);
+ npts = cf_read_col(infits, TDOUBLE, "STOP", (void **) &i_stop);
+
+ vinf=(phase*Period)/((float)Nout);
+ vsup=((phase+1)*Period)/((float)Nout);
+
+ tempgtis=_makegtis();
+ for (i=0;i<npts;i++){
+ cf_verbose(4,"Input GTI %ld = %lf/%lf",i,i_start[i],i_stop[i]);
+ a=i_start[i];
+ b=i_stop[i];
+ if (_isinphase(a,RefTime, Period, vinf, vsup)) _start=a;
+ else _start=_MIN(b,_getphasenextstart(a,RefTime, Period, vinf, vsup));
+
+ while (_start<b){
+ _stop=_MIN(b,_getphasenextstop(_start,RefTime, Period, vinf, vsup));
+ _pushgti(_start,_stop,tempgtis);
+ cf_verbose(4,"Output GTI = %lf,%lf",_start,_stop);
+ _start=_getphasenextstart(_stop,RefTime, Period, vinf, vsup);
+ }
+ }
+
+ ngtis=_ngtis(tempgtis);
+
+ o_start=(double *)malloc(ngtis*sizeof(double));
+ o_stop=(double *)malloc(ngtis*sizeof(double));
+
+ for (i=ngtis-1;i>=0;i--){
+ _popgti(&o_start[i],&o_stop[i],tempgtis);
+ }
+
+ _deletegtis(tempgtis);
+
+ /* Append a new empty binary table to the output file */
+ FITS_create_tbl(outfits, BINARY_TBL, ngtis, tfields, ttype, tform,
+ tunit, extname, &status);
+
+
+ if (ngtis>0){
+ FITS_write_col(outfits, TDOUBLE, 1, 1, 1, ngtis, o_start, &status);
+ FITS_write_col(outfits, TDOUBLE, 2, 1, 1, ngtis, o_stop, &status);
+ }
+
+ return ngtis;
+
+}
+/****************************************************************************/
+long make_timeline(fitsfile *infits, fitsfile *outfits,
+ double RefTime, double Period, long Nout, long phase,
+ char *daynight,
+ double *exptime, double *exp_bad, double *exp_brst, double *exp_hv,
+ double *exp_jitr, double *exp_lim, double *exp_saa, double *expnight){
+
+ char timeflgs;
+ char time_test;
+ int status=0;
+
+ int bigtime=1;
+ int big_vel=1;
+
+ char keyword[FLEN_CARD],card[FLEN_CARD];
+
+ char fmt_byte[FLEN_CARD],fmt_float[FLEN_CARD],fmt_short[FLEN_CARD];
+
+ struct key tscal[16];
+ struct key tzero[16];
+
+ char extname[]="TIMELINE";
+
+ int tfields=16; /* output table will have 16 columns */
+
+ char *ttype[]={"TIME", "STATUS_FLAGS", "TIME_SUNRISE", "TIME_SUNSET",
+ "LIMB_ANGLE", "LONGITUDE", "LATITUDE", "ORBITAL_VEL",
+ "HIGH_VOLTAGE", "LIF_CNT_RATE", "SIC_CNT_RATE",
+ "FEC_CNT_RATE", "AIC_CNT_RATE", "BKGD_CNT_RATE",
+ "YCENT_LIF","YCENT_SIC"};
+
+ char *tform[16]; /* we will define tform later, when the number
+ of photons is known */
+
+ char *tunit[]={"seconds", "unitless", "seconds", "seconds", "degrees",
+ "degrees", "degrees", "km/s", "unitless", "counts/sec",
+ "counts/sec", "counts/sec", "counts/sec", "counts/sec",
+ "pixels","pixels" };
+
+ float *i_time;
+ char *i_status_flags;
+ float *i_time_sunrise;
+ float *i_time_sunset;
+ float *i_limb_angle;
+ float *i_longitude;
+ float *i_latitude;
+ float *i_orbital_vel;
+ short *i_high_voltage;
+ short *i_lif_cnt_rate;
+ short *i_sic_cnt_rate;
+ short *i_fec_cnt_rate;
+ short *i_aic_cnt_rate;
+ short *i_bkgd_cnt_rate;
+ float *i_ycent_lif;
+ float *i_ycent_sic;
+
+ float *o_time;
+ char *o_status_flags;
+ float *o_time_sunrise;
+ float *o_time_sunset;
+ float *o_limb_angle;
+ float *o_longitude;
+ float *o_latitude;
+ float *o_orbital_vel;
+ short *o_high_voltage;
+ short *o_lif_cnt_rate;
+ short *o_sic_cnt_rate;
+ short *o_fec_cnt_rate;
+ short *o_aic_cnt_rate;
+ short *o_bkgd_cnt_rate;
+ float *o_ycent_lif;
+ float *o_ycent_sic;
+
+ long npts;
+
+ long i;
+
+ float vinf,vsup;
+
+ long nseconds=0;
+
+ *exptime=0;
+ *expnight=0;
+ *exp_bad=0;
+ *exp_brst=0;
+ *exp_hv=0;
+ *exp_jitr=0;
+ *exp_lim=0;
+ *exp_saa=0;
+ *expnight=0;
+
+
+
+ npts = cf_read_col(infits, TFLOAT, "TIME" , (void **) &i_time);
+ npts = cf_read_col(infits, TBYTE , "STATUS_FLAGS" , (void **) &i_status_flags);
+ npts = cf_read_col(infits, TFLOAT, "TIME_SUNRISE" , (void **) &i_time_sunrise);
+ npts = cf_read_col(infits, TFLOAT, "TIME_SUNSET" , (void **) &i_time_sunset);
+ npts = cf_read_col(infits, TFLOAT, "LIMB_ANGLE" , (void **) &i_limb_angle);
+ npts = cf_read_col(infits, TFLOAT, "LONGITUDE" , (void **) &i_longitude);
+ npts = cf_read_col(infits, TFLOAT, "LATITUDE" , (void **) &i_latitude);
+ npts = cf_read_col(infits, TFLOAT, "ORBITAL_VEL" , (void **) &i_orbital_vel);
+ npts = cf_read_col(infits, TSHORT, "HIGH_VOLTAGE" , (void **) &i_high_voltage);
+ npts = cf_read_col(infits, TSHORT, "LIF_CNT_RATE" , (void **) &i_lif_cnt_rate);
+ npts = cf_read_col(infits, TSHORT, "SIC_CNT_RATE" , (void **) &i_sic_cnt_rate);
+ npts = cf_read_col(infits, TSHORT, "FEC_CNT_RATE" , (void **) &i_fec_cnt_rate);
+ npts = cf_read_col(infits, TSHORT, "AIC_CNT_RATE" , (void **) &i_aic_cnt_rate);
+ npts = cf_read_col(infits, TSHORT, "BKGD_CNT_RATE" , (void **) &i_bkgd_cnt_rate);
+ npts = cf_read_col(infits, TFLOAT, "YCENT_LIF" , (void **) &i_ycent_lif);
+ npts = cf_read_col(infits, TFLOAT, "YCENT_SIC" , (void **) &i_ycent_sic);
+
+
+ o_time = (float *) malloc(npts*sizeof(float));
+ o_status_flags = (char *) malloc(npts*sizeof(char));
+ o_time_sunrise = (float *) malloc(npts*sizeof(float));
+ o_time_sunset = (float *) malloc(npts*sizeof(float));
+ o_limb_angle = (float *) malloc(npts*sizeof(float));
+ o_longitude = (float *) malloc(npts*sizeof(float));
+ o_latitude = (float *) malloc(npts*sizeof(float));
+ o_orbital_vel = (float *) malloc(npts*sizeof(float));
+ o_high_voltage = (short *) malloc(npts*sizeof(short));
+ o_lif_cnt_rate = (short *) malloc(npts*sizeof(short));
+ o_sic_cnt_rate = (short *) malloc(npts*sizeof(short));
+ o_fec_cnt_rate = (short *) malloc(npts*sizeof(short));
+ o_aic_cnt_rate = (short *) malloc(npts*sizeof(short));
+ o_bkgd_cnt_rate = (short *) malloc(npts*sizeof(short));
+ o_ycent_lif = (float *) malloc(npts*sizeof(float));
+ o_ycent_sic = (float *) malloc(npts*sizeof(float));
+
+
+ vinf=(phase*Period)/((float)Nout);
+ vsup=((phase+1)*Period)/((float)Nout);
+
+
+ for (i=0;i<npts;i++){
+
+ if (_isinphase(i_time[i], RefTime, Period, vinf, vsup)) {
+
+ o_time[nseconds] = i_time[i];
+ o_status_flags[nseconds] = i_status_flags[i];
+ o_time_sunrise[nseconds] = i_time_sunrise[i];
+ o_time_sunset[nseconds] = i_time_sunset[i];
+ o_limb_angle[nseconds] = i_limb_angle[i];
+ o_longitude[nseconds] = i_longitude[i];
+ o_latitude[nseconds] = i_latitude[i];
+ o_orbital_vel[nseconds] = i_orbital_vel[i];
+ o_high_voltage[nseconds] = i_high_voltage[i];
+ o_lif_cnt_rate[nseconds] = i_lif_cnt_rate[i];
+ o_sic_cnt_rate[nseconds] = i_sic_cnt_rate[i];
+ o_fec_cnt_rate[nseconds] = i_fec_cnt_rate[i];
+ o_aic_cnt_rate[nseconds] = i_aic_cnt_rate[i];
+ o_bkgd_cnt_rate[nseconds] = i_bkgd_cnt_rate[i];
+ o_ycent_lif[nseconds] = i_ycent_lif[i];
+ o_ycent_sic[nseconds] = i_ycent_sic[i];
+
+ timeflgs=i_status_flags[i];
+
+ switch(daynight[0]) {
+ case 'D':
+ time_test=timeflgs^TEMPORAL_DAY;
+ break;
+ case 'N':
+ time_test=timeflgs;
+ break;
+ default:
+ time_test=timeflgs&(~TEMPORAL_DAY);
+ }
+
+
+ if (time_test==0) {
+
+ *exptime+=1.0;
+
+ if (!(timeflgs & TEMPORAL_DAY))
+ *expnight+=1.0;
+
+ } else {
+
+ *exp_bad+=1.0;
+
+ if (timeflgs & TEMPORAL_BRST)
+ *exp_brst+=1.0;
+
+ if (timeflgs & TEMPORAL_HV)
+ *exp_hv=+1.0;
+
+ if (timeflgs & TEMPORAL_JITR)
+ *exp_jitr=+1.0;
+
+ if (timeflgs & TEMPORAL_LIMB)
+ *exp_lim=+1.0;
+
+ if (timeflgs & TEMPORAL_SAA)
+ *exp_saa=+1.0;
+
+ }
+
+ nseconds++;
+ }
+ }
+
+ /* Generate the tform array */
+ sprintf(fmt_byte, "%ldB", nseconds);
+ sprintf(fmt_float, "%ldE", nseconds);
+ sprintf(fmt_short, "%ldI", nseconds);
+
+
+ tform[0] = fmt_float;
+ tform[1] = fmt_byte;
+
+ for (i=2; i<tfields; i++) tform[i] = fmt_short;
+
+ /* Set TSCALE and TZERO values */
+ /* Not all of these will be used; see below. */
+ for (i=2; i<tfields; i++) {
+ sprintf(tscal[i].keyword, "TSCAL%ld", i+1);
+ tscal[i].value = 0.1;
+ sprintf(tzero[i].keyword, "TZERO%ld", i+1);
+ tzero[i].value = 0.;
+ }
+
+ /* Need TZEROn = 3000. for tsunrise and tsunset. */
+ tzero[2].value = tzero[3].value = 3000.;
+
+ /* Let's keep three significant figures for vorb. */
+ tscal[7].value = 0.01;
+
+ /* FEC_CNT_RATE and AIC_CNT_RATE can get big, so we
+ (essentially) store them as unsigned shorts. */
+ tscal[11].value = 1;
+ tscal[12].value = 1;
+ tzero[11].value = 32768;
+ tzero[12].value = 32768;
+
+
+ if (bigtime) {
+ tform[2]=tform[3]=fmt_float;
+ }
+
+ if (big_vel) tform[7]=fmt_float;
+
+ /* Append a new empty binary table to the output file */
+ FITS_create_tbl(outfits, BINARY_TBL, 1, tfields, ttype, tform,
+ tunit, extname, &status);
+
+
+
+ /* Write TSCALE and TZERO entries to header */
+ for (i=2; i<tfields; i++) {
+
+ /* If bigtime is TRUE, store tsunrise and tsunset as floats.*/
+ if ((i == 2 || i == 3) && bigtime) continue;
+
+ if ((i==7)&&(big_vel)) continue;
+
+ /* Omit TSCALE and TZERO for these four arrays. */
+ if (i == 8) continue; /* HIGH_VOLTAGE */
+ if (i == 9) continue; /* LIF_CNT_RATE */
+ if (i == 10) continue; /* SIC_CNT_RATE */
+ if (i == 13) continue; /* BKGD_CNT_RATE */
+
+
+ sprintf(keyword, "TUNIT%ld", i+1);
+ if (fits_read_keyword(outfits, keyword, card, NULL, &status))
+ cf_if_fits_error(status);
+ FITS_insert_key_flt(outfits, tscal[i].keyword, tscal[i].value,
+ -1, NULL, &status);
+ FITS_insert_key_flt(outfits, tzero[i].keyword, tzero[i].value,
+ -5, NULL, &status);
+ }
+
+ if (nseconds > 0) {
+
+ FITS_write_col(outfits, TFLOAT, 1, 1, 1, nseconds, o_time , &status);
+ FITS_write_col(outfits, TBYTE , 2, 1, 1, nseconds, o_status_flags , &status);
+ FITS_write_col(outfits, TFLOAT, 3, 1, 1, nseconds, o_time_sunrise , &status);
+ FITS_write_col(outfits, TFLOAT, 4, 1, 1, nseconds, o_time_sunset , &status);
+ FITS_write_col(outfits, TFLOAT, 5, 1, 1, nseconds, o_limb_angle , &status);
+ FITS_write_col(outfits, TFLOAT, 6, 1, 1, nseconds, o_longitude , &status);
+ FITS_write_col(outfits, TFLOAT, 7, 1, 1, nseconds, o_latitude , &status);
+ FITS_write_col(outfits, TFLOAT, 8, 1, 1, nseconds, o_orbital_vel , &status);
+ FITS_write_col(outfits, TSHORT, 9, 1, 1, nseconds, o_high_voltage , &status);
+ FITS_write_col(outfits, TSHORT, 10, 1, 1, nseconds, o_lif_cnt_rate , &status);
+ FITS_write_col(outfits, TSHORT, 11, 1, 1, nseconds, o_sic_cnt_rate , &status);
+ FITS_write_col(outfits, TSHORT, 12, 1, 1, nseconds, o_fec_cnt_rate , &status);
+ FITS_write_col(outfits, TSHORT, 13, 1, 1, nseconds, o_aic_cnt_rate , &status);
+ FITS_write_col(outfits, TSHORT, 14, 1, 1, nseconds, o_bkgd_cnt_rate , &status);
+ FITS_write_col(outfits, TFLOAT, 15, 1, 1, nseconds, o_ycent_lif , &status);
+ FITS_write_col(outfits, TFLOAT, 16, 1, 1, nseconds, o_ycent_sic , &status);
+
+ }
+
+ free(o_time);
+ free(o_status_flags);
+ free(o_time_sunrise);
+ free(o_time_sunset);
+ free(o_limb_angle);
+ free(o_longitude);
+ free(o_latitude);
+ free(o_orbital_vel);
+ free(o_high_voltage);
+ free(o_lif_cnt_rate);
+ free(o_sic_cnt_rate);
+ free(o_fec_cnt_rate);
+ free(o_aic_cnt_rate);
+ free(o_bkgd_cnt_rate);
+ free(o_ycent_lif);
+ free(o_ycent_sic);
+
+ free(i_time);
+ free(i_status_flags);
+ free(i_time_sunrise);
+ free(i_time_sunset);
+ free(i_limb_angle);
+ free(i_longitude);
+ free(i_latitude);
+ free(i_orbital_vel);
+ free(i_high_voltage);
+ free(i_lif_cnt_rate);
+ free(i_sic_cnt_rate);
+ free(i_fec_cnt_rate);
+ free(i_aic_cnt_rate);
+ free(i_bkgd_cnt_rate);
+ free(i_ycent_lif);
+ free(i_ycent_sic);
+
+ return nseconds;
+}
+/****************************************************************************/
+
+
+int main(int argc,char *argv[]){
+ time_t vtime;
+ char stime[FLEN_CARD];
+
+ fitsfile * infits;
+ fitsfile * outfits;
+
+ filename input_filename,output_filename, ifname;
+
+ char string0[FLEN_CARD], daynight[FLEN_CARD];
+
+
+
+ long nevents;
+ long nseconds;
+ long ngtis;
+
+ long nbadevnt;
+ long nbadpha;
+
+ double exptime;
+ double exp_bad;
+ double exp_brst;
+ double exp_hv;
+ double exp_jitr;
+ double exp_lim;
+ double exp_saa;
+ double expnight;
+
+ double RefTime;
+ double Period;
+ long Nout;
+
+ double expstart;
+
+ long i;
+
+ int optc;
+
+ char opts[] = "hmv:";
+ char usage[] =
+ "Usage:\n"
+ " idf_cut [-hm] [-v level] idf_file RefTime Period Nout\n";
+ char argument[] =
+ "Arguments:\n"
+ " RefTime : Reference Time in seconds since EXPSTART\n"
+ " Period : Period in seconds\n"
+ " Nout : Number of output files.\n";
+ char option[] =
+ "Options:\n"
+ " -m: interprets RefTime as MJD\n"
+ " -h: this help message\n"
+ " -v: verbosity level (=1; 0 is silent)\n";
+
+ int hdutype=0;
+ int status=0;
+ int rtime_mjd=0;
+ verbose_level = 1;
+
+ /* Check number of options and arguments */
+ while ((optc = getopt(argc, argv, opts)) != -1) {
+ switch(optc) {
+ case 'h':
+ printf("%s\n%s\n%s", usage, argument, option);
+ return 0;
+ case 'v':
+ verbose_level = atoi(optarg);
+ break;
+ case 'm':
+ rtime_mjd=1;
+ break;
+ }
+ }
+
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+ if (argc != optind+4) {
+ printf("%s", usage);
+ cf_if_error("Incorrect number of arguments");
+ }
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Started execution.");
+
+ /* get and display time */
+ vtime = time(NULL) ;
+ strcpy(stime,ctime(&vtime));
+
+ strcpy(input_filename,argv[optind]);
+
+ sscanf(argv[optind+1],"%lf",&RefTime);
+ sscanf(argv[optind+2],"%lf",&Period);
+ sscanf(argv[optind+3],"%ld",&Nout);
+
+ FITS_open_file(&infits,input_filename,READONLY,&status);
+ FITS_read_key(infits,TSTRING,"DAYNIGHT",daynight,NULL,&status);
+ FITS_read_key(infits,TSTRING,"FILENAME",ifname,NULL,&status);
+
+ if (rtime_mjd){
+ FITS_read_key(infits,TDOUBLE,"EXPSTART",&expstart,NULL,&status);
+ RefTime=(RefTime-expstart)*3600.0*24.0;
+ }
+
+ for (i=0;i<Nout;i++){
+ FITS_movabs_hdu(infits,1,&hdutype,&status);
+
+
+ strcpy(output_filename,ifname);
+ sprintf(string0,".p%ld.fit",i);
+ strcat(output_filename,string0);
+
+ FITS_create_file(&outfits,output_filename,&status);
+ FITS_copy_hdu(infits,outfits,0,&status);
+
+ FITS_update_key(outfits,TSTRING,"FILENAME",output_filename,NULL,&status);
+
+ cf_verbose(1,"Phase: %ld/%ld",i+1,Nout);
+
+ cf_verbose(2,"Creating Events List");
+ /* Create Events List */
+ FITS_movabs_hdu(infits,2,&hdutype,&status);
+ nevents=make_evlist(infits, outfits, RefTime, Period, Nout, i, daynight,
+ &nbadevnt, &nbadpha);
+ cf_verbose(2,"Number of Events: %ld",nevents);
+
+ cf_verbose(2,"Creating GTI table");
+ /* Create GTIs Table */
+ FITS_movabs_hdu(infits,3,&hdutype,&status);
+ ngtis=make_gtitab(infits, outfits, RefTime, Period, Nout, i);
+ cf_verbose(2,"Number of GTIs: %ld",ngtis);
+
+ cf_verbose(2,"Creating Timeline");
+ /* Create Timeline */
+ FITS_movabs_hdu(infits,4,&hdutype,&status);
+ nseconds=make_timeline(infits, outfits, RefTime, Period, Nout, i, daynight,
+ &exptime, &exp_bad, &exp_brst, &exp_hv, &exp_jitr,
+ &exp_lim, &exp_saa, &expnight);
+ cf_verbose(2,"Number of records in timeline: %ld",nseconds);
+
+
+ /* Update Main Header Keyword */
+ FITS_movabs_hdu(outfits,1,&hdutype,&status);
+
+
+ FITS_update_key(outfits,TDOUBLE ,"EXPTIME" ,&exptime ,NULL,&status);
+ FITS_update_key(outfits,TLONG ,"RAWTIME" ,&nseconds ,NULL,&status);
+ FITS_update_key(outfits,TLONG ,"NEVENTS" ,&nevents ,NULL,&status);
+ FITS_update_key(outfits,TLONG ,"NBADEVNT" ,&nbadevnt ,NULL,&status);
+ FITS_update_key(outfits,TLONG ,"NBADPHA" ,&nbadpha ,NULL,&status);
+ FITS_update_key(outfits,TDOUBLE ,"EXP_BAD" ,&exp_bad ,NULL,&status);
+ FITS_update_key(outfits,TDOUBLE ,"EXP_SAA" ,&exp_saa ,NULL,&status);
+ FITS_update_key(outfits,TDOUBLE ,"EXP_LIM" ,&exp_lim ,NULL,&status);
+ FITS_update_key(outfits,TDOUBLE ,"EXP_BRST" ,&exp_brst ,NULL,&status);
+ FITS_update_key(outfits,TDOUBLE ,"EXP_JITR" ,&exp_jitr ,NULL,&status);
+ FITS_update_key(outfits,TDOUBLE ,"EXPNIGHT" ,&expnight ,NULL,&status);
+
+ FITS_close_file(outfits,&status);
+ }
+ FITS_close_file(infits,&status);
+
+ return (status);
+}
diff --git a/src/analysis/idf_screen.c b/src/analysis/idf_screen.c
new file mode 100644
index 0000000..31aa022
--- /dev/null
+++ b/src/analysis/idf_screen.c
@@ -0,0 +1,339 @@
+
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: idf_screen infits outfits timeflag value
+ *
+ *
+ *
+ * History: 10/05/04 bjg 1.0 Begin work.
+ * 10/26/04 bjg 1.1 Updates important header
+ * keywords.
+ *
+ ****************************************************************************/
+
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include "calfuse.h"
+
+
+typedef char filename[FLEN_CARD];
+
+struct key {
+ char keyword[FLEN_KEYWORD];
+ float value;
+};
+
+static char CF_PRGM_ID[]= "idf_screen";
+static char CF_VER_NUM[]= "1.1";
+
+int main(int argc,char *argv[]){
+
+ char tempstring[FLEN_CARD];
+ char daynight[FLEN_CARD];
+ char * corrected_filename;
+ char * string_pointer;
+
+ char time_test;
+
+ int status=0;
+ int hdutype=0;
+
+ long i, npts;
+
+ char * tflags, * lflags;
+
+ fitsfile *infits , *outfits;
+
+ filename input_fname , output_fname;
+
+ char selstr1[FLEN_CARD];
+ char selstr2[FLEN_CARD];
+
+ char sel1;
+ int sel2;
+
+ long nbadevnt=0;
+ long nbadpha=0;
+
+ double exptime=0.0;
+ double exp_bad=0.0;
+ double exp_brst=0.0;
+ double exp_hv=0.0;
+ double exp_jitr=0.0;
+ double exp_lim=0.0;
+ double exp_saa=0.0;
+ double expnight=0.0;
+
+ int optc;
+
+ char opts[] = "hv:";
+ char usage[] =
+ "Usage:\n"
+ " idf_screen [-h] [-v level] input_idf_file output_idf_file \n"
+ " timeflag value\n";
+ char argument[] =
+ "Arguments :\n"
+ " timeflag : USER/JITR/OPUS/BRST/HV/SAA/LIMB/DAY \n"
+ " value : GOOD/BAD/EITHER \n";
+ char option[] =
+ "Options:\n"
+ " -h: this help message\n"
+ " -v: verbosity level (=1; 0 is silent)\n";
+
+ verbose_level = 1;
+
+ /* Check number of options and arguments */
+ while ((optc = getopt(argc, argv, opts)) != -1) {
+ switch(optc) {
+ case 'h':
+ printf("%s\n%s\n%s", usage, argument, option);
+ return 0;
+ case 'v':
+ verbose_level = atoi(optarg);
+ break;
+ }
+ }
+
+
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+ if (argc != optind+4) {
+ printf("%s", usage);
+ cf_if_error("Incorrect number of arguments");
+ }
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Started execution.");
+
+
+ strcpy(input_fname,argv[optind]);
+ strcpy(output_fname,argv[optind+1]);
+ strcpy(selstr1,argv[optind+2]);
+ strcpy(selstr2,argv[optind+3]);
+
+
+
+ if (!strcasecmp(selstr2,"GOOD")) {
+ sel2=0;
+ } else if (!strcasecmp(selstr2,"BAD")) {
+ sel2=1;
+ } else if (!strcasecmp(selstr2,"EITHER")) {
+ sel2=2;
+ } else {
+ printf("%s", usage);
+ cf_if_error("VALUE not recognized.");
+ }
+
+
+ if (!strcasecmp(selstr1,"USER")) {
+ sel1=TEMPORAL_USER;
+ } else if (!strcasecmp(selstr1,"JITR")) {
+ sel1=TEMPORAL_JITR;
+ } else if (!strcasecmp(selstr1,"OPUS")) {
+ sel1=TEMPORAL_OPUS;
+ } else if (!strcasecmp(selstr1,"BRST")) {
+ sel1=TEMPORAL_BRST;
+ } else if (!strcasecmp(selstr1,"HV")) {
+ sel1=TEMPORAL_HV;
+ } else if (!strcasecmp(selstr1,"SAA")) {
+ sel1=TEMPORAL_SAA;
+ } else if (!strcasecmp(selstr1,"LIMB")) {
+ sel1=TEMPORAL_LIMB;
+ } else if (!strcasecmp(selstr1,"DAY")) {
+ sel1=TEMPORAL_DAY;
+ } else {
+ printf("%s", usage);
+ cf_if_error("TIMEFLAG not recognized.");
+ }
+
+ cf_verbose(1,"Input Filename : %s",input_fname);
+ cf_verbose(1,"Output Filename : %s",output_fname);
+ cf_verbose(1,"FLAG : %s - %d",selstr1,sel1);
+ cf_verbose(1,"VALUE : %s - %d",selstr2,sel2);
+
+ if ((sel1>1)&&(sel2==0)){
+ cf_verbose(1,"Nothing to do.");
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Finished execution.");
+ return EXIT_SUCCESS;
+ }
+
+ cf_verbose(1,"OPENING INPUT FILE");
+ FITS_open_file(&infits,input_fname,READONLY,&status);
+
+ cf_verbose(1,"CREATING OUTPUT FILE");
+ FITS_create_file(&outfits,output_fname,&status);
+ FITS_copy_hdu(infits,outfits,0,&status);
+
+ string_pointer=strrchr(output_fname,'/');
+ if (string_pointer==NULL) corrected_filename=output_fname;
+ else corrected_filename=&(string_pointer[1]);
+
+ FITS_update_key(outfits,TSTRING,"FILENAME",corrected_filename,NULL,&status);
+
+ strcpy(tempstring,"");
+
+ FITS_update_key(outfits,TSTRING,"BPM_CAL",tempstring,NULL,&status);
+
+ if (sel1 == 1) {
+ switch(sel2) {
+ case 0:
+ strcpy(daynight,"NIGHT");
+ break;
+ case 1:
+ strcpy(daynight,"DAY");
+ break;
+ case 2:
+ strcpy(daynight,"BOTH");
+ break;
+ }
+ FITS_update_key(outfits,TSTRING,"DAYNIGHT",daynight,NULL,&status);
+ } else {
+ FITS_read_key(infits,TSTRING,"DAYNIGHT",daynight,NULL,&status);
+ }
+
+
+ FITS_movabs_hdu(infits,2,&hdutype,&status);
+ FITS_create_hdu(outfits,&status);
+ FITS_copy_hdu(infits,outfits,0,&status);
+
+
+ npts = cf_read_col(outfits, TBYTE, "TIMEFLGS", (void **) &tflags);
+ npts = cf_read_col(outfits, TBYTE, "LOC_FLGS", (void **) &lflags);
+ for (i=0;i<npts;i++){
+ if (sel1>1){
+ if (sel2==1){
+ tflags[i]=(tflags[i])^sel1;
+ } else if (sel2==2){
+ tflags[i]=(tflags[i])&(~sel1);
+ }
+ }
+
+ switch(daynight[0]) {
+ case 'D':
+ time_test=tflags[i]^TEMPORAL_DAY;
+ break;
+ case 'N':
+ time_test=tflags[i];
+ break;
+ default:
+ time_test=tflags[i]&(~TEMPORAL_DAY);
+ }
+
+ if (lflags[i]&LOCATION_PHA){
+ nbadpha++;
+ }
+
+ if ((lflags[i]&~LOCATION_AIR) || (time_test)) {
+ nbadevnt++;
+ }
+ }
+
+ if ((sel1>1)&&(sel2>0)){
+ cf_write_col(outfits, TBYTE, "TIMEFLGS", (void *) tflags, npts);
+ }
+
+ free(tflags);
+ free(lflags);
+
+
+ FITS_movabs_hdu(infits,3,&hdutype,&status);
+ FITS_create_hdu(outfits,&status);
+ FITS_copy_hdu(infits,outfits,0,&status);
+
+
+ FITS_movabs_hdu(infits,4,&hdutype,&status);
+ FITS_create_hdu(outfits,&status);
+ FITS_copy_hdu(infits,outfits,0,&status);
+
+
+ npts = cf_read_col(outfits, TBYTE, "STATUS_FLAGS", (void **) &tflags);
+
+ for (i=0;i<npts;i++){
+ if (sel1>1){
+ if (sel2==1){
+ tflags[i]=(tflags[i])^sel1;
+ } else if (sel2==2){
+ tflags[i]=(tflags[i])&(~sel1);
+ }
+ }
+
+ switch(daynight[0]) {
+ case 'D':
+ time_test=tflags[i]^TEMPORAL_DAY;
+ break;
+ case 'N':
+ time_test=tflags[i];
+ break;
+ default:
+ time_test=tflags[i]&(~TEMPORAL_DAY);
+ }
+
+
+ if (time_test==0) {
+
+ exptime+=1.0;
+
+ if (!(tflags[i] & TEMPORAL_DAY))
+ expnight+=1.0;
+
+ } else {
+
+ exp_bad+=1.0;
+
+ if (tflags[i] & TEMPORAL_BRST)
+ exp_brst+=1.0;
+
+ if (tflags[i] & TEMPORAL_HV)
+ exp_hv=+1.0;
+
+ if (tflags[i] & TEMPORAL_JITR)
+ exp_jitr=+1.0;
+
+ if (tflags[i] & TEMPORAL_LIMB)
+ exp_lim=+1.0;
+
+ if (tflags[i] & TEMPORAL_SAA)
+ exp_saa=+1.0;
+ }
+
+ }
+
+ if ((sel1>1)&&(sel2>0)){
+ cf_write_col(outfits, TBYTE, "STATUS_FLAGS", (void *) tflags, npts);
+ }
+
+ free(tflags);
+
+ /* Update Main Header Keyword */
+ FITS_movabs_hdu(outfits,1,&hdutype,&status);
+
+ FITS_update_key(outfits,TDOUBLE ,"EXPTIME" ,&exptime ,NULL,&status);
+ FITS_update_key(outfits,TLONG ,"NBADEVNT" ,&nbadevnt ,NULL,&status);
+ FITS_update_key(outfits,TLONG ,"NBADPHA" ,&nbadpha ,NULL,&status);
+ FITS_update_key(outfits,TDOUBLE ,"EXP_BAD" ,&exp_bad ,NULL,&status);
+ FITS_update_key(outfits,TDOUBLE ,"EXP_SAA" ,&exp_saa ,NULL,&status);
+ FITS_update_key(outfits,TDOUBLE ,"EXP_LIM" ,&exp_lim ,NULL,&status);
+ FITS_update_key(outfits,TDOUBLE ,"EXP_BRST" ,&exp_brst ,NULL,&status);
+ FITS_update_key(outfits,TDOUBLE ,"EXP_JITR" ,&exp_jitr ,NULL,&status);
+ FITS_update_key(outfits,TDOUBLE ,"EXPNIGHT" ,&expnight ,NULL,&status);
+
+ cf_verbose(1,"CLOSING INPUT FILE");
+ FITS_close_file(infits,&status);
+
+ cf_verbose(1,"CLOSING OUTPUT FILE");
+ FITS_close_file(outfits,&status);
+
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Finished execution.");
+ return EXIT_SUCCESS;
+
+}
+
+
diff --git a/src/analysis/mjd2hjd.c b/src/analysis/mjd2hjd.c
new file mode 100644
index 0000000..e0ecd18
--- /dev/null
+++ b/src/analysis/mjd2hjd.c
@@ -0,0 +1,129 @@
+
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ *
+ *
+ * Usage:
+ * mjd2hjd [-h] [-v level] mjd ra_h ra_m ra_s dec_d dec_m dec_s
+ *
+ *
+ * Arguments:
+ * mjd : Modified Julian Day
+ * ra_h ra_m ra_s dec_d dec_m dec_s : RA and DEC of target : hh mm ss.s dd mm ss.s
+ *
+ *
+ * Options:
+ * -h: this help message
+ * -v: verbosity level (=1; 0 is silent)
+ *
+ *
+ *
+ *
+ *
+ * History: 10/06/04 bjg v1.0
+ * 10/26/04 bjg v1.1 Cosmetic change
+ *
+ ****************************************************************************/
+
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "calfuse.h"
+
+
+
+#define SECONDS_PER_DAY (24.0*3600.0)
+
+static char CF_PRGM_ID[]= "mjd2hjd";
+static char CF_VER_NUM[]= "1.1";
+
+
+double gethmjd(double, int, int, float, int, int, float);
+
+int main(int argc,char *argv[]){
+
+ int optc;
+
+
+
+ double lighttime;
+ double jd, mjd, hjd, hmjd;
+
+ int rah,ram,decd,decm;
+ float ras,decs;
+
+
+ char opts[] = "hv:";
+ char usage[] =
+ "Usage:\n"
+ " mjd2hjd [-h] [-v level] mjd ra_h ra_m ra_s dec_d dec_m dec_s\n";
+ char argument[] =
+ "Arguments:\n"
+ " mjd : Modified Julian Day.\n"
+ " ra_h ra_m ra_s dec_d dec_m dec_s : RA and DEC of target.\n";
+ char option[] =
+ "Options:\n"
+ " -h: this help message\n"
+ " -v: verbosity level (=1; 0 is silent)\n";
+ verbose_level = 1;
+
+
+ /* Check number of options and arguments */
+ while ((optc = getopt(argc, argv, opts)) != -1) {
+ switch(optc) {
+
+ case 'h':
+ printf("%s\n%s\n%s", usage, argument, option);
+ return EXIT_SUCCESS;
+ case 'v':
+ verbose_level = atoi(optarg);
+ break;
+ }
+ }
+
+ /* Initialize error checking. */
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+ if (argc != optind+7)
+ cf_if_error("%s\nIncorrect number of program arguments", usage);
+
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Started execution.");
+
+ sscanf(argv[optind],"%lf",&mjd);
+ sscanf(argv[optind+1],"%d",&rah);
+ sscanf(argv[optind+2],"%d",&ram);
+ sscanf(argv[optind+3],"%f",&ras);
+ sscanf(argv[optind+4],"%d",&decd);
+ sscanf(argv[optind+5],"%d",&decm);
+ sscanf(argv[optind+6],"%f",&decs);
+
+
+ hmjd=gethmjd(mjd,rah,ram,ras,decd,decs,decm);
+
+ jd = mjd + 2400000.5;
+ hjd = hmjd + 2400000.5;
+
+ lighttime=(hmjd-mjd)*SECONDS_PER_DAY;
+
+ cf_verbose(1,"Right Ascension of target: %d h %d m %f s",rah,ram,ras);
+ cf_verbose(1,"Declination of target: %d deg %d m %f s",decd,decm,decs);
+ cf_verbose(1,"jd= %lf",jd);
+ cf_verbose(1,"mjd= %lf",mjd);
+ cf_verbose(1,"hjd= %lf",hjd);
+ cf_verbose(1,"hmjd= %lf",hmjd);
+ cf_verbose(1,"heliocentric light time correction = %lf s",lighttime);
+ cf_verbose(1,"---positive when Earth is closer to target than Sun");
+ return EXIT_SUCCESS;
+
+}
+
diff --git a/src/analysis/modhead.c b/src/analysis/modhead.c
new file mode 100644
index 0000000..0ffc40b
--- /dev/null
+++ b/src/analysis/modhead.c
@@ -0,0 +1,114 @@
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: modhead file.fit[ext] KEYWORD NEW_VALUE
+ *
+ * Description: Returns or modifies the value of a header keyword.
+ * If NEW_VALUE is not specified, current value of KEYWORD is
+ * returned. If KEYWORD is not found and NEW_VALUE is given,
+ * KEYWORD is added to header. If an extension beyond the
+ * primary HDU is requested, file name must be given in
+ * parentheses: "file.fit[3]" or an alternate construction
+ * used: file.fit+3 Note that the primary HDU is extension 0.
+ *
+ * History: 05/15/05 tc started work
+ * 08/30/05 wvd Allow multi-word strings.
+ *
+ ****************************************************************************/
+
+#include <string.h>
+#include <stdio.h>
+#include "fitsio.h"
+
+int main(int argc, char *argv[])
+{
+ fitsfile *fptr; /* FITS file pointer, defined in fitsio.h */
+ char card[FLEN_CARD], newcard[FLEN_CARD];
+ char oldvalue[FLEN_VALUE], comment[FLEN_COMMENT];
+ int status = 0; /* CFITSIO status value MUST be initialized to zero! */
+ int i, iomode, keytype;
+
+ if (argc == 3)
+ iomode = READONLY;
+ else if (argc >= 4)
+ iomode = READWRITE;
+ else if (argc < 3) {
+ printf("Usage: modhead filename[ext] keyword new_value\n");
+ printf("\n");
+ printf("Write or modify the value of a header keyword.\n");
+ printf("If 'newvalue' is not specified, then just print \n");
+ printf("the current value. \n");
+ printf("\n");
+ printf("Examples: \n");
+ printf(" modhead file.fits dec - list the DEC keyword \n");
+ printf(" modhead file.fits dec 30.0 - set DEC = 30.0 \n");
+ printf("\n");
+ printf(" modhead \"file.fits[2]\" OBSTIME - list OBSTIME from extention 2 \n");
+ printf(" modhead file.fits+2 OBSTIME - list OBSTIME from extention 2\n");
+ return(0);
+ }
+
+ if (!fits_open_file(&fptr, argv[1], iomode, &status))
+ {
+ if (fits_read_card(fptr,argv[2], card, &status))
+ {
+ printf("Keyword does not exist\n");
+ card[0] = '\0';
+ comment[0] = '\0';
+ status = 0; /* reset status after error */
+ }
+ else
+ printf("%s\n",card);
+
+ if (argc >= 4) /* write or overwrite the keyword */
+ {
+ /* check if this is a protected keyword that must not be changed */
+ if (*card && fits_get_keyclass(card) == TYP_STRUC_KEY)
+ {
+ printf("Protected keyword cannot be modified.\n");
+ }
+ else
+ {
+ /* get the comment string */
+ if (*card)fits_parse_value(card, oldvalue, comment, &status);
+
+ /* construct template for new keyword */
+ strcpy(newcard, argv[2]); /* copy keyword name */
+ strcat(newcard, " = "); /* '=' value delimiter */
+ if (argc == 4) strcat(newcard, argv[3]); /* new value */
+ else {
+ strcat(newcard, "'");
+ for (i = 3; i < argc-1; i++) {
+ strcat(newcard, argv[i]); /* new value */
+ strcat(newcard, " ");
+ }
+ strcat(newcard, argv[i]); /* new value */
+ strcat(newcard, "'");
+ }
+
+ if (*comment) {
+ strcat(newcard, " / "); /* comment delimiter */
+ strcat(newcard, comment); /* append the comment */
+ }
+
+ /* reformat the keyword string to conform to FITS rules */
+ fits_parse_template(newcard, card, &keytype, &status);
+
+ /* overwrite the keyword with the new value */
+ fits_update_card(fptr, argv[2], card, &status);
+
+ printf("Keyword has been changed to:\n");
+ printf("%s\n",card);
+ }
+ } /* if argc == 4 */
+ fits_close_file(fptr, &status);
+ } /* open_file */
+
+ /* if error occured, print out error message */
+ if (status) fits_report_error(stderr, status);
+ return(status);
+}
+
diff --git a/src/analysis/remove_target_orbital_motion.c b/src/analysis/remove_target_orbital_motion.c
new file mode 100644
index 0000000..d104b0d
--- /dev/null
+++ b/src/analysis/remove_target_orbital_motion.c
@@ -0,0 +1,503 @@
+
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ *
+ *
+ * Usage:
+ * remove_target_orbital_motion [-hb] [-v level]
+ * input_idf_file output_idf_file
+ * hjd0 period vrmax
+ * [ra_h ra_m ra_s dec_d dec_m dec_s]
+ *
+ * Arguments:
+ * mjd0 : Heliocentric or Geocentric
+ * Julian Day
+ * of closest approch on orbit.
+ * period : Period in seconds.
+ * vrmax : Maximum radial velocity in km/s
+ * ra_h ra_m ra_s dec_d dec_m dec_s : (Optional) RA and DEC of target.
+ * If present mjd0 is interpreted
+ * as Heliocentric.
+ *
+ * Options:
+ * -h: this help message
+ * -v: verbosity level (=1; 0 is silent)
+ * -b: update timeline doppler information (required for BPM)
+ *
+ *
+ * History: 12/01/03 bjg v1.0 Begin work.
+ * 12/02/03 bjg Changed calling
+ * parameters format.
+ * 12/04/03 bjg Number of elements in HDU2
+ * is now determined from HDU2
+ * header instead of HDU1
+ * header NEVENTS keyword
+ * 12/10/03 bjg Updated header.
+ * 04/05/04 bjg Remove unused variables
+ * 06/10/04 bjg Some code cleaning
+ * 10/07/04 bjg v1.1 Added heliocentric
+ * time correction (optional)
+ * Added timeline doppler
+ * correction information
+ * (optional) for cf_bad_pixels
+ * 10/26/04 bjg v1.2 Cosmetic change
+ *
+ ****************************************************************************/
+
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "calfuse.h"
+
+
+
+
+#define LIGHT_SPEED 299792.458 /* speed of light in kilometers per second */
+#define SECONDS_PER_DAY (24.0*3600.0)
+
+static char CF_PRGM_ID[]= "remove_target_orbital_motion";
+static char CF_VER_NUM[]= "1.2";
+
+struct key {
+ char keyword[FLEN_KEYWORD];
+ float value;
+};
+
+
+double gethmjd(double, int, int, float, int, int, float);
+
+int main(int argc,char *argv[]){
+
+
+ char fmt_byte[FLEN_CARD],fmt_float[FLEN_CARD],fmt_short[FLEN_CARD];
+
+ fitsfile * infits;
+ fitsfile * outfits;
+
+ char input_filename[FLEN_CARD],output_filename[FLEN_CARD];
+ char * corrected_filename;
+ char * string_pointer;
+
+ int intnull=0,anynull;
+ int status=0;
+ int hdutype=0;
+ int ncol;
+ char tempstring[FLEN_CARD];
+ char tempchar;
+ char keyword[FLEN_CARD],card[FLEN_CARD];
+
+
+ struct key hdu4_tscal[16];
+ struct key hdu4_tzero[16];
+
+ char hdu4_extname[]="TIMELINE";
+ int hdu4_tfields=16; /* output table will have 16 columns */
+ char *hdu4_ttype[]={"TIME", "STATUS_FLAGS", "TIME_SUNRISE", "TIME_SUNSET",
+ "LIMB_ANGLE", "LONGITUDE", "LATITUDE", "ORBITAL_VEL",
+ "HIGH_VOLTAGE", "LIF_CNT_RATE", "SIC_CNT_RATE",
+ "FEC_CNT_RATE", "AIC_CNT_RATE", "BKGD_CNT_RATE",
+ "YCENT_LIF","YCENT_SIC"};
+
+ char *hdu4_tform[16]; /* we will define tform later, when the number
+ of photons is known */
+
+ char *hdu4_tunit[]={"seconds", "unitless", "seconds", "seconds", "degrees",
+ "degrees", "degrees", "km/s", "unitless", "counts/sec",
+ "counts/sec", "counts/sec", "counts/sec", "counts/sec",
+ "pixels","pixels" };
+
+
+ long nevents, nrecords;
+ long i;
+
+ float * floatlist;
+ short * shortlist;
+ char * charlist;
+
+ double * hdu4_time;
+ double * hdu4_orbvel;
+
+ double * hdu2_time;
+ double * hdu2_lambda;
+
+ double delta_t;
+ double period, vrmax, mjd0;
+ double expstart, mjd;
+
+ int rah,ram,decd,decm;
+ float ras,decs;
+
+ int optc;
+
+ char opts[] = "hbv:";
+
+ char usage[] =
+ "Usage:\n"
+ " remove_target_orbital_motion [-hb] [-v level] \n"
+ " input_idf_file output_idf_file\n"
+ " mjd0 period vrmax\n"
+ " [ra_h ra_m ra_s dec_d dec_m dec_s]\n";
+ char argument[] =
+ "Arguments:\n"
+ " mjd0 : (Geocentric or Heliocentric) Modified Julian Day\n"
+ " of closest approch on orbit.\n"
+ " period : Period in seconds.\n"
+ " vrmax : Maximum radial velocity in km/s\n"
+ " ra_h ra_m ra_s dec_d dec_m dec_s : Optional RA and DEC of target.\n"
+ " If present mjd0 is interpreted\n"
+ " as Heliocentric. \n";
+
+ char option[] =
+ "Options:\n"
+ " -h: this help message\n"
+ " -v: verbosity level (=1; 0 is silent)\n"
+ " -b: update timeline doppler information (required for BPM)\n";
+
+
+
+ int bigtime=1; /* How to store TSUNRISE and TSUNSET" */
+ int do_timeline=0;
+ int helio_corr=0;
+
+ verbose_level = 1;
+
+
+ /* Check number of options and arguments */
+ while ((optc = getopt(argc, argv, opts)) != -1) {
+ switch(optc) {
+ case 'h':
+ printf("%s\n%s\n%s", usage, argument, option);
+ return EXIT_SUCCESS;
+ case 'v':
+ verbose_level = atoi(optarg);
+ break;
+ case 'b':
+ do_timeline=1;
+ break;
+ }
+ }
+
+ /* Initialize error checking. */
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+ if ((argc != optind+11)&&(argc != optind+5))
+ cf_if_error("%s\nIncorrect number of program arguments", usage);
+
+ if (argc==optind+11) helio_corr=1;
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Started execution.");
+
+ strcpy(input_filename,argv[optind]);
+ strcpy(output_filename,argv[optind+1]);
+
+ sscanf(argv[optind+2],"%lf",&mjd0);
+ sscanf(argv[optind+3],"%lf",&period);
+ sscanf(argv[optind+4],"%lf",&vrmax);
+
+ cf_verbose(1,"Target Orbital Motion Doppler Correction");
+ cf_verbose(1,"Processing file %s",input_filename);
+
+ if (helio_corr) {
+ sscanf(argv[optind+5],"%d",&rah);
+ sscanf(argv[optind+6],"%d",&ram);
+ sscanf(argv[optind+7],"%f",&ras);
+ sscanf(argv[optind+8],"%d",&decd);
+ sscanf(argv[optind+9],"%d",&decm);
+ sscanf(argv[optind+10],"%f",&decs);
+ cf_verbose(1,"Right Ascension of target: %d h %d m %f s",rah,ram,ras);
+ cf_verbose(1,"Declination of target: %d deg %d m %f s",decd,decm,decs);
+ cf_verbose(1,"Heliocentric Modified Julian Day of closest approch on orbit: %lf",mjd0);
+ } else {
+ cf_verbose(1,"Geocentric Modified Julian Day of closest approch on orbit: %lf",mjd0);
+ }
+
+ cf_verbose(1,"Period in seconds: %lf",period);
+ cf_verbose(1,"Maximum radial velocity in kilometers per second: %lf",vrmax);
+
+
+
+ FITS_open_file(&infits,input_filename,READONLY,&status);
+ FITS_read_key(infits,TDOUBLE,"EXPSTART",&(expstart),NULL,&status);
+
+ FITS_create_file(&outfits,output_filename,&status);
+ FITS_copy_hdu(infits,outfits,0,&status);
+
+ string_pointer=strrchr(output_filename,'/');
+ if (string_pointer==NULL) corrected_filename=output_filename;
+ else corrected_filename=&(string_pointer[1]);
+
+ FITS_update_key(outfits,TSTRING,"FILENAME",corrected_filename,NULL,&status);
+
+ strcpy(tempstring,"");
+
+ FITS_update_key(outfits,TSTRING,"BPM_CAL",tempstring,NULL,&status);
+
+
+
+ FITS_movabs_hdu(infits,2,&hdutype,&status);
+ FITS_read_key(infits,TSTRING,"TFORM1",tempstring,NULL,&status);
+ sscanf(tempstring,"%ld%c",&nevents,&tempchar);
+
+ FITS_create_hdu(outfits,&status);
+ FITS_copy_hdu(infits,outfits,0,&status);
+
+
+ hdu2_time=(double *)malloc(nevents*sizeof(double));
+ hdu2_lambda=(double *)malloc(nevents*sizeof(double));
+
+
+
+ FITS_get_colnum(infits, TRUE, "TIME", &ncol, &status);
+ FITS_read_col(infits, TDOUBLE, ncol, 1, 1, nevents, &intnull,
+ hdu2_time, &anynull, &status);
+
+ FITS_get_colnum(infits, TRUE, "LAMBDA", &ncol, &status);
+ FITS_read_col(infits, TDOUBLE, ncol, 1, 1, nevents, &intnull,
+ hdu2_lambda, &anynull, &status);
+
+
+
+
+ cf_verbose(1,"Geocentric Modified Julian Day of start of observation/exposure is: %f",expstart);
+ if (helio_corr) {
+ mjd=gethmjd(expstart,rah,ram,ras,decd,decm,decs);
+ cf_verbose(1,"Heliocentric Modified Julian Day of start of observation/exposure is: %f",mjd);
+ }
+
+ for (i=0;i<nevents;i++){
+
+ mjd=expstart+(hdu2_time[i])/SECONDS_PER_DAY;
+
+ if (helio_corr) mjd=gethmjd(mjd,rah,ram,ras,decd,decm,decs);
+
+ delta_t=(mjd-mjd0)*SECONDS_PER_DAY;
+
+ hdu2_lambda[i]=hdu2_lambda[i]*(1-(vrmax/LIGHT_SPEED)*sin(2*M_PI*delta_t/period));
+
+ }
+
+ FITS_get_colnum(outfits, TRUE, "LAMBDA", &ncol, &status);
+ FITS_write_col(outfits, TDOUBLE, ncol, 1, 1, nevents, hdu2_lambda, &status);
+
+
+ free(hdu2_time);
+ free(hdu2_lambda);
+
+
+ FITS_movabs_hdu(infits,3,&hdutype,&status);
+ FITS_create_hdu(outfits,&status);
+ FITS_copy_hdu(infits,outfits,0,&status);
+
+
+ FITS_movabs_hdu(infits,4,&hdutype,&status);
+
+ if (do_timeline) {
+
+ FITS_read_key(infits,TSTRING,"TFORM1",tempstring,NULL,&status);
+ sscanf(tempstring,"%ld%c",&nrecords,&tempchar);
+
+ /* Generate the tform array */
+ sprintf(fmt_byte, "%ldB", nrecords);
+ sprintf(fmt_float, "%ldE", nrecords);
+ sprintf(fmt_short, "%ldI", nrecords);
+
+
+
+ hdu4_tform[0] = fmt_float;
+ hdu4_tform[1] = fmt_byte;
+
+ for (i=2; i<hdu4_tfields; i++) hdu4_tform[i] = fmt_short;
+
+ /* Set TSCALE and TZERO values */
+ /* Not all of these will be used; see below. */
+ for (i=2; i<hdu4_tfields; i++) {
+ sprintf(hdu4_tscal[i].keyword, "TSCAL%ld", i+1);
+ hdu4_tscal[i].value = 0.1;
+ sprintf(hdu4_tzero[i].keyword, "TZERO%ld", i+1);
+ hdu4_tzero[i].value = 0.;
+ }
+
+ /* Need TZEROn = 3000. for tsunrise and tsunset. */
+ hdu4_tzero[2].value = hdu4_tzero[3].value = 3000.;
+
+ /* Let's keep three significant figures for vorb. */
+ hdu4_tscal[7].value = 0.01;
+
+ /* FEC_CNT_RATE and AIC_CNT_RATE can get big, so we
+ (essentially) store them as unsigned shorts. */
+ hdu4_tscal[11].value = 1;
+ hdu4_tscal[12].value = 1;
+ hdu4_tzero[11].value = 32768;
+ hdu4_tzero[12].value = 32768;
+
+
+ if (bigtime) {
+ hdu4_tform[2]=hdu4_tform[3]=fmt_float;
+ }
+
+ hdu4_tform[7]=fmt_float;
+
+ /* Append a new empty binary table to the output file */
+ FITS_create_tbl(outfits, BINARY_TBL, 1, hdu4_tfields, hdu4_ttype, hdu4_tform,
+ hdu4_tunit, hdu4_extname, &status);
+
+
+
+ /* Write TSCALE and TZERO entries to header */
+ for (i=2; i<hdu4_tfields; i++) {
+
+ /* If bigtime is TRUE, store tsunrise and tsunset as floats.*/
+ if ((i == 2 || i == 3) && bigtime) continue;
+
+ /* Omit TSCALE and TZERO for these four arrays. */
+ if (i == 8) continue; /* HIGH_VOLTAGE */
+ if (i == 9) continue; /* LIF_CNT_RATE */
+ if (i == 10) continue; /* SIC_CNT_RATE */
+ if (i == 13) continue; /* BKGD_CNT_RATE */
+
+
+ /* Store ORBITAL_VEL as float */
+ if (i == 7) continue;
+
+
+ sprintf(keyword, "TUNIT%ld", i+1);
+ if (fits_read_keyword(outfits, keyword, card, NULL, &status))
+ cf_if_fits_error(status);
+ FITS_insert_key_flt(outfits, hdu4_tscal[i].keyword, hdu4_tscal[i].value,
+ -1, NULL, &status);
+ FITS_insert_key_flt(outfits, hdu4_tzero[i].keyword, hdu4_tzero[i].value,
+ -5, NULL, &status);
+
+ }
+
+ floatlist=(float *)malloc(nrecords*sizeof(float));
+ shortlist=(short *)malloc(nrecords*sizeof(short));
+ charlist=(char *)malloc(nrecords*sizeof(char));
+ hdu4_time=(double *)malloc(nevents*sizeof(double));
+ hdu4_orbvel=(double *)malloc(nevents*sizeof(double));
+
+ FITS_get_colnum(infits, TRUE, "TIME", &ncol, &status);
+ FITS_read_col(infits, TDOUBLE, ncol, 1, 1, nrecords, &intnull,
+ hdu4_time, &anynull, &status);
+ FITS_write_col(outfits, TDOUBLE, 1, 1, 1, nrecords, hdu4_time, &status);
+
+ FITS_get_colnum(infits, TRUE, "STATUS_FLAGS", &ncol, &status);
+ FITS_read_col(infits, TBYTE, ncol, 1, 1, nrecords, &intnull,
+ charlist, &anynull, &status);
+ FITS_write_col(outfits, TBYTE, 2, 1, 1, nrecords, charlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "TIME_SUNRISE", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecords, &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 3, 1, 1, nrecords, floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "TIME_SUNSET", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecords, &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 4, 1, 1, nrecords, floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "LIMB_ANGLE", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecords, &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 5, 1, 1, nrecords, floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "LONGITUDE", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecords, &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 6, 1, 1, nrecords, floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "LATITUDE", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecords, &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 7, 1, 1, nrecords, floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "ORBITAL_VEL", &ncol, &status);
+ FITS_read_col(infits, TDOUBLE, ncol, 1, 1, nrecords, &intnull,
+ hdu4_orbvel, &anynull, &status);
+
+ for (i=0;i<nrecords;i++){
+
+ mjd=expstart+(hdu4_time[i])/SECONDS_PER_DAY;
+
+ if (helio_corr) mjd=gethmjd(mjd,rah,ram,ras,decd,decm,decs);
+
+ delta_t=(mjd-mjd0)*SECONDS_PER_DAY;
+
+ hdu4_orbvel[i]=hdu4_orbvel[i]-vrmax*sin(2*M_PI*delta_t/period);
+
+ }
+
+
+ FITS_write_col(outfits, TDOUBLE, 8, 1, 1, nrecords, hdu4_orbvel, &status);
+
+ FITS_get_colnum(infits, TRUE, "HIGH_VOLTAGE", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecords, &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 9, 1, 1, nrecords, floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "LIF_CNT_RATE", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecords, &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 10, 1, 1, nrecords, floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "SIC_CNT_RATE", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecords, &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 11, 1, 1, nrecords, floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "FEC_CNT_RATE", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecords, &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 12, 1, 1, nrecords, floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "AIC_CNT_RATE", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecords, &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 13, 1, 1, nrecords, floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "BKGD_CNT_RATE", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecords, &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 14, 1, 1, nrecords, floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "YCENT_LIF", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecords, &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 15, 1, 1, nrecords, floatlist, &status);
+
+ FITS_get_colnum(infits, TRUE, "YCENT_SIC", &ncol, &status);
+ FITS_read_col(infits, TFLOAT, ncol, 1, 1, nrecords, &intnull,
+ floatlist, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 16, 1, 1, nrecords, floatlist, &status);
+
+
+ free(hdu4_time);
+ free(hdu4_orbvel);
+
+ free(floatlist);
+ free(charlist);
+ free(shortlist);
+
+ } else {
+ FITS_create_hdu(outfits,&status);
+ FITS_copy_hdu(infits,outfits,0,&status);
+ }
+
+ FITS_close_file(infits,&status);
+ FITS_close_file(outfits,&status);
+
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Finished execution.");
+ return EXIT_SUCCESS;
+
+}
+
diff --git a/src/analysis/ttag_combine.c b/src/analysis/ttag_combine.c
new file mode 100644
index 0000000..77da230
--- /dev/null
+++ b/src/analysis/ttag_combine.c
@@ -0,0 +1,520 @@
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: ttag_combine outfile file1 file2 file3 file4 file5 ...
+ *
+ * Description: Reads multiple contiguous ttag files and concatenates them
+ * into a single file. For now, the input files should be
+ * listed in time order.
+ *
+ * History: 08/16/99 emurphy Begin work
+ * 08/27/99 emurphy Added comments. Good time intervals
+ * now match observing times.
+ * 10/09/99 emurphy exptime now sum of individual exptimes
+ * 08/20/01 v1.2 wvd Complain if FPA moves between exposures.
+ * Set MAXGTI = 2000.
+ * 10/01/01 v1.3 RDR Update all segment and active image counters
+ * DATE keyword now contains the date
+ * NEVENTS reflects total number of events in
+ * combined file
+ * EXP_ID defaults to 999 to signify combined
+ * data
+ * Print warning if FPA x position changes
+ * by more than 30 microns
+ * PLANTIME now reflects total planned exposure
+ * Will transfer DX, DY and DNFLG columns
+ * if available
+ * 10/09/01 v1.4 wvd Delete redundant check for FPA splits.
+ * Program complains if input files not in
+ * time order.
+ * 01/15/02 v1.5 wvd Update keyword EXPNIGHT.
+ * 02/13/02 v1.6 wvd Respond gracefully if EXPNIGHT does not exist.
+ * 02/20/02 wvd Update keyword RAWTIME, if it exists.
+ * 04/26/02 v1.7 wvd Change vtime to type time_t
+ * 12/11/02 v1.8 wvd Change EXPNIGHT to type long
+ * 02/20/03 v1.9 wvd Correct errors in pointer use.
+ * Change abs() to fabs().
+ * 03/22/04 v1.10 bjg Change cf_fpa_pos() to cf_read_fpa_pos()
+ * 04/05/04 v1.11 bjg Include math.h
+ * Remove unused variables
+ * Change formats to match arg type
+ * in printf
+ *
+ *
+ ****************************************************************************/
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <math.h>
+#include "calfuse.h"
+
+static char CF_PRGM_ID[] = "ttag_combine";
+static char CF_VER_NUM[] = "1.11";
+
+#define MAXGTI 2000 /* Maximum number of good time intervals */
+
+static int
+cf_dtcor_read_counters(fitsfile *infits, long *de, long *fe, long *ai1a,
+ long *ai1b, long *ai2a, long *ai2b, long *sic, long *lif, long *as,
+ double *ctm )
+{
+ char cntstr[FLEN_CARD], detstr[FLEN_CARD];
+ long de_b, de_e, fe_b, fe_e;
+ long ai1a_b, ai1a_e, ai1b_b, ai1b_e, ai2a_b, ai2a_e, ai2b_b, ai2b_e ;
+ long sic_b, sic_e, lif_b, lif_e, as_b, as_e ;
+ double ctm_b, ctm_e ;
+ int status=0;
+
+ FITS_read_key(infits, TSTRING, "DETECTOR", detstr, NULL, &status);
+
+ /* Segment 1A Counters */
+
+ sprintf(cntstr, "%1.1s%2.2s%4.4s","C",detstr,"DE_B");
+ FITS_read_key(infits, TLONG, cntstr, &de_b, NULL, &status);
+
+ sprintf(cntstr, "%1.1s%2.2s%4.4s","C",detstr,"DE_E");
+ FITS_read_key(infits, TLONG, cntstr, &de_e, NULL, &status);
+
+ sprintf(cntstr, "%1.1s%2.2s%4.4s","C",detstr,"FE_B");
+ FITS_read_key(infits, TLONG, cntstr, &fe_b, NULL, &status);
+
+ sprintf(cntstr, "%1.1s%2.2s%4.4s","C",detstr,"FE_E");
+ FITS_read_key(infits, TLONG, cntstr, &fe_e, NULL, &status);
+
+ sprintf(cntstr, "%1.1s%2.2s%5.5s","C",detstr,"SIC_B");
+ FITS_read_key(infits, TLONG, cntstr, &sic_b, NULL, &status);
+
+ sprintf(cntstr, "%1.1s%2.2s%5.5s","C",detstr,"SIC_E");
+ FITS_read_key(infits, TLONG, cntstr, &sic_e, NULL, &status);
+
+ sprintf(cntstr, "%1.1s%2.2s%5.5s","C",detstr,"LIF_B");
+ FITS_read_key(infits, TLONG, cntstr, &lif_b, NULL, &status);
+
+ sprintf(cntstr, "%1.1s%2.2s%5.5s","C",detstr,"LIF_E");
+ FITS_read_key(infits, TLONG, cntstr, &lif_e, NULL, &status);
+
+ sprintf(cntstr, "%1.1s%2.2s%4.4s","C",detstr,"AS_B");
+ FITS_read_key(infits, TLONG, cntstr, &as_b, NULL, &status);
+
+ sprintf(cntstr, "%1.1s%2.2s%4.4s","C",detstr,"AS_E");
+ FITS_read_key(infits, TLONG, cntstr, &as_e, NULL, &status);
+
+ /* Active Image Counters */
+ FITS_read_key(infits, TLONG, "C1AAI_B", &ai1a_b, NULL, &status);
+ FITS_read_key(infits, TLONG, "C1AAI_E", &ai1a_e, NULL, &status);
+ FITS_read_key(infits, TLONG, "C1BAI_B", &ai1b_b, NULL, &status);
+ FITS_read_key(infits, TLONG, "C1BAI_E", &ai1b_e, NULL, &status);
+ FITS_read_key(infits, TLONG, "C2AAI_B", &ai2a_b, NULL, &status);
+ FITS_read_key(infits, TLONG, "C2AAI_E", &ai2a_e, NULL, &status);
+ FITS_read_key(infits, TLONG, "C2BAI_B", &ai2b_b, NULL, &status);
+ FITS_read_key(infits, TLONG, "C2BAI_E", &ai2b_e, NULL, &status);
+ FITS_read_key(infits, TDOUBLE, "CTIME_B", &ctm_b, NULL, &status);
+ FITS_read_key(infits, TDOUBLE, "CTIME_E", &ctm_e, NULL, &status);
+
+
+ *de = de_e - de_b;
+ *fe= fe_e - fe_b;
+ *ai1a = ai1a_e - ai1a_b ;
+ *ai1b = ai1b_e - ai1b_b ;
+ *ai2a = ai2a_e - ai2a_b ;
+ *ai2b = ai2b_e - ai2b_b ;
+ *sic = sic_e - sic_b ;
+ *lif = lif_e - lif_b ;
+ *as = as_e - as_b ;
+ *ctm = ctm_e - ctm_b ;
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int i, j, k;
+ char buffer[FLEN_CARD], comment[FLEN_CARD], stime[FLEN_CARD];
+ char cntstr[FLEN_CARD], detstr[FLEN_CARD];
+ char expid[FLEN_CARD], procstep[FLEN_CARD] ;
+ long de, fe, de_tot, fe_tot, fe_b, de_b, fe_e, de_e;
+ long ai1a, ai1b, ai2a, ai2b, ai1a_tot, ai1b_tot, ai2a_tot;
+ long ai2b_tot,ai1a_b, ai1a_e, ai1b_b, ai1b_e, ai2a_b ;
+ long ai2a_e, ai2b_b, ai2b_e, sic_b, sic_e, sic_tot, sic ;
+ long lif_b, lif_e, lif_tot, lif, as_b, as_e, as_tot, as ;
+ long expnight, indnight;
+ int status=0, nfiles=0, hdutype=0, nkeys, keynum, anynull;
+ fitsfile *infits, *outfits;
+ long nevents, jrow, ngti, ngti_in;
+ char *pha_in, *dnflg ;
+ short *x_in, *y_in;
+ float *time_in, *gti_start, *gti_stop;
+ float *gti_start_in, *gti_stop_in, *dx, *dy ;
+ float fpasx0, fpasx, fpalx0, fpalx, dfpasx, dfpalx ;
+ double mjd_init, mjd_start, mjd_end, exptime, mjd_last=0, indtime;
+ double rawtime, trawtime;
+ double ctm, ctm_b, ctm_e, ctm_tot ;
+ int plantime, procflg ;
+ long tplantime ;
+ int tcol_in, xcol_in, ycol_in, phacol_in, startcol ,stopcol;
+ int tcol_out, xcol_out, ycol_out, phacol_out;
+ int dxcol_in, dxcol_out, dycol_in, dycol_out,dnflgcol_in;
+ int dnflgcol_out ;
+ int fpa_split = FALSE;
+ time_t vtime;
+
+
+ if (argc < 3) {
+ printf("Incorrect number of arguments.\n");
+ printf("Calling sequence:ttag_combine output_file input_file1 input_file2 input_file3 ...\n");
+ exit(1);
+ }
+
+ /* Initialize error checking. */
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Started execution.");
+
+ /* get and display time */
+ vtime = time(NULL) ;
+ strcpy(stime,ctime(&vtime)) ;
+
+ jrow=1;
+ de_tot=0 ;
+ fe_tot=0 ;
+ ai1a_tot=0 ;
+ ai1b_tot=0 ;
+ ai2a_tot=0 ;
+ ai2b_tot=0 ;
+ sic_tot=0 ;
+ lif_tot=0 ;
+ as_tot=0 ;
+ ctm_tot=0. ;
+ procflg=-1 ;
+ gti_start = (float *) cf_malloc(sizeof(float) * 1000);
+ gti_stop = (float *) cf_malloc(sizeof(float) * 1000);
+
+ gti_start[0] = 0.0;
+ gti_stop[0] = 0.0;
+
+ nfiles = argc-1;
+
+ exptime=0.0;
+ expnight=0;
+ trawtime=0.0;
+ tplantime=0;
+
+ ngti=0; /* is the number of new good time intervals */
+
+ for (i=2; i<=nfiles; i++) {
+ printf("Processing %-60.60s\n",argv[i]);
+ FITS_open_file(&infits, argv[i], READONLY, &status);
+
+ if (i==2) {
+ FITS_read_key(infits, TDOUBLE, "EXPSTART", &mjd_init,
+ NULL, &status);
+ mjd_last=mjd_start=mjd_init;
+ FITS_read_key(infits, TDOUBLE, "EXPEND", &mjd_end,
+ NULL, &status);
+ FITS_read_key(infits, TSTRING, "INIT_COR", procstep,
+ NULL, &status) ;
+ cf_read_fpa_pos (infits, &fpasx0, &fpalx0);
+ FITS_create_file(&outfits, argv[1], &status);
+ FITS_copy_hdu(infits, outfits, 0, &status);
+ FITS_create_hdu(outfits, &status);
+ FITS_movabs_hdu(infits,2,&hdutype,&status);
+ FITS_get_hdrpos(infits, &nkeys, &keynum, &status);
+ for (j=1; j<=nkeys; j++) {
+ FITS_read_record(infits, j, buffer, &status);
+ FITS_write_record(outfits, buffer, &status);
+ }
+ /* adjust some initial keywords */
+ nevents=0;
+ FITS_update_key(outfits, TLONG, "NAXIS2", &nevents,
+ NULL, &status);
+ /* set a flag (procflg) if the file is processed in any way */
+ if ( strncmp(procstep, "COMP", 4) == 0) {
+ printf("file has been processed - setting flag \n") ;
+ procflg = 1 ; }
+ else printf("These are raw data files \n") ;
+ } else {
+ FITS_read_key(infits, TDOUBLE, "EXPSTART", &mjd_start,
+ NULL, &status);
+ if (mjd_start < mjd_last)
+ cf_if_error("Files must be in time order, first to last.");
+ mjd_last=mjd_start;
+ FITS_read_key(infits, TDOUBLE, "EXPEND", &mjd_end,
+ NULL, &status);
+ cf_read_fpa_pos (infits, &fpasx, &fpalx);
+ dfpasx = fpasx - fpasx0 ;
+ dfpalx = fpalx - fpalx0 ;
+ if (fabs((double)dfpasx) > 30.) {
+ printf("\nLarge change in SIC FPA X position: %f \n",dfpasx) ;
+ fpa_split = TRUE;
+ }
+ if (fabs((double)dfpalx) > 30.) {
+ printf("\nLarge change in LIF FPA X position: %f \n",dfpalx) ;
+ fpa_split = TRUE;
+ }
+ }
+
+ FITS_movabs_hdu(infits,1,&hdutype,&status);
+
+ FITS_read_key(infits, TDOUBLE, "EXPTIME", &indtime,
+ NULL, &status);
+ exptime+=indtime;
+
+ fits_read_key(infits, TDOUBLE, "RAWTIME", &rawtime,
+ NULL, &status);
+ if (status)
+ status = 0;
+ else
+ trawtime+=rawtime;
+
+ FITS_read_key(infits, TINT, "PLANTIME", &plantime,
+ NULL, &status);
+ tplantime+=plantime ;
+
+ fits_read_key(infits, TLONG, "EXPNIGHT", &indnight,
+ NULL, &status);
+ if (status)
+ status = 0;
+ else
+ expnight+=indnight;
+
+ cf_dtcor_read_counters(infits,&de,&fe,&ai1a,&ai1b,&ai2a,&ai2b,
+ &sic,&lif,&as,&ctm) ;
+
+ de_tot += de;
+ fe_tot += fe;
+ ai1a_tot += ai1a ;
+ ai1b_tot += ai1b ;
+ ai2a_tot += ai2a ;
+ ai2b_tot += ai2b ;
+ sic_tot += sic ;
+ lif_tot += lif ;
+ as_tot += as ;
+ ctm_tot += ctm ;
+
+ FITS_movabs_hdu(infits,2,&hdutype,&status);
+ /* Get the number of events in the input file. */
+ FITS_read_key(infits, TLONG, "NAXIS2", &nevents, NULL, &status);
+
+ printf(" EXPTIME=%10.3f NEVENTS=%10ld\n",indtime,nevents);
+
+ /* Allocate space for the input and output times, coords,
+ pha */
+ time_in = (float *) cf_malloc(sizeof(float) * nevents);
+ x_in = (short *) cf_malloc(sizeof(short) * nevents);
+ y_in = (short *) cf_malloc(sizeof(short) * nevents);
+ pha_in = (char *) cf_malloc(sizeof(char) * nevents);
+ dx = (float *) cf_malloc(sizeof(float) * nevents);
+ dy = (float *) cf_malloc(sizeof(float) * nevents);
+ dnflg = (char *) cf_malloc(sizeof(char) * nevents);
+
+ FITS_get_colnum(infits, TRUE, "TIME", &tcol_in, &status);
+ FITS_get_colnum(infits, TRUE, "X", &xcol_in, &status);
+ FITS_get_colnum(infits, TRUE, "Y", &ycol_in, &status);
+ FITS_get_colnum(infits, TRUE, "PHA", &phacol_in, &status);
+ if(procflg > 0) {
+ FITS_get_colnum(infits, TRUE, "DX", &dxcol_in, &status);
+ FITS_get_colnum(infits, TRUE, "DY", &dycol_in, &status);
+ FITS_get_colnum(infits, TRUE, "DNFLG",&dnflgcol_in, &status); }
+
+ FITS_get_colnum(outfits, TRUE, "TIME", &tcol_out, &status);
+ FITS_get_colnum(outfits, TRUE, "X", &xcol_out, &status);
+ FITS_get_colnum(outfits, TRUE, "Y", &ycol_out, &status);
+ FITS_get_colnum(outfits, TRUE, "PHA", &phacol_out, &status);
+ if (procflg > 0 ) {
+ FITS_get_colnum(outfits, TRUE, "DX", &dxcol_out, &status);
+ FITS_get_colnum(outfits, TRUE, "DY", &dycol_out, &status);
+ FITS_get_colnum(outfits, TRUE, "DNFLG",&dnflgcol_out, &status);}
+
+ FITS_read_col(infits, TFLOAT, tcol_in, 1, 1, nevents, NULL,
+ time_in, &anynull, &status);
+ FITS_read_col(infits, TSHORT, xcol_in, 1, 1, nevents, NULL,
+ x_in, &anynull, &status);
+ FITS_read_col(infits, TSHORT, ycol_in, 1, 1, nevents, NULL,
+ y_in, &anynull, &status);
+ FITS_read_col(infits, TBYTE, phacol_in, 1, 1, nevents, NULL,
+ pha_in, &anynull, &status);
+ if(procflg > 0) {
+ FITS_read_col(infits, TFLOAT, dxcol_in, 1, 1, nevents, NULL,
+ dx, &anynull, &status);
+ FITS_read_col(infits, TFLOAT, dycol_in, 1, 1, nevents, NULL,
+ dy, &anynull, &status);
+ FITS_read_col(infits, TBYTE, dnflgcol_in, 1, 1, nevents, NULL,
+ dnflg, &anynull, &status);}
+
+ for (j=0; j<nevents; j++){
+ time_in[j]+=(float) ((mjd_start-mjd_init)*86400.0);
+ }
+
+ FITS_write_col(outfits, TFLOAT, tcol_out, jrow, 1,
+ nevents, time_in, &status);
+ FITS_write_col(outfits, TSHORT, xcol_out, jrow, 1,
+ nevents, x_in, &status);
+ FITS_write_col(outfits, TSHORT, ycol_out, jrow, 1,
+ nevents, y_in, &status);
+ FITS_write_col(outfits, TBYTE, phacol_out, jrow, 1,
+ nevents, pha_in, &status);
+ if (procflg > 0) {
+ FITS_write_col(outfits, TFLOAT, dxcol_out, jrow, 1,
+ nevents, dx, &status);
+ FITS_write_col(outfits, TFLOAT, dycol_out, jrow, 1,
+ nevents, dy, &status);
+ FITS_write_col(outfits, TBYTE, dnflgcol_out, jrow, 1,
+ nevents, dnflg, &status); }
+ jrow+=nevents;
+
+ free(time_in);
+ free(x_in);
+ free(y_in);
+ free(pha_in);
+ free(dx) ;
+ free(dy) ;
+ free(dnflg) ;
+
+
+ /* Copy GTI from input to output */
+ FITS_movabs_hdu(infits, 3, &hdutype, &status);
+ FITS_read_key(infits, TLONG, "NAXIS2", &ngti_in, NULL, &status);
+ gti_start_in = (float *) cf_malloc(sizeof(float) * ngti_in);
+ gti_stop_in = (float *) cf_malloc(sizeof(float) * ngti_in);
+ FITS_get_colnum(infits, TRUE, "START", &startcol, &status);
+ FITS_get_colnum(infits, TRUE, "STOP", &stopcol, &status);
+ FITS_read_col(infits, TFLOAT, startcol, 1, 1, ngti_in, 0,
+ gti_start_in, &anynull, &status);
+ FITS_read_col(infits, TFLOAT, stopcol, 1, 1, ngti_in, 0,
+ gti_stop_in, &anynull, &status);
+ for (k=0; k<ngti_in; k++) {
+ gti_start[ngti]=gti_start_in[k]+
+ (float) ((mjd_start-mjd_init)*86400.0);;
+ gti_stop[ngti]=gti_stop_in[k]+
+ (float) ((mjd_start-mjd_init)*86400.0);;
+ ngti++;
+ if (ngti >= MAXGTI) {
+ sprintf(buffer, "More than %d good time intervals.",MAXGTI) ;
+ cf_if_error(buffer);
+ }
+ }
+ free(gti_start_in);
+ free(gti_stop_in);
+
+ FITS_close_file(infits, &status);
+ }
+
+ FITS_flush_file(outfits, &status);
+
+ FITS_movabs_hdu(outfits, 1, &hdutype, &status);
+ jrow=jrow-1 ;
+ FITS_update_key(outfits, TLONG, "NEVENTS", &jrow, 0, &status) ;
+ FITS_update_key(outfits, TDOUBLE, "EXPTIME", &exptime, 0, &status);
+ FITS_update_key(outfits, TDOUBLE, "EXPEND", &mjd_end, 0, &status);
+ FITS_update_key(outfits, TLONG, "PLANTIME", &tplantime, 0, &status) ;
+
+ if (expnight < 0)
+ expnight = 0;
+ FITS_update_key(outfits, TLONG, "EXPNIGHT", &expnight, 0, &status);
+
+ if (trawtime - exptime > -1.)
+ FITS_update_key(outfits, TDOUBLE, "RAWTIME", &trawtime, 0, &status);
+
+ FITS_read_key(outfits, TSTRING, "DETECTOR", detstr, NULL, &status);
+ sprintf(cntstr, "%1.1s%2.2s%4.4s","C",detstr,"FE_B");
+ FITS_read_key(outfits, TLONG, cntstr, &fe_b, NULL, &status);
+ sprintf(cntstr, "%1.1s%2.2s%4.4s","C",detstr,"DE_B");
+ FITS_read_key(outfits, TLONG, cntstr, &de_b, NULL, &status);
+ sprintf(cntstr, "%1.1s%2.2s%5.5s","C",detstr,"SIC_B");
+ FITS_read_key(outfits, TLONG, cntstr, &sic_b, NULL, &status);
+ sprintf(cntstr, "%1.1s%2.2s%5.5s","C",detstr,"LIF_B");
+ FITS_read_key(outfits, TLONG, cntstr, &lif_b, NULL, &status);
+ sprintf(cntstr, "%1.1s%2.2s%4.4s","C",detstr,"AS_B");
+ FITS_read_key(outfits, TLONG, cntstr, &as_b, NULL, &status);
+
+ FITS_read_key(outfits, TLONG, "C1AAI_B", &ai1a_b, NULL, &status);
+ FITS_read_key(outfits, TLONG, "C1BAI_B", &ai1b_b, NULL, &status);
+ FITS_read_key(outfits, TLONG, "C2AAI_B", &ai2a_b, NULL, &status);
+ FITS_read_key(outfits, TLONG, "C2BAI_B", &ai2b_b, NULL, &status);
+ FITS_read_key(outfits, TDOUBLE, "CTIME_B", &ctm_b, NULL, &status);
+
+ sprintf(comment, "New ID for combined data") ;
+ strncpy(expid,"999 ",18) ;
+ expid[18]='\0' ;
+ FITS_update_key(outfits, TSTRING, "EXP_ID", expid, comment, &status);
+
+ sprintf(comment, "Date and time file was created") ;
+ stime[24]='\0' ;
+ FITS_update_key(outfits, TSTRING, "DATE", stime, comment, &status) ;
+
+ de_e = de_tot + de_b;
+ fe_e = fe_tot + fe_b;
+ lif_e = lif_tot + lif_b ;
+ sic_e = sic_tot + sic_b ;
+ as_e = as_tot + as_b ;
+ ctm_e = ctm_tot + ctm_b ;
+ ai1a_e = ai1a_tot + ai1a_b ;
+ ai1b_e = ai1b_tot + ai1b_b ;
+ ai2a_e = ai2a_tot + ai2a_b ;
+ ai2b_e = ai2b_tot + ai2b_b ;
+
+ sprintf(cntstr, "%1.1s%2.2s%4.4s","C",detstr,"DE_E");
+ FITS_update_key(outfits, TLONG, cntstr, &de_e, NULL, &status);
+ sprintf(cntstr, "%1.1s%2.2s%4.4s","C",detstr,"FE_E");
+ FITS_update_key(outfits, TLONG, cntstr, &fe_e, NULL, &status);
+ sprintf(cntstr, "%1.1s%2.2s%5.5s","C",detstr,"SIC_E");
+ FITS_update_key(outfits, TLONG, cntstr, &sic_e, NULL, &status);
+ sprintf(cntstr, "%1.1s%2.2s%5.5s","C",detstr,"LIF_E");
+ FITS_update_key(outfits, TLONG, cntstr, &lif_e, NULL, &status);
+ sprintf(cntstr, "%1.1s%2.2s%4.4s","C",detstr,"AS_E");
+ FITS_update_key(outfits, TLONG, cntstr, &as_e, NULL, &status);
+
+ FITS_update_key(outfits, TLONG, "C1AAI_E", &ai1a_e, NULL, &status);
+ FITS_update_key(outfits, TLONG, "C1BAI_E", &ai1b_e, NULL, &status);
+ FITS_update_key(outfits, TLONG, "C2AAI_E", &ai2a_e, NULL, &status);
+ FITS_update_key(outfits, TLONG, "C2BAI_E", &ai2b_e, NULL, &status);
+ FITS_update_key(outfits, TDOUBLE, "CTIME_E", &ctm_e, NULL, &status);
+
+
+ FITS_write_comment(outfits, " ", &status);
+ FITS_write_comment(outfits, "CF_TTAG_COMBINE", &status);
+ FITS_write_comment(outfits, " ", &status);
+ FITS_write_comment(outfits, "This file is a concatenation of:", &status);
+ for (i=2; i<=nfiles; i++) {
+ FITS_write_comment(outfits, argv[i], &status);
+ }
+
+
+ FITS_open_file(&infits, argv[2], READONLY, &status);
+
+ /* Move to the second extension which contains the goof time intervals. */
+ FITS_movabs_hdu(infits, 3, &hdutype, &status);
+
+ /* Create the second extension in the output file. */
+ FITS_create_hdu(outfits, &status);
+
+ /* Copy the header of the input file to the output file. */
+ FITS_get_hdrpos(infits, &nkeys, &keynum, &status);
+ for (i=1; i<=nkeys; i++) {
+ FITS_read_record(infits, i, buffer, &status);
+ FITS_write_record(outfits, buffer, &status);
+ }
+
+ FITS_get_colnum(outfits,TRUE,"START",&startcol,&status);
+ FITS_get_colnum(outfits,TRUE,"STOP",&stopcol,&status);
+
+ FITS_write_col(outfits, TFLOAT, startcol, 1, 1, ngti, gti_start, &status);
+ FITS_write_col(outfits, TFLOAT, stopcol, 1, 1, ngti, gti_stop, &status);
+
+ free(gti_start);
+ free(gti_stop);
+
+ FITS_close_file(infits, &status);
+ FITS_close_file(outfits, &status);
+
+ if (fpa_split)
+ cf_if_warning("FPA motion detected. Resolution may be compromised.\n");
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Finished execution.");
+ return 0;
+}
diff --git a/src/analysis/ttag_lightcurve.c b/src/analysis/ttag_lightcurve.c
new file mode 100644
index 0000000..f1a14fa
--- /dev/null
+++ b/src/analysis/ttag_lightcurve.c
@@ -0,0 +1,398 @@
+
+/*************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *************************************************************************
+ *
+ *
+ * Usage:
+ * ttag_lightcurve [-hf] [-v level] input_file output_file windows_file
+ * bins LiForSiC
+ *
+ *
+ * Arguments:
+ * input_file : ttag IDF file
+ * output_file : ASCII file with 2 columns :
+ * - time (MJD)
+ * - countrate
+ *
+ * windows_file : input ASCII file with 2 columns :
+ * - start of spectral windows
+ * - stop of spectral windows
+ *
+ * bins : bin size in seconds
+ * LiForSiC : 1=LiF, 2=SiC
+ *
+ *
+ *
+ *
+ * Options:
+ * -h: this help message
+ * -f: output calibrated flux (erg/cm2/s) instead of countrate
+ * -v: verbosity level (=1; 0 is silent)
+ *
+ *
+ *
+ *
+ * History: 10/06/04 bjg v1.0
+ * 06/03/05 wvd v1.1 Delete unused variables.
+ *
+ ***************************************************************************/
+
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "calfuse.h"
+
+
+
+
+#define N_MAX_WIN 100 /* Maximum number of spectral windows */
+
+typedef struct {
+ float start;
+ float stop;
+} interval; /* type to store a spectral window */
+
+
+int is_inside(float val,interval * interval_ptr, int nintervals);
+int is_good_time(char timeflag,char * daynight);
+int is_in_lif_channel(char channel, char * aperture);
+int is_in_sic_channel(char channel, char * aperture);
+
+
+
+
+
+static char CF_PRGM_ID[]= "ttag_lightcurve";
+static char CF_VER_NUM[]= "1.1";
+
+
+
+
+int main(int argc,char *argv[]){
+
+
+
+ char input_filename[FLEN_CARD];
+ char output_filename[FLEN_CARD];
+ char windefs_filename[FLEN_CARD];
+
+ FILE * output_file;
+ FILE * windefs_file;
+
+ fitsfile * infits;
+
+ interval swindows[N_MAX_WIN]; /* the spectral windows are stored
+ in an array of intervals */
+ int nwindows = 0; /* number of spectral windows TBD */
+
+ float bins;
+
+ int intnull=0,anynull;
+ int status=0;
+ int hdutype=0;
+
+ long nevents;
+ long i;
+ int ncol;
+
+ char tempchar;
+ char tempstring[FLEN_CARD];
+
+ char daynight[FLEN_CARD];
+ char instmode[FLEN_CARD];
+ char aperture[FLEN_CARD];
+
+ double * hdu2_time;
+ double * hdu2_lambda;
+ double * hdu2_weight;
+ char * hdu2_channel;
+ char * hdu2_timeflgs;
+ char * hdu2_loc_flgs;
+
+ float * gti_start;
+ float * gti_stop;
+ int ngtis;
+
+ interval * gtis;
+
+ double t, tmax, ctot;
+
+ double expstart;
+
+ int badtime;
+
+ int LiForSiC;
+
+
+ int optc;
+
+ int do_flux=0;
+
+ char opts[] = "hfv:";
+ char usage[] =
+ "Usage:\n"
+ " ttag_lightcurve [-hf] [-v level] input_file output_file windows_file\n"
+ " bins LiForSiC\n\n"
+ "Arguments:\n"
+ " input_file : ttag IDF file\n\n"
+ " output_file : ASCII file with 2 columns:\n"
+ " - time (MJD)\n"
+ " - countrate corrected for deadtime\n\n"
+ " windows_file : input ASCII file with 2 columns :\n"
+ " - start of spectral windows\n"
+ " - stop of spectral windows\n\n"
+ " bins : bin size in seconds\n"
+ " LiForSiC : 1=LiF, 2=SiC\n";
+ char option[] =
+ "Options:\n"
+ " -h: this help message \n"
+ " -f: output calibrated flux (erg/cm2/s) instead of countrate \n"
+ " -v: verbosity level (=1; 0 is silent) \n";
+
+ verbose_level = 1;
+
+
+ /* Check number of options and arguments */
+ while ((optc = getopt(argc, argv, opts)) != -1) {
+ switch(optc) {
+ case 'h':
+ printf("%s\n%s", usage, option);
+ return EXIT_SUCCESS;
+ case 'v':
+ verbose_level = atoi(optarg);
+ break;
+ case 'f':
+ do_flux=1;
+ break;
+ }
+ }
+
+ /* Initialize error checking. */
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+ if (argc != optind+5)
+ cf_if_error("%s\nIncorrect number of program arguments", usage);
+
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Started execution.");
+
+ strcpy(input_filename,argv[optind]);
+ strcpy(output_filename,argv[optind+1]);
+ strcpy(windefs_filename,argv[optind+2]);
+ sscanf(argv[optind+3],"%f",&bins);
+ sscanf(argv[optind+4],"%d",&LiForSiC);
+
+ if ((LiForSiC>2)||(LiForSiC<1)) {
+ cf_if_error("%s\nLiForSiC value must be 1 (LiF) or 2 (SiC)", usage);
+ }
+
+
+ if (bins<=0) {
+ cf_if_error("Time interval is less than or equal to zero.");
+ }
+
+
+ /* Open the spectral windows definition file */
+ if ((windefs_file = fopen (windefs_filename, "r")) == NULL){
+ cf_if_error ("Unable to open file %s\n", windefs_filename);
+ }
+
+
+ /* Read the spectral windows definition file and store the spectral windows */
+ while (fscanf(windefs_file,"%f %f",&((swindows[nwindows]).start),
+ &((swindows[nwindows]).stop))!=EOF)
+ {
+ nwindows++;
+ }
+
+
+
+
+ for (i=0;i<nwindows;i++){
+ printf("Window %ld : %f - %f\n",i+1,swindows[i].start,swindows[i].stop);
+ }
+
+
+
+ /* Create the output file */
+ if ((output_file = fopen(output_filename,"w")) == NULL){
+ fclose(windefs_file);
+ cf_if_error ("Unable to create file %s\n", output_filename);
+ }
+
+
+
+ FITS_open_file(&infits,input_filename,READONLY,&status);
+
+ FITS_read_key(infits,TSTRING,"INSTMODE",instmode,NULL,&status);
+
+ if (strncasecmp(instmode,"TTAG",4)){
+ FITS_close_file(infits,&status);
+ fclose(windefs_file);
+ fclose(output_file);
+ cf_if_error("Input file is not TTAG.");
+ }
+
+ FITS_read_key(infits,TDOUBLE,"EXPSTART",&expstart,NULL,&status);
+
+ FITS_read_key(infits,TSTRING,"DAYNIGHT",daynight,NULL,&status);
+
+ FITS_read_key(infits,TSTRING,"APERTURE",aperture,NULL,&status);
+
+
+ FITS_movabs_hdu(infits,2,&hdutype,&status);
+ FITS_read_key(infits,TSTRING,"TFORM1",tempstring,NULL,&status);
+ sscanf(tempstring,"%ld%c",&nevents,&tempchar);
+
+
+
+
+ hdu2_time=(double *)malloc(nevents*sizeof(double));
+ hdu2_lambda=(double *)malloc(nevents*sizeof(double));
+ hdu2_weight=(double *)malloc(nevents*sizeof(double));
+ hdu2_channel=(char *)malloc(nevents*sizeof(char));
+ hdu2_timeflgs=(char *)malloc(nevents*sizeof(char));
+ hdu2_loc_flgs=(char *)malloc(nevents*sizeof(char));
+
+ FITS_get_colnum(infits, TRUE, "TIME", &ncol, &status);
+ FITS_read_col(infits, TDOUBLE, ncol, 1, 1, nevents, &intnull,
+ hdu2_time, &anynull, &status);
+
+ FITS_get_colnum(infits, TRUE, "LAMBDA", &ncol, &status);
+ FITS_read_col(infits, TDOUBLE, ncol, 1, 1, nevents, &intnull,
+ hdu2_lambda, &anynull, &status);
+
+ if (do_flux) {
+ FITS_get_colnum(infits, TRUE, "ERGCM2", &ncol, &status);
+ FITS_read_col(infits, TDOUBLE, ncol, 1, 1, nevents, &intnull,
+ hdu2_weight, &anynull, &status);
+ } else {
+ FITS_get_colnum(infits, TRUE, "WEIGHT", &ncol, &status);
+ FITS_read_col(infits, TDOUBLE, ncol, 1, 1, nevents, &intnull,
+ hdu2_weight, &anynull, &status);
+ }
+
+ FITS_get_colnum(infits, TRUE, "CHANNEL", &ncol, &status);
+ FITS_read_col(infits, TBYTE, ncol, 1, 1, nevents, &intnull,
+ hdu2_channel, &anynull, &status);
+
+ FITS_get_colnum(infits, TRUE, "TIMEFLGS", &ncol, &status);
+ FITS_read_col(infits, TBYTE, ncol, 1, 1, nevents, &intnull,
+ hdu2_timeflgs, &anynull, &status);
+
+ FITS_get_colnum(infits, TRUE, "LOC_FLGS", &ncol, &status);
+ FITS_read_col(infits, TBYTE, ncol, 1, 1, nevents, &intnull,
+ hdu2_loc_flgs, &anynull, &status);
+
+
+ FITS_movabs_hdu(infits,3,&hdutype,&status);
+
+ ngtis=cf_read_col(infits,TFLOAT,"START",(void **) &gti_start);
+ ngtis=cf_read_col(infits,TFLOAT,"STOP",(void **) &gti_stop);
+
+ gtis=(interval *)malloc(ngtis*sizeof(interval));
+
+ for (i=0;i<ngtis;i++){
+ gtis[i].start=gti_start[i];
+ gtis[i].stop=gti_stop[i];
+ }
+
+
+
+ t=0.0;
+ tmax=bins;
+ i=0;
+ ctot=0.0;
+ badtime=0;
+ while (i<nevents){
+
+ while (hdu2_time[i]>=tmax) {
+ if (!(is_inside(t,gtis,ngtis))) badtime=1;
+ if (!(is_inside(tmax,gtis,ngtis))) badtime=1;
+ if (!badtime) fprintf(output_file,"%15lf %15lf\n",expstart+t/(3600.0*24.0),ctot/bins);
+ t=tmax;
+ tmax=t+bins;
+ ctot=0.0;
+ badtime=0;
+ }
+
+ if (!(is_good_time(hdu2_timeflgs[i],daynight))) badtime=1;
+
+ if (is_inside(hdu2_lambda[i],swindows,nwindows)){
+ if (hdu2_loc_flgs[i]==0){
+ if (LiForSiC==1){
+ if (is_in_lif_channel(hdu2_channel[i],aperture)){
+ ctot+=hdu2_weight[i];
+ }
+ }
+ else {
+ if (is_in_sic_channel(hdu2_channel[i],aperture)){
+ ctot+=hdu2_weight[i];
+ }
+ }
+ }
+ }
+
+ i++;
+ }
+
+ free(hdu2_time);
+ free(hdu2_lambda);
+ free(hdu2_weight);
+ free(hdu2_channel);
+ free(hdu2_timeflgs);
+ free(hdu2_loc_flgs);
+
+
+
+ FITS_close_file(infits,&status);
+ fclose(windefs_file);
+ fclose(output_file);
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Finished execution.");
+ return EXIT_SUCCESS;
+
+}
+
+int is_inside(float val,interval * interval_ptr, int nintervals){
+ int i;
+ i=0;
+ while (i<nintervals){
+ if ((val<=interval_ptr[i].stop)&&(val>=interval_ptr[i].start)){
+ return 1;
+ }
+ i++;
+ }
+ return 0;
+}
+
+int is_good_time(char timeflag,char * daynight){
+
+ if (!(strncasecmp(daynight,"DAY" ,3))) return (timeflag == 1);
+ if (!(strncasecmp(daynight,"NIGHT",5))) return (timeflag == 0);
+
+ return ((timeflag&254) == 0);
+
+}
+
+int is_in_lif_channel(char channel, char * aperture){
+ if (!strncasecmp(aperture,"LWRS",4)) return (channel == 3);
+ if (!strncasecmp(aperture,"MDRS",4)) return (channel == 2);
+ if (!strncasecmp(aperture,"HIRS",4)) return (channel == 1);
+ return 0;
+}
+
+int is_in_sic_channel(char channel, char * aperture){
+ if (!strncasecmp(aperture,"LWRS",4)) return (channel == 7);
+ if (!strncasecmp(aperture,"MDRS",4)) return (channel == 6);
+ if (!strncasecmp(aperture,"HIRS",4)) return (channel == 5);
+ return 0;
+}
diff --git a/src/analysis/ttag_lightcurve_channel_sum.c b/src/analysis/ttag_lightcurve_channel_sum.c
new file mode 100644
index 0000000..9f76c37
--- /dev/null
+++ b/src/analysis/ttag_lightcurve_channel_sum.c
@@ -0,0 +1,183 @@
+
+/*************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *************************************************************************
+ *
+ *
+ * Usage:
+ * ttag_lightcurve_channel_sum [-h] [-v level] output_file
+ * input_file1 input_file2
+ *
+ *
+ * Arguments:
+ * input_files : ASCII files with 2 columns :
+ * - time
+ * - signal
+ *
+ * output_file : ASCII file with 2 columns :
+ * - time
+ * - signal
+ *
+ *
+ *
+ *
+ *
+ *
+ * Options:
+ * -h: this help message
+ * -v: verbosity level (=1; 0 is silent)
+ *
+ *
+ *
+ *
+ * History: 10/06/04 bjg v1.0
+ * 11/04/04 bjg v1.1 time equality criteria changed
+ *
+ ***************************************************************************/
+
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "calfuse.h"
+
+
+#define MAX_INPUT_FILE 20
+
+static char CF_PRGM_ID[]= "ttag_lightcurve_channel_sum";
+static char CF_VER_NUM[]= "1.1";
+
+
+int is_equal(double a, double b, double delta){
+
+ return ( ((a-b) <= delta) && ((a-b) > -delta) );
+
+}
+
+
+int main(int argc,char *argv[]){
+
+
+
+ char input_filename1[FLEN_CARD];
+ char input_filename2[FLEN_CARD];
+ char output_filename[FLEN_CARD];
+
+
+ FILE * output_file;
+ FILE * input_file1;
+ FILE * input_file2;
+
+ double t1,v1,t2,v2, delta_t;
+
+ int end_of_file;
+
+ int optc;
+
+ char opts[] = "hv:";
+ char usage[] =
+ "Usage:\n"
+ " ttag_lightcurve_channel_sum [-h] [-v level] output_file\n"
+ " input_file1 input_file2\n\n"
+ "Arguments:\n"
+ " input_files : ASCII files with 2 columns :\n"
+ " - time\n"
+ " - signal\n\n"
+ " output_file : ASCII file with 2 columns : \n"
+ " - time \n"
+ " - signal\n";
+ char option[] =
+ "Options:\n"
+ " -h: this help message \n"
+ " -v: verbosity level (=1; 0 is silent) \n";
+
+ verbose_level = 1;
+
+
+ /* Check number of options and arguments */
+ while ((optc = getopt(argc, argv, opts)) != -1) {
+ switch(optc) {
+ case 'h':
+ printf("%s\n%s", usage, option);
+ return EXIT_SUCCESS;
+ case 'v':
+ verbose_level = atoi(optarg);
+ break;
+ }
+ }
+
+ /* Initialize error checking. */
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+ if (argc != optind+3)
+ cf_if_error("%s\nIncorrect number of program arguments", usage);
+
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Started execution.");
+
+ strcpy(output_filename,argv[optind]);
+ strcpy(input_filename1,argv[optind+1]);
+ strcpy(input_filename2,argv[optind+2]);
+
+
+
+ if ((input_file1 = fopen(input_filename1,"r")) == NULL){
+ cf_if_error ("Unable to open file %s\n", input_filename1);
+ }
+
+ if ((input_file2 = fopen(input_filename2,"r")) == NULL){
+ fclose(input_file1);
+ cf_if_error ("Unable to open file %s\n", input_filename2);
+ }
+
+
+ /* Create the output file */
+ if ((output_file = fopen(output_filename,"w")) == NULL){
+ fclose(input_file1);
+ fclose(input_file2);
+ cf_if_error ("Unable to create file %s\n", output_filename);
+ }
+
+ fscanf(input_file1,"%lf %lf",&t1,&v1);
+ fscanf(input_file1,"%lf %lf",&t2,&v2);
+ delta_t=t2-t1;
+
+ fseek(input_file1,0,SEEK_SET);
+
+
+ end_of_file=(fscanf(input_file2,"%lf %lf",&t2,&v2)==EOF)||(fscanf(input_file1,"%lf %lf",&t1,&v1)==EOF);
+
+
+ while (!end_of_file){
+ if (is_equal(t2,t1,delta_t/2)){
+ fprintf(output_file,"%15lf %15lf\n",t1,v1+v2);
+ end_of_file=(fscanf(input_file2,"%lf %lf",&t2,&v2)==EOF)||(fscanf(input_file1,"%lf %lf",&t1,&v1)==EOF);
+ }
+ else if (t2<t1) {
+ end_of_file=(fscanf(input_file2,"%lf %lf",&t2,&v2)==EOF);
+ }
+ else {
+ end_of_file=(fscanf(input_file1,"%lf %lf",&t1,&v1)==EOF);
+ }
+
+
+
+ }
+
+
+ fclose(input_file1);
+ fclose(input_file2);
+ fclose(output_file);
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Finished execution.");
+ return EXIT_SUCCESS;
+
+}
+
+
diff --git a/src/analysis/ttag_lightcurve_combine.c b/src/analysis/ttag_lightcurve_combine.c
new file mode 100644
index 0000000..9947f69
--- /dev/null
+++ b/src/analysis/ttag_lightcurve_combine.c
@@ -0,0 +1,182 @@
+
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: ttag_lightcurve_combine outfile file1 file2 file3 file4 ...
+ *
+ *
+ * History: 09/07/04 bjg v1.0
+ *
+ *
+ ****************************************************************************/
+
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include "calfuse.h"
+
+
+typedef char filename[FLEN_CARD];
+
+static char CF_PRGM_ID[]= "ttag_lightcurve_combine";
+static char CF_VER_NUM[]= "1.0";
+
+int main(int argc,char *argv[]){
+
+ char stime[FLEN_CARD];
+ time_t vtime;
+
+
+ filename *filelist;
+ double *expstartlist;
+
+ filename tempstring;
+ double tempdouble;
+
+ double minexpstart;
+ int minindex;
+
+ long nfiles, n2;
+ long i,j;
+
+ double t,v;
+ FILE * fin;
+ FILE * fout;
+
+ int optc;
+
+ char opts[] = "hv:";
+ char usage[] =
+ "Usage:\n"
+ " ttag_lightcurve_combine [-h] [-v level] output_file input_files\n";
+ char option[] =
+ "Options:\n"
+ " -h: this help message\n"
+ " -v: verbosity level (=1; 0 is silent)\n";
+
+ verbose_level = 1;
+
+ /* Check number of options and arguments */
+ while ((optc = getopt(argc, argv, opts)) != -1) {
+ switch(optc) {
+ case 'h':
+ printf("%s\n%s", usage, option);
+ return 0;
+ case 'v':
+ verbose_level = atoi(optarg);
+ break;
+ }
+ }
+
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+ if (argc < optind+2) {
+ printf("%s", usage);
+ cf_if_error("Incorrect number of arguments");
+ }
+
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Started execution.");
+
+ /* get and display time */
+ vtime = time(NULL) ;
+ strcpy(stime,ctime(&vtime));
+
+
+ nfiles=argc-optind-1;
+
+ filelist = (filename *)malloc(nfiles*sizeof(filename));
+ expstartlist = (double *)malloc(nfiles*sizeof(double));
+
+
+ cf_verbose(1,"GETTING INFORMATION ON INPUT FILES") ;
+
+ n2=0;
+
+ for (i=0; i<nfiles;i++) {
+
+ fin=fopen(argv[optind+i+1],"r");
+
+ if (fin==NULL){
+ cf_if_warning("Could not open file %s. Skipped.",argv[optind+i+1]);
+ continue;
+ }
+
+ fscanf(fin,"%lf %lf",&t,&v);
+
+ expstartlist[n2]=t;
+ strcpy(filelist[n2],argv[optind+i+1]);
+
+ fclose(fin);
+
+ n2++;
+ }
+
+ nfiles=n2;
+
+ if (nfiles==0){
+ cf_verbose(1,"No files to combine. Exiting.");
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Finished execution.");
+ exit(0);
+ }
+
+ cf_verbose(1,"SORTING INPUT FILES IN TIME ORDER") ;
+
+ for (i=0; i<nfiles-1;i++) {
+ minexpstart=expstartlist[i];
+ minindex=i;
+ for (j=i+1; j<nfiles;j++) {
+ if (expstartlist[j]<minexpstart){
+ minexpstart=expstartlist[j];
+ minindex=j;
+ }
+ }
+
+ strcpy(tempstring,filelist[minindex]);
+ strcpy(filelist[minindex],filelist[i]);
+ strcpy(filelist[i],tempstring);
+
+ tempdouble=expstartlist[minindex];
+ expstartlist[minindex]=expstartlist[i];
+ expstartlist[i]=tempdouble;
+
+ }
+
+ cf_verbose(2,"N: Filename ExpStart ");
+
+ for (i=0; i<nfiles;i++) {
+ cf_verbose(2,"%ld: %s %7.1f",i,filelist[i],expstartlist[i]);
+ }
+
+
+ cf_verbose(1,"CREATING OUTPUT FILE");
+ if ((fout = fopen(argv[optind],"w")) == NULL){
+ cf_if_error ("Unable to create file %s\n", argv[optind]);
+ }
+
+
+
+ for (i=0; i<nfiles;i++) {
+ fin=fopen(filelist[i],"r");
+ while (fscanf(fin, "%lf %lf", &t, &v)!=EOF){
+ fprintf(fout, "%15lf %15lf\n", t, v);
+ }
+ fclose(fin);
+ }
+
+
+
+ fclose(fout);
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Finished execution.");
+ return EXIT_SUCCESS;
+
+}
+
+
diff --git a/src/analysis/ttag_lightcurve_mjd2hmjd.c b/src/analysis/ttag_lightcurve_mjd2hmjd.c
new file mode 100644
index 0000000..def1978
--- /dev/null
+++ b/src/analysis/ttag_lightcurve_mjd2hmjd.c
@@ -0,0 +1,151 @@
+
+/*************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *************************************************************************
+ *
+ *
+ * Usage:
+ * ttag_lightcurve_mjd2hmjd [-h] [-v level] output_file input_file
+ * hh mm ss dd mm ss
+ *
+ *
+ * Arguments:
+ * input_file : ASCII file with 2 columns :
+ * - time (MJD)
+ * - signal
+ *
+ * output_file : ASCII file with 2 columns :
+ * - time (HMJD)
+ * - signal
+ *
+ * hh mm ss dd mm ss : RA and DEC of target
+ *
+ *
+ *
+ *
+ * Options:
+ * -h: this help message
+ * -v: verbosity level (=1; 0 is silent)
+ *
+ *
+ *
+ *
+ * History: 10/06/04 bjg v1.0
+ * 06/03/05 wvd v1.1 Delete unused variables.
+ *
+ ***************************************************************************/
+
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "calfuse.h"
+
+double gethmjd(double, int, int, float, int, int, float);
+
+static char CF_PRGM_ID[]= "ttag_lightcurve_mjd2hmjd";
+static char CF_VER_NUM[]= "1.1";
+
+
+int main(int argc,char *argv[]){
+
+
+
+ char input_filename[FLEN_CARD];
+ char output_filename[FLEN_CARD];
+
+
+ FILE * output_file;
+ FILE * input_file;
+
+
+ double t,t2,v;
+ int rah, ram, decd, decm;
+ float ras, decs;
+
+
+ int optc;
+
+ char opts[] = "hv:";
+ char usage[] =
+ "Usage:\n"
+ " ttag_lightcurve_mjd2hmjd [-h] [-v level] output_file input_file\n"
+ " hh mm ss dd mm ss\n\n"
+ "Arguments:\n"
+ " input_file : ASCII file with 2 columns :\n"
+ " - time (MJD) \n"
+ " - signal\n\n"
+ " output_file : ASCII file with 2 columns : \n"
+ " - time (HMJD) \n"
+ " - signal \n\n"
+ " hh mm ss dd mm ss : RA and DEC of target\n";
+ char option[] =
+ "Options:\n"
+ " -h: this help message \n"
+ " -v: verbosity level (=1; 0 is silent) \n";
+
+ verbose_level = 1;
+
+
+ /* Check number of options and arguments */
+ while ((optc = getopt(argc, argv, opts)) != -1) {
+ switch(optc) {
+ case 'h':
+ printf("%s\n%s", usage, option);
+ return EXIT_SUCCESS;
+ case 'v':
+ verbose_level = atoi(optarg);
+ break;
+ }
+ }
+
+ /* Initialize error checking. */
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+ if (argc != optind+8)
+ cf_if_error("%s\nIncorrect number of program arguments", usage);
+
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Started execution.");
+
+ strcpy(output_filename,argv[optind]);
+ strcpy(input_filename,argv[optind+1]);
+ sscanf(argv[optind+2],"%d",&rah);
+ sscanf(argv[optind+3],"%d",&ram);
+ sscanf(argv[optind+4],"%f",&ras);
+ sscanf(argv[optind+5],"%d",&decd);
+ sscanf(argv[optind+6],"%d",&decm);
+ sscanf(argv[optind+7],"%f",&decs);
+
+
+ if ((input_file = fopen(input_filename,"r")) == NULL){
+ cf_if_error ("Unable to open file %s\n", input_filename);
+ }
+
+ /* Create the output file */
+ if ((output_file = fopen(output_filename,"w")) == NULL){
+ fclose(input_file);
+ cf_if_error ("Unable to create file %s\n", output_filename);
+ }
+
+ while(fscanf(input_file,"%lf %lf",&t,&v)!=EOF) {
+ t2=gethmjd(t, rah, ram, ras, decd, decm, decs);
+
+ fprintf(output_file,"%15lf %15lf\n",t2,v);
+ }
+
+ fclose(input_file);
+ fclose(output_file);
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Finished execution.");
+ return EXIT_SUCCESS;
+
+}
+
+
diff --git a/src/analysis/ttag_lightcurve_periodogram.c b/src/analysis/ttag_lightcurve_periodogram.c
new file mode 100644
index 0000000..939a1ec
--- /dev/null
+++ b/src/analysis/ttag_lightcurve_periodogram.c
@@ -0,0 +1,294 @@
+
+/****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ ****************************************************************************
+ *
+ *
+ * Usage:
+ * ttag_lightcurve_periodogram [-hs] [-v level] input_file output_file
+ * minf maxf stepf
+ *
+ *
+ * Arguments:
+ * input_file : an ASCII file with 2 columns :
+ * - time (days)
+ * - countrate
+ *
+ * output_file : an ASCII file with 2 columns :
+ * - frequency (Hz)
+ * - normalized estimated power spectral density
+ *
+ * minf : start frequency (Hz)
+ * maxf : end frequency (Hz)
+ * stepf : frequency step (Hz)
+ *
+ *
+ *
+ * Options:
+ * -h: this help message
+ * -v: verbosity level (=1; 0 is silent)
+ * -s: time is in seconds instead of days
+ *
+ *
+ **************************************************************************
+ *
+ *
+ *
+ * Description:
+ *
+ * Computes the Lomb periodogram of signal h
+ * from samples (hj) j=1..N at times (tj) j=1..N
+ *
+ *
+ * w=2*pi*f
+ *
+ *
+ *
+ * 1 / (sum_j[(hj-H)*cos(w(tj-tau))])^2
+ * Pn(w) = ----------- | ---------------------------------
+ * 2*sigma2 \ sum_j[(cos(w(tj-tau)))^2]
+ *
+ *
+ * (sum_j[(hj-H)*sin(w(tj-tau))])^2 \
+ * + --------------------------------- |
+ * sum_j[(cos(w(tj-tau)))^2] /
+ *
+ *
+ *
+ *
+ * H=sum_i[hi]/N sigma2=sum_i[(hi-H)^2]/(N-1)
+ *
+ *
+ * sum_j[sin(2*w*tj)]
+ * tan (2*w*tau) = ------------------
+ * sum_j[cos(2*w*tj)]
+ *
+ *
+ * PAINFULLY SLOW
+ * NEED TO BE REWRITTEN TO DO A FAST TRANSFORM (RECURSIVE)
+ *
+ *
+ *
+ *****************************************************************************
+ *
+ * History: 10/07/04 bjg v1.0
+ * 11/04/04 bjg v1.1
+ *
+ * ----v1.1 CHANGES WERE CANCELLED ---
+ * 12/06/04 bjg v1.2
+ * 12/13/04 bjg v1.3 Changed N and i to long
+ * Initialize N to 0
+ * 06/03/05 wvd v1.4 Delete unused variables.
+ *
+ *
+ ***************************************************************************/
+
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <math.h>
+
+
+#include "calfuse.h"
+
+
+static char CF_PRGM_ID[]= "ttag_lightcurve_periodogram";
+static char CF_VER_NUM[]= "1.1";
+
+
+
+int main(int argc,char *argv[]){
+
+
+
+ char input_filename[FLEN_CARD],output_filename[FLEN_CARD];
+
+ FILE * output_file;
+ FILE * input_file;
+
+ float minf,maxf;
+ float stepf;
+
+
+ double H;
+ double sigma2;
+ double tau;
+
+
+ double val1,val2;
+ double * t;
+ double * h;
+ double total1,total2,total3,total4;
+ double aux;
+ double Pn;
+ double f;
+ double j0=0;
+
+ long i, N;
+ long ndx;
+
+ int time_unit=0;
+
+ int optc;
+
+ char opts[] = "hsv:";
+
+ char usage[] =
+ "Usage:\n"
+ " ttag_lightcurve_periodogram [-hs] [-v level] input_file output_file\n"
+ " minf, maxf, stepf\n"
+ "Arguments:\n"
+ " input_file : an ASCII file with 2 columns :\n"
+ " - time (JD or MJD, Helio- or Geo-centric)\n"
+ " - countrate\n\n"
+ " output_file : an ASCII file with 2 columns :\n"
+ " - frequency (Hz)\n"
+ " - normalized estimated power spectral density\n\n"
+ " minf : start frequency (Hz)\n"
+ " maxf : end frequency (Hz)\n"
+ " stepf : frequency step (Hz)\n";
+
+ char option[] =
+ "Options:\n"
+ " -h: this help message\n"
+ " -v: verbosity level (=1; 0 is silent)\n"
+ " -s: time is in seconds instead of days\n";
+
+ verbose_level = 1;
+
+
+ /* Check number of options and arguments */
+ while ((optc = getopt(argc, argv, opts)) != -1) {
+ switch(optc) {
+ case 'h':
+ printf("%s\n%s", usage, option);
+ return EXIT_SUCCESS;
+ case 'v':
+ verbose_level = atoi(optarg);
+ break;
+ case 's':
+ time_unit=1;
+ break;
+ }
+ }
+
+ /* Initialize error checking. */
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+ if (argc != optind+5)
+ cf_if_error("%s\nIncorrect number of program arguments", usage);
+
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Started execution.");
+
+ strcpy(input_filename,argv[optind]);
+ strcpy(output_filename,argv[optind+1]);
+ sscanf(argv[optind+2],"%f",&minf);
+ sscanf(argv[optind+3],"%f",&maxf);
+ sscanf(argv[optind+4],"%f",&stepf);
+
+
+
+ if ((input_file = fopen (input_filename, "r")) == NULL){
+ cf_if_error ("Unable to open file %s\n", input_filename);
+ }
+
+
+ N=0;
+ while (fscanf(input_file,"%lf %lf",&val1,&val2)!=EOF){
+ N++;
+ }
+
+ t=(double *)malloc(N*sizeof(double));
+ h=(double *)malloc(N*sizeof(double));
+
+
+ fseek(input_file,0,SEEK_SET);
+
+ i=0;
+ total1=0;
+ while (fscanf(input_file,"%lf %lf",&val1,&val2)!=EOF){
+ if (i==0) {
+ t[i]=0.0; j0=val1;
+ }
+ else {
+ if (time_unit) t[i]=val1-j0;
+ else t[i]=(val1-j0)*3600.0*24;
+ }
+
+ h[i]=val2;
+
+ total1+=h[i];
+
+ i++;
+
+ }
+
+ H=total1/N;
+
+ total1=0;
+ for (i=0;i<N;i++){
+ aux=(h[i]-H);
+ total1+=aux*aux;
+ }
+
+ sigma2=total1/(N-1);
+
+
+
+ if ((output_file = fopen(output_filename,"w")) == NULL){
+ fclose(input_file);
+ cf_if_error ("Unable to create file %s\n", output_filename);
+ }
+
+ ndx=0;
+ for (f=minf; f<=maxf; f+=stepf){
+ cf_verbose(4,"n=%ld;minf=%f;maxf=%f;freq=%lf",ndx,minf,maxf,f);
+ ndx++;
+ total1=0;
+ total2=0;
+ for (i=0;i<N;i++){
+ total1+=sin(4*M_PI*f*t[i]);
+ total2+=cos(4*M_PI*f*t[i]);
+ }
+
+
+ tau=atan(total1/total2)/(4*M_PI*f);
+
+
+
+ total1=0;
+ total2=0;
+ total3=0;
+ total4=0;
+
+ for (i=0;i<N;i++){
+ aux=cos(2*M_PI*f*(t[i]-tau));
+ total1+=(h[i]-H)*aux;
+ total2+=aux*aux;
+ aux=sin(2*M_PI*f*(t[i]-tau));
+ total3+=(h[i]-H)*aux;
+ total4+=aux*aux;
+ }
+
+ Pn=(total1*total1/total2+total3*total3/total4)/(2*sigma2);
+
+
+ fprintf(output_file,"%10lf %10lf\n",f,Pn);
+
+ }
+
+ fclose(input_file);
+ fclose(output_file);
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Finished execution.");
+ return EXIT_SUCCESS;
+
+}
+
+