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
57 //#define G_SMOOTH_EDISP_SAVE_TEST
159 if (
this != &edisp) {
207 const double& zenith,
208 const double& azimuth)
const
247 edisp /= etrue.
MeV();
352 std::string msg =
"Expected three-dimensional energy dispersion "
353 "response table but found "+
355 " dimensions. Please specify a three-dimensional "
356 "energy dispersion.";
440 if (fits.contains(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 "
506 "for true photon energy "+etrue.
print()+
", "
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;
543 f =
operator()(ereco, etrue, theta, phi, zenith, azimuth);
546 if (zeros > max_subsequent_zeros) {
547 std::string msg =
"No valid energy dispersion information "
548 "available for true photon energy "+
549 etrue.
print()+
", offset angle "+
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
617 double etrue_TeV = etrue.
TeV();
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 ===");
1130 etrue.
TeV(etrue_TeV);
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) {
1229 ereco_min = migra * etrue.
TeV();
1236 for (
int imigra = nmigra-1; imigra >= 0; imigra--) {
1251 ereco_max = migra * etrue.
TeV();
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) {
1337 etrue = ereco /
migra;
1340 double edisp =
operator()(ereco, etrue, theta);
1352 for (
int imigra = nmigras-1; imigra >= 0; imigra--) {
1363 etrue = ereco /
migra;
1366 double edisp =
operator()(ereco, etrue, theta);
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);
1680 sum += integral.
romberg(emin, emax);
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);
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;
int m_inx_etrue
True energy index.
const GNodeArray & axis_nodes(const int &axis) const
Return axis nodes.
void normalize_table(void)
Normalize energy dispersion table.
int size(void) const
Return number of nodes in node array.
CTA 2D energy dispersion class.
std::string print(const GChatter &chatter=NORMAL) const
Print energy dispersion information.
GEnergy m_etrue
True photon energy.
GFilename filename(void) const
Return filename.
GFitsTable * table(const int &extno)
Get pointer to table HDU.
double romberg(std::vector< double > bounds, const int &order=5)
Perform Romberg integration.
GEnergy etrue(const int &ietrue) const
Get true energy.
Random number generator class definition.
const GCTAEdisp2D * m_parent
Pointer to parent class.
double smoothed_array_value(const int &inx, const GNdarray &array, const int &nodes, const double &limit) const
Get smoothed array value.
double theta(const int &itheta) const
Get offset angle in radiaus.
int size(void) const
Return number of energy boundaries.
GCTAEdisp2D(void)
Void constructor.
void set_max_edisp(void)
Set array of maximum energy dispersion values.
bool is_empty(void) const
Signal if filename is empty.
void free_members(void)
Delete class members.
const double & wgt_left(void) const
Returns left node weight.
Abstract base class for the CTA energy dispersion.
double m_last_theta_etrue
bool m_ereco_bounds_computed
double TeV(void) const
Return energy in TeV.
double sum(const GVector &vector)
Computes vector sum.
std::string extname(const std::string &defaultname="") const
Return extension name.
double log10TeV(void) const
Return log10 of energy in TeV.
double m_last_theta_ereco
Random number generator class.
double migra(const int &imigra) const
Get migration.
void copy_members(const GCTAEdisp2D &edisp)
Copy class members.
double MeV(void) const
Return energy in MeV.
virtual ~GCTAEdisp2D(void)
Destructor.
GCTAResponseTable m_edisp
Edisp response table.
void fetch(void) const
Fetch energy dispersion.
GIntegral class interface definition.
void axis_radians(const int &axis)
Set nodes for a radians axis.
FITS file class interface definition.
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.
void set_value(const double &value) const
Set indices and weighting factors for interpolation.
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.
std::string strip_whitespace(const std::string &arg)
Strip leading and trailing whitespace from string.
bool m_etrue_bounds_computed
void read(const GFitsTable &table)
Read response table from FITS table HDU.
double m_theta_max
Maximum theta (radians)
double log10MeV(void) const
Return log10 of energy in MeV.
bool m_fetched
Signals that Edisp has been fetched.
bool is_notanumber(const double &x)
Signal if argument is not a number.
void write(GFitsBinTable &table) const
Write energy dispersion into FITS binary table.
const double & axis_lo(const int &axis, const int &bin) const
Return lower bin boundary for bin in axis.
bool is_infinite(const double &x)
Signal if argument is infinite.
Definition of support function used by CTA classes.
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.
void write(GFitsTable &table) const
Write response table into FITS table HDU.
int axis(const std::string &name) const
Determine index of an axis.
GVector sqrt(const GVector &vector)
Computes square root of vector elements.
const double & wgt_right(void) const
Returns right node weight.
void load(const GFilename &filename)
Load energy dispersion from FITS file.
Energy boundaries container class.
void remove(const int &extno)
Remove HDU from FITS file.
void set_table(void)
Set table.
std::string print(const GChatter &chatter=NORMAL) const
Print energy.
double eval(const double &log10Ereco)
Integration kernel for GCTAEdisp2D::edisp_ereco_kern class.
int table_stride(const int &axis) const
Return stride of response table axis.
void clear(void)
Clear response table.
void smooth_table(void)
Smoothed energy dispersion table.
N-dimensional array class interface definition.
const GEnergy & emin(void) const
Return minimum energy of all intervals.
double m_logEsrc_min
Minimum logE (log10(E/TeV))
void get_mean_rms(const GNdarray &array, double *mean, double *rms) const
Compute mean and root mean square of migration array.
bool exists(void) const
Checks whether file exists.
double uniform(void)
Returns random double precision floating value in range 0 to 1.
Abstract interface for FITS table.
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.
int size(void) const
Return number of elements in array.
const int & inx_left(void) const
Returns left node index.
CTA 2D energy dispersion class definition.
void save(const GFilename &filename, const bool &clobber=false) const
Save energy dispersion table into FITS file.
N-dimensional array class.
const std::string & extname(void) const
Return extension name.
void axis_log10(const int &axis)
Set nodes for a logarithmic (base 10) axis.
double get_max_edisp(const GEnergy &etrue, const double &theta) const
Get maximum energy dispersion value.
GNdarray smooth_array(const GNdarray &array, const int &nstart, const int &nstop, const double &limit) const
Smoothed array.
int table(const std::string &name) const
Determine index of table.
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.
const GCTAResponseTable & table(void) const
Return response table.
std::string gadf_hduclas4(const GFits &fits, const std::string &hduclas4)
Return extension name for GADF response table of given HDU class 4.
double m_logEsrc_max
Maximum logE (log10(E/TeV))
const int & inx_right(void) const
Returns right node index.
void free_members(void)
Delete class members.
Fast Fourier transformation class interface definition.
std::vector< GEbounds > m_ereco_bounds
GCTAEdisp & operator=(const GCTAEdisp &edisp)
Assignment operator.
void clear(void)
Clear energy dispersion.
double m_theta_min
Minimum theta (radians)
std::vector< double > m_max_edisp
Maximum Edisp.
const std::string & telescope(void) const
Return telescope string.
GCTAEdisp2D * clone(void) const
Clone energy dispersion.
const std::string extname_cta_edisp2d
void init_members(void)
Initialise class members.
void eps(const double &eps)
Set relative precision.
int m_inx_theta
Theta index.
GFilename m_filename
Name of Edisp response file.
std::string url(void) const
Return Uniform Resource Locator (URL)
int axis_bins(const int &axis) const
Return number bins in an axis.
void clear(void)
Clear file name.
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.
int table_index(const int &ietrue, const int &imigra, const int &itheta) const
Return index of response table element.
int m_inx_migra
Migration index.
GNdarray gaussian_array(const double &mean, const double &rms, const double &total) const
Return Gaussian approximation of energy dispersion array.
bool has_axis(const std::string &name) const
Check whether an axis exists.
const double & axis_hi(const int &axis, const int &bin) const
Return upper bin boundary for bin in axis.
Exception handler interface definition.
FITS binary table class definition.
GVector exp(const GVector &vector)
Computes exponential of vector elements.
CTA response table class.
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 .
void init_members(void)
Initialise class members.
double m_migra_min
Minimum migration.
const GEnergy & emax(void) const
Return maximum energy of all intervals.
void get_moments(const int &itheta, GNdarray *mean, GNdarray *rms, GNdarray *total) const
Compute moments.
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Integration class interface definition.
void close(void)
Close FITS file.
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.
const int & axes(void) const
Return number of axes of the tables.
GCTAEdisp2D & operator=(const GCTAEdisp2D &edisp)
Assignment operator.
double m_theta
Offset angle.
void clear(void)
Clear instance.
void read(const GFitsTable &table)
Read energy dispersion from FITS table.
double m_migra_max
Maximum migration.
Filename class interface definition.
Mathematical function definitions.
GVector log10(const GVector &vector)
Computes base10 logarithm of vector elements.
Class that handles energies in a unit independent way.
std::vector< GEbounds > m_etrue_bounds
void set_boundaries(void)
Set energy dispersion boundaries.
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
FITS table abstract base class interface definition.