Index: /trunk/psLib/src/astronomy/psAstrometry.c
===================================================================
--- /trunk/psLib/src/astronomy/psAstrometry.c	(revision 1513)
+++ /trunk/psLib/src/astronomy/psAstrometry.c	(revision 1514)
@@ -8,6 +8,6 @@
 *  @author George Gusciora, MHPCC
 *
-*  @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-08-12 03:11:45 $
+*  @version $Revision: 1.21 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-12 05:36:53 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -44,8 +44,14 @@
 }
 
-/*
-    XXX: Several members of the psGrommit data structure have no direct
-    counterpart in the psExposure structure.  How are we to determine them?
-*/
+extern void sla_aoppa(double date, double dut, double elongm,
+                          double phim, double him, double xp,
+                          double yp, double tdk, double pmb,
+                          double rh, double wl, double tlr,
+                          double *AOPRMS);
+#define TBD 0.0
+/*****************************************************************************
+XXX: Several of the input params to sla_aoppa() are currently undefined.
+We are awaiting futher direction from IfA on this.
+ *****************************************************************************/
 psGrommit* psGrommitAlloc(const psExposure* exp)
 {
@@ -54,26 +60,37 @@
     }
 
+    double date = TBD;  // "mjd" in psExposure will become a psTime
+    // from which it will be possible to get UTC.
+    double dut = 0.0;
+    double elongm = TBD;
+    double phim = TBD;
+    double hm = TBD;
+    double xp = 0.0;
+    double yp = 0.0;
+    double tdk = exp->temperature;
+    double pmb = exp->pressure;
+    double rh = exp->humidity;
+    double wl = exp->wavelength;
+    double tlr = TBD;
+    double *AOPRMS = NULL;
+
+    sla_aoppa(date, dut, elongm, phim, hm, xp, yp,
+              tdk, pmb, rh, wl, tlr, AOPRMS);
+
     psGrommit* grommit = (psGrommit* ) psAlloc(sizeof(psGrommit));
-
-    /*
-     * extern void sla_aoppa(double date, double dut, double elongm, double phim, double him, double xp,
-     * double yp, double tdk, double pmb, double rh, double wl, double tlr, double *AOPRMS);
-     * 
-     * sla_aoppa(date, deltaUT, meanLongitude, meanLatitude, height, xp, yp, exp->temperature, exp->pressure, 
-     * exp->humidity, wavelength, tlr); */
-    *(double *)&grommit->latitude = exp->dec;   // XXX Is this correct?
-    *(double *)&grommit->sinLat = sin(grommit->latitude);
-    *(double *)&grommit->cosLat = cos(grommit->latitude);
-    *(double *)&grommit->abberationMag = 0.0;
-    *(double *)&grommit->height = 0.0;
-    *(double *)&grommit->temperature = exp->temperature;
-    *(double *)&grommit->pressure = exp->pressure;
-    *(double *)&grommit->humidity = exp->humidity;
-    *(double *)&grommit->wavelength = 0.0;
-    *(double *)&grommit->lapseRate = 0.0;
-    *(double *)&grommit->refractA = 0.0;
-    *(double *)&grommit->refractB = 0.0;
-    *(double *)&grommit->longitudeOffset = exp->ra;     // XXX Is this correct?
-    *(double *)&grommit->siderealTime = 0.0;
+    *(double *)&grommit->latitude = AOPRMS[0];
+    *(double *)&grommit->sinLat = AOPRMS[1];
+    *(double *)&grommit->cosLat = AOPRMS[2];
+    *(double *)&grommit->height = AOPRMS[3];
+    *(double *)&grommit->abberationMag = AOPRMS[4];
+    *(double *)&grommit->temperature = AOPRMS[5];
+    *(double *)&grommit->pressure = AOPRMS[6];
+    *(double *)&grommit->humidity = AOPRMS[7];
+    *(double *)&grommit->wavelength = AOPRMS[8];
+    *(double *)&grommit->lapseRate = AOPRMS[9];
+    *(double *)&grommit->refractA = AOPRMS[10];
+    *(double *)&grommit->refractB = AOPRMS[11];
+    *(double *)&grommit->longitudeOffset = AOPRMS[12];
+    *(double *)&grommit->siderealTime = AOPRMS[13];
 
     return (grommit);
@@ -92,9 +109,9 @@
     psPlane* chipCoord = NULL;
 
+    if (fpaCoord == NULL) {
+        psAbort(__func__, "input parameter fpaCoord is NULL.");
+    }
     if (FPA == NULL) {
-        return(NULL);
-    }
-    if (fpaCoord == NULL) {
-        return(NULL);
+        psAbort(__func__, "input parameter FPA is NULL.");
     }
 
@@ -133,5 +150,5 @@
 
 /*****************************************************************************
-    XXX: Return the answer in "out".
+XXX: Should we return the result in "out"?
  *****************************************************************************/
 psChip* psChipInFPA(psChip* out,
@@ -143,4 +160,11 @@
     psPlane* chipCoord = NULL;
     psCell *tmpCell = NULL;
+
+    if (fpaCoord == NULL) {
+        psAbort(__func__, "input parameter fpaCoord is NULL.");
+    }
+    if (FPA == NULL) {
+        psAbort(__func__, "input parameter FPA is NULL.");
+    }
 
     // Loop through every chip in this FPA.  Convert the original
@@ -150,6 +174,7 @@
     for (int i = 0; i < nChips; i++) {
         psChip* tmpChip = chips->data[i];
-
-        chipCoord = psPlaneTransformApply(chipCoord, tmpChip->fromFPA, fpaCoord);
+        chipCoord = psPlaneTransformApply(chipCoord, tmpChip->fromFPA,
+                                          fpaCoord);
+
         tmpCell = psCellInChip(tmpCell, chipCoord, tmpChip);
         if (tmpCell != NULL) {
@@ -164,8 +189,5 @@
 
 /*****************************************************************************
-XXX: if we find no cell with has this coordinate, we return NULL.
-XXX: must deallocate memory.
-XXX: must return the cell in the "outCell" parameter.
-XXX: verify the NULL parameter error handling.
+XXX: Should we return the result in "out"?
  *****************************************************************************/
 psCell* psCellInChip(psCell* outCell,
@@ -175,13 +197,11 @@
     psPlane* cellCoord = NULL;
     psArray* cells;
-    psReadout *tmpReadout = NULL;
 
     // We return NULL if either of the input parameters is NULL.
+    if (chipCoord == NULL) {
+        psAbort(__func__, "the 'chipCoord' parameter is NULL\n");
+    }
     if (chip == NULL) {
-        return NULL;
-    }
-
-    if (chipCoord == NULL) {
-        return NULL;
+        psAbort(__func__, "the 'chip' parameter is NULL\n");
     }
 
@@ -196,17 +216,21 @@
     for (int i = 0; i < cells->n; i++) {
         psCell* tmpCell = (psCell* ) cells->data[i];
-        // XXX: figure this out
-        //        psReadout *tmpReadout = tmpCell->readouts;
-
-        while (tmpReadout != NULL) {
-            cellCoord = psPlaneTransformApply(cellCoord,
-                                              tmpCell->fromChip,
-                                              chipCoord);
-
-            if (p_psCheckValidImageCoords(cellCoord->x, cellCoord->y, tmpReadout->image)) {
-                psFree(cellCoord);
-                return (tmpCell);
+        psArray* readouts = tmpCell->readouts;
+
+        if (readouts != NULL) {
+            for (int j = 0; j < readouts->n; j++) {
+                psReadout* tmpReadout = readouts->data[j];
+
+                cellCoord = psPlaneTransformApply(cellCoord,
+                                                  tmpCell->fromChip,
+                                                  chipCoord);
+
+                if (p_psCheckValidImageCoords(cellCoord->x,
+                                              cellCoord->y,
+                                              tmpReadout->image)) {
+                    psFree(cellCoord);
+                    return (tmpCell);
+                }
             }
-            tmpReadout++;
         }
     }
@@ -220,4 +244,11 @@
                            const psCell* cell)
 {
+    if (inCoord == NULL) {
+        psAbort(__func__, "input parameter inCoord is NULL.");
+    }
+    if (cell == NULL) {
+        psAbort(__func__, "input parameter cell is NULL.");
+    }
+
     return (psPlaneTransformApply(outCoord, cell->toChip, inCoord));
 }
@@ -227,4 +258,11 @@
                           const psChip* chip)
 {
+    if (inCoord == NULL) {
+        psAbort(__func__, "input parameter inCoord is NULL.");
+    }
+    if (chip == NULL) {
+        psAbort(__func__, "input parameter chip is NULL.");
+    }
+
     return (psPlaneTransformApply(outCoord, chip->toFPA, inCoord));
 }
@@ -236,4 +274,11 @@
                         const psFPA* fpa)
 {
+    if (inCoord == NULL) {
+        psAbort(__func__, "input parameter inCoord is NULL.");
+    }
+    if (fpa == NULL) {
+        psAbort(__func__, "input parameter fpa is NULL.");
+    }
+
     return(psPlaneDistortApply(outCoord, fpa->toTangentPlane, inCoord,
                                magnitude, color));
@@ -245,4 +290,10 @@
                          const psGrommit* grommit)
 {
+    if (tpCoord == NULL) {
+        psAbort(__func__, "input parameter tpCoord is NULL.");
+    }
+    if (grommit == NULL) {
+        psAbort(__func__, "input parameter grommit is NULL.");
+    }
     if (outSphere == NULL) {
         outSphere = (psSphere* ) psAlloc(sizeof(psSphere));
@@ -263,10 +314,14 @@
                           const psCell* cell)
 {
+    if (cellCoord == NULL) {
+        psAbort(__func__, "input parameter cellCoord is NULL.");
+    }
+    if (cell == NULL) {
+        psAbort(__func__, "input parameter cell is NULL.");
+    }
+
     return (psPlaneTransformApply(fpaCoord, cell->toFPA, cellCoord));
 }
 
-/*****************************************************************************
-XXX: determine the grommit from the FPA associated with this chip.
- *****************************************************************************/
 psSphere* psCoordCellToSky(psSphere* skyCoord,
                            const psPlane* cellCoord,
@@ -275,4 +330,11 @@
                            const psCell* cell)
 {
+    if (cellCoord == NULL) {
+        psAbort(__func__, "input parameter cellCoord is NULL.");
+    }
+    if (cell == NULL) {
+        psAbort(__func__, "input parameter cell is NULL.");
+    }
+
     psPlane* fpaCoord = NULL;
     psPlane* tpCoord = NULL;
@@ -284,5 +346,6 @@
 
     // Convert the FPA coordinates to tangent plane Coordinates.
-    tpCoord = psPlaneDistortApply(tpCoord, parFPA->toTangentPlane, fpaCoord, magnitude, color);
+    tpCoord = psPlaneDistortApply(tpCoord, parFPA->toTangentPlane,
+                                  fpaCoord, magnitude, color);
 
     // Generate a grommit for this FPA.
@@ -307,4 +370,11 @@
                                 const psCell* cell)
 {
+    if (cellCoord == NULL) {
+        psAbort(__func__, "input parameter cellCoord is NULL.");
+    }
+    if (cell == NULL) {
+        psAbort(__func__, "input parameter cell is NULL.");
+    }
+
     psPlane *tpCoord = NULL;
     psChip *chip = cell->parent;
@@ -340,4 +410,11 @@
                         const psGrommit* grommit)
 {
+    if (in == NULL) {
+        psAbort(__func__, "input parameter in is NULL.");
+    }
+    if (grommit == NULL) {
+        psAbort(__func__, "input parameter grommit is NULL.");
+    }
+
     /*
         extern void sla_AOPQK(RAP, DAP, AOPRMS, AOB, ZOB, HOB, DOB, ROB);
@@ -367,33 +444,67 @@
                         const psFPA* fpa)
 {
+    if (tpCoord == NULL) {
+        psAbort(__func__, "input parameter tpCoord is NULL.");
+    }
+    if (fpa == NULL) {
+        psAbort(__func__, "input parameter fpa is NULL.");
+    }
+
     return (psPlaneDistortApply(fpaCoord, fpa->fromTangentPlane,
                                 tpCoord, magnitude, color));
 }
 
-/*****************************************************************************
-XXX: must first determine which chip contains this chipcoord.
- *****************************************************************************/
 psPlane* psCoordFPAToChip(psPlane* chipCoord,
                           const psPlane* fpaCoord,
                           const psChip* chip)
 {
-    return (psPlaneTransformApply(chipCoord, chip->fromFPA, fpaCoord));
-}
-
-/*****************************************************************************
-XXX: must first determine which cell contains this chipcoord.
- *****************************************************************************/
+    if (fpaCoord == NULL) {
+        psAbort(__func__, "input parameter fpaCoord is NULL.");
+    }
+    if (chip == NULL) {
+        psAbort(__func__, "input parameter chip is NULL.");
+    }
+
+    psFPA *FPA = chip->parent;
+    if (FPA == NULL) {
+        psAbort(__func__, "chip->parent is NULL");
+    }
+
+    psChip *newChip = psChipInFPA(newChip, fpaCoord, FPA);
+    if (newChip == NULL) {
+        return(NULL);
+    }
+
+    chipCoord = psPlaneTransformApply(chipCoord, newChip->fromFPA, fpaCoord);
+    psFree(newChip);
+    return(chipCoord);
+}
+
 psPlane* psCoordChipToCell(psPlane* cellCoord,
                            const psPlane* chipCoord,
                            const psCell* cell)
 {
-    return (psPlaneTransformApply(cellCoord, cell->fromChip, chipCoord));
-}
-
-/*****************************************************************************
-XXX: once this works, get rid of the individual pointers for the various
-     coords.
-XXX: must determine which cell contains this chipcoord.
- *****************************************************************************/
+    if (chipCoord == NULL) {
+        psAbort(__func__, "input parameter chipCoord is NULL.");
+    }
+    if (cell == NULL) {
+        psAbort(__func__, "input parameter cell is NULL.");
+    }
+
+    psChip *chip = cell->parent;
+    if (chip == NULL) {
+        psAbort(__func__, "cell->parent is NULL");
+    }
+
+    psCell *newCell = psCellInChip(newCell, chipCoord, chip);
+    if (newCell == NULL) {
+        return(NULL);
+    }
+
+    cellCoord = psPlaneTransformApply(cellCoord, newCell->fromChip, chipCoord);
+    psFree(newCell);
+    return(cellCoord);
+}
+
 psPlane* psCoordSkyToCell(psPlane* cellCoord,
                           const psSphere* skyCoord,
@@ -402,7 +513,14 @@
                           const psCell* cell)
 {
-    psChip *whichChip = cell->parent;
-    psFPA *whichFPA = whichChip->parent;
-    psGrommit* grommit = whichFPA->grommit;
+    if (skyCoord == NULL) {
+        psAbort(__func__, "input parameter skyCoord is NULL.");
+    }
+    if (cell == NULL) {
+        psAbort(__func__, "input parameter cell is NULL.");
+    }
+
+    psChip *parChip = cell->parent;
+    psFPA *parFPA = parChip->parent;
+    psGrommit* grommit = parFPA->grommit;
 
     // Convert the skyCoords to tangent plane coords.
@@ -411,8 +529,8 @@
     // Convert the tangent plane coords to FPA coords.
     psPlane *fpaCoord = psCoordTPToFPA(fpaCoord, tpCoord, color,
-                                       magnitude, whichFPA);
+                                       magnitude, parFPA);
 
     // Convert the FPA coords to chip coords.
-    psPlane *chipCoord = psCoordFPAToChip(chipCoord, fpaCoord, whichChip);
+    psPlane *chipCoord = psCoordFPAToChip(chipCoord, fpaCoord, parChip);
 
     // Convert the chip coords to cell coords.
@@ -427,10 +545,67 @@
 
 /*****************************************************************************
-XXX: hmmm: does this work?
+p_psIsProjectionLinear(): this is a private function which simply determines
+if the supplied psPlaneTransform transform is linear: if any of the
+cooefficients of order 2 are higher are non-zero, then it is not linear.
  *****************************************************************************/
+int p_psIsProjectionLinear(psPlaneTransform *transform)
+{
+    int i = 0;
+    if (transform == NULL) {
+        psAbort(__func__, "input parameter transform is NULL.");
+    }
+
+    for (i=2;i<(transform->x->nX);i++) {
+        if (transform->x->coeff[i][0] != 0.0) {
+            return(0);
+        }
+    }
+    for (i=2;i<(transform->x->nY);i++) {
+        if (transform->x->coeff[0][i] != 0.0) {
+            return(0);
+        }
+    }
+
+    for (i=2;i<(transform->y->nX);i++) {
+        if (transform->y->coeff[i][0] != 0.0) {
+            return(0);
+        }
+    }
+    for (i=2;i<(transform->y->nY);i++) {
+        if (transform->y->coeff[0][i] != 0.0) {
+            return(0);
+        }
+    }
+
+    return(1);
+}
+
+/*****************************************************************************
+p_psInvertPlaneTransform(transform): : this is a private function which
+simply inverts the supplied psPlaneTransform transform.  It assumes that
+"transform" is linear.
+ *****************************************************************************/
+psPlaneTransform *p_psInvertPlaneDistortTransform(psPlaneTransform *transform)
+{
+    if (transform == NULL) {
+        psAbort(__func__, "input parameter transform is NULL.");
+    }
+    psPlaneTransform *out = psAlloc(sizeof(psPlaneTransform));
+
+    // XXX: figure it out
+    return(out);
+}
+
 psPlane* psCoordSkyToCellQuick(psPlane* cellCoord,
                                const psSphere* skyCoord,
                                const psCell* cell)
 {
+    if (skyCoord == NULL) {
+        psAbort(__func__, "input parameter skyCoord is NULL.");
+    }
+    if (cell == NULL) {
+        psAbort(__func__, "input parameter cell is NULL.");
+    }
+
     psPlane *tpCoord = NULL;
     psChip *whichChip = cell->parent;
@@ -449,7 +624,10 @@
     tpCoord = psProject(skyCoord, whichFPA->projection);
 
-    // XXX: generate an error if cell->toTP is not linear.
-
-    // XXX: Invert cell->toTP, store in TPtoCell.
+    // generate an error if cell->toTP is not linear.
+    if (0 == p_psIsProjectionLinear(cell->toTP)) {
+        psAbort(__func__, "the cell->toTP transfrom is not linear.\n");
+    }
+
+    TPtoCell = p_psInvertPlaneDistortTransform(cell->toTP);
     cellCoord = psPlaneTransformApply(cellCoord, TPtoCell, tpCoord);
 
Index: /trunk/psLib/src/astronomy/psAstrometry.h
===================================================================
--- /trunk/psLib/src/astronomy/psAstrometry.h	(revision 1513)
+++ /trunk/psLib/src/astronomy/psAstrometry.h	(revision 1514)
@@ -8,6 +8,6 @@
 *  @author George Gusciora, MHPCC
 *
-*  @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-08-12 03:11:45 $
+*  @version $Revision: 1.21 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-08-12 05:36:53 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -204,4 +204,5 @@
     const float humidity;              ///< Relative humidity, for refraction
     const float exposureTime;          ///< Exposure time
+    const double wavelength;           ///< Wavelength
 
     /* Derived quantities */
