IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jun 16, 2006, 3:50:43 PM (20 years ago)
Author:
magnier
Message:

updates from day when MHPCC CVS was down

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psModules/src/camera/pmFPAfile.c

    r7529 r7589  
    55#include "pmHDU.h"
    66#include "pmFPA.h"
    7 #include "pmFPAMaskWeight.h"
     7// #include "pmFPAMaskWeight.h"
    88#include "pmFPAConstruct.h"
    99#include "pmFPAview.h"
    1010#include "pmFPAfile.h"
    1111#include "pmFPACopy.h"
    12 #include "pmFPARead.h"
    13 #include "pmFPAWrite.h"
    14 #include "pmPeaks.h"
    15 #include "pmMoments.h"
    16 #include "pmModel.h"
    17 #include "pmSource.h"
    18 #include "pmSourceIO.h"
    19 #include "pmGrowthCurve.h"
    20 #include "pmPSF.h"
    21 #include "pmPSF_IO.h"
    22 #include "pmFPA_JPEG.h"
     12// #include "pmFPARead.h"
     13// #include "pmFPAWrite.h"
     14// #include "pmPeaks.h"
     15// #include "pmMoments.h"
     16// #include "pmModel.h"
     17// #include "pmSource.h"
     18// #include "pmSourceIO.h"
     19// #include "pmGrowthCurve.h"
     20// #include "pmPSF.h"
     21// #include "pmPSF_IO.h"
     22// #include "pmFPA_JPEG.h"
    2323
    2424static void pmFPAfileFree(pmFPAfile *file)
     
    3333    psFree (file->names);
    3434
     35    psFree (file->camera);
    3536    psFree (file->format);
    3637    psFree (file->name);
     
    4849    psFree (file->extname);
    4950
    50     // these are just views ??
    51     // psFree (file->phu);
    52     // psFree (file->header);
    53 
    5451    return;
    5552}
     
    6865    file->names = psMetadataAlloc();
    6966
     67    file->camera = NULL;
    7068    file->format = NULL;
    7169    file->name = NULL;
     
    8684}
    8785
    88 static const char *depthEnumToName(pmFPAdepth depth)
    89 {
    90     const char *val = NULL;
    91 
    92     switch (depth) {
    93     case PM_FPA_DEPTH_NONE:
    94         val = "NONE";
    95         break;
    96     case PM_FPA_DEPTH_FPA:
    97         val = "FPA";
    98         break;
    99     case PM_FPA_DEPTH_CHIP:
    100         val = "CHIP";
    101         break;
    102     case PM_FPA_DEPTH_CELL:
    103         val = "CELL";
    104         break;
    105     case PM_FPA_DEPTH_READOUT:
    106         val = "READOUT";
    107         break;
    108     default:
    109         psAbort(PS_FILE_LINE, "You can't get here; depth = %d", depth);
    110     }
    111 
    112     return val;
    113 }
    114 
    115 static pmFPAdepth depthNameToEnum(const char *name)
    116 {
    117     pmFPAdepth val;
    118 
    119     if (name == NULL) {
    120         val = PM_FPA_DEPTH_NONE;
    121     } else if (!strcasecmp(name, "FPA"))     {
    122         val = PM_FPA_DEPTH_FPA;
    123     } else if (!strcasecmp(name, "CHIP"))    {
    124         val = PM_FPA_DEPTH_CHIP;
    125     } else if (!strcasecmp(name, "CELL"))    {
    126         val = PM_FPA_DEPTH_CELL;
    127     } else if (!strcasecmp(name, "READOUT")) {
    128         val = PM_FPA_DEPTH_READOUT;
    129     } else {
    130         val = PM_FPA_DEPTH_NONE;
    131     }
    132 
    133     return val;
    134 }
    135 
    136 // define a pmFPAfile, bind to the optional fpa if supplied
    137 pmFPAfile *pmFPAfileDefine(psMetadata *files, psMetadata *camera, pmFPA *fpa, char *name)
    138 {
    139     PS_ASSERT_PTR_NON_NULL(files, NULL);
    140     PS_ASSERT_PTR_NON_NULL(camera, NULL);
    141     PS_ASSERT_PTR_NON_NULL(name, NULL);
    142     PS_ASSERT_INT_POSITIVE(strlen(name), NULL);
    143 
    144     bool status;
    145     char *type;
    146 
    147     // select the FILERULES from the camera config
    148     psMetadata *filerules = psMetadataLookupPtr (&status, camera, "FILERULES");
    149     if (filerules == NULL) {
    150         psError(PS_ERR_IO, true, "Can't find FILERULES in the CAMERA configuration!");
    151         return NULL;
    152     }
    153 
    154     // select the name from the FILERULES
    155     // check for alias name (type == STR, name is aliased name)
    156     char *realname = psMetadataLookupStr (&status, filerules, name);
    157     if (!realname || strlen(realname) == 0) {
    158         realname = name;
    159     }
    160 
    161     psMetadata *data = psMetadataLookupPtr (&status, filerules, realname);
    162     if (data == NULL) {
    163         psError(PS_ERR_IO, true, "Can't find file concept %s!", name);
    164         return NULL;
    165     }
    166 
    167     pmFPAfile *file = pmFPAfileAlloc ();
    168 
    169     // save the name of this pmFPAfile
    170     file->name = psStringCopy (name);
    171 
    172     file->filerule = psMemIncrRefCounter(psMetadataLookupStr (&status, data, "FILENAME.RULE"));
    173     file->filextra = psMemIncrRefCounter(psMetadataLookupStr (&status, data, "FILENAME.XTRA"));
    174     file->extrule  = psMemIncrRefCounter(psMetadataLookupStr (&status, data, "EXTNAME.RULE"));
    175     file->extxtra  = psMemIncrRefCounter(psMetadataLookupStr (&status, data, "EXTNAME.XTRA"));
    176 
    177     file->fileDepth = depthNameToEnum(psMetadataLookupStr(&status, data, "FILE.DEPTH"));
    178     if (file->fileDepth == PM_FPA_DEPTH_NONE) {
    179         psError(PS_ERR_IO, true, "FILE.DEPTH is not set for %s\n", name);
    180         return NULL;
    181     }
    182 
    183     file->dataDepth = depthNameToEnum(psMetadataLookupStr (&status, data, "DATA.DEPTH"));
    184     if (file->dataDepth == PM_FPA_DEPTH_NONE) {
    185         psError(PS_ERR_IO, true, "DATA.DEPTH is not set for %s\n", name);
    186         return NULL;
    187     }
    188 
    189     file->type = PM_FPA_FILE_NONE;
    190     type = psMetadataLookupStr (&status, data, "FILE.TYPE");
    191     if (type != NULL) {
    192         if (!strcasecmp (type, "SX"))     {
    193             file->type = PM_FPA_FILE_SX;
    194         }
    195         if (!strcasecmp (type, "OBJ"))     {
    196             file->type = PM_FPA_FILE_OBJ;
    197         }
    198         if (!strcasecmp (type, "CMP"))     {
    199             file->type = PM_FPA_FILE_CMP;
    200         }
    201         if (!strcasecmp (type, "CMF"))     {
    202             file->type = PM_FPA_FILE_CMF;
    203         }
    204         if (!strcasecmp (type, "RAW"))     {
    205             file->type = PM_FPA_FILE_RAW;
    206         }
    207         if (!strcasecmp (type, "IMAGE"))     {
    208             file->type = PM_FPA_FILE_IMAGE;
    209         }
    210         if (!strcasecmp (type, "PSF"))     {
    211             file->type = PM_FPA_FILE_PSF;
    212         }
    213         if (!strcasecmp (type, "JPEG"))     {
    214             file->type = PM_FPA_FILE_JPEG;
    215         }
    216     }
    217     if (file->type == PM_FPA_FILE_NONE) {
    218         psError(PS_ERR_IO, true, "FILE.TYPE is not defined for %s\n", name);
    219         return NULL;
    220     }
    221 
    222     file->mode = PM_FPA_MODE_NONE;
    223     type = psMetadataLookupStr (&status, data, "FILE.MODE");
    224     if (type != NULL) {
    225         if (!strcasecmp (type, "READ"))     {
    226             file->mode = PM_FPA_MODE_READ;
    227         }
    228         if (!strcasecmp (type, "WRITE"))     {
    229             file->mode = PM_FPA_MODE_WRITE;
    230         }
    231     }
    232     if (file->mode == PM_FPA_MODE_NONE) {
    233         psError(PS_ERR_IO, true, "FILE.MODE is not defined for %s\n", name);
    234         return NULL;
    235     }
    236 
    237     if (fpa != NULL) {
    238         file->fpa = psMemIncrRefCounter(fpa);
    239     }
    240 
    241     // for WRITE type of data, the output format needs to be determined
    242     // this is only needed if the output file is not identical in structure to the input
    243     char *formatName = psMetadataLookupStr (&status, data, "FILE.FORMAT");
    244     if (formatName && strcasecmp (formatName, "NONE")) {
    245         psMetadata *formats = psMetadataLookupMD(&status, camera, "FORMATS"); // List of formats
    246         char *formatFile = psMetadataLookupStr (&status, formats, formatName);
    247         if (!formatFile) {
    248             psError(PS_ERR_IO, false, "format %s for %s not defined", formatName, name);
    249             psFree (file);
    250             return NULL;
    251         }
    252         readConfig (&file->format, formatFile, formatName);
    253     }
    254 
    255     psMetadataAddPtr (files, PS_LIST_TAIL, name, PS_DATA_UNKNOWN, "", file);
    256 
    257     // we free this copy of file, but 'files' still has a copy
    258     psFree (file);
    259 
    260     // the returned value is a view into the version on 'files'
    261     return (file);
    262 }
    263 
    264 /*
    265 pmFPAfile *pmFPAfileConstruct (psMetadata *files, psMetadata *format, psMetadata *camera, char *name)
    266 {
    267     pmFPA *fpa = pmFPAConstruct (camera);
    268     pmFPAfile *file = pmFPAfileDefine (files, format, fpa, name);
    269     psFree (fpa);
    270     if (!file) {
    271         psErrorStackPrint(stderr, "file %s not defined\n", name);
    272         return NULL;
    273     }
    274     return file;
    275 }
    276 */
    277 
    278 // open file (if not already opened)
    279 bool pmFPAfileOpen (pmFPAfile *file, const pmFPAview *view)
    280 {
    281     PS_ASSERT_PTR_NON_NULL(file, false);
    282     PS_ASSERT_PTR_NON_NULL(view, false);
    283 
    284     bool status;
    285     char *extra;
    286     char *mode = NULL;
    287     char *readMode = "r";
    288     char *writeMode = "w";
    289 
    290     if (file->state & PM_FPA_STATE_INACTIVE) {
    291         psTrace("pmFPAfile", 6, "skip open for %s, files is inactive", file->name);
    292         return true;
    293     }
    294 
    295     if (file->state == PM_FPA_STATE_OPEN) {
    296         return true;
    297     }
    298 
    299     if (file->mode == PM_FPA_MODE_NONE) {
    300         psError(PS_ERR_IO, true, "File is mode PM_FPA_MODE_NONE");
    301         return false;
    302     }
    303     if (file->mode == PM_FPA_MODE_INTERNAL) {
    304         psError(PS_ERR_IO, true, "File is mode PM_FPA_MODE_INTERNAL");
    305         return false;
    306     }
    307     if (file->mode == PM_FPA_MODE_READ) {
    308         mode = readMode;
    309     }
    310     if (file->mode == PM_FPA_MODE_WRITE) {
    311         mode = writeMode;
    312     }
    313 
    314     // determine the file name
    315     // free a name allocated earlier
    316     psFree (file->filename);
    317     file->filename = pmFPAfileNameFromRule (file->filerule, file, view);
    318     if (file->filename == NULL) {
    319         psError(PS_ERR_IO, true, "Filename is NULL");
    320         return false;
    321     }
    322 
    323     // indirect filenames
    324     if (!strcasecmp (file->filename, "@FILES")) {
    325         psFree (file->filename);
    326         extra = pmFPAfileNameFromRule (file->filextra, file, view);
    327         file->filename = psMetadataLookupStr (&status, file->names, extra);
    328         psFree (extra);
    329         if (file->filename == NULL) {
    330             psError(PS_ERR_IO, true, "filename lookup error (@FILES) for %s : %s\n", file->filextra, extra);
    331             return false;
    332         }
    333         // psMetadataLookupStr just returns a view, file->filename must be protected
    334         psMemIncrRefCounter (file->filename);
    335     }
    336     if (!strcasecmp (file->filename, "@DETDB")) {
    337         psFree (file->filename);
    338         extra = pmFPAfileNameFromRule (file->filextra, file, view);
    339         // file->filename = pmDetrendSelect (extra);
    340         psFree (extra);
    341         if (file->filename == NULL) {
    342             psError(PS_ERR_IO, true, "filename lookup error (@DETBD) for %s : %s\n", file->filextra, extra);
    343             return false;
    344         }
    345         psMemIncrRefCounter (file->filename);
    346     }
    347 
    348     switch (file->type) {
    349         // open the FITS types:
    350     case PM_FPA_FILE_IMAGE:
    351     case PM_FPA_FILE_CMF:
    352         psTrace ("pmFPAfile", 5, "opening %s (type: %d)\n", file->filename, file->type);
    353         file->fits = psFitsOpen (file->filename, mode);
    354         if (file->fits == NULL) {
    355             psError(PS_ERR_IO, false, "error opening file %s\n", file->filename);
    356             return false;
    357         }
    358         file->state = PM_FPA_STATE_OPEN;
    359         break;
    360 
    361         // defer opening TEXT types:
    362     case PM_FPA_FILE_SX:
    363     case PM_FPA_FILE_OBJ:
    364     case PM_FPA_FILE_CMP:
    365     case PM_FPA_FILE_RAW:
    366     case PM_FPA_FILE_PSF:
    367     case PM_FPA_FILE_JPEG:
    368         psTrace ("pmFPAfile", 5, "defer opening %s\n", file->filename);
    369         break;
    370 
    371     default:
    372         psError(PS_ERR_IO, true, "type mismatch for %s : %d\n", file->filename, file->type);
    373         return false;
    374     }
    375     return true;
    376 }
    377 
    378 bool pmFPAfileRead(pmFPAfile *file, const pmFPAview *view)
    379 {
    380     PS_ASSERT_PTR_NON_NULL(file, false);
    381     PS_ASSERT_PTR_NON_NULL(view, false);
    382 
    383     if (file->state & PM_FPA_STATE_INACTIVE) {
    384         psTrace("pmFPAfile", 6, "skip read for %s, files is inactive", file->name);
    385         return true;
    386     }
    387 
    388     if (file->mode != PM_FPA_MODE_READ) {
    389         psTrace("pmFPAfile", 6, "skip read for %s, mode is not READ", file->name);
    390         return true;
    391     }
    392 
    393     // get the current depth
    394     pmFPAdepth depth = pmFPAviewDepth (view);
    395 
    396     // do we need to open this file?
    397     if (depth == file->fileDepth) {
    398         if (!pmFPAfileOpen (file, view)) {
    399             psError(PS_ERR_IO, false, "failed to open file %s", file->name);
    400             return false;
    401         }
    402     }
    403 
    404     // do we need to read this file?
    405     if (depth != file->dataDepth) {
    406         psTrace("pmFPAfile", 6, "skip reading of %s at this depth %s: dataDepth is %s",
    407                 file->name, depthEnumToName(depth), depthEnumToName(file->dataDepth));
    408         return true;
    409     }
    410 
    411     switch (file->type) {
    412     case PM_FPA_FILE_IMAGE:
    413         if (pmFPAviewReadFitsImage (view, file)) {
    414             psTrace ("pmFPAfile", 5, "reading %s (type: %d)\n", file->filename, file->type);
    415         } else {
    416             psError(PS_ERR_UNKNOWN, false, "skipping %s (type: %d)\n", file->filename, file->type);
    417             return false;
    418         }
    419         break;
    420 
    421     case PM_FPA_FILE_SX:
    422     case PM_FPA_FILE_RAW:
    423     case PM_FPA_FILE_OBJ:
    424     case PM_FPA_FILE_CMP:
    425     case PM_FPA_FILE_CMF:
    426         pmFPAviewReadObjects (view, file);
    427         psTrace ("pmFPAfile", 5, "reading %s (type: %d)\n", file->filename, file->type);
    428         break;
    429 
    430     case PM_FPA_FILE_PSF:
    431         pmFPAviewReadPSFmodel (view, file);
    432         psTrace ("pmFPAfile", 5, "reading %s (type: %d)\n", file->filename, file->type);
    433         break;
    434 
    435     case PM_FPA_FILE_JPEG:
    436         break;
    437 
    438     default:
    439         psError(PS_ERR_IO, true, "warning: type mismatch; saw type %d", file->type);
    440         return false;
    441     }
    442     return true;
    443 }
    444 
    445 bool pmFPAfileFreeData(pmFPAfile *file, const pmFPAview *view)
    446 {
    447     PS_ASSERT_PTR_NON_NULL(file, false);
    448     PS_ASSERT_PTR_NON_NULL(view, false);
    449 
    450     if (file->state & PM_FPA_STATE_INACTIVE) {
    451         psTrace("pmFPAfile", 6, "skip free for %s, files is inactive", file->name);
    452         return true;
    453     }
    454 
    455     // get the current depth
    456     pmFPAdepth depth = pmFPAviewDepth (view);
    457 
    458     // do we need to read this file?
    459     if (depth != file->dataDepth) {
    460         psTrace("pmFPAfile", 6, "skip free of %s at this depth %s: dataDepth is %s",
    461                 file->name, depthEnumToName(depth), depthEnumToName(file->dataDepth));
    462         return true;
    463     }
    464 
    465     switch (file->type) {
    466     case PM_FPA_FILE_IMAGE:
    467         if (pmFPAviewFreeFitsImage (view, file)) {
    468             psTrace ("pmFPAfile", 5, "freed %s (type: %d)\n", file->filename, file->type);
    469         } else {
    470             psError(PS_ERR_UNKNOWN, false, "skipping %s (type: %d)\n", file->filename, file->type);
    471             return false;
    472         }
    473         break;
    474 
    475     case PM_FPA_FILE_SX:
    476     case PM_FPA_FILE_RAW:
    477     case PM_FPA_FILE_OBJ:
    478     case PM_FPA_FILE_CMP:
    479     case PM_FPA_FILE_CMF:
    480         // pmFPAviewFreeObjects (view, file);
    481         psTrace ("pmFPAfile", 5, "NOT freeing %s (type: %d)\n", file->filename, file->type);
    482         break;
    483 
    484         // XXX not certain what I need to free here
    485     case PM_FPA_FILE_PSF:
    486     case PM_FPA_FILE_JPEG:
    487         break;
    488 
    489     default:
    490         psError(PS_ERR_IO, true, "warning: type mismatch; saw type %d", file->type);
    491         return false;
    492     }
    493     return true;
    494 }
    495 
    496 bool pmFPAfileWrite(pmFPAfile *file, const pmFPAview *view)
    497 {
    498     PS_ASSERT_PTR_NON_NULL(file, false);
    499     PS_ASSERT_PTR_NON_NULL(view, false);
    500 
    501     if (file->state & PM_FPA_STATE_INACTIVE) {
    502         psTrace("pmFPAfile", 6, "skip write for %s, files is inactive", file->name);
    503         return true;
    504     }
    505 
    506     if (file->mode != PM_FPA_MODE_WRITE) {
    507         psTrace("pmFPAfile", 6, "skip write for %s, mode is not WRITE", file->name);
    508         return true;
    509     }
    510 
    511     // get the current depth
    512     pmFPAdepth depth = pmFPAviewDepth (view);
    513 
    514     // do we need to write this file?
    515     if (depth != file->dataDepth) {
    516         psTrace("pmFPAfile", 6, "skip writing of %s at this depth %s: dataDepth is %s",
    517                 file->name, depthEnumToName(depth), depthEnumToName(file->dataDepth));
    518         return true;
    519     }
    520 
    521     // do we need to open this file?
    522     if (depth >= file->fileDepth) {
    523         if (!pmFPAfileOpen (file, view)) {
    524             psError(PS_ERR_IO, false, "failed to open %s", file->filename);
    525             return false;
    526         }
    527     }
    528 
    529     switch (file->type) {
    530     case PM_FPA_FILE_IMAGE:
    531         pmFPAviewWriteFitsImage (view, file);
    532         psTrace ("pmFPAfile", 5, "wrote image %s (fpa: %p)\n", file->filename, file->fpa);
    533         break;
    534 
    535     case PM_FPA_FILE_SX:
    536     case PM_FPA_FILE_RAW:
    537     case PM_FPA_FILE_OBJ:
    538     case PM_FPA_FILE_CMP:
    539     case PM_FPA_FILE_CMF:
    540         psTrace ("pmFPAfile", 5, "writing object %s (fpa: %p)\n", file->filename, file->fpa);
    541         if (!pmFPAviewWriteObjects (view, file)) {
    542             psError(PS_ERR_IO, false, "Failed to write object %s", file->filename);
    543             return false;
    544         }
    545 
    546         break;
    547 
    548     case PM_FPA_FILE_PSF:
    549         pmFPAviewWritePSFmodel (view, file);
    550         psTrace ("pmFPAfile", 5, "wrote PSF %s (fpa: %p)\n", file->filename, file->fpa);
    551         break;
    552 
    553     case PM_FPA_FILE_JPEG:
    554         pmFPAviewWriteJPEG (view, file);
    555         psTrace ("pmFPAfile", 5, "wrote PSF %s (fpa: %p)\n", file->filename, file->fpa);
    556         break;
    557 
    558     default:
    559         fprintf (stderr, "warning: type mismatch\n");
    560         return false;
    561     }
    562     return true;
    563 }
    564 
    565 // create the data elements (headers, images) appropriate for this view
    566 bool pmFPAfileCreate (pmFPAfile *file, const pmFPAview *view)
    567 {
    568     PS_ASSERT_PTR_NON_NULL(file, false);
    569     PS_ASSERT_PTR_NON_NULL(view, false);
    570 
    571     // these are not error conditions; these are state tests
    572     if (file->state & PM_FPA_STATE_INACTIVE) {
    573         psTrace("pmFPAfile", 6, "skip create for inactive file %s", file->name);
    574         return true;
    575     }
    576     if (file->mode != PM_FPA_MODE_WRITE) {
    577         psTrace("pmFPAfile", 6, "skip create for non-write file %s", file->name);
    578         return true;
    579     }
    580 
    581     // get the current depth
    582     pmFPAdepth depth = pmFPAviewDepth (view);
    583 
    584     // don't create the file if the src FPA is not defined
    585     if (file->src == NULL) {
    586         psTrace("pmFPAfile", 6, "skip create for FPA without src FPA for %s", file->name);
    587         return true;
    588     }
    589 
    590     // do we need to write this file?
    591     if (depth != file->dataDepth) {
    592         psTrace("pmFPAfile", 6, "skip creation of %s at this depth %s: dataDepth is %s",
    593                 file->name, depthEnumToName(depth), depthEnumToName(file->dataDepth));
    594         return true;
    595     }
    596 
    597     switch (file->type) {
    598     case PM_FPA_FILE_IMAGE:
    599         /* create a PHU for thie file, if it does not exist */
    600         pmFPAfileCopyStructureView (file->fpa, file->src, file->format, file->xBin, file->yBin, view);
    601         psTrace ("pmFPAfile", 5, "created fpa data elements for %s (fpa: %p)\n", file->name, file->fpa);
    602         break;
    603 
    604     case PM_FPA_FILE_SX:
    605     case PM_FPA_FILE_RAW:
    606     case PM_FPA_FILE_OBJ:
    607     case PM_FPA_FILE_CMP:
    608     case PM_FPA_FILE_CMF:
    609     case PM_FPA_FILE_PSF:
    610     case PM_FPA_FILE_JPEG:
    611         break;
    612 
    613     default:
    614         psError(PS_ERR_IO, true, "Unsupported type for %s: %d", file->name, file->type);
    615         return false;
    616     }
    617     return true;
    618 }
    619 
    620 bool pmFPAfileClose (pmFPAfile *file, const pmFPAview *view)
    621 {
    622     PS_ASSERT_PTR_NON_NULL(file, false);
    623     PS_ASSERT_PTR_NON_NULL(view, false);
    624 
    625     if (file->state & PM_FPA_STATE_INACTIVE) {
    626         psTrace("pmFPAfile", 6, "skip close for %s, files is inactive", file->name);
    627         return true;
    628     }
    629     if (file->state == PM_FPA_STATE_CLOSED) {
    630         return true;
    631     }
    632 
    633     // is current depth == open depth?
    634     pmFPAdepth depth = pmFPAviewDepth (view);
    635     if (file->fileDepth != depth) {
    636         psTrace("pmFPAfile", 6, "skip closing of %s at this depth %s: dataDepth is %s",
    637                 file->name, depthEnumToName(depth), depthEnumToName(file->dataDepth));
    638         return true;
    639     }
    640 
    641     // check if we are actually open
    642     switch (file->type) {
    643         // check the FITS types
    644     case PM_FPA_FILE_IMAGE:
    645     case PM_FPA_FILE_CMF:
    646         psFitsClose (file->fits);
    647         psTrace ("pmFPAfile", 5, "closing %s (type: %d)\n", file->filename, file->type);
    648         file->fits = NULL;
    649         file->phu = NULL;
    650         file->header = NULL;
    651         file->state = PM_FPA_STATE_CLOSED;
    652         break;
    653 
    654         // ignore the TEXT types
    655     case PM_FPA_FILE_SX:
    656     case PM_FPA_FILE_RAW:
    657     case PM_FPA_FILE_OBJ:
    658     case PM_FPA_FILE_CMP:
    659     case PM_FPA_FILE_PSF:
    660     case PM_FPA_FILE_JPEG:
    661         break;
    662 
    663     default:
    664         psError(PS_ERR_IO, true, "type mismatch: %d", file->type);
    665         return false;
    666     }
    667     return true;
    668 }
    669 
    670 // set the state of the specified pmFPAfile to active (state == true) or inactive
    671 // if name is NULL, set the state for all pmFPAfiles
    672 bool pmFPAfileActivate (psMetadata *files, bool state, char *name)
    673 {
    674     PS_ASSERT_PTR_NON_NULL(files, false);
    675 
    676     if (!name) {
    677         psMetadataItem *item = NULL;
    678         psMetadataIterator *iter = psMetadataIteratorAlloc (files, PS_LIST_HEAD, NULL);
    679         while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
    680             pmFPAfile *file = item->data.V;
    681             if (state) {
    682                 file->state &= NOT_U8(PM_FPA_STATE_INACTIVE);
    683             } else {
    684                 file->state |= PM_FPA_STATE_INACTIVE;
    685             }
    686         }
    687         psFree (iter);
    688         return true;
    689     }
    690 
    691     bool status = false;
    692     pmFPAfile *file = psMetadataLookupPtr (&status, files, name);
    693     if (!status) {
    694         psTrace("pmFPAfile", 6, "%s is not a defined IO file", name);
    695         return false;
    696     }
    697     if (!file) {
    698         psError(PS_ERR_IO, true, "file %s is NULL", name);
    699         return false;
    700     }
    701     if (state) {
    702         file->state &= NOT_U8(PM_FPA_STATE_INACTIVE);
    703     } else {
    704         file->state |= PM_FPA_STATE_INACTIVE;
    705     }
    706     return true;
    707 }
    708 
    709 // attempt create, read, write, close, or free pmFPAfiles available in files
    710 // files are automatically opened before they are read
    711 bool pmFPAfileIOChecks (psMetadata *files, const pmFPAview *view, pmFPAfilePlace place)
    712 {
    713     PS_ASSERT_PTR_NON_NULL(files, false);
    714     PS_ASSERT_PTR_NON_NULL(view, false);
    715 
    716     bool status = true;
    717 
    718     // attempt to perform all create, read, write
    719     psMetadataItem *item = NULL;
    720     psMetadataIterator *iter = psMetadataIteratorAlloc (files, PS_LIST_HEAD, NULL);
    721     while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
    722         pmFPAfile *file = item->data.V;
    723 
    724         switch (place) {
    725         case PM_FPA_BEFORE:
    726             if (!pmFPAfileRead (file, view)) {
    727                 psError(PS_ERR_IO, false, "failed READ in FPA_BEFORE block for %s", file->name);
    728                 status = false;
    729             }
    730             if (!pmFPAfileCreate(file, view)) {
    731                 psError(PS_ERR_IO, false, "failed CREATE in FPA_BEFORE block for %s", file->name);
    732                 status = false;
    733             }
    734             break;
    735         case PM_FPA_AFTER:
    736             if (!pmFPAfileWrite (file, view)) {
    737                 psError(PS_ERR_IO, false, "failed WRITE in FPA_AFTER block for %s", file->name);
    738                 status = false;
    739             }
    740             if (!pmFPAfileClose(file, view)) {
    741                 psError(PS_ERR_IO, false, "failed CLOSE in FPA_AFTER block for %s", file->name);
    742                 status = false;
    743             }
    744             break;
    745         default:
    746             psAbort(PS_FILE_LINE, "You can't get here");
    747         }
    748     }
    749 
    750     // attempt to free data that is no longer needed
    751     psMetadataIteratorSet (iter, PS_LIST_HEAD);
    752     while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
    753         pmFPAfile *file = item->data.V;
    754 
    755         switch (place) {
    756         case PM_FPA_BEFORE:
    757             break;
    758         case PM_FPA_AFTER:
    759             if (!pmFPAfileFreeData(file, view)) {
    760                 psError(PS_ERR_IO, false, "failed FREE in FPA_AFTER block for %s", file->name);
    761                 status = false;
    762             }
    763             break;
    764         default:
    765             psAbort(PS_FILE_LINE, "You can't get here");
    766         }
    767     }
    768     psFree (iter);
    769     return status;
    770 }
    771 
    772 // create a file with the given name, assign it type "INTERNAL", and supply it with an image
    773 // of the requested dimensions. (image only, mask and weight are ignored)
    774 pmReadout *pmFPAfileCreateInternal (psMetadata *files, char *name, int Nx, int Ny, int type)
    775 {
    776     PS_ASSERT_PTR_NON_NULL(files, false);
    777     PS_ASSERT_PTR_NON_NULL(name, false);
    778     PS_ASSERT_INT_POSITIVE(strlen(name), false);
    779 
    780     pmReadout *readout = pmReadoutAlloc(NULL);
    781     readout->image = psImageAlloc(Nx, Ny, type);
    782 
    783     // I want an image from the
    784     pmFPAfile *file = pmFPAfileAlloc();
    785     file->mode = PM_FPA_MODE_INTERNAL;
    786     file->name = psStringCopy (name);
    787 
    788     file->readout = readout;
    789     psMetadataAddPtr(files, PS_LIST_TAIL, name, PS_DATA_UNKNOWN, "", file);
    790     psFree(file);
    791     // we free this copy of file, but 'files' still has a copy
    792 
    793     return readout;
    794 }
    795 
    796 bool pmFPAfileDropInternal(psMetadata *files, char *name)
    797 {
    798     PS_ASSERT_PTR_NON_NULL(files, false);
    799     PS_ASSERT_PTR_NON_NULL(name, false);
    800     PS_ASSERT_INT_POSITIVE(strlen(name), false);
    801 
    802     bool status = false;
    803 
    804     pmFPAfile *file = psMetadataLookupPtr (&status, files, name);
    805     if (!status) {
    806         psTrace("pmFPAfile", 6, "Internal File %s not in file list", name);
    807         return true;
    808     }
    809     if (file == NULL) {
    810         psError(PS_ERR_IO, true, "file %s is NULL", name);
    811         return false;
    812     }
    813     if (file->mode != PM_FPA_MODE_INTERNAL) {
    814         psTrace("pmFPAfile", 6, "FPA File %s not Internal, not dropping", name);
    815         return true;
    816     }
    817 
    818     psMetadataRemoveKey (files, name);
    819     return true;
    820 }
    821 
    82286// select the readout from the named pmFPAfile; if the named file does not exist,
    82387pmReadout *pmFPAfileThisReadout (psMetadata *files, const pmFPAview *view, const char *name)
     
    844108}
    845109
    846 // given an already-opened fits file, read the components corresponding
    847 // to the specified view
    848 bool pmFPAviewReadFitsImage (const pmFPAview *view, pmFPAfile *file)
    849 {
    850     PS_ASSERT_PTR_NON_NULL(view, false);
    851     PS_ASSERT_PTR_NON_NULL(file, false);
    852 
    853     bool status;
    854     pmFPA *fpa = file->fpa;
    855     psFits *fits = file->fits;
    856 
    857     if (view->chip == -1) {
    858         status = pmFPARead (fpa, fits, NULL);
    859         return status;
    860     }
    861 
    862     if (view->chip >= fpa->chips->n) {
    863         psError(PS_ERR_IO, true, "Requested chip == %d >= fpa->chips->n == %d", view->chip, fpa->chips->n);
    864         return false;
    865     }
    866     pmChip *chip = fpa->chips->data[view->chip];
    867 
    868     if (view->cell == -1) {
    869         status = pmChipRead (chip, fits, NULL);
    870         return status;
    871     }
    872 
    873     if (view->cell >= chip->cells->n) {
    874         psError(PS_ERR_IO, true, "Requested cell == %d >= chip->cells->n == %d", view->cell, chip->cells->n);
    875         return false;
    876     }
    877     pmCell *cell = chip->cells->data[view->cell];
    878 
    879     if (view->readout == -1) {
    880         status = pmCellRead (cell, fits, NULL);
    881         return status;
    882     }
    883     psError(PS_ERR_UNKNOWN, true, "Returning false");
    884     return false;
    885 
    886     // XXX pmReadoutRead, pmReadoutReadSegement disabled for now
    887     #if 0
    888 
    889     if (view->readout >= cell->readouts->n) {
    890         psError(PS_ERR_IO, true, "Requested readout == %d >= cell->readouts->n == %d",
    891                 view->readout, cell->readouts->n);
    892         return false;
    893     }
    894     pmReadout *readout = cell->readouts->data[view->readout];
    895 
    896     if (view->nRows == 0) {
    897         pmReadoutRead (readout, fits, NULL);
    898     } else {
    899         pmReadoutReadSegment (readout, fits, view->nRows, view->iRows, NULL, NULL);
    900     }
    901     return true;
    902     #endif
    903 }
    904 
    905 // given an already-opened fits file, read the components corresponding
    906 // to the specified view
    907 bool pmFPAviewFreeFitsImage (const pmFPAview *view, pmFPAfile *file)
    908 {
    909     PS_ASSERT_PTR_NON_NULL(view, false);
    910     PS_ASSERT_PTR_NON_NULL(file, false);
    911 
    912     pmFPA *fpa = file->fpa;
    913 
    914     if (view->chip == -1) {
    915         psTrace ("pmFPAfile", 5, "freeing fpa for %s\n", file->filename);
    916         psFree (fpa);
    917         file->fpa = NULL;
    918         return true;
    919     }
    920 
    921     if (view->chip >= fpa->chips->n) {
    922         psError(PS_ERR_IO, true, "Requested chip == %d >= fpa->chips->n == %d", view->chip, fpa->chips->n);
    923         return false;
    924     }
    925     pmChip *chip = fpa->chips->data[view->chip];
    926 
    927     if (view->cell == -1) {
    928         psTrace ("pmFPAfile", 5, "freeing chip %d for %s\n", view->chip, file->filename);
    929         psFree (chip);
    930         fpa->chips->data[view->chip] = NULL;
    931         return true;
    932     }
    933 
    934     if (view->cell >= chip->cells->n) {
    935         psError(PS_ERR_IO, true, "Requested cell == %d >= chip->cells->n == %d", view->cell, chip->cells->n);
    936         return false;
    937     }
    938     pmCell *cell = chip->cells->data[view->cell];
    939 
    940     if (view->readout == -1) {
    941         psTrace ("pmFPAfile", 5, "freeing cell %d for %s\n", view->cell, file->filename);
    942         psFree (cell);
    943         chip->cells->data[view->cell] = NULL;
    944         return true;
    945     }
    946     psError(PS_ERR_UNKNOWN, true, "Returning false");
    947     return false;
    948 
    949     // XXX pmReadoutRead, pmReadoutReadSegement disabled for now
    950     #if 0
    951 
    952     if (view->readout >= cell->readouts->n) {
    953         psError(PS_ERR_IO, true, "Requested readout == %d >= cell->readouts->n == %d",
    954                 view->readout, cell->readouts->n);
    955         return false;
    956     }
    957     pmReadout *readout = cell->readouts->data[view->readout];
    958 
    959     if (view->nRows == 0) {
    960         pmReadoutRead (readout, fits, NULL);
    961     } else {
    962         pmReadoutReadSegment (readout, fits, view->nRows, view->iRows, NULL, NULL);
    963     }
    964     return true;
    965     #endif
    966 }
    967 
    968 // given an already-opened fits file, write the components corresponding
    969 // to the specified view
    970 bool pmFPAviewWriteFitsImage (const pmFPAview *view, pmFPAfile *file)
    971 {
    972     PS_ASSERT_PTR_NON_NULL(view, false);
    973     PS_ASSERT_PTR_NON_NULL(file, false);
    974 
    975     pmFPA *fpa = file->fpa;
    976     psFits *fits = file->fits;
    977 
    978     // pmFPAWrite takes care of all PHUs as needed
    979     if (view->chip == -1) {
    980         pmFPAWrite(fpa, fits, NULL, true, true);
    981         return true;
    982     }
    983 
    984     if (view->chip >= fpa->chips->n) {
    985         psError(PS_ERR_IO, true, "Requested chip == %d >= fpa->chips->n == %d", view->chip, fpa->chips->n);
    986         return false;
    987     }
    988     pmChip *chip = fpa->chips->data[view->chip];
    989 
    990     // do we need to write out a PHU for this entry?
    991     if (file->phu == NULL) {
    992         pmHDU *hdu = pmFPAviewThisHDU (view, file->fpa);
    993         pmHDU *phu = pmFPAviewThisPHU (view, file->fpa);
    994         // if this hdu is the phu, the write function below will create the phu
    995         if (hdu != phu) {
    996             // we assume that the PHU is just a header
    997             psMetadata *outhead = psMetadataCopy (NULL, phu->header);
    998             psMetadataAdd (outhead, PS_LIST_TAIL, "EXTEND", PS_DATA_BOOL | PS_META_REPLACE, "this file has extensions", true);
    999             psFitsWriteBlank (file->fits, outhead);
    1000             file->phu = phu->header;
    1001             psTrace ("pmFPAfile", 5, "wrote phu %s (type: %d)\n", file->filename, file->type);
    1002             psFree (outhead);
    1003         }
    1004     }
    1005 
    1006     if (view->cell == -1) {
    1007         pmChipWrite (chip, fits, NULL, true, true);
    1008         return true;
    1009     }
    1010 
    1011     if (view->cell >= chip->cells->n) {
    1012         psError(PS_ERR_IO, true, "Requested cell == %d >= chip->cells->n == %d", view->cell, chip->cells->n);
    1013         return false;
    1014     }
    1015     pmCell *cell = chip->cells->data[view->cell];
    1016 
    1017     if (view->readout == -1) {
    1018         return pmCellWrite (cell, fits, NULL, true);
    1019     }
    1020     psError(PS_ERR_UNKNOWN, true, "Returning false");
    1021     return false;
    1022 
    1023     // XXX disable readout write for now
    1024     #if 0
    1025 
    1026     if (view->readout >= cell->readouts->n) {
    1027         psError(PS_ERR_IO, true, "Requested readout == %d >= cell->readouts->n == %d",
    1028                 view->readout, cell->readouts->n);
    1029         return false;
    1030     }
    1031     pmReadout *readout = cell->readouts->data[view->readout];
    1032 
    1033     if (view->nRows == 0) {
    1034         pmReadoutWrite (readout, fits, NULL, NULL);
    1035     } else {
    1036         pmReadoutWriteSegment (readout, fits, view->nRows, view->iRows, NULL, NULL);
    1037     }
    1038     return true;
    1039     #endif
    1040 }
    1041 
    1042 // look for the given name on the argument list.
    1043 // returns the file (a view to the one saved on config->files)
    1044 pmFPAfile *pmFPAfileFromArgs (bool *found, pmConfig *config, char *filename, char *argname)
    1045 {
    1046     PS_ASSERT_PTR_NON_NULL(config, false);
    1047     PS_ASSERT_PTR_NON_NULL(filename, false);
    1048     PS_ASSERT_INT_POSITIVE(strlen(filename), false);
    1049     PS_ASSERT_PTR_NON_NULL(argname, false);
    1050     PS_ASSERT_INT_POSITIVE(strlen(argname), false);
    1051 
    1052     bool status;
    1053     pmFPA *fpa = NULL;
    1054     psFits *fits = NULL;
    1055     pmFPAfile *file = NULL;
    1056     psMetadata *phu = NULL;
    1057     psMetadata *format = NULL;
    1058 
    1059     if (*found) {
    1060         return NULL;
    1061     }
    1062 
    1063     // we search the argument data for the named fileset (argname)
    1064     psArray *infiles = psMetadataLookupPtr(&status, config->arguments, argname);
    1065     if (!status) {
    1066         psTrace("pmFPAfile", 5, "Failed to find %s in argument list", argname);
    1067         return NULL;
    1068     }
    1069     if (infiles->n < 1) {
    1070         psError(PS_ERR_IO, false, "Found n == %d files in %s in arguments\n", infiles->n, argname);
    1071         return NULL;
    1072     }
    1073 
    1074     // determine the current format from the header
    1075     // if no camera has been specified, use the first image as a template for the rest.
    1076     fits = psFitsOpen (infiles->data[0], "r");
    1077     phu = psFitsReadHeader (NULL, fits);
    1078     format = pmConfigCameraFormatFromHeader (config, phu);
    1079     psFitsClose (fits);                        // don't close phu; we'll use it below
    1080     if (!format) {
    1081         psError(PS_ERR_IO, false, "Failed to read CCD format from %s\n", infiles->data[0]);
    1082         psFree(phu);
    1083         return NULL;
    1084     }
    1085 
    1086     // build the template fpa, set up the basic view
    1087     fpa = pmFPAConstruct (config->camera);
    1088     if (!fpa) {
    1089         psError(PS_ERR_IO, false, "Failed to construct FPA from %s", infiles->data[0]);
    1090         return NULL;
    1091     }
    1092 
    1093     // load the given filerule (from config->camera) and associate it with the fpa
    1094     // the output file is just a view to the file on config->files
    1095     file = pmFPAfileDefine (config->files, config->camera, fpa, filename);
    1096     if (!file) {
    1097         psError(PS_ERR_IO, false, "file %s not defined", filename);
    1098         psFree(phu);
    1099         psFree (fpa);
    1100         psFree (format);
    1101         return NULL;
    1102     }
    1103 
    1104     // this file is (by virtue of being supplied in the argument list) coming from the fileset
    1105     psFree (file->filerule);
    1106     psFree (file->filextra);
    1107 
    1108     // adjust the rules to identify these files in the file->names data
    1109     file->filerule = psStringCopy ("@FILES");
    1110     // XXX this rule does not work in general
    1111     file->filextra = psStringCopy ("{CHIP.NAME}.{CELL.NAME}");
    1112 
    1113     // examine the list of input files and validate their cameras
    1114     for (int i = 0; i < infiles->n; i++) {
    1115         if (i > 0) {
    1116             fits = psFitsOpen (infiles->data[i], "r");
    1117             phu = psFitsReadHeader (NULL, fits);
    1118             pmConfigValidateCameraFormat (format, phu);
    1119             psFitsClose (fits);
    1120         }
    1121 
    1122         // set the view to the corresponding entry for this phu
    1123         pmFPAview *view = pmFPAAddSourceFromHeader (fpa, phu, format);
    1124         if (!view) {
    1125             psError(PS_ERR_IO, false, "Failed to set view from file %s", infiles->data[i]);
    1126             psFree(phu);
    1127             psFree (fpa);
    1128             psFree (format);
    1129             return NULL;
    1130         }
    1131 
    1132         // XXX is this the correct psMD to save the filename?
    1133         char *name = pmFPAfileNameFromRule (file->filextra, file, view);
    1134         psMetadataAddStr (file->names, PS_LIST_TAIL, name, 0, "", infiles->data[i]);
    1135 
    1136         psFree (view);
    1137         psFree (name);
    1138         psFree (phu);
    1139     }
    1140     psFree (fpa);
    1141     psFree (format);
    1142     *found = true;
    1143 
    1144     return file;
    1145 }
    1146 
    1147 // XXX this this function through, then finish
    1148 #if 0
    1149 // look for the given name on the argument list.
    1150 // returns the file (a view to the one saved on config->files)
    1151 // in this case, each file should correspond to the same view
    1152 // (except at the readout level), of multiple FPAs
    1153 // XXX think this through a bit more:
    1154 //  - do we create multiple input fpas, or assign the same files to the single fpa?
    1155 //  - do we save the multiple pmFPAfiles in the config->files psMD?
    1156 //  - do we save the multiple filenames in the file->names psMD?
    1157 //  - if we have a single FPA and multiple names, we need a method to
    1158 //    turn on a specific name for the I/O actions.  probably true if we
    1159 //    have multiple FPAs as well.
    1160 pmFPAfile *pmFPAfileSetFromArgs (bool *found, pmConfig *config, char *filename, char *argname)
    1161 {
    1162     PS_ASSERT_PTR_NON_NULL(config, false);
    1163     PS_ASSERT_PTR_NON_NULL(filename, false);
    1164     PS_ASSERT_INT_POSITIVE(strlen(filename), false);
    1165     PS_ASSERT_PTR_NON_NULL(argname, false);
    1166     PS_ASSERT_INT_POSITIVE(strlen(argname), false);
    1167 
    1168     bool status;
    1169     pmFPA *fpa = NULL;
    1170     psFits *fits = NULL;
    1171     pmFPAfile *file = NULL;
    1172     psMetadata *phu = NULL;
    1173     psMetadata *format = NULL;
    1174 
    1175     if (*found)
    1176         return NULL;
    1177 
    1178     // we search the argument data for the named fileset (argname)
    1179     psArray *infiles = psMetadataLookupPtr(&status, config->arguments, argname);
    1180     if (!status) {
    1181         return NULL;
    1182     }
    1183     if (infiles->n < 1) {
    1184         return NULL;
    1185     }
    1186 
    1187     // determine the current format from the header
    1188     // if no camera has been specified, use the first image as a template for the rest.
    1189     fits = psFitsOpen (infiles->data[0], "r");
    1190     phu = psFitsReadHeader (NULL, fits);
    1191     format = pmConfigCameraFormatFromHeader (config, phu);
    1192     psFitsClose (fits);
    1193 
    1194     // build the template fpa, set up the basic view
    1195     fpa = pmFPAConstruct (config->camera);
    1196 
    1197     // load the given filerule (from config->camera) and associate it with the fpa
    1198     // the output file is just a view to the file on config->files
    1199     // XXX the filenames placed on config->files should include the seq number
    1200     file = pmFPAfileDefine (config->files, config->camera, fpa, filename);
    1201     if (!file) {
    1202         psError(PS_ERR_IO, false, "file %s not defined", filename);
    1203         psFree (fpa);
    1204         psFree (format);
    1205         return NULL;
    1206     }
    1207 
    1208     // this file is (by virtue of being supplied in the argument list) coming from the fileset
    1209     psFree (file->filerule);
    1210     psFree (file->filextra);
    1211 
    1212     // adjust the rules to identify these files in the file->names data
    1213     file->filerule = psStringCopy ("@FILES");
    1214     // XXX this rule does not work in general
    1215     file->filextra = psStringCopy ("{CHIP.NAME}.{CELL.NAME}");
    1216 
    1217     // examine the list of input files and validate their cameras
    1218     for (int i = 0; i < infiles->n; i++) {
    1219         if (i > 0) {
    1220             fits = psFitsOpen (infiles->data[i], "r");
    1221             phu = psFitsReadHeader (NULL, fits);
    1222             pmConfigValidateCameraFormat (format, phu);
    1223             psFitsClose (fits);
    1224         }
    1225 
    1226         // set the view to the corresponding entry for this phu
    1227         pmFPAview *view = pmFPAAddSourceFromHeader (fpa, phu, format);
    1228 
    1229         // XXX is this the correct psMD to save the filename?
    1230         char *name = pmFPAfileNameFromRule (file->filextra, file, view);
    1231         psMetadataAddStr (file->names, PS_LIST_TAIL, name, 0, "", infiles->data[i]);
    1232 
    1233         psFree (view);
    1234         psFree (name);
    1235         psFree (phu);
    1236     }
    1237     psFree (fpa);
    1238     psFree (format);
    1239     *found = true;
    1240 
    1241     return file;
    1242 }
    1243 #endif
    1244 
    1245 // create a new output pmFPAfile based on an existing FPA
    1246 pmFPAfile *pmFPAfileFromFPA (pmConfig *config, pmFPA *src, int xBin, int yBin, char *filename)
    1247 {
    1248     PS_ASSERT_PTR_NON_NULL(config, false);
    1249     PS_ASSERT_PTR_NON_NULL(src, false);
    1250     PS_ASSERT_PTR_NON_NULL(filename, false);
    1251     PS_ASSERT_INT_POSITIVE(strlen(filename), false);
    1252 
    1253     // XXX pmFPAConstruct has many leaks (6919)
    1254     pmFPA *fpa = pmFPAConstruct (config->camera);
    1255     pmFPAfile *file = pmFPAfileDefine (config->files, config->camera, fpa, filename);
    1256     if (!file) {
    1257         psErrorStackPrint(stderr, "file %s not defined\n", filename);
    1258         return NULL;
    1259     }
    1260     file->src = src; // inherit output elements from this source pmFPA
    1261     file->xBin = xBin;
    1262     file->yBin = yBin;
    1263 
    1264     psFree (fpa);
    1265     return file;
    1266 }
    1267 
    1268 // look for the given name on the argument list.
    1269 pmFPAfile *pmFPAfileFromConf (bool *found, pmConfig *config, char *filename, pmFPA *input)
    1270 {
    1271     PS_ASSERT_PTR_NON_NULL(config, false);
    1272     PS_ASSERT_PTR_NON_NULL(filename, false);
    1273     PS_ASSERT_INT_POSITIVE(strlen(filename), false);
    1274     PS_ASSERT_PTR_NON_NULL(input, false);
    1275 
    1276     psFits *fits = NULL;
    1277     pmFPAfile *file = NULL;
    1278     psMetadata *phu = NULL;
    1279     psMetadata *format = NULL;
    1280     psArray *infiles = NULL;
    1281 
    1282     if (*found) {
    1283         return NULL;
    1284     }
    1285 
    1286     // a camera config is needed (as source of file rule)
    1287     if (config->camera == NULL) {
    1288         psErrorStackPrint (stderr, "camera is not defined\n");
    1289         return NULL;
    1290     }
    1291 
    1292     // expect @DETDB in the config filerule
    1293     file = pmFPAfileDefine (config->files, config->camera, NULL, filename);
    1294     if (!file) {
    1295         psError(PS_ERR_IO, false, "file %s not defined\n", filename);
    1296         return NULL;
    1297     }
    1298 
    1299     // image names come from the file->name list?
    1300     if (!strcasecmp (file->filerule, "@FILES")) {
    1301         psAbort ("pmFPAfileFromConfig", "programming error");
    1302     }
    1303 
    1304     // image needs to come from the detrend database
    1305     if (!strcasecmp (file->filerule, "@DETDB")) {
    1306         // char *extra = pmFPAfileNameFromRule (file->filextra, file, view);
    1307         // psArray *infiles = pmDetrendSelect (extra, input);
    1308         psAbort ("pmFPAfileFromConfig", "programming error: @DETDB not yet defined");
    1309     } else {
    1310         infiles = psArrayAlloc(1);
    1311         infiles->n = 1;
    1312         infiles->data[0] = psStringCopy (file->filerule);
    1313     }
    1314     if (infiles == NULL) {
    1315         return NULL;
    1316     }
    1317     if (infiles->n < 1) {
    1318         psFree (infiles);
    1319         return NULL;
    1320     }
    1321 
    1322     // determine the current format from the header
    1323     // if no camera has been specified, use the first image as a template for the rest.
    1324     fits = psFitsOpen (infiles->data[0], "r");
    1325     phu = psFitsReadHeader (NULL, fits);
    1326     format = pmConfigCameraFormatFromHeader (config, phu);
    1327     psFitsClose (fits);
    1328 
    1329     // build the template fpa, set up the basic view
    1330     file->fpa = pmFPAConstruct (config->camera);
    1331 
    1332     // this file is (by virtue of being supplied in the argument list) coming from the fileset
    1333     psFree (file->filerule);
    1334     psFree (file->filextra);
    1335 
    1336     // adjust the rules to identify these files in the file->names data
    1337     file->filerule = psStringCopy ("@FILES");
    1338     // XXX this rule does not work in general
    1339     file->filextra = psStringCopy ("{CHIP.NAME}.{CELL.NAME}");
    1340 
    1341     // examine the list of input files and validate their cameras
    1342     for (int i = 0; i < infiles->n; i++) {
    1343         if (i > 0) {
    1344             fits = psFitsOpen (infiles->data[i], "r");
    1345             phu = psFitsReadHeader (NULL, fits);
    1346             pmConfigValidateCameraFormat (format, phu);
    1347             psFitsClose (fits);
    1348         }
    1349 
    1350         // set the view to the corresponding entry for this phu
    1351         pmFPAview *view = pmFPAAddSourceFromHeader (file->fpa, phu, format);
    1352         if (!view) {
    1353             psError(PS_ERR_IO, false, "Unable to determine source for %s", file->name);
    1354             return NULL;
    1355         }
    1356 
    1357         // XXX is this the correct psMD to save the filename?
    1358         char *name = pmFPAfileNameFromRule (file->filextra, file, view);
    1359         psMetadataAddStr (file->names, PS_LIST_TAIL, name, 0, "", infiles->data[i]);
    1360 
    1361         psFree (view);
    1362         psFree (name);
    1363         psFree (phu);
    1364     }
    1365     psFree (format);
    1366     psFree (infiles);
    1367     *found = true;
    1368     return file;
    1369 }
    1370 
     110// XXX reconsider this function name / concept
    1371111bool pmFPAfileAddFileNames (psMetadata *files, char *name, char *value, int mode)
    1372112{
Note: See TracChangeset for help on using the changeset viewer.