IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Mar 16, 2006, 3:47:44 PM (20 years ago)
Author:
Paul Price
Message:

PHU=NONE (i.e., megacam split) now working, with concept ingest; changed definition of pmFPAAddSource to return a pmFPAview

File:
1 edited

Legend:

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

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