IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 15168


Ignore:
Timestamp:
Oct 2, 2007, 5:01:45 PM (19 years ago)
Author:
Paul Price
Message:

Cleaning up some code, using PS_ASSERT_FITS_NON_NULL instead of custom code in each function. Adding function to determine if the FITS file pointer is on a PHU that should truly be a FITS image (but it's compressed so it's a FITS table, which can't be the PHU). Putting hooks to this function into the header and image read functions, so that they read what the user Really Wants. This behaviour (which some may not want if they want the unadulterated FITS file) can be turned off by setting psFits.compression=false (default is true). This works for reading uncompressed data, data we've compressed ourselves, and data compressed with fpack-0.93. It doesn't yet work with data compressed with cfitsio's imcopy program (due to multiple EXTNAME keywords; about to put in a fix for this).

Location:
branches/pap_branch_070920/psLib/src/fits
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • branches/pap_branch_070920/psLib/src/fits/psFits.c

    r15111 r15168  
    77 *  @author Robert DeSonia, MHPCC
    88 *
    9  *  @version $Revision: 1.71.2.2 $ $Name: not supported by cvs2svn $
    10  *  @date $Date: 2007-09-29 21:55:41 $
     9 *  @version $Revision: 1.71.2.3 $ $Name: not supported by cvs2svn $
     10 *  @date $Date: 2007-10-03 03:01:45 $
    1111 *
    1212 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    8181bool psFitsClose(psFits* fits)
    8282{
    83     if (fits == NULL) {
    84         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    85                 _("The input psFits object can not NULL."));
    86         return false;
    87     }
     83    PS_ASSERT_FITS_NON_NULL(fits, false);
    8884
    8985    bool status = fitsClose(fits);
     
    9591psFits* psFitsOpen(const char* name, const char* mode)
    9692{
     93    PS_ASSERT_STRING_NON_EMPTY(name, NULL);
     94
    9795    int status = 0;
    9896    fitsfile *fptr = NULL;      /* Pointer to the FITS file */
    99 
    100     if (name == NULL) {
    101         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    102                 _("Specified filename can not be NULL."));
    103         return NULL;
    104     }
    10597
    10698    /* check the mode to determine how to open/create file */
     
    131123        if (access(name, F_OK) == 0) {
    132124            // file exists, delete old one first
    133             remove
    134                 (name);
     125            remove(name);
    135126        }
    136127
     
    140131        (void)fits_create_file
    141132        #endif
    142         (&fptr,
    143          name,
    144          &status);
     133        (&fptr, name, &status);
    145134        if (fptr == NULL || status != 0) {
    146135            char fitsErr[MAX_STRING_LENGTH];
     
    157146        (void)fits_open_file
    158147        #endif
    159         (&fptr,
    160          name,
    161          iomode,
    162          &status);
     148        (&fptr, name, iomode, &status);
    163149        if (fptr == NULL || status != 0) {
    164150            char fitsErr[MAX_STRING_LENGTH];
     
    175161    fits->writable = (iomode == READWRITE);
    176162    fits->extword = NULL;
     163    fits->compression = true;
    177164    psMemSetDeallocator(fits,(psFreeFunc)fitsFree);
    178165
     
    180167}
    181168
    182 psErrorCode p_psFitsError(const char* filename,
    183                           unsigned int lineno,
    184                           const char* func,
    185                           int status,
    186                           bool new,
    187                           const char *errorMsg,
    188                           ...
    189                           )
     169psErrorCode p_psFitsError(const char* filename, unsigned int lineno, const char* func, int status,
     170                          bool new, const char *errorMsg, ...)
    190171{
    191172    if (status == 0) {
     
    211192static void psFitsCompressionFree(psFitsCompression *comp)
    212193{
     194    PS_ASSERT_PTR_NON_NULL(comp,);
    213195    psFree(comp->tilesize);
    214196}
     
    256238                                 const char *extword)
    257239{
    258     PS_ASSERT_PTR_NON_NULL(fits,    false);
     240    PS_ASSERT_FITS_NON_NULL(fits,   false);
    259241    PS_ASSERT_PTR_NON_NULL(extname, false);
    260242    PS_ASSERT_PTR_NON_NULL(extword, false);
     
    301283                       const char* extname)
    302284{
    303     int status = 0;
    304 
    305     if (fits == NULL) {
    306         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    307                 _("The input psFits object can not NULL."));
    308         return false;
    309     }
    310 
    311     if (extname == NULL) {
    312         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    313                 _("Specified extension name can not be NULL."));
    314         return false;
    315     }
     285    PS_ASSERT_FITS_NON_NULL(fits, false);
     286    PS_ASSERT_STRING_NON_EMPTY(extname, false);
     287
     288    int status = 0;
    316289
    317290    if (fits->extword != NULL) {
     
    336309                      bool relative)
    337310{
    338     if (fits == NULL) {
    339         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    340                 _("The input psFits object can not NULL."));
    341         return false;
    342     }
     311    PS_ASSERT_FITS_NON_NULL(fits, false);
    343312
    344313    int status = 0;
     
    372341bool psFitsMoveLast(psFits* fits)
    373342{
    374     if (fits == NULL) {
    375         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    376                 _("The input psFits object can not NULL."));
    377         return false;
    378     }
     343    PS_ASSERT_FITS_NON_NULL(fits, false);
     344
    379345    int size = psFitsGetSize(fits);
    380346    if (size == 0) { // empty file -- no action needed
     
    387353int psFitsGetExtNum(const psFits* fits)
    388354{
     355    PS_ASSERT_FITS_NON_NULL(fits, false);
    389356    int hdunum;
    390 
    391     if (fits == NULL) {
    392         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    393                 _("The input psFits object can not NULL."));
    394         return PS_FITS_TYPE_NONE;
    395     }
    396 
    397 
    398357    return fits_get_hdu_num(fits->fd,&hdunum) - 1;
    399358}
     
    401360psString psFitsGetExtName(const psFits* fits)
    402361{
    403     if (fits == NULL) {
    404         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    405                 _("The input psFits object can not NULL."));
    406         return NULL;
    407     }
     362    PS_ASSERT_FITS_NON_NULL(fits, NULL);
    408363
    409364    int status = 0;
     
    422377bool psFitsSetExtName(psFits* fits, const char* name)
    423378{
    424     if (fits == NULL) {
    425         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    426                 _("The input psFits object can not NULL."));
    427         return false;
    428     }
    429 
    430     if (name == NULL) {
    431         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    432                 _("Specified extension name can not be NULL."));
    433         return false;
    434     }
     379    PS_ASSERT_FITS_NON_NULL(fits, false);
     380    PS_ASSERT_STRING_NON_EMPTY(name, false);
    435381
    436382    int status = 0;
     
    454400                        bool relative)
    455401{
    456     if (fits == NULL) {
    457         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    458                 _("The input psFits object can not NULL."));
    459         return false;
    460     }
     402    PS_ASSERT_FITS_NON_NULL(fits, false);
    461403
    462404    if (! fits->writable) {
     
    492434                         const char* extname)
    493435{
    494     if (fits == NULL) {
    495         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    496                 _("The input psFits object can not NULL."));
    497         return false;
    498     }
     436    PS_ASSERT_FITS_NON_NULL(fits, false);
     437    PS_ASSERT_STRING_NON_EMPTY(extname, false);
    499438
    500439    if (! fits->writable) {
     
    530469int psFitsGetSize(const psFits* fits)
    531470{
    532     if (fits == NULL) {
    533         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    534                 _("The input psFits object can not NULL."));
    535         return 0;
    536     }
     471    PS_ASSERT_FITS_NON_NULL(fits, 0);
    537472
    538473    int num = 0;
     
    553488psFitsType psFitsGetExtType(const psFits* fits)
    554489{
    555     if (fits == NULL) {
    556         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    557                 _("The input psFits object can not NULL."));
    558         return PS_FITS_TYPE_NONE;
    559     }
     490    PS_ASSERT_FITS_NON_NULL(fits, PS_FITS_TYPE_NONE);
    560491
    561492    int status = 0;
     
    582513bool psFitsTruncate(psFits* fits)
    583514{
    584     if (fits == NULL) {
    585         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    586                 _("The input psFits object can not NULL."));
    587         return PS_FITS_TYPE_NONE;
    588     }
     515    PS_ASSERT_FITS_NON_NULL(fits, NULL);
    589516
    590517    if (! fits->writable) {
     
    623550)
    624551{
     552    PS_ASSERT_FITS_NON_NULL(fits, false);
     553
    625554    // convert psFitsCompressionType to cfitsio compression types
    626555    int comptype;
     
    708637}
    709638
     639psFitsCompression *psFitsCompressionGet(psFits* fits)
     640{
     641    PS_ASSERT_FITS_NON_NULL(fits, NULL);
     642
     643    int status = 0;                     // cfitsio status
     644
     645    psFitsCompressionType type = psFitsCompressionGetType(fits);
     646    if (type < 0) {
     647        psError(PS_ERR_UNKNOWN, false, "Unable to get compression type.");
     648        return NULL;
     649    }
     650
     651    psElemType tileType;                // Type corresponding to "long"
     652    if (sizeof(long) == sizeof(psS64)) {
     653        tileType = PS_TYPE_S64;
     654    } else if (sizeof(long) == sizeof(psS32)) {
     655        tileType = PS_TYPE_S32;
     656    } else {
     657        psAbort("can't map (long) type to a psLib type");
     658    }
     659
     660    psVector *tiles = psVectorAlloc(3, tileType); // Tile sizes
     661    if (fits_get_tile_dim(fits->fd, 3, (long*)tiles->data.U8, &status)) {
     662        psFitsError(status, true, "Unable to get compression tile sizes.");
     663        psFree(tiles);
     664        return NULL;
     665    }
     666
     667    int noisebits;                      // Noise bits for compression
     668    if (fits_get_noise_bits(fits->fd, &noisebits, &status)) {
     669        psFitsError(status, true, "Unable to get compression noise bits.");
     670        psFree(tiles);
     671        return NULL;
     672    }
     673
     674    int hscale = 0, hsmooth = 0;        // Scaling and smoothing for HCOMPRESS
     675
     676#if FITS_HCOMP
     677    if (fits_get_hcomp_scale(fits->fd, &hscale, &status)) {
     678        psFitsError(status, true, "Unable to get HCOMPRESS scaling.");
     679        psFree(tiles);
     680        return NULL;
     681    }
     682    if (fits_get_hcomp_smooth(fits->fd, &hsmooth, &status)) {
     683        psFitsError(status, true, "Unable to get HCOMPRESS smoothing.");
     684        psFree(tiles);
     685        return NULL;
     686    }
     687#endif // FITS_HCOMP
     688
     689    psFitsCompression *compress = psFitsCompressionAlloc(type, tiles, noisebits, hscale, hsmooth);
     690    psFree(tiles);                      // Drop reference
     691
     692    return compress;
     693}
     694
     695psFitsCompressionType psFitsCompressionGetType(psFits* fits)
     696{
     697    PS_ASSERT_FITS_NON_NULL(fits, -1);
     698
     699    int status = 0;                     // cfitsio status
     700    int comptype = 0;                   // cfitsio compression type
     701    if (fits_get_compression_type(fits->fd, &comptype, &status)) {
     702        psFitsError(status, true, "Unable to get compression type.");
     703        return -1;
     704    }
     705
     706    psFitsCompressionType type;
     707    switch (comptype) {
     708      case 0:
     709        type = PS_FITS_COMPRESS_NONE;
     710        break;
     711      case GZIP_1:
     712        type = PS_FITS_COMPRESS_GZIP;
     713        break;
     714      case RICE_1:
     715        type = PS_FITS_COMPRESS_RICE;
     716        break;
     717      case HCOMPRESS_1:
     718        type = PS_FITS_COMPRESS_HCOMPRESS;
     719        break;
     720      case PLIO_1:
     721        type = PS_FITS_COMPRESS_PLIO;
     722        break;
     723      default:
     724        psError(PS_ERR_UNKNOWN, true, "cfitsio reports unknown compression type.");
     725        return -1;
     726    }
     727
     728    return type;
     729}
     730
    710731
    711732bool psFitsCompressionApply(
  • branches/pap_branch_070920/psLib/src/fits/psFits.h

    r15111 r15168  
    44 * @author Robert DeSonia, MHPCC
    55 *
    6  * @version $Revision: 1.31.2.2 $ $Name: not supported by cvs2svn $
    7  * @date $Date: 2007-09-29 21:55:41 $
     6 * @version $Revision: 1.31.2.3 $ $Name: not supported by cvs2svn $
     7 * @date $Date: 2007-10-03 03:01:45 $
    88 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
    99 */
     
    5555    bool writable;                      ///< Is the file writable?
    5656    char *extword;                      ///< user-specified word to name extensions (NULL implies EXTNAME)
     57    bool compression;                   ///< Treat compressed images automatically?
    5758} psFits;
    5859
     
    140141 */
    141142bool psFitsSetCompression(
    142     psFits* fits,                       ///< psFits object to close
     143    psFits* fits,                       ///< psFits object for which to set compression
    143144    psFitsCompressionType type,         ///< type of compression
    144145    psVector *tilesize,                 ///< vector defining compression tile size
     
    148149);
    149150
     151/// Get the compression options for a file handle
     152psFitsCompression *psFitsCompressionGet(
     153    psFits* fits                        ///< psFits object for which to get compression
     154);
     155
     156/// Get the compression type for a file handle
     157psFitsCompressionType psFitsCompressionGetType(
     158    psFits* fits                        ///< psFits object for which to get compression type
     159    );
     160
    150161/** Sets FITS write options
    151162 *
     
    153164 */
    154165bool psFitsCompressionApply(
    155     psFits* fits,                       ///< psFits object to close
     166    psFits* fits,                       ///< psFits object for which to set compression
    156167    psFitsCompression *compress         ///< options object
    157168);
     
    290301                          );
    291302
     303#define PS_ASSERT_FITS_NON_NULL(NAME, RVAL) \
     304if (!(NAME) || !(NAME)->fd) { \
     305    psError(PS_ERR_UNEXPECTED_NULL, true, "Error: FITS file pointer %s is NULL", #NAME); \
     306    return RVAL; \
     307}
     308
    292309/// @}
    293310#endif // #ifndef PS_FITS_H
  • branches/pap_branch_070920/psLib/src/fits/psFitsHeader.c

    r15154 r15168  
    77 *  @author Robert DeSonia, MHPCC
    88 *
    9  *  @version $Revision: 1.34.4.4 $ $Name: not supported by cvs2svn $
    10  *  @date $Date: 2007-10-01 21:51:42 $
     9 *  @version $Revision: 1.34.4.5 $ $Name: not supported by cvs2svn $
     10 *  @date $Date: 2007-10-03 03:01:45 $
    1111 *
    1212 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    6868
    6969
    70 bool psFitsEmptyPHU(const psFits *fits, const psMetadata *header)
    71 {
    72     PS_ASSERT_PTR_NON_NULL(fits, false);
    73     PS_ASSERT_METADATA_NON_NULL(header, false);
     70bool psFitsCheckSingleCompressedImagePHU(const psFits *fits, psMetadata *header)
     71{
     72    PS_ASSERT_FITS_NON_NULL(fits, false);
     73
     74    if (!fits->compression) {
     75        // User has turned off compression conventions; doesn't want any nasty surprises
     76        return false;
     77    }
    7478
    7579    if (psFitsGetExtNum(fits) != 0) {
    76         // It's not the PHU, so it can't be an empty PHU!
    77         return false;
    78     }
    79 
    80     if (header->list->n == 0) {
    81         // There's nothing in the list
     80        // It's not the PHU, so it can't be the PHU for a single compressed image!
     81        return false;
     82    }
     83
     84    if (psFitsGetSize(fits) != 2) {
     85        // No second extension, or multiple extensions
     86        return false;
     87    }
     88
     89    int numKeys;                        // Number of keywords in the header
     90    int status = 0;                     // CFITSIO status
     91    fits_get_hdrspace(fits->fd, &numKeys, 0, &status);
     92    if (numKeys >= NUM_EMPTY_KEYS) {
     93        return false;
     94    }
     95
     96    int bitpix, naxis;                  // Bits per pixel and number of axes
     97    long naxes[MAX_COMPRESS_DIM];       // Dimensions
     98    fits_get_img_param(fits->fd, MAX_COMPRESS_DIM, &bitpix, &naxis, naxes, &status);
     99    if (naxis != 0) {
     100        return false;
     101    }
     102
     103    if (!header) {
     104        for (int i = 1; i <= numKeys; i++) {
     105            // Just want to read the keyword names, without parsing the values and stuffing into a metadata
     106            char keyName[MAX_STRING_LENGTH];// Keyword name
     107            char keyValue[MAX_STRING_LENGTH]; // Corresponding value
     108            char keyComment[MAX_STRING_LENGTH]; // Corresponding comment
     109            fits_read_keyn(fits->fd, i, keyName, keyValue, keyComment, &status);
     110            if (!keywordInList(keyName, emptyKeys)) {
     111                return false;
     112            }
     113        }
     114    } else {
     115        psMetadataIterator *iter = psMetadataIteratorAlloc(header, PS_LIST_HEAD, NULL); // Iterator
     116        psMetadataItem *item;           // Item from iteration
     117        while ((item = psMetadataGetAndIncrement(iter))) {
     118            if (!keywordInList(item->name, emptyKeys)) {
     119                psFree(iter);
     120                return false;
     121            }
     122        }
     123        psFree(iter);
     124    }
     125
     126    if (!psFitsMoveExtNum(fits, 1, false)) {
     127        psWarning("Unable to examine first extension as suspect compressed image.");
     128        return false;
     129    }
     130
     131    if (fits_is_compressed_image(fits->fd, &status)) {
    82132        return true;
    83133    }
    84134
    85     // Check if it's got any keywords of potential interest
    86     psMetadataIterator *iter = psMetadataIteratorAlloc(header, PS_LIST_HEAD, NULL); // Iterator
    87     psMetadataItem *item;               // Item from iteration
    88     while ((item = psMetadataGetAndIncrement(iter))) {
    89         if (!keywordInList(item->name, emptyKeys)) {
    90             psFree(iter);
    91             return false;
    92         }
    93     }
    94     psFree(iter);
    95 
    96     return true;
    97 }
    98 
    99 
    100 psMetadata* psFitsReadHeader(psMetadata* out,
    101                              const psFits* fits)
    102 {
    103     if (fits == NULL) {
    104         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    105                 _("The input psFits object can not NULL."));
    106         return NULL;
    107     }
    108 
    109     if (out == NULL) {
    110         out = psMetadataAlloc();
    111     }
     135    // It's not a single compressed image PHU --- move back to the PHU for the user
     136    if (!psFitsMoveExtNum(fits, 0, false)) {
     137        psWarning("Unable to examine first extension as suspect compressed image.");
     138        return false;
     139    }
     140
     141    return false;
     142}
     143
     144// Read the header
     145static psMetadata *readHeader(const psFits *fits // FITS file from which to read header
     146                              )
     147{
     148    assert(fits);
     149
     150    psMetadata *header = psMetadataAlloc(); // Header, to return
    112151
    113152    // Get number of key names
     
    150189        case 'X': // bit
    151190        case 'B': // byte
    152             success = psMetadataAddS8(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, atoi(keyValue));
     191            success = psMetadataAddS8(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, atoi(keyValue));
    153192            break;
    154193        case 'I': // short int.
     
    156195            // Trap NAN, INF and -INF, which cfitsio doesn't handle.
    157196            if (strncasecmp(keyValue, "NAN", 3) == 0) {
    158                 success = psMetadataAddF32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, NAN);
     197                success = psMetadataAddF32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, NAN);
    159198            } else if (strncasecmp(keyValue, "INF", 3) == 0) {
    160                 success = psMetadataAddF32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, INFINITY);
     199                success = psMetadataAddF32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, INFINITY);
    161200            } else if (strncasecmp(keyValue, "-INF", 4) == 0) {
    162                 success = psMetadataAddF32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, -INFINITY);
     201                success = psMetadataAddF32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, -INFINITY);
    163202            } else {
    164                 success = psMetadataAddS32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, atoi(keyValue));
     203                success = psMetadataAddS32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment,
     204                                           atoi(keyValue));
    165205            }
    166206            break;
    167207        case 'J': // int.
    168             success = psMetadataAddS32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, atoi(keyValue));
     208            success = psMetadataAddS32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, atoi(keyValue));
    169209            break;
    170210        case 'U': // unsigned int.
    171             success = psMetadataAddU32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, atol(keyValue));
     211            success = psMetadataAddU32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, atol(keyValue));
    172212            break;
    173213
    174214        case 'K': // long int. can't all fit in a psS32, put in psF64
    175215        case 'F':
    176             success = psMetadataAddF64(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, atof(keyValue));
     216            success = psMetadataAddF64(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, atof(keyValue));
    177217            break;
    178218        case 'C': {
     
    195235                // cfitsio won't write these, so we write them as strings, and then have to trap them on read.
    196236                if (strcasecmp(keyValueFixed, "NAN") == 0) {
    197                     success = psMetadataAddF32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, NAN);
     237                    success = psMetadataAddF32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, NAN);
    198238                } else if (strcasecmp(keyValueFixed, "INF") == 0) {
    199                     success = psMetadataAddF32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, INFINITY);
     239                    success = psMetadataAddF32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, INFINITY);
    200240                } else if (strcasecmp(keyValueFixed, "-INF") == 0) {
    201                     success = psMetadataAddF32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, -INFINITY);
     241                    success = psMetadataAddF32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, -INFINITY);
    202242                } else {
    203                     success = psMetadataAddStr(out, PS_LIST_TAIL, keyName, dupFlag, keyComment,
     243                    success = psMetadataAddStr(header, PS_LIST_TAIL, keyName, dupFlag, keyComment,
    204244                                               keyValueFixed);
    205245                }
     
    208248        case 'L': {
    209249                bool temp = (keyValue[0] == 'T') ? 1 : 0;
    210                 success = psMetadataAddBool(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, temp);
     250                success = psMetadataAddBool(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, temp);
    211251                break;
    212252            }
    213253        default:
    214254            psError(PS_ERR_IO, true, _("Specified FITS metadata type, %c, is not supported."), keyType);
    215             return out;
     255            psFree(header);
     256            return NULL;
    216257        }
    217258
    218259        if (!success) {
    219260            psError(PS_ERR_UNKNOWN, false, _("Failed to add metadata item, %s."), keyName);
    220             return out;
     261            psFree(header);
     262            return NULL;
    221263        }
    222264
     
    227269        (void)fits_get_errstatus(status, fitsErr);
    228270        psError(PS_ERR_IO, true, _("Failed to add metadata item, %s."), fitsErr);
    229         return false;
    230     }
    231 
     271        psFree(header);
     272        return false;
     273    }
     274
     275    return header;
     276}
     277
     278
     279psMetadata* psFitsReadHeader(psMetadata* out,
     280                             const psFits* fits)
     281{
     282    PS_ASSERT_FITS_NON_NULL(fits, NULL);
     283
     284    psMetadata *header = readHeader(fits); // Header
     285    if (!header) {
     286        return NULL;
     287    }
     288
     289    // Explore the potential case that this is an empty PHU, and the first extension contains the sole image,
     290    // which is compressed.
     291    if (psFitsCheckSingleCompressedImagePHU(fits, header)) {
     292        // This is really what we want, not the empty PHU
     293        psTrace("psLib.fits", 1,
     294                "This PHU should really be a compressed image --- getting that header instead.");
     295        psFree(header);
     296        header = readHeader(fits);
     297        if (!header) {
     298            return NULL;
     299        }
     300    }
     301
     302    if (!out) {
     303        return header;
     304    }
     305
     306    // Need to move header onto the nominated metadata
     307    psMetadataIterator *iter = psMetadataIteratorAlloc(header, PS_LIST_HEAD, NULL); // Iterator
     308    psMetadataItem *item;           // Item from iteration
     309    while ((item = psMetadataGetAndIncrement(iter))) {
     310        // Need to look for MULTI, which won't be picked up using the iterator.
     311        psMetadataItem *multiCheckItem = psMetadataLookup(header, item->name);
     312        assert(multiCheckItem);
     313        unsigned int flag = 0;      // Flag to indicate MULTI; otherwise default action
     314        if (multiCheckItem->type == PS_DATA_METADATA_MULTI) {
     315            flag = PS_META_DUPLICATE_OK;
     316        }
     317        if (!psMetadataAddItem(out, item, PS_LIST_TAIL, flag)) {
     318            psError(PS_ERR_UNKNOWN, false, "Unable to add header item %s to extant metadata.",
     319                    item->name);
     320            psFree(iter);
     321            psFree(header);
     322            return NULL;
     323        }
     324    }
     325    psFree(iter);
     326    psFree(header);
    232327    return out;
    233328}
     
    235330psMetadata* psFitsReadHeaderSet(psMetadata* out, const psFits* fits)
    236331{
    237     if (fits == NULL) {
    238         psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psFits object can not NULL."));
    239         psFree(out);
    240         return NULL;
    241     }
    242 
    243     if (out == NULL) {
     332    PS_ASSERT_FITS_NON_NULL(fits, NULL);
     333
     334    if (!out) {
    244335        out = psMetadataAlloc();
    245336    }
     
    378469                        }
    379470                    } else {
    380                         fits_update_key(fits->fd, TFLOAT, item->name, &item->data.F32, item->comment, &status);
     471                        fits_update_key(fits->fd, TFLOAT, item->name, &item->data.F32, item->comment,
     472                                        &status);
    381473                    }
    382474                    break;
     
    393485                        }
    394486                    } else {
    395                         fits_update_key(fits->fd, TDOUBLE, item->name, &item->data.F64, item->comment, &status);
     487                        fits_update_key(fits->fd, TDOUBLE, item->name, &item->data.F64, item->comment,
     488                                        &status);
    396489                    }
    397490                    break;
     
    424517                      )
    425518{
    426     if (!fits) {
    427         psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psFits object can not NULL."));
    428         return false;
    429     }
    430 
    431     if (!output) {
    432         psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psMetadata was NULL.  Need a non-NULL psMetadata for operation to be performed."));
    433         return false;
    434     }
     519    PS_ASSERT_FITS_NON_NULL(fits, false);
     520    PS_ASSERT_METADATA_NON_NULL(output, false);
    435521
    436522    return fitsWriteHeader(fits, output, true);
     
    442528                     )
    443529{
    444     if (!fits) {
    445         psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psFits object can not NULL."));
    446         return false;
    447     }
     530    PS_ASSERT_FITS_NON_NULL(fits, false);
    448531
    449532    // We allow output == NULL in order to write a minimal header.
     
    487570bool psFitsHeaderValidate(psMetadata *header)
    488571{
    489     if (header == NULL) {
    490         psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psMetadata was NULL.  Need a non-NULL psMetadata for operation to be performed."));
    491         return false;
    492     }
     572    PS_ASSERT_METADATA_NON_NULL(header, false);
    493573
    494574    // Traverse the metadata list and inspect at each key
  • branches/pap_branch_070920/psLib/src/fits/psFitsHeader.h

    r14985 r15168  
    44 * @author Robert DeSonia, MHPCC
    55 *
    6  * @version $Revision: 1.10.14.1 $ $Name: not supported by cvs2svn $
    7  * @date $Date: 2007-09-22 03:08:05 $
     6 * @version $Revision: 1.10.14.2 $ $Name: not supported by cvs2svn $
     7 * @date $Date: 2007-10-03 03:01:45 $
    88 *
    99 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    1919#include "psMetadata.h"
    2020
    21 /// Determines whether the current HDU is an empty PHU
    22 bool psFitsEmptyPHU(const psFits *fits, ///< FITS file pointer
    23                     const psMetadata *header ///< Header
     21
     22/// Determine whether the current HDU is an empty PHU with a single compressed image following.
     23///
     24/// In that case, what should be treated as an image PHU is technically an empty PHU with a binary table
     25/// extension.  We test the current position, number of extensions, the FITS headers and presence of a
     26/// following compressed image to determine if this is the case.  If so, the FITS file pointer is left
     27/// pointing at the compressed image.
     28bool psFitsCheckSingleCompressedImagePHU(const psFits *fits, ///< FITS file pointer
     29                                         const psMetadata *header ///< Header, or NULL
    2430    );
    25 
    2631
    2732/** Reads the header of the current HDU.
  • branches/pap_branch_070920/psLib/src/fits/psFitsImage.c

    r15110 r15168  
    77 *  @author Robert DeSonia, MHPCC
    88 *
    9  *  @version $Revision: 1.17.14.1 $ $Name: not supported by cvs2svn $
    10  *  @date $Date: 2007-09-29 21:55:05 $
     9 *  @version $Revision: 1.17.14.2 $ $Name: not supported by cvs2svn $
     10 *  @date $Date: 2007-10-03 03:01:45 $
    1111 *
    1212 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    5454                                              )
    5555{
    56     PS_ASSERT_PTR_NON_NULL(fits, NULL);
     56    PS_ASSERT_FITS_NON_NULL(fits, NULL);
    5757    PS_ASSERT_INT_NONNEGATIVE(z, NULL);
    5858
     
    219219                        )
    220220{
     221    PS_ASSERT_FITS_NON_NULL(fits, NULL);
     222    PS_ASSERT_INT_NONNEGATIVE(z, NULL);
     223
     224    if (psFitsCheckSingleCompressedImagePHU(fits, NULL)) {
     225        // This is really what we want, not the empty PHU
     226        psTrace("psLib.fits", 1,
     227                "This PHU should really be a compressed image --- reading that image instead.");
     228    }
     229
    221230    p_psFitsReadInfo *info = p_psFitsReadInfoAlloc(fits, region, z);
    222231
     
    241250                              )
    242251{
     252    PS_ASSERT_FITS_NON_NULL(fits, NULL);
     253    PS_ASSERT_INT_NONNEGATIVE(z, NULL);
     254
    243255    if (output && output->parent) {
    244256        psError(PS_ERR_IO, true, "Unable to read into a buffer for a child image.\n");
    245257        return NULL;
     258    }
     259
     260    if (psFitsCheckSingleCompressedImagePHU(fits, NULL)) {
     261        // This is really what we want, not the empty PHU
     262        psTrace("psLib.fits", 1,
     263                "This PHU should really be a compressed image --- reading that image instead.");
    246264    }
    247265
     
    268286                      const char* extname)
    269287{
     288    PS_ASSERT_FITS_NON_NULL(fits, false);
     289    PS_ASSERT_IMAGE_NON_NULL(input, false);
    270290    // this is equivalent to insert after the last HDU
    271291
     
    281301                       bool after)
    282302{
    283 
    284     if (!fits) {
    285         psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psFits object can not NULL."));
    286         return false;
    287     }
    288 
    289     if (!input) {
    290         psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psImage was NULL.  Need a non-NULL psImage for operation to be performed."));
    291         return false;
    292     }
     303    PS_ASSERT_FITS_NON_NULL(fits, false);
     304    PS_ASSERT_IMAGE_NON_NULL(input, false);
    293305
    294306    int numCols = input->numCols;       // Number of columns for image
     
    389401                       int z)
    390402{
     403    PS_ASSERT_FITS_NON_NULL(fits, false);
     404    PS_ASSERT_IMAGE_NON_NULL(input, false);
     405
    391406    int status = 0;
    392 
    393     if (fits == NULL) {
    394         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    395                 _("The input psFits object can not NULL."));
    396         return false;
    397     }
    398 
    399     if (input == NULL) {
    400         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    401                 _("The input psImage was NULL.  Need a non-NULL psImage for operation to be performed."));
    402         return false;
    403     }
    404407
    405408    // check to see if we are positioned on an image HDU
     
    497500psArray *psFitsReadImageCube(const psFits *fits, psRegion region)
    498501{
     502    PS_ASSERT_FITS_NON_NULL(fits, NULL);
     503
    499504    int nAxis = 0;                      // Number of axes
    500505    long nAxes[3];                      // Number of pixels on each axis
     
    502507    char fitsErr[80] = "";              // CFITSIO error message string
    503508
    504     if (fits == NULL) {
    505         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    506                 _("The input psFits object can not NULL."));
    507         return NULL;
    508     }
    509 
    510509    // Some of this replicates what is in psFitsReadImage, so it's a little inefficient.  But it saves
    511510    // code replication, and should be sufficient for our needs.
     511
     512    if (psFitsCheckSingleCompressedImagePHU(fits, NULL)) {
     513        // This is really what we want, not the empty PHU
     514        psTrace("psLib.fits", 1,
     515                "This PHU should really be a compressed image --- reading that image instead.");
     516    }
    512517
    513518    if (fits_get_img_dim(fits->fd, &nAxis, &status) != 0) {
     
    542547
    543548    // Bad dimensionality
    544     psError(PS_ERR_IO, true, _("Image number of dimensions, %d, is not valid.  Only two or three dimensions supported for FITS I/O."), nAxis);
     549    psError(PS_ERR_IO, true,
     550            _("Image number of dimensions, %d, is not valid."
     551              " Only two or three dimensions supported for FITS I/O."), nAxis);
    545552    return NULL;
    546553}
     
    548555bool psFitsWriteImageCube(psFits *fits, psMetadata *header, const psArray *input, const char *extname)
    549556{
    550     if (fits == NULL) {
    551         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    552                 _("The input psFits object can not NULL."));
    553         return false;
    554     }
    555 
    556     if (input == NULL) {
    557         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    558                 _("The input psImage was NULL.  Need a non-NULL psImage for operation to be performed."));
    559         return false;
    560     }
     557    PS_ASSERT_FITS_NON_NULL(fits, false);
     558    PS_ASSERT_ARRAY_NON_NULL(input, false);
    561559
    562560    if (input->n == 0) {
     
    590588    }
    591589    bool update = psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS", PS_META_REPLACE, "Dimensionality", 3) &&
    592                   psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS1", PS_META_REPLACE, "Number of columns", numCols) &&
    593                   psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS2", PS_META_REPLACE, "Number of rows", numRows) &&
    594                   psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS3", PS_META_REPLACE, "Number of image planes",
    595                                    input->n);
     590        psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS1", PS_META_REPLACE, "Number of columns", numCols) &&
     591        psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS2", PS_META_REPLACE, "Number of rows", numRows) &&
     592        psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS3", PS_META_REPLACE, "Number of image planes",
     593                         input->n);
    596594    if (! update) {
    597595        psError(PS_ERR_UNKNOWN, false, _("Failed to add metadata item, %s."),
     
    623621bool psFitsUpdateImageCube(psFits *fits, const psArray *input, int x0, int y0)
    624622{
    625     if (fits == NULL) {
    626         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    627                 _("The input psFits object can not NULL."));
    628         return false;
    629     }
    630 
    631     if (input == NULL) {
    632         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    633                 _("The input psImage was NULL.  Need a non-NULL psImage for operation to be performed."));
    634         return false;
    635     }
     623    PS_ASSERT_FITS_NON_NULL(fits, false);
     624    PS_ASSERT_ARRAY_NON_NULL(input, false);
    636625
    637626    if (input->n == 0) {
  • branches/pap_branch_070920/psLib/src/fits/psFitsTable.c

    r12549 r15168  
    77 *  @author Robert DeSonia, MHPCC
    88 *
    9  *  @version $Revision: 1.27 $ $Name: not supported by cvs2svn $
    10  *  @date $Date: 2007-03-22 21:40:47 $
     9 *  @version $Revision: 1.27.10.1 $ $Name: not supported by cvs2svn $
     10 *  @date $Date: 2007-10-03 03:01:45 $
    1111 *
    1212 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    3838                               int row)
    3939{
     40    PS_ASSERT_FITS_NON_NULL(fits, NULL);
     41    PS_ASSERT_INT_NONNEGATIVE(row, NULL);
     42
    4043    long numRows;
    4144    int numCols;
    4245    int status = 0;
    43 
    44     if (fits == NULL) {
    45         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    46                 _("The input psFits object can not NULL."));
    47         return NULL;
    48     }
    4946
    5047    // check to see if we even are positioned on a table HDU
     
    185182                               const char* colname)
    186183{
     184    PS_ASSERT_FITS_NON_NULL(fits, NULL);
     185    PS_ASSERT_STRING_NON_EMPTY(colname, NULL);
     186
    187187    int colnum = 0;
    188188    int status = 0;
    189 
    190     if (fits == NULL) {
    191         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    192                 _("The input psFits object can not NULL."));
    193         return NULL;
    194     }
    195189
    196190    // check to see if we even are positioned on a table HDU
     
    266260                                   const char* colname)
    267261{
     262    PS_ASSERT_FITS_NON_NULL(fits, NULL);
     263    PS_ASSERT_STRING_NON_EMPTY(colname, NULL);
     264
    268265    int status = 0;
    269266    int colnum = 0;
    270 
    271     if (fits == NULL) {
    272         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    273                 _("The input psFits object can not NULL."));
    274         return NULL;
    275     }
    276267
    277268    // check to see if we even are positioned on a table HDU
     
    348339psArray* psFitsReadTable(const psFits* fits)
    349340{
     341    PS_ASSERT_FITS_NON_NULL(fits, NULL);
     342
    350343    int status = 0;
    351 
    352     if (fits == NULL) {
    353         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    354                 _("The input psFits object can not NULL."));
    355         return NULL;
    356     }
    357344
    358345    // check to see if we even are positioned on a table HDU
     
    400387                      const char *extname)
    401388{
    402     psFitsMoveLast(fits);
     389    PS_ASSERT_FITS_NON_NULL(fits, false);
     390    if (!psFitsMoveLast(fits)) {
     391        psError(PS_ERR_UNKNOWN, false, "Unable to move to last extension to write table");
     392        return false;
     393    }
    403394    return psFitsInsertTable(fits, header, table, extname, true);
    404395}
     
    460451// Column specification
    461452// Included here, because there's no need for the user to have access to it
    462 typedef struct
    463 {
     453typedef struct {
    464454    psDataType type;                    // psLib type (e.g., PS_DATA_STRING or PS_TYPE_F32)
    465455    size_t size;                        // Size (number of repeats)
    466456    psElemType vectorType;              // psLib type of vectors
    467 }
    468 colSpec;
     457} colSpec;
    469458
    470459
     
    475464                       bool after)
    476465{
     466    PS_ASSERT_FITS_NON_NULL(fits, false);
     467    PS_ASSERT_ARRAY_NON_NULL(table, false);
     468
    477469    int status = 0;
    478 
    479     PS_ASSERT_PTR_NON_NULL(fits, false);
    480     PS_ASSERT_ARRAY_NON_NULL(table, false);
    481470
    482471    long numRows = table->n;
     
    614603        char fitsErr[MAX_STRING_LENGTH];
    615604        fits_get_errstatus(status, fitsErr);
    616         psError(PS_ERR_LOCATION_INVALID, true, "Unable to create FITS table with %ld columns and %ld rows: %s",
     605        psError(PS_ERR_LOCATION_INVALID, true,
     606                "Unable to create FITS table with %ld columns and %ld rows: %s",
    617607                numColumns, table->n, fitsErr);
    618608        psFree(colSpecsIter);
     
    632622    if (extname && strlen(extname) > 0) {
    633623        if (!psFitsSetExtName(fits, extname)) {
    634             psError(PS_ERR_IO, false, "Unable to write FITS header extension name.\n");
    635             psFree(colSpecsIter);
    636             psFree(colSpecs);
    637             return false;
    638         }
     624            psError(PS_ERR_IO, false, "Unable to write FITS header extension name.\n");
     625            psFree(colSpecsIter);
     626            psFree(colSpecs);
     627            return false;
     628        }
    639629    }
    640630
     
    728718                       int row)
    729719{
     720    PS_ASSERT_FITS_NON_NULL(fits, false);
     721    PS_ASSERT_METADATA_NON_NULL(data, false);
     722    PS_ASSERT_INT_NONNEGATIVE(row, false);
     723
    730724    int status = 0;
    731 
    732     if (fits == NULL) {
    733         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    734                 _("The input psFits object can not NULL."));
    735         return false;
    736     }
    737 
    738     if (data == NULL) {
    739         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    740                 _("The input psImage was NULL.  Need a non-NULL psImage for operation to be performed."));
    741         return false;
    742     }
    743725
    744726    // check to see if we even are positioned on a table HDU
Note: See TracChangeset for help on using the changeset viewer.