Changeset 15179
- Timestamp:
- Oct 3, 2007, 11:27:21 AM (19 years ago)
- Location:
- trunk/psLib/src/fits
- Files:
-
- 6 edited
-
psFits.c (modified) (28 diffs)
-
psFits.h (modified) (10 diffs)
-
psFitsHeader.c (modified) (15 diffs)
-
psFitsHeader.h (modified) (2 diffs)
-
psFitsImage.c (modified) (15 diffs)
-
psFitsTable.c (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/fits/psFits.c
r14878 r15179 7 7 * @author Robert DeSonia, MHPCC 8 8 * 9 * @version $Revision: 1.7 1$ $Name: not supported by cvs2svn $10 * @date $Date: 2007- 09-18 03:01:17$9 * @version $Revision: 1.72 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2007-10-03 21:27:21 $ 11 11 * 12 12 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 20 20 21 21 #include "psFits.h" 22 #include "psFitsHeader.h" 22 23 #include "string.h" 23 24 #include "psError.h" … … 65 66 return false; 66 67 } 67 fits->fd = NULL;68 fits->fd = NULL; 68 69 } 69 70 return true; … … 74 75 if (!fits) return; 75 76 if (fits->fd) { 76 fitsClose(fits);77 fitsClose(fits); 77 78 } 78 79 psFree (fits->extword); … … 81 82 bool psFitsClose(psFits* fits) 82 83 { 83 if (fits == NULL) { 84 psError(PS_ERR_BAD_PARAMETER_NULL, true, 85 _("The input psFits object can not NULL.")); 86 return false; 87 } 84 PS_ASSERT_FITS_NON_NULL(fits, false); 88 85 89 86 bool status = fitsClose(fits); … … 95 92 psFits* psFitsOpen(const char* name, const char* mode) 96 93 { 94 PS_ASSERT_STRING_NON_EMPTY(name, NULL); 95 97 96 int status = 0; 98 97 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 }105 98 106 99 /* check the mode to determine how to open/create file */ … … 131 124 if (access(name, F_OK) == 0) { 132 125 // file exists, delete old one first 133 remove 134 (name); 126 remove(name); 135 127 } 136 128 … … 140 132 (void)fits_create_file 141 133 #endif 142 (&fptr, 143 name, 144 &status); 134 (&fptr, name, &status); 145 135 if (fptr == NULL || status != 0) { 146 char fitsErr[MAX_STRING_LENGTH] 147 ; 136 char fitsErr[MAX_STRING_LENGTH]; 148 137 fits_get_errstatus(status, fitsErr); 149 138 psError(PS_ERR_IO, true, … … 158 147 (void)fits_open_file 159 148 #endif 160 (&fptr, 161 name, 162 iomode, 163 &status); 149 (&fptr, name, iomode, &status); 164 150 if (fptr == NULL || status != 0) { 165 char fitsErr[MAX_STRING_LENGTH] 166 ; 151 char fitsErr[MAX_STRING_LENGTH]; 167 152 fits_get_errstatus(status, fitsErr); 168 153 psError(PS_ERR_IO, true, … … 177 162 fits->writable = (iomode == READWRITE); 178 163 fits->extword = NULL; 164 fits->conventions.compression = true; 179 165 psMemSetDeallocator(fits,(psFreeFunc)fitsFree); 180 166 … … 182 168 } 183 169 184 static void psFitsOptionsFree(psFitsOptions *opt) 185 { 186 psFree(opt->tilesize); 187 } 188 189 psFitsOptions* psFitsOptionsAlloc( 170 psErrorCode p_psFitsError(const char* filename, unsigned int lineno, const char* func, int status, 171 bool new, const char *errorMsg, ...) 172 { 173 if (status == 0) { 174 return PS_ERR_NONE; 175 } 176 177 va_list ap; // Variable arguments 178 va_start(ap, errorMsg); 179 psString msg = NULL; // Message to pass to psError 180 psStringAppendV(&msg, errorMsg, ap); 181 va_end(ap); 182 183 char cfitsioMsg[MAX_STRING_LENGTH]; // Error message from cfitsio 184 (void)fits_get_errstatus(status, cfitsioMsg); 185 186 psStringAppend(&msg, "[CFITSIO error: %s]", cfitsioMsg); 187 188 psErrorCode code = p_psError(filename, lineno, func, PS_ERR_IO, new, msg); // Error code 189 psFree(msg); 190 return code; 191 } 192 193 static void psFitsCompressionFree(psFitsCompression *comp) 194 { 195 PS_ASSERT_PTR_NON_NULL(comp,); 196 psFree(comp->tilesize); 197 } 198 199 psFitsCompression* psFitsCompressionAlloc( 190 200 psFitsCompressionType type, ///< type of compression 191 201 psVector *tilesize, ///< vector defining compression tile size … … 195 205 ) 196 206 { 197 psFitsOptions *opt = psAlloc(sizeof(psFitsOptions)); 198 199 opt->type = type; 200 opt->tilesize = psVectorCopy(NULL, tilesize, PS_DATA_S64); 201 opt->noisebits = noisebits; 202 opt->scale = scale; 203 opt->smooth = smooth; 204 205 psMemSetDeallocator(opt, (psFreeFunc) psFitsOptionsFree); 206 207 return opt; 207 psFitsCompression *comp = psAlloc(sizeof(psFitsCompression)); 208 psMemSetDeallocator(comp, (psFreeFunc) psFitsCompressionFree); 209 210 comp->type = type; 211 comp->tilesize = psVectorCopy(NULL, tilesize, PS_DATA_S64); 212 comp->noisebits = noisebits; 213 comp->scale = scale; 214 comp->smooth = smooth; 215 216 return comp; 208 217 } 209 218 … … 224 233 } 225 234 226 // move to the first HDU where extword == extname. this is equivalent to fits_movnam_hdu() for 227 // a user-defined word in place of EXTNAME 228 bool p_psFitsMoveExtName_UserKey(const psFits *fits, 229 const char *extname, 230 const char *extword) 231 { 232 PS_ASSERT_PTR_NON_NULL(fits, false); 233 PS_ASSERT_PTR_NON_NULL(extname, false); 234 PS_ASSERT_PTR_NON_NULL(extword, false); 235 236 int hdutype = 0; 237 char name[MAX_STRING_LENGTH]; 238 char extstring[MAX_STRING_LENGTH]; 239 240 sprintf (extstring, "'%s'", extname); 241 242 // NOTE: fits_* return 0 for success 243 for (int i = 1; true; i++) { 244 // are we able to read the next HDU? 245 246 int status = 0; 247 if (fits_movabs_hdu(fits->fd, i, &hdutype, &status)) { 248 char fitsErr[MAX_STRING_LENGTH]; 249 fits_get_errstatus(status, fitsErr); 250 psError(PS_ERR_LOCATION_INVALID, true, 251 _("Could not find HDU with %s = '%s'. CFITSIO Error: %s"), 252 extword, extname, fitsErr); 253 return false; 254 } 255 // is there a keyword called 'extword'? (read as string regardless of type) 256 status = 0; 257 if (fits_read_keyword(fits->fd, (char *)extword, name, NULL, &status)) { 258 continue; 259 } 260 // if this was read as a string, we will have leading and trailing single-quotes 261 // try both for comparison 262 263 // do we have the right hdu (names match)? 264 if (!strcmp (name, extname) || !strcmp (name, extstring)) { 265 return true; 266 } 267 } 268 psAbort("we should not reach here"); 269 } 270 271 // XXX I will need to define a low-level function p_psFitsMoveExtName_UserKey () which 272 // uses fits_movabs_hdu() to replicate the functionality of fits_movnam_hdu using an 273 // alternate name for EXTNAME 235 // Files compressed with cfitsio's "imcopy" program may have multiple EXTNAME keywords, with the first set to 236 // COMPRESSED_IMAGE. However, fits_movnam_hdu won't find the second (proper) value of EXTNAME, and so can 237 // fail to find a perfectly legitimate extension, simply because imcopy does something silly. However, we 238 // really want to be able to read these files (MegaCam data are shipped as imcopy-compressed images). 239 // Therefore, we implement our own version of moving to an extension specified by name. The pure cfitsio 240 // version is used if "conventions.compression" handling is turned off in the psFits structure. 274 241 bool psFitsMoveExtName(const psFits* fits, 275 242 const char* extname) 276 243 { 277 int status = 0; 278 279 if (fits == NULL) { 280 psError(PS_ERR_BAD_PARAMETER_NULL, true, 281 _("The input psFits object can not NULL.")); 282 return false; 283 } 284 285 if (extname == NULL) { 286 psError(PS_ERR_BAD_PARAMETER_NULL, true, 287 _("Specified extension name can not be NULL.")); 288 return false; 289 } 290 291 if (fits->extword != NULL) { 292 bool result = p_psFitsMoveExtName_UserKey(fits, extname, fits->extword); 293 return (result); 294 } 295 296 if (fits_movnam_hdu(fits->fd, ANY_HDU, (char*)extname, 0, &status) != 0) { 297 char fitsErr[MAX_STRING_LENGTH]; 298 fits_get_errstatus(status, fitsErr); 299 psError(PS_ERR_LOCATION_INVALID, true, 300 _("Could not find HDU '%s'. CFITSIO Error: %s"), 301 extname, fitsErr); 302 return false; 303 } 304 305 return true; 244 PS_ASSERT_FITS_NON_NULL(fits, false); 245 PS_ASSERT_STRING_NON_EMPTY(extname, false); 246 247 int status = 0; 248 249 if (!fits->conventions.compression && !fits->extword) { 250 // User wants to use cfitsio. Good luck to them! 251 if (fits_movnam_hdu(fits->fd, ANY_HDU, (char*)extname, 0, &status) != 0) { 252 psFitsError(status, true, _("Could not find HDU '%s'"), extname); 253 return false; 254 } 255 return true; 256 } 257 258 bool ignoreCI = (fits->conventions.compression && 259 (strcmp(extname, "COMPRESSED_IMAGE") != 0)); // Ignore COMPRESSED_IMAGE extension name? 260 char *extword = (fits->extword ? fits->extword : "EXTNAME"); // Word to use as extension name 261 262 #if 0 263 // XXX Future optimisation: loop through from the current HDU to the end, then from the start to the 264 // current position. This will save seeking through the file multiple times. 265 int currentExt = psFitsGetExtNum(fits); // Current extension number 266 int numExt = psFitsGetSize(fits); // Total number of extensions 267 #endif 268 269 for (int i = 1; true; i++) { 270 int hdutype = 0; 271 if (fits_movabs_hdu(fits->fd, i, &hdutype, &status)) { 272 // We've run off the end 273 psFitsError(status, true, _("Could not find HDU with %s = '%s'"), extword, extname); 274 return false; 275 } 276 // Is there a keyword called 'extword'? (read as string regardless of type) 277 char name[MAX_STRING_LENGTH]; // Name of extension 278 if (fits_read_keyword(fits->fd, extword, name, NULL, &status)) { 279 // It doesn't exist in the header. 280 // This isn't the extension you're looking for. Move along. 281 status = 0; 282 continue; 283 } 284 char *fixed = p_psFitsHeaderParseString(name); // Parsed version (removing quotes and spaces) 285 286 if (ignoreCI && strcmp(fixed, "COMPRESSED_IMAGE") == 0) { 287 // Read it again, Sam 288 if (fits_read_keyword(fits->fd, extword, name, NULL, &status)) { 289 status = 0; 290 continue; 291 } 292 fixed = p_psFitsHeaderParseString(name); 293 } 294 295 if (strcmp(fixed, extname) == 0) { 296 // We've arrived 297 return true; 298 } 299 } 300 psAbort("Should never reach here."); 306 301 } 307 302 … … 310 305 bool relative) 311 306 { 312 if (fits == NULL) { 313 psError(PS_ERR_BAD_PARAMETER_NULL, true, 314 _("The input psFits object can not NULL.")); 315 return false; 316 } 307 PS_ASSERT_FITS_NON_NULL(fits, false); 317 308 318 309 int status = 0; … … 346 337 bool psFitsMoveLast(psFits* fits) 347 338 { 348 if (fits == NULL) { 349 psError(PS_ERR_BAD_PARAMETER_NULL, true, 350 _("The input psFits object can not NULL.")); 351 return false; 352 } 339 PS_ASSERT_FITS_NON_NULL(fits, false); 340 353 341 int size = psFitsGetSize(fits); 354 342 if (size == 0) { // empty file -- no action needed … … 361 349 int psFitsGetExtNum(const psFits* fits) 362 350 { 351 PS_ASSERT_FITS_NON_NULL(fits, false); 363 352 int hdunum; 364 365 if (fits == NULL) {366 psError(PS_ERR_BAD_PARAMETER_NULL, true,367 _("The input psFits object can not NULL."));368 return PS_FITS_TYPE_NONE;369 }370 371 372 353 return fits_get_hdu_num(fits->fd,&hdunum) - 1; 373 354 } … … 375 356 psString psFitsGetExtName(const psFits* fits) 376 357 { 377 if (fits == NULL) { 378 psError(PS_ERR_BAD_PARAMETER_NULL, true, 379 _("The input psFits object can not NULL.")); 380 return NULL; 381 } 358 PS_ASSERT_FITS_NON_NULL(fits, NULL); 382 359 383 360 int status = 0; … … 389 366 psError(PS_ERR_BAD_PARAMETER_NULL, true, 390 367 _("Header keyword %s is not found"), extword); 391 return NULL;368 return NULL; 392 369 } 393 370 return psStringCopy(name); … … 396 373 bool psFitsSetExtName(psFits* fits, const char* name) 397 374 { 398 if (fits == NULL) { 399 psError(PS_ERR_BAD_PARAMETER_NULL, true, 400 _("The input psFits object can not NULL.")); 401 return false; 402 } 403 404 if (name == NULL) { 405 psError(PS_ERR_BAD_PARAMETER_NULL, true, 406 _("Specified extension name can not be NULL.")); 407 return false; 408 } 375 PS_ASSERT_FITS_NON_NULL(fits, false); 376 PS_ASSERT_STRING_NON_EMPTY(name, false); 409 377 410 378 int status = 0; … … 428 396 bool relative) 429 397 { 430 if (fits == NULL) { 431 psError(PS_ERR_BAD_PARAMETER_NULL, true, 432 _("The input psFits object can not NULL.")); 433 return false; 434 } 398 PS_ASSERT_FITS_NON_NULL(fits, false); 435 399 436 400 if (! fits->writable) { … … 466 430 const char* extname) 467 431 { 468 if (fits == NULL) { 469 psError(PS_ERR_BAD_PARAMETER_NULL, true, 470 _("The input psFits object can not NULL.")); 471 return false; 472 } 432 PS_ASSERT_FITS_NON_NULL(fits, false); 433 PS_ASSERT_STRING_NON_EMPTY(extname, false); 473 434 474 435 if (! fits->writable) { … … 504 465 int psFitsGetSize(const psFits* fits) 505 466 { 506 if (fits == NULL) { 507 psError(PS_ERR_BAD_PARAMETER_NULL, true, 508 _("The input psFits object can not NULL.")); 509 return 0; 510 } 467 PS_ASSERT_FITS_NON_NULL(fits, 0); 511 468 512 469 int num = 0; … … 527 484 psFitsType psFitsGetExtType(const psFits* fits) 528 485 { 529 if (fits == NULL) { 530 psError(PS_ERR_BAD_PARAMETER_NULL, true, 531 _("The input psFits object can not NULL.")); 532 return PS_FITS_TYPE_NONE; 533 } 486 PS_ASSERT_FITS_NON_NULL(fits, PS_FITS_TYPE_NONE); 534 487 535 488 int status = 0; … … 556 509 bool psFitsTruncate(psFits* fits) 557 510 { 558 if (fits == NULL) { 559 psError(PS_ERR_BAD_PARAMETER_NULL, true, 560 _("The input psFits object can not NULL.")); 561 return PS_FITS_TYPE_NONE; 562 } 511 PS_ASSERT_FITS_NON_NULL(fits, NULL); 563 512 564 513 if (! fits->writable) { … … 597 546 ) 598 547 { 548 PS_ASSERT_FITS_NON_NULL(fits, false); 549 599 550 // convert psFitsCompressionType to cfitsio compression types 600 551 int comptype; … … 640 591 psAbort("can't map (long) type to a psLib type"); 641 592 } 593 psFree(dim); 642 594 // status check belongs to fits_set_tile_dim() call 643 595 if (status) { … … 681 633 } 682 634 683 684 bool psFitsSetOptions( 635 psFitsCompression *psFitsCompressionGet(psFits* fits) 636 { 637 PS_ASSERT_FITS_NON_NULL(fits, NULL); 638 639 int status = 0; // cfitsio status 640 641 psFitsCompressionType type = psFitsCompressionGetType(fits); 642 if (type < 0) { 643 psError(PS_ERR_UNKNOWN, false, "Unable to get compression type."); 644 return NULL; 645 } 646 647 psElemType tileType; // Type corresponding to "long" 648 if (sizeof(long) == sizeof(psS64)) { 649 tileType = PS_TYPE_S64; 650 } else if (sizeof(long) == sizeof(psS32)) { 651 tileType = PS_TYPE_S32; 652 } else { 653 psAbort("can't map (long) type to a psLib type"); 654 } 655 656 psVector *tiles = psVectorAlloc(3, tileType); // Tile sizes 657 if (fits_get_tile_dim(fits->fd, 3, (long*)tiles->data.U8, &status)) { 658 psFitsError(status, true, "Unable to get compression tile sizes."); 659 psFree(tiles); 660 return NULL; 661 } 662 663 int noisebits; // Noise bits for compression 664 if (fits_get_noise_bits(fits->fd, &noisebits, &status)) { 665 psFitsError(status, true, "Unable to get compression noise bits."); 666 psFree(tiles); 667 return NULL; 668 } 669 670 int hscale = 0, hsmooth = 0; // Scaling and smoothing for HCOMPRESS 671 672 #if FITS_HCOMP 673 if (fits_get_hcomp_scale(fits->fd, &hscale, &status)) { 674 psFitsError(status, true, "Unable to get HCOMPRESS scaling."); 675 psFree(tiles); 676 return NULL; 677 } 678 if (fits_get_hcomp_smooth(fits->fd, &hsmooth, &status)) { 679 psFitsError(status, true, "Unable to get HCOMPRESS smoothing."); 680 psFree(tiles); 681 return NULL; 682 } 683 #endif // FITS_HCOMP 684 685 psFitsCompression *compress = psFitsCompressionAlloc(type, tiles, noisebits, hscale, hsmooth); 686 psFree(tiles); // Drop reference 687 688 return compress; 689 } 690 691 psFitsCompressionType psFitsCompressionGetType(psFits* fits) 692 { 693 PS_ASSERT_FITS_NON_NULL(fits, -1); 694 695 int status = 0; // cfitsio status 696 int comptype = 0; // cfitsio compression type 697 if (fits_get_compression_type(fits->fd, &comptype, &status)) { 698 psFitsError(status, true, "Unable to get compression type."); 699 return -1; 700 } 701 702 psFitsCompressionType type; 703 switch (comptype) { 704 case 0: 705 type = PS_FITS_COMPRESS_NONE; 706 break; 707 case GZIP_1: 708 type = PS_FITS_COMPRESS_GZIP; 709 break; 710 case RICE_1: 711 type = PS_FITS_COMPRESS_RICE; 712 break; 713 case HCOMPRESS_1: 714 type = PS_FITS_COMPRESS_HCOMPRESS; 715 break; 716 case PLIO_1: 717 type = PS_FITS_COMPRESS_PLIO; 718 break; 719 default: 720 psError(PS_ERR_UNKNOWN, true, "cfitsio reports unknown compression type."); 721 return -1; 722 } 723 724 return type; 725 } 726 727 728 bool psFitsCompressionApply( 685 729 psFits* fits, ///< psFits object to close 686 psFits Options *opt///< options object730 psFitsCompression *comp ///< options object 687 731 ) 688 732 { 689 return psFitsSetCompression( 690 fits, 691 opt->type, 692 opt->tilesize, 693 opt->noisebits, 694 opt->scale, 695 opt->smooth); 733 return psFitsSetCompression(fits, comp->type, comp->tilesize, comp->noisebits, comp->scale, comp->smooth); 696 734 } 697 735 … … 826 864 827 865 866 psFitsCompressionType psFitsCompressionTypeFromString(const char *string) 867 { 868 if (!string || strlen(string) == 0) { 869 psWarning("Unable to identify compression type --- none set."); 870 return PS_FITS_COMPRESS_NONE; 871 } 872 873 if (strcmp(string, "GZIP") == 0) return PS_FITS_COMPRESS_GZIP; 874 if (strcmp(string, "RICE") == 0) return PS_FITS_COMPRESS_RICE; 875 if (strcmp(string, "HCOMPRESS") == 0) return PS_FITS_COMPRESS_HCOMPRESS; 876 if (strcmp(string, "PLIO") == 0) return PS_FITS_COMPRESS_PLIO; 877 878 psWarning("Unable to identify compression type (%s) --- none set.", string); 879 return PS_FITS_COMPRESS_NONE; 880 } -
trunk/psLib/src/fits/psFits.h
r14877 r15179 4 4 * @author Robert DeSonia, MHPCC 5 5 * 6 * @version $Revision: 1.3 1$ $Name: not supported by cvs2svn $7 * @date $Date: 2007- 09-18 02:56:36$6 * @version $Revision: 1.32 $ $Name: not supported by cvs2svn $ 7 * @date $Date: 2007-10-03 21:27:21 $ 8 8 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii 9 9 */ … … 21 21 #include "psMetadata.h" 22 22 #include "psImage.h" 23 24 #include "psErrorCodes.h" 23 25 24 26 /** FITS HDU type. … … 49 51 * 50 52 */ 51 typedef struct 52 { 53 fitsfile* fd; ///< the CFITSIO fits files handle.54 bool writable; ///< Is the file writable?55 char *extword; ///< user-specified word to name extensions (NULL implies EXTNAME)56 } 57 psFits; 58 59 /** FITS options object. */ 60 typedef struct 61 {53 typedef struct { 54 fitsfile* fd; ///< the CFITSIO fits files handle. 55 bool writable; ///< Is the file writable? 56 char *extword; ///< user-specified word to name extensions (NULL implies EXTNAME) 57 struct { 58 bool compression; ///< Honour compression convention, handling compressed images 59 } conventions; ///< Conventions to honour 60 } psFits; 61 62 /** FITS compression settings. */ 63 typedef struct { 62 64 psFitsCompressionType type; ///< type of compression 63 65 psVector *tilesize; ///< vector defining compression tile size … … 65 67 int scale; ///< hcompress scale 66 68 int smooth; ///< hcompress smothing 67 } 68 psFitsOptions; 69 } psFitsCompression; 69 70 70 71 /** Opens a FITS file and allocates the associated psFits object. … … 84 85 ); 85 86 86 /** Creates a new FITS options struct 87 88 /// Generate an error including the cfitsio error string 89 #ifdef DOXYGEN 90 psErrorCode psFitsError( 91 int status, ///< cfitsio status value 92 bool new, ///< new error? 93 const char *errorMsg, ///< printf-style format of header line 94 ... ///< any parameters required in format 95 ); 96 #else // ifdef DOXYGEN 97 psErrorCode p_psFitsError( 98 const char* filename, ///< file name 99 unsigned int lineno, ///< line number in file 100 const char* func, ///< function name 101 int status, ///< cfitsio status value 102 bool new, ///< new error? 103 const char *errorMsg, ///< printf-style format of header line 104 ... ///< any parameters required in format 105 ) PS_ATTR_FORMAT(printf, 6, 7); 106 #ifndef SWIG 107 #define psFitsError(status,new,...) \ 108 p_psFitsError(__FILE__,__LINE__,__func__,status,new,__VA_ARGS__) 109 #endif // ifndef SWIG 110 #endif // ifdef DOXYGEN 111 112 113 /** Creates a new FITS options struct 87 114 * 88 115 * @return psFitsOptions or NULL on failure 89 116 */ 90 psFits Options* psFitsOptionsAlloc(117 psFitsCompression* psFitsCompressionAlloc( 91 118 psFitsCompressionType type, ///< type of compression 92 119 psVector *tilesize, ///< vector defining compression tile size … … 96 123 ); 97 124 125 /// Return the FITS compression type specified by a string 126 psFitsCompressionType psFitsCompressionTypeFromString( 127 const char *string ///< String with compression type 128 ); 129 98 130 /** Closes a FITS file. 99 131 * … … 111 143 */ 112 144 bool psFitsSetCompression( 113 psFits* fits, ///< psFits object to close145 psFits* fits, ///< psFits object for which to set compression 114 146 psFitsCompressionType type, ///< type of compression 115 147 psVector *tilesize, ///< vector defining compression tile size … … 119 151 ); 120 152 153 /// Get the compression options for a file handle 154 psFitsCompression *psFitsCompressionGet( 155 psFits* fits ///< psFits object for which to get compression 156 ); 157 158 /// Get the compression type for a file handle 159 psFitsCompressionType psFitsCompressionGetType( 160 psFits* fits ///< psFits object for which to get compression type 161 ); 162 121 163 /** Sets FITS write options 122 164 * 123 165 * @return bool TRUE if successfully configured, otherwise FALSE 124 166 */ 125 bool psFits SetOptions(126 psFits* fits, ///< psFits object to close127 psFits Options *opt///< options object167 bool psFitsCompressionApply( 168 psFits* fits, ///< psFits object for which to set compression 169 psFitsCompression *compress ///< options object 128 170 ); 129 171 … … 146 188 // a user-defined word in place of EXTNAME 147 189 bool p_psFitsMoveExtName_UserKey(const psFits *fits, 148 const char *extname,149 const char *extword);190 const char *extname, 191 const char *extword); 150 192 151 193 /** Moves the FITS HDU to the specified extension name. … … 261 303 ); 262 304 305 #define PS_ASSERT_FITS_NON_NULL(NAME, RVAL) \ 306 if (!(NAME) || !(NAME)->fd) { \ 307 psError(PS_ERR_UNEXPECTED_NULL, true, "Error: FITS file pointer %s is NULL", #NAME); \ 308 return RVAL; \ 309 } 310 263 311 /// @} 264 312 #endif // #ifndef PS_FITS_H -
trunk/psLib/src/fits/psFitsHeader.c
r14460 r15179 7 7 * @author Robert DeSonia, MHPCC 8 8 * 9 * @version $Revision: 1.3 4$ $Name: not supported by cvs2svn $10 * @date $Date: 2007- 08-10 02:23:42$9 * @version $Revision: 1.35 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2007-10-03 21:27:21 $ 11 11 * 12 12 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 19 19 #include <unistd.h> 20 20 21 #include "psAssert.h" 21 22 #include "psFits.h" 22 23 #include "string.h" … … 32 33 33 34 #define MAX_STRING_LENGTH 256 // maximum length string for FITS routines 35 #define NUM_EMPTY_KEYS 8 // Number of keywords before header is considered practically empty 34 36 35 37 // list of FITS header keys to ignore; NULL-terminated 36 static c har* ignoreFitsKeys[] = {"", NULL};38 static const char* ignoreFitsKeys[] = { "", NULL}; 37 39 38 40 // List of FITS header keys that may be duplicated; NULL-terminated 39 static c har *duplicateFitsKeys[] = {"COMMENT", "HIERARCH", "HISTORY", NULL};41 static const char *duplicateFitsKeys[] = { "COMMENT", "HIERARCH", "HISTORY", NULL}; 40 42 41 43 // List of FITS header keys not to write (handled by cfitsio); NULL-terminated 42 static char *noWriteFitsKeys[] = {"SIMPLE", "XTENSION", "BITPIX", "NAXIS", "EXTNAME", "BSCALE", "BZERO", 43 "TFIELDS", NULL}; 44 static const char *noWriteFitsKeys[] = { "SIMPLE", "XTENSION", "BITPIX", "NAXIS", "EXTNAME", "BSCALE", 45 "BZERO", "TFIELDS", "PCOUNT", "GCOUNT", "ZIMAGE", "ZBITPIX", 46 "ZCMPTYPE", NULL}; 47 44 48 // List of the start of FITS header keys not to write (handled by cfitsio); NULL-terminated 45 static char *noWriteFitsKeyStarts[] = {"NAXIS", "TTYPE", "TFORM", NULL}; 46 47 // List of FITS header keys to be written with fits_write_comment 48 49 psMetadata* psFitsReadHeader(psMetadata* out, 50 const psFits* fits) 51 { 52 if (fits == NULL) { 53 psError(PS_ERR_BAD_PARAMETER_NULL, true, 54 _("The input psFits object can not NULL.")); 55 return NULL; 56 } 57 58 if (out == NULL) { 59 out = psMetadataAlloc(); 60 } 49 static const char *noWriteFitsKeyStarts[] = { "NAXIS", "TTYPE", "TFORM", "ZNAXIS", "ZTILE", "ZNAME", "ZVAL", 50 NULL}; 51 52 // List of FITS header keys that may be present if the header is considered "empty"; NULL-terminated 53 static const char *emptyKeys[] = { "SIMPLE", "BITPIX", "NAXIS", "EXTEND", "COMMENT", "CHECKSUM", "DATASUM", 54 NULL }; 55 56 // Compare a keyword with a list of keywords; return true if it's in the list 57 static bool keywordInList(const char *keyword, // Keyword to check 58 const char **list // List of keywords 59 ) 60 { 61 for (const char **check = list; *check; ++check) { 62 if (strcmp(keyword, *check) == 0) { 63 return true; 64 } 65 } 66 return false; 67 } 68 69 70 bool psFitsCheckSingleCompressedImagePHU(const psFits *fits, psMetadata *header) 71 { 72 PS_ASSERT_FITS_NON_NULL(fits, false); 73 74 if (!fits->conventions.compression) { 75 // User has turned off compression conventions; doesn't want any nasty surprises 76 return false; 77 } 78 79 if (psFitsGetExtNum(fits) != 0) { 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)) { 132 return true; 133 } 134 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 char *p_psFitsHeaderParseString(char *string) 145 { 146 if (!string || strlen(string) == 0) { 147 return string; 148 } 149 150 char *fixed = string; // Fixed version of the string 151 // remove the single-quotes at front/end 152 if (fixed[0] == '\'' && fixed[strlen(string)-1] == '\'') { 153 string[strlen(string)-1] = '\0'; // Remove the trailing quote 154 fixed += 1; // Advance past the leading quote 155 } 156 // Remove trailing spaces, which are not significant, according to the FITS standard 157 // http://archive.stsci.edu/fits/fits_standard/node31.html 158 char *lastSpace = NULL; // The last space in the string 159 while (strlen(fixed) > 1 && (lastSpace = strrchr(fixed, ' ')) && lastSpace[1] == '\0') { 160 // This is a trailing space, not a leading space. 161 lastSpace[0] = '\0'; // Truncate the string here 162 } 163 164 return fixed; 165 } 166 167 // Read the header 168 static psMetadata *readHeader(const psFits *fits // FITS file from which to read header 169 ) 170 { 171 assert(fits); 172 173 psMetadata *header = psMetadataAlloc(); // Header, to return 61 174 62 175 // Get number of key names … … 74 187 75 188 // Check to see if the keyword should be ignored 76 bool ignoreKey = false; // Ignore this keyword? 77 for (int i = 0; ignoreFitsKeys[i] && !ignoreKey; i++) { 78 if (strcmp(keyName, ignoreFitsKeys[i]) == 0) { 79 ignoreKey = true; 80 } 81 } 82 if (ignoreKey) { 189 if (keywordInList(keyName, ignoreFitsKeys)) { 83 190 // We're done here; skip to the next key 84 191 continue; 85 192 } 86 193 87 #if 088 // This doesn't seem to be necessary89 if (strncmp(keyName, "HIERARCH ", 9) == 0) {90 char temp[MAX_STRING_LENGTH];91 strcpy(temp, &keyName[9]);92 strcpy(keyName, temp);93 }94 #endif95 96 194 // Check to see if the keyword should be duplicated 97 195 int dupFlag = 0; // Duplicate flag 98 for (int i = 0; duplicateFitsKeys[i] && !dupFlag; i++) { 99 if (strcmp(keyName, duplicateFitsKeys[i]) == 0) { 100 dupFlag = PS_META_DUPLICATE_OK; 101 } 196 if (keywordInList(keyName, duplicateFitsKeys)) { 197 dupFlag = PS_META_DUPLICATE_OK; 102 198 } 103 199 … … 116 212 case 'X': // bit 117 213 case 'B': // byte 118 success = psMetadataAddS8( out, PS_LIST_TAIL, keyName, dupFlag, keyComment, atoi(keyValue));214 success = psMetadataAddS8(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, atoi(keyValue)); 119 215 break; 120 216 case 'I': // short int. … … 122 218 // Trap NAN, INF and -INF, which cfitsio doesn't handle. 123 219 if (strncasecmp(keyValue, "NAN", 3) == 0) { 124 success = psMetadataAddF32( out, PS_LIST_TAIL, keyName, dupFlag, keyComment, NAN);220 success = psMetadataAddF32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, NAN); 125 221 } else if (strncasecmp(keyValue, "INF", 3) == 0) { 126 success = psMetadataAddF32( out, PS_LIST_TAIL, keyName, dupFlag, keyComment, INFINITY);222 success = psMetadataAddF32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, INFINITY); 127 223 } else if (strncasecmp(keyValue, "-INF", 4) == 0) { 128 success = psMetadataAddF32( out, PS_LIST_TAIL, keyName, dupFlag, keyComment, -INFINITY);224 success = psMetadataAddF32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, -INFINITY); 129 225 } else { 130 success = psMetadataAddS32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, atoi(keyValue)); 226 success = psMetadataAddS32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, 227 atoi(keyValue)); 131 228 } 132 229 break; 133 230 case 'J': // int. 134 success = psMetadataAddS32( out, PS_LIST_TAIL, keyName, dupFlag, keyComment, atoi(keyValue));231 success = psMetadataAddS32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, atoi(keyValue)); 135 232 break; 136 233 case 'U': // unsigned int. 137 success = psMetadataAddU32( out, PS_LIST_TAIL, keyName, dupFlag, keyComment, atol(keyValue));234 success = psMetadataAddU32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, atol(keyValue)); 138 235 break; 139 236 140 237 case 'K': // long int. can't all fit in a psS32, put in psF64 141 238 case 'F': 142 success = psMetadataAddF64( out, PS_LIST_TAIL, keyName, dupFlag, keyComment, atof(keyValue));239 success = psMetadataAddF64(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, atof(keyValue)); 143 240 break; 144 241 case 'C': { 145 char *keyValueFixed = keyValue; // Fixed version of the string 146 // remove the single-quotes at front/end 147 if (keyValueFixed[0] == '\'' && keyValueFixed[strlen(keyValue)-1] == '\'') { 148 keyValue[strlen(keyValue)-1] = '\0'; // Remove the trailing quote 149 keyValueFixed += 1; // Advance past the leading quote 150 } 151 // Remove trailing spaces, which are not significant, according to the FITS standard 152 // http://archive.stsci.edu/fits/fits_standard/node31.html 153 char *lastSpace = NULL; // The last space in the string 154 while (strlen(keyValueFixed) > 1 && (lastSpace = strrchr(keyValueFixed, ' ')) && 155 lastSpace[1] == '\0') { 156 // This is a trailing space, not a leading space. 157 lastSpace[0] = '\0'; // Truncate the string here 158 } 159 160 // Need to trap NAN, INF and -INF written by psFitsWriteHeader. 161 // cfitsio won't write these, so we write them as strings, and then have to trap them on read. 162 if (strcasecmp(keyValueFixed, "NAN") == 0) { 163 success = psMetadataAddF32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, NAN); 164 } else if (strcasecmp(keyValueFixed, "INF") == 0) { 165 success = psMetadataAddF32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, INFINITY); 166 } else if (strcasecmp(keyValueFixed, "-INF") == 0) { 167 success = psMetadataAddF32(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, -INFINITY); 168 } else { 169 success = psMetadataAddStr(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, 170 keyValueFixed); 171 } 172 break; 242 char *keyValueFixed = p_psFitsHeaderParseString(keyValue); // Fixed version of the string 243 244 // Need to trap NAN, INF and -INF written by psFitsWriteHeader. 245 // cfitsio won't write these, so we write them as strings, and then have to trap them on read. 246 if (strcasecmp(keyValueFixed, "NAN") == 0) { 247 success = psMetadataAddF32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, NAN); 248 } else if (strcasecmp(keyValueFixed, "INF") == 0) { 249 success = psMetadataAddF32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, INFINITY); 250 } else if (strcasecmp(keyValueFixed, "-INF") == 0) { 251 success = psMetadataAddF32(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, -INFINITY); 252 } else if (!fits->conventions.compression || 253 (strcmp(keyName, "EXTNAME") != 0 || strcmp(keyValueFixed, "COMPRESSED_IMAGE") != 0)) { 254 // Ignore EXTNAME=COMPRESSED_IMAGE if compression convention is to be respected 255 success = psMetadataAddStr(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, 256 keyValueFixed); 173 257 } 258 break; 259 } 174 260 case 'L': { 175 bool temp = (keyValue[0] == 'T') ? 1 : 0;176 success = psMetadataAddBool(out, PS_LIST_TAIL, keyName, dupFlag, keyComment, temp);177 break;178 }261 bool temp = (keyValue[0] == 'T') ? 1 : 0; 262 success = psMetadataAddBool(header, PS_LIST_TAIL, keyName, dupFlag, keyComment, temp); 263 break; 264 } 179 265 default: 180 266 psError(PS_ERR_IO, true, _("Specified FITS metadata type, %c, is not supported."), keyType); 181 return out; 267 psFree(header); 268 return NULL; 182 269 } 183 270 184 271 if (!success) { 185 272 psError(PS_ERR_UNKNOWN, false, _("Failed to add metadata item, %s."), keyName); 186 return out; 273 psFree(header); 274 return NULL; 187 275 } 188 276 … … 193 281 (void)fits_get_errstatus(status, fitsErr); 194 282 psError(PS_ERR_IO, true, _("Failed to add metadata item, %s."), fitsErr); 195 return false; 196 } 197 283 psFree(header); 284 return false; 285 } 286 287 return header; 288 } 289 290 291 psMetadata* psFitsReadHeader(psMetadata* out, 292 const psFits* fits) 293 { 294 PS_ASSERT_FITS_NON_NULL(fits, NULL); 295 296 psMetadata *header = readHeader(fits); // Header 297 if (!header) { 298 return NULL; 299 } 300 301 // Explore the potential case that this is an empty PHU, and the first extension contains the sole image, 302 // which is compressed. 303 if (psFitsCheckSingleCompressedImagePHU(fits, header)) { 304 // This is really what we want, not the empty PHU 305 psTrace("psLib.fits", 1, 306 "This PHU should really be a compressed image --- getting that header instead."); 307 psFree(header); 308 header = readHeader(fits); 309 if (!header) { 310 return NULL; 311 } 312 } 313 314 if (!out) { 315 return header; 316 } 317 318 // Need to move header onto the nominated metadata 319 psMetadataIterator *iter = psMetadataIteratorAlloc(header, PS_LIST_HEAD, NULL); // Iterator 320 psMetadataItem *item; // Item from iteration 321 while ((item = psMetadataGetAndIncrement(iter))) { 322 // Need to look for MULTI, which won't be picked up using the iterator. 323 psMetadataItem *multiCheckItem = psMetadataLookup(header, item->name); 324 assert(multiCheckItem); 325 unsigned int flag = 0; // Flag to indicate MULTI; otherwise default action 326 if (multiCheckItem->type == PS_DATA_METADATA_MULTI) { 327 flag = PS_META_DUPLICATE_OK; 328 } 329 if (!psMetadataAddItem(out, item, PS_LIST_TAIL, flag)) { 330 psError(PS_ERR_UNKNOWN, false, "Unable to add header item %s to extant metadata.", 331 item->name); 332 psFree(iter); 333 psFree(header); 334 return NULL; 335 } 336 } 337 psFree(iter); 338 psFree(header); 198 339 return out; 199 340 } … … 201 342 psMetadata* psFitsReadHeaderSet(psMetadata* out, const psFits* fits) 202 343 { 203 if (fits == NULL) { 204 psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psFits object can not NULL.")); 205 psFree(out); 206 return NULL; 207 } 208 209 if (out == NULL) { 344 PS_ASSERT_FITS_NON_NULL(fits, NULL); 345 346 if (!out) { 210 347 out = psMetadataAlloc(); 211 348 } … … 279 416 // image, the NAXISn haven't been changed; or after converting to F32, the BITPIX hasn't been 280 417 // changed) so we'll take care of that for them. 281 bool writeKey = true; // Should we write this keyword? 282 for (int i = 0; noWriteFitsKeys[i] && writeKey; i++) { 283 if (strcmp(item->name, noWriteFitsKeys[i]) == 0) { 284 writeKey = false; 285 } 286 } 287 if (!writeKey) { 418 if (keywordInList(item->name, noWriteFitsKeys)) { 288 419 // Don't write it; skip to the next key 289 420 continue; … … 294 425 // that go in are correct. However, when we're writing a "blank" HDU (header only), we want 295 426 // to preserve NAXISn etc for reference, so we don't do this. 427 bool writeKey = true; // Write this keyword? 296 428 for (int i = 0; noWriteFitsKeyStarts[i] && writeKey; i++) { 297 429 if (strncmp(item->name, noWriteFitsKeyStarts[i], strlen(noWriteFitsKeyStarts[i])) == 0) { … … 349 481 } 350 482 } else { 351 fits_update_key(fits->fd, TFLOAT, item->name, &item->data.F32, item->comment, &status); 483 fits_update_key(fits->fd, TFLOAT, item->name, &item->data.F32, item->comment, 484 &status); 352 485 } 353 486 break; … … 364 497 } 365 498 } else { 366 fits_update_key(fits->fd, TDOUBLE, item->name, &item->data.F64, item->comment, &status); 499 fits_update_key(fits->fd, TDOUBLE, item->name, &item->data.F64, item->comment, 500 &status); 367 501 } 368 502 break; … … 395 529 ) 396 530 { 397 if (!fits) { 398 psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psFits object can not NULL.")); 399 return false; 400 } 401 402 if (!output) { 403 psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psMetadata was NULL. Need a non-NULL psMetadata for operation to be performed.")); 404 return false; 405 } 531 PS_ASSERT_FITS_NON_NULL(fits, false); 532 PS_ASSERT_METADATA_NON_NULL(output, false); 406 533 407 534 return fitsWriteHeader(fits, output, true); … … 413 540 ) 414 541 { 415 if (!fits) { 416 psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psFits object can not NULL.")); 417 return false; 418 } 542 PS_ASSERT_FITS_NON_NULL(fits, false); 419 543 420 544 // We allow output == NULL in order to write a minimal header. … … 458 582 bool psFitsHeaderValidate(psMetadata *header) 459 583 { 460 if (header == NULL) { 461 psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psMetadata was NULL. Need a non-NULL psMetadata for operation to be performed.")); 462 return false; 463 } 584 PS_ASSERT_METADATA_NON_NULL(header, false); 464 585 465 586 // Traverse the metadata list and inspect at each key -
trunk/psLib/src/fits/psFitsHeader.h
r11248 r15179 4 4 * @author Robert DeSonia, MHPCC 5 5 * 6 * @version $Revision: 1.1 0$ $Name: not supported by cvs2svn $7 * @date $Date: 2007- 01-23 22:47:23$6 * @version $Revision: 1.11 $ $Name: not supported by cvs2svn $ 7 * @date $Date: 2007-10-03 21:27:21 $ 8 8 * 9 9 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 18 18 #include "psFits.h" 19 19 #include "psMetadata.h" 20 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. 28 bool psFitsCheckSingleCompressedImagePHU(const psFits *fits, ///< FITS file pointer 29 const psMetadata *header ///< Header, or NULL 30 ); 31 32 /// Parse a string read from the FITS header. 33 34 /// Removes the quotes, and any trailing spaces. NOTE: the returned string is NOT on the psLib memory system 35 /// --- it's simply a hacked version of the input string. Note also that the input string is MODIFIED. 36 char *p_psFitsHeaderParseString(char *string ///< String to parse 37 ); 20 38 21 39 /** Reads the header of the current HDU. -
trunk/psLib/src/fits/psFitsImage.c
r10999 r15179 7 7 * @author Robert DeSonia, MHPCC 8 8 * 9 * @version $Revision: 1.1 7$ $Name: not supported by cvs2svn $10 * @date $Date: 2007- 01-09 22:38:52$9 * @version $Revision: 1.18 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2007-10-03 21:27:21 $ 11 11 * 12 12 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 38 38 39 39 // Information required to read a FITS file 40 typedef struct 41 { 40 typedef struct { 42 41 int nAxis; // Number of axes 43 42 int bitPix; // Bits per pixel … … 48 47 int fitsDatatype; // cfitsio data type 49 48 int psDatatype; // psLib data type 50 } 51 p_psFitsReadInfo; 49 } p_psFitsReadInfo; 52 50 53 51 static p_psFitsReadInfo *p_psFitsReadInfoAlloc(const psFits *fits, // The FITS file handle … … 56 54 ) 57 55 { 58 PS_ASSERT_ PTR_NON_NULL(fits, NULL);56 PS_ASSERT_FITS_NON_NULL(fits, NULL); 59 57 PS_ASSERT_INT_NONNEGATIVE(z, NULL); 60 58 … … 221 219 ) 222 220 { 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 223 230 p_psFitsReadInfo *info = p_psFitsReadInfoAlloc(fits, region, z); 224 231 … … 243 250 ) 244 251 { 252 PS_ASSERT_FITS_NON_NULL(fits, NULL); 253 PS_ASSERT_INT_NONNEGATIVE(z, NULL); 254 245 255 if (output && output->parent) { 246 256 psError(PS_ERR_IO, true, "Unable to read into a buffer for a child image.\n"); 247 257 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."); 248 264 } 249 265 … … 270 286 const char* extname) 271 287 { 288 PS_ASSERT_FITS_NON_NULL(fits, false); 289 PS_ASSERT_IMAGE_NON_NULL(input, false); 272 290 // this is equivalent to insert after the last HDU 273 291 … … 283 301 bool after) 284 302 { 285 286 if (!fits) { 287 psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psFits object can not NULL.")); 288 return false; 289 } 290 291 if (!input) { 292 psError(PS_ERR_BAD_PARAMETER_NULL, true, _("The input psImage was NULL. Need a non-NULL psImage for operation to be performed.")); 293 return false; 294 } 303 PS_ASSERT_FITS_NON_NULL(fits, false); 304 PS_ASSERT_IMAGE_NON_NULL(input, false); 295 305 296 306 int numCols = input->numCols; // Number of columns for image … … 391 401 int z) 392 402 { 403 PS_ASSERT_FITS_NON_NULL(fits, false); 404 PS_ASSERT_IMAGE_NON_NULL(input, false); 405 393 406 int status = 0; 394 395 if (fits == NULL) {396 psError(PS_ERR_BAD_PARAMETER_NULL, true,397 _("The input psFits object can not NULL."));398 return false;399 }400 401 if (input == NULL) {402 psError(PS_ERR_BAD_PARAMETER_NULL, true,403 _("The input psImage was NULL. Need a non-NULL psImage for operation to be performed."));404 return false;405 }406 407 407 408 // check to see if we are positioned on an image HDU … … 499 500 psArray *psFitsReadImageCube(const psFits *fits, psRegion region) 500 501 { 502 PS_ASSERT_FITS_NON_NULL(fits, NULL); 503 501 504 int nAxis = 0; // Number of axes 502 505 long nAxes[3]; // Number of pixels on each axis … … 504 507 char fitsErr[80] = ""; // CFITSIO error message string 505 508 506 if (fits == NULL) {507 psError(PS_ERR_BAD_PARAMETER_NULL, true,508 _("The input psFits object can not NULL."));509 return NULL;510 }511 512 509 // Some of this replicates what is in psFitsReadImage, so it's a little inefficient. But it saves 513 510 // 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 } 514 517 515 518 if (fits_get_img_dim(fits->fd, &nAxis, &status) != 0) { … … 544 547 545 548 // Bad dimensionality 546 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); 547 552 return NULL; 548 553 } … … 550 555 bool psFitsWriteImageCube(psFits *fits, psMetadata *header, const psArray *input, const char *extname) 551 556 { 552 if (fits == NULL) { 553 psError(PS_ERR_BAD_PARAMETER_NULL, true, 554 _("The input psFits object can not NULL.")); 555 return false; 556 } 557 558 if (input == NULL) { 559 psError(PS_ERR_BAD_PARAMETER_NULL, true, 560 _("The input psImage was NULL. Need a non-NULL psImage for operation to be performed.")); 561 return false; 562 } 557 PS_ASSERT_FITS_NON_NULL(fits, false); 558 PS_ASSERT_ARRAY_NON_NULL(input, false); 563 559 564 560 if (input->n == 0) { … … 592 588 } 593 589 bool update = psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS", PS_META_REPLACE, "Dimensionality", 3) && 594 psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS1", PS_META_REPLACE, "Number of columns", numCols) &&595 psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS2", PS_META_REPLACE, "Number of rows", numRows) &&596 psMetadataAddS32(headerCopy, PS_LIST_HEAD, "NAXIS3", PS_META_REPLACE, "Number of image planes",597 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); 598 594 if (! update) { 599 595 psError(PS_ERR_UNKNOWN, false, _("Failed to add metadata item, %s."), … … 625 621 bool psFitsUpdateImageCube(psFits *fits, const psArray *input, int x0, int y0) 626 622 { 627 if (fits == NULL) { 628 psError(PS_ERR_BAD_PARAMETER_NULL, true, 629 _("The input psFits object can not NULL.")); 630 return false; 631 } 632 633 if (input == NULL) { 634 psError(PS_ERR_BAD_PARAMETER_NULL, true, 635 _("The input psImage was NULL. Need a non-NULL psImage for operation to be performed.")); 636 return false; 637 } 623 PS_ASSERT_FITS_NON_NULL(fits, false); 624 PS_ASSERT_ARRAY_NON_NULL(input, false); 638 625 639 626 if (input->n == 0) { -
trunk/psLib/src/fits/psFitsTable.c
r12549 r15179 7 7 * @author Robert DeSonia, MHPCC 8 8 * 9 * @version $Revision: 1.2 7$ $Name: not supported by cvs2svn $10 * @date $Date: 2007- 03-22 21:40:47$9 * @version $Revision: 1.28 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2007-10-03 21:27:21 $ 11 11 * 12 12 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 38 38 int row) 39 39 { 40 PS_ASSERT_FITS_NON_NULL(fits, NULL); 41 PS_ASSERT_INT_NONNEGATIVE(row, NULL); 42 40 43 long numRows; 41 44 int numCols; 42 45 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 }49 46 50 47 // check to see if we even are positioned on a table HDU … … 185 182 const char* colname) 186 183 { 184 PS_ASSERT_FITS_NON_NULL(fits, NULL); 185 PS_ASSERT_STRING_NON_EMPTY(colname, NULL); 186 187 187 int colnum = 0; 188 188 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 }195 189 196 190 // check to see if we even are positioned on a table HDU … … 266 260 const char* colname) 267 261 { 262 PS_ASSERT_FITS_NON_NULL(fits, NULL); 263 PS_ASSERT_STRING_NON_EMPTY(colname, NULL); 264 268 265 int status = 0; 269 266 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 }276 267 277 268 // check to see if we even are positioned on a table HDU … … 348 339 psArray* psFitsReadTable(const psFits* fits) 349 340 { 341 PS_ASSERT_FITS_NON_NULL(fits, NULL); 342 350 343 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 }357 344 358 345 // check to see if we even are positioned on a table HDU … … 400 387 const char *extname) 401 388 { 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 } 403 394 return psFitsInsertTable(fits, header, table, extname, true); 404 395 } … … 460 451 // Column specification 461 452 // Included here, because there's no need for the user to have access to it 462 typedef struct 463 { 453 typedef struct { 464 454 psDataType type; // psLib type (e.g., PS_DATA_STRING or PS_TYPE_F32) 465 455 size_t size; // Size (number of repeats) 466 456 psElemType vectorType; // psLib type of vectors 467 } 468 colSpec; 457 } colSpec; 469 458 470 459 … … 475 464 bool after) 476 465 { 466 PS_ASSERT_FITS_NON_NULL(fits, false); 467 PS_ASSERT_ARRAY_NON_NULL(table, false); 468 477 469 int status = 0; 478 479 PS_ASSERT_PTR_NON_NULL(fits, false);480 PS_ASSERT_ARRAY_NON_NULL(table, false);481 470 482 471 long numRows = table->n; … … 614 603 char fitsErr[MAX_STRING_LENGTH]; 615 604 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", 617 607 numColumns, table->n, fitsErr); 618 608 psFree(colSpecsIter); … … 632 622 if (extname && strlen(extname) > 0) { 633 623 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 } 639 629 } 640 630 … … 728 718 int row) 729 719 { 720 PS_ASSERT_FITS_NON_NULL(fits, false); 721 PS_ASSERT_METADATA_NON_NULL(data, false); 722 PS_ASSERT_INT_NONNEGATIVE(row, false); 723 730 724 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 }743 725 744 726 // check to see if we even are positioned on a table HDU
Note:
See TracChangeset
for help on using the changeset viewer.
