IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 22699


Ignore:
Timestamp:
Feb 26, 2009, 2:45:31 PM (17 years ago)
Author:
Paul Price
Message:

Reorganised the concepts files, moving the Write functions into pmConceptsWrite, and the Read functions into pmConceptsRead, which sort of makes sense. Added new type of concept property: copy. Most concepts use the default copy method (which is to simply copy the item), but for the TIMESYS concepts, we want to ensure that the target is of the correct type --- if it's already set (e.g., via the DEFAULTS), then we don't copy it. This will allow us to set the target TIMESYS using the DEFAULTS in the camera format, and have the output time be adjusted appropriately. Without this, the TIMESYS is simply copied, and specifying the TIMESYS in the DEFAULTS results in a warning ('values don't match'). Removed pmFPACopyConcepts, since it is pretty much the same as pmConceptsCopyFPA.

Location:
trunk
Files:
2 added
22 edited

Legend:

Unmodified
Added
Removed
  • trunk/ppSub/src/ppSubReadoutSubtract.c

    r21524 r22699  
    8888    pmFPAfile *outFile = psMetadataLookupPtr(&mdok, config->files, "PPSUB.OUTPUT"); // Output file
    8989    pmFPA *outFPA = outFile->fpa;       // Output FPA
    90     if (!pmFPACopyConcepts(outFPA, inFPA)) {
     90    if (!pmConceptsCopyFPA(outFPA, inFPA, true, true)) {
    9191        psError(PS_ERR_UNKNOWN, false, "Unable to copy concepts from input to output.");
    9292        psFree(outRO);
  • trunk/psModules/src/camera/pmFPAConstruct.c

    r21363 r22699  
    1414#include "pmFPAview.h"
    1515#include "pmFPAFlags.h"
    16 #include "pmConcepts.h"
     16#include "pmConceptsRead.h"
    1717#include "pmFPAConstruct.h"
    1818#include "pmFPAUtils.h"
  • trunk/psModules/src/camera/pmFPACopy.c

    r22688 r22699  
    1313#include "pmFPAUtils.h"
    1414#include "pmHDUUtils.h"
    15 #include "pmConcepts.h"
     15#include "pmConceptsCopy.h"
    1616#include "pmFPACopy.h"
    1717
  • trunk/psModules/src/camera/pmFPAHeader.c

    r18163 r22699  
    1010#include "pmFPA.h"
    1111#include "pmFPALevel.h"
    12 #include "pmConcepts.h"
     12#include "pmConceptsRead.h"
    1313#include "pmFPAHeader.h"
    1414
  • trunk/psModules/src/camera/pmFPARead.c

    r21363 r22699  
    1717#include "pmFPAFlags.h"
    1818#include "pmHDUUtils.h"
    19 #include "pmConcepts.h"
     19#include "pmConceptsRead.h"
    2020#include "pmFPAHeader.h"
    2121
  • trunk/psModules/src/camera/pmFPAWrite.c

    r21363 r22699  
    1818#include "pmHDUUtils.h"
    1919#include "pmHDUGenerate.h"
    20 #include "pmConcepts.h"
     20#include "pmConceptsWrite.h"
    2121
    2222#include "pmFPAWrite.h"
  • trunk/psModules/src/camera/pmFPAfile.c

    r21363 r22699  
    1818#include "pmFPAfile.h"
    1919#include "pmFPACopy.h"
    20 #include "pmConcepts.h"
     20#include "pmConceptsCopy.h"
    2121
    2222static void pmFPAfileFree(pmFPAfile *file)
     
    409409    // XXX this should be smarter (ie, only copy concepts from the current chips)
    410410    // but such a call is needed, so re-copy stuff rather than no copy
    411     pmFPACopyConcepts (out, in);
     411    pmConceptsCopyFPA(out, in, true, true);
    412412
    413413    // pmFPAWrite takes care of all PHUs as needed
  • trunk/psModules/src/camera/pmFPAfileDefine.c

    r21314 r22699  
    2121#include "pmFPAConstruct.h"
    2222
    23 #include "pmConcepts.h"
     23#include "pmConceptsCopy.h"
    2424
    2525# define FPA_TEST_ASSERT(A){ \
     
    10241024        }
    10251025
    1026         // XXX A TEST: this is a provisional fpa until we read the first header for this pmFPAfile
    1027         // we are going to replace it when we determine the true file.  blow this away here...
    1028         psFree (file->fpa);
    1029         file->fpa = NULL;
     1026        // XXX A TEST: this is a provisional fpa until we read the first header for this pmFPAfile
     1027        // we are going to replace it when we determine the true file.  blow this away here...
     1028        psFree (file->fpa);
     1029        file->fpa = NULL;
    10301030    }
    10311031
     
    11841184
    11851185    // inherit the concepts from the src fpa:
    1186     pmFPACopyConcepts(file->fpa, file->src);
     1186    pmConceptsCopyFPA(file->fpa, file->src, true, true);
    11871187
    11881188    return file;
  • trunk/psModules/src/camera/pmFPAfileFitsIO.c

    r21363 r22699  
    2222#include "pmFPAConstruct.h"
    2323#include "pmDark.h"
    24 #include "pmConcepts.h"
     24#include "pmConceptsWrite.h"
    2525
    2626// Get a suitable FPA for the file; generate it if necessary
  • trunk/psModules/src/concepts/Makefile.am

    r11749 r22699  
    88        pmConceptsRead.c \
    99        pmConceptsWrite.c \
     10        pmConceptsCopy.c \
    1011        pmConceptsStandard.c \
    1112        pmConceptsPhotcode.c \
     
    1718        pmConceptsRead.h \
    1819        pmConceptsWrite.h \
     20        pmConceptsCopy.h \
    1921        pmConceptsStandard.h \
    2022        pmConceptsPhotcode.h \
  • trunk/psModules/src/concepts/pmConcepts.c

    r20951 r22699  
    1919#include "pmConceptsWrite.h"
    2020#include "pmConceptsStandard.h"
    21 #include "pmConceptsUpdate.h"
    2221
    2322static bool conceptsInitialised = false;// Have concepts been read?
     
    4948
    5049pmConceptSpec *pmConceptSpecAlloc(psMetadataItem *blank, pmConceptParseFunc parse,
    51                                   pmConceptFormatFunc format, bool required)
     50                                  pmConceptFormatFunc format, pmConceptCopyFunc copy,
     51                                  bool required)
    5252{
    5353    pmConceptSpec *spec = psAlloc(sizeof(pmConceptSpec));
     
    5757    spec->parse = parse;
    5858    spec->format = format;
     59    spec->copy = copy;
    5960    spec->required = required;
    6061
     
    8687}
    8788
     89psMetadata *pmConceptsSpecs(pmFPALevel level)
     90{
     91    if (!conceptsInitialised) {
     92        pmConceptsInit();
     93    }
     94
     95    // Get the appropriate concepts
     96    psMetadata *concepts = conceptsFromLevel(level); // Metadata of concepts specs
     97    if (!concepts) {
     98        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Invalid concept level provided: %d\n", level);
     99        return NULL;
     100    }
     101
     102    return concepts;
     103}
     104
    88105bool pmConceptGetRequired(const char *name, pmFPALevel level)
    89106{
     
    129146
    130147bool pmConceptRegister(psMetadataItem *blank, pmConceptParseFunc parse,
    131                         pmConceptFormatFunc format, bool required, pmFPALevel level)
     148                       pmConceptFormatFunc format, pmConceptCopyFunc copy,
     149                       bool required, pmFPALevel level)
    132150{
    133151    PS_ASSERT_PTR_NON_NULL(blank, false);
     
    144162    }
    145163
    146     pmConceptSpec *spec = pmConceptSpecAlloc(blank, parse, format, required); // The concept specification
     164    pmConceptSpec *spec = pmConceptSpecAlloc(blank, parse, format, copy, required); // Concept specification
    147165    psMetadataAdd(target, PS_LIST_TAIL, blank->name, PS_DATA_UNKNOWN | PS_META_REPLACE,
    148166                  "Concepts specification", spec);
     
    188206
    189207
    190 
    191 // Read all registered concepts for the specified level
    192 static bool conceptsRead(psMetadata **specs, // One of the concepts specifications
    193                          pmFPA *fpa,    // The FPA
    194                          pmChip *chip,  // The chip
    195                          pmCell *cell, // The cell
    196                          unsigned int *read,     // What's already been read
    197                          pmConceptSource source, // The source of the concepts to read
    198                          pmConfig *config, // Configuration
    199                          psMetadata *target // Place into which to read the concepts
    200                         )
    201 {
    202     assert(specs);
    203     assert(read);
    204     assert(target);
    205 
    206     if (!conceptsInitialised) {
    207         pmConceptsInit();
    208     }
    209 
    210     // At least one HDU is required for the reading functions
    211     pmHDU *hduLow = pmHDUGetLowest(fpa, chip, cell); // Lowest HDU.
    212     if (!hduLow) {
    213         // Can't do anything --- don't record any success, but don't return an error either
    214         return true;
    215     }
    216     pmHDU *hduHigh = pmHDUGetHighest(fpa, chip, cell); // Highest HDU
    217 
    218     if (cell && (cell->conceptsRead == PM_CONCEPT_SOURCE_NONE)) {
    219         pmConceptsBlankCell(cell);
    220         cell->conceptsRead = PM_CONCEPT_SOURCE_BLANK;
    221     }
    222     if (chip && (chip->conceptsRead == PM_CONCEPT_SOURCE_NONE)) {
    223         pmConceptsBlankChip(chip);
    224         chip->conceptsRead = PM_CONCEPT_SOURCE_BLANK;
    225     }
    226     if (fpa && (fpa->conceptsRead == PM_CONCEPT_SOURCE_NONE)) {
    227         pmConceptsBlankFPA(fpa);
    228         fpa->conceptsRead = PM_CONCEPT_SOURCE_BLANK;
    229     }
    230 
    231     bool success = true;                // Success in reading concepts?
    232     if (source & PM_CONCEPT_SOURCE_CELLS && !(*read & PM_CONCEPT_SOURCE_CELLS) && cell) {
    233         if (p_pmConceptsReadFromCells(target, *specs, cell)) {
    234             *read |= PM_CONCEPT_SOURCE_CELLS;
    235         } else {
    236             psError(PS_ERR_UNKNOWN, false, "Error reading concepts from camera configuration.\n");
    237             success = false;
    238         }
    239     }
    240 
    241     if (source & PM_CONCEPT_SOURCE_DEFAULTS && !(*read & PM_CONCEPT_SOURCE_DEFAULTS)) {
    242         if (p_pmConceptsReadFromDefaults(target, *specs, fpa, chip, cell)) {
    243             *read |= PM_CONCEPT_SOURCE_DEFAULTS;
    244         } else {
    245             psError(PS_ERR_UNKNOWN, false, "Error reading concepts from defaults.\n");
    246             success = false;
    247         }
    248     }
    249 
    250     if (source & PM_CONCEPT_SOURCE_PHU && !(*read & PM_CONCEPT_SOURCE_PHU) && hduHigh->header) {
    251         if (p_pmConceptsReadFromHeader(target, *specs, fpa, chip, cell)) {
    252             *read |= PM_CONCEPT_SOURCE_PHU;
    253         } else {
    254             psError(PS_ERR_UNKNOWN, false, "Error reading concepts from PHU.\n");
    255             success = false;
    256         }
    257     }
    258 
    259     // If there are multiple HDUs, then it may be that one of them hasn't been read yet (hdu->header not set)
    260     if (source & PM_CONCEPT_SOURCE_HEADER && !(*read & PM_CONCEPT_SOURCE_HEADER) &&
    261         hduLow != hduHigh && hduLow->header) {
    262         if (p_pmConceptsReadFromHeader(target, *specs, fpa, chip, cell)) {
    263             *read |= PM_CONCEPT_SOURCE_HEADER;
    264         } else {
    265             psError(PS_ERR_UNKNOWN, false, "Error reading concepts from header.\n");
    266             success = false;
    267         }
    268     }
    269 
    270     #ifdef HAVE_PSDB
    271     if (source & PM_CONCEPT_SOURCE_DATABASE && !(*read & PM_CONCEPT_SOURCE_DATABASE)) {
    272         if (p_pmConceptsReadFromDatabase(target, *specs, fpa, chip, cell, config)) {
    273             *read |= PM_CONCEPT_SOURCE_DATABASE;
    274         } else {
    275             psError(PS_ERR_UNKNOWN, false, "Error reading concepts from database.\n");
    276             success = false;
    277         }
    278     }
    279     #endif
    280 
    281     pmConceptsUpdate(fpa, chip, cell);
    282 
    283     return success;
    284 }
    285 
    286 // Write all registered concepts for the specified level
    287 static bool conceptsWrite(psMetadata **specs, // One of the concepts specifications
    288                           const pmFPA *fpa,   // The FPA
    289                           const pmChip *chip, // The chip
    290                           const pmCell *cell, // The cell
    291                           pmConceptSource source, // The source of the concepts to write
    292                           pmConfig *config, // Configuration
    293                           const psMetadata *concepts // The concepts to write out
    294                          )
    295 {
    296     assert(specs);
    297     assert(concepts);
    298 
    299     if (!conceptsInitialised) {
    300         pmConceptsInit();
    301     }
    302 
    303     psTrace("psModules.concepts", 3, "Writing concepts (%p %p %p): %d\n", fpa, chip, cell, source);
    304 
    305     if (source & PM_CONCEPT_SOURCE_CELLS) {
    306         p_pmConceptsWriteToCells(*specs, cell, concepts);
    307     }
    308     if (source & PM_CONCEPT_SOURCE_DEFAULTS) {
    309         p_pmConceptsWriteToDefaults(*specs, fpa, chip, cell, concepts);
    310     }
    311     if (source & (PM_CONCEPT_SOURCE_PHU | PM_CONCEPT_SOURCE_HEADER)) {
    312         p_pmConceptsWriteToHeader(*specs, fpa, chip, cell, concepts);
    313     }
    314     if (source & PM_CONCEPT_SOURCE_DATABASE) {
    315         p_pmConceptsWriteToDatabase(*specs, fpa, chip, cell, config, concepts);
    316     }
    317 
    318     return true;
    319 }
    320 
    321 
    322 bool pmConceptsRead(pmFPA *fpa, pmChip *chip, pmCell *cell, pmConceptSource source, pmConfig *config)
    323 {
    324     PS_ASSERT_PTR_NON_NULL(fpa, false);
    325     bool success = conceptsRead(&conceptsFPA, fpa, chip, cell, &fpa->conceptsRead, source,
    326                                 config, fpa->concepts);
    327     if (chip) {
    328         success &= conceptsRead(&conceptsChip, fpa, chip, cell, &chip->conceptsRead, source,
    329                                 config, chip->concepts);
    330     }
    331     if (cell) {
    332         success &= conceptsRead(&conceptsCell, fpa, chip, cell, &cell->conceptsRead, source,
    333                                 config, cell->concepts);
    334     }
    335 
    336     return success;
    337 }
    338 
    339 
    340208bool pmConceptsBlankFPA(pmFPA *fpa)
    341209{
     
    345213}
    346214
    347 
    348 bool pmConceptsReadFPA(pmFPA *fpa, pmConceptSource source, bool propagateDown, pmConfig *config)
    349 {
    350     PS_ASSERT_PTR_NON_NULL(fpa, false);
    351     psTrace("psModules.concepts", 5, "Reading FPA concepts: %p %p\n", conceptsFPA, fpa->concepts);
    352     bool success = conceptsRead(&conceptsFPA, fpa, NULL, NULL, &fpa->conceptsRead, source,
    353                                 config, fpa->concepts);
    354     if (propagateDown) {
    355         psArray *chips = fpa->chips;    // Array of chips
    356         for (long i = 0; i < chips->n; i++) {
    357             pmChip *chip = chips->data[i]; // Chip of interest
    358             if (chip) {
    359                 success &= pmConceptsReadChip(chip, source, false, true, config);
    360             }
    361         }
    362     }
    363 
    364     return success;
    365 }
    366 
    367 bool pmConceptsWriteFPA(const pmFPA *fpa, pmConceptSource source, bool propagateDown, pmConfig *config)
    368 {
    369     PS_ASSERT_PTR_NON_NULL(fpa, false);
    370     psTrace("psModules.concepts", 5, "Writing FPA concepts: %p %p\n", conceptsFPA, fpa->concepts);
    371     bool success = conceptsWrite(&conceptsFPA, fpa, NULL, NULL, source, config, fpa->concepts);
    372     if (propagateDown) {
    373         psArray *chips = fpa->chips;        // Array of chips
    374         for (long i = 0; i < chips->n; i++) {
    375             pmChip *chip = chips->data[i];  // Chip of interest
    376             if (chip && !chip->hdu) {
    377                 success &= pmConceptsWriteChip(chip, source, false, true, config);
    378             }
    379         }
    380     }
    381     return success;
    382 }
    383 
    384215bool pmConceptsBlankChip(pmChip *chip)
    385216{
     
    389220}
    390221
    391 bool pmConceptsReadChip(pmChip *chip, pmConceptSource source, bool propagateUp,
    392                         bool propagateDown, pmConfig *config)
    393 {
    394     PS_ASSERT_PTR_NON_NULL(chip, false);
    395     psTrace("psModules.concepts", 5, "Reading chip concepts: %p %p\n", conceptsChip, chip->concepts);
    396     pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
    397     bool success = conceptsRead(&conceptsChip, fpa, chip, NULL, &chip->conceptsRead, source, config,
    398                                 chip->concepts);
    399     if (propagateUp) {
    400         success &= conceptsRead(&conceptsFPA, fpa, chip, NULL, &fpa->conceptsRead, source,
    401                                 config, fpa->concepts);
    402     }
    403     if (propagateDown) {
    404         psArray *cells = chip->cells;        // Array of cells
    405         for (long i = 0; i < cells->n; i++) {
    406             pmCell *cell = cells->data[i];  // Cell of interest
    407             if (cell) {
    408                 success &= pmConceptsReadCell(cell, source, false, config);
    409             }
    410         }
    411     }
    412     return success;
    413 }
    414 
    415 bool pmConceptsWriteChip(const pmChip *chip, pmConceptSource source, bool propagateUp,
    416                          bool propagateDown, pmConfig *config)
    417 {
    418     PS_ASSERT_PTR_NON_NULL(chip, false);
    419     psTrace("psModules.concepts", 5, "Writing chip concepts: %p %p\n", conceptsChip, chip->concepts);
    420     pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
    421     bool success = conceptsWrite(&conceptsChip, fpa, chip, NULL, source, config, chip->concepts);
    422     if (propagateUp && !fpa->hdu) {
    423         success &= conceptsWrite(&conceptsFPA, fpa, chip, NULL, source, config, fpa->concepts);
    424     }
    425     if (propagateDown) {
    426         psArray *cells = chip->cells;        // Array of cells
    427         for (long i = 0; i < cells->n; i++) {
    428             pmCell *cell = cells->data[i];  // Cell of interest
    429             if (cell && !cell->hdu) {
    430                 success &= pmConceptsWriteCell(cell, source, false, config);
    431             }
    432         }
    433     }
    434     return success;
    435 }
    436 
    437222bool pmConceptsBlankCell(pmCell *cell)
    438223{
     
    440225    psTrace("psModules.concepts", 5, "Blanking cell concepts: %p %p\n", conceptsCell, cell->concepts);
    441226    return conceptsBlank(&conceptsCell, cell->concepts);
    442 }
    443 
    444 bool pmConceptsReadCell(pmCell *cell, pmConceptSource source, bool propagateUp, pmConfig *config)
    445 {
    446     PS_ASSERT_PTR_NON_NULL(cell, false);
    447     psTrace("psModules.concepts", 5, "Reading cell concepts: %p %p\n", conceptsCell, cell->concepts);
    448     pmChip *chip = cell->parent;        // Chip to which the cell belongs
    449     pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
    450 
    451     bool success = conceptsRead(&conceptsCell, fpa, chip, cell, &cell->conceptsRead, source, config,
    452                                 cell->concepts);
    453     if (propagateUp) {
    454         success &= conceptsRead(&conceptsChip, fpa, chip, cell, &chip->conceptsRead, source, config,
    455                                 chip->concepts);
    456         success &= conceptsRead(&conceptsFPA, fpa, chip, cell, &fpa->conceptsRead, source, config,
    457                                 fpa->concepts);
    458     }
    459 
    460     return success;
    461 }
    462 
    463 bool pmConceptsWriteCell(const pmCell *cell, pmConceptSource source, bool propagateUp, pmConfig *config)
    464 {
    465     PS_ASSERT_PTR_NON_NULL(cell, false);
    466     psTrace("psModules.concepts", 5, "Writing cell concepts: %p %p\n", conceptsCell, cell->concepts);
    467     pmChip *chip = cell->parent;        // Chip to which the cell belongs
    468     pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
    469 
    470     bool success = conceptsWrite(&conceptsCell, fpa, chip, cell, source, config, cell->concepts);
    471     if (propagateUp) {
    472         if (!chip->hdu) {
    473             success &= conceptsWrite(&conceptsChip, fpa, chip, cell, source, config, chip->concepts);
    474             if (!fpa->hdu) {
    475                 success &= conceptsWrite(&conceptsFPA, fpa, chip, cell, source, config, fpa->concepts);
    476             }
    477         }
    478     }
    479 
    480     return success;
    481227}
    482228
     
    485231static void conceptRegister##SUFFIX(const char *name, /* Name of concept */ \
    486232                                    const char *comment, /* Comment for concept */ \
    487                                     pmConceptParseFunc parse, /* Parsing function */ \
    488                                     pmConceptFormatFunc format, /* Formatting function */ \
     233                                    pmConceptParseFunc parse, /* Parsing function, or NULL */ \
     234                                    pmConceptFormatFunc format, /* Formatting function, or NULL */ \
     235                                    pmConceptCopyFunc copy, /* Copying function, or NULL */ \
    489236                                    bool required, /* Required concept? */ \
    490237                                    pmFPALevel level /* Level at which concept applies */ \
     
    492239{ \
    493240    psMetadataItem *item = psMetadataItemAlloc##TYPENAME(name, comment, DEFAULT); /* Item to add */ \
    494     pmConceptRegister(item, parse, format, required, level); \
     241    pmConceptRegister(item, parse, format, copy, required, level); \
    495242    psFree(item); \
    496243    return; \
     
    515262    psMetadataItem *item = psMetadataItemAlloc(name, PS_DATA_TIME, comment, time);
    516263    psFree(time);
    517     pmConceptRegister(item, p_pmConceptParse_TIME, p_pmConceptFormat_TIME, required, level);
     264    pmConceptRegister(item, p_pmConceptParse_TIME, p_pmConceptFormat_TIME, NULL, required, level);
    518265    psFree(item);
    519266}
     
    521268bool pmConceptsInit(void)
    522269{
     270    if (conceptsInitialised) {
     271        return true;
     272    }
     273
    523274    conceptsInitialised = true;
    524275
     
    527278    bool init = false;                  // Did we initialise anything?
    528279
    529     if (! conceptsFPA) {
     280    if (!conceptsFPA) {
    530281        conceptsFPA = psMetadataAlloc();
    531282        init = true;
    532283
    533284        // Install the standard concepts
    534         conceptRegisterStr("FPA.TELESCOPE", "Telescope of origin", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    535         conceptRegisterStr("FPA.INSTRUMENT", "Instrument name (according to the instrument)", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    536         conceptRegisterStr("FPA.DETECTOR", "Detector name", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    537         conceptRegisterStr("FPA.COMMENT", "Observation comment", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    538         conceptRegisterStr("FPA.OBS.MODE", "Observation mode (eg, survey id)", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    539         conceptRegisterStr("FPA.OBS.GROUP", "Observation group (eg, associated images)", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    540         conceptRegisterF32("FPA.FOCUS", "Telescope focus", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    541         conceptRegisterF32("FPA.AIRMASS", "Airmass at boresight", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    542         conceptRegisterStr("FPA.FILTERID", "Filter used (parsed, abstract name)", p_pmConceptParse_FPA_FILTER, p_pmConceptFormat_FPA_FILTER, false, PM_FPA_LEVEL_FPA);
    543         conceptRegisterStr("FPA.FILTER", "Filter used (instrument name)", false, NULL, NULL, PM_FPA_LEVEL_FPA);
    544         conceptRegisterF32("FPA.POSANGLE", "Position angle of instrument", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    545         conceptRegisterF32("FPA.ROTANGLE", "Rotator angle of instrument", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    546         conceptRegisterStr("FPA.RADECSYS", "Celestial coordinate system", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    547         conceptRegisterF64("FPA.RA", "Right Ascension of boresight", p_pmConceptParse_FPA_Coords, p_pmConceptFormat_FPA_Coords, false, PM_FPA_LEVEL_FPA);
    548         conceptRegisterF64("FPA.DEC", "Declination of boresight", p_pmConceptParse_FPA_Coords, p_pmConceptFormat_FPA_Coords, false, PM_FPA_LEVEL_FPA);
    549         conceptRegisterF64("FPA.LONGITUDE", "West longitude of observatory", p_pmConceptParse_FPA_Coords, p_pmConceptFormat_FPA_Coords, false, PM_FPA_LEVEL_FPA);
    550         conceptRegisterF64("FPA.LATITUDE", "Latitude of observatory", p_pmConceptParse_FPA_Coords, p_pmConceptFormat_FPA_Coords, false, PM_FPA_LEVEL_FPA);
    551         conceptRegisterF32("FPA.ELEVATION", "Elevation of observatory (metres)", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    552         conceptRegisterStr("FPA.OBSTYPE", "Type of observation", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    553         conceptRegisterStr("FPA.OBJECT", "Object of observation", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    554         conceptRegisterF64("FPA.ALT", "Altitude of boresight", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    555         conceptRegisterF64("FPA.AZ", "Azimuth of boresight", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    556         conceptRegisterEnum("FPA.TIMESYS", "Time system", p_pmConceptParse_TIMESYS, p_pmConceptFormat_TIMESYS, false, PM_FPA_LEVEL_FPA);
     285        conceptRegisterStr("FPA.TELESCOPE", "Telescope of origin", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     286        conceptRegisterStr("FPA.INSTRUMENT", "Instrument name (according to the instrument)", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     287        conceptRegisterStr("FPA.DETECTOR", "Detector name", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     288        conceptRegisterStr("FPA.COMMENT", "Observation comment", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     289        conceptRegisterStr("FPA.OBS.MODE", "Observation mode (eg, survey id)", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     290        conceptRegisterStr("FPA.OBS.GROUP", "Observation group (eg, associated images)", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     291        conceptRegisterF32("FPA.FOCUS", "Telescope focus", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     292        conceptRegisterF32("FPA.AIRMASS", "Airmass at boresight", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     293        conceptRegisterStr("FPA.FILTERID", "Filter used (parsed, abstract name)", p_pmConceptParse_FPA_FILTER, p_pmConceptFormat_FPA_FILTER, NULL, false, PM_FPA_LEVEL_FPA);
     294        conceptRegisterStr("FPA.FILTER", "Filter used (instrument name)", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     295        conceptRegisterF32("FPA.POSANGLE", "Position angle of instrument", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     296        conceptRegisterF32("FPA.ROTANGLE", "Rotator angle of instrument", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     297        conceptRegisterStr("FPA.RADECSYS", "Celestial coordinate system", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     298        conceptRegisterF64("FPA.RA", "Right Ascension of boresight", p_pmConceptParse_FPA_Coords, p_pmConceptFormat_FPA_Coords, NULL, false, PM_FPA_LEVEL_FPA);
     299        conceptRegisterF64("FPA.DEC", "Declination of boresight", p_pmConceptParse_FPA_Coords, p_pmConceptFormat_FPA_Coords, NULL, false, PM_FPA_LEVEL_FPA);
     300        conceptRegisterF64("FPA.LONGITUDE", "West longitude of observatory", p_pmConceptParse_FPA_Coords, p_pmConceptFormat_FPA_Coords, NULL, false, PM_FPA_LEVEL_FPA);
     301        conceptRegisterF64("FPA.LATITUDE", "Latitude of observatory", p_pmConceptParse_FPA_Coords, p_pmConceptFormat_FPA_Coords, NULL, false, PM_FPA_LEVEL_FPA);
     302        conceptRegisterF32("FPA.ELEVATION", "Elevation of observatory (metres)", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     303        conceptRegisterStr("FPA.OBSTYPE", "Type of observation", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     304        conceptRegisterStr("FPA.OBJECT", "Object of observation", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     305        conceptRegisterF64("FPA.ALT", "Altitude of boresight", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     306        conceptRegisterF64("FPA.AZ", "Azimuth of boresight", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     307        conceptRegisterEnum("FPA.TIMESYS", "Time system", p_pmConceptParse_TIMESYS, p_pmConceptFormat_TIMESYS, p_pmConceptCopy_TIMESYS, false, PM_FPA_LEVEL_FPA);
    557308        conceptRegisterTime("FPA.TIME", "Time of exposure", false, PM_FPA_LEVEL_FPA);
    558         conceptRegisterF32("FPA.TEMP", "Temperature of focal plane", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    559         conceptRegisterF32("FPA.M1X", "Primary Mirror X Position", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    560         conceptRegisterF32("FPA.M1Y", "Primary Mirror Y Position", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    561         conceptRegisterF32("FPA.M1Z", "Primary Mirror Z Position", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    562         conceptRegisterF32("FPA.M1TIP", "Primary Mirror TIP", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    563         conceptRegisterF32("FPA.M1TILT", "Primary Mirror TILT", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    564         conceptRegisterF32("FPA.M2X", "Primary Mirror X Position", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    565         conceptRegisterF32("FPA.M2Y", "Primary Mirror Y Position", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    566         conceptRegisterF32("FPA.M2Z", "Primary Mirror Z Position", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    567         conceptRegisterF32("FPA.M2TIP", "Primary Mirror TIP", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    568         conceptRegisterF32("FPA.M2TILT", "Primary Mirror TILT", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    569         conceptRegisterF32("FPA.ENV.TEMP", "Environment: Temperature", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    570         conceptRegisterF32("FPA.ENV.HUMID", "Environment: Humidity", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    571         conceptRegisterF32("FPA.ENV.WIND", "Environment: Wind speed", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    572         conceptRegisterF32("FPA.ENV.DIR", "Environment: Wind direction", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    573         conceptRegisterF32("FPA.TELTEMP.M1", "Telescope Temperatures: M1", p_pmConceptParse_TELTEMPS, NULL, false, PM_FPA_LEVEL_FPA);
    574         conceptRegisterF32("FPA.TELTEMP.M1CELL", "Telescope Temperatures: M1 cell", p_pmConceptParse_TELTEMPS, NULL, false, PM_FPA_LEVEL_FPA);
    575         conceptRegisterF32("FPA.TELTEMP.M2", "Telescope Temperatures: M2", p_pmConceptParse_TELTEMPS, NULL, false, PM_FPA_LEVEL_FPA);
    576         conceptRegisterF32("FPA.TELTEMP.SPIDER", "Telescope Temperatures: spider", p_pmConceptParse_TELTEMPS, NULL, false, PM_FPA_LEVEL_FPA);
    577         conceptRegisterF32("FPA.TELTEMP.TRUSS", "Telescope Temperatures: truss", p_pmConceptParse_TELTEMPS, NULL, false, PM_FPA_LEVEL_FPA);
    578         conceptRegisterF32("FPA.TELTEMP.EXTRA", "Telescope Temperatures: extra", p_pmConceptParse_TELTEMPS, NULL, false, PM_FPA_LEVEL_FPA);
    579         conceptRegisterF32("FPA.PON.TIME", "Power On Time", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    580         conceptRegisterF32("FPA.EXPOSURE", "Exposure time (sec)", NULL, NULL, false, PM_FPA_LEVEL_FPA);
    581     }
    582     if (! conceptsChip) {
     309        conceptRegisterF32("FPA.TEMP", "Temperature of focal plane", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     310        conceptRegisterF32("FPA.M1X", "Primary Mirror X Position", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     311        conceptRegisterF32("FPA.M1Y", "Primary Mirror Y Position", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     312        conceptRegisterF32("FPA.M1Z", "Primary Mirror Z Position", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     313        conceptRegisterF32("FPA.M1TIP", "Primary Mirror TIP", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     314        conceptRegisterF32("FPA.M1TILT", "Primary Mirror TILT", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     315        conceptRegisterF32("FPA.M2X", "Primary Mirror X Position", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     316        conceptRegisterF32("FPA.M2Y", "Primary Mirror Y Position", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     317        conceptRegisterF32("FPA.M2Z", "Primary Mirror Z Position", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     318        conceptRegisterF32("FPA.M2TIP", "Primary Mirror TIP", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     319        conceptRegisterF32("FPA.M2TILT", "Primary Mirror TILT", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     320        conceptRegisterF32("FPA.ENV.TEMP", "Environment: Temperature", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     321        conceptRegisterF32("FPA.ENV.HUMID", "Environment: Humidity", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     322        conceptRegisterF32("FPA.ENV.WIND", "Environment: Wind speed", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     323        conceptRegisterF32("FPA.ENV.DIR", "Environment: Wind direction", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     324        conceptRegisterF32("FPA.TELTEMP.M1", "Telescope Temperatures: M1", p_pmConceptParse_TELTEMPS, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     325        conceptRegisterF32("FPA.TELTEMP.M1CELL", "Telescope Temperatures: M1 cell", p_pmConceptParse_TELTEMPS, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     326        conceptRegisterF32("FPA.TELTEMP.M2", "Telescope Temperatures: M2", p_pmConceptParse_TELTEMPS, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     327        conceptRegisterF32("FPA.TELTEMP.SPIDER", "Telescope Temperatures: spider", p_pmConceptParse_TELTEMPS, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     328        conceptRegisterF32("FPA.TELTEMP.TRUSS", "Telescope Temperatures: truss", p_pmConceptParse_TELTEMPS, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     329        conceptRegisterF32("FPA.TELTEMP.EXTRA", "Telescope Temperatures: extra", p_pmConceptParse_TELTEMPS, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     330        conceptRegisterF32("FPA.PON.TIME", "Power On Time", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     331        conceptRegisterF32("FPA.EXPOSURE", "Exposure time (sec)", NULL, NULL, NULL, false, PM_FPA_LEVEL_FPA);
     332    }
     333    if (!conceptsChip) {
    583334        conceptsChip = psMetadataAlloc();
    584335        init = true;
    585336
    586337        // Install the standard concepts
    587         conceptRegisterS32("CHIP.XPARITY", "Orientation in x compared to the rest of the FPA", NULL, NULL, true, PM_FPA_LEVEL_CHIP);
    588         conceptRegisterS32("CHIP.YPARITY", "Orientation in y compared to the rest of the FPA", NULL, NULL, true, PM_FPA_LEVEL_CHIP);
    589         conceptRegisterS32("CHIP.X0", "Position of (0,0) on the FPA",p_pmConceptParse_Positions,p_pmConceptFormat_Positions, true, PM_FPA_LEVEL_CHIP);
    590         conceptRegisterS32("CHIP.Y0", "Position of (0,0) on the FPA",p_pmConceptParse_Positions,p_pmConceptFormat_Positions, true, PM_FPA_LEVEL_CHIP);
    591         conceptRegisterS32("CHIP.XSIZE", "Size of chip (pixels)", NULL, NULL, true, PM_FPA_LEVEL_CHIP);
    592         conceptRegisterS32("CHIP.YSIZE", "Size of chip (pixels)", NULL, NULL, true, PM_FPA_LEVEL_CHIP);
    593         conceptRegisterF32("CHIP.TEMP", "Temperature of chip", NULL, NULL, false, PM_FPA_LEVEL_CHIP);
    594         conceptRegisterStr("CHIP.ID", "Chip identifier", NULL, NULL, false, PM_FPA_LEVEL_CHIP);
    595     }
    596 
    597     if (! conceptsCell) {
     338        conceptRegisterS32("CHIP.XPARITY", "Orientation in x compared to the rest of the FPA", NULL, NULL, NULL, true, PM_FPA_LEVEL_CHIP);
     339        conceptRegisterS32("CHIP.YPARITY", "Orientation in y compared to the rest of the FPA", NULL, NULL, NULL, true, PM_FPA_LEVEL_CHIP);
     340        conceptRegisterS32("CHIP.X0", "Position of (0,0) on the FPA",p_pmConceptParse_Positions,p_pmConceptFormat_Positions, NULL, true, PM_FPA_LEVEL_CHIP);
     341        conceptRegisterS32("CHIP.Y0", "Position of (0,0) on the FPA",p_pmConceptParse_Positions,p_pmConceptFormat_Positions, NULL, true, PM_FPA_LEVEL_CHIP);
     342        conceptRegisterS32("CHIP.XSIZE", "Size of chip (pixels)", NULL, NULL, NULL, true, PM_FPA_LEVEL_CHIP);
     343        conceptRegisterS32("CHIP.YSIZE", "Size of chip (pixels)", NULL, NULL, NULL, true, PM_FPA_LEVEL_CHIP);
     344        conceptRegisterF32("CHIP.TEMP", "Temperature of chip", NULL, NULL, NULL, false, PM_FPA_LEVEL_CHIP);
     345        conceptRegisterStr("CHIP.ID", "Chip identifier", NULL, NULL, NULL, false, PM_FPA_LEVEL_CHIP);
     346    }
     347
     348    if (!conceptsCell) {
    598349        conceptsCell = psMetadataAlloc();
    599350        init = true;
    600351
    601352        // Install the standard concepts
    602         conceptRegisterF32("CELL.GAIN", "CCD gain (e/count)", NULL, NULL, true, PM_FPA_LEVEL_CELL);
    603         conceptRegisterF32("CELL.READNOISE", "CCD read noise (e)", p_pmConceptParse_CELL_READNOISE, p_pmConceptFormat_CELL_READNOISE, true, PM_FPA_LEVEL_CELL);
    604         conceptRegisterF32("CELL.SATURATION", "Saturation level (counts)", NULL, NULL, true, PM_FPA_LEVEL_CELL);
    605         conceptRegisterF32("CELL.BAD", "Bad level (counts)", NULL, NULL, true, PM_FPA_LEVEL_CELL);
    606         conceptRegisterS32("CELL.XPARITY", "Orientation in x compared to the rest of the chip", NULL, NULL, true, PM_FPA_LEVEL_CELL);
    607         conceptRegisterS32("CELL.YPARITY", "Orientation in y compared to the rest of the chip", NULL, NULL, true, PM_FPA_LEVEL_CELL);
    608         conceptRegisterS32("CELL.READDIR", "Read direction, rows=1, cols=2", NULL, NULL, true, PM_FPA_LEVEL_CELL);
     353        conceptRegisterF32("CELL.GAIN", "CCD gain (e/count)", NULL, NULL, NULL, true, PM_FPA_LEVEL_CELL);
     354        conceptRegisterF32("CELL.READNOISE", "CCD read noise (e)", p_pmConceptParse_CELL_READNOISE, p_pmConceptFormat_CELL_READNOISE, NULL, true, PM_FPA_LEVEL_CELL);
     355        conceptRegisterF32("CELL.SATURATION", "Saturation level (counts)", NULL, NULL, NULL, true, PM_FPA_LEVEL_CELL);
     356        conceptRegisterF32("CELL.BAD", "Bad level (counts)", NULL, NULL, NULL, true, PM_FPA_LEVEL_CELL);
     357        conceptRegisterS32("CELL.XPARITY", "Orientation in x compared to the rest of the chip", NULL, NULL, NULL, true, PM_FPA_LEVEL_CELL);
     358        conceptRegisterS32("CELL.YPARITY", "Orientation in y compared to the rest of the chip", NULL, NULL, NULL, true, PM_FPA_LEVEL_CELL);
     359        conceptRegisterS32("CELL.READDIR", "Read direction, rows=1, cols=2", NULL, NULL, NULL, true, PM_FPA_LEVEL_CELL);
    609360
    610361        // These (CELL.EXPOSURE and CELL.DARKTIME) used to be READOUT.EXPOSURE and READOUT.DARKTIME, but that
     
    613364        // readout is a plane in a 3D image.  We'll have to dream up some additional suffix to specify these,
    614365        // but for now....
    615         conceptRegisterF32("CELL.EXPOSURE", "Exposure time (sec)", NULL, NULL, false, PM_FPA_LEVEL_CELL);
    616         conceptRegisterF32("CELL.DARKTIME", "Time since flush (sec)", NULL, NULL, false, PM_FPA_LEVEL_CELL);
    617 
    618         conceptRegisterS32("CELL.XBIN", "Binning in x", p_pmConceptParse_CELL_Binning,p_pmConceptFormat_CELL_XBIN, true, PM_FPA_LEVEL_CELL);
    619         conceptRegisterS32("CELL.YBIN", "Binning in y",p_pmConceptParse_CELL_Binning,p_pmConceptFormat_CELL_YBIN, true, PM_FPA_LEVEL_CELL);
    620         conceptRegisterEnum("CELL.TIMESYS", "Time system", p_pmConceptParse_TIMESYS,p_pmConceptFormat_TIMESYS, false, PM_FPA_LEVEL_CELL);
     366        conceptRegisterF32("CELL.EXPOSURE", "Exposure time (sec)", NULL, NULL, NULL, false, PM_FPA_LEVEL_CELL);
     367        conceptRegisterF32("CELL.DARKTIME", "Time since flush (sec)", NULL, NULL, NULL, false, PM_FPA_LEVEL_CELL);
     368
     369        conceptRegisterS32("CELL.XBIN", "Binning in x", p_pmConceptParse_CELL_Binning,p_pmConceptFormat_CELL_XBIN, NULL, true, PM_FPA_LEVEL_CELL);
     370        conceptRegisterS32("CELL.YBIN", "Binning in y",p_pmConceptParse_CELL_Binning,p_pmConceptFormat_CELL_YBIN, NULL, true, PM_FPA_LEVEL_CELL);
     371        conceptRegisterEnum("CELL.TIMESYS", "Time system", p_pmConceptParse_TIMESYS,p_pmConceptFormat_TIMESYS, p_pmConceptCopy_TIMESYS, false, PM_FPA_LEVEL_CELL);
    621372        conceptRegisterTime("CELL.TIME", "Time of exposure", false, PM_FPA_LEVEL_CELL);
    622         conceptRegisterS32("CELL.X0", "Position of (0,0) on the chip",p_pmConceptParse_Positions,p_pmConceptFormat_Positions, true, PM_FPA_LEVEL_CELL);
    623         conceptRegisterS32("CELL.Y0", "Position of (0,0) on the chip",p_pmConceptParse_Positions,p_pmConceptFormat_Positions, true, PM_FPA_LEVEL_CELL);
    624         conceptRegisterS32("CELL.XSIZE", "Size of cell (pixels)", NULL, NULL, true, PM_FPA_LEVEL_CELL);
    625         conceptRegisterS32("CELL.YSIZE", "Size of cell (pixels)", NULL, NULL, true, PM_FPA_LEVEL_CELL);
    626         conceptRegisterS32("CELL.XWINDOW", "Start of cell window (pixels)",p_pmConceptParse_Positions,p_pmConceptFormat_Positions, true, PM_FPA_LEVEL_CELL);
    627         conceptRegisterS32("CELL.YWINDOW", "Start of cell window (pixels)",p_pmConceptParse_Positions,p_pmConceptFormat_Positions, true, PM_FPA_LEVEL_CELL);
    628         conceptRegisterF32("CELL.VARFACTOR", "Variance factor for conversion from large to small scales", NULL, NULL, true, PM_FPA_LEVEL_CELL);
     373        conceptRegisterS32("CELL.X0", "Position of (0,0) on the chip",p_pmConceptParse_Positions,p_pmConceptFormat_Positions, NULL, true, PM_FPA_LEVEL_CELL);
     374        conceptRegisterS32("CELL.Y0", "Position of (0,0) on the chip",p_pmConceptParse_Positions,p_pmConceptFormat_Positions, NULL, true, PM_FPA_LEVEL_CELL);
     375        conceptRegisterS32("CELL.XSIZE", "Size of cell (pixels)", NULL, NULL, NULL, true, PM_FPA_LEVEL_CELL);
     376        conceptRegisterS32("CELL.YSIZE", "Size of cell (pixels)", NULL, NULL, NULL, true, PM_FPA_LEVEL_CELL);
     377        conceptRegisterS32("CELL.XWINDOW", "Start of cell window (pixels)",p_pmConceptParse_Positions,p_pmConceptFormat_Positions, NULL, true, PM_FPA_LEVEL_CELL);
     378        conceptRegisterS32("CELL.YWINDOW", "Start of cell window (pixels)",p_pmConceptParse_Positions,p_pmConceptFormat_Positions, NULL, true, PM_FPA_LEVEL_CELL);
     379        conceptRegisterF32("CELL.VARFACTOR", "Variance factor for conversion from large to small scales", NULL, NULL, NULL, true, PM_FPA_LEVEL_CELL);
    629380
    630381        // CELL.TRIMSEC
     
    635386                                          "Trim section", trimsec);
    636387            psFree(trimsec);
    637             pmConceptRegister(cellTrimsec, p_pmConceptParse_CELL_TRIMSEC,p_pmConceptFormat_CELL_TRIMSEC, true, PM_FPA_LEVEL_CELL);
     388            pmConceptRegister(cellTrimsec, p_pmConceptParse_CELL_TRIMSEC,p_pmConceptFormat_CELL_TRIMSEC, NULL, true, PM_FPA_LEVEL_CELL);
    638389            psFree(cellTrimsec);
    639390        }
     
    645396                                          "Bias sections", biassecs);
    646397            psFree(biassecs);
    647             pmConceptRegister(cellBiassec, p_pmConceptParse_CELL_BIASSEC, p_pmConceptFormat_CELL_BIASSEC, true, PM_FPA_LEVEL_CELL);
     398            pmConceptRegister(cellBiassec, p_pmConceptParse_CELL_BIASSEC, p_pmConceptFormat_CELL_BIASSEC, NULL, true, PM_FPA_LEVEL_CELL);
    648399            psFree(cellBiassec);
    649400        }
     
    666417
    667418    conceptsInitialised = false;
    668 }
    669 
    670 
    671 // List of concepts not to copy, for each level.
    672 // Must be NULL-terminated
    673 static const char *dontCopyConceptsFPA[] = { "FPA.OBS", "FPA.NAME", "FPA.CAMERA", 0 };
    674 static const char *dontCopyConceptsChip[] = { "CHIP.NAME", 0 };
    675 static const char *dontCopyConceptsCell[] = { "CELL.NAME", "CELL.TRIMSEC", "CELL.BIASSEC", 0 };
    676 
    677 // Copy concepts from a source container to a target container, avoiding certain entries
    678 static void copyConcepts(psMetadata *target, // Target metadata container
    679                          psMetadata *source, // Source metadata container
    680                          const char *dontCopyConcepts[] // Don't copy these concepts
    681                          )
    682 {
    683     assert(target);
    684     assert(source);
    685     assert(dontCopyConcepts);
    686 
    687     psMetadataIterator *iter = psMetadataIteratorAlloc(source, PS_LIST_HEAD, NULL);
    688     psMetadataItem *item;               // Item from iteration
    689     while ((item = psMetadataGetAndIncrement(iter))) {
    690         const char *name = item->name;  // Name of concept
    691         bool copyOK = true;            // OK to copy
    692         for (int i = 0; dontCopyConcepts[i] && copyOK; i++) {
    693             if (!strcmp(name, dontCopyConcepts[i])) {
    694                 copyOK = false;
    695             }
    696         }
    697         if (!copyOK) {
    698             continue;
    699         }
    700         psMetadataItem *new = psMetadataItemCopy(item); // New item, a copy of the old
    701         psMetadataAddItem(target, new, PS_LIST_TAIL, PS_META_REPLACE);
    702         psFree(new);                    // Drop reference
    703     }
    704     psFree(iter);
    705 
    706     return;
    707 }
    708 
    709 
    710 bool pmFPACopyConcepts(pmFPA *target, const pmFPA *source)
    711 {
    712     PS_ASSERT_PTR_NON_NULL(target, false);
    713     PS_ASSERT_PTR_NON_NULL(source, false);
    714 
    715     // Copy FPA concepts
    716     copyConcepts(target->concepts, source->concepts, dontCopyConceptsFPA);
    717 
    718     // Copy chip concepts
    719     psArray *targetChips = target->chips; // Chips in target
    720     psArray *sourceChips = source->chips; // Chips in source
    721     if (targetChips->n != sourceChips->n) {
    722         psError(PS_ERR_IO, true, "Number of chips in target (%ld) and source (%ld) differ --- unable to copy "
    723                 "concepts.\n", targetChips->n, sourceChips->n);
    724         return false;
    725     }
    726     for (int i = 0; i < targetChips->n; i++) {
    727         pmChip *targetChip = targetChips->data[i]; // Target chip of interest
    728         pmChip *sourceChip = sourceChips->data[i]; // Source chip of interest
    729         if (! targetChip || ! sourceChip) {
    730             continue;
    731         }
    732 
    733         copyConcepts(targetChip->concepts, sourceChip->concepts, dontCopyConceptsChip);
    734 
    735         // Copy cell concepts
    736         psArray *targetCells = targetChip->cells; // Cells in target
    737         psArray *sourceCells = sourceChip->cells; // Cells in source
    738         if (targetCells->n != sourceCells->n) {
    739             psError(PS_ERR_IO, true, "Number of cells in target (%ld) and source (%ld) differ for chip %d ---"
    740                     " unable to copy concepts.\n", targetCells->n, sourceCells->n, i);
    741             return false;
    742         }
    743         for (int j = 0; j < targetCells->n; j++) {
    744             pmCell *targetCell = targetCells->data[j]; // Target chip of interest
    745             pmCell *sourceCell = sourceCells->data[j]; // Source chip of interest
    746             if (! targetCell || ! sourceCell) {
    747                 continue;
    748             }
    749 
    750             copyConcepts(targetCell->concepts, sourceCell->concepts, dontCopyConceptsCell);
    751         }
    752     }
    753 
    754     return true;
    755 }
    756 
    757 
    758 bool pmConceptsCopyFPA(pmFPA *target, const pmFPA *source, bool chips, bool cells)
    759 {
    760     PS_ASSERT_PTR_NON_NULL(target, false);
    761     PS_ASSERT_PTR_NON_NULL(source, false);
    762 
    763     // Copy FPA concepts
    764     copyConcepts(target->concepts, source->concepts, dontCopyConceptsFPA);
    765 
    766     // Copy chip concepts
    767     bool status = true;                 // Status of chips
    768     if (chips) {
    769         psArray *targetChips = target->chips; // Chips in target
    770         psArray *sourceChips = source->chips; // Chips in source
    771         if (targetChips->n != sourceChips->n) {
    772             psError(PS_ERR_IO, true,
    773                     "Number of chips in target (%ld) and source (%ld) differ --- unable to copy concepts.",
    774                     targetChips->n, sourceChips->n);
    775             return false;
    776         }
    777         for (int i = 0; i < targetChips->n; i++) {
    778             pmChip *targetChip = targetChips->data[i]; // Target chip of interest
    779             pmChip *sourceChip = sourceChips->data[i]; // Source chip of interest
    780             if (! targetChip || ! sourceChip) {
    781                 continue;
    782             }
    783 
    784             status &= pmConceptsCopyChip(targetChip, sourceChip, cells);
    785         }
    786     }
    787 
    788     return status;
    789 }
    790 
    791 bool pmConceptsCopyChip(pmChip *target, const pmChip *source, bool cells)
    792 {
    793     PS_ASSERT_PTR_NON_NULL(target, false);
    794     PS_ASSERT_PTR_NON_NULL(source, false);
    795 
    796     // Copy chip concepts
    797     copyConcepts(target->concepts, source->concepts, dontCopyConceptsChip);
    798 
    799     // Copy cell concepts
    800     bool status = true;                 // Status of cells
    801     if (cells) {
    802         psArray *targetCells = target->cells; // Cells in target
    803         psArray *sourceCells = source->cells; // Cells in source
    804         if (targetCells->n != sourceCells->n) {
    805             psError(PS_ERR_IO, true,
    806                     "Number of cells in target (%ld) and source (%ld) differ --- unable to copy concepts.",
    807                     targetCells->n, sourceCells->n);
    808             return false;
    809         }
    810         for (int j = 0; j < targetCells->n; j++) {
    811             pmCell *targetCell = targetCells->data[j]; // Target chip of interest
    812             pmCell *sourceCell = sourceCells->data[j]; // Source chip of interest
    813             if (! targetCell || ! sourceCell) {
    814                 continue;
    815             }
    816 
    817             status &= pmConceptsCopyCell(targetCell, sourceCell);
    818         }
    819     }
    820 
    821     return status;
    822 }
    823 
    824 
    825 bool pmConceptsCopyCell(pmCell *target, const pmCell *source)
    826 {
    827     PS_ASSERT_PTR_NON_NULL(target, false);
    828     PS_ASSERT_PTR_NON_NULL(source, false);
    829 
    830     copyConcepts(target->concepts, source->concepts, dontCopyConceptsCell);
    831 
    832     return true;
    833419}
    834420
  • trunk/psModules/src/concepts/pmConcepts.h

    r22688 r22699  
    3737
    3838/// Function to call to parse a concept once it has been read
    39 typedef psMetadataItem* (*pmConceptParseFunc)(const psMetadataItem *concept, ///< Concept to parse
    40         const psMetadataItem *pattern, ///< Pattern for parsing
    41                                               pmConceptSource source, ///< Source of concept
    42         const psMetadata *cameraFormat, ///< Camera format definition
    43         const pmFPA *fpa, ///< FPA for concept, or NULL
    44         const pmChip *chip, ///< Chip for concept, or NULL
    45         const pmCell *cell ///< Cell for concept, or NULL
    46                                              );
     39typedef psMetadataItem* (*pmConceptParseFunc)(
     40    const psMetadataItem *concept, ///< Concept to parse
     41    const psMetadataItem *pattern, ///< Pattern for parsing
     42    pmConceptSource source, ///< Source of concept
     43    const psMetadata *cameraFormat, ///< Camera format definition
     44    const pmFPA *fpa, ///< FPA for concept, or NULL
     45    const pmChip *chip, ///< Chip for concept, or NULL
     46    const pmCell *cell ///< Cell for concept, or NULL
     47    );
    4748
    4849/// Function to call to format a concept for writing
    49 typedef psMetadataItem* (*pmConceptFormatFunc)(const psMetadataItem *concept, ///< Concept to format
    50                                                pmConceptSource source, ///< Source of concept
    51         const psMetadata *cameraFormat, ///< Camera format definition
    52         const pmFPA *fpa, ///< FPA for concept, or NULL
    53         const pmChip *chip, ///< Chip for concept, or NULL
    54         const pmCell *cell ///< Cell for concept, or NULL
    55                                               );
     50typedef psMetadataItem* (*pmConceptFormatFunc)(
     51    const psMetadataItem *concept, ///< Concept to format
     52    pmConceptSource source, ///< Source of concept
     53    const psMetadata *cameraFormat, ///< Camera format definition
     54    const pmFPA *fpa, ///< FPA for concept, or NULL
     55    const pmChip *chip, ///< Chip for concept, or NULL
     56    const pmCell *cell ///< Cell for concept, or NULL
     57    );
     58
     59/// Function to call to copy a concept
     60typedef psMetadataItem* (*pmConceptCopyFunc)(
     61    const psMetadataItem *target,       ///< Target concept
     62    const psMetadataItem *source,       ///< Source concept
     63    const psMetadata *cameraFormat,     ///< Camera format definition
     64    const pmFPA *fpa,                   ///< Source FPA for concept, or NULL
     65    const pmChip *chip,                 ///< Source chip for concept, or NULL
     66    const pmCell *cell                  ///< Source cell for concept, or NULL
     67    );
     68
    5669
    5770/// A "concept" specification
     
    5972/// Defines the name, default comment, blank value, and functions to parse (after reading) and format (before
    6073/// writing) the concept.
    61 typedef struct
    62 {
     74typedef struct {
    6375    psMetadataItem *blank;              ///< Blank value of concept; also contains the name and comment
    64     pmConceptParseFunc parse;           ///< Function to call to read the concept
    65     pmConceptFormatFunc format;         ///< Function to call to write the concept
     76    pmConceptParseFunc parse;           ///< Function to call to read the concept, or NULL
     77    pmConceptFormatFunc format;         ///< Function to call to write the concept, or NULL
     78    pmConceptCopyFunc copy;             ///< Function to call to copy the concept, or NULL
    6679    bool required;                      ///< Is concept required (throw an error on problems)?
    6780}
     
    7083/// Allocator for pmConceptSpec
    7184pmConceptSpec *pmConceptSpecAlloc(psMetadataItem *blank, ///< Blank value; contains the name
    72                                   pmConceptParseFunc parse, ///< Function to call to parse the concept
    73                                   pmConceptFormatFunc format, ///< Function to call to format the concept
     85                                  pmConceptParseFunc parse, ///< Function to call to parse the concept/NULL
     86                                  pmConceptFormatFunc format, ///< Function to call to format the concept/NULL
     87                                  pmConceptCopyFunc copy, ///< Function to call to copy the concept, or NULL
    7488                                  bool required ///< Is concept required?
    7589                                 );
     
    95109                       pmConceptParseFunc parse, ///< Function to call to parse the concept, or NULL
    96110                       pmConceptFormatFunc format, ///< Function to call to format the concept, or NULL
     111                       pmConceptCopyFunc copy, ///< Function to call to copy the concept, or NULL
    97112                       bool required,   ///< Is concept required?
    98113                       pmFPALevel level ///< Level at which to store concept in the FPA hierarchy
    99114                      );
    100115
    101 /// Get a list of defined concepts for a particular level.
    102 psList *pmConceptsList(pmFPALevel level);
     116/// Get the specifications for defined concepts of a particular level
     117psMetadata *pmConceptsSpecs(pmFPALevel level);
    103118
    104 /// Read the concepts for the given set of fpa, chip, cell
    105 ///
    106 /// Attempts to read as many concepts as possible from the specified source for the specified FPA, chip and
    107 /// cell.  That is, it will read chip- and cell-level concepts in addition to fpa-level concepts, if the chip
    108 /// and cell are provided.
    109 bool pmConceptsRead(pmFPA *fpa,         ///< FPA for which to read concepts
    110                     pmChip *chip,       ///< Chip for which to read concepts, or NULL
    111                     pmCell *cell,       ///< Cell for which to read concepts, or NULL
    112                     pmConceptSource source, ///< The source of the concepts to read
    113                     pmConfig *config    ///< Configuration
    114                    );
    115119
    116120/// Set the concepts within the FPA to the blank value
    117121bool pmConceptsBlankFPA(pmFPA *fpa      ///< FPA for which to set blank concepts
    118                        );
    119 
    120 /// Read concepts for an FPA; optionally, read concepts at all lower levels.
    121 ///
    122 /// Once concepts should be available for reading at the FPA-level, this function attempts to read the
    123 /// concepts from the specified source.  It also allows concepts to be read at lower levels by iterating over
    124 /// the components.
    125 bool pmConceptsReadFPA(pmFPA *fpa,      ///< FPA for which to read concepts
    126                        pmConceptSource source, ///< Source for concepts
    127                        bool propagateDown, ///< Propagate to lower levels?
    128                        pmConfig *config         ///< Configuration
    129                       );
    130 
    131 /// Write concepts for an FPA; optionally, write concepts at all lower levels.
    132 ///
    133 /// This function writes all concepts for the FPA to the specified "source".  It also allows concepts to be
    134 /// written for all lower levels by iterating over the components.
    135 bool pmConceptsWriteFPA(const pmFPA *fpa,     ///< FPA for which to write concepts
    136                         pmConceptSource source, ///< Source for concepts
    137                         bool propagateDown, ///< Propagate to lower levels?
    138                         pmConfig *config        ///< Configuration
    139122                       );
    140123
     
    143126                        );
    144127
    145 /// Read concepts for a chip; optionally, read concepts at the FPA and cell levels.
    146 ///
    147 /// Once concepts should be available for reading at the FPA-level, this function attempts to read the
    148 /// concepts from the specified source.  It also allows concepts to be read at the fpa level (through the
    149 /// parent), and the cell level by iterating over the components.
    150 bool pmConceptsReadChip(pmChip *chip,   ///< Chip for which to read concepts
    151                         pmConceptSource source, ///< Source for concepts
    152                         bool propagateUp, ///< Propagate to higher levels?
    153                         bool propagateDown, ///< Propagate to lower levels?
    154                         pmConfig *config        ///< Configuration
    155                        );
    156 
    157 /// Write concepts for a chip; optionally, write concepts at the FPA and cell levels.
    158 ///
    159 /// This function writes all concepts for the chip to the specified "source".  It also allows concepts to be
    160 /// written for the FPA, and the cell level by iterating over the components.
    161 bool pmConceptsWriteChip(const pmChip *chip,  ///< Chip for which to write concepts
    162                          pmConceptSource source, ///< Source for concepts
    163                          bool propagateUp,///< Propagate to higher levels?
    164                          bool propagateDown, ///< Propagate to lower levels?
    165                          pmConfig *config       ///< Configuration
    166                         );
    167 
    168128/// Set the concepts within the cell to the blank value
    169129bool pmConceptsBlankCell(pmCell *cell   ///< Cell for which to set blank concepts
    170                         );
    171 
    172 /// Read concepts for a cell; optionally, read concepts for the parents.
    173 ///
    174 /// Once concepts should be available for reading at the FPA-level, this function attempts to read the
    175 /// concepts from the specified source.  It also allows concepts to be read at upper levels through the
    176 /// parents (note, it would not read concepts for all chips, but only the parent of this cell).
    177 bool pmConceptsReadCell(pmCell *cell,   ///< Cell for which to read concepts
    178                         pmConceptSource source, ///< Source for concepts
    179                         bool propagateUp, ///< Propagate to higher levels?
    180                         pmConfig *config        ///< Configuration
    181                        );
    182 
    183 /// Write concepts for a cell; optionally, write concepts for the parents.
    184 ///
    185 /// This function writes all concepts for the chip to the specified "source".  It also allows concepts to be
    186 /// written for the upper levels through the parents (note, it would not write concepts for all chips, but
    187 /// only the parent of this cell).
    188 bool pmConceptsWriteCell(const pmCell *cell,  ///< FPA for which to write concepts
    189                          pmConceptSource source, ///< Source for concepts
    190                          bool propagateUp, ///< Propagate to higher levels?
    191                          pmConfig *config ///< Configuration
    192130                        );
    193131
     
    202140/// Frees the registered concepts so there is no memory leak when the user checks "persistent" memory.
    203141void pmConceptsDone(void);
    204 
    205 /// Copy all the concepts within an FPA to another FPA
    206 ///
    207 /// Iterates over all components of the FPA, and copies the concepts metadata from the source to the target.
    208 bool pmFPACopyConcepts(pmFPA *target,   ///< The target FPA
    209                        const pmFPA *source    ///< The source FPA
    210                       );
    211 
    212 /// Copy the concepts within an FPA to another FPA; optionally recurse to lower levels
    213 bool pmConceptsCopyFPA(pmFPA *target,   ///< Target FPA
    214                        const pmFPA *source, ///< Source FPA
    215                        bool chips,      ///< Recurse to chips level?
    216                        bool cells       ///< Recurse to cells level?
    217     );
    218 
    219 /// Copy the concepts within a chip to another chip; optionally recurse to lower level
    220 bool pmConceptsCopyChip(pmChip *target, ///< Target chip
    221                         const pmChip *source, ///< Source chip
    222                         bool cells      ///< Recurse to cells level?
    223     );
    224 
    225 /// Copy the concepts within a cell to another cell
    226 bool pmConceptsCopyCell(pmCell *target, ///< Target cell
    227                         const pmCell *source ///< Source cell
    228     );
    229142
    230143/// Interpolate a concept name to the actual value
  • trunk/psModules/src/concepts/pmConceptsRead.c

    r20868 r22699  
    1515#include "pmHDUUtils.h"
    1616#include "pmConcepts.h"
     17#include "pmConceptsUpdate.h"
     18
    1719#include "pmConceptsRead.h"
    1820
     
    483485}
    484486
     487
     488
     489// Read all registered concepts for the specified level
     490static bool conceptsRead(psMetadata **specs, // One of the concepts specifications
     491                         pmFPA *fpa,    // The FPA
     492                         pmChip *chip,  // The chip
     493                         pmCell *cell, // The cell
     494                         unsigned int *read,     // What's already been read
     495                         pmConceptSource source, // The source of the concepts to read
     496                         pmConfig *config, // Configuration
     497                         psMetadata *target // Place into which to read the concepts
     498                        )
     499{
     500    assert(specs);
     501    assert(read);
     502    assert(target);
     503
     504    pmConceptsInit();
     505
     506    // At least one HDU is required for the reading functions
     507    pmHDU *hduLow = pmHDUGetLowest(fpa, chip, cell); // Lowest HDU.
     508    if (!hduLow) {
     509        // Can't do anything --- don't record any success, but don't return an error either
     510        return true;
     511    }
     512    pmHDU *hduHigh = pmHDUGetHighest(fpa, chip, cell); // Highest HDU
     513
     514    if (cell && (cell->conceptsRead == PM_CONCEPT_SOURCE_NONE)) {
     515        pmConceptsBlankCell(cell);
     516        cell->conceptsRead = PM_CONCEPT_SOURCE_BLANK;
     517    }
     518    if (chip && (chip->conceptsRead == PM_CONCEPT_SOURCE_NONE)) {
     519        pmConceptsBlankChip(chip);
     520        chip->conceptsRead = PM_CONCEPT_SOURCE_BLANK;
     521    }
     522    if (fpa && (fpa->conceptsRead == PM_CONCEPT_SOURCE_NONE)) {
     523        pmConceptsBlankFPA(fpa);
     524        fpa->conceptsRead = PM_CONCEPT_SOURCE_BLANK;
     525    }
     526
     527    bool success = true;                // Success in reading concepts?
     528    if (source & PM_CONCEPT_SOURCE_CELLS && !(*read & PM_CONCEPT_SOURCE_CELLS) && cell) {
     529        if (p_pmConceptsReadFromCells(target, *specs, cell)) {
     530            *read |= PM_CONCEPT_SOURCE_CELLS;
     531        } else {
     532            psError(PS_ERR_UNKNOWN, false, "Error reading concepts from camera configuration.\n");
     533            success = false;
     534        }
     535    }
     536
     537    if (source & PM_CONCEPT_SOURCE_DEFAULTS && !(*read & PM_CONCEPT_SOURCE_DEFAULTS)) {
     538        if (p_pmConceptsReadFromDefaults(target, *specs, fpa, chip, cell)) {
     539            *read |= PM_CONCEPT_SOURCE_DEFAULTS;
     540        } else {
     541            psError(PS_ERR_UNKNOWN, false, "Error reading concepts from defaults.\n");
     542            success = false;
     543        }
     544    }
     545
     546    if (source & PM_CONCEPT_SOURCE_PHU && !(*read & PM_CONCEPT_SOURCE_PHU) && hduHigh->header) {
     547        if (p_pmConceptsReadFromHeader(target, *specs, fpa, chip, cell)) {
     548            *read |= PM_CONCEPT_SOURCE_PHU;
     549        } else {
     550            psError(PS_ERR_UNKNOWN, false, "Error reading concepts from PHU.\n");
     551            success = false;
     552        }
     553    }
     554
     555    // If there are multiple HDUs, then it may be that one of them hasn't been read yet (hdu->header not set)
     556    if (source & PM_CONCEPT_SOURCE_HEADER && !(*read & PM_CONCEPT_SOURCE_HEADER) &&
     557        hduLow != hduHigh && hduLow->header) {
     558        if (p_pmConceptsReadFromHeader(target, *specs, fpa, chip, cell)) {
     559            *read |= PM_CONCEPT_SOURCE_HEADER;
     560        } else {
     561            psError(PS_ERR_UNKNOWN, false, "Error reading concepts from header.\n");
     562            success = false;
     563        }
     564    }
     565
     566#ifdef HAVE_PSDB
     567    if (source & PM_CONCEPT_SOURCE_DATABASE && !(*read & PM_CONCEPT_SOURCE_DATABASE)) {
     568        if (p_pmConceptsReadFromDatabase(target, *specs, fpa, chip, cell, config)) {
     569            *read |= PM_CONCEPT_SOURCE_DATABASE;
     570        } else {
     571            psError(PS_ERR_UNKNOWN, false, "Error reading concepts from database.\n");
     572            success = false;
     573        }
     574    }
     575#endif
     576
     577    pmConceptsUpdate(fpa, chip, cell);
     578
     579    return success;
     580}
     581
     582
     583
     584
     585bool pmConceptsRead(pmFPA *fpa, pmChip *chip, pmCell *cell, pmConceptSource source, pmConfig *config)
     586{
     587    PS_ASSERT_PTR_NON_NULL(fpa, false);
     588    psMetadata *conceptsFPA = pmConceptsSpecs(PM_FPA_LEVEL_FPA); // Concept specifications
     589    bool success = conceptsRead(&conceptsFPA, fpa, chip, cell, &fpa->conceptsRead, source,
     590                                config, fpa->concepts);
     591    if (chip) {
     592        psMetadata *conceptsChip = pmConceptsSpecs(PM_FPA_LEVEL_CHIP); // Concept specifications
     593        success &= conceptsRead(&conceptsChip, fpa, chip, cell, &chip->conceptsRead, source,
     594                                config, chip->concepts);
     595    }
     596    if (cell) {
     597        psMetadata *conceptsCell = pmConceptsSpecs(PM_FPA_LEVEL_CELL); // Concept specifications
     598        success &= conceptsRead(&conceptsCell, fpa, chip, cell, &cell->conceptsRead, source,
     599                                config, cell->concepts);
     600    }
     601
     602    return success;
     603}
     604
     605
     606
     607bool pmConceptsReadFPA(pmFPA *fpa, pmConceptSource source, bool propagateDown, pmConfig *config)
     608{
     609    PS_ASSERT_PTR_NON_NULL(fpa, false);
     610    psMetadata *conceptsFPA = pmConceptsSpecs(PM_FPA_LEVEL_FPA); // Concept specifications
     611    psTrace("psModules.concepts", 5, "Reading FPA concepts: %p %p\n", conceptsFPA, fpa->concepts);
     612    bool success = conceptsRead(&conceptsFPA, fpa, NULL, NULL, &fpa->conceptsRead, source,
     613                                config, fpa->concepts);
     614    if (propagateDown) {
     615        psArray *chips = fpa->chips;    // Array of chips
     616        for (long i = 0; i < chips->n; i++) {
     617            pmChip *chip = chips->data[i]; // Chip of interest
     618            if (chip) {
     619                success &= pmConceptsReadChip(chip, source, false, true, config);
     620            }
     621        }
     622    }
     623
     624    return success;
     625}
     626
     627
     628
     629bool pmConceptsReadChip(pmChip *chip, pmConceptSource source, bool propagateUp,
     630                        bool propagateDown, pmConfig *config)
     631{
     632    PS_ASSERT_PTR_NON_NULL(chip, false);
     633    psMetadata *conceptsChip = pmConceptsSpecs(PM_FPA_LEVEL_CHIP); // Concept specifications
     634    psTrace("psModules.concepts", 5, "Reading chip concepts: %p %p\n", conceptsChip, chip->concepts);
     635    pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
     636    bool success = conceptsRead(&conceptsChip, fpa, chip, NULL, &chip->conceptsRead, source, config,
     637                                chip->concepts);
     638    if (propagateUp) {
     639        psMetadata *conceptsFPA = pmConceptsSpecs(PM_FPA_LEVEL_FPA); // Concept specifications
     640        success &= conceptsRead(&conceptsFPA, fpa, chip, NULL, &fpa->conceptsRead, source,
     641                                config, fpa->concepts);
     642    }
     643    if (propagateDown) {
     644        psArray *cells = chip->cells;        // Array of cells
     645        for (long i = 0; i < cells->n; i++) {
     646            pmCell *cell = cells->data[i];  // Cell of interest
     647            if (cell) {
     648                success &= pmConceptsReadCell(cell, source, false, config);
     649            }
     650        }
     651    }
     652    return success;
     653}
     654
     655
     656bool pmConceptsReadCell(pmCell *cell, pmConceptSource source, bool propagateUp, pmConfig *config)
     657{
     658    PS_ASSERT_PTR_NON_NULL(cell, false);
     659    psMetadata *conceptsCell = pmConceptsSpecs(PM_FPA_LEVEL_CELL); // Concept specifications
     660    psTrace("psModules.concepts", 5, "Reading cell concepts: %p %p\n", conceptsCell, cell->concepts);
     661    pmChip *chip = cell->parent;        // Chip to which the cell belongs
     662    pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
     663
     664    bool success = conceptsRead(&conceptsCell, fpa, chip, cell, &cell->conceptsRead, source, config,
     665                                cell->concepts);
     666    if (propagateUp) {
     667        psMetadata *conceptsChip = pmConceptsSpecs(PM_FPA_LEVEL_CHIP); // Concept specifications
     668        success &= conceptsRead(&conceptsChip, fpa, chip, cell, &chip->conceptsRead, source, config,
     669                                chip->concepts);
     670        psMetadata *conceptsFPA = pmConceptsSpecs(PM_FPA_LEVEL_FPA); // Concept specifications
     671
     672        success &= conceptsRead(&conceptsFPA, fpa, chip, cell, &fpa->conceptsRead, source, config,
     673                                fpa->concepts);
     674    }
     675
     676    return success;
     677}
  • trunk/psModules/src/concepts/pmConceptsRead.h

    r18163 r22699  
    1111#ifndef PM_CONCEPTS_READ_H
    1212#define PM_CONCEPTS_READ_H
     13
     14#include <pslib.h>
     15#include <pmFPA.h>
     16#include <pmConfig.h>
     17#include <pmConcepts.h>
    1318
    1419/// Read concepts from the camera format file's CELLS.
     
    7984                                  pmConfig *config // Configuration
    8085                                 );
     86
     87/// Read the concepts for the given set of fpa, chip, cell
     88///
     89/// Attempts to read as many concepts as possible from the specified source for the specified FPA, chip and
     90/// cell.  That is, it will read chip- and cell-level concepts in addition to fpa-level concepts, if the chip
     91/// and cell are provided.
     92bool pmConceptsRead(pmFPA *fpa,         ///< FPA for which to read concepts
     93                    pmChip *chip,       ///< Chip for which to read concepts, or NULL
     94                    pmCell *cell,       ///< Cell for which to read concepts, or NULL
     95                    pmConceptSource source, ///< The source of the concepts to read
     96                    pmConfig *config    ///< Configuration
     97                   );
     98
     99/// Read concepts for an FPA; optionally, read concepts at all lower levels.
     100///
     101/// Once concepts should be available for reading at the FPA-level, this function attempts to read the
     102/// concepts from the specified source.  It also allows concepts to be read at lower levels by iterating over
     103/// the components.
     104bool pmConceptsReadFPA(pmFPA *fpa,      ///< FPA for which to read concepts
     105                       pmConceptSource source, ///< Source for concepts
     106                       bool propagateDown, ///< Propagate to lower levels?
     107                       pmConfig *config         ///< Configuration
     108                      );
     109
     110/// Read concepts for a chip; optionally, read concepts at the FPA and cell levels.
     111///
     112/// Once concepts should be available for reading at the FPA-level, this function attempts to read the
     113/// concepts from the specified source.  It also allows concepts to be read at the fpa level (through the
     114/// parent), and the cell level by iterating over the components.
     115bool pmConceptsReadChip(pmChip *chip,   ///< Chip for which to read concepts
     116                        pmConceptSource source, ///< Source for concepts
     117                        bool propagateUp, ///< Propagate to higher levels?
     118                        bool propagateDown, ///< Propagate to lower levels?
     119                        pmConfig *config        ///< Configuration
     120                       );
     121
     122/// Read concepts for a cell; optionally, read concepts for the parents.
     123///
     124/// Once concepts should be available for reading at the FPA-level, this function attempts to read the
     125/// concepts from the specified source.  It also allows concepts to be read at upper levels through the
     126/// parents (note, it would not read concepts for all chips, but only the parent of this cell).
     127bool pmConceptsReadCell(pmCell *cell,   ///< Cell for which to read concepts
     128                        pmConceptSource source, ///< Source for concepts
     129                        bool propagateUp, ///< Propagate to higher levels?
     130                        pmConfig *config        ///< Configuration
     131                       );
     132
    81133/// @}
    82134#endif
  • trunk/psModules/src/concepts/pmConceptsStandard.c

    r22683 r22699  
    13501350
    13511351
     1352psMetadataItem *p_pmConceptCopy_TIMESYS(const psMetadataItem *target,
     1353                                        const psMetadataItem *source,
     1354                                        const psMetadata *cameraFormat,
     1355                                        const pmFPA *fpa,
     1356                                        const pmChip *chip,
     1357                                        const pmCell *cell)
     1358{
     1359    if (!target || target->data.S32 == -1) {
     1360        // Replace
     1361        return psMetadataItemCopy(source);
     1362    }
     1363    // Keep what we've got --- it's been mandated by use of the DEFAULTS
     1364    return psMemIncrRefCounter((psMetadataItem*)target);
     1365}
  • trunk/psModules/src/concepts/pmConceptsStandard.h

    r20095 r22699  
    2020
    2121/// Parse the CELL.READNOISE concept to do ADU->e correction if required
    22 psMetadataItem *p_pmConceptParse_CELL_READNOISE(const psMetadataItem *concept,
    23                                                 const psMetadataItem *pattern,
    24                                                 pmConceptSource source,
    25                                                 const psMetadata *cameraFormat,
    26                                                 const pmFPA *fpa,
    27                                                 const pmChip *chip,
    28                                                 const pmCell *cell);
     22psMetadataItem *p_pmConceptParse_CELL_READNOISE(
     23    const psMetadataItem *concept,
     24    const psMetadataItem *pattern,
     25    pmConceptSource source,
     26    const psMetadata *cameraFormat,
     27    const pmFPA *fpa,
     28    const pmChip *chip,
     29    const pmCell *cell
     30);
    2931
    3032/// Format the CELL.READNOISE concept to do e->ADU correction if required
    31 psMetadataItem *p_pmConceptFormat_CELL_READNOISE(const psMetadataItem *concept,
    32                                                  pmConceptSource source,
    33                                                  const psMetadata *cameraFormat,
    34                                                  const pmFPA *fpa,
    35                                                  const pmChip *chip,
    36                                                  const pmCell *cell);
     33psMetadataItem *p_pmConceptFormat_CELL_READNOISE(
     34    const psMetadataItem *concept,
     35    pmConceptSource source,
     36    const psMetadata *cameraFormat,
     37    const pmFPA *fpa,
     38    const pmChip *chip,
     39    const pmCell *cell
     40    );
    3741
    3842// Parse the TELTEMPS concept : parse a list of the form 'X1 X2 X3 X4 X5 ...' : for now use median
    39 psMetadataItem *p_pmConceptParse_TELTEMPS(const psMetadataItem *concept,
    40                                           const psMetadataItem *pattern,
    41                                           pmConceptSource source,
    42                                           const psMetadata *cameraFormat,
    43                                           const pmFPA *fpa,
    44                                           const pmChip *chip,
    45                                           const pmCell *cell);
     43psMetadataItem *p_pmConceptParse_TELTEMPS(
     44    const psMetadataItem *concept,
     45    const psMetadataItem *pattern,
     46    pmConceptSource source,
     47    const psMetadata *cameraFormat,
     48    const pmFPA *fpa,
     49    const pmChip *chip,
     50    const pmCell *cell
     51    );
    4652
    4753/// Parse the FPA.FILTER concept to apply a lookup table
    48 psMetadataItem *p_pmConceptParse_FPA_FILTER(const psMetadataItem *concept, ///< Concept to parse
    49         const psMetadataItem *pattern, ///< Pattern to use in parsing
    50                                             pmConceptSource source, ///< Source for concept
    51         const psMetadata *cameraFormat, ///< Camera format definition
    52         const pmFPA *fpa, ///< FPA for concept, or NULL
    53         const pmChip *chip, ///< Chip for concept, or NULL
    54         const pmCell *cell ///< Cell for concept, or NULL
    55                                            );
     54psMetadataItem *p_pmConceptParse_FPA_FILTER(
     55    const psMetadataItem *concept, ///< Concept to parse
     56    const psMetadataItem *pattern, ///< Pattern to use in parsing
     57    pmConceptSource source, ///< Source for concept
     58    const psMetadata *cameraFormat, ///< Camera format definition
     59    const pmFPA *fpa, ///< FPA for concept, or NULL
     60    const pmChip *chip, ///< Chip for concept, or NULL
     61    const pmCell *cell ///< Cell for concept, or NULL
     62    );
    5663
    5764/// Format the FPA.FILTER concept to (reverse-)apply a lookup table
    58 psMetadataItem *p_pmConceptFormat_FPA_FILTER(const psMetadataItem *concept, ///< Concept to format
    59                                             pmConceptSource source, ///< Source for concept
    60         const psMetadata *cameraFormat, ///< Camera format definition
    61         const pmFPA *fpa, ///< FPA for concept, or NULL
    62         const pmChip *chip, ///< Chip for concept, or NULL
    63         const pmCell *cell ///< Cell for concept, or NULL
    64                                             );
     65psMetadataItem *p_pmConceptFormat_FPA_FILTER(
     66    const psMetadataItem *concept, ///< Concept to format
     67    pmConceptSource source, ///< Source for concept
     68    const psMetadata *cameraFormat, ///< Camera format definition
     69    const pmFPA *fpa, ///< FPA for concept, or NULL
     70    const pmChip *chip, ///< Chip for concept, or NULL
     71    const pmCell *cell ///< Cell for concept, or NULL
     72    );
    6573
    6674/// Parse the coordinates concepts: FPA.RA and FPA.DEC
    67 psMetadataItem *p_pmConceptParse_FPA_Coords(const psMetadataItem *concept, ///< Concept to parse
    68         const psMetadataItem *pattern, ///< Pattern to use in parsing
    69                                             pmConceptSource source, ///< Source for concept
    70         const psMetadata *cameraFormat, ///< Camera format definition
    71         const pmFPA *fpa, ///< FPA for concept, or NULL
    72         const pmChip *chip, ///< Chip for concept, or NULL
    73         const pmCell *cell ///< Cell for concept, or NULL
    74                                            );
     75psMetadataItem *p_pmConceptParse_FPA_Coords(
     76    const psMetadataItem *concept, ///< Concept to parse
     77    const psMetadataItem *pattern, ///< Pattern to use in parsing
     78    pmConceptSource source, ///< Source for concept
     79    const psMetadata *cameraFormat, ///< Camera format definition
     80    const pmFPA *fpa, ///< FPA for concept, or NULL
     81    const pmChip *chip, ///< Chip for concept, or NULL
     82    const pmCell *cell ///< Cell for concept, or NULL
     83    );
    7584
    7685/// Format the coordinates concepts: FPA.RA and FPA.DEC
    77 psMetadataItem *p_pmConceptFormat_FPA_Coords(const psMetadataItem *concept, ///< Concept to format
    78                                             pmConceptSource source, ///< Source for concept
    79         const psMetadata *cameraFormat, ///< Camera format definition
    80         const pmFPA *fpa, ///< FPA for concept, or NULL
    81         const pmChip *chip, ///< Chip for concept, or NULL
    82         const pmCell *cell ///< Cell for concept, or NULL
    83                                             );
     86psMetadataItem *p_pmConceptFormat_FPA_Coords(
     87    const psMetadataItem *concept, ///< Concept to format
     88    pmConceptSource source, ///< Source for concept
     89    const psMetadata *cameraFormat, ///< Camera format definition
     90    const pmFPA *fpa, ///< FPA for concept, or NULL
     91    const pmChip *chip, ///< Chip for concept, or NULL
     92    const pmCell *cell ///< Cell for concept, or NULL
     93    );
    8494
    8595/// Parse the CELL.TRIMSEC concept
    86 psMetadataItem *p_pmConceptParse_CELL_TRIMSEC(const psMetadataItem *concept, ///< Concept to parse
    87         const psMetadataItem *pattern, ///< Pattern to use in parsing
    88                                             pmConceptSource source, ///< Source for concept
    89         const psMetadata *cameraFormat, ///< Camera format definition
    90         const pmFPA *fpa, ///< FPA for concept, or NULL
    91         const pmChip *chip, ///< Chip for concept, or NULL
    92         const pmCell *cell ///< Cell for concept, or NULL
    93                                              );
     96psMetadataItem *p_pmConceptParse_CELL_TRIMSEC(
     97    const psMetadataItem *concept, ///< Concept to parse
     98    const psMetadataItem *pattern, ///< Pattern to use in parsing
     99    pmConceptSource source, ///< Source for concept
     100    const psMetadata *cameraFormat, ///< Camera format definition
     101    const pmFPA *fpa, ///< FPA for concept, or NULL
     102    const pmChip *chip, ///< Chip for concept, or NULL
     103    const pmCell *cell ///< Cell for concept, or NULL
     104    );
    94105
    95106/// Parse the CELL.BIASSEC concept
    96 psMetadataItem *p_pmConceptParse_CELL_BIASSEC(const psMetadataItem *concept, ///< Concept to parse
    97         const psMetadataItem *pattern, ///< Pattern to use in parsing
    98                                             pmConceptSource source, ///< Source for concept
    99         const psMetadata *cameraFormat, ///< Camera format definition
    100         const pmFPA *fpa, ///< FPA for concept, or NULL
    101         const pmChip *chip, ///< Chip for concept, or NULL
    102         const pmCell *cell ///< Cell for concept, or NULL
    103                                              );
     107psMetadataItem *p_pmConceptParse_CELL_BIASSEC(
     108    const psMetadataItem *concept, ///< Concept to parse
     109    const psMetadataItem *pattern, ///< Pattern to use in parsing
     110    pmConceptSource source, ///< Source for concept
     111    const psMetadata *cameraFormat, ///< Camera format definition
     112    const pmFPA *fpa, ///< FPA for concept, or NULL
     113    const pmChip *chip, ///< Chip for concept, or NULL
     114    const pmCell *cell ///< Cell for concept, or NULL
     115    );
    104116
    105117/// Parse the cell binning concepts: CELL.XBIN, CELL.YBIN
    106 psMetadataItem *p_pmConceptParse_CELL_Binning(const psMetadataItem *concept, ///< Concept to parse
    107         const psMetadataItem *pattern, ///< Pattern to use in parsing
    108                                             pmConceptSource source, ///< Source for concept
    109         const psMetadata *cameraFormat, ///< Camera format definition
    110         const pmFPA *fpa, ///< FPA for concept, or NULL
    111         const pmChip *chip, ///< Chip for concept, or NULL
    112         const pmCell *cell ///< Cell for concept, or NULL
    113                                              );
     118psMetadataItem *p_pmConceptParse_CELL_Binning(
     119    const psMetadataItem *concept, ///< Concept to parse
     120    const psMetadataItem *pattern, ///< Pattern to use in parsing
     121    pmConceptSource source, ///< Source for concept
     122    const psMetadata *cameraFormat, ///< Camera format definition
     123    const pmFPA *fpa, ///< FPA for concept, or NULL
     124    const pmChip *chip, ///< Chip for concept, or NULL
     125    const pmCell *cell ///< Cell for concept, or NULL
     126    );
    114127
    115128/// Parse the time system concepts: FPA.TIMESYS and CELL.TIMESYS
    116 psMetadataItem *p_pmConceptParse_TIMESYS(const psMetadataItem *concept, ///< Concept to parse
    117         const psMetadataItem *pattern, ///< Pattern to use in parsing
    118                                             pmConceptSource source, ///< Source for concept
    119         const psMetadata *cameraFormat, ///< Camera format definition
    120         const pmFPA *fpa, ///< FPA for concept, or NULL
    121         const pmChip *chip, ///< Chip for concept, or NULL
    122         const pmCell *cell ///< Cell for concept, or NULL
    123                                         );
     129psMetadataItem *p_pmConceptParse_TIMESYS(
     130    const psMetadataItem *concept, ///< Concept to parse
     131    const psMetadataItem *pattern, ///< Pattern to use in parsing
     132    pmConceptSource source, ///< Source for concept
     133    const psMetadata *cameraFormat, ///< Camera format definition
     134    const pmFPA *fpa, ///< FPA for concept, or NULL
     135    const pmChip *chip, ///< Chip for concept, or NULL
     136    const pmCell *cell ///< Cell for concept, or NULL
     137    );
    124138
    125139/// Parse the time concepts: FPA.TIME and CELL.TIME
    126 psMetadataItem *p_pmConceptParse_TIME(const psMetadataItem *concept, ///< Concept to parse
    127                                       const psMetadataItem *pattern, ///< Pattern to use in parsing
    128                                             pmConceptSource source, ///< Source for concept
    129                                       const psMetadata *cameraFormat, ///< Camera format definition
    130                                       const pmFPA *fpa, ///< FPA for concept, or NULL
    131                                       const pmChip *chip, ///< Chip for concept, or NULL
    132                                       const pmCell *cell ///< Cell for concept, or NULL
    133                                      );
     140psMetadataItem *p_pmConceptParse_TIME(
     141    const psMetadataItem *concept, ///< Concept to parse
     142    const psMetadataItem *pattern, ///< Pattern to use in parsing
     143    pmConceptSource source, ///< Source for concept
     144    const psMetadata *cameraFormat, ///< Camera format definition
     145    const pmFPA *fpa, ///< FPA for concept, or NULL
     146    const pmChip *chip, ///< Chip for concept, or NULL
     147    const pmCell *cell ///< Cell for concept, or NULL
     148    );
    134149
    135150/// Parse a cell position concept, e.g., CELL.X0
    136 psMetadataItem *p_pmConceptParse_Positions(const psMetadataItem *concept, ///< Concept to parse
    137         const psMetadataItem *pattern, ///< Pattern to use in parsing
    138                                             pmConceptSource source, ///< Source for concept
    139        const psMetadata *cameraFormat, ///< Camera format definition
    140         const pmFPA *fpa, ///< FPA for concept, or NULL
    141         const pmChip *chip, ///< Chip for concept, or NULL
    142         const pmCell *cell ///< Cell for concept, or NULL
    143                                           );
     151psMetadataItem *p_pmConceptParse_Positions(
     152    const psMetadataItem *concept, ///< Concept to parse
     153    const psMetadataItem *pattern, ///< Pattern to use in parsing
     154    pmConceptSource source, ///< Source for concept
     155    const psMetadata *cameraFormat, ///< Camera format definition
     156    const pmFPA *fpa, ///< FPA for concept, or NULL
     157    const pmChip *chip, ///< Chip for concept, or NULL
     158    const pmCell *cell ///< Cell for concept, or NULL
     159    );
    144160
    145161/// Format the CELL.TRIMSEC concept
    146 psMetadataItem *p_pmConceptFormat_CELL_TRIMSEC(const psMetadataItem *concept, ///< Concept to format
    147                                             pmConceptSource source, ///< Source for concept
    148         const psMetadata *cameraFormat, ///< Camera format definition
    149         const pmFPA *fpa, ///< FPA for concept, or NULL
    150         const pmChip *chip, ///< Chip for concept, or NULL
    151         const pmCell *cell ///< Cell for concept, or NULL
    152                                               );
     162psMetadataItem *p_pmConceptFormat_CELL_TRIMSEC(
     163    const psMetadataItem *concept, ///< Concept to format
     164    pmConceptSource source, ///< Source for concept
     165    const psMetadata *cameraFormat, ///< Camera format definition
     166    const pmFPA *fpa, ///< FPA for concept, or NULL
     167    const pmChip *chip, ///< Chip for concept, or NULL
     168    const pmCell *cell ///< Cell for concept, or NULL
     169    );
    153170
    154171/// Format the CELL.BIASSEC concept
    155 psMetadataItem *p_pmConceptFormat_CELL_BIASSEC(const psMetadataItem *concept, ///< Concept to format
    156                                             pmConceptSource source, ///< Source for concept
    157         const psMetadata *cameraFormat, ///< Camera format definition
    158         const pmFPA *fpa, ///< FPA for concept, or NULL
    159         const pmChip *chip, ///< Chip for concept, or NULL
    160         const pmCell *cell ///< Cell for concept, or NULL
    161                                               );
     172psMetadataItem *p_pmConceptFormat_CELL_BIASSEC(
     173    const psMetadataItem *concept, ///< Concept to format
     174    pmConceptSource source, ///< Source for concept
     175    const psMetadata *cameraFormat, ///< Camera format definition
     176    const pmFPA *fpa, ///< FPA for concept, or NULL
     177    const pmChip *chip, ///< Chip for concept, or NULL
     178    const pmCell *cell ///< Cell for concept, or NULL
     179    );
    162180
    163181/// Format the CELL.XBIN concept
    164 psMetadataItem *p_pmConceptFormat_CELL_XBIN(const psMetadataItem *concept, ///< Concept to format
    165                                             pmConceptSource source, ///< Source for concept
    166         const psMetadata *cameraFormat, ///< Camera format definition
    167         const pmFPA *fpa, ///< FPA for concept, or NULL
    168         const pmChip *chip, ///< Chip for concept, or NULL
    169         const pmCell *cell ///< Cell for concept, or NULL
    170                                            );
     182psMetadataItem *p_pmConceptFormat_CELL_XBIN(
     183    const psMetadataItem *concept, ///< Concept to format
     184    pmConceptSource source, ///< Source for concept
     185    const psMetadata *cameraFormat, ///< Camera format definition
     186    const pmFPA *fpa, ///< FPA for concept, or NULL
     187    const pmChip *chip, ///< Chip for concept, or NULL
     188    const pmCell *cell ///< Cell for concept, or NULL
     189    );
    171190
    172191/// Format the CELL.YBIN concept
    173 psMetadataItem *p_pmConceptFormat_CELL_YBIN(const psMetadataItem *concept, ///< Concept to format
    174                                             pmConceptSource source, ///< Source for concept
    175         const psMetadata *cameraFormat, ///< Camera format definition
    176         const pmFPA *fpa, ///< FPA for concept, or NULL
    177         const pmChip *chip, ///< Chip for concept, or NULL
    178         const pmCell *cell ///< Cell for concept, or NULL
    179                                            );
     192psMetadataItem *p_pmConceptFormat_CELL_YBIN(
     193    const psMetadataItem *concept, ///< Concept to format
     194    pmConceptSource source, ///< Source for concept
     195    const psMetadata *cameraFormat, ///< Camera format definition
     196    const pmFPA *fpa, ///< FPA for concept, or NULL
     197    const pmChip *chip, ///< Chip for concept, or NULL
     198    const pmCell *cell ///< Cell for concept, or NULL
     199    );
    180200
    181201/// Format the time system concepts: FPA.TIMESYS and CELL.TIMESYS
    182 psMetadataItem *p_pmConceptFormat_TIMESYS(const psMetadataItem *concept, ///< Concept to format
    183                                             pmConceptSource source, ///< Source for concept
    184         const psMetadata *cameraFormat, ///< Camera format definition
    185         const pmFPA *fpa, ///< FPA for concept, or NULL
    186         const pmChip *chip, ///< Chip for concept, or NULL
    187         const pmCell *cell ///< Cell for concept, or NULL
    188                                          );
     202psMetadataItem *p_pmConceptFormat_TIMESYS(
     203    const psMetadataItem *concept, ///< Concept to format
     204    pmConceptSource source, ///< Source for concept
     205    const psMetadata *cameraFormat, ///< Camera format definition
     206    const pmFPA *fpa, ///< FPA for concept, or NULL
     207    const pmChip *chip, ///< Chip for concept, or NULL
     208    const pmCell *cell ///< Cell for concept, or NULL
     209    );
    189210
    190211/// Format the time concepts: FPA.TIME and CELL.TIME
    191 psMetadataItem *p_pmConceptFormat_TIME(const psMetadataItem *concept, ///< Concept to format
    192                                             pmConceptSource source, ///< Source for concept
    193                                        const psMetadata *cameraFormat, ///< Camera format definition
    194                                        const pmFPA *fpa, ///< FPA for concept, or NULL
    195                                        const pmChip *chip, ///< Chip for concept, or NULL
    196                                        const pmCell *cell ///< Cell for concept, or NULL
    197                                       );
     212psMetadataItem *p_pmConceptFormat_TIME(
     213    const psMetadataItem *concept, ///< Concept to format
     214    pmConceptSource source, ///< Source for concept
     215    const psMetadata *cameraFormat, ///< Camera format definition
     216    const pmFPA *fpa, ///< FPA for concept, or NULL
     217    const pmChip *chip, ///< Chip for concept, or NULL
     218    const pmCell *cell ///< Cell for concept, or NULL
     219    );
    198220
    199221/// Format a cell position concept, e.g., CELL.X0
    200 psMetadataItem *p_pmConceptFormat_Positions(const psMetadataItem *concept, ///< Concept to format
    201                                             pmConceptSource source, ///< Source for concept
    202         const psMetadata *cameraFormat, ///< Camera format definition
    203         const pmFPA *fpa, ///< FPA for concept, or NULL
    204         const pmChip *chip, ///< Chip for concept, or NULL
    205         const pmCell *cell ///< Cell for concept, or NULL
    206                                            );
     222psMetadataItem *p_pmConceptFormat_Positions(
     223    const psMetadataItem *concept, ///< Concept to format
     224    pmConceptSource source, ///< Source for concept
     225    const psMetadata *cameraFormat, ///< Camera format definition
     226    const pmFPA *fpa, ///< FPA for concept, or NULL
     227    const pmChip *chip, ///< Chip for concept, or NULL
     228    const pmCell *cell ///< Cell for concept, or NULL
     229    );
     230
     231/// Copy the time system only if not already set
     232psMetadataItem *p_pmConceptCopy_TIMESYS(
     233    const psMetadataItem *target,
     234    const psMetadataItem *source,
     235    const psMetadata *cameraFormat,
     236    const pmFPA *fpa,
     237    const pmChip *chip,
     238    const pmCell *cell
     239    );
     240
    207241/// @}
    208242#endif
  • trunk/psModules/src/concepts/pmConceptsWrite.c

    r18163 r22699  
    1616#include "pmConcepts.h"
    1717#include "pmConceptsRead.h"
     18
     19#include "pmConceptsWrite.h"
    1820
    1921//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     
    320322
    321323bool p_pmConceptsWriteToDefaults(const psMetadata *specs, const pmFPA *fpa, const pmChip *chip,
    322                                  const pmCell *cell, psMetadata *concepts)
     324                                 const pmCell *cell, const psMetadata *concepts)
    323325{
    324326    PS_ASSERT_PTR_NON_NULL(specs, false);
     
    486488    #endif
    487489}
     490
     491
     492
     493
     494
     495// Write all registered concepts for the specified level
     496static bool conceptsWrite(psMetadata **specs, // One of the concepts specifications
     497                          const pmFPA *fpa,   // The FPA
     498                          const pmChip *chip, // The chip
     499                          const pmCell *cell, // The cell
     500                          pmConceptSource source, // The source of the concepts to write
     501                          pmConfig *config, // Configuration
     502                          psMetadata *concepts // The concepts to write out
     503                         )
     504{
     505    assert(specs);
     506    assert(concepts);
     507
     508    pmConceptsInit();
     509
     510    psTrace("psModules.concepts", 3, "Writing concepts (%p %p %p): %d\n", fpa, chip, cell, source);
     511
     512    if (source & PM_CONCEPT_SOURCE_CELLS) {
     513        p_pmConceptsWriteToCells(*specs, cell, concepts);
     514    }
     515    if (source & PM_CONCEPT_SOURCE_DEFAULTS) {
     516        p_pmConceptsWriteToDefaults(*specs, fpa, chip, cell, concepts);
     517    }
     518    if (source & (PM_CONCEPT_SOURCE_PHU | PM_CONCEPT_SOURCE_HEADER)) {
     519        p_pmConceptsWriteToHeader(*specs, fpa, chip, cell, concepts);
     520    }
     521    if (source & PM_CONCEPT_SOURCE_DATABASE) {
     522        p_pmConceptsWriteToDatabase(*specs, fpa, chip, cell, config, concepts);
     523    }
     524
     525    return true;
     526}
     527
     528
     529bool pmConceptsWriteFPA(const pmFPA *fpa, pmConceptSource source, bool propagateDown, pmConfig *config)
     530{
     531    PS_ASSERT_PTR_NON_NULL(fpa, false);
     532    psMetadata *conceptsFPA = pmConceptsSpecs(PM_FPA_LEVEL_FPA); // Concept specifications
     533    psTrace("psModules.concepts", 5, "Writing FPA concepts: %p %p\n", conceptsFPA, fpa->concepts);
     534    bool success = conceptsWrite(&conceptsFPA, fpa, NULL, NULL, source, config, fpa->concepts);
     535    if (propagateDown) {
     536        psArray *chips = fpa->chips;        // Array of chips
     537        for (long i = 0; i < chips->n; i++) {
     538            pmChip *chip = chips->data[i];  // Chip of interest
     539            if (chip && !chip->hdu) {
     540                success &= pmConceptsWriteChip(chip, source, false, true, config);
     541            }
     542        }
     543    }
     544    return success;
     545}
     546
     547
     548bool pmConceptsWriteChip(const pmChip *chip, pmConceptSource source, bool propagateUp,
     549                         bool propagateDown, pmConfig *config)
     550{
     551    PS_ASSERT_PTR_NON_NULL(chip, false);
     552    psMetadata *conceptsChip = pmConceptsSpecs(PM_FPA_LEVEL_CHIP); // Concept specifications
     553    psTrace("psModules.concepts", 5, "Writing chip concepts: %p %p\n", conceptsChip, chip->concepts);
     554    pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
     555    bool success = conceptsWrite(&conceptsChip, fpa, chip, NULL, source, config, chip->concepts);
     556    if (propagateUp && !fpa->hdu) {
     557        psMetadata *conceptsFPA = pmConceptsSpecs(PM_FPA_LEVEL_FPA); // Concept specifications
     558        success &= conceptsWrite(&conceptsFPA, fpa, chip, NULL, source, config, fpa->concepts);
     559    }
     560    if (propagateDown) {
     561        psArray *cells = chip->cells;        // Array of cells
     562        for (long i = 0; i < cells->n; i++) {
     563            pmCell *cell = cells->data[i];  // Cell of interest
     564            if (cell && !cell->hdu) {
     565                success &= pmConceptsWriteCell(cell, source, false, config);
     566            }
     567        }
     568    }
     569    return success;
     570}
     571
     572
     573bool pmConceptsWriteCell(const pmCell *cell, pmConceptSource source, bool propagateUp, pmConfig *config)
     574{
     575    PS_ASSERT_PTR_NON_NULL(cell, false);
     576    psMetadata *conceptsCell = pmConceptsSpecs(PM_FPA_LEVEL_CELL); // Concept specifications
     577    psTrace("psModules.concepts", 5, "Writing cell concepts: %p %p\n", conceptsCell, cell->concepts);
     578    pmChip *chip = cell->parent;        // Chip to which the cell belongs
     579    pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
     580
     581    bool success = conceptsWrite(&conceptsCell, fpa, chip, cell, source, config, cell->concepts);
     582    if (propagateUp) {
     583        if (!chip->hdu) {
     584            psMetadata *conceptsChip = pmConceptsSpecs(PM_FPA_LEVEL_CHIP); // Concept specifications
     585            success &= conceptsWrite(&conceptsChip, fpa, chip, cell, source, config, chip->concepts);
     586            if (!fpa->hdu) {
     587                psMetadata *conceptsFPA = pmConceptsSpecs(PM_FPA_LEVEL_FPA); // Concept specifications
     588                success &= conceptsWrite(&conceptsFPA, fpa, chip, cell, source, config, fpa->concepts);
     589            }
     590        }
     591    }
     592
     593    return success;
     594}
  • trunk/psModules/src/concepts/pmConceptsWrite.h

    r18163 r22699  
    1111#ifndef PM_CONCEPTS_WRITE_H
    1212#define PM_CONCEPTS_WRITE_H
     13
     14#include <pslib.h>
     15#include <pmFPA.h>
     16#include <pmConfig.h>
     17#include <pmConcepts.h>
    1318
    1419/// @addtogroup Concepts Data Abstraction Concepts
     
    5863                                 const psMetadata *concepts ///< The concepts
    5964                                );
     65
     66
     67/// Write concepts for an FPA; optionally, write concepts at all lower levels.
     68///
     69/// This function writes all concepts for the FPA to the specified "source".  It also allows concepts to be
     70/// written for all lower levels by iterating over the components.
     71bool pmConceptsWriteFPA(const pmFPA *fpa,     ///< FPA for which to write concepts
     72                        pmConceptSource source, ///< Source for concepts
     73                        bool propagateDown, ///< Propagate to lower levels?
     74                        pmConfig *config        ///< Configuration
     75                       );
     76
     77/// Write concepts for a chip; optionally, write concepts at the FPA and cell levels.
     78///
     79/// This function writes all concepts for the chip to the specified "source".  It also allows concepts to be
     80/// written for the FPA, and the cell level by iterating over the components.
     81bool pmConceptsWriteChip(const pmChip *chip,  ///< Chip for which to write concepts
     82                         pmConceptSource source, ///< Source for concepts
     83                         bool propagateUp,///< Propagate to higher levels?
     84                         bool propagateDown, ///< Propagate to lower levels?
     85                         pmConfig *config       ///< Configuration
     86                        );
     87
     88/// Write concepts for a cell; optionally, write concepts for the parents.
     89///
     90/// This function writes all concepts for the chip to the specified "source".  It also allows concepts to be
     91/// written for the upper levels through the parents (note, it would not write concepts for all chips, but
     92/// only the parent of this cell).
     93bool pmConceptsWriteCell(const pmCell *cell,  ///< FPA for which to write concepts
     94                         pmConceptSource source, ///< Source for concepts
     95                         bool propagateUp, ///< Propagate to higher levels?
     96                         pmConfig *config ///< Configuration
     97                        );
     98
    6099/// @}
    61100#endif
  • trunk/psModules/src/config/pmConfigCamera.c

    r20048 r22699  
    280280        psMetadata *translation = psMetadataAlloc(); // The TRANSLATION --- how to read the FITS headers
    281281
    282         psList *concepts;               // List of concepts for each level
    283         psListIterator *iter;           // Iterator for concepts
    284         psString name;                  // Concept name, from iteration
    285 
    286         concepts = pmConceptsList(PM_FPA_LEVEL_FPA); // FPA-level concepts
    287         iter = psListIteratorAlloc(concepts, PS_LIST_HEAD, false);
    288         while ((name = psListGetAndIncrement(iter))) {
    289             const char *new = skycellConceptName(name, skycellConceptsFPA, system); // Name for skycell
     282        psMetadata *concepts;           // List of concepts for each level
     283        psMetadataIterator *iter;       // Iterator for concepts
     284        psMetadataItem *item;           // Concept specification item, from iteration
     285
     286        concepts = pmConceptsSpecs(PM_FPA_LEVEL_FPA); // FPA-level concepts
     287        iter = psMetadataIteratorAlloc(concepts, PS_LIST_HEAD, NULL);
     288        while ((item = psMetadataGetAndIncrement(iter))) {
     289            const char *new = skycellConceptName(item->name, skycellConceptsFPA, system); // Name for skycell
    290290            if (new) {
    291                 psMetadataAddStr(translation, PS_LIST_TAIL, name, 0, NULL, new);
     291                psMetadataAddStr(translation, PS_LIST_TAIL, item->name, 0, NULL, new);
    292292            }
    293293        }
     
    295295        psFree(concepts);
    296296
    297         concepts = pmConceptsList(PM_FPA_LEVEL_CHIP);
    298         iter = psListIteratorAlloc(concepts, PS_LIST_HEAD, false);
    299         while ((name = psListGetAndIncrement(iter))) {
    300             const char *new = skycellConceptName(name, skycellConceptsChip, system); // Name for skycell
     297        concepts = pmConceptsSpecs(PM_FPA_LEVEL_CHIP);
     298        iter = psMetadataIteratorAlloc(concepts, PS_LIST_HEAD, NULL);
     299        while ((item = psMetadataGetAndIncrement(iter))) {
     300            const char *new = skycellConceptName(item->name, skycellConceptsChip, system); // Name for skycell
    301301            if (new) {
    302                 psMetadataAddStr(translation, PS_LIST_TAIL, name, 0, NULL, new);
     302                psMetadataAddStr(translation, PS_LIST_TAIL, item->name, 0, NULL, new);
    303303            }
    304304        }
     
    306306        psFree(concepts);
    307307
    308         concepts = pmConceptsList(PM_FPA_LEVEL_CELL);
    309         iter = psListIteratorAlloc(concepts, PS_LIST_HEAD, false);
    310         while ((name = psListGetAndIncrement(iter))) {
    311             const char *new = skycellConceptName(name, skycellConceptsCell, system); // Name for skycell
     308        concepts = pmConceptsSpecs(PM_FPA_LEVEL_CELL);
     309        iter = psMetadataIteratorAlloc(concepts, PS_LIST_HEAD, false);
     310        while ((item = psMetadataGetAndIncrement(iter))) {
     311            const char *new = skycellConceptName(item->name, skycellConceptsCell, system); // Name for skycell
    312312            if (new) {
    313                 psMetadataAddStr(translation, PS_LIST_TAIL, name, 0, NULL, new);
     313                psMetadataAddStr(translation, PS_LIST_TAIL, item->name, 0, NULL, new);
    314314            }
    315315        }
  • trunk/psModules/src/imcombine/pmSubtractionIO.c

    r20355 r22699  
    88#include "pmFPAfile.h"
    99#include "pmFPAfileFitsIO.h"
    10 #include "pmConcepts.h"
     10#include "pmConceptsRead.h"
    1111
    1212#include "pmSubtraction.h"
  • trunk/psModules/src/objects/pmSourceIO.c

    r21516 r22699  
    2929#include "pmFPAfile.h"
    3030#include "pmFPAfileFitsIO.h"
    31 #include "pmConcepts.h"
     31#include "pmConceptsRead.h"
    3232
    3333#include "pmSpan.h"
     
    503503                  status = pmSourcesWrite_PS1_CAL_0_XSRC (file->fits, readout, sources, file->header, xsrcname, recipe);
    504504              }
    505               if (!strcmp (exttype, "PS1_V1")) {
    506                   status = pmSourcesWrite_CMF_PS1_V1_XSRC (file->fits, sources, xsrcname, recipe);
    507               }
     505              if (!strcmp (exttype, "PS1_V1")) {
     506                  status = pmSourcesWrite_CMF_PS1_V1_XSRC (file->fits, sources, xsrcname, recipe);
     507              }
    508508            }
    509509            if (xfitname) {
  • trunk/psModules/src/psmodules.h

    r21422 r22699  
    3232// the following headers are from psModule:concepts
    3333#include <pmConcepts.h>
     34#include <pmConceptsStandard.h>
    3435#include <pmConceptsRead.h>
    35 #include <pmConceptsStandard.h>
    3636#include <pmConceptsWrite.h>
     37#include <pmConceptsCopy.h>
    3738#include <pmConceptsPhotcode.h>
    3839#include <pmConceptsAverage.h>
Note: See TracChangeset for help on using the changeset viewer.