Index: /trunk/psModules/src/camera/pmFPAfile.c
===================================================================
--- /trunk/psModules/src/camera/pmFPAfile.c	(revision 7678)
+++ /trunk/psModules/src/camera/pmFPAfile.c	(revision 7679)
@@ -114,29 +114,4 @@
 }
 
-// XXX reconsider this function name / concept
-# if 0
-bool pmFPAfileAddFileNames (psMetadata *files, char *name, char *value, int mode)
-{
-    PS_ASSERT_PTR_NON_NULL(files, false);
-    PS_ASSERT_PTR_NON_NULL(name, false);
-    PS_ASSERT_INT_POSITIVE(strlen(name), false);
-    PS_ASSERT_PTR_NON_NULL(value, false);
-    PS_ASSERT_INT_POSITIVE(strlen(value), false);
-
-    // add the output names to the output-type files
-    psMetadataItem *item = NULL;
-    psMetadataIterator *iter = psMetadataIteratorAlloc (files, PS_LIST_HEAD, NULL);
-    while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
-        pmFPAfile *file = item->data.V;
-
-        if (file->mode == mode) {
-            psMetadataAddStr (file->names, PS_LIST_TAIL, name, PS_META_NO_REPLACE, "", value);
-        }
-    }
-    psFree (iter);
-    return true;
-}
-# endif
-
 // select the rule from the camera configuration, perform substitutions as needed
 char *pmFPAfileNameFromRule (char *rule, pmFPAfile *file, const pmFPAview *view)
@@ -166,4 +141,14 @@
         }
     }
+    if (strstr (newName, "{CHIP.N}") != NULL) {
+        char *name = NULL;
+        if (view->chip < 0) {
+            psStringAppend (&name, "XX");
+        } else {
+            psStringAppend (&name, "%02d", view->chip);
+        }
+        newName = psStringSubstitute (newName, name, "{CHIP.N}");
+        psFree (name);
+    }
     if (strstr (newName, "{CELL.NAME}") != NULL) {
         pmCell *cell = pmFPAviewThisCell (view, file->fpa);
@@ -175,4 +160,13 @@
         }
     }
+    if (strstr (newName, "{CELL.N}") != NULL) {
+        char *name = NULL;
+        if (view->cell < 0) {
+            psStringAppend (&name, "XX");
+        } else {
+            psStringAppend (&name, "%02d", view->cell);
+        }
+        newName = psStringSubstitute (newName, name, "{CELL.N}");
+    }
     if (strstr (newName, "{EXTNAME}") != NULL) {
         pmHDU *hdu = pmFPAviewThisHDU (view, file->fpa);
@@ -181,4 +175,30 @@
         }
     }
+    if (strstr (newName, "{FILTER}") != NULL) {
+        if (file->fpa != NULL) {
+            char *name = psMetadataLookupStr (NULL, file->fpa->concepts, "FPA.FILTER");
+            if (name != NULL) {
+                newName = psStringSubstitute (newName, name, "{FILTER}");
+            }
+        }
+    }
+    if (strstr (newName, "{CAMERA}") != NULL) {
+        if (file->fpa != NULL) {
+            char *name = psMetadataLookupStr (NULL, file->fpa->concepts, "FPA.CAMERA");
+            if (name != NULL) {
+                newName = psStringSubstitute (newName, name, "{CAMERA}");
+            }
+        }
+    }
+    if (strstr (newName, "{FILTER.ID}") != NULL) {
+        if (file->fpa != NULL) {
+            char *filterName = psMetadataLookupStr (NULL, file->fpa->concepts, "FPA.FILTER");
+            psMetadata *filterTable = psMetadataLookupPtr (NULL, file->camera, "FILTER.ID");
+            if (filterName && filterTable) {
+                char *ID = psMetadataLookupStr (NULL, filterTable, filterName);
+                newName = psStringSubstitute (newName, ID, "{FILTER.ID}");
+            }
+        }
+    }
     return newName;
 }
Index: /trunk/psModules/src/camera/pmFPAfileDefine.c
===================================================================
--- /trunk/psModules/src/camera/pmFPAfileDefine.c	(revision 7678)
+++ /trunk/psModules/src/camera/pmFPAfileDefine.c	(revision 7679)
@@ -115,4 +115,5 @@
     if (fpa != NULL) {
         file->fpa = psMemIncrRefCounter(fpa);
+        file->camera = psMemIncrRefCounter((psMetadata *)fpa->camera);
     }
 
Index: /trunk/psModules/src/concepts/Makefile.am
===================================================================
--- /trunk/psModules/src/concepts/Makefile.am	(revision 7678)
+++ /trunk/psModules/src/concepts/Makefile.am	(revision 7679)
@@ -7,5 +7,6 @@
 	pmConceptsRead.c \
 	pmConceptsWrite.c \
-	pmConceptsStandard.c
+	pmConceptsStandard.c \
+	pmConceptsPhotcode.c
 
 psmoduleincludedir = $(includedir)
@@ -14,5 +15,6 @@
 	pmConceptsRead.h \
 	pmConceptsWrite.h \
-	pmConceptsStandard.h
+	pmConceptsStandard.h \
+	pmConceptsPhotcode.h
 
 CLEANFILES = *~
Index: /trunk/psModules/src/concepts/pmConcepts.c
===================================================================
--- /trunk/psModules/src/concepts/pmConcepts.c	(revision 7678)
+++ /trunk/psModules/src/concepts/pmConcepts.c	(revision 7679)
@@ -409,4 +409,11 @@
         #endif
 
+        // FPA.CAMERA
+        {
+            psMetadataItem *fpaCamera = psMetadataItemAllocStr("FPA.CAMERA", "Camera used", "");
+            pmConceptRegister(fpaCamera, NULL, NULL, PM_FPA_LEVEL_FPA);
+            psFree(fpaCamera);
+        }
+
         // FPA.AIRMASS
         {
Index: /trunk/psModules/src/concepts/pmConceptsPhotcode.c
===================================================================
--- /trunk/psModules/src/concepts/pmConceptsPhotcode.c	(revision 7679)
+++ /trunk/psModules/src/concepts/pmConceptsPhotcode.c	(revision 7679)
@@ -0,0 +1,32 @@
+#include <stdio.h>
+#include <pslib.h>
+
+#include "pmConceptsPhotcode.h"
+
+char *pmConceptsPhotcodeForView (pmConfig *config, pmFPAfile *file, pmFPAview *view)
+{
+
+    if (view->chip < -1) {
+        psError(PS_ERR_IO, true, "photcodes undefined for FPA: defined by chip\n");
+        return NULL;
+    }
+
+    // select recipe options supplied on command line
+    psMetadata *recipe  = psMetadataLookupPtr (NULL, config->recipes, "PHASE2");
+    if (recipe == NULL) {
+        psError(PS_ERR_IO, true, "recipe PHASE2 not found\n");
+        return NULL;
+    }
+
+    // select photcode rule from recipe
+    char *rule = psMetadataLookupStr (NULL, recipe, "PHOTCODE.RULE");
+    if (rule == NULL) {
+        psError(PS_ERR_IO, true, "PHOTCODE.RULE not found in PHASE2 recipe\n");
+        return NULL;
+    }
+
+    // convert rule to real photcode
+    char *photcode = pmFPAfileNameFromRule (rule, file, view);
+
+    return photcode;
+}
Index: /trunk/psModules/src/concepts/pmConceptsPhotcode.h
===================================================================
--- /trunk/psModules/src/concepts/pmConceptsPhotcode.h	(revision 7679)
+++ /trunk/psModules/src/concepts/pmConceptsPhotcode.h	(revision 7679)
@@ -0,0 +1,11 @@
+#ifndef PM_CONCEPTS_PHOTCODE_H
+#define PM_CONCEPTS_PHOTCODE_H
+
+#include "pslib.h"
+#include "pmConfig.h"
+#include "pmFPAview.h"
+#include "pmFPAfile.h"
+
+char *pmConceptsPhotcodeForView (pmConfig *config, pmFPAfile *file, pmFPAview *view);
+
+# endif
Index: /trunk/psModules/src/psmodules.h
===================================================================
--- /trunk/psModules/src/psmodules.h	(revision 7678)
+++ /trunk/psModules/src/psmodules.h	(revision 7679)
@@ -12,4 +12,5 @@
 #include <pmConceptsStandard.h>
 #include <pmConceptsWrite.h>
+#include <pmConceptsPhotcode.h>
 
 // the following headers are from psModule:camera
