IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Mar 30, 2006, 10:08:30 AM (20 years ago)
Author:
Paul Price
Message:

pmFPACopy now working

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/rel10_ifa/psModules/src/astrom/pmConcepts.c

    r6618 r6734  
    7676
    7777// Set all registered concepts to blank value for the specified level
    78 static bool conceptsBlank(psMetadata **specs,  // One of the concepts specifications
     78static bool conceptsBlank(psMetadata **specs, // One of the concepts specifications
    7979                          psMetadata *target // Place to install the concepts
    8080                         )
     
    8989        pmConceptSpec *spec = specItem->data.V; // The specification
    9090        psMetadataItem *blank = spec->blank; // The concept
    91         psMetadataAddItem(target, blank, PS_LIST_TAIL, PS_META_REPLACE);
     91        psMetadataItem *copy = NULL;    // Copy of the blank concept
     92        // Trap the lists, which can't be copied in the ordinary way without a warning
     93        if (blank->type == PS_DATA_LIST) {
     94            copy = psMetadataItemAlloc(blank->name, PS_DATA_LIST, blank->comment, blank->data.V);
     95        } else {
     96            copy = psMetadataItemCopy(blank);
     97        }
     98        if (!psMetadataAddItem(target, copy, PS_LIST_TAIL, PS_META_REPLACE)) {
     99            psLogMsg(__func__, PS_LOG_WARN, "Unable to add blank version of concept %s\n", blank->name);
     100        }
    92101    }
    93102    psFree(specsIter);
     
    158167}
    159168
    160 #if 0
    161 bool pmConceptsRead(pmFPAview *view,
    162                     pmFPAlevel levels,
    163                     pmConceptSource source,
    164                     psDB *db
    165                    )
    166 {
    167     pmFPA *fpa = view->fpa;             // The FPA
    168 
    169     #endif
    170 
    171     // Set the concepts for a given FPA to blanks
    172     bool pmConceptsBlankFPA(pmFPA *fpa    // FPA for which to set blank concepts
    173                            ) {
    174         psTrace("psModule.concepts", 5, "Blanking FPA concepts: %x %x\n", conceptsFPA, fpa->concepts);
    175         return conceptsBlank(&conceptsFPA, fpa->concepts);
    176     }
    177 
    178     // Read the concepts for a given FPA
    179     bool pmConceptsReadFPA(pmFPA *fpa,      // FPA for which to read concepts
    180                            pmConceptSource source, // The source of the concepts to read
    181                            psDB *db         // Database handle
    182                           ) {
    183         psTrace("psModule.concepts", 5, "Reading FPA concepts: %x %x\n", conceptsFPA, fpa->concepts);
    184         return conceptsRead(&conceptsFPA, fpa, NULL, NULL, source, db, fpa->concepts);
    185     }
    186 
    187     // Read the concepts for a given FPA
    188     bool pmConceptsWriteFPA(pmFPA *fpa,     // FPA for which to write concepts
    189                             pmConceptSource source, // The source of the concepts to read
    190                             psDB *db        // Database handle
    191                            ) {
    192         psTrace("psModule.concepts", 5, "Writing FPA concepts: %x %x\n", conceptsFPA, fpa->concepts);
    193         return conceptsWrite(&conceptsFPA, fpa, NULL, NULL, source, db, fpa->concepts);
    194     }
    195 
    196     // Set the concepts for a given chip to blanks
    197     bool pmConceptsBlankChip(pmChip *chip // FPA for which to set blank concepts
    198                             ) {
    199         psTrace("psModule.concepts", 5, "Blanking chip concepts: %x %x\n", conceptsChip, chip->concepts);
    200         return conceptsBlank(&conceptsChip, chip->concepts);
    201     }
    202 
    203     // Read the concepts for a given FPA
    204     bool pmConceptsReadChip(pmChip *chip,   // Chip for which to read concepts
    205                             pmConceptSource source, // The source of the concepts to read
    206                             bool propagate, // Propagate to higher levels as well?
    207                             psDB *db        // Database handle
    208                            ) {
    209         psTrace("psModule.concepts", 5, "Reading chip concepts: %x %x\n", conceptsChip, chip->concepts);
    210         pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
    211         return conceptsRead(&conceptsChip, fpa, chip, NULL, source, db, chip->concepts) &&
    212                ((propagate && conceptsRead(&conceptsFPA, fpa, chip, NULL, source, db, fpa->concepts)) ||
    213                 !propagate);
    214     }
    215 
    216     // Read the concepts for a given FPA
    217     bool pmConceptsWriteChip(pmChip *chip,  // Chip for which to write concepts
    218                              pmConceptSource source, // The source of the concepts to read
    219                              bool propagate,// Propagate to higher levels as well?
    220                              psDB *db        // Database handle
    221                             ) {
    222         psTrace("psModule.concepts", 5, "Writing chip concepts: %x %x\n", conceptsChip, chip->concepts);
    223         pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
    224         return conceptsWrite(&conceptsChip, fpa, chip, NULL, source, db, chip->concepts) &&
    225                ((propagate && conceptsWrite(&conceptsFPA, fpa, chip, NULL, source, db, fpa->concepts)) ||
    226                 !propagate);
    227     }
    228 
    229     // Set the concepts for a given chip to blanks
    230     bool pmConceptsBlankCell(pmCell *cell // Cell for which to set blank concepts
    231                             ) {
    232         psTrace("psModule.concepts", 5, "Blanking cell concepts: %x %x\n", conceptsCell, cell->concepts);
    233         return conceptsBlank(&conceptsCell, cell->concepts);
    234     }
    235 
    236     // Read the concepts for a given FPA
    237     bool pmConceptsReadCell(pmCell *cell,   // Cell for which to read concepts
    238                             pmConceptSource source, // The source of the concepts to read
    239                             bool propagate,// Propagate to higher levels as well?
    240                             psDB *db        // Database handle
    241                            ) {
    242         psTrace("psModule.concepts", 5, "Reading cell concepts: %x %x\n", conceptsCell, cell->concepts);
    243         pmChip *chip = cell->parent;        // Chip to which the cell belongs
    244         pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
    245         return conceptsRead(&conceptsCell, fpa, chip, cell, source, db, cell->concepts) &&
    246                ((propagate && conceptsRead(&conceptsChip, fpa, chip, cell, source, db, chip->concepts) &&
    247                  conceptsRead(&conceptsFPA, fpa, chip, cell, source, db, fpa->concepts)) || !propagate);
    248     }
    249 
    250     // Read the concepts for a given FPA
    251     bool pmConceptsWriteCell(pmCell *cell,  // FPA for which to write concepts
    252                              pmConceptSource source, // The source of the concepts to read
    253                              bool propagate,// Propagate to higher levels as well?
    254                              psDB *db       // Database handle
    255                             ) {
    256         psTrace("psModule.concepts", 5, "Writing cell concepts: %x %x\n", conceptsCell, cell->concepts);
    257         pmChip *chip = cell->parent;        // Chip to which the cell belongs
    258         pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
    259         return conceptsWrite(&conceptsCell, fpa, chip, cell, source, db, cell->concepts) &&
    260                ((propagate && conceptsWrite(&conceptsChip, fpa, chip, cell, source, db, chip->concepts) &&
    261                  conceptsWrite(&conceptsFPA, fpa, chip, cell, source, db, fpa->concepts)) || !propagate);
    262     }
    263 
    264 
    265     bool pmConceptsInit(void) {
    266         bool init = false;                  // Did we initialise anything?
    267         if (! conceptsFPA) {
    268             conceptsFPA = psMetadataAlloc();
    269             init = true;
    270 
    271             // Install the standard concepts
    272 
    273             #if 0
    274             // FPA.NAME
    275             {
    276                 psMetadataItem *fpaName = psMetadataItemAllocStr("FPA.NAME", "Name of FPA", "");
    277                 pmConceptRegister(fpaName, NULL, NULL, PM_CONCEPT_LEVEL_FPA);
    278                 psFree(fpaName);
    279             }
    280             #endif
    281 
    282             // FPA.AIRMASS
    283             {
    284                 psMetadataItem *fpaAirmass = psMetadataItemAllocF32("FPA.AIRMASS", "Airmass at boresight", 0.0);
    285                 pmConceptRegister(fpaAirmass, NULL, NULL, PM_CONCEPT_LEVEL_FPA);
    286                 psFree(fpaAirmass);
    287             }
    288 
    289             // FPA.FILTER
    290             {
    291                 psMetadataItem *fpaFilter = psMetadataItemAllocStr("FPA.FILTER", "Filter used", "");
    292                 pmConceptRegister(fpaFilter, NULL, NULL, PM_CONCEPT_LEVEL_FPA);
    293                 psFree(fpaFilter);
    294             }
    295 
    296             // FPA.POSANGLE
    297             {
    298                 psMetadataItem *fpaPosangle = psMetadataItemAllocF32("FPA.POSANGLE",
    299                                               "Position angle of instrument", 0.0);
    300                 pmConceptRegister(fpaPosangle, NULL, NULL, PM_CONCEPT_LEVEL_FPA);
    301                 psFree(fpaPosangle);
    302             }
    303 
    304             // FPA.RADECSYS
    305             {
    306                 psMetadataItem *fpaRadecsys = psMetadataItemAllocStr("FPA.RADECSYS",
    307                                               "Celestial coordinate system", "");
    308                 pmConceptRegister(fpaRadecsys, NULL, NULL, PM_CONCEPT_LEVEL_FPA);
    309                 psFree(fpaRadecsys);
    310             }
    311 
    312             // FPA.RA
    313             {
    314                 psMetadataItem *fpaRa = psMetadataItemAllocF64("FPA.RA", "Right Ascension of boresight", NAN);
    315                 pmConceptRegister(fpaRa, (pmConceptParseFunc)pmConceptParse_FPA_Coords,
    316                                   (pmConceptFormatFunc)pmConceptFormat_FPA_Coords, PM_CONCEPT_LEVEL_FPA);
    317                 psFree(fpaRa);
    318             }
    319 
    320             // FPA.DEC
    321             {
    322                 psMetadataItem *fpaDec = psMetadataItemAllocF64("FPA.DEC", "Declination of boresight", NAN);
    323                 pmConceptRegister(fpaDec, (pmConceptParseFunc)pmConceptParse_FPA_Coords,
    324                                   (pmConceptFormatFunc)pmConceptFormat_FPA_Coords, PM_CONCEPT_LEVEL_FPA);
    325                 psFree(fpaDec);
    326             }
    327 
    328             // Done with FPA level concepts
    329         }
    330         if (! conceptsChip) {
    331             conceptsChip = psMetadataAlloc();
    332             init = true;
    333             // There are no standard concepts at the chip level to be installed
    334         }
    335         if (! conceptsCell) {
    336             conceptsCell = psMetadataAlloc();
    337             init = true;
    338 
    339             // Install the standard concepts
    340 
    341             // CELL.GAIN
    342             {
    343                 psMetadataItem *cellGain = psMetadataItemAllocF32("CELL.GAIN", "CCD gain (e/count)", NAN);
    344                 pmConceptRegister(cellGain, NULL, NULL, PM_CONCEPT_LEVEL_CELL);
    345                 psFree(cellGain);
    346             }
    347 
    348             // CELL.READNOISE
    349             {
    350                 psMetadataItem *cellReadnoise = psMetadataItemAllocF32("CELL.READNOISE",
    351                                                 "CCD read noise (e)", NAN);
    352                 pmConceptRegister(cellReadnoise, NULL, NULL, PM_CONCEPT_LEVEL_CELL);
    353                 psFree(cellReadnoise);
    354             }
    355 
    356             // CELL.SATURATION
    357             {
    358                 psMetadataItem *cellSaturation = psMetadataItemAllocF32("CELL.SATURATION",
    359                                                  "Saturation level (counts)", NAN);
    360                 pmConceptRegister(cellSaturation, NULL, NULL, PM_CONCEPT_LEVEL_CELL);
    361                 psFree(cellSaturation);
    362             }
    363 
    364             // CELL.BAD
    365             {
    366                 psMetadataItem *cellBad = psMetadataItemAllocF32("CELL.BAD", "Bad level (counts)", NAN);
    367                 pmConceptRegister(cellBad, NULL, NULL, PM_CONCEPT_LEVEL_CELL);
    368                 psFree(cellBad);
    369             }
    370 
    371             // CELL.XPARITY
    372             {
    373                 psMetadataItem *cellXparity = psMetadataItemAllocS32("CELL.XPARITY",
    374                                               "Orientation in x compared to the rest of the FPA", 0);
    375                 pmConceptRegister(cellXparity, NULL, NULL, PM_CONCEPT_LEVEL_CELL);
    376                 psFree(cellXparity);
    377             }
    378 
    379             // CELL.YPARITY
    380             {
    381                 psMetadataItem *cellYparity = psMetadataItemAllocS32("CELL.YPARITY",
    382                                               "Orientation in x compared to the rest of the FPA", 0);
    383                 pmConceptRegister(cellYparity, NULL, NULL, PM_CONCEPT_LEVEL_CELL);
    384                 psFree(cellYparity);
    385             }
    386 
    387             // CELL.READDIR
    388             {
    389                 psMetadataItem *cellReaddir = psMetadataItemAllocS32("CELL.READDIR",
    390                                               "Read direction, rows=1, cols=2", 1);
    391                 pmConceptRegister(cellReaddir, NULL, NULL, PM_CONCEPT_LEVEL_CELL);
    392                 psFree(cellReaddir);
    393             }
    394 
    395 
    396             // These (CELL.EXPOSURE and CELL.DARKTIME) used to be READOUT.EXPOSURE and READOUT.DARKTIME, but that
    397             // doesn't really make sense at the moment.  Maybe we need to add a "parent" link to the readouts.
    398             // But then how are the exposure times REALLY derived?  They're not in the FITS headers, because a
    399             // readout is a plane in a 3D image.  We'll have to dream up some additional suffix to specify these,
    400             // but for now....
    401 
    402             // CELL.EXPOSURE
    403             {
    404                 psMetadataItem *cellExposure = psMetadataItemAllocF32("CELL.EXPOSURE",
    405                                                "Exposure time (sec)", NAN);
    406                 pmConceptRegister(cellExposure, NULL, NULL, PM_CONCEPT_LEVEL_CELL);
    407                 psFree(cellExposure);
    408             }
    409 
    410             // CELL.DARKTIME
    411             {
    412                 psMetadataItem *cellDarktime = psMetadataItemAllocF32("CELL.DARKTIME",
    413                                                "Time since flush (sec)", NAN);
    414                 pmConceptRegister(cellDarktime, NULL, NULL, PM_CONCEPT_LEVEL_CELL);
    415                 psFree(cellDarktime);
    416             }
    417 
    418             // CELL.TRIMSEC
    419             {
    420                 psRegion *trimsec = psAlloc(sizeof(psRegion)); // Blank trimsec
    421                 trimsec->x0 = trimsec->y0 = trimsec->x1 = trimsec->y1 = NAN;
    422                 psMetadataItem *cellTrimsec = psMetadataItemAllocPtr("CELL.TRIMSEC", PS_DATA_UNKNOWN,
    423                                               "Trim section", trimsec);
    424                 psFree(trimsec);
    425                 pmConceptRegister(cellTrimsec, (pmConceptParseFunc)pmConceptParse_CELL_TRIMSEC,
    426                                   (pmConceptFormatFunc)pmConceptFormat_CELL_TRIMSEC, PM_CONCEPT_LEVEL_CELL);
    427                 psFree(cellTrimsec);
    428             }
    429 
    430             // CELL.BIASSEC
    431             {
    432                 psList *biassecs = psListAlloc(NULL); // Blank biassecs
    433                 psMetadataItem *cellBiassec = psMetadataItemAllocPtr("CELL.BIASSEC", PS_DATA_LIST,
    434                                               "Bias sections", biassecs);
    435                 psFree(biassecs);
    436                 pmConceptRegister(cellBiassec, (pmConceptParseFunc)pmConceptParse_CELL_BIASSEC,
    437                                   (pmConceptFormatFunc)pmConceptFormat_CELL_BIASSEC, PM_CONCEPT_LEVEL_CELL);
    438                 psFree(cellBiassec);
    439             }
    440 
    441             // CELL.XBIN
    442             {
    443                 psMetadataItem *cellXbin = psMetadataItemAllocS32("CELL.XBIN", "Binning in x", 0);
    444                 pmConceptRegister(cellXbin, (pmConceptParseFunc)pmConceptParse_CELL_Binning,
    445                                   (pmConceptFormatFunc)pmConceptFormat_CELL_XBIN, PM_CONCEPT_LEVEL_CELL);
    446                 psFree(cellXbin);
    447             }
    448 
    449             // CELL.YBIN
    450             {
    451                 psMetadataItem *cellYbin = psMetadataItemAllocS32("CELL.YBIN", "Binning in y", 0);
    452                 pmConceptRegister(cellYbin, (pmConceptParseFunc)pmConceptParse_CELL_Binning,
    453                                   (pmConceptFormatFunc)pmConceptFormat_CELL_YBIN, PM_CONCEPT_LEVEL_CELL);
    454                 psFree(cellYbin);
    455             }
    456 
    457             // CELL.TIMESYS
    458             {
    459                 psMetadataItem *cellTimesys = psMetadataItemAllocS32("CELL.TIMESYS", "Time system", -1);
    460                 pmConceptRegister(cellTimesys, (pmConceptParseFunc)pmConceptParse_CELL_TIMESYS,
    461                                   (pmConceptFormatFunc)pmConceptFormat_CELL_TIMESYS, PM_CONCEPT_LEVEL_CELL);
    462                 psFree(cellTimesys);
    463             }
    464 
    465             // CELL.TIME
    466             {
    467                 psTime *time = psTimeAlloc(PS_TIME_TAI); // Blank time
    468                 // Not particularly distinguishing, but should be good enough
    469                 time->sec = 0;
    470                 time->nsec = 0;
    471                 psMetadataItem *cellTime = psMetadataItemAlloc("CELL.TIME", PS_DATA_TIME,
    472                                            "Time of exposure", time);
    473                 psFree(time);
    474                 pmConceptRegister(cellTime, (pmConceptParseFunc)pmConceptParse_CELL_TIME,
    475                                   (pmConceptFormatFunc)pmConceptFormat_CELL_TIME, PM_CONCEPT_LEVEL_CELL);
    476                 psFree(cellTime);
    477             }
    478 
    479             // CELL.X0
    480             {
    481                 psMetadataItem *cellX0 = psMetadataItemAllocS32("CELL.X0", "Position of (0,0) on the chip", 0);
    482                 pmConceptRegister(cellX0, (pmConceptParseFunc)pmConceptParse_CELL_Positions,
    483                                   (pmConceptFormatFunc)pmConceptFormat_CELL_Positions, PM_CONCEPT_LEVEL_CELL);
    484                 psFree(cellX0);
    485             }
    486 
    487             // CELL.Y0
    488             {
    489                 psMetadataItem *cellY0 = psMetadataItemAllocS32("CELL.Y0", "Position of (0,0) on the chip", 0);
    490                 pmConceptRegister(cellY0, (pmConceptParseFunc)pmConceptParse_CELL_Positions,
    491                                   (pmConceptFormatFunc)pmConceptFormat_CELL_Positions, PM_CONCEPT_LEVEL_CELL);
    492                 psFree(cellY0);
    493             }
    494 
    495         }
    496 
    497         conceptsInitialised = true;
    498 
    499         return init;
    500     }
    501 
    502     void pmConceptsDone(void) {
    503         psFree(conceptsFPA);
    504         psFree(conceptsChip);
    505         psFree(conceptsCell);
    506     }
    507 
    508 
    509     // Copy concepts from one FPA to another
    510     bool pmFPACopyConcepts(pmFPA *target,   // The target FPA
    511                            pmFPA *source    // The target FPA
    512                           ) {
    513         // Copy FPA concepts
    514         target->concepts = psMetadataCopy(target->concepts, source->concepts);
    515 
    516         // Copy chip concepts
    517         psArray *targetChips = target->chips; // Chips in target
    518         psArray *sourceChips = source->chips; // Chips in source
    519         if (targetChips->n != sourceChips->n) {
    520             psError(PS_ERR_IO, true, "Number of chips in target (%d) and source (%d) differ --- unable to copy "
    521                     "concepts.\n", targetChips->n, sourceChips->n);
     169// Set the concepts for a given FPA to blanks
     170bool pmConceptsBlankFPA(pmFPA *fpa    // FPA for which to set blank concepts
     171                       )
     172{
     173    psTrace("psModule.concepts", 5, "Blanking FPA concepts: %x %x\n", conceptsFPA, fpa->concepts);
     174    return conceptsBlank(&conceptsFPA, fpa->concepts);
     175}
     176
     177
     178// Read the concepts for a given FPA
     179bool pmConceptsReadFPA(pmFPA *fpa,      // FPA for which to read concepts
     180                       pmConceptSource source, // The source of the concepts to read
     181                       psDB *db         // Database handle
     182                      )
     183{
     184    psTrace("psModule.concepts", 5, "Reading FPA concepts: %x %x\n", conceptsFPA, fpa->concepts);
     185    return conceptsRead(&conceptsFPA, fpa, NULL, NULL, source, db, fpa->concepts);
     186}
     187
     188// Read the concepts for a given FPA
     189bool pmConceptsWriteFPA(pmFPA *fpa,     // FPA for which to write concepts
     190                        pmConceptSource source, // The source of the concepts to read
     191                        psDB *db        // Database handle
     192                       )
     193{
     194    psTrace("psModule.concepts", 5, "Writing FPA concepts: %x %x\n", conceptsFPA, fpa->concepts);
     195    return conceptsWrite(&conceptsFPA, fpa, NULL, NULL, source, db, fpa->concepts);
     196}
     197
     198// Set the concepts for a given chip to blanks
     199bool pmConceptsBlankChip(pmChip *chip // FPA for which to set blank concepts
     200                        )
     201{
     202    psTrace("psModule.concepts", 5, "Blanking chip concepts: %x %x\n", conceptsChip, chip->concepts);
     203    return conceptsBlank(&conceptsChip, chip->concepts);
     204}
     205
     206// Read the concepts for a given FPA
     207bool pmConceptsReadChip(pmChip *chip,   // Chip for which to read concepts
     208                        pmConceptSource source, // The source of the concepts to read
     209                        bool propagate, // Propagate to higher levels as well?
     210                        psDB *db        // Database handle
     211                       )
     212{
     213    psTrace("psModule.concepts", 5, "Reading chip concepts: %x %x\n", conceptsChip, chip->concepts);
     214    pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
     215    return conceptsRead(&conceptsChip, fpa, chip, NULL, source, db, chip->concepts) &&
     216           ((propagate && conceptsRead(&conceptsFPA, fpa, chip, NULL, source, db, fpa->concepts)) ||
     217            !propagate);
     218}
     219
     220// Read the concepts for a given FPA
     221bool pmConceptsWriteChip(pmChip *chip,  // Chip for which to write concepts
     222                         pmConceptSource source, // The source of the concepts to read
     223                         bool propagate,// Propagate to higher levels as well?
     224                         psDB *db        // Database handle
     225                        )
     226{
     227    psTrace("psModule.concepts", 5, "Writing chip concepts: %x %x\n", conceptsChip, chip->concepts);
     228    pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
     229    return conceptsWrite(&conceptsChip, fpa, chip, NULL, source, db, chip->concepts) &&
     230           ((propagate && conceptsWrite(&conceptsFPA, fpa, chip, NULL, source, db, fpa->concepts)) ||
     231            !propagate);
     232}
     233
     234// Set the concepts for a given chip to blanks
     235bool pmConceptsBlankCell(pmCell *cell // Cell for which to set blank concepts
     236                        )
     237{
     238    psTrace("psModule.concepts", 5, "Blanking cell concepts: %x %x\n", conceptsCell, cell->concepts);
     239    return conceptsBlank(&conceptsCell, cell->concepts);
     240}
     241
     242// Read the concepts for a given FPA
     243bool pmConceptsReadCell(pmCell *cell,   // Cell for which to read concepts
     244                        pmConceptSource source, // The source of the concepts to read
     245                        bool propagate,// Propagate to higher levels as well?
     246                        psDB *db        // Database handle
     247                       )
     248{
     249    psTrace("psModule.concepts", 5, "Reading cell concepts: %x %x\n", conceptsCell, cell->concepts);
     250    pmChip *chip = cell->parent;        // Chip to which the cell belongs
     251    pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
     252    return conceptsRead(&conceptsCell, fpa, chip, cell, source, db, cell->concepts) &&
     253           ((propagate && conceptsRead(&conceptsChip, fpa, chip, cell, source, db, chip->concepts) &&
     254             conceptsRead(&conceptsFPA, fpa, chip, cell, source, db, fpa->concepts)) || !propagate);
     255}
     256
     257// Read the concepts for a given FPA
     258bool pmConceptsWriteCell(pmCell *cell,  // FPA for which to write concepts
     259                         pmConceptSource source, // The source of the concepts to read
     260                         bool propagate,// Propagate to higher levels as well?
     261                         psDB *db       // Database handle
     262                        )
     263{
     264    psTrace("psModule.concepts", 5, "Writing cell concepts: %x %x\n", conceptsCell, cell->concepts);
     265    pmChip *chip = cell->parent;        // Chip to which the cell belongs
     266    pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
     267    return conceptsWrite(&conceptsCell, fpa, chip, cell, source, db, cell->concepts) &&
     268           ((propagate && conceptsWrite(&conceptsChip, fpa, chip, cell, source, db, chip->concepts) &&
     269             conceptsWrite(&conceptsFPA, fpa, chip, cell, source, db, fpa->concepts)) || !propagate);
     270}
     271
     272
     273bool pmConceptsInit(void)
     274{
     275    bool init = false;                  // Did we initialise anything?
     276    if (! conceptsFPA) {
     277        conceptsFPA = psMetadataAlloc();
     278        init = true;
     279
     280        // Install the standard concepts
     281
     282        #if 0
     283        // FPA.NAME
     284        {
     285            psMetadataItem *fpaName = psMetadataItemAllocStr("FPA.NAME", "Name of FPA", "");
     286            pmConceptRegister(fpaName, NULL, NULL, PM_CONCEPT_LEVEL_FPA);
     287            psFree(fpaName);
     288        }
     289        #endif
     290
     291        // FPA.AIRMASS
     292        {
     293            psMetadataItem *fpaAirmass = psMetadataItemAllocF32("FPA.AIRMASS", "Airmass at boresight", 0.0);
     294            pmConceptRegister(fpaAirmass, NULL, NULL, PM_CONCEPT_LEVEL_FPA);
     295            psFree(fpaAirmass);
     296        }
     297
     298        // FPA.FILTER
     299        {
     300            psMetadataItem *fpaFilter = psMetadataItemAllocStr("FPA.FILTER", "Filter used", "");
     301            pmConceptRegister(fpaFilter, NULL, NULL, PM_CONCEPT_LEVEL_FPA);
     302            psFree(fpaFilter);
     303        }
     304
     305        // FPA.POSANGLE
     306        {
     307            psMetadataItem *fpaPosangle = psMetadataItemAllocF32("FPA.POSANGLE",
     308                                          "Position angle of instrument", 0.0);
     309            pmConceptRegister(fpaPosangle, NULL, NULL, PM_CONCEPT_LEVEL_FPA);
     310            psFree(fpaPosangle);
     311        }
     312
     313        // FPA.RADECSYS
     314        {
     315            psMetadataItem *fpaRadecsys = psMetadataItemAllocStr("FPA.RADECSYS",
     316                                          "Celestial coordinate system", "");
     317            pmConceptRegister(fpaRadecsys, NULL, NULL, PM_CONCEPT_LEVEL_FPA);
     318            psFree(fpaRadecsys);
     319        }
     320
     321        // FPA.RA
     322        {
     323            psMetadataItem *fpaRa = psMetadataItemAllocF64("FPA.RA", "Right Ascension of boresight", NAN);
     324            pmConceptRegister(fpaRa, (pmConceptParseFunc)pmConceptParse_FPA_Coords,
     325                              (pmConceptFormatFunc)pmConceptFormat_FPA_Coords, PM_CONCEPT_LEVEL_FPA);
     326            psFree(fpaRa);
     327        }
     328
     329        // FPA.DEC
     330        {
     331            psMetadataItem *fpaDec = psMetadataItemAllocF64("FPA.DEC", "Declination of boresight", NAN);
     332            pmConceptRegister(fpaDec, (pmConceptParseFunc)pmConceptParse_FPA_Coords,
     333                              (pmConceptFormatFunc)pmConceptFormat_FPA_Coords, PM_CONCEPT_LEVEL_FPA);
     334            psFree(fpaDec);
     335        }
     336
     337        // Done with FPA level concepts
     338    }
     339    if (! conceptsChip) {
     340        conceptsChip = psMetadataAlloc();
     341        init = true;
     342        // There are no standard concepts at the chip level to be installed
     343    }
     344    if (! conceptsCell) {
     345        conceptsCell = psMetadataAlloc();
     346        init = true;
     347
     348        // Install the standard concepts
     349
     350        // CELL.GAIN
     351        {
     352            psMetadataItem *cellGain = psMetadataItemAllocF32("CELL.GAIN", "CCD gain (e/count)", NAN);
     353            pmConceptRegister(cellGain, NULL, NULL, PM_CONCEPT_LEVEL_CELL);
     354            psFree(cellGain);
     355        }
     356
     357        // CELL.READNOISE
     358        {
     359            psMetadataItem *cellReadnoise = psMetadataItemAllocF32("CELL.READNOISE",
     360                                            "CCD read noise (e)", NAN);
     361            pmConceptRegister(cellReadnoise, NULL, NULL, PM_CONCEPT_LEVEL_CELL);
     362            psFree(cellReadnoise);
     363        }
     364
     365        // CELL.SATURATION
     366        {
     367            psMetadataItem *cellSaturation = psMetadataItemAllocF32("CELL.SATURATION",
     368                                             "Saturation level (counts)", NAN);
     369            pmConceptRegister(cellSaturation, NULL, NULL, PM_CONCEPT_LEVEL_CELL);
     370            psFree(cellSaturation);
     371        }
     372
     373        // CELL.BAD
     374        {
     375            psMetadataItem *cellBad = psMetadataItemAllocF32("CELL.BAD", "Bad level (counts)", NAN);
     376            pmConceptRegister(cellBad, NULL, NULL, PM_CONCEPT_LEVEL_CELL);
     377            psFree(cellBad);
     378        }
     379
     380        // CELL.XPARITY
     381        {
     382            psMetadataItem *cellXparity = psMetadataItemAllocS32("CELL.XPARITY",
     383                                          "Orientation in x compared to the rest of the FPA", 0);
     384            pmConceptRegister(cellXparity, NULL, NULL, PM_CONCEPT_LEVEL_CELL);
     385            psFree(cellXparity);
     386        }
     387
     388        // CELL.YPARITY
     389        {
     390            psMetadataItem *cellYparity = psMetadataItemAllocS32("CELL.YPARITY",
     391                                          "Orientation in x compared to the rest of the FPA", 0);
     392            pmConceptRegister(cellYparity, NULL, NULL, PM_CONCEPT_LEVEL_CELL);
     393            psFree(cellYparity);
     394        }
     395
     396        // CELL.READDIR
     397        {
     398            psMetadataItem *cellReaddir = psMetadataItemAllocS32("CELL.READDIR",
     399                                          "Read direction, rows=1, cols=2", 1);
     400            pmConceptRegister(cellReaddir, NULL, NULL, PM_CONCEPT_LEVEL_CELL);
     401            psFree(cellReaddir);
     402        }
     403
     404
     405        // These (CELL.EXPOSURE and CELL.DARKTIME) used to be READOUT.EXPOSURE and READOUT.DARKTIME, but that
     406        // doesn't really make sense at the moment.  Maybe we need to add a "parent" link to the readouts.
     407        // But then how are the exposure times REALLY derived?  They're not in the FITS headers, because a
     408        // readout is a plane in a 3D image.  We'll have to dream up some additional suffix to specify these,
     409        // but for now....
     410
     411        // CELL.EXPOSURE
     412        {
     413            psMetadataItem *cellExposure = psMetadataItemAllocF32("CELL.EXPOSURE",
     414                                           "Exposure time (sec)", NAN);
     415            pmConceptRegister(cellExposure, NULL, NULL, PM_CONCEPT_LEVEL_CELL);
     416            psFree(cellExposure);
     417        }
     418
     419        // CELL.DARKTIME
     420        {
     421            psMetadataItem *cellDarktime = psMetadataItemAllocF32("CELL.DARKTIME",
     422                                           "Time since flush (sec)", NAN);
     423            pmConceptRegister(cellDarktime, NULL, NULL, PM_CONCEPT_LEVEL_CELL);
     424            psFree(cellDarktime);
     425        }
     426
     427        // CELL.TRIMSEC
     428        {
     429            psRegion *trimsec = psAlloc(sizeof(psRegion)); // Blank trimsec
     430            trimsec->x0 = trimsec->y0 = trimsec->x1 = trimsec->y1 = NAN;
     431            psMetadataItem *cellTrimsec = psMetadataItemAllocPtr("CELL.TRIMSEC", PS_DATA_REGION,
     432                                          "Trim section", trimsec);
     433            psFree(trimsec);
     434            pmConceptRegister(cellTrimsec, (pmConceptParseFunc)pmConceptParse_CELL_TRIMSEC,
     435                              #if 0
     436                              (pmConceptFormatFunc)pmConceptFormat_CELL_TRIMSEC,
     437                              #else
     438                              NULL,
     439                              #endif
     440                              PM_CONCEPT_LEVEL_CELL);
     441            psFree(cellTrimsec);
     442        }
     443
     444        // CELL.BIASSEC
     445        {
     446            psList *biassecs = psListAlloc(NULL); // Blank biassecs
     447            psMetadataItem *cellBiassec = psMetadataItemAllocPtr("CELL.BIASSEC", PS_DATA_LIST,
     448                                          "Bias sections", biassecs);
     449            psFree(biassecs);
     450            pmConceptRegister(cellBiassec, (pmConceptParseFunc)pmConceptParse_CELL_BIASSEC,
     451                              (pmConceptFormatFunc)pmConceptFormat_CELL_BIASSEC, PM_CONCEPT_LEVEL_CELL);
     452            psFree(cellBiassec);
     453        }
     454
     455        // CELL.XBIN
     456        {
     457            psMetadataItem *cellXbin = psMetadataItemAllocS32("CELL.XBIN", "Binning in x", 0);
     458            pmConceptRegister(cellXbin, (pmConceptParseFunc)pmConceptParse_CELL_Binning,
     459                              (pmConceptFormatFunc)pmConceptFormat_CELL_XBIN, PM_CONCEPT_LEVEL_CELL);
     460            psFree(cellXbin);
     461        }
     462
     463        // CELL.YBIN
     464        {
     465            psMetadataItem *cellYbin = psMetadataItemAllocS32("CELL.YBIN", "Binning in y", 0);
     466            pmConceptRegister(cellYbin, (pmConceptParseFunc)pmConceptParse_CELL_Binning,
     467                              (pmConceptFormatFunc)pmConceptFormat_CELL_YBIN, PM_CONCEPT_LEVEL_CELL);
     468            psFree(cellYbin);
     469        }
     470
     471        // CELL.TIMESYS
     472        {
     473            psMetadataItem *cellTimesys = psMetadataItemAllocS32("CELL.TIMESYS", "Time system", -1);
     474            pmConceptRegister(cellTimesys, (pmConceptParseFunc)pmConceptParse_CELL_TIMESYS,
     475                              (pmConceptFormatFunc)pmConceptFormat_CELL_TIMESYS, PM_CONCEPT_LEVEL_CELL);
     476            psFree(cellTimesys);
     477        }
     478
     479        // CELL.TIME
     480        {
     481            psTime *time = psTimeAlloc(PS_TIME_TAI); // Blank time
     482            // Not particularly distinguishing, but should be good enough
     483            time->sec = 0;
     484            time->nsec = 0;
     485            psMetadataItem *cellTime = psMetadataItemAlloc("CELL.TIME", PS_DATA_TIME,
     486                                       "Time of exposure", time);
     487            psFree(time);
     488            pmConceptRegister(cellTime, (pmConceptParseFunc)pmConceptParse_CELL_TIME,
     489                              (pmConceptFormatFunc)pmConceptFormat_CELL_TIME, PM_CONCEPT_LEVEL_CELL);
     490            psFree(cellTime);
     491        }
     492
     493        // CELL.X0
     494        {
     495            psMetadataItem *cellX0 = psMetadataItemAllocS32("CELL.X0", "Position of (0,0) on the chip", 0);
     496            pmConceptRegister(cellX0, (pmConceptParseFunc)pmConceptParse_CELL_Positions,
     497                              (pmConceptFormatFunc)pmConceptFormat_CELL_Positions, PM_CONCEPT_LEVEL_CELL);
     498            psFree(cellX0);
     499        }
     500
     501        // CELL.Y0
     502        {
     503            psMetadataItem *cellY0 = psMetadataItemAllocS32("CELL.Y0", "Position of (0,0) on the chip", 0);
     504            pmConceptRegister(cellY0, (pmConceptParseFunc)pmConceptParse_CELL_Positions,
     505                              (pmConceptFormatFunc)pmConceptFormat_CELL_Positions, PM_CONCEPT_LEVEL_CELL);
     506            psFree(cellY0);
     507        }
     508
     509    }
     510
     511    conceptsInitialised = true;
     512
     513    return init;
     514}
     515
     516void pmConceptsDone(void)
     517{
     518    psFree(conceptsFPA);
     519    psFree(conceptsChip);
     520    psFree(conceptsCell);
     521}
     522
     523
     524// Copy concepts from one FPA to another
     525bool pmFPACopyConcepts(pmFPA *target,   // The target FPA
     526                       pmFPA *source    // The target FPA
     527                      )
     528{
     529    // Copy FPA concepts
     530    target->concepts = psMetadataCopy(target->concepts, source->concepts);
     531
     532    // Copy chip concepts
     533    psArray *targetChips = target->chips; // Chips in target
     534    psArray *sourceChips = source->chips; // Chips in source
     535    if (targetChips->n != sourceChips->n) {
     536        psError(PS_ERR_IO, true, "Number of chips in target (%d) and source (%d) differ --- unable to copy "
     537                "concepts.\n", targetChips->n, sourceChips->n);
     538        return false;
     539    }
     540    for (int i = 0; i < targetChips->n; i++) {
     541        pmChip *targetChip = targetChips->data[i]; // Target chip of interest
     542        pmChip *sourceChip = sourceChips->data[i]; // Source chip of interest
     543        if (! targetChip || ! sourceChip) {
     544            continue;
     545        }
     546        targetChip->concepts = psMetadataCopy(targetChip->concepts, sourceChip->concepts);
     547
     548        // Copy cell concepts
     549        psArray *targetCells = targetChip->cells; // Cells in target
     550        psArray *sourceCells = sourceChip->cells; // Cells in source
     551        if (targetCells->n != sourceCells->n) {
     552            psError(PS_ERR_IO, true, "Number of cells in target (%d) and source (%d) differ for chip %d ---"
     553                    " unable to copy concepts.\n", targetCells->n, sourceCells->n, i);
    522554            return false;
    523555        }
    524         for (int i = 0; i < targetChips->n; i++) {
    525             pmChip *targetChip = targetChips->data[i]; // Target chip of interest
    526             pmChip *sourceChip = sourceChips->data[i]; // Source chip of interest
    527             if (! targetChip || ! sourceChip) {
     556        for (int j = 0; j < targetCells->n; j++) {
     557            pmCell *targetCell = targetCells->data[j]; // Target chip of interest
     558            pmCell *sourceCell = sourceCells->data[j]; // Source chip of interest
     559            if (! targetCell || ! sourceCell) {
    528560                continue;
    529561            }
    530             targetChip->concepts = psMetadataCopy(targetChip->concepts, sourceChip->concepts);
    531 
    532             // Copy cell concepts
    533             psArray *targetCells = targetChip->cells; // Cells in target
    534             psArray *sourceCells = sourceChip->cells; // Cells in source
    535             if (targetCells->n != sourceCells->n) {
    536                 psError(PS_ERR_IO, true, "Number of cells in target (%d) and source (%d) differ for chip %d ---"
    537                         " unable to copy concepts.\n", targetCells->n, sourceCells->n, i);
    538                 return false;
    539             }
    540             for (int j = 0; j < targetCells->n; j++) {
    541                 pmCell *targetCell = targetCells->data[j]; // Target chip of interest
    542                 pmCell *sourceCell = sourceCells->data[j]; // Source chip of interest
    543                 if (! targetCell || ! sourceCell) {
    544                     continue;
    545                 }
    546                 targetCell->concepts = psMetadataCopy(targetCell->concepts, sourceCell->concepts);
    547             }
    548         }
    549 
    550         return true;
    551     }
     562            targetCell->concepts = psMetadataCopy(targetCell->concepts, sourceCell->concepts);
     563        }
     564    }
     565
     566    return true;
     567}
Note: See TracChangeset for help on using the changeset viewer.