Commit bb8039af995d0c7d527da9962f401c3084dd6234

Authored by knodlseder
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&amp; GFitsTable::operator[](const std::string&amp; 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&amp; GFitsTable::operator[](const std::string&amp; 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&amp; 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 =
... ...