Commit bb8039af995d0c7d527da9962f401c3084dd6234
1 parent
e9039de9
read and validate TDIM information in data_open() and set unit and TDIM keywords in data_save()
Showing
1 changed file
with
141 additions
and
68 deletions
src/fits/GFitsTable.cpp
| ... | ... | @@ -30,6 +30,7 @@ |
| 30 | 30 | #endif |
| 31 | 31 | #include <cstring> |
| 32 | 32 | #include <iostream> |
| 33 | +#include <vector> | |
| 33 | 34 | #include "GException.hpp" |
| 34 | 35 | #include "GTools.hpp" |
| 35 | 36 | #include "GFitsCfitsio.hpp" |
| ... | ... | @@ -56,8 +57,6 @@ |
| 56 | 57 | #define G_INSERT_COLUMN "GFitsTable::insert_column(int, GFitsTableCol*)" |
| 57 | 58 | #define G_INSERT_ROWS "GFitsTable::insert_rows(int&, int&)" |
| 58 | 59 | #define G_REMOVE_ROWS "GFitsTable::remove_rows(int&, int&)" |
| 59 | -//#define G_COLUMN1 "GFitsTable::column(std::string&)" | |
| 60 | -//#define G_COLUMN2 "GFitsTable::column(int&)" | |
| 61 | 60 | #define G_OPEN_DATA "GFitsTable::open_data(void*)" |
| 62 | 61 | #define G_SAVE_DATA "GFitsTable::save_data()" |
| 63 | 62 | #define G_GET_TFORM "GFitsTable::get_tform(int&)" |
| ... | ... | @@ -262,20 +261,8 @@ GFitsTableCol& GFitsTable::operator[](const std::string& colname) |
| 262 | 261 | throw GException::fits_no_data(G_ACCESS2, "No columns in table."); |
| 263 | 262 | } |
| 264 | 263 | |
| 265 | - // Initialise pointer | |
| 266 | - GFitsTableCol* ptr = NULL; | |
| 267 | - | |
| 268 | - // Search for the specified name | |
| 269 | - for (int i = 0; i < m_cols; ++i) { | |
| 270 | - if (m_columns[i]->name() == colname) { | |
| 271 | - ptr = m_columns[i]; | |
| 272 | - if (ptr == NULL) { | |
| 273 | - throw GException::fits_no_data(G_ACCESS2, | |
| 274 | - "No data for this column"); | |
| 275 | - } | |
| 276 | - break; | |
| 277 | - } | |
| 278 | - } | |
| 264 | + // Get column pointer | |
| 265 | + GFitsTableCol* ptr = ptr_column(colname); | |
| 279 | 266 | |
| 280 | 267 | // If column has not been found throw an exception |
| 281 | 268 | if (ptr == NULL) { |
| ... | ... | @@ -304,20 +291,8 @@ const GFitsTableCol& GFitsTable::operator[](const std::string& colname) const |
| 304 | 291 | throw GException::fits_no_data(G_ACCESS2, "No columns in table."); |
| 305 | 292 | } |
| 306 | 293 | |
| 307 | - // Initialise pointer | |
| 308 | - const GFitsTableCol* ptr = NULL; | |
| 309 | - | |
| 310 | - // If there are columns then search for the specified name | |
| 311 | - for (int i = 0; i < m_cols; ++i) { | |
| 312 | - if (m_columns[i]->name() == colname) { | |
| 313 | - ptr = m_columns[i]; | |
| 314 | - if (ptr == NULL) { | |
| 315 | - throw GException::fits_no_data(G_ACCESS2, | |
| 316 | - "No data for this column"); | |
| 317 | - } | |
| 318 | - break; | |
| 319 | - } | |
| 320 | - } | |
| 294 | + // Get column pointer | |
| 295 | + GFitsTableCol* ptr = ptr_column(colname); | |
| 321 | 296 | |
| 322 | 297 | // If column has not been found throw an exception |
| 323 | 298 | if (ptr == NULL) { |
| ... | ... | @@ -585,37 +560,6 @@ GFitsTableCol* GFitsTable::column(const std::string& colname) |
| 585 | 560 | } |
| 586 | 561 | */ |
| 587 | 562 | |
| 588 | -/***********************************************************************//** | |
| 589 | - * @brief Return pointer to column with number | |
| 590 | - * | |
| 591 | - * @param[in] colnum Number of requested column (starting from 0) | |
| 592 | - * | |
| 593 | - * @exception GException::fits_no_data | |
| 594 | - * There are no column data in the table or there is not data | |
| 595 | - * for this column | |
| 596 | - * @exception GException::out_of_range | |
| 597 | - * Requested column has not been found in table. | |
| 598 | - ***************************************************************************/ | |
| 599 | -/* | |
| 600 | -GFitsTableCol* GFitsTable::column(const int& colnum) | |
| 601 | -{ | |
| 602 | - // If there is no data then throw an exception | |
| 603 | - if (m_columns == NULL) | |
| 604 | - throw GException::fits_no_data(G_COLUMN2, "No column data in table"); | |
| 605 | - | |
| 606 | - // If column number is out of range then throw an exception | |
| 607 | - if (colnum < 0 || colnum >= m_cols) | |
| 608 | - throw GException::out_of_range(G_COLUMN2, colnum, 0, m_cols-1); | |
| 609 | - | |
| 610 | - // Get column pointer | |
| 611 | - GFitsTableCol* ptr = ptr = m_columns[colnum]; | |
| 612 | - if (ptr == NULL) | |
| 613 | - throw GException::fits_no_data(G_COLUMN2, "No data for this column"); | |
| 614 | - | |
| 615 | - // Return column pointer | |
| 616 | - return ptr; | |
| 617 | -} | |
| 618 | -*/ | |
| 619 | 563 | |
| 620 | 564 | /***********************************************************************//** |
| 621 | 565 | * @brief Return number of rows in table |
| ... | ... | @@ -638,6 +582,19 @@ int GFitsTable::ncols(void) const |
| 638 | 582 | |
| 639 | 583 | |
| 640 | 584 | /***********************************************************************//** |
| 585 | + * @brief Checks the presence of a column in table | |
| 586 | + ***************************************************************************/ | |
| 587 | +bool GFitsTable::has(const std::string& colname) const | |
| 588 | +{ | |
| 589 | + // Get pointer in column | |
| 590 | + GFitsTableCol* ptr = ptr_column(colname); | |
| 591 | + | |
| 592 | + // Return state | |
| 593 | + return (ptr != NULL); | |
| 594 | +} | |
| 595 | + | |
| 596 | + | |
| 597 | +/***********************************************************************//** | |
| 641 | 598 | * @brief Print table information |
| 642 | 599 | ***************************************************************************/ |
| 643 | 600 | std::string GFitsTable::print(void) const |
| ... | ... | @@ -707,10 +664,13 @@ std::string GFitsTable::print(void) const |
| 707 | 664 | * A CFITSIO error occured during loading the table. |
| 708 | 665 | * @exception GException::fits_unknown_coltype |
| 709 | 666 | * FITS column of unsupported type has been found in the FITS file. |
| 667 | + * @exception GException::fits_inconsistent_tdim | |
| 668 | + * The TDIM information provided in the header is inconsistent | |
| 669 | + * with the size of the column. | |
| 710 | 670 | * |
| 711 | - * Builds a description of the table in memory. | |
| 712 | - * Columns are not loaded but column descriptors are allocated. | |
| 713 | - * The column data will only be loaded once it needs to be accessed. | |
| 671 | + * This method loads a description of the table into memory. Column data are | |
| 672 | + * not loaded at this point to save memory. They will be loaded on request | |
| 673 | + * later. | |
| 714 | 674 | ***************************************************************************/ |
| 715 | 675 | void GFitsTable::data_open(void* vptr) |
| 716 | 676 | { |
| ... | ... | @@ -799,6 +759,29 @@ void GFitsTable::data_open(void* vptr) |
| 799 | 759 | else |
| 800 | 760 | unit[strlen(unit)-1] = '\0'; |
| 801 | 761 | |
| 762 | + // Get column dimension (optional, leave blank if not found) | |
| 763 | + char dim[80]; | |
| 764 | + sprintf(keyname, "TDIM%d", i+1); | |
| 765 | + status = __ffgkey(FPTR(m_fitsfile), keyname, dim, NULL, &status); | |
| 766 | + if (status != 0) { | |
| 767 | + status = 0; | |
| 768 | + dim[0] = '\0'; | |
| 769 | + dim[1] = '\0'; | |
| 770 | + } | |
| 771 | + else { | |
| 772 | + dim[strlen(dim)-1] = '\0'; | |
| 773 | + } | |
| 774 | + | |
| 775 | + // If found, extract column dimension into vector array of integers | |
| 776 | + std::vector<int> vdim; | |
| 777 | + std::string sdim = strip_chars(strip_whitespace(&(dim[1])),"()"); | |
| 778 | + if (sdim.length() > 0) { | |
| 779 | + std::vector<std::string> elements = split(sdim, ","); | |
| 780 | + for (int k = 0; k < elements.size(); ++k) { | |
| 781 | + vdim.push_back(toint(elements[k])); | |
| 782 | + } | |
| 783 | + } | |
| 784 | + | |
| 802 | 785 | // Allocate column |
| 803 | 786 | m_columns[i] = alloc_column(typecode); |
| 804 | 787 | if (m_columns[i] == NULL) { |
| ... | ... | @@ -811,6 +794,7 @@ void GFitsTable::data_open(void* vptr) |
| 811 | 794 | // Store column definition |
| 812 | 795 | m_columns[i]->name(strip_whitespace(&(value[1]))); |
| 813 | 796 | m_columns[i]->unit(strip_whitespace(&(unit[1]))); |
| 797 | + m_columns[i]->dim(vdim); | |
| 814 | 798 | m_columns[i]->m_colnum = i+1; |
| 815 | 799 | m_columns[i]->m_type = typecode; |
| 816 | 800 | m_columns[i]->m_repeat = repeat; |
| ... | ... | @@ -819,15 +803,36 @@ void GFitsTable::data_open(void* vptr) |
| 819 | 803 | m_columns[i]->connect(FPTR(m_fitsfile)); |
| 820 | 804 | |
| 821 | 805 | // Extract column vector size |
| 822 | - if (m_columns[i]->m_repeat == 1) // ASCII tables | |
| 806 | + if (m_columns[i]->m_repeat == 1) { // ASCII tables | |
| 823 | 807 | m_columns[i]->m_number = 1; |
| 808 | + } | |
| 824 | 809 | else { // Binary tables |
| 825 | - if (typecode == __TSTRING) | |
| 810 | + if (typecode == __TSTRING) { | |
| 826 | 811 | m_columns[i]->m_number = m_columns[i]->m_repeat / |
| 827 | 812 | m_columns[i]->m_width; |
| 828 | - else | |
| 813 | + } | |
| 814 | + else { | |
| 829 | 815 | m_columns[i]->m_number = m_columns[i]->m_repeat; |
| 816 | + } | |
| 830 | 817 | } |
| 818 | + | |
| 819 | + // If TDIM information was set then check its consistency | |
| 820 | + if (vdim.size() > 0) { | |
| 821 | + | |
| 822 | + // Compute expectation | |
| 823 | + int num = vdim[0]; | |
| 824 | + for (int k = 1; k < vdim.size(); ++k) { | |
| 825 | + num *= vdim[k]; | |
| 826 | + } | |
| 827 | + | |
| 828 | + // Compare with real size | |
| 829 | + if (num != m_columns[i]->m_number) { | |
| 830 | + throw GException::fits_inconsistent_tdim(G_OPEN_DATA, | |
| 831 | + vdim, | |
| 832 | + m_columns[i]->m_number); | |
| 833 | + } | |
| 834 | + | |
| 835 | + } // endif: Valid TDIM information was found | |
| 831 | 836 | |
| 832 | 837 | } // endfor: looped over all columns |
| 833 | 838 | |
| ... | ... | @@ -1122,7 +1127,46 @@ void GFitsTable::data_save(void) |
| 1122 | 1127 | |
| 1123 | 1128 | } // endelse: FITS table has been updated |
| 1124 | 1129 | |
| 1125 | - // Now update the header | |
| 1130 | + // Now update the header for all columns (unit and TDIM information) | |
| 1131 | + for (int i = 0; i < m_cols; ++i) { | |
| 1132 | + | |
| 1133 | + // Only consider valid columns | |
| 1134 | + if (m_columns[i] != NULL) { | |
| 1135 | + | |
| 1136 | + // Get column number | |
| 1137 | + int colnum = m_columns[i]->m_colnum; | |
| 1138 | + | |
| 1139 | + // Update column units if available | |
| 1140 | + if (m_columns[i]->unit().length() > 0) { | |
| 1141 | + | |
| 1142 | + // Build keyname | |
| 1143 | + std::string keyname = "TUNIT"+str(colnum); | |
| 1144 | + | |
| 1145 | + // Update header card | |
| 1146 | + card(keyname, m_columns[i]->unit(), "physical unit of field"); | |
| 1147 | + } | |
| 1148 | + | |
| 1149 | + // Write TDIM keyword if available | |
| 1150 | + if (m_columns[i]->dim().size() > 0) { | |
| 1151 | + | |
| 1152 | + // Build keyname | |
| 1153 | + std::string keyname = "TDIM"+str(colnum); | |
| 1154 | + | |
| 1155 | + // Build value string | |
| 1156 | + std::string value = "("+str(m_columns[i]->dim()[0]); | |
| 1157 | + for (int k = 1; k < m_columns[i]->dim().size(); ++k) { | |
| 1158 | + value += ","+str(m_columns[i]->dim()[k]); | |
| 1159 | + } | |
| 1160 | + value += ")"; | |
| 1161 | + | |
| 1162 | + // Update header card | |
| 1163 | + card(keyname, value, "dimensions of field"); | |
| 1164 | + | |
| 1165 | + } // endif: wrote TDIM keyword | |
| 1166 | + | |
| 1167 | + } // endif: column was valid | |
| 1168 | + | |
| 1169 | + } // endfor: looped over all columns | |
| 1126 | 1170 | |
| 1127 | 1171 | // Debug definition: Dump method exit |
| 1128 | 1172 | #if defined(G_DEBUG_SAVE) |
| ... | ... | @@ -1415,6 +1459,35 @@ GFitsTableCol* GFitsTable::alloc_column(int typecode) const |
| 1415 | 1459 | } |
| 1416 | 1460 | |
| 1417 | 1461 | |
| 1462 | +/***********************************************************************//** | |
| 1463 | + * @brief Returns pointer of column with given name | |
| 1464 | + * | |
| 1465 | + * @param[in] colname Name of column. | |
| 1466 | + * | |
| 1467 | + * This method returns a pointer on the column with the specified name. It | |
| 1468 | + * returns NULL if no column with the given name was found, or if the | |
| 1469 | + * column is not allocated. | |
| 1470 | + ***************************************************************************/ | |
| 1471 | +GFitsTableCol* GFitsTable::ptr_column(const std::string& colname) const | |
| 1472 | +{ | |
| 1473 | + // Initialise pointer | |
| 1474 | + GFitsTableCol* ptr = NULL; | |
| 1475 | + | |
| 1476 | + // If there are columns then search for the specified name | |
| 1477 | + if (m_columns != NULL) { | |
| 1478 | + for (int i = 0; i < m_cols; ++i) { | |
| 1479 | + if (m_columns[i]->name() == colname) { | |
| 1480 | + ptr = m_columns[i]; | |
| 1481 | + break; | |
| 1482 | + } | |
| 1483 | + } | |
| 1484 | + } | |
| 1485 | + | |
| 1486 | + // Return pointer | |
| 1487 | + return ptr; | |
| 1488 | +} | |
| 1489 | + | |
| 1490 | + | |
| 1418 | 1491 | /*========================================================================== |
| 1419 | 1492 | = = |
| 1420 | 1493 | = Friends = | ... | ... |