Index: /branches/rel10_ifa/psModules/src/astrom/Makefile.am
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/Makefile.am	(revision 6520)
+++ /branches/rel10_ifa/psModules/src/astrom/Makefile.am	(revision 6521)
@@ -10,4 +10,6 @@
 	pmFPARead.c \
 	pmFPAWrite.c \
+        pmFPAfile.c \
+        pmFPAview.c \
 	pmReadout.c \
 	psAdditionals.c \
@@ -26,4 +28,6 @@
 	pmFPARead.h \
 	pmFPAWrite.h \
+        pmFPAfile.c \
+        pmFPAview.c \
 	pmReadout.h \
 	psAdditionals.h \
Index: /branches/rel10_ifa/psModules/src/astrom/pmFPAfile.c
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmFPAfile.c	(revision 6521)
+++ /branches/rel10_ifa/psModules/src/astrom/pmFPAfile.c	(revision 6521)
@@ -0,0 +1,182 @@
+# include "pmFPAfile.h"
+
+static void pmPFAfileFree (pmFPAfile *file)
+{
+
+    if (file == NULL)
+        return;
+
+    // psFree (file->element);
+    return;
+}
+
+pmFPAfile *pmFPAfileAlloc ()
+{
+
+    pmFPAfile *file = psAlloc (sizeof(pmFPAfile));
+
+    // file->element = foo;
+    return (file);
+}
+
+pmFile *pmFPAfileDefine (pmFPAview *view, psMetadata *camera, char *name)
+{
+
+    // select the name from the camera config data
+    psMetadata *data = psMetadataLookup (&status, camera, name);
+    if (data == NULL) {
+        return false;
+    }
+
+    pmFPAfile *file = pmFPAfileAlloc ();
+    file->filerule = psMetadataLookupStr (&status, data, "FILENAME.RULE");
+    file->filextra = psMetadataLookupStr (&status, data, "FILENAME.XTRA");
+    file->extrule  = psMetadataLookupStr (&status, data, "EXTNAME.RULE");
+    file->extxtra  = psMetadataLookupStr (&status, data, "EXTNAME.XTRA");
+
+    file->openDepth = PM_FPA_DEPTH_NONE;
+    char *depth = psMetadataLookupStr (&status, data, "OPEN.DEPTH");
+    if (depth != NULL) {
+        if (!strcasecmp (depth, "FPA"))     {
+            file->openDepth = PM_FPA_DEPTH_FPA;
+        }
+        if (!strcasecmp (depth, "CHIP"))    {
+            file->openDepth = PM_FPA_DEPTH_CHIP;
+        }
+        if (!strcasecmp (depth, "CELL"))    {
+            file->openDepth = PM_FPA_DEPTH_CELL;
+        }
+        if (!strcasecmp (depth, "READOUT")) {
+            file->openDepth = PM_FPA_DEPTH_READOUT;
+        }
+    }
+
+    file->readDepth = PM_FPA_DEPTH_NONE;
+    char *depth = psMetadataLookupStr (&status, data, "READ.DEPTH");
+    if (depth != NULL) {
+        if (!strcasecmp (depth, "FPA"))     {
+            file->readDepth = PM_FPA_DEPTH_FPA;
+        }
+        if (!strcasecmp (depth, "CHIP"))    {
+            file->readDepth = PM_FPA_DEPTH_CHIP;
+        }
+        if (!strcasecmp (depth, "CELL"))    {
+            file->readDepth = PM_FPA_DEPTH_CELL;
+        }
+        if (!strcasecmp (depth, "READOUT")) {
+            file->readDepth = PM_FPA_DEPTH_READOUT;
+        }
+    }
+
+    file->writeDepth = PM_FPA_DEPTH_NONE;
+    char *depth = psMetadataLookupStr (&status, data, "WRITE.DEPTH");
+    if (depth != NULL) {
+        if (!strcasecmp (depth, "FPA"))     {
+            file->readDepth = PM_FPA_DEPTH_FPA;
+        }
+        if (!strcasecmp (depth, "CHIP"))    {
+            file->readDepth = PM_FPA_DEPTH_CHIP;
+        }
+        if (!strcasecmp (depth, "CELL"))    {
+            file->readDepth = PM_FPA_DEPTH_CELL;
+        }
+        if (!strcasecmp (depth, "READOUT")) {
+            file->readDepth = PM_FPA_DEPTH_READOUT;
+        }
+    }
+    return (file);
+}
+
+bool pmFPAfileOpen (pmFPAfile *file, pmFPAview *view, psMetadata *camera)
+{
+
+    // is current depth == open depth?
+    depth = pmFPAviewDepth (view);
+    if (file->openDepth != depth) {
+        return false;
+    }
+
+    // determine the file name
+    file->filename = pmConfigNameFromRule (file->filerule, view);
+
+    // indirect filenames
+    if (!strcasecmp (file->filename, "@FPAIO")) {
+        extra = pmConfigNameFromRule (file->filextra, view);
+        file->filename = psMetadataLookupStr (&status, fpi->IO, extra);
+    }
+    if (!strcasecmp (file->filename, "@DETDB")) {
+        extra = pmConfigNameFromRule (file->filextra, camera, view);
+        file->filename = pmDetrendSelect (extra);
+    }
+
+    if (file->mode == READ) {
+        file->fits = psFitsOpen (file->filename, "r");
+    } else {
+        file->fits = psFitsOpen (file->filename, "w");
+    }
+}
+
+bool pmFPAfileRead (pmFPAfile *file, pmFPAview *view, psMetadata *camera)
+{
+
+    // is current depth == open depth?
+    depth = pmFPAviewDepth (view);
+    if (file->readDepth != depth) {
+        return false;
+    }
+
+    if (file->mode != READ) {
+        return false;
+    }
+
+    if (file->type == FITS) {
+        // read all selected elements for this view?
+        pmFPAviewReadFitsImage (view, file->fits, phu?, database?);
+    }
+
+    if (file->type == SMP) {
+        // read all selected elements for this view?
+        pmFPAviewReadSMP (view->fpa, file->fits, phu?, database?);
+    }
+}
+
+bool pmFPAfileWrite (pmFPAfile *file, pmFPAview *view, psMetadata *camera)
+{
+
+    // is current depth == open depth?
+    depth = pmFPAviewDepth (view);
+    if (file->writeDepth != depth) {
+        return false;
+    }
+
+    if (file->mode != WRITE) {
+        return false;
+    }
+
+    if (file->type == FITS) {
+        // read all selected elements for this view?
+        pmFPAviewWriteFitsImage (view, file->fits, phu?, database?);
+    }
+
+    if (file->type == SMP) {
+        // read all selected elements for this view?
+        pmFPAviewWriteSMP (view->fpa, file->fits, phu?, database?);
+    }
+}
+
+// attempt open and read for all pmFPAfiles in view->IO
+bool pmFPAfileIOCheck (pmFPAview *view, psMetadata *camera)
+{
+
+    // recipe override values (command-line options):
+    psMetadataItem *item = NULL;
+    psMetadataIterator *iter = psMetadataIteratorAlloc (view->IO, PS_LIST_HEAD, NULL);
+    while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
+        pmFPAfile *file = item->data.V;
+
+        pmFPAfileOpen (file, view, camera);
+        pmFPAfileRead (file, view, camera);
+    }
+    psFree (iter);
+    return true;
+}
Index: /branches/rel10_ifa/psModules/src/astrom/pmFPAfile.h
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmFPAfile.h	(revision 6521)
+++ /branches/rel10_ifa/psModules/src/astrom/pmFPAfile.h	(revision 6521)
@@ -0,0 +1,28 @@
+
+typedef struct
+{
+    pmFPAdepth openDepth;
+    pmFPAdepth readDepth;
+    pmFPAdepth writeDepth;
+
+    psFits *fits;
+    char *filerule;
+    char *filextra;
+    char *extrule;
+    char *extxtra;
+
+    char *filename;
+    char *extname;
+
+    int mode;
+    int type;
+}
+pmFPAfile;
+
+pmFPAfile *pmFPAfileAlloc ();
+pmFile *pmFPAfileDefine (pmFPAview *view, psMetadata *camera, char *name);
+bool pmFPAfileOpen (pmFPAfile *file, pmFPAview *view, psMetadata *camera);
+bool pmFPAfileRead (pmFPAfile *file, pmFPAview *view, psMetadata *camera);
+bool pmFPAfileWrite (pmFPAfile *file, pmFPAview *view, psMetadata *camera);
+bool pmFPAfileIOCheck (pmFPAview *view, psMetadata *camera);
+bool pmFPAviewReadFitsImage (pmFPAview *view, psFits *fits);
Index: /branches/rel10_ifa/psModules/src/astrom/pmFPAview.c
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmFPAview.c	(revision 6521)
+++ /branches/rel10_ifa/psModules/src/astrom/pmFPAview.c	(revision 6521)
@@ -0,0 +1,303 @@
+# include "pmFPAview.h"
+
+static void pmPFAviewFree (pmFPAview *view)
+{
+
+    if (view == NULL)
+        return;
+
+    psFree (view->IO);
+    return;
+}
+
+pmFPAview *pmFPAviewAlloc (pmFPA *fpa, psMetadata *camera, int nRows)
+{
+
+    pmFPAview *view = psAlloc (sizeof(pmFPAview));
+
+    view->fpa     = fpa;
+    view->nRows   = nRows;
+    view->camera  = camera;
+
+    view->chip    = -1;
+    view->cell    = -1;
+    view->readout = -1;
+    view->iRows   = 0;
+
+    view->IO      = psMetadataAlloc ();
+    return (view);
+}
+
+pmFPAdepth pmFPAviewDepth (pmFPAview *view)
+{
+
+    if (view->chip < 0) {
+        return PM_FPA_DEPTH_FPA;
+    }
+    if (view->cell < 0) {
+        return PM_FPA_DEPTH_CHIP;
+    }
+    if (view->readout < 0) {
+        return PM_FPA_DEPTH_CELL;
+    }
+    return PM_FPA_DEPTH_READOUT;
+}
+
+pmChip *pmFPAviewThisChip (pmFPAview *view)
+{
+
+    if (view->chip < 0) {
+        return NULL;
+    }
+
+    if (view->chip >= view->fpa->chips->n) {
+        return NULL;
+    }
+
+    pmChip *chip = view->fpa->chips->data[view->chip];
+    return chip;
+}
+
+pmChip *pmFPAviewNextChip (pmFPAview *view, int nStep)
+{
+
+    view->cell = -1;
+    view->readout = -1;
+    view->iRows = 0;
+
+    // if there are no available chips, return NULL
+    if (view->fpa->chips->n <= 0) {
+        view->chip = -1;
+        return NULL;
+    }
+
+    // clean up < -1 values
+    if (view->chip < -1) {
+        view->chip = -1;
+    }
+
+    // increment to the next chip
+    view->chip += nStep;
+
+    // if we are at the end of the stack, return NULL
+    if (view->chip >= view->fpa->chips->n) {
+        view->chip = -1;
+        return NULL;
+    }
+
+    // get the correct chip pointer
+    pmChip *chip = view->fpa->chips->data[view->chip];
+    return (chip);
+}
+
+pmCell *pmFPAviewThisCell (pmFPAview *view)
+{
+
+    if (view->cell < 0) {
+        return NULL;
+    }
+
+    pmChip *chip = pmFPAviewThisChip (view);
+    if (chip == NULL) {
+        return NULL;
+    }
+
+    if (view->cell >= chip->cells->n) {
+        return NULL;
+    }
+
+    pmCell *cell = chip->cells->data[view->cell];
+    return cell;
+}
+
+pmCell *pmFPAviewNextCell (pmFPAview *view, int nStep)
+{
+
+    pmChip *chip = pmFPAviewThisChip (view);
+    if (chip == NULL) {
+        return NULL;
+    }
+
+    view->readout = -1;
+    view->iRows = 0;
+
+    // if there are no available cells, return NULL
+    if (chip->cells->n <= 0) {
+        view->cell = -1;
+        return NULL;
+    }
+
+    // clean up < -1 values
+    if (view->cell < -1) {
+        view->cell = -1;
+    }
+
+    // increment to the next cell
+    view->cell += nStep;
+
+    // if we are at the end of the stack, return NULL
+    if (view->cell >= chip->cells->n) {
+        view->cell = -1;
+        return NULL;
+    }
+
+    // get the correct cell pointer
+    pmCell *cell = chip->cells->data[view->cell];
+    return (cell);
+}
+
+pmReadout *pmFPAviewThisReadout (pmFPAview *view)
+{
+
+    if (view->readout < 0) {
+        return NULL;
+    }
+
+    pmCell *cell = pmFPAviewThisCell (view);
+    if (cell == NULL) {
+        return NULL;
+    }
+
+    if (view->readout >= cell->readouts->n) {
+        return NULL;
+    }
+
+    pmReadout *readout = cell->readouts->data[view->readout];
+    return readout;
+}
+
+pmCell *pmFPAviewNextReadout (pmFPAview *view, int nStep)
+{
+
+    pmCell *cell = pmFPAviewThisCell (view);
+    if (cell == NULL) {
+        return NULL;
+    }
+
+    view->iRows = 0;
+
+    // if there are no available cells, return NULL
+    if (view->fpa->readouts->n <= 0) {
+        view->readouts = -1;
+        return NULL;
+    }
+
+    // clean up < -1 values
+    if (view->readout < -1) {
+        view->readout = -1;
+    }
+
+    // increment to the next cell
+    view->readout += nStep;
+
+    // if we are at the end of the stack, return NULL
+    if (view->readout >= cell->readouts->n) {
+        view->readout = -1;
+        return NULL;
+    }
+
+    // get the correct cell pointer
+    pmReadout *readout = cell->readouts->data[view->readout];
+    return (readout);
+}
+
+pmHDU *pmFPAviewThisHDU (pmFPAview *view)
+{
+
+    // the HDU is attached to a cell, chip or fpa
+    // if this view has a -1 for the level which contains the hdu,
+    // there is no unambiguous HDU
+
+    if (view->chip < 0) {
+        return pmHDUfromFPA (view->fpa);
+    }
+    if (view->cell < 0) {
+        return pmHDUfromChip (pmFPAviewThisChip (view));
+    }
+    if (view->readout < 0) {
+        return pmHDUfromCell (pmFPAviewThisCell (view));
+    }
+    return NULL;
+}
+
+// select the rule from the camera configuration, perform substitutions as needed
+char *pmFPAviewNameFromRule (char *rule, pmFPAview *view)
+{
+
+    char *name;
+    char *newName = NULL;     // destination for resulting name
+
+    newName = psStringCopy (rule);
+
+    if (strstr (newName, "{CHIP.NAME}") != NULL) {
+        pmChip *chip = pmFPAviewThisChip (view);
+        if (chip != NULL) {
+            char *name = psMetadataLookupStr (NULL, chip->concepts, "CHIP.NAME");
+            if (name != NULL) {
+                newName = psStringSubstitute (newName, name, "{CHIP.NAME}");
+            }
+        }
+    }
+    if (strstr (newName, "{CELL.NAME}") != NULL) {
+        pmCell *cell = pmFPAviewThisCell (view);
+        if (cell != NULL) {
+            char *name = psMetadataLookupStr (NULL, cell->concepts, "CELL.NAME");
+            if (name != NULL) {
+                newName = psStringSubstitute (newName, name, "{CELL.NAME}");
+            }
+        }
+    }
+    if (strstr (newName, "{EXTNAME}") != NULL) {
+        pmCell *cell = pmFPAviewThisCell (view);
+        char *name = psMetadataLookupStr (NULL, header, "EXTNAME");
+        if (name != NULL) {
+            newName = psStringSubstitute (newName, name, "{EXTNAME}");
+        }
+    }
+    return newName;
+}
+
+// given an already-opened fits file, read the components corresponding
+// to the specified view
+bool pmFPAviewReadFitsImage (pmFPAview *view, psFits *fits)
+{
+
+    pmFPA *fpa = view->fpa;
+
+    if (view->chip == -1) {
+        pmFPARead (fpa, fits, phu, database);
+        return true;
+    }
+
+    if (view->chip >= fpa->chips->n) {
+        return false;
+    }
+    pmChip *chip = fpa->chips->data[view->chip];
+
+    if (view->cell == -1) {
+        pmChipRead (chip, fits, phu, database);
+        return true;
+    }
+
+    if (view->cell >= chip->cells->n) {
+        return false;
+    }
+    pmCell *cell = chip->cells->data[view->cell];
+
+    if (view->readout == -1) {
+        pmCellRead (cell, fits, phu, database);
+        return true;
+    }
+
+    if (view->readout >= cell->readouts->n) {
+        return false;
+    }
+    pmReadout *readout = cell->readouts->data[view->readout];
+
+    if (view->nRows == 0) {
+        pmReadoutRead (readout, fits, phu, database);
+    } else {
+        pmReadoutReadSegment (readout, fits, view->nRows, view->iRows, phu, database);
+    }
+    return true;
+}
Index: /branches/rel10_ifa/psModules/src/astrom/pmFPAview.h
===================================================================
--- /branches/rel10_ifa/psModules/src/astrom/pmFPAview.h	(revision 6521)
+++ /branches/rel10_ifa/psModules/src/astrom/pmFPAview.h	(revision 6521)
@@ -0,0 +1,79 @@
+/** @file  pmFPAview.h
+*
+*  @brief Tools to manipulate the FPA structure elements.
+*
+*  @ingroup AstroImage
+*
+*  @author EAM, IfA
+*
+*  @version $Revision: 1.1.2.1 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2006-03-05 23:34:35 $
+*
+*  Copyright 2004-2005 Institute for Astronomy, University of Hawaii
+*/
+
+#ifndef PM_FPA_VIEW_H
+#define PM_FPA_VIEW_H
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "pslib.h"
+#include "pmFPA.h"
+
+/// @addtogroup AstroImage
+/// @{
+
+// depth of interest
+typedef enum {
+    PM_FPA_DEPTH_NONE,
+    PM_FPA_DEPTH_FPA,
+    PM_FPA_DEPTH_CHIP,
+    PM_FPA_DEPTH_CELL,
+    PM_FPA_DEPTH_READOUT,
+} pmFPAdepth;
+
+typedef struct
+{
+    pmFPA *fpa;
+    psMetadata IO;
+    psMetadata camera;
+    int chip;
+    int cell;
+    int readout;
+    int nRows;
+    int iRows;
+}
+pmFPAview;
+
+// allocate a pmFPAview structure for this fpa and camera
+pmFPAview *pmFPAviewAlloc (pmFPA *fpa, psMetadata *camera, int nRows);
+
+// determine the current view depth
+pmFPAdepth pmFPAviewDepth (pmFPAview *view);
+
+// return the currently selected chip for this view
+pmChip *pmFPAviewThisChip (pmFPAview *view);
+
+// advance view to the next chip
+pmChip *pmFPAviewNextChip (pmFPAview *view, int nStep);
+
+// return the currently selected cell for this view
+pmCell *pmFPAviewThisCell (pmFPAview *view);
+
+// advance view to the next cell
+pmCell *pmFPAviewNextCell (pmFPAview *view, int nStep);
+
+// return the currently selected readout for this view
+pmReadout *pmFPAviewThisReadout (pmFPAview *view);
+
+// advance view to the next readout
+pmCell *pmFPAviewNextReadout (pmFPAview *view, int nStep);
+
+// return the HDU corresponding to the current view
+pmHDU *pmFPAviewThisHDU (pmFPAview *view);
+
+// convert the rule to a name based on the current view
+char *pmFPAviewNameFromRule (char *rule, pmFPAview *view);
+
+// read an image into the current view
+bool pmFPAviewReadFitsImage (pmFPAview *view, psFits *fits);
