/***********************************************************************//** * @brief Read GTIs from HDU. * * @param[in] hdu GTI table. * * Reads the Good Time Intervals from the GTI extension. Since the Fermi * LAT Science Tools do not set corrently the time reference for source * maps, the method automatically adds this missing information so that * the time reference is set correctly. The time reference that is assumed * for Fermi LAT is * * MJDREFI 51910 * MJDREFF 0.00074287037037037 * ***************************************************************************/ void GLATEventCube::read_gti(const GFitsTable& hdu) { // Work on a local copy of the HDU to make the kluge work GFitsTable* hdu_local = hdu.clone(); // Kluge: modify HDU table in case that the MJDREF header keyword is // blank. This happens for Fermi LAT source maps since the Science // Tools do not properly write out the time reference. We hard-code // here the Fermi LAT time reference to circumvent the problem. if (hdu.has_card("MJDREF")) { if (gammalib::strip_whitespace(hdu.string("MJDREF")).empty()) { hdu_local->header().remove("MJDREF"); hdu_local->card("MJDREFI", 51910, "Integer part of MJD reference"); hdu_local->card("MJDREFF", 0.00074287037037037, "Fractional part of MJD reference"); } } // Read Good Time Intervals m_gti.read(*hdu_local); // Set time set_times(); // Return return; }
/***********************************************************************//** * @brief Read effective area from FITS table * * @param[in] hdu FITS table. * * @exception GLATException::inconsistent_response * Inconsistent response table encountered * * The effective area is converted into units of cm2. ***************************************************************************/ void GLATAeff::read_aeff(const GFitsTable& hdu) { // Clear array m_aeff.clear(); // Get energy and cos theta bins in response table m_aeff_bins.read(hdu); // Set minimum cos(theta) m_min_ctheta = m_aeff_bins.costheta_lo(0); // Continue only if there are effective area bins int size = m_aeff_bins.size(); if (size > 0) { // Allocate arrays m_aeff.reserve(size); // Get pointer to effective area column const GFitsTableCol* ptr = hdu["EFFAREA"]; // Check consistency of effective area table int num = ptr->number(); if (num != size) { throw GLATException::inconsistent_response(G_READ_AEFF, num, size); } // Copy data and convert from m2 into cm2 for (int i = 0; i < size; ++i) { m_aeff.push_back(ptr->real(0,i) * 1.0e4); } } // endif: there were effective area bins // Set detector section using the DETNAM keyword in the HDU std::string detnam = gammalib::strip_whitespace(hdu.string("DETNAM")); m_front = (detnam == "FRONT"); m_back = (detnam == "BACK"); // Return return; }
/***********************************************************************//** * @brief Load livetime cube from FITS file * * @param[in] table FITS table. ***************************************************************************/ void GLATLtCubeMap::read(const GFitsTable& table) { // Clear object clear(); // Load skymap m_map.read(table); // Set costheta binning scheme std::string scheme = gammalib::strip_whitespace(gammalib::toupper(table.string("THETABIN"))); m_sqrt_bin = (scheme == "SQRT(1-COSTHETA)"); // Read attributes m_num_ctheta = table.integer("NBRBINS"); m_num_phi = table.integer("PHIBINS"); m_min_ctheta = table.real("COSMIN"); // Return return; }
/***********************************************************************//** * @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; }
/***********************************************************************//** * @brief Read LAT events from FITS table. * * @param[in] table Event table. * * Read the LAT events from the event table. ***************************************************************************/ void GLATEventList::read_events(const GFitsTable& table) { // Clear existing events m_events.clear(); // Allocate space for keyword name char keyword[10]; // Extract number of events in FT1 file int num = table.integer("NAXIS2"); // If there are events then load them if (num > 0) { // Reserve data m_events.reserve(num); // Get column pointers const GFitsTableCol* ptr_time = table["TIME"]; const GFitsTableCol* ptr_energy = table["ENERGY"]; const GFitsTableCol* ptr_ra = table["RA"]; const GFitsTableCol* ptr_dec = table["DEC"]; const GFitsTableCol* ptr_theta = table["THETA"]; const GFitsTableCol* ptr_phi = table["PHI"]; const GFitsTableCol* ptr_zenith = table["ZENITH_ANGLE"]; const GFitsTableCol* ptr_azimuth = table["EARTH_AZIMUTH_ANGLE"]; const GFitsTableCol* ptr_eid = table["EVENT_ID"]; const GFitsTableCol* ptr_rid = table["RUN_ID"]; const GFitsTableCol* ptr_recon = table["RECON_VERSION"]; const GFitsTableCol* ptr_calib = table["CALIB_VERSION"]; const GFitsTableCol* ptr_class = table["EVENT_CLASS"]; const GFitsTableCol* ptr_conv = table["CONVERSION_TYPE"]; const GFitsTableCol* ptr_ltime = table["LIVETIME"]; // Copy data from columns into GLATEventAtom objects GLATEventAtom event; for (int i = 0; i < num; ++i) { event.m_time.set(ptr_time->real(i), m_gti.reference()); event.m_energy.MeV(ptr_energy->real(i)); event.m_dir.dir().radec_deg(ptr_ra->real(i), ptr_dec->real(i)); event.m_theta = ptr_theta->real(i); event.m_phi = ptr_phi->real(i); event.m_zenith_angle = ptr_zenith->real(i); event.m_earth_azimuth_angle = ptr_azimuth->real(i); event.m_event_id = ptr_eid->integer(i); event.m_run_id = ptr_rid->integer(i); event.m_recon_version = ptr_recon->integer(i); event.m_calib_version[0] = ptr_calib->integer(i,0); event.m_calib_version[1] = ptr_calib->integer(i,1); event.m_calib_version[2] = ptr_calib->integer(i,2); event.m_event_class = ptr_class->integer(i); event.m_conversion_type = ptr_conv->integer(i); event.m_livetime = ptr_ltime->real(i); m_events.push_back(event); } // Extract number of diffuse response labels int num_difrsp = table.integer("NDIFRSP"); // Allocate diffuse response components if (num_difrsp > 0) { // Reserve space m_difrsp_label.reserve(num_difrsp); // Allocate components for (int i = 0; i < num; ++i) { m_events[i].m_difrsp = new double[num_difrsp]; } // Load diffuse columns for (int k = 0; k < num_difrsp; ++k) { // Set keyword name std::sprintf(keyword, "DIFRSP%d", k); // Get DIFRSP label if (table.has_card(std::string(keyword))) { m_difrsp_label.push_back(table.string(std::string(keyword))); } else { m_difrsp_label.push_back("NONE"); } // Get column pointer const GFitsTableCol* ptr_dif = table[std::string(keyword)]; // Copy data from columns into GLATEventAtom objects for (int i = 0; i < num; ++i) { m_events[i].m_difrsp[k] = ptr_dif->real(i); } } // endfor: looped over diffuse columns } // endif: diffuse components found } // endif: events found // Return return; }