Changeset 7846
- Timestamp:
- Jul 7, 2006, 5:06:40 PM (20 years ago)
- Location:
- trunk/psLib/src/fits
- Files:
-
- 4 edited
-
psFits.c (modified) (2 diffs)
-
psFits.h (modified) (2 diffs)
-
psFitsImage.c (modified) (4 diffs)
-
psFitsTable.c (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/fits/psFits.c
r7300 r7846 7 7 * @author Robert DeSonia, MHPCC 8 8 * 9 * @version $Revision: 1.5 5$ $Name: not supported by cvs2svn $10 * @date $Date: 2006-0 6-02 21:33:33$9 * @version $Revision: 1.56 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2006-07-08 03:06:40 $ 11 11 * 12 12 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 486 486 return true; 487 487 } 488 489 490 psDataType p_psFitsTypeFromCfitsio(int datatype) 491 { 492 switch (datatype) { 493 case TBYTE: 494 return PS_TYPE_U8; 495 case TSBYTE: 496 return PS_TYPE_S8; 497 case TSHORT: 498 return PS_TYPE_S16; 499 case TUSHORT: 500 return PS_TYPE_U16; 501 case TLONG: 502 if (sizeof(long) == 8) { 503 return PS_TYPE_S64; 504 } 505 // no break 506 case TINT: 507 return PS_TYPE_S32; 508 case TULONG: 509 if (sizeof(unsigned long) == 8) { 510 return PS_TYPE_U64; 511 } 512 // no break 513 case TUINT: 514 return PS_TYPE_U32; 515 case TLONGLONG: 516 return PS_TYPE_S64; 517 case TFLOAT: 518 return PS_TYPE_F32; 519 case TDOUBLE: 520 return PS_TYPE_F64; 521 case TCOMPLEX: 522 return PS_TYPE_C32; 523 case TDBLCOMPLEX: 524 return PS_TYPE_C64; 525 case TLOGICAL: 526 return PS_TYPE_BOOL; 527 default: 528 psError(PS_ERR_IO, true, 529 "Unknown FITS datatype, %d.", 530 datatype); 531 return 0; 532 } 533 } 534 535 bool p_psFitsTypeToCfitsio(psDataType type, int* bitPix, double* bZero, int* dataType) 536 { 537 int bitpix; 538 int datatype; 539 double bzero = 0.0; 540 541 switch (type) { 542 543 case PS_TYPE_U8: 544 bitpix = BYTE_IMG; 545 datatype = TBYTE; 546 break; 547 548 case PS_TYPE_S8: 549 bitpix = BYTE_IMG; 550 bzero = INT8_MIN; 551 datatype = TSBYTE; 552 break; 553 554 case PS_TYPE_U16: 555 bitpix = SHORT_IMG; 556 bzero = -1.0 * INT16_MIN; 557 datatype = TUSHORT; 558 break; 559 560 case PS_TYPE_S16: 561 bitpix = SHORT_IMG; 562 datatype = TSHORT; 563 break; 564 565 case PS_TYPE_U32: 566 bitpix = LONG_IMG; 567 bzero = -1.0 * INT32_MIN; 568 datatype = TUINT; 569 break; 570 571 case PS_TYPE_S32: 572 bitpix = LONG_IMG; 573 datatype = TINT; 574 break; 575 576 case PS_TYPE_F32: 577 bitpix = FLOAT_IMG; 578 datatype = TFLOAT; 579 break; 580 581 case PS_TYPE_F64: 582 bitpix = DOUBLE_IMG; 583 datatype = TDOUBLE; 584 break; 585 586 case PS_DATA_STRING: 587 bitpix = BYTE_IMG; 588 datatype = TSTRING; 589 break; 590 591 case PS_DATA_BOOL: 592 bitpix = BYTE_IMG; 593 datatype = TLOGICAL; 594 break; 595 596 default: { 597 char* typeStr; 598 PS_TYPE_NAME(typeStr,type); 599 psError(PS_ERR_BAD_PARAMETER_TYPE, true, 600 PS_ERRORTEXT_psFits_TYPE_UNSUPPORTED, 601 typeStr); 602 return false; 603 } 604 } 605 606 // pass back the requested parameters (NULL parameters are not set, of course). 607 if (bitPix != NULL) { 608 *bitPix = bitpix; 609 } 610 611 if (dataType != NULL) { 612 *dataType = datatype; 613 } 614 615 if (bZero != NULL) { 616 *bZero = bzero; 617 } 618 619 return true; 620 } 621 622 -
trunk/psLib/src/fits/psFits.h
r6767 r7846 7 7 * @author Robert DeSonia, MHPCC 8 8 * 9 * @version $Revision: 1.2 4$ $Name: not supported by cvs2svn $10 * @date $Date: 2006-0 4-04 19:52:42$9 * @version $Revision: 1.25 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2006-07-08 03:06:40 $ 11 11 * 12 12 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 191 191 ); 192 192 193 // Return the psLib type, given a cfitsio data type 194 psDataType p_psFitsTypeFromCfitsio(int datatype // cfitsio data type 195 ); 196 197 // Return the cfitsio data type, given a psLib type 198 bool p_psFitsTypeToCfitsio(psDataType type, // psLib data type 199 int* bitPix, // The corresponding BITPIX (returned) 200 double* bZero, // The corresponding BZERO (returned) 201 int* dataType// The corresponding cfitsio data type (returned) 202 ); 203 193 204 /// @} 194 205 -
trunk/psLib/src/fits/psFitsImage.c
r7540 r7846 7 7 * @author Robert DeSonia, MHPCC 8 8 * 9 * @version $Revision: 1.1 0$ $Name: not supported by cvs2svn $10 * @date $Date: 2006-0 6-13 22:28:02$9 * @version $Revision: 1.11 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2006-07-08 03:06:40 $ 11 11 * 12 12 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 31 31 #define MAX_STRING_LENGTH 256 // maximum length string for FITS routines 32 32 33 34 static bool convertPsTypeToFits(int type, int* bitPix, double* bZero, int* dataType)35 {36 37 int bitpix;38 int datatype;39 double bzero = 0.0;40 41 switch (type) {42 43 case PS_TYPE_U8:44 bitpix = BYTE_IMG;45 datatype = TBYTE;46 break;47 48 case PS_TYPE_S8:49 bitpix = BYTE_IMG;50 bzero = INT8_MIN;51 datatype = TSBYTE;52 break;53 54 case PS_TYPE_U16:55 bitpix = SHORT_IMG;56 bzero = -1.0 * INT16_MIN;57 datatype = TUSHORT;58 break;59 60 case PS_TYPE_S16:61 bitpix = SHORT_IMG;62 datatype = TSHORT;63 break;64 65 case PS_TYPE_U32:66 bitpix = LONG_IMG;67 bzero = -1.0 * INT32_MIN;68 datatype = TUINT;69 break;70 71 case PS_TYPE_S32:72 bitpix = LONG_IMG;73 datatype = TINT;74 break;75 76 case PS_TYPE_F32:77 bitpix = FLOAT_IMG;78 datatype = TFLOAT;79 break;80 81 case PS_TYPE_F64:82 bitpix = DOUBLE_IMG;83 datatype = TDOUBLE;84 break;85 86 case PS_DATA_STRING:87 bitpix = BYTE_IMG;88 datatype = TSTRING;89 break;90 91 case PS_DATA_BOOL:92 bitpix = BYTE_IMG;93 datatype = TLOGICAL;94 break;95 96 default: {97 char* typeStr;98 PS_TYPE_NAME(typeStr,type);99 psError(PS_ERR_BAD_PARAMETER_TYPE, true,100 PS_ERRORTEXT_psFits_TYPE_UNSUPPORTED,101 typeStr);102 return false;103 }104 }105 106 // pass the requested parameters (NULL parameters are not set, of course).107 if (bitPix != NULL) {108 *bitPix = bitpix;109 }110 111 if (dataType != NULL) {112 *dataType = datatype;113 }114 115 if (bZero != NULL) {116 *bZero = bzero;117 }118 119 return true;120 }121 122 33 psImage* psFitsReadImage(const psFits* fits, // the psFits object 123 34 psRegion region, // the region in the FITS image to read … … 314 225 double bZero; // Zero offset 315 226 int dataType; // cfitsio data type 316 if (! convertPsTypeToFits(input->type.type, &bitPix, &bZero, &dataType) ) {227 if (! p_psFitsTypeToCfitsio(input->type.type, &bitPix, &bZero, &dataType) ) { 317 228 return false; 318 229 } … … 440 351 double bZero; 441 352 int dataType; 442 if (! convertPsTypeToFits(input->type.type, &bitPix, &bZero, &dataType) ) {353 if (! p_psFitsTypeToCfitsio(input->type.type, &bitPix, &bZero, &dataType) ) { 443 354 return false; 444 355 } -
trunk/psLib/src/fits/psFitsTable.c
r7538 r7846 7 7 * @author Robert DeSonia, MHPCC 8 8 * 9 * @version $Revision: 1.1 3$ $Name: not supported by cvs2svn $10 * @date $Date: 2006-0 6-13 22:05:23$9 * @version $Revision: 1.14 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2006-07-08 03:06:40 $ 11 11 * 12 12 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 26 26 #include "psFitsTable.h" 27 27 #include "psFitsHeader.h" 28 #include "psAbort.h" 29 #include "psAssert.h" 28 30 29 31 #define MAX_STRING_LENGTH 256 // maximum length string for FITS routines 30 32 31 static psElemType convertFitsToPsType(int datatype) 32 { 33 switch (datatype) { 34 case TBYTE: 35 return PS_TYPE_U8; 36 case TSBYTE: 37 return PS_TYPE_S8; 38 case TSHORT: 39 return PS_TYPE_S16; 40 case TUSHORT: 41 return PS_TYPE_U16; 42 case TLONG: 43 if (sizeof(long) == 8) { 44 return PS_TYPE_S64; 45 } 46 // no break 47 case TINT: 48 return PS_TYPE_S32; 49 case TULONG: 50 if (sizeof(unsigned long) == 8) { 51 return PS_TYPE_U64; 52 } 53 // no break 54 case TUINT: 55 return PS_TYPE_U32; 56 case TLONGLONG: 57 return PS_TYPE_S64; 58 case TFLOAT: 59 return PS_TYPE_F32; 60 case TDOUBLE: 61 return PS_TYPE_F64; 62 case TCOMPLEX: 63 return PS_TYPE_C32; 64 case TDBLCOMPLEX: 65 return PS_TYPE_C64; 66 case TLOGICAL: 67 return PS_TYPE_BOOL; 33 34 psMetadata* psFitsReadTableRow(const psFits* fits, 35 int row) 36 { 37 long numRows; 38 int numCols; 39 int status = 0; 40 41 if (fits == NULL) { 42 psError(PS_ERR_BAD_PARAMETER_NULL, true, 43 PS_ERRORTEXT_psFits_NULL); 44 return NULL; 45 } 46 47 // check to see if we even are positioned on a table HDU 48 int hdutype; 49 fits_get_hdu_type(fits->fd,&hdutype, &status); 50 if ( status != 0) { 51 char fitsErr[MAX_STRING_LENGTH]; 52 (void)fits_get_errstatus(status, fitsErr); 53 psError(PS_ERR_IO, true, 54 PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED, 55 fitsErr); 56 return NULL; 57 } 58 if (hdutype != ASCII_TBL && hdutype != BINARY_TBL) { 59 psError(PS_ERR_IO, true, 60 PS_ERRORTEXT_psFits_NOT_TABLE_TYPE); 61 return NULL; 62 } 63 64 // get the size of the FITS table 65 fits_get_num_rows(fits->fd, &numRows, &status); 66 fits_get_num_cols(fits->fd, &numCols, &status); 67 if ( status != 0) { 68 char fitsErr[MAX_STRING_LENGTH]; 69 (void)fits_get_errstatus(status, fitsErr); 70 psError(PS_ERR_IO, true, 71 PS_ERRORTEXT_psFits_GET_TABLE_SIZE_FAILED, 72 fitsErr); 73 return NULL; 74 } 75 76 psTrace(".psFits.psFitsReadTableRow",5,"Table size is %ix%i\n",numCols, numRows); 77 // the row parameter in the proper range? 78 if (row < 0 || row >= numRows) { 79 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 80 PS_ERRORTEXT_psFits_ROW_INVALID, 81 row,numRows); 82 return NULL; 83 } 84 85 psMetadata* data = psMetadataAlloc(); 86 87 int typecode; 88 long repeat; 89 long width; 90 char name[60]; 91 for (int col = 1; col <= numCols; col++) { 92 // get the column name 93 if (hdutype == BINARY_TBL) { 94 fits_get_bcolparms(fits->fd, col, name, 95 NULL, NULL, NULL, NULL, NULL, NULL, NULL, &status); 96 } else { 97 fits_get_acolparms(fits->fd, col, name, 98 NULL, NULL, NULL, NULL, NULL, NULL, NULL, &status); 99 } 100 // get the column type 101 fits_get_coltype(fits->fd, col, &typecode, &repeat, &width, &status); 102 103 if (status == 0) { 104 105 #define READ_TABLE_ROW_CASE(FITSTYPE, NATIVETYPE, TYPE, VECTYPE) \ 106 case FITSTYPE: { \ 107 if (repeat == 1) { \ 108 NATIVETYPE value; \ 109 int anynul = 0; \ 110 fits_read_col(fits->fd, FITSTYPE, col,row+1, \ 111 1, 1, NULL, &value, &anynul, &status); \ 112 psTrace(".psFits.psFitsReadTableRow",5,"Column #%i, '%s', is type %i, repeat %i, Value = %g\n", \ 113 col, name, typecode, repeat, (double)value); \ 114 psMetadataAdd(data,PS_LIST_TAIL, name, \ 115 PS_DATA_##TYPE, \ 116 "", (ps##TYPE)value); \ 117 } else { \ 118 NATIVETYPE* value = psAlloc(sizeof(NATIVETYPE)*repeat); \ 119 psVector* vec = psVectorAlloc(repeat,PS_TYPE_##VECTYPE); \ 120 int anynul = 0; \ 121 fits_read_col(fits->fd, FITSTYPE, col,row+1, \ 122 1, repeat, NULL, value, &anynul, &status); \ 123 for (int lcv = 0; lcv < repeat; lcv++) { \ 124 vec->data.VECTYPE[lcv] = value[lcv]; \ 125 } \ 126 psMetadataAdd(data,PS_LIST_TAIL, name, PS_DATA_VECTOR, "", vec); \ 127 psFree(value); \ 128 psFree(vec); \ 129 } \ 130 break; \ 131 } 132 133 switch (typecode) { 134 case TBYTE: 135 case TSHORT: 136 case TLONGLONG: 137 READ_TABLE_ROW_CASE(TLONG, long, S32,S32) 138 READ_TABLE_ROW_CASE(TFLOAT, float, F32,F32) 139 READ_TABLE_ROW_CASE(TDOUBLE, double, F64,F64) 140 READ_TABLE_ROW_CASE(TLOGICAL, bool, BOOL,S8); 141 case TSTRING: { 142 char* value = psAlloc(repeat+1); 143 int anynul = 0; 144 fits_read_col(fits->fd, TSTRING, col,row+1, 145 1, 1, NULL, &value, &anynul, &status); 146 psTrace(".psFits.psFitsReadTableRow",5,"Column #%i, '%s', is type %i, repeat %i, value = %s\n", 147 col, name, typecode, repeat, value); 148 if (anynul == 0) { 149 psMetadataAdd(data,PS_LIST_TAIL, name, 150 PS_DATA_STRING, 151 "", value); 152 } 153 psFree(value); 154 break; 155 } 156 default: 157 psWarning("Data type (%d) not supportted for column %d", 158 typecode, col); 159 160 psTrace("psFits.psFitsReadTableRow", 2, 161 "Column %d or row %d was of a non primitive type, %d", 162 col, row, typecode); 163 } 164 } 165 166 if ( status != 0) { 167 char fitsErr[MAX_STRING_LENGTH]; 168 (void)fits_get_errstatus(status, fitsErr); 169 psError(PS_ERR_IO, true, 170 PS_ERRORTEXT_psFits_GET_TABLE_ELEMENT, 171 col,row,fitsErr); 172 psFree(data); 173 return NULL; 174 } 175 176 } 177 178 return data; 179 } 180 181 psArray* psFitsReadTableColumn(const psFits* fits, 182 const char* colname) 183 { 184 int colnum = 0; 185 int status = 0; 186 187 if (fits == NULL) { 188 psError(PS_ERR_BAD_PARAMETER_NULL, true, 189 PS_ERRORTEXT_psFits_NULL); 190 return NULL; 191 } 192 193 // check to see if we even are positioned on a table HDU 194 int hdutype; 195 if ( fits_get_hdu_type(fits->fd,&hdutype, &status) != 0) { 196 char fitsErr[MAX_STRING_LENGTH]; 197 (void)fits_get_errstatus(status, fitsErr); 198 psError(PS_ERR_IO, true, 199 PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED, 200 fitsErr); 201 return NULL; 202 } 203 if (hdutype != ASCII_TBL && hdutype != BINARY_TBL) { 204 psError(PS_ERR_IO, true, 205 PS_ERRORTEXT_psFits_NOT_TABLE_TYPE); 206 return NULL; 207 } 208 209 // find the column by name 210 if ( fits_get_colnum(fits->fd, CASESEN, (char*)colname, &colnum, &status) != 0) { 211 char fitsErr[MAX_STRING_LENGTH]; 212 (void)fits_get_errstatus(status, fitsErr); 213 psError(PS_ERR_IO, true, 214 PS_ERRORTEXT_psFits_FIND_COLUMN, 215 colname, fitsErr); 216 return NULL; 217 } 218 219 // get the number of rows 220 long numRows = 0; 221 fits_get_num_rows(fits->fd, &numRows, &status); 222 223 // get the column length. 224 int width; 225 if ( fits_get_col_display_width(fits->fd, colnum, &width, &status) != 0) { 226 char fitsErr[MAX_STRING_LENGTH]; 227 (void)fits_get_errstatus(status, fitsErr); 228 psError(PS_ERR_IO, true, 229 PS_ERRORTEXT_psFits_GET_COLTYPE, 230 fitsErr); 231 return NULL; 232 } 233 234 // allocate the buffers 235 psArray* result = psArrayAlloc(numRows); 236 for (int row = 0; row < numRows; row++) { 237 result->data[row] = psAlloc((width+1)*sizeof(char)); 238 } 239 result->n = numRows; 240 241 fits_read_col_str(fits->fd, 242 colnum, 243 1, // firstrow 244 1, // firestelem 245 numRows, 246 "", // nulstr 247 (char**)result->data, 248 NULL, 249 &status); 250 251 if ( status != 0) { 252 char fitsErr[MAX_STRING_LENGTH]; 253 (void)fits_get_errstatus(status, fitsErr); 254 psError(PS_ERR_IO, true, 255 PS_ERRORTEXT_psFits_TABLE_READ_COL, 256 fitsErr); 257 return NULL; 258 } 259 260 return result; 261 } 262 263 psVector* psFitsReadTableColumnNum(const psFits* fits, 264 const char* colname) 265 { 266 int status = 0; 267 int colnum = 0; 268 269 if (fits == NULL) { 270 psError(PS_ERR_BAD_PARAMETER_NULL, true, 271 PS_ERRORTEXT_psFits_NULL); 272 return NULL; 273 } 274 275 // check to see if we even are positioned on a table HDU 276 int hdutype; 277 if ( fits_get_hdu_type(fits->fd,&hdutype, &status) != 0) { 278 char fitsErr[MAX_STRING_LENGTH]; 279 (void)fits_get_errstatus(status, fitsErr); 280 psError(PS_ERR_IO, true, 281 PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED, 282 fitsErr); 283 return NULL; 284 } 285 if (hdutype != ASCII_TBL && hdutype != BINARY_TBL) { 286 psError(PS_ERR_IO, true, 287 PS_ERRORTEXT_psFits_NOT_TABLE_TYPE); 288 return NULL; 289 } 290 291 // find the column by name 292 if ( fits_get_colnum(fits->fd, CASESEN, (char*)colname, &colnum, &status) != 0) { 293 char fitsErr[MAX_STRING_LENGTH]; 294 (void)fits_get_errstatus(status, fitsErr); 295 psError(PS_ERR_IO, true, 296 PS_ERRORTEXT_psFits_FIND_COLUMN, 297 colname, fitsErr); 298 return NULL; 299 } 300 301 // get the number of rows 302 long numRows = 0; 303 fits_get_num_rows(fits->fd, 304 &numRows, 305 &status); 306 307 // get the column datatype. 308 int typecode; 309 long repeat; 310 long width; 311 if ( fits_get_eqcoltype(fits->fd, colnum, &typecode, &repeat, &width, &status) != 0) { 312 char fitsErr[MAX_STRING_LENGTH]; 313 (void)fits_get_errstatus(status, fitsErr); 314 psError(PS_ERR_IO, true, 315 PS_ERRORTEXT_psFits_GET_COLTYPE, 316 fitsErr); 317 return NULL; 318 } 319 320 psVector* result = psVectorAlloc(numRows, p_psFitsTypeFromCfitsio(typecode)); 321 result->n = numRows; 322 323 fits_read_col(fits->fd, 324 typecode, 325 colnum, 326 1 /* firstrow */, 327 1 /* firstelem */, 328 numRows, 329 NULL, 330 (psPtr)(result->data.U8), 331 NULL, 332 &status); 333 334 if ( status != 0) { 335 char fitsErr[MAX_STRING_LENGTH]; 336 (void)fits_get_errstatus(status, fitsErr); 337 psError(PS_ERR_IO, true, 338 PS_ERRORTEXT_psFits_TABLE_READ_COL, 339 fitsErr); 340 return NULL; 341 } 342 343 return result; 344 } 345 346 347 psArray* psFitsReadTable(const psFits* fits) 348 { 349 int status = 0; 350 351 if (fits == NULL) { 352 psError(PS_ERR_BAD_PARAMETER_NULL, true, 353 PS_ERRORTEXT_psFits_NULL); 354 return NULL; 355 } 356 357 // check to see if we even are positioned on a table HDU 358 int hdutype; 359 if ( fits_get_hdu_type(fits->fd,&hdutype, &status) != 0) { 360 char fitsErr[MAX_STRING_LENGTH]; 361 (void)fits_get_errstatus(status, fitsErr); 362 psError(PS_ERR_IO, true, 363 PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED, 364 fitsErr); 365 return NULL; 366 } 367 if (hdutype != ASCII_TBL && hdutype != BINARY_TBL) { 368 psError(PS_ERR_IO, true, 369 PS_ERRORTEXT_psFits_NOT_TABLE_TYPE); 370 return NULL; 371 } 372 373 // get the size of the FITS table 374 long numRows = 0; 375 fits_get_num_rows(fits->fd, &numRows, &status); 376 if ( status != 0) { 377 char fitsErr[MAX_STRING_LENGTH]; 378 (void)fits_get_errstatus(status, fitsErr); 379 psError(PS_ERR_IO, true, 380 PS_ERRORTEXT_psFits_GET_TABLE_SIZE_FAILED, 381 fitsErr); 382 return NULL; 383 } 384 385 386 psArray* table = psArrayAlloc(numRows); 387 388 for (int row = 0; row < numRows; row++) { 389 psTrace(".psFits.psFitsReadTable",5,"Reading row %i of %i\n",row, numRows); 390 table->data[row] = psFitsReadTableRow(fits,row); 391 table->n++; 392 } 393 394 return table; 395 } 396 397 bool psFitsWriteTable(psFits* fits, 398 const psMetadata* header, 399 const psArray* table, 400 const char *extname) 401 { 402 psFitsMoveLast(fits); 403 return psFitsInsertTable(fits, header, table, extname, true); 404 } 405 406 407 // Return the size of the column 408 static inline size_t columnSize(const psMetadataItem *item // Item for which to get the size 409 ) 410 { 411 if (PS_DATA_IS_PRIMITIVE(item->type)) { 412 return 1; 413 } 414 switch (item->type) { 415 case PS_DATA_STRING: 416 return strlen(item->data.V); 417 case PS_DATA_VECTOR: { 418 psVector *vector = item->data.V; 419 return vector->n; 420 } 68 421 default: 69 psError(PS_ERR_IO, true, 70 "Unknown FITS datatype, %d.", 71 datatype); 72 return 0; 73 } 74 } 75 76 static bool convertPsTypeToFits(int type, int* bitPix, double* bZero, int* dataType) 77 { 78 79 int bitpix; 80 int datatype; 81 double bzero = 0.0; 82 83 switch (type) { 84 85 case PS_TYPE_U8: 86 bitpix = BYTE_IMG; 87 datatype = TBYTE; 88 break; 89 90 case PS_TYPE_S8: 91 bitpix = BYTE_IMG; 92 bzero = INT8_MIN; 93 datatype = TSBYTE; 94 break; 95 96 case PS_TYPE_U16: 97 bitpix = SHORT_IMG; 98 bzero = -1.0 * INT16_MIN; 99 datatype = TUSHORT; 100 break; 101 102 case PS_TYPE_S16: 103 bitpix = SHORT_IMG; 104 datatype = TSHORT; 105 break; 106 107 case PS_TYPE_U32: 108 bitpix = LONG_IMG; 109 bzero = -1.0 * INT32_MIN; 110 datatype = TUINT; 111 break; 112 113 case PS_TYPE_S32: 114 bitpix = LONG_IMG; 115 datatype = TINT; 116 break; 117 118 case PS_TYPE_F32: 119 bitpix = FLOAT_IMG; 120 datatype = TFLOAT; 121 break; 122 123 case PS_TYPE_F64: 124 bitpix = DOUBLE_IMG; 125 datatype = TDOUBLE; 126 break; 127 128 case PS_DATA_STRING: 129 bitpix = BYTE_IMG; 130 datatype = TSTRING; 131 break; 132 133 case PS_DATA_BOOL: 134 bitpix = BYTE_IMG; 135 datatype = TLOGICAL; 136 break; 137 138 default: { 139 char* typeStr; 140 PS_TYPE_NAME(typeStr,type); 141 psError(PS_ERR_BAD_PARAMETER_TYPE, true, 142 PS_ERRORTEXT_psFits_TYPE_UNSUPPORTED, 143 typeStr); 144 return false; 145 } 146 } 147 148 // pass the requested parameters (NULL parameters are not set, of course). 149 if (bitPix != NULL) { 150 *bitPix = bitpix; 151 } 152 153 if (dataType != NULL) { 154 *dataType = datatype; 155 } 156 157 if (bZero != NULL) { 158 *bZero = bzero; 159 } 160 161 return true; 162 } 163 164 static char getTForm(int type) 422 psAbort(__func__, "Shouldn't ever get here."); 423 } 424 return 0; 425 } 426 427 // Get the TFORM character, given a PS type 428 static inline const char getTForm(psDataType type) 165 429 { 166 430 switch (type) { … … 196 460 } 197 461 198 static bool getMetadataTForm(psMetadataItem* item, char** fitsType, int repeat) 199 { 200 if (item == NULL) { 201 return false; 202 } 203 204 *fitsType = NULL; 205 char tform = getTForm(item->type); 206 207 switch (item->type) { 208 case PS_TYPE_U8: 209 case PS_TYPE_S8: 210 case PS_TYPE_S16: 211 case PS_TYPE_S32: 212 case PS_TYPE_U64: 213 case PS_TYPE_S64: 214 case PS_TYPE_U16: 215 case PS_TYPE_U32: 216 case PS_TYPE_F32: 217 case PS_TYPE_F64: 218 case PS_TYPE_C32: 219 case PS_TYPE_C64: 220 case PS_TYPE_BOOL: 221 psStringAppend(fitsType, "%d%c",repeat,tform); 222 break; 223 224 case PS_DATA_STRING: 225 psStringAppend(fitsType,"%dA", 226 strlen(item->data.V)*repeat); 227 break; 228 229 case PS_DATA_VECTOR: { 230 psVector* vec = item->data.V; 231 tform = getTForm(vec->type.type); 232 psStringAppend(fitsType,"%d%c",repeat*vec->n,tform); 233 } 234 break; 235 236 default: 237 return false; 238 } 239 240 return true; 241 } 242 243 psMetadata* psFitsReadTableRow(const psFits* fits, 244 int row) 245 { 246 long numRows; 247 int numCols; 248 int status = 0; 249 250 if (fits == NULL) { 251 psError(PS_ERR_BAD_PARAMETER_NULL, true, 252 PS_ERRORTEXT_psFits_NULL); 253 return NULL; 254 } 255 256 // check to see if we even are positioned on a table HDU 257 int hdutype; 258 fits_get_hdu_type(fits->fd,&hdutype, &status); 259 if ( status != 0) { 260 char fitsErr[MAX_STRING_LENGTH]; 261 (void)fits_get_errstatus(status, fitsErr); 262 psError(PS_ERR_IO, true, 263 PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED, 264 fitsErr); 265 return NULL; 266 } 267 if (hdutype != ASCII_TBL && hdutype != BINARY_TBL) { 268 psError(PS_ERR_IO, true, 269 PS_ERRORTEXT_psFits_NOT_TABLE_TYPE); 270 return NULL; 271 } 272 273 // get the size of the FITS table 274 fits_get_num_rows(fits->fd, &numRows, &status); 275 fits_get_num_cols(fits->fd, &numCols, &status); 276 if ( status != 0) { 277 char fitsErr[MAX_STRING_LENGTH]; 278 (void)fits_get_errstatus(status, fitsErr); 279 psError(PS_ERR_IO, true, 280 PS_ERRORTEXT_psFits_GET_TABLE_SIZE_FAILED, 281 fitsErr); 282 return NULL; 283 } 284 285 psTrace(".psFits.psFitsReadTableRow",5,"Table size is %ix%i\n",numCols, numRows); 286 // the row parameter in the proper range? 287 if (row < 0 || row >= numRows) { 288 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 289 PS_ERRORTEXT_psFits_ROW_INVALID, 290 row,numRows); 291 return NULL; 292 } 293 294 psMetadata* data = psMetadataAlloc(); 295 296 int typecode; 297 long repeat; 298 long width; 299 char name[60]; 300 for (int col = 1; col <= numCols; col++) { 301 // get the column name 302 if (hdutype == BINARY_TBL) { 303 fits_get_bcolparms(fits->fd, col, name, 304 NULL, NULL, NULL, NULL, NULL, NULL, NULL, &status); 305 } else { 306 fits_get_acolparms(fits->fd, col, name, 307 NULL, NULL, NULL, NULL, NULL, NULL, NULL, &status); 308 } 309 // get the column type 310 fits_get_coltype(fits->fd, col, &typecode, &repeat, &width, &status); 311 312 if (status == 0) { 313 314 #define READ_TABLE_ROW_CASE(FITSTYPE, NATIVETYPE, TYPE, VECTYPE) \ 315 case FITSTYPE: { \ 316 if (repeat == 1) { \ 317 NATIVETYPE value; \ 318 int anynul = 0; \ 319 fits_read_col(fits->fd, FITSTYPE, col,row+1, \ 320 1, 1, NULL, &value, &anynul, &status); \ 321 psTrace(".psFits.psFitsReadTableRow",5,"Column #%i, '%s', is type %i, repeat %i, Value = %g\n", \ 322 col, name, typecode, repeat, (double)value); \ 323 psMetadataAdd(data,PS_LIST_TAIL, name, \ 324 PS_DATA_##TYPE, \ 325 "", (ps##TYPE)value); \ 326 } else { \ 327 NATIVETYPE* value = psAlloc(sizeof(NATIVETYPE)*repeat); \ 328 psVector* vec = psVectorAlloc(repeat,PS_TYPE_##VECTYPE); \ 329 int anynul = 0; \ 330 fits_read_col(fits->fd, FITSTYPE, col,row+1, \ 331 1, repeat, NULL, value, &anynul, &status); \ 332 for (int lcv = 0; lcv < repeat; lcv++) { \ 333 vec->data.VECTYPE[lcv] = value[lcv]; \ 334 } \ 335 psMetadataAdd(data,PS_LIST_TAIL, name, PS_DATA_VECTOR, "", vec); \ 336 psFree(value); \ 337 psFree(vec); \ 338 } \ 339 break; \ 340 } 341 342 switch (typecode) { 343 case TBYTE: 344 case TSHORT: 345 case TLONGLONG: 346 READ_TABLE_ROW_CASE(TLONG, long, S32,S32) 347 READ_TABLE_ROW_CASE(TFLOAT, float, F32,F32) 348 READ_TABLE_ROW_CASE(TDOUBLE, double, F64,F64) 349 READ_TABLE_ROW_CASE(TLOGICAL, bool, BOOL,S8); 350 case TSTRING: { 351 char* value = psAlloc(repeat+1); 352 int anynul = 0; 353 fits_read_col(fits->fd, TSTRING, col,row+1, 354 1, 1, NULL, &value, &anynul, &status); 355 psTrace(".psFits.psFitsReadTableRow",5,"Column #%i, '%s', is type %i, repeat %i, value = %s\n", 356 col, name, typecode, repeat, value); 357 if (anynul == 0) { 358 psMetadataAdd(data,PS_LIST_TAIL, name, 359 PS_DATA_STRING, 360 "", value); 361 } 362 psFree(value); 363 break; 364 } 365 default: 366 psWarning("Data type (%d) not supportted for column %d", 367 typecode, col); 368 369 psTrace("psFits.psFitsReadTableRow", 2, 370 "Column %d or row %d was of a non primitive type, %d", 371 col, row, typecode); 372 } 373 } 374 375 if ( 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_GET_TABLE_ELEMENT, 380 col,row,fitsErr); 381 psFree(data); 382 return NULL; 383 } 384 385 } 386 387 return data; 388 } 389 390 psArray* psFitsReadTableColumn(const psFits* fits, 391 const char* colname) 392 { 393 int colnum = 0; 394 int status = 0; 395 396 if (fits == NULL) { 397 psError(PS_ERR_BAD_PARAMETER_NULL, true, 398 PS_ERRORTEXT_psFits_NULL); 399 return NULL; 400 } 401 402 // check to see if we even are positioned on a table HDU 403 int hdutype; 404 if ( fits_get_hdu_type(fits->fd,&hdutype, &status) != 0) { 405 char fitsErr[MAX_STRING_LENGTH]; 406 (void)fits_get_errstatus(status, fitsErr); 407 psError(PS_ERR_IO, true, 408 PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED, 409 fitsErr); 410 return NULL; 411 } 412 if (hdutype != ASCII_TBL && hdutype != BINARY_TBL) { 413 psError(PS_ERR_IO, true, 414 PS_ERRORTEXT_psFits_NOT_TABLE_TYPE); 415 return NULL; 416 } 417 418 // find the column by name 419 if ( fits_get_colnum(fits->fd, CASESEN, (char*)colname, &colnum, &status) != 0) { 420 char fitsErr[MAX_STRING_LENGTH]; 421 (void)fits_get_errstatus(status, fitsErr); 422 psError(PS_ERR_IO, true, 423 PS_ERRORTEXT_psFits_FIND_COLUMN, 424 colname, fitsErr); 425 return NULL; 426 } 427 428 // get the number of rows 429 long numRows = 0; 430 fits_get_num_rows(fits->fd, &numRows, &status); 431 432 // get the column length. 433 int width; 434 if ( fits_get_col_display_width(fits->fd, colnum, &width, &status) != 0) { 435 char fitsErr[MAX_STRING_LENGTH]; 436 (void)fits_get_errstatus(status, fitsErr); 437 psError(PS_ERR_IO, true, 438 PS_ERRORTEXT_psFits_GET_COLTYPE, 439 fitsErr); 440 return NULL; 441 } 442 443 // allocate the buffers 444 psArray* result = psArrayAlloc(numRows); 445 for (int row = 0; row < numRows; row++) { 446 result->data[row] = psAlloc((width+1)*sizeof(char)); 447 } 448 result->n = numRows; 449 450 fits_read_col_str(fits->fd, 451 colnum, 452 1, // firstrow 453 1, // firestelem 454 numRows, 455 "", // nulstr 456 (char**)result->data, 457 NULL, 458 &status); 459 460 if ( status != 0) { 461 char fitsErr[MAX_STRING_LENGTH]; 462 (void)fits_get_errstatus(status, fitsErr); 463 psError(PS_ERR_IO, true, 464 PS_ERRORTEXT_psFits_TABLE_READ_COL, 465 fitsErr); 466 return NULL; 467 } 468 469 return result; 470 } 471 472 psVector* psFitsReadTableColumnNum(const psFits* fits, 473 const char* colname) 474 { 475 int status = 0; 476 int colnum = 0; 477 478 if (fits == NULL) { 479 psError(PS_ERR_BAD_PARAMETER_NULL, true, 480 PS_ERRORTEXT_psFits_NULL); 481 return NULL; 482 } 483 484 // check to see if we even are positioned on a table HDU 485 int hdutype; 486 if ( fits_get_hdu_type(fits->fd,&hdutype, &status) != 0) { 487 char fitsErr[MAX_STRING_LENGTH]; 488 (void)fits_get_errstatus(status, fitsErr); 489 psError(PS_ERR_IO, true, 490 PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED, 491 fitsErr); 492 return NULL; 493 } 494 if (hdutype != ASCII_TBL && hdutype != BINARY_TBL) { 495 psError(PS_ERR_IO, true, 496 PS_ERRORTEXT_psFits_NOT_TABLE_TYPE); 497 return NULL; 498 } 499 500 // find the column by name 501 if ( fits_get_colnum(fits->fd, CASESEN, (char*)colname, &colnum, &status) != 0) { 502 char fitsErr[MAX_STRING_LENGTH]; 503 (void)fits_get_errstatus(status, fitsErr); 504 psError(PS_ERR_IO, true, 505 PS_ERRORTEXT_psFits_FIND_COLUMN, 506 colname, fitsErr); 507 return NULL; 508 } 509 510 // get the number of rows 511 long numRows = 0; 512 fits_get_num_rows(fits->fd, 513 &numRows, 514 &status); 515 516 // get the column datatype. 517 int typecode; 518 long repeat; 519 long width; 520 if ( fits_get_eqcoltype(fits->fd, colnum, &typecode, &repeat, &width, &status) != 0) { 521 char fitsErr[MAX_STRING_LENGTH]; 522 (void)fits_get_errstatus(status, fitsErr); 523 psError(PS_ERR_IO, true, 524 PS_ERRORTEXT_psFits_GET_COLTYPE, 525 fitsErr); 526 return NULL; 527 } 528 529 psVector* result = psVectorAlloc(numRows, convertFitsToPsType(typecode)); 530 result->n = numRows; 531 532 fits_read_col(fits->fd, 533 typecode, 534 colnum, 535 1 /* firstrow */, 536 1 /* firstelem */, 537 numRows, 538 NULL, 539 (psPtr)(result->data.U8), 540 NULL, 541 &status); 542 543 if ( status != 0) { 544 char fitsErr[MAX_STRING_LENGTH]; 545 (void)fits_get_errstatus(status, fitsErr); 546 psError(PS_ERR_IO, true, 547 PS_ERRORTEXT_psFits_TABLE_READ_COL, 548 fitsErr); 549 return NULL; 550 } 551 552 return result; 553 } 554 555 556 psArray* psFitsReadTable(const psFits* fits) 557 { 558 int status = 0; 559 560 if (fits == NULL) { 561 psError(PS_ERR_BAD_PARAMETER_NULL, true, 562 PS_ERRORTEXT_psFits_NULL); 563 return NULL; 564 } 565 566 // check to see if we even are positioned on a table HDU 567 int hdutype; 568 if ( fits_get_hdu_type(fits->fd,&hdutype, &status) != 0) { 569 char fitsErr[MAX_STRING_LENGTH]; 570 (void)fits_get_errstatus(status, fitsErr); 571 psError(PS_ERR_IO, true, 572 PS_ERRORTEXT_psFits_GET_HDU_TYPE_FAILED, 573 fitsErr); 574 return NULL; 575 } 576 if (hdutype != ASCII_TBL && hdutype != BINARY_TBL) { 577 psError(PS_ERR_IO, true, 578 PS_ERRORTEXT_psFits_NOT_TABLE_TYPE); 579 return NULL; 580 } 581 582 // get the size of the FITS table 583 long numRows = 0; 584 fits_get_num_rows(fits->fd, &numRows, &status); 585 if ( status != 0) { 586 char fitsErr[MAX_STRING_LENGTH]; 587 (void)fits_get_errstatus(status, fitsErr); 588 psError(PS_ERR_IO, true, 589 PS_ERRORTEXT_psFits_GET_TABLE_SIZE_FAILED, 590 fitsErr); 591 return NULL; 592 } 593 594 595 psArray* table = psArrayAlloc(numRows); 596 597 for (int row = 0; row < numRows; row++) { 598 psTrace(".psFits.psFitsReadTable",5,"Reading row %i of %i\n",row, numRows); 599 table->data[row] = psFitsReadTableRow(fits,row); 600 table->n++; 601 } 602 603 return table; 604 } 605 606 bool psFitsWriteTable(psFits* fits, 607 const psMetadata* header, 608 const psArray* table, 609 const char *extname) 610 { 611 psFitsMoveLast(fits); 612 return psFitsInsertTable(fits, header, table, extname, true); 613 } 462 463 // Column specification 464 // Included here, because there's no need for the user to have access to it 465 typedef struct 466 { 467 psDataType type; // psLib type (e.g., PS_DATA_STRING or PS_TYPE_F32) 468 size_t size; // Size (number of repeats) 469 psElemType vectorType; // psLib type of vectors 470 } 471 colSpec; 472 614 473 615 474 bool psFitsInsertTable(psFits* fits, … … 621 480 int status = 0; 622 481 623 if (fits == NULL) { 624 psError(PS_ERR_BAD_PARAMETER_NULL, true, 625 PS_ERRORTEXT_psFits_NULL); 626 return false; 627 } 628 629 if (table == NULL) { 630 psError(PS_ERR_BAD_PARAMETER_NULL, true, 631 PS_ERRORTEXT_psFits_IMAGE_NULL); 632 return false; 633 } 634 635 int rows = table->n; 636 if (rows < 1) { 482 PS_ASSERT_PTR_NON_NULL(fits, false); 483 PS_ASSERT_ARRAY_NON_NULL(table, false); 484 485 long numRows = table->n; 486 if (numRows < 1) { 637 487 // no table data, what can I do? 638 488 psError(PS_ERR_BAD_PARAMETER_SIZE, true, … … 641 491 } 642 492 643 // find all the columns needed 644 psArray* columns = psArrayAlloc(((psMetadata*)table->data[0])->list->n); 645 columns->n=0; 646 647 // find the unique items in the array of metadata 'rows' 648 psMetadataItem* item; 649 for (int row=0; row < rows; row++) { 650 psMetadata* rowMeta = table->data[row]; 651 if (rowMeta != NULL) { 652 psListIterator* iter = psListIteratorAlloc(rowMeta->list, 653 PS_LIST_HEAD,true); 654 while ( (item=psListGetAndIncrement(iter)) != NULL) { 655 if (PS_DATA_IS_PRIMITIVE(item->type) || 656 item->type == PS_DATA_STRING || 657 item->type == PS_DATA_VECTOR) { 658 bool found = false; 659 psMetadataItem* fItem = NULL; 660 int n; 661 for (n=0; n < columns->n && ! found; n++) { 662 fItem = (psMetadataItem*)(columns->data[n]); 663 if (strcmp(item->name, fItem->name) == 0) { 664 found = true; 665 break; 666 } 493 // Find the unique items in the array of metadata 'rows', and their sizes 494 psMetadata *colSpecs = psMetadataAlloc(); // Column specifications 495 size_t rowSize = 0; // Size (in bytes) of each row 496 for (long i = 0; i < numRows; i++) { 497 psMetadata* row = table->data[i]; 498 if (!row) { 499 continue; 500 } 501 psMetadataIterator *rowIter = psMetadataIteratorAlloc(row, PS_LIST_HEAD, NULL); // Iterator 502 psMetadataItem *colItem; // Column item, from iteration 503 while ((colItem = psMetadataGetAndIncrement(rowIter))) { 504 if (!(PS_DATA_IS_PRIMITIVE(colItem->type) || colItem->type == PS_DATA_STRING || 505 colItem->type == PS_DATA_VECTOR)) { 506 // unsupported type -- treating as an error 507 psError(PS_ERR_BAD_PARAMETER_TYPE, true, 508 "Unsupported data type (%d) for Metadata Item '%s' in row %d.", 509 colItem->type, colItem->name, row); 510 psFree(rowIter); 511 psFree(colSpecs); 512 return false; 513 } 514 515 size_t size = columnSize(colItem); // Size for this column 516 517 // Check to see if we know about this one; or update the size if required 518 psMetadataItem *colSpecItem = psMetadataLookup(colSpecs, colItem->name); 519 if (!colSpecItem) { 520 // A new one! 521 colSpec *spec = psAlloc(sizeof(colSpec)); // Specification for this column 522 spec->type = colItem->type; 523 spec->size = size; 524 if (colItem->type == PS_DATA_VECTOR) { 525 psVector *vector = colItem->data.V; // The vector 526 spec->vectorType = vector->type.type; 527 } 528 psMetadataAddPtr(colSpecs, PS_LIST_TAIL, colItem->name, PS_DATA_UNKNOWN, "", spec); 529 psFree(spec); // Drop reference 530 rowSize += PSELEMTYPE_SIZEOF(spec->type); 531 } else { 532 colSpec *spec = colSpecItem->data.V; // The specification 533 if (size > spec->size) { 534 spec->size = size; 535 } 536 if (colItem->type != spec->type) { 537 psLogMsg(__func__, PS_LOG_WARN, "Differing type found for column %s: %x vs %x --- " 538 "using the first found.\n", colSpecItem->name, colItem->type, spec->type); 539 } 540 if (colItem->type == PS_DATA_VECTOR) { 541 psVector *vector = colItem->data.V; // The vector 542 if (vector->type.type != spec->vectorType) { 543 psLogMsg(__func__, PS_LOG_WARN, "Differing vector type found for column %s: %x vs %x" 544 "--- using the first found.\n", colSpecItem->name, vector->type.type, 545 spec->vectorType); 667 546 } 668 if (! found) {669 psArrayAdd(columns, columns->nalloc, item);670 } else if (item->type == PS_DATA_STRING &&671 strlen(fItem->data.V) < strlen(item->data.V)) {672 // got to keep the longest string value as to know what size to create the table column673 psMemDecrRefCounter(fItem);674 columns->data[n] = psMemIncrRefCounter(item);675 columns->n++;676 677 } else if (item->type == PS_DATA_VECTOR &&678 ((psVector*)(fItem->data.V))->n < ((psVector*)(item->data.V))->n) {679 psMemDecrRefCounter(fItem);680 columns->data[n] = psMemIncrRefCounter(item);681 columns->n++;682 }683 } else {684 // unsupported type -- treating as an error685 psError(PS_ERR_BAD_PARAMETER_TYPE, true,686 "Unsupported data type (%d) for Metadata Item '%s' in row %d.",687 item->type, item->name, row);688 psFree(iter);689 psFree(columns);690 return false;691 547 } 692 548 } 693 psFree(iter); 694 } 695 } 696 697 if (columns->n == 0) { // no table columns found 549 } 550 psFree(rowIter); 551 } 552 553 long numColumns = colSpecs->list->n;// Number of columns 554 if (numColumns == 0) { 555 // No table columns found 698 556 psError(PS_ERR_BAD_PARAMETER_SIZE, true, 699 557 "Did not find any column data to write to a table."); 700 psFree(col umns);558 psFree(colSpecs); 701 559 return false; 702 560 } 703 561 704 //create list of column names and types. 705 if (columns->n > 0) { // If we're going decrement columns->n (why?), at least free the memory 706 psFree(columns->data[columns->n - 1]); 707 } 708 columns->n--; 709 psArray* columnNames = psArrayAlloc(columns->n); 710 psArray* columnTypes = psArrayAlloc(columns->n); 711 for (int n=0; n < columns->n; n++) { 712 columnNames->data[n] = psMemIncrRefCounter(((psMetadataItem*)columns->data[n])->name); 713 columnNames->n++; 714 columnTypes->n++; 715 if ( ! getMetadataTForm((psMetadataItem*)columns->data[n], 716 (char**)&(columnTypes->data[n]),1) ) { 717 psError(PS_ERR_UNKNOWN, true, 718 "Failed to determine the FITS data type of '%s' (type=%d).", 719 columnNames->data[n], 720 ((psMetadataItem*)columns->data[n])->type); 721 psFree(columns); 722 psFree(columnNames); 723 psFree(columnTypes); 724 return false; 725 } 562 // Create array of column names and types. 563 psArray *columnNames = psArrayAlloc(numColumns); // Array of column names, for cfitsio 564 psArray *columnTypes = psArrayAlloc(numColumns); // Array of column types, for cfitsio 565 columnNames->n = numColumns; 566 columnTypes->n = numColumns; 567 psMetadataIterator *colSpecsIter = psMetadataIteratorAlloc(colSpecs, PS_LIST_HEAD, NULL); // Iterator 568 psMetadataItem *colSpecItem; // Column specification item, from iteration 569 for (long i = 0; (colSpecItem = psMetadataGetAndIncrement(colSpecsIter)); i++) { 570 colSpec *spec = colSpecItem->data.V; // The specification 571 columnNames->data[i] = psMemIncrRefCounter(colSpecItem->name); 572 psString colType = NULL; // The column type 573 psStringAppend(&colType, "%d%c", spec->size, getTForm(spec->type)); 574 columnTypes->data[i] = colType; 726 575 } 727 576 728 577 // Create the table HDU 729 int hdus = psFitsGetSize(fits);// Number of HDUs in file730 if ( hdus == 0) {578 int numHDUs = psFitsGetSize(fits); // Number of HDUs in file 579 if (numHDUs == 0) { 731 580 // We're creating the first extension 732 581 fits_create_tbl(fits->fd, 733 582 BINARY_TBL, 734 583 table->n, // number of rows in table 735 columns->n, // number of columns in table584 numColumns, // number of columns in table 736 585 (char**)columnNames->data, // names of the columns 737 586 (char**)columnTypes->data, // format of the columns … … 753 602 fits_insert_btbl(fits->fd, 754 603 table->n, // number of rows in table 755 columns->n, // number of columns in table604 numColumns, // number of columns in table 756 605 (char**)columnNames->data, // names of the columns 757 606 (char**)columnTypes->data, // format of the columns 758 607 NULL, // physical unit of columns 759 608 (char*)extname, // extension name; casting away const because cfitsio is horrible 760 0, 761 &status); 609 0, &status); 762 610 } 763 611 psFree(columnNames); … … 770 618 } 771 619 772 // fill in the table elements with data 773 for (int n = 0; n < columns->n; n++) { 774 int row; 775 item = columns->data[n]; 776 if (PS_DATA_IS_PRIMITIVE(item->type) ) { 777 psVector* col = psVectorAlloc(table->n, item->type); 778 int dataSize = PSELEMTYPE_SIZEOF(item->type); 779 int dataType; 780 convertPsTypeToFits(item->type, NULL,NULL,&dataType); 781 for (row = 0; row < table->n; row++) { 782 psMetadataItem* dataItem = psMetadataLookup( 783 table->data[row], 784 item->name); 785 memcpy(&col->data.U8[row*dataSize],&dataItem->data,dataSize); 786 } 620 621 // cfitsio requires that we write the data by columns --- urgh! 622 psMetadataIteratorSet(colSpecsIter, PS_LIST_HEAD); 623 for (long colNum = 1; (colSpecItem = psMetadataGetAndIncrement(colSpecsIter)); colNum++) { 624 // Note: colNum is unit-indexed, because it's for cfitsio 625 colSpec *spec = colSpecItem->data.V; // The specification 626 if (PS_DATA_IS_PRIMITIVE(spec->type)) { 627 size_t dataSize = PSELEMTYPE_SIZEOF(spec->type); // Size (in bytes) of this type 628 psVector *columnData = psVectorAlloc(table->n, spec->type); // The raw row data, to be written 629 psVectorInit(columnData, 0); 630 for (long i = 0; i < table->n; i++) { 631 psMetadata *row = table->data[i]; // The row of interest 632 psMetadataItem *dataItem = psMetadataLookup(row, colSpecItem->name); // The value of interest 633 memcpy(&columnData->data.U8[i * dataSize], &dataItem->data, dataSize); 634 } 635 636 int fitsDataType; // Data type for cfitsio 637 p_psFitsTypeToCfitsio(spec->type, NULL, NULL, &fitsDataType); 787 638 fits_write_col(fits->fd, 788 dataType,789 n+1, // column number790 1, // first row791 1, // first elem792 table->n, // n elements793 col ->data.U8,639 fitsDataType, 640 colNum, // column number 641 1, // first row 642 1, // first element 643 table->n, // number of rows 644 columnData->data.U8, // the data 794 645 &status); 795 psFree(col); 796 } else if (item->type == PS_DATA_STRING) { 797 psArray* colArray = psArrayAlloc(table->n); 798 for (row = 0; row < table->n; row++) { 799 colArray->data[row] = psStringCopy(psMetadataLookupStr(NULL, 800 table->data[row], 801 item->name)); 802 colArray->n++; 803 } 804 fits_write_col_str(fits->fd, 805 n+1, 806 1, 807 1, 808 table->n, 809 (char**)colArray->data, 646 psFree(columnData); 647 continue; 648 } 649 650 switch (spec->type) { 651 case PS_DATA_STRING: { 652 psArray *strings = psArrayAlloc(table->n); // Array of strings 653 strings->n = table->n; 654 for (long i = 0; i < table->n; i++) { 655 psMetadata *row = table->data[i]; // The row of interest 656 strings->data[i] = psMemIncrRefCounter(psMetadataLookupStr(NULL, row, colSpecItem->name)); 657 } 658 fits_write_col_str(fits->fd, colNum, 1, 1, table->n, (char**)strings->data, &status); 659 psFree(strings); 660 break; 661 } 662 case PS_DATA_VECTOR: { 663 psVector *columnData = psVectorAlloc(spec->size * table->n, spec->vectorType); 664 psVectorInit(columnData, 0); 665 size_t dataSize = PSELEMTYPE_SIZEOF(spec->vectorType); // Size of data, in bytes 666 for (long i = 0; i < table->n; i++) { 667 psMetadata *row = table->data[i]; // The row of interest 668 psMetadataItem* dataItem = psMetadataLookup(row, colSpecItem->name); 669 if (dataItem->type != PS_DATA_VECTOR) { 670 // Just in case --- get a zero instead of some weird result 671 continue; 672 } 673 psVector *vector = dataItem->data.V; 674 memcpy(&columnData->data.U8[i * dataSize], vector->data.U8, dataSize); 675 } 676 677 int fitsDataType; // Data type for cfitsio 678 p_psFitsTypeToCfitsio(spec->vectorType, NULL, NULL, &fitsDataType); 679 fits_write_col(fits->fd, fitsDataType, colNum, 1, 1, table->n * spec->size, columnData->data.U8, 810 680 &status); 811 psFree(colArray); 812 } else if (item->type == PS_DATA_VECTOR) { 813 psVector* vec = (psVector*)(item->data.V); 814 psVector* col = psVectorAlloc(table->n*vec->n, vec->type.type); 815 int dataSize = PSELEMTYPE_SIZEOF(vec->type.type)*vec->n; 816 int dataType; 817 convertPsTypeToFits(vec->type.type, NULL,NULL,&dataType); 818 for (row = 0; row < table->n; row++) { 819 psMetadataItem* dataItem = psMetadataLookup( 820 table->data[row], 821 item->name); 822 memcpy(&col->data.U8[row*dataSize], 823 ((psVector*)(dataItem->data.V))->data.U8, 824 dataSize); 825 } 826 fits_write_col(fits->fd, 827 dataType, 828 n+1, // column number 829 1, // firstrow 830 1, // firstelem 831 table->n*vec->n, // nelements 832 col->data.U8, 833 &status); 834 psFree(col); 835 } 836 if (status != 0) { 837 char fitsErr[MAX_STRING_LENGTH]; 838 (void)fits_get_errstatus(status, fitsErr); 839 psError(PS_ERR_IO, true, 840 PS_ERRORTEXT_psFits_WRITE_FAILED, 841 fitsErr); 842 psFree(columns); 843 return false; 844 } 845 846 } 847 848 psFree(columns); 681 psFree(columnData); 682 break; 683 } 684 default: 685 psAbort(__func__, "Should never get here.\n"); 686 } 687 } 688 689 psFree(colSpecsIter); 690 psFree(colSpecs); 849 691 850 692 return true; … … 899 741 // cooresponding column found in table 900 742 int dataType; 901 convertPsTypeToFits(item->type, NULL, NULL, &dataType);743 p_psFitsTypeToCfitsio(item->type, NULL, NULL, &dataType); 902 744 903 745 if (fits_write_col(fits->fd, dataType, colnum, row+1, 1, 1, &item->data,&status) != 0) {
Note:
See TracChangeset
for help on using the changeset viewer.
