Index: trunk/psModules/src/concepts/pmConceptsWrite.c
===================================================================
--- trunk/psModules/src/concepts/pmConceptsWrite.c	(revision 18163)
+++ trunk/psModules/src/concepts/pmConceptsWrite.c	(revision 22699)
@@ -16,4 +16,6 @@
 #include "pmConcepts.h"
 #include "pmConceptsRead.h"
+
+#include "pmConceptsWrite.h"
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -320,5 +322,5 @@
 
 bool p_pmConceptsWriteToDefaults(const psMetadata *specs, const pmFPA *fpa, const pmChip *chip,
-                                 const pmCell *cell, psMetadata *concepts)
+                                 const pmCell *cell, const psMetadata *concepts)
 {
     PS_ASSERT_PTR_NON_NULL(specs, false);
@@ -486,2 +488,107 @@
     #endif
 }
+
+
+
+
+
+// Write all registered concepts for the specified level
+static bool conceptsWrite(psMetadata **specs, // One of the concepts specifications
+                          const pmFPA *fpa,   // The FPA
+                          const pmChip *chip, // The chip
+                          const pmCell *cell, // The cell
+                          pmConceptSource source, // The source of the concepts to write
+                          pmConfig *config, // Configuration
+                          psMetadata *concepts // The concepts to write out
+                         )
+{
+    assert(specs);
+    assert(concepts);
+
+    pmConceptsInit();
+
+    psTrace("psModules.concepts", 3, "Writing concepts (%p %p %p): %d\n", fpa, chip, cell, source);
+
+    if (source & PM_CONCEPT_SOURCE_CELLS) {
+        p_pmConceptsWriteToCells(*specs, cell, concepts);
+    }
+    if (source & PM_CONCEPT_SOURCE_DEFAULTS) {
+        p_pmConceptsWriteToDefaults(*specs, fpa, chip, cell, concepts);
+    }
+    if (source & (PM_CONCEPT_SOURCE_PHU | PM_CONCEPT_SOURCE_HEADER)) {
+        p_pmConceptsWriteToHeader(*specs, fpa, chip, cell, concepts);
+    }
+    if (source & PM_CONCEPT_SOURCE_DATABASE) {
+        p_pmConceptsWriteToDatabase(*specs, fpa, chip, cell, config, concepts);
+    }
+
+    return true;
+}
+
+
+bool pmConceptsWriteFPA(const pmFPA *fpa, pmConceptSource source, bool propagateDown, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(fpa, false);
+    psMetadata *conceptsFPA = pmConceptsSpecs(PM_FPA_LEVEL_FPA); // Concept specifications
+    psTrace("psModules.concepts", 5, "Writing FPA concepts: %p %p\n", conceptsFPA, fpa->concepts);
+    bool success = conceptsWrite(&conceptsFPA, fpa, NULL, NULL, source, config, fpa->concepts);
+    if (propagateDown) {
+        psArray *chips = fpa->chips;        // Array of chips
+        for (long i = 0; i < chips->n; i++) {
+            pmChip *chip = chips->data[i];  // Chip of interest
+            if (chip && !chip->hdu) {
+                success &= pmConceptsWriteChip(chip, source, false, true, config);
+            }
+        }
+    }
+    return success;
+}
+
+
+bool pmConceptsWriteChip(const pmChip *chip, pmConceptSource source, bool propagateUp,
+                         bool propagateDown, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(chip, false);
+    psMetadata *conceptsChip = pmConceptsSpecs(PM_FPA_LEVEL_CHIP); // Concept specifications
+    psTrace("psModules.concepts", 5, "Writing chip concepts: %p %p\n", conceptsChip, chip->concepts);
+    pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
+    bool success = conceptsWrite(&conceptsChip, fpa, chip, NULL, source, config, chip->concepts);
+    if (propagateUp && !fpa->hdu) {
+        psMetadata *conceptsFPA = pmConceptsSpecs(PM_FPA_LEVEL_FPA); // Concept specifications
+        success &= conceptsWrite(&conceptsFPA, fpa, chip, NULL, source, config, fpa->concepts);
+    }
+    if (propagateDown) {
+        psArray *cells = chip->cells;        // Array of cells
+        for (long i = 0; i < cells->n; i++) {
+            pmCell *cell = cells->data[i];  // Cell of interest
+            if (cell && !cell->hdu) {
+                success &= pmConceptsWriteCell(cell, source, false, config);
+            }
+        }
+    }
+    return success;
+}
+
+
+bool pmConceptsWriteCell(const pmCell *cell, pmConceptSource source, bool propagateUp, pmConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(cell, false);
+    psMetadata *conceptsCell = pmConceptsSpecs(PM_FPA_LEVEL_CELL); // Concept specifications
+    psTrace("psModules.concepts", 5, "Writing cell concepts: %p %p\n", conceptsCell, cell->concepts);
+    pmChip *chip = cell->parent;        // Chip to which the cell belongs
+    pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
+
+    bool success = conceptsWrite(&conceptsCell, fpa, chip, cell, source, config, cell->concepts);
+    if (propagateUp) {
+        if (!chip->hdu) {
+            psMetadata *conceptsChip = pmConceptsSpecs(PM_FPA_LEVEL_CHIP); // Concept specifications
+            success &= conceptsWrite(&conceptsChip, fpa, chip, cell, source, config, chip->concepts);
+            if (!fpa->hdu) {
+                psMetadata *conceptsFPA = pmConceptsSpecs(PM_FPA_LEVEL_FPA); // Concept specifications
+                success &= conceptsWrite(&conceptsFPA, fpa, chip, cell, source, config, fpa->concepts);
+            }
+        }
+    }
+
+    return success;
+}
