135   auto const* geom = lar::providerFrom<geo::Geometry>();
 
  138     throw cet::exception(
"ClusterTrackAna")
 
  139       << 
"Failed to get a handle to hit collection '" << 
fHitModuleLabel.label() << 
"'\n";
 
  141   auto mcpHandle = art::Handle<std::vector<simb::MCParticle>>();
 
  142   if (!
evt.getByLabel(
"largeant", mcpHandle))
 
  143     throw cet::exception(
"ClusterTrackAna")
 
  144       << 
"Failed to get a handle to MCParticles using largeant\n";
 
  151     mf::LogVerbatim(
"ClusterTrackAna") << 
"Run: " << 
evt.
run();
 
  155   art::ServiceHandle<cheat::BackTrackerService const> bt_serv;
 
  156   art::ServiceHandle<cheat::ParticleInventoryService const> pi_serv;
 
  157   sim::ParticleList 
const& plist = pi_serv->ParticleList();
 
  158   auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(
evt);
 
  162   std::vector<int> trkIDs;
 
  164   std::vector<unsigned int> MCPIs;
 
  165   for (sim::ParticleList::const_iterator ipart = plist.begin(); ipart != plist.end(); ++ipart) {
 
  166     const simb::MCParticle* part = (*ipart).second;
 
  167     int trackID = part->TrackId();
 
  168     art::Ptr<simb::MCTruth> theTruth = pi_serv->TrackIdToMCTruth_P(trackID);
 
  169     if (!anySource && theTruth->Origin() != 
fTruthOrigin) 
continue;
 
  170     int pdg = 
abs(part->PdgCode());
 
  171     bool isCharged = (pdg == 11) || (pdg == 13) || (pdg == 211) || (pdg == 321) || (pdg == 2212);
 
  172     if (!isCharged) 
continue;
 
  174     float TMeV = 1000 * (part->E() - part->Mass());
 
  176     if (TMeV < 1) 
continue;
 
  178     unsigned int mcpi = UINT_MAX;
 
  179     for (mcpi = 0; mcpi < (*mcpHandle).size(); ++mcpi)
 
  180       if ((*mcpHandle)[mcpi].TrackId() == trackID) 
break;
 
  181     if (mcpi == UINT_MAX) {
 
  182       std::cout << 
"Failed to find a MCParticle from ParticleList\n";
 
  185     trkIDs.push_back(trackID);
 
  186     MCPIs.push_back(mcpi);
 
  188   if (trkIDs.empty()) 
return;
 
  194   std::vector<std::pair<unsigned int, unsigned int>> hitRange(geom->NTPC() + 1);
 
  198   for (
auto& hr : hitRange)
 
  199     hr = std::make_pair(UINT_MAX, UINT_MAX);
 
  200   for (
size_t iht = 0; iht < (*fHitHandle).size(); ++iht) {
 
  201     auto& 
hit = (*fHitHandle)[iht];
 
  203     unsigned int tpc = 
hit.WireID().TPC;
 
  206     auto tides = bt_serv->HitToTrackIDEs(clockData, 
hit);
 
  211     for (
auto& tide : tides) {
 
  213       if (tide.energyFrac < 0.5) 
continue;
 
  214       int trackID = tide.trackID;
 
  216       for (
size_t indx = 0; indx < trkIDs.size(); ++indx) {
 
  217         if (trkIDs[indx] == trackID) {
 
  227     if (hitRange[tpc].
first == UINT_MAX) hitRange[tpc].first = iht;
 
  228     hitRange[tpc].second = iht;
 
  238     mf::LogVerbatim myprt(
"ClusterTrackAna");
 
  239     myprt << 
"Checking " << trkIDs.size() << 
" selected MCParticles with the requested TruthOrigin";
 
  240     if (
fInTPC == UINT_MAX) { myprt << 
" in all TPCs\n"; }
 
  242       myprt << 
" in TPC " << 
fInTPC;
 
  246     myprt << 
"Found " << nMatch << 
" MC-matched hits with the requested TruthOrigin";
 
  247     myprt << 
" out of " << nInTPC << 
" total hits.\n";
 
  248     myprt << 
"Found " << noMatch << 
" hits not matched to ANY MCParticle.\n";
 
  251     std::vector<std::pair<unsigned int, unsigned int>> mcpCnt;
 
  253       if (mcpi == UINT_MAX) 
continue;
 
  254       unsigned short mIndx = 0;
 
  255       for (mIndx = 0; mIndx < mcpCnt.size(); ++mIndx)
 
  256         if (mcpCnt[mIndx].
first == mcpi) 
break;
 
  257       if (mIndx == mcpCnt.size()) mcpCnt.push_back(std::make_pair(mcpi, 0));
 
  259       ++mcpCnt[mIndx].second;
 
  261     myprt << 
" MCPI TrackID  PDGCode  T(MeV)   nHits    Process";
 
  262     for (
auto mcpcnt : mcpCnt) {
 
  264       unsigned int mcpi = mcpcnt.first;
 
  265       auto& mcp = (*mcpHandle)[mcpi];
 
  266       myprt << std::setw(5) << mcpi;
 
  267       myprt << std::setw(8) << mcp.TrackId();
 
  268       myprt << std::setw(8) << 
abs(mcp.PdgCode());
 
  269       int TMeV = 1000 * (mcp.E() - mcp.Mass());
 
  270       myprt << std::setw(9) << TMeV;
 
  271       myprt << std::setw(8) << mcpcnt.second;
 
  272       myprt << 
"    " << mcp.Process();
 
  277   std::vector<std::vector<unsigned int>> recoHits;
 
  279   std::vector<unsigned int> recoIndex;
 
  282   art::Handle<std::vector<recob::Cluster>> inputClusters;
 
  283   art::Handle<std::vector<recob::Track>> inputTracks;
 
  287       throw cet::exception(
"ClusterTrackAna")
 
  291     if (!hitsFromCls.isValid())
 
  292       throw cet::exception(
"ClusterTrackAna") << 
"Failed to get a handle to Cluster -> Hit assns\n";
 
  293     for (
unsigned int icl = 0; icl < (*inputClusters).size(); ++icl) {
 
  294       std::vector<art::Ptr<recob::Hit>> cluhits = hitsFromCls.at(icl);
 
  295       if (cluhits.empty()) 
continue;
 
  298           throw cet::exception(
"ClusterTrackAna")
 
  299             << 
"Hits associated with ClusterModuleLabel are in a different collection than " 
  306       std::vector<unsigned int> hitsIndex;
 
  307       for (
auto& cluhit : cluhits) {
 
  308         if (fHitMCPIndex[cluhit.key()] != UINT_MAX) hitsIndex.push_back(cluhit.key());
 
  310       if (hitsIndex.empty()) 
continue;
 
  311       recoIndex.push_back(icl);
 
  312       recoHits.push_back(hitsIndex);
 
  318       throw cet::exception(
"ClusterTrackAna")
 
  319         << 
"Failed to get a handle to the track collection '" << 
fTrackModuleLabel.label() << 
"'\n";
 
  321     if (!hitsFromTrk.isValid())
 
  322       throw cet::exception(
"ClusterTrackAna") << 
"Failed to get a handle to Track -> Hit assns\n";
 
  323     for (
unsigned int itk = 0; itk < (*inputTracks).size(); ++itk) {
 
  324       std::vector<art::Ptr<recob::Hit>> trkhits = hitsFromTrk.at(itk);
 
  325       if (trkhits.empty()) 
continue;
 
  328           throw cet::exception(
"ClusterTrackAna")
 
  329             << 
"Hits associated with TrackModuleLabel are in a different collection than " 
  333       std::vector<unsigned int> hitsIndex;
 
  334       for (
auto& trkhit : trkhits) {
 
  335         if (fHitMCPIndex[trkhit.key()] != UINT_MAX) hitsIndex.push_back(trkhit.key());
 
  337       if (hitsIndex.empty()) 
continue;
 
  338       recoIndex.push_back(itk);
 
  339       recoHits.push_back(hitsIndex);
 
  343   for (
const auto& tpcid : geom->IterateTPCIDs()) {
 
  344     unsigned int tpc = tpcid.TPC;
 
  345     if (hitRange[tpc].
first == UINT_MAX) 
continue;
 
  347     for (
unsigned short plane = 0; plane < geom->Nplanes(); ++plane) {
 
  348       unsigned int tpcMatHitCnt = 0;
 
  349       unsigned int tpcTotHitCnt = 0;
 
  352       std::vector<std::pair<unsigned int, float>> mcpCnt;
 
  354       std::vector<std::vector<std::pair<unsigned int, float>>> mcpClsCnt;
 
  355       for (
unsigned int iht = hitRange[tpc].
first; iht <= hitRange[tpc].second; ++iht) {
 
  356         auto& 
hit = (*fHitHandle)[iht];
 
  357         if (
hit.WireID().TPC != tpc) 
continue;
 
  358         if (
hit.WireID().Plane != plane) 
continue;
 
  362         if (fHitMCPIndex[iht] == UINT_MAX) 
continue;
 
  364         unsigned int mcpi = fHitMCPIndex[iht];
 
  365         unsigned short mIndx = 0;
 
  366         for (mIndx = 0; mIndx < mcpCnt.size(); ++mIndx)
 
  367           if (mcpCnt[mIndx].
first == mcpi) 
break;
 
  368         if (mIndx == mcpCnt.size()) {
 
  370           mcpCnt.push_back(std::make_pair(mcpi, 0));
 
  371           mcpClsCnt.resize(mcpCnt.size());
 
  374         ++mcpCnt[mIndx].second;
 
  378         mf::LogVerbatim myprt(
"ClusterTrackAna");
 
  379         myprt << 
"TPC:" << tpc << 
" Plane:" << plane << 
" has " << tpcMatHitCnt << 
"/" 
  381         myprt << 
" (MC-matched hits) / (all hits)";
 
  383       if (tpcMatHitCnt < 3) 
continue;
 
  385       for (
unsigned int ii = 0; ii < recoHits.size(); ++ii) {
 
  386         float nRecoHitsInPlane = 0;
 
  387         float nRecoMatHitsInPlane = 0;
 
  388         for (
auto iht : recoHits[ii]) {
 
  389           auto& 
hit = (*fHitHandle)[iht];
 
  390           if (
hit.WireID().TPC != tpc) 
continue;
 
  391           if (
hit.WireID().Plane != plane) 
continue;
 
  393           if (fHitMCPIndex[iht] == UINT_MAX) 
continue;
 
  394           ++nRecoMatHitsInPlane;
 
  395           unsigned int mcpi = fHitMCPIndex[iht];
 
  398           unsigned short mIndx = 0;
 
  399           for (mIndx = 0; mIndx < mcpCnt.size(); ++mIndx)
 
  400             if (mcpCnt[mIndx].
first == mcpi) 
break;
 
  401           if (mIndx == mcpCnt.size()) {
 
  402             std::cout << 
"Logic error: fHitMCPIndex = " << fHitMCPIndex[iht]
 
  403                       << 
" is valid but isn't in the list of MCParticles to use. Please send email " 
  404                          "to baller@fnal.gov.\n";
 
  407           unsigned short cIndx = 0;
 
  408           for (cIndx = 0; cIndx < mcpClsCnt[mIndx].size(); ++cIndx)
 
  409             if (mcpClsCnt[mIndx][cIndx].
first == ii) 
break;
 
  410           if (cIndx == mcpClsCnt[mIndx].
size()) mcpClsCnt[mIndx].push_back(std::make_pair(ii, 0));
 
  411           ++mcpClsCnt[mIndx][cIndx].second;
 
  413         if (nRecoMatHitsInPlane == 0) 
continue;
 
  416       for (
unsigned short mIndx = 0; mIndx < mcpCnt.size(); ++mIndx) {
 
  418         if (mcpCnt[mIndx].
second < 3) 
continue;
 
  419         unsigned int mcpi = mcpCnt[mIndx].first;
 
  420         auto& mcp = (*mcpHandle)[mcpi];
 
  421         unsigned int pdgCode = 
abs(mcp.PdgCode());
 
  422         unsigned short pIndx = USHRT_MAX;
 
  423         if (pdgCode == 11) pIndx = 0;
 
  424         if (pdgCode == 13) pIndx = 1;
 
  425         if (pdgCode == 211) pIndx = 2;
 
  426         if (pdgCode == 321) pIndx = 3;
 
  427         if (pdgCode == 2212) pIndx = 4;
 
  428         if (mcpClsCnt[mIndx].
empty()) {
 
  433             mf::LogVerbatim myprt(
"ClusterTrackAna");
 
  434             myprt << 
" MCPI " << mcpi;
 
  435             int TMeV = 1000 * (mcp.E() - mcp.Mass());
 
  436             myprt << 
" " << TMeV << 
" MeV";
 
  438             if (pdgCode == 11) partName = 
"El";
 
  439             if (pdgCode == 13) partName = 
"Mu";
 
  440             if (pdgCode == 211) partName = 
"Pi";
 
  441             if (pdgCode == 311) partName = 
"Ka";
 
  442             if (pdgCode == 2212) partName = 
"Pr";
 
  443             myprt << std::setw(5) << partName;
 
  445             unsigned int firstHitIndex = UINT_MAX;
 
  446             unsigned int lastHitIndex = UINT_MAX;
 
  448             myprt << 
" Failed to reconstruct. Truth-matched hit range from ";
 
  452             myprt << 
" <- EP = 0!";
 
  456         std::pair<unsigned int, float> big = std::make_pair(UINT_MAX, 0);
 
  457         for (
unsigned short cIndx = 0; cIndx < mcpClsCnt[mIndx].size(); ++cIndx) {
 
  458           auto& mcc = mcpClsCnt[mIndx][cIndx];
 
  459           if (mcc.second > big.second) big = mcc;
 
  461         if (big.first == UINT_MAX) {
 
  463             mf::LogVerbatim myprt(
"ClusterTrackAna");
 
  464             unsigned int mcpi = mcpCnt[mIndx].first;
 
  465             auto& mcp = (*mcpHandle)[mcpi];
 
  466             myprt << 
"Match failed: mcpi " << mcpi << 
" pdg " << mcp.PdgCode();
 
  468           std::cout << 
"match failed mIndx " << mIndx << 
"\n";
 
  471         unsigned int ii = big.first;
 
  472         float eff = big.second / mcpCnt[mIndx].second;
 
  473         float nRecoHitsInPlane = 0;
 
  475         unsigned int firstRecoHitIndex = UINT_MAX;
 
  476         unsigned int lastRecoHitIndex = UINT_MAX;
 
  477         for (
auto iht : recoHits[ii]) {
 
  478           auto& 
hit = (*fHitHandle)[iht];
 
  479           if (
hit.WireID().TPC != tpc) 
continue;
 
  480           if (
hit.WireID().Plane != plane) 
continue;
 
  482           if (firstRecoHitIndex == UINT_MAX) {
 
  483             firstRecoHitIndex = iht;
 
  484             lastRecoHitIndex = iht;
 
  486           unsigned int wire = (*fHitHandle)[iht].WireID().Wire;
 
  487           if (wire < (*
fHitHandle)[firstRecoHitIndex].
WireID().Wire) firstRecoHitIndex = iht;
 
  488           if (wire > (*
fHitHandle)[lastRecoHitIndex].
WireID().Wire) lastRecoHitIndex = iht;
 
  490         float pur = big.second / nRecoHitsInPlane;
 
  492         float ep = eff * pur;
 
  496         bool hasBadEP = (ep < 
fBadEP);
 
  500           mf::LogVerbatim myprt(
"ClusterTrackAna");
 
  502             myprt << 
"Hit location format is TPC:Plane:Wire:Tick\n";
 
  503             myprt << 
" MCPI     Ptcl T(MeV)  nMCPHits  ____From____ _____To_____";
 
  504             if (inputClusters.isValid()) { myprt << 
"  clsID"; }
 
  509               << 
"  ____From____  _____To_____   nRecoHits nMCPRecoHits    Eff      Pur      EP\n";
 
  512           myprt << std::setw(5) << mcpi;
 
  515           if (pdgCode == 11) partName = 
" Electron";
 
  516           if (pdgCode == 13) partName = 
"     Muon";
 
  517           if (pdgCode == 211) partName = 
"     Pion";
 
  518           if (pdgCode == 311) partName = 
"     Kaon";
 
  519           if (pdgCode == 2212) partName = 
"   Proton";
 
  521           int TMeV = 1000 * (mcp.E() - mcp.Mass());
 
  522           myprt << std::setw(7) << TMeV;
 
  524           myprt << std::setw(10) << mcpCnt[mIndx].second;
 
  525           unsigned int firstTruHitIndex = UINT_MAX;
 
  526           unsigned int lastTruHitIndex = UINT_MAX;
 
  528           myprt << std::setw(14) << 
HitLocation(firstTruHitIndex);
 
  529           myprt << std::setw(14) << 
HitLocation(lastTruHitIndex);
 
  531           if (inputClusters.isValid()) {
 
  533             auto& cls = (*inputClusters)[recoIndex[ii]];
 
  536           else if (inputTracks.isValid()) {
 
  538             auto& trk = (*inputTracks)[recoIndex[ii]];
 
  541           myprt << std::setw(6) << id;
 
  542           myprt << std::setw(14) << 
HitLocation(firstRecoHitIndex);
 
  543           myprt << std::setw(14) << 
HitLocation(lastRecoHitIndex);
 
  544           myprt << std::setw(12) << (int)nRecoHitsInPlane;
 
  545           myprt << std::setw(13) << (int)big.second;
 
  546           myprt << std::fixed << std::setprecision(2);
 
  547           myprt << std::setw(8) << eff;
 
  548           myprt << std::setw(8) << pur;
 
  549           myprt << std::setw(8) << ep;
 
  550           if (hasBadEP) myprt << 
" <- BadEP";
 
  558   fHitMCPIndex.resize(0);
 
art::InputTag fTrackModuleLabel
 
art::InputTag fClusterModuleLabel
 
std::array< float, 5 > PSums
 
std::size_t size(FixedBins< T, C > const &) noexcept
 
std::string HitLocation(unsigned int iht)
packs hit WireID and PeakTime into a compact format 
 
std::array< float, 5 > Cnts
 
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter. 
 
std::array< float, 5 > EPSums
 
void FirstLastHitInPlane(unsigned int tpc, unsigned int plane, unsigned int mcpi, unsigned int &firstHitIndex, unsigned int &lastHitIndex)
 
std::vector< int > fSkipPDGCodes
 
art::InputTag fHitModuleLabel
 
std::string to_string(WindowPattern const &pattern)
 
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
 
bool empty(FixedBins< T, C > const &) noexcept
 
BEGIN_PROLOG could also be cout
 
std::vector< unsigned int > fHitMCPIndex