Index: /branches/eam_branches/20090820/psModules/src/concepts/pmConcepts.c
===================================================================
--- /branches/eam_branches/20090820/psModules/src/concepts/pmConcepts.c	(revision 25141)
+++ /branches/eam_branches/20090820/psModules/src/concepts/pmConcepts.c	(revision 25142)
@@ -291,4 +291,5 @@
         conceptRegisterF32("FPA.FOCUS", "Telescope focus", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
         conceptRegisterF32("FPA.AIRMASS", "Airmass at boresight", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
+	// XXX p_pmConceptParse_FPA_FILTER -> p_pmConceptParse_FPA_FILTERID (and Format as well)?
         conceptRegisterStr("FPA.FILTERID", "Filter used (parsed, abstract name)", p_pmConceptParse_FPA_FILTER, p_pmConceptFormat_FPA_FILTER, NULL, false, PM_FPA_LEVEL_FPA);
         conceptRegisterStr("FPA.FILTER", "Filter used (instrument name)", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
@@ -300,6 +301,9 @@
         conceptRegisterF64("FPA.LONGITUDE", "West longitude of observatory", p_pmConceptParse_FPA_Coords, p_pmConceptFormat_FPA_Coords, NULL, false, PM_FPA_LEVEL_FPA);
         conceptRegisterF64("FPA.LATITUDE", "Latitude of observatory", p_pmConceptParse_FPA_Coords, p_pmConceptFormat_FPA_Coords, NULL, false, PM_FPA_LEVEL_FPA);
-        conceptRegisterF32("FPA.ELEVATION", "Elevation of observatory (metres)", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
-        conceptRegisterStr("FPA.OBSTYPE", "Type of observation", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterF32("FPA.ELEVATION", "Elevation of observatory (meters)", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
+
+        // conceptRegisterStr("FPA.OBSTYPE", "Type of observation", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
+        conceptRegisterStr("FPA.OBSTYPE", "Type of observation", p_pmConceptParse_FPA_OBSTYPE, p_pmConceptFormat_FPA_OBSTYPE, NULL, false, PM_FPA_LEVEL_FPA);
+
         conceptRegisterStr("FPA.OBJECT", "Object of observation", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
         conceptRegisterF64("FPA.ALT", "Altitude of boresight", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
Index: /branches/eam_branches/20090820/psModules/src/concepts/pmConceptsStandard.c
===================================================================
--- /branches/eam_branches/20090820/psModules/src/concepts/pmConceptsStandard.c	(revision 25141)
+++ /branches/eam_branches/20090820/psModules/src/concepts/pmConceptsStandard.c	(revision 25142)
@@ -4,6 +4,7 @@
 
 #include <stdio.h>
+#include <ctype.h>			// for tolower()
 #include <string.h>
-#include <strings.h>            /* for strn?casecmp */
+#include <strings.h>			// for strn?casecmp 
 #include <assert.h>
 #include <pslib.h>
@@ -318,4 +319,106 @@
             "Unable to find %s in FILTER.ID in camera configuration.\n", key);
     return NULL;
+}
+
+// FPA.OBSTYPE
+// convert concept->data.str to new value 
+psMetadataItem *p_pmConceptParse_FPA_OBSTYPE(const psMetadataItem *concept,
+                                            const psMetadataItem *pattern,
+                                            pmConceptSource source,
+                                            const psMetadata *cameraFormat,
+                                            const pmFPA *fpa,
+                                            const pmChip *chip,
+                                            const pmCell *cell)
+{
+    assert(concept);
+    assert(pattern);
+    assert(fpa);
+    assert(fpa->camera);
+
+    if (concept->type != PS_DATA_STRING) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Type for %s (%x) is not STR\n",
+                pattern->name, concept->type);
+        return NULL;
+    }
+    if (!concept->data.str || strlen(concept->data.str) == 0) {
+        return psMetadataItemAllocStr(pattern->name, pattern->comment, "");
+    }
+
+    bool mdok;                          // Status of MD lookup
+    psMetadata *table = psMetadataLookupMetadata(&mdok, fpa->camera, "OBSTYPE.TABLE");
+    if (!mdok || !table) {
+	// if the table is not defined, pass the supplied value unmodified
+        return psMetadataItemAllocStr(pattern->name, pattern->comment, concept->data.str);
+    }
+
+    // the metadata is in the format (external) STR (internal) 
+    // do a lookup to get the internal name
+    char *extname = psStringCopy (concept->data.str);
+    for (int i = 0; i < strlen(extname); i++) {
+	extname[i] = tolower(extname[i]);
+    }
+    char *name = psMetadataLookupStr (&mdok, table, extname);
+    if (!name) {
+	// if the entry is not defined, pass the supplied value unmodified
+        return psMetadataItemAllocStr(pattern->name, pattern->comment, concept->data.str);
+    }
+
+    return psMetadataItemAllocStr(pattern->name, pattern->comment, name);
+}
+
+// convert concept->data.str to new value 
+psMetadataItem *p_pmConceptFormat_FPA_OBSTYPE(const psMetadataItem *concept,
+                                             pmConceptSource source,
+                                             const psMetadata *cameraFormat,
+                                             const pmFPA *fpa,
+                                             const pmChip *chip,
+                                             const pmCell *cell)
+{
+    assert(concept);
+    assert(fpa);
+    assert(fpa->camera);
+
+    if (concept->type != PS_DATA_STRING) {
+        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Type for %s (%x) is not STR\n",
+                concept->name, concept->type);
+        return NULL;
+    }
+    if (!concept->data.str || strlen(concept->data.str) == 0) {
+        return psMetadataItemAllocStr(concept->name, concept->comment, "");
+    }
+
+    bool mdok;                          // Status of MD lookup
+    psMetadata *table = psMetadataLookupMetadata(&mdok, fpa->camera, "OBSTYPE.TABLE");
+    if (!mdok || !table) {
+	// if the table is not defined, pass the supplied value unmodified
+        return psMetadataItemAllocStr(concept->name, concept->comment, concept->data.str);
+    }
+
+    const char *key = concept->data.str;        // The name to look up
+    if (!key || strlen(key) == 0) {
+        return psMetadataItemAllocStr(concept->name, concept->comment, NULL);
+    }
+
+    // the metadata is in the format (internal) STR (external)
+    // do a reverse lookup to get the internal name
+    psMetadataIterator *iter = psMetadataIteratorAlloc(table, PS_LIST_HEAD, NULL); // Iterator for filters
+    psMetadataItem *item;               // Item from iteration
+    char *name = NULL;                  // The winning name
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        if (item->type != PS_DATA_STRING) {
+            psWarning("Type for %s (%x) in OBSTYPE.TABLE in camera configuration is not STR\n", item->name, item->type);
+            continue;
+        }
+        if (strcmp(item->data.str, key) == 0) {
+            name = item->name;
+            break;
+        }
+    }
+    psFree(iter);
+
+    if (!name) {
+	return psMetadataItemAllocStr(concept->name, concept->comment, key);
+    }
+    return psMetadataItemAllocStr(concept->name, concept->comment, name);
 }
 
Index: /branches/eam_branches/20090820/psModules/src/concepts/pmConceptsStandard.h
===================================================================
--- /branches/eam_branches/20090820/psModules/src/concepts/pmConceptsStandard.h	(revision 25141)
+++ /branches/eam_branches/20090820/psModules/src/concepts/pmConceptsStandard.h	(revision 25142)
@@ -72,4 +72,25 @@
     );
 
+/// Parse the FPA.OBSTYPE concept to apply a lookup table
+psMetadataItem *p_pmConceptParse_FPA_OBSTYPE(
+    const psMetadataItem *concept, ///< Concept to parse
+    const psMetadataItem *pattern, ///< Pattern to use in parsing
+    pmConceptSource source, ///< Source for concept
+    const psMetadata *cameraFormat, ///< Camera format definition
+    const pmFPA *fpa, ///< FPA for concept, or NULL
+    const pmChip *chip, ///< Chip for concept, or NULL
+    const pmCell *cell ///< Cell for concept, or NULL
+    );
+
+/// Format the FPA.OBSTYPE concept to (reverse-)apply a lookup table
+psMetadataItem *p_pmConceptFormat_FPA_OBSTYPE(
+    const psMetadataItem *concept, ///< Concept to format
+    pmConceptSource source, ///< Source for concept
+    const psMetadata *cameraFormat, ///< Camera format definition
+    const pmFPA *fpa, ///< FPA for concept, or NULL
+    const pmChip *chip, ///< Chip for concept, or NULL
+    const pmCell *cell ///< Cell for concept, or NULL
+    );
+
 /// Parse the coordinates concepts: FPA.RA and FPA.DEC
 psMetadataItem *p_pmConceptParse_FPA_Coords(
