Exemple #1
0
/***********************************************************************//**
 * @brief Save table column into FITS file
 *
 * @exception GException::fits_hdu_not_found
 *            Specified HDU not found in FITS file.
 * @exception GException::fits_error
 *            Error occured during writing of the column data.
 *
 * The table column is only saved if it is linked to a FITS file and if the
 * data are indeed present in the class instance. This avoids saving of data
 * that have not been modified.
 *
 * The method make use of the virtual methods 
 *   GFitsTableCol::ptr_data and
 *   GFitsTableCol::ptr_nulval.
 * These methods are implemented by the derived column classes which 
 * implement a specific storage class (i.e. float, double, short, ...).
 ***************************************************************************/
void GFitsTableCol::save_column_fixed(void)
{
    // Continue only if a FITS file is connected and data have been loaded
    if (FPTR(m_fitsfile)->Fptr != NULL && m_colnum > 0 && ptr_data() != NULL) {

        // Move to the HDU
        int status = 0;
        status     = __ffmahd(FPTR(m_fitsfile),
                              (FPTR(m_fitsfile)->HDUposition)+1, NULL,
                              &status);
        if (status != 0) {
            throw GException::fits_hdu_not_found(G_SAVE_COLUMN_FIXED,
                              (FPTR(m_fitsfile)->HDUposition)+1,
                              status);
        }

        // Save the column data
        status = __ffpcn(FPTR(m_fitsfile), m_type, m_colnum, 1, 1,
                         m_size, ptr_data(), ptr_nulval(), &status);
        if (status != 0) {
            std::string msg = "Unable to save column '"+name()+"' to"
                              " FITS file.";
            throw GException::fits_error(G_SAVE_COLUMN_FIXED, status, msg);
        }

    } // endif: FITS file was connected

    // Return
    return;
}
Exemple #2
0
/***********************************************************************//**
 * @brief Save table column into FITS file
 *
 * @exception GException::fits_hdu_not_found
 *            Specified HDU not found in FITS file.
 * @exception GException::fits_error
 *            Error occured during writing of the column data.
 *
 * Save Bit (vector) column into FITS file by writing 8 Bits at once.
 ***************************************************************************/
void GFitsTableBitCol::save_column(void)
{
    // Continue only if a FITS file is connected and data have been loaded
    if (FPTR(m_fitsfile)->Fptr != NULL && m_colnum > 0 && m_data != NULL) {

        // Set any pending Bit
        set_pending();

        // Move to the HDU
        int status = 0;
        status     = __ffmahd(FPTR(m_fitsfile),
                              (FPTR(m_fitsfile)->HDUposition)+1, NULL,
                              &status);
        if (status != 0) {
            throw GException::fits_hdu_not_found(G_SAVE_COLUMN,
                              (FPTR(m_fitsfile)->HDUposition)+1,
                              status);
        }

        // Save data 8 Bits at once
        status = __ffpcn(FPTR(m_fitsfile), __TBYTE, m_colnum, 1, 1,
                         m_size, m_data, m_nulval, &status);
        if (status != 0) {
            throw GException::fits_error(G_SAVE_COLUMN, status);
        }

    } // endif: FITS file was connected

    // Return
    return;
}
Exemple #3
0
/***********************************************************************//**
 * @brief Load fixed-length column from FITS file
 *
 * @exception GException::fits_hdu_not_found
 *            Specified HDU not found in FITS file.
 * @exception GException::fits_error
 *            An error occured while loading column data from FITS file.
 *
 * If a FITS file is attached to the column the data are loaded into memory
 * from the FITS file. If no FITS file is attached, memory is allocated
 * to hold the column data and all cells are set to 0.
 *
 * The method makes use of the virtual methods 
 * GFitsTableCol::alloc_data,
 * GFitsTableCol::init_data,
 * GFitsTableCol::ptr_data, and
 * GFitsTableCol::ptr_nulval.
 * These methods are implemented by the derived column classes which 
 * implement a specific storage class (i.e. float, double, short, ...).
 ***************************************************************************/
void GFitsTableCol::load_column_fixed(void)
{
    // Calculate size of memory
    m_size = m_number * m_length;

    // Load only if the column has a positive size
    if (m_size > 0) {

        // Allocate and initialise fresh memory
        alloc_data();
        init_data();

        // If a FITS file is attached then try loading column data from the
        // FITS file. This may fail in case that no data has yet been written
        // to the FITS file. In that case we just skip loading and return
        // the initalised column ... 
        if (FPTR(m_fitsfile)->Fptr != NULL) {

            // Move to the HDU
            int status = 0;
            status     = __ffmahd(FPTR(m_fitsfile),
                                  (FPTR(m_fitsfile)->HDUposition)+1,
                                  NULL, &status);
            
            // If this failed because:
            // - the primary HDU was not found (status 252)
            // - we moved past the file (status 107)
            // we assume that no data have yet been written to the file and
            // we skip the loading.
            if (status != 252 && status != 107) {
            
                // Break on any other cfitsio error
                if (status != 0) {
                    throw GException::fits_hdu_not_found(G_LOAD_COLUMN_FIXED,
                                  (FPTR(m_fitsfile)->HDUposition)+1,
                                  status);
                }

                // Load data
                status = __ffgcv(FPTR(m_fitsfile), m_type, m_colnum, 
                                 1, 1, m_size, ptr_nulval(), ptr_data(),
                                 &m_anynul, &status);
                if (status != 0) {
                    throw GException::fits_error(G_LOAD_COLUMN_FIXED, status,
                                    "for column '"+m_name+"'.");
                }
        
            } // endif: no primary HDU found

        } // endif: there was a FITS file attached

    } // endif: column has a positive size

    // Return
    return;
}
Exemple #4
0
/***********************************************************************//**
 * @brief Load table column from FITS file
 *
 * @exception GException::fits_hdu_not_found
 *            Specified HDU not found in FITS file.
 * @exception GException::fits_error
 *            An error occured while loading column data from FITS file.
 *
 * Load Bit (vector) column into memory by reading 8 Bits at once.
 ***************************************************************************/
void GFitsTableBitCol::load_column(void)
{
    // Compute total number of Bits in column
    m_bits = m_number * m_length;

    // Compute number of Bytes and Bits per row
    m_bytes_per_row = (m_number > 0) ? ((m_number-1) / 8) + 1 : 0;
    m_bits_per_row  = m_bytes_per_row * 8;

    // Compute length of memory array
    m_size = m_bytes_per_row * m_length;

    // Load only if the column has a positive size
    if (m_size > 0) {

        // Allocate and initialise fresh memory
        alloc_data();
        init_data();

        // If a FITS file is attached then load column data from the FITS
        // file
        if (FPTR(m_fitsfile)->Fptr != NULL) {

            // Move to the HDU
            int status = 0;
            status     = __ffmahd(FPTR(m_fitsfile),
                                  (FPTR(m_fitsfile)->HDUposition)+1,
                                  NULL, &status);
            if (status != 0) {
                throw GException::fits_hdu_not_found(G_LOAD_COLUMN,
                                  (FPTR(m_fitsfile)->HDUposition)+1,
                                  status);
            }

            // Load data 8 Bits at once
            status = __ffgcv(FPTR(m_fitsfile), __TBYTE, m_colnum, 1, 1, m_size,
                             m_nulval, m_data, &m_anynul, &status);
            if (status != 0) {
                throw GException::fits_error(G_LOAD_COLUMN, status,
                                  "for column \""+m_name+"\".");
            }
        }

    } // endif: column has a positive size

    // Return
    return;
}
Exemple #5
0
/***********************************************************************//**
 * @brief Save table column into FITS file
 *
 * @exception GException::fits_hdu_not_found
 *            Specified HDU not found in FITS file.
 * @exception GException::fits_error
 *            Error occured during writing of the column data.
 *
 * The table column is only saved if it is linked to a FITS file and if the
 * data are indeed present in the class instance. This avoids saving of data
 * that have not been modified.
 *
 * The method make use of the virtual methods 
 *   GFitsTableCol::ptr_data and
 *   GFitsTableCol::ptr_nulval.
 * These methods are implemented by the derived column classes which 
 * implement a specific storage class (i.e. float, double, short, ...).
 ***************************************************************************/
void GFitsTableCol::save_column_variable(void)
{
    // Continue only if a FITS file is connected and data have been loaded
    if (FPTR(m_fitsfile)->Fptr != NULL && m_colnum > 0 && ptr_data() != NULL) {

        // Move to the HDU
        int status = 0;
        status     = __ffmahd(FPTR(m_fitsfile),
                              (FPTR(m_fitsfile)->HDUposition)+1, NULL,
                              &status);
        if (status != 0) {
            throw GException::fits_hdu_not_found(G_SAVE_COLUMN_VARIABLE,
                              (FPTR(m_fitsfile)->HDUposition)+1,
                              status);
        }

        // Save the column data row-by-row
        for (int row = 0; row < m_length; ++row) {

            // Save row data
            status = __ffpcn(FPTR(m_fitsfile),
                             std::abs(m_type),
                             m_colnum, 
                             row+1,
                             1,
                             elements(row),
                             ptr_data(m_rowstart[row]),
                             ptr_nulval(),
                             &status);
            if (status != 0) {
                std::string msg = "Unable to save row "+gammalib::str(row+1)+""
                                  " of column '"+name()+"' to FITS file.";
                throw GException::fits_error(G_SAVE_COLUMN_VARIABLE, status,
                                             msg);
            }

        } // endfor: looped over rows

    } // endif: FITS file was connected

    // Return
    return;
}
Exemple #6
0
/***********************************************************************//**
 * @brief Load variable-length column from FITS file
 *
 * @exception GException::fits_hdu_not_found
 *            Specified HDU not found in FITS file.
 * @exception GException::fits_error
 *            An error occured while loading column data from FITS file.
 *
 * If a FITS file is attached to the column the data are loaded into memory
 * from the FITS file. If no FITS file is attached, memory is allocated
 * to hold the column data and all cells are set to 0.
 *
 * The method makes use of the virtual methods 
 * GFitsTableCol::alloc_data,
 * GFitsTableCol::init_data,
 * GFitsTableCol::ptr_data, and
 * GFitsTableCol::ptr_nulval.
 * These methods are implemented by the derived column classes which 
 * implement a specific storage class (i.e. float, double, short, ...).
 ***************************************************************************/
void GFitsTableCol::load_column_variable(void)
{
    // If a FITS file is attached then try loading column data from the
    // FITS file. This may fail in case that no data has yet been written
    // to the FITS file. In that case we just skip loading and return
    // the initalised column ... 
    if (FPTR(m_fitsfile)->Fptr != NULL) {

        // Move to the HDU
        int status = 0;
        status     = __ffmahd(FPTR(m_fitsfile),
                              (FPTR(m_fitsfile)->HDUposition)+1,
                              NULL,
                              &status);
            
        // If this failed because:
        // - the primary HDU was not found (status 252)
        // - we moved past the file (status 107)
        // we assume that no data have yet been written to the file and
        // we skip the loading.
        if (status != 252 && status != 107) {
            
            // Break on any other cfitsio error
            if (status != 0) {
                throw GException::fits_hdu_not_found(G_LOAD_COLUMN_VARIABLE,
                                  (FPTR(m_fitsfile)->HDUposition)+1,
                                  status);
            }

            // Allocate rowstart array
            m_rowstart.assign(m_length+1, 0);

            // Determine the column length for each row by looping over
            // all rows and derive the total memory requirement
            m_size        = 0;
            m_varlen      = 0;
            m_rowstart[0] = 0;
            for (int row = 0; row < m_length; ++row) {

                // Initialise offset and repeat
                long offset(0);
                long repeat(0);

                // Get variable-length of row in repeat
                status = __ffgdes(FPTR(m_fitsfile),
                                  m_colnum,
                                  row+1,
                                  &repeat,
                                  &offset,
                                  &status);
                if (status != 0) {
                    std::string msg = "Unable to get descriptor of row "+
                                      gammalib::str(row+1)+" of column '"+
                                      name()+"' from FITS file.";
                    throw GException::fits_error(G_LOAD_COLUMN_VARIABLE, status,
                                                 msg);
                }

                // Store start of next row
                m_rowstart[row+1] = m_rowstart[row] + repeat;
                m_size           += repeat;
                if (repeat > m_varlen) {
                    m_varlen = repeat;
                }

            } // endfor: looped over all rows

            // Allocate and initialise fresh memory
            alloc_data();
            init_data();

            // Load data for each row
            for (int row = 0; row < m_length; ++row) {

                // Initialise anynul
                int anynul(0);

                // Load data
                status = __ffgcv(FPTR(m_fitsfile),
                                 std::abs(m_type),
                                 m_colnum, 
                                 row+1,
                                 1,
                                 elements(row),
                                 ptr_nulval(),
                                 ptr_data(m_rowstart[row]),
                                 &anynul,
                                 &status);
                if (status != 0) {
                    std::string msg = "Unable to load row "+gammalib::str(row+1)+""
                                      " of column '"+name()+"' from FITS file.";
                    throw GException::fits_error(G_LOAD_COLUMN_VARIABLE, status,
                                                 msg);
                }

                // Increment anynul
                m_anynul += anynul;

            } // endfor: looped over all rows

        } // endif: no primary HDU found

    } // endif: there was a FITS file attached

    // Return
    return;
}
Exemple #7
0
/***********************************************************************//**
 * @brief Save table into FITS file
 *
 * @exception GException::fits_error
 *            A CFITSIO error occured in this method.
 * @exception GException::fits_bad_col_length
 *            Table columns have inconsistent lengths.
 *
 * This method saves a table into a FITS file.
 *
 * In case that no table HDU exists it will be created by appending a new
 * HDU to the existing file. The definition of this HDU will be based on the
 * table definition in the class instance.
 *
 * The method also verifies the consistency of all table columns. Table
 * columns need to have identical lengths to be saved into a FITS table.
 * All columns with a length of zero will be excluded from saving, and if
 * they exist in the FITS file, they will be removed from the file.
 *
 * @todo This method should also update the header. Even easier, this method
 *       should save the header into the file using the m_header.save()
 *       method.
 *       Only this assures coherence between the files !!!! Once this has
 *       been implemented (also in the GFitsImage method) we should delete
 *       the m_header.save() call in GFitsHDU::save.
 ***************************************************************************/
void GFitsTable::data_save(void)
{
    // Debug definition: Dump method entry
    #if defined(G_DEBUG_SAVE)
    std::cout << "GFitsTable::save: entry" << std::endl;
    #endif

    // Make sure that column lengths are consistent with table length.
    // Columns with zero length will not be considered (why?)
    for (int i = 0; i < m_cols; ++i) {
        if (m_columns[i] != NULL && m_columns[i]->length() > 0) {
            if (m_columns[i]->length() != m_rows) {
                throw GException::fits_bad_col_length(G_DATA_SAVE,
                                                      m_columns[i]->length(),
                                                      m_rows);
            }
        }
    }

    // Move to HDU
    int status = 0;
    status = __ffmahd(FPTR(m_fitsfile), m_hdunum+1, NULL, &status);

    // If HDU does not exist in file then create it now
    if (status == 107) {

        // Reset status
        status = 0;

        // Initialise number of fields
        int tfields = 0;

        // Setup cfitsio column definition arrays
        char** ttype = NULL;
        char** tform = NULL;
        char** tunit = NULL;
        if (m_cols > 0) {
            ttype = new char*[m_cols];
            tform = new char*[m_cols];
            tunit = new char*[m_cols];
            for (int i = 0; i < m_cols; ++i) {
                ttype[i] = NULL;
                tform[i] = NULL;
                tunit[i] = NULL;
            }
            for (int i = 0; i < m_cols; ++i) {
                ttype[tfields] = get_ttype(i);
                tform[tfields] = get_tform(i);
                tunit[tfields] = get_tunit(i);
                if (ttype[tfields] != NULL && tform[tfields] != NULL && 
                    tunit[tfields] != NULL)
                    tfields++;
            }
        }

        // Create FITS table
        status = __ffcrtb(FPTR(m_fitsfile), m_type, m_rows, tfields, ttype, tform,
                          tunit, NULL, &status);
        if (status != 0)
            throw GException::fits_error(G_DATA_SAVE, status);

        // De-allocate column definition arrays
        if (m_cols > 0) {
            for (int i = 0; i < m_cols; ++i) {
                if (ttype[i] != NULL) delete [] ttype[i];
                if (tform[i] != NULL) delete [] tform[i];
                if (tunit[i] != NULL) delete [] tunit[i];
            }
            if (ttype != NULL) delete [] ttype;
            if (ttype != NULL) delete [] tform;
            if (ttype != NULL) delete [] tunit;
        }

        // Connect all existing columns to FITS table
        if (m_columns != NULL) {
            for (int i = 0; i < m_cols; ++i) {
                if (m_columns[i] != NULL) {
                    FPTR_COPY(m_columns[i]->m_fitsfile, m_fitsfile);
                    m_columns[i]->m_colnum = i+1;
                }
            }
        }

        // Debug option: Signal table creation
        #if defined(G_DEBUG_SAVE)
        std::cout << "GFitsTable::save: created new table" << std::endl;
        #endif

    }
    
    // ... otherwise we signal a FITS error
    else if (status != 0) {
        throw GException::fits_error(G_DATA_SAVE, status);
    }

    // Determine number of columns in table
    int num_cols = 0;
    status = __ffgncl(FPTR(m_fitsfile), &num_cols, &status);
    if (status != 0) {
        throw GException::fits_error(G_DATA_SAVE, status);
    }
    
    // Debug option: Log number of columns in FITS table
    #if defined(G_DEBUG_SAVE)
    std::cout << "GFitsTable::save: FITS table contains ";
    std::cout << num_cols << " columns." << std::endl;
    #endif

    // If we have no columns in the table then delete all columns from
    // FITS table
    if (m_columns == NULL && num_cols > 0) {
        for (int i = 0; i < num_cols; ++i) {
            status = __ffdcol(FPTR(m_fitsfile), i, &status);
            if (status != 0) {
                throw GException::fits_error(G_DATA_SAVE, status);
            }
        }
    }

    // ... otherwise update the FITS table
    else {

        // Determine number of rows in table
        long num_rows = 0;
        status        = __ffgnrw(FPTR(m_fitsfile), &num_rows, &status);
        if (status != 0) {
            throw GException::fits_error(G_DATA_SAVE, status);
        }

        // Debug option: Log number of rows in FITS table
        #if defined(G_DEBUG_SAVE)
        std::cout << "GFitsTable::save: FITS table contains ";
        std::cout << num_rows << " rows." << std::endl;
        #endif

        // If the table length differs from number of rows in the FITS file
        // then readjust FITS table length. We do this by adding or
        // deleting rows at the end of the table as we anyways rewrite the
        // entire table later
        if (m_rows > num_rows) {
        
            // Insert rows at the end of the table
            long long firstrow = num_rows;
            long long nrows    = m_rows - num_rows;
            status = __ffirow(FPTR(m_fitsfile), firstrow, nrows, &status);
            if (status != 0) {
                throw GException::fits_error(G_DATA_SAVE, status);
            }
            
            // Debug option: Log row adding
            #if defined(G_DEBUG_SAVE)
            std::cout << "GFitsTable::save: Added " << nrows;
            std::cout << " rows to FITS table." << std::endl;
            #endif
            
        }
        else if (m_rows < num_rows) {

            // Delete rows at the end of the table
            long long firstrow = num_rows;
            long long nrows    = num_rows - m_rows;
            status = __ffdrow(FPTR(m_fitsfile), firstrow, nrows, &status);
            if (status != 0) {
                throw GException::fits_error(G_DATA_SAVE, status);
            }
            
            // Debug option: Log row adding
            #if defined(G_DEBUG_SAVE)
            std::cout << "GFitsTable::save: Deleted " << nrows;
            std::cout << " rows from FITS table." << std::endl;
            #endif
            
        }
        
        // Update all columns. The 'm_colnum' field specifies where in the
        // FITS file the column resides. If 'm_colnum=0' then we have a new
        // column that does not yet exist. In this case we append a new column
        // to the FITS file.
        for (int i = 0; i < m_cols; ++i) {

            // Only consider valid columns
            if (m_columns[i] != NULL) {

                // If column has no correspondance than add new column in
                // FITS table and link column to table.
                if (m_columns[i]->m_colnum == 0) {

                    // Increment number of columns in FITS file
                    num_cols++;

                    // Append column to FITS file
                    status = __fficol(FPTR(m_fitsfile), num_cols, get_ttype(i),
                                      get_tform(i), &status);
                    if (status != 0) {
                        throw GException::fits_error(G_DATA_SAVE, status);
                    }

                    // Connect all column to FITS table by copying over the
                    // FITS file pointer.
                    FPTR_COPY(m_columns[i]->m_fitsfile, m_fitsfile);
                    m_columns[i]->m_colnum = num_cols;

                } // endif: column appended to FITS file

                // Now write column into FITS file (only if length is positive)
                if (m_columns[i]->length() > 0) {
                    m_columns[i]->save();
                }

            } // endif: column was valid
        } // endfor: looped over all table columns

        // Delete all unused columns from FITS file. We do this from last to
        // first so that the column numbers remain valid. Also note that
        // FITS column counting starts from 1.
        for (int colnum = num_cols; colnum > 0; --colnum) {

            // Get column name from FITS file
            char keyname[10];
            char value[80];
            sprintf(keyname, "TTYPE%d", colnum);
            status = __ffgkey(FPTR(m_fitsfile), keyname, value, NULL, &status);
            if (status != 0) {
                throw GException::fits_error(G_DATA_SAVE, status);
            }
            value[strlen(value)-1] = '\0';
            std::string colname = strip_whitespace(&(value[1]));
            
            // Check if this column is actually in our list of columns
            bool used = false;
            for (int i = 0; i < m_cols; ++i) {
                if (m_columns[i]           != NULL &&
                    m_columns[i]->length() > 0 &&
                    m_columns[i]->name()   == colname) {
                    used = true;
                    break;
                }
            }

            // If column is not used then delete it now from FITS table
            if (!used) {

                // Delete column
                status = __ffdcol(FPTR(m_fitsfile), colnum, &status);
                if (status != 0) {
                    throw GException::fits_error(G_DATA_SAVE, status);
                }

                // Debug option: Log column deletion
                #if defined(G_DEBUG_SAVE)
                std::cout << "GFitsTable::save: Deleted obsolete column ";
                std::cout << value << " from FITS table." << std::endl;
                #endif
                
            } // endif: deleted column

        } // endfor: Looped over all FITS columns

    } // endelse: FITS table has been updated

    // Now update the header for all columns (unit and TDIM information)
    for (int i = 0; i < m_cols; ++i) {

        // Only consider valid columns
        if (m_columns[i] != NULL) {

            // Get column number
            int colnum = m_columns[i]->m_colnum;

            // Update column units if available
            if (m_columns[i]->unit().length() > 0) {

                // Build keyname
                std::string keyname = "TUNIT"+str(colnum);

                // Update header card
                card(keyname, m_columns[i]->unit(), "physical unit of field");
            }

            // Write TDIM keyword if available
            if (m_columns[i]->dim().size() > 0) {
        
                // Build keyname
                std::string keyname = "TDIM"+str(colnum);
            
                // Build value string
                std::string value = "("+str(m_columns[i]->dim()[0]);
                for (int k = 1; k < m_columns[i]->dim().size(); ++k) {
                    value += ","+str(m_columns[i]->dim()[k]);
                }
                value += ")";
                
                // Update header card
                card(keyname, value, "dimensions of field");
            
            } // endif: wrote TDIM keyword

        } // endif: column was valid

    } // endfor: looped over all columns

    // Debug definition: Dump method exit
    #if defined(G_DEBUG_SAVE)
    std::cout << "GFitsTable::save: exit" << std::endl;
    #endif

    // Return
    return;
}
Exemple #8
0
/***********************************************************************//**
 * @brief Open Table
 *
 * @param[in] vptr FITS file pointer.
 *
 * @exception GException::fits_hdu_not_found
 *            Specified HDU not found in FITS file.
 * @exception GException::fits_error
 *            A CFITSIO error occured during loading the table.
 * @exception GException::fits_unknown_coltype
 *            FITS column of unsupported type has been found in the FITS file.
 * @exception GException::fits_inconsistent_tdim
 *            The TDIM information provided in the header is inconsistent
 *            with the size of the column.
 *
 * This method loads a description of the table into memory. Column data are
 * not loaded at this point to save memory. They will be loaded on request
 * later. 
 ***************************************************************************/
void GFitsTable::data_open(void* vptr)
{
    // Move to HDU
    int status = 0;
    status     = __ffmahd(FPTR(vptr), (FPTR(vptr)->HDUposition)+1, NULL, &status);
    if (status != 0)
        throw GException::fits_hdu_not_found(G_DATA_OPEN, (FPTR(vptr)->HDUposition)+1,
                                             status);

    // Save FITS file pointer
    FPTR_COPY(m_fitsfile, vptr);

    // Determine number of rows in table
    long nrows  = 0;
    status      = __ffgnrw(FPTR(m_fitsfile), &nrows, &status);
    if (status != 0)
        throw GException::fits_error(G_DATA_OPEN, status);
    else
        m_rows = (int)nrows;

    // Determine number of columns in table
    status = __ffgncl(FPTR(m_fitsfile), &m_cols, &status);
    if (status != 0)
        throw GException::fits_error(G_DATA_OPEN, status);

    // Allocate and initialise memory for column pointers. Note that this
    // initialisation is needed to allow for a clean free_members() call
    // in case of any exception.
    if (m_columns != NULL) delete [] m_columns;
    m_columns = new GFitsTableCol*[m_cols];
    for (int i = 0; i < m_cols; ++i)
        m_columns[i] = NULL;

    // Get table column information
    int  typecode = 0;
    long repeat   = 0;
    long width    = 0;
    for (int i = 0; i < m_cols; ++i) {

        // Get column name
        char keyname[10];
        char value[80];
        sprintf(keyname, "TTYPE%d", i+1);
        status = __ffgkey(FPTR(m_fitsfile), keyname, value, NULL, &status);
        if (status != 0)
            throw GException::fits_error(G_DATA_OPEN, status);
        value[strlen(value)-1] = '\0';

        // Get column definition
        status = __ffgtcl(FPTR(m_fitsfile), i+1, &typecode, &repeat, &width,
                          &status);
        if (status != 0)
            throw GException::fits_error(G_DATA_OPEN, status);

        // Check for unsigned columns
        unsigned long offset = 0;
        sprintf(keyname, "TZERO%d", i+1);
        status = __ffgky(FPTR(m_fitsfile), __TULONG, keyname, &offset, NULL, &status);
        if (status == 0) {
            if (typecode == __TSHORT && offset == 32768u)
                typecode = __TUSHORT;
            else if (typecode == __TLONG && offset == 2147483648u)
                typecode = __TULONG;
            else if (typecode == __TINT && offset == 2147483648u)
                typecode = __TUINT;
            else {
                std::ostringstream message;
                message << ", but column " << value << " has typecode " << typecode
                        << " and unexpected associated TZERO=" << offset << ".";
                throw GException::fits_error(G_DATA_OPEN, 0, message.str());
            }
        }
        else
            status = 0;

        // Get column unit (optional, leave blank if not found)
        char unit[80];
        sprintf(keyname, "TUNIT%d", i+1);
        status = __ffgkey(FPTR(m_fitsfile), keyname, unit, NULL, &status);
        if (status != 0) {
            status = 0;
            unit[0] = '\0';
            unit[1] = '\0';
        }
        else
            unit[strlen(unit)-1] = '\0';

        // Get column dimension (optional, leave blank if not found)
        char dim[80];
        sprintf(keyname, "TDIM%d", i+1);
        status = __ffgkey(FPTR(m_fitsfile), keyname, dim, NULL, &status);
        if (status != 0) {
            status = 0;
            dim[0] = '\0';
            dim[1] = '\0';
        }
        else {
            dim[strlen(dim)-1] = '\0';
        }
        
        // If found, extract column dimension into vector array of integers
        std::vector<int> vdim;
        std::string      sdim = strip_chars(strip_whitespace(&(dim[1])),"()");
        if (sdim.length() > 0) {
            std::vector<std::string> elements = split(sdim, ",");
            for (int k = 0; k < elements.size(); ++k) {
                vdim.push_back(toint(elements[k]));
            }
        }

        // Allocate column
        m_columns[i] = alloc_column(typecode);
        if (m_columns[i] == NULL) {
            std::ostringstream colname;
            colname << value;
            throw GException::fits_unknown_coltype(G_DATA_OPEN, colname.str(), typecode);
        }

        // Store column definition
        m_columns[i]->name(strip_whitespace(&(value[1])));
        m_columns[i]->unit(strip_whitespace(&(unit[1])));
        m_columns[i]->dim(vdim);
        m_columns[i]->m_colnum = i+1;
        m_columns[i]->m_type   = typecode;
        m_columns[i]->m_repeat = repeat;
        m_columns[i]->m_width  = width;
        m_columns[i]->m_length = m_rows;
        m_columns[i]->connect(FPTR(m_fitsfile));

        // Extract column vector size
        if (m_columns[i]->m_repeat == 1) { // ASCII tables
            m_columns[i]->m_number = 1;
        }
        else {                             // Binary tables
            if (typecode == __TSTRING) {
                m_columns[i]->m_number = m_columns[i]->m_repeat /
                                         m_columns[i]->m_width;
            }
            else {
                m_columns[i]->m_number = m_columns[i]->m_repeat;
            }
        }
        
        // If TDIM information was set then check its consistency
        if (!vdim.empty()) {
            
            // Compute expectation
            int num = vdim[0];
            for (int k = 1; k < vdim.size(); ++k) {
                num *= vdim[k];
            }
                
            // Compare with real size
            if (num != m_columns[i]->m_number) {
                throw GException::fits_inconsistent_tdim(G_DATA_OPEN,
                                                         vdim,
                                                         m_columns[i]->m_number);
            }
                
        } // endif: Valid TDIM information was found

    } // endfor: looped over all columns

    // Return
    return;
}
Exemple #9
0
/***********************************************************************//**
 * @brief Save FITS image
 *
 * @param[in] datatype Datatype of pixels to be saved
 * @param[in] pixels Pixel array to be saved
 *
 * @exception GException::fits_file_not_open
 *            No FITS file has been opened.
 * @exception GException::fits_error
 *            FITS error.
 *
 * Save image pixels into FITS file. In case that the HDU does not exist it
 * is created. In case that the pixel array is empty no data are saved; all
 * image pixels will be empty in this case.
 ***************************************************************************/
void GFitsImage::save_image(int datatype, const void* pixels)
{
    // Throw an exception if FITS file is not open
    if (FPTR(m_fitsfile)->Fptr == NULL) {
        throw GException::fits_file_not_open(G_SAVE_IMAGE, 
              "Open file before saving the image.");
    }

    // Move to HDU. We use here an explicit cfitsio moveto function since we
    // want to recover the error code ...
    int status = 0;
    int type   = 0;
    status     = __ffmahd(FPTR(m_fitsfile), m_hdunum+1, &type, &status);

    // If move was successful but HDU type in file differs from HDU type
    // of object then replace the HDU in the file
    if (status == 0 && type != exttype()) {
        status = __ffdhdu(FPTR(m_fitsfile), NULL, &status);
        if (status != 0) {
            throw GException::fits_error(G_SAVE_IMAGE, status);
        }
        status = __ffiimg(FPTR(m_fitsfile), m_bitpix, m_naxis, m_naxes, &status);
        //status = __ffiimgll(FPTR(m_fitsfile), m_bitpix, m_naxis, m_naxes, &status);
        if (status != 0) {
            throw GException::fits_error(G_SAVE_IMAGE, status);
        }
    }

    // If HDU does not yet exist in file then create it now
    if (status == 107) {
        status = 0;
        status = __ffcrim(FPTR(m_fitsfile), m_bitpix, m_naxis, m_naxes, &status);
        if (status != 0) {
            throw GException::fits_error(G_SAVE_IMAGE, status);
        }
    }
    else if (status != 0) {
        throw GException::fits_error(G_SAVE_IMAGE, status);
    }

    // If HDU seems to be empty then create it now. This is only needed for the
    // primary HDU, since __ffmahd gives no error if the primary HDU is empty.
    // By checking the number of keywords in the HDU we detect an empty HDU ...
    int num = 0;
    status  = __ffghsp(FPTR(m_fitsfile), &num, NULL, &status);
    if (status != 0) {
        throw GException::fits_error(G_SAVE_IMAGE, status);
    }
    if (num == 0) {
        status = __ffcrim(FPTR(m_fitsfile), m_bitpix, m_naxis, m_naxes, &status);
        if (status != 0) {
            throw GException::fits_error(G_SAVE_IMAGE, status);
        }
    }

    // Make sure that the image on disk has the right size by resizing it
    status = __ffrsim(FPTR(m_fitsfile), m_bitpix, m_naxis, m_naxes, &status);
    if (status != 0) {
        throw GException::fits_error(G_SAVE_IMAGE, status);
    }

    // Save the image pixels (if there are some ...)
    if (m_naxis > 0 && pixels != NULL) {
        long* fpixel = new long[m_naxis];
        long* lpixel = new long[m_naxis];
        for (int i = 0; i < m_naxis; ++i) {
            fpixel[i] = 1;
            lpixel[i] = m_naxes[i];
        }
        status = __ffpss(FPTR(m_fitsfile), datatype, fpixel, lpixel,
                         (void*)pixels, &status);
        delete [] fpixel;
        delete [] lpixel;
        if (status != 0) {
            throw GException::fits_error(G_SAVE_IMAGE, status);
        }
    }

    // Return
    return;
}