Index: /trunk/archive/modules/src/pmFPAfromHeader.c
===================================================================
--- /trunk/archive/modules/src/pmFPAfromHeader.c	(revision 2517)
+++ /trunk/archive/modules/src/pmFPAfromHeader.c	(revision 2517)
@@ -0,0 +1,385 @@
+
+/*** still need to use the values from the header to define the offset values.
+     make this a separate function (still divided into Chip/Cell Base versions
+     where does PHU go?
+***/
+
+psFPA *pmFPAfromHeader (psMetadata *headers, psMetadata *camera) {
+
+    char *extType = NULL;
+    psFPA *fpa = NULL;
+
+    extType = psMetadataLookup(camera, "EXT.TYPE");
+
+    if (!strcasecmp (extType, "cell")) {
+	fpa = pmFPAfromHeader_CellBase (headers, camera);
+	return (fpa);
+    } 
+    if (!strcasecmp (extType, "chip")) {
+	fpa = pmFPAfromHeader_ChipBase (headers, camera);
+	return (fpa);
+    } 
+    fprintf (stderr, "unknown EXT.TYPE value %s\n", extType);
+    return (NULL);
+}
+
+/** what do we do with the PHU?  **/
+
+psFPA *pmFPAfromHeader_CellBase (psMetadata *headers, psMetadata *camera) {
+
+    char *extID   = NULL;
+    char *cellID  = NULL;
+
+    int   nCellMD = psMetadataLookupS32(camera, "NCELL");       // number of cells in camera definition file 
+    char *extKey  = psMetadataLookupPtr(camera, "EXT.KEY");     // identifier for a cell
+    char *cellFmt = psMetadataLookupPtr(camera, "CELL.FORMAT"); // format used to define the CELL keywords
+
+    psHash *chipsByID  = psHashAlloc ();		// this will store the list of cells for this chip
+    psHash *cellsByExt = psHashAlloc ();		// this will store the list of cells for this chip
+
+    psMetadata *cellMD     = NULL;
+    psMetadata *header     = NULL;
+    psListIterator *cursor = NULL;
+
+    /* construct a hash of the EXT.KEY entries (one per cell) */
+    cellsByExt = psHashAlloc ();
+    for (int i = 0; i < nCellMD; i++) {
+	sprintf (cell, cellFormat, i);
+	cellMD = psMetadataLookupPtr(camera, cell);
+	cellID = psMetadataLookupPtr(cellMD, "EXT.KEY");
+	psHashAdd (cellsByExt, cellID, cellMD);
+    }
+
+    /* examine all headers, try to find them in the CAMERA.CELL definition list */
+    cursor = psListIteratorAlloc(headers->list, PS_LIST_HEAD);
+    while ((header = (psMetadata *)psListGetNext(cursor)) != NULL) {
+	extID   = psMetadataLookupPtr(header, extKey);    // look up the EXTNAME keyword (or equiv) 
+	cellMD  = psHashLookup (cellsByExt, extID);
+	if (cellMD == NULL) {
+	    continue;  			/* extension not a valid cell */
+	}
+
+	Nreadout = MAX (psMetadataLookupS32 (header, "NAXIS3"), 1);
+	cell = psCellAlloc (Nreadout);
+	cell->metadata = psMetadataAdd (cell->metadata, PS_LIST_TAIL, "HEADER", PS_META_META, "header", header);
+	cell->metadata = psMetadataAdd (cell->metadata, PS_LIST_TAIL, "CELL", PS_META_META, "cell defs", cellMD);
+
+	chipID = psMetadataLookupPtr(cellMD, "CHIP");  // look for the chip value in this cell MD
+	cellArray = psHashLookup (chipsByID, chipID);
+	if (list == NULL) {
+	    cellArray = psArrayAlloc (10);
+	    status = psHashAdd(chipsByID, chipID, list);
+	}
+	status = psArrayAdd (cellArray, cell, 10);
+    }
+    psFree (cursor);
+
+    chipArray = psArrayFromHash (chipsByID);
+
+    fpa = psFPAAlloc ();
+    fpa->chips = psArrayAlloc(chipArray->n);
+    for (int i = 0; i < chipArray->n; i++) {
+	fpa->chips->data[i] = psChipAlloc ();
+	chip = fpa->chips->data[i];
+	chip->cells = chipArray->data[i];
+    }
+    fpa->metadata = psMetadataAdd (fpa->metadata, PS_LIST_TAIL, "CAMERA", PS_META_META, "camera definition data", camera);
+
+    pmFPA_DefineOffsets_CellBase (fpa);
+    return (fpa);
+}
+
+psFPA *pmFPAfromHeader_ChipBase (psMetadata *headers, psMetadata *camera) {
+
+    char *extID   = NULL;
+    char *cellID  = NULL;
+
+    int   nCellMD = psMetadataLookupS32(camera, "NCELL");
+    char *extKey  = psMetadataLookupPtr(camera, "EXT.KEY");
+    char *cellFmt = psMetadataLookupPtr(camera, "CELL.FMT");
+
+    psHash *chipsByID  = psHashAlloc ();		// this will store the list of cells for this chip
+    psHash *cellsByExt = psHashAlloc ();		// this will store the list of cells for this chip
+
+    psMetadata *cellMD     = NULL;
+    psMetadata *header     = NULL;
+    psListIterator *cursor = NULL;
+
+    /* construct a hash of the EXT.KEY entries (one per chip) */
+    chipsByExt = psHashAlloc ();
+    for (int i = 0; i < nCellMD; i++) {
+	char cell[64];
+	sprintf (cell, cellFormat, i);
+	cellMD = psMetadataLookupPtr(camera, cell);
+	chipID = psMetadataLookupPtr(cellMD, "EXT.KEY");
+	cells  = psHashLookup (chipsByExt, chipID);
+	if (cells == NULL) {
+	    cells = psListAlloc ();
+	    psHashAdd (chipsByExt, cellID, cells);
+	}
+	psListAdd (cells, PS_LIST_TAIL, cellMD);
+    }
+
+    chipArray = psArrayAlloc (10);
+    chipArray->n = 0;
+
+    /* examine all headers, try to find them in the CAMERA.CELL definition list */
+    cursor = psListIteratorAlloc(headers->list, PS_LIST_HEAD);
+    while ((header = (psMetadata *)psListGetNext(cursor)) != NULL) {
+	extID = psMetadataLookupPtr(header, extKey);
+	cells = psHashLookup(chipsByExt, extID);
+	if (cells == NULL) {
+	    continue;  			/* extension not a valid cell */
+	}
+
+	cellArray = psArrayFromList (cells);
+	Nreadout = MAX (psMetadataLookupS32 (header, "NAXIS3"), 1);
+
+	chip = psChipAlloc ();
+	chipArray = psArrayAdd (chipArray, chip, 10);
+
+	chip->cells = psArrayAlloc(cellArray->n);
+	for (i = 0; i < cellArray->n; i++) {
+	    chip->cells->data[i] = psCellAlloc (Nreadout);
+	    cell = chip->cells->data[i];
+	    cell->metadata = psMetadataAdd (cell->metadata, PS_LIST_TAIL, "CELL", PS_META_META, "cell defs", cellArray->data[i]);
+	}	    
+	chip->metadata = psMetadataAdd (chip->metadata, PS_LIST_TAIL, "HEADER", PS_META_META, "header", header);
+    }
+    psFree (cursor);
+    pmFPA_DefineOffsets_CellBase (fpa);
+    return (fpa);
+}
+
+/* define the values for fpa->chip.x0,y0, etc */
+bool pmFPADefineOffsets_CellBase (psFPA fpa) {
+
+    for (i = 0; i < fpa->chips->n; i++) {
+	chip = fpa->chips->data[i];
+	chip.x0 = 0;
+	chip.y0 = 0;
+	
+	for (j = 0; j < chip->cells->n; j++) {
+	    cell = chip->cells->data[i];
+
+	    header  = psMetadataLookupPtr(cell->metadata, "HEADER");
+	    cellMD  = psMetadataLookupPtr(cell->metadata, "CELL.MD");
+	    detsec  = pmRegionFromConfig(cellMD, header, "DETSEC");
+	    datasec = pmRegionFromConfig(cellMD, header, "DATASEC");
+
+	    xBin = pmConfigLookupS32(cellMD, header, "CCDBIN1");
+	    yBin = pmConfigLookupS32(cellMD, header, "CCDBIN2");
+
+	    cell.xP = (datasec.x0 > datasec.x1) ? -1 : 1;
+	    cell.yP = (datasec.y0 > datasec.y1) ? -1 : 1;
+	    
+	    cell.x0 = f(datasec,detsec);
+	    cell.y0 = f(datasec,detsec);
+	}
+    }
+}
+
+/* define the values for fpa->chip.x0,y0, etc */
+bool pmFPADefineOffsets_ChipBase (psFPA fpa) {
+
+    for (i = 0; i < fpa->chips->n; i++) {
+	chip = fpa->chips->data[i];
+	chip.x0 = 0;
+	chip.y0 = 0;
+	
+	/** need to get the cell IDs from AMPLIST **/
+	header = psMetadataLookupPtr(chip->metadata, "HEADER");
+
+	for (j = 0; j < chip->cells->n; j++) {
+	    cell = chip->cells->data[i];
+
+	    cellMD  = psMetadataLookupPtr(cell->metadata, "CELL.MD");
+	    detsec  = pmConfigFindRegion(cellMD, header, "DETSEC");
+	    datasec = pmConfigFindRegion(cellMD, header, "DATASEC");
+
+	    xBin = pmConfigLookupS32(cellMD, header, "CCDBIN1");
+	    yBin = pmConfigLookupS32(cellMD, header, "CCDBIN2");
+
+	    cell.xP = (datasec.x0 > datasec.x1) ? -1 : 1;
+	    cell.yP = (datasec.y0 > datasec.y1) ? -1 : 1;
+	    
+	    cell.x0 = f(datasec,detsec);
+	    cell.y0 = f(datasec,detsec);
+	}
+    }
+}
+
+psReadout *pmReadoutLoad (psReadout *input, psFits *f, psCell *cell, int plane) {
+
+    psReadout *readout;
+    psRegion *region;
+
+    readout = input;
+    if (readout == NULL) {
+	readout = psReadoutAlloc();
+    }
+
+    region = psRegionFromConfig (cell, header, "READOUT");
+    readout->image = psFitsReadImageSection(NULL, f, region, plane);
+    // does this read the header again?  if not, it needs the header
+
+    return (readout);
+}
+
+psRegion *pmConfigLookupRegion (psMetadata *config, psMetadata *header, char *name) {
+
+    char *source, *string;
+    psRegion *region;
+
+    source = psMetadataLookupPtr (config, name);
+
+    if (!strcasecmp (source, "NONE")) {
+	region = psRegionAlloc (0, 0, 0, 0); // the NULL section
+	return (region);
+    }
+
+    if (!strncasecmp (source, "HD:", 7)) {
+	char *keyword;
+    
+	keyword = &source[7]; 
+	string = psMetadataLookupPtr (readout[0].metadata, keyword);
+	region = psRegionFromString (string);
+	psFree (string);
+	psFree (source);
+	return (region);
+    }
+
+    if (!strncasecmp (source, "CF:", 7)) {
+	string = &source[7]; 
+	region = psRegionFromString (string);
+	psFree (source);
+	return (region);
+    }
+
+    psError ("invalid section");
+    return (NULL);
+
+}
+
+psS32 pmConfigLookupS32 (psMetadata *config, psMetadata *header, char *name) {
+
+    char *source, *string;
+    psS32 value;
+
+    source = psMetadataLookupPtr (config, name);
+
+    if (!strcasecmp (source, "NONE")) {
+	psFree (source);
+	return (0);
+    }
+
+    if (!strncasecmp (source, "HD:", 7)) {
+	char *keyword;
+    
+	keyword = &source[7]; 
+	value = psMetadataLookupS32 (readout[0].metadata, keyword);
+	psFree (source);
+	return (value);
+    }
+
+    if (!strncasecmp (source, "CF:", 7)) {
+	value = atoi (&source[7]);
+	return (value);
+    }
+
+    psError ("invalid key");
+    return (0);
+
+}
+
+psF64 pmConfigLookupF64 (psMetadata *config, psMetadata *header, char *name) {
+
+    char *source, *string;
+    psF64 value;
+
+    source = psMetadataLookupPtr (config, name);
+
+    if (!strcasecmp (source, "NONE")) {
+	psFree (source);
+	return (0);
+    }
+
+    if (!strncasecmp (source, "HD:", 7)) {
+	char *keyword;
+    
+	keyword = &source[7]; 
+	value = psMetadataLookupF64 (readout[0].metadata, keyword);
+	psFree (source);
+	return (value);
+    }
+
+    if (!strncasecmp (source, "CF:", 7)) {
+	value = atof (&source[7]);
+	return (value);
+    }
+
+    psError ("invalid key");
+    return (0);
+
+}
+
+void *psMetdataLookupPtr (psMetadata *md, char *key) {
+
+    void *value = NULL;
+    psMetadataItem *item = psMetadataLookup (md, key);
+
+    if (item == NULL) {
+	return (NULL);
+    }
+
+    value = item->data.V;
+    psFree (item);
+
+    return (value);
+}
+
+psS32 psMetdataLookupS32 (psMetadata *md, char *key) {
+
+    psS32 value;
+    psMetadataItem *item = psMetadataLookup (md, key);
+
+    if (item == NULL) {
+	return (0.0);
+    }
+
+    value = item->data.S32;
+    psFree (item);
+
+    return (value);
+}
+
+psF64 psMetdataLookupF64 (psMetadata *md, char *key) {
+
+    psF64 value;
+    psMetadataItem *item = psMetadataLookup (md, key);
+
+    if (item == NULL) {
+	return (0.0);
+    }
+
+    value = item->data.F64;
+    psFree (item);
+
+    return (value);
+}
+
+psArray psArrayAdd (psArray *array, void *value, int delta) {
+
+    if (delta < 1) {
+	delta = 5;
+    }
+
+    N = array->n;
+    if (N >= array->nAlloc) {
+	array = psArrayRealloc (array, array->nAlloc + delta);
+    }
+  
+    array->data[N] = value;
+    return (array);
+}
+
