예제 #1
0
/***********************************************************************//**
 * @brief Read Auxiliary Response File
 *
 * @param[in] table ARF FITS table.
 *
 * Reads the Auxiliary Response File from a FITS table. The true energy
 * boundaries are expected in the `ENERG_LO` and `ENERG_HI` columns, the
 * response information is expected in the `SPECRESP` column.
 *
 * The method will analyze the unit of the `SPECRESP` column, and if either
 * `m^2` or `m2` are encountered, multiply the values of the column by
 * \f$10^4\f$ to convert the response into units of \f$cm^2\f$. Units of the
 * `ENERG_LO` and `ENERG_HI` columns are also interpreted for conversion.
 *
 * See
 * http://heasarc.gsfc.nasa.gov/docs/heasarc/caldb/docs/memos/cal_gen_92_002/cal_gen_92_002.html#tth_sEc4
 * for details about the Auxiliary Response File format.
 ***************************************************************************/
void GArf::read(const GFitsTable& table)
{
    // Clear members
    clear();

    // Get pointer to data columns
    const GFitsTableCol* energy_lo = table["ENERG_LO"];
    const GFitsTableCol* energy_hi = table["ENERG_HI"];
    const GFitsTableCol* specresp  = table["SPECRESP"];

    // Determine effective area conversion factor. Internal
    // units are cm^2
    std::string u_specresp =
        gammalib::tolower(gammalib::strip_whitespace(specresp->unit()));
    double      c_specresp = 1.0;
    if (u_specresp == "m^2" || u_specresp == "m2") {
        c_specresp = 10000.0;
    }

    // Extract number of energy bins
    int num = energy_lo->length();

    // Set energy bins
    for (int i = 0; i < num; ++i) {

        // Append energy bin
        GEnergy emin(energy_lo->real(i), energy_lo->unit());
        GEnergy emax(energy_hi->real(i), energy_hi->unit());
        m_ebounds.append(emin, emax);

        // Append effective area value
        double aeff = specresp->real(i) * c_specresp;
        m_specresp.push_back(aeff);

    } // endfor: looped over energy bins

    // Read any additional columns
    for (int icol = 0; icol < table.ncols(); ++icol) {

        // Fall through if the column is a standard column
        std::string colname(table[icol]->name());
        if ((colname == "ENERG_LO") ||
                (colname == "ENERG_HI") ||
                (colname == "SPECRESP")) {
            continue;
        }

        // Get pointer to column
        const GFitsTableCol* column = table[icol];

        // Set column vector
        std::vector<double> coldata;
        for (int i = 0; i < num; ++i) {
            coldata.push_back(column->real(i));
        }

        // Append column
        append(colname, coldata);

    } // endfor: looped over all additional columns

    // Return
    return;
}
예제 #2
0
/***********************************************************************//**
 * @brief Read spectrum from FITS file
 *
 * @param[in] table FITS table.
 *
 * @exception GMWLException::bad_file_format
 *            Table has invalid format
 *
 * Read spectrum from FITS table. The table is expected to be in one of the
 * three following formats:
 * 2 columns: energy, flux
 * 3 columns: energy, flux, e_flux
 * 4 columns or more:  energy, e_energy, flux, e_flux, ...
 *
 * @todo Investigate whether we can exploit UCDs for identifying the correct
 * columns or for determining the units.
 ***************************************************************************/
void GMWLSpectrum::read_fits(const GFitsTable& table)
{
    // Reset spectrum
    m_data.clear();

    // Initialise column pointers columns
    const GFitsTableCol* c_energy     = NULL;
    const GFitsTableCol* c_energy_err = NULL;
    const GFitsTableCol* c_flux       = NULL;
    const GFitsTableCol* c_flux_err   = NULL;

    // Extract column pointers
    if (table.ncols() == 2) {
        c_energy = table[0];
        c_flux   = table[1];
    }
    else if (table.ncols() == 3) {
        c_energy   = table[0];
        c_flux     = table[1];
        c_flux_err = table[2];
    }
    else if (table.ncols() > 3) {
        c_energy     = table[0];
        c_energy_err = table[1];
        c_flux       = table[2];
        c_flux_err   = table[3];
    }
    else {
        throw GMWLException::bad_file_format(G_READ_FITS,
                             "At least 2 columns are expected is table \""+
                              table.extname()+"\".");
    }

    // Read spectral points and add to spectrum
    for (int i = 0; i < table.nrows(); ++i) {
        GMWLDatum datum;
        if (c_energy     != NULL) {
            datum.m_eng = conv_energy(c_energy->real(i), c_energy->unit());
        }
        if (c_energy_err != NULL) {
            datum.m_eng_err = conv_energy(c_energy_err->real(i), c_energy->unit());
        }
        if (c_flux       != NULL) {
            datum.m_flux = conv_flux(datum.m_eng, c_flux->real(i), c_flux->unit());
        }
        if (c_flux_err   != NULL) {
            datum.m_flux_err = conv_flux(datum.m_eng, c_flux_err->real(i), c_flux_err->unit());
        }
        m_data.push_back(datum);
    }

    // Get telescope name
    if (table.has_card("TELESCOP")) {
        m_telescope = table.string("TELESCOP");
    }
    else {
        m_telescope = "unknown";
    }

    // Get instrument name
    if (table.has_card("INSTRUME")) {
        m_instrument = table.string("INSTRUME");
    }
    else {
        m_instrument = "unknown";
    }

    // Set energy boundaries
    set_ebounds();

    // Return
    return;
}
예제 #3
0
/***********************************************************************//**
 * @brief Read column names from FITS HDU
 *
 * @param[in] hdu Response table HDU.
 *
 * @exception GCTAException::bad_rsp_table_format
 *            Bad response table format encountered in FITS HDU.
 *
 * Read the response table column names from the HDU. Column names
 * terminating with "_LO" and "_HI" define the parameter space axes, while
 * all other column names define response parameter data cubes. It is
 * assumed that parameter space axes are given in subsequent order, with
 * the first column corresponding to the lower bin boundaries of the first
 * axis. Lower bin boundaries are indicated by the "_LO" termination. Upper
 * bin boundaries are assumed to follow immediately the lower bin boundaires
 * and are designated by the "_HI" termination.
 *
 * This method sets the following members:
 *    m_colname_lo - Column names of lower boundaries
 *    m_colname_hi - Column names of upper boundaries
 *    m_colname_par - Column names of parameters
 *    m_naxes - Number of axes
 *    m_npars - Number of parameters
 *
 * In case that the HDU pointer is not valid (NULL), this method clears the
 * column names and does nothing else.
 *
 * @todo Implement exceptions for invalid HDU format
 ***************************************************************************/
void GCTAResponseTable::read_colnames(const GFitsTable& hdu)
{
    // Clear column name arrays
    m_naxes = 0;
    m_npars = 0;
    m_colname_lo.clear();
    m_colname_hi.clear();
    m_colname_par.clear();
    
    // Initialise search mode. There are three search modes:
    // 0 - we're looking for the next axis by searching for a column
    //     terminating with "_LO"
    // 1 - we're looking for the upper boundary of an axis, terminating
    //     with "_HI"
    // 2 - we're looking for a parameter column
    int         mode = 0;
    std::string lo_column;
    std::string next_column;

    // Extract column names for all axes
    for (int i = 0; i < hdu.ncols(); ++i) {

        // Get column name
        std::string colname = hdu[i]->name();

        // If we search for a "_LO" column, check if we have one. If one
        // is found, change the search mode to 1 and set the expected name
        // for the "_HI" column. If none is found, change the search
        // mode to 2 since from now on we should only have parameter
        // columns.
        if (mode == 0) {
            size_t pos = colname.rfind("_LO");
            if (pos != std::string::npos) {
                mode        = 1;
                lo_column   = colname;
                next_column = colname.substr(0, pos) + "_HI";
            }
            else {
                if (colname.rfind("_HI") != std::string::npos) {
                    std::string message = "Column '" +
                                          colname +
                                          "' encountered without"
                                          " preceeding '_LO' column.";
                    throw GCTAException::bad_rsp_table_format(G_READ_COLNAMES,
                                                              message);
                }
                else {
                    mode = 2;
                    m_colname_par.push_back(colname);
                }
            }
        }

        // If we search for a "_HI" column, check if we have the
        // expected column name. If this is the case, switch back to
        // search mode 0 to get the next "_LO" column. Otherwise
        // throw an exception.
        else if (mode == 1) {
            if (colname == next_column) {
                mode = 0;
                m_colname_lo.push_back(lo_column);
                m_colname_hi.push_back(next_column);
            }
            else {
                std::string message = "Expected column '" +
                                      next_column +
                                      "' not found. '_HI' columns have"
                                      " to be placed immediately after"
                                      " corresponding '_LO' columns.";
                throw GCTAException::bad_rsp_table_format(G_READ_COLNAMES,
                                                          message);
            }
        }

        // If we search for a parameter column, make sure that we have
        // neither a "_LO" nor a "_HI" column.
        else {
            if (colname.rfind("_LO") != std::string::npos) {
                std::string message = "Column '" +
                                      colname +
                                      "' found. All '_LO' columns have to"
                                      " be placed before the parameter"
                                      " columns.";
                throw GCTAException::bad_rsp_table_format(G_READ_COLNAMES,
                                                          message);
            }
            else if (colname.rfind("_HI") != std::string::npos) {
                std::string message = "Column '" +
                                      colname +
                                      "' found. All '_HI' columns have to"
                                      " be placed before the parameter"
                                      " columns.";
                throw GCTAException::bad_rsp_table_format(G_READ_COLNAMES,
                                                          message);
            }
            else {
                m_colname_par.push_back(colname);
            }
        }

    } // endfor: looped over all column names

    // Store number of axes
    m_naxes = m_colname_lo.size();

    // Store number of parameters
    m_npars = m_colname_par.size();

    // Return
    return;
}