16 #include "cetlib_except/exception.h" 25 #include "boost/math/special_functions/ellint_1.hpp" 26 #include "boost/math/special_functions/ellint_3.hpp" 33 const bool doReflectedLight,
34 const bool includeAnodeReflections,
35 const bool useXeAbsorption)
36 : fGeom{*(lar::providerFrom<geo::Geometry>())}
53 mf::LogInfo(
"SemiAnalyticalModel") <<
"Initializing Semi-analytical model." << std::endl;
56 mf::LogInfo(
"SemiAnalyticalModel") <<
"Using VUV visibility parameterization";
62 fradius = VUVHitsParams.get<
double>(
"PMT_radius", 10.16);
72 <<
"Both isFlatPDCorr/isFlatPDCorrLat and isDomePDCorr parameters are " 73 "false, at least one type of parameterisation is required for the " 74 "semi-analytic light simulation." 78 fGHvuvpars_flat = VUVHitsParams.get<std::vector<std::vector<double>>>(
"GH_PARS_flat");
80 fborder_corr_flat = VUVHitsParams.get<std::vector<std::vector<double>>>(
"GH_border_flat");
82 if (fIsFlatPDCorrLat) {
84 VUVHitsParams.get<std::vector<std::vector<double>>>(
"GH_PARS_flat_lateral");
86 VUVHitsParams.get<std::vector<double>>(
"GH_border_angulo_flat_lateral");
88 VUVHitsParams.get<std::vector<std::vector<double>>>(
"GH_border_flat_lateral");
91 fGHvuvpars_dome = VUVHitsParams.get<std::vector<std::vector<double>>>(
"GH_PARS_dome");
93 fborder_corr_dome = VUVHitsParams.get<std::vector<std::vector<double>>>(
"GH_border_dome");
98 mf::LogInfo(
"SemiAnalyticalModel") <<
"Using VIS (reflected) visibility parameterization";
105 VISHitsParams.get<std::vector<std::vector<std::vector<double>>>>(
"VIS_correction_flat");
111 VISHitsParams.get<std::vector<std::vector<std::vector<double>>>>(
"VIS_correction_dome");
122 mf::LogInfo(
"SemiAnalyticalModel") <<
"Using anode reflections parameterization";
130 VISHitsParams.get<std::vector<std::vector<std::vector<double>>>>(
"VIS_correction_flat");
133 if (fIsFlatPDCorrLat) {
135 VISHitsParams.get<std::vector<double>>(
"VIS_distances_x_flat_lateral");
137 VISHitsParams.get<std::vector<double>>(
"VIS_distances_r_flat_lateral");
139 "VIS_correction_flat_lateral");
159 mf::LogInfo(
"SemiAnalyticalModel") <<
"Semi-analytical model initialized." << std::endl;
165 std::map<double, double> abs_length_spectrum =
166 lar::providerFrom<detinfo::LArPropertiesService>()->AbsLengthSpectrum();
167 std::vector<double> x_v, y_v;
168 for (
auto elem : abs_length_spectrum) {
169 x_v.push_back(elem.first);
170 y_v.push_back(elem.second);
172 double vuv_absorption_length;
174 vuv_absorption_length =
177 vuv_absorption_length =
179 if (vuv_absorption_length <= 0) {
181 <<
"Error: VUV Absorption Length is 0 or negative.\n";
183 return vuv_absorption_length;
191 DetectedVisibilities.resize(
fNOpDets);
195 DetectedVisibilities[OpDet] = 0.;
200 const double distance = relative.R();
202 DetectedVisibilities[OpDet] = 0.;
215 const double distance = relative.R();
218 cosine =
std::abs(relative.Z()) / distance;
220 cosine =
std::abs(relative.Y()) / distance;
222 cosine =
std::abs(relative.X()) / distance;
225 double solid_angle = 0.;
227 if (opDet.
type == 0) {
234 else if (opDet.
type == 1) {
238 else if (opDet.
type == 2) {
239 const double zy_offset = std::sqrt(relative.Y() * relative.Y() + relative.Z() * relative.Z());
240 const double x_distance =
std::abs(relative.X());
245 <<
"Error: Invalid optical detector shape requested - configuration " 246 "error in semi-analytical model, only rectangular, dome or disk " 247 "optical detectors are supported." 253 double visibility_geo =
270 double pars_ini[4] = {0, 0, 0, 0};
300 <<
"Error: flat optical detectors are found, but parameters are " 301 "missing - configuration error in semi-analytical model." 317 <<
"Error: Invalid optical detector shape requested or corrections are " 318 "missing - configuration error in semi-analytical model." 323 pars_ini[0] = pars_ini[0] + s1 *
r;
324 pars_ini[1] = pars_ini[1] + s2 *
r;
325 pars_ini[2] = pars_ini[2] + s3 *
r;
326 pars_ini[3] = pars_ini[3];
333 if (!
std::isfinite(GH_correction) || GH_correction < 0 || GH_correction > 10) GH_correction = 0;
336 return GH_correction * visibility_geo / cosine;
342 std::vector<double>& ReflDetectedVisibilities,
344 bool AnodeMode)
const 353 Dims plane_dimensions;
365 ScintPoint_relative.SetCoordinates(
std::abs(ScintPoint.X() - plane_depth),
378 double distance_cathode =
std::abs(plane_depth - ScintPoint.X());
381 (solid_angle_cathode / (4. *
CLHEP::pi));
386 double pars_ini[4] = {0, 0, 0, 0};
401 <<
"Error: flat optical detector VUV correction required for reflected " 402 "semi-analytic hits. - configuration error in semi-analytical model." 407 pars_ini[0] = pars_ini[0] + s1 *
r;
408 pars_ini[1] = pars_ini[1] + s2 *
r;
409 pars_ini[2] = pars_ini[2] + s3 *
r;
410 pars_ini[3] = pars_ini[3];
413 double GH_correction =
Gaisser_Hillas(distance_cathode, pars_ini);
417 if (!
std::isfinite(GH_correction) || GH_correction < 0 || GH_correction > 10) GH_correction = 0;
419 const double cathode_visibility_rec = GH_correction * cathode_visibility_geo;
422 const geo::Point_t hotspot = {plane_depth, ScintPoint.Y(), ScintPoint.Z()};
423 ReflDetectedVisibilities.resize(
fNOpDets);
426 ReflDetectedVisibilities[OpDet] = 0.;
430 ReflDetectedVisibilities[OpDet] =
437 const double cathode_visibility,
439 bool AnodeMode)
const 455 const double distance_vis = emission_relative.R();
459 cosine_vis =
std::abs(emission_relative.Z()) / distance_vis;
462 cosine_vis =
std::abs(emission_relative.Y()) / distance_vis;
465 cosine_vis =
std::abs(emission_relative.X()) / distance_vis;
470 double solid_angle_detector = 0.;
472 if (opDet.
type == 0) {
477 solid_angle_detector =
481 else if (opDet.
type == 1) {
485 else if (opDet.
type == 2) {
486 const double zy_offset = std::sqrt(emission_relative.Y() * emission_relative.Y() +
487 emission_relative.Z() * emission_relative.Z());
488 const double x_distance =
std::abs(emission_relative.X());
493 <<
"Error: Invalid optical detector shape requested - configuration " 494 "error in semi-analytical model, only rectangular, dome or disk " 495 "optical detectors are supported." 500 double visibility_geo = (solid_angle_detector / (2. *
CLHEP::pi)) *
511 double d_c =
std::abs(ScintPoint.X() - plane_depth);
512 double border_correction = 0;
533 <<
"Error: Invalid optical detector shape requested or corrections " 534 "are missing - configuration error in semi-analytical model." 545 <<
"Error: Invalid optical detector shape requested or corrections are " 546 "missing - configuration error in semi-analytical model." 553 return border_correction * visibility_geo / cosine_vis;
560 double X_mu_0 = par[3];
561 double Normalization = par[0];
562 double Diff = par[1] - X_mu_0;
563 double Term = std::pow((x - X_mu_0) / Diff, Diff / par[2]);
564 double Exponential = std::exp((par[1] - x) / par[2]);
566 return (Normalization * Term * Exponential);
573 if (b <= 0. || d < 0. || h <= 0.)
return 0.;
574 const double leg2 = (b +
d) * (b + d);
575 const double aa = std::sqrt(h * h / (h * h + leg2));
577 double bb = 2. * std::sqrt(b * d / (h * h + leg2));
578 double cc = 4. * b * d / leg2;
586 catch (std::domain_error&
e) {
589 <<
"Elliptic Integral in Disk_SolidAngle() given parameters " 591 <<
"\nbb: " << bb <<
"\ncc: " << cc <<
"\nException message: " << e.what()
592 <<
"\nRelax condition and carry on.";
597 <<
"Elliptic Integral inside Disk_SolidAngle() given parameters " 599 <<
"\nbb: " << bb <<
"\ncc: " << cc <<
"Exception message: " << e.what();
611 catch (std::domain_error&
e) {
614 <<
"Elliptic Integral in Disk_SolidAngle() given parameters " 616 <<
"\nbb: " << bb <<
"\ncc: " << cc <<
"\nException message: " << e.what()
617 <<
"\nRelax condition and carry on.";
622 <<
"Elliptic Integral inside Disk_SolidAngle() given parameters " 624 <<
"\nbb: " << bb <<
"\ncc: " << cc <<
"Exception message: " << e.what();
639 const double d)
const 641 double aa = a / (2. *
d);
642 double bb = b / (2. *
d);
643 double aux = (1. + aa * aa + bb * bb) / ((1. + aa * aa) * (1. + bb * bb));
649 int OpDetOrientation)
const 658 if (OpDetOrientation == 2) {
663 else if (OpDetOrientation == 1) {
679 double A = d1 - o.
h * .5;
688 if ((d1 <= o.
h * .5) && (
std::abs(v.Z()) <= o.
w * .5)) {
689 double A = -d1 + o.
h * .5;
699 double A = d1 - o.
h * .5;
709 double A = -d1 + o.
h * .5;
735 constexpr
double par0[9] = {0., 0., 0., 0., 0., 0.597542, 1.00872, 1.46993, 2.04221};
736 constexpr
double par1[9] = {
737 0., 0., 0.19569, 0.300449, 0.555598, 0.854939, 1.39166, 2.19141, 2.57732};
738 const double delta_theta = 10.;
739 int j = int(theta / delta_theta);
743 const double d_break = 5 * b;
745 if (distance >= d_break) {
746 double R_apparent_far = b - par1[j];
747 double ratio_square = (R_apparent_far * R_apparent_far) / (distance * distance);
748 return (2 *
CLHEP::pi * (1 - std::sqrt(1 - ratio_square)));
751 double R_apparent_close = b - par0[j];
752 double ratio_square = (R_apparent_close * R_apparent_close) / (distance * distance);
753 return (2 *
CLHEP::pi * (1 - std::sqrt(1 - ratio_square)));
768 if (
fNTPC == 2 && ((ScintPoint.X() < 0.) != (OpDetPoint.X() < 0.)) &&
786 std::vector<SemiAnalyticalModel::OpticalDetector> opticalDetector;
800 else if (opDet.
isBar()) {
807 length = opDet.
Width();
811 height = opDet.
Width();
823 opticalDetector.emplace_back(
826 return opticalDetector;
std::vector< double > fvis_distances_x_dome
std::vector< std::vector< double > > fborder_corr_flat_lateral
Point_t GetCathodeCenter() const
Returns the expected drift direction based on geometry.
geo::WireReadoutGeom const & fChannelMap
static std::vector< geo::BoxBoundedGeo > extractActiveLArVolume(geo::GeometryCore const &geom)
Utilities related to art service access.
double VISVisibility(geo::Point_t const &ScintPoint, OpticalDetector const &opDet, const double cathode_visibility, geo::Point_t const &hotspot, bool AnodeMode=false) const
Encapsulate the construction of a single cyostat .
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
bool isOpDetInSameTPC(geo::Point_t const &ScintPoint, geo::Point_t const &OpDetPoint) const
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
unsigned int NTPC(CryostatID const &cryoid=details::cryostat_zero) const
Returns the total number of TPCs in the specified cryostat.
bool isBar() const
Returns whether the detector shape is a bar (TGeoBBox).
Point_t const & GetCenter() const
double VUVVisibility(geo::Point_t const &ScintPoint, OpticalDetector const &opDet) const
double fFieldCageTransparencyCathode
const bool fIncludeAnodeReflections
double Rectangle_SolidAngle(const double a, const double b, const double d) const
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::vector< std::vector< std::vector< double > > > fvispars_dome
static constexpr bool isDefinitelyGreaterThan(TReal a, TReal b, TReal tolerance=std::numeric_limits< TReal >::epsilon())
cout<< "Opened file "<< fin<< " ixs= "<< ixs<< endl;if(ixs==0) hhh=(TH1F *) fff-> Get("h1")
const larg4::ISTPC fISTPC
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
std::vector< std::vector< double > > fGHvuvpars_flat_lateral
std::vector< double > fvis_distances_r_flat
const TVector3 fcathode_centre
const std::vector< geo::BoxBoundedGeo > fActiveVolumes
std::vector< std::vector< double > > fborder_corr_dome
double VUVAbsorptionLength() const
bool isSphere() const
Returns whether the detector shape is a hemisphere (TGeoSphere).
Access the description of the physical detector geometry.
auto counter(T begin, T end)
Returns an object to iterate values from begin to end in a range-for loop.
geo::GeometryCore const & fGeom
bool isfinite(Vector const &v)
Returns whether all components of the vector are finite.
SemiAnalyticalModel(const fhicl::ParameterSet &VUVHits, const fhicl::ParameterSet &VISHits, const bool doReflectedLight=false, const bool includeAnodeReflections=false, const bool useXeAbsorption=false)
double fFieldCageTransparencyLateral
const bool fUseXeAbsorption
double fast_acos(double xin)
std::vector< double > fborder_corr_angulo_flat
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)
std::vector< double > fvis_distances_r_dome
bool fApplyFieldCageTransparency
std::vector< double > fborder_corr_angulo_dome
std::vector< std::vector< std::vector< double > > > fvispars_flat_lateral
Test of util::counter and support utilities.
The data type to uniquely identify a TPC.
double Gaisser_Hillas(const double x, const double *par) const
std::vector< double > fvis_distances_x_flat_lateral
unsigned int NOpDets() const
Number of OpDets in the whole detector.
Encapsulate the geometry of an optical detector.
const bool fDoReflectedLight
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
General LArSoft Utilities.
std::vector< std::vector< double > > fGHvuvpars_flat
void detectedDirectVisibilities(std::vector< double > &DetectedVisibilities, geo::Point_t const &ScintPoint) const
double fanode_plane_depth
double DriftDistance() const
Drift distance is defined as the distance between the anode and the cathode, in centimeters.
double Omega_Dome_Model(const double distance, const double theta) const
std::vector< std::vector< double > > fGHvuvpars_dome
double Disk_SolidAngle(const double d, const double h, const double b) const
static constexpr bool isApproximatelyEqual(TReal a, TReal b, TReal tolerance=std::numeric_limits< TReal >::epsilon())
std::vector< double > fvis_distances_x_flat
double fvuv_absorption_length
void detectedReflectedVisibilities(std::vector< double > &ReflDetectedVisibilities, geo::Point_t const &ScintPoint, bool AnodeMode=false) const
static constexpr bool isDefinitelyLessThan(TReal a, TReal b, TReal tolerance=std::numeric_limits< TReal >::epsilon())
std::vector< std::vector< std::vector< double > > > fvispars_flat
std::vector< double > fvis_distances_r_flat_lateral
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
constexpr T pi()
Returns the constant pi (up to 35 decimal digits of precision)
boost::math::policies::policy< boost::math::policies::promote_double< false > > noLDoublePromote
std::vector< OpticalDetector > opticalDetectors() const
const TVector3 fanode_centre
const std::vector< OpticalDetector > fOpDetector
double fAnodeReflectivity
PlaneGeo const & Plane(TPCID const &tpcid, View_t view) const
Returns the specified wire.
std::vector< std::vector< double > > fborder_corr_flat
TPCGeo const & TPC(TPCID const &tpcid=details::tpc_zero) const
Returns the specified TPC.
double interpolate(const std::vector< double > &xData, const std::vector< double > &yData, const double x, const bool extrapolate, size_t i)
static constexpr bool isApproximatelyZero(TReal a, TReal tolerance=std::numeric_limits< TReal >::epsilon())
art framework interface to geometry description
cet::coded_exception< error, detail::translate > exception
OpDetGeo const & OpDetGeoFromOpDet(unsigned int OpDet) const
Returns the geo::OpDetGeo object for the given detector number.
std::vector< double > fborder_corr_angulo_flat_lateral