aboutsummaryrefslogtreecommitdiff
path: root/src/libcf/cf_fpa_position.c
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2015-03-04 21:21:30 -0500
committerJoseph Hunkeler <jhunkeler@gmail.com>2015-03-04 21:21:30 -0500
commitd54fe7c1f704a63824c5bfa0ece65245572e9b27 (patch)
treeafc52015ffc2c74e0266653eecef1c8ef8ba5d91 /src/libcf/cf_fpa_position.c
downloadcalfuse-d54fe7c1f704a63824c5bfa0ece65245572e9b27.tar.gz
Initial commit
Diffstat (limited to 'src/libcf/cf_fpa_position.c')
-rw-r--r--src/libcf/cf_fpa_position.c231
1 files changed, 231 insertions, 0 deletions
diff --git a/src/libcf/cf_fpa_position.c b/src/libcf/cf_fpa_position.c
new file mode 100644
index 0000000..fd7229c
--- /dev/null
+++ b/src/libcf/cf_fpa_position.c
@@ -0,0 +1,231 @@
+/****************************************************************************
+ *
+ * Synopsis: cf_fpa_position(fitsfile *header, long nevents, float *x,
+ * unsigned char *channel)
+ *
+ * Description: Modify X position of photon events to account for an offset
+ * of the focal plane assembly (FPA)
+ *
+ * Arguments: fitsfile *header Pointer to the FITS header
+ * of the Intermediate Data File
+ * long npts Number of photons in the file
+ * float *x X positions for each photon event
+ * unsigned char *channel Assigned channel of each photon
+ *
+ * Calls: None
+ *
+ * Return: 0 on success
+ *
+ * History: 09/04/02 v1.1 wvd Based on cf_dpix by HSU
+ * 01/14/03 v1.3 wvd Rename cf_fpa_pos to cf_read_fpa_pos
+ * Move spectrograph optical parameters
+ * to separate calibration file.
+ * Abandon linear wavelength scale.
+ * 02/13/03 v1.4 wvd Write FPA shifts to file header.
+ * 04/07/03 v1.5 wvd Change keywords to FPADXLIF and
+ * FPADXSIC. Implement cf_verbose.
+ * Comment out cf_proc_check.
+ * Test channel[i] as int, not char.
+ * 05/20/03 v1.6 rdr Added call to cf_proc_check.
+ * 08/21/03 v1.7 wvd Change channel to unsigned char.
+ * 08/23/05 v1.8 wvd If either FPA position is out of
+ * bounds, issue a warning and set
+ * that FPA correction to zero.
+ * 08/01/05 v1.9 wvd Broaden FPA limits by +/- 1.
+ * 09/06/05 v1.10 wvd Correct for both X and Z motions
+ * of FPA.
+ * Delete call to cf_read_fpa_pos.c
+ * 12/02/05 v1.11 wvd Delete unused variables.
+ * 04/07/07 v1.12 wvd Clean up compiler warnings.
+ *
+ ****************************************************************************/
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include "calfuse.h"
+
+#define PIX1 2500 /* PIX1,2 are just inside the non-linear */
+#define PIX2 13500 /* regions of the detector */
+
+int cf_fpa_position(fitsfile *header, long nevents, float *x,
+ unsigned char *channel)
+{
+ char CF_PRGM_ID[] = "cf_fpa_position";
+ char CF_VER_NUM[] = "1.12";
+
+ int errflg=0, status=0, hdutype, hdunum;
+ int nwave; /* number of pixels in calibration file */
+ char aperture[FLEN_VALUE]; /* aperture keyword from FITS header */
+ char detector[FLEN_VALUE]; /* detector keyword from FITS header */
+ char wave_file[FLEN_FILENAME]; /* name of wavelength calibration file */
+ char spec_file[FLEN_FILENAME]; /* name of spectrograph calibration file */
+ long i;
+ /* Spectrograph optical parameters */
+ float alpha, alpha_lif, alpha_sic, sigma_lif, sigma_sic, diam;
+ float *wavelength; /* wavelengths read from calibration file */
+ float fpaxlifdata; /* LiF FPA X position in microns for spectrum */
+ float fpaxsicdata; /* SiC FPA X position in microns for spectrum */
+ float fpaxcal; /* FPA X position in microns for calibration file */
+ float dxfpa; /* fpax_data - fpaxcal */
+ float fpazlifdata; /* LiF FPA Z position in microns for spectrum */
+ float fpazsicdata; /* SiC FPA Z position in microns for spectrum */
+ float fpazcal; /* FPA Z position in microns for calibration file */
+ float dzfpa; /* fpaz_data - fpazcal */
+ float dpix, dpix_LiF, dpix_SiC; /* Spectral shift (in pixels)*/
+
+ double w1, w2; /* wavelengths at which to sample calibration */
+ double beta1,beta2; /* grating exit angle for w1, w2 */
+ double sinalpha; /* sin (spectrograph entrance angle) */
+ double cosalpha; /* cos (spectrograph entrance angle) */
+ double sigma; /* grating groove spacing in Angstroms */
+ double cosbeta; /* cos (mean grating exit angle) */
+ double pixscale; /* mean effective microns/pixel for det segment */
+ fitsfile *specfits, *wavefits;
+
+ /* Initialize error checking */
+ cf_error_init(CF_PRGM_ID, CF_VER_NUM, stderr);
+
+ /* Enter a timestamp into the log. */
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Begin Processing");
+
+ /* Check whether routine is appropriate for this data file. */
+ if ((errflg = cf_proc_check(header, CF_PRGM_ID))) return errflg;
+
+ /* Read keywords from data file header. */
+ FITS_read_key(header, TSTRING, "DETECTOR", detector, NULL, &status);
+ FITS_read_key(header, TSTRING, "APERTURE", aperture, NULL, &status);
+ FITS_read_key(header, TFLOAT, "FPASXPOS", &fpaxsicdata, NULL, &status);
+ FITS_read_key(header, TFLOAT, "FPALXPOS", &fpaxlifdata, NULL, &status);
+ FITS_read_key(header, TFLOAT, "FPASZPOS", &fpazsicdata, NULL, &status);
+ FITS_read_key(header, TFLOAT, "FPALZPOS", &fpazlifdata, NULL, &status);
+ FITS_read_key(header, TSTRING, "SPEC_CAL", spec_file, NULL, &status);
+ FITS_read_key(header, TSTRING, "WAVE_CAL", wave_file, NULL, &status);
+
+ /* Read spectrograph optical parameters from SPEC_CAL file. */
+ FITS_open_file(&specfits, cf_cal_file(spec_file), READONLY, &status);
+ FITS_read_key(specfits, TFLOAT, "ALPHALIF", &alpha_lif, NULL, &status);
+ FITS_read_key(specfits, TFLOAT, "ALPHASIC", &alpha_sic, NULL, &status);
+ FITS_read_key(specfits, TFLOAT, "SIGMALIF", &sigma_lif, NULL, &status);
+ FITS_read_key(specfits, TFLOAT, "SIGMASIC", &sigma_sic, NULL, &status);
+ FITS_read_key(specfits, TFLOAT, "DIAM", &diam, NULL, &status);
+ FITS_close_file(specfits, &status);
+
+ /* Determine the extension number (LiF) from aperture */
+ hdunum = 4; /* Default is LWRS */
+ if (!strcmp(aperture, "HIRS")) hdunum = 2;
+ if (!strcmp(aperture, "MDRS")) hdunum = 3;
+
+ /* Open wavelength calibration file */
+ FITS_open_file(&wavefits, cf_cal_file(wave_file), READONLY, &status);
+
+ /* Loop over the two apertures; first (i==0) LiF, then SiC. */
+ /* Determine shifts for LiF and SiC channels. */
+ for(i=0; i<2; i++) {
+
+ /* Move to appropriate HDU in WAVECAL file. */
+ hdunum += i*4;
+ FITS_movabs_hdu(wavefits, hdunum, &hdutype, &status);
+
+ /* Get FPA position for which WAVECAL was derived */
+ FITS_read_key(wavefits, TFLOAT, "FPACXPOS", &fpaxcal, NULL, &status);
+ FITS_read_key(wavefits, TFLOAT, "FPACZPOS", &fpazcal, NULL, &status);
+
+ /* Read the wavelength array from the WAVECAL file. */
+ nwave=cf_read_col(wavefits, TFLOAT,"WAVELENGTH", (void **) &wavelength);
+
+ /* Set LiF/SIC-dependent quantities */
+ if (i == 1) { /* SiC data */
+ dxfpa = fpaxsicdata - fpaxcal;
+ dzfpa = fpazsicdata - fpazcal;
+ sigma = sigma_sic;
+ alpha = alpha_sic;
+ } else { /* LiF data */
+ dxfpa = fpaxlifdata - fpaxcal;
+ dzfpa = fpazlifdata - fpazcal;
+ sigma = sigma_lif;
+ alpha = alpha_lif;
+ }
+ /*
+ * Compute mean pixel scale from points just inside the
+ * highly-nonlinear regions at edges of detectors */
+ w1 = wavelength[PIX1];
+ w2 = wavelength[PIX2];
+ sinalpha = sin (alpha * RADIAN);
+ cosalpha = cos (alpha * RADIAN);
+ beta1 = asin (w1/sigma - sinalpha);
+ beta2 = asin (w2/sigma - sinalpha);
+ cosbeta = cos ((beta1 + beta2)/2.); /* mean cosbeta for segment */
+ pixscale = diam * fabs(beta1 - beta2) * 1000. / (double)(PIX2-PIX1);
+
+ /* Compute shift of spectrum in pixels due to the FPA offset. */
+ if (i == 1) /* SiC data */
+ dpix = (dxfpa * cosalpha + dzfpa * sinalpha) / cosbeta / pixscale;
+
+ else /* LiF data */
+ dpix = (dxfpa * cosalpha - dzfpa * sinalpha) / cosbeta / pixscale;
+
+ /* For side 2, multiply the above expressions by -1. */
+ if (!strncmp(detector, "2", 1))
+ dpix *= -1;
+
+ /* Write info to log file */
+ if (i == 1) {
+ dpix_SiC = dpix;
+ cf_verbose(3, "FPAX data: %8.3f FPAX calib: %8.3f",
+ fpaxsicdata, fpaxcal);
+ cf_verbose(3, "FPAZ data: %8.3f FPAZ calib: %8.3f",
+ fpazsicdata, fpazcal);
+ cf_verbose(2, "SiC spectra to be shifted by %8.3f pixels", dpix_SiC);
+ }
+ else {
+ dpix_LiF = dpix;
+ cf_verbose(3, "FPAX data: %8.3f FPAX calib: %8.3f",
+ fpaxlifdata, fpaxcal);
+ cf_verbose(3, "FPAZ data: %8.3f FPAZ calib: %8.3f",
+ fpazlifdata, fpazcal);
+ cf_verbose(2, "LiF spectra to be shifted by %8.3f pixels", dpix_LiF);
+ }
+
+ } /* End of i loop */
+
+ /* Close the WAVECAL file */
+ FITS_close_file(wavefits, &status);
+
+ /* If tabulated FPA position is out of range, set the corresponding
+ dpix value to zero and issue a warning. */
+ if (fpaxlifdata < -1 || fpaxlifdata > 401) {
+ dpix_LiF = 0;
+ cf_if_warning("Keyword FPALXPOS is out of bounds. Setting FPADXLIF = 0.");
+ }
+ if (fpaxsicdata < -1 || fpaxsicdata > 401) {
+ dpix_SiC = 0;
+ cf_if_warning("Keyword FPASXPOS is out of bounds. Setting FPADXSIC = 0.");
+ }
+
+ /* Shift only photons with assigned apertures. */
+ for(i = 0; i < nevents; i++) {
+ switch(channel[i]) {
+ case 1: case 2: case 3: case 4:
+ x[i] += dpix_LiF;
+ break;
+ case 5: case 6: case 7: case 8:
+ x[i] += dpix_SiC;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Write shifts to IDF file header */
+ FITS_update_key(header, TFLOAT, "FPADXLIF", &dpix_LiF, NULL, &status);
+ FITS_update_key(header, TFLOAT, "FPADXSIC", &dpix_SiC, NULL, &status);
+
+ /* Update processing flags. */
+ cf_proc_update(header, CF_PRGM_ID, "COMPLETE");
+
+ /* Enter a timestamp into the log. */
+ cf_timestamp(CF_PRGM_ID, CF_VER_NUM, "Done processing");
+
+ return status;
+}