IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Mar 5, 2009, 11:13:29 AM (17 years ago)
Author:
beaumont
Message:

Finished ppStack visualization. Unified the way in which visualizations are invoked, plotting windows are closed, etc

Location:
branches/cnb_branches/cnb_branch_20090215
Files:
41 deleted
38 edited
2 copied

Legend:

Unmodified
Added
Removed
  • branches/cnb_branches/cnb_branch_20090215

  • branches/cnb_branches/cnb_branch_20090215/psModules/src/camera/pmFPAConstruct.c

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

    r21536 r23197  
    1313#include "pmFPAUtils.h"
    1414#include "pmHDUUtils.h"
     15#include "pmConceptsCopy.h"
    1516#include "pmFPACopy.h"
    1617
     
    452453    // Update the concepts
    453454    psMetadataItem *chipName = psMemIncrRefCounter(psMetadataLookup(target->concepts, "CHIP.NAME"));
    454     psMetadataCopy(target->concepts, source->concepts);
     455    pmConceptsCopyChip(target, source, false);
    455456    psMetadataAddItem(target->concepts, chipName, PS_LIST_TAIL, PS_META_REPLACE);
    456457    psFree(chipName);
    457     psMetadataCopy(target->parent->concepts, source->parent->concepts);
     458    pmConceptsCopyFPA(target->parent, source->parent, false, false);
    458459
    459460    // Update the astrometric parameters
     
    467468
    468469    if (targetFPA && sourceFPA) {
    469         if (targetFPA->toSky) {
    470             psAssert (targetFPA->toSky == sourceFPA->toSky, "chips within FPA have inconsistent astrometry references");
    471         } else {
    472             targetFPA->toSky = psMemIncrRefCounter (sourceFPA->toSky);
    473         }
    474         if (targetFPA->toTPA) {
    475             psAssert (targetFPA->toTPA == sourceFPA->toTPA, "chips within FPA have inconsistent astrometry references");
    476         } else {
    477             targetFPA->toTPA = psMemIncrRefCounter (sourceFPA->toTPA);
    478         }
    479         if (targetFPA->fromTPA) {
    480             psAssert (targetFPA->fromTPA == sourceFPA->fromTPA, "chips within FPA have inconsistent astrometry references");
    481         } else {
    482             targetFPA->fromTPA = psMemIncrRefCounter (sourceFPA->fromTPA);
    483         }
     470        if (targetFPA->toSky) {
     471            psAssert (targetFPA->toSky == sourceFPA->toSky, "chips within FPA have inconsistent astrometry references");
     472        } else {
     473            targetFPA->toSky = psMemIncrRefCounter (sourceFPA->toSky);
     474        }
     475        if (targetFPA->toTPA) {
     476            psAssert (targetFPA->toTPA == sourceFPA->toTPA, "chips within FPA have inconsistent astrometry references");
     477        } else {
     478            targetFPA->toTPA = psMemIncrRefCounter (sourceFPA->toTPA);
     479        }
     480        if (targetFPA->fromTPA) {
     481            psAssert (targetFPA->fromTPA == sourceFPA->fromTPA, "chips within FPA have inconsistent astrometry references");
     482        } else {
     483            targetFPA->fromTPA = psMemIncrRefCounter (sourceFPA->fromTPA);
     484        }
    484485    }
    485486
     
    525526
    526527    // Update the concepts
    527     psMetadataCopy(targetChip->concepts, sourceChip->concepts);
     528    pmConceptsCopyChip(targetChip, sourceChip, false);
    528529
    529530    // update the attributes
     
    572573
    573574    // Update the concepts
    574     psMetadataCopy(target->concepts, source->concepts);
     575    pmConceptsCopyFPA(target, source, false, false);
    575576
    576577    return status;
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/camera/pmFPAHeader.c

    r18163 r23197  
    1010#include "pmFPA.h"
    1111#include "pmFPALevel.h"
    12 #include "pmConcepts.h"
     12#include "pmConceptsRead.h"
    1313#include "pmFPAHeader.h"
    1414
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/camera/pmFPARead.c

    r21363 r23197  
    1717#include "pmFPAFlags.h"
    1818#include "pmHDUUtils.h"
    19 #include "pmConcepts.h"
     19#include "pmConceptsRead.h"
    2020#include "pmFPAHeader.h"
    2121
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/camera/pmFPAWrite.c

    r21363 r23197  
    1818#include "pmHDUUtils.h"
    1919#include "pmHDUGenerate.h"
    20 #include "pmConcepts.h"
     20#include "pmConceptsWrite.h"
    2121
    2222#include "pmFPAWrite.h"
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/camera/pmFPAfile.c

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

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

    r21363 r23197  
    2222#include "pmFPAConstruct.h"
    2323#include "pmDark.h"
    24 #include "pmConcepts.h"
     24#include "pmConceptsWrite.h"
    2525
    2626// Get a suitable FPA for the file; generate it if necessary
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/camera/pmHDUUtils.h

    r18554 r23197  
    1111#ifndef PM_HDU_UTILS_H
    1212#define PM_HDU_UTILS_H
     13
     14#include <pmHDU.h>
     15#include <pmFPA.h>
    1316
    1417/// @addtogroup Camera Camera Layout
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/concepts/Makefile.am

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

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

    r18364 r23197  
    1212#define PM_CONCEPTS_H
    1313
     14#include <pslib.h>
     15#include <pmFPALevel.h>
     16#include <pmFPA.h>
    1417#include <pmConfig.h>
    1518
     
    3437
    3538/// Function to call to parse a concept once it has been read
    36 typedef psMetadataItem* (*pmConceptParseFunc)(const psMetadataItem *concept, ///< Concept to parse
    37         const psMetadataItem *pattern, ///< Pattern for parsing
    38                                               pmConceptSource source, ///< Source of concept
    39         const psMetadata *cameraFormat, ///< Camera format definition
    40         const pmFPA *fpa, ///< FPA for concept, or NULL
    41         const pmChip *chip, ///< Chip for concept, or NULL
    42         const pmCell *cell ///< Cell for concept, or NULL
    43                                              );
     39typedef psMetadataItem* (*pmConceptParseFunc)(
     40    const psMetadataItem *concept, ///< Concept to parse
     41    const psMetadataItem *pattern, ///< Pattern for parsing
     42    pmConceptSource source, ///< Source of concept
     43    const psMetadata *cameraFormat, ///< Camera format definition
     44    const pmFPA *fpa, ///< FPA for concept, or NULL
     45    const pmChip *chip, ///< Chip for concept, or NULL
     46    const pmCell *cell ///< Cell for concept, or NULL
     47    );
    4448
    4549/// Function to call to format a concept for writing
    46 typedef psMetadataItem* (*pmConceptFormatFunc)(const psMetadataItem *concept, ///< Concept to format
    47                                                pmConceptSource source, ///< Source of concept
    48         const psMetadata *cameraFormat, ///< Camera format definition
    49         const pmFPA *fpa, ///< FPA for concept, or NULL
    50         const pmChip *chip, ///< Chip for concept, or NULL
    51         const pmCell *cell ///< Cell for concept, or NULL
    52                                               );
     50typedef psMetadataItem* (*pmConceptFormatFunc)(
     51    const psMetadataItem *concept, ///< Concept to format
     52    pmConceptSource source, ///< Source of concept
     53    const psMetadata *cameraFormat, ///< Camera format definition
     54    const pmFPA *fpa, ///< FPA for concept, or NULL
     55    const pmChip *chip, ///< Chip for concept, or NULL
     56    const pmCell *cell ///< Cell for concept, or NULL
     57    );
     58
     59/// Function to call to copy a concept
     60typedef psMetadataItem* (*pmConceptCopyFunc)(
     61    const psMetadataItem *target,       ///< Target concept
     62    const psMetadataItem *source,       ///< Source concept
     63    const psMetadata *cameraFormat,     ///< Camera format definition
     64    const pmFPA *fpa,                   ///< Source FPA for concept, or NULL
     65    const pmChip *chip,                 ///< Source chip for concept, or NULL
     66    const pmCell *cell                  ///< Source cell for concept, or NULL
     67    );
     68
    5369
    5470/// A "concept" specification
     
    5672/// Defines the name, default comment, blank value, and functions to parse (after reading) and format (before
    5773/// writing) the concept.
    58 typedef struct
    59 {
     74typedef struct {
    6075    psMetadataItem *blank;              ///< Blank value of concept; also contains the name and comment
    61     pmConceptParseFunc parse;           ///< Function to call to read the concept
    62     pmConceptFormatFunc format;         ///< Function to call to write the concept
     76    pmConceptParseFunc parse;           ///< Function to call to read the concept, or NULL
     77    pmConceptFormatFunc format;         ///< Function to call to write the concept, or NULL
     78    pmConceptCopyFunc copy;             ///< Function to call to copy the concept, or NULL
    6379    bool required;                      ///< Is concept required (throw an error on problems)?
    6480}
     
    6783/// Allocator for pmConceptSpec
    6884pmConceptSpec *pmConceptSpecAlloc(psMetadataItem *blank, ///< Blank value; contains the name
    69                                   pmConceptParseFunc parse, ///< Function to call to parse the concept
    70                                   pmConceptFormatFunc format, ///< Function to call to format the concept
     85                                  pmConceptParseFunc parse, ///< Function to call to parse the concept/NULL
     86                                  pmConceptFormatFunc format, ///< Function to call to format the concept/NULL
     87                                  pmConceptCopyFunc copy, ///< Function to call to copy the concept, or NULL
    7188                                  bool required ///< Is concept required?
    7289                                 );
     
    92109                       pmConceptParseFunc parse, ///< Function to call to parse the concept, or NULL
    93110                       pmConceptFormatFunc format, ///< Function to call to format the concept, or NULL
     111                       pmConceptCopyFunc copy, ///< Function to call to copy the concept, or NULL
    94112                       bool required,   ///< Is concept required?
    95113                       pmFPALevel level ///< Level at which to store concept in the FPA hierarchy
    96114                      );
    97115
    98 /// Get a list of defined concepts for a particular level.
    99 psList *pmConceptsList(pmFPALevel level);
     116/// Get the specifications for defined concepts of a particular level
     117psMetadata *pmConceptsSpecs(pmFPALevel level);
    100118
    101 /// Read the concepts for the given set of fpa, chip, cell
    102 ///
    103 /// Attempts to read as many concepts as possible from the specified source for the specified FPA, chip and
    104 /// cell.  That is, it will read chip- and cell-level concepts in addition to fpa-level concepts, if the chip
    105 /// and cell are provided.
    106 bool pmConceptsRead(pmFPA *fpa,         ///< FPA for which to read concepts
    107                     pmChip *chip,       ///< Chip for which to read concepts, or NULL
    108                     pmCell *cell,       ///< Cell for which to read concepts, or NULL
    109                     pmConceptSource source, ///< The source of the concepts to read
    110                     pmConfig *config    ///< Configuration
    111                    );
    112119
    113120/// Set the concepts within the FPA to the blank value
    114121bool pmConceptsBlankFPA(pmFPA *fpa      ///< FPA for which to set blank concepts
    115                        );
    116 
    117 /// Read concepts for an FPA; optionally, read concepts at all lower levels.
    118 ///
    119 /// Once concepts should be available for reading at the FPA-level, this function attempts to read the
    120 /// concepts from the specified source.  It also allows concepts to be read at lower levels by iterating over
    121 /// the components.
    122 bool pmConceptsReadFPA(pmFPA *fpa,      ///< FPA for which to read concepts
    123                        pmConceptSource source, ///< Source for concepts
    124                        bool propagateDown, ///< Propagate to lower levels?
    125                        pmConfig *config         ///< Configuration
    126                       );
    127 
    128 /// Write concepts for an FPA; optionally, write concepts at all lower levels.
    129 ///
    130 /// This function writes all concepts for the FPA to the specified "source".  It also allows concepts to be
    131 /// written for all lower levels by iterating over the components.
    132 bool pmConceptsWriteFPA(const pmFPA *fpa,     ///< FPA for which to write concepts
    133                         pmConceptSource source, ///< Source for concepts
    134                         bool propagateDown, ///< Propagate to lower levels?
    135                         pmConfig *config        ///< Configuration
    136122                       );
    137123
     
    140126                        );
    141127
    142 /// Read concepts for a chip; optionally, read concepts at the FPA and cell levels.
    143 ///
    144 /// Once concepts should be available for reading at the FPA-level, this function attempts to read the
    145 /// concepts from the specified source.  It also allows concepts to be read at the fpa level (through the
    146 /// parent), and the cell level by iterating over the components.
    147 bool pmConceptsReadChip(pmChip *chip,   ///< Chip for which to read concepts
    148                         pmConceptSource source, ///< Source for concepts
    149                         bool propagateUp, ///< Propagate to higher levels?
    150                         bool propagateDown, ///< Propagate to lower levels?
    151                         pmConfig *config        ///< Configuration
    152                        );
    153 
    154 /// Write concepts for a chip; optionally, write concepts at the FPA and cell levels.
    155 ///
    156 /// This function writes all concepts for the chip to the specified "source".  It also allows concepts to be
    157 /// written for the FPA, and the cell level by iterating over the components.
    158 bool pmConceptsWriteChip(const pmChip *chip,  ///< Chip for which to write concepts
    159                          pmConceptSource source, ///< Source for concepts
    160                          bool propagateUp,///< Propagate to higher levels?
    161                          bool propagateDown, ///< Propagate to lower levels?
    162                          pmConfig *config       ///< Configuration
    163                         );
    164 
    165128/// Set the concepts within the cell to the blank value
    166129bool pmConceptsBlankCell(pmCell *cell   ///< Cell for which to set blank concepts
    167                         );
    168 
    169 /// Read concepts for a cell; optionally, read concepts for the parents.
    170 ///
    171 /// Once concepts should be available for reading at the FPA-level, this function attempts to read the
    172 /// concepts from the specified source.  It also allows concepts to be read at upper levels through the
    173 /// parents (note, it would not read concepts for all chips, but only the parent of this cell).
    174 bool pmConceptsReadCell(pmCell *cell,   ///< Cell for which to read concepts
    175                         pmConceptSource source, ///< Source for concepts
    176                         bool propagateUp, ///< Propagate to higher levels?
    177                         pmConfig *config        ///< Configuration
    178                        );
    179 
    180 /// Write concepts for a cell; optionally, write concepts for the parents.
    181 ///
    182 /// This function writes all concepts for the chip to the specified "source".  It also allows concepts to be
    183 /// written for the upper levels through the parents (note, it would not write concepts for all chips, but
    184 /// only the parent of this cell).
    185 bool pmConceptsWriteCell(const pmCell *cell,  ///< FPA for which to write concepts
    186                          pmConceptSource source, ///< Source for concepts
    187                          bool propagateUp, ///< Propagate to higher levels?
    188                          pmConfig *config ///< Configuration
    189130                        );
    190131
     
    199140/// Frees the registered concepts so there is no memory leak when the user checks "persistent" memory.
    200141void pmConceptsDone(void);
    201 
    202 /// Copy all the concepts within an FPA to another FPA
    203 ///
    204 /// Iterates over all components of the FPA, and copies the concepts metadata from the source to the target.
    205 bool pmFPACopyConcepts(pmFPA *target,   ///< The target FPA
    206                        const pmFPA *source    ///< The source FPA
    207                       );
    208 
    209 /// Copy the concepts within an FPA to another FPA; optionally recurse to lower levels
    210 bool pmConceptsCopyFPA(pmFPA *target,   ///< Target FPA
    211                        const pmFPA *source, ///< Source FPA
    212                        bool chips,      ///< Recurse to chips level?
    213                        bool cells       ///< Recurse to cells level?
    214     );
    215 
    216 /// Copy the concepts within a chip to another chip; optionally recurse to lower level
    217 bool pmConceptsCopyChip(pmChip *target, ///< Target chip
    218                         const pmChip *source, ///< Source chip
    219                         bool cells      ///< Recurse to cells level?
    220     );
    221 
    222 /// Copy the concepts within a cell to another cell
    223 bool pmConceptsCopyCell(pmCell *target, ///< Target cell
    224                         const pmCell *source ///< Source cell
    225     );
    226142
    227143/// Interpolate a concept name to the actual value
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/concepts/pmConceptsAverage.c

    r20597 r23197  
    6161
    6262        psTime *fpaTime = psMetadataLookupPtr(NULL, fpa->concepts, "FPA.TIME");
     63        psTimeConvert(fpaTime, PS_TIME_TAI);
    6364        time       += psTimeToMJD(fpaTime);
    6465        if (num == 1) {
     
    9697        psMetadataItem *timeItem = psMetadataLookup(target->concepts, "FPA.TIME");
    9798        psFree(timeItem->data.V);
    98         timeItem->data.V = psTimeFromMJD(time);
     99        psTime *new = psTimeFromMJD(time);
     100        psTimeConvert(new, timeSys);
     101        timeItem->data.V = new;
    99102    }
    100103
     
    115118        }
    116119
    117         float value = psMetadataLookupF32(&status, cell->concepts, name);
    118         if (!status) continue;
    119         if (!isfinite(value)) continue;
     120        float value = psMetadataLookupF32(&status, cell->concepts, name);
     121        if (!status) continue;
     122        if (!isfinite(value)) continue;
    120123
    121124        sum += value;
     
    246249        psMetadataItem *timeItem = psMetadataLookup(target->concepts, "CELL.TIME");
    247250        psFree(timeItem->data.V);
    248         timeItem->data.V = psTimeFromMJD(time);
     251        psTime *new = psTimeFromMJD(time);
     252        psTimeConvert(new, timeSys);
     253        timeItem->data.V = new;
    249254    }
    250255
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/concepts/pmConceptsRead.c

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

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

    r21183 r23197  
    116116                        if (!isfinite(gain)) {
    117117                            psWarning("CELL.READNOISE is supposed to be in ADU, but CELL.GAIN isn't set -- forcing to 1.0");
    118                             gain = 1.0;
     118                            gain = 1.0;
    119119                        }
    120120                        rn /= gain;
     
    639639}
    640640
     641// Determine the corresponding TIMESYS for one of the TIME concepts
     642static psTimeType conceptGetTimesysForTime(const char *name, // Concept name ("CELL.TIME" or "FPA.TIME")
     643                                           const pmFPA *fpa, // FPA of interest
     644                                           const pmChip *chip, // Chip of interest, or NULL
     645                                           const pmCell *cell // Cell of interest, or NULL
     646                                           )
     647{
     648    assert(name);
     649
     650    psString timesysName = psStringCopy(name); // e.g., "CELL.TIME" --> "CELL.TIMESYS"
     651    psStringSubstitute(&timesysName, "TIMESYS", "TIME");
     652    bool mdok = false;                  // Result of MD lookup
     653    psTimeType timeSys = 0xFFFFFFFF;    // The time system
     654    if (cell) {
     655        timeSys = psMetadataLookupS32(&mdok, cell->concepts, timesysName);
     656    }
     657    if (!mdok && chip) {
     658        timeSys = psMetadataLookupS32(&mdok, chip->concepts, timesysName);
     659    }
     660    if (!mdok && fpa) {
     661        timeSys = psMetadataLookupS32(&mdok, fpa->concepts, timesysName);
     662    }
     663    if (!mdok || (timeSys == 0xFFFFFFFF)) {
     664        psWarning("Unable to find %s in concepts when parsing %s --- assuming UTC.\n",
     665                  timesysName, name);
     666        timeSys = PS_TIME_UTC;
     667    }
     668    psFree(timesysName);
     669
     670    return timeSys;
     671}
     672
    641673psMetadataItem *p_pmConceptParse_TIME(const psMetadataItem *concept,
    642674                                      const psMetadataItem *pattern,
     
    650682    assert(cameraFormat);
    651683
    652     // Need TIMESYS first
    653     psString timesysName = psStringCopy(pattern->name); // e.g., "CELL.TIME" --> "CELL.TIMESYS"
    654     psStringSubstitute(&timesysName, "TIMESYS", "TIME");
    655     bool mdok = false;                  // Result of MD lookup
    656     psTimeType timeSys = PS_TIME_UTC; // The time system
    657     if (cell) {
    658         timeSys = psMetadataLookupS32(&mdok, cell->concepts, timesysName);
    659     }
    660     if (!mdok && chip) {
    661         timeSys = psMetadataLookupS32(&mdok, chip->concepts, timesysName);
    662     }
    663     if (!mdok && fpa) {
    664         timeSys = psMetadataLookupS32(&mdok, fpa->concepts, timesysName);
    665     }
    666     if (!mdok || (timeSys == 0xffffffff)) {
    667         psWarning("Unable to find %s in concepts when parsing %s --- assuming UTC.\n",
    668                   timesysName, pattern->name);
    669         timeSys = PS_TIME_UTC;
    670     }
    671     psFree(timesysName);
     684    psTimeType timeSys = conceptGetTimesysForTime(pattern->name, fpa, chip, cell); // Time system
    672685
    673686    // Work out how the time is represented
     
    681694
    682695    // Get format
     696    bool mdok;                          // Status of MD lookup
    683697    psMetadata *formats = psMetadataLookupMetadata(&mdok, cameraFormat, "FORMATS");
    684698    if (!mdok || !formats) {
     
    877891    }
    878892
     893    time->type = timeSys;
     894
    879895    psMetadataItem *item = psMetadataItemAllocPtr(pattern->name, PS_DATA_TIME, pattern->comment, time);
    880896    psFree(time);                       // Drop reference
     
    11321148{
    11331149    psTime *time = concept->data.V;     // The time
     1150
     1151    psTimeType timeSys = conceptGetTimesysForTime(concept->name, fpa, chip, cell); // Time system
     1152    psTimeConvert(time, timeSys);
    11341153
    11351154    // Work out the format
     
    13311350
    13321351
     1352psMetadataItem *p_pmConceptCopy_TIMESYS(const psMetadataItem *target,
     1353                                        const psMetadataItem *source,
     1354                                        const psMetadata *cameraFormat,
     1355                                        const pmFPA *fpa,
     1356                                        const pmChip *chip,
     1357                                        const pmCell *cell)
     1358{
     1359    if (!target || target->data.S32 == -1) {
     1360        // Replace
     1361        return psMetadataItemCopy(source);
     1362    }
     1363    // Keep what we've got --- it's been mandated by use of the DEFAULTS
     1364    return psMemIncrRefCounter((psMetadataItem*)target);
     1365}
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/concepts/pmConceptsStandard.h

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

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

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

    r20048 r23197  
    280280        psMetadata *translation = psMetadataAlloc(); // The TRANSLATION --- how to read the FITS headers
    281281
    282         psList *concepts;               // List of concepts for each level
    283         psListIterator *iter;           // Iterator for concepts
    284         psString name;                  // Concept name, from iteration
    285 
    286         concepts = pmConceptsList(PM_FPA_LEVEL_FPA); // FPA-level concepts
    287         iter = psListIteratorAlloc(concepts, PS_LIST_HEAD, false);
    288         while ((name = psListGetAndIncrement(iter))) {
    289             const char *new = skycellConceptName(name, skycellConceptsFPA, system); // Name for skycell
     282        psMetadata *concepts;           // List of concepts for each level
     283        psMetadataIterator *iter;       // Iterator for concepts
     284        psMetadataItem *item;           // Concept specification item, from iteration
     285
     286        concepts = pmConceptsSpecs(PM_FPA_LEVEL_FPA); // FPA-level concepts
     287        iter = psMetadataIteratorAlloc(concepts, PS_LIST_HEAD, NULL);
     288        while ((item = psMetadataGetAndIncrement(iter))) {
     289            const char *new = skycellConceptName(item->name, skycellConceptsFPA, system); // Name for skycell
    290290            if (new) {
    291                 psMetadataAddStr(translation, PS_LIST_TAIL, name, 0, NULL, new);
     291                psMetadataAddStr(translation, PS_LIST_TAIL, item->name, 0, NULL, new);
    292292            }
    293293        }
    294294        psFree(iter);
    295         psFree(concepts);
    296 
    297         concepts = pmConceptsList(PM_FPA_LEVEL_CHIP);
    298         iter = psListIteratorAlloc(concepts, PS_LIST_HEAD, false);
    299         while ((name = psListGetAndIncrement(iter))) {
    300             const char *new = skycellConceptName(name, skycellConceptsChip, system); // Name for skycell
     295
     296        concepts = pmConceptsSpecs(PM_FPA_LEVEL_CHIP);
     297        iter = psMetadataIteratorAlloc(concepts, PS_LIST_HEAD, NULL);
     298        while ((item = psMetadataGetAndIncrement(iter))) {
     299            const char *new = skycellConceptName(item->name, skycellConceptsChip, system); // Name for skycell
    301300            if (new) {
    302                 psMetadataAddStr(translation, PS_LIST_TAIL, name, 0, NULL, new);
     301                psMetadataAddStr(translation, PS_LIST_TAIL, item->name, 0, NULL, new);
    303302            }
    304303        }
    305304        psFree(iter);
    306         psFree(concepts);
    307 
    308         concepts = pmConceptsList(PM_FPA_LEVEL_CELL);
    309         iter = psListIteratorAlloc(concepts, PS_LIST_HEAD, false);
    310         while ((name = psListGetAndIncrement(iter))) {
    311             const char *new = skycellConceptName(name, skycellConceptsCell, system); // Name for skycell
     305
     306        concepts = pmConceptsSpecs(PM_FPA_LEVEL_CELL);
     307        iter = psMetadataIteratorAlloc(concepts, PS_LIST_HEAD, false);
     308        while ((item = psMetadataGetAndIncrement(iter))) {
     309            const char *new = skycellConceptName(item->name, skycellConceptsCell, system); // Name for skycell
    312310            if (new) {
    313                 psMetadataAddStr(translation, PS_LIST_TAIL, name, 0, NULL, new);
     311                psMetadataAddStr(translation, PS_LIST_TAIL, item->name, 0, NULL, new);
    314312            }
    315313        }
    316314        psFree(iter);
    317         psFree(concepts);
    318315
    319316        psMetadataAddMetadata(format, PS_LIST_TAIL, "TRANSLATION", 0, "How to translate the FITS headers",
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/detrend/pmFlatField.c

    r21456 r23197  
    4343
    4444    // Using i,j for image; x,y for flat.
    45     for (int j = rowStart, y = yOffset; j < rowStop; j++, y++) {
     45    for (int j = rowStart, y = rowStart + yOffset; j < rowStop; j++, y++) {
    4646        for (int i = 0, x = xOffset; i < numCols; i++, x++) {
    4747            float flatValue = 1.0 / flatImage->data.F32[y][x];
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/detrend/pmShutterCorrection.h

    r21536 r23197  
    55 * @author Paul Price, IfA
    66 *
    7  * @version $Revision: 1.23.2.1 $ $Name: not supported by cvs2svn $
    8  * @date $Date: 2009-02-19 17:59:50 $
     7 * @version $Revision: 1.24 $ $Name: not supported by cvs2svn $
     8 * @date $Date: 2009-02-16 22:27:49 $
    99 * Copyright 2006 Institute for Astronomy, University of Hawaii
    1010 */
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/imcombine/pmSubtractionIO.c

    r21536 r23197  
    88#include "pmFPAfile.h"
    99#include "pmFPAfileFitsIO.h"
    10 #include "pmConcepts.h"
     10#include "pmConceptsRead.h"
    1111
    1212#include "pmSubtraction.h"
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmModel.c

    r21536 r23197  
    66 *  @author EAM, IfA
    77 *
    8  *  @version $Revision: 1.27.4.1 $ $Name: not supported by cvs2svn $
    9  *  @date $Date: 2009-02-19 17:59:50 $
     8 *  @version $Revision: 1.28 $ $Name: not supported by cvs2svn $
     9 *  @date $Date: 2009-02-16 22:30:26 $
    1010 *
    1111 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    235235
    236236    if (model->residuals) {
    237         DX = xBin*(image->col0 - xCenter - dx) + model->residuals->xCenter + 0.5;
    238         DY = yBin*(image->row0 - yCenter - dy) + model->residuals->yCenter + 0.5;
    239         Ro = (model->residuals->Ro)   ? model->residuals->Ro->data.F32 : NULL;
    240         Rx = (model->residuals->Rx)   ? model->residuals->Rx->data.F32 : NULL;
    241         Ry = (model->residuals->Ry)   ? model->residuals->Ry->data.F32 : NULL;
    242         Rm = (model->residuals->mask) ? model->residuals->mask->data.PS_TYPE_IMAGE_MASK_DATA : NULL;
    243         if (Ro) {
    244             NX = model->residuals->Ro->numCols;
    245             NY = model->residuals->Ro->numRows;
    246         }
     237        DX = xBin*(image->col0 - xCenter - dx) + model->residuals->xCenter + 0.5;
     238        DY = yBin*(image->row0 - yCenter - dy) + model->residuals->yCenter + 0.5;
     239        Ro = (model->residuals->Ro)   ? model->residuals->Ro->data.F32 : NULL;
     240        Rx = (model->residuals->Rx)   ? model->residuals->Rx->data.F32 : NULL;
     241        Ry = (model->residuals->Ry)   ? model->residuals->Ry->data.F32 : NULL;
     242        Rm = (model->residuals->mask) ? model->residuals->mask->data.PS_TYPE_IMAGE_MASK_DATA : NULL;
     243        if (Ro) {
     244            NX = model->residuals->Ro->numCols;
     245            NY = model->residuals->Ro->numRows;
     246        }           
    247247    }
    248248
     
    256256
    257257            // XXX should we use using 0.5 pixel offset?
    258             // Convert to coordinate in parent image, with offset (dx,dy)
     258            // Convert to coordinate in parent image, with offset (dx,dy)
    259259            imageCol = ix + image->col0 - dx;
    260260            imageRow = iy + image->row0 - dy;
     
    276276                float rx = xBin*ix + DX;
    277277
    278                 int rx0 = rx - 0.5;
    279                 int rx1 = rx + 0.5;
    280                 int ry0 = ry - 0.5;
    281                 int ry1 = ry + 0.5;
    282 
    283                 if (rx0 < 0) goto skip;
    284                 if (ry0 < 0) goto skip;
    285                 if (rx1 >= NX) goto skip;
    286                 if (ry1 >= NY) goto skip;
    287 
    288                 // these go from 0.0 to 1.0 between the centers of the pixels
    289                 float fx = rx - 0.5 - rx0;
    290                 float Fx = 1.0 - fx;
    291                 float fy = ry - 0.5 - ry0;
    292                 float Fy = 1.0 - fy;
    293 
    294                 // check the residual image mask (if set). give up if any of the 4 pixels are masked.
    295                 if (Rm) {
    296                     if (Rm[ry0][rx0]) goto skip;
    297                     if (Rm[ry0][rx1]) goto skip;
    298                     if (Rm[ry1][rx0]) goto skip;
    299                     if (Rm[ry1][rx1]) goto skip;
    300                 }
    301 
    302                 // a possible further optimization if we re-use these values
    303                 // XXX allow for masked pixels, and add pixel weights
    304                 float V0 = (Ro[ry0][rx0]*Fx + Ro[ry0][rx1]*fx);
    305                 float V1 = (Ro[ry1][rx0]*Fx + Ro[ry1][rx1]*fx);
    306                 float Vo = V0*Fy + V1*fy;
    307                 if (!isfinite(Vo)) goto skip;
    308 
    309                 float Vx = 0.0;
    310                 float Vy = 0.0;
    311 
    312                 // skip Rx,Ry if Ro is masked
    313                 if (Rx && Ry && (mode & PM_MODEL_OP_RES1)) {
    314                     V0 = (Rx[ry0][rx0]*Fx + Rx[ry0][rx1]*fx);
    315                     V1 = (Rx[ry1][rx0]*Fx + Rx[ry1][rx1]*fx);
    316                     Vx = V0*Fy + V1*fy;
    317 
    318                     V0 = (Ry[ry0][rx0]*Fx + Ry[ry0][rx1]*fx);
    319                     V1 = (Ry[ry1][rx0]*Fx + Ry[ry1][rx1]*fx);
    320                     Vy = V0*Fy + V1*fy;
    321                 }
    322                 if (!isfinite(Vx)) goto skip;
    323                 if (!isfinite(Vy)) goto skip;
    324 
    325                 // 2D residual variations are set for the true source position
    326                 pixelValue += Io*(Vo + XoSave*Vx + XoSave*Vy);
     278                int rx0 = rx - 0.5;
     279                int rx1 = rx + 0.5;
     280                int ry0 = ry - 0.5;
     281                int ry1 = ry + 0.5;
     282
     283                if (rx0 < 0) goto skip;
     284                if (ry0 < 0) goto skip;
     285                if (rx1 >= NX) goto skip;
     286                if (ry1 >= NY) goto skip;
     287
     288                // these go from 0.0 to 1.0 between the centers of the pixels
     289                float fx = rx - 0.5 - rx0;
     290                float Fx = 1.0 - fx;
     291                float fy = ry - 0.5 - ry0;
     292                float Fy = 1.0 - fy;
     293
     294                // check the residual image mask (if set). give up if any of the 4 pixels are masked.
     295                if (Rm) {
     296                    if (Rm[ry0][rx0]) goto skip;
     297                    if (Rm[ry0][rx1]) goto skip;
     298                    if (Rm[ry1][rx0]) goto skip;
     299                    if (Rm[ry1][rx1]) goto skip;
     300                }
     301
     302                // a possible further optimization if we re-use these values
     303                // XXX allow for masked pixels, and add pixel weights
     304                float V0 = (Ro[ry0][rx0]*Fx + Ro[ry0][rx1]*fx);
     305                float V1 = (Ro[ry1][rx0]*Fx + Ro[ry1][rx1]*fx);
     306                float Vo = V0*Fy + V1*fy;
     307                if (!isfinite(Vo)) goto skip;
     308
     309                float Vx = 0.0;
     310                float Vy = 0.0;
     311
     312                // skip Rx,Ry if Ro is masked
     313                if (Rx && Ry && (mode & PM_MODEL_OP_RES1)) {
     314                    V0 = (Rx[ry0][rx0]*Fx + Rx[ry0][rx1]*fx);
     315                    V1 = (Rx[ry1][rx0]*Fx + Rx[ry1][rx1]*fx);
     316                    Vx = V0*Fy + V1*fy;
     317
     318                    V0 = (Ry[ry0][rx0]*Fx + Ry[ry0][rx1]*fx);
     319                    V1 = (Ry[ry1][rx0]*Fx + Ry[ry1][rx1]*fx);
     320                    Vy = V0*Fy + V1*fy;
     321                }
     322                if (!isfinite(Vx)) goto skip;
     323                if (!isfinite(Vy)) goto skip;
     324
     325                // 2D residual variations are set for the true source position
     326                pixelValue += Io*(Vo + XoSave*Vx + XoSave*Vy);
    327327            }
    328328
    329         skip:
     329        skip:
    330330            // add or subtract the value
    331331            if (add) {
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmModel.h

    r21536 r23197  
    55 * @author EAM, IfA
    66 *
    7  * @version $Revision: 1.18.8.1 $ $Name: not supported by cvs2svn $
    8  * @date $Date: 2009-02-19 17:59:50 $
     7 * @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
     8 * @date $Date: 2009-02-16 22:30:50 $
    99 *
    1010 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    151151    pmModel *model,                     ///< The input pmModel
    152152    pmModelOpMode mode,                 ///< mode to control how the model is added into the image
    153     psImageMaskType maskVal             ///< Value to mask
     153    psImageMaskType maskVal             ///< Value to mask
    154154);
    155155
     
    169169    pmModel *model,                     ///< The input pmModel
    170170    pmModelOpMode mode,                 ///< mode to control how the model is added into the image
    171     psImageMaskType maskVal             ///< Value to mask
     171    psImageMaskType maskVal             ///< Value to mask
    172172);
    173173
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmPeaks.c

    r21536 r23197  
    66 *  @author EAM, IfA: significant modifications.
    77 *
    8  *  @version $Revision: 1.25.14.1 $ $Name: not supported by cvs2svn $
    9  *  @date $Date: 2009-02-19 17:59:50 $
     8 *  @version $Revision: 1.26 $ $Name: not supported by cvs2svn $
     9 *  @date $Date: 2009-02-16 22:30:14 $
    1010 *
    1111 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    2828AddPeak(): A private function which allocates a psArray, if the peaks
    2929argument is NULL, otherwise it adds the peak to that array.
    30 XXX EAM : row,col now refer to image coords, NOT parent (since this is private)
     30XXX EAM : row,col now refer to image coords, NOT parent (since this is private) 
    3131XXX EAM : now also calculates fractional peak positions from 3x3 bicube region
    3232*****************************************************************************/
     
    6464        peak->yf = min.y + iy + image->row0;
    6565
    66         // These errors are fractional errors, and should be scaled by the
    67         // error on the peak pixel (see, eg, psphotFindPeaks)
    68         peak->dx = min.xErr;
    69         peak->dy = min.yErr;
    70 
    71         // xf,yf must land on image with 0 pixel border
    72         peak->xf = PS_MAX (PS_MIN (peak->xf, image->numCols - 1), image->col0);
    73         peak->yf = PS_MAX (PS_MIN (peak->yf, image->numRows - 1), image->row0);
     66        // These errors are fractional errors, and should be scaled by the
     67        // error on the peak pixel (see, eg, psphotFindPeaks)
     68        peak->dx = min.xErr;
     69        peak->dy = min.yErr;
     70       
     71        // xf,yf must land on image with 0 pixel border
     72        peak->xf = PS_MAX (PS_MIN (peak->xf, image->numCols - 1), image->col0);
     73        peak->yf = PS_MAX (PS_MIN (peak->yf, image->numRows - 1), image->row0);
    7474    } else {
    7575        peak->xf = ix;
    7676        peak->yf = iy;
    77         peak->dx = NAN;
    78         peak->dy = NAN;
     77        peak->dx = NAN;
     78        peak->dy = NAN;
    7979    }
    8080
     
    8989getRowVectorFromImage(): a private function which simply returns a
    9090psVector containing the specified row of data from the psImage.
    91 
     91 
    9292XXX: Is there a better way to do this?
    9393XXX EAM: does this really need to alloc a new vector???
     
    248248above the given threshold.  Returns a vector of type PS_TYPE_U32 containing
    249249the location (x value) of all peaks.
    250 
     250 
    251251XXX: What types should be supported?  Only F32 is implemented.
    252 
     252 
    253253XXX: We currently step through the input vector twice; once to determine the
    254254size of the output vector, then to set the values of the output vector.
     
    256256*****************************************************************************/
    257257psVector *pmPeaksInVector(const psVector *vector,
    258                         psF32 threshold)
     258                        psF32 threshold)
    259259{
    260260    psTrace("psModules.objects", 3, "---- %s() begin ----\n", __func__);
     
    350350above the given threshold.  Returns a psArray containing location (x/y value)
    351351of all peaks.
    352 
     352 
    353353XXX: I'm not convinced the peak type definition in the SDRS is mutually
    354354exclusive.  Some peaks can have multiple types.  Edges for sure.  Also, a
    355355digonal line with the same value at each point will have a peak for every
    356356point on that line.
    357 
     357 
    358358XXX: This does not work if image has either a single row, or a single column.
    359 
     359 
    360360The peak is returned in the image parent coordinates
    361361
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSource.c

    r21536 r23197  
    66 *  @author EAM, IfA: significant modifications.
    77 *
    8  *  @version $Revision: 1.69.4.1 $ $Name: not supported by cvs2svn $
    9  *  @date $Date: 2009-02-19 17:59:50 $
     8 *  @version $Revision: 1.70 $ $Name: not supported by cvs2svn $
     9 *  @date $Date: 2009-02-16 22:29:59 $
    1010 *
    1111 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    543543        pmSource *source = (pmSource *) sources->data[i];
    544544
    545         // psf clumps are found for image subregions:
    546         // skip sources not in this region
     545        // psf clumps are found for image subregions:
     546        // skip sources not in this region
    547547        if (source->peak->x <  region->x0) continue;
    548548        if (source->peak->x >= region->x1) continue;
    549549        if (source->peak->y <  region->y0) continue;
    550         if (source->peak->y >= region->y1) continue;
    551 
    552         // should be set by pmSourceAlloc
     550        if (source->peak->y >= region->y1) continue;
     551
     552        // should be set by pmSourceAlloc
    553553        psAssert (source->type == PM_SOURCE_TYPE_UNKNOWN, "source type was not init-ed?");
    554554
     
    556556        if (!source->moments) {
    557557            source->type = PM_SOURCE_TYPE_STAR;
    558             psAssert (source->mode & noMoments, "why is this source missing moments?");
     558            psAssert (source->mode & noMoments, "why is this source missing moments?");
    559559            Nstar++;
    560560            continue;
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSource.h

    r21536 r23197  
    33 * @author EAM, IfA; GLG, MHPCC
    44 *
    5  * @version $Revision: 1.28.4.1 $ $Name: not supported by cvs2svn $
    6  * @date $Date: 2009-02-19 17:59:50 $
     5 * @version $Revision: 1.29 $ $Name: not supported by cvs2svn $
     6 * @date $Date: 2009-02-16 22:30:50 $
    77 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
    88 */
     
    3737// bit flags to distinguish analysis results
    3838typedef enum {
    39     PM_SOURCE_MODE_DEFAULT          = 0x00000000, ///< Initial value: resets all bits
    40     PM_SOURCE_MODE_PSFMODEL         = 0x00000001, ///< Source fitted with a psf model (linear or non-linear)
    41     PM_SOURCE_MODE_EXTMODEL         = 0x00000002, ///< Source fitted with an extended-source model
    42     PM_SOURCE_MODE_FITTED           = 0x00000004, ///< Source fitted with non-linear model (PSF or EXT; good or bad)
    43     PM_SOURCE_MODE_FAIL             = 0x00000008, ///< Fit (non-linear) failed (non-converge, off-edge, run to zero)
    44     PM_SOURCE_MODE_POOR             = 0x00000010, ///< Fit succeeds, but low-SN, high-Chisq, or large (for PSF -- drop?)
    45     PM_SOURCE_MODE_PAIR             = 0x00000020, ///< Source fitted with a double psf
    46     PM_SOURCE_MODE_PSFSTAR          = 0x00000040, ///< Source used to define PSF model
    47     PM_SOURCE_MODE_SATSTAR          = 0x00000080, ///< Source model peak is above saturation
    48     PM_SOURCE_MODE_BLEND            = 0x00000100, ///< Source is a blend with other sourcers
    49     PM_SOURCE_MODE_EXTERNAL         = 0x00000200, ///< Source based on supplied input position
    50     PM_SOURCE_MODE_BADPSF           = 0x00000400, ///< Failed to get good estimate of object's PSF
    51     PM_SOURCE_MODE_DEFECT           = 0x00000800, ///< Source is thought to be a defect
    52     PM_SOURCE_MODE_SATURATED        = 0x00001000, ///< Source is thought to be saturated pixels (bleed trail)
    53     PM_SOURCE_MODE_CR_LIMIT         = 0x00002000, ///< Source has crNsigma above limit
    54     PM_SOURCE_MODE_EXT_LIMIT        = 0x00004000, ///< Source has extNsigma above limit
     39    PM_SOURCE_MODE_DEFAULT          = 0x00000000, ///< Initial value: resets all bits
     40    PM_SOURCE_MODE_PSFMODEL         = 0x00000001, ///< Source fitted with a psf model (linear or non-linear)
     41    PM_SOURCE_MODE_EXTMODEL         = 0x00000002, ///< Source fitted with an extended-source model
     42    PM_SOURCE_MODE_FITTED           = 0x00000004, ///< Source fitted with non-linear model (PSF or EXT; good or bad)
     43    PM_SOURCE_MODE_FAIL             = 0x00000008, ///< Fit (non-linear) failed (non-converge, off-edge, run to zero)
     44    PM_SOURCE_MODE_POOR             = 0x00000010, ///< Fit succeeds, but low-SN, high-Chisq, or large (for PSF -- drop?)
     45    PM_SOURCE_MODE_PAIR             = 0x00000020, ///< Source fitted with a double psf
     46    PM_SOURCE_MODE_PSFSTAR          = 0x00000040, ///< Source used to define PSF model
     47    PM_SOURCE_MODE_SATSTAR          = 0x00000080, ///< Source model peak is above saturation
     48    PM_SOURCE_MODE_BLEND            = 0x00000100, ///< Source is a blend with other sourcers
     49    PM_SOURCE_MODE_EXTERNAL         = 0x00000200, ///< Source based on supplied input position
     50    PM_SOURCE_MODE_BADPSF           = 0x00000400, ///< Failed to get good estimate of object's PSF
     51    PM_SOURCE_MODE_DEFECT           = 0x00000800, ///< Source is thought to be a defect
     52    PM_SOURCE_MODE_SATURATED        = 0x00001000, ///< Source is thought to be saturated pixels (bleed trail)
     53    PM_SOURCE_MODE_CR_LIMIT         = 0x00002000, ///< Source has crNsigma above limit
     54    PM_SOURCE_MODE_EXT_LIMIT        = 0x00004000, ///< Source has extNsigma above limit
    5555    PM_SOURCE_MODE_MOMENTS_FAILURE  = 0x00008000, ///< could not measure the moments
    5656    PM_SOURCE_MODE_SKY_FAILURE      = 0x00010000, ///< could not measure the local sky
     
    101101    pmSourceType type;                  ///< Best identification of object.
    102102    pmSourceMode mode;                  ///< analysis flags set for object.
    103     pmSourceTmpF tmpFlags;              ///< internal-only flags
     103    pmSourceTmpF tmpFlags;              ///< internal-only flags
    104104    psArray *blends;                    ///< collection of sources thought to be confused with object
    105105    float psfMag;                       ///< calculated from flux in modelPSF
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceFitModel.c

    r21536 r23197  
    66 *  @author GLG, MHPCC
    77 *
    8  *  @version $Revision: 1.30.4.1 $ $Name: not supported by cvs2svn $
    9  *  @date $Date: 2009-02-19 17:59:50 $
     8 *  @version $Revision: 1.31 $ $Name: not supported by cvs2svn $
     9 *  @date $Date: 2009-02-16 22:29:09 $
    1010 *
    1111 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceIO.c

    r21536 r23197  
    33 *  @author EAM, IfA
    44 *
    5  *  @version $Revision: 1.69.14.1 $ $Name: not supported by cvs2svn $
    6  *  @date $Date: 2009-02-19 17:59:50 $
     5 *  @version $Revision: 1.70 $ $Name: not supported by cvs2svn $
     6 *  @date $Date: 2009-02-16 22:30:50 $
    77 *
    88 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    2929#include "pmFPAfile.h"
    3030#include "pmFPAfileFitsIO.h"
    31 #include "pmConcepts.h"
     31#include "pmConceptsRead.h"
    3232
    3333#include "pmSpan.h"
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceIO.h

    r21536 r23197  
    44 * @author EAM, IfA; GLG, MHPCC
    55 *
    6  * @version $Revision: 1.19.16.1 $ $Name: not supported by cvs2svn $
    7  * @date $Date: 2009-02-19 17:59:50 $
     6 * @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
     7 * @date $Date: 2009-02-16 22:30:50 $
    88 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
    99 *
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceIO_CMF_PS1_V1.c

    r21536 r23197  
    33 *  @author EAM, IfA
    44 *
    5  *  @version $Revision: 1.3.2.2 $ $Name: not supported by cvs2svn $
    6  *  @date $Date: 2009-02-19 17:59:50 $
     5 *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
     6 *  @date $Date: 2009-02-18 02:44:19 $
    77 *
    88 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    4545// followed by a zero-size matrix, followed by the table data
    4646
    47 bool pmSourcesWrite_CMF_PS1_V1 (psFits *fits, pmReadout *readout, psArray *sources, 
    48                                 psMetadata *imageHeader, psMetadata *tableHeader, char *extname)
     47bool pmSourcesWrite_CMF_PS1_V1 (psFits *fits, pmReadout *readout, psArray *sources,
     48                                psMetadata *imageHeader, psMetadata *tableHeader, char *extname)
    4949{
    5050    PS_ASSERT_PTR_NON_NULL(fits, false);
     
    7272    float zeroptErr = psMetadataLookupF32 (&status2, imageHeader, "ZPT_ERR");
    7373    if (status1 && status2 && (exptime > 0.0)) {
    74         magOffset = zeropt + 2.5*log10(exptime);
     74        magOffset = zeropt + 2.5*log10(exptime);
    7575    }
    7676
     
    7979    if (sources->n > 0) {
    8080        pmSource *source = (pmSource *) sources->data[0];
    81         if (source->seq == -1) {
    82           // let's write these out in S/N order
    83           sources = psArraySort (sources, pmSourceSortBySN);
    84         } else {
    85           sources = psArraySort (sources, pmSourceSortBySeq);
    86         }
     81        if (source->seq == -1) {
     82          // let's write these out in S/N order
     83          sources = psArraySort (sources, pmSourceSortBySN);
     84        } else {
     85          sources = psArraySort (sources, pmSourceSortBySeq);
     86        }
    8787    }
    8888
     
    9494        pmSource *source = (pmSource *) sources->data[i];
    9595
    96         // If source->seq is -1, source was generated in this analysis.  If source->seq is
    97         // not -1, source was read from elsewhere: in the latter case, preserve the source
    98         // ID.  source.seq is used instead of source.id since the latter is a const
    99         // generated on Alloc, and would thus be wrong for read in sources.
    100         if (source->seq == -1) {
    101           source->seq = i;
    102         }
     96        // If source->seq is -1, source was generated in this analysis.  If source->seq is
     97        // not -1, source was read from elsewhere: in the latter case, preserve the source
     98        // ID.  source.seq is used instead of source.id since the latter is a const
     99        // generated on Alloc, and would thus be wrong for read in sources.
     100        if (source->seq == -1) {
     101          source->seq = i;
     102        }
    103103
    104104        // no difference between PSF and non-PSF model
     
    110110            xPos = PAR[PM_PAR_XPOS];
    111111            yPos = PAR[PM_PAR_YPOS];
    112             if (source->mode & PM_SOURCE_MODE_NONLINEAR_FIT) {
    113               xErr = dPAR[PM_PAR_XPOS];
    114               yErr = dPAR[PM_PAR_YPOS];
    115             } else {
    116               // in linear-fit mode, there is no error on the centroid
    117               xErr = source->peak->dx;
    118               yErr = source->peak->dy;
    119             }         
    120             if (isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX])) {
    121                 axes = pmPSF_ModelToAxes (PAR, 20.0);
    122             } else {
    123                 axes.major = NAN;
    124                 axes.minor = NAN;
    125                 axes.theta = NAN;
    126             }
    127             chisq = model->chisq;
    128             nDOF = model->nDOF;
    129             nPix = model->nPix;
    130             apRadius = model->radiusFit; // XXX should we really use the fitRadius for aperture Radius?
    131             errMag = model->dparams->data.F32[PM_PAR_I0] / model->params->data.F32[PM_PAR_I0];
     112            if (source->mode & PM_SOURCE_MODE_NONLINEAR_FIT) {
     113              xErr = dPAR[PM_PAR_XPOS];
     114              yErr = dPAR[PM_PAR_YPOS];
     115            } else {
     116              // in linear-fit mode, there is no error on the centroid
     117              xErr = source->peak->dx;
     118              yErr = source->peak->dy;
     119            }
     120            if (isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX])) {
     121                axes = pmPSF_ModelToAxes (PAR, 20.0);
     122            } else {
     123                axes.major = NAN;
     124                axes.minor = NAN;
     125                axes.theta = NAN;
     126            }
     127            chisq = model->chisq;
     128            nDOF = model->nDOF;
     129            nPix = model->nPix;
     130            apRadius = model->radiusFit; // XXX should we really use the fitRadius for aperture Radius?
     131            errMag = model->dparams->data.F32[PM_PAR_I0] / model->params->data.F32[PM_PAR_I0];
    132132        } else {
    133133            xPos = source->peak->xf;
     
    138138            axes.minor = NAN;
    139139            axes.theta = NAN;
    140             chisq = NAN;
    141             nDOF = 0;
    142             nPix = 0;
    143             apRadius = NAN;
    144             errMag = NAN;
    145         }
    146 
    147         float calMag = isfinite(magOffset) ? source->psfMag + magOffset : NAN;
     140            chisq = NAN;
     141            nDOF = 0;
     142            nPix = 0;
     143            apRadius = NAN;
     144            errMag = NAN;
     145        }
     146
     147        float calMag = isfinite(magOffset) ? source->psfMag + magOffset : NAN;
    148148        float peakMag = (source->peak->flux > 0) ? -2.5*log10(source->peak->flux) : NAN;
    149149        psS16 nImageOverlap = 1;
    150150
    151         psSphere ptSky = {0.0, 0.0, 0.0, 0.0};
    152         float posAngle = 0.0;
    153         float pltScale = 0.0;
    154         pmSourceLocalAstrometry (&ptSky, &posAngle, &pltScale, chip, xPos, yPos);
     151        psSphere ptSky = {0.0, 0.0, 0.0, 0.0};
     152        float posAngle = 0.0;
     153        float pltScale = 0.0;
     154        pmSourceLocalAstrometry (&ptSky, &posAngle, &pltScale, chip, xPos, yPos);
    155155
    156156        row = psMetadataAlloc ();
     
    185185        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NPIX",         PS_DATA_S32, "number of pixels in fit",                    nPix);
    186186
    187         // distinguish moments measure from window vs S/N > XX ??
    188         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XX",       PS_DATA_F32, "second moments (X^2)",                      source->moments->Mxx);
    189         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XY",       PS_DATA_F32, "second moments (X*Y)",                      source->moments->Mxy);
    190         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_YY",       PS_DATA_F32, "second moments (Y*Y)",                      source->moments->Myy);
     187        // distinguish moments measure from window vs S/N > XX ??
     188        float mxx = source->moments ? source->moments->Mxx : NAN;
     189        float mxy = source->moments ? source->moments->Mxy : NAN;
     190        float myy = source->moments ? source->moments->Myy : NAN;
     191        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XX",       PS_DATA_F32, "second moments (X^2)",                      mxx);
     192        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XY",       PS_DATA_F32, "second moments (X*Y)",                      mxy);
     193        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_YY",       PS_DATA_F32, "second moments (Y*Y)",                      myy);
    191194
    192195        psMetadataAdd (row, PS_LIST_TAIL, "FLAGS",            PS_DATA_U32, "psphot analysis flags",                      source->mode);
     
    199202        psFree (row);
    200203
    201         // EXT_NSIGMA will be NAN if: 1) contour ellipse is imaginary; 2) source is not
    202         // subtracted
    203 
    204         // CR_NSIGMA will be NAN if: 1) source is not subtracted; 2) source is on the image
    205         // edge; 3) any pixels in the 3x3 peak region are masked;
     204        // EXT_NSIGMA will be NAN if: 1) contour ellipse is imaginary; 2) source is not
     205        // subtracted
     206
     207        // CR_NSIGMA will be NAN if: 1) source is not subtracted; 2) source is on the image
     208        // edge; 3) any pixels in the 3x3 peak region are masked;
    206209    }
    207210
     
    281284        source->apMag     = psMetadataLookupF32 (&status, row, "AP_MAG");
    282285
    283         // XXX this scaling is incorrect: does not include the 2 \pi AREA factor
    284         PAR[PM_PAR_I0]    = (isfinite(source->psfMag)) ? pow(10.0, -0.4*source->psfMag) : NAN;
    285         dPAR[PM_PAR_I0]   = (isfinite(source->psfMag)) ? PAR[PM_PAR_I0] * source->errMag : NAN;
     286        // XXX this scaling is incorrect: does not include the 2 \pi AREA factor
     287        PAR[PM_PAR_I0]    = (isfinite(source->psfMag)) ? pow(10.0, -0.4*source->psfMag) : NAN;
     288        dPAR[PM_PAR_I0]   = (isfinite(source->psfMag)) ? PAR[PM_PAR_I0] * source->errMag : NAN;
    286289
    287290        pmPSF_AxesToModel (PAR, axes);
     
    290293        float peakFlux    = (isfinite(peakMag)) ? pow(10.0, -0.4*peakMag) : NAN;
    291294
    292         // recreate the peak to match (xPos, yPos) +/- (xErr, yErr)
     295        // recreate the peak to match (xPos, yPos) +/- (xErr, yErr)
    293296        source->peak = pmPeakAlloc(PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], peakFlux, PM_PEAK_LONE);
    294297        source->peak->flux = peakFlux;
     
    300303        source->extNsigma = psMetadataLookupF32 (&status, row, "EXT_NSIGMA");
    301304
    302         // note that some older versions used PSF_PROBABILITY: this was not well defined.
    303         model->chisq      = psMetadataLookupF32 (&status, row, "PSF_CHISQ");
    304         model->nDOF       = psMetadataLookupS32 (&status, row, "PSF_NDOF");
    305         model->nPix       = psMetadataLookupS32 (&status, row, "PSF_NPIX");
     305        // note that some older versions used PSF_PROBABILITY: this was not well defined.
     306        model->chisq      = psMetadataLookupF32 (&status, row, "PSF_CHISQ");
     307        model->nDOF       = psMetadataLookupS32 (&status, row, "PSF_NDOF");
     308        model->nPix       = psMetadataLookupS32 (&status, row, "PSF_NPIX");
    306309        model->radiusFit  = psMetadataLookupS32 (&status, row, "AP_MAG_RADIUS");
    307310
    308         source->moments = pmMomentsAlloc ();
     311        source->moments = pmMomentsAlloc ();
    309312        source->moments->Mxx = psMetadataLookupF32 (&status, row, "MOMENTS_XX");
    310313        source->moments->Mxy = psMetadataLookupF32 (&status, row, "MOMENTS_XY");
     
    321324}
    322325
    323 // XXX this layout is still the same as PS1_DEV_1 
     326// XXX this layout is still the same as PS1_DEV_1
    324327bool pmSourcesWrite_CMF_PS1_V1_XSRC (psFits *fits, psArray *sources, char *extname, psMetadata *recipe)
    325328{
     
    355358    // we write out all sources, regardless of quality.  the source flags tell us the state
    356359    for (int i = 0; i < sources->n; i++) {
    357         // skip source if it is not a ext sourc
    358         // XXX we have two places that extended source parameters are measured:
    359         // psphotExtendedSources, which measures the aperture-like parameters and (potentially) the psf-convolved extended source models,
    360         // psphotFitEXT, which does the simple extended source model fit (not psf-convolved)
    361         // should we require both?
    362 
    363         pmSource *source = sources->data[i];
    364 
    365         // skip sources without measurements
    366         if (source->extpars == NULL) continue;
    367 
    368         // we require a PSF model fit (ignore the real crud)
    369         pmModel *model = source->modelPSF;
    370         if (model == NULL) continue;
    371 
    372         // XXX I need to split the extended models from the extended aperture measurements
    373         PAR = model->params->data.F32;
    374         dPAR = model->dparams->data.F32;
    375         xPos = PAR[PM_PAR_XPOS];
    376         yPos = PAR[PM_PAR_YPOS];
    377         xErr = dPAR[PM_PAR_XPOS];
    378         yErr = dPAR[PM_PAR_YPOS];
     360        // skip source if it is not a ext sourc
     361        // XXX we have two places that extended source parameters are measured:
     362        // psphotExtendedSources, which measures the aperture-like parameters and (potentially) the psf-convolved extended source models,
     363        // psphotFitEXT, which does the simple extended source model fit (not psf-convolved)
     364        // should we require both?
     365
     366        pmSource *source = sources->data[i];
     367
     368        // skip sources without measurements
     369        if (source->extpars == NULL) continue;
     370
     371        // we require a PSF model fit (ignore the real crud)
     372        pmModel *model = source->modelPSF;
     373        if (model == NULL) continue;
     374
     375        // XXX I need to split the extended models from the extended aperture measurements
     376        PAR = model->params->data.F32;
     377        dPAR = model->dparams->data.F32;
     378        xPos = PAR[PM_PAR_XPOS];
     379        yPos = PAR[PM_PAR_YPOS];
     380        xErr = dPAR[PM_PAR_XPOS];
     381        yErr = dPAR[PM_PAR_YPOS];
    379382
    380383        row = psMetadataAlloc ();
     
    387390        psMetadataAdd (row, PS_LIST_TAIL, "Y_EXT_SIG",        PS_DATA_F32, "Sigma in EXT y coordinate",                  yErr);
    388391
    389         // Petrosian measurements
    390         // XXX insert header data: petrosian ref radius, flux ratio
    391         if (doPetrosian) {
    392             pmSourcePetrosianValues *petrosian = source->extpars->petrosian;
    393             if (petrosian) {
    394                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG",        PS_DATA_F32, "Petrosian Magnitude",       petrosian->mag);
    395                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_ERR",    PS_DATA_F32, "Petrosian Magnitude Error", petrosian->magErr);
    396                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS",     PS_DATA_F32, "Petrosian Radius",          petrosian->rad);
    397                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_ERR", PS_DATA_F32, "Petrosian Radius Error",    petrosian->radErr);
    398             } else {
    399                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG",        PS_DATA_F32, "Petrosian Magnitude",       NAN);
    400                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_ERR",    PS_DATA_F32, "Petrosian Magnitude Error", NAN);
    401                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS",     PS_DATA_F32, "Petrosian Radius",          NAN);
    402                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_ERR", PS_DATA_F32, "Petrosian Radius Error",    NAN);
    403             }
    404         }
    405 
    406         // Kron measurements
    407         if (doKron) {
    408             pmSourceKronValues *kron = source->extpars->kron;
    409             if (kron) {
    410                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG",        PS_DATA_F32, "Kron Magnitude",       kron->mag);
    411                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG_ERR",    PS_DATA_F32, "Kron Magnitude Error", kron->magErr);
    412                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS",     PS_DATA_F32, "Kron Radius",          kron->rad);
    413                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS_ERR", PS_DATA_F32, "Kron Radius Error",    kron->radErr);
    414             } else {
    415                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG",        PS_DATA_F32, "Kron Magnitude",       NAN);
    416                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG_ERR",    PS_DATA_F32, "Kron Magnitude Error", NAN);
    417                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS",     PS_DATA_F32, "Kron Radius",          NAN);
    418                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS_ERR", PS_DATA_F32, "Kron Radius Error",    NAN);
    419             }
    420         }
    421 
    422         // Isophot measurements
    423         // XXX insert header data: isophotal level
    424         if (doIsophotal) {
    425             pmSourceIsophotalValues *isophot = source->extpars->isophot;
    426             if (isophot) {
    427                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG",        PS_DATA_F32, "Isophot Magnitude",       isophot->mag);
    428                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG_ERR",    PS_DATA_F32, "Isophot Magnitude Error", isophot->magErr);
    429                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS",     PS_DATA_F32, "Isophot Radius",          isophot->rad);
    430                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS_ERR", PS_DATA_F32, "Isophot Radius Error",    isophot->radErr);
    431             } else {
    432                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG",        PS_DATA_F32, "Isophot Magnitude",       NAN);
    433                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG_ERR",    PS_DATA_F32, "Isophot Magnitude Error", NAN);
    434                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS",     PS_DATA_F32, "Isophot Radius",          NAN);
    435                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS_ERR", PS_DATA_F32, "Isophot Radius Error",    NAN);
    436             }
    437         }
    438 
    439         // Flux Annuli
    440         if (doAnnuli) {
    441             pmSourceAnnuli *annuli = source->extpars->annuli;
    442             if (annuli) {
    443                 psVector *fluxVal = annuli->flux;
    444                 psVector *fluxErr = annuli->fluxErr;
    445                 psVector *fluxVar = annuli->fluxVar;
    446 
    447                 for (int j = 0; j < fluxVal->n; j++) {
    448                     char name[32];
    449                     sprintf (name, "FLUX_VAL_R_%02d", j);
    450                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux value in annulus", fluxVal->data.F32[j]);
    451                     sprintf (name, "FLUX_ERR_R_%02d", j);
    452                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux error in annulus", fluxErr->data.F32[j]);
    453                     sprintf (name, "FLUX_VAR_R_%02d", j);
    454                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux stdev in annulus", fluxVar->data.F32[j]);
    455                 }
    456             } else {
    457                 for (int j = 0; j < radialBinsLower->n; j++) {
    458                     char name[32];
    459                     sprintf (name, "FLUX_VAL_R_%02d", j);
    460                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux value in annulus", NAN);
    461                     sprintf (name, "FLUX_ERR_R_%02d", j);
    462                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux error in annulus", NAN);
    463                     sprintf (name, "FLUX_VAR_R_%02d", j);
    464                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux stdev in annulus", NAN);
    465                 }
    466             }
    467         }
    468 
    469         psArrayAdd (table, 100, row);
    470         psFree (row);
     392        // Petrosian measurements
     393        // XXX insert header data: petrosian ref radius, flux ratio
     394        if (doPetrosian) {
     395            pmSourcePetrosianValues *petrosian = source->extpars->petrosian;
     396            if (petrosian) {
     397                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG",        PS_DATA_F32, "Petrosian Magnitude",       petrosian->mag);
     398                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_ERR",    PS_DATA_F32, "Petrosian Magnitude Error", petrosian->magErr);
     399                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS",     PS_DATA_F32, "Petrosian Radius",          petrosian->rad);
     400                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_ERR", PS_DATA_F32, "Petrosian Radius Error",    petrosian->radErr);
     401            } else {
     402                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG",        PS_DATA_F32, "Petrosian Magnitude",       NAN);
     403                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_ERR",    PS_DATA_F32, "Petrosian Magnitude Error", NAN);
     404                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS",     PS_DATA_F32, "Petrosian Radius",          NAN);
     405                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_ERR", PS_DATA_F32, "Petrosian Radius Error",    NAN);
     406            }
     407        }
     408
     409        // Kron measurements
     410        if (doKron) {
     411            pmSourceKronValues *kron = source->extpars->kron;
     412            if (kron) {
     413                psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG",        PS_DATA_F32, "Kron Magnitude",       kron->mag);
     414                psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG_ERR",    PS_DATA_F32, "Kron Magnitude Error", kron->magErr);
     415                psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS",     PS_DATA_F32, "Kron Radius",          kron->rad);
     416                psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS_ERR", PS_DATA_F32, "Kron Radius Error",    kron->radErr);
     417            } else {
     418                psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG",        PS_DATA_F32, "Kron Magnitude",       NAN);
     419                psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG_ERR",    PS_DATA_F32, "Kron Magnitude Error", NAN);
     420                psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS",     PS_DATA_F32, "Kron Radius",          NAN);
     421                psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS_ERR", PS_DATA_F32, "Kron Radius Error",    NAN);
     422            }
     423        }
     424
     425        // Isophot measurements
     426        // XXX insert header data: isophotal level
     427        if (doIsophotal) {
     428            pmSourceIsophotalValues *isophot = source->extpars->isophot;
     429            if (isophot) {
     430                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG",        PS_DATA_F32, "Isophot Magnitude",       isophot->mag);
     431                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG_ERR",    PS_DATA_F32, "Isophot Magnitude Error", isophot->magErr);
     432                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS",     PS_DATA_F32, "Isophot Radius",          isophot->rad);
     433                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS_ERR", PS_DATA_F32, "Isophot Radius Error",    isophot->radErr);
     434            } else {
     435                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG",        PS_DATA_F32, "Isophot Magnitude",       NAN);
     436                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG_ERR",    PS_DATA_F32, "Isophot Magnitude Error", NAN);
     437                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS",     PS_DATA_F32, "Isophot Radius",          NAN);
     438                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS_ERR", PS_DATA_F32, "Isophot Radius Error",    NAN);
     439            }
     440        }
     441
     442        // Flux Annuli
     443        if (doAnnuli) {
     444            pmSourceAnnuli *annuli = source->extpars->annuli;
     445            if (annuli) {
     446                psVector *fluxVal = annuli->flux;
     447                psVector *fluxErr = annuli->fluxErr;
     448                psVector *fluxVar = annuli->fluxVar;
     449
     450                for (int j = 0; j < fluxVal->n; j++) {
     451                    char name[32];
     452                    sprintf (name, "FLUX_VAL_R_%02d", j);
     453                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux value in annulus", fluxVal->data.F32[j]);
     454                    sprintf (name, "FLUX_ERR_R_%02d", j);
     455                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux error in annulus", fluxErr->data.F32[j]);
     456                    sprintf (name, "FLUX_VAR_R_%02d", j);
     457                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux stdev in annulus", fluxVar->data.F32[j]);
     458                }
     459            } else {
     460                for (int j = 0; j < radialBinsLower->n; j++) {
     461                    char name[32];
     462                    sprintf (name, "FLUX_VAL_R_%02d", j);
     463                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux value in annulus", NAN);
     464                    sprintf (name, "FLUX_ERR_R_%02d", j);
     465                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux error in annulus", NAN);
     466                    sprintf (name, "FLUX_VAR_R_%02d", j);
     467                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux stdev in annulus", NAN);
     468                }
     469            }
     470        }
     471
     472        psArrayAdd (table, 100, row);
     473        psFree (row);
    471474    }
    472475
    473476    if (table->n == 0) {
    474         psFitsWriteBlank (fits, outhead, extname);
    475         psFree (outhead);
    476         psFree (table);
    477         return true;
     477        psFitsWriteBlank (fits, outhead, extname);
     478        psFree (outhead);
     479        psFree (table);
     480        return true;
    478481    }
    479482
    480483    psTrace ("pmFPAfile", 5, "writing ext data %s\n", extname);
    481484    if (!psFitsWriteTable (fits, outhead, table, extname)) {
    482         psError(PS_ERR_IO, false, "writing ext data %s\n", extname);
    483         psFree (outhead);
    484         psFree(table);
    485         return false;
     485        psError(PS_ERR_IO, false, "writing ext data %s\n", extname);
     486        psFree (outhead);
     487        psFree(table);
     488        return false;
    486489    }
    487490    psFree (outhead);
     
    491494}
    492495
    493 // XXX this layout is still the same as PS1_DEV_1 
     496// XXX this layout is still the same as PS1_DEV_1
    494497bool pmSourcesWrite_CMF_PS1_V1_XFIT (psFits *fits, psArray *sources, char *extname)
    495498{
     
    515518    int nParamMax = 0;
    516519    for (int i = 0; i < sources->n; i++) {
    517         pmSource *source = sources->data[i];
    518         if (source->modelFits == NULL) continue;
    519         for (int j = 0; j < source->modelFits->n; j++) {
    520             pmModel *model = source->modelFits->data[j];
    521             assert (model);
    522             nParamMax = PS_MAX (nParamMax, model->params->n);
    523         }
     520        pmSource *source = sources->data[i];
     521        if (source->modelFits == NULL) continue;
     522        for (int j = 0; j < source->modelFits->n; j++) {
     523            pmModel *model = source->modelFits->data[j];
     524            assert (model);
     525            nParamMax = PS_MAX (nParamMax, model->params->n);
     526        }
    524527    }
    525528
     
    529532    for (int i = 0; i < sources->n; i++) {
    530533
    531         pmSource *source = sources->data[i];
    532 
    533         // XXX if no model fits are saved, write out modelEXT?
    534         if (source->modelFits == NULL) continue;
    535 
    536         // We have multiple sources : need to flag the one used to subtract the light (the 'best' model)
    537         for (int j = 0; j < source->modelFits->n; j++) {
    538 
    539             // choose the convolved EXT model, if available, otherwise the simple one
    540             pmModel *model = source->modelFits->data[j];
    541             assert (model);
    542 
    543             PAR = model->params->data.F32;
    544             dPAR = model->dparams->data.F32;
    545             xPos = PAR[PM_PAR_XPOS];
    546             yPos = PAR[PM_PAR_YPOS];
    547             xErr = dPAR[PM_PAR_XPOS];
    548             yErr = dPAR[PM_PAR_YPOS];
    549 
    550             axes = pmPSF_ModelToAxes (PAR, 20.0);
    551 
    552             row = psMetadataAlloc ();
    553 
    554             // XXX we are not writing out the mode (flags) or the type (psf, ext, etc)
    555             psMetadataAddU32 (row, PS_LIST_TAIL, "IPP_IDET",         0, "IPP detection identifier index",             source->seq);
    556             psMetadataAddF32 (row, PS_LIST_TAIL, "X_EXT",            0, "EXT model x coordinate",                     xPos);
    557             psMetadataAddF32 (row, PS_LIST_TAIL, "Y_EXT",            0, "EXT model y coordinate",                     yPos);
    558             psMetadataAddF32 (row, PS_LIST_TAIL, "X_EXT_SIG",        0, "Sigma in EXT x coordinate",                  xErr);
    559             psMetadataAddF32 (row, PS_LIST_TAIL, "Y_EXT_SIG",        0, "Sigma in EXT y coordinate",                  yErr);
    560             psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_INST_MAG",     0, "EXT fit instrumental magnitude",             model->mag);
    561             psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_INST_MAG_SIG", 0, "Sigma of PSF instrumental magnitude",        model->magErr);
    562 
    563             psMetadataAddF32 (row, PS_LIST_TAIL, "NPARAMS",          0, "number of model parameters",                 model->params->n);
    564             psMetadataAddStr (row, PS_LIST_TAIL, "MODEL_TYPE",       0, "name of model",                              pmModelClassGetName (model->type));
    565 
    566             // XXX these should be major and minor, not 'x' and 'y'
    567             psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_WIDTH_MAJ",    0, "EXT width in x coordinate",                  axes.major);
    568             psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_WIDTH_MIN",    0, "EXT width in y coordinate",                  axes.minor);
    569             psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_THETA",        0, "EXT orientation angle",                      axes.theta);
    570 
    571             // write out the other generic parameters
    572             for (int k = 0; k < nParamMax; k++) {
    573                 if (k == PM_PAR_I0) continue;
    574                 if (k == PM_PAR_SKY) continue;
    575                 if (k == PM_PAR_XPOS) continue;
    576                 if (k == PM_PAR_YPOS) continue;
    577                 if (k == PM_PAR_SXX) continue;
    578                 if (k == PM_PAR_SXY) continue;
    579                 if (k == PM_PAR_SYY) continue;
    580 
    581                 snprintf (name, 64, "EXT_PAR_%02d", k);
    582 
    583                 if (k < model->params->n) {
    584                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "", model->params->data.F32[k]);
    585                 } else {
    586                     psMetadataAddF32 (row, PS_LIST_TAIL, name, PS_DATA_F32, "", NAN);
    587                 }
    588             }
    589 
    590             // XXX other parameters which may be set.
    591             // XXX flag / value to define the model
    592             // XXX write out the model type, fit status flags
    593 
    594             psArrayAdd (table, 100, row);
    595             psFree (row);
    596         }
     534        pmSource *source = sources->data[i];
     535
     536        // XXX if no model fits are saved, write out modelEXT?
     537        if (source->modelFits == NULL) continue;
     538
     539        // We have multiple sources : need to flag the one used to subtract the light (the 'best' model)
     540        for (int j = 0; j < source->modelFits->n; j++) {
     541
     542            // choose the convolved EXT model, if available, otherwise the simple one
     543            pmModel *model = source->modelFits->data[j];
     544            assert (model);
     545
     546            PAR = model->params->data.F32;
     547            dPAR = model->dparams->data.F32;
     548            xPos = PAR[PM_PAR_XPOS];
     549            yPos = PAR[PM_PAR_YPOS];
     550            xErr = dPAR[PM_PAR_XPOS];
     551            yErr = dPAR[PM_PAR_YPOS];
     552
     553            axes = pmPSF_ModelToAxes (PAR, 20.0);
     554
     555            row = psMetadataAlloc ();
     556
     557            // XXX we are not writing out the mode (flags) or the type (psf, ext, etc)
     558            psMetadataAddU32 (row, PS_LIST_TAIL, "IPP_IDET",         0, "IPP detection identifier index",             source->seq);
     559            psMetadataAddF32 (row, PS_LIST_TAIL, "X_EXT",            0, "EXT model x coordinate",                     xPos);
     560            psMetadataAddF32 (row, PS_LIST_TAIL, "Y_EXT",            0, "EXT model y coordinate",                     yPos);
     561            psMetadataAddF32 (row, PS_LIST_TAIL, "X_EXT_SIG",        0, "Sigma in EXT x coordinate",                  xErr);
     562            psMetadataAddF32 (row, PS_LIST_TAIL, "Y_EXT_SIG",        0, "Sigma in EXT y coordinate",                  yErr);
     563            psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_INST_MAG",     0, "EXT fit instrumental magnitude",             model->mag);
     564            psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_INST_MAG_SIG", 0, "Sigma of PSF instrumental magnitude",        model->magErr);
     565
     566            psMetadataAddF32 (row, PS_LIST_TAIL, "NPARAMS",          0, "number of model parameters",                 model->params->n);
     567            psMetadataAddStr (row, PS_LIST_TAIL, "MODEL_TYPE",       0, "name of model",                              pmModelClassGetName (model->type));
     568
     569            // XXX these should be major and minor, not 'x' and 'y'
     570            psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_WIDTH_MAJ",    0, "EXT width in x coordinate",                  axes.major);
     571            psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_WIDTH_MIN",    0, "EXT width in y coordinate",                  axes.minor);
     572            psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_THETA",        0, "EXT orientation angle",                      axes.theta);
     573
     574            // write out the other generic parameters
     575            for (int k = 0; k < nParamMax; k++) {
     576                if (k == PM_PAR_I0) continue;
     577                if (k == PM_PAR_SKY) continue;
     578                if (k == PM_PAR_XPOS) continue;
     579                if (k == PM_PAR_YPOS) continue;
     580                if (k == PM_PAR_SXX) continue;
     581                if (k == PM_PAR_SXY) continue;
     582                if (k == PM_PAR_SYY) continue;
     583
     584                snprintf (name, 64, "EXT_PAR_%02d", k);
     585
     586                if (k < model->params->n) {
     587                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "", model->params->data.F32[k]);
     588                } else {
     589                    psMetadataAddF32 (row, PS_LIST_TAIL, name, PS_DATA_F32, "", NAN);
     590                }
     591            }
     592
     593            // XXX other parameters which may be set.
     594            // XXX flag / value to define the model
     595            // XXX write out the model type, fit status flags
     596
     597            psArrayAdd (table, 100, row);
     598            psFree (row);
     599        }
    597600    }
    598601
    599602    if (table->n == 0) {
    600         psFitsWriteBlank (fits, outhead, extname);
    601         psFree (outhead);
    602         psFree (table);
    603         return true;
     603        psFitsWriteBlank (fits, outhead, extname);
     604        psFree (outhead);
     605        psFree (table);
     606        return true;
    604607    }
    605608
    606609    psTrace ("pmFPAfile", 5, "writing ext data %s\n", extname);
    607610    if (!psFitsWriteTable (fits, outhead, table, extname)) {
    608         psError(PS_ERR_IO, false, "writing ext data %s\n", extname);
    609         psFree (outhead);
    610         psFree(table);
    611         return false;
     611        psError(PS_ERR_IO, false, "writing ext data %s\n", extname);
     612        psFree (outhead);
     613        psFree(table);
     614        return false;
    612615    }
    613616    psFree (outhead);
     
    645648    psPlaneTransformApply (&ptFP, chip->toFPA, &ptCH);
    646649    psPlaneTransformApply (&ptTP_y, fpa->toTPA, &ptFP);
    647    
     650
    648651    // the resulting Tangent Plane coordinates are in TP pixels; convert to local Tangent Plane
    649652    // degrees
     
    671674    *posAngle = NAN;
    672675    *pltScale = NAN;
    673    
     676
    674677    return false;
    675678}
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceIO_PS1_CAL_0.c

    r21536 r23197  
    33 *  @author EAM, IfA
    44 *
    5  *  @version $Revision: 1.2.14.1 $ $Name: not supported by cvs2svn $
    6  *  @date $Date: 2009-02-19 17:59:50 $
     5 *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
     6 *  @date $Date: 2009-02-16 22:30:50 $
    77 *
    88 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    4949// XXX how do I generate the source tables which I need to send to PSPS?
    5050
    51 bool pmSourcesWrite_PS1_CAL_0 (psFits *fits, pmReadout *readout, psArray *sources,
    52                                psMetadata *imageHeader, psMetadata *tableHeader, char *extname)
     51bool pmSourcesWrite_PS1_CAL_0 (psFits *fits, pmReadout *readout, psArray *sources, 
     52                               psMetadata *imageHeader, psMetadata *tableHeader, char *extname)
    5353{
    5454    PS_ASSERT_PTR_NON_NULL(fits, false);
     
    6868    pmFPA  *fpa  = chip->parent;
    6969    if (!chip->toFPA || !fpa->toTPA || !fpa->toSky) {
    70         psWarning ("astrometry calibration is missing, no calibrated coords");
     70        psWarning ("astrometry calibration is missing, no calibrated coords");
    7171    }
    7272
     
    7777    float zeropt  = psMetadataLookupF32 (&status2, imageHeader, "ZPT_OBS");
    7878    if (!status1 || !status2 || (exptime == 0.0)) {
    79         psWarning ("exposure time or measured zero point not found for a readout, no calibrated mags");
     79        psWarning ("exposure time or measured zero point not found for a readout, no calibrated mags");
    8080    } else {
    81         magOffset = zeropt + 2.5*log10(exptime);
     81        magOffset = zeropt + 2.5*log10(exptime);
    8282    }
    8383
     
    9090    for (i = 0; i < sources->n; i++) {
    9191        pmSource *source = (pmSource *) sources->data[i];
    92         if (source->seq == -1) {
    93             source->seq = i;
    94         }
     92        if (source->seq == -1) {
     93            source->seq = i;
     94        }
    9595
    9696        // no difference between PSF and non-PSF model
     
    104104            xErr = dPAR[PM_PAR_XPOS];
    105105            yErr = dPAR[PM_PAR_YPOS];
    106             if (isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX])) {
    107                 axes = pmPSF_ModelToAxes (PAR, 20.0);
    108             } else {
    109                 axes.major = NAN;
    110                 axes.minor = NAN;
    111                 axes.theta = NAN;
    112             }
    113             chisq = model->chisq;
    114 
    115             // need to determine the PSF photometry error: source->errMag is the error on the 'best' model mag.
    116             errMag = model->dparams->data.F32[PM_PAR_I0] / model->params->data.F32[PM_PAR_I0];
     106            if (isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX])) {
     107                axes = pmPSF_ModelToAxes (PAR, 20.0);
     108            } else {
     109                axes.major = NAN;
     110                axes.minor = NAN;
     111                axes.theta = NAN;
     112            }
     113            chisq = model->chisq;
     114
     115            // need to determine the PSF photometry error: source->errMag is the error on the 'best' model mag.
     116            errMag = model->dparams->data.F32[PM_PAR_I0] / model->params->data.F32[PM_PAR_I0];
    117117        } else {
    118118            xPos = source->peak->xf;
     
    123123            axes.minor = NAN;
    124124            axes.theta = NAN;
    125             chisq = NAN;
    126             errMag = NAN;
     125            chisq = NAN;
     126            errMag = NAN;
    127127        }
    128128
    129         float calMag = source->psfMag + magOffset;
     129        float calMag = source->psfMag + magOffset;
    130130        float peakMag = (source->peak->flux > 0) ? -2.5*log10(source->peak->flux) : NAN;
    131131        psS16 nImageOverlap = 1;
    132132
    133         // generate RA,DEC
    134         psPlane ptCH, ptFP, ptTP;
    135         psSphere ptSky;
    136 
    137         ptCH.x = xPos;
    138         ptCH.y = yPos;
    139         if (chip->toFPA && fpa->toTPA && fpa->toSky) {
    140             psPlaneTransformApply (&ptFP, chip->toFPA, &ptCH);
    141             psPlaneTransformApply (&ptTP, fpa->toTPA, &ptFP);
    142             psDeproject (&ptSky, &ptTP, fpa->toSky);
    143         } else {
    144             ptSky.r = NAN;
    145             ptSky.d = NAN;
    146         }
     133        // generate RA,DEC
     134        psPlane ptCH, ptFP, ptTP;
     135        psSphere ptSky;
     136
     137        ptCH.x = xPos;
     138        ptCH.y = yPos;
     139        if (chip->toFPA && fpa->toTPA && fpa->toSky) {
     140            psPlaneTransformApply (&ptFP, chip->toFPA, &ptCH);
     141            psPlaneTransformApply (&ptTP, fpa->toTPA, &ptFP);
     142            psDeproject (&ptSky, &ptTP, fpa->toSky);
     143        } else {
     144            ptSky.r = NAN;
     145            ptSky.d = NAN;
     146        }
    147147
    148148        row = psMetadataAlloc ();
     
    150150        psMetadataAdd (row, PS_LIST_TAIL, "RA_PSF",           PS_DATA_F32, "PSF RA coordinate (degrees)",                ptSky.r*PS_DEG_RAD);
    151151        psMetadataAdd (row, PS_LIST_TAIL, "DEC_PSF",          PS_DATA_F32, "PSF DEC coordinate (degrees)",               ptSky.d*PS_DEG_RAD);
    152         // XXX need to do the error propagation correctly..
     152        // XXX need to do the error propagation correctly..
    153153        // psMetadataAdd (row, PS_LIST_TAIL, "RA_PSF_SIG",       PS_DATA_F32, "Sigma of PSF fit RA",                     dRA);
    154154        // psMetadataAdd (row, PS_LIST_TAIL, "DEC_PSF_SIG",      PS_DATA_F32, "Sigma of PSF fit DEC",                    dDEC);
     
    170170        psMetadataAdd (row, PS_LIST_TAIL, "EXT_NSIGMA",       PS_DATA_F32,  "Nsigma deviations from PSF to EXT",         source->extNsigma);
    171171
    172         // EXT_NSIGMA will be NAN if: 1) contour ellipse is imaginary; 2) source is not
    173         // subtracted
    174 
    175         // CR_NSIGMA will be NAN if: 1) source is not subtracted; 2) source is on the image
    176         // edge; 3) any pixels in the 3x3 peak region are masked;
     172        // EXT_NSIGMA will be NAN if: 1) contour ellipse is imaginary; 2) source is not
     173        // subtracted
     174
     175        // CR_NSIGMA will be NAN if: 1) source is not subtracted; 2) source is on the image
     176        // edge; 3) any pixels in the 3x3 peak region are masked;
    177177
    178178        // XXX these should be major and minor, not 'x' and 'y'
     
    277277        source->psfMag    = psMetadataLookupF32 (&status, row, "PSF_INST_MAG");
    278278        source->errMag    = psMetadataLookupF32 (&status, row, "PSF_INST_MAG_SIG");
    279         PAR[PM_PAR_I0]    = (isfinite(source->psfMag)) ? pow(10.0, -0.4*source->psfMag) : NAN;
    280         dPAR[PM_PAR_I0]   = (isfinite(source->psfMag)) ? PAR[PM_PAR_I0] * source->errMag : NAN;
     279        PAR[PM_PAR_I0]    = (isfinite(source->psfMag)) ? pow(10.0, -0.4*source->psfMag) : NAN;
     280        dPAR[PM_PAR_I0]   = (isfinite(source->psfMag)) ? PAR[PM_PAR_I0] * source->errMag : NAN;
    281281
    282282        pmPSF_AxesToModel (PAR, axes);
     
    289289        source->pixWeight = psMetadataLookupF32 (&status, row, "PSF_QF");
    290290
    291         // note that some older versions used PSF_PROBABILITY: this was not well defined.
     291        // note that some older versions used PSF_PROBABILITY: this was not well defined.
    292292        model->chisq      = psMetadataLookupF32 (&status, row, "PSF_CHISQ");
    293293        source->crNsigma  = psMetadataLookupF32 (&status, row, "CR_NSIGMA");
     
    321321    pmFPA  *fpa  = chip->parent;
    322322    if (!chip->toFPA || !fpa->toTPA || !fpa->toSky) {
    323         psWarning ("astrometry calibration is missing, no calibrated coords");
     323        psWarning ("astrometry calibration is missing, no calibrated coords");
    324324    }
    325325
     
    331331    float zeropt  = psMetadataLookupF32 (&status2, imageHeader, "ZPT_OBS");
    332332    if (!status1 || !status2 || (exptime == 0.0)) {
    333         psWarning ("exposure time or measured zero point not found for a readout, no calibrated mags");
     333        psWarning ("exposure time or measured zero point not found for a readout, no calibrated mags");
    334334    } else {
    335         magOffset = zeropt + 2.5*log10(exptime);
    336         calMags = true;
     335        magOffset = zeropt + 2.5*log10(exptime);
     336        calMags = true;
    337337    }
    338338
     
    360360    // we write out all sources, regardless of quality.  the source flags tell us the state
    361361    for (int i = 0; i < sources->n; i++) {
    362         // skip source if it is not a ext sourc
    363         // XXX we have two places that extended source parameters are measured:
    364         // psphotExtendedSources, which measures the aperture-like parameters and (potentially) the psf-convolved extended source models,
    365         // psphotFitEXT, which does the simple extended source model fit (not psf-convolved)
    366         // should we require both?
    367 
    368         pmSource *source = sources->data[i];
    369 
    370         // skip sources without measurements
    371         if (source->extpars == NULL) continue;
    372 
    373         // we require a PSF model fit (ignore the real crud)
    374         pmModel *model = source->modelPSF;
    375         if (model == NULL) continue;
    376 
    377         // XXX I need to split the extended models from the extended aperture measurements
    378         PAR = model->params->data.F32;
    379         dPAR = model->dparams->data.F32;
    380         xPos = PAR[PM_PAR_XPOS];
    381         yPos = PAR[PM_PAR_YPOS];
    382         xErr = dPAR[PM_PAR_XPOS];
    383         yErr = dPAR[PM_PAR_YPOS];
    384 
    385         // generate RA,DEC
    386         psPlane ptCH, ptFP, ptTP;
    387         psSphere ptSky;
    388 
    389         ptCH.x = xPos;
    390         ptCH.y = yPos;
    391         if (chip->toFPA && fpa->toTPA && fpa->toSky) {
    392             psPlaneTransformApply (&ptFP, chip->toFPA, &ptCH);
    393             psPlaneTransformApply (&ptTP, fpa->toTPA, &ptFP);
    394             psDeproject (&ptSky, &ptTP, fpa->toSky);
    395         } else {
    396             ptSky.r = NAN;
    397             ptSky.d = NAN;
    398         }
     362        // skip source if it is not a ext sourc
     363        // XXX we have two places that extended source parameters are measured:
     364        // psphotExtendedSources, which measures the aperture-like parameters and (potentially) the psf-convolved extended source models,
     365        // psphotFitEXT, which does the simple extended source model fit (not psf-convolved)
     366        // should we require both?
     367
     368        pmSource *source = sources->data[i];
     369
     370        // skip sources without measurements
     371        if (source->extpars == NULL) continue;
     372
     373        // we require a PSF model fit (ignore the real crud)
     374        pmModel *model = source->modelPSF;
     375        if (model == NULL) continue;
     376
     377        // XXX I need to split the extended models from the extended aperture measurements
     378        PAR = model->params->data.F32;
     379        dPAR = model->dparams->data.F32;
     380        xPos = PAR[PM_PAR_XPOS];
     381        yPos = PAR[PM_PAR_YPOS];
     382        xErr = dPAR[PM_PAR_XPOS];
     383        yErr = dPAR[PM_PAR_YPOS];
     384
     385        // generate RA,DEC
     386        psPlane ptCH, ptFP, ptTP;
     387        psSphere ptSky;
     388
     389        ptCH.x = xPos;
     390        ptCH.y = yPos;
     391        if (chip->toFPA && fpa->toTPA && fpa->toSky) {
     392            psPlaneTransformApply (&ptFP, chip->toFPA, &ptCH);
     393            psPlaneTransformApply (&ptTP, fpa->toTPA, &ptFP);
     394            psDeproject (&ptSky, &ptTP, fpa->toSky);
     395        } else {
     396            ptSky.r = NAN;
     397            ptSky.d = NAN;
     398        }
    399399
    400400        row = psMetadataAlloc ();
     
    410410        psMetadataAdd (row, PS_LIST_TAIL, "Y_EXT_SIG",        PS_DATA_F32, "Sigma in EXT y coordinate",                  yErr);
    411411
    412         // Petrosian measurements
    413         // XXX insert header data: petrosian ref radius, flux ratio
    414         if (doPetrosian) {
    415             pmSourcePetrosianValues *petrosian = source->extpars->petrosian;
    416             if (petrosian) {
    417                 if (calMags) {
    418                     psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_CAL",    PS_DATA_F32, "Petrosian Magnitude (calibrated)", petrosian->mag + magOffset);
    419                 } else {
    420                     psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_INST",   PS_DATA_F32, "Petrosian Magnitude (instrumental)", petrosian->mag);
    421                 }
    422                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_ERR",    PS_DATA_F32, "Petrosian Magnitude Error", petrosian->magErr);
    423                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS",     PS_DATA_F32, "Petrosian Radius",          petrosian->rad);
    424                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_ERR", PS_DATA_F32, "Petrosian Radius Error",    petrosian->radErr);
    425             } else {
    426                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG",        PS_DATA_F32, "Petrosian Magnitude",       NAN);
    427                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_ERR",    PS_DATA_F32, "Petrosian Magnitude Error", NAN);
    428                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS",     PS_DATA_F32, "Petrosian Radius",          NAN);
    429                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_ERR", PS_DATA_F32, "Petrosian Radius Error",    NAN);
    430             }
    431         }
    432 
    433         // Kron measurements
    434         if (doKron) {
    435             pmSourceKronValues *kron = source->extpars->kron;
    436             if (kron) {
    437                 if (calMags) {
    438                     psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG_CAL",  PS_DATA_F32, "Kron Magnitude",     kron->mag + magOffset);
    439                 } else {
    440                     psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG_INST", PS_DATA_F32, "Kron Magnitude",     kron->mag);
    441                 }
    442                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG_ERR",    PS_DATA_F32, "Kron Magnitude Error", kron->magErr);
    443                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS",     PS_DATA_F32, "Kron Radius",          kron->rad);
    444                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS_ERR", PS_DATA_F32, "Kron Radius Error",    kron->radErr);
    445             } else {
    446                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG",        PS_DATA_F32, "Kron Magnitude",       NAN);
    447                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG_ERR",    PS_DATA_F32, "Kron Magnitude Error", NAN);
    448                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS",     PS_DATA_F32, "Kron Radius",          NAN);
    449                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS_ERR", PS_DATA_F32, "Kron Radius Error",    NAN);
    450             }
    451         }
    452 
    453         // Isophot measurements
    454         // XXX insert header data: isophotal level
    455         if (doIsophotal) {
    456             pmSourceIsophotalValues *isophot = source->extpars->isophot;
    457             if (isophot) {
    458                 if (calMags) {
    459                     psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG_CAL",    PS_DATA_F32, "Isophot Magnitude (calibrated)",   isophot->mag + magOffset);
    460                 } else {
    461                     psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG_INST",   PS_DATA_F32, "Isophot Magnitude (uncalibrated)", isophot->mag);
    462                 }
    463                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG_ERR",    PS_DATA_F32, "Isophot Magnitude Error", isophot->magErr);
    464                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS",     PS_DATA_F32, "Isophot Radius",          isophot->rad);
    465                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS_ERR", PS_DATA_F32, "Isophot Radius Error",    isophot->radErr);
    466             } else {
    467                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG",        PS_DATA_F32, "Isophot Magnitude",       NAN);
    468                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG_ERR",    PS_DATA_F32, "Isophot Magnitude Error", NAN);
    469                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS",     PS_DATA_F32, "Isophot Radius",          NAN);
    470                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS_ERR", PS_DATA_F32, "Isophot Radius Error",    NAN);
    471             }
    472         }
    473 
    474         // Flux Annuli
    475         if (doAnnuli) {
    476             pmSourceAnnuli *annuli = source->extpars->annuli;
    477             if (annuli) {
    478                 psVector *fluxVal = annuli->flux;
    479                 psVector *fluxErr = annuli->fluxErr;
    480                 psVector *fluxVar = annuli->fluxVar;
    481 
    482                 for (int j = 0; j < fluxVal->n; j++) {
    483                     char name[32];
    484                     sprintf (name, "FLUX_VAL_R_%02d", j);
    485                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux value in annulus", fluxVal->data.F32[j]);
    486                     sprintf (name, "FLUX_ERR_R_%02d", j);
    487                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux error in annulus", fluxErr->data.F32[j]);
    488                     sprintf (name, "FLUX_VAR_R_%02d", j);
    489                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux stdev in annulus", fluxVar->data.F32[j]);
    490                 }
    491             } else {
    492                 for (int j = 0; j < radialBinsLower->n; j++) {
    493                     char name[32];
    494                     sprintf (name, "FLUX_VAL_R_%02d", j);
    495                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux value in annulus", NAN);
    496                     sprintf (name, "FLUX_ERR_R_%02d", j);
    497                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux error in annulus", NAN);
    498                     sprintf (name, "FLUX_VAR_R_%02d", j);
    499                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux stdev in annulus", NAN);
    500                 }
    501             }
    502         }
    503 
    504         psArrayAdd (table, 100, row);
    505         psFree (row);
     412        // Petrosian measurements
     413        // XXX insert header data: petrosian ref radius, flux ratio
     414        if (doPetrosian) {
     415            pmSourcePetrosianValues *petrosian = source->extpars->petrosian;
     416            if (petrosian) {
     417                if (calMags) {
     418                    psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_CAL",    PS_DATA_F32, "Petrosian Magnitude (calibrated)", petrosian->mag + magOffset);
     419                } else {
     420                    psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_INST",   PS_DATA_F32, "Petrosian Magnitude (instrumental)", petrosian->mag);
     421                }
     422                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_ERR",    PS_DATA_F32, "Petrosian Magnitude Error", petrosian->magErr);
     423                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS",     PS_DATA_F32, "Petrosian Radius",          petrosian->rad);
     424                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_ERR", PS_DATA_F32, "Petrosian Radius Error",    petrosian->radErr);
     425            } else {
     426                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG",        PS_DATA_F32, "Petrosian Magnitude",       NAN);
     427                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_ERR",    PS_DATA_F32, "Petrosian Magnitude Error", NAN);
     428                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS",     PS_DATA_F32, "Petrosian Radius",          NAN);
     429                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_ERR", PS_DATA_F32, "Petrosian Radius Error",    NAN);
     430            }
     431        }
     432
     433        // Kron measurements
     434        if (doKron) {
     435            pmSourceKronValues *kron = source->extpars->kron;
     436            if (kron) {
     437                if (calMags) {
     438                    psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG_CAL",  PS_DATA_F32, "Kron Magnitude",     kron->mag + magOffset);
     439                } else {
     440                    psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG_INST", PS_DATA_F32, "Kron Magnitude",     kron->mag);
     441                }
     442                psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG_ERR",    PS_DATA_F32, "Kron Magnitude Error", kron->magErr);
     443                psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS",     PS_DATA_F32, "Kron Radius",          kron->rad);
     444                psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS_ERR", PS_DATA_F32, "Kron Radius Error",    kron->radErr);
     445            } else {
     446                psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG",        PS_DATA_F32, "Kron Magnitude",       NAN);
     447                psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG_ERR",    PS_DATA_F32, "Kron Magnitude Error", NAN);
     448                psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS",     PS_DATA_F32, "Kron Radius",          NAN);
     449                psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS_ERR", PS_DATA_F32, "Kron Radius Error",    NAN);
     450            }
     451        }
     452
     453        // Isophot measurements
     454        // XXX insert header data: isophotal level
     455        if (doIsophotal) {
     456            pmSourceIsophotalValues *isophot = source->extpars->isophot;
     457            if (isophot) {
     458                if (calMags) {
     459                    psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG_CAL",    PS_DATA_F32, "Isophot Magnitude (calibrated)",   isophot->mag + magOffset);
     460                } else {
     461                    psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG_INST",   PS_DATA_F32, "Isophot Magnitude (uncalibrated)", isophot->mag);
     462                }
     463                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG_ERR",    PS_DATA_F32, "Isophot Magnitude Error", isophot->magErr);
     464                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS",     PS_DATA_F32, "Isophot Radius",          isophot->rad);
     465                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS_ERR", PS_DATA_F32, "Isophot Radius Error",    isophot->radErr);
     466            } else {
     467                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG",        PS_DATA_F32, "Isophot Magnitude",       NAN);
     468                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG_ERR",    PS_DATA_F32, "Isophot Magnitude Error", NAN);
     469                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS",     PS_DATA_F32, "Isophot Radius",          NAN);
     470                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS_ERR", PS_DATA_F32, "Isophot Radius Error",    NAN);
     471            }
     472        }
     473
     474        // Flux Annuli
     475        if (doAnnuli) {
     476            pmSourceAnnuli *annuli = source->extpars->annuli;
     477            if (annuli) {
     478                psVector *fluxVal = annuli->flux;
     479                psVector *fluxErr = annuli->fluxErr;
     480                psVector *fluxVar = annuli->fluxVar;
     481
     482                for (int j = 0; j < fluxVal->n; j++) {
     483                    char name[32];
     484                    sprintf (name, "FLUX_VAL_R_%02d", j);
     485                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux value in annulus", fluxVal->data.F32[j]);
     486                    sprintf (name, "FLUX_ERR_R_%02d", j);
     487                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux error in annulus", fluxErr->data.F32[j]);
     488                    sprintf (name, "FLUX_VAR_R_%02d", j);
     489                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux stdev in annulus", fluxVar->data.F32[j]);
     490                }
     491            } else {
     492                for (int j = 0; j < radialBinsLower->n; j++) {
     493                    char name[32];
     494                    sprintf (name, "FLUX_VAL_R_%02d", j);
     495                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux value in annulus", NAN);
     496                    sprintf (name, "FLUX_ERR_R_%02d", j);
     497                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux error in annulus", NAN);
     498                    sprintf (name, "FLUX_VAR_R_%02d", j);
     499                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux stdev in annulus", NAN);
     500                }
     501            }
     502        }
     503
     504        psArrayAdd (table, 100, row);
     505        psFree (row);
    506506    }
    507507
    508508    if (table->n == 0) {
    509         psFitsWriteBlank (fits, outhead, extname);
    510         psFree (outhead);
    511         psFree (table);
    512         return true;
     509        psFitsWriteBlank (fits, outhead, extname);
     510        psFree (outhead);
     511        psFree (table);
     512        return true;
    513513    }
    514514
    515515    psTrace ("pmFPAfile", 5, "writing ext data %s\n", extname);
    516516    if (!psFitsWriteTable (fits, outhead, table, extname)) {
    517         psError(PS_ERR_IO, false, "writing ext data %s\n", extname);
    518         psFree (outhead);
    519         psFree(table);
    520         return false;
     517        psError(PS_ERR_IO, false, "writing ext data %s\n", extname);
     518        psFree (outhead);
     519        psFree(table);
     520        return false;
    521521    }
    522522    psFree (outhead);
     
    540540    pmFPA  *fpa  = chip->parent;
    541541    if (!chip->toFPA || !fpa->toTPA || !fpa->toSky) {
    542         psWarning ("astrometry calibration is missing, no calibrated coords");
     542        psWarning ("astrometry calibration is missing, no calibrated coords");
    543543    }
    544544
     
    549549    float zeropt  = psMetadataLookupF32 (&status2, imageHeader, "ZPT_OBS");
    550550    if (!status1 || !status2 || (exptime == 0.0)) {
    551         psWarning ("exposure time or measured zero point not found for a readout, no calibrated mags");
     551        psWarning ("exposure time or measured zero point not found for a readout, no calibrated mags");
    552552    } else {
    553         magOffset = zeropt + 2.5*log10(exptime);
     553        magOffset = zeropt + 2.5*log10(exptime);
    554554    }
    555555
     
    566566    int nParamMax = 0;
    567567    for (int i = 0; i < sources->n; i++) {
    568         pmSource *source = sources->data[i];
    569         if (source->modelFits == NULL) continue;
    570         for (int j = 0; j < source->modelFits->n; j++) {
    571             pmModel *model = source->modelFits->data[j];
    572             assert (model);
    573             nParamMax = PS_MAX (nParamMax, model->params->n);
    574         }
     568        pmSource *source = sources->data[i];
     569        if (source->modelFits == NULL) continue;
     570        for (int j = 0; j < source->modelFits->n; j++) {
     571            pmModel *model = source->modelFits->data[j];
     572            assert (model);
     573            nParamMax = PS_MAX (nParamMax, model->params->n);
     574        }
    575575    }
    576576
     
    580580    for (int i = 0; i < sources->n; i++) {
    581581
    582         pmSource *source = sources->data[i];
    583 
    584         // XXX if no model fits are saved, write out modelEXT?
    585         if (source->modelFits == NULL) continue;
    586 
    587         // We have multiple sources : need to flag the one used to subtract the light (the 'best' model)
    588         for (int j = 0; j < source->modelFits->n; j++) {
    589 
    590             // choose the convolved EXT model, if available, otherwise the simple one
    591             pmModel *model = source->modelFits->data[j];
    592             assert (model);
    593 
    594             PAR = model->params->data.F32;
    595             dPAR = model->dparams->data.F32;
    596             xPos = PAR[PM_PAR_XPOS];
    597             yPos = PAR[PM_PAR_YPOS];
    598             xErr = dPAR[PM_PAR_XPOS];
    599             yErr = dPAR[PM_PAR_YPOS];
    600 
    601             axes = pmPSF_ModelToAxes (PAR, 20.0);
    602 
    603             // generate RA,DEC
    604             psPlane ptCH, ptFP, ptTP;
    605             psSphere ptSky;
    606 
    607             ptCH.x = xPos;
    608             ptCH.y = yPos;
    609             if (chip->toFPA && fpa->toTPA && fpa->toSky) {
    610                 psPlaneTransformApply (&ptFP, chip->toFPA, &ptCH);
    611                 psPlaneTransformApply (&ptTP, fpa->toTPA, &ptFP);
    612                 psDeproject (&ptSky, &ptTP, fpa->toSky);
    613             } else {
    614                 ptSky.r = NAN;
    615                 ptSky.d = NAN;
    616             }
    617 
    618             row = psMetadataAlloc ();
    619 
    620             // XXX we are not writing out the mode (flags) or the type (psf, ext, etc)
    621             psMetadataAddU32 (row, PS_LIST_TAIL, "IPP_IDET",         0, "IPP detection identifier index",             source->seq);
    622             psMetadataAddF32 (row, PS_LIST_TAIL, "RA_EXT",           0, "EXT model RA (degrees)",                     ptSky.r);
    623             psMetadataAddF32 (row, PS_LIST_TAIL, "DEC_EXT",          0, "EXT model DEC (degrees)",                    ptSky.d);
    624             psMetadataAddF32 (row, PS_LIST_TAIL, "X_EXT",            0, "EXT model x coordinate",                     xPos);
    625             psMetadataAddF32 (row, PS_LIST_TAIL, "Y_EXT",            0, "EXT model y coordinate",                     yPos);
    626             psMetadataAddF32 (row, PS_LIST_TAIL, "X_EXT_SIG",        0, "Sigma in EXT x coordinate",                  xErr);
    627             psMetadataAddF32 (row, PS_LIST_TAIL, "Y_EXT_SIG",        0, "Sigma in EXT y coordinate",                  yErr);
    628             psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_CAL_MAG",      0, "EXT fit calibrated magnitude",               model->mag + magOffset);
    629             psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_INST_MAG",     0, "EXT fit instrumental magnitude",             model->mag);
    630             psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_INST_MAG_SIG", 0, "Sigma of PSF instrumental magnitude",        model->magErr);
    631 
    632             psMetadataAddF32 (row, PS_LIST_TAIL, "NPARAMS",          0, "number of model parameters",                 model->params->n);
    633             psMetadataAddStr (row, PS_LIST_TAIL, "MODEL_TYPE",       0, "name of model",                              pmModelClassGetName (model->type));
    634 
    635             // XXX these should be major and minor, not 'x' and 'y'
    636             psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_WIDTH_MAJ",    0, "EXT width in x coordinate",                  axes.major);
    637             psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_WIDTH_MIN",    0, "EXT width in y coordinate",                  axes.minor);
    638             psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_THETA",        0, "EXT orientation angle",                      axes.theta);
    639 
    640             // write out the other generic parameters
    641             for (int k = 0; k < nParamMax; k++) {
    642                 if (k == PM_PAR_I0) continue;
    643                 if (k == PM_PAR_SKY) continue;
    644                 if (k == PM_PAR_XPOS) continue;
    645                 if (k == PM_PAR_YPOS) continue;
    646                 if (k == PM_PAR_SXX) continue;
    647                 if (k == PM_PAR_SXY) continue;
    648                 if (k == PM_PAR_SYY) continue;
    649 
    650                 snprintf (name, 64, "EXT_PAR_%02d", k);
    651 
    652                 if (k < model->params->n) {
    653                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "", model->params->data.F32[k]);
    654                 } else {
    655                     psMetadataAddF32 (row, PS_LIST_TAIL, name, PS_DATA_F32, "", NAN);
    656                 }
    657             }
    658 
    659             // XXX other parameters which may be set.
    660             // XXX flag / value to define the model
    661             // XXX write out the model type, fit status flags
    662 
    663             psArrayAdd (table, 100, row);
    664             psFree (row);
    665         }
     582        pmSource *source = sources->data[i];
     583
     584        // XXX if no model fits are saved, write out modelEXT?
     585        if (source->modelFits == NULL) continue;
     586
     587        // We have multiple sources : need to flag the one used to subtract the light (the 'best' model)
     588        for (int j = 0; j < source->modelFits->n; j++) {
     589
     590            // choose the convolved EXT model, if available, otherwise the simple one
     591            pmModel *model = source->modelFits->data[j];
     592            assert (model);
     593
     594            PAR = model->params->data.F32;
     595            dPAR = model->dparams->data.F32;
     596            xPos = PAR[PM_PAR_XPOS];
     597            yPos = PAR[PM_PAR_YPOS];
     598            xErr = dPAR[PM_PAR_XPOS];
     599            yErr = dPAR[PM_PAR_YPOS];
     600
     601            axes = pmPSF_ModelToAxes (PAR, 20.0);
     602
     603            // generate RA,DEC
     604            psPlane ptCH, ptFP, ptTP;
     605            psSphere ptSky;
     606
     607            ptCH.x = xPos;
     608            ptCH.y = yPos;
     609            if (chip->toFPA && fpa->toTPA && fpa->toSky) {
     610                psPlaneTransformApply (&ptFP, chip->toFPA, &ptCH);
     611                psPlaneTransformApply (&ptTP, fpa->toTPA, &ptFP);
     612                psDeproject (&ptSky, &ptTP, fpa->toSky);
     613            } else {
     614                ptSky.r = NAN;
     615                ptSky.d = NAN;
     616            }
     617
     618            row = psMetadataAlloc ();
     619
     620            // XXX we are not writing out the mode (flags) or the type (psf, ext, etc)
     621            psMetadataAddU32 (row, PS_LIST_TAIL, "IPP_IDET",         0, "IPP detection identifier index",             source->seq);
     622            psMetadataAddF32 (row, PS_LIST_TAIL, "RA_EXT",           0, "EXT model RA (degrees)",                     ptSky.r);
     623            psMetadataAddF32 (row, PS_LIST_TAIL, "DEC_EXT",          0, "EXT model DEC (degrees)",                    ptSky.d);
     624            psMetadataAddF32 (row, PS_LIST_TAIL, "X_EXT",            0, "EXT model x coordinate",                     xPos);
     625            psMetadataAddF32 (row, PS_LIST_TAIL, "Y_EXT",            0, "EXT model y coordinate",                     yPos);
     626            psMetadataAddF32 (row, PS_LIST_TAIL, "X_EXT_SIG",        0, "Sigma in EXT x coordinate",                  xErr);
     627            psMetadataAddF32 (row, PS_LIST_TAIL, "Y_EXT_SIG",        0, "Sigma in EXT y coordinate",                  yErr);
     628            psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_CAL_MAG",      0, "EXT fit calibrated magnitude",               model->mag + magOffset);
     629            psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_INST_MAG",     0, "EXT fit instrumental magnitude",             model->mag);
     630            psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_INST_MAG_SIG", 0, "Sigma of PSF instrumental magnitude",        model->magErr);
     631
     632            psMetadataAddF32 (row, PS_LIST_TAIL, "NPARAMS",          0, "number of model parameters",                 model->params->n);
     633            psMetadataAddStr (row, PS_LIST_TAIL, "MODEL_TYPE",       0, "name of model",                              pmModelClassGetName (model->type));
     634
     635            // XXX these should be major and minor, not 'x' and 'y'
     636            psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_WIDTH_MAJ",    0, "EXT width in x coordinate",                  axes.major);
     637            psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_WIDTH_MIN",    0, "EXT width in y coordinate",                  axes.minor);
     638            psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_THETA",        0, "EXT orientation angle",                      axes.theta);
     639
     640            // write out the other generic parameters
     641            for (int k = 0; k < nParamMax; k++) {
     642                if (k == PM_PAR_I0) continue;
     643                if (k == PM_PAR_SKY) continue;
     644                if (k == PM_PAR_XPOS) continue;
     645                if (k == PM_PAR_YPOS) continue;
     646                if (k == PM_PAR_SXX) continue;
     647                if (k == PM_PAR_SXY) continue;
     648                if (k == PM_PAR_SYY) continue;
     649
     650                snprintf (name, 64, "EXT_PAR_%02d", k);
     651
     652                if (k < model->params->n) {
     653                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "", model->params->data.F32[k]);
     654                } else {
     655                    psMetadataAddF32 (row, PS_LIST_TAIL, name, PS_DATA_F32, "", NAN);
     656                }
     657            }
     658
     659            // XXX other parameters which may be set.
     660            // XXX flag / value to define the model
     661            // XXX write out the model type, fit status flags
     662
     663            psArrayAdd (table, 100, row);
     664            psFree (row);
     665        }
    666666    }
    667667
    668668    if (table->n == 0) {
    669         psFitsWriteBlank (fits, outhead, extname);
    670         psFree (outhead);
    671         psFree (table);
    672         return true;
     669        psFitsWriteBlank (fits, outhead, extname);
     670        psFree (outhead);
     671        psFree (table);
     672        return true;
    673673    }
    674674
    675675    psTrace ("pmFPAfile", 5, "writing ext data %s\n", extname);
    676676    if (!psFitsWriteTable (fits, outhead, table, extname)) {
    677         psError(PS_ERR_IO, false, "writing ext data %s\n", extname);
    678         psFree (outhead);
    679         psFree(table);
    680         return false;
     677        psError(PS_ERR_IO, false, "writing ext data %s\n", extname);
     678        psFree (outhead);
     679        psFree(table);
     680        return false;
    681681    }
    682682    psFree (outhead);
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourceIO_PS1_DEV_1.c

    r21536 r23197  
    33 *  @author EAM, IfA
    44 *
    5  *  @version $Revision: 1.14.14.1 $ $Name: not supported by cvs2svn $
    6  *  @date $Date: 2009-02-19 17:59:50 $
     5 *  @version $Revision: 1.15 $ $Name: not supported by cvs2svn $
     6 *  @date $Date: 2009-02-16 22:30:50 $
    77 *
    88 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    4949// XXX how do I generate the source tables which I need to send to PSPS?
    5050
    51 bool pmSourcesWrite_PS1_DEV_1 (psFits *fits, psArray *sources,
    52                                psMetadata *imageHeader, psMetadata *tableHeader, char *extname)
     51bool pmSourcesWrite_PS1_DEV_1 (psFits *fits, psArray *sources, 
     52                               psMetadata *imageHeader, psMetadata *tableHeader, char *extname)
    5353{
    5454    PS_ASSERT_PTR_NON_NULL(fits, false);
     
    7373    for (i = 0; i < sources->n; i++) {
    7474        pmSource *source = (pmSource *) sources->data[i];
    75         if (source->seq == -1) {
    76             source->seq = i;
    77         }
     75        if (source->seq == -1) {
     76            source->seq = i;
     77        }
    7878
    7979        // no difference between PSF and non-PSF model
     
    8787            xErr = dPAR[PM_PAR_XPOS];
    8888            yErr = dPAR[PM_PAR_YPOS];
    89             if (isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX])) {
    90                 axes = pmPSF_ModelToAxes (PAR, 20.0);
    91             } else {
    92                 axes.major = NAN;
    93                 axes.minor = NAN;
    94                 axes.theta = NAN;
    95             }
    96             chisq = model->chisq;
    97 
    98             // need to determine the PSF photometry error: source->errMag is the error on the 'best' model mag.
    99             errMag = model->dparams->data.F32[PM_PAR_I0] / model->params->data.F32[PM_PAR_I0];
     89            if (isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX])) {
     90                axes = pmPSF_ModelToAxes (PAR, 20.0);
     91            } else {
     92                axes.major = NAN;
     93                axes.minor = NAN;
     94                axes.theta = NAN;
     95            }
     96            chisq = model->chisq;
     97
     98            // need to determine the PSF photometry error: source->errMag is the error on the 'best' model mag.
     99            errMag = model->dparams->data.F32[PM_PAR_I0] / model->params->data.F32[PM_PAR_I0];
    100100        } else {
    101101            xPos = source->peak->xf;
     
    106106            axes.minor = NAN;
    107107            axes.theta = NAN;
    108             chisq = NAN;
    109             errMag = NAN;
     108            chisq = NAN;
     109            errMag = NAN;
    110110        }
    111111
     
    130130        psMetadataAdd (row, PS_LIST_TAIL, "EXT_NSIGMA",       PS_DATA_F32,  "Nsigma deviations from PSF to EXT",         source->extNsigma);
    131131
    132         // EXT_NSIGMA will be NAN if: 1) contour ellipse is imaginary; 2) source is not
    133         // subtracted
    134 
    135         // CR_NSIGMA will be NAN if: 1) source is not subtracted; 2) source is on the image
    136         // edge; 3) any pixels in the 3x3 peak region are masked;
    137 
    138         // CR_NSIGMA and
     132        // EXT_NSIGMA will be NAN if: 1) contour ellipse is imaginary; 2) source is not
     133        // subtracted
     134
     135        // CR_NSIGMA will be NAN if: 1) source is not subtracted; 2) source is on the image
     136        // edge; 3) any pixels in the 3x3 peak region are masked;
     137
     138        // CR_NSIGMA and
    139139
    140140        // XXX these should be major and minor, not 'x' and 'y'
     
    247247        source->psfMag    = psMetadataLookupF32 (&status, row, "PSF_INST_MAG");
    248248        source->errMag    = psMetadataLookupF32 (&status, row, "PSF_INST_MAG_SIG");
    249         PAR[PM_PAR_I0]    = (isfinite(source->psfMag)) ? pow(10.0, -0.4*source->psfMag) : NAN;
    250         dPAR[PM_PAR_I0]   = (isfinite(source->psfMag)) ? PAR[PM_PAR_I0] * source->errMag : NAN;
     249        PAR[PM_PAR_I0]    = (isfinite(source->psfMag)) ? pow(10.0, -0.4*source->psfMag) : NAN;
     250        dPAR[PM_PAR_I0]   = (isfinite(source->psfMag)) ? PAR[PM_PAR_I0] * source->errMag : NAN;
    251251
    252252        pmPSF_AxesToModel (PAR, axes);
     
    259259        source->pixWeight = psMetadataLookupF32 (&status, row, "PSF_QF");
    260260
    261         // note that some older versions used PSF_PROBABILITY: this was not well defined.
     261        // note that some older versions used PSF_PROBABILITY: this was not well defined.
    262262        model->chisq      = psMetadataLookupF32 (&status, row, "PSF_CHISQ");
    263263        source->crNsigma  = psMetadataLookupF32 (&status, row, "CR_NSIGMA");
     
    311311    // we write out all sources, regardless of quality.  the source flags tell us the state
    312312    for (int i = 0; i < sources->n; i++) {
    313         // skip source if it is not a ext sourc
    314         // XXX we have two places that extended source parameters are measured:
    315         // psphotExtendedSources, which measures the aperture-like parameters and (potentially) the psf-convolved extended source models,
    316         // psphotFitEXT, which does the simple extended source model fit (not psf-convolved)
    317         // should we require both?
    318 
    319         pmSource *source = sources->data[i];
    320 
    321         // skip sources without measurements
    322         if (source->extpars == NULL) continue;
    323 
    324         // we require a PSF model fit (ignore the real crud)
    325         pmModel *model = source->modelPSF;
    326         if (model == NULL) continue;
    327 
    328         // XXX I need to split the extended models from the extended aperture measurements
    329         PAR = model->params->data.F32;
    330         dPAR = model->dparams->data.F32;
    331         xPos = PAR[PM_PAR_XPOS];
    332         yPos = PAR[PM_PAR_YPOS];
    333         xErr = dPAR[PM_PAR_XPOS];
    334         yErr = dPAR[PM_PAR_YPOS];
     313        // skip source if it is not a ext sourc
     314        // XXX we have two places that extended source parameters are measured:
     315        // psphotExtendedSources, which measures the aperture-like parameters and (potentially) the psf-convolved extended source models,
     316        // psphotFitEXT, which does the simple extended source model fit (not psf-convolved)
     317        // should we require both?
     318
     319        pmSource *source = sources->data[i];
     320
     321        // skip sources without measurements
     322        if (source->extpars == NULL) continue;
     323
     324        // we require a PSF model fit (ignore the real crud)
     325        pmModel *model = source->modelPSF;
     326        if (model == NULL) continue;
     327
     328        // XXX I need to split the extended models from the extended aperture measurements
     329        PAR = model->params->data.F32;
     330        dPAR = model->dparams->data.F32;
     331        xPos = PAR[PM_PAR_XPOS];
     332        yPos = PAR[PM_PAR_YPOS];
     333        xErr = dPAR[PM_PAR_XPOS];
     334        yErr = dPAR[PM_PAR_YPOS];
    335335
    336336        row = psMetadataAlloc ();
     
    343343        psMetadataAdd (row, PS_LIST_TAIL, "Y_EXT_SIG",        PS_DATA_F32, "Sigma in EXT y coordinate",                  yErr);
    344344
    345         // Petrosian measurements
    346         // XXX insert header data: petrosian ref radius, flux ratio
    347         if (doPetrosian) {
    348             pmSourcePetrosianValues *petrosian = source->extpars->petrosian;
    349             if (petrosian) {
    350                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG",        PS_DATA_F32, "Petrosian Magnitude",       petrosian->mag);
    351                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_ERR",    PS_DATA_F32, "Petrosian Magnitude Error", petrosian->magErr);
    352                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS",     PS_DATA_F32, "Petrosian Radius",          petrosian->rad);
    353                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_ERR", PS_DATA_F32, "Petrosian Radius Error",    petrosian->radErr);
    354             } else {
    355                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG",        PS_DATA_F32, "Petrosian Magnitude",       NAN);
    356                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_ERR",    PS_DATA_F32, "Petrosian Magnitude Error", NAN);
    357                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS",     PS_DATA_F32, "Petrosian Radius",          NAN);
    358                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_ERR", PS_DATA_F32, "Petrosian Radius Error",    NAN);
    359             }
    360         }
    361 
    362         // Kron measurements
    363         if (doKron) {
    364             pmSourceKronValues *kron = source->extpars->kron;
    365             if (kron) {
    366                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG",        PS_DATA_F32, "Kron Magnitude",       kron->mag);
    367                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG_ERR",    PS_DATA_F32, "Kron Magnitude Error", kron->magErr);
    368                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS",     PS_DATA_F32, "Kron Radius",          kron->rad);
    369                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS_ERR", PS_DATA_F32, "Kron Radius Error",    kron->radErr);
    370             } else {
    371                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG",        PS_DATA_F32, "Kron Magnitude",       NAN);
    372                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG_ERR",    PS_DATA_F32, "Kron Magnitude Error", NAN);
    373                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS",     PS_DATA_F32, "Kron Radius",          NAN);
    374                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS_ERR", PS_DATA_F32, "Kron Radius Error",    NAN);
    375             }
    376         }
    377 
    378         // Isophot measurements
    379         // XXX insert header data: isophotal level
    380         if (doIsophotal) {
    381             pmSourceIsophotalValues *isophot = source->extpars->isophot;
    382             if (isophot) {
    383                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG",        PS_DATA_F32, "Isophot Magnitude",       isophot->mag);
    384                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG_ERR",    PS_DATA_F32, "Isophot Magnitude Error", isophot->magErr);
    385                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS",     PS_DATA_F32, "Isophot Radius",          isophot->rad);
    386                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS_ERR", PS_DATA_F32, "Isophot Radius Error",    isophot->radErr);
    387             } else {
    388                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG",        PS_DATA_F32, "Isophot Magnitude",       NAN);
    389                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG_ERR",    PS_DATA_F32, "Isophot Magnitude Error", NAN);
    390                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS",     PS_DATA_F32, "Isophot Radius",          NAN);
    391                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS_ERR", PS_DATA_F32, "Isophot Radius Error",    NAN);
    392             }
    393         }
    394 
    395         // Flux Annuli
    396         if (doAnnuli) {
    397             pmSourceAnnuli *annuli = source->extpars->annuli;
    398             if (annuli) {
    399                 psVector *fluxVal = annuli->flux;
    400                 psVector *fluxErr = annuli->fluxErr;
    401                 psVector *fluxVar = annuli->fluxVar;
    402 
    403                 for (int j = 0; j < fluxVal->n; j++) {
    404                     char name[32];
    405                     sprintf (name, "FLUX_VAL_R_%02d", j);
    406                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux value in annulus", fluxVal->data.F32[j]);
    407                     sprintf (name, "FLUX_ERR_R_%02d", j);
    408                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux error in annulus", fluxErr->data.F32[j]);
    409                     sprintf (name, "FLUX_VAR_R_%02d", j);
    410                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux stdev in annulus", fluxVar->data.F32[j]);
    411                 }
    412             } else {
    413                 for (int j = 0; j < radialBinsLower->n; j++) {
    414                     char name[32];
    415                     sprintf (name, "FLUX_VAL_R_%02d", j);
    416                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux value in annulus", NAN);
    417                     sprintf (name, "FLUX_ERR_R_%02d", j);
    418                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux error in annulus", NAN);
    419                     sprintf (name, "FLUX_VAR_R_%02d", j);
    420                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux stdev in annulus", NAN);
    421                 }
    422             }
    423         }
    424 
    425         psArrayAdd (table, 100, row);
    426         psFree (row);
     345        // Petrosian measurements
     346        // XXX insert header data: petrosian ref radius, flux ratio
     347        if (doPetrosian) {
     348            pmSourcePetrosianValues *petrosian = source->extpars->petrosian;
     349            if (petrosian) {
     350                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG",        PS_DATA_F32, "Petrosian Magnitude",       petrosian->mag);
     351                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_ERR",    PS_DATA_F32, "Petrosian Magnitude Error", petrosian->magErr);
     352                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS",     PS_DATA_F32, "Petrosian Radius",          petrosian->rad);
     353                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_ERR", PS_DATA_F32, "Petrosian Radius Error",    petrosian->radErr);
     354            } else {
     355                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG",        PS_DATA_F32, "Petrosian Magnitude",       NAN);
     356                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_ERR",    PS_DATA_F32, "Petrosian Magnitude Error", NAN);
     357                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS",     PS_DATA_F32, "Petrosian Radius",          NAN);
     358                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_ERR", PS_DATA_F32, "Petrosian Radius Error",    NAN);
     359            }
     360        }
     361
     362        // Kron measurements
     363        if (doKron) {
     364            pmSourceKronValues *kron = source->extpars->kron;
     365            if (kron) {
     366                psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG",        PS_DATA_F32, "Kron Magnitude",       kron->mag);
     367                psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG_ERR",    PS_DATA_F32, "Kron Magnitude Error", kron->magErr);
     368                psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS",     PS_DATA_F32, "Kron Radius",          kron->rad);
     369                psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS_ERR", PS_DATA_F32, "Kron Radius Error",    kron->radErr);
     370            } else {
     371                psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG",        PS_DATA_F32, "Kron Magnitude",       NAN);
     372                psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG_ERR",    PS_DATA_F32, "Kron Magnitude Error", NAN);
     373                psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS",     PS_DATA_F32, "Kron Radius",          NAN);
     374                psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS_ERR", PS_DATA_F32, "Kron Radius Error",    NAN);
     375            }
     376        }
     377
     378        // Isophot measurements
     379        // XXX insert header data: isophotal level
     380        if (doIsophotal) {
     381            pmSourceIsophotalValues *isophot = source->extpars->isophot;
     382            if (isophot) {
     383                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG",        PS_DATA_F32, "Isophot Magnitude",       isophot->mag);
     384                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG_ERR",    PS_DATA_F32, "Isophot Magnitude Error", isophot->magErr);
     385                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS",     PS_DATA_F32, "Isophot Radius",          isophot->rad);
     386                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS_ERR", PS_DATA_F32, "Isophot Radius Error",    isophot->radErr);
     387            } else {
     388                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG",        PS_DATA_F32, "Isophot Magnitude",       NAN);
     389                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG_ERR",    PS_DATA_F32, "Isophot Magnitude Error", NAN);
     390                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS",     PS_DATA_F32, "Isophot Radius",          NAN);
     391                psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS_ERR", PS_DATA_F32, "Isophot Radius Error",    NAN);
     392            }
     393        }
     394
     395        // Flux Annuli
     396        if (doAnnuli) {
     397            pmSourceAnnuli *annuli = source->extpars->annuli;
     398            if (annuli) {
     399                psVector *fluxVal = annuli->flux;
     400                psVector *fluxErr = annuli->fluxErr;
     401                psVector *fluxVar = annuli->fluxVar;
     402
     403                for (int j = 0; j < fluxVal->n; j++) {
     404                    char name[32];
     405                    sprintf (name, "FLUX_VAL_R_%02d", j);
     406                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux value in annulus", fluxVal->data.F32[j]);
     407                    sprintf (name, "FLUX_ERR_R_%02d", j);
     408                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux error in annulus", fluxErr->data.F32[j]);
     409                    sprintf (name, "FLUX_VAR_R_%02d", j);
     410                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux stdev in annulus", fluxVar->data.F32[j]);
     411                }
     412            } else {
     413                for (int j = 0; j < radialBinsLower->n; j++) {
     414                    char name[32];
     415                    sprintf (name, "FLUX_VAL_R_%02d", j);
     416                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux value in annulus", NAN);
     417                    sprintf (name, "FLUX_ERR_R_%02d", j);
     418                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux error in annulus", NAN);
     419                    sprintf (name, "FLUX_VAR_R_%02d", j);
     420                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "flux stdev in annulus", NAN);
     421                }
     422            }
     423        }
     424
     425        psArrayAdd (table, 100, row);
     426        psFree (row);
    427427    }
    428428
    429429    if (table->n == 0) {
    430         psFitsWriteBlank (fits, outhead, extname);
    431         psFree (outhead);
    432         psFree (table);
    433         return true;
     430        psFitsWriteBlank (fits, outhead, extname);
     431        psFree (outhead);
     432        psFree (table);
     433        return true;
    434434    }
    435435
    436436    psTrace ("pmFPAfile", 5, "writing ext data %s\n", extname);
    437437    if (!psFitsWriteTable (fits, outhead, table, extname)) {
    438         psError(PS_ERR_IO, false, "writing ext data %s\n", extname);
    439         psFree (outhead);
    440         psFree(table);
    441         return false;
     438        psError(PS_ERR_IO, false, "writing ext data %s\n", extname);
     439        psFree (outhead);
     440        psFree(table);
     441        return false;
    442442    }
    443443    psFree (outhead);
     
    470470    int nParamMax = 0;
    471471    for (int i = 0; i < sources->n; i++) {
    472         pmSource *source = sources->data[i];
    473         if (source->modelFits == NULL) continue;
    474         for (int j = 0; j < source->modelFits->n; j++) {
    475             pmModel *model = source->modelFits->data[j];
    476             assert (model);
    477             nParamMax = PS_MAX (nParamMax, model->params->n);
    478         }
     472        pmSource *source = sources->data[i];
     473        if (source->modelFits == NULL) continue;
     474        for (int j = 0; j < source->modelFits->n; j++) {
     475            pmModel *model = source->modelFits->data[j];
     476            assert (model);
     477            nParamMax = PS_MAX (nParamMax, model->params->n);
     478        }
    479479    }
    480480
     
    484484    for (int i = 0; i < sources->n; i++) {
    485485
    486         pmSource *source = sources->data[i];
    487 
    488         // XXX if no model fits are saved, write out modelEXT?
    489         if (source->modelFits == NULL) continue;
    490 
    491         // We have multiple sources : need to flag the one used to subtract the light (the 'best' model)
    492         for (int j = 0; j < source->modelFits->n; j++) {
    493 
    494             // choose the convolved EXT model, if available, otherwise the simple one
    495             pmModel *model = source->modelFits->data[j];
    496             assert (model);
    497 
    498             PAR = model->params->data.F32;
    499             dPAR = model->dparams->data.F32;
    500             xPos = PAR[PM_PAR_XPOS];
    501             yPos = PAR[PM_PAR_YPOS];
    502             xErr = dPAR[PM_PAR_XPOS];
    503             yErr = dPAR[PM_PAR_YPOS];
    504 
    505             axes = pmPSF_ModelToAxes (PAR, 20.0);
    506 
    507             row = psMetadataAlloc ();
    508 
    509             // XXX we are not writing out the mode (flags) or the type (psf, ext, etc)
    510             psMetadataAddU32 (row, PS_LIST_TAIL, "IPP_IDET",         0, "IPP detection identifier index",             source->seq);
    511             psMetadataAddF32 (row, PS_LIST_TAIL, "X_EXT",            0, "EXT model x coordinate",                     xPos);
    512             psMetadataAddF32 (row, PS_LIST_TAIL, "Y_EXT",            0, "EXT model y coordinate",                     yPos);
    513             psMetadataAddF32 (row, PS_LIST_TAIL, "X_EXT_SIG",        0, "Sigma in EXT x coordinate",                  xErr);
    514             psMetadataAddF32 (row, PS_LIST_TAIL, "Y_EXT_SIG",        0, "Sigma in EXT y coordinate",                  yErr);
    515             psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_INST_MAG",     0, "EXT fit instrumental magnitude",             model->mag);
    516             psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_INST_MAG_SIG", 0, "Sigma of PSF instrumental magnitude",        model->magErr);
    517 
    518             psMetadataAddF32 (row, PS_LIST_TAIL, "NPARAMS",          0, "number of model parameters",                 model->params->n);
    519             psMetadataAddStr (row, PS_LIST_TAIL, "MODEL_TYPE",       0, "name of model",                              pmModelClassGetName (model->type));
    520 
    521             // XXX these should be major and minor, not 'x' and 'y'
    522             psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_WIDTH_MAJ",    0, "EXT width in x coordinate",                  axes.major);
    523             psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_WIDTH_MIN",    0, "EXT width in y coordinate",                  axes.minor);
    524             psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_THETA",        0, "EXT orientation angle",                      axes.theta);
    525 
    526             // write out the other generic parameters
    527             for (int k = 0; k < nParamMax; k++) {
    528                 if (k == PM_PAR_I0) continue;
    529                 if (k == PM_PAR_SKY) continue;
    530                 if (k == PM_PAR_XPOS) continue;
    531                 if (k == PM_PAR_YPOS) continue;
    532                 if (k == PM_PAR_SXX) continue;
    533                 if (k == PM_PAR_SXY) continue;
    534                 if (k == PM_PAR_SYY) continue;
    535 
    536                 snprintf (name, 64, "EXT_PAR_%02d", k);
    537 
    538                 if (k < model->params->n) {
    539                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "", model->params->data.F32[k]);
    540                 } else {
    541                     psMetadataAddF32 (row, PS_LIST_TAIL, name, PS_DATA_F32, "", NAN);
    542                 }
    543             }
    544 
    545             // XXX other parameters which may be set.
    546             // XXX flag / value to define the model
    547             // XXX write out the model type, fit status flags
    548 
    549             psArrayAdd (table, 100, row);
    550             psFree (row);
    551         }
     486        pmSource *source = sources->data[i];
     487
     488        // XXX if no model fits are saved, write out modelEXT?
     489        if (source->modelFits == NULL) continue;
     490
     491        // We have multiple sources : need to flag the one used to subtract the light (the 'best' model)
     492        for (int j = 0; j < source->modelFits->n; j++) {
     493
     494            // choose the convolved EXT model, if available, otherwise the simple one
     495            pmModel *model = source->modelFits->data[j];
     496            assert (model);
     497
     498            PAR = model->params->data.F32;
     499            dPAR = model->dparams->data.F32;
     500            xPos = PAR[PM_PAR_XPOS];
     501            yPos = PAR[PM_PAR_YPOS];
     502            xErr = dPAR[PM_PAR_XPOS];
     503            yErr = dPAR[PM_PAR_YPOS];
     504
     505            axes = pmPSF_ModelToAxes (PAR, 20.0);
     506
     507            row = psMetadataAlloc ();
     508
     509            // XXX we are not writing out the mode (flags) or the type (psf, ext, etc)
     510            psMetadataAddU32 (row, PS_LIST_TAIL, "IPP_IDET",         0, "IPP detection identifier index",             source->seq);
     511            psMetadataAddF32 (row, PS_LIST_TAIL, "X_EXT",            0, "EXT model x coordinate",                     xPos);
     512            psMetadataAddF32 (row, PS_LIST_TAIL, "Y_EXT",            0, "EXT model y coordinate",                     yPos);
     513            psMetadataAddF32 (row, PS_LIST_TAIL, "X_EXT_SIG",        0, "Sigma in EXT x coordinate",                  xErr);
     514            psMetadataAddF32 (row, PS_LIST_TAIL, "Y_EXT_SIG",        0, "Sigma in EXT y coordinate",                  yErr);
     515            psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_INST_MAG",     0, "EXT fit instrumental magnitude",             model->mag);
     516            psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_INST_MAG_SIG", 0, "Sigma of PSF instrumental magnitude",        model->magErr);
     517
     518            psMetadataAddF32 (row, PS_LIST_TAIL, "NPARAMS",          0, "number of model parameters",                 model->params->n);
     519            psMetadataAddStr (row, PS_LIST_TAIL, "MODEL_TYPE",       0, "name of model",                              pmModelClassGetName (model->type));
     520
     521            // XXX these should be major and minor, not 'x' and 'y'
     522            psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_WIDTH_MAJ",    0, "EXT width in x coordinate",                  axes.major);
     523            psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_WIDTH_MIN",    0, "EXT width in y coordinate",                  axes.minor);
     524            psMetadataAddF32 (row, PS_LIST_TAIL, "EXT_THETA",        0, "EXT orientation angle",                      axes.theta);
     525
     526            // write out the other generic parameters
     527            for (int k = 0; k < nParamMax; k++) {
     528                if (k == PM_PAR_I0) continue;
     529                if (k == PM_PAR_SKY) continue;
     530                if (k == PM_PAR_XPOS) continue;
     531                if (k == PM_PAR_YPOS) continue;
     532                if (k == PM_PAR_SXX) continue;
     533                if (k == PM_PAR_SXY) continue;
     534                if (k == PM_PAR_SYY) continue;
     535
     536                snprintf (name, 64, "EXT_PAR_%02d", k);
     537
     538                if (k < model->params->n) {
     539                    psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "", model->params->data.F32[k]);
     540                } else {
     541                    psMetadataAddF32 (row, PS_LIST_TAIL, name, PS_DATA_F32, "", NAN);
     542                }
     543            }
     544
     545            // XXX other parameters which may be set.
     546            // XXX flag / value to define the model
     547            // XXX write out the model type, fit status flags
     548
     549            psArrayAdd (table, 100, row);
     550            psFree (row);
     551        }
    552552    }
    553553
    554554    if (table->n == 0) {
    555         psFitsWriteBlank (fits, outhead, extname);
    556         psFree (outhead);
    557         psFree (table);
    558         return true;
     555        psFitsWriteBlank (fits, outhead, extname);
     556        psFree (outhead);
     557        psFree (table);
     558        return true;
    559559    }
    560560
    561561    psTrace ("pmFPAfile", 5, "writing ext data %s\n", extname);
    562562    if (!psFitsWriteTable (fits, outhead, table, extname)) {
    563         psError(PS_ERR_IO, false, "writing ext data %s\n", extname);
    564         psFree (outhead);
    565         psFree(table);
    566         return false;
     563        psError(PS_ERR_IO, false, "writing ext data %s\n", extname);
     564        psFree (outhead);
     565        psFree(table);
     566        return false;
    567567    }
    568568    psFree (outhead);
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourcePhotometry.c

    r21536 r23197  
    33 *  @author EAM, IfA; GLG, MHPCC
    44 *
    5  *  @version $Revision: 1.49.4.1 $ $Name: not supported by cvs2svn $
    6  *  @date $Date: 2009-02-19 17:59:50 $
     5 *  @version $Revision: 1.50 $ $Name: not supported by cvs2svn $
     6 *  @date $Date: 2009-02-16 22:28:54 $
    77 *
    88 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    578578        }
    579579    }
    580     model->nPix = Npix;
     580    model->nPix = Npix; 
    581581    model->nDOF = Npix - 1;
    582582    model->chisq = dC;
     
    768768// measure centroid of unshifted gaussian (should be 16.0,16.0)
    769769        {
    770           psImage *image = source->pixels;
    771           float xo = 0.0;
    772           float yo = 0.0;
    773           float xo2 = 0.0;
    774           float yo2 = 0.0;
    775           float no = 0.0;
    776           for (int j = 0; j < image->numRows; j++)
    777           {
    778             for (int i = 0; i < image->numCols; i++) {
    779               xo += i*image->data.F32[j][i];
    780               yo += j*image->data.F32[j][i];
    781               xo2 += i*i*image->data.F32[j][i];
    782               yo2 += j*j*image->data.F32[j][i];
    783               no += image->data.F32[j][i];
    784             }
    785           }
    786           xo /= no;
    787           yo /= no;
    788           xo2 = sqrt (xo2/no - xo*xo);
    789           yo2 = sqrt (yo2/no - yo*yo);
    790           fprintf (stderr, "pre-shift centroid: %f,%f, sigma: %f,%f: flux: %f\n", xo, yo, xo2, yo2, no);
     770          psImage *image = source->pixels;
     771          float xo = 0.0;
     772          float yo = 0.0;
     773          float xo2 = 0.0;
     774          float yo2 = 0.0;
     775          float no = 0.0;
     776          for (int j = 0; j < image->numRows; j++)
     777          {
     778            for (int i = 0; i < image->numCols; i++) {
     779              xo += i*image->data.F32[j][i];
     780              yo += j*image->data.F32[j][i];
     781              xo2 += i*i*image->data.F32[j][i];
     782              yo2 += j*j*image->data.F32[j][i];
     783              no += image->data.F32[j][i];
     784            }
     785          }
     786          xo /= no;
     787          yo /= no;
     788          xo2 = sqrt (xo2/no - xo*xo);
     789          yo2 = sqrt (yo2/no - yo*yo);
     790          fprintf (stderr, "pre-shift centroid: %f,%f, sigma: %f,%f: flux: %f\n", xo, yo, xo2, yo2, no);
    791791        }
    792792
    793793// measure centroid of unshifted gaussian (should be 16.0,16.0)
    794794        {
    795           psImage *image = flux;
    796           float xo = 0.0;
    797           float yo = 0.0;
    798           float xo2 = 0.0;
    799           float yo2 = 0.0;
    800           float no = 0.0;
    801           for (int j = 0; j < image->numRows; j++)
    802           {
    803             for (int i = 0; i < image->numCols; i++) {
    804               xo += i*image->data.F32[j][i];
    805               yo += j*image->data.F32[j][i];
    806               xo2 += i*i*image->data.F32[j][i];
    807               yo2 += j*j*image->data.F32[j][i];
    808               no += image->data.F32[j][i];
    809             }
    810           }
    811           xo /= no;
    812           yo /= no;
    813           xo2 = sqrt (xo2/no - xo*xo);
    814           yo2 = sqrt (yo2/no - yo*yo);
    815           fprintf (stderr, "pre-shift centroid: %f,%f, sigma: %f,%f: flux: %f\n", xo, yo, xo2, yo2, no);
     795          psImage *image = flux;
     796          float xo = 0.0;
     797          float yo = 0.0;
     798          float xo2 = 0.0;
     799          float yo2 = 0.0;
     800          float no = 0.0;
     801          for (int j = 0; j < image->numRows; j++)
     802          {
     803            for (int i = 0; i < image->numCols; i++) {
     804              xo += i*image->data.F32[j][i];
     805              yo += j*image->data.F32[j][i];
     806              xo2 += i*i*image->data.F32[j][i];
     807              yo2 += j*j*image->data.F32[j][i];
     808              no += image->data.F32[j][i];
     809            }
     810          }
     811          xo /= no;
     812          yo /= no;
     813          xo2 = sqrt (xo2/no - xo*xo);
     814          yo2 = sqrt (yo2/no - yo*yo);
     815          fprintf (stderr, "pre-shift centroid: %f,%f, sigma: %f,%f: flux: %f\n", xo, yo, xo2, yo2, no);
    816816        }
    817817# endif
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/objects/pmSourcePhotometry.h

    r21536 r23197  
    44 * @author EAM, IfA; GLG, MHPCC
    55 *
    6  * @version $Revision: 1.12.8.1 $ $Name: not supported by cvs2svn $
    7  * @date $Date: 2009-02-19 17:59:50 $
     6 * @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
     7 * @date $Date: 2009-02-16 22:28:54 $
    88 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii
    99 */
     
    4646    psImage *image,                     ///< image pixels to be used
    4747    psImage *mask,                      ///< mask of pixels to ignore
    48     psImageMaskType maskVal             ///< Value to mask
     48    psImageMaskType maskVal             ///< Value to mask
    4949);
    5050
  • branches/cnb_branches/cnb_branch_20090215/psModules/src/psmodules.h

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