LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
tca Namespace Reference

Classes

struct  ClusterStore
 struct of temporary clusters More...
 
struct  CRTreeVars
 
struct  DebugStuff
 
struct  DontClusterStruct
 
struct  HistStuff
 
struct  MatchStruct
 
class  MCParticleListUtils
 
struct  PFPStruct
 
struct  ShowerPoint
 
struct  ShowerStruct
 
struct  ShowerStruct3D
 
struct  ShowerTreeVars
 
struct  SortEntry
 
struct  TCHit
 
struct  Tj2Pt
 
struct  TjStuff
 
class  TrajClusterAlg
 
struct  Trajectory
 
struct  TrajPoint
 
struct  TrajPoint3
 
class  TruthMatcher
 
struct  Vtx3Store
 struct of temporary 3D vertices More...
 
struct  VtxStore
 struct of temporary 2D vertices (end points) More...
 

Typedefs

using Point3_t = std::array< double, 3 >
 
using Vector3_t = std::array< double, 3 >
 
using Point2_t = std::array< float, 2 >
 
using Vector2_t = std::array< double, 2 >
 
typedef unsigned int CTP_t
 

Enumerations

enum  HitStatus_t { kAllHits, kUsedHits, kUnusedHits }
 

Functions

geo::PlaneID DecodeCTP (CTP_t CTP)
 
CTP_t EncodeCTP (unsigned int cryo, unsigned int tpc, unsigned int plane)
 
CTP_t EncodeCTP (const geo::PlaneID &planeID)
 
CTP_t EncodeCTP (const geo::WireID &wireID)
 
bool valDecreasings (SortEntry c1, SortEntry c2)
 
bool valIncreasings (SortEntry c1, SortEntry c2)
 
void UpdateMatchStructs (TjStuff &tjs, int oldTj, int newTj)
 
void UpdateTp3s (TjStuff &tjs, PFPStruct &pfp, int oldTj, int newTj)
 
void FillmAllTraj (TjStuff &tjs, const geo::TPCID &tpcid)
 
bool SetStart (TjStuff &tjs, PFPStruct &pfp, bool prt)
 
void FollowTp3s (TjStuff &tjs, PFPStruct &pfp, bool prt)
 
bool FitTp3s (TjStuff &tjs, const std::vector< TrajPoint3 > &tp3s, Point3_t &pos, Vector3_t &dir, float &rCorr)
 
bool FitTp3s (TjStuff &tjs, const std::vector< TrajPoint3 > &tp3s, unsigned short fromPt, unsigned short toPt, Point3_t &pos, Vector3_t &dir, float &rCorr)
 
bool FitTp3 (TjStuff &tjs, TrajPoint3 &tp3, const std::vector< Tj2Pt > &tj2pts)
 
void FindCompleteness (TjStuff &tjs, PFPStruct &pfp, bool doFit, bool fillTp3s, bool prt)
 
void FindMissedTjsInTp3s (TjStuff &tjs, PFPStruct &pfp, std::vector< int > &missTjs, std::vector< float > &missFrac)
 
bool SharesHighScoreVx (TjStuff &tjs, const PFPStruct &pfp, const Trajectory &tj)
 
void Fit3D (unsigned short mode, Point3_t point, Vector3_t dir, Point3_t &fitPos, Vector3_t &fitDir)
 
unsigned short WiresSkippedInCTP (TjStuff &tjs, std::vector< int > &tjids, CTP_t inCTP)
 
float LengthInCTP (TjStuff &tjs, std::vector< int > &tjids, CTP_t inCTP)
 
bool AddMissedTj (TjStuff &tjs, PFPStruct &pfp, unsigned short itj, bool looseCuts, bool prt)
 
bool MergePFPTjs (TjStuff &tjs, PFPStruct &pfp, bool prt)
 
void FindXMatches (TjStuff &tjs, unsigned short numPlanes, short maxScore, std::vector< MatchStruct > &matVec, bool prt)
 
bool MakeTp3 (TjStuff &tjs, const TrajPoint &itp, const TrajPoint &jtp, TrajPoint3 &tp3, bool findDirection)
 
double DeltaAngle (const Vector3_t v1, const Vector3_t v2)
 
Vector3_t PointDirection (const Point3_t p1, const Point3_t p2)
 
double PosSep (const Point3_t &pos1, const Point3_t &pos2)
 
double PosSep2 (const Point3_t &pos1, const Point3_t &pos2)
 
bool SetMag (Vector3_t &v1, double mag)
 
void FilldEdx (TjStuff &tjs, PFPStruct &pfp)
 
void FilldEdx (TjStuff &tjs, TrajPoint3 &tp3)
 
float PFPDOCA (const PFPStruct &pfp1, const PFPStruct &pfp2, unsigned short &close1, unsigned short &close2)
 
bool Split3DKink (TjStuff &tjs, PFPStruct &pfp, double sep, bool prt)
 
std::vector< unsigned short > FindKinks (const TjStuff &tjs, PFPStruct &pfp, double sep, bool prt)
 
double KinkAngle (const TjStuff &tjs, const std::vector< TrajPoint3 > &tp3s, unsigned short atPt, double sep)
 
PFPStruct CreatePFP (const TjStuff &tjs, const geo::TPCID &tpcid)
 
void FindPFParticles (TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
 
bool DefinePFP (std::string inFcnLabel, TjStuff &tjs, PFPStruct &pfp, bool prt)
 
bool PFPVxTjOK (TjStuff &tjs, PFPStruct &pfp, bool prt)
 
bool AnalyzePFP (TjStuff &tjs, PFPStruct &pfp, bool prt)
 
void PFPVertexCheck (TjStuff &tjs)
 
void DefinePFPParents (TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
 
void DefinePFPParentsTestBeam (TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
 
bool StorePFP (TjStuff &tjs, PFPStruct &pfp)
 
bool InsideTPC (const TjStuff &tjs, Point3_t &pos, geo::TPCID &inTPCID)
 
void FindAlongTrans (Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
 
bool PointDirIntersect (Point3_t p1, Vector3_t p1Dir, Point3_t p2, Vector3_t p2Dir, Point3_t &intersect, float &doca)
 
bool LineLineIntersect (Point3_t p1, Point3_t p2, Point3_t p3, Point3_t p4, Point3_t &intersect, float &doca)
 
void ReversePFP (TjStuff &tjs, PFPStruct &pfp)
 
float ChgFracBetween (TjStuff &tjs, Point3_t pos1, Point3_t pos2, geo::TPCID tpcid)
 
float ChgFracNearEnd (TjStuff &tjs, PFPStruct &pfp, unsigned short end)
 
unsigned short FarEnd (const TjStuff &tjs, const PFPStruct &pfp, const Point3_t &pos)
 
void PrintTp3 (std::string someText, const TjStuff &tjs, const TrajPoint3 &tp3)
 
void PrintTp3s (std::string someText, const TjStuff &tjs, const PFPStruct &pfp, short printPts)
 
float AspectRatio (TjStuff &tjs, std::vector< int > &tjids, CTP_t inCTP)
 
void CleanTjs (TjStuff &tjs, PFPStruct &pfp, bool prt)
 
double DotProd (const Vector3_t &v1, const Vector3_t &v2)
 
void SaveCRInfo (TjStuff &tjs, PFPStruct &pfp, bool prt, bool fIsRealData)
 
int GetOrigin (TjStuff &tjs, PFPStruct &pfp)
 
void ClearCRInfo (TjStuff &tjs)
 
void ConfigureMVA (TjStuff &tjs, std::string fMVAShowerParentWeights)
 
bool FindShowerStart (TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
 
void Finish3DShowers (TjStuff &tjs)
 
bool FindShowers3D (TjStuff &tjs, const geo::TPCID &tpcid)
 
bool Reconcile3D (std::string inFcnLabel, TjStuff &tjs, const geo::TPCID &tpcid, bool parentSearchDone, bool prt)
 
bool Reconcile3D (std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
 
void KillVerticesInShower (std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
 
bool CompleteIncompleteShower (std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
 
void Match2DShowers (std::string inFcnLabel, TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
 
bool UpdateShower (std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
 
bool UpdateShower (std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
 
float Match3DFOM (std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
 
float Match3DFOM (std::string inFcnLabel, TjStuff &tjs, int icid, int jcid, int kcid, bool prt)
 
float Match3DFOM (std::string inFcnLabel, TjStuff &tjs, int icid, int jcid, bool prt)
 
void MergeTjList (std::vector< std::vector< int >> &tjList)
 
bool RemovePFP (std::string inFcnLabel, TjStuff &tjs, PFPStruct &pfp, ShowerStruct3D &ss3, bool doUpdate, bool prt)
 
bool AddPFP (std::string inFcnLabel, TjStuff &tjs, int pID, ShowerStruct3D &ss3, bool doUpdate, bool prt)
 
bool AddTj (std::string inFcnLabel, TjStuff &tjs, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
 
bool RemoveTj (std::string inFcnLabel, TjStuff &tjs, int TjID, ShowerStruct &ss, bool doUpdate, bool prt)
 
bool FindParent (std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
 
bool SetParent (std::string inFcnLabel, TjStuff &tjs, PFPStruct &pfp, ShowerStruct3D &ss3, bool prt)
 
PFPStruct CreateFakePFP (const TjStuff &tjs, const ShowerStruct3D &ss3)
 
bool IsShowerLike (const TjStuff &tjs, const std::vector< int > TjIDs)
 
void ShowerParams (double showerEnergy, double &shMaxAlong, double &along95)
 
double ShowerParamTransRMS (double showerEnergy, double along)
 
double InShowerProbLong (double showerEnergy, double along)
 
double InShowerProbTrans (double showerEnergy, double along, double trans)
 
double InShowerProbParam (double showerEnergy, double along, double trans)
 
float InShowerProb (const TjStuff &tjs, const ShowerStruct3D &ss3, const PFPStruct &pfp)
 
float InShowerProb (const TjStuff &tjs, const ShowerStruct &ss, const Trajectory &tj)
 
float ParentFOM (std::string inFcnLabel, TjStuff &tjs, PFPStruct &pfp, unsigned short pend, ShowerStruct3D &ss3, bool prt)
 
float ParentFOM (std::string inFcnLabel, TjStuff &tjs, Trajectory &tj, unsigned short &tjEnd, ShowerStruct &ss, float &tp1Sep, float &vx2Score, bool prt)
 
bool WrongSplitTj (std::string inFcnLabel, TjStuff &tjs, Trajectory &tj, unsigned short tjEnd, ShowerStruct &ss, bool prt)
 
void MergeNearby2DShowers (std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP, bool prt)
 
void MergeOverlap (std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP, bool prt)
 
void MergeShowerChain (std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP, bool prt)
 
void MergeSubShowersTj (std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP, bool prt)
 
void MergeSubShowers (std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP, bool prt)
 
int MergeShowers (std::string inFcnLabel, TjStuff &tjs, std::vector< int > ssIDs, bool prt)
 
bool MergeShowersAndStore (std::string inFcnLabel, TjStuff &tjs, int icotID, int jcotID, bool prt)
 
bool MergeShowerTjsAndStore (TjStuff &tjs, unsigned short istj, unsigned short jstj, bool prt)
 
bool AnalyzeRotPos (std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
 
void ReverseShower (std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
 
void ReverseShower (std::string inFcnLabel, TjStuff &tjs, int cotID, bool prt)
 
void MakeShowerObsolete (std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
 
void MakeShowerObsolete (std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
 
bool DontCluster (const TjStuff &tjs, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
 
void DefineDontCluster (TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
 
void FindCots (std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP, std::vector< std::vector< int >> &tjLists, bool prt)
 
void TagShowerLike (std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP)
 
void FindNearbyTjs (std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
 
void AddCloseTjsToList (TjStuff &tjs, unsigned short itj, std::vector< int > list)
 
void DefineEnvelope (std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
 
bool AddTjsInsideEnvelope (std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
 
bool AddLooseHits (TjStuff &tjs, int cotID, bool prt)
 
void FindStartChg (std::string inFcnLabel, TjStuff &tjs, int cotID, bool prt)
 
std::vector< float > StartChgVec (TjStuff &tjs, int cotID, bool prt)
 
void DumpShowerPts (TjStuff &tjs, int cotID)
 
bool TransferTjHits (TjStuff &tjs, bool prt)
 
int GetCotID (TjStuff &tjs, int ShowerTjID)
 
double ShowerEnergy (const ShowerStruct3D &ss3)
 
float ShowerEnergy (const TjStuff &tjs, const std::vector< int > tjIDs)
 
float ChgToMeV (float chg)
 
bool StoreShower (std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3)
 
bool StoreShower (std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss)
 
ShowerStruct3D CreateSS3 (TjStuff &tjs, const geo::TPCID &tpcid)
 
ShowerStruct CreateSS (TjStuff &tjs, CTP_t inCTP, const std::vector< int > &tjl)
 
bool ChkAssns (std::string inFcnLabel, TjStuff &tjs)
 
void PrintShowers (std::string fcnLabel, TjStuff &tjs)
 
void Print2DShowers (std::string someText, const TjStuff &tjs, CTP_t inCTP, bool printKilledShowers)
 
void PrintShower (std::string someText, const TjStuff &tjs, const ShowerStruct &ss, bool printHeader, bool printExtras)
 
bool RemovePFP (std::string inFcnLabel, TjStuff &tjs, int pID, ShowerStruct3D &ss3, bool doUpdate, bool prt)
 
double InShowerProb (double showerEnergy, double along, double trans)
 
bool AddLooseHits (std::string inFcnLabel, TjStuff &tjs, int cotID, bool prt)
 
void DumpShowerPts (std::string inFcnLabel, TjStuff &tjs, int cotID)
 
void AddCloseTjsToList (std::string inFcnLabel, TjStuff &tjs, unsigned short itj, std::vector< int > list)
 
void MergeTjList2 (std::string inFcnLabel, TjStuff &tjs, std::vector< std::vector< int >> &tjList, bool prt)
 
void SaveTjInfo (TjStuff &tjs, std::vector< std::vector< int >> &tjList, std::string stageName)
 
void SaveTjInfo (TjStuff &tjs, const ShowerStruct &ss, std::string stageName)
 
void SaveTjInfoStuff (TjStuff &tjs, Trajectory &tj, int stageNum, std::string stageName)
 
void SaveAllCots (TjStuff &tjs, const CTP_t &inCTP, std::string someText)
 
void SaveAllCots (TjStuff &tjs, std::string someText)
 
int GetStageNum (ShowerTreeVars &stv, std::string stageName)
 
void ClearShowerTree (ShowerTreeVars &stv)
 
bool valDecreasing (SortEntry c1, SortEntry c2)
 
bool valIncreasing (SortEntry c1, SortEntry c2)
 
void MakeJunkVertices (TjStuff &tjs, const CTP_t &inCTP)
 
void Find2DVertices (TjStuff &tjs, const CTP_t &inCTP)
 
void FindNeutralVertices (TjStuff &tjs, const geo::TPCID &tpcid)
 
bool MergeWithVertex (TjStuff &tjs, VtxStore &vx, unsigned short oVxID, bool prt)
 
void ChkVxTjs (TjStuff &tjs, const CTP_t &inCTP, bool prt)
 
void FindHammerVertices2 (TjStuff &tjs, const CTP_t &inCTP)
 
void FindHammerVertices (TjStuff &tjs, const CTP_t &inCTP)
 
void SplitTrajCrossingVertices (TjStuff &tjs, CTP_t inCTP)
 
void Find3DVertices (TjStuff &tjs, const geo::TPCID &tpcid)
 
void Match3DVtxTjs (TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
 
unsigned short TPNearVertex (TjStuff &tjs, const TrajPoint &tp)
 
bool AttachPFPToVertex (TjStuff &tjs, PFPStruct &pfp, unsigned short end, unsigned short vx3ID, bool prt)
 
bool AttachAnyTrajToVertex (TjStuff &tjs, unsigned short ivx, bool prt)
 
bool AttachTrajToVertex (TjStuff &tjs, Trajectory &tj, VtxStore &vx, bool prt)
 
float TrajPointVertexPull (TjStuff &tjs, const TrajPoint &tp, const VtxStore &vx)
 
float VertexVertexPull (TjStuff &tjs, const Vtx3Store &vx1, const Vtx3Store &vx2)
 
float VertexVertexPull (TjStuff &tjs, const VtxStore &vx1, const VtxStore &vx2)
 
bool StoreVertex (TjStuff &tjs, VtxStore &vx)
 
bool FitVertex (TjStuff &tjs, VtxStore &vx, bool prt)
 
bool FitVertex (TjStuff &tjs, VtxStore &vx, std::vector< TrajPoint > vxTp, bool prt)
 
bool ChkVtxAssociations (TjStuff &tjs, const CTP_t &inCTP)
 
void ScoreVertices (TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
 
void KillPoorVertices (TjStuff &tjs, const geo::TPCID &tpcid)
 
void SetHighScoreBits (TjStuff &tjs, Vtx3Store &vx3)
 
void SetVx3Score (TjStuff &tjs, Vtx3Store &vx3, bool prt)
 
void SetVx2Score (TjStuff &tjs, bool prt)
 
void SetVx2Score (TjStuff &tjs, VtxStore &vx2, bool prt)
 
unsigned short Vx3Topo (TjStuff &tjs, Vtx3Store &vx3)
 
void CompleteIncomplete3DVerticesInGaps (TjStuff &tjs, const geo::TPCID &tpcid)
 
void CompleteIncomplete3DVertices (TjStuff &tjs, const geo::TPCID &tpcid)
 
bool RefineVtxPosition (TjStuff &tjs, const Trajectory &tj, unsigned short &nearPt, short nPtsToChk, bool prt)
 
void VtxHitsSwap (TjStuff &tjs, const CTP_t inCTP)
 
bool MakeVertexObsolete (TjStuff &tjs, VtxStore &vx2, bool forceKill)
 
bool MakeVertexObsolete (TjStuff &tjs, Vtx3Store &vx3)
 
std::vector< int > GetVtxTjIDs (const TjStuff &tjs, const VtxStore &vx2)
 
std::vector< int > GetVtxTjIDs (const TjStuff &tjs, const Vtx3Store &vx3, float &score)
 
std::vector< unsigned short > GetPFPVertices (const TjStuff &tjs, const PFPStruct &pfp)
 
void PosInPlane (const TjStuff &tjs, const Vtx3Store &vx3, unsigned short plane, Point2_t &pos)
 
unsigned short IsCloseToVertex (TjStuff &tjs, VtxStore &inVx2)
 
unsigned short IsCloseToVertex (TjStuff &tjs, Vtx3Store &vx3)
 
void MakeJunkTjVertices (TjStuff &tjs, const CTP_t &inCTP)
 
void DefineTjParents (TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
 
float MaxChargeAsymmetry (TjStuff &tjs, std::vector< int > &tjIDs)
 
int PDGCodeVote (TjStuff &tjs, std::vector< int > &tjIDs, bool prt)
 
unsigned short NumDeltaRays (const TjStuff &tjs, const Trajectory &tj)
 
unsigned short NumDeltaRays (const TjStuff &tjs, std::vector< int > &tjIDs)
 
int NeutrinoPrimaryTjID (const TjStuff &tjs, const Trajectory &tj)
 
int PrimaryID (const TjStuff &tjs, const Trajectory &tj)
 
int PrimaryID (const TjStuff &tjs, const PFPStruct &pfp)
 
bool MergeTjIntoPFP (TjStuff &tjs, int mtjid, PFPStruct &pfp, bool prt)
 
bool CompatibleMerge (TjStuff &tjs, std::vector< int > &tjIDs, bool prt)
 
bool CompatibleMerge (TjStuff &tjs, const Trajectory &tj1, const Trajectory &tj2, bool prt)
 
float OverlapFraction (TjStuff &tjs, const Trajectory &tj1, const Trajectory &tj2)
 
unsigned short AngleRange (TjStuff &tjs, TrajPoint const &tp)
 
void SetAngleCode (TjStuff &tjs, TrajPoint &tp)
 
unsigned short AngleRange (TjStuff &tjs, float angle)
 
void FitTraj (TjStuff &tjs, Trajectory &tj)
 
void FitTraj (TjStuff &tjs, Trajectory &tj, unsigned short originPt, unsigned short npts, short fitDir, TrajPoint &tpFit)
 
float TjDirFOM (const TjStuff &tjs, const Trajectory &tj, bool prt)
 
void WatchHit (std::string someText, TjStuff &tjs, const unsigned int &wHit, short &wInTraj, const unsigned short &tjID)
 
void Reverse3DMatchTjs (TjStuff &tjs, PFPStruct &pfp, bool prt)
 
unsigned short GetPFPIndex (const TjStuff &tjs, int tjID)
 
unsigned short MatchVecIndex (const TjStuff &tjs, int tjID)
 
void ReleaseHits (TjStuff &tjs, Trajectory &tj)
 
void UnsetUsedHits (TjStuff &tjs, TrajPoint &tp)
 
bool StoreTraj (TjStuff &tjs, Trajectory &tj)
 
bool InTrajOK (TjStuff &tjs, std::string someText)
 
void CheckTrajBeginChg (TjStuff &tjs, unsigned short itj, bool prt)
 
void TrimEndPts (std::string fcnLabel, TjStuff &tjs, Trajectory &tj, const std::vector< float > &fQualityCuts, bool prt)
 
void ChkChgAsymmetry (TjStuff &tjs, Trajectory &tj, bool prt)
 
bool SignalBetween (TjStuff &tjs, const TrajPoint &tp1, const TrajPoint &tp2, const float &MinWireSignalFraction, bool prt)
 
bool SignalBetween (TjStuff &tjs, TrajPoint tp, float toPos0, const float &MinWireSignalFraction, bool prt)
 
float ChgFracBetween (TjStuff &tjs, TrajPoint tp, float toPos0, bool prt)
 
bool TrajHitsOK (TjStuff &tjs, const std::vector< unsigned int > &iHitsInMultiplet, const std::vector< unsigned int > &jHitsInMultiplet)
 
bool TrajHitsOK (TjStuff &tjs, const unsigned int iht, const unsigned int jht)
 
float ExpectedHitsRMS (TjStuff &tjs, const TrajPoint &tp)
 
bool SignalAtTp (TjStuff &tjs, const TrajPoint &tp)
 
float TpSumHitChg (TjStuff &tjs, TrajPoint const &tp)
 
unsigned short NumPtsWithCharge (const TjStuff &tjs, const Trajectory &tj, bool includeDeadWires)
 
unsigned short NumPtsWithCharge (const TjStuff &tjs, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
 
float DeadWireCount (const TjStuff &tjs, const TrajPoint &tp1, const TrajPoint &tp2)
 
float DeadWireCount (const TjStuff &tjs, const float &inWirePos1, const float &inWirePos2, CTP_t tCTP)
 
unsigned short PDGCodeIndex (TjStuff &tjs, int PDGCode)
 
void MakeTrajectoryObsolete (TjStuff &tjs, unsigned int itj)
 
void RestoreObsoleteTrajectory (TjStuff &tjs, unsigned int itj)
 
void MergeGhostTjs (TjStuff &tjs, CTP_t inCTP)
 
bool SplitTraj (TjStuff &tjs, unsigned short itj, float XPos, bool makeVx2, bool prt)
 
bool SplitTraj (TjStuff &tjs, unsigned short itj, unsigned short pos, unsigned short ivx, bool prt)
 
void TrajPointTrajDOCA (TjStuff &tjs, TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
 
bool TrajTrajDOCA (const TjStuff &tjs, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
 
bool TrajTrajDOCA (const TjStuff &tjs, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep, bool considerDeadWires)
 
float HitSep2 (TjStuff &tjs, unsigned int iht, unsigned int jht)
 
unsigned short CloseEnd (TjStuff &tjs, const Trajectory &tj, const Point2_t &pos)
 
float PointTrajSep2 (float wire, float time, TrajPoint const &tp)
 
float PointTrajDOCA (TjStuff const &tjs, unsigned int iht, TrajPoint const &tp)
 
float PointTrajDOCA (TjStuff const &tjs, float wire, float time, TrajPoint const &tp)
 
float PointTrajDOCA2 (TjStuff const &tjs, float wire, float time, TrajPoint const &tp)
 
void TrajIntersection (TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
 
void TrajIntersection (TrajPoint const &tp1, TrajPoint const &tp2, float &x, float &y)
 
float MaxTjLen (TjStuff const &tjs, std::vector< int > &tjIDs)
 
float TrajLength (Trajectory &tj)
 
float PosSep (const Point2_t &pos1, const Point2_t &pos2)
 
float PosSep2 (const Point2_t &pos1, const Point2_t &pos2)
 
float TrajPointSeparation (TrajPoint &tp1, TrajPoint &tp2)
 
bool TrajClosestApproach (Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
 
float TwoTPAngle (TrajPoint &tp1, TrajPoint &tp2)
 
std::vector< unsigned int > PutTrajHitsInVector (Trajectory const &tj, HitStatus_t hitRequest)
 
void TagJunkTj (TjStuff const &tjs, Trajectory &tj, bool prt)
 
bool HasDuplicateHits (TjStuff const &tjs, Trajectory const &tj, bool prt)
 
void MoveTPToWire (TrajPoint &tp, float wire)
 
std::vector< unsigned int > FindCloseHits (TjStuff const &tjs, std::array< int, 2 > const &wireWindow, Point2_t const &timeWindow, const unsigned short plane, HitStatus_t hitRequest, bool usePeakTime, bool &hitsNear)
 
bool FindCloseHits (TjStuff const &tjs, TrajPoint &tp, float const &maxDelta, HitStatus_t hitRequest)
 
std::vector< int > FindCloseTjs (const TjStuff &tjs, const TrajPoint &fromTp, const TrajPoint &toTp, const float &maxDelta)
 
float ChgFracNearPos (TjStuff &tjs, const Point2_t &pos, const std::vector< int > &tjIDs)
 
float MaxHitDelta (TjStuff &tjs, Trajectory &tj)
 
void ReverseTraj (TjStuff &tjs, Trajectory &tj)
 
bool PointInsideEnvelope (const Point2_t &Point, const std::vector< Point2_t > &Envelope)
 
bool SetMag (Vector2_t &v1, double mag)
 
void FindAlongTrans (Point2_t pos1, Vector2_t dir1, Point2_t pos2, Point2_t &alongTrans)
 
double DeltaAngle (const Point2_t &p1, const Point2_t &p2)
 
double DeltaAngle2 (double Ang1, double Ang2)
 
double DeltaAngle (double Ang1, double Ang2)
 
void SetEndPoints (TjStuff &tjs, Trajectory &tj)
 
bool TrajIsClean (TjStuff &tjs, Trajectory &tj, bool prt)
 
short MCSMom (const TjStuff &tjs, const std::vector< int > &tjIDs)
 
short MCSMom (TjStuff &tjs, Trajectory &tj)
 
short MCSMom (TjStuff &tjs, Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
 
unsigned short NearestPtWithChg (TjStuff &tjs, Trajectory &tj, unsigned short thePt)
 
float MCSThetaRMS (TjStuff &tjs, Trajectory &tj)
 
double MCSThetaRMS (TjStuff &tjs, Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
 
void TjDeltaRMS (TjStuff &tjs, Trajectory &tj, unsigned short firstPt, unsigned short lastPt, double &rms, unsigned short &cnt)
 
void TagDeltaRays (TjStuff &tjs, const CTP_t &inCTP)
 
void TagMuonDirections (TjStuff &tjs, short debugWorkID)
 
void UpdateTjChgProperties (std::string inFcnLabel, TjStuff &tjs, Trajectory &tj, bool prt)
 
void UpdateVxEnvironment (std::string inFcnLabel, TjStuff &tjs, VtxStore &vx2, bool prt)
 
TrajPoint MakeBareTP (TjStuff &tjs, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
 
bool MakeBareTrajPoint (const TjStuff &tjs, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
 
bool MakeBareTrajPoint (const TjStuff &tjs, float fromWire, float fromTick, float toWire, float toTick, CTP_t tCTP, TrajPoint &tp)
 
bool MakeBareTrajPoint (const Point2_t &fromPos, const Point2_t &toPos, TrajPoint &tpOut)
 
bool MakeBareTrajPoint (const TjStuff &tjs, const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
 
unsigned short FarEnd (const TjStuff &tjs, const Trajectory &tj, const Point2_t &pos)
 
Vector2_t PointDirection (const Point2_t p1, const Point2_t p2)
 
float TPHitsRMSTime (TjStuff &tjs, TrajPoint &tp, HitStatus_t hitRequest)
 
float TPHitsRMSTick (TjStuff &tjs, TrajPoint &tp, HitStatus_t hitRequest)
 
float HitsRMSTime (TjStuff &tjs, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
 
float HitsRMSTick (TjStuff &tjs, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
 
float HitsPosTime (TjStuff &tjs, const std::vector< unsigned int > &hitsInMultiplet, float &sum, HitStatus_t hitRequest)
 
float HitsPosTick (TjStuff &tjs, const std::vector< unsigned int > &hitsInMultiplet, float &sum, HitStatus_t hitRequest)
 
unsigned short NumUsedHitsInTj (const TjStuff &tjs, const Trajectory &tj)
 
unsigned short NumHitsInTP (const TrajPoint &tp, HitStatus_t hitRequest)
 
void SetPDGCode (TjStuff &tjs, unsigned short itj)
 
void SetPDGCode (TjStuff &tjs, Trajectory &tj)
 
bool FillWireHitRange (TjStuff &tjs, const geo::TPCID &tpcid)
 
bool CheckWireHitRange (const TjStuff &tjs)
 
bool WireHitRangeOK (const TjStuff &tjs, const CTP_t &inCTP)
 
bool MergeAndStore (TjStuff &tjs, unsigned int itj1, unsigned int itj2, bool doPrt)
 
std::vector< int > GetAssns (const TjStuff &tjs, std::string type1Name, int id, std::string type2Name)
 
void PrintAllTraj (std::string someText, const TjStuff &tjs, const DebugStuff &debug, unsigned short itj, unsigned short ipt, bool prtVtx)
 
void PrintTrajectory (std::string someText, const TjStuff &tjs, const Trajectory &tj, unsigned short tPoint)
 
void PrintHeader (std::string someText)
 
void PrintTrajPoint (std::string someText, const TjStuff &tjs, unsigned short ipt, short dir, unsigned short pass, TrajPoint const &tp)
 
void PrintPFP (std::string someText, const TjStuff &tjs, const PFPStruct &pfp, bool printHeader)
 
void PrintPFPs (std::string someText, const TjStuff &tjs)
 
std::string PrintStopFlag (const Trajectory &tj, unsigned short end)
 
std::string PrintHitShort (const TCHit &hit)
 
std::string PrintHit (const TCHit &hit)
 
std::string PrintPos (const TjStuff &tjs, const TrajPoint &tp)
 
std::string PrintPos (const TjStuff &tjs, const Point2_t &pos)
 
bool SignalAtTp (TjStuff &tjs, TrajPoint const &tp)
 
double DotProd (const Vector2_t &v1, const Vector2_t &v2)
 
template<typename T >
std::vector< T > SetIntersection (const std::vector< T > &set1, const std::vector< T > &set2)
 
template<typename T >
std::vector< T > SetDifference (const std::vector< T > &set1, const std::vector< T > &set2)
 
void PrintClusters ()
 

Variables

constexpr unsigned int Tpad = 10
 
constexpr unsigned int Cpad = 10000
 
DebugStuff debug
 

Data structures for the reconstruction results

enum  VtxBit_t {
  kVtxTrjTried, kFixed, kOnDeadWire, kHiVx3Score,
  kVtxTruMatch, kVtxMerged, kVtxBitSize
}
 
enum  AlgBit_t {
  kMaskHits, kMaskBadTPs, kMichel, kDeltaRay,
  kCTKink, kCTStepChk, kTryWithNextPass, kRvPrp,
  kCHMUH, kSplit, kComp3DVx, kComp3DVxIG,
  kHED, kHamVx, kHamVx2, kJunkVx,
  kJunkTj, kKilled, kMerge, kTEP,
  kCHMEH, kFillGap, kUseGhostHits, kMrgGhost,
  kChkInTraj, kStopBadFits, kFixBegin, kFTBChg,
  kBeginChg, kFixEnd, kUUH, kVtxTj,
  kChkVxTj, kMisdVxTj, kPhoton, kNoFitToVx,
  kVxMerge, kVxNeutral, kNoKinkChk, kSoftKink,
  kChkStop, kChkStopEP, kChkChgAsym, kFTBRvProp,
  kStopAtTj, kMat3D, kMat3DMerge, kSplit3DKink,
  kTjHiVx3Score, kVtxHitsSwap, kSplitHiChgHits, kShowerLike,
  kKillInShowerVx, kShowerTj, kShwrParent, kMergeOverlap,
  kMergeSubShowers, kMergeSubShowersTj, kMergeNrShowers, kMergeShChain,
  kCompleteShower, kSplitTjCVx, kSetDir, kCheat,
  kAlgBitSize
}
 
enum  StopFlag_t {
  kSignal, kAtKink, kAtVtx, kBragg,
  kAtTj, kOutFV, kFlagBitSize
}
 
enum  TPEnvironment_t {
  kEnvNearTj, kEnvNearShower, kEnvOverlap, kEnvUnusedHits,
  kEnvClean, kEnvFlag
}
 
const std::vector< std::string > AlgBitNames
 
const std::vector< std::string > StopFlagNames
 
const std::vector< std::string > VtxBitNames
 

Typedef Documentation

typedef unsigned int tca::CTP_t

Definition at line 41 of file DataStructs.h.

using tca::Point2_t = typedef std::array<float, 2>

Definition at line 37 of file DataStructs.h.

using tca::Point3_t = typedef std::array<double, 3>

Definition at line 35 of file DataStructs.h.

using tca::Vector2_t = typedef std::array<double, 2>

Definition at line 38 of file DataStructs.h.

using tca::Vector3_t = typedef std::array<double, 3>

Definition at line 36 of file DataStructs.h.

Enumeration Type Documentation

Enumerator
kMaskHits 
kMaskBadTPs 
kMichel 
kDeltaRay 
kCTKink 

kink found in CheckTraj

kCTStepChk 
kTryWithNextPass 
kRvPrp 
kCHMUH 
kSplit 
kComp3DVx 
kComp3DVxIG 
kHED 
kHamVx 
kHamVx2 
kJunkVx 
kJunkTj 
kKilled 
kMerge 
kTEP 
kCHMEH 
kFillGap 
kUseGhostHits 
kMrgGhost 
kChkInTraj 
kStopBadFits 
kFixBegin 
kFTBChg 
kBeginChg 
kFixEnd 
kUUH 
kVtxTj 
kChkVxTj 
kMisdVxTj 
kPhoton 
kNoFitToVx 
kVxMerge 
kVxNeutral 
kNoKinkChk 
kSoftKink 
kChkStop 
kChkStopEP 
kChkChgAsym 
kFTBRvProp 
kStopAtTj 
kMat3D 
kMat3DMerge 
kSplit3DKink 
kTjHiVx3Score 
kVtxHitsSwap 
kSplitHiChgHits 
kShowerLike 
kKillInShowerVx 
kShowerTj 
kShwrParent 
kMergeOverlap 
kMergeSubShowers 
kMergeSubShowersTj 
kMergeNrShowers 
kMergeShChain 
kCompleteShower 
kSplitTjCVx 
kSetDir 
kCheat 
kAlgBitSize 

don't mess with this line

Definition at line 374 of file DataStructs.h.

374  {
375  kMaskHits,
376  kMaskBadTPs,
377  kMichel,
378  kDeltaRay,
379  kCTKink,
380  kCTStepChk,
382  kRvPrp,
383  kCHMUH,
384  kSplit,
385  kComp3DVx,
386  kComp3DVxIG,
387  kHED, // High End Delta
388  kHamVx,
389  kHamVx2,
390  kJunkVx,
391  kJunkTj,
392  kKilled,
393  kMerge,
394  kTEP,
395  kCHMEH,
396  kFillGap,
398  kMrgGhost,
399  kChkInTraj,
400  kStopBadFits,
401  kFixBegin,
402  kFTBChg,
403  kBeginChg,
404  kFixEnd,
405  kUUH,
406  kVtxTj,
407  kChkVxTj,
408  kMisdVxTj,
409  kPhoton,
410  kNoFitToVx,
411  kVxMerge,
412  kVxNeutral,
413  kNoKinkChk,
414  kSoftKink,
415  kChkStop,
416  kChkStopEP,
417  kChkChgAsym,
418  kFTBRvProp,
419  kStopAtTj,
420  kMat3D,
421  kMat3DMerge,
422  kSplit3DKink,
424  kVtxHitsSwap,
426  kShowerLike,
428  kShowerTj,
429  kShwrParent,
436  kSplitTjCVx,
437  kSetDir,
438  kCheat,
439  kAlgBitSize
440  } AlgBit_t;
AlgBit_t
Definition: DataStructs.h:374
kink found in CheckTraj
Definition: DataStructs.h:379
don&#39;t mess with this line
Definition: DataStructs.h:439
Enumerator
kAllHits 
kUsedHits 
kUnusedHits 

Definition at line 37 of file Utils.h.

37  {
38  kAllHits,
39  kUsedHits,
41  } HitStatus_t ;
HitStatus_t
Definition: Utils.h:37
Enumerator
kSignal 
kAtKink 
kAtVtx 
kBragg 
kAtTj 
kOutFV 
kFlagBitSize 

don't mess with this line

Definition at line 443 of file DataStructs.h.

443  {
444  kSignal,
445  kAtKink,
446  kAtVtx,
447  kBragg,
448  kAtTj,
449  kOutFV,
450  kFlagBitSize
451  } StopFlag_t;
don&#39;t mess with this line
Definition: DataStructs.h:450
StopFlag_t
Definition: DataStructs.h:443
Enumerator
kEnvNearTj 
kEnvNearShower 
kEnvOverlap 
kEnvUnusedHits 
kEnvClean 

the charge fraction is small near this point

kEnvFlag 

a general purpose flag bit used in 3D matching

Definition at line 453 of file DataStructs.h.

453  {
454  kEnvNearTj,
456  kEnvOverlap,
458  kEnvClean,
459  kEnvFlag,
460  } TPEnvironment_t;
a general purpose flag bit used in 3D matching
Definition: DataStructs.h:459
the charge fraction is small near this point
Definition: DataStructs.h:458
TPEnvironment_t
Definition: DataStructs.h:453
Enumerator
kVtxTrjTried 

FindVtxTraj algorithm tried.

kFixed 

vertex position fixed manually - no fitting done

kOnDeadWire 
kHiVx3Score 

matched to a high-score 3D vertex

kVtxTruMatch 

tagged as a vertex between Tjs that are matched to MC truth neutrino interaction particles

kVtxMerged 
kVtxBitSize 

don't mess with this line

Definition at line 100 of file DataStructs.h.

100  {
101  kVtxTrjTried,
102  kFixed,
103  kOnDeadWire,
104  kHiVx3Score,
105  kVtxTruMatch,
106  kVtxMerged,
107  kVtxBitSize
108  } VtxBit_t;
FindVtxTraj algorithm tried.
Definition: DataStructs.h:101
vertex position fixed manually - no fitting done
Definition: DataStructs.h:102
matched to a high-score 3D vertex
Definition: DataStructs.h:104
VtxBit_t
Definition: DataStructs.h:100
don&#39;t mess with this line
Definition: DataStructs.h:107
tagged as a vertex between Tjs that are matched to MC truth neutrino interaction particles ...
Definition: DataStructs.h:105

Function Documentation

void tca::AddCloseTjsToList ( std::string  inFcnLabel,
TjStuff tjs,
unsigned short  itj,
std::vector< int >  list 
)
void tca::AddCloseTjsToList ( TjStuff tjs,
unsigned short  itj,
std::vector< int >  list 
)

Definition at line 3907 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::TjStuff::fHits, tca::Trajectory::MCSMom, and tca::TjStuff::ShowerTag.

3908  {
3909  // Searches the trajectory points for hits that are used in a different trajectory and add
3910  // them to the list if any are found, and the MCSMomentum is not too large
3911  if(itj > tjs.allTraj.size() - 1) return;
3912 
3913  //short maxMom = (short)(2 * tjs.ShowerTag[1]);
3914  short maxMom = tjs.ShowerTag[1];
3915  //XL: why is maxMom is twice of the shower tag [1]?
3916  for(auto& tp : tjs.allTraj[itj].Pts) {
3917  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3918  // ignore hits that are used in this trajectory
3919  if(tp.UseHit[ii]) continue;
3920  unsigned int iht = tp.Hits[ii];
3921  // ignore if there is no hit -> Tj association
3922  if(tjs.fHits[iht].InTraj <= 0) continue;
3923  if((unsigned int)tjs.fHits[iht].InTraj > tjs.allTraj.size()) continue;
3924  // check the momentum
3925  Trajectory& tj = tjs.allTraj[tjs.fHits[iht].InTraj - 1];
3926  if(tj.MCSMom > maxMom) continue;
3927 // if(tj.AlgMod[kTjHiVx3Score]) continue;
3928  // see if it is already in the list
3929  if(std::find(list.begin(), list.end(), tjs.fHits[iht].InTraj) != list.end()) continue;
3930  list.push_back(tjs.fHits[iht].InTraj);
3931  } // ii
3932  } // tp
3933  } // AddCloseTjsToList
bool tca::AddLooseHits ( std::string  inFcnLabel,
TjStuff tjs,
int  cotID,
bool  prt 
)
bool tca::AddLooseHits ( TjStuff tjs,
int  cotID,
bool  prt 
)

Definition at line 4069 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::TjStuff::cots, tca::ShowerStruct::CTP, DecodeCTP(), tca::ShowerStruct::Envelope, tca::TjStuff::fHits, tca::TrajPoint::Hits, tca::Trajectory::ID, tca::ShowerStruct::ID, tca::TjStuff::LastWire, geo::PlaneID::Plane, PointInsideEnvelope(), tca::Trajectory::Pts, tca::ShowerStruct::ShowerTjID, ss, tca::ShowerStruct::TjIDs, tca::TjStuff::UnitsPerTick, and tca::TjStuff::WireHitRange.

4070  {
4071  // Add hits that are inside the envelope to the shower if they are loose, i.e. not
4072  // used by any trajectory. This function returns true if the set of hits is different than
4073  // the current set. The calling function should update the shower if this is the case.
4074 
4075  ShowerStruct& ss = tjs.cots[cotID - 1];
4076  if(ss.Envelope.empty()) return false;
4077  if(ss.ID == 0) return false;
4078  if(ss.TjIDs.empty()) return false;
4079 
4080  geo::PlaneID planeID = DecodeCTP(ss.CTP);
4081  unsigned short ipl = planeID.Plane;
4082 
4083  Trajectory& stj = tjs.allTraj[ss.ShowerTjID - 1];
4084  TrajPoint& stp0 = stj.Pts[0];
4085  // start a list of new hits
4086  std::vector<unsigned int> newHits;
4087 
4088  // look for hits inside the envelope. Find the range of wires that spans the envelope
4089  float fLoWire = 1E6;
4090  float fHiWire = 0;
4091  // and the range of ticks
4092  float loTick = 1E6;
4093  float hiTick = 0;
4094  for(auto& vtx : ss.Envelope) {
4095  if(vtx[0] < fLoWire) fLoWire = vtx[0];
4096  if(vtx[0] > fHiWire) fHiWire = vtx[0];
4097  if(vtx[1] < loTick) loTick = vtx[1];
4098  if(vtx[1] > hiTick) hiTick = vtx[1];
4099  } // vtx
4100  loTick /= tjs.UnitsPerTick;
4101  hiTick /= tjs.UnitsPerTick;
4102  unsigned int loWire = std::nearbyint(fLoWire);
4103  unsigned int hiWire = std::nearbyint(fHiWire) + 1;
4104  if(hiWire > tjs.LastWire[ipl]-1) hiWire = tjs.LastWire[ipl]-1;
4105  std::array<float, 2> point;
4106  for(unsigned int wire = loWire; wire < hiWire; ++wire) {
4107  // skip bad wires or no hits on the wire
4108  if(tjs.WireHitRange[ipl][wire].first < 0) continue;
4109  unsigned int firstHit = (unsigned int)tjs.WireHitRange[ipl][wire].first;
4110  unsigned int lastHit = (unsigned int)tjs.WireHitRange[ipl][wire].second;
4111  for(unsigned int iht = firstHit; iht < lastHit; ++iht) {
4112  // used in a trajectory?
4113  if(tjs.fHits[iht].InTraj != 0) continue;
4114  // inside the tick range?
4115  if(tjs.fHits[iht].PeakTime < loTick) continue;
4116  // Note that hits are sorted by increasing time so we can break here
4117  if(tjs.fHits[iht].PeakTime > hiTick) break;
4118  // see if this hit is inside the envelope
4119  point[0] = tjs.fHits[iht].ArtPtr->WireID().Wire;
4120  point[1] = tjs.fHits[iht].PeakTime * tjs.UnitsPerTick;
4121  if(!PointInsideEnvelope(point, ss.Envelope)) continue;
4122  newHits.push_back(iht);
4123  } // iht
4124  } // wire
4125 
4126  // no new hits and no old hits. Nothing to do
4127  if(newHits.empty()) {
4128  if(prt) mf::LogVerbatim("TC")<<"ALH: No new loose hits found";
4129  return false;
4130  }
4131 
4132  // Update
4133  stp0.Hits.insert(stp0.Hits.end(), newHits.begin(), newHits.end());
4134  for(auto& iht: newHits) tjs.fHits[iht].InTraj = stj.ID;
4135 
4136  if(prt) mf::LogVerbatim("TC")<<"ALH: Added "<<stp0.Hits.size()<<" hits to stj "<<stj.ID;
4137  return true;
4138 
4139  } // AddLooseHits
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
Float_t ss
Definition: plot.C:23
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:2705
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
bool tca::AddMissedTj ( TjStuff tjs,
PFPStruct pfp,
unsigned short  itj,
bool  looseCuts,
bool  prt 
)

Definition at line 1130 of file PFPUtils.cxx.

References tca::PFPStruct::ID, tca::TjStuff::matchVec, PFPVxTjOK(), SetIntersection(), tca::PFPStruct::TjCompleteness, and tca::PFPStruct::TjIDs.

1131  {
1132  // The Tj pfp.TjIDs[itj] has poor completeness. Search tjs.matchVec for
1133  // the occurrence of this tj with a large completeness AND the occurrence
1134  // of another tj in pfp.TjIDs.
1135  if(itj > pfp.TjIDs.size() - 1) return false;
1136  if(tjs.matchVec.empty()) return false;
1137 
1138  int theTj = pfp.TjIDs[itj];
1139 // bool pfpInShower = (pfp.PDGCode == 11);
1140 
1141  unsigned short oldSize = pfp.TjIDs.size();
1142 
1143  for(unsigned int ims = 0; ims < tjs.matchVec.size(); ++ims) {
1144  auto& ms = tjs.matchVec[ims];
1145  // look for theTj in the match struct
1146  unsigned short tjIndex = 0;
1147  for(tjIndex = 0; tjIndex < ms.TjIDs.size(); ++tjIndex) if(ms.TjIDs[tjIndex] == theTj) break;
1148  if(tjIndex == ms.TjIDs.size()) continue;
1149  auto shared = SetIntersection(pfp.TjIDs, ms.TjIDs);
1150  if(shared.empty()) continue;
1151  if(looseCuts) {
1152  // Look for shared size at least 2 (theTj and another tj) or size 1 and higher TjCompleteness
1153  bool isWorse = (ms.TjCompleteness[tjIndex] < pfp.TjCompleteness[itj]);
1154  if(shared.size() < 2 && isWorse) continue;
1155  } else {
1156  // Look for shared size at least 2 (theTj and another tj in pfp.TjIDs)
1157  if(shared.size() < 2) continue;
1158  }
1159  // Add the tjs that are not in pfp.TjIDs
1160  for(auto tjid : ms.TjIDs) {
1161  if(std::find(pfp.TjIDs.begin(), pfp.TjIDs.end(), tjid) != pfp.TjIDs.end()) continue;
1162  pfp.TjIDs.push_back(tjid);
1163  // check vertex - tj consistency
1164  if(PFPVxTjOK(tjs, pfp, prt)) continue;
1165  pfp.TjCompleteness.push_back(0);
1166  if(prt) mf::LogVerbatim("TC")<<"AMT: P"<<pfp.ID<<" T"<<theTj<<" Add T"<<tjid;
1167  } // mtjid
1168  } // ims
1169  if(pfp.TjIDs.size() > oldSize) return true;
1170  return false;
1171  } // AddMissedTj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:214
bool PFPVxTjOK(TjStuff &tjs, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:2283
bool tca::AddPFP ( std::string  inFcnLabel,
TjStuff tjs,
int  pID,
ShowerStruct3D ss3,
bool  doUpdate,
bool  prt 
)

Definition at line 1570 of file TCShower.cxx.

References AddTj(), tca::TjStuff::allTraj, tca::ShowerStruct3D::CotIDs, tca::TjStuff::cots, tca::ShowerStruct3D::ID, tca::ShowerStruct3D::NeedsUpdate, tca::TjStuff::pfps, ss, tca::ShowerStruct3D::TPCID, and UpdateShower().

Referenced by Reconcile3D().

1571  {
1572  // Add the tjs in the pfp with id = pID to the 2D showers in ss3 and optionally update everything. This
1573  // function returns true if the addition was successful or if the Tjs in the pfp are already in ss3.
1574  // This function returns false if there was a failure. There isn't any error recovery.
1575 
1576  std::string fcnLabel = inFcnLabel + ".AddP";
1577 
1578  if(pID <= 0 || pID > (int)tjs.pfps.size()) return false;
1579  auto& pfp = tjs.pfps[pID - 1];
1580 
1581  if(pfp.TPCID != ss3.TPCID) {
1582  mf::LogVerbatim("TC")<<fcnLabel<<" P"<<pID<<" is in the wrong TPC for 3S"<<ss3.ID;
1583  return false;
1584  }
1585 
1586  for(auto tid : pfp.TjIDs) {
1587  auto& tj = tjs.allTraj[tid - 1];
1588  // is this tj in a 2D shower that is in a 3D shower that is not this shower?
1589  if(tj.SSID > 0) {
1590  auto& ss = tjs.cots[tj.SSID - 1];
1591  if(ss.SS3ID > 0 && ss.SS3ID != ss3.ID) {
1592  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Conflict: 3S"<<ss3.ID<<" adding P"<<pfp.ID<<" -> T"<<tid<<" is in 2S"<<tj.SSID<<" that is in 3S"<<ss.SS3ID<<" that is not this shower";
1593  return false;
1594  } // conflict
1595  // tj is in the correct 2D shower so nothing needs to be done
1596  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" adding P"<<pfp.ID<<" -> T"<<tid<<" is in the correct shower 2S"<<tj.SSID;
1597  continue;
1598  } // pfp tj is in a shower
1599  if(prt) {
1600  mf::LogVerbatim myprt("TC");
1601  myprt<<fcnLabel<<" 3S"<<ss3.ID<<" adding P"<<pfp.ID<<" -> T"<<tid;
1602  for(unsigned short ii = 0; ii < pfp.TjIDs.size(); ++ii) {
1603  if(pfp.TjIDs[ii] == tid) myprt<<" pfp TjCompleteness "<<std::fixed<<std::setprecision(2)<<pfp.TjCompleteness[ii];
1604  } // itj
1605  myprt<<" tj.SSID 2S"<<tj.SSID;
1606  } // prt
1607  // add it to the shower in the correct CTP
1608  for(auto& cid : ss3.CotIDs) {
1609  auto& ss = tjs.cots[cid - 1];
1610  if(ss.CTP != tj.CTP) continue;
1611  // Add it to the shower.
1612  AddTj(fcnLabel, tjs, tid, ss, doUpdate, prt);
1613  ss3.NeedsUpdate = true;
1614  break;
1615  } // cid
1616  } // tid
1617 
1618  if(doUpdate && ss3.NeedsUpdate) UpdateShower(fcnLabel, tjs, ss3, prt);
1619  return true;
1620 
1621  } // AddPFP
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool AddTj(std::string inFcnLabel, TjStuff &tjs, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1624
Float_t ss
Definition: plot.C:23
bool UpdateShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1302
bool tca::AddTj ( std::string  inFcnLabel,
TjStuff tjs,
int  tjID,
ShowerStruct ss,
bool  doUpdate,
bool  prt 
)

Definition at line 1624 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::TrajPoint::Chg, tca::Trajectory::CTP, tca::ShowerStruct::CTP, tca::Trajectory::EndPt, tca::TjStuff::fHits, tca::TrajPoint::Hits, tca::Trajectory::ID, tca::ShowerStruct::ID, tca::ShowerStruct::NearTjIDs, tca::ShowerStruct::NeedsUpdate, tca::Trajectory::Pts, tca::ShowerStruct::ShPts, tca::Trajectory::SSID, tca::ShowerStruct::TjIDs, tca::TjStuff::UnitsPerTick, UpdateShower(), and tca::TrajPoint::UseHit.

Referenced by AddPFP(), AddTjsInsideEnvelope(), MergeNearby2DShowers(), MergeSubShowersTj(), and SetParent().

1625  {
1626  // Adds the Tj to the shower and optionally updates the shower variables
1627 
1628  if(tjID <= 0 || tjID > (int)tjs.allTraj.size()) return false;
1629 
1630  std::string fcnLabel = inFcnLabel + ".AddT";
1631 
1632  Trajectory& tj = tjs.allTraj[tjID - 1];
1633 
1634  if(tj.CTP != ss.CTP) {
1635  mf::LogVerbatim("TC")<<fcnLabel<<" T"<<tjID<<" is in the wrong CTP for 2S"<<ss.ID;
1636  return false;
1637  }
1638 
1639  if(tj.SSID > 0) {
1640  if(tj.SSID == ss.ID) {
1641  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" T"<<tjID<<" is already in 2S"<<ss.ID;
1642  return true;
1643  } else {
1644  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Can't add T"<<tjID<<" to 2S"<<ss.ID<<". it is already used in 2S"<<tj.SSID;
1645  return false;
1646  }
1647  } // tj.SSID > 0
1648 
1649  ss.TjIDs.push_back(tjID);
1650  tj.SSID = ss.ID;
1651  std::sort(ss.TjIDs.begin(), ss.TjIDs.end());
1652  // remove this ID from the NearTjIDs list
1653  for(unsigned short ii = 0; ii < ss.NearTjIDs.size(); ++ii) {
1654  if(ss.NearTjIDs[ii] == tjID) ss.NearTjIDs.erase(ss.NearTjIDs.begin() + ii);
1655  }
1656  // count the hits in the TPs
1657  unsigned short cnt = 0;
1658  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1659  TrajPoint& tp = tj.Pts[ipt];
1660  if(tp.Chg == 0) continue;
1661  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) if(tp.UseHit[ii]) ++cnt;
1662  } // ipt
1663  unsigned short newSize = ss.ShPts.size() + cnt;
1664  cnt = ss.ShPts.size();
1665  ss.ShPts.resize(newSize);
1666  // now add them
1667  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1668  TrajPoint& tp = tj.Pts[ipt];
1669  if(tp.Chg == 0) continue;
1670  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1671  if(tp.UseHit[ii]) {
1672  unsigned int iht = tp.Hits[ii];
1673  ss.ShPts[cnt].HitIndex = iht;
1674  ss.ShPts[cnt].TID = tj.ID;
1675  ss.ShPts[cnt].Chg = tjs.fHits[iht].Integral;
1676  ss.ShPts[cnt].Pos[0] = tjs.fHits[iht].ArtPtr->WireID().Wire;
1677  ss.ShPts[cnt].Pos[1] = tjs.fHits[iht].PeakTime * tjs.UnitsPerTick;
1678  ++cnt;
1679  }
1680  }
1681  } // ipt
1682  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Added T"<<tj.ID<<" to 2S"<<ss.ID;
1683  ss.NeedsUpdate = true;
1684 
1685  if(doUpdate) return UpdateShower(fcnLabel, tjs, ss, prt);
1686  return true;
1687 
1688  } // AddTj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
Float_t ss
Definition: plot.C:23
bool UpdateShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1302
bool tca::AddTjsInsideEnvelope ( std::string  inFcnLabel,
TjStuff tjs,
ShowerStruct ss,
bool  prt 
)

Definition at line 3996 of file TCShower.cxx.

References AddTj(), tca::TjStuff::allTraj, tca::ShowerStruct::AngleErr, tca::ShowerStruct::CTP, DontCluster(), tca::ShowerStruct::Envelope, tca::ShowerStruct::ID, kKilled, kShowerTj, tca::ShowerStruct::NeedsUpdate, NeutrinoPrimaryTjID(), tca::ShowerStruct::ParentID, PointInsideEnvelope(), tca::ShowerStruct::TjIDs, tmp, and UpdateShower().

Referenced by FindShowers3D().

3997  {
3998  // This function adds Tjs to the shower. It updates the shower parameters.
3999 
4000  if(ss.Envelope.empty()) return false;
4001  if(ss.ID == 0) return false;
4002  if(ss.TjIDs.empty()) return false;
4003 
4004  std::string fcnLabel = inFcnLabel + ".ATIE";
4005 
4006  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Checking 2S"<<ss.ID;
4007 
4008  std::vector<int> tmp(1);
4009  unsigned short nadd = 0;
4010  for(auto& tj : tjs.allTraj) {
4011  if(tj.CTP != ss.CTP) continue;
4012  if(tj.AlgMod[kKilled]) continue;
4013  if(tj.SSID > 0) continue;
4014  if(tj.AlgMod[kShowerTj]) continue;
4015  // See if this Tjs is attached to a neutrino vertex.
4016  if(tj.ParentID == 0) continue;
4017  int neutPrimTj = NeutrinoPrimaryTjID(tjs, tj);
4018  if(neutPrimTj > 0 && neutPrimTj != tj.ID) {
4019  // The Tj is connected to a primary Tj that is associated with a neutrino primary.
4020  // Don't allow tjs to be added to the shower that are not connected to this neutrino primary (if
4021  // one exists)
4022  if(ss.ParentID > 0 && neutPrimTj != ss.ParentID) continue;
4023  } // neutrino primary tj
4024  // This shouldn't be necessary but ensure that the Tj ID appears only once in ss.TjIDs
4025  if(std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tj.ID) != ss.TjIDs.end()) continue;
4026  // check consistency
4027  tmp[0] = tj.ID;
4028  if(DontCluster(tjs, tmp, ss.TjIDs)) continue;
4029  // See if both ends are outside the envelope
4030  bool end0Inside = PointInsideEnvelope(tj.Pts[tj.EndPt[0]].Pos, ss.Envelope);
4031  bool end1Inside = PointInsideEnvelope(tj.Pts[tj.EndPt[1]].Pos, ss.Envelope);
4032  if(!end0Inside && !end1Inside) continue;
4033  if(end0Inside && end1Inside) {
4034  // TODO: See if the Tj direction is compatible with the shower?
4035  if(AddTj(fcnLabel, tjs, tj.ID, ss, false, prt)) ++nadd;
4036  ++nadd;
4037  continue;
4038  } // both ends inside
4039  // Require high momentum Tjs be aligned with the shower axis
4040  // TODO also require high momentum Tjs close to the shower axis?
4041 
4042  if(tj.MCSMom > 200) {
4043  float tjAngle = tj.Pts[tj.EndPt[0]].Ang;
4044  float dangPull = std::abs(tjAngle - ss.AngleErr) / ss.AngleErr;
4045  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" high MCSMom "<<tj.MCSMom<<" dangPull "<<dangPull;
4046  if(dangPull > 2) continue;
4047  } // high momentum
4048  if(AddTj(fcnLabel, tjs, tj.ID, ss, false, prt)) {
4049  ++nadd;
4050  } else {
4051  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" AddTj failed to add T"<<tj.ID;
4052  }
4053  } // tj
4054 
4055  if(nadd > 0) {
4056  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Added "<<nadd<<" trajectories ";
4057  ss.NeedsUpdate = true;
4058  UpdateShower(fcnLabel, tjs, ss, prt);
4059  return true;
4060  } else {
4061  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" No new trajectories added to envelope ";
4062  ss.NeedsUpdate = false;
4063  return false;
4064  }
4065 
4066  } // AddTjsInsideEnvelope
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool AddTj(std::string inFcnLabel, TjStuff &tjs, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1624
Float_t ss
Definition: plot.C:23
Float_t tmp
Definition: plot.C:37
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:2705
bool DontCluster(const TjStuff &tjs, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3381
int NeutrinoPrimaryTjID(const TjStuff &tjs, const Trajectory &tj)
Definition: Utils.cxx:363
bool UpdateShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1302
bool tca::AnalyzePFP ( TjStuff tjs,
PFPStruct pfp,
bool  prt 
)

Definition at line 2339 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, DefinePFP(), tca::PFPStruct::ID, kMat3D, tca::PFPStruct::NeedsUpdate, NumPtsWithCharge(), PFPVxTjOK(), tca::PFPStruct::TjCompleteness, tca::PFPStruct::TjIDs, and tca::PFPStruct::Tp3s.

Referenced by DotProd(), FindPFParticles(), and Match3DVtxTjs().

2340  {
2341  // Analyzes the PFP for oddities and tries to fix them
2342  if(pfp.ID == 0) return false;
2343  if(pfp.TjIDs.empty()) return false;
2344  if(pfp.Tp3s.empty()) return false;
2345 
2346  // don't bother analyzing this pfp has been altered
2347  if(pfp.NeedsUpdate) {
2348  if(prt) mf::LogVerbatim("TC")<<"AnalyzePFP: P"<<pfp.ID<<" needs to be updated. Skip analysis ";
2349  return true;
2350  }
2351 
2352  // check the tj completeness
2353  float minCompleteness = 0.95;
2354  for(auto tjc : pfp.TjCompleteness) if(tjc < minCompleteness) minCompleteness = tjc;
2355  if(prt) mf::LogVerbatim("TC")<<"inside AnalyzePFP P"<<pfp.ID<<" minCompleteness "<<minCompleteness;
2356  if(minCompleteness == 0.95) return true;
2357 
2358  // compare the Tjs in Tp3s with those in TjIDs
2359  std::vector<int> tjIDs;
2360  std::vector<unsigned short> tjCnt;
2361  for(auto& tp3 : pfp.Tp3s) {
2362  for(auto& tp2 : tp3.Tj2Pts) {
2363  // convert to int for std::find
2364  int itjID = tp2.id;
2365  unsigned short indx = 0;
2366  for(indx = 0; indx < tjIDs.size(); ++indx) if(tjIDs[indx] == tp2.id) break;
2367  if(indx == tjIDs.size()) {
2368  tjIDs.push_back(itjID);
2369  tjCnt.push_back(1);
2370  } else {
2371  ++tjCnt[indx];
2372  }
2373  } // tp2
2374  } // tp3
2375 
2376  // look for differences
2377  for(unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2378  if(std::find(pfp.TjIDs.begin(), pfp.TjIDs.end(), tjIDs[ii]) != pfp.TjIDs.end()) continue;
2379  auto& missTj = tjs.allTraj[tjIDs[ii] - 1];
2380  if(missTj.AlgMod[kMat3D]) continue;
2381  unsigned short npwc = NumPtsWithCharge(tjs, missTj, false);
2382  if(prt) mf::LogVerbatim("TC")<<" missed T"<<missTj.ID<<" npwc "<<npwc<<" tjCnt "<<tjCnt[ii];
2383  if(tjCnt[ii] < 0.5 * npwc) continue;
2384  // June 4, 2018. 3D merging is turned off so require the missed tj to be in
2385  // a missing plane
2386  bool skipit = false;
2387  for(auto tid : pfp.TjIDs) {
2388  auto& tj = tjs.allTraj[tid - 1];
2389  if(tj.CTP == missTj.CTP) skipit = true;
2390  } // tid
2391  if(skipit) continue;
2392  // add the missed Tj to the pfp and flag it as needing an update
2393  pfp.TjIDs.push_back(missTj.ID);
2394  if(PFPVxTjOK(tjs, pfp, prt)) pfp.NeedsUpdate = true;
2395  } // ii
2396 
2397  if(pfp.NeedsUpdate) DefinePFP("APFP", tjs, pfp, prt);
2398 
2399  if(prt) {
2400  mf::LogVerbatim myprt("TC");
2401  myprt<<"APFP: Tjs in pfp\n";
2402  for(auto tjid : pfp.TjIDs) {
2403  auto& tj = tjs.allTraj[tjid - 1];
2404  myprt<<"T"<<tj.ID<<" npwc "<<NumPtsWithCharge(tjs, tj, false);
2405  unsigned short indx = 0;
2406  for(indx = 0; indx < tjIDs.size(); ++indx) if(tjIDs[indx] == tjid) break;
2407  if(indx == tjIDs.size()) {
2408  myprt<<" not found in P"<<pfp.ID<<"\n";
2409  continue;
2410  }
2411  myprt<<" nTp3 "<<tjCnt[indx]<<"\n";
2412  } // tjid
2413  } // prt
2414  return true;
2415  } // AnalyzePFP
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool DefinePFP(std::string inFcnLabel, TjStuff &tjs, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:2159
bool PFPVxTjOK(TjStuff &tjs, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:2283
unsigned short NumPtsWithCharge(const TjStuff &tjs, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1738
bool tca::AnalyzeRotPos ( std::string  inFcnLabel,
TjStuff tjs,
ShowerStruct ss,
bool  prt 
)

Definition at line 3170 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::ShowerStruct::DirectionFOM, tca::ShowerStruct::ID, tca::Trajectory::Pts, tca::ShowerStruct::ShowerTjID, and tca::ShowerStruct::ShPts.

Referenced by UpdateShower().

3171  {
3172  // The RotPos vector was filled and sorted by increasing distance along the shower axis.
3173  // This function divides the RotPos points into 3 sections and puts the transverse rms width in the
3174  // three sections into the shower Tj TrajPoint DeltaRMS variable. It also calculates the charge and number of shower
3175  // points closest to each TrajPoint. The
3176 
3177  if(ss.ID == 0) return false;
3178  if(ss.ShPts.empty()) return false;
3179  Trajectory& stj = tjs.allTraj[ss.ShowerTjID - 1];
3180  if(stj.Pts.size() != 3) return false;
3181 
3182  std::string fcnLabel = inFcnLabel + ".ARP";
3183 
3184  for(auto& tp : stj.Pts) {
3185  tp.Chg = 0;
3186  tp.DeltaRMS = 0;
3187  tp.NTPsFit = 0;
3188  tp.HitPos = {{0.0, 0.0}};
3189  }
3190 
3191  float minAlong = ss.ShPts[0].RotPos[0];
3192  float maxAlong = ss.ShPts[ss.ShPts.size()-1].RotPos[0];
3193  float sectionLength = (maxAlong - minAlong) / 3;
3194  float sec0 = minAlong + sectionLength;
3195  float sec2 = maxAlong - sectionLength;
3196  // iterate over the shower points (aka hits)
3197  for(auto& spt : ss.ShPts) {
3198  // The point on the shower Tj to which the charge will assigned
3199  unsigned short ipt = 0;
3200  if(spt.RotPos[0] < sec0) {
3201  // closest to point 0
3202  ipt = 0;
3203  } else if(spt.RotPos[0] > sec2) {
3204  // closest to point 2
3205  ipt = 2;
3206  } else {
3207  // closest to point 1
3208  ipt = 1;
3209  }
3210  stj.Pts[ipt].Chg += spt.Chg;
3211 /*
3212  if(ss.ID == 2) {
3213  std::cout<<"2S"<<ss.ID;
3214  std::cout<<" Pos "<<PrintPos(tjs, spt.Pos);
3215  std::cout<<" RP "<<std::fixed<<std::setprecision(1)<<spt.RotPos[0]<<" "<<spt.RotPos[1];
3216  std::cout<<" chg "<<(int)spt.Chg;
3217  std::cout<<" ipt "<<ipt;
3218  std::cout<<"\n";
3219  }
3220 */
3221  // Average the absolute value of the transverse position in lieu of
3222  // using the sum of the squares. The result is ~15% higher than the actual
3223  // rms which is OK since this is used to find the transverse size of the shower
3224  // which is not a precisely defined quantity anyway
3225  stj.Pts[ipt].DeltaRMS += spt.Chg * std::abs(spt.RotPos[1]);
3226  ++stj.Pts[ipt].NTPsFit;
3227  // Average the charge center at each point
3228  stj.Pts[ipt].HitPos[0] += spt.Chg * spt.Pos[0];
3229  stj.Pts[ipt].HitPos[1] += spt.Chg * spt.Pos[1];
3230  } // spt
3231 
3232  for(auto& tp : stj.Pts) {
3233  if(tp.Chg > 0) {
3234  tp.DeltaRMS /= tp.Chg;
3235  tp.HitPos[0] /= tp.Chg;
3236  tp.HitPos[1] /= tp.Chg;
3237  }
3238  } // tp
3239 
3240  // require that there is charge in point 0 and 2. Point 1 may not have charge if
3241  // we are constructing a sparse shower that is not yet well-defined
3242  if(stj.Pts[0].Chg == 0 || stj.Pts[2].Chg == 0) return false;
3243 
3244  // ensure that the charge center is defined
3245  if(stj.Pts[1].Chg == 0) {
3246  // do a simple interpolation
3247  stj.Pts[1].HitPos[0] = 0.5 * (stj.Pts[0].HitPos[0] + stj.Pts[2].HitPos[0]);
3248  stj.Pts[1].HitPos[1] = 0.5 * (stj.Pts[0].HitPos[1] + stj.Pts[2].HitPos[1]);
3249  }
3250  if(stj.Pts[2].DeltaRMS > 0) {
3251  ss.DirectionFOM = stj.Pts[0].DeltaRMS / stj.Pts[2].DeltaRMS;
3252  } else {
3253  ss.DirectionFOM = 10;
3254  }
3255  if(prt) {
3256  mf::LogVerbatim myprt("TC");
3257  myprt<<fcnLabel<<" 2S"<<ss.ID;
3258  myprt<<" HitPos[0] "<<std::fixed<<std::setprecision(1);
3259  myprt<<stj.Pts[1].HitPos[0]<<" "<<stj.Pts[1].HitPos[1]<<" "<<stj.Pts[1].HitPos[2];
3260  myprt<<" DeltaRMS "<<std::setprecision(2);
3261  myprt<<stj.Pts[0].DeltaRMS<<" "<<stj.Pts[1].DeltaRMS<<" "<<stj.Pts[2].DeltaRMS;
3262  myprt<<" DirectionFOM "<<std::fixed<<std::setprecision(2)<<ss.DirectionFOM;
3263  }
3264  return true;
3265 
3266  } // AnalyzeRotPos
Float_t ss
Definition: plot.C:23
unsigned short tca::AngleRange ( TjStuff tjs,
TrajPoint const &  tp 
)

Definition at line 636 of file Utils.cxx.

References tca::TrajPoint::Ang, and AngleRange().

Referenced by tca::TrajClusterAlg::CheckHiMultUnusedHits(), and tca::TrajClusterAlg::UseUnusedHits().

637  {
638  return AngleRange(tjs, tp.Ang);
639  }
unsigned short AngleRange(TjStuff &tjs, float angle)
Definition: Utils.cxx:659
unsigned short tca::AngleRange ( TjStuff tjs,
float  angle 
)

Definition at line 659 of file Utils.cxx.

References tca::TjStuff::AngleRanges.

Referenced by AngleRange(), FitTraj(), and SetAngleCode().

660  {
661  // returns the index of the angle range
662  if(angle > M_PI) angle = M_PI;
663  if(angle < -M_PI) angle = M_PI;
664  if(angle < 0) angle = -angle;
665  if(angle > M_PI/2) angle = M_PI - angle;
666  for(unsigned short ir = 0; ir < tjs.AngleRanges.size(); ++ir) {
667  if(angle < tjs.AngleRanges[ir]) return ir;
668  }
669  return tjs.AngleRanges.size() - 1;
670  } // AngleRange
float tca::AspectRatio ( TjStuff tjs,
std::vector< int > &  tjids,
CTP_t  inCTP 
)
bool tca::AttachAnyTrajToVertex ( TjStuff tjs,
unsigned short  ivx,
bool  prt 
)

Definition at line 1689 of file TCVertex.cxx.

References tca::TjStuff::allTraj, AttachTrajToVertex(), tca::VtxStore::CTP, tca::VtxStore::ID, kKilled, tca::TjStuff::Vertex2DCuts, and tca::TjStuff::vtx.

Referenced by CompleteIncomplete3DVertices(), Find2DVertices(), FindHammerVertices(), FindHammerVertices2(), tca::TrajClusterAlg::ReconstructAllTraj(), and Split3DKink().

1690  {
1691 
1692  if(ivx > tjs.vtx.size() - 1) return false;
1693  if(tjs.vtx[ivx].ID == 0) return false;
1694  if(tjs.Vertex2DCuts[0] < 0) return false;
1695 
1696  VtxStore& vx = tjs.vtx[ivx];
1697 
1698  unsigned short nadd = 0;
1699  for(auto& tj : tjs.allTraj) {
1700  if(tj.AlgMod[kKilled]) continue;
1701  if(tj.CTP != vx.CTP) continue;
1702  if(tj.VtxID[0] == vx.ID || tj.VtxID[1] == vx.ID) continue;
1703  if(AttachTrajToVertex(tjs, tj, vx, prt)) ++nadd;
1704  } // tj
1705  if(prt) mf::LogVerbatim("TC")<<" AttachAnyTrajToVertex: nadd "<<nadd;
1706  if(nadd == 0) return false;
1707  return true;
1708 
1709  } // AttachAnyTrajToVertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool AttachTrajToVertex(TjStuff &tjs, Trajectory &tj, VtxStore &vx, bool prt)
Definition: TCVertex.cxx:1712
bool tca::AttachPFPToVertex ( TjStuff tjs,
PFPStruct pfp,
unsigned short  end,
unsigned short  vx3ID,
bool  prt 
)

Definition at line 1651 of file TCVertex.cxx.

References tca::TjStuff::allTraj, DecodeCTP(), evd::details::end(), tca::PFPStruct::ID, tca::PFPStruct::PDGCode, tca::TjStuff::pfps, geo::PlaneID::Plane, PosInPlane(), tca::PFPStruct::TjIDs, tca::TjStuff::vtx3, and tca::PFPStruct::Vx3ID.

1652  {
1653  if(vx3ID > int(tjs.vtx3.size())) return false;
1654  if(pfp.ID > int(tjs.pfps.size())) return false;
1655  if(pfp.PDGCode == 22) return false;
1656  if(end > 1) return false;
1657 
1658  auto& vx3 = tjs.vtx3[vx3ID - 1];
1659 
1660  pfp.Vx3ID[end] = vx3.ID;
1661 
1662  // We are done if this a PFP-only vertex
1663  if(vx3.Wire == -2) return true;
1664 
1665  // Update the 2D and 3D vertex and tj associations
1666  for(auto tjid : pfp.TjIDs) {
1667  auto& tj = tjs.allTraj[tjid - 1];
1668  unsigned short plane = DecodeCTP(tj.CTP).Plane;
1669  // TODO: Check to see if the Tjs have been ordered correctly?
1670  if(tj.VtxID[end] == 0) {
1671  // tj is available to be attached to a 2D vertex. See if the 3D vertex is matched to
1672  // an existing 2D vertex in this plane
1673  if(vx3.Vx2ID[plane] == 0) {
1674  // not matched. Look for one
1675  std::array<float, 2> pos;
1676  PosInPlane(tjs, vx3, plane, pos);
1677 // if(prt) std::cout<<" tj "<<tj.ID<<" has no 2D vertex. Look for one vertex near "<<tj.CTP<<":"<<PrintPos(tjs, pos)<<" Events processed "<<tjs.EventsProcessed<<"\n";
1678  } else {
1679  // Existing 2D vertex matched to the 3D vertex
1680 // if(prt) std::cout<<" tj "<<tj.ID<<" has no 2D vertex in CTP "<<tj.CTP<<" but vx3 is matched to 2D vertex"<<vx3.Vx2ID[plane]<<". Attach it? Events processed "<<tjs.EventsProcessed<<"\n";
1681  }
1682  }
1683  } // tjid
1684 
1685  return true;
1686  } // AttachPFPToVertex
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
void PosInPlane(const TjStuff &tjs, const Vtx3Store &vx3, unsigned short plane, Point2_t &pos)
Definition: TCVertex.cxx:3083
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool tca::AttachTrajToVertex ( TjStuff tjs,
Trajectory tj,
VtxStore vx,
bool  prt 
)

Definition at line 1712 of file TCVertex.cxx.

References tca::Trajectory::AlgMod, tca::TjStuff::allTraj, tca::VtxStore::CTP, tca::Trajectory::CTP, evd::details::end(), tca::Trajectory::EndPt, FitVertex(), tca::VtxStore::ID, tca::Trajectory::ID, kFixed, kKilled, kNoFitToVx, kPhoton, tca::VtxStore::NTraj, tca::VtxStore::Pos, PosSep2(), tca::Trajectory::Pts, SetVx2Score(), SignalBetween(), tca::VtxStore::Stat, TrajClosestApproach(), TrajLength(), TrajPointVertexPull(), tca::TjStuff::Vertex2DCuts, and tca::Trajectory::VtxID.

Referenced by AttachAnyTrajToVertex(), and tca::TrajClusterAlg::StepCrawl().

1713  {
1714  // Note that this function does not require a signal between the end of the Tj and the vertex
1715 
1716  // tjs.Vertex2DCuts fcl input usage
1717  // 0 = maximum length of a short trajectory
1718  // 1 = max vertex - trajectory separation for short trajectories
1719  // 2 = max vertex - trajectory separation for long trajectories
1720  // 3 = max position pull for adding TJs to a vertex
1721  // 4 = max allowed vertex position error
1722  // 5 = min MCSMom
1723  // 6 = min Pts/Wire fraction
1724 
1725  if(tj.AlgMod[kKilled]) return false;
1726  if(tj.CTP != vx.CTP) return false;
1727  // already attached?
1728  if(tj.VtxID[0] == vx.ID || tj.VtxID[1] == vx.ID) return false;
1729 
1730  unsigned short maxShortTjLen = tjs.Vertex2DCuts[0];
1731  // square the separation cut to simplify testing in the loop
1732  float maxSepCutShort2 = tjs.Vertex2DCuts[1] * tjs.Vertex2DCuts[1];
1733  float maxSepCutLong2 = tjs.Vertex2DCuts[2] * tjs.Vertex2DCuts[2];
1734 
1735  // assume that end 0 is closest to the vertex
1736  unsigned short end = 0;
1737  float vtxTjSep2 = PosSep2(vx.Pos, tj.Pts[tj.EndPt[0]].Pos);
1738  float sep1 = PosSep2(vx.Pos, tj.Pts[tj.EndPt[1]].Pos);
1739  if(sep1 < vtxTjSep2) {
1740  // End 1 is closer
1741  end = 1;
1742  vtxTjSep2 = sep1;
1743  }
1744  // is there a vertex already assigned to this end?
1745  if(tj.VtxID[end] > 0) return false;
1746 
1747  // is the trajectory short?
1748  bool tjShort = (tj.EndPt[1] - tj.EndPt[0] < maxShortTjLen);
1749  float closestApproach;
1750  // ignore bad separation between the closest tj end and the vertex
1751  if(tjShort) {
1752  if(vtxTjSep2 > maxSepCutShort2) return false;
1753  closestApproach = tjs.Vertex2DCuts[1];
1754  } else {
1755  closestApproach = tjs.Vertex2DCuts[2];
1756  if(vtxTjSep2 > maxSepCutLong2) return false;
1757  }
1758 
1759  // Calculate the pull on the vertex
1760  TrajPoint& tp = tj.Pts[tj.EndPt[end]];
1761  float tpVxPull = TrajPointVertexPull(tjs, tp, vx);
1762  bool signalBetween = SignalBetween(tjs, tp, vx.Pos[0], 0.8, prt);
1763 
1764  // See if the vertex position is close to an end
1765  unsigned short closePt;
1766  TrajClosestApproach(tj, vx.Pos[0], vx.Pos[1], closePt, closestApproach);
1767  // count the number of points between the end of the trajectory and the vertex.
1768  // tj ------------- tj ------------
1769  // vx * >> dpt = 0 vx * >> dpt = 2
1770  short dpt;
1771  if(end == 0) {
1772  dpt = closePt - tj.EndPt[end];
1773  } else {
1774  dpt = tj.EndPt[end] - closePt;
1775  }
1776 
1777  float length = TrajLength(tj);
1778  // don't attach it if the tj length is shorter than the separation distance
1779  if(length > 2 && length < closestApproach) return false;
1780 
1781  float pullCut = tjs.Vertex2DCuts[3];
1782  // Dec 21, 2017 Loosen up the pull cut for short close Tjs. These are likely to
1783  // be poorly reconstructed. It is better to have them associated with the vertex
1784  // than not.
1785  if(tjShort) pullCut = 10;
1786 
1787  if(prt) {
1788  mf::LogVerbatim myprt("TC");
1789  myprt<<"ATTV: 2V"<<vx.ID;
1790  myprt<<" NTraj "<<vx.NTraj;
1791  myprt<<" oldTJs";
1792  for(unsigned short itj = 0; itj < tjs.allTraj.size(); ++itj) {
1793  Trajectory& tj = tjs.allTraj[itj];
1794  if(tj.AlgMod[kKilled]) continue;
1795  if(tj.CTP != vx.CTP) continue;
1796  if(tj.VtxID[0] == vx.ID) myprt<<" "<<tj.ID<<"_0";
1797  if(tj.VtxID[1] == vx.ID) myprt<<" "<<tj.ID<<"_1";
1798  }
1799  myprt<<" +tjID "<<tj.ID<<"_"<<end<<" vtxTjSep "<<sqrt(vtxTjSep2)<<" tpVxPull "<<tpVxPull<<" pullCut "<<pullCut<<" dpt "<<dpt;
1800  }
1801 // if(tpVxPull > tjs.Vertex2DCuts[3]) return false;
1802  if(tpVxPull > pullCut) return false;
1803  if(dpt > 2) return true;
1804 
1805  // remove the fixed position flag if there are more than 2 tjs
1806  bool fixedBit = vx.Stat[kFixed];
1807  if(fixedBit && vx.NTraj < 2) vx.Stat[kFixed] = false;
1808 
1809  // don't allow a short Tj with a large pull to bias the fit
1810  if(tjShort && tpVxPull > tjs.Vertex2DCuts[3]) tj.AlgMod[kNoFitToVx] = true;
1811 
1812  // Passed all the cuts. Attach it to the vertex and try a fit
1813  tj.VtxID[end] = vx.ID;
1814  // flag as a photon Tj so it isn't included in the fit
1815  tj.AlgMod[kPhoton] = !signalBetween;
1816  // make a copy of the vertex and fit it
1817  auto vxTmp = vx;
1818  if(FitVertex(tjs, vxTmp, prt)) {
1819  SetVx2Score(tjs, vxTmp, prt);
1820  if(prt) mf::LogVerbatim("TC")<<" Success";
1821  vx = vxTmp;
1822  return true;
1823  }
1824 
1825  // test this again
1826  tj.AlgMod[kNoFitToVx] = true;
1827  if(prt) mf::LogVerbatim("TC")<<" Poor fit. Keep Tj "<<tj.ID<<" with kNoFitToVx";
1828  return true;
1829 /*
1830  // fit failed so remove the tj -> vx assignment if it is long and
1831  // set noFitToVtx if it is short
1832  if(tjShort) {
1833  tj.AlgMod[kNoFitToVx] = true;
1834  if(prt) mf::LogVerbatim("TC")<<" Poor fit. Keep short Tj "<<tj.ID<<" with kNoFitToVx";
1835  return true;
1836  } else {
1837  tj.VtxID[end] = 0;
1838  // restore the fixed flag
1839  vx.Stat[kFixed] = fixedBit;
1840  if(prt) mf::LogVerbatim("TC")<<" Poor fit. Removed Tj "<<tj.ID;
1841  return false;
1842  }
1843 */
1844  } // AttachTrajToVertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float TrajPointVertexPull(TjStuff &tjs, const TrajPoint &tp, const VtxStore &vx)
Definition: TCVertex.cxx:1847
vertex position fixed manually - no fitting done
Definition: DataStructs.h:102
bool TrajClosestApproach(Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
Definition: Utils.cxx:2244
bool FitVertex(TjStuff &tjs, VtxStore &vx, std::vector< TrajPoint > vxTp, bool prt)
Definition: TCVertex.cxx:1986
bool SignalBetween(TjStuff &tjs, const TrajPoint &tp1, const TrajPoint &tp2, const float &MinWireSignalFraction, bool prt)
Definition: Utils.cxx:1495
float TrajLength(Trajectory &tj)
Definition: Utils.cxx:2204
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1631
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void SetVx2Score(TjStuff &tjs, VtxStore &vx2, bool prt)
Definition: TCVertex.cxx:2331
void tca::CheckTrajBeginChg ( TjStuff tjs,
unsigned short  itj,
bool  prt 
)

Definition at line 1272 of file Utils.cxx.

References tca::TjStuff::allTraj, tca::VtxStore::ChiDOF, tca::VtxStore::CTP, tca::VtxStore::ID, kBeginChg, kBragg, kFixed, kFTBRvProp, kKilled, MakeVertexObsolete(), tca::VtxStore::NTraj, tca::VtxStore::Pass, tca::VtxStore::Pos, PrintPos(), SetVx2Score(), SplitTraj(), tca::VtxStore::Stat, StoreVertex(), tca::VtxStore::Topo, tca::TjStuff::UseAlg, and tca::TjStuff::vtx.

Referenced by tca::TrajClusterAlg::ReconstructAllTraj().

1273  {
1274  // This function is called after the beginning of the tj has been inspected to see if
1275  // reverse propagation was warranted. Trajectory points at the beginning were removed by
1276  // this process.
1277  // A search has been made for a Bragg peak with nothing
1278  // found. Here we look for a charge pattern like the following, where C means large charge
1279  // and c means lower charge:
1280  // CCCCCCccccccc
1281  // The charge in the two regions should be fairly uniform.
1282 
1283  // This function may split the trajectory so it needs to have been stored
1284  if(itj > tjs.allTraj.size() - 1) return;
1285  auto& tj = tjs.allTraj[itj];
1286 
1287  if(!tjs.UseAlg[kBeginChg]) return;
1288  if(tj.StopFlag[0][kBragg]) return;
1289  if(tj.AlgMod[kFTBRvProp]) return;
1290  if(tj.AlgMod[kKilled]) return;
1291  if(tj.Pts.size() < 20) return;
1292 
1293  // look for a large drop between the average charge near the beginning
1294  float chg2 = tj.Pts[tj.EndPt[0] + 2].AveChg;
1295  // and the average charge 15 points away
1296  float chg15 = tj.Pts[tj.EndPt[0] + 15].AveChg;
1297  if(chg2 < 3 * chg15) return;
1298 
1299  // find the point where the charge falls below the mid-point
1300  float midChg = 0.5 * (chg2 + chg15);
1301 
1302  unsigned short breakPt = USHRT_MAX;
1303  for(unsigned short ipt = tj.EndPt[0] + 3; ipt < 15; ++ipt) {
1304  float chgm2 = tj.Pts[ipt - 2].Chg;
1305  if(chgm2 == 0) continue;
1306  float chgm1 = tj.Pts[ipt - 1].Chg;
1307  if(chgm1 == 0) continue;
1308  float chgp1 = tj.Pts[ipt + 1].Chg;
1309  if(chgp1 == 0) continue;
1310  float chgp2 = tj.Pts[ipt + 2].Chg;
1311  if(chgp2 == 0) continue;
1312  if(chgm2 > midChg && chgm1 > midChg && chgp1 < midChg && chgp2 < midChg) {
1313  breakPt = ipt;
1314  break;
1315  }
1316  } // breakPt
1317  if(breakPt == USHRT_MAX) return;
1318  // Create a vertex at the break point
1319  VtxStore aVtx;
1320  aVtx.Pos = tj.Pts[breakPt].Pos;
1321  aVtx.NTraj = 2;
1322  aVtx.Pass = tj.Pass;
1323  aVtx.Topo = 8;
1324  aVtx.ChiDOF = 0;
1325  aVtx.CTP = tj.CTP;
1326  aVtx.ID = tjs.vtx.size() + 1;
1327  aVtx.Stat[kFixed] = true;
1328  unsigned short ivx = tjs.vtx.size();
1329  if(!StoreVertex(tjs, aVtx)) return;
1330  if(!SplitTraj(tjs, itj, breakPt, ivx, prt)) {
1331  if(prt) mf::LogVerbatim("TC")<<"CTBC: Failed to split trajectory";
1332  MakeVertexObsolete(tjs, tjs.vtx[ivx], false);
1333  return;
1334  }
1335  SetVx2Score(tjs, prt);
1336 
1337  if(prt) mf::LogVerbatim("TC")<<"CTBC: Split T"<<tj.ID<<" at "<<PrintPos(tjs, tj.Pts[breakPt].Pos)<<"\n";
1338 
1339  } // CheckTrajBeginChg
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
vertex position fixed manually - no fitting done
Definition: DataStructs.h:102
bool MakeVertexObsolete(TjStuff &tjs, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:2917
std::string PrintPos(const TjStuff &tjs, const Point2_t &pos)
Definition: Utils.cxx:4744
bool SplitTraj(TjStuff &tjs, unsigned short itj, unsigned short pos, unsigned short ivx, bool prt)
Definition: Utils.cxx:1918
void SetVx2Score(TjStuff &tjs, bool prt)
Definition: TCVertex.cxx:2322
bool StoreVertex(TjStuff &tjs, VtxStore &vx)
Definition: TCVertex.cxx:1911
bool tca::CheckWireHitRange ( const TjStuff tjs)

Definition at line 3855 of file Utils.cxx.

References tca::TjStuff::fHits, tca::TjStuff::NumPlanes, tca::TjStuff::NumWires, and tca::TjStuff::WireHitRange.

Referenced by tca::TrajClusterAlg::CreateHit(), DotProd(), tca::TrajClusterAlg::EraseHit(), and FillWireHitRange().

3856  {
3857  // do a QC check
3858  for(unsigned short ipl = 0; ipl < tjs.NumPlanes; ++ipl) {
3859  for(unsigned int wire = 0; wire < tjs.NumWires[ipl]; ++wire) {
3860  // No hits or dead wire
3861  if(tjs.WireHitRange[ipl][wire].first < 0) continue;
3862  unsigned int firstHit = tjs.WireHitRange[ipl][wire].first;
3863  unsigned int lastHit = tjs.WireHitRange[ipl][wire].second;
3864  if(lastHit > tjs.fHits.size()) {
3865  mf::LogWarning("TC")<<"CheckWireHitRange: Invalid lastHit "<<lastHit<<" > fHits.size "<<tjs.fHits.size()<<" in plane "<<ipl;
3866  return false;
3867  }
3868  for(unsigned int iht = firstHit; iht < lastHit; ++iht) {
3869  if(tjs.fHits[iht].ArtPtr->WireID().Plane != ipl) {
3870  mf::LogWarning("TC")<<"CheckWireHitRange: Invalid plane "<<tjs.fHits[iht].ArtPtr->WireID().Plane<<" != "<<ipl;
3871  return false;
3872  }
3873  if(tjs.fHits[iht].ArtPtr->WireID().Wire != wire) {
3874  mf::LogWarning("TC")<<"CheckWireHitRange: Invalid wire "<<tjs.fHits[iht].ArtPtr->WireID().Wire<<" != "<<wire<<" in plane "<<ipl;
3875  return false;
3876  }
3877  } // iht
3878  } // wire
3879  } // ipl
3880 
3881  return true;
3882 
3883  } // CheckWireHitRange
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
float tca::ChgFracBetween ( TjStuff tjs,
TrajPoint  tp,
float  toPos0,
bool  prt 
)

Definition at line 1527 of file Utils.cxx.

References tca::TrajPoint::Dir, tca::TrajPoint::Pos, and SignalAtTp().

Referenced by SignalBetween().

1528  {
1529  // Returns the fraction of wires between tp.Pos[0] and toPos0 that have a hit
1530  // on the line defined by tp.Pos and tp.Dir
1531 
1532  if(tp.Pos[0] < -0.4 || toPos0 < -0.4) return 0;
1533  int fromWire = std::nearbyint(tp.Pos[0]);
1534  int toWire = std::nearbyint(toPos0);
1535 
1536  if(fromWire == toWire) {
1537  if(prt) mf::LogVerbatim("TC")<<" SignalBetween fromWire = toWire = "<<fromWire<<" SignalAtTp? "<<SignalAtTp(tjs, tp);
1538  return SignalAtTp(tjs, tp);
1539  }
1540 
1541  int nWires = abs(toWire - fromWire) + 1;
1542 
1543  if(std::abs(tp.Dir[0]) < 0.001) tp.Dir[0] = 0.001;
1544  float stepSize = std::abs(1/tp.Dir[0]);
1545  // ensure that we step in the right direction
1546  if(toWire > fromWire && tp.Dir[0] < 0) stepSize = -stepSize;
1547  if(toWire < fromWire && tp.Dir[0] > 0) stepSize = -stepSize;
1548  float nsig = 0;
1549  float num = 0;
1550  for(unsigned short cnt = 0; cnt < nWires; ++cnt) {
1551  ++num;
1552  if(SignalAtTp(tjs, tp)) ++nsig;
1553  tp.Pos[0] += tp.Dir[0] * stepSize;
1554  tp.Pos[1] += tp.Dir[1] * stepSize;
1555  } // cnt
1556  float sigFrac = nsig / num;
1557  if(prt) mf::LogVerbatim("TC")<<" ChgFracBetween fromWire "<<fromWire<<" toWire "<<toWire<<" nWires "<<num<<" nsig "<<nsig<<" "<<sigFrac;
1558  return sigFrac;
1559 
1560  } // ChgFracBetween
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool SignalAtTp(TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:1639
float tca::ChgFracBetween ( TjStuff tjs,
Point3_t  pos1,
Point3_t  pos2,
geo::TPCID  tpcid 
)

Definition at line 2860 of file PFPUtils.cxx.

References detinfo::DetectorProperties::ConvertXToTicks(), geo::CryostatID::Cryostat, tca::TrajPoint::CTP, tca::TjStuff::detprop, dir, EncodeCTP(), tca::TjStuff::geom, tca::TjStuff::NumPlanes, PointDirection(), tca::TrajPoint::Pos, PosSep(), SignalAtTp(), geo::TPCID::TPC, tca::TjStuff::TPCID, tca::TjStuff::UnitsPerTick, geo::GeometryCore::WireCoordinate(), and tca::TjStuff::WirePitch.

Referenced by DotProd(), FindNeutralVertices(), FindParent(), ParentFOM(), and tca::TruthMatcher::StudyShowerParents().

2861  {
2862  // Step between pos1 and pos2 and find the fraction of the points that have nearby hits
2863  // in each plane. This function returns -1 if something is fishy, but this doesn't mean
2864  // that there is no charge. Note that there is no check for charge precisely at the pos1 and pos2
2865  // positions
2866  if(tpcid != tjs.TPCID) return -1;
2867  float sep = PosSep(pos1, pos2);
2868  if(sep == 0) return -1;
2869  unsigned short nstep = sep / tjs.WirePitch;
2870  auto dir = PointDirection(pos1, pos2);
2871  float sum = 0;
2872  float cnt = 0;
2873  TrajPoint tp;
2874  for(unsigned short step = 0; step < nstep; ++step) {
2875  for(unsigned short xyz = 0; xyz < 3; ++xyz) pos1[xyz] += tjs.WirePitch * dir[xyz];
2876  for(unsigned short plane = 0; plane < tjs.NumPlanes; ++plane) {
2877  tp.CTP = EncodeCTP(tpcid.Cryostat, tpcid.TPC, plane);
2878  tp.Pos[0] = tjs.geom->WireCoordinate(pos1[1], pos1[2], plane, tpcid.TPC, tpcid.Cryostat);
2879  tp.Pos[1] = tjs.detprop->ConvertXToTicks(pos1[0], plane, tpcid.TPC, tpcid.Cryostat) * tjs.UnitsPerTick;
2880  ++cnt;
2881  if(SignalAtTp(tjs, tp)) ++sum;
2882  } // plane
2883  } // step
2884  if(cnt == 0) return -1;
2885  return sum / cnt;
2886 
2887  } // ChgFracBetween
TPCID()=default
Default constructor: an invalid TPC ID.
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
bool SignalAtTp(TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:1639
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:1614
TDirectory * dir
Definition: macro.C:5
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
float tca::ChgFracNearEnd ( TjStuff tjs,
PFPStruct pfp,
unsigned short  end 
)

Definition at line 2890 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, ChgFracNearPos(), detinfo::DetectorProperties::ConvertXToTicks(), geo::CryostatID::Cryostat, tca::TjStuff::detprop, EncodeCTP(), tca::TjStuff::geom, tca::PFPStruct::ID, tca::TjStuff::NumPlanes, tca::TjStuff::NumWires, tca::PFPStruct::TjIDs, geo::TPCID::TPC, tca::PFPStruct::TPCID, tca::TjStuff::TPCID, tca::TjStuff::UnitsPerTick, geo::GeometryCore::WireCoordinate(), tca::TjStuff::WireHitRange, and tca::PFPStruct::XYZ.

Referenced by DotProd(), and FindNeutralVertices().

2891  {
2892  // returns the charge fraction near the end of the pfp. Note that this function
2893  // assumes that there is only one Tj in a plane.
2894  if(pfp.ID == 0) return 0;
2895  if(pfp.TjIDs.empty()) return 0;
2896  if(end < 0 || end > 1) return 0;
2897  if(pfp.TPCID != tjs.TPCID) return 0;
2898 
2899  float sum = 0;
2900  float cnt = 0;
2901  // keep track of the lowest value and maybe reject it
2902  float lo = 1;
2903  float hi = 0;
2904  for(unsigned short plane = 0; plane < tjs.NumPlanes; ++plane) {
2905  CTP_t inCTP = EncodeCTP(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
2906  std::vector<int> tjids(1);
2907  for(auto tjid : pfp.TjIDs) {
2908  auto& tj = tjs.allTraj[tjid - 1];
2909  if(tj.CTP != inCTP) continue;
2910  tjids[0] = tjid;
2911  Point2_t pos;
2912  geo::PlaneID planeID = geo::PlaneID(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
2913  pos[0] = tjs.geom->WireCoordinate(pfp.XYZ[end][1], pfp.XYZ[end][2], planeID);
2914  if(pos[0] < -0.4) continue;
2915  // check for dead wires
2916  unsigned int wire = std::nearbyint(pos[0]);
2917  if(wire > tjs.NumWires[plane]) continue;
2918  if(tjs.WireHitRange[plane][wire].first == -1) continue;
2919  pos[1] = tjs.detprop->ConvertXToTicks(pfp.XYZ[end][0], planeID) * tjs.UnitsPerTick;
2920  float cf = ChgFracNearPos(tjs, pos, tjids);
2921  if(cf < lo) lo = cf;
2922  if(cf > hi) hi = cf;
2923  sum += cf;
2924  ++cnt;
2925  } // tjid
2926  } // plane
2927  if(cnt == 0) return 0;
2928  if(cnt > 1 && lo < 0.3 && hi > 0.8) {
2929  sum -= lo;
2930  --cnt;
2931  }
2932  return sum / cnt;
2933  } // ChgFracNearEnd
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
float ChgFracNearPos(TjStuff &tjs, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2614
unsigned int CTP_t
Definition: DataStructs.h:41
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
float tca::ChgFracNearPos ( TjStuff tjs,
const Point2_t pos,
const std::vector< int > &  tjIDs 
)

Definition at line 2614 of file Utils.cxx.

References tca::TjStuff::allTraj, DecodeCTP(), tca::TjStuff::fHits, FindCloseHits(), kAllHits, and geo::PlaneID::Plane.

Referenced by ChgFracNearEnd(), tca::TrajClusterAlg::ChkStop(), CompleteIncomplete3DVertices(), CompleteIncomplete3DVerticesInGaps(), tca::TrajClusterAlg::EndMerge(), ParentFOM(), and SetVx2Score().

2615  {
2616  // returns the fraction of the charge in the region around pos that is associated with
2617  // the list of Tj IDs
2618  if(tjIDs.empty()) return 0;
2619  std::array<int, 2> wireWindow;
2620  Point2_t timeWindow;
2621  // 1/2 size of the region
2622  constexpr float NNDelta = 5;
2623  wireWindow[0] = pos[0] - NNDelta;
2624  wireWindow[1] = pos[0] + NNDelta;
2625  timeWindow[0] = pos[1] - NNDelta;
2626  timeWindow[1] = pos[1] + NNDelta;
2627  // do some checking
2628  for(auto& tjID : tjIDs) if(tjID <= 0 || tjID > (int)tjs.allTraj.size()) return 0;
2629  // Determine which plane we are in
2630  geo::PlaneID planeID = DecodeCTP(tjs.allTraj[tjIDs[0]-1].CTP);
2631  // get a list of all hits in this region
2632  bool hitsNear;
2633  std::vector<unsigned int> closeHits = FindCloseHits(tjs, wireWindow, timeWindow, planeID.Plane, kAllHits, true, hitsNear);
2634  if(closeHits.empty()) return 0;
2635  float chg = 0;
2636  float tchg = 0;
2637  // Add the hit charge in the box
2638  // All hits in the box, and all hits associated with the Tjs
2639  for(auto& iht : closeHits) {
2640  chg += tjs.fHits[iht].Integral;
2641  if(tjs.fHits[iht].InTraj == 0) continue;
2642  if(std::find(tjIDs.begin(), tjIDs.end(), tjs.fHits[iht].InTraj) != tjIDs.end()) tchg += tjs.fHits[iht].Integral;
2643  } // iht
2644  if(chg == 0) return 0;
2645  return tchg / chg;
2646  } // ChgFracNearPos
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
bool FindCloseHits(TjStuff const &tjs, TrajPoint &tp, float const &maxDelta, HitStatus_t hitRequest)
Definition: Utils.cxx:2418
float tca::ChgToMeV ( float  chg)

Definition at line 4460 of file TCShower.cxx.

Referenced by FindParent(), MergeSubShowersTj(), ShowerEnergy(), tca::TruthMatcher::StudyShowerParents(), and UpdateShower().

4461  {
4462  // Conversion from shower charge to energy in MeV. The calibration factor
4463  // was found by processing 500 pizero events with StudyPiZeros using StudyMode
4464  return 0.012 * chg;
4465  }
bool tca::ChkAssns ( std::string  inFcnLabel,
TjStuff tjs 
)

Definition at line 4625 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::TjStuff::cots, kKilled, tca::TjStuff::showers, and ss.

Referenced by CompleteIncompleteShower(), FindShowers3D(), Finish3DShowers(), Match2DShowers(), MergeNearby2DShowers(), MergeOverlap(), MergeShowerChain(), MergeSubShowers(), MergeSubShowersTj(), and Reconcile3D().

4626  {
4627  // check tj - ss assns
4628 
4629  std::string fcnLabel = inFcnLabel + ".ChkAssns";
4630  for(auto& ss : tjs.cots) {
4631  if(ss.ID == 0) continue;
4632  for(auto tid : ss.TjIDs) {
4633  auto& tj = tjs.allTraj[tid - 1];
4634  if(tj.SSID != ss.ID) {
4635  std::cout<<fcnLabel<<" ***** Error: 2S"<<ss.ID<<" -> TjIDs T"<<tid<<" != tj.SSID 2S"<<tj.SSID<<"\n";
4636  return false;
4637  }
4638  } // tid
4639  // check 2S -> 3S
4640  if(ss.SS3ID > 0 && ss.SS3ID <= (int)tjs.showers.size()) {
4641  auto& ss3 = tjs.showers[ss.SS3ID - 1];
4642  if(std::find(ss3.CotIDs.begin(), ss3.CotIDs.end(), ss.ID) == ss3.CotIDs.end()) {
4643  std::cout<<fcnLabel<<" ***** Error: 2S"<<ss.ID<<" -> 3S"<<ss.SS3ID<<" but the shower says no\n";
4644  return false;
4645  }
4646  } // ss.SS3ID > 0
4647  } // ss
4648  for(auto& tj : tjs.allTraj) {
4649  if(tj.AlgMod[kKilled]) continue;
4650  if(tj.SSID < 0) {
4651  std::cout<<fcnLabel<<" ***** Error: T"<<tj.ID<<" tj.SSID is fubar\n";
4652  tj.SSID = 0;
4653  return false;
4654  }
4655  if(tj.SSID == 0) continue;
4656  auto& ss = tjs.cots[tj.SSID - 1];
4657  if(std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tj.ID) != ss.TjIDs.end()) continue;
4658  std::cout<<fcnLabel<<" ***** Error: T"<<tj.ID<<" tj.SSID = 2S"<<tj.SSID<<" but the shower says no\n";
4659  return false;
4660  } // tj
4661 
4662  for(auto& ss3 : tjs.showers) {
4663  if(ss3.ID == 0) continue;
4664  for(auto cid : ss3.CotIDs) {
4665  auto& ss = tjs.cots[cid - 1];
4666  if(ss.SS3ID != ss3.ID) {
4667  std::cout<<fcnLabel<<" ***** Error: 3S"<<ss3.ID<<" -> 2S"<<cid<<" but it thinks it belongs to 3S"<<ss.SS3ID<<"\n";
4668  return false;
4669  }
4670  } // cid
4671  } // ss3
4672  return true;
4673  } // ChkAssns
Float_t ss
Definition: plot.C:23
void tca::ChkChgAsymmetry ( TjStuff tjs,
Trajectory tj,
bool  prt 
)

Definition at line 1436 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::EndPt, tca::Trajectory::ID, kChkChgAsym, PrintTrajectory(), tca::Trajectory::Pts, SetEndPoints(), UnsetUsedHits(), and tca::TjStuff::UseAlg.

Referenced by tca::TrajClusterAlg::CheckTraj().

1437  {
1438  // looks for a high-charge point in the trajectory which may be due to the
1439  // trajectory crossing an interaction vertex. The properties of points on the opposite
1440  // sides of the high-charge point are analyzed. If significant differences are found, all points
1441  // near the high-charge point are removed as well as those from that point to the end
1442  if(!tjs.UseAlg[kChkChgAsym]) return;
1443  unsigned short npts = tj.EndPt[1] - tj.EndPt[0];
1444  if(prt) mf::LogVerbatim("TC")<<" Inside ChkChgAsymmetry T"<<tj.ID;
1445  // ignore long tjs
1446  if(npts > 50) return;
1447  // ignore short tjs
1448  if(npts < 8) return;
1449  // require the charge pull > 5
1450  float bigPull = 5;
1451  unsigned short atPt = 0;
1452  // Don't consider the first/last few points in case there is a Bragg peak
1453  for(unsigned short ipt = tj.EndPt[0] + 2; ipt <= tj.EndPt[1] - 2; ++ipt) {
1454  auto& tp = tj.Pts[ipt];
1455  if(tp.ChgPull > bigPull) {
1456  bigPull = tp.ChgPull;
1457  atPt = ipt;
1458  }
1459  } // ipt
1460  if(atPt == 0) return;
1461  // require that this point be near the DS end
1462  if((atPt - tj.EndPt[0]) < 0.5 * npts) return;
1463  if(prt) mf::LogVerbatim("TC")<<"CCA: T"<<tj.ID<<" Large Chg point at "<<atPt<<". Check charge asymmetry around it.";
1464  unsigned short nchk = 0;
1465  unsigned short npos = 0;
1466  unsigned short nneg = 0;
1467  for(short ii = 1; ii < 5; ++ii) {
1468  short iplu = atPt + ii;
1469  if(iplu > tj.EndPt[1]) break;
1470  short ineg = atPt - ii;
1471  if(ineg < tj.EndPt[0]) break;
1472  if(tj.Pts[iplu].Chg == 0) continue;
1473  if(tj.Pts[ineg].Chg == 0) continue;
1474  float asym = (tj.Pts[iplu].Chg - tj.Pts[ineg].Chg) / (tj.Pts[iplu].Chg + tj.Pts[ineg].Chg);
1475  ++nchk;
1476  if(asym > 0.5) ++npos;
1477  if(asym < -0.5) ++nneg;
1478  if(prt) mf::LogVerbatim("TC")<<" ineg "<<ineg<<" iplu "<<iplu<<" asym "<<asym<<" nchk "<<nchk;
1479  } // ii
1480  if(nchk < 3) return;
1481  // require most of the points be very positive or very negative
1482  nchk -= 2;
1483  bool doTrim = (nneg > nchk) || (npos > nchk);
1484  if(!doTrim) return;
1485  // remove all the points at the end starting at the one just before the peak if the pull is not so good
1486  auto& prevTP = tj.Pts[atPt - 1];
1487  if(std::abs(prevTP.ChgPull) > 2) --atPt;
1488  for(unsigned short ipt = atPt; ipt <= tj.EndPt[1]; ++ipt) UnsetUsedHits(tjs, tj.Pts[ipt]);
1489  SetEndPoints(tjs, tj);
1490  tj.AlgMod[kChkChgAsym] = true;
1491  if(prt) PrintTrajectory("CCA", tjs, tj, USHRT_MAX);
1492  } // ChkChgAsymmetry
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void PrintTrajectory(std::string someText, const TjStuff &tjs, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:4488
void SetEndPoints(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:2788
void UnsetUsedHits(TjStuff &tjs, TrajPoint &tp)
Definition: Utils.cxx:1082
bool tca::ChkVtxAssociations ( TjStuff tjs,
const CTP_t inCTP 
)

Definition at line 2128 of file TCVertex.cxx.

References tca::TjStuff::allTraj, DecodeCTP(), evd::details::end(), kKilled, geo::PlaneID::Plane, tca::TjStuff::vtx, and tca::TjStuff::vtx3.

Referenced by tca::TrajClusterAlg::ReconstructAllTraj(), and tca::TrajClusterAlg::RunTrajClusterAlg().

2129  {
2130  // Check the associations
2131 
2132  // check the 2D -> 3D associations
2133  geo::PlaneID planeID = DecodeCTP(inCTP);
2134  unsigned short plane = planeID.Plane;
2135  for(auto& vx2 : tjs.vtx) {
2136  if(vx2.CTP != inCTP) continue;
2137  if(vx2.ID == 0) continue;
2138  if(vx2.Vx3ID == 0) continue;
2139  if(vx2.Vx3ID > int(tjs.vtx3.size())) {
2140  mf::LogVerbatim("TC")<<"ChkVtxAssociations: Invalid vx2.Vx3ID "<<vx2.Vx3ID<<" in 2D vtx "<<vx2.ID;
2141  return false;
2142  }
2143  auto& vx3 = tjs.vtx3[vx2.Vx3ID-1];
2144  if(vx3.ID == 0) {
2145  mf::LogVerbatim("TC")<<"ChkVtxAssociations: 2V"<<vx2.ID<<" thinks it is matched to 3V"<<vx3.ID<<" but vx3 is obsolete";
2146  return false;
2147  }
2148  if(vx3.Vx2ID[plane] != vx2.ID) {
2149  mf::LogVerbatim("TC")<<"ChkVtxAssociations: 2V"<<vx2.ID<<" thinks it is matched to 3V"<<vx3.ID<<" but vx3 says no!";
2150  return false;
2151  }
2152  } // vx2
2153  // check the 3D -> 2D associations
2154  for(auto& vx3 : tjs.vtx3) {
2155  if(vx3.ID == 0) continue;
2156  if(vx3.Vx2ID[plane] == 0) continue;
2157  if(vx3.Vx2ID[plane] > (int)tjs.vtx.size()) {
2158  mf::LogVerbatim("TC")<<"ChkVtxAssociations: Invalid vx3.Vx2ID "<<vx3.Vx2ID[plane]<<" in CTP "<<inCTP;
2159  return false;
2160  }
2161  auto& vx2 = tjs.vtx[vx3.Vx2ID[plane]-1];
2162  if(vx2.Vx3ID != vx3.ID) {
2163  mf::LogVerbatim("TC")<<"ChkVtxAssociations: 3V"<<vx3.ID<<" thinks it is matched to 2V"<<vx2.ID<<" but vx2 says no!";
2164  return false;
2165  }
2166  } // vx3
2167 
2168  // check the Tj -> 2D associations
2169  for(auto& tj : tjs.allTraj) {
2170  if(tj.AlgMod[kKilled]) continue;
2171  for(unsigned short end = 0; end < 2; ++end) {
2172  if(tj.VtxID[end] == 0) continue;
2173  if(tj.VtxID[end] > tjs.vtx.size()) {
2174  mf::LogVerbatim("TC")<<"ChkVtxAssociations: T"<<tj.ID<<" thinks it is matched to 2V"<<tj.VtxID[end]<<" on end "<<end<<" but no vertex exists. Recovering";
2175  tj.VtxID[end] = 0;
2176  return false;
2177  }
2178  unsigned short ivx = tj.VtxID[end] - 1;
2179  auto& vx2 = tjs.vtx[ivx];
2180  if(vx2.ID == 0) {
2181  mf::LogVerbatim("TC")<<"ChkVtxAssociations: T"<<tj.ID<<" thinks it is matched to 2V"<<tj.VtxID[end]<<" on end "<<end<<" but the vertex is killed. Fixing the Tj";
2182  tj.VtxID[end] = 0;
2183  return false;
2184  }
2185  } // end
2186  } // tj
2187 
2188  return true;
2189 
2190  } // ChkVtxAssociations
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void tca::ChkVxTjs ( TjStuff tjs,
const CTP_t inCTP,
bool  prt 
)

Definition at line 715 of file TCVertex.cxx.

References tca::TjStuff::allTraj, close(), CompatibleMerge(), DeltaAngle(), FarEnd(), GetAssns(), kChkVxTj, kDeltaRay, kFixed, kKilled, MakeVertexObsolete(), MergeAndStore(), PointTrajDOCA(), PosSep(), PrintPos(), tca::TjStuff::UseAlg, and tca::TjStuff::vtx.

Referenced by tca::TrajClusterAlg::EndMerge(), and Find2DVertices().

716  {
717  //
718 
719  if(!tjs.UseAlg[kChkVxTj]) return;
720 
721  for(unsigned short ivx = 0; ivx < tjs.vtx.size(); ++ivx) {
722  auto& vx2 = tjs.vtx[ivx];
723  if(vx2.ID == 0) continue;
724  if(vx2.CTP != inCTP) continue;
725  auto vxtjs = GetAssns(tjs, "2V", vx2.ID, "T");
726  if(vxtjs.size() < 2) continue;
727  // BB added June 4, 2018
728  // find the closest separation between the vertex and the ends of the tjs
729  float close = 200;
730  int closeID = 0;
731  unsigned short closeEnd = 0;
732  for(auto tid : vxtjs) {
733  auto& tj = tjs.allTraj[tid - 1];
734  unsigned short nearEnd = 1 - FarEnd(tjs, tj, vx2.Pos);
735  if(tj.VtxID[nearEnd] != vx2.ID) continue;
736  float sep = PosSep(tj.Pts[tj.EndPt[nearEnd]].Pos, vx2.Pos);
737  if(sep > close) continue;
738  close = sep;
739  closeID = tid;
740  closeEnd = nearEnd;
741  } // tid
742  if(close > 1.5 && closeID > 0) {
743  auto& closeTj = tjs.allTraj[closeID - 1];
744  auto& closeTP = closeTj.Pts[closeTj.EndPt[closeEnd]];
745  if(prt) mf::LogVerbatim("TC")<<"CVTjs: moved 2V"<<vx2.ID<<" from "<<PrintPos(tjs, vx2.Pos)<<" to "<<PrintPos(tjs, closeTP);
746  vx2.Pos = closeTP.Pos;
747  vx2.Stat[kFixed] = true;
748  }
749  for(unsigned short it1 = 0; it1 < vxtjs.size() - 1; ++it1) {
750  auto& tj1 = tjs.allTraj[vxtjs[it1] - 1];
751  if(tj1.AlgMod[kKilled]) continue;
752  unsigned short end1 = 0;
753  if(tj1.VtxID[1] == vx2.ID) end1 = 1;
754  auto& vtp1 = tj1.Pts[tj1.EndPt[end1]];
755  auto& otp1 = tj1.Pts[tj1.EndPt[1 - end1]];
756  float tj1sep = PosSep(vtp1.Pos, vx2.Pos);
757  for(unsigned short it2 = it1 + 1; it2 < vxtjs.size(); ++it2) {
758  auto& tj2 = tjs.allTraj[vxtjs[it2] - 1];
759  if(tj2.AlgMod[kKilled]) continue;
760  unsigned short end2 = 0;
761  if(tj2.VtxID[2] == vx2.ID) end2 = 1;
762  auto& vtp2 = tj2.Pts[tj2.EndPt[end2]];
763  auto& otp2 = tj2.Pts[tj2.EndPt[1 - end2]];
764  float tj2sep = PosSep(vtp2.Pos, vx2.Pos);
765  float otj1tj2 = PosSep(otp1.Pos, vtp2.Pos);
766  float delta12 = PointTrajDOCA(tjs, otp1.Pos[0], otp1.Pos[1], vtp2);
767  float dang12 = DeltaAngle(otp1.Ang, vtp2.Ang);
768  if(otj1tj2 < tj2sep && delta12 < 1 && otj1tj2 < 4) {
769  if(prt) {
770  mf::LogVerbatim myprt("TC");
771  myprt<<"CVTjs: "<<vx2.ID<<" tj1 "<<tj1.ID<<" tj2 "<<tj2.ID;
772  myprt<<" otj1tj2 "<<otj1tj2;
773  myprt<<" delta12 "<<delta12;
774  myprt<<" dang12 "<<dang12;
775  myprt<<" Try to merge";
776  }
777  // End 1 of tj1 is closer to end0 of tj2 than tj2 is to the vertex
778  tj2.VtxID[end2] = 0;
779  if(CompatibleMerge(tjs, tj1, tj2, prt) && MergeAndStore(tjs, vxtjs[it1], vxtjs[it2], prt)) {
780  auto& newTj = tjs.allTraj[tjs.allTraj.size()-1];
781  newTj.AlgMod[kChkVxTj] = true;
782  if(prt) mf::LogVerbatim("TC")<<"CVTjs: Merged tjs "<<tj1.ID<<" and "<<tj2.ID<<" -> "<<newTj.ID;
783  } else {
784  if(prt) mf::LogVerbatim("TC")<<"CVTjs: Merge failed";
785  }
786  continue;
787  } // other end is closer
788  // now check the other end of tj2
789  float tj1otj2 = PosSep(vtp1.Pos, otp2.Pos);
790  if(tj1otj2 < tj1sep && delta12 < 1 && tj1otj2 < 4) {
791  // End 1 of tj1 is closer to end0 of tj2 than tj2 is to the vertex
792  tj1.VtxID[end1] = 0;
793  if(CompatibleMerge(tjs, tj2, tj1, prt) && MergeAndStore(tjs, vxtjs[it2], vxtjs[it1], prt)) {
794  auto& newTj = tjs.allTraj[tjs.allTraj.size()-1];
795  newTj.AlgMod[kChkVxTj] = true;
796  if(prt) mf::LogVerbatim("TC")<<"CVTjs: Merged tjs "<<tj1.ID<<" and "<<tj2.ID<<" -> "<<newTj.ID;
797  } else {
798  if(prt) mf::LogVerbatim("TC")<<"CVTjs: Merge failed";
799  }
800  } // the other end is closer
801  } // it2
802  } // it1
803  // Check for delta-rays that have a vertex when they should have been merged
804  if(vx2.Topo == 1 && vxtjs.size() == 2) {
805  auto& tj1 = tjs.allTraj[vxtjs[0] - 1];
806  auto& tj2 = tjs.allTraj[vxtjs[1] - 1];
807  // ensure that these weren't killed above
808  if(tj1.AlgMod[kKilled] || tj2.AlgMod[kKilled]) continue;
809  if(tj1.AlgMod[kDeltaRay] || tj2.AlgMod[kDeltaRay]) {
810  if(prt) mf::LogVerbatim("TC")<<"CVTjs: Merge delta rays "<<tj1.ID<<" and "<<tj2.ID<<" CompatibleMerge? "<<CompatibleMerge(tjs, tj1, tj2, prt);
811  MakeVertexObsolete(tjs, vx2, true);
812  MergeAndStore(tjs, vxtjs[0] - 1, vxtjs[1] - 1, prt);
813  } // one is a tagged delta-ray
814  } // delta-ray check
815  } // ivx
816  } // ChkVxTjs
std::string PrintPos(const TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:4738
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
vertex position fixed manually - no fitting done
Definition: DataStructs.h:102
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1607
bool CompatibleMerge(TjStuff &tjs, std::vector< int > &tjIDs, bool prt)
Definition: Utils.cxx:455
unsigned short FarEnd(const TjStuff &tjs, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:2936
float PointTrajDOCA(TjStuff const &tjs, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2139
in close()
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
bool MergeAndStore(TjStuff &tjs, unsigned int itj1, unsigned int itj2, bool doPrt)
Definition: Utils.cxx:3896
bool MakeVertexObsolete(TjStuff &tjs, Vtx3Store &vx3)
Definition: TCVertex.cxx:3001
std::vector< int > GetAssns(const TjStuff &tjs, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4079
void tca::CleanTjs ( TjStuff tjs,
PFPStruct pfp,
bool  prt 
)
void tca::ClearCRInfo ( TjStuff tjs)

Definition at line 117 of file TCCR.cxx.

References tca::CRTreeVars::cr_origin, tca::CRTreeVars::cr_pfpxmax, tca::CRTreeVars::cr_pfpxmin, tca::CRTreeVars::cr_pfpyzmindis, and tca::TjStuff::crt.

Referenced by tca::TrajClusterAlg::ClearResults().

117  {
118  tjs.crt.cr_origin.clear();
119  tjs.crt.cr_pfpxmin.clear();
120  tjs.crt.cr_pfpxmax.clear();
121  tjs.crt.cr_pfpyzmindis.clear();
122  }
void tca::ClearShowerTree ( ShowerTreeVars stv)

Definition at line 203 of file TCShTree.cxx.

References tca::ShowerTreeVars::BeginAng, tca::ShowerTreeVars::BeginChg, tca::ShowerTreeVars::BeginTim, tca::ShowerTreeVars::BeginVtx, tca::ShowerTreeVars::BeginWir, tca::ShowerTreeVars::EndAng, tca::ShowerTreeVars::EndChg, tca::ShowerTreeVars::EndTim, tca::ShowerTreeVars::EndVtx, tca::ShowerTreeVars::EndWir, tca::ShowerTreeVars::Envelope, tca::ShowerTreeVars::EnvPlane, tca::ShowerTreeVars::EnvShowerID, tca::ShowerTreeVars::EnvStage, tca::ShowerTreeVars::IsShowerParent, tca::ShowerTreeVars::IsShowerTj, tca::ShowerTreeVars::MCSMom, tca::ShowerTreeVars::PlaneNum, tca::ShowerTreeVars::ShowerID, tca::ShowerTreeVars::StageNum, and tca::ShowerTreeVars::TjID.

Referenced by tca::TrajClusterAlg::ClearResults().

203  {
204  stv.BeginWir.clear();
205  stv.BeginTim.clear();
206  stv.BeginAng.clear();
207  stv.BeginChg.clear();
208  stv.BeginVtx.clear();
209  stv.EndWir.clear();
210  stv.EndTim.clear();
211  stv.EndAng.clear();
212  stv.EndChg.clear();
213  stv.EndVtx.clear();
214  stv.MCSMom.clear();
215  stv.PlaneNum.clear();
216  stv.TjID.clear();
217  stv.IsShowerTj.clear();
218  stv.ShowerID.clear();
219  stv.IsShowerParent.clear();
220  stv.StageNum.clear();
221  stv.Envelope.clear();
222  stv.EnvPlane.clear();
223  stv.EnvStage.clear();
224  stv.EnvShowerID.clear();
225 
226  return;
227 
228  } // ClearShowerTree
unsigned short tca::CloseEnd ( TjStuff tjs,
const Trajectory tj,
const Point2_t pos 
)

Definition at line 2120 of file Utils.cxx.

References tca::Trajectory::EndPt, PosSep2(), and tca::Trajectory::Pts.

Referenced by FindNeutralVertices(), and MergeWithVertex().

2121  {
2122  unsigned short endPt = tj.EndPt[0];
2123  auto& tp0 = tj.Pts[endPt];
2124  endPt = tj.EndPt[1];
2125  auto& tp1 = tj.Pts[endPt];
2126  if(PosSep2(tp0.Pos, pos) < PosSep2(tp1.Pos, pos)) return 0;
2127  return 1;
2128  } // CloseEnd
float PosSep2(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2226
bool tca::CompatibleMerge ( TjStuff tjs,
std::vector< int > &  tjIDs,
bool  prt 
)

Definition at line 455 of file Utils.cxx.

References tca::TjStuff::allTraj, evd::details::end(), and TrajClosestApproach().

Referenced by ChkVxTjs(), DefinePFP(), and tca::TrajClusterAlg::EndMerge().

456  {
457  // Returns true if the last Tj in tjIDs has a topology consistent with it being
458  // merged with other Tjs in the same plane in the list. This is done by requiring that
459  // the closest TP between the last Tj and any other Tj is EndPt[0] or EndPt[1]. This is
460  // shown graphically here where the numbers represent the ID of a Tj that has a TP on a wire.
461  // Assume that TjIDs = {1, 2, 3, 4, 7} where T1 and T3 are in plane 0, T2 is in plane 1 and
462  // T4 is in plane 2. T7, in plane 0, was added to TjIDs with the intent of merging it with
463  // T1 and T3 into a single trajectory. This is a compatible merge if Tj7 has the following
464  // topology:
465  // 111111 333333 7777777
466  // This is an incompatible topology
467  // 111111 333333
468  // 7777777777
469  if(tjIDs.size() < 2) return false;
470  unsigned short lasttj = tjIDs[tjIDs.size() - 1] - 1;
471  auto& mtj = tjs.allTraj[lasttj];
472  bool mtjIsShort = (mtj.Pts.size() < 5);
473  // minimum separation from each end of mtj
474  std::array<float, 2> minsep2 {{1000, 1000}};
475  // ID of the Tj with the minimum separation
476  std::array<int, 2> minsepTj {{0, 0}};
477  // and the index of the point on that Tj
478  std::array<unsigned short, 2> minsepPt;
479  // determine the end of the closest Tj point. Start by assuming
480  // the closest Tj point is not near an end (end = 0);
481  std::array<unsigned short, 2> minsepEnd;
482  for(auto tjid : tjIDs) {
483  auto& tj = tjs.allTraj[tjid - 1];
484  if(tj.CTP != mtj.CTP) continue;
485  if(tj.ID == mtj.ID) continue;
486  for(unsigned short mend = 0; mend < 2; ++mend) {
487  Point2_t mendPos = mtj.Pts[mtj.EndPt[mend]].Pos;
488  float sep2 = minsep2[mend];
489  unsigned short closePt = 0;
490  if(!TrajClosestApproach(tj, mendPos[0], mendPos[1], closePt, sep2)) continue;
491  minsep2[mend] = sep2;
492  minsepTj[mend] = tjid;
493  minsepPt[mend] = closePt;
494  // set the end to a bogus value (not near an end)
495  minsepEnd[mend] = 2;
496  short dend0 = abs((short)closePt - tj.EndPt[0]);
497  short dend1 = abs((short)closePt - tj.EndPt[1]);
498  if(dend0 < dend1 && dend0 < 3) minsepEnd[mend] = 0;
499  if(dend1 < dend0 && dend1 < 3) minsepEnd[mend] = 1;
500  } // mend
501  } // tjid
502 // bool isCompatible = (minsepEnd[0] != 2 && minsepTj[0] == minsepTj[1] && minsepEnd[0] == minsepEnd[1]);
503  // don't require that the minsepTjs be the same. This would reject this topology
504  // 111111 333333 7777777
505  // if mtj.ID = 3
506  bool isCompatible = (minsepEnd[0] != 2 && minsepEnd[1] != 2);
507  // check for large separation between the closest points for short Tjs
508  if(isCompatible && mtjIsShort) {
509  float minminsep = minsep2[0];
510  if(minsep2[1] < minminsep) minminsep = minsep2[1];
511  // require that the separation be less than sqrt(5)
512  isCompatible = minminsep < 5;
513 // if(minminsep > 2) std::cout<<"CM: mtj T"<<mtj.ID<<" is short and the separation is large "<<minminsep<<". Check for signal between\n ";
514  }
515  if(prt) {
516  mf::LogVerbatim myprt("TC");
517  myprt<<"CompatibleMerge: T"<<mtj.ID<<" end";
518  for(unsigned short end = 0; end < 2; ++end) myprt<<" T"<<minsepTj[end]<<"_I"<<minsepPt[end]<<"_E"<<minsepEnd[end]<<" minsep "<<sqrt(minsep2[end]);
519  myprt<<" Compatible? "<<isCompatible;
520  } // prt
521  return isCompatible;
522 
523  } // CompatibleMerge
bool TrajClosestApproach(Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
Definition: Utils.cxx:2244
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool tca::CompatibleMerge ( TjStuff tjs,
const Trajectory tj1,
const Trajectory tj2,
bool  prt 
)

Definition at line 526 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::CTP, DeltaAngle(), tca::Trajectory::EndPt, tca::Trajectory::ID, tca::TjStuff::KinkCuts, kKilled, OverlapFraction(), PointTrajDOCA(), PosSep(), and tca::Trajectory::Pts.

527  {
528  // returns true if the two Tjs are compatible with and end0-end1 merge. This function has many aspects of the
529  // compatibility checks done in EndMerge but with looser cuts.
530  if(tj1.AlgMod[kKilled] || tj2.AlgMod[kKilled]) return false;
531  if(tj1.CTP != tj2.CTP) return false;
532  unsigned short end1 = -1, end2 = 0;
533  float minLen = PosSep(tj1.Pts[tj1.EndPt[0]].Pos, tj1.Pts[tj1.EndPt[1]].Pos);
534  float len2 = PosSep(tj2.Pts[tj2.EndPt[0]].Pos, tj2.Pts[tj2.EndPt[1]].Pos);
535  if(len2 < minLen) minLen = len2;
536  minLen *= 1.2;
537  if(minLen > 10) minLen = 10;
538  for(unsigned short e1 = 0; e1 < 2; ++e1) {
539  auto& tp1 = tj1.Pts[tj1.EndPt[e1]];
540  for(unsigned short e2 = 0; e2 < 2; ++e2) {
541  auto& tp2 = tj2.Pts[tj2.EndPt[e2]];
542  float sep = PosSep(tp1.Pos, tp2.Pos);
543  if(sep < minLen) {
544  minLen = sep;
545  end1 = e1; end2 = e2;
546  }
547  } // e2
548  } // e1
549  if(end1 < 0) return false;
550  // require end to end
551  if(end2 != 1 - end1) return false;
552 
553  float overlapFraction = OverlapFraction(tjs, tj1, tj2);
554  if(overlapFraction > 0.25) {
555  if(prt) mf::LogVerbatim("TC")<<"CM: "<<tj1.ID<<" "<<tj2.ID<<" overlapFraction "<<overlapFraction<<" > 0.25 ";
556  return false;
557  }
558 
559  auto& tp1 = tj1.Pts[tj1.EndPt[end1]];
560  auto& tp2 = tj2.Pts[tj2.EndPt[end2]];
561 /* This causes problems with hit collections that have cosmics removed
562  if(!SignalBetween(tjs, tp1, tp2, 0.8, false)) {
563  if(prt) mf::LogVerbatim("TC")<<"CM: "<<tj1.ID<<" "<<tj2.ID<<" no signal between these points "<<PrintPos(tjs, tp1.Pos)<<" "<<PrintPos(tjs, tp2.Pos);
564  return false;
565  }
566 */
567  float doca1 = PointTrajDOCA(tjs, tp1.Pos[0], tp1.Pos[1], tp2);
568  float doca2 = PointTrajDOCA(tjs, tp2.Pos[0], tp2.Pos[1], tp1);
569  if(doca1 > 2 && doca2 > 2) {
570  if(prt) mf::LogVerbatim("TC")<<"CM: "<<tj1.ID<<" "<<tj2.ID<<" Both docas > 2 "<<doca1<<" "<<doca2;
571  return false;
572  }
573 
574  float dang = DeltaAngle(tp1.Ang, tp2.Ang);
575  if(dang > 2 * tjs.KinkCuts[0]) {
576  if(prt) mf::LogVerbatim("TC")<<"CM: "<<tj1.ID<<" "<<tj2.ID<<" dang "<<dang<<" > "<<2 * tjs.KinkCuts[0];
577  return false;
578  }
579 
580  return true;
581  } // CompatibleMerge
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float OverlapFraction(TjStuff &tjs, const Trajectory &tj1, const Trajectory &tj2)
Definition: Utils.cxx:584
float PosSep(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2220
float PointTrajDOCA(TjStuff const &tjs, float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2147
double DeltaAngle(double Ang1, double Ang2)
Definition: Utils.cxx:2782
void tca::CompleteIncomplete3DVertices ( TjStuff tjs,
const geo::TPCID tpcid 
)

Definition at line 2569 of file TCVertex.cxx.

References tca::TjStuff::allTraj, AttachAnyTrajToVertex(), ChgFracNearPos(), detinfo::DetectorProperties::ConvertXToTicks(), tca::VtxStore::CTP, debug, tca::TjStuff::detprop, EncodeCTP(), evd::details::end(), GetAssns(), tca::VtxStore::ID, kComp3DVx, kFixed, kKilled, MakeVertexObsolete(), tca::VtxStore::NTraj, tca::TjStuff::NumPlanes, NumPtsWithCharge(), tca::VtxStore::Pass, tca::DebugStuff::Plane, tca::VtxStore::Pos, tca::TrajPoint::Pos, PrintPos(), RefineVtxPosition(), SetPDGCode(), SetVx2Score(), SplitTraj(), tca::VtxStore::Stat, StoreVertex(), tca::DebugStuff::Tick, tca::VtxStore::TjChgFrac, util::flags::to_string(), tca::VtxStore::Topo, TrajPointTrajDOCA(), tca::TjStuff::UnitsPerTick, tca::TjStuff::UseAlg, tca::TjStuff::vtx, tca::TjStuff::vtx3, and tca::VtxStore::Vx3ID.

Referenced by Find3DVertices().

2570  {
2571  // Look for trajectories in a plane that lack a 2D vertex as listed in
2572  // 2DVtxID that are near the projected wire. This may trigger splitting trajectories,
2573  // assigning them to a new 2D vertex and completing 3D vertices
2574 
2575  if(!tjs.UseAlg[kComp3DVx]) return;
2576  if(tjs.NumPlanes != 3) return;
2577 
2578  bool prt = (debug.Plane >= 0 && debug.Tick == 33333);
2579 
2580  float maxdoca = 3;
2581  if(prt) mf::LogVerbatim("TC")<<"Inside CI3DV with maxdoca set to "<<maxdoca;
2582  unsigned short ivx3 = 0;
2583  for(auto& vx3 : tjs.vtx3) {
2584  // ignore obsolete vertices
2585  if(vx3.ID == 0) continue;
2586  if(vx3.TPCID != tpcid) continue;
2587  // check for a completed 3D vertex
2588  if(vx3.Wire < 0) continue;
2589  unsigned short mPlane = USHRT_MAX;
2590  for(unsigned short plane = 0; plane < tjs.NumPlanes; ++plane) {
2591  if(vx3.Vx2ID[plane] > 0) continue;
2592  mPlane = plane;
2593  } // ipl
2594  if(mPlane == USHRT_MAX) continue;
2595  CTP_t mCTP = EncodeCTP(vx3.TPCID.Cryostat, vx3.TPCID.TPC, mPlane);
2596  // X position of the purported missing vertex
2597  // A TP for the missing 2D vertex
2598  TrajPoint vtp;
2599  vtp.Pos[0] = vx3.Wire;
2600  vtp.Pos[1] = tjs.detprop->ConvertXToTicks(vx3.X, mPlane, vx3.TPCID.TPC, vx3.TPCID.Cryostat) * tjs.UnitsPerTick;
2601  if(prt) mf::LogVerbatim("TC")<<"CI3DV 3V"<<vx3.ID<<" Pos "<<mPlane<<":"<<PrintPos(tjs, vtp.Pos);
2602  std::vector<int> tjIDs;
2603  std::vector<unsigned short> tjPts;
2604  for(auto& tj : tjs.allTraj) {
2605  if(tj.CTP != mCTP) continue;
2606  if(tj.AlgMod[kKilled]) continue;
2607  if(tj.Pts.size() < 6) continue;
2608  if(tj.AlgMod[kComp3DVx]) continue;
2609  float doca = maxdoca;
2610  // find the closest distance between the vertex and the trajectory
2611  unsigned short closePt = 0;
2612  TrajPointTrajDOCA(tjs, vtp, tj, closePt, doca);
2613  if(closePt > tj.EndPt[1]) continue;
2614  // try to improve the location of the vertex by looking for a distinctive feature on the
2615  // trajectory, e.g. high multiplicity hits or larger than normal charge
2616  if(RefineVtxPosition(tjs, tj, closePt, 3, false)) vtp.Pos = tj.Pts[closePt].Pos;
2617  if(prt) mf::LogVerbatim("TC")<<"CI3DV 3V"<<vx3.ID<<" candidate itj ID "<<tj.ID<<" vtx pos "<<PrintPos(tjs, vtp.Pos)<<" doca "<<doca;
2618  tjIDs.push_back(tj.ID);
2619  tjPts.push_back(closePt);
2620  } // itj
2621  if(tjIDs.empty()) continue;
2622  // compare the length of the Tjs used to make the vertex with the length of the
2623  // Tj that we want to split. Don't allow a vertex using very short Tjs to split a long
2624  // Tj in the 3rd plane
2625 // float score;
2626 // auto vxtjs = GetVtxTjIDs(tjs, vx3, score);
2627  auto vxtjs = GetAssns(tjs, "3V", vx3.ID, "T");
2628  unsigned short maxPts = 0;
2629  for(auto tjid : vxtjs) {
2630  auto& tj = tjs.allTraj[tjid - 1];
2631  unsigned short npwc = NumPtsWithCharge(tjs, tj, false);
2632  if(npwc > maxPts) maxPts = npwc;
2633  } // tjid
2634  // skip this operation if any of the Tjs in the split list are > 3 * maxPts
2635  maxPts *= 3;
2636  bool skipit = false;
2637  for(auto tjid : tjIDs) {
2638  auto& tj = tjs.allTraj[tjid - 1];
2639  if(NumPtsWithCharge(tjs, tj, false) > maxPts) skipit = true;
2640  } // tjid
2641  if(prt) mf::LogVerbatim("TC")<<" maxPts "<<maxPts<<" skipit? "<<skipit;
2642  if(skipit) continue;
2643  // 2D vertex
2644  VtxStore aVtx;
2645  unsigned short newVtxIndx = tjs.vtx.size();
2646  aVtx.ID = newVtxIndx + 1;
2647  aVtx.CTP = mCTP;
2648  aVtx.Topo = 3;
2649  aVtx.NTraj = 0;
2650  // Give it a bogus pass to indicate it wasn't created while stepping
2651  aVtx.Pass = 9;
2652  aVtx.Pos = vtp.Pos;
2653  // ensure this isn't in a messy region
2654  aVtx.TjChgFrac = ChgFracNearPos(tjs, aVtx.Pos, tjIDs);
2655  if(prt) mf::LogVerbatim("TC")<<" charge fraction near position "<<aVtx.TjChgFrac;
2656  if(aVtx.TjChgFrac < 0.6) continue;
2657  if(!StoreVertex(tjs, aVtx)) continue;
2658  // make a reference to the new vertex
2659  VtxStore& newVtx = tjs.vtx[tjs.vtx.size()-1];
2660  if(prt) mf::LogVerbatim("TC")<<" Stored 2D vertex "<<newVtx.ID;
2661  // make a temporary copy so we can nudge it a bit if there is only one Tj
2662  std::array<float, 2> vpos = aVtx.Pos;
2663  for(unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2664  unsigned short itj = tjIDs[ii] - 1;
2665  // Don't use a reference variable since it may get scrambled after SplitTraj
2666 // auto& tj = tjs.allTraj[itj];
2667  unsigned short closePt = tjPts[ii];
2668  // determine which end is the closest
2669  unsigned short end = 1;
2670  // closest to the beginning?
2671  if(fabs(closePt - tjs.allTraj[itj].EndPt[0]) < fabs(closePt - tjs.allTraj[itj].EndPt[1])) end = 0;
2672  short dpt = fabs(closePt - tjs.allTraj[itj].EndPt[end]);
2673  if(dpt < 3) {
2674  // close to an end
2675  if(tjs.allTraj[itj].VtxID[end] > 0) {
2676  if(prt) mf::LogVerbatim("TC")<<" T"<<tjs.allTraj[itj].ID<<" has a vertex "<<tjs.allTraj[itj].VtxID[end]<<" at end "<<end<<". Skip it";
2677  continue;
2678  }
2679  tjs.allTraj[itj].VtxID[end] = tjs.vtx[newVtxIndx].ID;
2680  ++newVtx.NTraj;
2681  if(prt) mf::LogVerbatim("TC")<<" attach Traj T"<<tjs.allTraj[itj].ID<<" at end "<<end;
2682  tjs.allTraj[itj].AlgMod[kComp3DVx] = true;
2683  vpos = tjs.allTraj[itj].Pts[tjs.allTraj[itj].EndPt[end]].Pos;
2684  } else {
2685  // closePt is not near an end, so split the trajectory
2686  if(SplitTraj(tjs, itj, closePt, newVtxIndx, prt)) {
2687  if(prt) mf::LogVerbatim("TC")<<" SplitTraj success 2V"<<tjs.vtx[newVtxIndx].ID<<" at closePt "<<closePt;
2688  // successfully split the Tj
2689  newVtx.NTraj += 2;
2690  } else {
2691  // split failed. Give up
2692  if(prt) mf::LogVerbatim("TC")<<" SplitTraj failed";
2693  newVtx.NTraj = 0;
2694  break;
2695  }
2696  // Update the PDGCode for the chopped trajectory
2697  SetPDGCode(tjs, itj);
2698  // and for the new trajectory
2699  SetPDGCode(tjs, tjs.allTraj.size()-1);
2700  } // closePt is not near an end, so split the trajectory
2701  tjs.allTraj[itj].AlgMod[kComp3DVx] = true;
2702  unsigned short newtj = tjs.allTraj.size() - 1;
2703  tjs.allTraj[newtj].AlgMod[kComp3DVx] = true;
2704  } // ii
2705  if(newVtx.NTraj == 0) {
2706  // A failure occurred. Recover
2707  if(prt) mf::LogVerbatim("TC")<<" Failed. Recover and delete vertex "<<newVtx.ID;
2708  MakeVertexObsolete(tjs, newVtx, true);
2709  } else {
2710  // success
2711  vx3.Vx2ID[mPlane] = newVtx.ID;
2712  newVtx.Vx3ID = vx3.ID;
2713  vx3.Wire = -1;
2714  // set the vertex position to the start of the Tj if there is only one and fix it
2715  if(newVtx.NTraj == 1) {
2716  newVtx.Pos = vpos;
2717  newVtx.Stat[kFixed] = true;
2718  }
2719  AttachAnyTrajToVertex(tjs, newVtx.ID - 1, prt);
2720  SetVx2Score(tjs, prt);
2721  if(prt) {
2722  mf::LogVerbatim myprt("TC");
2723  myprt<<" Success: new 2V"<<newVtx.ID<<" at "<<(int)newVtx.Pos[0]<<":"<<(int)newVtx.Pos[1]/tjs.UnitsPerTick;
2724  myprt<<" points to 3V"<<vx3.ID;
2725  myprt<<" TjIDs:";
2726  for(auto& tjID : tjIDs) myprt<<" T"<<std::to_string(tjID);
2727  } // prt
2728  } // success
2729  ++ivx3;
2730  } // vx3
2731 
2732  } // CompleteIncomplete3DVertices
std::string PrintPos(const TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:4738
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool RefineVtxPosition(TjStuff &tjs, const Trajectory &tj, unsigned short &nearPt, short nPtsToChk, bool prt)
Definition: TCVertex.cxx:2735
vertex position fixed manually - no fitting done
Definition: DataStructs.h:102
bool AttachAnyTrajToVertex(TjStuff &tjs, unsigned short ivx, bool prt)
Definition: TCVertex.cxx:1689
bool SplitTraj(TjStuff &tjs, unsigned short itj, float XPos, bool makeVx2, bool prt)
Definition: Utils.cxx:1879
DebugStuff debug
Definition: DebugStruct.cxx:4
int Plane
Select plane.
Definition: DebugStruct.h:29
float ChgFracNearPos(TjStuff &tjs, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2614
int Tick
Select hit PeakTime for debugging (< 0 for vertex finding)
Definition: DebugStruct.h:32
unsigned int CTP_t
Definition: DataStructs.h:41
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Definition: BitMask.h:187
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
unsigned short NumPtsWithCharge(const TjStuff &tjs, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1738
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void SetPDGCode(TjStuff &tjs, unsigned short itj)
Definition: Utils.cxx:3697
bool StoreVertex(TjStuff &tjs, VtxStore &vx)
Definition: TCVertex.cxx:1911
bool MakeVertexObsolete(TjStuff &tjs, Vtx3Store &vx3)
Definition: TCVertex.cxx:3001
void TrajPointTrajDOCA(TjStuff &tjs, TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
Definition: Utils.cxx:2026
std::vector< int > GetAssns(const TjStuff &tjs, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4079
void SetVx2Score(TjStuff &tjs, VtxStore &vx2, bool prt)
Definition: TCVertex.cxx:2331
void tca::CompleteIncomplete3DVerticesInGaps ( TjStuff tjs,
const geo::TPCID tpcid 
)

Definition at line 2478 of file TCVertex.cxx.

References tca::TjStuff::allTraj, ChgFracNearPos(), detinfo::DetectorProperties::ConvertXToTicks(), geo::CryostatID::Cryostat, tca::VtxStore::CTP, tca::TrajPoint::CTP, DeadWireCount(), debug, tca::TjStuff::detprop, EncodeCTP(), evd::details::end(), tca::VtxStore::ID, tca::Vtx3Store::ID, kComp3DVxIG, kKilled, tca::VtxStore::NTraj, tca::TjStuff::NumPlanes, tca::VtxStore::Pass, tca::DebugStuff::Plane, PointTrajDOCA(), tca::VtxStore::Pos, tca::TrajPoint::Pos, SetVx2Score(), StoreVertex(), tca::DebugStuff::Tick, tca::VtxStore::TjChgFrac, tca::VtxStore::Topo, geo::TPCID::TPC, tca::Vtx3Store::TPCID, tca::TjStuff::UnitsPerTick, tca::TjStuff::UseAlg, tca::TjStuff::vtx, tca::TjStuff::vtx3, tca::Vtx3Store::Vx2ID, tca::VtxStore::Vx3ID, tca::Vtx3Store::Wire, and tca::Vtx3Store::X.

Referenced by Find3DVertices().

2479  {
2480 
2481  if(!tjs.UseAlg[kComp3DVxIG]) return;
2482  if(tjs.NumPlanes != 3) return;
2483 
2484  bool prt = (debug.Plane >= 0 && debug.Tick == 44444);
2485  if(prt) mf::LogVerbatim("TC")<<"Inside CI3DVIG:";
2486 
2487  for(unsigned short iv3 = 0; iv3 < tjs.vtx3.size(); ++iv3) {
2488  Vtx3Store& vx3 = tjs.vtx3[iv3];
2489  // ignore obsolete vertices
2490  if(vx3.ID == 0) continue;
2491  if(vx3.TPCID != tpcid) continue;
2492  // check for a completed 3D vertex
2493  if(vx3.Wire < 0) continue;
2494  unsigned short mPlane = USHRT_MAX;
2495  for(unsigned short ipl = 0; ipl < tjs.NumPlanes; ++ipl) {
2496  if(vx3.Vx2ID[ipl] > 0) continue;
2497  mPlane = ipl;
2498  break;
2499  } // ipl
2500  if(mPlane == USHRT_MAX) continue;
2501 // CTP_t mCTP = EncodeCTP(vx3.CStat, vx3.TPC, mPlane);
2502  CTP_t mCTP = EncodeCTP(vx3.TPCID.Cryostat, vx3.TPCID.TPC, mPlane);
2503  // require that the missing vertex be in a large block of dead wires
2504  float dwc = DeadWireCount(tjs, vx3.Wire - 4, vx3.Wire + 4, mCTP);
2505  if(dwc < 5) continue;
2506  // X position of the purported missing vertex
2507  // A TP for the missing 2D vertex
2508  VtxStore aVtx;
2509  aVtx.ID = tjs.vtx.size() + 1;
2510  aVtx.Pos[0] = vx3.Wire;
2511  aVtx.Pos[1] = tjs.detprop->ConvertXToTicks(vx3.X, mPlane, vx3.TPCID.TPC, vx3.TPCID.Cryostat) * tjs.UnitsPerTick;
2512  aVtx.CTP = mCTP;
2513  aVtx.Topo = 4;
2514  aVtx.NTraj = 0;
2515  // Give it a bogus pass to indicate it wasn't created while stepping
2516  aVtx.Pass = 9;
2517  if(prt) mf::LogVerbatim("TC")<<"CI3DVIG: Incomplete vertex "<<iv3<<" in plane "<<mPlane<<" wire "<<vx3.Wire<<" Made 2D vertex ";
2518  std::vector<int> tjIDs;
2519  std::vector<unsigned short> tjEnds;
2520  for(unsigned short itj = 0; itj < tjs.allTraj.size(); ++itj) {
2521  if(tjs.allTraj[itj].CTP != mCTP) continue;
2522  if(tjs.allTraj[itj].AlgMod[kKilled]) continue;
2523  for(unsigned short end = 0; end < 2; ++end) {
2524  unsigned short ept = tjs.allTraj[itj].EndPt[end];
2525  TrajPoint& tp = tjs.allTraj[itj].Pts[ept];
2526  unsigned short oept = tjs.allTraj[itj].EndPt[1 - end];
2527  TrajPoint& otp = tjs.allTraj[itj].Pts[oept];
2528  // ensure that this is the end closest to the vertex
2529  if(std::abs(tp.Pos[0] - aVtx.Pos[0]) > std::abs(otp.Pos[0] - aVtx.Pos[0])) continue;
2530  float doca = PointTrajDOCA(tjs, aVtx.Pos[0], aVtx.Pos[1], tp);
2531  if(doca > 2) continue;
2532  float dwc = DeadWireCount(tjs, aVtx.Pos[0], tp.Pos[0], tp.CTP);
2533  float ptSep;
2534  if(aVtx.Pos[0] > tp.Pos[0]) {
2535  ptSep = aVtx.Pos[0] - tp.Pos[0] - dwc;
2536  } else {
2537  ptSep = tp.Pos[0] - aVtx.Pos[0] - dwc;
2538  }
2539  if(prt) mf::LogVerbatim("TC")<<"CI3DVIG: tj ID "<<tjs.allTraj[itj].ID<<" doca "<<doca<<" ptSep "<<ptSep;
2540  if(ptSep < -2 || ptSep > 2) continue;
2541  // don't clobber an existing association
2542  if(tjs.allTraj[itj].VtxID[end] > 0) continue;
2543  tjIDs.push_back(tjs.allTraj[itj].ID);
2544  tjEnds.push_back(end);
2545  } // end
2546  } // itj
2547  if(!tjIDs.empty()) {
2548  // Determine how messy this region is
2549  aVtx.TjChgFrac = ChgFracNearPos(tjs, aVtx.Pos, tjIDs);
2550  if(aVtx.TjChgFrac < 0.7) continue;
2551  aVtx.Vx3ID = vx3.ID;
2552  // Save the 2D vertex
2553  if(!StoreVertex(tjs, aVtx)) continue;
2554  for(unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2555  unsigned short itj = tjIDs[ii] - 1;
2556  tjs.allTraj[itj].VtxID[tjEnds[ii]] = aVtx.ID;
2557  tjs.allTraj[itj].AlgMod[kComp3DVxIG] = true;
2558  } // ii
2559  SetVx2Score(tjs, prt);
2560  vx3.Vx2ID[mPlane] = aVtx.ID;
2561  vx3.Wire = -1;
2562  if(prt) mf::LogVerbatim("TC")<<"CI3DVIG: new vtx 2V"<<aVtx.ID<<" points to 3V"<<vx3.ID;
2563  }
2564  } // vx3
2565 
2566  } // CompleteIncomplete3DVerticesInGaps
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float DeadWireCount(const TjStuff &tjs, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:1756
DebugStuff debug
Definition: DebugStruct.cxx:4
int Plane
Select plane.
Definition: DebugStruct.h:29
float PointTrajDOCA(TjStuff const &tjs, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2139
float ChgFracNearPos(TjStuff &tjs, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2614
int Tick
Select hit PeakTime for debugging (< 0 for vertex finding)
Definition: DebugStruct.h:32
unsigned int CTP_t
Definition: DataStructs.h:41
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool StoreVertex(TjStuff &tjs, VtxStore &vx)
Definition: TCVertex.cxx:1911
void SetVx2Score(TjStuff &tjs, VtxStore &vx2, bool prt)
Definition: TCVertex.cxx:2331
bool tca::CompleteIncompleteShower ( std::string  inFcnLabel,
TjStuff tjs,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 804 of file TCShower.cxx.

References tca::TjStuff::allTraj, ChkAssns(), tca::ShowerStruct3D::CotIDs, tca::TjStuff::cots, CreateSS(), DecodeCTP(), evd::details::end(), GetAssns(), tca::ShowerStruct3D::ID, kCompleteShower, MakeShowerObsolete(), tca::ShowerStruct3D::NeedsUpdate, tca::TjStuff::NumPlanes, tca::TjStuff::pfps, geo::PlaneID::Plane, SetIntersection(), ShowerEnergy(), ss, StoreShower(), UpdateShower(), tca::TjStuff::UseAlg, and tca::TjStuff::vtx.

Referenced by Match2DShowers().

805  {
806  // Find low-energy two-plane showers and try to complete it by making a 2D shower in the third
807  // plane using 3D matched tjs
808 
809  if(tjs.NumPlanes != 3) return false;
810  if(ss3.CotIDs.size() != 2) return false;
811 
812  if(!tjs.UseAlg[kCompleteShower]) return false;
813 
814  std::string fcnLabel = inFcnLabel + ".CIS";
815  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID;
816 
817  auto& iss = tjs.cots[ss3.CotIDs[0] - 1];
818  auto& jss = tjs.cots[ss3.CotIDs[1] - 1];
819  // make a list of pfps for each SS
820  std::vector<int> iplist;
821  for(auto tid : iss.TjIDs) {
822  auto plist = GetAssns(tjs, "T", tid, "P");
823  if(!plist.empty()) iplist.insert(iplist.end(), plist.begin(), plist.end());
824  } // tid
825  std::vector<int> jplist;
826  for(auto tid : jss.TjIDs) {
827  auto plist = GetAssns(tjs, "T", tid, "P");
828  if(!plist.empty()) jplist.insert(jplist.end(), plist.begin(), plist.end());
829  } // tid
830  // look for pfps that have tjs in both showers
831  auto shared = SetIntersection(iplist, jplist);
832  if(shared.empty()) return false;
833  // put the list of tjs for both SS into a flat vector to simplify searching
834  std::vector<int> flat = iss.TjIDs;
835  flat.insert(flat.end(), jss.TjIDs.begin(), jss.TjIDs.end());
836  // make a list of tjs in the k plane that maybe should made into a shower if they
837  // aren't already in a shower that failed the 3D match
838  std::vector<int> ktlist;
839  for(auto pid : shared) {
840  auto& pfp = tjs.pfps[pid - 1];
841  for(auto tid : pfp.TjIDs) {
842  // ignore the tjs that are already in the shower in the other planes
843  if(std::find(flat.begin(), flat.end(), tid) != flat.end()) continue;
844  if(std::find(ktlist.begin(), ktlist.end(), tid) == ktlist.end()) ktlist.push_back(tid);
845  // look for 2D vertices attached to this tj and add all attached tjs to ktlist
846  auto& tj = tjs.allTraj[tid - 1];
847  for(unsigned short end = 0; end < 2; ++end) {
848  if(tj.VtxID[end] <= 0) continue;
849  auto& vx2 = tjs.vtx[tj.VtxID[end] - 1];
850  auto TIn2V = GetAssns(tjs, "2V", vx2.ID, "T");
851  for(auto vtid : TIn2V) {
852  if(std::find(ktlist.begin(), ktlist.end(), vtid) == ktlist.end()) ktlist.push_back(vtid);
853  }
854  } // end
855  } // tid
856  } // pid
857  if(ktlist.empty()) return false;
858  // list of 2D showers that include tjs in ktlist
859  std::vector<int> ksslist;
860  for(auto tid : ktlist) {
861  auto& tj = tjs.allTraj[tid - 1];
862  if(tj.SSID == 0) continue;
863  // ignore showers that are 3D-matched. This case should be handled elsewhere by a merging function
864  auto& ss = tjs.cots[tj.SSID - 1];
865  if(ss.SS3ID > 0) {
866  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Found existing T"<<tid<<" -> 2S"<<ss.ID<<" -> 3S"<<ss.SS3ID<<" assn. Give up";
867  return false;
868  }
869  if(std::find(ksslist.begin(), ksslist.end(), ss.ID) == ksslist.end()) ksslist.push_back(ss.ID);
870  } // tid
871  // find the shower energy for this list
872  float ktlistEnergy = ShowerEnergy(tjs, ktlist);
873  if(prt) {
874  mf::LogVerbatim myprt("TC");
875  myprt<<fcnLabel<<" 3S"<<ss3.ID<<"\n";
876  myprt<<" -> i2S"<<iss.ID<<" ->";
877  for(auto pid : iplist) myprt<<" P"<<pid;
878  myprt<<"\n";
879  myprt<<" -> j2S"<<jss.ID<<" ->";
880  for(auto pid : jplist) myprt<<" P"<<pid;
881  myprt<<"\n";
882  geo::PlaneID iPlaneID = DecodeCTP(iss.CTP);
883  geo::PlaneID jPlaneID = DecodeCTP(jss.CTP);
884  unsigned short kplane = 3 - iPlaneID.Plane - jPlaneID.Plane;
885  myprt<<" kplane "<<kplane<<" ktlist:";
886  for(auto tid : ktlist) myprt<<" T"<<tid;
887  myprt<<" ktlistEnergy "<<ktlistEnergy;
888  if(ksslist.empty()) {
889  myprt<<"\n No matching showers in kplane";
890  } else {
891  myprt<<"\n";
892  myprt<<" Candidate showers:";
893  for(auto ssid : ksslist) {
894  myprt<<" 2S"<<ssid;
895  auto& sst = tjs.cots[ssid - 1];
896  if(sst.SS3ID > 0) myprt<<"_3S"<<sst.SS3ID;
897  } // ssid
898  } // ssList not empty
899  } // prt
900  if(ksslist.size() > 1) {
901  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Found more than 1 shower. Need some better code here";
902  return false;
903  }
904  if(ktlistEnergy > 2 * ShowerEnergy(ss3)) {
905  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" ktlistEnergy exceeds 2 * ss3 energy. Need some better code here";
906  return false;
907  } // ktlistEnergy too high
908 
909  if(ksslist.empty()) {
910  // no 2D shower so make one using ktlist
911  auto kss = CreateSS(tjs, 0, ktlist);
912  if(kss.ID == 0) return false;
913  kss.SS3ID = ss3.ID;
914  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" create new 2S"<<kss.ID<<" from ktlist";
915  if(!UpdateShower(fcnLabel, tjs, kss, prt)) {
916  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" UpdateShower failed 2S"<<kss.ID;
917  MakeShowerObsolete(fcnLabel, tjs, kss, prt);
918  return false;
919  } // UpdateShower failed
920  if(!StoreShower(fcnLabel, tjs, kss)) {
921  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" StoreShower failed";
922  MakeShowerObsolete(fcnLabel, tjs, kss, prt);
923  return false;
924  } // StoreShower failed
925  ss3.CotIDs.push_back(kss.ID);
926  auto& stj = tjs.allTraj[kss.ShowerTjID - 1];
927  stj.AlgMod[kCompleteShower] = true;
928  ss3.NeedsUpdate = true;
929  return true;
930  } // ksslist empty
931 
932  // associate ksslist[0] with 3S
933  auto& ss = tjs.cots[ksslist[0] - 1];
934  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" found pfp-matched 2S"<<ss.ID;
935  ss.SS3ID = ss3.ID;
936  ss3.CotIDs.push_back(ss.ID);
937  auto& stj = tjs.allTraj[ss.ShowerTjID - 1];
938  stj.AlgMod[kCompleteShower] = true;
939  ss3.NeedsUpdate = true;
940 
941  ChkAssns(fcnLabel, tjs);
942  return true;
943 
944  } // CompleteIncompleteShower
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void MakeShowerObsolete(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3334
bool ChkAssns(std::string inFcnLabel, TjStuff &tjs)
Definition: TCShower.cxx:4625
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
Float_t ss
Definition: plot.C:23
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:214
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
float ShowerEnergy(const TjStuff &tjs, const std::vector< int > tjIDs)
Definition: TCShower.cxx:4447
bool StoreShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss)
Definition: TCShower.cxx:4511
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
ShowerStruct CreateSS(TjStuff &tjs, CTP_t inCTP, const std::vector< int > &tjl)
Definition: TCShower.cxx:4572
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
std::vector< int > GetAssns(const TjStuff &tjs, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4079
bool UpdateShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1302
void tca::ConfigureMVA ( TjStuff tjs,
std::string  fMVAShowerParentWeights 
)

Definition at line 15 of file TCShower.cxx.

References tca::TjStuff::ShowerParentReader, and tca::TjStuff::ShowerParentVars.

Referenced by tca::TrajClusterAlg::reconfigure().

16  {
17  // Define the reference in TJStuff to the MVA reader used to determine the best
18  // shower parent PFParticle
19  cet::search_path sp("FW_SEARCH_PATH");
20  if(!tjs.ShowerParentReader) {
21  std::cout<<"its not defined\n";
22  return;
23  }
24  std::string fullFileSpec;
25  sp.find_file(fMVAShowerParentWeights, fullFileSpec);
26  if(fullFileSpec == "") {
27  std::cout<<"ConfigureMVA: weights file "<<fMVAShowerParentWeights<<" not found in path\n";
28  tjs.ShowerParentReader = 0;
29  return;
30  }
31  tjs.ShowerParentVars.resize(9);
32  tjs.ShowerParentReader->AddVariable("fShEnergy", &tjs.ShowerParentVars[0]);
33  tjs.ShowerParentReader->AddVariable("fPfpEnergy", &tjs.ShowerParentVars[1]);
34  tjs.ShowerParentReader->AddVariable("fMCSMom", &tjs.ShowerParentVars[2]);
35  tjs.ShowerParentReader->AddVariable("fPfpLen", &tjs.ShowerParentVars[3]);
36  tjs.ShowerParentReader->AddVariable("fSep", &tjs.ShowerParentVars[4]);
37  tjs.ShowerParentReader->AddVariable("fDang1", &tjs.ShowerParentVars[5]);
38  tjs.ShowerParentReader->AddVariable("fDang2", &tjs.ShowerParentVars[6]);
39  tjs.ShowerParentReader->AddVariable("fChgFrac", &tjs.ShowerParentVars[7]);
40  tjs.ShowerParentReader->AddVariable("fInShwrProb", &tjs.ShowerParentVars[8]);
41  tjs.ShowerParentReader->BookMVA("BDT", fullFileSpec);
42  } // ConfigureTMVA
PFPStruct tca::CreateFakePFP ( const TjStuff tjs,
const ShowerStruct3D ss3 
)

Definition at line 2050 of file TCShower.cxx.

References CreatePFP(), tca::ShowerStruct3D::Dir, tca::ShowerStruct3D::End, tca::ShowerStruct3D::Len, PointDirection(), tca::ShowerStruct3D::Start, and tca::ShowerStruct3D::TPCID.

2051  {
2052  // Creates a fake PFParticle on the shower axis with a TP3S point every cm. This is
2053  // used to find the separation between the shower core and a PFParticle or trajectory
2054  auto pfp = CreatePFP(tjs, ss3.TPCID);
2055  pfp.XYZ[0] = ss3.Start;
2056  pfp.Dir[0] = ss3.Dir;
2057  pfp.XYZ[1] = ss3.End;
2058  pfp.Dir[1] = ss3.Dir;
2059  pfp.Dir[0] = PointDirection(ss3.Start, ss3.End);
2060  unsigned short npts = ss3.Len;
2061  if(npts < 2) return pfp;
2062  pfp.Tp3s.resize(npts);
2063  pfp.Tp3s[0].Pos = ss3.Start;
2064  for(unsigned short ipt = 1; ipt < npts; ++ipt) {
2065  for(unsigned short xyz = 0; xyz < 3; ++xyz) pfp.Tp3s[ipt].Pos[xyz] = pfp.Tp3s[ipt-1].Pos[xyz] + pfp.Dir[0][xyz];
2066  } // ipt
2067  return pfp;
2068  } // CreateFakePFP
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:1614
PFPStruct CreatePFP(const TjStuff &tjs, const geo::TPCID &tpcid)
Definition: PFPUtils.cxx:1943
PFPStruct tca::CreatePFP ( const TjStuff tjs,
const geo::TPCID tpcid 
)

Definition at line 1943 of file PFPUtils.cxx.

References tca::PFPStruct::dEdx, tca::PFPStruct::dEdxErr, tca::PFPStruct::Dir, tca::PFPStruct::DirErr, tca::PFPStruct::ID, tca::TjStuff::NumPlanes, tca::PFPStruct::ParentID, tca::TjStuff::pfps, tca::PFPStruct::TPCID, and tca::PFPStruct::XYZ.

Referenced by CreateFakePFP(), DefineTjParents(), DotProd(), FindPFParticles(), Finish3DShowers(), and Match3DVtxTjs().

1944  {
1945  // The calling function should define the size of pfp.TjIDs
1946  PFPStruct pfp;
1947  pfp.ID = tjs.pfps.size() + 1;
1948  pfp.ParentID = 0;
1949  pfp.TPCID = tpcid;
1950  // initialize arrays for both ends
1951  if(tjs.NumPlanes < 4) {
1952  pfp.dEdx[0].resize(tjs.NumPlanes, 0);
1953  pfp.dEdx[1].resize(tjs.NumPlanes, 0);
1954  pfp.dEdxErr[0].resize(tjs.NumPlanes, 0);
1955  pfp.dEdxErr[1].resize(tjs.NumPlanes, 0);
1956  }
1957  for(unsigned short startend = 0; startend < 2; ++startend) {
1958  // BUG the double brace syntax is required to work around clang bug 21629
1959  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1960  pfp.Dir[startend] = {{0.0, 0.0, 0.0}};
1961  pfp.DirErr[startend] = {{0.0, 0.0, 0.0}};
1962  pfp.XYZ[startend] = {{0.0, 0.0, 0.0}};
1963  }
1964  return pfp;
1965  } // CreatePFP
ShowerStruct tca::CreateSS ( TjStuff tjs,
CTP_t  inCTP,
const std::vector< int > &  tjl 
)

Definition at line 4572 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::ShowerStruct::Cheat, tca::TjStuff::cots, tca::Trajectory::CTP, tca::ShowerStruct::CTP, tca::ShowerStruct::Envelope, tca::ShowerStruct::ID, kCheat, kShowerTj, tca::ShowerStruct::ShowerTjID, ss, and tca::ShowerStruct::TjIDs.

Referenced by CompleteIncompleteShower(), FindShowers3D(), tca::MCParticleListUtils::MakeCheatShower(), and MergeShowers().

4573  {
4574  // Create a shower and shower Tj using Tjs in the list. If tjl is empty a
4575  // MC cheat shower is created inCTP. Note that inCTP is only used if tjl is empty.
4576  // A companion shower tj is created and stored but the ShowerStruct is not.
4577  ShowerStruct ss;
4578 
4579  if(tjl.empty()) ss.Cheat = true;
4580 
4581  // Create the shower tj
4582  Trajectory stj;
4583  if(ss.Cheat) {
4584  stj.CTP = inCTP;
4585  } else {
4586  stj.CTP = tjs.allTraj[tjl[0]-1].CTP;
4587  }
4588  // with three points
4589  stj.Pts.resize(3);
4590  for(auto& stp : stj.Pts) {
4591  stp.CTP = stj.CTP;
4592  // set all UseHit bits true so we don't get confused
4593  stp.UseHit.set();
4594  }
4595  stj.EndPt[0] = 0;
4596  stj.EndPt[1] = 2;
4597  stj.ID = tjs.allTraj.size() + 1;
4598  // Declare that stj is a shower Tj
4599  stj.AlgMod[kShowerTj] = true;
4600  // and maybe a cheat trajectory
4601  if(ss.Cheat) stj.AlgMod[kCheat] = true;
4602  stj.PDGCode = 1111;
4603  tjs.allTraj.push_back(stj);
4604  // define the ss
4605  ss.ID = tjs.cots.size() + 1;
4606  ss.CTP = stj.CTP;
4607  // assign all TJ IDs to this ShowerStruct
4608  ss.TjIDs = tjl;
4609  // declare them to be InShower
4610  for(auto tjid : tjl) {
4611  auto& tj = tjs.allTraj[tjid - 1];
4612  if(tj.CTP != stj.CTP) {
4613  ss.ID = 0;
4614  return ss;
4615  }
4616  tj.SSID = ss.ID;
4617  } // tjid
4618  ss.ShowerTjID = stj.ID;
4619  ss.Envelope.resize(4);
4620  return ss;
4621 
4622  } // CreateSS
Float_t ss
Definition: plot.C:23
ShowerStruct3D tca::CreateSS3 ( TjStuff tjs,
const geo::TPCID tpcid 
)

Definition at line 4553 of file TCShower.cxx.

References tca::ShowerStruct3D::dEdx, tca::ShowerStruct3D::dEdxErr, tca::ShowerStruct3D::Energy, tca::ShowerStruct3D::EnergyErr, tca::ShowerStruct3D::ID, tca::ShowerStruct3D::MIPEnergy, tca::ShowerStruct3D::MIPEnergyErr, tca::TjStuff::NumPlanes, tca::TjStuff::showers, and tca::ShowerStruct3D::TPCID.

Referenced by tca::MCParticleListUtils::MakeCheatShower(), and Match2DShowers().

4554  {
4555  // create a 3D shower and size the vectors that are indexed by plane
4556 
4557  ShowerStruct3D ss3;
4558  ss3.TPCID = tpcid;
4559  ss3.ID = tjs.showers.size() + 1;
4560  ss3.Energy.resize(tjs.NumPlanes);
4561  ss3.EnergyErr.resize(tjs.NumPlanes);
4562  ss3.MIPEnergy.resize(tjs.NumPlanes);
4563  ss3.MIPEnergyErr.resize(tjs.NumPlanes);
4564  ss3.dEdx.resize(tjs.NumPlanes);
4565  ss3.dEdxErr.resize(tjs.NumPlanes);
4566 
4567  return ss3;
4568 
4569  } // CreateSS3
float tca::DeadWireCount ( const TjStuff tjs,
const TrajPoint tp1,
const TrajPoint tp2 
)

Definition at line 1756 of file Utils.cxx.

References tca::TrajPoint::CTP, DeadWireCount(), and tca::TrajPoint::Pos.

Referenced by tca::TrajClusterAlg::AddHits(), cluster::ClusterCrawlerAlg::CheckClusterHitFrac(), cluster::ClusterCrawlerAlg::ChkMerge(), CompleteIncomplete3DVerticesInGaps(), Find2DVertices(), tca::TrajClusterAlg::StepCrawl(), and tca::TrajClusterAlg::UpdateTraj().

1757  {
1758  return DeadWireCount(tjs, tp1.Pos[0], tp2.Pos[0], tp1.CTP);
1759  } // DeadWireCount
float DeadWireCount(const TjStuff &tjs, const float &inWirePos1, const float &inWirePos2, CTP_t tCTP)
Definition: Utils.cxx:1762
float tca::DeadWireCount ( const TjStuff tjs,
const float &  inWirePos1,
const float &  inWirePos2,
CTP_t  tCTP 
)

Definition at line 1762 of file Utils.cxx.

References DecodeCTP(), tca::TjStuff::NumWires, geo::PlaneID::Plane, tmp, and tca::TjStuff::WireHitRange.

Referenced by DeadWireCount(), NumPtsWithCharge(), and TrajTrajDOCA().

1763  {
1764  if(inWirePos1 < -0.4 || inWirePos2 < -0.4) return 0;
1765  unsigned int inWire1 = std::nearbyint(inWirePos1);
1766  unsigned int inWire2 = std::nearbyint(inWirePos2);
1767  geo::PlaneID planeID = DecodeCTP(tCTP);
1768  unsigned short plane = planeID.Plane;
1769  if(inWire1 > tjs.NumWires[plane] || inWire2 > tjs.NumWires[plane]) return 0;
1770  if(inWire1 > inWire2) {
1771  // put in increasing order
1772  unsigned int tmp = inWire1;
1773  inWire1 = inWire2;
1774  inWire2 = tmp;
1775  } // inWire1 > inWire2
1776  ++inWire2;
1777  unsigned int wire, ndead = 0;
1778  for(wire = inWire1; wire < inWire2; ++wire) if(tjs.WireHitRange[plane][wire].first == -1) ++ndead;
1779  return ndead;
1780  } // DeadWireCount
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
Float_t tmp
Definition: plot.C:37
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
geo::PlaneID tca::DecodeCTP ( CTP_t  CTP)

Definition at line 89 of file DataStructs.cxx.

References Cpad, and Tpad.

Referenced by tca::TrajClusterAlg::AddHits(), tca::TrajClusterAlg::AddLAHits(), AddLooseHits(), AttachPFPToVertex(), ChgFracNearPos(), tca::TrajClusterAlg::ChkStopEndPts(), ChkVtxAssociations(), CompleteIncompleteShower(), DeadWireCount(), DefineDontCluster(), tca::TrajClusterAlg::DefineHit(), DefinePFP(), DefineTjParents(), EncodeCTP(), tca::TrajClusterAlg::EndMerge(), ExpectedHitsRMS(), FilldEdx(), FillmAllTraj(), Find2DVertices(), Find3DVertices(), FindCloseHits(), FindCloseTjs(), FindCompleteness(), tca::TrajClusterAlg::FindJunkTraj(), FindMissedTjsInTp3s(), FindShowers3D(), tca::TrajClusterAlg::FindVtxTraj(), FindXMatches(), Finish3DShowers(), FitTp3(), FitTp3s(), cluster::ClusterCrawlerAlg::FitVtx(), FollowTp3s(), cluster::ClusterCrawlerAlg::GetHitRange(), KillPoorVertices(), MakeBareTP(), MakeJunkVertices(), MakeTp3(), MakeVertexObsolete(), Match2DShowers(), Match3DFOM(), tca::TruthMatcher::MatchAndSum(), tca::TruthMatcher::MatchTruth(), MaxChargeAsymmetry(), tca::MCParticleListUtils::MCParticleStartTjID(), MergePFPTjs(), PrintAllTraj(), cluster::TrajCluster::produce(), tca::TruthMatcher::PutMCPHitsInVector(), Reconcile3D(), tca::TrajClusterAlg::ReconstructAllTraj(), tca::TrajClusterAlg::ReversePropagate(), SaveTjInfo(), SaveTjInfoStuff(), ScoreVertices(), SignalAtTp(), Split3DKink(), SplitTraj(), SplitTrajCrossingVertices(), tca::TrajClusterAlg::StartTraj(), tca::TrajClusterAlg::StepCrawl(), TrimEndPts(), UpdateMatchStructs(), UpdateShower(), UpdateTp3s(), VtxHitsSwap(), cluster::ClusterCrawlerAlg::VtxMatch(), and WireHitRangeOK().

89  {
90  auto const cryo = (CTP / Cpad);
91  return geo::PlaneID(
92  /* Cryostat */ cryo,
93  /* TPC */ (CTP - cryo * Cpad) / Tpad,
94  /* Plane */ (CTP % 10)
95  );
96  }
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
constexpr unsigned int Tpad
Definition: DataStructs.h:42
constexpr unsigned int Cpad
Definition: DataStructs.h:43
void tca::DefineDontCluster ( TjStuff tjs,
const geo::TPCID tpcid,
bool  prt 
)

Definition at line 3397 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::TjStuff::DebugMode, DecodeCTP(), tca::TjStuff::dontCluster, DotProd(), GetAssns(), IsShowerLike(), PFPDOCA(), tca::TjStuff::pfps, geo::PlaneID::Plane, PointDirection(), PosSep(), t1, t2, tca::DontClusterStruct::TjIDs, tca::TjStuff::vtx3, tca::DontClusterStruct::Vx2ID, and tca::DontClusterStruct::Vx3ID.

Referenced by FindShowers3D().

3398  {
3399  // make a list of tj pairs that pass the cuts, but shouldn't be clustered for
3400  // different reasons, e.g. are likely parent tjs in different showers, are both attached
3401  // to the same high-score vertex, etc
3402 
3403  tjs.dontCluster.clear();
3404 
3405  DontClusterStruct dc;
3406  for(auto& vx3 : tjs.vtx3) {
3407  if(vx3.ID == 0) continue;
3408  if(vx3.TPCID != tpcid) continue;
3409  if(!vx3.Neutrino) continue;
3410  auto PIn3V = GetAssns(tjs, "3V", vx3.ID, "P");
3411  if(PIn3V.size() < 2) continue;
3412  Point3_t v3pos = {{vx3.X, vx3.Y, vx3.Z}};
3413  for(unsigned short ip1 = 0; ip1 < PIn3V.size() - 1; ++ip1) {
3414  auto& p1 = tjs.pfps[PIn3V[ip1] - 1];
3415  // ignore the neutrino pfp
3416  if(p1.TjIDs.empty()) continue;
3417  unsigned short p1End = 0;
3418  if(p1.Vx3ID[1] == vx3.ID) p1End = 1;
3419  bool p1ShowerLike = IsShowerLike(tjs, p1.TjIDs);
3420  // find the direction using the vertex position and the end that is
3421  // farthest away from the vertex
3422  auto p1Dir = PointDirection(v3pos, p1.XYZ[1 - p1End]);
3423  float p1Sep = PosSep(p1.XYZ[p1End], v3pos);
3424  for(unsigned short ip2 = ip1 + 1; ip2 < PIn3V.size(); ++ip2) {
3425  auto& p2 = tjs.pfps[PIn3V[ip2] - 1];
3426  if(p2.TjIDs.empty()) continue;
3427  unsigned short p2End = 0;
3428  if(p2.Vx3ID[1] == vx3.ID) p2End = 1;
3429  auto p2Dir = PointDirection(v3pos, p2.XYZ[1 - p2End]);
3430  float p2Sep = PosSep(p2.XYZ[p2End], v3pos);
3431  // Look for the case where an electron starts to shower close to the
3432  // vertex, creating a daughter that is also attached to the vertex. This
3433  // pair is OK to include in a shower. The signature is that the PFP doca between them is less
3434  // than the pfp - vx3 separation and both are shower like - something like this
3435  // where 3V is a 3D vertex
3436  // \ P3 (not shower-like) -> 3V
3437  // 3V ----------- P1 -> 3V (shower-like or NOT shower-like)
3438  // ----------- P2 (shower-like doca closer to P1 than the vertex) -> 3V
3439  // The tjs in the P1 - P3 pair shouldn't be clustered
3440  // The tjs in the P2 - P3 pair shouldn't be clustered
3441  // The tjs in the P1 - P2 pair can be clustered
3442  bool p2ShowerLike = IsShowerLike(tjs, p2.TjIDs);
3443  if(p1ShowerLike && p2ShowerLike) continue;
3444 
3445  float costh = DotProd(p1Dir, p2Dir);
3446  if(costh < 0.92) continue;
3447  unsigned short closePt1, closePt2;
3448  float doca = PFPDOCA(p1, p2, closePt1, closePt2);
3449  float minSep = p1Sep;
3450  if(p1Sep < minSep) minSep = p2Sep;
3451  bool allowCluster = (doca < minSep);
3452 
3453  if(tjs.DebugMode) {
3454  std::cout<<"DDC: P"<<p1.ID<<" p1ShowerLike "<<p1ShowerLike;
3455  std::cout<<" P"<<p2.ID<<" p2ShowerLike "<<p2ShowerLike;
3456  std::cout<<" costh "<<costh;
3457  std::cout<<" doca "<<doca;
3458  std::cout<<" minSep "<<minSep;
3459  std::cout<<" allowCluster? "<<allowCluster;
3460  std::cout<<"\n";
3461  }
3462  if(!allowCluster) continue;
3463 
3464  // now enter the Tj pairs
3465  for(auto tid1 : p1.TjIDs) {
3466  auto& t1 = tjs.allTraj[tid1 - 1];
3467  for(auto tid2 : p2.TjIDs) {
3468  auto& t2 = tjs.allTraj[tid2 - 1];
3469  if(t1.CTP != t2.CTP) continue;
3470  dc.TjIDs[0] = tid1;
3471  dc.TjIDs[1] = tid2;
3472  if(dc.TjIDs[0] > dc.TjIDs[1]) std::swap(dc.TjIDs[0], dc.TjIDs[1]);
3473  dc.Vx2ID = vx3.Vx2ID[DecodeCTP(t1.CTP).Plane];
3474  dc.Vx3ID = vx3.ID;
3475  tjs.dontCluster.push_back(dc);
3476  } // tid2
3477  } // tid1
3478  } // ip2
3479  } // ip1
3480  } // vx3
3481 
3482  } // DefineDontCluster
TTree * t1
Definition: plottest35.C:26
std::array< double, 3 > Point3_t
Definition: DataStructs.h:35
float PFPDOCA(const PFPStruct &pfp1, const PFPStruct &pfp2, unsigned short &close1, unsigned short &close2)
Definition: PFPUtils.cxx:1761
bool IsShowerLike(const TjStuff &tjs, const std::vector< int > TjIDs)
Definition: TCShower.cxx:2071
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:1614
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
TTree * t2
Definition: plottest35.C:36
void swap(art::HLTGlobalStatus &lhs, art::HLTGlobalStatus &rhs)
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:60
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
std::vector< int > GetAssns(const TjStuff &tjs, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4079
void tca::DefineEnvelope ( std::string  inFcnLabel,
TjStuff tjs,
ShowerStruct ss,
bool  prt 
)

Definition at line 3936 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::TrajPoint::Ang, tca::TrajPoint::Chg, tca::ShowerStruct::ChgDensity, tca::TrajPoint::DeltaRMS, tca::ShowerStruct::Envelope, tca::ShowerStruct::EnvelopeArea, tca::ShowerStruct::ID, SortEntry::length, tca::ShowerStruct::NeedsUpdate, tca::TrajPoint::Pos, PosSep(), tca::Trajectory::Pts, tca::TjStuff::ShowerTag, tca::ShowerStruct::ShowerTjID, tca::ShowerStruct::TjIDs, and tca::TjStuff::UnitsPerTick.

Referenced by ReverseShower(), and UpdateShower().

3937  {
3938 
3939  if(ss.ID == 0) return;
3940  if(ss.TjIDs.empty()) return;
3941  Trajectory& stj = tjs.allTraj[ss.ShowerTjID - 1];
3942  // shower Tj isn't fully defined yet
3943  if(stj.Pts[0].Pos[0] == 0) return;
3944 
3945  std::string fcnLabel = inFcnLabel + ".DE";
3946 
3947  ss.Envelope.resize(4);
3948  TrajPoint& stp0 = stj.Pts[0];
3949  TrajPoint& stp1 = stj.Pts[1];
3950  TrajPoint& stp2 = stj.Pts[2];
3951 
3952  // construct the Envelope polygon. Start with a rectangle using the fixed 1/2 width fcl input
3953  // expanded by the rms width at each end to create a polygon. The polygon is constructed along
3954  // the Pos[0] direction and then rotated into the ShowerTj direction. Use sTp1 as the origin.
3955  // First vertex
3956  ss.Envelope[0][0] = -PosSep(stp0.Pos, stp1.Pos);
3957  ss.Envelope[0][1] = tjs.ShowerTag[5] + tjs.ShowerTag[4] * stp0.DeltaRMS;
3958  // second vertex
3959  ss.Envelope[1][0] = PosSep(stp1.Pos, stp2.Pos);
3960  ss.Envelope[1][1] = tjs.ShowerTag[5] + tjs.ShowerTag[4] * stp2.DeltaRMS;
3961  // third and fourth are reflections of the first and second
3962  ss.Envelope[2][0] = ss.Envelope[1][0];
3963  ss.Envelope[2][1] = -ss.Envelope[1][1];
3964  ss.Envelope[3][0] = ss.Envelope[0][0];
3965  ss.Envelope[3][1] = -ss.Envelope[0][1];
3966 
3967  float length = ss.Envelope[1][0] - ss.Envelope[0][0];
3968  float width = ss.Envelope[0][1] + ss.Envelope[1][1];
3969  ss.EnvelopeArea = length * width;
3970 
3971  // Rotate into the stp1 coordinate system
3972  float cs = cos(stp1.Ang);
3973  float sn = sin(stp1.Ang);
3974  for(auto& vtx : ss.Envelope) {
3975  // Rotate along the stj shower axis
3976  float pos0 = cs * vtx[0] - sn * vtx[1];
3977  float pos1 = sn * vtx[0] + cs * vtx[1];
3978  // translate
3979  vtx[0] = pos0 + stp1.Pos[0];
3980  vtx[1] = pos1 + stp1.Pos[1];
3981  } // vtx
3982  // Find the charge density inside the envelope
3983  ss.ChgDensity = (stp0.Chg + stp1.Chg + stp2.Chg) / ss.EnvelopeArea;
3984  if(prt) {
3985  mf::LogVerbatim myprt("TC");
3986  myprt<<fcnLabel<<" 2S"<<ss.ID<<" Envelope";
3987  for(auto& vtx : ss.Envelope) myprt<<" "<<(int)vtx[0]<<":"<<(int)(vtx[1]/tjs.UnitsPerTick);
3988  myprt<<" Area "<<(int)ss.EnvelopeArea;
3989  myprt<<" ChgDensity "<<ss.ChgDensity;
3990  }
3991  // This is the last function used to update a shower
3992  ss.NeedsUpdate = false;
3993  } // DefineEnvelope
Float_t ss
Definition: plot.C:23
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
bool tca::DefinePFP ( std::string  inFcnLabel,
TjStuff tjs,
PFPStruct pfp,
bool  prt 
)

Definition at line 2159 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, CompatibleMerge(), DecodeCTP(), FindCompleteness(), FollowTp3s(), tca::PFPStruct::ID, kKilled, kMat3D, kMat3DMerge, tca::TjStuff::Match3DCuts, tca::TjStuff::matchVec, tca::PFPStruct::MatchVecIndex, MaxTjLen(), MCSMom(), MergePFPTjs(), tca::PFPStruct::NeedsUpdate, tca::TjStuff::NumPlanes, tca::PFPStruct::PDGCode, PFPVxTjOK(), geo::PlaneID::Plane, PosSep(), SetIntersection(), SetStart(), SharesHighScoreVx(), tca::PFPStruct::TjIDs, tca::PFPStruct::Tp3s, tca::TjStuff::UseAlg, and tca::PFPStruct::Vx3ID.

Referenced by AnalyzePFP(), DotProd(), FindPFParticles(), and Match3DVtxTjs().

2160  {
2161  // This function is called after the 3D matched TjIDs have been specified and optionally
2162  // a start or end vertex ID. It defines the PFParticle but doesn't store it
2163 
2164  if(pfp.PDGCode == 1111) return false;
2165  if(pfp.TjIDs.size() < 2) return false;
2166 
2167  std::string fcnLabel = inFcnLabel + ".DPFP";
2168 
2169  // require at least one tj in at least two planes
2170  std::vector<unsigned short> nInPln(tjs.NumPlanes);
2171  for(auto tjid : pfp.TjIDs) {
2172  auto& tj = tjs.allTraj[tjid - 1];
2173  ++nInPln[DecodeCTP(tj.CTP).Plane];
2174  if(tj.AlgMod[kMat3D] || tj.AlgMod[kKilled]) {
2175  std::cout<<fcnLabel<<" P"<<pfp.ID<<" uses T"<<tj.ID<<" but kMat3D is set true\n";
2176  return false;
2177  }
2178  } // tjid
2179  unsigned short npl = 0;
2180  for(unsigned short plane = 0; plane < tjs.NumPlanes; ++plane) if(nInPln[plane] > 0) ++npl;
2181  if(npl < 2) return false;
2182 
2183  if(pfp.Vx3ID[0] == 0 && pfp.Vx3ID[1] > 0) {
2184  std::cout<<fcnLabel<<" P"<<pfp.ID<<" end 1 has a vertex but end 0 doesn't. No endpoints defined\n";
2185  return false;
2186  }
2187 
2188  // check for vertex consistency. There should only be one tj in each plane
2189  // that is attached to a vertex. Remove the shorter tj from the list
2190  // if that is not the case
2191  if(pfp.Vx3ID[0] > 0) PFPVxTjOK(tjs, pfp, prt);
2192 
2193  bool pfpTrackLike = (MaxTjLen(tjs, pfp.TjIDs) > tjs.Match3DCuts[5] && MCSMom(tjs, pfp.TjIDs) > tjs.Match3DCuts[3]);
2194 
2195  if(prt) {
2196  mf::LogVerbatim myprt("TC");
2197  myprt<<fcnLabel<<" pfp P"<<pfp.ID;
2198  myprt<<" Vx3ID 3V"<<pfp.Vx3ID[0]<<" 3V"<<pfp.Vx3ID[1];
2199  myprt<<" Tjs";
2200  for(auto id : pfp.TjIDs) myprt<<" T"<<id;
2201  myprt<<" matchVec index "<<pfp.MatchVecIndex;
2202  myprt<<" max Tj len "<<MaxTjLen(tjs, pfp.TjIDs);
2203  myprt<<" MCSMom "<<MCSMom(tjs, pfp.TjIDs);
2204  myprt<<" pfpTrackLike? "<<pfpTrackLike;
2205  } // prt
2206 
2207  if(tjs.UseAlg[kMat3DMerge] && pfpTrackLike && pfp.MatchVecIndex < tjs.matchVec.size()) {
2208  // The index of tjs.matchVec has been specified for this pfp so we can look for evidence of
2209  // broken Tjs starting at the beginning
2210  for(unsigned short ims = 0; ims < pfp.MatchVecIndex + 10; ++ims) {
2211  if(ims >= tjs.matchVec.size()) break;
2212  auto& ms = tjs.matchVec[ims];
2213  if(ms.Count == 0) continue;
2214  std::vector<int> shared = SetIntersection(ms.TjIDs, pfp.TjIDs);
2215  if(shared.size() < 2) continue;
2216  // check the max length Tj and cut on MCSMom
2217  if(MaxTjLen(tjs, ms.TjIDs) < tjs.Match3DCuts[5]) continue;
2218  if(MCSMom(tjs, ms.TjIDs) < tjs.Match3DCuts[3]) continue;
2219  for(auto tjid : ms.TjIDs) {
2220  if(std::find(shared.begin(), shared.end(), tjid) != shared.end()) continue;
2221  auto& tj = tjs.allTraj[tjid - 1];
2222  if(tj.AlgMod[kKilled]) continue;
2223  if(tj.AlgMod[kMat3D]) continue;
2224  // check for PDGCode compatibility - muons and delta rays
2225  if(pfp.PDGCode == 13 && tj.PDGCode == 11) continue;
2226  if(pfp.PDGCode == 11 && tj.PDGCode == 13) continue;
2227  if(SharesHighScoreVx(tjs, pfp, tj)) continue;
2228  if(tj.MCSMom < tjs.Match3DCuts[3]) continue;
2229  float len = PosSep(tj.Pts[tj.EndPt[0]].Pos, tj.Pts[tj.EndPt[1]].Pos);
2230  if(len < tjs.Match3DCuts[5]) continue;
2231  // check for a compatible merge
2232  bool skipit = false;
2233  for(auto tjid : pfp.TjIDs) {
2234  auto& ptj = tjs.allTraj[tjid - 1];
2235  if(ptj.CTP != tj.CTP) continue;
2236  if(!CompatibleMerge(tjs, tj, ptj, prt)) {
2237  skipit = true;
2238  break;
2239  }
2240  } // tjid
2241  if(skipit) continue;
2242  if(prt) mf::LogVerbatim("TC")<<" add T"<<tjid<<" MCSMom "<<tj.MCSMom<<" length "<<len;
2243  pfp.TjIDs.push_back(tjid);
2244  PFPVxTjOK(tjs, pfp, prt);
2245  } // tjid
2246  } // ims
2247  } // matchVec index defined
2248 
2249 /* BB April 25. CheckAndMerge needs work. Shut it off for now.
2250  // check the completeness of matching points in this set of Tjs and possibly
2251  // merge Tjs
2252  if(tjs.UseAlg[kMat3DMerge] && pfpTrackLike) {
2253  if(!CheckAndMerge(tjs, pfp, prt)) return false;
2254  } else {
2255  // not track-like. Find completeness and fill the TP3s
2256  FindCompleteness(tjs, pfp, true, true, prt);
2257  }
2258 */
2259  // Find completeness and fill the TP3s
2260  FindCompleteness(tjs, pfp, true, true, prt);
2261  if(pfp.Tp3s.empty()) return false;
2262 
2263  // Set the starting position in 3D if it isn't already defined by a 3D vertex
2264  SetStart(tjs, pfp, prt);
2265  FollowTp3s(tjs, pfp, prt);
2266  // Check the list of Tjs and merge those that are in the same plane
2267  MergePFPTjs(tjs, pfp, prt);
2268 
2269  if(prt) {
2270  mf::LogVerbatim myprt("TC");
2271  myprt<<fcnLabel<<" pfp P"<<pfp.ID;
2272  myprt<<" Vx3ID 3V"<<pfp.Vx3ID[0]<<" 3V"<<pfp.Vx3ID[1];
2273  myprt<<" Tjs";
2274  for(auto id : pfp.TjIDs) myprt<<" T"<<id;
2275  myprt<<" Tp3s size "<<pfp.Tp3s.size();
2276  }
2277 
2278  pfp.NeedsUpdate = false;
2279  return true;
2280  } // DefinePFP
bool SetStart(TjStuff &tjs, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:207
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void FollowTp3s(TjStuff &tjs, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:261
bool SharesHighScoreVx(TjStuff &tjs, const PFPStruct &pfp, const Trajectory &tj)
Definition: PFPUtils.cxx:883
bool CompatibleMerge(TjStuff &tjs, std::vector< int > &tjIDs, bool prt)
Definition: Utils.cxx:455
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:214
float MaxTjLen(TjStuff const &tjs, std::vector< int > &tjIDs)
Definition: Utils.cxx:2189
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
bool PFPVxTjOK(TjStuff &tjs, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:2283
short MCSMom(const TjStuff &tjs, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2837
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
void FindCompleteness(TjStuff &tjs, PFPStruct &pfp, bool doFit, bool fillTp3s, bool prt)
Definition: PFPUtils.cxx:593
bool MergePFPTjs(TjStuff &tjs, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:1174
void tca::DefinePFPParents ( TjStuff tjs,
const geo::TPCID tpcid,
bool  prt 
)

Definition at line 2441 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, tca::TjStuff::DebugMode, DefinePFPParentsTestBeam(), GetPFPIndex(), IsShowerLike(), tca::TjStuff::NumPlanes, PDGCodeVote(), tca::TjStuff::pfps, tca::TjStuff::TestBeam, and tca::TjStuff::vtx.

Referenced by DotProd(), and tca::TrajClusterAlg::RunTrajClusterAlg().

2442  {
2443  /*
2444  This function reconciles vertices, PFParticles and Tjs, then
2445  defines the parent (j) - daughter (i) relationship and PDGCode. Here is a
2446  description of the conventions:
2447 
2448  V1 is the highest score 3D vertex in this tpcid so a neutrino PFParticle P1 is defined.
2449  V4 is a high-score vertex that has lower score than V1. It is declared to be a
2450  primary vertex because its score is higher than V5 and it is not associated with the
2451  neutrino interaction
2452  V6 was created to adhere to the convention that all PFParticles, in this case P9,
2453  be associated with a start vertex. There is no score for V6. P9 is it's own parent
2454  but is not a primary PFParticle.
2455 
2456  P1 - V1 - P2 - V2 - P4 - V3 - P5 V4 - P6 V6 - P9
2457  \ \
2458  P3 P7 - V5 - P8
2459 
2460  The PrimaryID in this table is the ID of the PFParticle that is attached to the
2461  primary vertex, which may or may not be a neutrino interaction vertex.
2462  The PrimaryID is returned by the PrimaryID function
2463  PFP parentID DtrIDs PrimaryID
2464  -----------------------------------
2465  P1 P1 P2, P3 P1
2466  P2 P1 P4 P2
2467  P3 P1 none P3
2468  P4 P2 P5 P2
2469  P5 P4 none P2
2470 
2471  P6 P6 none P6
2472  P7 P7 P8 P7
2473 
2474  P9 P9 none 0
2475 
2476  */
2477  if(tjs.pfps.empty()) return;
2478  int neutrinoPFPID = 0;
2479  for(auto& pfp : tjs.pfps) {
2480  if(pfp.ID == 0) continue;
2481  if(pfp.TPCID != tpcid) continue;
2482  if(!tjs.TestBeam && neutrinoPFPID == 0 && (pfp.PDGCode == 12 || pfp.PDGCode == 14)) {
2483  neutrinoPFPID = pfp.ID;
2484  break;
2485  }
2486  } // pfp
2487 
2488  // define the end vertex if the Tjs have end vertices
2489  constexpr unsigned short end1 = 1;
2490  for(auto& pfp : tjs.pfps) {
2491  if(pfp.ID == 0) continue;
2492  if(pfp.TPCID != tpcid) continue;
2493  // already done?
2494  if(pfp.Vx3ID[end1] > 0) continue;
2495  // ignore shower-like pfps
2496  if(IsShowerLike(tjs, pfp.TjIDs)) continue;
2497  // count 2D -> 3D matched vertices
2498  unsigned short cnt3 = 0;
2499  unsigned short vx3id = 0;
2500  // list of unmatched 2D vertices that should be merged
2501  std::vector<int> vx2ids;
2502  for(auto tjid : pfp.TjIDs) {
2503  auto& tj = tjs.allTraj[tjid - 1];
2504  if(tj.VtxID[end1] == 0) continue;
2505  auto& vx2 = tjs.vtx[tj.VtxID[end1] - 1];
2506  if(vx2.Vx3ID == 0) {
2507  if(vx2.Topo == 1 && vx2.NTraj == 2) vx2ids.push_back(vx2.ID);
2508  continue;
2509  }
2510  if(vx3id == 0) vx3id = vx2.Vx3ID;
2511  if(vx2.Vx3ID == vx3id) ++cnt3;
2512  } // tjid
2513  if(cnt3 > 1) {
2514  // ensure it isn't attached at the other end
2515  if(pfp.Vx3ID[1 - end1] == vx3id) continue;
2516  pfp.Vx3ID[end1] = vx3id;
2517  if(cnt3 != tjs.NumPlanes && tjs.DebugMode) {
2518  std::cout<<"DPFPR: Missed an end vertex for PFP "<<pfp.ID<<" Write some code\n";
2519  }
2520  } // cnt3 > 1
2521  } // pfp
2522 
2523  // Assign a PDGCode to each PFParticle and look for a parent
2524  for(auto& pfp : tjs.pfps) {
2525  if(pfp.ID == 0) continue;
2526  if(pfp.TPCID != tpcid) continue;
2527  // skip a neutrino PFParticle
2528  if(pfp.PDGCode == 12 || pfp.PDGCode == 14 || pfp.PDGCode == 22) continue;
2529  pfp.PDGCode = PDGCodeVote(tjs, pfp.TjIDs, prt);
2530  // next look for a parent
2531  int pfpParentID = INT_MAX;
2532  unsigned short nParent = 0;
2533  for(auto tjid : pfp.TjIDs) {
2534  auto& tj = tjs.allTraj[tjid - 1];
2535  if(tj.ParentID == 0) continue;
2536  unsigned short ppindex = GetPFPIndex(tjs, tj.ParentID);
2537  if(ppindex == USHRT_MAX) continue;
2538  int ppid = ppindex + 1;
2539  if(pfpParentID == INT_MAX) pfpParentID = ppid;
2540  if(ppid == pfpParentID) ++nParent;
2541  } // ii
2542  // look for a parent
2543  if(nParent > 1) {
2544  pfp.ParentID = (size_t)pfpParentID;
2545  auto& parpfp = tjs.pfps[pfpParentID - 1];
2546  parpfp.DtrIDs.push_back(pfp.ID);
2547  } // nParent > 1
2548  } // ipfp
2549 
2550 
2551  if(tjs.TestBeam) {
2552  DefinePFPParentsTestBeam(tjs, tpcid, prt);
2553  return;
2554  }
2555 
2556  // associate primary PFParticles with a neutrino PFParticle
2557  if(neutrinoPFPID > 0) {
2558  auto& neutrinoPFP = tjs.pfps[neutrinoPFPID - 1];
2559  int vx3id = neutrinoPFP.Vx3ID[1];
2560  for(auto& pfp : tjs.pfps) {
2561  if(pfp.ID == 0 || pfp.ID == neutrinoPFPID) continue;
2562  if(pfp.TPCID != tpcid) continue;
2563  if(pfp.Vx3ID[0] != vx3id) continue;
2564  pfp.ParentID = (size_t)neutrinoPFPID;
2565  pfp.Primary = true;
2566  neutrinoPFP.DtrIDs.push_back(pfp.ID);
2567  } // pfp
2568  } // neutrino PFP exists
2569  } // DefinePFPParents
bool IsShowerLike(const TjStuff &tjs, const std::vector< int > TjIDs)
Definition: TCShower.cxx:2071
int PDGCodeVote(TjStuff &tjs, std::vector< int > &tjIDs, bool prt)
Definition: Utils.cxx:267
void DefinePFPParentsTestBeam(TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
Definition: PFPUtils.cxx:2572
unsigned short GetPFPIndex(const TjStuff &tjs, int tjID)
Definition: Utils.cxx:1045
void tca::DefinePFPParentsTestBeam ( TjStuff tjs,
const geo::TPCID tpcid,
bool  prt 
)

Definition at line 2572 of file PFPUtils.cxx.

References GetPFPIndex(), GetVtxTjIDs(), tca::TjStuff::pfps, SetDifference(), tca::TjStuff::vtx3, and tca::TjStuff::ZLo.

Referenced by DefinePFPParents(), and DotProd().

2573  {
2574  // analog of the one above that was written for neutrino interactions. This differs in that
2575  // the Tj parent - daughter relationship isn't known yet. If one exists, it is ignored...
2576  // The assumption here is that all PFParticles that enter (end0) from upstream Z are parents and
2577  // any PFParticles attached to them at end1 are daughters.
2578 
2579  // create a list (stack) of parent ID <-> daughter IDs. The idea is similar to that
2580  // used in DefineTjParents. A parent-daughter association is made for each entry. After
2581  // it is made, 1) that entry is removed from the stack, 2) the daughter is checked to see
2582  // if it a parent of a grand-daughter and if so that pair is added to the stack.
2583  std::vector<std::pair<unsigned short, unsigned short>> pardtr;
2584 
2585  // Fill the stack with parents that enter the TPC and have daughters attached to
2586  // 3D vertices at the other end
2587  double fidZCut = tjs.ZLo + 2;
2588  for(auto& parPFP : tjs.pfps) {
2589  if(parPFP.ID == 0) continue;
2590  parPFP.Primary = false;
2591  if(parPFP.XYZ[0][2] > fidZCut) continue;
2592  parPFP.Primary = true;
2593  // we found a pfp that entered the TPC. Call it the parent and look for a daughter
2594  if(prt) mf::LogVerbatim("TC")<<"DPFPTestBeam: parent "<<parPFP.ID<<" end1 vtx "<<parPFP.Vx3ID[1];
2595  if(parPFP.Vx3ID[1] == 0) continue;
2596  // There must be other Tjs attached to this vertex which are the daughters. Find them
2597  // and add them to the pardtr stack
2598  float score = 0;
2599  auto& vx3 = tjs.vtx3[parPFP.Vx3ID[1] - 1];
2600  // ensure that it is valid
2601  if(vx3.ID == 0) continue;
2602  // get a list of Tjs attached to this vertex. This will include the Tjs in the parent.
2603  auto vx3TjList = GetVtxTjIDs(tjs, vx3, score);
2604  if(vx3TjList.empty()) continue;
2605  // filter out the parent Tjs
2606  auto dtrTjlist = SetDifference(vx3TjList, parPFP.TjIDs);
2607  if(prt) {
2608  mf::LogVerbatim myprt("TC");
2609  myprt<<" Dtrs:";
2610  for(auto dtjID : dtrTjlist) myprt<<" "<<dtjID<<"_"<<GetPFPIndex(tjs, dtjID);
2611  }
2612  // Add to the stack
2613  for(auto dtjID : dtrTjlist) {
2614  unsigned short pfpIndex = GetPFPIndex(tjs, dtjID);
2615  if(pfpIndex > tjs.pfps.size() - 1) continue;
2616  unsigned short dtrID = pfpIndex + 1;
2617  // See if this is a duplicate
2618  bool duplicate = false;
2619  for(auto& pd : pardtr) if(parPFP.ID == pd.first && dtrID == pd.second) duplicate = true;
2620  if(!duplicate) pardtr.push_back(std::make_pair(parPFP.ID, dtrID));
2621  } // dtjID
2622  } // parPFP
2623 
2624  // iterate through the parent - daughter stack, removing the last pair when a
2625  // ParentID is updated and adding pairs for new daughters
2626  for(unsigned short nit = 0; nit < 100; ++nit) {
2627  if(pardtr.empty()) break;
2628  auto lastPair = pardtr[pardtr.size() - 1];
2629  auto& dtr = tjs.pfps[lastPair.second - 1];
2630  auto& par = tjs.pfps[lastPair.first - 1];
2631  dtr.ParentID = par.ID;
2632  par.DtrIDs.push_back(dtr.ID);
2633  // remove the last pair
2634  pardtr.pop_back();
2635  // Now see if the daughter is a parent. First check for a vertex at the other end.
2636  // To do that we need to know which end has the vertex between the parent and daughter
2637  unsigned short dtrEnd = USHRT_MAX;
2638  for(unsigned short ep = 0; ep < 2; ++ep) {
2639  if(par.Vx3ID[ep] == 0) continue;
2640  for(unsigned short ed = 0; ed < 2; ++ed) if(dtr.Vx3ID[ed] == par.Vx3ID[ep]) dtrEnd = ed;
2641  } // ep
2642  if(dtrEnd > 1) continue;
2643  // look at the other end of the daughter
2644  dtrEnd = 1 - dtrEnd;
2645  // check for a vertex
2646  if(dtr.Vx3ID[dtrEnd] == 0) continue;
2647  // get the list of Tjs attached to it
2648  auto& vx3 = tjs.vtx3[dtr.Vx3ID[dtrEnd] - 1];
2649  float score = 0;
2650  auto vx3TjList = GetVtxTjIDs(tjs, vx3, score);
2651  if(vx3TjList.empty()) continue;
2652  // filter out the new parent
2653  auto dtrTjlist = SetDifference(vx3TjList, dtr.TjIDs);
2654  // put these onto the stack
2655  for(auto tjid : dtrTjlist) pardtr.push_back(std::make_pair(dtr.ID, tjid));
2656  } // nit
2657  } // DefinePFPParentsTestBeam
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< int > GetVtxTjIDs(const TjStuff &tjs, const VtxStore &vx2)
Definition: TCVertex.cxx:3022
unsigned short GetPFPIndex(const TjStuff &tjs, int tjID)
Definition: Utils.cxx:1045
std::vector< T > SetDifference(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:236
void tca::DefineTjParents ( TjStuff tjs,
const geo::TPCID tpcid,
bool  prt 
)

Definition at line 17 of file Utils.cxx.

References tca::TjStuff::allTraj, CreatePFP(), geo::CryostatID::Cryostat, DecodeCTP(), evd::details::end(), GetVtxTjIDs(), SortEntry::index, kDeltaRay, kKilled, kSetDir, tca::TjStuff::Match3DCuts, ReverseTraj(), StorePFP(), tca::TjStuff::TestBeam, geo::TPCID::TPC, TrajTrajDOCA(), valDecreasing(), tca::TjStuff::Vertex2DCuts, tca::TjStuff::vtx, and tca::TjStuff::vtx3.

Referenced by tca::TrajClusterAlg::RunTrajClusterAlg().

18  {
19 /*
20  This function sets the ParentID of Tjs in this tpcid to create a hierarchy. The highest Score
21  3D vertex in a chain of Tjs and vertices is declared the primary vertex; vx3.Primary = true. Tjs directly attached
22  to that vertex are declared Primary trajectories with ParentID = 0. All other Tjs in the chain have ParentID
23  set to the next upstream Tj to which it is attached by a vertex. In the graphical description below, V1 and V4 are
24  2D vertices that are matched to a high-score 3D vertex. The V1 Score is greater than the V2 Score and V3 Score.
25  V1 and V4 are declared to be primary vertices. T1, T2, T6 and T7 are declared to be primary Tjs.
26 
27  V1 - T1 - V2 - T3 V4 - T6 / T8
28  \ \ /
29  T2 - V3 - T4 T7
30  \
31  T5
32 
33  This is represented as follows. The NeutrinoPrimaryTjID is defined by a function.
34  Tj ParentID NeutrinoPrimaryTjID
35  -----------------------------------
36  T1 0 T1
37  T2 0 T2
38  T3 T1 T2
39  T4 T2 T2
40  T5 T2 T2
41  T6 0 -1
42  T7 0 -1
43  T8 -1 -1
44 */
45 
46  // don't do anything if this is test beam data
47  if(tjs.TestBeam) return;
48 
49  // clear old information
50  for(auto& tj : tjs.allTraj) {
51  if(tj.AlgMod[kKilled]) continue;
52  if(DecodeCTP(tj.CTP).Cryostat != tpcid.Cryostat) continue;
53  if(DecodeCTP(tj.CTP).TPC != tpcid.TPC) continue;
54  // ignore delta rays
55  if(tj.AlgMod[kDeltaRay]) continue;
56  // ignore pion-like
57 // if(tj.PDGCode == 211) continue;
58  tj.ParentID = 0;
59  } // tj
60 
61  // sort vertice by decreasing score
62  std::vector<int> temp;
63  for(auto& vx3 : tjs.vtx3) {
64  if(vx3.ID == 0) continue;
65  if(vx3.TPCID != tpcid) continue;
66  // clear the Primary flag while we are here
67  vx3.Primary = false;
68  temp.push_back(vx3.ID);
69  } // vx3
70  if(temp.empty()) return;
71 
72  // Make a master list of all Tjs that are attached to these vertices
73  std::vector<int> masterlist;
74  for(auto vx3id : temp) {
75  auto& vx3 = tjs.vtx3[vx3id - 1];
76  float score;
77  auto tjlist = GetVtxTjIDs(tjs, vx3, score);
78  for(auto tjid : tjlist) {
79  // Temp? Check for an existing parentID
80  auto& tj = tjs.allTraj[tjid - 1];
81  if(tj.ParentID != 0) {
82 // std::cout<<"**** Tj "<<tj.ID<<" Existing parent "<<tj.ParentID<<" PDGCode "<<tj.PDGCode<<". with a vertex... \n";
83  tj.ParentID = 0;
84  }
85  if(std::find(masterlist.begin(), masterlist.end(), tjid) == masterlist.end()) masterlist.push_back(tjid);
86  } // tjid
87  } // vxid
88  if(prt) {
89  mf::LogVerbatim myprt("TC");
90  myprt<<"DTP: masterlist Tjs";
91  for(auto tjid : masterlist) myprt<<" "<<tjid;
92  }
93 
94  // Do the sort
95  std::vector<SortEntry> sortVec(temp.size());
96  for(unsigned short indx = 0; indx < temp.size(); ++indx) {
97  auto& vx3 = tjs.vtx3[temp[indx] - 1];
98  sortVec[indx].index = indx;
99  sortVec[indx].val = vx3.Score;
100  } // indx
101  if(sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(), valDecreasing);
102  // put them into order
103  auto vlist = temp;
104  for(unsigned short indx = 0; indx < temp.size(); ++indx) vlist[indx] = temp[sortVec[indx].index];
105 
106  // make a neutrino PFParticle to associate with the highest score vertex if it is high enough
107  if(tjs.Match3DCuts[0] > 0) {
108  auto& vx3 = tjs.vtx3[vlist[0] - 1];
109  if(vx3.Score > tjs.Vertex2DCuts[7]) {
110  auto neutrinoPFP = CreatePFP(tjs, tpcid);
111  // call it the neutrino vertex
112  vx3.Neutrino = true;
113  // put the vertex at the end of the neutrino
114  neutrinoPFP.XYZ[1][0] = vx3.X;
115  neutrinoPFP.XYZ[1][1] = vx3.Y;
116  neutrinoPFP.XYZ[1][2] = vx3.Z;
117  neutrinoPFP.XYZ[0] = neutrinoPFP.XYZ[1];
118  neutrinoPFP.Dir[1][2] = 1;
119  neutrinoPFP.Dir[0][2] = 1;
120  // This may be set to 12 later on if a primary shower is reconstructed
121  neutrinoPFP.PDGCode = 14;
122  neutrinoPFP.Vx3ID[1] = vx3.ID;
123  neutrinoPFP.Vx3ID[0] = vx3.ID;
124  neutrinoPFP.NeedsUpdate = false;
125  // the rest of this will be defined later
126  if(!StorePFP(tjs, neutrinoPFP)) return;
127  }
128  } // User wants to make PFParticles
129  // a temp vector to ensure that we only consider a vertex once
130  std::vector<bool> lookedAt3(tjs.vtx3.size() + 1, false);
131  std::vector<bool> lookedAt2(tjs.vtx.size() + 1, false);
132  // vector of parent-daughter pairs
133  std::vector<std::pair<int, int>> pardtr;
134  // Start with the highest score vertex
135  for(unsigned short indx = 0; indx < vlist.size(); ++indx) {
136  auto& vx3 = tjs.vtx3[vlist[indx] - 1];
137  if(lookedAt3[vx3.ID]) continue;
138  vx3.Primary = true;
139  lookedAt3[vx3.ID] = true;
140  // make a list of Tjs attached to this vertex
141  float score;
142  auto primTjList = GetVtxTjIDs(tjs, vx3, score);
143  if(primTjList.empty()) continue;
144  pardtr.clear();
145  for(auto primTjID : primTjList) {
146  auto& primTj = tjs.allTraj[primTjID - 1];
147  // This isn't a primary tj if the parent ID isn't -1
148  if(primTj.ParentID != -1) continue;
149  if(prt) mf::LogVerbatim("TC")<<"Vx3 "<<vx3.ID<<" Primary tj "<<primTj.ID;
150  // declare this a primary tj
151  primTj.ParentID = 0;
152  // look for daughter tjs = those that are attached to a 2D vertex
153  // at the other end
154  for(unsigned short end = 0; end < 2; ++end) {
155  if(primTj.VtxID[end] == 0) continue;
156  auto& vx2 = tjs.vtx[primTj.VtxID[end] - 1];
157  if(vx2.Vx3ID == vx3.ID) continue;
158  // found a 2D vertex. Check for daughters
159  auto dtrList = GetVtxTjIDs(tjs, vx2);
160  for(auto dtrID : dtrList) {
161  // ignore the primary tj
162  if(dtrID == primTjID) continue;
163  auto& dtj = tjs.allTraj[dtrID - 1];
164  if(dtj.ParentID != -1) {
165 // std::cout<<"DTP Error: dtr "<<dtrID<<" already has a parent "<<dtj.ParentID<<". Can't make it daughter of "<<primTjID<<"\n";
166  continue;
167  }
168  pardtr.push_back(std::make_pair(primTjID, dtrID));
169  if(prt) mf::LogVerbatim("TC")<<" primTj "<<primTjID<<" dtrID "<<dtrID;
170  } // tjid
171  } // end
172  // Ensure that end 0 of the trajectory is attached to the primary vertex
173  for(unsigned short end = 0; end < 2; ++end) {
174  if(primTj.VtxID[end] == 0) continue;
175  auto& vx2 = tjs.vtx[primTj.VtxID[end] - 1];
176  if(vx2.Vx3ID == vx3.ID && end != 0) ReverseTraj(tjs, primTj);
177  } // end
178  } // tjid
179  if(pardtr.empty()) continue;
180  if(prt) {
181  mf::LogVerbatim myprt("TC");
182  myprt<<" par_dtr";
183  for(auto pdtr : pardtr) myprt<<" "<<pdtr.first<<"_"<<pdtr.second;
184  }
185  // iterate through the parent - daughter stack, removing the last pair when a
186  // ParentID is updated and adding pairs for new daughters
187  for(unsigned short nit = 0; nit < 100; ++nit) {
188  auto lastPair = pardtr[pardtr.size() - 1];
189  auto& dtj = tjs.allTraj[lastPair.second - 1];
190  dtj.ParentID = lastPair.first;
191  // reverse the daughter trajectory if necessary so that end 0 is closest to the parent
192  float doca = 100;
193  unsigned short dpt = 0, ppt = 0;
194  auto& ptj = tjs.allTraj[lastPair.first - 1];
195  // find the point on the daughter tj that is closest to the parent
196  TrajTrajDOCA(tjs, dtj, ptj, dpt, ppt, doca);
197  // reverse the daughter if the closest point is near end 1 of the daughter
198  unsigned short midPt = (dtj.EndPt[0] + dtj.EndPt[1]) / 2;
199  if(dpt > midPt && !dtj.AlgMod[kSetDir]) ReverseTraj(tjs, dtj);
200  if(prt) mf::LogVerbatim("TC")<<"Set parent "<<ptj.ID<<" dtr "<<dtj.ID;
201  // remove that entry
202  pardtr.pop_back();
203  // Add entries for new daughters
204  for(unsigned short end = 0; end < 2; ++end) {
205  if(dtj.VtxID[end] == 0) continue;
206  auto& vx2 = tjs.vtx[dtj.VtxID[end] - 1];
207  if(lookedAt2[vx2.ID]) continue;
208  lookedAt2[vx2.ID] = true;
209  auto tjlist = GetVtxTjIDs(tjs, vx2);
210  for(auto tjid : tjlist) {
211  if(tjid == dtj.ID || tjid == ptj.ID) continue;
212  pardtr.push_back(std::make_pair(dtj.ID, tjid));
213  if(prt) {
214  mf::LogVerbatim myprt("TC");
215  myprt<<" add par_dtr";
216  for(auto pdtr : pardtr) myprt<<" "<<pdtr.first<<"_"<<pdtr.second;
217  }
218  }
219  } // end
220  if(pardtr.empty()) break;
221  } // nit
222  } // indx
223  // check the master list
224  for(auto tjid : masterlist) {
225  auto& tj = tjs.allTraj[tjid - 1];
226  if(tj.ParentID < 0) {
227 // std::cout<<"Tj "<<tj.ID<<" is in the master list but doesn't have a Parent\n";
228  tj.ParentID = tj.ID;
229  }
230  } // tjid
231 
232  } // DefineTjParents
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
void ReverseTraj(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:2666
bool TrajTrajDOCA(const TjStuff &tjs, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep, bool considerDeadWires)
Definition: Utils.cxx:2052
std::vector< int > GetVtxTjIDs(const TjStuff &tjs, const VtxStore &vx2)
Definition: TCVertex.cxx:3022
PFPStruct CreatePFP(const TjStuff &tjs, const geo::TPCID &tpcid)
Definition: PFPUtils.cxx:1943
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
bool StorePFP(TjStuff &tjs, PFPStruct &pfp)
Definition: PFPUtils.cxx:2660
bool valDecreasing(SortEntry c1, SortEntry c2)
Definition: Utils.cxx:11
double tca::DeltaAngle ( const Vector3_t  v1,
const Vector3_t  v2 
)

Definition at line 1607 of file PFPUtils.cxx.

References DotProd().

Referenced by tca::TrajClusterAlg::AddLAHits(), ChkVxTjs(), DotProd(), tca::TrajClusterAlg::EndMerge(), FindHammerVertices(), FindHammerVertices2(), tca::TrajClusterAlg::FindSoftKink(), FindXMatches(), tca::TrajClusterAlg::GottaKink(), KinkAngle(), tca::TruthMatcher::MatchTruth(), ParentFOM(), PrintTp3s(), SetVx2Score(), SplitTrajCrossingVertices(), and tca::TrajClusterAlg::StepCrawl().

1608  {
1609  if(v1[0] == v2[0] && v1[1] == v2[1] && v1[2] == v2[2]) return 0;
1610  return acos(DotProd(v1, v2));
1611  }
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:60
double tca::DeltaAngle ( const Point2_t p1,
const Point2_t p2 
)

Definition at line 2763 of file Utils.cxx.

References DeltaAngle2().

2764  {
2765  // angle between two points
2766  double ang1 = atan2(p1[1], p1[0]);
2767  double ang2 = atan2(p2[1], p2[0]);
2768  return DeltaAngle2(ang1, ang2);
2769  } // DeltaAngle
double DeltaAngle2(double Ang1, double Ang2)
Definition: Utils.cxx:2772
double tca::DeltaAngle ( double  Ang1,
double  Ang2 
)

Definition at line 2782 of file Utils.cxx.

Referenced by CompatibleMerge(), PointInsideEnvelope(), and TagDeltaRays().

2783  {
2784  return std::abs(std::remainder(Ang1 - Ang2, M_PI));
2785  }
double tca::DeltaAngle2 ( double  Ang1,
double  Ang2 
)

Definition at line 2772 of file Utils.cxx.

Referenced by DeltaAngle(), and DotProd().

2773  {
2774  constexpr double twopi = 2 * M_PI;
2775  double dang = Ang1 - Ang2;
2776  while(dang > M_PI) dang -= twopi;
2777  while(dang < -M_PI) dang += twopi;
2778  return dang;
2779  }
bool tca::DontCluster ( const TjStuff tjs,
const std::vector< int > &  tjlist1,
const std::vector< int > &  tjlist2 
)

Definition at line 3381 of file TCShower.cxx.

References tca::TjStuff::dontCluster.

Referenced by AddTjsInsideEnvelope(), FindCots(), FindParent(), MergeNearby2DShowers(), MergeOverlap(), MergeShowerChain(), MergeSubShowers(), MergeSubShowersTj(), and Print2DShowers().

3382  {
3383  // returns true if a pair of tjs in the two lists are in the dontCluster vector
3384  if(tjlist1.empty() || tjlist2.empty()) return false;
3385  if(tjs.dontCluster.empty()) return false;
3386  for(auto tid1 : tjlist1) {
3387  for(auto tid2 : tjlist2) {
3388  int ttid1 = tid1;
3389  if(ttid1 > tid2) std::swap(ttid1, tid2);
3390  for(auto& dc : tjs.dontCluster) if(dc.TjIDs[0] == ttid1 && dc.TjIDs[1] == tid2) return true;
3391  } // dc
3392  } // tid1
3393  return false;
3394  } // DontCluster
void swap(art::HLTGlobalStatus &lhs, art::HLTGlobalStatus &rhs)
void tca::DumpShowerPts ( std::string  inFcnLabel,
TjStuff tjs,
int  cotID 
)
void tca::DumpShowerPts ( TjStuff tjs,
int  cotID 
)

Definition at line 4302 of file TCShower.cxx.

References tca::TjStuff::cots, tca::ShowerStruct::ID, pt, tca::ShowerStruct::ShPts, ss, and tca::ShowerStruct::TjIDs.

4303  {
4304  // Print the shower points to the screen. The user should probably pipe the output to a text file
4305  // then grep this file for the character string PTS which is piped to a text file which can then be
4306  // imported into Excel, etc
4307  // Finds the charge at the start of a shower
4308  if(cotID > (int)tjs.cots.size()) return;
4309 
4310  ShowerStruct& ss = tjs.cots[cotID - 1];
4311  if(ss.ID == 0) return;
4312  if(ss.TjIDs.empty()) return;
4313  std::cout<<"PTS Pos0 Pos1 RPos0 RPos1 Chg TID\n";
4314  for(auto& pt : ss.ShPts) {
4315  std::cout<<"PTS "<<std::fixed<<std::setprecision(1)<<pt.Pos[0]<<" "<<pt.Pos[1]<<" "<<pt.RotPos[0]<<" "<<pt.RotPos[1];
4316  std::cout<<" "<<(int)pt.Chg<<" "<<pt.TID;
4317  std::cout<<"\n";
4318  }
4319 
4320  } // DumpShowerPts
Float_t ss
Definition: plot.C:23
TMarker * pt
Definition: egs.C:25
CTP_t tca::EncodeCTP ( const geo::PlaneID planeID)
inline

Definition at line 46 of file DataStructs.h.

References geo::CryostatID::Cryostat, EncodeCTP(), geo::PlaneID::Plane, and geo::TPCID::TPC.

46 { return EncodeCTP(planeID.Cryostat, planeID.TPC, planeID.Plane); }
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
CTP_t EncodeCTP(const geo::WireID &wireID)
Definition: DataStructs.h:47
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
CTP_t tca::EncodeCTP ( const geo::WireID wireID)
inline

Definition at line 47 of file DataStructs.h.

References geo::CryostatID::Cryostat, DecodeCTP(), EncodeCTP(), geo::PlaneID::Plane, and geo::TPCID::TPC.

47 { return EncodeCTP(wireID.Cryostat, wireID.TPC, wireID.Plane); }
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
CTP_t EncodeCTP(const geo::WireID &wireID)
Definition: DataStructs.h:47
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
float tca::ExpectedHitsRMS ( TjStuff tjs,
const TrajPoint tp 
)

Definition at line 1627 of file Utils.cxx.

References tca::TjStuff::AveHitRMS, tca::TrajPoint::CTP, DecodeCTP(), tca::TrajPoint::Dir, geo::PlaneID::Plane, and tca::TjStuff::UnitsPerTick.

Referenced by tca::TrajClusterAlg::AddHits(), tca::TrajClusterAlg::FindUseHits(), and tca::TrajClusterAlg::StartTraj().

1628  {
1629  // returns the expected RMS of hits for the trajectory point in ticks
1630  if(std::abs(tp.Dir[0]) > 0.001) {
1631  geo::PlaneID planeID = DecodeCTP(tp.CTP);
1632  return 1.5 * tjs.AveHitRMS[planeID.Plane] + 2 * std::abs(tp.Dir[1]/tp.Dir[0])/tjs.UnitsPerTick;
1633  } else {
1634  return 500;
1635  }
1636  } // ExpectedHitsRMS
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
unsigned short tca::FarEnd ( const TjStuff tjs,
const PFPStruct pfp,
const Point3_t pos 
)

Definition at line 2936 of file PFPUtils.cxx.

References tca::PFPStruct::ID, PosSep2(), and tca::PFPStruct::XYZ.

Referenced by ChkVxTjs(), DotProd(), FindParent(), MergeSubShowersTj(), ParentFOM(), tca::MCParticleListUtils::PrimaryElectronPFPID(), Reconcile3D(), SetParent(), tca::TruthMatcher::StudyShowerParents(), TagShowerLike(), and UpdateShower().

2937  {
2938  // Returns the end (0 or 1) of the pfp that is furthest away from the position pos
2939  if(pfp.ID == 0) return 0;
2940  if(PosSep2(pfp.XYZ[1], pos) > PosSep2(pfp.XYZ[0], pos)) return 1;
2941  return 0;
2942  } // FarEnd
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1631
unsigned short tca::FarEnd ( const TjStuff tjs,
const Trajectory tj,
const Point2_t pos 
)

Definition at line 3554 of file Utils.cxx.

References tca::Trajectory::EndPt, tca::Trajectory::ID, PosSep2(), and tca::Trajectory::Pts.

3555  {
3556  // Returns the end (0 or 1) of the Tj that is furthest away from the position pos
3557  if(tj.ID == 0) return 0;
3558  if(PosSep2(tj.Pts[tj.EndPt[1]].Pos, pos) > PosSep2(tj.Pts[tj.EndPt[0]].Pos, pos)) return 1;
3559  return 0;
3560  } // FarEnd
float PosSep2(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2226
void tca::FilldEdx ( TjStuff tjs,
PFPStruct pfp 
)

Definition at line 1654 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, tca::PFPStruct::BestPlane, tca::TjStuff::caloAlg, tca::Trajectory::ChgRMS, tca::Trajectory::CTP, DecodeCTP(), tca::Trajectory::dEdx, tca::PFPStruct::dEdx, calo::CalorimetryAlg::dEdx_AREA(), tca::PFPStruct::dEdxErr, tca::PFPStruct::Dir, tca::Trajectory::EndPt, tca::TjStuff::geom, tca::PFPStruct::ID, tca::TjStuff::NumPlanes, tca::PFPStruct::PDGCode, geo::PlaneID::Plane, geo::GeometryCore::Plane(), tca::Trajectory::Pts, geo::PlaneGeo::ThetaZ(), tca::PFPStruct::TjIDs, tca::TjStuff::UnitsPerTick, and geo::GeometryCore::WirePitch().

Referenced by DotProd(), and StorePFP().

1655  {
1656  // Fills the dEdX vector in the match struct. This function should be called after the
1657  // matched trajectory points are ordered so that dE/dx is calculated at the start of the PFParticle
1658  if(pfp.ID == 0) return;
1659  // error check
1660  bool notgood = false;
1661  for(unsigned short startend = 0; startend < 2; ++startend) {
1662  if(pfp.dEdx[startend].size() != tjs.NumPlanes) notgood = true;
1663  if(pfp.dEdxErr[startend].size() != tjs.NumPlanes) notgood = true;
1664  }
1665  if(notgood) {
1666  // if(prt) mf::LogVerbatim("TC")<<"FilldEdx found inconsistent sizes for dEdx\n";
1667  return;
1668  }
1669 
1670  double t0 = 0;
1671 
1672  unsigned short numEnds = 2;
1673  // don't attempt to find dE/dx at the end of a shower
1674  if(pfp.PDGCode == 1111) numEnds = 1;
1675 
1676  unsigned short maxlen = 0;
1677  for(auto tjID : pfp.TjIDs) {
1678 
1679  Trajectory& tj = tjs.allTraj[tjID - 1];
1680  geo::PlaneID planeID = DecodeCTP(tj.CTP);
1681  double angleToVert = tjs.geom->Plane(planeID).ThetaZ() - 0.5 * ::util::pi<>();
1682  for(unsigned short startend = 0; startend < numEnds; ++startend) {
1683  pfp.dEdx[startend][planeID.Plane] = 0;
1684  tj.dEdx[startend] = 0;
1685  double cosgamma = std::abs(std::sin(angleToVert) * pfp.Dir[startend][1] + std::cos(angleToVert) * pfp.Dir[startend][2]);
1686  if(cosgamma == 0) continue;
1687  double dx = tjs.geom->WirePitch(planeID) / cosgamma;
1688  if(dx == 0) continue;
1689  double dQ = tj.Pts[tj.EndPt[startend]].AveChg;
1690  if(dQ == 0) continue;
1691  // convert to dQ/dx
1692  dQ /= dx;
1693  double time = tj.Pts[tj.EndPt[startend]].Pos[1] / tjs.UnitsPerTick;
1694  float dedx = tjs.caloAlg->dEdx_AREA(dQ, time, planeID.Plane, t0);
1695  if(dedx > 999) dedx = 999;
1696  pfp.dEdx[startend][planeID.Plane] = dedx;
1697  tj.dEdx[startend] = dedx;
1698  // ChgRMS is the fractional error
1699  pfp.dEdxErr[startend][planeID.Plane] = dedx * tj.ChgRMS;
1700 
1701  } // startend
1702  // Grab the best plane iusing the start f 1 < dE/dx < 50 MeV/cm
1703  if(pfp.dEdx[0][planeID.Plane] > 1 && pfp.dEdx[0][planeID.Plane] < 50) {
1704  if(tj.Pts.size() > maxlen) {
1705  maxlen = tj.Pts.size();
1706  pfp.BestPlane = planeID.Plane;
1707  }
1708  } // valid dE/dx
1709 
1710  } // tj
1711  } // FilldEdX
code to link reconstructed objects back to the MC truth information
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
void tca::FilldEdx ( TjStuff tjs,
TrajPoint3 tp3 
)

Definition at line 1714 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, tca::TjStuff::caloAlg, DecodeCTP(), tca::TrajPoint3::dEdx, calo::CalorimetryAlg::dEdx_AREA(), tca::TrajPoint3::Dir, tca::TjStuff::fHits, tca::TjStuff::geom, geo::PlaneID::Plane, geo::GeometryCore::Plane(), geo::PlaneGeo::ThetaZ(), tca::TrajPoint3::Tj2Pts, tca::TjStuff::UnitsPerTick, and geo::GeometryCore::WirePitch().

1715  {
1716  // fills the dEdx variables in tp3 (MeV/cm)
1717  tp3.dEdx = 0;
1718  if(tp3.Tj2Pts.empty()) return;
1719  double t0 = 0;
1720  float sum = 0;
1721  float sum2 = 0;
1722  float cnt = 0;
1723  for(auto& tj2pt : tp3.Tj2Pts) {
1724  auto& tp = tjs.allTraj[tj2pt.id - 1].Pts[tj2pt.ipt];
1725  if(tp.Chg <= 0) continue;
1726  geo::PlaneID planeID = DecodeCTP(tp.CTP);
1727  double angleToVert = tjs.geom->Plane(planeID).ThetaZ() - 0.5 * ::util::pi<>();
1728  double cosgamma = std::abs(std::sin(angleToVert) * tp3.Dir[1] + std::cos(angleToVert) * tp3.Dir[2]);
1729  if(cosgamma == 0) continue;
1730  double dx = tjs.geom->WirePitch(planeID) / cosgamma;
1731  // sum the hit charge
1732  double chg = 0;
1733  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1734  if(!tp.UseHit[ii]) continue;
1735  unsigned int iht = tp.Hits[ii];
1736  chg += tjs.fHits[iht].Integral;
1737  }
1738  double dQ = chg / dx;
1739  double time = tp.Pos[1] / tjs.UnitsPerTick;
1740  float dedx = tjs.caloAlg->dEdx_AREA(dQ, time, planeID.Plane, t0);
1741  if(dedx > 200) continue;
1742  sum += dedx;
1743  sum2 += dedx * dedx;
1744  ++cnt;
1745  } // tj2pt
1746  if(cnt == 0) return;
1747  tp3.dEdx = sum / cnt;
1748 /*
1749  if(cnt > 1) {
1750  float arg = sum2 - cnt * tp3.dEdx * tp3.dEdx;
1751  if(arg > 0) {
1752  tp3.dEdxErr = sqrt(arg / (cnt - 1));
1753  // convert to error on the mean
1754  tp3.dEdxErr /= sqrt(cnt);
1755  }
1756  } // cnt > 1
1757 */
1758  } // FilldEdx
code to link reconstructed objects back to the MC truth information
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
void tca::FillmAllTraj ( TjStuff tjs,
const geo::TPCID tpcid 
)

Definition at line 127 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, detinfo::DetectorProperties::ConvertTicksToX(), geo::CryostatID::Cryostat, DecodeCTP(), tca::TjStuff::detprop, tca::TjStuff::geom, geo::GeometryCore::HasWire(), kKilled, kMat3D, kTjHiVx3Score, kUsedHits, tca::TjStuff::mallTraj, tca::TjStuff::Match3DCuts, tca::TjStuff::matchVec, NumPtsWithCharge(), geo::PlaneID::Plane, geo::TPCID::TPC, TPHitsRMSTime(), tca::TjStuff::UnitsPerTick, and valIncreasings().

Referenced by tca::TrajClusterAlg::RunTrajClusterAlg().

128  {
129  // Fills the tjs.mallTraj vector with trajectory points in the tpc and sorts
130  // them by increasing X
131  tjs.matchVec.clear();
132 
133  int cstat = tpcid.Cryostat;
134  int tpc = tpcid.TPC;
135 
136  // count the number of TPs and clear out any old 3D match flags
137  unsigned int ntp = 0;
138  for(auto& tj : tjs.allTraj) {
139  if(tj.AlgMod[kKilled]) continue;
140  if(tj.ID <= 0) continue;
141  geo::PlaneID planeID = DecodeCTP(tj.CTP);
142  if((int)planeID.Cryostat != cstat) continue;
143  if((int)planeID.TPC != tpc) continue;
144  ntp += NumPtsWithCharge(tjs, tj, false);
145  tj.AlgMod[kMat3D] = false;
146  } // tj
147  if(ntp < 2) return;
148 
149  tjs.mallTraj.resize(ntp);
150 
151  // define mallTraj
152  unsigned int icnt = 0;
153  for(auto& tj : tjs.allTraj) {
154  if(tj.AlgMod[kKilled]) continue;
155  geo::PlaneID planeID = DecodeCTP(tj.CTP);
156  if((int)planeID.Cryostat != cstat) continue;
157  if((int)planeID.TPC != tpc) continue;
158  int plane = planeID.Plane;
159  int tjID = tj.ID;
160  if(tjID <= 0) continue;
161  short score = 1;
162  if(tj.AlgMod[kTjHiVx3Score]) score = 0;
163  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
164  auto& tp = tj.Pts[ipt];
165  if(tp.Chg == 0) continue;
166  if(icnt > tjs.mallTraj.size() - 1) break;
167  if(tp.Pos[0] < -0.4) continue;
168  tjs.mallTraj[icnt].wire = std::nearbyint(tp.Pos[0]);
169  bool hasWire = tjs.geom->HasWire(geo::WireID(cstat, tpc, plane, tjs.mallTraj[icnt].wire));
170  // don't try matching if the wire doesn't exist
171  if(!hasWire) continue;
172  float xpos = tjs.detprop->ConvertTicksToX(tp.Pos[1]/tjs.UnitsPerTick, plane, tpc, cstat);
173  float posPlusRMS = tp.Pos[1] + TPHitsRMSTime(tjs, tp, kUsedHits);
174  float rms = tjs.detprop->ConvertTicksToX(posPlusRMS/tjs.UnitsPerTick, plane, tpc, cstat) - xpos;
175  if(rms < tjs.Match3DCuts[0]) rms = tjs.Match3DCuts[0];
176  if(icnt == tjs.mallTraj.size()) break;
177  tjs.mallTraj[icnt].xlo = xpos - rms;
178  tjs.mallTraj[icnt].xhi = xpos + rms;
179  tjs.mallTraj[icnt].dir = tp.Dir;
180  tjs.mallTraj[icnt].ctp = tp.CTP;
181  tjs.mallTraj[icnt].id = tjID;
182  tjs.mallTraj[icnt].ipt = ipt;
183  tjs.mallTraj[icnt].npts = tj.EndPt[1] - tj.EndPt[0] + 1;
184  tjs.mallTraj[icnt].score = score;
185  ++icnt;
186  } // tp
187  } // tj
188 
189  if(icnt < tjs.mallTraj.size()) tjs.mallTraj.resize(icnt);
190 
191  // This is pretty self-explanatory
192  std::vector<SortEntry> sortVec(tjs.mallTraj.size());
193  for(unsigned int ipt = 0; ipt < tjs.mallTraj.size(); ++ipt) {
194  // populate the sort vector
195  sortVec[ipt].index = ipt;
196  sortVec[ipt].val = tjs.mallTraj[ipt].xlo;
197  } // ipt
198  // sort by increasing xlo
199  std::sort(sortVec.begin(), sortVec.end(), valIncreasings);
200  // put tjs.mallTraj into sorted order
201  auto tallTraj = tjs.mallTraj;
202  for(unsigned int ii = 0; ii < sortVec.size(); ++ii) tjs.mallTraj[ii] = tallTraj[sortVec[ii].index];
203 
204  } // FillmAllTraj
float TPHitsRMSTime(TjStuff &tjs, TrajPoint &tp, HitStatus_t hitRequest)
Definition: Utils.cxx:3576
bool valIncreasings(SortEntry c1, SortEntry c2)
Definition: PFPUtils.cxx:13
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
unsigned short NumPtsWithCharge(const TjStuff &tjs, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1738
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
bool tca::FillWireHitRange ( TjStuff tjs,
const geo::TPCID tpcid 
)

Definition at line 3722 of file Utils.cxx.

References tca::TjStuff::AveHitRMS, CheckWireHitRange(), geo::CryostatID::Cryostat, debug, tca::TjStuff::DebugMode, geo::GeometryCore::DetHalfHeight(), geo::GeometryCore::DetHalfWidth(), geo::GeometryCore::DetLength(), tca::TjStuff::detprop, detinfo::DetectorProperties::DriftVelocity(), detinfo::DetectorProperties::Efield(), tca::TjStuff::fHits, tca::TjStuff::FirstWire, tca::TjStuff::geom, tca::TjStuff::LastWire, geo::TPCGeo::LocalToWorld(), tca::TjStuff::MaxPos0, tca::TjStuff::MaxPos1, geo::TPCGeo::Nplanes(), detinfo::DetectorProperties::NumberTimeSamples(), tca::TjStuff::NumPlanes, tca::TjStuff::NumWires, geo::GeometryCore::Nwires(), geo::GeometryCore::PlaneWireToChannel(), detinfo::DetectorProperties::SamplingRate(), detinfo::DetectorProperties::Temperature(), tca::DebugStuff::TPC, geo::TPCID::TPC, geo::GeometryCore::TPC(), tca::TjStuff::TPCID, tca::TjStuff::UnitsPerTick, geo::GeometryCore::View(), tca::TjStuff::WireHitRange, tca::TjStuff::WirePitch, geo::GeometryCore::WirePitch(), tca::TjStuff::XHi, tca::TjStuff::XLo, tca::TjStuff::YHi, tca::TjStuff::YLo, tca::TjStuff::ZHi, and tca::TjStuff::ZLo.

Referenced by DotProd(), FindShowers3D(), trkf::CCTrackMaker::produce(), and tca::TrajClusterAlg::RunTrajClusterAlg().

3723  {
3724  // fills the WireHitRange vector. Slightly modified version of the one in ClusterCrawlerAlg.
3725  // Returns false if there was a serious error
3726 
3727  // determine the number of planes
3728  geo::TPCGeo const& TPC = tjs.geom->TPC(tpcid);
3729  unsigned int cstat = tpcid.Cryostat;
3730  unsigned int tpc = tpcid.TPC;
3731  unsigned short nplanes = TPC.Nplanes();
3732  tjs.NumPlanes = nplanes;
3733  tjs.TPCID = tpcid;
3734 
3735  // Y,Z limits of the detector
3736  double local[3] = {0.,0.,0.};
3737  double world[3] = {0.,0.,0.};
3738  const geo::TPCGeo &thetpc = tjs.geom->TPC(tpc, cstat);
3739  thetpc.LocalToWorld(local,world);
3740  // reduce the active area of the TPC by 1 cm to prevent wire boundary issues
3741  tjs.XLo = world[0]-tjs.geom->DetHalfWidth(tpc,cstat) + 1;
3742  tjs.XHi = world[0]+tjs.geom->DetHalfWidth(tpc,cstat) - 1;
3743  tjs.YLo = world[1]-tjs.geom->DetHalfHeight(tpc,cstat) + 1;
3744  tjs.YHi = world[1]+tjs.geom->DetHalfHeight(tpc,cstat) - 1;
3745  tjs.ZLo = world[2]-tjs.geom->DetLength(tpc,cstat)/2 + 1;
3746  tjs.ZHi = world[2]+tjs.geom->DetLength(tpc,cstat)/2 - 1;
3747 
3748  lariov::ChannelStatusProvider const& channelStatus = art::ServiceHandle<lariov::ChannelStatusService>()->GetProvider();
3749 
3750  if(!tjs.WireHitRange.empty()) tjs.WireHitRange.clear();
3751 
3752  // initialize everything
3753  tjs.WireHitRange.resize(nplanes);
3754  tjs.FirstWire.resize(nplanes);
3755  tjs.LastWire.resize(nplanes);
3756  tjs.NumWires.resize(nplanes);
3757  tjs.MaxPos0.resize(nplanes);
3758  tjs.MaxPos1.resize(nplanes);
3759  tjs.AveHitRMS.resize(nplanes, nplanes);
3760 
3761  std::pair<int, int> flag;
3762  flag.first = -2; flag.second = -2;
3763 
3764  // Calculate tjs.UnitsPerTick, the scale factor to convert a tick into
3765  // Wire Spacing Equivalent (WSE) units where the wire spacing in this plane = 1.
3766  // Strictly speaking this factor should be calculated for each plane to handle the
3767  // case where the wire spacing is different in each plane. Deal with this later if
3768  // the approximation used here fails.
3769 
3770  raw::ChannelID_t channel = tjs.geom->PlaneWireToChannel(0, 0, (int)tpc, (int)cstat);
3771  tjs.WirePitch = tjs.geom->WirePitch(tjs.geom->View(channel));
3772  float tickToDist = tjs.detprop->DriftVelocity(tjs.detprop->Efield(),tjs.detprop->Temperature());
3773  tickToDist *= 1.e-3 * tjs.detprop->SamplingRate(); // 1e-3 is conversion of 1/us to 1/ns
3774  tjs.UnitsPerTick = tickToDist / tjs.WirePitch;
3775  for(unsigned short ipl = 0; ipl < nplanes; ++ipl) {
3776  tjs.FirstWire[ipl] = INT_MAX;
3777  tjs.LastWire[ipl] = 0;
3778  tjs.NumWires[ipl] = tjs.geom->Nwires(ipl, tpc, cstat);
3779  tjs.WireHitRange[ipl].resize(tjs.NumWires[ipl], flag);
3780  tjs.MaxPos0[ipl] = (float)tjs.NumWires[ipl] - 0.5;
3781  tjs.MaxPos1[ipl] = (float)tjs.detprop->NumberTimeSamples() * tjs.UnitsPerTick;
3782  }
3783 
3784  // overwrite with the "dead wires" condition
3785  flag.first = -1; flag.second = -1;
3786  for(unsigned short ipl = 0; ipl < nplanes; ++ipl) {
3787  for(unsigned int wire = 0; wire < tjs.NumWires[ipl]; ++wire) {
3788  raw::ChannelID_t chan = tjs.geom->PlaneWireToChannel((int)ipl, (int)wire, (int)tpc, (int)cstat);
3789  if(!channelStatus.IsGood(chan)) tjs.WireHitRange[ipl][wire] = flag;
3790  } // wire
3791  } // ipl
3792 
3793  unsigned int lastwire = 0, lastipl = 0;
3794  for(unsigned int iht = 0; iht < tjs.fHits.size(); ++iht) {
3795  if(tjs.fHits[iht].ArtPtr->WireID().Cryostat != cstat) continue;
3796  if(tjs.fHits[iht].ArtPtr->WireID().TPC != tpc) continue;
3797  unsigned short ipl = tjs.fHits[iht].ArtPtr->WireID().Plane;
3798  unsigned int wire = tjs.fHits[iht].ArtPtr->WireID().Wire;
3799  if(wire > tjs.NumWires[ipl] - 1) {
3800  mf::LogWarning("TC")<<"FillWireHitRange: Invalid wire number "<<wire<<" > "<<tjs.NumWires[ipl] - 1<<" in plane "<<ipl<<" Quitting";
3801  return false;
3802  } // too large wire number
3803  if(ipl == lastipl && wire < lastwire) {
3804  mf::LogWarning("TC")<<"FillWireHitRange: Hits are not in increasing wire order. Quitting ";
3805  return false;
3806  } // hits out of order
3807  lastwire = wire;
3808  lastipl = ipl;
3809  if(tjs.FirstWire[ipl] == INT_MAX) tjs.FirstWire[ipl] = wire;
3810  if(tjs.WireHitRange[ipl][wire].first < 0) tjs.WireHitRange[ipl][wire].first = iht;
3811  tjs.WireHitRange[ipl][wire].second = iht + 1;
3812  tjs.LastWire[ipl] = wire + 1;
3813  } // iht
3814 
3815  if(!CheckWireHitRange(tjs)) return false;
3816 
3817  // Find the average multiplicity 1 hit RMS and calculate the expected max RMS for each range
3818  if(tjs.DebugMode && (int)tpc == debug.TPC) {
3819  std::cout<<"tpc "<<tpc<<" tjs.UnitsPerTick "<<std::setprecision(3)<<tjs.UnitsPerTick<<"\n";
3820  std::cout<<"Fiducial volume (";
3821  std::cout<<std::fixed<<std::setprecision(1)<<tjs.XLo<<" < X < "<<tjs.XHi<<") (";
3822  std::cout<<std::fixed<<std::setprecision(1)<<tjs.YLo<<" < Y < "<<tjs.YHi<<") (";
3823  std::cout<<std::fixed<<std::setprecision(1)<<tjs.ZLo<<" < Z < "<<tjs.ZHi<<")\n";
3824  }
3825  for(unsigned short ipl = 0; ipl < tjs.NumPlanes; ++ipl) {
3826  float sumRMS = 0;
3827  float sumAmp = 0;
3828  unsigned int cnt = 0;
3829  for(unsigned int wire = 0; wire < tjs.NumWires[ipl]; ++wire) {
3830  if(tjs.WireHitRange[ipl][wire].first < 0) continue;
3831  unsigned int firstHit = tjs.WireHitRange[ipl][wire].first;
3832  unsigned int lastHit = tjs.WireHitRange[ipl][wire].second;
3833  // don't let noisy wires screw up the calculation
3834  if(lastHit - firstHit > 100) continue;
3835  for(unsigned int iht = firstHit; iht < lastHit; ++iht) {
3836  if(tjs.fHits[iht].Multiplicity != 1) continue;
3837  if(tjs.fHits[iht].GoodnessOfFit < 0 || tjs.fHits[iht].GoodnessOfFit > 100) continue;
3838  // don't let a lot of runt hits screw up the calculation
3839  if(tjs.fHits[iht].PeakAmplitude < 1) continue;
3840  ++cnt;
3841  sumRMS += tjs.fHits[iht].RMS;
3842  sumAmp += tjs.fHits[iht].PeakAmplitude;
3843  } // iht
3844  } // wire
3845  if(cnt < 4) continue;
3846  tjs.AveHitRMS[ipl] = sumRMS/(float)cnt;
3847  sumAmp /= (float)cnt;
3848  if(tjs.DebugMode) std::cout<<"Pln "<<ipl<<" tjs.AveHitRMS "<<tjs.AveHitRMS[ipl]<<" Ave PeakAmplitude "<<sumAmp<<"\n";
3849  } // ipl
3850  return true;
3851 
3852  } // FillWireHitRange
unsigned int Nplanes() const
Number of planes in this tpc.
Definition: TPCGeo.h:145
Geometry information for a single TPC.
Definition: TPCGeo.h:37
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
bool CheckWireHitRange(const TjStuff &tjs)
Definition: Utils.cxx:3855
DebugStuff debug
Definition: DebugStruct.cxx:4
int TPC
Select TPC.
Definition: DebugStruct.h:28
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:27
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
void LocalToWorld(const double *tpc, double *world) const
Transform point from local TPC frame to world frame.
Definition: TPCGeo.h:490
void tca::Find2DVertices ( TjStuff tjs,
const CTP_t inCTP 
)

Definition at line 114 of file TCVertex.cxx.

References tca::TjStuff::allTraj, AttachAnyTrajToVertex(), tca::VtxStore::ChiDOF, ChkVxTjs(), tca::VtxStore::CTP, tca::TrajPoint::CTP, DeadWireCount(), debug, DecodeCTP(), FindHammerVertices(), FindHammerVertices2(), FitVertex(), tca::VtxStore::ID, IsCloseToVertex(), kFixed, kKilled, kOnDeadWire, kShowerLike, tca::TjStuff::MaxPos0, tca::TjStuff::MaxPos1, MergeWithVertex(), MoveTPToWire(), NearestPtWithChg(), tca::VtxStore::NTraj, tca::VtxStore::Pass, tca::DebugStuff::Plane, geo::PlaneID::Plane, tca::VtxStore::Pos, tca::TrajPoint::Pos, PosSep(), PosSep2(), PrintAllTraj(), PrintPos(), SetVx2Score(), SignalBetween(), tca::VtxStore::Stat, tca::TjStuff::StepDir, StoreVertex(), tca::DebugStuff::Tick, tca::VtxStore::Topo, TrajClosestApproach(), TrajIntersection(), TrajLength(), TrajTrajDOCA(), tca::TjStuff::UnitsPerTick, tca::TjStuff::Vertex2DCuts, and tca::TjStuff::vtx.

Referenced by tca::TrajClusterAlg::ReconstructAllTraj().

115  {
116  // Find 2D vertices between pairs of tjs that have a same-end topology. Using an example
117  // where StepDir = 1 (end 0 is at small wire number) vertices will be found with Topo = 0
118  // with a vertex US of the ends (<) or Topo = 2 with a vertex DS of the ends (>). This is reversed
119  // if StepDir = -1. Vertices with Topo = 1 (/\) and (\/) are found in EndMerge.
120 
121  // tjs.Vertex2DCuts fcl input usage
122  // 0 = maximum length of a short trajectory
123  // 1 = max vertex - trajectory separation for short trajectories
124  // 2 = max vertex - trajectory separation for long trajectories
125  // 3 = max position pull for adding TJs to a vertex
126  // 4 = max allowed vertex position error
127  // 5 = min MCSMom
128  // 6 = min Pts/Wire fraction
129  // 7 min Score
130  // 8 Min charge fraction near a merge point (not a vertex)
131  // 9 max MCSmom asymmetry for a merge
132 
133  if(tjs.Vertex2DCuts[0] <= 0) return;
134 
135  if(tjs.allTraj.size() < 2) return;
136 
137  geo::PlaneID planeID = DecodeCTP(inCTP);
138 
139  bool prt = (debug.Plane == (int)planeID.Plane && debug.Tick < 0);
140  if(prt) {
141  mf::LogVerbatim("TC")<<"prt set for plane "<<planeID.Plane<<" in Find2DVertices";
142  PrintAllTraj("F2DVi", tjs, debug, USHRT_MAX, tjs.allTraj.size());
143  }
144 
145  unsigned short maxShortTjLen = tjs.Vertex2DCuts[0];
146  for(unsigned short it1 = 0; it1 < tjs.allTraj.size() - 1; ++it1) {
147  auto& tj1 = tjs.allTraj[it1];
148  if(tj1.AlgMod[kKilled]) continue;
149  if(tj1.SSID > 0 || tj1.AlgMod[kShowerLike]) continue;
150  if(tj1.CTP != inCTP) continue;
151  bool tj1Short = (TrajLength(tj1) < maxShortTjLen);
152  for(unsigned short end1 = 0; end1 < 2; ++end1) {
153  // vertex assignment exists?
154  if(tj1.VtxID[end1] > 0) continue;
155  // default condition is to use the end point to define the trajectory and direction
156  // at the end
157  short endPt1 = tj1.EndPt[end1];
158  float wire1 = tj1.Pts[endPt1].Pos[0];
159  // unless there are few points fitted, indicating that the trajectory fit
160  // may have been biased by the presence of another trajectory at the vertex or by
161  // other close unresolved tracks
162  if(tj1.Pts.size() > 6 && tj1.Pts[endPt1].NTPsFit < 4) {
163  if(end1 == 0 && endPt1 < int(tj1.Pts.size()) - 3) {
164  endPt1 += 3;
165  } else if (end1 == 1 && endPt1 >=3 ) {
166  endPt1 -= 3;
167  }
168  if(tj1.Pts[endPt1].Chg == 0) endPt1 = NearestPtWithChg(tjs, tj1, endPt1);
169  } // few points fit at end1
170  TrajPoint tp1 = tj1.Pts[endPt1];
171  MoveTPToWire(tp1, wire1);
172  // re-purpose endPt1 to reference the end point. This will be used the find the point on
173  // tj1 that is closest to the vertex position
174  endPt1 = tj1.EndPt[end1];
175  short oendPt1 = tj1.EndPt[1-end1];
176  // reference to the other end of tj1
177  auto& otp1 = tj1.Pts[oendPt1];
178  for(unsigned short it2 = it1 + 1; it2 < tjs.allTraj.size(); ++it2) {
179  auto& tj2 = tjs.allTraj[it2];
180  if(tj2.AlgMod[kKilled]) continue;
181  if(tj2.SSID > 0 || tj2.AlgMod[kShowerLike]) continue;
182  if(tj2.CTP != inCTP) continue;
183  if(tj1.VtxID[end1] > 0) continue;
184  if(tj1.MCSMom < tjs.Vertex2DCuts[5] && tj2.MCSMom < tjs.Vertex2DCuts[5]) continue;
185  bool tj2Short = (TrajLength(tj2) < maxShortTjLen);
186  // find the end that is closer to tp1
187  unsigned short end2 = 0;
188  if(PosSep2(tj2.Pts[tj2.EndPt[1]].Pos, tp1.Pos) < PosSep2(tj2.Pts[tj2.EndPt[0]].Pos, tp1.Pos)) end2 = 1;
189  if(tj2.VtxID[end2] > 0) continue;
190  // check for a vertex between these tjs at the other ends
191  if(tj1.VtxID[1 - end1] > 0 && tj1.VtxID[1 - end1] == tj2.VtxID[1 - end2]) continue;
192  // see if the other ends are closer
193  unsigned short oendPt2 = tj2.EndPt[1-end2];
194  auto& otp2 = tj2.Pts[oendPt2];
195  if(PosSep2(otp1.Pos, otp2.Pos) < PosSep2(tp1.Pos, tj2.Pts[tj2.EndPt[end2]].Pos)) continue;
196  short endPt2 = tj2.EndPt[end2];
197  float wire2 = tj2.Pts[endPt2].Pos[0];
198  if(tj2.Pts.size() > 6 && tj2.Pts[endPt2].NTPsFit < 4) {
199  if(end2 == 0 && endPt2 < int(tj2.Pts.size()) - 3) {
200  endPt2 += 3;
201  } else if (end2 == 1 && endPt2 >= 3){
202  endPt2 -= 3;
203  }
204  if(tj2.Pts[endPt2].Chg == 0) endPt2 = NearestPtWithChg(tjs, tj2, endPt2);
205  } // few points fit at end1
206  TrajPoint tp2 = tj2.Pts[endPt2];
207  MoveTPToWire(tp2, wire2);
208  // re-purpose endPt2
209  endPt2 = tj2.EndPt[end2];
210  // Rough first cut on the separation between the end points of the
211  // two trajectories
212  float sepCut = 100;
213  if(std::abs(tp1.Pos[0] - tp2.Pos[0]) > sepCut) continue;
214  if(std::abs(tp1.Pos[1] - tp2.Pos[1]) > sepCut) continue;
215  float wint, tint;
216  TrajIntersection(tp1, tp2, wint, tint);
217  // make sure this is inside the TPC
218  if(wint < 0 || wint > tjs.MaxPos0[planeID.Plane]) continue;
219  if(tint < 0 || tint > tjs.MaxPos1[planeID.Plane]) continue;
220  // Next cut on separation between the TPs and the intersection point
221  if(tj1Short || tj2Short) { sepCut = tjs.Vertex2DCuts[1]; } else { sepCut = tjs.Vertex2DCuts[2]; }
222  Point2_t vPos {{wint, tint}};
223  float vt1Sep = PosSep(vPos, tp1.Pos);
224  float vt2Sep = PosSep(vPos, tp2.Pos);
225  float dwc1 = DeadWireCount(tjs, wint, tp1.Pos[0], tp1.CTP);
226  float dwc2 = DeadWireCount(tjs, wint, tp2.Pos[0], tp1.CTP);
227  vt1Sep -= dwc1;
228  vt2Sep -= dwc2;
229  bool vtxOnDeadWire = (DeadWireCount(tjs, wint, wint, tp1.CTP) == 1);
230  if(prt && vt1Sep < 200 && vt2Sep < 200) {
231  mf::LogVerbatim myprt("TC");
232  myprt<<"F2DV candidate T"<<tj1.ID<<"_"<<end1<<"-T"<<tj2.ID<<"_"<<end2;
233  myprt<<" vtx pos "<<(int)wint<<":"<<(int)(tint/tjs.UnitsPerTick)<<" tp1 "<<PrintPos(tjs, tp1)<<" tp2 "<<PrintPos(tjs, tp2);
234  myprt<<" dwc1 "<<dwc1<<" dwc2 "<<dwc2<<" on dead wire? "<<vtxOnDeadWire;
235  myprt<<" vt1Sep "<<vt1Sep<<" vt2Sep "<<vt2Sep<<" sepCut "<<sepCut;
236  }
237  if(vt1Sep > sepCut || vt2Sep > sepCut) continue;
238  // make sure that the other end isn't closer
239  if(PosSep(vPos, tjs.allTraj[it1].Pts[oendPt1].Pos) < vt1Sep) {
240  if(prt) mf::LogVerbatim("TC")<<" tj1 other end "<<PrintPos(tjs, tj1.Pts[oendPt1])<<" is closer to the vertex";
241  continue;
242  }
243  if(PosSep(vPos, tjs.allTraj[it2].Pts[oendPt2].Pos) < vt2Sep) {
244  if(prt) mf::LogVerbatim("TC")<<" tj2 other end "<<PrintPos(tjs, tj2.Pts[oendPt2])<<" is closer to the vertex";
245  continue;
246  }
247  // Ensure that the vertex position is close to the end of each Tj
248  unsigned short closePt1;
249  float doca1 = sepCut;
250  if(!TrajClosestApproach(tj1, wint, tint, closePt1, doca1)) continue;
251  // dpt1 (and dpt2) will be 0 if the vertex is at the end
252  short dpt1 = tjs.StepDir * (closePt1 - endPt1);
253  if(prt) mf::LogVerbatim("TC")<<" endPt1 "<<endPt1<<" closePt1 "<<closePt1<<" dpt1 "<<dpt1<<" doca1 "<<doca1;
254  // BB April 19, 2018: require vertex to be near the end
255  if(dpt1 < -1) continue;
256  if(tjs.allTraj[it1].EndPt[1] > 4) {
257  if(dpt1 > 3) continue;
258  } else {
259  // tighter cut for short trajectories
260  if(dpt1 > 2) continue;
261  }
262  unsigned short closePt2;
263  float doca2 = sepCut;
264  if(!TrajClosestApproach(tj2, wint, tint, closePt2, doca2)) continue;
265  short dpt2 = tjs.StepDir * (closePt2 - endPt2);
266  if(prt) mf::LogVerbatim("TC")<<" endPt2 "<<endPt2<<" closePt2 "<<closePt2<<" dpt2 "<<dpt2<<" doca2 "<<doca2;
267  // BB April 19, 2018: require vertex to be near the end
268  if(dpt2 < -1) continue;
269  if(tjs.allTraj[it2].EndPt[1] > 4) {
270  if(dpt2 > 3) continue;
271  } else {
272  // tighter cut for short trajectories
273  if(dpt2 > 2) continue;
274  }
275  if(prt) mf::LogVerbatim("TC")<<" wint:tint "<<(int)wint<<":"<<(int)(tint/tjs.UnitsPerTick);
276  // ensure that there is a signal between these TPs and the vertex on most of the wires
277  bool signalBetween = true;
278  bool fixVxPos = false;
279  short dpt = abs(wint - tp1.Pos[0]);
280  if(dpt > 2 && !SignalBetween(tjs, tp1, wint, tjs.Vertex2DCuts[6], prt)) {
281  if(prt) mf::LogVerbatim("TC")<<" Fails SignalBetween for tp1 "<<dpt;
282  signalBetween = false;
283  }
284  dpt = abs(wint - tp2.Pos[0]);
285  if(dpt > 2 && !SignalBetween(tjs, tp2, wint, tjs.Vertex2DCuts[6], prt)) {
286  if(prt) mf::LogVerbatim("TC")<<" Fails SignalBetween for tp2 "<<dpt;
287  signalBetween = false;
288  }
289  // consider the case where the intersection point is wrong because the
290  // end TP angles are screwed up but the Tjs are close to each other near the end
291  if(!signalBetween) {
292  unsigned short ipt1, ipt2;
293  float maxSep = 3;
294  bool isClose = TrajTrajDOCA(tjs, tj1, tj2, ipt1, ipt2, maxSep, false);
295  if(prt) mf::LogVerbatim("TC")<<" TrajTrajDOCA close? "<<isClose<<" minSep "<<maxSep;
296  if(isClose) {
297  // put the vertex at the TP that is closest to the intersection point
298  Point2_t vpos = {{wint, tint}};
299  if(PosSep2(tp1.Pos, vpos) < PosSep2(tp2.Pos, vpos)) {
300  wint = tp1.Pos[0];
301  tint = tp1.Pos[1];
302  } else {
303  wint = tp2.Pos[0];
304  tint = tp2.Pos[1];
305  }
306  fixVxPos = true;
307  if(prt) mf::LogVerbatim("TC")<<" new wint:tint "<<(int)wint<<":"<<(int)(tint/tjs.UnitsPerTick);
308  } else {
309  // closest approach > 3
310  continue;
311  }
312  } // no signal between
313  // make a new temporary vertex
314  VtxStore aVtx;
315  aVtx.Pos[0] = wint;
316  aVtx.Pos[1] = tint;
317  aVtx.NTraj = 0;
318  aVtx.Pass = tj1.Pass;
319  // Topo 0 has this topology (<) and Topo 2 has this (>)
320  aVtx.Topo = 2 * end1;
321  aVtx.ChiDOF = 0;
322  aVtx.CTP = inCTP;
323  aVtx.Stat[kOnDeadWire] = vtxOnDeadWire;
324  // fix the vertex position if we needed to move it significantly, or if it is on a dead wire
325  aVtx.Stat[kFixed] = fixVxPos;
326 // if(close2 > 1) aVtx.Stat[kFixed] = true;
327  // try to fit it. We need to give it an ID to do that. Take the next
328  // available ID
329  unsigned short newVtxID = tjs.vtx.size() + 1;
330  aVtx.ID = newVtxID;
331  tj1.VtxID[end1] = newVtxID;
332  tj2.VtxID[end2] = newVtxID;
333  if(!FitVertex(tjs, aVtx, prt)) {
334  tj1.VtxID[end1] = 0;
335  tj2.VtxID[end2] = 0;
336  continue;
337  }
338  // check proximity to nearby vertices
339  unsigned short mergeMeWithVx = IsCloseToVertex(tjs, aVtx);
340  if(mergeMeWithVx > 0 && MergeWithVertex(tjs, aVtx, mergeMeWithVx, prt)) {
341  if(prt) mf::LogVerbatim("TC")<<" Merged with close vertex "<<mergeMeWithVx;
342  continue;
343  }
344  // Save it
345  if(!StoreVertex(tjs, aVtx)) continue;
346  if(prt) {
347  mf::LogVerbatim myprt("TC");
348  myprt<<" New vtx 2V"<<aVtx.ID;
349  myprt<<" Tjs "<<tj1.ID<<"_"<<end1<<"-"<<tj2.ID<<"_"<<end2;
350  myprt<<" at "<<std::fixed<<std::setprecision(1)<<aVtx.Pos[0]<<":"<<aVtx.Pos[1]/tjs.UnitsPerTick;
351  }
352  AttachAnyTrajToVertex(tjs, tjs.vtx.size() - 1, prt);
353  SetVx2Score(tjs, prt);
354  } // it2
355  } // end1
356  } // it1
357 
358  // check the consistency of the Tjs for the newly added vertices
359  ChkVxTjs(tjs, inCTP, prt);
360 
361  FindHammerVertices(tjs, inCTP);
362  FindHammerVertices2(tjs, inCTP);
363 
364  if(prt) PrintAllTraj("F2DVo", tjs, debug, USHRT_MAX, USHRT_MAX);
365 
366  } // Find2DVertices
std::string PrintPos(const TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:4738
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void PrintAllTraj(std::string someText, const TjStuff &tjs, const DebugStuff &debug, unsigned short itj, unsigned short ipt, bool prtVtx)
Definition: Utils.cxx:4232
vertex position fixed manually - no fitting done
Definition: DataStructs.h:102
unsigned short NearestPtWithChg(TjStuff &tjs, Trajectory &tj, unsigned short thePt)
Definition: Utils.cxx:2889
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
bool AttachAnyTrajToVertex(TjStuff &tjs, unsigned short ivx, bool prt)
Definition: TCVertex.cxx:1689
void ChkVxTjs(TjStuff &tjs, const CTP_t &inCTP, bool prt)
Definition: TCVertex.cxx:715
bool TrajClosestApproach(Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
Definition: Utils.cxx:2244
bool FitVertex(TjStuff &tjs, VtxStore &vx, std::vector< TrajPoint > vxTp, bool prt)
Definition: TCVertex.cxx:1986
float DeadWireCount(const TjStuff &tjs, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:1756
unsigned short IsCloseToVertex(TjStuff &tjs, Vtx3Store &vx3)
Definition: TCVertex.cxx:3110
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
DebugStuff debug
Definition: DebugStruct.cxx:4
bool SignalBetween(TjStuff &tjs, const TrajPoint &tp1, const TrajPoint &tp2, const float &MinWireSignalFraction, bool prt)
Definition: Utils.cxx:1495
int Plane
Select plane.
Definition: DebugStruct.h:29
float TrajLength(Trajectory &tj)
Definition: Utils.cxx:2204
void FindHammerVertices2(TjStuff &tjs, const CTP_t &inCTP)
Definition: TCVertex.cxx:819
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1631
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
int Tick
Select hit PeakTime for debugging (< 0 for vertex finding)
Definition: DebugStruct.h:32
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
Definition: Utils.cxx:2166
bool MergeWithVertex(TjStuff &tjs, VtxStore &vx, unsigned short oVxID, bool prt)
Definition: TCVertex.cxx:544
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
void FindHammerVertices(TjStuff &tjs, const CTP_t &inCTP)
Definition: TCVertex.cxx:995
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2351
bool StoreVertex(TjStuff &tjs, VtxStore &vx)
Definition: TCVertex.cxx:1911
bool TrajTrajDOCA(const TjStuff &tjs, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2046
void SetVx2Score(TjStuff &tjs, VtxStore &vx2, bool prt)
Definition: TCVertex.cxx:2331
void tca::Find3DVertices ( TjStuff tjs,
const geo::TPCID tpcid 
)

Definition at line 1215 of file TCVertex.cxx.

References tca::TjStuff::allTraj, CompleteIncomplete3DVertices(), CompleteIncomplete3DVerticesInGaps(), detinfo::DetectorProperties::ConvertTicksToX(), detinfo::DetectorProperties::ConvertXToTicks(), geo::CryostatID::Cryostat, debug, DecodeCTP(), tca::TjStuff::detprop, tca::TjStuff::fHits, FindCloseHits(), tca::TjStuff::geom, geo::GeometryCore::HasWire(), tca::SortEntry::index, geo::GeometryCore::IntersectionPoint(), kAllHits, kKilled, kTjHiVx3Score, evd::kWire, geo::kX, tca::TjStuff::NumPlanes, tca::TjStuff::NumWires, tca::DebugStuff::Plane, geo::PlaneID::Plane, PrintAllTraj(), PrintHit(), tca::Vtx3Store::Score, SetVx2Score(), SetVx3Score(), tca::DebugStuff::Tick, geo::TPCID::TPC, tca::Vtx3Store::TPCID, tca::TjStuff::UnitsPerTick, tca::SortEntry::val, valIncreasing(), tca::TjStuff::Vertex3DCuts, tca::TjStuff::vtx, tca::TjStuff::vtx3, tca::Vtx3Store::Vx2ID, tca::VtxStore::Vx3ID, tca::Vtx3Store::Wire, geo::GeometryCore::WireCoordinate(), geo::GeometryCore::WirePitch(), tca::Vtx3Store::X, tca::Vtx3Store::XErr, y, tca::Vtx3Store::Y, tca::Vtx3Store::YErr, tca::TjStuff::YHi, tca::Vtx3Store::Z, z, tca::Vtx3Store::ZErr, and tca::TjStuff::ZHi.

Referenced by tca::TrajClusterAlg::RunTrajClusterAlg().

1216  {
1217  // Create 3D vertices from 2D vertices. 3D vertices that are matched
1218  // in all three planes have Vtx2ID > 0 for all planes. This function re-scores all
1219  // 2D and 3D vertices and flags Tjs that have high-score 3D vertices
1220 
1221  if(tjs.Vertex3DCuts[0] < 0) return;
1222  if(tjs.vtx.size() < 2) return;
1223 
1224  const unsigned int cstat = tpcid.Cryostat;
1225  const unsigned int tpc = tpcid.TPC;
1226 
1227  // create a array/vector of 2D vertex indices in each plane
1228  std::vector<std::vector<unsigned short>> vIndex(3);
1229  for(unsigned short ivx = 0; ivx < tjs.vtx.size(); ++ivx) {
1230  // obsolete vertex
1231  if(tjs.vtx[ivx].ID == 0) continue;
1232  geo::PlaneID planeID = DecodeCTP(tjs.vtx[ivx].CTP);
1233  if(planeID.TPC != tpc || planeID.Cryostat != cstat) continue;
1234  unsigned short plane = planeID.Plane;
1235  if(plane > 2) continue;
1236  vIndex[plane].push_back(ivx);
1237  }
1238 
1239  unsigned short vtxInPln = 0;
1240  for(unsigned short plane = 0; plane < tjs.NumPlanes; ++plane) if(vIndex[plane].size() > 0) ++vtxInPln;
1241  if(vtxInPln < 2) return;
1242 
1243  bool prt = (debug.Plane >= 0) && (debug.Tick == 2222);
1244 
1245  float thirdPlanedXCut = 2 * tjs.Vertex3DCuts[0];
1246 
1247  if(prt) {
1248  mf::LogVerbatim("TC")<<"Inside Find3DVertices. dX cut "<<tjs.Vertex3DCuts[0]<<" thirdPlanedXCut "<<thirdPlanedXCut;
1249  PrintAllTraj("F3DV", tjs, debug, USHRT_MAX, tjs.allTraj.size());
1250  }
1251 
1252  // wire spacing in cm
1253  float wirePitch = tjs.geom->WirePitch(0, tpcid.TPC, tpcid.Cryostat);
1254 
1255  size_t vsize = tjs.vtx.size();
1256  // vector of 2D vertices -> 3D vertices.
1257  std::vector<short> vPtr(vsize, -1);
1258  // fill temp vectors of 2D vertex X and X errors
1259  std::vector<float> vX(vsize, -100);
1260 
1261  for(unsigned short ivx = 0; ivx < vsize; ++ivx) {
1262  if(tjs.vtx[ivx].ID == 0) continue;
1263  geo::PlaneID planeID = DecodeCTP(tjs.vtx[ivx].CTP);
1264  if(planeID.TPC != tpc || planeID.Cryostat != cstat) continue;
1265  int plane = planeID.Plane;
1266  if(tjs.vtx[ivx].Pos[0] < -0.4) continue;
1267  unsigned int wire = std::nearbyint(tjs.vtx[ivx].Pos[0]);
1268  if(!tjs.geom->HasWire(geo::WireID(cstat, tpc, plane, wire))) continue;
1269  // Convert 2D vertex time error to X error
1270  double ticks = tjs.vtx[ivx].Pos[1] / tjs.UnitsPerTick;
1271  vX[ivx] = tjs.detprop->ConvertTicksToX(ticks, plane, (int)tpc, (int)cstat);
1272  } // ivx
1273 
1274  // temp vector of all 2D vertex matches
1275  std::vector<Vtx3Store> v3temp;
1276 
1277  TrajPoint tp;
1278  float maxScore = 0;
1279  constexpr float maxSep = 4;
1280  // i, j, k indicates 3 different wire planes
1281  // compare vertices in each view
1282  for(unsigned short ipl = 0; ipl < 2; ++ipl) {
1283  for(unsigned short ii = 0; ii < vIndex[ipl].size(); ++ii) {
1284  unsigned short ivx = vIndex[ipl][ii];
1285  if(vX[ivx] < 0) continue;
1286  auto& ivx2 = tjs.vtx[ivx];
1287  if(ivx2.Pos[0] < -0.4) continue;
1288  unsigned int iWire = std::nearbyint(ivx2.Pos[0]);
1289  for(unsigned short jpl = ipl + 1; jpl < 3; ++jpl) {
1290  for(unsigned short jj = 0; jj < vIndex[jpl].size(); ++jj) {
1291  unsigned short jvx = vIndex[jpl][jj];
1292  if(vX[jvx] < 0) continue;
1293  auto& jvx2 = tjs.vtx[jvx];
1294  if(jvx2.Pos[0] < -0.4) continue;
1295  unsigned int jWire = std::nearbyint(jvx2.Pos[0]);
1296  float dX = std::abs(vX[ivx] - vX[jvx]);
1297  if(dX > tjs.Vertex3DCuts[0]) continue;
1298  if(prt) {
1299  mf::LogVerbatim("TC")<<"F3DV: ipl "<<ipl<<" i2V"<<ivx2.ID<<" iX "<<vX[ivx]
1300  <<" jpl "<<jpl<<" j2V"<<jvx2.ID<<" jvX "<<vX[jvx]<<" W:T "<<(int)jvx2.Pos[0]<<":"<<(int)jvx2.Pos[1]<<" dX "<<dX;
1301  }
1302  double y = -1000, z = -1000;
1303  tjs.geom->IntersectionPoint(iWire, jWire, ipl, jpl, cstat, tpc, y, z);
1304  if(y < tjs.YLo || y > tjs.YHi || z < tjs.ZLo || z > tjs.ZHi) continue;
1305  unsigned short kpl = 3 - ipl - jpl;
1306  float kX = 0.5 * (vX[ivx] + vX[jvx]);
1307  int kWire = -1;
1308  if(tjs.NumPlanes > 2) {
1309  kWire = (int)(tjs.geom->WireCoordinate(y, z, kpl, tpc, cstat) + 0.5);
1310  if(kWire < 0 || (unsigned int)kWire > tjs.NumWires[kpl]) continue;
1311  if(!tjs.geom->HasWire(geo::WireID(cstat, tpc, kpl, kWire))) continue;
1312  std::array<int, 2> wireWindow;
1313  std::array<float, 2> timeWindow;
1314  wireWindow[0] = kWire - maxSep;
1315  wireWindow[1] = kWire + maxSep;
1316  float time = tjs.detprop->ConvertXToTicks(kX, kpl, (int)tpc, (int)cstat) * tjs.UnitsPerTick;
1317  timeWindow[0] = time - maxSep;
1318  timeWindow[1] = time + maxSep;
1319  bool hitsNear;
1320  std::vector<unsigned int> closeHits = FindCloseHits(tjs, wireWindow, timeWindow, kpl, kAllHits, true, hitsNear);
1321  if(prt) {
1322  mf::LogVerbatim myprt("TC");
1323  myprt<<" Hits near "<<kpl<<":"<<kWire<<":"<<(int)(time/tjs.UnitsPerTick)<<" = ";
1324  for(auto iht : closeHits) myprt<<" "<<PrintHit(tjs.fHits[iht]);
1325  }
1326  if(!hitsNear) continue;
1327  } // 3-plane TPC
1328 /* Don't require a Tj near this position. Look for hits instead
1329  if(tjs.NumPlanes > 2) {
1330  kWire = (int)(tjs.geom->WireCoordinate(y, z, kpl, tpc, cstat) + 0.5);
1331  if(kWire < 0 || (unsigned int)kWire > tjs.NumWires[kpl]) continue;
1332  if(!tjs.geom->HasWire(geo::WireID(cstat, tpc, kpl, kWire))) continue;
1333  tp.Pos[0] = kWire;
1334  // See if there is a wire signal nearby in kpl
1335  tp.Pos[1] = tjs.detprop->ConvertXToTicks(kX, kpl, tpc, cstat) * tjs.UnitsPerTick;
1336  tp.CTP = EncodeCTP(cstat, tpc, kpl);
1337  auto tjlist = FindCloseTjs(tjs, tp, tp, maxSep);
1338  if(prt) {
1339  mf::LogVerbatim myprt("TC");
1340  myprt<<" Tjs near "<<kpl<<":"<<PrintPos(tjs, tp);
1341  for(auto tjid : tjlist) myprt<<" T"<<tjid;
1342  }
1343  if(tjlist.empty()) continue;
1344  }
1345 */
1346  // save this incomplete 3D vertex
1347  Vtx3Store v3d;
1348  v3d.Vx2ID[ipl] = ivx + 1;
1349  v3d.Vx2ID[jpl] = jvx + 1;
1350  v3d.Vx2ID[kpl] = 0;
1351  // see if this is already in the list
1352  bool gotit = false;
1353  for(unsigned short i3t = 0; i3t < v3temp.size(); ++i3t) {
1354  if(v3temp[i3t].Vx2ID[0] == v3d.Vx2ID[0] && v3temp[i3t].Vx2ID[1] == v3d.Vx2ID[1] && v3temp[i3t].Vx2ID[2] == v3d.Vx2ID[2]) {
1355  gotit = true;
1356  break;
1357  }
1358  } // i3t
1359  if(gotit) continue;
1360  v3d.X = kX;
1361  // Use XErr to store dX
1362  v3d.XErr = dX;
1363  v3d.Y = y;
1364  v3d.Z = z;
1365  v3d.Wire = kWire;
1366  v3d.Score = dX / tjs.Vertex3DCuts[0];
1367  v3d.TPCID = tpcid;
1368  // push the incomplete vertex onto the list
1369  v3temp.push_back(v3d);
1370 
1371  if(prt) mf::LogVerbatim("TC")<<"F3DV: 2 Plane match i2V"<<tjs.vtx[ivx].ID<<" P:W:T "<<ipl<<":"<<(int)tjs.vtx[ivx].Pos[0]<<":"<<(int)tjs.vtx[ivx].Pos[1]<<" j2V"<<tjs.vtx[jvx].ID<<" P:W:T "<<jpl<<":"<<(int)tjs.vtx[jvx].Pos[0]<<":"<<(int)tjs.vtx[jvx].Pos[1]<<" dX "<<dX;
1372 
1373  if(tjs.NumPlanes == 2) continue;
1374 
1375  // look for a 3 plane match
1376  for(unsigned short kk = 0; kk < vIndex[kpl].size(); ++kk) {
1377  unsigned short kvx = vIndex[kpl][kk];
1378  if(vX[kvx] < 0) continue;
1379  float dX = std::abs(vX[kvx] - v3d.X);
1380  // Wire difference error
1381  float dW = wirePitch * std::abs(tjs.vtx[kvx].Pos[0] - kWire);
1382  if(prt) mf::LogVerbatim("TC")<<" k2V"<<kvx+1<<" dX "<<dX<<" dW "<<dW;
1383  if(dX > thirdPlanedXCut) continue;
1384  if(dW > tjs.Vertex3DCuts[1]) continue;
1385  // put the Y,Z difference in YErr and ZErr
1386  double y = -1000, z = -1000;
1387  tjs.geom->IntersectionPoint(iWire, kWire, ipl, kpl, cstat, tpc, y, z);
1388  v3d.YErr = y - v3d.Y;
1389  v3d.ZErr = z - v3d.Z;
1390  v3d.Vx2ID[kpl] = kvx + 1;
1391  v3d.Wire = -1;
1392  // hijack the Score variable to hold the separation^2, weighted by the
1393  // vertex3DCuts
1394  dX = (vX[kvx] - v3d.X) / tjs.Vertex3DCuts[0];
1395  float dY = v3d.YErr / tjs.Vertex3DCuts[1];
1396  float dZ = v3d.ZErr / tjs.Vertex3DCuts[1];
1397  v3d.Score = dX * dX + dY * dY + dZ * dZ;
1398  if(v3d.Score > maxScore) maxScore = v3d.Score;
1399  v3temp.push_back(v3d);
1400  } // kk
1401  } // jj
1402  } // jpl
1403  } // ii
1404  } // ipl
1405 
1406  if(v3temp.empty()) return;
1407 
1408  // We will sort this list by increasing score. First add the maxScore for 2-plane matches so that
1409  // they are considered after the 3-plane matches
1410  maxScore += 1;
1411  for(auto& v3 : v3temp) if(v3.Wire >= 0) v3.Score += maxScore;
1412 
1413  if(prt) {
1414  mf::LogVerbatim("TC")<<"v3temp list";
1415  for(auto& v3 : v3temp) {
1416  mf::LogVerbatim("TC")<<v3.Vx2ID[0]<<" "<<v3.Vx2ID[1]<<" "<<v3.Vx2ID[2]<<" wire "<<v3.Wire<<" "<<v3.Score;
1417  } // v3
1418  }
1419  SortEntry sEntry;
1420  std::vector<SortEntry> sortVec(v3temp.size());
1421  for(unsigned short ivx = 0; ivx < v3temp.size(); ++ivx) {
1422  sEntry.index = ivx;
1423  sEntry.val = v3temp[ivx].Score;
1424  sortVec[ivx] = sEntry;
1425  } // ivx
1426  if(sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(), valIncreasing);
1427  // create a new vector of selected 3D vertices
1428  std::vector<Vtx3Store> v3sel;
1429  for(unsigned short ii = 0; ii < sortVec.size(); ++ii) {
1430  unsigned short ivx = sortVec[ii].index;
1431  // ensure that all 2D vertices are unique
1432  bool skipit = false;
1433  for(auto& v3 : v3sel) {
1434  for(unsigned short ipl = 0; ipl < tjs.NumPlanes; ++ipl) {
1435  if(v3temp[ivx].Vx2ID[ipl] == 0) continue;
1436  if(v3temp[ivx].Vx2ID[ipl] == v3.Vx2ID[ipl]) {
1437  skipit = true;
1438  break;
1439  }
1440  } // ipl
1441  if(skipit) break;
1442  } // v3
1443  if(skipit) continue;
1444  v3sel.push_back(v3temp[ivx]);
1445  } // ii
1446  v3temp.clear();
1447 
1448  if(prt) {
1449  mf::LogVerbatim("TC")<<"v3sel list";
1450  for(auto& v3d : v3sel) {
1451  mf::LogVerbatim("TC")<<v3d.Vx2ID[0]<<" "<<v3d.Vx2ID[1]<<" "<<v3d.Vx2ID[2]<<" wire "<<v3d.Wire<<" "<<v3d.Score;
1452  } // v3d
1453  }
1454 
1455  // Count the number of incomplete vertices and store
1456  unsigned short ninc = 0;
1457  for(auto& vx3 : v3sel) {
1458  if(tjs.NumPlanes == 2) {
1459  vx3.Vx2ID[2] = 666;
1460  } else {
1461  if(vx3.Wire >= 0) ++ninc;
1462  }
1463  vx3.ID = tjs.vtx3.size() + 1;
1464  if(prt) mf::LogVerbatim("TC")<<" 3V"<<vx3.ID<<" 2V"<<vx3.Vx2ID[0]<<" 2V"<<vx3.Vx2ID[1]<<" 2V"<<vx3.Vx2ID[2]
1465  <<" wire "<<vx3.Wire;
1466  tjs.vtx3.push_back(vx3);
1467  // make the 2D -> 3D associations
1468  for(unsigned short ipl = 0; ipl < tjs.NumPlanes; ++ipl) {
1469  if(vx3.Vx2ID[ipl] == 0) continue;
1470  VtxStore& vx2 = tjs.vtx[vx3.Vx2ID[ipl]-1];
1471  vx2.Vx3ID = vx3.ID;
1472  } // ipl
1473  } // ivx
1474 
1475  // Try to complete incomplete vertices
1476  if(ninc > 0) {
1478  CompleteIncomplete3DVertices(tjs, tpcid);
1479  }
1480 
1481  // Score and flag Tjs that are attached to high-score vertices
1482  // First remove Tj vertex flags
1483  for(auto& tj : tjs.allTraj) {
1484  if(tj.AlgMod[kKilled]) continue;
1485  geo::PlaneID planeID = DecodeCTP(tj.CTP);
1486  if(planeID.TPC != tpc || planeID.Cryostat != cstat) continue;
1487  tj.AlgMod[kTjHiVx3Score] = false;
1488  } // tj
1489  // Score the 2D vertices
1490  for(auto& vx2 : tjs.vtx) {
1491  if(vx2.ID == 0) continue;
1492  geo::PlaneID planeID = DecodeCTP(vx2.CTP);
1493  if(planeID.TPC != tpc || planeID.Cryostat != cstat) continue;
1494  SetVx2Score(tjs, vx2, prt);
1495  } // vx2
1496  // and the 3D vertices
1497  for(auto& vx3 : tjs.vtx3) {
1498  if(vx3.ID == 0) continue;
1499  if(vx3.TPCID != tpcid) continue;
1500  SetVx3Score(tjs, vx3, prt);
1501  } // vx3
1502 
1503  } // Find3DVertices
void SetVx3Score(TjStuff &tjs, Vtx3Store &vx3, bool prt)
Definition: TCVertex.cxx:2303
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< unsigned int > FindCloseHits(TjStuff const &tjs, std::array< int, 2 > const &wireWindow, Point2_t const &timeWindow, const unsigned short plane, HitStatus_t hitRequest, bool usePeakTime, bool &hitsNear)
Definition: Utils.cxx:2362
static unsigned int kWire
unsigned int index
Definition: TCShower.cxx:5
void CompleteIncomplete3DVertices(TjStuff &tjs, const geo::TPCID &tpcid)
Definition: TCVertex.cxx:2569
void PrintAllTraj(std::string someText, const TjStuff &tjs, const DebugStuff &debug, unsigned short itj, unsigned short ipt, bool prtVtx)
Definition: Utils.cxx:4232
Float_t y
Definition: compare.C:6
Double_t z
Definition: plot.C:279
Planes which measure X direction.
Definition: geo_types.h:81
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
bool valIncreasing(SortEntry c1, SortEntry c2)
Definition: TCVertex.cxx:11
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
DebugStuff debug
Definition: DebugStruct.cxx:4
int Plane
Select plane.
Definition: DebugStruct.h:29
std::string PrintHit(const TCHit &hit)
Definition: Utils.cxx:4732
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
void CompleteIncomplete3DVerticesInGaps(TjStuff &tjs, const geo::TPCID &tpcid)
Definition: TCVertex.cxx:2478
int Tick
Select hit PeakTime for debugging (< 0 for vertex finding)
Definition: DebugStruct.h:32
float val
Definition: Utils.cxx:8
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
void SetVx2Score(TjStuff &tjs, VtxStore &vx2, bool prt)
Definition: TCVertex.cxx:2331
void tca::FindAlongTrans ( Point2_t  pos1,
Vector2_t  dir1,
Point2_t  pos2,
Point2_t alongTrans 
)

Definition at line 2741 of file Utils.cxx.

References DotProd(), E, and SetMag().

2742  {
2743  // Calculate the distance along and transverse to the direction vector dir1 from pos1 to pos2
2744  alongTrans[0] = 0;
2745  alongTrans[1] = 0;
2746  if(pos1[0] == pos2[0] && pos1[1] == pos2[1]) return;
2747  pos1[0] = pos2[0] - pos1[0];
2748  pos1[1] = pos2[1] - pos1[1];
2749  double sep = sqrt(pos1[0] * pos1[0] + pos1[1] * pos1[1]);
2750  if(sep < 1E-6) return;
2751  Vector2_t ptDir;
2752  ptDir[0] = pos1[0] / sep;
2753  ptDir[1] = pos1[1] / sep;
2754  SetMag(dir1, 1.0);
2755  double costh = DotProd(dir1, ptDir);
2756  if(costh > 1.0 || costh < -1.0) return;
2757  alongTrans[0] = costh * sep;
2758  double sinth = sqrt(1 - costh * costh);
2759  alongTrans[1] = sinth * sep;
2760  } // FindAlongTrans
Float_t E
Definition: plot.C:23
bool SetMag(Vector2_t &v1, double mag)
Definition: Utils.cxx:2729
std::array< double, 2 > Vector2_t
Definition: DataStructs.h:38
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:60
void tca::FindAlongTrans ( Point3_t  pos1,
Vector3_t  dir1,
Point3_t  pos2,
Point2_t alongTrans 
)

Definition at line 2751 of file PFPUtils.cxx.

References DotProd(), E, PointDirection(), PosSep(), and SetMag().

Referenced by DotProd(), FindCompleteness(), FindParent(), FollowTp3s(), InShowerProb(), MergeSubShowers(), ParentFOM(), and tca::TruthMatcher::StudyShowerParents().

2752  {
2753  // Calculate the distance along and transvers to the direction vector from pos1 to pos2
2754  alongTrans[0] = 0;
2755  alongTrans[1] = 0;
2756  if(pos1[0] == pos2[0] && pos1[1] == pos2[1] && pos1[2] == pos2[2]) return;
2757  auto ptDir = PointDirection(pos1, pos2);
2758  SetMag(dir1, 1.0);
2759  double costh = DotProd(dir1, ptDir);
2760  if(costh > 1) return;
2761  double sep = PosSep(pos1, pos2);
2762  if(sep < 1E-6) return;
2763  alongTrans[0] = costh * sep;
2764  double sinth = sqrt(1 - costh * costh);
2765  alongTrans[1] = sinth * sep;
2766  } // FindAlongTrans
Float_t E
Definition: plot.C:23
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:1614
bool SetMag(Vector3_t &v1, double mag)
Definition: PFPUtils.cxx:1641
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:60
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
std::vector< unsigned int > tca::FindCloseHits ( TjStuff const &  tjs,
std::array< int, 2 > const &  wireWindow,
Point2_t const &  timeWindow,
const unsigned short  plane,
HitStatus_t  hitRequest,
bool  usePeakTime,
bool &  hitsNear 
)

Definition at line 2362 of file Utils.cxx.

References tca::TjStuff::fHits, tca::TjStuff::FirstWire, kAllHits, kUnusedHits, kUsedHits, tca::TjStuff::LastWire, tca::TjStuff::UnitsPerTick, and tca::TjStuff::WireHitRange.

Referenced by tca::TrajClusterAlg::AddLAHits(), tca::TrajClusterAlg::ChkStopEndPts(), Find3DVertices(), tca::TrajClusterAlg::FindVtxTraj(), tca::TrajClusterAlg::FixTrajBegin(), and tca::TrajClusterAlg::ReversePropagate().

2363  {
2364  // returns a vector of hits that are within the Window[Pos0][Pos1] in plane.
2365  // Note that hits on wire wireWindow[1] are returned as well. The definition of close
2366  // depends on setting of usePeakTime. If UsePeakTime is true, a hit is considered nearby if
2367  // the PeakTime is within the window. This is shown schematically here where
2368  // the time is on the horizontal axis and a "-" denotes a valid entry
2369  // timeWindow -----------------
2370  // hit PeakTime + close
2371  // hit PeakTime + not close
2372  // If usePeakTime is false, a hit is considered nearby if the hit StartTick and EndTick overlap with the timeWindow
2373  // Time window ---------
2374  // Hit StartTick-EndTick -------- close
2375  // Hit StartTick - EndTick -------- not close
2376 
2377  hitsNear = false;
2378  std::vector<unsigned int> closeHits;
2379  if(plane > tjs.FirstWire.size() - 1) return closeHits;
2380  // window in the wire coordinate
2381  int loWire = wireWindow[0];
2382  if(loWire < (int)tjs.FirstWire[plane]) loWire = tjs.FirstWire[plane];
2383  int hiWire = wireWindow[1];
2384  if(hiWire > (int)tjs.LastWire[plane]-1) hiWire = tjs.LastWire[plane]-1;
2385  // window in the time coordinate
2386  float minTick = timeWindow[0] / tjs.UnitsPerTick;
2387  float maxTick = timeWindow[1] / tjs.UnitsPerTick;
2388  for(int wire = loWire; wire <= hiWire; ++wire) {
2389  // Set hitsNear if the wire is dead
2390  if(tjs.WireHitRange[plane][wire].first == -2) hitsNear = true;
2391  if(tjs.WireHitRange[plane][wire].first < 0) continue;
2392  unsigned int firstHit = (unsigned int)tjs.WireHitRange[plane][wire].first;
2393  unsigned int lastHit = (unsigned int)tjs.WireHitRange[plane][wire].second;
2394  for(unsigned int iht = firstHit; iht < lastHit; ++iht) {
2395  if(tjs.fHits[iht].InTraj == INT_MAX) continue;
2396  if(usePeakTime) {
2397  if(tjs.fHits[iht].PeakTime < minTick) continue;
2398  if(tjs.fHits[iht].PeakTime > maxTick) break;
2399  } else {
2400  int hiLo = minTick;
2401  if(tjs.fHits[iht].StartTick > hiLo) hiLo = tjs.fHits[iht].StartTick;
2402  int loHi = maxTick;
2403  if(tjs.fHits[iht].EndTick < loHi) loHi = tjs.fHits[iht].EndTick;
2404  if(loHi < hiLo) continue;
2405  if(hiLo > loHi) break;
2406  }
2407  hitsNear = true;
2408  bool takeit = (hitRequest == kAllHits);
2409  if(hitRequest == kUsedHits && tjs.fHits[iht].InTraj > 0) takeit = true;
2410  if(hitRequest == kUnusedHits && tjs.fHits[iht].InTraj == 0) takeit = true;
2411  if(takeit) closeHits.push_back(iht);
2412  } // iht
2413  } // wire
2414  return closeHits;
2415  } // FindCloseHits
bool tca::FindCloseHits ( TjStuff const &  tjs,
TrajPoint tp,
float const &  maxDelta,
HitStatus_t  hitRequest 
)

Definition at line 2418 of file Utils.cxx.

References tca::TrajPoint::CTP, DecodeCTP(), tca::TjStuff::fHits, tca::TjStuff::FirstWire, tca::TrajPoint::Hits, kAllHits, kUnusedHits, kUsedHits, tca::TjStuff::LastWire, geo::PlaneID::Plane, PointTrajDOCA(), tca::TrajPoint::Pos, tca::TjStuff::UnitsPerTick, tca::TrajPoint::UseHit, tca::TjStuff::WireHitRange, and WireHitRangeOK().

Referenced by ChgFracNearPos().

2419  {
2420  // Fills tp.Hits sets tp.UseHit true for hits that are close to tp.Pos. Returns true if there are
2421  // close hits OR if the wire at this position is dead
2422 
2423  tp.Hits.clear();
2424  tp.UseHit.reset();
2425  if(!WireHitRangeOK(tjs, tp.CTP)) {
2426 // std::cout<<"FindCloseHits: WireHitRange not valid for CTP "<<tp.CTP<<". tjs.WireHitRange Cstat "<<tjs.TPCID.Cryostat<<" TPC "<<tjs.TPCID.TPC<<"\n";
2427  return false;
2428  }
2429 
2430  geo::PlaneID planeID = DecodeCTP(tp.CTP);
2431  unsigned short ipl = planeID.Plane;
2432  if(tp.Pos[0] < -0.4) return false;
2433  unsigned int wire = std::nearbyint(tp.Pos[0]);
2434  if(wire < tjs.FirstWire[ipl]) return false;
2435  if(wire > tjs.LastWire[ipl]-1) return false;
2436 
2437  // dead wire
2438  if(tjs.WireHitRange[ipl][wire].first == -1) return true;
2439  // live wire with no hits
2440  if(tjs.WireHitRange[ipl][wire].first == -2) return false;
2441 
2442  unsigned int firstHit = (unsigned int)tjs.WireHitRange[ipl][wire].first;
2443  unsigned int lastHit = (unsigned int)tjs.WireHitRange[ipl][wire].second;
2444 
2445  float fwire = wire;
2446  for(unsigned int iht = firstHit; iht < lastHit; ++iht) {
2447  if(tjs.fHits[iht].InTraj == INT_MAX) continue;
2448  bool useit = (hitRequest == kAllHits);
2449  if(hitRequest == kUsedHits && tjs.fHits[iht].InTraj > 0) useit = true;
2450  if(hitRequest == kUnusedHits && tjs.fHits[iht].InTraj == 0) useit = true;
2451  if(!useit) continue;
2452  float ftime = tjs.UnitsPerTick * tjs.fHits[iht].PeakTime;
2453  float delta = PointTrajDOCA(tjs, fwire, ftime, tp);
2454  if(delta < maxDelta) tp.Hits.push_back(iht);
2455  } // iht
2456  if(tp.Hits.size() > 16) {
2457  tp.Hits.resize(16);
2458  }
2459  // Set UseHit false. The calling routine should decide if these hits should be used
2460  tp.UseHit.reset();
2461  return true;
2462 
2463  } // FindCloseHits
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
float PointTrajDOCA(TjStuff const &tjs, float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2147
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
bool WireHitRangeOK(const TjStuff &tjs, const CTP_t &inCTP)
Definition: Utils.cxx:3886
std::vector< int > tca::FindCloseTjs ( const TjStuff tjs,
const TrajPoint fromTp,
const TrajPoint toTp,
const float &  maxDelta 
)

Definition at line 2466 of file Utils.cxx.

References tca::TjStuff::allTraj, tca::TrajPoint::CTP, DecodeCTP(), tca::TjStuff::fHits, tca::TjStuff::FirstWire, tca::TjStuff::LastWire, MakeBareTrajPoint(), MoveTPToWire(), geo::PlaneID::Plane, tca::TrajPoint::Pos, tmp, tca::TjStuff::UnitsPerTick, and tca::TjStuff::WireHitRange.

Referenced by MakeJunkVertices().

2467  {
2468  // Returns a list of Tj IDs that have hits within distance maxDelta on a line drawn between the two Tps as shown
2469  // graphically here, where a "*" is a Tp and "|" and "-" are the boundaries of the region that is checked
2470  //
2471  // ---------------
2472  // | |
2473  // * *
2474  // | |
2475  // ---------------
2476  // If the wire positions of fromTp and toTp are the same, a different region is checked as shown here
2477  //
2478  // -----------
2479  // | |
2480  // | * |
2481  // | |
2482  // -----------
2483 
2484  std::vector<int> tmp;
2485  if(fromTp.Pos[0] < -0.4 || toTp.Pos[0] < -0.4) return tmp;
2486 
2487  TrajPoint tp;
2488  // Make the tp so that stepping is positive
2489  unsigned int firstWire, lastWire;
2490  if(toTp.Pos[0] > fromTp.Pos[0]) {
2491  if(!MakeBareTrajPoint(tjs, fromTp, toTp, tp)) return tmp;
2492  firstWire = std::nearbyint(fromTp.Pos[0]);
2493  lastWire = std::nearbyint(toTp.Pos[0]);
2494  } else if(toTp.Pos[0] < fromTp.Pos[0]) {
2495  if(!MakeBareTrajPoint(tjs, toTp, fromTp, tp)) return tmp;
2496  firstWire = std::nearbyint(toTp.Pos[0]);
2497  lastWire = std::nearbyint(fromTp.Pos[0]);
2498  } else {
2499  tp.Pos = fromTp.Pos;
2500  float tmp = fromTp.Pos[0] - maxDelta;
2501  if(tmp < 0) tmp = 0;
2502  firstWire = std::nearbyint(tmp);
2503  tmp = fromTp.Pos[0] + maxDelta;
2504  lastWire = std::nearbyint(tmp);
2505  }
2506 
2507  geo::PlaneID planeID = DecodeCTP(tp.CTP);
2508  unsigned short ipl = planeID.Plane;
2509 
2510  if(firstWire < tjs.FirstWire[ipl]) firstWire = tjs.FirstWire[ipl];
2511  if(firstWire > tjs.LastWire[ipl]-1) return tmp;
2512  if(lastWire < tjs.FirstWire[ipl]) return tmp;
2513  if(lastWire > tjs.LastWire[ipl]-1) lastWire = tjs.LastWire[ipl]-1;
2514 
2515  for(unsigned int wire = firstWire; wire <= lastWire; ++wire) {
2516  if(tjs.WireHitRange[ipl][wire].first == -1) continue;
2517  if(tjs.WireHitRange[ipl][wire].first == -2) continue;
2518  MoveTPToWire(tp, (float)wire);
2519  // Find the tick range at this position
2520  float minTick = (tp.Pos[1] - maxDelta) / tjs.UnitsPerTick;
2521  float maxTick = (tp.Pos[1] + maxDelta) / tjs.UnitsPerTick;
2522  unsigned int firstHit = (unsigned int)tjs.WireHitRange[ipl][wire].first;
2523  unsigned int lastHit = (unsigned int)tjs.WireHitRange[ipl][wire].second;
2524  for(unsigned int iht = firstHit; iht < lastHit; ++iht) {
2525  if(tjs.fHits[iht].InTraj <= 0) continue;
2526  if((unsigned int)tjs.fHits[iht].InTraj > tjs.allTraj.size()) continue;
2527  if(tjs.fHits[iht].PeakTime < minTick) continue;
2528  // Hits are sorted by increasing time so we can break when maxTick is reached
2529  if(tjs.fHits[iht].PeakTime > maxTick) break;
2530  if(std::find(tmp.begin(), tmp.end(), tjs.fHits[iht].InTraj) != tmp.end()) continue;
2531  tmp.push_back(tjs.fHits[iht].InTraj);
2532  } // iht
2533  } // wire
2534 
2535  return tmp;
2536 
2537  } // FindCloseTjs
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
Float_t tmp
Definition: plot.C:37
bool MakeBareTrajPoint(const TjStuff &tjs, const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
Definition: Utils.cxx:3536
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2351
void tca::FindCompleteness ( TjStuff tjs,
PFPStruct pfp,
bool  doFit,
bool  fillTp3s,
bool  prt 
)

Definition at line 593 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, tca::TrajPoint3::AlongTrans, geo::CryostatID::Cryostat, DecodeCTP(), dir, tca::TrajPoint3::Dir, tca::PFPStruct::Dir, tca::PFPStruct::EffPur, trkf::fill(), FindAlongTrans(), Fit3D(), tca::TjStuff::geom, tca::PFPStruct::ID, MakeTp3(), tca::TjStuff::mallTraj, tca::TjStuff::Match3DCuts, tca::TjStuff::NumPlanes, geo::PlaneID::Plane, tca::TrajPoint3::Pos, tca::TrajPoint3::Tj2Pts, tca::PFPStruct::TjCompleteness, tca::PFPStruct::TjIDs, tmp, tca::PFPStruct::Tp3s, geo::TPCID::TPC, geo::GeometryCore::WireCoordinate(), tca::TjStuff::WireHitRange, and tca::PFPStruct::XYZ.

Referenced by DefinePFP(), and FindPFParticles().

594  {
595  // Calculate the 3D-matching completeness of the set of Tjs in pfp.TjIDs and store in pfp.EffPur.
596  // The completeness for each Tj is put in pfp.TjCompleteness. The TP-weighted average completeness
597  // is put in pfp.EffPur. This function also fits the matching points to a 3D line and puts the
598  // position and direction in pfp.XYZ[0] and pfp.Dir[0]. The absolute value of the linear correlation
599  // coefficients are averaged and stored in pfp.AspecRatio. The pfp.TP3s vector is optionally filled.
600 
601  if(pfp.TjIDs.size() < 2) return;
602  if(tjs.Match3DCuts[0] <= 0) return;
603  // This function uses mallTraj but it isn't necessarily a failure if it doesn't exist
604  if(tjs.mallTraj.size() < 6) return;
605 
606  pfp.TjCompleteness.resize(pfp.TjIDs.size());
607  std::fill(pfp.TjCompleteness.begin(), pfp.TjCompleteness.end(), 0);
608  if(fillTp3s) pfp.Tp3s.clear();
609 
610  bool twoPlanes = (tjs.NumPlanes == 2);
611  bool twoTjs = (pfp.TjIDs.size() == 2);
612  // decide if special handling of small angle pfps is required when filling Tp3s
613  bool smallAngle = false;
614  if(fillTp3s) {
615  smallAngle = (pfp.Dir[0][0] != 0 && std::abs(pfp.Dir[0][0]) < 0.1);
616 // if(pfp.Dir[0][0] == 0 && tjs.DebugMode) std::cout<<"P"<<pfp.ID<<" Dir[0] isn't defined\n";
617  }
618  double yzcut = 1.5 * tjs.Match3DCuts[0];
619 
620  // initialize the fit sums
621  Point3_t point;
622  Vector3_t dir;
623  if(doFit) Fit3D(0, point, dir, point, dir);
624 
625  // create a vector of bools for each tj for points that are matched in 3D
626  // cast the IDs into an unsigned short for faster comparing
627  std::vector<unsigned short> tjids(pfp.TjIDs.size());
628  // This vector is for matches in 3 planes
629  std::vector<std::vector<bool>> tjptMat3;
630  // This vector is for matches in 2 planes
631  std::vector<std::vector<bool>> tjptMat2;
632  // and the plane index
633  std::vector<unsigned short> tjplane;
634  // Set a maximum size for the TP3s vector
635  unsigned int maxTp3Size = 10000;
636  // Initialize the vectors
637  for(unsigned short itj = 0; itj < pfp.TjIDs.size(); ++itj) {
638  if(pfp.TjIDs[itj] <= 0) {
639  std::cout<<"FindCompleteness: Bad tjid "<<pfp.TjIDs[itj]<<"\n";
640  return;
641  }
642  tjids[itj] = pfp.TjIDs[itj];
643  auto& tj = tjs.allTraj[pfp.TjIDs[itj] - 1];
644  std::vector<bool> tmp(tj.Pts.size(), false);
645  tjptMat2.push_back(tmp);
646  if(!twoPlanes) tjptMat3.push_back(tmp);
647  tjplane.push_back(DecodeCTP(tj.CTP).Plane);
648  } // tjid
649 
650  for(unsigned int ipt = 0; ipt < tjs.mallTraj.size() - 1; ++ipt) {
651  auto& iTjPt = tjs.mallTraj[ipt];
652  unsigned short indx = 0;
653  for(indx = 0; indx < tjids.size(); ++indx) if(iTjPt.id == tjids[indx]) break;
654  // require that the Tj ID of this point be in the list
655  if(indx == tjids.size()) continue;
656  auto& itj = tjs.allTraj[iTjPt.id - 1];
657 // if(itj.AlgMod[kMat3D]) continue;
658  auto& itp = itj.Pts[iTjPt.ipt];
659  unsigned short iplane = DecodeCTP(itp.CTP).Plane;
660  unsigned short tpc = DecodeCTP(itp.CTP).TPC;
661  unsigned short cstat = DecodeCTP(itp.CTP).Cryostat;
662  for(unsigned int jpt = ipt + 1; jpt < tjs.mallTraj.size() - 1; ++jpt) {
663  auto& jTjPt = tjs.mallTraj[jpt];
664  // ensure that the planes are different
665  if(jTjPt.ctp == iTjPt.ctp) continue;
666  unsigned short jndx = 0;
667  for(jndx = 0; jndx < tjids.size(); ++jndx) if(jTjPt.id == tjids[jndx]) break;
668  // require that the Tj ID of this point be in the list
669  if(jndx == tjids.size()) continue;
670  // check for x range overlap. We know that jTjPt.xlo is > iTjPt.xlo because of the sort
671  if(jTjPt.xlo > iTjPt.xhi) continue;
672  // break out if the x range difference becomes large (5 cm)
673  if(jTjPt.xlo > iTjPt.xhi + 5) break;
674  auto& jtj = tjs.allTraj[jTjPt.id - 1];
675 // if(jtj.AlgMod[kMat3D]) continue;
676  auto& jtp = jtj.Pts[jTjPt.ipt];
677  TrajPoint3 ijtp3;
678  if(!MakeTp3(tjs, itp, jtp, ijtp3, true)) continue;
679  ijtp3.Tj2Pts.resize(2);
680  ijtp3.Tj2Pts[0] = iTjPt;
681  ijtp3.Tj2Pts[1] = jTjPt;
682  // Set the 2-plane match bits
683  tjptMat2[indx][iTjPt.ipt] = true;
684  tjptMat2[jndx][jTjPt.ipt] = true;
685  if(twoPlanes) {
686  if(fillTp3s && pfp.Tp3s.size() < maxTp3Size) {
687  bool saveIt = true;
688  FindAlongTrans(pfp.XYZ[0], pfp.Dir[0], ijtp3.Pos, ijtp3.AlongTrans);
689  // cut on transverse distance
690  if(smallAngle) saveIt = ijtp3.AlongTrans[1] < 1;
691  if(saveIt) pfp.Tp3s.push_back(ijtp3);
692  }
693  if(doFit) Fit3D(1, ijtp3.Pos, ijtp3.Dir, point, dir);
694  continue;
695  }
696  // count it as a triple if this point is in a dead region
697  unsigned short jplane = DecodeCTP(jtp.CTP).Plane;
698  unsigned short kplane = 3 - iplane - jplane;
699  float fwire = tjs.geom->WireCoordinate(ijtp3.Pos[1], ijtp3.Pos[2], kplane, tpc, cstat);
700  if(fwire < -0.4) continue;
701  unsigned int kwire = std::nearbyint(fwire);
702  if(kwire < tjs.WireHitRange[kplane].size() && tjs.WireHitRange[kplane][kwire].first == -1) {
703  // accumulate the fit sums
704  if(doFit) Fit3D(1, ijtp3.Pos, ijtp3.Dir, point, dir);
705  // fill Tp3s?
706  if(fillTp3s && pfp.Tp3s.size() < maxTp3Size) {
707  bool saveIt = true;
708  FindAlongTrans(pfp.XYZ[0], pfp.Dir[0], ijtp3.Pos, ijtp3.AlongTrans);
709  if(smallAngle) saveIt = ijtp3.AlongTrans[1] < 1;
710  if(saveIt) pfp.Tp3s.push_back(ijtp3);
711  }
712  continue;
713  } // dead wire in kplane
714  for(unsigned int kpt = jpt + 1; kpt < tjs.mallTraj.size(); ++kpt) {
715  auto& kTjPt = tjs.mallTraj[kpt];
716  // ensure that the planes are different
717  if(kTjPt.ctp == iTjPt.ctp || kTjPt.ctp == jTjPt.ctp) continue;
718  // Look for this tj point in tjids
719  unsigned short kndx = 0;
720  for(kndx = 0; kndx < tjids.size(); ++kndx) if(kTjPt.id == tjids[kndx]) break;
721  // require that the Tj ID of this point be in the list if we aren't filling the Tp3s
722  if(!fillTp3s && kndx == tjids.size()) continue;
723  if(kTjPt.xlo > iTjPt.xhi) continue;
724  // break out if the x range difference becomes large
725  if(kTjPt.xlo > iTjPt.xhi + 5) break;
726  auto& ktj = tjs.allTraj[kTjPt.id - 1];
727 // if(ktj.AlgMod[kMat3D]) continue;
728  auto& ktp = ktj.Pts[kTjPt.ipt];
729  TrajPoint3 iktp3;
730  if(!MakeTp3(tjs, itp, ktp, iktp3, true)) continue;
731  if(std::abs(ijtp3.Pos[1] - iktp3.Pos[1]) > yzcut) continue;
732  if(std::abs(ijtp3.Pos[2] - iktp3.Pos[2]) > yzcut) continue;
733  // make a copy of ijtp3 -> ijktp3
734  auto ijktp3 = ijtp3;
735  // add the Tj2Pt to it
736  ijktp3.Tj2Pts.push_back(kTjPt);
737  // accumulate the fit sums
738  if(doFit) Fit3D(1, iktp3.Pos, iktp3.Dir, point, dir);
739  // fill Tp3s?
740  if(fillTp3s && pfp.Tp3s.size() < maxTp3Size) {
741  // update the charge
742  ijktp3.dEdx = (2 * ijktp3.dEdx + ktp.Chg) / 3;
743  bool saveIt = true;
744  FindAlongTrans(pfp.XYZ[0], pfp.Dir[0], ijktp3.Pos, ijktp3.AlongTrans);
745  if(smallAngle) saveIt = ijktp3.AlongTrans[1] < 1;
746  if(saveIt) pfp.Tp3s.push_back(ijktp3);
747  }
748  // Set the 3-plane match bits
749  if(kndx == tjids.size()) continue;
750  tjptMat3[indx][iTjPt.ipt] = true;
751  tjptMat3[jndx][jTjPt.ipt] = true;
752  tjptMat3[kndx][kTjPt.ipt] = true;
753  } // kpt
754  } // jpt
755  } // ipt
756  // do the fit and put the results into the pfp
757  Fit3D(2, point, dir, pfp.XYZ[0], pfp.Dir[0]);
758  if(prt && doFit) {
759  mf::LogVerbatim myprt("TC");
760  myprt<<"FC: P"<<pfp.ID<<" fit pos "<<std::fixed<<std::setprecision(1)<<pfp.XYZ[0][0]<<" "<<pfp.XYZ[0][1]<<" "<<pfp.XYZ[0][2];
761  myprt<<" fit dir "<<std::setprecision(2)<<pfp.Dir[0][0]<<" "<<pfp.Dir[0][1]<<" "<<pfp.Dir[0][2];
762  myprt<<" Note: fit pos is the average position of all Tp3s - not the start or end.";
763  }
764  // now count the number of tj points were matched
765  // total number of points with charge in all Tjs
766  float tnpwc = 0;
767  // total number that are matched in 3D in 3 planes
768  float tcnt3 = 0;
769  // total number that are matched in 3D in 2 planes
770  float tcnt2 = 0;
771  for(unsigned short itj = 0; itj < tjids.size(); ++itj) {
772  auto& tj = tjs.allTraj[tjids[itj] - 1];
773  // counts for each tj
774  float npwc = 0;
775  float cnt2 = 0;
776  float cnt3 = 0;
777  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
778  if(tj.Pts[ipt].Chg <= 0) continue;
779  ++npwc;
780  if(tjptMat2[itj][ipt]) ++cnt2;
781  if(!twoPlanes && tjptMat3[itj][ipt]) ++cnt3;
782  } // ipt
783  if(twoTjs) {
784  pfp.TjCompleteness[itj] = cnt2 / npwc;
785  } else {
786  pfp.TjCompleteness[itj] = cnt3 / npwc;
787  }
788  tnpwc += npwc;
789  tcnt3 += cnt3;
790  tcnt2 += cnt2;
791  if(prt) {
792  mf::LogVerbatim myprt("TC");
793  myprt<<"FC: P"<<pfp.ID<<" T"<<tj.ID<<" npwc "<<npwc<<" cnt2 "<<cnt2<<" cnt3 "<<cnt3<<" PDGCode "<<tj.PDGCode;
794  myprt<<" MCSMom "<<tj.MCSMom<<" InShower? "<<tj.SSID;
795  myprt<<" TjCompleteness "<<std::setprecision(2)<<pfp.TjCompleteness[itj];
796  } // prt
797  } // itj
798  if(twoTjs) {
799  pfp.EffPur = tcnt2 / tnpwc;
800  } else {
801  pfp.EffPur = tcnt3 / tnpwc;
802  }
803 
804  } // FindCompleteness
void Fit3D(unsigned short mode, Point3_t point, Vector3_t dir, Point3_t &fitPos, Vector3_t &fitDir)
Definition: PFPUtils.cxx:899
std::array< double, 3 > Point3_t
Definition: DataStructs.h:35
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:2751
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
Float_t tmp
Definition: plot.C:37
bool MakeTp3(TjStuff &tjs, const TrajPoint &itp, const TrajPoint &jtp, TrajPoint3 &tp3, bool findDirection)
Definition: PFPUtils.cxx:1526
void fill(const art::PtrVector< recob::Hit > &hits, int only_plane)
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
TDirectory * dir
Definition: macro.C:5
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
std::array< double, 3 > Vector3_t
Definition: DataStructs.h:36
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
void tca::FindCots ( std::string  inFcnLabel,
TjStuff tjs,
const CTP_t inCTP,
std::vector< std::vector< int >> &  tjLists,
bool  prt 
)

Definition at line 3485 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::TjStuff::ChargeCuts, DontCluster(), GetAssns(), greaterThan(), tca::Trajectory::ID, kKilled, kMat3D, kShowerLike, kShowerTj, tca::Trajectory::MCSMom, MCSMom(), NumPtsWithCharge(), PFPDOCA(), tca::TjStuff::pfps, PosSep(), SetIntersection(), ShowerEnergy(), tca::TjStuff::ShowerTag, t1, t2, tmp, TrajTrajDOCA(), and tca::TjStuff::WirePitch.

Referenced by FindShowers3D().

3486  {
3487  // Version 2 of TagShowerLike to try to improve the separation between close showers, e.g. from pi-zeros
3488  tjLists.clear();
3489  if(tjs.ShowerTag[0] <= 0) return;
3490 
3491  // take the average of the low and high charge RMS range to use as a cut
3492  float typicalChgRMS = 0.5 * (tjs.ChargeCuts[1] + tjs.ChargeCuts[2]);
3493 
3494  // clear out old tags and make a list of Tjs to consider
3495  std::vector<int> tjids;
3496  for(auto& tj : tjs.allTraj) {
3497  if(tj.CTP != inCTP) continue;
3498  if(tj.AlgMod[kKilled]) continue;
3499  tj.AlgMod[kShowerLike] = false;
3500  if(tj.AlgMod[kShowerTj]) continue;
3501  short npwc = NumPtsWithCharge(tjs, tj, false);
3502  // Don't expect any (primary) electron to be reconstructed as a single trajectory for
3503  // more than ~2 radiation lengths ~ 30 cm for uB ~ 100 wires
3504  if(npwc > 100) continue;
3505  // check MCSMom for longish Tjs
3506  if(npwc > 5) {
3507  // Increase the MCSMom cut if the Tj is long and the charge RMS is high to reduce sensitivity
3508  // to the fcl configuration. A primary electron may be reconstructed as one long Tj with large
3509  // charge rms and possibly high MCSMom or as several nearby shorter Tjs with lower charge rms
3510  float momCut = tjs.ShowerTag[1];
3511  if(tj.ChgRMS > typicalChgRMS) momCut *= tj.ChgRMS / typicalChgRMS;
3512  if(tj.MCSMom > momCut) continue;
3513  }
3514  // see if this tj is in a muon pfparticle that looks shower-like in this view
3515  if(tj.AlgMod[kMat3D]) {
3516  auto TInP = GetAssns(tjs, "T", tj.ID, "P");
3517  if(!TInP.empty()) {
3518  auto& pfp = tjs.pfps[TInP[0] - 1];
3519  if(pfp.PDGCode == 13 && MCSMom(tjs, pfp.TjIDs) > 500) continue;
3520  } // TInP not empty
3521  } // 3D-matched
3522  tjids.push_back(tj.ID);
3523  } // tj
3524 
3525  if(tjids.size() < 2) return;
3526 
3527  struct ClosePair {
3528  float doca; // distance of closest approach between the tj pair
3529  int id1; // id of the first tj
3530  int id2; // id of the second tj
3531  unsigned short closePt1; // index of the closest point on tj1
3532  unsigned short closePt2; // index of the closest point on tj2
3533  bool used; // set true when this pair is used
3534  };
3535  // min separation between tjs
3536  std::vector<ClosePair> cps;
3537  // list of tjs that are close
3538  std::vector<int> closeTjs;
3539  for(unsigned short it1 = 0; it1 < tjids.size() - 1; ++it1) {
3540  Trajectory& t1 = tjs.allTraj[tjids[it1] - 1];
3541  bool t1TrackLike = (t1.MCSMom > tjs.ShowerTag[1]);
3542  auto T1InP = GetAssns(tjs, "T", t1.ID, "P");
3543  for(unsigned short it2 = it1 + 1; it2 < tjids.size(); ++it2) {
3544  Trajectory& t2 = tjs.allTraj[tjids[it2] - 1];
3545  // require one of them to be not tracklike
3546  bool t2TrackLike = (t2.MCSMom > tjs.ShowerTag[1]);
3547  if(t1TrackLike && t2TrackLike) continue;
3548  unsigned short ipt1, ipt2;
3549  float doca = tjs.ShowerTag[2];
3550  // Find the separation between Tjs without considering dead wires
3551  TrajTrajDOCA(tjs, t1, t2, ipt1, ipt2, doca, false);
3552  if(doca == tjs.ShowerTag[2]) continue;
3553  // see if they are close in 3D if that information exists
3554  if(!T1InP.empty()) {
3555  auto T2InP = GetAssns(tjs, "T", t2.ID, "P");
3556  if(!T2InP.empty()) {
3557  auto& p1 = tjs.pfps[T1InP[0] - 1];
3558  auto& p2 = tjs.pfps[T2InP[0] - 1];
3559  unsigned short closePt1, closePt2;
3560  float doca = PFPDOCA(p1, p2, closePt1, closePt2);
3561 // float costh = DotProd(p1.Dir[0], p2.Dir[0]);
3562 // std::cout<<"chk T"<<t1.ID<<" T"<<t2.ID<<" doca "<<doca<<" costh "<<costh<<"\n";
3563  if(doca > tjs.ShowerTag[2] * tjs.WirePitch) continue;
3564  } // !T2InP.empty()
3565  } // !T1InP.empty()
3566 
3567  // add a new one
3568  ClosePair cp;
3569  cp.doca = doca;
3570  cp.id1 = t1.ID;
3571  cp.closePt1 = ipt1;
3572  cp.id2 = t2.ID;
3573  cp.closePt2 = ipt2;
3574  cp.used = false;
3575  cps.push_back(cp);
3576  if(std::find(closeTjs.begin(), closeTjs.end(), t1.ID) == closeTjs.end()) closeTjs.push_back(t1.ID);
3577  if(std::find(closeTjs.begin(), closeTjs.end(), t2.ID) == closeTjs.end()) closeTjs.push_back(t2.ID);
3578  } // it2 (t2)
3579  } // it1 (t1)
3580 
3581  if(cps.empty()) return;
3582 
3583  // sort tjList by decreasing length
3584  std::vector<SortEntry> sortVec(closeTjs.size());
3585  for(unsigned short ii = 0; ii < closeTjs.size(); ++ii) {
3586  sortVec[ii].index = ii;
3587  auto& tj = tjs.allTraj[closeTjs[ii] - 1];
3588  sortVec[ii].length = PosSep(tj.Pts[tj.EndPt[0]].Pos, tj.Pts[tj.EndPt[1]].Pos);
3589  } // ii
3590  std::sort(sortVec.begin(), sortVec.end(), greaterThan);
3591 
3592 
3593  // cluster them starting with the longest
3594  // a temp vector for DontCluster
3595  std::vector<int> tmp(1);
3596  for(unsigned short ii = 0; ii < sortVec.size(); ++ii) {
3597  unsigned short indx = sortVec[ii].index;
3598  auto& t1 = tjs.allTraj[closeTjs[indx] - 1];
3599  // already tagged?
3600  if(t1.AlgMod[kShowerLike]) continue;
3601 // float t1Len = sortVec[ii].length;
3602  // get the general direction
3603 // auto t1Dir = PointDirection(t1.Pts[t1.EndPt[0]].Pos, t1.Pts[t1.EndPt[1]].Pos);
3604  // start a list of clustered tjs
3605  std::vector<int> tlist;
3606  tlist.push_back(t1.ID);
3607  // try to add other close tjs
3608  bool added = true;
3609  while(added) {
3610  added = false;
3611  for(auto& cp : cps) {
3612  if(cp.used) continue;
3613  // is any ID in tlist equal to cp.id1 or cp.id2?
3614  bool isID1 = (std::find(tlist.begin(), tlist.end(), cp.id1) != tlist.end());
3615  bool isID2 = (std::find(tlist.begin(), tlist.end(), cp.id2) != tlist.end());
3616  if(!(isID1 || isID2)) continue;
3617  // determine which one is not in tlist and call it t2
3618  unsigned short t2id = cp.id1;
3619  if(isID1) t2id = cp.id2;
3620  auto& t2 = tjs.allTraj[t2id - 1];
3621  // already tagged?
3622  if(t2.AlgMod[kShowerLike]) continue;
3623  tmp[0] = t2.ID;
3624  if(DontCluster(tjs, tmp, tlist)) continue;
3625  // don't cluster if this tj is closer to another long tj
3626  bool isCloser = false;
3627  for(auto& pcp : cps) {
3628  if(t1.ID == pcp.id1 || t1.ID == pcp.id2) continue;
3629  if(!(t2.ID == pcp.id1 || t2.ID == pcp.id2)) continue;
3630  unsigned short oid = pcp.id1;
3631  if(oid == t2.ID) oid = pcp.id2;
3632  auto otj = tjs.allTraj[oid - 1];
3633  float otjLen = PosSep(otj.Pts[otj.EndPt[0]].Pos, otj.Pts[otj.EndPt[1]].Pos);
3634 // std::cout<<"tid1 T"<<t1.ID<<" tid2 T"<<t2.ID<<" oid T"<<oid<<"\n";
3635  if(pcp.doca < cp.doca && otjLen > 10) isCloser = true;
3636  } // pcp
3637  if(isCloser) continue;
3638  if(std::find(tlist.begin(), tlist.end(), t2.ID) != tlist.end()) continue;
3639 // std::cout<<" add T"<<t2.ID<<" to "<<tjLists.size()<<"\n";
3640  tlist.push_back(t2.ID);
3641  // call it used
3642  cp.used = true;
3643  added = true;
3644  } // cp
3645  } // added
3646  if(tlist.size() > 1) {
3647  // tag them
3648  for(auto tjid : tlist) {
3649  auto& tj = tjs.allTraj[tjid - 1];
3650  tj.AlgMod[kShowerLike] = true;
3651  } // tjid
3652  // ignore wimpy cots (< 10 MeV)
3653  if(ShowerEnergy(tjs, tlist) < 10) continue;
3654  tjLists.push_back(tlist);
3655  } // tlist.size() > 1
3656  } // ii
3657 /* This causes problems later on
3658  // Check for leftover tjs and add them if they are shower-like
3659  for(auto tjid : closeTjs) {
3660  auto& tj = tjs.allTraj[tjid - 1];
3661  if(tj.AlgMod[kShowerLike]) continue;
3662  std::vector<int> tlist(1, tjid);
3663  tj.AlgMod[kShowerLike] = true;
3664  // ignore wimpy cots (< 10 MeV)
3665  if(ShowerEnergy(tjs, tlist) < 10) continue;
3666  tjLists.push_back(tlist);
3667  } // tjid
3668 */
3669  if(tjLists.size() < 2) return;
3670  // check consistency
3671  for(unsigned short ip = 0; ip < tjLists.size() - 1; ++ip) {
3672  auto& ilist = tjLists[ip];
3673  for(unsigned short jp = ip + 1; jp < tjLists.size(); ++jp) {
3674  auto& jlist = tjLists[jp];
3675  auto sij = SetIntersection(ilist, jlist);
3676  if(!sij.empty()) {
3677  std::cout<<"******** FindCots conflict:";
3678  for(auto tid : sij) std::cout<<" T"<<tid;
3679  std::cout<<" appears in multiple lists\n";
3680  }
3681  } // jp
3682  } // ip
3683 /*
3684  std::cout<<"FindCots inCTP "<<inCTP<<" tjLists size "<<tjLists.size()<<"\n";
3685  for(unsigned short ip = 0; ip < tjLists.size(); ++ip) {
3686  auto& tlist = tjLists[ip];
3687  std::cout<<"ip "<<ip;
3688  for(auto tid : tlist) {
3689  std::cout<<" T"<<tid;
3690  auto plist = GetAssns(tjs, "T", tid, "P");
3691  if(!plist.empty()) std::cout<<"_P"<<plist[0];
3692  }
3693  std::cout<<"\n";
3694  } // ip
3695 */
3696 
3697  } // FindCots
bool greaterThan(SortEntry c1, SortEntry c2)
Definition: TCShower.cxx:9
TTree * t1
Definition: plottest35.C:26
float PFPDOCA(const PFPStruct &pfp1, const PFPStruct &pfp2, unsigned short &close1, unsigned short &close2)
Definition: PFPUtils.cxx:1761
Float_t tmp
Definition: plot.C:37
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:214
bool DontCluster(const TjStuff &tjs, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3381
float ShowerEnergy(const TjStuff &tjs, const std::vector< int > tjIDs)
Definition: TCShower.cxx:4447
TTree * t2
Definition: plottest35.C:36
short MCSMom(const TjStuff &tjs, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2837
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
unsigned short NumPtsWithCharge(const TjStuff &tjs, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1738
bool TrajTrajDOCA(const TjStuff &tjs, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2046
std::vector< int > GetAssns(const TjStuff &tjs, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4079
void tca::FindHammerVertices ( TjStuff tjs,
const CTP_t inCTP 
)

Definition at line 995 of file TCVertex.cxx.

References tca::TjStuff::allTraj, AttachAnyTrajToVertex(), tca::VtxStore::ChiDOF, tca::VtxStore::CTP, debug, DeltaAngle(), tca::VtxStore::ID, kHamVx, kJunkTj, kKilled, kShowerLike, tca::VtxStore::NTraj, tca::VtxStore::Pass, tca::DebugStuff::Plane, tca::VtxStore::Pos, SetPDGCode(), SetVx2Score(), SplitTraj(), StoreVertex(), tca::DebugStuff::Tick, tca::VtxStore::Topo, TrajPointTrajDOCA(), tca::TjStuff::UseAlg, and tca::TjStuff::vtx.

Referenced by Find2DVertices().

996  {
997  // Look for a trajectory that intersects another. Split
998  // the trajectory and make a vertex. The convention used
999  // is shown pictorially here. Trajectory tj1 must be longer
1000  // than tj2
1001  // tj2 ------
1002  // tj1 /
1003  // tj1 /
1004  // tj1 /
1005 
1006  if(!tjs.UseAlg[kHamVx]) return;
1007 
1008  bool prt = (debug.Plane >= 0 && debug.Tick == 55555);
1009 
1010  for(unsigned short it1 = 0; it1 < tjs.allTraj.size(); ++it1) {
1011  if(tjs.allTraj[it1].CTP != inCTP) continue;
1012  if(tjs.allTraj[it1].AlgMod[kKilled]) continue;
1013  if(tjs.allTraj[it1].AlgMod[kShowerLike]) continue;
1014  if(tjs.allTraj[it1].AlgMod[kJunkTj]) continue;
1015  // minimum length requirements
1016  unsigned short tj1len = tjs.allTraj[it1].EndPt[1] - tjs.allTraj[it1].EndPt[0];
1017  if(tj1len < 6) continue;
1018  // Check each end of tj1
1019  bool didaSplit = false;
1020  for(unsigned short end1 = 0; end1 < 2; ++end1) {
1021  // vertex assignment exists?
1022  if(tjs.allTraj[it1].VtxID[end1] > 0) continue;
1023  unsigned short endPt1 = tjs.allTraj[it1].EndPt[end1];
1024  for(unsigned short it2 = 0; it2 < tjs.allTraj.size(); ++it2) {
1025  if(tjs.allTraj[it2].CTP != inCTP) continue;
1026  if(it1 == it2) continue;
1027  if(tjs.allTraj[it2].AlgMod[kKilled]) continue;
1028  if(tjs.allTraj[it2].AlgMod[kJunkTj]) continue;
1029  // length of tj2 cut
1030  unsigned short tj2len = tjs.allTraj[it2].EndPt[1] - tjs.allTraj[it2].EndPt[0];
1031  if(tj2len < 10) continue;
1032  // ignore if tj1 is a lot shorter than tj2
1033  if(tj1len < 0.5 * tj2len) continue;
1034  // ignore very long straight trajectories (probably a cosmic muon)
1035  unsigned short end20 = tjs.allTraj[it2].EndPt[0];
1036  unsigned short end21 = tjs.allTraj[it2].EndPt[1];
1037  if(tj2len > 100 && DeltaAngle(tjs.allTraj[it2].Pts[end20].Ang, tjs.allTraj[it2].Pts[end21].Ang) < 0.2) continue;
1038  // Require no vertex associated with itj2
1039  if(tjs.allTraj[it2].VtxID[0] > 0 || tjs.allTraj[it2].VtxID[1] > 0) continue;
1040  float minDOCA = 3;
1041  float doca = minDOCA;
1042  unsigned short closePt2 = 0;
1043  TrajPointTrajDOCA(tjs, tjs.allTraj[it1].Pts[endPt1], tjs.allTraj[it2], closePt2, doca);
1044  if(doca == minDOCA) continue;
1045  // ensure that the closest point is not near an end
1046  if(prt) mf::LogVerbatim("TC")<<"FindHammerVertices: Candidate "<<tjs.allTraj[it1].ID<<" "<<tjs.allTraj[it2].ID<<" doca "<<doca<<" tj2.EndPt[0] "<<tjs.allTraj[it2].EndPt[0]<<" closePt2 "<<closePt2<<" tj2.EndPt[1] "<<tjs.allTraj[it2].EndPt[1];
1047  if(closePt2 < tjs.allTraj[it2].EndPt[0] + 3) continue;
1048  if(closePt2 > tjs.allTraj[it2].EndPt[1] - 3) continue;
1049  // make an angle cut
1050  float dang = DeltaAngle(tjs.allTraj[it1].Pts[endPt1].Ang, tjs.allTraj[it2].Pts[closePt2].Ang);
1051  if(prt) mf::LogVerbatim("TC")<<" dang "<<dang<<" imposing a hard cut of 0.4 for now ";
1052  if(dang < 0.4) continue;
1053  // we have a winner
1054  // create a new vertex
1055  VtxStore aVtx;
1056  aVtx.Pos = tjs.allTraj[it2].Pts[closePt2].Pos;
1057  aVtx.NTraj = 3;
1058  aVtx.Pass = tjs.allTraj[it2].Pass;
1059  aVtx.Topo = 5;
1060  aVtx.ChiDOF = 0;
1061  aVtx.CTP = inCTP;
1062  aVtx.ID = tjs.vtx.size() + 1;
1063  unsigned short ivx = tjs.vtx.size();
1064  if(!StoreVertex(tjs, aVtx)) continue;
1065  if(!SplitTraj(tjs, it2, closePt2, ivx, prt)) {
1066  if(prt) mf::LogVerbatim("TC")<<"FindHammerVertices: Failed to split trajectory";
1067  tjs.vtx.pop_back();
1068  continue;
1069  }
1070  tjs.allTraj[it1].VtxID[end1] = tjs.vtx[ivx].ID;
1071  tjs.allTraj[it1].AlgMod[kHamVx] = true;
1072  tjs.allTraj[it2].AlgMod[kHamVx] = true;
1073  unsigned short newTjIndex = tjs.allTraj.size() - 1;
1074  tjs.allTraj[newTjIndex].AlgMod[kHamVx] = true;
1075  AttachAnyTrajToVertex(tjs, ivx, prt);
1076  SetVx2Score(tjs, prt);
1077  // Update the PDGCode for the chopped trajectory
1078  SetPDGCode(tjs, it2);
1079  // and for the new trajectory
1080  SetPDGCode(tjs, newTjIndex);
1081  didaSplit = true;
1082  break;
1083  } // tj2
1084  if(didaSplit) break;
1085  } // end1
1086  } // tj1
1087 
1088  } // FindHammerVertices
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool AttachAnyTrajToVertex(TjStuff &tjs, unsigned short ivx, bool prt)
Definition: TCVertex.cxx:1689
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1607
bool SplitTraj(TjStuff &tjs, unsigned short itj, float XPos, bool makeVx2, bool prt)
Definition: Utils.cxx:1879
DebugStuff debug
Definition: DebugStruct.cxx:4
int Plane
Select plane.
Definition: DebugStruct.h:29
int Tick
Select hit PeakTime for debugging (< 0 for vertex finding)
Definition: DebugStruct.h:32
void SetPDGCode(TjStuff &tjs, unsigned short itj)
Definition: Utils.cxx:3697
bool StoreVertex(TjStuff &tjs, VtxStore &vx)
Definition: TCVertex.cxx:1911
void TrajPointTrajDOCA(TjStuff &tjs, TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
Definition: Utils.cxx:2026
void SetVx2Score(TjStuff &tjs, VtxStore &vx2, bool prt)
Definition: TCVertex.cxx:2331
void tca::FindHammerVertices2 ( TjStuff tjs,
const CTP_t inCTP 
)

Definition at line 819 of file TCVertex.cxx.

References tca::TjStuff::allTraj, AttachAnyTrajToVertex(), tca::VtxStore::ChiDOF, tca::VtxStore::CTP, debug, DeltaAngle(), dir, tca::VtxStore::ID, kHamVx, kHamVx2, kJunkTj, kKilled, kShowerLike, MCSMom(), MoveTPToWire(), tca::VtxStore::NTraj, NumPtsWithCharge(), tca::VtxStore::Pass, tca::DebugStuff::Plane, PointTrajDOCA(), tca::VtxStore::Pos, PosSep(), PrintPos(), SetPDGCode(), SetVx2Score(), SignalAtTp(), SplitTraj(), StoreVertex(), tca::DebugStuff::Tick, tmp, tca::VtxStore::Topo, TrajClosestApproach(), TrajIntersection(), TrajPointTrajDOCA(), tca::TjStuff::UnitsPerTick, tca::TjStuff::UseAlg, and tca::TjStuff::vtx.

Referenced by Find2DVertices().

820  {
821  // Variant of FindHammerVertices with slightly different requirements:
822  // 1) tj1 is a straight trajectory with most of the points fit
823  // 2) No angle requirement between tj1 and tj2
824  // 3) Large charge near the intersection point X on tj2
825  // tj2 ---X---
826  // tj1 /
827  // tj1 /
828  // tj1 /
829  // minimum^2 DOCA of tj1 endpoint with tj2
830 
831  if(!tjs.UseAlg[kHamVx2]) return;
832 
833  bool prt = (debug.Plane >= 0 && debug.Tick == 66666);
834  if(prt) mf::LogVerbatim("TC")<<"Inside FindHammerVertices2";
835 
836  for(unsigned short it1 = 0; it1 < tjs.allTraj.size(); ++it1) {
837  if(tjs.allTraj[it1].CTP != inCTP) continue;
838  if(tjs.allTraj[it1].AlgMod[kKilled]) continue;
839  if(tjs.allTraj[it1].AlgMod[kHamVx]) continue;
840  if(tjs.allTraj[it1].AlgMod[kHamVx2]) continue;
841  if(tjs.allTraj[it1].AlgMod[kJunkTj]) continue;
842  unsigned short numPtsWithCharge1 = NumPtsWithCharge(tjs, tjs.allTraj[it1], false);
843  if(numPtsWithCharge1 < 6) continue;
844  // Check each end of tj1
845  bool didaSplit = false;
846  for(unsigned short end1 = 0; end1 < 2; ++end1) {
847  // vertex assignment exists?
848  if(tjs.allTraj[it1].VtxID[end1] > 0) continue;
849  unsigned short endPt1 = tjs.allTraj[it1].EndPt[end1];
850  for(unsigned short it2 = 0; it2 < tjs.allTraj.size(); ++it2) {
851  if(it1 == it2) continue;
852  if(tjs.allTraj[it2].AlgMod[kKilled]) continue;
853  if(tjs.allTraj[it2].AlgMod[kHamVx]) continue;
854  if(tjs.allTraj[it2].AlgMod[kHamVx2]) continue;
855  // require that both be in the same CTP
856  if(tjs.allTraj[it2].CTP != inCTP) continue;
857  if(tjs.allTraj[it2].AlgMod[kShowerLike]) continue;
858  if(tjs.allTraj[it2].AlgMod[kJunkTj]) continue;
859  unsigned short numPtsWithCharge2 = NumPtsWithCharge(tjs, tjs.allTraj[it2], true);
860  if(numPtsWithCharge2 < 6) continue;
861  // ignore if tj1 is a lot shorter than tj2
862  // ignore if ChgRMS isn't known
863  // Jan 22. Try this
864 // if(tjs.allTraj[it2].ChgRMS == 0) continue;
865 // if(numPtsWithCharge1 < 0.2 * numPtsWithCharge2) continue;
866  // Find the minimum separation between tj1 and tj2
867  float minDOCA = 5;
868  float doca = minDOCA;
869  unsigned short closePt2 = 0;
870  TrajPointTrajDOCA(tjs, tjs.allTraj[it1].Pts[endPt1], tjs.allTraj[it2], closePt2, doca);
871  if(doca == minDOCA) continue;
872  if(prt) {
873  mf::LogVerbatim myprt("TC");
874  auto& tj1 = tjs.allTraj[it1];
875  auto& tj2 = tjs.allTraj[it2];
876  myprt<<" FHV2 CTP"<<tj1.CTP;
877  myprt<<" T"<<tj1.ID<<"_"<<end1<<" MCSMom "<<tj1.MCSMom<<" ChgRMS "<<tj1.ChgRMS;
878  myprt<<" split T"<<tj2.ID<<"? MCSMom "<<tj2.MCSMom<<" ChgRMS "<<tj2.ChgRMS;
879  myprt<<" doca "<<doca<<" tj2.EndPt[0] "<<tj2.EndPt[0]<<" closePt2 "<<closePt2;
880  myprt<<" tj2.EndPt[1] "<<tj2.EndPt[1];
881  } // prt
882  // ensure that the closest point is not near an end
883  if(closePt2 < tjs.allTraj[it2].EndPt[0] + 3) continue;
884  if(closePt2 > tjs.allTraj[it2].EndPt[1] - 3) continue;
885  // Find the intersection point between the tj1 end and tj2 closest Pt
886  float wint, tint;
887  TrajIntersection(tjs.allTraj[it1].Pts[endPt1], tjs.allTraj[it2].Pts[closePt2], wint, tint);
888  // make an angle cut
889  float dang = DeltaAngle(tjs.allTraj[it1].Pts[endPt1].Ang, tjs.allTraj[it2].Pts[closePt2].Ang);
890  if(dang < 0.2) continue;
891  // ensure that tj1 doesn't cross tj2 but ensuring that the closest point on tj1 is at closePt1
892  doca = 5;
893  unsigned short closePt1 = 0;
894  TrajPointTrajDOCA(tjs, tjs.allTraj[it2].Pts[closePt2], tjs.allTraj[it1], closePt1, doca);
895  if(closePt1 != endPt1) continue;
896  if(prt) mf::LogVerbatim("TC")<<" intersection W:T "<<(int)wint<<":"<<(int)(tint/tjs.UnitsPerTick)<<" dang "<<dang;
897  // Find the point on tj2 that is closest to this point, overwriting closePt
898  doca = minDOCA;
899  // the point on tj2 that is closest to the intersection point
900  unsigned short intPt2;
901  TrajClosestApproach(tjs.allTraj[it2], wint, tint, intPt2, doca);
902  if(prt) mf::LogVerbatim("TC")<<" intPt2 on tj2 "<<intPt2<<" at Pos "<<PrintPos(tjs, tjs.allTraj[it2].Pts[intPt2])<<" doca "<<doca;
903  if(doca == minDOCA) continue;
904  // find the MCSMom for both sections of tj2
905  float mcsmom = tjs.allTraj[it2].MCSMom;
906  float mcsmom1 = MCSMom(tjs, tjs.allTraj[it2], tjs.allTraj[it2].EndPt[0], intPt2);
907  float mcsmom2 = MCSMom(tjs, tjs.allTraj[it2], intPt2, tjs.allTraj[it2].EndPt[1]);
908  // require that the both MCSMoms be greater than
909  if(prt) mf::LogVerbatim("TC")<<" Check MCSMom after split: mcsmom1 "<<mcsmom1<<" mcsmom2 "<<mcsmom2;
910  if(mcsmom1 < mcsmom || mcsmom2 < mcsmom) continue;
911  // start scanning for the point on tj2 that has the best IP with the end of tj1 in the direction
912  // from closePt2 -> endPt2
913  short dir = 1;
914  if(intPt2 < closePt2) dir = -1;
915  unsigned short nit = 0;
916  unsigned short ipt = intPt2;
917  float mostChg = tjs.allTraj[it2].Pts[ipt].Chg;
918  if(prt) mf::LogVerbatim("TC")<<" ipt "<<ipt<<" at Pos "<<PrintPos(tjs, tjs.allTraj[it2].Pts[ipt])<<" chg "<<mostChg;
919  while(nit < 20) {
920  ipt += dir;
921  if(ipt < 3 || ipt > tjs.allTraj[it2].Pts.size() - 4) break;
922  float delta = PointTrajDOCA(tjs, tjs.allTraj[it2].Pts[ipt].Pos[0], tjs.allTraj[it2].Pts[ipt].Pos[1], tjs.allTraj[it1].Pts[endPt1]);
923  float sep = PosSep(tjs.allTraj[it2].Pts[ipt].Pos, tjs.allTraj[it1].Pts[endPt1].Pos);
924  float dang = delta / sep;
925  float pull = dang / tjs.allTraj[it1].Pts[endPt1].DeltaRMS;
926  // if(prt) mf::LogVerbatim("TC")<<" intPt2 "<<intPt2<<" at Pos "<<PrintPos(tjs, tjs.allTraj[it2].Pts[ipt])<<" delta "<<delta<<" chg "<<tjs.allTraj[it2].Pts[ipt].Chg<<" pull "<<pull;
927  if(pull < 2 && tjs.allTraj[it2].Pts[ipt].Chg > mostChg) {
928  mostChg = tjs.allTraj[it2].Pts[ipt].Chg;
929  intPt2 = ipt;
930  }
931  }
932  // require a lot of charge in tj2 in this vicinity compared with the average.
933  float chgPull = (mostChg - tjs.allTraj[it2].AveChg) / tjs.allTraj[it2].ChgRMS;
934  if(prt) mf::LogVerbatim("TC")<<" chgPull at intersection point "<<chgPull;
935  if(chgPull < 10) continue;
936  // require a signal on every wire between it1 and intPt2
937  TrajPoint ltp = tjs.allTraj[it1].Pts[endPt1];
938  if(tjs.allTraj[it1].Pts[endPt1].Pos[0] < -0.4) continue;
939  unsigned int fromWire = std::nearbyint(tjs.allTraj[it1].Pts[endPt1].Pos[0]);
940  if(tjs.allTraj[it2].Pts[intPt2].Pos[0] < -0.4) continue;
941  unsigned int toWire = std::nearbyint(tjs.allTraj[it2].Pts[intPt2].Pos[0]);
942  if(fromWire > toWire) {
943  unsigned int tmp = fromWire;
944  fromWire = toWire;
945  toWire = tmp;
946  }
947  bool skipIt = false;
948  for(unsigned int wire = fromWire + 1; wire < toWire; ++wire) {
949  MoveTPToWire(ltp, (float)wire);
950  if(!SignalAtTp(tjs, ltp)) {
951  skipIt = true;
952  break;
953  }
954  } // wire
955  if(skipIt) continue;
956  // we have a winner
957  // create a new vertex
958  VtxStore aVtx;
959  aVtx.Pos = tjs.allTraj[it2].Pts[intPt2].Pos;
960  aVtx.NTraj = 3;
961  aVtx.Pass = tjs.allTraj[it2].Pass;
962  aVtx.Topo = 6;
963  aVtx.ChiDOF = 0;
964  aVtx.CTP = inCTP;
965  aVtx.ID = tjs.vtx.size() + 1;
966  unsigned short ivx = tjs.vtx.size();
967  if(!StoreVertex(tjs, aVtx)) continue;
968  if(!SplitTraj(tjs, it2, intPt2, ivx, prt)) {
969  if(prt) mf::LogVerbatim("TC")<<"FHV2: Failed to split trajectory";
970  // we can just remove the vertex since no Tj VtxID association has been made yet
971  tjs.vtx.pop_back();
972  continue;
973  }
974  tjs.allTraj[it1].VtxID[end1] = tjs.vtx[ivx].ID;
975  tjs.allTraj[it1].AlgMod[kHamVx2] = true;
976  tjs.allTraj[it2].AlgMod[kHamVx2] = true;
977  unsigned short newTjIndex = tjs.allTraj.size() - 1;
978  tjs.allTraj[newTjIndex].AlgMod[kHamVx2] = true;
979  AttachAnyTrajToVertex(tjs, ivx, prt);
980  SetVx2Score(tjs, prt);
981  // Update the PDGCode for the chopped trajectory
982  SetPDGCode(tjs, it2);
983  // and for the new trajectory
984  SetPDGCode(tjs, newTjIndex);
985  if(prt) mf::LogVerbatim("TC")<<" FHV2: New vtx 2V"<<tjs.vtx[ivx].ID<<" Score "<<tjs.vtx[ivx].Score;
986  didaSplit = true;
987  break;
988  } // it2
989  if(didaSplit) break;
990  } // end1
991  } // it1
992  } // FindHammerVertices2
std::string PrintPos(const TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:4738
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool AttachAnyTrajToVertex(TjStuff &tjs, unsigned short ivx, bool prt)
Definition: TCVertex.cxx:1689
bool TrajClosestApproach(Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
Definition: Utils.cxx:2244
Float_t tmp
Definition: plot.C:37
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1607
bool SignalAtTp(TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:1639
bool SplitTraj(TjStuff &tjs, unsigned short itj, float XPos, bool makeVx2, bool prt)
Definition: Utils.cxx:1879
DebugStuff debug
Definition: DebugStruct.cxx:4
int Plane
Select plane.
Definition: DebugStruct.h:29
float PointTrajDOCA(TjStuff const &tjs, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2139
short MCSMom(const TjStuff &tjs, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2837
int Tick
Select hit PeakTime for debugging (< 0 for vertex finding)
Definition: DebugStruct.h:32
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
Definition: Utils.cxx:2166
TDirectory * dir
Definition: macro.C:5
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
unsigned short NumPtsWithCharge(const TjStuff &tjs, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1738
void SetPDGCode(TjStuff &tjs, unsigned short itj)
Definition: Utils.cxx:3697
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2351
bool StoreVertex(TjStuff &tjs, VtxStore &vx)
Definition: TCVertex.cxx:1911
void TrajPointTrajDOCA(TjStuff &tjs, TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
Definition: Utils.cxx:2026
void SetVx2Score(TjStuff &tjs, VtxStore &vx2, bool prt)
Definition: TCVertex.cxx:2331
std::vector< unsigned short > tca::FindKinks ( const TjStuff tjs,
PFPStruct pfp,
double  sep,
bool  prt 
)

Definition at line 1870 of file PFPUtils.cxx.

References KinkAngle(), PosSep2(), and tca::PFPStruct::Tp3s.

Referenced by DotProd(), and Split3DKink().

1871  {
1872  // returns a vector of indices in pfp.Tp3s where kinks exist. The kink angle is calculated using
1873  // Tp3s separated by +/- sep (cm)
1874  std::vector<unsigned short> kinkPts;
1875 // double kang = tjs.KinkCuts[0];
1876  // look for a kink angle greater than angCut
1877  double angCut = 0.3;
1878  double kang = 0;
1879  unsigned short kStart = USHRT_MAX;
1880  // foundKink is set true after a kink is found to skip past some number of points after the kink
1881  bool foundKink = false;
1882  double kinkSep2 = 2 * sep * sep;
1883  for(unsigned short ipt = 1; ipt < pfp.Tp3s.size(); ++ipt) {
1884  // skip ahead after a kink?
1885  if(foundKink) {
1886  // location of the previously found kink
1887  unsigned short kpt = kinkPts[kinkPts.size() - 1];
1888  if(foundKink && PosSep2(pfp.Tp3s[ipt].Pos, pfp.Tp3s[kpt].Pos) < kinkSep2) continue;
1889  }
1890  foundKink = false;
1891  double dang = KinkAngle(tjs, pfp.Tp3s, ipt, sep);
1892  if(dang < angCut && kStart == USHRT_MAX) continue;
1893  // found a kink larger than the cut. See if this is the onset of a kink
1894  if(kStart == USHRT_MAX) {
1895  // onset of a kink
1896  kStart = ipt;
1897  } else {
1898  // a kink was found. Keep scanning until delta angle (dang) is less than the maximum (kang)
1899  if(dang < kang) {
1900  unsigned short klen = ipt - kStart;
1901  if(prt) mf::LogVerbatim("TC")<<" findKinks: kink angle "<<kang<<" at point "<<ipt<<" klen "<<klen;
1902  kinkPts.push_back(ipt - 1);
1903  foundKink = true;
1904  kStart = USHRT_MAX;
1905  } // dang < kang
1906  } // kink found
1907  kang = dang;
1908  } // ipt
1909  return kinkPts;
1910  } // findKinks
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1631
double KinkAngle(const TjStuff &tjs, const std::vector< TrajPoint3 > &tp3s, unsigned short atPt, double sep)
Definition: PFPUtils.cxx:1913
void tca::FindMissedTjsInTp3s ( TjStuff tjs,
PFPStruct pfp,
std::vector< int > &  missTjs,
std::vector< float > &  missFrac 
)

Definition at line 807 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, geo::CryostatID::Cryostat, DecodeCTP(), tca::PFPStruct::Dir, EncodeCTP(), kKilled, kMat3D, MakeBareTP(), mat, tca::TjStuff::NumPlanes, geo::PlaneID::Plane, PosSep(), SharesHighScoreVx(), tca::PFPStruct::TjIDs, tca::PFPStruct::Tp3s, geo::TPCID::TPC, tca::PFPStruct::TPCID, and tca::PFPStruct::XYZ.

808  {
809  // compare the Tjs in pfp.TjIDs with the Tjs in Tp3s and return a list of Tjs
810  // in Tp3s that aren't in pfp.TjIDs
811  missTjs.clear();
812  missFrac.clear();
813  if(pfp.TjIDs.empty() || pfp.Tp3s.empty()) return;
814 
815  // determine the projection of the pfp direction vector in each plane.
816  // Don't try to merge if the projection is small
817  std::vector<float> projInPlane(tjs.NumPlanes);
818  for(unsigned short plane = 0; plane < tjs.NumPlanes; ++plane) {
819  CTP_t inCTP = EncodeCTP(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
820  auto tp = MakeBareTP(tjs, pfp.XYZ[0], pfp.Dir[0], inCTP);
821  projInPlane[plane] = tp.Delta;
822  } // plane
823 
824  std::vector<unsigned short> pfpTjs;
825  std::vector<unsigned short> usMissTjs;
826  std::vector<std::vector<bool>> misTjPtMat;
827  for(auto tjid : pfp.TjIDs) pfpTjs.push_back((unsigned short)tjid);
828  for(auto& tp3 : pfp.Tp3s) {
829  for(auto& tj2pt : tp3.Tj2Pts) {
830  if(std::find(pfpTjs.begin(), pfpTjs.end(), tj2pt.id) != pfpTjs.end()) continue;
831  // Tj isn't in pfp.TjIDs. See if we have it in the missed list
832  unsigned short mtjIndx = 0;
833  for(mtjIndx = 0; mtjIndx < usMissTjs.size(); ++mtjIndx) if(tj2pt.id == usMissTjs[mtjIndx]) break;
834  if(mtjIndx == usMissTjs.size()) {
835  // not in the misTjs list. Ensure that it isn't matched
836  auto& mtj = tjs.allTraj[tj2pt.id - 1];
837  if(mtj.AlgMod[kKilled] || mtj.AlgMod[kMat3D]) continue;
838  // add it to the list
839  usMissTjs.push_back(tj2pt.id);
840  // create the point match vector
841  std::vector<bool> ptMat(mtj.Pts.size(), false);
842  ptMat[tj2pt.ipt] = true;
843  misTjPtMat.push_back(ptMat);
844  } else {
845  if(tj2pt.ipt < misTjPtMat[mtjIndx].size()) misTjPtMat[mtjIndx][tj2pt.ipt] = true;
846  }
847  } // tj2pt
848  } // tp3
849  for(unsigned short im = 0; im < usMissTjs.size(); ++im) {
850  int mtjid = usMissTjs[im];
851  // calculate the fraction of points that are in Tp3s
852  float cnt = 0;
853  float mat = 0;
854  auto& mtj = tjs.allTraj[mtjid - 1];
855  // ignore if there is a high-score vertex between the missed tj and those in the pfp list
856  if(SharesHighScoreVx(tjs, pfp, mtj)) continue;
857  for(unsigned short ipt = mtj.EndPt[0]; ipt <= mtj.EndPt[1]; ++ipt) {
858  auto& mtp = mtj.Pts[ipt];
859  if(mtp.Chg <= 0) continue;
860  ++cnt;
861  if(misTjPtMat[im][ipt]) ++mat;
862  } // ipt
863  float frac = mat / cnt;
864  // ignore if low fraction matched
865  if(frac < 0.1) continue;
866  // ignore if this would only extend the tj in this plane by a small amount
867  float lenInPlane = 0;
868  for(auto tjid : pfp.TjIDs) {
869  auto& tj = tjs.allTraj[tjid - 1];
870  if(tj.CTP != mtj.CTP) continue;
871  float len = PosSep(tj.Pts[tj.EndPt[0]].Pos, tj.Pts[tj.EndPt[1]].Pos);
872  if(len > lenInPlane) lenInPlane = len;
873  } // tjid
874  if(cnt < 0.05 * lenInPlane) continue;
875  // check the direction vector projection in this plane
876  if(projInPlane[DecodeCTP(mtj.CTP).Plane] < 0.1) continue;
877  missTjs.push_back(mtjid);
878  missFrac.push_back(frac);
879  } // im
880  } // FindMissedTjsInTp3s
bool SharesHighScoreVx(TjStuff &tjs, const PFPStruct &pfp, const Trajectory &tj)
Definition: PFPUtils.cxx:883
TrajPoint MakeBareTP(TjStuff &tjs, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
Definition: Utils.cxx:3435
Float_t mat
Definition: plot.C:40
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
unsigned int CTP_t
Definition: DataStructs.h:41
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
void tca::FindNearbyTjs ( std::string  inFcnLabel,
TjStuff tjs,
ShowerStruct ss,
bool  prt 
)

Definition at line 3829 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::ShowerStruct::CTP, tca::ShowerStruct::Envelope, GetAssns(), tca::ShowerStruct::ID, kKilled, kShowerTj, tca::ShowerStruct::NearTjIDs, PointInsideEnvelope(), PointTrajDOCA(), tca::ShowerStruct::ShowerTjID, tca::ShowerStruct::TjIDs, TrajTrajDOCA(), and tca::TjStuff::vtx.

Referenced by FindShowers3D().

3830  {
3831  // Find Tjs that are near the shower but are not included in it
3832  ss.NearTjIDs.clear();
3833 
3834  // check for a valid envelope
3835  if(ss.Envelope.empty()) return;
3836  auto& stj = tjs.allTraj[ss.ShowerTjID - 1];
3837 
3838  std::string fcnLabel = inFcnLabel + ".FNTj";
3839 
3840  std::vector<int> ntj;
3841 
3842  // set max distance of closest approach ~ 5 radiation lengths ~200 WSE
3843  constexpr float fiveRadLen = 200;
3844 
3845  // look for vertices inside the envelope
3846  for(auto vx : tjs.vtx) {
3847  if(vx.CTP != ss.CTP) continue;
3848  if(vx.ID == 0) continue;
3849  if(!PointInsideEnvelope(vx.Pos, ss.Envelope)) continue;
3850 // auto vxTjIDs = GetVtxTjIDs(tjs, vx);
3851  auto vxTjIDs = GetAssns(tjs, "2V", vx.ID, "T");
3852  for(auto tjID : vxTjIDs) {
3853  // ignore those that are in the shower
3854  if(std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tjID) != ss.TjIDs.end()) continue;
3855  // or already in the list
3856  if(std::find(ntj.begin(), ntj.end(), tjID) != ntj.end()) continue;
3857  ntj.push_back(tjID);
3858  } // tjID
3859  } // vx
3860 
3861  // Check for tj points inside the envelope
3862  for(auto& tj : tjs.allTraj) {
3863  if(tj.CTP != ss.CTP) continue;
3864  if(tj.AlgMod[kKilled]) continue;
3865  // not a showerTj
3866  if(tj.AlgMod[kShowerTj]) continue;
3867  // make sure it's not in the shower
3868  if(std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tj.ID) != ss.TjIDs.end()) continue;
3869  // or already in the list
3870  if(std::find(ntj.begin(), ntj.end(), tj.ID) != ntj.end()) continue;
3871  // check proximity of long high MCSMom Tjs to the shower center
3872  if(tj.Pts.size() > 40 && tj.MCSMom > 200) {
3873  float delta = PointTrajDOCA(tjs, stj.Pts[1].Pos[0], stj.Pts[1].Pos[1], tj.Pts[tj.EndPt[0]]);
3874  // TODO: This could be done much better
3875  if(delta < 20) {
3876  float doca = fiveRadLen;
3877  unsigned short spt = 0, ipt = 0;
3878  TrajTrajDOCA(tjs, stj, tj, spt, ipt, doca);
3879  if(doca < fiveRadLen) {
3880  ntj.push_back(tj.ID);
3881  continue;
3882  }
3883  }
3884  } // long hi-MCSMom tj
3885  // don't need to check every point. Every third should be enough
3886  bool isInside = false;
3887  for(unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1]; ipt += 3) {
3888  if(PointInsideEnvelope(tj.Pts[ipt].Pos, ss.Envelope)) {
3889  isInside = true;
3890  break;
3891  }
3892  } // ipt
3893  // check the last point which was probably missed above
3894  if(!isInside) {
3895  unsigned short ipt = tj.EndPt[1];
3896  isInside = PointInsideEnvelope(tj.Pts[ipt].Pos, ss.Envelope);
3897  }
3898  if(isInside) ntj.push_back(tj.ID);
3899  } // tj
3900  if(ntj.size() > 1) std::sort(ntj.begin(), ntj.end());
3901  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Found "<<ntj.size()<<" Tjs near ss.ID "<<ss.ID;
3902  ss.NearTjIDs = ntj;
3903 
3904  } // FindNearbyTjs
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
Float_t ss
Definition: plot.C:23
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:2705
float PointTrajDOCA(TjStuff const &tjs, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2139
bool TrajTrajDOCA(const TjStuff &tjs, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2046
std::vector< int > GetAssns(const TjStuff &tjs, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4079
void tca::FindNeutralVertices ( TjStuff tjs,
const geo::TPCID tpcid 
)

Definition at line 369 of file TCVertex.cxx.

References tca::TjStuff::allTraj, ChgFracBetween(), ChgFracNearEnd(), CloseEnd(), tca::VtxStore::CTP, debug, dir, EncodeCTP(), evd::details::end(), FitVertex(), tca::VtxStore::ID, tca::Vtx3Store::ID, kVxNeutral, MakeBareTP(), tca::TjStuff::NeutralVxCuts, tca::TjStuff::NumPlanes, tca::TjStuff::pfps, tca::DebugStuff::Plane, PointDirIntersect(), tca::VtxStore::Pos, PosSep(), tca::Vtx3Store::Primary, PrintPos(), SetVx2Score(), SetVx3Score(), StoreVertex(), tca::DebugStuff::Tick, tca::VtxStore::Topo, tca::Vtx3Store::TPCID, geo::TPCID::TPCID(), tca::TjStuff::TPCID, tca::TjStuff::UseAlg, tca::TjStuff::vtx, tca::TjStuff::vtx3, tca::Vtx3Store::Vx2ID, tca::VtxStore::Vx3ID, tca::Vtx3Store::X, tca::TjStuff::XHi, tca::TjStuff::XLo, tca::Vtx3Store::Y, tca::TjStuff::YHi, tca::TjStuff::YLo, tca::Vtx3Store::Z, tca::TjStuff::ZHi, and tca::TjStuff::ZLo.

Referenced by tca::TrajClusterAlg::RunTrajClusterAlg().

370  {
371  // Look for 2D neutral vertices between Tjs
372  if(!tjs.UseAlg[kVxNeutral]) return;
373  if(tjs.NeutralVxCuts.size() < 4) return;
374  if(tjs.NumPlanes < 3) return;
375  if(tjs.pfps.size() < 2) return;
376 
377  bool prt = (debug.Plane >= 0 && debug.Tick == 88888);
378 
379  struct CandVx {
380  unsigned short ip1;
381  unsigned short end1;
382  unsigned short ip2;
383  unsigned short end2;
384  Point3_t intersect;
385  float sepSum;
386  bool isValid;
387  };
388  std::vector<CandVx> candVxs;
389 
390  for(unsigned short ip1 = 0; ip1 < tjs.pfps.size() - 1; ++ip1) {
391  auto& p1 = tjs.pfps[ip1];
392  if(p1.ID == 0) continue;
393  if(p1.Tp3s.empty()) continue;
394  if(p1.TPCID != tpcid) continue;
395  float len1 = PosSep(p1.XYZ[0], p1.XYZ[1]);
396  if(len1 < tjs.NeutralVxCuts[3]) continue;
397  for(unsigned short end1 = 0; end1 < 2; ++end1) {
398  float cfne1 = ChgFracNearEnd(tjs, p1, end1);
399  if(cfne1 < tjs.NeutralVxCuts[0]) continue;
400  for(unsigned short ip2 = ip1 + 1; ip2 < tjs.pfps.size(); ++ip2) {
401  auto& p2 = tjs.pfps[ip2];
402  if(p2.ID == 0) continue;
403  if(p2.Tp3s.empty()) continue;
404  if(p2.TPCID != tpcid) continue;
405  float len2 = PosSep(p2.XYZ[0], p2.XYZ[1]);
406  if(len2 < tjs.NeutralVxCuts[3]) continue;
407  for(unsigned short end2 = 0; end2 < 2; ++end2) {
408  float cfne2 = ChgFracNearEnd(tjs, p2, end2);
409  if(cfne2 < tjs.NeutralVxCuts[0]) continue;
410  float vxDOCA = 1E6;
411  Point3_t intersect;
412  if(!PointDirIntersect(p1.XYZ[end1], p1.Dir[end1], p2.XYZ[end2], p2.Dir[end2], intersect, vxDOCA)) continue;
413  if(intersect[0] < tjs.XLo || intersect[0] > tjs.XHi) continue;
414  if(intersect[1] < tjs.YLo || intersect[1] > tjs.YHi) continue;
415  if(intersect[2] < tjs.ZLo || intersect[2] > tjs.ZHi) continue;
416  // ensure that the pfp end and the vertex are consistent
417  float sep1 = PosSep(intersect, p1.XYZ[end1]);
418  if(PosSep(intersect, p1.XYZ[1-end1]) < sep1) continue;
419  float sep2 = PosSep(intersect, p2.XYZ[end2]);
420  if(PosSep(intersect, p2.XYZ[1-end2]) < sep2) continue;
421  if(vxDOCA > tjs.NeutralVxCuts[1]) continue;
422 /*
423  // find the DOCA between these two
424  unsigned short closePt1, closePt2;
425  float pfpDOCA = PFPDOCA(p1, p2, closePt1, closePt2);
426  if(closePt1 == USHRT_MAX) continue;
427 */
428  // ensure that there isn't a lot of charge between the end of each pfp and the intersection point
429  float cfb1 = ChgFracBetween(tjs, p1.XYZ[end1], intersect, p1.TPCID);
430  float cfb2 = ChgFracBetween(tjs, p2.XYZ[end2], intersect, p2.TPCID);
431  if(prt) {
432  mf::LogVerbatim myprt("TC");
433  myprt<<"FNV: P"<<p1.ID<<"_"<<end1<<" sep1 "<<std::fixed<<std::setprecision(2)<<sep1;
434  myprt<<" cfne1 "<<cfne1<<" cfb1 "<<cfb1;
435  myprt<<" P"<<p2.ID<<"_"<<end2<<" sep2 "<<sep2<<" cfne2 "<<cfne2<<" cfb2 "<<cfb2;
436  myprt<<" intersect "<<intersect[0]<<" "<<intersect[1]<<" "<<intersect[2];
437  myprt<<" vxDOCA "<<vxDOCA;
438  } // prt
439  if(cfb1 > tjs.NeutralVxCuts[2]) continue;
440  if(cfb2 > tjs.NeutralVxCuts[2]) continue;
441  // check existing candidates
442  float sepSum = sep1 + sep2;
443  bool skipit = false;
444  for(auto& candVx : candVxs) {
445  if(!candVx.isValid) continue;
446  if(candVx.ip1 != ip1 && candVx.ip2 != ip2) continue;
447  // see if the separation sum is smaller
448  if(sepSum < candVx.sepSum) {
449  // flag the saved one as not valid
450  candVx.isValid = false;
451  } else {
452  skipit = true;
453  break;
454  }
455  } // candVx
456  if(skipit) continue;
457  CandVx candVx;
458  candVx.ip1 = ip1;
459  candVx.end1 = end1;
460  candVx.ip2 = ip2;
461  candVx.end2 = end2;
462  candVx.intersect = intersect;
463  candVx.sepSum = sep1 + sep2;
464  candVx.isValid = true;
465  candVxs.push_back(candVx);
466  if(prt) mf::LogVerbatim("TC")<<" candidate";
467  } // end2
468  } // ip2
469  } // end1
470  } // ip1
471 
472  if(candVxs.empty()) return;
473 
474  // Make vertices with the valid candidates
475  for(auto& candVx : candVxs) {
476  if(!candVx.isValid) continue;
477  Vtx3Store vx3;
478  auto& p1 = tjs.pfps[candVx.ip1];
479  auto& p2 = tjs.pfps[candVx.ip2];
480  vx3.TPCID = p1.TPCID;
481  vx3.ID = tjs.vtx3.size() + 1;
482  // try to improve the vertex position by fitting the Tjs in 2D
483  std::vector<TrajPoint> vxTps;
484  Vector3_t dir = {{0, 0, 0}};
485  for(unsigned short plane = 0; plane < tjs.NumPlanes; ++plane) {
486  vxTps.clear();
487  CTP_t inCTP = EncodeCTP(p1.TPCID.Cryostat, p1.TPCID.TPC, plane);
488  // Need the position in this plane to find the closest end
489  auto vtp = MakeBareTP(tjs, candVx.intersect, dir, inCTP);
490  if(vtp.Pos[0] < 0) continue;
491  for(auto tid : p1.TjIDs) {
492  auto& tj = tjs.allTraj[tid - 1];
493  if(tj.CTP != vtp.CTP) continue;
494  unsigned short end = CloseEnd(tjs, tj, vtp.Pos);
495  auto vxTp = tj.Pts[tj.EndPt[end]];
496  vxTp.Step = tid;
497  vxTp.AngleCode = end;
498  vxTps.push_back(vxTp);
499  } // tid
500  for(auto tid : p2.TjIDs) {
501  auto& tj = tjs.allTraj[tid - 1];
502  if(tj.CTP != vtp.CTP) continue;
503  unsigned short end = CloseEnd(tjs, tj, vtp.Pos);
504  auto vxTp = tj.Pts[tj.EndPt[end]];
505  vxTp.Step = tid;
506  vxTp.AngleCode = end;
507  vxTps.push_back(vxTp);
508  } // tid
509  if(vxTps.size() < 2) continue;
510  VtxStore vx2;
511  vx2.CTP = inCTP;
512  vx2.Topo = 11;
513  if(!FitVertex(tjs, vx2, vxTps, prt)) {
514  if(prt) mf::LogVerbatim("TC")<<"FNV: vertex fit failed";
515  continue;
516  } // fit failed
517  vx2.ID = tjs.vtx.size() + 1;
518  for(auto& vxTp : vxTps) {
519  int tid = vxTp.Step;
520  auto& tj = tjs.allTraj[tid - 1];
521  tj.VtxID[vxTp.AngleCode] = vx2.ID;
522  }
523  if(prt) mf::LogVerbatim("TC")<<"FNV: 2V fit inCTP "<<inCTP<<" pos "<<PrintPos(tjs, vx2.Pos);
524  vx2.Vx3ID = vx3.ID;
525  vx3.Vx2ID[plane] = vx2.ID;
526  SetVx2Score(tjs, vx2, prt);
527  if(!StoreVertex(tjs, vx2)) {
528  if(prt) mf::LogVerbatim("TC")<<"FNV: store vertex failed";
529  continue;
530  } // StoreVertex failed
531  } // plane
532  vx3.X = candVx.intersect[0];
533  vx3.Y = candVx.intersect[1];
534  vx3.Z = candVx.intersect[2];
535  vx3.Primary = true;
536  SetVx3Score(tjs, vx3, prt);
537  tjs.vtx3.push_back(vx3);
538  if(prt) mf::LogVerbatim("TC")<<"FNV: P"<<p1.ID<<"_"<<candVx.end1<<" P"<<p2.ID<<"_"<<candVx.end2<<" -> 3V"<<vx3.ID;
539  } // candVx
540 
541  } // FindNeutralVertices
void SetVx3Score(TjStuff &tjs, Vtx3Store &vx3, bool prt)
Definition: TCVertex.cxx:2303
std::string PrintPos(const TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:4738
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::array< double, 3 > Point3_t
Definition: DataStructs.h:35
float ChgFracBetween(TjStuff &tjs, Point3_t pos1, Point3_t pos2, geo::TPCID tpcid)
Definition: PFPUtils.cxx:2860
bool FitVertex(TjStuff &tjs, VtxStore &vx, std::vector< TrajPoint > vxTp, bool prt)
Definition: TCVertex.cxx:1986
DebugStuff debug
Definition: DebugStruct.cxx:4
TrajPoint MakeBareTP(TjStuff &tjs, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
Definition: Utils.cxx:3435
int Plane
Select plane.
Definition: DebugStruct.h:29
unsigned short CloseEnd(TjStuff &tjs, const Trajectory &tj, const Point2_t &pos)
Definition: Utils.cxx:2120
bool PointDirIntersect(Point3_t p1, Vector3_t p1Dir, Point3_t p2, Vector3_t p2Dir, Point3_t &intersect, float &doca)
Definition: PFPUtils.cxx:2769
float ChgFracNearEnd(TjStuff &tjs, PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:2890
int Tick
Select hit PeakTime for debugging (< 0 for vertex finding)
Definition: DebugStruct.h:32
unsigned int CTP_t
Definition: DataStructs.h:41
TDirectory * dir
Definition: macro.C:5
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
std::array< double, 3 > Vector3_t
Definition: DataStructs.h:36
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool StoreVertex(TjStuff &tjs, VtxStore &vx)
Definition: TCVertex.cxx:1911
void SetVx2Score(TjStuff &tjs, VtxStore &vx2, bool prt)
Definition: TCVertex.cxx:2331
bool tca::FindParent ( std::string  inFcnLabel,
TjStuff tjs,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 1739 of file TCShower.cxx.

References tca::TjStuff::allTraj, ChgFracBetween(), tca::ShowerStruct3D::ChgPos, ChgToMeV(), tca::ShowerStruct3D::CotIDs, tca::TjStuff::cots, geo::CryostatID::Cryostat, tca::ShowerStruct3D::Dir, DontCluster(), DotProd(), EncodeCTP(), tca::ShowerStruct3D::End, energy, FarEnd(), FindAlongTrans(), GetAssns(), tca::ShowerStruct3D::ID, InShowerProbLong(), kShwrParent, MakeBareTP(), MCSMom(), tca::TjStuff::NumPlanes, tca::ShowerStruct3D::ParentID, tca::TjStuff::pfps, PointDirection(), PosSep(), PosSep2(), SetParent(), ShowerEnergy(), ShowerParams(), tca::TjStuff::ShowerParentReader, tca::TjStuff::ShowerParentVars, tca::TjStuff::showers, ss, tca::ShowerStruct3D::Start, geo::TPCID::TPC, tca::ShowerStruct3D::TPCID, UpdateShower(), tca::TjStuff::UseAlg, and tca::ShowerStruct3D::Vx3ID.

Referenced by FindShowers3D().

1740  {
1741  // look for a parent pfp for the shower.The 2D showers associated with it
1742  // The parent should be at the start of the shower (shend = 0) if it is well-defined
1743  // (has small AspectRatio and small DirectionFOM). A search is also made for a parent at
1744  // the "wrong" end of the shower (shend = 1). The best one at the wrong end is used if
1745  // no parent is found at the shower start and the shower is poorly defined.
1746  //
1747  // This function returns false if there was a failure. Not finding a parent is not a failure
1748 
1749  if(ss3.ID == 0) return false;
1750  if(ss3.CotIDs.size() < 2) return false;
1751  // Use the MVA reader
1752  if(!tjs.ShowerParentReader) return false;
1753  if(tjs.ShowerParentVars.size() != 9) return false;
1754  // don't call this function when studying this function. See TCTruth StudyShowerParents
1755  if(!tjs.UseAlg[kShwrParent]) return false;
1756 
1757  std::string fcnLabel = inFcnLabel + ".FPar";
1758  MCParticleListUtils mcpu{tjs};
1759  int truPFP = mcpu.PrimaryElectronPFPID(ss3.TPCID);
1760 
1761  double energy = ShowerEnergy(ss3);
1762  // the energy is probably under-estimated since there isn't a parent yet.
1763  energy *= 1.2;
1764  double shMaxAlong, along95;
1765  ShowerParams(energy, shMaxAlong, along95);
1766  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" Estimated energy "<<(int)energy<<" MeV shMaxAlong "<<shMaxAlong<<" along95 "<<along95<<" truPFP "<<truPFP;
1767 
1768  // look for the pfp that has a reasonable probability of being in the shower but with the
1769  // minimum along distance from the shower center.
1770  // This image explains the concept. The *'s represents the points in 2D showers that define
1771  // the charge center in 3D, ChgPos. We are looking for a pfp parent denoted by ----. The end
1772  // that is farthest from ChgPos is labeled P (pfp.XYZ[pend] in the code). The expected distance
1773  // from the shower start to shower Max, shMaxAlong, is found from ShowerParams. The longitudinal
1774  // and transverse distance of P relative to the shower center is alongTrans. The first cut on a
1775  // candidate parent is made requiring that D (alongTrans[0]) > 0.5 * shMaxAlong.
1776  //
1777  // __________shend = 0________________ __________shend = 1________________
1778  // **********
1779  // ****** ****** ****** ******
1780  // P-----*****ChgPos****** ** *****ChgPos******-------P
1781  // ******** ******* *******
1782  // |----> along |---> along
1783  // |<----D------>| |<----D------>|
1784  // |<----shMaxAlong--->| |<----shMaxAlong--->|
1785  //
1786  // Candidate parent ID for each end and the FOM
1787  std::array<int, 2> parID {{0, 0}};
1788  std::array<float, 2> parFOM {{-1E6, -1E6}};
1789 
1790  // temp vector to flag pfps that are already parents - indexed by ID
1791  std::vector<bool> isParent(tjs.pfps.size() + 1, false);
1792  for(auto& oldSS3 : tjs.showers) {
1793  if(oldSS3.ID == 0) continue;
1794  isParent[oldSS3.ParentID] = true;
1795  } // pfp
1796 
1797  // put the tjs associated with this shower in a flat vector
1798  auto TjsInSS3 = GetAssns(tjs, "3S", ss3.ID, "T");
1799  if(TjsInSS3.empty()) return false;
1800 
1801  for(auto& pfp : tjs.pfps) {
1802  if(pfp.ID == 0) continue;
1803  bool dprt = (pfp.ID == truPFP);
1804  if(pfp.TPCID != ss3.TPCID) continue;
1805  // ignore neutrinos
1806  if(pfp.PDGCode == 14 || pfp.PDGCode == 14) continue;
1807  // ignore shower pfps
1808  if(pfp.PDGCode == 1111) continue;
1809  // ignore existing parents
1810  if(isParent[pfp.ID]) continue;
1811  // check for inconsistent pfp - shower tjs
1812  if(DontCluster(tjs, pfp.TjIDs, TjsInSS3)) continue;
1813  // ignore if the pfp energy is larger than the shower energy
1814  float pfpEnergy = 0;
1815  float minEnergy = 1E6;
1816  for(auto tid : pfp.TjIDs) {
1817  auto& tj = tjs.allTraj[tid - 1];
1818  float energy = ChgToMeV(tj.TotChg);
1819  pfpEnergy += energy;
1820  if(energy < minEnergy) minEnergy = energy;
1821  }
1822  pfpEnergy -= minEnergy;
1823  pfpEnergy /= (float)(pfp.TjIDs.size() - 1);
1824  if(dprt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" P"<<pfp.ID<<" E "<<pfpEnergy;
1825  if(pfpEnergy > energy) continue;
1826  // find the end that is farthest away
1827  unsigned short pEnd = FarEnd(tjs, pfp, ss3.ChgPos);
1828  auto pToS = PointDirection(pfp.XYZ[pEnd], ss3.ChgPos);
1829  double costh1 = std::abs(DotProd(pToS, ss3.Dir));
1830  if(costh1 < 0.4) continue;
1831  float costh2 = DotProd(pToS, pfp.Dir[pEnd]);
1832  // distance^2 between the pfp end and the shower start, charge center, and shower end
1833  float distToStart2 = PosSep2(pfp.XYZ[pEnd], ss3.Start);
1834  float distToChgPos2 = PosSep2(pfp.XYZ[pEnd], ss3.ChgPos);
1835  float distToEnd2 = PosSep2(pfp.XYZ[pEnd], ss3.End);
1836  if(dprt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" P"<<pfp.ID<<"_"<<pEnd<<" distToStart "<<sqrt(distToStart2)<<" distToChgPos "<<sqrt(distToChgPos2)<<" distToEnd "<<sqrt(distToEnd2);
1837  // find the end of the shower closest to the pfp
1838  unsigned short shEnd = 0;
1839  if(distToEnd2 < distToStart2) shEnd = 1;
1840  // This can't be a parent if the pfp end is closer to the shower center than the start or the end
1841  if(shEnd == 0 && distToChgPos2 < distToStart2) continue;
1842  if(shEnd == 1 && distToChgPos2 < distToEnd2) continue;
1843  if(dprt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<"_"<<shEnd<<" P"<<pfp.ID<<"_"<<pEnd<<" costh1 "<<costh1;
1844  Point2_t alongTrans;
1845  // find the longitudinal and transverse components of the pfp start point relative to the
1846  // shower center
1847  FindAlongTrans(ss3.ChgPos, ss3.Dir, pfp.XYZ[pEnd], alongTrans);
1848  if(dprt) mf::LogVerbatim("TC")<<fcnLabel<<" alongTrans "<<alongTrans[0]<<" "<<alongTrans[1];
1849  // find the probability this point is inside the shower. Offset by the expected
1850  // shower max distance. distToShowerMax will be > 0 if the pfp end is closer to
1851  // ChgPos than expected from the parameterization
1852  float distToShowerMax = shMaxAlong - std::abs(alongTrans[0]);
1853  float prob = InShowerProbLong(energy, distToShowerMax);
1854  if(dprt) mf::LogVerbatim("TC")<<fcnLabel<<" prob "<<prob;
1855  if(prob < 0.1) continue;
1856  float chgFrac = 0;
1857  float totSep = 0;
1858  // find the charge fraction btw the pfp start and the point that is
1859  // half the distance to the charge center in each plane
1860  for(unsigned short plane = 0; plane < tjs.NumPlanes; ++plane) {
1861  CTP_t inCTP = EncodeCTP(ss3.TPCID.Cryostat, ss3.TPCID.TPC, plane);
1862  int ssid = 0;
1863  for(auto cid : ss3.CotIDs) {
1864  auto& ss = tjs.cots[cid - 1];
1865  if(ss.CTP != inCTP) continue;
1866  ssid = ss.ID;
1867  break;
1868  } // cid
1869  if(ssid == 0) continue;
1870  auto tpFrom = MakeBareTP(tjs, pfp.XYZ[pEnd], pToS, inCTP);
1871  auto& ss = tjs.cots[ssid - 1];
1872  auto& stp1 = tjs.allTraj[ss.ShowerTjID - 1].Pts[1];
1873  float sep = PosSep(tpFrom.Pos, stp1.Pos);
1874  float toPos = tpFrom.Pos[0] + 0.5 * tpFrom.Dir[0] * sep;
1875  float cf = ChgFracBetween(tjs, tpFrom, toPos, false);
1876  // weight by the separation in the plane
1877  totSep += sep;
1878  chgFrac += sep * cf;
1879  } // plane
1880  if(totSep > 0) chgFrac /= totSep;
1881 /*
1882  tjs.ShowerParentReader->AddVariable("fShEnergy", &tjs.ShowerParentVars[0]);
1883  tjs.ShowerParentReader->AddVariable("fPfpEnergy", &tjs.ShowerParentVars[1]);
1884  tjs.ShowerParentReader->AddVariable("fMCSMom", &tjs.ShowerParentVars[2]);
1885  tjs.ShowerParentReader->AddVariable("fPfpLen", &tjs.ShowerParentVars[3]);
1886  tjs.ShowerParentReader->AddVariable("fSep", &tjs.ShowerParentVars[4]);
1887  tjs.ShowerParentReader->AddVariable("fDang1", &tjs.ShowerParentVars[5]);
1888  tjs.ShowerParentReader->AddVariable("fDang2", &tjs.ShowerParentVars[6]);
1889  tjs.ShowerParentReader->AddVariable("fChgFrac", &tjs.ShowerParentVars[7]);
1890  tjs.ShowerParentReader->AddVariable("fInShwrProb", &tjs.ShowerParentVars[8]);
1891 */
1892  // load the MVA variables
1893  tjs.ShowerParentVars[0] = energy;
1894  tjs.ShowerParentVars[1] = pfpEnergy;
1895  tjs.ShowerParentVars[2] = MCSMom(tjs, pfp.TjIDs);
1896  tjs.ShowerParentVars[3] = PosSep(pfp.XYZ[0], pfp.XYZ[1]);
1897  tjs.ShowerParentVars[4] = sqrt(distToChgPos2);
1898  tjs.ShowerParentVars[5] = acos(costh1);
1899  tjs.ShowerParentVars[6] = acos(costh2);
1900  tjs.ShowerParentVars[7] = chgFrac;
1901  tjs.ShowerParentVars[8] = prob;
1902  float candParFOM = tjs.ShowerParentReader->EvaluateMVA("BDT");
1903 /*
1904  // use the overall pfp direction instead of the starting direction. It may not be so
1905  // good if the shower develops quickly
1906  auto pfpDir = PointDirection(pfp.XYZ[pEnd], pfp.XYZ[1 - pEnd]);
1907  costh = DotProd(pfpDir, ss3.Dir);
1908  if(dprt) mf::LogVerbatim("TC")<<fcnLabel<<" pfpDir "<<pfpDir[0]<<" "<<pfpDir[1]<<" "<<pfpDir[2]<<" costh "<<costh;
1909  if(std::abs(costh) < 0.6) continue;
1910 */
1911  // find the parentFOM
1912 // float candParFOM = ParentFOM(fcnLabel, tjs, pfp, pEnd, ss3, prt);
1913 
1914  if(prt) {
1915  mf::LogVerbatim myprt("TC");
1916  myprt<<fcnLabel;
1917  myprt<<" 3S"<<ss3.ID<<"_"<<shEnd;
1918  myprt<<" P"<<pfp.ID<<"_"<<pEnd<<" ParentVars";
1919  for(auto var : tjs.ShowerParentVars) myprt<<" "<<std::fixed<<std::setprecision(2)<<var;
1920  myprt<<" candParFOM "<<candParFOM;
1921  } // prt
1922  if(candParFOM > parFOM[shEnd]) {
1923  parFOM[shEnd] = candParFOM;
1924  parID[shEnd] = pfp.ID;
1925  }
1926  } // pfp
1927 
1928  if(parID[0] == 0 && parID[1] == 0) return true;
1929 
1930  // decide which to use
1931  int bestPFP = 0;
1932  // find the average DirectionFOM to help decide
1933  float aveDirFOM = 0;
1934  float fom3D = 0;
1935  for(auto cid : ss3.CotIDs) aveDirFOM += tjs.cots[cid - 1].DirectionFOM;
1936  aveDirFOM /= (float)ss3.CotIDs.size();
1937  if(prt) {
1938  mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" parID[0] "<<parID[0]<<" fom "<<parFOM[0]<<" parID[1] "<<parID[1]<<" fom "<<parFOM[1]<<" aveDirFOM "<<aveDirFOM;
1939  }
1940  if(parID[0] > 0 && parID[1] > 0 && aveDirFOM > 0.3) {
1941  // candidates at both ends and the direction is not well known. Take
1942  // the one with the best FOM
1943  bestPFP = parID[0];
1944  fom3D = parFOM[0];
1945  if(parFOM[1] > parFOM[0]) {
1946  bestPFP = parID[1];
1947  fom3D = parFOM[1];
1948  }
1949  } else if(parID[0] > 0) {
1950  bestPFP = parID[0];
1951  fom3D = parFOM[0];
1952  } else {
1953  bestPFP = parID[1];
1954  fom3D = parFOM[1];
1955  }
1956  if(bestPFP == 0) return true;
1957 
1958  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" setting P"<<bestPFP<<" as the parent "<<fom3D;
1959 
1960  // make local copies so we can recover from a failure
1961  auto oldSS3 = ss3;
1962  std::vector<ShowerStruct> oldSS(ss3.CotIDs.size());
1963  for(unsigned short ii = 0; ii < ss3.CotIDs.size(); ++ii) {
1964  oldSS[ii] = tjs.cots[ss3.CotIDs[ii] - 1];
1965  }
1966 
1967  ss3.ParentID = bestPFP;
1968  auto& pfp = tjs.pfps[bestPFP - 1];
1969  unsigned short pend = FarEnd(tjs, pfp, ss3.ChgPos);
1970  ss3.Vx3ID = pfp.Vx3ID[pend];
1971 
1972  if(SetParent(fcnLabel, tjs, pfp, ss3, prt) && UpdateShower(fcnLabel, tjs, ss3, prt)) {
1973  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" successful update";
1974  return true;
1975  }
1976 
1977  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" Failed. Recovering...";
1978  ss3 = oldSS3;
1979  for(unsigned short ii = 0; ii < oldSS.size(); ++ii) {
1980  auto& ss = oldSS[ii];
1981  tjs.cots[ss.ID - 1] = ss;
1982  } // ii
1983  return false;
1984 
1985  } // FindParent
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
double InShowerProbLong(double showerEnergy, double along)
Definition: TCShower.cxx:2118
float ChgFracBetween(TjStuff &tjs, Point3_t pos1, Point3_t pos2, geo::TPCID tpcid)
Definition: PFPUtils.cxx:2860
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:2751
Float_t ss
Definition: plot.C:23
bool SetParent(std::string inFcnLabel, TjStuff &tjs, PFPStruct &pfp, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1988
unsigned short FarEnd(const TjStuff &tjs, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:2936
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:1614
TrajPoint MakeBareTP(TjStuff &tjs, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
Definition: Utils.cxx:3435
double energy
Definition: plottest35.C:25
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1631
bool DontCluster(const TjStuff &tjs, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3381
float ShowerEnergy(const TjStuff &tjs, const std::vector< int > tjIDs)
Definition: TCShower.cxx:4447
short MCSMom(const TjStuff &tjs, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2837
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:60
unsigned int CTP_t
Definition: DataStructs.h:41
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
Definition: TCShower.cxx:2084
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
float ChgToMeV(float chg)
Definition: TCShower.cxx:4460
std::vector< int > GetAssns(const TjStuff &tjs, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4079
bool UpdateShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1302
void tca::FindPFParticles ( TjStuff tjs,
const geo::TPCID tpcid,
bool  prt 
)

Definition at line 1968 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, AnalyzePFP(), CreatePFP(), geo::CryostatID::Cryostat, DefinePFP(), tca::PFPStruct::Dir, EncodeCTP(), FindCompleteness(), FindXMatches(), tca::PFPStruct::ID, tca::SortEntry::index, kEnvFlag, kKilled, kMat3D, MakeBareTP(), tca::TjStuff::Match3DCuts, Match3DVtxTjs(), tca::TjStuff::matchVec, tca::PFPStruct::MatchVecIndex, MaxTjLen(), MCSMom(), tca::TjStuff::NumPlanes, tca::PFPStruct::PDGCode, PDGCodeVote(), SetIntersection(), Split3DKink(), StorePFP(), tca::TjStuff::TestBeam, tca::PFPStruct::TjCompleteness, tca::PFPStruct::TjIDs, geo::TPCID::TPC, tca::PFPStruct::TPCID, tca::SortEntry::val, valDecreasings(), and tca::PFPStruct::XYZ.

Referenced by DotProd(), and tca::TrajClusterAlg::RunTrajClusterAlg().

1969  {
1970  // Match Tjs in 3D and create PFParticles
1971 
1972  if(tjs.Match3DCuts[0] <= 0) return;
1973 
1974  if(prt) mf::LogVerbatim("TC")<<" inside FindPFParticles";
1975  // clear matchVec
1976  tjs.matchVec.clear();
1977  // clear the kEnvFlag bits on all Tjs. The bit will be set true when a TP is
1978  // used in a PFParticle Tp3
1979  for(auto& tj : tjs.allTraj) {
1980  for(auto& tp : tj.Pts) tp.Environment[kEnvFlag] = false;
1981  } // tj
1982 
1983  // Match these points in 3D and put the results in tjs.matchVec
1984  std::vector<MatchStruct> matVec;
1985  // first look for 3-plane matches in a 3-plane TPC
1986  if(tjs.NumPlanes == 3) {
1987  // Match Tjs with high quality vertices first and the leftovers next
1988  for(short maxScore = 0; maxScore < 2; ++maxScore) FindXMatches(tjs, 3, maxScore, matVec, prt);
1989  } // 3-plane TPC
1990  // Make 2-plane matches if we haven't hit the user-defined size limit
1991  if(matVec.size() < tjs.Match3DCuts[4]) {
1992  // 2-plane TPC or 2-plane matches in a 3-plane TPC
1993  if(tjs.NumPlanes == 2) {
1994  for(short maxScore = 0; maxScore < 2; ++maxScore) FindXMatches(tjs, 2, maxScore, matVec, prt);
1995  } else {
1996  // Make one attempt at 2-plane matches in a 3-plane TPC, setting maxScore large
1997  FindXMatches(tjs, 2, 3, matVec, prt);
1998  }
1999  } // can add more combinations
2000 
2001  if(matVec.empty()) return;
2002 
2003  // sort by decreasing number of matched points
2004  if(matVec.size() > 1) {
2005  PFPStruct pfp = CreatePFP(tjs, tpcid);
2006  std::vector<int> dum1;
2007  std::vector<float> dum2;
2008  std::vector<SortEntry> sortVec(matVec.size());
2009  for(unsigned int ii = 0; ii < matVec.size(); ++ii) {
2010  sortVec[ii].index = ii;
2011  auto& ms = matVec[ii];
2012  sortVec[ii].val = ms.Count;
2013  // de-weight two-plane matches
2014  if(ms.TjIDs.size() == 2) sortVec[ii].val /= 2;
2015  } // ii
2016  std::sort(sortVec.begin(), sortVec.end(), valDecreasings);
2017  std::vector<MatchStruct> tmpVec;
2018  tmpVec.reserve(matVec.size());
2019  for(unsigned int ii = 0; ii < matVec.size(); ++ii) {
2020  tmpVec.push_back(matVec[sortVec[ii].index]);
2021  } // ii
2022  matVec = tmpVec;
2023  } // sort matVec
2024 
2025  // put the maybe OK matches into tjs
2026  PFPStruct pfp = CreatePFP(tjs, tpcid);
2027  for(auto& ms : matVec) {
2028  if(ms.Count < 2) continue;
2029  // check for duplicates
2030  bool skipit = false;
2031  for(auto& oms : tjs.matchVec) {
2032  if(ms.TjIDs == oms.TjIDs) {
2033  skipit = true;
2034  break;
2035  }
2036  } // oms
2037  if(skipit) continue;
2038  // Find completeness, do the fit, don't fill Tp3s, don't print
2039  pfp.TjIDs = ms.TjIDs;
2040  FindCompleteness(tjs, pfp, true, false, false);
2041  // save the info in matchStruct
2042  ms.TjCompleteness = pfp.TjCompleteness;
2043  ms.Pos = pfp.XYZ[0];
2044  ms.Dir = pfp.Dir[0];
2045  tjs.matchVec.push_back(ms);
2046  }
2047  if(tjs.matchVec.empty()) return;
2048 
2049  if(prt) {
2050  mf::LogVerbatim myprt("TC");
2051  myprt<<"FPFP: tjs.matchVec\n";
2052  unsigned short cnt = 0;
2053  PFPStruct pfp = CreatePFP(tjs, tpcid);
2054  std::vector<int> dum1;
2055  std::vector<float> dum2;
2056  for(unsigned int ii = 0; ii < tjs.matchVec.size(); ++ii) {
2057  auto& ms = tjs.matchVec[ii];
2058  if(ms.Count == 0) continue;
2059  myprt<<std::setw(4)<<ii<<" Count "<<std::setw(5)<<(int)ms.Count;
2060  myprt<<" TjIDs:";
2061  for(auto& tjid : ms.TjIDs) myprt<<" T"<<tjid;
2062  myprt<<" Comp ";
2063  for(unsigned short itj = 0; itj < ms.TjCompleteness.size(); ++itj) {
2064  myprt<<std::setprecision(2)<<std::setw(6)<<ms.TjCompleteness[itj];
2065  }
2066  myprt<<" Pos ("<<std::setprecision(0)<<std::fixed;
2067  myprt<<ms.Pos[0]<<", "<<ms.Pos[1]<<", "<<ms.Pos[2];
2068  myprt<<") Dir "<<std::setprecision(2)<<std::setw(6)<<ms.Dir[0]<<std::setw(6)<<ms.Dir[1]<<std::setw(6)<<ms.Dir[2];
2069  myprt<<" projInPlane";
2070  for(unsigned short plane = 0; plane < tjs.NumPlanes; ++plane) {
2071  CTP_t inCTP = EncodeCTP(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
2072  auto tp = MakeBareTP(tjs, ms.Pos, ms.Dir, inCTP);
2073  myprt<<" "<<std::setprecision(2)<<tp.Delta;
2074  } // plane
2075  myprt<<" maxTjLen "<<(int)MaxTjLen(tjs, ms.TjIDs);
2076  myprt<<" MCSMom "<<MCSMom(tjs, ms.TjIDs);
2077  myprt<<" PDGCodeVote "<<PDGCodeVote(tjs, ms.TjIDs, false);
2078  myprt<<"\n";
2079  ++cnt;
2080  if(cnt == 1000 || ms.Count < 2) {
2081  myprt<<"...stopped printing after 500 entries or Count < 2";
2082  break;
2083  }
2084  } // ii
2085  } // prt
2086 
2087  // create the list of associations to matches that will be converted to PFParticles
2088  // Start with Tjs attached to 3D vertices. This is only done when reconstructing neutrino events
2089  if(!tjs.TestBeam) {
2090  Match3DVtxTjs(tjs, tpcid, prt);
2091  }
2092 
2093  // define the PFParticleList
2094  for(unsigned int indx = 0; indx < tjs.matchVec.size(); ++indx) {
2095  auto& ms = tjs.matchVec[indx];
2096  // ignore dead matches
2097  if(ms.Count == 0) continue;
2098  // skip this match if any of the trajectories is already matched or merged and killed
2099  bool skipit = false;
2100  // check for muons and delta rays or InShower Tjs
2101  bool has13 = false;
2102  bool has11 = false;
2103  for(unsigned short itj = 0; itj < ms.TjIDs.size(); ++itj) {
2104  if(ms.TjIDs[itj] <= 0 || ms.TjIDs[itj] > (int)tjs.allTraj.size()) {
2105  std::cout<<"FindPFParticles: bogus ms TjID "<<ms.TjIDs[itj]<<"\n";
2106  return;
2107  }
2108  auto& tj = tjs.allTraj[ms.TjIDs[itj] - 1];
2109  if(tj.AlgMod[kMat3D] || tj.AlgMod[kKilled]) skipit = true;
2110  // skip low TjCompleteness
2111  if(ms.TjCompleteness.empty()) {
2112  std::cout<<"FindPFParticles: ms.TjCompleteness is empty\n";
2113  return;
2114  }
2115  if(ms.TjCompleteness[itj] < 0.1) skipit = true;
2116  if(tj.PDGCode == 13) has13 = true;
2117  if(tj.PDGCode == 11) has11 = true;
2118  } // tjID
2119  if(skipit) continue;
2120  if(has13 && has11) continue;
2121  int pdgCode = PDGCodeVote(tjs, ms.TjIDs, prt);
2122  PFPStruct pfp = CreatePFP(tjs, tpcid);
2123  pfp.TjIDs = ms.TjIDs;
2124  // note that the ms position is the average position of all 3D matched Tp3s at this point.
2125  // It is not the start position. This will be determined in DefinePFP.
2126  pfp.XYZ[0] = ms.Pos;
2127  pfp.Dir[0] = ms.Dir;
2128  pfp.MatchVecIndex = indx;
2129  // Set the PDGCode so DefinePFP can ignore incompatible matches
2130  pfp.PDGCode = pdgCode;
2131  // set the PDGCode to ensure that delta rays aren't merged with muons. PDGCodeVote
2132  // returns 0 if the vote is mixed
2133  if(has13) pfp.PDGCode = 13;
2134  if(has11) pfp.PDGCode = 11;
2135  if(!DefinePFP("FPFP", tjs, pfp, prt)) {
2136  if(prt) mf::LogVerbatim("TC")<<" DefinePFP failed";
2137  continue;
2138  }
2139  double sep = 1;
2140  Split3DKink(tjs, pfp, sep, prt);
2141  if(!AnalyzePFP(tjs, pfp, prt)) continue;
2142  if(!StorePFP(tjs, pfp)) {
2143  if(prt) mf::LogVerbatim("TC")<<" StorePFP failed P"<<pfp.ID;
2144  if(prt) std::cout<<" StorePFP failed P"<<pfp.ID<<"\n";
2145  continue;
2146  }
2147  ms.Count = 0;
2148  // clobber MatchStructs that use the Tjs in this pfp
2149  for(auto& allms : tjs.matchVec) {
2150  auto shared = SetIntersection(allms.TjIDs, pfp.TjIDs);
2151  if(!shared.empty()) allms.Count = 0;
2152  } // allms
2153  } // indx
2154  // CheckNoMatchTjs(tjs, tpcid, prt);
2155 
2156  } // FindPFParticles
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool AnalyzePFP(TjStuff &tjs, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:2339
bool DefinePFP(std::string inFcnLabel, TjStuff &tjs, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:2159
a general purpose flag bit used in 3D matching
Definition: DataStructs.h:459
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:214
int PDGCodeVote(TjStuff &tjs, std::vector< int > &tjIDs, bool prt)
Definition: Utils.cxx:267
void Match3DVtxTjs(TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
Definition: TCVertex.cxx:1506
TrajPoint MakeBareTP(TjStuff &tjs, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
Definition: Utils.cxx:3435
float MaxTjLen(TjStuff const &tjs, std::vector< int > &tjIDs)
Definition: Utils.cxx:2189
bool valDecreasings(SortEntry c1, SortEntry c2)
Definition: PFPUtils.cxx:12
short MCSMom(const TjStuff &tjs, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2837
unsigned int CTP_t
Definition: DataStructs.h:41
PFPStruct CreatePFP(const TjStuff &tjs, const geo::TPCID &tpcid)
Definition: PFPUtils.cxx:1943
bool Split3DKink(TjStuff &tjs, PFPStruct &pfp, double sep, bool prt)
Definition: PFPUtils.cxx:1782
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
void FindXMatches(TjStuff &tjs, unsigned short numPlanes, short maxScore, std::vector< MatchStruct > &matVec, bool prt)
Definition: PFPUtils.cxx:1326
void FindCompleteness(TjStuff &tjs, PFPStruct &pfp, bool doFit, bool fillTp3s, bool prt)
Definition: PFPUtils.cxx:593
bool StorePFP(TjStuff &tjs, PFPStruct &pfp)
Definition: PFPUtils.cxx:2660
bool tca::FindShowers3D ( TjStuff tjs,
const geo::TPCID tpcid 
)

Definition at line 286 of file TCShower.cxx.

References AddTjsInsideEnvelope(), ChkAssns(), tca::TjStuff::cots, CreateSS(), geo::CryostatID::Cryostat, debug, DecodeCTP(), DefineDontCluster(), DotProd(), EncodeCTP(), energy, FillWireHitRange(), FindCots(), FindNearbyTjs(), FindParent(), tca::TjStuff::geom, MakeShowerObsolete(), Match2DShowers(), tca::TjStuff::MCPartList, MergeNearby2DShowers(), MergeOverlap(), MergeShowerChain(), MergeSubShowers(), MergeSubShowersTj(), geo::TPCGeo::Nplanes(), tca::TjStuff::NumPlanes, PosSep(), Print2DShowers(), PrintAllTraj(), PrintPFPs(), Reconcile3D(), SaveAllCots(), tca::TjStuff::SaveShowerTree, SaveTjInfo(), ShowerEnergy(), tca::TjStuff::showers, tca::TjStuff::ShowerTag, ss, StoreShower(), geo::TPCID::TPC, geo::GeometryCore::TPC(), tca::TjStuff::TPCID, and UpdateShower().

Referenced by tca::TrajClusterAlg::RunTrajClusterAlg().

287  {
288  // Find 2D showers using 3D-matched trajectories. This returns true if showers were found
289  // which requires re-doing the 3D trajectory match
290 
291  bool reconstruct = (tjs.ShowerTag[0] == 2) || (tjs.ShowerTag[0] == 4);
292  if(!reconstruct) return false;
293 
294  bool prt = tjs.ShowerTag[12] >= 0;
295  // Add 10 for more detailed printing
296  short dbgPlane = ((int)tjs.ShowerTag[12] % 10);
297  CTP_t dbgCTP = UINT_MAX;
298  if(dbgPlane >= 0 && dbgPlane <= tjs.NumPlanes) dbgCTP = EncodeCTP(tpcid.Cryostat, tpcid.TPC, dbgPlane);
299 
300  std::string fcnLabel = "FS";
301 
302  geo::TPCGeo const& TPC = tjs.geom->TPC(tpcid);
303  // check for already-existing showers
304  for(unsigned short plane = 0; plane < TPC.Nplanes(); ++plane) {
305  CTP_t inCTP = EncodeCTP(tpcid.Cryostat, tpcid.TPC, plane);
306  for(auto& ss : tjs.cots) if(ss.CTP == inCTP) return false;
307  }
308 
309  // rebuild the hit range references if necessary
310  if(tpcid != tjs.TPCID && !FillWireHitRange(tjs, tpcid)) return false;
311 
312  if(prt) {
313  PrintPFPs("FSi", tjs);
314  PrintAllTraj("FSi", tjs, debug, USHRT_MAX, 0);
315  }
316 
317  // define a list of tjs that shouldn't be clustered in the same shower because
318  // they are matched to pfp particles that are likely parents of 3D showers
319  DefineDontCluster(tjs, tpcid, prt);
320 
321  // lists of Tj IDs in plane, (list1, list2, list3, ...)
322  std::vector<std::vector<std::vector<int>>> bigList(tjs.NumPlanes);
323  for(unsigned short plane = 0; plane < TPC.Nplanes(); ++plane) {
324  CTP_t inCTP = EncodeCTP(tpcid.Cryostat, tpcid.TPC, plane);
325  std::vector<std::vector<int>> tjList;
326  // Make lists of lists of ShowerLike tjs that will become showers
327  FindCots(fcnLabel, tjs, inCTP, tjList, prt);
328  SaveTjInfo(tjs, tjList, "TJL");
329  if(tjList.empty()) continue;
330  bigList[plane] = tjList;
331  } // plane
332  unsigned short nPlanesWithShowers = 0;
333  for(unsigned short plane = 0; plane < TPC.Nplanes(); ++plane) if(!bigList.empty()) ++nPlanesWithShowers;
334  if(nPlanesWithShowers < 2) return false;
335  for(unsigned short plane = 0; plane < TPC.Nplanes(); ++plane) {
336  CTP_t inCTP = EncodeCTP(tpcid.Cryostat, tpcid.TPC, plane);
337  // print detailed debug info for one plane
338  prt = (inCTP == dbgCTP);
339  // Create a shower for each one
340  for(auto& tjl : bigList[plane]) {
341  if(tjl.empty()) continue;
342  if(prt) {
343  mf::LogVerbatim myprt("TC");
344  myprt<<"Plane "<<plane<<" tjList";
345  for(auto& tjID : tjl) myprt<<" "<<tjID;
346  }
347  auto ss = CreateSS(tjs, 0, tjl);
348  if(ss.ID == 0) continue;
349  if(!UpdateShower(fcnLabel, tjs, ss, prt)) continue;
350  SaveTjInfo(tjs, ss, "DS");
351  FindNearbyTjs(fcnLabel, tjs, ss, prt);
352  // don't try to do anything else here until all of the showers are defined
353  if(!StoreShower(fcnLabel, tjs, ss)) {
354  std::cout<<fcnLabel<<" StoreShower failed 2S"<<ss.ID<<"\n";
355  MakeShowerObsolete(fcnLabel, tjs, ss, prt);
356  }
357  } // tjl
358  ChkAssns(fcnLabel, tjs);
359  // try to merge showers in this plane using the lists of nearby Tjs
360  if(inCTP == UINT_MAX) continue;
361  if(tjs.cots.empty()) continue;
362  prt = (inCTP == dbgCTP || dbgPlane == 3);
363  if(prt) Print2DShowers("tjl", tjs, inCTP, false);
364  MergeShowerChain(fcnLabel, tjs, inCTP, prt);
365  SaveAllCots(tjs, inCTP, "MSC");
366  if(prt) Print2DShowers("MSCo", tjs, inCTP, false);
367  MergeOverlap(fcnLabel, tjs, inCTP, prt);
368  SaveAllCots(tjs, inCTP, "MO");
369  if(prt) Print2DShowers("MO", tjs, inCTP, false);
370  MergeNearby2DShowers(fcnLabel, tjs, inCTP, prt);
371  SaveAllCots(tjs, inCTP, "MSS");
372  // merge sub-showers with other showers
373  MergeSubShowers(fcnLabel, tjs, inCTP, prt);
374  // merge sub-showers with shower-like tjs
375  MergeSubShowersTj(fcnLabel, tjs, inCTP, prt);
376  SaveAllCots(tjs, inCTP, "MNrby");
377  if(prt) Print2DShowers("Nrby", tjs, inCTP, false);
378  bool tryMerge = false;
379  for(unsigned short ii = 0; ii < tjs.cots.size(); ++ii) {
380  auto& ss = tjs.cots[ii];
381  if(ss.ID == 0) continue;
382  if(ss.CTP != inCTP) continue;
383  if(AddTjsInsideEnvelope(fcnLabel, tjs, ss, prt)) tryMerge = true;
384  if (tjs.SaveShowerTree) SaveAllCots(tjs, inCTP, "Merge");
385  }
386  if(tryMerge) MergeNearby2DShowers(fcnLabel, tjs, inCTP, prt);
387  SaveAllCots(tjs, inCTP, "ATj2");
388  if(prt) Print2DShowers("ATIE", tjs, inCTP, false);
389  } // plane
390  if(tjs.cots.empty()) return false;
391  prt = (dbgPlane > 2);
392  if(prt) Print2DShowers("B4", tjs, USHRT_MAX, false);
393  // Match in 3D, make 3D showers and define them
394  Match2DShowers(fcnLabel, tjs, tpcid, prt);
395  SaveAllCots(tjs, "M2DS");
396  // Reconcile pfp and shower assns before the Parent search
397  Reconcile3D(fcnLabel, tjs, tpcid, false, prt);
398  SaveAllCots(tjs, "R3D");
399 // std::cout<<"Add function to check for neutrino vertex inside showers\n";
400  for(auto& ss3 : tjs.showers) {
401  if(ss3.ID == 0) continue;
402  if(ss3.TPCID != tpcid) continue;
403  FindParent(fcnLabel, tjs, ss3, prt);
404  } // ss3
405  // Reconcile pfp and shower assns again
406  Reconcile3D(fcnLabel, tjs, tpcid, true, prt);
407  if(prt) Print2DShowers("M2DS", tjs, USHRT_MAX, false);
408  SaveAllCots(tjs, "FP");
409 
410  // kill low energy 3D showers
411  for(auto& ss3 : tjs.showers) {
412  if(ss3.ID == 0) continue;
413  if(ss3.TPCID != tpcid) continue;
414  bool killMe = (ShowerEnergy(ss3) < tjs.ShowerTag[3]);
415  if(killMe) MakeShowerObsolete(fcnLabel, tjs, ss3, prt);
416  } // ss3
417 
418  // kill 2D showers that are either below threshold or have only one tj
419  for(auto& ss : tjs.cots) {
420  if(ss.ID == 0) continue;
421  if(ss.SS3ID > 0) continue;
422  bool killMe = (ss.TjIDs.size() == 1 || ss.Energy < tjs.ShowerTag[3]);
423  // too small aspect ratio -> something track-like with some shower-like fuzz
424  if(ss.AspectRatio < tjs.ShowerTag[10]) killMe = true;
425  if(killMe) MakeShowerObsolete(fcnLabel, tjs, ss, prt);
426  } // ss
427 
428  unsigned short nNewShowers = 0;
429  for(auto& ss : tjs.cots) {
430  if(ss.ID == 0) continue;
431  if(ss.TjIDs.empty()) continue;
432  geo::PlaneID planeID = DecodeCTP(ss.CTP);
433  if(planeID.Cryostat != tpcid.Cryostat) continue;
434  if(planeID.TPC != tpcid.TPC) continue;
435  SaveTjInfo(tjs, ss, "Done");
436  ++nNewShowers;
437  } // ss
438 
439  // temp for testing with MC
440  if(!tjs.MCPartList.empty()) {
441  // get some truth information
442  MCParticleListUtils mcpu{tjs};
443  for(unsigned short plane = 0; plane < TPC.Nplanes(); ++plane) {
444  CTP_t inCTP = EncodeCTP(tpcid.Cryostat, tpcid.TPC, plane);
445  int truElectronTID = mcpu.PrimaryElectronTjID(inCTP);
446  std::cout<<"Plane "<<plane<<" trueElectron T"<<truElectronTID;
447  for(auto& ss : tjs.cots) {
448  if(ss.ID == 0) continue;
449  if(ss.CTP != inCTP) continue;
450  if(std::find(ss.TjIDs.begin(), ss.TjIDs.end(), truElectronTID) == ss.TjIDs.end()) continue;
451  std::cout<<" in 2S"<<ss.ID<<" with Parent T"<<ss.ParentID;
452  if(ss.SS3ID > 0) std::cout<<" -> 3S"<<ss.SS3ID;
453  } // ss
454  std::cout<<"\n";
455  } // plane
456  Point3_t truStart;
457  Vector3_t truDir;
458  float truE;
459  if(mcpu.PrimaryElectronStart(truStart, truDir, truE)) {
460  // assume that the highest energy shower is from the primary electron
461  float big = 0;
462  int imBig = 0;
463  for(auto& ss3 : tjs.showers) {
464  float energy = ShowerEnergy(ss3);
465  if(energy < big) continue;
466  big = energy;
467  imBig = ss3.ID;
468  } // ss3
469  if(imBig > 0) {
470  auto& ss3 = tjs.showers[imBig - 1];
471  float shMaxSep = PosSep(truStart, ss3.ChgPos);
472  float dang = acos(DotProd(truDir, ss3.Dir));
473  float energy = ShowerEnergy(ss3);
474  std::cout<<"Big 3S"<<ss3.ID<<" E "<<(int)energy<<" truE "<<(int)truE;
475  std::cout<<" truStart "<<std::fixed<<std::setprecision(1)<<truStart[0]<<" "<<truStart[1]<<" "<<truStart[2];
476  std::cout<<" tru P"<<mcpu.PrimaryElectronPFPID(tpcid);
477  std::cout<<" rec P"<<ss3.ParentID;
478  std::cout<<" shMax "<<(int)shMaxSep<<" cm.";
479  std::cout<<" dang "<<std::fixed<<std::setprecision(2)<<dang<<"\n";
480  } // imBig > 0
481  } // PrimaryElectronStart success
482  } // !tjs.MCPartList.empty()
483 
484 // if(prt) Print2DShowers("FSo", tjs, USHRT_MAX, false);
485 
486  return (nNewShowers > 0);
487 
488  } // FindShowers3D
TPCID()=default
Default constructor: an invalid TPC ID.
bool FindParent(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1739
void MakeShowerObsolete(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3334
void MergeShowerChain(std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP, bool prt)
Definition: TCShower.cxx:2642
bool AddTjsInsideEnvelope(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3996
void MergeOverlap(std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP, bool prt)
Definition: TCShower.cxx:2530
void MergeNearby2DShowers(std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP, bool prt)
Definition: TCShower.cxx:2443
void Print2DShowers(std::string someText, const TjStuff &tjs, CTP_t inCTP, bool printKilledShowers)
Definition: TCShower.cxx:4713
std::array< double, 3 > Point3_t
Definition: DataStructs.h:35
void PrintAllTraj(std::string someText, const TjStuff &tjs, const DebugStuff &debug, unsigned short itj, unsigned short ipt, bool prtVtx)
Definition: Utils.cxx:4232
unsigned int Nplanes() const
Number of planes in this tpc.
Definition: TPCGeo.h:145
bool ChkAssns(std::string inFcnLabel, TjStuff &tjs)
Definition: TCShower.cxx:4625
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
Geometry information for a single TPC.
Definition: TPCGeo.h:37
Float_t ss
Definition: plot.C:23
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
bool Reconcile3D(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:645
void FindCots(std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP, std::vector< std::vector< int >> &tjLists, bool prt)
Definition: TCShower.cxx:3485
void MergeSubShowers(std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP, bool prt)
Definition: TCShower.cxx:2878
DebugStuff debug
Definition: DebugStruct.cxx:4
double energy
Definition: plottest35.C:25
void SaveTjInfo(TjStuff &tjs, std::vector< std::vector< int >> &tjList, std::string stageName)
Definition: TCShTree.cxx:5
void DefineDontCluster(TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
Definition: TCShower.cxx:3397
float ShowerEnergy(const TjStuff &tjs, const std::vector< int > tjIDs)
Definition: TCShower.cxx:4447
void SaveAllCots(TjStuff &tjs, const CTP_t &inCTP, std::string someText)
Definition: TCShTree.cxx:165
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:60
unsigned int CTP_t
Definition: DataStructs.h:41
void FindNearbyTjs(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3829
bool FillWireHitRange(TjStuff &tjs, const geo::TPCID &tpcid)
Definition: Utils.cxx:3722
bool StoreShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss)
Definition: TCShower.cxx:4511
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
std::array< double, 3 > Vector3_t
Definition: DataStructs.h:36
ShowerStruct CreateSS(TjStuff &tjs, CTP_t inCTP, const std::vector< int > &tjl)
Definition: TCShower.cxx:4572
void PrintPFPs(std::string someText, const TjStuff &tjs)
Definition: Utils.cxx:4690
void Match2DShowers(std::string inFcnLabel, TjStuff &tjs, const geo::TPCID &tpcid, bool prt)
Definition: TCShower.cxx:947
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
void MergeSubShowersTj(std::string inFcnLabel, TjStuff &tjs, const CTP_t &inCTP, bool prt)
Definition: TCShower.cxx:2768
bool UpdateShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1302
bool tca::FindShowerStart ( TjStuff tjs,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 45 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::ShowerStruct3D::ChgPos, tca::ShowerStruct3D::CotIDs, tca::TjStuff::cots, tca::ShowerStruct3D::Dir, DotProd(), tca::ShowerStruct3D::End, tca::ShowerStruct3D::ID, tca::ShowerStruct3D::Len, MakeBareTP(), tca::ShowerStruct3D::OpenAngle, PosSep(), ReverseShower(), ss, tca::ShowerStruct3D::Start, tca::TjStuff::vtx3, tca::ShowerStruct3D::Vx3ID, and tca::TjStuff::WirePitch.

46  {
47  // The shower ChgPos and Dir were found by the calling function but Dir
48  // may be inconsistent with the 2D shower directions
49  if(ss3.ID == 0) return false;
50 
51  if(prt) {
52  mf::LogVerbatim myprt("TC");
53  myprt<<"Inside FSS: 3S"<<ss3.ID<<" ->";
54  for(auto cid : ss3.CotIDs) myprt<<" 2S"<<cid;
55  myprt<<" Vx 3V"<<ss3.Vx3ID;
56  } // prt
57 
58  // find a parent Tj in the list of 2D showers that is the farthest away from the
59  // shower center
60  unsigned short useParentCID = 0;
61  float maxParentSep = 0;
62  unsigned short usePtSepCID = 0;
63  float maxPtSep = 0;
64  // assume that the 2D shower direction is consistent with the 3D shower direction. This
65  // variable is only used when no parent exists
66  bool dirOK = true;
67  for(auto cid : ss3.CotIDs) {
68  auto& ss = tjs.cots[cid - 1];
69  // Find the position, direction and projection in this plane
70  auto& stj = tjs.allTraj[ss.ShowerTjID - 1];
71  auto chgCtrTP = MakeBareTP(tjs, ss3.ChgPos, ss3.Dir, stj.CTP);
72  // projection too small in this view?
73  if(chgCtrTP.Delta < 0.5) continue;
74  auto& startTP = stj.Pts[0];
75  float sep = PosSep(startTP.Pos, chgCtrTP.Pos);
76  if(ss.ParentID > 0) {
77  if(sep > maxParentSep) {
78  maxParentSep = sep;
79  useParentCID = cid;
80  }
81  } else if(sep > maxPtSep) {
82  // no parent exists.
83  maxPtSep = sep;
84  usePtSepCID = cid;
85  float costh = DotProd(chgCtrTP.Dir, startTP.Dir);
86  if(costh < 0) dirOK = false;
87  }
88  } // ci
89  if(useParentCID == 0 && usePtSepCID == 0) return false;
90 
91  unsigned short useCID = useParentCID;
92  if(useCID == 0) {
93  useCID = usePtSepCID;
94  if(!dirOK) ReverseShower("FSS", tjs, useCID, prt);
95  }
96 
97  // now define the start and length
98  auto& ss = tjs.cots[useCID - 1];
99  auto& stj = tjs.allTraj[ss.ShowerTjID - 1];
100 
101  auto chgCtrTP = MakeBareTP(tjs, ss3.ChgPos, ss3.Dir, stj.CTP);
102  if(ss3.Vx3ID > 0) {
103  auto& vx3 = tjs.vtx3[ss3.Vx3ID - 1];
104  ss3.Start[0] = vx3.X;
105  ss3.Start[1] = vx3.Y;
106  ss3.Start[2] = vx3.Z;
107  } else {
108  // no start vertex
109  auto& startTP = stj.Pts[0];
110  // The 2D separation btw the shower start and the shower center, converted
111  // to the 3D separation
112 // std::cout<<"useCI "<<useCID<<" sep "<<PosSep(startTP.Pos, stj.Pts[1].Pos)<<" projInPln "<<chgCtrTP.Delta<<"\n";
113  float sep = tjs.WirePitch * PosSep(startTP.Pos, stj.Pts[1].Pos) / chgCtrTP.Delta;
114  // set the start position
115  for(unsigned short xyz = 0; xyz < 3; ++xyz) ss3.Start[xyz] = ss3.ChgPos[xyz] - sep * ss3.Dir[xyz];
116  }
117  // now do the end position
118  auto& endTP = stj.Pts[2];
119  float sep = tjs.WirePitch * PosSep(endTP.Pos, chgCtrTP.Pos) / chgCtrTP.Delta;
120  for(unsigned short xyz = 0; xyz < 3; ++xyz) ss3.End[xyz] = ss3.ChgPos[xyz] + sep * ss3.Dir[xyz];
121  ss3.Len = PosSep(ss3.Start, ss3.End);
122  auto& startTP = stj.Pts[0];
123  sep = PosSep(startTP.Pos, endTP.Pos);
124  ss3.OpenAngle = (endTP.DeltaRMS - startTP.DeltaRMS) / sep;
125  ss3.OpenAngle /= chgCtrTP.Delta;
126  return true;
127 
128  } // FindShowerStart
Float_t ss
Definition: plot.C:23
TrajPoint MakeBareTP(TjStuff &tjs, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
Definition: Utils.cxx:3435
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:60
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
void ReverseShower(std::string inFcnLabel, TjStuff &tjs, int cotID, bool prt)
Definition: TCShower.cxx:3298
void tca::FindStartChg ( std::string  inFcnLabel,
TjStuff tjs,
int  cotID,
bool  prt 
)

Definition at line 4142 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::ShowerStruct::AspectRatio, tca::TjStuff::cots, tca::ShowerStruct::DirectionFOM, tca::ShowerStruct::ID, tca::ShowerStruct::ParentID, tca::TjStuff::ShowerTag, tca::ShowerStruct::ShowerTjID, ss, StartChgVec(), and tca::ShowerStruct::TjIDs.

4143  {
4144  // Finds the charge at the start of a shower and puts it in AveChg of the first
4145  // point of the shower Tj. This is only done when there is no parent.
4146  if(cotID > (int)tjs.cots.size()) return;
4147 
4148  ShowerStruct& ss = tjs.cots[cotID - 1];
4149  if(ss.ID == 0) return;
4150  if(ss.TjIDs.empty()) return;
4151  if(ss.ShowerTjID == 0) return;
4152  if(ss.ParentID > 0) return;
4153  auto& stp0 = tjs.allTraj[ss.ShowerTjID - 1].Pts[0];
4154 
4155  std::string fcnLabel = inFcnLabel + ".FSC";
4156 
4157  stp0.AveChg = 0;
4158 
4159  if(ss.AspectRatio > tjs.ShowerTag[10] || ss.DirectionFOM > tjs.ShowerTag[9]) {
4160  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Not possible due to poor AspectRatio "<<ss.AspectRatio<<" or ss.DirectionFOM "<<ss.DirectionFOM;
4161  return;
4162  }
4163 
4164  // Create and fill a vector of the charge at the beginning of the shower in 1 WSE bins
4165  auto schg = StartChgVec(tjs, cotID, prt);
4166  if(schg.empty()) return;
4167 
4168  // Look for two consecutive charge entries. Use the second one
4169  // for the initial guess at the charge
4170  unsigned short startPt = USHRT_MAX;
4171  float chg = 0;
4172  for(unsigned short ii = 0; ii < schg.size() - 1; ++ii) {
4173  if(schg[ii] > 0 && schg[ii + 1] > 0) {
4174  startPt = ii + 1;
4175  chg = schg[ii + 1];
4176  break;
4177  }
4178  }
4179  if(startPt == USHRT_MAX) return;
4180 
4181  // get an initial average and rms using all the points
4182  float ave = 0;
4183  float rms = 0;
4184  float cnt = 0;
4185  for(unsigned short ii = startPt; ii < schg.size() - 1; ++ii) {
4186  ave += schg[ii];
4187  rms += schg[ii] * schg[ii];
4188  ++cnt;
4189  } // ii
4190  ave /= cnt;
4191  rms = rms - cnt * ave * ave;
4192  if(rms < 0) return;
4193  rms = sqrt(rms / (cnt - 1));
4194 
4195  if(prt) {
4196  mf::LogVerbatim myprt("TC");
4197  myprt<<fcnLabel<<" schg:";
4198  for(unsigned short ii = 0; ii < 20; ++ii) myprt<<" "<<(int)schg[ii];
4199  myprt<<"\n First guess at the charge "<<(int)chg<<" average charge of all bins "<<(int)ave<<" rms "<<(int)rms;
4200  }
4201 
4202  // initial guess at the charge rms
4203  rms = 0.8 * chg;
4204 
4205  // Correct for dead wires in this region - maybe later...
4206 // unsigned short nDeadWires = DeadWireCount();
4207 
4208  unsigned short nBinsAverage = 5;
4209  double maxChg = 2 * chg;
4210  for(unsigned short nit = 0; nit < 2; ++nit) {
4211  double sum = 0;
4212  double sum2 = 0;
4213  double cnt = 0;
4214  for(unsigned short ii = startPt; ii < schg.size() - 1; ++ii) {
4215  // break if we find 2 consecutive high charge points
4216  if(schg[ii] > maxChg && schg[ii + 1] > maxChg) break;
4217  // or two zeros
4218  if(schg[ii] == 0 && schg[ii + 1] == 0) break;
4219  if(schg[ii] > maxChg) continue;
4220  sum += schg[ii];
4221  sum2 += schg[ii] * schg[ii];
4222  ++cnt;
4223  if(cnt == nBinsAverage) break;
4224  } // ii
4225  // check for a failure
4226  if(cnt < 3) {
4227  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" nit "<<nit<<" cnt "<<cnt<<" is too low. sum "<<(int)sum<<" maxChg "<<(int)maxChg;
4228  // try to recover. Pick the next point
4229  ++startPt;
4230  chg = schg[startPt];
4231  maxChg = 2 * chg;
4232  continue;
4233  }
4234  // convert sum to the average charge
4235  chg = sum / cnt;
4236  double arg = sum2 - cnt * chg * chg;
4237  if(arg < 0) break;
4238  rms = sqrt(arg / (cnt - 1));
4239  // don't allow the rms to get crazy
4240  double maxrms = 0.5 * sum;
4241  if(rms > maxrms) rms = maxrms;
4242  maxChg = chg + 2 * rms;
4243  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" nit "<<nit<<" cnt "<<cnt<<" chg "<<(int)chg<<" rms "<<(int)rms<<" maxChg "<<(int)maxChg<<" nBinsAverage "<<nBinsAverage;
4244  nBinsAverage = 20;
4245  } // nit
4246 
4247  stp0.AveChg = chg;
4248 
4249  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 2S"<<cotID<<" Starting charge "<<(int)stp0.AveChg<<" startPt "<<startPt;
4250 
4251  } // FindStartChg
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< float > StartChgVec(TjStuff &tjs, int cotID, bool prt)
Definition: TCShower.cxx:4254
Float_t ss
Definition: plot.C:23
for(int i=0;i< 401;i++)
if(nlines<=0)
void tca::FindXMatches ( TjStuff tjs,
unsigned short  numPlanes,
short  maxScore,
std::vector< MatchStruct > &  matVec,
bool  prt 
)

Definition at line 1326 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, detinfo::DetectorProperties::ConvertXToTicks(), tca::MatchStruct::Count, geo::CryostatID::Cryostat, tca::TrajPoint::CTP, DecodeCTP(), DeltaAngle(), tca::TjStuff::detprop, tca::TrajPoint3::Dir, EncodeCTP(), tca::TjStuff::geom, tca::SortEntry::index, MakeTp3(), tca::TjStuff::mallTraj, tca::TjStuff::Match3DCuts, tca::TjStuff::MaxPos0, tca::TjStuff::NumPlanes, geo::PlaneID::Plane, tca::TrajPoint::Pos, tca::TrajPoint3::Pos, SignalAtTp(), tca::MatchStruct::TjIDs, geo::TPCID::TPC, tca::TjStuff::UnitsPerTick, valDecreasings(), and geo::GeometryCore::WireCoordinate().

Referenced by FindPFParticles().

1327  {
1328  // This function matches trajectory points in tjs.mallTraj using the X position. These points should
1329  // have already been sorted by increasing X by the function that created mallTraj.
1330 
1331  if(tjs.mallTraj.empty()) return;
1332  if(tjs.Match3DCuts[0] <= 0) return;
1333  if(numPlanes < 2) return;
1334 
1335  int cstat = DecodeCTP(tjs.mallTraj[0].ctp).Cryostat;
1336  int tpc = DecodeCTP(tjs.mallTraj[0].ctp).TPC;
1337  constexpr float twopi = 2 * M_PI;
1338  constexpr float piOver2 = M_PI / 2;
1339 
1340  // create a temp vector to check for duplicates
1341  auto inMatVec = matVec;
1342  std::vector<MatchStruct> temp;
1343 
1344  // the minimum number of points for matching
1345  unsigned short minPts = 2;
1346  // override this with the user minimum for 2-plane matches
1347  if(numPlanes == 2) minPts = tjs.Match3DCuts[2];
1348 
1349  // max number of match combos left
1350  unsigned int nAvailable = 0;
1351  if(matVec.size() < tjs.Match3DCuts[4]) nAvailable = tjs.Match3DCuts[4] - matVec.size();
1352  if(nAvailable == 0 || nAvailable > tjs.Match3DCuts[4]) return;
1353 
1354  // these cuts presume that the resolution in X is better than it is in Y and Z
1355  float xcut = tjs.Match3DCuts[0];
1356  double yzcut = 1.5 * xcut;
1357  for(unsigned int ipt = 0; ipt < tjs.mallTraj.size() - 1; ++ipt) {
1358  auto& iTjPt = tjs.mallTraj[ipt];
1359  // length cut
1360  if(iTjPt.npts < minPts) continue;
1361  // look for matches using Tjs that have the correct score
1362  if(iTjPt.score < 0 || iTjPt.score > maxScore) continue;
1363  auto& itp = tjs.allTraj[iTjPt.id - 1].Pts[iTjPt.ipt];
1364  unsigned short iplane = DecodeCTP(itp.CTP).Plane;
1365  for(unsigned int jpt = ipt + 1; jpt < tjs.mallTraj.size() - 1; ++jpt) {
1366  auto& jTjPt = tjs.mallTraj[jpt];
1367  // ensure that the planes are different
1368  if(jTjPt.ctp == iTjPt.ctp) continue;
1369  // length cut
1370  if(jTjPt.npts < minPts) continue;
1371  // score cut
1372  if(jTjPt.score < 0 || jTjPt.score > maxScore) continue;
1373  // check for x range overlap. We know that jTjPt.xlo is >= iTjPt.xlo because of the sort
1374  if(jTjPt.xlo > iTjPt.xhi) continue;
1375  // break out if the x range difference becomes large (5 cm)
1376  if(jTjPt.xlo > iTjPt.xhi + 5) break;
1377  auto& jtp = tjs.allTraj[jTjPt.id - 1].Pts[jTjPt.ipt];
1378  unsigned short jplane = DecodeCTP(jtp.CTP).Plane;
1379  TrajPoint3 tp3;
1380  if(!MakeTp3(tjs, itp, jtp, tp3, false)) continue;
1381  // count weight is one for a two-plane match
1382  float cntWght = 1;
1383  if(numPlanes == 3) {
1384  // numPlanes == 3
1385  for(unsigned int kpt = jpt + 1; kpt < tjs.mallTraj.size(); ++kpt) {
1386  auto& kTjPt = tjs.mallTraj[kpt];
1387  // ensure that the planes are different
1388  if(kTjPt.ctp == iTjPt.ctp || kTjPt.ctp == jTjPt.ctp) continue;
1389  if(kTjPt.score < 0 || kTjPt.score > maxScore) continue;
1390  if(kTjPt.xlo > iTjPt.xhi) continue;
1391  // break out if the x range difference becomes large
1392  if(kTjPt.xlo > iTjPt.xhi + 5) break;
1393  auto& ktp = tjs.allTraj[kTjPt.id - 1].Pts[kTjPt.ipt];
1394  unsigned short kplane = DecodeCTP(ktp.CTP).Plane;
1395  TrajPoint3 iktp3;
1396  if(!MakeTp3(tjs, itp, ktp, iktp3, false)) continue;
1397  if(std::abs(tp3.Pos[1] - iktp3.Pos[1]) > yzcut) continue;
1398  if(std::abs(tp3.Pos[2] - iktp3.Pos[2]) > yzcut) continue;
1399  float dang = 0;
1400  if(tjs.Match3DCuts[1] > 0) {
1401  dang = std::abs(DeltaAngle(tp3.Dir, iktp3.Dir));
1402  while(dang > M_PI) dang -= twopi;
1403  if(dang > piOver2) dang = M_PI - dang;
1404  float mcsmom = tjs.allTraj[iTjPt.id - 1].MCSMom + tjs.allTraj[jTjPt.id - 1].MCSMom + tjs.allTraj[kTjPt.id - 1].MCSMom;
1405  mcsmom /= 3;
1406  if(mcsmom > 150 && dang > tjs.Match3DCuts[1]) continue;
1407  }
1408  // we have a match.
1409  // Just fill temp. See if the Tj IDs are in the match list.
1410  // first check the input matVec
1411  bool gotit = false;
1412  for(auto& ms : inMatVec) {
1413  if(ms.TjIDs.size() != 3) continue;
1414  if(iTjPt.id == ms.TjIDs[iplane] && jTjPt.id == ms.TjIDs[jplane] && kTjPt.id == ms.TjIDs[kplane]) {
1415  gotit = true;
1416  break;
1417  }
1418  } // ms
1419  if(gotit) continue;
1420  // Triple match count = 2 de-weighted by delta angle
1421  cntWght = 2 - dang;
1422  if(cntWght <= 0) continue;
1423  // next check the temp vector
1424  unsigned short indx = 0;
1425  for(indx = 0; indx < temp.size(); ++indx) {
1426  auto& ms = temp[indx];
1427  if(iTjPt.id != ms.TjIDs[iplane]) continue;
1428  if(jTjPt.id != ms.TjIDs[jplane]) continue;
1429  if(kTjPt.id != ms.TjIDs[kplane]) continue;
1430  ms.Count += cntWght;
1431  break;
1432  } // indx
1433  if(indx == temp.size()) {
1434  // not found in the match vector so add it
1435  MatchStruct ms;
1436  ms.TjIDs.resize(3);
1437  // Note that we can put the Tj IDs in plane-order since there are 3 of them
1438  // This is not the case when there are 2 planes
1439  ms.TjIDs[iplane] = iTjPt.id;
1440  ms.TjIDs[jplane] = jTjPt.id;
1441  ms.TjIDs[kplane] = kTjPt.id;
1442  ms.Count = cntWght;
1443  temp.push_back(ms);
1444  // give up if there are too many
1445  if(temp.size() > nAvailable) break;
1446  } // not found in the list
1447  } // kpt
1448  // numPlanes == 3
1449  } else {
1450  // 2-plane TPC or 2-plane match in a 3-plane TPC
1451  if(tjs.NumPlanes == 3) {
1452  // See if there is a signal at this point.
1453  unsigned short kplane = 3 - iplane - jplane;
1454  float fkwire = tjs.geom->WireCoordinate(tp3.Pos[1], tp3.Pos[2], kplane, tpc, cstat);
1455  if(fkwire < 0 || fkwire > tjs.MaxPos0[kplane]) continue;
1456  TrajPoint tpk;
1457  tpk.CTP = EncodeCTP(cstat, tpc, kplane);
1458  tpk.Pos[0] = fkwire;
1459  float xp = 0.5 * (iTjPt.xlo + iTjPt.xhi);
1460  tpk.Pos[1] = tjs.detprop->ConvertXToTicks(xp, kplane, tpc, cstat) * tjs.UnitsPerTick;
1461  // Note that SignalAtTp assumes that a signal exists if the wire is dead
1462  if(!SignalAtTp(tjs, tpk)) continue;
1463  }
1464  // Just fill temp. See if the Tj IDs are in the match list
1465  bool gotit = false;
1466  for(auto& ms : inMatVec) {
1467  if(std::find(ms.TjIDs.begin(), ms.TjIDs.end(), iTjPt.id) != ms.TjIDs.end() &&
1468  std::find(ms.TjIDs.begin(), ms.TjIDs.end(), jTjPt.id) != ms.TjIDs.end()) {
1469  gotit = true;
1470  break;
1471  }
1472  } // ms
1473  if(gotit) continue;
1474  unsigned short indx = 0;
1475  for(indx = 0; indx < temp.size(); ++indx) {
1476  auto& ms = temp[indx];
1477  if(std::find(ms.TjIDs.begin(), ms.TjIDs.end(), iTjPt.id) != ms.TjIDs.end() &&
1478  std::find(ms.TjIDs.begin(), ms.TjIDs.end(), jTjPt.id) != ms.TjIDs.end()) break;
1479  } // indx
1480  if(indx == temp.size()) {
1481  MatchStruct ms;
1482  ms.TjIDs.resize(2);
1483  // Here we put the Tj IDs in no particular order
1484  ms.TjIDs[0] = iTjPt.id;
1485  ms.TjIDs[1] = jTjPt.id;
1486  ms.Count = 1;
1487  temp.push_back(ms);
1488  } // not found in the list
1489  else {
1490  ++temp[indx].Count;
1491  }
1492  } // 2-plane TPC
1493  // give up if there are too many
1494  if(temp.size() > nAvailable) break;
1495  } // jpt
1496  // give up if there are too many
1497  if(temp.size() > nAvailable) break;
1498  } // ipt
1499 
1500  // temp
1501 
1502  if(temp.empty()) return;
1503 
1504  if(temp.size() == 1) {
1505  matVec.push_back(temp[0]);
1506  } else {
1507  // multiple entries - need to sort by decreasing match count
1508  std::vector<SortEntry> sortVec(temp.size());
1509  for(unsigned int indx = 0; indx < sortVec.size(); ++indx) {
1510  sortVec[indx].index = indx;
1511  sortVec[indx].val = temp[indx].Count;
1512  } // indx
1513  std::sort(sortVec.begin(), sortVec.end(), valDecreasings);
1514  // Re-order temp
1515  auto tmpVec = temp;
1516  for(unsigned int ii = 0; ii < sortVec.size(); ++ii) temp[ii] = tmpVec[sortVec[ii].index];
1517  // insert it after the triple matches
1518  matVec.insert(matVec.end(), temp.begin(), temp.end());
1519  } // temp size > 1
1520 
1521  if(prt) mf::LogVerbatim("TC")<<"FindXMatches: Found "<<temp.size()<<" matches";
1522 
1523  } // FindXMatches
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1607
bool MakeTp3(TjStuff &tjs, const TrajPoint &itp, const TrajPoint &jtp, TrajPoint3 &tp3, bool findDirection)
Definition: PFPUtils.cxx:1526
bool SignalAtTp(TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:1639
bool valDecreasings(SortEntry c1, SortEntry c2)
Definition: PFPUtils.cxx:12
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
void tca::Finish3DShowers ( TjStuff tjs)

Definition at line 131 of file TCShower.cxx.

References tca::TjStuff::allTraj, ChkAssns(), tca::TjStuff::cots, CreatePFP(), DecodeCTP(), evd::details::end(), GetAssns(), kKilled, kUsedHits, tca::TjStuff::pfps, geo::PlaneID::Plane, PutTrajHitsInVector(), tca::TjStuff::showers, ss, tca::TjStuff::TPCID, TransferTjHits(), tca::TjStuff::vtx, tca::TjStuff::vtx3, and tca::Trajectory::VtxID.

Referenced by tca::TrajClusterAlg::MakeAllTrajClusters().

132  {
133  // Finish defining the showers, create a companion PFParticle for each one.
134  // Note to the reader: This code doesn't use MakeVertexObsolete to kill vertices using the assumption
135  // that Finish3DShowers is being called after reconstruction is complete, in which case there is no
136  // need to re-calculate the 2D and 3D vertex score which could potentially screw up the decisions that have
137  // already been made.
138 
139  // See if any need to be finished
140  bool noShowers = true;
141  for(auto& ss3 : tjs.showers) {
142  if(ss3.ID == 0) continue;
143  noShowers = false;
144  }
145  if(noShowers) return;
146 
147  ChkAssns("Fin3D", tjs);
148 
149  // create a pfp and define the mother-daughter relationship. At this point, the shower parent PFP (if
150  // one exists) is a track-like pfp that might be the daughter of another pfp, e.g. the neutrino. This
151  // association is changed from shower ParentID -> parent pfp, to shower PFP -> parent pfp
152  for(auto& ss3 : tjs.showers) {
153  if(ss3.ID == 0) continue;
154  if(ss3.Cheat) continue;
155  if(ss3.PFPIndex != USHRT_MAX) {
156  std::cout<<"Finish3DShowers 3S"<<ss3.ID<<" already has a pfp associated with it...\n";
157  continue;
158  }
159  auto showerPFP = CreatePFP(tjs, ss3.TPCID);
160  showerPFP.TjIDs.resize(ss3.CotIDs.size());
161  for(unsigned short ii = 0; ii < ss3.CotIDs.size(); ++ii) {
162  unsigned short cid = ss3.CotIDs[ii];
163  if(cid == 0 || cid > tjs.cots.size()) {
164  std::cout<<"Finish3DShowers 3S"<<ss3.ID<<" has an invalid cots ID"<<cid<<"\n";
165  return;
166  }
167  auto& ss = tjs.cots[cid - 1];
168  auto& stj = tjs.allTraj[ss.ShowerTjID - 1];
169  showerPFP.TjIDs[ii] = stj.ID;
170  } // ci
171  showerPFP.PDGCode = 1111;
172  showerPFP.XYZ[0] = ss3.Start;
173  showerPFP.Dir[0] = ss3.Dir;
174  showerPFP.DirErr[0] = ss3.DirErr;
175  showerPFP.Vx3ID[0] = ss3.Vx3ID;
176  showerPFP.XYZ[1] = ss3.End;
177  showerPFP.Dir[1] = ss3.Dir;
178  // dEdx is indexed by plane for pfps and by 2D shower index for 3D showers
179  for(auto cid : ss3.CotIDs) {
180  auto& ss = tjs.cots[cid - 1];
181  unsigned short plane = DecodeCTP(ss.CTP).Plane;
182  auto& stj = tjs.allTraj[ss.ShowerTjID - 1];
183  showerPFP.dEdx[0][plane] = stj.dEdx[0];
184  showerPFP.dEdxErr[0][plane] = 0.3 * stj.dEdx[0];
185  } // ci
186  ss3.PFPIndex = tjs.pfps.size();
187  if(ss3.ParentID > 0) {
188  // see if this is a daughter
189  auto& dtrPFP = tjs.pfps[ss3.ParentID - 1];
190  if(dtrPFP.ParentID > 0) {
191  // Transfer the daughter <-> parent assn
192  auto& parPFP = tjs.pfps[dtrPFP.ParentID - 1];
193  showerPFP.ParentID = parPFP.ID;
194  std::replace(parPFP.DtrIDs.begin(), parPFP.DtrIDs.end(), dtrPFP.ID, showerPFP.ID);
195  dtrPFP.ParentID = 0;
196  } // dtrPFP.ParentID > 0
197  } // ss3.ParentID > 0
198  tjs.pfps.push_back(showerPFP);
199  } // ss3
200 
201  // Transfer Tj hits from InShower Tjs to the shower Tj. This kills the InShower Tjs but doesn't consider how
202  // this action affects vertices
203  if(!TransferTjHits(tjs, false)) return;
204 
205  // Associate shower Tj hits with 3D showers
206  for(auto& ss3 : tjs.showers) {
207  if(ss3.ID == 0) continue;
208  for(unsigned short ii = 0; ii < ss3.CotIDs.size(); ++ii) {
209  unsigned short cid = ss3.CotIDs[ii];
210  auto& ss = tjs.cots[cid - 1];
211  for(auto tjid : ss.TjIDs) {
212  Trajectory& tj = tjs.allTraj[tjid - 1];
213  auto tjHits = PutTrajHitsInVector(tj, kUsedHits);
214  ss3.Hits.insert(ss3.Hits.end(), tjHits.begin(), tjHits.end());
215  // kill vertices associated with the Tj unless it is the neutrino primary vtx
216  for(unsigned short end = 0; end < 2; ++end) {
217  if(tj.VtxID[end] == 0) continue;
218  auto& vx2 = tjs.vtx[tj.VtxID[end] - 1];
219  if(vx2.Vx3ID <= 0) {
220  // This is a 2D vertex that is not matched in 3D. Kill it. Shouldn't need to
221  // use MakeVertexObsolete here...
222  vx2.ID = 0;
223  continue;
224  }
225  // vx2 is matched in 3D. Kill it if it is NOT the neutrino primary
226  auto& vx3 = tjs.vtx3[vx2.Vx3ID - 1];
227  if(vx3.Neutrino) continue;
228  vx3.ID = 0;
229  } // end
230  } // tjid
231  } // ii
232  } // ss3
233 
234  // kill PFParticles
235  if(!tjs.pfps.empty()) {
236  for(auto& pfp : tjs.pfps) {
237  if(pfp.ID == 0) continue;
238  if(pfp.TjIDs.empty()) continue;
239  unsigned short ndead = 0;
240  for(auto tjid : pfp.TjIDs) {
241  auto& tj = tjs.allTraj[tjid - 1];
242  if(tj.AlgMod[kKilled]) ++ndead;
243  } // tjid
244  if(ndead == 0) continue;
245  if(ndead != pfp.TjIDs.size()) {
246  std::cout<<"Finish3DShowers: Not all Tjs in P"<<pfp.ID<<" are killed";
247  for(auto tid : pfp.TjIDs) {
248  auto& tj = tjs.allTraj[tid - 1];
249  std::cout<<" T"<<tid<<" dead? "<<tj.AlgMod[kKilled];
250  }
251  std::cout<<"\n";
252  } // ndead
253  pfp.ID = 0;
254  } // pfp
255  } // pfps not empty
256 
257  // kill orphan 2D vertices
258  for(auto& vx2 : tjs.vtx) {
259  if(vx2.ID == 0) continue;
260  auto vxtjs = GetAssns(tjs, "2V", vx2.ID, "T");
261  if(vxtjs.empty()) vx2.ID = 0;
262  } // vx2
263 
264  // kill orphan vertices
265  for(auto& vx3 : tjs.vtx3) {
266  if(vx3.ID == 0) continue;
267  auto vxtjs = GetAssns(tjs, "3V", vx3.ID, "T");
268  if(vxtjs.empty()) {
269  vx3.ID = 0;
270  continue;
271  }
272  } // vx3
273 
274  // check
275  for(auto& pfp : tjs.pfps) {
276  if(pfp.ID == 0) continue;
277  if(pfp.PDGCode != 1111) continue;
278  if(pfp.Vx3ID[0] > 0 && tjs.vtx3[pfp.Vx3ID[0] - 1].ID == 0) {
279  std::cout<<"Finish3DShowers shower P"<<pfp.ID<<" has Vx3ID[0] = "<<pfp.Vx3ID[0]<<" but the vertex is killed\n";
280  } // Vx3 check
281  } // pfp
282 
283  } // Finish3DShowers
bool TransferTjHits(TjStuff &tjs, bool prt)
Definition: TCShower.cxx:4383
std::vector< unsigned int > PutTrajHitsInVector(Trajectory const &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2283
bool ChkAssns(std::string inFcnLabel, TjStuff &tjs)
Definition: TCShower.cxx:4625
Float_t ss
Definition: plot.C:23
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
PFPStruct CreatePFP(const TjStuff &tjs, const geo::TPCID &tpcid)
Definition: PFPUtils.cxx:1943
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
std::vector< int > GetAssns(const TjStuff &tjs, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4079
void tca::Fit3D ( unsigned short  mode,
Point3_t  point,
Vector3_t  dir,
Point3_t fitPos,
Vector3_t fitDir 
)

Definition at line 899 of file PFPUtils.cxx.

References SetMag().

Referenced by FindCompleteness().

900  {
901  // initialize, accumulate and fit the points. The code to fit the direction using the positions
902  // of the points is commented out and replaced with a simple average of the directions of the points
903 
904  // 3D fit sum variables
905  static double fSum, fSumx, fSumy, fSumz;
906 // static double fSumx2, fSumy2, fSumz2, fSumxz, fSumyz;
907  // average the direction vectors
908  static double fSumDir0, fSumDir1, fSumDir2;
909 
910  if(mode == 0) {
911  fSum = 0; fSumx = 0; fSumy = 0; fSumz = 0;
912 // fSumx2 = 0; fSumy2 = 0; fSumz2 = 0; fSumxz = 0; fSumyz = 0;
913  fSumDir0 = 0; fSumDir1 = 0; fSumDir2 = 0;
914  return;
915  }
916  // accumulate
917  if(mode == 1) {
918  fSum += 1;
919  fSumx += point[0];
920  fSumy += point[1];
921  fSumz += point[2];
922 /*
923  fSumx2 += point[0] * point[0];
924  fSumy2 += point[1] * point[1];
925  fSumz2 += point[2] * point[2];
926  fSumxz += point[0] * point[2];
927  fSumyz += point[1] * point[2];
928 */
929  fSumDir0 += dir[0];
930  fSumDir1 += dir[1];
931  fSumDir2 += dir[2];
932  return;
933  }
934 
935  if(fSum < 2) return;
936  // just use the average for the position
937  fitPos[0] = fSumx / fSum;
938  fitPos[1] = fSumy / fSum;
939  fitPos[2] = fSumz / fSum;
940  // and for the direction
941  fitDir = {{fSumDir0, fSumDir1, fSumDir2}};
942  SetMag(fitDir, 1);
943 /*
944  std::cout<<"fitDir"<<std::fixed<<std::setprecision(2);
945  std::cout<<" "<<fitDir[0]<<" "<<fitDir[1]<<" "<<fitDir[2];
946 
947  // calculate the direction
948  double delta = fSum * fSumz2 - fSumz * fSumz;
949  if(delta == 0) return;
950  double Bx = (fSumxz * fSum - fSumz * fSumx) / delta;
951  double By = (fSumyz * fSum - fSumz * fSumy) / delta;
952  double norm = sqrt(1 + Bx * Bx + By * By);
953  Vector3_t tmpDir;
954  tmpDir[0] = Bx / norm;
955  tmpDir[1] = By / norm;
956  tmpDir[2] = 1 / norm;
957  std::cout<<" tmpDir"<<std::fixed<<std::setprecision(2);
958  std::cout<<" "<<tmpDir[0]<<" "<<tmpDir[1]<<" "<<tmpDir[2]<<"\n";
959 */
960  } // Fit3D
bool SetMag(Vector3_t &v1, double mag)
Definition: PFPUtils.cxx:1641
TDirectory * dir
Definition: macro.C:5
bool tca::FitTp3 ( TjStuff tjs,
TrajPoint3 tp3,
const std::vector< Tj2Pt > &  tj2pts 
)

Definition at line 502 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, detinfo::DetectorProperties::ConvertTicksToX(), geo::CryostatID::Cryostat, DecodeCTP(), tca::TjStuff::detprop, tca::TrajPoint3::Dir, tca::TjStuff::geom, norm, geo::PlaneID::Plane, tca::TrajPoint3::Pos, PosSep(), PosSep2(), sw, geo::TPCID::TPC, tca::TjStuff::UnitsPerTick, w, geo::GeometryCore::WireCoordinate(), and x.

503  {
504  // Fits the vector of Tj2Pts points and puts the results into tp3. This code is adapted
505  // from TrackLineFitAlg: SVD fit adapted from $ROOTSYS/tutorials/matrix/solveLinear.C
506  // Fit equation is w = A(X)v, where w is a vector of hit wires, A is
507  // a matrix to calculate a track projected to a point at X, and v is
508  // a vector (Yo, Zo, dY/dX, dZ/dX).
509  if(tj2pts.size() < 4) return false;
510 
511  const unsigned int nvars = 4;
512  unsigned int npts = tj2pts.size();
513  TMatrixD A(npts, nvars);
514  // vector holding the Wire number
515  TVectorD w(npts);
516 
517  double x0 = 0;
518  for(auto& tj2pt : tj2pts) {
519  auto& tp = tjs.allTraj[tj2pt.id - 1].Pts[tj2pt.ipt];
520  geo::PlaneID planeID = DecodeCTP(tp.CTP);
521  x0 += tjs.detprop->ConvertTicksToX(tp.Pos[1]/tjs.UnitsPerTick, planeID);
522  }
523  x0 /= (double)tj2pts.size();
524 
525  unsigned short ninpl[3] = {0};
526  unsigned short nok = 0;
527  double wght = 1;
528  for(unsigned short ipt = 0; ipt < tj2pts.size(); ++ipt) {
529  auto& tj2pt = tj2pts[ipt];
530  auto& tp = tjs.allTraj[tj2pt.id - 1].Pts[tj2pt.ipt];
531  geo::PlaneID planeID = DecodeCTP(tp.CTP);
532  unsigned int cstat = planeID.Cryostat;
533  unsigned int tpc = planeID.TPC;
534  unsigned int plane = planeID.Plane;
535  // get the wire plane offset
536  double off = tjs.geom->WireCoordinate(0, 0, plane, tpc, cstat);
537  // get the "cosine-like" component
538  double cw = tjs.geom->WireCoordinate(1, 0, plane, tpc, cstat) - off;
539  // the "sine-like" component
540  double sw = tjs.geom->WireCoordinate(0, 1, plane, tpc, cstat) - off;
541  double x = tjs.detprop->ConvertTicksToX(tp.Pos[1]/tjs.UnitsPerTick, planeID) - x0;
542  A[ipt][0] = wght * cw;
543  A[ipt][1] = wght * sw;
544  A[ipt][2] = wght * cw * x;
545  A[ipt][3] = wght * sw * x;
546  w[ipt] = wght * (tp.Pos[0] - off);
547  ++ninpl[plane];
548  // need at least two points in a plane
549  if(ninpl[plane] == 2) ++nok;
550  } // ipt
551 
552  // need at least 2 planes with at least two points
553  if(nok < 2) return false;
554 
555  TDecompSVD svd(A);
556  bool ok;
557  TVectorD tVec = svd.Solve(w, ok);
558 
559  // Calculate Chi/DOF here
560 // tp3.ChiDOF = 1;
561 
562  Vector3_t fitDir;
563  double norm = sqrt(1 + tVec[2] * tVec[2] + tVec[3] * tVec[3]);
564  fitDir[0] = 1 / norm;
565  fitDir[1] = tVec[2] / norm;
566  fitDir[2] = tVec[3] / norm;
567 
568  Point3_t fitPos;
569  fitPos[0] = x0;
570  fitPos[1] = tVec[0];
571  fitPos[2] = tVec[1];
572  // move it to the same Z position as tp3.Pos
573  if(tp3.Pos[2] != 0) {
574  double dz = tp3.Pos[2] - fitPos[2];
575  fitPos[0] += dz * fitDir[0] / fitDir[2];
576  fitPos[1] += dz * fitDir[1] / fitDir[2];
577  fitPos[2] += dz;
578  }
579 
580  if(PosSep2(fitPos, tp3.Pos) > 5) {
581  std::cout<<"Crazy fitPos "<<PosSep(fitPos, tp3.Pos)<<"\n";
582 // tp3.ChiDOF = 10;
583  return false;
584  }
585 
586  tp3.Pos = fitPos;
587  tp3.Dir = fitDir;
588 
589  return true;
590  } // FitTp3
Float_t x
Definition: compare.C:6
std::array< double, 3 > Point3_t
Definition: DataStructs.h:35
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1631
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
Float_t sw
Definition: plot.C:23
Float_t norm
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
std::array< double, 3 > Vector3_t
Definition: DataStructs.h:36
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
Float_t w
Definition: plot.C:23
bool tca::FitTp3s ( TjStuff tjs,
const std::vector< TrajPoint3 > &  tp3s,
Point3_t pos,
Vector3_t dir,
float &  rCorr 
)

Definition at line 412 of file PFPUtils.cxx.

References dir.

413  {
414  return FitTp3s(tjs, tp3s, 0, tp3s.size(), pos, dir, rCorr);
415  } // FitTp3s
bool FitTp3s(TjStuff &tjs, const std::vector< TrajPoint3 > &tp3s, unsigned short fromPt, unsigned short toPt, Point3_t &pos, Vector3_t &dir, float &rCorr)
Definition: PFPUtils.cxx:418
TDirectory * dir
Definition: macro.C:5
bool tca::FitTp3s ( TjStuff tjs,
const std::vector< TrajPoint3 > &  tp3s,
unsigned short  fromPt,
unsigned short  toPt,
Point3_t pos,
Vector3_t dir,
float &  rCorr 
)

Definition at line 418 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, detinfo::DetectorProperties::ConvertTicksToX(), geo::CryostatID::Cryostat, DecodeCTP(), tca::TjStuff::detprop, tca::TjStuff::geom, norm, tca::TjStuff::NumPlanes, geo::PlaneID::Plane, sw, geo::TPCID::TPC, tca::TjStuff::UnitsPerTick, w, geo::GeometryCore::WireCoordinate(), and x.

419  {
420  // Fits the Tj2Pts points in Tp3s to a line
421  if(tp3s.size() < 3) return false;
422  if(fromPt >= toPt) return false;
423  if(toPt > tp3s.size()) return false;
424 
425  // temp vectors to ensure that a TP is only used once
426  std::vector<unsigned short> useID;
427  std::vector<unsigned short> useIpt;
428  std::vector<unsigned short> cntInPln(tjs.NumPlanes);
429  for(unsigned short ipt = fromPt; ipt < toPt; ++ipt) {
430  auto& tp3 = tp3s[ipt];
431  for(auto& tj2pt : tp3.Tj2Pts) {
432  bool isUsed = false;
433  for(unsigned short ii = 0; ii < useID.size(); ++ii) {
434  if(tj2pt.id == useID[ii] && tj2pt.ipt == useIpt[ii]) isUsed = true;
435  } // ii
436  if(isUsed) continue;
437  // add it to the list
438  useID.push_back(tj2pt.id);
439  useIpt.push_back(tj2pt.ipt);
440  auto& tj = tjs.allTraj[tj2pt.id - 1];
441  ++cntInPln[DecodeCTP(tj.CTP).Plane];
442  } // tj2pt
443  } // ipt
444  // ensure there are at least two points in at least two planes
445  unsigned short enufInPlane = 0;
446  for(unsigned short plane = 0; plane < tjs.NumPlanes; ++plane) if(cntInPln[plane] > 1) ++enufInPlane;
447  if(enufInPlane < 2) return false;
448 
449  const unsigned int nvars = 4;
450  unsigned int npts = useID.size();
451  TMatrixD A(npts, nvars);
452  // vector holding the Wire number
453  TVectorD w(npts);
454 
455  // X origin
456  double x0 = 0;
457  for(unsigned short ipt = 0; ipt < useID.size(); ++ipt) {
458  auto& tp = tjs.allTraj[useID[ipt] - 1].Pts[useIpt[ipt]];
459  geo::PlaneID planeID = DecodeCTP(tp.CTP);
460  x0 += tjs.detprop->ConvertTicksToX(tp.Pos[1]/tjs.UnitsPerTick, planeID);
461  }
462  x0 /= (double)useID.size();
463 
464  double wght = 1;
465  for(unsigned short ipt = 0; ipt < useID.size(); ++ipt) {
466  auto& tp = tjs.allTraj[useID[ipt] - 1].Pts[useIpt[ipt]];
467  geo::PlaneID planeID = DecodeCTP(tp.CTP);
468  unsigned int cstat = planeID.Cryostat;
469  unsigned int tpc = planeID.TPC;
470  unsigned int plane = planeID.Plane;
471  // get the wire plane offset
472  double off = tjs.geom->WireCoordinate(0, 0, plane, tpc, cstat);
473  // get the "cosine-like" component
474  double cw = tjs.geom->WireCoordinate(1, 0, plane, tpc, cstat) - off;
475  // the "sine-like" component
476  double sw = tjs.geom->WireCoordinate(0, 1, plane, tpc, cstat) - off;
477  double x = tjs.detprop->ConvertTicksToX(tp.Pos[1]/tjs.UnitsPerTick, planeID) - x0;
478  A[ipt][0] = wght * cw;
479  A[ipt][1] = wght * sw;
480  A[ipt][2] = wght * cw * x;
481  A[ipt][3] = wght * sw * x;
482  w[ipt] = wght * (tp.Pos[0] - off);
483  } // ipt
484 
485  TDecompSVD svd(A);
486  bool ok;
487  TVectorD tVec = svd.Solve(w, ok);
488  double norm = sqrt(1 + tVec[2] * tVec[2] + tVec[3] * tVec[3]);
489  dir[0] = 1 / norm;
490  dir[1] = tVec[2] / norm;
491  dir[2] = tVec[3] / norm;
492  pos[0] = x0;
493  pos[1] = tVec[0];
494  pos[2] = tVec[1];
495  rCorr = 1;
496  std::cout<<"FTP3s: "<<useID.size()<<" cntInPln "<<cntInPln[0]<<" "<<cntInPln[1]<<" "<<cntInPln[2]<<"\n";
497  return true;
498 
499  } // FitTp3s
Float_t x
Definition: compare.C:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
Float_t sw
Definition: plot.C:23
Float_t norm
TDirectory * dir
Definition: macro.C:5
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
Float_t w
Definition: plot.C:23
void tca::FitTraj ( TjStuff tjs,
Trajectory tj 
)

Definition at line 673 of file Utils.cxx.

References tca::Trajectory::EndPt, FitTraj(), and tca::Trajectory::Pts.

Referenced by tca::TrajClusterAlg::EndMerge(), tca::TrajClusterAlg::GottaKink(), tca::TrajClusterAlg::HiEndDelta(), tca::TrajClusterAlg::MaskBadTPs(), tca::TrajClusterAlg::MaskedHitsOK(), tca::TrajClusterAlg::PrepareForNextPass(), and tca::TrajClusterAlg::UpdateTraj().

674  {
675  // Jacket around FitTraj to fit the leading edge of the supplied trajectory
676  unsigned short originPt = tj.EndPt[1];
677  unsigned short npts = tj.Pts[originPt].NTPsFit;
678  TrajPoint tpFit;
679  unsigned short fitDir = -1;
680  FitTraj(tjs, tj, originPt, npts, fitDir, tpFit);
681  tj.Pts[originPt] = tpFit;
682 
683  } // FitTraj
void FitTraj(TjStuff &tjs, Trajectory &tj, unsigned short originPt, unsigned short npts, short fitDir, TrajPoint &tpFit)
Definition: Utils.cxx:686
void tca::FitTraj ( TjStuff tjs,
Trajectory tj,
unsigned short  originPt,
unsigned short  npts,
short  fitDir,
TrajPoint tpFit 
)

Definition at line 686 of file Utils.cxx.

References tca::TrajPoint::Ang, tca::TrajPoint::AngErr, tca::TrajPoint::AngleCode, AngleRange(), B, dir, tca::TrajPoint::Dir, tca::Trajectory::EndPt, tca::TrajPoint::FitChi, MoveTPToWire(), NumPtsWithCharge(), geo::origin(), tca::TrajPoint::Pos, tca::Trajectory::Pts, SetAngleCode(), w, x, xx, and y.

Referenced by FitTraj().

687  {
688  // Fit the supplied trajectory using HitPos positions with the origin at originPt.
689  // The npts is interpreted as the number of points on each side of the origin
690  // The allowed modes are as follows, where i denotes a TP that is included, . denotes
691  // a TP with no hits, and x denotes a TP that is not included
692  //TP 012345678 fitDir originPt npts
693  // Oiiixxxxx 1 0 4 << npts in the fit
694  // xi.iiOxxx -1 5 4
695  // xiiiOiiix 0 4 4 << 2 * npts + 1 points in the fit
696  // xxxiO.ixx 0 4 1
697  // 0iiixxxxx 0 0 4
698  // This routine puts the results into tp if the fit is successfull. The
699  // fit "direction" is in increasing order along the trajectory from 0 to tj.Pts.size() - 1.
700 
701  // static const float twoPi = 2 * M_PI;
702 
703  if(originPt > tj.Pts.size() - 1) {
704  mf::LogWarning("TC")<<"FitTraj: Requesting fit of invalid TP "<<originPt;
705  return;
706  }
707 
708  // copy the origin TP into the fit TP
709  tpFit = tj.Pts[originPt];
710  // Assume that the fit will fail
711  tpFit.FitChi = 999;
712  if(fitDir < -1 || fitDir > 1) return;
713 
714  std::vector<double> x, y;
715  Point2_t origin = tj.Pts[originPt].HitPos;
716  // Use TP position if there aren't any hits on it
717  if(tj.Pts[originPt].Chg == 0) origin = tj.Pts[originPt].Pos;
718 
719  // simple two point case
720  if(NumPtsWithCharge(tjs, tj, false) == 2) {
721  for(unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1]; ++ipt) {
722  if(tj.Pts[ipt].Chg == 0) continue;
723  double xx = tj.Pts[ipt].HitPos[0] - origin[0];
724  double yy = tj.Pts[ipt].HitPos[1] - origin[1];
725  x.push_back(xx);
726  y.push_back(yy);
727  } // ii
728  if(x.size() != 2) return;
729  if(x[0] == x[1]) {
730  // Either + or - pi/2
731  tpFit.Ang = M_PI/2;
732  if(y[1] < y[0]) tpFit.Ang = -tpFit.Ang;
733  } else {
734  double dx = x[1] - x[0];
735  double dy = y[1] - y[0];
736  tpFit.Ang = atan2(dy, dx);
737  }
738  tpFit.Dir[0] = cos(tpFit.Ang);
739  tpFit.Dir[1] = sin(tpFit.Ang);
740  tpFit.Pos[0] += origin[0];
741  tpFit.Pos[1] += origin[1];
742  tpFit.AngErr = 0.01;
743  tpFit.FitChi = 0.01;
744  SetAngleCode(tjs, tpFit);
745  return;
746  } // two points
747 
748  std::vector<double> w, q;
749  std::array<double, 2> dir;
750  double xx, yy, xr, yr;
751  double chgWt;
752 
753  // Rotate the traj hit position into the coordinate system defined by the
754  // originPt traj point, where x = along the trajectory, y = transverse
755  double rotAngle = tj.Pts[originPt].Ang;
756  double cs = cos(-rotAngle);
757  double sn = sin(-rotAngle);
758 
759  // enter the originPT hit info if it exists
760  if(tj.Pts[originPt].Chg > 0) {
761  xx = tj.Pts[originPt].HitPos[0] - origin[0];
762  yy = tj.Pts[originPt].HitPos[1] - origin[1];
763  xr = cs * xx - sn * yy;
764  yr = sn * xx + cs * yy;
765  x.push_back(xr);
766  y.push_back(yr);
767  chgWt = tj.Pts[originPt].ChgPull;
768  if(chgWt < 1) chgWt = 1;
769  chgWt *= chgWt;
770  w.push_back(chgWt * tj.Pts[originPt].HitPosErr2);
771  }
772 
773  // correct npts to account for the origin point
774  if(fitDir != 0) --npts;
775 
776  // step in the + direction first
777  if(fitDir != -1) {
778  unsigned short cnt = 0;
779  for(unsigned short ipt = originPt + 1; ipt < tj.Pts.size(); ++ipt) {
780  if(tj.Pts[ipt].Chg == 0) continue;
781  xx = tj.Pts[ipt].HitPos[0] - origin[0];
782  yy = tj.Pts[ipt].HitPos[1] - origin[1];
783  xr = cs * xx - sn * yy;
784  yr = sn * xx + cs * yy;
785  x.push_back(xr);
786  y.push_back(yr);
787  chgWt = tj.Pts[ipt].ChgPull;
788  if(chgWt < 1) chgWt = 1;
789  chgWt *= chgWt;
790  w.push_back(chgWt * tj.Pts[ipt].HitPosErr2);
791  ++cnt;
792  if(cnt == npts) break;
793  } // ipt
794  } // fitDir != -1
795 
796  // step in the - direction next
797  if(fitDir != 1 && originPt > 0) {
798  unsigned short cnt = 0;
799  for(unsigned short ii = 1; ii < tj.Pts.size(); ++ii) {
800  unsigned short ipt = originPt - ii;
801  if(ipt > tj.Pts.size() - 1) continue;
802  if(tj.Pts[ipt].Chg == 0) continue;
803  xx = tj.Pts[ipt].HitPos[0] - origin[0];
804  yy = tj.Pts[ipt].HitPos[1] - origin[1];
805  xr = cs * xx - sn * yy;
806  yr = sn * xx + cs * yy;
807  x.push_back(xr);
808  y.push_back(yr);
809  chgWt = tj.Pts[ipt].ChgPull;
810  if(chgWt < 1) chgWt = 1;
811  chgWt *= chgWt;
812  w.push_back(chgWt * tj.Pts[ipt].HitPosErr2);
813  ++cnt;
814  if(cnt == npts) break;
815  if(ipt == 0) break;
816  } // ipt
817  } // fitDir != -1
818 
819  // Not enough points to define a line?
820  if(x.size() < 2) return;
821 
822  double sum = 0.;
823  double sumx = 0.;
824  double sumy = 0.;
825  double sumxy = 0.;
826  double sumx2 = 0.;
827  double sumy2 = 0.;
828 
829  // weight by the charge ratio and accumulate sums
830  double wght;
831  for(unsigned short ipt = 0; ipt < x.size(); ++ipt) {
832  if(w[ipt] < 0.00001) w[ipt] = 0.00001;
833  wght = 1 / w[ipt];
834  sum += wght;
835  sumx += wght * x[ipt];
836  sumy += wght * y[ipt];
837  sumx2 += wght * x[ipt] * x[ipt];
838  sumy2 += wght * y[ipt] * y[ipt];
839  sumxy += wght * x[ipt] * y[ipt];
840  }
841  // calculate coefficients and std dev
842  double delta = sum * sumx2 - sumx * sumx;
843  if(delta == 0) return;
844  // A is the intercept
845  double A = (sumx2 * sumy - sumx * sumxy) / delta;
846  // B is the slope
847  double B = (sumxy * sum - sumx * sumy) / delta;
848 
849  // The chisq will be set below if there are enough points. Don't allow it to be 0
850  // so we can take Chisq ratios later
851  tpFit.FitChi = 0.01;
852  double newang = atan(B);
853  dir[0] = cos(newang);
854  dir[1] = sin(newang);
855  // rotate back into the (w,t) coordinate system
856  cs = cos(rotAngle);
857  sn = sin(rotAngle);
858  tpFit.Dir[0] = cs * dir[0] - sn * dir[1];
859  tpFit.Dir[1] = sn * dir[0] + cs * dir[1];
860  // ensure that the direction is consistent with the originPt direction
861  bool flipDir = false;
862  if(AngleRange(tjs, tj.Pts[originPt]) > 0) {
863  flipDir = std::signbit(tpFit.Dir[1]) != std::signbit(tj.Pts[originPt].Dir[1]);
864  } else {
865  flipDir = std::signbit(tpFit.Dir[0]) != std::signbit(tj.Pts[originPt].Dir[0]);
866  }
867  if(flipDir) {
868  tpFit.Dir[0] = -tpFit.Dir[0];
869  tpFit.Dir[1] = -tpFit.Dir[1];
870  }
871  tpFit.Ang = atan2(tpFit.Dir[1], tpFit.Dir[0]);
872  SetAngleCode(tjs, tpFit);
873  // if(prt) mf::LogVerbatim("TC")<<"FitTraj "<<originPt<<" originPt Dir "<<tj.Pts[originPt].Dir[0]<<" "<<tj.Pts[originPt].Dir[1]<<" rotAngle "<<rotAngle<<" tpFit.Dir "<<tpFit.Dir[0]<<" "<<tpFit.Dir[1]<<" Ang "<<tpFit.Ang<<" flipDir "<<flipDir<<" fit vector size "<<x.size();
874 
875  // rotate (0, intcpt) into (W,T) coordinates
876  tpFit.Pos[0] = -sn * A + origin[0];
877  tpFit.Pos[1] = cs * A + origin[1];
878  // force the origin to be at origin[0]
879  if(tpFit.AngleCode < 2) MoveTPToWire(tpFit, origin[0]);
880 
881  if(x.size() < 3) return;
882 
883  // Calculate chisq/DOF
884  double ndof = x.size() - 2;
885  double varnce = (sumy2 + A*A*sum + B*B*sumx2 - 2 * (A*sumy + B*sumxy - A*B*sumx)) / ndof;
886  if(varnce > 0.) {
887  // Intercept error is not used
888  // InterceptError = sqrt(varnce * sumx2 / delta);
889  double slopeError = sqrt(varnce * sum / delta);
890  tpFit.AngErr = std::abs(atan(slopeError));
891  } else {
892  tpFit.AngErr = 0.01;
893  }
894  sum = 0;
895  // calculate chisq
896  double arg;
897  for(unsigned short ii = 0; ii < y.size(); ++ii) {
898  arg = y[ii] - A - B * x[ii];
899  sum += arg * arg / w[ii];
900  }
901  tpFit.FitChi = sum / ndof;
902 
903  } // FitTraj
Float_t x
Definition: compare.C:6
Double_t xx
Definition: macro.C:12
Float_t y
Definition: compare.C:6
Int_t B
Definition: plot.C:25
void SetAngleCode(TjStuff &tjs, TrajPoint &tp)
Definition: Utils.cxx:642
unsigned short NumPtsWithCharge(const TjStuff &tjs, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:1746
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
TDirectory * dir
Definition: macro.C:5
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
unsigned short AngleRange(TjStuff &tjs, float angle)
Definition: Utils.cxx:659
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2351
Float_t w
Definition: plot.C:23
constexpr Point origin()
Returns a origin position with a point of the specified type.
Definition: geo_vectors.h:230
bool tca::FitVertex ( TjStuff tjs,
VtxStore vx,
bool  prt 
)

Definition at line 1946 of file TCVertex.cxx.

References tca::TjStuff::allTraj, tca::VtxStore::CTP, tca::VtxStore::ID, kFixed, kKilled, kNoFitToVx, kPhoton, and tca::VtxStore::Stat.

Referenced by AttachTrajToVertex(), tca::TrajClusterAlg::EndMerge(), Find2DVertices(), FindNeutralVertices(), MergeWithVertex(), and SplitTrajCrossingVertices().

1947  {
1948  // A poor-mans fitting scheme. If the fitted vertex position error is within the supplied
1949  // value, the position and errors are updated and we return true, otherwise the vertex is
1950  // left unchanged and we return false
1951 
1952  // tjs.Vertex2DCuts fcl input usage
1953  // 0 = maximum length of a short trajectory
1954  // 1 = max vertex - trajectory separation for short trajectories
1955  // 2 = max vertex - trajectory separation for long trajectories
1956  // 3 = max position pull for adding TJs to a vertex
1957  // 4 = max allowed vertex position error
1958  // 5 = min MCSMom
1959  // 6 = min Pts/Wire fraction
1960 
1961  if(vx.Stat[kFixed]) {
1962  if(prt) mf::LogVerbatim("TC")<<" vertex position fixed. No fit allowed";
1963  return true;
1964  }
1965 
1966 
1967  // Create a vector of trajectory points that will be used to fit the vertex position
1968  std::vector<TrajPoint> vxTp;
1969  for(auto& tj : tjs.allTraj) {
1970  if(tj.AlgMod[kKilled]) continue;
1971  if(tj.CTP != vx.CTP) continue;
1972  if(tj.AlgMod[kPhoton]) continue;
1973  if(tj.AlgMod[kNoFitToVx]) continue;
1974  if(tj.VtxID[0] == vx.ID) vxTp.push_back(tj.Pts[tj.EndPt[0]]);
1975  if(tj.VtxID[1] == vx.ID) vxTp.push_back(tj.Pts[tj.EndPt[1]]);
1976  } // tj
1977 
1978  bool success = FitVertex(tjs, vx, vxTp, prt);
1979 
1980  if(!success) return false;
1981  return true;
1982 
1983  } // FitVertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
vertex position fixed manually - no fitting done
Definition: DataStructs.h:102
bool FitVertex(TjStuff &tjs, VtxStore &vx, std::vector< TrajPoint > vxTp, bool prt)
Definition: TCVertex.cxx:1986
bool tca::FitVertex ( TjStuff tjs,
VtxStore vx,
std::vector< TrajPoint vxTp,
bool  prt 
)

Definition at line 1986 of file TCVertex.cxx.

References tca::TrajPoint::Ang, tca::TrajPoint::AngErr, tca::VtxStore::ChiDOF, tca::VtxStore::CTP, tca::TrajPoint::CTP, tca::TrajPoint::Dir, tca::VtxStore::ID, kOnDeadWire, tca::VtxStore::NTraj, tca::VtxStore::Pos, tca::TrajPoint::Pos, tca::VtxStore::PosErr, PrintHeader(), PrintPos(), PrintTrajPoint(), tca::VtxStore::Stat, tmp, tca::VtxStore::Topo, TrajIntersection(), TrajPointVertexPull(), tca::TjStuff::UnitsPerTick, and tca::TjStuff::Vertex2DCuts.

1987  {
1988  // Variant of FitVertex that fits the passed trajectory points to a vertex position but doesn't
1989  // require using information in TJStuff
1990 
1991  // tjs.Vertex2DCuts fcl input usage
1992  // 0 = maximum length of a short trajectory
1993  // 1 = max vertex - trajectory separation for short trajectories
1994  // 2 = max vertex - trajectory separation for long trajectories
1995  // 3 = max position pull for adding TJs to a vertex
1996  // 4 = max allowed vertex position error
1997  // 5 = min MCSMom
1998  // 6 = min Pts/Wire fraction
1999  // 7 min Score
2000  // 8 Min charge fraction near a merge point (not a vertex)
2001  // 9 max MCSmom asymmetry for a merge
2002 
2003 
2004  vx.NTraj = vxTp.size();
2005 
2006  if(vxTp.size() < 2) return false;
2007 
2008  if(prt) {
2009  PrintHeader("FV");
2010  for(auto& tp : vxTp) PrintTrajPoint("FV", tjs, 0, 1, 1, tp);
2011  }
2012 
2013  // Find trajectory intersections pair-wise tweaking the angle and position(?) within
2014  // +/- 1 sigma
2015  double sum0 = 0, sum02 = 0;
2016  double sum1 = 0, sum12 = 0;
2017  double sumw = 0;
2018  double wgt;
2019  double cnt = 0;
2020  // a temporary TP for tweaking the angle
2021  TrajPoint tmp;
2022  // another point to check for a signal at each intersection
2023  TrajPoint intTp;
2024  intTp.CTP = vxTp[0].CTP;
2025  for(unsigned short itj = 0; itj < vxTp.size() - 1; ++itj) {
2026  for(unsigned short jtj = itj + 1; jtj < vxTp.size(); ++jtj) {
2027  float p0, p1;
2028  TrajIntersection(vxTp[itj], vxTp[jtj], p0, p1);
2029  intTp.Pos[0] = p0; intTp.Pos[1] = p1;
2030  wgt = 1;
2031  // accumulate
2032  sum0 += wgt * p0; sum02 += wgt * p0 * p0;
2033  sum1 += wgt * p1; sum12 += wgt * p1 * p1; sumw += wgt; ++cnt;
2034  // tweak the itj angle +
2035  tmp = vxTp[itj];
2036  tmp.Ang += tmp.AngErr;
2037  tmp.Dir[0] = cos(tmp.Ang); tmp.Dir[1] = sin(tmp.Ang);
2038  TrajIntersection(tmp, vxTp[jtj], p0, p1);
2039  intTp.Pos[0] = p0; intTp.Pos[1] = p1;
2040  // adjust the weight for 4 points at +/1 1 sigma = 0.607 / 4
2041  wgt = 0.152;
2042  // accumulate
2043  sum0 += wgt * p0; sum02 += wgt * p0 * p0;
2044  sum1 += wgt * p1; sum12 += wgt * p1 * p1; sumw += wgt; ++cnt;
2045  // tweak the itj angle -
2046  tmp = vxTp[itj];
2047  tmp.Ang -= 2 * tmp.AngErr;
2048  tmp.Dir[0] = cos(tmp.Ang); tmp.Dir[1] = sin(tmp.Ang);
2049  TrajIntersection(tmp, vxTp[jtj], p0, p1);
2050  intTp.Pos[0] = p0; intTp.Pos[1] = p1;
2051  // accumulate
2052  sum0 += wgt * p0; sum02 += wgt * p0 * p0;
2053  sum1 += wgt * p1; sum12 += wgt * p1 * p1; sumw += wgt; ++cnt;
2054  // Repeat this process with jtj
2055  // tweak the jtj angle +
2056  tmp = vxTp[jtj];
2057  tmp.Ang += tmp.AngErr;
2058  tmp.Dir[0] = cos(tmp.Ang); tmp.Dir[1] = sin(tmp.Ang);
2059  TrajIntersection(vxTp[itj], tmp, p0, p1);
2060  intTp.Pos[0] = p0; intTp.Pos[1] = p1;
2061  // accumulate
2062  sum0 += wgt * p0; sum02 += wgt * p0 * p0;
2063  sum1 += wgt * p1; sum12 += wgt * p1 * p1; sumw += wgt; ++cnt;
2064  // tweak the itj angle -
2065  tmp = vxTp[itj];
2066  tmp.Ang -= 2 * tmp.AngErr;
2067  tmp.Dir[0] = cos(tmp.Ang); tmp.Dir[1] = sin(tmp.Ang);
2068  TrajIntersection(vxTp[itj], tmp, p0, p1);
2069  intTp.Pos[0] = p0; intTp.Pos[1] = p1;
2070  // accumulate
2071  sum0 += wgt * p0; sum02 += wgt * p0 * p0;
2072  sum1 += wgt * p1; sum12 += wgt * p1 * p1; sumw += wgt; ++cnt;
2073  } // jtj
2074  } // itj
2075 
2076  if(sumw == 0) return false;
2077 
2078  double vxP0 = sum0 / sumw;
2079  double vxP1 = sum1 / sumw;
2080  double vxP0rms = sqrt((sum02 - sumw * vxP0 * vxP0) / sumw);
2081  double vxP1rms = sqrt((sum12 - sumw * vxP1 * vxP1) / sumw);
2082  double rootN = sqrt(cnt);
2083  vxP0rms /= rootN;
2084  vxP1rms /= rootN;
2085  // don't let the errors get too small
2086  if(vxP0rms < 0.5) vxP0rms = 0.5;
2087  if(vxP1rms < 0.5) vxP1rms = 0.5;
2088 
2089  if(prt) mf::LogVerbatim("TC")<<"FitVertex 2V"<<vx.ID<<" CTP "<<vx.CTP<<" NTraj "<<vx.NTraj<<" in "<<std::fixed<<std::setprecision(1)<<vx.Pos[0]<<":"<<vx.Pos[1]/tjs.UnitsPerTick<<" out wire "<<vxP0<<" +/- "<<vxP0rms<<" ticks "<<vxP1/tjs.UnitsPerTick<<"+/-"<<vxP1rms/tjs.UnitsPerTick;
2090 
2091  // apply Vertex2DCuts if this isn't a neutral vertex (which is expected to have very large
2092  // errors)
2093  if(vx.Topo != 11) {
2094  float inflate = 1;
2095  if(vx.Stat[kOnDeadWire]) inflate = 1.5;
2096  if(vxP0rms > inflate * tjs.Vertex2DCuts[4] || vxP1rms > inflate * tjs.Vertex2DCuts[4]) {
2097  if(prt) mf::LogVerbatim("TC")<<" fit failed. Max allowed position error "<<inflate * tjs.Vertex2DCuts[4];
2098  return false;
2099  }
2100  } // not a neutral vertex
2101 
2102  vx.Pos[0] = vxP0;
2103  vx.PosErr[0] = vxP0rms;
2104  vx.Pos[1] = vxP1;
2105  vx.PosErr[1] = vxP1rms;
2106 
2107  // Calculate chisq
2108  vx.ChiDOF = 0;
2109  for(unsigned short itj = 0; itj < vxTp.size(); ++itj) {
2110  vx.ChiDOF += TrajPointVertexPull(tjs, vxTp[itj], vx);
2111  } // itj
2112  vx.ChiDOF /= (float)vxTp.size();
2113 
2114  if(prt) {
2115  mf::LogVerbatim myprt("TC");
2116  myprt<<"Pull";
2117  for(unsigned short itj = 0; itj < vxTp.size(); ++itj) {
2118  float pull = TrajPointVertexPull(tjs, vxTp[itj], vx);
2119  myprt<<" "<<PrintPos(tjs, vxTp[itj])<<" - "<<std::fixed<<std::setprecision(2)<<pull;
2120  } // itj
2121  myprt<<" ChiDOF "<<vx.ChiDOF;
2122  }
2123  return true;
2124 
2125  } // FitVertex
std::string PrintPos(const TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:4738
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float TrajPointVertexPull(TjStuff &tjs, const TrajPoint &tp, const VtxStore &vx)
Definition: TCVertex.cxx:1847
Float_t tmp
Definition: plot.C:37
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
Definition: Utils.cxx:2166
void PrintTrajPoint(std::string someText, const TjStuff &tjs, unsigned short ipt, short dir, unsigned short pass, TrajPoint const &tp)
Definition: Utils.cxx:4574
void PrintHeader(std::string someText)
Definition: Utils.cxx:4568
void tca::FollowTp3s ( TjStuff tjs,
PFPStruct pfp,
bool  prt 
)

Definition at line 261 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, detinfo::DetectorProperties::ConvertXToTicks(), geo::CryostatID::Cryostat, DecodeCTP(), tca::TjStuff::detprop, tca::PFPStruct::Dir, FindAlongTrans(), tca::TjStuff::geom, kEnvFlag, tca::TjStuff::NumPlanes, geo::PlaneID::Plane, PointDirection(), PosSep(), PosSep2(), SetMag(), tca::PFPStruct::TjIDs, tca::PFPStruct::Tp3s, geo::TPCID::TPC, tca::PFPStruct::TPCID, tca::TjStuff::UnitsPerTick, tca::TjStuff::vtx3, tca::PFPStruct::Vx3ID, geo::GeometryCore::WireCoordinate(), tca::TjStuff::WirePitch, and tca::PFPStruct::XYZ.

Referenced by DefinePFP().

262  {
263  // Step through the set of Tp3s on this pfp to create a trajectory. The start and end points
264  // are assumed to be Tp3s[0] and Tp3s[Tp3s.size()-1] respectively.
265 
266  if(pfp.Tp3s.size() < 2) return;
267 
268  unsigned short startPt = 0;
269  unsigned short endPt = pfp.Tp3s.size() - 1;
270  // divide the trajectory in 5 cm long sections. The average position of the Tp3s in
271  // each section will be found. Tp3s
272  constexpr float sectionLen = 5;
273  float endAlong = pfp.Tp3s[0].AlongTrans[0] + sectionLen;
274  std::vector<Vector3_t> sectionPos;
275  sectionPos.push_back(pfp.Tp3s[0].Pos);
276  std::vector<unsigned short> sectionPt;
277  sectionPt.push_back(0);
278  for(unsigned short section = 0; section < 100; ++section) {
279  // a point to find the average position in this section
280  Point3_t avePos {{0,0,0}};
281  Vector3_t aveDir {{0,0,0}};
282  unsigned short cnt = 0;
283  for(unsigned short ipt = startPt; ipt < endPt; ++ipt) {
284  auto& tp3 = pfp.Tp3s[ipt];
285  // The path length along the direction vector from the start point to the end
286  // point was stashed in dEdxErr
287  // remove outliers
288  if(tp3.AlongTrans[1] > 2) continue;
289  if(tp3.AlongTrans[0] < endAlong) {
290  // still in the same section - sum and continue
291  for(unsigned short xyz = 0; xyz < 3; ++xyz) {
292  avePos[xyz] += tp3.Pos[xyz];
293  aveDir[xyz] += tp3.Dir[xyz];
294  }
295  ++cnt;
296  continue;
297  }
298  // entered the next section. Check for a failure
299  if(cnt == 0) continue;
300  // calculate the average position
301  for(unsigned short xyz = 0; xyz < 3; ++xyz) avePos[xyz] /= cnt;
302  SetMag(aveDir, 1);
303 /*
304  std::cout<<"Section "<<section<<" cnt "<<cnt<<" avePos"<<std::fixed<<std::setprecision(1);
305  std::cout<<" "<<avePos[0]<<" "<<avePos[1]<<" "<<avePos[2];
306  std::cout<<" aveDir "<<std::setprecision(2)<<aveDir[0]<<" "<<aveDir[1]<<" "<<aveDir[2]<<"\n";
307 */
308  sectionPos.push_back(avePos);
309  sectionPt.push_back(ipt);
310  startPt = ipt;
311  endAlong += sectionLen;
312  break;
313  } // ipt
314  } // section
315  sectionPos.push_back(pfp.Tp3s[endPt].Pos);
316  sectionPt.push_back(pfp.Tp3s.size() - 1);
317 /*
318  for(unsigned short ipt = 0; ipt < sectionPos.size(); ++ipt) {
319  std::cout<<ipt<<" sectionPt "<<sectionPt[ipt]<<" sectionPos "<<" "<<sectionPos[ipt][0]<<" "<<sectionPos[ipt][1]<<" "<<sectionPos[ipt][2]<<"\n";
320  } // ipt
321 */
322  // set the general purpose flag bit false (unused) for all Tj Pts. This will be set true
323  // when a Tp is used in a Tp3
324  for(auto tjid : pfp.TjIDs) {
325  auto& tj = tjs.allTraj[tjid - 1];
326  for(auto& tp : tj.Pts) tp.Environment[kEnvFlag] = false;
327  } // tjid
328  // set the bits true for the first point
329  for(auto tj2pt : pfp.Tp3s[0].Tj2Pts) {
330  tjs.allTraj[tj2pt.id - 1].Pts[tj2pt.ipt].Environment[kEnvFlag] = true;
331  }
332  // create a vector of new Tp3s that will replace pfp.Tp3s
333  std::vector<TrajPoint3> ntp3;
334  ntp3.push_back(pfp.Tp3s[0]);
335  // 2D position (WSE units) of the TPs at the start of this section. We will require that all 2D TPs are
336  // less than sectionLen (in WSE units) from this point.
337  std::vector<Point2_t> startPos2D(tjs.NumPlanes);
338  // collect Tp3s in each section
339  unsigned short lastPtAdded = 0;
340  for(unsigned short section = 1; section < sectionPt.size(); ++section) {
341  Point3_t startPos = sectionPos[section - 1];
342  Point3_t endPos = sectionPos[section];
343  auto startDir = PointDirection(startPos, endPos);
344  // define the pfp start direction
345  if(section == 1) pfp.Dir[0] = startDir;
346  // and the end direction
347  pfp.Dir[1] = startDir;
348 // std::cout<<"Section "<<section<<" startDir "<<std::fixed<<std::setprecision(2)<<startDir[0]<<" "<<startDir[1]<<" "<<startDir[2]<<"\n";
349  // define the 2D positions for this point in each plane
350  for(unsigned short plane = 0; plane < tjs.NumPlanes; ++plane) {
351  geo::PlaneID planeID = geo::PlaneID(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
352  startPos2D[plane][0] = tjs.geom->WireCoordinate(sectionPos[section - 1][1], sectionPos[section - 1][2], planeID);
353  startPos2D[plane][1] = tjs.detprop->ConvertXToTicks(sectionPos[section - 1][0], planeID) * tjs.UnitsPerTick;
354  } // plane
355  for(unsigned short ipt = sectionPt[section - 1]; ipt < sectionPt[section]; ++ipt) {
356  auto& tp3 = pfp.Tp3s[ipt];
357  // count the number of Tps in this Tp3 that are already used in the trajectory
358  unsigned short nused = 0;
359  bool big2DSep = false;
360  for(auto tj2pt : pfp.Tp3s[ipt].Tj2Pts) {
361  auto& tp = tjs.allTraj[tj2pt.id - 1].Pts[tj2pt.ipt];
362  if(tp.Environment[kEnvFlag]) ++nused;
363  unsigned short plane = DecodeCTP(tp.CTP).Plane;
364  float sep2D = PosSep(startPos2D[plane], tp.Pos) * tjs.WirePitch;
365  if(sep2D > sectionLen) big2DSep = true;
366  } // tj2pt
367  if(big2DSep || nused > 1) continue;
368  Point2_t alongTrans;
369  FindAlongTrans(startPos, startDir, tp3.Pos, alongTrans);
370  if(alongTrans[1] > 0.5) continue;
371 /*
372  std::cout<<section<<" ipt "<<ipt<<" trans "<<alongTrans[1]<<" tj_ipt";
373  for(auto tj2pt : tp3.Tj2Pts) std::cout<<" "<<tj2pt.id - 1<<"_"<<tj2pt.ipt;
374  std::cout<<"\n";
375 */
376  tp3.AlongTrans = alongTrans;
377  // don't clobber the original direction
378 // tp3.Dir = dir;
379  ntp3.push_back(tp3);
380  // set the flag
381  for(auto tj2pt : tp3.Tj2Pts) tjs.allTraj[tj2pt.id - 1].Pts[tj2pt.ipt].Environment[kEnvFlag] = true;
382  lastPtAdded = ipt;
383  } // ipt
384  } // section
385 
386  if(lastPtAdded != endPt) ntp3.push_back(pfp.Tp3s[endPt]);
387 
388  if(prt) {
389  float len = PosSep(ntp3[0].Pos, ntp3[ntp3.size()-1].Pos);
390  mf::LogVerbatim("TC")<<"FollowTp3s: Tp3s size in "<<pfp.Tp3s.size()<<" size out "<<ntp3.size()<<" len "<<std::fixed<<std::setprecision(2)<<len;
391  }
392 
393  // reverse if necessary to be consistent with a vertex
394  if(pfp.Vx3ID[0] > 0) {
395  auto& vx3 = tjs.vtx3[pfp.Vx3ID[0] - 1];
396  Point3_t vpos = {{vx3.X, vx3.Y, vx3.Z}};
397  auto& firstTp3Pos = ntp3[0].Pos;
398  auto& lastTp3Pos = ntp3[ntp3.size() - 1].Pos;
399  if(PosSep2(lastTp3Pos, vpos) < PosSep2(firstTp3Pos, vpos)) std::reverse(ntp3.begin(), ntp3.end());
400  } // pfp.Vx3ID[0] > 0
401 
402  pfp.Tp3s = ntp3;
403  // The directions were set above. Set the start and end positions. Note that the start position
404  // may have been previously determined by a vertex but that is now superseded by the actual start
405  // of the pfp
406  pfp.XYZ[0] = ntp3[0].Pos;
407  pfp.XYZ[1] = ntp3[ntp3.size()-1].Pos;
408 // if(prt) PrintTp3s("FTp3o", tjs, pfp, -1);
409 
410  } // FollowTp3s
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::array< double, 3 > Point3_t
Definition: DataStructs.h:35
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:2751
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
a general purpose flag bit used in 3D matching
Definition: DataStructs.h:459
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:1614
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1631
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
bool SetMag(Vector3_t &v1, double mag)
Definition: PFPUtils.cxx:1641
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
std::array< double, 3 > Vector3_t
Definition: DataStructs.h:36
std::vector< int > tca::GetAssns ( const TjStuff tjs,
std::string  type1Name,
int  id,
std::string  type2Name 
)

Definition at line 4079 of file Utils.cxx.

References tca::TjStuff::allTraj, tca::TjStuff::cots, evd::details::end(), kKilled, kMat3D, tca::TjStuff::pfps, SetIntersection(), tca::TjStuff::showers, ss, tmp, tca::TjStuff::vtx, and tca::TjStuff::vtx3.

Referenced by ChkVxTjs(), CompleteIncomplete3DVertices(), CompleteIncompleteShower(), DefineDontCluster(), DotProd(), FindCots(), FindNearbyTjs(), FindParent(), Finish3DShowers(), KillVerticesInShower(), tca::MCParticleListUtils::MakeCheatShower(), MergeNearby2DShowers(), ParentFOM(), tca::MCParticleListUtils::PrimaryElectronPFPID(), PrintAllTraj(), Reconcile3D(), SetParent(), and TagShowerLike().

4080  {
4081  // returns a list of IDs of objects (tjs, vertices, pfps, etc) with type1Name that are in TJStuff with
4082  // type2Name. This is intended to be a general purpose replacement for specific functions like GetVtxTjIDs, etc
4083 
4084  std::vector<int> tmp;
4085  if(id <= 0) return tmp;
4086  unsigned int uid = id;
4087 
4088  if(type1Name == "T" && uid <= tjs.allTraj.size() && type2Name == "P") {
4089  // return a list of PFPs that have the tj in TjIDs, P -> T<ID>
4090  for(auto& pfp : tjs.pfps) {
4091  if(pfp.ID <= 0) continue;
4092  if(std::find(pfp.TjIDs.begin(), pfp.TjIDs.end(), id) != pfp.TjIDs.end()) tmp.push_back(pfp.ID);
4093  } // pf
4094  return tmp;
4095  } // P -> T
4096 
4097  if(type1Name == "P" && uid <= tjs.pfps.size() && (type2Name == "2S" || type2Name == "3S")) {
4098  // return a list of 3D or 2D showers with the assn 3S -> 2S -> T -> P<ID> or 2S -> T -> P.
4099  auto& pfp = tjs.pfps[uid - 1];
4100  // First form a list of 2S -> T -> P<ID>
4101  std::vector<int> ssid;
4102  for(auto& ss : tjs.cots) {
4103  if(ss.ID <= 0) continue;
4104  auto shared = SetIntersection(ss.TjIDs, pfp.TjIDs);
4105  if(!shared.empty() && std::find(ssid.begin(), ssid.end(), ss.ID) == ssid.end()) ssid.push_back(ss.ID);
4106  } // ss
4107  if(type2Name == "2S") return ssid;
4108  for(auto& ss3 : tjs.showers) {
4109  if(ss3.ID <= 0) continue;
4110  auto shared = SetIntersection(ss3.CotIDs, ssid);
4111  if(!shared.empty() && std::find(tmp.begin(), tmp.end(), ss3.ID) == tmp.end()) tmp.push_back(ss3.ID);
4112  } // ss3
4113  return tmp;
4114  } // 3S -> 2S -> T -> P
4115 
4116  if(type1Name == "2V" && uid <= tjs.vtx.size() && type2Name == "T" ) {
4117  // 2V -> T
4118  for(auto& tj : tjs.allTraj) {
4119  if(tj.AlgMod[kKilled]) continue;
4120  for(unsigned short end = 0; end < 2; ++end) {
4121  if(tj.VtxID[end] != id) continue;
4122  if(std::find(tmp.begin(), tmp.end(), tj.ID) == tmp.end()) tmp.push_back(tj.ID);
4123  } // end
4124  } // tj
4125  return tmp;
4126  } // 2V -> T
4127 
4128  if(type1Name == "3V" && uid <= tjs.vtx3.size() && type2Name == "P") {
4129  for(auto& pfp : tjs.pfps) {
4130  if(pfp.ID == 0) continue;
4131  for(unsigned short end = 0; end < 2; ++end) {
4132  if(pfp.Vx3ID[end] != id) continue;
4133  // encode the end with the ID
4134  if(std::find(tmp.begin(), tmp.end(), pfp.ID) == tmp.end()) tmp.push_back(pfp.ID);
4135  } // end
4136  } // pfp
4137  return tmp;
4138  } // 3V -> P
4139 
4140  if(type1Name == "3V" && uid <= tjs.vtx3.size() && type2Name == "T") {
4141  // 3V -> T
4142  for(auto& tj : tjs.allTraj) {
4143  if(tj.AlgMod[kKilled]) continue;
4144  for(unsigned short end = 0; end < 2; ++end) {
4145  if(tj.VtxID[end] > 0 && tj.VtxID[end] <= tjs.vtx.size()) {
4146  auto& vx2 = tjs.vtx[tj.VtxID[end] - 1];
4147  if(vx2.Vx3ID != id) continue;
4148  if(std::find(tmp.begin(), tmp.end(), tj.ID) == tmp.end()) tmp.push_back(tj.ID);
4149  }
4150  } // end
4151  } // tj
4152  return tmp;
4153  } // 3V -> T
4154 
4155  if(type1Name == "3V" && uid <= tjs.vtx3.size() && type2Name == "2V") {
4156  // 3V -> 2V
4157  for(auto& vx2 : tjs.vtx) {
4158  if(vx2.ID == 0) continue;
4159  if(vx2.Vx3ID == id) tmp.push_back(vx2.ID);
4160  } // vx2
4161  return tmp;
4162  } // 3V -> 2V
4163 
4164  if(type1Name == "3S" && uid <= tjs.showers.size() && type2Name == "T") {
4165  // 3S -> T
4166  auto& ss3 = tjs.showers[uid - 1];
4167  if(ss3.ID == 0) return tmp;
4168  for(auto cid : ss3.CotIDs) {
4169  auto& ss = tjs.cots[cid - 1];
4170  if(ss.ID == 0) continue;
4171  tmp.insert(tmp.end(), ss.TjIDs.begin(), ss.TjIDs.end());
4172  } // cid
4173  return tmp;
4174  } // 3S -> T
4175 
4176  // This isn't strictly necessary but do it for consistency
4177  if(type1Name == "2S" && uid <= tjs.cots.size() && type2Name == "T") {
4178  // 2S -> T
4179  auto& ss = tjs.cots[uid - 1];
4180  return ss.TjIDs;
4181  } // 2S -> T
4182 
4183  if(type1Name == "3S" && uid <= tjs.showers.size() && type2Name == "P") {
4184  // 3S -> P
4185  auto& ss3 = tjs.showers[uid - 1];
4186  if(ss3.ID == 0) return tmp;
4187  for(auto cid : ss3.CotIDs) {
4188  auto& ss = tjs.cots[cid - 1];
4189  if(ss.ID == 0) continue;
4190  for(auto tid : ss.TjIDs) {
4191  auto& tj = tjs.allTraj[tid - 1];
4192  if(tj.AlgMod[kKilled]) continue;
4193  if(!tj.AlgMod[kMat3D]) continue;
4194  for(auto& pfp : tjs.pfps) {
4195  if(pfp.ID <= 0) continue;
4196  if(std::find(pfp.TjIDs.begin(), pfp.TjIDs.end(), tj.ID) == pfp.TjIDs.end()) continue;
4197  if(std::find(tmp.begin(), tmp.end(), pfp.ID) == tmp.end()) tmp.push_back(pfp.ID);
4198  } // pf
4199  } // tid
4200  } // cid
4201  return tmp;
4202  } // 3S -> P
4203 
4204  if(type1Name == "T" && uid <= tjs.allTraj.size() && type2Name == "2S") {
4205  // T -> 2S
4206  for(auto& ss : tjs.cots) {
4207  if(ss.ID == 0) continue;
4208  if(std::find(ss.TjIDs.begin(), ss.TjIDs.end(), id) != ss.TjIDs.end()) tmp.push_back(ss.ID);
4209  } // ss
4210  return tmp;
4211  } // T -> 2S
4212 
4213  if(type1Name == "T" && uid <= tjs.allTraj.size() && type2Name == "3S") {
4214  // T -> 3S
4215  for(auto& ss : tjs.cots) {
4216  if(ss.ID == 0) continue;
4217  if(std::find(ss.TjIDs.begin(), ss.TjIDs.end(), id) == ss.TjIDs.end()) continue;
4218  if(ss.SS3ID > 0) tmp.push_back(ss.SS3ID);
4219  } // ss
4220  return tmp;
4221  } // T -> 3S
4222 
4223  std::cout<<"GetAssns doesn't know about "<<type1Name<<" -> "<<type2Name<<" assns, or id "<<id<<" is not valid.\n";
4224 
4225  return tmp;
4226 
4227  } // GetAssns
Float_t ss
Definition: plot.C:23
Float_t tmp
Definition: plot.C:37
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:214
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
int tca::GetCotID ( TjStuff tjs,
int  ShowerTjID 
)

Definition at line 4424 of file TCShower.cxx.

References tca::TjStuff::cots.

Referenced by MergeShowerTjsAndStore().

4425  {
4426  for(unsigned short ii = 0; ii < tjs.cots.size(); ++ii) {
4427  if(ShowerTjID == tjs.cots[ii].ShowerTjID) return ii + 1;
4428  } // iii
4429  return 0;
4430 
4431  } // GetCotID
int tca::GetOrigin ( TjStuff tjs,
PFPStruct pfp 
)

Definition at line 77 of file TCCR.cxx.

References tca::TjStuff::allTraj, tca::TCHit::ArtPtr, cheat::BackTrackerService::ChannelToTrackIDEs(), geo::CryostatID::Cryostat, tca::TjStuff::fHits, tca::TjStuff::geom, simb::MCTruth::Origin(), geo::origin(), tca::TCHit::PeakTime, geo::PlaneID::Plane, geo::GeometryCore::PlaneWireToChannel(), tca::Trajectory::Pts, tca::TCHit::RMS, tca::PFPStruct::TjIDs, geo::TPCID::TPC, cheat::ParticleInventoryService::TrackIdToMCTruth_P(), geo::WireID::Wire, and recob::Hit::WireID().

Referenced by SaveCRInfo().

77  {
78 
81 
82  std::map<int, float> omap; //<origin, energy>
83 
84  for(auto& tjID : pfp.TjIDs) {
85 
86  Trajectory& tj = tjs.allTraj[tjID - 1];
87  for(auto& tp : tj.Pts) {
88  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
89  if(!tp.UseHit[ii]) continue;
90  unsigned int iht = tp.Hits[ii];
91  TCHit& hit = tjs.fHits[iht];
92  raw::ChannelID_t channel = tjs.geom->PlaneWireToChannel((int)hit.ArtPtr->WireID().Plane, (int)hit.ArtPtr->WireID().Wire, (int)hit.ArtPtr->WireID().TPC, (int)hit.ArtPtr->WireID().Cryostat);
93  double startTick = hit.PeakTime - hit.RMS;
94  double endTick = hit.PeakTime + hit.RMS;
95  // get a list of track IDEs that are close to this hit
96  std::vector<sim::TrackIDE> tides;
97  tides = bt_serv->ChannelToTrackIDEs(channel, startTick, endTick);
98  for(auto itide = tides.begin(); itide != tides.end(); ++itide) {
99  omap[pi_serv->TrackIdToMCTruth_P(itide->trackID)->Origin()] += itide->energy;
100  }
101  }
102  }
103  }
104 
105  float maxe = -1;
106  int origin = 0;
107  for (auto & i : omap){
108  if (i.second > maxe){
109  maxe = i.second;
110  origin = i.first;
111  }
112  }
113  return origin;
114  }
simb::Origin_t Origin() const
Definition: MCTruth.h:71
Detector simulation of raw signals on wires.
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:27
const std::vector< sim::TrackIDE > ChannelToTrackIDEs(raw::ChannelID_t channel, const double hit_start_time, const double hit_end_time)
constexpr Point origin()
Returns a origin position with a point of the specified type.
Definition: geo_vectors.h:230
const art::Ptr< simb::MCTruth > & TrackIdToMCTruth_P(int const &id)
unsigned short tca::GetPFPIndex ( const TjStuff tjs,
int  tjID 
)

Definition at line 1045 of file Utils.cxx.

References tca::TjStuff::pfps.

Referenced by DefinePFPParents(), DefinePFPParentsTestBeam(), and MergeAndStore().

1046  {
1047  // returns the index into the tjs.matchVec vector of the first 3D match that
1048  // includes tjID
1049  if(tjs.pfps.empty()) return USHRT_MAX;
1050  for(unsigned int ipfp = 0; ipfp < tjs.pfps.size(); ++ipfp) {
1051  const auto& pfp = tjs.pfps[ipfp];
1052  if(std::find(pfp.TjIDs.begin(), pfp.TjIDs.end(), tjID) != pfp.TjIDs.end()) return ipfp;
1053  } // indx
1054  return USHRT_MAX;
1055  } // GetPFPIndex
std::vector< unsigned short > tca::GetPFPVertices ( const TjStuff tjs,
const PFPStruct pfp 
)

Definition at line 3063 of file TCVertex.cxx.

References tca::TjStuff::allTraj, evd::details::end(), tca::PFPStruct::TjIDs, tmp, and tca::TjStuff::vtx.

3064  {
3065  // returns a list of 3D vertices that are attached to Tjs in this pfp. No check is
3066  // made of the actual vertex attachment of the pfp.
3067  std::vector<unsigned short> tmp;
3068  if(pfp.TjIDs.empty()) return tmp;
3069  for(auto tjid : pfp.TjIDs) {
3070  auto& tj = tjs.allTraj[tjid - 1];
3071  for(unsigned short end = 0; end < 2; ++end) {
3072  if(tj.VtxID[end] == 0) continue;
3073  auto& vx2 = tjs.vtx[tj.VtxID[end] - 1];
3074  if(vx2.Vx3ID == 0) continue;
3075  if(std::find(tmp.begin(), tmp.end(), vx2.Vx3ID) != tmp.end()) continue;
3076  tmp.push_back(vx2.Vx3ID);
3077  } // end
3078  } // tjid
3079  return tmp;
3080  } // GetPFPVertices
Float_t tmp
Definition: plot.C:37
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
int tca::GetStageNum ( ShowerTreeVars stv,
std::string  stageName 
)

Definition at line 185 of file TCShTree.cxx.

References tca::ShowerTreeVars::StageName.

Referenced by SaveTjInfo().

185  {
186  int stageNum;
187  bool existingStage = false;
188  for (unsigned short i = 0; i < stv.StageName.size(); ++i) {
189  if (stv.StageName.at(i) == stageName) {
190  existingStage = true;
191  stageNum = i+1;
192  }
193  }
194 
195  if (!existingStage) {
196  stv.StageName.push_back(stageName);
197  stageNum = stv.StageName.size();
198  }
199 
200  return stageNum;
201  }
std::vector< int > tca::GetVtxTjIDs ( const TjStuff tjs,
const VtxStore vx2 
)

Definition at line 3022 of file TCVertex.cxx.

References tca::TjStuff::allTraj, tca::VtxStore::CTP, evd::details::end(), tca::VtxStore::ID, kKilled, and tmp.

Referenced by DefinePFPParentsTestBeam(), DefineTjParents(), GetVtxTjIDs(), Match3DVtxTjs(), MergeWithVertex(), PFPVxTjOK(), SetHighScoreBits(), SetVx2Score(), SharesHighScoreVx(), and SplitTrajCrossingVertices().

3023  {
3024  // returns a list of trajectory IDs that are attached to vx2
3025  std::vector<int> tmp;
3026  if(vx2.ID == 0) return tmp;
3027  for(auto& tj : tjs.allTraj) {
3028  if(tj.AlgMod[kKilled]) continue;
3029  if(tj.CTP != vx2.CTP) continue;
3030  for(unsigned short end = 0; end < 2; ++end) {
3031  if(tj.VtxID[end] == vx2.ID) tmp.push_back(tj.ID);
3032  } // end
3033  } // tj
3034  return tmp;
3035  } // GetVtxTjIDs
Float_t tmp
Definition: plot.C:37
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
std::vector< int > tca::GetVtxTjIDs ( const TjStuff tjs,
const Vtx3Store vx3,
float &  score 
)

Definition at line 3039 of file TCVertex.cxx.

References GetVtxTjIDs(), tca::Vtx3Store::ID, tmp, and tca::TjStuff::vtx.

3040  {
3041  // returns a list of Tjs in all planes that are attached to vx3
3042  std::vector<int> tmp;
3043  if(vx3.ID == 0) return tmp;
3044  float nvx2 = 0;
3045  score = 0;
3046  for(auto& vx2 : tjs.vtx) {
3047  if(vx2.ID == 0) continue;
3048  if(vx2.Vx3ID != vx3.ID) continue;
3049  auto vtxTjID2 = GetVtxTjIDs(tjs, vx2);
3050  tmp.insert(tmp.end(), vtxTjID2.begin(), vtxTjID2.end());
3051  score += vx2.Score;
3052  ++nvx2;
3053  } // vx2
3054  if(nvx2 < 1) return tmp;
3055  // find the average score
3056  score /= nvx2;
3057  // sort by increasing ID
3058  std::sort(tmp.begin(), tmp.end());
3059  return tmp;
3060  } // GetVtxTjIDs
Float_t tmp
Definition: plot.C:37
std::vector< int > GetVtxTjIDs(const TjStuff &tjs, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:3039
bool tca::HasDuplicateHits ( TjStuff const &  tjs,
Trajectory const &  tj,
bool  prt 
)

Definition at line 2335 of file Utils.cxx.

References tca::TjStuff::fHits, kAllHits, PrintHit(), and PutTrajHitsInVector().

Referenced by tca::TrajClusterAlg::CheckTraj(), and MergeAndStore().

2336  {
2337  // returns true if a hit is associated with more than one TP
2338  auto tjHits = PutTrajHitsInVector(tj, kAllHits);
2339  for(unsigned short ii = 0; ii < tjHits.size() - 1; ++ii) {
2340  for(unsigned short jj = ii + 1; jj < tjHits.size(); ++jj) {
2341  if(tjHits[ii] == tjHits[jj]) {
2342  if(prt) mf::LogVerbatim("TC")<<"HDH: Hit "<<PrintHit(tjs.fHits[ii])<<" is a duplicate "<<ii<<" "<<jj;
2343  return true;
2344  }
2345  } // jj
2346  } // ii
2347  return false;
2348  } // HasDuplicateHits
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< unsigned int > PutTrajHitsInVector(Trajectory const &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2283
std::string PrintHit(const TCHit &hit)
Definition: Utils.cxx:4732
float tca::HitSep2 ( TjStuff tjs,
unsigned int  iht,
unsigned int  jht 
)

Definition at line 2110 of file Utils.cxx.

References tca::TjStuff::fHits, and tca::TjStuff::UnitsPerTick.

Referenced by tca::TrajClusterAlg::FindJunkTraj().

2111  {
2112  // returns the separation^2 between two hits in WSE units
2113  if(iht > tjs.fHits.size()-1 || jht > tjs.fHits.size()-1) return 1E6;
2114  float dw = (float)tjs.fHits[iht].ArtPtr->WireID().Wire - (float)tjs.fHits[jht].ArtPtr->WireID().Wire;
2115  float dt = (tjs.fHits[iht].PeakTime - tjs.fHits[jht].PeakTime) * tjs.UnitsPerTick;
2116  return dw * dw + dt * dt;
2117  } // HitSep2
float tca::HitsPosTick ( TjStuff tjs,
const std::vector< unsigned int > &  hitsInMultiplet,
float &  sum,
HitStatus_t  hitRequest 
)

Definition at line 3645 of file Utils.cxx.

References tca::TjStuff::fHits, kAllHits, kUnusedHits, and kUsedHits.

Referenced by DotProd(), HitsPosTime(), tca::TrajClusterAlg::ReconstructAllTraj(), and TrajHitsOK().

3646  {
3647  // returns the position and the charge
3648  float pos = 0;
3649  sum = 0;
3650  for(unsigned short ii = 0; ii < hitsInMultiplet.size(); ++ii) {
3651  unsigned int iht = hitsInMultiplet[ii];
3652  bool useit = (hitRequest == kAllHits);
3653  if(hitRequest == kUsedHits && tjs.fHits[iht].InTraj > 0) useit = true;
3654  if(hitRequest == kUnusedHits && tjs.fHits[iht].InTraj == 0) useit = true;
3655  if(!useit) continue;
3656  float chg = tjs.fHits[iht].Integral;
3657  pos += chg * tjs.fHits[iht].PeakTime;
3658  sum += chg;
3659  } // ii
3660  if(sum == 0) return 0;
3661  return pos / sum;
3662  } // HitsPosTick
float tca::HitsPosTime ( TjStuff tjs,
const std::vector< unsigned int > &  hitsInMultiplet,
float &  sum,
HitStatus_t  hitRequest 
)

Definition at line 3639 of file Utils.cxx.

References HitsPosTick(), and tca::TjStuff::UnitsPerTick.

Referenced by DotProd().

3640  {
3641  return tjs.UnitsPerTick * HitsPosTick(tjs, hitsInMultiplet, sum, hitRequest);
3642  } // HitsPosTime
float HitsPosTick(TjStuff &tjs, const std::vector< unsigned int > &hitsInMultiplet, float &sum, HitStatus_t hitRequest)
Definition: Utils.cxx:3645
float tca::HitsRMSTick ( TjStuff tjs,
const std::vector< unsigned int > &  hitsInMultiplet,
HitStatus_t  hitRequest 
)

Definition at line 3613 of file Utils.cxx.

References tca::TjStuff::fHits, kAllHits, kUnusedHits, and kUsedHits.

Referenced by DotProd(), tca::TrajClusterAlg::FindUseHits(), HitsRMSTime(), and tca::TrajClusterAlg::ReconstructAllTraj().

3614  {
3615  if(hitsInMultiplet.empty()) return 0;
3616 
3617  if(hitsInMultiplet.size() == 1) return tjs.fHits[hitsInMultiplet[0]].RMS;
3618 
3619  float minVal = 9999;
3620  float maxVal = 0;
3621  for(unsigned short ii = 0; ii < hitsInMultiplet.size(); ++ii) {
3622  unsigned int iht = hitsInMultiplet[ii];
3623  bool useit = (hitRequest == kAllHits);
3624  if(hitRequest == kUsedHits && tjs.fHits[iht].InTraj > 0) useit = true;
3625  if(hitRequest == kUnusedHits && tjs.fHits[iht].InTraj == 0) useit = true;
3626  if(!useit) continue;
3627  float cv = tjs.fHits[iht].PeakTime;
3628  float rms = tjs.fHits[iht].RMS;
3629  float arg = cv - rms;
3630  if(arg < minVal) minVal = arg;
3631  arg = cv + rms;
3632  if(arg > maxVal) maxVal = arg;
3633  } // ii
3634  if(maxVal == 0) return 0;
3635  return (maxVal - minVal) / 2;
3636  } // HitsRMSTick
float tca::HitsRMSTime ( TjStuff tjs,
const std::vector< unsigned int > &  hitsInMultiplet,
HitStatus_t  hitRequest 
)

Definition at line 3607 of file Utils.cxx.

References HitsRMSTick(), and tca::TjStuff::UnitsPerTick.

Referenced by DotProd(), and tca::TrajClusterAlg::HitsTimeErr2().

3608  {
3609  return tjs.UnitsPerTick * HitsRMSTick(tjs, hitsInMultiplet, hitRequest);
3610  } // HitsRMSTick
float HitsRMSTick(TjStuff &tjs, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
Definition: Utils.cxx:3613
double tca::InShowerProb ( double  showerEnergy,
double  along,
double  trans 
)
float tca::InShowerProb ( const TjStuff tjs,
const ShowerStruct3D ss3,
const PFPStruct pfp 
)

Definition at line 2172 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::ShowerStruct3D::CotIDs, tca::TjStuff::cots, tca::PFPStruct::ID, tca::ShowerStruct3D::ID, InShowerProb(), ss, and tca::PFPStruct::TjIDs.

2173  {
2174  // returns a likelihood (0 - 1) that the pfp particle belongs in shower ss3
2175 
2176  if(ss3.ID == 0 || pfp.ID == 0) return 0;
2177  float sum = 0;
2178  float cnt = 0;
2179  for(auto cid : ss3.CotIDs) {
2180  auto& ss = tjs.cots[cid - 1];
2181  if(ss.ID == 0) continue;
2182  for(auto tid : pfp.TjIDs) {
2183  auto& tj = tjs.allTraj[tid - 1];
2184  if(tj.CTP != ss.CTP) continue;
2185 // std::cout<<"3S"<<ss3.ID<<" P"<<pfp.ID<<" ";
2186  sum += InShowerProb(tjs, ss, tj);
2187  ++cnt;
2188  } // tid
2189  } //cid
2190  if(cnt == 0) return 0;
2191  return sum / cnt;
2192 
2193  } // InShowerProb
Float_t ss
Definition: plot.C:23
float InShowerProb(const TjStuff &tjs, const ShowerStruct &ss, const Trajectory &tj)
Definition: TCShower.cxx:2196
float tca::InShowerProb ( const TjStuff tjs,
const ShowerStruct ss,
const Trajectory tj 
)

Definition at line 2196 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::Trajectory::CTP, tca::ShowerStruct::CTP, DotProd(), FindAlongTrans(), tca::Trajectory::ID, tca::ShowerStruct::ID, PosSep(), tca::Trajectory::Pts, tca::ShowerStruct::ShowerTjID, and TrajTrajDOCA().

Referenced by InShowerProb(), and Reconcile3D().

2197  {
2198  // returns a likelihood (0 - 1) that the tj particle belongs in shower ss
2199  // Keep it simple: construct a FOM, take the inverse and limit it to the range 0 - 1
2200  if(ss.ID == 0 || tj.ID == 0) return 0;
2201  if(ss.CTP != tj.CTP) return 0;
2202 
2203  auto& stj = tjs.allTraj[ss.ShowerTjID - 1];
2204  if(stj.Pts.size() != 3) return 0;
2205  unsigned short closePt1, closePt2;
2206  float doca = 1E6;
2207  TrajTrajDOCA(tjs, stj, tj, closePt1, closePt2, doca);
2208  if(doca == 1E6) return 0;
2209  float showerLen = PosSep(stj.Pts[0].Pos, stj.Pts[2].Pos);
2210  // make a rough separation cut. Return a small but non-zero value
2211  if(doca > 5 * showerLen) return 0.01;
2212  auto& stp = stj.Pts[closePt1];
2213  if(stp.DeltaRMS == 0) return 0;
2214  auto& ttp = tj.Pts[closePt2];
2215  Point2_t alongTrans;
2216  FindAlongTrans(stp.Pos, stp.Dir, ttp.Pos, alongTrans);
2217 // std::cout<<"ISP: 2S"<<ss.ID<<" T"<<tj.ID<<" showerLen "<<(int)showerLen<<" closePt "<<closePt1;
2218 // std::cout<<" closePt "<<closePt2<<" along "<<std::fixed<<std::setprecision(1)<<alongTrans[0]<<" "<<alongTrans[1];
2219  float rms = stp.DeltaRMS;
2220  if(rms < 1) rms = 1;
2221  float arg = alongTrans[1] / rms;
2222  float radProb = exp(-0.5 * arg * arg);
2223 // std::cout<<" rms "<<rms<<" radProb "<<std::setprecision(3)<<radProb;
2224  // This is a fake but may be OK if this function is called before the shower is well-defined
2225  rms = showerLen;
2226  arg = alongTrans[0] / rms;
2227  float longProb = exp(-0.5 * arg * arg);
2228 // std::cout<<" longProb "<<std::setprecision(3)<<longProb;
2229  float costh = std::abs(DotProd(stp.Dir, ttp.Dir));
2230 // std::cout<<" costh "<<std::setprecision(3)<<costh;
2231  float prob = radProb * longProb * costh;
2232 // std::cout<<" InShowerProb "<<std::setprecision(3)<<prob<<"\n";
2233  return prob;
2234 
2235  } // InShowerProb
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:2751
Float_t ss
Definition: plot.C:23
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:60
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
bool TrajTrajDOCA(const TjStuff &tjs, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2046
double tca::InShowerProbLong ( double  showerEnergy,
double  along 
)

Definition at line 2118 of file TCShower.cxx.

References ShowerParams().

Referenced by FindParent(), InShowerProbParam(), MergeSubShowers(), ParentFOM(), and tca::TruthMatcher::StudyShowerParents().

2119  {
2120  // Returns the likelihood that the point at position along (cm) is inside an EM shower
2121  // having showerEnergy (MeV). The variable along is relative to shower max.
2122 
2123  if(showerEnergy < 10) return 0;
2124 
2125  double shMaxAlong, shE95Along;
2126  ShowerParams(showerEnergy, shMaxAlong, shE95Along);
2127  // 50% of the shower energy is deposited between 0 < shMaxAlong < 1, which should be obvious considering
2128  // that is the definition of the shower max, so the probability should be ~1 at shMaxAlong = 1.
2129  // The Geant study shows that 95% of the energy is contained within 2.5 * shMax and has a small dependence
2130  // on the shower energy, which is modeled in ShowerParams. This function uses a
2131  // sigmoid likelihood function is constructed with these constraints using the scaling variable tau
2132  double tau = (along + shMaxAlong) / shMaxAlong;
2133  if(tau < -1 || tau > 4) return 0;
2134 
2135  double tauHalf, width;
2136  if(tau > 0) {
2137  tauHalf = 1.7;
2138  width = 0.35;
2139  } else {
2140  // Allow for some uncertainty in the shower start position
2141  tau = -tau;
2142  tauHalf = 0.2;
2143  width = 0.1;
2144  }
2145 
2146  double prob = 1 / (1 + exp((tau - tauHalf)/width));
2147  return prob;
2148 
2149  } // InShowrProbLong
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
Definition: TCShower.cxx:2084
double tca::InShowerProbParam ( double  showerEnergy,
double  along,
double  trans 
)

Definition at line 2166 of file TCShower.cxx.

References InShowerProbLong(), and InShowerProbTrans().

2167  {
2168  return InShowerProbLong(showerEnergy, along) * InShowerProbTrans(showerEnergy, along, trans);
2169  } // InShowerProbParam
double InShowerProbLong(double showerEnergy, double along)
Definition: TCShower.cxx:2118
double InShowerProbTrans(double showerEnergy, double along, double trans)
Definition: TCShower.cxx:2152
double tca::InShowerProbTrans ( double  showerEnergy,
double  along,
double  trans 
)

Definition at line 2152 of file TCShower.cxx.

References ShowerParamTransRMS().

Referenced by InShowerProbParam(), and MergeSubShowers().

2153  {
2154  // Returns the likelihood that the point, (along, trans) (cm), is inside an EM shower having energy showerEnergy (MeV)
2155  // where along is relative to the shower start position and trans is the radial distance.
2156 
2157  if(showerEnergy < 10) return 0;
2158  double rms = ShowerParamTransRMS(showerEnergy, along);
2159  trans = std::abs(trans);
2160  double prob = exp(-0.5 * trans / rms);
2161  return prob;
2162 
2163  } // InShowerProbTrans
double ShowerParamTransRMS(double showerEnergy, double along)
Definition: TCShower.cxx:2104
bool tca::InsideTPC ( const TjStuff tjs,
Point3_t pos,
geo::TPCID inTPCID 
)

Definition at line 2725 of file PFPUtils.cxx.

References geo::GeometryCore::DetHalfHeight(), geo::GeometryCore::DetHalfWidth(), geo::GeometryCore::DetLength(), tca::TjStuff::geom, geo::GeometryCore::IterateTPCIDs(), geo::TPCGeo::LocalToWorld(), and geo::GeometryCore::TPC().

Referenced by DotProd(), tca::TruthMatcher::MatchTruth(), and tca::TruthMatcher::StudyShowerParents().

2726  {
2727  // determine which TPC this point is in. This function returns false
2728  // if the point is not inside any TPC
2729  double abit = -2;
2730  for (const geo::TPCID& tpcid: tjs.geom->IterateTPCIDs()) {
2731  const geo::TPCGeo& TPC = tjs.geom->TPC(tpcid);
2732  double local[3] = {0.,0.,0.};
2733  double world[3] = {0.,0.,0.};
2734  TPC.LocalToWorld(local,world);
2735  unsigned int cstat = tpcid.Cryostat;
2736  unsigned int tpc = tpcid.TPC;
2737  // reduce the active area of the TPC by 1 cm to be consistent with FillWireHitRange
2738  if(pos[0] < world[0]-tjs.geom->DetHalfWidth(tpc,cstat) + abit) continue;
2739  if(pos[0] > world[0]+tjs.geom->DetHalfWidth(tpc,cstat) - abit) continue;
2740  if(pos[1] < world[1]-tjs.geom->DetHalfHeight(tpc,cstat) + abit) continue;
2741  if(pos[1] > world[1]+tjs.geom->DetHalfHeight(tpc,cstat) - abit) continue;
2742  if(pos[2] < world[2]-tjs.geom->DetLength(tpc,cstat)/2 + abit) continue;
2743  if(pos[2] > world[2]+tjs.geom->DetLength(tpc,cstat)/2 - abit) continue;
2744  inTPCID = tpcid;
2745  return true;
2746  } // tpcid
2747  return false;
2748  } // InsideTPC
Geometry information for a single TPC.
Definition: TPCGeo.h:37
The data type to uniquely identify a TPC.
Definition: geo_types.h:195
void LocalToWorld(const double *tpc, double *world) const
Transform point from local TPC frame to world frame.
Definition: TPCGeo.h:490
bool tca::InTrajOK ( TjStuff tjs,
std::string  someText 
)

Definition at line 1199 of file Utils.cxx.

References AlgBitNames, tca::TjStuff::allTraj, evd::details::end(), tca::TjStuff::fHits, kKilled, kUsedHits, PrintHit(), PrintTrajectory(), PutTrajHitsInVector(), and tca::TjStuff::vtx.

Referenced by tca::TrajClusterAlg::FindVtxTraj(), tca::TrajClusterAlg::MakeAllTrajClusters(), tca::TrajClusterAlg::MakeJunkTraj(), and tca::TrajClusterAlg::ReconstructAllTraj().

1200  {
1201  // Check tjs.allTraj -> InTraj associations
1202 
1203  unsigned short tID;
1204  unsigned int iht;
1205  unsigned short itj = 0;
1206  std::vector<unsigned int> tHits;
1207  std::vector<unsigned int> atHits;
1208  for(auto& tj : tjs.allTraj) {
1209  // ignore abandoned trajectories
1210  if(tj.AlgMod[kKilled]) continue;
1211  tID = tj.ID;
1212  if(tj.AlgMod[kKilled]) {
1213  std::cout<<someText<<" ChkInTraj hit size mis-match in tj ID "<<tj.ID<<" AlgBitNames";
1214  for(unsigned short ib = 0; ib < AlgBitNames.size(); ++ib) if(tj.AlgMod[ib]) std::cout<<" "<<AlgBitNames[ib];
1215  std::cout<<"\n";
1216  continue;
1217  }
1218  tHits = PutTrajHitsInVector(tj, kUsedHits);
1219  if(tHits.size() < 2) {
1220  std::cout<<someText<<" ChkInTraj: Insufficient hits in traj "<<tj.ID<<"\n";
1221  PrintTrajectory("CIT", tjs, tj, USHRT_MAX);
1222  continue;
1223  }
1224  std::sort(tHits.begin(), tHits.end());
1225  atHits.clear();
1226  for(iht = 0; iht < tjs.fHits.size(); ++iht) {
1227  if(tjs.fHits[iht].InTraj == tID) atHits.push_back(iht);
1228  } // iht
1229  if(atHits.size() < 2) {
1230  std::cout<<someText<<" ChkInTraj: Insufficient hits in atHits in traj "<<tj.ID<<" Killing it\n";
1231  tj.AlgMod[kKilled] = true;
1232  continue;
1233  }
1234  if(!std::equal(tHits.begin(), tHits.end(), atHits.begin())) {
1235  mf::LogVerbatim myprt("TC");
1236  myprt<<someText<<" ChkInTraj failed: inTraj - UseHit mis-match for T"<<tID<<" tj.WorkID "<<tj.WorkID<<" atHits size "<<atHits.size()<<" tHits size "<<tHits.size()<<" in CTP "<<tj.CTP<<"\n";
1237  myprt<<"AlgMods: ";
1238  for(unsigned short ib = 0; ib < AlgBitNames.size(); ++ib) if(tj.AlgMod[ib]) myprt<<" "<<AlgBitNames[ib];
1239  myprt<<"\n";
1240  myprt<<"index inTraj UseHit \n";
1241  for(iht = 0; iht < atHits.size(); ++iht) {
1242  myprt<<"iht "<<iht<<" "<<PrintHit(tjs.fHits[atHits[iht]]);
1243  if(iht < tHits.size()) myprt<<" "<<PrintHit(tjs.fHits[tHits[iht]]);
1244  if(atHits[iht] != tHits[iht]) myprt<<" <<< "<<atHits[iht]<<" != "<<tHits[iht];
1245  myprt<<"\n";
1246  } // iht
1247  if(tHits.size() > atHits.size()) {
1248  for(iht = atHits.size(); iht < atHits.size(); ++iht) {
1249  myprt<<"atHits "<<iht<<" "<<PrintHit(tjs.fHits[atHits[iht]])<<"\n";
1250  } // iht
1251  PrintTrajectory("CIT", tjs, tj, USHRT_MAX);
1252  } // tHit.size > atHits.size()
1253  return false;
1254  }
1255  // check the VtxID
1256  for(unsigned short end = 0; end < 2; ++end) {
1257  if(tj.VtxID[end] > tjs.vtx.size()) {
1258  mf::LogVerbatim("TC")<<someText<<" ChkInTraj: Bad VtxID "<<tj.ID;
1259  std::cout<<someText<<" ChkInTraj: Bad VtxID "<<tj.ID<<" vtx size "<<tjs.vtx.size()<<"\n";
1260  tj.AlgMod[kKilled] = true;
1261  PrintTrajectory("CIT", tjs, tj, USHRT_MAX);
1262  return false;
1263  }
1264  } // end
1265  ++itj;
1266  } // tj
1267  return true;
1268 
1269  } // InTrajOK
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void PrintTrajectory(std::string someText, const TjStuff &tjs, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:4488
const std::vector< std::string > AlgBitNames
Definition: DataStructs.cxx:4
std::vector< unsigned int > PutTrajHitsInVector(Trajectory const &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2283
std::string PrintHit(const TCHit &hit)
Definition: Utils.cxx:4732
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
unsigned short tca::IsCloseToVertex ( TjStuff tjs,
VtxStore inVx2 
)

Definition at line 3093 of file TCVertex.cxx.

References tca::TjStuff::Vertex2DCuts, VertexVertexPull(), and tca::TjStuff::vtx.

Referenced by Find2DVertices().

3094  {
3095  // Returns the ID of a 2D vertex having the minimum pull < user-specified cut
3096 
3097  float minPull = tjs.Vertex2DCuts[3];
3098  unsigned short imBest = 0;
3099  for(auto& vx2 : tjs.vtx) {
3100  float pull = VertexVertexPull(tjs, inVx2, vx2);
3101  if(pull < minPull) {
3102  minPull = pull;
3103  imBest = vx2.ID;
3104  }
3105  } // vx2
3106  return imBest;
3107  } // IsCloseToVertex
float VertexVertexPull(TjStuff &tjs, const VtxStore &vx1, const VtxStore &vx2)
Definition: TCVertex.cxx:1898
unsigned short tca::IsCloseToVertex ( TjStuff tjs,
Vtx3Store vx3 
)

Definition at line 3110 of file TCVertex.cxx.

References tca::TjStuff::Vertex3DCuts, VertexVertexPull(), tca::TjStuff::vtx3, and tca::Vtx3Store::X.

3111  {
3112  // Returns the ID of a 3D vertex having the minimum pull < user-specified cut
3113 
3114  float minPull = tjs.Vertex3DCuts[1];
3115  unsigned short imBest = 0;
3116  for(auto& oldvx3 : tjs.vtx3) {
3117  if(oldvx3.ID == 0) continue;
3118  if(std::abs(oldvx3.X - vx3.X) > tjs.Vertex3DCuts[0]) continue;
3119  float pull = VertexVertexPull(tjs, vx3, oldvx3);
3120  if(pull < minPull) {
3121  minPull = pull;
3122  imBest = oldvx3.ID;
3123  }
3124  } // oldvx3
3125  return imBest;
3126 
3127  } // IsCloseToVertex
float VertexVertexPull(TjStuff &tjs, const VtxStore &vx1, const VtxStore &vx2)
Definition: TCVertex.cxx:1898
bool tca::IsShowerLike ( const TjStuff tjs,
const std::vector< int >  TjIDs 
)

Definition at line 2071 of file TCShower.cxx.

References tca::TjStuff::allTraj, and kShowerLike.

Referenced by DefineDontCluster(), DefinePFPParents(), and PrintPFP().

2072  {
2073  // Vote for the list of Tjs (assumed associated with a PFParticle) being shower-like
2074  if(TjIDs.empty()) return false;
2075  unsigned short cnt = 0;
2076  for(auto tid : TjIDs) {
2077  if(tid <= 0 || tid > (int)tjs.allTraj.size()) continue;
2078  if(tjs.allTraj[tid - 1].AlgMod[kShowerLike] > 0) ++cnt;
2079  } // tjid
2080  return (cnt > 1);
2081  } // IsInShower
void tca::KillPoorVertices ( TjStuff tjs,
const geo::TPCID tpcid 
)

Definition at line 2233 of file TCVertex.cxx.

References geo::CryostatID::Cryostat, DecodeCTP(), MakeVertexObsolete(), geo::TPCID::TPC, tca::TjStuff::Vertex2DCuts, tca::TjStuff::vtx, and tca::TjStuff::vtx3.

Referenced by tca::TrajClusterAlg::RunTrajClusterAlg().

2234  {
2235  // kill 2D vertices that have low score and are not attached to a high-score 3D vertex
2236  if(tjs.vtx.empty()) return;
2237  unsigned int cstat = tpcid.Cryostat;
2238  unsigned int tpc = tpcid.TPC;
2239  for(auto& vx : tjs.vtx) {
2240  if(vx.ID == 0) continue;
2241  geo::PlaneID planeID = DecodeCTP(vx.CTP);
2242  if(planeID.Cryostat != cstat) continue;
2243  if(planeID.TPC != tpc) continue;
2244  if(vx.Score > tjs.Vertex2DCuts[7]) continue;
2245  if(vx.Vx3ID > 0) {
2246  auto& vx3 = tjs.vtx3[vx.Vx3ID - 1];
2247  if(vx3.Primary) continue;
2248  if(tjs.vtx3[vx.Vx3ID - 1].Score >= tjs.Vertex2DCuts[7]) continue;
2249  }
2250  MakeVertexObsolete(tjs, vx, false);
2251  } // vx
2252 
2253  } // KillPoorVertices
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
bool MakeVertexObsolete(TjStuff &tjs, Vtx3Store &vx3)
Definition: TCVertex.cxx:3001
void tca::KillVerticesInShower ( std::string  inFcnLabel,
TjStuff tjs,
ShowerStruct ss,
bool  prt 
)

Definition at line 767 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::ShowerStruct::CTP, tca::TjStuff::dontCluster, tca::ShowerStruct::Envelope, GetAssns(), tca::ShowerStruct::ID, kKillInShowerVx, MakeVertexObsolete(), PointInsideEnvelope(), tca::TjStuff::UseAlg, tca::TjStuff::vtx, and tca::TjStuff::vtx3.

Referenced by MergeShowersAndStore().

768  {
769  // make the vertices inside the shower envelope obsolete and update dontCluster
770  if(ss.ID == 0) return;
771  if(!tjs.UseAlg[kKillInShowerVx]) return;
772  std::string fcnLabel = inFcnLabel + ".KVIS";
773 
774  for(auto& vx2 : tjs.vtx) {
775  if(vx2.ID == 0) continue;
776  if(vx2.CTP != ss.CTP) continue;
777  // ensure it isn't associated with a neutrino vertex
778  if(vx2.Vx3ID > 0 && tjs.vtx3[vx2.Vx3ID - 1].Neutrino) continue;
779  if(!PointInsideEnvelope(vx2.Pos, ss.Envelope)) continue;
780  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Clobber 2V"<<vx2.ID<<" -> 3V"<<vx2.Vx3ID<<" inside 2S"<<ss.ID;
781  // update dontCluster
782  for(auto& dc : tjs.dontCluster) {
783  if(dc.TjIDs[0] == 0) continue;
784  if(dc.Vx2ID != vx2.ID) continue;
785  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Remove T"<<dc.TjIDs[0]<<"-T"<<dc.TjIDs[0]<<" in dontCluster";
786  dc.TjIDs[0] = 0;
787  dc.TjIDs[1] = 0;
788  } // dc
789  if(vx2.Vx3ID > 0) {
790  auto TIn3V = GetAssns(tjs, "3V", vx2.Vx3ID, "T");
791  for(auto tid : TIn3V) tjs.allTraj[tid - 1].AlgMod[kKillInShowerVx] = true;
792  auto& vx3 = tjs.vtx3[vx2.Vx3ID - 1];
793  MakeVertexObsolete(tjs, vx3);
794  } else {
795  auto TIn2V = GetAssns(tjs, "2V", vx2.ID, "T");
796  for(auto tid : TIn2V) tjs.allTraj[tid - 1].AlgMod[kKillInShowerVx] = true;
797  MakeVertexObsolete(tjs, vx2, true);
798  }
799  } // vx2
800 
801  } // KillVerticesInShower
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
Float_t ss
Definition: plot.C:23
bool MakeVertexObsolete(TjStuff &tjs, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:2917
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:2705
std::vector< int > GetAssns(const TjStuff &tjs, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4079
double tca::KinkAngle ( const TjStuff tjs,
const std::vector< TrajPoint3 > &  tp3s,
unsigned short  atPt,
double  sep 
)

Definition at line 1913 of file PFPUtils.cxx.

References DeltaAngle(), and PosSep2().

Referenced by DotProd(), FindKinks(), PrintTp3s(), and Split3DKink().

1914  {
1915  // calculate a kink angle at the TjPt
1916  if(tp3s.empty()) return -1;
1917  if(atPt < 1 || atPt > tp3s.size() - 2) return -1;
1918  double sep2 = sep * sep;
1919  unsigned short pt1 = USHRT_MAX;
1920  for(unsigned short ii = 1; ii < tp3s.size(); ++ii) {
1921  unsigned short ipt = atPt - ii;
1922  if(PosSep2(tp3s[atPt].Pos, tp3s[ipt].Pos) > sep2) {
1923  pt1 = ipt;
1924  break;
1925  }
1926  if(ipt == 0) break;
1927  } // ii
1928  if(pt1 == USHRT_MAX) return -1;
1929  unsigned short pt2 = USHRT_MAX;
1930  for(unsigned short ii = 1; ii < tp3s.size(); ++ii) {
1931  unsigned short ipt = atPt + ii;
1932  if(ipt == tp3s.size()) break;
1933  if(PosSep2(tp3s[atPt].Pos, tp3s[ipt].Pos) > sep2) {
1934  pt2 = ipt;
1935  break;
1936  }
1937  } // ii
1938  if(pt2 == USHRT_MAX) return -1;
1939  return DeltaAngle(tp3s[pt1].Dir, tp3s[pt2].Dir);
1940  } // KinkAngle
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1607
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1631
float tca::LengthInCTP ( TjStuff tjs,
std::vector< int > &  tjids,
CTP_t  inCTP 
)

Definition at line 1106 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, and PosSep2().

1107  {
1108  // Calculates the maximum length between the end points of Tjs in the list of tjids in inCTP
1109  if(tjids.empty()) return 0;
1110  // put the end point positions into a vector
1111  std::vector<Point2_t> endPos;
1112  for(auto tjid : tjids) {
1113  auto& tj = tjs.allTraj[tjid - 1];
1114  if(tj.CTP != inCTP) continue;
1115  endPos.push_back(tj.Pts[tj.EndPt[0]].Pos);
1116  endPos.push_back(tj.Pts[tj.EndPt[1]].Pos);
1117  } // tjid
1118  if(endPos.size() < 2) return 0;
1119  float extent = 0;
1120  for(unsigned short pt1 = 0; pt1 < endPos.size() - 1; ++pt1) {
1121  for(unsigned short pt2 = pt1 + 1; pt2 < endPos.size(); ++pt2) {
1122  float sep = PosSep2(endPos[pt1], endPos[pt2]);
1123  if(sep > extent) extent = sep;
1124  } // pt2
1125  } // pt1
1126  return sqrt(extent);
1127  } // LengthInCTP
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1631
bool tca::LineLineIntersect ( Point3_t  p1,
Point3_t  p2,
Point3_t  p3,
Point3_t  p4,
Point3_t intersect,
float &  doca 
)

Definition at line 2781 of file PFPUtils.cxx.

References min, and PosSep().

Referenced by DotProd(), and PointDirIntersect().

2782  {
2783  /*
2784  Calculate the line segment PaPb that is the shortest route between
2785  two lines P1P2 and P3P4. Calculate also the values of mua and mub where
2786  Pa = P1 + mua (P2 - P1)
2787  Pb = P3 + mub (P4 - P3)
2788  Return FALSE if no solution exists.
2789  http://paulbourke.net/geometry/pointlineplane/
2790  */
2791 
2792  Point3_t p13, p43, p21;
2793  double d1343,d4321,d1321,d4343,d2121;
2794  double numer,denom;
2795  constexpr double EPS = std::numeric_limits<double>::min();
2796 
2797  p13[0] = p1[0] - p3[0];
2798  p13[1] = p1[1] - p3[1];
2799  p13[2] = p1[2] - p3[2];
2800  p43[0] = p4[0] - p3[0];
2801  p43[1] = p4[1] - p3[1];
2802  p43[2] = p4[2] - p3[2];
2803  if (std::abs(p43[0]) < EPS && std::abs(p43[1]) < EPS && std::abs(p43[2]) < EPS) return(false);
2804  p21[0] = p2[0] - p1[0];
2805  p21[1] = p2[1] - p1[1];
2806  p21[2] = p2[2] - p1[2];
2807  if (std::abs(p21[0]) < EPS && std::abs(p21[1]) < EPS && std::abs(p21[2]) < EPS) return(false);
2808 
2809  d1343 = p13[0] * p43[0] + p13[1] * p43[1] + p13[2] * p43[2];
2810  d4321 = p43[0] * p21[0] + p43[1] * p21[1] + p43[2] * p21[2];
2811  d1321 = p13[0] * p21[0] + p13[1] * p21[1] + p13[2] * p21[2];
2812  d4343 = p43[0] * p43[0] + p43[1] * p43[1] + p43[2] * p43[2];
2813  d2121 = p21[0] * p21[0] + p21[1] * p21[1] + p21[2] * p21[2];
2814 
2815  denom = d2121 * d4343 - d4321 * d4321;
2816  if (std::abs(denom) < EPS) return(false);
2817  numer = d1343 * d4321 - d1321 * d4343;
2818 
2819  double mua = numer / denom;
2820  double mub = (d1343 + d4321 * mua) / d4343;
2821 
2822  intersect[0] = p1[0] + mua * p21[0];
2823  intersect[1] = p1[1] + mua * p21[1];
2824  intersect[2] = p1[2] + mua * p21[2];
2825  Point3_t pb;
2826  pb[0] = p3[0] + mub * p43[0];
2827  pb[1] = p3[1] + mub * p43[1];
2828  pb[2] = p3[2] + mub * p43[2];
2829  doca = PosSep(intersect, pb);
2830  // average the closest points
2831  for(unsigned short xyz = 0; xyz < 3; ++xyz) intersect[xyz] += pb[xyz];
2832  for(unsigned short xyz = 0; xyz < 3; ++xyz) intersect[xyz] /= 2;
2833  return true;
2834  } // LineLineIntersect
std::array< double, 3 > Point3_t
Definition: DataStructs.h:35
Int_t min
Definition: plot.C:26
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
TrajPoint tca::MakeBareTP ( TjStuff tjs,
Point3_t pos,
Vector3_t dir,
CTP_t  inCTP 
)

Definition at line 3435 of file Utils.cxx.

References tca::TrajPoint::Ang, detinfo::DetectorProperties::ConvertXToTicks(), tca::TrajPoint::CTP, DecodeCTP(), tca::TrajPoint::Delta, tca::TjStuff::detprop, tca::TrajPoint::Dir, tca::TjStuff::geom, tca::TjStuff::MaxPos0, norm, geo::PlaneID::Plane, tca::TrajPoint::Pos, tca::TjStuff::UnitsPerTick, and geo::GeometryCore::WireCoordinate().

Referenced by DotProd(), FindMissedTjsInTp3s(), FindNeutralVertices(), FindParent(), FindPFParticles(), FindShowerStart(), tca::MCParticleListUtils::MakeTruTrajPoint(), tca::TruthMatcher::MatchTruth(), PrintShowers(), SetParent(), and tca::TruthMatcher::StudyShowerParents().

3436  {
3437  // Projects the space point defined by pos and dir into the CTP and returns it in the form of a trajectory point.
3438  // The TP Pos[0] is set to a negative number if the point has an invalid wire position but doesn't return an
3439  // error if the position is on a dead wire. The projection of the direction vector in CTP is stored in tp.Delta.
3440  TrajPoint tp;
3441  tp.Pos = {{0,0}};
3442  tp.Dir = {{0,1}};
3443  tp.CTP = inCTP;
3444  geo::PlaneID planeID = DecodeCTP(inCTP);
3445 
3446  tp.Pos[0] = tjs.geom->WireCoordinate(pos[1], pos[2], planeID);
3447  if(tp.Pos[0] < 0 || (!tjs.MaxPos0.empty() && tp.Pos[0] > tjs.MaxPos0[planeID.Plane])) {
3448  tp.Pos[0] = -1;
3449  return tp;
3450  }
3451  tp.Pos[1] = tjs.detprop->ConvertXToTicks(pos[0], planeID) * tjs.UnitsPerTick;
3452 
3453  // now find the direction if dir is defined
3454  if(dir[0] == 0 && dir[1] == 0 && dir[2] == 0) return tp;
3455  // Make a point at the origin and one 100 units away
3456  // BUG the double brace syntax is required to work around clang bug 21629
3457  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
3458  Point3_t ori3 = {{0.0, 0.0, 0.0}};
3459  Point3_t pos3 = {{100 * dir[0], 100 * dir[1], 100 * dir[2]}};
3460  // 2D position of ori3 and the pos3 projection
3461  std::array<double, 2> ori2;
3462  std::array<double, 2> pos2;
3463  std::array<double, 2> dir2;
3464  // the wire coordinates
3465  ori2[0] = tjs.geom->WireCoordinate(ori3[1], ori3[2], planeID);
3466  pos2[0] = tjs.geom->WireCoordinate(pos3[1], pos3[2], planeID);
3467  // the time coordinates
3468  ori2[1] = tjs.detprop->ConvertXToTicks(ori3[0], planeID) * tjs.UnitsPerTick;
3469  pos2[1] = tjs.detprop->ConvertXToTicks(pos3[0], planeID) * tjs.UnitsPerTick;
3470 
3471  dir2[0] = pos2[0] - ori2[0];
3472  dir2[1] = pos2[1] - ori2[1];
3473 
3474  double norm = sqrt(dir2[0] * dir2[0] + dir2[1] * dir2[1]);
3475  tp.Dir[0] = dir2[0] / norm;
3476  tp.Dir[1] = dir2[1] / norm;
3477  tp.Ang = atan2(dir2[1], dir2[0]);
3478  tp.Delta = norm / 100;
3479 
3480  // The Orth vectors are not unit normalized so we need to correct for this
3481  double w0 = tjs.geom->WireCoordinate(0, 0, planeID);
3482  // cosine-like component
3483  double cs = tjs.geom->WireCoordinate(1, 0, planeID) - w0;
3484  // sine-like component
3485  double sn = tjs.geom->WireCoordinate(0, 1, planeID) - w0;
3486  norm = sqrt(cs * cs + sn * sn);
3487  tp.Delta /= norm;
3488 
3489  return tp;
3490  } // MakeBareTP
std::array< double, 3 > Point3_t
Definition: DataStructs.h:35
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
Float_t norm
TDirectory * dir
Definition: macro.C:5
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
bool tca::MakeBareTrajPoint ( const TjStuff tjs,
unsigned int  fromHit,
unsigned int  toHit,
TrajPoint tp 
)

Definition at line 3493 of file Utils.cxx.

References EncodeCTP(), tca::TjStuff::fHits, and MakeBareTrajPoint().

Referenced by DotProd(), tca::TrajClusterAlg::EndMerge(), tca::TrajClusterAlg::FillGaps(), tca::TrajClusterAlg::GottaKink(), MergeShowerChain(), ParentFOM(), and tca::TrajClusterAlg::StartTraj().

3494  {
3495  CTP_t tCTP = EncodeCTP(tjs.fHits[fromHit].ArtPtr->WireID());
3496  return MakeBareTrajPoint(tjs, (float)tjs.fHits[fromHit].ArtPtr->WireID().Wire, tjs.fHits[fromHit].PeakTime,
3497  (float)tjs.fHits[toHit].ArtPtr->WireID().Wire, tjs.fHits[toHit].PeakTime, tCTP, tp);
3498 
3499  } // MakeBareTrajPoint
bool MakeBareTrajPoint(const TjStuff &tjs, const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
Definition: Utils.cxx:3536
unsigned int CTP_t
Definition: DataStructs.h:41
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
bool tca::MakeBareTrajPoint ( const TjStuff tjs,
float  fromWire,
float  fromTick,
float  toWire,
float  toTick,
CTP_t  tCTP,
TrajPoint tp 
)

Definition at line 3502 of file Utils.cxx.

References tca::TrajPoint::Ang, tca::TrajPoint::CTP, tca::TrajPoint::Dir, norm, tca::TrajPoint::Pos, and tca::TjStuff::UnitsPerTick.

3503  {
3504  tp.CTP = tCTP;
3505  tp.Pos[0] = fromWire;
3506  tp.Pos[1] = tjs.UnitsPerTick * fromTick;
3507  tp.Dir[0] = toWire - fromWire;
3508  tp.Dir[1] = tjs.UnitsPerTick * (toTick - fromTick);
3509  double norm = sqrt(tp.Dir[0] * tp.Dir[0] + tp.Dir[1] * tp.Dir[1]);
3510  if(norm == 0) return false;
3511  tp.Dir[0] /= norm;
3512  tp.Dir[1] /= norm;
3513  tp.Ang = atan2(tp.Dir[1], tp.Dir[0]);
3514  return true;
3515  } // MakeBareTrajPoint
Float_t norm
bool tca::MakeBareTrajPoint ( const Point2_t fromPos,
const Point2_t toPos,
TrajPoint tpOut 
)

Definition at line 3518 of file Utils.cxx.

References tca::TrajPoint::Ang, tca::TrajPoint::Dir, PointDirection(), and tca::TrajPoint::Pos.

3519  {
3520  tpOut.Pos = fromPos;
3521  tpOut.Dir = PointDirection(fromPos, toPos);
3522 /*
3523  tpOut.Dir[0] = toPos[0] - fromPos[0];
3524  tpOut.Dir[1] = toPos[1] - fromPos[1];
3525  double norm = sqrt(tpOut.Dir[0] * tpOut.Dir[0] + tpOut.Dir[1] * tpOut.Dir[1]);
3526  if(norm == 0) return false;
3527  tpOut.Dir[0] /= norm;
3528  tpOut.Dir[1] /= norm;
3529 */
3530  tpOut.Ang = atan2(tpOut.Dir[1], tpOut.Dir[0]);
3531  return true;
3532 
3533  } // MakeBareTrajPoint
Vector2_t PointDirection(const Point2_t p1, const Point2_t p2)
Definition: Utils.cxx:3563
bool tca::MakeBareTrajPoint ( const TjStuff tjs,
const TrajPoint tpIn1,
const TrajPoint tpIn2,
TrajPoint tpOut 
)

Definition at line 3536 of file Utils.cxx.

References tca::TrajPoint::Ang, tca::TrajPoint::CTP, tca::TrajPoint::Dir, PointDirection(), and tca::TrajPoint::Pos.

Referenced by FindCloseTjs(), MakeBareTrajPoint(), SignalBetween(), TjDeltaRMS(), and UpdateVxEnvironment().

3537  {
3538  tpOut.CTP = tpIn1.CTP;
3539  tpOut.Pos = tpIn1.Pos;
3540  tpOut.Dir = PointDirection(tpIn1.Pos, tpIn2.Pos);
3541 /*
3542  tpOut.Dir[0] = tpIn2.Pos[0] - tpIn1.Pos[0];
3543  tpOut.Dir[1] = tpIn2.Pos[1] - tpIn1.Pos[1];
3544  double norm = sqrt(tpOut.Dir[0] * tpOut.Dir[0] + tpOut.Dir[1] * tpOut.Dir[1]);
3545  if(norm == 0) return false;
3546  tpOut.Dir[0] /= norm;
3547  tpOut.Dir[1] /= norm;
3548 */
3549  tpOut.Ang = atan2(tpOut.Dir[1], tpOut.Dir[0]);
3550  return true;
3551  } // MakeBareTrajPoint
Vector2_t PointDirection(const Point2_t p1, const Point2_t p2)
Definition: Utils.cxx:3563
void tca::MakeJunkTjVertices ( TjStuff tjs,
const CTP_t inCTP 
)
void tca::MakeJunkVertices ( TjStuff tjs,
const CTP_t inCTP 
)

Definition at line 14 of file TCVertex.cxx.

References tca::TjStuff::allTraj, close(), tca::VtxStore::CTP, debug, DecodeCTP(), FindCloseTjs(), tca::VtxStore::ID, kFixed, kJunkTj, kJunkVx, kKilled, kShowerLike, tca::DebugStuff::Plane, geo::PlaneID::Plane, tca::VtxStore::Pos, tca::VtxStore::PosErr, PosSep(), tca::VtxStore::Score, SignalBetween(), tca::VtxStore::Stat, StoreVertex(), tca::DebugStuff::Tick, tca::VtxStore::Topo, TrajLength(), tca::TjStuff::UnitsPerTick, tca::TjStuff::UseAlg, tca::TjStuff::Vertex2DCuts, and tca::TjStuff::vtx.

Referenced by tca::TrajClusterAlg::ReconstructAllTraj().

15  {
16  // Vertices between poorly reconstructed tjs (especially junk tjs) and normal
17  // tjs can fail because the junk tj trajectory parameters are inaccurate. This function
18  // uses proximity and not pointing to make junk vertices
19  // Don't use this if standard vertex reconstruction is disabled
20  if(tjs.Vertex2DCuts[0] <= 0) return;
21  if(!tjs.UseAlg[kJunkVx]) return;
22  if(tjs.allTraj.size() < 2) return;
23 
24  // Look for tjs that are within maxSep of the end of a Tj
25  constexpr float maxSep = 4;
26 
27  geo::PlaneID planeID = DecodeCTP(inCTP);
28  bool prt = (debug.Plane == (int)planeID.Plane && debug.Tick == 99999);
29  if(prt) {
30  mf::LogVerbatim("TC")<<"MakeJunkVertices: prt set for plane "<<planeID.Plane<<" maxSep btw tjs "<<maxSep;
31 // PrintAllTraj("MJTi", tjs, debug, USHRT_MAX, tjs.allTraj.size());
32  }
33 
34  // make a template vertex
35  VtxStore junkVx;
36  junkVx.CTP = inCTP;
37  junkVx.Topo = 9;
38  junkVx.Stat[kJunkVx] = true;
39  junkVx.Stat[kFixed] = true;
40  // set an invalid ID
41  junkVx.ID = USHRT_MAX;
42  // put in generous errors
43  // BUG the double brace syntax is required to work around clang bug 21629
44  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
45  junkVx.PosErr = {{2.0, 2.0}};
46  // define a minimal score so it won't get clobbered
47  junkVx.Score = tjs.Vertex2DCuts[7] + 0.1;
48 
49  // look at both ends of long tjs
50  for(unsigned short it1 = 0; it1 < tjs.allTraj.size() - 1; ++it1) {
51  auto& tj1 = tjs.allTraj[it1];
52  if(tj1.AlgMod[kKilled]) continue;
53  if(tj1.SSID > 0 || tj1.AlgMod[kShowerLike]) continue;
54  if(tj1.CTP != inCTP) continue;
55  if(tj1.AlgMod[kJunkTj]) continue;
56  if(TrajLength(tj1) < 10) continue;
57  if(tj1.MCSMom < 100) continue;
58  for(unsigned short end1 = 0; end1 < 2; ++end1) {
59  // existing vertex?
60  if(tj1.VtxID[end1] > 0) continue;
61  auto& tp1 = tj1.Pts[tj1.EndPt[end1]];
62  // get a list of tjs in this vicinity
63  auto tjlist = FindCloseTjs(tjs, tp1, tp1, maxSep);
64  if(tjlist.empty()) continue;
65  // set to an invalid ID
66  junkVx.ID = USHRT_MAX;
67  for(auto tj2id : tjlist) {
68  auto& tj2 = tjs.allTraj[tj2id - 1];
69  if(tj2.CTP != inCTP) continue;
70  if(tj2id == tj1.ID) continue;
71  if(tj2.SSID > 0 || tj2.AlgMod[kShowerLike]) continue;
72  float close = maxSep;
73  unsigned short closeEnd = USHRT_MAX;
74  for(unsigned short end2 = 0; end2 < 2; ++end2) {
75  auto& tp2 = tj2.Pts[tj2.EndPt[end2]];
76  float sep = PosSep(tp1.Pos, tp2.Pos);
77  if(sep < close) {
78  close = sep;
79  closeEnd = end2;
80  } // sep
81  } // end2
82  if(closeEnd > 1) continue;
83  auto& tp2 = tj2.Pts[tj2.EndPt[closeEnd]];
84  bool signalBetween = SignalBetween(tjs, tp1, tp2, 0.8, prt);
85  if(!signalBetween) continue;
86  if(junkVx.ID == USHRT_MAX) {
87  // define the new vertex
88  junkVx.ID = tjs.vtx.size() + 1;
89  junkVx.Pos = tp1.Pos;
90  } // new vertex
91  tj2.VtxID[closeEnd] = junkVx.ID;
92  tj1.VtxID[end1] = junkVx.ID;
93  } // tjid
94  if(junkVx.ID == USHRT_MAX) continue;
95  if(!StoreVertex(tjs, junkVx)) {
96  mf::LogVerbatim("TC")<<"MJV: StoreVertex failed";
97  for(auto& tj : tjs.allTraj) {
98  if(tj.AlgMod[kKilled]) continue;
99  if(tj.VtxID[0] == junkVx.ID) tj.VtxID[0] = 0;
100  if(tj.VtxID[1] == junkVx.ID) tj.VtxID[1] = 0;
101  } // tj
102  continue;
103  } // StoreVertex failed
104  if(prt) {
105  mf::LogVerbatim("TC")<<" New junk 2V"<<junkVx.ID<<" at "<<std::fixed<<std::setprecision(1)<<junkVx.Pos[0]<<":"<<junkVx.Pos[1]/tjs.UnitsPerTick;
106  } // prt
107  junkVx.ID = USHRT_MAX;
108  } // end1
109  } // it1
110 
111  } // MakeJunkVertices
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
vertex position fixed manually - no fitting done
Definition: DataStructs.h:102
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
DebugStuff debug
Definition: DebugStruct.cxx:4
bool SignalBetween(TjStuff &tjs, const TrajPoint &tp1, const TrajPoint &tp2, const float &MinWireSignalFraction, bool prt)
Definition: Utils.cxx:1495
int Plane
Select plane.
Definition: DebugStruct.h:29
std::vector< int > FindCloseTjs(const TjStuff &tjs, const TrajPoint &fromTp, const TrajPoint &toTp, const float &maxDelta)
Definition: Utils.cxx:2466
float TrajLength(Trajectory &tj)
Definition: Utils.cxx:2204
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
int Tick
Select hit PeakTime for debugging (< 0 for vertex finding)
Definition: DebugStruct.h:32
in close()
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
bool StoreVertex(TjStuff &tjs, VtxStore &vx)
Definition: TCVertex.cxx:1911
void tca::MakeShowerObsolete ( std::string  inFcnLabel,
TjStuff tjs,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 3310 of file TCShower.cxx.

References tca::ShowerStruct3D::CotIDs, tca::TjStuff::cots, tca::ShowerStruct3D::ID, tca::ShowerStruct3D::PFPIndex, tca::TjStuff::pfps, and ss.

3311  {
3312  // set the ss3 ID = 0 and remove 2D shower -> 3D shower associations. The 2D showers are not
3313  // declared obsolete
3314  for(auto cid : ss3.CotIDs) {
3315  if(cid == 0 || (unsigned short)cid > tjs.cots.size()) continue;
3316  auto& ss = tjs.cots[cid - 1];
3317  if(ss.SS3ID > 0 && ss.SS3ID != ss3.ID) {
3318  std::cout<<"MakeShowerObsolete: 3S"<<ss3.ID<<" -> 2S"<<ss.ID<<" SS3ID 3S"<<ss.SS3ID<<" != "<<ss3.ID<<"\n";
3319  continue;
3320  }
3321  ss.SS3ID = 0;
3322  } // cid
3323  if(prt) {
3324  std::string fcnLabel = inFcnLabel + ".MSO";
3325  mf::LogVerbatim("TC")<<fcnLabel<<" Killed 3S"<<ss3.ID;
3326  }
3327  if(ss3.PFPIndex < tjs.pfps.size()) {
3328  std::cout<<"MakeShowerObsolete: 3S"<<ss3.ID<<" -> P"<<ss3.PFPIndex+1<<" assn exists but maybe shouldn't...";
3329  }
3330  ss3.ID = 0;
3331  } // MakeShowerObsolete
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
Float_t ss
Definition: plot.C:23
void tca::MakeShowerObsolete ( std::string  inFcnLabel,
TjStuff tjs,
ShowerStruct ss,
bool  prt 
)

Definition at line 3334 of file TCShower.cxx.

References tca::Trajectory::AlgMod, tca::TjStuff::allTraj, tca::ShowerStruct::ID, kKilled, kMergeNrShowers, kMergeOverlap, kMergeShChain, kMergeSubShowers, kShwrParent, MakeTrajectoryObsolete(), tca::TjStuff::showers, tca::ShowerStruct::ShowerTjID, tca::ShowerStruct::SS3ID, tca::Trajectory::SSID, and tca::ShowerStruct::TjIDs.

Referenced by CompleteIncompleteShower(), FindShowers3D(), Match2DShowers(), MergeShowers(), Reconcile3D(), and RemoveTj().

3335  {
3336  // Gracefully kills the shower and the associated shower Tj
3337 
3338  if(ss.ID == 0) return;
3339 
3340  std::string fcnLabel = inFcnLabel + ".MSO";
3341 
3342  auto& stp1 = tjs.allTraj[ss.ShowerTjID - 1].Pts[1];
3343  if(!stp1.Hits.empty()) {
3344  std::cout<<fcnLabel<<" Trying to kill shower "<<ss.ID<<" that has hits associated with it. Don't do this...\n";
3345  }
3346 
3347  // clear a 3S -> 2S assn
3348  if(ss.SS3ID > 0 && ss.SS3ID <= (int)tjs.showers.size()) {
3349  auto& ss3 = tjs.showers[ss.SS3ID - 1];
3350  std::vector<int> newCIDs;
3351  for(auto cid : ss3.CotIDs) {
3352  if(cid != ss.ID) newCIDs.push_back(cid);
3353  } // cid
3354  ss3.CotIDs = newCIDs;
3355  } // ss3 assn exists
3356 
3357  // Kill the shower Tj if it exists. This also releases the hits
3358  if(ss.ShowerTjID > 0) MakeTrajectoryObsolete(tjs, ss.ShowerTjID - 1);
3359 
3360  // Restore the original InShower Tjs
3361  // Unset the killed bit
3362  for(auto& tjID : ss.TjIDs) {
3363  Trajectory& tj = tjs.allTraj[tjID - 1];
3364  tj.AlgMod[kKilled] = false;
3365  // clear all of the shower-related bits
3366  tj.SSID = 0;
3367  tj.AlgMod[kShwrParent] = false;
3368  tj.AlgMod[kMergeOverlap] = false;
3369  tj.AlgMod[kMergeSubShowers] = false;
3370  tj.AlgMod[kMergeNrShowers] = false;
3371  tj.AlgMod[kMergeShChain] = false;
3372  } // tjID
3373  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Killed 2S"<<ss.ID<<" and ST"<<ss.ShowerTjID;
3374  ss.ID = 0;
3375  // No reason to do this
3376 // ss.TjIDs.clear();
3377 
3378  } // MakeShowerObsolete
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
Float_t ss
Definition: plot.C:23
void MakeTrajectoryObsolete(TjStuff &tjs, unsigned int itj)
Definition: Utils.cxx:1797
bool tca::MakeTp3 ( TjStuff tjs,
const TrajPoint itp,
const TrajPoint jtp,
TrajPoint3 tp3,
bool  findDirection 
)

Definition at line 1526 of file PFPUtils.cxx.

References tca::TrajPoint::Chg, detinfo::DetectorProperties::ConvertTicksToX(), detinfo::DetectorProperties::ConvertXToTicks(), tca::TrajPoint::CTP, DecodeCTP(), tca::TrajPoint3::dEdx, den, tca::TjStuff::detprop, tca::TrajPoint::Dir, tca::TrajPoint3::Dir, tca::TjStuff::geom, tca::TrajPoint::Pos, tca::TrajPoint3::Pos, PosSep(), tca::TjStuff::UnitsPerTick, and geo::GeometryCore::WireCoordinate().

Referenced by FindCompleteness(), FindXMatches(), Match2DShowers(), and UpdateShower().

1527  {
1528  // Make a 3D trajectory point using two 2D trajectory points
1529  tp3.Dir = {{999.0, 999.0, 999.0}};
1530  tp3.Pos = {{999.0, 999.0, 999.0}};
1531  geo::PlaneID iPlnID = DecodeCTP(itp.CTP);
1532  geo::PlaneID jPlnID = DecodeCTP(jtp.CTP);
1533  double upt = tjs.UnitsPerTick;
1534  double ix = tjs.detprop->ConvertTicksToX(itp.Pos[1] / upt, iPlnID);
1535  double jx = tjs.detprop->ConvertTicksToX(jtp.Pos[1] / upt, jPlnID);
1536 
1537  // don't continue if the points are wildly far apart in X
1538  if(std::abs(ix - jx) > 20) return false;
1539  tp3.Pos[0] = 0.5 * (ix + jx);
1540  // determine the wire orientation and offsets using WireCoordinate
1541  // wire = yp * OrthY + zp * OrthZ - Wire0 = cs * yp + sn * zp - wire0
1542  // wire offset
1543  double iw0 = tjs.geom->WireCoordinate(0, 0, iPlnID);
1544  // cosine-like component
1545  double ics = tjs.geom->WireCoordinate(1, 0, iPlnID) - iw0;
1546  // sine-like component
1547  double isn = tjs.geom->WireCoordinate(0, 1, iPlnID) - iw0;
1548  double jw0 = tjs.geom->WireCoordinate(0, 0, jPlnID);
1549  double jcs = tjs.geom->WireCoordinate(1, 0, jPlnID) - jw0;
1550  double jsn = tjs.geom->WireCoordinate(0, 1, jPlnID) - jw0;
1551  double den = isn * jcs - ics * jsn;
1552  if(den == 0) return false;
1553  double iPos0 = itp.Pos[0];
1554  double jPos0 = jtp.Pos[0];
1555  // Find the Z position of the intersection
1556  tp3.Pos[2] = (jcs * (iPos0 - iw0) - ics * (jPos0 - jw0)) / den;
1557  // and the Y position
1558  bool useI = std::abs(ics) > std::abs(jcs);
1559  if(useI) {
1560  tp3.Pos[1] = (iPos0 - iw0 - isn * tp3.Pos[2]) / ics;
1561  } else {
1562  tp3.Pos[1] = (jPos0 - jw0 - jsn * tp3.Pos[2]) / jcs;
1563  }
1564 
1565  // Now find the direction. Protect against large angles first
1566  if(jtp.Dir[1] == 0) {
1567  // Going either in the +X direction or -X direction
1568  if(jtp.Dir[0] > 0) { tp3.Dir[0] = 1; } else { tp3.Dir[0] = -1; }
1569  tp3.Dir[1] = 0;
1570  tp3.Dir[2] = 0;
1571  return true;
1572  } // jtp.Dir[1] == 0
1573 
1574  // stuff the average TP charge into dEdx
1575  tp3.dEdx = 0.5 * (itp.Chg + jtp.Chg);
1576 
1577  if(!findDirection) return true;
1578 
1579  // make a copy of itp and shift it by many wires to avoid precision problems
1580  double itp2_0 = itp.Pos[0] + 100;
1581  double itp2_1 = itp.Pos[1];
1582  if(std::abs(itp.Dir[0]) > 0.01) itp2_1 += 100 * itp.Dir[1] / itp.Dir[0];
1583  // Create a second Point3 for the shifted point
1584  Point3_t pos2;
1585  // Find the X position corresponding to the shifted point
1586  pos2[0] = tjs.detprop->ConvertTicksToX(itp2_1 / upt, iPlnID);
1587  // Convert X to Ticks in the j plane and then to WSE units
1588  double jtp2Pos1 = tjs.detprop->ConvertXToTicks(pos2[0], jPlnID) * upt;
1589  // Find the wire position (Pos0) in the j plane that this corresponds to
1590  double jtp2Pos0 = (jtp2Pos1 - jtp.Pos[1]) * (jtp.Dir[0] / jtp.Dir[1]) + jtp.Pos[0];
1591  // Find the Y,Z position using itp2 and jtp2Pos0
1592  pos2[2] = (jcs * (itp2_0 - iw0) - ics * (jtp2Pos0 - jw0)) / den;
1593  if(useI) {
1594  pos2[1] = (itp2_0 - iw0 - isn * pos2[2]) / ics;
1595  } else {
1596  pos2[1] = (jtp2Pos0 - jw0 - jsn * pos2[2]) / jcs;
1597  }
1598  double sep = PosSep(tp3.Pos, pos2);
1599  if(sep == 0) return false;
1600  for(unsigned short ixyz = 0; ixyz < 3; ++ixyz) tp3.Dir[ixyz] = (pos2[ixyz] - tp3.Pos[ixyz]) /sep;
1601 
1602  return true;
1603 
1604  } // MakeTP3
std::array< double, 3 > Point3_t
Definition: DataStructs.h:35
Float_t den
Definition: plot.C:37
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
void tca::MakeTrajectoryObsolete ( TjStuff tjs,
unsigned int  itj 
)

Definition at line 1797 of file Utils.cxx.

References tca::TjStuff::allTraj, tca::TjStuff::fHits, and kKilled.

Referenced by MakeShowerObsolete(), MergeAndStore(), MergePFPTjs(), and MergeShowersAndStore().

1798  {
1799  // Note that this does not change the state of UseHit to allow
1800  // resurrecting the trajectory later (RestoreObsoleteTrajectory)
1801  if(itj > tjs.allTraj.size() - 1) return;
1802  int killTjID = tjs.allTraj[itj].ID;
1803  for(auto& hit : tjs.fHits) if(hit.InTraj == killTjID) hit.InTraj = 0;
1804  tjs.allTraj[itj].AlgMod[kKilled] = true;
1805  } // MakeTrajectoryObsolete
Detector simulation of raw signals on wires.
bool tca::MakeVertexObsolete ( TjStuff tjs,
VtxStore vx2,
bool  forceKill 
)

Definition at line 2917 of file TCVertex.cxx.

References tca::TjStuff::allTraj, tca::VtxStore::CTP, DecodeCTP(), evd::details::end(), tca::VtxStore::ID, tca::Vtx3Store::ID, kEnvOverlap, kHiVx3Score, kKilled, kPhoton, kTjHiVx3Score, tca::TjStuff::NumPlanes, tca::TjStuff::pfps, geo::PlaneID::Plane, tca::VtxStore::Pos, SetVx3Score(), tca::TjStuff::Vertex2DCuts, tca::TjStuff::vtx, tca::TjStuff::vtx3, tca::Vtx3Store::Vx2ID, tca::VtxStore::Vx3ID, and tca::Vtx3Store::Wire.

Referenced by CheckTrajBeginChg(), ChkVxTjs(), CompleteIncomplete3DVertices(), KillPoorVertices(), KillVerticesInShower(), MakeVertexObsolete(), MergeAndStore(), MergePFPTjs(), SplitTrajCrossingVertices(), and TagShowerLike().

2918  {
2919  // Makes a 2D vertex obsolete
2920 
2921  // check for a high-score 3D vertex
2922  bool hasHighScoreVx3 = (vx2.Vx3ID > 0);
2923  if(hasHighScoreVx3 && !forceKill && tjs.vtx3[vx2.Vx3ID - 1].Score >= tjs.Vertex2DCuts[7]) return false;
2924 
2925  // Kill it
2926  int vx2id = vx2.ID;
2927  if(vx2.Vx3ID > 0) {
2928  auto& vx3 = tjs.vtx3[vx2.Vx3ID - 1];
2929  for(auto& v3v2id : vx3.Vx2ID) if(v3v2id == vx2.ID) v3v2id = 0;
2930  }
2931  vx2.ID = 0;
2932  for(auto& tj : tjs.allTraj) {
2933  if(tj.AlgMod[kKilled]) continue;
2934  for(unsigned short end = 0; end < 2; ++end) {
2935  if(tj.VtxID[end] != vx2id) continue;
2936  tj.VtxID[end] = 0;
2937  tj.AlgMod[kPhoton] = false;
2938  // clear the kEnvOverlap bits on the TPs
2939  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
2940  if(end == 0) {
2941  unsigned short ipt = tj.EndPt[0] + ii;
2942  auto& tp = tj.Pts[ipt];
2943  if(!tp.Environment[kEnvOverlap]) break;
2944  if(ipt == tj.EndPt[1]) break;
2945  } else {
2946  unsigned short ipt = tj.EndPt[1] - ii;
2947  auto& tp = tj.Pts[ipt];
2948  if(!tp.Environment[kEnvOverlap]) break;
2949  if(ipt == tj.EndPt[0]) break;
2950  }
2951  } // ii
2952  if(tj.AlgMod[kTjHiVx3Score]) {
2953  // see if the vertex at the other end is high-score and if so, preserve the state
2954  unsigned short oend = 1 - end;
2955  if(tj.VtxID[oend] > 0) {
2956  auto& ovx2 = tjs.vtx[tj.VtxID[oend] - 1];
2957  if(!ovx2.Stat[kHiVx3Score]) tj.AlgMod[kTjHiVx3Score] = false;
2958  } // vertex at the other end
2959  } // tj.AlgMod[kTjHiVx3Score]
2960  } // end
2961  } // tj
2962 
2963  if(!hasHighScoreVx3) return true;
2964 
2965  // update the affected 3D vertex
2966  Vtx3Store& vx3 = tjs.vtx3[vx2.Vx3ID - 1];
2967  // make the 3D vertex incomplete
2968  geo::PlaneID planeID = DecodeCTP(vx2.CTP);
2969  unsigned short plane = planeID.Plane;
2970  if(vx3.Vx2ID[plane] != vx2id) return true;
2971  vx3.Vx2ID[plane] = 0;
2972  vx3.Wire = vx2.Pos[0];
2973  // Ensure that there are at least two 2D vertices left
2974  unsigned short n2D = 0;
2975  for(unsigned short plane = 0; plane < tjs.NumPlanes; ++plane) {
2976  if(vx3.Vx2ID[plane] > 0) ++n2D;
2977  } // plane
2978 
2979  if(n2D > 1) {
2980  // 3D vertex is incomplete
2981  // correct the score
2982  SetVx3Score(tjs, vx3, false);
2983  return true;
2984  }
2985 
2986  // 3D vertex is obsolete
2987  // Detach the all remaining 2D vertices from the 3D vertex
2988  for(auto& vx2 : tjs.vtx) {
2989  if(vx2.ID == 0) continue;
2990  if(vx2.Vx3ID == vx3.ID) vx2.Vx3ID = 0;
2991  } // vx2
2992  for(auto& pfp : tjs.pfps) {
2993  for(unsigned short end = 0; end < 2; ++end) if(pfp.Vx3ID[end] == vx3.ID) pfp.Vx3ID[end] = 0;
2994  } // pfp
2995  vx3.ID = 0;
2996  return true;
2997 
2998  } // MakeVertexObsolete
void SetVx3Score(TjStuff &tjs, Vtx3Store &vx3, bool prt)
Definition: TCVertex.cxx:2303
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
matched to a high-score 3D vertex
Definition: DataStructs.h:104
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool tca::MakeVertexObsolete ( TjStuff tjs,
Vtx3Store vx3 
)

Definition at line 3001 of file TCVertex.cxx.

References tca::Vtx3Store::ID, MakeVertexObsolete(), tca::TjStuff::vtx, tca::TjStuff::vtx3, and tca::Vtx3Store::Vx2ID.

3002  {
3003  // Deletes a 3D vertex and 2D vertices in all planes
3004  // The 2D and 3D vertices are NOT killed if forceKill is false and the 3D vertex
3005  // has a high score
3006  if(vx3.ID == 0) return true;
3007  if(vx3.ID > int(tjs.vtx3.size())) return false;
3008 
3009  // set the score to 0
3010 // vx3.Score = 0;
3011 
3012  for(auto vx2id : vx3.Vx2ID) {
3013  if(vx2id == 0 || vx2id > (int)tjs.vtx.size()) continue;
3014  auto& vx2 = tjs.vtx[vx2id - 1];
3015  MakeVertexObsolete(tjs, vx2, true);
3016  }
3017  vx3.ID = 0;
3018  return true;
3019  } // MakeVertexObsolete
bool MakeVertexObsolete(TjStuff &tjs, Vtx3Store &vx3)
Definition: TCVertex.cxx:3001
void tca::Match2DShowers ( std::string  inFcnLabel,
TjStuff tjs,
const geo::TPCID tpcid,
bool  prt 
)

Definition at line 947 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::ShowerStruct3D::ChgPos, ChkAssns(), CompleteIncompleteShower(), tca::ShowerStruct3D::CotIDs, tca::TjStuff::cots, CreateSS3(), geo::CryostatID::Cryostat, tca::ShowerStruct::CTP, DecodeCTP(), tca::TrajPoint3::Dir, tca::ShowerStruct3D::Dir, tca::ShowerStruct::Energy, tca::ShowerStruct3D::Energy, greaterThan(), tca::ShowerStruct::ID, tca::ShowerStruct3D::ID, tca::SortEntry::index, MakeShowerObsolete(), MakeTp3(), Match3DFOM(), tca::ShowerStruct3D::MatchFOM, tca::TjStuff::NumPlanes, tca::ShowerStruct3D::PFPIndex, geo::PlaneID::Plane, tca::TrajPoint3::Pos, PosSep(), PrintShowers(), tca::Trajectory::Pts, Reconcile3D(), tca::TjStuff::showers, tca::ShowerStruct::ShowerTjID, ss, tca::ShowerStruct::SS3ID, StoreShower(), tca::ShowerStruct::TjIDs, geo::TPCID::TPC, and UpdateShower().

Referenced by FindShowers3D().

948  {
949  // Match 2D showers using position and direction to create 3D showers
950 
951  std::string fcnLabel = inFcnLabel + ".M2DS";
952  if(prt) mf::LogVerbatim("TC")<<fcnLabel;
953 
954  float fomCut = 2;
955 
956  ChkAssns(fcnLabel, tjs);
957 
958  // sort the showers by decreasing energy and increasing AspectRatio so that the 3D direction is defined
959  // by the first matching pair
960  std::vector<SortEntry> sortVec;
961  for(unsigned short indx = 0; indx < tjs.cots.size(); ++indx) {
962  auto& ss = tjs.cots[indx];
963  if(ss.ID == 0) continue;
964  // already matched?
965  if(ss.SS3ID > 0) continue;
966  if(ss.TjIDs.empty()) continue;
967  geo::PlaneID planeID = DecodeCTP(ss.CTP);
968  if(planeID.Cryostat != tpcid.Cryostat) continue;
969  if(planeID.TPC != tpcid.TPC) continue;
970  SortEntry se;
971  se.index = indx;
972  se.length = ss.Energy / ss.AspectRatio;
973  sortVec.push_back(se);
974  } // indx
975  if(sortVec.size() < 2) return;
976  std::sort(sortVec.begin(), sortVec.end(), greaterThan);
977 
978  // Look for a 3D match using the 2D shower charge centers
979  for(unsigned short ii = 0; ii < sortVec.size() - 1; ++ii) {
980  unsigned short iIndx = sortVec[ii].index;
981  auto& iss = tjs.cots[iIndx];
982  // already matched?
983  if(iss.SS3ID > 0) continue;
984  Trajectory& istj = tjs.allTraj[iss.ShowerTjID - 1];
985  geo::PlaneID iplaneID = DecodeCTP(iss.CTP);
986  for(unsigned short jj = 0; jj < sortVec.size(); ++jj) {
987  if(iss.SS3ID > 0) break;
988  unsigned short jIndx = sortVec[jj].index;
989  ShowerStruct& jss = tjs.cots[jIndx];
990  // already matched?
991  if(iss.SS3ID > 0) break;
992  if(jss.SS3ID > 0) continue;
993  if(jss.CTP == iss.CTP) continue;
994  Trajectory& jstj = tjs.allTraj[jss.ShowerTjID - 1];
995  TrajPoint3 tp3;
996  if(!MakeTp3(tjs, istj.Pts[1], jstj.Pts[1], tp3, true)) continue;
997  float fomij = Match3DFOM(fcnLabel, tjs, iss.ID, jss.ID, prt);
998  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" i2S"<<iss.ID<<" j2S"<<jss.ID<<" fomij "<<fomij<<" fomCut "<<fomCut;
999  if(fomij > fomCut) continue;
1000  geo::PlaneID jplaneID = DecodeCTP(jss.CTP);
1001  if(tjs.NumPlanes == 2) {
1002  ShowerStruct3D ss3 = CreateSS3(tjs, tpcid);
1003  ss3.ChgPos = tp3.Pos;
1004  ss3.Dir = tp3.Dir;
1005  ss3.CotIDs.resize(2);
1006  ss3.CotIDs[0] = iss.ID;
1007  ss3.CotIDs[1] = jss.ID;
1008  ss3.Energy.resize(2);
1009  ss3.Energy[0] = iss.Energy;
1010  ss3.Energy[1] = jss.Energy;
1011  ss3.MatchFOM = fomij;
1012  ss3.PFPIndex = USHRT_MAX;
1013  if(!StoreShower(fcnLabel, tjs, ss3)) continue;
1014  if(prt) mf::LogVerbatim("TC")<<" new 2-plane TPC 3S"<<ss3.ID<<" with fomij "<<fomij;
1015  continue;
1016  } // 2-plane TPC
1017  float bestFOM = fomCut;
1018  unsigned short bestck = USHRT_MAX;
1019  for(unsigned short ck = 0; ck < tjs.cots.size(); ++ck) {
1020  ShowerStruct& kss = tjs.cots[ck];
1021  if(kss.ID == iss.ID || kss.ID == jss.ID) continue;
1022  if(kss.CTP == iss.CTP || kss.CTP == jss.CTP) continue;
1023  if(kss.ID == 0) continue;
1024  if(kss.TjIDs.empty()) continue;
1025  if(kss.SS3ID > 0) continue;
1026  geo::PlaneID kplaneID = DecodeCTP(kss.CTP);
1027  if(kplaneID.Cryostat != tpcid.Cryostat) continue;
1028  if(kplaneID.TPC != tpcid.TPC) continue;
1029  Trajectory& kstj = tjs.allTraj[kss.ShowerTjID - 1];
1030  TrajPoint3 iktp3;
1031  MakeTp3(tjs, istj.Pts[1], kstj.Pts[1], iktp3, true);
1032  float fomik = Match3DFOM(fcnLabel, tjs, iss.ID, kss.ID, prt);
1033  if(fomik > bestFOM) continue;
1034  float sep = PosSep(tp3.Pos, iktp3.Pos);
1035  if(sep > 50) {
1036  if(prt) mf::LogVerbatim("TC")<<" 2S"<<iss.ID<<" 2S"<<jss.ID<<" 2S"<<kss.ID<<" Large stp[1] point separation "<<(int)sep;
1037  continue;
1038  }
1039  bestFOM = fomik;
1040  bestck = ck;
1041  } // ck
1042  // 3-plane TPC below
1043  ShowerStruct3D ss3 = CreateSS3(tjs, tpcid);
1044  // Define ss3 using the tp3 found with the first pair
1045  ss3.ChgPos = tp3.Pos;
1046  ss3.Dir = tp3.Dir;
1047  ss3.MatchFOM = bestFOM;
1048  if(bestck == USHRT_MAX) {
1049  // showers match in 2 planes
1050  ss3.CotIDs.resize(2);
1051  ss3.CotIDs[0] = iss.ID;
1052  ss3.CotIDs[1] = jss.ID;
1053  ss3.Energy[iplaneID.Plane] = iss.Energy;
1054  ss3.Energy[jplaneID.Plane] = jss.Energy;
1055  if(prt) mf::LogVerbatim("TC")<<" new 2-plane 3S"<<ss3.ID<<" using 2S"<<iss.ID<<" 2S"<<jss.ID<<" with FOM "<<ss3.MatchFOM<<" try to complete it";
1056  // ignore this 3D match if the shower can't be completed
1057  if(!CompleteIncompleteShower(fcnLabel, tjs, ss3, prt)) continue;
1058  iss.SS3ID = ss3.ID;
1059  jss.SS3ID = ss3.ID;
1060  } else {
1061  // showers match in 3 planes
1062  unsigned short ck = bestck;
1063  ShowerStruct& kss = tjs.cots[ck];
1064  ss3.CotIDs.resize(3);
1065  ss3.CotIDs[0] = iss.ID;
1066  ss3.CotIDs[1] = jss.ID;
1067  ss3.CotIDs[2] = kss.ID;
1068  geo::PlaneID kplaneID = DecodeCTP(kss.CTP);
1069  ss3.Energy[iplaneID.Plane] = iss.Energy;
1070  ss3.Energy[jplaneID.Plane] = jss.Energy;
1071  ss3.Energy[kplaneID.Plane] = kss.Energy;
1072  tjs.cots[ck].SS3ID = ss3.ID;
1073  if(prt) mf::LogVerbatim("TC")<<" new 3-plane 3S"<<ss3.ID<<" using 2S"<<iss.ID<<" 2S"<<jss.ID<<" 2S"<<tjs.cots[ck].ID<<" with FOM "<<ss3.MatchFOM;
1074  }
1075  ss3.MatchFOM = 0.5 * (fomij + bestFOM);
1076  // sort the IDs
1077  std::sort(ss3.CotIDs.begin(), ss3.CotIDs.end());
1078  // Set the 3S -> 2S assns and store it
1079  if(!StoreShower(fcnLabel, tjs, ss3)) {
1080  MakeShowerObsolete(fcnLabel, tjs, ss3, prt);
1081  continue;
1082  }
1083  // make a reference to the stored shower
1084  auto& nss3 = tjs.showers[tjs.showers.size() - 1];
1085  if(nss3.NeedsUpdate) UpdateShower(fcnLabel, tjs, nss3, prt);
1086  // reconcile tj -> 2S -> 3S and tj -> pfps
1087  if(!Reconcile3D(fcnLabel, tjs, nss3, prt)) {
1088  MakeShowerObsolete(fcnLabel, tjs, nss3, prt);
1089  continue;
1090  }
1091  if(nss3.NeedsUpdate) UpdateShower(fcnLabel, tjs, nss3, prt);
1092  if(prt) mf::LogVerbatim("TC")<<" 3S"<<nss3.ID<<" updated";
1093  break;
1094  } // cj
1095  } // ci
1096 
1097  ChkAssns(fcnLabel, tjs);
1098 
1099  if(prt) PrintShowers("M2DS", tjs);
1100 
1101  } // Match2DShowers
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void MakeShowerObsolete(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3334
bool greaterThan(SortEntry c1, SortEntry c2)
Definition: TCShower.cxx:9
unsigned int index
Definition: TCShower.cxx:5
bool ChkAssns(std::string inFcnLabel, TjStuff &tjs)
Definition: TCShower.cxx:4625
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
Float_t ss
Definition: plot.C:23
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
float length
Definition: TCShower.cxx:6
bool MakeTp3(TjStuff &tjs, const TrajPoint &itp, const TrajPoint &jtp, TrajPoint3 &tp3, bool findDirection)
Definition: PFPUtils.cxx:1526
bool Reconcile3D(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:645
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
ShowerStruct3D CreateSS3(TjStuff &tjs, const geo::TPCID &tpcid)
Definition: TCShower.cxx:4553
float Match3DFOM(std::string inFcnLabel, TjStuff &tjs, int icid, int jcid, bool prt)
Definition: TCShower.cxx:1449
void PrintShowers(std::string fcnLabel, TjStuff &tjs)
Definition: TCShower.cxx:4676
bool StoreShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss)
Definition: TCShower.cxx:4511
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
bool CompleteIncompleteShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:804
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
bool UpdateShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1302
float tca::Match3DFOM ( std::string  inFcnLabel,
TjStuff tjs,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 1417 of file TCShower.cxx.

References tca::ShowerStruct3D::CotIDs, and Match3DFOM().

1418  {
1419  float fom = 0;
1420  float cnt = 0;
1421  for(unsigned short ii = 0; ii < ss3.CotIDs.size() - 1; ++ii) {
1422  unsigned short icid = ss3.CotIDs[ii];
1423  for(unsigned short jj = ii + 1; jj < ss3.CotIDs.size(); ++jj) {
1424  unsigned short jcid = ss3.CotIDs[jj];
1425  fom += Match3DFOM(inFcnLabel, tjs, icid, jcid, prt);
1426  ++cnt;
1427  } // cj
1428  } // ci
1429  if(cnt == 0) return 100;
1430  return fom / cnt;
1431  } // Match3DFOM
float Match3DFOM(std::string inFcnLabel, TjStuff &tjs, int icid, int jcid, bool prt)
Definition: TCShower.cxx:1449
float tca::Match3DFOM ( std::string  inFcnLabel,
TjStuff tjs,
int  icid,
int  jcid,
int  kcid,
bool  prt 
)

Definition at line 1434 of file TCShower.cxx.

References tca::TjStuff::cots, and Match3DFOM().

1436  {
1437  if(icid == 0 || icid > (int)tjs.cots.size()) return 100;
1438  if(jcid == 0 || jcid > (int)tjs.cots.size()) return 100;
1439  if(kcid == 0 || kcid > (int)tjs.cots.size()) return 100;
1440 
1441  float ijfom = Match3DFOM(inFcnLabel, tjs, icid, jcid, prt);
1442  float jkfom = Match3DFOM(inFcnLabel, tjs, jcid, kcid, prt);
1443 
1444  return 0.5 * (ijfom + jkfom);
1445 
1446  } // Match3DFOM
float Match3DFOM(std::string inFcnLabel, TjStuff &tjs, int icid, int jcid, bool prt)
Definition: TCShower.cxx:1449
float tca::Match3DFOM ( std::string  inFcnLabel,
TjStuff tjs,
int  icid,
int  jcid,
bool  prt 
)

Definition at line 1449 of file TCShower.cxx.

References tca::TjStuff::allTraj, detinfo::DetectorProperties::ConvertTicksToX(), tca::TjStuff::cots, DecodeCTP(), tca::TjStuff::detprop, and tca::TjStuff::UnitsPerTick.

Referenced by Match2DShowers(), and Match3DFOM().

1450  {
1451  // returns a Figure of Merit for a 3D match of two showers
1452  if(icid == 0 || icid > (int)tjs.cots.size()) return 100;
1453  if(jcid == 0 || jcid > (int)tjs.cots.size()) return 100;
1454 
1455  auto& iss = tjs.cots[icid - 1];
1456  auto& istj = tjs.allTraj[iss.ShowerTjID - 1];
1457  auto& jss = tjs.cots[jcid - 1];
1458  auto& jstj = tjs.allTraj[jss.ShowerTjID - 1];
1459 
1460  if(iss.CTP == jss.CTP) return 100;
1461 
1462  std::string fcnLabel = inFcnLabel + ".MFOM";
1463 
1464  float energyAsym = std::abs(iss.Energy - jss.Energy) / (iss.Energy + jss.Energy);
1465 
1466  // don't apply the asymmetry cut on low energy showers
1467  if((iss.Energy > 200 || jss.Energy > 200) && energyAsym > 0.5) return 50;
1468 
1469  geo::PlaneID iPlnID = DecodeCTP(iss.CTP);
1470  geo::PlaneID jPlnID = DecodeCTP(jss.CTP);
1471 
1472  // compare match at the charge center
1473  float ix = tjs.detprop->ConvertTicksToX(istj.Pts[1].Pos[1] / tjs.UnitsPerTick, iPlnID);
1474  float jx = tjs.detprop->ConvertTicksToX(jstj.Pts[1].Pos[1] / tjs.UnitsPerTick, jPlnID);
1475  float pos1fom = std::abs(ix - jx) / 10;
1476 
1477  float mfom = energyAsym * pos1fom;
1478 
1479  if(prt) {
1480  mf::LogVerbatim myprt("TC");
1481  myprt<<fcnLabel<<" i2S"<<iss.ID<<" j2S"<<jss.ID;
1482  myprt<<std::fixed<<std::setprecision(2);
1483 // myprt<<" pos0fom "<<pos0fom;
1484  myprt<<" pos1fom "<<pos1fom;
1485 // myprt<<" pos2fom "<<pos2fom;
1486  myprt<<" energyAsym "<<energyAsym;
1487  myprt<<" mfom "<<mfom;
1488  }
1489 
1490  return mfom;
1491  } // Madtch3DFOM
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
void tca::Match3DVtxTjs ( TjStuff tjs,
const geo::TPCID tpcid,
bool  prt 
)

Definition at line 1506 of file TCVertex.cxx.

References tca::TjStuff::allTraj, AnalyzePFP(), CreatePFP(), DefinePFP(), tca::PFPStruct::Dir, GetVtxTjIDs(), tca::PFPStruct::ID, tca::SortEntry::index, kKilled, kMat3D, tca::TjStuff::matchVec, tca::PFPStruct::MatchVecIndex, tca::TjStuff::NumPlanes, tca::PFPStruct::PDGCode, PDGCodeVote(), PrintPFP(), SetDifference(), SetIntersection(), Split3DKink(), StorePFP(), tca::PFPStruct::TjIDs, tmp, tca::SortEntry::val, valDecreasing(), tca::TjStuff::Vertex2DCuts, tca::TjStuff::vtx3, tca::PFPStruct::Vx3ID, and tca::PFPStruct::XYZ.

Referenced by FindPFParticles().

1507  {
1508  // Matches Tjs that are attached to 2D vertices that are matched in 3D. This function does not attempt
1509  // to determine the appropriate ends of matched Tjs when there is a 3D vertex at both ends. This is done
1510  // in Find3DEndPoints
1511 
1512  if(tjs.vtx3.empty()) return;
1513  if(tjs.matchVec.empty()) return;
1514 
1515  // sort the vertices by decreasing score
1516  std::vector<SortEntry> sortVec;
1517  for(unsigned short iv3 = 0; iv3 < tjs.vtx3.size(); ++iv3) {
1518  auto& vx3 = tjs.vtx3[iv3];
1519  if(vx3.ID == 0) continue;
1520  if(vx3.TPCID != tpcid) continue;
1521  // put the TjIDs into a vector for matching
1522  float score = 0;
1523  auto v3TjIDs = GetVtxTjIDs(tjs, vx3, score);
1524  if(v3TjIDs.empty()) continue;
1525  if(score < tjs.Vertex2DCuts[7]) continue;
1526 /*
1527  if(prt) {
1528  mf::LogVerbatim myprt("TC");
1529  myprt<<"M3DVTj 3V"<<vx3.ID<<" score "<<score<<" TjIDs";
1530  for(auto& tjID : v3TjIDs) myprt<<" T"<<std::to_string(tjID);
1531  }
1532 */
1533  SortEntry se;
1534  se.index = iv3;
1535  se.val = score;
1536  sortVec.push_back(se);
1537  } // vx3
1538  if(sortVec.empty()) return;
1539  if(sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(), valDecreasing);
1540 
1541  for(unsigned short ii = 0; ii < sortVec.size(); ++ii) {
1542  auto& vx3 = tjs.vtx3[sortVec[ii].index];
1543  float score = 0;
1544  std::vector<int> v3TjIDs = GetVtxTjIDs(tjs, vx3, score);
1545  if(prt) {
1546  mf::LogVerbatim myprt("TC");
1547  myprt<<"M3DVTj 3V"<<vx3.ID<<" score "<<score<<" Tjs";
1548  for(auto& tjID : v3TjIDs) myprt<<" T"<<tjID;
1549  }
1550  for(unsigned int ims = 0; ims < tjs.matchVec.size(); ++ims) {
1551  auto& ms = tjs.matchVec[ims];
1552  if(ms.Count == 0) continue;
1553  bool skipit = false;
1554  for(auto tjid : ms.TjIDs) {
1555  auto& tj = tjs.allTraj[tjid - 1];
1556  if(tj.AlgMod[kMat3D]) skipit = true;
1557  if(tj.AlgMod[kKilled]) skipit = true;
1558  }
1559  if(skipit) continue;
1560  std::vector<int> shared = SetIntersection(ms.TjIDs, v3TjIDs);
1561  if(shared.size() < 2) continue;
1562  if(prt) mf::LogVerbatim("TC")<<" ims "<<ims<<" shared size "<<shared.size();
1563  PFPStruct pfp = CreatePFP(tjs, tpcid);
1564  pfp.TjIDs = ms.TjIDs;
1565  pfp.Vx3ID[0] = vx3.ID;
1566  // note that the ms position is the average position of all 3D matched Tp3s at this point.
1567  // It is not the start position. This will be determined in DefinePFP.
1568  pfp.XYZ[0] = ms.Pos;
1569  pfp.Dir[0] = ms.Dir;
1570  pfp.MatchVecIndex = ims;
1571  if(prt) mf::LogVerbatim("TC")<<"M3DVTj: pfp P"<<pfp.ID<<" 3V"<<vx3.ID<<" ims "<<ims;
1572  // Set the PDGCode so DefinePFP can ignore incompatible matches
1573  pfp.PDGCode = PDGCodeVote(tjs, pfp.TjIDs, prt);
1574  // make a copy of the TjIDs to test for changes
1575  auto saveTjIDs = pfp.TjIDs;
1576  if(!DefinePFP("M3DVTj1", tjs, pfp, prt)) continue;
1577  // separation distance (cm) for kink detection.
1578  double sep = 1;
1579  bool didSplit = Split3DKink(tjs, pfp, sep, prt);
1580  if(prt) PrintPFP("M3D", tjs, pfp, true);
1581  if(!didSplit && shared.size() != ms.TjIDs.size()) {
1582  // Try to repair the PFParticle by merging the Tj that was in the match list but
1583  // wasn't attached to the vertex. Hopefully there aren't more than one...
1584  auto tjNotInVx = SetDifference(ms.TjIDs, shared);
1585  }
1586  AnalyzePFP(tjs, pfp, prt);
1587  if(!StorePFP(tjs, pfp)) continue;
1588  if(pfp.TjIDs != saveTjIDs) {
1589  // v3TjIDs is wrong if Tjs were merged so re-make it.
1590  auto tmp = GetVtxTjIDs(tjs, vx3, score);
1591  v3TjIDs.clear();
1592  // then re-build it
1593  for(auto tjid : tmp) {
1594  auto& tj = tjs.allTraj[tjid - 1];
1595  if(!tj.AlgMod[kMat3D]) v3TjIDs.push_back(tjid);
1596  } // tjid
1597  if(v3TjIDs.size() < 2) break;
1598  } // pfp.TjIDs != saveTjIDs
1599  ms.Count = 0;
1600  // clobber MatchStructs that use the Tjs in this pfp
1601  for(auto& allms : tjs.matchVec) {
1602  auto mfpfp = SetIntersection(allms.TjIDs, pfp.TjIDs);
1603  if(!mfpfp.empty()) allms.Count = 0;
1604  } // allms
1605  auto leftover = SetDifference(v3TjIDs, pfp.TjIDs);
1606  if(prt) {
1607  mf::LogVerbatim myprt("TC");
1608  myprt<<" leftover";
1609  for(auto tjid : leftover) myprt<<" T"<<tjid;
1610  }
1611  if(leftover.size() < 2) break;
1612  // keep looking using the leftovers
1613  v3TjIDs = leftover;
1614  } // ims
1615  if(v3TjIDs.size() > 1 && v3TjIDs.size() <= tjs.NumPlanes) {
1616  // a last-ditch attempt
1617  PFPStruct pfp = CreatePFP(tjs, tpcid);
1618  // put the available leftovers in
1619  for(auto& tjid : v3TjIDs) {
1620  auto& tj = tjs.allTraj[tjid - 1];
1621  if(tj.AlgMod[kMat3D]) continue;
1622  if(tj.AlgMod[kKilled]) continue;
1623  pfp.TjIDs.push_back(tjid);
1624  } // tjid
1625  if(pfp.TjIDs.size() < 2) continue;
1626  pfp.Vx3ID[0] = vx3.ID;
1627  if(!DefinePFP("M3DVTj2", tjs, pfp, prt)) continue;
1628  Split3DKink(tjs, pfp, 1, prt);
1629  AnalyzePFP(tjs, pfp, prt);
1630  if(prt) PrintPFP("left", tjs, pfp, true);
1631  if(!StorePFP(tjs, pfp)) continue;
1632  }
1633  } // ims
1634  } // Match3DVtxTjs
bool valDecreasing(SortEntry c1, SortEntry c2)
Definition: TCVertex.cxx:10
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
unsigned int index
Definition: TCShower.cxx:5
bool AnalyzePFP(TjStuff &tjs, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:2339
bool DefinePFP(std::string inFcnLabel, TjStuff &tjs, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:2159
Float_t tmp
Definition: plot.C:37
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:214
int PDGCodeVote(TjStuff &tjs, std::vector< int > &tjIDs, bool prt)
Definition: Utils.cxx:267
std::vector< int > GetVtxTjIDs(const TjStuff &tjs, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:3039
float val
Definition: Utils.cxx:8
PFPStruct CreatePFP(const TjStuff &tjs, const geo::TPCID &tpcid)
Definition: PFPUtils.cxx:1943
bool Split3DKink(TjStuff &tjs, PFPStruct &pfp, double sep, bool prt)
Definition: PFPUtils.cxx:1782
std::vector< T > SetDifference(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:236
void PrintPFP(std::string someText, const TjStuff &tjs, const PFPStruct &pfp, bool printHeader)
Definition: Utils.cxx:4619
bool StorePFP(TjStuff &tjs, PFPStruct &pfp)
Definition: PFPUtils.cxx:2660
unsigned short tca::MatchVecIndex ( const TjStuff tjs,
int  tjID 
)

Definition at line 1058 of file Utils.cxx.

References tca::TjStuff::matchVec.

1059  {
1060  // returns the index into the tjs.matchVec vector of the first 3D match that
1061  // includes tjID
1062  for(unsigned int ims = 0; ims < tjs.matchVec.size(); ++ims) {
1063  const auto& ms = tjs.matchVec[ims];
1064  if(std::find(ms.TjIDs.begin(), ms.TjIDs.end(), tjID) != ms.TjIDs.end()) return ims;
1065  } // indx
1066  return USHRT_MAX;
1067  } // MatchVecIndex
float tca::MaxChargeAsymmetry ( TjStuff tjs,
std::vector< int > &  tjIDs 
)

Definition at line 235 of file Utils.cxx.

References tca::TjStuff::allTraj, DecodeCTP(), tca::TjStuff::NumPlanes, geo::PlaneID::Plane, and UpdateTjChgProperties().

236  {
237  // calculates the maximum charge asymmetry in all planes using the supplied list of Tjs
238  if(tjIDs.size() < 2) return 1;
239  std::vector<float> plnchg(tjs.NumPlanes);
240  for(auto tjid : tjIDs) {
241  if(tjid <= 0 || tjid > (int)tjs.allTraj.size()) return 1;
242  auto& tj = tjs.allTraj[tjid - 1];
243  if(tj.TotChg == 0) UpdateTjChgProperties("MCA", tjs, tj, false);
244  unsigned short plane = DecodeCTP(tj.CTP).Plane;
245  plnchg[plane] += tj.TotChg;
246  } // tjid
247  float aveChg = 0;
248  float cnt = 0;
249  for(unsigned short plane = 0; plane < tjs.NumPlanes; ++plane) {
250  if(plnchg[plane] == 0) continue;
251  aveChg += plnchg[plane];
252  ++cnt;
253  } // plane
254  if(cnt < 2) return 1;
255  aveChg /= cnt;
256  float maxAsym = 0;
257  for(unsigned short plane = 0; plane < tjs.NumPlanes; ++plane) {
258  // ignore zeros
259  if(plnchg[plane] == 0) continue;
260  float asym = std::abs(plnchg[plane] - aveChg) / (plnchg[plane] + aveChg);
261  if(asym > maxAsym) maxAsym = asym;
262  } // plane
263  return maxAsym;
264  } // MaxChargeAsymmetry
void UpdateTjChgProperties(std::string inFcnLabel, TjStuff &tjs, Trajectory &tj, bool prt)
Definition: Utils.cxx:3118
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
float tca::MaxHitDelta ( TjStuff tjs,
Trajectory tj 
)

Definition at line 2649 of file Utils.cxx.

References PointTrajDOCA(), and tca::Trajectory::Pts.

Referenced by tca::TrajClusterAlg::CheckHiMultUnusedHits(), and tca::TrajClusterAlg::FillGaps().

2650  {
2651  float delta, md = 0;
2652  unsigned short ii;
2653  unsigned int iht;
2654  for(auto& tp : tj.Pts) {
2655  for(ii = 0; ii < tp.Hits.size(); ++ii) {
2656  if(!tp.UseHit[ii]) continue;
2657  iht = tp.Hits[ii];
2658  delta = PointTrajDOCA(tjs, iht, tp);
2659  if(delta > md) md = delta;
2660  } // ii
2661  } // pts
2662  return md;
2663  } // MaxHitDelta
float PointTrajDOCA(TjStuff const &tjs, float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2147
float tca::MaxTjLen ( TjStuff const &  tjs,
std::vector< int > &  tjIDs 
)

Definition at line 2189 of file Utils.cxx.

References tca::TjStuff::allTraj, and PosSep2().

Referenced by DefinePFP(), and FindPFParticles().

2190  {
2191  // returns the length of the longest Tj in the supplied list
2192  if(tjIDs.empty()) return 0;
2193  float maxLen = 0;
2194  for(auto tjid : tjIDs) {
2195  if(tjid < 1 || tjid > (int)tjs.allTraj.size()) continue;
2196  auto& tj = tjs.allTraj[tjid - 1];
2197  float sep2 = PosSep2(tj.Pts[tj.EndPt[0]].Pos, tj.Pts[tj.EndPt[1]].Pos);
2198  if(sep2 > maxLen) maxLen = sep2;
2199  } // tj
2200  return sqrt(maxLen);
2201  } // MaxTjLen
float PosSep2(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2226
short tca::MCSMom ( const TjStuff tjs,
const std::vector< int > &  tjIDs 
)

Definition at line 2837 of file Utils.cxx.

References tca::TjStuff::allTraj.

Referenced by tca::TrajClusterAlg::CheckTraj(), DefinePFP(), DotProd(), tca::TrajClusterAlg::FillGaps(), FindCots(), FindHammerVertices2(), FindParent(), FindPFParticles(), tca::TrajClusterAlg::FindSoftKink(), tca::TrajClusterAlg::GottaKink(), tca::TrajClusterAlg::IsGhost(), MergeNearby2DShowers(), MergePFPTjs(), MergeSubShowersTj(), tca::TruthMatcher::StudyElectrons(), tca::TruthMatcher::StudyShowerParents(), and tca::TrajClusterAlg::UpdateTraj().

2838  {
2839  // Find the average MCSMom of the trajectories
2840  if(tjIDs.empty()) return 0;
2841  float summ = 0;
2842  float suml = 0;
2843  for(auto tjid : tjIDs) {
2844  auto& tj = tjs.allTraj[tjid - 1];
2845  float npts = tj.EndPt[1] - tj.EndPt[0] + 1;
2846  summ += npts * tj.MCSMom;
2847  suml += npts;
2848  } // tjid
2849  return (short)(summ / suml);
2850  } // MCSMom
short tca::MCSMom ( TjStuff tjs,
Trajectory tj 
)

Definition at line 2853 of file Utils.cxx.

References tca::Trajectory::EndPt, and MCSMom().

2854  {
2855  return MCSMom(tjs, tj, tj.EndPt[0], tj.EndPt[1]);
2856  } // MCSMom
short MCSMom(TjStuff &tjs, Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:2859
short tca::MCSMom ( TjStuff tjs,
Trajectory tj,
unsigned short  firstPt,
unsigned short  lastPt 
)

Definition at line 2859 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::EndPt, kJunkTj, MCSThetaRMS(), NearestPtWithChg(), NumPtsWithCharge(), tca::Trajectory::Pts, and TrajPointSeparation().

Referenced by MCSMom(), PrintPFP(), and SetPDGCode().

2860  {
2861  // Estimate the trajectory momentum using Multiple Coulomb Scattering ala PDG RPP
2862 
2863  if(firstPt == lastPt) return 0;
2864  if(firstPt > lastPt) std::swap(firstPt, lastPt);
2865 
2866  firstPt = NearestPtWithChg(tjs, tj, firstPt);
2867  lastPt = NearestPtWithChg(tjs, tj, lastPt);
2868  if(firstPt >= lastPt) return 0;
2869 
2870  if(firstPt < tj.EndPt[0]) return 0;
2871  if(lastPt > tj.EndPt[1]) return 0;
2872  // Can't do this with only 2 points
2873  if(NumPtsWithCharge(tjs, tj, false, firstPt, lastPt) < 3) return 0;
2874  // Ignore junk Tjs
2875  if(tj.AlgMod[kJunkTj]) return 0;
2876 
2877  double tjLen = TrajPointSeparation(tj.Pts[firstPt], tj.Pts[lastPt]);
2878  if(tjLen < 1) return 0;
2879  // mom calculated in MeV
2880  double thetaRMS = MCSThetaRMS(tjs, tj, firstPt, lastPt);
2881  if(thetaRMS < 0.001) return 999;
2882  double mom = 13.8 * sqrt(tjLen / 14) / thetaRMS;
2883  if(mom > 999) mom = 999;
2884  return (short)mom;
2885  } // MCSMom
unsigned short NearestPtWithChg(TjStuff &tjs, Trajectory &tj, unsigned short thePt)
Definition: Utils.cxx:2889
float TrajPointSeparation(TrajPoint &tp1, TrajPoint &tp2)
Definition: Utils.cxx:2235
unsigned short NumPtsWithCharge(const TjStuff &tjs, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:1746
void swap(art::HLTGlobalStatus &lhs, art::HLTGlobalStatus &rhs)
double MCSThetaRMS(TjStuff &tjs, Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:2921
float tca::MCSThetaRMS ( TjStuff tjs,
Trajectory tj 
)

Definition at line 2907 of file Utils.cxx.

References tca::Trajectory::EndPt, MCSThetaRMS(), tca::Trajectory::Pts, and TrajPointSeparation().

Referenced by DotProd(), tca::TrajClusterAlg::EndMerge(), and tca::TrajClusterAlg::GottaKink().

2908  {
2909  // This returns the MCS scattering angle expected for one WSE unit of travel along the trajectory.
2910  // It is used to define kink and vertex cuts. This should probably be named something different to
2911  // prevent confusion
2912 
2913  float tps = TrajPointSeparation(tj.Pts[tj.EndPt[0]], tj.Pts[tj.EndPt[1]]);
2914  if(tps < 1) return 1;
2915 
2916  return MCSThetaRMS(tjs, tj, tj.EndPt[0], tj.EndPt[1]) / sqrt(tps);
2917 
2918  } // MCSThetaRMS
float TrajPointSeparation(TrajPoint &tp1, TrajPoint &tp2)
Definition: Utils.cxx:2235
double MCSThetaRMS(TjStuff &tjs, Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:2921
double tca::MCSThetaRMS ( TjStuff tjs,
Trajectory tj,
unsigned short  firstPt,
unsigned short  lastPt 
)

Definition at line 2921 of file Utils.cxx.

References tca::Trajectory::EndPt, tca::Trajectory::MCSMom, NearestPtWithChg(), tca::Trajectory::Pts, TjDeltaRMS(), and TrajPointSeparation().

Referenced by MCSMom(), and MCSThetaRMS().

2922  {
2923  // This returns the MCS scattering angle expected for the length of the trajectory
2924  // spanned by firstPt to lastPt. It is used primarily to calculate MCSMom
2925 
2926  if(firstPt < tj.EndPt[0]) return 1;
2927  if(lastPt > tj.EndPt[1]) return 1;
2928 
2929  firstPt = NearestPtWithChg(tjs, tj, firstPt);
2930  lastPt = NearestPtWithChg(tjs, tj, lastPt);
2931  if(firstPt >= lastPt) return 1;
2932 
2933  double sigmaS;
2934  unsigned short cnt;
2935  TjDeltaRMS(tjs, tj, firstPt, lastPt, sigmaS, cnt);
2936  if(sigmaS < 0) return 1;
2937  // require that cnt is a significant fraction of the total number of charged points
2938  // so that we don't get erroneously high MCSMom when there are large gaps.
2939  // This is the number of points expected in the count if there are no gaps
2940  unsigned short numPts = lastPt - firstPt - 1;
2941  // return the previously calculated value of MCSMom
2942  if(numPts > 5 && cnt < 0.7 * numPts) return tj.MCSMom;
2943  double tjLen = TrajPointSeparation(tj.Pts[firstPt], tj.Pts[lastPt]);
2944  if(tjLen < 1) return 1;
2945  // Theta_o = 4 * sqrt(3) * sigmaS / path
2946  return (6.8 * sigmaS / tjLen);
2947 
2948  } // MCSThetaRMS
unsigned short NearestPtWithChg(TjStuff &tjs, Trajectory &tj, unsigned short thePt)
Definition: Utils.cxx:2889
float TrajPointSeparation(TrajPoint &tp1, TrajPoint &tp2)
Definition: Utils.cxx:2235
void TjDeltaRMS(TjStuff &tjs, Trajectory &tj, unsigned short firstPt, unsigned short lastPt, double &rms, unsigned short &cnt)
Definition: Utils.cxx:2951
bool tca::MergeAndStore ( TjStuff tjs,
unsigned int  itj1,
unsigned int  itj2,
bool  doPrt 
)

Not allowed

Definition at line 3896 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::TjStuff::allTraj, tca::Trajectory::EndPt, GetPFPIndex(), HasDuplicateHits(), tca::Trajectory::ID, kBragg, kDeltaRay, kKilled, kMichel, kShowerTj, MakeTrajectoryObsolete(), MakeVertexObsolete(), MergeShowerTjsAndStore(), tca::Trajectory::ParentID, PosSep2(), PrintPos(), PrintTrajectory(), tca::Trajectory::Pts, ReverseTraj(), SetEndPoints(), SetPDGCode(), tca::Trajectory::StepDir, tca::Trajectory::StopFlag, StoreTraj(), TrajPointTrajDOCA(), UpdateMatchStructs(), tca::TjStuff::vtx, tca::Trajectory::VtxID, and tca::Trajectory::WorkID.

Referenced by ChkVxTjs(), DotProd(), tca::TrajClusterAlg::EndMerge(), and MergeTjIntoPFP().

3897  {
3898  // Merge the two trajectories in allTraj and store them. Returns true if it was successfull.
3899  // Merging is done between the end (end = 1) of tj1 and the beginning (end = 0) of tj2. This function preserves the
3900  // AlgMod state of itj1.
3901  // The itj1 -> itj2 merge order is reversed if end1 of itj2 is closer to end0 of itj1
3902 
3903  if(itj1 > tjs.allTraj.size() - 1) return false;
3904  if(itj2 > tjs.allTraj.size() - 1) return false;
3905  if(tjs.allTraj[itj1].AlgMod[kKilled] || tjs.allTraj[itj2].AlgMod[kKilled]) return false;
3906 
3907  // Merging shower Tjs requires merging the showers as well.
3908  if(tjs.allTraj[itj1].AlgMod[kShowerTj] || tjs.allTraj[itj2].AlgMod[kShowerTj]) return MergeShowerTjsAndStore(tjs, itj1, itj2, doPrt);
3909 
3910  // Ensure that the order of 3D-matched Tjs is consistent with the convention that
3911  unsigned short pfp1 = GetPFPIndex(tjs, tjs.allTraj[itj1].ID);
3912  unsigned short pfp2 = GetPFPIndex(tjs, tjs.allTraj[itj2].ID);
3913  if(pfp1 != USHRT_MAX || pfp2 != USHRT_MAX) {
3914  if(pfp1 != USHRT_MAX && pfp2 != USHRT_MAX) {
3915 // std::cout<<"MAS: Both tjs are used in a PFParticle. Need PFParticle merging code to do this. pfps size "<<tjs.pfps.size()<<"\n";
3916  return false;
3917  }
3918  // Swap so that the order of tj1 is preserved. Tj2 may be reversed to be consistent
3919  if(pfp1 == USHRT_MAX) std::swap(itj1, itj2);
3920  } // one or both used in a PFParticle
3921 
3922  // make copies so they can be trimmed as needed
3923  Trajectory tj1 = tjs.allTraj[itj1];
3924  Trajectory tj2 = tjs.allTraj[itj2];
3925 
3926  // ensure that these are in the same step order
3927  if(tj2.StepDir != tj1.StepDir) ReverseTraj(tjs, tj2);
3928 
3929  Point2_t tp1e0 = tj1.Pts[tj1.EndPt[0]].Pos;
3930  Point2_t tp1e1 = tj1.Pts[tj1.EndPt[1]].Pos;
3931  Point2_t tp2e0 = tj2.Pts[tj2.EndPt[0]].Pos;
3932  Point2_t tp2e1 = tj2.Pts[tj2.EndPt[1]].Pos;
3933 
3934  if(doPrt) {
3935  mf::LogVerbatim("TC")<<"MergeAndStore: tj1 T"<<tj1.ID<<" tj2 T"<<tj2.ID<<" at merge points "<<PrintPos(tjs, tp1e1)<<" "<<PrintPos(tjs, tp2e0);
3936  }
3937 
3938  // swap the order so that abs(tj1end1 - tj2end0) is less than abs(tj2end1 - tj1end0)
3939  if(PosSep2(tp1e1, tp2e0) > PosSep2(tp2e1, tp1e0)) {
3940  std::swap(tj1, tj2);
3941  std::swap(tp1e0, tp2e0);
3942  std::swap(tp1e1, tp2e1);
3943  if(doPrt) mf::LogVerbatim("TC")<<" swapped the order. Merge points "<<PrintPos(tjs, tp1e1)<<" "<<PrintPos(tjs, tp2e0);
3944  }
3945 
3946  // Here is what we are looking for, where - indicates a TP with charge.
3947  // Note that this graphic is in the stepping direction (+1 = +wire direction)
3948  // tj1: 0------------1
3949  // tj2: 0-----------1
3950  // Another possibility with overlap
3951  // tj1: 0-------------1
3952  // tj2: 0--------------1
3953 
3954  if(tj1.StepDir > 1) {
3955  // Not allowed
3956  // tj1: 0---------------------------1
3957  // tj2: 0------1
3958  if(tp2e0[0] > tp1e0[0] && tp2e1[0] < tp1e1[0]) return false;
3960  // tj1: 0------1
3961  // tj2: 0---------------------------1
3962  if(tp1e0[0] > tp2e0[0] && tp1e1[0] < tp2e1[0]) return false;
3963  } else {
3964  // same as above but with ends reversed
3965  if(tp2e1[0] > tp1e1[0] && tp2e0[0] < tp1e0[0]) return false;
3966  if(tp1e1[0] > tp2e1[0] && tp1e0[0] < tp2e0[0]) return false;
3967  }
3968 
3969  if(tj1.VtxID[1] > 0 && tj2.VtxID[0] == tj1.VtxID[1]) {
3970  auto& vx = tjs.vtx[tj1.VtxID[1] - 1];
3971  if(!MakeVertexObsolete(tjs, vx, false)) {
3972  if(doPrt) mf::LogVerbatim("TC")<<"MergeAndStore: Found a good vertex between Tjs "<<tj1.VtxID[1]<<" No merging";
3973  return false;
3974  }
3975  }
3976 
3977  if(tj1.StopFlag[1][kBragg]) {
3978  if(doPrt) mf::LogVerbatim("TC")<<"MergeAndStore: You are merging the end of trajectory T"<<tj1.ID<<" with a Bragg peak. Not merging\n";
3979  return false;
3980  }
3981 
3982  // remove any points at the end of tj1 that don't have used hits
3983  tj1.Pts.resize(tj1.EndPt[1] + 1);
3984 
3985  // determine if they overlap by finding the point on tj2 that is closest
3986  // to the end point of tj1.
3987  TrajPoint& endtj1TP = tj1.Pts[tj1.EndPt[1]];
3988  // Set minSep large so that dead wire regions are accounted for
3989  float minSep = 1000;
3990  unsigned short tj2ClosePt = 0;
3991  // Note that TrajPointTrajDOCA only considers TPs that have charge
3992  TrajPointTrajDOCA(tjs, endtj1TP, tj2, tj2ClosePt, minSep);
3993  if(doPrt) mf::LogVerbatim("TC")<<" Merge point tj1 "<<PrintPos(tjs, endtj1TP)<<" tj2ClosePt "<<tj2ClosePt<<" Pos "<<PrintPos(tjs, tj2.Pts[tj2ClosePt]);
3994  // check for full overlap
3995  if(tj2ClosePt > tj2.EndPt[1]) return false;
3996 
3997  // The approach is to append tj2 to tj1, store tj1 as a new trajectory,
3998  // and re-assign all hits to the new trajectory
3999 
4000  // First ensure that any hit will appear only once in the merged trajectory in the overlap region
4001  // whether it is used or unused. The point on tj2 where the merge will begin, tj2ClosePt, will be
4002  // increased until this condition is met.
4003  // Make a temporary vector of tj1 hits in the end points for simpler searching
4004  std::vector<unsigned int> tj1Hits;
4005  for(unsigned short ii = 0; ii < tj1.Pts.size(); ++ii) {
4006  // only go back a few points in tj1
4007  if(ii > 10) break;
4008  unsigned short ipt = tj1.Pts.size() - 1 - ii;
4009  tj1Hits.insert(tj1Hits.end(), tj1.Pts[ipt].Hits.begin(), tj1.Pts[ipt].Hits.end());
4010  if(ipt == 0) break;
4011  } // ii
4012 
4013  bool bumpedPt = true;
4014  while(bumpedPt) {
4015  bumpedPt = false;
4016  for(unsigned short ii = 0; ii < tj2.Pts[tj2ClosePt].Hits.size(); ++ii) {
4017  unsigned int iht = tj2.Pts[tj2ClosePt].Hits[ii];
4018  if(std::find(tj1Hits.begin(), tj1Hits.end(), iht) != tj1Hits.end()) bumpedPt = true;
4019  } // ii
4020  if(bumpedPt && tj2ClosePt < tj2.EndPt[1]) {
4021  ++tj2ClosePt;
4022  } else {
4023  break;
4024  }
4025  } // bumpedPt
4026  if(doPrt) mf::LogVerbatim("TC")<<" revised tj2ClosePt "<<tj2ClosePt;
4027  // append tj2 hits to tj1
4028 
4029  tj1.Pts.insert(tj1.Pts.end(), tj2.Pts.begin() + tj2ClosePt, tj2.Pts.end());
4030  // re-define the end points
4031  SetEndPoints(tjs, tj1);
4032  tj1.StopFlag[1] = tj2.StopFlag[1];
4033 
4034  // A more exhaustive check that hits only appear once
4035  if(HasDuplicateHits(tjs, tj1, doPrt)) {
4036  if(doPrt) {
4037  mf::LogVerbatim("TC")<<"MergeAndStore found duplicate hits. Coding error";
4038  PrintTrajectory("MAS", tjs, tj1, USHRT_MAX);
4039  PrintTrajectory("tj1", tjs, tjs.allTraj[itj1], USHRT_MAX);
4040  PrintTrajectory("tj2", tjs, tjs.allTraj[itj2], USHRT_MAX);
4041  }
4042  return false;
4043  }
4044  if(tj2.VtxID[1] > 0) {
4045  // move the end vertex of tj2 to the end of tj1
4046  tj1.VtxID[1] = tj2.VtxID[1];
4047  }
4048  // Transfer some of the AlgMod bits
4049  if(tj2.AlgMod[kMichel]) tj1.AlgMod[kMichel] = true;
4050  if(tj2.AlgMod[kDeltaRay]) {
4051  tj1.AlgMod[kDeltaRay] = true;
4052  tj1.ParentID = tj2.ParentID;
4053  }
4054  // keep track of the IDs before they are clobbered
4055  int tj1ID = tj1.ID;
4056  int tj2ID = tj2.ID;
4057  // kill the original trajectories
4058  MakeTrajectoryObsolete(tjs, itj1);
4059  MakeTrajectoryObsolete(tjs, itj2);
4060  // Do this so that StoreTraj keeps the correct WorkID (of itj1)
4061  tj1.ID = tj1.WorkID;
4062  SetPDGCode(tjs, tj1);
4063  if(!StoreTraj(tjs, tj1)) return false;
4064  int newTjID = tjs.allTraj.size();
4065  // Use the ParentID to trace which new Tj is superseding the merged ones
4066  tj1.ParentID = newTjID;
4067  tj2.ParentID = newTjID;
4068  // update match structs if they exist
4069  UpdateMatchStructs(tjs, tj1.ID, newTjID);
4070  UpdateMatchStructs(tjs, tj2.ID, newTjID);
4071  if(doPrt) mf::LogVerbatim("TC")<<" MAS success. New Tj T"<<newTjID;
4072  // Transfer the ParentIDs of any other Tjs that refer to Tj1 and Tj2 to the new Tj
4073  for(auto& tj : tjs.allTraj) if(tj.ParentID == tj1ID || tj.ParentID == tj2ID) tj.ParentID = newTjID;
4074 
4075  return true;
4076  } // MergeAndStore
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void PrintTrajectory(std::string someText, const TjStuff &tjs, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:4488
bool HasDuplicateHits(TjStuff const &tjs, Trajectory const &tj, bool prt)
Definition: Utils.cxx:2335
void ReverseTraj(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:2666
bool MakeVertexObsolete(TjStuff &tjs, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:2917
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
void UpdateMatchStructs(TjStuff &tjs, int oldTj, int newTj)
Definition: PFPUtils.cxx:16
float PosSep2(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2226
void swap(art::HLTGlobalStatus &lhs, art::HLTGlobalStatus &rhs)
bool MergeShowerTjsAndStore(TjStuff &tjs, unsigned short istj, unsigned short jstj, bool prt)
Definition: TCShower.cxx:3128
std::string PrintPos(const TjStuff &tjs, const Point2_t &pos)
Definition: Utils.cxx:4744
void SetEndPoints(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:2788
unsigned short GetPFPIndex(const TjStuff &tjs, int tjID)
Definition: Utils.cxx:1045
void MakeTrajectoryObsolete(TjStuff &tjs, unsigned int itj)
Definition: Utils.cxx:1797
bool StoreTraj(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:1095
void TrajPointTrajDOCA(TjStuff &tjs, TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
Definition: Utils.cxx:2026
void SetPDGCode(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:3704
void tca::MergeGhostTjs ( TjStuff tjs,
CTP_t  inCTP 
)

Definition at line 1830 of file Utils.cxx.

References tca::TjStuff::allTraj, tca::TjStuff::fHits, kAllHits, kKilled, kMrgGhost, PutTrajHitsInVector(), and tca::TjStuff::UseAlg.

1831  {
1832  // Merges short Tjs that share many hits with a longer Tj
1833  if(!tjs.UseAlg[kMrgGhost]) return;
1834 
1835  for(auto& shortTj : tjs.allTraj) {
1836  if(shortTj.AlgMod[kKilled]) continue;
1837  if(shortTj.CTP != inCTP) continue;
1838  unsigned short spts = shortTj.EndPt[1] - shortTj.EndPt[0];
1839  if(spts > 20) continue;
1840  // ignore delta rays
1841  if(shortTj.PDGCode == 11) continue;
1842  // ignore InShower Tjs
1843  if(shortTj.SSID > 0) continue;
1844  auto tjhits = PutTrajHitsInVector(shortTj, kAllHits);
1845  if(tjhits.empty()) continue;
1846  std::vector<int> tids;
1847  std::vector<unsigned short> tcnt;
1848  for(auto iht : tjhits) {
1849  auto& hit = tjs.fHits[iht];
1850  if(hit.InTraj <= 0) continue;
1851  if((unsigned int)hit.InTraj > tjs.allTraj.size()) continue;
1852  if(hit.InTraj == shortTj.ID) continue;
1853  unsigned short indx = 0;
1854  for(indx = 0; indx < tids.size(); ++indx) if(hit.InTraj == tids[indx]) break;
1855  if(indx == tids.size()) {
1856  tids.push_back(hit.InTraj);
1857  tcnt.push_back(1);
1858  } else {
1859  ++tcnt[indx];
1860  }
1861  } // iht
1862  if(tids.empty()) continue;
1863  // find the max count for Tjs that are longer than this one
1864  unsigned short maxcnt = 0;
1865  for(unsigned short indx = 0; indx < tids.size(); ++indx) {
1866  if(tcnt[indx] > maxcnt) {
1867  auto& ltj = tjs.allTraj[tids[indx] - 1];
1868  unsigned short lpts = ltj.EndPt[1] - ltj.EndPt[0];
1869  if(lpts < spts) continue;
1870  maxcnt = tcnt[indx];
1871  }
1872  } // indx
1873  float hitFrac = (float)maxcnt / (float)tjhits.size();
1874  if(hitFrac < 0.1) continue;
1875  } // shortTj
1876  } // MergeGhostTjs
std::vector< unsigned int > PutTrajHitsInVector(Trajectory const &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2283
Detector simulation of raw signals on wires.
void tca::MergeNearby2DShowers ( std::string  inFcnLabel,
TjStuff tjs,
const CTP_t inCTP,
bool  prt 
)

Definition at line 2443 of file TCShower.cxx.

References AddTj(), tca::Trajectory::AlgMod, tca::TjStuff::allTraj, ChkAssns(), tca::TjStuff::cots, tca::ShowerStruct::CTP, DontCluster(), GetAssns(), tca::ShowerStruct::ID, kMat3D, kMergeNrShowers, MCSMom(), MergeShowersAndStore(), tca::ShowerStruct::NearTjIDs, tca::TjStuff::pfps, SetIntersection(), tca::ShowerStruct::ShowerTjID, ss, tca::ShowerStruct::TjIDs, and tca::TjStuff::UseAlg.

Referenced by FindShowers3D().

2444  {
2445  if(!tjs.UseAlg[kMergeNrShowers]) return;
2446  if(tjs.cots.empty()) return;
2447 
2448  std::string fcnLabel = inFcnLabel + ".MNS";
2449 
2450  if(prt) {
2451  mf::LogVerbatim myprt("TC");
2452  myprt<<fcnLabel<<" list";
2453  for(auto& ss : tjs.cots) {
2454  if(ss.CTP != inCTP) continue;
2455  if(ss.ID == 0) continue;
2456  myprt<<" ss.ID "<<ss.ID<<" NearTjs";
2457  for(auto& id : ss.NearTjIDs) myprt<<" "<<id;
2458  myprt<<"\n";
2459  }
2460  } // prt
2461 
2462  bool keepMerging = true;
2463  while(keepMerging) {
2464  keepMerging = false;
2465  for(unsigned short ci1 = 0; ci1 < tjs.cots.size() - 1; ++ci1) {
2466  ShowerStruct& ss1 = tjs.cots[ci1];
2467  if(ss1.CTP != inCTP) continue;
2468  if(ss1.ID == 0) continue;
2469  if(ss1.TjIDs.empty()) continue;
2470  // put the inshower tjs and the nearby tjs into one list
2471  std::vector<int> ss1list = ss1.TjIDs;
2472  ss1list.insert(ss1list.end(), ss1.NearTjIDs.begin(), ss1.NearTjIDs.end());
2473  for(unsigned short ci2 = ci1 + 1; ci2 < tjs.cots.size(); ++ci2) {
2474  ShowerStruct& ss2 = tjs.cots[ci2];
2475  if(ss2.CTP != inCTP) continue;
2476  if(ss2.ID == 0) continue;
2477  if(ss2.TjIDs.empty()) continue;
2478  if(DontCluster(tjs, ss1.TjIDs, ss2.TjIDs)) continue;
2479  std::vector<int> ss2list = ss2.TjIDs;
2480  ss2list.insert(ss2list.end(), ss2.NearTjIDs.begin(), ss2.NearTjIDs.end());
2481  std::vector<int> shared = SetIntersection(ss1list, ss2list);
2482  if(shared.empty()) continue;
2483  if(prt) {
2484  mf::LogVerbatim myprt("TC");
2485  myprt<<fcnLabel<<" Merge 2S"<<ss2.ID<<" into 2S"<<ss1.ID<<"? shared nearby:";
2486  for(auto tjid : shared) myprt<<" T"<<tjid;
2487  } // prt
2488  // add the shared Tjs to ss1 if they meet the requirements
2489  bool doMerge = false;
2490  for(auto& tjID : shared) {
2491  bool inSS1 = (std::find(ss1.TjIDs.begin(), ss1.TjIDs.end(), tjID) != ss1.TjIDs.end());
2492  bool inSS2 = (std::find(ss2.TjIDs.begin(), ss2.TjIDs.end(), tjID) != ss2.TjIDs.end());
2493  if(inSS1 && !inSS2) doMerge = true;
2494  if(!inSS1 && inSS2) doMerge = true;
2495  // need to add it?
2496  if(inSS1 || inSS2) continue;
2497  auto& tj = tjs.allTraj[tjID - 1];
2498  // ignore long muons
2499  if(tj.PDGCode == 13 && tj.Pts.size() > 100 && tj.ChgRMS < 0.5) {
2500  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" T"<<tj.ID<<" looks like a muon. Don't add it";
2501  continue;
2502  }
2503  // see if it looks like a muon in 3D
2504  if(tj.AlgMod[kMat3D]) {
2505  auto TInP = GetAssns(tjs, "T", tj.ID, "P");
2506  if(!TInP.empty()) {
2507  auto& pfp = tjs.pfps[TInP[0] - 1];
2508  if(pfp.PDGCode == 13 && MCSMom(tjs, pfp.TjIDs) > 500) continue;
2509  } // TInP not empty
2510  } // 3D matched
2511  if(AddTj(fcnLabel, tjs, tjID, ss1, false, prt)) doMerge = true;
2512  } // tjID
2513  if(!doMerge) continue;
2514  if(MergeShowersAndStore(fcnLabel, tjs, ss1.ID, ss2.ID, prt)) {
2515  Trajectory& stj = tjs.allTraj[ss1.ShowerTjID - 1];
2516  stj.AlgMod[kMergeNrShowers] = true;
2517  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" success";
2518  keepMerging = true;
2519  break;
2520  }
2521  } // ci2
2522  } // ci1
2523  } // keepMerging
2524 
2525  ChkAssns(fcnLabel, tjs);
2526 
2527  } //MergeNearby2DShowers
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool AddTj(std::string inFcnLabel, TjStuff &tjs, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1624
bool MergeShowersAndStore(std::string inFcnLabel, TjStuff &tjs, int icotID, int jcotID, bool prt)
Definition: TCShower.cxx:3053
bool ChkAssns(std::string inFcnLabel, TjStuff &tjs)
Definition: TCShower.cxx:4625
Float_t ss
Definition: plot.C:23
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:214
bool DontCluster(const TjStuff &tjs, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3381
short MCSMom(const TjStuff &tjs, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2837
std::vector< int > GetAssns(const TjStuff &tjs, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4079
void tca::MergeOverlap ( std::string  inFcnLabel,
TjStuff tjs,
const CTP_t inCTP,
bool  prt 
)

Definition at line 2530 of file TCShower.cxx.

References tca::Trajectory::AlgMod, tca::TjStuff::allTraj, ChkAssns(), close(), tca::TjStuff::cots, DontCluster(), DotProd(), kMergeOverlap, MergeShowersAndStore(), PointInsideEnvelope(), PosSep(), PosSep2(), tca::TjStuff::ShowerTag, and tca::TjStuff::UseAlg.

Referenced by cluster::ClusterCrawlerAlg::ClusterLoop(), and FindShowers3D().

2531  {
2532  // Merge showers whose envelopes overlap each other
2533 
2534  /*
2535  # 0 Mode (<= 0 OFF, 1 = find showers before 3D match, 2 = find showers after 3D match)
2536  # 1 Max Tj MCSMom for a shower tag
2537  # 2 Max separation
2538  # 3 Min energy (MeV)
2539  # 4 rms width factor
2540  # 5 Min shower 1/2 width (WSE units)
2541  # 6 Min total Tj Pts
2542  # 7 Min Tjs
2543  # 8 max parent FOM
2544  # 9 max direction FOM
2545  # 10 max aspect ratio
2546  # 11 Debug in CTP (>10 debug cotID + 10)
2547  */
2548 
2549  if(tjs.ShowerTag[2] <= 0) return;
2550  if(!tjs.UseAlg[kMergeOverlap]) return;
2551  if(tjs.cots.empty()) return;
2552 
2553  std::string fcnLabel = inFcnLabel + ".MO";
2554 
2555  // Require that the maximum separation is about two radiation lengths
2556  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" checking using separation cut "<<tjs.ShowerTag[2];
2557 
2558  float sepCut2 = tjs.ShowerTag[2] * tjs.ShowerTag[2];
2559 
2560  // Iterate if a merge is done
2561  bool didMerge = true;
2562  while(didMerge) {
2563  didMerge = false;
2564  // See if the envelopes overlap
2565  for(unsigned short ict = 0; ict < tjs.cots.size() - 1; ++ict) {
2566  auto& iss = tjs.cots[ict];
2567  if(iss.ID == 0) continue;
2568  if(iss.TjIDs.empty()) continue;
2569  if(iss.CTP != inCTP) continue;
2570  for(unsigned short jct = ict + 1; jct < tjs.cots.size(); ++jct) {
2571  auto& jss = tjs.cots[jct];
2572  if(jss.ID == 0) continue;
2573  if(jss.TjIDs.empty()) continue;
2574  if(jss.CTP != iss.CTP) continue;
2575  if(DontCluster(tjs, iss.TjIDs, jss.TjIDs)) continue;
2576  bool doMerge = false;
2577  for(auto& ivx : iss.Envelope) {
2578  doMerge = PointInsideEnvelope(ivx, jss.Envelope);
2579  if(doMerge) break;
2580  } // ivx
2581  if(!doMerge) {
2582  for(auto& jvx : jss.Envelope) {
2583  doMerge = PointInsideEnvelope(jvx, iss.Envelope);
2584  if(doMerge) break;
2585  } // ivx
2586  }
2587  if(!doMerge) {
2588  // check proximity between the envelopes
2589  for(auto& ivx : iss.Envelope) {
2590  for(auto& jvx : jss.Envelope) {
2591  if(PosSep2(ivx, jvx) < sepCut2) {
2592  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Envelopes 2S"<<iss.ID<<" 2S"<<jss.ID<<" are close "<<PosSep(ivx, jvx)<<" cut "<<tjs.ShowerTag[2];
2593  doMerge = true;
2594  break;
2595  }
2596  } // jvx
2597  if(doMerge) break;
2598  } // ivx
2599  } // !domerge
2600  if(!doMerge) continue;
2601  // check the relative positions and angle differences. Determine which tps are the
2602  // closest. Don't merge if the closest points are at the shower start and the angle
2603  // difference is large
2604  unsigned short iClosePt = 0;
2605  unsigned short jClosePt = 0;
2606  float close = 1E6;
2607  auto& istj = tjs.allTraj[iss.ShowerTjID - 1];
2608  auto& jstj = tjs.allTraj[jss.ShowerTjID - 1];
2609  for(unsigned short ipt = 0; ipt < 3; ++ipt) {
2610  for(unsigned short jpt = 0; jpt < 3; ++jpt) {
2611  float sep = PosSep2(istj.Pts[ipt].Pos, jstj.Pts[jpt].Pos);
2612  if(sep < close) {
2613  close = sep;
2614  iClosePt = ipt;
2615  jClosePt = jpt;
2616  }
2617  } // jpt
2618  } // ipt
2619  float costh = DotProd(istj.Pts[0].Dir, jstj.Pts[0].Dir);
2620  if(iClosePt == 0 && jClosePt == 0 && costh < 0.955) {
2621  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" showers are close at the start points with costh "<<costh<<". Don't merge";
2622  continue;
2623  }
2624  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Merge "<<iss.ID<<" and "<<jss.ID;
2625  if(MergeShowersAndStore(fcnLabel, tjs, iss.ID, jss.ID, prt)) {
2626  Trajectory& stj = tjs.allTraj[iss.ShowerTjID - 1];
2627  stj.AlgMod[kMergeOverlap] = true;
2628  didMerge = true;
2629  break;
2630  } else {
2631  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Merge failed";
2632  }
2633  } // jct
2634  } // ict
2635  } // didMerge
2636 
2637  ChkAssns(fcnLabel, tjs);
2638 
2639  } // MergeOverlap
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MergeShowersAndStore(std::string inFcnLabel, TjStuff &tjs, int icotID, int jcotID, bool prt)
Definition: TCShower.cxx:3053
bool ChkAssns(std::string inFcnLabel, TjStuff &tjs)
Definition: TCShower.cxx:4625
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:2705
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1631
bool DontCluster(const TjStuff &tjs, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3381
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:60
in close()
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
bool tca::MergePFPTjs ( TjStuff tjs,
PFPStruct pfp,
bool  prt 
)

Definition at line 1174 of file PFPUtils.cxx.

References tca::Trajectory::AlgMod, tca::TjStuff::allTraj, geo::CryostatID::Cryostat, tca::Trajectory::CTP, DecodeCTP(), EncodeCTP(), evd::details::end(), tca::TjStuff::EventsProcessed, tca::TjStuff::geom, tca::Trajectory::ID, tca::PFPStruct::ID, kMat3DMerge, MakeTrajectoryObsolete(), MakeVertexObsolete(), tca::Trajectory::MCSMom, MCSMom(), geo::TPCGeo::Nplanes(), geo::PlaneID::Plane, PrintPFP(), tca::Trajectory::Pts, ReverseTraj(), SetEndPoints(), SetPDGCode(), tca::Trajectory::SSID, tca::Trajectory::StepDir, StoreTraj(), tca::PFPStruct::TjIDs, tca::PFPStruct::Tp3s, geo::TPCID::TPC, geo::GeometryCore::TPC(), tca::PFPStruct::TPCID, UpdateMatchStructs(), UpdateTp3s(), tca::TjStuff::vtx, and tca::Trajectory::VtxID.

Referenced by DefinePFP().

1175  {
1176  // Checks the list of Tjs in pfp.TjIDs and merges those that are in
1177  // the same plane. This function uses the ordering of Tps which should
1178  // have been sorted
1179  if(pfp.TjIDs.empty()) return false;
1180  if(pfp.Tp3s.empty()) return false;
1181 
1182  geo::TPCGeo const& TPC = tjs.geom->TPC(pfp.TPCID);
1183  unsigned short nplanes = TPC.Nplanes();
1184 
1185  // see if anything needs to be done
1186  std::vector<unsigned short> cntInPln(nplanes);
1187  bool itsOK = true;
1188  for(auto tjid : pfp.TjIDs) {
1189  auto& tj = tjs.allTraj[tjid - 1];
1190  unsigned short plane = DecodeCTP(tj.CTP).Plane;
1191  ++cntInPln[plane];
1192  if(cntInPln[plane] > 1) itsOK = false;
1193  }
1194  if(itsOK) return true;
1195 
1196  // vector of tj IDs that will replace pfp.TjIDs
1197  std::vector<int> newTjIDs;
1198 
1199  if(prt) {
1200  mf::LogVerbatim myprt("TC");
1201  myprt<<"MergePFPTjs: P"<<pfp.ID<<" in";
1202  for(auto tjid : pfp.TjIDs) myprt<<" T"<<tjid;
1203  }
1204 
1205  for(unsigned short plane = 0; plane < nplanes; ++plane) {
1206  CTP_t inCTP = EncodeCTP(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
1207  // save the TjIDs as unsigned short to match with Tj2Pts
1208  std::vector<unsigned short> tjids;
1209  for(auto tjid : pfp.TjIDs) if(tjs.allTraj[tjid - 1].CTP == inCTP) tjids.push_back((unsigned short)tjid);
1210  // Only one tj in this plane. No need to merge
1211  if(tjids.size() == 1) {
1212  newTjIDs.push_back((int)tjids[0]);
1213  continue;
1214  }
1215  // no tjs in this plane
1216  if(tjids.size() == 0) continue;
1217  // find the first ID and ipt of Tjs in this plane as they are
1218  // encountered while iterating through Tp3s. This scheme assumes that the Tp3s have
1219  // been sorted by distance from the start and the Tjs are broken end-to-end. This
1220  // information will be used to determine if Tjs need to be reversed before inserting
1221  // the points in to the merged trajectory
1222  // Tj ID first ipt
1223  std::vector<std::array<unsigned short, 2>> firstPts;
1224  for(unsigned short itp3 = 0; itp3 < pfp.Tp3s.size(); ++itp3) {
1225  auto& tp3 = pfp.Tp3s[itp3];
1226  for(auto& tj2pt : tp3.Tj2Pts) {
1227  unsigned short tjIndx = 0;
1228  for(tjIndx = 0; tjIndx < tjids.size(); ++tjIndx) if(tj2pt.id == tjids[tjIndx]) break;
1229  if(tjIndx == tjids.size()) continue;
1230  // look for this tj in firstPts
1231  unsigned short firstPtsIndx = 0;
1232  for(firstPtsIndx = 0; firstPtsIndx < firstPts.size(); ++firstPtsIndx) if(tj2pt.id == firstPts[firstPtsIndx][0]) break;
1233  if(firstPtsIndx == firstPts.size()) {
1234  // not found so add it
1235  std::array<unsigned short, 2> firstPt {{tj2pt.id, tj2pt.ipt}};
1236  firstPts.push_back(firstPt);
1237  }
1238  } // tj2pt
1239  } // itp3
1240  if(firstPts.empty()) continue;
1241  // create a new merged trajectory
1242  Trajectory mtj;
1243  // give it a bogus ID
1244  mtj.ID = -6666;
1245  mtj.CTP = inCTP;
1246  mtj.StepDir = 1;
1247  bool first = true;
1248  for(auto firstPt : firstPts) {
1249  // make a copy so we can reverse it and drop it if the merge fails
1250  auto tj = tjs.allTraj[firstPt[0] - 1];
1251  unsigned short midPt = 0.5 * (tj.EndPt[0] + tj.EndPt[1]);
1252  if(firstPt[1] > midPt) ReverseTraj(tjs, tj);
1253  // Transfer vertices to mtj
1254  if(first) {
1255  first = false;
1256  mtj.VtxID[0] = tj.VtxID[0];
1257  }
1258  mtj.VtxID[1] = tj.VtxID[1];
1259  // insert the points at the end
1260  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1261  auto& tp = tj.Pts[ipt];
1262  if(tp.Chg <= 0) continue;
1263  mtj.Pts.push_back(tp);
1264  }
1265  } // firstPt
1266  mtj.AlgMod[kMat3DMerge] = true;
1267  SetEndPoints(tjs, mtj);
1268  mtj.MCSMom = MCSMom(tjs, mtj);
1269  SetPDGCode(tjs, mtj);
1270  if(prt) {
1271  mf::LogVerbatim myprt("TC");
1272  myprt<<" P"<<pfp.ID<<" try to merge";
1273  for(auto tjid : tjids) {
1274  auto& tj = tjs.allTraj[tjid - 1];
1275  myprt<<" T"<<tjid<<" MCSMom "<<tj.MCSMom;
1276  }
1277  myprt<<" -> T"<<tjs.allTraj.size() + 1;
1278  myprt<<" MCSMom "<<mtj.MCSMom;
1279  }
1280  // kill the broken tjs and update the pfp TP3s
1281  for(auto tjid : tjids) {
1282  auto& tj = tjs.allTraj[tjid - 1];
1283  if(tj.SSID > 0) mtj.SSID = tj.SSID;
1284  MakeTrajectoryObsolete(tjs, tjid - 1);
1285  }
1286  // save the new one
1287  if(!StoreTraj(tjs, mtj)) {
1288  std::cout<<"MergePFPTjs: StoreTraj failed P"<<pfp.ID<<" EventsProcessed "<<tjs.EventsProcessed<<"\n";
1289  return false;
1290  }
1291  int newTjID = tjs.allTraj.size();
1292  newTjIDs.push_back(newTjID);
1293  // prepare to clobber vertices
1294  std::vector<unsigned short> vxlist;
1295  for(auto tjid : tjids) {
1296  // update the stored match struct and Tp3s
1297  UpdateMatchStructs(tjs, tjid, newTjID);
1298  // Update the Tp3s of this pfp
1299  UpdateTp3s(tjs, pfp, tjid, newTjID);
1300  auto& tj = tjs.allTraj[tjid - 1];
1301  for(unsigned short end = 0; end < 2; ++end) {
1302  if(tj.VtxID[end] == 0) continue;
1303  if(std::find(vxlist.begin(), vxlist.end(), tj.VtxID[end]) != vxlist.end()) {
1304  auto& vx2 = tjs.vtx[tj.VtxID[end] - 1];
1305 // std::cout<<"P"<<pfp.ID<<" Clobber 2V"<<vx2.ID<<"\n";
1306  MakeVertexObsolete(tjs, vx2, true);
1307  } else {
1308  vxlist.push_back(tj.VtxID[end]);
1309  }
1310  } // end
1311  } // tjid
1312  } // plane
1313 
1314  pfp.TjIDs = newTjIDs;
1315 
1316  if(prt) {
1317  mf::LogVerbatim myprt("TC");
1318  myprt<<"MergePFPTjs: P"<<pfp.ID<<" out";
1319  for(auto tjid : pfp.TjIDs) myprt<<" T"<<tjid;
1320  PrintPFP("MPTJ", tjs, pfp, true);
1321  }
1322  return true;
1323  } // MergePFPTjs
unsigned int Nplanes() const
Number of planes in this tpc.
Definition: TPCGeo.h:145
Geometry information for a single TPC.
Definition: TPCGeo.h:37
void UpdateTp3s(TjStuff &tjs, PFPStruct &pfp, int oldTj, int newTj)
Definition: PFPUtils.cxx:85
void ReverseTraj(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:2666
bool MakeVertexObsolete(TjStuff &tjs, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:2917
void UpdateMatchStructs(TjStuff &tjs, int oldTj, int newTj)
Definition: PFPUtils.cxx:16
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
short MCSMom(const TjStuff &tjs, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2837
unsigned int CTP_t
Definition: DataStructs.h:41
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
void SetEndPoints(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:2788
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void MakeTrajectoryObsolete(TjStuff &tjs, unsigned int itj)
Definition: Utils.cxx:1797
void PrintPFP(std::string someText, const TjStuff &tjs, const PFPStruct &pfp, bool printHeader)
Definition: Utils.cxx:4619
void SetPDGCode(TjStuff &tjs, unsigned short itj)
Definition: Utils.cxx:3697
bool StoreTraj(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:1095
void tca::MergeShowerChain ( std::string  inFcnLabel,
TjStuff tjs,
const CTP_t inCTP,
bool  prt 
)

Definition at line 2642 of file TCShower.cxx.

References tca::TjStuff::allTraj, ChkAssns(), tca::TjStuff::cots, tca::ShowerStruct::CTP, DontCluster(), tca::ShowerStruct::Energy, tca::ShowerStruct::ID, kMergeShChain, lessThan(), MakeBareTrajPoint(), MergeShowers(), PointTrajDOCA(), PosSep(), PrintPos(), tca::ShowerStruct::ShowerTjID, tca::ShowerStruct::TjIDs, and tca::TjStuff::UseAlg.

Referenced by FindShowers3D().

2643  {
2644  // Merge chains of 3 or more showers that lie on a line
2645 
2646  if(!tjs.UseAlg[kMergeShChain]) return;
2647 
2648  std::string fcnLabel = inFcnLabel + ".MSC";
2649 
2650  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<": MergeShowerChain inCTP "<<inCTP;
2651 
2652  std::vector<int> sids;
2653  std::vector<TrajPoint> tpList;
2654  for(unsigned short ict = 0; ict < tjs.cots.size(); ++ict) {
2655  ShowerStruct& iss = tjs.cots[ict];
2656  if(iss.ID == 0) continue;
2657  if(iss.TjIDs.empty()) continue;
2658  if(iss.CTP != inCTP) continue;
2659  // ignore wimpy showers
2660  if(iss.Energy < 50) continue;
2661  // save the shower ID
2662  sids.push_back(iss.ID);
2663  // and the shower center TP
2664  tpList.push_back(tjs.allTraj[iss.ShowerTjID - 1].Pts[1]);
2665  } // ict
2666  if(sids.size() < 3) return;
2667 
2668  // sort by wire so the chain order is reasonable
2669  std::vector<SortEntry> sortVec(sids.size());
2670  for(unsigned short ii = 0; ii < sortVec.size(); ++ii) {
2671  sortVec[ii].index = ii;
2672  sortVec[ii].length = tpList[ii].Pos[0];
2673  }
2674  std::sort(sortVec.begin(), sortVec.end(), lessThan);
2675  auto tsids = sids;
2676  auto ttpList = tpList;
2677  for(unsigned short ii = 0; ii < sortVec.size(); ++ii) {
2678  unsigned short indx = sortVec[ii].index;
2679  sids[ii] = tsids[indx];
2680  tpList[ii] = ttpList[indx];
2681  }
2682 
2683  // TODO: These cuts should be generalized somehow
2684  float minSep = 150;
2685  float maxDelta = 30;
2686  for(unsigned short ii = 0; ii < sids.size() - 2; ++ii) {
2687  auto& iss = tjs.cots[sids[ii] - 1];
2688  if(iss.ID == 0) continue;
2689  unsigned short jj = ii + 1;
2690  auto& jss = tjs.cots[sids[jj] - 1];
2691  if(jss.ID == 0) continue;
2692  std::vector<int> chain;
2693  float sepij = PosSep(tpList[ii].Pos, tpList[jj].Pos);
2694  if(sepij > minSep) continue;
2695  bool skipit = DontCluster(tjs, iss.TjIDs, jss.TjIDs);
2696  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" i2S"<<iss.ID<<" "<<PrintPos(tjs, tpList[ii].Pos)<<" j2S"<<jss.ID<<" "<<PrintPos(tjs, tpList[jj].Pos)<<" sepij "<<sepij<<" skipit? "<<skipit;
2697  if(skipit) continue;
2698  // draw a line between these points
2699  TrajPoint tp;
2700  MakeBareTrajPoint(tjs, tpList[ii], tpList[jj], tp);
2701 // PrintTrajPoint("ij", tjs, 0, 1, 0, tp);
2702  for(unsigned short kk = jj + 1; kk < sids.size(); ++kk) {
2703  auto& kss = tjs.cots[sids[kk] - 1];
2704  if(kss.ID == 0) continue;
2705  if(DontCluster(tjs, iss.TjIDs, kss.TjIDs)) continue;
2706  if(DontCluster(tjs, jss.TjIDs, kss.TjIDs)) continue;
2707  float sepjk = PosSep(tpList[jj].Pos, tpList[kk].Pos);
2708  float delta = PointTrajDOCA(tjs, tpList[kk].Pos[0], tpList[kk].Pos[1], tp);
2709  if(prt) {
2710  mf::LogVerbatim myprt("TC");
2711  myprt<<fcnLabel<<" k2S"<<kss.ID<<" "<<PrintPos(tjs, tpList[kk].Pos)<<" sepjk "<<sepjk<<" delta "<<delta;
2712  if(sepjk > minSep || delta > maxDelta) {
2713  myprt<<" failed separation "<<minSep<<" or delta cut "<<maxDelta;
2714  } else {
2715  myprt<<" add to the chain";
2716  }
2717  } // prt
2718  if(sepjk > minSep || delta > maxDelta) {
2719  // clear a short chain?
2720  if(chain.size() > 2) {
2721  // merge this chain
2722  int newID = MergeShowers(fcnLabel, tjs, chain, prt);
2723  if(prt) {
2724  mf::LogVerbatim myprt("TC");
2725  myprt<<fcnLabel<<" merged chain";
2726  for(auto ssID : chain) myprt<<" 2S"<<ssID;
2727  myprt<<" -> 2S"<<newID;
2728  } // prt
2729  } // long chain
2730  chain.clear();
2731  break;
2732  } else {
2733  // add this shower to the chain
2734  if(chain.empty()) {
2735  chain.resize(3);
2736  chain[0] = sids[ii]; chain[1] = sids[jj]; chain[2] = sids[kk];
2737  } else {
2738  chain.push_back(sids[kk]);
2739  }
2740  // Refine the TP position and direction
2741  MakeBareTrajPoint(tjs, tpList[ii], tpList[kk], tp);
2742 // PrintTrajPoint("ik", tjs, 0, 0, chain.size(), tp);
2743  } // add to an existing chain
2744  } // kk
2745  // push the last one
2746  if(chain.size() > 2) {
2747  int newID = MergeShowers(fcnLabel, tjs, chain, prt);
2748 /*
2749  if(newID > 0) {
2750  auto& newss = tjs.cots[newID - 1];
2751  if(AddTjsInsideEnvelope(fcnLabel, tjs, newss, prt)) UpdateShower(fcnLabel, tjs, newss, prt);
2752  }
2753 */
2754  if(prt) {
2755  mf::LogVerbatim myprt("TC");
2756  myprt<<fcnLabel<<" merged chain";
2757  for(auto ssID : chain) myprt<<" "<<ssID;
2758  myprt<<" -> new ssID "<<newID;
2759  } // prt
2760  } // long chain
2761  } // ii
2762 
2763  ChkAssns(fcnLabel, tjs);
2764 
2765  } // MergeShowerChain
std::string PrintPos(const TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:4738
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool ChkAssns(std::string inFcnLabel, TjStuff &tjs)
Definition: TCShower.cxx:4625
bool MakeBareTrajPoint(const TjStuff &tjs, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:3493
bool DontCluster(const TjStuff &tjs, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3381
float PointTrajDOCA(TjStuff const &tjs, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2139
bool lessThan(SortEntry c1, SortEntry c2)
Definition: TCShower.cxx:10
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
int MergeShowers(std::string inFcnLabel, TjStuff &tjs, std::vector< int > ssIDs, bool prt)
Definition: TCShower.cxx:2985
int tca::MergeShowers ( std::string  inFcnLabel,
TjStuff tjs,
std::vector< int >  ssIDs,
bool  prt 
)

Definition at line 2985 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::TjStuff::cots, CreateSS(), kKilled, MakeShowerObsolete(), ss, StoreShower(), and UpdateShower().

Referenced by MergeShowerChain().

2986  {
2987  // merge a list of showers and return the ID of the merged shower.
2988  // Returns 0 if there was a failure.
2989 
2990  std::string fcnLabel = inFcnLabel + ".MS";
2991  if(ssIDs.size() < 2) return 0;
2992  // check for a valid ID
2993  for(auto ssID : ssIDs) if(ssID <= 0 || ssID > (int)tjs.cots.size()) return 0;
2994  // check for the same CTP and consistent assns
2995  int ss3Assn = 0;
2996  auto& ss0 = tjs.cots[ssIDs[0] - 1];
2997  std::vector<int> tjl;
2998  for(auto ssID : ssIDs) {
2999  auto& ss = tjs.cots[ssID - 1];
3000  if(ss.CTP != ss0.CTP) return 0;
3001  tjl.insert(tjl.end(), ss.TjIDs.begin(), ss.TjIDs.end());
3002  if(ss.SS3ID > 0 && ss3Assn == 0) ss3Assn = ss.SS3ID;
3003  if(ss.SS3ID > 0 && ss.SS3ID != ss3Assn) {
3004  std::cout<<fcnLabel<<" Assn conflict \n";
3005  return 0;
3006  }
3007  } // ssID
3008  // ensure the InShower Tjs are valid
3009  for(auto tjID : tjl) {
3010  auto& tj = tjs.allTraj[tjID - 1];
3011  if(tj.CTP != ss0.CTP || tj.AlgMod[kKilled]) {
3012  std::cout<<fcnLabel<<" bad InShower T"<<tjID<<"\n";
3013  return 0;
3014  }
3015  } // tjID
3016 
3017  // mark the old showers killed
3018  for(auto ssID : ssIDs) {
3019  auto& ss = tjs.cots[ssID - 1];
3020  ss.ID = 0;
3021  // kill the shower Tj
3022  auto& stj = tjs.allTraj[ss.ShowerTjID - 1];
3023  stj.AlgMod[kKilled] = true;
3024  } // tjID
3025 
3026  // in with the new
3027  auto newss = CreateSS(tjs, 0, tjl);
3028  if(newss.ID == 0) return 0;
3029 
3030  for(auto tid : tjl) {
3031  auto& tj = tjs.allTraj[tid - 1];
3032  tj.SSID = newss.ID;
3033  } // tid
3034  newss.SS3ID = ss3Assn;
3035 
3036  // define the new shower
3037  if(!UpdateShower(fcnLabel, tjs, newss, prt)) {
3038  std::cout<<fcnLabel<<" UpdateShower failed\n";
3039  MakeShowerObsolete(fcnLabel, tjs, newss, prt);
3040  return 0;
3041  }
3042  // store it
3043  if(!StoreShower(fcnLabel, tjs, newss)) {
3044  std::cout<<fcnLabel<<" StoreShower failed\n";
3045  MakeShowerObsolete(fcnLabel, tjs, newss, prt);
3046  return 0;
3047  }
3048  return newss.ID;
3049 
3050  } // MergeShowers
void MakeShowerObsolete(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3334
Float_t ss
Definition: plot.C:23
bool StoreShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss)
Definition: TCShower.cxx:4511
ShowerStruct CreateSS(TjStuff &tjs, CTP_t inCTP, const std::vector< int > &tjl)
Definition: TCShower.cxx:4572
bool UpdateShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1302
bool tca::MergeShowersAndStore ( std::string  inFcnLabel,
TjStuff tjs,
int  icotID,
int  jcotID,
bool  prt 
)

Definition at line 3053 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::TjStuff::cots, tca::ShowerStruct::CTP, tca::Trajectory::ID, tca::ShowerStruct::ID, KillVerticesInShower(), MakeTrajectoryObsolete(), tca::ShowerStruct::NearTjIDs, tca::ShowerStruct::NeedsUpdate, tca::Trajectory::Pts, tca::ShowerStruct::ShowerTjID, tca::ShowerStruct::ShPts, tca::ShowerStruct::SS3ID, tca::ShowerStruct::TjIDs, tca::ShowerStruct::TruParentID, and UpdateShower().

Referenced by MergeNearby2DShowers(), MergeOverlap(), MergeShowerTjsAndStore(), MergeSubShowers(), and Reconcile3D().

3054  {
3055  // Merge showers using shower indices. The icotID shower is modified in-place.
3056  // The jcotID shower is declared obsolete. This function also re-defines the shower and
3057  // preserves the icotID Parent ID.
3058 
3059  if(icotID <= 0 || icotID > (int)tjs.cots.size()) return false;
3060  ShowerStruct& iss = tjs.cots[icotID - 1];
3061  if(iss.ID == 0) return false;
3062  if(iss.TjIDs.empty()) return false;
3063  if(iss.ShowerTjID <= 0) return false;
3064 
3065  if(jcotID <= 0 || jcotID > (int)tjs.cots.size()) return false;
3066  ShowerStruct& jss = tjs.cots[jcotID - 1];
3067  if(jss.TjIDs.empty()) return false;
3068  if(jss.ID == 0) return false;
3069  if(jss.ShowerTjID <= 0) return false;
3070 
3071  if(iss.CTP != jss.CTP) return false;
3072 
3073  std::string fcnLabel = inFcnLabel + ".MSAS";
3074 
3075  if(iss.SS3ID > 0 && jss.SS3ID > 0 && iss.SS3ID != jss.SS3ID) {
3076  std::cout<<fcnLabel<<" Error: 2S"<<iss.ID<<" and S"<<jss.ID<<" have different 2S -> 3S assns\n";
3077  return false;
3078  }
3079 
3080  Trajectory& itj = tjs.allTraj[iss.ShowerTjID - 1];
3081  Trajectory& jtj = tjs.allTraj[jss.ShowerTjID - 1];
3082  if(!itj.Pts[1].Hits.empty() || !jtj.Pts[1].Hits.empty()) {
3083  std::cout<<fcnLabel<<" Error: These shower Tjs have hits! T"<<itj.ID<<" T"<<jtj.ID<<"\n";
3084  return false;
3085  }
3086 
3087  iss.TjIDs.insert(iss.TjIDs.end(), jss.TjIDs.begin(), jss.TjIDs.end());
3088  // make a new trajectory using itj as a template
3089  Trajectory ktj = itj;
3090  ktj.ID = tjs.allTraj.size() + 1;
3091 
3092  tjs.allTraj.push_back(ktj);
3093  // kill jtj
3094  MakeTrajectoryObsolete(tjs, iss.ShowerTjID - 1);
3095  MakeTrajectoryObsolete(tjs, jss.ShowerTjID - 1);
3096  tjs.allTraj[iss.ShowerTjID - 1].ParentID = ktj.ID;
3097  tjs.allTraj[jss.ShowerTjID - 1].ParentID = ktj.ID;
3098  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" killed stj T"<<iss.ShowerTjID<<" and T"<<jss.ShowerTjID<<" new T"<<ktj.ID;
3099  // revise the shower
3100  iss.ShowerTjID = ktj.ID;
3101  // transfer the list of Tj IDs
3102  iss.TjIDs.insert(iss.TjIDs.end(), jss.TjIDs.begin(), jss.TjIDs.begin());
3103  std::sort(iss.TjIDs.begin(), iss.TjIDs.end());
3104  // correct the assn
3105  for(auto tid : iss.TjIDs) {
3106  auto& tj = tjs.allTraj[tid - 1];
3107  tj.SSID = iss.ID;
3108  } // tid
3109  // transfer a 2S -> 3S assn
3110  if(iss.SS3ID == 0 && jss.SS3ID > 0) iss.SS3ID = jss.SS3ID;
3111  // merge the list of nearby Tjs
3112  iss.NearTjIDs.insert(iss.NearTjIDs.end(), jss.NearTjIDs.begin(), jss.NearTjIDs.end());
3113  // transfer the TruParentID if it is in jss
3114  if(jss.TruParentID > 0) iss.TruParentID = jss.TruParentID;
3115 // iss.ParentID = 0;
3116  iss.NeedsUpdate = true;
3117  // force a full update
3118  iss.ShPts.clear();
3119  jss.ID = 0;
3120  bool success = UpdateShower(fcnLabel, tjs, iss, prt);
3121  KillVerticesInShower(fcnLabel, tjs, iss, prt);
3122 
3123  return success;
3124 
3125  } // MergeShowersAndStore
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void KillVerticesInShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:767
void MakeTrajectoryObsolete(TjStuff &tjs, unsigned int itj)
Definition: Utils.cxx:1797
bool UpdateShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1302
bool tca::MergeShowerTjsAndStore ( TjStuff tjs,
unsigned short  istj,
unsigned short  jstj,
bool  prt 
)

Definition at line 3128 of file TCShower.cxx.

References tca::Trajectory::AlgMod, tca::TjStuff::allTraj, tca::TjStuff::cots, GetCotID(), tca::Trajectory::ID, tca::ShowerStruct::ID, kShowerTj, MergeShowersAndStore(), and tca::ShowerStruct::TjIDs.

Referenced by MergeAndStore().

3129  {
3130  // Merge showers using showerTj indices
3131  // This function is called from MergeAndStore whose function is to merge two line-like
3132  // trajectories and store them. This function was called because at least one of the
3133  // trajectories is a shower Tj. Assume that the decision to merge them has been made elsewhere.
3134 
3135  if(istj > tjs.allTraj.size() - 1) return false;
3136  if(jstj > tjs.allTraj.size() - 1) return false;
3137 
3138  Trajectory& itj = tjs.allTraj[istj];
3139  Trajectory& jtj = tjs.allTraj[jstj];
3140 
3141  std::string fcnLabel = "MSTJ";
3142 
3143  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" MergeShowerTjsAndStore Tj IDs "<<itj.ID<<" "<<jtj.ID;
3144 
3145  // First we check to make sure that both are shower Tjs.
3146  if(!itj.AlgMod[kShowerTj] && !jtj.AlgMod[kShowerTj]) {
3147  if(prt) mf::LogVerbatim("TC")<<" One of these isn't a shower Tj";
3148  return false;
3149  }
3150 
3151  // We need to keep the convention used in MergeAndStore to create a new merged trajectory
3152  // and kill the two fragments. This doesn't require making a new shower however. We can just
3153  // re-purpose one of the existing showers
3154  int icotID = GetCotID(tjs, itj.ID);
3155  if(icotID == 0) return false;
3156  ShowerStruct& iss = tjs.cots[icotID - 1];
3157  if(iss.ID == 0) return false;
3158  if(iss.TjIDs.empty()) return false;
3159  int jcotID = GetCotID(tjs, jtj.ID);
3160  if(jcotID == 0) return false;
3161  ShowerStruct& jss = tjs.cots[jcotID - 1];
3162  if(jss.ID == 0) return false;
3163  if(jss.TjIDs.empty()) return false;
3164 
3165  return MergeShowersAndStore(fcnLabel, tjs, icotID, jcotID, prt);
3166 
3167  } // MergeShowerTjsAndStore
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MergeShowersAndStore(std::string inFcnLabel, TjStuff &tjs, int icotID, int jcotID, bool prt)
Definition: TCShower.cxx:3053
int GetCotID(TjStuff &tjs, int ShowerTjID)
Definition: TCShower.cxx:4424
void tca::MergeSubShowers ( std::string  inFcnLabel,
TjStuff tjs,
const CTP_t inCTP,
bool  prt 
)

Definition at line 2878 of file TCShower.cxx.

References tca::Trajectory::AlgMod, tca::TjStuff::allTraj, tca::ShowerStruct::AspectRatio, ChkAssns(), tca::TjStuff::cots, tca::TrajPoint::Dir, DontCluster(), tca::ShowerStruct::Energy, FindAlongTrans(), greaterThan(), tca::ShowerStruct::ID, tca::SortEntry::index, InShowerProbLong(), InShowerProbTrans(), kMergeSubShowers, MergeShowersAndStore(), PointTrajDOCA(), tca::TrajPoint::Pos, PosSep(), ShowerParams(), tca::TjStuff::ShowerTag, tca::ShowerStruct::ShowerTjID, ss, tca::ShowerStruct::TjIDs, tca::TjStuff::UseAlg, and tca::TjStuff::WirePitch.

Referenced by FindShowers3D().

2879  {
2880  // Merge small showers that are downstream of larger showers
2881 
2882  if(!tjs.UseAlg[kMergeSubShowers]) return;
2883 
2884  std::string fcnLabel = inFcnLabel + ".MSS";
2885  bool newCuts = (tjs.ShowerTag[0] == 4);
2886  constexpr float radLen = 14 / 0.3;
2887 
2888  if(prt) {
2889  if(newCuts) {
2890  mf::LogVerbatim("TC")<<fcnLabel<<" MergeSubShowers checking using ShowerParams";
2891  } else {
2892  mf::LogVerbatim("TC")<<fcnLabel<<" MergeSubShowers checking using radiation length cut ";
2893  }
2894  } // prt
2895 
2896  bool keepMerging = true;
2897  while(keepMerging) {
2898  keepMerging = false;
2899  // sort by decreasing energy
2900  std::vector<SortEntry> sortVec;
2901  for(auto& ss : tjs.cots) {
2902  if(ss.ID == 0) continue;
2903  if(ss.CTP != inCTP) continue;
2904  SortEntry se;
2905  se.index = ss.ID - 1;
2906  se.length = ss.Energy;
2907  sortVec.push_back(se);
2908  } // ss
2909  if(sortVec.size() < 2) return;
2910  std::sort(sortVec.begin(), sortVec.end(), greaterThan);
2911  for(unsigned short ii = 0; ii < sortVec.size() - 1; ++ii) {
2912  ShowerStruct& iss = tjs.cots[sortVec[ii].index];
2913  if(iss.ID == 0) continue;
2914  // this shouldn't be done to showers that are ~round
2915  if(iss.AspectRatio > 0.5) continue;
2916  TrajPoint& istp1 = tjs.allTraj[iss.ShowerTjID - 1].Pts[1];
2917  double shMaxAlong, along95;
2918  ShowerParams((double)iss.Energy, shMaxAlong, along95);
2919  // convert along95 to a separation btw shower max and along95
2920  along95 -= shMaxAlong;
2921  // convert to WSE
2922  along95 /= tjs.WirePitch;
2923  for(unsigned short jj = ii + 1; jj < sortVec.size(); ++jj) {
2924  ShowerStruct& jss = tjs.cots[sortVec[jj].index];
2925  if(jss.ID == 0) continue;
2926  if(DontCluster(tjs, iss.TjIDs, jss.TjIDs)) continue;
2927  TrajPoint& jstp1 = tjs.allTraj[jss.ShowerTjID - 1].Pts[1];
2928  if(newCuts) {
2929  // find the longitudinal and transverse separation using the higher energy
2930  // shower which probably is better defined.
2931  Point2_t alongTrans;
2932  FindAlongTrans(istp1.Pos, istp1.Dir, jstp1.Pos, alongTrans);
2933  // the lower energy shower is at the wrong end of the higher energy shower if alongTrans[0] < 0
2934  if(alongTrans[0] < 0) continue;
2935  // increase the cut if the second shower is < 10% of the first shower
2936  float alongCut = along95;
2937  if(jss.Energy < 0.1 * iss.Energy) alongCut *= 1.5;
2938  float probLong = InShowerProbLong(iss.Energy, alongTrans[0]);
2939  float probTran = InShowerProbTrans(iss.Energy, alongTrans[0], alongTrans[1]);
2940  if(prt) {
2941  mf::LogVerbatim myprt("TC");
2942  myprt<<fcnLabel<<" Candidate i2S"<<iss.ID<<" E = "<<(int)iss.Energy<<" j2S"<<jss.ID<<" E = "<<(int)jss.Energy;
2943  myprt<<" along "<<std::fixed<<std::setprecision(1)<<alongTrans[0]<<" trans "<<alongTrans[1];
2944  myprt<<" alongCut "<<alongCut<<" probLong "<<probLong<<" probTran "<<probTran;
2945  } // prt
2946  // TODO: fix ShowerParams so we can use the likelihood cut instead
2947  if(alongTrans[0] > alongCut) continue;
2948  if(alongTrans[1] > alongTrans[0]) continue;
2949  } else {
2950  // old cuts
2951  float sep = PosSep(istp1.Pos, jstp1.Pos);
2952  float trad = sep / radLen;
2953  // Find the IP between them using the projection of the one with the lowest aspect ratio
2954  float delta = 9999;
2955  if(iss.AspectRatio < jss.AspectRatio) {
2956  delta = PointTrajDOCA(tjs, jstp1.Pos[0], jstp1.Pos[1], istp1);
2957  } else {
2958  delta = PointTrajDOCA(tjs, istp1.Pos[0], istp1.Pos[1], jstp1);
2959  }
2960  // See if delta is consistent with the cone angle of the i shower
2961  float dang = delta / sep;
2962  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Candidate i2S"<<iss.ID<<" j2S"<<jss.ID<<" separation "<<(int)sep<<" radiation lengths "<<trad<<" delta "<<delta<<" dang "<<dang;
2963  if(trad > 3) continue;
2964  // There must be a correlation between dang and the energy of these showers...
2965  if(dang > 0.3) continue;
2966  } // old cuts
2967 
2968  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Merge them. Re-find shower center, etc";
2969  if(MergeShowersAndStore(fcnLabel, tjs, iss.ID, jss.ID, prt)) {
2970  Trajectory& stj = tjs.allTraj[iss.ShowerTjID - 1];
2971  stj.AlgMod[kMergeSubShowers] = true;
2972  keepMerging = true;
2973  break;
2974  }
2975  } // jj
2976  if(keepMerging) break;
2977  } // ii
2978  } // keepMerging
2979 
2980  ChkAssns(fcnLabel, tjs);
2981 
2982  } // MergeSubShowers
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool greaterThan(SortEntry c1, SortEntry c2)
Definition: TCShower.cxx:9
bool MergeShowersAndStore(std::string inFcnLabel, TjStuff &tjs, int icotID, int jcotID, bool prt)
Definition: TCShower.cxx:3053
double InShowerProbLong(double showerEnergy, double along)
Definition: TCShower.cxx:2118
unsigned int index
Definition: TCShower.cxx:5
bool ChkAssns(std::string inFcnLabel, TjStuff &tjs)
Definition: TCShower.cxx:4625
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:2751
Float_t ss
Definition: plot.C:23
float length
Definition: TCShower.cxx:6
double InShowerProbTrans(double showerEnergy, double along, double trans)
Definition: TCShower.cxx:2152
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
bool DontCluster(const TjStuff &tjs, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3381
float PointTrajDOCA(TjStuff const &tjs, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2139
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
Definition: TCShower.cxx:2084
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
void tca::MergeSubShowersTj ( std::string  inFcnLabel,
TjStuff tjs,
const CTP_t inCTP,
bool  prt 
)

Definition at line 2768 of file TCShower.cxx.

References AddTj(), tca::TjStuff::allTraj, ChgToMeV(), ChkAssns(), tca::TjStuff::cots, DontCluster(), FarEnd(), kKilled, kMergeSubShowersTj, mat, MCSMom(), NumPtsWithCharge(), PointTrajDOCA(), PosSep(), tca::TjStuff::ShowerTag, ss, and tca::TjStuff::UseAlg.

Referenced by FindShowers3D().

2769  {
2770  // merge small showers that are downstream of shower-like tjs. This algorithm is written
2771  // for low-energy showers with are likely to be sparse and poorly defined.
2772 
2773  if(!tjs.UseAlg[kMergeSubShowersTj]) return;
2774 
2775  std::string fcnLabel = inFcnLabel + ".MSSTj";
2776 
2777  struct TjSS {
2778  int ssID;
2779  int tjID;
2780  float dang;
2781  };
2782  std::vector<TjSS> tjss;
2783 
2784  // temp vector for DontCluster
2785  std::vector<int> tjid(1);
2786  for(auto& ss : tjs.cots) {
2787  if(ss.ID == 0) continue;
2788  if(ss.CTP != inCTP) continue;
2789  // TODO: Evaluate this cut
2790  if(ss.Energy > 300) continue;
2791  auto& stj = tjs.allTraj[ss.ShowerTjID - 1];
2792  auto stp0 = stj.Pts[0];
2793  float bestDang = 0.3;
2794  int bestTj = 0;
2795  // look for a Tj that has higher energy than the shower
2796  for(auto& tj : tjs.allTraj) {
2797  if(tj.AlgMod[kKilled]) continue;
2798  if(tj.CTP != ss.CTP) continue;
2799  // require that it isn't in any shower
2800  if(tj.SSID > 0) continue;
2801  // require it to be not short
2802  if(NumPtsWithCharge(tjs, tj, false) < 10) continue;
2803  // and satisfy the ShowerLike MCSMom cut. It is unlikely to be tagged shower-like
2804  if(tj.MCSMom > tjs.ShowerTag[1]) continue;
2805  // check consistency
2806  tjid[0] = tj.ID;
2807  if(DontCluster(tjs, tjid, ss.TjIDs)) continue;
2808  float tjEnergy = ChgToMeV(tj.TotChg);
2809  // find the end that is furthest away from the shower center
2810  unsigned short farEnd = FarEnd(tjs, tj, stj.Pts[1].Pos);
2811  // compare MCSMom at the far end and the near end
2812  unsigned short midpt = 0.5 * (tj.EndPt[0] + tj.EndPt[1]);
2813  float mom1 = MCSMom(tjs, tj, tj.EndPt[farEnd], midpt);
2814  float mom2 = MCSMom(tjs, tj, tj.EndPt[1 - farEnd], midpt);
2815  float asym = (mom1 - mom2) / (mom1 + mom2);
2816  auto& farTP = tj.Pts[tj.EndPt[farEnd]];
2817  // IP btw the far end TP and the shower center
2818  float doca = PointTrajDOCA(tjs, stp0.Pos[0], stp0.Pos[1], farTP);
2819  float sep = PosSep(farTP.Pos, stp0.Pos);
2820  float dang = doca / sep;
2821  if(prt) {
2822  mf::LogVerbatim myprt("TC");
2823  myprt<<fcnLabel<<" Candidate 2S"<<ss.ID<<" T"<<tj.ID<<"_"<<farEnd;
2824  myprt<<" ShEnergy "<<(int)ss.Energy<<" tjEnergy "<<(int)tjEnergy;
2825  myprt<<" doca "<<doca<<" sep "<<sep<<" dang "<<dang<<" asym "<<asym;
2826  }
2827  if(tjEnergy < ss.Energy) continue;
2828  if(asym < 0.5) continue;
2829  // TODO: This should be done more carefully
2830  // separation cut 100 WSE ~ 30 cm in uB
2831  if(sep > 100) continue;
2832  if(dang > bestDang) continue;
2833  bestDang = dang;
2834  bestTj = tj.ID;
2835  } // tj
2836  if(bestTj == 0) continue;
2837  TjSS match;
2838  match.ssID = ss.ID;
2839  match.tjID = bestTj;
2840  match.dang = bestDang;
2841  tjss.push_back(match);
2842  } // ss
2843 
2844  if(tjss.empty()) return;
2845 
2846  // ensure that a tj is only put in one shower
2847  bool keepGoing = true;
2848  while(keepGoing) {
2849  keepGoing = false;
2850  float bestDang = 0.3;
2851  int bestMatch = 0;
2852  for(unsigned short mat = 0; mat < tjss.size(); ++mat) {
2853  auto& match = tjss[mat];
2854  // already used
2855  if(match.dang < 0) continue;
2856  if(match.dang < bestDang) bestMatch = mat;
2857  } // mat
2858  if(bestMatch > 0) {
2859  auto& match = tjss[bestMatch];
2860  auto& ss = tjs.cots[match.ssID - 1];
2861  if(!AddTj(fcnLabel, tjs, match.tjID, ss, true, prt)) {
2862  if(prt) mf::LogVerbatim("TC")<<" Failed";
2863  continue;
2864  }
2865  match.dang = -1;
2866  // set the AlgMod bit
2867  auto& stj = tjs.allTraj[ss.ShowerTjID - 1];
2868  stj.AlgMod[kMergeSubShowersTj] = true;
2869  keepGoing = true;
2870  } // found bestMatch
2871  } // keepGoing
2872 
2873  ChkAssns(fcnLabel, tjs);
2874 
2875  } // MergeSubShowersTj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool AddTj(std::string inFcnLabel, TjStuff &tjs, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1624
bool ChkAssns(std::string inFcnLabel, TjStuff &tjs)
Definition: TCShower.cxx:4625
Float_t ss
Definition: plot.C:23
unsigned short FarEnd(const TjStuff &tjs, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:2936
Float_t mat
Definition: plot.C:40
bool DontCluster(const TjStuff &tjs, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3381
float PointTrajDOCA(TjStuff const &tjs, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2139
short MCSMom(const TjStuff &tjs, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2837
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
unsigned short NumPtsWithCharge(const TjStuff &tjs, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1738
float ChgToMeV(float chg)
Definition: TCShower.cxx:4460
bool tca::MergeTjIntoPFP ( TjStuff tjs,
int  mtjid,
PFPStruct pfp,
bool  prt 
)

Definition at line 428 of file Utils.cxx.

References tca::TjStuff::allTraj, MergeAndStore(), and tca::PFPStruct::TjIDs.

429  {
430  // Tries to merge Tj with ID tjid into PFParticle pfp
431  if(mtjid > (int)tjs.allTraj.size()) return false;
432  auto& mtj = tjs.allTraj[mtjid - 1];
433  // find the Tj in pfp.TjIDs which it should be merged with
434  int otjid = 0;
435  for(auto tjid : pfp.TjIDs) {
436  auto& otj = tjs.allTraj[tjid - 1];
437  if(otj.CTP == mtj.CTP) {
438  otjid = tjid;
439  break;
440  }
441  } // tjid
442  if(otjid == 0) return false;
443  if(MergeAndStore(tjs, otjid - 1, mtjid - 1, prt)) {
444  int newtjid = tjs.allTraj.size();
445  if(prt) mf::LogVerbatim("TC")<<"MergeTjIntoPFP: merged T"<<otjid<<" with T"<<mtjid<<" -> T"<<newtjid;
446  std::replace(pfp.TjIDs.begin(), pfp.TjIDs.begin(), otjid, newtjid);
447  return true;
448  } else {
449  if(prt) mf::LogVerbatim("TC")<<"MergeTjIntoPFP: merge T"<<otjid<<" with T"<<mtjid<<" failed ";
450  return false;
451  }
452  } // MergeTjIntoPFP
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MergeAndStore(TjStuff &tjs, unsigned int itj1, unsigned int itj2, bool doPrt)
Definition: Utils.cxx:3896
void tca::MergeTjList ( std::vector< std::vector< int >> &  tjList)

Definition at line 1494 of file TCShower.cxx.

1495  {
1496  // Merge the lists of Tjs in the lists if they share a common Tj ID
1497 
1498  if(tjList.size() < 2) return;
1499 
1500  bool didMerge = true;
1501  while(didMerge) {
1502  didMerge = false;
1503  for(unsigned short itl = 0; itl < tjList.size() - 1; ++itl) {
1504  if(tjList[itl].empty()) continue;
1505  for(unsigned short jtl = itl + 1; jtl < tjList.size(); ++jtl) {
1506  if(tjList[itl].empty()) continue;
1507  auto& itList = tjList[itl];
1508  auto& jtList = tjList[jtl];
1509  // See if the j Tj is in the i tjList
1510  bool jtjInItjList = false;
1511  for(auto& jtj : jtList) {
1512  if(std::find(itList.begin(), itList.end(), jtj) != itList.end()) {
1513  jtjInItjList = true;
1514  break;
1515  }
1516  if(jtjInItjList) break;
1517  } // jtj
1518  if(jtjInItjList) {
1519  // append the jtList to itList
1520  itList.insert(itList.end(), jtList.begin(), jtList.end());
1521  // clear jtList
1522  jtList.clear();
1523  didMerge = true;
1524  }
1525  } // jtl
1526  } // itl
1527  } // didMerge
1528 
1529  // erase the deleted elements
1530  unsigned short imEmpty = 0;
1531  while(imEmpty < tjList.size()) {
1532  for(imEmpty = 0; imEmpty < tjList.size(); ++imEmpty) if(tjList[imEmpty].empty()) break;
1533  if(imEmpty < tjList.size()) tjList.erase(tjList.begin() + imEmpty);
1534  } // imEmpty < tjList.size()
1535 
1536  // sort the lists by increasing ID and remove duplicates
1537  for(auto& tjl : tjList) {
1538  std::sort(tjl.begin(), tjl.end());
1539  auto last = std::unique(tjl.begin(), tjl.end());
1540  tjl.erase(last, tjl.end());
1541  } // tjl
1542 
1543  } // MergeTjList
void tca::MergeTjList2 ( std::string  inFcnLabel,
TjStuff tjs,
std::vector< std::vector< int >> &  tjList,
bool  prt 
)
bool tca::MergeWithVertex ( TjStuff tjs,
VtxStore vx,
unsigned short  oVxID,
bool  prt 
)

Definition at line 544 of file TCVertex.cxx.

References tca::TjStuff::allTraj, tca::VtxStore::ChiDOF, CloseEnd(), tca::VtxStore::CTP, evd::details::end(), FitVertex(), GetVtxTjIDs(), tca::VtxStore::ID, tca::SortEntry::index, kFixed, kKilled, kVtxMerged, kVxMerge, NearestPtWithChg(), NumPtsWithCharge(), tca::VtxStore::Pos, tca::VtxStore::PosErr, PrintPos(), SetVx2Score(), tca::VtxStore::Stat, tmp, tca::TjStuff::UseAlg, valDecreasing(), and tca::TjStuff::vtx.

Referenced by Find2DVertices().

545  {
546  // Attempts to merge the trajectories attached to vx with an existing 2D vertex
547  // referenced by existingVxID. This function doesn't use the existing end0/end1 vertex association.
548  // It returns true if the merging was successful in which case the calling function should
549  // not store vx. The calling function needs to have set VtxID to vx.ID for tjs that are currently attached
550  // to vx. It assumed that vx hasn't yet been pushed onto tjs.vtx
551 
552  if(!tjs.UseAlg[kVxMerge]) return false;
553 
554  if(oVxID > tjs.vtx.size()) return false;
555  auto& oVx = tjs.vtx[oVxID - 1];
556  if(vx.CTP != oVx.CTP) return false;
557 
558  // get a list of tjs attached to both vertices
559  std::vector<int> tjlist = GetVtxTjIDs(tjs, vx);
560 // auto tjlist = GetAssns(tjs, "2V", vx.ID, "T");
561  if(tjlist.empty()) return false;
562  std::vector<int> tmp = GetVtxTjIDs(tjs, oVx);
563 // auto tmp = GetAssns(tjs, "2V", oVx.ID, "T");
564  if(tmp.empty()) return false;
565  for(auto tjid : tmp) {
566  if(std::find(tjlist.begin(), tjlist.end(), tjid) == tjlist.end()) tjlist.push_back(tjid);
567  } // tjid
568  if(tjlist.size() < 2) return false;
569  // handle the simple case
570  if(tjlist.size() == 2) {
571  // Unset the fixed bit
572  vx.Stat[kFixed] = false;
573  oVx.Stat[kFixed] = false;
574  // assign the vx tjs to oVx
575  for(auto tjid : tjlist) {
576  auto& tj = tjs.allTraj[tjid - 1];
577  for(unsigned short end = 0; end < 2; ++end) {
578  if(tj.VtxID[end] == vx.ID) tj.VtxID[end] = oVx.ID;
579  } // end
580  } // tjid
581  if(!FitVertex(tjs, oVx, prt)) {
582  if(prt) mf::LogVerbatim("TC")<<"MWV: merge failed "<<vx.ID<<" and existing "<<oVx.ID;
583  return false;
584  }
585  return true;
586  } // size = 2
587 
588  // sort by decreasing length
589  std::vector<SortEntry> sortVec(tjlist.size());
590  for(unsigned int indx = 0; indx < sortVec.size(); ++indx) {
591  sortVec[indx].index = indx;
592  auto& tj = tjs.allTraj[tjlist[indx] - 1];
593  sortVec[indx].val = tj.Pts.size();
594  } // indx
595  std::sort(sortVec.begin(), sortVec.end(), valDecreasing);
596  // re-order the list of Tjs
597  auto ttl = tjlist;
598  for(unsigned short ii = 0; ii < sortVec.size(); ++ii) tjlist[ii] = ttl[sortVec[ii].index];
599  // Create a local vertex using the two longest tjs, then add the shorter ones
600  // until the pull reaches the cut
601  VtxStore aVx;
602  aVx.CTP = vx.CTP;
603  std::vector<TrajPoint> tjpts(tjlist.size());
604  // determine which point on each Tj that will be used in the vertex fit and stash it in
605  // the traj point Step variable. This requires knowing the real position of the merged vertex
606  // which we estimate by averaging
607  std::array<float, 2> vpos;
608  vpos[0] = 0.5 * (vx.Pos[0] + oVx.Pos[0]);
609  vpos[1] = 0.5 * (vx.Pos[1] + oVx.Pos[1]);
610  for(unsigned short ii = 0; ii < tjpts.size(); ++ii) {
611  auto& tj = tjs.allTraj[tjlist[ii] - 1];
612  unsigned short npwc = NumPtsWithCharge(tjs, tj, false);
613  unsigned short end = CloseEnd(tjs, tj, vpos);
614  // assume that we will use the end point of the tj
615  unsigned short endPt = tj.EndPt[end];
616  if(npwc > 6 && tj.Pts[endPt].NTPsFit < 4) {
617  if(end == 0) {
618  endPt += 3;
619  } else {
620  endPt -= 3;
621  }
622  endPt = NearestPtWithChg(tjs, tj, endPt);
623  } // few points fit at the end
624  if(endPt < tj.EndPt[0]) endPt = tj.EndPt[0];
625  if(endPt > tj.EndPt[1]) endPt = tj.EndPt[1];
626  // define tjpts
627  tjpts[ii].CTP = tj.CTP;
628  tjpts[ii].Pos = tj.Pts[endPt].Pos;
629  tjpts[ii].Dir = tj.Pts[endPt].Dir;
630  tjpts[ii].Ang = tj.Pts[endPt].Ang;
631  tjpts[ii].AngErr = tj.Pts[endPt].AngErr;
632  // stash the point in Step
633  tjpts[ii].Step = endPt;
634  // and the end in AngleCode
635  tjpts[ii].AngleCode = end;
636  // stash the ID in Hits
637  tjpts[ii].Hits.resize(1, tj.ID);
638  } // tjid
639  if(prt) {
640  mf::LogVerbatim myprt("TC");
641  myprt<<"MWV: "<<oVxID;
642  myprt<<" Fit TPs";
643  for(unsigned short ii = 0; ii < tjpts.size(); ++ii) {
644  auto& tjpt = tjpts[ii];
645  myprt<<" "<<tjlist[ii]<<"_"<<tjpt.Step<<"_"<<PrintPos(tjs, tjpt.Pos);
646  }
647  } // prt
648  // create a subset of the first two for the first fit
649  auto fitpts = tjpts;
650  fitpts.resize(2);
651  if(!FitVertex(tjs, aVx, fitpts, prt)) {
652  if(prt) mf::LogVerbatim("TC")<<"MWV: first fit failed ";
653  return false;
654  }
655  // Fit and add tjs to the vertex
656  bool needsUpdate = false;
657  for(unsigned short ii = 2; ii < tjlist.size(); ++ii) {
658  fitpts.push_back(tjpts[ii]);
659  if(FitVertex(tjs, aVx, fitpts, prt)) {
660  needsUpdate = false;
661  } else {
662  // remove the last Tj point and keep going
663  fitpts.pop_back();
664  needsUpdate = true;
665  }
666  } // ii
667 
668  if(needsUpdate) FitVertex(tjs, aVx, fitpts, prt);
669  if(prt) mf::LogVerbatim("TC")<<"MWV: done "<<vx.ID<<" and existing "<<oVx.ID;
670 
671  // update. Remove old associations
672  for(auto& tj : tjs.allTraj) {
673  if(tj.AlgMod[kKilled]) continue;
674  if(tj.CTP != vx.CTP) continue;
675  for(unsigned short end = 0; end < 2; ++end) {
676  if(tj.VtxID[end] == vx.ID) tj.VtxID[end] = 0;
677  if(tj.VtxID[end] == oVxID) tj.VtxID[end] = 0;
678  }
679  } // tj
680  // set the new associations
681  for(unsigned short ii = 0; ii < fitpts.size(); ++ii) {
682  auto& tjpt = fitpts[ii];
683  unsigned short end = tjpt.AngleCode;
684  auto& tj = tjs.allTraj[tjpt.Hits[0] - 1];
685  if(tj.VtxID[end] != 0) {
686  std::cout<<"MWV: coding error. tj "<<tj.ID<<" end "<<end<<" VtxID "<<tj.VtxID[end]<<" != 0\n";
687  return false;
688  }
689  tj.VtxID[end] = oVxID;
690  } // ii
691 
692  // Update oVx
693  oVx.Pos = aVx.Pos;
694  oVx.PosErr = aVx.PosErr;
695  oVx.ChiDOF = aVx.ChiDOF;
696  oVx.NTraj = fitpts.size();
697  // Update the score and the charge fraction
698  SetVx2Score(tjs, oVx, prt);
699  oVx.Stat[kVtxMerged] = true;
700  oVx.Stat[kFixed] = false;
701  if(prt) {
702  mf::LogVerbatim myprt("TC");
703  myprt<<"MWV: "<<oVxID;
704  myprt<<" Done TPs";
705  for(unsigned short ii = 0; ii < fitpts.size(); ++ii) {
706  auto& tjpt = fitpts[ii];
707  myprt<<" "<<tjpt.Hits[0]<<"_"<<tjpt.AngleCode<<"_"<<PrintPos(tjs, tjpt.Pos);
708  }
709  } // prt
710 
711  return true;
712  } // MergeWithVertex
bool valDecreasing(SortEntry c1, SortEntry c2)
Definition: TCVertex.cxx:10
std::string PrintPos(const TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:4738
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
vertex position fixed manually - no fitting done
Definition: DataStructs.h:102
unsigned short NearestPtWithChg(TjStuff &tjs, Trajectory &tj, unsigned short thePt)
Definition: Utils.cxx:2889
Float_t tmp
Definition: plot.C:37
bool FitVertex(TjStuff &tjs, VtxStore &vx, std::vector< TrajPoint > vxTp, bool prt)
Definition: TCVertex.cxx:1986
std::vector< int > GetVtxTjIDs(const TjStuff &tjs, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:3039
unsigned short CloseEnd(TjStuff &tjs, const Trajectory &tj, const Point2_t &pos)
Definition: Utils.cxx:2120
unsigned short NumPtsWithCharge(const TjStuff &tjs, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1738
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void SetVx2Score(TjStuff &tjs, VtxStore &vx2, bool prt)
Definition: TCVertex.cxx:2331
void tca::MoveTPToWire ( TrajPoint tp,
float  wire 
)

Definition at line 2351 of file Utils.cxx.

References tca::TrajPoint::Dir, and tca::TrajPoint::Pos.

Referenced by tca::TrajClusterAlg::AddHits(), Find2DVertices(), FindCloseTjs(), FindHammerVertices2(), tca::TrajClusterAlg::FindVtxTraj(), FitTraj(), tca::TrajClusterAlg::IsGhost(), and tca::TrajClusterAlg::ReversePropagate().

2352  {
2353  // Project TP to a "wire position" Pos[0] and update Pos[1]
2354  if(tp.Dir[0] == 0) return;
2355  float dw = wire - tp.Pos[0];
2356  if(std::abs(dw) < 0.01) return;
2357  tp.Pos[0] = wire;
2358  tp.Pos[1] += dw * tp.Dir[1] / tp.Dir[0];
2359  } // MoveTPToWire
unsigned short tca::NearestPtWithChg ( TjStuff tjs,
Trajectory tj,
unsigned short  thePt 
)

Definition at line 2889 of file Utils.cxx.

References tca::Trajectory::EndPt, and tca::Trajectory::Pts.

Referenced by DotProd(), Find2DVertices(), MCSMom(), MCSThetaRMS(), MergeWithVertex(), and TjDeltaRMS().

2890  {
2891  // returns a point near thePt which has charge
2892  if(thePt > tj.EndPt[1]) return thePt;
2893  if(tj.Pts[thePt].Chg > 0) return thePt;
2894 
2895  short endPt0 = tj.EndPt[0];
2896  short endPt1 = tj.EndPt[1];
2897  for(short off = 1; off < 10; ++off) {
2898  short ipt = thePt + off;
2899  if(ipt <= endPt1 && tj.Pts[ipt].Chg > 0) return (unsigned short)ipt;
2900  ipt = thePt - off;
2901  if(ipt >= endPt0 && tj.Pts[ipt].Chg > 0) return (unsigned short)ipt;
2902  } // off
2903  return thePt;
2904  } // NearestPtWithChg
int tca::NeutrinoPrimaryTjID ( const TjStuff tjs,
const Trajectory tj 
)

Definition at line 363 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::TjStuff::allTraj, evd::details::end(), kKilled, tca::Trajectory::ParentID, PrimaryID(), tca::TjStuff::vtx, and tca::TjStuff::vtx3.

Referenced by AddTjsInsideEnvelope(), and PrintAllTraj().

364  {
365  // Returns the ID of the grandparent of this tj that is a primary tj that is attached
366  // to the neutrino vertex. 0 is returned if this condition is not met.
367  if(tj.AlgMod[kKilled]) return -1;
368  if(tj.ParentID <= 0) return -1;
369  int primID = PrimaryID(tjs, tj);
370  if(primID <= 0 || primID > (int)tjs.allTraj.size()) return -1;
371 
372  // We have the ID of the primary tj. Now see if it is attached to the neutrino vertex
373  auto& ptj = tjs.allTraj[primID - 1];
374  for(unsigned short end = 0; end < 2; ++end) {
375  if(ptj.VtxID[end] == 0) continue;
376  auto& vx2 = tjs.vtx[ptj.VtxID[end] - 1];
377  if(vx2.Vx3ID == 0) continue;
378  auto& vx3 = tjs.vtx3[vx2.Vx3ID - 1];
379  if(vx3.Neutrino) return primID;
380  } // end
381  return -1;
382  } // NeutrinoPrimaryTjID
int PrimaryID(const TjStuff &tjs, const PFPStruct &pfp)
Definition: Utils.cxx:404
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
unsigned short tca::NumDeltaRays ( const TjStuff tjs,
const Trajectory tj 
)

Definition at line 335 of file Utils.cxx.

References tca::TjStuff::allTraj, tca::Trajectory::ID, kDeltaRay, and kKilled.

336  {
337  // returns the number of delta rays that have this tj as a parent
338  unsigned short cnt = 0;
339  for(auto& dtj : tjs.allTraj) {
340  if(dtj.AlgMod[kKilled]) continue;
341  if(!dtj.AlgMod[kDeltaRay]) continue;
342  if(dtj.ParentID == tj.ID) ++cnt;
343  } // tj
344  return cnt;
345  } // NumDeltaRays
unsigned short tca::NumDeltaRays ( const TjStuff tjs,
std::vector< int > &  tjIDs 
)

Definition at line 348 of file Utils.cxx.

References tca::TjStuff::allTraj, kDeltaRay, and kKilled.

Referenced by PDGCodeVote().

349  {
350  // Count the number of delta-rays that have a Tj in the list of TjIDs as a parent.
351  if(tjIDs.empty()) return 0;
352  if(tjIDs[0] <= 0 || tjIDs[0] > (int)tjs.allTraj.size()) return 0;
353  unsigned short cnt = 0;
354  for(auto& tj : tjs.allTraj) {
355  if(tj.AlgMod[kKilled]) continue;
356  if(!tj.AlgMod[kDeltaRay]) continue;
357  if(std::find(tjIDs.begin(), tjIDs.end(), tj.ParentID) != tjIDs.end()) ++cnt;
358  } // tj
359  return cnt;
360  } // NumDeltaRays
unsigned short tca::NumHitsInTP ( const TrajPoint tp,
HitStatus_t  hitRequest 
)

Definition at line 3677 of file Utils.cxx.

References tca::TrajPoint::Hits, kAllHits, kUsedHits, and tca::TrajPoint::UseHit.

Referenced by tca::TrajClusterAlg::AddHits(), tca::TrajClusterAlg::CheckHiMultUnusedHits(), DotProd(), and tca::TrajClusterAlg::MergeTPHits().

3678  {
3679  // Counts the number of hits of the specified type in tp
3680  if(tp.Hits.empty()) return 0;
3681 
3682  if(hitRequest == kAllHits) return tp.Hits.size();
3683 
3684  unsigned short nhits = 0;
3685  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3686  if(hitRequest == kUsedHits) {
3687  if(tp.UseHit[ii]) ++nhits;
3688  } else {
3689  // looking for unused hits
3690  if(!tp.UseHit[ii]) ++nhits;
3691  }
3692  } // ii
3693  return nhits;
3694  } // NumHitsInTP
unsigned short tca::NumPtsWithCharge ( const TjStuff tjs,
const Trajectory tj,
bool  includeDeadWires 
)

Definition at line 1738 of file Utils.cxx.

References tca::Trajectory::EndPt, and NumPtsWithCharge().

Referenced by AnalyzePFP(), tca::TrajClusterAlg::CheckHiMultUnusedHits(), tca::TrajClusterAlg::CheckTraj(), CompleteIncomplete3DVertices(), tca::TrajClusterAlg::EndMerge(), FillmAllTraj(), FindCots(), FindHammerVertices2(), tca::TrajClusterAlg::FindVtxTraj(), tca::TrajClusterAlg::FixTrajBegin(), tca::TrajClusterAlg::FixTrajEnd(), MergeSubShowersTj(), MergeWithVertex(), tca::TrajClusterAlg::ReconstructAllTraj(), SplitTrajCrossingVertices(), tca::TrajClusterAlg::StepCrawl(), TagShowerLike(), and tca::TrajClusterAlg::UpdateTraj().

1739  {
1740  unsigned short firstPt = tj.EndPt[0];
1741  unsigned short lastPt = tj.EndPt[1];
1742  return NumPtsWithCharge(tjs, tj, includeDeadWires, firstPt, lastPt);
1743  }
unsigned short NumPtsWithCharge(const TjStuff &tjs, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:1746
unsigned short tca::NumPtsWithCharge ( const TjStuff tjs,
const Trajectory tj,
bool  includeDeadWires,
unsigned short  firstPt,
unsigned short  lastPt 
)

Definition at line 1746 of file Utils.cxx.

References DeadWireCount(), and tca::Trajectory::Pts.

Referenced by FitTraj(), MCSMom(), NumPtsWithCharge(), and TrimEndPts().

1747  {
1748  unsigned short ntp = 0;
1749  for(unsigned short ipt = firstPt; ipt <= lastPt; ++ipt) if(tj.Pts[ipt].Chg > 0) ++ntp;
1750  // Add the count of deadwires
1751  if(includeDeadWires) ntp += DeadWireCount(tjs, tj.Pts[firstPt], tj.Pts[lastPt]);
1752  return ntp;
1753  } // NumPtsWithCharge
float DeadWireCount(const TjStuff &tjs, const float &inWirePos1, const float &inWirePos2, CTP_t tCTP)
Definition: Utils.cxx:1762
unsigned short tca::NumUsedHitsInTj ( const TjStuff tjs,
const Trajectory tj 
)

Definition at line 3665 of file Utils.cxx.

References tca::Trajectory::AlgMod, kKilled, and tca::Trajectory::Pts.

Referenced by DotProd().

3666  {
3667  if(tj.AlgMod[kKilled]) return 0;
3668  if(tj.Pts.empty()) return 0;
3669  unsigned short nhits = 0;
3670  for(auto& tp : tj.Pts) {
3671  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) if(tp.UseHit[ii]) ++nhits;
3672  } // tp
3673  return nhits;
3674  } // NumHitsInTj
float tca::OverlapFraction ( TjStuff tjs,
const Trajectory tj1,
const Trajectory tj2 
)

Definition at line 584 of file Utils.cxx.

References tca::Trajectory::Pts.

Referenced by CompatibleMerge(), and tca::TrajClusterAlg::EndMerge().

585  {
586  // returns the fraction of wires spanned by two trajectories
587  float minWire = 1E6;
588  float maxWire = -1E6;
589 
590  float cnt1 = 0;
591  for(auto& tp : tj1.Pts) {
592  if(tp.Chg == 0) continue;
593  if(tp.Pos[0] < 0) continue;
594  if(tp.Pos[0] < minWire) minWire = tp.Pos[0];
595  if(tp.Pos[0] > maxWire) maxWire = tp.Pos[0];
596  ++cnt1;
597  }
598  if(cnt1 == 0) return 0;
599  float cnt2 = 0;
600  for(auto& tp : tj2.Pts) {
601  if(tp.Chg == 0) continue;
602  if(tp.Pos[0] < 0) continue;
603  if(tp.Pos[0] < minWire) minWire = tp.Pos[0];
604  if(tp.Pos[0] > maxWire) maxWire = tp.Pos[0];
605  ++cnt2;
606  }
607  if(cnt2 == 0) return 0;
608  int span = maxWire - minWire;
609  if(span <= 0) return 0;
610  std::vector<unsigned short> wcnt(span);
611  for(auto& tp : tj1.Pts) {
612  if(tp.Chg == 0) continue;
613  if(tp.Pos[0] < -0.4) continue;
614  int indx = std::nearbyint(tp.Pos[0] - minWire);
615  if(indx < 0 || indx > span - 1) continue;
616  ++wcnt[indx];
617  }
618  for(auto& tp : tj2.Pts) {
619  if(tp.Chg == 0) continue;
620  if(tp.Pos[0] < -0.4) continue;
621  int indx = std::nearbyint(tp.Pos[0] - minWire);
622  if(indx < 0 || indx > span - 1) continue;
623  ++wcnt[indx];
624  }
625  float cntOverlap = 0;
626  for(auto cnt : wcnt) if(cnt > 1) ++cntOverlap;
627  if(cnt1 < cnt2) {
628  return cntOverlap / cnt1;
629  } else {
630  return cntOverlap / cnt2;
631  }
632 
633  } // OverlapFraction
float tca::ParentFOM ( std::string  inFcnLabel,
TjStuff tjs,
PFPStruct pfp,
unsigned short  pend,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 2238 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::ShowerStruct3D::CotIDs, tca::TjStuff::cots, FarEnd(), tca::PFPStruct::ID, tca::ShowerStruct3D::ID, ParentFOM(), PosSep2(), ss, and tca::PFPStruct::TjIDs.

2239  {
2240  // Returns an average weighted parent FOM for all trajectories in the pfp being a parent of the 2D showers in ss3
2241  if(ss3.ID == 0) return 1000;
2242  float sum = 0;
2243  float wsum = 0;
2244  std::string fcnLabel = inFcnLabel + ".P3FOM";
2245  float dum1, dum2;
2246  for(auto cid : ss3.CotIDs) {
2247  auto& ss = tjs.cots[cid - 1];
2248  if(ss.ID == 0) continue;
2249  // look for the 3D matched tj in this CTP
2250  int tjid = 0;
2251  for(auto tid : pfp.TjIDs) {
2252  auto& tj = tjs.allTraj[tid - 1];
2253  if(tj.ID == 0) continue;
2254  if(tj.CTP == ss.CTP) tjid = tid;
2255  } // tid
2256  if(tjid == 0) continue;
2257  auto& ptj = tjs.allTraj[tjid - 1];
2258  auto& stj = tjs.allTraj[ss.ShowerTjID - 1];
2259  // determine which end is farthest away from the shower center
2260  unsigned short ptjEnd = FarEnd(tjs, ptj, stj.Pts[1].Pos);
2261  auto& farTP = ptj.Pts[ptj.EndPt[ptjEnd]];
2262  float chgCtrSep2 = PosSep2(farTP.Pos, stj.Pts[1].Pos);
2263  if(chgCtrSep2 < PosSep2(farTP.Pos, stj.Pts[0].Pos) && chgCtrSep2 < PosSep2(farTP.Pos, stj.Pts[2].Pos)) continue;
2264  float fom = ParentFOM(fcnLabel, tjs, ptj, ptjEnd, ss, dum1, dum2, prt);
2265  // ignore failures
2266  if(fom > 50) continue;
2267  // weight by the 1/aspect ratio
2268  float wt = 1;
2269  if(ss.AspectRatio > 0) wt = 1 / ss.AspectRatio;
2270  sum += wt * fom;
2271  wsum += wt;
2272  } // cid
2273  if(wsum == 0) return 100;
2274  float fom = sum / wsum;
2275  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" P"<<pfp.ID<<" fom "<<std::fixed<<std::setprecision(3)<<fom;
2276  return fom;
2277  } // ParentFOM
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float ParentFOM(std::string inFcnLabel, TjStuff &tjs, Trajectory &tj, unsigned short &tjEnd, ShowerStruct &ss, float &tp1Sep, float &vx2Score, bool prt)
Definition: TCShower.cxx:2280
Float_t ss
Definition: plot.C:23
unsigned short FarEnd(const TjStuff &tjs, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:2936
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1631
float tca::ParentFOM ( std::string  inFcnLabel,
TjStuff tjs,
Trajectory tj,
unsigned short &  tjEnd,
ShowerStruct ss,
float &  tp1Sep,
float &  vx2Score,
bool  prt 
)

Definition at line 2280 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::TrajPoint::Ang, tca::ShowerStruct::AspectRatio, ChgFracBetween(), ChgFracNearPos(), DeltaAngle(), tca::TrajPoint::DeltaRMS, tca::TrajPoint::Dir, tca::ShowerStruct::DirectionFOM, tca::Trajectory::EndPt, tca::ShowerStruct::Energy, FarEnd(), FindAlongTrans(), GetAssns(), tca::VtxStore::ID, tca::Trajectory::ID, tca::ShowerStruct::ID, InShowerProbLong(), MakeBareTrajPoint(), tca::VtxStore::Pos, tca::TrajPoint::Pos, PosSep(), PrintPos(), tca::Trajectory::Pts, tca::VtxStore::Score, ShowerParams(), tca::ShowerStruct::ShowerTjID, tca::ShowerStruct::TjIDs, tca::TjStuff::vtx, tca::Trajectory::VtxID, and tca::TjStuff::WirePitch.

Referenced by ParentFOM(), and SetParent().

2281  {
2282  // returns a FOM for the trajectory at the end point being the parent of ss and the end which
2283  // was matched.
2284 
2285  vx2Score = 0;
2286  tp1Sep = 0;
2287 
2288  if(tjEnd > 1) return 1000;
2289  if(ss.Energy == 0) return 1000;
2290 
2291  if(ss.ID == 0) return 1000;
2292  if(ss.TjIDs.empty()) return 1000;
2293  if(ss.ShowerTjID == 0) return 1000;
2294 
2295  std::string fcnLabel = inFcnLabel + ".PFOM";
2296 
2297  if(ss.AspectRatio > 0.5) {
2298  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 2S"<<ss.ID<<" poor AspectRatio "<<ss.AspectRatio<<" FOM not calculated";
2299  return 100;
2300  }
2301 
2302  float fom = 0;
2303  float cnt = 0;
2304  auto& stj = tjs.allTraj[ss.ShowerTjID - 1];
2305  TrajPoint& stp0 = stj.Pts[0];
2306  // Shower charge center TP
2307  TrajPoint& stp1 = stj.Pts[1];
2308  // get the end that is farthest away from the shower center
2309  tjEnd = FarEnd(tjs, tj, stp1.Pos);
2310  // prospective parent TP
2311  TrajPoint& ptp = tj.Pts[tj.EndPt[tjEnd]];
2312  // find the along and trans components in WSE units relative to the
2313  // shower center
2314  Point2_t alongTrans;
2315  FindAlongTrans(stp1.Pos, stp1.Dir, ptp.Pos, alongTrans);
2316  // We can return here if the shower direction is well defined and
2317  // alongTrans[0] is > 0
2318  if(ss.AspectRatio < 0.2 && ss.DirectionFOM < 0.5 && alongTrans[0] > 0) return 100;
2319  tp1Sep = std::abs(alongTrans[0]);
2320  // Find the expected shower start relative to shower max (cm)
2321  double shMaxAlong, shE95Along;
2322  ShowerParams(ss.Energy, shMaxAlong, shE95Along);
2323  double alongcm = tjs.WirePitch * tp1Sep;
2324  // InShowerProbLong expects the longitudinal distance relative to shower max so it
2325  // should be < 0
2326  float prob = InShowerProbLong(ss.Energy, -alongcm);
2327  if(prob < 0.05) return 100;
2328  // The transverse position must certainly be less than the longitudinal distance
2329  // to shower max.
2330  if(alongTrans[1] > shMaxAlong) return 100;
2331  // longitudinal contribution to fom with 1 Xo error error (14 cm)
2332  float longFOM = std::abs(alongcm + shMaxAlong) / 14;
2333  fom += longFOM;
2334  ++cnt;
2335  // transverse contribution
2336  float transFOM = -1;
2337  if(stp0.DeltaRMS > 0) {
2338  transFOM = alongTrans[1] / stp0.DeltaRMS;
2339  fom += transFOM;
2340  ++cnt;
2341  }
2342  // make a tp between the supposed parent TP and the shower center
2343  TrajPoint tp;
2344  if(!MakeBareTrajPoint(tjs, ptp, stp1, tp)) return 100;
2345  // we have three angles to compare. The ptp angle, the shower angle and
2346  // the tp angle.
2347  float dang1 = DeltaAngle(ptp.Ang, stp1.Ang);
2348  float dang1FOM = dang1 / 0.1;
2349  fom += dang1FOM;
2350  ++cnt;
2351  float dang2 = DeltaAngle(ptp.Ang, tp.Ang);
2352  float dang2FOM = dang1 / 0.1;
2353  fom += dang2FOM;
2354  ++cnt;
2355  // the environment near the parent start should be clean.
2356  std::vector<int> tjlist(1);
2357  tjlist[0] = tj.ID;
2358  // check for a vertex at this end and include the vertex tjs if the vertex is close
2359  // to the expected shower max position
2360  float vx2Sep = 0;
2361  // put in a largish FOM value for Tjs that don't have a vertex
2362  float vxFOM = 10;
2363  if(tj.VtxID[tjEnd] > 0) {
2364  VtxStore& vx2 = tjs.vtx[tj.VtxID[tjEnd] - 1];
2365  vx2Sep = PosSep(vx2.Pos, stp1.Pos);
2366  vx2Score = vx2.Score;
2367  tjlist = GetAssns(tjs, "2V", vx2.ID, "T");
2368 // tjlist = GetVtxTjIDs(tjs, vx2);
2369  vxFOM = std::abs(shMaxAlong - vx2Sep) / 20;
2370  } // 2D vertex exists
2371  fom += vxFOM;
2372  ++cnt;
2373  float chgFrac = ChgFracNearPos(tjs, ptp.Pos, tjlist);
2374  float chgFracFOM = (1 - chgFrac) / 0.1;
2375  fom += chgFracFOM;
2376  ++cnt;
2377  // Fraction of wires that have a signal between the parent start and the shower center
2378  float chgFracBtw = ChgFracBetween(tjs, ptp, stp1.Pos[0], false);
2379  float chgFrcBtwFOM = (1 - chgFrac) / 0.05;
2380  fom += chgFrcBtwFOM;
2381  ++cnt;
2382 
2383  // take the average
2384  fom /= cnt;
2385  // divide by the InShowerProbability
2386  fom /= prob;
2387 
2388  if(prt) {
2389  mf::LogVerbatim myprt("TC");
2390  myprt<<fcnLabel;
2391  myprt<<" 2S"<<ss.ID;
2392  myprt<<" T"<<tj.ID<<"_"<<tjEnd<<" Pos "<<PrintPos(tjs, ptp);
2393  myprt<<std::fixed<<std::setprecision(2);
2394  myprt<<" along "<<std::fixed<<std::setprecision(1)<<alongTrans[0]<<" fom "<<longFOM;
2395  myprt<<" trans "<<alongTrans[1]<<" fom "<<transFOM;
2396  myprt<<" prob "<<prob;
2397  myprt<<" dang1 "<<dang1<<" fom "<<dang1FOM;
2398  myprt<<" dang2 "<<dang2<<" fom "<<dang2FOM;
2399  myprt<<" vx2Score "<<vx2Score<<" fom "<<vxFOM;
2400  myprt<<" chgFrac "<<chgFrac<<" fom "<<chgFracFOM;
2401  myprt<<" chgFracBtw "<<chgFracBtw<<" fom "<<chgFrcBtwFOM;
2402  myprt<<" FOM "<<fom;
2403  }
2404  return fom;
2405 
2406  } // ParentFOM
std::string PrintPos(const TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:4738
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
double InShowerProbLong(double showerEnergy, double along)
Definition: TCShower.cxx:2118
float ChgFracBetween(TjStuff &tjs, Point3_t pos1, Point3_t pos2, geo::TPCID tpcid)
Definition: PFPUtils.cxx:2860
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:2751
Float_t ss
Definition: plot.C:23
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1607
unsigned short FarEnd(const TjStuff &tjs, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:2936
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
bool MakeBareTrajPoint(const TjStuff &tjs, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:3493
float ChgFracNearPos(TjStuff &tjs, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2614
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
Definition: TCShower.cxx:2084
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
std::vector< int > GetAssns(const TjStuff &tjs, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4079
unsigned short tca::PDGCodeIndex ( TjStuff tjs,
int  PDGCode 
)

Definition at line 1783 of file Utils.cxx.

Referenced by tca::TruthMatcher::MatchAndSum(), tca::TruthMatcher::MatchTruth(), and tca::TruthMatcher::StudyElectrons().

1784  {
1785  unsigned short pdg = abs(PDGCode);
1786  if(pdg == 11) return 0; // electron
1787  if(pdg == 13) return 1; // muon
1788  if(pdg == 211) return 2; // pion
1789  if(pdg == 321) return 3; // kaon
1790  if(pdg == 2212) return 4; // proton
1791 
1792  return USHRT_MAX;
1793 
1794  } // PDGCodeIndex
int tca::PDGCodeVote ( TjStuff tjs,
std::vector< int > &  tjIDs,
bool  prt 
)

Definition at line 267 of file Utils.cxx.

References tca::TjStuff::allTraj, evd::details::end(), kBragg, kShowerLike, NumDeltaRays(), and TrajLength().

Referenced by DefinePFPParents(), FindPFParticles(), and Match3DVtxTjs().

268  {
269  // Returns the most likely PDGCode for the set of Tjs provided
270  // The PDG codes are:
271  // 0 = your basic track-like trajectory
272  // 11 = Tagged delta-ray
273  // 13 = Tagged muon
274  // 211 = pion-like. There exists a Bragg peak at an end with a vertex
275  // 2212 = proton-like. There exists a Bragg peak at an end without a vertex
276  // BUG the double brace syntax is required to work around clang bug 21629
277  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
278  std::array<int, 5> codeList = {{0, 11, 13, 211, 2212}};
279  unsigned short codeIndex = 0;
280  if(tjIDs.empty()) return codeList[codeIndex];
281 
282  std::array<unsigned short, 5> cnts;
283  cnts.fill(0);
284  // Count Bragg peaks. This assumes that the Tjs are in order...
285  std::array<unsigned short, 2> stopCnt {{0, 0}};
286  float maxLen = 0;
287  for(auto tjid : tjIDs) {
288  if(tjid <= 0 || tjid > (int)tjs.allTraj.size()) continue;
289  auto& tj = tjs.allTraj[tjid - 1];
290  for(unsigned short ii = 0; ii < 5; ++ii) if(tj.PDGCode == codeList[ii]) ++cnts[ii];
291  // count InShower Tjs with PDGCode not set (yet)
292  if(tj.PDGCode != 11 && tj.AlgMod[kShowerLike]) ++cnts[1];
293  for(unsigned short end = 0; end < 2; ++end) if(tj.StopFlag[end][kBragg]) ++stopCnt[end];
294  float len = TrajLength(tj);
295  if(len > maxLen) maxLen = len;
296  } // tjid
297  unsigned maxCnt = 0;
298  // ignore the first PDG code in the list (the default)
299  for(unsigned short ii = 1; ii < 5; ++ii) {
300  if(cnts[ii] > maxCnt) {
301  maxCnt = cnts[ii];
302  codeIndex = ii;
303  }
304  } // ii
305  // check for an inconsistent code
306  bool confused = false;
307  for(unsigned short ii = 1; ii < 5; ++ii) {
308  if(ii == codeIndex) continue;
309  if(cnts[ii] == 0) continue;
310  confused = true;
311  } // ii
312  if(confused) {
313  // Check for a muon called it a proton
314  if(cnts[4] > 0 && stopCnt[2] > 0 && NumDeltaRays(tjs, tjIDs) == 0) {
315  codeIndex = 4;
316  confused = false;
317  }
318  } // confused
319  if(confused) {
320  codeIndex = 0;
321  if(prt) {
322  mf::LogVerbatim myprt("TC");
323  myprt<<"PDGCodeVote: mixed vote on the PDGCode: Tj_PDGCode";
324  for(auto tjid : tjIDs) {
325  if(tjid <= 0 || tjid > (int)tjs.allTraj.size()) continue;
326  auto& tj = tjs.allTraj[tjid - 1];
327  myprt<<" "<<tj.ID<<"_"<<tj.PDGCode<<"_"<<tj.StopFlag[1][kBragg];
328  } // tjid
329  }
330  } // confused
331  return codeList[codeIndex];
332  } // PDGCodeVote
unsigned short NumDeltaRays(const TjStuff &tjs, std::vector< int > &tjIDs)
Definition: Utils.cxx:348
float TrajLength(Trajectory &tj)
Definition: Utils.cxx:2204
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
float tca::PFPDOCA ( const PFPStruct pfp1,
const PFPStruct pfp2,
unsigned short &  close1,
unsigned short &  close2 
)

Definition at line 1761 of file PFPUtils.cxx.

References PosSep2(), and tca::PFPStruct::Tp3s.

Referenced by DefineDontCluster(), DotProd(), and FindCots().

1762  {
1763  // returns the Distance of Closest Approach between two PFParticles.
1764  close1 = USHRT_MAX;
1765  close2 = USHRT_MAX;
1766  float minSep2 = 1E8;
1767  for(unsigned short ipt1 = 0; ipt1 < pfp1.Tp3s.size(); ++ipt1) {
1768  auto& tp1 = pfp1.Tp3s[ipt1];
1769  for(unsigned short ipt2 = 0; ipt2 < pfp2.Tp3s.size(); ++ipt2) {
1770  auto& tp2 = pfp2.Tp3s[ipt2];
1771  float sep2 = PosSep2(tp1.Pos, tp2.Pos);
1772  if(sep2 > minSep2) continue;
1773  minSep2 = sep2;
1774  close1 = ipt1;
1775  close2 = ipt2;
1776  } // tp2
1777  } // tp1
1778  return sqrt(minSep2);
1779  } // PFPDOCA
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1631
void tca::PFPVertexCheck ( TjStuff tjs)

Definition at line 2418 of file PFPUtils.cxx.

References tca::Vtx3Store::ID, tca::TjStuff::pfps, tca::Vtx3Store::Primary, tca::Vtx3Store::TPCID, geo::TPCID::TPCID(), tca::TjStuff::vtx3, tca::Vtx3Store::Wire, tca::Vtx3Store::X, tca::Vtx3Store::Y, and tca::Vtx3Store::Z.

Referenced by DotProd(), and tca::TrajClusterAlg::RunTrajClusterAlg().

2419  {
2420  // Ensure that all PFParticles have a start vertex. It is possible for
2421  // PFParticles to be attached to a 3D vertex that is later killed.
2422  for(auto& pfp : tjs.pfps) {
2423  if(pfp.ID == 0) continue;
2424  if(pfp.Vx3ID[0] > 0) continue;
2425  Vtx3Store vx3;
2426  vx3.TPCID = pfp.TPCID;
2427  // Flag it as a PFP vertex that isn't required to have matched 2D vertices
2428  vx3.Wire = -2;
2429  vx3.X = pfp.XYZ[0][0];
2430  vx3.Y = pfp.XYZ[0][1];
2431  vx3.Z = pfp.XYZ[0][2];
2432  vx3.ID = tjs.vtx3.size() + 1;
2433  vx3.Primary = false;
2434  tjs.vtx3.push_back(vx3);
2435 // std::cout<<"PFPVertexCheck: P"<<pfp.ID<<" create 3V"<<vx3.ID<<"\n";
2436  pfp.Vx3ID[0] = vx3.ID;
2437  } // pfp
2438  } // PFPVertexCheck
bool tca::PFPVxTjOK ( TjStuff tjs,
PFPStruct pfp,
bool  prt 
)

Definition at line 2283 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, GetVtxTjIDs(), tca::PFPStruct::ID, SetIntersection(), tca::PFPStruct::TjIDs, tmp, tca::TjStuff::vtx, tca::TjStuff::vtx3, and tca::PFPStruct::Vx3ID.

Referenced by AddMissedTj(), AnalyzePFP(), DefinePFP(), and DotProd().

2284  {
2285  // Checks the PFP Vx3 -> Vx2 -> Tj assignment to see if there is more
2286  // than one tj in a plane in the pfp.TjIDs list that is attached to the same 2D vertex.
2287  // This problem is fixed by removing the shorter tj from the TjIDs list. This function
2288  // return true if nothing was done to TjIDs
2289  if(pfp.ID == 0) return true;
2290  if(pfp.TjIDs.empty()) return true;
2291  if(pfp.Vx3ID[0] == 0) return true;
2292 
2293  auto& vx3 = tjs.vtx3[pfp.Vx3ID[0] - 1];
2294  std::vector<int> killMe;
2295  for(auto vx2id : vx3.Vx2ID) {
2296  if(vx2id == 0) continue;
2297  if(vx2id == 666) continue;
2298  auto& vx2 = tjs.vtx[vx2id - 1];
2299  auto tjlist = GetVtxTjIDs(tjs, vx2);
2300  auto setInt = SetIntersection(pfp.TjIDs, tjlist);
2301 /*
2302  std::cout<<"PVTC: P"<<pfp.ID<<" Tjs";
2303  for(auto tid : pfp.TjIDs) std::cout<<" T"<<tid;
2304  std::cout<<" set Intersection";
2305  for(auto tid : setInt) std::cout<<" T"<<tid;
2306  std::cout<<"\n";
2307 */
2308  if(setInt.size() < 2) continue;
2309  // find the longest one
2310  int imLong = 0;
2311  unsigned short lenth = 0;
2312  for(auto tid : setInt) {
2313  auto& tj = tjs.allTraj[tid - 1];
2314  unsigned short npts = tj.EndPt[1] - tj.EndPt[0] + 1;
2315  if(npts < lenth) continue;
2316  lenth = npts;
2317  imLong = tj.ID;
2318  } // tid
2319  if(imLong == 0) continue;
2320  // add the others to the killMe list
2321  for(auto tid : setInt) if(tid != imLong) killMe.push_back(tid);
2322  } // vx2id
2323  if(killMe.empty()) return true;
2324  if(prt) {
2325  mf::LogVerbatim myprt("TC");
2326  myprt<<"PVTC: P"<<pfp.ID<<" removing short tjs attached to a vertex:";
2327  for(auto tid : killMe) myprt<<" T"<<tid;
2328  }
2329  // re-create the TjIDs vector
2330  std::vector<int> tmp;
2331  for(auto tid : pfp.TjIDs) {
2332  if(std::find(killMe.begin(), killMe.end(), tid) == killMe.end()) tmp.push_back(tid);
2333  } // tid
2334  pfp.TjIDs = tmp;
2335  return false;
2336  } // PFPVxTjOK
Float_t tmp
Definition: plot.C:37
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:214
std::vector< int > GetVtxTjIDs(const TjStuff &tjs, const VtxStore &vx2)
Definition: TCVertex.cxx:3022
Vector3_t tca::PointDirection ( const Point3_t  p1,
const Point3_t  p2 
)

Definition at line 1614 of file PFPUtils.cxx.

References dir, and SetMag().

Referenced by ChgFracBetween(), CreateFakePFP(), DefineDontCluster(), DotProd(), FindAlongTrans(), FindParent(), FollowTp3s(), tca::TruthMatcher::StudyShowerParents(), and UpdateShower().

1615  {
1616  // Finds the direction vector between the two points from p1 to p2
1617  Vector3_t dir;
1618  for(unsigned short xyz = 0; xyz < 3; ++xyz) dir[xyz] = p2[xyz] - p1[xyz];
1619  if(dir[0] == 0 && dir[1] == 0 && dir[2] == 0) return dir;
1620  if(!SetMag(dir, 1)) { dir[0] = 0; dir[1] = 0; dir[3] = 0; }
1621  return dir;
1622  } // PointDirection
bool SetMag(Vector3_t &v1, double mag)
Definition: PFPUtils.cxx:1641
TDirectory * dir
Definition: macro.C:5
std::array< double, 3 > Vector3_t
Definition: DataStructs.h:36
Vector2_t tca::PointDirection ( const Point2_t  p1,
const Point2_t  p2 
)

Definition at line 3563 of file Utils.cxx.

References dir, and norm.

Referenced by MakeBareTrajPoint().

3564  {
3565  // Finds the direction vector between the two points from p1 to p2
3566  Vector2_t dir;
3567  for(unsigned short xyz = 0; xyz < 2; ++xyz) dir[xyz] = p2[xyz] - p1[xyz];
3568  if(dir[0] == 0 && dir[1] == 0) return dir;
3569  double norm = sqrt(dir[0] * dir[0] + dir[1] * dir[1]);
3570  dir[0] /= norm;
3571  dir[1] /= norm;
3572  return dir;
3573  } // PointDirection
std::array< double, 2 > Vector2_t
Definition: DataStructs.h:38
Float_t norm
TDirectory * dir
Definition: macro.C:5
bool tca::PointDirIntersect ( Point3_t  p1,
Vector3_t  p1Dir,
Point3_t  p2,
Vector3_t  p2Dir,
Point3_t intersect,
float &  doca 
)

Definition at line 2769 of file PFPUtils.cxx.

References LineLineIntersect().

Referenced by DotProd(), and FindNeutralVertices().

2770  {
2771  // Point - vector version
2772  Point3_t p1End, p2End;
2773  for(unsigned short xyz = 0; xyz < 3; ++xyz) {
2774  p1End[xyz] = p1[xyz] + 10 * p1Dir[xyz];
2775  p2End[xyz] = p2[xyz] + 10 * p2Dir[xyz];
2776  }
2777  return LineLineIntersect(p1, p1End, p2, p2End, intersect, doca);
2778  } // PointDirIntersect
std::array< double, 3 > Point3_t
Definition: DataStructs.h:35
bool LineLineIntersect(Point3_t p1, Point3_t p2, Point3_t p3, Point3_t p4, Point3_t &intersect, float &doca)
Definition: PFPUtils.cxx:2781
bool tca::PointInsideEnvelope ( const Point2_t Point,
const std::vector< Point2_t > &  Envelope 
)

Definition at line 2705 of file Utils.cxx.

References DeltaAngle().

Referenced by AddLooseHits(), AddTjsInsideEnvelope(), FindNearbyTjs(), KillVerticesInShower(), and MergeOverlap().

2706  {
2707  // returns true if the Point is within the Envelope polygon. Entries in Envelope are the
2708  // Pos[0], Pos[1] locations of the polygon vertices. This is based on the algorithm that the
2709  // sum of the angles of a vector between a point and the vertices will be 2 * pi for an interior
2710  // point and 0 for an exterior point
2711 
2712  Point2_t p1, p2;
2713  unsigned short nvx = Envelope.size();
2714  double angleSum = 0;
2715  for(unsigned short ii = 0; ii < Envelope.size(); ++ii) {
2716  p1[0] = Envelope[ii][0] - Point[0];
2717  p1[1] = Envelope[ii][1] - Point[1];
2718  p2[0] = Envelope[(ii+1)%nvx][0] - Point[0];
2719  p2[1] = Envelope[(ii+1)%nvx][1] - Point[1];
2720  angleSum += DeltaAngle(p1, p2);
2721  }
2722  if(abs(angleSum) < M_PI) return false;
2723  return true;
2724 
2725  } // InsideEnvelope
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:34
double DeltaAngle(double Ang1, double Ang2)
Definition: Utils.cxx:2782
float tca::PointTrajDOCA ( TjStuff const &  tjs,
unsigned int  iht,
TrajPoint const &  tp 
)
float tca::PointTrajDOCA ( TjStuff const &  tjs,
float  wire,
float  time,
TrajPoint const &  tp 
)

Definition at line 2147 of file Utils.cxx.

References PointTrajDOCA2().

Referenced by CompatibleMerge(), FindCloseHits(), MaxHitDelta(), and TagDeltaRays().

2148  {
2149  return sqrt(PointTrajDOCA2(tjs, wire, time, tp));
2150  } // PointTrajDOCA
float PointTrajDOCA2(TjStuff const &tjs, float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2153
float tca::PointTrajDOCA2 ( TjStuff const &  tjs,
float  wire,
float  time,
TrajPoint const &  tp 
)

Definition at line 2153 of file Utils.cxx.

References tca::TrajPoint::Dir, and tca::TrajPoint::Pos.

Referenced by PointTrajDOCA(), and TjDeltaRMS().

2154  {
2155  // returns the distance of closest approach squared between a (wire, time(WSE)) point
2156  // and a trajectory point
2157 
2158  float t = (wire - tp.Pos[0]) * tp.Dir[0] + (time - tp.Pos[1]) * tp.Dir[1];
2159  float dw = tp.Pos[0] + t * tp.Dir[0] - wire;
2160  float dt = tp.Pos[1] + t * tp.Dir[1] - time;
2161  return (dw * dw + dt * dt);
2162 
2163  } // PointTrajDOCA2
float tca::PointTrajSep2 ( float  wire,
float  time,
TrajPoint const &  tp 
)

Definition at line 2131 of file Utils.cxx.

References tca::TrajPoint::Pos.

2132  {
2133  float dw = wire - tp.Pos[0];
2134  float dt = time - tp.Pos[1];
2135  return dw * dw + dt * dt;
2136  }
void tca::PosInPlane ( const TjStuff tjs,
const Vtx3Store vx3,
unsigned short  plane,
Point2_t pos 
)

Definition at line 3083 of file TCVertex.cxx.

References detinfo::DetectorProperties::ConvertXToTicks(), geo::CryostatID::Cryostat, tca::TjStuff::detprop, tca::TjStuff::geom, geo::TPCID::TPC, tca::Vtx3Store::TPCID, tca::TjStuff::UnitsPerTick, geo::GeometryCore::WireCoordinate(), tca::Vtx3Store::X, tca::Vtx3Store::Y, and tca::Vtx3Store::Z.

Referenced by AttachPFPToVertex(), and PrintAllTraj().

3084  {
3085  // returns the 2D position of the vertex in the plane
3086  pos[0] = tjs.geom->WireCoordinate(vx3.Y, vx3.Z, plane, vx3.TPCID.TPC, vx3.TPCID.Cryostat);
3087  pos[1] = tjs.detprop->ConvertXToTicks(vx3.X, plane, vx3.TPCID.TPC, vx3.TPCID.Cryostat) * tjs.UnitsPerTick;
3088 
3089  } // PosInPlane
float tca::PosSep ( const Point2_t pos1,
const Point2_t pos2 
)

Definition at line 2220 of file Utils.cxx.

References PosSep2().

Referenced by CompatibleMerge(), PrintPFP(), TagDeltaRays(), and TjDirFOM().

2221  {
2222  return sqrt(PosSep2(pos1, pos2));
2223  } // PosSep
float PosSep2(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2226
double tca::PosSep2 ( const Point3_t pos1,
const Point3_t pos2 
)

Definition at line 1631 of file PFPUtils.cxx.

Referenced by AttachTrajToVertex(), DotProd(), tca::TrajClusterAlg::EndMerge(), FarEnd(), Find2DVertices(), FindKinks(), FindParent(), FitTp3(), FollowTp3s(), KinkAngle(), LengthInCTP(), tca::TrajClusterAlg::MakeAllTrajClusters(), MergeOverlap(), ParentFOM(), PFPDOCA(), PosSep(), tca::MCParticleListUtils::PrimaryElectronPFPID(), tca::TrajClusterAlg::StepCrawl(), tca::TruthMatcher::StudyShowerParents(), TrajPointVertexPull(), UpdateShower(), and tca::TrajClusterAlg::UseUnusedHits().

1632  {
1633  // returns the separation distance^2 between two positions in 3D
1634  double d0 = pos1[0] - pos2[0];
1635  double d1 = pos1[1] - pos2[1];
1636  double d2 = pos1[2] - pos2[2];
1637  return d0*d0 + d1*d1 + d2*d2;
1638  } // PosSep2
float tca::PosSep2 ( const Point2_t pos1,
const Point2_t pos2 
)

Definition at line 2226 of file Utils.cxx.

Referenced by CloseEnd(), FarEnd(), MaxTjLen(), MergeAndStore(), and PosSep().

2227  {
2228  // returns the separation distance^2 between two positions
2229  float d0 = pos1[0] - pos2[0];
2230  float d1 = pos1[1] - pos2[1];
2231  return d0*d0+d1*d1;
2232  } // PosSep2
int tca::PrimaryID ( const TjStuff tjs,
const Trajectory tj 
)

Definition at line 385 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::TjStuff::allTraj, tca::Trajectory::ID, kKilled, and tca::Trajectory::ParentID.

386  {
387  // Returns the ID of the grandparent trajectory of this trajectory that is a primary
388  // trajectory (i.e. whose ParentID = 0).
389  if(tj.AlgMod[kKilled]) return -1;
390  if(tj.ParentID < 0 || tj.ParentID > (int)tjs.allTraj.size()) return -1;
391  if(tj.ParentID == 0) return tj.ID;
392  int parid = tj.ParentID;
393  for(unsigned short nit = 0; nit < 10; ++nit) {
394  if(parid < 1 || parid > (int)tjs.allTraj.size()) break;
395  auto& tj = tjs.allTraj[parid - 1];
396  if(tj.ParentID < 0 || tj.ParentID > (int)tjs.allTraj.size()) return -1;
397  if(tj.ParentID == 0) return tj.ID;
398  parid = tj.ParentID;
399  } // nit
400  return -1;
401  } // PrimaryID
int tca::PrimaryID ( const TjStuff tjs,
const PFPStruct pfp 
)

Definition at line 404 of file Utils.cxx.

References tca::PFPStruct::ID, tca::PFPStruct::ParentID, and tca::TjStuff::pfps.

Referenced by NeutrinoPrimaryTjID(), PrintAllTraj(), and PrintPFP().

405  {
406  // returns the ID of the most upstream PFParticle (that is not a neutrino)
407 
408  if(int(pfp.ParentID) == pfp.ID || pfp.ParentID <= 0) return pfp.ID;
409  int parid = pfp.ParentID;
410  int dtrid = pfp.ID;
411  unsigned short nit = 0;
412  while(true) {
413  auto& parent = tjs.pfps[parid - 1];
414  // found a neutrino
415  if(parent.PDGCode == 14 || parent.PDGCode == 12) return dtrid;
416  // found a primary PFParticle?
417  if(parent.ParentID == 0) return parent.ID;
418  if(int(parent.ParentID) == parent.ID) return parent.ID;
419  dtrid = parent.ID;
420  parid = parent.ParentID;
421  if(parid < 0) return 0;
422  ++nit;
423  if(nit == 10) return 0;
424  }
425  } // PrimaryID
void tca::Print2DShowers ( std::string  someText,
const TjStuff tjs,
CTP_t  inCTP,
bool  printKilledShowers 
)

Definition at line 4713 of file TCShower.cxx.

References tca::TjStuff::cots, tca::TjStuff::dontCluster, DontCluster(), nlines, PrintShower(), tca::TjStuff::ShowerTag, ss, util::flags::to_string(), and tca::TjStuff::UnitsPerTick.

Referenced by FindShowers3D(), Reconcile3D(), and tca::TrajClusterAlg::RunTrajClusterAlg().

4714  {
4715  // Prints a one-line summary of 2D showers
4716  if(tjs.cots.empty()) return;
4717 
4718  mf::LogVerbatim myprt("TC");
4719 
4720  // see how many lines were are going to print
4721  bool printAllCTP = (inCTP == USHRT_MAX);
4722  if(!printAllCTP) {
4723  unsigned short nlines = 0;
4724  for(const auto& ss : tjs.cots) {
4725  if(!printAllCTP && ss.CTP != inCTP) continue;
4726  if(!printKilledShowers && ss.ID == 0) continue;
4727  ++nlines;
4728  } // ss
4729  if(nlines == 0) {
4730  myprt<<someText<<" Print2DShowers: Nothing to print";
4731  return;
4732  }
4733  } // !printAllCTP
4734 
4735  bool printHeader = true;
4736  bool printExtras = false;
4737  for(unsigned short ict = 0; ict < tjs.cots.size(); ++ict) {
4738  const auto& ss = tjs.cots[ict];
4739  if(!printAllCTP && ss.CTP != inCTP) continue;
4740  if(!printKilledShowers && ss.ID == 0) continue;
4741  PrintShower(someText, tjs, ss, printHeader, printExtras);
4742  printHeader = false;
4743  } // ss
4744  if(tjs.ShowerTag[12] > 9) {
4745  // List of Tjs
4746  for(unsigned short ict = 0; ict < tjs.cots.size(); ++ict) {
4747  const auto& ss = tjs.cots[ict];
4748  if(!printAllCTP && ss.CTP != inCTP) continue;
4749  if(!printKilledShowers && ss.ID == 0) continue;
4750  myprt<<someText<<std::fixed;
4751  std::string sid = "2S" + std::to_string(ss.ID);
4752  myprt<<std::setw(5)<<sid;
4753  myprt<<" Tjs";
4754  for(auto id : ss.TjIDs) myprt<<" T"<<id;
4755  myprt<<"\n";
4756  } // ict
4757 
4758  }
4759  // Print the envelopes
4760  for(unsigned short ict = 0; ict < tjs.cots.size(); ++ict) {
4761  const auto& ss = tjs.cots[ict];
4762  if(!printAllCTP && ss.CTP != inCTP) continue;
4763  if(!printKilledShowers && ss.ID == 0) continue;
4764  myprt<<someText<<std::fixed;
4765  std::string sid = "2S" + std::to_string(ss.ID);
4766  myprt<<std::setw(5)<<sid;
4767  myprt<<" Envelope";
4768  for(auto& vtx : ss.Envelope) myprt<<" "<<(int)vtx[0]<<":"<<(int)(vtx[1]/tjs.UnitsPerTick);
4769  myprt<<"\n";
4770  } // ict
4771  // List of nearby Tjs
4772  for(unsigned short ict = 0; ict < tjs.cots.size(); ++ict) {
4773  const auto& ss = tjs.cots[ict];
4774  if(!printAllCTP && ss.CTP != inCTP) continue;
4775  if(!printKilledShowers && ss.ID == 0) continue;
4776  myprt<<someText<<std::fixed;
4777  std::string sid = "2S" + std::to_string(ss.ID);
4778  myprt<<std::setw(5)<<sid;
4779  myprt<<" Nearby";
4780  for(auto id : ss.NearTjIDs) myprt<<" T"<<id;
4781  myprt<<"\n";
4782  } // ict
4783  // don't cluster list
4784  myprt<<"DontCluster";
4785  for(auto& dc : tjs.dontCluster) {
4786  if(dc.TjIDs[0] > 0) myprt<<" T"<<dc.TjIDs[0]<<"-T"<<dc.TjIDs[1];
4787  } // dc
4788  myprt<<"\nDontCluster";
4789  for(unsigned short ict = 0; ict < tjs.cots.size(); ++ict) {
4790  const auto& iss = tjs.cots[ict];
4791  if(iss.ID == 0) continue;
4792  for(unsigned short jct = ict + 1; jct < tjs.cots.size(); ++jct) {
4793  const auto& jss = tjs.cots[jct];
4794  if(jss.ID == 0) continue;
4795  if(DontCluster(tjs, iss.TjIDs, jss.TjIDs)) myprt<<" 2S"<<iss.ID<<"-2S"<<jss.ID;
4796  } // jct
4797  } // ict
4798  } // Print2DShowers
Float_t ss
Definition: plot.C:23
nlines
void PrintShower(std::string someText, const TjStuff &tjs, const ShowerStruct &ss, bool printHeader, bool printExtras)
Definition: TCShower.cxx:4801
bool DontCluster(const TjStuff &tjs, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3381
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Definition: BitMask.h:187
void tca::PrintAllTraj ( std::string  someText,
const TjStuff tjs,
const DebugStuff debug,
unsigned short  itj,
unsigned short  ipt,
bool  prtVtx 
)

Definition at line 4232 of file Utils.cxx.

References AlgBitNames, tca::TjStuff::allTraj, geo::CryostatID::Cryostat, DecodeCTP(), evd::details::end(), GetAssns(), tca::Vtx3Store::ID, kAtKink, kAtTj, kAtVtx, kBragg, kEnvNearTj, kKilled, kVtxTruMatch, tca::TjStuff::MCPartList, tca::Vtx3Store::Neutrino, NeutrinoPrimaryTjID(), tca::TjStuff::NumPlanes, tca::TjStuff::pfps, tca::DebugStuff::Plane, geo::PlaneID::Plane, PosInPlane(), tca::Vtx3Store::Primary, PrimaryID(), PrintHeader(), PrintPos(), PrintTrajPoint(), art::right(), tca::Vtx3Store::Score, tca::TjStuff::StepDir, tmp, util::flags::to_string(), geo::TPCID::TPC, tca::Vtx3Store::TPCID, tca::TjStuff::UnitsPerTick, tca::TjStuff::vtx, tca::TjStuff::vtx3, VtxBitNames, tca::Vtx3Store::Vx2ID, tca::Vtx3Store::Wire, tca::Vtx3Store::X, tca::Vtx3Store::XErr, tca::Vtx3Store::Y, tca::Vtx3Store::YErr, tca::Vtx3Store::Z, and tca::Vtx3Store::ZErr.

Referenced by DotProd(), Find2DVertices(), Find3DVertices(), FindShowers3D(), and tca::TrajClusterAlg::RunTrajClusterAlg().

4233  {
4234 
4235  mf::LogVerbatim myprt("TC");
4236 
4237  if(prtVtx) {
4238  if(!tjs.vtx3.empty()) {
4239  // print out 3D vertices
4240  myprt<<someText<<"****** 3D vertices ******************************************__2DVtx_ID__*******\n";
4241  myprt<<someText<<" Vtx Cstat TPC X Y Z XEr YEr ZEr pln0 pln1 pln2 Wire score Prim? Nu? nTru";
4242  myprt<<" ___________2D_Pos____________ _____Tjs________\n";
4243  for(unsigned short iv = 0; iv < tjs.vtx3.size(); ++iv) {
4244  if(tjs.vtx3[iv].ID == 0) continue;
4245  const Vtx3Store& vx3 = tjs.vtx3[iv];
4246  myprt<<someText;
4247  std::string vid = "3V" + std::to_string(vx3.ID);
4248  myprt<<std::right<<std::setw(5)<<std::fixed<<vid;
4249  myprt<<std::setprecision(1);
4250  myprt<<std::right<<std::setw(7)<<vx3.TPCID.Cryostat;
4251  myprt<<std::right<<std::setw(5)<<vx3.TPCID.TPC;
4252  myprt<<std::right<<std::setw(8)<<vx3.X;
4253  myprt<<std::right<<std::setw(8)<<vx3.Y;
4254  myprt<<std::right<<std::setw(8)<<vx3.Z;
4255  myprt<<std::right<<std::setw(5)<<vx3.XErr;
4256  myprt<<std::right<<std::setw(5)<<vx3.YErr;
4257  myprt<<std::right<<std::setw(5)<<vx3.ZErr;
4258  myprt<<std::right<<std::setw(5)<<vx3.Vx2ID[0];
4259  myprt<<std::right<<std::setw(5)<<vx3.Vx2ID[1];
4260  myprt<<std::right<<std::setw(5)<<vx3.Vx2ID[2];
4261  myprt<<std::right<<std::setw(5)<<vx3.Wire;
4262  unsigned short nTruMatch = 0;
4263  for(unsigned short ipl = 0; ipl < tjs.NumPlanes; ++ipl) {
4264  if(vx3.Vx2ID[ipl] == 0) continue;
4265  unsigned short iv2 = vx3.Vx2ID[ipl] - 1;
4266  if(tjs.vtx[iv2].Stat[kVtxTruMatch]) ++nTruMatch;
4267  } // ipl
4268  myprt<<std::right<<std::setw(6)<<std::setprecision(1)<<vx3.Score;
4269  myprt<<std::setw(6)<<vx3.Primary;
4270  myprt<<std::setw(4)<<vx3.Neutrino;
4271  myprt<<std::right<<std::setw(5)<<nTruMatch;
4272  Point2_t pos;
4273  for(unsigned short plane = 0; plane < tjs.NumPlanes; ++plane) {
4274  PosInPlane(tjs, vx3, plane, pos);
4275  myprt<<" "<<PrintPos(tjs, pos);
4276  } // plane
4277  if(vx3.Wire == -2) {
4278  // find the Tjs that are attached to it
4279  for(auto& pfp : tjs.pfps) {
4280  if(pfp.Vx3ID[0] == tjs.vtx3[iv].ID) {
4281  for(auto& tjID : pfp.TjIDs) myprt<<" T"<<tjID;
4282  }
4283  if(pfp.Vx3ID[1] == tjs.vtx3[iv].ID) {
4284  for(auto& tjID : pfp.TjIDs) myprt<<" T"<<tjID;
4285  }
4286  } // ipfp
4287  } else {
4288  auto vxtjs = GetAssns(tjs, "3V", vx3.ID, "T");
4289  for(auto tjid : vxtjs) myprt<<" T"<<tjid;
4290  }
4291  myprt<<"\n";
4292  }
4293  } // tjs.vtx3.size
4294  if(!tjs.vtx.empty()) {
4295  bool foundOne = false;
4296  for(unsigned short iv = 0; iv < tjs.vtx.size(); ++iv) {
4297  auto& vx2 = tjs.vtx[iv];
4298  if(debug.Plane < 3 && debug.Plane != (int)DecodeCTP(vx2.CTP).Plane) continue;
4299  if(vx2.NTraj == 0) continue;
4300  foundOne = true;
4301  } // iv
4302  if(foundOne) {
4303  // print out 2D vertices
4304  myprt<<someText<<"************ 2D vertices ************\n";
4305  myprt<<someText<<" Vtx CTP wire err tick err ChiDOF NTj Pass Topo ChgFrac Score v3D TjIDs\n";
4306  for(auto& vx2 : tjs.vtx) {
4307  if(vx2.ID == 0) continue;
4308  if(debug.Plane < 3 && debug.Plane != (int)DecodeCTP(vx2.CTP).Plane) continue;
4309  myprt<<someText;
4310  std::string vid = "2V" + std::to_string(vx2.ID);
4311  myprt<<std::right<<std::setw(5)<<std::fixed<<vid;
4312  myprt<<std::right<<std::setw(6)<<vx2.CTP;
4313  myprt<<std::right<<std::setw(8)<<std::setprecision(0)<<std::nearbyint(vx2.Pos[0]);
4314  myprt<<std::right<<std::setw(5)<<std::setprecision(1)<<vx2.PosErr[0];
4315  myprt<<std::right<<std::setw(8)<<std::setprecision(0)<<std::nearbyint(vx2.Pos[1]/tjs.UnitsPerTick);
4316  myprt<<std::right<<std::setw(5)<<std::setprecision(1)<<vx2.PosErr[1]/tjs.UnitsPerTick;
4317  myprt<<std::right<<std::setw(7)<<vx2.ChiDOF;
4318  myprt<<std::right<<std::setw(5)<<vx2.NTraj;
4319  myprt<<std::right<<std::setw(5)<<vx2.Pass;
4320  myprt<<std::right<<std::setw(6)<<vx2.Topo;
4321  myprt<<std::right<<std::setw(9)<<std::setprecision(2)<<vx2.TjChgFrac;
4322  myprt<<std::right<<std::setw(6)<<std::setprecision(1)<<vx2.Score;
4323  myprt<<std::right<<std::setw(5)<<vx2.Vx3ID;
4324  myprt<<" ";
4325  // display the traj IDs
4326  for(unsigned short ii = 0; ii < tjs.allTraj.size(); ++ii) {
4327  auto const& aTj = tjs.allTraj[ii];
4328  if(debug.Plane < 3 && debug.Plane != (int)DecodeCTP(aTj.CTP).Plane) continue;
4329  if(aTj.AlgMod[kKilled]) continue;
4330  for(unsigned short end = 0; end < 2; ++end) {
4331  if(aTj.VtxID[end] != (short)vx2.ID) continue;
4332  std::string tid = " T" + std::to_string(aTj.ID) + "_" + std::to_string(end);
4333  myprt<<std::right<<std::setw(6)<<tid;
4334  } // end
4335  } // ii
4336  // Special flags. Ignore the first flag bit (0 = kVtxTrjTried) which is done for every vertex
4337  for(unsigned short ib = 1; ib < VtxBitNames.size(); ++ib) if(vx2.Stat[ib]) myprt<<" "<<VtxBitNames[ib];
4338  myprt<<"\n";
4339  } // iv
4340  }
4341  } // tjs.vtx.size
4342  }
4343 
4344  if(tjs.allTraj.empty()) {
4345  mf::LogVerbatim("TC")<<someText<<" No allTraj trajectories to print";
4346  return;
4347  }
4348 
4349  // Print all trajectories in tjs.allTraj if itj == USHRT_MAX
4350  // Print a single traj (itj) and a single TP (ipt) or all TPs (USHRT_MAX)
4351  if(itj == USHRT_MAX) {
4352  // Print summary trajectory information
4353  std::vector<unsigned int> tmp;
4354 // myprt<<someText<<" TRJ ID CTP Pass Pts W:T Ang CS AveQ dEdx W:T Ang CS AveQ dEdx Chg(k) chgRMS Mom SDr __Vtx__ PDG Par Pri NuPar TRuPDG E*P TruKE WorkID \n";
4355  myprt<<someText<<" ID CTP Pass Pts W:T Ang CS AveQ fnTj W:T Ang CS AveQ fnTj Chg(k) chgRMS Mom SDr __Vtx__ PDG DirFOM Par Pri NuPar TRuPDG E*P TruKE WorkID \n";
4356  for(unsigned short ii = 0; ii < tjs.allTraj.size(); ++ii) {
4357  auto& aTj = tjs.allTraj[ii];
4358  if(debug.Plane >=0 && debug.Plane < 3 && debug.Plane != (int)DecodeCTP(aTj.CTP).Plane) continue;
4359  myprt<<someText<<" ";
4360  std::string tid;
4361  if(aTj.AlgMod[kKilled]) { tid = "k" + std::to_string(aTj.ID); } else { tid = "T" + std::to_string(aTj.ID); }
4362  myprt<<std::fixed<<std::setw(5)<<tid;
4363  myprt<<std::setw(6)<<aTj.CTP;
4364  myprt<<std::setw(5)<<aTj.Pass;
4365 // myprt<<std::setw(5)<<aTj.Pts.size();
4366  myprt<<std::setw(5)<<aTj.EndPt[1] - aTj.EndPt[0] + 1;
4367  unsigned short endPt0 = aTj.EndPt[0];
4368  auto& tp0 = aTj.Pts[endPt0];
4369  int itick = tp0.Pos[1]/tjs.UnitsPerTick;
4370  if(itick < 0) itick = 0;
4371  myprt<<std::setw(6)<<(int)(tp0.Pos[0]+0.5)<<":"<<itick; // W:T
4372  if(itick < 10) { myprt<<" "; }
4373  if(itick < 100) { myprt<<" "; }
4374  if(itick < 1000) { myprt<<" "; }
4375  myprt<<std::setw(6)<<std::setprecision(2)<<tp0.Ang;
4376  myprt<<std::setw(2)<<tp0.AngleCode;
4377  if(aTj.StopFlag[0][kBragg]) {
4378  myprt<<"B";
4379  } else if(aTj.StopFlag[0][kAtVtx]) {
4380  myprt<<"V";
4381  } else if(aTj.StopFlag[0][kAtKink]) {
4382  myprt<<"K";
4383  } else if(aTj.StopFlag[0][kAtTj]) {
4384  myprt<<"T";
4385  } else {
4386  myprt<<" ";
4387  }
4388  myprt<<std::setw(5)<<(int)tp0.AveChg;
4389  // Print the fraction of points in the first half that are in a shower
4390  float frac = 0;
4391  float cnt = 0;
4392  unsigned short midPt = 0.5 * (aTj.EndPt[0] + aTj.EndPt[1]);
4393  for(unsigned short ipt = aTj.EndPt[0]; ipt < midPt; ++ipt) {
4394  auto& tp = aTj.Pts[ipt];
4395 // if(tp.Environment[kEnvNearShower]) ++frac;
4396  if(tp.Environment[kEnvNearTj]) ++frac;
4397  ++cnt;
4398  } // ipt
4399  if(cnt > 0) frac /= cnt;
4400  myprt<<std::setw(5)<<std::setprecision(1)<<frac;
4401 /* print NearInShower fraction instead
4402  unsigned short prec = 1;
4403  if(aTj.dEdx[0] > 99) prec = 0;
4404  myprt<<std::setw(5)<<std::setprecision(prec)<<aTj.dEdx[0];
4405 */
4406  unsigned short endPt1 = aTj.EndPt[1];
4407  auto& tp1 = aTj.Pts[endPt1];
4408  itick = tp1.Pos[1]/tjs.UnitsPerTick;
4409  myprt<<std::setw(6)<<(int)(tp1.Pos[0]+0.5)<<":"<<itick; // W:T
4410  if(itick < 10) { myprt<<" "; }
4411  if(itick < 100) { myprt<<" "; }
4412  if(itick < 1000) { myprt<<" "; }
4413  myprt<<std::setw(6)<<std::setprecision(2)<<tp1.Ang;
4414  myprt<<std::setw(2)<<tp1.AngleCode;
4415  if(aTj.StopFlag[1][kBragg]) {
4416  myprt<<"B";
4417  } else if(aTj.StopFlag[1][kAtVtx]) {
4418  myprt<<"V";
4419  } else {
4420  myprt<<" ";
4421  }
4422  myprt<<std::setw(5)<<(int)tp1.AveChg;
4423  // Print the fraction of points in the second half that are NearInShower
4424  frac = 0;
4425  cnt = 0;
4426  for(unsigned short ipt = midPt; ipt <= aTj.EndPt[1]; ++ipt) {
4427  auto& tp = aTj.Pts[ipt];
4428 // if(tp.Environment[kEnvNearShower]) ++frac;
4429  if(tp.Environment[kEnvNearTj]) ++frac;
4430  ++cnt;
4431  } // ipt
4432  if(cnt > 0) frac /= cnt;
4433  myprt<<std::setw(5)<<std::setprecision(1)<<frac;
4434 /*
4435  prec = 1;
4436  if(aTj.dEdx[1] > 99) prec = 0;
4437  myprt<<std::setw(5)<<std::setprecision(prec)<<aTj.dEdx[1];
4438 */
4439  myprt<<std::setw(7)<<std::setprecision(1)<<aTj.TotChg/1000;
4440  myprt<<std::setw(7)<<std::setprecision(2)<<aTj.ChgRMS;
4441  myprt<<std::setw(5)<<aTj.MCSMom;
4442  myprt<<std::setw(4)<<aTj.StepDir;
4443  myprt<<std::setw(4)<<aTj.VtxID[0];
4444  myprt<<std::setw(4)<<aTj.VtxID[1];
4445  myprt<<std::setw(5)<<aTj.PDGCode;
4446  myprt<<std::setw(7)<<std::setprecision(1)<<aTj.DirFOM;
4447  myprt<<std::setw(5)<<aTj.ParentID;
4448  myprt<<std::setw(5)<<PrimaryID(tjs, aTj);
4449  myprt<<std::setw(6)<<NeutrinoPrimaryTjID(tjs, aTj);
4450  int truKE = 0;
4451  int pdg = 0;
4452  if(aTj.MCPartListIndex < tjs.MCPartList.size()) {
4453  auto& mcp = tjs.MCPartList[aTj.MCPartListIndex];
4454  truKE = 1000 * (mcp->E() - mcp->Mass());
4455  pdg = mcp->PdgCode();
4456  }
4457  myprt<<std::setw(6)<<pdg;
4458  myprt<<std::setw(6)<<std::setprecision(2)<<aTj.EffPur;
4459  myprt<<std::setw(5)<<truKE;
4460  myprt<<std::setw(7)<<aTj.WorkID;
4461  for(unsigned short ib = 0; ib < AlgBitNames.size(); ++ib) if(aTj.AlgMod[ib]) myprt<<" "<<AlgBitNames[ib];
4462  myprt<<"\n";
4463  } // ii
4464  return;
4465  } // itj > tjs.allTraj.size()-1
4466 
4467  if(itj > tjs.allTraj.size()-1) return;
4468 
4469  auto const& aTj = tjs.allTraj[itj];
4470 
4471  mf::LogVerbatim("TC")<<"Print tjs.allTraj["<<itj<<"]: ClusterIndex "<<aTj.ClusterIndex<<" Vtx[0] "<<aTj.VtxID[0]<<" Vtx[1] "<<aTj.VtxID[1];
4472  myprt<<"AlgBits";
4473  for(unsigned short ib = 0; ib < AlgBitNames.size(); ++ib) if(aTj.AlgMod[ib]) myprt<<" "<<AlgBitNames[ib];
4474  myprt<<"\n";
4475 
4476  PrintHeader(someText);
4477  if(ipt == USHRT_MAX) {
4478  // print all points
4479  for(unsigned short ii = 0; ii < aTj.Pts.size(); ++ii) PrintTrajPoint(someText, tjs, ii, aTj.StepDir, aTj.Pass, aTj.Pts[ii]);
4480  } else {
4481  // print just one
4482  PrintTrajPoint(someText, tjs, ipt, aTj.StepDir, aTj.Pass, aTj.Pts[ipt]);
4483  }
4484  } // PrintAllTraj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:112
int PrimaryID(const TjStuff &tjs, const PFPStruct &pfp)
Definition: Utils.cxx:404
const std::vector< std::string > AlgBitNames
Definition: DataStructs.cxx:4
Float_t tmp
Definition: plot.C:37
tagged as a vertex between Tjs that are matched to MC truth neutrino interaction particles ...
Definition: DataStructs.h:105
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
DebugStuff debug
Definition: DebugStruct.cxx:4
int Plane
Select plane.
Definition: DebugStruct.h:29
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
const std::vector< std::string > VtxBitNames
Definition: DataStructs.cxx:80
std::string PrintPos(const TjStuff &tjs, const Point2_t &pos)
Definition: Utils.cxx:4744
int NeutrinoPrimaryTjID(const TjStuff &tjs, const Trajectory &tj)
Definition: Utils.cxx:363
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Definition: BitMask.h:187
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
void PosInPlane(const TjStuff &tjs, const Vtx3Store &vx3, unsigned short plane, Point2_t &pos)
Definition: TCVertex.cxx:3083
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void PrintTrajPoint(std::string someText, const TjStuff &tjs, unsigned short ipt, short dir, unsigned short pass, TrajPoint const &tp)
Definition: Utils.cxx:4574
void PrintHeader(std::string someText)
Definition: Utils.cxx:4568
std::vector< int > GetAssns(const TjStuff &tjs, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4079
void tca::PrintHeader ( std::string  someText)

Definition at line 4568 of file Utils.cxx.

Referenced by DotProd(), tca::TrajClusterAlg::FindVtxTraj(), FitVertex(), PrintAllTraj(), lar_content::LArFormattingHelper::PrintRule(), and PrintTrajectory().

4569  {
4570  mf::LogVerbatim("TC")<<someText<<" TRP CTP Ind Stp W:Tick Delta RMS Ang C Err Dir0 Dir1 Q AveQ Pull FitChi NTPF Hits ";
4571  } // PrintHeader
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::string tca::PrintHit ( const TCHit hit)
std::string tca::PrintHitShort ( const TCHit hit)

Definition at line 4726 of file Utils.cxx.

References tca::TCHit::ArtPtr, tca::TCHit::PeakTime, geo::PlaneID::Plane, util::flags::to_string(), geo::WireID::Wire, and recob::Hit::WireID().

Referenced by DotProd(), tca::TruthMatcher::MatchTruth(), and WatchHit().

4727  {
4728  return std::to_string(hit.ArtPtr->WireID().Plane) + ":" + std::to_string(hit.ArtPtr->WireID().Wire) + ":" + std::to_string((int)hit.PeakTime);
4729  } // PrintHit
Detector simulation of raw signals on wires.
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Definition: BitMask.h:187
void tca::PrintPFP ( std::string  someText,
const TjStuff tjs,
const PFPStruct pfp,
bool  printHeader 
)

Definition at line 4619 of file Utils.cxx.

References tca::PFPStruct::dEdx, tca::PFPStruct::Dir, tca::PFPStruct::DtrIDs, tca::PFPStruct::EffPur, tca::PFPStruct::ID, IsShowerLike(), kOutFV, SortEntry::length, tca::TjStuff::MCPartList, tca::PFPStruct::MCPartListIndex, MCSMom(), tca::PFPStruct::ParentID, tca::PFPStruct::PDGCode, PosSep(), PrimaryID(), art::right(), tca::PFPStruct::StopFlag, tca::PFPStruct::TjIDs, util::flags::to_string(), tca::PFPStruct::Tp3s, tca::PFPStruct::Vx3ID, and tca::PFPStruct::XYZ.

Referenced by DotProd(), Match3DVtxTjs(), MergePFPTjs(), and PrintPFPs().

4620  {
4621 // if(pfp.ID == 0) return;
4622  mf::LogVerbatim myprt("TC");
4623  if(printHeader) {
4624  myprt<<someText;
4625  myprt<<" PFP sVx ________sPos_______ CS _______sDir______ ____sdEdx_____ eVx ________ePos_______ CS _______eDir______ ____edEdx____ Len nTp3 MCSMom ShLike? PDG mcpIndx Par Prim E*P\n";
4626  }
4627  myprt<<someText;
4628  std::string pid = "P" + std::to_string(pfp.ID);
4629  myprt<<std::setw(5)<<pid;
4630  // start and end stuff
4631  for(unsigned short startend = 0; startend < 2; ++startend) {
4632  myprt<<std::setw(4)<<pfp.Vx3ID[startend];
4633  myprt<<std::fixed<<std::right<<std::setprecision(1);
4634  myprt<<std::setw(7)<<pfp.XYZ[startend][0];
4635  myprt<<std::setw(7)<<pfp.XYZ[startend][1];
4636  myprt<<std::setw(7)<<pfp.XYZ[startend][2];
4637  // print character for Outside or Inside the FV
4638  if(pfp.StopFlag[startend][kOutFV]) {
4639  myprt<<" O";
4640  } else {
4641  myprt<<" I";
4642  }
4643  myprt<<std::fixed<<std::right<<std::setprecision(2);
4644  myprt<<std::setw(6)<<pfp.Dir[startend][0];
4645  myprt<<std::setw(6)<<pfp.Dir[startend][1];
4646  myprt<<std::setw(6)<<pfp.Dir[startend][2];
4647  for(auto& dedx : pfp.dEdx[startend]) {
4648  if(dedx < 50) {
4649  myprt<<std::setw(5)<<std::setprecision(1)<<dedx;
4650  } else {
4651  myprt<<std::setw(5)<<std::setprecision(0)<<dedx;
4652  }
4653  } // dedx
4654  if (pfp.dEdx[startend].size()<3){
4655  for(size_t i = 0; i<3-pfp.dEdx[startend].size(); ++i){
4656  myprt<<std::setw(6)<<' ';
4657  }
4658  }
4659  } // startend
4660  // global stuff
4661 // myprt<<std::setw(5)<<pfp.BestPlane;
4662  float length = PosSep(pfp.XYZ[0], pfp.XYZ[1]);
4663  if(length < 100) {
4664  myprt<<std::setw(5)<<std::setprecision(1)<<length;
4665  } else {
4666  myprt<<std::setw(5)<<std::setprecision(0)<<length;
4667  }
4668  myprt<<std::setw(5)<<std::setprecision(2)<<pfp.Tp3s.size();
4669  myprt<<std::setw(7)<<MCSMom(tjs, pfp.TjIDs);
4670  myprt<<std::setw(5)<<IsShowerLike(tjs, pfp.TjIDs);
4671  myprt<<std::setw(5)<<pfp.PDGCode;
4672  if(pfp.MCPartListIndex < tjs.MCPartList.size()) {
4673  myprt<<std::setw(8)<<pfp.MCPartListIndex;
4674  } else {
4675  myprt<<" NA";
4676  }
4677  myprt<<std::setw(4)<<pfp.ParentID;
4678  myprt<<std::setw(5)<<PrimaryID(tjs, pfp);
4679  myprt<<std::setw(5)<<std::setprecision(2)<<pfp.EffPur;
4680  if(!pfp.TjIDs.empty()) {
4681  for(auto& tjID : pfp.TjIDs) myprt<<" T"<<tjID;
4682  }
4683  if(!pfp.DtrIDs.empty()) {
4684  myprt<<" dtrs";
4685  for(auto& dtrID : pfp.DtrIDs) myprt<<" P"<<dtrID;
4686  }
4687  } // PrintPFP
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:112
int PrimaryID(const TjStuff &tjs, const PFPStruct &pfp)
Definition: Utils.cxx:404
float PosSep(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2220
bool IsShowerLike(const TjStuff &tjs, const std::vector< int > TjIDs)
Definition: TCShower.cxx:2071
short MCSMom(TjStuff &tjs, Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:2859
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Definition: BitMask.h:187
void tca::PrintPFPs ( std::string  someText,
const TjStuff tjs 
)

Definition at line 4690 of file Utils.cxx.

References tca::TjStuff::pfps, and PrintPFP().

Referenced by DotProd(), FindShowers3D(), and tca::TrajClusterAlg::RunTrajClusterAlg().

4691  {
4692  if(tjs.pfps.empty()) return;
4693 
4694  mf::LogVerbatim myprt("TC");
4695  myprt<<someText;
4696  myprt<<" PFP sVx ________sPos_______ ______sDir______ ______sdEdx_____ eVx ________ePos_______ ______eDir______ ______edEdx_____ BstPln PDG TruPDG Par Prim E*P\n";
4697  bool printHeader = true;
4698  for(auto& pfp : tjs.pfps) {
4699 // if(pfp.ID == 0) continue;
4700  PrintPFP(someText, tjs, pfp, printHeader);
4701  printHeader = false;
4702  } // im
4703 
4704  } // PrintPFPs
void PrintPFP(std::string someText, const TjStuff &tjs, const PFPStruct &pfp, bool printHeader)
Definition: Utils.cxx:4619
std::string tca::PrintPos ( const TjStuff tjs,
const Point2_t pos 
)

Definition at line 4744 of file Utils.cxx.

References util::flags::to_string(), and tca::TjStuff::UnitsPerTick.

Referenced by CheckTrajBeginChg(), MergeAndStore(), PrintAllTraj(), PrintPos(), TagDeltaRays(), TagMuonDirections(), TjDirFOM(), and UpdateVxEnvironment().

4745  {
4746  unsigned int wire = 0;
4747  if(pos[0] > -0.4) wire = std::nearbyint(pos[0]);
4748  int time = std::nearbyint(pos[1]/tjs.UnitsPerTick);
4749  return std::to_string(wire) + ":" + std::to_string(time);
4750  } // PrintPos
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Definition: BitMask.h:187
void tca::PrintShower ( std::string  someText,
const TjStuff tjs,
const ShowerStruct ss,
bool  printHeader,
bool  printExtras 
)

Definition at line 4801 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::ShowerStruct::AspectRatio, tca::ShowerStruct::CTP, tca::ShowerStruct::DirectionFOM, tca::ShowerStruct::Energy, tca::ShowerStruct::Envelope, tca::ShowerStruct::ID, tca::ShowerStruct::NearTjIDs, tca::ShowerStruct::NeedsUpdate, tca::ShowerStruct::ParentFOM, tca::ShowerStruct::ParentID, tca::TjStuff::pfps, PrintPos(), tca::TjStuff::showers, tca::ShowerStruct::ShowerTjID, tca::ShowerStruct::SS3ID, tca::ShowerStruct::TjIDs, util::flags::to_string(), tca::ShowerStruct::TruParentID, and tca::TjStuff::UnitsPerTick.

Referenced by Print2DShowers().

4802  {
4803  // print a single shower and a header (optional) and the extra variables like TjIDs, envelope, etc
4804  mf::LogVerbatim myprt("TC");
4805 
4806  if(printHeader) {
4807  myprt<<someText<<" ID CTP ParID ParFOM TruParID Energy nTjs dFOM AspRat stj vx0 __Pos0___ Chg(k) dRMS __Pos1___ Chg(k) dRMS __Pos2___ Chg(k) dRMS Angle SS3ID PFPID\n";
4808  } // printHeader
4809 
4810  myprt<<someText<<std::fixed;
4811  std::string sid = "2S" + std::to_string(ss.ID);
4812  myprt<<std::setw(5)<<sid;
4813  myprt<<std::setw(6)<<ss.CTP;
4814  sid = "NA";
4815  if(ss.ParentID > 0) sid = "T" + std::to_string(ss.ParentID);
4816  myprt<<std::setw(7)<<sid;
4817  myprt<<std::setw(7)<<std::setprecision(2)<<ss.ParentFOM;
4818  myprt<<std::setw(9)<<ss.TruParentID;
4819  myprt<<std::setw(7)<<(int)ss.Energy;
4820  myprt<<std::setw(5)<<ss.TjIDs.size();
4821  myprt<<std::setw(6)<<std::setprecision(2)<<ss.DirectionFOM;
4822  myprt<<std::setw(7)<<std::setprecision(2)<<ss.AspectRatio;
4823  const auto& stj = tjs.allTraj[ss.ShowerTjID - 1];
4824  std::string tid = "T" + std::to_string(stj.ID);
4825  myprt<<std::setw(5)<<tid;
4826  std::string vid = "NA";
4827  if(stj.VtxID[0] > 0) vid = "2V" + std::to_string(stj.VtxID[0]);
4828  myprt<<std::setw(5)<<vid;
4829  for(auto& spt : stj.Pts) {
4830  myprt<<std::setw(10)<<PrintPos(tjs, spt.Pos);
4831  myprt<<std::setw(7)<<std::fixed<<std::setprecision(1)<<spt.Chg/1000;
4832  // myprt<<std::setw(5)<<spt.NTPsFit;
4833  myprt<<std::setw(5)<<std::setprecision(1)<<spt.DeltaRMS;
4834  } // spt
4835  myprt<<std::setw(6)<<std::setprecision(2)<<stj.Pts[1].Ang;
4836  std::string sss = "NA";
4837  if(ss.SS3ID > 0) sss = "3S" + std::to_string(ss.SS3ID);
4838  myprt<<std::setw(6)<<sss;
4839  if(ss.SS3ID > 0 && ss.SS3ID < (int)tjs.showers.size()) {
4840  auto& ss3 = tjs.showers[ss.SS3ID - 1];
4841  if(ss3.PFPIndex >= 0 && ss3.PFPIndex < tjs.pfps.size()) {
4842  std::string pid = "P" + std::to_string(ss3.PFPIndex + 1);
4843  myprt<<std::setw(6)<<pid;
4844  } else {
4845  myprt<<std::setw(6)<<"NA";
4846  }
4847  } else {
4848  myprt<<std::setw(6)<<"NA";
4849  }
4850  if(ss.NeedsUpdate) myprt<<" *** Needs update";
4851 
4852  if(!printExtras) return;
4853  myprt<<"\n";
4854 
4855  myprt<<someText<<std::fixed;
4856  sid = "2S" + std::to_string(ss.ID);
4857  myprt<<std::setw(5)<<sid;
4858  myprt<<" Tjs";
4859  for(auto id : ss.TjIDs) myprt<<" T"<<id;
4860  myprt<<"\n";
4861  myprt<<someText<<std::fixed;
4862  sid = "2S" + std::to_string(ss.ID);
4863  myprt<<std::setw(5)<<sid;
4864  myprt<<" Envelope";
4865  for(auto& vtx : ss.Envelope) myprt<<" "<<(int)vtx[0]<<":"<<(int)(vtx[1]/tjs.UnitsPerTick);
4866  myprt<<"\n";
4867  myprt<<someText<<std::fixed;
4868  sid = "2S" + std::to_string(ss.ID);
4869  myprt<<std::setw(5)<<sid;
4870  myprt<<" Nearby";
4871  for(auto id : ss.NearTjIDs) myprt<<" T"<<id;
4872 
4873  } // PrintShower
std::string PrintPos(const TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:4738
Float_t ss
Definition: plot.C:23
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Definition: BitMask.h:187
void tca::PrintShowers ( std::string  fcnLabel,
TjStuff tjs 
)

Definition at line 4676 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::TjStuff::cots, EncodeCTP(), MakeBareTP(), tca::TjStuff::NumPlanes, PrintPos(), tca::TjStuff::showers, and ss.

Referenced by Match2DShowers(), and tca::TrajClusterAlg::RunTrajClusterAlg().

4677  {
4678  if(tjs.showers.empty()) return;
4679  mf::LogVerbatim myprt("TC");
4680  myprt<<fcnLabel<<" 3D showers \n";
4681  for(auto& ss3 : tjs.showers) {
4682  myprt<<fcnLabel<<" 3S"<<ss3.ID<<" 3V"<<ss3.Vx3ID;
4683  myprt<<" parentID "<<ss3.ParentID;
4684  myprt<<" ChgPos"<<std::fixed;
4685  for(unsigned short xyz = 0; xyz < 3; ++xyz) myprt<<" "<<std::setprecision(0)<<ss3.ChgPos[xyz];
4686  myprt<<" Dir";
4687  for(unsigned short xyz = 0; xyz < 3; ++xyz) myprt<<" "<<std::setprecision(2)<<ss3.Dir[xyz];
4688  myprt<<" posInPlane";
4689  std::vector<float> projInPlane(tjs.NumPlanes);
4690  for(unsigned short plane = 0; plane < tjs.NumPlanes; ++plane) {
4691  CTP_t inCTP = EncodeCTP(ss3.TPCID.Cryostat, ss3.TPCID.TPC, plane);
4692  auto tp = MakeBareTP(tjs, ss3.ChgPos, ss3.Dir, inCTP);
4693  myprt<<" "<<PrintPos(tjs, tp.Pos);
4694  projInPlane[plane] = tp.Delta;
4695  } // plane
4696  myprt<<" projInPlane";
4697  for(unsigned short plane = 0; plane < tjs.NumPlanes; ++plane) {
4698  myprt<<" "<<std::fixed<<std::setprecision(2)<<projInPlane[plane];
4699  } // plane
4700  for(auto cid : ss3.CotIDs) {
4701  auto& ss = tjs.cots[cid - 1];
4702  myprt<<"\n 2S"<<ss.ID;
4703  auto& stj = tjs.allTraj[ss.ShowerTjID - 1];
4704  myprt<<" ST"<<stj.ID;
4705  myprt<<" "<<PrintPos(tjs, stj.Pts[stj.EndPt[0]].Pos)<<" - "<<PrintPos(tjs, stj.Pts[stj.EndPt[1]].Pos);
4706  } // ci
4707  if(ss3.NeedsUpdate) myprt<<" *** Needs update";
4708  myprt<<"\n";
4709  } // sss3
4710  } // PrintShowers
std::string PrintPos(const TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:4738
Float_t ss
Definition: plot.C:23
TrajPoint MakeBareTP(TjStuff &tjs, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
Definition: Utils.cxx:3435
unsigned int CTP_t
Definition: DataStructs.h:41
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
std::string tca::PrintStopFlag ( const Trajectory tj,
unsigned short  end 
)

Definition at line 4707 of file Utils.cxx.

References tca::Trajectory::StopFlag, StopFlagNames, tmp, and util::flags::to_string().

Referenced by DotProd(), tca::TrajClusterAlg::FixTrajBegin(), and PrintTrajectory().

4708  {
4709  if(end > 1) return "Invalid end";
4710  std::string tmp;
4711  bool first = true;
4712  for(unsigned short ib = 0; ib < StopFlagNames.size(); ++ib) {
4713  if(tj.StopFlag[end][ib]) {
4714  if(first) {
4715  tmp = std::to_string(end) + ":" + StopFlagNames[ib];
4716  first = false;
4717  } else {
4718  tmp += "," + StopFlagNames[ib];
4719  }
4720  }
4721  } // ib
4722  return tmp;
4723  } // PrintStopFlag
Float_t tmp
Definition: plot.C:37
const std::vector< std::string > StopFlagNames
Definition: DataStructs.cxx:71
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Definition: BitMask.h:187
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void tca::PrintTp3 ( std::string  someText,
const TjStuff tjs,
const TrajPoint3 tp3 
)

Definition at line 2945 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, tca::TrajPoint3::Dir, tca::TrajPoint3::Pos, PrintPos(), and tca::TrajPoint3::Tj2Pts.

Referenced by DotProd(), and SetStart().

2946  {
2947  mf::LogVerbatim myprt("TC");
2948  myprt<<someText<<" Pos"<<std::fixed<<std::setprecision(1);
2949  myprt<<std::setw(6)<<tp3.Pos[0]<<std::setw(6)<<tp3.Pos[1]<<std::setw(6)<<tp3.Pos[2];
2950  myprt<<" Dir"<<std::fixed<<std::setprecision(3);
2951  myprt<<std::setw(7)<<tp3.Dir[0]<<std::setw(7)<<tp3.Dir[1]<<std::setw(7)<<tp3.Dir[2];
2952  myprt<<" tj_ipt";
2953  for(auto tj2pt : tp3.Tj2Pts) {
2954  auto& tj = tjs.allTraj[tj2pt.id - 1];
2955  auto& tp = tj.Pts[tj2pt.ipt];
2956  myprt<<" "<<tj.ID<<"_"<<PrintPos(tjs, tp);
2957  } // tj2pt
2958  } // PrintTp3
std::string PrintPos(const TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:4738
void tca::PrintTp3s ( std::string  someText,
const TjStuff tjs,
const PFPStruct pfp,
short  printPts 
)

Definition at line 2961 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, DeltaAngle(), tca::PFPStruct::Dir, tca::PFPStruct::ID, KinkAngle(), PosSep(), PrintPos(), tca::PFPStruct::Tp3s, and tca::PFPStruct::XYZ.

Referenced by DotProd().

2962  {
2963  if(pfp.Tp3s.empty()) return;
2964  mf::LogVerbatim myprt("TC");
2965  if(printPts < 0) {
2966  // print the head if we are print all points
2967  myprt<<someText<<" pfp P"<<pfp.ID<<"\n";
2968  myprt<<someText<<" ipt ________Pos________ Path ________Dir_______ along trans dang Kink Tj_ipt \n";
2969  }
2970  // print the start
2971  myprt<<someText<<" ";
2972  myprt<<std::fixed<<std::setprecision(1);
2973  myprt<<std::setw(7)<<pfp.XYZ[0][0]<<std::setw(7)<<pfp.XYZ[0][1]<<std::setw(7)<<pfp.XYZ[0][2];
2974  myprt<<" ";
2975  myprt<<std::fixed<<std::setprecision(2);
2976  myprt<<std::setw(7)<<pfp.Dir[0][0]<<std::setw(7)<<pfp.Dir[0][1]<<std::setw(7)<<pfp.Dir[0][2];
2977  myprt<<" <--- pfp.XYZ[0] \n";
2978 
2979  unsigned short fromPt = 0;
2980  unsigned short toPt = pfp.Tp3s.size() - 1;
2981  if(printPts >= 0) fromPt = toPt;
2982  Vector3_t prevDir = pfp.Dir[0];
2983  for(unsigned short ipt = fromPt; ipt <= toPt; ++ipt) {
2984  auto tp3 = pfp.Tp3s[ipt];
2985  myprt<<someText<<std::setw(4)<<ipt;
2986  myprt<<std::fixed<<std::setprecision(1);
2987  myprt<<std::setw(7)<<tp3.Pos[0]<<std::setw(7)<<tp3.Pos[1]<<std::setw(7)<<tp3.Pos[2];
2988  myprt<<std::setprecision(1)<<std::setw(5)<<PosSep(tp3.Pos, pfp.XYZ[0]);
2989  myprt<<std::setprecision(2)<<std::setw(7)<<tp3.Dir[0]<<std::setw(7)<<tp3.Dir[1]<<std::setw(7)<<tp3.Dir[2];
2990  myprt<<std::setprecision(1)<<std::setw(6)<<tp3.AlongTrans[0];
2991  myprt<<std::setprecision(1)<<std::setw(6)<<tp3.AlongTrans[1];
2992  myprt<<std::setprecision(2)<<std::setw(7)<<DeltaAngle(prevDir, tp3.Dir);
2993  prevDir = tp3.Dir;
2994  // Calculate the kink angle at point ipt, using the two points that are
2995  // +/- 1 cm on either side of that point
2996  double sep = 1;
2997  myprt<<std::setprecision(2)<<std::setw(7)<<KinkAngle(tjs, pfp.Tp3s, ipt, sep);
2998  for(auto tj2pt : tp3.Tj2Pts) {
2999  auto& tj = tjs.allTraj[tj2pt.id - 1];
3000  auto& tp = tj.Pts[tj2pt.ipt];
3001  myprt<<" "<<tj.ID<<"_"<<tj2pt.ipt<<"_"<<PrintPos(tjs, tp);
3002  } // tj2pt
3003  myprt<<"\n";
3004  } // ipt
3005  // print the end
3006  myprt<<someText<<" ";
3007  myprt<<std::fixed<<std::setprecision(1);
3008  myprt<<std::setw(7)<<pfp.XYZ[1][0]<<std::setw(7)<<pfp.XYZ[1][1]<<std::setw(7)<<pfp.XYZ[1][2];
3009  myprt<<" ";
3010  myprt<<std::fixed<<std::setprecision(2);
3011  myprt<<std::setw(7)<<pfp.Dir[1][0]<<std::setw(7)<<pfp.Dir[1][1]<<std::setw(7)<<pfp.Dir[1][2];
3012  myprt<<" <--- pfp.XYZ[1]. Length "<<PosSep(pfp.XYZ[0], pfp.XYZ[1])<<"\n";
3013  } // PrintTp3s
std::string PrintPos(const TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:4738
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1607
double KinkAngle(const TjStuff &tjs, const std::vector< TrajPoint3 > &tp3s, unsigned short atPt, double sep)
Definition: PFPUtils.cxx:1913
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
std::array< double, 3 > Vector3_t
Definition: DataStructs.h:36
void tca::PrintTrajectory ( std::string  someText,
const TjStuff tjs,
const Trajectory tj,
unsigned short  tPoint 
)

Definition at line 4488 of file Utils.cxx.

References AlgBitNames, tca::Trajectory::AlgMod, tca::ShowerStruct::Angle, tca::ShowerStruct::AngleErr, tca::ShowerStruct::AspectRatio, tca::ShowerStruct::ChgDensity, tca::TjStuff::cots, tca::Trajectory::CTP, tca::ShowerStruct::DirectionFOM, tca::Trajectory::EndPt, tca::ShowerStruct::Energy, tca::ShowerStruct::Envelope, tca::ShowerStruct::EnvelopeArea, tca::Trajectory::ID, kShowerTj, tca::TjStuff::MCPartList, tca::Trajectory::MCPartListIndex, tca::Trajectory::MCSMom, tca::ShowerStruct::NearTjIDs, tca::ShowerStruct::NeedsUpdate, tca::ShowerStruct::ParentFOM, tca::ShowerStruct::ParentID, tca::Trajectory::Pass, tca::Trajectory::PDGCode, PrintHeader(), PrintStopFlag(), PrintTrajPoint(), tca::Trajectory::Pts, ss, tca::ShowerStruct::SS3ID, tca::Trajectory::StepDir, tca::ShowerStruct::TjIDs, tca::ShowerStruct::TruParentID, tca::TjStuff::UnitsPerTick, tca::Trajectory::VtxID, and tca::Trajectory::WorkID.

Referenced by tca::TrajClusterAlg::CheckHiMultUnusedHits(), tca::TrajClusterAlg::CheckTraj(), ChkChgAsymmetry(), tca::TrajClusterAlg::ChkInTraj(), DotProd(), tca::TrajClusterAlg::FixTrajBegin(), tca::TrajClusterAlg::FixTrajEnd(), tca::TrajClusterAlg::GottaKink(), InTrajOK(), tca::TrajClusterAlg::IsGhost(), tca::TrajClusterAlg::MakeAllTrajClusters(), tca::TrajClusterAlg::MakeJunkTraj(), tca::TrajClusterAlg::MaskedHitsOK(), MergeAndStore(), tca::TrajClusterAlg::ReconstructAllTraj(), tca::TrajClusterAlg::ReversePropagate(), tca::TrajClusterAlg::StepCrawl(), and TrimEndPts().

4489  {
4490  // prints one or all trajectory points on tj
4491 
4492  int trupdg = 0;
4493  if(tj.MCPartListIndex < tjs.MCPartList.size()) trupdg = tjs.MCPartList[tj.MCPartListIndex]->PdgCode();
4494 
4495  if(tPoint == USHRT_MAX) {
4496  if(tj.ID < 0) {
4497  mf::LogVerbatim myprt("TC");
4498  myprt<<someText<<" ";
4499  myprt<<"Work: ID "<<tj.ID<<" CTP "<<tj.CTP<<" StepDir "<<tj.StepDir<<" PDG "<<tj.PDGCode<<" TruPDG "<<trupdg<<" tjs.vtx "<<tj.VtxID[0]<<" "<<tj.VtxID[1]<<" nPts "<<tj.Pts.size()<<" EndPts "<<tj.EndPt[0]<<" "<<tj.EndPt[1];
4500  myprt<<" MCSMom "<<tj.MCSMom;
4501  myprt<<" StopFlags "<<PrintStopFlag(tj, 0)<<" "<<PrintStopFlag(tj, 1);
4502  myprt<<" AlgMod names:";
4503  for(unsigned short ib = 0; ib < AlgBitNames.size(); ++ib) if(tj.AlgMod[ib]) myprt<<" "<<AlgBitNames[ib];
4504  } else {
4505  mf::LogVerbatim myprt("TC");
4506  myprt<<someText<<" ";
4507  myprt<<"tjs.allTraj: ID "<<tj.ID<<" WorkID "<<tj.WorkID<<" StepDir "<<tj.StepDir<<" PDG "<<tj.PDGCode<<" TruPDG "<<trupdg<<" tjs.vtx "<<tj.VtxID[0]<<" "<<tj.VtxID[1]<<" nPts "<<tj.Pts.size()<<" EndPts "<<tj.EndPt[0]<<" "<<tj.EndPt[1];
4508  myprt<<" MCSMom "<<tj.MCSMom;
4509  myprt<<" StopFlags "<<PrintStopFlag(tj, 0)<<" "<<PrintStopFlag(tj, 1);
4510  myprt<<" AlgMod names:";
4511  for(unsigned short ib = 0; ib < AlgBitNames.size(); ++ib) if(tj.AlgMod[ib]) myprt<<" "<<AlgBitNames[ib];
4512  }
4513  PrintHeader(someText);
4514  for(unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) PrintTrajPoint(someText, tjs, ipt, tj.StepDir, tj.Pass, tj.Pts[ipt]);
4515  // See if this trajectory is a shower Tj
4516  if(tj.AlgMod[kShowerTj]) {
4517  for(unsigned short ic = 0; ic < tjs.cots.size(); ++ic) {
4518  if(tjs.cots[ic].TjIDs.empty()) continue;
4519  // only print out the info for the correct Tj
4520  if(tjs.cots[ic].ShowerTjID != tj.ID) continue;
4521  const ShowerStruct& ss = tjs.cots[ic];
4522  mf::LogVerbatim myprt("TC");
4523  myprt<<"cots index "<<ic<<" ";
4524  myprt<<someText<<" Envelope";
4525  if(ss.Envelope.empty()) {
4526  myprt<<" NA";
4527  } else {
4528  for(auto& vtx : ss.Envelope) myprt<<" "<<(int)vtx[0]<<":"<<(int)(vtx[1]/tjs.UnitsPerTick);
4529  }
4530  myprt<<" Energy "<<(int)ss.Energy;
4531  myprt<<" Area "<<std::fixed<<std::setprecision(1)<<(int)ss.EnvelopeArea<<" ChgDensity "<<ss.ChgDensity;
4532  myprt<<"\nInShower TjIDs";
4533  for(auto& tjID : ss.TjIDs) {
4534  myprt<<" "<<tjID;
4535  } // tjIDA_Klystron_4U
4536 
4537  myprt<<"\n";
4538  myprt<<"NearTjIDs";
4539  for(auto& tjID : ss.NearTjIDs) {
4540  myprt<<" "<<tjID;
4541  } // tjID
4542  myprt<<"\n";
4543  myprt<<"\n";
4544  myprt<<"Angle "<<std::fixed<<std::setprecision(2)<<ss.Angle<<" +/- "<<ss.AngleErr;
4545  myprt<<" AspectRatio "<<std::fixed<<std::setprecision(2)<<ss.AspectRatio;
4546  myprt<<" DirectionFOM "<<std::fixed<<std::setprecision(2)<<ss.DirectionFOM;
4547  if(ss.ParentID > 0) {
4548  myprt<<" Parent Tj "<<ss.ParentID<<" FOM "<<ss.ParentFOM;
4549  } else {
4550  myprt<<" No parent";
4551  }
4552  myprt<<" TruParentID "<<ss.TruParentID<<" SS3ID "<<ss.SS3ID<<"\n";
4553  if(ss.NeedsUpdate) myprt<<"*********** This shower needs to be updated ***********";
4554  myprt<<"................................................";
4555  } // ic
4556  } // Shower Tj
4557  } else {
4558  // just print one traj point
4559  if(tPoint > tj.Pts.size() -1) {
4560  mf::LogVerbatim("TC")<<"Can't print non-existent traj point "<<tPoint;
4561  return;
4562  }
4563  PrintTrajPoint(someText, tjs, tPoint, tj.StepDir, tj.Pass, tj.Pts[tPoint]);
4564  }
4565  } // PrintTrajectory
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
const std::vector< std::string > AlgBitNames
Definition: DataStructs.cxx:4
Float_t ss
Definition: plot.C:23
std::string PrintStopFlag(const Trajectory &tj, unsigned short end)
Definition: Utils.cxx:4707
void PrintTrajPoint(std::string someText, const TjStuff &tjs, unsigned short ipt, short dir, unsigned short pass, TrajPoint const &tp)
Definition: Utils.cxx:4574
void PrintHeader(std::string someText)
Definition: Utils.cxx:4568
void tca::PrintTrajPoint ( std::string  someText,
const TjStuff tjs,
unsigned short  ipt,
short  dir,
unsigned short  pass,
TrajPoint const &  tp 
)

Definition at line 4574 of file Utils.cxx.

References tca::TrajPoint::Ang, tca::TrajPoint::AngErr, tca::TrajPoint::AngleCode, tca::TrajPoint::AveChg, tca::TrajPoint::Chg, tca::TrajPoint::ChgPull, tca::TrajPoint::CTP, tca::TrajPoint::Delta, tca::TrajPoint::DeltaRMS, tca::TrajPoint::Dir, tca::TjStuff::fHits, tca::TrajPoint::FitChi, tca::TrajPoint::Hits, tca::TrajPoint::NTPsFit, tca::TrajPoint::Pos, tca::TrajPoint::Step, tca::TjStuff::UnitsPerTick, and tca::TrajPoint::UseHit.

Referenced by DotProd(), tca::TrajClusterAlg::FillGaps(), tca::TrajClusterAlg::FindVtxTraj(), FitVertex(), tca::TrajClusterAlg::FixTrajBegin(), tca::TrajClusterAlg::HiEndDelta(), PrintAllTraj(), PrintTrajectory(), SplitTrajCrossingVertices(), and tca::TrajClusterAlg::StepCrawl().

4575  {
4576  mf::LogVerbatim myprt("TC");
4577  myprt<<someText<<" TRP"<<std::fixed;
4578  myprt<<pass;
4579  if(dir > 0) { myprt<<"+"; } else { myprt<<"-"; }
4580  myprt<<std::setw(6)<<tp.CTP;
4581  myprt<<std::setw(5)<<ipt;
4582  myprt<<std::setw(5)<<tp.Step;
4583  myprt<<std::setw(7)<<std::setprecision(1)<<tp.Pos[0]<<":"<<tp.Pos[1]/tjs.UnitsPerTick; // W:T
4584  if(tp.Pos[1] < 10) { myprt<<" "; }
4585  if(tp.Pos[1] < 100) { myprt<<" "; }
4586  if(tp.Pos[1] < 1000) { myprt<<" "; }
4587  myprt<<std::setw(6)<<std::setprecision(2)<<tp.Delta;
4588  myprt<<std::setw(6)<<std::setprecision(2)<<tp.DeltaRMS;
4589  myprt<<std::setw(6)<<std::setprecision(2)<<tp.Ang;
4590  myprt<<std::setw(2)<<tp.AngleCode;
4591  myprt<<std::setw(6)<<std::setprecision(2)<<tp.AngErr;
4592  myprt<<std::setw(6)<<std::setprecision(2)<<tp.Dir[0];
4593  myprt<<std::setw(6)<<std::setprecision(2)<<tp.Dir[1];
4594  myprt<<std::setw(7)<<(int)tp.Chg;
4595  myprt<<std::setw(8)<<(int)tp.AveChg;
4596  myprt<<std::setw(6)<<std::setprecision(1)<<tp.ChgPull;
4597  myprt<<std::setw(7)<<tp.FitChi;
4598  myprt<<std::setw(6)<<tp.NTPsFit;
4599  // print the hits associated with this traj point
4600  if(tp.Hits.size() > 16) {
4601  // don't print too many hits (e.g. from a shower Tj)
4602  myprt<<" "<<tp.Hits.size()<<" shower hits";
4603  } else {
4604  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
4605  unsigned int iht = tp.Hits[ii];
4606  myprt<<" "<<tjs.fHits[iht].ArtPtr->WireID().Wire<<":"<<(int)tjs.fHits[iht].PeakTime;
4607  if(tp.UseHit[ii]) {
4608  // Distinguish used hits from nearby hits
4609  myprt<<"_";
4610  } else {
4611  myprt<<"x";
4612  }
4613  myprt<<tjs.fHits[iht].InTraj;
4614  } // iht
4615  }
4616  } // PrintTrajPoint
TDirectory * dir
Definition: macro.C:5
std::vector< unsigned int > tca::PutTrajHitsInVector ( Trajectory const &  tj,
HitStatus_t  hitRequest 
)

Definition at line 2283 of file Utils.cxx.

References tca::Trajectory::AlgMod, kAllHits, kShowerTj, kUnusedHits, kUsedHits, and tca::Trajectory::Pts.

Referenced by tca::TrajClusterAlg::AddLAHits(), tca::TrajClusterAlg::CheckHiMultUnusedHits(), tca::TrajClusterAlg::ChkInTraj(), Finish3DShowers(), HasDuplicateHits(), InTrajOK(), tca::TrajClusterAlg::MakeAllTrajClusters(), tca::TruthMatcher::MatchAndSum(), tca::TruthMatcher::MatchTruth(), MergeGhostTjs(), tca::MCParticleListUtils::PrimaryElectronPFPID(), and TransferTjHits().

2284  {
2285  // Put hits in each trajectory point into a flat vector
2286  std::vector<unsigned int> hitVec;
2287 
2288  // special handling for shower trajectories. UseHit isn't valid
2289  if(tj.AlgMod[kShowerTj]) {
2290  for(auto& tp : tj.Pts) hitVec.insert(hitVec.end(), tp.Hits.begin(), tp.Hits.end());
2291  return hitVec;
2292  } // shower Tj
2293 
2294  // reserve under the assumption that there will be one hit per point
2295  hitVec.reserve(tj.Pts.size());
2296  for(unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) {
2297  for(unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
2298  unsigned int iht = tj.Pts[ipt].Hits[ii];
2299  bool useit = (hitRequest == kAllHits);
2300  if(tj.Pts[ipt].UseHit[ii] && hitRequest == kUsedHits) useit = true;
2301  if(!tj.Pts[ipt].UseHit[ii] && hitRequest == kUnusedHits) useit = true;
2302  if(useit) hitVec.push_back(iht);
2303  } // iht
2304  } // ipt
2305  return hitVec;
2306  } // PutTrajHitsInVector
bool tca::Reconcile3D ( std::string  inFcnLabel,
TjStuff tjs,
const geo::TPCID tpcid,
bool  parentSearchDone,
bool  prt 
)

Definition at line 491 of file TCShower.cxx.

References AddPFP(), tca::TjStuff::allTraj, ChkAssns(), tca::TjStuff::cots, geo::CryostatID::Cryostat, DecodeCTP(), evd::details::end(), GetAssns(), InShowerProb(), kMat3D, MakeShowerObsolete(), MergeShowersAndStore(), tca::TjStuff::pfps, Print2DShowers(), RemovePFP(), SetIntersection(), ShowerEnergy(), tca::TjStuff::showers, ss, geo::TPCID::TPC, and UpdateShower().

492  {
493  // Reconcile pfp and shower assns
494 
495  std::string fcnLabel = inFcnLabel + ".R3D2";
496 
497  if(prt) Print2DShowers("R3D2i", tjs, USHRT_MAX, false);
498 
499  // consider them pair-wise
500  if(tjs.showers.size() > 1) {
501  for(unsigned short ii = 0; ii < tjs.showers.size() - 1; ++ii) {
502  auto iss3 = tjs.showers[ii];
503  if(iss3.ID == 0) continue;
504  if(iss3.TPCID != tpcid) continue;
505  auto iPInSS3 = GetAssns(tjs, "3S", iss3.ID, "P");
506  if(prt) {
507  mf::LogVerbatim myprt("TC");
508  myprt<<fcnLabel<<" 3S"<<iss3.ID<<" ->";
509  for(auto pid : iPInSS3) myprt<<" P"<<pid;
510  } // prt
511  for(unsigned short jj = ii + 1; jj < tjs.showers.size(); ++jj) {
512  auto jss3 = tjs.showers[jj];
513  if(jss3.ID == 0) continue;
514  auto jPInSS3 = GetAssns(tjs, "3S", jss3.ID, "P");
515  auto shared = SetIntersection(iPInSS3, jPInSS3);
516  if(shared.empty()) continue;
517  if(prt) {
518  mf::LogVerbatim myprt("TC");
519  myprt<<fcnLabel<<" Conflict i3S"<<iss3.ID<<" and j3S"<<jss3.ID<<" share";
520  for(auto pid : shared) myprt<<" P"<<pid;
521  } // prt
522  // Compare the InShower likelihoods
523  for(auto pid : shared) {
524  auto& pfp = tjs.pfps[pid - 1];
525  float iProb = InShowerProb(tjs, iss3, pfp);
526  float jProb = InShowerProb(tjs, jss3, pfp);
527  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" i3S"<<iss3.ID<<" prob "<<std::setprecision(3)<<iProb<<" j3S"<<jss3.ID<<" prob "<<jProb;
528  if(iProb > jProb) {
529  // remove the remnants of pfp from jss3
530  RemovePFP(fcnLabel, tjs, pfp, jss3, true, prt);
531  // and add them to iss3
532  AddPFP(fcnLabel, tjs, pfp.ID, iss3, true, prt);
533  } else {
534  RemovePFP(fcnLabel, tjs, pfp, iss3, true, prt);
535  AddPFP(fcnLabel, tjs, pfp.ID, jss3, true, prt);
536  }
537  } // pid
538  } // jj
539  } // ii
540  } // > 1 shower
541 
542  // Look for an in-shower pfp that is not the shower parent that is attached to a vertex.
543  // Remove the attachment and any parent - daughter assn
544  if(parentSearchDone) {
545  for(auto& ss3 : tjs.showers) {
546  if(ss3.ID == 0) continue;
547  if(ss3.TPCID != tpcid) continue;
548  auto PIn3S = GetAssns(tjs, "3S", ss3.ID, "P");
549  for(auto pid : PIn3S) {
550  if(pid == ss3.ParentID) continue;
551  auto& pfp = tjs.pfps[pid - 1];
552  for(unsigned short end = 0; end < 2; ++end) {
553  if(pfp.Vx3ID[end] <= 0) continue;
554  if(prt) {
555  mf::LogVerbatim myprt("TC");
556  myprt<<fcnLabel<<" Detach 3S"<<ss3.ID<<" -> P"<<pfp.ID<<"_"<<end<<" -> 3V"<<pfp.Vx3ID[end];
557  if(pfp.ParentID > 0) myprt<<" ->Parent P"<<pfp.ParentID;
558  }
559  // remove P -> P parent-daughter assn
560  pfp.Vx3ID[end] = 0;
561  if(pfp.ParentID > 0) {
562  auto& parentPFP = tjs.pfps[pfp.ParentID - 1];
563  std::vector<int> newDtrIDs;
564  for(auto did : parentPFP.DtrIDs) if(did != pfp.ID) newDtrIDs.push_back(did);
565  parentPFP.DtrIDs = newDtrIDs;
566  } // pfp Parent exists
567  } // end
568  } // pid
569  } // ss3
570  } // parentSearchDone
571 
572  unsigned int cstat = tpcid.Cryostat;
573  unsigned int tpc = tpcid.TPC;
574  // now look for 2D showers that not matched in 3D and have tjs
575  // that are 3D-matched
576  for(auto& ss : tjs.cots) {
577  if(ss.ID == 0) continue;
578  if(ss.SS3ID > 0) continue;
579  if(DecodeCTP(ss.CTP).TPC != tpc) continue;
580  if(DecodeCTP(ss.CTP).Cryostat != cstat) continue;
581  std::vector<int> matchedTjs;
582  for(auto tid : ss.TjIDs) if(tjs.allTraj[tid - 1].AlgMod[kMat3D]) matchedTjs.push_back(tid);
583  if(matchedTjs.empty()) continue;
584  // try to merge it with an existing 3D-matched shower
585  int mergeWith3S = 0;
586  // The merge is compatible if it only matches to one shower
587  bool isCompatible = true;
588  for(auto tid : matchedTjs) {
589  auto TInP = GetAssns(tjs, "T", tid, "P");
590  if(TInP.empty()) continue;
591  // do some more checking. See what other showers the Tjs in the pfp
592  // may belong to in other planes
593  auto PIn3S = GetAssns(tjs, "P", TInP[0], "3S");
594  for(auto sid : PIn3S) {
595  // require that the energy be lower
596  auto& ss3 = tjs.showers[sid - 1];
597  if(ss.Energy > ShowerEnergy(ss3)) continue;
598  if(mergeWith3S == 0) mergeWith3S = sid;
599  if(mergeWith3S > 0 && mergeWith3S != sid) isCompatible = false;
600  } // sid
601  } // tid
602  if(prt) {
603  mf::LogVerbatim myprt("TC");
604  myprt<<fcnLabel<<" 2S"<<ss.ID<<" is not 3D-matched but has 3D-matched Tjs:";
605  for(auto tid : matchedTjs) {
606  myprt<<" T"<<tid;
607  auto TInP = GetAssns(tjs, "T", tid, "P");
608  if(!TInP.empty()) {
609  myprt<<"->P"<<TInP[0];
610  } // TInP not empty
611  } // tid
612  } // prt
613  if(mergeWith3S == 0 && ss.Energy < 50) {
614  // kill it
615  MakeShowerObsolete(fcnLabel, tjs, ss, prt);
616  } else if(mergeWith3S > 0 && isCompatible) {
617  auto& ss3 = tjs.showers[mergeWith3S - 1];
618  for(auto cid : ss3.CotIDs) {
619  auto& oss = tjs.cots[cid - 1];
620  if(oss.CTP != ss.CTP) continue;
621  if(!MergeShowersAndStore(fcnLabel, tjs, oss.ID, ss.ID, prt)) {
622  std::cout<<fcnLabel<<" Merge failed\n";
623  }
624  if(!UpdateShower(fcnLabel, tjs, oss, prt)) {
625  std::cout<<fcnLabel<<" UpdateShower failed\n";
626  }
627  ss3.NeedsUpdate = true;
628  if(!UpdateShower(fcnLabel, tjs, ss3, prt)) {
629  std::cout<<fcnLabel<<" UpdateShower failed\n";
630  }
631  break;
632  } // cid
633  } // mergeWith3S > 0
634  } // ss
635 
636 
637  if(prt) Print2DShowers("R3D2o", tjs, USHRT_MAX, false);
638 
639  ChkAssns(fcnLabel, tjs);
640 
641  return true;
642  } // Reconcile3D
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void MakeShowerObsolete(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3334
bool AddPFP(std::string inFcnLabel, TjStuff &tjs, int pID, ShowerStruct3D &ss3, bool doUpdate, bool prt)
Definition: TCShower.cxx:1570
bool MergeShowersAndStore(std::string inFcnLabel, TjStuff &tjs, int icotID, int jcotID, bool prt)
Definition: TCShower.cxx:3053
void Print2DShowers(std::string someText, const TjStuff &tjs, CTP_t inCTP, bool printKilledShowers)
Definition: TCShower.cxx:4713
bool RemovePFP(std::string inFcnLabel, TjStuff &tjs, PFPStruct &pfp, ShowerStruct3D &ss3, bool doUpdate, bool prt)
Definition: TCShower.cxx:1547
bool ChkAssns(std::string inFcnLabel, TjStuff &tjs)
Definition: TCShower.cxx:4625
Float_t ss
Definition: plot.C:23
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:214
float ShowerEnergy(const TjStuff &tjs, const std::vector< int > tjIDs)
Definition: TCShower.cxx:4447
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
float InShowerProb(const TjStuff &tjs, const ShowerStruct &ss, const Trajectory &tj)
Definition: TCShower.cxx:2196
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
std::vector< int > GetAssns(const TjStuff &tjs, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4079
bool UpdateShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1302
bool tca::Reconcile3D ( std::string  inFcnLabel,
TjStuff tjs,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 645 of file TCShower.cxx.

References AddPFP(), evd::details::begin(), tca::ShowerStruct3D::ChgPos, ChkAssns(), tca::ShowerStruct3D::CotIDs, tca::TjStuff::cots, evd::details::end(), FarEnd(), GetAssns(), tca::ShowerStruct3D::ID, InShowerProb(), tca::TjStuff::pfps, PosSep(), Print2DShowers(), RemovePFP(), SetDifference(), ss, and UpdateShower().

Referenced by FindShowers3D(), and Match2DShowers().

646  {
647  // checks consistency between pfparticles, showers and tjs associated with ss3
648  if(ss3.ID == 0) return false;
649  // it isn't a failure if there is a 3D shower in two planes
650  if(ss3.CotIDs.size() < 3) return true;
651  std::string fcnLabel = inFcnLabel + ".R3D";
652 
653  if(prt) Print2DShowers("R3Di", tjs, USHRT_MAX, false);
654 
655  // make local copies so we can recover from a failure
656  auto oldSS3 = ss3;
657  std::vector<ShowerStruct> oldSS(ss3.CotIDs.size());
658  for(unsigned short ii = 0; ii < ss3.CotIDs.size(); ++ii) {
659  oldSS[ii] = tjs.cots[ss3.CotIDs[ii] - 1];
660  }
661 
662  std::vector<std::vector<int>> plist(ss3.CotIDs.size());
663  for(unsigned short ci = 0; ci < ss3.CotIDs.size(); ++ci) {
664  auto& ss = tjs.cots[ss3.CotIDs[ci] - 1];
665  for(auto tid : ss.TjIDs) {
666  auto tToP = GetAssns(tjs, "T", tid, "P");
667  if(tToP.empty()) continue;
668  // there should only be one pfp for a tj
669  int pid = tToP[0];
670  if(std::find(plist[ci].begin(), plist[ci].end(), pid) == plist[ci].end()) plist[ci].push_back(pid);
671  } // tid
672  } // ci
673  // count the occurrence of each pfp
674  std::vector<std::array<int, 2>> p_cnt;
675  for(auto& pl : plist) {
676  for(auto pid : pl) {
677  unsigned short indx = 0;
678  for(indx = 0; indx < p_cnt.size(); ++indx) if(p_cnt[indx][0] == pid) break;
679  if(indx == p_cnt.size()) {
680  // not found so add it
681  p_cnt.push_back(std::array<int,2> {{pid, 1}});
682  } else {
683  ++p_cnt[indx][1];
684  }
685  } // pid
686  } // pl
687  if(prt) {
688  mf::LogVerbatim myprt("TC");
689  myprt<<fcnLabel<<" 3S"<<ss3.ID<<"\n";
690  for(unsigned short ci = 0; ci < ss3.CotIDs.size(); ++ci) {
691  myprt<<" -> 2S"<<ss3.CotIDs[ci]<<" ->";
692  for(auto pid : plist[ci]) myprt<<" P"<<pid;
693  myprt<<"\n";
694  } // ci
695  myprt<<" P<ID>_count:";
696  for(auto& pc : p_cnt) myprt<<" P"<<pc[0]<<"_"<<pc[1];
697  } // prt
698 
699  for(auto& pc : p_cnt) {
700  // matched in all planes?
701  if(pc[1] == (int)ss3.CotIDs.size()) continue;
702  if(pc[1] == 2) {
703  // missing a tj in a plane or is this a two-plane pfp?
704  auto& pfp = tjs.pfps[pc[0] - 1];
705  if(pfp.TjIDs.size() > 2) {
706  // ensure that none of the tjs in this pfp are included in a different shower
707  auto PIn2S = GetAssns(tjs, "P", pfp.ID, "2S");
708  auto sDiff = SetDifference(PIn2S, ss3.CotIDs);
709  // Not sure if this can happen
710 // if(sDiff.size() > 1) {std::cout<<fcnLabel<<" sDiff size > 2. Is this possible?\n";}
711  if(!sDiff.empty() && std::find(ss3.CotIDs.begin(), ss3.CotIDs.end(), sDiff[0]) == ss3.CotIDs.end()) continue;
712  if(prt) {
713  mf::LogVerbatim myprt("TC");
714  myprt<<fcnLabel<<" 3S"<<ss3.ID<<" P"<<pfp.ID<<" ->";
715  for(auto sid : PIn2S) myprt<<" 2S"<<sid;
716  myprt<<" sDiff";
717  for(auto sid : sDiff) myprt<<" 2S"<<sid;
718  } // prt
719  // missed a tj in a 2D shower so "add the PFP to the shower" and update it
720  if(AddPFP(fcnLabel, tjs, pfp.ID, ss3, true, prt)) {
721  // Update the local copies
722  oldSS3 = ss3;
723  if(ss3.CotIDs.size() != oldSS.size()) {
724  std::cout<<fcnLabel<<" Major failure...";
725  return false;
726  }
727  for(unsigned short ii = 0; ii < ss3.CotIDs.size(); ++ii) oldSS[ii] = tjs.cots[ss3.CotIDs[ii] - 1];
728  } else {
729  // restore the previous state
730  ss3 = oldSS3;
731  for(unsigned short ii = 0; ii < oldSS.size(); ++ii) {
732  auto& ss = oldSS[ii];
733  tjs.cots[ss.ID - 1] = ss;
734  } // ii
735  } // AddPFP failed
736  } // pfp.TjIDs.size() > 2
737  } else {
738  // only one occurrence. check proximity to ss3
739  auto& pfp = tjs.pfps[pc[0] - 1];
740  unsigned short nearEnd = 1 - FarEnd(tjs, pfp, ss3.ChgPos);
741  float prob = InShowerProb(tjs, ss3, pfp);
742  float sep = PosSep(pfp.XYZ[nearEnd], ss3.ChgPos);
743  if(prt) {
744  mf::LogVerbatim myprt("TC");
745  myprt<<fcnLabel<<" one occurrence: P"<<pfp.ID<<"_"<<nearEnd<<" closest to ChgPos";
746  myprt<<" ChgPos "<<std::fixed<<std::setprecision(1)<<ss3.ChgPos[0]<<" "<<ss3.ChgPos[1]<<" "<<ss3.ChgPos[2];
747  myprt<<" sep "<<sep;
748  myprt<<" InShowerProb "<<prob;
749  } // prt
750  if(sep < 30 && prob > 0.3 && AddPFP(fcnLabel, tjs, pfp.ID, ss3, true, prt)) {
751  if(prt) mf::LogVerbatim("TC")<<" AddPFP success";
752  } else if(!RemovePFP(fcnLabel, tjs, pfp, ss3, true, prt)) {
753  std::cout<<"RemovePFP failed \n";
754  }
755  } // only one occurrence.
756  } // pc
757 
758  if(!UpdateShower(fcnLabel, tjs, ss3, prt)) return false;
759  ChkAssns(fcnLabel, tjs);
760  if(prt) Print2DShowers("R3Do", tjs, USHRT_MAX, false);
761 
762  return true;
763 
764  } // Reconcile3D
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool AddPFP(std::string inFcnLabel, TjStuff &tjs, int pID, ShowerStruct3D &ss3, bool doUpdate, bool prt)
Definition: TCShower.cxx:1570
void Print2DShowers(std::string someText, const TjStuff &tjs, CTP_t inCTP, bool printKilledShowers)
Definition: TCShower.cxx:4713
bool RemovePFP(std::string inFcnLabel, TjStuff &tjs, PFPStruct &pfp, ShowerStruct3D &ss3, bool doUpdate, bool prt)
Definition: TCShower.cxx:1547
bool ChkAssns(std::string inFcnLabel, TjStuff &tjs)
Definition: TCShower.cxx:4625
Float_t ss
Definition: plot.C:23
unsigned short FarEnd(const TjStuff &tjs, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:2936
std::vector< evd::details::RawDigitInfo_t >::const_iterator begin(RawDigitCacheDataClass const &cache)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
std::vector< T > SetDifference(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:236
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
float InShowerProb(const TjStuff &tjs, const ShowerStruct &ss, const Trajectory &tj)
Definition: TCShower.cxx:2196
std::vector< int > GetAssns(const TjStuff &tjs, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4079
bool UpdateShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1302
bool tca::RefineVtxPosition ( TjStuff tjs,
const Trajectory tj,
unsigned short &  nearPt,
short  nPtsToChk,
bool  prt 
)

Definition at line 2735 of file TCVertex.cxx.

References tca::Trajectory::EndPt, PrintPos(), and tca::Trajectory::Pts.

Referenced by CompleteIncomplete3DVertices().

2736  {
2737  // The tj has been slated to be split somewhere near point nearPt. This function will move
2738  // the near point a bit to the most likely point of a vertex
2739 
2740  float maxChg = tj.Pts[nearPt].Chg;
2741  short maxChgPt = nearPt;
2742 
2743  for(short ipt = nearPt - nPtsToChk; ipt < nearPt + nPtsToChk; ++ipt) {
2744  if(ipt < tj.EndPt[0] || ipt > tj.EndPt[1]) continue;
2745  auto& tp = tj.Pts[ipt];
2746  if(tp.Chg > maxChg) {
2747  maxChg = tp.Chg;
2748  maxChgPt = ipt;
2749  }
2750  if(prt) mf::LogVerbatim("TC")<<"RVP: ipt "<<ipt<<" Pos "<<tp.CTP<<":"<<PrintPos(tjs, tp.Pos)<<" chg "<<(int)tp.Chg<<" nhits "<<tp.Hits.size();
2751  } // ipt
2752  if(nearPt == maxChgPt) return false;
2753  nearPt = maxChgPt;
2754  return true;
2755  } //RefineVtxPosition
std::string PrintPos(const TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:4738
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void tca::ReleaseHits ( TjStuff tjs,
Trajectory tj 
)

Definition at line 1070 of file Utils.cxx.

References tca::TjStuff::fHits, tca::Trajectory::ID, and tca::Trajectory::Pts.

Referenced by tca::TrajClusterAlg::FindVtxTraj(), tca::TrajClusterAlg::MakeJunkTraj(), tca::TrajClusterAlg::ReconstructAllTraj(), and StoreTraj().

1071  {
1072  // Sets InTraj[] = 0 for all TPs in work. Called when abandoning work
1073  for(auto& tp : tj.Pts) {
1074  for(auto iht : tp.Hits) {
1075  if(tjs.fHits[iht].InTraj == tj.ID) tjs.fHits[iht].InTraj = 0;
1076  }
1077  } // tp
1078 
1079  } // ReleaseWorkHits
bool tca::RemovePFP ( std::string  inFcnLabel,
TjStuff tjs,
int  pID,
ShowerStruct3D ss3,
bool  doUpdate,
bool  prt 
)
bool tca::RemovePFP ( std::string  inFcnLabel,
TjStuff tjs,
PFPStruct pfp,
ShowerStruct3D ss3,
bool  doUpdate,
bool  prt 
)

Definition at line 1547 of file TCShower.cxx.

References tca::ShowerStruct3D::CotIDs, tca::TjStuff::cots, tca::PFPStruct::ID, tca::ShowerStruct3D::ID, tca::ShowerStruct3D::NeedsUpdate, RemoveTj(), ss, tca::PFPStruct::TjIDs, and UpdateShower().

Referenced by Reconcile3D().

1548  {
1549  // removes the tjs in the pfp from the ss3 2D showers and optionally update. This function only returns
1550  // false if there was a failure. The absence of any pfp Tjs in ss3 is not considered a failure
1551 
1552  if(pfp.ID == 0 || ss3.ID == 0) return false;
1553 
1554  std::string fcnLabel = inFcnLabel + ".RemP";
1555  for(auto tid : pfp.TjIDs) {
1556  for(auto cid : ss3.CotIDs) {
1557  auto& ss = tjs.cots[cid - 1];
1558  if(std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tid) == ss.TjIDs.end()) continue;
1559  if(!RemoveTj(fcnLabel, tjs, tid, ss, doUpdate, prt)) return false;
1560  ss3.NeedsUpdate = true;
1561  } // cid
1562  } // ptid
1563 
1564  if(doUpdate && ss3.NeedsUpdate) UpdateShower(fcnLabel, tjs, ss3, prt);
1565  return true;
1566 
1567  } // Remove PFP
Float_t ss
Definition: plot.C:23
bool RemoveTj(std::string inFcnLabel, TjStuff &tjs, int TjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1691
bool UpdateShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1302
bool tca::RemoveTj ( std::string  inFcnLabel,
TjStuff tjs,
int  TjID,
ShowerStruct ss,
bool  doUpdate,
bool  prt 
)

Definition at line 1691 of file TCShower.cxx.

References tca::Trajectory::AlgMod, tca::TjStuff::allTraj, tca::ShowerStruct::ID, kShwrParent, MakeShowerObsolete(), tca::ShowerStruct::NeedsUpdate, tca::ShowerStruct::ParentID, tca::ShowerStruct::ShPts, tca::Trajectory::SSID, tca::ShowerStruct::TjIDs, and UpdateShower().

Referenced by RemovePFP().

1692  {
1693  // Removes the Tj from a shower
1694 
1695  if(TjID > (int)tjs.allTraj.size()) return false;
1696 
1697  std::string fcnLabel = inFcnLabel + ".RTj";
1698 
1699  // make sure it isn't already in a shower
1700  Trajectory& tj = tjs.allTraj[TjID - 1];
1701 
1702  if(tj.SSID != ss.ID) {
1703  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Can't Remove T"<<TjID<<" from 2S"<<ss.ID<<" because it's not in this shower";
1704  // This isn't a failure
1705  return true;
1706  }
1707  tj.AlgMod[kShwrParent] = false;
1708 
1709  bool gotit = false;
1710  for(unsigned short ii = 0; ii < ss.TjIDs.size(); ++ii) {
1711  if(TjID == ss.TjIDs[ii]) {
1712  ss.TjIDs.erase(ss.TjIDs.begin() + ii);
1713  gotit = true;
1714  break;
1715  }
1716  } // ii
1717  if(!gotit) return false;
1718  tj.SSID = 0;
1719  // Removing a parent Tj?
1720  if(TjID == ss.ParentID) ss.ParentID = 0;
1721  // re-build everything?
1722  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Remove T"<<TjID<<" from 2S"<<ss.ID;
1723  // removed the only tj
1724  if(ss.TjIDs.empty()) {
1725  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Removed the last Tj. Killing 2S"<<ss.ID;
1726  MakeShowerObsolete(fcnLabel, tjs, ss, prt);
1727  return true;
1728  }
1729  // clear out the shower points to force a complete update when UpdateShower is next called
1730  ss.ShPts.clear();
1731  if(doUpdate) {
1732  ss.NeedsUpdate = true;
1733  return UpdateShower(fcnLabel, tjs, ss, prt);
1734  }
1735  return true;
1736  } // RemoveTj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void MakeShowerObsolete(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3334
Float_t ss
Definition: plot.C:23
bool UpdateShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1302
void tca::RestoreObsoleteTrajectory ( TjStuff tjs,
unsigned int  itj 
)

Definition at line 1808 of file Utils.cxx.

References tca::TjStuff::allTraj, tca::TjStuff::fHits, and kKilled.

1809  {
1810  if(itj > tjs.allTraj.size() - 1) return;
1811  if(!tjs.allTraj[itj].AlgMod[kKilled]) {
1812  mf::LogWarning("TC")<<"RestoreObsoleteTrajectory: Trying to restore not-obsolete trajectory "<<tjs.allTraj[itj].ID;
1813  return;
1814  }
1815  unsigned int iht;
1816  for(auto& tp : tjs.allTraj[itj].Pts) {
1817  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1818  if(tp.UseHit[ii]) {
1819  iht = tp.Hits[ii];
1820  if(tjs.fHits[iht].InTraj == 0) {
1821  tjs.fHits[iht].InTraj = tjs.allTraj[itj].ID;
1822  }
1823  }
1824  } // ii
1825  } // tp
1826  tjs.allTraj[itj].AlgMod[kKilled] = false;
1827  } // RestoreObsoleteTrajectory
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
void tca::Reverse3DMatchTjs ( TjStuff tjs,
PFPStruct pfp,
bool  prt 
)

Definition at line 996 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::TjStuff::allTraj, tca::PFPStruct::dEdx, tca::PFPStruct::dEdxErr, tca::PFPStruct::Dir, tca::PFPStruct::DirErr, kBragg, kMat3D, tca::PFPStruct::PDGCode, ReverseTraj(), tca::PFPStruct::TjIDs, tca::PFPStruct::Vx3ID, and tca::PFPStruct::XYZ.

997  {
998  // Return true if the 3D matched hits in the trajectories in tjs.pfps are in the wrong order in terms of the
999  // physics standpoint, e.g. dQ/dx, muon delta-ray tag, cosmic rays entering the detector, etc.
1000 
1001  // Don't reverse showers
1002  if(pfp.PDGCode == 1111) return;
1003 
1004  bool reverseMe = false;
1005 
1006  // look for stopping Tjs for contained PFParticles
1007  if(!reverseMe) {
1008  unsigned short braggCnt0 = 0;
1009  unsigned short braggCnt1 = 0;
1010  for(auto& tjID : pfp.TjIDs) {
1011  auto& tj = tjs.allTraj[tjID - 1];
1012  if(tj.StopFlag[0][kBragg]) ++braggCnt0;
1013  if(tj.StopFlag[1][kBragg]) ++braggCnt1;
1014  }
1015  if(braggCnt0 > 0 || braggCnt1 > 0) {
1016  pfp.PDGCode = 2212;
1017  // Vote for a Bragg peak at the beginning. It should be at the end
1018  if(braggCnt0 > braggCnt1) reverseMe = true;
1019  } // found a Bragg Peak
1020  } // look for stopping Tjs
1021 
1022  if(!reverseMe) return;
1023 
1024  // All of the trajectories should be reversed
1025  for(auto& tjID : pfp.TjIDs) {
1026  unsigned short itj = tjID - 1;
1027  Trajectory& tj = tjs.allTraj[itj];
1028  tj.AlgMod[kMat3D] = false;
1029  ReverseTraj(tjs, tj);
1030  tj.AlgMod[kMat3D] = true;
1031  } // tjID
1032  // swap the matchVec end info also
1033  std::swap(pfp.XYZ[0], pfp.XYZ[1]);
1034  std::swap(pfp.Dir[0], pfp.Dir[1]);
1035  std::swap(pfp.DirErr[0], pfp.DirErr[1]);
1036  std::swap(pfp.dEdx[0], pfp.dEdx[1]);
1037  std::swap(pfp.dEdxErr[0], pfp.dEdxErr[1]);
1038  std::swap(pfp.Vx3ID[0], pfp.Vx3ID[1]);
1039 
1040  return;
1041 
1042  } // Reverse3DMatchTjs
void ReverseTraj(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:2666
void swap(art::HLTGlobalStatus &lhs, art::HLTGlobalStatus &rhs)
void tca::ReversePFP ( TjStuff tjs,
PFPStruct pfp 
)

Definition at line 2837 of file PFPUtils.cxx.

References tca::PFPStruct::dEdx, tca::PFPStruct::dEdxErr, tca::PFPStruct::Dir, tca::PFPStruct::DirErr, tca::PFPStruct::StopFlag, tca::PFPStruct::Tp3s, tca::PFPStruct::Vx3ID, and tca::PFPStruct::XYZ.

Referenced by DotProd().

2838  {
2839  std::swap(pfp.XYZ[0], pfp.XYZ[1]);
2840  std::swap(pfp.Dir[0], pfp.Dir[1]);
2841  for(unsigned short xyz = 0; xyz < 3; ++xyz) {
2842  pfp.Dir[0][xyz] *= -1;
2843  pfp.Dir[1][xyz] *= -1;
2844  }
2845  std::swap(pfp.DirErr[0], pfp.DirErr[1]);
2846  std::swap(pfp.dEdx[0], pfp.dEdx[1]);
2847  std::swap(pfp.dEdxErr[0], pfp.dEdxErr[1]);
2848  std::swap(pfp.Vx3ID[0], pfp.Vx3ID[1]);
2849  std::swap(pfp.StopFlag[0], pfp.StopFlag[1]);
2850  std::reverse(pfp.Tp3s.begin(), pfp.Tp3s.end());
2851  for(auto& tp3 : pfp.Tp3s) {
2852  for(unsigned short xyz = 0; xyz < 3; ++xyz) {
2853  tp3.Dir[xyz] *= -1;
2854  tp3.Dir[xyz] *= -1;
2855  } // xyz
2856  } // tp3
2857  } // ReversePFP
void swap(art::HLTGlobalStatus &lhs, art::HLTGlobalStatus &rhs)
void tca::ReverseShower ( std::string  inFcnLabel,
TjStuff tjs,
ShowerStruct ss,
bool  prt 
)

Definition at line 3269 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::ShowerStruct::Angle, DefineEnvelope(), tca::ShowerStruct::DirectionFOM, tca::ShowerStruct::ID, ReverseTraj(), tca::ShowerStruct::ShowerTjID, tca::ShowerStruct::ShPts, and tca::ShowerStruct::TjIDs.

3270  {
3271  // Reverses the shower and the shower tj
3272 
3273  if(ss.ID == 0) return;
3274  if(ss.TjIDs.empty()) return;
3275 
3276  std::string fcnLabel = inFcnLabel + ".RevSh";
3277 
3278  std::reverse(ss.ShPts.begin(), ss.ShPts.end());
3279  // change the sign of RotPos
3280  for(auto& sspt : ss.ShPts) {
3281  sspt.RotPos[0] = -sspt.RotPos[0];
3282  sspt.RotPos[1] = -sspt.RotPos[1];
3283  }
3284  // flip the shower angle
3285  if(ss.Angle > 0) {
3286  ss.Angle -= M_PI;
3287  } else {
3288  ss.Angle += M_PI;
3289  }
3290  if(ss.DirectionFOM != 0) ss.DirectionFOM = 1 / ss.DirectionFOM;
3291  auto& stj = tjs.allTraj[ss.ShowerTjID - 1];
3292  ReverseTraj(tjs, stj);
3293  DefineEnvelope(fcnLabel, tjs, ss, prt);
3294  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Reversed shower. Shower angle = "<<ss.Angle;
3295  } // ReverseShower
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
Float_t ss
Definition: plot.C:23
void ReverseTraj(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:2666
void DefineEnvelope(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3936
void tca::ReverseShower ( std::string  inFcnLabel,
TjStuff tjs,
int  cotID,
bool  prt 
)

Definition at line 3298 of file TCShower.cxx.

References tca::TjStuff::cots, tca::ShowerStruct::ID, and ss.

Referenced by FindShowerStart(), and UpdateShower().

3299  {
3300  // Reverses the shower and the shower tj
3301 
3302  if(cotID > (int)tjs.cots.size()) return;
3303  ShowerStruct& ss = tjs.cots[cotID - 1];
3304  if(ss.ID == 0) return;
3305  ReverseShower(inFcnLabel, tjs, ss, prt);
3306 
3307  }
Float_t ss
Definition: plot.C:23
void ReverseShower(std::string inFcnLabel, TjStuff &tjs, int cotID, bool prt)
Definition: TCShower.cxx:3298
void tca::ReverseTraj ( TjStuff tjs,
Trajectory tj 
)

Definition at line 2666 of file Utils.cxx.

References tca::Trajectory::dEdx, tca::Trajectory::DirFOM, tca::Trajectory::ID, tca::Trajectory::Pts, SetEndPoints(), tca::Trajectory::StepDir, tca::Trajectory::StopFlag, UpdateMatchStructs(), and tca::Trajectory::VtxID.

Referenced by DefineTjParents(), tca::TrajClusterAlg::EndMerge(), MergeAndStore(), MergePFPTjs(), tca::TrajClusterAlg::ReconstructAllTraj(), Reverse3DMatchTjs(), tca::TrajClusterAlg::ReversePropagate(), ReverseShower(), StorePFP(), TagDeltaRays(), and TagMuonDirections().

2667  {
2668  // reverse the trajectory
2669  if(tj.Pts.empty()) return;
2670 /*
2671  if(tj.AlgMod[kMat3D]) {
2672  std::cout<<"Trying to reverse 3D matched Tj "<<tj.ID<<". Need to modify other Tjs and the MatchStruct\n";
2673  return;
2674  }
2675  if(tj.AlgMod[kSetDir]) {
2676  std::cout<<"Trying to reverse Tj "<<tj.ID<<" whose direction has been set. Not doing it.\n";
2677  return;
2678  }
2679 */
2680  // reverse the crawling direction flag
2681  tj.StepDir = -tj.StepDir;
2682  tj.DirFOM = 1 - tj.DirFOM;
2683  // Vertices
2684  std::swap(tj.VtxID[0], tj.VtxID[1]);
2685  // trajectory points
2686  std::reverse(tj.Pts.begin(), tj.Pts.end());
2687  // reverse the stop flag
2688  std::reverse(tj.StopFlag.begin(), tj.StopFlag.end());
2689  std::swap(tj.dEdx[0], tj.dEdx[1]);
2690  // reverse the direction vector on all points
2691  for(unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) {
2692  if(tj.Pts[ipt].Dir[0] != 0) tj.Pts[ipt].Dir[0] = -tj.Pts[ipt].Dir[0];
2693  if(tj.Pts[ipt].Dir[1] != 0) tj.Pts[ipt].Dir[1] = -tj.Pts[ipt].Dir[1];
2694  if(tj.Pts[ipt].Ang > 0) {
2695  tj.Pts[ipt].Ang -= M_PI;
2696  } else {
2697  tj.Pts[ipt].Ang += M_PI;
2698  }
2699  } // ipt
2700  SetEndPoints(tjs, tj);
2701  UpdateMatchStructs(tjs, tj.ID, tj.ID);
2702  } // ReverseTraj
void UpdateMatchStructs(TjStuff &tjs, int oldTj, int newTj)
Definition: PFPUtils.cxx:16
void swap(art::HLTGlobalStatus &lhs, art::HLTGlobalStatus &rhs)
void SetEndPoints(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:2788
void tca::SaveAllCots ( TjStuff tjs,
const CTP_t inCTP,
std::string  someText 
)

Definition at line 165 of file TCShTree.cxx.

References tca::TjStuff::cots, tca::TjStuff::SaveShowerTree, SaveTjInfo(), and ss.

Referenced by FindShowers3D().

165  {
166  if(!tjs.SaveShowerTree) return;
167  for(unsigned short cotIndex = 0; cotIndex < tjs.cots.size(); ++cotIndex) {
168  auto& ss = tjs.cots[cotIndex];
169  if (ss.CTP != inCTP) continue;
170  if(ss.ID == 0) continue;
171  SaveTjInfo(tjs, ss, someText);
172  } // cotIndex
173  } // SaveAllCots
Float_t ss
Definition: plot.C:23
void SaveTjInfo(TjStuff &tjs, const ShowerStruct &ss, std::string stageName)
Definition: TCShTree.cxx:47
void tca::SaveAllCots ( TjStuff tjs,
std::string  someText 
)

Definition at line 176 of file TCShTree.cxx.

References tca::TjStuff::cots, tca::TjStuff::SaveShowerTree, SaveTjInfo(), and ss.

176  {
177  if(!tjs.SaveShowerTree) return;
178  for(unsigned short cotIndex = 0; cotIndex < tjs.cots.size(); ++cotIndex) {
179  auto& ss = tjs.cots[cotIndex];
180  if(ss.ID == 0) continue;
181  SaveTjInfo(tjs, ss, someText);
182  } // cotIndex
183  }
Float_t ss
Definition: plot.C:23
void SaveTjInfo(TjStuff &tjs, const ShowerStruct &ss, std::string stageName)
Definition: TCShTree.cxx:47
void tca::SaveCRInfo ( TjStuff tjs,
PFPStruct pfp,
bool  prt,
bool  fIsRealData 
)

Definition at line 8 of file TCCR.cxx.

References tca::PFPStruct::CosmicScore, tca::CRTreeVars::cr_origin, tca::CRTreeVars::cr_pfpxmax, tca::CRTreeVars::cr_pfpxmin, tca::CRTreeVars::cr_pfpyzmindis, tca::TjStuff::crt, tca::TjStuff::geom, GetOrigin(), max, geo::BoxBoundedGeo::MaxY(), geo::BoxBoundedGeo::MaxZ(), min, geo::BoxBoundedGeo::MinY(), geo::BoxBoundedGeo::MinZ(), tca::TjStuff::SaveCRTree, geo::GeometryCore::TPC(), and tca::PFPStruct::XYZ.

Referenced by tca::TrajClusterAlg::RunTrajClusterAlg().

8  {
9 
10  //Check the origin of pfp
11  if (tjs.SaveCRTree){
12  if (fIsRealData){
13  tjs.crt.cr_origin.push_back(-1);
14  }
15  else{
16  tjs.crt.cr_origin.push_back(GetOrigin(tjs, pfp));
17  }
18  }
19 
20  // save the xmin and xmax of each pfp
21  tjs.crt.cr_pfpxmin.push_back(std::min(pfp.XYZ[0][0], pfp.XYZ[1][0]));
22  tjs.crt.cr_pfpxmax.push_back(std::max(pfp.XYZ[0][0], pfp.XYZ[1][0]));
23 
24  //find max
25  const geo::TPCGeo &tpc = tjs.geom->TPC(0);
26  float mindis0 = FLT_MAX;
27  float mindis1 = FLT_MAX;
28  if (std::abs(pfp.XYZ[0][1] - tpc.MinY())<mindis0) mindis0 = std::abs(pfp.XYZ[0][1] - tpc.MinY());
29  if (std::abs(pfp.XYZ[0][1] - tpc.MaxY())<mindis0) mindis0 = std::abs(pfp.XYZ[0][1] - tpc.MaxY());
30  if (std::abs(pfp.XYZ[0][2] - tpc.MinZ())<mindis0) mindis0 = std::abs(pfp.XYZ[0][2] - tpc.MinZ());
31  if (std::abs(pfp.XYZ[0][2] - tpc.MaxZ())<mindis0) mindis0 = std::abs(pfp.XYZ[0][2] - tpc.MaxZ());
32  if (std::abs(pfp.XYZ[1][1] - tpc.MinY())<mindis1) mindis1 = std::abs(pfp.XYZ[1][1] - tpc.MinY());
33  if (std::abs(pfp.XYZ[1][1] - tpc.MaxY())<mindis1) mindis1 = std::abs(pfp.XYZ[1][1] - tpc.MaxY());
34  if (std::abs(pfp.XYZ[1][2] - tpc.MinZ())<mindis1) mindis1 = std::abs(pfp.XYZ[1][2] - tpc.MinZ());
35  if (std::abs(pfp.XYZ[1][2] - tpc.MaxZ())<mindis1) mindis1 = std::abs(pfp.XYZ[1][2] - tpc.MaxZ());
36  //std::cout<<pfp.XYZ[0][1]<<" "<<pfp.XYZ[0][2]<<" "<<pfp.XYZ[1][1]<<" "<<pfp.XYZ[1][2]<<" "<<tpc.MinY()<<" "<<tpc.MaxY()<<" "<<tpc.MinZ()<<" "<<tpc.MaxZ()<<" "<<mindis0<<" "<<mindis1<<" "<<mindis0+mindis1<<std::endl;
37  tjs.crt.cr_pfpyzmindis.push_back(mindis0+mindis1);
38 
39  if (tjs.crt.cr_pfpxmin.back()<-2||
40  tjs.crt.cr_pfpxmax.back()>260||
41  tjs.crt.cr_pfpyzmindis.back()<30){
42  pfp.CosmicScore = 1.;
43  }
44  else pfp.CosmicScore = 0;
45 
46  /*
47  float minx = FLT_MAX;
48  float maxx = FLT_MIN;
49 
50  for(auto& tjID : pfp.TjIDs) {
51  Trajectory& tj = tjs.allTraj[tjID - 1];
52  TrajPoint& beginPoint = tj.Pts[tj.EndPt[0]];
53  TrajPoint& endPoint = tj.Pts[tj.EndPt[1]];
54  if (beginPoint.Pos[1]/tjs.UnitsPerTick<minx){
55  minx = beginPoint.Pos[1]/tjs.UnitsPerTick;
56  }
57  if (beginPoint.Pos[1]/tjs.UnitsPerTick>maxx){
58  maxx = beginPoint.Pos[1]/tjs.UnitsPerTick;
59  }
60  if (endPoint.Pos[1]/tjs.UnitsPerTick<minx){
61  minx = endPoint.Pos[1]/tjs.UnitsPerTick;
62  }
63  if (endPoint.Pos[1]/tjs.UnitsPerTick>maxx){
64  maxx = endPoint.Pos[1]/tjs.UnitsPerTick;
65  }
66  } // tjID
67 
68  tjs.crt.cr_pfpmintick.push_back(minx);
69  tjs.crt.cr_pfpmaxtick.push_back(maxx);
70  */
71 // std::cout<<pfp.MCPartListIndex<<std::endl;
72 // std::cout<<pfp.XYZ[0][0]<<" "<<pfp.XYZ[1][0]<<std::endl;
73 
74  }
Geometry information for a single TPC.
Definition: TPCGeo.h:37
Int_t max
Definition: plot.C:27
double MinZ() const
Returns the world z coordinate of the start of the box.
int GetOrigin(TjStuff &tjs, PFPStruct &pfp)
Definition: TCCR.cxx:77
double MaxY() const
Returns the world y coordinate of the end of the box.
Int_t min
Definition: plot.C:26
double MaxZ() const
Returns the world z coordinate of the end of the box.
double MinY() const
Returns the world y coordinate of the start of the box.
void tca::SaveTjInfo ( TjStuff tjs,
std::vector< std::vector< int >> &  tjList,
std::string  stageName 
)

Definition at line 5 of file TCShTree.cxx.

References tca::Trajectory::AlgMod, tca::TjStuff::allTraj, tca::Trajectory::CTP, tca::ShowerTreeVars::Envelope, tca::ShowerTreeVars::EnvPlane, tca::ShowerTreeVars::EnvShowerID, tca::ShowerTreeVars::EnvStage, GetStageNum(), tca::Trajectory::ID, kKilled, tca::TjStuff::SaveShowerTree, SaveTjInfoStuff(), tca::ShowerTreeVars::ShowerID, and tca::TjStuff::stv.

Referenced by FindShowers3D(), and SaveAllCots().

6  {
7  if(!tjs.SaveShowerTree) return;
8  if(tjList.empty()) return;
9  int stageNum = GetStageNum(tjs.stv, stageName);
10 
11  // get the CTP from the first tj
12  CTP_t inCTP = tjs.allTraj[tjList[0][0] - 1].CTP;
13  for(unsigned short it1 = 0; it1 < tjs.allTraj.size(); ++it1) {
14  Trajectory& tj1 = tjs.allTraj[it1];
15  if(tj1.CTP != inCTP) continue;
16  if(tj1.AlgMod[kKilled]) continue;
17 
18  SaveTjInfoStuff(tjs, tj1, stageNum, stageName);
19 
20  int trajID = tj1.ID;
21  bool inShower = false;
22 
23  for (size_t l1 = 0; l1 < tjList.size(); ++l1) {
24  if (inShower) break;
25  for (size_t l2 = 0; l2 < tjList[l1].size(); ++l2) {
26 
27  if (trajID == tjList[l1][l2]) {
28  tjs.stv.ShowerID.back() = l1;
29  inShower = true;
30  break;
31  }
32  } // end list loop 2
33  } // end list loop 1
34  } // end tjs loop
35  // add meaningless envelope to list for counting purposes
36  // envelopes are defined once DefineShower is called
37  // fill four times, one for each side of polygon
38  for (int i = 0; i < 8; i++) {
39  tjs.stv.Envelope.push_back(-999);
40  tjs.stv.EnvStage.push_back(stageNum);
41  tjs.stv.EnvPlane.push_back(-1);
42  tjs.stv.EnvShowerID.push_back(-1);
43  }
44 
45  } // SaveTjInfo (tjlist)
unsigned int CTP_t
Definition: DataStructs.h:41
void SaveTjInfoStuff(TjStuff &tjs, Trajectory &tj, int stageNum, std::string stageName)
Definition: TCShTree.cxx:131
int GetStageNum(ShowerTreeVars &stv, std::string stageName)
Definition: TCShTree.cxx:185
void tca::SaveTjInfo ( TjStuff tjs,
const ShowerStruct ss,
std::string  stageName 
)

Definition at line 47 of file TCShTree.cxx.

References tca::Trajectory::AlgMod, tca::TjStuff::allTraj, tca::ShowerStruct::CTP, DecodeCTP(), tca::ShowerStruct::Envelope, tca::ShowerTreeVars::Envelope, tca::ShowerTreeVars::EnvPlane, tca::ShowerTreeVars::EnvShowerID, tca::ShowerTreeVars::EnvStage, GetStageNum(), tca::Trajectory::ID, tca::ShowerStruct::ID, tca::ShowerTreeVars::IsShowerParent, tca::ShowerTreeVars::IsShowerTj, kKilled, kShowerTj, tca::ShowerStruct::ParentID, geo::PlaneID::Plane, tca::ShowerTreeVars::PlaneNum, tca::TjStuff::SaveShowerTree, SaveTjInfoStuff(), tca::ShowerTreeVars::ShowerID, tca::ShowerStruct::ShowerTjID, tca::ShowerTreeVars::StageNum, tca::TjStuff::stv, tca::ShowerTreeVars::TjID, tca::ShowerStruct::TjIDs, and tca::TjStuff::UnitsPerTick.

47  {
48  if(!tjs.SaveShowerTree) return;
49  int stageNum = GetStageNum(tjs.stv, stageName);
50 
51  // killed shower?
52  if(ss.ID == 0) return;
53 
54  bool noMatch = true;
55 
56  for(unsigned short it1 = 0; it1 < tjs.allTraj.size(); ++it1) {
57 
58  Trajectory& tj1 = tjs.allTraj[it1];
59 
60  if(tj1.AlgMod[kKilled]) continue;
61 
62  int trajID = tj1.ID;
63 
64  // check if this tj has already been added to the list
65  // for this particular stage and plane
66  int tjIndex = -1;
67  bool isShowerTj = false;
68  for (size_t i = 0; i < tjs.stv.TjID.size(); ++i) {
69  if (tjs.stv.StageNum.at(i) != (int)stageNum) continue;
70  if (tjs.stv.PlaneNum.at(i) != (short)DecodeCTP(ss.CTP).Plane) continue;
71 
72  if (tjs.stv.TjID.at(i) == trajID) {
73  tjIndex = i;
74  if (tjs.stv.IsShowerTj.at(tjIndex) == 1) isShowerTj = true;
75  //beenDoneBefore = true;
76  break;
77  }
78  }
79 
80  if (isShowerTj) continue;
81  if (tjIndex == -1) SaveTjInfoStuff(tjs, tj1, stageNum, stageName);
82 
83  for (size_t i = 0; i < ss.TjIDs.size(); ++i) {
84  if (trajID == ss.TjIDs[i]) {
85  noMatch = false;
86  if (tjIndex == -1) tjs.stv.ShowerID.back() = ss.ID;
87  else tjs.stv.ShowerID.at(tjIndex) = ss.ID;
88  }
89 
90  if (it1 == (ss.ShowerTjID - 1)) tjs.stv.IsShowerTj.back() = 1;
91  else if (tj1.AlgMod[kShowerTj]) tjs.stv.IsShowerTj.back() = 1; // this is a better check
92  // check if tj is shower parent. if so, add to ttree
93  // and mark parent flag
94  if (trajID == ss.ParentID) {
95  if (tjIndex == -1) {
96  tjs.stv.ShowerID.back() = ss.ID;
97  tjs.stv.IsShowerParent.back() = 1;
98  }
99  else {
100  tjs.stv.ShowerID.at(tjIndex) = ss.ID;
101  tjs.stv.IsShowerParent.at(tjIndex) = 1;
102  }
103  break;
104 
105  }
106  } // ss TjID loop
107  } // end tjs loop
108 
109  if (noMatch) return;
110 
111  // add envelope information to showertreevars
112  geo::PlaneID iPlnID = DecodeCTP(ss.CTP);
113 
114  for (int i = 0; i < 8; i++) {
115  tjs.stv.EnvStage.push_back(stageNum);
116  tjs.stv.EnvPlane.push_back(iPlnID.Plane);
117  tjs.stv.EnvShowerID.push_back(ss.ID);
118  }
119 
120  tjs.stv.Envelope.push_back(ss.Envelope[0][0]);
121  tjs.stv.Envelope.push_back(ss.Envelope[0][1]/tjs.UnitsPerTick);
122  tjs.stv.Envelope.push_back(ss.Envelope[1][0]);
123  tjs.stv.Envelope.push_back(ss.Envelope[1][1]/tjs.UnitsPerTick);
124  tjs.stv.Envelope.push_back(ss.Envelope[2][0]);
125  tjs.stv.Envelope.push_back(ss.Envelope[2][1]/tjs.UnitsPerTick);
126  tjs.stv.Envelope.push_back(ss.Envelope[3][0]);
127  tjs.stv.Envelope.push_back(ss.Envelope[3][1]/tjs.UnitsPerTick);
128 
129  } // SaveTjInfo (cots)
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
Float_t ss
Definition: plot.C:23
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
void SaveTjInfoStuff(TjStuff &tjs, Trajectory &tj, int stageNum, std::string stageName)
Definition: TCShTree.cxx:131
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
int GetStageNum(ShowerTreeVars &stv, std::string stageName)
Definition: TCShTree.cxx:185
void tca::SaveTjInfoStuff ( TjStuff tjs,
Trajectory tj,
int  stageNum,
std::string  stageName 
)

Definition at line 131 of file TCShTree.cxx.

References tca::TrajPoint::Ang, tca::ShowerTreeVars::BeginAng, tca::ShowerTreeVars::BeginChg, tca::ShowerTreeVars::BeginTim, tca::ShowerTreeVars::BeginVtx, tca::ShowerTreeVars::BeginWir, tca::TrajPoint::Chg, tca::Trajectory::CTP, DecodeCTP(), tca::ShowerTreeVars::EndAng, tca::ShowerTreeVars::EndChg, tca::Trajectory::EndPt, tca::ShowerTreeVars::EndTim, tca::ShowerTreeVars::EndVtx, tca::ShowerTreeVars::EndWir, tca::Trajectory::ID, tca::ShowerTreeVars::IsShowerParent, tca::ShowerTreeVars::IsShowerTj, tca::Trajectory::MCSMom, tca::ShowerTreeVars::MCSMom, tca::ShowerTreeVars::nPlanes, tca::ShowerTreeVars::nStages, tca::TjStuff::NumPlanes, geo::PlaneID::Plane, tca::ShowerTreeVars::PlaneNum, tca::TrajPoint::Pos, tca::Trajectory::Pts, tca::TjStuff::SaveShowerTree, tca::ShowerTreeVars::ShowerID, tca::ShowerTreeVars::StageNum, tca::TjStuff::stv, tca::ShowerTreeVars::TjID, tca::TjStuff::UnitsPerTick, and tca::Trajectory::VtxID.

Referenced by SaveTjInfo().

131  {
132  if(!tjs.SaveShowerTree) return;
133 
134  TrajPoint& beginPoint = tj.Pts[tj.EndPt[0]];
135  TrajPoint& endPoint = tj.Pts[tj.EndPt[1]];
136 
137  tjs.stv.BeginWir.push_back(std::nearbyint(beginPoint.Pos[0]));
138  tjs.stv.BeginTim.push_back(std::nearbyint(beginPoint.Pos[1]/tjs.UnitsPerTick));
139  tjs.stv.BeginAng.push_back(beginPoint.Ang);
140  tjs.stv.BeginChg.push_back(beginPoint.Chg);
141  tjs.stv.BeginVtx.push_back(tj.VtxID[0]);
142 
143  tjs.stv.EndWir.push_back(std::nearbyint(endPoint.Pos[0]));
144  tjs.stv.EndTim.push_back(std::nearbyint(endPoint.Pos[1]/tjs.UnitsPerTick));
145  tjs.stv.EndAng.push_back(endPoint.Ang);
146  tjs.stv.EndChg.push_back(endPoint.Chg);
147  tjs.stv.EndVtx.push_back(tj.VtxID[1]);
148 
149  tjs.stv.MCSMom.push_back(tj.MCSMom);
150  tjs.stv.TjID.push_back(tj.ID);
151  tjs.stv.IsShowerTj.push_back(-1);
152 
153  tjs.stv.ShowerID.push_back(-1);
154  tjs.stv.IsShowerParent.push_back(-1);
155  tjs.stv.StageNum.push_back(stageNum);
156  tjs.stv.nStages = stageNum;
157  geo::PlaneID iPlnID = DecodeCTP(tj.CTP);
158  tjs.stv.PlaneNum.push_back(iPlnID.Plane);
159 
160  tjs.stv.nPlanes = tjs.NumPlanes;
161 
162  } // SaveTjInfoStuff
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
void tca::ScoreVertices ( TjStuff tjs,
const geo::TPCID tpcid,
bool  prt 
)

Definition at line 2193 of file TCVertex.cxx.

References tca::TjStuff::allTraj, geo::CryostatID::Cryostat, DecodeCTP(), kHiVx3Score, kKilled, kTjHiVx3Score, SetVx2Score(), SetVx3Score(), geo::TPCID::TPC, tca::TjStuff::vtx, and tca::TjStuff::vtx3.

Referenced by tca::TrajClusterAlg::RunTrajClusterAlg().

2194  {
2195  // reset all 3D vertex, 2D vertex and Tj high-score vertex bits in tpcid
2196 
2197  unsigned int cstat = tpcid.Cryostat;
2198  unsigned int tpc = tpcid.TPC;
2199 
2200  // reset the 2D vertex status bits
2201  for(auto& vx : tjs.vtx) {
2202  if(vx.ID == 0) continue;
2203  geo::PlaneID planeID = DecodeCTP(vx.CTP);
2204  if(planeID.Cryostat != cstat) continue;
2205  if(planeID.TPC != tpc) continue;
2206  vx.Stat[kHiVx3Score] = false;
2207  } // vx
2208  // and the tj bits
2209  for(auto& tj : tjs.allTraj) {
2210  if(tj.AlgMod[kKilled]) continue;
2211  geo::PlaneID planeID = DecodeCTP(tj.CTP);
2212  if(planeID.Cryostat != cstat) continue;
2213  if(planeID.TPC != tpc) continue;
2214  tj.AlgMod[kTjHiVx3Score] = false;
2215  } // tj
2216  // Score the 2D vertices
2217  for(auto& vx : tjs.vtx) {
2218  if(vx.ID == 0) continue;
2219  geo::PlaneID planeID = DecodeCTP(vx.CTP);
2220  if(planeID.Cryostat != cstat) continue;
2221  if(planeID.TPC != tpc) continue;
2222  SetVx2Score(tjs, vx, prt);
2223  } // vx
2224  // Score the 3D vertices
2225  for(auto& vx3 : tjs.vtx3) {
2226  if(vx3.ID == 0) continue;
2227  if(vx3.TPCID != tpcid) continue;
2228  SetVx3Score(tjs, vx3, prt);
2229  } // vx3
2230  } // ScoreVertices
void SetVx3Score(TjStuff &tjs, Vtx3Store &vx3, bool prt)
Definition: TCVertex.cxx:2303
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
matched to a high-score 3D vertex
Definition: DataStructs.h:104
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
void SetVx2Score(TjStuff &tjs, VtxStore &vx2, bool prt)
Definition: TCVertex.cxx:2331
void tca::SetAngleCode ( TjStuff tjs,
TrajPoint tp 
)

Definition at line 642 of file Utils.cxx.

References tca::TrajPoint::Ang, tca::TrajPoint::AngleCode, AngleRange(), and tca::TjStuff::AngleRanges.

Referenced by FitTraj(), tca::TrajClusterAlg::MakeJunkTraj(), tca::TrajClusterAlg::StartTraj(), and tca::TrajClusterAlg::UpdateTraj().

643  {
644  unsigned short ar = AngleRange(tjs, tp.Ang);
645  if(ar == tjs.AngleRanges.size() - 1) {
646  // Very large angle
647  tp.AngleCode = 2;
648  } else if(tjs.AngleRanges.size() > 2 && ar == tjs.AngleRanges.size() - 2) {
649  // Large angle
650  tp.AngleCode = 1;
651  } else {
652  // Small angle
653  tp.AngleCode = 0;
654  }
655 
656  } // SetAngleCode
unsigned short AngleRange(TjStuff &tjs, float angle)
Definition: Utils.cxx:659
template<typename T >
std::vector< T > tca::SetDifference ( const std::vector< T > &  set1,
const std::vector< T > &  set2 
)

Definition at line 236 of file Utils.h.

Referenced by DefinePFPParentsTestBeam(), DotProd(), Match3DVtxTjs(), and Reconcile3D().

237  {
238  // returns the elements of set1 and set2 that are different
239  std::vector<T> different;
240  if(set1.empty() && set2.empty()) return different;
241  if(!set1.empty() && set2.empty()) return set1;
242  if(set1.empty() && !set2.empty()) return set2;
243  for(auto element1 : set1) {
244  // check for a common element
245  if(std::find(set2.begin(), set2.end(), element1) != set2.end()) continue;
246  // check for a duplicate
247  if(std::find(different.begin(), different.end(), element1) != different.end()) continue;
248  different.push_back(element1);
249  } // element1
250  for(auto element2 : set2) {
251  // check for a common element
252  if(std::find(set1.begin(), set1.end(), element2) != set1.end()) continue;
253  // check for a duplicate
254  if(std::find(different.begin(), different.end(), element2) != different.end()) continue;
255  different.push_back(element2);
256  } // element1
257  return different;
258  } // SetDifference
void tca::SetEndPoints ( TjStuff tjs,
Trajectory tj 
)

Definition at line 2788 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::EndPt, kShowerTj, and tca::Trajectory::Pts.

Referenced by tca::TrajClusterAlg::AddHits(), tca::TrajClusterAlg::AddLAHits(), tca::TrajClusterAlg::CheckHiMultEndHits(), tca::TrajClusterAlg::CheckHiMultUnusedHits(), tca::TrajClusterAlg::CheckTraj(), ChkChgAsymmetry(), tca::TrajClusterAlg::ChkStopEndPts(), DotProd(), tca::TrajClusterAlg::EraseHit(), tca::TrajClusterAlg::FindSoftKink(), tca::TrajClusterAlg::FixTrajBegin(), tca::TrajClusterAlg::IsGhost(), tca::TrajClusterAlg::MakeAllTrajClusters(), tca::TrajClusterAlg::MakeJunkTraj(), tca::TrajClusterAlg::MaskedHitsOK(), tca::TrajClusterAlg::MaskTrajEndPoints(), MergeAndStore(), MergePFPTjs(), tca::TrajClusterAlg::ReversePropagate(), ReverseTraj(), tca::TrajClusterAlg::SplitHiChgHits(), SplitTraj(), tca::TrajClusterAlg::StepCrawl(), StoreTraj(), TrimEndPts(), tca::TrajClusterAlg::UpdateTraj(), tca::TrajClusterAlg::UseUnusedHits(), and VtxHitsSwap().

2789  {
2790  // Find the first (last) TPs, EndPt[0] (EndPt[1], that have charge
2791 
2792  // don't mess with showerTjs
2793  if(tj.AlgMod[kShowerTj]) return;
2794  tj.EndPt[0] = 0; tj.EndPt[1] = 0;
2795  if(tj.Pts.size() == 0) return;
2796 
2797  // check the end point pointers
2798  for(unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) {
2799  if(tj.Pts[ipt].Chg != 0) {
2800  tj.EndPt[0] = ipt;
2801  break;
2802  }
2803  }
2804  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
2805  unsigned short ipt = tj.Pts.size() - 1 - ii;
2806  if(tj.Pts[ipt].Chg != 0) {
2807  tj.EndPt[1] = ipt;
2808  break;
2809  }
2810  }
2811  } // SetEndPoints
void tca::SetHighScoreBits ( TjStuff tjs,
Vtx3Store vx3 
)

Definition at line 2256 of file TCVertex.cxx.

References tca::TjStuff::allTraj, evd::details::end(), GetVtxTjIDs(), tca::VtxStore::ID, tca::Vtx3Store::ID, kHiVx3Score, kTjHiVx3Score, tca::TjStuff::NumPlanes, tca::VtxStore::Stat, tmp, tca::TjStuff::vtx, and tca::Vtx3Store::Vx2ID.

Referenced by SetVx3Score().

2257  {
2258  // Sets the tj and 2D vertex score bits to true
2259 
2260  if(vx3.ID == 0) return;
2261 
2262  for(unsigned short ipl = 0; ipl < tjs.NumPlanes; ++ipl) {
2263  if(vx3.Vx2ID[ipl] <= 0) continue;
2264  VtxStore& vx2 = tjs.vtx[vx3.Vx2ID[ipl] - 1];
2265  vx2.Stat[kHiVx3Score] = false;
2266  // transfer this to all attached tjs and vertices attached to those tjs
2267  std::vector<int> tjlist = GetVtxTjIDs(tjs, vx2);
2268  std::vector<int> vxlist;
2269  while(true) {
2270  // tag Tjs and make a list of attached vertices whose high-score
2271  // bit needs to be set
2272  vxlist.clear();
2273  for(auto tjid : tjlist) {
2274  auto& tj = tjs.allTraj[tjid - 1];
2275  tj.AlgMod[kTjHiVx3Score] = true;
2276  for(unsigned short end = 0; end < 2; ++end) {
2277  if(tj.VtxID[end] == 0) continue;
2278  auto& vx2 = tjs.vtx[tj.VtxID[end] - 1];
2279  if(vx2.Stat[kHiVx3Score]) continue;
2280  vx2.Stat[kHiVx3Score] = true;
2281  vxlist.push_back(vx2.ID);
2282  } // end
2283  } // tjid
2284 
2285  if(vxlist.empty()) break;
2286  // re-build tjlist using vxlist
2287  std::vector<int> newtjlist;
2288  for(auto vxid : vxlist) {
2289  auto& vx2 = tjs.vtx[vxid - 1];
2290  auto tmp = GetVtxTjIDs(tjs, vx2);
2291  for(auto tjid : tmp) {
2292  if(std::find(tjlist.begin(), tjlist.end(), tjid) == tjlist.end()) newtjlist.push_back(tjid);
2293  } // tjid
2294  } // vxid
2295  if(newtjlist.empty()) break;
2296  tjlist = newtjlist;
2297  } // true
2298  } // ipl
2299 
2300  } // SetHighScoreBits
matched to a high-score 3D vertex
Definition: DataStructs.h:104
Float_t tmp
Definition: plot.C:37
std::vector< int > GetVtxTjIDs(const TjStuff &tjs, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:3039
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
template<typename T >
std::vector< T > tca::SetIntersection ( const std::vector< T > &  set1,
const std::vector< T > &  set2 
)

Definition at line 214 of file Utils.h.

Referenced by AddMissedTj(), CompleteIncompleteShower(), DefinePFP(), DotProd(), FindCots(), FindPFParticles(), GetAssns(), Match3DVtxTjs(), tca::TruthMatcher::MatchAndSum(), MergeNearby2DShowers(), PFPVxTjOK(), tca::MCParticleListUtils::PrimaryElectronPFPID(), Reconcile3D(), and SharesHighScoreVx().

215  {
216  // returns a vector containing the elements of set1 and set2 that are common. This function
217  // is a replacement for std::set_intersection which fails in the following situation:
218  // set1 = {11 12 17 18} and set2 = {6 12 18}
219  // There is no requirement that the elements be sorted, unlike std::set_intersection
220  std::vector<T> shared;
221 
222  if(set1.empty()) return shared;
223  if(set2.empty()) return shared;
224  for(auto element1 : set1) {
225  // check for a common element
226  if(std::find(set2.begin(), set2.end(), element1) == set2.end()) continue;
227  // check for a duplicate
228  if(std::find(shared.begin(), shared.end(), element1) != shared.end()) continue;
229  shared.push_back(element1);
230  } // element1
231  return shared;
232  } // SetIntersection
bool tca::SetMag ( Vector3_t v1,
double  mag 
)

Definition at line 1641 of file PFPUtils.cxx.

References den.

Referenced by DotProd(), FindAlongTrans(), Fit3D(), FollowTp3s(), tca::MCParticleListUtils::MakeTruTrajPoint(), tca::TruthMatcher::MatchTrueHits(), tca::TruthMatcher::MatchTruth(), PointDirection(), tca::MCParticleListUtils::PrimaryElectronStart(), tca::TruthMatcher::StudyPiZeros(), and UpdateShower().

1642  {
1643  double den = v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2];
1644  if(den == 0) return false;
1645  den = sqrt(den);
1646 
1647  v1[0] *= mag / den;
1648  v1[1] *= mag / den;
1649  v1[2] *= mag / den;
1650  return true;
1651  } // SetMag
Float_t den
Definition: plot.C:37
bool tca::SetMag ( Vector2_t v1,
double  mag 
)

Definition at line 2729 of file Utils.cxx.

References den.

Referenced by FindAlongTrans().

2730  {
2731  double den = v1[0] * v1[0] + v1[1] * v1[1];
2732  if(den == 0) return false;
2733  den = sqrt(den);
2734 
2735  v1[0] *= mag / den;
2736  v1[1] *= mag / den;
2737  return true;
2738  } // SetMag
Float_t den
Definition: plot.C:37
bool tca::SetParent ( std::string  inFcnLabel,
TjStuff tjs,
PFPStruct pfp,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 1988 of file TCShower.cxx.

References AddTj(), tca::TjStuff::allTraj, tca::ShowerStruct3D::ChgPos, tca::ShowerStruct3D::CotIDs, tca::TjStuff::cots, tca::PFPStruct::Dir, evd::details::end(), FarEnd(), GetAssns(), tca::PFPStruct::ID, tca::ShowerStruct3D::ID, kShwrParent, MakeBareTP(), ParentFOM(), tca::ShowerStruct3D::ParentID, ss, tca::PFPStruct::TjIDs, UpdateShower(), tca::TjStuff::vtx3, tca::PFPStruct::Vx3ID, tca::ShowerStruct3D::Vx3ID, and tca::PFPStruct::XYZ.

Referenced by FindParent().

1989  {
1990  // set the pfp as the parent of ss3. The calling function should do the error recovery
1991  if(pfp.ID == 0 || ss3.ID == 0) return false;
1992  if(ss3.CotIDs.empty()) return false;
1993 
1994  std::string fcnLabel = inFcnLabel + ".SP";
1995 
1996  for(auto cid : ss3.CotIDs) {
1997  auto& ss = tjs.cots[cid - 1];
1998  auto& stj = tjs.allTraj[ss.ShowerTjID - 1];
1999  stj.VtxID[0] = 0;
2000  if(ss.ParentID > 0) {
2001  auto& oldParent = tjs.allTraj[ss.ParentID - 1];
2002  oldParent.AlgMod[kShwrParent] = false;
2003  ss.ParentID = 0;
2004  ss.ParentFOM = 10;
2005  } // remove old parents
2006  // add new parents
2007  for(auto tjid : pfp.TjIDs) {
2008  auto& tj = tjs.allTraj[tjid - 1];
2009  if(tj.CTP != ss.CTP) continue;
2010  if(std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tjid) == ss.TjIDs.end()) {
2011  // Add the tj but don't update yet
2012  if(!AddTj(fcnLabel, tjs, tjid, ss, false, prt)) return false;
2013  } // parent not in ss
2014  // Don't define it to be the parent if it is short and the pfp projection in this plane is low
2015  unsigned short pEnd = FarEnd(tjs, pfp, ss3.ChgPos);
2016  auto tp = MakeBareTP(tjs, pfp.XYZ[0], pfp.Dir[pEnd], tj.CTP);
2017  unsigned short npts = tj.EndPt[1] - tj.EndPt[0] + 1;
2018  if(tp.Delta > 0.5 || npts > 20) {
2019  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" parent P"<<pfp.ID<<" -> T"<<tjid<<" -> 2S"<<ss.ID<<" parent";
2020  } else {
2021  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" parent P"<<pfp.ID<<" -> T"<<tjid<<" low projection in plane "<<tp.Delta<<". Not a parent";
2022  continue;
2023  }
2024  ss.ParentID = tjid;
2025  ss.NeedsUpdate = true;
2026  // set the ss start vertex
2027  if(ss3.Vx3ID > 0) {
2028  auto& vx3 = tjs.vtx3[ss3.Vx3ID - 1];
2029  auto v2list = GetAssns(tjs, "3V", vx3.ID, "2V");
2030  for(unsigned short end = 0; end < 2; ++end) {
2031  if(tj.VtxID[end] <= 0) continue;
2032  if(std::find(v2list.begin(), v2list.end(), tj.VtxID[end]) != v2list.end()) stj.VtxID[0] = tj.VtxID[end];
2033  } // end
2034  } // ss3.Vx3ID > 0
2035  // and update
2036  if(!UpdateShower(fcnLabel, tjs, ss, prt)) return false;
2037  } // tjid
2038  } // cid
2039  ss3.ParentID = pfp.ID;
2040 
2041  unsigned short pEnd = FarEnd(tjs, pfp, ss3.ChgPos);
2042  ss3.Vx3ID = pfp.Vx3ID[pEnd];
2043  float fom3D = ParentFOM(fcnLabel, tjs, pfp, pEnd, ss3, prt);
2044  for(auto cid : ss3.CotIDs) tjs.cots[cid - 1].ParentFOM = fom3D;
2045 
2046  return true;
2047  } // SetParent
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float ParentFOM(std::string inFcnLabel, TjStuff &tjs, Trajectory &tj, unsigned short &tjEnd, ShowerStruct &ss, float &tp1Sep, float &vx2Score, bool prt)
Definition: TCShower.cxx:2280
bool AddTj(std::string inFcnLabel, TjStuff &tjs, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1624
Float_t ss
Definition: plot.C:23
unsigned short FarEnd(const TjStuff &tjs, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:2936
TrajPoint MakeBareTP(TjStuff &tjs, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
Definition: Utils.cxx:3435
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
std::vector< int > GetAssns(const TjStuff &tjs, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4079
bool UpdateShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1302
void tca::SetPDGCode ( TjStuff tjs,
unsigned short  itj 
)

Definition at line 3697 of file Utils.cxx.

References tca::TjStuff::allTraj, and SetPDGCode().

Referenced by CompleteIncomplete3DVertices(), DotProd(), FindHammerVertices(), FindHammerVertices2(), MergePFPTjs(), and tca::TrajClusterAlg::StepCrawl().

3698  {
3699  if(itj > tjs.allTraj.size() - 1) return;
3700  SetPDGCode(tjs, tjs.allTraj[itj]);
3701  }
void SetPDGCode(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:3704
void tca::SetPDGCode ( TjStuff tjs,
Trajectory tj 
)

Definition at line 3704 of file Utils.cxx.

References tca::Trajectory::EndPt, tca::Trajectory::MCSMom, MCSMom(), tca::TjStuff::MuonTag, and tca::Trajectory::PDGCode.

Referenced by MergeAndStore(), SetPDGCode(), and SplitTraj().

3705  {
3706  // Sets the PDG code for the supplied trajectory. Note that the existing
3707  // PDG code is left unchanged if these cuts are not met
3708 
3709  tj.MCSMom = MCSMom(tjs, tj);
3710  if(tjs.MuonTag[0] <= 0) return;
3711  // Special handling of very long straight trajectories, e.g. uB cosmic rays
3712  unsigned short npts = tj.EndPt[1] - tj.EndPt[0];
3713  bool isAMuon = (npts > (unsigned short)tjs.MuonTag[0] && tj.MCSMom > tjs.MuonTag[1]);
3714  // anything really really long must be a muon
3715  if(npts > 500) isAMuon = true;
3716  if(isAMuon) tj.PDGCode = 13;
3717 
3718  } // SetPDGCode
short MCSMom(TjStuff &tjs, Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:2859
bool tca::SetStart ( TjStuff tjs,
PFPStruct pfp,
bool  prt 
)

Definition at line 207 of file PFPUtils.cxx.

References tca::PFPStruct::Dir, tca::PFPStruct::ID, PrintTp3(), tca::PFPStruct::TjIDs, tca::PFPStruct::Tp3s, valIncreasings(), and tca::PFPStruct::XYZ.

Referenced by DefinePFP().

208  {
209  // Analyzes the space point collection and the Tjs in the pfp to find a new start
210  // position. The Tp3s found in FindCompleteness are ordered by increasing X. The general direction
211  // pfp.Dir[0] and the average position of all points in Tp3s was stored in pfp.XYZ[0]. This function
212  // rotates each tp3 into this coordinate system to determine (along, trans) for each point. The min (max)
213  // value of along defines the start (end) of the trajectory.
214 
215  if(pfp.ID <= 0 || pfp.TjIDs.empty()) return false;
216  if(pfp.Tp3s.size() < 2) return false;
217 
218  // The projection along the general direction relative to the average position was found
219  // in FillCompleteness. Now
220  float minAlong = 1E6;
221  unsigned short minPt = 0;
222  float maxAlong = -1E6;
223  unsigned short maxPt = 0;
224  std::vector<SortEntry> sortVec(pfp.Tp3s.size());
225  for(unsigned short ipt = 0; ipt < pfp.Tp3s.size(); ++ipt) {
226  auto& tp3 = pfp.Tp3s[ipt];
227  sortVec[ipt].index = ipt;
228  sortVec[ipt].val = tp3.AlongTrans[0];
229  // find the min (max)
230  if(tp3.AlongTrans[0] < minAlong) {
231  minAlong = tp3.AlongTrans[0];
232  minPt = ipt;
233  }
234  if(tp3.AlongTrans[0] > maxAlong) {
235  maxAlong = tp3.AlongTrans[0];
236  maxPt = ipt;
237  }
238  } // tp3
239 
240  pfp.XYZ[0] = pfp.Tp3s[minPt].Pos;
241  pfp.XYZ[1] = pfp.Tp3s[maxPt].Pos;
242 
243  if(prt) {
244  mf::LogVerbatim("TC")<<"SNS: P"<<pfp.ID<<" minPt "<<minPt<<" maxPt "<<maxPt<<" dir "<<std::fixed<<std::setprecision(2)<<pfp.Dir[0][0]<<" "<<pfp.Dir[0][1]<<" "<<pfp.Dir[0][2];
245  PrintTp3("minPt", tjs, pfp.Tp3s[minPt]);
246  PrintTp3("maxPt", tjs, pfp.Tp3s[maxPt]);
247  }
248 
249  std::sort(sortVec.begin(), sortVec.end(), valIncreasings);
250  // put them into order
251  std::vector<TrajPoint3> temp;
252  for(unsigned short ii = 0; ii < sortVec.size(); ++ii) temp.push_back(pfp.Tp3s[sortVec[ii].index]);
253  pfp.Tp3s = temp;
254 // PrintTp3s("SNS", tjs, pfp, -1);
255 
256  return true;
257 
258  } // SetStart
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool valIncreasings(SortEntry c1, SortEntry c2)
Definition: PFPUtils.cxx:13
void PrintTp3(std::string someText, const TjStuff &tjs, const TrajPoint3 &tp3)
Definition: PFPUtils.cxx:2945
void tca::SetVx2Score ( TjStuff tjs,
bool  prt 
)

Definition at line 2322 of file TCVertex.cxx.

References tca::TjStuff::vtx.

Referenced by AttachTrajToVertex(), CheckTrajBeginChg(), CompleteIncomplete3DVertices(), CompleteIncomplete3DVerticesInGaps(), tca::TrajClusterAlg::EndMerge(), Find2DVertices(), Find3DVertices(), FindHammerVertices(), FindHammerVertices2(), FindNeutralVertices(), MergeWithVertex(), ScoreVertices(), and tca::TrajClusterAlg::SplitHiChgHits().

2323  {
2324  // A version that sets the score of the last added vertex
2325  if(tjs.vtx.empty()) return;
2326  auto& vx2 = tjs.vtx[tjs.vtx.size() - 1];
2327  SetVx2Score(tjs, vx2, prt);
2328  } // SetVx2Score
void SetVx2Score(TjStuff &tjs, VtxStore &vx2, bool prt)
Definition: TCVertex.cxx:2331
void tca::SetVx2Score ( TjStuff tjs,
VtxStore vx2,
bool  prt 
)

Definition at line 2331 of file TCVertex.cxx.

References tca::Trajectory::AlgMod, tca::TjStuff::allTraj, ChgFracNearPos(), tca::Trajectory::ChgRMS, DeltaAngle(), tca::Trajectory::EndPt, GetVtxTjIDs(), tca::VtxStore::ID, kBragg, kJunkTj, kShowerLike, kShowerTj, tca::Trajectory::MCSMom, tca::Trajectory::PDGCode, tca::VtxStore::Pos, tca::VtxStore::PosErr, tca::Trajectory::Pts, tca::VtxStore::Score, tca::Trajectory::StopFlag, tca::VtxStore::TjChgFrac, tca::VtxStore::Topo, tca::TjStuff::Vertex2DCuts, tca::TjStuff::VertexScoreWeights, tca::TjStuff::vtx3, tca::Trajectory::VtxID, and tca::VtxStore::Vx3ID.

2332  {
2333  // Calculate the 2D vertex score
2334  if(vx2.ID == 0) return;
2335 
2336  // Don't score vertices from CheckTrajBeginChg, MakeJunkVertices or Neutral vertices. Set to the minimum
2337  if(vx2.Topo == 8 || vx2.Topo == 9 || vx2.Topo == 11) {
2338  vx2.Score = tjs.Vertex2DCuts[7] + 0.1;
2339  auto vtxTjID = GetVtxTjIDs(tjs, vx2);
2340  vx2.TjChgFrac = ChgFracNearPos(tjs, vx2.Pos, vtxTjID);
2341  return;
2342  }
2343 
2344  // Cuts on Tjs attached to vertices
2345  constexpr float maxChgRMS = 0.25;
2346  constexpr float momBin = 50;
2347 
2348  vx2.Score = -1000;
2349  vx2.TjChgFrac = 0;
2350  if(vx2.ID == 0) return;
2351  if(tjs.VertexScoreWeights.size() < 4) return;
2352 
2353  auto vtxTjIDs = GetVtxTjIDs(tjs, vx2);
2354  if(vtxTjIDs.empty()) return;
2355 
2356  // Vertex position error
2357  float vpeScore = -tjs.VertexScoreWeights[0] * (vx2.PosErr[0] + vx2.PosErr[1]);
2358 
2359  unsigned short m3Dcnt = 0;
2360  if(vx2.Vx3ID > 0) {
2361  m3Dcnt = 1;
2362  // Add another if the 3D vertex is complete
2363  unsigned short ivx3 = vx2.Vx3ID - 1;
2364  if(tjs.vtx3[ivx3].Wire < 0) m3Dcnt = 2;
2365  }
2366  float m3DScore = tjs.VertexScoreWeights[1] * m3Dcnt;
2367 
2368  vx2.TjChgFrac = ChgFracNearPos(tjs, vx2.Pos, vtxTjIDs);
2369  float cfScore = tjs.VertexScoreWeights[2] * vx2.TjChgFrac;
2370 
2371  // Define a weight for each Tj
2372  std::vector<int> tjids;
2373  std::vector<float> tjwts;
2374  for(auto tjid : vtxTjIDs) {
2375  Trajectory& tj = tjs.allTraj[tjid - 1];
2376  // Feb 22 Ignore short Tjs and junk tjs
2377  if(tj.AlgMod[kJunkTj]) continue;
2378  unsigned short lenth = tj.EndPt[1] - tj.EndPt[0] + 1;
2379  if(lenth < 3) continue;
2380  float wght = (float)tj.MCSMom / momBin;
2381  if(wght > 10) wght = 10;
2382  // weight by tagged muon
2383  if(tj.PDGCode == 13) wght *= 2;
2384  // weight by charge rms
2385  if(tj.ChgRMS < maxChgRMS) ++wght;
2386  // Shower Tj
2387  if(tj.AlgMod[kShowerTj]) ++wght;
2388  // ShowerLike
2389  if(tj.AlgMod[kShowerLike]) --wght;
2390  tjids.push_back(tjid);
2391  tjwts.push_back(wght);
2392  } // tjid
2393 
2394  if(tjids.empty()) return;
2395 
2396  float tjScore = 0;
2397  float sum = 0;
2398  float cnt = 0;
2399  for(unsigned short it1 = 0; it1 < tjids.size() - 1; ++it1) {
2400  Trajectory& tj1 = tjs.allTraj[tjids[it1] - 1];
2401  float wght1 = tjwts[it1];
2402  // the end that has a vertex
2403  unsigned short end1 = 0;
2404  if(tj1.VtxID[1] == vx2.ID) end1 = 1;
2405  unsigned short endPt1 = tj1.EndPt[end1];
2406  // bump up the weight if there is a Bragg peak at the other end
2407  unsigned short oend1 = 1 - end1;
2408  if(tj1.StopFlag[oend1][kBragg]) ++wght1;
2409  float ang1 = tj1.Pts[endPt1].Ang;
2410  float ang1Err2 = tj1.Pts[endPt1].AngErr * tj1.Pts[endPt1].AngErr;
2411  for(unsigned short it2 = it1 + 1; it2 < tjids.size(); ++it2) {
2412  Trajectory& tj2 = tjs.allTraj[tjids[it2] - 1];
2413  float wght2 = tjwts[it2];
2414  unsigned end2 = 0;
2415  if(tj2.VtxID[1] == vx2.ID) end2 = 1;
2416  // bump up the weight if there is a Bragg peak at the other end
2417  unsigned short oend2 = 1 - end2;
2418  if(tj2.StopFlag[oend2][kBragg]) ++wght2;
2419  unsigned short endPt2 = tj2.EndPt[end2];
2420  float ang2 = tj2.Pts[endPt2].Ang;
2421  float ang2Err2 = tj2.Pts[endPt2].AngErr * tj2.Pts[endPt2].AngErr;
2422  float dang = DeltaAngle(ang1, ang2);
2423  float dangErr = 0.5 * sqrt(ang1Err2 + ang2Err2);
2424  if((dang / dangErr) > 3 && wght1 > 0 && wght2 > 0) {
2425  sum += wght1 + wght2;
2426  ++cnt;
2427  }
2428  } // it2
2429  } // it1
2430  if(cnt > 0) {
2431  sum /= cnt;
2432  tjScore = tjs.VertexScoreWeights[3] * sum;
2433  }
2434  vx2.Score = vpeScore + m3DScore + cfScore + tjScore;
2435  if(prt) {
2436  // last call after vertices have been matched to the truth. Use to optimize VertexScoreWeights using
2437  // an ntuple
2438  mf::LogVerbatim myprt("TC");
2439  myprt<<" SVx2W 2V"<<vx2.ID;
2440  myprt<<" m3Dcnt "<<m3Dcnt;
2441  myprt<<" PosErr "<<std::fixed<<std::setprecision(2)<<(vx2.PosErr[0] + vx2.PosErr[1]);
2442  myprt<<" TjChgFrac "<<std::fixed<<std::setprecision(3)<<vx2.TjChgFrac;
2443  myprt<<" sum "<<std::fixed<<std::setprecision(1)<<sum;
2444  myprt<<" cnt "<<(int)cnt;
2445  myprt<<" Score "<<vx2.Score;
2446  }
2447  } // SetVx2Score
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1607
std::vector< int > GetVtxTjIDs(const TjStuff &tjs, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:3039
float ChgFracNearPos(TjStuff &tjs, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2614
void tca::SetVx3Score ( TjStuff tjs,
Vtx3Store vx3,
bool  prt 
)

Definition at line 2303 of file TCVertex.cxx.

References tca::Vtx3Store::ID, tca::TjStuff::NumPlanes, tca::VtxStore::Score, tca::Vtx3Store::Score, SetHighScoreBits(), tca::TjStuff::Vertex2DCuts, tca::TjStuff::vtx, and tca::Vtx3Store::Vx2ID.

Referenced by Find3DVertices(), FindNeutralVertices(), MakeVertexObsolete(), and ScoreVertices().

2304  {
2305  // Calculate the 3D vertex score and flag Tjs that are attached to high score vertices as defined
2306  // by Vertex2DCuts
2307 
2308  if(vx3.ID == 0) return;
2309 
2310  vx3.Score = 0;
2311  for(unsigned short ipl = 0; ipl < tjs.NumPlanes; ++ipl) {
2312  if(vx3.Vx2ID[ipl] <= 0) continue;
2313  VtxStore& vx2 = tjs.vtx[vx3.Vx2ID[ipl] - 1];
2314  vx3.Score += vx2.Score;
2315  } // ipl
2316  vx3.Score /= (float)tjs.NumPlanes;
2317  if(vx3.Score > tjs.Vertex2DCuts[7]) SetHighScoreBits(tjs, vx3);
2318 
2319  } // SetVx3Score
void SetHighScoreBits(TjStuff &tjs, Vtx3Store &vx3)
Definition: TCVertex.cxx:2256
bool tca::SharesHighScoreVx ( TjStuff tjs,
const PFPStruct pfp,
const Trajectory tj 
)

Definition at line 883 of file PFPUtils.cxx.

References evd::details::end(), GetVtxTjIDs(), kHiVx3Score, SetIntersection(), tca::PFPStruct::TjIDs, tca::TjStuff::vtx, and tca::Trajectory::VtxID.

Referenced by DefinePFP(), and FindMissedTjsInTp3s().

884  {
885  // returns true if tj with tjID shares a high-score 3D vertex with any
886  // tj in pfp.TjIDs
887  for(unsigned short end = 0; end < 2; ++end) {
888  if(tj.VtxID[end] == 0) continue;
889  auto& vx2 = tjs.vtx[tj.VtxID[end] - 1];
890  if(!vx2.Stat[kHiVx3Score]) continue;
891  std::vector<int> vtjlist = GetVtxTjIDs(tjs, vx2);
892  auto shared = SetIntersection(vtjlist, pfp.TjIDs);
893  if(!shared.empty()) return true;
894  } // end
895  return false;
896  } // SharesHighScoreVx
matched to a high-score 3D vertex
Definition: DataStructs.h:104
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:214
std::vector< int > GetVtxTjIDs(const TjStuff &tjs, const VtxStore &vx2)
Definition: TCVertex.cxx:3022
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
double tca::ShowerEnergy ( const ShowerStruct3D ss3)

Definition at line 4434 of file TCShower.cxx.

References e, tca::ShowerStruct3D::Energy, and tca::ShowerStruct3D::ID.

Referenced by tca::TruthMatcher::StudyShowerParents(), and showerreco::ShowerCalo::~ShowerCalo().

4435  {
4436  if(ss3.ID == 0) return 0;
4437  if(ss3.Energy.empty()) return 0;
4438  double ave = 0;
4439  for(auto e : ss3.Energy) {
4440  ave += e;
4441  } // e
4442  ave /= ss3.Energy.size();
4443  return ave;
4444  } // ShowerEnergy
Float_t e
Definition: plot.C:34
float tca::ShowerEnergy ( const TjStuff tjs,
const std::vector< int >  tjIDs 
)

Definition at line 4447 of file TCShower.cxx.

References tca::TjStuff::allTraj, and ChgToMeV().

Referenced by CompleteIncompleteShower(), FindCots(), FindParent(), FindShowers3D(), and Reconcile3D().

4448  {
4449  // Calculate energy using the total charge of all hits in each tj in the shower
4450  if(tjIDs.empty()) return 0;
4451  float sum = 0;
4452  for(auto tid : tjIDs) {
4453  auto& tj = tjs.allTraj[tid - 1];
4454  sum += tj.TotChg;
4455  } // tid
4456  return ChgToMeV(sum);
4457  } // ShowerEnergy
float ChgToMeV(float chg)
Definition: TCShower.cxx:4460
void tca::ShowerParams ( double  showerEnergy,
double &  shMaxAlong,
double &  along95 
)

Definition at line 2084 of file TCShower.cxx.

References scale.

Referenced by FindParent(), InShowerProbLong(), MergeSubShowers(), ParentFOM(), and ShowerParamTransRMS().

2085  {
2086  // Returns summary properties of photon showers parameterized in the energy range 50 MeV < E_gamma < 1 GeV:
2087  // shMaxAlong = the longitudinal distance (cm) between the start of the shower and the center of charge
2088  // along95 = the longitudinal distance (cm) between the start of the shower and 95% energy containment
2089  // all units are in cm
2090  if(showerEnergy < 10) {
2091  shMaxAlong = 0;
2092  along95 = 0;
2093  return;
2094  }
2095 // shMaxAlong = 7.0 * log(showerEnergy / 15);
2096  shMaxAlong = 16 * log(showerEnergy / 15);
2097  // The 95% containment is reduced a bit at higher energy
2098  double scale = 2.75 - 9.29E-4 * showerEnergy;
2099  if(scale < 2) scale = 2;
2100  along95 = scale * shMaxAlong;
2101  } // ShowerParams
Double_t scale
Definition: plot.C:25
double tca::ShowerParamTransRMS ( double  showerEnergy,
double  along 
)

Definition at line 2104 of file TCShower.cxx.

References ShowerParams().

Referenced by InShowerProbTrans().

2105  {
2106  // returns the pareameterized width rms of a shower at along relative to the shower max
2107  double shMaxAlong, shE95Along;
2108  ShowerParams(showerEnergy, shMaxAlong, shE95Along);
2109  if(shMaxAlong <= 0) return 0;
2110  double tau = (along + shMaxAlong) / shMaxAlong;
2111  // The shower width is modeled as a simple cone that scales with tau
2112  double rms = -0.4 + 2.5 * tau;
2113  if(rms < 0.5) rms = 0.5;
2114  return rms;
2115  } // ShowerParamTransRMS
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
Definition: TCShower.cxx:2084
bool tca::SignalAtTp ( TjStuff tjs,
TrajPoint const &  tp 
)
bool tca::SignalAtTp ( TjStuff tjs,
const TrajPoint tp 
)

Definition at line 1639 of file Utils.cxx.

References tca::TrajPoint::CTP, DecodeCTP(), tca::TrajPoint::Dir, tca::TjStuff::fHits, tca::TjStuff::MaxPos1, tca::TjStuff::NumWires, tca::TCHit::PeakTime, geo::PlaneID::Plane, tca::TrajPoint::Pos, tca::TCHit::RMS, tca::TjStuff::UnitsPerTick, and tca::TjStuff::WireHitRange.

Referenced by ChgFracBetween(), FindHammerVertices2(), FindXMatches(), SignalBetween(), and tca::TrajClusterAlg::StepCrawl().

1640  {
1641  // returns true if there is a hit near tp.Pos
1642 
1643  if(tp.Pos[0] < -0.4) return false;
1644  unsigned int wire = std::nearbyint(tp.Pos[0]);
1645  geo::PlaneID planeID = DecodeCTP(tp.CTP);
1646  unsigned int ipl = planeID.Plane;
1647  if(wire >= tjs.NumWires[ipl]) return false;
1648  if(tp.Pos[1] > tjs.MaxPos1[ipl]) return false;
1649  // Assume dead wires have a signal
1650  if(tjs.WireHitRange[ipl][wire].first == -1) return true;
1651  float projTick = (float)(tp.Pos[1] / tjs.UnitsPerTick);
1652  float tickRange = 0;
1653  if(std::abs(tp.Dir[1]) != 0) {
1654  tickRange = std::abs(0.5 / tp.Dir[1]) / tjs.UnitsPerTick;
1655  // don't let it get too large
1656  if(tickRange > 40) tickRange = 40;
1657  }
1658  float loTpTick = projTick - tickRange;
1659  float hiTpTick = projTick + tickRange;
1660  unsigned int firstHit = (unsigned int)tjs.WireHitRange[ipl][wire].first;
1661  unsigned int lastHit = (unsigned int)tjs.WireHitRange[ipl][wire].second;
1662 
1663  for(unsigned int iht = firstHit; iht < lastHit; ++iht) {
1664  TCHit& hit = tjs.fHits[iht];
1665  if(projTick < hit.PeakTime) {
1666  float loHitTick = hit.PeakTime - 3 * hit.RMS;
1667  if(hiTpTick > loHitTick) return true;
1668  } else {
1669  float hiHitTick = hit.PeakTime + 3 * hit.RMS;
1670  if(loTpTick < hiHitTick) return true;
1671  }
1672  } // iht
1673  return false;
1674 
1675  } // SignalAtTp
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
Detector simulation of raw signals on wires.
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
bool tca::SignalBetween ( TjStuff tjs,
const TrajPoint tp1,
const TrajPoint tp2,
const float &  MinWireSignalFraction,
bool  prt 
)

Definition at line 1495 of file Utils.cxx.

References MakeBareTrajPoint(), tca::TrajPoint::Pos, SignalAtTp(), and SignalBetween().

Referenced by AttachTrajToVertex(), tca::TrajClusterAlg::EndMerge(), Find2DVertices(), and MakeJunkVertices().

1496  {
1497  // Returns true if there is a signal on > MinWireSignalFraction of the wires between tp1 and tp2.
1498  if(MinWireSignalFraction == 0) return true;
1499 
1500  if(tp1.Pos[0] < -0.4 || tp2.Pos[0] < -0.4) return false;
1501  int fromWire = std::nearbyint(tp1.Pos[0]);
1502  int toWire = std::nearbyint(tp2.Pos[0]);
1503 
1504  if(fromWire == toWire) {
1505  TrajPoint tp = tp1;
1506  // check for a signal midway between
1507  tp.Pos[1] = 0.5 * (tp1.Pos[1] + tp2.Pos[1]);
1508  if(prt) mf::LogVerbatim("TC")<<" SignalBetween fromWire = toWire = "<<fromWire<<" SignalAtTp? "<<SignalAtTp(tjs, tp);
1509  return SignalAtTp(tjs, tp);
1510  }
1511  // define a trajectory point located at tp1 that has a direction towards tp2
1512  TrajPoint tp;
1513  if(!MakeBareTrajPoint(tjs, tp1, tp2, tp)) return true;
1514  return SignalBetween(tjs, tp, toWire, MinWireSignalFraction, prt);
1515  } // SignalBetween
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeBareTrajPoint(const TjStuff &tjs, const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
Definition: Utils.cxx:3536
bool SignalAtTp(TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:1639
bool SignalBetween(TjStuff &tjs, TrajPoint tp, float toPos0, const float &MinWireSignalFraction, bool prt)
Definition: Utils.cxx:1520
bool tca::SignalBetween ( TjStuff tjs,
TrajPoint  tp,
float  toPos0,
const float &  MinWireSignalFraction,
bool  prt 
)

Definition at line 1520 of file Utils.cxx.

References ChgFracBetween().

Referenced by SignalBetween().

1521  {
1522  // Returns true if there is a signal on > MinWireSignalFraction of the wires between tp and toPos0.
1523  return ChgFracBetween(tjs, tp, toPos0, prt) >= MinWireSignalFraction;
1524  } // SignalBetween
float ChgFracBetween(TjStuff &tjs, TrajPoint tp, float toPos0, bool prt)
Definition: Utils.cxx:1527
bool tca::Split3DKink ( TjStuff tjs,
PFPStruct pfp,
double  sep,
bool  prt 
)

Definition at line 1782 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, AttachAnyTrajToVertex(), tca::VtxStore::CTP, DecodeCTP(), FindKinks(), tca::VtxStore::ID, tca::Vtx3Store::ID, KinkAngle(), kSplit3DKink, tca::PFPStruct::NeedsUpdate, tca::TjStuff::NumPlanes, geo::PlaneID::Plane, tca::VtxStore::Pos, SplitTraj(), StoreVertex(), tca::PFPStruct::TjIDs, tca::VtxStore::Topo, tca::PFPStruct::Tp3s, tca::Vtx3Store::TPCID, tca::PFPStruct::TPCID, tca::TjStuff::UseAlg, tca::TjStuff::vtx, tca::TjStuff::vtx3, tca::Vtx3Store::Vx2ID, tca::Vtx3Store::X, tca::Vtx3Store::Y, and tca::Vtx3Store::Z.

Referenced by DotProd(), FindPFParticles(), and Match3DVtxTjs().

1783  {
1784  // Finds kinks in the PFParticle, splits Tjs, creates 2D vertices and forces a rebuild if any are found
1785  if(pfp.Tp3s.empty()) return false;
1786  if(!tjs.UseAlg[kSplit3DKink]) return false;
1787 
1788  auto kinkPts = FindKinks(tjs, pfp, sep, prt);
1789  if(kinkPts.empty()) return false;
1790  if(prt) mf::LogVerbatim("TC")<<"Split3DKink found a kink at Tp3s point "<<kinkPts[0];
1791 
1792  // Only split the biggest angle kink
1793  double big = 0;
1794  unsigned short kpt = 0;
1795  for(auto ipt : kinkPts) {
1796  double dang = KinkAngle(tjs, pfp.Tp3s, ipt, sep);
1797  if(dang > big) {
1798  big = dang;
1799  kpt = ipt;
1800  }
1801  } // ipt
1802  if(kpt < 1 || kpt > pfp.Tp3s.size() - 1) return false;
1803  // determine which tjs need to be split
1804  std::vector<unsigned short> tjids;
1805  std::vector<unsigned short> vx2ids;
1806  // inspect a few Tp3s near the kink point to get a list of Tjs
1807  for(unsigned short ipt = kpt; ipt < kpt + 2; ++ipt) {
1808  auto& tp3 = pfp.Tp3s[ipt];
1809  for(auto& tp2 : tp3.Tj2Pts) {
1810  // see if this Tj id is in the list
1811  if(std::find(tjids.begin(), tjids.end(), tp2.id) != tjids.end()) continue;
1812  // ensure that it is pfp.TjIDs
1813  if(std::find(pfp.TjIDs.begin(), pfp.TjIDs.end(), tp2.id) == pfp.TjIDs.end()) continue;
1814  tjids.push_back(tp2.id);
1815  auto& tj = tjs.allTraj[tp2.id - 1];
1816  auto& tp = tj.Pts[tp2.ipt];
1817  unsigned short closeEnd = USHRT_MAX;
1818  if(tp2.ipt < tj.EndPt[0] + 2) closeEnd = 0;
1819  if(tp2.ipt > tj.EndPt[1] - 2) closeEnd = 1;
1820  if(closeEnd < 2) {
1821  // No split is needed and there should be a vertex at this end of the Tj that
1822  // should be associated with a 3D vertex that we will construct
1823  if(tj.VtxID[closeEnd] == 0) {
1824 // std::cout<<Split3DKink: TODO Tj "<<tj.ID<<" has no vertex attached on end "<<closeEnd<<". Write some code.\n";
1825  return false;
1826  }
1827  vx2ids.push_back(tj.VtxID[closeEnd]);
1828  if(prt) mf::LogVerbatim("TC")<<" tj "<<tj.ID<<" use existing 2V"<<tj.VtxID[closeEnd];
1829  } else {
1830  // make a 2D vertex at this point
1831  VtxStore vx2;
1832  vx2.ID = tjs.vtx.size() + 1;
1833  vx2.CTP = tj.CTP;
1834  vx2.Topo = 10;
1835  vx2.Pos = tp.Pos;
1836  if(!StoreVertex(tjs, vx2)) return false;
1837  if(!SplitTraj(tjs, tp2.id - 1, tp2.ipt, tjs.vtx.size() - 1, prt)) return false;
1838  vx2ids.push_back(vx2.ID);
1839  AttachAnyTrajToVertex(tjs, tjs.vtx.size() - 1, prt);
1840  if(prt) mf::LogVerbatim("TC")<<" tj "<<tj.ID<<" new 2V"<<vx2.ID;
1841  }
1842  } // tp2
1843  } // ipt
1844 
1845  if(vx2ids.size() != tjs.NumPlanes) {
1846 // std::cout<<"Split3DKink: TODO pfp "<<pfp.ID<<" only has "<<vx2ids.size()<<" 2D vertices. \n";
1847  return false;
1848  }
1849  Vtx3Store vx3;
1850  vx3.TPCID = pfp.TPCID;
1851  vx3.ID = tjs.vtx3.size() + 1;
1852  vx3.X = pfp.Tp3s[kpt].Pos[0];
1853  vx3.Y = pfp.Tp3s[kpt].Pos[1];
1854  vx3.Z = pfp.Tp3s[kpt].Pos[2];
1855  for(auto vx2id : vx2ids) {
1856  if(vx2id == 0) continue;
1857  auto& vx2 = tjs.vtx[vx2id - 1];
1858  unsigned short plane = DecodeCTP(vx2.CTP).Plane;
1859  vx3.Vx2ID[plane] = vx2id;
1860  vx2.Vx3ID = vx3.ID;
1861  } // vx2id
1862  std::cout<<"Split3DKink add 3V"<<vx3.ID<<"\n";
1863  tjs.vtx3.push_back(vx3);
1864  // mark this as needing an update
1865  pfp.NeedsUpdate = true;
1866  return true;
1867  } // Split3DKink
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool AttachAnyTrajToVertex(TjStuff &tjs, unsigned short ivx, bool prt)
Definition: TCVertex.cxx:1689
bool SplitTraj(TjStuff &tjs, unsigned short itj, float XPos, bool makeVx2, bool prt)
Definition: Utils.cxx:1879
double KinkAngle(const TjStuff &tjs, const std::vector< TrajPoint3 > &tp3s, unsigned short atPt, double sep)
Definition: PFPUtils.cxx:1913
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
std::vector< unsigned short > FindKinks(const TjStuff &tjs, PFPStruct &pfp, double sep, bool prt)
Definition: PFPUtils.cxx:1870
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
bool StoreVertex(TjStuff &tjs, VtxStore &vx)
Definition: TCVertex.cxx:1911
bool tca::SplitTraj ( TjStuff tjs,
unsigned short  itj,
float  XPos,
bool  makeVx2,
bool  prt 
)

Definition at line 1879 of file Utils.cxx.

References tca::TjStuff::allTraj, detinfo::DetectorProperties::ConvertXToTicks(), tca::VtxStore::CTP, DecodeCTP(), tca::TjStuff::detprop, tca::VtxStore::NTraj, tca::VtxStore::Pos, SplitTraj(), StoreVertex(), tca::VtxStore::Topo, tca::TjStuff::UnitsPerTick, and tca::TjStuff::vtx.

Referenced by CompleteIncomplete3DVertices(), FindHammerVertices(), FindHammerVertices2(), Split3DKink(), and SplitTrajCrossingVertices().

1880  {
1881  // Splits the trajectory at an X position and optionally creates a 2D vertex at the split point
1882  if(itj > tjs.allTraj.size()-1) return false;
1883 
1884  auto& tj = tjs.allTraj[itj];
1885  geo::PlaneID planeID = DecodeCTP(tj.CTP);
1886  float atPos1 = tjs.detprop->ConvertXToTicks(XPos, planeID) * tjs.UnitsPerTick;
1887  unsigned short atPt = USHRT_MAX;
1888  for(unsigned short ipt = tj.EndPt[0] + 1; ipt <= tj.EndPt[1]; ++ipt) {
1889  if(tj.Pts[ipt].Pos[1] > tj.Pts[ipt - 1].Pos[1]) {
1890  // positive slope
1891  if(tj.Pts[ipt - 1].Pos[1] < atPos1 && tj.Pts[ipt].Pos[1] >= atPos1) {
1892  atPt = ipt;
1893  break;
1894  }
1895  } else {
1896  // negative slope
1897  if(tj.Pts[ipt - 1].Pos[1] >= atPos1 && tj.Pts[ipt].Pos[1] < atPos1) {
1898  atPt = ipt;
1899  break;
1900  }
1901  } // negative slope
1902  } // ipt
1903  if(atPt == USHRT_MAX) return false;
1904  unsigned short vx2Index = USHRT_MAX;
1905  if(makeVx2) {
1906  VtxStore newVx2;
1907  newVx2.CTP = tj.CTP;
1908  newVx2.Pos[0] = 0.5 * (tj.Pts[atPt - 1].Pos[0] + tj.Pts[atPt].Pos[0]);
1909  newVx2.Pos[1] = 0.5 * (tj.Pts[atPt - 1].Pos[1] + tj.Pts[atPt].Pos[1]);
1910  newVx2.Topo = 10;
1911  newVx2.NTraj = 2;
1912  if(StoreVertex(tjs, newVx2)) vx2Index = tjs.vtx.size() - 1;
1913  } // makeVx2
1914  return SplitTraj(tjs, itj, atPt, vx2Index, prt);
1915  } // SplitTraj
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
bool SplitTraj(TjStuff &tjs, unsigned short itj, unsigned short pos, unsigned short ivx, bool prt)
Definition: Utils.cxx:1918
bool StoreVertex(TjStuff &tjs, VtxStore &vx)
Definition: TCVertex.cxx:1911
bool tca::SplitTraj ( TjStuff tjs,
unsigned short  itj,
unsigned short  pos,
unsigned short  ivx,
bool  prt 
)

Definition at line 1918 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::TjStuff::allTraj, tca::Trajectory::EndPt, tca::TjStuff::fHits, tca::Trajectory::ID, kSplit, tca::Trajectory::ParentID, tca::Trajectory::PDGCode, tca::Trajectory::Pts, SetEndPoints(), SetPDGCode(), UpdateMatchStructs(), UpdateTjChgProperties(), tca::TjStuff::vtx, and tca::Trajectory::VtxID.

Referenced by CheckTrajBeginChg(), and SplitTraj().

1919  {
1920  // Splits the trajectory itj in the tjs.allTraj vector into two trajectories at position pos. Splits
1921  // the trajectory and associates the ends to the supplied vertex.
1922  // Here is an example where itj has 9 points and we will split at pos = 4
1923  // itj (0 1 2 3 4 5 6 7 8) -> new traj (0 1 2 3) + new traj (4 5 6 7 8)
1924 
1925  if(itj > tjs.allTraj.size()-1) return false;
1926  if(pos < tjs.allTraj[itj].EndPt[0] + 1 || pos > tjs.allTraj[itj].EndPt[1] - 1) return false;
1927  if(ivx != USHRT_MAX && ivx > tjs.vtx.size() - 1) return false;
1928 
1929  Trajectory& tj = tjs.allTraj[itj];
1930 
1931  // Reset the PDG Code if we are splitting a tagged muon
1932  bool splittingMuon = (tj.PDGCode == 13);
1933  if(splittingMuon) tj.PDGCode = 0;
1934 
1935  if(prt) {
1936  mf::LogVerbatim myprt("TC");
1937  myprt<<"SplitTraj: Split T"<<tj.ID<<" at point "<<pos;
1938  if(ivx < tjs.vtx.size()) myprt<<" with Vtx 2V"<<tjs.vtx[ivx].ID;
1939  }
1940 
1941  // ensure that there will be at least 3 TPs on each trajectory
1942  unsigned short ipt, ii, ntp = 0;
1943  for(ipt = 0; ipt < pos; ++ipt) {
1944  if(tj.Pts[ipt].Chg > 0) ++ntp;
1945  if(ntp > 2) break;
1946  } // ipt
1947  if(ntp < 3) {
1948  if(prt) mf::LogVerbatim("TC")<<" Split point to small at begin "<<ntp<<" pos "<<pos<<" ID ";
1949  return false;
1950  }
1951  ntp = 0;
1952  for(ipt = pos + 1; ipt < tj.Pts.size(); ++ipt) {
1953  if(tj.Pts[ipt].Chg > 0) ++ntp;
1954  if(ntp > 2) break;
1955  } // ipt
1956  if(ntp < 3) {
1957  if(prt) mf::LogVerbatim("TC")<<" Split point too small at end "<<ntp<<" pos "<<pos<<" EndPt "<<tj.EndPt[1];
1958  return false;
1959  }
1960 
1961  // make a copy that will become the Tj after the split point
1962  Trajectory newTj = tj;
1963  newTj.ID = tjs.allTraj.size() + 1;
1964  // make another copy in case something goes wrong
1965  Trajectory oldTj = tj;
1966 
1967  // Leave the first section of tj in place. Re-assign the hits
1968  // to the new trajectory
1969  unsigned int iht;
1970  for(ipt = pos + 1; ipt < tj.Pts.size(); ++ipt) {
1971  tj.Pts[ipt].Chg = 0;
1972  for(ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
1973  if(!tj.Pts[ipt].UseHit[ii]) continue;
1974  iht = tj.Pts[ipt].Hits[ii];
1975  // This shouldn't happen but check anyway
1976  if(tjs.fHits[iht].InTraj != tj.ID) continue;
1977  tjs.fHits[iht].InTraj = newTj.ID;
1978  tj.Pts[ipt].UseHit[ii] = false;
1979  } // ii
1980  } // ipt
1981  SetEndPoints(tjs, tj);
1982  UpdateTjChgProperties("ST", tjs, tj, prt);
1983  if(splittingMuon) SetPDGCode(tjs, tj);
1984 
1985  // Append 3 points from the end of tj onto the
1986  // beginning of newTj so that hits can be swapped between
1987  // them later
1988  unsigned short eraseSize = pos - 2;
1989  if(eraseSize > newTj.Pts.size() - 1) {
1990  tj = oldTj;
1991  return false;
1992  }
1993 
1994  if(ivx < tjs.vtx.size()) tj.VtxID[1] = tjs.vtx[ivx].ID;
1995  tj.AlgMod[kSplit] = true;
1996  if(prt) {
1997  mf::LogVerbatim("TC")<<" Splitting T"<<tj.ID<<" new EndPts "<<tj.EndPt[0]<<" to "<<tj.EndPt[1];
1998  }
1999 
2000  // erase the TPs at the beginning of the new trajectory
2001  newTj.Pts.erase(newTj.Pts.begin(), newTj.Pts.begin() + eraseSize);
2002  // unset the first 3 TP hits
2003  for(ipt = 0; ipt < 3; ++ipt) {
2004  for(ii = 0; ii < newTj.Pts[ipt].Hits.size(); ++ii) newTj.Pts[ipt].UseHit[ii] = false;
2005  newTj.Pts[ipt].Chg = 0;
2006  } // ipt
2007  SetEndPoints(tjs, newTj);
2008  UpdateTjChgProperties("ST", tjs, newTj, prt);
2009  if(splittingMuon) SetPDGCode(tjs, newTj);
2010  if(ivx < tjs.vtx.size()) newTj.VtxID[0] = tjs.vtx[ivx].ID;
2011  newTj.AlgMod[kSplit] = true;
2012  newTj.ParentID = 0;
2013  // save the ID before push_back in case the tj reference gets lost
2014  int tjid = tj.ID;
2015  tjs.allTraj.push_back(newTj);
2016  UpdateMatchStructs(tjs, tjid, newTj.ID);
2017 
2018  if(prt) {
2019  mf::LogVerbatim("TC")<<" newTj T"<<newTj.ID<<" EndPts "<<newTj.EndPt[0]<<" to "<<newTj.EndPt[1];
2020  }
2021  return true;
2022 
2023  } // SplitTraj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void UpdateTjChgProperties(std::string inFcnLabel, TjStuff &tjs, Trajectory &tj, bool prt)
Definition: Utils.cxx:3118
void UpdateMatchStructs(TjStuff &tjs, int oldTj, int newTj)
Definition: PFPUtils.cxx:16
void SetEndPoints(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:2788
void SetPDGCode(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:3704
void tca::SplitTrajCrossingVertices ( TjStuff tjs,
CTP_t  inCTP 
)

Definition at line 1091 of file TCVertex.cxx.

References tca::TjStuff::allTraj, debug, DecodeCTP(), DeltaAngle(), evd::details::end(), FitVertex(), GetVtxTjIDs(), kDeltaRay, tca::TjStuff::KinkCuts, kKilled, kOnDeadWire, kSplitTjCVx, MakeVertexObsolete(), NumPtsWithCharge(), tca::DebugStuff::Plane, geo::PlaneID::Plane, PointTrajDOCA(), PrintTrajPoint(), SplitTraj(), tca::DebugStuff::Tick, TrajClosestApproach(), tca::TjStuff::UseAlg, tca::TjStuff::Vertex2DCuts, and tca::TjStuff::vtx.

Referenced by tca::TrajClusterAlg::ReconstructAllTraj().

1092  {
1093  // This is kind of self-explanatory...
1094 
1095  if(!tjs.UseAlg[kSplitTjCVx]) return;
1096 
1097  if(tjs.vtx.empty()) return;
1098  if(tjs.allTraj.empty()) return;
1099 
1100  constexpr float docaCut = 4;
1101 
1102  bool prt = (debug.Plane >= 0 && debug.Tick == 77777);
1103  if(prt) mf::LogVerbatim("TC")<<"Inside SplitTrajCrossingVertices inCTP "<<inCTP;
1104 
1105  geo::PlaneID planeID = DecodeCTP(inCTP);
1106 
1107  unsigned short nTraj = tjs.allTraj.size();
1108  for(unsigned short itj = 0; itj < nTraj; ++itj) {
1109  // NOTE: Don't use a reference variable because it may get lost if the tj is split
1110 // auto& tj = tjs.allTraj[itj];
1111  if(tjs.allTraj[itj].CTP != inCTP) continue;
1112  // obsolete trajectory
1113  if(tjs.allTraj[itj].AlgMod[kKilled]) continue;
1114  if(tjs.allTraj[itj].AlgMod[kSplitTjCVx]) continue;
1115  // too short
1116  if(tjs.allTraj[itj].EndPt[1] < 6) continue;
1117  for(unsigned short iv = 0; iv < tjs.vtx.size(); ++iv) {
1118  auto& vx2 = tjs.vtx[iv];
1119  // obsolete vertex
1120  if(vx2.NTraj == 0) continue;
1121  // trajectory already associated with vertex
1122  if(tjs.allTraj[itj].VtxID[0] == vx2.ID ||
1123  tjs.allTraj[itj].VtxID[1] == vx2.ID) continue;
1124  // not in the cryostat/tpc/plane
1125  if(tjs.allTraj[itj].CTP != vx2.CTP) continue;
1126  // poor quality
1127  if(vx2.Score < tjs.Vertex2DCuts[7]) continue;
1128  float doca = docaCut;
1129  // make the cut significantly larger if the vertex is in a dead
1130  // wire gap to get the first TP that is just outside the gap.
1131  if(vx2.Stat[kOnDeadWire]) doca = 100;
1132  unsigned short closePt = 0;
1133  if(!TrajClosestApproach(tjs.allTraj[itj], vx2.Pos[0], vx2.Pos[1], closePt, doca)) continue;
1134  if(vx2.Stat[kOnDeadWire]) {
1135  // special handling for vertices in dead wire regions. Find the IP between
1136  // the closest point on the Tj and the vertex
1137  doca = PointTrajDOCA(tjs, vx2.Pos[0], vx2.Pos[1], tjs.allTraj[itj].Pts[closePt]);
1138  }
1139  if(doca > docaCut) continue;
1140  if(prt) mf::LogVerbatim("TC")<<" doca "<<doca<<" btw T"<<tjs.allTraj[itj].ID<<" and 2V"<<tjs.vtx[iv].ID<<" closePt "<<closePt<<" in plane "<<planeID.Plane;
1141  // compare the length of the Tjs used to make the vertex with the length of the
1142  // Tj that we want to split. Don't allow a vertex using very short Tjs to split a long
1143  // Tj in the 3rd plane
1144  auto vxtjs = GetVtxTjIDs(tjs, vx2);
1145  if(vxtjs.empty()) continue;
1146  unsigned short maxPts = 0;
1147  // ensure that there is a large angle between a Tj already attached to the vertex and the
1148  // tj that we want to split. We might be considering a delta-ray here
1149  float maxdang = 0;
1150  float tjAng = tjs.allTraj[itj].Pts[closePt].Ang;
1151  for(auto tjid : vxtjs) {
1152  auto& vtj = tjs.allTraj[tjid - 1];
1153  if(vtj.AlgMod[kDeltaRay]) continue;
1154  unsigned short npwc = NumPtsWithCharge(tjs, vtj, false);
1155  if(npwc > maxPts) maxPts = npwc;
1156  unsigned short end = 0;
1157  if(vtj.VtxID[1] == tjs.vtx[iv].ID) end = 1;
1158  auto& vtp = vtj.Pts[vtj.EndPt[end]];
1159  float dang = DeltaAngle(vtp.Ang, tjAng);
1160  if(dang > maxdang) maxdang = dang;
1161  } // tjid
1162  // skip this operation if any of the Tjs in the split list are > 3 * maxPts
1163  maxPts *= 3;
1164  bool skipit = false;
1165  if(NumPtsWithCharge(tjs, tjs.allTraj[itj], false) > maxPts && maxPts < 100) skipit = true;
1166  if(!skipit && maxdang < tjs.KinkCuts[0]) skipit = true;
1167  if(prt) mf::LogVerbatim("TC")<<" maxPts "<<maxPts<<" vxtjs[0] "<<vxtjs[0]<<" maxdang "<<maxdang<<" skipit? "<<skipit;
1168  if(skipit) {
1169  // kill the vertex?
1170  if(doca < 1) MakeVertexObsolete(tjs, vx2, true);
1171  continue;
1172  }
1173 
1174  // make some adjustments to closePt
1175  if(vx2.Stat[kOnDeadWire]) {
1176  // ensure that the tj will be split at the gap. The closePt point may be
1177  // on the wrong side of it
1178  auto& closeTP = tjs.allTraj[itj].Pts[closePt];
1179  if(tjs.allTraj[itj].StepDir > 0 && closePt > tjs.allTraj[itj].EndPt[0]) {
1180  if(closeTP.Pos[0] > vx2.Pos[0]) --closePt;
1181  } else if(tjs.allTraj[itj].StepDir < 0 && closePt < tjs.allTraj[itj].EndPt[1]) {
1182  if(closeTP.Pos[0] < vx2.Pos[0]) ++closePt;
1183  }
1184  } else {
1185  // improve closePt based on vertex position
1186  // check if closePt and EndPt[1] are the two sides of vertex
1187  // take dot product of closePt-vtx and EndPt[1]-vtx
1188  if ((tjs.allTraj[itj].Pts[closePt].Pos[0]-vx2.Pos[0])*(tjs.allTraj[itj].Pts[tjs.allTraj[itj].EndPt[1]].Pos[0]-vx2.Pos[0]) + (tjs.allTraj[itj].Pts[closePt].Pos[1]-vx2.Pos[1])*(tjs.allTraj[itj].Pts[tjs.allTraj[itj].EndPt[1]].Pos[1]-vx2.Pos[1]) <0 && closePt < tjs.allTraj[itj].EndPt[1] - 1) ++closePt;
1189  else if ((tjs.allTraj[itj].Pts[closePt].Pos[0]-vx2.Pos[0])*(tjs.allTraj[itj].Pts[tjs.allTraj[itj].EndPt[0]].Pos[0]-vx2.Pos[0]) + (tjs.allTraj[itj].Pts[closePt].Pos[1]-vx2.Pos[1])*(tjs.allTraj[itj].Pts[tjs.allTraj[itj].EndPt[0]].Pos[1]-tjs.vtx[iv].Pos[1]) <0 && closePt > tjs.allTraj[itj].EndPt[0] + 1) --closePt;
1190  }
1191 
1192 
1193  if(prt) {
1194  mf::LogVerbatim("TC")<<"Good doca "<<doca<<" btw T"<<tjs.allTraj[itj].ID<<" and 2V"<<vx2.ID<<" closePt "<<closePt<<" in plane "<<planeID.Plane<<" CTP "<<tjs.vtx[iv].CTP;
1195  PrintTrajPoint("STCV", tjs, closePt, 1, tjs.allTraj[itj].Pass, tjs.allTraj[itj].Pts[closePt]);
1196  }
1197  // ensure that the closest point is not near an end
1198  if(closePt < tjs.allTraj[itj].EndPt[0] + 3) continue;
1199  if(closePt > tjs.allTraj[itj].EndPt[1] - 3) continue;
1200  if(!SplitTraj(tjs, itj, closePt, iv, prt)) {
1201  if(prt) mf::LogVerbatim("TC")<<"SplitTrajCrossingVertices: Failed to split trajectory";
1202  continue;
1203  }
1204  tjs.allTraj[itj].AlgMod[kSplitTjCVx] = true;
1205  unsigned short newTjIndex = tjs.allTraj.size() - 1;
1206  tjs.allTraj[newTjIndex].AlgMod[kSplitTjCVx] = true;
1207  // re-fit the vertex position
1208  FitVertex(tjs, vx2, prt);
1209  } // iv
1210  } // itj
1211 
1212  } // SplitTrajCrossingVertices
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
bool TrajClosestApproach(Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
Definition: Utils.cxx:2244
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1607
bool FitVertex(TjStuff &tjs, VtxStore &vx, std::vector< TrajPoint > vxTp, bool prt)
Definition: TCVertex.cxx:1986
bool SplitTraj(TjStuff &tjs, unsigned short itj, float XPos, bool makeVx2, bool prt)
Definition: Utils.cxx:1879
DebugStuff debug
Definition: DebugStruct.cxx:4
std::vector< int > GetVtxTjIDs(const TjStuff &tjs, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:3039
int Plane
Select plane.
Definition: DebugStruct.h:29
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
float PointTrajDOCA(TjStuff const &tjs, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2139
int Tick
Select hit PeakTime for debugging (< 0 for vertex finding)
Definition: DebugStruct.h:32
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
unsigned short NumPtsWithCharge(const TjStuff &tjs, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1738
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool MakeVertexObsolete(TjStuff &tjs, Vtx3Store &vx3)
Definition: TCVertex.cxx:3001
void PrintTrajPoint(std::string someText, const TjStuff &tjs, unsigned short ipt, short dir, unsigned short pass, TrajPoint const &tp)
Definition: Utils.cxx:4574
std::vector< float > tca::StartChgVec ( TjStuff tjs,
int  cotID,
bool  prt 
)

Definition at line 4254 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::ShowerStruct::Angle, tca::TjStuff::cots, tca::TjStuff::fHits, tca::ShowerStruct::ID, tca::ShowerStruct::ParentID, tca::TrajPoint::Pos, tca::ShowerStruct::ShowerTjID, tca::ShowerStruct::ShPts, ss, tca::ShowerStruct::TjIDs, and tca::TjStuff::UnitsPerTick.

Referenced by FindStartChg().

4255  {
4256  // Returns a histogram vector of the charge in bins of 1 WSE unit at the start of the shower
4257 
4258  ShowerStruct& ss = tjs.cots[cotID - 1];
4259  constexpr unsigned short nbins = 20;
4260  std::vector<float> schg(nbins);
4261  if(ss.ID == 0) return schg;
4262  if(ss.TjIDs.empty()) return schg;
4263  TrajPoint& stp1 = tjs.allTraj[ss.ShowerTjID-1].Pts[1];
4264 
4265  // move the min along point back by 2 WSE so that most of the charge in the hits in the
4266  // first point is included in the histogram
4267  float minAlong = ss.ShPts[0].RotPos[0] - 2;
4268 
4269  float maxTrans = 4;
4270  // Tighten up on the maximum allowed transverse position if there is a parent
4271  if(ss.ParentID > 0) maxTrans = 1;
4272  float cs = cos(-ss.Angle);
4273  float sn = sin(-ss.Angle);
4274  std::array<float, 2> chgPos;
4275  float along, arg;
4276 
4277  for(auto& sspt : ss.ShPts) {
4278  unsigned short indx = (unsigned short)((sspt.RotPos[0] - minAlong));
4279  if(indx > nbins - 1) break;
4280  // Count the charge if it is within a few WSE transverse from the shower axis
4281  if(std::abs(sspt.RotPos[1]) > maxTrans) continue;
4282  unsigned int iht = sspt.HitIndex;
4283  float& peakTime = tjs.fHits[iht].PeakTime;
4284  float& amp = tjs.fHits[iht].PeakAmplitude;
4285  float& rms = tjs.fHits[iht].RMS;
4286  chgPos[0] = tjs.fHits[iht].ArtPtr->WireID().Wire - stp1.Pos[0];
4287  for(float time = peakTime - 2.5 * rms; time < peakTime + 2.5 * rms; ++time) {
4288  chgPos[1] = time * tjs.UnitsPerTick - stp1.Pos[1];
4289  along = cs * chgPos[0] - sn * chgPos[1];
4290  if(along < minAlong) continue;
4291  indx = (unsigned short)(along - minAlong);
4292  if(indx > nbins - 1) continue;
4293  arg = (time - peakTime) / rms;
4294  schg[indx] += amp * exp(-0.5 * arg * arg);
4295  } // time
4296  } // sspt
4297 
4298  return schg;
4299  } // StartChgVec
Float_t ss
Definition: plot.C:23
bool tca::StorePFP ( TjStuff tjs,
PFPStruct pfp 
)

Definition at line 2660 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, tca::PFPStruct::BestPlane, FilldEdx(), tca::PFPStruct::ID, kMat3D, kSetDir, tca::PFPStruct::NeedsUpdate, tca::PFPStruct::PDGCode, tca::TjStuff::pfps, ReverseTraj(), tca::PFPStruct::TjIDs, and tca::PFPStruct::Tp3s.

Referenced by DefineTjParents(), DotProd(), FindPFParticles(), and Match3DVtxTjs().

2661  {
2662  // stores the PFParticle in TJStuff
2663  if(pfp.ID < int(tjs.pfps.size())) return false;
2664  bool neutrinoPFP = pfp.PDGCode == 12 || pfp.PDGCode == 14;
2665  if(!neutrinoPFP) {
2666  if(pfp.TjIDs.empty()) return false;
2667  if(pfp.PDGCode != 1111 && pfp.Tp3s.size() < 2) return false;
2668  }
2669  // check the ID and correct it if it is wrong
2670  if(pfp.ID != (int)tjs.pfps.size() + 1) pfp.ID = tjs.pfps.size() + 1;
2671  // check the Tjs and set the 3D match flag
2672  for(auto tjid : pfp.TjIDs) {
2673  auto& tj = tjs.allTraj[tjid - 1];
2674  if(tj.AlgMod[kMat3D]) return false;
2675  tj.AlgMod[kMat3D] = true;
2676  } // tjid
2677 
2678  if(!pfp.Tp3s.empty()) {
2679  // ensure that the Tj points are in increasing order and reverse them if they aren't. This
2680  // presumes that the space points have been ordered from pfp start to pfp end
2681  std::vector<int> tjids;
2682  // list of tj points to check for increasing (or decreasing) order
2683  std::vector<short> firstIpt;
2684  std::vector<short> lastIpt;
2685  for(auto& Tp3 : pfp.Tp3s) {
2686  for(auto& tj2pt : Tp3.Tj2Pts) {
2687  int tjid = tj2pt.id;
2688  // check for the first occurrence
2689  unsigned short ii = 0;
2690  for(ii = 0; ii < tjids.size(); ++ii) if(tjid == tjids[ii]) break;
2691  if(ii < tjids.size()) {
2692  // exists in the list. Keep track of the last point
2693  lastIpt[ii] = tj2pt.ipt;
2694  continue;
2695  }
2696  tjids.push_back(tjid);
2697  firstIpt.push_back((short)tj2pt.ipt);
2698  lastIpt.push_back((short)tj2pt.ipt);
2699  } // tjpt
2700  } // spt
2701  // reverse Tjs if necessary so that end0 is at the start of the pfp
2702  for(unsigned short ii = 0; ii < tjids.size(); ++ii) {
2703  // ignore Tjs that aren't associated with this pfp
2704  if(std::find(pfp.TjIDs.begin(), pfp.TjIDs.end(), tjids[ii]) == pfp.TjIDs.end()) continue;
2705  auto& tj = tjs.allTraj[tjids[ii] - 1];
2706  if(lastIpt[ii] < firstIpt[ii]) {
2707  if(tj.AlgMod[kSetDir]) {
2708 // std::cout<<"StorePFP "<<pfp.ID<<" Violating the SetDir flag for Tj "<<tj.ID<<"\n";
2709  tj.AlgMod[kSetDir] = false;
2710  }
2711  ReverseTraj(tjs, tj);
2712  } // lastIpt[ii] > firstIpt[ii]
2713  } // ii
2714  } // Tp3s exist
2715 
2716  if(pfp.BestPlane < 0) FilldEdx(tjs, pfp);
2717 
2718  if(pfp.NeedsUpdate) std::cout<<"StorePFP: stored P"<<pfp.ID<<" but NeedsUpdate is true...\n";
2719 
2720  tjs.pfps.push_back(pfp);
2721  return true;
2722  } // StorePFP
void ReverseTraj(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:2666
void FilldEdx(TjStuff &tjs, TrajPoint3 &tp3)
Definition: PFPUtils.cxx:1714
bool tca::StoreShower ( std::string  inFcnLabel,
TjStuff tjs,
ShowerStruct3D ss3 
)

Definition at line 4468 of file TCShower.cxx.

References tca::ShowerStruct3D::CotIDs, tca::TjStuff::cots, tca::ShowerStruct3D::ID, tca::TjStuff::showers, and ss.

Referenced by tca::MCParticleListUtils::MakeCheatShower(), and tca::TruthMatcher::StudyShowerParents().

4469  {
4470  // Store a 3D shower. This function sets the 3S -> 2S assns using CotIDs and ensures
4471  // that the 2S -> 3S assns are OK.
4472 
4473  std::string fcnLabel = inFcnLabel + ".S3S";
4474  if(ss3.ID <= 0) {
4475  std::cout<<fcnLabel<<" Invalid ID";
4476  return false;
4477  }
4478  if(ss3.CotIDs.size() < 2) {
4479  std::cout<<fcnLabel<<" not enough CotIDs";
4480  return false;
4481  }
4482 
4483  // check the 2S -> 3S assns
4484  for(auto& ss : tjs.cots) {
4485  if(ss.ID == 0) continue;
4486  if(ss.SS3ID == ss3.ID && std::find(ss3.CotIDs.begin(), ss3.CotIDs.end(), ss.ID) == ss3.CotIDs.end()) {
4487  std::cout<<fcnLabel<<" Bad assn: 2S"<<ss.ID<<" -> 3S"<<ss3.ID<<" but it's not inCotIDs.\n";
4488  return false;
4489  }
4490  } // ss
4491 
4492  // check the 3S -> 2S assns
4493  for(auto cid : ss3.CotIDs) {
4494  if(cid <= 0 || cid > (int)tjs.cots.size()) return false;
4495  auto& ss = tjs.cots[cid - 1];
4496  if(ss.SS3ID > 0 && ss.SS3ID != ss3.ID) {
4497  std::cout<<fcnLabel<<" Bad assn: 3S"<<ss3.ID<<" -> 2S"<<cid<<" but 2S -> 3S"<<ss.SS3ID<<"\n";
4498  return false;
4499  }
4500  } // cid
4501 
4502  // set the 2S -> 3S assns
4503  for(auto cid : ss3.CotIDs) tjs.cots[cid - 1].SS3ID = ss3.ID;
4504 
4505  tjs.showers.push_back(ss3);
4506  return true;
4507 
4508  } // StoreShower
Float_t ss
Definition: plot.C:23
bool tca::StoreShower ( std::string  inFcnLabel,
TjStuff tjs,
ShowerStruct ss 
)

Definition at line 4511 of file TCShower.cxx.

References tca::Trajectory::AlgMod, tca::TjStuff::allTraj, tca::ShowerStruct::Cheat, tca::TjStuff::cots, tca::Trajectory::ID, tca::ShowerStruct::ID, kShwrParent, tca::ShowerStruct::ParentID, tca::Trajectory::SSID, and tca::ShowerStruct::TjIDs.

Referenced by CompleteIncompleteShower(), FindShowers3D(), Match2DShowers(), and MergeShowers().

4512  {
4513  // Store a ShowerStruct
4514  std::string fcnLabel = inFcnLabel + ".S2S";
4515  if(ss.ID <= 0) {
4516  std::cout<<fcnLabel<<" Invalid ID";
4517  return false;
4518  }
4519  if(!ss.Cheat && ss.TjIDs.empty()) {
4520  std::cout<<fcnLabel<<" Fail: No TjIDs in 2S"<<ss.ID<<"\n";
4521  return false;
4522  }
4523  if(ss.ParentID > 0) {
4524  if(ss.ParentID > (int)tjs.allTraj.size()) {
4525  std::cout<<fcnLabel<<" Fail: 2S"<<ss.ID<<" has an invalid ParentID T"<<ss.ParentID<<"\n";
4526  return false;
4527  }
4528  if(std::find(ss.TjIDs.begin(), ss.TjIDs.end(), ss.ParentID) != ss.TjIDs.end()) {
4529  std::cout<<fcnLabel<<" Fail: 2S"<<ss.ID<<" ParentID is not in TjIDs.\n";
4530  return false;
4531  }
4532  } // ss.ParentID > 0
4533 
4534  // check the ID
4535  if(ss.ID != (int)tjs.cots.size() + 1) {
4536  std::cout<<fcnLabel<<" Correcting the ID 2S"<<ss.ID<<" -> 2S"<<tjs.cots.size() + 1;
4537  ss.ID = tjs.cots.size() + 1;
4538  }
4539 
4540  // set the tj shower bits
4541  for(auto& tjID : ss.TjIDs) {
4542  Trajectory& tj = tjs.allTraj[tjID - 1];
4543  tj.SSID = ss.ID;
4544  tj.AlgMod[kShwrParent] = false;
4545  if(tj.ID == ss.ParentID) tj.AlgMod[kShwrParent] = true;
4546  } // tjID
4547  tjs.cots.push_back(ss);
4548  return true;
4549 
4550  } // StoreShower
Float_t ss
Definition: plot.C:23
bool tca::StoreTraj ( TjStuff tjs,
Trajectory tj 
)

Definition at line 1095 of file Utils.cxx.

References tca::TjStuff::allTraj, debug, tca::Trajectory::DirFOM, tca::Trajectory::EndPt, tca::TjStuff::fHits, tca::DebugStuff::Hit, tca::Trajectory::ID, tca::Trajectory::ParentID, PrintHit(), tca::Trajectory::Pts, ReleaseHits(), SetEndPoints(), tca::Trajectory::StepDir, TjDirFOM(), UpdateTjChgProperties(), and tca::Trajectory::WorkID.

Referenced by tca::TrajClusterAlg::FindVtxTraj(), tca::TrajClusterAlg::MakeJunkTraj(), MergeAndStore(), MergePFPTjs(), and tca::TrajClusterAlg::ReconstructAllTraj().

1096  {
1097 
1098  if(!(tj.StepDir == 1 || tj.StepDir == -1)) {
1099  mf::LogError("TC")<<"StoreTraj: Invalid StepDir "<<tj.StepDir;
1100  return false;
1101  }
1102 
1103  if(tjs.allTraj.size() >= USHRT_MAX) {
1104  mf::LogError("TC")<<"StoreTraj: Too many trajectories "<<tjs.allTraj.size();
1105  return false;
1106  }
1107 
1108  // This shouldn't be necessary but do it anyway
1109  SetEndPoints(tjs, tj);
1110 
1111  if(tj.EndPt[1] <= tj.EndPt[0]) return false;
1112  if(tj.EndPt[1] > tj.Pts.size()) return false;
1113  unsigned short npts = tj.EndPt[1] - tj.EndPt[0] + 1;
1114  if(npts < 2) return false;
1115 
1116  auto& endTp0 = tj.Pts[tj.EndPt[0]];
1117  auto& endTp1 = tj.Pts[tj.EndPt[1]];
1118 
1119  // Calculate the charge near the end and beginning if necessary. This must be a short
1120  // trajectory. Find the average using 4 points
1121  if(endTp0.AveChg <= 0) {
1122  unsigned short cnt = 0;
1123  float sum = 0;
1124  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1125  if(tj.Pts[ipt].Chg == 0) continue;
1126  sum += tj.Pts[ipt].Chg;
1127  ++cnt;
1128  if(cnt == 4) break;
1129  }
1130  tj.Pts[tj.EndPt[0]].AveChg = sum / (float)cnt;
1131  }
1132  if(endTp1.AveChg <= 0 && npts < 5) endTp1.AveChg = endTp0.AveChg;
1133  if(endTp1.AveChg <= 0) {
1134  float sum = 0;
1135  unsigned short cnt = 0;
1136  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
1137  short ipt = tj.EndPt[1] - ii;
1138  if(ipt < 0) break;
1139  if(tj.Pts[ipt].Chg == 0) continue;
1140  sum += tj.Pts[ipt].Chg;
1141  ++cnt;
1142  if(cnt == 4) break;
1143  if(ipt == 0) break;
1144  } // ii
1145  tj.Pts[tj.EndPt[1]].AveChg = sum / (float)cnt;
1146  } // begin charge == end charge
1147 
1148 
1149  tj.DirFOM = TjDirFOM(tjs, tj, false);
1150  UpdateTjChgProperties("ST", tjs, tj, false);
1151 
1152  int trID = tjs.allTraj.size() + 1;
1153 
1154  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1155  for(unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
1156  if(tj.Pts[ipt].UseHit[ii]) {
1157  unsigned int iht = tj.Pts[ipt].Hits[ii];
1158  if(tjs.fHits[iht].InTraj > 0) {
1159  mf::LogWarning("TC")<<"StoreTraj: Failed trying to store hit "<<PrintHit(tjs.fHits[iht])<<" in T"<<trID<<" but it is used in T"<<tjs.fHits[iht].InTraj<<" with WorkID "<<tjs.allTraj[tjs.fHits[iht].InTraj-1].WorkID<<" Print and quit";
1160 // PrintTrajectory("ST", tjs, tj, USHRT_MAX);
1161  ReleaseHits(tjs, tj);
1162  return false;
1163  } // error
1164  tjs.fHits[iht].InTraj = trID;
1165  }
1166  } // ii
1167  } // ipt
1168 
1169  // ensure that inTraj is clean for the ID
1170  for(unsigned int iht = 0; iht < tjs.fHits.size(); ++iht) {
1171  if(tjs.fHits[iht].InTraj == tj.ID) {
1172  mf::LogWarning("TC")<<"StoreTraj: Hit "<<PrintHit(tjs.fHits[iht])<<" thinks it belongs to T"<<tj.ID<<" but it isn't in the Tj\n";
1173 // PrintTrajectory("ST", tjs, tj, USHRT_MAX);
1174  return false;
1175  }
1176  } // iht
1177 
1178  tj.WorkID = tj.ID;
1179  tj.ID = trID;
1180  // Don't clobber the ParentID if it was defined by the calling function
1181  if(tj.ParentID == 0) tj.ParentID = trID;
1182  tjs.allTraj.push_back(tj);
1183 // if(prt) mf::LogVerbatim("TC")<<"StoreTraj trID "<<trID<<" CTP "<<tj.CTP<<" EndPts "<<tj.EndPt[0]<<" "<<tj.EndPt[1];
1184  if(debug.Hit != UINT_MAX) {
1185  // print out some debug info
1186  for(unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) {
1187  for(unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
1188  unsigned int iht = tj.Pts[ipt].Hits[ii];
1189  if(iht == debug.Hit) std::cout<<"Debug hit appears in trajectory w WorkID "<<tj.WorkID<<" UseHit "<<tj.Pts[ipt].UseHit[ii]<<"\n";
1190  } // ii
1191  } // ipt
1192  } // debug.Hit ...
1193 
1194  return true;
1195 
1196  } // StoreTraj
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
void ReleaseHits(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:1070
unsigned int Hit
set to the hit index in fHits if a Plane:Wire:Tick match is found
Definition: DebugStruct.h:33
DebugStuff debug
Definition: DebugStruct.cxx:4
void UpdateTjChgProperties(std::string inFcnLabel, TjStuff &tjs, Trajectory &tj, bool prt)
Definition: Utils.cxx:3118
std::string PrintHit(const TCHit &hit)
Definition: Utils.cxx:4732
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
void SetEndPoints(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:2788
float TjDirFOM(const TjStuff &tjs, const Trajectory &tj, bool prt)
Definition: Utils.cxx:906
bool tca::StoreVertex ( TjStuff tjs,
VtxStore vx 
)

Definition at line 1911 of file TCVertex.cxx.

References tca::TjStuff::allTraj, tca::VtxStore::CTP, tca::VtxStore::ID, kKilled, tca::VtxStore::NTraj, tca::VtxStore::Topo, and tca::TjStuff::vtx.

Referenced by CheckTrajBeginChg(), CompleteIncomplete3DVertices(), CompleteIncomplete3DVerticesInGaps(), tca::TrajClusterAlg::EndMerge(), Find2DVertices(), FindHammerVertices(), FindHammerVertices2(), FindNeutralVertices(), MakeJunkVertices(), Split3DKink(), tca::TrajClusterAlg::SplitHiChgHits(), and SplitTraj().

1912  {
1913  // jacket around the push to ensure that the Tj and vtx CTP is consistent.
1914  // The calling function should score the vertex after the trajectories are attached
1915 
1916  if(vx.ID != int(tjs.vtx.size() + 1)) {
1917  mf::LogVerbatim("TC")<<"StoreVertex: Invalid ID "<<vx.ID<<" It should be "<<tjs.vtx.size() + 1;
1918  return false;
1919  }
1920 
1921  unsigned short nvxtj = 0;
1922  unsigned short nok = 0;
1923  for(auto& tj : tjs.allTraj) {
1924  if(tj.AlgMod[kKilled]) continue;
1925  if(vx.ID == tj.VtxID[0] || vx.ID == tj.VtxID[1]) ++nvxtj;
1926  if(vx.CTP != tj.CTP) continue;
1927  if(vx.ID == tj.VtxID[0] || vx.ID == tj.VtxID[1]) ++nok;
1928  } // tj
1929 
1930  if(nok != nvxtj) {
1931  mf::LogVerbatim("TC")<<"StoreVertex: vertex "<<vx.ID<<" Topo "<<vx.Topo<<" has inconsistent CTP code "<<vx.CTP<<" with one or more Tjs\n";
1932  for(auto& tj : tjs.allTraj) {
1933  if(tj.AlgMod[kKilled]) continue;
1934  if(tj.VtxID[0] == vx.ID) tj.VtxID[0] = 0;
1935  if(tj.VtxID[1] == vx.ID) tj.VtxID[1] = 0;
1936  }
1937  return false;
1938  }
1939  vx.NTraj = nok;
1940  tjs.vtx.push_back(vx);
1941  return true;
1942 
1943  } // StoreVertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void tca::TagDeltaRays ( TjStuff tjs,
const CTP_t inCTP 
)

Definition at line 2985 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::TjStuff::allTraj, tca::DebugStuff::CTP, tca::Trajectory::CTP, debug, DeltaAngle(), tca::TjStuff::DeltaRayTag, tca::Trajectory::EndPt, tca::Trajectory::ID, kDeltaRay, tca::TjStuff::KinkCuts, kKilled, tca::Trajectory::MCSMom, tca::Trajectory::ParentID, tca::Trajectory::PDGCode, PointTrajDOCA(), PosSep(), PrintPos(), tca::Trajectory::Pts, ReverseTraj(), tca::Trajectory::StepDir, tca::DebugStuff::Tick, TrajTrajDOCA(), tca::TjStuff::UseAlg, and tca::TjStuff::Vertex2DCuts.

Referenced by DotProd(), and tca::TrajClusterAlg::ReconstructAllTraj().

2986  {
2987  // DeltaRayTag vector elements
2988  // [0] = max separation of both endpoints from a muon
2989  // [1] = minimum MCSMom
2990  // [2] = maximum MCSMom
2991 
2992  if(!tjs.UseAlg[kDeltaRay]) return;
2993  if(tjs.DeltaRayTag[0] < 0) return;
2994  if(tjs.DeltaRayTag.size() < 3) return;
2995 
2996  bool prt = (debug.CTP == inCTP) && (debug.Tick == 31313);
2997 
2998  // double the user-defined separation cut. We will require that at least one of the ends of
2999  // a delta ray be within the user-defined cut and allow
3000  float maxSep = 2 * tjs.DeltaRayTag[0];
3001  float maxMinSep = tjs.DeltaRayTag[0];
3002  unsigned short minMom = tjs.DeltaRayTag[1];
3003  unsigned short maxMom = tjs.DeltaRayTag[2];
3004  unsigned short minMuonLength = 2 * tjs.Vertex2DCuts[2];
3005  unsigned short minpts = 4;
3006  if(prt) mf::LogVerbatim("TC")<<"TagDeltaRays: maxSep "<<maxSep<<" maxMinSep "<<maxMinSep<<" Mom range "<<minMom<<" to "<<maxMom<<" minpts "<<minpts;
3007 
3008  for(unsigned short itj = 0; itj < tjs.allTraj.size(); ++itj) {
3009  Trajectory& muTj = tjs.allTraj[itj];
3010  if(muTj.CTP != inCTP) continue;
3011  if(muTj.AlgMod[kKilled]) continue;
3012  if(muTj.PDGCode != 13) continue;
3013  if(prt) mf::LogVerbatim("TC")<<"TagDeltaRays: Muon T"<<muTj.ID<<" EndPts "<<PrintPos(tjs, muTj.Pts[muTj.EndPt[0]])<<"-"<<PrintPos(tjs, muTj.Pts[muTj.EndPt[1]]);
3014  // min length
3015  if(muTj.EndPt[1] - muTj.EndPt[0] < minMuonLength) continue;
3016  auto& mtp0 = muTj.Pts[muTj.EndPt[0]];
3017  auto& mtp1 = muTj.Pts[muTj.EndPt[1]];
3018  // Found a muon, now look for delta rays
3019  for(unsigned short jtj = 0; jtj < tjs.allTraj.size(); ++jtj) {
3020  if(jtj == itj) continue;
3021  Trajectory& dtj = tjs.allTraj[jtj];
3022  if(dtj.AlgMod[kKilled]) continue;
3023  if(dtj.CTP != inCTP) continue;
3024  if(dtj.PDGCode == 13) continue;
3025  // MCSMom cut
3026  if(dtj.MCSMom < minMom) continue;
3027  if(dtj.MCSMom > maxMom) continue;
3028  if(dtj.EndPt[1] - dtj.EndPt[0] < minpts) continue;
3029  // some rough cuts to require that the delta ray is within the
3030  // ends of the muon
3031  auto& dtp0 = dtj.Pts[dtj.EndPt[0]];
3032  auto& dtp1 = dtj.Pts[dtj.EndPt[1]];
3033  if(muTj.StepDir > 0) {
3034  if(dtp0.Pos[0] < mtp0.Pos[0]) continue;
3035  if(dtp1.Pos[0] > mtp1.Pos[0]) continue;
3036  } else {
3037  if(dtp0.Pos[0] > mtp0.Pos[0]) continue;
3038  if(dtp1.Pos[0] < mtp1.Pos[0]) continue;
3039  }
3040  // find the minimum separation
3041  float doca = maxMinSep;
3042  unsigned short mpt = 0;
3043  unsigned short dpt = 0;
3044  TrajTrajDOCA(tjs, muTj, dtj, mpt, dpt, doca, false);
3045  if(doca == maxMinSep) continue;
3046  auto& dTp = dtj.Pts[dpt];
3047  // cut on the distance from the muon ends
3048  if(PosSep(dTp.Pos, mtp0.Pos) < tjs.Vertex2DCuts[2]) continue;
3049  if(PosSep(dTp.Pos, mtp1.Pos) < tjs.Vertex2DCuts[2]) continue;
3050  // make an angle cut at this point. A delta-ray should have a small angle
3051  float dang = DeltaAngle(muTj.Pts[mpt].Ang, dtj.Pts[dpt].Ang);
3052  if(prt) mf::LogVerbatim("TC")<<" dRay? T"<<dtj.ID<<" at "<<PrintPos(tjs, dtj.Pts[dpt].Pos)<<" dang "<<dang<<" doca "<<doca;
3053  // ignore the angle cut if the separation is small and the delta ray MCSMom is low
3054  bool closeDeltaRay = (doca < 2 && dtj.MCSMom < 20);
3055  if(!closeDeltaRay && dang > tjs.KinkCuts[0]) continue;
3056  // Feb 7, 2018
3057 // if(dang > tjs.KinkCuts[0]) continue;
3058  unsigned short oend = 0;
3059  // check the delta at the end of the delta-ray that is farthest away from the
3060  // closest point
3061  if(dpt > 0.5 * (dtj.EndPt[0] + dtj.EndPt[1])) oend = 1;
3062  auto& farEndTP = dtj.Pts[dtj.EndPt[oend]];
3063  float farEndDelta = PointTrajDOCA(tjs, farEndTP.Pos[0], farEndTP.Pos[1], muTj.Pts[mpt]);
3064  if(prt) mf::LogVerbatim("TC")<<" farEnd "<<PrintPos(tjs, farEndTP.Pos)<<" farEndDelta "<<farEndDelta;
3065  if(farEndDelta > maxSep) continue;
3066  if(prt) mf::LogVerbatim("TC")<<" delta ray "<<dtj.ID<<" parent -> "<<muTj.ID;
3067  dtj.ParentID = muTj.ID;
3068  dtj.PDGCode = 11;
3069  dtj.AlgMod[kDeltaRay] = true;
3070  // Set the start of the delta-ray to be end 0
3071  if(oend != 1) ReverseTraj(tjs, dtj);
3072  } // jtj
3073  } // itj
3074 
3075  } // TagDeltaRays
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float PosSep(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2220
void ReverseTraj(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:2666
DebugStuff debug
Definition: DebugStruct.cxx:4
bool TrajTrajDOCA(const TjStuff &tjs, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep, bool considerDeadWires)
Definition: Utils.cxx:2052
int Tick
Select hit PeakTime for debugging (< 0 for vertex finding)
Definition: DebugStruct.h:32
float PointTrajDOCA(TjStuff const &tjs, float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2147
std::string PrintPos(const TjStuff &tjs, const Point2_t &pos)
Definition: Utils.cxx:4744
double DeltaAngle(double Ang1, double Ang2)
Definition: Utils.cxx:2782
CTP_t CTP
set to an invalid CTP
Definition: DebugStruct.h:30
void tca::TagJunkTj ( TjStuff const &  tjs,
Trajectory tj,
bool  prt 
)

Definition at line 2309 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::ID, kJunkTj, and tca::Trajectory::Pts.

Referenced by tca::TrajClusterAlg::CheckTraj().

2310  {
2311  // Characterizes the trajectory as a junk tj even though it may not
2312  // have been reconstructed in FindJunkTraj. The distinguishing feature is
2313  // that it is short and has many used hits in each trajectory point.
2314 
2315  // Don't bother if it is too long
2316  if(tj.Pts.size() > 10) return;
2317  // count the number of points that have many used hits
2318  unsigned short nhm = 0;
2319  unsigned short npwc = 0;
2320  for(auto& tp : tj.Pts) {
2321  if(tp.Chg == 0) continue;
2322  ++npwc;
2323  unsigned short nused = 0;
2324  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2325  if(tp.UseHit[ii]) ++nused;
2326  } // ii
2327  if(nused > 3) ++nhm;
2328  } // tp
2329  // Set the junkTj bit if most of the hits are used in most of the tps
2330  if(nhm > 0.5 * npwc) tj.AlgMod[kJunkTj] = true;
2331  if(prt) mf::LogVerbatim("TC")<<"TGT: T"<<tj.ID<<" npwc "<<npwc<<" nhm "<<nhm<<" junk? "<<tj.AlgMod[kJunkTj];
2332  } // TagJunkTj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void tca::TagMuonDirections ( TjStuff tjs,
short  debugWorkID 
)

Definition at line 3078 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::TjStuff::allTraj, tca::Trajectory::CTP, tca::Trajectory::EndPt, tca::Trajectory::ID, kKilled, tca::TjStuff::MuonTag, tca::Trajectory::PDGCode, PrintPos(), tca::Trajectory::Pts, ReverseTraj(), tca::Trajectory::StepDir, and tca::Trajectory::WorkID.

Referenced by DotProd(), and tca::TrajClusterAlg::RunTrajClusterAlg().

3079  {
3080  // Determine muon directions delta-ray proximity to muon trajectories
3081 
3082  if(tjs.MuonTag[0] < 0) return;
3083 
3084  unsigned short minLen = tjs.MuonTag[3];
3085 
3086  for(unsigned short itj = 0; itj < tjs.allTraj.size(); ++itj) {
3087  Trajectory& muTj = tjs.allTraj[itj];
3088  if(muTj.AlgMod[kKilled]) continue;
3089  bool prt = (debugWorkID < 0 && muTj.WorkID == debugWorkID);
3090  if(prt) {
3091  mf::LogVerbatim("TC")<<"TagMuonDirection: Muon "<<muTj.CTP<<" "<<PrintPos(tjs, muTj.Pts[muTj.EndPt[0]])<<"-"<<PrintPos(tjs, muTj.Pts[muTj.EndPt[1]]);
3092  }
3093  if(muTj.PDGCode != 13) continue;
3094  // look for delta ray trajectories and count the number of times that
3095  unsigned short nPos = 0;
3096  unsigned short nNeg = 0;
3097  for(auto& dtj : tjs.allTraj) {
3098  if(dtj.AlgMod[kKilled]) continue;
3099  if(dtj.ParentID != muTj.ID) continue;
3100  if(dtj.EndPt[1] - dtj.EndPt[0] > minLen) continue;
3101  if(dtj.StepDir > 0) {
3102  ++nPos;
3103  } else {
3104  ++nNeg;
3105  }
3106  } // dtj
3107  if(nPos == nNeg) continue;
3108  if(nPos > nNeg) {
3109  if(muTj.StepDir < 0) ReverseTraj(tjs, muTj);
3110  } else {
3111  if(muTj.StepDir > 0) ReverseTraj(tjs, muTj);
3112  }
3113 // muTj.AlgMod[kSetDir] = true;
3114  } // itj
3115  } // TagMuonDirections
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void ReverseTraj(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:2666
std::string PrintPos(const TjStuff &tjs, const Point2_t &pos)
Definition: Utils.cxx:4744
void tca::TagShowerLike ( std::string  inFcnLabel,
TjStuff tjs,
const CTP_t inCTP 
)

Definition at line 3700 of file TCShower.cxx.

References tca::TjStuff::allTraj, evd::details::begin(), tca::TjStuff::ChargeCuts, evd::details::end(), tca::Trajectory::EndPt, FarEnd(), GetAssns(), tca::Trajectory::ID, kBragg, kKilled, kSetDir, kShowerLike, kShowerTj, MakeVertexObsolete(), NumPtsWithCharge(), PosSep(), tca::Trajectory::Pts, tca::TjStuff::ShowerTag, TrajTrajDOCA(), and tca::TjStuff::vtx.

Referenced by tca::TrajClusterAlg::ReconstructAllTraj().

3701  {
3702  // Tag Tjs as InShower if they have MCSMom < ShowerTag[0] and there are more than
3703  // ShowerTag[6] other Tjs with a separation < ShowerTag[1].
3704 
3705  if(tjs.ShowerTag[0] <= 0) return;
3706 
3707  if(tjs.allTraj.size() > 20000) return;
3708 
3709  // evaluate different cuts
3710  bool newCuts = (tjs.ShowerTag[0] > 2);
3711  float typicalChgRMS = 0.5 * (tjs.ChargeCuts[1] + tjs.ChargeCuts[2]);
3712 
3713  // clear out old tags and make a list of Tjs to consider
3714  std::vector<std::vector<int>> tjLists;
3715  std::vector<int> tjids;
3716  for(auto& tj : tjs.allTraj) {
3717  if(tj.CTP != inCTP) continue;
3718  if(tj.AlgMod[kKilled]) continue;
3719  tj.AlgMod[kShowerLike] = false;
3720  if(tj.AlgMod[kShowerTj]) continue;
3721  // ignore Tjs with Bragg peaks
3722  bool skipit = false;
3723  for(unsigned short end = 0; end < 2; ++end) if(tj.StopFlag[end][kBragg]) skipit = true;
3724  if(skipit) continue;
3725  short npwc = NumPtsWithCharge(tjs, tj, false);
3726  if(newCuts) {
3727  // evaluate different cuts
3728  // Don't expect any (primary) electron to be reconstructed as a single trajectory for
3729  // more than ~2 radiation lengths ~ 30 cm for uB ~ 100 wires
3730  if(npwc > 100) continue;
3731  // allow short Tjs.
3732  if(npwc > 5) {
3733  // Increase the MCSMom cut if the Tj is long and the charge RMS is high to reduce sensitivity
3734  // to the fcl configuration. A primary electron may be reconstructed as one long Tj with large
3735  // charge rms and possibly high MCSMom or as several nearby shorter Tjs with lower charge rms
3736  float momCut = tjs.ShowerTag[1];
3737  if(tj.ChgRMS > typicalChgRMS) momCut *= tj.ChgRMS / typicalChgRMS;
3738  if(tj.MCSMom > momCut) continue;
3739  }
3740  } else {
3741  if(npwc < 3) continue;
3742  if(npwc > 4 && tj.MCSMom > tjs.ShowerTag[1]) continue;
3743  }
3744  tjids.push_back(tj.ID);
3745  } // tj
3746 
3747  if(tjids.size() < 2) return;
3748 
3749  for(unsigned short it1 = 0; it1 < tjids.size() - 1; ++it1) {
3750  Trajectory& tj1 = tjs.allTraj[tjids[it1] - 1];
3751  float len1 = PosSep(tj1.Pts[tj1.EndPt[1]].Pos, tj1.Pts[tj1.EndPt[0]].Pos);
3752  for(unsigned short it2 = it1 + 1; it2 < tjids.size(); ++it2) {
3753  Trajectory& tj2 = tjs.allTraj[tjids[it2] - 1];
3754  unsigned short ipt1, ipt2;
3755  float doca = tjs.ShowerTag[2];
3756  // Find the separation between Tjs without considering dead wires
3757  TrajTrajDOCA(tjs, tj1, tj2, ipt1, ipt2, doca, false);
3758  if(doca == tjs.ShowerTag[2]) continue;
3759  // make tighter cuts for user-defined short Tjs
3760  float len2 = PosSep(tj2.Pts[tj2.EndPt[1]].Pos, tj2.Pts[tj2.EndPt[0]].Pos);
3761  if(!newCuts) {
3762  if(len1 < len2 && len1 < doca) {
3763  if(len1 < doca) continue;
3764  } else {
3765  if(len2 < doca) continue;
3766  }
3767  } // !newCuts
3768  // found a close pair. See if one of these is in an existing cluster of Tjs
3769  bool inlist = false;
3770  for(unsigned short it = 0; it < tjLists.size(); ++it) {
3771  bool tj1InList = (std::find(tjLists[it].begin(), tjLists[it].end(), tj1.ID) != tjLists[it].end());
3772  bool tj2InList = (std::find(tjLists[it].begin(), tjLists[it].end(), tj2.ID) != tjLists[it].end());
3773  if(tj1InList || tj2InList) {
3774  // add the one that is not in the list
3775  if(!tj1InList) tjLists[it].push_back(tj1.ID);
3776  if(!tj2InList) tjLists[it].push_back(tj2.ID);
3777  inlist = true;
3778  break;
3779  }
3780  if(inlist) break;
3781  } // it
3782  // start a new list with this pair?
3783  if(!inlist) {
3784  std::vector<int> newlist(2);
3785  newlist[0] = tj1.ID;
3786  newlist[1] = tj2.ID;
3787  tjLists.push_back(newlist);
3788  }
3789  } // it2
3790  } // it1
3791  if(tjLists.empty()) return;
3792 
3793  // mark them all as ShowerLike Tjs
3794  unsigned short nsh = 0;
3795  for(auto& tjl : tjLists) {
3796  nsh += tjl.size();
3797  for(auto& tjID : tjl) {
3798  auto& tj = tjs.allTraj[tjID - 1];
3799  tj.AlgMod[kShowerLike] = true;
3800  // unset flags
3801  tj.AlgMod[kSetDir] = false;
3802  } // tjid
3803  } // tjl
3804 
3805  // kill vertices with more than 1 shower-like tj that is close to the
3806  // vertex
3807  unsigned short nkill = 0;
3808  for(auto& vx2 : tjs.vtx) {
3809  if(vx2.ID == 0) continue;
3810  if(vx2.CTP != inCTP) continue;
3811  auto TInV2 = GetAssns(tjs, "2V", vx2.ID, "T");
3812  unsigned short nsl = 0;
3813  for(auto tid : TInV2) {
3814  auto& tj = tjs.allTraj[tid - 1];
3815  if(tj.AlgMod[kShowerLike]) {
3816  unsigned short nearEnd = 1 - FarEnd(tjs, tj, vx2.Pos);
3817  if(PosSep(tj.Pts[tj.EndPt[nearEnd]].Pos, vx2.Pos) < 6) ++nsl;
3818  }
3819  } // tid
3820  if(nsl < 2) continue;
3821  MakeVertexObsolete(tjs, vx2, true);
3822  ++nkill;
3823  } // vx2
3824  if(tjs.ShowerTag[12] >= 0) mf::LogVerbatim("TC")<<"TagShowerLike tagged "<<nsh<<" Tjs and killed "<<nkill<<" vertices in CTP "<<inCTP;
3825 
3826  } // TagShowerLike
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
unsigned short FarEnd(const TjStuff &tjs, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:2936
bool MakeVertexObsolete(TjStuff &tjs, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:2917
std::vector< evd::details::RawDigitInfo_t >::const_iterator begin(RawDigitCacheDataClass const &cache)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
unsigned short NumPtsWithCharge(const TjStuff &tjs, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1738
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool TrajTrajDOCA(const TjStuff &tjs, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2046
std::vector< int > GetAssns(const TjStuff &tjs, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4079
void tca::TjDeltaRMS ( TjStuff tjs,
Trajectory tj,
unsigned short  firstPt,
unsigned short  lastPt,
double &  rms,
unsigned short &  cnt 
)

Definition at line 2951 of file Utils.cxx.

References tca::Trajectory::EndPt, tca::TrajPoint::HitPos, MakeBareTrajPoint(), NearestPtWithChg(), PointTrajDOCA2(), tca::TrajPoint::Pos, tca::Trajectory::Pts, and tmp.

Referenced by DotProd(), and MCSThetaRMS().

2952  {
2953  // returns the rms scatter of points around a line formed by the firstPt and lastPt of the trajectory
2954 
2955  rms = -1;
2956  if(firstPt < tj.EndPt[0]) return;
2957  if(lastPt > tj.EndPt[1]) return;
2958 
2959  firstPt = NearestPtWithChg(tjs, tj, firstPt);
2960  lastPt = NearestPtWithChg(tjs, tj, lastPt);
2961  if(firstPt >= lastPt) return;
2962 
2963  TrajPoint tmp;
2964  // make a bare trajectory point to define a line between firstPt and lastPt.
2965  // Use the position of the hits at these points
2966  TrajPoint firstTP = tj.Pts[firstPt];
2967  firstTP.Pos = firstTP.HitPos;
2968  TrajPoint lastTP = tj.Pts[lastPt];
2969  lastTP.Pos = lastTP.HitPos;
2970  if(!MakeBareTrajPoint(tjs, firstTP, lastTP, tmp)) return;
2971  // sum up the deviations^2
2972  double dsum = 0;
2973  cnt = 0;
2974  for(unsigned short ipt = firstPt + 1; ipt < lastPt; ++ipt) {
2975  if(tj.Pts[ipt].Chg == 0) continue;
2976  dsum += PointTrajDOCA2(tjs, tj.Pts[ipt].HitPos[0], tj.Pts[ipt].HitPos[1], tmp);
2977  ++cnt;
2978  } // ipt
2979  if(cnt < 2) return;
2980  rms = sqrt(dsum / (double)cnt);
2981 
2982  } // TjDeltaRMS
unsigned short NearestPtWithChg(TjStuff &tjs, Trajectory &tj, unsigned short thePt)
Definition: Utils.cxx:2889
Float_t tmp
Definition: plot.C:37
bool MakeBareTrajPoint(const TjStuff &tjs, const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
Definition: Utils.cxx:3536
float PointTrajDOCA2(TjStuff const &tjs, float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2153
float tca::TjDirFOM ( const TjStuff tjs,
const Trajectory tj,
bool  prt 
)

Definition at line 906 of file Utils.cxx.

References tca::Trajectory::AlgMod, B, tca::Trajectory::EndPt, tca::Trajectory::ID, kEnvOverlap, kKilled, geo::origin(), PosSep(), PrintPos(), tca::Trajectory::Pts, w, x, and y.

Referenced by StoreTraj().

907  {
908  // Calculate a FOM for the tj to be going from EndPt[0] -> EndPt[1] (FOM = 1)
909  // or EndPt[1] -> EndPt[0] (FOM = -1) by finding the overall charge slope, weighted
910  // by the presence of nearby InShower Tjs
911  if(tj.AlgMod[kKilled]) return 0;
912  if(tj.EndPt[1] - tj.EndPt[0] < 8) return 0;
913 
914  std::vector<double> x, y;
915  Point2_t origin = tj.Pts[tj.EndPt[0]].HitPos;
916  std::vector<double> w, q;
917 
918  unsigned short firstPt = tj.EndPt[0] + 2;
919  unsigned short lastPt = tj.EndPt[1] - 2;
920  if(lastPt < firstPt + 3) return 0;
921  // don't include end points
922  for(unsigned short ipt = firstPt; ipt <= lastPt; ++ipt) {
923  auto& tp = tj.Pts[ipt];
924  if(tp.Chg <= 0) continue;
925  // only consider points that don't overlap with other tjs
926  if(tp.Environment[kEnvOverlap]) continue;
927  double sep = PosSep(tp.Pos, origin);
928  x.push_back(sep);
929  y.push_back((double)tp.Chg);
930  double wght = 0.2 * tp.Chg;
931  w.push_back(wght * wght);
932  } // tp
933  if(w.size() < 3) return 0;
934 
935  double sum = 0.;
936  double sumx = 0.;
937  double sumy = 0.;
938  double sumxy = 0.;
939  double sumx2 = 0.;
940  double sumy2 = 0.;
941 
942  // weight by the charge ratio and accumulate sums
943  double wght;
944  for(unsigned short ipt = 0; ipt < x.size(); ++ipt) {
945  wght = 1 / w[ipt];
946  sum += wght;
947  sumx += wght * x[ipt];
948  sumy += wght * y[ipt];
949  sumx2 += wght * x[ipt] * x[ipt];
950  sumy2 += wght * y[ipt] * y[ipt];
951  sumxy += wght * x[ipt] * y[ipt];
952  }
953  // calculate coefficients and std dev
954  double delta = sum * sumx2 - sumx * sumx;
955  if(delta == 0) return 0;
956  // A is the intercept
957  double A = (sumx2 * sumy - sumx * sumxy) / delta;
958  // B is the slope
959  double B = (sumxy * sum - sumx * sumy) / delta;
960 
961  // Calculate the FOM
962  double ndof = x.size() - 2;
963  double varnce = (sumy2 + A*A*sum + B*B*sumx2 - 2 * (A*sumy + B*sumxy - A*B*sumx)) / ndof;
964  if(varnce <= 0) return 0;
965  double BErr = sqrt(varnce * sum / delta);
966  // scale the error so that the significance is +/-1 when the slope is 3 * error
967  // Note that the error is correct only if the average Chi/DOF = 1 which is probably not the case
968  float slopeSig = B / (3 * BErr);
969  if(slopeSig > 1) slopeSig = 1;
970  if(slopeSig < -1) slopeSig = -1;
971  // rescale it to be in the range of 0 - 1
972  slopeSig = (1 + slopeSig) / 2;
973 
974  if(prt) {
975  mf::LogVerbatim myprt("TC");
976  myprt<<"TjDir: T"<<tj.ID<<" slope "<<std::fixed<<std::setprecision(1)<<B<<" error "<<BErr<<" DirFOM "<<slopeSig;
977  myprt<<" using points from "<<PrintPos(tjs, tj.Pts[firstPt])<<" "<<PrintPos(tjs, tj.Pts[lastPt]);
978  } // prt
979  return slopeSig;
980 
981  } // TjDirFOM
Float_t x
Definition: compare.C:6
float PosSep(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2220
Float_t y
Definition: compare.C:6
Int_t B
Definition: plot.C:25
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
std::string PrintPos(const TjStuff &tjs, const Point2_t &pos)
Definition: Utils.cxx:4744
Float_t w
Definition: plot.C:23
constexpr Point origin()
Returns a origin position with a point of the specified type.
Definition: geo_vectors.h:230
float tca::TPHitsRMSTick ( TjStuff tjs,
TrajPoint tp,
HitStatus_t  hitRequest 
)

Definition at line 3582 of file Utils.cxx.

References tca::TjStuff::fHits, tca::TrajPoint::Hits, kAllHits, kUnusedHits, kUsedHits, and tca::TrajPoint::UseHit.

Referenced by DotProd(), tca::TrajClusterAlg::FindUseHits(), and TPHitsRMSTime().

3583  {
3584  // Estimate the RMS of all hits associated with a trajectory point
3585  // without a lot of calculation
3586  if(tp.Hits.empty()) return 0;
3587  float minVal = 9999;
3588  float maxVal = 0;
3589  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3590  bool useit = (hitRequest == kAllHits);
3591  if(hitRequest == kUsedHits && tp.UseHit[ii]) useit = true;
3592  if(hitRequest == kUnusedHits && !tp.UseHit[ii]) useit = true;
3593  if(!useit) continue;
3594  unsigned int iht = tp.Hits[ii];
3595  float cv = tjs.fHits[iht].PeakTime;
3596  float rms = tjs.fHits[iht].RMS;
3597  float arg = cv - rms;
3598  if(arg < minVal) minVal = arg;
3599  arg = cv + rms;
3600  if(arg > maxVal) maxVal = arg;
3601  } // ii
3602  if(maxVal == 0) return 0;
3603  return (maxVal - minVal) / 2;
3604  } // TPHitsRMSTick
float tca::TPHitsRMSTime ( TjStuff tjs,
TrajPoint tp,
HitStatus_t  hitRequest 
)

Definition at line 3576 of file Utils.cxx.

References TPHitsRMSTick(), and tca::TjStuff::UnitsPerTick.

Referenced by DotProd(), and FillmAllTraj().

3577  {
3578  return tjs.UnitsPerTick * TPHitsRMSTick(tjs, tp, hitRequest);
3579  } // TPHitsRMSTime
float TPHitsRMSTick(TjStuff &tjs, TrajPoint &tp, HitStatus_t hitRequest)
Definition: Utils.cxx:3582
unsigned short tca::TPNearVertex ( TjStuff tjs,
const TrajPoint tp 
)

Definition at line 1637 of file TCVertex.cxx.

References tca::TrajPoint::CTP, tca::TrajPoint::Pos, and tca::TjStuff::vtx.

Referenced by tca::TrajClusterAlg::StepCrawl().

1638  {
1639  // Returns the index of a vertex if tp is nearby
1640  for(unsigned short ivx = 0; ivx < tjs.vtx.size(); ++ivx) {
1641  if(tjs.vtx[ivx].ID == 0) continue;
1642  if(tjs.vtx[ivx].CTP != tp.CTP) continue;
1643  if(std::abs(tjs.vtx[ivx].Pos[0] - tp.Pos[0]) > 1.2) continue;
1644  if(std::abs(tjs.vtx[ivx].Pos[1] - tp.Pos[1]) > 1.2) continue;
1645  return ivx;
1646  } // ivx
1647  return USHRT_MAX;
1648  } // TPNearVertex
float tca::TpSumHitChg ( TjStuff tjs,
TrajPoint const &  tp 
)

Definition at line 1678 of file Utils.cxx.

References tca::TjStuff::fHits, tca::TrajPoint::Hits, and tca::TrajPoint::UseHit.

Referenced by tca::TrajClusterAlg::SplitHiChgHits(), and VtxHitsSwap().

1678  {
1679  float totchg = 0;
1680  for (size_t i = 0; i<tp.Hits.size(); ++i){
1681  if (!tp.UseHit[i]) continue;
1682  totchg += tjs.fHits[tp.Hits[i]].Integral;
1683  }
1684  return totchg;
1685  } // TpSumHitChg
bool tca::TrajClosestApproach ( Trajectory const &  tj,
float  x,
float  y,
unsigned short &  closePt,
float &  DOCA 
)

Definition at line 2244 of file Utils.cxx.

References tca::Trajectory::EndPt, tca::Trajectory::Pts, x, and y.

Referenced by AttachTrajToVertex(), CompatibleMerge(), Find2DVertices(), FindHammerVertices2(), and SplitTrajCrossingVertices().

2245  {
2246  // find the closest approach between a trajectory tj and a point (x,y). Returns
2247  // the index of the closest trajectory point and the distance. Returns false if none
2248  // of the points on the tj are within DOCA
2249 
2250  float close2 = DOCA * DOCA;
2251  closePt = 0;
2252  bool foundClose = false;
2253 
2254  for(unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1] + 1; ++ipt) {
2255  if(tj.Pts[ipt].Chg == 0) continue;
2256  float dx = tj.Pts[ipt].Pos[0] - x;
2257  if(std::abs(dx) > DOCA) continue;
2258  float dy = tj.Pts[ipt].Pos[1] - y;
2259  if(std::abs(dy) > DOCA) continue;
2260  float sep2 = dx * dx + dy * dy;
2261  if(sep2 < close2) {
2262  close2 = sep2;
2263  closePt = ipt;
2264  foundClose = true;
2265  }
2266  } // ipt
2267 
2268  DOCA = sqrt(close2);
2269  return foundClose;
2270 
2271  } // TrajClosestApproach
Float_t x
Definition: compare.C:6
Float_t y
Definition: compare.C:6
bool tca::TrajHitsOK ( TjStuff tjs,
const std::vector< unsigned int > &  iHitsInMultiplet,
const std::vector< unsigned int > &  jHitsInMultiplet 
)

Definition at line 1563 of file Utils.cxx.

References tca::TjStuff::fHits, HitsPosTick(), and kAllHits.

Referenced by tca::TrajClusterAlg::FindJunkTraj(), and tca::TrajClusterAlg::ReconstructAllTraj().

1564  {
1565  // Hits (assume to be on adjacent wires have an acceptable signal overlap
1566 
1567  if(iHitsInMultiplet.empty() || jHitsInMultiplet.empty()) return false;
1568 
1569  float sum;
1570  float cvI = HitsPosTick(tjs, iHitsInMultiplet, sum, kAllHits);
1571  float minI = 1E6;
1572  float maxI = 0;
1573  for(auto& iht : iHitsInMultiplet) {
1574  float cv = tjs.fHits[iht].PeakTime;
1575  float rms = tjs.fHits[iht].RMS;
1576  float arg = cv - 3 * rms;
1577  if(arg < minI) minI = arg;
1578  arg = cv + 3 * rms;
1579  if(arg > maxI) maxI = arg;
1580  }
1581 
1582  float cvJ = HitsPosTick(tjs, jHitsInMultiplet, sum, kAllHits);
1583  float minJ = 1E6;
1584  float maxJ = 0;
1585  for(auto& jht : jHitsInMultiplet) {
1586  float cv = tjs.fHits[jht].PeakTime;
1587  float rms = tjs.fHits[jht].RMS;
1588  float arg = cv - 3 * rms;
1589  if(arg < minJ) minJ = arg;
1590  arg = cv + 3 * rms;
1591  if(arg > maxJ) maxJ = arg;
1592  }
1593 
1594  if(cvI < cvJ) {
1595  if(maxI > minJ) return true;
1596  } else {
1597  if(minI < maxJ) return true;
1598  }
1599  return false;
1600  } // TrajHitsOK
float HitsPosTick(TjStuff &tjs, const std::vector< unsigned int > &hitsInMultiplet, float &sum, HitStatus_t hitRequest)
Definition: Utils.cxx:3645
bool tca::TrajHitsOK ( TjStuff tjs,
const unsigned int  iht,
const unsigned int  jht 
)

Definition at line 1603 of file Utils.cxx.

References tca::TCHit::ArtPtr, tca::TjStuff::fHits, tca::TCHit::PeakTime, tca::TCHit::RMS, geo::WireID::Wire, and recob::Hit::WireID().

1604  {
1605  // ensure that two adjacent hits have an acceptable overlap
1606  if(iht > tjs.fHits.size() - 1) return false;
1607  if(jht > tjs.fHits.size() - 1) return false;
1608  // require that they be on adjacent wires
1609  TCHit& ihit = tjs.fHits[iht];
1610  TCHit& jhit = tjs.fHits[jht];
1611  int iwire = ihit.ArtPtr->WireID().Wire;
1612  int jwire = jhit.ArtPtr->WireID().Wire;
1613  if(std::abs(iwire - jwire) > 1) return false;
1614  if(ihit.PeakTime > jhit.PeakTime) {
1615  float minISignal = ihit.PeakTime - 3 * ihit.RMS;
1616  float maxJSignal = jhit.PeakTime + 3 * ihit.RMS;
1617  if(maxJSignal > minISignal) return true;
1618  } else {
1619  float maxISignal = ihit.PeakTime + 3 * ihit.RMS;
1620  float minJSignal = jhit.PeakTime - 3 * ihit.RMS;
1621  if(minJSignal > maxISignal) return true;
1622  }
1623  return false;
1624  } // TrajHitsOK
void tca::TrajIntersection ( TrajPoint const &  tp1,
TrajPoint const &  tp2,
Point2_t pos 
)

Definition at line 2166 of file Utils.cxx.

References TrajIntersection().

Referenced by tca::TrajClusterAlg::EndMerge(), Find2DVertices(), FindHammerVertices2(), and FitVertex().

2167  {
2168  TrajIntersection(tp1, tp2, pos[0], pos[1]);
2169  } // TrajIntersection
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, float &x, float &y)
Definition: Utils.cxx:2171
void tca::TrajIntersection ( TrajPoint const &  tp1,
TrajPoint const &  tp2,
float &  x,
float &  y 
)

Definition at line 2171 of file Utils.cxx.

References tca::TrajPoint::Dir, tca::TrajPoint::Pos, and s.

Referenced by TrajIntersection().

2172  {
2173  // returns the intersection position, (x,y), of two trajectory points
2174 
2175  x = -9999; y = -9999;
2176 
2177  double arg1 = tp1.Pos[0] * tp1.Dir[1] - tp1.Pos[1] * tp1.Dir[0];
2178  double arg2 = tp2.Pos[0] * tp1.Dir[1] - tp2.Pos[1] * tp1.Dir[0];
2179  double arg3 = tp2.Dir[0] * tp1.Dir[1] - tp2.Dir[1] * tp1.Dir[0];
2180  if(arg3 == 0) return;
2181  double s = (arg1 - arg2) / arg3;
2182 
2183  x = (float)(tp2.Pos[0] + s * tp2.Dir[0]);
2184  y = (float)(tp2.Pos[1] + s * tp2.Dir[1]);
2185 
2186  } // TrajIntersection
Float_t x
Definition: compare.C:6
Float_t s
Definition: plot.C:23
Float_t y
Definition: compare.C:6
bool tca::TrajIsClean ( TjStuff tjs,
Trajectory tj,
bool  prt 
)

Definition at line 2814 of file Utils.cxx.

References tca::Trajectory::EndPt, tca::TrajPoint::Hits, tca::Trajectory::Pts, and tca::TrajPoint::UseHit.

Referenced by DotProd(), and tca::TrajClusterAlg::UpdateTraj().

2815  {
2816  // Returns true if the trajectory has low hit multiplicity and is in a
2817  // clean environment
2818  unsigned short nUsed = 0;
2819  unsigned short nTotHits = 0;
2820  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2821  TrajPoint& tp = tj.Pts[ipt];
2822  nTotHits += tp.Hits.size();
2823  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2824  if(tp.UseHit[ii]) ++nUsed;
2825  } // ii
2826  } // ipt
2827  if(nTotHits == 0) return false;
2828  float fracUsed = (float)nUsed / (float)nTotHits;
2829  if(prt) mf::LogVerbatim("TC")<<"TrajIsClean: nTotHits "<<nTotHits<<" nUsed "<<nUsed<<" fracUsed "<<fracUsed;
2830 
2831  if(fracUsed > 0.9) return true;
2832  return false;
2833 
2834  } // TrajIsClean
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float tca::TrajLength ( Trajectory tj)

Definition at line 2204 of file Utils.cxx.

References tca::Trajectory::EndPt, and tca::Trajectory::Pts.

Referenced by AttachTrajToVertex(), tca::TrajClusterAlg::EndMerge(), Find2DVertices(), MakeJunkVertices(), and PDGCodeVote().

2205  {
2206  float len = 0, dx, dy;
2207  unsigned short ipt;
2208  unsigned short prevPt = tj.EndPt[0];
2209  for(ipt = tj.EndPt[0] + 1; ipt < tj.EndPt[1] + 1; ++ipt) {
2210  if(tj.Pts[ipt].Chg == 0) continue;
2211  dx = tj.Pts[ipt].Pos[0] - tj.Pts[prevPt].Pos[0];
2212  dy = tj.Pts[ipt].Pos[1] - tj.Pts[prevPt].Pos[1];
2213  len += sqrt(dx * dx + dy * dy);
2214  prevPt = ipt;
2215  }
2216  return len;
2217  } // TrajLength
float tca::TrajPointSeparation ( TrajPoint tp1,
TrajPoint tp2 
)

Definition at line 2235 of file Utils.cxx.

References tca::TrajPoint::Pos.

Referenced by tca::TrajClusterAlg::EndMerge(), tca::TrajClusterAlg::GottaKink(), tca::TrajClusterAlg::MakeJunkTraj(), tca::TrajClusterAlg::MaskTrajEndPoints(), MCSMom(), MCSThetaRMS(), and tca::TrajClusterAlg::StepCrawl().

2236  {
2237  // Returns the separation distance between two trajectory points
2238  float dx = tp1.Pos[0] - tp2.Pos[0];
2239  float dy = tp1.Pos[1] - tp2.Pos[1];
2240  return sqrt(dx * dx + dy * dy);
2241  } // TrajPointSeparation
void tca::TrajPointTrajDOCA ( TjStuff tjs,
TrajPoint const &  tp,
Trajectory const &  tj,
unsigned short &  closePt,
float &  minSep 
)

Definition at line 2026 of file Utils.cxx.

References tca::Trajectory::EndPt, tca::TrajPoint::Pos, and tca::Trajectory::Pts.

Referenced by CompleteIncomplete3DVertices(), FindHammerVertices(), FindHammerVertices2(), tca::TrajClusterAlg::FindMissedVxTjs(), and MergeAndStore().

2027  {
2028  // Finds the point, ipt, on trajectory tj that is closest to trajpoint tp
2029  float best = minSep * minSep;
2030  closePt = USHRT_MAX;
2031  float dw, dt, dp2;
2032  unsigned short ipt;
2033  for(ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2034  dw = tj.Pts[ipt].Pos[0] - tp.Pos[0];
2035  dt = tj.Pts[ipt].Pos[1] - tp.Pos[1];
2036  dp2 = dw * dw + dt * dt;
2037  if(dp2 < best) {
2038  best = dp2;
2039  closePt = ipt;
2040  }
2041  } // ipt
2042  minSep = sqrt(best);
2043  } // TrajPointTrajDOCA
float tca::TrajPointVertexPull ( TjStuff tjs,
const TrajPoint tp,
const VtxStore vx 
)

Definition at line 1847 of file TCVertex.cxx.

References tca::TrajPoint::AngErr, tca::TrajPoint::Dir, tca::TrajPoint::HitPosErr2, PointTrajDOCA(), tca::VtxStore::Pos, tca::TrajPoint::Pos, tca::VtxStore::PosErr, and PosSep2().

Referenced by AttachTrajToVertex(), and FitVertex().

1848  {
1849  // Calculates the position pull between a trajectory point and a vertex
1850 
1851  // impact parameter between them
1852  double ip = PointTrajDOCA(tjs, vx.Pos[0], vx.Pos[1], tp);
1853  // separation^2
1854  double sep2 = PosSep2(vx.Pos, tp.Pos);
1855 
1856  // Find the projection of the vertex error ellipse in a coordinate system
1857  // along the TP direction
1858  double vxErrW = vx.PosErr[0] * tp.Dir[1];
1859  double vxErrT = vx.PosErr[1] * tp.Dir[0];
1860  double vxErr2 = vxErrW * vxErrW + vxErrT * vxErrT;
1861  // add the TP position error^2
1862  vxErr2 += tp.HitPosErr2;
1863 
1864  // close together so ignore the TP projection error and return
1865  // the pull using the vertex error and TP position error
1866  if(sep2 < 1) return (float)(ip/sqrt(vxErr2));
1867 
1868  double dang = ip / sqrt(sep2);
1869 
1870  // calculate the angle error.
1871  // Start with the vertex error^2
1872  double angErr = vxErr2 / sep2;
1873  // Add the TP angle error^2
1874  angErr += tp.AngErr * tp.AngErr;
1875  if(angErr == 0) return 999;
1876  angErr = sqrt(angErr);
1877  return (float)(dang / angErr);
1878 
1879  } // TrajPointVertexPull
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1631
float PointTrajDOCA(TjStuff const &tjs, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2139
bool tca::TrajTrajDOCA ( const TjStuff tjs,
const Trajectory tj1,
const Trajectory tj2,
unsigned short &  ipt1,
unsigned short &  ipt2,
float &  minSep 
)

Definition at line 2046 of file Utils.cxx.

References TrajTrajDOCA().

Referenced by tca::TrajClusterAlg::EndMerge(), Find2DVertices(), FindCots(), FindNearbyTjs(), InShowerProb(), and TagShowerLike().

2047  {
2048  return TrajTrajDOCA(tjs, tj1, tj2, ipt1, ipt2, minSep, false);
2049  } // TrajTrajDOCA
bool TrajTrajDOCA(const TjStuff &tjs, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep, bool considerDeadWires)
Definition: Utils.cxx:2052
bool tca::TrajTrajDOCA ( const TjStuff tjs,
const Trajectory tj1,
const Trajectory tj2,
unsigned short &  ipt1,
unsigned short &  ipt2,
float &  minSep,
bool  considerDeadWires 
)

Definition at line 2052 of file Utils.cxx.

References DeadWireCount(), tca::Trajectory::EndPt, and tca::Trajectory::Pts.

Referenced by DefineTjParents(), TagDeltaRays(), and TrajTrajDOCA().

2053  {
2054  // Find the Distance Of Closest Approach between two trajectories less than minSep
2055  // start with some rough cuts to minimize the use of the more expensive checking. This
2056  // function returns true if the DOCA is less than minSep
2057  for(unsigned short iwt = 0; iwt < 2; ++iwt) {
2058  // Apply box cuts on the ends of the trajectories
2059  // The Lo/Hi wire(time) at each end of tj1
2060  float wt0 = tj1.Pts[tj1.EndPt[0]].Pos[iwt];
2061  float wt1 = tj1.Pts[tj1.EndPt[1]].Pos[iwt];
2062  float lowt1 = wt0;
2063  float hiwt1 = wt1;
2064  if(wt1 < lowt1) {
2065  lowt1 = wt1;
2066  hiwt1 = wt0;
2067  }
2068  // The Lo/Hi wire(time) at each end of tj2
2069  wt0 = tj2.Pts[tj2.EndPt[0]].Pos[iwt];
2070  wt1 = tj2.Pts[tj2.EndPt[1]].Pos[iwt];
2071  float lowt2 = wt0;
2072  float hiwt2 = wt1;
2073  if(wt1 < lowt2) {
2074  lowt2 = wt1;
2075  hiwt2 = wt0;
2076  }
2077  // Check for this configuration
2078  // loWire1.......hiWire1 minSep loWire2....hiWire2
2079  // loTime1.......hiTime1 minSep loTime2....hiTime2
2080  if(lowt2 > hiwt1 + minSep) return false;
2081  // and the other
2082  if(lowt1 > hiwt2 + minSep) return false;
2083  } // iwt
2084 
2085  float best = minSep * minSep;
2086  ipt1 = 0; ipt2 = 0;
2087  float dwc = 0;
2088  bool isClose = false;
2089  for(unsigned short i1 = tj1.EndPt[0]; i1 < tj1.EndPt[1] + 1; ++i1) {
2090  for(unsigned short i2 = tj2.EndPt[0]; i2 < tj2.EndPt[1] + 1; ++i2) {
2091  if(considerDeadWires) dwc = DeadWireCount(tjs, tj1.Pts[i1], tj2.Pts[i2]);
2092  float dw = tj1.Pts[i1].Pos[0] - tj2.Pts[i2].Pos[0] - dwc;
2093  if(std::abs(dw) > minSep) continue;
2094  float dt = tj1.Pts[i1].Pos[1] - tj2.Pts[i2].Pos[1];
2095  if(std::abs(dt) > minSep) continue;
2096  float dp2 = dw * dw + dt * dt;
2097  if(dp2 < best) {
2098  best = dp2;
2099  ipt1 = i1;
2100  ipt2 = i2;
2101  isClose = true;
2102  }
2103  } // i2
2104  } // i1
2105  minSep = sqrt(best);
2106  return isClose;
2107  } // TrajTrajDOCA
float DeadWireCount(const TjStuff &tjs, const float &inWirePos1, const float &inWirePos2, CTP_t tCTP)
Definition: Utils.cxx:1762
bool tca::TransferTjHits ( TjStuff tjs,
bool  prt 
)

Definition at line 4383 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::TjStuff::cots, tca::TjStuff::fHits, tca::Trajectory::ID, kKilled, kShowerTj, kUsedHits, tca::Trajectory::Pts, PutTrajHitsInVector(), and ss.

Referenced by Finish3DShowers().

4384  {
4385  // Transfer InShower hits in all TPCs and planes to the shower Tjs
4386 
4387  bool newShowers = false;
4388  for(auto& ss : tjs.cots) {
4389  if(ss.ID == 0) continue;
4390  if(ss.ShowerTjID == 0) continue;
4391  // Tp 1 of stj will get all of the shower hits
4392  Trajectory& stj = tjs.allTraj[ss.ShowerTjID - 1];
4393  if(!stj.Pts[1].Hits.empty()) {
4394  std::cout<<"TTjH: ShowerTj T"<<stj.ID<<" already has "<<stj.Pts[1].Hits.size()<<" hits\n";
4395  continue;
4396  }
4397  // Note that UseHit is not used since the size is limited to 16
4398  for(auto& tjID : ss.TjIDs) {
4399  unsigned short itj = tjID - 1;
4400  if(tjs.allTraj[itj].AlgMod[kShowerTj]) {
4401  std::cout<<"TTjH: Coding error. T"<<tjID<<" is a ShowerTj but is in TjIDs\n";
4402  continue;
4403  }
4404  if(tjs.allTraj[itj].SSID <= 0) {
4405  std::cout<<"TTjH: Coding error. Trying to transfer T"<<tjID<<" hits but it isn't an InShower Tj\n";
4406  continue;
4407  }
4408  auto thits = PutTrajHitsInVector(tjs.allTraj[itj], kUsedHits);
4409  // associate all hits with the charge center TP
4410  stj.Pts[1].Hits.insert(stj.Pts[1].Hits.end(), thits.begin(), thits.end());
4411  // kill Tjs that are in showers
4412  tjs.allTraj[itj].AlgMod[kKilled] = true;
4413  } // tjID
4414  // re-assign the hit -> stj association
4415  for(auto& iht : stj.Pts[1].Hits) tjs.fHits[iht].InTraj = stj.ID;
4416  newShowers = true;
4417  } // ss
4418 
4419  if(prt) mf::LogVerbatim("TC")<<"TTJH: success? "<<newShowers;
4420  return newShowers;
4421  } // TransferTjHits
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< unsigned int > PutTrajHitsInVector(Trajectory const &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2283
Float_t ss
Definition: plot.C:23
void tca::TrimEndPts ( std::string  fcnLabel,
TjStuff tjs,
Trajectory tj,
const std::vector< float > &  fQualityCuts,
bool  prt 
)

Definition at line 1342 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::CTP, DecodeCTP(), tca::Trajectory::EndPt, tca::Trajectory::ID, kTEP, NumPtsWithCharge(), tca::TjStuff::NumWires, geo::PlaneID::Plane, PrintTrajectory(), tca::Trajectory::Pts, SetEndPoints(), tca::Trajectory::StepDir, UnsetUsedHits(), tca::TjStuff::UseAlg, and tca::TjStuff::WireHitRange.

Referenced by tca::TrajClusterAlg::CheckTraj(), tca::TrajClusterAlg::FixTrajBegin(), and tca::TrajClusterAlg::IsGhost().

1343  {
1344  // Trim the hits off the end until there are at least MinPts consecutive hits at the end
1345  // and the fraction of hits on the trajectory exceeds fQualityCuts[0]
1346  // Minimum length requirement accounting for dead wires where - denotes a wire with a point
1347  // and D is a dead wire. Here is an example with minPts = 3
1348  // ---DDDDD--- is OK
1349  // ----DD-DD-- is OK
1350  // ----DDD-D-- is OK
1351  // ----DDDDD-- is not OK
1352 
1353  if(!tjs.UseAlg[kTEP]) return;
1354 
1355  unsigned short npwc = NumPtsWithCharge(tjs, tj, false);
1356  short minPts = fQualityCuts[1];
1357  if(minPts < 1) return;
1358  if(npwc < minPts) return;
1359 
1360  // handle short tjs
1361  if(npwc == minPts + 1) {
1362  unsigned short endPt1 = tj.EndPt[1];
1363  auto& tp = tj.Pts[endPt1];
1364  auto& ptp = tj.Pts[endPt1 - 1];
1365  // remove the last point if the previous point has no charge or if
1366  // it isn't on the next wire
1367  float dwire = std::abs(ptp.Pos[0] - tp.Pos[0]);
1368  if(ptp.Chg == 0 || dwire > 1.1) {
1369  UnsetUsedHits(tjs, tp);
1370  SetEndPoints(tjs, tj);
1371  tj.AlgMod[kTEP] = true;
1372  }
1373  return;
1374  } // short tj
1375 
1376  // find the separation between adjacent points, starting at the end
1377  short lastPt = 0;
1378  for(lastPt = tj.EndPt[1]; lastPt >= minPts; --lastPt) {
1379  // check for an error
1380  if(lastPt == 1) break;
1381  if(tj.Pts[lastPt].Chg == 0) continue;
1382  // number of adjacent points on adjacent wires
1383  unsigned short nadj = 0;
1384  unsigned short npwc = 0;
1385  for(short ipt = lastPt - minPts; ipt < lastPt; ++ipt) {
1386  if(ipt < 2) break;
1387  // the current point
1388  auto& tp = tj.Pts[ipt];
1389  // the previous point
1390  auto& ptp = tj.Pts[ipt - 1];
1391  if(tp.Chg > 0 && ptp.Chg > 0) {
1392  ++npwc;
1393  if(std::abs(tp.Pos[0] - ptp.Pos[0]) < 1.5) ++nadj;
1394  }
1395  } // ipt
1396  float ntpwc = NumPtsWithCharge(tjs, tj, true, tj.EndPt[0], lastPt);
1397  float nwires = std::abs(tj.Pts[tj.EndPt[0]].Pos[0] - tj.Pts[lastPt].Pos[0]) + 1;
1398  float hitFrac = ntpwc / nwires;
1399  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<"-TEP: T"<<tj.ID<<" lastPt "<<lastPt<<" npwc "<<npwc<<" nadj "<<nadj<<" hitFrac "<<hitFrac;
1400  if(hitFrac > fQualityCuts[0] && npwc == minPts && nadj == minPts) break;
1401  } // lastPt
1402 
1403  // trim the last point if it just after a dead wire.
1404  if(tj.Pts[lastPt].Pos[0] > -0.4) {
1405  unsigned int prevWire = std::nearbyint(tj.Pts[lastPt].Pos[0]);
1406  if(tj.StepDir > 0) {
1407  --prevWire;
1408  } else {
1409  ++prevWire;
1410  }
1411  if(prt) {
1412  mf::LogVerbatim("TC")<<fcnLabel<<"-TEP: is prevWire "<<prevWire<<" dead? ";
1413  }
1414  unsigned short plane = DecodeCTP(tj.CTP).Plane;
1415  if(prevWire < tjs.NumWires[plane] && tjs.WireHitRange[plane][prevWire].first == -1) --lastPt;
1416  } // valid Pos[0]
1417 
1418  // Nothing needs to be done
1419  if(lastPt == tj.EndPt[1]) {
1420  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<"-TEPo: Tj is OK";
1421  return;
1422  }
1423 
1424  // clear the points after lastPt
1425  for(unsigned short ipt = lastPt + 1; ipt <= tj.EndPt[1]; ++ipt) UnsetUsedHits(tjs, tj.Pts[ipt]);
1426  SetEndPoints(tjs, tj);
1427  tj.AlgMod[kTEP] = true;
1428  if(prt) {
1429  fcnLabel += "-TEPo";
1430  PrintTrajectory(fcnLabel, tjs, tj, USHRT_MAX);
1431  }
1432 
1433  } // TrimEndPts
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void PrintTrajectory(std::string someText, const TjStuff &tjs, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:4488
unsigned short NumPtsWithCharge(const TjStuff &tjs, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:1746
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
void SetEndPoints(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:2788
void UnsetUsedHits(TjStuff &tjs, TrajPoint &tp)
Definition: Utils.cxx:1082
float tca::TwoTPAngle ( TrajPoint tp1,
TrajPoint tp2 
)

Definition at line 2274 of file Utils.cxx.

References tca::TrajPoint::Pos.

2275  {
2276  // Calculates the angle of a line between two TPs
2277  float dw = tp2.Pos[0] - tp1.Pos[0];
2278  float dt = tp2.Pos[1] - tp1.Pos[1];
2279  return atan2(dw, dt);
2280  } // TwoTPAngle
void tca::UnsetUsedHits ( TjStuff tjs,
TrajPoint tp 
)

Definition at line 1082 of file Utils.cxx.

References tca::TrajPoint::Chg, tca::TjStuff::fHits, tca::TrajPoint::Hits, and tca::TrajPoint::UseHit.

Referenced by tca::TrajClusterAlg::CheckHiMultEndHits(), tca::TrajClusterAlg::CheckHiMultUnusedHits(), tca::TrajClusterAlg::CheckTraj(), ChkChgAsymmetry(), tca::TrajClusterAlg::ChkStopEndPts(), tca::TrajClusterAlg::FillGaps(), tca::TrajClusterAlg::FindSoftKink(), tca::TrajClusterAlg::FixTrajBegin(), tca::TrajClusterAlg::IsGhost(), tca::TrajClusterAlg::MaskBadTPs(), tca::TrajClusterAlg::MaskTrajEndPoints(), TrimEndPts(), tca::TrajClusterAlg::UpdateTraj(), and tca::TrajClusterAlg::UseUnusedHits().

1083  {
1084  // Sets InTraj = 0 and UseHit false for all used hits in tp
1085  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1086  if(tp.UseHit[ii]) {
1087  tjs.fHits[tp.Hits[ii]].InTraj = 0;
1088  tp.UseHit[ii] = false;
1089  } // UseHit
1090  } // ii
1091  tp.Chg = 0;
1092  } // UnsetUsedHits
void tca::UpdateMatchStructs ( TjStuff tjs,
int  oldTj,
int  newTj 
)

Definition at line 16 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, detinfo::DetectorProperties::ConvertTicksToX(), DecodeCTP(), tca::TjStuff::detprop, tca::TjStuff::mallTraj, tca::TjStuff::pfps, and tca::TjStuff::UnitsPerTick.

Referenced by MergeAndStore(), MergePFPTjs(), ReverseTraj(), and SplitTraj().

17  {
18  // Replaces tjid and ipt references in tjs.matchVec and tjs.pfps from
19  // oldTj to newTj. This function is called when Tjs are split or merged
20  // or if a Tj is reversed (in which case oldTj = newTj).
21  // The method used is to match the trajectory point positions
22  if(oldTj <= 0 || oldTj > (int)tjs.allTraj.size()) return;
23  if(newTj <= 0 || newTj > (int)tjs.allTraj.size()) return;
24  if(tjs.mallTraj.empty() && tjs.pfps.empty()) return;
25 
26  // convert from int to unsigned short
27  int oldtjid = oldTj;
28  int newtjid = newTj;
29  auto& ntj = tjs.allTraj[newTj - 1];
30  unsigned short npts = ntj.EndPt[1] - ntj.EndPt[0] + 1;
31  // put the X positions of the new Tj into a vector for matching
32  std::vector<float> xpos(ntj.Pts.size());
33  geo::PlaneID planeID = DecodeCTP(ntj.CTP);
34  for(unsigned short npt = ntj.EndPt[0]; npt <= ntj.EndPt[1]; ++npt) {
35  auto& ntp = ntj.Pts[npt];
36  if(ntp.Chg <= 0) continue;
37  xpos[npt] = tjs.detprop->ConvertTicksToX(ntp.Pos[1]/tjs.UnitsPerTick, planeID);
38  } // npt
39 
40  if(!tjs.mallTraj.empty()) {
41  for(unsigned int ipt = 0; ipt < tjs.mallTraj.size(); ++ipt) {
42  auto& tj2pt = tjs.mallTraj[ipt];
43  if(tj2pt.id > tjs.allTraj.size()) continue;
44  if(tj2pt.id != oldtjid) continue;
45  // Found the old Tj. Now find the point
46  for(unsigned short npt = ntj.EndPt[0]; npt <= ntj.EndPt[1]; ++npt) {
47  auto& ntp = ntj.Pts[npt];
48  if(ntp.Chg <= 0) continue;
49  if(std::nearbyint(ntp.Pos[0]) == tj2pt.wire && xpos[npt] > tj2pt.xlo && xpos[npt] < tj2pt.xhi) {
50  tj2pt.id = newtjid;
51  tj2pt.ipt = npt;
52  tj2pt.npts = npts;
53  break;
54  } // points match
55  } // npt
56  } // ipt
57  } // !tjs.mallTraj.empty()
58 
59  // Update pfp space points
60  if(!tjs.pfps.empty()) {
61  for(auto& pfp : tjs.pfps) {
62  for(auto& tp3 : pfp.Tp3s) {
63  // check each of the Tj2Pts associated with this space point
64  for(auto& tj2pt : tp3.Tj2Pts) {
65  if(tj2pt.id > tjs.allTraj.size()) continue;
66  if(tj2pt.id != oldtjid) continue;
67  // look for the corresponding point (wire) on the new Tj
68  for(unsigned short npt = ntj.EndPt[0]; npt <= ntj.EndPt[1]; ++npt) {
69  auto& ntp = ntj.Pts[npt];
70  if(std::nearbyint(ntp.Pos[0]) == tj2pt.wire && xpos[npt] > tj2pt.xlo && xpos[npt] < tj2pt.xhi) {
71  tj2pt.id = newtjid;
72  tj2pt.ipt = npt;
73  tj2pt.npts = npts;
74  break;
75  }
76  } // npt
77  } // tj2pt
78  } // tp3
79  } // pfp
80  } // pfps exists
81 
82  } // UpdateMatchStructs
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
bool tca::UpdateShower ( std::string  inFcnLabel,
TjStuff tjs,
ShowerStruct ss,
bool  prt 
)

Definition at line 1104 of file TCShower.cxx.

References tca::TjStuff::allTraj, AnalyzeRotPos(), tca::ShowerStruct::Angle, tca::ShowerStruct::AspectRatio, B, tca::ShowerStruct::Cheat, tca::ShowerPoint::Chg, ChgToMeV(), tca::ShowerStruct::CTP, DefineEnvelope(), tca::ShowerStruct::DirectionFOM, tca::ShowerStruct::Energy, FarEnd(), tca::TjStuff::fHits, tca::ShowerPoint::HitIndex, tca::TrajPoint::Hits, tca::ShowerStruct::ID, kShowerTj, lessThan(), tca::ShowerStruct::NeedsUpdate, tca::ShowerStruct::ParentID, PointDirection(), tca::ShowerPoint::Pos, PosSep2(), PrintPos(), ReverseShower(), tca::ShowerStruct::ShowerTjID, tca::ShowerStruct::ShPts, ss, tca::ShowerPoint::TID, tca::ShowerStruct::TjIDs, tca::TjStuff::UnitsPerTick, tca::TrajPoint::UseHit, and xx.

Referenced by tca::MCParticleListUtils::MakeCheatShower().

1105  {
1106  // This is intended to be a single function replacement for FCC, FA, USWP, etc. The calling
1107  // function should have set NeedsUpdate true. A complete re-build is done if the ShPts vector
1108  // is empty. This is only required if a tj is removed from the shower. When adding a tj
1109  // to the shower the AddTj function appends the tj points to ShPts but doesn't fill
1110  // the ShPts RotPos values.
1111  // This function doesn't alter or check associations btw showers and tjs.
1112 
1113  if(ss.ID == 0) return false;
1114  if(!ss.Cheat && ss.TjIDs.empty()) return false;
1115  if(ss.ShowerTjID <= 0 || ss.ShowerTjID > (int)tjs.allTraj.size()) return false;
1116  if(ss.ParentID > 0 && ss.ParentID > (int)tjs.allTraj.size()) return false;
1117  auto& stj = tjs.allTraj[ss.ShowerTjID - 1];
1118  if(stj.Pts.size() != 3) return false;
1119 
1120  std::string fcnLabel = inFcnLabel + ".U2S";
1121 
1122  if(!ss.NeedsUpdate && !ss.ShPts.empty()) {
1123 // std::cout<<fcnLabel<<" 2S"<<ss.ID<<" doesn't need an update\n";
1124  return true;
1125  }
1126 
1127  // initialize the variables that will be defined in this function
1128  ss.Energy = 0; // This is just ShowerEnergy(stj.TotChg) and could be deleted
1129  ss.AspectRatio = 10;
1130  // Direction FOM (0 = good). This is a property of the shower shape and is not
1131  // defined by the presence or absence of a parent tj start point
1132  ss.DirectionFOM = 10;
1133  // Total charge of all hits in the shower
1134  stj.TotChg = 0;
1135  for(auto& stp : stj.Pts) {
1136  // Shower start, charge center, and shower end
1137  stp.Pos = {{0.0, 0.0}};
1138  // Charge weighted average of hits this section (TP) along the shower
1139  stp.HitPos = {{0.0, 0.0}};
1140  // Direction from the start to the charge center - same for all TPs
1141  stp.Dir = {{0.0, 0.0}};
1142  // Hit charge in each section
1143  stp.Chg = 0;
1144  // transverse rms of hit positions relative to HitPos in this section
1145  stp.DeltaRMS = 0;
1146  // number of hits in this section
1147  stp.NTPsFit = 0;
1148  } // stp
1149 
1150  if(!ss.Cheat) {
1151  ss.ShPts.clear();
1152  for(auto tjid : ss.TjIDs) {
1153  if(tjid <= 0 || tjid > (int)tjs.allTraj.size()) return false;
1154  auto& tj = tjs.allTraj[tjid - 1];
1155  if(tj.CTP != ss.CTP) return false;
1156  if(tj.AlgMod[kShowerTj]) return false;
1157  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1158  TrajPoint& tp = tj.Pts[ipt];
1159  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1160  if(!tp.UseHit[ii]) continue;
1161  unsigned int iht = tp.Hits[ii];
1162  if(tjs.fHits[iht].Integral <= 0) continue;
1163  ShowerPoint shpt;
1164  shpt.HitIndex = iht;
1165  shpt.TID = tj.ID;
1166  shpt.Chg = tjs.fHits[iht].Integral;
1167  shpt.Pos[0] = tjs.fHits[iht].ArtPtr->WireID().Wire;
1168  shpt.Pos[1] = tjs.fHits[iht].PeakTime * tjs.UnitsPerTick;
1169  ss.ShPts.push_back(shpt);
1170  } // ii
1171  } // ipt
1172  } // tjid
1173  }
1174  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 2S"<<ss.ID<<" nShPts "<<ss.ShPts.size();
1175 
1176  if(ss.ShPts.size() < 3) return false;
1177 
1178  // find the charge center and total charge
1179  auto& stp1 = stj.Pts[1];
1180  for(auto& shpt : ss.ShPts) {
1181  stp1.Pos[0] += shpt.Chg * shpt.Pos[0];
1182  stp1.Pos[1] += shpt.Chg * shpt.Pos[1];
1183  stj.TotChg += shpt.Chg;
1184  } // shpt
1185  if(stj.TotChg <= 0) return false;
1186  stp1.Pos[0] /= stj.TotChg;
1187  stp1.Pos[1] /= stj.TotChg;
1188  ss.Energy = ChgToMeV(stj.TotChg);
1189  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 2S"<<ss.ID<<" Chg ctr "<<PrintPos(tjs, stp1.Pos)<<" Energy "<<(int)ss.Energy<<" MeV";
1190 
1191  // find the direction using the shower parent if one exists
1192  if(ss.ParentID > 0) {
1193  // Set the direction to be the start of the parent to the shower center
1194  auto& ptj = tjs.allTraj[ss.ParentID - 1];
1195  // find the parent end farthest away from the charge center
1196  unsigned short pend = FarEnd(tjs, ptj, stp1.Pos);
1197  auto& ptp = ptj.Pts[ptj.EndPt[pend]];
1198  stp1.Dir = PointDirection(ptp.Pos, stp1.Pos);
1199  stp1.Ang = atan2(stp1.Dir[1], stp1.Dir[0]);
1200  } else {
1201  // find the shower direction using the points
1202  double sum = 0.;
1203  double sumx = 0.;
1204  double sumy = 0.;
1205  double sumxy = 0.;
1206  double sumx2 = 0.;
1207  double sumy2 = 0.;
1208  for(auto& shpt : ss.ShPts) {
1209  sum += shpt.Chg;
1210  double xx = shpt.Pos[0] - stp1.Pos[0];
1211  double yy = shpt.Pos[1] - stp1.Pos[1];
1212  sumx += shpt.Chg * xx;
1213  sumy += shpt.Chg * yy;
1214  sumxy += shpt.Chg * xx * yy;
1215  sumx2 += shpt.Chg * xx * xx;
1216  sumy2 += shpt.Chg * yy * yy;
1217  } // shpt
1218  double delta = sum * sumx2 - sumx * sumx;
1219  if(delta == 0) return false;
1220  // A is the intercept (This should be ~0 )
1221 // double A = (sumx2 * sumy - sumx * sumxy) / delta;
1222  // B is the slope
1223  double B = (sumxy * sum - sumx * sumy) / delta;
1224  stp1.Ang = atan(B);
1225  stp1.Dir[0] = cos(stp1.Ang);
1226  stp1.Dir[1] = sin(stp1.Ang);
1227  } // no shower parent
1228 
1229  // TODO: ss.Angle should be eliminated. The shower tj Ang should be used instead
1230  ss.Angle = stp1.Ang;
1231  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 2S"<<ss.ID<<" dir "<<std::fixed<<std::setprecision(2)<<stp1.Dir[0]<<" "<<stp1.Dir[1]<<" Angle "<<stp1.Ang;
1232  for(unsigned short ipt = 0; ipt < 3; ++ipt) {
1233  if(ipt == 1) continue;
1234  stj.Pts[ipt].Dir = stp1.Dir;
1235  stj.Pts[ipt].Ang = stp1.Ang;
1236  } // ipt
1237 
1238  // fill the RotPos vector and sort
1239  std::vector<SortEntry> sortVec(ss.ShPts.size());
1240  unsigned short indx = 0;
1241  double cs = cos(-stp1.Ang);
1242  double sn = sin(-stp1.Ang);
1243  for(auto& shpt : ss.ShPts) {
1244  double xx = shpt.Pos[0] - stp1.Pos[0];
1245  double yy = shpt.Pos[1] - stp1.Pos[1];
1246  shpt.RotPos[0] = cs * xx - sn * yy;
1247  shpt.RotPos[1] = sn * xx + cs * yy;
1248  sortVec[indx].index = indx;
1249  sortVec[indx].length = shpt.RotPos[0];
1250  ++indx;
1251  } // shpt
1252  std::sort(sortVec.begin(), sortVec.end(), lessThan);
1253  // put the points vector into the sorted order
1254  auto tPts = ss.ShPts;
1255  for(unsigned short ii = 0; ii < ss.ShPts.size(); ++ii) ss.ShPts[ii] = tPts[sortVec[ii].index];
1256 
1257  // Calculate the aspect ratio
1258  Point2_t alongTrans {{0.0, 0.0}};
1259  for(auto& shpt : ss.ShPts) {
1260  alongTrans[0] += shpt.Chg * std::abs(shpt.RotPos[0]);
1261  alongTrans[1] += shpt.Chg * std::abs(shpt.RotPos[1]);
1262  } // shpt
1263  alongTrans[0] /= stj.TotChg;
1264  alongTrans[1] /= stj.TotChg;
1265  if(alongTrans[1] == 0) return false;
1266  ss.AspectRatio = alongTrans[1] / alongTrans[0];
1267  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 2S"<<ss.ID<<" AspectRatio "<<ss.AspectRatio;
1268 
1269  // analyze the charge in three sections. Fill the stj HitPos and find DeltaRMS
1270  if(!AnalyzeRotPos(fcnLabel, tjs, ss, prt)) return false;
1271 
1272  // Reverse the shower direction if needed and define the start point
1273  if(ss.ParentID > 0) {
1274  // The direction was defined by the start of a parent to the charge center. Check the consistency
1275  // with ShPts and reverse if needed
1276  auto& ptj = tjs.allTraj[ss.ParentID - 1];
1277  // find the parent end farthest away from the charge center
1278  unsigned short pend = FarEnd(tjs, ptj, stp1.Pos);
1279  auto& ptp = ptj.Pts[ptj.EndPt[pend]];
1280  auto& firstShPt = ss.ShPts[0];
1281  auto& lastShPt = ss.ShPts[ss.ShPts.size() - 1];
1282  if(PosSep2(ptp.Pos, lastShPt.Pos) < PosSep2(ptp.Pos, firstShPt.Pos)) ReverseShower(fcnLabel, tjs, ss, prt);
1283  stj.Pts[0].Pos = ptp.Pos;
1284  } else {
1285  // no parent exists. Compare the DeltaRMS at the ends
1286  if(stj.Pts[2].DeltaRMS < stj.Pts[0].DeltaRMS) ReverseShower(fcnLabel, tjs, ss, prt);
1287  stj.Pts[0].Pos = ss.ShPts[0].Pos;
1288  } // no parent
1289 
1290  if(stj.Pts[2].DeltaRMS > 0) ss.DirectionFOM = stj.Pts[0].DeltaRMS / stj.Pts[2].DeltaRMS;
1291  // define the end point
1292  stj.Pts[2].Pos = ss.ShPts[ss.ShPts.size() - 1].Pos;
1293 
1294  DefineEnvelope(fcnLabel, tjs, ss, prt);
1295  ss.NeedsUpdate = false;
1296  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 2S"<<ss.ID<<" updated";
1297  return true;
1298 
1299  } // UpdateShower
std::string PrintPos(const TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:4738
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
Double_t xx
Definition: macro.C:12
Int_t B
Definition: plot.C:25
Float_t ss
Definition: plot.C:23
unsigned short FarEnd(const TjStuff &tjs, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:2936
void DefineEnvelope(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3936
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:1614
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1631
bool lessThan(SortEntry c1, SortEntry c2)
Definition: TCShower.cxx:10
float ChgToMeV(float chg)
Definition: TCShower.cxx:4460
bool AnalyzeRotPos(std::string inFcnLabel, TjStuff &tjs, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3170
void ReverseShower(std::string inFcnLabel, TjStuff &tjs, int cotID, bool prt)
Definition: TCShower.cxx:3298
bool tca::UpdateShower ( std::string  inFcnLabel,
TjStuff tjs,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 1302 of file TCShower.cxx.

References tca::TjStuff::allTraj, tca::ShowerStruct3D::ChgPos, tca::ShowerStruct3D::CotIDs, tca::TjStuff::cots, DecodeCTP(), tca::ShowerStruct3D::dEdx, tca::ShowerStruct3D::dEdxErr, dir, tca::TrajPoint3::Dir, tca::ShowerStruct3D::Dir, tca::ShowerStruct3D::End, tca::ShowerStruct3D::Energy, tca::ShowerStruct3D::EnergyErr, FarEnd(), tca::ShowerStruct3D::ID, tca::ShowerStruct3D::Len, MakeTp3(), tca::ShowerStruct3D::MIPEnergy, tca::ShowerStruct3D::MIPEnergyErr, tca::ShowerStruct3D::NeedsUpdate, tca::ShowerStruct3D::ParentID, tca::TjStuff::pfps, geo::PlaneID::Plane, tca::TrajPoint3::Pos, PosSep(), SetMag(), ss, tca::ShowerStruct3D::Start, and tca::ShowerStruct3D::Vx3ID.

Referenced by AddPFP(), AddTj(), AddTjsInsideEnvelope(), CompleteIncompleteShower(), FindParent(), FindShowers3D(), Match2DShowers(), MergeShowers(), MergeShowersAndStore(), Reconcile3D(), RemovePFP(), RemoveTj(), and SetParent().

1303  {
1304  // Updates the 3D shower presumably because the 2D showers were changed or need to be updated.
1305  // This function returns false if there was a failure.
1306 
1307  if(ss3.ID == 0) return false;
1308  if(ss3.CotIDs.size() < 2) return false;
1309 
1310  std::string fcnLabel = inFcnLabel + ".U3S";
1311 
1312  // see if any of the 2D showers need an update
1313  for(auto cid : ss3.CotIDs) {
1314  auto& ss = tjs.cots[cid - 1];
1315  if(ss.NeedsUpdate && prt) std::cout<<fcnLabel<<" ********* 3S"<<ss3.ID<<" 2S"<<ss.ID<<" needs an update...\n";
1316  UpdateShower(fcnLabel, tjs, ss, prt);
1317  } // ci
1318 
1319  // check consistency
1320  if(ss3.ParentID > 0) {
1321  auto& pfp = tjs.pfps[ss3.ParentID - 1];
1322  unsigned short pend = FarEnd(tjs, pfp, ss3.ChgPos);
1323  if(pfp.Vx3ID[pend] != ss3.Vx3ID) {
1324  if(prt) std::cout<<fcnLabel<<" ********* 3S"<<ss3.ID<<" has parent P"<<ss3.ParentID<<" with a vertex that is not attached the shower\n";
1325  }
1326  } // ss3.ParentID > 0
1327 
1328  // Find the average position and direction using pairs of 2D shower Tjs
1329  std::array<Point3_t, 3> pos;
1330  // the direction of all points in 2D showers is the same
1331  Vector3_t dir;
1332  std::array<double, 3> chg;
1333  for(unsigned short ipt = 0; ipt < 3; ++ipt) {
1334  chg[ipt] = 0;
1335  for(unsigned short xyz = 0; xyz < 3; ++xyz) {
1336  pos[ipt][xyz] = 0;
1337  dir[xyz] = 0;
1338  }
1339  } // ipt
1340 
1341  for(unsigned short ii = 0; ii < ss3.CotIDs.size() - 1; ++ii) {
1342  unsigned short ciid = ss3.CotIDs[ii];
1343  auto& iss = tjs.cots[ciid - 1];
1344  // make a local copy of the trajectory so we can replace Pos with HitPos = charge center
1345  auto istj = tjs.allTraj[iss.ShowerTjID - 1];
1346  for(auto& tp : istj.Pts) tp.Pos = tp.HitPos;
1347  for(unsigned short jj = ii + 1; jj < ss3.CotIDs.size(); ++jj) {
1348  unsigned short cjid = ss3.CotIDs[jj];
1349  auto& jss = tjs.cots[cjid - 1];
1350  auto jstj = tjs.allTraj[jss.ShowerTjID - 1];
1351  for(auto& tp : jstj.Pts) tp.Pos = tp.HitPos;
1352  TrajPoint3 tp3;
1353  for(unsigned short ipt = 0; ipt < 3; ++ipt) {
1354  if(!MakeTp3(tjs, istj.Pts[ipt], jstj.Pts[ipt], tp3, true)) continue;
1355  double ptchg = 0.5 * (istj.Pts[ipt].Chg + jstj.Pts[ipt].Chg);
1356  chg[ipt] += ptchg;
1357  for(unsigned short xyz = 0; xyz < 3; ++xyz) {
1358  pos[ipt][xyz] += ptchg * tp3.Pos[xyz];
1359  dir[xyz] += ptchg * tp3.Dir[xyz];
1360  } // xyz
1361  } // ipt
1362  } // jj
1363  } // ii
1364 
1365  unsigned short nok = 0;
1366  for(unsigned short ipt = 0; ipt < 3; ++ipt) {
1367  if(chg[ipt] == 0) continue;
1368  for(unsigned short xyz = 0; xyz < 3; ++xyz) pos[ipt][xyz] /= chg[ipt];
1369  SetMag(dir, 1);
1370  ++nok;
1371  } // ipt
1372 
1373  if(nok != 3) {
1374 // if(prt) std::cout<<fcnLabel<<" ********* 3S"<<ss3.ID<<" Can't find 3 points that match in 3D. \n";
1375  return false;
1376  }
1377  ss3.ChgPos = pos[1];
1378 
1379  if(ss3.ParentID > 0) {
1380  // There is a 3D-matched pfp at the shower start. The end that is farthest away from the
1381  // shower center should be shower start
1382  auto& pfp = tjs.pfps[ss3.ParentID - 1];
1383  unsigned short pend = FarEnd(tjs, pfp, ss3.ChgPos);
1384  ss3.Start = pfp.XYZ[pend];
1385  // TODO: use charge weighted average of shower direction and pfp direction?
1386  ss3.Dir = dir;
1387  } else {
1388  ss3.Dir = dir;
1389  ss3.Start = pos[0];
1390  }
1391  // define the end
1392  ss3.End = pos[2];
1393  ss3.Len = PosSep(ss3.Start, ss3.End);
1394 
1395  // dE/dx, energy, etc
1396  for(auto cid : ss3.CotIDs) {
1397  auto& ss = tjs.cots[cid - 1];
1398  auto& stj = tjs.allTraj[ss.ShowerTjID - 1];
1399  unsigned short plane = DecodeCTP(ss.CTP).Plane;
1400  ss3.Energy[plane] = ss.Energy;
1401  // TODO: calculate the errors in some better way
1402  ss3.EnergyErr[plane] = 0.3 * ss.Energy;
1403  // TODO: what does MIPEnergy mean anyway?
1404  ss3.MIPEnergy[plane] = ss3.EnergyErr[plane];
1405  ss3.MIPEnergyErr[plane] = ss.Energy;
1406  ss3.dEdx[plane] = stj.dEdx[0];
1407  ss3.dEdxErr[plane] = 0.3 * stj.dEdx[0];
1408  } // ci
1409 
1410  ss3.NeedsUpdate = false;
1411  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" updated";
1412  return true;
1413 
1414  } // UpdateShower
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
Float_t ss
Definition: plot.C:23
bool MakeTp3(TjStuff &tjs, const TrajPoint &itp, const TrajPoint &jtp, TrajPoint3 &tp3, bool findDirection)
Definition: PFPUtils.cxx:1526
unsigned short FarEnd(const TjStuff &tjs, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:2936
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
bool SetMag(Vector3_t &v1, double mag)
Definition: PFPUtils.cxx:1641
TDirectory * dir
Definition: macro.C:5
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1625
std::array< double, 3 > Vector3_t
Definition: DataStructs.h:36
bool UpdateShower(std::string inFcnLabel, TjStuff &tjs, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1302
void tca::UpdateTjChgProperties ( std::string  inFcnLabel,
TjStuff tjs,
Trajectory tj,
bool  prt 
)

Definition at line 3118 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::AveChg, tca::Trajectory::ChgRMS, evd::details::end(), tca::Trajectory::EndPt, tca::TjStuff::fHits, kEnvNearTj, kEnvOverlap, kEnvUnusedHits, kKilled, kPhoton, tca::Trajectory::NeedsUpdate, tca::TjStuff::NPtsAve, tca::Trajectory::Pts, tca::Trajectory::TotChg, tca::TjStuff::vtx, and tca::Trajectory::VtxID.

Referenced by tca::TrajClusterAlg::AddLAHits(), tca::TrajClusterAlg::ChkStopEndPts(), DotProd(), tca::TrajClusterAlg::MaskedHitsOK(), MaxChargeAsymmetry(), SplitTraj(), StoreTraj(), tca::TrajClusterAlg::UpdateTraj(), and UpdateVxEnvironment().

3119  {
3120  // Updates properties of the tj that are affected when the TP environment
3121  // is changed. The most likely reason for a change is when the tj is attached to a
3122  // vertex in which case the Environment kEnvOverlap bit may be set by the UpdateVxEnvironment
3123  // function in which case this function is called.
3124  // The kEnvNearShower bit may be set by TagShowerTjs but this doesn't affect the
3125  // calculation of the properties of this Tj. This function simply sets the kEnvUnusedHits bit
3126  // for all TPs.
3127  if(tj.AlgMod[kKilled]) return;
3128 
3129  std::string fcnLabel = inFcnLabel + ".UpTjProp";
3130 
3131  // first (un)set some bits
3132  for(auto& tp : tj.Pts) {
3133  if(tp.Chg <= 0) continue;
3134  tp.Environment[kEnvUnusedHits] = false;
3135  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3136  if(tp.UseHit[ii]) continue;
3137  unsigned int iht = tp.Hits[ii];
3138  if(tjs.fHits[iht].InTraj == 0) {
3139  tp.Environment[kEnvUnusedHits] = true;
3140  } else {
3141  tp.Environment[kEnvNearTj] = true;
3142  }
3143  } // ii
3144  } // tp
3145 
3146  // Update the tj charge variables. The concept is explained by this graphic where
3147  // each column is a wire, Q = a TP with charge, q = a TP with charge that is an
3148  // EnvOverlap region, x = a wire that has a TP with Chg = 0 or a wire that has no TP
3149  // because the wire is dead, o = an EnvOverlap region, V = vertex attached to end. You should
3150  // imagine that all 3 tjs come from the same vertex
3151  // 01234567890123456789 npwc cnt range
3152  // VooooQQQQxxxQQQ 7 7 0 - 14
3153  // VqqqqQQQQxxxQQQQQQQQ 16 12 0 - 19
3154  // VooQQQ 3 3 0 - 5
3155  // The average is first calculated using Ave = sum(Q) / npwc
3156  // TotChg is calculated using
3157  tj.TotChg = 0;
3158  tj.AveChg = 0;
3159  tj.ChgRMS = 0.5;
3160 
3161  // These variables are used to calculate the average and rms using valid points with charge
3162  double vcnt = 0;
3163  double vsum = 0;
3164  double vsum2 = 0;
3165  // variables for calculating the backup quanties. These are only used if npwc < 3
3166  double bcnt = 0;
3167  double bsum = 0;
3168  double bsum2 = 0;
3169  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
3170  auto& tp = tj.Pts[ipt];
3171  if(tp.Chg <= 0) continue;
3172  // accumulate a backup sum in case most of the points are overlapped. Note that
3173  // tp.Chg has an angle correction, which is why the hit integral is summed
3174  // below. We don't care about this detail for the backup sum
3175  bsum += tp.Chg;
3176  bsum2 += tp.Chg * tp.Chg;
3177  ++bcnt;
3178  // Skip TPs that overlap with TPs on other Tjs. A correction will be made below
3179  if(tj.Pts[ipt].Environment[kEnvOverlap]) continue;
3180  ++vcnt;
3181  double tpchg = 0;
3182  for(unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
3183  if(!tp.UseHit[ii]) continue;
3184  unsigned int iht = tp.Hits[ii];
3185  tpchg += tjs.fHits[iht].Integral;
3186  } // ii
3187  vsum += tpchg;
3188  vsum2 += tpchg * tpchg;
3189  } // ipt
3190 
3191  if(bcnt == 0) return;
3192 
3193  if(vcnt < 3) {
3194  // use the backup sum
3195  tj.TotChg = bsum;
3196  tj.AveChg = bsum / bcnt;
3197  if(vcnt > 2) {
3198  double arg = bsum2 - bcnt * tj.AveChg * tj.AveChg;
3199  if(arg > 0) tj.ChgRMS = sqrt(arg / (bcnt - 1));
3200  }
3201  for(auto& tp : tj.Pts) tp.AveChg = tj.AveChg;
3202  return;
3203  } // low npwc
3204 
3205  double nWires = tj.EndPt[1] - tj.EndPt[0] + 1;
3206  if(nWires < 2) return;
3207  // correct for wires missing near vertices.
3208  // Count the number of wires between vertices at the ends and the first wire
3209  // that has charge. This code assumes that there should be one TP on each wire
3210  if(!tj.AlgMod[kPhoton]) {
3211  for(unsigned short end = 0; end < 2; ++end) {
3212  if(tj.VtxID[end] == 0) continue;
3213  auto& tp = tj.Pts[tj.EndPt[end]];
3214  auto& vx2 = tjs.vtx[tj.VtxID[end] - 1];
3215  int dw = std::abs(tp.Pos[0] - vx2.Pos[0]);
3216  // This assumes that the vertex is not inside the wire boundaries of the tj
3217  nWires += dw;
3218  } // end
3219  } // not a photon Tj
3220 
3221  tj.AveChg = vsum / vcnt;
3222  // calculate the total charge using the tj wire range
3223  tj.TotChg = nWires * tj.AveChg;
3224  // calculate the rms
3225  double arg = vsum2 - vcnt * tj.AveChg * tj.AveChg;
3226  double rms = 0.5;
3227  if(arg > 0) rms = sqrt(arg / (vcnt - 1));
3228  rms /= tj.AveChg;
3229  // don't let it be an unrealistically low value. It could be crazy large however.
3230  if(rms < 0.1) rms = 0.1;
3231  // Don't let the calculated charge RMS dominate until it is well known; after there are 5 - 10 valid TPs.
3232  // Set the starting charge rms = 0.5
3233  if(vcnt < 10) {
3234  double defFrac = 1 / vcnt;
3235  rms = defFrac * 0.5 + (1 - defFrac) * rms;
3236  }
3237  tj.ChgRMS = rms;
3238 
3239  // Update the TP charge pulls.
3240  // Don't let the calculated charge RMS dominate the default
3241  // RMS until it is well known. Start with 50% error on the
3242  // charge RMS
3243  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
3244  auto& tp = tj.Pts[ipt];
3245  if(tp.Chg <= 0) continue;
3246  tp.ChgPull = (tp.Chg / tj.AveChg - 1) / tj.ChgRMS;
3247  } // ipt
3248 
3249  // update the local charge average using NPtsAve of the preceding points.
3250  // Handle short Tjs first.
3251  if(vcnt < tjs.NPtsAve) {
3252  for(auto& tp : tj.Pts) tp.AveChg = tj.AveChg;
3253  return;
3254  }
3255 
3256  // Set the local average to 0 first
3257  for(auto& tp : tj.Pts) tp.AveChg = 0;
3258  // Enter the local average on the points where an average can be calculated
3259  unsigned short nptsave = tjs.NPtsAve;
3260  unsigned short minPt = tj.EndPt[0] + nptsave;
3261  float lastAve = 0;
3262  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
3263  unsigned short ipt = tj.EndPt[1] - ii;
3264  if(ipt < minPt) break;
3265  float cnt = 0;
3266  float sum = 0;
3267  for(unsigned short iii = 0; iii < nptsave; ++iii) {
3268  unsigned short iipt = ipt - iii;
3269  // Don't include the charge of the first point
3270  if(iipt == tj.EndPt[0]) break;
3271  auto& tp = tj.Pts[iipt];
3272  if(tp.Chg <= 0) continue;
3273  sum += tp.Chg;
3274  ++cnt;
3275  } // iii
3276  if(cnt > 2) {
3277  tj.Pts[ipt].AveChg = sum / cnt;
3278  lastAve = tj.Pts[ipt].AveChg;
3279  }
3280  } // ii
3281  // Fill in the points where no average was calculated
3282  for(unsigned short ii = tj.EndPt[0]; ii <= tj.EndPt[1]; ++ii) {
3283  unsigned short ipt = tj.EndPt[1] - ii;
3284  auto& tp = tj.Pts[ipt];
3285  if(tp.AveChg == 0) {
3286  tp.AveChg = lastAve;
3287  } else {
3288  lastAve = tp.AveChg;
3289  }
3290  } // ii
3291 
3292  tj.NeedsUpdate = false;
3293 
3294  } // UpdateTjChgProperties
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void tca::UpdateTp3s ( TjStuff tjs,
PFPStruct pfp,
int  oldTj,
int  newTj 
)

Definition at line 85 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, detinfo::DetectorProperties::ConvertTicksToX(), DecodeCTP(), tca::TjStuff::detprop, tca::TjStuff::mallTraj, tca::PFPStruct::Tp3s, and tca::TjStuff::UnitsPerTick.

Referenced by MergePFPTjs().

86  {
87  // Replaces occurrences of oldTj with newTj in the pfp vector of Tp3s
88  if(oldTj <= 0 || oldTj > (int)tjs.allTraj.size()) return;
89  if(newTj <= 0 || newTj > (int)tjs.allTraj.size()) return;
90  if(tjs.mallTraj.empty() && pfp.Tp3s.empty()) return;
91 
92  // convert from int to unsigned short
93  unsigned short oldtjid = oldTj;
94  unsigned short newtjid = newTj;
95  auto& ntj = tjs.allTraj[newTj - 1];
96  unsigned short npts = ntj.EndPt[1] - ntj.EndPt[0] + 1;
97  // put the X positions of the new Tj into a vector for matching
98  std::vector<float> xpos(ntj.Pts.size());
99  geo::PlaneID planeID = DecodeCTP(ntj.CTP);
100  for(unsigned short npt = ntj.EndPt[0]; npt <= ntj.EndPt[1]; ++npt) {
101  auto& ntp = ntj.Pts[npt];
102  if(ntp.Chg <= 0) continue;
103  xpos[npt] = tjs.detprop->ConvertTicksToX(ntp.Pos[1]/tjs.UnitsPerTick, planeID);
104  } // npt
105 
106  for(auto& tp3 : pfp.Tp3s) {
107  // check each of the Tj2Pts associated with this space point
108  for(auto& tj2pt : tp3.Tj2Pts) {
109  if(tj2pt.id > tjs.allTraj.size()) continue;
110  if(tj2pt.id != oldtjid) continue;
111  // look for the corresponding point (wire) on the new Tj
112  for(unsigned short npt = ntj.EndPt[0]; npt <= ntj.EndPt[1]; ++npt) {
113  auto& ntp = ntj.Pts[npt];
114  if(std::nearbyint(ntp.Pos[0]) == tj2pt.wire && xpos[npt] > tj2pt.xlo && xpos[npt] < tj2pt.xhi) {
115  tj2pt.id = newtjid;
116  tj2pt.ipt = npt;
117  tj2pt.npts = npts;
118  break;
119  }
120  } // npt
121  } // tj2pt
122  } // tp3
123 
124  } // UpdateTp3s
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
void tca::UpdateVxEnvironment ( std::string  inFcnLabel,
TjStuff tjs,
VtxStore vx2,
bool  prt 
)

Definition at line 3297 of file Utils.cxx.

References tca::TjStuff::allTraj, tca::TrajPoint::Chg, tca::VtxStore::CTP, tca::TrajPoint::Dir, evd::details::end(), tca::VtxStore::ID, kEnvOverlap, kKilled, kOnDeadWire, kPhoton, MakeBareTrajPoint(), tca::VtxStore::Pos, tca::TrajPoint::Pos, PrintPos(), tca::VtxStore::Stat, and UpdateTjChgProperties().

Referenced by DotProd(), and tca::TrajClusterAlg::ReconstructAllTraj().

3298  {
3299  // Update the Environment each TP on trajectories near the vertex. This is called when
3300  // the Tj has been added to a vertex to identify nearby trajectories that contribute to
3301  // the charge on TPs near the vertex.
3302  if(vx2.ID == 0) return;
3303  if(vx2.Stat[kOnDeadWire]) return;
3304 
3305  std::string fcnLabel = inFcnLabel + ".UpVxProp";
3306 
3307  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" UpdateTjEnvironment check Tjs attached to vx2 "<<vx2.ID;
3308 
3309  std::vector<int> tjlist;
3310  std::vector<unsigned short> tjends;
3311  if(vx2.Pos[0] < -0.4) return;
3312  unsigned int vxWire = std::nearbyint(vx2.Pos[0]);
3313  unsigned int loWire = vxWire;
3314  unsigned int hiWire = vxWire;
3315  for(auto& tj : tjs.allTraj) {
3316  if(tj.AlgMod[kKilled]) continue;
3317  if(tj.CTP != vx2.CTP) continue;
3318  // ignore photon Tjs
3319  if(tj.AlgMod[kPhoton]) continue;
3320  for(unsigned short end = 0; end < 2; ++end) {
3321  if(tj.VtxID[end] != vx2.ID) continue;
3322  tjlist.push_back(tj.ID);
3323  tjends.push_back(end);
3324  if(tj.Pts[tj.EndPt[end]].Pos[0] < -0.4) return;
3325  unsigned int endWire = std::nearbyint(tj.Pts[tj.EndPt[end]].Pos[0]);
3326  if(endWire < loWire) loWire = endWire;
3327  if(endWire > hiWire) hiWire = endWire;
3328  } // end
3329  } // tj
3330  if(tjlist.size() < 2) return;
3331  if(hiWire < loWire + 1) return;
3332  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" check Tjs on wires in the range "<<loWire<<" to "<<hiWire;
3333 
3334  // create a vector of TPs between loWire and hiWire for every tj in the list
3335  // wire TP
3336  std::vector<std::vector<TrajPoint>> wire_tjpt;
3337  // companion vector of IDs
3338  std::vector<int> tjids;
3339  // populate this vector with TPs on Tjs that are in this range
3340  unsigned short nwires = hiWire - loWire + 1;
3341  for(unsigned short itj = 0; itj < tjlist.size(); ++itj) {
3342  auto& tj = tjs.allTraj[tjlist[itj] - 1];
3343  unsigned short end = tjends[itj];
3344  std::vector<TrajPoint> tjpt(nwires);
3345  // first enter valid TPs in the range
3346  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
3347  unsigned short ipt;
3348  if(end == 0) { ipt = tj.EndPt[0] + ii; } else { ipt = tj.EndPt[1] - ii; }
3349  if(ipt > tj.Pts.size() - 1) break;
3350  // Make a copy of the TP so we can alter it
3351  auto tp = tj.Pts[ipt];
3352  if(tp.Chg <= 0) continue;
3353  tp.Chg = 1;
3354  tp.Hits.clear();
3355  if(tp.Pos[0] < -0.4) continue;
3356  unsigned int wire = std::nearbyint(tp.Pos[0]);
3357  unsigned short indx = wire - loWire;
3358  if(indx > nwires - 1) break;
3359  tp.Step = ipt;
3360  // We will use NTPsFit to count the number of neighboring TPs
3361  tp.NTPsFit = 0;
3362  tjpt[indx] = tp;
3363  } // ii
3364  // next make TPs on the wires that don't have real TPs
3365  TrajPoint ltp;
3366  // put ltp at the vertex position with direction towards the end point
3367  MakeBareTrajPoint(vx2.Pos, tj.Pts[tj.EndPt[end]].Pos, ltp);
3368  if(ltp.Dir[0] == 0) continue;
3369  if(ltp.Pos[0] < -0.4) continue;
3370  unsigned int wire = std::nearbyint(ltp.Pos[0]);
3371  ltp.Chg = 0;
3372  unsigned short indx = wire - loWire;
3373  // Break if we found a real TP
3374  if(tjpt[indx].Chg == 0) tjpt[indx] = ltp;
3375  double stepSize = std::abs(1/ltp.Dir[0]);
3376  for(unsigned short ii = 0; ii < nwires; ++ii) {
3377  // move the local TP position by one step in the right direction
3378  for(unsigned short iwt = 0; iwt < 2; ++iwt) ltp.Pos[iwt] += ltp.Dir[iwt] * stepSize;
3379  if(ltp.Pos[0] < -0.4) break;
3380  wire = std::nearbyint(ltp.Pos[0]);
3381  if(wire < loWire || wire > hiWire) break;
3382  indx = wire - loWire;
3383  if(tjpt[indx].Chg > 0) continue;
3384  tjpt[indx]= ltp;
3385  } // ii
3386  if(prt) {
3387  mf::LogVerbatim myprt("TC");
3388  myprt<<fcnLabel<<" T"<<tj.ID;
3389  for(auto& tp : tjpt) myprt<<" "<<PrintPos(tjs, tp.Pos)<<"_"<<tp.Step<<"_"<<(int)tp.Chg;
3390  }
3391  wire_tjpt.push_back(tjpt);
3392  tjids.push_back(tj.ID);
3393  } // itj
3394 
3395  // iterate over the wires in the range
3396  for(unsigned short indx = 0; indx < nwires; ++indx) {
3397  // count the number of valid points on this wire
3398  unsigned short npts = 0;
3399  // count the number of points on this wire that have charge
3400  unsigned short npwc = 0;
3401  for(unsigned short itj = 0; itj < wire_tjpt.size(); ++itj) {
3402  if(wire_tjpt[itj][indx].Pos[0] == 0) continue;
3403  // found a valid point
3404  ++npts;
3405  if(wire_tjpt[itj][indx].Chg > 0) ++npwc;
3406  } // itj
3407  // no valid points
3408 // if(prt) mf::LogVerbatim("TC")<<" wire "<<loWire + indx<<" npts "<<npts<<" npwc "<<npwc;
3409  if(npts == 0) continue;
3410  // all valid points have charge
3411  if(npwc == npts) continue;
3412  // re-find the valid points with charge and set the kEnvOverlap bit
3413  for(unsigned short itj = 0; itj < wire_tjpt.size(); ++itj) {
3414  if(wire_tjpt[itj][indx].Pos[0] == 0) continue;
3415  if(wire_tjpt[itj][indx].Chg == 0) continue;
3416  auto& tj = tjs.allTraj[tjids[itj] - 1];
3417  unsigned short ipt = wire_tjpt[itj][indx].Step;
3418  tj.Pts[ipt].Environment[kEnvOverlap] = true;
3419  tj.NeedsUpdate = true;
3420  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Set kEnvOverlap bit on T"<<tj.ID<<" ipt "<<ipt;
3421  } // itj
3422  } // indx
3423 
3424  // update the charge rms for those tjs whose environment was changed above (or elsewhere)
3425  for(auto tjid : tjids) {
3426  auto& tj = tjs.allTraj[tjid - 1];
3427  if(!tj.NeedsUpdate) continue;
3428  if(tj.CTP != vx2.CTP) continue;
3429  UpdateTjChgProperties(fcnLabel, tjs, tj, prt);
3430  } // tjid
3431 
3432  } // UpdateVxEnvironment
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeBareTrajPoint(const TjStuff &tjs, const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
Definition: Utils.cxx:3536
void UpdateTjChgProperties(std::string inFcnLabel, TjStuff &tjs, Trajectory &tj, bool prt)
Definition: Utils.cxx:3118
std::string PrintPos(const TjStuff &tjs, const Point2_t &pos)
Definition: Utils.cxx:4744
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool tca::valDecreasing ( SortEntry  c1,
SortEntry  c2 
)
bool tca::valDecreasings ( SortEntry  c1,
SortEntry  c2 
)

Definition at line 12 of file PFPUtils.cxx.

References tca::SortEntry::val.

Referenced by FindPFParticles(), and FindXMatches().

12 { return (c1.val > c2.val);}
float val
Definition: Utils.cxx:8
bool tca::valIncreasing ( SortEntry  c1,
SortEntry  c2 
)

Definition at line 11 of file TCVertex.cxx.

References tca::SortEntry::val.

Referenced by Find3DVertices().

11 { return (c1.val < c2.val);}
float val
Definition: Utils.cxx:8
bool tca::valIncreasings ( SortEntry  c1,
SortEntry  c2 
)

Definition at line 13 of file PFPUtils.cxx.

References tca::SortEntry::val.

Referenced by FillmAllTraj(), and SetStart().

13 { return (c1.val < c2.val);}
float val
Definition: Utils.cxx:8
float tca::VertexVertexPull ( TjStuff tjs,
const Vtx3Store vx1,
const Vtx3Store vx2 
)

Definition at line 1882 of file TCVertex.cxx.

References tca::Vtx3Store::X, tca::Vtx3Store::XErr, tca::Vtx3Store::Y, tca::Vtx3Store::YErr, tca::Vtx3Store::Z, and tca::Vtx3Store::ZErr.

Referenced by IsCloseToVertex().

1883  {
1884  // Calculates the position pull between two vertices
1885  double dx = vx1.X - vx2.X;
1886  double dy = vx1.Y - vx2.Y;
1887  double dz = vx1.Z - vx2.Z;
1888  double dxErr2 = (vx1.XErr * vx1.XErr + vx2.XErr * vx2.XErr) / 2;
1889  double dyErr2 = (vx1.YErr * vx1.YErr + vx2.YErr * vx2.YErr) / 2;
1890  double dzErr2 = (vx1.ZErr * vx1.ZErr + vx2.ZErr * vx2.ZErr) / 2;
1891  dx = dx * dx / dxErr2;
1892  dy = dy * dy / dyErr2;
1893  dz = dz * dz / dzErr2;
1894  return (float)(sqrt(dx + dy + dz)/3);
1895  }
float tca::VertexVertexPull ( TjStuff tjs,
const VtxStore vx1,
const VtxStore vx2 
)

Definition at line 1898 of file TCVertex.cxx.

References tca::VtxStore::Pos, and tca::VtxStore::PosErr.

1899  {
1900  // Calculates the position pull between two vertices
1901  double dw = vx1.Pos[0] - vx2.Pos[0];
1902  double dt = vx1.Pos[1] - vx2.Pos[1];
1903  double dwErr2 = (vx1.PosErr[0] * vx1.PosErr[0] + vx2.PosErr[0] * vx2.PosErr[0]) / 2;
1904  double dtErr2 = (vx1.PosErr[1] * vx1.PosErr[1] + vx2.PosErr[1] * vx2.PosErr[1]) / 2;
1905  dw = dw * dw / dwErr2;
1906  dt = dt * dt / dtErr2;
1907  return (float)sqrt(dw + dt);
1908  }
void tca::VtxHitsSwap ( TjStuff tjs,
const CTP_t  inCTP 
)

Definition at line 2758 of file TCVertex.cxx.

References tca::Trajectory::AlgMod, tca::TjStuff::allTraj, tca::VtxStore::CTP, debug, DecodeCTP(), evd::details::end(), tca::Trajectory::EndPt, tca::TjStuff::fHits, tca::TrajPoint::Hits, tca::VtxStore::ID, tca::Trajectory::ID, kKilled, kVtxHitsSwap, tca::VtxStore::NTraj, tca::DebugStuff::Plane, geo::PlaneID::Plane, PointTrajDOCA(), tca::VtxStore::Pos, PrintPos(), tca::Trajectory::Pts, SetEndPoints(), tca::DebugStuff::Tick, TpSumHitChg(), tca::TjStuff::UseAlg, tca::TrajPoint::UseHit, tca::TjStuff::vtx, and tca::Trajectory::VtxID.

Referenced by tca::TrajClusterAlg::ReconstructAllTraj().

2758  {
2759 
2760  if(!tjs.UseAlg[kVtxHitsSwap]) return;
2761 
2762  geo::PlaneID planeID = DecodeCTP(inCTP);
2763 
2764  bool vtxPrt = ((debug.Plane == (int)planeID.Plane || debug.Plane == 3) && debug.Tick < 0);
2765  if(vtxPrt) mf::LogVerbatim("TC")<<"inside VtxHitsSwap on plane "<<planeID.Plane;
2766  for (unsigned short iv = 0; iv < tjs.vtx.size(); ++iv){
2767  VtxStore& rvx = tjs.vtx[iv];
2768  if(rvx.CTP != inCTP) continue;
2769  // Only consider vertex with two trajectories
2770  if(rvx.NTraj != 2) continue;
2771  if (vtxPrt) mf::LogVerbatim("TC")<<"Vertex "<<iv<<" Pos[0]: "<<rvx.Pos[0]<<" "<<rvx.Pos[1];
2772  std::array<unsigned short, 2> tjlist{{0,0}};
2773  for(unsigned short itj = 0; itj < tjs.allTraj.size(); ++itj) {
2774  if(tjs.allTraj[itj].AlgMod[kKilled]) continue;
2775  if(tjs.allTraj[itj].CTP != rvx.CTP) continue;
2776  Trajectory& tj = tjs.allTraj[itj];
2777  // ensure that the ID is OK so the code below doesn't choke
2778  for(unsigned short end = 0; end < 2; ++end) {
2779  if(tj.VtxID[end] == rvx.ID) {
2780  tjlist[end] = itj;
2781  }
2782  }
2783  }//all trajectories
2784 
2785  //Ignore short trajectories
2786  if (tjs.allTraj[tjlist[0]].EndPt[1]<5||
2787  tjs.allTraj[tjlist[1]].EndPt[1]<5) continue;
2788 
2789  for (unsigned short i = 0; i<2; ++i){
2790 
2791  //First check if first hit should be swapped
2792  Trajectory& tj0 = tjs.allTraj[tjlist[i]];
2793  Trajectory& tj1 = tjs.allTraj[tjlist[1-i]];
2794  unsigned short endPt0 = tjs.allTraj[tjlist[i]].EndPt[i];
2795  unsigned short endPt1 = tjs.allTraj[tjlist[1-i]].EndPt[1-i];
2796  //first TP on first trajectory
2797  float chg0 = TpSumHitChg(tjs, tj0.Pts[endPt0]);
2798  float w0 = tj0.Pts[endPt0].Pos[0];
2799  //if (vtxPrt) mf::LogVerbatim("TC")<<PrintPos(tjs, tj0.Pts[endPt0]);
2800  //second TP on first trajectory
2801  float chg1 = 0;
2802  float w1 = 0;
2803  unsigned short j = endPt0;
2804  while (j!=tj0.EndPt[1-i]){
2805  if (i==0) ++j;
2806  else --j;
2807  if (tj0.Pts[j].Chg){
2808  chg1 = TpSumHitChg(tjs, tj0.Pts[j]);
2809  w1 = tj0.Pts[j].Pos[0];
2810  //if (vtxPrt) mf::LogVerbatim("TC")<<PrintPos(tjs, tj0.Pts[j]);
2811  break;
2812  }
2813  }
2814  //first TP on second trajectory
2815  float chg2 = TpSumHitChg(tjs,tj1.Pts[endPt1]);
2816  float w2 = tj1.Pts[endPt1].Pos[0];
2817  //DOCA between first TP on first TJ and first TP on second TJ
2818  float delta = 1000;
2819  for (size_t k = 0; k<tj0.Pts[endPt0].Hits.size(); ++k){
2820  if (!tj0.Pts[endPt0].UseHit[k]) continue;
2821  float this_delta = PointTrajDOCA(tjs, tj0.Pts[endPt0].Hits[k], tj1.Pts[endPt1]);
2822  if (this_delta<delta) delta = this_delta;
2823  }
2824  // if (vtxPrt) mf::LogVerbatim("TC")<<PrintPos(tjs, tj1.Pts[endPt1]);
2825  //if (vtxPrt) mf::LogVerbatim("TC")<<chg0<<" "<<chg1<<" "<<chg2<<" "<<delta;
2826  if (chg0>0&&std::abs((chg0-chg1)/chg0)-std::abs((chg0-chg2)/chg0)>0.2&&delta<1.5&&std::abs(w2-w1)<1.5){
2827  if (vtxPrt) {
2828  mf::LogVerbatim("TC")<<"chg0 = "<<chg0<<" chg1 = "<<chg1<<" chg2 = "<<chg2<<" delta = "<<delta<<" w0 = "<<w0<<" w1 = "<<w1<<" w2 = "<<w2;
2829  mf::LogVerbatim("TC")<<"VHS Moving TP "<<PrintPos(tjs, tj0.Pts[endPt0])<<" from TJ "<<tj0.ID<<" to TJ "<<tj1.ID;
2830  }
2831  //Add first TP of first trajectory to the second trajectory
2832  TrajPoint tp = tj0.Pts[endPt0];
2833  for (size_t j = 0; j<tp.Hits.size(); ++j){
2834  if (!tp.UseHit[j]) continue;
2835  tjs.fHits[tp.Hits[j]].InTraj = tj1.ID;
2836  }
2837  if (i==0){
2838  //append to the end
2839  tj1.Pts.push_back(tp);
2840  }
2841  else{
2842  //insert at the beginning
2843  tj1.Pts.insert(tj1.Pts.begin(), tp);
2844  }
2845  SetEndPoints(tjs, tj1);
2846 
2847  //Remove first TP from first trajectory
2848  tj0.Pts[endPt0].Chg = 0;
2849  for (size_t j = 0; j<tj0.Pts[endPt0].Hits.size(); ++j){
2850  tj0.Pts[endPt0].UseHit[j] = false;
2851  }
2852  SetEndPoints(tjs, tj0);
2853  tj0.AlgMod[kVtxHitsSwap] = true;
2854  tj1.AlgMod[kVtxHitsSwap] = true;
2855  break;
2856  }
2857 
2858  //Now Check if the beginning of the first trajectory should be moved to the second trajectory.
2859  j = endPt0;
2860  std::vector<unsigned short> tplist;
2861  while (j!=tj0.EndPt[1-i]){
2862  if (tj0.Pts[j].Chg){
2863  float delta = 1000;
2864  for (size_t k = 0; k<tj0.Pts[j].Hits.size(); ++k){
2865  if (!tj0.Pts[j].UseHit[k]) continue;
2866  float this_delta = PointTrajDOCA(tjs, tj0.Pts[j].Hits[k], tj1.Pts[endPt1]);
2867  if (this_delta<delta) delta = this_delta;
2868  //if (vtxPrt) mf::LogVerbatim("TC")<<j<<" "<<k<<" "<<PrintPos(tjs, tj0.Pts[j])<<" "<<PointTrajDOCA(tjs, tj0.Pts[j].Hits[k], tj1.Pts[endPt1]);
2869  }
2870  if (delta < 0.3 && tj0.Pts[j].Delta > 1.0 && (j==endPt0 || !tplist.empty())){
2871  tplist.push_back(j);
2872  }
2873  else break;
2874  }
2875  if (i==0) ++j;
2876  else --j;
2877  }
2878  //if (vtxPrt) mf::LogVerbatim("TC")<<tplist.size();
2879  //Need at least two TPs to make this change
2880  if (tplist.size()>1){
2881  if (vtxPrt) mf::LogVerbatim("TC")<<"VHS Moving "<<tplist.size()<<" TPs from TJ "<<tj0.ID<<" to TJ "<<tj1.ID;
2882  //Append TPs to the second TJ
2883  for (unsigned short j = 0; j<tplist.size(); ++j){
2884  TrajPoint tp = tj0.Pts[tplist[j]];
2885  for (size_t k = 0; k<tp.Hits.size(); ++k){
2886  if (!tp.UseHit[k]) continue;
2887  tjs.fHits[tp.Hits[k]].InTraj = tj1.ID;
2888  }
2889  if (i==0){
2890  //append to the end
2891  tj1.Pts.push_back(tp);
2892  }
2893  else{
2894  //insert at the beginning
2895  tj1.Pts.insert(tj1.Pts.begin(), tp);
2896  }
2897  }
2898  SetEndPoints(tjs, tj1);
2899 
2900  //Remove TPs from first trajectory
2901  for (unsigned short j = 0; j<tplist.size(); ++j){
2902  tj0.Pts[tplist[j]].Chg = 0;
2903  for (size_t k = 0; k<tj0.Pts[tplist[j]].Hits.size(); ++k){
2904  tj0.Pts[tplist[j]].UseHit[k] = false;
2905  }
2906  }
2907  SetEndPoints(tjs, tj0);
2908  tj0.AlgMod[kVtxHitsSwap] = true;
2909  tj1.AlgMod[kVtxHitsSwap] = true;
2910  break;
2911  }
2912  }//loop over two trajectories
2913  }//loop over vertices
2914  }
std::string PrintPos(const TjStuff &tjs, const TrajPoint &tp)
Definition: Utils.cxx:4738
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float TpSumHitChg(TjStuff &tjs, TrajPoint const &tp)
Definition: Utils.cxx:1678
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
DebugStuff debug
Definition: DebugStruct.cxx:4
int Plane
Select plane.
Definition: DebugStruct.h:29
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
float PointTrajDOCA(TjStuff const &tjs, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2139
int Tick
Select hit PeakTime for debugging (< 0 for vertex finding)
Definition: DebugStruct.h:32
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
void SetEndPoints(TjStuff &tjs, Trajectory &tj)
Definition: Utils.cxx:2788
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
unsigned short tca::Vx3Topo ( TjStuff tjs,
Vtx3Store vx3 
)

Definition at line 2450 of file TCVertex.cxx.

References tca::Vtx3Store::ID, tca::TjStuff::vtx, and tca::Vtx3Store::Vx2ID.

2451  {
2452  // Returns the most common value of Topo for the 2D vertices that are matched
2453  // to this 3D vertex. This **might** be a useful measure to identify neutrino interaction
2454  // vertices
2455 
2456  if(vx3.ID == 0) return USHRT_MAX;
2457  // Consider Topo values between 0 and 9
2458  std::array<short, 10> cnts;
2459  cnts.fill(0);
2460  for(auto vx2id : vx3.Vx2ID) {
2461  if(vx2id == 0) continue;
2462  auto& vx2 = tjs.vtx[vx2id - 1];
2463  if(vx2.Topo < 0 || vx2.Topo > 9) continue;
2464  ++cnts[vx2.Topo];
2465  } // vx2id
2466  short most = 0;
2467  unsigned short theMost = USHRT_MAX;
2468  for(unsigned short itp = 0; itp < 10; ++itp) {
2469  if(cnts[itp] > most) {
2470  most = cnts[itp];
2471  theMost = itp;
2472  }
2473  } // itp
2474  return theMost;
2475  } // Vx3Topo
void tca::WatchHit ( std::string  someText,
TjStuff tjs,
const unsigned int &  wHit,
short &  wInTraj,
const unsigned short &  tjID 
)

Definition at line 984 of file Utils.cxx.

References tca::TjStuff::fHits, and PrintHitShort().

985  {
986  // a temp routine to watch when inTraj changes for the supplied hit index, watchHit
987  if(wHit > tjs.fHits.size() - 1) return;
988 
989  if(tjs.fHits[wHit].InTraj != wInTraj) {
990  std::cout<<someText<<" Hit "<<PrintHitShort(tjs.fHits[wHit])<<" was InTraj "<<wInTraj<<" now InTraj "<<tjs.fHits[wHit].InTraj<<" T"<<tjID<<"\n";
991  wInTraj = tjs.fHits[wHit].InTraj;
992  }
993  } // WatchHit
std::string PrintHitShort(const TCHit &hit)
Definition: Utils.cxx:4726
bool tca::WireHitRangeOK ( const TjStuff tjs,
const CTP_t inCTP 
)

Definition at line 3886 of file Utils.cxx.

References geo::CryostatID::Cryostat, DecodeCTP(), geo::TPCID::TPC, and tca::TjStuff::TPCID.

Referenced by DotProd(), and FindCloseHits().

3887  {
3888  // returns true if the passed CTP code is consistent with the CT code of the WireHitRangeVector
3889  geo::PlaneID planeID = DecodeCTP(inCTP);
3890  if(planeID.Cryostat != tjs.TPCID.Cryostat) return false;
3891  if(planeID.TPC != tjs.TPCID.TPC) return false;
3892  return true;
3893  }
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
geo::PlaneID DecodeCTP(CTP_t CTP)
Definition: DataStructs.cxx:89
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
unsigned short tca::WiresSkippedInCTP ( TjStuff tjs,
std::vector< int > &  tjids,
CTP_t  inCTP 
)

Definition at line 1060 of file PFPUtils.cxx.

References tca::TjStuff::allTraj, and evd::details::end().

1061  {
1062  // counts the number of wires between the end points of all Tjs in the list of tjids
1063  // in inCTP where there is no TP with charge
1064  if(tjids.empty()) return 0;
1065 
1066  // find the min and max Pos[0] positions
1067  float fLoWire = 1E6;
1068  float fHiWire = -1E6;
1069  for(auto tjid : tjids) {
1070  auto& tj = tjs.allTraj[tjid - 1];
1071  if(tj.CTP != inCTP) continue;
1072  for(unsigned short end = 0; end < 2; ++end) {
1073  float endWire = tj.Pts[tj.EndPt[end]].Pos[0];
1074  if(endWire < -0.4) continue;
1075  if(endWire < fLoWire) fLoWire = endWire;
1076  if(endWire > fHiWire) fHiWire = endWire;
1077  } // end
1078  } // tjid
1079  if(fLoWire >= fHiWire) return 0;
1080  unsigned int loWire = std::nearbyint(fLoWire);
1081  unsigned short nWires = std::nearbyint(fHiWire) - loWire + 1;
1082  std::vector<bool> ptOnWire(nWires, false);
1083 
1084  // count the number of points with charge on all Tjs
1085  float npwc = 0;
1086  for(auto tjid : tjids) {
1087  auto& tj = tjs.allTraj[tjid - 1];
1088  if(tj.CTP != inCTP) continue;
1089  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1090  auto& tp = tj.Pts[ipt];
1091  if(tp.Chg <= 0) continue;
1092  if(tp.Pos[0] < -0.4) continue;
1093  ++npwc;
1094  unsigned short indx = std::nearbyint(tp.Pos[0]) - loWire;
1095  if(indx < nWires) ptOnWire[indx] = true;
1096  } // ipt
1097  } // tjid
1098  if(npwc == 0) return 0;
1099  float nskip = 0;
1100  for(unsigned short indx = 0; indx < nWires; ++indx) if(!ptOnWire[indx]) ++nskip;
1101  return (nskip / npwc);
1102 
1103  } // WiresSkippedInCTP
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool tca::WrongSplitTj ( std::string  inFcnLabel,
TjStuff tjs,
Trajectory tj,
unsigned short  tjEnd,
ShowerStruct ss,
bool  prt 
)

Definition at line 2409 of file TCShower.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::ID, kComp3DVx, tca::TjStuff::vtx, and tca::Trajectory::VtxID.

2410  {
2411  // Returns true if the trajectory was split by a 3D vertex match and the end of this trajectory is further
2412  // away from the shower than the partner trajectory
2413  // Here is a cartoon showing what we are trying to prevent. The shower is represented by a box. The trajectory
2414  // that is shown as (---*---) was originally reconstructed as a single trajectory. It was later split at the * position
2415  // by matching in 3D into two trajectories with ID = 1 and 2. We don't want to consider Tj 1 using end 0 as a parent for
2416  // the shower. Tj is more likely to be the real parent
2417  //
2418  // 1111111111 2222222 TjID
2419  // 0 1 0 1 Tj end
2420  // --------------
2421  // | |
2422  // ----------*------- |
2423  // | |
2424  // --------------
2425  if(!tj.AlgMod[kComp3DVx]) return false;
2426  if(tjEnd > 1) return false;
2427 
2428  std::string fcnLabel = inFcnLabel + ".WSTj";
2429 
2430  // See if the other end is the end that was split. It should have a vertex with Topo = 8 or 11
2431  unsigned short otherEnd = 1 - tjEnd;
2432 // if(prt) mf::LogVerbatim("TC")<<"WSTj: otherEnd "<<otherEnd<<" vtxID "<<tj.VtxID[otherEnd];
2433  if(tj.VtxID[otherEnd] == 0) return false;
2434  unsigned short ivx = tj.VtxID[otherEnd] - 1;
2435  // A vertex exists but not a 3D split vertex
2436  if(tjs.vtx[ivx].Topo != 8 && tjs.vtx[ivx].Topo != 10) return false;
2437  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Primary candidate "<<tj.ID<<" was split by a 3D vertex";
2438  return true;
2439 
2440  } // WrongSplitTj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim

Variable Documentation

constexpr unsigned int tca::Cpad = 10000

Definition at line 43 of file DataStructs.h.

Referenced by DecodeCTP().

const std::vector< std::string > tca::StopFlagNames
Initial value:
{
"Signal",
"AtKink",
"AtVtx",
"Bragg",
"AtTj",
"OutFV"
}

Definition at line 71 of file DataStructs.cxx.

Referenced by PrintStopFlag(), and tca::TrajClusterAlg::reconfigure().

constexpr unsigned int tca::Tpad = 10

Definition at line 42 of file DataStructs.h.

Referenced by DecodeCTP().

const std::vector< std::string > tca::VtxBitNames
Initial value:
{
"VtxTrjTried",
"Fixed",
"OnDeadWire",
"HiVx3Score",
"VtxTruMatch",
"VtxMerged"
}

Definition at line 80 of file DataStructs.cxx.

Referenced by PrintAllTraj().