Index: /trunk/dbconfig/changes.txt
===================================================================
--- /trunk/dbconfig/changes.txt	(revision 42384)
+++ /trunk/dbconfig/changes.txt	(revision 42385)
@@ -2575,2 +2575,59 @@
       REFERENCES stackExternalCamera(ext_camera_id)
 ) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+-- EAM 2022.05.09 : adding fpcamRun, fpcamProcessedExp
+
+CREATE TABLE fpcamRun (
+    fpcam_id      BIGINT AUTO_INCREMENT,
+    cam_id        BIGINT,
+    chip_id       BIGINT,
+    state         VARCHAR(64),
+    workdir       VARCHAR(255),
+    workdir_state VARCHAR(64),
+    label         VARCHAR(64),
+    data_group    VARCHAR(64),
+    dist_group    VARCHAR(64),
+    reduction     VARCHAR(64),
+    dvodb         VARCHAR(255),
+    software_ver  VARCHAR(16),
+    note          VARCHAR(255),
+    PRIMARY KEY(fpcam_id),
+    KEY(cam_id),
+    KEY(chip_id),
+    KEY(state),
+    KEY(label),
+    INDEX(chip_id, cam_id),
+    FOREIGN KEY (cam_id) REFERENCES camRun(cam_id),
+    FOREIGN KEY (chip_id) REFERENCES chipRun(chip_id))
+ENGINE=innodb DEFAULT CHARSET=latin1;
+
+CREATE TABLE fpcamProcessedExp (
+    fpcam_id     BIGINT,
+    path_base    VARCHAR(255),
+
+    zpt_obs      FLOAT,
+    zpt_stdev    FLOAT,
+    zpt_lq       FLOAT,
+    zpt_uq       FLOAT,
+
+    dtime_script FLOAT,
+
+    hostname     VARCHAR(64),
+    n_stars      INT,
+    fault        SMALLINT NOT NULL,
+    epoch        TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+
+    software_ver VARCHAR(16),
+
+    deteff_obs   FLOAT,
+    deteff_err   FLOAT,
+    deteff_lq    FLOAT,
+    deteff_uq    FLOAT,
+
+    quality      SMALLINT
+
+    PRIMARY KEY(fpcam_id),
+    KEY(fault),
+    FOREIGN KEY (fpcam_id) REFERENCES fpcamRun(fpcam_id),
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
Index: /trunk/dbconfig/fpcam.md
===================================================================
--- /trunk/dbconfig/fpcam.md	(revision 42385)
+++ /trunk/dbconfig/fpcam.md	(revision 42385)
@@ -0,0 +1,47 @@
+# Forced Camera Photometry (fpcam)
+
+# For this stage, we are processing an exposure by applying the camera
+# stage astrometric calibration to force the photometry of sources
+# defined in the dvo database (dvodb) on the processed chip images.
+# For a given exposure, it should not be necessary to select the chip
+# analysis which is connected to the desired camera analysis
+
+fpcamRun METADATA
+    fpcam_id      S64       0       # Primary Key AUTO_INCREMENT
+    chip_id       S64       0       # Key INDEX(cam_id, chip_id) fkey(chip_id) ref chipRun(chip_id)
+    cam_id        S64       0       # Key INDEX(cam_id, chip_id) fkey(cam_id)  ref camRun(cam_id)
+    state         STR       64      # key
+    workdir       STR       255 
+    workdir_state STR       64
+    label         STR       64      # key
+    data_group    STR       64      # key
+    dist_group    STR       64
+    reduction     STR       64
+    dvodb         STR       255
+    note          STR       255
+END
+
+fpcamProcessedExp METADATA
+    fpcam_id       S64      0       # Primary Key fkey(fpcam_id) ref fpcamRun(fpcam_id)
+    path_base      STR      255
+
+    zpt_obs        F32      0.0
+    zpt_stdev      F32      0.0
+    zpt_lq         F32      0.0
+    zpt_uq         F32      0.0
+
+    dtime_script   F32      0.0
+
+    hostname       STR      64
+    n_stars        S32      0
+    fault          S16      0       # Key NOT NULL
+    epoch          UTC      0001-01-01T00:00:00Z
+
+    software_ver   STR      16
+    deteff_obs     F32      0
+    deteff_err     F32      0
+    deteff_lq      F32      0
+    deteff_uq      F32      0
+
+    quality        S16      0
+END
Index: /trunk/dbconfig/ipp.m4
===================================================================
--- /trunk/dbconfig/ipp.m4	(revision 42384)
+++ /trunk/dbconfig/ipp.m4	(revision 42385)
@@ -42,2 +42,3 @@
 include(ff.md)
 include(remote.md)
+include(fpcam.md)
Index: /trunk/extsrc/gpcsw/gpcsrc/Make.Common
===================================================================
--- /trunk/extsrc/gpcsw/gpcsrc/Make.Common	(revision 42384)
+++ /trunk/extsrc/gpcsw/gpcsrc/Make.Common	(revision 42385)
@@ -163,5 +163,5 @@
 CCWARN	 = -Wall -Wstrict-prototypes # -Wshadow
 CFLAGS   = $(CCDEBUG) $(EXTRA_CFLAGS) $(CCWARN) $(CCDEFS) $(CCINCS) $(CCHACKS)
-LDFLAGS  = $(CCDEBUG) $(EXTRA_CFLAGS) $(CCLIBS)
+LDFLAGS  = $(CCDEBUG) $(EXTRA_CFLAGS) $(CCLIBS) -Wl,--allow-multiple-definition
 CXXFLAGS = $(subst -Wstrict-prototypes,,$(CFLAGS))
 ARFLAGS  = -rc
Index: unk/extsrc/gpcsw/gpcsrc/fits/libfh/fh_registry.asm
===================================================================
--- /trunk/extsrc/gpcsw/gpcsrc/fits/libfh/fh_registry.asm	(revision 42384)
+++ 	(revision )
@@ -1,786 +1,0 @@
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 0.0 E \"\ARG\" \"Standard FITS\""
-    ENDM
-DETCOM_N MACRO ARG
-    COBJ "detcom:dheader 0.0 N \"\ARG\" \"\""
-    ENDM
-DETCOM_X MACRO ARG
-    COBJ "detcom:dheader 1.0 X \"\ARG\" \"Bits per pixel\""
-    ENDM
-DETCOM_S MACRO ARG
-    COBJ "detcom:dheader 2.0 S \"\ARG\" \"Number of axes\""
-    ENDM
-DETCOM_1 MACRO ARG
-    COBJ "detcom:dheader 2.1 1 \"\ARG\" \"Number of pixel columns\""
-    ENDM
-DETCOM_2 MACRO ARG
-    COBJ "detcom:dheader 2.2 2 \"\ARG\" \"Number of pixel rows\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 2.3 3 \"\ARG\" \"Number of stacked frames (cube)\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 3.0 D \"\ARG\" \"File contains extensions\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 3.1 D \"\ARG\" \"Number of extensions\""
-    ENDM
-DETCOM_S MACRO ARG
-    COBJ "detcom:dheader 4.0 S \"\ARG\" \"File contains random groups records\""
-    ENDM
-DETCOM_T MACRO ARG
-    COBJ "detcom:dheader 5.0 T \"\ARG\" \"Random parameters before each array in a group\""
-    ENDM
-DETCOM_T MACRO ARG
-    COBJ "detcom:dheader 6.0 T \"\ARG\" \"Number of random groups\""
-    ENDM
-DETCOM_S MACRO ARG
-    COBJ "detcom:dheader 7.0000 S \"\ARG\" \"Number of fields in a row\""
-    ENDM
-DETCOM_1 MACRO ARG
-    COBJ "detcom:dheader 7.0011 1 \"\ARG\" \"Table format for field 1\""
-    ENDM
-DETCOM_1 MACRO ARG
-    COBJ "detcom:dheader 7.0012 1 \"\ARG\" \"Start Column for field 1\""
-    ENDM
-DETCOM_2 MACRO ARG
-    COBJ "detcom:dheader 7.0021 2 \"\ARG\" \"Table format for field 2\""
-    ENDM
-DETCOM_2 MACRO ARG
-    COBJ "detcom:dheader 7.0022 2 \"\ARG\" \"Start Column for field 2\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 7.0031 3 \"\ARG\" \"Table format for field 3\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 7.0032 3 \"\ARG\" \"Start Column for field 3\""
-    ENDM
-DETCOM_4 MACRO ARG
-    COBJ "detcom:dheader 7.0041 4 \"\ARG\" \"Table format for field 4\""
-    ENDM
-DETCOM_4 MACRO ARG
-    COBJ "detcom:dheader 7.0042 4 \"\ARG\" \"Start Column for field 4\""
-    ENDM
-DETCOM_5 MACRO ARG
-    COBJ "detcom:dheader 7.0051 5 \"\ARG\" \"Table format for field 5\""
-    ENDM
-DETCOM_5 MACRO ARG
-    COBJ "detcom:dheader 7.0052 5 \"\ARG\" \"Start Column for field 5\""
-    ENDM
-DETCOM_S MACRO ARG
-    COBJ "detcom:dheader 1.0 S \"\ARG\" \"\""
-    ENDM
-DETCOM_Q MACRO ARG
-    COBJ "detcom:dheader 2.0 Q \"\ARG\" \"\""
-    ENDM
-DETCOM_T MACRO ARG
-    COBJ "detcom:dheader 3.0 T \"\ARG\" \"\""
-    ENDM
-DETCOM_R MACRO ARG
-    COBJ "detcom:dheader 4.0 R \"\ARG\" \"\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 5.0 E \"\ARG\" \"\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 6.0 D \"\ARG\" \"\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 1.00 E \"\ARG\" \"Base filename at acquisition\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 1.01 E \"\ARG\" \"Original directory name at acquisition\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 1.10 E \"\ARG\" \"Extension name\""
-    ENDM
-DETCOM_R MACRO ARG
-    COBJ "detcom:dheader 1.20 R \"\ARG\" \"Extension version\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 4.00 E \"\ARG\" \"UTC Date of file creation\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 4.10 E \"\ARG\" \"Local time in Hawaii\""
-    ENDM
-DETCOM_V MACRO ARG
-    COBJ "detcom:dheader 7.00 V \"\ARG\" \"Image creation software version\""
-    ENDM
-DETCOM_R MACRO ARG
-    COBJ "detcom:dheader 1.0 R \"\ARG\" \"Science Detector\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 2.0 E \"\ARG\" \"Instrument Name\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 2.1 E \"\ARG\" \"Instrument Mode\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 2.0 E \"\ARG\" \"Total data pixels in full mosaic\""
-    ENDM
-DETCOM_R MACRO ARG
-    COBJ "detcom:dheader 3.0 R \"\ARG\" \"\""
-    ENDM
-DETCOM_M MACRO ARG
-    COBJ "detcom:dheader 5.0 M \"\ARG\" \"Binning factors\""
-    ENDM
-DETCOM_1 MACRO ARG
-    COBJ "detcom:dheader 5.1 1 \"\ARG\" \"Binning factor along first axis\""
-    ENDM
-DETCOM_2 MACRO ARG
-    COBJ "detcom:dheader 5.2 2 \"\ARG\" \"Binning factor along second axis\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 0.0 3 \"\ARG\" \"Pixel size for both axes (microns)\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 1.1 3 \"\ARG\" \"Pixel size for axis 1 (microns)\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 1.2 3 \"\ARG\" \"Pixel size for axis 2 (microns)\""
-    ENDM
-DETCOM_4 MACRO ARG
-    COBJ "detcom:dheader 2.1 4 \"\ARG\" \"Pixel scale for axis 1 (arcsec/pixel)\""
-    ENDM
-DETCOM_4 MACRO ARG
-    COBJ "detcom:dheader 2.2 4 \"\ARG\" \"Pixel scale for axis 2 (arcsec/pixel)\""
-    ENDM
-DETCOM_T MACRO ARG
-    COBJ "detcom:dheader 0.0 T \"\ARG\" \"List of amplifiers for this image\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 1.0 E \"\ARG\" \"Amplifier name\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 0.0 E \"\ARG\" \"Detector imaging area size\""
-    ENDM
-DETCOM_C MACRO ARG
-    COBJ "detcom:dheader 0.1 C \"\ARG\" \"Mosaic area of the detector\""
-    ENDM
-DETCOM_A MACRO ARG
-    COBJ "detcom:dheader 0.11 A \"\ARG\" \"Mosaic area of the detector from Amp A\""
-    ENDM
-DETCOM_B MACRO ARG
-    COBJ "detcom:dheader 0.12 B \"\ARG\" \"Mosaic area of the detector from Amp B\""
-    ENDM
-DETCOM_C MACRO ARG
-    COBJ "detcom:dheader 0.13 C \"\ARG\" \"Mosaic area of the detector from Amp C\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 0.14 D \"\ARG\" \"Mosaic area of the detector from Amp D\""
-    ENDM
-DETCOM_C MACRO ARG
-    COBJ "detcom:dheader 0.2 C \"\ARG\" \"Imaging area of the detector\""
-    ENDM
-DETCOM_C MACRO ARG
-    COBJ "detcom:dheader 0.3 C \"\ARG\" \"Overscan (bias) area of the detector\""
-    ENDM
-DETCOM_A MACRO ARG
-    COBJ "detcom:dheader 1.11 A \"\ARG\" \"Section from Amp A (non-contig. bias excluded)\""
-    ENDM
-DETCOM_B MACRO ARG
-    COBJ "detcom:dheader 1.12 B \"\ARG\" \"Section from Amp B (non-contig. bias excluded)\""
-    ENDM
-DETCOM_C MACRO ARG
-    COBJ "detcom:dheader 1.13 C \"\ARG\" \"Section from Amp C (non-contig. bias excluded)\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 1.14 D \"\ARG\" \"Section from Amp D (non-contig. bias excluded)\""
-    ENDM
-DETCOM_A MACRO ARG
-    COBJ "detcom:dheader 1.21 A \"\ARG\" \"Overscan (bias) area from Amp A\""
-    ENDM
-DETCOM_B MACRO ARG
-    COBJ "detcom:dheader 1.22 B \"\ARG\" \"Overscan (bias) area from Amp B\""
-    ENDM
-DETCOM_C MACRO ARG
-    COBJ "detcom:dheader 1.23 C \"\ARG\" \"Overscan (bias) area from Amp C\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 1.24 D \"\ARG\" \"Overscan (bias) area from Amp D\""
-    ENDM
-DETCOM_A MACRO ARG
-    COBJ "detcom:dheader 1.31 A \"\ARG\" \"Section in full CCD for DSECA\""
-    ENDM
-DETCOM_B MACRO ARG
-    COBJ "detcom:dheader 1.32 B \"\ARG\" \"Section in full CCD for DSECB\""
-    ENDM
-DETCOM_C MACRO ARG
-    COBJ "detcom:dheader 1.33 C \"\ARG\" \"Section in full CCD for DSECC\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 1.34 D \"\ARG\" \"Section in full CCD for DSECD\""
-    ENDM
-DETCOM_A MACRO ARG
-    COBJ "detcom:dheader 1.41 A \"\ARG\" \"Imaging area from Amp A\""
-    ENDM
-DETCOM_B MACRO ARG
-    COBJ "detcom:dheader 1.42 B \"\ARG\" \"Imaging area from Amp B\""
-    ENDM
-DETCOM_C MACRO ARG
-    COBJ "detcom:dheader 1.43 C \"\ARG\" \"Imaging area from Amp C\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 1.44 D \"\ARG\" \"Imaging area from Amp D\""
-    ENDM
-DETCOM_A MACRO ARG
-    COBJ "detcom:dheader 1.51 A \"\ARG\" \"Trim section for Amp A\""
-    ENDM
-DETCOM_B MACRO ARG
-    COBJ "detcom:dheader 1.52 B \"\ARG\" \"Trim section for Amp B\""
-    ENDM
-DETCOM_C MACRO ARG
-    COBJ "detcom:dheader 1.53 C \"\ARG\" \"Trim section for Amp C\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 1.54 D \"\ARG\" \"Trim section for Amp D\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 0.1 E \"\ARG\" \"Name of the CCD (manufacturer reference)\""
-    ENDM
-DETCOM_K MACRO ARG
-    COBJ "detcom:dheader 0.2 K \"\ARG\" \"Nickname of the CCD\""
-    ENDM
-DETCOM_N MACRO ARG
-    COBJ "detcom:dheader 2.0 N \"\ARG\" \"Maximum linearity value (ADU)\""
-    ENDM
-DETCOM_A MACRO ARG
-    COBJ "detcom:dheader 2.01 A \"\ARG\" \"Maximum linearity value for Amp A (ADU)\""
-    ENDM
-DETCOM_B MACRO ARG
-    COBJ "detcom:dheader 2.02 B \"\ARG\" \"Maximum linearity value for Amp B (ADU)\""
-    ENDM
-DETCOM_C MACRO ARG
-    COBJ "detcom:dheader 2.03 C \"\ARG\" \"Maximum linearity value for Amp C (ADU)\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 2.04 D \"\ARG\" \"Maximum linearity value for Amp D (ADU)\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 2.1 E \"\ARG\" \"Saturation value (ADU)\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 5.0 3 \"\ARG\" \"Amplifier gain (electrons/ADU)\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 5.01 3 \"\ARG\" \"Amp A gain (electrons/ADU)\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 5.02 3 \"\ARG\" \"Amp B gain (electrons/ADU)\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 5.03 3 \"\ARG\" \"Amp C gain (electrons/ADU)\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 5.04 3 \"\ARG\" \"Amp D gain (electrons/ADU)\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 6.0 3 \"\ARG\" \"Read noise (electrons)\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 6.01 3 \"\ARG\" \"Amp A read noise (electrons)\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 6.02 3 \"\ARG\" \"Amp B read noise (electrons)\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 6.03 3 \"\ARG\" \"Amp C read noise (electrons)\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 6.04 3 \"\ARG\" \"Amp D read noise (electrons)\""
-    ENDM
-DETCOM_5 MACRO ARG
-    COBJ "detcom:dheader 7.0 5 \"\ARG\" \"Dark current (ADU/pixel/second)\""
-    ENDM
-DETCOM_5 MACRO ARG
-    COBJ "detcom:dheader 7.1 5 \"\ARG\" \"Dark current (e-/pixel/hour)\""
-    ENDM
-DETCOM_S MACRO ARG
-    COBJ "detcom:dheader 8.0 S \"\ARG\" \"QE%@wavelength in nm\""
-    ENDM
-DETCOM_V MACRO ARG
-    COBJ "detcom:dheader 0.0 V \"\ARG\" \"Controller software DSPID and SERNO versions\""
-    ENDM
-DETCOM_T MACRO ARG
-    COBJ "detcom:dheader 0.0 T \"\ARG\" \"Detector status\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 0.0 3 \"\ARG\" \"Detector temperature\""
-    ENDM
-DETCOM_P MACRO ARG
-    COBJ "detcom:dheader 1.1 P \"\ARG\" \"\""
-    ENDM
-DETCOM_N MACRO ARG
-    COBJ "detcom:dheader 1.2 N \"\ARG\" \"Canada-France-Hawaii Telescope\""
-    ENDM
-DETCOM_T MACRO ARG
-    COBJ "detcom:dheader 3.0 T \"\ARG\" \"Telescope Control System status\""
-    ENDM
-DETCOM_S MACRO ARG
-    COBJ "detcom:dheader 0.0 S \"\ARG\" \"Time System for DATExxxx\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 2.0 E \"\ARG\" \"Time at start of observation (UT)\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 4.0 E \"\ARG\" \"Sidereal time at start of observation\""
-    ENDM
-DETCOM_H MACRO ARG
-    COBJ "detcom:dheader 1.0 H \"\ARG\" \"Equinox of coordinates\""
-    ENDM
-DETCOM_X MACRO ARG
-    COBJ "detcom:dheader 1.1 X \"\ARG\" \"Equinox of coordinates\""
-    ENDM
-DETCOM_S MACRO ARG
-    COBJ "detcom:dheader 2.0 S \"\ARG\" \"Coordinate system for equinox (FK4/FK5/GAPPT)\""
-    ENDM
-DETCOM_A MACRO ARG
-    COBJ "detcom:dheader 2.1 A \"\ARG\" \"Object right ascension\""
-    ENDM
-DETCOM_C MACRO ARG
-    COBJ "detcom:dheader 2.2 C \"\ARG\" \"Object declination\""
-    ENDM
-DETCOM_1 MACRO ARG
-    COBJ "detcom:dheader 5.211 1 \"\ARG\" \"WCS Coordinate type\""
-    ENDM
-DETCOM_2 MACRO ARG
-    COBJ "detcom:dheader 5.212 2 \"\ARG\" \"WCS Coordinate type\""
-    ENDM
-DETCOM_6 MACRO ARG
-    COBJ "detcom:dheader 5.411 6 \"\ARG\" \"WCS Coordinate scale matrix\""
-    ENDM
-DETCOM_6 MACRO ARG
-    COBJ "detcom:dheader 5.412 6 \"\ARG\" \"WCS Coordinate scale matrix\""
-    ENDM
-DETCOM_6 MACRO ARG
-    COBJ "detcom:dheader 5.421 6 \"\ARG\" \"WCS Coordinate scale matrix\""
-    ENDM
-DETCOM_6 MACRO ARG
-    COBJ "detcom:dheader 5.422 6 \"\ARG\" \"WCS Coordinate scale matrix\""
-    ENDM
-DETCOM_R MACRO ARG
-    COBJ "detcom:dheader 0.0 R \"\ARG\" \"TCS Number of guiders\""
-    ENDM
-DETCOM_R MACRO ARG
-    COBJ "detcom:dheader 0.01 R \"\ARG\" \"TCS number of guide stars/probes in use\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 0.1 E \"\ARG\" \"TCS guider name\""
-    ENDM
-DETCOM_N MACRO ARG
-    COBJ "detcom:dheader 0.21 N \"\ARG\" \"TCS guider equinox\""
-    ENDM
-DETCOM_C MACRO ARG
-    COBJ "detcom:dheader 0.22 C \"\ARG\" \"TCS guider system for equinox\""
-    ENDM
-DETCOM_A MACRO ARG
-    COBJ "detcom:dheader 0.23 A \"\ARG\" \"TCS guider right ascension\""
-    ENDM
-DETCOM_C MACRO ARG
-    COBJ "detcom:dheader 0.24 C \"\ARG\" \"TCS guider declination\""
-    ENDM
-DETCOM_N MACRO ARG
-    COBJ "detcom:dheader 0.3 N \"\ARG\" \"TCS guider object name\""
-    ENDM
-DETCOM_X MACRO ARG
-    COBJ "detcom:dheader 0.6 X \"\ARG\" \"TCS guider flux\""
-    ENDM
-DETCOM_X MACRO ARG
-    COBJ "detcom:dheader 0.8 X \"\ARG\" \"TCS total sky flux\""
-    ENDM
-DETCOM_1 MACRO ARG
-    COBJ "detcom:dheader 1.1 1 \"\ARG\" \"TCS guider #1 identification\""
-    ENDM
-DETCOM_1 MACRO ARG
-    COBJ "detcom:dheader 1.21 1 \"\ARG\" \"TCS guider #1 equinox\""
-    ENDM
-DETCOM_1 MACRO ARG
-    COBJ "detcom:dheader 1.22 1 \"\ARG\" \"TCS guider #1 system for equinox\""
-    ENDM
-DETCOM_1 MACRO ARG
-    COBJ "detcom:dheader 1.23 1 \"\ARG\" \"TCS guider #1 right ascension\""
-    ENDM
-DETCOM_1 MACRO ARG
-    COBJ "detcom:dheader 1.24 1 \"\ARG\" \"TCS guider #1 declination\""
-    ENDM
-DETCOM_1 MACRO ARG
-    COBJ "detcom:dheader 1.3 1 \"\ARG\" \"TCS guider #1 object name\""
-    ENDM
-DETCOM_1 MACRO ARG
-    COBJ "detcom:dheader 1.6 1 \"\ARG\" \"TCS guider #1 flux\""
-    ENDM
-DETCOM_2 MACRO ARG
-    COBJ "detcom:dheader 2.1 2 \"\ARG\" \"TCS guider #2 identification\""
-    ENDM
-DETCOM_2 MACRO ARG
-    COBJ "detcom:dheader 2.21 2 \"\ARG\" \"TCS guider #2 equinox\""
-    ENDM
-DETCOM_2 MACRO ARG
-    COBJ "detcom:dheader 2.22 2 \"\ARG\" \"TCS guider #2 system for equinox\""
-    ENDM
-DETCOM_2 MACRO ARG
-    COBJ "detcom:dheader 2.23 2 \"\ARG\" \"TCS guider #2 right ascension\""
-    ENDM
-DETCOM_2 MACRO ARG
-    COBJ "detcom:dheader 2.24 2 \"\ARG\" \"TCS guider #2 declination\""
-    ENDM
-DETCOM_2 MACRO ARG
-    COBJ "detcom:dheader 2.3 2 \"\ARG\" \"TCS guider #2 object name\""
-    ENDM
-DETCOM_2 MACRO ARG
-    COBJ "detcom:dheader 2.6 2 \"\ARG\" \"TCS guider #2 flux\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 3.1 3 \"\ARG\" \"TCS guider #3 identification\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 3.21 3 \"\ARG\" \"TCS guider #3 equinox\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 3.22 3 \"\ARG\" \"TCS guider #3 system for equinox\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 3.23 3 \"\ARG\" \"TCS guider #3 right ascension\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 3.24 3 \"\ARG\" \"TCS guider #3 declination\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 3.3 3 \"\ARG\" \"TCS guider #3 object name\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 3.6 3 \"\ARG\" \"TCS guider #3 flux\""
-    ENDM
-DETCOM_4 MACRO ARG
-    COBJ "detcom:dheader 4.1 4 \"\ARG\" \"TCS guider #4 identification\""
-    ENDM
-DETCOM_4 MACRO ARG
-    COBJ "detcom:dheader 4.21 4 \"\ARG\" \"TCS guider #4 equinox\""
-    ENDM
-DETCOM_4 MACRO ARG
-    COBJ "detcom:dheader 4.22 4 \"\ARG\" \"TCS guider #4 system for equinox\""
-    ENDM
-DETCOM_4 MACRO ARG
-    COBJ "detcom:dheader 4.23 4 \"\ARG\" \"TCS guider #4 right ascension\""
-    ENDM
-DETCOM_4 MACRO ARG
-    COBJ "detcom:dheader 4.24 4 \"\ARG\" \"TCS guider #4 declination\""
-    ENDM
-DETCOM_4 MACRO ARG
-    COBJ "detcom:dheader 4.3 4 \"\ARG\" \"TCS guider #4 object name\""
-    ENDM
-DETCOM_4 MACRO ARG
-    COBJ "detcom:dheader 4.6 4 \"\ARG\" \"TCS guider #4 flux\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 0.0 D \"\ARG\" \"Telescope focus in use\""
-    ENDM
-DETCOM_F MACRO ARG
-    COBJ "detcom:dheader 0.1 F \"\ARG\" \"Telescope focus in use\""
-    ENDM
-DETCOM_S MACRO ARG
-    COBJ "detcom:dheader 1.0 S \"\ARG\" \"Telescope focus encoder readout\""
-    ENDM
-DETCOM_S MACRO ARG
-    COBJ "detcom:dheader 1.1 S \"\ARG\" \"Telescope focus encoder readout\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 0.4 E \"\ARG\" \"ISU control state (Off/Only/TCS/Full/Frozen)\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 0.4 E \"\ARG\" \"FSA control state (Off/On/Paused)\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 0.5 E \"\ARG\" \"FSA number of actual moves in last 10 minutes\""
-    ENDM
-DETCOM_C MACRO ARG
-    COBJ "detcom:dheader 0.11 C \"\ARG\" \"TCS GPS read out in BCD\""
-    ENDM
-DETCOM_S MACRO ARG
-    COBJ "detcom:dheader 0.13 S \"\ARG\" \"TCS RBUSS clock time\""
-    ENDM
-DETCOM_S MACRO ARG
-    COBJ "detcom:dheader 0.14 S \"\ARG\" \"TCS EPICS clock time\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 0.15 E \"\ARG\" \"TCS acquisition mode - T/O/G/g for t/o/g coords\""
-    ENDM
-DETCOM_A MACRO ARG
-    COBJ "detcom:dheader 0.51 A \"\ARG\" \"TCS hour angle encoder bits reading\""
-    ENDM
-DETCOM_C MACRO ARG
-    COBJ "detcom:dheader 0.52 C \"\ARG\" \"TCS declination encoder bits reading\""
-    ENDM
-DETCOM_P MACRO ARG
-    COBJ "detcom:dheader 1.0 P \"\ARG\" \"AOB closed loop Open/Closed\""
-    ENDM
-DETCOM_S MACRO ARG
-    COBJ "detcom:dheader 3.0 S \"\ARG\" \"Loop type \"Nested\"/\"Tip/Tilt\"/\"Single\"\""
-    ENDM
-DETCOM_T MACRO ARG
-    COBJ "detcom:dheader 5.0 T \"\ARG\" \"Optimized loop control True/False\""
-    ENDM
-DETCOM_T MACRO ARG
-    COBJ "detcom:dheader 6.0 T \"\ARG\" \"WFS optical gain\""
-    ENDM
-DETCOM_T MACRO ARG
-    COBJ "detcom:dheader 2.0 T \"\ARG\" \"Total flux count on WFS\""
-    ENDM
-DETCOM_S MACRO ARG
-    COBJ "detcom:dheader 1.0 S \"\ARG\" \"AOB ADC position In/Out\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 4.0 D \"\ARG\" \"Beam splitter ID\""
-    ENDM
-DETCOM_P MACRO ARG
-    COBJ "detcom:dheader 5.0 P \"\ARG\" \"Beam splitter description\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 6.0 E \"\ARG\" \"AOB mirror slide \"F/20\"/\"F/8\"\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 7.0 D \"\ARG\" \"WFS ND filter position\""
-    ENDM
-DETCOM_N MACRO ARG
-    COBJ "detcom:dheader 0.0 N \"\ARG\" \"flatfield lamp status ON/OFF\""
-    ENDM
-DETCOM_P MACRO ARG
-    COBJ "detcom:dheader 1.0 P \"\ARG\" \"flatfield lamp intensity\""
-    ENDM
-DETCOM_N MACRO ARG
-    COBJ "detcom:dheader 0.0 N \"\ARG\" \"comparison lamp 0 status ON/OFF\""
-    ENDM
-DETCOM_0 MACRO ARG
-    COBJ "detcom:dheader 0.1 0 \"\ARG\" \"comparison lamp 0 description\""
-    ENDM
-DETCOM_N MACRO ARG
-    COBJ "detcom:dheader 1.0 N \"\ARG\" \"comparison lamp 1 status ON/OFF\""
-    ENDM
-DETCOM_1 MACRO ARG
-    COBJ "detcom:dheader 1.1 1 \"\ARG\" \"comparison lamp 1 description\""
-    ENDM
-DETCOM_N MACRO ARG
-    COBJ "detcom:dheader 2.0 N \"\ARG\" \"comparison lamp 2 status ON/OFF\""
-    ENDM
-DETCOM_2 MACRO ARG
-    COBJ "detcom:dheader 2.1 2 \"\ARG\" \"comparison lamp 2 description\""
-    ENDM
-DETCOM_N MACRO ARG
-    COBJ "detcom:dheader 3.0 N \"\ARG\" \"comparison lamp 3 status ON/OFF\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 3.1 3 \"\ARG\" \"comparison lamp 3 description\""
-    ENDM
-DETCOM_0 MACRO ARG
-    COBJ "detcom:dheader 0.0 0 \"\ARG\" \"lamp 0 ON/OFF\""
-    ENDM
-DETCOM_1 MACRO ARG
-    COBJ "detcom:dheader 1.0 1 \"\ARG\" \"lamp 1 ON/OFF\""
-    ENDM
-DETCOM_2 MACRO ARG
-    COBJ "detcom:dheader 2.0 2 \"\ARG\" \"lamp 2 ON/OFF\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 3.0 3 \"\ARG\" \"lamp 3 ON/OFF\""
-    ENDM
-DETCOM_4 MACRO ARG
-    COBJ "detcom:dheader 4.0 4 \"\ARG\" \"lamp 4 ON/OFF\""
-    ENDM
-DETCOM_5 MACRO ARG
-    COBJ "detcom:dheader 5.0 5 \"\ARG\" \"lamp 5 ON/OFF\""
-    ENDM
-DETCOM_6 MACRO ARG
-    COBJ "detcom:dheader 6.0 6 \"\ARG\" \"lamp 6 ON/OFF\""
-    ENDM
-DETCOM_7 MACRO ARG
-    COBJ "detcom:dheader 7.0 7 \"\ARG\" \"lamp 7 ON/OFF\""
-    ENDM
-DETCOM_8 MACRO ARG
-    COBJ "detcom:dheader 8.0 8 \"\ARG\" \"lamp 8 ON/OFF\""
-    ENDM
-DETCOM_9 MACRO ARG
-    COBJ "detcom:dheader 9.0 9 \"\ARG\" \"lamp 9 ON/OFF\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 0.1 D \"\ARG\" \"wheel position\""
-    ENDM
-DETCOM_R MACRO ARG
-    COBJ "detcom:dheader 0.2 R \"\ARG\" \"description of filter\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 0.3 3 \"\ARG\" \"filter bandwidth\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 0.4 3 \"\ARG\" \"filter wavelength\""
-    ENDM
-DETCOM_5 MACRO ARG
-    COBJ "detcom:dheader 0.5 5 \"\ARG\" \"lower bound of filter (units/%?)\""
-    ENDM
-DETCOM_5 MACRO ARG
-    COBJ "detcom:dheader 0.6 5 \"\ARG\" \"upper bound of filter (units/%?)\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 0.7 D \"\ARG\" \"filter drawer number\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 0.1 D \"\ARG\" \"'wheel' A position\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 0.2 E \"\ARG\" \"description of filter\""
-    ENDM
-DETCOM_4 MACRO ARG
-    COBJ "detcom:dheader 0.5 4 \"\ARG\" \"lower bound of filter A (units/%?)\""
-    ENDM
-DETCOM_4 MACRO ARG
-    COBJ "detcom:dheader 0.6 4 \"\ARG\" \"upper bound of filter A (units/%?)\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 0.1 D \"\ARG\" \"'wheel' B position\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 0.2 E \"\ARG\" \"description of filter\""
-    ENDM
-DETCOM_4 MACRO ARG
-    COBJ "detcom:dheader 0.5 4 \"\ARG\" \"lower bound of filter B (units/%?)\""
-    ENDM
-DETCOM_4 MACRO ARG
-    COBJ "detcom:dheader 0.6 4 \"\ARG\" \"upper bound of filter B (units/%?)\""
-    ENDM
-DETCOM_7 MACRO ARG
-    COBJ "detcom:dheader 1.0 7 \"\ARG\" \"internal instrument focus value\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 1.0 D \"\ARG\" \"grism position\""
-    ENDM
-DETCOM_M MACRO ARG
-    COBJ "detcom:dheader 2.0 M \"\ARG\" \"grism description\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 3.0 D \"\ARG\" \"grism drawer number\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 1.0 D \"\ARG\" \"mask position\""
-    ENDM
-DETCOM_K MACRO ARG
-    COBJ "detcom:dheader 2.0 K \"\ARG\" \"mask description\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 3.0 D \"\ARG\" \"mask slider number\""
-    ENDM
-DETCOM_L MACRO ARG
-    COBJ "detcom:dheader 1.0 L \"\ARG\" \"grating description\""
-    ENDM
-DETCOM_S MACRO ARG
-    COBJ "detcom:dheader 2.0 S \"\ARG\" \"dispersion axis (1 or 2)\""
-    ENDM
-DETCOM_6 MACRO ARG
-    COBJ "detcom:dheader 3.0 6 \"\ARG\" \"grating angle in degrees\""
-    ENDM
-DETCOM_0 MACRO ARG
-    COBJ "detcom:dheader 4.0 0 \"\ARG\" \"central wavelength in angstroms\""
-    ENDM
-DETCOM_R MACRO ARG
-    COBJ "detcom:dheader 5.0 R \"\ARG\" \"spectral order\""
-    ENDM
-DETCOM_5 MACRO ARG
-    COBJ "detcom:dheader 6.0 5 \"\ARG\" \"grating setup constant in degrees\""
-    ENDM
-DETCOM_7 MACRO ARG
-    COBJ "detcom:dheader 7.0 7 \"\ARG\" \"setup const in degrees (opening angle / 2)\""
-    ENDM
-DETCOM_5 MACRO ARG
-    COBJ "detcom:dheader 8.0 5 \"\ARG\" \"rel.angle between prisms in degrees\""
-    ENDM
-DETCOM_R MACRO ARG
-    COBJ "detcom:dheader 0.0 R \"\ARG\" \"image slicer in place\""
-    ENDM
-DETCOM_A MACRO ARG
-    COBJ "detcom:dheader 1.0 A \"\ARG\" \"hartman mask 1a position OPEN/CLOSED\""
-    ENDM
-DETCOM_B MACRO ARG
-    COBJ "detcom:dheader 1.1 B \"\ARG\" \"hartman mask 1b position OPEN/CLOSED\""
-    ENDM
-DETCOM_2 MACRO ARG
-    COBJ "detcom:dheader 2.0 2 \"\ARG\" \"hartman mask 2 position OPEN/CLOSED\""
-    ENDM
-DETCOM_3 MACRO ARG
-    COBJ "detcom:dheader 3.0 3 \"\ARG\" \"hartman mask 3 position OPEN/CLOSED\""
-    ENDM
-DETCOM_4 MACRO ARG
-    COBJ "detcom:dheader 4.0 4 \"\ARG\" \"hartman mask 4 position OPEN/CLOSED\""
-    ENDM
-DETCOM_N MACRO ARG
-    COBJ "detcom:dheader 0.0 N \"\ARG\" \"coude train color UV/RED/CAFE\""
-    ENDM
-DETCOM_R MACRO ARG
-    COBJ "detcom:dheader 0.0 R \"\ARG\" \"exposure meter filter description\""
-    ENDM
-DETCOM_S MACRO ARG
-    COBJ "detcom:dheader 1.0 S \"\ARG\" \"exposure meter counts at end\""
-    ENDM
-DETCOM_M MACRO ARG
-    COBJ "detcom:dheader 2.0 M \"\ARG\" \"mid-exposure time (seconds)\""
-    ENDM
-DETCOM_E MACRO ARG
-    COBJ "detcom:dheader 0.0 E \"\ARG\" \"CAFE is being used Null/INUSE\""
-    ENDM
-DETCOM_T MACRO ARG
-    COBJ "detcom:dheader 1.0 T \"\ARG\" \"fabry perot etalon description\""
-    ENDM
-DETCOM_N MACRO ARG
-    COBJ "detcom:dheader 3.0 N \"\ARG\" \"number of channels per scan\""
-    ENDM
-DETCOM_N MACRO ARG
-    COBJ "detcom:dheader 4.0 N \"\ARG\" \"current channel\""
-    ENDM
-DETCOM_L MACRO ARG
-    COBJ "detcom:dheader 5.0 L \"\ARG\" \"binary control value\""
-    ENDM
-DETCOM_S MACRO ARG
-    COBJ "detcom:dheader 0.0 S \"\ARG\" \"GriF position of FP carriage - In/Out\""
-    ENDM
-DETCOM_6 MACRO ARG
-    COBJ "detcom:dheader 1.1 6 \"\ARG\" \"GriF wavelength of order used to scan\""
-    ENDM
-DETCOM_6 MACRO ARG
-    COBJ "detcom:dheader 1.2 6 \"\ARG\" \"GriF wavelength of calibration spectral line\""
-    ENDM
-DETCOM_6 MACRO ARG
-    COBJ "detcom:dheader 1.3 6 \"\ARG\" \"GriF BCV at calibration line\""
-    ENDM
-DETCOM_Y MACRO ARG
-    COBJ "detcom:dheader 2.0 Y \"\ARG\" \"GriF type of scan - bcv, wave, velocity\""
-    ENDM
-DETCOM_6 MACRO ARG
-    COBJ "detcom:dheader 3.1 6 \"\ARG\" \"GriF wavelength at beginning of scan\""
-    ENDM
-DETCOM_6 MACRO ARG
-    COBJ "detcom:dheader 3.2 6 \"\ARG\" \"GriF wavelength step\""
-    ENDM
-DETCOM_6 MACRO ARG
-    COBJ "detcom:dheader 3.3 6 \"\ARG\" \"GriF current observed wavelength\""
-    ENDM
-DETCOM_6 MACRO ARG
-    COBJ "detcom:dheader 4.1 6 \"\ARG\" \"GriF Binary Contol Value at beginning of scan\""
-    ENDM
-DETCOM_6 MACRO ARG
-    COBJ "detcom:dheader 4.2 6 \"\ARG\" \"GriF BCV step\""
-    ENDM
-DETCOM_R MACRO ARG
-    COBJ "detcom:dheader 4.3 R \"\ARG\" \"GriF applied BCV\""
-    ENDM
-DETCOM_N MACRO ARG
-    COBJ "detcom:dheader 5.1 N \"\ARG\" \"GriF number of channels in scan\""
-    ENDM
-DETCOM_H MACRO ARG
-    COBJ "detcom:dheader 5.2 H \"\ARG\" \"GriF current channel\""
-    ENDM
-DETCOM_X MACRO ARG
-    COBJ "detcom:dheader 6.1 X \"\ARG\" \"GriF X Binary Control Value FP\""
-    ENDM
-DETCOM_Y MACRO ARG
-    COBJ "detcom:dheader 6.2 Y \"\ARG\" \"GriF Y Binary Control Value FP\""
-    ENDM
-DETCOM_D MACRO ARG
-    COBJ "detcom:dheader 1.0 D \"\ARG\" \"Elixir camera run ID\""
-    ENDM
Index: /trunk/fpcamera/Makefile.am
===================================================================
--- /trunk/fpcamera/Makefile.am	(revision 42385)
+++ /trunk/fpcamera/Makefile.am	(revision 42385)
@@ -0,0 +1,5 @@
+SUBDIRS = src
+
+CLEANFILES = *.pyc *~ core core.*
+
+EXTRA_DIST = autogen.sh
Index: /trunk/fpcamera/autogen.sh
===================================================================
--- /trunk/fpcamera/autogen.sh	(revision 42385)
+++ /trunk/fpcamera/autogen.sh	(revision 42385)
@@ -0,0 +1,103 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+PROJECT=fpcamera
+TEST_TYPE=-f
+# change this to be a unique filename in the top level dir
+FILE=autogen.sh
+
+DIE=0
+
+LIBTOOLIZE=libtoolize
+ACLOCAL="aclocal $ACLOCAL_FLAGS"
+AUTOHEADER=autoheader
+AUTOMAKE=automake
+AUTOCONF=autoconf
+
+($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $LIBTOOLIZE installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/libtool/"
+        DIE=1
+}
+
+($ACLOCAL --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $ACLOCAL installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/automake/"
+        DIE=1
+}
+
+($AUTOHEADER --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $AUTOHEADER installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/autoconf/"
+        DIE=1
+}
+
+($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $AUTOMAKE installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/automake/"
+        DIE=1
+}
+
+($AUTOCONF --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $AUTOCONF installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/autoconf/"
+        DIE=1
+}
+
+if test "$DIE" -eq 1; then
+        exit 1
+fi
+
+test $TEST_TYPE $FILE || {
+        echo "You must run this script in the top-level $PROJECT directory"
+        exit 1
+}
+
+if test -z "$*"; then
+        echo "I am going to run ./configure with no arguments - if you wish "
+        echo "to pass any to it, please specify them on the $0 command line."
+fi
+
+$LIBTOOLIZE --copy --force || echo "$LIBTOOLIZE failed"
+$ACLOCAL || echo "$ACLOCAL failed"
+$AUTOHEADER || echo "$AUTOHEADER failed"
+$AUTOMAKE --add-missing --force-missing --copy || echo "$AUTOMAKE  failed"
+$AUTOCONF || echo "$AUTOCONF failed"
+
+cd $ORIGDIR
+
+run_configure=true
+for arg in $*; do
+    case $arg in
+        --no-configure)
+            run_configure=false
+            ;;
+        *)
+            ;;
+    esac
+done
+
+if $run_configure; then
+    $srcdir/configure --enable-maintainer-mode "$@"
+    echo
+    echo "Now type 'make' to compile $PROJECT."
+else
+    echo
+    echo "Now run 'configure' and 'make' to compile $PROJECT."
+fi
Index: /trunk/fpcamera/configure.ac
===================================================================
--- /trunk/fpcamera/configure.ac	(revision 42385)
+++ /trunk/fpcamera/configure.ac	(revision 42385)
@@ -0,0 +1,207 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.61)
+
+AC_INIT([fpcamera], [0.1.0], [ipp-support@ifa.hawaii.edu])
+AC_CONFIG_SRCDIR([src])
+
+AM_INIT_AUTOMAKE([1.6 foreign dist-bzip2])
+AM_CONFIG_HEADER([src/config.h])
+AM_MAINTAINER_MODE
+
+IPP_STDLDFLAGS
+
+AC_LANG(C)
+AC_GNU_SOURCE
+AC_PROG_CC_C99
+AC_PROG_INSTALL
+AC_PROG_LIBTOOL
+AC_SYS_LARGEFILE
+
+dnl ------------------------------------------------------------
+
+AC_PATH_PROG([ERRORCODES], [psParseErrorCodes], [missing])
+if test "$ERRORCODES" = "missing" ; then
+  AC_MSG_ERROR([psParseErrorCodes is required])
+fi
+
+dnl ------------------ kapa,libkapa options -------------------------
+dnl -- libkapa implies the requirement for libpng, libjpeg as well --
+
+dnl save LIBS/CFLAGS/LDFLAGS
+TMP_LIBS=${LIBS}
+TMP_CFLAGS=${CFLAGS}
+TMP_LDFLAGS=${LDFLAGS}
+TMP_CPPFLAGS=${CPPFLAGS}
+
+dnl test for command-line options: use ohana-config if not supplied
+KAPA_CFLAGS_CONFIG="true"
+KAPA_LIBS_CONFIG="true"
+AC_ARG_WITH(kapa,
+[AS_HELP_STRING(--with-kapa=DIR,Specify location of libkapa)],
+[KAPA_CFLAGS="-I$withval/include" KAPA_LIBS="-L$withval/lib" 
+ KAPA_CFLAGS_CONFIG="false"       KAPA_LIBS_CONFIG="false"])
+AC_ARG_WITH(kapa-include,
+[AS_HELP_STRING(--with-kapa-include=DIR,Specify libkapa include directory.)],
+[KAPA_CFLAGS="-I$withval" KAPA_CFLAGS_CONFIG="false"])
+AC_ARG_WITH(kapa-lib,
+[AS_HELP_STRING(--with-kapa-lib=DIR,Specify libkapa library directory.)],
+[KAPA_LIBS="-L$withval" KAPA_LIBS_CONFIG="false"])
+
+echo "KAPA_CFLAGS_CONFIG: $KAPA_CFLAGS_CONFIG"
+echo "KAPA_LIBS_CONFIG: $KAPA_LIBS_CONFIG"
+echo "KAPA_CFLAGS: $KAPA_CFLAGS"
+echo "KAPA_LIBS: $KAPA_LIBS"
+
+dnl HAVE_KAPA is set to false if any of the tests fail
+HAVE_KAPA="true"
+AC_MSG_NOTICE([checking for libkapa])
+if test "$KAPA_CFLAGS_CONFIG" = "true" -o "$KAPA_LIBS_CONFIG" = "true"; then
+  AC_MSG_NOTICE([kapa info supplied by ohana-config])
+  KAPA_CONFIG=`which ohana-config`
+  AC_CHECK_FILE($KAPA_CONFIG,[],
+    [HAVE_KAPA="false"; AC_MSG_WARN([libkapa is not found: output plots disabled.  Obtain libkapa at http://kiawe.ifa.hawaii.edu/Elixir/Ohana or use --with-kapa to specify location])])
+  
+  echo "HAVE_KAPA: $HAVE_KAPA"
+  echo "KAPA_CFLAGS_CONFIG: $KAPA_CFLAGS_CONFIG"
+
+  if test "$HAVE_KAPA" = "true" -a "$KAPA_CFLAGS_CONFIG" = "true" ; then
+   AC_MSG_NOTICE([libkapa cflags info supplied by ohana-config])
+   AC_MSG_CHECKING([libkapa cflags])
+   KAPA_CFLAGS="`${KAPA_CONFIG} --cflags`"
+   AC_MSG_RESULT([${KAPA_CFLAGS}])
+  fi
+
+  if test "$HAVE_KAPA" = "true" -a "$KAPA_LIBS_CONFIG" = "true" ; then
+   AC_MSG_NOTICE([libkapa ldflags info supplied by ohana-config])
+   AC_MSG_CHECKING([libkapa ldflags])
+   KAPA_LIBS="`${KAPA_CONFIG} --libs` -lX11"
+   AC_MSG_RESULT([${KAPA_LIBS}])
+  fi
+fi
+
+if test "$HAVE_KAPA" = "true" ; then
+ AC_MSG_NOTICE([libkapa supplied])
+ FPCAMERA_CFLAGS="${FPCAMERA_CFLAGS} ${KAPA_CFLAGS}"
+ FPCAMERA_LIBS="${FPCAMERA_LIBS} ${KAPA_LIBS}"
+else
+ AC_MSG_NOTICE([libkapa ignored])
+fi
+
+dnl restore the CFLAGS/LDFLAGS
+LIBS=${TMP_LIBS}
+CFLAGS=${TMP_CFLAGS}
+LDFLAGS=${TMP_LDFLAGS}
+CPPFLAGS=${TMP_CPPFLAGS}
+
+dnl ------------------ libjpeg options ---------------------
+
+dnl save LIBS/CFLAGS/LDFLAGS
+TMP_LIBS=${LIBS}
+TMP_CFLAGS=${CFLAGS}
+TMP_LDFLAGS=${LDFLAGS}
+TMP_CPPFLAGS=${CPPFLAGS}
+
+AC_ARG_WITH(jpeg,
+[AS_HELP_STRING(--with-jpeg=DIR,Specify location of libjpeg.)],
+[JPEG_CFLAGS="-I$withval/include"
+ JPEG_LDFLAGS="-L$withval/lib"])
+AC_ARG_WITH(jpeg-include,
+[AS_HELP_STRING(--with-jpeg-include=DIR,Specify libjpeg include directory.)],
+[JPEG_CFLAGS="-I$withval"])
+AC_ARG_WITH(jpeg-lib,
+[AS_HELP_STRING(--with-jpeg-lib=DIR,Specify libjpeg library directory.)],
+[JPEG_LDFLAGS="-L$withval"])
+
+CFLAGS="${CFLAGS} ${JPEG_CFLAGS}"
+CPPFLAGS=${CFLAGS}
+LDFLAGS="${LDFLAGS} ${JPEG_LDFLAGS}"
+
+AC_CHECK_HEADERS([jpeglib.h],
+  [FPCAMERA_CFLAGS="$FPCAMERA_CFLAGS $JPEG_CFLAGS" AC_SUBST(JPEG_CFLAGS)],
+  [HAVE_KAPA=false; AC_MSG_WARN([libjpeg headers not found: output plots disabled.  Obtain libjpeg from http://www.ijg.org/ or use --with-jpeg to specify location.])]
+)
+
+AC_CHECK_LIB(jpeg,jpeg_CreateCompress,
+  [FPCAMERA_LIBS="$FPCAMERA_LIBS $JPEG_LDFLAGS -ljpeg"],
+  [HAVE_KAPA=false; AC_MSG_WARN([libjpeg library not found: output plots disabled.  Obtain libjpeg from http://www.ijg.org/ or use --with-jpeg to specify location.])]
+)
+
+dnl restore the CFLAGS/LDFLAGS
+LIBS=${TMP_LIBS}
+CFLAGS=${TMP_CFLAGS}
+LDFLAGS=${TMP_LDFLAGS}
+CPPFLAGS=${TMP_CPPFLAGS}
+
+dnl ------------------ libpng options ---------------------
+
+dnl save LIBS/CFLAGS/LDFLAGS
+TMP_LIBS=${LIBS}
+TMP_CFLAGS=${CFLAGS}
+TMP_LDFLAGS=${LDFLAGS}
+TMP_CPPFLAGS=${CPPFLAGS}
+
+AC_ARG_WITH(png,
+[AS_HELP_STRING(--with-png=DIR,Specify location of libpng.)],
+[PNG_CFLAGS="-I$withval/include"
+ PNG_LDFLAGS="-L$withval/lib"])
+AC_ARG_WITH(png-include,
+[AS_HELP_STRING(--with-png-include=DIR,Specify libpng include directory.)],
+[PNG_CFLAGS="-I$withval"])
+AC_ARG_WITH(png-lib,
+[AS_HELP_STRING(--with-png-lib=DIR,Specify libpng library directory.)],
+[PNG_LDFLAGS="-L$withval"])
+
+CFLAGS="${CFLAGS} ${PNG_CFLAGS}"
+CPPFLAGS=${CFLAGS}
+LDFLAGS="${LDFLAGS} ${PNG_LDFLAGS}"
+
+AC_CHECK_HEADERS([png.h],
+  [FPCAMERA_CFLAGS="$FPCAMERA_CFLAGS $PNG_CFLAGS" AC_SUBST(PNG_CFLAGS)],
+  [HAVE_KAPA=false; AC_MSG_WARN([libpng headers not found: output plots disabled.  Obtain libpng from http://www.ijg.org/ or use --with-png to specify location.])]
+)
+
+AC_CHECK_LIB(png,png_init_io,
+  [FPCAMERA_LIBS="$FPCAMERA_LIBS $PNG_LDFLAGS -lpng"],
+  [HAVE_KAPA=false; AC_MSG_WARN([libpng library not found: output plots disabled.  Obtain libpng from http://www.ijg.org/ or use --with-png to specify location.])]
+)
+
+dnl restore the CFLAGS/LDFLAGS
+LIBS=${TMP_LIBS}
+CFLAGS=${TMP_CFLAGS}
+LDFLAGS=${TMP_LDFLAGS}
+CPPFLAGS=${TMP_CPPFLAGS}
+
+dnl ------------------ use kapa or not? ---------------------
+
+if test "$HAVE_KAPA" == "true" ; then
+  AC_MSG_RESULT([including plotting functions])
+  AC_DEFINE([HAVE_KAPA],[1],[enable use of libkapa])
+else
+  AC_MSG_RESULT([skipping plotting functions])
+  AC_DEFINE([HAVE_KAPA],[0],[disable use of libkapa])
+fi
+
+dnl ------------- psLib, psModules ---------------
+PKG_CHECK_MODULES([PSLIB],    [pslib >= 1.0.0])
+PKG_CHECK_MODULES([PSMODULE], [psmodules >= 1.0.0])
+PKG_CHECK_MODULES([PSPHOT],   [psphot >= 0.8.0]) 
+PKG_CHECK_MODULES([PPSTATS],  [ppStats >= 1.0.0]) 
+
+dnl Set CFLAGS for build
+IPP_STDOPTS
+IPP_STDCFLAGS
+
+echo "FPCAMERA_CFLAGS: $FPCAMERA_CFLAGS"
+echo "FPCAMERA_LIBS: $FPCAMERA_LIBS"
+
+IPP_VERSION
+
+AC_SUBST([FPCAMERA_CFLAGS])
+AC_SUBST([FPCAMERA_LIBS])
+
+AC_CONFIG_FILES([
+  Makefile
+  src/Makefile
+])
+
+AC_OUTPUT
Index: /trunk/fpcamera/doc/notes.txt
===================================================================
--- /trunk/fpcamera/doc/notes.txt	(revision 42385)
+++ /trunk/fpcamera/doc/notes.txt	(revision 42385)
@@ -0,0 +1,15 @@
+
+psphotSetHeaderNstars : counts N_STARS and writes to a header metadata
+
+psphotReadoutCleanup:
+  psphotPSFstatsSources : measure stats for PSF model (e.g., FWHM_MAJ) [readout->analysis]
+  psphotMomentsStats    : measure stats based on 2nd moments           [readout->analysis]
+  psphotSetHeaderNstars : count stars (& subsets)                      [PSPHOT.HEADER]
+  psphotDefineHeader    : moves the values from readout->analysis to PSPHOT.HEADER
+  
+pmSourceID : appends the header MD entries from PSPHOT.HEADER & PSASTRO.HEADER to the output cmf
+
+psastro ---
+
+psastroMosaicOneChip : measure stats for astrom, Nstars, etc : PSASTRO.HEADER
+
Index: /trunk/fpcamera/src/Makefile.am
===================================================================
--- /trunk/fpcamera/src/Makefile.am	(revision 42385)
+++ /trunk/fpcamera/src/Makefile.am	(revision 42385)
@@ -0,0 +1,79 @@
+
+bin_PROGRAMS = fpcamera
+
+noinst_HEADERS = fpcamera.h fpcameraErrorCodes.h
+
+fpcamera_CFLAGS = $(FPCAMERA_CFLAGS) $(PPSTATS_CFLAGS) $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
+fpcamera_LDFLAGS = $(FPCAMERA_LIBS) $(PPSTATS_LIBS) $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
+
+fpcamera_SOURCES = \
+	fpcamera.c		    \
+        fpcameraArguments.c	    \
+	fpcameraVersion.c           \
+	fpcameraParseCamera.c       \
+	fpcameraDataLoad.c          \
+	fpcameraAnalysis.c          \
+	fpcameraDataSave.c          \
+	fpcameraErrorCodes.c        \
+	fpcameraReadAstrometry.c    \
+	fpcameraLoadRefstars.c      \
+	fpcameraChooseRefstars.c    \
+	fpcameraAstrometryHeaders.c \
+	fpcameraMetadataStats.c     \
+	fpcameraCleanup.c
+
+unused = \
+	fpcameraMaskUpdates.c        \
+	fpcameraMaskUtils.c          \
+	fpcameraChooseGlintStars.c   \
+	fpcameraLoadCrosstalk.c \
+	fpcameraLoadGlints.c   \
+	fpcameraLoadGhosts.c         \
+	fpcameraGhostUtils.c         \
+	fpcameraDefineFiles.c        \
+	fpcameraAstromGuess.c        \
+	fpcameraLoadRefstars.c       \
+	fpcameraChooseRefstars.c     \
+	fpcameraConvert.c	    \
+	fpcameraChipAstrom.c         \
+	fpcameraOneChipGrid.c	    \
+	fpcameraOneChipFit.c	    \
+	fpcameraRemoveClumps.c	    \
+	fpcameraUtils.c	       	    \
+	fpcameraTestFuncs.c          \
+	fpcameraLuminosityFunction.c \
+	fpcameraRefstarSubset.c      \
+	fpcameraFixChips.c           \
+	fpcameraFixChipsTest.c       \
+	fpcameraUseModel.c           \
+	fpcameraFindChip.c           \
+	fpcameraZeroPoint.c    	    \
+	fpcameraDemoDump.c           \
+	fpcameraDemoPlot.c
+
+CLEANFILES = fpcameraErrorCodes.h fpcameraErrorCodes.c
+EXTRA_DIST = fpcameraErrorCodes.dat fpcameraErrorCodes.h.in fpcameraErrorCodes.c.in
+
+clean-local:
+	-rm -f TAGS
+
+# Tags for emacs
+tags:
+	etags `find . -name \*.[ch] -print`
+
+BUILT_SOURCES = fpcameraErrorCodes.h fpcameraErrorCodes.c fpcameraVersionDefinitions.h
+
+fpcameraErrorCodes.h : fpcameraErrorCodes.dat fpcameraErrorCodes.h.in
+	$(ERRORCODES) --data=fpcameraErrorCodes.dat --outdir=. fpcameraErrorCodes.h
+
+fpcameraErrorCodes.c : fpcameraErrorCodes.dat fpcameraErrorCodes.c.in fpcameraErrorCodes.h
+	$(ERRORCODES) --data=fpcameraErrorCodes.dat --outdir=. fpcameraErrorCodes.c
+
+# Force recompilation of fpcameraVersion.c, since it gets the version information
+fpcameraVersion.c: fpcameraVersionDefinitions.h
+fpcameraVersionDefinitions.h: fpcameraVersionDefinitions.h.in FORCE
+	pslib-setsvnversion.pl FPCAMERA fpcameraVersionDefinitions.h.in fpcameraVersionDefinitions.h
+
+FORCE: ;
+
+# cat fpcameraVersionDefinitions.h.in | tr '@' '"' > fpcameraVersionDefinitions.h
Index: /trunk/fpcamera/src/fpcamera.c
===================================================================
--- /trunk/fpcamera/src/fpcamera.c	(revision 42385)
+++ /trunk/fpcamera/src/fpcamera.c	(revision 42385)
@@ -0,0 +1,90 @@
+# include "fpcamera.h"
+
+/** @file fpcamera.c
+ *
+ *  @brief
+ *
+ *  @ingroup fpcamera
+ *
+ *  @author Eugene Magnier, IfA
+ *  @version $Revision$ $LastChangedBy$
+ *  @date $Date$
+ *  Copyright 2022 Institute for Astronomy, University of Hawaii
+ */
+
+# define ESCAPE(ERROR, MSG) { psErrorStackPrint(stderr, MSG); psFree(config); psFree(stats); exit(ERROR); }
+
+void usage(void) {
+    fprintf (stderr, "USAGE: one of the following:\n\n");
+    fprintf (stderr, "  fpcamera -file filename[,filename,...] -mask maskfile[,maskfile,...] -variance varfile[,varfile,...] -astrom-file (smffile) OutFileBaseName\n");
+    fprintf (stderr, "  fpcamera -list filelist -masklist masklist -varlist varlist -astrom-file (smffile) -OutFileBaseName\n\n");
+    fprintf (stderr, "where:\n");
+    fprintf (stderr, "  FileNameList is a text file containing filenames, one per line\n");
+    fprintf (stderr, "  MaskFileNameList is a text file of mask filenames, one per line\n");
+    fprintf (stderr, "  VarFileNameList is a text file of variance filenames, one per line\n");
+    fprintf (stderr, "  OutFileBaseName is the 'root name' for output files\n\n");
+    fprintf(stderr, "Optional arguments:\n");
+    fprintf(stderr, "   -stats STATS.mdc: Output statistics into STATS.mdc\n");
+    fprintf(stderr, "   -chip CHIPNUM: Only process this chip number.\n\n");
+    fprintf(stderr, "   -D FPCAMERA.CATDIR (catdir): specify the reference catalog.\n\n");
+    exit (PS_EXIT_CONFIG_ERROR);
+}
+
+int main (int argc, char **argv) {
+
+    // these two must be defined and set to NULL so ESCAPE can try to free them
+    psMetadata *stats = NULL;
+    pmConfig  *config = NULL;
+
+    // initialize & load configuration information
+    config = fpcameraArguments(argc, argv);
+    if (!config) usage();
+
+    fpcameraVersionPrint();
+
+    // identify the data sources from the header of the astrometry file
+    if (!fpcameraParseCamera (config)) ESCAPE(PS_EXIT_CONFIG_ERROR, "Error setting up the camera");
+
+    // load the raw detection data (using PSPHOT.SOURCES filerule)
+    // select subset of stars for astrometry
+    if (!fpcameraDataLoad (config)) ESCAPE(PS_EXIT_DATA_ERROR, "error loading input data");
+    psLogMsg("fpcamera", 3, "TIMEMARK: fpcameraDataLoad: %f sec\n", psTimerMark ("complete"));
+
+    stats = psMetadataAlloc(); // Statistics, for output
+    psMetadataAddS32(stats, PS_LIST_TAIL, "QUALITY", 0, "No problems", 0);
+
+    // run the full astrometry analysis (chip and/or mosaic)
+    if (!fpcameraAnalysis(config, stats)) ESCAPE(PS_EXIT_SYS_ERROR, "failure in fpcamera analysis");
+    psLogMsg("fpcamera", 3, "TIMEMARK: fpcameraAnalysis: %f sec\n", psTimerMark ("complete"));
+
+    // write out the results
+    if (!fpcameraDataSave(config, stats)) ESCAPE(PS_EXIT_DATA_ERROR, "failed to write out data");
+    psLogMsg("fpcamera", 3, "complete fpcamera run: %f sec\n", psTimerMark ("complete"));
+
+    fpcameraCleanup(config, stats);
+    exit(PS_EXIT_SUCCESS);
+}
+
+/* code outline
+
+   - init & parse arguments
+   
+   - construct pmFPAfiles for the inputs and output, identify camera
+
+   - load astrometry from smf file
+
+   - load reference sources for full field
+
+   - loop over chips (already detrended)
+
+     - generate subset of sources for this chip
+
+     - generate a PSF model for this chip
+       - use stars in a specific apparent magnitude range?
+       - use a starting guess PSF model and choose stars based on initial fit?
+
+     - fit known stars with PSF model to pixel data
+
+     - output cmf / smf
+*/
+
Index: /trunk/fpcamera/src/fpcamera.h
===================================================================
--- /trunk/fpcamera/src/fpcamera.h	(revision 42385)
+++ /trunk/fpcamera/src/fpcamera.h	(revision 42385)
@@ -0,0 +1,78 @@
+/** @file fpcamera.h
+ *
+ *  @brief This file defines the library functions available to external
+ *  programs.
+ *
+ *  It must be included by programs which are compiled against
+ *  psphot functions.
+ *
+ *  @ingroup fpcamera
+ *
+ *  @author IfA
+ *  @version $Revision: 1.49 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2009-02-09 21:25:34 $
+ *  Copyright 2009 Institute for Astronomy, University of Hawaii
+ */
+
+# ifndef FPCAMERA_H
+# define FPCAMERA_H
+
+#include <stdio.h>
+#include <string.h>
+#include <pslib.h>
+#include <psmodules.h>
+#include <psphot.h>
+#include <ppStats.h>
+#include "fpcameraErrorCodes.h"
+
+/// @addtogroup fpcamera
+/// @{
+
+# define FPCAMERA_RECIPE "FPCAMERA" ///< Name of the recipe to use
+
+# define psMemCopy(A)(psMemIncrRefCounter((A)))
+# define DEG_RAD 57.295779513082322
+# define RAD_DEG  0.017453292519943
+# define SIGN(X)  (((X) == 0) ? 0 : ((fabs((double)(X))) / (X)))
+
+pmConfig         *fpcameraArguments (int argc, char **argv);
+bool 		  fpcameraParseCamera (pmConfig *config);
+bool 		  fpcameraDataLoad (pmConfig *config);
+bool              fpcameraAnalysis (pmConfig *config, psMetadata *stats);
+bool              fpcameraDataSave (pmConfig *config, psMetadata *stats);
+
+void              fpcameraCleanup (pmConfig *config, psMetadata *stats);
+
+bool              fpcameraDefineFiles (pmConfig *config, pmFPAfile *input);
+bool              fpcameraDefineFile (pmConfig *config, pmFPA *input, char *filerule, char *argname, pmFPAfileType fileType, pmDetrendType detrendType);
+
+bool              fpcameraLoadRefstars (pmFPAfile *input, pmConfig *config);
+bool              fpcameraReadAstrometry (pmFPAfile *input, pmConfig *config);
+bool              fpcameraChooseRefstars (pmFPAfile *input, pmFPAfile *astrom, pmFPAview *view);
+
+// Return version strings.
+psString          fpcameraVersion(void);
+psString          fpcameraSource(void);
+psString          fpcameraVersionLong(void);
+bool              fpcameraVersionHeader(psMetadata *header);
+bool              fpcameraVersionHeaderFull(psMetadata *header);
+void              fpcameraVersionPrint(void);
+
+psArray          *fpcameraReadGetstarCatalog (psFits *fits);
+psArray          *fpcameraReadGetstar_PS1_DEV_0 (psFits *fits);
+
+bool              fpcameraMetadataStats (pmConfig *config, psMetadata *stats);
+
+pmChip           *fpcameraFindChip (double *xChip, double *yChip, pmFPA *fpa, double xFPA, double yFPA);
+bool 		  fpcameraChipBounds (pmFPA *fpa);
+bool              fpcameraFindChipInXrange (pmFPA *fpa, int nChip, double xFPA, double yFPA);
+bool              fpcameraFindChipInYrange (pmFPA *fpa, int nChip, double xFPA, double yFPA);
+bool 		  fpcameraFindChipYedges (double *yFPAs, double *yFPAe, pmFPA *fpa, int nChip);
+bool 		  fpcameraFindChipXedges (double *yFPAs, double *yFPAe, pmFPA *fpa, int nChip);
+bool 		  fpcameraFPAtoChip (double *xChip, double *yChip, pmFPA *fpa, int nChip, double xFPA, double yFPA);
+
+bool              fpcameraAstrometryFPAHeader(pmFPA *fpa, pmFPAfile *astrom, psMetadata *stats);
+bool              fpcameraAstrometryChipHeader (pmConfig *config, pmFPAview *view, pmReadout *readout, pmFPAfile *astrom);
+
+///@}
+# endif /* FPCAMERA_H */
Index: /trunk/fpcamera/src/fpcameraAnalysis.c
===================================================================
--- /trunk/fpcamera/src/fpcameraAnalysis.c	(revision 42385)
+++ /trunk/fpcamera/src/fpcameraAnalysis.c	(revision 42385)
@@ -0,0 +1,122 @@
+# include "fpcamera.h"
+
+# define ESCAPE(ERROR, MSG) { psErrorStackPrint(stderr, MSG); psFree (view); return false; }
+
+/* \brief this function loops over chips and performs forced photometry for the references */
+bool fpcameraAnalysis (pmConfig *config, psMetadata *stats) {
+
+    bool status;
+    pmChip *chip;
+    pmCell *cell;
+    pmReadout *readout;
+    pmFPAview *view = NULL;
+
+    // measure the total elapsed time in fpcameraAnalysis.
+    psTimerStart ("fpcameraAnalysis");
+
+    // select the current recipe
+    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, FPCAMERA_RECIPE);
+    if (!recipe) ESCAPE (FPCAMERA_ERR_CONFIG, "Can't find FPCAMERA recipe");
+
+    // loop over the input images
+    pmFPAfile *input = psMetadataLookupPtr (&status, config->files, "FPCAMERA.INPUT");
+    if (!input) ESCAPE(FPCAMERA_ERR_CONFIG, "Can't find or interpret output file rule FPCAMERA.INPUT!");
+
+    // astrometry reference (smf)
+    pmFPAfile *astrom = psMetadataLookupPtr (&status, config->files, "FPCAMERA.INPUT.ASTROM");
+    if (!astrom) ESCAPE(FPCAMERA_ERR_CONFIG, "Can't find or interpret output file rule FPCAMERA.INPUT.ASTROM!");
+
+    // only activate input image-type files
+    pmFPAfileActivate (config->files, false, NULL);
+    pmFPAfileActivate (config->files, true, "FPCAMERA.INPUT");
+    pmFPAfileActivate (config->files, true, "FPCAMERA.INPUT.MASK");
+    pmFPAfileActivate (config->files, true, "FPCAMERA.INPUT.VARIANCE");
+    pmFPAfileActivate (config->files, true, "FPCAMERA.RESID");
+    pmFPAfileActivate (config->files, true, "PSPHOT.PSF.LOAD"); // if this file is defined, we need to activate it now
+    // Note: the output file FPCAMERA.RESID is tied to FPCAMERA.INPUT so they must be active in the same block.
+
+    view = pmFPAviewAlloc (0);
+
+    // load images at FPA level (if appropriate)
+    if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE(FPCAMERA_ERR_DATA, "failed to load images at FPA level");
+
+    // count the number of sucesses and raise bad quality if none succeed
+    int nChipGood = 0;
+    int nChipTotal = 0;
+
+    // load images at chip level (if appropriate) 
+    while ((chip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
+	nChipTotal ++;
+        psTrace ("fpcamera", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+        if (!chip->process || !chip->file_exists) { continue; }
+	if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE(FPCAMERA_ERR_DATA, "failed to load images at Chip level");
+
+	// loop over all cells in chip
+        while ((cell = pmFPAviewNextCell (view, input->fpa, 1)) != NULL) {
+            psLogMsg ("fpcamera", 5, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+            if (!cell->process || !cell->file_exists) { continue; }
+
+	    // loop over all readouts in cell
+            while ((readout = pmFPAviewNextReadout (view, input->fpa, 1)) != NULL) {
+                psLogMsg ("fpcamera", 6, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+                if (!readout->data_exists) { continue; }
+
+		fpcameraChooseRefstars (input, astrom, view);
+
+		// Provide a simple (wrong) PSF as a default if psf model is not supplied with -psf or -psflist.
+		// The user-supplied psf model will replace this one on a chip-by-chip basis
+		// pmPSF *psf = pmPSFBuildSimple ("PS_MODEL_PS1_V1", 5.0, 5.0, 0.0, 0.5);
+		pmPSF *psf = pmPSFBuildSimple ("PS_MODEL_GAUSS", 5.0, 5.0, 0.0);
+		psf->fieldNx = readout->image->numCols;
+		psf->fieldNy = readout->image->numRows;
+		psMetadataAddPtr (readout->analysis, PS_LIST_TAIL, "PSPHOT.PSF", PS_META_REPLACE | PS_DATA_UNKNOWN, "psphot PSF model", psf);
+		psFree (psf);
+
+		if (!psphotForcedReadout (config, view, "FPCAMERA.INPUT")) {
+		    // This is likely a data quality issue, e.g. no stars on a chip
+		    // Do not raise an error, but do not add to count of good chips
+		    psErrorStackPrint(stderr, "Unable to perform photometry on image");
+		    psWarning("Unable to perform photometry on image --- suspect bad data quality.");
+		    psErrorClear();
+		    continue;
+		}
+		fpcameraAstrometryChipHeader (config, view, readout, astrom);
+		nChipGood ++;
+	    }
+            // drop all versions of the internal files
+            status = true;
+            status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKMDL");
+            status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKMDL.STDEV");
+            status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKGND");
+            if (!status) ESCAPE(FPCAMERA_ERR_PROG, "trouble dropping internal files");
+	}
+        if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE(FPCAMERA_ERR_IO, "failure in IOChecks(AFTER) at Chip");
+    }
+    fpcameraAstrometryFPAHeader (input->fpa, astrom, stats);
+    if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE(FPCAMERA_ERR_IO, "failure in IOChecks(AFTER) at FPA");
+
+    if (!nChipGood) {
+	if (stats && psMetadataLookupS32(NULL, stats, "QUALITY") == 0) {
+	    psMetadataAddS32(stats, PS_LIST_TAIL, "QUALITY", PS_META_REPLACE, "Unable to perform photometry on image", FPCAMERA_ERR_DATA);
+	}
+    }
+    psLogMsg("fpcamera", 3, "fpcameraAnalysis: %d of %d chips are good\n", nChipGood, nChipTotal);
+
+    psFree (view);
+
+    psLogMsg("fpcamera", 3, "TIMEMARK: fpcameraAnalysis: %f sec\n", psTimerMark ("analysis"));
+    return true;
+}
+
+// NOTES
+// chip->process is set (unset) based on command-line -chip selections (in fpcameraArguments)
+// chip->file_exists is set (in pmFPAFlags.c:pmChipSetFileStatus) by pmFPAfileDefineFromArgs (in pmFPAAddSource...)
+
+/*
+        // XXX set sxx, etc from FWHM in recipe
+        pmPSF *psf = pmPSFBuildSimple (modelNames->data[0], 1.0, 1.0, 0.0, 1.0);
+        psf->fieldNx = readout->image->numCols;
+        psf->fieldNy = readout->image->numRows;
+        psFree (modelNames);
+
+*/
Index: /trunk/fpcamera/src/fpcameraArguments.c
===================================================================
--- /trunk/fpcamera/src/fpcameraArguments.c	(revision 42385)
+++ /trunk/fpcamera/src/fpcameraArguments.c	(revision 42385)
@@ -0,0 +1,86 @@
+# include "fpcamera.h"
+
+# define ESCAPE(ERROR,MSG) { psError(ERROR, true, MSG); psErrorStackPrint(stderr, "exit"); return NULL; }
+
+pmConfig *fpcameraArguments (int argc, char **argv) {
+
+    bool status;
+    int N;
+
+    psTimerStart ("complete");		// set an overall timer
+    fpcameraErrorRegister();		// register our error codes/messages
+    pmModelClassInit();			// model inits are needed in pmSourceIO
+    psphotInit();
+
+    if (argc == 1) ESCAPE(FPCAMERA_ERR_ARGUMENTS, "No arguments supplied");
+
+    // load config data from default locations
+    pmConfig *config = pmConfigRead(&argc, argv, FPCAMERA_RECIPE);
+    if (config == NULL) ESCAPE(FPCAMERA_ERR_CONFIG, "Can't read site configuration");
+
+    // save the following additional recipe values based on command-line options
+    // these options override the FPCAMERA recipe values loaded from recipe files
+    psMetadata *options = pmConfigRecipeOptions (config, FPCAMERA_RECIPE);
+
+    // photcode : used in output to supplement header data (argument or recipe?)
+    if ((N = psArgumentGet (argc, argv, "-photcode"))) {
+        psArgumentRemove (N, &argc, argv);
+        psMetadataAddStr (options, PS_LIST_TAIL, "PHOTCODE", PS_META_REPLACE, "", argv[N]);
+        psArgumentRemove (N, &argc, argv);
+    }
+
+    // chip selection is used to limit chips to be processed
+    if ((N = psArgumentGet (argc, argv, "-chip"))) {
+        psArgumentRemove (N, &argc, argv);
+        psMetadataAddStr (config->arguments, PS_LIST_TAIL, "CHIP_SELECTIONS", PS_META_REPLACE, "", argv[N]);
+        psArgumentRemove (N, &argc, argv);
+    }
+
+    // dump the statistics to a file
+    if ((N = psArgumentGet(argc, argv, "-stats"))) {
+        psArgumentRemove(N, &argc, argv);
+        psMetadataAddStr(config->arguments, PS_LIST_TAIL, "STATS", PS_META_REPLACE, "Filename for summary statistics", argv[N]);
+        psArgumentRemove(N, &argc, argv);
+    }
+
+    // dump the configuration to a file?
+    if ((N = psArgumentGet (argc, argv, "-dumpconfig"))) {
+        psArgumentRemove (N, &argc, argv);
+        psMetadataAddStr (config->arguments, PS_LIST_TAIL, "DUMP_CONFIG", PS_META_REPLACE, "", argv[N]);
+        psArgumentRemove (N, &argc, argv);
+    }
+
+    // chip selection is used to limit chips to be processed
+    if ((N = psArgumentGet (argc, argv, "-save-resid"))) {
+        psArgumentRemove (N, &argc, argv);
+        psMetadataAddBool (config->arguments, PS_LIST_TAIL, "SAVE.RESID", PS_META_REPLACE, "", true);
+    }
+
+    // specify the input images to process
+    status = pmConfigFileSetsMD (config->arguments, &argc, argv, "INPUT",    "-file",     "-list");
+    if (!status) ESCAPE(FPCAMERA_ERR_ARGUMENTS, "Missing -file (input) or -list (input)");
+
+    // specify the input images to process
+    status = pmConfigFileSetsMD (config->arguments, &argc, argv, "MASK",     "-mask",     "-masklist");
+    if (!status) ESCAPE(FPCAMERA_ERR_ARGUMENTS, "Missing -mask (input) or -masklist (input)");
+
+    // specify the input images to process
+    status = pmConfigFileSetsMD (config->arguments, &argc, argv, "VARIANCE", "-variance", "-varlist");
+    if (!status) ESCAPE(FPCAMERA_ERR_ARGUMENTS, "Missing -variance (input) or -varlist (input)");
+
+    // specify the astrometry calibration
+    status = pmConfigFileSetsMD (config->arguments, &argc, argv, "INPUT.ASTROM", "-astrom-file", NULL);
+    if (!status) ESCAPE(FPCAMERA_ERR_ARGUMENTS, "Missing -astrom-file (input) : provide an smf or similar");
+
+    // specify the input images to process
+    status = pmConfigFileSetsMD (config->arguments, &argc, argv, "INPUT.PSF", "-psf",     "-psflist");
+    // user-supplied psf model is optional
+    
+    if (argc != 2) ESCAPE(FPCAMERA_ERR_ARGUMENTS, "Incorrect number of arguments supplied");
+
+    // output position is fixed
+    psMetadataAddStr (config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "", argv[1]);
+
+    psTrace("fpcamera", 1, "Done with fpcameraArguments...\n");
+    return (config);
+}
Index: /trunk/fpcamera/src/fpcameraAstrometryHeaders.c
===================================================================
--- /trunk/fpcamera/src/fpcameraAstrometryHeaders.c	(revision 42385)
+++ /trunk/fpcamera/src/fpcameraAstrometryHeaders.c	(revision 42385)
@@ -0,0 +1,78 @@
+# include "fpcamera.h"
+# define NONLIN_TOL 0.001 /* tolerance in pixels */
+
+bool fpcameraAstrometryBilevel (pmFPAfile *astrom) {
+    myAssert (astrom, "programming error");
+
+    pmFPA *fpa = astrom->fpa;
+    myAssert (fpa, "programming error");
+
+    bool useBilevelWCS = (fpa->toTPA->x->nX > 1) || (fpa->toTPA->x->nY > 1);
+    return useBilevelWCS;
+}
+
+// this is saved on the readout->analysis, but we assume a chip has only one cell & readout
+bool fpcameraAstrometryChipHeader (pmConfig *config, pmFPAview *view, pmReadout *readout, pmFPAfile *astrom) {
+
+    bool status;
+
+    // select the current recipe
+    psMetadata *recipe  = psMetadataLookupPtr (NULL, config->recipes, FPCAMERA_RECIPE);
+
+    // save WCS and analysis metadata in update header
+    // (pull or create local view to entry on readout->analysis)
+    psMetadata *updates = psMetadataLookupMetadata (&status, readout->analysis, "PSASTRO.HEADER");
+    if (!updates) {
+	updates = psMetadataAlloc ();
+	psMetadataAddMetadata (readout->analysis, PS_LIST_TAIL, "PSASTRO.HEADER",  PS_META_REPLACE, "psastro header stats", updates);
+	psFree (updates);
+    }
+
+    bool useBilevelWCS = fpcameraAstrometryBilevel(astrom);
+
+    pmFPA *fpa = astrom->fpa;
+    pmChip *astromChip = pmFPAviewThisChip(view, astrom->fpa);
+
+    // if the toTPA distortion model uses higher-order terms, then we need to use BiLevel astrometry 
+    if (useBilevelWCS) {
+	// create the header keywords to descripe the results
+	if (!pmAstromWriteBilevelChip (updates, astromChip, NONLIN_TOL)) {
+	    psError(PS_ERR_UNKNOWN, false, "invalid solution for %d,%d,%d\n", view->chip, view->cell, view->readout);
+	    psErrorStackPrint(stderr, "failure to generate WCS keywords for one chip\n");
+	    psErrorClear();
+	    return false;
+	}
+    } else {
+	fpa->wcsCDkeys = psMetadataLookupBool(&status, recipe, "PSASTRO.WCS.USECDKEYS");
+	pmAstromWriteWCS (updates, fpa, astromChip, NONLIN_TOL);
+    }
+    
+    return true;
+}
+
+bool fpcameraAstrometryFPAHeader(pmFPA *fpa, pmFPAfile *astrom, psMetadata *stats) {
+
+    bool status;
+
+    bool useBilevelWCS = fpcameraAstrometryBilevel(astrom);
+    if (!useBilevelWCS) return true; // no fpa-level headers if not bilevel
+    
+    // save WCS and analysis metadata in update header.
+    // (pull or create local view to entry on readout->analysis)
+    psMetadata *updates = psMetadataLookupMetadata (&status, fpa->analysis, "PSASTRO.HEADER");
+    if (!updates) {
+        updates = psMetadataAlloc ();
+        psMetadataAddMetadata (fpa->analysis, PS_LIST_TAIL, "PSASTRO.HEADER",  PS_META_REPLACE, "psastro header stats", updates);
+        psFree (updates);
+    }
+
+    if (!pmAstromWriteBilevelMosaic (updates, astrom->fpa, NONLIN_TOL)) {
+	// error here is a data quality problem (and too bad to write smf)
+	psWarning ("Failed to save header terms");
+	if (stats && psMetadataLookupS32(NULL, stats, "QUALITY") == 0) {
+	    psMetadataAddS32(stats, PS_LIST_TAIL, "QUALITY", PS_META_REPLACE, "Mosaic astrometry failed", FPCAMERA_ERR_DATA);
+	}
+	return false;
+    }
+    return true;
+}
Index: /trunk/fpcamera/src/fpcameraChooseRefstars.c
===================================================================
--- /trunk/fpcamera/src/fpcameraChooseRefstars.c	(revision 42385)
+++ /trunk/fpcamera/src/fpcameraChooseRefstars.c	(revision 42385)
@@ -0,0 +1,206 @@
+# include "fpcamera.h"
+
+# define ESCAPE(ERROR, MSG) { psErrorStackPrint(stderr, MSG); return false; }
+
+bool fpcameraMarkStar (pmReadout *readout, float Xo, float Yo);
+bool fpcameraMakeSources (pmReadout *readout, psArray *refstars);
+
+/* \brief this function loops over chips and performs forced photometry for the references */
+bool fpcameraChooseRefstars (pmFPAfile *input, pmFPAfile *astrom, pmFPAview *view) {
+
+    // the astrometry FPA and Chip store the references and the astrometric info
+    pmFPA *astromFPA = astrom->fpa;
+    pmChip *astromChip = pmFPAviewThisChip(view, astromFPA);
+    pmReadout *readout = pmFPAviewThisReadout(view, input->fpa);
+
+    // use the ra,dec range of the chip to make an initial cut before
+    // transforming the positions to x,y.  Note the reference coordinates (refs->sky->r,d) are
+    // stored in radians, so compare in radians
+    float rMin = RAD_DEG*psMetadataLookupF32 (NULL, astromChip->analysis, "RA_MIN");
+    float rMax = RAD_DEG*psMetadataLookupF32 (NULL, astromChip->analysis, "RA_MAX");
+    float dMin = RAD_DEG*psMetadataLookupF32 (NULL, astromChip->analysis, "DEC_MIN");
+    float dMax = RAD_DEG*psMetadataLookupF32 (NULL, astromChip->analysis, "DEC_MAX");
+
+    // the full set of references is saved on the analysis MD of the astrometry FPA structure
+    psArray *allrefs = psMetadataLookupPtr (NULL, astromFPA->analysis, "FPCAMERA.REFSTARS");
+
+    // XXX is the astrom readout extent the same as the input readout?
+    psRegion *extent = pmReadoutExtent (readout);
+    if (!extent) ESCAPE(FPCAMERA_ERR_CONFIG, "Can't find readout size!");
+
+    // full pixel range of the chip
+    float minX = extent->x0;
+    float maxX = extent->x1;
+    float minY = extent->y0;
+    float maxY = extent->y1;
+    psFree (extent);
+
+    // the refstars is a subset within range of this chip
+    psArray *refstars = psArrayAllocEmpty (100);
+
+    // select the reference objects within range of this readout
+    // project the reference objects to this chip
+    for (int i = 0; i < allrefs->n; i++) {
+
+	pmAstromObj *ref = allrefs->data[i];
+	
+	if (ref->sky->r < rMin) continue;
+	if (ref->sky->r > rMax) continue;
+	if (ref->sky->d < dMin) continue;
+	if (ref->sky->d > dMax) continue;
+
+	// use the astrometry source to transform to chip coordinates
+	psProject (ref->TP, ref->sky, astromFPA->toSky);
+	psPlaneTransformApply (ref->FP, astromFPA->fromTPA, ref->TP);
+	psPlaneTransformApply (ref->chip, astromChip->fromFPA, ref->FP);
+
+	// limit the X,Y range of the refs to the selected chip
+	if (ref->chip->x < minX) continue;
+	if (ref->chip->x > maxX) continue;
+	if (ref->chip->y < minY) continue;
+	if (ref->chip->y > maxY) continue;
+
+	// XXX mark the location of the refstars with a small box
+	// fpcameraMarkStar (readout, ref->chip->x, ref->chip->y);
+
+	psArrayAdd (refstars, 100, ref);
+    }
+
+    fpcameraMakeSources (readout, refstars);
+
+    const char *chipName = psMetadataLookupStr(NULL, astromChip->concepts, "CHIP.NAME");
+
+    psLogMsg ("fpcamera", 3, "Extracted %d reference stars for chip %s\n", (int) refstars->n, chipName);
+    psFree (refstars);
+    
+    return true;
+}
+
+bool fpcameraMarkStar (pmReadout *readout, float Xo, float Yo) {
+
+    psImage *image = readout->image;
+
+    int nX = image->numCols;
+    int nY = image->numRows;
+
+    int xS = PS_MIN(PS_MAX(Xo - 5, 0), nX - 1);
+    int xE = PS_MIN(PS_MAX(Xo + 5, 0), nX - 1);
+    int yS = PS_MIN(PS_MAX(Yo - 5, 0), nY - 1);
+    int yE = PS_MIN(PS_MAX(Yo + 5, 0), nY - 1);
+
+    for (int ix = xS; ix <= xE; ix++) {
+	for (int iy = yS; iy <= yE; iy++) {
+
+	    float value = image->data.F32[iy][ix];
+	    value = value * 0.5;
+	    image->data.F32[iy][ix] = value;
+	}
+    }
+    return true;
+}
+
+bool fpcameraMakeSources (pmReadout *readout, psArray *refstars) {
+
+    // generate pmDetections to carry the sources
+    pmDetections *detections = pmDetectionsAlloc();
+    detections->allSources   = psArrayAllocEmpty (100);
+    detections->newSources   = psArrayAllocEmpty (100);
+
+    bool status = psMetadataAddPtr (readout->analysis, PS_LIST_TAIL, "PSPHOT.DETECTIONS", PS_META_REPLACE | PS_DATA_UNKNOWN, "psphot detections", detections);
+    if (!status) ESCAPE(FPCAMERA_ERR_CONFIG, "problem saving detections on readout");
+
+    // define PSF model type
+    // int modelType = pmModelClassGetType ("PS_MODEL_GAUSS");
+
+    // for now, just use a PSF model (add EXT model later, see pmSourceIO_CFF.c)
+
+    for (int i = 0; i < refstars->n; i++) { 
+
+	pmAstromObj *ref = refstars->data[i];
+	
+	float Xraw = ref->chip->x;
+	float Yraw = ref->chip->y;
+
+	// pixel coordinate in the image
+	int Xoff = Xraw - readout->image->row0 - 0.5;
+	int Yoff = Yraw - readout->image->col0 - 0.5;
+
+	// create a new source
+	pmSource *source = pmSourceAlloc();
+
+	source->seq       = i;
+	source->imageID   = 0;
+	source->type      = PM_SOURCE_TYPE_UNKNOWN; // RoughClass wants source type to be unknown
+	source->type      = PM_SOURCE_TYPE_STAR;    // until we know more, assume a PSF fit
+	source->mode     |= PM_SOURCE_MODE_EXTERNAL;
+	source->mode2    |= PM_SOURCE_MODE2_MATCHED; // source is generated based on another image
+	source->tmpFlags  = 0;
+	source->tmpFlags |= PM_SOURCE_TMPF_CANDIDATE_PSFSTAR; // XXX choose good PSF stars
+
+	source->sky    = 0.0;
+	source->skyErr = 0.0;
+	
+	source->psfMag    = 0.0;
+	source->psfMagErr = 0.0;
+	source->apMag     = 0.0;
+	source->apRadius  = 0.0;
+
+	// The peak type is not used in psphot. PM_PEAK_LONE may be wrong, but irrelevant
+	// the supplied peak flux needs to be re-normalized
+	float peakFlux = readout->image->data.F32[Yoff][Xoff];
+	source->peak     = pmPeakAlloc(Xraw, Yraw, peakFlux, PM_PEAK_LONE);
+	source->peak->xf = Xraw;
+	source->peak->yf = Yraw;
+	source->peak->dx = 0.0;
+	source->peak->dy = 0.0;
+	source->peak->rawFlux    = 1.0;
+	source->peak->smoothFlux = 1.0;
+	source->peak->detValue   = 1.0;
+
+	// allocate space for moments
+	source->moments = pmMomentsAlloc();
+	source->moments->Mx = Xraw;
+	source->moments->My = Yraw;
+	source->moments->Mrf = 5; // kronRadius is 2.5 * first radial moment
+	
+	// allocate image, weight, mask arrays for each peak (square of radius OUTER)
+	// XXX how does this happen? pmSourceDefinePixels (source, readout, source->peak->x, source->peak->y, OUTER);
+	
+	// XXX not clear we need to define a model here
+# if (0)
+	pmModel *model = pmModelAlloc (modelType);
+	source->modelPSF  = model;
+
+	// NOTE: A SEGV here because "model" is NULL is probably caused by not initialising the models.
+	psF32 *PAR = model->params->data.F32;
+	psF32 *dPAR = model->dparams->data.F32;
+
+	PAR[PM_PAR_XPOS]  = Xraw;
+	PAR[PM_PAR_YPOS]  = Yraw;
+	
+	dPAR[PM_PAR_XPOS] = 0.0;
+	dPAR[PM_PAR_YPOS] = 0.0;
+	
+	PAR[PM_PAR_SKY]   = 0.0;
+	dPAR[PM_PAR_SKY]  = 0.0;
+	
+	PAR[PM_PAR_I0]    = 1.0;
+	dPAR[PM_PAR_I0]   = 0.0;
+	
+	// we generate a somewhat fake PSF model here -- 
+	// in most (all?) contexts, we will replace this with a measured psf model
+	// elsewhere
+	psEllipseAxes axes;
+	axes.major        = 1.0;
+	axes.minor        = 1.0;
+	axes.theta        = 0.0;
+	pmPSF_AxesToModel (PAR, axes, model->class->useReff);
+# endif
+
+	psArrayAdd (detections->allSources, 100, source);
+	psFree (source);
+    }
+    psFree (detections); // we have placed a reference on readout->analysis so we must free this copy
+    return true;
+}
+
Index: /trunk/fpcamera/src/fpcameraCleanup.c
===================================================================
--- /trunk/fpcamera/src/fpcameraCleanup.c	(revision 42385)
+++ /trunk/fpcamera/src/fpcameraCleanup.c	(revision 42385)
@@ -0,0 +1,26 @@
+# include "fpcamera.h"
+
+/* \brief this loop saves the photometry/astrometry data files */
+void fpcameraCleanup (pmConfig *config, psMetadata *stats) {
+
+    psMemCheckCorruption (stderr, true);
+
+    psFree (stats);
+    psFree (config);
+    pmVisualClose ();
+    pmVisualCleanup ();
+
+    psTimerStop ();
+    psphotVisualClose();
+
+    pmModelClassCleanup ();
+    psTimeFinalize ();
+    pmConceptsDone ();
+    pmConfigDone ();
+
+    pmSourceFitSetDone ();
+    psLibFinalize();
+
+    fprintf (stderr, "found %d leaks at %s\n", psMemCheckLeaks (0, NULL, stdout, false), "fpcamera");
+    return;
+}
Index: /trunk/fpcamera/src/fpcameraDataLoad.c
===================================================================
--- /trunk/fpcamera/src/fpcameraDataLoad.c	(revision 42385)
+++ /trunk/fpcamera/src/fpcameraDataLoad.c	(revision 42385)
@@ -0,0 +1,24 @@
+# include "fpcamera.h"
+
+# define ESCAPE(ERROR,MSG) { psError(ERROR, false, MSG); return false; }
+  
+/*\brief this loop loads the data from the input files */
+
+bool fpcameraDataLoad (pmConfig *config) {
+
+    psTimerStart ("fpcamera");
+
+    // select the input data sources
+    pmFPAfile *input = psMetadataLookupPtr (NULL, config->files, "FPCAMERA.INPUT.ASTROM");
+    if (!input) ESCAPE (PS_ERR_UNKNOWN, "FPCAMERA.INPUT.ASTROM not listed in config->files");
+
+    // read the astrometry calibration information (from cmf/smf)
+    if (!fpcameraReadAstrometry (input, config)) ESCAPE (PS_ERR_UNKNOWN, "Failure to read astrometry calibration");
+
+    // load the reference stars overlapping the data stars
+    if (!fpcameraLoadRefstars(input, config)) ESCAPE (PS_ERR_UNKNOWN, "failed to load reference data");
+
+    psLogMsg ("fpcamera", 3, "load data : %f sec\n", psTimerMark ("fpcamera"));
+
+    return true;
+}
Index: /trunk/fpcamera/src/fpcameraDataSave.c
===================================================================
--- /trunk/fpcamera/src/fpcameraDataSave.c	(revision 42385)
+++ /trunk/fpcamera/src/fpcameraDataSave.c	(revision 42385)
@@ -0,0 +1,79 @@
+# include "fpcamera.h"
+
+# define ESCAPE(ERROR, MSG) { psErrorStackPrint(stderr, MSG); psFree (view); return false; }
+
+/* \brief this loop saves the photometry/astrometry data files */
+bool fpcameraDataSave (pmConfig *config, psMetadata *stats) {
+
+    bool status;
+    pmChip *chip;
+    pmCell *cell;
+    pmReadout *readout;
+    pmFPAview *view = NULL;
+
+    // select the current recipe
+    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, FPCAMERA_RECIPE);
+    if (!recipe) ESCAPE (FPCAMERA_ERR_CONFIG, "Can't find FPCAMERA recipe");
+
+    // select the output data sources
+    pmFPAfile *output = psMetadataLookupPtr (NULL, config->files, "FPCAMERA.OUTPUT");
+    if (!output) ESCAPE(FPCAMERA_ERR_CONFIG, "Can't find or interpret output file rule FPCAMERA.OUTPUT!");
+
+    // de-activate all files except FPCAMERA.OUTPUT
+    pmFPAfileActivate (config->files, false, NULL);
+    pmFPAfileActivate (config->files, true, "FPCAMERA.OUTPUT");
+    pmFPAfileActivate (config->files, true, "FPCAMERA.INPUT.ASTROM");
+    // Note: I/O for the image-type files is performed in fpcameraAnalysis
+
+    view = pmFPAviewAlloc (0);
+
+    // open/load files as needed
+    if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE(FPCAMERA_ERR_IO, "failure to save at FPA");
+
+    pmHDU *lastHDU = NULL;              // Last HDU updated
+    while ((chip = pmFPAviewNextChip (view, output->fpa, 1)) != NULL) {
+        psTrace ("fpcamera", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+        if (!chip->process || !chip->file_exists) { continue; }
+        if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE(FPCAMERA_ERR_IO, "failure to save at Chip");
+
+        while ((cell = pmFPAviewNextCell (view, output->fpa, 1)) != NULL) {
+            psTrace ("fpcamera", 4, "Cell %d: %x %x\n", view->cell, cell->file_exists, cell->process);
+            if (!cell->process || !cell->file_exists) { continue; }
+            if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE(FPCAMERA_ERR_IO, "failure to save at Cell");
+
+            // process each of the readouts
+            while ((readout = pmFPAviewNextReadout (view, output->fpa, 1)) != NULL) {
+                if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE(FPCAMERA_ERR_IO, "failure in IOChecks(BEFORE) at Readout");
+                if (!readout->data_exists) { continue; }
+
+                // Put version information into the header
+                pmHDU *hdu = pmHDUGetHighest(output->fpa, chip, cell);
+                if (hdu && hdu != lastHDU) {
+                    fpcameraVersionHeaderFull(hdu->header);
+		    // Append the reference catalog to the header as well.
+		    char *catdir = psMetadataLookupStr(NULL,recipe,"FPCAMERA.CATDIR");
+		    psMetadataAddStr(hdu->header,PS_LIST_TAIL, "PSREFCAT", PS_META_REPLACE, NULL, catdir);
+                    lastHDU = hdu;
+                }
+                if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE(FPCAMERA_ERR_IO, "failure in IOChecks(AFTER) at Readout");
+            }
+            if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE(FPCAMERA_ERR_IO, "failure in IOChecks(AFTER) at Cell");
+        }
+        if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE(FPCAMERA_ERR_IO, "failure in IOChecks(AFTER) at Chip");
+    }
+    if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE(FPCAMERA_ERR_IO, "failure in IOChecks(AFTER) at FPA");
+
+    // Write out summary statistics
+    if (!fpcameraMetadataStats (config, stats)) ESCAPE(FPCAMERA_ERR_UNKNOWN, "failure to save state in Metadata");
+
+    psString dump_file = psMetadataLookupStr(&status, config->arguments, "DUMP_CONFIG");
+    if (dump_file) {
+        pmConfigCamerasCull(config, NULL);
+        pmConfigRecipesCull(config, "PPIMAGE,PPSTATS,PSPHOT,MASKS,FPCAMERA");
+
+        if (!pmConfigDump(config, dump_file)) ESCAPE(FPCAMERA_ERR_IO, "Unable to dump configuration.");
+    }
+
+    psFree (view);
+    return true;
+}
Index: /trunk/fpcamera/src/fpcameraDefineFiles.c
===================================================================
--- /trunk/fpcamera/src/fpcameraDefineFiles.c	(revision 42385)
+++ /trunk/fpcamera/src/fpcameraDefineFiles.c	(revision 42385)
@@ -0,0 +1,11 @@
+# include "fpcamera.h"
+
+bool fpcameraDefineFiles (pmConfig *config, pmFPAfile *input) {
+
+    // these calls bind the I/O handle to the specified fpa
+    bool status;
+
+    return true;
+}
+
+
Index: /trunk/fpcamera/src/fpcameraErrorCodes.c.in
===================================================================
--- /trunk/fpcamera/src/fpcameraErrorCodes.c.in	(revision 42385)
+++ /trunk/fpcamera/src/fpcameraErrorCodes.c.in	(revision 42385)
@@ -0,0 +1,37 @@
+/** @file fpcameraErrorCodes.c
+ *
+ *  @brief
+ *
+ *  @ingroup fpcamera
+ *
+ *  @author IfA
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2009-02-07 02:03:34 $
+ *  Copyright 2009 Institute for Astronomy, University of Hawaii
+ */
+
+#include "pslib.h"
+#include "fpcameraErrorCodes.h"
+
+/*
+ * The line
+    { FPCAMERA_ERR_$X{ErrorCode}, "$X{ErrorDescription}"},
+ * (without the Xs)
+ * will be replaced by values from errorCodes.dat
+ */
+void fpcameraErrorRegister(void)
+{
+    static psErrorDescription errors[] = {
+       { FPCAMERA_ERR_BASE, "First value we use; lower values belong to psLib" },
+       { FPCAMERA_ERR_${ErrorCode}, "${ErrorDescription}"},
+    };
+    static int nerror = FPCAMERA_ERR_NERROR - FPCAMERA_ERR_BASE; // number of values in enum
+
+    for (int i = 0; i < nerror; i++) {
+       psErrorDescription *tmp = psAlloc(sizeof(psErrorDescription));
+       *tmp = errors[i];
+       psErrorRegister(tmp, 1);
+       psFree(tmp);			/* it's on the internal list */
+    }
+    nerror = 0;			                // don't register more than once
+}
Index: /trunk/fpcamera/src/fpcameraErrorCodes.dat
===================================================================
--- /trunk/fpcamera/src/fpcameraErrorCodes.dat	(revision 42385)
+++ /trunk/fpcamera/src/fpcameraErrorCodes.dat	(revision 42385)
@@ -0,0 +1,12 @@
+#
+# This file is used to generate pmErrorClasses.h
+#
+BASE = 4500		First value we use; lower values belong to psLib
+UNKNOWN			Unknown fpcamera error code
+NOT_IMPLEMENTED		Desired feature is not yet implemented
+ARGUMENTS		Incorrect arguments
+CONFIG			Problem in configure files
+IO			Problem in FITS I/O
+WCS      		Error interpreting FITS WCS information
+DATA                    Problem in data values
+REFSTARS                Problem in data values
Index: /trunk/fpcamera/src/fpcameraErrorCodes.h
===================================================================
--- /trunk/fpcamera/src/fpcameraErrorCodes.h	(revision 42385)
+++ /trunk/fpcamera/src/fpcameraErrorCodes.h	(revision 42385)
@@ -0,0 +1,37 @@
+/** @file fpcameraErrorCodes.h
+ *
+ *  @brief
+ *
+ *  @ingroup fpcamera
+ *
+ *  @author IfA
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2009-02-07 02:03:34 $
+ *  Copyright 2009 Institute for Astronomy, University of Hawaii
+ */
+
+#if !defined(FPCAMERA_ERROR_CODES_H)
+#define FPCAMERA_ERROR_CODES_H
+/*
+ * The line
+ *  FPCAMERA_ERR_$X{ErrorCode},
+ * (without the X)
+ *
+ * will be replaced by values from errorCodes.dat
+ */
+typedef enum {
+    FPCAMERA_ERR_BASE = 4500,
+    FPCAMERA_ERR_UNKNOWN,
+    FPCAMERA_ERR_NOT_IMPLEMENTED,
+    FPCAMERA_ERR_ARGUMENTS,
+    FPCAMERA_ERR_CONFIG,
+    FPCAMERA_ERR_IO,
+    FPCAMERA_ERR_WCS,
+    FPCAMERA_ERR_DATA,
+    FPCAMERA_ERR_REFSTARS,
+    FPCAMERA_ERR_NERROR
+} fpcameraErrorCode;
+
+void fpcameraErrorRegister(void);
+
+#endif
Index: /trunk/fpcamera/src/fpcameraErrorCodes.h.in
===================================================================
--- /trunk/fpcamera/src/fpcameraErrorCodes.h.in	(revision 42385)
+++ /trunk/fpcamera/src/fpcameraErrorCodes.h.in	(revision 42385)
@@ -0,0 +1,30 @@
+/** @file fpcameraErrorCodes.h
+ *
+ *  @brief
+ *
+ *  @ingroup fpcamera
+ *
+ *  @author IfA
+ *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2009-02-07 02:03:34 $
+ *  Copyright 2009 Institute for Astronomy, University of Hawaii
+ */
+
+#if !defined(FPCAMERA_ERROR_CODES_H)
+#define FPCAMERA_ERROR_CODES_H
+/*
+ * The line
+ *  FPCAMERA_ERR_$X{ErrorCode},
+ * (without the X)
+ *
+ * will be replaced by values from errorCodes.dat
+ */
+typedef enum {
+    FPCAMERA_ERR_BASE = 4500,
+    FPCAMERA_ERR_${ErrorCode},
+    FPCAMERA_ERR_NERROR
+} fpcameraErrorCode;
+
+void fpcameraErrorRegister(void);
+
+#endif
Index: /trunk/fpcamera/src/fpcameraLoadRefstars.c
===================================================================
--- /trunk/fpcamera/src/fpcameraLoadRefstars.c	(revision 42385)
+++ /trunk/fpcamera/src/fpcameraLoadRefstars.c	(revision 42385)
@@ -0,0 +1,199 @@
+# include "fpcamera.h"
+
+# define ESCAPE(ERROR,...) { p_psError(__FILE__,__LINE__,__func__,ERROR,false,__VA_ARGS__); return false; }
+
+/* \brief this loop saves the photometry/astrometry data files */
+bool fpcameraLoadRefstars (pmFPAfile *input, pmConfig *config) {
+
+    int fd;
+    bool status;
+
+    // select the current recipe
+    psMetadata *recipe  = psMetadataLookupPtr (NULL, config->recipes, FPCAMERA_RECIPE);
+
+    // FPA FOV is determined by fpcameraReadAstrometry & save on fpa->analysis
+    float RAmin  = psMetadataLookupF32(NULL, input->fpa->analysis, "RA_MIN");
+    float RAmax  = psMetadataLookupF32(NULL, input->fpa->analysis, "RA_MAX");
+    float DECmin = psMetadataLookupF32(NULL, input->fpa->analysis, "DEC_MIN");
+    float DECmax = psMetadataLookupF32(NULL, input->fpa->analysis, "DEC_MAX");
+
+    // extra field fraction to add
+    double fieldPadding = psMetadataLookupF32 (&status, recipe, "FPCAMERA.FIELD.PADDING");
+    if (!status) ESCAPE(FPCAMERA_ERR_CONFIG, "missing FPCAMERA.FIELD.PADDING in recipe");
+
+    float dRA = RAmax - RAmin;
+    if (dRA * (1. + 2 * fieldPadding) < 180.) {
+        RAmin -= dRA * fieldPadding;
+        RAmax += dRA * fieldPadding;
+    } else {
+        // if dRA > 180 getstar has problems. Just search the entire range
+        RAmin = 0;
+        RAmax = 360;
+    }
+
+    float dDEC = DECmax - DECmin;
+    DECmin -= dDEC * fieldPadding;
+    DECmax += dDEC * fieldPadding;
+
+    // grab the FPCAMERA.CATDIR name from the FPCAMERA recipe
+    char *catdir_recipe = psMetadataLookupStr(&status, recipe, "FPCAMERA.CATDIR");
+    if (!catdir_recipe) ESCAPE(FPCAMERA_ERR_CONFIG, "Need a recipe for the catdir!");
+
+    // *** substitute abstract name with concrete name, if present in FPCAMERA.CATDIRS ***
+
+    // the name in the recipe may be one of:
+    // (A) the actual directory name
+    // (B) a reference to the name in the FPCAMERA.CATDIRS folder in site.config
+    // (C) a reference to a folder in the FPCAMERA.CATDIRS folder in site.config, containing multiple copy locations
+
+    // Folder in site.config containing a list of FPCAMERA.CATDIR entries.
+    // NOTE: it is allowed that FPCAMERA.CATDIRS not be defined in site.config: then FPCAMERA.CATDIR must be a real path
+    psMetadata *catdirs = psMetadataLookupMetadata(&status, config->site, "FPCAMERA.CATDIRS"); // List of cameras
+
+    // can we find a plain string matching catdir_recipe in the catdirs folder?
+    char *catdir_virtual = catdirs ? psMetadataLookupStr(&status, catdirs, catdir_recipe) : NULL;
+
+    // OR, can we find a subfolder in the catdirs folder?
+    psMetadata *catdir_folder = catdirs ? psMetadataLookupMetadata(&status, catdirs, catdir_recipe) : NULL;
+    if (catdir_folder) {
+        // randomly choose one of the entries
+        psLogMsg ("fpcamera", 3, "choosing catdir_folder\n");
+        int nEntry = catdir_folder->list->n;
+
+        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS);
+        double frnd = psRandomUniform(rng);
+        int entry = PS_MIN(nEntry - 1, PS_MAX(0, nEntry * frnd));
+        psFree(rng);
+
+        psMetadataItem *item = psListGet(catdir_folder->list, entry);
+	psAssert (item, "programming error? no valid entry?");
+
+        if (item->type != PS_DATA_STRING) ESCAPE(FPCAMERA_ERR_CONFIG, "Invalid entry in FPCAMERA.CATDIR folder: %s\n", item->name);
+        catdir_virtual = item->data.str;
+    }
+
+    // if catdir_virtual is NULL, catdir_recipe must be a file name
+    char *catdir = (catdir_virtual == NULL) ? catdir_recipe : catdir_virtual;
+
+    // convert the uri to a real filename (ie, path://foobar)
+    psString CATDIR = pmConfigConvertFilename(catdir, config, false, false); // Resolved filename
+    if (!CATDIR) ESCAPE(FPCAMERA_ERR_CONFIG, "unable to determine filename for CATDIR %s", catdir);
+
+    psLogMsg ("fpcamera", 3, "looking up reference objects in %s\n", CATDIR);
+
+    char *getstarCommand = psStringCopy(psMetadataLookupStr(NULL, recipe, "DVO.GETSTAR"));
+    if (!getstarCommand) ESCAPE(FPCAMERA_ERR_CONFIG, "unable to find DVO.GETSTAR in recipe");
+
+    char *outformat = psMetadataLookupStr(NULL, recipe, "DVO.GETSTAR.OUTFORMAT");
+    if (!outformat) ESCAPE(FPCAMERA_ERR_CONFIG, "unable to find DVO.GETSTAR.OUTFORMAT in recipe");
+
+    // issue the following command:
+    // getstar -region RAmin RAmax DECmin DECmax
+    char tempFile[64];
+    sprintf (tempFile, "/tmp/fpcamera.XXXXXX");
+    if ((fd = mkstemp (tempFile)) == -1) {
+        psFree(CATDIR);
+	ESCAPE(FPCAMERA_ERR_IO, "error creating temp output file for getstar");
+    }
+    close (fd);
+
+    psTimerStart ("fpcamera");
+
+    // supply a known output format (for CATALOG output) so the code below knows what to read
+    // XXX I do not think this affects the getstar command (CATFORMAT is used to define the dvo db format)
+    // if (ELIXIR_MODE) {
+    //     psStringAppend (&getstarCommand, " -D CATMODE mef -D CATFORMAT elixir");
+    // } else {
+    //     psStringAppend (&getstarCommand, " -D CATMODE mef -D CATFORMAT panstarrs");
+    // }
+
+    // Define the full getstar command.  Above, we require CATDIR to be valid and defined at
+    // this point.  Also add region and output filename.
+    psStringAppend (&getstarCommand, " -D CATDIR %s", CATDIR);
+    psStringAppend (&getstarCommand, " -format %s", outformat);
+    psStringAppend (&getstarCommand, " -region %f %f %f %f -o %s", RAmin, DECmin, RAmax, DECmax, tempFile);
+
+    psFree(CATDIR);
+
+    psLogMsg("fpcamera", PS_LOG_INFO, "getstar command: %s", getstarCommand);
+
+    // run getstar, result is saved in the temp file
+    status = system (getstarCommand);
+    if (status) ESCAPE(FPCAMERA_ERR_REFSTARS, "error loading reference data");
+    psFree (getstarCommand);
+
+    psLogMsg ("fpcamera", 3, "ran getstar : %f sec\n", psTimerMark ("fpcamera"));
+
+    // the output from getstar is a file with the Average table
+    psFits *fits = psFitsOpen (tempFile, "r");
+
+    psTimerStart ("fpcamera");
+
+    psArray *refstars = NULL;
+    if (!strcmp (outformat, "PS1_DEV_0")) {
+      refstars = fpcameraReadGetstar_PS1_DEV_0 (fits);
+    }
+    if (!refstars) {
+        psFitsClose (fits);
+        ESCAPE(FPCAMERA_ERR_REFSTARS, "error reading reference data");
+    }
+    if (refstars->n == 0) ESCAPE(FPCAMERA_ERR_REFSTARS, "no reference stars found");
+
+    psLogMsg ("fpcamera", 3, "loaded %ld reference stars : %f sec\n", refstars->n, psTimerMark ("fpcamera"));
+
+    psTrace ("fpcamera", 3, "loaded %ld reference stars from (%10.6f,%10.6f) - (%10.6f,%10.6f)\n",
+             refstars->n, RAmin, DECmin, RAmax, DECmax);
+
+    psFitsClose (fits);
+    unlink (tempFile);
+
+    psMetadataAdd (input->fpa->analysis, PS_LIST_TAIL, "FPCAMERA.REFSTARS", PS_DATA_ARRAY, "reference sources", refstars);
+    psFree (refstars);
+
+    return true;
+}
+
+// method to read PS1_DEV_0 format
+// Note other options can be found in psastroLoadRefstars.c
+psArray *fpcameraReadGetstar_PS1_DEV_0 (psFits *fits) {
+
+    bool status;
+
+    psFitsMoveExtName (fits, "GETSTAR_PS1_DEV_0");
+
+    long numSources = psFitsTableSize(fits); // Number of sources in table
+
+    // convert the Average table to the pmAstromObj entries
+    psArray *refstars = psArrayAllocEmpty (numSources);
+    for (int i = 0; i < numSources; i++) {
+        pmAstromObj *ref = pmAstromObjAlloc ();
+
+        psMetadata *row = psFitsReadTableRow(fits, i); // Table row
+
+        ref->sky->r   = RAD_DEG*psMetadataLookupF64 (&status, row, "RA");
+        ref->sky->d   = RAD_DEG*psMetadataLookupF64 (&status, row, "DEC");
+        ref->Mag      = psMetadataLookupF32 (&status, row, "MAG");
+        float MagC1   = psMetadataLookupF32 (&status, row, "MAG_C1");
+        float MagC2   = psMetadataLookupF32 (&status, row, "MAG_C2");
+        if (!isnan(MagC1) && !isnan(MagC2)) {
+            ref->Color = MagC1 - MagC2;
+        } else {
+            ref->Color = 0.0;
+        }
+	ref->magCal   = ref->Mag;
+
+        // XXX VERY temporary hack to avoid M31 bulge
+        if ((fabs(ref->sky->r - 0.186438) < 0.002) && (fabs(ref->sky->d - 0.720270) < 0.002)) {
+          psFree (ref);
+          psFree (row);
+          continue;
+        }
+
+        psArrayAdd (refstars, 100, ref);
+        psFree (ref);
+        psFree (row);
+    }
+    return refstars;
+}
+
+
Index: /trunk/fpcamera/src/fpcameraMetadataStats.c
===================================================================
--- /trunk/fpcamera/src/fpcameraMetadataStats.c	(revision 42385)
+++ /trunk/fpcamera/src/fpcameraMetadataStats.c	(revision 42385)
@@ -0,0 +1,59 @@
+# include "fpcamera.h"
+
+# define ESCAPE(ERROR,...) { p_psError(__FILE__,__LINE__,__func__,ERROR,false,__VA_ARGS__); psFree (statsMDC); psFree(view); psFree(resolved); return false; }
+
+bool fpcameraMetadataStats (pmConfig *config, psMetadata *stats) {
+
+    bool status;
+    char *statsMDC = NULL;
+    pmFPAview *view = NULL;
+    psString resolved = NULL;
+
+    char *filename = psMetadataLookupStr (&status, config->arguments, "STATS");
+    if (!filename) return true; // stats not requested
+
+    // Extract statistics from the output fpa
+    pmFPAfile *output = psMetadataLookupPtr(&status, config->files, "FPCAMERA.OUTPUT");
+    if (!output) ESCAPE (PS_ERR_UNEXPECTED_NULL, "Unable to find output file (FPCAMERA.OUTPUT).");
+
+    // extract stats for the complete fpa
+    view = pmFPAviewAlloc(0);
+
+    // Entries in the FPCAMERA.HEADER in the FPA don't get seen by ppStats
+    psMetadata *header = psMetadataLookupMetadata(&status, output->fpa->analysis, "FPCAMERA.HEADER");
+    if (status && header) {
+        psMetadataItemSupplement(&status, stats, header, "ZPT_OBS"); // XXX not yet calculated
+        psMetadataItemSupplement(&status, stats, header, "ZPT_ERR");
+    }
+
+    if (!ppStatsMetadata(stats, output->fpa, view, 0, config)) ESCAPE (PS_ERR_UNEXPECTED_NULL, "Unable to generate stats for image.");
+
+    // if we did not request any specific stats, the structure is empty
+    if (stats && stats->list->n == 0) {
+        psWarning ("stats output specified, but no requested stats entries in headers");
+        return true;
+    }
+
+    // convert the stats MDC to a string
+    statsMDC = psMetadataConfigFormat(stats);
+    if (!statsMDC || strlen(statsMDC) == 0) ESCAPE(PS_ERR_IO, "Unable to serialize stats metadata.\n");
+
+    // convert to a real UNIX filename
+    resolved = pmConfigConvertFilename(filename, config, true, false); // Resolved filename
+    if (!resolved) ESCAPE(psErrorCodeLast(), "Unable to resolve statistics filename: %s", filename);
+
+    FILE *statsFile = fopen (resolved, "w");
+    if (!statsFile) ESCAPE (PS_ERR_IO, "Unable to open statistics file %s for writing.\n", resolved);
+
+    // write the stats MDC to a file
+    if (fprintf(statsFile, "%s", statsMDC) != strlen(statsMDC)) ESCAPE (PS_ERR_IO, "Unable to write statistics file %s", resolved);
+    if (fclose(statsFile) == EOF) ESCAPE (PS_ERR_IO, "Unable to write statistics file %s", resolved);
+
+    pmConfigRunFilenameAddWrite(config, "STATS", filename);
+
+    psFree(resolved);
+    psFree(statsMDC);
+    psFree(view);
+
+    return true;
+}
Index: /trunk/fpcamera/src/fpcameraParseCamera.c
===================================================================
--- /trunk/fpcamera/src/fpcameraParseCamera.c	(revision 42385)
+++ /trunk/fpcamera/src/fpcameraParseCamera.c	(revision 42385)
@@ -0,0 +1,72 @@
+# include "fpcamera.h"
+
+# define ESCAPE(ERROR,...) { p_psError(__FILE__,__LINE__,__func__,ERROR,false,__VA_ARGS__); return false; }
+
+bool fpcameraParseCamera (pmConfig *config) {
+
+    bool status = false;
+
+    // the input image(s) are required arguments; they define the camera (or use the smf?)
+    pmFPAfile *input = pmFPAfileDefineFromArgs (&status, config, "FPCAMERA.INPUT", "INPUT");
+    if (!status) ESCAPE(FPCAMERA_ERR_CONFIG, "Failed to build FPA from FPCAMERA.INPUT");
+
+    // if MASK was supplied on command line, bind files to 'input'
+    pmFPAfileBindFromArgs (&status, input, config, "FPCAMERA.INPUT.MASK", "MASK");
+    if (!status) ESCAPE(PS_ERR_UNKNOWN, "failed to load find definition");
+
+    // if VARIANCE was supplied on command line, bind files to 'input'
+    pmFPAfileBindFromArgs (&status, input, config, "FPCAMERA.INPUT.VARIANCE", "VARIANCE");
+    if (!status) ESCAPE (PS_ERR_UNKNOWN, "failed to load find definition");
+
+    pmFPAfile *psphotInput = pmFPAfileDefineFromFile (config, input, 1, 1, "PSPHOT.INPUT");
+    if (!psphotInput) ESCAPE(FPCAMERA_ERR_CONFIG, "Failed to define FPA for PSPHOT.INPUT");
+
+    if (!psphotSetMaskBits (config)) ESCAPE (PS_ERR_UNKNOWN, "failed to set mask bit values");
+
+    // the input smf file is a required argument.  the smf file is distinct from the input
+    // chips (FPCAMERA.INPUT = input).  accept the return argument to set the selected
+    // chips in this pmFPAfile (as well as input)
+
+    pmFPAfile *astro = pmFPAfileDefineFromArgs (&status, config, "FPCAMERA.INPUT.ASTROM", "INPUT.ASTROM");
+    if (!status) ESCAPE(FPCAMERA_ERR_CONFIG, "Failed to build FPA from FPCAMERA.INPUT.ASTROM");
+
+    // if optional PSF model is supplied, associate with input file
+    if (psMetadataLookupPtr(NULL, config->arguments, "INPUT.PSF")) {
+        pmFPAfileBindFromArgs(&status, input, config, "PSPHOT.PSF.LOAD", "INPUT.PSF");
+        if (!status) ESCAPE(FPCAMERA_ERR_CONFIG, "Failed to find/build PSPHOT.PSF.LOAD");
+    }
+
+    // select the current recipe
+    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, FPCAMERA_RECIPE);
+    if (!recipe) ESCAPE(FPCAMERA_ERR_CONFIG, "Can't find FPCAMERA recipe!");
+
+    // associates the output pmFPA with the file OUTPUT on config->arguments
+    pmFPAfile *output = pmFPAfileDefineOutput (config, input->fpa, "FPCAMERA.OUTPUT");
+    if (!output) ESCAPE(FPCAMERA_ERR_CONFIG, "Failed to build OUTPUT FPA from FPCAMERA.INPUT");
+    output->save = true;
+
+    // optionally save the residual image
+    if (psMetadataLookupBool(&status, config->arguments, "SAVE.RESID")) {
+        pmFPAfile *output = pmFPAfileDefineOutputFromFile (config, input, "FPCAMERA.RESID");
+        if (!output) ESCAPE(FPCAMERA_ERR_CONFIG, "Cannot find a rule for FPCAMERA.RESID");
+        output->save = true;
+    }
+
+    // Chip selection: turn on only the chips specified (option is not required)
+    char *chipLine = psMetadataLookupStr(&status, config->arguments, "CHIP_SELECTIONS"); 
+    psArray *chips = psStringSplitArray (chipLine, ",", false);
+    if (chips->n > 0) {
+	pmFPASelectChip (input->fpa, -1, true); // deselect all chips
+	pmFPASelectChip (astro->fpa, -1, true); // deselect all chips
+	for (int i = 0; i < chips->n; i++) {
+	    int chipNum = atoi(chips->data[i]);
+	    if (! pmFPASelectChip(input->fpa, chipNum, false)) ESCAPE(FPCAMERA_ERR_CONFIG, "Chip number %d doesn't exist in input chip images.\n", chipNum);
+	    if (! pmFPASelectChip(astro->fpa, chipNum, false)) ESCAPE(FPCAMERA_ERR_CONFIG, "Chip number %d doesn't exist in astrometry file.\n", chipNum);
+        }
+    }
+    psFree (chips);
+
+    psTrace("fpcamera", 1, "Done with fpcameraParseCamera...\n");
+    return true;
+}
+
Index: /trunk/fpcamera/src/fpcameraReadAstrometry.c
===================================================================
--- /trunk/fpcamera/src/fpcameraReadAstrometry.c	(revision 42385)
+++ /trunk/fpcamera/src/fpcameraReadAstrometry.c	(revision 42385)
@@ -0,0 +1,132 @@
+# include "fpcamera.h"
+
+# define ESCAPE(ERROR, MSG) { psError(ERROR, false, MSG); psFree(view); return false; }
+
+/* \brief this function loads the astrometry calibration from the input smf file */
+bool fpcameraReadAstrometry (pmFPAfile *input, pmConfig *config) {
+
+    bool status;
+    pmChip *chip = NULL;
+    pmFPAview *view = NULL;
+
+    // select the current recipe (just needed for pixel scale)
+    // XXX this is defined in psastro.config : use that value instead of one defined in fpcamera.config?
+    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, FPCAMERA_RECIPE);
+    if (!recipe) ESCAPE(FPCAMERA_ERR_CONFIG, "Can't find FPCAMERA recipe!");
+
+    // physical pixel scale in microns per pixel (used in case of non-bilevel astrometry)
+    double pixelScale = psMetadataLookupF32 (&status, recipe, "FPCAMERA.PIXEL.SCALE");
+    if (!status) ESCAPE(PS_ERR_IO, "Failed to lookup pixel scale"); 
+
+    // de-activate all files except FPCAMERA.INPUT.ASTROM (where we get the astrometric calibration)
+    pmFPAfileActivate (config->files, false, NULL);
+    pmFPAfileActivate (config->files, true, "FPCAMERA.INPUT.ASTROM");
+
+    view = pmFPAviewAlloc (0);
+
+    // load headers for astrometry calibration
+    if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE(FPCAMERA_ERR_DATA, "failed to load header at FPA level");
+
+    // add in chip headers
+    while ((chip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
+        psTrace ("psastro", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+        if (!chip->process) { continue; }
+	if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE(FPCAMERA_ERR_DATA, "failed to load header at Chip level");
+    }
+    psLogMsg ("psastro", 3, "load headers : %f sec\n", psTimerMark ("psastro"));
+
+    // reset to loop over all chips:
+    pmFPAviewReset (view);
+
+    // check PHU header to see if we are using mosaic-level or per-chip astrometry
+    bool bilevelAstrometry = false;
+    pmHDU *phu = pmFPAviewThisPHU (view, input->fpa);
+    if (phu) {
+	char *ctype = psMetadataLookupStr (NULL, phu->header, "CTYPE1");
+	if (ctype) bilevelAstrometry = !strcmp (&ctype[4], "-DIS");
+    }
+    if (bilevelAstrometry) {
+	pmAstromReadBilevelMosaic (input->fpa, phu->header);
+    } 
+
+    // we need the min/max RA & DEC for each of the chips and for the entire FOV
+    double rMinFPA = +FLT_MAX;
+    double rMaxFPA = -FLT_MAX;
+    double dMinFPA = +FLT_MAX;
+    double dMaxFPA = -FLT_MAX;
+
+    while ((chip = pmFPAviewNextChip (view, input->fpa, 1)) != NULL) {
+	psTrace ("fpcamera", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process);
+	if (!chip->process || !chip->file_exists || !chip->data_exists) { continue; }
+
+	// read WCS data from the corresponding header
+	pmHDU *hdu = pmFPAviewThisHDU (view, input->fpa);
+	int nAstro = psMetadataLookupS32 (&status, hdu->header, "NASTRO");
+	if (!nAstro) continue;
+	// XXX use additional information to identify poor quality astrometry?
+
+	if (bilevelAstrometry) {
+	    if (!pmAstromReadBilevelChip (chip, hdu->header)) {
+		psWarning("Could not get WCS information from header for chip %d, skipping", view->chip); 
+		continue;
+	    } 
+	} else {
+	    if (!pmAstromReadWCS (input->fpa, chip, hdu->header, pixelScale)) {
+		psWarning("Could not get WCS information from header for chip %d, skipping", view->chip); 
+		continue;
+	    } 
+	}
+
+	// we need the min/max RA & DEC for each of the chips and for the entire FOV
+	double rMinChip = +FLT_MAX;
+	double rMaxChip = -FLT_MAX;
+	double dMinChip = +FLT_MAX;
+	double dMaxChip = -FLT_MAX;
+	
+	// this region defines the data area of the chip
+	psRegion *region = pmChipPixels (chip);
+	psPlane ptCH[4];
+	
+	// save the 4 corners
+	ptCH[0].x = region->x0; ptCH[0].y = region->y0;
+	ptCH[1].x = region->x1; ptCH[1].y = region->y0;
+	ptCH[2].x = region->x1; ptCH[2].y = region->y1;
+	ptCH[3].x = region->x0;	ptCH[3].y = region->y1;
+	psFree (region);
+	
+        // report and save the current best guess for the chip 0,0 pixel coordinates
+        for (int i = 0; i < 4; i++) {
+            psPlane ptFP, ptTP;
+            psSphere ptSky;
+
+	    // 4 corners
+            psPlaneTransformApply (&ptFP, chip->toFPA, &ptCH[i]);
+            psPlaneTransformApply (&ptTP, input->fpa->toTPA, &ptFP);
+            psDeproject (&ptSky, &ptTP, input->fpa->toSky);
+	    rMinChip = PS_MIN(rMinChip, DEG_RAD*ptSky.r);
+	    rMaxChip = PS_MAX(rMaxChip, DEG_RAD*ptSky.r);
+	    dMinChip = PS_MIN(dMinChip, DEG_RAD*ptSky.d);
+	    dMaxChip = PS_MAX(dMaxChip, DEG_RAD*ptSky.d);
+        }
+	psMetadataAddF32 (chip->analysis, PS_LIST_TAIL, "RA_MIN",  PS_META_REPLACE, "", rMinChip);
+	psMetadataAddF32 (chip->analysis, PS_LIST_TAIL, "RA_MAX",  PS_META_REPLACE, "", rMaxChip);
+	psMetadataAddF32 (chip->analysis, PS_LIST_TAIL, "DEC_MIN", PS_META_REPLACE, "", dMinChip);
+	psMetadataAddF32 (chip->analysis, PS_LIST_TAIL, "DEC_MAX", PS_META_REPLACE, "", dMaxChip);
+	psLogMsg ("fpcamera", 3, "chip %3d = (%f,%f) - (%f,%f)\n", view->chip, rMinChip, dMinChip, rMaxChip, dMaxChip);
+
+	rMinFPA = PS_MIN(rMinFPA, rMinChip);
+	rMaxFPA = PS_MAX(rMaxFPA, rMaxChip);
+	dMinFPA = PS_MIN(dMinFPA, dMinChip);
+	dMaxFPA = PS_MAX(dMaxFPA, dMaxChip);
+    }
+    psMetadataAddF32 (input->fpa->analysis, PS_LIST_TAIL, "RA_MIN",  PS_META_REPLACE, "", rMinFPA);
+    psMetadataAddF32 (input->fpa->analysis, PS_LIST_TAIL, "RA_MAX",  PS_META_REPLACE, "", rMaxFPA);
+    psMetadataAddF32 (input->fpa->analysis, PS_LIST_TAIL, "DEC_MIN", PS_META_REPLACE, "", dMinFPA);
+    psMetadataAddF32 (input->fpa->analysis, PS_LIST_TAIL, "DEC_MAX", PS_META_REPLACE, "", dMaxFPA);
+
+    psLogMsg ("fpcamera", 3, "FPA FOV = (%f,%f) - (%f,%f)\n", rMinFPA, dMinFPA, rMaxFPA, dMaxFPA);
+    psLogMsg ("fpcamera", 3, "convert wcs terms to internal format : %f sec\n", psTimerMark ("fpcamera"));
+
+    psFree (view);
+    return true;
+}
Index: /trunk/fpcamera/src/fpcameraVersion.c
===================================================================
--- /trunk/fpcamera/src/fpcameraVersion.c	(revision 42385)
+++ /trunk/fpcamera/src/fpcameraVersion.c	(revision 42385)
@@ -0,0 +1,119 @@
+/** @file fpcameraVersion.c
+ *
+ *  @brief
+ *
+ *  @ingroup libfpcamera
+ *
+ *  Copyright 2009 Institute for Astronomy, University of Hawaii
+ */
+
+#include "fpcamera.h"
+#include "fpcameraVersionDefinitions.h"
+
+#ifndef FPCAMERA_VERSION
+#error "FPCAMERA_VERSION is not set"
+#endif
+#ifndef FPCAMERA_BRANCH
+#error "FPCAMERA_BRANCH is not set"
+#endif
+#ifndef FPCAMERA_SOURCE
+#error "FPCAMERA_SOURCE is not set"
+#endif
+
+psString fpcameraVersion(void)
+{
+    char *value = NULL;
+    psStringAppend(&value, "%s@%s", FPCAMERA_BRANCH, FPCAMERA_VERSION);
+    return value;
+}
+
+psString fpcameraSource(void)
+{
+  return psStringCopy(FPCAMERA_SOURCE);
+}
+
+psString fpcameraVersionLong(void)
+{
+    psString version = fpcameraVersion();  // Version, to return
+    psString source = fpcameraSource();    // Source
+
+    psStringPrepend(&version, "fpcamera ");
+    psStringAppend(&version, " from %s, built %s, %s", source, __DATE__, __TIME__);
+    psFree(source);
+
+#ifdef __OPTIMIZE__
+    psStringAppend(&version, " optimised");
+#else
+    psStringAppend(&version, " unoptimised");
+#endif
+
+    return version;
+};
+
+bool fpcameraVersionHeader(psMetadata *header)
+{
+    PS_ASSERT_METADATA_NON_NULL(header, false);
+
+    psString version = fpcameraVersion(); // Software version
+    psString source = fpcameraSource();   // Software source
+
+    psMetadataAddStr(header, PS_LIST_TAIL, "FPCAM_V", PS_META_REPLACE, NULL, FPCAMERA_VERSION);
+    
+    psStringPrepend(&version, "fpcamera version: ");
+    psStringPrepend(&source, "fpcamera source: ");
+
+    psMetadataAddStr(header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, NULL, version);
+    psMetadataAddStr(header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, NULL, source);
+
+    psFree(version);
+    psFree(source);
+
+    return true;
+}
+
+bool fpcameraVersionHeaderFull(psMetadata *header)
+{
+    PS_ASSERT_METADATA_NON_NULL(header, false);
+
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psString history = NULL;               // History string
+    psStringAppend(&history, "fpcamera at %s", timeString);
+    psFree(timeString);
+    psMetadataAddStr(header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, NULL, history);
+    psFree(history);
+
+    psLibVersionHeader(header);
+    psModulesVersionHeader(header);
+    ppStatsVersionHeader(header);
+    fpcameraVersionHeader(header);
+
+    return true;
+}
+
+void fpcameraVersionPrint(void)
+{
+    psTime *time = psTimeGetNow(PS_TIME_TAI); // The time now
+    psString timeString = psTimeToISO(time); // The time in an ISO string
+    psFree(time);
+    psLogMsg("fpcamera", PS_LOG_INFO, "fpcamera at %s", timeString);
+    psFree(timeString);
+
+    psString pslib = psLibVersionLong();// psLib version
+    psString psmodules = psModulesVersionLong(); // psModules version
+    psString ppStats = ppStatsVersionLong(); // ppStats version
+    psString fpcamera = fpcameraVersionLong(); // fpcamera version
+
+    psLogMsg("fpcamera", PS_LOG_INFO, "%s", pslib);
+    psLogMsg("fpcamera", PS_LOG_INFO, "%s", psmodules);
+    psLogMsg("fpcamera", PS_LOG_INFO, "%s", ppStats);
+    psLogMsg("fpcamera", PS_LOG_INFO, "%s", fpcamera);
+
+    psFree(pslib);
+    psFree(psmodules);
+    psFree(ppStats);
+    psFree(fpcamera);
+
+    return;
+}
Index: /trunk/fpcamera/src/fpcameraVersionDefinitions.h.in
===================================================================
--- /trunk/fpcamera/src/fpcameraVersionDefinitions.h.in	(revision 42385)
+++ /trunk/fpcamera/src/fpcameraVersionDefinitions.h.in	(revision 42385)
@@ -0,0 +1,8 @@
+#ifndef FPCAMERA_VERSION_DEFINITIONS_H
+#define FPCAMERA_VERSION_DEFINITIONS_H
+
+#define FPCAMERA_VERSION @FPCAMERA_VERSION@ // SVN version
+#define FPCAMERA_BRANCH  @FPCAMERA_BRANCH@  // SVN branch
+#define FPCAMERA_SOURCE  @FPCAMERA_SOURCE@  // SVN source
+
+#endif
Index: /trunk/ippTasks/Makefile.am
===================================================================
--- /trunk/ippTasks/Makefile.am	(revision 42384)
+++ /trunk/ippTasks/Makefile.am	(revision 42385)
@@ -50,4 +50,5 @@
 	bg.regeneration.pro \
 	remote.pro \
+	fpcamera.pro \
 	fullforce.pro
 
Index: /trunk/ippTasks/automate.pro
===================================================================
--- /trunk/ippTasks/automate.pro	(revision 42384)
+++ /trunk/ippTasks/automate.pro	(revision 42385)
@@ -17,4 +17,19 @@
 # DONE (action finished)
 
+macro automate.status
+
+  ## Pull out the ones that are to be run regularly
+  local npages
+  book npages automate -var npages
+  for i 0 $npages
+    book getpage automate $i -var pageName
+    echo $i : $pageName
+    book getword automate $pageName pantaskState -var myState
+    if ("$myState" != "NULL")
+      echo $pageName : $myState
+    end
+  end
+end
+
 macro automate.reset
   ## probably should not always init
@@ -27,7 +42,15 @@
     break
   end
-  queueload tmp -x "cat $MODULES:0/$1"
+
+  file $1 isFound
+  if ($isFound)
+    queueload tmp -x "cat $1"
+  else
+    # search module path list for existing file
+    queueload tmp -x "cat $MODULES:0/$1"
+  end
 
   pwd -var cwd
+  $username = `whoami`
 
   ## interpolate standard values
@@ -35,6 +58,4 @@
   queuesubstr tmp @DBNAME@ $3
   queuesubstr tmp @CWD@ $cwd
-
-  $username = `whoami`
   queuesubstr tmp @USER@ $username
 
Index: /trunk/ippTasks/fpcamera.pro
===================================================================
--- /trunk/ippTasks/fpcamera.pro	(revision 42385)
+++ /trunk/ippTasks/fpcamera.pro	(revision 42385)
@@ -0,0 +1,268 @@
+## fpcamera.pro : globals and support macros : -*- sh -*-
+## this file contains the tasks for running the forced photometry camera analysis stage
+## these tasks use the book fpcamPendingExp
+
+# test for required global variables
+check.globals
+
+# fpcamera.pro should have a more restricted polling limit (to avoid stress with getstar)
+if ($?POLL_LIMIT_FPCAMERA == 0) set POLL_LIMIT_FPCAMERA = 10
+
+macro set.fpcamera.poll
+  if ($0 != 2)
+    echo "USAGE:set.fpcamera.poll (value)"
+    break
+  end
+ 
+  $POLL_LIMIT_FPCAMERA = $1
+end
+
+macro get.fpcamera.poll
+  echo "fpcamera poll limit: $POLL_LIMIT_FPCAMERA"
+end
+
+book init fpcamPendingExp
+
+macro fpcamera.status
+  book listbook fpcamPendingExp
+end
+
+macro fpcamera.reset
+  book init fpcamPendingExp
+end
+
+macro fpcamera.on
+  task fpcamera.exp.load
+    active true
+  end
+  task fpcamera.exp.run
+    active true
+  end
+  task fpcamera.revert
+    active true
+  end
+end
+
+macro fpcamera.off
+  task fpcamera.exp.load
+    active false
+  end
+  task fpcamera.exp.run
+    active false
+  end
+  task fpcamera.revert
+    active false
+  end
+end
+
+macro fpcamera.revert.on
+  task fpcamera.revert
+    active true
+  end
+end
+
+macro fpcamera.revert.off
+  task fpcamera.revert
+    active false
+  end
+end
+
+# this variable will cycle through the known database names
+$fpcamera_DB = 0
+$fpcamera_revert_DB = 0
+
+# select images ready for fpcamera analysis
+# new entries are added to fpcamPendingExp
+# skip already-present entries
+task	       fpcamera.exp.load
+  host         local
+
+  periods      -poll $LOADPOLL
+  periods      -exec $LOADEXEC
+  periods      -timeout 30
+  npending     1
+
+  stdout NULL
+  stderr $LOGDIR/fpcamera.exp.log
+
+  task.exec
+    if ($LABEL:n == 0) break
+    $run = fpcamtool -pendingexp
+    if ($DB:n == 0)
+      option DEFAULT
+    else
+      # save the DB name for the exit tasks
+      option $DB:$fpcamera_DB
+      $run = $run -dbname $DB:$fpcamera_DB
+      $fpcamera_DB ++
+      if ($fpcamera_DB >= $DB:n) set fpcamera_DB = 0
+    end
+    $run = $run -limit $POLL_LIMIT_FPCAMERA
+    # NOTE: we do not want to overload the dvo db machine with getstar queries, 
+    # so we will limit the fpcamera stage to a smaller number than the other stages
+    # add_poll_args run
+    add_poll_labels run
+    command $run
+  end
+
+  # success
+  task.exit    0
+    # convert 'stdout' to book format
+    ipptool2book stdout fpcamPendingExp -key fpcam_id -uniq -setword dbname $options:0 -setword pantaskState INIT
+    if ($VERBOSE > 2)
+      book listbook fpcamPendingExp
+    end
+
+    # delete existing entries in the appropriate pantaskStates
+    process_cleanup fpcamPendingExp
+  end
+
+  # default exit status
+  task.exit    default
+    showcommand failure
+  end
+
+  task.exit    crash
+    showcommand crash
+  end
+
+  # operation times out?
+  task.exit    timeout
+    showcommand timeout
+  end
+end
+
+# run the fpcamera_exp script on pending images
+task	       fpcamera.exp.run
+  periods      -poll $RUNPOLL
+  periods      -exec $RUNEXEC
+  periods      -timeout 10
+
+  task.exec
+    book npages fpcamPendingExp -var N
+    if ($N == 0) break
+    if ($NETWORK == 0) break
+    if ($BURNTOOLING == 1) break
+    
+    # look for new images in fpcamPendingExp (pantaskState == INIT)
+    book getpage fpcamPendingExp 0 -var pageName -key pantaskState INIT
+    if ("$pageName" == "NULL") break
+
+    book setword fpcamPendingExp $pageName pantaskState RUN
+    book getword fpcamPendingExp $pageName camera -var CAMERA
+    book getword fpcamPendingExp $pageName exp_tag -var EXP_TAG
+    book getword fpcamPendingExp $pageName fpcam_id -var FPCAM_ID
+    book getword fpcamPendingExp $pageName workdir -var WORKDIR_TEMPLATE
+    book getword fpcamPendingExp $pageName path_base -var PATH_BASE
+    book getword fpcamPendingExp $pageName dbname -var DBNAME
+    book getword fpcamPendingExp $pageName dvodb -var DVODB
+    book getword fpcamPendingExp $pageName reduction -var REDUCTION
+
+    # specify choice of remote host based on camera and chip (class_id)
+    set.host.for.camera $CAMERA FPA
+
+    # set the WORKDIR variable
+    set.workdir.by.camera $CAMERA FPA $WORKDIR_TEMPLATE $default_host WORKDIR
+
+    # notes on how this works:
+    # -- raw workdir examples:
+    # file://data/@HOST@.0/gpc1/20080130
+    # neb:///@HOST@-vol0/gpc1/20080130 (need to supply volname?, or are we re-defining this each time?)
+    # -- out workdir examples:
+    # file://data/ipp004.0/gpc1/20080130
+    # neb:///ipp004-vol0/gpc1/20080130
+
+    if ("$PATH_BASE" == "NULL") 
+        ## generate outroot specific to this exposure (& chip)
+        sprintf outroot "%s/%s/%s.fp.%s" $WORKDIR $EXP_TAG $EXP_TAG $FPCAM_ID
+    else
+        $outroot = $PATH_BASE
+    end
+
+    stdout $LOGDIR/fpcamera.exp.log
+    stderr $LOGDIR/fpcamera.exp.log
+
+    $run = fpcamera_exp.pl --exp_tag $EXP_TAG --fpcam_id $FPCAM_ID --camera $CAMERA --outroot $outroot --redirect-output
+    if ("$REDUCTION" != "NULL")
+      $run = $run --reduction $REDUCTION
+    end
+    if ("$DVODB" != "NULL")
+      $run = $run --dvodb $DVODB
+    end
+    add_standard_args run
+
+    # save the pageName for future reference below
+    options $pageName
+
+    # create the command line
+    if ($VERBOSE > 1)
+      echo command $run
+    end
+    command $run
+  end
+
+  # success
+  task.exit default
+    process_exit fpcamPendingExp $options:0 $JOB_STATUS
+  end
+
+  # locked list
+  task.exit    crash
+    showcommand crash
+    echo "hostname: $JOB_HOSTNAME"
+    book setword fpcamPendingExp $options:0 pantaskState CRASH
+  end
+
+  # operation times out?
+  task.exit    timeout
+    showcommand timeout
+    book setword fpcamPendingExp $options:0 pantaskState TIMEOUT
+  end
+end
+
+task fpcamera.revert
+  host         local
+
+  periods      -poll 60.0
+  periods      -exec 1800.0
+  periods      -timeout 120.0
+  npending     1
+
+  stdout NULL
+  stderr $LOGDIR/revert.log
+
+  task.exec
+    if ($LABEL:n == 0) break
+    $run = fpcamtool -revertprocessedexp
+    if ($DB:n == 0)
+      option DEFAULT
+    else
+      # save the DB name for the exit tasks
+      option $DB:$fpcamera_revert_DB
+      $run = $run -dbname $DB:$fpcamera_revert_DB
+      $fpcamera_revert_DB ++
+      if ($fpcamera_revert_DB >= $DB:n) set fpcamera_revert_DB = 0
+    end
+    add_poll_labels run
+    command $run
+  end
+
+  # success
+  task.exit    0
+  end
+
+  # locked list
+  task.exit    default
+    showcommand failure
+  end
+
+  task.exit    crash
+    showcommand crash
+  end
+
+  # operation times out?
+  task.exit    timeout
+    showcommand timeout
+  end
+end
+
Index: /trunk/ippTasks/simtest.images.auto
===================================================================
--- /trunk/ippTasks/simtest.images.auto	(revision 42385)
+++ /trunk/ippTasks/simtest.images.auto	(revision 42385)
@@ -0,0 +1,22 @@
+
+automate MULTI
+
+# we run in the sequence BLOCK -> CHECK -> LAUNCH -> BLOCK -> CHECK
+# success on CHECK -> LAUNCH
+# failure on BLOCK -> CHECK
+
+# XXX these steps all refer to "@DBNAME@"; they need to be more generic, even for the basic simtest analysis
+
+automate METADATA
+  name       STR OBJECT-i
+  check      STR "regtool -processedexp -exp_type OBJECT -filter i -inst @CAMERA@ -dbname @DBNAME@"
+  launch     STR "chiptool  -dbname @DBNAME@ -definebyquery -inst @CAMERA@ -filter i -set_label simtest -set_data_group simtest_i -set_dist_group simtest -set_reduction PROCESSED -set_workdir @CWD@/work -set_end_stage fake"
+  block      STR NONE
+END
+
+automate METADATA
+  name       STR OBJECT-r
+  check      STR "regtool -processedexp -exp_type OBJECT -filter r -inst @CAMERA@ -dbname @DBNAME@"
+  launch     STR "chiptool  -dbname @DBNAME@ -definebyquery -inst @CAMERA@ -filter r -set_label simtest -set_data_group simtest_r -set_dist_group simtest -set_reduction PROCESSED -set_workdir @CWD@/work -set_end_stage fake"
+  block      STR NONE
+END
Index: /trunk/ippTasks/simtest.images.config
===================================================================
--- /trunk/ippTasks/simtest.images.config	(revision 42385)
+++ /trunk/ippTasks/simtest.images.config	(revision 42385)
@@ -0,0 +1,77 @@
+
+# define the simulated data to be generated
+SEQUENCE MULTI
+
+SEQUENCE METADATA
+  OBSTYPE    STR OBJECT
+  CAMERA     STR SIMTEST
+
+### Carina
+  CENTER.RA  F32 270.75
+  CENTER.DEC F32 -23.7
+### COSMOS field
+#  CENTER.RA  F32 150.119167 
+#  CENTER.DEC F32   2.205833
+
+  OFFSET.RA  F32 3600.0 # linear offset in arcsec (do not include cos(DEC) correction)
+  OFFSET.DEC F32 3600.0 # linear offset in arcsec (do not include cos(DEC) correction)
+  OFFSET.NR  S32 1
+  OFFSET.ND  S32 1
+
+  DITHER.RA  F32 60.0   # linear offset in arcsec (do not include cos(DEC) correction)
+  DITHER.DEC F32 60.0   # linear offset in arcsec (do not include cos(DEC) correction)
+  DITHER.NR  S32 3
+  DITHER.ND  S32 2
+
+  DVODB      STR /data/alala.0/ipp/ippRefs/catdir.synth.simtest 
+  FILTERS    STR r,i
+  @EXPTIMES  F32 10.00,10.00
+  @SKYMAGS   F32 20.86,20.15
+
+  # XXX use a more realistic IQ distribution...
+  IQ_MIN     F32 0.55
+  IQ_MAX     F32 1.25
+  
+  # rotation sequence
+  POS_MIN    F32 0.0
+  POS_MAX    F32 0.0
+  POS_DELTA  F32 1.0
+END
+
+
+## SEQUENCE METADATA
+##   OBSTYPE    STR OBJECT
+##   CAMERA     STR SIMTEST
+## 
+## ### Carina
+##   CENTER.RA  F32 270.75
+##   CENTER.DEC F32 -23.7
+## ### COSMOS field
+## #  CENTER.RA  F32 150.119167 
+## #  CENTER.DEC F32   2.205833
+## 
+##   OFFSET.RA  F32 3600.0 # linear offset in arcsec (do not include cos(DEC) correction)
+##   OFFSET.DEC F32 3600.0 # linear offset in arcsec (do not include cos(DEC) correction)
+##   OFFSET.NR  S32 1
+##   OFFSET.ND  S32 1
+## 
+##   DITHER.RA  F32 30.0   # linear offset in arcsec (do not include cos(DEC) correction)
+##   DITHER.DEC F32 30.0   # linear offset in arcsec (do not include cos(DEC) correction)
+##   DITHER.NR  S32 1
+##   DITHER.ND  S32 1
+## 
+##   DVODB      STR /data/alala.0/ipp/ippRefs/catdir.synth.simtest 
+##   FILTERS    STR r,r,i,i
+##   @EXPTIMES  F32 5.0, 240.0, 5.0, 240.0
+##   @SKYMAGS   F32 20.86,20.86,20.15,20.15
+## 
+##   # XXX use a more realistic IQ distribution...
+##   IQ_MIN     F32 0.55
+##   IQ_MAX     F32 1.25
+##   
+##   # rotation sequence
+##   POS_MIN    F32 0.0
+##   POS_MAX    F32 0.0
+##   POS_DELTA  F32 1.0
+## END
+
Index: /trunk/ippTasks/simtest.pro
===================================================================
--- /trunk/ippTasks/simtest.pro	(revision 42384)
+++ /trunk/ippTasks/simtest.pro	(revision 42385)
@@ -66,7 +66,9 @@
   if (("$init" == "new") || ("$init" == "inject"))  
     # XXX this will fail and exit the script if the db does not exist or is old...
+    # XXX this step is too dangerous and was eliminated
     exec pxadmin -delete -dbname $dbname
 
     # XXX this gives warnings if the db exists...
+    # XXX this step is too dangerous and was eliminated
     exec pxadmin -create -dbname $dbname
 
@@ -74,5 +76,8 @@
       # the labels "wait" and "proc" are special names used in automate.pro
     
-      $ppsim = "ppSimSequence $MODULES:0/$SIMTEST_SEQUENCE simtest.mkimages simtest.inject -path $SIMTEST_RAWDIR -workdir $SIMTEST_WORKDIR -dbname $dbname -label wait -dvodb DVO -tess_id TESS"
+      # make a reference database
+      mkref refcat 10
+
+      $ppsim = "ppSimSequence $SIMTEST_SEQUENCE simtest.mkimages simtest.inject -path $SIMTEST_RAWDIR -workdir $SIMTEST_WORKDIR -dbname $dbname -label wait -dvodb DVO -tess_id TESS -refcat refcat.catdir"
       if ("$PPSIM_RECIPE" != "default") 
          $ppsim = $ppsim -ppsim_recipe $PPSIM_RECIPE
@@ -101,7 +106,11 @@
   module automate.pro
 
-  module.tasks
-
-  add.label proc
+  module chip.pro
+  module camera.pro
+  module register.pro
+  # module.tasks
+
+  # XXX consolidate design of label / state / ?? for processing sequences
+  add.label simtest
 
   if ($SIMTEST_THREADS == 0) 
@@ -115,5 +124,5 @@
   automate.load $SIMTEST_AUTO $SIMTEST_CAMERA $dbname
 
-  tasks.revert.off
+  # tasks.revert.off
 
   run
@@ -159,2 +168,68 @@
   $SIMTEST_AUTO = simtest.flatcorr.auto
 end
+
+# basic options for the these images (filter, location, obstype)
+$BaseOptions = -type OBJECT -filter r -skymags 20.86 -ra 270.70 -dec -23.70 -pa 0.0
+$BaseOptions = $BaseOptions -Df PSASTRO:DVO.GETSTAR.MAX.RHO 50000.0
+$BaseOptions = $BaseOptions -nx 2500 -ny 2500
+
+# options for the reference image
+$RefOptions = $BaseOptions -exptime 100.0 -seeing 1.0
+$RefOptions = $RefOptions -D PSF.MODEL PS_MODEL_GAUSS
+$RefOptions = $RefOptions -Df STARS.SIGMA.LIM 0.5
+$RefOptions = $RefOptions -Db PSF.CONVOLVE T
+
+# create a reference database of fake stars to be used by ppSim below
+macro mkref
+  if ($0 != 3)
+    echo "mkref (refbase) (density)"
+    break
+  end
+
+  local refbase
+  $refbase = $1
+
+  exec rm -rf $refbase.catdir
+  exec rm -f $refbase.fits
+  
+  $RefOptions = $RefOptions -Df STARS.DENSITY $2
+
+  # create an image with fake sources and insert the resulting cmf file into a dvodb
+  $RefConfig = -camera SIMTEST -recipe PPSIM STACKTEST.MAKE -D PSASTRO:PSASTRO.CATDIR $refbase.catdir
+
+  exec ppSim $RefOptions $RefConfig $refbase
+  
+  file synth.photcodes found
+  if (not($found))
+    echo "making photcodes file"
+    mkphotcodes synth.photcodes
+  end
+
+  exec addstar -D CAMERA simtest -D CATDIR $refbase.catdir -accept-astrom -photcode SYNTH.r -D PHOTCODE_FILE synth.photcodes $refbase.cmf -quick-airmass
+  exec relphot -averages -D CATDIR $refbase.catdir -update -region 260 280 -33 -13
+end
+
+# if we run this test as a stand-alone program somewhere, we may need to create a local copy of the photcode file:
+macro mkphotcodes
+  if ($0 != 2)
+    echo "USAGE: mkphotcodes (filename)"
+    break
+  end
+
+  exec /bin/rm -f $1
+  output $1
+  echo "#                                           airmass      color                         astrometry  mag    photom  astrom mask    photom mask"
+  echo "# code  name                type    zero  slope offset c1    c2   slope   zero  equiv  sys scale   scale  sys     poor   bad     poor   bad"
+  echo "  1     g_SYNTH              sec   0.000  0.000 0.000     1     3 0.0000     0    21   0.000 0.000 0.000  0.000   0x0000 0x0000  0x0000 0x0000"
+  echo "  2     r_SYNTH              sec   0.000  0.000 0.000     2     3 0.0000     0    22   0.000 0.000 0.000  0.000   0x0000 0x0000  0x0000 0x0000"
+  echo "  3     i_SYNTH              sec   0.000  0.000 0.000     2     3 0.0000     0    23   0.000 0.000 0.000  0.000   0x0000 0x0000  0x0000 0x0000"
+  echo "  4     z_SYNTH              sec   0.000  0.000 0.000     3     4 0.0000     0    24   0.000 0.000 0.000  0.000   0x0000 0x0000  0x0000 0x0000"
+  echo "  5     y_SYNTH              sec   0.000  0.000 0.000     4     5 0.0000     0    25   0.000 0.000 0.000  0.000   0x0000 0x0000  0x0000 0x0000"
+  echo "  3001  SYNTH.g              ref   0.000  0.000 0.000     -     - 0.0000     0     1   0.000 0.000 0.000  0.000   0x0000 0x0000  0x0000 0x0000"
+  echo "  3002  SYNTH.r              ref   0.000  0.000 0.000     -     - 0.0000     0     2   0.000 0.000 0.000  0.000   0x0000 0x0000  0x0000 0x0000"
+  echo "  3003  SYNTH.i              ref   0.000  0.000 0.000     -     - 0.0000     0     3   0.000 0.000 0.000  0.000   0x0000 0x0000  0x0000 0x0000"
+  echo "  3004  SYNTH.z              ref   0.000  0.000 0.000     -     - 0.0000     0     4   0.000 0.000 0.000  0.000   0x0000 0x0000  0x0000 0x0000"
+  echo "  3005  SYNTH.y              ref   0.000  0.000 0.000     -     - 0.0000     0     5   0.000 0.000 0.000  0.000   0x0000 0x0000  0x0000 0x0000"
+  output stdout
+end
+
Index: /trunk/ppSim/src/ppSimSequence.c
===================================================================
--- /trunk/ppSim/src/ppSimSequence.c	(revision 42384)
+++ /trunk/ppSim/src/ppSimSequence.c	(revision 42385)
@@ -48,4 +48,11 @@
         psArgumentRemove(argNum, &argc, argv);
         ppsim_recipe = psStringCopy (argv[argNum]);
+        psArgumentRemove(argNum, &argc, argv);
+    }
+
+    char *refcat = NULL;
+    if ((argNum = psArgumentGet (argc, argv, "-refcat"))) {
+        psArgumentRemove(argNum, &argc, argv);
+        refcat = psStringCopy (argv[argNum]);
         psArgumentRemove(argNum, &argc, argv);
     }
@@ -96,4 +103,5 @@
         fprintf (stderr, " -label (label)\n");
         fprintf (stderr, " -dvodb (dvodb)\n");
+        fprintf (stderr, " -refcat (catdir)\n");
         fprintf (stderr, " -tess_id (tess_id)\n");
         exit (2);
@@ -242,5 +250,5 @@
         }
         if (!strcasecmp (type, "OBJECT")) {
-            ppSimSequenceObject (simfile, inject, sequence, i, rng, path, basename, ppSimCommandReal, injectCommandReal, files);
+            ppSimSequenceObject (simfile, inject, sequence, i, rng, path, basename, refcat, ppSimCommandReal, injectCommandReal, files);
 	    psFree (injectCommandReal);
 	    psFree (ppSimCommandReal);
Index: /trunk/ppSim/src/ppSimSequence.h
===================================================================
--- /trunk/ppSim/src/ppSimSequence.h	(revision 42384)
+++ /trunk/ppSim/src/ppSimSequence.h	(revision 42385)
@@ -15,5 +15,5 @@
 bool ppSimSequenceDark 	 (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *ppSimCommand, const char *injectCommand, psArray *files);
 bool ppSimSequenceFlat 	 (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *ppSimCommand, const char *injectCommand, psArray *files);
-bool ppSimSequenceObject (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *ppSimCommand, const char *injectCommand, psArray *files);
+bool ppSimSequenceObject (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *refcat, const char *ppSimCommand, const char *injectCommand, psArray *files);
 
 #endif
Index: /trunk/ppSim/src/ppSimSequenceObject.c
===================================================================
--- /trunk/ppSim/src/ppSimSequenceObject.c	(revision 42384)
+++ /trunk/ppSim/src/ppSimSequenceObject.c	(revision 42385)
@@ -1,5 +1,5 @@
 # include "ppSimSequence.h"
 
-bool ppSimSequenceObject (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *ppSimCommand, const char *injectCommand, psArray *files) {
+bool ppSimSequenceObject (FILE *simfile, FILE *inject, psMetadata *sequence, int nSeq, psRandom *rng, const char *path, const char *basename, const char *refcat, const char *ppSimCommand, const char *injectCommand, psArray *files) {
 
     bool status;
@@ -97,4 +97,6 @@
 			    psStringAppend (&command, " -obs_mode OBJECT.%s", (char *) filters->data[i]);
 
+			    if (refcat) { psStringAppend (&command, " -D PSASTRO:PSASTRO.CATDIR %s", refcat); }
+
 			    double frnd = psRandomUniform(rng);
 			    float seeing = IQmin + (IQmax - IQmin)*frnd;
