10 #include "cetlib_except/exception.h" 18 #include "boost/math/special_functions/ellint_1.hpp" 19 #include "boost/math/special_functions/ellint_3.hpp" 23 : fISTPC{*(lar::providerFrom<geo::Geometry>())}
34 std::cout <<
"Semi-analytical model initialized." <<
std::endl;
74 else if (opDet.
isBar()) {
96 std::map<double, double> abs_length_spectrum = lar::providerFrom<detinfo::LArPropertiesService>()->AbsLengthSpectrum();
97 std::vector<double> x_v, y_v;
98 for (
auto elem : abs_length_spectrum) {
99 x_v.push_back(elem.first);
100 y_v.push_back(elem.second);
105 mf::LogInfo(
"SemiAnalyticalModel") <<
"Using VUV visibility parameterization";
118 <<
"Both isFlatPDCorr/isFlatPDCorrLat and isDomePDCorr parameters are false, at least one type of parameterisation is required for the semi-analytic light simulation." <<
"\n";
125 if (fIsFlatPDCorrLat) {
137 mf::LogInfo(
"SemiAnalyticalModel") <<
"Using VIS (reflected) visibility parameterization";
163 mf::LogInfo(
"SemiAnalyticalModel") <<
"Using anode reflections parameterization";
173 if (fIsFlatPDCorrLat) {
208 DetectedVisibilities[OpDet] = DetThis;
217 const double distance = relative.R();
220 else cosine =
std::abs(relative.X()) / distance;
223 double solid_angle = 0.;
225 if (opDet.
type == 0) {
231 else if (opDet.
type == 1) {
235 else if (opDet.
type == 2) {
236 const double zy_offset = std::sqrt(relative.Y() * relative.Y() + relative.Z() * relative.Z());
237 const double x_distance =
std::abs(relative.X());
242 <<
"Error: Invalid optical detector shape requested - configuration error in semi-analytical model, only rectangular, dome or disk optical detectors are supported." <<
"\n";
247 double visibility_geo = std::exp(-1. * distance /
fL_abs_vuv) * (solid_angle / (4 *
CLHEP::pi));
257 double pars_ini[4] = {0, 0, 0, 0};
258 double s1 = 0;
double s2 = 0;
double s3 = 0;
267 std::vector<double> p1, p2, p3, p4;
268 p1.reserve(n_distances); p2.reserve(n_distances); p3.reserve(n_distances); p4.reserve(n_distances);
269 for (
int i = 0; i < n_distances; i++) {
294 <<
"Error: flat optical detectors are found, but parameters are missing - configuration error in semi-analytical model." <<
"\n";
309 <<
"Error: Invalid optical detector shape requested or corrections are missing - configuration error in semi-analytical model." <<
"\n";
313 pars_ini[0] = pars_ini[0] + s1 *
r;
314 pars_ini[1] = pars_ini[1] + s2 *
r;
315 pars_ini[2] = pars_ini[2] + s3 *
r;
316 pars_ini[3] = pars_ini[3];
328 DetThis = GH_correction * visibility_geo / cosine;
344 Dims plane_dimensions;
363 double distance_cathode =
std::abs(plane_depth - ScintPoint.X());
365 double cathode_visibility_geo = std::exp(-1. * distance_cathode /
fL_abs_vuv) * (solid_angle_cathode / (4. *
CLHEP::pi));
370 double pars_ini[4] = {0, 0, 0, 0};
371 double s1 = 0;
double s2 = 0;
double s3 = 0;
383 <<
"Error: flat optical detector VUV correction required for reflected semi-analytic hits. - configuration error in semi-analytical model." <<
"\n";
387 pars_ini[0] = pars_ini[0] + s1 *
r;
388 pars_ini[1] = pars_ini[1] + s2 *
r;
389 pars_ini[2] = pars_ini[2] + s3 *
r;
390 pars_ini[3] = pars_ini[3];
393 double GH_correction =
Gaisser_Hillas(distance_cathode, pars_ini);
394 const double cathode_visibility_rec = GH_correction * cathode_visibility_geo;
397 const geo::Point_t hotspot = {plane_depth, ScintPoint.Y(), ScintPoint.Z()};
407 VISVisibility(ScintPoint, op, cathode_visibility_rec, hotspot, ReflDetThis, AnodeMode);
409 ReflDetectedVisibilities[OpDet] = ReflDetThis;
415 geo::Point_t const& hotspot,
double &ReflDetThis,
bool AnodeMode)
429 const double distance_vis = emission_relative.R();
433 cosine_vis =
std::abs(emission_relative.Y()) / distance_vis;
436 cosine_vis =
std::abs(emission_relative.X()) / distance_vis;
441 double solid_angle_detector = 0.;
443 if (opDet.
type == 0) {
451 else if (opDet.
type == 1) {
455 else if (opDet.
type == 2) {
456 const double zy_offset = std::sqrt(emission_relative.Y() * emission_relative.Y() +
457 emission_relative.Z() * emission_relative.Z());
458 const double x_distance =
std::abs(emission_relative.X());
463 <<
"Error: Invalid optical detector shape requested - configuration error in semi-analytical model, only rectangular, dome or disk optical detectors are supported." <<
"\n";
467 double visibility_geo = (solid_angle_detector / (2. *
CLHEP::pi)) *
473 double d_c =
std::abs(ScintPoint.X() - plane_depth);
474 double border_correction = 0;
483 <<
"Error: Invalid optical detector shape requested or corrections are missing - configuration error in semi-analytical model." <<
"\n";
490 <<
"Error: Invalid optical detector shape requested or corrections are missing - configuration error in semi-analytical model." <<
"\n";
502 ReflDetThis = border_correction * visibility_geo / cosine_vis;
510 double X_mu_0 = par[3];
511 double Normalization = par[0];
512 double Diff = par[1] - X_mu_0;
513 double Term =
std::pow((x - X_mu_0) / Diff, Diff / par[2]);
514 double Exponential = std::exp((par[1] - x) / par[2]);
516 return (Normalization * Term * Exponential);
524 if (b <= 0. || d < 0. || h <= 0.)
return 0.;
525 const double leg2 = (b +
d) * (b + d);
526 const double aa = std::sqrt(h * h / (h * h + leg2));
528 double bb = 2. * std::sqrt(b * d / (h * h + leg2));
529 double cc = 4. * b * d /
leg2;
537 catch (std::domain_error&
e) {
540 <<
"Elliptic Integral in Disk_SolidAngle() given parameters " 542 <<
"\nbb: " << bb <<
"\ncc: " << cc <<
"\nException message: " << e.what()
543 <<
"\nRelax condition and carry on.";
548 <<
"Elliptic Integral inside Disk_SolidAngle() given parameters " 550 <<
"\nbb: " << bb <<
"\ncc: " << cc <<
"Exception message: " << e.what();
562 catch (std::domain_error&
e) {
565 <<
"Elliptic Integral in Disk_SolidAngle() given parameters " 567 <<
"\nbb: " << bb <<
"\ncc: " << cc <<
"\nException message: " << e.what()
568 <<
"\nRelax condition and carry on.";
573 <<
"Elliptic Integral inside Disk_SolidAngle() given parameters " 575 <<
"\nbb: " << bb <<
"\ncc: " << cc <<
"Exception message: " << e.what();
591 double aa = a / (2. *
d);
592 double bb = b / (2. *
d);
593 double aux = (1. + aa * aa + bb * bb) / ((1. + aa * aa) * (1. + bb * bb));
606 if (OpDetOrientation == 1) {
621 double A = d1 - o.
h * .5;
630 if ((d1 <= o.
h * .5) && (
std::abs(v.Z()) <= o.
w * .5)) {
631 double A = -d1 + o.
h * .5;
641 double A = d1 - o.
h * .5;
651 double A = -d1 + o.
h * .5;
678 double par0[9] = {0., 0., 0., 0., 0., 0.597542, 1.00872, 1.46993, 2.04221};
679 double par1[9] = {0, 0, 0.19569, 0.300449, 0.555598, 0.854939, 1.39166, 2.19141, 2.57732};
680 const double delta_theta = 10.;
681 int j =
int(theta/delta_theta);
685 const double d_break = 5*
b;
687 if(distance >= d_break) {
688 double R_apparent_far = b - par1[j];
692 double R_apparent_close = b - par0[j];
693 return (2*
CLHEP::pi * (1 - std::sqrt(1 -
std::pow(R_apparent_close/distance,2))));
706 if (((ScintPoint.X() < 0.) != (OpDetPoint.X() < 0.)) &&
717 double negate = double(x < 0);
719 x -= double(x > 1.0) * (x - 1.0);
720 double ret = -0.0187293;
722 ret = ret + 0.0742610;
724 ret = ret - 0.2121144;
726 ret = ret + 1.5707288;
727 ret = ret * std::sqrt(1.0 - x);
728 ret = ret - 2. * negate * ret;
729 return negate * 3.14159265358979 + ret;
739 const std::vector<double>& yData,
745 size_t size = xData.size();
746 if (x >= xData[size - 2]) {
750 while (x > xData[i + 1])
754 double xL = xData[i];
755 double xR = xData[i + 1];
756 double yL = yData[i];
757 double yR = yData[i + 1];
759 if (x < xL)
return yL;
760 if (x > xR)
return yL;
762 const double dydx = (yR - yL) / (xR - xL);
763 return yL + dydx * (x - xL);
768 const std::vector<double>& rDistances,
772 const size_t k)
const 775 const size_t nbins_r = parameters[
k].size();
776 std::vector<double> interp_vals(nbins_r, 0.0);
779 size_t size = xDistances.size();
780 if (x >= xDistances[size - 2])
783 while (x > xDistances[idx + 1])
786 for (
size_t i = 0; i < nbins_r; ++i) {
795 double border_correction =
interpolate(rDistances, interp_vals, r,
false);
796 return border_correction;
bool fIncludeAnodeReflections
std::vector< double > fvis_distances_r_dome
std::vector< std::vector< std::vector< double > > > fGHvuvpars_flat_lateral
std::vector< double > fvis_distances_r_flat_lateral
static constexpr bool isDefinitelyLessThan(TReal a, TReal b, TReal tolerance=std::numeric_limits< TReal >::epsilon())
double Gaisser_Hillas(const double x, const double *par) const
OpDetGeo const & OpDetGeoFromOpDet(unsigned int OpDet) const
Returns the geo::OpDetGeo object for the given detector number.
static std::vector< geo::BoxBoundedGeo > extractActiveLArVolume(geo::GeometryCore const &geom)
std::vector< std::vector< double > > fborder_corr_dome
double fcathode_zdimension
Encapsulate the construction of a single cyostat.
double interpolate2(const std::vector< double > &xDistances, const std::vector< double > &rDistances, const std::vector< std::vector< std::vector< double >>> ¶meters, const double x, const double r, const size_t k) const
std::vector< std::vector< std::vector< double > > > fvispars_flat_lateral
double Omega_Dome_Model(const double distance, const double theta) const
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
void detectedDirectVisibilities(std::map< size_t, double > &DetectedVisibilities, geo::Point_t const &ScintPoint)
bool isBar() const
Returns whether the detector shape is a bar (TGeoBBox).
std::vector< double > fGH_distances_anode
std::vector< std::vector< double > > fGHvuvpars_flat
Point GetCathodeCenter() const
std::vector< std::vector< double > > fGHvuvpars_dome
std::vector< double > fvis_distances_r_flat
geo::PlaneGeo const & FirstPlane() const
Returns the first wire plane (the closest to TPC center).
std::vector< double > fOpDetHeight
void GetCenter(double *xyz, double localz=0.0) const
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
void VUVVisibility(geo::Point_t const &ScintPoint, OpticalDetector const &opDet, double &DetThis)
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
std::vector< std::vector< std::vector< double > > > fvispars_flat
void detectedReflectedVisibilities(std::map< size_t, double > &ReflDetectedVisibilities, geo::Point_t const &ScintPoint, bool AnodeMode=false)
double fast_acos(double x) const
bool fApplyFieldCageTransparency
std::enable_if_t< std::is_arithmetic_v< T >, T > hypot(T x, T y)
double fFieldCageTransparencyCathode
bool isSphere() const
Returns whether the detector shape is a hemisphere (TGeoSphere).
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
double Rectangle_SolidAngle(const double a, const double b, const double d) const
std::vector< geo::BoxBoundedGeo > fActiveVolumes
auto counter(T begin, T end)
Returns an object to iterate values from begin to end in a range-for loop.
std::vector< double > fvis_distances_x_flat
boost::math::policies::policy< boost::math::policies::promote_double< false > > noLDoublePromote
T get(std::string const &key) const
Point GetCenter() const
Returns the centre of the wire plane in world coordinates [cm].
double interpolate(const std::vector< double > &xData, const std::vector< double > &yData, double x, bool extrapolate, size_t i=0) const
Test of util::counter and support utilities.
std::vector< double > fvis_distances_x_flat_lateral
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
std::vector< geo::Point_t > fOpDetCenter
std::vector< double > fOpDetLength
Description of geometry of one entire detector.
std::vector< std::vector< double > > fborder_corr_flat
double fAnodeReflectivity
unsigned int NOpDets() const
Number of OpDets in the whole detector.
unsigned int NTPC(unsigned int cstat=0) const
Returns the total number of TPCs in the specified cryostat.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Encapsulate the geometry of an optical detector.
static constexpr bool isApproximatelyEqual(TReal a, TReal b, TReal tolerance=std::numeric_limits< TReal >::epsilon())
void VISVisibility(geo::Point_t const &ScintPoint, OpticalDetector const &opDet, const double cathode_visibility, geo::Point_t const &hotspot, double &ReflDetThis, bool AnodeMode=false)
static constexpr bool isApproximatelyZero(TReal a, TReal tolerance=std::numeric_limits< TReal >::epsilon())
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::vector< int > fOpDetType
std::vector< double > fborder_corr_angulo_dome
bool isOpDetInSameTPC(geo::Point_t const &ScintPoint, geo::Point_t const &OpDetPoint) const
std::vector< double > fvis_distances_x_dome
static constexpr bool isDefinitelyGreaterThan(TReal a, TReal b, TReal tolerance=std::numeric_limits< TReal >::epsilon())
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
double fcathode_ydimension
double Disk_SolidAngle(const double d, const double h, const double b) const
fhicl::ParameterSet fVISHitsParams
double fanode_plane_depth
SemiAnalyticalModel(fhicl::ParameterSet VUVHits, fhicl::ParameterSet VISHits, bool doReflectedLight=false, bool includeAnodeReflections=false)
std::vector< double > fborder_corr_angulo_flat
std::vector< int > fOpDetOrientation
cet::coded_exception< error, detail::translate > exception
QTextStream & endl(QTextStream &s)
fhicl::ParameterSet fVUVHitsParams
double fFieldCageTransparencyLateral
std::vector< std::vector< std::vector< double > > > fvispars_dome