30 #include <phparameter/PHParameterInterface.h>
42 #include <gsl/gsl_randist.h>
43 #include <gsl/gsl_rng.h>
65 return std::exp(-
square(x / sigma) / 2) / (sigma * std::sqrt(2 * M_PI));
70 inline T bind_angle(
const T& angle)
74 return angle - 2 * M_PI;
76 else if (angle < -M_PI)
78 return angle + 2 * M_PI;
88 inline T get_rectangular_fraction(
const T& xloc,
const T& sigma,
const T& pitch)
90 return (std::erf((xloc + pitch / 2) / (M_SQRT2 * sigma)) - std::erf((xloc - pitch / 2) / (M_SQRT2 * sigma))) / 2;
98 inline T get_zigzag_fraction(
const T& xloc,
const T& sigma,
const T& pitch)
102 (pitch - xloc) * (std::erf(xloc / (M_SQRT2 * sigma)) - std::erf((xloc - pitch) / (M_SQRT2 * sigma))) / (pitch * 2) + (gaus(xloc - pitch, sigma) - gaus(xloc, sigma)) *
square(sigma) / pitch
105 + (pitch + xloc) * (std::erf((xloc + pitch) / (M_SQRT2 *
sigma)) - std::erf(xloc / (M_SQRT2 * sigma))) / (pitch * 2) + (gaus(xloc + pitch, sigma) - gaus(xloc, sigma)) *
square(sigma) / pitch;
111 out <<
"(" << position.x() <<
", " << position.y() <<
", " << position.z() <<
")";
124 m_rng.reset(gsl_rng_alloc(gsl_rng_mt19937));
147 <<
"PHG4MicromegasHitReco::InitRun\n"
148 <<
" m_tmin: " <<
m_tmin <<
"ns, m_tmax: " <<
m_tmax <<
"ns\n"
150 <<
" m_gain: " <<
m_gain <<
"\n"
162 std::cout <<
"PHG4MicromegasHitReco::InitRun - DST Node missing, doing nothing." << std::endl;
167 auto hitsetcontainer = findNode::getClass<TrkrHitSetContainer>(topNode,
"TRKR_HITSET");
168 if (!hitsetcontainer)
170 std::cout <<
"PHG4MicromegasHitReco::InitRun - creating TRKR_HITSET." << std::endl;
178 dstNode->addNode(trkrnode);
184 trkrnode->addNode(newNode);
188 auto hittruthassoc = findNode::getClass<TrkrHitTruthAssoc>(topNode,
"TRKR_HITTRUTHASSOC");
191 std::cout <<
"PHG4MicromegasHitReco::InitRun - creating TRKR_HITTRUTHASSOC." << std::endl;
199 dstNode->addNode(trkrnode);
204 trkrnode->addNode(newNode);
215 auto g4hitcontainer = findNode::getClass<PHG4HitContainer>(topNode,
"G4HIT_MICROMEGAS");
219 m_acts_geometry = findNode::getClass<ActsGeometry>(topNode,
"ActsGeometry");
224 auto geonode = findNode::getClass<PHG4CylinderGeomContainer>(topNode, geonodename.c_str());
228 auto trkrhitsetcontainer = findNode::getClass<TrkrHitSetContainer>(topNode,
"TRKR_HITSET");
229 assert(trkrhitsetcontainer);
232 auto hittruthassoc = findNode::getClass<TrkrHitTruthAssoc>(topNode,
"TRKR_HITTRUTHASSOC");
236 auto layer_range = g4hitcontainer->getLayers();
237 for (
auto layer_it = layer_range.first; layer_it != layer_range.second; ++layer_it)
240 const auto layer = *layer_it;
253 const auto mesh_local_z = layergeom->get_drift_direction() == MicromegasDefs::DriftDirection::OUTWARD ? layergeom->get_thickness() / 2 : -layergeom->get_thickness() / 2;
268 for (
auto g4hit_it = g4hit_range.first; g4hit_it != g4hit_range.second; ++g4hit_it)
271 PHG4Hit* g4hit = g4hit_it->second;
291 const auto local_in = layergeom->get_local_from_world_coords(tileid,
m_acts_geometry, world_in);
292 const auto local_out = layergeom->get_local_from_world_coords(tileid,
m_acts_geometry, world_out);
303 const auto hitset_it = trkrhitsetcontainer->findOrAddHitSet(hitsetkey);
306 using charge_map_t = std::map<int, double>;
307 charge_map_t total_charges;
310 for (uint ie = 0; ie < nprimary; ++ie)
315 const auto t = gsl_ran_flat(
m_rng.get(), 0.0, 1.0);
316 auto local = local_in *
t + local_out * (1.0 -
t);
322 const double z = local.z();
323 const double drift_distance = std::abs(z - mesh_local_z);
325 const double diffusion_angle = gsl_ran_flat(
m_rng.get(), -M_PI, M_PI);
328 local += TVector3(diffusion * std::cos(diffusion_angle), diffusion * std::sin(diffusion_angle), 0);
333 if (added_smear_sigma > 0)
336 const double added_smear_trans = gsl_ran_gaussian(
m_rng.get(), added_smear_sigma);
337 const double added_smear_angle = gsl_ran_flat(
m_rng.get(), -M_PI, M_PI);
338 local += TVector3(added_smear_trans * std::cos(added_smear_angle), added_smear_trans * std::sin(added_smear_angle), 0);
347 const auto sum = std::accumulate(fractions.begin(), fractions.end(),
double(0),
349 {
return value + pair.second; });
350 std::cout <<
"PHG4MicromegasHitReco::process_event - sum: " <<
sum << std::endl;
357 for (
const auto& pair : fractions)
359 const int strip = pair.first;
360 if (strip < 0 || strip >= (
int) layergeom->get_strip_count(tileid,
m_acts_geometry))
365 const auto it = total_charges.lower_bound(strip);
366 if (
it != total_charges.end() &&
it->first == strip)
368 it->second += pair.second *
gain;
372 total_charges.insert(
it, std::make_pair(strip, pair.second *
gain));
379 for (
const auto pair : total_charges)
382 const int strip = pair.first;
386 auto hit = hitset_it->second->getHit(hitkey);
391 hitset_it->second->addHitSpecificKey(hitkey, hit);
398 hittruthassoc->addAssoc(hitsetkey, hitkey, g4hit_it->first);
422 static constexpr
double Ar_dEdx = 2.44;
423 static constexpr
double iC4H10_dEdx = 5.93;
424 static constexpr
double mix_dEdx = 0.9 * Ar_dEdx + 0.1 * iC4H10_dEdx;
427 static constexpr
double Ar_ntot = 94;
428 static constexpr
double iC4H10_ntot = 195;
429 static constexpr
double mix_ntot = 0.9 * Ar_ntot + 0.1 * iC4H10_ntot;
432 static constexpr
double mix_electrons_per_gev = 1e6 * mix_ntot / mix_dEdx;
470 const TVector2& local_coords,
483 const auto pitch = layergeom->
get_pitch();
487 const int nstrips = 5. * sigma / pitch + 1;
488 const auto stripnum_min = std::clamp<int>(stripnum - nstrips, 0, strip_count);
489 const auto stripnum_max = std::clamp<int>(stripnum + nstrips, 0, strip_count);
495 for (
int strip = stripnum_min; strip <= stripnum_max; ++strip)
515 const auto fraction = zigzag_strips ? get_zigzag_fraction(xloc, sigma, pitch) : get_rectangular_fraction(xloc, sigma, pitch);
518 charge_list.push_back(std::make_pair(strip, fraction));