Changeset 5511 for trunk/psLib/src/fits
- Timestamp:
- Nov 14, 2005, 12:18:38 PM (20 years ago)
- Location:
- trunk/psLib/src/fits
- Files:
-
- 6 added
- 4 edited
-
Makefile.am (modified) (2 diffs)
-
fits.i (modified) (1 diff)
-
psFits.c (modified) (4 diffs)
-
psFits.h (modified) (9 diffs)
-
psFitsHeader.c (added)
-
psFitsHeader.h (added)
-
psFitsImage.c (added)
-
psFitsImage.h (added)
-
psFitsTable.c (added)
-
psFitsTable.h (added)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/fits/Makefile.am
r4981 r5511 3 3 noinst_LTLIBRARIES = libpslibfits.la 4 4 5 libpslibfits_la_C PPFLAGS = $(SRCINC) $(CFITSIO_CFLAGS)5 libpslibfits_la_CFLAGS = $(SRCINC) $(CFITSIO_CFLAGS) $(AM_CFLAGS) 6 6 libpslibfits_la_SOURCES = \ 7 psFits.c 7 psFits.c \ 8 psFitsHeader.c \ 9 psFitsImage.c \ 10 psFitsTable.c 8 11 9 12 EXTRA_DIST = fits.i … … 11 14 pslibincludedir = $(includedir) 12 15 pslibinclude_HEADERS = \ 13 psFits.h 16 psFits.h \ 17 psFitsHeader.h \ 18 psFitsImage.h \ 19 psFitsTable.h -
trunk/psLib/src/fits/fits.i
r4540 r5511 1 1 /* fits headers */ 2 2 %include "psFits.h" 3 %include "psFitsHeader.h" 4 %include "psFitsImage.h" 5 %include "psFitsTable.h" -
trunk/psLib/src/fits/psFits.c
r5168 r5511 7 7 * @author Robert DeSonia, MHPCC 8 8 * 9 * @version $Revision: 1.5 0$ $Name: not supported by cvs2svn $10 * @date $Date: 2005- 09-28 20:02:46$9 * @version $Revision: 1.51 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2005-11-14 22:18:30 $ 11 11 * 12 12 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 28 28 #define MAX_STRING_LENGTH 256 // maximum length string for FITS routines 29 29 30 // list of FITS header keys to ignore.31 static char* standardFitsKeys[] = {32 NULL33 };34 35 static psElemType convertFitsToPsType(int datatype)36 {37 switch (datatype) {38 case TBYTE:39 return PS_TYPE_U8;40 case TSBYTE:41 return PS_TYPE_S8;42 case TSHORT:43 return PS_TYPE_S16;44 case TUSHORT:45 return PS_TYPE_U16;46 case TLONG:47 if (sizeof(long) == 8) {48 return PS_TYPE_S64;49 }50 // no break51 case TINT:52 return PS_TYPE_S32;53 case TULONG:54 if (sizeof(unsigned long) == 8) {55 return PS_TYPE_U64;56 }57 // no break58 case TUINT:59 return PS_TYPE_U32;60 case TLONGLONG:61 return PS_TYPE_S64;62 case TFLOAT:63 return PS_TYPE_F32;64 case TDOUBLE:65 return PS_TYPE_F64;66 case TCOMPLEX:67 return PS_TYPE_C32;68 case TDBLCOMPLEX:69 return PS_TYPE_C64;70 case TLOGICAL:71 return PS_TYPE_BOOL;72 default:73 psError(PS_ERR_IO, true,74 "Unknown FITS datatype, %d.",75 datatype);76 return 0;77 }78 }79 80 static bool convertPsTypeToFits(int type, int* bitPix, double* bZero, int* dataType)81 {82 83 int bitpix;84 int datatype;85 double bzero = 0.0;86 87 switch (type) {88 89 case PS_TYPE_U8:90 bitpix = BYTE_IMG;91 datatype = TBYTE;92 break;93 94 case PS_TYPE_S8:95 bitpix = BYTE_IMG;96 bzero = INT8_MIN;97 datatype = TSBYTE;98 break;99 100 case PS_TYPE_U16:101 bitpix = SHORT_IMG;102 bzero = -1.0 * INT16_MIN;103 datatype = TUSHORT;104 break;105 106 case PS_TYPE_S16:107 bitpix = SHORT_IMG;108 datatype = TSHORT;109 break;110 111 case PS_TYPE_U32:112 bitpix = LONG_IMG;113 bzero = -1.0 * INT32_MIN;114 datatype = TUINT;115 break;116 117 case PS_TYPE_S32:118 bitpix = LONG_IMG;119 datatype = TINT;120 break;121 122 case PS_TYPE_F32:123 bitpix = FLOAT_IMG;124 datatype = TFLOAT;125 break;126 127 case PS_TYPE_F64:128 bitpix = DOUBLE_IMG;129 datatype = TDOUBLE;130 break;131 132 case PS_DATA_STRING:133 bitpix = BYTE_IMG;134 datatype = TSTRING;135 break;136 137 case PS_DATA_BOOL:138 bitpix = BYTE_IMG;139 datatype = TLOGICAL;140 break;141 142 default: {143 char* typeStr;144 PS_TYPE_NAME(typeStr,type);145 psError(PS_ERR_BAD_PARAMETER_TYPE, true,146 PS_ERRORTEXT_psFits_TYPE_UNSUPPORTED,147 typeStr);148 return false;149 }150 }151 152 // pass the requested parameters (NULL parameters are not set, of course).153 if (bitPix != NULL) {154 *bitPix = bitpix;155 }156 157 if (dataType != NULL) {158 *dataType = datatype;159 }160 161 if (bZero != NULL) {162 *bZero = bzero;163 }164 165 return true;166 }167 168 static char getTForm(int type)169 {170 switch (type) {171 case PS_TYPE_U8:172 case PS_TYPE_S8:173 return 'B';174 case PS_TYPE_S16:175 return 'I';176 case PS_TYPE_S32:177 return 'J';178 case PS_TYPE_U64:179 case PS_TYPE_S64:180 return 'K';181 case PS_TYPE_U16:182 return 'U';183 case PS_TYPE_U32:184 return 'V';185 case PS_TYPE_F32:186 return 'E';187 case PS_TYPE_F64:188 return 'D';189 case PS_TYPE_C32:190 return 'C';191 case PS_TYPE_C64:192 return 'M';193 case PS_TYPE_BOOL:194 return 'L';195 case PS_DATA_STRING:196 return 'A';197 default:198 return '?';199 }200 }201 202 203 static bool getMetadataTForm(psMetadataItem* item, char** fitsType, int repeat)204 {205 if (item == NULL) {206 return false;207 }208 209 *fitsType = NULL;210 char tform = getTForm(item->type);211 212 switch (item->type) {213 case PS_TYPE_U8:214 case PS_TYPE_S8:215 case PS_TYPE_S16:216 case PS_TYPE_S32:217 case PS_TYPE_U64:218 case PS_TYPE_S64:219 case PS_TYPE_U16:220 case PS_TYPE_U32:221 case PS_TYPE_F32:222 case PS_TYPE_F64:223 case PS_TYPE_C32:224 case PS_TYPE_C64:225 case PS_TYPE_BOOL:226 psStringAppend(fitsType, "%d%c",repeat,tform);227 break;228 229 case PS_DATA_STRING:230 psStringAppend(fitsType,"%dA",231 strlen(item->data.V)*repeat);232 break;233 234 case PS_DATA_VECTOR: {235 psVector* vec = item->data.V;236 tform = getTForm(vec->type.type);237 psStringAppend(fitsType,"%d%c",repeat*vec->n,tform);238 }239 break;240 241 default:242 return false;243 }244 245 return true;246 }247 248 30 static bool isHDUEmpty(const psFits* fits) 249 31 { … … 264 46 } 265 47 48 static bool fitsClose(psFits* fits) 49 { 50 int status = 0; 51 52 if (fits != NULL) { 53 if (fits_close_file(fits->fd, &status)) { 54 char fitsErr[MAX_STRING_LENGTH]; 55 fits_get_errstatus(status, fitsErr); 56 psError(PS_ERR_IO, true, 57 "Error while closing psFits object. CFITSIO error: %s", 58 fitsErr); 59 return false; 60 } 61 } 62 63 return true; 64 } 65 266 66 static void fitsFree(psFits* fits) 267 67 { 268 int status = 0; 269 270 if (fits != NULL) { 271 (void)fits_close_file(fits->fd, &status); 272 psFree(fits->filename); 273 } 68 (void)fitsClose(fits); 274 69 } 275 70 276 psFits* psFitsAlloc(const char* name) 277 { 278 int status = 0; 279 fitsfile *fptr = NULL; /* Pointer to the FITS file */ 280 281 if (name == NULL) { 282 psError(PS_ERR_BAD_PARAMETER_NULL, true, 283 PS_ERRORTEXT_psFits_FILENAME_NULL); 284 return NULL; 285 } 286 287 /* Open/Create the FITS file */ 288 if (access(name, F_OK) == 0) { // file exists 289 (void)fits_open_file(&fptr, name, READWRITE, &status); 290 if (fptr == NULL) { // if failed, try openning as just read-only 291 status = 0; 292 (void)fits_open_file(&fptr, name, READONLY, &status); 293 } 294 if (fptr == NULL || status != 0) { 295 char fitsErr[MAX_STRING_LENGTH]; 296 fits_get_errstatus(status, fitsErr); 297 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 298 PS_ERRORTEXT_psFits_FILENAME_INVALID, 299 name, fitsErr); 300 return NULL; 301 } 302 } else { // file does not exist, so create. 303 (void)fits_create_file(&fptr, name, &status); 304 if (fptr == NULL || status != 0) { 305 char fitsErr[MAX_STRING_LENGTH]; 306 fits_get_errstatus(status, fitsErr); 307 psError(PS_ERR_IO, true, 308 PS_ERRORTEXT_psFits_FILENAME_CREATE_FAILED, 309 name, fitsErr); 310 return NULL; 311 } 312 } 313 314 psFits* fits = psAlloc(sizeof(psFits)); 315 fits->filename = psAlloc(strlen(name)+1); 316 fits->fd = fptr; 317 strcpy((char*)fits->filename,name); 318 psMemSetDeallocator(fits,(psFreeFunc)fitsFree); 319 320 return fits; 321 } 322 323 324 bool psMemCheckFits(psPtr ptr) 325 { 326 return ( psMemGetDeallocator(ptr) == (psFreeFunc)fitsFree ); 327 } 328 329 330 bool psFitsMoveExtName(const psFits* fits, 331 const char* extname) 332 { 333 int status = 0; 334 335 if (fits == NULL) { 336 psError(PS_ERR_BAD_PARAMETER_NULL, true, 337 PS_ERRORTEXT_psFits_NULL); 338 return false; 339 } 340 341 if (extname == NULL) { 342 psError(PS_ERR_BAD_PARAMETER_NULL, true, 343 PS_ERRORTEXT_psFits_EXTNAME_NULL); 344 return false; 345 } 346 347 348 if (fits_movnam_hdu(fits->fd, ANY_HDU, (char*)extname, 0, &status) != 0) { 349 char fitsErr[MAX_STRING_LENGTH]; 350 fits_get_errstatus(status, fitsErr); 351 psError(PS_ERR_LOCATION_INVALID, true, 352 PS_ERRORTEXT_psFits_EXTNAME_INVALID, 353 extname, fits->filename, fitsErr); 354 return false; 355 } 356 357 return true; 358 } 359 360 bool psFitsMoveExtNum(const psFits* fits, 361 int extnum, 362 bool relative) 71 bool psFitsClose(psFits* fits) 363 72 { 364 73 if (fits == NULL) { … … 368 77 } 369 78 79 bool status = fitsClose(fits); 80 psMemSetDeallocator(fits,NULL); 81 psFree(fits); 82 83 return status; 84 } 85 86 psFits* psFitsOpen(const char* name, const char* mode) 87 { 370 88 int status = 0; 371 int hdutype = 0; 372 373 if (relative) { 374 fits_movrel_hdu(fits->fd, extnum, &hdutype, &status); 375 if (status != 0) { 89 fitsfile *fptr = NULL; /* Pointer to the FITS file */ 90 91 if (name == NULL) { 92 psError(PS_ERR_BAD_PARAMETER_NULL, true, 93 PS_ERRORTEXT_psFits_FILENAME_NULL); 94 return NULL; 95 } 96 97 /* check the mode to determine how to open/create file */ 98 int iomode; 99 bool newFile; 100 if (strcmp(mode,"r") == 0) { 101 iomode = READONLY; 102 newFile = false; 103 } else if (strcmp(mode,"rw") == 0 || strcmp(mode,"r+") == 0) { 104 iomode = READWRITE; 105 newFile = false; 106 } else if (strcmp(mode,"w") == 0 || strcmp(mode,"w+") == 0) { 107 iomode = READWRITE; 108 newFile = true; 109 } else if (strcmp(mode,"a") == 0|| strcmp(mode,"a+") == 0) { 110 iomode = READWRITE; 111 newFile = (access(name, F_OK) != 0); 112 } else { 113 // mode is not valid 114 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 115 "Specified mode, '%s', is invalid. Supported modes are r, r+, rw, w, w+, a, or a+.", 116 mode); 117 return NULL; 118 } 119 120 if (newFile) { 121 /* Check if an existing file is in the way before creating file*/ 122 if (access(name, F_OK) == 0) { 123 // file exists, delete old one first 124 remove 125 (name); 126 } 127 128 #if ( CFITSIO_DISKFILE == 1 ) 129 (void)fits_create_diskfile( 130 #else 131 (void)fits_create_file( 132 #endif 133 &fptr, 134 name, 135 &status); 136 if (fptr == NULL || status != 0) { 137 char fitsErr[MAX_STRING_LENGTH] 138 ; 139 fits_get_errstatus(status, fitsErr); 140 psError(PS_ERR_IO, true, 141 PS_ERRORTEXT_psFits_FILENAME_CREATE_FAILED, 142 name, fitsErr); 143 return NULL; 144 } 145 } else { 146 #if ( CFITSIO_DISKFILE == 1 ) 147 (void)fits_open_diskfile( 148 #else 149 (void)fits_open_file( 150 #endif 151 &fptr, 152 name, 153 iomode, 154 &status); 155 if (fptr == NULL || status != 0) { 156 char fitsErr[MAX_STRING_LENGTH] 157 ; 158 fits_get_errstatus(status, fitsErr); 159 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 160 PS_ERRORTEXT_psFits_FILENAME_INVALID, 161 name, fitsErr); 162 return NULL; 163 } 164 } 165 166 psFits* fits = psAlloc(sizeof(psFits)); 167 fits->fd = fptr; 168 psMemSetDeallocator(fits,(psFreeFunc)fitsFree); 169 170 return fits; 171 } 172 173 bool psMemCheckFits(psPtr ptr) 174 { 175 return ( psMemGetDeallocator(ptr) == (psFreeFunc)fitsFree ); 176 } 177 178 179 bool psFitsMoveExtName(const psFits* fits, 180 const char* extname) 181 { 182 int status = 0; 183 184 if (fits == NULL) { 185 psError(PS_ERR_BAD_PARAMETER_NULL, true, 186 PS_ERRORTEXT_psFits_NULL); 187 return false; 188 } 189 190 if (extname == NULL) { 191 psError(PS_ERR_BAD_PARAMETER_NULL, true, 192 PS_ERRORTEXT_psFits_EXTNAME_NULL); 193 return false; 194 } 195 196 197 if (fits_movnam_hdu(fits->fd, ANY_HDU, (char*)extname, 0, &status) != 0) { 376 198 char fitsErr[MAX_STRING_LENGTH]; 377 199 fits_get_errstatus(status, fitsErr); 378 200 psError(PS_ERR_LOCATION_INVALID, true, 379 PS_ERRORTEXT_psFits_EXTNUM_REL_MOVE_FAILED, 380 extnum, fits->filename, fitsErr); 381 return false; 382 } 383 } else { 384 fits_movabs_hdu(fits->fd, extnum+1, &hdutype, &status); 385 if (status != 0) { 386 char fitsErr[MAX_STRING_LENGTH]; 387 fits_get_errstatus(status, fitsErr); 388 psError(PS_ERR_LOCATION_INVALID, true, 389 PS_ERRORTEXT_psFits_EXTNUM_ABS_MOVE_FAILED, 390 extnum, fits->filename, fitsErr); 391 return false; 392 } 393 } 394 395 return true; 396 } 397 398 int psFitsGetExtNum(const psFits* fits) 399 { 400 int hdunum; 401 402 if (fits == NULL) { 403 psError(PS_ERR_BAD_PARAMETER_NULL, true, 404 PS_ERRORTEXT_psFits_NULL); 405 return PS_FITS_TYPE_NONE; 406 } 407 408 409 return fits_get_hdu_num(fits->fd,&hdunum) - 1; 410 } 411 412 psString psFitsGetExtName(const psFits* fits) 413 { 414 if (fits == NULL) { 415 psError(PS_ERR_BAD_PARAMETER_NULL, true, 416 PS_ERRORTEXT_psFits_NULL); 417 return NULL; 418 } 419 420 int status = 0; 421 char name[MAX_STRING_LENGTH]; 422 423 if (fits_read_key_str(fits->fd, "EXTNAME", name, NULL, &status) != 0) { 424 status = 0; 425 if (fits_read_key_str(fits->fd, "HDUNAME", name, NULL, &status) != 0) { 426 int num = psFitsGetExtNum(fits); 427 snprintf(name, MAX_STRING_LENGTH, "EXT-%3d",num); 428 } 429 } 430 return psStringCopy(name); 431 } 432 433 bool psFitsSetExtName(psFits* fits, const char* name) 434 { 435 if (fits == NULL) { 436 psError(PS_ERR_BAD_PARAMETER_NULL, true, 437 PS_ERRORTEXT_psFits_NULL); 438 return false; 439 } 440 441 if (name == NULL) { 442 psError(PS_ERR_BAD_PARAMETER_NULL, true, 443 PS_ERRORTEXT_psFits_EXTNAME_NULL); 444 return false; 445 } 446 447 int status = 0; 448 449 if (fits_update_key_str(fits->fd, "EXTNAME", (char*)name, NULL, &status) != 0) { 450 char fitsErr[MAX_STRING_LENGTH]; 451 (void)fits_get_errstatus(status, fitsErr); 452 psError(PS_ERR_IO, true, 453 PS_ERRORTEXT_psFits_WRITE_FAILED, 454 fits->filename, fitsErr); 455 return false; 456 } 457 458 return true; 459 } 460 461 int psFitsGetSize(const psFits* fits) 462 { 463 if (fits == NULL) { 464 psError(PS_ERR_BAD_PARAMETER_NULL, true, 465 PS_ERRORTEXT_psFits_NULL); 466 return 0; 467 } 468 469 int num = 0; 470 int status = 0; 471 472 if (fits_get_num_hdus(fits->fd, &num, &status) != 0) { 473 char fitsErr[MAX_STRING_LENGTH]; 474 fits_get_errstatus(status, fitsErr); 475 psError(PS_ERR_LOCATION_INVALID, true, 476 PS_ERRORTEXT_psFits_GETNUMHDUS_FAILED, 477 fits->filename, fitsErr); 478 return 0; 479 } 480 481 return num; 482 } 483 484 psFitsType psFitsGetExtType(const psFits* fits) 485 { 486 if (fits == NULL) { 487 psError(PS_ERR_BAD_PARAMETER_NULL, true, 488 PS_ERRORTEXT_psFits_NULL); 489 return PS_FITS_TYPE_NONE; 490 } 491 492 int status = 0; 493 int hdutype = PS_FITS_TYPE_NONE; 494 495 if (fits_get_hdu_type(fits->fd, &hdutype, &status) != 0) { 496 char fitsErr[MAX_STRING_LENGTH]; 497 fits_get_errstatus(status, fitsErr); 498 psError(PS_ERR_LOCATION_INVALID, true, 499 PS_ERRORTEXT_psFits_GETHDUTYPE_FAILED, 500 fits->filename, fitsErr); 501 return PS_FITS_TYPE_NONE; 502 } 503 504 if (hdutype == PS_FITS_TYPE_IMAGE && 505 psFitsGetExtNum(fits) > 0 && 506 isHDUEmpty(fits)) { 507 return PS_FITS_TYPE_ANY; 508 } 509 510 return hdutype; 511 } 512 513 psMetadata* psFitsReadHeader(psMetadata* out, 514 const psFits* fits) 515 { 516 if (fits == NULL) { 517 psError(PS_ERR_BAD_PARAMETER_NULL, true, 518 PS_ERRORTEXT_psFits_NULL); 519 return NULL; 520 } 521 522 if (out == NULL) { 523 out = psMetadataAlloc(); 524 if (out == NULL) { 525 psError(PS_ERR_UNKNOWN, false, 526 "Failed to allocate a new psMetadata container."); 201 PS_ERRORTEXT_psFits_EXTNAME_INVALID, 202 extname, fitsErr); 203 return false; 204 } 205 206 return true; 207 } 208 209 bool psFitsMoveExtNum(const psFits* fits, 210 int extnum, 211 bool relative) 212 { 213 if (fits == NULL) { 214 psError(PS_ERR_BAD_PARAMETER_NULL, true, 215 PS_ERRORTEXT_psFits_NULL); 216 return false; 217 } 218 219 int status = 0; 220 int hdutype = 0; 221 222 if (relative) { 223 fits_movrel_hdu(fits->fd, extnum, &hdutype, &status); 224 if (status != 0) { 225 char fitsErr[MAX_STRING_LENGTH]; 226 fits_get_errstatus(status, fitsErr); 227 psError(PS_ERR_LOCATION_INVALID, true, 228 PS_ERRORTEXT_psFits_EXTNUM_REL_MOVE_FAILED, 229 extnum, fitsErr); 230 return false; 231 } 232 } else { 233 fits_movabs_hdu(fits->fd, extnum+1, &hdutype, &status); 234 if (status != 0) { 235 char fitsErr[MAX_STRING_LENGTH]; 236 fits_get_errstatus(status, fitsErr); 237 psError(PS_ERR_LOCATION_INVALID, true, 238 PS_ERRORTEXT_psFits_EXTNUM_ABS_MOVE_FAILED, 239 extnum, fitsErr); 240 return false; 241 } 242 } 243 244 return true; 245 } 246 247 bool psFitsMoveLast(const psFits* fits) 248 { 249 if (fits == NULL) { 250 psError(PS_ERR_BAD_PARAMETER_NULL, true, 251 PS_ERRORTEXT_psFits_NULL); 252 return false; 253 } 254 255 return psFitsMoveExtNum(fits,psFitsGetSize(fits),false); 256 } 257 258 int psFitsGetExtNum(const psFits* fits) 259 { 260 int hdunum; 261 262 if (fits == NULL) { 263 psError(PS_ERR_BAD_PARAMETER_NULL, true, 264 PS_ERRORTEXT_psFits_NULL); 265 return PS_FITS_TYPE_NONE; 266 } 267 268 269 return fits_get_hdu_num(fits->fd,&hdunum) - 1; 270 } 271 272 psString psFitsGetExtName(const psFits* fits) 273 { 274 if (fits == NULL) { 275 psError(PS_ERR_BAD_PARAMETER_NULL, true, 276 PS_ERRORTEXT_psFits_NULL); 527 277 return NULL; 528 278 } 529 } 530 531 // Get number of key names 532 int numKeys = 0; 533 int keyNum = 0; 534 int status = 0; 535 fits_get_hdrpos(fits->fd, &numKeys, &keyNum, &status); 536 537 // Get each key name. Keywords start at one. 538 char keyType; 539 char keyName[MAX_STRING_LENGTH]; 540 char keyValue[MAX_STRING_LENGTH]; 541 char keyComment[MAX_STRING_LENGTH]; 542 psBool tempBool; 543 psBool success; 544 psBool stdKey; 545 for (int i = 1; i <= numKeys; i++) { 546 547 fits_read_keyn(fits->fd, i, keyName, keyValue, keyComment, &status); 548 549 stdKey = false; 550 551 int stdKeyIdx = 0; 552 while (standardFitsKeys[stdKeyIdx] != NULL && ! stdKey) { 553 if (strcmp(keyName,standardFitsKeys[stdKeyIdx++]) == 0) { 554 stdKey = true; 555 } 556 } 557 558 if (keyValue[0] != 0) { // blank values are not handled by fits_get_keytype 559 fits_get_keytype(keyValue, &keyType, &status); 560 } else { 561 keyType = 'C'; 562 } 563 if (status != 0) { 564 break; 565 } 566 567 if (! stdKey) { 568 switch (keyType) { 569 case 'X': // bit 570 case 'I': // short int. 571 case 'J': // int. 572 case 'B': // byte 573 success = psMetadataAdd(out, 574 PS_LIST_TAIL, 575 keyName, 576 PS_DATA_S32 | PS_META_DUPLICATE_OK, 577 keyComment, 578 atoi(keyValue)); 579 break; 580 case 'U': // unsigned int. may not fit in a psS32 581 case 'K': // long int. can't all fit in a psS32 582 case 'F': 583 success = psMetadataAdd(out, 584 PS_LIST_TAIL, 585 keyName, 586 PS_DATA_F64 | PS_META_DUPLICATE_OK, 587 keyComment, 588 atof(keyValue)); 589 break; 590 case 'C': 591 // remove the single-quotes at front/end 592 if (keyValue[0] == '\'' && keyValue[strlen(keyValue)-1] == '\'') { 593 keyValue[strlen(keyValue)-1] = '\0'; 594 success = psMetadataAdd(out, 595 PS_LIST_TAIL, 596 keyName, 597 PS_DATA_STRING | PS_META_DUPLICATE_OK, 598 keyComment, 599 keyValue+1); 600 } else { 601 success = psMetadataAdd(out, 602 PS_LIST_TAIL, 603 keyName, 604 PS_DATA_STRING | PS_META_DUPLICATE_OK, 605 keyComment, 606 keyValue); 607 } 608 break; 609 case 'L': 610 tempBool = (keyValue[0] == 'T') ? 1 : 0; 611 success = psMetadataAdd(out, 612 PS_LIST_TAIL, 613 keyName, 614 PS_DATA_BOOL | PS_META_DUPLICATE_OK, 615 keyComment, 616 tempBool); 617 break; 618 default: 619 psError(PS_ERR_IO, true, 620 PS_ERRORTEXT_psFits_METATYPE_INVALID, 621 keyType); 622 return out; 623 } 624 625 if (!success) { 626 psError(PS_ERR_UNKNOWN, false, 627 PS_ERRORTEXT_psFits_METADATA_ADD_FAILED, 628 keyName); 629 return out; 630 } 631 } 632 633 } 634 635 if ( status != 0) { 636 char fitsErr[MAX_STRING_LENGTH]; 637 (void)fits_get_errstatus(status, fitsErr); 638 psError(PS_ERR_IO, true, 639 PS_ERRORTEXT_psFits_METADATA_ADD_FAILED, 640 fitsErr); 641 return false; 642 } 643 644 return out; 645 } 646 647 psMetadata* psFitsReadHeaderSet(psMetadata* out, 648 const psFits* fits) 649 { 650 if (fits == NULL) { 651 psError(PS_ERR_BAD_PARAMETER_NULL, true, 652 PS_ERRORTEXT_psFits_NULL); 653 psFree(out); 654 return NULL; 655 } 656 657 if (out == NULL) { 658 out = psMetadataAlloc(); 659 if (out == NULL) { 660 psError(PS_ERR_UNKNOWN, false, 661 "Failed to allocate a new psMetadata container."); 662 return NULL; 663 } 664 } 665 666 int size = psFitsGetSize(fits); 667 668 int origPosition = psFitsGetExtNum(fits); 669 670 for (int lcv=0; lcv < size; lcv++) { 671 psFitsMoveExtNum(fits, lcv, false); 672 673 char* name = NULL; 674 if (lcv == 0) { 675 name = psStringCopy("PHU"); 676 } else { 677 name = psFitsGetExtName(fits); 678 } 679 680 psMetadata* header = psFitsReadHeader(NULL, fits); 681 if (name != NULL && header != NULL) { 682 psMetadataAddMetadata(out, PS_LIST_HEAD, name, 0, "FITS Header", 683 header); 684 } else { 685 psWarning("Failed to read HDU#%d header data.", 686 lcv); 687 } 688 689 psFree(name); 690 psFree(header); 691 } 692 693 // reposition to the original position 694 psFitsMoveExtNum(fits, origPosition, false); 695 696 return out; 697 } 698 699 psImage* psFitsReadImage(psImage* output, // a psImage to recycle. 700 const psFits* fits, // the psFits object 701 psRegion region, // the region in the FITS image to read 702 int z) // the z-plane in the FITS image cube to read 703 { 704 psS32 status = 0; /* CFITSIO file vars */ 705 psS32 nAxis = 0; 706 psS32 anynull = 0; 707 psS32 bitPix = 0; /* Pixel type */ 708 long nAxes[3]; 709 long firstPixel[3]; /* lower-left corner of image subset */ 710 long lastPixel[3]; /* upper-right corner of image subset */ 711 long increment[3]; /* increment for image subset */ 712 char fitsErr[80] = ""; /* CFITSIO error message string */ 713 psS32 fitsDatatype = 0; 714 psS32 datatype = 0; 715 716 if (fits == NULL) { 717 psError(PS_ERR_BAD_PARAMETER_NULL, true, 718 PS_ERRORTEXT_psFits_NULL); 719 psFree(output); 720 return NULL; 721 } 722 723 // check to see if we even are positioned on an image HDU 724 int hdutype; 725 if ( fits_get_hdu_type(fits->fd,&hdutype, &status) != 0) { 726 char fitsErr[MAX_STRING_LENGTH]; 727 (void)fits_get_errstatus(status, fitsErr); 728 psError(PS_ERR_IO, true, 729 PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED, 730 fitsErr); 731 return NULL; 732 } 733 if (hdutype != IMAGE_HDU) { 734 psError(PS_ERR_IO, true, 735 PS_ERRORTEXT_psFits_NOT_IMAGE_TYPE); 736 return NULL; 737 } 738 739 /* Get the data type 'bitPix' from the FITS image */ 740 if (fits_get_img_equivtype(fits->fd, &bitPix, &status) != 0) { 741 fits_get_errstatus(status, fitsErr); 742 psError(PS_ERR_IO, true, 743 PS_ERRORTEXT_psFits_DATATYPE_UNKNOWN, 744 fitsErr); 745 psFree(output); 746 return NULL; 747 } 748 749 /* Get the dimensions 'nAxis' from the FITS image */ 750 if (fits_get_img_dim(fits->fd, &nAxis, &status) != 0) { 751 (void)fits_get_errstatus(status, fitsErr); 752 psError(PS_ERR_IO, true, 753 PS_ERRORTEXT_psFits_IMAGE_DIM_UNKNOWN, 754 fitsErr); 755 psFree(output); 756 return NULL; 757 } 758 759 /* Validate the number of axis */ 760 if ((nAxis < 2) || (nAxis > 3)) { 761 psError(PS_ERR_IO, true, 762 PS_ERRORTEXT_psFits_IMAGE_DIMENSION_UNSUPPORTED, 763 nAxis); 764 psFree(output); 765 return NULL; 766 } 767 768 /* Get the Image size from the FITS file */ 769 if (fits_get_img_size(fits->fd, nAxis, nAxes, &status) != 0) { 770 (void)fits_get_errstatus(status, fitsErr); 771 psError(PS_ERR_IO, true, 772 PS_ERRORTEXT_psFits_IMAGE_SIZE_UNKNOWN, 773 fitsErr); 774 psFree(output); 775 return NULL; 776 } 777 778 firstPixel[0] = region.x0 + 1; 779 firstPixel[1] = region.y0 + 1; 780 firstPixel[2] = z + 1; 781 782 if (region.x1 > 0) { 783 lastPixel[0] = region.x1; 784 } else { 785 lastPixel[0] = nAxes[0] + region.x1; // n.b., region.x1 < 0 786 } 787 if (region.y1 > 0) { 788 lastPixel[1] = region.y1; 789 } else { 790 lastPixel[1] = nAxes[1] + region.y1; // n.b., region.y1 < 0 791 } 792 lastPixel[2] = z + 1; 793 794 increment[0] = 1; 795 increment[1] = 1; 796 increment[2] = 1; 797 798 switch (bitPix) { 799 case BYTE_IMG: 800 datatype = PS_TYPE_U8; 801 fitsDatatype = TBYTE; 802 break; 803 case SBYTE_IMG: 804 datatype = PS_TYPE_S8; 805 fitsDatatype = TSBYTE; 806 break; 807 case USHORT_IMG: 808 datatype = PS_TYPE_U16; 809 fitsDatatype = TUSHORT; 810 break; 811 case SHORT_IMG: 812 datatype = PS_TYPE_S16; 813 fitsDatatype = TSHORT; 814 break; 815 case ULONG_IMG: 816 datatype = PS_TYPE_U32; 817 fitsDatatype = TUINT; 818 break; 819 case LONG_IMG: 820 datatype = PS_TYPE_S32; 821 fitsDatatype = TINT; 822 break; 823 case LONGLONG_IMG: 824 datatype = PS_TYPE_S64; 825 fitsDatatype = TLONGLONG; 826 break; 827 case FLOAT_IMG: 828 datatype = PS_TYPE_F32; 829 fitsDatatype = TFLOAT; 830 break; 831 case DOUBLE_IMG: 832 datatype = PS_TYPE_F64; 833 fitsDatatype = TDOUBLE; 834 break; 835 default: 836 psError(PS_ERR_IO, true, 837 PS_ERRORTEXT_psFits_FITS_TYPE_UNSUPPORTED, 838 bitPix); 839 psFree(output); 840 return NULL; 841 } 842 843 output = psImageRecycle(output, 844 lastPixel[0]-firstPixel[0]+1, 845 lastPixel[1]-firstPixel[1]+1, 846 datatype); 847 848 if (output == NULL) { 849 psError(PS_ERR_UNKNOWN, false, 850 "Failed to allocate a properly sized image."); 851 return false; 852 } 853 854 // n.b., this assumes contiguous image buffer 855 if (fits_read_subset(fits->fd, fitsDatatype, firstPixel, lastPixel, increment, 856 NULL, output->data.V[0], &anynull, &status) != 0) { 857 psFree(output); 858 (void)fits_get_errstatus(status, fitsErr); 859 psError(PS_ERR_IO, true, 860 PS_ERRORTEXT_psFits_READ_FAILED, 861 fitsErr); 862 return NULL; 863 } 864 865 return output; 866 867 } 868 869 bool psFitsWriteImage(psFits* fits, 870 psMetadata* header, 871 const psImage* input, 872 int numZPlanes) 873 { 874 875 if (fits == NULL) { 876 psError(PS_ERR_BAD_PARAMETER_NULL, true, 877 PS_ERRORTEXT_psFits_NULL); 878 return false; 879 } 880 881 if (input == NULL) { 882 psError(PS_ERR_BAD_PARAMETER_NULL, true, 883 PS_ERRORTEXT_psFits_IMAGE_NULL); 884 return false; 885 } 886 int numCols = input->numCols; 887 int numRows = input->numRows; 888 889 int status = 0; 890 891 // determine the FITS-equivalent parameters 892 int bitPix; 893 double bZero; 894 int dataType; 895 if (! convertPsTypeToFits(input->type.type, &bitPix, &bZero, &dataType) ) { 896 return false; 897 } 898 899 int naxis = 3; 900 long naxes[3]; 901 902 naxes[0] = numCols; 903 naxes[1] = numRows; 904 naxes[2] = numZPlanes; 905 906 if (numZPlanes < 2) { 907 naxis = 2; 908 } 909 910 fits_create_img(fits->fd, bitPix, naxis, naxes, &status); 911 912 if (bZero != 0) { // set the bscale/bzero 913 fits_write_key_dbl(fits->fd, "BZERO", bZero, 12, "Pixel Value Offset", &status); 914 fits_write_key_dbl(fits->fd, "BSCALE", 1.0, 12, "Pixel Value Scale", &status); 915 fits_set_bscale(fits->fd, 1.0, bZero, &status); 916 } 917 918 // write the header, if any. 919 if (header != NULL) { 920 psFitsWriteHeader(header, (psPtr)fits); 921 } 922 923 if (input->parent == NULL) { // if no parent, assume that the image data is contiguous 924 fits_write_img(fits->fd, 925 dataType, // datatype 926 1, // writing to the first z-plane 927 numCols*numRows, // number of elements to write, i.e., the whole image 928 input->data.V[0], // the data 929 &status); 930 } else { // image data may not be contiguous; write one row at a time 931 int firstPixel = 1; 932 for (int row = 0; row < numRows; row++) { 933 fits_write_img(fits->fd, 934 dataType, // datatype 935 firstPixel, 936 numCols, // number of elements to write, i.e., one row's worth 937 input->data.V[row],// the raw row data 938 &status); 939 firstPixel += numCols; // move to next row 940 } 941 } 942 943 if ( status != 0) { 944 char fitsErr[MAX_STRING_LENGTH]; 945 (void)fits_get_errstatus(status, fitsErr); 946 psError(PS_ERR_IO, true, 947 PS_ERRORTEXT_psFits_WRITE_FAILED, 948 fits->filename, fitsErr); 949 return false; 950 } 951 952 return true; 953 954 } 955 956 bool psFitsUpdateImage(psFits* fits, 957 const psImage* input, 958 psRegion region, 959 int z) 960 { 961 int status = 0; 962 963 if (fits == NULL) { 964 psError(PS_ERR_BAD_PARAMETER_NULL, true, 965 PS_ERRORTEXT_psFits_NULL); 966 return false; 967 } 968 969 if (input == NULL) { 970 psError(PS_ERR_BAD_PARAMETER_NULL, true, 971 PS_ERRORTEXT_psFits_IMAGE_NULL); 972 return false; 973 } 974 975 // check to see if we are positioned on an image HDU 976 int hdutype; 977 if ( fits_get_hdu_type(fits->fd,&hdutype, &status) != 0) { 978 char fitsErr[MAX_STRING_LENGTH]; 979 (void)fits_get_errstatus(status, fitsErr); 980 psError(PS_ERR_IO, true, 981 PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED, 982 fitsErr); 983 return NULL; 984 } 985 if (hdutype != IMAGE_HDU) { 986 psError(PS_ERR_IO, true, 987 PS_ERRORTEXT_psFits_NOT_IMAGE_TYPE); 988 return NULL; 989 } 990 991 int numCols = input->numCols; 992 int numRows = input->numRows; 993 994 // determine the FITS-equivalent parameters 995 int bitPix; 996 double bZero; 997 int dataType; 998 if (! convertPsTypeToFits(input->type.type, &bitPix, &bZero, &dataType) ) { 999 return false; 1000 } 1001 1002 //check to see if the HDU has the same datatype 1003 int fileBitpix; 1004 int naxis; 1005 long nAxes[3]; 1006 nAxes[2] = 1; 1007 fits_get_img_param(fits->fd, 3, &fileBitpix, &naxis, nAxes, &status); 1008 1009 //check to see if the HDU has the same datatype 1010 if (bitPix != fileBitpix) { 1011 char* fitsTypeStr; 1012 char* imageTypeStr; 1013 PS_TYPE_NAME(fitsTypeStr,fileBitpix); 1014 PS_TYPE_NAME(imageTypeStr,input->type.type); 1015 psError(PS_ERR_IO, true, 1016 PS_ERRORTEXT_psFits_IMAGE_UPDATE_TYPE_MISMATCH, 1017 fitsTypeStr, imageTypeStr); 1018 return false; 1019 } 1020 1021 //check if the HDU has the z-plane requested 1022 if (z >= nAxes[2]) { 1023 psError(PS_ERR_BAD_PARAMETER_SIZE, true, 1024 PS_ERRORTEXT_psFits_FITS_Z_SMALL, 1025 nAxes[2],z); 1026 return false; 1027 } 1028 1029 // determine the region in the FITS file domain 1030 long firstPixel[3]; 1031 long lastPixel[3]; 1032 1033 firstPixel[0] = region.x0 + 1; 1034 firstPixel[1] = region.y0 + 1; 1035 firstPixel[2] = z + 1; 1036 1037 if (region.x1 > 0) { 1038 lastPixel[0] = region.x1; 1039 } else { 1040 lastPixel[0] = nAxes[0] + region.x1; // n.b., region.x1 < 0 1041 } 1042 if (region.y1 > 0) { 1043 lastPixel[1] = region.y1; 1044 } else { 1045 lastPixel[1] = nAxes[1] + region.y1; // n.b., region.y1 < 0 1046 } 1047 lastPixel[2] = z + 1; 1048 1049 if (firstPixel[0] < 1 || firstPixel[0] > nAxes[0] || 1050 firstPixel[1] < 1 || firstPixel[1] > nAxes[1] || 1051 lastPixel[0] < 1 || lastPixel[0] > nAxes[0] || 1052 lastPixel[1] < 1 || lastPixel[1] > nAxes[1]) { 1053 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 1054 "Specified region [%d:%d,%d:%d], is not valid given the %dx%d FITS image.", 1055 region.y0,region.y1-1,region.x0,region.x1-1); 1056 return false; 1057 1058 } 1059 1060 int dx = lastPixel[0] - firstPixel[0]; 1061 int dy = lastPixel[1] - firstPixel[1]; 1062 if (dx > numCols || 1063 dy > numRows) { 1064 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 1065 "The region [%d:%d,%d:%d], is not valid given the input %dx%d image.", 1066 firstPixel[1]-1,lastPixel[1]-1, 1067 firstPixel[0]-1,lastPixel[0]-1, 1068 numCols, numRows); 1069 return false; 1070 } 1071 1072 psImage* subset; 1073 if (dx != numCols || dy != numRows) { 1074 // the input image needs to be subsetted 1075 subset = psImageSubset((psImage*)input, psRegionSet(0,dx+1,0,dy+1)); 1076 } else { 1077 subset = psMemIncrRefCounter((psImage*)input); 1078 } 1079 1080 fits_write_subset(fits->fd, dataType, firstPixel, lastPixel, subset->data.V[0], &status); 1081 1082 if ( status != 0) { 1083 char fitsErr[MAX_STRING_LENGTH]; 1084 (void)fits_get_errstatus(status, fitsErr); 1085 psError(PS_ERR_IO, true, 1086 PS_ERRORTEXT_psFits_WRITE_FAILED, 1087 fits->filename, fitsErr); 1088 return false; 1089 } 1090 1091 return true; 1092 } 1093 1094 bool psFitsWriteHeader(const psMetadata* output, 1095 psFits* fits) 1096 { 1097 1098 if (fits == NULL) { 1099 psError(PS_ERR_BAD_PARAMETER_NULL, true, 1100 PS_ERRORTEXT_psFits_NULL); 1101 return false; 1102 } 1103 1104 if (output == NULL) { 1105 psError(PS_ERR_BAD_PARAMETER_NULL, true, 1106 PS_ERRORTEXT_psFits_METADATA_NULL); 1107 return false; 1108 } 1109 1110 int status = 0; 1111 1112 //transverse the metadata list and add each key. 1113 1114 psListIterator* iter = psListIteratorAlloc(output->list,PS_LIST_HEAD,true); 1115 psMetadataItem* item; 1116 while ( (item=psListGetAndIncrement(iter)) != NULL ) { 1117 switch (item->type) { 1118 case PS_DATA_BOOL: { 1119 int value = item->data.B; 1120 fits_update_key(fits->fd, 1121 TLOGICAL, 1122 item->name, 1123 &value, 1124 item->comment, 1125 &status); 1126 break; 1127 } 1128 case PS_DATA_S32: 1129 fits_update_key(fits->fd, 1130 TINT, 1131 item->name, 1132 &item->data.S32, 1133 item->comment, 1134 &status); 1135 break; 1136 case PS_DATA_F32: 1137 fits_update_key(fits->fd, 1138 TFLOAT, 1139 item->name, 1140 &item->data.F32, 1141 item->comment, 1142 &status); 1143 break; 1144 case PS_DATA_F64: 1145 fits_update_key(fits->fd, 1146 TDOUBLE, 1147 item->name, 1148 &item->data.F64, 1149 item->comment, 1150 &status); 1151 break; 1152 case PS_DATA_STRING: 1153 fits_update_key(fits->fd, 1154 TSTRING, 1155 item->name, 1156 item->data.V, 1157 item->comment, 1158 &status); 1159 break; 1160 default: // all other META types are ignored 1161 break; 1162 } 1163 1164 if ( status != 0) { 279 280 int status = 0; 281 char name[MAX_STRING_LENGTH]; 282 283 if (fits_read_key_str(fits->fd, "EXTNAME", name, NULL, &status) != 0) { 284 status = 0; 285 if (fits_read_key_str(fits->fd, "HDUNAME", name, NULL, &status) != 0) { 286 int num = psFitsGetExtNum(fits); 287 snprintf(name, MAX_STRING_LENGTH, "EXT-%3d",num); 288 } 289 } 290 return psStringCopy(name); 291 } 292 293 bool psFitsSetExtName(psFits* fits, const char* name) 294 { 295 if (fits == NULL) { 296 psError(PS_ERR_BAD_PARAMETER_NULL, true, 297 PS_ERRORTEXT_psFits_NULL); 298 return false; 299 } 300 301 if (name == NULL) { 302 psError(PS_ERR_BAD_PARAMETER_NULL, true, 303 PS_ERRORTEXT_psFits_EXTNAME_NULL); 304 return false; 305 } 306 307 int status = 0; 308 309 if (fits_update_key_str(fits->fd, "EXTNAME", (char*)name, NULL, &status) != 0) { 1165 310 char fitsErr[MAX_STRING_LENGTH]; 1166 311 (void)fits_get_errstatus(status, fitsErr); 1167 312 psError(PS_ERR_IO, true, 1168 313 PS_ERRORTEXT_psFits_WRITE_FAILED, 1169 fits->filename, fitsErr); 1170 return false; 1171 } 1172 } 1173 1174 return true; 1175 } 1176 1177 psMetadata* psFitsReadTableRow(const psFits* fits, 1178 int row) 1179 { 1180 long numRows; 1181 int numCols; 1182 int status = 0; 1183 1184 if (fits == NULL) { 1185 psError(PS_ERR_BAD_PARAMETER_NULL, true, 1186 PS_ERRORTEXT_psFits_NULL); 1187 return NULL; 1188 } 1189 1190 // check to see if we even are positioned on a table HDU 1191 int hdutype; 1192 fits_get_hdu_type(fits->fd,&hdutype, &status); 1193 if ( status != 0) { 1194 char fitsErr[MAX_STRING_LENGTH]; 1195 (void)fits_get_errstatus(status, fitsErr); 1196 psError(PS_ERR_IO, true, 1197 PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED, 1198 fitsErr); 1199 return NULL; 1200 } 1201 if (hdutype != ASCII_TBL && hdutype != BINARY_TBL) { 1202 psError(PS_ERR_IO, true, 1203 PS_ERRORTEXT_psFits_NOT_TABLE_TYPE); 1204 return NULL; 1205 } 1206 1207 // get the size of the FITS table 1208 fits_get_num_rows(fits->fd, &numRows, &status); 1209 fits_get_num_cols(fits->fd, &numCols, &status); 1210 if ( status != 0) { 1211 char fitsErr[MAX_STRING_LENGTH]; 1212 (void)fits_get_errstatus(status, fitsErr); 1213 psError(PS_ERR_IO, true, 1214 PS_ERRORTEXT_psFits_GET_TABLE_SIZE_FAILED, 1215 fitsErr); 1216 return NULL; 1217 } 1218 1219 psTrace(".psFits.psFitsReadTableRow",5,"Table size is %ix%i\n",numCols, numRows); 1220 // the row parameter in the proper range? 1221 if (row < 0 || row >= numRows) { 1222 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 1223 PS_ERRORTEXT_psFits_ROW_INVALID, 1224 row,numRows); 1225 return NULL; 1226 } 1227 1228 psMetadata* data = psMetadataAlloc(); 1229 1230 int typecode; 1231 long repeat; 1232 long width; 1233 char name[60]; 1234 for (int col = 1; col <= numCols; col++) { 1235 // get the column name 1236 if (hdutype == BINARY_TBL) { 1237 fits_get_bcolparms(fits->fd, col, name, 1238 NULL, NULL, NULL, NULL, NULL, NULL, NULL, &status); 1239 } else { 1240 fits_get_acolparms(fits->fd, col, name, 1241 NULL, NULL, NULL, NULL, NULL, NULL, NULL, &status); 1242 } 1243 // get the column type 1244 fits_get_coltype(fits->fd, col, &typecode, &repeat, &width, &status); 1245 1246 if (status == 0) { 1247 1248 #define READ_TABLE_ROW_CASE(FITSTYPE, NATIVETYPE, TYPE) \ 1249 case FITSTYPE: { \ 1250 if (repeat == 1) { \ 1251 NATIVETYPE value; \ 1252 int anynul = 0; \ 1253 fits_read_col(fits->fd, FITSTYPE, col,row+1, \ 1254 1, 1, NULL, &value, &anynul, &status); \ 1255 psTrace(".psFits.psFitsReadTableRow",5,"Column #%i, '%s', is type %i, repeat %i, Value = %g\n", \ 1256 col, name, typecode, repeat, (double)value); \ 1257 psMetadataAdd(data,PS_LIST_TAIL, name, \ 1258 PS_DATA_##TYPE, \ 1259 "", (ps##TYPE)value); \ 1260 } else { \ 1261 psVector* value = psVectorAlloc(repeat,PS_DATA_##TYPE); \ 1262 int anynul = 0; \ 1263 fits_read_col(fits->fd, FITSTYPE, col,row+1, \ 1264 1, repeat, NULL, value->data.U8, &anynul, &status); \ 1265 psMetadataAdd(data,PS_LIST_TAIL, name, \ 1266 PS_DATA_VECTOR, \ 1267 "", value); \ 1268 psFree(value); \ 1269 } \ 1270 break; \ 1271 } 1272 1273 switch (typecode) { 1274 case TBYTE: 1275 case TSHORT: 1276 case TLONGLONG: 1277 READ_TABLE_ROW_CASE(TLONG, long, S32) 1278 READ_TABLE_ROW_CASE(TFLOAT, float, F32) 1279 READ_TABLE_ROW_CASE(TDOUBLE, double, F64) 1280 READ_TABLE_ROW_CASE(TLOGICAL, bool, BOOL); 1281 case TSTRING: { 1282 char* value = psAlloc(repeat+1); 1283 int anynul = 0; 1284 fits_read_col(fits->fd, TSTRING, col,row+1, 1285 1, 1, NULL, &value, &anynul, &status); 1286 psTrace(".psFits.psFitsReadTableRow",5,"Column #%i, '%s', is type %i, repeat %i, value = %s\n", 1287 col, name, typecode, repeat, value); 1288 if (anynul == 0) { 1289 psMetadataAdd(data,PS_LIST_TAIL, name, 1290 PS_DATA_STRING, 1291 "", value); 1292 } 1293 psFree(value); 1294 break; 1295 } 1296 default: 1297 psWarning("Data type (%d) not supportted for column %d", 1298 typecode, col); 1299 1300 psTrace("psFits.psFitsReadTableRow", 2, 1301 "Column %d or row %d was of a non primitive type, %d", 1302 col, row, typecode); 1303 } 1304 } 1305 1306 if ( status != 0) { 1307 char fitsErr[MAX_STRING_LENGTH]; 1308 (void)fits_get_errstatus(status, fitsErr); 1309 psError(PS_ERR_IO, true, 1310 PS_ERRORTEXT_psFits_GET_TABLE_ELEMENT, 1311 col,row,fitsErr); 1312 psFree(data); 1313 return NULL; 1314 } 1315 1316 } 1317 1318 return data; 1319 } 1320 1321 psArray* psFitsReadTableColumn(const psFits* fits, 1322 const char* colname) 1323 { 1324 int colnum = 0; 1325 int status = 0; 1326 1327 if (fits == NULL) { 1328 psError(PS_ERR_BAD_PARAMETER_NULL, true, 1329 PS_ERRORTEXT_psFits_NULL); 1330 return NULL; 1331 } 1332 1333 // check to see if we even are positioned on a table HDU 1334 int hdutype; 1335 if ( fits_get_hdu_type(fits->fd,&hdutype, &status) != 0) { 1336 char fitsErr[MAX_STRING_LENGTH]; 1337 (void)fits_get_errstatus(status, fitsErr); 1338 psError(PS_ERR_IO, true, 1339 PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED, 1340 fitsErr); 1341 return NULL; 1342 } 1343 if (hdutype != ASCII_TBL && hdutype != BINARY_TBL) { 1344 psError(PS_ERR_IO, true, 1345 PS_ERRORTEXT_psFits_NOT_TABLE_TYPE); 1346 return NULL; 1347 } 1348 1349 // find the column by name 1350 if ( fits_get_colnum(fits->fd, CASESEN, (char*)colname, &colnum, &status) != 0) { 1351 char fitsErr[MAX_STRING_LENGTH]; 1352 (void)fits_get_errstatus(status, fitsErr); 1353 psError(PS_ERR_IO, true, 1354 PS_ERRORTEXT_psFits_FIND_COLUMN, 1355 colname, fitsErr); 1356 return NULL; 1357 } 1358 1359 // get the number of rows 1360 long numRows = 0; 1361 fits_get_num_rows(fits->fd, &numRows, &status); 1362 1363 // get the column length. 1364 int width; 1365 if ( fits_get_col_display_width(fits->fd, colnum, &width, &status) != 0) { 1366 char fitsErr[MAX_STRING_LENGTH]; 1367 (void)fits_get_errstatus(status, fitsErr); 1368 psError(PS_ERR_IO, true, 1369 PS_ERRORTEXT_psFits_GET_COLTYPE, 1370 fitsErr); 1371 return NULL; 1372 } 1373 1374 // allocate the buffers 1375 psArray* result = psArrayAlloc(numRows); 1376 for (int row = 0; row < numRows; row++) { 1377 result->data[row] = psAlloc((width+1)*sizeof(char)); 1378 } 1379 result->n = numRows; 1380 1381 fits_read_col_str(fits->fd, 1382 colnum, 1383 1, // firstrow 1384 1, // firestelem 1385 numRows, 1386 "", // nulstr 1387 (char**)result->data, 1388 NULL, 1389 &status); 1390 1391 if ( status != 0) { 1392 char fitsErr[MAX_STRING_LENGTH]; 1393 (void)fits_get_errstatus(status, fitsErr); 1394 psError(PS_ERR_IO, true, 1395 PS_ERRORTEXT_psFits_TABLE_READ_COL, 1396 fitsErr); 1397 return NULL; 1398 } 1399 1400 return result; 1401 } 1402 1403 psVector* psFitsReadTableColumnNum(const psFits* fits, 1404 const char* colname) 1405 { 1406 int status = 0; 1407 int colnum = 0; 1408 1409 if (fits == NULL) { 1410 psError(PS_ERR_BAD_PARAMETER_NULL, true, 1411 PS_ERRORTEXT_psFits_NULL); 1412 return NULL; 1413 } 1414 1415 // check to see if we even are positioned on a table HDU 1416 int hdutype; 1417 if ( fits_get_hdu_type(fits->fd,&hdutype, &status) != 0) { 1418 char fitsErr[MAX_STRING_LENGTH]; 1419 (void)fits_get_errstatus(status, fitsErr); 1420 psError(PS_ERR_IO, true, 1421 PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED, 1422 fitsErr); 1423 return NULL; 1424 } 1425 if (hdutype != ASCII_TBL && hdutype != BINARY_TBL) { 1426 psError(PS_ERR_IO, true, 1427 PS_ERRORTEXT_psFits_NOT_TABLE_TYPE); 1428 return NULL; 1429 } 1430 1431 // find the column by name 1432 if ( fits_get_colnum(fits->fd, CASESEN, (char*)colname, &colnum, &status) != 0) { 1433 char fitsErr[MAX_STRING_LENGTH]; 1434 (void)fits_get_errstatus(status, fitsErr); 1435 psError(PS_ERR_IO, true, 1436 PS_ERRORTEXT_psFits_FIND_COLUMN, 1437 colname, fitsErr); 1438 return NULL; 1439 } 1440 1441 // get the number of rows 1442 long numRows = 0; 1443 fits_get_num_rows(fits->fd, 1444 &numRows, 1445 &status); 1446 1447 // get the column datatype. 1448 int typecode; 1449 long repeat; 1450 long width; 1451 if ( fits_get_eqcoltype(fits->fd, colnum, &typecode, &repeat, &width, &status) != 0) { 1452 char fitsErr[MAX_STRING_LENGTH]; 1453 (void)fits_get_errstatus(status, fitsErr); 1454 psError(PS_ERR_IO, true, 1455 PS_ERRORTEXT_psFits_GET_COLTYPE, 1456 fitsErr); 1457 return NULL; 1458 } 1459 1460 psVector* result = psVectorAlloc(numRows, convertFitsToPsType(typecode)); 1461 1462 fits_read_col(fits->fd, 1463 typecode, 1464 colnum, 1465 1 /* firstrow */, 1466 1 /* firstelem */, 1467 numRows, 1468 NULL, 1469 (psPtr)(result->data.U8), 1470 NULL, 1471 &status); 1472 1473 if ( status != 0) { 1474 char fitsErr[MAX_STRING_LENGTH]; 1475 (void)fits_get_errstatus(status, fitsErr); 1476 psError(PS_ERR_IO, true, 1477 PS_ERRORTEXT_psFits_TABLE_READ_COL, 1478 fitsErr); 1479 return NULL; 1480 } 1481 1482 return result; 1483 } 1484 1485 1486 psArray* psFitsReadTable(psFits* fits) 1487 { 1488 int status = 0; 1489 1490 if (fits == NULL) { 1491 psError(PS_ERR_BAD_PARAMETER_NULL, true, 1492 PS_ERRORTEXT_psFits_NULL); 1493 return NULL; 1494 } 1495 1496 // check to see if we even are positioned on a table HDU 1497 int hdutype; 1498 if ( fits_get_hdu_type(fits->fd,&hdutype, &status) != 0) { 1499 char fitsErr[MAX_STRING_LENGTH]; 1500 (void)fits_get_errstatus(status, fitsErr); 1501 psError(PS_ERR_IO, true, 1502 PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED, 1503 fitsErr); 1504 return NULL; 1505 } 1506 if (hdutype != ASCII_TBL && hdutype != BINARY_TBL) { 1507 psError(PS_ERR_IO, true, 1508 PS_ERRORTEXT_psFits_NOT_TABLE_TYPE); 1509 return NULL; 1510 } 1511 1512 // get the size of the FITS table 1513 long numRows = 0; 1514 fits_get_num_rows(fits->fd, &numRows, &status); 1515 if ( status != 0) { 1516 char fitsErr[MAX_STRING_LENGTH]; 1517 (void)fits_get_errstatus(status, fitsErr); 1518 psError(PS_ERR_IO, true, 1519 PS_ERRORTEXT_psFits_GET_TABLE_SIZE_FAILED, 1520 fitsErr); 1521 return NULL; 1522 } 1523 1524 1525 psArray* table = psArrayAlloc(numRows); 1526 1527 for (int row = 0; row < numRows; row++) { 1528 psTrace(".psFits.psFitsReadTable",5,"Reading row %i of %i\n",row, numRows); 1529 table->data[row] = psFitsReadTableRow(fits,row); 1530 } 1531 1532 return table; 1533 } 1534 1535 bool psFitsWriteTable(psFits* fits, 1536 const psMetadata* header, 1537 const psArray* table) 1538 { 1539 int status = 0; 1540 1541 if (fits == NULL) { 1542 psError(PS_ERR_BAD_PARAMETER_NULL, true, 1543 PS_ERRORTEXT_psFits_NULL); 1544 return false; 1545 } 1546 1547 if (table == NULL) { 1548 psError(PS_ERR_BAD_PARAMETER_NULL, true, 1549 PS_ERRORTEXT_psFits_IMAGE_NULL); 1550 return false; 1551 } 1552 1553 int rows = table->n; 1554 if (rows < 1) { 1555 // no table data, what can I do? 1556 psError(PS_ERR_BAD_PARAMETER_SIZE, true, 1557 PS_ERRORTEXT_psFits_TABLE_EMPTY); 1558 return false; 1559 } 1560 1561 // find all the columns needed 1562 psArray* columns = psArrayAlloc(((psMetadata*)table->data[0])->list->n); 1563 columns->n=0; 1564 1565 // find the unique items in the array of metadata 'rows' 1566 psMetadataItem* item; 1567 for (int row=0; row < rows; row++) { 1568 psMetadata* rowMeta = table->data[row]; 1569 if (rowMeta != NULL) { 1570 psListIterator* iter = psListIteratorAlloc(rowMeta->list, 1571 PS_LIST_HEAD,true); 1572 while ( (item=psListGetAndIncrement(iter)) != NULL) { 1573 if (PS_DATA_IS_PRIMITIVE(item->type) || 1574 item->type == PS_DATA_STRING || 1575 item->type == PS_DATA_VECTOR) { 1576 bool found = false; 1577 psMetadataItem* fItem = NULL; 1578 int n; 1579 for (n=0; n < columns->n && ! found; n++) { 1580 fItem = (psMetadataItem*)(columns->data[n]); 1581 if (strcmp(item->name, fItem->name) == 0) { 1582 found = true; 1583 break; 1584 } 1585 } 1586 if (! found) { 1587 psArrayAdd(columns, columns->nalloc, item); 1588 } else if (item->type == PS_DATA_STRING && 1589 strlen(fItem->data.V) < strlen(item->data.V)) { 1590 // got to keep the longest string value as to know what size to create the table column 1591 psMemDecrRefCounter(fItem); 1592 columns->data[n] = psMemIncrRefCounter(item); 1593 1594 } else if (item->type == PS_DATA_VECTOR && 1595 ((psVector*)(fItem->data.V))->n < ((psVector*)(item->data.V))->n) { 1596 psMemDecrRefCounter(fItem); 1597 columns->data[n] = psMemIncrRefCounter(item); 1598 } 1599 } else { 1600 // unsupported type -- treating as an error 1601 psError(PS_ERR_BAD_PARAMETER_TYPE, true, 1602 "Unsupported data type (%d) for Metadata Item '%s' in row %d.", 1603 item->type, item->name, row); 1604 psFree(iter); 1605 psFree(columns); 1606 return false; 1607 } 1608 } 1609 psFree(iter); 1610 } 1611 } 1612 1613 if (columns->n == 0) { // no table columns found 1614 psError(PS_ERR_BAD_PARAMETER_SIZE, true, 1615 "Did not find any column data to write to a table."); 1616 psFree(columns); 1617 return false; 1618 } 1619 1620 //create list of column names and types. 1621 psArray* columnNames = psArrayAlloc(columns->n); 1622 psArray* columnTypes = psArrayAlloc(columns->n); 1623 for (int n=0; n < columns->n; n++) { 1624 columnNames->data[n] = psMemIncrRefCounter(((psMetadataItem*)columns->data[n])->name); 1625 if ( ! getMetadataTForm((psMetadataItem*)columns->data[n], 1626 (char**)&(columnTypes->data[n]),1) ) { 1627 psError(PS_ERR_UNKNOWN, true, 1628 "Failed to determine the FITS data type of '%s' (type=%d).", 1629 columnNames->data[n], 1630 ((psMetadataItem*)columns->data[n])->type); 1631 psFree(columns); 1632 psFree(columnNames); 1633 psFree(columnTypes); 1634 return false; 1635 } 1636 } 1637 1638 char* extname = NULL; 1639 if (header != NULL) { 1640 extname = psMetadataLookupPtr(NULL, header, "EXTNAME"); 1641 if ( extname == NULL) { 1642 extname = psMetadataLookupPtr(NULL, header, "HDUNAME"); 1643 } 1644 } 1645 1646 fits_create_tbl(fits->fd, 1647 BINARY_TBL, 1648 table->n, // number of rows in table 1649 columns->n, // number of columns in table 1650 (char**)columnNames->data, // names of the columns 1651 (char**)columnTypes->data, // format of the columns 1652 NULL, // physical unit of columns 1653 extname, // extension name 1654 &status); 1655 1656 psFree(columnNames); 1657 psFree(columnTypes); 1658 1659 // fill in the table elements with data 1660 for (int n = 0; n < columns->n; n++) { 1661 int row; 1662 item = columns->data[n]; 1663 if (PS_DATA_IS_PRIMITIVE(item->type) ) { 1664 psVector* col = psVectorAlloc(table->n, item->type); 1665 int dataSize = PSELEMTYPE_SIZEOF(item->type); 1666 int dataType; 1667 convertPsTypeToFits(item->type, NULL,NULL,&dataType); 1668 for (row = 0; row < table->n; row++) { 1669 psMetadataItem* dataItem = psMetadataLookup( 1670 table->data[row], 1671 item->name); 1672 memcpy(&col->data.U8[row*dataSize],&dataItem->data,dataSize); 1673 } 1674 fits_write_col(fits->fd, 1675 dataType, 1676 n+1, // column number 1677 1, // firstrow 1678 1, // firstelem 1679 table->n, // nelements 1680 col->data.U8, 1681 &status); 1682 psFree(col); 1683 } else if (item->type == PS_DATA_STRING) { 1684 psArray* colArray = psArrayAlloc(table->n); 1685 for (row = 0; row < table->n; row++) { 1686 colArray->data[row] = psMemIncrRefCounter( 1687 psMetadataLookupStr(NULL, 1688 table->data[row], 1689 item->name)); 1690 } 1691 fits_write_col_str(fits->fd, 1692 n+1, 1693 1, 1694 1, 1695 table->n, 1696 (char**)colArray->data, 1697 &status); 1698 psFree(colArray); 1699 } else if (item->type == PS_DATA_VECTOR) { 1700 psVector* vec = (psVector*)(item->data.V); 1701 psVector* col = psVectorAlloc(table->n*vec->n, vec->type.type); 1702 int dataSize = PSELEMTYPE_SIZEOF(vec->type.type)*vec->n; 1703 int dataType; 1704 convertPsTypeToFits(vec->type.type, NULL,NULL,&dataType); 1705 for (row = 0; row < table->n; row++) { 1706 psMetadataItem* dataItem = psMetadataLookup( 1707 table->data[row], 1708 item->name); 1709 memcpy(&col->data.U8[row*dataSize], 1710 ((psVector*)(dataItem->data.V))->data.U8, 1711 dataSize); 1712 } 1713 fits_write_col(fits->fd, 1714 dataType, 1715 n+1, // column number 1716 1, // firstrow 1717 1, // firstelem 1718 table->n*vec->n, // nelements 1719 col->data.U8, 1720 &status); 1721 psFree(col); 1722 } 1723 if (status != 0) { 314 fitsErr); 315 return false; 316 } 317 318 return true; 319 } 320 321 bool psFitsDeleteExtNum(psFits* fits, 322 int extnum, 323 bool relative) 324 { 325 if (fits == NULL) { 326 psError(PS_ERR_BAD_PARAMETER_NULL, true, 327 PS_ERRORTEXT_psFits_NULL); 328 return false; 329 } 330 331 // move to the specified HDU 332 if (! psFitsMoveExtNum(fits,extnum,relative) ) { 333 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 334 "Failed to delete HDU #%d", 335 extnum); 336 return false; 337 } 338 339 int status = 0; 340 341 // OK, now let's delete the HDU 342 if (fits_delete_hdu(fits->fd, NULL, &status) != 0) { 1724 343 char fitsErr[MAX_STRING_LENGTH]; 1725 344 (void)fits_get_errstatus(status, fitsErr); 1726 345 psError(PS_ERR_IO, true, 1727 346 PS_ERRORTEXT_psFits_WRITE_FAILED, 1728 fits->filename, fitsErr); 1729 psFree(columns); 1730 return false; 1731 } 1732 1733 } 1734 1735 psFree(columns); 1736 1737 return true; 1738 } 1739 1740 bool psFitsUpdateTable(psFits* fits, 1741 const psMetadata* data, 1742 int row) 1743 { 1744 int status = 0; 1745 1746 if (fits == NULL) { 1747 psError(PS_ERR_BAD_PARAMETER_NULL, true, 1748 PS_ERRORTEXT_psFits_NULL); 1749 return false; 1750 } 1751 1752 if (data == NULL) { 1753 psError(PS_ERR_BAD_PARAMETER_NULL, true, 1754 PS_ERRORTEXT_psFits_IMAGE_NULL); 1755 return false; 1756 } 1757 1758 // check to see if we even are positioned on a table HDU 1759 int hdutype; 1760 if ( fits_get_hdu_type(fits->fd,&hdutype, &status) != 0) { 1761 char fitsErr[MAX_STRING_LENGTH]; 1762 (void)fits_get_errstatus(status, fitsErr); 1763 psError(PS_ERR_IO, true, 1764 PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED, 1765 fitsErr); 1766 return false; 1767 } 1768 if (hdutype != ASCII_TBL && hdutype != BINARY_TBL) { 1769 psError(PS_ERR_IO, true, 1770 PS_ERRORTEXT_psFits_NOT_TABLE_TYPE); 1771 return false; 1772 } 1773 1774 psMetadataIterator* iter = psMetadataIteratorAlloc((psPtr)data,PS_LIST_HEAD,NULL); 1775 1776 psMetadataItem* item; 1777 1778 while ( (item=psMetadataGetAndIncrement(iter)) != NULL) { 1779 if (PS_DATA_IS_PRIMITIVE(item->type) || 1780 item->type == PS_DATA_BOOL || 1781 item->type == PS_DATA_STRING) { 1782 // operating on primitive data type or string, i.e., not a complex object 1783 int colnum = 0; 1784 1785 if ( fits_get_colnum(fits->fd, CASESEN, item->name, &colnum, &status) == 0) { 1786 // cooresponding column found in table 1787 int dataType; 1788 convertPsTypeToFits(item->type, NULL, NULL, &dataType); 1789 1790 if (fits_write_col(fits->fd, dataType, colnum, row+1, 1, 1, &item->data,&status) != 0) { 1791 char fitsErr[MAX_STRING_LENGTH]; 1792 (void)fits_get_errstatus(status, fitsErr); 1793 psError(PS_ERR_IO, true, 1794 PS_ERRORTEXT_psFits_WRITE_FAILED, 1795 fits->filename, fitsErr); 1796 psFree(iter); 1797 return false; 1798 } 1799 } else { 1800 // the column was not found. 1801 psWarning("No column with the name '%s' exists in the table.", 1802 item->name); 1803 } 1804 } 1805 } 1806 1807 psFree(iter); 1808 1809 return true; 1810 } 347 fitsErr); 348 return false; 349 } 350 351 return true; 352 } 353 354 bool psFitsDeleteExtName(psFits* fits, 355 const char* extname) 356 { 357 if (fits == NULL) { 358 psError(PS_ERR_BAD_PARAMETER_NULL, true, 359 PS_ERRORTEXT_psFits_NULL); 360 return false; 361 } 362 363 // move to the specified HDU 364 if (! psFitsMoveExtName(fits,extname) ) { 365 psError(PS_ERR_BAD_PARAMETER_VALUE, false, 366 "Failed to delete HDU with the name '%s'", 367 extname); 368 return false; 369 } 370 371 372 int status = 0; 373 374 // OK, now let's delete the HDU 375 if (fits_delete_hdu(fits->fd, NULL, &status) != 0) { 376 char fitsErr[MAX_STRING_LENGTH]; 377 (void)fits_get_errstatus(status, fitsErr); 378 psError(PS_ERR_IO, true, 379 PS_ERRORTEXT_psFits_WRITE_FAILED, 380 fitsErr); 381 return false; 382 } 383 384 return true; 385 } 386 387 int psFitsGetSize(const psFits* fits) 388 { 389 if (fits == NULL) { 390 psError(PS_ERR_BAD_PARAMETER_NULL, true, 391 PS_ERRORTEXT_psFits_NULL); 392 return 0; 393 } 394 395 int num = 0; 396 int status = 0; 397 398 if (fits_get_num_hdus(fits->fd, &num, &status) != 0) { 399 char fitsErr[MAX_STRING_LENGTH]; 400 fits_get_errstatus(status, fitsErr); 401 psError(PS_ERR_LOCATION_INVALID, true, 402 PS_ERRORTEXT_psFits_GETNUMHDUS_FAILED, 403 fitsErr); 404 return 0; 405 } 406 407 return num; 408 } 409 410 psFitsType psFitsGetExtType(const psFits* fits) 411 { 412 if (fits == NULL) { 413 psError(PS_ERR_BAD_PARAMETER_NULL, true, 414 PS_ERRORTEXT_psFits_NULL); 415 return PS_FITS_TYPE_NONE; 416 } 417 418 int status = 0; 419 int hdutype = PS_FITS_TYPE_NONE; 420 421 if (fits_get_hdu_type(fits->fd, &hdutype, &status) != 0) { 422 char fitsErr[MAX_STRING_LENGTH]; 423 fits_get_errstatus(status, fitsErr); 424 psError(PS_ERR_LOCATION_INVALID, true, 425 PS_ERRORTEXT_psFits_GETHDUTYPE_FAILED, 426 fitsErr); 427 return PS_FITS_TYPE_NONE; 428 } 429 430 if (hdutype == PS_FITS_TYPE_IMAGE && 431 psFitsGetExtNum(fits) > 0 && 432 isHDUEmpty(fits)) { 433 return PS_FITS_TYPE_ANY; 434 } 435 436 return hdutype; 437 } 438 439 bool psFitsTruncate(psFits* fits) 440 { 441 if (fits == NULL) { 442 psError(PS_ERR_BAD_PARAMETER_NULL, true, 443 PS_ERRORTEXT_psFits_NULL); 444 return PS_FITS_TYPE_NONE; 445 } 446 447 int newEnd = psFitsGetExtNum(fits); 448 449 psFitsMoveLast(fits); 450 int end = psFitsGetExtNum(fits); 451 452 // delete HDUs from end to beginning position + 1; 453 for (int lcv=end;lcv > newEnd; lcv--) { 454 if (! psFitsDeleteExtNum(fits,lcv,false)) { 455 // failed to delete an HDU!? 456 psError(PS_ERR_UNKNOWN, false, 457 "Failed to truncate file. HDU #%d out of %d could not be deleted.", 458 lcv,end); 459 return false; 460 } 461 } 462 463 return true; 464 } -
trunk/psLib/src/fits/psFits.h
r5057 r5511 7 7 * @author Robert DeSonia, MHPCC 8 8 * 9 * @version $Revision: 1.2 1$ $Name: not supported by cvs2svn $10 * @date $Date: 2005- 09-15 21:22:21$9 * @version $Revision: 1.22 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2005-11-14 22:18:30 $ 11 11 * 12 12 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 16 16 #define PS_FITS_H 17 17 18 #include <fitsio.h>18 #include <fitsio.h> 19 19 20 20 #include "psType.h" … … 49 49 { 50 50 fitsfile* fd; ///< the CFITSIO fits files handle. 51 const char* filename; ///< the filename of the fits file52 bool writable; ///< Is the file writable?53 51 } 54 52 psFits; … … 59 57 * NULL if the open of the FITS file failed 60 58 */ 61 psFits* psFitsAlloc( 62 const char* name ///< the FITS file name 59 psFits* psFitsOpen( 60 const char* filename, ///< the FITS file name 61 const char* mode 62 /**< File open mode. Could be one of the following: 63 * 'r' (read only), 64 * 'r+' (read & write), 65 * 'rw' (same as 'r+'), or 66 * 'w' (create new file for writing) 67 */ 68 ); 69 70 /** Closes a FITS file. 71 * 72 * @return bool TRUE if FITS file was successfully closed, otherwise FALSE 73 */ 74 bool psFitsClose( 75 psFits* fits ///< psFits object to close 63 76 ); 64 77 65 78 /** Checks the type of a particular pointer. 66 79 * 67 * Uses the appropriate deallocation function in psMemBlock to check the ptr datatype. 80 * Uses the appropriate deallocation function in psMemBlock to check the ptr 81 * datatype. 68 82 * 69 * @return bool: True if the pointer matches a psFits structure, false otherwise. 83 * @return bool: True if the pointer matches a psFits structure, false 84 * otherwise. 70 85 */ 71 86 bool psMemCheckFits( … … 76 91 /** Moves the FITS HDU to the specified extension name. 77 92 * 78 * @return psFitsType The HDU type, or PS_FITS_TYPE_NONE if move failed. 93 * @return bool TRUE if the extension name was found and move was 94 * successful, otherwise FALSE 79 95 */ 80 96 bool psFitsMoveExtName( … … 85 101 /** Moves the FITS HDU to the specified extension number 86 102 * 87 * @return psFitsType The HDU type, or PS_FITS_TYPE_NONE if move failed. 103 * @return bool TRUE if the extension number was found and move was 104 * successful, otherwise FALSE 88 105 */ 89 106 bool psFitsMoveExtNum( … … 91 108 int extnum, ///< the extension number to move to (zero is primary HDU) 92 109 bool relative ///< if true, extnum is a relative number to the current position 110 ); 111 112 /** Moves the FITS HDU to the end of the file 113 * 114 * @return bool TRUE if the move was successful, otherwise FALSE 115 */ 116 bool psFitsMoveLast( 117 const psFits* fits ///< the psFits object to move 93 118 ); 94 119 … … 129 154 ); 130 155 156 /** Remove the an HDU as specified by number 157 * 158 * @return bool TRUE if the specified HDU was removed, otherwise FALSE 159 */ 160 bool psFitsDeleteExtNum( 161 psFits* fits, ///< the psFits object 162 int extnum, ///< the extension number to delete (zero is primary HDU) 163 bool relative ///< if true, extnum is a relative number to the current position 164 ); 165 166 /** Remove the an HDU as specified by extension name 167 * 168 * @return bool TRUE if the specified HDU was removed, otherwise FALSE 169 */ 170 bool psFitsDeleteExtName( 171 psFits* fits, ///< the psFits object 172 const char* extname ///< the extension name to delete 173 ); 174 131 175 /** Get the extension type of the current HDU. 132 176 * … … 138 182 ); 139 183 140 /** Reads the header of the current HDU.184 /** Delete all extensions after the current position 141 185 * 142 * @return psMetadata* the header data186 * @return bool TRUE if the operation was successful, otherwise FALSE 143 187 */ 144 psMetadata* psFitsReadHeader( 145 psMetadata* out, 146 ///< The psMetadata to add the header data. If null, a new psMetadata is created. 147 148 const psFits* fits ///< the psFits object 149 ); 150 151 /** Reads the header of all HDUs. The current HDU is not changed. 152 * 153 * @return psMetadata* the header data set as a number of metadata entries 154 */ 155 psMetadata* psFitsReadHeaderSet( 156 psMetadata* out, 157 ///< The psMetadata to add the header data via psMetadata items. If null, a 158 ///< new psMetadata is created. The keys of the psMetadata are the extension names 159 ///< of the cooresponding HDUs. 160 161 const psFits* fits ///< the psFits object 162 ); 163 164 /** Writes the values of the metadata to the current HDU header. 165 * 166 * @return bool if TRUE, the write was successful, otherwise FALSE. 167 */ 168 bool psFitsWriteHeader( 169 const psMetadata* output, ///< the psMetadata data in which to write 188 bool psFitsTruncate( 170 189 psFits* fits ///< the psFits object 171 );172 173 /** Reads an image, given the desired region and z-plane.174 *175 * @return psImage* the read image or NULL if there was an error.176 */177 psImage* psFitsReadImage(178 psImage* out, ///< a psImage to recycle.179 const psFits* fits, ///< the psFits object180 psRegion region, ///< the region in the FITS image to read181 int z ///< the z-plane in the FITS image cube to read182 );183 184 /** Writes an image, given the desired region and z-plane.185 *186 * @return bool TRUE is the write was successful, otherwise FALSE.187 */188 bool psFitsWriteImage(189 psFits* fits, ///< the psFits object190 psMetadata* header, ///< header items for the new HDU. Can be NULL.191 const psImage* input, ///< the image to output192 int depth ///< the number of z-planes of the FITS image data cube193 );194 195 /** Updates the FITS file image, given the desired region and z-plane.196 *197 * @return bool TRUE is the write was successful, otherwise FALSE.198 */199 bool psFitsUpdateImage(200 psFits* fits, ///< the psFits object201 const psImage* input, ///< the image to output202 psRegion region, ///< the region in the FITS image to write203 int z ///< the z-planes of the FITS image data cube to write204 );205 206 /** Reads a table row. The current HDU type must be either207 * PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.208 *209 * @return psMetadata* The table row's data. The keys are the column names.210 */211 psMetadata* psFitsReadTableRow(212 const psFits* fits, ///< the psFits object213 int row ///< row number to read214 );215 216 /** Reads a table column. The current HDU type must be either217 * PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.218 *219 * @return psArray* Array of data items for the specified column or NULL220 * if an error occurred.221 */222 psArray* psFitsReadTableColumn(223 const psFits* fits, ///< the psFits object224 const char* colname ///< the column name225 );226 227 /** Reads a table column of numbers. The current HDU type must be either228 * PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.229 *230 * @return psVector* Vector of data for the specified column or NULL231 * if an error occurred.232 */233 psVector* psFitsReadTableColumnNum(234 const psFits* fits, ///< the psFits object235 const char* colname ///< the column name236 );237 238 239 /** Reads a whole FITS table. The current HDU type must be either240 * PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.241 *242 * @return psArray* Array of psMetadata items, which contains the output243 * data items of each row.244 *245 * @see psFitsReadTableRow246 */247 psArray* psFitsReadTable(248 psFits* fits ///< the psFits object249 );250 251 /** Writes a whole FITS table. The current HDU type must be either252 * PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.253 *254 * @return bool TRUE if the write was successful, otherwise FALSE255 *256 * @see psFitsReadTableRow257 */258 bool psFitsWriteTable(259 psFits* fits, ///< the psFits object260 const psMetadata* header, ///< header items for the new HDU. Can be NULL.261 const psArray* table262 ///< Array of psMetadata items, which contains the output data items of each row.263 );264 265 /** Updates a FITS table. The current HDU type must be either266 * PS_FITS_TYPE_BINARY_TABLE or PS_FITS_TYPE_ASCII_TABLE.267 *268 * @return bool TRUE if the write was successful, otherwise FALSE269 *270 * @see psFitsWriteTable271 */272 bool psFitsUpdateTable(273 psFits* fits, ///< the psFits object274 const psMetadata* data,275 ///< Array of psMetadata items, which contains the output data items of each row.276 int row ///< the row number to update.277 190 ); 278 191
Note:
See TracChangeset
for help on using the changeset viewer.
