aboutsummaryrefslogtreecommitdiff
path: root/src/fuv
diff options
context:
space:
mode:
Diffstat (limited to 'src/fuv')
-rw-r--r--src/fuv/Makefile.Linux.orig75
-rw-r--r--src/fuv/Makefile.Linux64.orig74
-rw-r--r--src/fuv/Makefile.MacOSX.orig76
-rw-r--r--src/fuv/Makefile.Solaris.orig75
-rw-r--r--src/fuv/Makefile.orig.orig75
-rw-r--r--src/fuv/cf_assign_wavelength.c178
-rw-r--r--src/fuv/cf_bad_pixels.c1001
-rw-r--r--src/fuv/cf_convert_to_farf.c268
-rw-r--r--src/fuv/cf_countmap.c541
-rw-r--r--src/fuv/cf_extract_spectra.c336
-rw-r--r--src/fuv/cf_flux_calibrate.c173
-rw-r--r--src/fuv/cf_gainmap.c610
-rw-r--r--src/fuv/cf_hist_init.c653
-rw-r--r--src/fuv/cf_remove_motions.c316
-rw-r--r--src/fuv/cf_screen_photons.c298
-rw-r--r--src/fuv/cf_ttag_init.c594
16 files changed, 5343 insertions, 0 deletions
diff --git a/src/fuv/Makefile.Linux.orig b/src/fuv/Makefile.Linux.orig
new file mode 100644
index 0000000..da60b24
--- /dev/null
+++ b/src/fuv/Makefile.Linux.orig
@@ -0,0 +1,75 @@
+
+CALFUSEDIR= ${PWD}/../..
+SHARED= -shared
+FITSVER= 2.470
+
+# Symbols for include directories
+FUSEINCLDIR= -I${CALFUSEDIR}/include
+
+# Symbols used for compiling
+CC= cc
+OPT= -g -Wall -DCFORTRAN -Dg77Fortran -Df2cFortran
+CFLAGS= ${OPT} ${FUSEINCLDIR}
+
+FUSEBINDIR= ${CALFUSEDIR}/bin
+FUSELIBDIR= -L${CALFUSEDIR}/lib
+FUSELIBS= -lcfitsio-${FITSVER} -lsla -lcf
+LIBS= -lc -lm -lnsl -ldl -lgfortran
+LDFLAGS= -Wl,-R${CALFUSEDIR}/lib,-R${CALFUSEDIR}/src/libcf
+
+# Symbols used for creating shared libraries
+
+BINS= cf_hist_init cf_ttag_init cf_convert_to_farf cf_remove_motions \
+ cf_assign_wavelength cf_screen_photons cf_flux_calibrate \
+ cf_extract_spectra cf_countmap cf_gainmap cf_bad_pixels
+
+all: ${BINS}
+ chmod g+w ${BINS}
+
+install: all
+ /bin/cp -p ${BINS} ${FUSEBINDIR}
+
+clean:
+ - /bin/rm -f ${BINS}
+
+distclean:
+ - /bin/rm -f ${BINS}
+ cd ../../bin; /bin/rm -f ${BINS} calfuse
+
+cf_hist_init:
+ ${CC} ${CFLAGS} -o cf_hist_init cf_hist_init.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_ttag_init:
+ ${CC} ${CFLAGS} -o cf_ttag_init cf_ttag_init.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_convert_to_farf:
+ ${CC} ${CFLAGS} -o cf_convert_to_farf cf_convert_to_farf.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_remove_motions:
+ ${CC} ${CFLAGS} -o cf_remove_motions cf_remove_motions.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_assign_wavelength:
+ ${CC} ${CFLAGS} -o cf_assign_wavelength \
+ cf_assign_wavelength.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_screen_photons:
+ ${CC} ${CFLAGS} -o cf_screen_photons cf_screen_photons.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_flux_calibrate:
+ ${CC} ${CFLAGS} -o cf_flux_calibrate cf_flux_calibrate.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_extract_spectra:
+ ${CC} ${CFLAGS} -o cf_extract_spectra cf_extract_spectra.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_countmap:
+ ${CC} ${CFLAGS} -o cf_countmap cf_countmap.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_gainmap:
+ ${CC} ${CFLAGS} -o cf_gainmap cf_gainmap.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_bad_pixels:
+ ${CC} ${CFLAGS} -o cf_bad_pixels cf_bad_pixels.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
diff --git a/src/fuv/Makefile.Linux64.orig b/src/fuv/Makefile.Linux64.orig
new file mode 100644
index 0000000..6fbead0
--- /dev/null
+++ b/src/fuv/Makefile.Linux64.orig
@@ -0,0 +1,74 @@
+
+CALFUSEDIR= ${PWD}/../..
+SHARED= -shared
+
+# Symbols for include directories
+FUSEINCLDIR= -I${CALFUSEDIR}/include
+
+# Symbols used for compiling
+CC= cc
+OPT= -g -Wall -DCFORTRAN -Dg77Fortran -Df2cFortran
+CFLAGS= ${OPT} ${FUSEINCLDIR}
+
+FUSEBINDIR= ${CALFUSEDIR}/bin
+FUSELIBDIR= -L${CALFUSEDIR}/lib
+FUSELIBS= -lsla -lcf
+LIBS= -lc -lm -lnsl -ldl -lgfortran -lcfitsio
+LDFLAGS= -Wl,-R${CALFUSEDIR}/lib,-R${CALFUSEDIR}/src/libcf
+
+# Symbols used for creating shared libraries
+
+BINS= cf_hist_init cf_ttag_init cf_convert_to_farf cf_remove_motions \
+ cf_assign_wavelength cf_screen_photons cf_flux_calibrate \
+ cf_extract_spectra cf_countmap cf_gainmap cf_bad_pixels
+
+all: ${BINS}
+ chmod g+w ${BINS}
+
+install: all
+ /bin/cp -p ${BINS} ${FUSEBINDIR}
+
+clean:
+ - /bin/rm -f ${BINS}
+
+distclean:
+ - /bin/rm -f ${BINS}
+ cd ../../bin; /bin/rm -f ${BINS} calfuse
+
+cf_hist_init:
+ ${CC} ${CFLAGS} -o cf_hist_init cf_hist_init.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_ttag_init:
+ ${CC} ${CFLAGS} -o cf_ttag_init cf_ttag_init.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_convert_to_farf:
+ ${CC} ${CFLAGS} -o cf_convert_to_farf cf_convert_to_farf.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_remove_motions:
+ ${CC} ${CFLAGS} -o cf_remove_motions cf_remove_motions.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_assign_wavelength:
+ ${CC} ${CFLAGS} -o cf_assign_wavelength \
+ cf_assign_wavelength.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_screen_photons:
+ ${CC} ${CFLAGS} -o cf_screen_photons cf_screen_photons.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_flux_calibrate:
+ ${CC} ${CFLAGS} -o cf_flux_calibrate cf_flux_calibrate.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_extract_spectra:
+ ${CC} ${CFLAGS} -o cf_extract_spectra cf_extract_spectra.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_countmap:
+ ${CC} ${CFLAGS} -o cf_countmap cf_countmap.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_gainmap:
+ ${CC} ${CFLAGS} -o cf_gainmap cf_gainmap.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_bad_pixels:
+ ${CC} ${CFLAGS} -o cf_bad_pixels cf_bad_pixels.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
diff --git a/src/fuv/Makefile.MacOSX.orig b/src/fuv/Makefile.MacOSX.orig
new file mode 100644
index 0000000..acbfaf7
--- /dev/null
+++ b/src/fuv/Makefile.MacOSX.orig
@@ -0,0 +1,76 @@
+
+CALFUSEDIR= ${PWD}/../..
+FITSVER= 2.470
+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}
+
+FUSEBINDIR= ${CALFUSEDIR}/bin
+FUSELIBDIR= -L${CALFUSEDIR}/lib
+# FUSELIBS= -lcfitsio-${FITSVER} -lsla -lcf
+FUSELIBS= -lcfitsio -lsla -lcf
+LIBS= -lc -lm -ldl -L/sw/lib/ -lgfortran
+
+BINS= cf_hist_init cf_ttag_init cf_convert_to_farf cf_remove_motions \
+ cf_assign_wavelength cf_screen_photons cf_flux_calibrate \
+ cf_extract_spectra cf_countmap cf_gainmap cf_bad_pixels
+
+all: ${BINS}
+ chmod g+w ${BINS}
+
+install:
+ MACOSX_DEPLOYMENT_TARGET="${MACOSX_DEPLOYMENT_TARGET}"; \
+ export MACOSX_DEPLOYMENT_TARGET; \
+ make all
+ /bin/cp -p ${BINS} ${FUSEBINDIR}
+
+clean:
+ - /bin/rm -f ${BINS}
+
+distclean:
+ - /bin/rm -f ${BINS}
+ cd ../../bin; /bin/rm -f ${BINS} calfuse
+
+cf_hist_init:
+ ${CC} ${CFLAGS} -o cf_hist_init cf_hist_init.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS}
+cf_ttag_init:
+ ${CC} ${CFLAGS} -o cf_ttag_init cf_ttag_init.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS}
+cf_convert_to_farf:
+ ${CC} ${CFLAGS} -o cf_convert_to_farf cf_convert_to_farf.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS}
+cf_remove_motions:
+ ${CC} ${CFLAGS} -o cf_remove_motions cf_remove_motions.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS}
+cf_assign_wavelength:
+ ${CC} ${CFLAGS} -o cf_assign_wavelength \
+ cf_assign_wavelength.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS}
+cf_screen_photons:
+ ${CC} ${CFLAGS} -o cf_screen_photons cf_screen_photons.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS}
+cf_flux_calibrate:
+ ${CC} ${CFLAGS} -o cf_flux_calibrate cf_flux_calibrate.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS}
+cf_extract_spectra:
+ ${CC} ${CFLAGS} -o cf_extract_spectra cf_extract_spectra.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS}
+cf_countmap:
+ ${CC} ${CFLAGS} -o cf_countmap cf_countmap.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS}
+
+cf_gainmap:
+ ${CC} ${CFLAGS} -o cf_gainmap cf_gainmap.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS}
+
+cf_bad_pixels:
+ ${CC} ${CFLAGS} -o cf_bad_pixels cf_bad_pixels.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS}
+
diff --git a/src/fuv/Makefile.Solaris.orig b/src/fuv/Makefile.Solaris.orig
new file mode 100644
index 0000000..528e6bc
--- /dev/null
+++ b/src/fuv/Makefile.Solaris.orig
@@ -0,0 +1,75 @@
+
+CALFUSEDIR= ${PWD}/../..
+SHARED= -G
+FITSVER= 2.470
+
+# Symbols for include directories
+FUSEINCLDIR= -I${CALFUSEDIR}/include
+
+# Symbols used for compiling
+CC= cc
+OPT= -O -DCFORTRAN -KPIC
+CFLAGS= ${OPT} ${FUSEINCLDIR}
+
+FUSEBINDIR= ${CALFUSEDIR}/bin
+FUSELIBDIR= -L${CALFUSEDIR}/lib
+FUSELIBS= -lcfitsio-${FITSVER} -lsla -lcf
+LIBS= -lc -lm -lnsl -ldl -lsocket -lsunmath
+LDFLAGS= -Wl,-R${CALFUSEDIR}/lib,-R${CALFUSEDIR}/src/libcf
+
+# Symbols used for creating shared libraries
+
+BINS= cf_hist_init cf_ttag_init cf_convert_to_farf cf_remove_motions \
+ cf_assign_wavelength cf_screen_photons cf_flux_calibrate \
+ cf_extract_spectra cf_countmap cf_gainmap cf_bad_pixels
+
+all: ${BINS}
+ chmod g+w ${BINS}
+
+install: all
+ /bin/cp -p ${BINS} ${FUSEBINDIR}
+
+clean:
+ - /bin/rm -f ${BINS}
+
+distclean:
+ - /bin/rm -f ${BINS}
+ cd ../../bin; /bin/rm -f ${BINS} calfuse
+
+cf_hist_init:
+ ${CC} ${CFLAGS} -o cf_hist_init cf_hist_init.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_ttag_init:
+ ${CC} ${CFLAGS} -o cf_ttag_init cf_ttag_init.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_convert_to_farf:
+ ${CC} ${CFLAGS} -o cf_convert_to_farf cf_convert_to_farf.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_remove_motions:
+ ${CC} ${CFLAGS} -o cf_remove_motions cf_remove_motions.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_assign_wavelength:
+ ${CC} ${CFLAGS} -o cf_assign_wavelength \
+ cf_assign_wavelength.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_screen_photons:
+ ${CC} ${CFLAGS} -o cf_screen_photons cf_screen_photons.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_flux_calibrate:
+ ${CC} ${CFLAGS} -o cf_flux_calibrate cf_flux_calibrate.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_extract_spectra:
+ ${CC} ${CFLAGS} -o cf_extract_spectra cf_extract_spectra.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_countmap:
+ ${CC} ${CFLAGS} -o cf_countmap cf_countmap.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_gainmap:
+ ${CC} ${CFLAGS} -o cf_gainmap cf_gainmap.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_bad_pixels:
+ ${CC} ${CFLAGS} -o cf_bad_pixels cf_bad_pixels.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
diff --git a/src/fuv/Makefile.orig.orig b/src/fuv/Makefile.orig.orig
new file mode 100644
index 0000000..528e6bc
--- /dev/null
+++ b/src/fuv/Makefile.orig.orig
@@ -0,0 +1,75 @@
+
+CALFUSEDIR= ${PWD}/../..
+SHARED= -G
+FITSVER= 2.470
+
+# Symbols for include directories
+FUSEINCLDIR= -I${CALFUSEDIR}/include
+
+# Symbols used for compiling
+CC= cc
+OPT= -O -DCFORTRAN -KPIC
+CFLAGS= ${OPT} ${FUSEINCLDIR}
+
+FUSEBINDIR= ${CALFUSEDIR}/bin
+FUSELIBDIR= -L${CALFUSEDIR}/lib
+FUSELIBS= -lcfitsio-${FITSVER} -lsla -lcf
+LIBS= -lc -lm -lnsl -ldl -lsocket -lsunmath
+LDFLAGS= -Wl,-R${CALFUSEDIR}/lib,-R${CALFUSEDIR}/src/libcf
+
+# Symbols used for creating shared libraries
+
+BINS= cf_hist_init cf_ttag_init cf_convert_to_farf cf_remove_motions \
+ cf_assign_wavelength cf_screen_photons cf_flux_calibrate \
+ cf_extract_spectra cf_countmap cf_gainmap cf_bad_pixels
+
+all: ${BINS}
+ chmod g+w ${BINS}
+
+install: all
+ /bin/cp -p ${BINS} ${FUSEBINDIR}
+
+clean:
+ - /bin/rm -f ${BINS}
+
+distclean:
+ - /bin/rm -f ${BINS}
+ cd ../../bin; /bin/rm -f ${BINS} calfuse
+
+cf_hist_init:
+ ${CC} ${CFLAGS} -o cf_hist_init cf_hist_init.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_ttag_init:
+ ${CC} ${CFLAGS} -o cf_ttag_init cf_ttag_init.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_convert_to_farf:
+ ${CC} ${CFLAGS} -o cf_convert_to_farf cf_convert_to_farf.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_remove_motions:
+ ${CC} ${CFLAGS} -o cf_remove_motions cf_remove_motions.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_assign_wavelength:
+ ${CC} ${CFLAGS} -o cf_assign_wavelength \
+ cf_assign_wavelength.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_screen_photons:
+ ${CC} ${CFLAGS} -o cf_screen_photons cf_screen_photons.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_flux_calibrate:
+ ${CC} ${CFLAGS} -o cf_flux_calibrate cf_flux_calibrate.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_extract_spectra:
+ ${CC} ${CFLAGS} -o cf_extract_spectra cf_extract_spectra.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+cf_countmap:
+ ${CC} ${CFLAGS} -o cf_countmap cf_countmap.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_gainmap:
+ ${CC} ${CFLAGS} -o cf_gainmap cf_gainmap.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
+cf_bad_pixels:
+ ${CC} ${CFLAGS} -o cf_bad_pixels cf_bad_pixels.c \
+ ${FUSELIBDIR} ${FUSELIBS} ${LIBS} ${LDFLAGS}
+
diff --git a/src/fuv/cf_assign_wavelength.c b/src/fuv/cf_assign_wavelength.c
new file mode 100644
index 0000000..d84c7a0
--- /dev/null
+++ b/src/fuv/cf_assign_wavelength.c
@@ -0,0 +1,178 @@
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: cf_assign_wavelength options intermediate_data_file
+ *
+ * Description: Assign a wavelength to each photon, correcting for
+ * spacecraft motion and instrumental astigmatism.
+ * The final wavelength scale is heliocentric.
+ *
+ * By default all corrections are performed. Command-line
+ * options allow one or more corrections to be omitted.
+ *
+ * Arguments: input_file FARF-corrected intermediate data file
+ *
+ * Calibration files: ASTG_CAL, WAVE_CAL
+ *
+ * Returns: 0 on successful completion
+ *
+ * Calls: cf_astigmatism, cf_dispersion, cf_doppler_and_heliocentric
+ *
+ * History: 11/05/02 1.1 peb Begin work
+ * 12/16/02 1.2 wvd Install subroutines.
+ * 02/12/03 1.3 wvd Change ORBITAL_VELOCITY to ORBITAL_VEL
+ * 03/10/03 1.4 peb Added verbose_level, changed channel to
+ * char *, and added unistd.h for getopt
+ * portability
+ * 03/12/03 1.5 wvd If lambda[k] is undefined,
+ * set channel[k] = 0 in IDF
+ * 03/23/03 1.6 wvd If -w option is set, write astigmatism-
+ * corrected X values to IDF.
+ * 06/11/03 1.7 wvd Pass datatype to cf_read_col and
+ * cf_write_col.
+ * 08/25/03 1.8 wvd Change coltype from string to int in
+ * cf_read_col and cf_write_col.
+ * 09/16/03 1.9 wvd Write comment lines to IDF header if
+ * -w option is requested.
+ * 10/31/03 1.10 wvd Change channel to unsigned char.
+ * 12/03/03 1.11 wvd Initialize astig_return to 1.
+ * 04/06/04 1.12 bjg Function returns EXIT_SUCCESS
+ * Fix option[]
+ * 06/21/04 1.13 wvd If -w flag is set, run the program
+ * even if it's been run before.
+ * 05/20/05 1.14 wvd Clean up i/o.
+ * 05/15/06 1.15 wvd Divide cf_astigmatism_and_dispersion
+ * into two routines. Note that wave-
+ * length calibration is performed even
+ * if astigmatism correction is not.
+ *
+ ****************************************************************************/
+
+#include <unistd.h>
+#include <stdlib.h>
+#include "calfuse.h"
+
+int
+main(int argc, char *argv[])
+{
+ char CF_PRGM_ID[] = "cf_assign_wavelength";
+ char CF_VER_NUM[] = "1.15";
+
+ char comment[FLEN_CARD], datestr[FLEN_CARD];
+ unsigned char *channel=NULL;
+ int astig_corr=1, doppler_corr=1, status=0, optc, timeref;
+ int astig_return=1, wavecal = FALSE;
+ long nevents, nseconds;
+ float *time=NULL, *x=NULL, *y=NULL, *lambda=NULL, *timeline=NULL;
+ float *velocity=NULL;
+ fitsfile *header;
+
+ char opts[] = "hadwv:";
+ char usage[] =
+ "Usage:\n"
+ " cf_assign_wavelength [-hadw] [-v level] idf_file\n";
+ char option[] =
+ "Options:\n"
+ " -h: this help message\n"
+ " -v: verbose mode (default is 1; 0 is silent)\n"
+ " -a: no astigmatism correction\n"
+ " -d: no doppler correction\n"
+ " -w: write astigmatism-corrected X values to IDF\n";
+
+ verbose_level = 1;
+
+ 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;
+ case 'a':
+ astig_corr = 0;
+ break;
+ case 'd':
+ doppler_corr = 0;
+ break;
+ case 'w':
+ wavecal = TRUE;
+ break;
+ }
+ }
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+ if (argc <= optind) {
+ printf("%s", usage);
+ cf_if_error("Incorrect number of program arguments");
+ }
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Begin Processing");
+
+ FITS_open_file(&header, argv[optind], READWRITE, &status);
+
+ FITS_movabs_hdu(header, 2, NULL, &status);
+ nevents = cf_read_col(header, TFLOAT, "TIME", (void **) &time);
+ nevents = cf_read_col(header, TFLOAT, "X", (void **) &x);
+ nevents = cf_read_col(header, TFLOAT, "Y", (void **) &y);
+ nevents = cf_read_col(header, TBYTE, "CHANNEL",(void **) &channel);
+ nevents = cf_read_col(header, TFLOAT, "LAMBDA", (void **) &lambda);
+
+ FITS_movabs_hdu(header, 4, NULL, &status);
+ nseconds = cf_read_col(header, TFLOAT, "TIME", (void **) &timeline);
+ nseconds = cf_read_col(header, TFLOAT, "ORBITAL_VEL", (void **) &velocity);
+ FITS_movabs_hdu(header, 1, NULL, &status);
+
+ if (wavecal) {
+ FITS_update_key(header, TSTRING, "WAVE_COR", "PERFORM", NULL, &status);
+ FITS_update_key(header, TSTRING, "DOPP_COR", "PERFORM", NULL, &status);
+ }
+
+ /* Correct X coordinate for 2-D astigmatism. */
+ if (astig_corr)
+ astig_return = cf_astigmatism(header, nevents, x, y, channel);
+
+ /* Assign wavelength to each photon event according to channel and X */
+ cf_dispersion(header, nevents, x, channel, lambda);
+
+ /* Correct for spacecraft motion and shift to heliocentric wavelength scale. */
+ if (doppler_corr)
+ cf_doppler_and_heliocentric(header, nevents, time, channel,
+ lambda, nseconds, timeline, velocity);
+
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+ FITS_movabs_hdu(header, 2, NULL, &status);
+ cf_write_col(header, TBYTE, "CHANNEL", (void *) channel, nevents);
+ cf_write_col(header, TFLOAT, "LAMBDA", (void *) lambda, nevents);
+
+ /* If -w option is requested and astigmatism correction was applied,
+ write astigmatism-corrected X array to IDF. */
+ if (wavecal && !astig_return) {
+ cf_write_col(header, TFLOAT, "X", (void *) x, nevents);
+ FITS_movabs_hdu(header, 1, NULL, &status);
+ sprintf(comment, "Writing astigmatism-corrected X array to IDF.");
+ cf_if_warning(comment);
+ FITS_write_comment(header, " ", &status);
+ FITS_write_comment(header, comment, &status);
+ fits_get_system_time(datestr, &timeref, &status);
+ sprintf(comment, "CalFUSE v%s %.10s", CALFUSE_VERSION, datestr);
+ FITS_write_comment(header, comment, &status);
+ FITS_write_comment(header, " ", &status);
+ }
+
+ FITS_close_file(header, &status);
+
+ free(velocity);
+ free(timeline);
+ free(lambda);
+ free(channel);
+ free(y);
+ free(x);
+ free(time);
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Done processing");
+ return EXIT_SUCCESS;
+}
diff --git a/src/fuv/cf_bad_pixels.c b/src/fuv/cf_bad_pixels.c
new file mode 100644
index 0000000..a10ed20
--- /dev/null
+++ b/src/fuv/cf_bad_pixels.c
@@ -0,0 +1,1001 @@
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: cf_bad_pixels options input_file
+ *
+ * Description: Determines a map of the bad pixels on the detector, after
+ * correction for image motions during the observation. The
+ * procedure works by generating a series of pseudo photons
+ * corresponding to bad pixels within the area of the detector
+ * seen by the target aperture. This list of pseudo photons is
+ * repeated for each second of the observation where the data
+ * is expected to be acceptable (i.e., it excludes times of
+ * bursts, SAA passages, etc). The list is then run through
+ * various routines in the pipeline which correct for photon
+ * motions. A map is then generated from the final photon
+ * list.
+ *
+ * Arguments: input_file FARF-corrected intermediate data
+ * file
+ * Calibration files: QUAL_CAL
+ *
+ * Returns: file containing the bad pixel map
+ *
+ *
+ * History: 04/08/03 1.0 rdr Begin work
+ * 04/30/03 1.1 wvd Install
+ * 05/22/03 1.2 wvd Modify call to cf_set_photon_flags
+ * 05/28/03 1.3 rdr Made adjustments for HIST data and
+ * correct some bugs
+ * 05/04/03 1.4 wvd Reset JITR_COR and FLAG_COR to PERFORM.
+ * Pass weights to cf_set_photon_flags.
+ * 09/06/03 1.5 rdr Incorporate tscreen flag.
+ * 06/11/03 1.6 wvd Pass datatype to cf_read_col and
+ * cf_write_col.
+ * 08/22/03 1.7 wvd Change channel array to unsigned char.
+ * Delete GTI from call to
+ * cf_satellite_jitter.
+ * 08/25/03 1.8 wvd Change coltype from string to int in
+ * cf_read_col.
+ * 10/17/03 1.9 wvd If EXPTIME = 0, exit without
+ * generating a bad-pixel file.
+ * 11/05/03 1.10 wvd Change chan_pix to unsigned char
+ * 11/05/03 1.11 wvd Use fits_create_tbl alone to make
+ * binary table extension.
+ * 12/01/03 1.12 bjg Update FILENAME, FILETYPE and IDF_FILE
+ * keywords.
+ * 12/01/03 1.13 bjg Minor changes.
+ * 12/21/03 1.14 wvd Remove underscore from idf and bpm
+ * filenames.
+ * 02/24/04 1.15 rdr change maximum size of the output
+ * arrays in cf_combine_pothole_data
+ * 03/03/04 1.16 rdr make sure that lif_cnt and sic_cnt arrays
+ * are non-zero
+ * 04/06/04 1.19 bjg Include ctype.h and strings.h
+ * Change formats to match arg types in
+ * printf
+ * Change ( a<b & a>c ) to ((a<b)&&(a>c))
+ * in cf_combine_pothole_data
+ * Create potholes from HIST FILL_DATA
+ * 06/07/04 1.20 wvd Add exp_jitr to cf_satellite_jitter(),
+ * delete timeline from cf_apply_filters.
+ * 07/21/04 1.21 wvd Delete unused variable nmax in
+ * cf_generate_pseudo_photons
+ * 10/29/04 1.22 bjg Added check for selected potholes that
+ * fall out the extraction window
+ * 12/02/04 1.23 wvd If a processing step was skipped for
+ * the data file, skip it also for the
+ * bpm file.
+ * 01/27/05 1.24 wvd Ignore LIMB, SAA, and BRST when
+ * determining good times for HIST data.
+ * 02/01/05 1.25 wvd In cf_generate_pseudo_photons, pad
+ * extraction windows by ten pixels
+ * when making pothole list.
+ * In cf_combine_pothole_data, toss any
+ * potholes that drift out of extraction
+ * window. Call cf_get_extraction_limits
+ * only when the aperture changes.
+ * 02/17/05 1.26 wvd Increase estimated size of output
+ * pixel arrays (nmax) by 20%.
+ * Add additional diagnostic output.
+ * 03/15/05 1.27 wvd Replace cf_get_extraction_limits with
+ * cf_extraction_limits
+ * 03/16/05 1.28 wvd Pass srctype to cf_extraction_limits.
+ * 03/22/05 1.29 wvd Change TIME_SUNRISE and TIME_SUNSET
+ * from floats to shorts.
+ * 03/22/05 1.30 wvd In cf_combine_pothole_data, use fabs()
+ * when looking for changes in the time
+ * array.
+ * 04/12/05 1.31 wvd Add -n flag, which forces creation
+ * of night-only BPM file. Its argument
+ * is the name of the output BPM file.
+ * This file name is NOT written to the
+ * IDF file header.
+ * 06/03/05 1.32 wvd Include math.h
+ * 11/25/05 1.33 wvd Use cf_x2lambda and cf_get_potholes
+ * rather than writing new routines here.
+ * Don't add random numbers to output
+ * pixel coordinates.
+ * 05/15/06 1.34 wvd Divide cf_astigmatism_and_dispersion
+ * into two routines. Note that wave-
+ * length calibration is performed even
+ * if astigmatism correction is not.
+ * Add ASTG_COR to list of updated
+ * keywords.
+ * 06/13/06 1.35 wvd In cf_combine_pothole_data,
+ * initialize nfill to 0 before each
+ * iteration and ignore bad pixels that
+ * lie outside of the extraction window.
+ * 03/20/07 1.36 wvd In cf_combine_pothole_data, if the
+ * entire dead spot falls outside of the
+ * aperture, stop and move on to the
+ * next one.
+ * 03/21/07 1.37 wvd Replace "break" with "continue" in
+ * cf_combine_pothole_data.
+ * 04/03/07 1.38 wvd Scale nmax by 1.5. Call cf_error_init
+ * after each call to cf_extraction_limits.
+ * Make CF_PRGM_ID and CF_VER_NUM static
+ * variables.
+ * 04/03/07 1.39 bot In cf_generate_pseduo_photons, l.198
+ * and l.219 added a test on LOCATION_SHLD
+ * for FILL DATA.
+ * 07/18/08 1.40 wvd If EXP_STAT = 2, target is bright
+ * earth/airglow. Mask out limb-angle flag.
+ *
+ ****************************************************************************/
+
+#include <strings.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <math.h>
+#include "calfuse.h"
+
+static char CF_PRGM_ID[] = "cf_bad_pixels";
+static char CF_VER_NUM[] = "1.40";
+
+
+/****************************************************************************
+ *
+ * CF_GENERATE_PSEUDO_PHOTONS
+ *
+ * Procedure to generate an array of pseudo photons to represent the
+ * locations of the detector potholes
+ *
+ ****************************************************************************/
+
+int cf_generate_pseudo_photons(fitsfile *header, long ngood, long *good_index,
+ float *timeline, unsigned char *statflag, float *lif_cnt,
+ float *sic_cnt, long *nevents, float **time, float **weight,
+ float **x, float **y, unsigned char **channel, float **rx,
+ float **ry, unsigned char **timeflag, unsigned char **loc_flag) {
+
+ char instmode[FLEN_CARD] ;
+ long nevts, npot, nfill=0, npot_sel;
+ int *bpndx, npot2, status=0, hdutype ;
+ int srctype, ap[2], bymax, bymin, pad=10 ;
+ short *ylow, *yhigh;
+ long npts, i, j, k, xndx, num, num_tot, ndx, tndx ;
+ float *xpot, *ypot, *rxpot, *rypot ;
+ float *xpot2, *ypot2, *rxpot2, *rypot2 ;
+ float *xval, *yval, *rxval, *ryval, *xout, *yout, *rxout, *ryout ;
+ float *time_out, *weight_out, tval, ctot_lif, ctot_sic ;
+ float wval_lif, wval_sic ;
+ short binx, biny, xmin, xmax;
+ unsigned char *chan, *chan_out;
+ unsigned char *tflag_out, tflag_val ;
+ char * hdu2_loc_flgs;
+ float * hdu2_xfarf, * hdu2_yfarf;
+
+
+ cf_verbose(3, "Generating pseudo-photons") ;
+
+ /* read the instrument mode for the data */
+ FITS_movabs_hdu(header, 1, &hdutype, &status);
+ FITS_read_key(header, TSTRING, "INSTMODE", instmode, NULL, &status) ;
+ FITS_read_key(header, TSHORT, "SPECBINX", &binx, NULL, &status) ;
+ FITS_read_key(header, TSHORT, "SPECBINY", &biny, NULL, &status) ;
+
+ /* read the header and determine the target apertures for the exposure */
+ srctype = cf_source_aper(header, ap) ;
+ cf_verbose(3,"Target apertures = %d and %d ",ap[0],ap[1]) ;
+
+ /* read in the pothole positions */
+ npot2 = cf_get_potholes(header, &xpot2, &ypot2, &rxpot2, &rypot2) ;
+ cf_verbose(3, "number of potholes found = %d ",npot2) ;
+
+ if (!(strncasecmp(instmode,"HIST",4))) {
+ FITS_movabs_hdu(header, 2, &hdutype, &status);
+ nevts=cf_read_col(header,TBYTE,"LOC_FLGS",(void **) &hdu2_loc_flgs);
+ nevts=cf_read_col(header,TFLOAT,"XFARF",(void **) &hdu2_xfarf);
+ nevts=cf_read_col(header,TFLOAT,"YFARF",(void **) &hdu2_yfarf);
+ for (j=0;j<nevts;++j) {
+ if (!((hdu2_loc_flgs[j] & LOCATION_FILL) == 0) &&
+ ((hdu2_loc_flgs[j] & LOCATION_SHLD) == 0)) ++nfill;
+ }
+ cf_verbose(3, "number of FILL DATA potholes found = %d ",nfill) ;
+ npot=npot2+nfill;
+
+ xpot=(float *) cf_calloc(npot, sizeof(float)) ;
+ ypot=(float *) cf_calloc(npot, sizeof(float)) ;
+ rxpot=(float *) cf_calloc(npot, sizeof(float)) ;
+ rypot=(float *) cf_calloc(npot, sizeof(float)) ;
+
+ for (j=0;j<npot2;++j){
+ xpot[j]=xpot2[j];
+ ypot[j]=ypot2[j];
+ rxpot[j]=rxpot2[j];
+ rypot[j]=rypot2[j];
+ }
+
+ k=npot2;
+
+ for (j=0;j<nevts;++j){
+ if (!((hdu2_loc_flgs[j] & LOCATION_FILL) == 0) &&
+ ((hdu2_loc_flgs[j] & LOCATION_SHLD) == 0)) {
+
+ xpot[k]=hdu2_xfarf[j];
+ ypot[k]=hdu2_yfarf[j];
+ rxpot[k]=binx;
+ rypot[k]=biny;
+ k++;
+
+ }
+ }
+ free(hdu2_loc_flgs) ;
+ free(hdu2_xfarf) ;
+ free(hdu2_yfarf) ;
+ }
+ else {
+ npot=npot2;
+ xpot=xpot2;
+ ypot=ypot2;
+ rxpot=rxpot2;
+ rypot=rypot2;
+ }
+
+ /* allocate space to hold the pothole list (for 1 second of data) */
+ xval = (float *) cf_calloc(npot, sizeof(float)) ;
+ yval = (float *) cf_calloc(npot, sizeof(float)) ;
+ rxval = (float *) cf_calloc(npot, sizeof(float)) ;
+ ryval = (float *) cf_calloc(npot, sizeof(float)) ;
+ chan = (unsigned char *) cf_calloc(npot, sizeof(char)) ;
+ num=-1 ;
+
+
+ cf_verbose(3, "For initial pothole selection, "
+ "we pad extraction windows by %d pixels in Y.", pad);
+
+ /* do each aperture separately */
+
+ for (j=0 ; j<2; j++) {
+
+ /* get the extraction limits for the relevant apertures */
+ npts = cf_extraction_limits(header, ap[j], srctype,
+ &ylow, &yhigh, &xmin, &xmax) ;
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+ /* select potholes located within the extraction window */
+ bpndx = (int *) cf_calloc(npot, sizeof(int)) ;
+ npot_sel = -1 ;
+ for (i=0; i<npot; i++) {
+ xndx = (int) (xpot[i] + 0.5) ;
+ bymax = (int) (ypot[i]+rypot[i]+0.5) ;
+ bymin = (int) (ypot[i]-rypot[i]) ;
+ if ( bymax >= ylow[xndx] - pad && bymin <= yhigh[xndx] + pad ) {
+ npot_sel += 1 ;
+ bpndx[npot_sel] = i ;
+ cf_verbose(3, "pothole %d selected: x=%d, y=%d, rx=%d, ry=%d ", i,
+ cf_nint(xpot[i]),cf_nint(ypot[i]),cf_nint(rxpot[i]),cf_nint(rypot[i]));
+ }
+ }
+
+ /* convert npot_sel from an array index to a number of potholes selected */
+ npot_sel++ ;
+ cf_verbose(3, "number of potholes selected for ap %d = %d ",
+ ap[j], npot_sel) ;
+
+ /* put the locations into the output arrays */
+ for (i=0; i<npot_sel; i++) {
+ num+=1 ;
+ ndx = bpndx[i] ;
+ xval[num] = xpot[ndx] ;
+ yval[num] = ypot[ndx] ;
+ chan[num] = ap[j] ;
+ rxval[num] = rxpot[ndx] ;
+ ryval[num] = rypot[ndx] ;
+ }
+ }
+
+ /* convert num from an index to the number of potholes found */
+ num+=1 ;
+ cf_verbose(3, "total number of potholes found = %d ",num) ;
+
+ /* generate a timeline with only the good times included */
+ num_tot = num * ngood ;
+
+ /* copy the non-zero values into the output arrays */
+ time_out = (float *) cf_calloc(num_tot, sizeof(float)) ;
+ weight_out = (float *) cf_calloc(num_tot, sizeof(float)) ;
+ xout = (float *) cf_calloc(num_tot, sizeof(float)) ;
+ yout = (float *) cf_calloc(num_tot, sizeof(float)) ;
+ rxout = (float *) cf_calloc(num_tot, sizeof(float)) ;
+ ryout = (float *) cf_calloc(num_tot, sizeof(float)) ;
+ chan_out = (unsigned char *) cf_calloc(num_tot, sizeof(char)) ;
+ tflag_out = (unsigned char *) cf_calloc(num_tot, sizeof(char)) ;
+ *loc_flag = (unsigned char *) cf_calloc(num_tot, sizeof(char)) ;
+
+ tndx=-1 ;
+ ctot_lif = 0. ;
+ ctot_sic = 0. ;
+ for (j=0; j<ngood; j++) {
+ ndx=good_index[j] ;
+ tval = timeline[ndx] ;
+ ctot_lif += lif_cnt[ndx] ;
+ ctot_sic += sic_cnt[ndx] ;
+ wval_lif = lif_cnt[ndx] ;
+ wval_sic = sic_cnt[ndx] ;
+ tflag_val = statflag[ndx] ;
+ for (i=0; i<num; i++) {
+ tndx += 1;
+ if (tndx > num_tot -1) {
+ cf_verbose(2, "overflow tndx while filling pothole array ") ;
+ tndx= num_tot-1 ; }
+ time_out[tndx] = tval ;
+ if (chan[i] < 4) weight_out[tndx] = wval_lif ;
+ else weight_out[tndx] = wval_sic ;
+ xout[tndx] = xval[i] ;
+ yout[tndx] = yval[i] ;
+ rxout[tndx] = rxval[i] ;
+ ryout[tndx] = ryval[i] ;
+ chan_out[tndx] = chan[i] ;
+ tflag_out[tndx] = tflag_val ;
+ }
+ }
+
+ /* normalize the weights for TTAG data and set to 1 for HIST data*/
+ if (!strncmp(instmode,"T",1))
+ for (i=0; i<num_tot; i++) {
+ if (chan_out[i] < 4) weight_out[i] /= ctot_lif ;
+ else weight_out[i] /= ctot_sic ;
+ }
+ else for (i=0; i<num_tot; i++) weight_out[i] = 1. ;
+
+ /* assign pointers to output variables */
+ *x = xout ;
+ *y = yout ;
+ *rx = rxout ;
+ *ry = ryout ;
+ *channel = chan_out ;
+ *timeflag = tflag_out ;
+ *nevents = num_tot ;
+ *weight = weight_out ;
+ *time = time_out ;
+
+ free(xval) ;
+ free(yval) ;
+ free(rxval) ;
+ free(ryval) ;
+ free(chan) ;
+ free(bpndx) ;
+
+ return 0;
+
+}
+
+
+/*******************************************************************************
+ *
+ * CF_CORRECT_DOPPLER_MOTIONS
+ *
+ * procedure to correct the pothole centroid positions for doppler effects
+ *
+ ******************************************************************************/
+
+ int cf_correct_doppler_motions(fitsfile *header, long nevents, float *time,
+ float *x, unsigned char *channel, long nseconds, float *timeline,
+ float *velocity)
+{
+ char wave_file[FLEN_FILENAME];
+ float *wavelength, v_helio, vel, lam, dlam, dx;
+ fitsfile *wavefits;
+ int status=0, anynull;
+ int fcol, targ_ap[2], ap, ii;
+ long i, k, ndx ;
+
+ /* get the information needed in the analysis */
+
+ /* first determine the target apertures */
+ cf_source_aper(header, targ_ap) ;
+ cf_verbose(3, "target apertures = %d and %d ",targ_ap[0], targ_ap[1]) ;
+
+ /* read in the wavelength calibration */
+ FITS_read_key(header, TSTRING, "WAVE_CAL", wave_file, NULL, &status);
+ FITS_open_file(&wavefits, cf_cal_file(wave_file), READONLY, &status);
+ wavelength = (float *) cf_calloc(NXMAX, sizeof(float));
+
+ /* read the heliocentric velocity from the header */
+ FITS_read_key(header, TFLOAT, "V_HELIO", &v_helio, NULL, &status);
+ cf_verbose(3, "heliocentric velocity = %f ",v_helio) ;
+
+ /* Go through each target aperture */
+ for (i = 0; i < 2; i++) {
+ ap = targ_ap[i] ;
+
+ FITS_movabs_hdu(wavefits, ap+1, NULL, &status);
+ FITS_get_colnum(wavefits, TRUE, "WAVELENGTH", &fcol, &status);
+ fits_read_col(wavefits, TFLOAT, fcol, 1, 1, NXMAX, NULL, wavelength,
+ &anynull, &status);
+
+ ndx = 0 ;
+ for (k = 0; k < nevents; k++)
+ if (channel[k] == ap) {
+ while (time[k] >= timeline[ndx] ) ndx++ ;
+ if (ndx > nseconds-1 ) ndx=nseconds-1 ;
+ ii = (int) (x[k] + 0.5);
+ if (ii >= 1 && ii < NXMAX) {
+ lam = wavelength[ii];
+ vel = velocity[ndx] + v_helio ;
+ dlam = vel * lam / C ;
+ dx = dlam / ( wavelength[ii] - wavelength[ii-1]) ;
+ x[k] += dx ;
+ if (vel > 100 || vel < -100 )
+ cf_if_warning ("at k=%ld, time=%f, lam=%f, vel=%f, "
+ "dlam=%f, dx=%f \n",
+ k, time[k], lam, vel, dlam, dx) ;
+ }
+ }
+
+ }
+ free(wavelength);
+ FITS_close_file(wavefits, &status);
+
+ return status;
+}
+
+
+/*******************************************************************************
+ *
+ * CF_COMBINE_POTHOLE_DATA
+ *
+ * procedure to combine the centroid data as a function of time with the
+ * pothole size information to generate a list of affected pixels on the
+ * detector
+ *
+ ******************************************************************************/
+
+ long cf_combine_pothole_data(fitsfile *header, long nevents, float *time,
+ float *weight, float *x, float *rx, float *y, float *ry,
+ unsigned char *channel, unsigned char *timeflag, float **xpix,
+ float **ypix, unsigned char **chan_pix, float **wt_pix) {
+
+ int srctype, expstat, aperture[2];
+ int npot, xndx, yndx, ap, nfill ;
+ short sxmin, sxmax, *ylow, *yhigh ;
+ int xdim1, ydim1, xmin1, xmax1, ymin1, ymax1 ;
+ int xminp, xmaxp, yminp, ymaxp ;
+ long i, j, k, l, m, num, numt ;
+ long nout, nmax, npts1, npts2, xdim, ydim, ndx, ndxp ;
+ float *xpixt, *ypixt, *wt_pixt, xmin, xmax, ymin, ymax ;
+ float *array1, *array2, wtot, wval, wmax ;
+ float xv2, yv2, rx2, ry2, pos, xval, yval ;
+ float rxp, ryp, xv, yv, time0 ;
+ unsigned char *chan_pixt;
+
+ int status=0;
+ char instmode[FLEN_VALUE];
+ unsigned char TEMPORAL_MASK;
+
+ cf_verbose(3, "Combining pothole data") ;
+
+ /*
+ * Read INSTMODE keyword. If in HIST mode, mask out
+ * LIMB, SAA, and BRST flags. TEMPORAL_DAY is the default.
+ */
+ TEMPORAL_MASK = TEMPORAL_DAY;
+ FITS_read_key(header, TSTRING, "INSTMODE", instmode, NULL, &status);
+ if (!strncmp(instmode, "HIST", 4)) {
+ TEMPORAL_MASK |= TEMPORAL_LIMB;
+ TEMPORAL_MASK |= TEMPORAL_SAA;
+ TEMPORAL_MASK |= TEMPORAL_BRST;
+ }
+ /*
+ * If EXP_STAT = 2, target is bright earth/airglow. Mast out limb-angle flag.
+ */
+ FITS_read_key(header, TINT, "EXP_STAT", &expstat, NULL, &status);
+ if (expstat == 2) TEMPORAL_MASK |= TEMPORAL_LIMB;
+
+ /* Read source type from header. */
+ srctype = cf_source_aper(header, aperture) ;
+
+ /* determine the number of potholes by looking at the number
+ of entries for time=time[0] */
+
+ time0 = time[0] ;
+ i = 1 ;
+ while (fabs((time[i] - time0)) < 0.5) i++ ;
+ cf_verbose(3, "Number of potholes found = %d ", npot = i) ;
+
+ nmax = 0;
+ /* estimate size of the array needed to store the data and open
+ arrays to contain it */
+ for (i=0; i<npot; i++) nmax += (60.+2.*rx[i]) * (30.+2*ry[i]) ;
+ nmax *= 1.5;
+ cf_verbose(3, "Estimated storage space needed for output array = %d ",
+ nmax) ;
+ xpixt = (float *) cf_calloc(nmax, sizeof(float)) ;
+ ypixt = (float *) cf_calloc(nmax, sizeof(float)) ;
+ wt_pixt = (float *) cf_calloc(nmax, sizeof(float)) ;
+ chan_pixt = (unsigned char *) cf_calloc(nmax, sizeof(char)) ;
+
+ /* initialize nout = total number of pixels affected by potholes */
+ nout = -1 ;
+
+ /* process each pothole individually */
+
+ ap = -1;
+ for (i=0; i<npot; i++) {
+
+ nfill = 0;
+
+ /* If channel has changed, get the new extraction limits */
+ if (ap != (int) channel[i]) {
+ ap = (int) channel[i] ;
+ (void) cf_extraction_limits(header, ap, srctype,
+ &ylow, &yhigh, &sxmin, &sxmax);
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+ }
+
+ /* determine the range in X and Y for the pothole centroid positions */
+ xmin = 17000. ;
+ xmax = 0. ;
+ ymin = 1024. ;
+ ymax = 0. ;
+ numt = 0 ;
+ for (j=i; j<nevents ; j+= npot) {
+ numt ++ ;
+ if ((x[j] > xmax) && (x[j] < 16383)) xmax = x[j] ;
+ if ((x[j] < xmin) && (x[j] > 0)) xmin = x[j] ;
+ if ((y[j] > ymax) && (y[j] < 1023)) ymax = y[j] ;
+ if ((y[j] < ymin) && (y[j] > 0)) ymin = y[j] ;
+ }
+ cf_verbose(3,"For pothole %.1d, xmin=%.1d, "
+ "xmax=%.1d, ymin=%.1d, ymax=%.1d",
+ i, cf_nint(xmin), cf_nint(xmax), cf_nint(ymin), cf_nint(ymax)) ;
+
+ /* set up a 2D array which contains all of the movement in the pothole */
+ xdim = (long) (xmax - xmin + 1.5) ;
+ ydim = (long) (ymax - ymin + 1.5) ;
+ npts1 = xdim * ydim ;
+ cf_verbose(3, "Setting up array1: xdim=%d, ydim=%d, npts=%d ",
+ xdim, ydim, npts1) ;
+ array1 = (float *) cf_calloc(npts1, sizeof(float)) ;
+
+ /* Determine the 2D distribution of positions for the pothole */
+ num = 0 ;
+ for (j=i ; j<nevents ; j+= npot)
+ if (!(timeflag[j] & ~TEMPORAL_MASK)) {
+ num++ ;
+ xndx = cf_nint(x[j] - xmin) ;
+ if (xndx < 0 ) xndx = 0 ;
+ if (xndx > xdim-1) xndx = xdim-1 ;
+ yndx = cf_nint(y[j] - ymin) ;
+ if (yndx < 0 ) yndx = 0 ;
+ if (yndx > ydim-1) yndx = ydim-1 ;
+ ndx = xndx + yndx*xdim ;
+ if (ndx > npts1-1) ndx=npts1-1 ;
+ array1[ndx] += weight[j] ;
+ }
+
+ if (i == 0 ) cf_verbose(3, "%d good seconds out of a total of %d ",
+ num, numt) ;
+
+ wtot=0. ;
+ for(j=0; j<ydim; j++)
+ for (k=0; k<xdim; k++) wtot += array1[j*xdim + k] ;
+ cf_verbose(3, "wtot for array 1= %d", cf_nint(wtot)) ;
+
+ /* specify the size of the pothole */
+ rxp = rx[i] ;
+ rx2 = rxp * rxp ;
+ ryp = ry[i] ;
+ ry2 = ryp * ryp ;
+ cf_verbose(3,"pothole size: rx=%d, ry=%d ",cf_nint(rxp),cf_nint(ryp));
+
+ /* set up a target array to contain the image of the full pothole, after
+ reconstruction */
+ xmax1 = xmax + rxp ;
+ xmin1 = xmin - rxp ;
+ xdim1 = (int) (xmax1 - xmin1 + 1.5) ;
+ xndx = (long) x[i] ;
+ ymax1 = ymax + ryp ;
+ ymin1 = ymin - ryp ;
+ cf_verbose(3,"area of the detector covered by pothole :") ;
+ cf_verbose(3, " xmin=%d, xmax=%d, ymin=%d, ymax=%d ",
+ xmin1,xmax1,ymin1,ymax1) ;
+ cf_verbose(3,"extraction window extends from %d to %d ",ylow[xndx], yhigh[xndx]) ;
+
+ /* Include only pixels that lie within extraction window. */
+ if (ymin1 < ylow[xndx]) ymin1 = ylow[xndx];
+ if (ymax1 > yhigh[xndx]) ymax1 = yhigh[xndx];
+ ydim1 = (int) (ymax1 - ymin1 + 1.5) ;
+
+ /* If no pixels overlap the extraction window, skip to the next one. */
+ if (ydim1 <= 0) {
+ cf_verbose(3, "This pothole does not overlap the extraction window. We'll skip it.");
+ continue;
+ }
+
+ npts2 = xdim1 * ydim1 ;
+ cf_verbose(3, "setting up array2: xdim = %d, ydim = %d, npts2 = %d ",
+ xdim1, ydim1, npts2) ;
+ array2 = (float *) cf_calloc(npts2, sizeof(float)) ;
+
+ /* fill in array2
+ - scan all of the positions specified in array1 */
+ for (j=0 ; j<ydim ; j++)
+ for (k=0 ; k<xdim ; k++){
+ /* specify the properties of the pothole at this location */
+ xval = k + xmin ;
+ yval = j + ymin ;
+ ndx = j*xdim + k ;
+ if (ndx > npts1-1) ndx=npts1-1 ;
+ wval = array1[ndx] ;
+
+ if (wval > 0) {
+ /* set limits to the region of array2 affected by the pothole */
+ xminp = (int) (xval - rxp - xmin1 + 0.5) ;
+ xmaxp = (int) (xval + rxp - xmin1 + 0.5) ;
+ yminp = (int) (yval - ryp - ymin1 + 0.5) ;
+ ymaxp = (int) (yval + ryp - ymin1 + 0.5) ;
+ if (yminp < 0) yminp = 0 ;
+ if (ymaxp > ydim1-1) ymaxp = ydim1-1 ;
+ if (xminp < 0) xminp = 0 ;
+ if (xmaxp > xdim1-1) xmaxp = xdim1-1 ;
+
+ /* fill in the array for this pothole location */
+ for (l=yminp; l<=ymaxp; l++)
+ for (m=xminp; m <= xmaxp ; m++) {
+ ndxp = l * xdim1 + m ;
+ if (ndxp > npts2-1) ndxp = npts2 -1 ;
+ xv = m + xmin1 - xval ;
+ yv = l + ymin1 - yval ;
+ xv2= xv * xv ;
+ yv2 = yv * yv ;
+ pos = (xv2/rx2) + (yv2/ry2) ;
+ if ( pos <= 1) array2[ndxp] += wval ;
+ nfill++;
+ }
+ }
+ }
+
+ cf_verbose(3,"number of pixels affected by this pothole = %d ",nfill);
+
+ /* determine the maximum weights across the pothole map */
+ wmax=0. ;
+ for(j=0; j<ydim1; j++)
+ for (k=0; k<xdim1; k++) {
+ ndx = j * xdim1 + k ;
+ if (array2[ndx] > wmax) wmax = array2[ndx] ;
+ }
+ cf_verbose(3, "wmax for array2 = %d ", cf_nint(wmax)) ;
+
+ /* normalize the values of the affected pixels to the maximum and put
+ their locations into the output array */
+ for(j=0; j<ydim1; j++)
+ for (k=0; k<xdim1; k++) {
+ ndx = j * xdim1 + k ;
+ if (array2[ndx] > 0) {
+ if (nout < nmax-1) {
+ nout ++ ;
+ xpixt[nout] = k + xmin1;
+ ypixt[nout] = j + ymin1;
+ wt_pixt[nout] = array2[ndx]/wmax ;
+ chan_pixt[nout] = channel[i] ;
+ }
+ else {
+ cf_if_warning("Array overflow. Truncating pseudo-photon list.");
+ break;
+ }
+ }
+ }
+
+
+ cf_verbose(3, "%d points tabulated after processing pothole %d\n",nout,i);
+
+ free(array1) ;
+ free(array2) ;
+ }
+
+ /* assign output pointers */
+ *xpix = xpixt ;
+ *ypix = ypixt ;
+ *wt_pix = wt_pixt ;
+ *chan_pix = chan_pixt ;
+
+ cf_verbose(3, "Total number of pixels tabulated = %d ", nout) ;
+
+ return nout ;
+}
+
+
+/****************************************************************************/
+
+int
+main(int argc, char *argv[])
+{
+ unsigned char *timeflag=NULL, *statflag=NULL, *locflag=NULL;
+ unsigned char *loc_flag=NULL, *channel=NULL ;
+ int grating_motion=1, mirror_motion=1, fpa_pos=1;
+ int jitter=1, doppler_motion=1, astig=1, tscreen=1, night_only=FALSE;
+ int status=0, hdutype, optc;
+ long nevents, nseconds, i, nrows=1, npixels ;
+ long ngood, *good_index, dtime, ntime ;
+ float exptime, *time=NULL, *x=NULL, *y=NULL, *velocity=NULL;
+ float *rx=NULL, *ry=NULL, *xpix, *ypix, *wt_pix ;
+ float *lif_cnt=NULL, *sic_cnt=NULL, *lambda=NULL ;
+ float *timeline=NULL, *weight=NULL;
+ short *tsunrise=NULL, *tsunset=NULL ;
+ fitsfile *header, *bpmfits, *memp;
+ char rootname[FLEN_VALUE]={'\0'}, bpm_file[FLEN_FILENAME]={'\0'};
+ char idf_file[FLEN_FILENAME]={'\0'}, det[FLEN_VALUE]={'\0'};
+ char *keywords[] = {"GRAT_COR","FPA__COR","MIRR_COR","ASTG_COR","WAVE_COR"};
+ char keyval[FLEN_VALUE];
+ unsigned char *chan_pix ;
+
+ char extname[]="POTHOLE_DATA", fmt_float[FLEN_VALUE], fmt_byte[FLEN_VALUE] ;
+ char instmode[FLEN_VALUE] ;
+ int tfields=5 ;
+ char *ttype[]={ "X", "Y", "CHANNEL", "WEIGHT", "LAMBDA"} ;
+ char *tform[5] ; /* we will define the tform once the number of
+ array elements is known */
+ char *tunit[]={ "pixels", "pixels", "unitless", "unitless", "Angstroms"} ;
+
+ char opts[] = "hgmfjdasn:v:";
+ char usage[] =
+ "Usage:\n"
+ " cf_bad_pixels [-hvgmfjdas] [-n bpm_filename] [-v level] idffile\n";
+ char option[] =
+ "Options:\n"
+ " -h: this help message\n"
+ " -v: verbosity level (=1; 0 is silent)\n"
+ " -g: no grating motion correction \n"
+ " -m: no mirror motion correction \n"
+ " -n: Create BPM file for nighttime fraction of exposure.\n"
+ " Argument is the name of the output BPM file.\n"
+ " -f: no fpa motion correction \n"
+ " -j: no jitter correction \n"
+ " -d: no doppler correction \n"
+ " -a: no astigmatism correction \n"
+ " -s: no screening on time flags (if 0)" ;
+
+ verbose_level = 1;
+
+ 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;
+ case 'g':
+ grating_motion = 0 ;
+ break;
+ case 'm':
+ mirror_motion = 0 ;
+ break ;
+ case 'n':
+ sprintf(bpm_file,"%s", optarg) ;
+ night_only = TRUE;
+ break;
+ case 'f':
+ fpa_pos = 0 ;
+ break ;
+ case 'j':
+ jitter = 0 ;
+ break ;
+ case 'a':
+ astig = 0 ;
+ break;
+ case 'd':
+ doppler_motion = 0 ;
+ break ;
+ case 's':
+ tscreen = 0 ;
+ break ;
+
+ }
+ }
+
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+ if (argc <= optind) {
+ printf("%s", usage);
+ return -1;
+ }
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Begin Processing");
+
+ /* Open the input IDF file. */
+ FITS_open_file(&header, argv[optind], READWRITE, &status);
+ FITS_read_key(header, TSTRING, "INSTMODE", instmode, NULL, &status) ;
+
+ /* If EXPTIME < 1, exit without generating a bad-pixel file. */
+ FITS_read_key(header, TFLOAT, "EXPTIME", &exptime, NULL, &status);
+ if (night_only)
+ FITS_read_key(header, TFLOAT, "EXPNIGHT", &exptime, NULL, &status);
+ if (exptime < 1.) {
+ cf_verbose(1, "EXPTIME = %g. "
+ "Will not attempt to generate bad-pixel map.", exptime);
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Done processing");
+ return 0;
+ }
+
+ /* Read timeline data from the input file */
+ FITS_movabs_hdu(header, 4, &hdutype, &status);
+ nseconds = cf_read_col(header, TFLOAT, "TIME", (void **) &timeline);
+ nseconds = cf_read_col(header, TBYTE, "STATUS_FLAGS", (void **) &statflag);
+ nseconds = cf_read_col(header, TSHORT, "TIME_SUNRISE", (void **) &tsunrise);
+ nseconds = cf_read_col(header, TSHORT, "TIME_SUNSET", (void **) &tsunset) ;
+ nseconds = cf_read_col(header, TFLOAT, "ORBITAL_VEL", (void **) &velocity);
+ nseconds = cf_read_col(header, TFLOAT, "LIF_CNT_RATE", (void **) &lif_cnt) ;
+ nseconds = cf_read_col(header, TFLOAT, "SIC_CNT_RATE", (void **) &sic_cnt) ;
+ FITS_movabs_hdu(header, 1, NULL, &status);
+
+ /*
+ * If night-only spectrum is requested from the command line, copy
+ * IDF header into memory, close the IDF, modify copy, and pass it
+ * to subsequent routines.
+ */
+ if (night_only) {
+ cf_verbose(3, "Night-only spectrum requested from command line.");
+ FITS_create_file(&memp, "mem://", &status);
+ FITS_copy_hdu(header, memp, 0, &status);
+ if (!strncmp(instmode, "H",1)) {
+ FITS_movabs_hdu(header, 2, NULL, &status);
+ FITS_copy_hdu(header, memp, 0, &status);
+ }
+ FITS_close_file(header, &status);
+ header = memp;
+
+ FITS_movabs_hdu(header, 1, NULL, &status);
+ FITS_update_key(header, TFLOAT, "EXPTIME", &exptime, NULL, &status);
+ FITS_update_key(header, TSTRING, "DAYNIGHT", "NIGHT", NULL, &status);
+ }
+ else { /* Generate name of output file */
+ FITS_read_key(header, TSTRING, "ROOTNAME", rootname, NULL, &status) ;
+ FITS_read_key(header, TSTRING, "DETECTOR", det, NULL, &status) ;
+ det[1]=tolower(det[1]) ;
+ if (!strncmp(instmode, "T",1))
+ sprintf(bpm_file,"%11s%2sttagfbpm.fit",rootname,det) ;
+ else
+ sprintf(bpm_file,"%11s%2shistfbpm.fit",rootname,det) ;
+ }
+
+ /* Write name of BPM file to header of IDF. */
+ cf_verbose(3,"Output bad pixel map to file %s", bpm_file) ;
+ FITS_update_key(header, TSTRING, "BPM_CAL", bpm_file, NULL, &status);
+
+ /* Create the output file and copy header from the input */
+ FITS_create_file(&bpmfits, bpm_file, &status) ;
+ FITS_copy_hdu(header, bpmfits, 0, &status) ;
+
+ FITS_update_key(bpmfits, TSTRING, "FILENAME", bpm_file,
+ NULL, &status) ;
+ FITS_update_key(bpmfits, TSTRING, "FILETYPE", "BAD PIXEL MAP",
+ NULL, &status) ;
+
+ FITS_read_key(header, TSTRING, "FILENAME", idf_file, NULL, &status) ;
+ FITS_update_key(bpmfits, TSTRING, "IDF_FILE", idf_file,
+ NULL, &status) ;
+
+ /* Reset analysis keywords in the top level of the output file */
+ FITS_movabs_hdu(bpmfits, 1, &hdutype, &status);
+ for (i = 0; i < 5; i++) {
+ FITS_read_key(bpmfits, TSTRING, keywords[i], keyval, NULL, &status);
+ if (!strncmp(keyval, "COMPLETE", 8))
+ FITS_update_key(bpmfits, TSTRING, keywords[i], "PERFORM", NULL,
+ &status) ;
+ else
+ FITS_update_key(bpmfits, TSTRING, keywords[i], "OMIT", NULL,
+ &status) ;
+ }
+
+ /* Make sure that the count rates are non-zero */
+ for (i=0; i<nseconds; i++) {
+ if (lif_cnt[i] < 0.01) lif_cnt[i] = 0.01 ;
+ if (sic_cnt[i] < 0.01) sic_cnt[i] = 0.01 ;
+ }
+
+ /* generate a null array for locflag */
+ locflag = (unsigned char *) cf_calloc(nseconds, sizeof(unsigned char)) ;
+
+ /* select only the good times */
+ FITS_movabs_hdu(header, 1, &hdutype, &status);
+ cf_apply_filters(header, tscreen, nseconds, statflag, locflag, nseconds,
+ statflag, &dtime, &ntime, &ngood, &good_index) ;
+
+ free(locflag) ;
+
+ cf_verbose(3, "nseconds=%d, dtime=%d, ntime=%d, ngood=%d ",
+ nseconds, dtime, ntime, ngood) ;
+
+ /* Generate the pseudo photons */
+ cf_generate_pseudo_photons(header, ngood, good_index, timeline, statflag,
+ lif_cnt, sic_cnt, &nevents, &time, &weight, &x,
+ &y, &channel, &rx, &ry, &timeflag, &loc_flag) ;
+
+ if (night_only)
+ FITS_delete_file(header, &status);
+ else
+ FITS_close_file(header, &status);
+
+ cf_verbose(3, "number of pseudo photon events = %d ",nevents) ;
+
+ /* Call routines to remove motions */
+ if (grating_motion) {
+ cf_verbose(4,"Correcting for grating motions") ;
+ cf_grating_motion(bpmfits, nevents, time, x, y, channel,
+ nseconds, timeline, tsunrise) ; }
+ if (fpa_pos) {
+ cf_verbose(4,"Correcting for fpa motions ") ;
+ cf_fpa_position(bpmfits, nevents, x, channel) ;}
+ if (mirror_motion) {
+ cf_verbose(4,"Correcting for mirror motions") ;
+ cf_mirror_motion(bpmfits, nevents, time, x, y, channel,
+ nseconds, timeline, tsunset) ; }
+ if (jitter) {
+ cf_verbose(4,"Correcting for satellite jitter ") ;
+ cf_satellite_jitter(bpmfits, nevents, time, x, y, channel, nseconds,
+ timeline, statflag) ;
+ }
+
+ /* correct for the Doppler motions */
+ if (doppler_motion)
+ cf_correct_doppler_motions(bpmfits, nevents, time, x, channel,
+ nseconds, timeline, velocity) ;
+
+ /* combine the pothole centroid information and generate a pothole map by
+ including the pothole sizes and shapes */
+ npixels = cf_combine_pothole_data(bpmfits, nevents, time, weight,
+ x, rx, y, ry, channel, timeflag, &xpix, &ypix, &chan_pix, &wt_pix) ;
+
+ /* generate a blank wavelength array */
+ lambda = (float *) cf_calloc( npixels, sizeof(float) ) ;
+
+ /* correct for astigmatism and assign wavelengths */
+ if (astig) cf_astigmatism(bpmfits, npixels, xpix, ypix, chan_pix) ;
+ cf_dispersion(bpmfits, npixels, xpix, chan_pix, lambda);
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+ /* create a table and output the results to the file */
+ /* first set tform values */
+ cf_verbose(3, "Writing pseudo-pixel information to output file.");
+ sprintf(fmt_float, "%1ldE", npixels) ;
+ sprintf(fmt_byte, "%1ldB", npixels) ;
+ tform[0]=fmt_float ;
+ tform[1]=fmt_float ;
+ tform[2]=fmt_byte ;
+ tform[3]=fmt_float ;
+ tform[4]=fmt_float ;
+
+ /* put the data into the table */
+ FITS_create_tbl(bpmfits, BINARY_TBL, nrows, tfields, ttype, tform,
+ tunit, extname, &status) ;
+ cf_verbose(3, " Photon list created.");
+ FITS_write_col(bpmfits, TFLOAT, 1, 1L, 1L, npixels, xpix, &status) ;
+ cf_verbose(3, " X array has been written.");
+ FITS_write_col(bpmfits, TFLOAT, 2, 1L, 1L, npixels, ypix, &status) ;
+ cf_verbose(3, " Y array has been written.");
+ FITS_write_col(bpmfits, TBYTE, 3, 1L, 1L, npixels, chan_pix, &status) ;
+ cf_verbose(3, " Channel array has been written.");
+ FITS_write_col(bpmfits, TFLOAT, 4, 1L, 1L, npixels, wt_pix, &status) ;
+ cf_verbose(3, " Weights array has been written.");
+ FITS_write_col(bpmfits, TFLOAT, 5, 1L, 1L, npixels, lambda, &status) ;
+ cf_verbose(3, " Lambda array has been written.");
+
+ FITS_close_file(bpmfits, &status);
+
+ free(statflag);
+ free(timeline);
+ free(timeflag);
+ free(rx) ;
+ free(ry) ;
+ free(y);
+ free(x);
+ free(time);
+ free(xpix) ;
+ free(ypix) ;
+ free(chan_pix) ;
+ free(wt_pix) ;
+ free(lambda) ;
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Done processing");
+ return 0;
+}
diff --git a/src/fuv/cf_convert_to_farf.c b/src/fuv/cf_convert_to_farf.c
new file mode 100644
index 0000000..a50dd2e
--- /dev/null
+++ b/src/fuv/cf_convert_to_farf.c
@@ -0,0 +1,268 @@
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: cf_convert_to_farf options intermediate_file
+ *
+ * Description: Corrects the RAW data for IDS and electronic deadtime
+ * and for thermal, count rate, geometric, and PHA distortions.
+ * The resulting data are in the Flight Aligned Reference
+ * Frame (FARF), the location of an event on an ideal
+ * detector. The input file is modified in place.
+ *
+ * By default all corrections are performed. Command line
+ * options allow one or more corrections to be omitted.
+ *
+ * Arguments: input_file Intermediate data file
+ *
+ * Calibration files:
+ *
+ * Returns: 0 on successful completion
+ *
+ * Calls: cf_ids_dead_time, cf_electronics_dead_time,
+ * cf_thermal_distort, cf_count_rate_y_distort,
+ * cf_geometric_distort, cf_pha_x_distort
+ *
+ * History: 08/08/02 peb 1.1 Begin work
+ * 10/27/02 peb 1.3 Added IDS and electronics dead time
+ * corrections and time-dependent
+ * correction for count_rate_y_distort.
+ * Changed the help option to -h.
+ * Corrected function description.
+ * 11/12/02 peb 1.4 Added argument to cf_thermal_distort,
+ * cf_count_rate_y_distort, and
+ * cf_geometric_distort calls, so
+ * stim-pulse flag can be set.
+ * Added function to flag events in
+ * inactive regions.
+ * 12/09/02 wvd 1.5 Set keyword TOT_DEAD to mean value
+ * for exposure.
+ * 01/28/03 wvd 1.6 Added cf_check_digitizer
+ * 03/10/03 peb 1.7 Added verbose_level option and unistd.h
+ * so getopt.h will be portable.
+ * 03/10/03 peb 1.8 Changed locflgs to unsigned char *
+ * 03/10/03 peb 1.9 Changed pha to unsigned char *
+ * 06/11/03 wvd 1.10 Pass datatype to cf_read_col and
+ * cf_write_col.
+ * 06/16/03 rdr 1.11 Correct datatype in reading LOC_FLGS
+ * 08/01/03 wvd 1.12 Add cf_apply_dead_time to properly
+ * correct both TTAG and HIST data.
+ * 08/04/03 wvd 1.13 Convert count-rate arrays to shorts.
+ * 08/25/03 wvd 1.14 Change coltype from string to int in
+ * cf_read_col and cf_write_col.
+ * 11/26/03 wvd 1.15 Read aic_rate and fec_rate as floats.
+ * 02/09/04 wvd 1.16 Don't pass aic_rate to
+ * cf_apply_dead_time().
+ * 02/27/04 rdr 1.17 Added weight to cf_thermal_distortion
+ * 03/02/05 wvd 1.18 Must assign channel numbers and pulse-
+ * height values to HIST data before walk
+ * correction.
+ * Read XFARF and YFARF from XRAW and YRAW.
+ * 05/20/05 wvd 1.19 Clean up i/o.
+ * 11/02/06 wvd 1.20 Add call to cf_time_xy_distort.
+ * 12/29/06 wvd 1.21 Move cf_screen_fifo_overflow from
+ * cf_screen_photons. Rename it
+ * cf_fifo_dead_time. Set all dead-time
+ * keywords to 1.0 by default.
+ * 02/08/08 wvd 1.22 For HIST data, write modified PHA
+ * values to the IDF.
+ *
+ ****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "calfuse.h"
+
+int
+main(int argc, char *argv[])
+{
+ char CF_PRGM_ID[] = "cf_convert_to_farf";
+ char CF_VER_NUM[] = "1.22";
+
+ unsigned char *pha=NULL, *locflags=NULL;
+ char instmode[FLEN_VALUE], aperture[FLEN_VALUE];
+ int check_digitizer=1, ids_deadtime=1, elec_deadtime=1, fifo_deadtime=1;
+ int thermal_corr=1;
+ int countrate_corr=1, geometric_corr=1, pha_corr=1, active_flag=1;
+ int temporal_corr=1, status=0, hdutype, last_call, optc, pad;
+ long i, nevents, nseconds;
+ float *elec_dtc=NULL, *ids_dtc=NULL, unity = 1.0;
+ float *time=NULL, *xfarf=NULL, *yfarf=NULL, *weight=NULL;
+ float *timeline=NULL;
+ float *aic_rate=NULL, *fec_rate=NULL;
+ fitsfile *header;
+
+ char opts[] = "hceiftrsgpav:";
+ char usage[] =
+ "Usage:\n"
+ " cf_convert_to_farf [-hceiftrsgpa] [-v level] idf_file\n";
+ char option[] =
+ "Options:\n"
+ " -h: this help message\n"
+ " -v: verbosity level (default is 1; 0 is silent)\n"
+ " -c: no check of digitizer values\n"
+ " -e: no electronics deadtime correction\n"
+ " -i: no IDS deadtime correction\n"
+ " -f: no FIFO deadtime correction\n"
+ " -t: no thermal distortion correction\n"
+ " -r: no count-rate distortion correction\n"
+ " -s: no time-dependent distortion correction\n"
+ " -g: no geometric distortion correction\n"
+ " -p: no PHA distortion correction\n"
+ " -a: do not flag events beyond active region\n";
+
+ verbose_level=1;
+
+ 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;
+ case 'c':
+ check_digitizer = 0;
+ break;
+ case 'i':
+ ids_deadtime = 0;
+ break;
+ case 'e':
+ elec_deadtime = 0;
+ break;
+ case 'f':
+ fifo_deadtime = 0;
+ break;
+ case 't':
+ thermal_corr = 0;
+ break;
+ case 'r':
+ countrate_corr = 0;
+ break;
+ case 's':
+ temporal_corr = 0;
+ break;
+ case 'g':
+ geometric_corr = 0;
+ break;
+ case 'p':
+ pha_corr = 0;
+ break;
+ case 'a':
+ active_flag = 0;
+ break;
+ }
+ }
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+ if (argc <= optind) {
+ printf("%s", usage);
+ cf_if_error("Incorrect number of program arguments");
+ }
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Begin Processing");
+
+ FITS_open_file(&header, argv[optind], READWRITE, &status);
+
+ /* Read a couple of keywords from the file header. */
+ FITS_read_key(header, TSTRING, "INSTMODE", instmode, NULL, &status);
+ FITS_read_key(header, TSTRING, "APERTURE", aperture, NULL, &status);
+
+ FITS_movabs_hdu(header, 2, &hdutype, &status);
+ nevents = cf_read_col(header, TFLOAT, "TIME", (void **) &time);
+ nevents = cf_read_col(header, TBYTE, "PHA", (void **) &pha);
+ nevents = cf_read_col(header, TFLOAT, "XRAW", (void **) &xfarf);
+ nevents = cf_read_col(header, TFLOAT, "YRAW", (void **) &yfarf);
+ nevents = cf_read_col(header, TFLOAT, "WEIGHT", (void **) &weight);
+ nevents = cf_read_col(header, TBYTE, "LOC_FLGS", (void **) &locflags);
+
+ FITS_movabs_hdu(header, 4, &hdutype, &status);
+ nseconds = cf_read_col(header, TFLOAT, "TIME", (void **) &timeline);
+ nseconds = cf_read_col(header, TFLOAT, "FEC_CNT_RATE", (void **) &fec_rate);
+ nseconds = cf_read_col(header, TFLOAT, "AIC_CNT_RATE", (void **) &aic_rate);
+ FITS_movabs_hdu(header, 1, &hdutype, &status);
+
+ /* Initialize dead-time correction arrays and header keywords. */
+ FITS_update_key (header, TFLOAT, "DET_DEAD", &unity, NULL, &status);
+ FITS_update_key (header, TFLOAT, "IDS_DEAD", &unity, NULL, &status);
+ FITS_update_key (header, TFLOAT, "TOT_DEAD", &unity, NULL, &status);
+ elec_dtc = (float *) cf_malloc(sizeof(float) * nseconds);
+ ids_dtc = (float *) cf_malloc(sizeof(float) * nseconds);
+ for (i = 0; i < nseconds; i++) elec_dtc[i] = ids_dtc[i] = 1.0;
+
+ if (check_digitizer)
+ cf_check_digitizer(header);
+
+ if (elec_deadtime)
+ cf_electronics_dead_time(header, nseconds, fec_rate, elec_dtc);
+
+ if (ids_deadtime)
+ cf_ids_dead_time(header, nseconds, aic_rate, ids_dtc);
+
+ if (fifo_deadtime)
+ cf_fifo_dead_time(header, nevents, time,
+ nseconds, timeline, aic_rate, ids_dtc);
+
+ if (ids_deadtime || elec_deadtime || fifo_deadtime)
+ cf_apply_dead_time(header, nevents, time, weight,
+ nseconds, timeline, ids_dtc, elec_dtc);
+
+ if (thermal_corr)
+ cf_thermal_distort(header, nevents, xfarf, yfarf, weight, locflags);
+
+ if (countrate_corr)
+ cf_count_rate_y_distort(header, nevents, time, yfarf, locflags,
+ nseconds, timeline, fec_rate);
+ if (temporal_corr)
+ cf_time_xy_distort(header, nevents, xfarf, yfarf, locflags);
+
+ if (geometric_corr)
+ cf_geometric_distort(header, nevents, xfarf, yfarf, locflags);
+
+ /* Must assign PHA values to HIST data before applying walk correction. */
+ if (pha_corr && !strncmp(instmode, "HIST", 4)) {
+ unsigned char *channel;
+ channel = cf_calloc(nevents, sizeof(unsigned char));
+ if (!strncmp(aperture, "RFPT", 4)) pad = 10;
+ else pad = 100;
+ cf_identify_channel(header, nevents, xfarf, yfarf, channel, locflags,
+ pad, last_call=FALSE);
+ cf_modify_hist_pha(header, nevents, pha, channel);
+ free(channel);
+ }
+
+ if (pha_corr)
+ cf_pha_x_distort(header, nevents, pha, xfarf, locflags);
+
+ if (active_flag)
+ cf_active_region(header, nevents, xfarf, yfarf, locflags);
+
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+ FITS_movabs_hdu(header, 2, &hdutype, &status);
+ if (pha_corr && !strncmp(instmode, "HIST", 4))
+ cf_write_col(header, TBYTE, "PHA", (void *) pha, nevents);
+ cf_write_col(header, TFLOAT, "WEIGHT", (void *) weight, nevents);
+ cf_write_col(header, TFLOAT, "XFARF", (void *) xfarf, nevents);
+ cf_write_col(header, TFLOAT, "YFARF", (void *) yfarf, nevents);
+ cf_write_col(header, TBYTE, "LOC_FLGS", (void *) locflags, nevents);
+
+ FITS_close_file(header, &status);
+
+ free(fec_rate);
+ free(aic_rate);
+ free(timeline);
+ free(locflags);
+ free(weight);
+ free(yfarf);
+ free(xfarf);
+ free(pha);
+ free(time);
+ free(elec_dtc);
+ free(ids_dtc);
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Done processing");
+ return 0;
+}
diff --git a/src/fuv/cf_countmap.c b/src/fuv/cf_countmap.c
new file mode 100644
index 0000000..2d62b14
--- /dev/null
+++ b/src/fuv/cf_countmap.c
@@ -0,0 +1,541 @@
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: cf_countmap input_files
+ *
+ * Description: Adds the counts from a list of input idf files into
+ * the count map. The accumulated count map cube is
+ * determined by reading the COUNT_CAL keyword in the
+ * input file's header. To prevent multiple copies
+ * of reprocessed input files from being added to
+ * the total exposure map, if the input file has been
+ * previously added, it is skipped over and a message is
+ * printed out.
+ *
+ *
+ * Arguments: input_files Input initialized ttag FITS file names
+ *
+ * Calibration files required: None
+ *
+ * Returns: int 0 = successful completion
+ *
+ * Note: This routine requires significantly more memory than your
+ * average routine. Its design has not been optimized to
+ * reduce memory usage.
+ *
+ * History: 03/25/03 1.1 peb Begin and finish work. Based on
+ * cf_ttag_to_image
+ * 03/31/03 1.2 peb Removed filtering of photons and fixed
+ * exposure time bug when subtracting data
+ * 06/11/03 1.3 wvd Pass datatype to cf_read_col
+ * 08/25/03 1.4 wvd Change coltype from string to int in
+ * cf_read_col.
+ * 08/25/03 1.5 wvd Change CHIDCOR1 to CHID_COR
+ * 02/17/04 1.6 bjg Added scaling option
+ * Routine name changed from
+ * cf_ttag_countmap to cf_countmap.
+ * 02/26/04 1.7 bjg Added option to select coordinates
+ * to use: RAW, FARF (default), final
+ * 04/08/04 1.8 bjg Remove unused function get_xy_columns
+ * 04/27/04 1.9 bjg Change author name of countfile
+ * 08/25/04 1.10 bjg Added lower and upper limits option
+ * for PHA. In force mode, issue a warning
+ * if file already included.
+ * 03/02/05 1.11 wvd Don't write AUTHOR keyword to header.
+ * 08/24/07 1.12 bot Changed nx and ny to long and called
+ * as TLONG ; changed binx and biny to int
+ * and called as TINT.
+ *
+ ****************************************************************************/
+
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "calfuse.h"
+
+#define ROOT_LENGTH 13
+#define MAXCHARS 120
+#define MASTER_CAL_FILE "master_calib_file.dat"
+#define IMAGE_EXT 1
+#define INDEX_EXT 2
+
+static char CF_PRGM_ID[] = "cf_countmap";
+static char CF_VER_NUM[] = "1.12";
+
+
+static int
+new_imagfile(char *newfile, char *detector, float effmjd, int binx, int biny)
+{
+ char date[FLEN_CARD]={'\0'};
+ char *ttype[] = {"ROOTNAME", "OBSDATE", "COUNTS", "EXPTIME", "ADDDATE", "SCALE", "PHAMIN", "PHAMAX"};
+ char *tform[] = {"13A" , "19A" , "1J" , "1E" , "19A" , "1E" , "1I" , "1I" };
+ char *tunit[] = {" " , " " , "counts", "seconds", " " , " " , " " , " " };
+ int status=0, version=1, tref = 0, tfields = 8;
+ long axis[2];
+ float exptime=0.;
+ double nevents=0.;
+ fitsfile *imagfits;
+
+ FITS_create_file(&imagfits, newfile, &status);
+
+ axis[0] = NXMAX/binx;
+ axis[1] = NYMAX/biny;
+
+ FITS_create_img(imagfits, FLOAT_IMG, 2, axis, &status);
+ FITS_write_key(imagfits, TINT, "SPECBINX", &binx,
+ "Binsize in detector X coordinate", &status);
+ FITS_write_key(imagfits, TINT, "SPECBINY", &biny,
+ "Binsize in detector Y coordinate", &status);
+ FITS_write_key(imagfits, TSTRING, "CALFTYPE", "COUNT",
+ "Calibration file type", &status);
+ FITS_write_key(imagfits, TINT, "CALFVERS", &version,
+ "Calibration file version", &status);
+ FITS_write_key(imagfits, TSTRING, "DETECTOR", detector,
+ "detector (1A, 1B, 2A, 2B)", &status);
+ FITS_write_key(imagfits, TFLOAT, "EFFMJD", &effmjd,
+ "Date on which file should be applied (MJD)", &status);
+ fits_get_system_time(date, &tref, &status);
+ FITS_write_key(imagfits, TSTRING, "DATE", date,
+ "file creation date (YYYY-MM-DDThh:mm:ss UTC)", &status);
+ FITS_write_key(imagfits, TDOUBLE, "NEVENTS", &nevents,
+ "Accumulated events", &status);
+ FITS_write_key(imagfits, TFLOAT, "EXPTIME", &exptime,
+ "Accumulated exposure time", &status);
+
+ FITS_create_tbl(imagfits, BINARY_TBL, 0, tfields, ttype, tform, tunit,
+ "PROCESSED FILES", &status);
+
+ FITS_close_file(imagfits, &status);
+ return status;
+}
+
+static int
+_check_index(fitsfile *imagfits, char *rootname, float *scale, int *phamin, int *phamax)
+{
+ int status=0, anynull=0, hdutype;
+ float *scal;
+ int *phami, *phama;
+ long j, nrows, frow=1, felem=1;
+ char **filename, strnull[] = " ";
+
+ FITS_movabs_hdu(imagfits, INDEX_EXT, &hdutype, &status);
+ FITS_read_key(imagfits, TLONG, "NAXIS2", &nrows, NULL, &status);
+
+ filename = (char **) cf_malloc(nrows * sizeof(char *));
+ filename[0] = (char *) cf_malloc(nrows*(ROOT_LENGTH+1)*sizeof(char));
+ scal = (float *) cf_malloc(nrows * sizeof(float));
+ phami = (int *) cf_malloc(nrows * sizeof(int));
+ phama = (int *) cf_malloc(nrows * sizeof(int));
+ for (j=1; j<nrows; j++)
+ filename[j] = filename[j-1]+(ROOT_LENGTH+1);
+
+ FITS_read_col(imagfits, TSTRING, 1, frow, felem, nrows, strnull,
+ filename, &anynull, &status);
+ FITS_read_col(imagfits, TFLOAT, 6, frow, felem, nrows, strnull,
+ scal, &anynull, &status);
+ FITS_read_col(imagfits, TINT, 7, frow, felem, nrows, strnull,
+ phami, &anynull, &status);
+ FITS_read_col(imagfits, TINT, 8, frow, felem, nrows, strnull,
+ phama, &anynull, &status);
+
+ for (j=0; j<nrows; j++) {
+ if (strncmp(filename[j], rootname, strlen(rootname)) == 0) {
+ *scale = scal[j];
+ *phamin = phami[j];
+ *phamax = phama[j];
+ free(filename[0]);
+ free(filename);
+ free(scal);
+ return j+1;
+ }
+ }
+ free(filename[0]);
+ free(filename);
+ free(scal);
+ free(phami);
+ free(phama);
+ return 0;
+}
+
+static int
+_update_index(fitsfile *imagfits, char *rootname, char *obsdate,
+ double nevents, float exptime, float scale, int phamin, int phamax)
+{
+ char *strptr[1], adddate[FLEN_CARD]={'\0'};
+ int status=0, hdutype, tref=0;
+ long nrows;
+
+ FITS_movabs_hdu(imagfits, INDEX_EXT, &hdutype, &status);
+ FITS_read_key(imagfits, TLONG, "NAXIS2", &nrows, NULL, &status);
+
+ strptr[0] = rootname;
+ FITS_write_col(imagfits, TSTRING, 1, nrows+1, 1, 1, strptr, &status);
+ strptr[0] = obsdate;
+ FITS_write_col(imagfits, TSTRING, 2, nrows+1, 1, 1, strptr, &status);
+ FITS_write_col(imagfits, TDOUBLE, 3, nrows+1, 1, 1, &nevents, &status);
+ FITS_write_col(imagfits, TFLOAT, 4, nrows+1, 1, 1, &exptime, &status);
+ fits_get_system_time(adddate, &tref, &status);
+ strptr[0] = adddate;
+ fits_write_col(imagfits, TSTRING, 5, nrows+1, 1, 1, strptr, &status);
+ FITS_write_col(imagfits, TFLOAT, 6, nrows+1, 1, 1, &scale, &status);
+ FITS_write_col(imagfits, TINT, 7, nrows+1, 1, 1, &phamin, &status);
+ FITS_write_col(imagfits, TINT, 8, nrows+1, 1, 1, &phamax, &status);
+ return 0;
+}
+
+
+
+static double
+add_events(fitsfile *infits, char *xcolumn, char *ycolumn, float scale,
+ int phamin, int phamax, fitsfile *imagfits)
+{
+ int binx, biny, status=0, hdutype, anynull=0;
+ long nx, ny, nevents, j;
+ float *xpos, *ypos, *weight, *image;
+ char *pha;
+ double ncounts=0.;
+
+ FITS_movabs_hdu(infits, 2, &hdutype, &status);
+ nevents = cf_read_col(infits, TFLOAT, xcolumn, (void **) &xpos);
+ nevents = cf_read_col(infits, TFLOAT, ycolumn, (void **) &ypos);
+ nevents = cf_read_col(infits, TFLOAT, "WEIGHT", (void **) &weight);
+ nevents = cf_read_col(infits, TBYTE, "PHA", (void **) &pha);
+
+ FITS_movabs_hdu(imagfits, IMAGE_EXT, &hdutype, &status);
+ FITS_read_key(imagfits, TLONG, "NAXIS1", &nx, NULL, &status);
+ FITS_read_key(imagfits, TLONG, "NAXIS2", &ny, NULL, &status);
+ FITS_read_key(imagfits, TINT, "SPECBINX", &binx, NULL, &status);
+ FITS_read_key(imagfits, TINT, "SPECBINY", &biny, NULL, &status);
+
+ image = (float *) cf_malloc(sizeof(float)*nx*ny);
+ FITS_read_img(imagfits, TFLOAT, 1, nx*ny, NULL, image, &anynull, &status);
+
+ for (j=0; j<nevents; j++) {
+ if ((pha[j]>=phamin) && (pha[j]<=phamax)){
+ int x, y;
+ x = xpos[j];
+ y = ypos[j];
+ if ((x >= 0) && (x < nx*binx) && (y >= 0) && (y < ny*biny)) {
+ image[(y/biny)*nx + (x/binx)] += weight[j]*scale;
+ ncounts += weight[j]*scale;
+ }
+ }
+ }
+ FITS_write_img(imagfits, TFLOAT, 1, nx*ny, image, &status);
+
+ free(image);
+ free(weight);
+ free(ypos);
+ free(xpos);
+ return ncounts;
+}
+
+static double
+subtract_events(fitsfile *infits, char *xcolumn, char *ycolumn,
+ float scale, int phamin, int phamax, fitsfile *imagfits)
+{
+ int binx, biny, status=0, hdutype, anynull=0;
+ long nx, ny, nevents, j;
+ float *xpos, *ypos, *weight, *image;
+ double ncounts=0.;
+ char *pha;
+
+ FITS_movabs_hdu(infits, 2, &hdutype, &status);
+ nevents = cf_read_col(infits, TFLOAT, xcolumn, (void **) &xpos);
+ nevents = cf_read_col(infits, TFLOAT, ycolumn, (void **) &ypos);
+ nevents = cf_read_col(infits, TFLOAT, "WEIGHT", (void **) &weight);
+ nevents = cf_read_col(infits, TBYTE, "PHA", (void **) &pha);
+
+ FITS_movabs_hdu(imagfits, IMAGE_EXT, &hdutype, &status);
+ FITS_read_key(imagfits, TLONG, "NAXIS1", &nx, NULL, &status);
+ FITS_read_key(imagfits, TLONG, "NAXIS2", &ny, NULL, &status);
+ FITS_read_key(imagfits, TINT, "SPECBINX", &binx, NULL, &status);
+ FITS_read_key(imagfits, TINT, "SPECBINY", &biny, NULL, &status);
+
+ image = (float *) cf_malloc(sizeof(float)*nx*ny);
+ FITS_read_img(imagfits, TFLOAT, 1, nx*ny, NULL, image, &anynull, &status);
+
+ for (j=0; j<nevents; j++) {
+ if ((pha[j]>=phamin) && (pha[j]<=phamax)){
+ int x, y;
+ x = xpos[j];
+ y = ypos[j];
+ if ((x >= 0) && (x < nx*binx) && (y >= 0) && (y < ny*biny)) {
+ image[(y/biny)*nx + (x/binx)] -= weight[j]*scale;
+ ncounts += weight[j]*scale;
+ }
+ }
+ }
+ FITS_write_img(imagfits, TFLOAT, 1, nx*ny, image, &status);
+
+ free(image);
+ free(weight);
+ free(ypos);
+ free(xpos);
+ return ncounts;
+}
+
+
+int main(int argc, char *argv[])
+{
+ char *newfile = NULL, *detector = NULL, buffer[FLEN_CARD]={'\0'};
+ int subtract=0, force=0, newbinx=1, newbiny=1, status=0, optc;
+ float effmjd = 0.,scale=1.,old_scale;
+ int phamin=0, phamax=31;
+ int old_phamin, old_phamax;
+
+ char xcolumn[FLEN_CARD]={'\0'}, ycolumn[FLEN_CARD]={'\0'};
+
+ char opts[] = "hv:fsrcn:d:j:w:x:y:l:u:";
+ char usage[] =
+ "Usage:\n"
+ " cf_countmap [-hfsrc] [-v level] [-n filename] [-d segment]\n"
+ " [-w scale] [-j effmjd] [-x xbin] [-y ybin] \n"
+ " [-l phamin] [-u phamax] idffiles\n";
+ char option[] =
+ "Options:\n"
+ " -h: this help message\n"
+ " -v: verbosity level (=1; 0 is silent)\n"
+ " -f: force processing\n"
+ " -s: subtract files\n"
+ " -n: image map file\n"
+ " -d: image map segment (no default for new file)\n"
+ " -j: effective MJD (=0.0)\n"
+ " -w: weighting factor for image (=1.0)\n"
+ " -x: X-bin size (=1)\n"
+ " -y: Y-bin size (=1)\n"
+ " -r: use raw XY coordinates instead of farf\n"
+ " -c: use final XY coordinates instead of farf\n"
+ " -l: lower limit for pha (=0) \n"
+ " -u: upper limit for pha (=31) \n";
+
+ verbose_level = 1;
+
+ strcpy(xcolumn, "XFARF");
+ strcpy(ycolumn, "YFARF");
+
+ /* 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;
+ case 'f':
+ force = 1;
+ break;
+ case 's':
+ subtract = 1;
+ break;
+ case 'n':
+ newfile = optarg;
+ break;
+ case 'd':
+ detector = optarg;
+ break;
+ case 'j':
+ effmjd = atof(optarg);
+ break;
+ case 'w':
+ scale = atof(optarg);
+ break;
+ case 'x':
+ newbinx = atoi(optarg);
+ break;
+ case 'y':
+ newbiny = atoi(optarg);
+ break;
+ case 'r':
+ strcpy(xcolumn, "XRAW");
+ strcpy(ycolumn, "YRAW");
+ break;
+ case 'c':
+ strcpy(xcolumn, "X");
+ strcpy(ycolumn, "Y");
+ break;
+ case 'l':
+ phamin = atoi(optarg);
+ break;
+ case 'u':
+ phamax = atoi(optarg);
+ break;
+ }
+ }
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+ if (argc <= optind) {
+ cf_if_error("%s\nIncorrect number of program arguments", usage);
+ }
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Begin processing");
+
+ while (optind < argc) {
+
+ char imagfile[FLEN_CARD], rootname[FLEN_CARD]={'\0'};
+ char segment[FLEN_CARD] = {'\0'};
+ int hdutype;
+ FILE *fptr;
+ fitsfile *infits, *imagfits;
+
+ FITS_open_file(&infits, argv[optind], READONLY, &status);
+ FITS_movabs_hdu(infits, 1, &hdutype, &status);
+
+ if (newfile) {
+ strcpy(imagfile, newfile);
+
+ if ((fptr = fopen(imagfile, "r")))
+ fclose(fptr);
+ else {
+ if (!detector)
+ cf_if_error("No detector segment specified: "
+ "1A, 1B, 2A, 2B");
+ status = new_imagfile(imagfile, detector, effmjd,
+ newbinx, newbiny);
+ }
+ FITS_open_file(&imagfits, imagfile, READWRITE, &status);
+ FITS_movabs_hdu(imagfits, IMAGE_EXT, &hdutype, &status);
+ detector = buffer;
+ FITS_read_key(imagfits, TSTRING, "DETECTOR", detector, NULL,
+ &status);
+ }
+ else {
+ FITS_read_key(infits, TSTRING, "TCNT_MAP", imagfile, NULL,
+ &status);
+ detector = buffer;
+ FITS_read_key(infits, TSTRING, "DETECTOR", detector, NULL,
+ &status);
+
+ if ((fptr = fopen(cf_hist_file(imagfile), "r"))) {
+ fclose(fptr);
+ } else {
+ char keyword[FLEN_CARD]={'\0'}, segment[FLEN_CARD]={'\n'};
+ char linin[MAXCHARS]={'\0'}, filename[FLEN_CARD]={'\0'};
+ int interp;
+ float aftermjd;
+ FILE *master;
+ /*
+ * Get the effective MJD from the master calibration file
+ */
+ master = fopen(cf_parm_file(MASTER_CAL_FILE), "r");
+ if (master == NULL)
+ cf_if_error("Master calibration database file not found");
+ while (fgets(linin, MAXCHARS, master) != NULL) {
+ /*
+ * Check for comment lines
+ */
+ if ((linin[0] != '#') && (linin[0] != '\n')) {
+ sscanf(linin, "%4c%*2c%2c%*2c%13c%*2c%9f%*2c%1d",
+ keyword, segment, filename, &aftermjd, &interp);
+ if (strcmp(filename, imagfile) == 0) {
+ effmjd = aftermjd;
+ break;
+ }
+ }
+ }
+ fclose(master);
+
+ status = new_imagfile(cf_hist_file(imagfile), detector,
+ effmjd, newbinx, newbiny);
+ }
+ FITS_open_file(&imagfits, cf_hist_file(imagfile), READWRITE,
+ &status);
+ }
+
+ strncpy(rootname, argv[optind], ROOT_LENGTH);
+ FITS_read_key(infits, TSTRING, "DETECTOR", segment, NULL,
+ &status);
+ if (strcmp(detector, segment) != 0) {
+ cf_if_warning("%s segment is not the same as %s.",
+ argv[optind], imagfile);
+ }
+ else if (subtract) {
+ int index;
+ if ((index = _check_index(imagfits, rootname, &scale, &phamin, &phamax))) {
+
+ int hdutype;
+ float exptime=0., acctime=0.;
+ double nevents, accevnt=0.;
+
+ FITS_read_key(infits, TFLOAT, "EXPTIME", &exptime, NULL,
+ &status);
+
+
+ nevents = subtract_events(infits, xcolumn, ycolumn, scale, phamin, phamax, imagfits);
+
+ FITS_movabs_hdu(imagfits, IMAGE_EXT, &hdutype, &status);
+ FITS_read_key(imagfits, TDOUBLE, "NEVENTS", &accevnt,
+ NULL, &status);
+ FITS_read_key(imagfits, TFLOAT, "EXPTIME", &acctime,
+ NULL, &status);
+ accevnt -= nevents;
+ acctime -= exptime;
+ FITS_update_key(imagfits, TDOUBLE, "NEVENTS", &accevnt,
+ NULL, &status);
+ FITS_update_key(imagfits, TFLOAT, "EXPTIME", &acctime,
+ NULL, &status);
+
+ FITS_movabs_hdu(imagfits, INDEX_EXT, &hdutype, &status);
+ FITS_delete_rows(imagfits, index, 1, &status);
+ cf_verbose(1, "%s is subtracted from %s",
+ argv[optind], imagfile);
+ } else {
+ cf_if_warning("%s is not in %s.", argv[optind], imagfile);
+ }
+ } else {
+ if (!force && _check_index(imagfits, rootname, &old_scale, &old_phamin, &old_phamax)) {
+ cf_if_warning("%s is already in %s with scale = %f, phamin = %d, phamax=%d.",
+ argv[optind], imagfile, old_scale, old_phamin, old_phamax);
+ } else {
+ char obsdate[FLEN_CARD]={'\0'}, dateobs[FLEN_CARD]={'\0'};
+ char timeobs[FLEN_CARD]={'\0'};
+
+ float exptime=0., acctime=0.;
+ double nevents, accevnt=0;
+
+ FITS_movabs_hdu(imagfits, IMAGE_EXT, &hdutype, &status);
+ FITS_read_key(infits, TSTRING, "DATEOBS", dateobs, NULL,
+ &status);
+ FITS_read_key(infits, TSTRING, "TIMEOBS", timeobs, NULL,
+ &status);
+ obsdate[0] = '\0';
+ sprintf(obsdate, "%s%s%s", dateobs, "T", timeobs);
+ FITS_read_key(infits, TFLOAT, "EXPTIME", &exptime, NULL,
+ &status);
+
+ if ((force) && _check_index(imagfits, rootname, &old_scale, &old_phamin, &old_phamax))
+ cf_if_warning("FORCE MODE - %s is already in %s with scale = %f, phamin = %d, phamax=%d.",
+ argv[optind], imagfile, old_scale, old_phamin, old_phamax);
+
+ nevents = add_events(infits, xcolumn, ycolumn, scale, phamin, phamax, imagfits);
+
+ FITS_movabs_hdu(imagfits, IMAGE_EXT, &hdutype, &status);
+ FITS_read_key(imagfits, TDOUBLE, "NEVENTS", &accevnt,
+ NULL, &status);
+ FITS_read_key(imagfits, TFLOAT, "EXPTIME", &acctime,
+ NULL, &status);
+ accevnt += nevents;
+ acctime += exptime;
+ FITS_update_key(imagfits, TDOUBLE, "NEVENTS", &accevnt,
+ NULL, &status);
+ FITS_update_key(imagfits, TFLOAT, "EXPTIME", &acctime,
+ NULL, &status);
+
+ status = _update_index(imagfits, rootname, obsdate, nevents,
+ exptime, scale, phamin, phamax);
+ cf_verbose(1, "%s is added to %s", argv[optind], imagfile);
+ }
+ }
+ FITS_close_file(imagfits, &status);
+ FITS_close_file(infits, &status);
+ optind ++;
+ }
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Finished processing");
+ return 0;
+}
diff --git a/src/fuv/cf_extract_spectra.c b/src/fuv/cf_extract_spectra.c
new file mode 100644
index 0000000..6e06119
--- /dev/null
+++ b/src/fuv/cf_extract_spectra.c
@@ -0,0 +1,336 @@
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: cf_extract_spectra options intermediate_file
+ *
+ * Description: This module computes a background model, reads the various
+ * calibration files, and performs either a standard or optimal
+ * extraction for the target spectrum in each of the LiF and
+ * SiC channels.
+ *
+ * Note: some of the routines called by this module modify values
+ * in the IDF file header. We want those changes to appear in
+ * the final, extracted spectral files, but not in the archived
+ * IDF, so we make a copy in memory of the IDF header and pass it
+ * to the various routines. We delete it at the end.
+ *
+ * Arguments: input_file Intermediate data file
+ *
+ * Calibration files:
+ *
+ * Returns: 0 on successful completion
+ *
+ * Calls: cf_apply_filters, cf_scale_bkgd, cf_make_wave_array,
+ * cf_rebin_and_flux_calibrate, cf_rebin_probability_array,
+ * cf_standard_or_optimal_extraction, cf_optimal_extraction
+ * cf_write_extracted_spectrum
+ *
+ * History: 02/13/03 peb 1.1 Begin work
+ * 03/02/03 wvd 1.3 Add cf_standard_or_optimal_extraction()
+ * 03/10/03 peb 1.4 Added verbose_level, unistd.h for
+ * getopt portability, and remove debug
+ * print statements
+ * 04/08/03 wvd 1.6 Copy header of IDF into memory
+ * so that subsequent routines can
+ * modify it without changing IDF.
+ * Delete this virtual header when done.
+ * Read arrays from timeline table and
+ * pass to cf_apply_filters.
+ * 05/06/03 rdr 1.7 Read from column ERGCM2 rather than
+ * ERGCM2S
+ * 05/07/03 wvd 1.8 Change ergcm2 to ergcm2 throughout
+ * 05/28/03 rdr 1.9 Read pothole mask
+ * 06/09/03 rdr 1.10 Incorporate the tscreen flag
+ * 06/11/03 wvd 1.11 Pass datatype to cf_read_col
+ * 08/25/03 wvd 1.12 Change coltype from string to int in
+ * cf_read_col.
+ * 09/29/03 wvd 1.13 Move standard_or_optimal so that it
+ * runs just once. Don't check return
+ * values from subroutines.
+ * 10/08/03 wvd 1.14 Change counts_out array to type long.
+ * 10/16/03 wvd 1.15 If EXPTIME = 0, generate a pair of
+ * null-valued spectra and exit.
+ * 10/31/03 wvd 1.16 Change channel to unsigned char.
+ * 12/12/03 wvd 1.18 Clean up i/o.
+ * 03/16/04 wvd 1.19 Don't pass wave_out to optimal
+ * extraction subroutine.
+ * Change pycent from int to float.
+ * 03/24/04 wvd 1.20 Eliminate got_no_data(); fold into
+ * main routine. If either EXPTIME = 0
+ * or NEVENTS = 0, write null spectrum.
+ * 04/26/04 wvd 1.21 Replace cf_rebin_and_flux_calibrate
+ * background with cf_rebin_background.
+ * cf_optimal_extraction now returns
+ * flux_out and sigma_out in units of
+ * counts; must flux-calibrate each.
+ * 06/10/04 wvd 1.22 Don't pass time array from timeline
+ * table to cf_apply_filters.
+ * 06/11/04 peb 1.23 Add the -r option to override the
+ * default rootname.
+ * 01/28/05 wvd 1.24 If EXP_STAT < 0, generate a pair of
+ * null-valued spectra and exit.
+ * 03/09/05 wvd 1.25 Change cf_ttag_bkgd to cf_scale_bkgd,
+ * pass weights array to it.
+ * 04/12/05 wvd 1.27 Add -n flag, which forces extraction
+ * of night-only spectrum. Its argument
+ * is the name of a night-only BPM file.
+ * 06/15/05 wvd 1.28 BUG FIX: program always read the
+ * point-source probability arrays from
+ * the WGTS_CAL file. Now uses value
+ * of extended to determine which HDU
+ * to read.
+ * 11/23/05 wvd 1.29 Add flag to disable optimal
+ * extraction from the command line.
+ * 01/27/06 wvd 1.30 Add flag to force use of optimal
+ * extraction from the command line.
+ * 05/19/06 wvd 1.31 Don't discard spectra with non-zero
+ * values of EXP_STAT.
+ * 06/12/06 wvd 1.32 Change cf_if_warning to cf_verbose.
+ *
+ ****************************************************************************/
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include "calfuse.h"
+
+static char CF_PRGM_ID[] = "cf_extract_spectra";
+static char CF_VER_NUM[] = "1.32";
+
+int
+main(int argc, char *argv[])
+{
+ char *bpm_file=NULL, *outrootname = NULL;
+ unsigned char *channel=NULL, *timeflags=NULL, *loc_flags=NULL;
+ unsigned char *time_status=NULL;
+ int extended, status=0, optc, j, tscreen=1;
+ int binx, biny, bnx[2], bny[2], bymin[2], aper[2];
+ int night_only=FALSE, optimal=FALSE;
+ int force_optimal=FALSE, override_optimal=FALSE;
+ long nevents=0, ntimes=0, ngood=0, dtime=0, ntime=0, *good_index=NULL;
+ float *weight=NULL, *x=NULL, *y=NULL, *lambda=NULL;
+ float exptime, *bpmask=NULL ;
+ float *bimage[2]={NULL, NULL};
+
+ fitsfile *memp, *header;
+
+ char opts[] = "hn:ofr:sv:";
+ char usage[] =
+ "Usage:\n"
+ " cf_extract_spectra [-hsof] [-n bpm_filename] [-r rootname] [-v level]"
+ " idf_file\n";
+ char option[] =
+ "Options:\n"
+ " -h: this help message\n"
+ " -n: extract night-only spectrum using given bad-pixel map\n"
+ " -o: disable optimal extraction\n"
+ " -f: force optimal extraction\n"
+ " -r: override the default rootname\n"
+ " -s: do not perform screening on time flags\n"
+ " -v: verbosity level (=1; 0 is silent)\n" ;
+
+ verbose_level = 1;
+
+ while ((optc = getopt(argc, argv, opts)) != -1) {
+ switch(optc) {
+
+ case 'h':
+ printf("%s\n%s", usage, option);
+ return 0;
+ case 'n':
+ bpm_file = optarg;
+ night_only = TRUE;
+ break;
+ case 'o':
+ override_optimal = TRUE;
+ break;
+ case 'f':
+ force_optimal = TRUE;
+ break;
+ case 'r':
+ outrootname = optarg;
+ break;
+ case 'v':
+ verbose_level = atoi(optarg);
+ break;
+ case 's':
+ tscreen = 0 ;
+ break;
+ }
+ }
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+ if (argc <= optind) {
+ printf("%s", usage);
+ return -1;
+ }
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Begin Processing");
+
+ /* Open input data file. */
+ FITS_open_file(&header, argv[optind], READONLY, &status);
+ FITS_read_key(header, TFLOAT, "EXPTIME", &exptime, NULL, &status);
+
+ FITS_movabs_hdu(header, 2, NULL, &status);
+ nevents = cf_read_col(header, TFLOAT, "WEIGHT", (void **) &weight);
+ nevents = cf_read_col(header, TFLOAT, "X", (void **) &x);
+ nevents = cf_read_col(header, TFLOAT, "Y", (void **) &y);
+ nevents = cf_read_col(header, TBYTE, "CHANNEL", (void **) &channel);
+ nevents = cf_read_col(header, TBYTE, "TIMEFLGS", (void **) &timeflags);
+ nevents = cf_read_col(header, TBYTE, "LOC_FLGS", (void **) &loc_flags);
+ nevents = cf_read_col(header, TFLOAT, "LAMBDA", (void **) &lambda);
+
+ FITS_movabs_hdu(header, 4, NULL, &status);
+ ntimes = cf_read_col(header, TBYTE, "STATUS_FLAGS", (void **) &time_status);
+
+ /*
+ * Copy header of IDF into memory, close IDF,
+ * and pass copy of header to subsequent routines.
+ */
+ FITS_movabs_hdu(header, 1, NULL, &status);
+ FITS_create_file(&memp, "mem://", &status);
+ FITS_copy_hdu(header, memp, 0, &status);
+ FITS_close_file(header, &status);
+ header = memp;
+
+ /* If night-only spectrum is requested, modify header accordingly. */
+ if (night_only) {
+ cf_verbose(3, "Night-only spectrum requested from command line.");
+ FITS_read_key(header, TFLOAT, "EXPNIGHT", &exptime, NULL, &status);
+ FITS_update_key(header, TFLOAT, "EXPTIME", &exptime, NULL, &status);
+ FITS_update_key(header, TSTRING, "DAYNIGHT", "NIGHT", NULL, &status);
+ FITS_update_key(header, TSTRING, "BPM_CAL", bpm_file, NULL, &status);
+ }
+
+ extended = cf_source_aper(header, aper);
+
+ /* Determine whether to attempt optimal extraction. */
+ if (override_optimal) {
+ cf_verbose (1, "User set -o flag. No optimal extraction.");
+ optimal=FALSE;
+ }
+ else if (force_optimal) {
+ cf_verbose (1, "User set -f flag. Forcing use of optimal extraction.");
+ optimal=TRUE;
+ }
+ else cf_standard_or_optimal_extraction(header, &optimal);
+
+ /* Make list of all photons that satisfy requested screenings. */
+ cf_apply_filters(header, tscreen, nevents, timeflags, loc_flags,
+ ntimes, time_status, &dtime, &ntime, &ngood, &good_index);
+
+ /* Generate model backgrounds for LiF and SiC channels. */
+ cf_scale_bkgd(header, nevents, x, y, weight, channel, timeflags,
+ loc_flags, ngood, good_index, dtime, ntime, &binx, &biny,
+ &bnx[0], &bny[0], &bymin[0], &bimage[0],
+ &bnx[1], &bny[1], &bymin[1], &bimage[1]);
+
+ /* Run once for each of LiF and SiC target channels. */
+ for (j=0; j<2; j++) {
+ int pny, valid_spectrum=TRUE;
+ float pycent, wpc;
+ long *counts_out=NULL, i, nout=0, nphotons=0;
+ float *wave_out=NULL, *bkgd_out=NULL, *flux_out=NULL, *sigma_out=NULL;
+ float *weights_out=NULL, *barray=NULL, *parray=NULL;
+ short *bpix_out=NULL;
+ unsigned char *channel_temp=NULL;
+
+ /* Generate output wavelength array. */
+ cf_make_wave_array(header, aper[j], &nout, &wave_out);
+
+ /* If no data, generate null-valued output arrays. */
+ for (i = 0; i < ngood; i++) {
+ if (channel[good_index[i]] == aper[j]) {
+ nphotons++;
+ break;
+ }
+ }
+ if (exptime < 1. || nphotons < 1) {
+ bkgd_out = (float *) cf_calloc(nout, sizeof(float));
+ bpix_out = (short *) cf_calloc(nout, sizeof(short));
+ counts_out = (long *) cf_calloc(nout, sizeof(long));
+ flux_out = (float *) cf_calloc(nout, sizeof(float));
+ sigma_out = (float *) cf_calloc(nout, sizeof(float));
+ weights_out = (float *) cf_calloc(nout, sizeof(float));
+ valid_spectrum=FALSE;
+ cf_verbose(1, "No data for aperture %d. Generating "
+ "null-valued output spectrum.", aper[j]);
+ }
+ else { /* Extract target spectrum. */
+
+ /* Bin background model to match output wavelength array. */
+ cf_rebin_background(header, aper[j], nout, wave_out,
+ binx, biny, bnx[j], bny[j], bimage[j], &barray);
+
+ /* Use QUAL_CAL files to create a bad-pixel mask for this exposure. */
+ cf_make_mask(header, aper[j], nout, wave_out, bny[j], bymin[j],
+ &bpmask);
+
+ /* Bin the weights/probability array to match output wave array. */
+ cf_rebin_probability_array(header, extended, aper[j], nout,
+ wave_out, &pny, &pycent, &parray);
+
+ /* Use optimal extraction if possible, standard extraction otherwise. */
+ cf_optimal_extraction(header, optimal, aper[j],
+ weight, y, channel, lambda, ngood, good_index,
+ barray, bpmask, pny, pycent, parray, nout, wave_out, &flux_out,
+ &sigma_out, &counts_out, &weights_out, &bkgd_out, &bpix_out);
+
+ /* Optimal-extraction routine returns flux_out and sigma_out in units
+ of counts. Must flux-calibrate both arrays. */
+ channel_temp =
+ (unsigned char *) cf_malloc(sizeof(unsigned char) * nout);
+ memset (channel_temp, aper[j], sizeof(unsigned char) * nout);
+ FITS_read_key(header, TFLOAT, "WPC", &wpc, NULL, &status);
+ FITS_update_key(header, TSTRING, "FLUX_COR", "PERFORM", NULL,
+ &status) ;
+ cf_convert_to_ergs(header, nout, flux_out, flux_out, channel_temp,
+ wave_out);
+ FITS_update_key(header, TSTRING, "FLUX_COR", "PERFORM", NULL,
+ &status) ;
+ cf_convert_to_ergs(header, nout, sigma_out, sigma_out, channel_temp,
+ wave_out);
+ free(channel_temp);
+
+ /* Divide flux and errors by EXPTIME * WPC to get units of erg/cm2/s/A. */
+ for (i = 0; i < nout; i++) {
+ flux_out[i] /= exptime * wpc;
+ sigma_out[i] /= exptime * wpc;
+ }
+ }
+
+ /* Write extracted spectrum to output file. */
+ cf_write_extracted_spectrum(header, aper[j], valid_spectrum,
+ nout, wave_out, flux_out, sigma_out, counts_out,
+ weights_out, bkgd_out, bpix_out, outrootname);
+
+ free(counts_out);
+ free(bkgd_out);
+ free(weights_out);
+ free(sigma_out);
+ free(flux_out);
+ free(wave_out);
+ free(bpix_out) ;
+ free(parray);
+ free(barray);
+ }
+
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+ FITS_delete_file(header, &status);
+
+ free(bimage[1]);
+ free(bimage[0]);
+ free(lambda);
+ free(loc_flags);
+ free(timeflags);
+ free(channel);
+ free(y);
+ free(x);
+ free(weight);
+ free(time_status);
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Done processing");
+ return 0;
+}
diff --git a/src/fuv/cf_flux_calibrate.c b/src/fuv/cf_flux_calibrate.c
new file mode 100644
index 0000000..2ad92e6
--- /dev/null
+++ b/src/fuv/cf_flux_calibrate.c
@@ -0,0 +1,173 @@
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: cf_flux_calibrate options intermediate_file
+ *
+ * Description: Flux calibrate each photon assigned to a channel.
+ *
+ * ** NEXT STEPS COMMENTED OUT FOR NOW **
+ * For each photon in the target aperture,
+ * apply astigmatism correction to XFARF array and use the
+ * resulting coordinate system to apply flat-field and
+ * worm corrections to photon weights.
+ *
+ * By default all corrections are performed. Command line
+ * options allow one or more corrections to be omitted.
+ *
+ * Arguments: input_file Intermediate data file
+ *
+ * Calibration files: AEFF_CAL
+ *
+ * Returns: 0 on successful completion
+ *
+ * Calls: cf_effective_area, cf_astig_farf, cf_flat_field,
+ * cf_worm_correction
+ *
+ * History: 12/06/02 wvd 1.1 Begin work
+ * 02/12/03 wvd 1.2 Read ERGCM2S from IDF
+ * Move cf_convert_to_ergs to end of
+ * module
+ * 03/11/03 wvd 1.3 Change channel to type char
+ * 03/12/03 wvd 1.4 If ERGCM2S[i] is undefined,
+ * set channel[i] = 0
+ * 03/19/03 peb 1.5 Added verbose_level option.
+ * 05/06/03 rdr 1.6 Read from column ERGCM2 rather
+ * than ERGCM2S
+ * 05/07/03 wvd 1.7 Change ergcm2s to ergcm2
+ * 06/11/03 wvd 1.8 Pass datatype to cf_read_col and
+ * cf_write_col.
+ * Comment out call to cf_astig_farf().
+ * 08/25/03 wvd 1.9 Change coltype from string to int in
+ * cf_read_col and cf_write_col.
+ * 09/17/03 wvd 1.10 Add some documentation.
+ * 09/17/03 wvd 1.11 Change channel to unsigned char.
+ * 05/20/05 wvd 1.12 Clean up i/o.
+ *
+ ****************************************************************************/
+
+#include <unistd.h>
+#include <stdlib.h>
+#include "calfuse.h"
+
+static char CF_PRGM_ID[] = "cf_flux_calibrate";
+static char CF_VER_NUM[] = "1.12";
+
+int
+main(int argc, char *argv[])
+{
+ unsigned char *channel=NULL;
+ int effective_area=1, astig_farf=1, flat_field=1, worm_correction=1;
+ int status=0, hdutype, optc;
+ long nevents, nseconds;
+ float *time=NULL, *ttime=NULL, *xfarf=NULL, *yfarf=NULL, *weight=NULL;
+ float *lambda=NULL, *ycentl=NULL, *ycents=NULL, *ergcm2=NULL;
+ fitsfile *header;
+
+ char opts[] = "heafwv:";
+ char usage[] =
+ "Usage:\n"
+ " cf_flux_calibrate [-heafw] [-v level] idf_file\n";
+ char option[] =
+ "Options:\n"
+ " -h: this help message\n"
+ " -v: verbosity level (default is 1; 0 is silent)\n"
+ " -e: no effective-area calibration\n"
+ " -a: no astigmatism correction of XFARF array\n"
+ " -f: no flat-field correction\n"
+ " -w: no worm correction\n";
+
+ verbose_level = 1;
+
+ 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;
+ case 'e':
+ effective_area = 0;
+ break;
+ case 'a':
+ astig_farf = 0;
+ break;
+ case 'f':
+ flat_field = 0;
+ break;
+ case 'w':
+ worm_correction = 0;
+ break;
+ }
+ }
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+ if (argc != optind+1) {
+ printf("%s", usage);
+ cf_if_error("Incorrect number of command-line arguments");
+ }
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Begin Processing");
+
+ FITS_open_file(&header, argv[optind], READWRITE, &status);
+
+ FITS_movabs_hdu(header, 2, &hdutype, &status);
+ nevents = cf_read_col(header, TFLOAT, "TIME", (void **) &time);
+ nevents = cf_read_col(header, TFLOAT, "WEIGHT", (void **) &weight);
+ nevents = cf_read_col(header, TFLOAT, "XFARF", (void **) &xfarf);
+ nevents = cf_read_col(header, TFLOAT, "YFARF", (void **) &yfarf);
+ nevents = cf_read_col(header, TBYTE, "CHANNEL", (void **) &channel);
+ nevents = cf_read_col(header, TFLOAT, "LAMBDA", (void **) &lambda);
+ nevents = cf_read_col(header, TFLOAT, "ERGCM2", (void **) &ergcm2);
+
+ FITS_movabs_hdu(header, 4, &hdutype, &status) ;
+ nseconds = cf_read_col(header, TFLOAT, "TIME", (void **) &ttime) ;
+ nseconds = cf_read_col(header, TFLOAT, "YCENT_LIF", (void **) &ycentl) ;
+ nseconds = cf_read_col(header, TFLOAT, "YCENT_SIC", (void **) &ycents) ;
+
+ FITS_movabs_hdu(header, 1, &hdutype, &status);
+
+ /***************************************************************************
+ * Since we currently have no flat-field or worm correction,
+ * these subroutines are commented out.
+ *
+ if (astig_farf)
+ cf_astig_farf(header, nevents, xfarf, yfarf, channel, time,
+ nseconds, ttime, ycentl, ycents);
+ if (flat_field)
+ cf_flat_field(header, nevents, time, weight, xfarf, yfarf, channel,
+ nseconds, ttime, ycentl, ycents);
+
+ if (worm_correction)
+ cf_worm_correction(header, nevents, time, weight, xfarf, yfarf, channel,
+ nseconds, ttime, ycentl, ycents);
+ ***************************************************************************/
+
+ if (effective_area)
+ cf_convert_to_ergs(header, nevents, weight, ergcm2, channel, lambda);
+
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+ FITS_movabs_hdu(header, 2, &hdutype, &status);
+ cf_write_col(header, TFLOAT, "WEIGHT", (void *) weight, nevents);
+ cf_write_col(header, TBYTE, "CHANNEL", (void *) channel, nevents);
+ cf_write_col(header, TFLOAT, "ERGCM2", (void *) ergcm2, nevents);
+
+ FITS_close_file(header, &status);
+
+ free(time);
+ free(weight);
+ free(xfarf);
+ free(yfarf);
+ free(channel);
+ free(lambda);
+ free(ergcm2);
+ free(ttime);
+ free(ycentl);
+ free(ycents);
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Done processing");
+ return 0;
+}
diff --git a/src/fuv/cf_gainmap.c b/src/fuv/cf_gainmap.c
new file mode 100644
index 0000000..63ed3f7
--- /dev/null
+++ b/src/fuv/cf_gainmap.c
@@ -0,0 +1,610 @@
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: cf_gainmap input_files
+ *
+ * Description: Adds the counts from a list of input ttag idf files into
+ * the gain map. The accumulated gain map cube is
+ * determined by reading the GAIN_CAL keyword in the
+ * input file's header. To prevent multiple copies
+ * of reprocessed input files from being added to
+ * the total exposure map, the gain map contains an
+ * index list of the files which have been added.
+ * The new file is skipped if it is in the list.
+ *
+ *
+ * Arguments: input_files Input ttag IDF FITS file name
+ *
+ * Calibration files required: None
+ *
+ * Returns: int 0 = successful completion
+ *
+ * Note: This routine requires significantly more memory than your
+ * average routine. Its design has not been optimized to
+ * reduce memory usage.
+ *
+ * History: 03/31/03 1.1 peb Finished work.
+ * Based on cf_ttag_countmap.
+ * 06/11/03 1.2 wvd Pass datatype to cf_read_col
+ * 08/25/03 1.3 wvd Change coltype from string to int in
+ * cf_read_col.
+ * 01/09/04 1.4 bjg Change CHIDCOR1 to CHID_COR
+ * 02/17/04 1.5 bjg Added scaling option
+ * histogram files given in the argument
+ * list are ignored
+ * 02/26/04 1.6 bjg Bug Fix. Routine name changed from
+ * cf_ttag_gainmap to cf_gainmap.
+ * Added option to select coordinates
+ * to use: RAW, FARF (default), final
+ * Print ignored HIST files
+ * 04/08/04 1.7 bjg Remove unused function get_xy_columns
+ * Use cf_verbose instead of printf
+ * 04/27/04 1.8 bjg Added lower and upper limits option
+ * for PHA
+ * Change author name of gainfile
+ * 08/26/04 1.9 bjg In force mode, issue a warning
+ * if file already included.
+ * 03/02/05 1.10 wvd Use FLOAT_IMG to insure that output
+ * images are written as floats.
+ * 03/02/05 1.11 wvd Don't write AUTHOR keyword to header.
+ * 04/11/05 1.12 wvd Force detector string to be upper case.
+ * Add -t option, which prevents creation
+ * of detector image for PHA=31. It's
+ * required if you don't bin the data.
+ * 06/03/05 1.13 wvd Include ctype.h
+ * 09/09/05 1.14 wvd Update list of allowed options.
+ * 08/24/07 1.15 bot Changed nx and ny to long and called
+ * as TLONG ; changed binx and biny to int
+ * and called as TINT.
+ *
+ ****************************************************************************/
+
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "calfuse.h"
+
+#define ROOT_LENGTH 13
+#define MAXCHARS 120
+#define MASTER_CAL_FILE "master_calib_file.dat"
+#define IMAGE_EXT 1
+#define INDEX_EXT 34
+
+static char CF_PRGM_ID[] = "cf_gainmap";
+static char CF_VER_NUM[] = "1.15";
+
+
+static int
+new_gainfile(char *newfile, char *detector, float effmjd, int binx, int biny, int truncate)
+{
+ char date[FLEN_CARD]={'\0'};
+ char *ttype[] = {"ROOTNAME", "OBSDATE", "COUNTS", "EXPTIME", "ADDDATE", "SCALE", "PHAMIN", "PHAMAX"};
+ char *tform[] = {"13A", "19A", "1D", "1E", "19A", "1E", "1I", "1I"};
+ char *tunit[] = {" ", " ", "counts", "seconds", " ", " ", " ", " "};
+ int naxis=2, status=0, version=1, tref=0, tfields=8, phaext;
+ long axis[2], naxis2=0;
+ float exptime=0.;
+ double ncounts=0.;
+ fitsfile *gainfits;
+
+ cf_verbose(3, "Entering subroutine new_gainfile");
+ cf_verbose(3, "Creating file %s", newfile);
+
+ FITS_create_file(&gainfits, newfile, &status);
+
+ FITS_create_img(gainfits, 8, 0, NULL, &status);
+ FITS_write_key(gainfits, TSTRING, "CALFTYPE", "GAIN",
+ "Calibration file type", &status);
+ FITS_write_key(gainfits, TINT, "CALFVERS", &version,
+ "Calibration file version", &status);
+ FITS_write_key(gainfits, TSTRING, "DETECTOR", detector,
+ "detector (1A, 1B, 2A, 2B)", &status);
+ FITS_write_key(gainfits, TFLOAT, "EFFMJD", &effmjd,
+ "Date on which file should be applied (MJD)", &status);
+ fits_get_system_time(date, &tref, &status);
+ FITS_write_key(gainfits, TSTRING, "DATE", date,
+ "file creation date (YYYY-MM-DDThh:mm:ss UTC)", &status);
+ FITS_write_key(gainfits, TDOUBLE, "NEVENTS", &ncounts,
+ "Accumulated weighted events", &status);
+ FITS_write_key(gainfits, TFLOAT, "EXPTIME", &exptime,
+ "Accumulated exposure time", &status);
+
+ axis[0] = NXMAX/binx;
+ axis[1] = NYMAX/biny;
+ for (phaext=0; phaext<32-truncate; phaext++) {
+
+ cf_verbose(3, "Creating extension %d", phaext);
+ FITS_create_img(gainfits, FLOAT_IMG, naxis, axis, &status);
+ FITS_write_key(gainfits, TINT, "PHA", &phaext,
+ "PHA value of image", &status);
+ FITS_write_key(gainfits, TINT, "SPECBINX", &binx,
+ "Binsize in detector X coordinate", &status);
+ FITS_write_key(gainfits, TINT, "SPECBINY", &biny,
+ "Binsize in detector Y coordinate", &status);
+
+ }
+
+ cf_verbose(3, "Creating binary table extension");
+ FITS_create_tbl(gainfits, BINARY_TBL, naxis2, tfields, ttype, tform, tunit,
+ "PROCESSED FILES", &status);
+
+ cf_verbose(3, "Closing file %s", newfile);
+ FITS_close_file(gainfits, &status);
+ cf_verbose(3, "Exiting new_gainfile");
+ return status;
+}
+
+static int
+_check_index(fitsfile *gainfits, char *rootname, float *scale, int *phamin,
+ int *phamax, int truncate)
+{
+ int status=0, anynull=0, hdutype;
+ float *scal;
+ int *phami, *phama;
+ long j, nrows, frow=1, felem=1;
+ char **filename, strnull[] = " ";
+
+ FITS_movabs_hdu(gainfits, INDEX_EXT-truncate, &hdutype, &status);
+ FITS_read_key(gainfits, TLONG, "NAXIS2", &nrows, NULL, &status);
+
+ filename = (char **) cf_malloc(nrows * sizeof(char *));
+ filename[0] = (char *) cf_malloc(nrows*(ROOT_LENGTH+1)*sizeof(char));
+ scal = (float *) cf_malloc(nrows * sizeof(float));
+ phami = (int *) cf_malloc(nrows * sizeof(int));
+ phama = (int *) cf_malloc(nrows * sizeof(int));
+ for (j=1; j<nrows; j++)
+ filename[j] = filename[j-1]+(ROOT_LENGTH+1);
+
+ FITS_read_col(gainfits, TSTRING, 1, frow, felem, nrows, strnull,
+ filename, &anynull, &status);
+ FITS_read_col(gainfits, TFLOAT, 6, frow, felem, nrows, strnull,
+ scal, &anynull, &status);
+ FITS_read_col(gainfits, TINT, 7, frow, felem, nrows, strnull,
+ phami, &anynull, &status);
+ FITS_read_col(gainfits, TINT, 8, frow, felem, nrows, strnull,
+ phama, &anynull, &status);
+
+ for (j=0; j<nrows; j++) {
+ if (strncmp(filename[j], rootname, strlen(rootname)) == 0) {
+ *scale = scal[j];
+ *phamin = phami[j];
+ *phamax = phama[j];
+ free(filename[0]);
+ free(filename);
+ free(scal);
+ free(phami);
+ free(phama);
+ return j+1;
+ }
+ }
+ free(filename[0]);
+ free(filename);
+ free(scal);
+ free(phami);
+ free(phama);
+ return 0;
+}
+
+static int
+_update_index(fitsfile *gainfits, char *rootname, char *obsdate,
+ double ncounts, float exptime, float scale, int phamin, int phamax,
+ int truncate)
+{
+ char *strptr[1], adddate[FLEN_CARD]={'\0'};
+ int status=0, hdutype, tref=0;
+ long nrows;
+
+ FITS_movabs_hdu(gainfits, INDEX_EXT-truncate, &hdutype, &status);
+ FITS_read_key(gainfits, TLONG, "NAXIS2", &nrows, NULL, &status);
+
+ strptr[0] = rootname;
+ FITS_write_col(gainfits, TSTRING, 1, nrows+1, 1, 1, strptr, &status);
+ strptr[0] = obsdate;
+ FITS_write_col(gainfits, TSTRING, 2, nrows+1, 1, 1, strptr, &status);
+ FITS_write_col(gainfits, TDOUBLE, 3, nrows+1, 1, 1, &ncounts, &status);
+ FITS_write_col(gainfits, TFLOAT, 4, nrows+1, 1, 1, &exptime, &status);
+ fits_get_system_time(adddate, &tref, &status);
+ strptr[0] = adddate;
+ fits_write_col(gainfits, TSTRING, 5, nrows+1, 1, 1, strptr, &status);
+ FITS_write_col(gainfits, TFLOAT, 6, nrows+1, 1, 1, &scale, &status);
+ fits_write_col(gainfits, TINT, 7, nrows+1, 1, 1, &phamin, &status);
+ FITS_write_col(gainfits, TINT, 8, nrows+1, 1, 1, &phamax, &status);
+ return 0;
+}
+
+
+static double
+add_events(fitsfile *infits, char *xcolumn, char *ycolumn, float scale,
+ int phamin, int phamax, fitsfile *gainfits)
+{
+ char *pha;
+ int binx, biny, phaext, status=0, hdutype, anynull=0;
+ long nevents, j;
+ long nx, ny;
+ float *xpos, *ypos, *weight, *image;
+ double ncounts=0.;
+
+ cf_verbose(3,"Entering add_events");
+
+ FITS_movabs_hdu(infits, 2, &hdutype, &status);
+ nevents = cf_read_col(infits, TFLOAT, xcolumn, (void **) &xpos);
+ nevents = cf_read_col(infits, TFLOAT, ycolumn, (void **) &ypos);
+ nevents = cf_read_col(infits, TBYTE, "PHA", (void **) &pha);
+ nevents = cf_read_col(infits, TFLOAT, "WEIGHT", (void **) &weight);
+
+ for (phaext=phamin; phaext<=phamax; phaext++) {
+ FITS_movabs_hdu(gainfits, phaext+2, &hdutype, &status);
+ if (hdutype == BINARY_TBL) {
+ cf_if_warning("Can't find image extension for PHA = %d", phaext);
+ break;
+ }
+ FITS_read_key(gainfits, TLONG, "NAXIS1", &nx, NULL, &status);
+ FITS_read_key(gainfits, TLONG, "NAXIS2", &ny, NULL, &status);
+ FITS_read_key(gainfits, TINT, "SPECBINX", &binx, NULL, &status);
+ FITS_read_key(gainfits, TINT, "SPECBINY", &biny, NULL, &status);
+
+ image = (float *) cf_malloc(sizeof(float)*nx*ny);
+ FITS_read_img(gainfits, TFLOAT, 1, nx*ny, NULL, image,
+ &anynull, &status);
+
+ for (j=0; j<nevents; j++) {
+ if (pha[j] == phaext) {
+ int x, y;
+ x = xpos[j];
+ y = ypos[j];
+ if ((x >= 0) && (x < nx*binx) && (y >= 0) && (y < ny*biny)) {
+ image[(y/biny)*nx + (x/binx)] += weight[j]*scale;
+ ncounts += weight[j]*scale;
+ }
+ }
+ }
+ FITS_write_img(gainfits, TFLOAT, 1, nx*ny, image, &status);
+ free(image);
+ }
+
+ free(weight);
+ free(pha);
+ free(ypos);
+ free(xpos);
+ return ncounts;
+}
+
+static double
+subtract_events(fitsfile *infits, char *xcolumn, char *ycolumn,
+ float scale, int phamin, int phamax, fitsfile *gainfits)
+{
+ char *pha;
+ long nx, ny;
+ int phaext, status=0, hdutype, anynull=0, binx, biny;
+ long nevents, j;
+ float *xpos, *ypos, *weight, *image;
+ double ncounts=0.;
+
+ FITS_movabs_hdu(infits, 2, &hdutype, &status);
+ nevents = cf_read_col(infits, TFLOAT, xcolumn, (void **) &xpos);
+ nevents = cf_read_col(infits, TFLOAT, ycolumn, (void **) &ypos);
+ nevents = cf_read_col(infits, TBYTE, "PHA", (void **) &pha);
+ nevents = cf_read_col(infits, TFLOAT, "WEIGHT", (void **) &weight);
+
+ for (phaext=phamin; phaext<=phamax; phaext++) {
+ FITS_movabs_hdu(gainfits, phaext+2, &hdutype, &status);
+ FITS_read_key(gainfits, TLONG, "NAXIS1", &nx, NULL, &status);
+ FITS_read_key(gainfits, TLONG, "NAXIS2", &ny, NULL, &status);
+ FITS_read_key(gainfits, TINT, "SPECBINX", &binx, NULL, &status);
+ FITS_read_key(gainfits, TINT, "SPECBINY", &biny, NULL, &status);
+
+ image = (float *) cf_malloc(sizeof(float) * nx*ny);
+ FITS_read_img(gainfits, TFLOAT, 1, nx*ny, NULL, image,
+ &anynull, &status);
+
+ for (j=0; j<nevents; j++) {
+ if (pha[j] == phaext) {
+ int x, y;
+ x = xpos[j];
+ y = ypos[j];
+ if ((x >=0) && (x < nx*binx) && (y >= 0) && (y < ny*biny)) {
+ image[(y/biny)*nx + (x/binx)] -= weight[j]*scale;
+ ncounts += weight[j]*scale;
+ }
+ }
+ }
+ FITS_write_img(gainfits, TFLOAT, 1, nx*ny, image, &status);
+ free(image);
+ }
+
+ free(weight);
+ free(pha);
+ free(ypos);
+ free(xpos);
+ return ncounts;
+}
+
+
+int main(int argc, char *argv[])
+{
+ char *newfile = NULL, *detector = NULL, buffer[FLEN_CARD]={'\0'}, instmode[FLEN_CARD]={'\0'};
+ int subtract=0, force=0, newbinx=8, newbiny=4, status=0, optc;
+ int truncate=0;
+ float effmjd = 0.,scale=1., old_scale;
+ int phamin=0, phamax=31;
+ int old_phamin, old_phamax;
+
+ char xcolumn[FLEN_CARD]={'\0'}, ycolumn[FLEN_CARD]={'\0'};
+
+ char opts[] = "hv:fsrtcn:d:j:w:x:y:l:u:";
+ char usage[] =
+ "Usage:\n"
+ " cf_gainmap [-hfsrtc] [-v level] [-n filename] [-d segment]\n"
+ " [-w scale] [-j effmjd] [-x xbin] [-y ybin] \n"
+ " [-l phamin] [-u phamax] idffiles\n";
+ char option[] =
+ "Options:\n"
+ " -h: this help message\n"
+ " -v: verbosity level (=1; 0 is silent)\n"
+ " -f: force the files\n"
+ " -s: subtract files\n"
+ " -n: gain map file\n"
+ " -d: gain map segment (no default for new file)\n"
+ " -j: effective MJD (=0.0)\n"
+ " -w: weighting factor for image (=1.0)\n"
+ " -x: X-bin size (=8)\n"
+ " -y: Y-bin size (=4)\n"
+ " -r: use raw XY coordinates instead of farf\n"
+ " -t: truncate map at PHA = 30\n"
+ " -c: use final XY coordinates instead of farf\n"
+ " -l: lower limit for pha (=0) \n"
+ " -u: upper limit for pha (=31) \n";
+
+ verbose_level = 1;
+
+ strcpy(xcolumn, "XFARF");
+ strcpy(ycolumn, "YFARF");
+
+
+
+ /* 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;
+ case 'f':
+ force = 1;
+ break;
+ case 's':
+ subtract = 1;
+ break;
+ case 'n':
+ newfile = optarg;
+ break;
+ case 'd':
+ detector = optarg;
+ break;
+ case 'j':
+ effmjd = atof(optarg);
+ break;
+ case 'w':
+ scale = atof(optarg);
+ break;
+ case 'x':
+ newbinx = atoi(optarg);
+ break;
+ case 'y':
+ newbiny = atoi(optarg);
+ break;
+ case 'r':
+ strcpy(xcolumn, "XRAW");
+ strcpy(ycolumn, "YRAW");
+ break;
+ case 't':
+ truncate = 1;
+ break;
+ case 'c':
+ strcpy(xcolumn, "X");
+ strcpy(ycolumn, "Y");
+ break;
+ case 'l':
+ phamin = atoi(optarg);
+ break;
+ case 'u':
+ phamax = atoi(optarg);
+ break;
+ }
+ }
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+ if (argc <= optind)
+ cf_if_error("%s\nIncorrect number of program arguments", usage);
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Begin processing");
+
+ while (optind < argc) {
+
+ char gainfile[FLEN_CARD], rootname[FLEN_CARD]={'\0'};
+ char segment[FLEN_CARD] = {'\0'};
+ int hdutype;
+ FILE *fptr;
+ fitsfile *infits, *gainfits;
+
+ FITS_open_file(&infits, argv[optind], READONLY, &status);
+ FITS_movabs_hdu(infits, 1, &hdutype, &status);
+
+ FITS_read_key(infits, TSTRING, "INSTMODE", instmode, NULL,
+ &status);
+
+ if (strncmp(instmode,"TTAG",4)){
+ FITS_close_file(infits, &status);
+ cf_verbose(1,"Skipped HIST file: %s\n",argv[optind]);
+ optind ++;
+ continue;
+ }
+
+ if (newfile) {
+ cf_verbose(3, "newfile is TRUE");
+ strcpy(gainfile, newfile);
+
+ if ((fptr = fopen(gainfile, "r")))
+ fclose(fptr);
+ else {
+ if (!detector)
+ cf_if_error("No detector segment specified: "
+ "1A, 1B, 2A, 2B");
+ detector[1] = toupper(detector[1]);
+ status = new_gainfile(gainfile, detector, effmjd,
+ newbinx, newbiny, truncate);
+ }
+ FITS_open_file(&gainfits, gainfile, READWRITE, &status);
+ FITS_movabs_hdu(gainfits, 1, &hdutype, &status);
+ detector = buffer;
+ FITS_read_key(gainfits, TSTRING, "DETECTOR", detector, NULL,
+ &status);
+ } else {
+ cf_verbose(3, "newfile is FALSE");
+ FITS_read_key(infits, TSTRING, "GAIN_MAP", gainfile, NULL,
+ &status);
+ detector = buffer;
+ FITS_read_key(infits, TSTRING, "DETECTOR", detector, NULL,
+ &status);
+
+ if ((fptr = fopen(cf_hist_file(gainfile), "r"))) {
+ fclose(fptr);
+ } else {
+ char keyword[FLEN_CARD]={'\0'}, segment[FLEN_CARD]={'\n'};
+ char linin[MAXCHARS]={'\0'}, filename[FLEN_CARD]={'\0'};
+ int interp;
+ float aftermjd;
+ FILE *master;
+ /*
+ * Get the effective MJD from the master calibration file
+ */
+ master = fopen(cf_parm_file(MASTER_CAL_FILE), "r");
+ if (master == NULL)
+ cf_if_error("Master calibration database file not found");
+ while (fgets(linin, MAXCHARS, master) != NULL) {
+ /*
+ * Check for comment lines
+ */
+ if ((linin[0] != '#') && (linin[0] != '\n')) {
+ sscanf(linin, "%4c%*2c%2c%*2c%13c%*2c%9f%*2c%1d",
+ keyword, segment, filename, &aftermjd, &interp);
+ if (strcmp(filename, gainfile) == 0) {
+ effmjd = aftermjd;
+ break;
+ }
+ }
+ }
+ fclose(master);
+
+ status = new_gainfile(cf_hist_file(gainfile), detector,
+ effmjd, newbinx, newbiny, truncate);
+ }
+ FITS_open_file(&gainfits, cf_hist_file(gainfile), READWRITE,
+ &status);
+ }
+
+ strncpy(rootname, argv[optind], ROOT_LENGTH);
+ FITS_read_key(infits, TSTRING, "DETECTOR", segment, NULL, &status);
+ if (strcmp(detector, segment) != 0) {
+ cf_if_warning("%s segment is not the same as %s",
+ argv[optind], gainfile);
+ }
+ else if (subtract) {
+ int index;
+ if ((index = _check_index(gainfits, rootname, &scale, &phamin,
+ &phamax, truncate))) {
+
+ int hdutype;
+ float exptime=0., acctime=0.;
+ double ncounts=0, accevnt=0;
+
+ FITS_read_key(infits, TFLOAT, "EXPTIME", &exptime, NULL,
+ &status);
+
+
+ ncounts = subtract_events(infits, xcolumn, ycolumn, scale, phamin,
+ phamax-truncate, gainfits);
+
+ FITS_movabs_hdu(gainfits, IMAGE_EXT, &hdutype, &status);
+ FITS_read_key(gainfits, TDOUBLE, "NEVENTS", &accevnt,
+ NULL, &status);
+ FITS_read_key(gainfits, TFLOAT, "EXPTIME", &acctime,
+ NULL, &status);
+ accevnt -= ncounts;
+ acctime -= exptime;
+ FITS_update_key(gainfits, TDOUBLE, "NEVENTS", &accevnt,
+ NULL, &status);
+ FITS_update_key(gainfits, TFLOAT, "EXPTIME", &acctime,
+ NULL, &status);
+
+ FITS_movabs_hdu(gainfits, INDEX_EXT-truncate, &hdutype, &status);
+ FITS_delete_rows(gainfits, index, 1, &status);
+ cf_verbose(1, "%s is subtracted from %s",
+ argv[optind], gainfile);
+ } else {
+ cf_if_warning("%s is not in %s.", argv[optind], gainfile);
+ }
+ } else {
+ cf_verbose(3, "Adding new data file.");
+ if (!force && _check_index(gainfits, rootname, &old_scale,
+ &old_phamin, &old_phamax, truncate)) {
+ cf_if_warning("%s is already in %s with scale = %f, "
+ "phamin = %d, phamax=%d.",
+ argv[optind], gainfile, old_scale, old_phamin, old_phamax);
+ } else {
+ char obsdate[FLEN_CARD]={'\0'}, dateobs[FLEN_CARD]={'\0'};
+ char timeobs[FLEN_CARD]={'\0'};
+
+ float exptime=0., acctime=0.;
+ double ncounts=0, accevnt=0;
+
+ FITS_read_key(infits, TSTRING, "DATEOBS", dateobs, NULL,
+ &status);
+ FITS_read_key(infits, TSTRING, "TIMEOBS", timeobs, NULL,
+ &status);
+ obsdate[0] = '\0';
+ sprintf(obsdate, "%s%s%s", dateobs, "T", timeobs);
+ FITS_read_key(infits, TFLOAT, "EXPTIME", &exptime, NULL,
+ &status);
+
+ if ((force) && _check_index(gainfits, rootname, &old_scale,
+ &old_phamin, &old_phamax, truncate))
+ cf_if_warning("FORCE MODE - %s is already in %s with scale = %f, "
+ "phamin = %d, phamax=%d.",
+ argv[optind], gainfile, old_scale, old_phamin, old_phamax);
+
+ ncounts = add_events(infits, xcolumn, ycolumn, scale, phamin,
+ phamax-truncate, gainfits);
+
+ FITS_movabs_hdu(gainfits, IMAGE_EXT, &hdutype, &status);
+ FITS_read_key(gainfits, TDOUBLE, "NEVENTS", &accevnt,
+ NULL, &status);
+ FITS_read_key(gainfits, TFLOAT, "EXPTIME", &acctime,
+ NULL, &status);
+ accevnt += ncounts;
+ acctime += exptime;
+ FITS_update_key(gainfits, TDOUBLE, "NEVENTS", &accevnt,
+ NULL, &status);
+ FITS_update_key(gainfits, TFLOAT, "EXPTIME", &acctime,
+ NULL, &status);
+
+ status = _update_index(gainfits, rootname, obsdate, ncounts,
+ exptime, scale, phamin, phamax, truncate);
+ cf_verbose(1, "%s is added to %s", argv[optind], gainfile);
+ }
+ }
+ FITS_close_file(gainfits, &status);
+ FITS_close_file(infits, &status);
+ optind ++;
+ }
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Finished processing");
+ return 0;
+}
diff --git a/src/fuv/cf_hist_init.c b/src/fuv/cf_hist_init.c
new file mode 100644
index 0000000..5829707
--- /dev/null
+++ b/src/fuv/cf_hist_init.c
@@ -0,0 +1,653 @@
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: cf_hist_init input_file output_file
+ *
+ * Description: Reads a raw hist file and generates a list of the pixels
+ * that contain counts. This list has the same format
+ * as a TTAG list, so analysis can be carried out using
+ * many of the modules in the TTAG pipeline.
+ *
+ * The output file will have the same format as a TTAG
+ * file, with the following definitions:
+ *
+ * TIME FLOAT all equal to the midpoint of the exp.
+ * XRAW INT raw x position
+ * YRAW INT raw y position (midpoint of 8 pixel bin)
+ * PHA BYTE all 20 - indicating a good point
+ * WEIGHT FLOAT number of photons falling in that bin
+ * XFARF FLOAT x position in geometrically
+ * corrected frame
+ * YFARF FLOAT y position in geometrically
+ * corrected frame
+ * X FLOAT final x position (after correcting
+ * for motions)
+ * Y FLOAT final y position (after correcting
+ * for motions)
+ * CHANNEL CHAR aperture ID for the photon
+ * TIMEFLGS CHAR temporal flags - various bits set
+ * LOC_FLGS CHAR location flags - various bits set
+ * LAMBDA FLOAT wavelength for each photon
+ * ERGCM2 FLOAT flux calibration for each photon
+ *
+ * This routine calls cf_fuv_init to populate the calibration
+ * entries in the header.
+ *
+ * In addition, the routine creates a timeline table containing
+ * the orbital information, count rates, and high-voltage
+ * information to be used by later pipeline modules.
+ *
+ *
+ * Returns: Zero upon successful completion.
+ *
+ * History: 05/09/03 v1.1 rdr Adapted from cf_ttag_init
+ * 06/04/03 v1.4 wvd Add call to cf_proc_check
+ * 06/10/03 v1.5 rdr Scan for hot pixels and remove
+ * 06/11/03 v1.6 wvd Compress data with TSCALE and TZERO
+ * 06/11/03 v1.7 wvd Changed calfusettag.h to calfuse.h
+ * 07/17/03 v1.8 wvd Move various subroutines to libcf.
+ * 07/22/03 v1.9 wvd Read all extensions of raw hist file.
+ * Test for hot pixels only in active
+ * region and only if img[j]>15.
+ * 07/28/03 v1.10 wvd Close ELEC_CAL.
+ * 10/26/03 v1.11 wvd Increase morekeys to 38.
+ * 11/05/03 v1.12 wvd Added stdlib.h and unistd.h.
+ * 12/05/03 bjg Modified cf_make_pixel_list
+ * to unbin data in y.
+ * 12/10/03 v1.13 bjg Unbin is now optional
+ * Update keyword SPECBINY
+ * 03/03/04 v1.14 rdr Exit if no photons found
+ * 03/05/04 v1.15 rdr Warning if data is missing
+ * 03/09/04 v1.16 rdr Fix error in correcting hot pixels
+ * 03/26/04 v1.17 rdr Continue when there is no data
+ * 03/30/04 v1.20 wvd Clean up i/o.
+ * 03/31/04 v1.21 bjg functions return EXIT_SUCCESS instead
+ * of zero.
+ * >>>Include math.h for fmod<<<
+ * Type conversion for
+ * double fmod(double, double)
+ * 04/06/04 v1.22 bjg Remove unused variables
+ * Change format to match arg type
+ * in printf
+ * Remove static keyword in struct key
+ * definition
+ * Add braces in TSCAL and TZERO
+ * definitions
+ * Test for fill data
+ * 10/15/04 v1.23 bjg Fill Data Photon gets flag
+ * LOCATION_FILL only if it is
+ * in Active Aperture
+ * 12/24/2004 v1.24 bjg npix_max now takes binx and biny into
+ * account
+ * 01/24/2005 v1.25 wvd Modify cf_make_pixel_list to ignore
+ * duplicate data, which can sneak in
+ * with the stim pulses.
+ * 02/11/2005 v1.26 wvd Hot pixels and fill data cause the
+ * header keyword NEVENTS to be too
+ * large, so we correct/exclude these
+ * points and update NEVENTS.
+ * 03/10/2005 v1.27 wvd Move flagging of airglow photons to
+ * cf_screen_airglow.
+ * Initialize XFARF and YFARF with zero.
+ * 05/20/2005 v1.28 wvd Clean up i/o.
+ * 05/31/2006 v1.29 wvd OPUS has been updated, so we can set
+ * morekeys to 0.
+ * 06/12/2006 v1.30 wvd Call cf_verbose rather than
+ * cf_if_warning when an extension
+ * contains no photons.
+ * 02/23/2007 v1.31 wvd If a raw hist file contains no
+ * extensions, set EXP_STAT to -1.
+ * Make active-area limits inclusive.
+ * 11/07/2008 v1.32 wvd Clean up i/o.
+ *
+ ****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "calfuse.h"
+
+struct key {
+ char keyword[FLEN_KEYWORD];
+ float value;
+ };
+
+
+/*****************************************************************************/
+
+static int
+cf_make_pixel_list(fitsfile *infits, fitsfile *outfits, char unbin) {
+
+/*****************************************************************************
+ *
+ * Description: procedure to take input data from the raw HIST data file and
+ * generate a table with 14 columns. This table lists
+ * all pixels that contain counts. The
+ * table is designed to mimic a TTAG list, so that it can be used
+ * with various modules in the TTAG pipeline
+ *
+ ****************************************************************************/
+
+ fitsfile *elecfits;
+ char fmt_byte[FLEN_CARD], fmt_float[FLEN_CARD], fmt_short[FLEN_CARD];
+ char *inpha, *dumarrb;
+ char elecfile[FLEN_CARD];
+ char keyword[FLEN_CARD], card[FLEN_CARD];
+ unsigned char *dumarrbu ;
+ int status=0, anynull=0, hdutype;
+ int colval;
+ int tfields = 14; /* output table will have 14 columns */
+ int active_l, active_r ;
+ long i, j, k, nevents, nfdp;
+ long frow=1, felem=1, nrows=1; /* output table will have 1 row */
+ float sum_weights;
+ float *intime, *dumarrf;
+
+ int sia_index[512], sia_temp[512]; /* Indices of SIA rectangles */
+ int sia_width = 2048, sia_height = 16; /* Dimensions of SIA recs */
+ int xx, yy; /* Pixel coordinates (unbinned) */
+
+ int x0, y0, xstart, ystart ;
+ int nx, ny, yndx, binx, biny ;
+ int nhot, nhot_total=0;
+ short *xpix, *ypix, *img, *fill_data_pix, nmask, nullval;
+ long npix, npix_max, npts ;
+ float *wtpix, exptime, mtime, nave;
+
+
+ char extname[]="TTAG DATA"; /* name of the extension containing
+ the binary table holding the data */
+
+ char *ttype[]={"TIME", "XRAW", "YRAW", "PHA", "WEIGHT", "XFARF",
+ "YFARF", "X", "Y", "CHANNEL", "TIMEFLGS",
+ "LOC_FLGS", "LAMBDA", "ERGCM2" };
+
+ char *tform[14]; /* will asign values when we find out
+ the number of elements in the data set */
+
+
+ char *tunit[]={"SECONDS", "PIXELS", "PIXELS", " ", " ", "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.}};
+
+ /* Initialize the sia_index array. */
+ (void) memset((void *)sia_index, 0, sizeof(int)*512);
+
+ /*********************************************************************
+ Read information to be used in the screening analysis.
+ **********************************************************************/
+
+ /* Read the limits to the active area of the detector */
+ FITS_read_key(outfits, TSTRING, "ELEC_CAL", elecfile, NULL, &status);
+ FITS_open_file(&elecfits, cf_cal_file(elecfile), READONLY, &status);
+ FITS_read_key(elecfits, TINT, "ACTIVE_L", &active_l, NULL,
+ &status);
+ FITS_read_key(elecfits, TINT, "ACTIVE_R", &active_r, NULL,
+ &status);
+ FITS_close_file(elecfits, &status);
+ cf_verbose(3, "Limits to the active area: left=%d, right=%d",
+ active_l, active_r);
+
+ /* Determine the exposure time */
+ FITS_movabs_hdu(infits, 1, &hdutype, &status);
+ FITS_read_key(infits, TFLOAT, "EXPTIME", &exptime, NULL, &status);
+ cf_verbose(3, "exptime = %d ", cf_nint(exptime)) ;
+
+ /* Determine the binning factors in x and y */
+ FITS_read_key(infits, TINT, "SPECBINX", &binx, NULL, &status);
+ FITS_read_key(infits, TINT, "SPECBINY", &biny, NULL, &status);
+ cf_verbose(3, "binx=%d, biny=%d \n", binx, biny) ;
+
+
+ /***********************************************************************
+ Get information from the raw data file.
+ ************************************************************************/
+
+ /* Set up arrays to contain the positions of each pixel with counts
+ (xpix and ypix) and the number of counts in that pixel (wtpix) */
+ if (unbin) npix_max = (NXMAX * NYMAX) / binx ;
+ else npix_max = (NXMAX * NYMAX) / (binx * biny) ;
+ npix = -1 ;
+ xpix = (short *) cf_calloc(npix_max, sizeof(short)) ;
+ ypix = (short *) cf_calloc(npix_max, sizeof(short)) ;
+ wtpix = (float *) cf_calloc(npix_max, sizeof(float)) ;
+ fill_data_pix = (short *) cf_calloc(npix_max, sizeof(short)) ;
+
+ /*
+ * Loop over all extensions in the input file, and place contents
+ * of each extension into outbuff. Keep trying to read a new HDU
+ * in the input file until we hit the EOF.
+ *
+ * Note that the next line cannot use FITS_movrel_hdu because
+ * that routine automatically exits upon error.
+ */
+ for (i = 1; !(fits_movrel_hdu(infits, 1, &hdutype, &status)); i++) {
+ FITS_read_key(infits, TINT, "NAXIS1", &nx, NULL, &status);
+ FITS_read_key(infits, TINT, "NAXIS2", &ny, NULL, &status);
+ FITS_read_key(infits, TINT, "XORIGIN", &x0, NULL, &status);
+ FITS_read_key(infits, TINT, "YORIGIN", &y0, NULL, &status);
+
+ npts = nx * ny ;
+ cf_verbose(3, "Reading extension %d ", i) ;
+ cf_verbose(3, "nx=%d, ny=%d, npts=%d ", nx, ny, npts) ;
+
+ /* Initialize the sia_temp array */
+ (void) memset((void *)sia_temp, 0, sizeof(int)*512);
+
+ /*
+ * Allocate space for and read the input image
+ */
+ img = cf_malloc(sizeof(short) * npts);
+ FITS_read_img(infits, TSHORT, 1L, npts, &nullval,
+ img, &anynull, &status);
+
+ /* Specify the starting positions in x and y.
+ Place the point in the middle of the bin */
+ xstart = x0 * binx + binx / 2;
+ ystart = y0 * biny + biny / 2;
+ cf_verbose(3, "x0=%d, y0=%d, xstart=%d, ystart=%d",
+ x0, y0, xstart, ystart) ;
+
+ /* Go through the image and tabulate the pixels with counts. */
+ nhot=0 ;
+ for (j=0; j<npts; j++)
+ if (img[j] > 0) {
+
+ /* If this pixel falls in an SIA rectangle that has already
+ been written to the output data list, skip it and move to
+ the next SIA rectangle. */
+
+ xx = (x0 + (j % nx)) * binx;
+ yy = (y0 + (j / nx)) * biny;
+ k = xx / sia_width + yy / sia_height * 8;
+ if (k < 0 || k >= 512) continue;
+ if (sia_index[k] == 1) {
+ j += sia_width / binx - 1;
+ continue;
+ }
+ sia_temp[k] = 1;
+
+ /* Check for a hot pixel by comparing the value in the pixel with
+ those on either side. Ignore pixels outside of detector active
+ area or with fewer than 16 counts. */
+
+ if ((img[j] > 15) && (img[j] != FILL_DATA) &&
+ (xx >= active_l) && (xx <= active_r)) {
+ nave = (img[j-2] + img[j-1] + img[j+1] + img[j+2]) / 4. ;
+ if (nave > 32000.) nave=32000. ;
+ if (nave < 1.) nave=1. ;
+ if (img[j] > 8*nave) {
+ nhot++ ;
+ cf_verbose(3,"hot pixel at point %d: val=%d, ave=%f",
+ j, img[j], nave) ;
+ /* Repair hot pixel */
+ nmask=1 ;
+ while(nmask < 8*nave && nmask < 16000) nmask*=2 ;
+ nmask-=1 ;
+ img[j] = (img[j] & nmask) ;
+ cf_verbose(3,"corrected value = %d ",img[j]) ;
+ }
+ }
+
+ yndx = (int) ( j / nx ) ;
+
+ if (unbin){
+ for (k=0;k<biny;k++){
+ npix++ ;
+ xpix[npix] = (short) (xstart + (j - (yndx * nx)) * binx) ;
+ ypix[npix] = (short) (ystart + yndx*biny + k) ;
+ wtpix[npix] = (float) ( ((float) img[j]) / ((float) biny) ) ;
+
+ fill_data_pix[npix]=0;
+ if (img[j] == FILL_DATA) {
+ wtpix[npix]=0.0;
+ fill_data_pix[npix]=1;
+ }
+
+
+ }
+ }
+ else {
+ npix++ ;
+ xpix[npix] = (short) (xstart + (j - (yndx * nx)) * binx) ;
+ ypix[npix] = (short) (ystart + yndx*biny) ;
+ wtpix[npix] = (float) img[j];
+
+ fill_data_pix[npix]=0;
+ if (img[j] == FILL_DATA) {
+ wtpix[npix]=0.0;
+ fill_data_pix[npix]=1;
+ }
+ }
+
+
+ }
+
+ nhot_total += nhot;
+ cf_verbose(2, "%d hot pixels found in extn %d ",nhot, i) ;
+ cf_verbose(3, "total number of pixels with counts = %d \n", npix) ;
+ if (nhot > 10) cf_if_warning("More than 10 hot pixels found.") ;
+
+ free(img) ;
+
+ /* Copy new SIA indices to sia_index array. */
+ for (k = 0; k < 512; k++)
+ if (sia_temp[k]) sia_index[k] = 1;
+
+ } /* Finished loop over all extensions in infits */
+ /*
+ * Status upon completion of loop through extensions should be
+ * "end of file."
+ * If it is, reset value of status. If not, there was an
+ * unexpected error. Print and exit.
+ */
+ if( status == END_OF_FILE ) { /* !!! This might cause a problem */
+ status = 0;
+ } else {
+ cf_if_fits_error(status);
+ }
+
+ cf_verbose(3, "Finished reading data ") ;
+
+ if (npix < 0) {
+ npix = 1 ;
+ xpix[0]=0 ;
+ ypix[0]=0 ;
+ wtpix[0]=1. ;
+ fill_data_pix[0]=0;
+ }
+
+ /*************************************************************************
+ Output the analysis to a table
+ ***************************************************************************/
+
+ /* Generate the tform array */
+ sprintf(fmt_byte, "%ldB", npix);
+ sprintf(fmt_float, "%ldE", npix);
+ sprintf(fmt_short, "%ldI", npix);
+
+ 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 */
+
+ cf_verbose(3, "Creating table") ;
+ FITS_movabs_hdu(outfits, 1, &hdutype, &status);
+ FITS_create_tbl(outfits, BINARY_TBL, nrows, 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);
+ }
+
+ /* Allocate space for the new output columns */
+
+ cf_verbose(3, "Allocating space for arrays ") ;
+ dumarrf = (float *) cf_malloc(sizeof(float) * npix);
+ dumarrb = (char *) cf_malloc(sizeof(char) * npix);
+ dumarrbu = (unsigned char *) cf_malloc(sizeof(unsigned char) * npix);
+
+ cf_verbose(3, "Filling columns") ;
+ /* Specify a time array - assign the same time to all pixels */
+ intime = (float *) cf_calloc(npix, sizeof(float) ) ;
+ mtime = exptime/2. ;
+ for (i=0; i<npix; i++) intime[i]=mtime ;
+ FITS_write_col(outfits, TFLOAT, 1, frow, felem, npix, intime, &status);
+
+ /* Output X and Y positions */
+ FITS_write_col(outfits, TSHORT, 2, frow, felem, npix, xpix, &status);
+ FITS_write_col(outfits, TSHORT, 3, frow, felem, npix, ypix, &status);
+
+ /* Now do the PHA column - assume 20 */
+ inpha = (char *) cf_calloc(npix, sizeof(char) ) ;
+ for (i=0; i<npix; i++) inpha[i] = 20 ;
+ FITS_write_col(outfits, TBYTE, 4, frow, felem, npix, inpha, &status);
+
+ /* Fill weights column with counts per pixel */
+ FITS_write_col(outfits, TFLOAT, 5, frow, felem, npix, wtpix, &status);
+
+ /* Fill XFARF, YFARF, X and Y arrays with 0 */
+ for (i=0; i<npix; i++) dumarrf[i] = 0.;
+ for (colval=6; colval<10; colval++) {
+ FITS_write_col(outfits, TFLOAT, colval, frow, felem, npix,
+ dumarrf, &status);
+ }
+
+ /* Initialize the channel and temporal flag arrays with 0 - byte */
+ for (i=0;i<npix; i++)
+ dumarrb[i] = 0;
+ FITS_write_col(outfits, TBYTE, 10, frow, felem, npix, dumarrb, &status);
+ for (i=0;i<npix; i++)
+ dumarrbu[i] = 0;
+ FITS_write_col(outfits, TBYTE, 11, frow, felem, npix, dumarrbu, &status);
+
+ /* Flag events that lie outside of the active area or
+ in fill-data regions. */
+ for (i=0 ; i<npix ; i++) {
+ dumarrbu[i] = 0 ;
+
+ /* Flag photons that lie outside the active area. */
+ if (xpix[i] < active_l || xpix[i] > active_r)
+ dumarrbu[i] = dumarrbu[i] | LOCATION_SHLD ;
+
+ /* If inside, is it fill data? */
+ else if (fill_data_pix[i])
+ dumarrbu[i] = dumarrbu[i] | LOCATION_FILL ;
+ }
+
+ FITS_movabs_hdu(outfits, 2, &hdutype, &status);
+ FITS_write_col(outfits, TBYTE, 12, frow, felem, npix,
+ dumarrbu, &status);
+
+ /* Fill lambda and energy arrays with 0 */
+ FITS_write_col(outfits, TFLOAT, 13, frow, felem, npix, dumarrf, &status);
+ FITS_write_col(outfits, TFLOAT, 14, frow, felem, npix, dumarrf, &status);
+
+ /* If file contains hot pixels or fill data, recalculate NEVENTS. */
+ nfdp = 0;
+ sum_weights = 0.;
+ for (i=0; i<npix; i++) {
+ nfdp += fill_data_pix[i];
+ sum_weights += wtpix[i];
+ }
+ if (nfdp > 0 || nhot_total > 0) {
+ nevents = cf_nlong(sum_weights);
+ FITS_movabs_hdu(outfits, 1, &hdutype, &status);
+ FITS_update_key(outfits, TLONG, "NEVENTS", &nevents, NULL, &status);
+ cf_verbose(1, "Image contains bad pixels. Updating NEVENTS = %ld",
+ nevents);
+ }
+
+ free(intime);
+ free(xpix);
+ free(ypix);
+ free(wtpix) ;
+ free(inpha);
+ free(dumarrf);
+ free(dumarrb);
+
+ cf_verbose(3, "Leaving cf_make_pixel_list") ;
+
+ return EXIT_SUCCESS ;
+}
+
+
+/******************************************************************************
+ *
+ * CF_MAKE_GTI_TABLE
+ *
+ * Procedure to generate a table of GTI values and put it into the second
+ * extension of the output file. There is assumed to be only one GTI,
+ * starting at 0 and ending at the exposure time.
+ *
+ ******************************************************************************/
+
+int cf_make_gti_table (fitsfile *outfits) {
+
+ int status=0, nrows=1, hdutype, frow=1, felem=1 ;
+ float exptime ;
+ double start[1]={0.}, stop[1] ;
+
+ char extname[]="GTI";
+ int tfields=2; /* output table will have 2 columns */
+ char *ttype[]={"START", "STOP"};
+
+ char *tform[]={"1D","1D"};
+ char *tunit[]={"seconds", "seconds"};
+
+ cf_verbose(3, "Entering cf_make_gti_table ") ;
+
+ /* read the exposure time from the output file */
+ FITS_movabs_hdu(outfits, 1, &hdutype, &status);
+ FITS_read_key(outfits, TFLOAT, "EXPTIME", &exptime, NULL, &status);
+ stop[0] = (double) exptime ;
+
+
+ /* Append a new empty binary table to the output file */
+ FITS_movabs_hdu(outfits, 2, &hdutype, &status);
+ FITS_create_tbl(outfits, BINARY_TBL, nrows, tfields, ttype, tform,
+ tunit, extname, &status);
+
+ /* Write the data to the table */
+ FITS_write_col(outfits, TDOUBLE, 1, frow, felem, nrows, start, &status);
+ FITS_write_col(outfits, TDOUBLE, 2, frow, felem, nrows, stop, &status);
+
+ return EXIT_SUCCESS ;
+}
+
+/*****************************************************************************/
+
+
+int main(int argc, char *argv[])
+{
+ char CF_PRGM_ID[] = "cf_hist_init";
+ char CF_VER_NUM[] = "1.32";
+
+ fitsfile *infits, *outfits;
+
+ int morekeys=0; /* Change to zero when OPUS is updated. */
+ int status=0, optc;
+
+ int one=1, nextn=0;
+ long nphot ;
+ char unbin=0;
+
+ char opts[] = "hsv:";
+ char usage[] =
+ "Usage:\n"
+ " cf_hist_init [-h] [-s] [-v level] rawhistfile idf_file\n";
+ char option[] =
+ "Options:\n"
+ " -h: this help message\n"
+ " -s: to unbin the data in Y\n"
+ " -v: verbosity level (default is 1; 0 is silent)\n";
+
+
+ verbose_level = 1;
+
+ while ((optc = getopt(argc, argv, opts)) != -1) {
+ switch(optc) {
+
+ case 'h':
+ printf("%s\n%s", usage, option);
+ return 0;
+ case 's':
+ unbin=1;
+ break;
+ 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, "Begin execution");
+
+ FITS_open_file(&infits, argv[optind++], READONLY, &status);
+
+ /* Exit if data are not in HIST mode. */
+ if ( cf_proc_check(infits, CF_PRGM_ID) ) {
+ FITS_close_file(infits, &status);
+ return (-1);
+ }
+
+ /* Issue warning message if data are missing. */
+ FITS_read_key(infits, TLONG, "NEVENTS", &nphot, NULL, &status);
+ FITS_read_key(infits, TINT, "NEXTEND", &nextn, NULL, &status);
+ cf_verbose(3,"Number of extensions to the file = %d ", nextn) ;
+ if (nphot < 1) cf_verbose(1, "%s contains no photons.", argv[optind-1]);
+ if (nextn < 1) cf_if_warning("%s contains no extensions.", argv[optind-1]);
+ else if (nextn < 4) cf_verbose(1, "%s contains only %d extensions.",
+ argv[optind-1], nextn) ;
+
+ /* Create output file. */
+ FITS_create_file(&outfits, argv[optind], &status);
+ /* Copy primary image header from the input file. */
+ FITS_copy_hdu(infits, outfits, morekeys, &status);
+
+ /* Update header keywords. */
+ FITS_update_key(outfits, TSTRING, "FILENAME", argv[optind], NULL, &status);
+ FITS_update_key(outfits, TSTRING, "FILETYPE",
+ "INTERMEDIATE DATA FILE", NULL, &status);
+
+ if (unbin) FITS_update_key(outfits, TINT, "SPECBINY", &one, NULL, &status);
+
+ /* If input file contains no extensions, set EXP_STAT to -1. */
+ if (nextn < 1) {
+ char comment[] = "Raw file contains no data.";
+ int eflag = -1;
+ FITS_update_key(outfits, TINT, "EXP_STAT", &eflag, comment, &status);
+ }
+
+ /* Populate the calibration keywords in the primary header. */
+ cf_fuv_init(outfits);
+
+ /* Fill in the first extension with the photon information */
+ cf_make_pixel_list(infits, outfits, unbin) ;
+
+ /* Generate a good-times table and put it in the second extension. */
+ cf_make_gti_table(outfits);
+
+ /* Append a table containing the orbital timeline */
+ cf_timeline(outfits);
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+ /* Update processing flags. */
+ cf_proc_update(outfits, CF_PRGM_ID, "COMPLETE");
+
+ 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/fuv/cf_remove_motions.c b/src/fuv/cf_remove_motions.c
new file mode 100644
index 0000000..ec2b332
--- /dev/null
+++ b/src/fuv/cf_remove_motions.c
@@ -0,0 +1,316 @@
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: cf_remove_motions options intermediate_file
+ *
+ * Description: Associates a photon with an aperture and corrects for grating,
+ * mirror, spacecraft (jitter) and focal plane assembly (FPA)
+ * motion. The position of the Y centroid is also determined
+ * both as a function of time (before correction for s/c motion)
+ * and for the entire exposure (after motion correction).
+ * The resulting coordinates represent the data obtained by a
+ * motionless instrument.
+ *
+ * By default, all corrections are performed. Command line
+ * options allow one or more corrections to be omitted.
+ *
+ * Arguments: input_file Intermediate data file
+ *
+ * Calibration files:
+ *
+ * Returns: 0 on successful completion
+ *
+ * Calls: cf_find_spectra, cf_calculate_ycent_motion,
+ * cf_grating_motion, cf_fpa_position, cf_mirror_motion,
+ * cf_satellite_jitter, cf_calculate_y_centroid
+ *
+ * History: 09/30/02 peb 1.1 Begin work
+ * 12/04/02 wvd 1.5 Install Y centroid routines.
+ * Modify call to cf_satellite_jitter
+ * 12/12/02 wvd 1.6 Change infits -> header throughout
+ * 03/04/03 peb 1.10 Minor code changes to remove gcc -Wall
+ * messages: unused j in main.
+ * Added unistd.h, so getopt is portable
+ * 03/05/03 wvd 1.11 Added cf_target_count_rate
+ * 03/10/03 peb 1.12 Added verbose_level, unistd.h for
+ * getopt portability, and changed
+ * locflags to unsigned char *.
+ * 03/13/03 rdr 1.13 corrected small error in tabulating
+ * count rate_sic
+ * 04/17/03 wvd 1.17 Add cf_find_spectra for initial
+ * assignment of photons to
+ * target apertures. Add last_call to
+ * cf_identify_channel, last_call and
+ * weight to cf_calculate_y_centroid
+ * 04/21/03 wvd 1.18 Pass tsunrise to cf_grating_motion,
+ * tsunset to cf_mirror_motion,
+ * channel to cf_satellite_jitter.
+ * 06/02/03 wvd 1.20 Don't modify count-rate arrays
+ * for HIST data.
+ * 06/11/03 wvd 1.21 Pass datatype to cf_read_col and
+ * cf_write_col.
+ * 08/01/03 wvd 1.23 Add cf_error_init after calls to
+ * subroutines.
+ * 08/06/03 wvd 1.24 Change channel to unsigned char.
+ * Remove GTI's from cf_satellite_jitter.
+ * 08/25/03 wvd 1.25 Change coltype from string to int in
+ * cf_read_col and cf_write_col.
+ * 09/18/03 wvd 1.26 Pass locflags to cf_identify_channel
+ * 10/21/03 wvd 1.27 For HIST data, don't write blank
+ * LiF and SiC count-rate arrays to IDF.
+ * 10/27/03 wvd 1.28 Pass pha array to cf_find_spectra.
+ * Delete last_call from argument list
+ * of cf_calculate_y_centroid.
+ * 10/31/03 wvd 1.29 Treat channel as unsigned char
+ * throughout.
+ * 04/06/04 bjg 1.30 Remove unused variables
+ * 05/03/04 wvd 1.31 Improve documentation.
+ * Move first call of cf_identify_channel
+ * from cf_find_spectra to this routine.
+ * 06/02/04 wvd 1.32 Copy/move cf_set_photon_flags(),
+ * cf_set_good_time_intervals(), and
+ * cf_modify_hist_times() from
+ * cf_screen_photons. Run them only if
+ * cf_satellite_jitter rejects some time
+ * AND if they were already run before.
+ * Pass timeflags to cf_find_spectra()
+ * and cf_calculate_y_centroid().
+ * Get exp_jitr from cf_satellite_jitter.
+ * 07/21/04 wvd 1.33 Add include file <string.h>
+ * 03/10/05 wvd 1.34 Change use of variable pad. Now add
+ * 10 to user_pad on first call to
+ * cf_identify_channel, 0 on second call.
+ * 03/22/05 wvd 1.35 Change TIME_SUNRISE and TIME_SUNSET
+ * from floats to shorts.
+ * 05/20/05 wvd 1.36 Clean up i/o.
+ * 09/09/05 wvd 1.37 Add -j to list of allowed options.
+ * 11/29/05 wvd 1.38 Separate cf_satellite_jitter into two
+ * routines. Screening is performed
+ * earlier, so we need not copy flags.
+ * 08/30/06 wvd 1.39 Add -a to list of allowed options.
+ * 12/29/06 wvd 1.40 Pass weights array and initial LiF
+ * and SiC counts arrays to
+ * cf_target_count_rate. Make arrays
+ * rate_lif and rate_sic floats. If
+ * they are too large to store as shorts,
+ * store as unsigned shorts.
+ * 02/02/07 wvd 1.41 If LiF or SiC count rate is too large
+ * for an unsigned int, set to zero.
+ *
+ ****************************************************************************/
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include "calfuse.h"
+
+static char CF_PRGM_ID[] = "cf_remove_motions";
+static char CF_VER_NUM[] = "1.41";
+
+int
+main(int argc, char *argv[])
+{
+ unsigned char *channel=NULL, *timeflags=NULL, *locflags=NULL,
+ *statflag=NULL;
+ int grating_motion=1, fpa_position=1, mirror_motion=1, sat_jitter=1;
+ int last_call, set_times=FALSE, set_gtis=FALSE, airglow_centroid=FALSE;
+ int user_pad=0, status=0, set_rate=FALSE, optc;
+ long i, nevents, ntimes;
+ float *time=NULL, *ttime=NULL, *xfarf=NULL, *yfarf=NULL, *x, *y;
+ float *weight=NULL, *ycent_lif, *ycent_sic;
+ float max_rate_lif=0, max_rate_sic=0, *rate_lif=NULL, *rate_sic=NULL;
+ float tscale=1, tzero=32768;
+ short *tsunrise=NULL, *tsunset=NULL;
+ GTI gti;
+ fitsfile *header;
+
+ char opts[] = "hagfmjp:v:";
+ char usage[] =
+ "Usage:\n"
+ " cf_remove_motions [-hagfmj] [-p pad] [-v level] idf_file\n";
+ char option[] =
+ "Options:\n"
+ " -h: this help message\n"
+ " -v: verbose level (default is 1; 0 is silent)\n"
+ " -a: use airglow lines to determine spectral centroid\n"
+ " -p: aperture padding in pixels (default is 10)\n"
+ " -g: no grating motion correction\n"
+ " -f: no fpa position correction\n"
+ " -m: no mirror motion correction\n"
+ " -j: no satellite jitter correction\n";
+
+ verbose_level = 1;
+
+ 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;
+ case 'p':
+ user_pad = atoi(optarg);
+ break;
+ case 'g':
+ grating_motion = 0;
+ break;
+ case 'f':
+ fpa_position = 0;
+ break;
+ case 'a':
+ airglow_centroid = TRUE;
+ break;
+ case 'm':
+ mirror_motion = 0;
+ break;
+ case 'j':
+ sat_jitter = 0;
+ break;
+ }
+ }
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+ if (argc <= optind) {
+ printf("%s", usage);
+ cf_if_error("Incorrect number of command-line arguments");
+ }
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Begin Processing");
+
+ FITS_open_file(&header, argv[optind], READWRITE, &status);
+
+ FITS_movabs_hdu(header, 2, NULL, &status);
+ nevents = cf_read_col(header, TFLOAT, "TIME", (void **) &time);
+ nevents = cf_read_col(header, TFLOAT, "WEIGHT", (void **) &weight);
+ nevents = cf_read_col(header, TFLOAT, "XFARF", (void **) &xfarf);
+ nevents = cf_read_col(header, TFLOAT, "YFARF", (void **) &yfarf);
+ nevents = cf_read_col(header, TBYTE, "TIMEFLGS", (void **) &timeflags);
+ nevents = cf_read_col(header, TBYTE, "LOC_FLGS", (void **) &locflags);
+ channel = cf_calloc(nevents, sizeof(unsigned char));
+
+ FITS_movabs_hdu(header, 4, NULL, &status) ;
+ ntimes = cf_read_col(header, TFLOAT, "TIME", (void **) &ttime) ;
+ ntimes = cf_read_col(header, TBYTE, "STATUS_FLAGS", (void **) &statflag);
+ ntimes = cf_read_col(header, TSHORT, "TIME_SUNRISE", (void **) &tsunrise) ;
+ ntimes = cf_read_col(header, TSHORT, "TIME_SUNSET", (void **) &tsunset) ;
+ ntimes = cf_read_col(header, TFLOAT, "LIF_CNT_RATE", (void **) &rate_lif) ;
+ ntimes = cf_read_col(header, TFLOAT, "SIC_CNT_RATE", (void **) &rate_sic) ;
+ ycent_lif=(float *) cf_calloc(ntimes, sizeof(float)) ;
+ ycent_sic=(float *) cf_calloc(ntimes, sizeof(float)) ;
+
+ FITS_movabs_hdu(header, 1, NULL, &status);
+ x = xfarf;
+ y = yfarf;
+
+ /* Find all six spectra and compute centroids. */
+ cf_find_spectra(header, nevents, weight, x, y, channel, timeflags,
+ locflags, airglow_centroid);
+
+ /* Initial assignment of channel numbers to photons */
+ cf_identify_channel(header, nevents, xfarf, yfarf, channel, locflags,
+ user_pad+10, last_call=FALSE);
+
+ /* Track Y centroids of moving spectra. */
+ cf_calculate_ycent_motion(header, nevents, time, y, channel, locflags,
+ ntimes, ttime, ycent_lif, ycent_sic);
+
+ /* Correct for detector motion during exposure. */
+ if (grating_motion)
+ cf_grating_motion(header, nevents, time, x, y, channel,
+ ntimes, ttime, tsunrise);
+
+ /* Shift spectra in X to account for position of the FPA. */
+ if (fpa_position)
+ cf_fpa_position(header, nevents, x, channel);
+
+ /* Correct for mirror motion during exposure. */
+ if (mirror_motion)
+ cf_mirror_motion(header, nevents, time, x, y, channel,
+ ntimes, ttime, tsunset);
+
+ /* Correct for spacecraft motion during exposure. */
+ if (sat_jitter)
+ cf_satellite_jitter(header, nevents, time, x, y, channel,
+ ntimes, ttime, statflag);
+
+ /* Compute centroids of motion-corrected spectra. */
+ cf_calculate_y_centroid(header, nevents, weight, x, y, channel,
+ timeflags, locflags);
+
+ /* Final assignment of channel numbers to photons */
+ cf_identify_channel(header, nevents, x, y, channel, locflags,
+ user_pad, last_call=TRUE);
+
+ /* Compute count rates for TTAG target spectra. */
+ set_rate = !(cf_target_count_rate(header, nevents, time, weight,
+ channel, locflags, ntimes, ttime, rate_lif, rate_sic));
+
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+ cf_verbose(3, "Writing X, Y, CHANNEL to IDF");
+ FITS_movabs_hdu(header, 2, NULL, &status);
+ if (set_times)
+ cf_write_col(header, TFLOAT, "TIME", (void *) time, nevents);
+ cf_write_col(header, TFLOAT, "X", (void *) x, nevents);
+ cf_write_col(header, TFLOAT, "Y", (void *) y, nevents);
+ cf_write_col(header, TBYTE, "CHANNEL", (void *) channel, nevents);
+
+ if (set_gtis) {
+ cf_verbose(3, "Writing good-time intervals to IDF");
+ FITS_movabs_hdu(header, 3, NULL, &status);
+ cf_write_col(header, TDOUBLE, "START", (void *) gti.start, gti.ntimes);
+ cf_write_col(header, TDOUBLE, "STOP", (void *) gti.stop, gti.ntimes);
+ free(gti.stop);
+ free(gti.start);
+ }
+
+ FITS_movabs_hdu(header, 4, NULL, &status);
+ cf_verbose(3, "Writing timeline information to IDF");
+ if (set_rate) {
+ for (i = 0; i < ntimes; i++) {
+ if (rate_lif[i] > 65535) rate_lif[i] = 0;
+ if (rate_sic[i] > 65535) rate_sic[i] = 0;
+ if (max_rate_lif < rate_lif[i]) max_rate_lif = rate_lif[i];
+ if (max_rate_sic < rate_sic[i]) max_rate_sic = rate_sic[i];
+ }
+ cf_verbose(2, "max_rate_lif = %.0f", max_rate_lif);
+ cf_verbose(2, "max_rate_sic = %.0f", max_rate_sic);
+ if (max_rate_lif > 32767) {
+ FITS_update_key(header, TFLOAT, "TSCAL10", &tscale, NULL, &status);
+ FITS_update_key(header, TFLOAT, "TZERO10", &tzero, NULL, &status);
+ fits_set_tscale(header, 10, (double)tscale, (double)tzero, &status);
+ }
+ if (max_rate_sic > 32767) {
+ FITS_update_key(header, TFLOAT, "TSCAL11", &tscale, NULL, &status);
+ FITS_update_key(header, TFLOAT, "TZERO11", &tzero, NULL, &status);
+ fits_set_tscale(header, 11, (double)tscale, (double)tzero, &status);
+ }
+ FITS_write_col(header, TFLOAT, 10, 1, 1, ntimes, rate_lif, &status);
+ FITS_write_col(header, TFLOAT, 11, 1, 1, ntimes, rate_sic, &status);
+ }
+ cf_write_col(header, TFLOAT, "YCENT_LIF", (void *) ycent_lif, ntimes);
+ cf_write_col(header, TFLOAT, "YCENT_SIC", (void *) ycent_sic, ntimes);
+ cf_verbose(3, "IDF updates complete");
+
+ FITS_close_file(header, &status);
+
+ free(time);
+ free(weight);
+ free(xfarf);
+ free(yfarf);
+ free(locflags);
+ free(timeflags);
+ free(channel);
+ free(ttime);
+ free(rate_lif);
+ free(rate_sic);
+ free(ycent_lif);
+ free(ycent_sic);
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Done processing");
+ return status;
+}
diff --git a/src/fuv/cf_screen_photons.c b/src/fuv/cf_screen_photons.c
new file mode 100644
index 0000000..bd82bba
--- /dev/null
+++ b/src/fuv/cf_screen_photons.c
@@ -0,0 +1,298 @@
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: cf_screen_photons options intermediate_file
+ *
+ * Description: Filters events in the intermediate data file (IDF) for limb
+ * angle, SAA crossing, high voltage changes, bursts, and PHA.
+ * Sets the event flags and GTIs. Data are modified in place.
+ *
+ * By default all corrections are performed. Command line
+ * options allow one or more corrections to be omitted.
+ *
+ * Arguments: input_file FARF-corrected intermediate data file
+ *
+ * Calibration files:
+ *
+ * Returns: 0 on successful completion
+ *
+ * Calls: cf_screen_limb_angle, cf_screen_saa, cf_screen_high_voltage,
+ * cf_screen_burst, cf_screen_jitter,
+ * cf_set_user_gtis, cf_set_photon_flags, cf_modify_hist_times,
+ * cf_screen_pulse_height, cf_screen_airglow, cf_screen_bad_pixels
+ *
+ * History: 11/05/02 1.1 peb Begin work
+ * 11/13/02 1.2 peb Added screening functions to program
+ * 11/14/02 1.3 peb Added burst-screening function
+ * 11/18/02 1.4 peb Corrected logic dealing with reading,
+ * writing, and freeing of GTI struct.
+ * Corrected some grammatical errors.
+ * 12/10/02 1.5 rdr changed call to cf_screen_bursts
+ * 12/18/02 1.6 rdr updated names of some columns in
+ * the calls to the timeline extension
+ * 12/20/02 1.7 wvd Change flags to unsigned char
+ * 03/10/03 1.9 peb Added verbose_level and added unistd.h
+ * for getopt portability
+ * 05/10/03 1.10 wvd Pass locflag to cf_set_photon_flags
+ * 05/30/03 1.11 wvd Pass weight to cf_set_photon_flags
+ * 06/11/03 1.12 wvd Treat HV as array of shorts.
+ * Pass datatype to cf_read_col and
+ * cf_write_col.
+ * 08/25/03 1.13 wvd Change coltype from string to int in
+ * cf_read_col and cf_write_col.
+ * 09/10/03 1.14 wvd Change background array to type short.
+ * Add cf_set_user_gtis().
+ * 10/02/03 1.15 wvd Pass locflag array to
+ * cf_screen_pulse_height; write to IDF
+ * 02/10/04 1.16 wvd Add cf_screen_fifo_overflow()
+ * 06/02/04 1.17 wvd Add cf_modify_hist_times()
+ * 06/03/04 1.18 wvd Read XFARF and YFARF, not X and Y.
+ * If INSTMODE = TTAG, don't bother to
+ * call cf_modify_hist_times().
+ * 02/02/05 1.19 wvd Pass rate_aic to cf_screen_burst
+ * 03/10/05 1.20 wvd Add cf_screen_airglow()
+ * 03/30/05 1.21 wvd Don't change TIME_COR to SKIPPED
+ * for TTAG data. Leave as OMIT.
+ * 05/20/05 1.22 wvd Clean up i/o.
+ * 06/03/05 1.23 wvd Fix typo in CF_VER_NUM.
+ * 09/09/05 1.24 wvd Update list of allowed options.
+ * 11/09/05 1.25 wvd Change argument list for
+ * cf_screen_fifo_overflow.
+ * 11/22/05 1.26 wvd Add cf_screen_jitter and
+ * cf_screen_bad_pixels.
+ * 01/24/06 1.27 wvd Move cf_screen_airglow before
+ * cf_screen_burst
+ * 12/29/06 1.28 wvd Move cf_screen_fifo_overflow to
+ * cf_convert_to_farf.
+ * 07/18/08 1.29 wvd Write STATUS_FLAGS to IDF before
+ * calling cf_set_photon_flags, which
+ * may change the array.
+ *
+ ****************************************************************************/
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include "calfuse.h"
+
+int
+main(int argc, char *argv[])
+{
+ char CF_PRGM_ID[] = "cf_screen_photons";
+ char CF_VER_NUM[] = "1.29";
+
+ char instmode[FLEN_VALUE];
+ unsigned char *pha=NULL, *timeflag=NULL, *statflag=NULL, *locflag=NULL;
+ int limb_screening=1, saa_screening=1, voltage_screening=1;
+ int burst_screening=1, set_flags=1, airglow_screening=1, pha_screening=1;
+ int modify_times=1, set_gtis=1, set_user_gtis=1;
+ int bad_pixel_screening=1, set_times=FALSE, jitter_screening=1;
+ int status=0, optc;
+ long nevents, nseconds;
+ short *background=NULL, *rate_lif=NULL, *rate_sic=NULL, *voltage=NULL;
+ float *time=NULL, *x=NULL, *y=NULL, *weight=NULL;
+ float *timeline=NULL, *limb=NULL, *longitude=NULL, *latitude=NULL;
+ float *rate_aic=NULL;
+ GTI gti;
+ fitsfile *header;
+
+ char opts[] = "halstbjufimdpv:";
+ char usage[] =
+ "Usage:\n"
+ " cf_screen_photons [-halstbjufimdp] [-v level] idf_file\n";
+ char option[] =
+ "Options:\n"
+ " -h: this help message\n"
+ " -v: verbosity level (default is 1; 0 is silent)\n"
+ " -a: no airglow screening\n"
+ " -l: no limb screening\n"
+ " -s: no SAA screening\n"
+ " -t: no high voltage screening\n"
+ " -b: no burst screening\n"
+ " -j: no jitter screening\n"
+ " -u: no user-defined good-time intervals\n"
+ " -f: do not set photon event flags\n"
+ " -i: do not update GTI arrays\n"
+ " -m: do not modify HIST photon times\n"
+ " -d: no bad-pixel screening\n"
+ " -p: no PHA screening\n";
+
+ verbose_level = 1;
+
+ 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;
+ case 'l':
+ limb_screening = 0;
+ break;
+ case 't':
+ voltage_screening = 0;
+ break;
+ case 's':
+ saa_screening = 0;
+ break;
+ case 'b':
+ burst_screening = 0;
+ break;
+ case 'j':
+ jitter_screening = 0;
+ break;
+ case 'u':
+ set_user_gtis = 0;
+ break;
+ case 'f':
+ set_flags = 0;
+ break;
+ case 'i':
+ set_gtis = 0;
+ break;
+ case 'm':
+ modify_times = 0;
+ break;
+ case 'a':
+ airglow_screening = 0;
+ break;
+ case 'd':
+ bad_pixel_screening = 0;
+ break;
+ case 'p':
+ pha_screening = 0;
+ break;
+ }
+ }
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+ if (argc <= optind) {
+ printf("%s", usage);
+ cf_if_error("Incorrect number of program arguments");
+ }
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Begin Processing");
+
+ FITS_open_file(&header, argv[optind], READWRITE, &status);
+
+ FITS_movabs_hdu(header, 2, NULL, &status);
+ nevents = cf_read_col(header, TFLOAT, "TIME", (void **) &time);
+ nevents = cf_read_col(header, TBYTE, "PHA", (void **) &pha);
+ nevents = cf_read_col(header, TFLOAT, "WEIGHT", (void **) &weight);
+ nevents = cf_read_col(header, TFLOAT, "XFARF", (void **) &x);
+ nevents = cf_read_col(header, TFLOAT, "YFARF", (void **) &y);
+ nevents = cf_read_col(header, TBYTE, "TIMEFLGS", (void **) &timeflag);
+ nevents = cf_read_col(header, TBYTE, "LOC_FLGS", (void **) &locflag);
+
+ if (burst_screening) {
+ FITS_movabs_hdu(header, 3, NULL, &status);
+ gti.ntimes = cf_read_col(header, TDOUBLE, "START",(void **) &gti.start);
+ gti.ntimes = cf_read_col(header, TDOUBLE, "STOP", (void **) &gti.stop);
+ }
+ FITS_movabs_hdu(header, 4, NULL, &status);
+ nseconds = cf_read_col(header, TFLOAT, "TIME", (void **) &timeline);
+ nseconds = cf_read_col(header, TBYTE, "STATUS_FLAGS", (void **) &statflag);
+ nseconds = cf_read_col(header, TFLOAT, "LIMB_ANGLE", (void **) &limb);
+ nseconds = cf_read_col(header, TFLOAT, "LONGITUDE", (void **) &longitude);
+ nseconds = cf_read_col(header, TFLOAT, "LATITUDE", (void **) &latitude);
+ nseconds = cf_read_col(header, TSHORT, "HIGH_VOLTAGE", (void **) &voltage);
+ nseconds = cf_read_col(header, TSHORT, "LIF_CNT_RATE", (void **) &rate_lif);
+ nseconds = cf_read_col(header, TSHORT, "SIC_CNT_RATE", (void **) &rate_sic);
+ nseconds = cf_read_col(header, TFLOAT, "AIC_CNT_RATE", (void **) &rate_aic);
+ background = (short *) cf_calloc(nseconds, sizeof(short)) ;
+
+ /* If INSTMODE = TTAG, don't bother to call cf_modify_hist_times. */
+ FITS_movabs_hdu(header, 1, NULL, &status);
+ FITS_read_key(header, TSTRING, "INSTMODE", instmode, NULL, &status);
+ if (!strncmp(instmode, "TTAG", 4)) modify_times = FALSE;
+
+ if (airglow_screening)
+ cf_screen_airglow(header, nevents, x, y, locflag);
+
+ if (limb_screening)
+ cf_screen_limb_angle(header, nseconds, statflag, limb);
+
+ if (saa_screening)
+ cf_screen_saa(header, nseconds, statflag, longitude, latitude);
+
+ if (voltage_screening)
+ cf_screen_high_voltage(header, nseconds, statflag, voltage);
+
+ if (burst_screening) {
+ cf_screen_burst(header, nevents, time, x, y, locflag, &gti,
+ nseconds, timeline, statflag, rate_aic, background);
+ free(gti.stop);
+ free(gti.start);
+ }
+
+ if (jitter_screening)
+ cf_screen_jitter(header, nseconds, timeline, statflag);
+
+ if (set_user_gtis)
+ cf_set_user_gtis(header, nseconds, timeline, statflag);
+
+ /* Write STATUS_FLAGS array to IDF before calling cf_set_photon_flags. */
+ FITS_movabs_hdu(header, 4, NULL, &status);
+ cf_write_col(header, TBYTE, "STATUS_FLAGS", (void *) statflag, nseconds);
+ FITS_movabs_hdu(header, 1, NULL, &status);
+
+ if (set_flags)
+ cf_set_photon_flags(header, nevents, time, weight, timeflag,
+ locflag, nseconds, timeline, statflag);
+
+ if (set_gtis)
+ cf_set_good_time_intervals(header, nseconds, timeline,
+ statflag, &gti);
+
+ if (modify_times)
+ set_times = !(cf_modify_hist_times(header, nevents, time, &gti));
+
+ if (bad_pixel_screening)
+ cf_screen_bad_pixels(header, nevents, x, y, locflag);
+
+ if (pha_screening)
+ cf_screen_pulse_height(header, nevents, pha, locflag);
+
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+ FITS_movabs_hdu(header, 2, NULL, &status);
+ if (set_times)
+ cf_write_col(header, TFLOAT, "TIME", (void *) time, nevents);
+ cf_write_col(header, TBYTE, "TIMEFLGS", (void *) timeflag, nevents);
+ cf_write_col(header, TBYTE, "LOC_FLGS", (void *) locflag, nevents);
+
+ if (set_gtis) {
+ FITS_movabs_hdu(header, 3, NULL, &status);
+ cf_write_col(header, TDOUBLE, "START", (void *) gti.start, gti.ntimes);
+ cf_write_col(header, TDOUBLE, "STOP", (void *) gti.stop, gti.ntimes);
+ free(gti.stop);
+ free(gti.start);
+ }
+
+ if (burst_screening) {
+ FITS_movabs_hdu(header, 4, NULL, &status);
+ cf_write_col(header, TSHORT, "BKGD_CNT_RATE", (void *) background,
+ nseconds);
+ }
+
+ FITS_close_file(header, &status);
+
+ free(background);
+ free(voltage);
+ free(latitude);
+ free(longitude);
+ free(limb);
+ free(statflag);
+ free(timeline);
+ free(timeflag);
+ free(pha);
+ free(y);
+ free(x);
+ free(time);
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Done processing");
+ return 0;
+}
diff --git a/src/fuv/cf_ttag_init.c b/src/fuv/cf_ttag_init.c
new file mode 100644
index 0000000..ec11f19
--- /dev/null
+++ b/src/fuv/cf_ttag_init.c
@@ -0,0 +1,594 @@
+/*****************************************************************************
+ * Johns Hopkins University
+ * Center For Astrophysical Sciences
+ * FUSE
+ *****************************************************************************
+ *
+ * Synopsis: cf_ttag_init input_file output_file
+ *
+ * Description: Reads a raw ttag file, which is a FITS binary table
+ * consisting of four columns:
+ *
+ * TIME FLOAT
+ * X INT
+ * Y INT
+ * PHA BYTE
+ *
+ * This routine will convert the raw ttag file to another binary
+ * table with 13 columns the values for most of these columns
+ * will be added by various modules of the pipeline:
+ *
+ * TIME FLOAT time of arrival for photon
+ * XRAW INT raw x position
+ * YRAW INT raw y position
+ * PHA BYTE pha value
+ * WEIGHT FLOAT effective area and flux calibration
+ * XFARF FLOAT x position in geometrically
+ * corrected frame
+ * YFARF FLOAT y position in geometrically
+ * corrected frame
+ * X FLOAT final x position (after correcting
+ * for motions)
+ * Y FLOAT final y position (after correcting
+ * for motions)
+ * CHANNEL CHAR aperture ID for the photon
+ * TIMEFLGS CHAR temporal flags - various bits set
+ * LOC_FLGS CHAR location flags - various bits set
+ * LAMBDA FLOAT wavelength for each photon
+ * ERGCM2 FLOAT flux calibration for each photon
+ *
+ * This routine calls cf_fuv_init to set up the calibration
+ * entries in the header.
+ *
+ * In addition, the routine creates a timeline containing
+ * orbital information, count rates, and high-voltage
+ * information which is used in later pipeline modules.
+ *
+ * Turns out that OPUS good-time intervals may exclude SAA
+ * passes that remain in the photon-event list. This means
+ * that there may be photons in the photon-event list whose
+ * times are not listed in the timeline table. To catch
+ * them, we set all photon status flags to TEMPORAL_HV.
+ *
+ *
+ * Returns: Zero upon successful completion
+ *
+ * History: 03/30/98 gak Begin work
+ * 03/18/99 emm Modified header.
+ * 04/06/99 emm Added check on nrows to be no
+ * larger than nevents.
+ * 04/15/99 barrett Deleted FF and DY columns,
+ * added FITS wrapper functions,
+ * tidied code.
+ * 04/22/99 emm Program now returns int.
+ * 04/23/99 emm Fixed two bugs causing segmentation
+ * faults (pha was being written as
+ * long, at definition of outdx was
+ * given as 1B instead of 1E.) Added
+ * check on number of arguments.
+ * 04/29/99 emm Added check on nrows to make sure
+ * it is smaller than nevents.
+ * 04/30/99 peb Added cf_malloc functions.
+ * 06/07/99 peb Added reporting of version number.
+ * 18/07/99 1.12 jm Populate APER_ACT keyword
+ * 10/28/99 1.14 emm Added DY column.
+ * 12/02/99 1.15 emm Added corrections to some keywords
+ * removed APER_ACT keyword update
+ * 12/21/00 1.16 peb Fixed type mismatches in cfitsio
+ * calls
+ * 05/16/01 1.17 rdr added night/day flag column (dnflg)
+ * 08/20/01 1.18 wvd Check keywords SPECBINX and SPECBINY;
+ * if 0, set to 1
+ * 10/19/01 1.19 wvd Move correction of SPECBINX, etc.
+ * from cf_ttag_image.
+ * 04/03/02 1.20 wvd Clean up keywords in photon-event list.
+ * 08/02/02 1.21 rdr - changed the format of the binary
+ * tables to improve speed
+ * - added new columns to the table
+ * 09/15/02 1.22 rdr added extension containing timeline
+ * 11/07/02 1.23 peb Modified columns for event and
+ * timeline flags. Removed temporary
+ * keywords. Changed include files to
+ * use calfusettag.h
+ * 11/13/02 1.24 rdr Added ycentl and ycents columns to
+ * timeline.
+ * Added section to flag geocoronal photons
+ * and photons in the inactive part of the
+ * detector. Moved processing of the
+ * photon list into a separate subroutine.
+ * Fixed problem of program crashing when
+ * needed columns are not in the hskp file
+ * 12/06/02 1.25 rdr removed variables which were not being
+ * used
+ * 12/12/02 1.5 wvd Installed program.
+ * 12/18/02 1.6 rdr use AIRG calibration file for airglow
+ * locations
+ * 12/20/02 1.7 rdr - check for negative count rates and
+ * correct
+ * - convert status flags to unsigned char
+ * - flag photons near start and end of
+ * GTI
+ * 01/24/03 1.8 rdr - correct situation where hskp file
+ * has blank columns
+ * 02/11/03 1.9 rdr Added ERGCM2S column to photon table
+ * 03/04/03 1.10 rdr removed YFARFC column and deleted some
+ * unused variables
+ * 03/19/03 1.12 peb Added command-line options and
+ * verbose_level parameter
+ * Changed all printf calls to cf_verbose
+ * calls with verbose level == 1
+ * 03/25/03 1.13 peb Changed a cf_verbose to cf_timestamp.
+ * 04/01/03 1.15 wvd Call cf_error_init after cf_timeline.
+ * 04/04/03 1.16 wvd Update FILETYPE keyword. Set verbose
+ * level of each call to cf_verbose.
+ * 04/07/03 1.17 wvd Update FILENAME keyword.
+ * 04/07/03 1.18 wvd Add FPADXLIF and FPADXSIC to header.
+ * 04/09/03 1.19 rdr Correct error in determining the name
+ * of the housekeeping file
+ * 04/29/03 1.21 wvd Allow possiblity that housekeeping
+ * filename is in lower-case letters.
+ * 05/06/03 1.22 rdr Add daynight keyword, bkg_max and
+ * bkg_min keywords, and changed the
+ * column ergcm2s to ergcm2
+ * 05/10/03 1.23 wvd Modify internal copy of GTI's.
+ * Make number of timeline entries more
+ * nearly equal to EXPTIME. Discard
+ * photons with bad time markers.
+ * 06/03/03 1.24 wvd Add call to cf_proc_check.
+ * Keep trying to get GTI's right.
+ * 06/09/03 1.25 wvd Compress data with TSCALE and TZERO.
+ * 06/11/03 1.26 wvd Change calfusettag.h to calfuse.h
+ * 07/07/03 1.27 rdr Correct initialization of dn_flag_last
+ * when searching for time_sunrise and
+ * time_sunset
+ * 07/17/03 1.28 wvd Move various subroutines to library.
+ * 07/23/03 1.29 wvd Close ELEC_CAL file.
+ * Delete goto statement.
+ * 09/15/03 1.31 wvd Set temporal flags to TEMPORAL_HV.
+ * 10/02/03 1.32 wvd Delete reference to LOCATION_GTI flag
+ * 10/26/03 1.33 wvd Increase to morekeys to 38.
+ * 11/05/03 1.34 wvd Added stdlib.h and unistd.h
+ * 03/03/04 1.35 rdr Exit if no photons found.
+ * 04/06/04 1.37 bjg Change formats to match arg types
+ * in printf
+ * Functions return EXIT_SUCCESS
+ * Remove static keyword in struct key
+ * definition
+ * Add braces in TSCAL and TZERO
+ * definitions
+ * When no events are present in
+ * the raw file, create a photon list
+ * with a dummy event.
+ * 03/10/05 1.38 wvd Move airglow screening to
+ * cf_screen_airglow.
+ * Initialize XFARF and YFARF to zero.
+ * 05/20/05 1.39 wvd Clean up i/o.
+ * 05/31/06 1.40 wvd OPUS has been updated, so we can set
+ * morekeys to 0.
+ * 06/12/06 1.41 wvd Change cf_if_warning to cf_verbose.
+ * 08/21/07 1.42 wvd Add -e flag to set HKEXISTS to YES.
+ *
+ ****************************************************************************/
+
+#include <stdlib.h>
+#include <unistd.h>
+#include "calfuse.h"
+
+struct key {
+ char keyword[FLEN_KEYWORD];
+ float value;
+ };
+
+static int
+cf_init_null_photon_list(fitsfile *outfits) {
+
+ int status=0;
+
+ long i;
+
+ char keyword[FLEN_CARD], card[FLEN_CARD];
+
+ 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]={"1E","1I","1I","1B","1E","1I","1I",
+ "1I","1I","1B","1B","1B","1E","1E"};
+
+ 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 hdu2_time[1] = {0.0};
+ short hdu2_xraw[1] = {0};
+ short hdu2_yraw[1] = {0};
+ char hdu2_pha[1] = {0};
+ float hdu2_weight[1] = {0.0};
+ float hdu2_xfarf[1] = {0.0};
+ float hdu2_yfarf[1] = {0.0};
+ float hdu2_x[1] = {0.0};
+ float hdu2_y[1] = {0.0};
+ char hdu2_channel[1] = {0};
+ char hdu2_timeflgs[1] = {TEMPORAL_HV};
+ char hdu2_loc_flgs[1] = {LOCATION_SHLD};
+ float hdu2_lambda[1] = {0.0};
+ float hdu2_ergcm2s[1] = {0.0};
+
+ cf_verbose(3, "Entering cf_init_null_photon_list.");
+
+ /* Append a new empty binary table to the output file */
+ FITS_create_tbl(outfits, BINARY_TBL, 1, 14, 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);
+ }
+
+
+
+
+ FITS_write_col(outfits, TFLOAT, 1, 1, 1, 1, hdu2_time , &status);
+ FITS_write_col(outfits, TSHORT, 2, 1, 1, 1, hdu2_xraw , &status);
+ FITS_write_col(outfits, TSHORT, 3, 1, 1, 1, hdu2_yraw , &status);
+ FITS_write_col(outfits, TBYTE , 4, 1, 1, 1, hdu2_pha , &status);
+ FITS_write_col(outfits, TFLOAT, 5, 1, 1, 1, hdu2_weight , &status);
+ FITS_write_col(outfits, TFLOAT, 6, 1, 1, 1, hdu2_xfarf , &status);
+ FITS_write_col(outfits, TFLOAT, 7, 1, 1, 1, hdu2_yfarf , &status);
+ FITS_write_col(outfits, TFLOAT, 8, 1, 1, 1, hdu2_x , &status);
+ FITS_write_col(outfits, TFLOAT, 9, 1, 1, 1, hdu2_y , &status);
+ FITS_write_col(outfits, TBYTE , 10, 1, 1, 1, hdu2_channel , &status);
+ FITS_write_col(outfits, TBYTE , 11, 1, 1, 1, hdu2_timeflgs , &status);
+ FITS_write_col(outfits, TBYTE , 12, 1, 1, 1, hdu2_loc_flgs , &status);
+ FITS_write_col(outfits, TFLOAT, 13, 1, 1, 1, hdu2_lambda , &status);
+ FITS_write_col(outfits, TFLOAT, 14, 1, 1, 1, hdu2_ergcm2s , &status);
+
+ cf_verbose(3, "Exiting cf_init_null_photon_list.");
+ return EXIT_SUCCESS;
+}
+
+/*****************************************************************************/
+
+static int
+cf_init_photon_list(fitsfile *infits, fitsfile *outfits) {
+
+/*****************************************************************************
+ *
+ * Description: procedure to take input data from the raw data file and
+ * generate a table with 14 columns. These columns
+ * will be modified by later pipeline modules.
+ *
+ * ARGUMENTS:
+ * infits fitsfile name of the input raw data file
+ * outfits fitsfile name of the output intermediate data
+ * file
+ * INPUT DATA:
+ * TIME FLOAT time of arrival for each photon
+ * XRAW INT x position of photon
+ * YRAW INT y position of photon
+ * PHA BYTE pha value of the photon
+ *
+ * OUTPUT DATA:
+ * TIME FLOAT time of arrival for photon
+ * XRAW INT raw x position
+ * YRAW INT raw y position
+ * PHA BYTE pha value
+ * WEIGHT FLOAT effective area and flux calibration
+ * XFARF FLOAT x position in geometrically
+ * corrected frame
+ * YFARF FLOAT y position in geometrically
+ * corrected frame
+ * X FLOAT final x position (after correcting
+ * for motions)
+ * Y FLOAT final y position (after correcting
+ * for motions)
+ * CHANNEL CHAR aperture ID for the photon
+ * TIMEFLGS CHAR temporal flags - various bits set
+ * LOC_FLGS CHAR location flags - various bits set
+ * LAMBDA FLOAT wavelength for each photon
+ * ERGCM2 FLOAT flux cal for each photon
+ *
+ ****************************************************************************/
+
+ fitsfile *elecfits;
+ char fmt_byte[FLEN_CARD], fmt_float[FLEN_CARD], fmt_short[FLEN_CARD];
+ char *inpha;
+ char elecfile[FLEN_FILENAME];
+ char keyword[FLEN_CARD], card[FLEN_CARD];
+ unsigned char *channel, *location, *temporal;
+ short *inx, *iny ;
+ int status=0, intnull=0, anynull, hdutype;
+ int tcol, xcol, ycol, phacol, colval;
+ int tfields = 14; /* output table will have 14 columns */
+ int active_l, active_r;
+ long i;
+ long frow=1, felem=1, nevents, nrows=1; /* output table will have 1 row */
+ float *intime, *dumarrf;
+
+ 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.}};
+
+ cf_verbose(3, "Entering cf_init_photon_list.");
+
+ /* Move to the extension of the input file containing the data. */
+ FITS_movabs_hdu(infits, 2, &hdutype, &status);
+
+ /* Read the limits to the active area of the detector. */
+ FITS_read_key(outfits, TSTRING, "ELEC_CAL", elecfile, NULL, &status);
+ FITS_open_file(&elecfits, cf_cal_file(elecfile), READONLY, &status);
+ FITS_read_key(elecfits, TINT, "ACTIVE_L", &active_l, NULL, &status);
+ FITS_read_key(elecfits, TINT, "ACTIVE_R", &active_r, NULL, &status);
+ FITS_close_file(elecfits, &status);
+ cf_verbose(3, "Limits to the active area: left=%d, right=%d",
+ active_l, active_r);
+
+ /*
+ * Get the number of events in the input file.
+ */
+ FITS_read_key(infits, TLONG, "NAXIS2", &nevents, NULL, &status);
+ cf_verbose(3, "Raw data file contains %ld entries", 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, nrows, 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);
+ }
+
+ /*
+ * Allocate space for the input times, coords, and pha.
+ */
+ intime = (float *) cf_malloc(sizeof(float) * nevents);
+ inx = (short *) cf_malloc(sizeof(short) * nevents);
+ iny = (short *) cf_malloc(sizeof(short) * nevents);
+ inpha = (char *) cf_malloc(sizeof(char) * nevents);
+ /*
+ * Allocate space for the new output columns.
+ */
+ dumarrf = (float *) cf_malloc(sizeof(float) * nevents);
+ channel = (unsigned char *) cf_calloc(nevents, sizeof(unsigned char));
+ location = (unsigned char *) cf_calloc(nevents, sizeof(unsigned char));
+ temporal = (unsigned char *) cf_calloc(nevents, sizeof(unsigned char));
+
+ /*
+ * Read the data from the input file and write to the output
+ * file in a new format
+ *
+ * read the times
+ */
+ FITS_get_colnum(infits, TRUE, "TIME", &tcol, &status);
+ FITS_read_col(infits, TFLOAT, tcol, frow, felem, nevents, &intnull,
+ intime, &anynull, &status);
+ FITS_write_col(outfits, TFLOAT, 1, frow, felem, nevents, intime, &status);
+
+ /* process X and Y positions */
+ FITS_get_colnum(infits, TRUE, "X", &xcol, &status);
+ FITS_read_col(infits, TSHORT, xcol, frow, felem, nevents, &intnull,
+ inx, &anynull, &status);
+ FITS_write_col(outfits, TSHORT, 2, frow, felem, nevents, inx, &status);
+
+ FITS_get_colnum(infits, TRUE, "Y", &ycol, &status);
+ FITS_read_col(infits, TSHORT, ycol, frow, felem, nevents, &intnull,
+ iny, &anynull, &status);
+ FITS_write_col(outfits, TSHORT, 3, frow, felem, nevents, iny, &status);
+
+ /* now do the PHA column */
+ FITS_get_colnum(infits, TRUE, "PHA", &phacol, &status);
+ FITS_read_col(infits, TBYTE, phacol, frow, felem, nevents, &intnull,
+ inpha, &anynull, &status);
+ FITS_write_col(outfits, TBYTE, 4, frow, felem, nevents, inpha, &status);
+
+ /* fill weights with a dummy float - all equal to 1. */
+ for (i=0; i<nevents; i++)
+ dumarrf[i] = 1.;
+ FITS_write_col(outfits, TFLOAT, 5, frow, felem, nevents, dumarrf, &status);
+
+ /* fill XFARF, YFARF, X and Y arrays with 0. */
+ for (i=0; i<nevents; i++)
+ dumarrf[i] = 0.;
+ for (colval=6; colval<10; colval++) {
+ FITS_write_col(outfits, TFLOAT, colval, frow, felem, nevents,
+ dumarrf, &status);
+ }
+
+ /* Default value of temporal array is TEMPORAL_HV */
+ for (i=0; i<nevents; i++)
+ temporal[i] = TEMPORAL_HV;
+ FITS_write_col(outfits, TBYTE, 10, frow, felem, nevents, channel, &status);
+ FITS_write_col(outfits, TBYTE, 11, frow, felem, nevents, temporal, &status);
+
+ /* Set flags in the screening array for photons outside of the active
+ region of the detector. */
+ for (i=0; i<nevents; i++)
+ if (inx[i] < active_l || inx[i] > active_r)
+ location[i] = location[i] | LOCATION_SHLD;
+
+ /* Write location flags to output file. */
+ FITS_movabs_hdu(outfits, 2, &hdutype, &status);
+ FITS_write_col(outfits, TBYTE, 12, frow, felem, nevents,
+ location, &status);
+
+ /* Fill lambda and energy arrays with 0. */
+ FITS_write_col(outfits, TFLOAT, 13, frow, felem, nevents, dumarrf,
+ &status);
+ FITS_write_col(outfits, TFLOAT, 14, frow, felem, nevents, dumarrf,
+ &status);
+
+ free(intime);
+ free(inx);
+ free(iny);
+ free(inpha);
+ free(dumarrf);
+ free(channel);
+ free(location);
+ free(temporal);
+
+ cf_verbose(3, "Exiting cf_init_photon_list.");
+ return EXIT_SUCCESS;
+}
+
+
+/*****************************************************************************/
+
+int main(int argc, char *argv[])
+
+/*****************************************************************************/
+{
+ char CF_PRGM_ID[] = "cf_ttag_init";
+ char CF_VER_NUM[] = "1.42";
+
+ fitsfile *infits, *outfits;
+ int morekeys=0;
+ int modify_hkexists=FALSE;
+ int status=0, hdutype, optc;
+ long nphot ;
+
+ char opts[] = "ehv:";
+ char usage[] =
+ "Usage:\n"
+ " cf_ttag_init [-he] [-v level] rawttagfile idf_file\n";
+ char option[] =
+ "Options:\n"
+ " -h: this help message\n"
+ " -e: set header keyword HKEXISTS to YES in IDF file\n"
+ " -v: verbosity level (default is 1; 0 is silent)\n";
+
+ verbose_level = 1;
+
+ while ((optc = getopt(argc, argv, opts)) != -1) {
+ switch(optc) {
+
+ case 'h':
+ printf("%s\n%s", usage, option);
+ return 0;
+ case 'e':
+ modify_hkexists = TRUE;
+ break;
+ 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, "Begin execution");
+
+ FITS_open_file(&infits, argv[optind++], READONLY, &status);
+
+ /* Exit if data are not in TTAG mode. */
+ if ( cf_proc_check(infits, CF_PRGM_ID) ) {
+ FITS_close_file(infits, &status);
+ return (-1);
+ }
+
+ /* Issue warning if there are no events in the data set. */
+ FITS_read_key(infits, TLONG, "NEVENTS", &nphot, NULL, &status);
+ cf_verbose(3,"Number of events = %d ",nphot) ;
+ if (nphot < 1) {
+ cf_verbose(1, "No photons found in the data.") ;
+ }
+
+
+ /* Create output file. */
+ FITS_create_file(&outfits, argv[optind], &status);
+ /* Copy primary image header from the input file. */
+ FITS_copy_hdu(infits, outfits, morekeys, &status);
+
+ /* Update header keywords. */
+ FITS_update_key(outfits, TSTRING, "FILENAME", argv[optind], NULL, &status);
+ FITS_update_key(outfits, TSTRING, "FILETYPE",
+ "INTERMEDIATE DATA FILE", NULL, &status);
+ if (modify_hkexists)
+ FITS_update_key(outfits, TSTRING, "HKEXISTS", "YES", NULL, &status);
+
+ /* Populate the calibration keywords in the primary header. */
+ cf_fuv_init(outfits);
+
+ /* Write background limits to file header */
+ cf_set_background_limits(outfits);
+
+ /* Fill in the first extension with the photon information */
+ if (nphot<1) {
+ cf_init_null_photon_list(outfits);
+ }
+ else {
+ cf_init_photon_list(infits, outfits);
+ }
+
+ /* Copy good-time intervals from input to output. */
+ cf_verbose(3, "Copying good-time intervals from input to output.");
+ FITS_movabs_hdu(infits, 3, &hdutype, &status);
+ FITS_create_hdu(outfits, &status);
+ FITS_copy_hdu(infits, outfits, 0, &status);
+
+ /* Append a table containing the orbital timeline */
+ cf_timeline(outfits);
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+ /* Update processing flags. */
+ cf_proc_update(outfits, CF_PRGM_ID, "COMPLETE");
+
+ FITS_close_file(infits, &status);
+ FITS_close_file(outfits, &status);
+
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Finished execution.");
+ return EXIT_SUCCESS;
+}