133 auto const* geom = lar::providerFrom<geo::Geometry>();
140 if (!
evt.getByLabel(
"largeant", mcpHandle))
142 <<
"Failed to get a handle to MCParticles using largeant\n";
155 sim::ParticleList
const& plist = pi_serv->
ParticleList();
160 std::vector<int> trkIDs;
162 std::vector<unsigned int> MCPIs;
169 bool isCharged = (pdg == 11) || (pdg == 13) || (pdg == 211) || (pdg == 321) || (pdg == 2212);
170 if (!isCharged)
continue;
172 float TMeV = 1000 * (part->
E() - part->
Mass());
174 if (TMeV < 1)
continue;
176 unsigned int mcpi = UINT_MAX;
177 for (mcpi = 0; mcpi < (*mcpHandle).size(); ++mcpi)
178 if ((*mcpHandle)[mcpi].TrackId() == trackID)
break;
179 if (mcpi == UINT_MAX) {
180 std::cout <<
"Failed to find a MCParticle from ParticleList\n";
183 trkIDs.push_back(trackID);
184 MCPIs.push_back(mcpi);
186 if (trkIDs.empty())
return;
192 std::vector<std::pair<unsigned int, unsigned int>> hitRange(geom->NTPC() + 1);
196 for (
auto&
hr : hitRange)
197 hr = std::make_pair(UINT_MAX, UINT_MAX);
198 for (
size_t iht = 0; iht < (*fHitHandle).size(); ++iht) {
199 auto&
hit = (*fHitHandle)[iht];
201 unsigned int tpc =
hit.WireID().TPC;
209 for (
auto& tide : tides) {
211 if (tide.energyFrac < 0.5)
continue;
212 int trackID = tide.trackID;
214 for (
size_t indx = 0; indx < trkIDs.size(); ++indx) {
215 if (trkIDs[indx] == trackID) {
225 if (hitRange[tpc].first == UINT_MAX) hitRange[tpc].first = iht;
226 hitRange[tpc].second = iht;
237 myprt <<
"Checking " << trkIDs.size() <<
" selected MCParticles with the requested TruthOrigin";
238 if (
fInTPC == UINT_MAX) { myprt <<
" in all TPCs\n"; }
240 myprt <<
" in TPC " <<
fInTPC;
244 myprt <<
"Found " << nMatch <<
" MC-matched hits with the requested TruthOrigin";
245 myprt <<
" out of " << nInTPC <<
" total hits.\n";
246 myprt <<
"Found " << noMatch <<
" hits not matched to ANY MCParticle.\n";
249 std::vector<std::pair<unsigned int, unsigned int>> mcpCnt;
251 if (mcpi == UINT_MAX)
continue;
252 unsigned short mIndx = 0;
253 for (mIndx = 0; mIndx < mcpCnt.size(); ++mIndx)
254 if (mcpCnt[mIndx].first == mcpi)
break;
255 if (mIndx == mcpCnt.size()) mcpCnt.push_back(std::make_pair(mcpi, 0));
257 ++mcpCnt[mIndx].second;
259 myprt <<
" MCPI TrackID PDGCode T(MeV) nHits Process";
260 for (
auto mcpcnt : mcpCnt) {
262 unsigned int mcpi = mcpcnt.first;
263 auto& mcp = (*mcpHandle)[mcpi];
267 int TMeV = 1000 * (mcp.E() - mcp.Mass());
270 myprt <<
" " << mcp.Process();
275 std::vector<std::vector<unsigned int>> recoHits;
277 std::vector<unsigned int> recoIndex;
289 if (!hitsFromCls.isValid())
290 throw cet::exception(
"ClusterTrackAna") <<
"Failed to get a handle to Cluster -> Hit assns\n";
291 for (
unsigned int icl = 0; icl < (*inputClusters).size(); ++icl) {
292 std::vector<art::Ptr<recob::Hit>> cluhits = hitsFromCls.at(icl);
293 if (cluhits.empty())
continue;
297 <<
"Hits associated with ClusterModuleLabel are in a different collection than " 304 std::vector<unsigned int> hitsIndex;
305 for (
auto& cluhit : cluhits) {
306 if (fHitMCPIndex[cluhit.key()] != UINT_MAX) hitsIndex.push_back(cluhit.key());
308 if (hitsIndex.empty())
continue;
309 recoIndex.push_back(icl);
310 recoHits.push_back(hitsIndex);
319 if (!hitsFromTrk.isValid())
320 throw cet::exception(
"ClusterTrackAna") <<
"Failed to get a handle to Track -> Hit assns\n";
321 for (
unsigned int itk = 0; itk < (*inputTracks).size(); ++itk) {
322 std::vector<art::Ptr<recob::Hit>> trkhits = hitsFromTrk.at(itk);
323 if (trkhits.empty())
continue;
327 <<
"Hits associated with TrackModuleLabel are in a different collection than " 331 std::vector<unsigned int> hitsIndex;
332 for (
auto& trkhit : trkhits) {
333 if (fHitMCPIndex[trkhit.key()] != UINT_MAX) hitsIndex.push_back(trkhit.key());
335 if (hitsIndex.empty())
continue;
336 recoIndex.push_back(itk);
337 recoHits.push_back(hitsIndex);
341 for (
const auto& tpcid : geom->IterateTPCIDs()) {
342 unsigned int tpc = tpcid.TPC;
343 if (hitRange[tpc].first == UINT_MAX)
continue;
345 for (
unsigned short plane = 0; plane < geom->Nplanes(); ++plane) {
346 unsigned int tpcMatHitCnt = 0;
347 unsigned int tpcTotHitCnt = 0;
350 std::vector<std::pair<unsigned int, float>> mcpCnt;
352 std::vector<std::vector<std::pair<unsigned int, float>>> mcpClsCnt;
353 for (
unsigned int iht = hitRange[tpc].first; iht <= hitRange[tpc].second; ++iht) {
354 auto&
hit = (*fHitHandle)[iht];
355 if (
hit.WireID().TPC != tpc)
continue;
356 if (
hit.WireID().Plane != plane)
continue;
360 if (fHitMCPIndex[iht] == UINT_MAX)
continue;
362 unsigned int mcpi = fHitMCPIndex[iht];
363 unsigned short mIndx = 0;
364 for (mIndx = 0; mIndx < mcpCnt.size(); ++mIndx)
365 if (mcpCnt[mIndx].first == mcpi)
break;
366 if (mIndx == mcpCnt.size()) {
368 mcpCnt.push_back(std::make_pair(mcpi, 0));
369 mcpClsCnt.resize(mcpCnt.size());
372 ++mcpCnt[mIndx].second;
377 myprt <<
"TPC:" << tpc <<
" Plane:" << plane <<
" has " << tpcMatHitCnt <<
"/" 379 myprt <<
" (MC-matched hits) / (all hits)";
381 if (tpcMatHitCnt < 3)
continue;
383 for (
unsigned int ii = 0; ii < recoHits.size(); ++ii) {
384 float nRecoHitsInPlane = 0;
385 float nRecoMatHitsInPlane = 0;
386 for (
auto iht : recoHits[ii]) {
387 auto&
hit = (*fHitHandle)[iht];
388 if (
hit.WireID().TPC != tpc)
continue;
389 if (
hit.WireID().Plane != plane)
continue;
391 if (fHitMCPIndex[iht] == UINT_MAX)
continue;
392 ++nRecoMatHitsInPlane;
393 unsigned int mcpi = fHitMCPIndex[iht];
396 unsigned short mIndx = 0;
397 for (mIndx = 0; mIndx < mcpCnt.size(); ++mIndx)
398 if (mcpCnt[mIndx].first == mcpi)
break;
399 if (mIndx == mcpCnt.size()) {
400 std::cout <<
"Logic error: fHitMCPIndex = " << fHitMCPIndex[iht]
401 <<
" is valid but isn't in the list of MCParticles to use. Please send email " 402 "to baller@fnal.gov.\n";
405 unsigned short cIndx = 0;
406 for (cIndx = 0; cIndx < mcpClsCnt[mIndx].size(); ++cIndx)
407 if (mcpClsCnt[mIndx][cIndx].first == ii)
break;
408 if (cIndx == mcpClsCnt[mIndx].
size()) mcpClsCnt[mIndx].
push_back(std::make_pair(ii, 0));
409 ++mcpClsCnt[mIndx][cIndx].second;
411 if (nRecoMatHitsInPlane == 0)
continue;
414 for (
unsigned short mIndx = 0; mIndx < mcpCnt.size(); ++mIndx) {
416 if (mcpCnt[mIndx].
second < 3)
continue;
417 unsigned int mcpi = mcpCnt[mIndx].first;
418 auto& mcp = (*mcpHandle)[mcpi];
419 unsigned int pdgCode =
abs(mcp.PdgCode());
420 unsigned short pIndx = USHRT_MAX;
421 if (pdgCode == 11) pIndx = 0;
422 if (pdgCode == 13) pIndx = 1;
423 if (pdgCode == 211) pIndx = 2;
424 if (pdgCode == 321) pIndx = 3;
425 if (pdgCode == 2212) pIndx = 4;
426 if (mcpClsCnt[mIndx].
empty()) {
432 myprt <<
" MCPI " << mcpi;
433 int TMeV = 1000 * (mcp.E() - mcp.Mass());
434 myprt <<
" " << TMeV <<
" MeV";
436 if (pdgCode == 11) partName =
"El";
437 if (pdgCode == 13) partName =
"Mu";
438 if (pdgCode == 211) partName =
"Pi";
439 if (pdgCode == 311) partName =
"Ka";
440 if (pdgCode == 2212) partName =
"Pr";
443 unsigned int firstHitIndex = UINT_MAX;
444 unsigned int lastHitIndex = UINT_MAX;
446 myprt <<
" Failed to reconstruct. Truth-matched hit range from ";
450 myprt <<
" <- EP = 0!";
454 std::pair<unsigned int, float> big = std::make_pair(UINT_MAX, 0);
455 for (
unsigned short cIndx = 0; cIndx < mcpClsCnt[mIndx].size(); ++cIndx) {
456 auto& mcc = mcpClsCnt[mIndx][cIndx];
457 if (mcc.second > big.second) big = mcc;
459 if (big.first == UINT_MAX) {
462 unsigned int mcpi = mcpCnt[mIndx].first;
463 auto& mcp = (*mcpHandle)[mcpi];
464 myprt <<
"Match failed: mcpi " << mcpi <<
" pdg " << mcp.PdgCode();
466 std::cout <<
"match failed mIndx " << mIndx <<
"\n";
469 unsigned int ii = big.first;
470 float eff = big.second / mcpCnt[mIndx].second;
471 float nRecoHitsInPlane = 0;
473 unsigned int firstRecoHitIndex = UINT_MAX;
474 unsigned int lastRecoHitIndex = UINT_MAX;
475 for (
auto iht : recoHits[ii]) {
476 auto&
hit = (*fHitHandle)[iht];
477 if (
hit.WireID().TPC != tpc)
continue;
478 if (
hit.WireID().Plane != plane)
continue;
480 if (firstRecoHitIndex == UINT_MAX) {
481 firstRecoHitIndex = iht;
482 lastRecoHitIndex = iht;
484 unsigned int wire = (*fHitHandle)[iht].WireID().Wire;
488 float pur = big.second / nRecoHitsInPlane;
490 float ep = eff * pur;
494 bool hasBadEP = (ep <
fBadEP);
500 myprt <<
"Hit location format is TPC:Plane:Wire:Tick\n";
501 myprt <<
" MCPI Ptcl T(MeV) nMCPHits ____From____ _____To_____";
502 if (inputClusters.
isValid()) { myprt <<
" clsID"; }
507 <<
" ____From____ _____To_____ nRecoHits nMCPRecoHits Eff Pur EP\n";
513 if (pdgCode == 11) partName =
" Electron";
514 if (pdgCode == 13) partName =
" Muon";
515 if (pdgCode == 211) partName =
" Pion";
516 if (pdgCode == 311) partName =
" Kaon";
517 if (pdgCode == 2212) partName =
" Proton";
519 int TMeV = 1000 * (mcp.E() - mcp.Mass());
522 myprt <<
std::setw(10) << mcpCnt[mIndx].second;
523 unsigned int firstTruHitIndex = UINT_MAX;
524 unsigned int lastTruHitIndex = UINT_MAX;
531 auto& cls = (*inputClusters)[recoIndex[ii]];
534 else if (inputTracks.
isValid()) {
536 auto&
trk = (*inputTracks)[recoIndex[ii]];
548 if (hasBadEP) myprt <<
" <- BadEP";
556 fHitMCPIndex.resize(0);
double E(const int i=0) const
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
art::InputTag fTrackModuleLabel
std::vector< sim::TrackIDE > HitToTrackIDEs(detinfo::DetectorClocksData const &clockData, recob::Hit const &hit) const
art::InputTag fClusterModuleLabel
std::array< float, 5 > PSums
simb::Origin_t Origin() const
std::string HitLocation(unsigned int iht)
packs hit WireID and PeakTime into a compact format
std::array< float, 5 > Cnts
Q_EXPORT QTSManip setprecision(int p)
bool isValid() const noexcept
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
fInnerVessel push_back(Point(-578.400000, 0.000000, 0.000000))
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
const art::Ptr< simb::MCTruth > & TrackIdToMCTruth_P(int id) const
std::array< float, 5 > EPSums
void FirstLastHitInPlane(unsigned int tpc, unsigned int plane, unsigned int mcpi, unsigned int &firstHitIndex, unsigned int &lastHitIndex)
Detector simulation of raw signals on wires.
Q_EXPORT QTSManip setw(int w)
const sim::ParticleList & ParticleList() const
std::vector< int > fSkipPDGCodes
art::InputTag fHitModuleLabel
simb::Origin_t fTruthOrigin
bool fCompareProductIDs
compare Hit and Cluster-> Hit art product IDs on the first event
art::Handle< std::vector< recob::Hit > > fHitHandle
std::array< float, 5 > ESums
second_as<> second
Type of time stored in seconds, in double precision.
std::string to_string(ModuleType const mt)
cet::coded_exception< error, detail::translate > exception
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
std::vector< unsigned int > fHitMCPIndex