IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Mar 27, 2007, 10:49:57 AM (19 years ago)
Author:
magnier
Message:

added wrote_phu to pmFPA, etc; added test in WritePHU

Location:
trunk/psModules/src/camera
Files:
5 edited

Legend:

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

    r11676 r12603  
    277277    tmpCell->file_exists = false;       // Not yet identified
    278278    tmpCell->data_exists = false;       // Not yet read in
     279    tmpCell->wrote_phu = false;
    279280
    280281    tmpCell->concepts = psMetadataAlloc();
     
    311312    tmpChip->file_exists = false;       // Not yet identified
    312313    tmpChip->data_exists = false;       // Not yet read in
     314    tmpChip->wrote_phu = false;
    313315
    314316    tmpChip->concepts = psMetadataAlloc();
     
    337339    tmpFPA->chips = psArrayAlloc(0);
    338340    tmpFPA->hdu = NULL;
     341    tmpFPA->wrote_phu = false;
    339342
    340343    tmpFPA->concepts = psMetadataAlloc();
  • trunk/psModules/src/camera/pmFPA.h

    r11253 r12603  
    66 * @author Eugene Magnier, IfA
    77 *
    8  * @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
    9  * @date $Date: 2007-01-24 02:54:14 $
     8 * @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
     9 * @date $Date: 2007-03-27 20:49:57 $
    1010 * Copyright 2005-2006 Institute for Astronomy, University of Hawaii
    1111 */
     
    4444    psArray *chips;                     ///< The component chips
    4545    pmHDU *hdu;                         ///< FITS header data unit of interest, or NULL
     46    bool wrote_phu;                     ///< Have we written a PHU at this level? (write case only)
    4647}
    4748pmFPA;
     
    7172    bool data_exists;                   ///< Does the data for this chip exist (read case only)?
    7273    pmHDU *hdu;                         ///< FITS header data unit of interest,
     74    bool wrote_phu;                     ///< Have we written a PHU at this level? (write case only)
    7375}
    7476pmChip;
     
    103105    bool data_exists;                   ///< Does the data for this cell exist (read case only)?
    104106    pmHDU *hdu;                         ///< FITS header data unit of interest
     107    bool wrote_phu;                     ///< Have we written a PHU at this level? (write case only)
    105108}
    106109pmCell;
  • trunk/psModules/src/camera/pmFPAfileDefine.c

    r12557 r12603  
    930930
    931931    if (config->cameraName[0] == '_' &&
    932             strcmp(config->cameraName + strlen(config->cameraName) - 5, "-CHIP") == 0) {
     932        strcmp(config->cameraName + strlen(config->cameraName) - 5, "-CHIP") == 0) {
    933933        // The input camera has already been mosaicked to this level
    934934        pmFPAfile *file = pmFPAfileDefineOutput(config, NULL, filename);
  • trunk/psModules/src/camera/pmFPAfileFitsIO.c

    r11864 r12603  
    7676        psFree(copy);
    7777        psFree(phuView);
    78         return false;
     78        return NULL;
    7979    }
    8080    psFree(phuView);
     81
     82    // preserve this state variable
     83    copy->wrote_phu = file->fpa->wrote_phu;
    8184
    8285    switch (level) {
  • trunk/psModules/src/camera/pmFPAfileIO.c

    r12590 r12603  
    3131#include "pmDetrendDB.h"
    3232
    33 // XXXX should we require this function to be called only within pmFPAfileRead or pmFPAfileWrite?
    34 // open file (if not already opened)
     33// attempt create, read, write, close, or free pmFPAfiles available in files files are
     34// automatically opened before they are read.  In the case of MEF files, the PHU is
     35// read when the file is opened and written before the first extension is written.
     36bool pmFPAfileIOChecks (pmConfig *config, const pmFPAview *view, pmFPAfilePlace place)
     37{
     38    PS_ASSERT_PTR_NON_NULL(config, false);
     39    PS_ASSERT_PTR_NON_NULL(config->files, false);
     40    PS_ASSERT_PTR_NON_NULL(view, false);
     41
     42    psMetadata *files = config->files;
     43
     44    // attempt to perform all create, read, write, close operations
     45    psMetadataItem *item = NULL;
     46    psMetadataIterator *iter = psMetadataIteratorAlloc (files, PS_LIST_HEAD, NULL);
     47    while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
     48        pmFPAfile *file = item->data.V;
     49
     50        switch (place) {
     51        case PM_FPA_BEFORE:
     52            if (!pmFPAfileRead (file, view, config)) {
     53                psError(PS_ERR_IO, false, "failed READ in FPA_BEFORE block for %s", file->name);
     54                goto failure;
     55            }
     56            if (!pmFPAfileCreate(file, view, config)) {
     57                psError(PS_ERR_IO, false, "failed CREATE in FPA_BEFORE block for %s", file->name);
     58                goto failure;
     59            }
     60            break;
     61        case PM_FPA_AFTER:
     62            if (!pmFPAfileWrite (file, view, config)) {
     63                psError(PS_ERR_IO, false, "failed WRITE in FPA_AFTER block for %s", file->name);
     64                goto failure;
     65            }
     66            if (!pmFPAfileClose(file, view)) {
     67                psError(PS_ERR_IO, false, "failed CLOSE in FPA_AFTER block for %s", file->name);
     68                goto failure;
     69            }
     70            break;
     71        default:
     72            psAbort("You can't get here");
     73        }
     74    }
     75
     76    // attempt to free data that is no longer needed
     77    psMetadataIteratorSet (iter, PS_LIST_HEAD);
     78    while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
     79        pmFPAfile *file = item->data.V;
     80
     81        switch (place) {
     82        case PM_FPA_BEFORE:
     83            break;
     84        case PM_FPA_AFTER:
     85            if (!pmFPAfileFreeData(file, view)) {
     86                if (!psMetadataRemoveKey(files, file->name)) {
     87                    psError(PS_ERR_IO, false, "failed to remove %s in FPA_AFTER block", file->name);
     88                    goto failure;
     89                }
     90            }
     91            break;
     92        default:
     93            psAbort("You can't get here");
     94        }
     95    }
     96    psFree (iter);
     97    return true;
     98
     99failure:
     100    psFree (iter);
     101    return false;
     102}
     103
     104// read the file, if necessary and possible
     105bool pmFPAfileRead(pmFPAfile *file, const pmFPAview *view, pmConfig *config)
     106{
     107    PS_ASSERT_PTR_NON_NULL(file, false);
     108    PS_ASSERT_PTR_NON_NULL(view, false);
     109
     110    // an internal file should not be sent here (should not be left on config->files)
     111    PS_ASSERT(file->mode != PM_FPA_MODE_INTERNAL, false);
     112
     113    // skip the following states
     114    if (file->state & PM_FPA_STATE_INACTIVE) {
     115        psTrace("psModules.camera", 6, "skip read for %s, file is inactive", file->name);
     116        return true;
     117    }
     118    if (file->mode != PM_FPA_MODE_READ) {
     119        psTrace("psModules.camera", 6, "skip read for %s, mode is not READ", file->name);
     120        return true;
     121    }
     122
     123    // get the current level
     124    pmFPALevel level = pmFPAviewLevel (view);
     125
     126    // do we need to read this file? defer until we read the correct level
     127    if (level != file->dataLevel) {
     128        psTrace("psModules.camera", 6, "skip reading of %s at this level %s: dataLevel is %s",
     129                file->name, pmFPALevelToName(level), pmFPALevelToName(file->dataLevel));
     130        return true;
     131    }
     132
     133    // do we need to open this file?
     134    if (level >= file->fileLevel) {
     135        // we are allowed to open a file at a level which is not the fileLevel, but we need to
     136        // supply a view at the fileLevel for the file lookup functions below
     137        pmFPAview *fileView = pmFPAviewForLevel (file->fileLevel, view);
     138        if (!pmFPAfileOpen (file, fileView, config)) {
     139            psError(PS_ERR_IO, false, "failed to open file %s (%s)", file->filename, file->name);
     140            psFree (fileView);
     141            return false;
     142        }
     143        psFree (fileView);
     144    }
     145
     146    // We need to read it --- double-check it's open!
     147    if (file->state == PM_FPA_STATE_CLOSED) {
     148        psError(PS_ERR_IO, false, "failed to open file %s when attempting to read", file->name);
     149        return false;
     150    }
     151
     152    // select a reading method
     153    bool status = true;
     154    switch (file->type) {
     155      case PM_FPA_FILE_IMAGE:
     156        status = pmFPAviewReadFitsImage(view, file);
     157        break;
     158      case PM_FPA_FILE_MASK:
     159        status = pmFPAviewReadFitsMask(view, file);
     160        break;
     161      case PM_FPA_FILE_WEIGHT:
     162        status = pmFPAviewReadFitsWeight(view, file);
     163        break;
     164      case PM_FPA_FILE_HEADER:
     165        status = pmFPAviewReadFitsHeaderSet(view, file);
     166        break;
     167      case PM_FPA_FILE_FRINGE:
     168        status = pmFPAviewReadFitsImage (view, file);
     169        if (status) {
     170            if (!pmFPAviewReadFitsTable(view, file, "FRINGE")) {
     171                psError(PS_ERR_UNKNOWN, false, "Unable to read fringe data from %s.\n", file->filename);
     172                return false;
     173            }
     174        }
     175        break;
     176      case PM_FPA_FILE_SX:
     177      case PM_FPA_FILE_RAW:
     178      case PM_FPA_FILE_OBJ:
     179      case PM_FPA_FILE_CMP:
     180      case PM_FPA_FILE_CMF:
     181        status = pmFPAviewReadObjects (view, file, config);
     182        break;
     183      case PM_FPA_FILE_PSF:
     184        status = pmFPAviewReadPSFmodel (view, file, config);
     185        break;
     186      case PM_FPA_FILE_JPEG:
     187      case PM_FPA_FILE_KAPA:
     188        break;
     189      default:
     190        psError(PS_ERR_IO, true, "warning: type mismatch; saw type %d (%s)", file->type, file->name);
     191        return false;
     192    }
     193    if (!status) {
     194        psError(PS_ERR_UNKNOWN, false, "failed to read %s (%s)\n", file->filename, file->name);
     195        return false;
     196    }
     197    psTrace ("psModules.camera", 5, "read %s (%s)\n", file->filename, file->name);
     198    return true;
     199}
     200
     201// create the data elements (headers, images) appropriate for this view
     202bool pmFPAfileCreate (pmFPAfile *file, const pmFPAview *view, const pmConfig *config)
     203{
     204    PS_ASSERT_PTR_NON_NULL(file, false);
     205    PS_ASSERT_PTR_NON_NULL(view, false);
     206
     207    // these are not error conditions; these are state tests
     208    if (file->state & PM_FPA_STATE_INACTIVE) {
     209        psTrace("psModules.camera", 6, "skip create for inactive file %s", file->name);
     210        return true;
     211    }
     212    if (file->mode != PM_FPA_MODE_WRITE) {
     213        psTrace("psModules.camera", 6, "skip create for non-write file %s", file->name);
     214        return true;
     215    }
     216
     217    // an internal file should not be returned to here
     218    PS_ASSERT(file->mode != PM_FPA_MODE_INTERNAL, false);
     219
     220    // get the current level
     221    pmFPALevel level = pmFPAviewLevel (view);
     222
     223    // don't create the file if the src (FPA) is not defined
     224    if (file->src == NULL) {
     225        psTrace("psModules.camera", 6, "skip create for FPA without src FPA for %s", file->name);
     226        return true;
     227    }
     228
     229    // do we need to write this file?
     230    if (level != file->fileLevel || file->mosaicLevel != PM_FPA_LEVEL_NONE) {
     231        psTrace("psModules.camera", 6, "skip creation of %s at this level %s: fileLevel is %s",
     232                file->name, pmFPALevelToName(level), pmFPALevelToName(file->fileLevel));
     233        return true;
     234    }
     235
     236    switch (file->type) {
     237    case PM_FPA_FILE_IMAGE:
     238    case PM_FPA_FILE_MASK:
     239    case PM_FPA_FILE_WEIGHT:
     240    case PM_FPA_FILE_FRINGE: {
     241            // create FPA structure component based on view
     242            psMetadata *format = file->format; // Camera format configuration
     243            if (!format) {
     244                format = config->format;
     245            }
     246
     247            pmFPA *nameSource = file->src; // Source of FPA.NAME
     248            if (!nameSource) {
     249                nameSource = file->fpa;
     250            }
     251            bool mdok;                  // Status of MD lookup
     252            const char *fpaname = psMetadataLookupStr(&mdok, nameSource->concepts, "FPA.NAME"); // Name of FPA
     253
     254            pmFPAAddSourceFromView(file->fpa, fpaname, view, format);
     255            psTrace ("psModules.camera", 5, "created fpa data elements for %s (fpa: %p)\n", file->name, file->fpa);
     256            break;
     257    }
     258    case PM_FPA_FILE_HEADER:
     259      psAbort ("Create not defined for HEADER");
     260      break;
     261    case PM_FPA_FILE_SX:
     262    case PM_FPA_FILE_RAW:
     263    case PM_FPA_FILE_OBJ:
     264    case PM_FPA_FILE_CMP:
     265    case PM_FPA_FILE_CMF:
     266    case PM_FPA_FILE_PSF:
     267    case PM_FPA_FILE_JPEG:
     268    case PM_FPA_FILE_KAPA:
     269        break;
     270
     271    default:
     272        psError(PS_ERR_IO, true, "Unsupported type for %s: %d", file->name, file->type);
     273        return false;
     274    }
     275    return true;
     276}
     277
     278bool pmFPAfileWrite(pmFPAfile *file, const pmFPAview *view, pmConfig *config)
     279{
     280    PS_ASSERT_PTR_NON_NULL(file, false);
     281    PS_ASSERT_PTR_NON_NULL(view, false);
     282
     283    if (file->state & PM_FPA_STATE_INACTIVE) {
     284        psTrace("psModules.camera", 6, "skip write for %s, files is inactive", file->name);
     285        return true;
     286    }
     287
     288    if (file->mode != PM_FPA_MODE_WRITE) {
     289        psTrace("psModules.camera", 6, "skip write for %s, mode is not WRITE", file->name);
     290        return true;
     291    }
     292
     293    // an internal file should not be returned to here
     294    if (file->mode == PM_FPA_MODE_INTERNAL) {
     295        psError(PS_ERR_IO, true, "File is mode PM_FPA_MODE_INTERNAL");
     296        return false;
     297    }
     298
     299    if (!file->save) {
     300        psTrace("psModules.camera", 6, "skip write for %s, save is FALSE", file->name);
     301        return true;
     302    }
     303
     304    // get the current level
     305    pmFPALevel level = pmFPAviewLevel (view);
     306
     307    // the effective dataLevel (for mosaics, we have preserved the original dataLevel)
     308    pmFPALevel dataLevel = (file->mosaicLevel != PM_FPA_LEVEL_NONE) ? file->mosaicLevel : file->dataLevel;
     309
     310    // do we need to write this file?
     311    if (level != dataLevel) {
     312        psTrace("psModules.camera", 6, "skip writing of %s at this level %s: dataLevel is %s",
     313                file->name, pmFPALevelToName(level), pmFPALevelToName(dataLevel));
     314        return true;
     315    }
     316
     317    // open the file if not yet opened
     318    // XXX do we need to test mosaicLevel?
     319    if (level >= file->fileLevel) {
     320        // we are allowed to open a file at a level which is not the fileLevel, but
     321        // we need to supply view at the fileLevel for the file lookup functions below
     322        pmFPAview *fileView = pmFPAviewForLevel (file->fileLevel, view);
     323        if (!pmFPAfileOpen (file, fileView, config)) {
     324            psError(PS_ERR_IO, false, "failed to open %s (%s)", file->filename, file->name);
     325            psFree (fileView);
     326            return false;
     327        }
     328        psFree (fileView);
     329    }
     330
     331    // do we need to write out a PHU?
     332    if (level >= file->fileLevel) {
     333        if (!pmFPAfileWritePHU (file, view, config)) {
     334            psError(PS_ERR_IO, false, "failed to write phu for %s (%s)", file->filename, file->name);
     335            return false;
     336        }
     337    }
     338
     339    // select a writing method
     340    bool status = true;
     341    switch (file->type) {
     342      case PM_FPA_FILE_IMAGE:
     343        status = pmFPAviewWriteFitsImage(view, file, config);
     344        break;
     345      case PM_FPA_FILE_MASK:
     346        status = pmFPAviewWriteFitsMask(view, file, config);
     347        break;
     348      case PM_FPA_FILE_WEIGHT:
     349        status = pmFPAviewWriteFitsWeight(view, file, config);
     350        break;
     351      case PM_FPA_FILE_HEADER:
     352        psAbort ("no HEADER write functions defined");
     353        break;
     354      case PM_FPA_FILE_FRINGE:
     355        status = pmFPAviewWriteFitsImage (view, file, config);
     356        if (status) {
     357            if (!pmFPAviewWriteFitsTable(view, file, "FRINGE")) {
     358                psError(PS_ERR_UNKNOWN, false, "Unable to write fringe data from %s.\n", file->filename);
     359                return false;
     360            }
     361        }
     362        break;
     363      case PM_FPA_FILE_SX:
     364      case PM_FPA_FILE_RAW:
     365      case PM_FPA_FILE_OBJ:
     366      case PM_FPA_FILE_CMP:
     367      case PM_FPA_FILE_CMF:
     368        status = pmFPAviewWriteObjects (view, file, config);
     369        break;
     370
     371      case PM_FPA_FILE_PSF:
     372        status = pmFPAviewWritePSFmodel (view, file, config);
     373        break;
     374
     375      case PM_FPA_FILE_JPEG:
     376        status = pmFPAviewWriteJPEG (view, file, config);
     377        break;
     378
     379      case PM_FPA_FILE_KAPA:
     380        status = pmFPAviewWriteSourcePlot (view, file, config);
     381        break;
     382
     383      default:
     384        psError(PS_ERR_IO, true, "warning: type mismatch; saw type %d (%s)", file->type, file->name);
     385        return false;
     386    }
     387    if (!status) {
     388        psError(PS_ERR_UNKNOWN, false, "failed to write %s (%s)\n", file->filename, file->name);
     389        return false;
     390    }
     391    psTrace ("psModules.camera", 5, "wrote %s (fpa: %p)\n", file->filename, file->fpa);
     392    return true;
     393}
     394
     395bool pmFPAfileClose (pmFPAfile *file, const pmFPAview *view)
     396{
     397    PS_ASSERT_PTR_NON_NULL(file, false);
     398    PS_ASSERT_PTR_NON_NULL(view, false);
     399
     400    // an internal file should not be sent here (should not be left on config->files)
     401    PS_ASSERT(file->mode != PM_FPA_MODE_INTERNAL, false);
     402
     403    // skip the following states
     404    if (file->state & PM_FPA_STATE_INACTIVE) {
     405        psTrace("psModules.camera", 6, "skip close for %s, files is inactive", file->name);
     406        return true;
     407    }
     408    if (file->state == PM_FPA_STATE_CLOSED) {
     409        psTrace("psModules.camera", 6, "skip close for %s, files is closed", file->name);
     410        return true;
     411    }
     412
     413    // is current level == open level?
     414    pmFPALevel level = pmFPAviewLevel (view);
     415    if (file->fileLevel != level) {
     416        psTrace("psModules.camera", 6, "skip closing of %s at this level %s: dataLevel is %s",
     417                file->name, pmFPALevelToName(level), pmFPALevelToName(file->dataLevel));
     418        return true;
     419    }
     420
     421    // check if we are actually open
     422    bool status = true;
     423    switch (file->type) {
     424        // check the FITS types
     425      case PM_FPA_FILE_IMAGE:
     426      case PM_FPA_FILE_MASK:
     427      case PM_FPA_FILE_WEIGHT:
     428      case PM_FPA_FILE_HEADER:
     429      case PM_FPA_FILE_FRINGE:
     430      case PM_FPA_FILE_CMF:
     431        psTrace ("psModules.camera", 5, "closing %s (type: %d)\n", file->filename, file->type);
     432        status = psFitsClose (file->fits);
     433        file->fits = NULL;
     434        file->phu = NULL;
     435        file->header = NULL;
     436        file->state = PM_FPA_STATE_CLOSED;
     437        break;
     438
     439        // ignore the TEXT types
     440      case PM_FPA_FILE_SX:
     441      case PM_FPA_FILE_RAW:
     442      case PM_FPA_FILE_OBJ:
     443      case PM_FPA_FILE_CMP:
     444      case PM_FPA_FILE_PSF:
     445      case PM_FPA_FILE_JPEG:
     446      case PM_FPA_FILE_KAPA:
     447        break;
     448
     449      default:
     450        psError(PS_ERR_IO, true, "type mismatch: %d (%s)", file->type, file->name);
     451        return false;
     452    }
     453    if (!status) {
     454        psError(PS_ERR_UNKNOWN, false, "failed to close %s (%s)\n", file->filename, file->name);
     455        return false;
     456    }
     457    return true;
     458}
     459
     460bool pmFPAfileFreeData(pmFPAfile *file, const pmFPAview *view)
     461{
     462    PS_ASSERT_PTR_NON_NULL(file, false);
     463    PS_ASSERT_PTR_NON_NULL(view, false);
     464
     465    // an internal file should not be sent here (should not be left on config->files)
     466    PS_ASSERT(file->mode != PM_FPA_MODE_INTERNAL, false);
     467
     468    if (file->state & PM_FPA_STATE_INACTIVE) {
     469        psTrace("psModules.camera", 6, "skip free for %s, files is inactive", file->name);
     470        return true;
     471    }
     472
     473    // get the current level
     474    pmFPALevel level = pmFPAviewLevel (view);
     475
     476    // do we need to free this file?
     477    if (level != file->freeLevel) {
     478        psTrace("psModules.camera", 6, "skip free of %s at this level %s: freeLevel is %s",
     479                file->name, pmFPALevelToName(level), pmFPALevelToName(file->freeLevel));
     480        return true;
     481    }
     482
     483    bool status = true;
     484    switch (file->type) {
     485      case PM_FPA_FILE_IMAGE:
     486      case PM_FPA_FILE_MASK:
     487      case PM_FPA_FILE_WEIGHT:
     488      case PM_FPA_FILE_HEADER:
     489      case PM_FPA_FILE_FRINGE:
     490        status = pmFPAviewFreeData(view, file);
     491        break;
     492      case PM_FPA_FILE_SX:
     493      case PM_FPA_FILE_RAW:
     494      case PM_FPA_FILE_OBJ:
     495      case PM_FPA_FILE_CMP:
     496      case PM_FPA_FILE_CMF:
     497        psTrace ("psModules.camera", 5, "NOT freeing %s (%s) : save for further analysis\n", file->filename, file->name);
     498        break;
     499      case PM_FPA_FILE_PSF:
     500      case PM_FPA_FILE_JPEG:
     501      case PM_FPA_FILE_KAPA:
     502        psTrace ("psModules.camera", 5, "nothing to free for %s (%s)\n", file->filename, file->name);
     503        break;
     504      default:
     505        psError(PS_ERR_IO, true, "warning: type mismatch; saw type %d", file->type);
     506        return false;
     507    }
     508    if (!status) {
     509        psError(PS_ERR_UNKNOWN, false, "failed to read %s (%s)\n", file->filename, file->name);
     510        return false;
     511    }
     512    psTrace ("psModules.camera", 5, "freed %s (%s)\n", file->filename, file->name);
     513    return true;
     514}
     515
     516// open file (if not already opened).
     517// this function is only called only within pmFPAfileRead or pmFPAfileWrite.
    35518bool pmFPAfileOpen (pmFPAfile *file, const pmFPAview *view, pmConfig *config)
    36519{
     
    52535    }
    53536
    54     // XXX are these programming errors?
    55     if (file->mode == PM_FPA_MODE_NONE) {
    56         psError(PS_ERR_IO, true, "File is mode PM_FPA_MODE_NONE");
    57         return false;
    58     }
    59     if (file->mode == PM_FPA_MODE_INTERNAL) {
    60         psError(PS_ERR_IO, true, "File is mode PM_FPA_MODE_INTERNAL");
    61         return false;
    62     }
     537    // these are programming errors
     538    PS_ASSERT(file->mode != PM_FPA_MODE_NONE, false);
     539    PS_ASSERT(file->mode != PM_FPA_MODE_INTERNAL, false);
     540
    63541    if (file->mode == PM_FPA_MODE_READ) {
    64542        mode = readMode;
     
    200678    }
    201679    return true;
    202 }
    203 
    204 bool pmFPAfileRead(pmFPAfile *file, const pmFPAview *view, pmConfig *config)
    205 {
    206     PS_ASSERT_PTR_NON_NULL(file, false);
    207     PS_ASSERT_PTR_NON_NULL(view, false);
    208 
    209     // an internal file should not be sent here
    210     // XXX is this a programming error?
    211     if (file->mode == PM_FPA_MODE_INTERNAL) {
    212         psError(PS_ERR_IO, true, "File is mode PM_FPA_MODE_INTERNAL");
    213         return false;
    214     }
    215 
    216     if (file->state & PM_FPA_STATE_INACTIVE) {
    217         psTrace("psModules.camera", 6, "skip read for %s, file is inactive", file->name);
    218         return true;
    219     }
    220 
    221     if (file->mode != PM_FPA_MODE_READ) {
    222         psTrace("psModules.camera", 6, "skip read for %s, mode is not READ", file->name);
    223         return true;
    224     }
    225 
    226     // get the current level
    227     pmFPALevel level = pmFPAviewLevel (view);
    228 
    229     // do we need to read this file? defer until we read the correct level
    230     if (level != file->dataLevel) {
    231         psTrace("psModules.camera", 6, "skip reading of %s at this level %s: dataLevel is %s",
    232                 file->name, pmFPALevelToName(level), pmFPALevelToName(file->dataLevel));
    233         return true;
    234     }
    235 
    236     // do we need to open this file?
    237     if (level >= file->fileLevel) {
    238         // we are allowed to open a file at a level which is not the fileLevel, but
    239         // we need to supply view at the fileLevel for the file lookup functions below
    240         pmFPAview *fileView = pmFPAviewForLevel (file->fileLevel, view);
    241         if (!pmFPAfileOpen (file, fileView, config)) {
    242             psError(PS_ERR_IO, false, "failed to open file %s (%s)", file->filename, file->name);
    243             psFree (fileView);
    244             return false;
    245         }
    246         psFree (fileView);
    247     }
    248 
    249     // We need to read it --- double-check it's open!
    250     if (file->state == PM_FPA_STATE_CLOSED) {
    251         psError(PS_ERR_IO, false, "failed to open file %s when attempting to read", file->name);
    252         return false;
    253     }
    254 
    255     // select a reading method
    256     bool status = false;
    257     switch (file->type) {
    258       case PM_FPA_FILE_IMAGE:
    259         status = pmFPAviewReadFitsImage(view, file);
    260         break;
    261       case PM_FPA_FILE_MASK:
    262         status = pmFPAviewReadFitsMask(view, file);
    263         break;
    264       case PM_FPA_FILE_WEIGHT:
    265         status = pmFPAviewReadFitsWeight(view, file);
    266         break;
    267       case PM_FPA_FILE_HEADER:
    268         status = pmFPAviewReadFitsHeaderSet(view, file);
    269         break;
    270       case PM_FPA_FILE_FRINGE:
    271         status = pmFPAviewReadFitsImage (view, file);
    272         if (status) {
    273             if (!pmFPAviewReadFitsTable(view, file, "FRINGE")) {
    274                 psError(PS_ERR_UNKNOWN, false, "Unable to read fringe data from %s.\n", file->filename);
    275                 return false;
    276             }
    277         }
    278         break;
    279       case PM_FPA_FILE_SX:
    280       case PM_FPA_FILE_RAW:
    281       case PM_FPA_FILE_OBJ:
    282       case PM_FPA_FILE_CMP:
    283       case PM_FPA_FILE_CMF:
    284         status = pmFPAviewReadObjects (view, file, config);
    285         break;
    286       case PM_FPA_FILE_PSF:
    287         status = pmFPAviewReadPSFmodel (view, file, config);
    288         break;
    289       case PM_FPA_FILE_JPEG:
    290       case PM_FPA_FILE_KAPA:
    291         break;
    292       default:
    293         psError(PS_ERR_IO, true, "warning: type mismatch; saw type %d (%s)", file->type, file->name);
    294         return false;
    295     }
    296 
    297     if (!status) {
    298         psError(PS_ERR_UNKNOWN, false, "skipping %s (%s)\n", file->filename, file->name);
    299         return false;
    300     }
    301     psTrace ("psModules.camera", 5, "read %s (%s)\n", file->filename, file->name);
    302 
    303     return true;
    304 }
    305 
    306 bool pmFPAfileFreeData(pmFPAfile *file, const pmFPAview *view)
    307 {
    308     PS_ASSERT_PTR_NON_NULL(file, false);
    309     PS_ASSERT_PTR_NON_NULL(view, false);
    310 
    311     if (file->state & PM_FPA_STATE_INACTIVE) {
    312         psTrace("psModules.camera", 6, "skip free for %s, files is inactive", file->name);
    313         return true;
    314     }
    315 
    316     // an internal file should not be sent here
    317     if (file->mode == PM_FPA_MODE_INTERNAL) {
    318         psError(PS_ERR_IO, true, "File is mode PM_FPA_MODE_INTERNAL");
    319         return false;
    320     }
    321 
    322     // get the current level
    323     pmFPALevel level = pmFPAviewLevel (view);
    324 
    325     // do we need to free this file?
    326     if (level != file->freeLevel) {
    327         psTrace("psModules.camera", 6, "skip free of %s at this level %s: freeLevel is %s",
    328                 file->name, pmFPALevelToName(level), pmFPALevelToName(file->freeLevel));
    329         return true;
    330     }
    331 
    332     switch (file->type) {
    333     case PM_FPA_FILE_IMAGE:
    334     case PM_FPA_FILE_MASK:
    335     case PM_FPA_FILE_WEIGHT:
    336     case PM_FPA_FILE_HEADER:
    337     case PM_FPA_FILE_FRINGE:
    338         if (pmFPAviewFreeData(view, file)) {
    339             psTrace ("psModules.camera", 5, "freed %s (%s)\n", file->filename, file->name);
    340             if (file->filename == NULL) {
    341                 psTrace ("psModules.camera", 5, "filename is not defined for %s\n", file->name);
    342             }
    343         } else {
    344             psError(PS_ERR_UNKNOWN, false, "skipping %s (%s)\n", file->filename, file->name);
    345             return false;
    346         }
    347         break;
    348     case PM_FPA_FILE_SX:
    349     case PM_FPA_FILE_RAW:
    350     case PM_FPA_FILE_OBJ:
    351     case PM_FPA_FILE_CMP:
    352     case PM_FPA_FILE_CMF:
    353         // pmFPAviewFreeObjects (view, file);
    354         psTrace ("psModules.camera", 5, "NOT freeing %s (%s)\n", file->filename, file->name);
    355         break;
    356 
    357         // XXX not certain what I need to free here
    358     case PM_FPA_FILE_PSF:
    359     case PM_FPA_FILE_JPEG:
    360     case PM_FPA_FILE_KAPA:
    361         break;
    362 
    363     default:
    364         psError(PS_ERR_IO, true, "warning: type mismatch; saw type %d", file->type);
    365         return false;
    366     }
    367     return true;
    368 }
    369 
    370 bool pmFPAfileWrite(pmFPAfile *file, const pmFPAview *view, pmConfig *config)
    371 {
    372     PS_ASSERT_PTR_NON_NULL(file, false);
    373     PS_ASSERT_PTR_NON_NULL(view, false);
    374 
    375     if (file->state & PM_FPA_STATE_INACTIVE) {
    376         psTrace("psModules.camera", 6, "skip write for %s, files is inactive", file->name);
    377         return true;
    378     }
    379 
    380     if (file->mode != PM_FPA_MODE_WRITE) {
    381         psTrace("psModules.camera", 6, "skip write for %s, mode is not WRITE", file->name);
    382         return true;
    383     }
    384 
    385     // an internal file should not be returned to here
    386     if (file->mode == PM_FPA_MODE_INTERNAL) {
    387         psError(PS_ERR_IO, true, "File is mode PM_FPA_MODE_INTERNAL");
    388         return false;
    389     }
    390 
    391     if (!file->save) {
    392         psTrace("psModules.camera", 6, "skip write for %s, save is FALSE", file->name);
    393         return true;
    394     }
    395 
    396     // get the current level
    397     pmFPALevel level = pmFPAviewLevel (view);
    398 
    399     // do we need to write this file?
    400     if ((file->mosaicLevel == PM_FPA_LEVEL_NONE && level != file->dataLevel) || // No mosaicking happening
    401         (file->mosaicLevel != PM_FPA_LEVEL_NONE && level != file->mosaicLevel)) { // Mosaicking happening
    402         psTrace("psModules.camera", 6, "skip writing of %s at this level %s: dataLevel is %s",
    403                 file->name, pmFPALevelToName(level), pmFPALevelToName(file->dataLevel));
    404         return true;
    405     }
    406 
    407     // do we need to open this file?
    408     // XXX do we need both mosaicLevel and dataLevel?
    409 # if (0)   
    410     if (level >= file->fileLevel &&
    411         (file->mosaicLevel == PM_FPA_LEVEL_NONE ||
    412          (file->mosaicLevel != PM_FPA_LEVEL_NONE && level >= file->mosaicLevel))) {
    413         if (!pmFPAfileOpen (file, view, config)) {
    414             psError(PS_ERR_IO, false, "failed to open %s", file->filename);
    415             return false;
    416         }
    417     }
    418 # endif
    419 
    420     // open the file if not yet opened
    421     if (level >= file->fileLevel) {
    422         // we are allowed to open a file at a level which is not the fileLevel, but
    423         // we need to supply view at the fileLevel for the file lookup functions below
    424         pmFPAview *fileView = pmFPAviewForLevel (file->fileLevel, view);
    425         if (!pmFPAfileOpen (file, fileView, config)) {
    426             psError(PS_ERR_IO, false, "failed to open %s (%s)", file->filename, file->name);
    427             psFree (fileView);
    428             return false;
    429         }
    430         psFree (fileView);
    431     }
    432 
    433     // do we need to write out a PHU?
    434     if (level >= file->fileLevel) {
    435         if (!pmFPAfileWritePHU (file, view, config)) {
    436             psError(PS_ERR_IO, false, "failed to write phu for %s (%s)", file->filename, file->name);
    437             return false;
    438         }
    439     }
    440 
    441     // XXX catch error status
    442     switch (file->type) {
    443     case PM_FPA_FILE_IMAGE:
    444         pmFPAviewWriteFitsImage(view, file, config);
    445         psTrace ("psModules.camera", 5, "wrote image %s (fpa: %p)\n", file->filename, file->fpa);
    446         break;
    447     case PM_FPA_FILE_MASK:
    448         pmFPAviewWriteFitsMask(view, file, config);
    449         psTrace ("psModules.camera", 5, "wrote mask %s (fpa: %p)\n", file->filename, file->fpa);
    450         break;
    451     case PM_FPA_FILE_WEIGHT:
    452         pmFPAviewWriteFitsWeight(view, file, config);
    453         psTrace ("psModules.camera", 5, "wrote weight %s (fpa: %p)\n", file->filename, file->fpa);
    454         break;
    455     case PM_FPA_FILE_HEADER:
    456       // pmFPAviewWriteFitsWeight(view, file, config);
    457       // psTrace ("psModules.camera", 5, "wrote weight %s (fpa: %p)\n", file->filename, file->fpa);
    458       psAbort ("no HEADER write functions defined");
    459         break;
    460     case PM_FPA_FILE_FRINGE:
    461         pmFPAviewWriteFitsImage (view, file, config);
    462         psTrace ("psModules.camera", 5, "wrote image %s (fpa: %p)\n", file->filename, file->fpa);
    463         pmFPAviewWriteFitsTable(view, file, "FRINGE");
    464         psTrace ("psModules.camera", 5, "wrote fringe table %s (fpa: %p)\n", file->filename, file->fpa);
    465         break;
    466 
    467     case PM_FPA_FILE_SX:
    468     case PM_FPA_FILE_RAW:
    469     case PM_FPA_FILE_OBJ:
    470     case PM_FPA_FILE_CMP:
    471     case PM_FPA_FILE_CMF:
    472         psTrace ("psModules.camera", 5, "writing object %s (fpa: %p)\n", file->filename, file->fpa);
    473         if (!pmFPAviewWriteObjects (view, file, config)) {
    474             psError(PS_ERR_IO, false, "Failed to write object %s", file->filename);
    475             return false;
    476         }
    477 
    478         break;
    479 
    480     case PM_FPA_FILE_PSF:
    481         pmFPAviewWritePSFmodel (view, file, config);
    482         psTrace ("psModules.camera", 5, "wrote PSF %s (fpa: %p)\n", file->filename, file->fpa);
    483         break;
    484 
    485     case PM_FPA_FILE_JPEG:
    486         pmFPAviewWriteJPEG (view, file, config);
    487         psTrace ("psModules.camera", 5, "wrote JPEG %s (fpa: %p)\n", file->filename, file->fpa);
    488         break;
    489 
    490     case PM_FPA_FILE_KAPA:
    491         pmFPAviewWriteSourcePlot (view, file, config);
    492         psTrace ("psModules.camera", 5, "wrote KAPA %s (fpa: %p)\n", file->filename, file->fpa);
    493         break;
    494 
    495     default:
    496         fprintf (stderr, "warning: type mismatch\n");
    497         return false;
    498     }
    499     return true;
    500 }
    501 
    502 // create the data elements (headers, images) appropriate for this view
    503 bool pmFPAfileCreate (pmFPAfile *file, const pmFPAview *view, const pmConfig *config)
    504 {
    505     PS_ASSERT_PTR_NON_NULL(file, false);
    506     PS_ASSERT_PTR_NON_NULL(view, false);
    507 
    508     // these are not error conditions; these are state tests
    509     if (file->state & PM_FPA_STATE_INACTIVE) {
    510         psTrace("psModules.camera", 6, "skip create for inactive file %s", file->name);
    511         return true;
    512     }
    513     if (file->mode != PM_FPA_MODE_WRITE) {
    514         psTrace("psModules.camera", 6, "skip create for non-write file %s", file->name);
    515         return true;
    516     }
    517 
    518     // an internal file should not be returned to here
    519     if (file->mode == PM_FPA_MODE_INTERNAL) {
    520         psError(PS_ERR_IO, true, "File is mode PM_FPA_MODE_INTERNAL");
    521         return false;
    522     }
    523 
    524     // get the current level
    525     pmFPALevel level = pmFPAviewLevel (view);
    526 
    527     // don't create the file if the src (FPA) is not defined
    528     if (file->src == NULL) {
    529         psTrace("psModules.camera", 6, "skip create for FPA without src FPA for %s", file->name);
    530         return true;
    531     }
    532 
    533     // do we need to write this file?
    534     if (level != file->fileLevel || file->mosaicLevel != PM_FPA_LEVEL_NONE) {
    535         psTrace("psModules.camera", 6, "skip creation of %s at this level %s: fileLevel is %s",
    536                 file->name, pmFPALevelToName(level), pmFPALevelToName(file->fileLevel));
    537         return true;
    538     }
    539 
    540     switch (file->type) {
    541     case PM_FPA_FILE_IMAGE:
    542     case PM_FPA_FILE_MASK:
    543     case PM_FPA_FILE_WEIGHT:
    544     case PM_FPA_FILE_FRINGE: {
    545             // create FPA structure component based on view
    546             psMetadata *format = file->format; // Camera format configuration
    547             if (!format) {
    548                 format = config->format;
    549             }
    550 
    551             pmFPA *nameSource = file->src; // Source of FPA.NAME
    552             if (!nameSource) {
    553                 nameSource = file->fpa;
    554             }
    555             bool mdok;                  // Status of MD lookup
    556             const char *fpaname = psMetadataLookupStr(&mdok, nameSource->concepts, "FPA.NAME"); // Name of FPA
    557 
    558             pmFPAAddSourceFromView(file->fpa, fpaname, view, format);
    559             psTrace ("psModules.camera", 5, "created fpa data elements for %s (fpa: %p)\n", file->name, file->fpa);
    560             break;
    561     }
    562     case PM_FPA_FILE_HEADER:
    563       psAbort ("Create not defined for HEADER");
    564       break;
    565     case PM_FPA_FILE_SX:
    566     case PM_FPA_FILE_RAW:
    567     case PM_FPA_FILE_OBJ:
    568     case PM_FPA_FILE_CMP:
    569     case PM_FPA_FILE_CMF:
    570     case PM_FPA_FILE_PSF:
    571     case PM_FPA_FILE_JPEG:
    572     case PM_FPA_FILE_KAPA:
    573         break;
    574 
    575     default:
    576         psError(PS_ERR_IO, true, "Unsupported type for %s: %d", file->name, file->type);
    577         return false;
    578     }
    579     return true;
    580 }
    581 
    582 bool pmFPAfileClose (pmFPAfile *file, const pmFPAview *view)
    583 {
    584     PS_ASSERT_PTR_NON_NULL(file, false);
    585     PS_ASSERT_PTR_NON_NULL(view, false);
    586 
    587     if (file->state & PM_FPA_STATE_INACTIVE) {
    588         psTrace("psModules.camera", 6, "skip close for %s, files is inactive", file->name);
    589         return true;
    590     }
    591     if (file->state == PM_FPA_STATE_CLOSED) {
    592         return true;
    593     }
    594 
    595     // an internal file should not be returned to here
    596     if (file->mode == PM_FPA_MODE_INTERNAL) {
    597         psError(PS_ERR_IO, true, "File is mode PM_FPA_MODE_INTERNAL");
    598         return false;
    599     }
    600 
    601     // is current level == open level?
    602     pmFPALevel level = pmFPAviewLevel (view);
    603     if (file->fileLevel != level) {
    604         psTrace("psModules.camera", 6, "skip closing of %s at this level %s: dataLevel is %s",
    605                 file->name, pmFPALevelToName(level), pmFPALevelToName(file->dataLevel));
    606         return true;
    607     }
    608 
    609     // check if we are actually open
    610     switch (file->type) {
    611         // check the FITS types
    612     case PM_FPA_FILE_IMAGE:
    613     case PM_FPA_FILE_MASK:
    614     case PM_FPA_FILE_WEIGHT:
    615     case PM_FPA_FILE_HEADER:
    616     case PM_FPA_FILE_FRINGE:
    617     case PM_FPA_FILE_CMF:
    618         psFitsClose (file->fits);
    619         psTrace ("psModules.camera", 5, "closing %s (type: %d)\n", file->filename, file->type);
    620         file->fits = NULL;
    621         file->phu = NULL;
    622         file->header = NULL;
    623         file->state = PM_FPA_STATE_CLOSED;
    624         break;
    625 
    626         // ignore the TEXT types
    627     case PM_FPA_FILE_SX:
    628     case PM_FPA_FILE_RAW:
    629     case PM_FPA_FILE_OBJ:
    630     case PM_FPA_FILE_CMP:
    631     case PM_FPA_FILE_PSF:
    632     case PM_FPA_FILE_JPEG:
    633     case PM_FPA_FILE_KAPA:
    634         break;
    635 
    636     default:
    637         psError(PS_ERR_IO, true, "type mismatch: %d", file->type);
    638         return false;
    639     }
    640     return true;
    641 }
    642 
    643 // set the state of the specified pmFPAfile to active (state == true) or inactive
    644 // if name is NULL, set the state for all pmFPAfiles
    645 bool pmFPAfileActivate (psMetadata *files, bool state, char *name)
    646 {
    647     PS_ASSERT_PTR_NON_NULL(files, false);
    648 
    649     if (!name) {
    650         psMetadataItem *item = NULL;
    651         psMetadataIterator *iter = psMetadataIteratorAlloc (files, PS_LIST_HEAD, NULL);
    652         while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
    653             pmFPAfile *file = item->data.V;
    654             if (state) {
    655                 file->state &= PS_NOT_U8(PM_FPA_STATE_INACTIVE);
    656             } else {
    657                 file->state |= PM_FPA_STATE_INACTIVE;
    658             }
    659         }
    660         psFree (iter);
    661         return true;
    662     }
    663 
    664     bool status = false;
    665     pmFPAfile *file = psMetadataLookupPtr (&status, files, name);
    666     if (!status) {
    667         psTrace("psModules.camera", 6, "%s is not a defined IO file", name);
    668         return false;
    669     }
    670     if (!file) {
    671         psError(PS_ERR_IO, true, "file %s is NULL", name);
    672         return false;
    673     }
    674     if (state) {
    675         file->state &= PS_NOT_U8(PM_FPA_STATE_INACTIVE);
    676     } else {
    677         file->state |= PM_FPA_STATE_INACTIVE;
    678     }
    679     return true;
    680 }
    681 
    682 // attempt create, read, write, close, or free pmFPAfiles available in files
    683 // files are automatically opened before they are read
    684 bool pmFPAfileIOChecks (pmConfig *config, const pmFPAview *view, pmFPAfilePlace place)
    685 {
    686     PS_ASSERT_PTR_NON_NULL(config, false);
    687     PS_ASSERT_PTR_NON_NULL(config->files, false);
    688     PS_ASSERT_PTR_NON_NULL(view, false);
    689 
    690     psMetadata *files = config->files;
    691 
    692     // attempt to perform all create, read, write, close operations
    693     psMetadataItem *item = NULL;
    694     psMetadataIterator *iter = psMetadataIteratorAlloc (files, PS_LIST_HEAD, NULL);
    695     while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
    696         pmFPAfile *file = item->data.V;
    697 
    698         switch (place) {
    699         case PM_FPA_BEFORE:
    700 # if (0)
    701             if (!pmFPAfileOpen(file, view, config)) {
    702                 psError(PS_ERR_IO, false, "failed OPEN in FPA_BEFORE block for %s", file->name);
    703                 goto failure;
    704             }
    705 # endif
    706             if (!pmFPAfileRead (file, view, config)) {
    707                 psError(PS_ERR_IO, false, "failed READ in FPA_BEFORE block for %s", file->name);
    708                 goto failure;
    709             }
    710             if (!pmFPAfileCreate(file, view, config)) {
    711                 psError(PS_ERR_IO, false, "failed CREATE in FPA_BEFORE block for %s", file->name);
    712                 goto failure;
    713             }
    714 # if (0)
    715             if (!pmFPAfileBlank(file, view, config)) {
    716                 psError(PS_ERR_IO, false, "failed BLANK in FPA_BEFORE block for %s", file->name);
    717                 goto failure;
    718             }
    719 # endif
    720             break;
    721         case PM_FPA_AFTER:
    722             if (!pmFPAfileWrite (file, view, config)) {
    723                 psError(PS_ERR_IO, false, "failed WRITE in FPA_AFTER block for %s", file->name);
    724                 goto failure;
    725             }
    726             if (!pmFPAfileClose(file, view)) {
    727                 psError(PS_ERR_IO, false, "failed CLOSE in FPA_AFTER block for %s", file->name);
    728                 goto failure;
    729             }
    730             break;
    731         default:
    732             psAbort("You can't get here");
    733         }
    734     }
    735 
    736     // attempt to free data that is no longer needed
    737     psMetadataIteratorSet (iter, PS_LIST_HEAD);
    738     while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
    739         pmFPAfile *file = item->data.V;
    740 
    741         switch (place) {
    742         case PM_FPA_BEFORE:
    743             break;
    744         case PM_FPA_AFTER:
    745             if (!pmFPAfileFreeData(file, view)) {
    746                 if (!psMetadataRemoveKey(files, file->name)) {
    747                     psError(PS_ERR_IO, false, "failed to remove %s in FPA_AFTER block", file->name);
    748                     goto failure;
    749                 }
    750             }
    751             break;
    752         default:
    753             psAbort("You can't get here");
    754         }
    755     }
    756     psFree (iter);
    757     return true;
    758 
    759 failure:
    760     psFree (iter);
    761     return false;
    762680}
    763681
     
    828746    PS_ASSERT_PTR_NON_NULL(view, false);
    829747
    830     // XXX we need to test IF we need to write out a PHU blank
    831     // is this function performed by the pmFPAWrite,etc functions?
    832 
     748    bool status = true;
    833749    switch (file->type) {
    834     case PM_FPA_FILE_IMAGE:
    835     case PM_FPA_FILE_MASK:
    836     case PM_FPA_FILE_WEIGHT:
    837     case PM_FPA_FILE_FRINGE:
    838     if (file->mode == PM_FPA_MODE_WRITE) {
    839         // Want to write out any potential blank
    840         pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config); // FPA, ensuring it's ready to write a blank
    841 
    842         switch (file->fileLevel) {
    843         case PM_FPA_LEVEL_FPA:
    844             pmFPAWrite(fpa, file->fits, NULL, true, false);
    845             break;
    846         case PM_FPA_LEVEL_CHIP: {
    847                 pmChip *chip = pmFPAviewThisChip(view, fpa);
    848                 pmChipWrite(chip, file->fits, NULL, true, false);
    849                 break;
     750      case PM_FPA_FILE_IMAGE:
     751      case PM_FPA_FILE_MASK:
     752      case PM_FPA_FILE_WEIGHT:
     753      case PM_FPA_FILE_FRINGE:
     754        if (file->mode == PM_FPA_MODE_WRITE) {
     755            // Want to write out any potential blank
     756            // XXX why do we need to construct a new fpa??
     757            pmFPA *fpa = pmFPAfileSuitableFPA(file, view, config); // FPA, ensuring it's ready to write a blank
     758
     759            switch (file->fileLevel) {
     760              case PM_FPA_LEVEL_FPA:
     761                if (file->fpa->wrote_phu) break;
     762                status = pmFPAWrite(fpa, file->fits, NULL, true, false);
     763                file->fpa->wrote_phu = true;
     764                break;
     765              case PM_FPA_LEVEL_CHIP: {
     766                  pmChip *chip = pmFPAviewThisChip(view, fpa);
     767                  if (chip->wrote_phu) break;
     768                  status = pmChipWrite(chip, file->fits, NULL, true, false);
     769                  chip->wrote_phu = true;
     770                  break;
     771              }
     772              case PM_FPA_LEVEL_CELL: {
     773                  pmCell *cell = pmFPAviewThisCell(view, fpa);
     774                  if (cell->wrote_phu) break;
     775                  status = pmCellWrite(cell, file->fits, NULL, true);
     776                  cell->wrote_phu = true;
     777                  break;
     778              }
     779              default:
     780                psAbort("fileLevel not correctly set");
     781                break;
     782            }
     783
     784            psFree(fpa);
     785        }
     786      case PM_FPA_FILE_SX:
     787      case PM_FPA_FILE_RAW:
     788      case PM_FPA_FILE_OBJ:
     789      case PM_FPA_FILE_CMP:
     790      case PM_FPA_FILE_CMF:
     791      case PM_FPA_FILE_PSF:
     792      case PM_FPA_FILE_JPEG:
     793      case PM_FPA_FILE_KAPA:
     794        break;
     795      default:
     796        fprintf (stderr, "warning: type mismatch\n");
     797        return false;
     798    }
     799    if (!status) {
     800        psError(PS_ERR_UNKNOWN, false, "failed to write PHU for %s (%s)\n", file->filename, file->name);
     801        return false;
     802    }
     803    return true;
     804}
     805
     806// set the state of the specified pmFPAfile to active (state == true) or inactive
     807// if name is NULL, set the state for all pmFPAfiles
     808bool pmFPAfileActivate (psMetadata *files, bool state, char *name)
     809{
     810    PS_ASSERT_PTR_NON_NULL(files, false);
     811
     812    if (!name) {
     813        psMetadataItem *item = NULL;
     814        psMetadataIterator *iter = psMetadataIteratorAlloc (files, PS_LIST_HEAD, NULL);
     815        while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
     816            pmFPAfile *file = item->data.V;
     817            if (state) {
     818                file->state &= PS_NOT_U8(PM_FPA_STATE_INACTIVE);
     819            } else {
     820                file->state |= PM_FPA_STATE_INACTIVE;
    850821            }
    851         case PM_FPA_LEVEL_CELL: {
    852                 pmCell *cell = pmFPAviewThisCell(view, fpa);
    853                 pmCellWrite(cell, file->fits, NULL, true);
    854                 break;
    855             }
    856         default:
    857             psAbort("fileLevel not correctly set");
    858             break;
    859         }
    860 
    861         psFree(fpa);
    862     }
    863     case PM_FPA_FILE_SX:
    864     case PM_FPA_FILE_RAW:
    865     case PM_FPA_FILE_OBJ:
    866     case PM_FPA_FILE_CMP:
    867     case PM_FPA_FILE_CMF:
    868     case PM_FPA_FILE_PSF:
    869     case PM_FPA_FILE_JPEG:
    870     case PM_FPA_FILE_KAPA:
    871       break;
    872     default:
    873         fprintf (stderr, "warning: type mismatch\n");
    874         return false;
    875     }
    876     return true;
    877 }
    878 
    879 # if (0)
    880 
    881 //XXX from pmFPAfileOpen (Image section)
    882         psTrace ("psModules.camera", 5, "opening %s (type: %d)\n", file->filename, file->type);
    883         if (!openImage(file, view, mode, config)) {
    884             psError(PS_ERR_UNKNOWN, false, "Unable to open image %s (type %d)\n", file->filename, file->type);
    885             return false;
    886         }
    887         break;
    888         // open the FITS object files
    889 /////
    890 
    891 
    892 // Open a file that contains an image
    893 static bool openImage(pmFPAfile *file,  // File to open
    894                       const pmFPAview *view, // View pointing to open level
    895                       const char *mode,  // Open mode (for psFitsOpen)
    896                       pmConfig *config  // Configuration
    897                      )
    898 {
    899     bool status;
    900 
    901     file->fits = psFitsOpen (file->filename, mode);
    902     if (file->fits == NULL) {
    903         psError(PS_ERR_IO, false, "error opening file %s\n", file->filename);
    904         return false;
    905     }
    906     file->state = PM_FPA_STATE_OPEN;
    907    
    908     // if needed, set the optional EXTWORD field based on the camera value
    909     if (config && config->format) {
    910         psMetadata *fileMenu = psMetadataLookupMetadata (NULL, config->format, "FILE");
    911         if (!fileMenu) {
    912             psError (PS_ERR_IO, true, "FILE METADATA missing from camera format %s\n", config->formatName);
    913             return false;
    914         }
    915         char *extword = psMetadataLookupStr (&status, fileMenu, "EXTWORD");
    916         if (status) {
    917             psFitsSetExtnameWord (file->fits, extword);
    918         }
    919     }
    920 
    921     // In some cases, we need to read the PHU after we've opened the file.  This happens for
    922     // the images supplied by the detrend database, which are only identified here (above).
    923     if (!pmFPAfileReadPHU (file, view, config)) {
    924         psError (PS_ERR_IO, true, "error reading PHU for %s (%s)\n", file->filename, file->name);
    925         return false;
    926     }
    927     return true;
    928 }
    929 # endif
     822        }
     823        psFree (iter);
     824        return true;
     825    }
     826
     827    bool status = false;
     828    pmFPAfile *file = psMetadataLookupPtr (&status, files, name);
     829    if (!status) {
     830        psTrace("psModules.camera", 6, "%s is not a defined IO file", name);
     831        return false;
     832    }
     833    if (!file) {
     834        psError(PS_ERR_IO, true, "file %s is NULL", name);
     835        return false;
     836    }
     837    if (state) {
     838        file->state &= PS_NOT_U8(PM_FPA_STATE_INACTIVE);
     839    } else {
     840        file->state |= PM_FPA_STATE_INACTIVE;
     841    }
     842    return true;
     843}
Note: See TracChangeset for help on using the changeset viewer.