Changeset 32228
- Timestamp:
- Aug 30, 2011, 3:47:39 PM (15 years ago)
- Location:
- trunk/psLib/src/fits
- Files:
-
- 3 edited
-
Makefile.am (modified) (2 diffs)
-
psFitsTableNew.c (modified) (14 diffs)
-
psFitsTableNew.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/fits/Makefile.am
r16185 r32228 9 9 psFitsImage.c \ 10 10 psFitsTable.c \ 11 psFitsTableNew.c \ 11 12 psFitsFloat.c \ 12 13 psFitsFloatFile.c \ … … 20 21 psFitsImage.h \ 21 22 psFitsTable.h \ 23 psFitsTableNew.h \ 22 24 psFitsFloat.h \ 23 25 psFitsFloatFile.h \ -
trunk/psLib/src/fits/psFitsTableNew.c
r32217 r32228 96 96 } 97 97 98 void breakhere() 99 { 100 } 101 102 void 103 freeTable(psFitsTable *table) { 104 for (int col = 0; col < table->numCols; col++) { 105 psFitsTableColumn *column = &table->columns[col]; 106 psFree(column->name); 107 // all of the members in the data union are pointers so just pick S32 108 psFree(column->data.S32); 109 } 110 psFree(table->columns); 111 psFree(table->index); 112 } 113 114 psFitsTable* psFitsTableAlloc(int numCols, int numRows) { 115 if (numCols <= 0) { 116 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 117 "Can't allocate a psFitsTable with %d columns.", numCols); 118 return NULL; 119 } 120 121 psFitsTable *table = psAlloc(sizeof(psFitsTable)); 122 table->index = psMetadataAlloc(); 123 table->numRows = numRows; 124 table->numCols = numCols; 125 table->columns = psAlloc(sizeof(psFitsTableColumn) * numCols); 126 memset(table->columns, sizeof(psFitsTableColumn) * numCols, 0); 127 psMemSetDeallocator(table, (psFreeFunc) freeTable); 128 129 return table; 130 } 98 131 99 132 psFitsTable* psFitsReadTableNew(const psFits* fits) … … 122 155 123 156 psTrace("psLib.fits",5,"Table size is %ix%li\n",numCols, numRows); 124 // the row parameter in the proper range? 125 #ifdef notdef 126 if (row < 0 || row >= numRows) { 127 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 128 _("Specified row, %d, is not valid for current table of %ld rows."), 129 row, numRows); 130 return NULL; 131 } 132 #endif 133 134 psFitsTable *table = psAlloc(sizeof(psFitsTable)); 135 table->index = psMetadataAlloc(); \ 136 table->numRows = numRows; 137 table->numCols = numCols; 138 table->columns = psAlloc(sizeof(psFitsTableColumn) * numCols); 139 // psMetadata* data = psMetadataAlloc(); 157 158 psFitsTable *table = psFitsTableAlloc(numCols, numRows); 140 159 141 160 int hdutype; // Type of HDU: need to distinguish ASCII and binary tables … … 151 170 for (int col = 1; col <= numCols; col++) { 152 171 // get the column name 172 double tscal; 173 double tzero; 153 174 if (hdutype == BINARY_TBL) { 154 175 fits_get_bcolparms(fits->fd, col, name, 155 NULL, NULL, NULL, NULL, NULL, NULL, NULL, &status);176 NULL, NULL, NULL, &tscal, &tzero, NULL, NULL, &status); 156 177 } else { 157 178 fits_get_acolparms(fits->fd, col, name, … … 170 191 column->data.TYPE = psAlloc(sizeof(ps##TYPE)*table->numRows); \ 171 192 if (repeat == 1) { \ 193 column->elementSize = 1; \ 172 194 NATIVETYPE *values = (NATIVETYPE *) psAlloc(sizeof(NATIVETYPE) * table->numRows); \ 173 195 int anynul = 0; \ 196 breakhere(); \ 174 197 fits_read_col(fits->fd, FITSTYPE, col, 1, \ 175 198 1, numRows, NULL, values, &anynul, &status); \ … … 180 203 col, name, typecode, repeat); \ 181 204 } else { \ 205 column->elementSize = repeat; \ 182 206 column->type = PS_DATA_VECTOR; \ 207 column->vectorType = PS_DATA_##TYPE; \ 183 208 column->data.vec = psAlloc(sizeof(psVector*) * table->numRows); \ 184 209 for (int row = 0; row < table->numRows; row++) { \ … … 192 217 } \ 193 218 column->data.vec[row] = vec; \ 194 /* psMetadataAdd(data,PS_LIST_TAIL, name, PS_DATA_VECTOR, "", vec); */ \195 219 psFree(values); \ 196 /* psFree(vec); */ \197 220 } \ 198 221 \ … … 201 224 } 202 225 226 // Handle cases where the data is "really" unsigned 227 if (typecode == TLONG && tzero == 2147483648) { 228 typecode = TULONG; 229 } else if (typecode == TSHORT && tzero == 32768) { 230 typecode = TUSHORT; 231 } 232 233 // Save the column number for this column in the index metadata 203 234 psMetadataAddS32(table->index, PS_LIST_TAIL, name, 0, NULL, col-1); 235 204 236 psFitsTableColumn *column = &table->columns[col-1]; 205 // column->name = psStringCopy(name); 237 // This second copy of the name makes it easily available when writing the table 238 column->name = psStringCopy(name); 206 239 switch (typecode) { 207 // TBYTE and TSHORT fall though to read into psS32 208 case TBYTE: 209 case TSHORT: 240 READ_TABLE_ROW_CASE(TBYTE, long, S32, S32); 241 READ_TABLE_ROW_CASE(TSHORT, short, S16, S16); 242 READ_TABLE_ROW_CASE(TUSHORT, unsigned short, U16, U16); 243 READ_TABLE_ROW_CASE(TULONG, unsigned long, U32, U32); 210 244 READ_TABLE_ROW_CASE(TLONG, long, S32, S32); 211 245 READ_TABLE_ROW_CASE(TLONGLONG, psS64, S64, S64); … … 216 250 column->data.str = psAlloc(sizeof(psString) * table->numRows); 217 251 column->type = PS_DATA_STRING; 252 column->elementSize = 0; 218 253 for (int row = 0; row < table->numRows; row++) { 219 254 psString value = psStringAlloc(repeat); … … 227 262 } 228 263 column->data.str[row] = value; 264 int len = strlen(value); 265 if (len > column->elementSize) { 266 column->elementSize = len; 267 } 229 268 } 230 269 break; … … 245 284 } 246 285 286 // return the index for a given column 247 287 int psFitsTableGetColumnIndex(psFitsTable *table, psString name) 248 288 { … … 258 298 } 259 299 300 // return F32 value for given cell 260 301 psF32 psFitsTableGetCellF32(psFitsTable *table, int row, int col) { 261 302 return table->columns[col].data.F32[row]; 262 303 } 263 304 305 // return value for a named column for a given row 264 306 psF32 psFitsTableGetF32(bool *status, psFitsTable *table, psString name, int row) { 265 307 bool mdok; … … 295 337 psFitsTableColumn *column = &table->columns[col]; 296 338 switch (column->type) { 339 case PS_DATA_S16: 340 column->data.S16[newRow] = column->data.S16[row]; 341 break; 342 case PS_DATA_U16: 343 column->data.U16[newRow] = column->data.U16[row]; 344 break; 297 345 case PS_DATA_S32: 298 346 column->data.S32[newRow] = column->data.S32[row]; 347 break; 348 case PS_DATA_U32: 349 column->data.U32[newRow] = column->data.U32[row]; 299 350 break; 300 351 case PS_DATA_S64: … … 331 382 } 332 383 } 384 333 385 // set the new number of rows 334 // XXX: should we do this?335 386 table->numRows = newRow; 336 387 … … 338 389 } 339 390 391 // Get the TFORM character, given a PS type 392 static inline char getTForm(psDataType type) 393 { 394 switch (type) { 395 case PS_TYPE_U8: 396 case PS_TYPE_S8: 397 return 'B'; 398 case PS_TYPE_S16: 399 return 'I'; 400 case PS_TYPE_S32: 401 return 'J'; 402 case PS_TYPE_U64: 403 case PS_TYPE_S64: 404 return 'K'; 405 case PS_TYPE_U16: 406 return 'U'; 407 case PS_TYPE_U32: 408 return 'V'; 409 case PS_TYPE_F32: 410 return 'E'; 411 case PS_TYPE_F64: 412 return 'D'; 413 case PS_TYPE_BOOL: 414 return 'L'; 415 case PS_DATA_STRING: 416 return 'A'; 417 default: 418 psError(PS_ERR_UNKNOWN, true, "Unknown type: %x\n", type); 419 return '?'; 420 } 421 } 422 423 static bool fitsInsertTableNew(psFits* fits, // FITS file 424 const psMetadata* header, // FITS header to write 425 psFitsTable *table, // internal representation of the table 426 const char *extname, // Extension name to give table 427 bool after, // Write table after current extension? 428 bool writeData // Write data? 429 ) 430 { 431 PS_ASSERT_FITS_NON_NULL(fits, false); 432 PS_ASSERT_FITS_WRITABLE(fits, false); 433 PS_ASSERT_PTR_NON_NULL(table, false); 434 435 int status = 0; 436 437 long numRows = table->numRows; 438 if (writeData && numRows < 1) { 439 // no table data, what can I do? 440 psError(PS_ERR_BAD_PARAMETER_SIZE, true, 441 _("Can't create a table without any rows.")); 442 return false; 443 } 444 340 445 #ifdef notdef 341 446 // Find the unique items in the array of metadata 'rows', and their sizes 447 psMetadata *colSpecs = psMetadataAlloc(); // Column specifications 448 size_t rowSize = 0; // Size (in bytes) of each row 449 for (long i = 0; i < numRows; i++) { 450 psMetadata* row = table->data[i]; 451 452 if (!row) { 453 continue; 454 } 455 psMetadataIterator *rowIter = psMetadataIteratorAlloc(row, PS_LIST_HEAD, NULL); // Iterator 456 psMetadataItem *colItem; // Column item, from iteration 457 while ((colItem = psMetadataGetAndIncrement(rowIter))) { 458 if (!(PS_DATA_IS_PRIMITIVE(colItem->type) || colItem->type == PS_DATA_STRING || 459 colItem->type == PS_DATA_VECTOR)) { 460 // unsupported type -- treating as an error 461 psError(PS_ERR_BAD_PARAMETER_TYPE, true, 462 "Unsupported data type (%d) for Metadata Item '%s' in row %ld.", 463 colItem->type, colItem->name, i); 464 psFree(rowIter); 465 psFree(colSpecs); 466 return false; 467 } 468 469 size_t size = columnSize(colItem); // Size for this column 470 471 // Check to see if we know about this one; or update the size if required 472 psMetadataItem *colSpecItem = psMetadataLookup(colSpecs, colItem->name); 473 if (!colSpecItem) { 474 // A new one! 475 colSpec *spec = psAlloc(sizeof(colSpec)); // Specification for this column 476 // BOOL type is not a valid vector type, so we translate it to U8 477 spec->type = colItem->type == PS_TYPE_BOOL ? PS_TYPE_U8 : colItem->type; 478 spec->size = size; 479 if (colItem->type == PS_DATA_VECTOR) { 480 psVector *vector = colItem->data.V; // The vector 481 spec->vectorType = vector->type.type; 482 } 483 psMetadataAddPtr(colSpecs, PS_LIST_TAIL, colItem->name, PS_DATA_UNKNOWN, "", spec); 484 psFree(spec); // Drop reference 485 rowSize += PSELEMTYPE_SIZEOF(spec->type); 486 } else { 487 colSpec *spec = colSpecItem->data.V; // The specification 488 if (size > spec->size) { 489 spec->size = size; 490 } 491 if (colItem->type != spec->type && 492 colItem->type != PS_TYPE_BOOL && spec->type != PS_TYPE_U8) { 493 psWarning("Differing type found for column %s: %x vs %x --- using the first found.\n", 494 colSpecItem->name, colItem->type, spec->type); 495 } 496 if (colItem->type == PS_DATA_VECTOR) { 497 psVector *vector = colItem->data.V; // The vector 498 if (vector->type.type != spec->vectorType) { 499 psWarning("Differing vector type found for column %s: %x vs %x " 500 "--- using the first found.\n", colSpecItem->name, vector->type.type, 501 spec->vectorType); 502 } 503 } 504 } 505 } 506 psFree(rowIter); 507 } 508 509 long numColumns = colSpecs->list->n;// Number of columns 510 if (numColumns == 0) { 511 // No table columns found 512 psError(PS_ERR_BAD_PARAMETER_SIZE, true, 513 "Did not find any column data to write to a table."); 514 psFree(colSpecs); 515 return false; 516 } 517 #endif // notdef end of OLD column spec determination 518 519 // Create array of column names and types. 520 psArray *columnNames = psArrayAlloc(table->numCols); // Array of column names, for cfitsio 521 psArray *columnTypes = psArrayAlloc(table->numCols); // Array of column types, for cfitsio 522 for (long i = 0; i < table->numCols; i++) { 523 psFitsTableColumn *column = &table->columns[i]; 524 columnNames->data[i] = psMemIncrRefCounter(column->name); 525 psString colType = NULL; // The FITS column type 526 size_t size = column->elementSize; 527 if (column->type == PS_DATA_VECTOR) { 528 psStringAppend(&colType, "%zd%c", size, getTForm(column->vectorType)); 529 } else { 530 psStringAppend(&colType, "%zd%c", size, getTForm(column->type)); 531 } 532 columnTypes->data[i] = colType; 533 } 534 535 // Create the table HDU 536 int numHDUs = psFitsGetSize(fits); // Number of HDUs in file 537 if (numHDUs == 0) { 538 // We're creating the first extension 539 fits_create_tbl(fits->fd, 540 BINARY_TBL, 541 writeData ? numRows : 0, // number of rows in table 542 table->numCols, // number of columns in table 543 (char**)columnNames->data, // names of the columns 544 (char**)columnTypes->data, // format of the columns 545 NULL, // physical unit of columns 546 NULL, // skip extension name: we set the by hand below 547 &status); 548 } else { 549 if (!after) { 550 if (psFitsGetExtNum(fits) == 0) { 551 // We're creating a replacement primary HDU. 552 // Set status to signal fits_insert_img to insert a new primary HDU 553 status = PREPEND_PRIMARY; 554 } else { 555 // Move back one to perform an insert after the previous HDU 556 psFitsMoveExtNum(fits, -1, true); 557 } 558 } 559 // Insert the table 560 fits_insert_btbl(fits->fd, 561 writeData ? numRows : 0, // number of rows in table 562 table->numCols, // number of columns in table 563 (char**)columnNames->data, // names of the columns 564 (char**)columnTypes->data, // format of the columns 565 NULL, // physical unit of columns 566 NULL, // skip extension name: we set this by hand below 567 0, &status); 568 } 569 psFree(columnNames); 570 psFree(columnTypes); 571 572 if (status != 0) { 573 psFitsError(status, true, "Unable to create FITS table with %d columns and %d rows", 574 table->numCols, table->numRows); 575 return false; 576 } 577 578 // Write header 579 if (header && !psFitsWriteHeader(fits, header)) { 580 psError(PS_ERR_IO, false, "Unable to write FITS header.\n"); 581 return false; 582 } 583 584 // write the header, if any. 585 if (extname && strlen(extname) > 0) { 586 if (!psFitsSetExtName(fits, extname)) { 587 psError(PS_ERR_IO, false, "Unable to write FITS header extension name.\n"); 588 return false; 589 } 590 } 591 592 if (writeData) { 593 // psMetadataIteratorSet(colSpecsIter, PS_LIST_HEAD); 594 for (long colNum = 1; colNum <= table->numCols; colNum++) { 595 // Note: colNum is unit-indexed, because it's for cfitsio 596 psFitsTableColumn *column = &table->columns[colNum - 1]; 597 // colSpec *spec = colSpecItem->data.V; // The specification 598 if (PS_DATA_IS_PRIMITIVE(column->type)) { 599 #ifdef notdef 600 size_t dataSize = PSELEMTYPE_SIZEOF(column->type); // Size (in bytes) of this type 601 psVector *columnData = psVectorAlloc(table->n, column->type); // The raw row data, to be written 602 psVectorInit(columnData, 0); 603 for (long i = 0; i < table->numRows; i++) { 604 psMetadata *row = table->data[i]; // The row of interest 605 psMetadataItem *dataItem = psMetadataLookup(row, colSpecItem->name); // Value of interest 606 if (dataItem) { 607 memcpy(&columnData->data.U8[i * dataSize], &dataItem->data, dataSize); 608 } else { 609 // this element is missing from this row; insert an appropriate-sized place holder 610 // XXX this should insert a NAN for float / double and an appropriate blank for int types 611 // XXX for the moment I am putting in 0.0 612 memset(&columnData->data.U8[i * dataSize], 0, dataSize); 613 } 614 } 615 #endif 616 617 int fitsDataType; // Data type for cfitsio 618 p_psFitsTypeToCfitsio(column->type, NULL, NULL, &fitsDataType); 619 fits_write_col(fits->fd, 620 fitsDataType, 621 colNum, // column number 622 1, // first row 623 1, // first element 624 table->numRows, // number of rows 625 column->data.U8, // the data 626 &status); 627 // psFree(columnData); 628 } else { 629 switch (column->type) { 630 case PS_DATA_STRING: { 631 #ifdef notdef 632 psArray *strings = psArrayAlloc(table->n); // Array of strings 633 for (long i = 0; i < table->n; i++) { 634 psMetadata *row = table->data[i]; // The row of interest 635 strings->data[i] = psMemIncrRefCounter(psMetadataLookupStr(NULL, row, 636 colSpecItem->name)); 637 } 638 fits_write_col_str(fits->fd, colNum, 1, 1, table->n, (char**)strings->data, &status); 639 #endif 640 fits_write_col_str(fits->fd, colNum, 1, 1, table->numRows, (char**)column->data.str, &status); 641 // psFree(strings); 642 break; 643 } 644 case PS_DATA_VECTOR: { 645 size_t dataSize = PSELEMTYPE_SIZEOF(column->vectorType); // Size of data, in bytes 646 psVector *columnData = psVectorAlloc(column->elementSize * table->numRows * dataSize, PS_TYPE_U8); 647 psVectorInit(columnData, 0); 648 for (long i = 0; i < table->numRows; i++) { 649 #ifdef notdef 650 psMetadata *row = table->data[i]; // The row of interest 651 psMetadataItem* dataItem = psMetadataLookup(row, colSpecItem->name); 652 if (dataItem->type != PS_DATA_VECTOR) { 653 // Just in case --- get a zero instead of some weird result 654 continue; 655 } 656 psVector *vector = dataItem->data.V; 657 #endif 658 psVector *vector = column->data.vec[i]; 659 memcpy(&columnData->data.U8[i * dataSize * column->elementSize], vector->data.U8, 660 vector->n * dataSize); 661 } 662 663 int fitsDataType; // Data type for cfitsio 664 p_psFitsTypeToCfitsio(column->vectorType, NULL, NULL, &fitsDataType); 665 fits_write_col(fits->fd, fitsDataType, colNum, 1, 1, table->numRows * column->elementSize, 666 columnData->data.U8, &status); 667 psFree(columnData); 668 break; 669 } 670 default: 671 psAbort("Should never get here.\n"); 672 } 673 } 674 675 // Check error status from writing column 676 if (status != 0) { 677 psFitsError(status, true, "Unable to write column %ld of FITS table", colNum); 678 return false; 679 } 680 } 681 } 682 683 // This forces a re-scan of the header to ensure everything's kosher. We found this occassionally 684 // necessary for compressed images, which are tables, so perhaps it helps here too. I guess it can't 685 // hurt. 686 ffrdef(fits->fd, &status); 687 if (psFitsError(status, true, "Could not re-scan HDU.")) { 688 return false; 689 } 690 691 return true; 692 } 693 694 // END OF new insert table 695 696 bool psFitsWriteTableNew(psFits* fits, 697 const psMetadata* header, 698 psFitsTable* table, 699 const char *extname) 700 { 701 PS_ASSERT_FITS_NON_NULL(fits, false); 702 PS_ASSERT_FITS_WRITABLE(fits, false); 703 if (!psFitsMoveLast(fits)) { 704 psError(PS_ERR_UNKNOWN, false, "Unable to move to last extension to write table"); 705 return false; 706 } 707 bool writeData = table->numRows > 0; 708 return fitsInsertTableNew(fits, header, table, extname, true, writeData); 709 } 710 711 #ifdef notdef 342 712 343 713 psArray* psFitsReadTableColumn(const psFits* fits, -
trunk/psLib/src/fits/psFitsTableNew.h
r32217 r32228 14 14 15 15 typedef struct { 16 /* psString name; */16 psString name; 17 17 psDataType type; 18 psDataType vectorType; // type inside if Vector 19 int elementSize; // 1 for primitives, strlen for strings 20 // vector length for vectors 18 21 // only types supported by fits tables will be implemented 19 22 union { … … 49 52 50 53 psFitsTable *psFitsReadTableNew(const psFits *fits); 51 bool psFitsWriteTableNew(psFits *fits, psFitsTable *table, const char *extname);54 bool psFitsWriteTableNew(psFits *fits, const psMetadata *header, psFitsTable *table, const char *extname); 52 55 bool psFitsTableCensor(psFitsTable *table, bool *rowMask); 53 56
Note:
See TracChangeset
for help on using the changeset viewer.
