00001 /*************************************************************************** 00002 * GFitsTableBitCol.cpp - FITS table Bit column class * 00003 * ----------------------------------------------------------------------- * 00004 * copyright (C) 2008-2016 by Juergen Knoedlseder * 00005 * ----------------------------------------------------------------------- * 00006 * * 00007 * This program is free software: you can redistribute it and/or modify * 00008 * it under the terms of the GNU General Public License as published by * 00009 * the Free Software Foundation, either version 3 of the License, or * 00010 * (at your option) any later version. * 00011 * * 00012 * This program is distributed in the hope that it will be useful, * 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00015 * GNU General Public License for more details. * 00016 * * 00017 * You should have received a copy of the GNU General Public License * 00018 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 00019 * * 00020 ***************************************************************************/ 00021 /** 00022 * @file GFitsTableBitCol.cpp 00023 * @brief FITS table bit column class implementation 00024 * @author Juergen Knoedlseder 00025 */ 00026 00027 /* __ Includes ___________________________________________________________ */ 00028 #ifdef HAVE_CONFIG_H 00029 #include <config.h> 00030 #endif 00031 #include <string> 00032 #include "GException.hpp" 00033 #include "GTools.hpp" 00034 #include "GFitsCfitsio.hpp" 00035 #include "GFitsTableBitCol.hpp" 00036 00037 /* __ Method name definitions ____________________________________________ */ 00038 #define G_INSERT "GFitsTableBitCol::insert(int&, int&)" 00039 #define G_REMOVE "GFitsTableBitCol::remove(int&, int&)" 00040 #define G_LOAD_COLUMN "GFitsTableBitCol::load_column()" 00041 #define G_SAVE_COLUMN "GFitsTableBitCol::save_column()" 00042 #define G_GET_BIT "GFitsTableBitCol::get_bit(int&,int&)" 00043 00044 /* __ Macros _____________________________________________________________ */ 00045 00046 /* __ Coding definitions _________________________________________________ */ 00047 00048 /* __ Debug definitions __________________________________________________ */ 00049 //#define G_CALL_GRAPH //!< Dump call graph in console 00050 00051 00052 /*========================================================================== 00053 = = 00054 = Constructors/destructors = 00055 = = 00056 ==========================================================================*/ 00057 00058 /***********************************************************************//** 00059 * @brief Constructor 00060 ***************************************************************************/ 00061 GFitsTableBitCol::GFitsTableBitCol(void) : GFitsTableCol() 00062 { 00063 // Initialise class members for clean destruction 00064 init_members(); 00065 00066 // Return 00067 return; 00068 } 00069 00070 00071 /***********************************************************************//** 00072 * @brief Constructor 00073 * 00074 * @param[in] name Name of column. 00075 * @param[in] length Length of column. 00076 * @param[in] size Vector size of column. 00077 ***************************************************************************/ 00078 GFitsTableBitCol::GFitsTableBitCol(const std::string& name, 00079 const int& length, 00080 const int& size) : 00081 GFitsTableCol(name, length, size, 1) 00082 { 00083 // Initialise class members for clean destruction 00084 init_members(); 00085 00086 // Return 00087 return; 00088 } 00089 00090 00091 /***********************************************************************//** 00092 * @brief Copy constructor 00093 * 00094 * @param[in] column Table column. 00095 ***************************************************************************/ 00096 GFitsTableBitCol::GFitsTableBitCol(const GFitsTableBitCol& column) : 00097 GFitsTableCol(column) 00098 { 00099 // Initialise class members for clean destruction 00100 init_members(); 00101 00102 // Copy members 00103 copy_members(column); 00104 00105 // Return 00106 return; 00107 } 00108 00109 00110 /***********************************************************************//** 00111 * @brief Destructor 00112 ***************************************************************************/ 00113 GFitsTableBitCol::~GFitsTableBitCol(void) 00114 { 00115 // Free members 00116 free_members(); 00117 00118 // Return 00119 return; 00120 } 00121 00122 00123 /*========================================================================== 00124 = = 00125 = Operators = 00126 = = 00127 ==========================================================================*/ 00128 00129 /***********************************************************************//** 00130 * @brief Assignment operator 00131 * 00132 * @param[in] column Table column. 00133 * @return Table column. 00134 ***************************************************************************/ 00135 GFitsTableBitCol& GFitsTableBitCol::operator=(const GFitsTableBitCol& column) 00136 { 00137 // Execute only if object is not identical 00138 if (this != &column) { 00139 00140 // Copy base class members 00141 this->GFitsTableCol::operator=(column); 00142 00143 // Free members 00144 free_members(); 00145 00146 // Initialise private members for clean destruction 00147 init_members(); 00148 00149 // Copy members 00150 copy_members(column); 00151 00152 } // endif: object was not identical 00153 00154 // Return this object 00155 return *this; 00156 } 00157 00158 00159 /***********************************************************************//** 00160 * @brief Column data access operator 00161 * 00162 * @param[in] row Row of column to access. 00163 * @param[in] inx Vector index in column row to access. 00164 * 00165 * Provides access to data in a column. 00166 ***************************************************************************/ 00167 bool& GFitsTableBitCol::operator()(const int& row, const int& inx) 00168 { 00169 // If data are not available then load them now 00170 if (m_data == NULL) this->fetch_data(); 00171 00172 // Set any pending Bit 00173 set_pending(); 00174 00175 // Get Bit 00176 get_bit(row, inx); 00177 00178 // Signal that a Bit is pending. We need this here since the non-const 00179 // operator allows changing the Bit after exiting the method, hence 00180 // we have to signal that the actual value of 'm_bit_value' could have 00181 // been modified and needs to be written back into the data array. 00182 m_bit_pending = true; 00183 00184 // Return Bit 00185 return m_bit_value; 00186 } 00187 00188 00189 /***********************************************************************//** 00190 * @brief Column data access operator (const variant) 00191 * 00192 * @param[in] row Row of column to access. 00193 * @param[in] inx Vector index in column row to access 00194 * 00195 * Provides access to data in a column. 00196 ***************************************************************************/ 00197 const bool& GFitsTableBitCol::operator()(const int& row, const int& inx) const 00198 { 00199 // Circumvent const correctness 00200 GFitsTableBitCol* ptr = const_cast<GFitsTableBitCol*>(this); 00201 00202 // If data are not available then load them now 00203 if (m_data == NULL) ptr->fetch_data(); 00204 00205 // Set any pending Bit 00206 ptr->set_pending(); 00207 00208 // Get Bit 00209 ptr->get_bit(row, inx); 00210 00211 // Return data bin 00212 return m_bit_value; 00213 } 00214 00215 00216 /*========================================================================== 00217 = = 00218 = Public methods = 00219 = = 00220 ==========================================================================*/ 00221 00222 /***********************************************************************//** 00223 * @brief Clear instance 00224 * 00225 * This method properly resets the object to an initial state. 00226 ***************************************************************************/ 00227 void GFitsTableBitCol::clear(void) 00228 { 00229 // Free class members (base and derived classes, derived class first) 00230 free_members(); 00231 this->GFitsTableCol::free_members(); 00232 00233 // Initialise members 00234 this->GFitsTableCol::init_members(); 00235 init_members(); 00236 00237 // Return 00238 return; 00239 } 00240 00241 00242 /***********************************************************************//** 00243 * @brief Clone column 00244 ***************************************************************************/ 00245 GFitsTableBitCol* GFitsTableBitCol::clone(void) const 00246 { 00247 return new GFitsTableBitCol(*this); 00248 } 00249 00250 00251 /***********************************************************************//** 00252 * @brief Get string value 00253 * 00254 * @param[in] row Table row. 00255 * @param[in] inx Table column vector index. 00256 * 00257 * Returns value of specified row and vector index as string. 00258 ***************************************************************************/ 00259 std::string GFitsTableBitCol::string(const int& row, const int& inx) const 00260 { 00261 // Get Bit value 00262 bool bit = (*this)(row, inx); 00263 00264 // Convert bit into string 00265 std::string result = (bit) ? "T" : "F"; 00266 00267 // Return result 00268 return result; 00269 } 00270 00271 00272 /***********************************************************************//** 00273 * @brief Get double precision value 00274 * 00275 * @param[in] row Table row. 00276 * @param[in] inx Table column vector index. 00277 * 00278 * Returns value of specified row and vector index as double precision. 00279 ***************************************************************************/ 00280 double GFitsTableBitCol::real(const int& row, const int& inx) const 00281 { 00282 // Get Bit value 00283 bool bit = (*this)(row, inx); 00284 00285 // Convert bit into double 00286 double result = (bit) ? 1.0 : 0.0; 00287 00288 // Return result 00289 return result; 00290 } 00291 00292 00293 /***********************************************************************//** 00294 * @brief Get integer value 00295 * 00296 * @param[in] row Table row. 00297 * @param[in] inx Table column vector index. 00298 * 00299 * Returns value of specified row and vector index as integer. 00300 ***************************************************************************/ 00301 int GFitsTableBitCol::integer(const int& row, const int& inx) const 00302 { 00303 // Get Bit value 00304 bool bit = (*this)(row, inx); 00305 00306 // Convert bit into double 00307 int result = (bit) ? 1 : 0; 00308 00309 // Return result 00310 return result; 00311 } 00312 00313 00314 /***********************************************************************//** 00315 * @brief Insert rows in column 00316 * 00317 * @param[in] row Row after which rows should be inserted (0=first row). 00318 * @param[in] nrows Number of rows to be inserted. 00319 * 00320 * @exception GException::fits_invalid_row 00321 * Specified row is invalid. 00322 * 00323 * Inserts rows into a FITS table. This implies that the column will be 00324 * loaded into memory. 00325 ***************************************************************************/ 00326 void GFitsTableBitCol::insert(const int& row, const int& nrows) 00327 { 00328 // Make sure that row is valid 00329 if (row < 0 || row > m_length) { 00330 throw GException::fits_invalid_row(G_INSERT, row, m_length); 00331 } 00332 00333 // Continue only if there are rows to be inserted 00334 if (nrows > 0) { 00335 00336 // If we have no rows yet then simply set the length to the 00337 // number of rows to be inserted 00338 if (m_length == 0) { 00339 m_length = nrows; 00340 m_size = m_number * m_length; 00341 alloc_data(); 00342 init_data(); 00343 } 00344 00345 // ... otherwise fetch data, allocate new data and copy over 00346 // the existing items 00347 else { 00348 00349 // If data are not available then load them now 00350 if (m_data == NULL) fetch_data(); 00351 00352 // Set any pending Bit 00353 set_pending(); 00354 00355 // Compute new column length 00356 int length = m_length + nrows; 00357 00358 // Compute total number of Bits in column 00359 m_bits = m_number * length; 00360 00361 // Compute number of Bytes and Bits per row 00362 m_bytes_per_row = (m_number > 0) ? ((m_number-1) / 8) + 1 : 0; 00363 m_bits_per_row = m_bytes_per_row * 8; 00364 00365 // Compute length of memory array 00366 m_size = m_bytes_per_row * length; 00367 00368 // Allocate new data to hold the column 00369 unsigned char* new_data = new unsigned char[m_size]; 00370 00371 // Compute the number of elements before the insertion point, 00372 // the number of elements that get inserted, and the total 00373 // number of elements after the insertion point 00374 int n_before = m_bytes_per_row * row; 00375 int n_insert = m_bytes_per_row * nrows; 00376 int n_after = m_bytes_per_row * (m_length - row); 00377 00378 // Copy and initialise data 00379 unsigned char* src = m_data; 00380 unsigned char* dst = new_data; 00381 for (int i = 0; i < n_before; ++i) { 00382 *dst++ = *src++; 00383 } 00384 for (int i = 0; i < n_insert; ++i) { 00385 *dst++ = 0; 00386 } 00387 for (int i = 0; i < n_after; ++i) { 00388 *dst++ = *src++; 00389 } 00390 00391 // Free old data 00392 if (m_data != NULL) delete [] m_data; 00393 00394 // Set pointer to new data and store length 00395 m_data = new_data; 00396 m_length = length; 00397 00398 } // endelse: there were already data 00399 00400 } // endfor: there were rows to be inserted 00401 00402 // Return 00403 return; 00404 } 00405 00406 00407 /***********************************************************************//** 00408 * @brief Remove rows from column 00409 * 00410 * @param[in] row Row after which rows should be removed (0=first row). 00411 * @param[in] nrows Number of rows to be removed. 00412 * 00413 * @exception GException::fits_invalid_row 00414 * Specified row is invalid. 00415 * @exception GException::fits_invalid_nrows 00416 * Invalid number of rows specified. 00417 * 00418 * This method removes rows from a FITS table. This implies that the column 00419 * will be loaded into memory. 00420 ***************************************************************************/ 00421 void GFitsTableBitCol::remove(const int& row, const int& nrows) 00422 { 00423 // Make sure that row is valid 00424 if (row < 0 || row >= m_length) { 00425 throw GException::fits_invalid_row(G_REMOVE, row, m_length-1); 00426 } 00427 00428 // Make sure that we don't remove beyond the limit 00429 if (nrows < 0 || nrows > m_length-row) { 00430 throw GException::fits_invalid_nrows(G_REMOVE, nrows, m_length-row); 00431 } 00432 00433 // Continue only if there are rows to be removed 00434 if (nrows > 0) { 00435 00436 // If data are not available then load them now 00437 if (m_data == NULL) fetch_data(); 00438 00439 // Set any pending Bit 00440 set_pending(); 00441 00442 // Compute new column length 00443 int length = m_length - nrows; 00444 00445 // Compute total number of Bits in column 00446 m_bits = m_number * length; 00447 00448 // Compute number of Bytes and Bits per row 00449 m_bytes_per_row = (m_number > 0) ? ((m_number-1) / 8) + 1 : 0; 00450 m_bits_per_row = m_bytes_per_row * 8; 00451 00452 // Compute length of memory array 00453 m_size = m_bytes_per_row * length; 00454 00455 // If we have rows remaining then allocate new data to hold 00456 // the column 00457 if (m_size > 0) { 00458 00459 // Allocate new data to hold the column 00460 unsigned char* new_data = new unsigned char[m_size]; 00461 00462 // Compute the number of elements before the removal point, 00463 // the number of elements that get removed, and the total 00464 // number of elements after the removal point 00465 int n_before = m_bytes_per_row * row; 00466 int n_remove = m_bytes_per_row * nrows; 00467 int n_after = m_bytes_per_row * (length - row); 00468 00469 // Copy data 00470 unsigned char* src = m_data; 00471 unsigned char* dst = new_data; 00472 for (int i = 0; i < n_before; ++i) { 00473 *dst++ = *src++; 00474 } 00475 src += n_remove; 00476 for (int i = 0; i < n_after; ++i) { 00477 *dst++ = *src++; 00478 } 00479 00480 // Free old data 00481 if (m_data != NULL) delete [] m_data; 00482 00483 // Set pointer to new data and store length 00484 m_data = new_data; 00485 m_length = length; 00486 00487 } // endif: there are still elements after removal 00488 00489 // ... otherwise just remove all data 00490 else { 00491 00492 // Free old data 00493 if (m_data != NULL) delete [] m_data; 00494 00495 // Set pointer to new data and store length 00496 m_data = NULL; 00497 m_length = length; 00498 } 00499 00500 } // endfor: there were rows to be removed 00501 00502 // Return 00503 return; 00504 } 00505 00506 00507 /***********************************************************************//** 00508 * @brief Set nul value 00509 * 00510 * @param[in] value Nul value. 00511 * 00512 * @todo To correctly reflect the nul value in the data, the column should 00513 * be reloaded. However, the column may have been changed, so in principle 00514 * saving is needed. However, we may not want to store the data, hence saving 00515 * is also not desired. We thus have to develop a method to update the 00516 * column information for a new nul value in place ... 00517 ***************************************************************************/ 00518 void GFitsTableBitCol::nulval(const unsigned char* value) 00519 { 00520 // Allocate nul value 00521 alloc_nulval(value); 00522 00523 // Update column 00524 // if (m_data != NULL) { 00525 // save(); 00526 // load(); 00527 // } 00528 00529 // Return 00530 return; 00531 } 00532 00533 00534 /*========================================================================== 00535 = = 00536 = Private methods = 00537 = = 00538 ==========================================================================*/ 00539 00540 /***********************************************************************//** 00541 * @brief Initialise class members 00542 ***************************************************************************/ 00543 void GFitsTableBitCol::init_members(void) 00544 { 00545 // Optionally print call graph 00546 #if defined(G_CALL_GRAPH) 00547 printf("GFitsTableBitCol::init_members\n"); 00548 #endif 00549 00550 // Initialise members 00551 m_type = __TBIT; 00552 m_bits = 0; 00553 m_bytes_per_row = 0; 00554 m_bits_per_row = 0; 00555 m_data = NULL; 00556 m_nulval = NULL; 00557 m_bit_pending = false; 00558 m_bit_value = false; 00559 m_bit_byte = 0; 00560 m_bit_mask = 0; 00561 00562 // Optionally print call graph 00563 #if defined(G_CALL_GRAPH) 00564 printf("exit GFitsTableBitCol::init_members\n"); 00565 #endif 00566 00567 // Return 00568 return; 00569 } 00570 00571 00572 /***********************************************************************//** 00573 * @brief Copy class members 00574 * 00575 * @param[in] column Column. 00576 * 00577 * Sets the content of the vector column by copying from another column. 00578 * If the code is compiled with the small memory option, and if the source 00579 * column has not yet been loaded, then we only load the column temporarily 00580 * for copying purposes and release it again once copying is finished. 00581 ***************************************************************************/ 00582 void GFitsTableBitCol::copy_members(const GFitsTableBitCol& column) 00583 { 00584 // Fetch data if necessary 00585 bool not_loaded = (!column.is_loaded()); 00586 if (not_loaded) { 00587 column.fetch_data(); 00588 } 00589 00590 // Copy attributes 00591 m_type = column.m_type; 00592 m_size = column.m_size; 00593 m_varlen = column.m_varlen; 00594 m_rowstart = column.m_rowstart; 00595 m_bits = column.m_bits; 00596 m_bytes_per_row = column.m_bytes_per_row; 00597 m_bits_per_row = column.m_bits_per_row; 00598 m_bit_pending = column.m_bit_pending; 00599 m_bit_value = column.m_bit_value; 00600 m_bit_byte = column.m_bit_byte; 00601 m_bit_mask = column.m_bit_mask; 00602 00603 // Copy column data 00604 if (column.m_data != NULL && m_size > 0) { 00605 alloc_data(); 00606 for (int i = 0; i < m_size; ++i) 00607 m_data[i] = column.m_data[i]; 00608 } 00609 00610 // Copy NULL value 00611 alloc_nulval(column.m_nulval); 00612 00613 // Small memory option: release column if it was fetch above 00614 #if defined(G_SMALL_MEMORY) 00615 if (not_loaded) { 00616 const_cast<GFitsTableBitCol*>(&column)->release_data(); 00617 } 00618 #endif 00619 00620 // Return 00621 return; 00622 } 00623 00624 00625 /***********************************************************************//** 00626 * @brief Delete class members 00627 ***************************************************************************/ 00628 void GFitsTableBitCol::free_members(void) 00629 { 00630 // Optionally print call graph 00631 #if defined(G_CALL_GRAPH) 00632 printf("GFitsTableBitCol::free_members\n"); 00633 #endif 00634 00635 // Free memory 00636 if (m_data != NULL) delete [] m_data; 00637 if (m_nulval != NULL) delete m_nulval; 00638 00639 // Mark memory as freed 00640 m_data = NULL; 00641 m_nulval = NULL; 00642 00643 // Reset load flag 00644 m_size = 0; 00645 00646 // Optionally print call graph 00647 #if defined(G_CALL_GRAPH) 00648 printf("exit GFitsTableBitCol::free_members\n"); 00649 #endif 00650 00651 // Return 00652 return; 00653 } 00654 00655 00656 /***********************************************************************//** 00657 * @brief Returns format string of ASCII table 00658 ***************************************************************************/ 00659 std::string GFitsTableBitCol::ascii_format(void) const 00660 { 00661 // Initialize format string 00662 std::string format; 00663 00664 // Set type code 00665 format.append("I"); 00666 00667 // Set width 00668 format.append(gammalib::str(m_width)); 00669 00670 // Return format 00671 return format; 00672 } 00673 00674 00675 /***********************************************************************//** 00676 * @brief Allocates column data 00677 ***************************************************************************/ 00678 void GFitsTableBitCol::alloc_data(void) 00679 { 00680 // Optionally print call graph 00681 #if defined(G_CALL_GRAPH) 00682 printf("GFitsTableBitCol::alloc_data(%d)\n", m_size); 00683 #endif 00684 00685 // Free any existing memory 00686 if (m_data != NULL) delete [] m_data; 00687 00688 // Mark pointer as free 00689 m_data = NULL; 00690 00691 // Allocate new data 00692 if (m_size > 0) { 00693 m_data = new unsigned char[m_size]; 00694 } 00695 00696 // Optionally print call graph 00697 #if defined(G_CALL_GRAPH) 00698 printf("exit GFitsTableBitCol::alloc_data(m_data=%x)\n", m_data); 00699 #endif 00700 00701 // Return 00702 return; 00703 } 00704 00705 00706 /***********************************************************************//** 00707 * @brief Fetch column data 00708 * 00709 * This method fetches column data when needed. It is declared const, so 00710 * that const data access methods can be implemented. 00711 * 00712 * If a FITS file is attached to the column the data are loaded into memory 00713 * from the FITS file. If no FITS file is attached, memory is allocated 00714 * to hold the column data and all cells are initialised. 00715 * 00716 * This method calls GFitsTableCol::load_column to do the job. 00717 ***************************************************************************/ 00718 void GFitsTableBitCol::fetch_data(void) const 00719 { 00720 // Load column (circumvent const correctness) 00721 const_cast<GFitsTableBitCol*>(this)->load_column(); 00722 00723 // Return 00724 return; 00725 } 00726 00727 00728 /***********************************************************************//** 00729 * @brief Resize column data 00730 * 00731 * @param[in] index Start index. 00732 * @param[in] number Number of elements to add/remove. 00733 * 00734 * Adds or removes elements from specified index on. Adding is done if 00735 * @p number is a positive number, removing if @p number is negative. 00736 * Note that the method does not change the validity of the arguments. 00737 * This needs to be done by the client. 00738 * 00739 * @todo Needs to be implemented 00740 ***************************************************************************/ 00741 void GFitsTableBitCol::resize_data(const int& index, const int& number) 00742 { 00743 //TODO 00744 00745 // Return 00746 return; 00747 } 00748 00749 00750 /***********************************************************************//** 00751 * @brief Release column data 00752 ***************************************************************************/ 00753 void GFitsTableBitCol::release_data(void) 00754 { 00755 // Free any existing memory 00756 if (m_data != NULL) delete [] m_data; 00757 00758 // Mark pointer as free and reset loaded vector size 00759 m_data = NULL; 00760 m_size = 0; 00761 00762 // Return 00763 return; 00764 } 00765 00766 00767 /***********************************************************************//** 00768 * @brief Allocates null value 00769 ***************************************************************************/ 00770 void GFitsTableBitCol::alloc_nulval(const unsigned char* value) 00771 { 00772 // Free any existing memory 00773 if (m_nulval != NULL) delete m_nulval; 00774 00775 // Mark pointer as free 00776 m_nulval = NULL; 00777 00778 // If we have valid value, allocate and set nul value 00779 if (value != NULL) { 00780 m_nulval = new unsigned char; 00781 *m_nulval = *value; 00782 } 00783 00784 // Return 00785 return; 00786 } 00787 00788 00789 /***********************************************************************//** 00790 * @brief Initialise column data 00791 ***************************************************************************/ 00792 void GFitsTableBitCol::init_data(void) 00793 { 00794 // Initialise data if they exist 00795 if (m_data != NULL) { 00796 for (int i = 0; i < m_size; ++i) { 00797 m_data[i] = 0; 00798 } 00799 } 00800 00801 // Return 00802 return; 00803 } 00804 00805 00806 /***********************************************************************//** 00807 * @brief Load table column from FITS file 00808 * 00809 * @exception GException::fits_hdu_not_found 00810 * Specified HDU not found in FITS file. 00811 * @exception GException::fits_error 00812 * An error occured while loading column data from FITS file. 00813 * 00814 * Load Bit (vector) column into memory by reading 8 Bits at once. 00815 ***************************************************************************/ 00816 void GFitsTableBitCol::load_column(void) 00817 { 00818 // Compute total number of Bits in column 00819 m_bits = m_number * m_length; 00820 00821 // Compute number of Bytes and Bits per row 00822 m_bytes_per_row = (m_number > 0) ? ((m_number-1) / 8) + 1 : 0; 00823 m_bits_per_row = m_bytes_per_row * 8; 00824 00825 // Compute length of memory array 00826 m_size = m_bytes_per_row * m_length; 00827 00828 // Load only if the column has a positive size 00829 if (m_size > 0) { 00830 00831 // Allocate and initialise fresh memory 00832 alloc_data(); 00833 init_data(); 00834 00835 // If a FITS file is attached then load column data from the FITS 00836 // file 00837 if (FPTR(m_fitsfile)->Fptr != NULL) { 00838 00839 // Move to the HDU 00840 int status = 0; 00841 status = __ffmahd(FPTR(m_fitsfile), 00842 (FPTR(m_fitsfile)->HDUposition)+1, 00843 NULL, &status); 00844 if (status != 0) { 00845 throw GException::fits_hdu_not_found(G_LOAD_COLUMN, 00846 (FPTR(m_fitsfile)->HDUposition)+1, 00847 status); 00848 } 00849 00850 // Load data 8 Bits at once 00851 status = __ffgcv(FPTR(m_fitsfile), __TBYTE, m_colnum, 1, 1, m_size, 00852 m_nulval, m_data, &m_anynul, &status); 00853 if (status != 0) { 00854 throw GException::fits_error(G_LOAD_COLUMN, status, 00855 "for column \""+m_name+"\"."); 00856 } 00857 } 00858 00859 } // endif: column has a positive size 00860 00861 // Return 00862 return; 00863 } 00864 00865 00866 /***********************************************************************//** 00867 * @brief Save table column into FITS file 00868 * 00869 * @exception GException::fits_hdu_not_found 00870 * Specified HDU not found in FITS file. 00871 * @exception GException::fits_error 00872 * Error occured during writing of the column data. 00873 * 00874 * Save Bit (vector) column into FITS file by writing 8 Bits at once. 00875 ***************************************************************************/ 00876 void GFitsTableBitCol::save_column(void) 00877 { 00878 // Continue only if a FITS file is connected and data have been loaded 00879 if (FPTR(m_fitsfile)->Fptr != NULL && m_colnum > 0 && m_data != NULL) { 00880 00881 // Set any pending Bit 00882 set_pending(); 00883 00884 // Move to the HDU 00885 int status = 0; 00886 status = __ffmahd(FPTR(m_fitsfile), 00887 (FPTR(m_fitsfile)->HDUposition)+1, NULL, 00888 &status); 00889 if (status != 0) { 00890 throw GException::fits_hdu_not_found(G_SAVE_COLUMN, 00891 (FPTR(m_fitsfile)->HDUposition)+1, 00892 status); 00893 } 00894 00895 // Save data 8 Bits at once 00896 status = __ffpcn(FPTR(m_fitsfile), __TBYTE, m_colnum, 1, 1, 00897 m_size, m_data, m_nulval, &status); 00898 if (status != 0) { 00899 throw GException::fits_error(G_SAVE_COLUMN, status); 00900 } 00901 00902 } // endif: FITS file was connected 00903 00904 // Return 00905 return; 00906 } 00907 00908 00909 /***********************************************************************//** 00910 * @brief Get Bit for boolean access 00911 * 00912 * @param[in] row Row of column. 00913 * @param[in] inx Vector index in column row. 00914 * 00915 * @exception GException::fits_invalid_row 00916 * Table row out of valid range. 00917 * @exception GException::out_of_range 00918 * Table vector index out of valid range. 00919 * 00920 * Set the Bit for boolean data access. Note that this method assumes that 00921 * the data have already been loaded. 00922 ***************************************************************************/ 00923 void GFitsTableBitCol::get_bit(const int& row, const int& inx) 00924 { 00925 // Check row value 00926 #if defined(G_RANGE_CHECK) 00927 if (row < 0 || row >= m_length) { 00928 throw GException::fits_invalid_row(G_GET_BIT, row, m_length-1); 00929 } 00930 #endif 00931 00932 // Check inx value 00933 #if defined(G_RANGE_CHECK) 00934 if (inx < 0 || inx >= m_number) { 00935 throw GException::out_of_range(G_GET_BIT, inx, 0, m_number-1); 00936 } 00937 #endif 00938 00939 // Compute Byte and Bit mask 00940 m_bit_byte = row * m_bytes_per_row + inx / 8; 00941 m_bit_mask = 1 << (7 - (inx % 8)); 00942 00943 // Set Bit value 00944 m_bit_value = (m_data[m_bit_byte] & m_bit_mask); 00945 00946 // Return 00947 return; 00948 } 00949 00950 00951 /***********************************************************************//** 00952 * @brief Set pending Bit 00953 * 00954 * Write the pending Bit into the data. Note that this method assumes that 00955 * the data have already been loaded. 00956 ***************************************************************************/ 00957 void GFitsTableBitCol::set_pending(void) 00958 { 00959 // Continue only if we have a pending Bit 00960 if (m_bit_pending) { 00961 00962 // Set or unset Bit 00963 if (m_bit_value) { 00964 m_data[m_bit_byte] = m_data[m_bit_byte] | m_bit_mask; 00965 } 00966 else { 00967 m_data[m_bit_byte] = m_data[m_bit_byte] & ~m_bit_mask; 00968 } 00969 00970 // Signal that no more Bit is pending 00971 m_bit_pending = false; 00972 00973 } 00974 00975 // Return 00976 return; 00977 }