Index: /trunk/psModules/src/camera/pmHDUGenerate.c
===================================================================
--- /trunk/psModules/src/camera/pmHDUGenerate.c	(revision 15298)
+++ /trunk/psModules/src/camera/pmHDUGenerate.c	(revision 15299)
@@ -13,4 +13,6 @@
 #include "pmFPALevel.h"
 #include "pmHDUUtils.h"
+#include "pmConcepts.h"
+#include "pmConceptsStandard.h"
 #include "pmHDUGenerate.h"
 
@@ -169,4 +171,56 @@
     return true;
 }
+
+// Attempt to read CELL.TRIMSEC and CELL.BIASSEC from the cell format if they are specified by VALUE
+static bool readTrimBias(psList *cells // List of cells below the HDU
+    )
+{
+    bool mdok;                          // Status of MD lookup
+    psListIterator *cellsIter = psListIteratorAlloc(cells, PS_LIST_HEAD, false); // Iterator for cells
+    pmCell *cell = NULL;                // Cell from iteration
+    bool allFixed = true;               // We're able to fix all TRIMSEC and BIASSEC
+    while ((cell = psListGetAndIncrement(cellsIter))) {
+        psMetadataItem *trimsecItem = psMetadataLookup(cell->concepts, "CELL.TRIMSEC"); // Item with trimsec
+        if (!trimsecItem || trimsecItem->type != PS_DATA_REGION) {
+            psWarning("CELL.TRIMSEC has not been initialised in cell --- ignored.\n");
+            return false;
+        }
+        psRegion *trimsec = trimsecItem->data.V; // Trim section
+        if (psRegionIsNaN(*trimsec)) {
+            const char *trimsecSource = psMetadataLookupStr(&mdok, cell->config, "CELL.TRIMSEC.SOURCE");
+            if (strcmp(trimsecSource, "VALUE") == 0) {
+
+                const char *trimsecStr = psMetadataLookupStr(&mdok, cell->config, "CELL.TRIMSEC");
+                *trimsec = psRegionFromString(trimsecStr);
+            } else {
+                allFixed = false;
+            }
+        }
+
+        psMetadataItem *biassecItem = psMetadataLookup(cell->concepts, "CELL.BIASSEC"); // Bias sections
+        if (!biassecItem) {
+            psWarning("CELL.BIASSEC has not been initialised in cell --- ignored.\n");
+            return false;
+        }
+        psList *biassecs = biassecItem->data.V;
+        if (biassecs->n != 0) {
+            allFixed = false;
+            continue;
+        }
+
+        const char *biassecSource = psMetadataLookupStr(&mdok, cell->config, "CELL.BIASSEC.SOURCE");
+        if (strcmp(biassecSource, "VALUE") == 0) {
+            const char *biassecStr = psMetadataLookupStr(&mdok, cell->config, "CELL.BIASSEC");
+            psFree(biassecItem->data.V);
+            biassecItem->data.V = p_pmConceptParseRegions(biassecStr);
+        } else {
+            allFixed = false;
+        }
+    }
+    psFree(cellsIter);
+
+    return allFixed;
+}
+
 
 // Generate CELL.TRIMSEC and CELL.BIASSEC for the cells
@@ -341,5 +395,7 @@
     // Get the size of the HDU, either from existing trimsec and biassec, or generate these and try again
     int xSize = 0, ySize = 0;           // Size of HDU
-    if (!sizeHDU(&xSize, &ySize, cells) && !(generateTrimBias(cells) && sizeHDU(&xSize, &ySize, cells))) {
+    if (!sizeHDU(&xSize, &ySize, cells) &&
+        !(readTrimBias(cells) && sizeHDU(&xSize, &ySize, cells)) &&
+        !(generateTrimBias(cells) && sizeHDU(&xSize, &ySize, cells))) {
         psError(PS_ERR_IO, true, "Unable to determine size of HDU!\n");
         return false;
Index: /trunk/psModules/src/concepts/pmConceptsStandard.c
===================================================================
--- /trunk/psModules/src/concepts/pmConceptsStandard.c	(revision 15298)
+++ /trunk/psModules/src/concepts/pmConceptsStandard.c	(revision 15299)
@@ -329,4 +329,36 @@
 }
 
+
+psList *p_pmConceptParseRegions(const char *region)
+{
+    assert(region && strlen(region) > 0);
+
+    psList *list = psListAlloc(NULL);   // List of regions
+
+    // a single BIASSEC is of the form [AAAA]
+    // we may have multiple BIASSEC entries separated by space, commas, or semicolons
+    int xParity = 0, yParity = 0;       // Parity of region
+    char *p = strchr (region, '[');
+    while (p) {
+        char *q = strchr (p, ']');
+        if (!q) {
+            break;
+        }
+        char *regionString = psStringAlloc(q - p + 2);
+        strncpy (regionString, p, q - p + 1);
+        regionString[q - p + 1] = 0;
+
+        psRegion *region = psAlloc(sizeof(psRegion)); // The region
+        *region = psRegionAndParityFromString(&xParity, &yParity, regionString);
+        psListAdd(list, PS_LIST_TAIL, region);
+        psFree(region);           // Drop reference
+        psFree(regionString);     // Drop reference
+
+        p = strchr (q, '[');
+    }
+
+    return list;
+}
+
 psMetadataItem *p_pmConceptParse_CELL_BIASSEC(const psMetadataItem *concept,
                                               const psMetadataItem *pattern,
@@ -341,31 +373,13 @@
     assert(pattern);
 
-    psList *biassecs = psListAlloc(NULL); // List of bias sections
+    psList *biassecs; // List of bias sections
 
     switch (concept->type) {
       case PS_DATA_STRING: {
-          // a single BIASSEC is of the form [AAAA]
-          // we may have multiple BIASSEC entries separated by space, commas, or semicolons
-          int xParity = 0;
-          int yParity = 0;
-          char *p = strchr (concept->data.V, '[');
-          while (p != NULL) {
-              char *q = strchr (p, ']');
-              if (q == NULL) break;
-              char *regionString = psAlloc (q - p + 2);
-              strncpy (regionString, p, q - p + 1);
-              regionString[q - p + 1] = 0;
-
-              psRegion *region = psAlloc(sizeof(psRegion)); // The region
-              *region = psRegionAndParityFromString(&xParity, &yParity, regionString);
-              psListAdd(biassecs, PS_LIST_TAIL, region);
-              psFree(region);           // Drop reference
-              psFree(regionString);     // Drop reference
-
-              p = strchr (q, '[');
-          }
+          biassecs = p_pmConceptParseRegions(concept->data.V);
           break;
       }
       case PS_DATA_LIST: {
+          biassecs = psListAlloc(NULL);
           psList *regions = concept->data.V; // The list of regions
           psListIterator *regionsIter = psListIteratorAlloc(regions, PS_LIST_HEAD, false); // Iterator
Index: /trunk/psModules/src/concepts/pmConceptsStandard.h
===================================================================
--- /trunk/psModules/src/concepts/pmConceptsStandard.h	(revision 15298)
+++ /trunk/psModules/src/concepts/pmConceptsStandard.h	(revision 15299)
@@ -4,6 +4,6 @@
  * @author Paul Price, IfA
  *
- * @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
- * @date $Date: 2007-03-30 21:12:56 $
+ * @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
+ * @date $Date: 2007-10-12 03:18:11 $
  * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
  */
@@ -14,4 +14,8 @@
 /// @addtogroup Concepts Data Abstraction Concepts
 /// @{
+
+/// Parse a list of region specifiers on a line
+psList *p_pmConceptParseRegions(const char *region ///< Regions, separated by whitespace
+    );
 
 /// Parse the FPA.FILTER concept to apply a lookup table
