46 #include <G4SystemOfUnits.hh>
61 , m_detector(detector)
65 , m_strobe_separation(0.)
70 std::cout <<
"Creating PHG4MvtxHitReco for detector = " <<
detector << std::endl;
74 m_rng.reset(gsl_rng_alloc(gsl_rng_mt19937));
94 <<
"PHG4MvtxHitReco::InitRun\n"
95 <<
" m_tmin: " <<
m_tmin <<
"ns, m_tmax: " <<
m_tmax <<
"ns\n"
96 <<
" m_strobe_width: " << m_strobe_width <<
"\n"
104 auto dstNode =
dynamic_cast<PHCompositeNode *
>(iter.findFirst(
"PHCompositeNode",
"DST"));
108 auto runNode =
dynamic_cast<PHCompositeNode *
>(iter.findFirst(
"PHCompositeNode",
"RUN"));
116 runNode->addNode(runDetNode);
122 auto hitsetcontainer = findNode::getClass<TrkrHitSetContainer>(topNode,
"TRKR_HITSET");
123 if (!hitsetcontainer)
130 dstNode->addNode(trkrnode);
135 trkrnode->addNode(newNode);
139 auto hittruthassoc = findNode::getClass<TrkrHitTruthAssoc>(topNode,
"TRKR_HITTRUTHASSOC");
147 dstNode->addNode(trkrnode);
152 trkrnode->addNode(newNode);
156 m_truthtracks = findNode::getClass<TrkrTruthTrackContainer>(topNode,
"TRKR_TRUTHTRACKCONTAINER");
162 dstNode->addNode(newNode);
165 m_truthclusters = findNode::getClass<TrkrClusterContainer>(topNode,
"TRKR_TRUTHCLUSTERCONTAINER");
170 dstNode->addNode(newNode);
173 m_truthinfo = findNode::getClass<PHG4TruthInfoContainer>(topNode,
"G4TruthInfo");
176 std::cout <<
PHWHERE <<
" PHG4TruthInfoContainer node not found on node tree" << std::endl;
182 mClusHitsVerbose = findNode::getClass<ClusHitsVerbosev1>(topNode,
"Trkr_TruthClusHitsVerbose");
190 dstNode->addNode(DetNode);
194 DetNode->addNode(newNode);
203 ActsGeometry *tgeometry = findNode::getClass<ActsGeometry>(topNode,
"ActsGeometry");
206 std::cout <<
"Could not locate acts geometry" << std::endl;
212 auto g4hitContainer = findNode::getClass<PHG4HitContainer>(topNode, g4hitnodename);
217 auto geoNode = findNode::getClass<PHG4CylinderGeomContainer>(topNode, geonodename);
221 auto trkrHitSetContainer = findNode::getClass<TrkrHitSetContainer>(topNode,
"TRKR_HITSET");
222 assert(trkrHitSetContainer);
225 auto hitTruthAssoc = findNode::getClass<TrkrHitTruthAssoc>(topNode,
"TRKR_HITTRUTHASSOC");
233 double clearance = 200.0;
235 m_tmin = alpide_pulse.second - clearance;
245 auto layer_range = g4hitContainer->getLayers();
246 for (
auto layer_it = layer_range.first; layer_it != layer_range.second; ++layer_it)
249 const auto layer = *layer_it;
260 double xpixw = layergeom->get_pixel_x();
261 double xpixw_half = xpixw / 2.0;
262 double zpixw = layergeom->get_pixel_z();
263 double zpixw_half = zpixw / 2.0;
264 int maxNX = layergeom->get_NX();
265 int maxNZ = layergeom->get_NZ();
268 for (
auto g4hit_it = g4hit_range.first; g4hit_it != g4hit_range.second; ++g4hit_it)
271 auto g4hit = g4hit_it->second;
279 unsigned int n_replica = 1;
284 double lead_edge = g4hit->get_t(0) *
ns + alpide_pulse.first;
285 double fall_edge = g4hit->get_t(1) *
ns + alpide_pulse.second;
288 std::cout <<
" MvtxHitReco: t0 " << g4hit->get_t(0) <<
" t1 " << g4hit->get_t(1) <<
" lead_edge " << lead_edge
289 <<
" fall_edge " << fall_edge <<
" tmin " <<
m_tmin <<
" tmax " <<
m_tmax << std::endl;
296 n_replica += t1_strobe_frame - t0_strobe_frame;
301 <<
"MVTX is in strobed timing mode\n"
302 <<
"layer " <<
layer <<
" t0(ns) " << g4hit->get_t(0) <<
" t1(ns) " << g4hit->get_t(1) <<
"\n"
303 <<
"strobe_zero_tm_start(us): " << strobe_zero_tm_start / microsecond <<
"\n"
306 <<
"alpide pulse start(us): " << alpide_pulse.first / microsecond <<
"\n"
307 <<
"alpide pulse end(us): " << alpide_pulse.second / microsecond <<
"\n"
308 <<
"tm_zero_strobe_frame: " << t0_strobe_frame <<
"\n"
309 <<
"tm_one_strobe_frame: " << t1_strobe_frame <<
"\n"
310 <<
"number of hit replica: " << n_replica <<
"\n"
320 TVector3 local_in(g4hit->get_local_x(0), g4hit->get_local_y(0), g4hit->get_local_z(0));
321 TVector3 local_out(g4hit->get_local_x(1), g4hit->get_local_y(1), g4hit->get_local_z(1));
322 TVector3 midpoint((local_in.X() + local_out.X()) / 2.0, (local_in.Y() + local_out.Y()) / 2.0, (local_in.Z() + local_out.Z()) / 2.0);
327 <<
" world entry point position: "
328 << g4hit->get_x(0) <<
" " << g4hit->get_y(0) <<
" " << g4hit->get_z(0) <<
"\n"
329 <<
" world exit point position: "
330 << g4hit->get_x(1) <<
" " << g4hit->get_y(1) <<
" " << g4hit->get_z(1) <<
"\n"
331 <<
" local coords of entry point from G4 "
332 << g4hit->get_local_x(0) <<
" " << g4hit->get_local_y(0) <<
" " << g4hit->get_local_z(0)
335 TVector3 world_in(g4hit->get_x(0), g4hit->get_y(0), g4hit->get_z(0));
339 TVector3 local_in_check = layergeom->get_local_from_world_coords(
surf, tgeometry, world_in);
341 <<
" local coords of entry point from geom (a check) "
342 << local_in_check.X() <<
" " << local_in_check.Y() <<
" " << local_in_check.Z() <<
"\n"
343 <<
" local coords of exit point from G4 "
344 << g4hit->get_local_x(1) <<
" " << g4hit->get_local_y(1) <<
" " << g4hit->get_local_z(1)
346 <<
" local coords of exit point from geom (a check) "
347 << local_out.X() <<
" " << local_out.Y() <<
" " << local_out.Z()
391 int pixel_number_in = layergeom->get_pixel_from_local_coords(local_in);
393 int pixel_number_out = layergeom->get_pixel_from_local_coords(local_out);
395 if (pixel_number_in < 0 || pixel_number_out < 0)
398 <<
"Oops! got negative pixel number in layer " << layergeom->get_layer()
399 <<
" pixel_number_in " << pixel_number_in
400 <<
" pixel_number_out " << pixel_number_out
401 <<
" local_in = " << local_in.X() <<
" " << local_in.Y() <<
" " << local_in.Z()
402 <<
" local_out = " << local_out.X() <<
" " << local_out.Y() <<
" " << local_out.Z()
410 <<
"entry pixel number " << pixel_number_in
411 <<
" exit pixel number " << pixel_number_out
415 std::vector<int> vpixel;
416 std::vector<int> vxbin;
417 std::vector<int> vzbin;
418 std::vector<std::pair<double, double> > venergy;
436 TVector3 pathvec = local_in - local_out;
444 double diffusion_width_max = 25.0e-04;
445 double diffusion_width_min = 8.0e-04;
447 double ydrift_max = pathvec.Y();
454 int xbin_in = layergeom->get_pixel_X_from_pixel_number(pixel_number_in);
455 int zbin_in = layergeom->get_pixel_Z_from_pixel_number(pixel_number_in);
456 int xbin_out = layergeom->get_pixel_X_from_pixel_number(pixel_number_out);
457 int zbin_out = layergeom->get_pixel_Z_from_pixel_number(pixel_number_out);
459 int xbin_max, xbin_min;
461 if (xbin_in > xbin_out)
463 xbin_max = xbin_in + nadd;
464 xbin_min = xbin_out - nadd;
468 xbin_max = xbin_out + nadd;
469 xbin_min = xbin_in - nadd;
472 int zbin_max, zbin_min;
473 if (zbin_in > zbin_out)
475 zbin_max = zbin_in + nadd;
476 zbin_min = zbin_out - nadd;
480 zbin_max = zbin_out + nadd;
481 zbin_min = zbin_in - nadd;
486 if (xbin_min < 0) xbin_min = 0;
487 if (zbin_min < 0) zbin_min = 0;
488 if (xbin_max >= maxNX) xbin_max = maxNX - 1;
489 if (zbin_max >= maxNZ) xbin_max = maxNZ - 1;
493 std::cout <<
" xbin_in " << xbin_in <<
" xbin_out " << xbin_out <<
" xbin_min " << xbin_min <<
" xbin_max " << xbin_max << std::endl;
494 std::cout <<
" zbin_in " << zbin_in <<
" zbin_out " << zbin_out <<
" zbin_min " << zbin_min <<
" zbin_max " << zbin_max << std::endl;
499 if (xbin_max - xbin_min > 12 || zbin_max - zbin_min > 12)
continue;
502 double pixenergy[12][12] = {};
503 double pixeion[12][12] = {};
506 for (
int i = 0;
i < nsegments;
i++)
512 double frac = interval / (
double) (2 * nsegments);
513 TVector3 segvec(pathvec.X() * frac, pathvec.Y() * frac, pathvec.Z() * frac);
514 segvec = segvec + local_out;
518 double ydrift = segvec.Y() - local_out.Y();
522 double ydiffusion_radius = diffusion_width_min + (ydrift / ydrift_max) * (diffusion_width_max - diffusion_width_min);
528 <<
" interval " << interval
530 <<
" local_in.X " << local_in.X()
531 <<
" local_in.Z " << local_in.Z()
532 <<
" local_in.Y " << local_in.Y()
533 <<
" pathvec.X " << pathvec.X()
534 <<
" pathvec.Z " << pathvec.Z()
535 <<
" pathvec.Y " << pathvec.Y()
536 <<
" segvec.X " << segvec.X()
537 <<
" segvec.Z " << segvec.Z()
538 <<
" segvec.Y " << segvec.Y()
539 <<
" ydrift " << ydrift
540 <<
" ydrift_max " << ydrift_max
541 <<
" ydiffusion_radius " << ydiffusion_radius
545 for (
int ix = xbin_min; ix <= xbin_max; ix++)
547 for (
int iz = zbin_min; iz <= zbin_max; iz++)
550 int pixnum = layergeom->get_pixel_number_from_xbin_zbin(ix, iz);
555 <<
" pixnum < 0 , pixnum = " << pixnum <<
"\n"
556 <<
" ix " << ix <<
" iz " << iz <<
"\n"
557 <<
" xbin_min " << xbin_min <<
" zbin_min " << zbin_min <<
"\n"
558 <<
" xbin_max " << xbin_max <<
" zbin_max " << zbin_max <<
"\n"
559 <<
" maxNX " << maxNX <<
" maxNZ " << maxNZ
563 TVector3
tmp = layergeom->get_local_coords_from_pixel(pixnum);
565 double x1 = tmp.X() - xpixw_half;
566 double z1 = tmp.Z() + zpixw_half;
567 double x2 = tmp.X() + xpixw_half;
568 double z2 = tmp.Z() - zpixw_half;
574 pixenergy[ix - xbin_min][iz - zbin_min] += pixarea_frac * g4hit->get_edep() / (float) nsegments;
577 pixeion[ix - xbin_min][iz - zbin_min] += pixarea_frac * g4hit->get_eion() / (float) nsegments;
582 <<
" pixnum " << pixnum <<
" xbin " << ix <<
" zbin " << iz
583 <<
" pixel_area fraction of circle " << pixarea_frac <<
" accumulated pixel energy " << pixenergy[ix - xbin_min][iz - zbin_min]
591 for (
int ix = xbin_min; ix <= xbin_max; ix++)
593 for (
int iz = zbin_min; iz <= zbin_max; iz++)
595 if (pixenergy[ix - xbin_min][iz - zbin_min] > 0.0)
597 int pixnum = layergeom->get_pixel_number_from_xbin_zbin(ix, iz);
598 vpixel.push_back(pixnum);
601 std::pair<double, double> tmppair = std::make_pair(pixenergy[ix - xbin_min][iz - zbin_min], pixeion[ix - xbin_min][iz - zbin_min]);
602 venergy.push_back(tmppair);
606 <<
" Added pixel number " << pixnum <<
" xbin " << ix
607 <<
" zbin " << iz <<
" to vectors with energy " << pixenergy[ix - xbin_min][iz - zbin_min]
619 for (
unsigned int i1 = 0; i1 < vpixel.size(); i1++)
623 for (
unsigned int i_rep = 0; i_rep < n_replica; i_rep++)
625 int strobe = t0_strobe_frame + i_rep;
627 if (strobe < -16) strobe = -16;
628 if (strobe >= 16) strobe = 15;
639 hit = hitsetit->second->getHit(hitkey);
644 hitsetit->second->addHitSpecificKey(hitkey, hit);
648 double hitenergy = venergy[i1].first * TrkrDefs::MvtxEnergyScaleup;
654 std::cout <<
" added hit " << hitkey <<
" to hitset " << hitsetkey <<
" with strobe id " << strobe <<
" in layer " <<
layer
655 <<
" with energy " << hit->
getEnergy() / TrkrDefs::MvtxEnergyScaleup << std::endl;
664 hitTruthAssoc->findOrAddAssoc(bare_hitsetkey, hitkey, g4hit_it->first);
675 std::cout <<
"From PHG4MvtxHitReco: " << std::endl;
676 hitTruthAssoc->identify();
685 std::cout <<
PHWHERE <<
": content of clusters " << std::endl;
687 std::cout <<
" Number of tracks: " << tmap.size() << std::endl;
688 for (
auto& _pair : tmap) {
689 auto& track = _pair.second;
691 printf(
"id(%2i) phi:eta:pt(", (
int)track->getTrackid());
692 std::cout <<
"phi:eta:pt(";
693 printf(
"%5.2f:%5.2f:%5.2f", track->getPhi(), track->getPseudoRapidity(), track->getPt());
696 std::cout <<
") nclusters(" << track->getClusters().size() <<
") ";
698 for (
auto cluskey : track->getClusters()) {
703 if (nclusprint > 0 && nclus >= nclusprint) {
704 std::cout <<
" ... ";
709 std::cout <<
PHWHERE <<
" ----- end of clusters " << std::endl;
725 std::cout <<
"energy_deposited: " << energy_deposited << std::endl;
735 return std::make_pair<double, double>(1.5 * microsecond, 5.9 * microsecond);
746 strobe_frame += (alpide_time < strobe_zero_tm_start) ? -1 : 0;
755 <<
"PHG4MvtxHitReco: Set Mvtx timing window parameters from macro for layer = "
756 << detid <<
" to tmin = " << tmin <<
" tmax = " << tmax
781 return bare_hitsetkey;
789 int new_trkid = (g4hit==
nullptr) ? -1 : g4hit->
get_trkid();
790 bool is_new_track = (new_trkid !=
m_trkid);
791 if (
Verbosity()>5) std::cout <<
PHWHERE << std::endl <<
" -> Checking status of PHG4Hit. Track id("<<new_trkid<<
")" << std::endl;
815 if (
Verbosity()>2) std::cout <<
PHWHERE << std::endl <<
" -> Found new embedded track with id: " << new_trkid << std::endl;
848 hit = hitsetit->second->getHit(hitkey);
853 hitsetit->second->addHitSpecificKey(hitkey, hit);
924 std::multimap<TrkrDefs::hitsetkey, TrkrDefs::hitsetkey> hitset_multimap;
925 std::set<TrkrDefs::hitsetkey> bare_hitset_set;
929 hitsetitr != hitsetrange.second;
940 hitset_multimap.insert(std::make_pair(bare_hitsetkey,
hitsetkey));
941 bare_hitset_set.insert(bare_hitsetkey);
943 if(
Verbosity() > 0) std::cout <<
" found hitsetkey " <<
hitsetkey <<
" for bare_hitsetkey " << bare_hitsetkey << std::endl;
948 for(
auto bare_it = bare_hitset_set.begin(); bare_it != bare_hitset_set.end(); ++bare_it)
950 auto bare_hitsetkey = *bare_it;
952 if(
Verbosity() > 0) std::cout <<
" bare_hitset " << bare_hitsetkey <<
" initially has " << bare_hitset->
size() <<
" hits " << std::endl;
954 auto bare_hitsetrange= hitset_multimap.equal_range(bare_hitsetkey);
955 for(
auto it = bare_hitsetrange.first;
it != bare_hitsetrange.second; ++
it)
962 if(
Verbosity() > 0) std::cout <<
" process hitsetkey " <<
hitsetkey <<
" for bare_hitsetkey " << bare_hitsetkey << std::endl;
968 std::cout <<
" hitsetkey " <<
hitsetkey <<
" has strobe " << strobe <<
" and has " << hitset->
size() <<
" hits, so copy it" << std::endl;
972 hitr != hitrangei.second;
975 auto hitkey = hitr->first;
976 if(
Verbosity() > 0) std::cout <<
" found hitkey " <<
hitkey << std::endl;
981 if(
Verbosity() > 0) std::cout <<
" hitkey " <<
hitkey <<
" is already in bare hitsest, do not copy" << std::endl;
986 if(
Verbosity() > 0) std::cout <<
" copying over hitkey " <<
hitkey << std::endl;
987 auto old_hit = hitr->second;
989 new_hit->
setAdc(old_hit->getAdc());
1002 PHG4CylinderGeomContainer* geom_container = findNode::getClass<PHG4CylinderGeomContainer>(topNode,
"CYLINDERGEOM_MVTX");
1003 if (!geom_container) {
1004 std::cout <<
PHWHERE << std::endl;
1005 std::cout <<
"WARNING: cannot find the geometry CYLINDERGEOM_MVTX" << std::endl;
1017 hitsetitr != hitsetrange.second;
1029 std::cout <<
"MvtxClusterizer found hitsetkey " << hitsetitr->first <<
" layer " << layer <<
" stave " << stave <<
" chip " << chip <<
" strobe " << strobe << std::endl;
1042 std::set<int> zbins;
1045 double locxsum = 0.;
1046 double loczsum = 0.;
1048 double locclusx = NAN;
1049 double locclusz = NAN;
1060 double sum_adc { 0. };
1061 for (
auto ihit = hitrangei.first;
ihit != hitrangei.second; ++
ihit) {
1062 sum_adc +=
ihit->second->getAdc();
1065 std::map<int,unsigned int> m_iphi, m_it, m_iphiCut, m_itCut;
1069 double npixels {0.};
1070 for (
auto ihit = hitrangei.first;
ihit != hitrangei.second; ++
ihit)
1072 const auto adc =
ihit->second->getAdc();
1077 std::map<int,unsigned int>& m_phi = (adc<threshold) ? m_iphiCut : m_iphi;
1078 std::map<int,unsigned int>& m_z = (adc<threshold) ? m_itCut : m_it;
1080 auto pnew = m_phi.try_emplace(row,adc);
1081 if (!pnew.second) pnew.first->second += adc;
1083 pnew = m_z.try_emplace(col,adc);
1084 if (!pnew.second) pnew.first->second += adc;
1086 if (adc<threshold)
continue;
1091 phibins.insert(row);
1094 auto local_coords = layergeom->get_local_coords_from_pixel(row,col);
1101 local_coords.SetY( 1
e-4 );
1104 locxsum += local_coords.X();
1105 loczsum += local_coords.Z();
1110 for (
auto& hit : m_iphi) {
1111 std::cout <<
" m_phi(" << hit.first <<
" : " << hit.second<<
") " << std::endl;
1121 locclusx = locxsum / npixels;
1122 locclusz = loczsum / npixels;
1124 const double pitch = layergeom->get_pixel_x();
1125 const double length = layergeom->get_pixel_z();
1126 const double phisize = phibins.size() * pitch;
1131 std::cout <<
" MvtxClusterizer: cluskey " << ckey <<
" layer " << layer <<
" rad " << layergeom->get_radius() <<
" phibins " << phibins.size() <<
" pitch " << pitch <<
" phisize " << phisize
1132 <<
" zbins " << zbins.size() <<
" length " << length <<
" zsize " << zsize
1133 <<
" local x " << locclusx <<
" local y " << locclusz
1140 auto clus = std::make_unique<TrkrClusterv4>();
1141 clus->setAdc(npixels);
1142 clus->setLocalX(locclusx);
1143 clus->setLocalY(locclusz);
1145 clus->setPhiSize(phibins.size());
1146 clus->setZSize(zbins.size());
1149 clus->setSubSurfKey(0);
1164 std::cout <<
PHWHERE << std::endl;
1165 std::cout <<
"Error: only cluster version 4 allowed." << std::endl;