/***********************************************************************//** * @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; }
/***********************************************************************//** * @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; }
/***********************************************************************//** * @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; }
/***********************************************************************//** * @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; }
/***********************************************************************//** * @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; }
/***********************************************************************//** * @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; }
/***********************************************************************//** * @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; }
/***********************************************************************//** * @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; }
/***********************************************************************//** * @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; }