Changeset 6734 for branches/rel10_ifa/psModules/src/astrom/pmConcepts.c
- Timestamp:
- Mar 30, 2006, 10:08:30 AM (20 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/rel10_ifa/psModules/src/astrom/pmConcepts.c
r6618 r6734 76 76 77 77 // Set all registered concepts to blank value for the specified level 78 static bool conceptsBlank(psMetadata **specs, // One of the concepts specifications78 static bool conceptsBlank(psMetadata **specs, // One of the concepts specifications 79 79 psMetadata *target // Place to install the concepts 80 80 ) … … 89 89 pmConceptSpec *spec = specItem->data.V; // The specification 90 90 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 } 92 101 } 93 102 psFree(specsIter); … … 158 167 } 159 168 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 170 bool 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 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 { 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 189 bool 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 199 bool 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 207 bool 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 221 bool 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 235 bool 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 243 bool 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 258 bool 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 273 bool 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 516 void pmConceptsDone(void) 517 { 518 psFree(conceptsFPA); 519 psFree(conceptsChip); 520 psFree(conceptsCell); 521 } 522 523 524 // Copy concepts from one FPA to another 525 bool 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); 522 554 return false; 523 555 } 524 for (int i = 0; i < targetChips->n; i++) {525 pmC hip *targetChip = targetChips->data[i]; // Target chip of interest526 pmC hip *sourceChip = sourceChips->data[i]; // Source chip of interest527 if (! targetC hip || ! 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) { 528 560 continue; 529 561 } 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.
