src/fits/GFitsTableBitCol.cpp

Go to the documentation of this file.
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 }

Generated on Tue Jan 24 12:37:22 2017 for GammaLib by  doxygen 1.4.7