48#define G_READ "GCTAEdisp2D::read(GFitsTable&)"
49#define G_MC "GCTAEdisp2D::mc(GRan&, GEnergy&, double&, double&, double&, "\
51#define G_FETCH "GCTAEdisp2D::fetch()"
56#define G_SMOOTH_EDISP_KLUDGE
159 if (
this != &edisp) {
207 const double& zenith,
208 const double& azimuth)
const
352 std::string msg =
"Expected three-dimensional energy dispersion "
353 "response table but found "+
355 " dimensions. Please specify a three-dimensional "
356 "energy dispersion.";
451 table.extname(extname);
487 const double& zenith,
488 const double& azimuth)
const
498 double emin = ebounds.
emin().
TeV();
499 double emax = ebounds.
emax().
TeV();
505 std::string msg =
"No valid energy dispersion information available "
509 "and azimuth angle "+
511 "provide an energy dispersion matrix covering these "
512 "parameters or restrict the parameter space.";
520 if (max_edisp <= 0.0) {
521 std::string msg =
"Energy dispersion matrix is empty. Please provide "
522 "a valid energy dispersion matrix.";
527 double ewidth = emax - emin;
530 const int max_subsequent_zeros = 10;
546 if (zeros > max_subsequent_zeros) {
547 std::string msg =
"No valid energy dispersion information "
548 "available for true photon energy "+
551 " deg and azimuth angle "+
553 " deg. Either provide an energy "
554 "dispersion matrix covering these "
555 "parameters or restrict the parameter "
565 ftest = ran.
uniform() * max_edisp;
591 const double& zenith,
592 const double& azimuth)
const
622 while ((high-low) > 1) {
623 int mid = (low+high) / 2;
660 const double& zenith,
661 const double& azimuth)
const
686 double ereco_TeV = ereco.
TeV();
691 while ((high-low) > 1) {
692 int mid = (low+high) / 2;
744 std::string msg =
"File \""+
m_filename+
"\" not found. Cannot "
745 "fetch energy dispersion. Maybe the file has "
746 "been deleted in the meantime.";
756 bool has_exception =
false;
761 #pragma omp critical(GCTAEdisp2D_fetch)
773 if (extname.empty()) {
788 has_exception =
true;
794 std::string msg =
"Unable to load energy dispersion from "
837 const double& theta)
const
849 double migra_min = ereco_min /
etrue;
850 double migra_max = ereco_max /
etrue;
885 double x1 = migra_min;
886 double f1 =
table_value(base_ll, base_lr, base_rl, base_rr,
895 for (
int i = 0, offset = 0; i < migra_nodes.
size(); ++i, offset += stride) {
898 if (migra_nodes[i] <= migra_min) {
904 if (migra_nodes[i] > migra_max) {
906 f2 =
table_value(base_ll, base_lr, base_rl, base_rr,
916 f2 =
table_value(base_ll, base_lr, base_rl, base_rr,
924 prob += 0.5 * (f1 + f2) * (x2 - x1);
931 if (migra_nodes[i] > migra_max) {
939 if (x1 < migra_max) {
941 f2 =
table_value(base_ll, base_lr, base_rl, base_rr,
946 prob += 0.5 * (f1 + f2) * (x2 - x1);
971 result.append(
"=== GCTAEdisp2D ===");
1188 const double& zenith,
1189 const double& azimuth)
const
1195 const double eps = 1.0e-12;
1202 for (
int ietrue = 0; ietrue < netrue; ++ietrue) {
1208 double ereco_min = 0.0;
1209 double ereco_max = 0.0;
1210 bool found_min =
false;
1211 bool found_max =
false;
1214 for (
int imigra = 0; imigra < nmigra; ++imigra) {
1236 for (
int imigra = nmigra-1; imigra >= 0; imigra--) {
1259 if (!found_min || !found_max) {
1267 emin.
TeV(ereco_min);
1268 emax.
TeV(ereco_max);
1296 const double& zenith,
1297 const double& azimuth)
const
1307 const double eps = 1.0e-12;
1314 for (
int iereco = 0; iereco < nereco; ++iereco) {
1322 bool found_min =
false;
1323 bool found_max =
false;
1326 for (
int imigra = 0; imigra < nmigras; ++imigra) {
1352 for (
int imigra = nmigras-1; imigra >= 0; imigra--) {
1379 if (!found_min || !found_max) {
1439 #if defined(G_SMOOTH_EDISP_KLUDGE)
1452 #if defined(G_SMOOTH_EDISP_SAVE_TEST)
1453 this->
save(
"test_edisp.fits",
true);
1510 for (
int itheta = 0, index = 0; itheta < ntheta; ++itheta) {
1513 for (
int ietrue = 0; ietrue < netrue; ++ietrue, ++index) {
1523 double maximum = 0.0;
1524 for (
int imigra = 0, i = offset; imigra < nmigra; ++imigra, i += stride) {
1526 if (value > maximum) {
1557 const double& theta)
const
1560 double max_edisp = 0.0;
1577 int inx_left = theta_nodes.
inx_left() * netrue;
1578 int inx_right = theta_nodes.
inx_right() * netrue;
1579 int index_1 = inx_left + etrue_nodes.
inx_left();
1580 int index_2 = inx_left + etrue_nodes.
inx_right();
1581 int index_3 = inx_right + etrue_nodes.
inx_left();
1582 int index_4 = inx_right + etrue_nodes.
inx_right();
1589 if (max_edisp_2 > max_edisp) {
1590 max_edisp = max_edisp_2;
1592 if (max_edisp_3 > max_edisp) {
1593 max_edisp = max_edisp_3;
1595 if (max_edisp_4 > max_edisp) {
1596 max_edisp = max_edisp_4;
1641 for (
int pass = 0; pass < 2; ++pass) {
1644 std::vector<double> sums;
1645 sums.reserve(theta_size*etrue_size);
1648 for (
int i_theta = 0; i_theta < theta_size; ++i_theta) {
1654 for (
int i_etrue = 0; i_etrue < etrue_size; ++i_etrue) {
1666 for (
int i = 0; i < ebounds.
size(); ++i) {
1677 integral.
eps(1.0e-6);
1685 sums.push_back(
sum);
1692 for (
int i_theta = 0, inx = 0; i_theta < theta_size; ++i_theta) {
1693 for (
int i_etrue = 0; i_etrue < etrue_size; ++i_etrue, ++inx) {
1694 double sum = sums[inx];
1698 for (
int k = 0, i = offset; k < migra_size; ++k, i += stride) {
1722 const int& itheta)
const
1781 const double& wgt_el,
1782 const double& wgt_er,
1783 const double& wgt_tl,
1784 const double& wgt_tr,
1785 const int& offset)
const
1788 int inx_ll = base_ll + offset;
1789 int inx_lr = base_lr + offset;
1790 int inx_rl = base_rl + offset;
1791 int inx_rr = base_rr + offset;
1822 const double& wgt_el,
1823 const double& wgt_er,
1824 const double& wgt_tl,
1825 const double& wgt_tr,
1826 const double& migra)
const
1838 double value_left =
table_value(base_ll, base_lr, base_rl, base_rr,
1839 wgt_el, wgt_er, wgt_tl, wgt_tr,
1843 double value_right =
table_value(base_ll, base_lr, base_rl, base_rr,
1844 wgt_el, wgt_er, wgt_tl, wgt_tr,
1848 double value = migra_nodes.
wgt_left() * value_left +
1873 int npix = netrue * nmigra;
1876 for (
int itheta = 0; itheta < ntheta; ++itheta) {
1890 for (
int ietrue = 0; ietrue < netrue; ++ietrue) {
1891 if (total(ietrue) < 0.0) {
1892 total(ietrue) = 0.0;
1897 for (
int ietrue = 0; ietrue < netrue; ++ietrue) {
1900 if (total(ietrue) > 0.0) {
1906 int ibase = itheta * npix + ietrue;
1907 if ((mean(ietrue) > 0.0) && (rms(ietrue))) {
1908 for (
int imigra = 0, i = ibase; imigra < nmigra; ++imigra, i += netrue) {
1913 for (
int imigra = 0, i = ibase; imigra < nmigra; ++imigra, i += netrue) {
1922 int ibase = itheta * npix + ietrue;
1923 for (
int imigra = 0, i = ibase; imigra < nmigra; ++imigra, i += netrue) {
1952 const double& limit)
const
1958 double nstep = double(nstop - nstart)/double(array.
size());
1961 for (
int i = 0; i < array.
size(); ++i) {
1962 int nodes = nstart + int(i*nstep);
1967 return smoothed_array;
1987 const double& limit)
const
1990 double mean_x = 0.0;
1991 double mean_y = 0.0;
1992 int ileft = inx - 1;
1993 int iright = inx + 1;
1998 std::vector<double> x_vals;
1999 std::vector<double> y_vals;
2002 while (nleft < nodes) {
2006 if (array(ileft) > limit) {
2007 double x = double(ileft);
2008 double y = array(ileft);
2009 x_vals.push_back(x);
2010 y_vals.push_back(y);
2019 while (nright < 2*nodes-nleft) {
2020 if (iright >= array.
size()) {
2023 if (array(iright) > limit) {
2024 double x = double(iright);
2025 double y = array(iright);
2026 x_vals.push_back(x);
2027 y_vals.push_back(y);
2036 while (nleft < 2*nodes-nright) {
2040 if (array(ileft) > limit) {
2041 double x = double(ileft);
2042 double y = array(ileft);
2043 x_vals.push_back(x);
2044 y_vals.push_back(y);
2053 double total = double(nleft+nright);
2060 double beta_nom = 0.0;
2061 double beta_denom = 0.0;
2062 for (
int i = 0; i < x_vals.size(); ++i) {
2063 double x = x_vals[i];
2064 double y = y_vals[i];
2065 beta_nom += (x - mean_x) * (y - mean_y);
2066 beta_denom += (x - mean_x) * (x - mean_x);
2068 double beta = beta_nom / beta_denom;
2071 double alpha = mean_y - beta * mean_x;
2074 double value = alpha + beta * double(inx);
2100 int npix = netrue * nmigra;
2103 for (
int ietrue = 0; ietrue < netrue; ++ietrue) {
2106 int ibase = itheta * npix + ietrue;
2110 for (
int imigra = 0, i = ibase; imigra < nmigra; ++imigra, i += netrue) {
2115 (*total)(ietrue) =
sum(array);
2118 double mean_value = 0.0;
2119 double rms_value = 0.0;
2123 (*mean)(ietrue) = mean_value;
2124 (*rms)(ietrue) = rms_value;
2157 int nmigra = migras.
size();
2161 for (
int imigra = 0; imigra < nmigra; ++imigra) {
2162 double migra = migras[imigra];
2163 double weight =
migra * array(imigra);
2164 *mean +=
migra * array(imigra);
2165 *rms += weight *
migra;
2166 sum += array(imigra);
2173 *rms -= (*mean) * (*mean);
2174 *rms = std::sqrt(*rms);
2198 const double& total)
const
2209 int nmigra = migras.
size();
2212 double total_gauss = 0.0;
2213 for (
int imigra = 0; imigra < nmigra; ++imigra) {
2214 double arg = (migras[imigra] - mean) / rms;
2215 double value = std::exp(-0.5*arg*arg);
2216 gaussian(imigra) = value;
2217 total_gauss += value;
2221 if (total_gauss > 0.0) {
2222 gaussian *= total / total_gauss;
2270 #if defined(G_NAN_CHECK)
2272 std::cout <<
"*** ERROR: GCTAEdisp2D::edisp_ereco_kern::eval";
2273 std::cout <<
"(log10Ereco=" << log10Ereco <<
"): ";
2274 std::cout <<
" NaN/Inf encountered";
2275 std::cout <<
" (value=" << value;
2276 std::cout <<
")" << std::endl;
CTA 2D energy dispersion class definition.
Definition of support function used by CTA classes.
Exception handler interface definition.
Fast Fourier transformation class interface definition.
Filename class interface definition.
FITS binary table class definition.
FITS table abstract base class interface definition.
FITS file class interface definition.
Integration class interface definition.
Mathematical function definitions.
N-dimensional array class interface definition.
Random number generator class definition.
double sum(const GVector &vector)
Computes vector sum.
double m_theta
Offset angle.
GEnergy m_etrue
True photon energy.
double eval(const double &log10Ereco)
Integration kernel for GCTAEdisp2D::edisp_ereco_kern class.
const GCTAEdisp2D * m_parent
Pointer to parent class.
CTA 2D energy dispersion class.
GEbounds ereco_bounds(const GEnergy &etrue, const double &theta=0.0, const double &phi=0.0, const double &zenith=0.0, const double &azimuth=0.0) const
Return observed energy interval that contains the energy dispersion.
double m_last_theta_etrue
void copy_members(const GCTAEdisp2D &edisp)
Copy class members.
void fetch(void) const
Fetch energy dispersion.
std::vector< double > m_max_edisp
Maximum Edisp.
GEnergy etrue(const int &ietrue) const
Get true energy.
void set_table(void)
Set table.
void init_members(void)
Initialise class members.
double get_max_edisp(const GEnergy &etrue, const double &theta) const
Get maximum energy dispersion value.
void save(const GFilename &filename, const bool &clobber=false) const
Save energy dispersion table into FITS file.
GNdarray gaussian_array(const double &mean, const double &rms, const double &total) const
Return Gaussian approximation of energy dispersion array.
double table_value(const int &base_ll, const int &base_lr, const int &base_rl, const int &base_rr, const double &wgt_el, const double &wgt_er, const double &wgt_tl, const double &wgt_tr, const int &offset) const
Return bi-linearly interpolate table value for given migration bin.
void get_moments(const int &itheta, GNdarray *mean, GNdarray *rms, GNdarray *total) const
Compute moments.
double smoothed_array_value(const int &inx, const GNdarray &array, const int &nodes, const double &limit) const
Get smoothed array value.
double m_migra_min
Minimum migration.
double m_theta_min
Minimum theta (radians)
const GCTAResponseTable & table(void) const
Return response table.
void set_boundaries(void)
Set energy dispersion boundaries.
GFilename filename(void) const
Return filename.
void clear(void)
Clear energy dispersion.
std::vector< GEbounds > m_ereco_bounds
void get_mean_rms(const GNdarray &array, double *mean, double *rms) const
Compute mean and root mean square of migration array.
int m_inx_etrue
True energy index.
double m_theta_max
Maximum theta (radians)
int table_stride(const int &axis) const
Return stride of response table axis.
void load(const GFilename &filename)
Load energy dispersion from FITS file.
double m_logEsrc_max
Maximum logE (log10(E/TeV))
void compute_etrue_bounds(const double &theta=0.0, const double &phi=0.0, const double &zenith=0.0, const double &azimuth=0.0) const
Compute vector of true energy boundaries.
double operator()(const GEnergy &ereco, const GEnergy &etrue, const double &theta=0.0, const double &phi=0.0, const double &zenith=0.0, const double &azimuth=0.0) const
Return energy dispersion in units of MeV .
GEnergy mc(GRan &ran, const GEnergy &etrue, const double &theta=0.0, const double &phi=0.0, const double &zenith=0.0, const double &azimuth=0.0) const
Simulate energy dispersion.
std::vector< GEbounds > m_etrue_bounds
double m_last_theta_ereco
void set_max_edisp(void)
Set array of maximum energy dispersion values.
void write(GFitsBinTable &table) const
Write energy dispersion into FITS binary table.
void normalize_table(void)
Normalize energy dispersion table.
int m_inx_theta
Theta index.
GCTAEdisp2D & operator=(const GCTAEdisp2D &edisp)
Assignment operator.
void compute_ereco_bounds(const double &theta=0.0, const double &phi=0.0, const double &zenith=0.0, const double &azimuth=0.0) const
Compute vector of reconstructed energy bounds.
double prob_erecobin(const GEnergy &ereco_min, const GEnergy &ereco_max, const GEnergy &etrue, const double &theta) const
Return energy dispersion probability for reconstructed energy interval.
bool m_fetched
Signals that Edisp has been fetched.
GCTAResponseTable m_edisp
Edisp response table.
std::string print(const GChatter &chatter=NORMAL) const
Print energy dispersion information.
double m_migra_max
Maximum migration.
virtual ~GCTAEdisp2D(void)
Destructor.
double m_logEsrc_min
Minimum logE (log10(E/TeV))
GFilename m_filename
Name of Edisp response file.
void free_members(void)
Delete class members.
GEbounds etrue_bounds(const GEnergy &ereco, const double &theta=0.0, const double &phi=0.0, const double &zenith=0.0, const double &azimuth=0.0) const
Return true energy interval that contains the energy dispersion.
GNdarray smooth_array(const GNdarray &array, const int &nstart, const int &nstop, const double &limit) const
Smoothed array.
bool m_ereco_bounds_computed
int m_inx_migra
Migration index.
bool m_etrue_bounds_computed
GCTAEdisp2D * clone(void) const
Clone energy dispersion.
double theta(const int &itheta) const
Get offset angle in radiaus.
int table_index(const int &ietrue, const int &imigra, const int &itheta) const
Return index of response table element.
void read(const GFitsTable &table)
Read energy dispersion from FITS table.
void smooth_table(void)
Smoothed energy dispersion table.
double migra(const int &imigra) const
Get migration.
GCTAEdisp2D(void)
Void constructor.
Abstract base class for the CTA energy dispersion.
GCTAEdisp & operator=(const GCTAEdisp &edisp)
Assignment operator.
void free_members(void)
Delete class members.
void init_members(void)
Initialise class members.
CTA response table class.
void read(const GFitsTable &table)
Read response table from FITS table HDU.
int table(const std::string &name) const
Determine index of table.
const std::string & telescope(void) const
Return telescope string.
void axis_log10(const int &axis)
Set nodes for a logarithmic (base 10) axis.
void axis_radians(const int &axis)
Set nodes for a radians axis.
int axis(const std::string &name) const
Determine index of an axis.
const int & axes(void) const
Return number of axes of the tables.
void write(GFitsTable &table) const
Write response table into FITS table HDU.
int axis_bins(const int &axis) const
Return number bins in an axis.
const double & axis_hi(const int &axis, const int &bin) const
Return upper bin boundary for bin in axis.
bool has_axis(const std::string &name) const
Check whether an axis exists.
const GNodeArray & axis_nodes(const int &axis) const
Return axis nodes.
void clear(void)
Clear response table.
const double & axis_lo(const int &axis, const int &bin) const
Return lower bin boundary for bin in axis.
Energy boundaries container class.
const GEnergy & emax(void) const
Return maximum energy of all intervals.
int size(void) const
Return number of energy boundaries.
const GEnergy & emin(void) const
Return minimum energy of all intervals.
Class that handles energies in a unit independent way.
double log10TeV(void) const
Return log10 of energy in TeV.
double MeV(void) const
Return energy in MeV.
double log10MeV(void) const
Return log10 of energy in MeV.
std::string print(const GChatter &chatter=NORMAL) const
Print energy.
void clear(void)
Clear instance.
double TeV(void) const
Return energy in TeV.
std::string url(void) const
Return Uniform Resource Locator (URL)
std::string extname(const std::string &defaultname="") const
Return extension name.
bool exists(void) const
Checks whether file exists.
bool is_empty(void) const
Signal if filename is empty.
void clear(void)
Clear file name.
Abstract interface for FITS table.
bool contains(const int &extno) const
Check if HDU exists in FITS file.
GFitsHDU * append(const GFitsHDU &hdu)
Append HDU to FITS file.
void close(void)
Close FITS file.
void remove(const int &extno)
Remove HDU from FITS file.
void save(const bool &clobber=false)
Saves FITS file.
GFitsTable * table(const int &extno)
Get pointer to table HDU.
GIntegral class interface definition.
void eps(const double &eps)
Set relative precision.
double romberg(std::vector< double > bounds, const int &order=5)
Perform Romberg integration.
N-dimensional array class.
int size(void) const
Return number of elements in array.
void set_value(const double &value) const
Set indices and weighting factors for interpolation.
const int & inx_right(void) const
Returns right node index.
const int & inx_left(void) const
Returns left node index.
const double & wgt_right(void) const
Returns right node weight.
const double & wgt_left(void) const
Returns left node weight.
int size(void) const
Return number of nodes in node array.
Random number generator class.
double uniform(void)
Returns random double precision floating value in range 0 to 1.
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
bool is_infinite(const double &x)
Signal if argument is infinite.
bool is_notanumber(const double &x)
Signal if argument is not a number.
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
std::string strip_whitespace(const std::string &arg)
Strip leading and trailing whitespace from string.
const std::string extname_cta_edisp2d
std::string gadf_hduclas4(const GFits &fits, const std::string &hduclas4)
Return extension name for GADF response table of given HDU class 4.