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

Classes

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  TCConfig
 
struct  TCEvent
 
struct  TCHit
 
struct  TCSlice
 
struct  Tj2Pt
 
struct  TjForecast
 
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 StitchPFPs ()
 
void UpdateMatchStructs (TCSlice &slc, int oldTj, int newTj)
 
void UpdateTp3s (TCSlice &slc, PFPStruct &pfp, int oldTj, int newTj)
 
void FillmAllTraj (TCSlice &slc)
 
bool SetStart (TCSlice &slc, PFPStruct &pfp, bool prt)
 
void FollowTp3s (TCSlice &slc, PFPStruct &pfp, bool prt)
 
bool FitTp3s (TCSlice &slc, const std::vector< TrajPoint3 > &tp3s, Point3_t &pos, Vector3_t &dir, float &rCorr)
 
bool FitTp3s (TCSlice &slc, const std::vector< TrajPoint3 > &tp3s, unsigned short fromPt, unsigned short toPt, Point3_t &pos, Vector3_t &dir, float &rCorr)
 
bool FitTp3 (TCSlice &slc, TrajPoint3 &tp3, const std::vector< Tj2Pt > &tj2pts)
 
void FindCompleteness (TCSlice &slc, PFPStruct &pfp, bool doFit, bool fillTp3s, bool prt)
 
void FindMissedTjsInTp3s (TCSlice &slc, PFPStruct &pfp, std::vector< int > &missTjs, std::vector< float > &missFrac)
 
bool SharesHighScoreVx (TCSlice &slc, 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 (TCSlice &slc, std::vector< int > &tjids, CTP_t inCTP)
 
float LengthInCTP (TCSlice &slc, std::vector< int > &tjids, CTP_t inCTP)
 
bool AddMissedTj (TCSlice &slc, PFPStruct &pfp, unsigned short itj, bool looseCuts, bool prt)
 
bool MergePFPTjs (TCSlice &slc, PFPStruct &pfp, bool prt)
 
void FindXMatches (TCSlice &slc, unsigned short numPlanes, short maxScore, std::vector< MatchStruct > &matVec, bool prt)
 
bool MakeTp3 (TCSlice &slc, 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 (TCSlice &slc, PFPStruct &pfp)
 
void FilldEdx (TCSlice &slc, TrajPoint3 &tp3)
 
float PFPDOCA (const PFPStruct &pfp1, const PFPStruct &pfp2, unsigned short &close1, unsigned short &close2)
 
bool Split3DKink (TCSlice &slc, PFPStruct &pfp, double sep, bool prt)
 
std::vector< unsigned short > FindKinks (TCSlice &slc, PFPStruct &pfp, double sep, bool prt)
 
double KinkAngle (TCSlice &slc, const std::vector< TrajPoint3 > &tp3s, unsigned short atPt, double sep)
 
PFPStruct CreatePFP (TCSlice &slc)
 
void FindPFParticles (TCSlice &slc)
 
bool DefinePFP (std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, bool prt)
 
bool PFPVxTjOK (TCSlice &slc, PFPStruct &pfp, bool prt)
 
bool AnalyzePFP (TCSlice &slc, PFPStruct &pfp, bool prt)
 
void PFPVertexCheck (TCSlice &slc)
 
void DefinePFPParents (TCSlice &slc, bool prt)
 
void DefinePFPParentsTestBeam (TCSlice &slc, bool prt)
 
bool StorePFP (TCSlice &slc, PFPStruct &pfp)
 
bool InsideFV (TCSlice &slc, PFPStruct &pfp, unsigned short end)
 
bool InsideTPC (const 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 (TCSlice &slc, PFPStruct &pfp)
 
float ChgFracBetween (TCSlice &slc, Point3_t pos1, Point3_t pos2)
 
float ChgFracNearEnd (TCSlice &slc, PFPStruct &pfp, unsigned short end)
 
unsigned short FarEnd (TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
 
void PrintTp3 (std::string someText, TCSlice &slc, const TrajPoint3 &tp3)
 
void PrintTp3s (std::string someText, TCSlice &slc, const PFPStruct &pfp, short printPts)
 
float AspectRatio (TCSlice &slc, std::vector< int > &tjids, CTP_t inCTP)
 
void CleanTjs (TCSlice &slc, PFPStruct &pfp, bool prt)
 
double DotProd (const Vector3_t &v1, const Vector3_t &v2)
 
void StepAway (TCSlice &slc, Trajectory &tj)
 
void SetStrategy (TCSlice &slc, Trajectory &tj)
 
void Forecast (TCSlice &slc, Trajectory &tj)
 
void UpdateStiffEl (TCSlice &slc, Trajectory &tj)
 
void UpdateTraj (TCSlice &slc, Trajectory &tj)
 
void CheckStiffEl (TCSlice &slc, Trajectory &tj)
 
void CheckTraj (TCSlice &slc, Trajectory &tj)
 
void AddHits (TCSlice &slc, Trajectory &tj, unsigned short ipt, bool &sigOK)
 
void AddLAHits (TCSlice &slc, Trajectory &tj, unsigned short ipt, bool &sigOK)
 
void ReversePropagate (TCSlice &slc, Trajectory &tj)
 
void GetHitMultiplet (TCSlice &slc, unsigned int theHit, std::vector< unsigned int > &hitsInMultiplet)
 
void GetHitMultiplet (TCSlice &slc, unsigned int theHit, std::vector< unsigned int > &hitsInMultiplet, unsigned short &localIndex)
 
float HitTimeErr (TCSlice &slc, unsigned int iht)
 
float HitsTimeErr2 (TCSlice &slc, const std::vector< unsigned int > &hitVec)
 
void ChkStopEndPts (TCSlice &slc, Trajectory &tj, bool prt)
 
void DefineHitPos (TCSlice &slc, TrajPoint &tp)
 
void FindUseHits (TCSlice &slc, Trajectory &tj, unsigned short ipt, float maxDelta, bool useChg)
 
void FindSoftKink (TCSlice &slc, Trajectory &tj)
 
void FillGaps (TCSlice &slc, Trajectory &tj)
 
void CheckHiMultUnusedHits (TCSlice &slc, Trajectory &tj)
 
void CheckHiMultEndHits (TCSlice &slc, Trajectory &tj)
 
void HiEndDelta (TCSlice &slc, Trajectory &tj)
 
void UpdateDeltaRMS (TCSlice &slc, Trajectory &tj)
 
void MaskBadTPs (TCSlice &slc, Trajectory &tj, float const &maxChi)
 
bool MaskedHitsOK (TCSlice &slc, Trajectory &tj)
 
bool StopIfBadFits (TCSlice &slc, Trajectory &tj)
 
void GottaKink (TCSlice &slc, Trajectory &tj, unsigned short &killPts)
 
void FixTrajBegin (TCSlice &slc, Trajectory &tj)
 
void FixTrajBegin (TCSlice &slc, Trajectory &tj, unsigned short atPt)
 
void FixTrajEnd (TCSlice &slc, Trajectory &tj, unsigned short atPt)
 
bool IsGhost (TCSlice &slc, Trajectory &tj)
 
bool IsGhost (TCSlice &slc, std::vector< unsigned int > &tHits)
 
void EndMerge (TCSlice &slc, CTP_t inCTP, bool lastPass)
 
void MaskTrajEndPoints (TCSlice &slc, Trajectory &tj, unsigned short nPts)
 
void ChkStop (TCSlice &slc, Trajectory &tj)
 
bool ChkMichel (TCSlice &slc, Trajectory &tj, unsigned short &lastGoodPt)
 
void ChkHiChgHits (TCSlice &slc, CTP_t inCTP)
 
void SplitHiChgHits (TCSlice &slc, Trajectory &tj)
 
bool MakeJunkTraj (TCSlice &slc, std::vector< unsigned int > tHits)
 
void SaveCRInfo (TCSlice &slc, PFPStruct &pfp, bool prt, bool fIsRealData)
 
int GetOrigin (TCSlice &slc, PFPStruct &pfp)
 
void ClearCRInfo (TCSlice &slc)
 
void ConfigureMVA (TCConfig &tcc, std::string fMVAShowerParentWeights)
 
bool FindShowerStart (TCSlice &slc, ShowerStruct3D &ss3, bool prt)
 
void Finish3DShowers (TCSlice &slc)
 
bool FindShowers3D (TCSlice &slc)
 
bool Reconcile3D (std::string inFcnLabel, TCSlice &slc, bool parentSearchDone, bool prt)
 
bool Reconcile3D (std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
 
void KillVerticesInShower (std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
 
bool CompleteIncompleteShower (std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
 
void Match2DShowers (std::string inFcnLabel, TCSlice &slc, bool prt)
 
bool UpdateShower (std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
 
bool UpdateShower (std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
 
float Match3DFOM (std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
 
float Match3DFOM (std::string inFcnLabel, TCSlice &slc, int icid, int jcid, int kcid, bool prt)
 
float Match3DFOM (std::string inFcnLabel, TCSlice &slc, int icid, int jcid, bool prt)
 
void MergeTjList (std::vector< std::vector< int >> &tjList)
 
bool RemovePFP (std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, ShowerStruct3D &ss3, bool doUpdate, bool prt)
 
bool AddPFP (std::string inFcnLabel, TCSlice &slc, int pID, ShowerStruct3D &ss3, bool doUpdate, bool prt)
 
bool AddTj (std::string inFcnLabel, TCSlice &slc, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
 
bool RemoveTj (std::string inFcnLabel, TCSlice &slc, int TjID, ShowerStruct &ss, bool doUpdate, bool prt)
 
bool FindParent (std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
 
bool SetParent (std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, ShowerStruct3D &ss3, bool prt)
 
PFPStruct CreateFakePFP (TCSlice &slc, const ShowerStruct3D &ss3)
 
bool IsShowerLike (TCSlice &slc, 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 (TCSlice &slc, const ShowerStruct3D &ss3, const PFPStruct &pfp)
 
float InShowerProb (TCSlice &slc, const ShowerStruct &ss, const Trajectory &tj)
 
float ParentFOM (std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, unsigned short pend, ShowerStruct3D &ss3, bool prt)
 
float ParentFOM (std::string inFcnLabel, TCSlice &slc, Trajectory &tj, unsigned short &tjEnd, ShowerStruct &ss, float &tp1Sep, float &vx2Score, bool prt)
 
bool WrongSplitTj (std::string inFcnLabel, TCSlice &slc, Trajectory &tj, unsigned short tjEnd, ShowerStruct &ss, bool prt)
 
void MergeNearby2DShowers (std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
 
void MergeOverlap (std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
 
void MergeShowerChain (std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
 
void MergeSubShowersTj (std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
 
void MergeSubShowers (std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
 
int MergeShowers (std::string inFcnLabel, TCSlice &slc, std::vector< int > ssIDs, bool prt)
 
bool MergeShowersAndStore (std::string inFcnLabel, TCSlice &slc, int icotID, int jcotID, bool prt)
 
bool MergeShowerTjsAndStore (TCSlice &slc, unsigned short istj, unsigned short jstj, bool prt)
 
bool AnalyzeRotPos (std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
 
void ReverseShower (std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
 
void ReverseShower (std::string inFcnLabel, TCSlice &slc, int cotID, bool prt)
 
void MakeShowerObsolete (std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
 
void MakeShowerObsolete (std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
 
bool DontCluster (TCSlice &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
 
void DefineDontCluster (TCSlice &slc, bool prt)
 
void FindCots (std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, std::vector< std::vector< int >> &tjLists, bool prt)
 
void TagShowerLike (std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP)
 
void FindNearbyTjs (std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
 
void AddCloseTjsToList (TCSlice &slc, unsigned short itj, std::vector< int > list)
 
void DefineEnvelope (std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
 
bool AddTjsInsideEnvelope (std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
 
bool AddLooseHits (TCSlice &slc, int cotID, bool prt)
 
void FindStartChg (std::string inFcnLabel, TCSlice &slc, int cotID, bool prt)
 
std::vector< float > StartChgVec (TCSlice &slc, int cotID, bool prt)
 
void DumpShowerPts (TCSlice &slc, int cotID)
 
bool TransferTjHits (TCSlice &slc, bool prt)
 
int GetCotID (TCSlice &slc, int ShowerTjID)
 
double ShowerEnergy (const ShowerStruct3D &ss3)
 
float ShowerEnergy (TCSlice &slc, const std::vector< int > tjIDs)
 
float ChgToMeV (float chg)
 
bool StoreShower (std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3)
 
bool StoreShower (std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss)
 
ShowerStruct3D CreateSS3 (TCSlice &slc)
 
ShowerStruct CreateSS (TCSlice &slc, const std::vector< int > &tjl)
 
bool ChkAssns (std::string inFcnLabel, TCSlice &slc)
 
void PrintShowers (std::string fcnLabel, TCSlice &slc)
 
void Print2DShowers (std::string someText, TCSlice &slc, CTP_t inCTP, bool printKilledShowers)
 
void PrintShower (std::string someText, TCSlice &slc, const ShowerStruct &ss, bool printHeader, bool printExtras)
 
bool RemovePFP (std::string inFcnLabel, TCSlice &slc, int pID, ShowerStruct3D &ss3, bool doUpdate, bool prt)
 
double InShowerProb (double showerEnergy, double along, double trans)
 
bool AddLooseHits (std::string inFcnLabel, TCSlice &slc, int cotID, bool prt)
 
void DumpShowerPts (std::string inFcnLabel, TCSlice &slc, int cotID)
 
void AddCloseTjsToList (std::string inFcnLabel, TCSlice &slc, unsigned short itj, std::vector< int > list)
 
void MergeTjList2 (std::string inFcnLabel, TCSlice &slc, std::vector< std::vector< int >> &tjList, bool prt)
 
void SaveTjInfo (TCSlice &slc, std::vector< std::vector< int >> &tjList, std::string stageName)
 
void SaveTjInfo (TCSlice &slc, const ShowerStruct &ss, std::string stageName)
 
void SaveTjInfoStuff (TCSlice &slc, Trajectory &tj, int stageNum, std::string stageName)
 
void SaveAllCots (TCSlice &slc, const CTP_t &inCTP, std::string someText)
 
void SaveAllCots (TCSlice &slc, 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 (TCSlice &slc, const CTP_t &inCTP)
 
void Find2DVertices (TCSlice &slc, const CTP_t &inCTP, unsigned short pass)
 
void FindVtxTjs (TCSlice &slc, VtxStore &vx2)
 
void FindNeutralVertices (TCSlice &slc)
 
bool MergeWithVertex (TCSlice &slc, VtxStore &vx, unsigned short oVxID)
 
void ChkVxTjs (TCSlice &slc, const CTP_t &inCTP, bool prt)
 
void FindHammerVertices2 (TCSlice &slc, const CTP_t &inCTP)
 
void FindHammerVertices (TCSlice &slc, const CTP_t &inCTP)
 
void SplitTrajCrossingVertices (TCSlice &slc, CTP_t inCTP)
 
void Find3DVertices (TCSlice &slc)
 
void Match3DVtxTjs (TCSlice &slc, bool prt)
 
unsigned short TPNearVertex (TCSlice &slc, const TrajPoint &tp)
 
bool AttachPFPToVertex (TCSlice &slc, PFPStruct &pfp, unsigned short end, unsigned short vx3ID, bool prt)
 
bool AttachAnyTrajToVertex (TCSlice &slc, unsigned short ivx, bool prt)
 
bool AttachTrajToVertex (TCSlice &slc, Trajectory &tj, VtxStore &vx, bool prt)
 
float TrajPointVertexPull (TCSlice &slc, const TrajPoint &tp, const VtxStore &vx)
 
float VertexVertexPull (TCSlice &slc, const Vtx3Store &vx1, const Vtx3Store &vx2)
 
float VertexVertexPull (TCSlice &slc, const VtxStore &vx1, const VtxStore &vx2)
 
bool StoreVertex (TCSlice &slc, VtxStore &vx)
 
bool FitVertex (TCSlice &slc, VtxStore &vx, bool prt)
 
bool FitVertex (TCSlice &slc, VtxStore &vx, std::vector< TrajPoint > vxTp, bool prt)
 
bool ChkVtxAssociations (TCSlice &slc, const CTP_t &inCTP)
 
void ScoreVertices (TCSlice &slc)
 
void KillPoorVertices (TCSlice &slc)
 
void SetHighScoreBits (TCSlice &slc, Vtx3Store &vx3)
 
void SetVx3Score (TCSlice &slc, Vtx3Store &vx3)
 
void SetVx2Score (TCSlice &slc)
 
void SetVx2Score (TCSlice &slc, VtxStore &vx2)
 
unsigned short Vx3Topo (TCSlice &slc, Vtx3Store &vx3)
 
void CompleteIncomplete3DVerticesInGaps (TCSlice &slc)
 
void CompleteIncomplete3DVertices (TCSlice &slc)
 
void VtxHitsSwap (TCSlice &slc, const CTP_t inCTP)
 
bool MakeVertexObsolete (std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
 
bool MakeVertexObsolete (TCSlice &slc, Vtx3Store &vx3)
 
std::vector< int > GetVtxTjIDs (const TCSlice &slc, const VtxStore &vx2)
 
std::vector< int > GetVtxTjIDs (const TCSlice &slc, const Vtx3Store &vx3, float &score)
 
std::vector< unsigned short > GetPFPVertices (const TCSlice &slc, const PFPStruct &pfp)
 
void PosInPlane (const TCSlice &slc, const Vtx3Store &vx3, unsigned short plane, Point2_t &pos)
 
unsigned short IsCloseToVertex (TCSlice &slc, VtxStore &inVx2)
 
unsigned short IsCloseToVertex (TCSlice &slc, Vtx3Store &vx3)
 
void MakeJunkTjVertices (TCSlice &slc, const CTP_t &inCTP)
 
void MakeHaloTj (TCSlice &slc, Trajectory &muTj, bool prt)
 
void DefineTjParents (TCSlice &slc, bool prt)
 
float MaxChargeAsymmetry (TCSlice &slc, std::vector< int > &tjIDs)
 
int PDGCodeVote (TCSlice &slc, std::vector< int > &tjIDs, bool prt)
 
unsigned short NumDeltaRays (TCSlice &slc, const Trajectory &tj)
 
unsigned short NumDeltaRays (TCSlice &slc, std::vector< int > &tjIDs)
 
int NeutrinoPrimaryTjID (TCSlice &slc, const Trajectory &tj)
 
int PrimaryID (TCSlice &slc, const Trajectory &tj)
 
int PrimaryUID (TCSlice &slc, const PFPStruct &pfp)
 
bool MergeTjIntoPFP (TCSlice &slc, int mtjid, PFPStruct &pfp, bool prt)
 
bool CompatibleMerge (TCSlice &slc, std::vector< int > &tjIDs, bool prt)
 
bool CompatibleMerge (TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, bool prt)
 
float OverlapFraction (TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2)
 
unsigned short AngleRange (TrajPoint const &tp)
 
void SetAngleCode (TrajPoint &tp)
 
unsigned short AngleRange (float angle)
 
void FitTraj (TCSlice &slc, Trajectory &tj)
 
void FitTraj (TCSlice &slc, Trajectory &tj, unsigned short originPt, unsigned short npts, short fitDir, TrajPoint &tpFit)
 
float TjDirFOM (TCSlice &slc, const Trajectory &tj, bool prt)
 
void Reverse3DMatchTjs (TCSlice &slc, PFPStruct &pfp, bool prt)
 
unsigned short GetPFPIndex (TCSlice &slc, int tjID)
 
unsigned short MatchVecIndex (TCSlice &slc, int tjID)
 
void ReleaseHits (TCSlice &slc, Trajectory &tj)
 
void UnsetUsedHits (TCSlice &slc, TrajPoint &tp)
 
bool StoreTraj (TCSlice &slc, Trajectory &tj)
 
void ChgSlope (TCSlice &slc, Trajectory &tj, float &slope, float &slopeErr, float &chiDOF)
 
void ChgSlope (TCSlice &slc, Trajectory &tj, unsigned short fromPt, unsigned short toPt, float &slope, float &slopeErr, float &chiDOF)
 
bool InTrajOK (TCSlice &slc, std::string someText)
 
void CheckTrajBeginChg (TCSlice &slc, unsigned short itj)
 
void TrimEndPts (std::string fcnLabel, TCSlice &slc, Trajectory &tj, const std::vector< float > &fQualityCuts, bool prt)
 
void ChkChgAsymmetry (TCSlice &slc, Trajectory &tj, bool prt)
 
bool SignalBetween (TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2, const float &MinWireSignalFraction)
 
bool SignalBetween (TCSlice &slc, TrajPoint tp, float toPos0, const float &MinWireSignalFraction)
 
float ChgFracBetween (TCSlice &slc, TrajPoint tp, float toPos0)
 
bool TrajHitsOK (TCSlice &slc, const std::vector< unsigned int > &iHitsInMultiplet, const std::vector< unsigned int > &jHitsInMultiplet)
 
bool TrajHitsOK (TCSlice &slc, const unsigned int iht, const unsigned int jht)
 
float ExpectedHitsRMS (TCSlice &slc, const TrajPoint &tp)
 
bool SignalAtTp (TCSlice &slc, const TrajPoint &tp)
 
float TpSumHitChg (TCSlice &slc, TrajPoint const &tp)
 
unsigned short NumPtsWithCharge (TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
 
unsigned short NumPtsWithCharge (TCSlice &slc, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
 
float DeadWireCount (TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
 
float DeadWireCount (TCSlice &slc, const float &inWirePos1, const float &inWirePos2, CTP_t tCTP)
 
unsigned short PDGCodeIndex (int PDGCode)
 
void MakeTrajectoryObsolete (TCSlice &slc, unsigned int itj)
 
void RestoreObsoleteTrajectory (TCSlice &slc, unsigned int itj)
 
void MergeGhostTjs (TCSlice &slc, CTP_t inCTP)
 
bool SplitTraj (TCSlice &slc, unsigned short itj, float XPos, bool makeVx2, bool prt)
 
bool SplitTraj (TCSlice &slc, unsigned short itj, unsigned short pos, unsigned short ivx, bool prt)
 
void TrajPointTrajDOCA (TCSlice &slc, TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
 
bool TrajTrajDOCA (TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
 
bool TrajTrajDOCA (TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep, bool considerDeadWires)
 
float HitSep2 (TCSlice &slc, unsigned int iht, unsigned int jht)
 
unsigned short CloseEnd (TCSlice &slc, const Trajectory &tj, const Point2_t &pos)
 
float PointTrajSep2 (float wire, float time, TrajPoint const &tp)
 
float PointTrajDOCA (TCSlice &slc, unsigned int iht, TrajPoint const &tp)
 
float PointTrajDOCA (TCSlice &slc, float wire, float time, TrajPoint const &tp)
 
float PointTrajDOCA2 (TCSlice &slc, 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 (TCSlice &slc, 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 (TCSlice &slc, Trajectory &tj, bool prt)
 
bool HasDuplicateHits (TCSlice &slc, Trajectory const &tj, bool prt)
 
void MoveTPToWire (TrajPoint &tp, float wire)
 
std::vector< unsigned int > FindCloseHits (TCSlice &slc, std::array< int, 2 > const &wireWindow, Point2_t const &timeWindow, const unsigned short plane, HitStatus_t hitRequest, bool usePeakTime, bool &hitsNear)
 
bool FindCloseHits (TCSlice &slc, TrajPoint &tp, float const &maxDelta, HitStatus_t hitRequest)
 
std::vector< int > FindCloseTjs (TCSlice &slc, const TrajPoint &fromTp, const TrajPoint &toTp, const float &maxDelta)
 
float ElectronLikelihood (TCSlice &slc, Trajectory &tj, float &asym)
 
float ChgFracNearPos (TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
 
float MaxHitDelta (TCSlice &slc, Trajectory &tj)
 
void ReverseTraj (TCSlice &slc, 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 (Trajectory &tj)
 
bool TrajIsClean (TCSlice &slc, Trajectory &tj, bool prt)
 
short MCSMom (TCSlice &slc, const std::vector< int > &tjIDs)
 
short MCSMom (TCSlice &slc, Trajectory &tj)
 
short MCSMom (TCSlice &slc, Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
 
unsigned short NearestPtWithChg (TCSlice &slc, Trajectory &tj, unsigned short thePt)
 
float MCSThetaRMS (TCSlice &slc, Trajectory &tj)
 
double MCSThetaRMS (TCSlice &slc, Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
 
void TjDeltaRMS (TCSlice &slc, Trajectory &tj, unsigned short firstPt, unsigned short lastPt, double &rms, unsigned short &cnt)
 
void TagDeltaRays (TCSlice &slc, const CTP_t &inCTP)
 
void UpdateTjChgProperties (std::string inFcnLabel, TCSlice &slc, Trajectory &tj, bool prt)
 
void UpdateVxEnvironment (std::string inFcnLabel, TCSlice &slc, VtxStore &vx2, bool prt)
 
TrajPoint MakeBareTP (TCSlice &slc, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
 
bool MakeBareTrajPoint (TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
 
bool MakeBareTrajPoint (TCSlice &slc, 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 (TCSlice &slc, const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
 
unsigned short FarEnd (TCSlice &slc, const Trajectory &tj, const Point2_t &pos)
 
Vector2_t PointDirection (const Point2_t p1, const Point2_t p2)
 
float TPHitsRMSTime (TCSlice &slc, TrajPoint &tp, HitStatus_t hitRequest)
 
float TPHitsRMSTick (TCSlice &slc, TrajPoint &tp, HitStatus_t hitRequest)
 
float HitsRMSTime (TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
 
float HitsRMSTick (TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
 
float HitsPosTime (TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, float &sum, HitStatus_t hitRequest)
 
float HitsPosTick (TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, float &sum, HitStatus_t hitRequest)
 
unsigned short NumUsedHitsInTj (TCSlice &slc, const Trajectory &tj)
 
unsigned short NumHitsInTP (const TrajPoint &tp, HitStatus_t hitRequest)
 
void SetPDGCode (TCSlice &slc, unsigned short itj, bool tjDone)
 
void SetPDGCode (TCSlice &slc, Trajectory &tj, bool tjDone)
 
bool AnalyzeHits ()
 
bool LongPulseHit (const recob::Hit &hit)
 
bool FillWireHitRange (TCSlice &slc)
 
bool WireHitRangeOK (TCSlice &slc, const CTP_t &inCTP)
 
bool MergeAndStore (TCSlice &slc, unsigned int itj1, unsigned int itj2, bool doPrt)
 
std::vector< int > GetAssns (TCSlice &slc, std::string type1Name, int id, std::string type2Name)
 
bool StartTraj (TCSlice &slc, Trajectory &tj, unsigned int fromhit, unsigned int tohit, unsigned short pass)
 
bool StartTraj (TCSlice &slc, Trajectory &tj, float fromWire, float fromTick, float toWire, float toTick, CTP_t &tCTP, unsigned short pass)
 
std::pair< unsigned short, unsigned short > GetSliceIndex (std::string typeName, int uID)
 
bool Fit2D (short mode, Point2_t inPt, float &inPtErr, Vector2_t &outVec, Vector2_t &outVecErr, float &chiDOF)
 
bool DecodeDebugString (std::string strng)
 
void DumpTj ()
 
void PrintAll (std::string someText, const std::vector< simb::MCParticle * > &mcpList)
 
void PrintP (std::string someText, mf::LogVerbatim &myprt, PFPStruct &pfp, bool &printHeader)
 
void Print3V (std::string someText, mf::LogVerbatim &myprt, Vtx3Store &vx3)
 
void Print2V (std::string someText, mf::LogVerbatim &myprt, VtxStore &vx2)
 
void Print3S (std::string someText, mf::LogVerbatim &myprt, ShowerStruct3D &ss3)
 
void PrintT (std::string someText, mf::LogVerbatim &myprt, Trajectory &tj, bool &printHeader)
 
void PrintAllTraj (std::string someText, TCSlice &slc, unsigned short itj, unsigned short ipt, bool prtVtx)
 
void PrintTrajectory (std::string someText, TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
 
void PrintHeader (std::string someText)
 
void PrintTrajPoint (std::string someText, TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, TrajPoint const &tp)
 
void PrintPFP (std::string someText, TCSlice &slc, const PFPStruct &pfp, bool printHeader)
 
void PrintPFPs (std::string someText, TCSlice &slc)
 
std::string PrintStopFlag (const Trajectory &tj, unsigned short end)
 
std::string PrintHitShort (const TCHit &tch)
 
std::string PrintHit (const TCHit &tch)
 
std::string PrintPos (TCSlice &slc, const TrajPoint &tp)
 
std::string PrintPos (TCSlice &slc, const Point2_t &pos)
 
bool SignalAtTp (TCSlice &slc, 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, kVtxIndPlnNoChg, 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, kHaloTj,
  kNoFitToVx, kVxMerge, kVxNeutral, kNoKinkChk,
  kSoftKink, kChkStop, kChkStopEP, kChkChgAsym,
  kFTBRvProp, kStopAtTj, kMat3D, kM3DVxTj,
  kMat3DMerge, kSplit3DKink, kTjHiVx3Score, kVtxHitsSwap,
  kSplitHiChgHits, kShowerLike, kKillInShowerVx, kShowerTj,
  kShwrParent, kMergeOverlap, kMergeSubShowers, kMergeSubShowersTj,
  kMergeNrShowers, kMergeShChain, kCompleteShower, kSplitTjCVx,
  kNewStpCuts, kNewVtxCuts, kAlgBitSize
}
 
enum  Strategy_t { kNormal, kStiffEl, kStiffMu, kSlowing }
 
enum  StopFlag_t {
  kSignal, kAtKink, kAtVtx, kBragg,
  kAtTj, kOutFV, kFlagBitSize
}
 
enum  TPEnvironment_t {
  kEnvDeadWire, kEnvNearTj, kEnvNearShower, kEnvOverlap,
  kEnvUnusedHits, kEnvClean, kEnvFlag
}
 
enum  TCModes_t {
  kStepDir, kTestBeam, kDebug, kStudy1,
  kStudy2, kStudy3, kStudy4, kSaveCRTree,
  kTagCosmics, kSaveShowerTree
}
 
TCEvent evt
 
TCConfig tcc
 
std::vector< TjForecasttjfs
 
ShowerTreeVars stv
 
std::vector< TCSliceslices
 
std::vector< TrajPointseeds
 
const std::vector< std::string > AlgBitNames
 
const std::vector< std::string > StopFlagNames
 
const std::vector< std::string > VtxBitNames
 
const std::vector< std::string > StrategyBitNames
 

Detailed Description

TrajClusterAlg

Bruce Baller, balle.nosp@m.r@fn.nosp@m.al.go.nosp@m.v Citation: Liquid argon TPC signal formation, signal processing and reconstruction techniques B. Baller 2017 JINST 12 P07010

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 
kHaloTj 
kNoFitToVx 
kVxMerge 
kVxNeutral 
kNoKinkChk 
kSoftKink 
kChkStop 
kChkStopEP 
kChkChgAsym 
kFTBRvProp 
kStopAtTj 
kMat3D 
kM3DVxTj 
kMat3DMerge 
kSplit3DKink 
kTjHiVx3Score 
kVtxHitsSwap 
kSplitHiChgHits 
kShowerLike 
kKillInShowerVx 
kShowerTj 
kShwrParent 
kMergeOverlap 
kMergeSubShowers 
kMergeSubShowersTj 
kMergeNrShowers 
kMergeShChain 
kCompleteShower 
kSplitTjCVx 
kNewStpCuts 
kNewVtxCuts 
kAlgBitSize 

don't mess with this line

Definition at line 346 of file DataStructs.h.

346  {
347  kMaskHits,
348  kMaskBadTPs,
349  kMichel,
350  kDeltaRay,
351  kCTKink,
352  kCTStepChk,
354  kRvPrp,
355  kCHMUH,
356  kSplit,
357  kComp3DVx,
358  kComp3DVxIG,
359  kHED, // High End Delta
360  kHamVx,
361  kHamVx2,
362  kJunkVx,
363  kJunkTj,
364  kKilled,
365  kMerge,
366  kTEP,
367  kCHMEH,
368  kFillGap,
370  kMrgGhost,
371  kChkInTraj,
372  kStopBadFits,
373  kFixBegin,
374  kFTBChg,
375  kBeginChg,
376  kFixEnd,
377  kUUH,
378  kVtxTj,
379  kChkVxTj,
380  kMisdVxTj,
381  kPhoton,
382  kHaloTj,
383  kNoFitToVx,
384  kVxMerge,
385  kVxNeutral,
386  kNoKinkChk,
387  kSoftKink,
388  kChkStop,
389  kChkStopEP,
390  kChkChgAsym,
391  kFTBRvProp,
392  kStopAtTj,
393  kMat3D,
394  kM3DVxTj,
395  kMat3DMerge,
396  kSplit3DKink,
398  kVtxHitsSwap,
400  kShowerLike,
402  kShowerTj,
403  kShwrParent,
410  kSplitTjCVx,
411  kNewStpCuts,
412  kNewVtxCuts,
413  kAlgBitSize
414  } AlgBit_t;
AlgBit_t
Definition: DataStructs.h:346
kink found in CheckTraj
Definition: DataStructs.h:351
don&#39;t mess with this line
Definition: DataStructs.h:413
Enumerator
kAllHits 
kUsedHits 
kUnusedHits 

Definition at line 36 of file Utils.h.

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

don't mess with this line

Definition at line 424 of file DataStructs.h.

424  {
425  kSignal,
426  kAtKink,
427  kAtVtx,
428  kBragg,
429  kAtTj,
430  kOutFV,
431  kFlagBitSize
432  } StopFlag_t;
don&#39;t mess with this line
Definition: DataStructs.h:431
StopFlag_t
Definition: DataStructs.h:424
Enumerator
kNormal 
kStiffEl 

use the stiff electron strategy

kStiffMu 

use the stiff muon strategy

kSlowing 

use the slowing-down strategy

Definition at line 416 of file DataStructs.h.

416  {
417  kNormal,
418  kStiffEl,
419  kStiffMu,
420  kSlowing
421  } Strategy_t;
Strategy_t
Definition: DataStructs.h:416
use the slowing-down strategy
Definition: DataStructs.h:420
use the stiff electron strategy
Definition: DataStructs.h:418
use the stiff muon strategy
Definition: DataStructs.h:419
Enumerator
kStepDir 

step from US -> DS (true) or DS -> US (false)

kTestBeam 

Expect tracks entering from the front face. Don't create neutrino PFParticles.

kDebug 

master switch for turning on debug mode

kStudy1 

call study functions to develop cuts, etc (see TCTruth.cxx)

kStudy2 

call study functions to develop cuts, etc

kStudy3 

call study functions to develop cuts, etc

kStudy4 

call study functions to develop cuts, etc

kSaveCRTree 

save cosmic ray tree

kTagCosmics 

tag cosmic rays

kSaveShowerTree 

save shower tree

Definition at line 446 of file DataStructs.h.

446  {
447  kStepDir,
448  kTestBeam,
449  kDebug,
450  kStudy1,
451  kStudy2,
452  kStudy3,
453  kStudy4,
454  kSaveCRTree,
455  kTagCosmics,
457  } TCModes_t;
Expect tracks entering from the front face. Don&#39;t create neutrino PFParticles.
Definition: DataStructs.h:448
step from US -> DS (true) or DS -> US (false)
Definition: DataStructs.h:447
call study functions to develop cuts, etc
Definition: DataStructs.h:452
save shower tree
Definition: DataStructs.h:456
call study functions to develop cuts, etc
Definition: DataStructs.h:453
TCModes_t
Definition: DataStructs.h:446
save cosmic ray tree
Definition: DataStructs.h:454
call study functions to develop cuts, etc
Definition: DataStructs.h:451
call study functions to develop cuts, etc (see TCTruth.cxx)
Definition: DataStructs.h:450
master switch for turning on debug mode
Definition: DataStructs.h:449
tag cosmic rays
Definition: DataStructs.h:455
Enumerator
kEnvDeadWire 
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 435 of file DataStructs.h.

435  {
436  kEnvDeadWire,
437  kEnvNearTj,
439  kEnvOverlap,
441  kEnvClean,
442  kEnvFlag
443  } TPEnvironment_t;
a general purpose flag bit used in 3D matching
Definition: DataStructs.h:442
the charge fraction is small near this point
Definition: DataStructs.h:441
TPEnvironment_t
Definition: DataStructs.h:435
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 
kVtxIndPlnNoChg 

vertex quality is suspect - No requirement made on chg btw it and the Tj

kVtxBitSize 

don't mess with this line

Definition at line 72 of file DataStructs.h.

72  {
73  kVtxTrjTried,
74  kFixed,
76  kHiVx3Score,
77  kVtxTruMatch,
78  kVtxMerged,
81  } VtxBit_t;
FindVtxTraj algorithm tried.
Definition: DataStructs.h:73
vertex position fixed manually - no fitting done
Definition: DataStructs.h:74
matched to a high-score 3D vertex
Definition: DataStructs.h:76
VtxBit_t
Definition: DataStructs.h:72
don&#39;t mess with this line
Definition: DataStructs.h:80
tagged as a vertex between Tjs that are matched to MC truth neutrino interaction particles ...
Definition: DataStructs.h:77
vertex quality is suspect - No requirement made on chg btw it and the Tj
Definition: DataStructs.h:79

Function Documentation

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

Definition at line 3840 of file TCShower.cxx.

References tca::Trajectory::MCSMom, tca::TCConfig::showerTag, tca::TCSlice::slHits, tcc, and tca::TCSlice::tjs.

3841  {
3842  // Searches the trajectory points for hits that are used in a different trajectory and add
3843  // them to the list if any are found, and the MCSMomentum is not too large
3844  if(itj > slc.tjs.size() - 1) return;
3845 
3846  //short maxMom = (short)(2 * tcc.showerTag[1]);
3847  short maxMom = tcc.showerTag[1];
3848  //XL: why is maxMom is twice of the shower tag [1]?
3849  for(auto& tp : slc.tjs[itj].Pts) {
3850  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3851  // ignore hits that are used in this trajectory
3852  if(tp.UseHit[ii]) continue;
3853  unsigned int iht = tp.Hits[ii];
3854  // ignore if there is no hit -> Tj association
3855  if(slc.slHits[iht].InTraj <= 0) continue;
3856  if((unsigned int)slc.slHits[iht].InTraj > slc.tjs.size()) continue;
3857  // check the momentum
3858  Trajectory& tj = slc.tjs[slc.slHits[iht].InTraj - 1];
3859  if(tj.MCSMom > maxMom) continue;
3860 // if(tj.AlgMod[kTjHiVx3Score]) continue;
3861  // see if it is already in the list
3862  if(std::find(list.begin(), list.end(), slc.slHits[iht].InTraj) != list.end()) continue;
3863  list.push_back(slc.slHits[iht].InTraj);
3864  } // ii
3865  } // tp
3866  } // AddCloseTjsToList
TCConfig tcc
Definition: DataStructs.cxx:6
std::vector< float > showerTag
[min MCSMom, max separation, min # Tj < separation] for a shower tag
Definition: DataStructs.h:474
void tca::AddHits ( TCSlice slc,
Trajectory tj,
unsigned short  ipt,
bool &  sigOK 
)

Definition at line 1091 of file StepUtils.cxx.

References AddLAHits(), tca::Trajectory::AlgMod, tca::TCEvent::allHits, tca::Trajectory::CTP, tca::TCConfig::dbgStp, DeadWireCount(), DecodeCTP(), DefineHitPos(), tca::TrajPoint::Delta, tca::TrajPoint::DeltaRMS, tca::TrajPoint::Dir, tca::Trajectory::EndPt, evt, ExpectedHitsRMS(), FindUseHits(), tca::TCSlice::firstWire, GetHitMultiplet(), tca::TrajPoint::Hits, tca::Trajectory::ID, kAtTj, kNewStpCuts, kRvPrp, kSlowing, kStiffEl, kStopAtTj, kUsedHits, tca::TCSlice::lastWire, LongPulseHit(), MoveTPToWire(), NumHitsInTP(), geo::PlaneID::Plane, PointTrajDOCA(), tca::TrajPoint::Pos, PrintHit(), tca::TCConfig::projectionErrFactor, tca::Trajectory::Pts, SetEndPoints(), tca::TCSlice::slHits, tca::Trajectory::StopFlag, tca::Trajectory::Strategy, tcc, tca::TCConfig::unitsPerTick, tca::TCConfig::useAlg, tca::TrajPoint::UseHit, and tca::TCSlice::wireHitRange.

Referenced by cluster::ClusterAndHitMerger::Add(), tca::TrajClusterAlg::ReconstructAllTraj(), and StepAway().

1092  {
1093  // Try to add hits to the trajectory point ipt on the supplied
1094  // trajectory
1095 
1096  // assume failure
1097  sigOK = false;
1098 
1099  if(tj.Pts.empty()) return;
1100  if(ipt > tj.Pts.size() - 1) return;
1101 
1102  // Call large angle hit finding if the last tp is large angle
1103  if(tj.Pts[ipt].AngleCode == 2) {
1104  AddLAHits(slc, tj, ipt, sigOK);
1105  return;
1106  }
1107 
1108  TrajPoint& tp = tj.Pts[ipt];
1109  std::vector<unsigned int> closeHits;
1110  unsigned int lastPtWithUsedHits = tj.EndPt[1];
1111 
1112  unsigned short plane = DecodeCTP(tj.CTP).Plane;
1113  unsigned int wire = std::nearbyint(tp.Pos[0]);
1114  if(wire < slc.firstWire[plane] || wire > slc.lastWire[plane]-1) return;
1115  // Move the TP to this wire
1116  MoveTPToWire(tp, (float)wire);
1117 
1118  // find the projection error to this point. Note that if this is the first
1119  // TP, lastPtWithUsedHits = 0, so the projection error is 0
1120  float dw = tp.Pos[0] - tj.Pts[lastPtWithUsedHits].Pos[0];
1121  float dt = tp.Pos[1] - tj.Pts[lastPtWithUsedHits].Pos[1];
1122  float dpos = sqrt(dw * dw + dt * dt);
1123  float projErr = dpos * tj.Pts[lastPtWithUsedHits].AngErr;
1124  // Add this to the Delta RMS factor and construct a cut
1125  float deltaCut = 3 * (projErr + tp.DeltaRMS);
1126 
1127  if(tcc.useAlg[kNewStpCuts]) {
1128  // The delta cut shouldn't be less than the delta of hits added on the previous step
1129  float minDeltaCut = 1.1 * tj.Pts[lastPtWithUsedHits].Delta;
1130  if(deltaCut < minDeltaCut) deltaCut = minDeltaCut;
1131  }
1132 
1133  deltaCut *= tcc.projectionErrFactor;
1134  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" AddHits: calculated deltaCut "<<deltaCut<<" dw "<<dw<<" dpos "<<dpos;
1135 
1136  if(deltaCut < 0.5) deltaCut = 0.5;
1137  if(deltaCut > 3) deltaCut = 3;
1138 
1139  // TY: open it up for RevProp, since we might be following a stopping track
1140  if(tj.AlgMod[kRvPrp]) deltaCut *= 2;
1141 
1142  // loosen up a bit if we just passed a block of dead wires
1143  bool passedDeadWires = (abs(dw) > 20 && DeadWireCount(slc, tp.Pos[0], tj.Pts[lastPtWithUsedHits].Pos[0], tj.CTP) > 10);
1144  if(passedDeadWires) deltaCut *= 2;
1145  // open it up for StiffEl and Slowing strategies
1146  if(tj.Strategy[kStiffEl] || tj.Strategy[kSlowing]) deltaCut = 2.5;
1147 
1148  // Create a larger cut to use in case there is nothing close
1149  float bigDelta = 2 * deltaCut;
1150  unsigned int imBig = UINT_MAX;
1151  tp.Delta = deltaCut;
1152  // ignore all hits with delta larger than maxDeltaCut
1153  float maxDeltaCut = 2 * bigDelta;
1154  // apply some limits
1155  if(tcc.useAlg[kNewStpCuts] && !passedDeadWires && maxDeltaCut > 3) {
1156  maxDeltaCut = 3;
1157  bigDelta = 1.5;
1158  }
1159 
1160  // projected time in ticks for testing the existence of a hit signal
1161  raw::TDCtick_t rawProjTick = (float)(tp.Pos[1] / tcc.unitsPerTick);
1162  if(tcc.dbgStp) {
1163  mf::LogVerbatim("TC")<<" AddHits: wire "<<wire<<" tp.Pos[0] "<<tp.Pos[0]<<" projTick "<<rawProjTick<<" deltaRMS "<<tp.DeltaRMS<<" tp.Dir[0] "<<tp.Dir[0]<<" deltaCut "<<deltaCut<<" dpos "<<dpos<<" projErr "<<projErr<<" ExpectedHitsRMS "<<ExpectedHitsRMS(slc, tp);
1164  }
1165 
1166  std::vector<unsigned int> hitsInMultiplet;
1167 
1168  geo::PlaneID planeID = DecodeCTP(tj.CTP);
1169  unsigned int ipl = planeID.Plane;
1170  if(wire > slc.lastWire[ipl]) return;
1171  // Assume a signal exists on a dead wire
1172  if(slc.wireHitRange[ipl][wire].first == -1) sigOK = true;
1173  if(slc.wireHitRange[ipl][wire].first < 0) return;
1174  unsigned int firstHit = (unsigned int)slc.wireHitRange[ipl][wire].first;
1175  unsigned int lastHit = (unsigned int)slc.wireHitRange[ipl][wire].second;
1176  float fwire = wire;
1177  for(unsigned int iht = firstHit; iht < lastHit; ++iht) {
1178  if(slc.slHits[iht].InTraj == tj.ID) continue;
1179  if(slc.slHits[iht].InTraj == SHRT_MAX) continue;
1180  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1181  if(rawProjTick > hit.StartTick() && rawProjTick < hit.EndTick()) sigOK = true;
1182  float ftime = tcc.unitsPerTick * hit.PeakTime();
1183  float delta = PointTrajDOCA(slc, fwire, ftime, tp);
1184  // increase the delta cut if this is a long pulse hit
1185  bool longPulseHit = LongPulseHit(hit);
1186  if(tcc.useAlg[kNewStpCuts] && longPulseHit) {
1187  if(delta > 3) continue;
1188  } else {
1189  if(delta > maxDeltaCut) continue;
1190  }
1191  float dt = std::abs(ftime - tp.Pos[1]);
1192  unsigned short localIndex = 0;
1193  GetHitMultiplet(slc, iht, hitsInMultiplet, localIndex);
1194  if(tcc.dbgStp && delta < 100 && dt < 100) {
1195  mf::LogVerbatim myprt("TC");
1196  myprt<<" iht "<<iht;
1197  myprt<<" "<<PrintHit(slc.slHits[iht]);
1198  myprt<<" delta "<<std::fixed<<std::setprecision(2)<<delta<<" deltaCut "<<deltaCut<<" dt "<<dt;
1199  myprt<<" BB Mult "<<hitsInMultiplet.size()<<" localIndex "<<localIndex<<" RMS "<<std::setprecision(1)<<hit.RMS();
1200  myprt<<" Chi "<<std::setprecision(1)<<hit.GoodnessOfFit();
1201  myprt<<" InTraj "<<slc.slHits[iht].InTraj;
1202  myprt<<" Chg "<<(int)hit.Integral();
1203  myprt<<" Signal? "<<sigOK;
1204  }
1205  if(slc.slHits[iht].InTraj == 0 && delta < bigDelta && hitsInMultiplet.size() < 3 && !tj.AlgMod[kRvPrp]) {
1206  // An available hit that is just outside the window that is not part of a large multiplet
1207  bigDelta = delta;
1208  imBig = iht;
1209  }
1210  if(tcc.useAlg[kNewStpCuts] && longPulseHit) {
1211  if(delta > 3) continue;
1212  } else {
1213  if(delta > deltaCut) continue;
1214  }
1215 
1216  if(std::find(closeHits.begin(), closeHits.end(), iht) != closeHits.end()) continue;
1217  closeHits.push_back(iht);
1218  if(hitsInMultiplet.size() > 1) {
1219  // include all the hits in a multiplet
1220  for(auto& jht : hitsInMultiplet) {
1221  if(slc.slHits[jht].InTraj == tj.ID) continue;
1222  if(std::find(closeHits.begin(), closeHits.end(), jht) != closeHits.end()) continue;
1223  closeHits.push_back(jht);
1224  } // jht
1225  } // multiplicity > 1
1226  } // iht
1227 
1228  if(tcc.dbgStp) {
1229  mf::LogVerbatim myprt("TC");
1230  myprt<<"closeHits ";
1231  for(auto iht : closeHits) myprt<<" "<<PrintHit(slc.slHits[iht]);
1232  if(imBig < slc.slHits.size()) {
1233  myprt<<" imBig "<<PrintHit(slc.slHits[imBig]);
1234  } else {
1235  myprt<<" imBig "<<imBig;
1236  }
1237  }
1238  if(closeHits.empty() && imBig == UINT_MAX) {
1239  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" no signal on any wire at tp.Pos "<<tp.Pos[0]<<" "<<tp.Pos[1]<<" tick "<<(int)tp.Pos[1]/tcc.unitsPerTick<<" closeHits size "<<closeHits.size();
1240  return;
1241  }
1242  if(imBig < slc.slHits.size() && closeHits.empty()) {
1243  closeHits.push_back(imBig);
1244  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Added bigDelta hit "<<PrintHit(slc.slHits[imBig])<<" w delta = "<<bigDelta;
1245  }
1246  if(!closeHits.empty()) sigOK = true;
1247  if(!sigOK) return;
1248  if(closeHits.size() > 16) closeHits.resize(16);
1249  tp.Hits.insert(tp.Hits.end(), closeHits.begin(), closeHits.end());
1250 
1251  // reset UseHit and assume that none of these hits will be used (yet)
1252  tp.UseHit.reset();
1253  if(tcc.useAlg[kStopAtTj]) {
1254  // don't continue if we have run into another trajectory and there are no available hits
1255  unsigned short nAvailable = 0;
1256  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1257  auto& tcHit = slc.slHits[tp.Hits[ii]];
1258  if(tcHit.InTraj == 0) ++nAvailable;
1259  } // ii
1260  if(nAvailable == 0) {
1261  tj.StopFlag[1][kAtTj] = true;
1262  return;
1263  }
1264  } // stop at Tj
1265  // decide which of these hits should be used in the fit. Use a generous maximum delta
1266  // and require a charge check if we'not just starting out
1267  bool useChg = true;
1268  if(tj.Strategy[kStiffEl] || tj.Strategy[kSlowing]) useChg = false;
1269  FindUseHits(slc, tj, ipt, 10, useChg);
1270  DefineHitPos(slc, tp);
1271  SetEndPoints(tj);
1272  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" number of close hits "<<closeHits.size()<<" used hits "<<NumHitsInTP(tp, kUsedHits);
1273  } // AddHits
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
void FindUseHits(TCSlice &slc, Trajectory &tj, unsigned short ipt, float maxDelta, bool useChg)
Definition: StepUtils.cxx:1923
float ExpectedHitsRMS(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:1802
bool LongPulseHit(const recob::Hit &hit)
Definition: Utils.cxx:3936
float DeadWireCount(TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:1881
int TDCtick_t
Type representing a TDC tick.
Definition: RawTypes.h:24
float projectionErrFactor
Definition: DataStructs.h:501
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
use the slowing-down strategy
Definition: DataStructs.h:420
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1840
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:5704
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
unsigned short NumHitsInTP(const TrajPoint &tp, HitStatus_t hitRequest)
Definition: Utils.cxx:3775
Detector simulation of raw signals on wires.
void AddLAHits(TCSlice &slc, Trajectory &tj, unsigned short ipt, bool &sigOK)
Definition: StepUtils.cxx:1277
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
use the stiff electron strategy
Definition: DataStructs.h:418
void GetHitMultiplet(TCSlice &slc, unsigned int theHit, std::vector< unsigned int > &hitsInMultiplet, unsigned short &localIndex)
Definition: StepUtils.cxx:1580
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2485
TCEvent evt
Definition: DataStructs.cxx:5
void tca::AddLAHits ( TCSlice slc,
Trajectory tj,
unsigned short  ipt,
bool &  sigOK 
)

Definition at line 1277 of file StepUtils.cxx.

References tca::TrajPoint::Ang, tca::TrajPoint::AngleCode, tca::Trajectory::CTP, tca::TCConfig::dbgStp, DecodeCTP(), DefineHitPos(), DeltaAngle(), tca::TrajPoint::Dir, FindCloseHits(), tca::TrajPoint::Hits, tca::Trajectory::ID, kAllHits, kAtTj, kStopAtTj, tca::TCSlice::lastWire, geo::PlaneID::Plane, tca::TrajPoint::Pos, PrintHit(), PrintPos(), tca::Trajectory::Pts, PutTrajHitsInVector(), SetEndPoints(), tca::TCSlice::slHits, tca::Trajectory::StopFlag, tcc, tca::TCSlice::tjs, tca::TCConfig::unitsPerTick, UpdateTjChgProperties(), tca::TCConfig::useAlg, tca::TrajPoint::UseHit, tca::TCConfig::VLAStepSize, and tca::TCSlice::wireHitRange.

Referenced by AddHits().

1278  {
1279  // Very Large Angle version of AddHits to be called for the last angle range
1280 
1281  if(ipt > tj.Pts.size() - 1) return;
1282  TrajPoint& tp = tj.Pts[ipt];
1283  tp.Hits.clear();
1284  tp.UseHit.reset();
1285  sigOK = false;
1286 
1287  unsigned short plane = DecodeCTP(tj.CTP).Plane;
1288 
1289  // look at adjacent wires for larger angle trajectories
1290  // We will check the most likely wire first
1291  std::vector<int> wires(1);
1292  wires[0] = std::nearbyint(tp.Pos[0]);
1293  if(wires[0] < 0 || wires[0] > (int)slc.lastWire[plane]-1) return;
1294 
1295  if(tp.AngleCode != 2) {
1296  mf::LogVerbatim("TC")<<"AddLAHits called with a bad angle code. "<<tp.AngleCode<<" Don't do this";
1297  return;
1298  }
1299  // and the adjacent wires next in the most likely order only
1300  // after the first two points have been defined
1301  if(ipt > 1) {
1302  if(tp.Dir[0] > 0) {
1303  if(wires[0] < (int)slc.lastWire[plane]-1) wires.push_back(wires[0] + 1);
1304  if(wires[0] > 0) wires.push_back(wires[0] - 1);
1305  } else {
1306  if(wires[0] > 0) wires.push_back(wires[0] - 1);
1307  if(wires[0] < (int)slc.lastWire[plane]-1) wires.push_back(wires[0] + 1);
1308  }
1309  } // ipt > 0 ...
1310 
1311  if(tcc.dbgStp) {
1312  mf::LogVerbatim myprt("TC");
1313  myprt<<" AddLAHits: Pos "<<PrintPos(slc, tp)<<" tp.AngleCode "<<tp.AngleCode<<" Wires under consideration";
1314  for(auto& wire : wires) myprt<<" "<<wire;
1315  }
1316 
1317  // a temporary tp that we can move around
1318  TrajPoint ltp = tp;
1319  // do this while testing
1320  sigOK = false;
1321 
1322  tp.Hits.clear();
1323  std::array<int, 2> wireWindow;
1324  std::array<float, 2> timeWindow;
1325  float pos1Window = tcc.VLAStepSize/2;
1326  timeWindow[0] = ltp.Pos[1] - pos1Window;
1327  timeWindow[1] = ltp.Pos[1] + pos1Window;
1328  // Put the existing hits in to a vector so we can ensure that they aren't added again
1329  std::vector<unsigned int> oldHits = PutTrajHitsInVector(tj, kAllHits);
1330 
1331  for(unsigned short ii = 0; ii < wires.size(); ++ii) {
1332  int wire = wires[ii];
1333  if(wire < 0 || wire > (int)slc.lastWire[plane]) continue;
1334  // Assume a signal exists on a dead wire
1335  if(slc.wireHitRange[plane][wire].first == -1) sigOK = true;
1336  if(slc.wireHitRange[plane][wire].first < 0) continue;
1337  wireWindow[0] = wire;
1338  wireWindow[1] = wire;
1339  bool hitsNear;
1340  // Look for hits using the requirement that the timeWindow overlaps with the hit StartTick and EndTick
1341  std::vector<unsigned int> closeHits = FindCloseHits(slc, wireWindow, timeWindow, plane, kAllHits, true, hitsNear);
1342  if(hitsNear) sigOK = true;
1343  for(auto& iht : closeHits) {
1344  // Ensure that none of these hits are already used by this trajectory
1345  if(slc.slHits[iht].InTraj == tj.ID) continue;
1346  // or in another trajectory in any previously added point
1347  if(std::find(oldHits.begin(), oldHits.end(), iht) != oldHits.end()) continue;
1348  tp.Hits.push_back(iht);
1349  }
1350  } // ii
1351 
1352  if(tcc.dbgStp) {
1353  mf::LogVerbatim myprt("TC");
1354  myprt<<" LAPos "<<PrintPos(slc, ltp)<<" Tick window "<<(int)(timeWindow[0]/tcc.unitsPerTick)<<" to "<<(int)(timeWindow[1]/tcc.unitsPerTick);
1355  for(auto& iht : tp.Hits) myprt<<" "<<PrintHit(slc.slHits[iht]);
1356  } // prt
1357 
1358  // no hits found
1359  if(tp.Hits.empty()) return;
1360 
1361  if(tp.Hits.size() > 16) tp.Hits.resize(16);
1362 
1363  tp.UseHit.reset();
1364 
1365  if(tcc.useAlg[kStopAtTj]) {
1366  // don't continue if we have run into another trajectory that has a similar angle
1367  unsigned short nAvailable = 0;
1368  unsigned int otherTjHit = INT_MAX;
1369  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1370  auto& tcHit = slc.slHits[tp.Hits[ii]];
1371  if(tcHit.InTraj == SHRT_MAX) continue;
1372  if(tcHit.InTraj > 0) {
1373  otherTjHit = tp.Hits[ii];
1374  continue;
1375  }
1376  ++nAvailable;
1377  } // ii
1378  if(nAvailable == 0 && otherTjHit != UINT_MAX) {
1379  // get the trajectory index
1380  unsigned short otherTj = slc.slHits[otherTjHit].InTraj - 1;
1381  Trajectory& otj = slc.tjs[otherTj];
1382  // find out what point the hit is in
1383  unsigned short atPt = USHRT_MAX;
1384  for(unsigned short ipt = 0; ipt < otj.Pts.size(); ++ipt) {
1385  for(auto& iht : otj.Pts[ipt].Hits) {
1386  if(iht == otherTjHit) {
1387  atPt = ipt;
1388  break;
1389  } // iht == otherTjHit
1390  } // iht
1391  if(atPt != USHRT_MAX) break;
1392  } // ipt
1393  if(atPt != USHRT_MAX && DeltaAngle(tp.Ang, otj.Pts[atPt].Ang) < 0.1) {
1394  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Found a VLA merge candidate trajectory "<<otj.ID<<". Set StopFlag[kAtTj] and stop stepping";
1395  tj.StopFlag[1][kAtTj] = true;
1396  return;
1397  } // atPt is valid
1398  } // nAvailable == 0 &&
1399  } // stop at Tj
1400 
1401  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1402  unsigned int iht = tp.Hits[ii];
1403  if(slc.slHits[iht].InTraj != 0) continue;
1404  tp.UseHit[ii] = true;
1405  slc.slHits[iht].InTraj = tj.ID;
1406  } // ii
1407  DefineHitPos(slc, tp);
1408  SetEndPoints(tj);
1409  UpdateTjChgProperties("ALAH", slc, tj, tcc.dbgStp);
1410 
1411  } // AddLAHits
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
TCConfig tcc
Definition: DataStructs.cxx:6
std::vector< unsigned int > PutTrajHitsInVector(Trajectory const &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2416
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1636
std::vector< unsigned int > FindCloseHits(TCSlice &slc, std::array< int, 2 > const &wireWindow, Point2_t const &timeWindow, const unsigned short plane, HitStatus_t hitRequest, bool usePeakTime, bool &hitsNear)
Definition: Utils.cxx:2496
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1840
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:5704
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3196
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
float VLAStepSize
Definition: DataStructs.h:502
geo::PlaneID DecodeCTP(CTP_t CTP)
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
bool tca::AddLooseHits ( std::string  inFcnLabel,
TCSlice slc,
int  cotID,
bool  prt 
)
bool tca::AddLooseHits ( TCSlice slc,
int  cotID,
bool  prt 
)

Definition at line 4002 of file TCShower.cxx.

References tca::TCEvent::allHits, tca::TCSlice::cots, tca::ShowerStruct::CTP, DecodeCTP(), tca::ShowerStruct::Envelope, evt, tca::TrajPoint::Hits, tca::Trajectory::ID, tca::ShowerStruct::ID, tca::TCSlice::lastWire, geo::PlaneID::Plane, PointInsideEnvelope(), tca::Trajectory::Pts, tca::ShowerStruct::ShowerTjID, tca::TCSlice::slHits, ss, tcc, tca::ShowerStruct::TjIDs, tca::TCSlice::tjs, tca::TCConfig::unitsPerTick, and tca::TCSlice::wireHitRange.

4003  {
4004  // Add hits that are inside the envelope to the shower if they are loose, i.e. not
4005  // used by any trajectory. This function returns true if the set of hits is different than
4006  // the current set. The calling function should update the shower if this is the case.
4007 
4008  ShowerStruct& ss = slc.cots[cotID - 1];
4009  if(ss.Envelope.empty()) return false;
4010  if(ss.ID == 0) return false;
4011  if(ss.TjIDs.empty()) return false;
4012 
4013  geo::PlaneID planeID = DecodeCTP(ss.CTP);
4014  unsigned short ipl = planeID.Plane;
4015 
4016  Trajectory& stj = slc.tjs[ss.ShowerTjID - 1];
4017  TrajPoint& stp0 = stj.Pts[0];
4018  // start a list of new hits
4019  std::vector<unsigned int> newHits;
4020 
4021  // look for hits inside the envelope. Find the range of wires that spans the envelope
4022  float fLoWire = 1E6;
4023  float fHiWire = 0;
4024  // and the range of ticks
4025  float loTick = 1E6;
4026  float hiTick = 0;
4027  for(auto& vtx : ss.Envelope) {
4028  if(vtx[0] < fLoWire) fLoWire = vtx[0];
4029  if(vtx[0] > fHiWire) fHiWire = vtx[0];
4030  if(vtx[1] < loTick) loTick = vtx[1];
4031  if(vtx[1] > hiTick) hiTick = vtx[1];
4032  } // vtx
4033  loTick /= tcc.unitsPerTick;
4034  hiTick /= tcc.unitsPerTick;
4035  unsigned int loWire = std::nearbyint(fLoWire);
4036  unsigned int hiWire = std::nearbyint(fHiWire) + 1;
4037  if(hiWire > slc.lastWire[ipl]-1) hiWire = slc.lastWire[ipl]-1;
4038  std::array<float, 2> point;
4039  for(unsigned int wire = loWire; wire < hiWire; ++wire) {
4040  // skip bad wires or no hits on the wire
4041  if(slc.wireHitRange[ipl][wire].first < 0) continue;
4042  unsigned int firstHit = (unsigned int)slc.wireHitRange[ipl][wire].first;
4043  unsigned int lastHit = (unsigned int)slc.wireHitRange[ipl][wire].second;
4044  for(unsigned int iht = firstHit; iht < lastHit; ++iht) {
4045  // used in a trajectory?
4046  if(slc.slHits[iht].InTraj != 0) continue;
4047  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
4048  // inside the tick range?
4049  if(hit.PeakTime() < loTick) continue;
4050  // Note that hits are sorted by increasing time so we can break here
4051  if(hit.PeakTime() > hiTick) break;
4052  // see if this hit is inside the envelope
4053  point[0] = hit.WireID().Wire;
4054  point[1] = hit.PeakTime() * tcc.unitsPerTick;
4055  if(!PointInsideEnvelope(point, ss.Envelope)) continue;
4056  newHits.push_back(iht);
4057  } // iht
4058  } // wire
4059 
4060  // no new hits and no old hits. Nothing to do
4061  if(newHits.empty()) {
4062  if(prt) mf::LogVerbatim("TC")<<"ALH: No new loose hits found";
4063  return false;
4064  }
4065 
4066  // Update
4067  stp0.Hits.insert(stp0.Hits.end(), newHits.begin(), newHits.end());
4068  for(auto& iht: newHits) slc.slHits[iht].InTraj = stj.ID;
4069 
4070  if(prt) mf::LogVerbatim("TC")<<"ALH: Added "<<stp0.Hits.size()<<" hits to stj "<<stj.ID;
4071  return true;
4072 
4073  } // AddLooseHits
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
Float_t ss
Definition: plot.C:23
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:2781
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)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
bool tca::AddMissedTj ( TCSlice slc,
PFPStruct pfp,
unsigned short  itj,
bool  looseCuts,
bool  prt 
)

Definition at line 1159 of file PFPUtils.cxx.

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

1160  {
1161  // The Tj pfp.TjIDs[itj] has poor completeness. Search matchVec for
1162  // the occurrence of this tj with a large completeness AND the occurrence
1163  // of another tj in pfp.TjIDs.
1164  if(itj > pfp.TjIDs.size() - 1) return false;
1165  if(slc.matchVec.empty()) return false;
1166 
1167  int theTj = pfp.TjIDs[itj];
1168 // bool pfpInShower = (pfp.PDGCode == 11);
1169 
1170  unsigned short oldSize = pfp.TjIDs.size();
1171 
1172  for(unsigned int ims = 0; ims < slc.matchVec.size(); ++ims) {
1173  auto& ms = slc.matchVec[ims];
1174  // look for theTj in the match struct
1175  unsigned short tjIndex = 0;
1176  for(tjIndex = 0; tjIndex < ms.TjIDs.size(); ++tjIndex) if(ms.TjIDs[tjIndex] == theTj) break;
1177  if(tjIndex == ms.TjIDs.size()) continue;
1178  auto shared = SetIntersection(pfp.TjIDs, ms.TjIDs);
1179  if(shared.empty()) continue;
1180  if(looseCuts) {
1181  // Look for shared size at least 2 (theTj and another tj) or size 1 and higher TjCompleteness
1182  bool isWorse = (ms.TjCompleteness[tjIndex] < pfp.TjCompleteness[itj]);
1183  if(shared.size() < 2 && isWorse) continue;
1184  } else {
1185  // Look for shared size at least 2 (theTj and another tj in pfp.TjIDs)
1186  if(shared.size() < 2) continue;
1187  }
1188  // Add the tjs that are not in pfp.TjIDs
1189  for(auto tjid : ms.TjIDs) {
1190  if(std::find(pfp.TjIDs.begin(), pfp.TjIDs.end(), tjid) != pfp.TjIDs.end()) continue;
1191  pfp.TjIDs.push_back(tjid);
1192  // check vertex - tj consistency
1193  if(PFPVxTjOK(slc, pfp, prt)) continue;
1194  pfp.TjCompleteness.push_back(0);
1195  if(prt) mf::LogVerbatim("TC")<<"AMT: P"<<pfp.ID<<" T"<<theTj<<" Add T"<<tjid;
1196  } // mtjid
1197  } // ims
1198  if(pfp.TjIDs.size() > oldSize) return true;
1199  return false;
1200  } // AddMissedTj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:231
bool PFPVxTjOK(TCSlice &slc, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:2366
bool tca::AddPFP ( std::string  inFcnLabel,
TCSlice slc,
int  pID,
ShowerStruct3D ss3,
bool  doUpdate,
bool  prt 
)

Definition at line 1498 of file TCShower.cxx.

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

Referenced by Reconcile3D().

1499  {
1500  // Add the tjs in the pfp with id = pID to the 2D showers in ss3 and optionally update everything. This
1501  // function returns true if the addition was successful or if the Tjs in the pfp are already in ss3.
1502  // This function returns false if there was a failure. There isn't any error recovery.
1503 
1504  std::string fcnLabel = inFcnLabel + ".AddP";
1505 
1506  if(pID <= 0 || pID > (int)slc.pfps.size()) return false;
1507  auto& pfp = slc.pfps[pID - 1];
1508 
1509  if(pfp.TPCID != ss3.TPCID) {
1510  mf::LogVerbatim("TC")<<fcnLabel<<" P"<<pID<<" is in the wrong TPC for 3S"<<ss3.ID;
1511  return false;
1512  }
1513 
1514  for(auto tid : pfp.TjIDs) {
1515  auto& tj = slc.tjs[tid - 1];
1516  // is this tj in a 2D shower that is in a 3D shower that is not this shower?
1517  if(tj.SSID > 0) {
1518  auto& ss = slc.cots[tj.SSID - 1];
1519  if(ss.SS3ID > 0 && ss.SS3ID != ss3.ID) {
1520  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";
1521  return false;
1522  } // conflict
1523  // tj is in the correct 2D shower so nothing needs to be done
1524  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" adding P"<<pfp.ID<<" -> T"<<tid<<" is in the correct shower 2S"<<tj.SSID;
1525  continue;
1526  } // pfp tj is in a shower
1527  if(prt) {
1528  mf::LogVerbatim myprt("TC");
1529  myprt<<fcnLabel<<" 3S"<<ss3.ID<<" adding P"<<pfp.ID<<" -> T"<<tid;
1530  for(unsigned short ii = 0; ii < pfp.TjIDs.size(); ++ii) {
1531  if(pfp.TjIDs[ii] == tid) myprt<<" pfp TjCompleteness "<<std::fixed<<std::setprecision(2)<<pfp.TjCompleteness[ii];
1532  } // itj
1533  myprt<<" tj.SSID 2S"<<tj.SSID;
1534  } // prt
1535  // add it to the shower in the correct CTP
1536  for(auto& cid : ss3.CotIDs) {
1537  auto& ss = slc.cots[cid - 1];
1538  if(ss.CTP != tj.CTP) continue;
1539  // Add it to the shower.
1540  AddTj(fcnLabel, slc, tid, ss, doUpdate, prt);
1541  ss3.NeedsUpdate = true;
1542  break;
1543  } // cid
1544  } // tid
1545 
1546  if(doUpdate && ss3.NeedsUpdate) UpdateShower(fcnLabel, slc, ss3, prt);
1547  return true;
1548 
1549  } // AddPFP
bool AddTj(std::string inFcnLabel, TCSlice &slc, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1552
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
Float_t ss
Definition: plot.C:23
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1230
bool tca::AddTj ( std::string  inFcnLabel,
TCSlice slc,
int  tjID,
ShowerStruct ss,
bool  doUpdate,
bool  prt 
)

Definition at line 1552 of file TCShower.cxx.

References tca::TCEvent::allHits, tca::TrajPoint::Chg, tca::Trajectory::CTP, tca::ShowerStruct::CTP, tca::Trajectory::EndPt, evt, tca::TrajPoint::Hits, tca::Trajectory::ID, tca::ShowerStruct::ID, tca::ShowerStruct::NearTjIDs, tca::ShowerStruct::NeedsUpdate, tca::Trajectory::Pts, tca::ShowerStruct::ShPts, tca::TCSlice::slHits, tca::Trajectory::SSID, tcc, tca::ShowerStruct::TjIDs, tca::TCSlice::tjs, tca::TCConfig::unitsPerTick, UpdateShower(), and tca::TrajPoint::UseHit.

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

1553  {
1554  // Adds the Tj to the shower and optionally updates the shower variables
1555 
1556  if(tjID <= 0 || tjID > (int)slc.tjs.size()) return false;
1557 
1558  std::string fcnLabel = inFcnLabel + ".AddT";
1559 
1560  Trajectory& tj = slc.tjs[tjID - 1];
1561 
1562  if(tj.CTP != ss.CTP) {
1563  mf::LogVerbatim("TC")<<fcnLabel<<" T"<<tjID<<" is in the wrong CTP for 2S"<<ss.ID;
1564  return false;
1565  }
1566 
1567  if(tj.SSID > 0) {
1568  if(tj.SSID == ss.ID) {
1569  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" T"<<tjID<<" is already in 2S"<<ss.ID;
1570  return true;
1571  } else {
1572  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Can't add T"<<tjID<<" to 2S"<<ss.ID<<". it is already used in 2S"<<tj.SSID;
1573  return false;
1574  }
1575  } // tj.SSID > 0
1576 
1577  ss.TjIDs.push_back(tjID);
1578  tj.SSID = ss.ID;
1579  std::sort(ss.TjIDs.begin(), ss.TjIDs.end());
1580  // remove this ID from the NearTjIDs list
1581  for(unsigned short ii = 0; ii < ss.NearTjIDs.size(); ++ii) {
1582  if(ss.NearTjIDs[ii] == tjID) ss.NearTjIDs.erase(ss.NearTjIDs.begin() + ii);
1583  }
1584  // count the hits in the TPs
1585  unsigned short cnt = 0;
1586  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1587  TrajPoint& tp = tj.Pts[ipt];
1588  if(tp.Chg == 0) continue;
1589  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) if(tp.UseHit[ii]) ++cnt;
1590  } // ipt
1591  unsigned short newSize = ss.ShPts.size() + cnt;
1592  cnt = ss.ShPts.size();
1593  ss.ShPts.resize(newSize);
1594  // now add them
1595  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1596  TrajPoint& tp = tj.Pts[ipt];
1597  if(tp.Chg == 0) continue;
1598  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1599  if(tp.UseHit[ii]) {
1600  unsigned int iht = tp.Hits[ii];
1601  ss.ShPts[cnt].HitIndex = iht;
1602  ss.ShPts[cnt].TID = tj.ID;
1603  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1604  ss.ShPts[cnt].Chg = hit.Integral();
1605  ss.ShPts[cnt].Pos[0] = hit.WireID().Wire;
1606  ss.ShPts[cnt].Pos[1] = hit.PeakTime() * tcc.unitsPerTick;
1607  ++cnt;
1608  }
1609  }
1610  } // ipt
1611  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Added T"<<tj.ID<<" to 2S"<<ss.ID;
1612  ss.NeedsUpdate = true;
1613 
1614  if(doUpdate) return UpdateShower(fcnLabel, slc, ss, prt);
1615  return true;
1616 
1617  } // AddTj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
Float_t ss
Definition: plot.C:23
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1230
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
bool tca::AddTjsInsideEnvelope ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct ss,
bool  prt 
)

Definition at line 3929 of file TCShower.cxx.

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

Referenced by FindShowers3D().

3930  {
3931  // This function adds Tjs to the shower. It updates the shower parameters.
3932 
3933  if(ss.Envelope.empty()) return false;
3934  if(ss.ID == 0) return false;
3935  if(ss.TjIDs.empty()) return false;
3936 
3937  std::string fcnLabel = inFcnLabel + ".ATIE";
3938 
3939  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Checking 2S"<<ss.ID;
3940 
3941  std::vector<int> tmp(1);
3942  unsigned short nadd = 0;
3943  for(auto& tj : slc.tjs) {
3944  if(tj.CTP != ss.CTP) continue;
3945  if(tj.AlgMod[kKilled]) continue;
3946  if(tj.SSID > 0) continue;
3947  if(tj.AlgMod[kShowerTj]) continue;
3948  // See if this Tjs is attached to a neutrino vertex.
3949  if(tj.ParentID == 0) continue;
3950  int neutPrimTj = NeutrinoPrimaryTjID(slc, tj);
3951  if(neutPrimTj > 0 && neutPrimTj != tj.ID) {
3952  // The Tj is connected to a primary Tj that is associated with a neutrino primary.
3953  // Don't allow tjs to be added to the shower that are not connected to this neutrino primary (if
3954  // one exists)
3955  if(ss.ParentID > 0 && neutPrimTj != ss.ParentID) continue;
3956  } // neutrino primary tj
3957  // This shouldn't be necessary but ensure that the Tj ID appears only once in ss.TjIDs
3958  if(std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tj.ID) != ss.TjIDs.end()) continue;
3959  // check consistency
3960  tmp[0] = tj.ID;
3961  if(DontCluster(slc, tmp, ss.TjIDs)) continue;
3962  // See if both ends are outside the envelope
3963  bool end0Inside = PointInsideEnvelope(tj.Pts[tj.EndPt[0]].Pos, ss.Envelope);
3964  bool end1Inside = PointInsideEnvelope(tj.Pts[tj.EndPt[1]].Pos, ss.Envelope);
3965  if(!end0Inside && !end1Inside) continue;
3966  if(end0Inside && end1Inside) {
3967  // TODO: See if the Tj direction is compatible with the shower?
3968  if(AddTj(fcnLabel, slc, tj.ID, ss, false, prt)) ++nadd;
3969  ++nadd;
3970  continue;
3971  } // both ends inside
3972  // Require high momentum Tjs be aligned with the shower axis
3973  // TODO also require high momentum Tjs close to the shower axis?
3974 
3975  if(tj.MCSMom > 200) {
3976  float tjAngle = tj.Pts[tj.EndPt[0]].Ang;
3977  float dangPull = std::abs(tjAngle - ss.AngleErr) / ss.AngleErr;
3978  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" high MCSMom "<<tj.MCSMom<<" dangPull "<<dangPull;
3979  if(dangPull > 2) continue;
3980  } // high momentum
3981  if(AddTj(fcnLabel, slc, tj.ID, ss, false, prt)) {
3982  ++nadd;
3983  } else {
3984  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" AddTj failed to add T"<<tj.ID;
3985  }
3986  } // tj
3987 
3988  if(nadd > 0) {
3989  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Added "<<nadd<<" trajectories ";
3990  ss.NeedsUpdate = true;
3991  UpdateShower(fcnLabel, slc, ss, prt);
3992  return true;
3993  } else {
3994  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" No new trajectories added to envelope ";
3995  ss.NeedsUpdate = false;
3996  return false;
3997  }
3998 
3999  } // AddTjsInsideEnvelope
bool AddTj(std::string inFcnLabel, TCSlice &slc, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1552
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
int NeutrinoPrimaryTjID(TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:441
Float_t ss
Definition: plot.C:23
Float_t tmp
Definition: plot.C:37
bool DontCluster(TCSlice &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3313
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1230
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:2781
bool tca::AnalyzeHits ( )

Definition at line 3877 of file Utils.cxx.

References tca::TCEvent::allHits, tca::TCEvent::aveHitRMS, tca::TCEvent::aveHitRMSValid, evt, tca::TCConfig::geom, kDebug, tca::TCConfig::modes, geo::GeometryCore::Nplanes(), and tcc.

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

3878  {
3879  // Find the average hit rms by analyzing the full hit collection. This
3880  // only needs to be done once per job.
3881 
3882  if((*evt.allHits).empty()) return false;
3883  // no sense re-calculating it if it's been done
3884  if(evt.aveHitRMSValid) return true;
3885 
3886  unsigned short cstat = (*evt.allHits)[0].WireID().Cryostat;
3887  unsigned short tpc = (*evt.allHits)[0].WireID().TPC;
3888 
3889  unsigned short nplanes = tcc.geom->Nplanes(tpc, cstat);
3890  evt.aveHitRMS.resize(nplanes);
3891  std::vector<float> cnt(nplanes, 0);
3892  for(unsigned short iht = 0; iht < (*evt.allHits).size(); ++iht) {
3893  auto& hit = (*evt.allHits)[iht];
3894  unsigned short plane = hit.WireID().Plane;
3895  if(plane > nplanes - 1) {
3896  std::cout<<"AnalyzeHits found bad plane\n";
3897  return false;
3898  } // plane check
3899  if(cnt[plane] > 200) continue;
3900  // require multiplicity one
3901  if(hit.Multiplicity() != 1) continue;
3902  // not-crazy Chisq/DOF
3903  if(hit.GoodnessOfFit() < 0 || hit.GoodnessOfFit() > 500) continue;
3904  // don't let a lot of runt hits screw up the calculation
3905  if(hit.PeakAmplitude() < 1) continue;
3906  evt.aveHitRMS[plane] += hit.RMS();
3907  ++cnt[plane];
3908  // quit if enough hits are found
3909  bool allDone = true;
3910  for(unsigned short plane = 0; plane < nplanes; ++plane) if(cnt[plane] < 200) allDone = false;
3911  if(allDone) break;
3912  } // iht
3913 
3914  // assume there are enough hits in each plane
3915  evt.aveHitRMSValid = true;
3916  for(unsigned short plane = 0; plane < nplanes; ++plane) {
3917  if(cnt[plane] > 4) {
3918  evt.aveHitRMS[plane] /= cnt[plane];
3919  } else {
3920  evt.aveHitRMS[plane] = 10;
3921  evt.aveHitRMSValid = false;
3922  } // cnt too low
3923  } // plane
3924 
3925  if(tcc.modes[kDebug]) {
3926  std::cout<<"Analyze hits aveHitRMS";
3927  std::cout<<std::fixed<<std::setprecision(1);
3928  for(auto rms : evt.aveHitRMS) std::cout<<" "<<rms;
3929  std::cout<<" aveHitRMSValid? "<<evt.aveHitRMSValid<<"\n";
3930  }
3931 
3932  return true;
3933  } // Analyze hits
TCConfig tcc
Definition: DataStructs.cxx:6
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
std::vector< float > aveHitRMS
average RMS of an isolated hit
Definition: DataStructs.h:541
const geo::GeometryCore * geom
Definition: DataStructs.h:493
Detector simulation of raw signals on wires.
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
bool aveHitRMSValid
set true when the average hit RMS is well-known
Definition: DataStructs.h:549
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
master switch for turning on debug mode
Definition: DataStructs.h:449
bool tca::AnalyzePFP ( TCSlice slc,
PFPStruct pfp,
bool  prt 
)

Definition at line 2421 of file PFPUtils.cxx.

References DefinePFP(), tca::PFPStruct::ID, kMat3D, tca::PFPStruct::NeedsUpdate, NumPtsWithCharge(), tca::PFPStruct::PDGCode, PFPVxTjOK(), tca::PFPStruct::TjCompleteness, tca::PFPStruct::TjIDs, tca::TCSlice::tjs, and tca::PFPStruct::Tp3s.

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

2422  {
2423  // Analyzes the PFP for oddities and tries to fix them
2424  if(pfp.ID == 0) return false;
2425  if(pfp.TjIDs.empty()) return false;
2426  if(pfp.Tp3s.empty()) return false;
2427 
2428  // don't bother analyzing this pfp has been altered
2429  if(pfp.NeedsUpdate) {
2430  if(prt) mf::LogVerbatim("TC")<<"AnalyzePFP: P"<<pfp.ID<<" needs to be updated. Skip analysis ";
2431  return true;
2432  }
2433 
2434  // check the tj completeness
2435  float minCompleteness = 0.95;
2436  for(auto tjc : pfp.TjCompleteness) if(tjc < minCompleteness) minCompleteness = tjc;
2437  if(prt) mf::LogVerbatim("TC")<<"inside AnalyzePFP P"<<pfp.ID<<" minCompleteness "<<minCompleteness;
2438  if(minCompleteness == 0.95) return true;
2439  // don't analyze electrons
2440  if(pfp.PDGCode == 111) return true;
2441 
2442  // compare the Tjs in Tp3s with those in TjIDs
2443  std::vector<int> tjIDs;
2444  std::vector<unsigned short> tjCnt;
2445  for(auto& tp3 : pfp.Tp3s) {
2446  for(auto& tp2 : tp3.Tj2Pts) {
2447  // convert to int for std::find
2448  int itjID = tp2.id;
2449  unsigned short indx = 0;
2450  for(indx = 0; indx < tjIDs.size(); ++indx) if(tjIDs[indx] == tp2.id) break;
2451  if(indx == tjIDs.size()) {
2452  tjIDs.push_back(itjID);
2453  tjCnt.push_back(1);
2454  } else {
2455  ++tjCnt[indx];
2456  }
2457  } // tp2
2458  } // tp3
2459 
2460  // look for differences
2461  for(unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2462  if(std::find(pfp.TjIDs.begin(), pfp.TjIDs.end(), tjIDs[ii]) != pfp.TjIDs.end()) continue;
2463  auto& missTj = slc.tjs[tjIDs[ii] - 1];
2464  if(missTj.AlgMod[kMat3D]) continue;
2465  unsigned short npwc = NumPtsWithCharge(slc, missTj, false);
2466  if(prt) mf::LogVerbatim("TC")<<" missed T"<<missTj.ID<<" npwc "<<npwc<<" tjCnt "<<tjCnt[ii];
2467  if(tjCnt[ii] < 0.5 * npwc) continue;
2468  // June 4, 2018. 3D merging is turned off so require the missed tj to be in
2469  // a missing plane
2470  bool skipit = false;
2471  for(auto tid : pfp.TjIDs) {
2472  auto& tj = slc.tjs[tid - 1];
2473  if(tj.CTP == missTj.CTP) skipit = true;
2474  } // tid
2475  if(skipit) continue;
2476  // add the missed Tj to the pfp and flag it as needing an update
2477  pfp.TjIDs.push_back(missTj.ID);
2478  if(PFPVxTjOK(slc, pfp, prt)) pfp.NeedsUpdate = true;
2479  } // ii
2480 
2481  if(pfp.NeedsUpdate) DefinePFP("APFP", slc, pfp, prt);
2482 
2483  if(prt) {
2484  mf::LogVerbatim myprt("TC");
2485  myprt<<"APFP: Tjs in pfp\n";
2486  for(auto tjid : pfp.TjIDs) {
2487  auto& tj = slc.tjs[tjid - 1];
2488  myprt<<"T"<<tj.ID<<" npwc "<<NumPtsWithCharge(slc, tj, false);
2489  unsigned short indx = 0;
2490  for(indx = 0; indx < tjIDs.size(); ++indx) if(tjIDs[indx] == tjid) break;
2491  if(indx == tjIDs.size()) {
2492  myprt<<" not found in P"<<pfp.ID<<"\n";
2493  continue;
2494  }
2495  myprt<<" nTp3 "<<tjCnt[indx]<<"\n";
2496  } // tjid
2497  } // prt
2498  return true;
2499  } // AnalyzePFP
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool DefinePFP(std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:2233
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
bool PFPVxTjOK(TCSlice &slc, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:2366
bool tca::AnalyzeRotPos ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct ss,
bool  prt 
)

Definition at line 3102 of file TCShower.cxx.

References tca::ShowerStruct::DirectionFOM, tca::ShowerStruct::ID, tca::Trajectory::Pts, tca::ShowerStruct::ShowerTjID, tca::ShowerStruct::ShPts, and tca::TCSlice::tjs.

Referenced by UpdateShower().

3103  {
3104  // The RotPos vector was filled and sorted by increasing distance along the shower axis.
3105  // This function divides the RotPos points into 3 sections and puts the transverse rms width in the
3106  // three sections into the shower Tj TrajPoint DeltaRMS variable. It also calculates the charge and number of shower
3107  // points closest to each TrajPoint. The
3108 
3109  if(ss.ID == 0) return false;
3110  if(ss.ShPts.empty()) return false;
3111  Trajectory& stj = slc.tjs[ss.ShowerTjID - 1];
3112  if(stj.Pts.size() != 3) return false;
3113 
3114  std::string fcnLabel = inFcnLabel + ".ARP";
3115 
3116  for(auto& tp : stj.Pts) {
3117  tp.Chg = 0;
3118  tp.DeltaRMS = 0;
3119  tp.NTPsFit = 0;
3120  tp.HitPos = {{0.0, 0.0}};
3121  }
3122 
3123  float minAlong = ss.ShPts[0].RotPos[0];
3124  float maxAlong = ss.ShPts[ss.ShPts.size()-1].RotPos[0];
3125  float sectionLength = (maxAlong - minAlong) / 3;
3126  float sec0 = minAlong + sectionLength;
3127  float sec2 = maxAlong - sectionLength;
3128  // iterate over the shower points (aka hits)
3129  for(auto& spt : ss.ShPts) {
3130  // The point on the shower Tj to which the charge will assigned
3131  unsigned short ipt = 0;
3132  if(spt.RotPos[0] < sec0) {
3133  // closest to point 0
3134  ipt = 0;
3135  } else if(spt.RotPos[0] > sec2) {
3136  // closest to point 2
3137  ipt = 2;
3138  } else {
3139  // closest to point 1
3140  ipt = 1;
3141  }
3142  stj.Pts[ipt].Chg += spt.Chg;
3143 /*
3144  if(ss.ID == 2) {
3145  std::cout<<"2S"<<ss.ID;
3146  std::cout<<" Pos "<<PrintPos(slc, spt.Pos);
3147  std::cout<<" RP "<<std::fixed<<std::setprecision(1)<<spt.RotPos[0]<<" "<<spt.RotPos[1];
3148  std::cout<<" chg "<<(int)spt.Chg;
3149  std::cout<<" ipt "<<ipt;
3150  std::cout<<"\n";
3151  }
3152 */
3153  // Average the absolute value of the transverse position in lieu of
3154  // using the sum of the squares. The result is ~15% higher than the actual
3155  // rms which is OK since this is used to find the transverse size of the shower
3156  // which is not a precisely defined quantity anyway
3157  stj.Pts[ipt].DeltaRMS += spt.Chg * std::abs(spt.RotPos[1]);
3158  ++stj.Pts[ipt].NTPsFit;
3159  // Average the charge center at each point
3160  stj.Pts[ipt].HitPos[0] += spt.Chg * spt.Pos[0];
3161  stj.Pts[ipt].HitPos[1] += spt.Chg * spt.Pos[1];
3162  } // spt
3163 
3164  for(auto& tp : stj.Pts) {
3165  if(tp.Chg > 0) {
3166  tp.DeltaRMS /= tp.Chg;
3167  tp.HitPos[0] /= tp.Chg;
3168  tp.HitPos[1] /= tp.Chg;
3169  }
3170  } // tp
3171 
3172  // require that there is charge in point 0 and 2. Point 1 may not have charge if
3173  // we are constructing a sparse shower that is not yet well-defined
3174  if(stj.Pts[0].Chg == 0 || stj.Pts[2].Chg == 0) return false;
3175 
3176  // ensure that the charge center is defined
3177  if(stj.Pts[1].Chg == 0) {
3178  // do a simple interpolation
3179  stj.Pts[1].HitPos[0] = 0.5 * (stj.Pts[0].HitPos[0] + stj.Pts[2].HitPos[0]);
3180  stj.Pts[1].HitPos[1] = 0.5 * (stj.Pts[0].HitPos[1] + stj.Pts[2].HitPos[1]);
3181  }
3182  if(stj.Pts[2].DeltaRMS > 0) {
3183  ss.DirectionFOM = stj.Pts[0].DeltaRMS / stj.Pts[2].DeltaRMS;
3184  } else {
3185  ss.DirectionFOM = 10;
3186  }
3187  if(prt) {
3188  mf::LogVerbatim myprt("TC");
3189  myprt<<fcnLabel<<" 2S"<<ss.ID;
3190  myprt<<" HitPos[0] "<<std::fixed<<std::setprecision(1);
3191  myprt<<stj.Pts[1].HitPos[0]<<" "<<stj.Pts[1].HitPos[1]<<" "<<stj.Pts[1].HitPos[2];
3192  myprt<<" DeltaRMS "<<std::setprecision(2);
3193  myprt<<stj.Pts[0].DeltaRMS<<" "<<stj.Pts[1].DeltaRMS<<" "<<stj.Pts[2].DeltaRMS;
3194  myprt<<" DirectionFOM "<<std::fixed<<std::setprecision(2)<<ss.DirectionFOM;
3195  }
3196  return true;
3197 
3198  } // AnalyzeRotPos
Float_t ss
Definition: plot.C:23
unsigned short tca::AngleRange ( TrajPoint const &  tp)

Definition at line 716 of file Utils.cxx.

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

Referenced by CheckHiMultUnusedHits().

717  {
718  return AngleRange(tp.Ang);
719  }
unsigned short AngleRange(float angle)
Definition: Utils.cxx:739
unsigned short tca::AngleRange ( float  angle)

Definition at line 739 of file Utils.cxx.

References tca::TCConfig::angleRanges, and tcc.

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

740  {
741  // returns the index of the angle range
742  if(angle > M_PI) angle = M_PI;
743  if(angle < -M_PI) angle = M_PI;
744  if(angle < 0) angle = -angle;
745  if(angle > M_PI/2) angle = M_PI - angle;
746  for(unsigned short ir = 0; ir < tcc.angleRanges.size(); ++ir) {
747  if(angle < tcc.angleRanges[ir]) return ir;
748  }
749  return tcc.angleRanges.size() - 1;
750  } // AngleRange
TCConfig tcc
Definition: DataStructs.cxx:6
std::vector< float > angleRanges
list of max angles for each angle range
Definition: DataStructs.h:486
float tca::AspectRatio ( TCSlice slc,
std::vector< int > &  tjids,
CTP_t  inCTP 
)
bool tca::AttachAnyTrajToVertex ( TCSlice slc,
unsigned short  ivx,
bool  prt 
)

Definition at line 1868 of file TCVertex.cxx.

References AttachTrajToVertex(), tca::VtxStore::CTP, tca::VtxStore::ID, kHaloTj, kKilled, tcc, tca::TCSlice::tjs, tca::VtxStore::Topo, tca::TCConfig::vtx2DCuts, and tca::TCSlice::vtxs.

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

1869  {
1870 
1871  if(ivx > slc.vtxs.size() - 1) return false;
1872  if(slc.vtxs[ivx].ID == 0) return false;
1873  if(tcc.vtx2DCuts[0] < 0) return false;
1874 
1875  VtxStore& vx = slc.vtxs[ivx];
1876  // Hammer vertices should be isolated and clean
1877  if(vx.Topo == 5 || vx.Topo == 6) return false;
1878 
1879  unsigned short nadd = 0;
1880  for(auto& tj : slc.tjs) {
1881  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
1882  if(tj.CTP != vx.CTP) continue;
1883  if(tj.VtxID[0] == vx.ID || tj.VtxID[1] == vx.ID) continue;
1884  if(AttachTrajToVertex(slc, tj, vx, prt)) ++nadd;
1885  } // tj
1886  if(prt) mf::LogVerbatim("TC")<<" AttachAnyTrajToVertex: nadd "<<nadd;
1887  if(nadd == 0) return false;
1888  return true;
1889 
1890  } // AttachAnyTrajToVertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
bool AttachTrajToVertex(TCSlice &slc, Trajectory &tj, VtxStore &vx, bool prt)
Definition: TCVertex.cxx:1893
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:466
bool tca::AttachPFPToVertex ( TCSlice slc,
PFPStruct pfp,
unsigned short  end,
unsigned short  vx3ID,
bool  prt 
)

Definition at line 1830 of file TCVertex.cxx.

References DecodeCTP(), evd::details::end(), tca::PFPStruct::ID, tca::PFPStruct::PDGCode, tca::TCSlice::pfps, geo::PlaneID::Plane, PosInPlane(), tca::PFPStruct::TjIDs, tca::TCSlice::tjs, tca::TCSlice::vtx3s, and tca::PFPStruct::Vx3ID.

1831  {
1832  if(vx3ID > int(slc.vtx3s.size())) return false;
1833  if(pfp.ID > int(slc.pfps.size())) return false;
1834  if(pfp.PDGCode == 22) return false;
1835  if(end > 1) return false;
1836 
1837  auto& vx3 = slc.vtx3s[vx3ID - 1];
1838 
1839  pfp.Vx3ID[end] = vx3.ID;
1840 
1841  // We are done if this a PFP-only vertex
1842  if(vx3.Wire == -2) return true;
1843 
1844  // Update the 2D and 3D vertex and tj associations
1845  for(auto tjid : pfp.TjIDs) {
1846  auto& tj = slc.tjs[tjid - 1];
1847  unsigned short plane = DecodeCTP(tj.CTP).Plane;
1848  // TODO: Check to see if the Tjs have been ordered correctly?
1849  if(tj.VtxID[end] == 0) {
1850  // tj is available to be attached to a 2D vertex. See if the 3D vertex is matched to
1851  // an existing 2D vertex in this plane
1852  if(vx3.Vx2ID[plane] == 0) {
1853  // not matched. Look for one
1854  std::array<float, 2> pos;
1855  PosInPlane(slc, vx3, plane, pos);
1856 // if(prt) std::cout<<" tj "<<tj.ID<<" has no 2D vertex. Look for one vertex near "<<tj.CTP<<":"<<PrintPos(slc, pos)<<" Events processed "<<slc.EventsProcessed<<"\n";
1857  } else {
1858  // Existing 2D vertex matched to the 3D vertex
1859 // 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 "<<slc.EventsProcessed<<"\n";
1860  }
1861  }
1862  } // tjid
1863 
1864  return true;
1865  } // AttachPFPToVertex
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void PosInPlane(const TCSlice &slc, const Vtx3Store &vx3, unsigned short plane, Point2_t &pos)
Definition: TCVertex.cxx:3287
bool tca::AttachTrajToVertex ( TCSlice slc,
Trajectory tj,
VtxStore vx,
bool  prt 
)

Definition at line 1893 of file TCVertex.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::ChgRMS, tca::VtxStore::CTP, tca::Trajectory::CTP, evd::details::end(), tca::Trajectory::EndPt, FitVertex(), tca::VtxStore::ID, tca::Trajectory::ID, kFixed, kHaloTj, kKilled, kNewVtxCuts, kNoFitToVx, kPhoton, tca::VtxStore::NTraj, tca::VtxStore::Pos, PosSep2(), tca::Trajectory::Pts, SetVx2Score(), SignalBetween(), tca::VtxStore::Stat, tcc, tca::TCSlice::tjs, TrajClosestApproach(), TrajLength(), TrajPointVertexPull(), tca::TCConfig::useAlg, tca::TCConfig::vtx2DCuts, and tca::Trajectory::VtxID.

Referenced by AttachAnyTrajToVertex(), and StepAway().

1894  {
1895  // Note that this function does not require a signal between the end of the Tj and the vertex
1896 
1897  // tcc.vtx2DCuts fcl input usage
1898  // 0 = maximum length of a short trajectory
1899  // 1 = max vertex - trajectory separation for short trajectories
1900  // 2 = max vertex - trajectory separation for long trajectories
1901  // 3 = max position pull for adding TJs to a vertex
1902  // 4 = max allowed vertex position error
1903  // 5 = min MCSMom
1904  // 6 = min Pts/Wire fraction
1905 
1906  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) return false;
1907  if(tj.CTP != vx.CTP) return false;
1908  // already attached?
1909  if(tj.VtxID[0] == vx.ID || tj.VtxID[1] == vx.ID) return false;
1910 
1911  unsigned short maxShortTjLen = tcc.vtx2DCuts[0];
1912  // square the separation cut to simplify testing in the loop
1913  float maxSepCutShort2 = tcc.vtx2DCuts[1] * tcc.vtx2DCuts[1];
1914  float maxSepCutLong2 = tcc.vtx2DCuts[2] * tcc.vtx2DCuts[2];
1915 
1916  // assume that end 0 is closest to the vertex
1917  unsigned short end = 0;
1918  float vtxTjSep2 = PosSep2(vx.Pos, tj.Pts[tj.EndPt[0]].Pos);
1919  float sep1 = PosSep2(vx.Pos, tj.Pts[tj.EndPt[1]].Pos);
1920  if(sep1 < vtxTjSep2) {
1921  // End 1 is closer
1922  end = 1;
1923  vtxTjSep2 = sep1;
1924  }
1925  // is there a vertex already assigned to this end?
1926  if(tj.VtxID[end] > 0) return false;
1927 
1928  // is the trajectory short?
1929  bool tjShort = (tj.EndPt[1] - tj.EndPt[0] < maxShortTjLen);
1930  // use the short Tj cut if the trajectory looks like an electron
1931  if(tcc.useAlg[kNewVtxCuts] && !tjShort && tj.ChgRMS > 0.5) tjShort = true;
1932  float closestApproach;
1933  // ignore bad separation between the closest tj end and the vertex
1934  if(tjShort) {
1935  if(vtxTjSep2 > maxSepCutShort2) return false;
1936  closestApproach = tcc.vtx2DCuts[1];
1937  } else {
1938  closestApproach = tcc.vtx2DCuts[2];
1939  if(vtxTjSep2 > maxSepCutLong2) return false;
1940  }
1941 
1942  // Calculate the pull on the vertex
1943  TrajPoint& tp = tj.Pts[tj.EndPt[end]];
1944  float tpVxPull = TrajPointVertexPull(slc, tp, vx);
1945  bool signalBetween = SignalBetween(slc, tp, vx.Pos[0], 0.8);
1946 
1947  // See if the vertex position is close to an end
1948  unsigned short closePt;
1949  TrajClosestApproach(tj, vx.Pos[0], vx.Pos[1], closePt, closestApproach);
1950  // count the number of points between the end of the trajectory and the vertex.
1951  // tj ------------- tj ------------
1952  // vx * >> dpt = 0 vx * >> dpt = 2
1953  short dpt;
1954  if(end == 0) {
1955  dpt = closePt - tj.EndPt[end];
1956  } else {
1957  dpt = tj.EndPt[end] - closePt;
1958  }
1959 
1960  float length = TrajLength(tj);
1961  // don't attach it if the tj length is shorter than the separation distance
1962  if(length > 4 && length < closestApproach) return false;
1963 
1964  float pullCut = tcc.vtx2DCuts[3];
1965  // Dec 21, 2017 Loosen up the pull cut for short close slc. These are likely to
1966  // be poorly reconstructed. It is better to have them associated with the vertex
1967  // than not. Oct 5, 2018 This was too loose.
1968  if(tcc.useAlg[kNewVtxCuts]) {
1969  if(tjShort) pullCut *= 2;
1970  } else {
1971  if(tjShort) pullCut = 10;
1972  }
1973 
1974  if(prt) {
1975  mf::LogVerbatim myprt("TC");
1976  myprt<<"ATTV: 2V"<<vx.ID;
1977  myprt<<" NTraj "<<vx.NTraj;
1978  myprt<<" oldTJs";
1979  for(unsigned short itj = 0; itj < slc.tjs.size(); ++itj) {
1980  Trajectory& tj = slc.tjs[itj];
1981  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
1982  if(tj.CTP != vx.CTP) continue;
1983  if(tj.VtxID[0] == vx.ID) myprt<<" T"<<tj.ID<<"_0";
1984  if(tj.VtxID[1] == vx.ID) myprt<<" T"<<tj.ID<<"_1";
1985  }
1986  myprt<<" + T"<<tj.ID<<"_"<<end<<" vtxTjSep "<<sqrt(vtxTjSep2)<<" tpVxPull "<<tpVxPull<<" pullCut "<<pullCut<<" dpt "<<dpt;
1987  }
1988 // if(tpVxPull > tcc.vtx2DCuts[3]) return false;
1989  if(tpVxPull > pullCut) return false;
1990  if(dpt > 2) return true;
1991 
1992  // remove the fixed position flag if there are more than 2 tjs
1993  bool fixedBit = vx.Stat[kFixed];
1994  if(fixedBit && vx.NTraj < 2) vx.Stat[kFixed] = false;
1995 
1996  // don't allow a short Tj with a large pull to bias the fit
1997  if(tjShort && tpVxPull > tcc.vtx2DCuts[3]) tj.AlgMod[kNoFitToVx] = true;
1998 
1999  // Passed all the cuts. Attach it to the vertex and try a fit
2000  tj.VtxID[end] = vx.ID;
2001  // flag as a photon Tj so it isn't included in the fit
2002  tj.AlgMod[kPhoton] = !signalBetween;
2003  // make a copy of the vertex and fit it
2004  auto vxTmp = vx;
2005  if(FitVertex(slc, vxTmp, prt)) {
2006  SetVx2Score(slc, vxTmp);
2007  if(prt) mf::LogVerbatim("TC")<<" Success";
2008  vx = vxTmp;
2009  return true;
2010  }
2011 
2012  // fit failed so remove the tj -> vx assignment if it is long and
2013  // set noFitToVtx if it is short
2014  if(tjShort) {
2015  tj.AlgMod[kNoFitToVx] = true;
2016  if(prt) mf::LogVerbatim("TC")<<" Poor fit. Keep short Tj "<<tj.ID<<" with kNoFitToVx";
2017  return true;
2018  } else {
2019  tj.VtxID[end] = 0;
2020  // restore the fixed flag
2021  vx.Stat[kFixed] = fixedBit;
2022  if(prt) mf::LogVerbatim("TC")<<" Poor fit. Removed Tj "<<tj.ID;
2023  return false;
2024  }
2025 
2026  } // AttachTrajToVertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool FitVertex(TCSlice &slc, VtxStore &vx, std::vector< TrajPoint > vxTp, bool prt)
Definition: TCVertex.cxx:2184
TCConfig tcc
Definition: DataStructs.cxx:6
vertex position fixed manually - no fitting done
Definition: DataStructs.h:74
float TrajPointVertexPull(TCSlice &slc, const TrajPoint &tp, const VtxStore &vx)
Definition: TCVertex.cxx:2029
bool TrajClosestApproach(Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
Definition: Utils.cxx:2377
bool SignalBetween(TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2, const float &MinWireSignalFraction)
Definition: Utils.cxx:1671
float TrajLength(Trajectory &tj)
Definition: Utils.cxx:2337
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1660
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2513
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:466
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void tca::CheckHiMultEndHits ( TCSlice slc,
Trajectory tj 
)

Definition at line 2526 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::TCConfig::dbgStp, tca::Trajectory::EndPt, kBragg, kCHMEH, tca::Trajectory::Pts, SetEndPoints(), tca::Trajectory::StopFlag, tcc, UnsetUsedHits(), and tca::TCConfig::useAlg.

Referenced by CheckTraj().

2527  {
2528  // mask off high multiplicity TPs at the end
2529  if(!tcc.useAlg[kCHMEH]) return;
2530  if(tj.StopFlag[1][kBragg]) return;
2531  if(tj.Pts.size() < 10) return;
2532  if(tj.Pts[tj.EndPt[1]].AngleCode == 0) return;
2533  // find the average multiplicity in the first half
2534  unsigned short aveMult= 0;
2535  unsigned short ipt, nhalf = tj.Pts.size() / 2;
2536  unsigned short cnt = 0;
2537  for(auto& tp : tj.Pts) {
2538  if(tp.Chg == 0) continue;
2539  aveMult += tp.Hits.size();
2540  ++cnt;
2541  if(cnt == nhalf) break;
2542  } // pt
2543  if(cnt == 0) return;
2544  aveMult /= cnt;
2545  if(aveMult == 0) aveMult = 1;
2546  // convert this into a cut
2547  aveMult *= 3;
2548  cnt = 0;
2549  for(ipt = tj.EndPt[1]; ipt > tj.EndPt[0]; --ipt) {
2550  if(tj.Pts[ipt].Chg == 0) continue;
2551  if(tj.Pts[ipt].Hits.size() > aveMult) {
2552  UnsetUsedHits(slc, tj.Pts[ipt]);
2553  ++cnt;
2554  continue;
2555  }
2556  break;
2557  } // ipt
2558  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"CHMEH multiplicity cut "<<aveMult<<" number of TPs masked off "<<cnt;
2559  if(cnt > 0) {
2560  tj.AlgMod[kCHMEH] = true;
2561  SetEndPoints(tj);
2562  }
2563  } // CheckHiMultEndHits
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
TCConfig tcc
Definition: DataStructs.cxx:6
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1162
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
void tca::CheckHiMultUnusedHits ( TCSlice slc,
Trajectory tj 
)

Definition at line 2378 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, AngleRange(), tca::TCConfig::dbgStp, DefineHitPos(), tca::Trajectory::EndPt, GottaKink(), tca::Trajectory::ID, tca::Trajectory::IsGood, kAtKink, kCHMUH, kUsedHits, MaskTrajEndPoints(), MaxHitDelta(), tca::TCConfig::minPtsFit, tca::Trajectory::NeedsUpdate, NumHitsInTP(), NumPtsWithCharge(), tca::Trajectory::Pass, PointTrajDOCA(), PrintHit(), PrintTrajectory(), tca::Trajectory::Pts, PutTrajHitsInVector(), SetEndPoints(), tca::TCSlice::slHits, tca::Trajectory::StopFlag, tcc, UnsetUsedHits(), UpdateTraj(), and tca::TCConfig::useAlg.

2379  {
2380  // Check for many unused hits in high multiplicity TPs in work and try to use them
2381 
2382  if(!tcc.useAlg[kCHMUH]) return;
2383 
2384  // This code might do bad things to short trajectories
2385  if(NumPtsWithCharge(slc, tj, true) < 6) return;
2386  if(tj.EndPt[0] == tj.EndPt[1]) return;
2387  // Angle code 0 tjs shouldn't have any high multiplicity hits added to them
2388  if(tj.Pts[tj.EndPt[1]].AngleCode == 0) return;
2389 
2390  // count the number of unused hits multiplicity > 1 hits and decide
2391  // if the unused hits should be used. This may trigger another
2392  // call to StepAway
2393  unsigned short ii, stopPt;
2394  // Use this to see if the high multiplicity Pts are mostly near
2395  // the end or further upstream
2396  unsigned short lastMult1Pt = USHRT_MAX;
2397  // the number of TPs with > 1 hit (HiMult)
2398  unsigned short nHiMultPt = 0;
2399  // the total number of hits associated with HiMult TPs
2400  unsigned short nHiMultPtHits = 0;
2401  // the total number of used hits associated with HiMult TPs
2402  unsigned short nHiMultPtUsedHits = 0;
2403  unsigned int iht;
2404  // start counting at the leading edge and break if a hit
2405  // is found that is used in a trajectory
2406  bool doBreak = false;
2407  unsigned short jj;
2408  for(ii = 1; ii < tj.Pts.size(); ++ii) {
2409  stopPt = tj.EndPt[1] - ii;
2410  for(jj = 0; jj < tj.Pts[stopPt].Hits.size(); ++jj) {
2411  iht = tj.Pts[stopPt].Hits[jj];
2412  if(slc.slHits[iht].InTraj > 0) {
2413  doBreak = true;
2414  break;
2415  }
2416  } // jj
2417  if(doBreak) break;
2418  // require 2 consecutive multiplicity = 1 points
2419  if(lastMult1Pt == USHRT_MAX && tj.Pts[stopPt].Hits.size() == 1 && tj.Pts[stopPt-1].Hits.size() == 1) lastMult1Pt = stopPt;
2420  if(tj.Pts[stopPt].Hits.size() > 1) {
2421  ++nHiMultPt;
2422  nHiMultPtHits += tj.Pts[stopPt].Hits.size();
2423  nHiMultPtUsedHits += NumHitsInTP(tj.Pts[stopPt], kUsedHits);
2424  } // high multiplicity TP
2425  // stop looking when two consecutive single multiplicity TPs are found
2426  if(lastMult1Pt != USHRT_MAX) break;
2427  if(stopPt == 1) break;
2428  } // ii
2429  // Don't do this if there aren't a lot of high multiplicity TPs
2430  float fracHiMult = (float)nHiMultPt / (float)ii;
2431  if(lastMult1Pt != USHRT_MAX) {
2432  float nchk = tj.EndPt[1] - lastMult1Pt + 1;
2433  fracHiMult = (float)nHiMultPt / nchk;
2434  } else {
2435  fracHiMult = (float)nHiMultPt / (float)ii;
2436  }
2437  float fracHitsUsed = 0;
2438  if(nHiMultPt > 0 && nHiMultPtHits > 0) fracHitsUsed = (float)nHiMultPtUsedHits / (float)nHiMultPtHits;
2439  // Use this to limit the number of points fit for trajectories that
2440  // are close the LA tracking cut
2441  ii = tj.EndPt[1];
2442  bool sortaLargeAngle = (AngleRange(tj.Pts[ii]) == 1);
2443 
2444  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"CHMUH: First InTraj stopPt "<<stopPt<<" fracHiMult "<<fracHiMult<<" fracHitsUsed "<<fracHitsUsed<<" lastMult1Pt "<<lastMult1Pt<<" sortaLargeAngle "<<sortaLargeAngle;
2445  if(fracHiMult < 0.3) return;
2446  if(fracHitsUsed > 0.98) return;
2447 
2448  float maxDelta = 2.5 * MaxHitDelta(slc, tj);
2449 
2450  if(tcc.dbgStp) {
2451  mf::LogVerbatim("TC")<<" Pts size "<<tj.Pts.size()<<" nHiMultPt "<<nHiMultPt<<" nHiMultPtHits "<<nHiMultPtHits<<" nHiMultPtUsedHits "<<nHiMultPtUsedHits<<" sortaLargeAngle "<<sortaLargeAngle<<" maxHitDelta "<<maxDelta;
2452  }
2453 
2454  // Use next pass cuts if available
2455  if(sortaLargeAngle && tj.Pass < tcc.minPtsFit.size()-1) ++tj.Pass;
2456 
2457  // Make a copy of tj in case something bad happens
2458  Trajectory TjCopy = tj;
2459  // and the list of used hits
2460  auto inTrajHits = PutTrajHitsInVector(tj, kUsedHits);
2461  unsigned short ipt;
2462 
2463  // unset the used hits from stopPt + 1 to the end
2464  for(ipt = stopPt + 1; ipt < tj.Pts.size(); ++ipt) UnsetUsedHits(slc, tj.Pts[ipt]);
2465  SetEndPoints(tj);
2466  unsigned short killPts;
2467  float delta;
2468  bool added;
2469  for(ipt = stopPt + 1; ipt < tj.Pts.size(); ++ipt) {
2470  // add hits that are within maxDelta and re-fit at each point
2471  added = false;
2472  for(ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
2473  iht = tj.Pts[ipt].Hits[ii];
2474  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" ipt "<<ipt<<" hit "<<PrintHit(slc.slHits[iht])<<" inTraj "<<slc.slHits[iht].InTraj<<" delta "<<PointTrajDOCA(slc, iht, tj.Pts[ipt]);
2475  if(slc.slHits[iht].InTraj != 0) continue;
2476  delta = PointTrajDOCA(slc, iht, tj.Pts[ipt]);
2477  if(delta > maxDelta) continue;
2478  if (!NumHitsInTP(TjCopy.Pts[ipt], kUsedHits)||TjCopy.Pts[ipt].UseHit[ii]){
2479  tj.Pts[ipt].UseHit[ii] = true;
2480  slc.slHits[iht].InTraj = tj.ID;
2481  added = true;
2482  }
2483  } // ii
2484  if(added) DefineHitPos(slc, tj.Pts[ipt]);
2485  if(tj.Pts[ipt].Chg == 0) continue;
2486  tj.EndPt[1] = ipt;
2487  // This will be incremented by one in UpdateTraj
2488  if(sortaLargeAngle) tj.Pts[ipt].NTPsFit = 2;
2489  UpdateTraj(slc, tj);
2490  if(tj.NeedsUpdate) {
2491  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"UpdateTraj failed on point "<<ipt;
2492  // Clobber the used hits from the corrupted points in tj
2493  for(unsigned short jpt = stopPt + 1; jpt <= ipt; ++jpt) {
2494  for(unsigned short jj = 0; jj < tj.Pts[jpt].Hits.size(); ++jj) {
2495  if(tj.Pts[jpt].UseHit[jj]) slc.slHits[tj.Pts[jpt].Hits[jj]].InTraj = 0;
2496  } // jj
2497  } // jpt
2498  // restore the original trajectory
2499  tj = TjCopy;
2500  // restore the hits
2501  for(unsigned short jpt = stopPt + 1; jpt <= ipt; ++jpt) {
2502  for(unsigned short jj = 0; jj < tj.Pts[jpt].Hits.size(); ++jj) {
2503  if(tj.Pts[jpt].UseHit[jj]) slc.slHits[tj.Pts[jpt].Hits[jj]].InTraj = tj.ID;
2504  } // jj
2505  } // jpt
2506  return;
2507  }
2508  GottaKink(slc, tj, killPts);
2509  if(killPts > 0) {
2510  MaskTrajEndPoints(slc, tj, killPts);
2511  if(!tj.IsGood) return;
2512  break;
2513  }
2514  if(tcc.dbgStp) PrintTrajectory("CHMUH", slc, tj, ipt);
2515  } // ipt
2516  // if we made it here it must be OK
2517  SetEndPoints(tj);
2518  // Try to extend it, unless there was a kink
2519  if(tj.StopFlag[1][kAtKink]) return;
2520  // trim the end points although this shouldn't happen
2521  if(tj.EndPt[1] != tj.Pts.size() - 1) tj.Pts.resize(tj.EndPt[1] + 1);
2522  tj.AlgMod[kCHMUH] = true;
2523  } // CheckHiMultUnusedHits
void PrintTrajectory(std::string someText, TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:5455
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
void UpdateTraj(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:655
std::vector< unsigned short > minPtsFit
Reconstruct in several passes.
Definition: DataStructs.h:482
TCConfig tcc
Definition: DataStructs.cxx:6
std::vector< unsigned int > PutTrajHitsInVector(Trajectory const &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2416
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1162
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1840
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:5704
void GottaKink(TCSlice &slc, Trajectory &tj, unsigned short &killPts)
Definition: StepUtils.cxx:2842
unsigned short NumHitsInTP(const TrajPoint &tp, HitStatus_t hitRequest)
Definition: Utils.cxx:3775
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
float MaxHitDelta(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:2734
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
void MaskTrajEndPoints(TCSlice &slc, Trajectory &tj, unsigned short nPts)
Definition: StepUtils.cxx:3887
unsigned short AngleRange(TrajPoint const &tp)
Definition: Utils.cxx:716
void tca::CheckStiffEl ( TCSlice slc,
Trajectory tj 
)

Definition at line 898 of file StepUtils.cxx.

References tca::TCConfig::dbgStp, FillGaps(), FixTrajBegin(), kStiffEl, NumPtsWithCharge(), tca::Trajectory::Strategy, and tcc.

Referenced by CheckTraj().

899  {
900  if(!tj.Strategy[kStiffEl]) return;
901  if(tcc.dbgStp) {
902  mf::LogVerbatim("TC")<<"inside CheckStiffTj with NumPtsWithCharge = "<<NumPtsWithCharge(slc, tj, false);
903  }
904  // Fill in any gaps with hits that were skipped, most likely delta rays on muon tracks
905  FillGaps(slc, tj);
906  // Update the trajectory parameters at the beginning of the trajectory
907  FixTrajBegin(slc, tj);
908  } // CheckStiffTj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
void FillGaps(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2264
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
void FixTrajBegin(TCSlice &slc, Trajectory &tj, unsigned short atPt)
Definition: StepUtils.cxx:3092
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
use the stiff electron strategy
Definition: DataStructs.h:418
void tca::CheckTraj ( TCSlice slc,
Trajectory tj 
)

Definition at line 911 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, CheckHiMultEndHits(), CheckStiffEl(), ChkChgAsymmetry(), ChkStop(), ChkStopEndPts(), tca::TCConfig::dbgStp, tca::Trajectory::EndPt, FillGaps(), FixTrajBegin(), HasDuplicateHits(), HiEndDelta(), IsGhost(), tca::Trajectory::IsGood, tca::TCSlice::isValid, kAtKink, kBragg, kCTKink, kCTStepChk, kJunkTj, kKilled, kRvPrp, kSignal, kSlowing, kStiffEl, tca::Trajectory::MCSMom, MCSMom(), tca::TCConfig::minMCSMom, tca::TCConfig::minPts, NumPtsWithCharge(), tca::Trajectory::Pass, PrintTrajectory(), tca::Trajectory::Pts, tca::TCConfig::qualityCuts, SetEndPoints(), tca::Trajectory::StopFlag, tca::Trajectory::Strategy, TagJunkTj(), tcc, TrimEndPts(), UnsetUsedHits(), and tca::TCConfig::useAlg.

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

912  {
913  // Check the quality of the trajectory and possibly trim it or flag it for deletion
914 
915  if(!tj.IsGood) return;
916 
917  // ensure that the end points are defined
918  SetEndPoints(tj);
919  if(tj.EndPt[0] == tj.EndPt[1]) return;
920 
921  if(tj.Strategy[kStiffEl]) {
922  CheckStiffEl(slc, tj);
923  return;
924  }
925 
926  if(tcc.dbgStp) {
927  mf::LogVerbatim("TC")<<"inside CheckTraj with NumPtsWithCharge = "<<NumPtsWithCharge(slc, tj, false);
928  }
929 
930  if(NumPtsWithCharge(slc, tj, false) < tcc.minPts[tj.Pass]) {
931  tj.IsGood = false;
932  return;
933  }
934 
935  // Look for a charge asymmetry between points on both sides of a high-
936  // charge point and trim points in the vicinity
937  ChkChgAsymmetry(slc, tj, tcc.dbgStp);
938 
939  // flag this tj as a junk Tj (even though it wasn't created in FindJunkTraj).
940  // Drop it and let FindJunkTraj do it's job
941  TagJunkTj(slc, tj, tcc.dbgStp);
942  if(tj.AlgMod[kJunkTj]) {
943  tj.IsGood = false;
944  return;
945  }
946 
947  tj.MCSMom = MCSMom(slc, tj);
948 
949  // See if the points at the stopping end can be included in the Tj
950  ChkStopEndPts(slc, tj, tcc.dbgStp);
951 
952  // remove any points at the end that don't have charge
953  tj.Pts.resize(tj.EndPt[1] + 1);
954 
955  // Ensure that a hit only appears once in the TJ
956  if(HasDuplicateHits(slc, tj, tcc.dbgStp)) {
957  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" HasDuplicateHits ";
958  tj.IsGood = false;
959  return;
960  }
961 
962  // See if this is a ghost trajectory
963  if(IsGhost(slc, tj)) {
964  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" CT: Ghost trajectory - trimmed hits ";
965  if(!tj.IsGood) return;
966  }
967 
968  if(tj.AlgMod[kJunkTj]) return;
969 
970  // checks are different for Very Large Angle trajectories
971  bool isVLA = (tj.Pts[tj.EndPt[1]].AngleCode == 2);
972  // The last two ranges are Large Angle and Very Large Angle. Determine if the TJ is Small Angle
973  bool isSA = (tj.Pts[tj.EndPt[1]].AngleCode == 0);
974 
975  // First remove any TPs at the end that have no hits after
976  // setting the StopFlag. Assume that there are no hits on TPs after the end
977  tj.StopFlag[1][kSignal] = false;
978  if(tj.EndPt[1] < tj.Pts.size() - 1) {
979  // There must be hits at the end so set the kSignal StopFlag
980  if(!tj.Pts[tj.EndPt[1]+1].Hits.empty()) tj.StopFlag[1][kSignal] = true;
981  }
982  tj.Pts.resize(tj.EndPt[1] + 1);
983 
984  // Fill in any gaps with hits that were skipped, most likely delta rays on muon tracks
985  if(!isVLA) FillGaps(slc, tj);
986 
987  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" CheckTraj MCSMom "<<tj.MCSMom<<" isVLA? "<<isVLA<<" NumPtsWithCharge "<<NumPtsWithCharge(slc, tj, false)<<" Min Req'd "<<tcc.minPts[tj.Pass];
988 
989  // Check for hit width consistency on short trajectories
990  if(tj.Pts.size() < 10) {
991  float maxWidth = 0;
992  float minWidth = 999;
993  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
994  if(tj.Pts[ipt].Chg == 0) continue;
995  if(tj.Pts[ipt].HitPosErr2 > maxWidth) maxWidth = tj.Pts[ipt].HitPosErr2;
996  if(tj.Pts[ipt].HitPosErr2 < minWidth) minWidth = tj.Pts[ipt].HitPosErr2;
997  } // ipt
998  // Require less than a 3X difference in the hit width or 10X for HitPosErr2
999  if(maxWidth > 10 * minWidth) {
1000  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" TP width variation too large: minWidth "<<minWidth<<" maxWidth "<<maxWidth;
1001  tj.IsGood = false;
1002  return;
1003  }
1004  } // short trajectory
1005 
1006  // Trim the end points until the TJ meets the quality cuts
1007  TrimEndPts("CT", slc, tj, tcc.qualityCuts, tcc.dbgStp);
1008  if(tj.AlgMod[kKilled]) {
1009  tj.IsGood = false;
1010  return;
1011  }
1012 
1013  // Check for a Bragg peak at both ends. This may be used by FixTrajBegin.
1014  ChkStop(slc, tj);
1015 
1016  // Update the trajectory parameters at the beginning of the trajectory
1017  FixTrajBegin(slc, tj);
1018 
1019  // ignore short trajectories
1020  if(tj.EndPt[1] < 4) return;
1021 
1022  if(isSA && !tj.StopFlag[1][kBragg]) {
1023  // Small angle checks
1024 
1025  if(tcc.useAlg[kCTKink] && tj.EndPt[1] > 8 && !tj.StopFlag[1][kAtKink] && tj.MCSMom > 50) {
1026  // look for the signature of a kink near the end of the trajectory.
1027  // These are: Increasing delta for the last few hits
1028  unsigned short newSize = USHRT_MAX;
1029  unsigned short lastPtToChk = tj.EndPt[1] - 4;
1030  float deltaCut = 2 * tj.Pts[lastPtToChk].DeltaRMS;
1031  for(unsigned short ipt = tj.EndPt[1]; ipt > lastPtToChk; --ipt) {
1032  // Stop checking if delta is good
1033  if(tj.Pts[ipt].Delta < deltaCut) break;
1034  float drat = tj.Pts[ipt].Delta / tj.Pts[ipt-1].Delta;
1035  if(drat > 1.2) newSize = ipt;
1036  } // ipt
1037  if(newSize != USHRT_MAX) {
1038  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"CTKink: Masking end points to newSize "<<newSize;
1039  for(unsigned short ipt = newSize; ipt < tj.Pts.size(); ++ipt) UnsetUsedHits(slc, tj.Pts[ipt]);
1040  SetEndPoints(tj);
1041  tj.AlgMod[kCTKink] = true;
1042  }
1043  } // tcc.useAlg[kCTKink]
1044 
1045  if(tcc.useAlg[kCTStepChk] && !tj.AlgMod[kRvPrp]) {
1046  // Compare the number of steps taken per TP near the beginning and
1047  // at the end. This will get confused if RevProp is used
1048  short nStepBegin = tj.Pts[2].Step - tj.Pts[1].Step;
1049  short nStepEnd;
1050  unsigned short lastPt = tj.Pts.size() - 1;
1051  unsigned short newSize = tj.Pts.size();
1052  for(unsigned short ipt = lastPt; ipt > lastPt - 2; --ipt) {
1053  nStepEnd = tj.Pts[ipt].Step - tj.Pts[ipt - 1].Step;
1054  if(nStepEnd > 3 * nStepBegin) newSize = ipt;
1055  }
1056  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"CTStepChk: check number of steps. newSize "<<newSize<<" tj.Pts.size() "<<tj.Pts.size();
1057  if(newSize < tj.Pts.size()) {
1058  for(unsigned short ipt = newSize; ipt < tj.Pts.size(); ++ipt) UnsetUsedHits(slc, tj.Pts[ipt]);
1059  SetEndPoints(tj);
1060  tj.AlgMod[kCTStepChk] = true;
1061  tj.Pts.resize(newSize);
1062  return;
1063  } // newSize < tj.Pts.size()
1064  } // tcc.useAlg[kCTStepChk]
1065  } // isSA
1066  // Oct 30, 2018. FindSoftKink needs work
1067 // FindSoftKink(slc, tj);
1068 
1069  HiEndDelta(slc, tj);
1070 
1071  // final quality check
1072  float npwc = NumPtsWithCharge(slc, tj, true);
1073  float npts = tj.EndPt[1] - tj.EndPt[0] + 1;
1074  float frac = npwc / npts;
1075  tj.IsGood = (frac >= tcc.qualityCuts[0]);
1076  if(tj.IsGood && tj.Pass < tcc.minMCSMom.size() && !tj.Strategy[kSlowing]) tj.IsGood = (tj.MCSMom >= tcc.minMCSMom[tj.Pass]);
1077  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"CTStepChk: fraction of points with charge "<<frac<<" good traj? "<<tj.IsGood;
1078  if(!tj.IsGood || !slc.isValid) return;
1079 
1080  // lop off high multiplicity hits at the end
1081  CheckHiMultEndHits(slc, tj);
1082 
1083  // Check for a Bragg peak at both ends. This may be used by FixTrajBegin.
1084  ChkStop(slc, tj);
1085 
1086  if(tcc.dbgStp && tj.Pts.size() < 100) PrintTrajectory("CTo", slc, tj, USHRT_MAX);
1087 
1088  } // CheckTraj
void PrintTrajectory(std::string someText, TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:5455
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
short MCSMom(TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2914
std::vector< float > qualityCuts
Min points/wire, min consecutive pts after a gap.
Definition: DataStructs.h:479
TCConfig tcc
Definition: DataStructs.cxx:6
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1162
void FillGaps(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2264
bool IsGhost(TCSlice &slc, std::vector< unsigned int > &tHits)
Definition: StepUtils.cxx:3385
void ChkChgAsymmetry(TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:1611
void HiEndDelta(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2566
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
use the slowing-down strategy
Definition: DataStructs.h:420
std::vector< short > minMCSMom
Min MCSMom for each pass.
Definition: DataStructs.h:485
void CheckStiffEl(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:898
void FixTrajBegin(TCSlice &slc, Trajectory &tj, unsigned short atPt)
Definition: StepUtils.cxx:3092
void TagJunkTj(TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:2442
std::vector< unsigned short > minPts
min number of Pts required to make a trajectory
Definition: DataStructs.h:483
void TrimEndPts(std::string fcnLabel, TCSlice &slc, Trajectory &tj, const std::vector< float > &fQualityCuts, bool prt)
Definition: Utils.cxx:1511
void ChkStop(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:3952
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
bool HasDuplicateHits(TCSlice &slc, Trajectory const &tj, bool prt)
Definition: Utils.cxx:2469
use the stiff electron strategy
Definition: DataStructs.h:418
kink found in CheckTraj
Definition: DataStructs.h:351
void ChkStopEndPts(TCSlice &slc, Trajectory &tj, bool prt)
Definition: StepUtils.cxx:1711
void CheckHiMultEndHits(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2526
void tca::CheckTrajBeginChg ( TCSlice slc,
unsigned short  itj 
)

Definition at line 1406 of file Utils.cxx.

References tca::VtxStore::ChiDOF, tca::VtxStore::CTP, tca::TCConfig::dbgAlg, tca::TCConfig::dbgSlc, tca::TCConfig::dbgStp, evd::details::end(), tca::VtxStore::ID, kBeginChg, kBragg, kFixed, kFTBRvProp, kHaloTj, kKilled, kNewStpCuts, MakeVertexObsolete(), tca::VtxStore::NTraj, tca::VtxStore::Pass, tca::VtxStore::Pos, PrintPos(), SetVx2Score(), SplitTraj(), tca::VtxStore::Stat, StoreVertex(), tcc, tca::TCSlice::tjs, tca::VtxStore::Topo, tca::TCConfig::useAlg, and tca::TCSlice::vtxs.

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

1407  {
1408  // This function is called after the beginning of the tj has been inspected to see if
1409  // reverse propagation was warranted. Trajectory points at the beginning were removed by
1410  // this process.
1411  // A search has been made for a Bragg peak with nothing
1412  // found. Here we look for a charge pattern like the following, where C means large charge
1413  // and c means lower charge:
1414  // CCCCCCccccccc
1415  // The charge in the two regions should be fairly uniform.
1416 
1417  // This function may split the trajectory so it needs to have been stored
1418  if(itj > slc.tjs.size() - 1) return;
1419  auto& tj = slc.tjs[itj];
1420 
1421  if(!tcc.useAlg[kBeginChg]) return;
1422  if(tj.StopFlag[0][kBragg]) return;
1423  if(tj.AlgMod[kFTBRvProp]) return;
1424  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) return;
1425  if(tj.Pts.size() < 20) return;
1426 
1427  bool prt = (tcc.dbgSlc && (tcc.dbgStp || tcc.dbgAlg[kBeginChg]));
1428 
1429  // look for a large drop between the average charge near the beginning
1430  float chg2 = tj.Pts[tj.EndPt[0] + 2].AveChg;
1431  // and the average charge 15 points away
1432  float chg15 = tj.Pts[tj.EndPt[0] + 15].AveChg;
1433  if(chg2 < 3 * chg15) return;
1434 
1435  // find the point where the charge falls below the mid-point
1436  float midChg = 0.5 * (chg2 + chg15);
1437 
1438  unsigned short breakPt = USHRT_MAX;
1439  for(unsigned short ipt = tj.EndPt[0] + 3; ipt < 15; ++ipt) {
1440  float chgm2 = tj.Pts[ipt - 2].Chg;
1441  if(chgm2 == 0) continue;
1442  float chgm1 = tj.Pts[ipt - 1].Chg;
1443  if(chgm1 == 0) continue;
1444  float chgp1 = tj.Pts[ipt + 1].Chg;
1445  if(chgp1 == 0) continue;
1446  float chgp2 = tj.Pts[ipt + 2].Chg;
1447  if(chgp2 == 0) continue;
1448  if(chgm2 > midChg && chgm1 > midChg && chgp1 < midChg && chgp2 < midChg) {
1449  breakPt = ipt;
1450  break;
1451  }
1452  } // breakPt
1453  if(breakPt == USHRT_MAX) return;
1454  if(tcc.useAlg[kNewStpCuts]) {
1455  // check the charge and rms before and after the split
1456  std::array<double, 2> cnt, sum, sum2;
1457  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1458  auto& tp = tj.Pts[ipt];
1459  if(tp.Chg <= 0) continue;
1460  unsigned short end = 0;
1461  if(ipt > breakPt) end = 1;
1462  ++cnt[end];
1463  sum[end] += tp.Chg;
1464  sum2[end] += tp.Chg * tp.Chg;
1465  } // ipt
1466  for(unsigned short end = 0; end < 2; ++end) {
1467  if(cnt[end] < 3) return;
1468  double ave = sum[end] / cnt[end];
1469  double arg = sum2[end] - cnt[end] * ave * ave;
1470  if(arg <= 0) return;
1471  sum2[end] = sqrt(arg / (cnt[end] - 1));
1472  sum2[end] /= ave;
1473  sum[end] = ave;
1474  } // region
1475  bool doSplit = true;
1476  // don't split if this looks like an electron - no significant improvement
1477  // in the charge rms before and after
1478  if(tj.ChgRMS > 0.5 && sum2[0] > 0.3 && sum2[1] > 0.3) doSplit = false;
1479  if(prt) {
1480  mf::LogVerbatim myprt("TC");
1481  myprt<<"CTBC: T"<<tj.ID<<" chgRMS "<<tj.ChgRMS;
1482  myprt<<" AveChg before split point "<<(int)sum[0]<<" rms "<<sum2[0];
1483  myprt<<" after "<<(int)sum[1]<<" rms "<<sum2[1]<<" doSplit? "<<doSplit;
1484  } // prt
1485  if(!doSplit) return;
1486  } // NewStpCuts
1487  // Create a vertex at the break point
1488  VtxStore aVtx;
1489  aVtx.Pos = tj.Pts[breakPt].Pos;
1490  aVtx.NTraj = 2;
1491  aVtx.Pass = tj.Pass;
1492  aVtx.Topo = 8;
1493  aVtx.ChiDOF = 0;
1494  aVtx.CTP = tj.CTP;
1495  aVtx.ID = slc.vtxs.size() + 1;
1496  aVtx.Stat[kFixed] = true;
1497  unsigned short ivx = slc.vtxs.size();
1498  if(!StoreVertex(slc, aVtx)) return;
1499  if(!SplitTraj(slc, itj, breakPt, ivx, prt)) {
1500  if(prt) mf::LogVerbatim("TC")<<"CTBC: Failed to split trajectory";
1501  MakeVertexObsolete("CTBC", slc, slc.vtxs[ivx], false);
1502  return;
1503  }
1504  SetVx2Score(slc);
1505 
1506  if(prt) mf::LogVerbatim("TC")<<"CTBC: Split T"<<tj.ID<<" at "<<PrintPos(slc, tj.Pts[breakPt].Pos)<<"\n";
1507 
1508  } // CheckTrajBeginChg
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:3120
TCConfig tcc
Definition: DataStructs.cxx:6
vertex position fixed manually - no fitting done
Definition: DataStructs.h:74
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:507
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:2093
std::string PrintPos(TCSlice &slc, const Point2_t &pos)
Definition: Utils.cxx:5718
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
bool SplitTraj(TCSlice &slc, unsigned short itj, unsigned short pos, unsigned short ivx, bool prt)
Definition: Utils.cxx:2043
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:505
void SetVx2Score(TCSlice &slc)
Definition: TCVertex.cxx:2504
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
float tca::ChgFracBetween ( TCSlice slc,
TrajPoint  tp,
float  toPos0 
)

Definition at line 1702 of file Utils.cxx.

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

Referenced by SignalBetween().

1703  {
1704  // Returns the fraction of wires between tp.Pos[0] and toPos0 that have a hit
1705  // on the line defined by tp.Pos and tp.Dir
1706 
1707  if(tp.Pos[0] < -0.4 || toPos0 < -0.4) return 0;
1708  int fromWire = std::nearbyint(tp.Pos[0]);
1709  int toWire = std::nearbyint(toPos0);
1710 
1711  if(fromWire == toWire) {
1712  return SignalAtTp(slc, tp);
1713  }
1714 
1715  int nWires = abs(toWire - fromWire) + 1;
1716 
1717  if(std::abs(tp.Dir[0]) < 0.001) tp.Dir[0] = 0.001;
1718  float stepSize = std::abs(1/tp.Dir[0]);
1719  // ensure that we step in the right direction
1720  if(toWire > fromWire && tp.Dir[0] < 0) stepSize = -stepSize;
1721  if(toWire < fromWire && tp.Dir[0] > 0) stepSize = -stepSize;
1722  float nsig = 0;
1723  float num = 0;
1724  for(unsigned short cnt = 0; cnt < nWires; ++cnt) {
1725  ++num;
1726  if(SignalAtTp(slc, tp)) ++nsig;
1727  tp.Pos[0] += tp.Dir[0] * stepSize;
1728  tp.Pos[1] += tp.Dir[1] * stepSize;
1729  } // cnt
1730  float sigFrac = nsig / num;
1731  return sigFrac;
1732 
1733  } // ChgFracBetween
bool SignalAtTp(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:1814
float tca::ChgFracBetween ( TCSlice slc,
Point3_t  pos1,
Point3_t  pos2 
)

Definition at line 2957 of file PFPUtils.cxx.

References detinfo::DetectorProperties::ConvertXToTicks(), geo::CryostatID::Cryostat, tca::TrajPoint::CTP, tca::TCConfig::detprop, dir, EncodeCTP(), tca::TCConfig::geom, tca::TCSlice::nPlanes, PointDirection(), tca::TrajPoint::Pos, PosSep(), SignalAtTp(), tcc, geo::TPCID::TPC, tca::TCSlice::TPCID, tca::TCConfig::unitsPerTick, geo::GeometryCore::WireCoordinate(), and tca::TCConfig::wirePitch.

Referenced by DotProd(), FindParent(), and ParentFOM().

2958  {
2959  // Step between pos1 and pos2 and find the fraction of the points that have nearby hits
2960  // in each plane. This function returns -1 if something is fishy, but this doesn't mean
2961  // that there is no charge. Note that there is no check for charge precisely at the pos1 and pos2
2962  // positions
2963  float sep = PosSep(pos1, pos2);
2964  if(sep == 0) return -1;
2965  unsigned short nstep = sep / tcc.wirePitch;
2966  auto dir = PointDirection(pos1, pos2);
2967  float sum = 0;
2968  float cnt = 0;
2969  TrajPoint tp;
2970  for(unsigned short step = 0; step < nstep; ++step) {
2971  for(unsigned short xyz = 0; xyz < 3; ++xyz) pos1[xyz] += tcc.wirePitch * dir[xyz];
2972  for(unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
2973  tp.CTP = EncodeCTP(slc.TPCID.Cryostat, slc.TPCID.TPC, plane);
2974  tp.Pos[0] = tcc.geom->WireCoordinate(pos1[1], pos1[2], plane, slc.TPCID.TPC, slc.TPCID.Cryostat);
2975  tp.Pos[1] = tcc.detprop->ConvertXToTicks(pos1[0], plane, slc.TPCID.TPC, slc.TPCID.Cryostat) * tcc.unitsPerTick;
2976  ++cnt;
2977  if(SignalAtTp(slc, tp)) ++sum;
2978  } // plane
2979  } // step
2980  if(cnt == 0) return -1;
2981  return sum / cnt;
2982 
2983  } // ChgFracBetween
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
TCConfig tcc
Definition: DataStructs.cxx:6
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
const detinfo::DetectorProperties * detprop
Definition: DataStructs.h:494
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:1643
bool SignalAtTp(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:1814
const geo::GeometryCore * geom
Definition: DataStructs.h:493
TDirectory * dir
Definition: macro.C:5
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
float tca::ChgFracNearEnd ( TCSlice slc,
PFPStruct pfp,
unsigned short  end 
)

Definition at line 2986 of file PFPUtils.cxx.

References ChgFracNearPos(), detinfo::DetectorProperties::ConvertXToTicks(), geo::CryostatID::Cryostat, tca::TCConfig::detprop, EncodeCTP(), tca::TCConfig::geom, tca::PFPStruct::ID, tca::TCSlice::nPlanes, tca::TCSlice::nWires, tcc, tca::PFPStruct::TjIDs, tca::TCSlice::tjs, geo::TPCID::TPC, tca::PFPStruct::TPCID, tca::TCSlice::TPCID, tca::TCConfig::unitsPerTick, geo::GeometryCore::WireCoordinate(), tca::TCSlice::wireHitRange, and tca::PFPStruct::XYZ.

Referenced by DotProd().

2987  {
2988  // returns the charge fraction near the end of the pfp. Note that this function
2989  // assumes that there is only one Tj in a plane.
2990  if(pfp.ID == 0) return 0;
2991  if(pfp.TjIDs.empty()) return 0;
2992  if(end < 0 || end > 1) return 0;
2993  if(pfp.TPCID != slc.TPCID) return 0;
2994 
2995  float sum = 0;
2996  float cnt = 0;
2997  // keep track of the lowest value and maybe reject it
2998  float lo = 1;
2999  float hi = 0;
3000  for(unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
3001  CTP_t inCTP = EncodeCTP(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
3002  std::vector<int> tjids(1);
3003  for(auto tjid : pfp.TjIDs) {
3004  auto& tj = slc.tjs[tjid - 1];
3005  if(tj.CTP != inCTP) continue;
3006  tjids[0] = tjid;
3007  Point2_t pos;
3008  geo::PlaneID planeID = geo::PlaneID(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
3009  pos[0] = tcc.geom->WireCoordinate(pfp.XYZ[end][1], pfp.XYZ[end][2], planeID);
3010  if(pos[0] < -0.4) continue;
3011  // check for dead wires
3012  unsigned int wire = std::nearbyint(pos[0]);
3013  if(wire > slc.nWires[plane]) continue;
3014  if(slc.wireHitRange[plane][wire].first == -1) continue;
3015  pos[1] = tcc.detprop->ConvertXToTicks(pfp.XYZ[end][0], planeID) * tcc.unitsPerTick;
3016  float cf = ChgFracNearPos(slc, pos, tjids);
3017  if(cf < lo) lo = cf;
3018  if(cf > hi) hi = cf;
3019  sum += cf;
3020  ++cnt;
3021  } // tjid
3022  } // plane
3023  if(cnt == 0) return 0;
3024  if(cnt > 1 && lo < 0.3 && hi > 0.8) {
3025  sum -= lo;
3026  --cnt;
3027  }
3028  return sum / cnt;
3029  } // ChgFracNearEnd
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
const detinfo::DetectorProperties * detprop
Definition: DataStructs.h:494
const geo::GeometryCore * geom
Definition: DataStructs.h:493
float ChgFracNearPos(TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2698
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 ( TCSlice slc,
const Point2_t pos,
const std::vector< int > &  tjIDs 
)

Definition at line 2698 of file Utils.cxx.

References tca::TCEvent::allHits, DecodeCTP(), evt, FindCloseHits(), kAllHits, geo::PlaneID::Plane, tca::TCSlice::slHits, and tca::TCSlice::tjs.

Referenced by ChgFracNearEnd(), CompleteIncomplete3DVertices(), CompleteIncomplete3DVerticesInGaps(), EndMerge(), FindHammerVertices(), ParentFOM(), and SetVx2Score().

2699  {
2700  // returns the fraction of the charge in the region around pos that is associated with
2701  // the list of Tj IDs
2702  if(tjIDs.empty()) return 0;
2703  std::array<int, 2> wireWindow;
2704  Point2_t timeWindow;
2705  // 1/2 size of the region
2706  constexpr float NNDelta = 5;
2707  wireWindow[0] = pos[0] - NNDelta;
2708  wireWindow[1] = pos[0] + NNDelta;
2709  timeWindow[0] = pos[1] - NNDelta;
2710  timeWindow[1] = pos[1] + NNDelta;
2711  // do some checking
2712  for(auto& tjID : tjIDs) if(tjID <= 0 || tjID > (int)slc.tjs.size()) return 0;
2713  // Determine which plane we are in
2714  geo::PlaneID planeID = DecodeCTP(slc.tjs[tjIDs[0]-1].CTP);
2715  // get a list of all hits in this region
2716  bool hitsNear;
2717  std::vector<unsigned int> closeHits = FindCloseHits(slc, wireWindow, timeWindow, planeID.Plane, kAllHits, true, hitsNear);
2718  if(closeHits.empty()) return 0;
2719  float chg = 0;
2720  float tchg = 0;
2721  // Add the hit charge in the box
2722  // All hits in the box, and all hits associated with the Tjs
2723  for(auto& iht : closeHits) {
2724  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2725  chg += hit.Integral();
2726  if(slc.slHits[iht].InTraj == 0) continue;
2727  if(std::find(tjIDs.begin(), tjIDs.end(), slc.slHits[iht].InTraj) != tjIDs.end()) tchg += hit.Integral();
2728  } // iht
2729  if(chg == 0) return 0;
2730  return tchg / chg;
2731  } // 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
Detector simulation of raw signals on wires.
bool FindCloseHits(TCSlice &slc, TrajPoint &tp, float const &maxDelta, HitStatus_t hitRequest)
Definition: Utils.cxx:2552
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
void tca::ChgSlope ( TCSlice slc,
Trajectory tj,
float &  slope,
float &  slopeErr,
float &  chiDOF 
)

Definition at line 1288 of file Utils.cxx.

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

Referenced by Forecast(), and SetStrategy().

1289  {
1290  // Fits the points with charge on the Tj and returns the charge slope, slope error and
1291  // Chi/DOF
1292  ChgSlope(slc, tj, tj.EndPt[0], tj.EndPt[1], slope, slopeErr, chiDOF);
1293  } // ChgSlope
void ChgSlope(TCSlice &slc, Trajectory &tj, unsigned short fromPt, unsigned short toPt, float &slope, float &slopeErr, float &chiDOF)
Definition: Utils.cxx:1296
void tca::ChgSlope ( TCSlice slc,
Trajectory tj,
unsigned short  fromPt,
unsigned short  toPt,
float &  slope,
float &  slopeErr,
float &  chiDOF 
)

Definition at line 1296 of file Utils.cxx.

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

Referenced by ChgSlope().

1297  {
1298  // Fits the points with charge on the Tj and returns the charge slope, slope error and
1299  // Chi/DOF
1300 
1301  slope = -1000;
1302  slopeErr = 1000;
1303  chiDOF = 1000;
1304 
1305  // prepare to do the fit
1306  Point2_t inPt;
1307  Vector2_t outVec, outVecErr;
1308  float chgErr;
1309  // Initialize
1310  Fit2D(0, inPt, chgErr, outVec, outVecErr, chiDOF);
1311  float wire0 = -1;
1312  unsigned short cnt = 0;
1313  for(unsigned short ipt = fromPt; ipt <= toPt; ++ipt) {
1314  auto& tp = tj.Pts[ipt];
1315  if(tp.Chg <= 0) continue;
1316  ++cnt;
1317  if(wire0 < 0) wire0 = tp.Pos[0];
1318  // Accumulate and save points
1319  inPt[0] = std::abs(tp.Pos[0] - wire0);
1320  inPt[1] = tp.Chg;
1321  // Assume 10% point-to-point charge fluctuations
1322  chgErr = 0.1 * tp.Chg;
1323  if(!Fit2D(2, inPt, chgErr, outVec, outVecErr, chiDOF)) break;
1324  } // tp
1325  if(cnt < 3) return;
1326  // do the fit and get the results
1327  if(!Fit2D(-1, inPt, chgErr, outVec, outVecErr, chiDOF)) return;
1328  slope = outVec[1];
1329  slopeErr = outVecErr[1];
1330  } // ChgSlope
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
bool Fit2D(short mode, Point2_t inPt, float &inPtErr, Vector2_t &outVec, Vector2_t &outVecErr, float &chiDOF)
Definition: Utils.cxx:4536
std::array< double, 2 > Vector2_t
Definition: DataStructs.h:38
float tca::ChgToMeV ( float  chg)

Definition at line 4395 of file TCShower.cxx.

Referenced by FindParent(), MergeSubShowersTj(), ShowerEnergy(), and UpdateShower().

4396  {
4397  // Conversion from shower charge to energy in MeV. The calibration factor
4398  // was found by processing 500 pizero events with StudyPiZeros using StudyMode
4399  return 0.012 * chg;
4400  }
bool tca::ChkAssns ( std::string  inFcnLabel,
TCSlice slc 
)

Definition at line 4560 of file TCShower.cxx.

References tca::TCSlice::cots, kKilled, tca::TCSlice::showers, ss, and tca::TCSlice::tjs.

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

4561  {
4562  // check tj - ss assns
4563 
4564  std::string fcnLabel = inFcnLabel + ".ChkAssns";
4565  for(auto& ss : slc.cots) {
4566  if(ss.ID == 0) continue;
4567  for(auto tid : ss.TjIDs) {
4568  auto& tj = slc.tjs[tid - 1];
4569  if(tj.SSID != ss.ID) {
4570  std::cout<<fcnLabel<<" ***** Error: 2S"<<ss.ID<<" -> TjIDs T"<<tid<<" != tj.SSID 2S"<<tj.SSID<<"\n";
4571  return false;
4572  }
4573  } // tid
4574  // check 2S -> 3S
4575  if(ss.SS3ID > 0 && ss.SS3ID <= (int)slc.showers.size()) {
4576  auto& ss3 = slc.showers[ss.SS3ID - 1];
4577  if(std::find(ss3.CotIDs.begin(), ss3.CotIDs.end(), ss.ID) == ss3.CotIDs.end()) {
4578  std::cout<<fcnLabel<<" ***** Error: 2S"<<ss.ID<<" -> 3S"<<ss.SS3ID<<" but the shower says no\n";
4579  return false;
4580  }
4581  } // ss.SS3ID > 0
4582  } // ss
4583  for(auto& tj : slc.tjs) {
4584  if(tj.AlgMod[kKilled]) continue;
4585  if(tj.SSID < 0) {
4586  std::cout<<fcnLabel<<" ***** Error: T"<<tj.ID<<" tj.SSID is fubar\n";
4587  tj.SSID = 0;
4588  return false;
4589  }
4590  if(tj.SSID == 0) continue;
4591  auto& ss = slc.cots[tj.SSID - 1];
4592  if(std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tj.ID) != ss.TjIDs.end()) continue;
4593  std::cout<<fcnLabel<<" ***** Error: T"<<tj.ID<<" tj.SSID = 2S"<<tj.SSID<<" but the shower says no\n";
4594  return false;
4595  } // tj
4596 
4597  for(auto& ss3 : slc.showers) {
4598  if(ss3.ID == 0) continue;
4599  for(auto cid : ss3.CotIDs) {
4600  auto& ss = slc.cots[cid - 1];
4601  if(ss.SS3ID != ss3.ID) {
4602  std::cout<<fcnLabel<<" ***** Error: 3S"<<ss3.ID<<" -> 2S"<<cid<<" but it thinks it belongs to 3S"<<ss.SS3ID<<"\n";
4603  return false;
4604  }
4605  } // cid
4606  } // ss3
4607  return true;
4608  } // ChkAssns
Float_t ss
Definition: plot.C:23
void tca::ChkChgAsymmetry ( TCSlice slc,
Trajectory tj,
bool  prt 
)

Definition at line 1611 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::EndPt, tca::Trajectory::ID, kChkChgAsym, kNewStpCuts, tca::Trajectory::PDGCode, PrintTrajectory(), tca::Trajectory::Pts, SetEndPoints(), tcc, UnsetUsedHits(), and tca::TCConfig::useAlg.

Referenced by CheckTraj().

1612  {
1613  // looks for a high-charge point in the trajectory which may be due to the
1614  // trajectory crossing an interaction vertex. The properties of points on the opposite
1615  // sides of the high-charge point are analyzed. If significant differences are found, all points
1616  // near the high-charge point are removed as well as those from that point to the end
1617  if(!tcc.useAlg[kChkChgAsym]) return;
1618  if(tcc.useAlg[kNewStpCuts] && tj.PDGCode == 111) return;
1619  unsigned short npts = tj.EndPt[1] - tj.EndPt[0];
1620  if(prt) mf::LogVerbatim("TC")<<" Inside ChkChgAsymmetry T"<<tj.ID;
1621  // ignore long tjs
1622  if(npts > 50) return;
1623  // ignore short tjs
1624  if(npts < 8) return;
1625  // require the charge pull > 5
1626  float bigPull = 5;
1627  unsigned short atPt = 0;
1628  // Don't consider the first/last few points in case there is a Bragg peak
1629  for(unsigned short ipt = tj.EndPt[0] + 2; ipt <= tj.EndPt[1] - 2; ++ipt) {
1630  auto& tp = tj.Pts[ipt];
1631  if(tp.ChgPull > bigPull) {
1632  bigPull = tp.ChgPull;
1633  atPt = ipt;
1634  }
1635  } // ipt
1636  if(atPt == 0) return;
1637  // require that this point be near the DS end
1638  if((atPt - tj.EndPt[0]) < 0.5 * npts) return;
1639  if(prt) mf::LogVerbatim("TC")<<"CCA: T"<<tj.ID<<" Large Chg point at "<<atPt<<". Check charge asymmetry around it.";
1640  unsigned short nchk = 0;
1641  unsigned short npos = 0;
1642  unsigned short nneg = 0;
1643  for(short ii = 1; ii < 5; ++ii) {
1644  short iplu = atPt + ii;
1645  if(iplu > tj.EndPt[1]) break;
1646  short ineg = atPt - ii;
1647  if(ineg < tj.EndPt[0]) break;
1648  if(tj.Pts[iplu].Chg == 0) continue;
1649  if(tj.Pts[ineg].Chg == 0) continue;
1650  float asym = (tj.Pts[iplu].Chg - tj.Pts[ineg].Chg) / (tj.Pts[iplu].Chg + tj.Pts[ineg].Chg);
1651  ++nchk;
1652  if(asym > 0.5) ++npos;
1653  if(asym < -0.5) ++nneg;
1654  if(prt) mf::LogVerbatim("TC")<<" ineg "<<ineg<<" iplu "<<iplu<<" asym "<<asym<<" nchk "<<nchk;
1655  } // ii
1656  if(nchk < 3) return;
1657  // require most of the points be very positive or very negative
1658  nchk -= 2;
1659  bool doTrim = (nneg > nchk) || (npos > nchk);
1660  if(!doTrim) return;
1661  // remove all the points at the end starting at the one just before the peak if the pull is not so good
1662  auto& prevTP = tj.Pts[atPt - 1];
1663  if(std::abs(prevTP.ChgPull) > 2) --atPt;
1664  for(unsigned short ipt = atPt; ipt <= tj.EndPt[1]; ++ipt) UnsetUsedHits(slc, tj.Pts[ipt]);
1665  SetEndPoints(tj);
1666  tj.AlgMod[kChkChgAsym] = true;
1667  if(prt) PrintTrajectory("CCA", slc, tj, USHRT_MAX);
1668  } // ChkChgAsymmetry
void PrintTrajectory(std::string someText, TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:5455
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
TCConfig tcc
Definition: DataStructs.cxx:6
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1162
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
void tca::ChkHiChgHits ( TCSlice slc,
CTP_t  inCTP 
)

Definition at line 4105 of file StepUtils.cxx.

References kKilled, kSplitHiChgHits, SplitHiChgHits(), tcc, tca::TCSlice::tjs, and tca::TCConfig::useAlg.

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

4106  {
4107  // Check allTraj trajectories in the current CTP to see if they are stopping
4108  if(!tcc.useAlg[kSplitHiChgHits]) return;
4109 
4110  for(size_t i = 0; i< slc.tjs.size(); ++i) {
4111  auto & tj = slc.tjs[i];
4112  if(tj.CTP != inCTP) continue;
4113  if(tj.AlgMod[kKilled]) continue;
4114  SplitHiChgHits(slc, tj);
4115  } // tj
4116 
4117  } // ChkHiChgHits
TCConfig tcc
Definition: DataStructs.cxx:6
void SplitHiChgHits(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:4120
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
bool tca::ChkMichel ( TCSlice slc,
Trajectory tj,
unsigned short &  lastGoodPt 
)

Definition at line 4049 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::TCConfig::dbgAlg, tca::TCConfig::dbgStp, tca::Trajectory::EndPt, kMichel, tca::Trajectory::Pts, tcc, and tca::TCConfig::useAlg.

Referenced by MaskTrajEndPoints().

4049  {
4050 
4051  if(!tcc.useAlg[kMichel]) return false;
4052 
4053  bool prt = (tcc.dbgStp || tcc.dbgAlg[kMichel]);
4054 
4055  //find number of hits that are consistent with Michel electron
4056  unsigned short nmichelhits = 0;
4057  //find number of hits that are consistent with Bragg peak
4058  unsigned short nbragghits = 0;
4059  float lastChg = 0;
4060 
4061  bool isfirsthit = true;
4062  unsigned short braggpeak = 0;
4063 
4064  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
4065  if (ii>tj.EndPt[1]) continue;
4066  unsigned short ipt = tj.EndPt[1] - ii;
4067  if (tj.Pts[ipt].Chg>0){
4068  if (isfirsthit){
4069  isfirsthit = false;
4070  if (tj.Pts[ipt].ChgPull<0){
4071  ++nmichelhits;
4072  }
4073  }
4074  else{
4075  if (tj.Pts[ipt].ChgPull<0&&nmichelhits&&!nbragghits){//still Michel
4076  ++nmichelhits;
4077  }
4078  else{
4079  if (!nbragghits){
4080  ++nbragghits; //Last Bragg peak hit
4081  lastChg = tj.Pts[ipt].Chg;
4082  braggpeak = ipt;
4083  }
4084  else if (tj.Pts[ipt].Chg<lastChg){ //still Bragg peak
4085  ++nbragghits;
4086  lastChg = tj.Pts[ipt].Chg;
4087  }
4088  else break;
4089  }
4090  }
4091  }
4092  }
4093  if(prt) mf::LogVerbatim("TC")<<"ChkMichel Michel hits: "<<nmichelhits<<" Bragg peak hits: "<<nbragghits;
4094  if (nmichelhits>0&&nbragghits>2){//find Michel topology
4095  lastGoodPt = braggpeak;
4096  tj.AlgMod[kMichel] = true;
4097  return true;
4098  }
4099  else{
4100  return false;
4101  }
4102  }
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:505
void tca::ChkStop ( TCSlice slc,
Trajectory tj 
)

Definition at line 3952 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::TrajPoint::Chg, tca::TCConfig::chkStopCuts, tca::TCConfig::dbgAlg, tca::TCConfig::dbgStp, dir, evd::details::end(), tca::Trajectory::EndPt, Fit2D(), tca::Trajectory::ID, kBragg, kChkStop, kStiffEl, tca::Trajectory::MCSMom, tca::TrajPoint::Pos, tca::Trajectory::Pts, tca::Trajectory::StopFlag, tca::Trajectory::Strategy, tcc, and tca::TCConfig::useAlg.

Referenced by CheckTraj(), ChkStopEndPts(), Forecast(), and ReversePropagate().

3953  {
3954  // Sets the StopFlag[kBragg] bits on the trajectory by identifying the Bragg peak
3955  // at each end. This function checks both ends, finding the point with the highest charge nearest the
3956  // end and considering the first (when end = 0) 4 points or last 4 points (when end = 1). The next
3957  // 5 - 10 points (fChkStop[0]) are fitted to a line, Q(x - x0) = Qo + (x - x0) * slope where x0 is the
3958  // wire position of the highest charge point. A large negative slope indicates that there is a Bragg
3959  // peak at the end.
3960 
3961  tj.StopFlag[0][kBragg] = false;
3962  tj.StopFlag[1][kBragg] = false;
3963  if(!tcc.useAlg[kChkStop]) return;
3964  if(tcc.chkStopCuts[0] < 0) return;
3965 
3966  // don't attempt with low momentum trajectories
3967  if(tj.MCSMom < 30) return;
3968 
3969  if(tj.Strategy[kStiffEl]) return;
3970 
3971  // ignore trajectories that are very large angle at both ends
3972  if(tj.Pts[tj.EndPt[0]].AngleCode == 2 || tj.Pts[tj.EndPt[1]].AngleCode == 2) return;
3973 
3974  unsigned short nPtsToCheck = tcc.chkStopCuts[1];
3975  if(tj.Pts.size() < 6) return;
3976 
3977  bool prt = (tcc.dbgStp || tcc.dbgAlg[kChkStop]);
3978 
3979  if(prt) {
3980  mf::LogVerbatim("TC")<<"ChkStop: T"<<tj.ID<<" requiring "<<nPtsToCheck<<" points with charge slope > "<<tcc.chkStopCuts[0]<<" Chg/WSEU";
3981  }
3982 
3983  // find the highest charge hit in the first 3 points at each end
3984  for(unsigned short end = 0; end < 2; ++end) {
3985  short dir = 1 - 2 * end;
3986  // find the point with the highest charge considering the first 3 points
3987  float big = 0;
3988  unsigned short hiPt = 0;
3989  float wire0 = 0;
3990  for(unsigned short ii = 0; ii < 5; ++ii) {
3991  short ipt = tj.EndPt[end] + ii * dir;
3992  if(ipt < tj.EndPt[0] || ipt > tj.EndPt[1]) break;
3993  TrajPoint& tp = tj.Pts[ipt];
3994  if(tp.Chg > big) {
3995  big = tp.Chg;
3996  wire0 = tp.Pos[0];
3997  hiPt = ipt;
3998  }
3999  } // ii
4000  if(prt) mf::LogVerbatim("TC")<<" end "<<end<<" wire0 "<<wire0<<" Chg "<<big<<" hiPt "<<hiPt;
4001  float prevChg = big;
4002  // prepare to do the fit
4003  Point2_t inPt;
4004  Vector2_t outVec, outVecErr;
4005  float chgErr, chiDOF;
4006  // Initialize
4007  Fit2D(0, inPt, chgErr, outVec, outVecErr, chiDOF);
4008  unsigned short cnt = 0;
4009  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
4010  short ipt = hiPt + ii * dir;
4011  if(ipt < tj.EndPt[0] || ipt > tj.EndPt[1]) break;
4012  TrajPoint& tp = tj.Pts[ipt];
4013  if(tp.Chg == 0) continue;
4014  // quit if the charge is much larger than the previous charge
4015  if(tp.Chg > 1.5 * prevChg) continue;
4016  prevChg = tp.Chg;
4017  // Accumulate and save points
4018  inPt[0] = std::abs(tp.Pos[0] - wire0);
4019  inPt[1] = tp.Chg;
4020  // Assume 20% point-to-point charge fluctuations
4021  chgErr = 0.2 * tp.Chg;
4022  if(!Fit2D(2, inPt, chgErr, outVec, outVecErr, chiDOF)) break;
4023 // if(tcc.dbgStp) mf::LogVerbatim("TC")<<ipt<<" "<<PrintPos(slc, tp.Pos)<<" "<<inPt[0]<<" Chg "<<(int)tp.Chg;
4024  ++cnt;
4025  if(cnt == nPtsToCheck) break;
4026  } // ii
4027  if(cnt < 4) continue;
4028  // do the fit and get the results
4029  if(!Fit2D(-1, inPt, chgErr, outVec, outVecErr, chiDOF)) continue;
4030  // check for really bad chidof indicating a major failure
4031  if(chiDOF > 500) continue;
4032  // The charge slope is negative for a stopping track in the way that the fit was constructed.
4033  // Flip the sign so we can make a cut against tcc.chkStopCuts[0] which is positive.
4034  outVec[1] = -outVec[1];
4035  if(outVec[1] > tcc.chkStopCuts[0] && chiDOF < tcc.chkStopCuts[2] && outVec[1] > 2 * outVecErr[1]) {
4036  tj.StopFlag[end][kBragg] = true;
4037  tj.AlgMod[kChkStop] = true;
4038  // Put the charge at the end into tp.AveChg
4039  tj.Pts[tj.EndPt[end]].AveChg = outVec[0];
4040  if(prt) mf::LogVerbatim("TC")<<" end "<<end<<" fit chidof "<<chiDOF<<" slope "<<outVec[1]<<" +/- "<<outVecErr[1]<<" stopping";
4041  } else {
4042  if(prt) mf::LogVerbatim("TC")<<" end "<<end<<" fit chidof "<<chiDOF<<" slope "<<outVec[1]<<" +/- "<<outVecErr[1]<<" Not stopping";
4043  }
4044  } // end
4045 
4046  } // ChkStop
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
bool Fit2D(short mode, Point2_t inPt, float &inPtErr, Vector2_t &outVec, Vector2_t &outVecErr, float &chiDOF)
Definition: Utils.cxx:4536
std::array< double, 2 > Vector2_t
Definition: DataStructs.h:38
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
TDirectory * dir
Definition: macro.C:5
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:505
use the stiff electron strategy
Definition: DataStructs.h:418
std::vector< float > chkStopCuts
[Min Chg ratio, Chg slope pull cut, Chg fit chi cut]
Definition: DataStructs.h:473
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void tca::ChkStopEndPts ( TCSlice slc,
Trajectory tj,
bool  prt 
)

Definition at line 1711 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, ChkStop(), tca::TrajPoint::CTP, tca::Trajectory::CTP, tca::TCConfig::dbgStp, DecodeCTP(), DefineHitPos(), tca::TrajPoint::Dir, tca::Trajectory::EndPt, FindCloseHits(), tca::Trajectory::ID, kAllHits, kBragg, kChkStopEP, kJunkTj, kNewStpCuts, kStiffEl, geo::PlaneID::Plane, tca::TrajPoint::Pos, PrintHit(), PrintPos(), tca::Trajectory::Pts, SetEndPoints(), tca::TCSlice::slHits, tca::Trajectory::StopFlag, tca::Trajectory::Strategy, tcc, tmp, UnsetUsedHits(), UpdateTjChgProperties(), and tca::TCConfig::useAlg.

Referenced by CheckTraj(), FixTrajBegin(), and ReversePropagate().

1712  {
1713  // Analyze the end of the Tj after crawling has stopped to see if any of the points
1714  // should be used
1715  // TODO: This function results in a small loss of efficiency and needs work. Perhaps by requir
1716 
1717  if(!tcc.useAlg[kChkStopEP]) return;
1718  if(tj.AlgMod[kJunkTj]) return;
1719  if(tj.Strategy[kStiffEl]) return;
1720 
1721  unsigned short endPt = tj.EndPt[1];
1722  // ignore VLA Tjs
1723  if(tj.Pts[endPt].AngleCode > 1) return;
1724  // don't get too carried away with this
1725  if(tj.Pts.size() - endPt > 10) return;
1726 
1727  // Get a list of hits a few wires beyond the last point on the Tj
1728  geo::PlaneID planeID = DecodeCTP(tj.CTP);
1729  unsigned short plane = planeID.Plane;
1730 
1731  // find the last point that has hits on it
1732  unsigned short lastPt = tj.Pts.size() - 1;
1733  for(lastPt = tj.Pts.size() - 1; lastPt >= tj.EndPt[1]; --lastPt) if(!tj.Pts[lastPt].Hits.empty()) break;
1734  auto& lastTP = tj.Pts[lastPt];
1735 
1736  if(tcc.dbgStp) {
1737  mf::LogVerbatim("TC")<<"CSEP: checking "<<tj.ID<<" endPt "<<endPt<<" Pts size "<<tj.Pts.size()<<" lastPt Pos "<<PrintPos(slc, lastTP.Pos);
1738  }
1739 
1740  // Check the charge and delta of the last point if there were many points fit
1741  // BB 11/26/ 2018 This is a bad idea for stopping tracks
1742  if(!tcc.useAlg[kNewStpCuts]) {
1743  if(lastTP.NTPsFit > 10 && lastTP.DeltaRMS > 0 && (lastTP.Delta / lastTP.DeltaRMS) > 3 && lastTP.ChgPull > 3) {
1744  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Removing last TP with large Delta "<<lastTP.Delta<<" and large ChgPull "<<lastTP.ChgPull;
1745  UnsetUsedHits(slc, lastTP);
1746  tj.AlgMod[kChkStopEP] = true;
1747  SetEndPoints(tj);
1748  // check again
1749  auto& tp = tj.Pts[tj.EndPt[1]];
1750  if(tp.DeltaRMS > 0 && (tp.Delta / tp.DeltaRMS) > 3 && tp.ChgPull > 3) {
1751  UnsetUsedHits(slc, tp);
1752  SetEndPoints(tj);
1753  }
1754  return;
1755  }
1756  }
1757 
1758  TrajPoint ltp;
1759  ltp.CTP = tj.CTP;
1760  ltp.Pos = tj.Pts[endPt].Pos;
1761  ltp.Dir = tj.Pts[endPt].Dir;
1762  double stepSize = std::abs(1/ltp.Dir[0]);
1763  std::array<int, 2> wireWindow;
1764  std::array<float, 2> timeWindow;
1765  std::vector<int> closeHits;
1766  bool isClean = true;
1767  for(unsigned short step = 0; step < 10; ++step) {
1768  for(unsigned short iwt = 0; iwt < 2; ++iwt) ltp.Pos[iwt] += ltp.Dir[iwt] * stepSize;
1769  int wire = std::nearbyint(ltp.Pos[0]);
1770  wireWindow[0] = wire;
1771  wireWindow[1] = wire;
1772  timeWindow[0] = ltp.Pos[1] - 5;
1773  timeWindow[1] = ltp.Pos[1] + 5;
1774  bool hitsNear;
1775  auto tmp = FindCloseHits(slc, wireWindow, timeWindow, plane, kAllHits, true, hitsNear);
1776  // add close hits that are not associated with this tj
1777  for(auto iht : tmp) if(slc.slHits[iht].InTraj != tj.ID) closeHits.push_back(iht);
1778  float nWiresPast = 0;
1779  // Check beyond the end of the trajectory to see if there are hits there
1780  if(ltp.Dir[0] > 0) {
1781  // stepping +
1782  nWiresPast = ltp.Pos[0] - lastTP.Pos[0];
1783  } else {
1784  // stepping -
1785  nWiresPast = lastTP.Pos[0] - ltp.Pos[0];
1786  }
1787  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Found "<<tmp.size()<<" hits near pos "<<PrintPos(slc, ltp.Pos)<<" nWiresPast "<<nWiresPast;
1788  if(nWiresPast > 0.5) {
1789  if(!tmp.empty()) isClean = false;
1790  if(nWiresPast > 1.5) break;
1791  } // nWiresPast > 0.5
1792  } // step
1793 
1794  // count the number of available hits
1795  unsigned short nAvailable = 0;
1796  for(auto iht : closeHits) if(slc.slHits[iht].InTraj == 0) ++nAvailable;
1797 
1798  if(tcc.dbgStp) {
1799  mf::LogVerbatim myprt("TC");
1800  myprt<<"closeHits";
1801  for(auto iht : closeHits) myprt<<" "<<PrintHit(slc.slHits[iht]);
1802  myprt<<" nAvailable "<<nAvailable;
1803  myprt<<" isClean "<<isClean;
1804  } // prt
1805 
1806  if(!isClean || nAvailable != closeHits.size()) return;
1807 
1808  unsigned short originalEndPt = tj.EndPt[1] + 1;
1809  // looks clean so use all the hits
1810  for(unsigned short ipt = originalEndPt; ipt <= lastPt; ++ipt) {
1811  auto& tp = tj.Pts[ipt];
1812  bool hitsAdded = false;
1813  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1814  // This shouldn't happen but check anyway
1815  if(slc.slHits[tp.Hits[ii]].InTraj != 0) continue;
1816  tp.UseHit[ii] = true;
1817  slc.slHits[tp.Hits[ii]].InTraj = tj.ID;
1818  hitsAdded = true;
1819  } // ii
1820  if(hitsAdded) DefineHitPos(slc, tp);
1821  } // ipt
1822  tj.AlgMod[kChkStopEP] = true;
1823  SetEndPoints(tj);
1824  // Re-fitting the end might be a good idea but it's probably not necessary. The
1825  // values of Delta should have already been filled
1826 
1827  // require a Bragg peak
1828  ChkStop(slc, tj);
1829  if(!tj.StopFlag[1][kBragg]) {
1830  // restore the original
1831  for(unsigned short ipt = originalEndPt; ipt <= lastPt; ++ipt) UnsetUsedHits(slc, tj.Pts[ipt]);
1832  SetEndPoints(tj);
1833  } // no Bragg Peak
1834 
1835  UpdateTjChgProperties("CSEP", slc, tj, prt);
1836 
1837  } // ChkStopEndPts
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1162
Float_t tmp
Definition: plot.C:37
std::vector< unsigned int > FindCloseHits(TCSlice &slc, std::array< int, 2 > const &wireWindow, Point2_t const &timeWindow, const unsigned short plane, HitStatus_t hitRequest, bool usePeakTime, bool &hitsNear)
Definition: Utils.cxx:2496
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1840
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:5704
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3196
void ChkStop(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:3952
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
geo::PlaneID DecodeCTP(CTP_t CTP)
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
use the stiff electron strategy
Definition: DataStructs.h:418
bool tca::ChkVtxAssociations ( TCSlice slc,
const CTP_t inCTP 
)

Definition at line 2326 of file TCVertex.cxx.

References DecodeCTP(), evd::details::end(), kHaloTj, kKilled, geo::PlaneID::Plane, tca::TCSlice::tjs, tca::TCSlice::vtx3s, and tca::TCSlice::vtxs.

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

2327  {
2328  // Check the associations
2329 
2330  // check the 2D -> 3D associations
2331  geo::PlaneID planeID = DecodeCTP(inCTP);
2332  unsigned short plane = planeID.Plane;
2333  for(auto& vx2 : slc.vtxs) {
2334  if(vx2.CTP != inCTP) continue;
2335  if(vx2.ID == 0) continue;
2336  if(vx2.Vx3ID == 0) continue;
2337  if(vx2.Vx3ID > int(slc.vtx3s.size())) {
2338  mf::LogVerbatim("TC")<<"ChkVtxAssociations: Invalid vx2.Vx3ID "<<vx2.Vx3ID<<" in 2D vtx "<<vx2.ID;
2339  return false;
2340  }
2341  auto& vx3 = slc.vtx3s[vx2.Vx3ID-1];
2342  if(vx3.ID == 0) {
2343  mf::LogVerbatim("TC")<<"ChkVtxAssociations: 2V"<<vx2.ID<<" thinks it is matched to 3V"<<vx3.ID<<" but vx3 is obsolete";
2344  return false;
2345  }
2346  if(vx3.Vx2ID[plane] != vx2.ID) {
2347  mf::LogVerbatim("TC")<<"ChkVtxAssociations: 2V"<<vx2.ID<<" thinks it is matched to 3V"<<vx3.ID<<" but vx3 says no!";
2348  return false;
2349  }
2350  } // vx2
2351  // check the 3D -> 2D associations
2352  for(auto& vx3 : slc.vtx3s) {
2353  if(vx3.ID == 0) continue;
2354  if(vx3.Vx2ID[plane] == 0) continue;
2355  if(vx3.Vx2ID[plane] > (int)slc.vtxs.size()) {
2356  mf::LogVerbatim("TC")<<"ChkVtxAssociations: Invalid vx3.Vx2ID "<<vx3.Vx2ID[plane]<<" in CTP "<<inCTP;
2357  return false;
2358  }
2359  auto& vx2 = slc.vtxs[vx3.Vx2ID[plane]-1];
2360  if(vx2.Vx3ID != vx3.ID) {
2361  mf::LogVerbatim("TC")<<"ChkVtxAssociations: 3V"<<vx3.ID<<" thinks it is matched to 2V"<<vx2.ID<<" but vx2 says no!";
2362  return false;
2363  }
2364  } // vx3
2365 
2366  // check the Tj -> 2D associations
2367  for(auto& tj : slc.tjs) {
2368  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
2369  for(unsigned short end = 0; end < 2; ++end) {
2370  if(tj.VtxID[end] == 0) continue;
2371  if(tj.VtxID[end] > slc.vtxs.size()) {
2372  mf::LogVerbatim("TC")<<"ChkVtxAssociations: T"<<tj.ID<<" thinks it is matched to 2V"<<tj.VtxID[end]<<" on end "<<end<<" but no vertex exists. Recovering";
2373  tj.VtxID[end] = 0;
2374  return false;
2375  }
2376  unsigned short ivx = tj.VtxID[end] - 1;
2377  auto& vx2 = slc.vtxs[ivx];
2378  if(vx2.ID == 0) {
2379  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";
2380  tj.VtxID[end] = 0;
2381  return false;
2382  }
2383  } // end
2384  } // tj
2385 
2386  return true;
2387 
2388  } // 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)
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void tca::ChkVxTjs ( TCSlice slc,
const CTP_t inCTP,
bool  prt 
)

Definition at line 874 of file TCVertex.cxx.

References close(), CompatibleMerge(), DeltaAngle(), FarEnd(), GetAssns(), tca::TCSlice::ID, kChkVxTj, kDeltaRay, kFixed, kHaloTj, kKilled, kNewVtxCuts, kOnDeadWire, MakeVertexObsolete(), MergeAndStore(), PointTrajDOCA(), PosSep(), PrintPos(), tcc, tca::TCSlice::tjs, tca::TCConfig::useAlg, and tca::TCSlice::vtxs.

Referenced by EndMerge(), and Find2DVertices().

875  {
876  //
877 
878  if(!tcc.useAlg[kChkVxTj]) return;
879 
880  for(unsigned short ivx = 0; ivx < slc.vtxs.size(); ++ivx) {
881  auto& vx2 = slc.vtxs[ivx];
882  if(vx2.ID == 0) continue;
883  if(vx2.CTP != inCTP) continue;
884  auto vxtjs = GetAssns(slc, "2V", vx2.ID, "T");
885  if(vxtjs.size() < 2) continue;
886  if(tcc.useAlg[kNewVtxCuts] && vx2.Stat[kOnDeadWire]) continue;
887  // BB added June 4, 2018
888  // find the closest separation between the vertex and the ends of the tjs
889  float close = 200;
890  int closeID = 0;
891  unsigned short closeEnd = 0;
892  for(auto tid : vxtjs) {
893  auto& tj = slc.tjs[tid - 1];
894  unsigned short nearEnd = 1 - FarEnd(slc, tj, vx2.Pos);
895  if(tj.VtxID[nearEnd] != vx2.ID) continue;
896  float sep = PosSep(tj.Pts[tj.EndPt[nearEnd]].Pos, vx2.Pos);
897  if(sep > close) continue;
898  close = sep;
899  closeID = tid;
900  closeEnd = nearEnd;
901  } // tid
902  if(close > 1.5 && closeID > 0) {
903  auto& closeTj = slc.tjs[closeID - 1];
904  auto& closeTP = closeTj.Pts[closeTj.EndPt[closeEnd]];
905  if(prt) mf::LogVerbatim("TC")<<"CVTjs: moved 2V"<<vx2.ID<<" from "<<PrintPos(slc, vx2.Pos)<<" to "<<PrintPos(slc, closeTP);
906  vx2.Pos = closeTP.Pos;
907  vx2.Stat[kFixed] = true;
908  }
909  for(unsigned short it1 = 0; it1 < vxtjs.size() - 1; ++it1) {
910  auto& tj1 = slc.tjs[vxtjs[it1] - 1];
911  if(tj1.AlgMod[kKilled] || tj1.AlgMod[kHaloTj]) continue;
912  unsigned short end1 = 0;
913  if(tj1.VtxID[1] == vx2.ID) end1 = 1;
914  auto& vtp1 = tj1.Pts[tj1.EndPt[end1]];
915  auto& otp1 = tj1.Pts[tj1.EndPt[1 - end1]];
916  float tj1sep = PosSep(vtp1.Pos, vx2.Pos);
917  for(unsigned short it2 = it1 + 1; it2 < vxtjs.size(); ++it2) {
918  auto& tj2 = slc.tjs[vxtjs[it2] - 1];
919  if(tj2.AlgMod[kKilled] || tj2.AlgMod[kHaloTj]) continue;
920  unsigned short end2 = 0;
921  if(tj2.VtxID[2] == vx2.ID) end2 = 1;
922  auto& vtp2 = tj2.Pts[tj2.EndPt[end2]];
923  auto& otp2 = tj2.Pts[tj2.EndPt[1 - end2]];
924  float tj2sep = PosSep(vtp2.Pos, vx2.Pos);
925  float otj1tj2 = PosSep(otp1.Pos, vtp2.Pos);
926  float delta12 = PointTrajDOCA(slc, otp1.Pos[0], otp1.Pos[1], vtp2);
927  float dang12 = DeltaAngle(otp1.Ang, vtp2.Ang);
928  if(otj1tj2 < tj2sep && delta12 < 1 && otj1tj2 < 4) {
929  if(prt) {
930  mf::LogVerbatim myprt("TC");
931  myprt<<"CVTjs: "<<vx2.ID<<" tj1 "<<tj1.ID<<" tj2 "<<tj2.ID;
932  myprt<<" otj1tj2 "<<otj1tj2;
933  myprt<<" delta12 "<<delta12;
934  myprt<<" dang12 "<<dang12;
935  myprt<<" Try to merge";
936  }
937  // End 1 of tj1 is closer to end0 of tj2 than tj2 is to the vertex
938  tj2.VtxID[end2] = 0;
939  if(CompatibleMerge(slc, tj1, tj2, prt) && MergeAndStore(slc, vxtjs[it1], vxtjs[it2], prt)) {
940  auto& newTj = slc.tjs[slc.tjs.size()-1];
941  newTj.AlgMod[kChkVxTj] = true;
942  if(prt) mf::LogVerbatim("TC")<<"CVTjs: Merged tjs "<<tj1.ID<<" and "<<tj2.ID<<" -> "<<newTj.ID;
943  } else {
944  if(prt) mf::LogVerbatim("TC")<<"CVTjs: Merge failed";
945  }
946  continue;
947  } // other end is closer
948  // now check the other end of tj2
949  float tj1otj2 = PosSep(vtp1.Pos, otp2.Pos);
950  if(tj1otj2 < tj1sep && delta12 < 1 && tj1otj2 < 4) {
951  // End 1 of tj1 is closer to end0 of tj2 than tj2 is to the vertex
952  tj1.VtxID[end1] = 0;
953  if(CompatibleMerge(slc, tj2, tj1, prt) && MergeAndStore(slc, vxtjs[it2], vxtjs[it1], prt)) {
954  auto& newTj = slc.tjs[slc.tjs.size()-1];
955  newTj.AlgMod[kChkVxTj] = true;
956  if(prt) mf::LogVerbatim("TC")<<"CVTjs: Merged tjs "<<tj1.ID<<" and "<<tj2.ID<<" -> "<<newTj.ID;
957  } else {
958  if(prt) mf::LogVerbatim("TC")<<"CVTjs: Merge failed";
959  }
960  } // the other end is closer
961  } // it2
962  } // it1
963  // Check for delta-rays that have a vertex when they should have been merged
964  if(vx2.Topo == 1 && vxtjs.size() == 2) {
965  auto& tj1 = slc.tjs[vxtjs[0] - 1];
966  auto& tj2 = slc.tjs[vxtjs[1] - 1];
967  // ensure that these weren't killed above
968  if(tj1.AlgMod[kKilled] || tj2.AlgMod[kKilled]) continue;
969  if(tj1.AlgMod[kDeltaRay] || tj2.AlgMod[kDeltaRay]) {
970  if(prt) mf::LogVerbatim("TC")<<"CVTjs: Merge delta rays "<<tj1.ID<<" and "<<tj2.ID<<" CompatibleMerge? "<<CompatibleMerge(slc, tj1, tj2, prt);
971  MakeVertexObsolete("CVTjs", slc, vx2, true);
972  MergeAndStore(slc, vxtjs[0] - 1, vxtjs[1] - 1, prt);
973  } // one is a tagged delta-ray
974  } // delta-ray check
975  } // ivx
976  } // ChkVxTjs
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeVertexObsolete(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:3208
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4279
TCConfig tcc
Definition: DataStructs.cxx:6
vertex position fixed manually - no fitting done
Definition: DataStructs.h:74
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1636
unsigned short FarEnd(TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3032
bool MergeAndStore(TCSlice &slc, unsigned int itj1, unsigned int itj2, bool doPrt)
Definition: Utils.cxx:4095
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
in close()
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
bool CompatibleMerge(TCSlice &slc, std::vector< int > &tjIDs, bool prt)
Definition: Utils.cxx:534
void tca::CleanTjs ( TCSlice slc,
PFPStruct pfp,
bool  prt 
)
void tca::ClearCRInfo ( TCSlice slc)

Definition at line 118 of file TCCR.cxx.

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

118  {
119  slc.crt.cr_origin.clear();
120  slc.crt.cr_pfpxmin.clear();
121  slc.crt.cr_pfpxmax.clear();
122  slc.crt.cr_pfpyzmindis.clear();
123  }
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.

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
std::vector< int > EnvStage
Definition: DataStructs.h:330
std::vector< int > IsShowerParent
Definition: DataStructs.h:323
std::vector< float > EndWir
Definition: DataStructs.h:310
std::vector< float > EndAng
Definition: DataStructs.h:312
std::vector< float > BeginTim
Definition: DataStructs.h:306
std::vector< float > BeginAng
Definition: DataStructs.h:307
std::vector< float > EndTim
Definition: DataStructs.h:311
std::vector< int > ShowerID
Definition: DataStructs.h:322
ShowerTreeVars stv
Definition: DataStructs.cxx:8
std::vector< int > TjID
Definition: DataStructs.h:320
std::vector< short > BeginVtx
Definition: DataStructs.h:309
std::vector< short > EndVtx
Definition: DataStructs.h:314
std::vector< float > Envelope
Definition: DataStructs.h:328
std::vector< float > BeginChg
Definition: DataStructs.h:308
std::vector< int > EnvPlane
Definition: DataStructs.h:329
std::vector< short > MCSMom
Definition: DataStructs.h:316
std::vector< int > StageNum
Definition: DataStructs.h:324
std::vector< float > BeginWir
Definition: DataStructs.h:305
std::vector< float > EndChg
Definition: DataStructs.h:313
std::vector< int > EnvShowerID
Definition: DataStructs.h:331
std::vector< int > IsShowerTj
Definition: DataStructs.h:321
std::vector< short > PlaneNum
Definition: DataStructs.h:318
unsigned short tca::CloseEnd ( TCSlice slc,
const Trajectory tj,
const Point2_t pos 
)

Definition at line 2251 of file Utils.cxx.

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

Referenced by MergeWithVertex().

2252  {
2253  unsigned short endPt = tj.EndPt[0];
2254  auto& tp0 = tj.Pts[endPt];
2255  endPt = tj.EndPt[1];
2256  auto& tp1 = tj.Pts[endPt];
2257  if(PosSep2(tp0.Pos, pos) < PosSep2(tp1.Pos, pos)) return 0;
2258  return 1;
2259  } // CloseEnd
float PosSep2(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2359
bool tca::CompatibleMerge ( TCSlice slc,
std::vector< int > &  tjIDs,
bool  prt 
)

Definition at line 534 of file Utils.cxx.

References evd::details::end(), tca::TCSlice::tjs, and TrajClosestApproach().

Referenced by ChkVxTjs(), DefinePFP(), and EndMerge().

535  {
536  // Returns true if the last Tj in tjIDs has a topology consistent with it being
537  // merged with other Tjs in the same plane in the list. This is done by requiring that
538  // the closest TP between the last Tj and any other Tj is EndPt[0] or EndPt[1]. This is
539  // shown graphically here where the numbers represent the ID of a Tj that has a TP on a wire.
540  // Assume that TjIDs = {1, 2, 3, 4, 7} where T1 and T3 are in plane 0, T2 is in plane 1 and
541  // T4 is in plane 2. T7, in plane 0, was added to TjIDs with the intent of merging it with
542  // T1 and T3 into a single trajectory. This is a compatible merge if Tj7 has the following
543  // topology:
544  // 111111 333333 7777777
545  // This is an incompatible topology
546  // 111111 333333
547  // 7777777777
548  if(tjIDs.size() < 2) return false;
549  unsigned short lasttj = tjIDs[tjIDs.size() - 1] - 1;
550  auto& mtj = slc.tjs[lasttj];
551  bool mtjIsShort = (mtj.Pts.size() < 5);
552  // minimum separation from each end of mtj
553  std::array<float, 2> minsep2 {{1000, 1000}};
554  // ID of the Tj with the minimum separation
555  std::array<int, 2> minsepTj {{0, 0}};
556  // and the index of the point on that Tj
557  std::array<unsigned short, 2> minsepPt;
558  // determine the end of the closest Tj point. Start by assuming
559  // the closest Tj point is not near an end (end = 0);
560  std::array<unsigned short, 2> minsepEnd;
561  for(auto tjid : tjIDs) {
562  auto& tj = slc.tjs[tjid - 1];
563  if(tj.CTP != mtj.CTP) continue;
564  if(tj.ID == mtj.ID) continue;
565  for(unsigned short mend = 0; mend < 2; ++mend) {
566  Point2_t mendPos = mtj.Pts[mtj.EndPt[mend]].Pos;
567  float sep2 = minsep2[mend];
568  unsigned short closePt = 0;
569  if(!TrajClosestApproach(tj, mendPos[0], mendPos[1], closePt, sep2)) continue;
570  minsep2[mend] = sep2;
571  minsepTj[mend] = tjid;
572  minsepPt[mend] = closePt;
573  // set the end to a bogus value (not near an end)
574  minsepEnd[mend] = 2;
575  short dend0 = abs((short)closePt - tj.EndPt[0]);
576  short dend1 = abs((short)closePt - tj.EndPt[1]);
577  if(dend0 < dend1 && dend0 < 3) minsepEnd[mend] = 0;
578  if(dend1 < dend0 && dend1 < 3) minsepEnd[mend] = 1;
579  } // mend
580  } // tjid
581 // bool isCompatible = (minsepEnd[0] != 2 && minsepTj[0] == minsepTj[1] && minsepEnd[0] == minsepEnd[1]);
582  // don't require that the minsepTjs be the same. This would reject this topology
583  // 111111 333333 7777777
584  // if mtj.ID = 3
585  bool isCompatible = (minsepEnd[0] != 2 && minsepEnd[1] != 2);
586  // check for large separation between the closest points for short Tjs
587  if(isCompatible && mtjIsShort) {
588  float minminsep = minsep2[0];
589  if(minsep2[1] < minminsep) minminsep = minsep2[1];
590  // require that the separation be less than sqrt(5)
591  isCompatible = minminsep < 5;
592 // if(minminsep > 2) std::cout<<"CM: mtj T"<<mtj.ID<<" is short and the separation is large "<<minminsep<<". Check for signal between\n ";
593  }
594  if(prt) {
595  mf::LogVerbatim myprt("TC");
596  myprt<<"CompatibleMerge: T"<<mtj.ID<<" end";
597  for(unsigned short end = 0; end < 2; ++end) myprt<<" T"<<minsepTj[end]<<"_I"<<minsepPt[end]<<"_E"<<minsepEnd[end]<<" minsep "<<sqrt(minsep2[end]);
598  myprt<<" Compatible? "<<isCompatible;
599  } // prt
600  return isCompatible;
601 
602  } // CompatibleMerge
bool TrajClosestApproach(Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
Definition: Utils.cxx:2377
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 ( TCSlice slc,
const Trajectory tj1,
const Trajectory tj2,
bool  prt 
)

Definition at line 605 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::CTP, DeltaAngle(), tca::Trajectory::EndPt, tca::Trajectory::ID, kHaloTj, tca::TCConfig::kinkCuts, kKilled, OverlapFraction(), PointTrajDOCA(), PosSep(), tca::Trajectory::Pts, and tcc.

606  {
607  // returns true if the two Tjs are compatible with and end0-end1 merge. This function has many aspects of the
608  // compatibility checks done in EndMerge but with looser cuts.
609  if(tj1.AlgMod[kKilled] || tj2.AlgMod[kKilled]) return false;
610  if(tj1.AlgMod[kHaloTj] || tj2.AlgMod[kHaloTj]) return false;
611  if(tj1.CTP != tj2.CTP) return false;
612  unsigned short end1 = -1, end2 = 0;
613  float minLen = PosSep(tj1.Pts[tj1.EndPt[0]].Pos, tj1.Pts[tj1.EndPt[1]].Pos);
614  float len2 = PosSep(tj2.Pts[tj2.EndPt[0]].Pos, tj2.Pts[tj2.EndPt[1]].Pos);
615  if(len2 < minLen) minLen = len2;
616  minLen *= 1.2;
617  if(minLen > 10) minLen = 10;
618  for(unsigned short e1 = 0; e1 < 2; ++e1) {
619  auto& tp1 = tj1.Pts[tj1.EndPt[e1]];
620  for(unsigned short e2 = 0; e2 < 2; ++e2) {
621  auto& tp2 = tj2.Pts[tj2.EndPt[e2]];
622  float sep = PosSep(tp1.Pos, tp2.Pos);
623  if(sep < minLen) {
624  minLen = sep;
625  end1 = e1; end2 = e2;
626  }
627  } // e2
628  } // e1
629  if(end1 < 0) return false;
630  // require end to end
631  if(end2 != 1 - end1) return false;
632 
633  float overlapFraction = OverlapFraction(slc, tj1, tj2);
634  if(overlapFraction > 0.25) {
635  if(prt) mf::LogVerbatim("TC")<<"CM: "<<tj1.ID<<" "<<tj2.ID<<" overlapFraction "<<overlapFraction<<" > 0.25 ";
636  return false;
637  }
638 
639  auto& tp1 = tj1.Pts[tj1.EndPt[end1]];
640  auto& tp2 = tj2.Pts[tj2.EndPt[end2]];
641 /* This causes problems with hit collections that have cosmics removed
642  if(!SignalBetween(slc, tp1, tp2, 0.8, false)) {
643  if(prt) mf::LogVerbatim("TC")<<"CM: "<<tj1.ID<<" "<<tj2.ID<<" no signal between these points "<<PrintPos(slc, tp1.Pos)<<" "<<PrintPos(slc, tp2.Pos);
644  return false;
645  }
646 */
647  float doca1 = PointTrajDOCA(slc, tp1.Pos[0], tp1.Pos[1], tp2);
648  float doca2 = PointTrajDOCA(slc, tp2.Pos[0], tp2.Pos[1], tp1);
649  if(doca1 > 2 && doca2 > 2) {
650  if(prt) mf::LogVerbatim("TC")<<"CM: "<<tj1.ID<<" "<<tj2.ID<<" Both docas > 2 "<<doca1<<" "<<doca2;
651  return false;
652  }
653 
654  float dang = DeltaAngle(tp1.Ang, tp2.Ang);
655  if(dang > 2 * tcc.kinkCuts[0]) {
656  if(prt) mf::LogVerbatim("TC")<<"CM: "<<tj1.ID<<" "<<tj2.ID<<" dang "<<dang<<" > "<<2 * tcc.kinkCuts[0];
657  return false;
658  }
659 
660  return true;
661  } // CompatibleMerge
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< float > kinkCuts
kink angle, nPts fit, (alternate) kink angle significance
Definition: DataStructs.h:475
float PosSep(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2353
TCConfig tcc
Definition: DataStructs.cxx:6
float PointTrajDOCA(TCSlice &slc, float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2280
float OverlapFraction(TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2)
Definition: Utils.cxx:664
double DeltaAngle(double Ang1, double Ang2)
Definition: Utils.cxx:2858
void tca::CompleteIncomplete3DVertices ( TCSlice slc)

Definition at line 2759 of file TCVertex.cxx.

References AttachAnyTrajToVertex(), ChgFracNearPos(), detinfo::DetectorProperties::ConvertXToTicks(), tca::VtxStore::CTP, tca::TCConfig::dbgAlg, tca::TCConfig::dbgSlc, tca::TCConfig::detprop, EncodeCTP(), evd::details::end(), GetAssns(), tca::VtxStore::ID, tca::TCSlice::ID, kComp3DVx, kDebug, kFixed, kHaloTj, kKilled, kVtxIndPlnNoChg, MakeVertexObsolete(), tca::TCConfig::modes, tca::TCSlice::nPlanes, tca::VtxStore::NTraj, NumPtsWithCharge(), tca::VtxStore::Pass, tca::VtxStore::Pos, tca::TrajPoint::Pos, PrintPos(), SetPDGCode(), SetVx2Score(), SplitTraj(), tca::VtxStore::Stat, StoreVertex(), tcc, tca::VtxStore::TjChgFrac, tca::TCSlice::tjs, util::flags::to_string(), tca::VtxStore::Topo, TrajPointTrajDOCA(), tca::TCConfig::unitsPerTick, tca::TCConfig::useAlg, tca::TCSlice::vtx3s, tca::TCSlice::vtxs, and tca::VtxStore::Vx3ID.

Referenced by Find3DVertices().

2760  {
2761  // Look for trajectories in a plane that lack a 2D vertex as listed in
2762  // 2DVtxID that are near the projected wire. This may trigger splitting trajectories,
2763  // assigning them to a new 2D vertex and completing 3D vertices
2764 
2765  if(!tcc.useAlg[kComp3DVx]) return;
2766  if(slc.nPlanes != 3) return;
2767 
2768  bool prt = (tcc.modes[kDebug] && tcc.dbgSlc && tcc.dbgAlg[kComp3DVx]);
2769 
2770  float maxdoca = 3;
2771  if(prt) mf::LogVerbatim("TC")<<"Inside CI3DV with maxdoca set to "<<maxdoca;
2772  unsigned short ivx3 = 0;
2773  for(auto& vx3 : slc.vtx3s) {
2774  // ignore obsolete vertices
2775  if(vx3.ID == 0) continue;
2776  // check for a completed 3D vertex
2777  if(vx3.Wire < 0) continue;
2778  unsigned short mPlane = USHRT_MAX;
2779  // look for vertices in the induction plane in which the charge requirement wasn't imposed
2780  bool indPlnNoChgVtx = false;
2781  for(unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
2782  if(vx3.Vx2ID[plane] > 0) {
2783  auto& vx2 = slc.vtxs[vx3.Vx2ID[plane] - 1];
2784  if(vx2.Stat[kVtxIndPlnNoChg]) indPlnNoChgVtx = true;
2785  continue;
2786  }
2787  mPlane = plane;
2788  } // ipl
2789  if(mPlane == USHRT_MAX) continue;
2790  if(indPlnNoChgVtx) continue;
2791  CTP_t mCTP = EncodeCTP(vx3.TPCID.Cryostat, vx3.TPCID.TPC, mPlane);
2792  // X position of the purported missing vertex
2793  // A TP for the missing 2D vertex
2794  TrajPoint vtp;
2795  vtp.Pos[0] = vx3.Wire;
2796  vtp.Pos[1] = tcc.detprop->ConvertXToTicks(vx3.X, mPlane, vx3.TPCID.TPC, vx3.TPCID.Cryostat) * tcc.unitsPerTick;
2797  if(prt) mf::LogVerbatim("TC")<<"CI3DV 3V"<<vx3.ID<<" Pos "<<mPlane<<":"<<PrintPos(slc, vtp.Pos);
2798  std::vector<int> tjIDs;
2799  std::vector<unsigned short> tjPts;
2800  for(auto& tj : slc.tjs) {
2801  if(tj.CTP != mCTP) continue;
2802  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
2803  if(tj.Pts.size() < 6) continue;
2804  if(tj.AlgMod[kComp3DVx]) continue;
2805  float doca = maxdoca;
2806  // find the closest distance between the vertex and the trajectory
2807  unsigned short closePt = 0;
2808  TrajPointTrajDOCA(slc, vtp, tj, closePt, doca);
2809  if(closePt > tj.EndPt[1]) continue;
2810  // try to improve the location of the vertex by looking for a distinctive feature on the
2811  // trajectory, e.g. high multiplicity hits or larger than normal charge
2812 // if(RefineVtxPosition(slc, tj, closePt, 3, false)) vtp.Pos = tj.Pts[closePt].Pos;
2813  if(prt) mf::LogVerbatim("TC")<<"CI3DV 3V"<<vx3.ID<<" candidate itj ID "<<tj.ID<<" vtx pos "<<PrintPos(slc, vtp.Pos)<<" doca "<<doca;
2814  tjIDs.push_back(tj.ID);
2815  tjPts.push_back(closePt);
2816  } // itj
2817  if(tjIDs.empty()) continue;
2818  // compare the length of the Tjs used to make the vertex with the length of the
2819  // Tj that we want to split. Don't allow a vertex using very short Tjs to split a long
2820  // Tj in the 3rd plane
2821 // float score;
2822 // auto vxtjs = GetVtxTjIDs(slc, vx3, score);
2823  auto vxtjs = GetAssns(slc, "3V", vx3.ID, "T");
2824  unsigned short maxPts = 0;
2825  for(auto tjid : vxtjs) {
2826  auto& tj = slc.tjs[tjid - 1];
2827  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
2828  if(npwc > maxPts) maxPts = npwc;
2829  } // tjid
2830  // skip this operation if any of the Tjs in the split list are > 3 * maxPts
2831  maxPts *= 3;
2832  bool skipit = false;
2833  for(auto tjid : tjIDs) {
2834  auto& tj = slc.tjs[tjid - 1];
2835  if(NumPtsWithCharge(slc, tj, false) > maxPts) skipit = true;
2836  } // tjid
2837  if(prt) mf::LogVerbatim("TC")<<" maxPts "<<maxPts<<" skipit? "<<skipit;
2838  if(skipit) continue;
2839  // 2D vertex
2840  VtxStore aVtx;
2841  unsigned short newVtxIndx = slc.vtxs.size();
2842  aVtx.ID = newVtxIndx + 1;
2843  aVtx.CTP = mCTP;
2844  aVtx.Topo = 3;
2845  aVtx.NTraj = 0;
2846  // Give it a bogus pass to indicate it wasn't created while stepping
2847  aVtx.Pass = 9;
2848  aVtx.Pos = vtp.Pos;
2849  // ensure this isn't in a messy region
2850  aVtx.TjChgFrac = ChgFracNearPos(slc, aVtx.Pos, tjIDs);
2851  if(prt) mf::LogVerbatim("TC")<<" charge fraction near position "<<aVtx.TjChgFrac;
2852  if(aVtx.TjChgFrac < 0.6) continue;
2853  if(!StoreVertex(slc, aVtx)) continue;
2854  // make a reference to the new vertex
2855  VtxStore& newVtx = slc.vtxs[slc.vtxs.size()-1];
2856  if(prt) mf::LogVerbatim("TC")<<" Stored 2D vertex "<<newVtx.ID;
2857  // make a temporary copy so we can nudge it a bit if there is only one Tj
2858  std::array<float, 2> vpos = aVtx.Pos;
2859  for(unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2860  unsigned short itj = tjIDs[ii] - 1;
2861  // Don't use a reference variable since it may get scrambled after SplitTraj
2862 // auto& tj = slc.tjs[itj];
2863  unsigned short closePt = tjPts[ii];
2864  // determine which end is the closest
2865  unsigned short end = 1;
2866  // closest to the beginning?
2867  if(fabs(closePt - slc.tjs[itj].EndPt[0]) < fabs(closePt - slc.tjs[itj].EndPt[1])) end = 0;
2868  short dpt = fabs(closePt - slc.tjs[itj].EndPt[end]);
2869  if(dpt < 3) {
2870  // close to an end
2871  if(slc.tjs[itj].VtxID[end] > 0) {
2872  // find the distance btw the existing vertex and the end of this tj
2873  auto& oldTj = slc.tjs[itj];
2874  auto& oldVx = slc.vtxs[oldTj.VtxID[end] - 1];
2875  short oldSep = fabs(oldVx.Pos[0] - oldTj.Pts[oldTj.EndPt[end]].Pos[0]);
2876  if(prt) mf::LogVerbatim("TC")<<" T"<<slc.tjs[itj].ID<<" has vertex 2V"<<slc.tjs[itj].VtxID[end]<<" at end "<<end<<". oldSep "<<oldSep;
2877  if(dpt < oldSep) {
2878  MakeVertexObsolete("CI3DV", slc, oldVx, true);
2879  } else {
2880  continue;
2881  }
2882  } // slc.tjs[itj].VtxID[end] > 0
2883  slc.tjs[itj].VtxID[end] = slc.vtxs[newVtxIndx].ID;
2884  ++newVtx.NTraj;
2885  if(prt) mf::LogVerbatim("TC")<<" attach Traj T"<<slc.tjs[itj].ID<<" at end "<<end;
2886  slc.tjs[itj].AlgMod[kComp3DVx] = true;
2887  vpos = slc.tjs[itj].Pts[slc.tjs[itj].EndPt[end]].Pos;
2888  } else {
2889  // closePt is not near an end, so split the trajectory
2890  if(SplitTraj(slc, itj, closePt, newVtxIndx, prt)) {
2891  if(prt) mf::LogVerbatim("TC")<<" SplitTraj success 2V"<<slc.vtxs[newVtxIndx].ID<<" at closePt "<<closePt;
2892  // successfully split the Tj
2893  newVtx.NTraj += 2;
2894  } else {
2895  // split failed. Give up
2896  if(prt) mf::LogVerbatim("TC")<<" SplitTraj failed";
2897  newVtx.NTraj = 0;
2898  break;
2899  }
2900  // Update the PDGCode for the chopped trajectory
2901  SetPDGCode(slc, itj, true);
2902  // and for the new trajectory
2903  SetPDGCode(slc, slc.tjs.size()-1, true);
2904  } // closePt is not near an end, so split the trajectory
2905  slc.tjs[itj].AlgMod[kComp3DVx] = true;
2906  unsigned short newtj = slc.tjs.size() - 1;
2907  slc.tjs[newtj].AlgMod[kComp3DVx] = true;
2908  } // ii
2909  if(newVtx.NTraj == 0) {
2910  // A failure occurred. Recover
2911  if(prt) mf::LogVerbatim("TC")<<" Failed. Recover and delete vertex "<<newVtx.ID;
2912  MakeVertexObsolete("CI3DV", slc, newVtx, true);
2913  } else {
2914  // success
2915  vx3.Vx2ID[mPlane] = newVtx.ID;
2916  newVtx.Vx3ID = vx3.ID;
2917  vx3.Wire = -1;
2918  // set the vertex position to the start of the Tj if there is only one and fix it
2919  if(newVtx.NTraj == 1) {
2920  newVtx.Pos = vpos;
2921  newVtx.Stat[kFixed] = true;
2922  }
2923  AttachAnyTrajToVertex(slc, newVtx.ID - 1, prt);
2924  SetVx2Score(slc);
2925  if(prt) {
2926  mf::LogVerbatim myprt("TC");
2927  myprt<<" Success: new 2V"<<newVtx.ID<<" at "<<(int)newVtx.Pos[0]<<":"<<(int)newVtx.Pos[1]/tcc.unitsPerTick;
2928  myprt<<" points to 3V"<<vx3.ID;
2929  myprt<<" TjIDs:";
2930  for(auto& tjID : tjIDs) myprt<<" T"<<std::to_string(tjID);
2931  } // prt
2932  } // success
2933  ++ivx3;
2934  } // vx3
2935 
2936  } // CompleteIncomplete3DVertices
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeVertexObsolete(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:3208
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4279
void TrajPointTrajDOCA(TCSlice &slc, TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
Definition: Utils.cxx:2155
TCConfig tcc
Definition: DataStructs.cxx:6
vertex position fixed manually - no fitting done
Definition: DataStructs.h:74
bool AttachAnyTrajToVertex(TCSlice &slc, unsigned short ivx, bool prt)
Definition: TCVertex.cxx:1868
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:507
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:2093
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
const detinfo::DetectorProperties * detprop
Definition: DataStructs.h:494
void SetPDGCode(TCSlice &slc, unsigned short itj, bool tjDone)
Definition: Utils.cxx:3795
vertex quality is suspect - No requirement made on chg btw it and the Tj
Definition: DataStructs.h:79
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
float ChgFracNearPos(TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2698
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2513
unsigned int CTP_t
Definition: DataStructs.h:41
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Definition: BitMask.h:187
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:505
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
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 SplitTraj(TCSlice &slc, unsigned short itj, float XPos, bool makeVx2, bool prt)
Definition: Utils.cxx:2004
master switch for turning on debug mode
Definition: DataStructs.h:449
void tca::CompleteIncomplete3DVerticesInGaps ( TCSlice slc)

Definition at line 2669 of file TCVertex.cxx.

References ChgFracNearPos(), detinfo::DetectorProperties::ConvertXToTicks(), geo::CryostatID::Cryostat, tca::VtxStore::CTP, tca::TrajPoint::CTP, tca::TCConfig::dbgAlg, tca::TCConfig::dbgSlc, DeadWireCount(), tca::TCConfig::detprop, EncodeCTP(), evd::details::end(), tca::VtxStore::ID, tca::Vtx3Store::ID, kComp3DVxIG, kDebug, kHaloTj, kKilled, tca::TCConfig::modes, tca::TCSlice::nPlanes, tca::VtxStore::NTraj, tca::VtxStore::Pass, PointTrajDOCA(), tca::VtxStore::Pos, tca::TrajPoint::Pos, SetVx2Score(), StoreVertex(), tcc, tca::VtxStore::TjChgFrac, tca::TCSlice::tjs, tca::VtxStore::Topo, geo::TPCID::TPC, tca::Vtx3Store::TPCID, tca::TCConfig::unitsPerTick, tca::TCConfig::useAlg, tca::TCSlice::vtx3s, tca::TCSlice::vtxs, tca::Vtx3Store::Vx2ID, tca::VtxStore::Vx3ID, tca::Vtx3Store::Wire, and tca::Vtx3Store::X.

Referenced by Find3DVertices().

2670  {
2671 
2672  if(!tcc.useAlg[kComp3DVxIG]) return;
2673  if(slc.nPlanes != 3) return;
2674 
2675  bool prt = (tcc.modes[kDebug] && tcc.dbgSlc && tcc.dbgAlg[kComp3DVxIG]);
2676  if(prt) mf::LogVerbatim("TC")<<"Inside CI3DVIG:";
2677 
2678  for(unsigned short iv3 = 0; iv3 < slc.vtx3s.size(); ++iv3) {
2679  Vtx3Store& vx3 = slc.vtx3s[iv3];
2680  // ignore obsolete vertices
2681  if(vx3.ID == 0) continue;
2682  // check for a completed 3D vertex
2683  if(vx3.Wire < 0) continue;
2684  unsigned short mPlane = USHRT_MAX;
2685  for(unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
2686  if(vx3.Vx2ID[ipl] > 0) continue;
2687  mPlane = ipl;
2688  break;
2689  } // ipl
2690  if(mPlane == USHRT_MAX) continue;
2691 // CTP_t mCTP = EncodeCTP(vx3.CStat, vx3.TPC, mPlane);
2692  CTP_t mCTP = EncodeCTP(vx3.TPCID.Cryostat, vx3.TPCID.TPC, mPlane);
2693  // require that the missing vertex be in a large block of dead wires
2694  float dwc = DeadWireCount(slc, vx3.Wire - 4, vx3.Wire + 4, mCTP);
2695  if(dwc < 5) continue;
2696  // X position of the purported missing vertex
2697  // A TP for the missing 2D vertex
2698  VtxStore aVtx;
2699  aVtx.ID = slc.vtxs.size() + 1;
2700  aVtx.Pos[0] = vx3.Wire;
2701  aVtx.Pos[1] = tcc.detprop->ConvertXToTicks(vx3.X, mPlane, vx3.TPCID.TPC, vx3.TPCID.Cryostat) * tcc.unitsPerTick;
2702  aVtx.CTP = mCTP;
2703  aVtx.Topo = 4;
2704  aVtx.NTraj = 0;
2705  // Give it a bogus pass to indicate it wasn't created while stepping
2706  aVtx.Pass = 9;
2707  if(prt) mf::LogVerbatim("TC")<<"CI3DVIG: Incomplete vertex "<<iv3<<" in plane "<<mPlane<<" wire "<<vx3.Wire<<" Made 2D vertex ";
2708  std::vector<int> tjIDs;
2709  std::vector<unsigned short> tjEnds;
2710  for(unsigned short itj = 0; itj < slc.tjs.size(); ++itj) {
2711  if(slc.tjs[itj].CTP != mCTP) continue;
2712  if(slc.tjs[itj].AlgMod[kKilled] || slc.tjs[itj].AlgMod[kHaloTj]) continue;
2713  for(unsigned short end = 0; end < 2; ++end) {
2714  unsigned short ept = slc.tjs[itj].EndPt[end];
2715  TrajPoint& tp = slc.tjs[itj].Pts[ept];
2716  unsigned short oept = slc.tjs[itj].EndPt[1 - end];
2717  TrajPoint& otp = slc.tjs[itj].Pts[oept];
2718  // ensure that this is the end closest to the vertex
2719  if(std::abs(tp.Pos[0] - aVtx.Pos[0]) > std::abs(otp.Pos[0] - aVtx.Pos[0])) continue;
2720  float doca = PointTrajDOCA(slc, aVtx.Pos[0], aVtx.Pos[1], tp);
2721  if(doca > 2) continue;
2722  float dwc = DeadWireCount(slc, aVtx.Pos[0], tp.Pos[0], tp.CTP);
2723  float ptSep;
2724  if(aVtx.Pos[0] > tp.Pos[0]) {
2725  ptSep = aVtx.Pos[0] - tp.Pos[0] - dwc;
2726  } else {
2727  ptSep = tp.Pos[0] - aVtx.Pos[0] - dwc;
2728  }
2729  if(prt) mf::LogVerbatim("TC")<<"CI3DVIG: tj ID "<<slc.tjs[itj].ID<<" doca "<<doca<<" ptSep "<<ptSep;
2730  if(ptSep < -2 || ptSep > 2) continue;
2731  // don't clobber an existing association
2732  if(slc.tjs[itj].VtxID[end] > 0) continue;
2733  tjIDs.push_back(slc.tjs[itj].ID);
2734  tjEnds.push_back(end);
2735  } // end
2736  } // itj
2737  if(!tjIDs.empty()) {
2738  // Determine how messy this region is
2739  aVtx.TjChgFrac = ChgFracNearPos(slc, aVtx.Pos, tjIDs);
2740  if(aVtx.TjChgFrac < 0.7) continue;
2741  aVtx.Vx3ID = vx3.ID;
2742  // Save the 2D vertex
2743  if(!StoreVertex(slc, aVtx)) continue;
2744  for(unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2745  unsigned short itj = tjIDs[ii] - 1;
2746  slc.tjs[itj].VtxID[tjEnds[ii]] = aVtx.ID;
2747  slc.tjs[itj].AlgMod[kComp3DVxIG] = true;
2748  } // ii
2749  SetVx2Score(slc);
2750  vx3.Vx2ID[mPlane] = aVtx.ID;
2751  vx3.Wire = -1;
2752  if(prt) mf::LogVerbatim("TC")<<"CI3DVIG: new vtx 2V"<<aVtx.ID<<" points to 3V"<<vx3.ID;
2753  }
2754  } // vx3
2755 
2756  } // CompleteIncomplete3DVerticesInGaps
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:507
float DeadWireCount(TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:1881
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:2093
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
const detinfo::DetectorProperties * detprop
Definition: DataStructs.h:494
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
float ChgFracNearPos(TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2698
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2513
unsigned int CTP_t
Definition: DataStructs.h:41
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:505
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
master switch for turning on debug mode
Definition: DataStructs.h:449
bool tca::CompleteIncompleteShower ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 739 of file TCShower.cxx.

References ChkAssns(), tca::ShowerStruct3D::CotIDs, tca::TCSlice::cots, CreateSS(), DecodeCTP(), evd::details::end(), GetAssns(), tca::ShowerStruct3D::ID, tca::TCSlice::ID, kCompleteShower, MakeShowerObsolete(), tca::ShowerStruct3D::NeedsUpdate, tca::TCSlice::nPlanes, tca::TCSlice::pfps, geo::PlaneID::Plane, SetIntersection(), ShowerEnergy(), ss, StoreShower(), tcc, tca::TCSlice::tjs, UpdateShower(), tca::TCConfig::useAlg, and tca::TCSlice::vtxs.

Referenced by Match2DShowers().

740  {
741  // Find low-energy two-plane showers and try to complete it by making a 2D shower in the third
742  // plane using 3D matched tjs
743 
744  if(slc.nPlanes != 3) return false;
745  if(ss3.CotIDs.size() != 2) return false;
746 
747  if(!tcc.useAlg[kCompleteShower]) return false;
748 
749  std::string fcnLabel = inFcnLabel + ".CIS";
750  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID;
751 
752  auto& iss = slc.cots[ss3.CotIDs[0] - 1];
753  auto& jss = slc.cots[ss3.CotIDs[1] - 1];
754  // make a list of pfps for each SS
755  std::vector<int> iplist;
756  for(auto tid : iss.TjIDs) {
757  auto plist = GetAssns(slc, "T", tid, "P");
758  if(!plist.empty()) iplist.insert(iplist.end(), plist.begin(), plist.end());
759  } // tid
760  std::vector<int> jplist;
761  for(auto tid : jss.TjIDs) {
762  auto plist = GetAssns(slc, "T", tid, "P");
763  if(!plist.empty()) jplist.insert(jplist.end(), plist.begin(), plist.end());
764  } // tid
765  // look for pfps that have tjs in both showers
766  auto shared = SetIntersection(iplist, jplist);
767  if(shared.empty()) return false;
768  // put the list of tjs for both SS into a flat vector to simplify searching
769  std::vector<int> flat = iss.TjIDs;
770  flat.insert(flat.end(), jss.TjIDs.begin(), jss.TjIDs.end());
771  // make a list of tjs in the k plane that maybe should made into a shower if they
772  // aren't already in a shower that failed the 3D match
773  std::vector<int> ktlist;
774  for(auto pid : shared) {
775  auto& pfp = slc.pfps[pid - 1];
776  for(auto tid : pfp.TjIDs) {
777  // ignore the tjs that are already in the shower in the other planes
778  if(std::find(flat.begin(), flat.end(), tid) != flat.end()) continue;
779  if(std::find(ktlist.begin(), ktlist.end(), tid) == ktlist.end()) ktlist.push_back(tid);
780  // look for 2D vertices attached to this tj and add all attached tjs to ktlist
781  auto& tj = slc.tjs[tid - 1];
782  for(unsigned short end = 0; end < 2; ++end) {
783  if(tj.VtxID[end] <= 0) continue;
784  auto& vx2 = slc.vtxs[tj.VtxID[end] - 1];
785  auto TIn2V = GetAssns(slc, "2V", vx2.ID, "T");
786  for(auto vtid : TIn2V) {
787  if(std::find(ktlist.begin(), ktlist.end(), vtid) == ktlist.end()) ktlist.push_back(vtid);
788  }
789  } // end
790  } // tid
791  } // pid
792  if(ktlist.empty()) return false;
793  // list of 2D showers that include tjs in ktlist
794  std::vector<int> ksslist;
795  for(auto tid : ktlist) {
796  auto& tj = slc.tjs[tid - 1];
797  if(tj.SSID == 0) continue;
798  // ignore showers that are 3D-matched. This case should be handled elsewhere by a merging function
799  auto& ss = slc.cots[tj.SSID - 1];
800  if(ss.SS3ID > 0) {
801  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Found existing T"<<tid<<" -> 2S"<<ss.ID<<" -> 3S"<<ss.SS3ID<<" assn. Give up";
802  return false;
803  }
804  if(std::find(ksslist.begin(), ksslist.end(), ss.ID) == ksslist.end()) ksslist.push_back(ss.ID);
805  } // tid
806  // find the shower energy for this list
807  float ktlistEnergy = ShowerEnergy(slc, ktlist);
808  if(prt) {
809  mf::LogVerbatim myprt("TC");
810  myprt<<fcnLabel<<" 3S"<<ss3.ID<<"\n";
811  myprt<<" -> i2S"<<iss.ID<<" ->";
812  for(auto pid : iplist) myprt<<" P"<<pid;
813  myprt<<"\n";
814  myprt<<" -> j2S"<<jss.ID<<" ->";
815  for(auto pid : jplist) myprt<<" P"<<pid;
816  myprt<<"\n";
817  geo::PlaneID iPlaneID = DecodeCTP(iss.CTP);
818  geo::PlaneID jPlaneID = DecodeCTP(jss.CTP);
819  unsigned short kplane = 3 - iPlaneID.Plane - jPlaneID.Plane;
820  myprt<<" kplane "<<kplane<<" ktlist:";
821  for(auto tid : ktlist) myprt<<" T"<<tid;
822  myprt<<" ktlistEnergy "<<ktlistEnergy;
823  if(ksslist.empty()) {
824  myprt<<"\n No matching showers in kplane";
825  } else {
826  myprt<<"\n";
827  myprt<<" Candidate showers:";
828  for(auto ssid : ksslist) {
829  myprt<<" 2S"<<ssid;
830  auto& sst = slc.cots[ssid - 1];
831  if(sst.SS3ID > 0) myprt<<"_3S"<<sst.SS3ID;
832  } // ssid
833  } // ssList not empty
834  } // prt
835  if(ksslist.size() > 1) {
836  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Found more than 1 shower. Need some better code here";
837  return false;
838  }
839  if(ktlistEnergy > 2 * ShowerEnergy(ss3)) {
840  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" ktlistEnergy exceeds 2 * ss3 energy. Need some better code here";
841  return false;
842  } // ktlistEnergy too high
843 
844  if(ksslist.empty()) {
845  // no 2D shower so make one using ktlist
846  auto kss = CreateSS(slc, ktlist);
847  if(kss.ID == 0) return false;
848  kss.SS3ID = ss3.ID;
849  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" create new 2S"<<kss.ID<<" from ktlist";
850  if(!UpdateShower(fcnLabel, slc, kss, prt)) {
851  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" UpdateShower failed 2S"<<kss.ID;
852  MakeShowerObsolete(fcnLabel, slc, kss, prt);
853  return false;
854  } // UpdateShower failed
855  if(!StoreShower(fcnLabel, slc, kss)) {
856  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" StoreShower failed";
857  MakeShowerObsolete(fcnLabel, slc, kss, prt);
858  return false;
859  } // StoreShower failed
860  ss3.CotIDs.push_back(kss.ID);
861  auto& stj = slc.tjs[kss.ShowerTjID - 1];
862  stj.AlgMod[kCompleteShower] = true;
863  ss3.NeedsUpdate = true;
864  return true;
865  } // ksslist empty
866 
867  // associate ksslist[0] with 3S
868  auto& ss = slc.cots[ksslist[0] - 1];
869  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" found pfp-matched 2S"<<ss.ID;
870  ss.SS3ID = ss3.ID;
871  ss3.CotIDs.push_back(ss.ID);
872  auto& stj = slc.tjs[ss.ShowerTjID - 1];
873  stj.AlgMod[kCompleteShower] = true;
874  ss3.NeedsUpdate = true;
875 
876  ChkAssns(fcnLabel, slc);
877  return true;
878 
879  } // CompleteIncompleteShower
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4279
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4560
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
Float_t ss
Definition: plot.C:23
ShowerStruct CreateSS(TCSlice &slc, const std::vector< int > &tjl)
Definition: TCShower.cxx:4514
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:231
void MakeShowerObsolete(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3266
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1230
float ShowerEnergy(TCSlice &slc, const std::vector< int > tjIDs)
Definition: TCShower.cxx:4382
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
bool StoreShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss)
Definition: TCShower.cxx:4449
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void tca::ConfigureMVA ( TCConfig tcc,
std::string  fMVAShowerParentWeights 
)

Definition at line 15 of file TCShower.cxx.

References tca::TCConfig::showerParentReader, and tca::TCConfig::showerParentVars.

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

16  {
17  // Define the reference to the MVA reader used to determine the best
18  // shower parent PFParticle
19  cet::search_path sp("FW_SEARCH_PATH");
20  if(!tcc.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";
29  return;
30  }
31  tcc.showerParentVars.resize(9);
32  tcc.showerParentReader->AddVariable("fShEnergy", &tcc.showerParentVars[0]);
33  tcc.showerParentReader->AddVariable("fPfpEnergy", &tcc.showerParentVars[1]);
34  tcc.showerParentReader->AddVariable("fMCSMom", &tcc.showerParentVars[2]);
35  tcc.showerParentReader->AddVariable("fPfpLen", &tcc.showerParentVars[3]);
36  tcc.showerParentReader->AddVariable("fSep", &tcc.showerParentVars[4]);
37  tcc.showerParentReader->AddVariable("fDang1", &tcc.showerParentVars[5]);
38  tcc.showerParentReader->AddVariable("fDang2", &tcc.showerParentVars[6]);
39  tcc.showerParentReader->AddVariable("fChgFrac", &tcc.showerParentVars[7]);
40  tcc.showerParentReader->AddVariable("fInShwrProb", &tcc.showerParentVars[8]);
41  tcc.showerParentReader->BookMVA("BDT", fullFileSpec);
42  } // ConfigureTMVA
TCConfig tcc
Definition: DataStructs.cxx:6
TMVA::Reader * showerParentReader
Definition: DataStructs.h:496
std::vector< float > showerParentVars
Definition: DataStructs.h:497
PFPStruct tca::CreateFakePFP ( TCSlice slc,
const ShowerStruct3D ss3 
)

Definition at line 1981 of file TCShower.cxx.

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

1982  {
1983  // Creates a fake PFParticle on the shower axis with a TP3S point every cm. This is
1984  // used to find the separation between the shower core and a PFParticle or trajectory
1985  auto pfp = CreatePFP(slc);
1986  pfp.XYZ[0] = ss3.Start;
1987  pfp.Dir[0] = ss3.Dir;
1988  pfp.XYZ[1] = ss3.End;
1989  pfp.Dir[1] = ss3.Dir;
1990  pfp.Dir[0] = PointDirection(ss3.Start, ss3.End);
1991  unsigned short npts = ss3.Len;
1992  if(npts < 2) return pfp;
1993  pfp.Tp3s.resize(npts);
1994  pfp.Tp3s[0].Pos = ss3.Start;
1995  for(unsigned short ipt = 1; ipt < npts; ++ipt) {
1996  for(unsigned short xyz = 0; xyz < 3; ++xyz) pfp.Tp3s[ipt].Pos[xyz] = pfp.Tp3s[ipt-1].Pos[xyz] + pfp.Dir[0][xyz];
1997  } // ipt
1998  return pfp;
1999  } // CreateFakePFP
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:1643
PFPStruct CreatePFP(TCSlice &slc)
Definition: PFPUtils.cxx:1973
PFPStruct tca::CreatePFP ( TCSlice slc)

Definition at line 1973 of file PFPUtils.cxx.

References tca::PFPStruct::dEdx, tca::PFPStruct::dEdxErr, tca::PFPStruct::Dir, tca::PFPStruct::DirErr, evd::details::end(), tca::PFPStruct::ID, tca::TCSlice::nPlanes, tca::PFPStruct::ParentUID, tca::TCSlice::pfps, tca::PFPStruct::TPCID, tca::TCSlice::TPCID, and tca::PFPStruct::XYZ.

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

1974  {
1975  // The calling function should define the size of pfp.TjIDs
1976  PFPStruct pfp;
1977  pfp.ID = slc.pfps.size() + 1;
1978  pfp.ParentUID = 0;
1979  pfp.TPCID = slc.TPCID;
1980  // initialize arrays for both ends
1981  if(slc.nPlanes < 4) {
1982  pfp.dEdx[0].resize(slc.nPlanes, 0);
1983  pfp.dEdx[1].resize(slc.nPlanes, 0);
1984  pfp.dEdxErr[0].resize(slc.nPlanes, 0);
1985  pfp.dEdxErr[1].resize(slc.nPlanes, 0);
1986  }
1987  for(unsigned short end = 0; end < 2; ++end) {
1988  // BUG the double brace syntax is required to work around clang bug 21629
1989  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1990  pfp.Dir[end] = {{0.0, 0.0, 0.0}};
1991  pfp.DirErr[end] = {{0.0, 0.0, 0.0}};
1992  pfp.XYZ[end] = {{0.0, 0.0, 0.0}};
1993  }
1994  return pfp;
1995  } // CreatePFP
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
ShowerStruct tca::CreateSS ( TCSlice slc,
const std::vector< int > &  tjl 
)

Definition at line 4514 of file TCShower.cxx.

References tca::Trajectory::AlgMod, tca::TCSlice::cots, tca::Trajectory::CTP, tca::ShowerStruct::CTP, tca::Trajectory::EndPt, tca::ShowerStruct::Envelope, tca::Trajectory::ID, tca::ShowerStruct::ID, kShowerTj, tca::Trajectory::PDGCode, tca::Trajectory::Pts, tca::ShowerStruct::ShowerTjID, ss, tca::ShowerStruct::TjIDs, and tca::TCSlice::tjs.

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

4515  {
4516  // Create a shower and shower Tj using Tjs in the list. If tjl is empty a
4517  // MC cheat shower is created inCTP. Note that inCTP is only used if tjl is empty.
4518  // A companion shower tj is created and stored but the ShowerStruct is not.
4519  ShowerStruct ss;
4520 
4521  // Create the shower tj
4522  Trajectory stj;
4523  stj.CTP = slc.tjs[tjl[0]-1].CTP;
4524 
4525  // with three points
4526  stj.Pts.resize(3);
4527  for(auto& stp : stj.Pts) {
4528  stp.CTP = stj.CTP;
4529  // set all UseHit bits true so we don't get confused
4530  stp.UseHit.set();
4531  }
4532  stj.EndPt[0] = 0;
4533  stj.EndPt[1] = 2;
4534  stj.ID = slc.tjs.size() + 1;
4535  // Declare that stj is a shower Tj
4536  stj.AlgMod[kShowerTj] = true;
4537  stj.PDGCode = 1111;
4538  slc.tjs.push_back(stj);
4539  // define the ss
4540  ss.ID = slc.cots.size() + 1;
4541  ss.CTP = stj.CTP;
4542  // assign all TJ IDs to this ShowerStruct
4543  ss.TjIDs = tjl;
4544  // declare them to be InShower
4545  for(auto tjid : tjl) {
4546  auto& tj = slc.tjs[tjid - 1];
4547  if(tj.CTP != stj.CTP) {
4548  ss.ID = 0;
4549  return ss;
4550  }
4551  tj.SSID = ss.ID;
4552  } // tjid
4553  ss.ShowerTjID = stj.ID;
4554  ss.Envelope.resize(4);
4555  return ss;
4556 
4557  } // CreateSS
Float_t ss
Definition: plot.C:23
ShowerStruct3D tca::CreateSS3 ( TCSlice slc)

Definition at line 4495 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::TCSlice::nPlanes, tca::TCSlice::showers, tca::ShowerStruct3D::TPCID, and tca::TCSlice::TPCID.

Referenced by Match2DShowers().

4496  {
4497  // create a 3D shower and size the vectors that are indexed by plane
4498 
4499  ShowerStruct3D ss3;
4500  ss3.TPCID = slc.TPCID;
4501  ss3.ID = slc.showers.size() + 1;
4502  ss3.Energy.resize(slc.nPlanes);
4503  ss3.EnergyErr.resize(slc.nPlanes);
4504  ss3.MIPEnergy.resize(slc.nPlanes);
4505  ss3.MIPEnergyErr.resize(slc.nPlanes);
4506  ss3.dEdx.resize(slc.nPlanes);
4507  ss3.dEdxErr.resize(slc.nPlanes);
4508 
4509  return ss3;
4510 
4511  } // CreateSS3
float tca::DeadWireCount ( TCSlice slc,
const TrajPoint tp1,
const TrajPoint tp2 
)

Definition at line 1881 of file Utils.cxx.

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

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

1882  {
1883  return DeadWireCount(slc, tp1.Pos[0], tp2.Pos[0], tp1.CTP);
1884  } // DeadWireCount
float DeadWireCount(TCSlice &slc, const float &inWirePos1, const float &inWirePos2, CTP_t tCTP)
Definition: Utils.cxx:1887
float tca::DeadWireCount ( TCSlice slc,
const float &  inWirePos1,
const float &  inWirePos2,
CTP_t  tCTP 
)

Definition at line 1887 of file Utils.cxx.

References DecodeCTP(), tca::TCSlice::nWires, geo::PlaneID::Plane, tmp, and tca::TCSlice::wireHitRange.

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

1888  {
1889  if(inWirePos1 < -0.4 || inWirePos2 < -0.4) return 0;
1890  unsigned int inWire1 = std::nearbyint(inWirePos1);
1891  unsigned int inWire2 = std::nearbyint(inWirePos2);
1892  geo::PlaneID planeID = DecodeCTP(tCTP);
1893  unsigned short plane = planeID.Plane;
1894  if(inWire1 > slc.nWires[plane] || inWire2 > slc.nWires[plane]) return 0;
1895  if(inWire1 > inWire2) {
1896  // put in increasing order
1897  unsigned int tmp = inWire1;
1898  inWire1 = inWire2;
1899  inWire2 = tmp;
1900  } // inWire1 > inWire2
1901  ++inWire2;
1902  unsigned int wire, ndead = 0;
1903  for(wire = inWire1; wire < inWire2; ++wire) if(slc.wireHitRange[plane][wire].first == -1) ++ndead;
1904  return ndead;
1905  } // 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)
geo::PlaneID tca::DecodeCTP ( CTP_t  CTP)

Definition at line 108 of file DataStructs.cxx.

References Cpad, and Tpad.

Referenced by AddHits(), AddLAHits(), AddLooseHits(), AttachPFPToVertex(), ChgFracNearPos(), ChkStopEndPts(), ChkVtxAssociations(), CompleteIncompleteShower(), DeadWireCount(), DefineDontCluster(), DefinePFP(), EncodeCTP(), ExpectedHitsRMS(), FilldEdx(), FillmAllTraj(), Find2DVertices(), Find3DVertices(), FindCloseHits(), FindCloseTjs(), FindCompleteness(), tca::TrajClusterAlg::FindJunkTraj(), FindMissedTjsInTp3s(), FindVtxTjs(), FindXMatches(), Finish3DShowers(), FitTp3(), FitTp3s(), cluster::ClusterCrawlerAlg::FitVtx(), FixTrajBegin(), FollowTp3s(), Forecast(), cluster::ClusterCrawlerAlg::GetHitRange(), MakeBareTP(), MakeJunkVertices(), MakeTp3(), MakeVertexObsolete(), Match2DShowers(), Match3DFOM(), tca::TruthMatcher::MatchAndSum(), MaxChargeAsymmetry(), MergePFPTjs(), Print2V(), PrintAllTraj(), cluster::TrajCluster::produce(), tca::TrajClusterAlg::ReconstructAllTraj(), ReversePropagate(), SaveTjInfo(), SaveTjInfoStuff(), SetVx2Score(), SignalAtTp(), Split3DKink(), SplitTraj(), SplitTrajCrossingVertices(), StepAway(), TrimEndPts(), UpdateMatchStructs(), UpdateShower(), UpdateTp3s(), VtxHitsSwap(), cluster::ClusterCrawlerAlg::VtxMatch(), and WireHitRangeOK().

108  {
109  auto const cryo = (CTP / Cpad);
110  return geo::PlaneID(
111  /* Cryostat */ cryo,
112  /* TPC */ (CTP - cryo * Cpad) / Tpad,
113  /* Plane */ (CTP % 10)
114  );
115  }
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
bool tca::DecodeDebugString ( std::string  strng)

Definition at line 4611 of file Utils.cxx.

References tca::DebugStuff::Cryostat, tca::DebugStuff::CTP, tca::TCConfig::dbg2S, tca::TCConfig::dbg2V, tca::TCConfig::dbg3S, tca::TCConfig::dbg3V, tca::TCConfig::dbgDeltaRayTag, tca::TCConfig::dbgDump, tca::TCConfig::dbgMrg, tca::TCConfig::dbgMuonTag, tca::TCConfig::dbgPFP, tca::TCConfig::dbgStitch, tca::TCConfig::dbgStp, tca::TCConfig::dbgSummary, tca::TCConfig::dbgVxJunk, tca::TCConfig::dbgVxMerge, debug, kDebug, tca::TCConfig::modes, tca::DebugStuff::Plane, tca::TCConfig::recoSlice, tca::DebugStuff::Slice, tcc, tca::DebugStuff::Tick, tca::DebugStuff::TPC, tca::DebugStuff::Wire, and tca::DebugStuff::WorkID.

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

4612  {
4613  // try to unpack the string as Cryostat:TPC:Plane:Wire:Tick or something
4614  // like Slice:<slice index>
4615 
4616  if(strng == "instruct") {
4617  std::cout<<"****** Unrecognized DebugConfig. Here are your options\n";
4618  std::cout<<" 'C:T:P:W:Tick' where C = cryostat, T = TPC, W = wire, Tick (+/-5) to debug stepping (DUNE)\n";
4619  std::cout<<" 'P:W:Tick' for single cryostat/TPC detectors (uB, LArIAT, etc)\n";
4620  std::cout<<" 'WorkID <id> <slice index>' where <id> is a tj work ID (< 0) in slice <slice index> (default = 0)\n";
4621  std::cout<<" 'Merge <CTP>' to debug trajectory merging\n";
4622  std::cout<<" '2V <plane>' to debug 2D vertex finding in plane <plane>\n";
4623  std::cout<<" '3V' to debug 3D vertex finding\n";
4624  std::cout<<" 'VxMerge' to debug 2D vertex merging\n";
4625  std::cout<<" 'JunkVx' to debug 2D junk vertex finder\n";
4626  std::cout<<" 'PFP' to debug 3D matching and PFParticles\n";
4627  std::cout<<" 'DeltaRay' to debug delta ray tagging\n";
4628  std::cout<<" 'Muon' to debug muon tagging\n";
4629  std::cout<<" '2S <plane>' to debug a 2D shower in plane <plane>\n";
4630  std::cout<<" 'Reco <ID>' to reconstruct all sub-slices in the recob::Slice with the specified ID\n";
4631  std::cout<<" 'SubSlice <sub-slice index>' where <slice index> restricts output to the specified sub-slice index\n";
4632  std::cout<<" 'Stitch' to debug PFParticle stitching between TPCs\n";
4633  std::cout<<" 'Sum' or 'Summary' to print a debug summary report\n";
4634  std::cout<<" 'Dump <WorkID>' or 'Dump <UID>' to print all TPs in the trajectory to tcdump<UID>.csv\n";
4635  std::cout<<" Note: Algs with debug printing include HamVx, HamVx2, SplitTjCVx, Comp3DVx, Comp3DVxIG, VtxHitsSwap\n";
4636  std::cout<<" Set SkipAlgs: [\"bogusText\"] to print a list of algorithm names\n";
4637  return false;
4638  } // instruct
4639 
4640  // handle the simple cases that don't need decoding
4641  if(strng.find("3V") != std::string::npos) { tcc.dbg3V = true; tcc.modes[kDebug] = true; return true; }
4642  if(strng.find("3S") != std::string::npos) { tcc.dbg3S = true; tcc.modes[kDebug] = true; return true; }
4643  if(strng.find("VxMerge") != std::string::npos) { tcc.dbgVxMerge = true; tcc.modes[kDebug] = true; return true; }
4644  if(strng.find("JunkVx") != std::string::npos) { tcc.dbgVxJunk = true; tcc.modes[kDebug] = true; return true; }
4645  if(strng.find("PFP") != std::string::npos) { tcc.dbgPFP = true; tcc.modes[kDebug] = true; return true; }
4646  if(strng.find("DeltaRay") != std::string::npos) { tcc.dbgDeltaRayTag = true; tcc.modes[kDebug] = true; return true; }
4647  if(strng.find("Muon") != std::string::npos) { tcc.dbgMuonTag = true; tcc.modes[kDebug] = true; return true; }
4648  if(strng.find("Stitch") != std::string::npos) { tcc.dbgStitch = true; tcc.modes[kDebug] = true; return true; }
4649  if(strng.find("Sum") != std::string::npos) { tcc.dbgSummary = true; tcc.modes[kDebug] = true; return true; }
4650 
4651  std::vector<std::string> words;
4652  boost::split(words, strng, boost::is_any_of(" :"), boost::token_compress_on);
4653  if(words.size() == 5) {
4654  // configure for DUNE
4655  debug.Cryostat = std::stoi(words[0]);
4656  debug.TPC = std::stoi(words[1]);
4657  debug.Plane = std::stoi(words[2]);
4658  debug.Wire = std::stoi(words[3]);
4659  debug.Tick = std::stoi(words[4]);
4660  tcc.modes[kDebug] = true;
4661  tcc.dbgStp = true;
4662  // also dump this tj
4663  tcc.dbgDump = true;
4664  return true;
4665  } // nums.size() == 5
4666  if(words.size() == 2 && words[0] == "Dump") {
4667  debug.WorkID = std::stoi(words[1]);
4668  debug.Slice = 0;
4669  tcc.modes[kDebug] = true;
4670  tcc.dbgDump = true;
4671  return true;
4672  }
4673  if(words.size() > 1 && words[0] == "WorkID") {
4674  debug.WorkID = std::stoi(words[1]);
4675  if(debug.WorkID >= 0) return false;
4676  // default to sub-slice index 0
4677  debug.Slice = 0;
4678  if(words.size() > 2) debug.Slice = std::stoi(words[2]);
4679  tcc.modes[kDebug] = true;
4680  // dbgStp is set true after debug.WorkID is found
4681  tcc.dbgStp = false;
4682  return true;
4683  } // words.size() == 3 && words[0] == "WorkID"
4684  if(words.size() == 3) {
4685  // configure for uB, LArIAT, etc
4686  debug.Cryostat = 0;
4687  debug.TPC = 0;
4688  debug.Plane = std::stoi(words[0]);
4689  debug.Wire = std::stoi(words[1]);
4690  debug.Tick = std::stoi(words[2]);
4691  tcc.modes[kDebug] = true;
4692  tcc.dbgStp = true;
4693  return true;
4694  }
4695  if(words.size() == 2 && words[0] == "Merge") {
4696  debug.CTP = std::stoi(words[1]);
4697  tcc.dbgMrg = true;
4698  tcc.modes[kDebug] = true;
4699  return true;
4700  }
4701  if(words.size() == 2 && words[0] == "2V") {
4702  debug.Plane = std::stoi(words[1]);
4703  tcc.dbg2V = true;
4704  tcc.modes[kDebug] = true;
4705  return true;
4706  }
4707  if(words.size() == 2 && words[0] == "2S") {
4708  debug.Plane = std::stoi(words[1]);
4709  tcc.dbg2S = true;
4710  tcc.modes[kDebug] = true;
4711  return true;
4712  }
4713  // Slice could apply to several debug options.
4714  if(words.size() == 2 && words[0] == "SubSlice") {
4715  debug.Slice = std::stoi(words[1]);
4716  return true;
4717  }
4718  if(words.size() == 2 && words[0] == "Reco") {
4719  tcc.recoSlice = std::stoi(words[1]);
4720  std::cout<<"Reconstructing Slice "<<tcc.recoSlice<<"\n";
4721  return true;
4722  }
4723  return false;
4724  } // DecodeDebugString
bool dbgStitch
debug PFParticle stitching
Definition: DataStructs.h:520
TCConfig tcc
Definition: DataStructs.cxx:6
bool dbgDeltaRayTag
Definition: DataStructs.h:516
bool dbg3V
debug 3D vertex finding
Definition: DataStructs.h:514
int Cryostat
Select Cryostat.
Definition: DebugStruct.h:19
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
int Wire
Select hit Wire for debugging.
Definition: DebugStruct.h:23
int WorkID
Select the StartWorkID for debugging.
Definition: DebugStruct.h:26
DebugStuff debug
Definition: DebugStruct.cxx:4
bool dbg2V
debug 2D vertex finding
Definition: DataStructs.h:510
int Plane
Select plane.
Definition: DebugStruct.h:21
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
int Tick
Select hit PeakTime for debugging (< 0 for vertex finding)
Definition: DebugStruct.h:24
int TPC
Select TPC.
Definition: DebugStruct.h:20
short recoSlice
only reconstruct the slice with ID (0 = all)
Definition: DataStructs.h:506
bool dbgSummary
print a summary report
Definition: DataStructs.h:521
master switch for turning on debug mode
Definition: DataStructs.h:449
CTP_t CTP
set to an invalid CTP
Definition: DebugStruct.h:22
void tca::DefineDontCluster ( TCSlice slc,
bool  prt 
)

Definition at line 3329 of file TCShower.cxx.

References DecodeCTP(), tca::TCSlice::dontCluster, DotProd(), GetAssns(), tca::TCSlice::ID, IsShowerLike(), kDebug, tca::TCConfig::modes, PFPDOCA(), tca::TCSlice::pfps, geo::PlaneID::Plane, PointDirection(), PosSep(), t1, t2, tcc, tca::DontClusterStruct::TjIDs, tca::TCSlice::tjs, tca::TCSlice::vtx3s, tca::DontClusterStruct::Vx2ID, and tca::DontClusterStruct::Vx3ID.

Referenced by FindShowers3D().

3330  {
3331  // make a list of tj pairs that pass the cuts, but shouldn't be clustered for
3332  // different reasons, e.g. are likely parent tjs in different showers, are both attached
3333  // to the same high-score vertex, etc
3334 
3335  slc.dontCluster.clear();
3336 
3337  DontClusterStruct dc;
3338  for(auto& vx3 : slc.vtx3s) {
3339  if(vx3.ID == 0) continue;
3340  if(!vx3.Neutrino) continue;
3341  auto PIn3V = GetAssns(slc, "3V", vx3.ID, "P");
3342  if(PIn3V.size() < 2) continue;
3343  Point3_t v3pos = {{vx3.X, vx3.Y, vx3.Z}};
3344  for(unsigned short ip1 = 0; ip1 < PIn3V.size() - 1; ++ip1) {
3345  auto& p1 = slc.pfps[PIn3V[ip1] - 1];
3346  // ignore the neutrino pfp
3347  if(p1.TjIDs.empty()) continue;
3348  unsigned short p1End = 0;
3349  if(p1.Vx3ID[1] == vx3.ID) p1End = 1;
3350  bool p1ShowerLike = IsShowerLike(slc, p1.TjIDs);
3351  // find the direction using the vertex position and the end that is
3352  // farthest away from the vertex
3353  auto p1Dir = PointDirection(v3pos, p1.XYZ[1 - p1End]);
3354  float p1Sep = PosSep(p1.XYZ[p1End], v3pos);
3355  for(unsigned short ip2 = ip1 + 1; ip2 < PIn3V.size(); ++ip2) {
3356  auto& p2 = slc.pfps[PIn3V[ip2] - 1];
3357  if(p2.TjIDs.empty()) continue;
3358  unsigned short p2End = 0;
3359  if(p2.Vx3ID[1] == vx3.ID) p2End = 1;
3360  auto p2Dir = PointDirection(v3pos, p2.XYZ[1 - p2End]);
3361  float p2Sep = PosSep(p2.XYZ[p2End], v3pos);
3362  // Look for the case where an electron starts to shower close to the
3363  // vertex, creating a daughter that is also attached to the vertex. This
3364  // pair is OK to include in a shower. The signature is that the PFP doca between them is less
3365  // than the pfp - vx3 separation and both are shower like - something like this
3366  // where 3V is a 3D vertex
3367  // \ P3 (not shower-like) -> 3V
3368  // 3V ----------- P1 -> 3V (shower-like or NOT shower-like)
3369  // ----------- P2 (shower-like doca closer to P1 than the vertex) -> 3V
3370  // The tjs in the P1 - P3 pair shouldn't be clustered
3371  // The tjs in the P2 - P3 pair shouldn't be clustered
3372  // The tjs in the P1 - P2 pair can be clustered
3373  bool p2ShowerLike = IsShowerLike(slc, p2.TjIDs);
3374  if(p1ShowerLike && p2ShowerLike) continue;
3375 
3376  float costh = DotProd(p1Dir, p2Dir);
3377  if(costh < 0.92) continue;
3378  unsigned short closePt1, closePt2;
3379  float doca = PFPDOCA(p1, p2, closePt1, closePt2);
3380  float minSep = p1Sep;
3381  if(p1Sep < minSep) minSep = p2Sep;
3382  bool allowCluster = (doca < minSep);
3383 
3384  if(tcc.modes[kDebug]) {
3385  std::cout<<"DDC: P"<<p1.ID<<" p1ShowerLike "<<p1ShowerLike;
3386  std::cout<<" P"<<p2.ID<<" p2ShowerLike "<<p2ShowerLike;
3387  std::cout<<" costh "<<costh;
3388  std::cout<<" doca "<<doca;
3389  std::cout<<" minSep "<<minSep;
3390  std::cout<<" allowCluster? "<<allowCluster;
3391  std::cout<<"\n";
3392  }
3393  if(!allowCluster) continue;
3394 
3395  // now enter the Tj pairs
3396  for(auto tid1 : p1.TjIDs) {
3397  auto& t1 = slc.tjs[tid1 - 1];
3398  for(auto tid2 : p2.TjIDs) {
3399  auto& t2 = slc.tjs[tid2 - 1];
3400  if(t1.CTP != t2.CTP) continue;
3401  dc.TjIDs[0] = tid1;
3402  dc.TjIDs[1] = tid2;
3403  if(dc.TjIDs[0] > dc.TjIDs[1]) std::swap(dc.TjIDs[0], dc.TjIDs[1]);
3404  dc.Vx2ID = vx3.Vx2ID[DecodeCTP(t1.CTP).Plane];
3405  dc.Vx3ID = vx3.ID;
3406  slc.dontCluster.push_back(dc);
3407  } // tid2
3408  } // tid1
3409  } // ip2
3410  } // ip1
3411  } // vx3
3412 
3413  } // DefineDontCluster
TTree * t1
Definition: plottest35.C:26
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4279
std::array< double, 3 > Point3_t
Definition: DataStructs.h:35
TCConfig tcc
Definition: DataStructs.cxx:6
float PFPDOCA(const PFPStruct &pfp1, const PFPStruct &pfp2, unsigned short &close1, unsigned short &close2)
Definition: PFPUtils.cxx:1790
bool IsShowerLike(TCSlice &slc, const std::vector< int > TjIDs)
Definition: TCShower.cxx:2002
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:1643
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
TTree * t2
Definition: plottest35.C:36
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
void swap(art::HLTGlobalStatus &lhs, art::HLTGlobalStatus &rhs)
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:59
geo::PlaneID DecodeCTP(CTP_t CTP)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
master switch for turning on debug mode
Definition: DataStructs.h:449
void tca::DefineEnvelope ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct ss,
bool  prt 
)

Definition at line 3869 of file TCShower.cxx.

References 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::TCConfig::showerTag, tca::ShowerStruct::ShowerTjID, tcc, tca::ShowerStruct::TjIDs, tca::TCSlice::tjs, and tca::TCConfig::unitsPerTick.

Referenced by ReverseShower(), and UpdateShower().

3870  {
3871 
3872  if(ss.ID == 0) return;
3873  if(ss.TjIDs.empty()) return;
3874  Trajectory& stj = slc.tjs[ss.ShowerTjID - 1];
3875  // shower Tj isn't fully defined yet
3876  if(stj.Pts[0].Pos[0] == 0) return;
3877 
3878  std::string fcnLabel = inFcnLabel + ".DE";
3879 
3880  ss.Envelope.resize(4);
3881  TrajPoint& stp0 = stj.Pts[0];
3882  TrajPoint& stp1 = stj.Pts[1];
3883  TrajPoint& stp2 = stj.Pts[2];
3884 
3885  // construct the Envelope polygon. Start with a rectangle using the fixed 1/2 width fcl input
3886  // expanded by the rms width at each end to create a polygon. The polygon is constructed along
3887  // the Pos[0] direction and then rotated into the ShowerTj direction. Use sTp1 as the origin.
3888  // First vertex
3889  ss.Envelope[0][0] = -PosSep(stp0.Pos, stp1.Pos);
3890  ss.Envelope[0][1] = tcc.showerTag[5] + tcc.showerTag[4] * stp0.DeltaRMS;
3891  // second vertex
3892  ss.Envelope[1][0] = PosSep(stp1.Pos, stp2.Pos);
3893  ss.Envelope[1][1] = tcc.showerTag[5] + tcc.showerTag[4] * stp2.DeltaRMS;
3894  // third and fourth are reflections of the first and second
3895  ss.Envelope[2][0] = ss.Envelope[1][0];
3896  ss.Envelope[2][1] = -ss.Envelope[1][1];
3897  ss.Envelope[3][0] = ss.Envelope[0][0];
3898  ss.Envelope[3][1] = -ss.Envelope[0][1];
3899 
3900  float length = ss.Envelope[1][0] - ss.Envelope[0][0];
3901  float width = ss.Envelope[0][1] + ss.Envelope[1][1];
3902  ss.EnvelopeArea = length * width;
3903 
3904  // Rotate into the stp1 coordinate system
3905  float cs = cos(stp1.Ang);
3906  float sn = sin(stp1.Ang);
3907  for(auto& vtx : ss.Envelope) {
3908  // Rotate along the stj shower axis
3909  float pos0 = cs * vtx[0] - sn * vtx[1];
3910  float pos1 = sn * vtx[0] + cs * vtx[1];
3911  // translate
3912  vtx[0] = pos0 + stp1.Pos[0];
3913  vtx[1] = pos1 + stp1.Pos[1];
3914  } // vtx
3915  // Find the charge density inside the envelope
3916  ss.ChgDensity = (stp0.Chg + stp1.Chg + stp2.Chg) / ss.EnvelopeArea;
3917  if(prt) {
3918  mf::LogVerbatim myprt("TC");
3919  myprt<<fcnLabel<<" 2S"<<ss.ID<<" Envelope";
3920  for(auto& vtx : ss.Envelope) myprt<<" "<<(int)vtx[0]<<":"<<(int)(vtx[1]/tcc.unitsPerTick);
3921  myprt<<" Area "<<(int)ss.EnvelopeArea;
3922  myprt<<" ChgDensity "<<ss.ChgDensity;
3923  }
3924  // This is the last function used to update a shower
3925  ss.NeedsUpdate = false;
3926  } // DefineEnvelope
TCConfig tcc
Definition: DataStructs.cxx:6
Float_t ss
Definition: plot.C:23
std::vector< float > showerTag
[min MCSMom, max separation, min # Tj < separation] for a shower tag
Definition: DataStructs.h:474
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
void tca::DefineHitPos ( TCSlice slc,
TrajPoint tp 
)

Definition at line 1840 of file StepUtils.cxx.

References tca::TCEvent::allHits, tca::TrajPoint::Chg, tca::TCConfig::dbgStp, tca::TrajPoint::Dir, evt, tca::TrajPoint::HitPos, tca::TrajPoint::HitPosErr2, tca::TrajPoint::Hits, HitsTimeErr2(), HitTimeErr(), kNewStpCuts, LongPulseHit(), tca::TCSlice::slHits, tcc, tca::TCConfig::unitsPerTick, tca::TCConfig::useAlg, and tca::TrajPoint::UseHit.

Referenced by AddHits(), AddLAHits(), CheckHiMultUnusedHits(), ChkStopEndPts(), FillGaps(), Forecast(), MakeHaloTj(), MakeJunkTraj(), MaskedHitsOK(), StepAway(), and UpdateTraj().

1841  {
1842  // defines HitPos, HitPosErr2 and Chg for the used hits in the trajectory point
1843 
1844  tp.Chg = 0;
1845  if(tp.Hits.empty()) return;
1846 
1847  unsigned short nused = 0;
1848  unsigned int iht = 0;
1849  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1850  if(!tp.UseHit[ii]) continue;
1851  ++nused;
1852  iht = tp.Hits[ii];
1853  }
1854  if(nused == 0) return;
1855 
1856  // don't bother with rest of this if there is only one hit since it can
1857  // only reside on one wire
1858  if(nused == 1) {
1859  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1860  tp.Chg = hit.Integral();
1861  tp.HitPos[0] = hit.WireID().Wire;
1862  tp.HitPos[1] = hit.PeakTime() * tcc.unitsPerTick;
1864  // give it a huge error^2 since the position is not well defined
1865  tp.HitPosErr2 = 100;
1866  } else {
1867  // Normalize to 1 WSE path length
1868  float pathInv = std::abs(tp.Dir[0]);
1869  if(pathInv < 0.05) pathInv = 0.05;
1870  tp.Chg *= pathInv;
1871  float wireErr = tp.Dir[1] * 0.289;
1872  float timeErr = tp.Dir[0] * HitTimeErr(slc, iht);
1873  tp.HitPosErr2 = wireErr * wireErr + timeErr * timeErr;
1874  }
1875  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"DefineHitPos: singlet "<<std::fixed<<std::setprecision(1)<<tp.HitPos[0]<<":"<<(int)(tp.HitPos[1]/tcc.unitsPerTick)<<" ticks. HitPosErr "<<sqrt(tp.HitPosErr2);
1876  return;
1877  } // nused == 1
1878 
1879  // multiple hits possibly on different wires
1880  std::vector<unsigned int> hitVec;
1881  tp.Chg = 0;
1882  std::array<float, 2> newpos;
1883  float chg;
1884  newpos[0] = 0;
1885  newpos[1] = 0;
1886  // Find the wire range for hits used in the TP
1887  unsigned int loWire = INT_MAX;
1888  unsigned int hiWire = 0;
1889  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1890  if(!tp.UseHit[ii]) continue;
1891  unsigned int iht = tp.Hits[ii];
1892  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1893  chg = hit.Integral();
1894  unsigned int wire = hit.WireID().Wire;
1895  if(wire < loWire) loWire = wire;
1896  if(wire > hiWire) hiWire = wire;
1897  newpos[0] += chg * wire;
1898  newpos[1] += chg * hit.PeakTime();
1899  tp.Chg += chg;
1900  hitVec.push_back(iht);
1901  } // ii
1902 
1903  if(tp.Chg == 0) return;
1904 
1905  tp.HitPos[0] = newpos[0] / tp.Chg;
1906  tp.HitPos[1] = newpos[1] * tcc.unitsPerTick / tp.Chg;
1907  // Normalize to 1 WSE path length
1908  float pathInv = std::abs(tp.Dir[0]);
1909  if(pathInv < 0.05) pathInv = 0.05;
1910  tp.Chg *= pathInv;
1911  // Error is the wire error (1/sqrt(12))^2 if all hits are on one wire.
1912  // Scale it by the wire range
1913  float dWire = 1 + hiWire - loWire;
1914  float wireErr = tp.Dir[1] * dWire * 0.289;
1915  float timeErr2 = tp.Dir[0] * tp.Dir[0] * HitsTimeErr2(slc, hitVec);
1916  tp.HitPosErr2 = wireErr * wireErr + timeErr2;
1917  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"DefineHitPos: multiplet "<<std::fixed<<std::setprecision(1)<<tp.HitPos[0]<<":"<<(int)(tp.HitPos[1]/tcc.unitsPerTick)<<" ticks. HitPosErr "<<sqrt(tp.HitPosErr2);
1918 
1919  } // DefineHitPos
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
bool LongPulseHit(const recob::Hit &hit)
Definition: Utils.cxx:3936
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
Detector simulation of raw signals on wires.
float HitTimeErr(TCSlice &slc, unsigned int iht)
Definition: StepUtils.cxx:1693
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
float HitsTimeErr2(TCSlice &slc, const std::vector< unsigned int > &hitVec)
Definition: StepUtils.cxx:1701
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
bool tca::DefinePFP ( std::string  inFcnLabel,
TCSlice slc,
PFPStruct pfp,
bool  prt 
)

Definition at line 2233 of file PFPUtils.cxx.

References CompatibleMerge(), DecodeCTP(), evd::details::end(), FindCompleteness(), FollowTp3s(), tca::PFPStruct::ID, kHaloTj, kKilled, kMat3D, kMat3DMerge, tca::TCConfig::match3DCuts, tca::TCSlice::matchVec, tca::PFPStruct::MatchVecIndex, MaxTjLen(), MCSMom(), MergePFPTjs(), tca::PFPStruct::NeedsUpdate, tca::TCSlice::nPlanes, tca::PFPStruct::PDGCode, PFPVxTjOK(), geo::PlaneID::Plane, PosSep(), SetIntersection(), SetStart(), SharesHighScoreVx(), tcc, tca::PFPStruct::TjIDs, tca::TCSlice::tjs, tca::PFPStruct::Tp3s, tca::TCConfig::useAlg, tca::TCSlice::vtxs, and tca::PFPStruct::Vx3ID.

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

2234  {
2235  // This function is called after the 3D matched TjIDs have been specified and optionally
2236  // a start or end vertex ID. It defines the PFParticle but doesn't store it
2237 
2238  if(pfp.PDGCode == 1111) return false;
2239  if(pfp.TjIDs.size() < 2) return false;
2240 
2241  std::string fcnLabel = inFcnLabel + ".DPFP";
2242 
2243  // require at least one tj in at least two planes
2244  std::vector<unsigned short> nInPln(slc.nPlanes);
2245  for(auto tjid : pfp.TjIDs) {
2246  auto& tj = slc.tjs[tjid - 1];
2247  ++nInPln[DecodeCTP(tj.CTP).Plane];
2248  if(tj.AlgMod[kMat3D] || tj.AlgMod[kKilled]) {
2249  std::cout<<fcnLabel<<" P"<<pfp.ID<<" uses T"<<tj.ID<<" but kMat3D is set true\n";
2250  return false;
2251  }
2252  } // tjid
2253  unsigned short npl = 0;
2254  for(unsigned short plane = 0; plane < slc.nPlanes; ++plane) if(nInPln[plane] > 0) ++npl;
2255  if(npl < 2) return false;
2256 
2257  for(unsigned short end = 0; end < 2; ++end) {
2258  if(pfp.Vx3ID[end] < 0 || pfp.Vx3ID[end] > (int)slc.vtxs.size()) {
2259  std::cout<<fcnLabel<<" P"<<pfp.ID<<" end "<<end<<" is invalid\n";
2260  return false;
2261  }
2262  } // end
2263 
2264  if(pfp.Vx3ID[0] == 0 && pfp.Vx3ID[1] > 0) {
2265  std::cout<<fcnLabel<<" P"<<pfp.ID<<" end 1 has a vertex but end 0 doesn't. No endpoints defined\n";
2266  return false;
2267  }
2268 
2269  // check for vertex consistency. There should only be one tj in each plane
2270  // that is attached to a vertex. Remove the shorter tj from the list
2271  // if that is not the case
2272  if(pfp.Vx3ID[0] > 0) PFPVxTjOK(slc, pfp, prt);
2273 
2274  bool pfpTrackLike = (MaxTjLen(slc, pfp.TjIDs) > tcc.match3DCuts[5] && MCSMom(slc, pfp.TjIDs) > tcc.match3DCuts[3]);
2275  // don't look for broken Tjs for primary electron PFPs
2276  if(pfp.PDGCode == 111) pfpTrackLike = false;
2277 
2278  if(prt) {
2279  mf::LogVerbatim myprt("TC");
2280  myprt<<fcnLabel<<" pfp P"<<pfp.ID;
2281  myprt<<" Vx3ID 3V"<<pfp.Vx3ID[0]<<" 3V"<<pfp.Vx3ID[1];
2282  myprt<<" Tjs";
2283  for(auto id : pfp.TjIDs) myprt<<" T"<<id;
2284  myprt<<" matchVec index "<<pfp.MatchVecIndex;
2285  myprt<<" max Tj len "<<MaxTjLen(slc, pfp.TjIDs);
2286  myprt<<" MCSMom "<<MCSMom(slc, pfp.TjIDs);
2287  myprt<<" pfpTrackLike? "<<pfpTrackLike;
2288  } // prt
2289 
2290  if(tcc.useAlg[kMat3DMerge] && pfpTrackLike && pfp.MatchVecIndex < slc.matchVec.size()) {
2291  // The index of slc.matchVec has been specified for this pfp so we can look for evidence of
2292  // broken Tjs starting at the beginning
2293  for(unsigned short ims = 0; ims < pfp.MatchVecIndex + 10; ++ims) {
2294  if(ims >= slc.matchVec.size()) break;
2295  auto& ms = slc.matchVec[ims];
2296  if(ms.Count == 0) continue;
2297  std::vector<int> shared = SetIntersection(ms.TjIDs, pfp.TjIDs);
2298  if(shared.size() < 2) continue;
2299  // check the max length Tj and cut on MCSMom
2300  if(MaxTjLen(slc, ms.TjIDs) < tcc.match3DCuts[5]) continue;
2301  if(MCSMom(slc, ms.TjIDs) < tcc.match3DCuts[3]) continue;
2302  for(auto tjid : ms.TjIDs) {
2303  if(std::find(shared.begin(), shared.end(), tjid) != shared.end()) continue;
2304  auto& tj = slc.tjs[tjid - 1];
2305  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
2306  if(tj.AlgMod[kMat3D]) continue;
2307  // check for PDGCode compatibility - muons and delta rays
2308  if(pfp.PDGCode == 13 && tj.PDGCode == 11) continue;
2309  if(pfp.PDGCode == 11 && tj.PDGCode == 13) continue;
2310  if(SharesHighScoreVx(slc, pfp, tj)) continue;
2311  if(tj.MCSMom < tcc.match3DCuts[3]) continue;
2312  float len = PosSep(tj.Pts[tj.EndPt[0]].Pos, tj.Pts[tj.EndPt[1]].Pos);
2313  if(len < tcc.match3DCuts[5]) continue;
2314  // check for a compatible merge
2315  bool skipit = false;
2316  for(auto tjid : pfp.TjIDs) {
2317  auto& ptj = slc.tjs[tjid - 1];
2318  if(ptj.CTP != tj.CTP) continue;
2319  if(!CompatibleMerge(slc, tj, ptj, prt)) {
2320  skipit = true;
2321  break;
2322  }
2323  } // tjid
2324  if(skipit) continue;
2325  if(prt) mf::LogVerbatim("TC")<<" add T"<<tjid<<" MCSMom "<<tj.MCSMom<<" length "<<len;
2326  pfp.TjIDs.push_back(tjid);
2327  PFPVxTjOK(slc, pfp, prt);
2328  } // tjid
2329  } // ims
2330  } // matchVec index defined
2331 
2332 /* BB April 25. CheckAndMerge needs work. Shut it off for now.
2333  // check the completeness of matching points in this set of Tjs and possibly
2334  // merge Tjs
2335  if(tcc.useAlg[kMat3DMerge] && pfpTrackLike) {
2336  if(!CheckAndMerge(slc, pfp, prt)) return false;
2337  } else {
2338  // not track-like. Find completeness and fill the TP3s
2339  FindCompleteness(slc, pfp, true, true, prt);
2340  }
2341 */
2342  // Find completeness and fill the TP3s
2343  FindCompleteness(slc, pfp, true, true, prt);
2344  if(pfp.Tp3s.empty()) return false;
2345 
2346  // Set the starting position in 3D if it isn't already defined by a 3D vertex
2347  SetStart(slc, pfp, prt);
2348  FollowTp3s(slc, pfp, prt);
2349  // Check the list of Tjs and merge those that are in the same plane
2350  MergePFPTjs(slc, pfp, prt);
2351 
2352  if(prt) {
2353  mf::LogVerbatim myprt("TC");
2354  myprt<<fcnLabel<<" pfp P"<<pfp.ID;
2355  myprt<<" Vx3ID 3V"<<pfp.Vx3ID[0]<<" 3V"<<pfp.Vx3ID[1];
2356  myprt<<" Tjs";
2357  for(auto id : pfp.TjIDs) myprt<<" T"<<id;
2358  myprt<<" Tp3s size "<<pfp.Tp3s.size();
2359  }
2360 
2361  pfp.NeedsUpdate = false;
2362  return true;
2363  } // DefinePFP
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void FindCompleteness(TCSlice &slc, PFPStruct &pfp, bool doFit, bool fillTp3s, bool prt)
Definition: PFPUtils.cxx:737
short MCSMom(TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2914
TCConfig tcc
Definition: DataStructs.cxx:6
bool MergePFPTjs(TCSlice &slc, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:1203
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:231
float MaxTjLen(TCSlice &slc, std::vector< int > &tjIDs)
Definition: Utils.cxx:2322
std::vector< float > match3DCuts
3D matching cuts
Definition: DataStructs.h:476
void FollowTp3s(TCSlice &slc, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:405
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
geo::PlaneID DecodeCTP(CTP_t CTP)
bool SetStart(TCSlice &slc, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:351
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
bool SharesHighScoreVx(TCSlice &slc, const PFPStruct &pfp, const Trajectory &tj)
Definition: PFPUtils.cxx:1026
bool PFPVxTjOK(TCSlice &slc, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:2366
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool CompatibleMerge(TCSlice &slc, std::vector< int > &tjIDs, bool prt)
Definition: Utils.cxx:534
void tca::DefinePFPParents ( TCSlice slc,
bool  prt 
)

Definition at line 2530 of file PFPUtils.cxx.

References GetAssns(), IsShowerLike(), kDebug, kTestBeam, tca::TCConfig::modes, tca::TCSlice::nPlanes, PDGCodeVote(), tca::TCSlice::pfps, tcc, tca::TCSlice::tjs, and tca::TCSlice::vtxs.

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

2531  {
2532  /*
2533  This function reconciles vertices, PFParticles and slc, then
2534  defines the parent (j) - daughter (i) relationship and PDGCode. Here is a
2535  description of the conventions:
2536 
2537  V1 is the highest score 3D vertex in this tpcid so a neutrino PFParticle P1 is defined.
2538  V4 is a high-score vertex that has lower score than V1. It is declared to be a
2539  primary vertex because its score is higher than V5 and it is not associated with the
2540  neutrino interaction
2541  V6 was created to adhere to the convention that all PFParticles, in this case P9,
2542  be associated with a start vertex. There is no score for V6. P9 is it's own parent
2543  but is not a primary PFParticle.
2544 
2545  P1 - V1 - P2 - V2 - P4 - V3 - P5 V4 - P6 V6 - P9
2546  \ \
2547  P3 P7 - V5 - P8
2548 
2549  The PrimaryID in this table is the ID of the PFParticle that is attached to the
2550  primary vertex, which may or may not be a neutrino interaction vertex.
2551  The PrimaryID is returned by the PrimaryID function
2552  PFP parentID DtrIDs PrimaryID
2553  -----------------------------------
2554  P1 P1 P2, P3 P1
2555  P2 P1 P4 P2
2556  P3 P1 none P3
2557  P4 P2 P5 P2
2558  P5 P4 none P2
2559 
2560  P6 P6 none P6
2561  P7 P7 P8 P7
2562 
2563  P9 P9 none 0
2564 
2565  */
2566  if(slc.pfps.empty()) return;
2567  if(tcc.modes[kTestBeam]) return;
2568 
2569  int neutrinoPFPID = 0;
2570  for(auto& pfp : slc.pfps) {
2571  if(pfp.ID == 0) continue;
2572  if(!tcc.modes[kTestBeam] && neutrinoPFPID == 0 && (pfp.PDGCode == 12 || pfp.PDGCode == 14)) {
2573  neutrinoPFPID = pfp.ID;
2574  break;
2575  }
2576  } // pfp
2577 
2578  // define the end vertex if the Tjs have end vertices
2579  constexpr unsigned short end1 = 1;
2580  for(auto& pfp : slc.pfps) {
2581  if(pfp.ID == 0) continue;
2582  // already done?
2583  if(pfp.Vx3ID[end1] > 0) continue;
2584  // ignore shower-like pfps
2585  if(IsShowerLike(slc, pfp.TjIDs)) continue;
2586  // count 2D -> 3D matched vertices
2587  unsigned short cnt3 = 0;
2588  unsigned short vx3id = 0;
2589  // list of unmatched 2D vertices that should be merged
2590  std::vector<int> vx2ids;
2591  for(auto tjid : pfp.TjIDs) {
2592  auto& tj = slc.tjs[tjid - 1];
2593  if(tj.VtxID[end1] == 0) continue;
2594  auto& vx2 = slc.vtxs[tj.VtxID[end1] - 1];
2595  if(vx2.Vx3ID == 0) {
2596  if(vx2.Topo == 1 && vx2.NTraj == 2) vx2ids.push_back(vx2.ID);
2597  continue;
2598  }
2599  if(vx3id == 0) vx3id = vx2.Vx3ID;
2600  if(vx2.Vx3ID == vx3id) ++cnt3;
2601  } // tjid
2602  if(cnt3 > 1) {
2603  // ensure it isn't attached at the other end
2604  if(pfp.Vx3ID[1 - end1] == vx3id) continue;
2605  pfp.Vx3ID[end1] = vx3id;
2606  if(cnt3 != slc.nPlanes && tcc.modes[kDebug]) {
2607  std::cout<<"DPFPR: Missed an end vertex for PFP "<<pfp.ID<<" Write some code\n";
2608  }
2609  } // cnt3 > 1
2610  } // pfp
2611 
2612  // Assign a PDGCode to each PFParticle and look for a parent
2613  for(auto& pfp : slc.pfps) {
2614  if(pfp.ID == 0) continue;
2615  // skip a neutrino PFParticle
2616  if(pfp.PDGCode == 12 || pfp.PDGCode == 14 || pfp.PDGCode == 22) continue;
2617  pfp.PDGCode = PDGCodeVote(slc, pfp.TjIDs, prt);
2618  // Define a PFP parent if there are two or more Tjs that are daughters of
2619  // Tjs that are used by the same PFParticle
2620  int pfpParentID = INT_MAX;
2621  unsigned short nParent = 0;
2622  for(auto tjid : pfp.TjIDs) {
2623  auto& tj = slc.tjs[tjid - 1];
2624  if(tj.ParentID <= 0) continue;
2625  auto parPFP = GetAssns(slc, "T", tj.ParentID, "P");
2626  if(parPFP.empty()) continue;
2627  if(pfpParentID == INT_MAX) pfpParentID = parPFP[0];
2628  if(parPFP[0] == pfpParentID) ++nParent;
2629  } // ii
2630  if(nParent > 1) {
2631  auto& ppfp = slc.pfps[pfpParentID - 1];
2632  // set the parent UID
2633  pfp.ParentUID = ppfp.UID;
2634  // add to the parent daughters list
2635  ppfp.DtrUIDs.push_back(pfp.UID);
2636  } // nParent > 1
2637  } // ipfp
2638 
2639 /* TODO: This needs work
2640  if(tcc.modes[kTestBeam]) {
2641  DefinePFPParentsTestBeam(slc, prt);
2642  return;
2643  }
2644 */
2645  // associate primary PFParticles with a neutrino PFParticle
2646  if(neutrinoPFPID > 0) {
2647  auto& neutrinoPFP = slc.pfps[neutrinoPFPID - 1];
2648  int vx3id = neutrinoPFP.Vx3ID[1];
2649  for(auto& pfp : slc.pfps) {
2650  if(pfp.ID == 0 || pfp.ID == neutrinoPFPID) continue;
2651  if(pfp.Vx3ID[0] != vx3id) continue;
2652  pfp.ParentUID = (size_t)neutrinoPFPID;
2653  pfp.Primary = true;
2654  neutrinoPFP.DtrUIDs.push_back(pfp.ID);
2655  if(pfp.PDGCode == 111) neutrinoPFP.PDGCode = 12;
2656  } // pfp
2657  } // neutrino PFP exists
2658  } // DefinePFPParents
Expect tracks entering from the front face. Don&#39;t create neutrino PFParticles.
Definition: DataStructs.h:448
int PDGCodeVote(TCSlice &slc, std::vector< int > &tjIDs, bool prt)
Definition: Utils.cxx:372
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4279
TCConfig tcc
Definition: DataStructs.cxx:6
bool IsShowerLike(TCSlice &slc, const std::vector< int > TjIDs)
Definition: TCShower.cxx:2002
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
master switch for turning on debug mode
Definition: DataStructs.h:449
void tca::DefinePFPParentsTestBeam ( TCSlice slc,
bool  prt 
)

Definition at line 2661 of file PFPUtils.cxx.

References GetPFPIndex(), GetVtxTjIDs(), tca::TCSlice::pfps, SetDifference(), tca::TCSlice::vtx3s, and tca::TCSlice::zLo.

Referenced by DotProd().

2662  {
2663  // analog of the one above that was written for neutrino interactions. This differs in that
2664  // the Tj parent - daughter relationship isn't known yet. If one exists, it is ignored...
2665  // The assumption here is that all PFParticles that enter (end0) from upstream Z are parents and
2666  // any PFParticles attached to them at end1 are daughters.
2667 
2668  // create a list (stack) of parent ID <-> daughter IDs. The idea is similar to that
2669  // used in DefineTjParents. A parent-daughter association is made for each entry. After
2670  // it is made, 1) that entry is removed from the stack, 2) the daughter is checked to see
2671  // if it a parent of a grand-daughter and if so that pair is added to the stack.
2672  std::vector<std::pair<unsigned short, unsigned short>> pardtr;
2673 
2674  // Fill the stack with parents that enter the TPC and have daughters attached to
2675  // 3D vertices at the other end
2676  double fidZCut = slc.zLo + 2;
2677  for(auto& parPFP : slc.pfps) {
2678  if(parPFP.ID == 0) continue;
2679  parPFP.Primary = false;
2680  if(parPFP.XYZ[0][2] > fidZCut) continue;
2681  parPFP.Primary = true;
2682  // we found a pfp that entered the TPC. Call it the parent and look for a daughter
2683  if(prt) mf::LogVerbatim("TC")<<"DPFPTestBeam: parent "<<parPFP.ID<<" end1 vtx "<<parPFP.Vx3ID[1];
2684  if(parPFP.Vx3ID[1] == 0) continue;
2685  // There must be other Tjs attached to this vertex which are the daughters. Find them
2686  // and add them to the pardtr stack
2687  float score = 0;
2688  auto& vx3 = slc.vtx3s[parPFP.Vx3ID[1] - 1];
2689  // ensure that it is valid
2690  if(vx3.ID == 0) continue;
2691  // get a list of Tjs attached to this vertex. This will include the Tjs in the parent.
2692  auto vx3TjList = GetVtxTjIDs(slc, vx3, score);
2693  if(vx3TjList.empty()) continue;
2694  // filter out the parent Tjs
2695  auto dtrTjlist = SetDifference(vx3TjList, parPFP.TjIDs);
2696  if(prt) {
2697  mf::LogVerbatim myprt("TC");
2698  myprt<<" Dtrs:";
2699  for(auto dtjID : dtrTjlist) myprt<<" "<<dtjID<<"_"<<GetPFPIndex(slc, dtjID);
2700  }
2701  // Add to the stack
2702  for(auto dtjID : dtrTjlist) {
2703  unsigned short pfpIndex = GetPFPIndex(slc, dtjID);
2704  if(pfpIndex > slc.pfps.size() - 1) continue;
2705  unsigned short dtrID = pfpIndex + 1;
2706  // See if this is a duplicate
2707  bool duplicate = false;
2708  for(auto& pd : pardtr) if(parPFP.ID == pd.first && dtrID == pd.second) duplicate = true;
2709  if(!duplicate) pardtr.push_back(std::make_pair(parPFP.ID, dtrID));
2710  } // dtjID
2711  } // parPFP
2712 
2713  // iterate through the parent - daughter stack, removing the last pair when a
2714  // ParentID is updated and adding pairs for new daughters
2715  for(unsigned short nit = 0; nit < 100; ++nit) {
2716  if(pardtr.empty()) break;
2717  auto lastPair = pardtr[pardtr.size() - 1];
2718  auto& dtr = slc.pfps[lastPair.second - 1];
2719  auto& par = slc.pfps[lastPair.first - 1];
2720  dtr.ParentUID = par.UID;
2721  par.DtrUIDs.push_back(dtr.UID);
2722  // remove the last pair
2723  pardtr.pop_back();
2724  // Now see if the daughter is a parent. First check for a vertex at the other end.
2725  // To do that we need to know which end has the vertex between the parent and daughter
2726  unsigned short dtrEnd = USHRT_MAX;
2727  for(unsigned short ep = 0; ep < 2; ++ep) {
2728  if(par.Vx3ID[ep] == 0) continue;
2729  for(unsigned short ed = 0; ed < 2; ++ed) if(dtr.Vx3ID[ed] == par.Vx3ID[ep]) dtrEnd = ed;
2730  } // ep
2731  if(dtrEnd > 1) continue;
2732  // look at the other end of the daughter
2733  dtrEnd = 1 - dtrEnd;
2734  // check for a vertex
2735  if(dtr.Vx3ID[dtrEnd] == 0) continue;
2736  // get the list of Tjs attached to it
2737  auto& vx3 = slc.vtx3s[dtr.Vx3ID[dtrEnd] - 1];
2738  float score = 0;
2739  auto vx3TjList = GetVtxTjIDs(slc, vx3, score);
2740  if(vx3TjList.empty()) continue;
2741  // filter out the new parent
2742  auto dtrTjlist = SetDifference(vx3TjList, dtr.TjIDs);
2743  // put these onto the stack
2744  for(auto tjid : dtrTjlist) pardtr.push_back(std::make_pair(dtr.ID, tjid));
2745  } // nit
2746  } // DefinePFPParentsTestBeam
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
unsigned short GetPFPIndex(TCSlice &slc, int tjID)
Definition: Utils.cxx:1127
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const VtxStore &vx2)
Definition: TCVertex.cxx:3226
std::vector< T > SetDifference(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:253
void tca::DefineTjParents ( TCSlice slc,
bool  prt 
)

Definition at line 129 of file Utils.cxx.

References CreatePFP(), evd::details::end(), GetVtxTjIDs(), SortEntry::index, kDeltaRay, kHaloTj, kKilled, kTestBeam, tca::TCConfig::match3DCuts, tca::TCConfig::modes, ReverseTraj(), StorePFP(), tcc, tca::TCSlice::tjs, TrajTrajDOCA(), valDecreasing(), tca::TCConfig::vtx2DCuts, tca::TCSlice::vtx3s, and tca::TCSlice::vtxs.

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

130  {
131 /*
132  This function sets the ParentUID of Tjs in this tpcid to create a hierarchy. The highest Score
133  3D vertex in a chain of Tjs and vertices is declared the primary vertex; vx3.Primary = true. Tjs directly attached
134  to that vertex are declared Primary trajectories with ParentUID = 0. All other Tjs in the chain have ParentUID
135  set to the next upstream Tj to which it is attached by a vertex. In the graphical description below, V1 and V4 are
136  2D vertices that are matched to a high-score 3D vertex. The V1 Score is greater than the V2 Score and V3 Score.
137  V1 and V4 are declared to be primary vertices. T1, T2, T6 and T7 are declared to be primary Tjs
138 
139  V1 - T1 - V2 - T3 V4 - T6 / T8
140  \ \ /
141  T2 - V3 - T4 T7
142  \
143  T5
144 
145  This is represented as follows. The NeutrinoPrimaryTjID is defined by a function.
146  Tj ParentUID NeutrinoPrimaryTjID
147  -----------------------------------
148  T1 0 T1
149  T2 0 T2
150  T3 T1 T2
151  T4 T2 T2
152  T5 T2 T2
153  T6 0 -1
154  T7 0 -1
155  T8 -1 -1
156 */
157 
158  // don't do anything if this is test beam data
159  if(tcc.modes[kTestBeam]) return;
160 
161  // clear old information
162  for(auto& tj : slc.tjs) {
163  if(tj.AlgMod[kKilled]) continue;
164  // ignore delta rays
165  if(tj.AlgMod[kDeltaRay] || tj.AlgMod[kHaloTj]) continue;
166  tj.ParentID = 0;
167  } // tj
168 
169  // sort vertice by decreasing score
170  std::vector<int> temp;
171  for(auto& vx3 : slc.vtx3s) {
172  if(vx3.ID == 0) continue;
173  // clear the Primary flag while we are here
174  vx3.Primary = false;
175  temp.push_back(vx3.ID);
176  } // vx3
177  if(temp.empty()) return;
178 
179  // Make a master list of all Tjs that are attached to these vertices
180  std::vector<int> masterlist;
181  for(auto vx3id : temp) {
182  auto& vx3 = slc.vtx3s[vx3id - 1];
183  float score;
184  auto tjlist = GetVtxTjIDs(slc, vx3, score);
185  for(auto tjid : tjlist) {
186  // Temp? Check for an existing parentID
187  auto& tj = slc.tjs[tjid - 1];
188  if(tj.ParentID != 0) {
189 // std::cout<<"**** Tj "<<tj.ID<<" Existing parent "<<tj.ParentID<<" PDGCode "<<tj.PDGCode<<". with a vertex... \n";
190  tj.ParentID = 0;
191  }
192  if(std::find(masterlist.begin(), masterlist.end(), tjid) == masterlist.end()) masterlist.push_back(tjid);
193  } // tjid
194  } // vxid
195  if(prt) {
196  mf::LogVerbatim myprt("TC");
197  myprt<<"DTP: masterlist Tjs";
198  for(auto tjid : masterlist) myprt<<" "<<tjid;
199  }
200 
201  // Do the sort
202  std::vector<SortEntry> sortVec(temp.size());
203  for(unsigned short indx = 0; indx < temp.size(); ++indx) {
204  auto& vx3 = slc.vtx3s[temp[indx] - 1];
205  sortVec[indx].index = indx;
206  sortVec[indx].val = vx3.Score;
207  } // indx
208  if(sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(), valDecreasing);
209  // put them into order
210  auto vlist = temp;
211  for(unsigned short indx = 0; indx < temp.size(); ++indx) vlist[indx] = temp[sortVec[indx].index];
212 
213  // make a neutrino PFParticle to associate with the highest score vertex if it is high enough
214  if(tcc.match3DCuts[0] > 0) {
215  auto& vx3 = slc.vtx3s[vlist[0] - 1];
216  if(vx3.Score > tcc.vtx2DCuts[7]) {
217  auto neutrinoPFP = CreatePFP(slc);
218  // call it the neutrino vertex
219  vx3.Neutrino = true;
220  // put the vertex at the end of the neutrino
221  neutrinoPFP.XYZ[1][0] = vx3.X;
222  neutrinoPFP.XYZ[1][1] = vx3.Y;
223  neutrinoPFP.XYZ[1][2] = vx3.Z;
224  neutrinoPFP.XYZ[0] = neutrinoPFP.XYZ[1];
225  neutrinoPFP.Dir[1][2] = 1;
226  neutrinoPFP.Dir[0][2] = 1;
227  // This may be set to 12 later on if a primary shower is reconstructed
228  neutrinoPFP.PDGCode = 14;
229  neutrinoPFP.Vx3ID[1] = vx3.ID;
230  neutrinoPFP.Vx3ID[0] = vx3.ID;
231  neutrinoPFP.NeedsUpdate = false;
232  // the rest of this will be defined later
233  if(!StorePFP(slc, neutrinoPFP)) return;
234  }
235  } // User wants to make PFParticles
236  // a temp vector to ensure that we only consider a vertex once
237  std::vector<bool> lookedAt3(slc.vtx3s.size() + 1, false);
238  std::vector<bool> lookedAt2(slc.vtxs.size() + 1, false);
239  // vector of parent-daughter pairs
240  std::vector<std::pair<int, int>> pardtr;
241  // Start with the highest score vertex
242  for(unsigned short indx = 0; indx < vlist.size(); ++indx) {
243  auto& vx3 = slc.vtx3s[vlist[indx] - 1];
244  if(lookedAt3[vx3.ID]) continue;
245  vx3.Primary = true;
246  lookedAt3[vx3.ID] = true;
247  // make a list of Tjs attached to this vertex
248  float score;
249  auto primTjList = GetVtxTjIDs(slc, vx3, score);
250  if(primTjList.empty()) continue;
251  pardtr.clear();
252  for(auto primTjID : primTjList) {
253  auto& primTj = slc.tjs[primTjID - 1];
254  // This isn't a primary tj if the parent ID isn't -1
255  if(primTj.ParentID != -1) continue;
256  if(prt) mf::LogVerbatim("TC")<<"Vx3 "<<vx3.ID<<" Primary tj "<<primTj.ID;
257  // declare this a primary tj
258  primTj.ParentID = 0;
259  // look for daughter tjs = those that are attached to a 2D vertex
260  // at the other end
261  for(unsigned short end = 0; end < 2; ++end) {
262  if(primTj.VtxID[end] == 0) continue;
263  auto& vx2 = slc.vtxs[primTj.VtxID[end] - 1];
264  if(vx2.Vx3ID == vx3.ID) continue;
265  // found a 2D vertex. Check for daughters
266  auto dtrList = GetVtxTjIDs(slc, vx2);
267  for(auto dtrID : dtrList) {
268  // ignore the primary tj
269  if(dtrID == primTjID) continue;
270  auto& dtj = slc.tjs[dtrID - 1];
271  if(dtj.ParentID != -1) {
272 // std::cout<<"DTP Error: dtr "<<dtrID<<" already has a parent "<<dtj.ParentID<<". Can't make it daughter of "<<primTjID<<"\n";
273  continue;
274  }
275  pardtr.push_back(std::make_pair(primTjID, dtrID));
276  if(prt) mf::LogVerbatim("TC")<<" primTj "<<primTjID<<" dtrID "<<dtrID;
277  } // tjid
278  } // end
279  // Ensure that end 0 of the trajectory is attached to the primary vertex
280  for(unsigned short end = 0; end < 2; ++end) {
281  if(primTj.VtxID[end] == 0) continue;
282  auto& vx2 = slc.vtxs[primTj.VtxID[end] - 1];
283  if(vx2.Vx3ID == vx3.ID && end != 0) ReverseTraj(slc, primTj);
284  } // end
285  } // tjid
286  if(pardtr.empty()) continue;
287  if(prt) {
288  mf::LogVerbatim myprt("TC");
289  myprt<<" par_dtr";
290  for(auto pdtr : pardtr) myprt<<" "<<pdtr.first<<"_"<<pdtr.second;
291  }
292  // iterate through the parent - daughter stack, removing the last pair when a
293  // ParentID is updated and adding pairs for new daughters
294  for(unsigned short nit = 0; nit < 100; ++nit) {
295  auto lastPair = pardtr[pardtr.size() - 1];
296  auto& dtj = slc.tjs[lastPair.second - 1];
297  dtj.ParentID = lastPair.first;
298  // reverse the daughter trajectory if necessary so that end 0 is closest to the parent
299  float doca = 100;
300  unsigned short dpt = 0, ppt = 0;
301  auto& ptj = slc.tjs[lastPair.first - 1];
302  // find the point on the daughter tj that is closest to the parent
303  TrajTrajDOCA(slc, dtj, ptj, dpt, ppt, doca);
304  // reverse the daughter if the closest point is near end 1 of the daughter
305  if(prt) mf::LogVerbatim("TC")<<"Set parent "<<ptj.ID<<" dtr "<<dtj.ID;
306  // remove that entry
307  pardtr.pop_back();
308  // Add entries for new daughters
309  for(unsigned short end = 0; end < 2; ++end) {
310  if(dtj.VtxID[end] == 0) continue;
311  auto& vx2 = slc.vtxs[dtj.VtxID[end] - 1];
312  if(lookedAt2[vx2.ID]) continue;
313  lookedAt2[vx2.ID] = true;
314  auto tjlist = GetVtxTjIDs(slc, vx2);
315  for(auto tjid : tjlist) {
316  if(tjid == dtj.ID || tjid == ptj.ID) continue;
317  pardtr.push_back(std::make_pair(dtj.ID, tjid));
318  if(prt) {
319  mf::LogVerbatim myprt("TC");
320  myprt<<" add par_dtr";
321  for(auto pdtr : pardtr) myprt<<" "<<pdtr.first<<"_"<<pdtr.second;
322  }
323  }
324  } // end
325  if(pardtr.empty()) break;
326  } // nit
327  } // indx
328  // check the master list
329  for(auto tjid : masterlist) {
330  auto& tj = slc.tjs[tjid - 1];
331  if(tj.ParentID < 0) {
332 // std::cout<<"Tj "<<tj.ID<<" is in the master list but doesn't have a Parent\n";
333  tj.ParentID = tj.ID;
334  }
335  } // tjid
336 
337  } // DefineTjParents
Expect tracks entering from the front face. Don&#39;t create neutrino PFParticles.
Definition: DataStructs.h:448
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
bool TrajTrajDOCA(TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep, bool considerDeadWires)
Definition: Utils.cxx:2181
std::vector< float > match3DCuts
3D matching cuts
Definition: DataStructs.h:476
void ReverseTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:2751
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
PFPStruct CreatePFP(TCSlice &slc)
Definition: PFPUtils.cxx:1973
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const VtxStore &vx2)
Definition: TCVertex.cxx:3226
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:466
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool StorePFP(TCSlice &slc, PFPStruct &pfp)
Definition: PFPUtils.cxx:2749
bool valDecreasing(SortEntry c1, SortEntry c2)
Definition: Utils.cxx:14
double tca::DeltaAngle ( const Vector3_t  v1,
const Vector3_t  v2 
)

Definition at line 1636 of file PFPUtils.cxx.

References DotProd().

Referenced by AddLAHits(), ChkVxTjs(), DotProd(), EndMerge(), FindHammerVertices(), FindHammerVertices2(), FindSoftKink(), FindXMatches(), KinkAngle(), ParentFOM(), PrintTp3s(), SetVx2Score(), SplitTrajCrossingVertices(), and StepAway().

1637  {
1638  if(v1[0] == v2[0] && v1[1] == v2[1] && v1[2] == v2[2]) return 0;
1639  return acos(DotProd(v1, v2));
1640  }
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:59
double tca::DeltaAngle ( const Point2_t p1,
const Point2_t p2 
)

Definition at line 2839 of file Utils.cxx.

References DeltaAngle2().

2840  {
2841  // angle between two points
2842  double ang1 = atan2(p1[1], p1[0]);
2843  double ang2 = atan2(p2[1], p2[0]);
2844  return DeltaAngle2(ang1, ang2);
2845  } // DeltaAngle
double DeltaAngle2(double Ang1, double Ang2)
Definition: Utils.cxx:2848
double tca::DeltaAngle ( double  Ang1,
double  Ang2 
)

Definition at line 2858 of file Utils.cxx.

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

2859  {
2860  return std::abs(std::remainder(Ang1 - Ang2, M_PI));
2861  }
double tca::DeltaAngle2 ( double  Ang1,
double  Ang2 
)

Definition at line 2848 of file Utils.cxx.

Referenced by DeltaAngle(), and DotProd().

2849  {
2850  constexpr double twopi = 2 * M_PI;
2851  double dang = Ang1 - Ang2;
2852  while(dang > M_PI) dang -= twopi;
2853  while(dang < -M_PI) dang += twopi;
2854  return dang;
2855  }
bool tca::DontCluster ( TCSlice slc,
const std::vector< int > &  tjlist1,
const std::vector< int > &  tjlist2 
)

Definition at line 3313 of file TCShower.cxx.

References tca::TCSlice::dontCluster.

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

3314  {
3315  // returns true if a pair of tjs in the two lists are in the dontCluster vector
3316  if(tjlist1.empty() || tjlist2.empty()) return false;
3317  if(slc.dontCluster.empty()) return false;
3318  for(auto tid1 : tjlist1) {
3319  for(auto tid2 : tjlist2) {
3320  int ttid1 = tid1;
3321  if(ttid1 > tid2) std::swap(ttid1, tid2);
3322  for(auto& dc : slc.dontCluster) if(dc.TjIDs[0] == ttid1 && dc.TjIDs[1] == tid2) return true;
3323  } // dc
3324  } // tid1
3325  return false;
3326  } // DontCluster
void swap(art::HLTGlobalStatus &lhs, art::HLTGlobalStatus &rhs)
void tca::DumpShowerPts ( std::string  inFcnLabel,
TCSlice slc,
int  cotID 
)
void tca::DumpShowerPts ( TCSlice slc,
int  cotID 
)

Definition at line 4237 of file TCShower.cxx.

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

4238  {
4239  // Print the shower points to the screen. The user should probably pipe the output to a text file
4240  // then grep this file for the character string PTS which is piped to a text file which can then be
4241  // imported into Excel, etc
4242  // Finds the charge at the start of a shower
4243  if(cotID > (int)slc.cots.size()) return;
4244 
4245  ShowerStruct& ss = slc.cots[cotID - 1];
4246  if(ss.ID == 0) return;
4247  if(ss.TjIDs.empty()) return;
4248  std::cout<<"PTS Pos0 Pos1 RPos0 RPos1 Chg TID\n";
4249  for(auto& pt : ss.ShPts) {
4250  std::cout<<"PTS "<<std::fixed<<std::setprecision(1)<<pt.Pos[0]<<" "<<pt.Pos[1]<<" "<<pt.RotPos[0]<<" "<<pt.RotPos[1];
4251  std::cout<<" "<<(int)pt.Chg<<" "<<pt.TID;
4252  std::cout<<"\n";
4253  }
4254 
4255  } // DumpShowerPts
Float_t ss
Definition: plot.C:23
TMarker * pt
Definition: egs.C:25
void tca::DumpTj ( )

Definition at line 4728 of file Utils.cxx.

References tca::TCEvent::allHits, debug, evt, kKilled, slices, tcc, util::flags::to_string(), tca::TCConfig::unitsPerTick, and tca::DebugStuff::WorkID.

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

4729  {
4730  // Dump all of the points in a trajectory to the output in a form that can
4731  // be imported by another application, e.g. Excel
4732  // Search for the trajectory with the specified WorkID or Unique ID
4733 
4734  for(auto& slc : slices) {
4735  for(auto& tj : slc.tjs) {
4736  if(tj.AlgMod[kKilled]) continue;
4737  if(tj.WorkID != debug.WorkID && tj.UID !=debug.WorkID) continue;
4738  // print a header
4739  std::ofstream outfile;
4740  std::string fname = "tcdump" + std::to_string(tj.UID) + ".csv";
4741  outfile.open(fname,std::ios::out | std::ios::trunc);
4742  outfile<<"Dump trajectory T"<<tj.UID<<" WorkID "<<tj.WorkID;
4743  outfile<<" ChgRMS "<<std::setprecision(2)<<tj.ChgRMS;
4744  outfile<<"\n";
4745  outfile<<"Wire, Chg T"<<tj.UID<<", totChg, Tick, Delta, NTPsFit, Ang, TPErr\n";
4746  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
4747  auto& tp = tj.Pts[ipt];
4748  outfile<<std::fixed;
4749  outfile<<std::setprecision(0)<<std::nearbyint(tp.Pos[0]);
4750  outfile<<","<<(int)tp.Chg;
4751  // total charge near the TP
4752  float totChg = 0;
4753  for(auto iht : tp.Hits) {
4754  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
4755  totChg += hit.Integral();
4756  }
4757  outfile<<","<<(int)totChg;
4758  outfile<<","<<std::setprecision(0)<<std::nearbyint(tp.Pos[1]/tcc.unitsPerTick);
4759  outfile<<","<<std::setprecision(2)<<tp.Delta;
4760  outfile<<","<<tp.NTPsFit;
4761  outfile<<","<<std::setprecision(2)<<tp.Ang;
4762  outfile<<","<<std::setprecision(2)<<sqrt(tp.HitPosErr2);
4763  outfile<<"\n";
4764  } // ipt
4765  outfile.close();
4766  std::cout<<"Points on T"<<tj.UID<<" dumped to "<<fname<<"\n";
4767  return;
4768  } // tj
4769  } // slc
4770 
4771  } // DumpTj
TCConfig tcc
Definition: DataStructs.cxx:6
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
int WorkID
Select the StartWorkID for debugging.
Definition: DebugStruct.h:26
DebugStuff debug
Definition: DebugStruct.cxx:4
std::vector< TCSlice > slices
Definition: DataStructs.cxx:10
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
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
float tca::ElectronLikelihood ( TCSlice slc,
Trajectory tj,
float &  asym 
)

Definition at line 2679 of file Utils.cxx.

References tca::Trajectory::ChgRMS, tca::Trajectory::EndPt, kBragg, NumPtsWithCharge(), tca::Trajectory::StopFlag, and TjDeltaRMS().

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

2680  {
2681  // returns a number between 0 (not electron-like) and 1 (electron-like)
2682  if(NumPtsWithCharge(slc, tj, false) < 8) return -1;
2683  if(tj.StopFlag[1][kBragg]) return 0;
2684 
2685  unsigned short midPt = 0.5 * (tj.EndPt[0] + tj.EndPt[1]);
2686  double rms0 = 0, rms1 = 0;
2687  unsigned short cnt;
2688  TjDeltaRMS(slc, tj, tj.EndPt[0], midPt, rms0, cnt);
2689  TjDeltaRMS(slc, tj, midPt, tj.EndPt[1], rms1, cnt);
2690  asym = std::abs(rms0 - rms1) / (rms0 + rms1);
2691  float chgFact = (tj.ChgRMS - 0.1) * 5;
2692  float elh = 5 * asym * chgFact;
2693  if(elh > 1) elh = 1;
2694  return elh;
2695  } // ElectronLikelihood
void TjDeltaRMS(TCSlice &slc, Trajectory &tj, unsigned short firstPt, unsigned short lastPt, double &rms, unsigned short &cnt)
Definition: Utils.cxx:3029
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:1871
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
void tca::EndMerge ( TCSlice slc,
CTP_t  inCTP,
bool  lastPass 
)

Definition at line 3464 of file StepUtils.cxx.

References tca::TrajPoint::Ang, tca::TrajPoint::AngleCode, tca::TrajPoint::AveChg, tca::TCConfig::chargeCuts, ChgFracNearPos(), ChkVxTjs(), CompatibleMerge(), tca::DebugStuff::CTP, tca::VtxStore::CTP, tca::TCConfig::dbgMrg, tca::TCConfig::dbgSlc, debug, DeltaAngle(), FitTraj(), FitVertex(), tca::VtxStore::ID, kBragg, kFixed, tca::TCConfig::kinkCuts, kKilled, kMerge, kShowerLike, kStepDir, kStiffEl, MakeBareTrajPoint(), max, MCSThetaRMS(), MergeAndStore(), min, tca::TCConfig::modes, tca::TrajPoint::NTPsFit, tca::VtxStore::NTraj, NumPtsWithCharge(), OverlapFraction(), tca::VtxStore::Pass, PointTrajDOCA(), tca::VtxStore::Pos, tca::TrajPoint::Pos, PosSep(), PosSep2(), PrintPos(), tca::TCConfig::qualityCuts, ReverseTraj(), SetVx2Score(), SignalBetween(), slices, tca::VtxStore::Stat, StoreVertex(), tcc, tca::TCSlice::tjs, tca::VtxStore::Topo, TrajIntersection(), TrajLength(), TrajPointSeparation(), TrajTrajDOCA(), tca::TCConfig::unitsPerTick, tca::TCConfig::useAlg, tca::TCConfig::vtx2DCuts, and tca::TCSlice::vtxs.

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

3465  {
3466  // Merges trajectories end-to-end or makes vertices. Does a more careful check on the last pass
3467 
3468  if(slc.tjs.size() < 2) return;
3469  if(!tcc.useAlg[kMerge]) return;
3470 
3471  bool prt = (tcc.dbgMrg && tcc.dbgSlc && inCTP == debug.CTP);
3472  if(prt) mf::LogVerbatim("TC")<<"inside EndMerge slice "<<slices.size()-1<<" inCTP "<<inCTP<<" nTjs "<<slc.tjs.size()<<" lastPass? "<<lastPass;
3473 
3474  // Ensure that all tjs are in the same order
3475  short tccStepDir = 1;
3476  if(!tcc.modes[kStepDir]) tccStepDir = -1;
3477  for(auto& tj : slc.tjs) {
3478  if(tj.AlgMod[kKilled]) continue;
3479  if(tj.CTP != inCTP) continue;
3480  if(tj.StepDir != tccStepDir) ReverseTraj(slc, tj);
3481  } // tj
3482 
3483  unsigned short maxShortTjLen = tcc.vtx2DCuts[0];
3484 
3485  // temp vector for checking the fraction of hits near a merge point
3486  std::vector<int> tjlist(2);
3487 
3488  float minChgRMS = 0.5 * (tcc.chargeCuts[1] + tcc.chargeCuts[2]);
3489 
3490  // iterate whenever a merge occurs since tjs will change. This is not necessary
3491  // when a vertex is created however.
3492  bool iterate = true;
3493  while(iterate) {
3494  iterate = false;
3495  for(unsigned int it1 = 0; it1 < slc.tjs.size(); ++it1) {
3496  auto& tj1 = slc.tjs[it1];
3497  if(tj1.AlgMod[kKilled]) continue;
3498  if(tj1.CTP != inCTP) continue;
3499  // don't try to merge high energy electrons
3500  if(tj1.PDGCode == 111) continue;
3501  for(unsigned short end1 = 0; end1 < 2; ++end1) {
3502  // no merge if there is a vertex at the end
3503  if(tj1.VtxID[end1] > 0) continue;
3504  // make a copy of tp1 so we can mess with it
3505  TrajPoint tp1 = tj1.Pts[tj1.EndPt[end1]];
3506  // do a local fit on the lastpass only using the last 3 points
3507  if(lastPass && tp1.NTPsFit > 3) {
3508  // make a local copy of the tj
3509  auto ttj = slc.tjs[it1];
3510  auto& lastTP = ttj.Pts[ttj.EndPt[end1]];
3511  // fit the last 3 points
3512  lastTP.NTPsFit = 3;
3513  FitTraj(slc, ttj);
3514  tp1 = ttj.Pts[ttj.EndPt[end1]];
3515  } // last pass
3516  bool isVLA = (tp1.AngleCode == 2);
3517  float bestFOM = 5;
3518  if(isVLA) bestFOM = 20;
3519  float bestDOCA;
3520  unsigned int imbest = INT_MAX;
3521  for(unsigned int it2 = 0; it2 < slc.tjs.size(); ++it2) {
3522  if(it1 == it2) continue;
3523  auto& tj2 = slc.tjs[it2];
3524  // check for consistent direction
3525  if(tj1.StepDir != tj2.StepDir) continue;
3526  if(tj2.AlgMod[kKilled]) continue;
3527  if(tj2.CTP != inCTP) continue;
3528  // don't try to merge high energy electrons
3529  if(tj2.PDGCode == 111) continue;
3530  float olf = OverlapFraction(slc, tj1, tj2);
3531  if(olf > 0.25) continue;
3532  unsigned short end2 = 1 - end1;
3533  // check for a vertex at this end
3534  if(tj2.VtxID[end2] > 0) continue;
3535  TrajPoint& tp2 = tj2.Pts[tj2.EndPt[end2]];
3536  TrajPoint& tp2OtherEnd = tj2.Pts[tj2.EndPt[end1]];
3537  // ensure that the other end isn't closer
3538  if(std::abs(tp2OtherEnd.Pos[0] - tp1.Pos[0]) < std::abs(tp2.Pos[0] - tp1.Pos[0])) continue;
3539  // ensure that the order is correct
3540  if(tj1.StepDir > 0) {
3541  if(tp2.Pos[0] < tp1.Pos[0] - 2) continue;
3542  } else {
3543  if(tp2.Pos[0] > tp1.Pos[0] + 2) continue;
3544  }
3545  // ensure that there is a signal on most of the wires between these points
3546  if(!SignalBetween(slc, tp1, tp2, 0.8)) {
3547  continue;
3548  }
3549  // Find the distance of closest approach for small angle merging
3550  // Inflate the doca cut if we are bridging a block of dead wires
3551  float dang = DeltaAngle(tp1.Ang, tp2.Ang);
3552  float doca = 15;
3553  if(isVLA) {
3554  // compare the minimum separation between Large Angle trajectories using a generous cut
3555  unsigned short ipt1, ipt2;
3556  TrajTrajDOCA(slc, tj1, tj2, ipt1, ipt2, doca);
3557  // if(prt) mf::LogVerbatim("TC")<<" isVLA check ipt1 "<<ipt1<<" ipt2 "<<ipt2<<" doca "<<doca;
3558  } else {
3559  // small angle
3560  doca = PointTrajDOCA(slc, tp1.Pos[0], tp1.Pos[1], tp2);
3561  }
3562  float fom = dang * doca;
3563  if(fom < bestFOM) {
3564  bestFOM = fom;
3565  bestDOCA = doca;
3566  imbest = it2;
3567  }
3568  } // it2
3569  // No merge/vertex candidates
3570  if(imbest == INT_MAX) continue;
3571 
3572  // Make angle adjustments to tp1.
3573  unsigned int it2 = imbest;
3574  auto& tj2 = slc.tjs[imbest];
3575  unsigned short end2 = 1 - end1;
3576  bool loMCSMom = (tj1.MCSMom + tj2.MCSMom) < 150;
3577  // Don't use the angle at the end Pt for high momentum long trajectories in case there is a little kink at the end
3578  if(tj1.Pts.size() > 50 && tj1.MCSMom > 100) {
3579  if(end1 == 0) {
3580  tp1.Ang = tj1.Pts[tj1.EndPt[0] + 2].Ang;
3581  } else {
3582  tp1.Ang = tj1.Pts[tj1.EndPt[1] - 2].Ang;
3583  }
3584  } else if(loMCSMom) {
3585  // Low momentum - calculate the angle using the two Pts at the end
3586  unsigned short pt1, pt2;
3587  if(end1 == 0) {
3588  pt1 = tj1.EndPt[0];
3589  pt2 = pt1 + 1;
3590  } else {
3591  pt2 = tj1.EndPt[1];
3592  pt1 = pt2 - 1;
3593  }
3594  TrajPoint tpdir;
3595  if(MakeBareTrajPoint(slc, tj1.Pts[pt1], tj1.Pts[pt2], tpdir)) tp1.Ang = tpdir.Ang;
3596  } // low MCSMom
3597  // Now do the same for tj2
3598  TrajPoint tp2 = tj2.Pts[tj2.EndPt[end2]];
3599  if(tj2.Pts.size() > 50 && tj2.MCSMom > 100) {
3600  if(end1 == 0) {
3601  tp2.Ang = tj2.Pts[tj2.EndPt[0] + 2].Ang;
3602  } else {
3603  tp2.Ang = tj2.Pts[tj2.EndPt[1] - 2].Ang;
3604  }
3605  } else if(loMCSMom) {
3606  // Low momentum - calculate the angle using the two Pts at the end
3607  unsigned short pt1, pt2;
3608  if(end2 == 0) {
3609  pt1 = tj2.EndPt[0];
3610  pt2 = pt1 + 1;
3611  } else {
3612  pt2 = tj2.EndPt[1];
3613  pt1 = pt2 - 1;
3614  }
3615  TrajPoint tpdir;
3616  if(MakeBareTrajPoint(slc, tj2.Pts[pt1], tj2.Pts[pt2], tpdir)) tp2.Ang = tpdir.Ang;
3617  } // low MCSMom
3618 
3619  if(!isVLA && !SignalBetween(slc, tp1, tp2, 0.99)) continue;
3620 
3621  // decide whether to merge or make a vertex
3622  float dang = DeltaAngle(tp1.Ang, tp2.Ang);
3623  float sep = PosSep(tp1.Pos, tp2.Pos);
3624 
3625  float dangCut;
3626  float docaCut;
3627  float chgPull = 0;
3628  if(tp1.AveChg > tp2.AveChg) {
3629  chgPull = (tp1.AveChg / tp2.AveChg - 1) / minChgRMS;
3630  } else {
3631  chgPull = (tp2.AveChg / tp1.AveChg - 1) / minChgRMS;
3632  }
3633  if(loMCSMom) {
3634  // increase dangCut dramatically for low MCSMom tjs
3635  dangCut = 1.0;
3636  // and the doca cut
3637  docaCut = 2;
3638  } else {
3639  // do a more careful calculation of the angle cut
3640  unsigned short e0 = tj1.EndPt[0];
3641  unsigned short e1 = tj1.EndPt[1];
3642  float tj1len = TrajPointSeparation(tj1.Pts[e0], tj1.Pts[e1]);
3643  float thetaRMS1 = MCSThetaRMS(slc, tj1);
3644  // calculate (thetaRMS / sqrt(length) )^2
3645  thetaRMS1 *= thetaRMS1 / tj1len;
3646  // and now tj2
3647  e0 = tj2.EndPt[0];
3648  e1 = tj2.EndPt[1];
3649  float tj2len = TrajPointSeparation(tj2.Pts[e0], tj2.Pts[e1]);
3650  float thetaRMS2 = MCSThetaRMS(slc, tj2);
3651  thetaRMS2 *= thetaRMS2 / tj2len;
3652  float dangErr = 0.5 * sqrt(thetaRMS1 + thetaRMS2);
3653  dangCut = tcc.kinkCuts[0] + tcc.kinkCuts[1] * dangErr;
3654  docaCut = 1;
3655  if(isVLA) docaCut = 15;
3656  }
3657 
3658  // open up the cuts on the last pass
3659  float chgFracCut = tcc.vtx2DCuts[8];
3660  float chgPullCut = tcc.chargeCuts[0];
3661  if(lastPass) {
3662  docaCut *= 2;
3663  chgFracCut *= 0.5;
3664  chgPullCut *= 1.5;
3665  }
3666 
3667  // check the merge cuts. Start with doca and dang requirements
3668  bool doMerge = bestDOCA < docaCut && dang < dangCut;
3669  bool showerTjs = tj1.PDGCode == 11 || tj2.PDGCode == 11;
3670  bool hiMCSMom = tj1.MCSMom > 200 || tj2.MCSMom > 200;
3671  // add a charge similarity requirement if not shower-like or low momentum or not LA
3672  if(doMerge && !showerTjs && hiMCSMom && chgPull > tcc.chargeCuts[0] && !isVLA) doMerge = false;
3673  // ignore the charge pull cut if both are high momentum and dang is really small
3674  if(!doMerge && tj1.MCSMom > 900 && tj2.MCSMom > 900 && dang < 0.1 && bestDOCA < docaCut) doMerge = true;
3675 
3676  // do not merge if chgPull is really high
3677  if(doMerge && chgPull > 2 * chgPullCut) doMerge = false;
3678 
3679  if(doMerge) {
3680  if(lastPass) {
3681  // last pass cuts are looser but ensure that the tj after merging meets the quality cut
3682  float npwc = NumPtsWithCharge(slc, tj1, true) + NumPtsWithCharge(slc, tj2, true);
3683  auto& tp1OtherEnd = tj1.Pts[tj1.EndPt[1 - end1]];
3684  auto& tp2OtherEnd = tj2.Pts[tj2.EndPt[1 - end2]];
3685  float nwires = std::abs(tp1OtherEnd.Pos[0] - tp2OtherEnd.Pos[0]);
3686  if(nwires == 0) nwires = 1;
3687  float hitFrac = npwc / nwires;
3688  doMerge = (hitFrac > tcc.qualityCuts[0]);
3689  // if(prt) mf::LogVerbatim("TC")<<" lastPass merged Tj from "<<PrintPos(slc, tp1OtherEnd.Pos)<<" to "<<PrintPos(slc, tp2OtherEnd.Pos)<<" hitfrac "<<hitFrac<<" cut "<<tcc.qualityCuts[0];
3690  } else {
3691  // don't merge if the gap between them is longer than the length of the shortest Tj
3692  float len1 = TrajLength(slc.tjs[it1]);
3693  float len2 = TrajLength(slc.tjs[it2]);
3694  if(len1 < len2) {
3695  if(sep > len1) doMerge = false;
3696  } else {
3697  if(sep > len2) doMerge = false;
3698  }
3699  // if(prt) mf::LogVerbatim("TC")<<" merge check sep "<<sep<<" len1 "<<len1<<" len2 "<<len2<<" Merge? "<<doMerge;
3700  } // not lastPass
3701  } // doMerge
3702 
3703  // Require a large charge fraction near a merge point
3704  tjlist[0] = slc.tjs[it1].ID;
3705  tjlist[1] = slc.tjs[it2].ID;
3706  float chgFrac = ChgFracNearPos(slc, tp1.Pos, tjlist);
3707  if(doMerge && bestDOCA > 1 && chgFrac < chgFracCut) doMerge = false;
3708 
3709  // don't merge if a Bragg peak exists. A vertex should be made instead
3710  if(doMerge && (tj1.StopFlag[end1][kBragg] || tj2.StopFlag[end2][kBragg])) doMerge = false;
3711 
3712  // Check the MCSMom asymmetry and don't merge if it is higher than the user-specified cut
3713  float momAsym = std::abs(tj1.MCSMom - tj2.MCSMom) / (float)(tj1.MCSMom + tj2.MCSMom);
3714  if(doMerge && momAsym > tcc.vtx2DCuts[9]) doMerge = false;
3715 
3716  if(prt) {
3717  mf::LogVerbatim myprt("TC");
3718  myprt<<"EM: T"<<slc.tjs[it1].ID<<"_"<<end1<<" - T"<<slc.tjs[it2].ID<<"_"<<end2<<" tp1-tp2 "<<PrintPos(slc, tp1)<<"-"<<PrintPos(slc, tp2);
3719  myprt<<" ShowerLike? "<<slc.tjs[it1].AlgMod[kShowerLike]<<" "<<slc.tjs[it2].AlgMod[kShowerLike];
3720  myprt<<" bestFOM "<<std::fixed<<std::setprecision(2)<<bestFOM;
3721  myprt<<" bestDOCA "<<std::setprecision(1)<<bestDOCA;
3722  myprt<<" cut "<<docaCut<<" isVLA? "<<isVLA;
3723  myprt<<" dang "<<std::setprecision(2)<<dang<<" dangCut "<<dangCut;
3724  myprt<<" chgPull "<<std::setprecision(1)<<chgPull<<" Cut "<<chgPullCut;
3725  myprt<<" chgFrac "<<std::setprecision(2)<<chgFrac;
3726  myprt<<" momAsym "<<momAsym;
3727  myprt<<" lastPass? "<<lastPass;
3728  myprt<<" doMerge? "<<doMerge;
3729  }
3730 
3731  if(bestDOCA > docaCut) continue;
3732 
3733  if(doMerge) {
3734  if(prt) mf::LogVerbatim("TC")<<" Merge ";
3735  bool didMerge = false;
3736  if(end1 == 1) {
3737  didMerge = MergeAndStore(slc, it1, it2, tcc.dbgMrg);
3738  } else {
3739  didMerge = MergeAndStore(slc, it2, it1, tcc.dbgMrg);
3740  }
3741  if(didMerge) {
3742  // Set the end merge flag for the killed trajectories to aid tracing merges
3743  tj1.AlgMod[kMerge] = true;
3744  tj2.AlgMod[kMerge] = true;
3745  iterate = true;
3746  } // Merge and store successfull
3747  else {
3748  if(prt) mf::LogVerbatim("TC")<<" MergeAndStore failed ";
3749  }
3750  } else {
3751  // create a vertex instead if it passes the vertex cuts
3752  VtxStore aVtx;
3753  aVtx.CTP = slc.tjs[it1].CTP;
3754  aVtx.ID = slc.vtxs.size() + 1;
3755  // keep it simple if tp1 and tp2 are very close or if the angle between them
3756  // is small
3757  if(PosSep(tp1.Pos, tp2.Pos) < 3 || dang < 0.1) {
3758  aVtx.Pos[0] = 0.5 * (tp1.Pos[0] + tp2.Pos[0]);
3759  aVtx.Pos[1] = 0.5 * (tp1.Pos[1] + tp2.Pos[1]);
3760  aVtx.Stat[kFixed] = true;
3761  } else {
3762  // Tps not so close
3763  // Dec 11, 2017. Require small separation in EndMerge.
3764  // float sepCut = tcc.vtx2DCuts[2];
3765  float sepCut = tcc.vtx2DCuts[1];
3766  bool tj1Short = (slc.tjs[it1].EndPt[1] - slc.tjs[it1].EndPt[0] < maxShortTjLen);
3767  bool tj2Short = (slc.tjs[it2].EndPt[1] - slc.tjs[it2].EndPt[0] < maxShortTjLen);
3768  if(tj1Short || tj2Short) sepCut = tcc.vtx2DCuts[1];
3769  TrajIntersection(tp1, tp2, aVtx.Pos);
3770  float dw = aVtx.Pos[0] - tp1.Pos[0];
3771  if(std::abs(dw) > sepCut) continue;
3772  float dt = aVtx.Pos[1] - tp1.Pos[1];
3773  if(std::abs(dt) > sepCut) continue;
3774  dw = aVtx.Pos[0] - tp2.Pos[0];
3775  if(std::abs(dw) > sepCut) continue;
3776  dt = aVtx.Pos[1] - tp2.Pos[1];
3777  if(std::abs(dt) > sepCut) continue;
3778  // ensure that the vertex is not closer to the other end if the tj is short
3779  if(tj1Short) {
3780  TrajPoint otp1 = slc.tjs[it1].Pts[slc.tjs[it1].EndPt[1-end1]];
3781  if(PosSep2(otp1.Pos, aVtx.Pos) < PosSep2(tp1.Pos, aVtx.Pos)) continue;
3782  }
3783  if(tj2Short) {
3784  TrajPoint otp2 = slc.tjs[it2].Pts[slc.tjs[it2].EndPt[1-end2]];
3785  if(PosSep2(otp2.Pos, aVtx.Pos) < PosSep2(tp2.Pos, aVtx.Pos)) continue;
3786  }
3787  // we expect the vertex to be between tp1 and tp2
3788  if(aVtx.Pos[0] < tp1.Pos[0] && aVtx.Pos[0] < tp2.Pos[0]) {
3789  aVtx.Pos[0] = std::min(tp1.Pos[0], tp2.Pos[0]);
3790  aVtx.Stat[kFixed] = true;
3791  }
3792  if(aVtx.Pos[0] > tp1.Pos[0] && aVtx.Pos[0] > tp2.Pos[0]) {
3793  aVtx.Pos[0] = std::max(tp1.Pos[0], tp2.Pos[0]);
3794  aVtx.Stat[kFixed] = true;
3795  }
3796  } // Tps not so close
3797  // We got this far. Try a vertex fit to ensure that the errors are reasonable
3798  slc.tjs[it1].VtxID[end1] = aVtx.ID;
3799  slc.tjs[it2].VtxID[end2] = aVtx.ID;
3800  // save the position
3801  // do a fit
3802  if(!aVtx.Stat[kFixed] && !FitVertex(slc, aVtx, tcc.dbgMrg)) {
3803  // back out
3804  slc.tjs[it1].VtxID[end1] = 0;
3805  slc.tjs[it2].VtxID[end2] = 0;
3806  if(prt) mf::LogVerbatim("TC")<<" Vertex fit failed ";
3807  continue;
3808  }
3809  aVtx.NTraj = 2;
3810  aVtx.Pass = slc.tjs[it1].Pass;
3811  aVtx.Topo = end1 + end2;
3812  tj1.AlgMod[kMerge] = true;
3813  tj2.AlgMod[kMerge] = true;
3814  // Set pion-like PDGCodes
3815  if(!tj1.Strategy[kStiffEl] && !tj2.Strategy[kStiffEl]) {
3816  if(tj1.StopFlag[end1][kBragg] && !tj2.StopFlag[end2][kBragg]) tj1.PDGCode = 211;
3817  if(tj2.StopFlag[end2][kBragg] && !tj1.StopFlag[end1][kBragg]) tj2.PDGCode = 211;
3818  }
3819  if(!StoreVertex(slc, aVtx)) continue;
3820  SetVx2Score(slc);
3821  if(prt) {
3822  auto& newVx = slc.vtxs[slc.vtxs.size() - 1];
3823  mf::LogVerbatim("TC")<<" New 2V"<<newVx.ID<<" at "<<(int)newVx.Pos[0]<<":"<<(int)(newVx.Pos[1]/tcc.unitsPerTick)<<" Score "<<newVx.Score;
3824  }
3825  // check the score and kill it if it is below the cut
3826  auto& newVx2 = slc.vtxs[slc.vtxs.size() - 1];
3827  if(newVx2.Score < tcc.vtx2DCuts[7] && CompatibleMerge(slc, tj1, tj2, tcc.dbgMrg)) {
3828  slc.tjs[it1].VtxID[end1] = 0;
3829  slc.tjs[it2].VtxID[end2] = 0;
3830  slc.vtxs.pop_back();
3831  bool didMerge = false;
3832  if(end1 == 1) {
3833  didMerge = MergeAndStore(slc, it1, it2, tcc.dbgMrg);
3834  } else {
3835  didMerge = MergeAndStore(slc, it2, it1, tcc.dbgMrg);
3836  }
3837  if(didMerge) {
3838  // Set the end merge flag for the killed trajectories to aid tracing merges
3839  tj1.AlgMod[kMerge] = true;
3840  tj1.AlgMod[kMerge] = true;
3841  iterate = true;
3842  } // Merge and store successfull
3843  else {
3844  if(prt) mf::LogVerbatim("TC")<<" MergeAndStore failed ";
3845  }
3846  }
3847  } // create a vertex
3848  if(tj1.AlgMod[kKilled]) break;
3849  } // end1
3850  } // it1
3851  } // iterate
3852 
3853  ChkVxTjs(slc, inCTP, tcc.dbgMrg);
3854  /*
3855  // Do some checking in debug mode
3856  if(tcc.modes[kDebug] && lastPass) {
3857  for(unsigned short it1 = 0; it1 < slc.tjs.size() - 1; ++it1) {
3858  auto& tj1 = slc.tjs[it1];
3859  if(tj1.CTP != inCTP) continue;
3860  if(tj1.AlgMod[kKilled]) continue;
3861  for(unsigned short end1 = 0; end1 < 2; ++end1) {
3862  unsigned short end2 = 1 - end1;
3863  auto& tp1 = tj1.Pts[tj1.EndPt[end1]];
3864  for(unsigned short it2 = it1 + 1; it2 < slc.tjs.size(); ++it2) {
3865  auto& tj2 = slc.tjs[it2];
3866  if(tj2.CTP != inCTP) continue;
3867  if(tj2.AlgMod[kKilled]) continue;
3868  auto& tp2 = tj2.Pts[tj2.EndPt[end2]];
3869  float sep = PosSep2(tp1.HitPos, tp2.HitPos);
3870  if(sep < 2.5) {
3871  if(tj1.VtxID[end1] == 0 && tj2.VtxID[end2] == 0) {
3872  std::cout<<"Tjs "<<tj1.ID<<" and "<<tj2.ID<<" are close at Pos "<<tj1.CTP<<":"<<PrintPos(slc, tp1.HitPos)<<" "<<tj2.CTP<<":"<<PrintPos(slc, tp2.HitPos)<<" with no merge or vertex\n";
3873  } else if(tj1.VtxID[end1] != tj2.VtxID[end2]) {
3874  std::cout<<"Tjs "<<tj1.ID<<" and "<<tj2.ID<<" are close at Pos "<<tj1.CTP<<":"<<PrintPos(slc, tp1.HitPos);
3875  std::cout<<" but have different vertex IDs "<<tj1.VtxID[end1]<<" != "<<tj2.VtxID[end2];
3876  std::cout<<"\n";
3877  }
3878  } // close points
3879  } // it2
3880  } // end1
3881  } // it1
3882  } // debug mode
3883  */
3884  } // EndMerge
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeBareTrajPoint(TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:3581
std::vector< float > kinkCuts
kink angle, nPts fit, (alternate) kink angle significance
Definition: DataStructs.h:475
bool FitVertex(TCSlice &slc, VtxStore &vx, bool prt)
Definition: TCVertex.cxx:2131
std::vector< float > qualityCuts
Min points/wire, min consecutive pts after a gap.
Definition: DataStructs.h:479
TCConfig tcc
Definition: DataStructs.cxx:6
vertex position fixed manually - no fitting done
Definition: DataStructs.h:74
step from US -> DS (true) or DS -> US (false)
Definition: DataStructs.h:447
float TrajPointSeparation(TrajPoint &tp1, TrajPoint &tp2)
Definition: Utils.cxx:2368
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1636
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:507
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:2093
bool TrajTrajDOCA(TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2175
Int_t max
Definition: plot.C:27
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
DebugStuff debug
Definition: DebugStruct.cxx:4
bool SignalBetween(TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2, const float &MinWireSignalFraction)
Definition: Utils.cxx:1671
float TrajLength(Trajectory &tj)
Definition: Utils.cxx:2337
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1660
void FitTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:753
void ReverseTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:2751
std::vector< TCSlice > slices
Definition: DataStructs.cxx:10
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
std::vector< float > chargeCuts
Definition: DataStructs.h:478
bool MergeAndStore(TCSlice &slc, unsigned int itj1, unsigned int itj2, bool doPrt)
Definition: Utils.cxx:4095
float ChgFracNearPos(TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2698
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
Definition: Utils.cxx:2299
float MCSThetaRMS(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:2984
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
Int_t min
Definition: plot.C:26
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
float OverlapFraction(TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2)
Definition: Utils.cxx:664
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
use the stiff electron strategy
Definition: DataStructs.h:418
void SetVx2Score(TCSlice &slc)
Definition: TCVertex.cxx:2504
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:466
void ChkVxTjs(TCSlice &slc, const CTP_t &inCTP, bool prt)
Definition: TCVertex.cxx:874
CTP_t CTP
set to an invalid CTP
Definition: DebugStruct.h:22
bool CompatibleMerge(TCSlice &slc, std::vector< int > &tjIDs, bool prt)
Definition: Utils.cxx:534
float tca::ExpectedHitsRMS ( TCSlice slc,
const TrajPoint tp 
)

Definition at line 1802 of file Utils.cxx.

References tca::TCEvent::aveHitRMS, tca::TrajPoint::CTP, DecodeCTP(), tca::TrajPoint::Dir, evt, geo::PlaneID::Plane, tcc, and tca::TCConfig::unitsPerTick.

Referenced by AddHits(), FindUseHits(), and StartTraj().

1803  {
1804  // returns the expected RMS of hits for the trajectory point in ticks
1805  if(std::abs(tp.Dir[0]) > 0.001) {
1806  geo::PlaneID planeID = DecodeCTP(tp.CTP);
1807  return 1.5 * evt.aveHitRMS[planeID.Plane] + 2 * std::abs(tp.Dir[1]/tp.Dir[0])/tcc.unitsPerTick;
1808  } else {
1809  return 500;
1810  }
1811  } // ExpectedHitsRMS
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
std::vector< float > aveHitRMS
average RMS of an isolated hit
Definition: DataStructs.h:541
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
TCEvent evt
Definition: DataStructs.cxx:5
unsigned short tca::FarEnd ( TCSlice slc,
const PFPStruct pfp,
const Point3_t pos 
)

Definition at line 3032 of file PFPUtils.cxx.

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

Referenced by ChkVxTjs(), DotProd(), FindParent(), MergeSubShowersTj(), ParentFOM(), Reconcile3D(), SetParent(), TagShowerLike(), and UpdateShower().

3033  {
3034  // Returns the end (0 or 1) of the pfp that is furthest away from the position pos
3035  if(pfp.ID == 0) return 0;
3036  if(PosSep2(pfp.XYZ[1], pos) > PosSep2(pfp.XYZ[0], pos)) return 1;
3037  return 0;
3038  } // FarEnd
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1660
unsigned short tca::FarEnd ( TCSlice slc,
const Trajectory tj,
const Point2_t pos 
)

Definition at line 3646 of file Utils.cxx.

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

3647  {
3648  // Returns the end (0 or 1) of the Tj that is furthest away from the position pos
3649  if(tj.ID == 0) return 0;
3650  if(PosSep2(tj.Pts[tj.EndPt[1]].Pos, pos) > PosSep2(tj.Pts[tj.EndPt[0]].Pos, pos)) return 1;
3651  return 0;
3652  } // FarEnd
float PosSep2(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2359
void tca::FilldEdx ( TCSlice slc,
PFPStruct pfp 
)

Definition at line 1683 of file PFPUtils.cxx.

References tca::PFPStruct::BestPlane, tca::TCConfig::caloAlg, tca::Trajectory::ChgRMS, tca::Trajectory::CTP, DecodeCTP(), tca::Trajectory::dEdx, tca::PFPStruct::dEdx, calo::CalorimetryAlg::dEdx_AREA(), tca::PFPStruct::dEdxErr, tca::PFPStruct::Dir, evd::details::end(), tca::Trajectory::EndPt, tca::TCConfig::geom, tca::PFPStruct::ID, tca::TCSlice::nPlanes, tca::PFPStruct::PDGCode, geo::PlaneID::Plane, geo::GeometryCore::Plane(), tca::Trajectory::Pts, tcc, geo::PlaneGeo::ThetaZ(), tca::PFPStruct::TjIDs, tca::TCSlice::tjs, tca::TCConfig::unitsPerTick, and geo::GeometryCore::WirePitch().

Referenced by DotProd(), and StorePFP().

1684  {
1685  // Fills the dEdX vector in the match struct. This function should be called after the
1686  // matched trajectory points are ordered so that dE/dx is calculated at the start of the PFParticle
1687  if(pfp.ID == 0) return;
1688  // error check
1689  bool notgood = false;
1690  for(unsigned short end = 0; end < 2; ++end) {
1691  if(pfp.dEdx[end].size() != slc.nPlanes) notgood = true;
1692  if(pfp.dEdxErr[end].size() != slc.nPlanes) notgood = true;
1693  }
1694  if(notgood) {
1695  // if(prt) mf::LogVerbatim("TC")<<"FilldEdx found inconsistent sizes for dEdx\n";
1696  return;
1697  }
1698 
1699  double t0 = 0;
1700 
1701  // don't attempt to find dE/dx at the end of a shower
1702  unsigned short numEnds = 2;
1703  if(pfp.PDGCode == 1111) numEnds = 1;
1704 
1705  unsigned short maxlen = 0;
1706  for(auto tjID : pfp.TjIDs) {
1707 
1708  Trajectory& tj = slc.tjs[tjID - 1];
1709  geo::PlaneID planeID = DecodeCTP(tj.CTP);
1710  double angleToVert = tcc.geom->Plane(planeID).ThetaZ() - 0.5 * ::util::pi<>();
1711  for(unsigned short end = 0; end < numEnds; ++end) {
1712  pfp.dEdx[end][planeID.Plane] = 0;
1713  tj.dEdx[end] = 0;
1714  double cosgamma = std::abs(std::sin(angleToVert) * pfp.Dir[end][1] + std::cos(angleToVert) * pfp.Dir[end][2]);
1715  if(cosgamma == 0) continue;
1716  double dx = tcc.geom->WirePitch(planeID) / cosgamma;
1717  if(dx == 0) continue;
1718  double dQ = tj.Pts[tj.EndPt[end]].AveChg;
1719  if(dQ == 0) continue;
1720  // convert to dQ/dx
1721  dQ /= dx;
1722  double time = tj.Pts[tj.EndPt[end]].Pos[1] / tcc.unitsPerTick;
1723  float dedx = tcc.caloAlg->dEdx_AREA(dQ, time, planeID.Plane, t0);
1724  if(dedx > 999) dedx = -1;
1725  pfp.dEdx[end][planeID.Plane] = dedx;
1726  tj.dEdx[end] = dedx;
1727  // ChgRMS is the fractional error
1728  pfp.dEdxErr[end][planeID.Plane] = dedx * tj.ChgRMS;
1729 
1730  } // end
1731  // Grab the best plane iusing the start f 1 < dE/dx < 50 MeV/cm
1732  if(pfp.dEdx[0][planeID.Plane] > 1 && pfp.dEdx[0][planeID.Plane] < 50) {
1733  if(tj.Pts.size() > maxlen) {
1734  maxlen = tj.Pts.size();
1735  pfp.BestPlane = planeID.Plane;
1736  }
1737  } // valid dE/dx
1738 
1739  } // tj
1740  } // FilldEdX
calo::CalorimetryAlg * caloAlg
Definition: DataStructs.h:495
code to link reconstructed objects back to the MC truth information
PlaneGeo const & Plane(unsigned int const p, unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified wire.
double dEdx_AREA(art::Ptr< recob::Hit > hit, double pitch, double T0=0) const
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
double ThetaZ() const
Angle of the wires from positive z axis; .
Definition: PlaneGeo.cxx:728
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
const geo::GeometryCore * geom
Definition: DataStructs.h:493
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void tca::FilldEdx ( TCSlice slc,
TrajPoint3 tp3 
)

Definition at line 1743 of file PFPUtils.cxx.

References tca::TCEvent::allHits, tca::TCConfig::caloAlg, DecodeCTP(), tca::TrajPoint3::dEdx, calo::CalorimetryAlg::dEdx_AREA(), tca::TrajPoint3::Dir, evt, tca::TCConfig::geom, geo::PlaneID::Plane, geo::GeometryCore::Plane(), tca::TCSlice::slHits, tcc, geo::PlaneGeo::ThetaZ(), tca::TrajPoint3::Tj2Pts, tca::TCSlice::tjs, tca::TCConfig::unitsPerTick, and geo::GeometryCore::WirePitch().

1744  {
1745  // fills the dEdx variables in tp3 (MeV/cm)
1746  tp3.dEdx = 0;
1747  if(tp3.Tj2Pts.empty()) return;
1748  double t0 = 0;
1749  float sum = 0;
1750  float sum2 = 0;
1751  float cnt = 0;
1752  for(auto& tj2pt : tp3.Tj2Pts) {
1753  auto& tp = slc.tjs[tj2pt.id - 1].Pts[tj2pt.ipt];
1754  if(tp.Chg <= 0) continue;
1755  geo::PlaneID planeID = DecodeCTP(tp.CTP);
1756  double angleToVert = tcc.geom->Plane(planeID).ThetaZ() - 0.5 * ::util::pi<>();
1757  double cosgamma = std::abs(std::sin(angleToVert) * tp3.Dir[1] + std::cos(angleToVert) * tp3.Dir[2]);
1758  if(cosgamma == 0) continue;
1759  double dx = tcc.geom->WirePitch(planeID) / cosgamma;
1760  // sum the hit charge
1761  double chg = 0;
1762  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1763  if(!tp.UseHit[ii]) continue;
1764  unsigned int iht = tp.Hits[ii];
1765  chg += (*evt.allHits)[slc.slHits[iht].allHitsIndex].Integral();
1766  }
1767  double dQ = chg / dx;
1768  double time = tp.Pos[1] / tcc.unitsPerTick;
1769  float dedx = tcc.caloAlg->dEdx_AREA(dQ, time, planeID.Plane, t0);
1770  if(dedx > 200) continue;
1771  sum += dedx;
1772  sum2 += dedx * dedx;
1773  ++cnt;
1774  } // tj2pt
1775  if(cnt == 0) return;
1776  tp3.dEdx = sum / cnt;
1777 /*
1778  if(cnt > 1) {
1779  float arg = sum2 - cnt * tp3.dEdx * tp3.dEdx;
1780  if(arg > 0) {
1781  tp3.dEdxErr = sqrt(arg / (cnt - 1));
1782  // convert to error on the mean
1783  tp3.dEdxErr /= sqrt(cnt);
1784  }
1785  } // cnt > 1
1786 */
1787  } // FilldEdx
calo::CalorimetryAlg * caloAlg
Definition: DataStructs.h:495
code to link reconstructed objects back to the MC truth information
PlaneGeo const & Plane(unsigned int const p, unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified wire.
double dEdx_AREA(art::Ptr< recob::Hit > hit, double pitch, double T0=0) const
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
double ThetaZ() const
Angle of the wires from positive z axis; .
Definition: PlaneGeo.cxx:728
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
const geo::GeometryCore * geom
Definition: DataStructs.h:493
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
void tca::FillGaps ( TCSlice slc,
Trajectory tj 
)

Definition at line 2264 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::TCEvent::allHits, tca::TCConfig::chargeCuts, tca::Trajectory::ChgRMS, tca::TCConfig::dbgStp, DefineHitPos(), tca::Trajectory::EndPt, evt, tca::Trajectory::ID, tca::Trajectory::IsGood, tca::TCSlice::isValid, kFillGap, kJunkTj, kNewStpCuts, MakeBareTrajPoint(), MaxHitDelta(), tca::Trajectory::MCSMom, MCSMom(), tca::Trajectory::Pass, PointTrajDOCA(), PrintHit(), PrintPos(), PrintTrajPoint(), tca::Trajectory::Pts, tca::TCSlice::slHits, tca::Trajectory::StepDir, tcc, UnsetUsedHits(), and tca::TCConfig::useAlg.

Referenced by CheckStiffEl(), and CheckTraj().

2265  {
2266  // Fill in any gaps in the trajectory with close hits regardless of charge (well maybe not quite that)
2267 
2268  if(!tcc.useAlg[kFillGap]) return;
2269  if(tj.AlgMod[kJunkTj]) return;
2270 
2271  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"FG: Check Tj "<<tj.ID<<" from "<<PrintPos(slc, tj.Pts[tj.EndPt[0]])<<" to "<<PrintPos(slc, tj.Pts[tj.EndPt[1]]);
2272 
2273  // start with the first point that has charge
2274  short firstPtWithChg = tj.EndPt[0];
2275  bool first = true;
2276  float maxDelta = 1;
2277  // don't let MCSMom suffer too much while filling gaps
2278  short minMCSMom = 0.7 * tj.MCSMom;
2279  while(firstPtWithChg < tj.EndPt[1]) {
2280  short nextPtWithChg = firstPtWithChg + 1;
2281  // find the next point with charge
2282  for(nextPtWithChg = firstPtWithChg + 1; nextPtWithChg < tj.EndPt[1]; ++nextPtWithChg) {
2283  if(tj.Pts[nextPtWithChg].Chg > 0) break;
2284  } // nextPtWithChg
2285  if(nextPtWithChg == firstPtWithChg + 1) {
2286  // the next point has charge
2287  ++firstPtWithChg;
2288  continue;
2289  }
2290  // Found a gap. Require at least two consecutive points with charge after the gap
2291  if(nextPtWithChg < (tj.EndPt[1] - 1) && tj.Pts[nextPtWithChg + 1].Chg == 0) {
2292  firstPtWithChg = nextPtWithChg;
2293  continue;
2294  }
2295  // 10/1/2018 BB This shouldn't be a requirement
2296  // Compare the charge before and after
2297  if(!tcc.useAlg[kNewStpCuts] && tj.Pts[firstPtWithChg].Chg > 0) {
2298  float chgrat = tj.Pts[nextPtWithChg].Chg / tj.Pts[firstPtWithChg].Chg;
2299  if(chgrat < 0.7 || chgrat > 1.4) {
2300  firstPtWithChg = nextPtWithChg;
2301  continue;
2302  }
2303  }
2304 
2305  // Make a bare trajectory point at firstPtWithChg that points to nextPtWithChg
2306  TrajPoint tp;
2307  if(!MakeBareTrajPoint(slc, tj.Pts[firstPtWithChg], tj.Pts[nextPtWithChg], tp)) {
2308  tj.IsGood = false;
2309  return;
2310  }
2311  // Find the maximum delta between hits and the trajectory Pos for all
2312  // hits on this trajectory
2313  if(first) {
2314  maxDelta = 2.5 * MaxHitDelta(slc, tj);
2315  first = false;
2316  } // first
2317  // define a loose charge cut using the average charge at the first point with charge
2318  float maxChg = tj.Pts[firstPtWithChg].AveChg * (1 + 2 * tcc.chargeCuts[0] * tj.ChgRMS);
2319  // Eliminate the charge cut altogether if we are close to an end
2320  if(tj.Pts.size() < 10) {
2321  maxChg = 1E6;
2322  } else {
2323  short chgCutPt = tj.EndPt[0] + 5;
2324  if(firstPtWithChg < chgCutPt) {
2325  // gap is near end 0
2326  maxChg = 1E6;
2327  } else {
2328  // check for gap near end 1
2329  chgCutPt = tj.EndPt[1] - 5;
2330  if(chgCutPt < tj.EndPt[0]) chgCutPt = tj.EndPt[0];
2331  if(nextPtWithChg > chgCutPt) maxChg = 1E6;
2332  }
2333  }
2334 
2335  // fill in the gap
2336  for(unsigned short mpt = firstPtWithChg + 1; mpt < nextPtWithChg; ++mpt) {
2337  if(tj.Pts[mpt].Chg > 0) {
2338  mf::LogWarning("TC")<<"FillGaps coding error: firstPtWithChg "<<firstPtWithChg<<" mpt "<<mpt<<" nextPtWithChg "<<nextPtWithChg;
2339  slc.isValid = false;
2340  return;
2341  }
2342  bool filled = false;
2343  float chg = 0;
2344  for(unsigned short ii = 0; ii < tj.Pts[mpt].Hits.size(); ++ii) {
2345  unsigned int iht = tj.Pts[mpt].Hits[ii];
2346  if(slc.slHits[iht].InTraj > 0) continue;
2347  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2348  float delta = PointTrajDOCA(slc, iht, tp);
2349  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" FG: "<<PrintPos(slc,tj.Pts[mpt])<<" hit "<<PrintHit(slc.slHits[iht])<<" delta "<<delta<<" maxDelta "<<maxDelta<<" Chg "<<hit.Integral()<<" maxChg "<<maxChg;
2350  if(delta > maxDelta) continue;
2351  tj.Pts[mpt].UseHit[ii] = true;
2352  slc.slHits[iht].InTraj = tj.ID;
2353  chg += hit.Integral();
2354  filled = true;
2355  } // ii
2356  if(chg > maxChg || MCSMom(slc, tj) < minMCSMom) {
2357  // don't use these hits after all
2358  UnsetUsedHits(slc, tj.Pts[mpt]);
2359  filled = false;
2360  }
2361  if(filled) {
2362  DefineHitPos(slc, tj.Pts[mpt]);
2363  tj.AlgMod[kFillGap] = true;
2364  if(tcc.dbgStp) {
2365  PrintTrajPoint("FG", slc, mpt, tj.StepDir, tj.Pass, tj.Pts[mpt]);
2366  mf::LogVerbatim("TC")<<"Check MCSMom "<<MCSMom(slc, tj);
2367  }
2368  } // filled
2369  } // mpt
2370  firstPtWithChg = nextPtWithChg;
2371  } // firstPtWithChg
2372 
2373  if(tj.AlgMod[kFillGap]) tj.MCSMom = MCSMom(slc, tj);
2374 
2375  } // FillGaps
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeBareTrajPoint(TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:3581
short MCSMom(TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2914
TCConfig tcc
Definition: DataStructs.cxx:6
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1162
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1840
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:5704
Detector simulation of raw signals on wires.
std::vector< float > chargeCuts
Definition: DataStructs.h:478
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
float MaxHitDelta(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:2734
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
TCEvent evt
Definition: DataStructs.cxx:5
void PrintTrajPoint(std::string someText, TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, TrajPoint const &tp)
Definition: Utils.cxx:5541
void tca::FillmAllTraj ( TCSlice slc)

Definition at line 271 of file PFPUtils.cxx.

References detinfo::DetectorProperties::ConvertTicksToX(), geo::CryostatID::Cryostat, DecodeCTP(), tca::TCConfig::detprop, tca::TCConfig::geom, geo::GeometryCore::HasWire(), kHaloTj, kKilled, kMat3D, kTjHiVx3Score, kUsedHits, tca::TCSlice::mallTraj, tca::TCConfig::match3DCuts, tca::TCSlice::matchVec, NumPtsWithCharge(), geo::PlaneID::Plane, tcc, tca::TCSlice::tjs, geo::TPCID::TPC, tca::TCSlice::TPCID, TPHitsRMSTime(), tca::TCConfig::unitsPerTick, and valIncreasings().

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

272  {
273  // Fills the mallTraj vector with trajectory points in the tpc and sorts
274  // them by increasing X
275  slc.matchVec.clear();
276 
277  int cstat = slc.TPCID.Cryostat;
278  int tpc = slc.TPCID.TPC;
279 
280  // count the number of TPs and clear out any old 3D match flags
281  unsigned int ntp = 0;
282  for(auto& tj : slc.tjs) {
283  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
284  if(tj.ID <= 0) continue;
285  geo::PlaneID planeID = DecodeCTP(tj.CTP);
286  if((int)planeID.Cryostat != cstat) continue;
287  if((int)planeID.TPC != tpc) continue;
288  ntp += NumPtsWithCharge(slc, tj, false);
289  tj.AlgMod[kMat3D] = false;
290  } // tj
291  if(ntp < 2) return;
292 
293  slc.mallTraj.resize(ntp);
294 
295  // define mallTraj
296  unsigned int icnt = 0;
297  for(auto& tj : slc.tjs) {
298  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
299  geo::PlaneID planeID = DecodeCTP(tj.CTP);
300  if((int)planeID.Cryostat != cstat) continue;
301  if((int)planeID.TPC != tpc) continue;
302  int plane = planeID.Plane;
303  int tjID = tj.ID;
304  if(tjID <= 0) continue;
305  short score = 1;
306  if(tj.AlgMod[kTjHiVx3Score]) score = 0;
307  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
308  auto& tp = tj.Pts[ipt];
309  if(tp.Chg == 0) continue;
310  if(icnt > slc.mallTraj.size() - 1) break;
311  if(tp.Pos[0] < -0.4) continue;
312  slc.mallTraj[icnt].wire = std::nearbyint(tp.Pos[0]);
313  bool hasWire = tcc.geom->HasWire(geo::WireID(cstat, tpc, plane, slc.mallTraj[icnt].wire));
314  // don't try matching if the wire doesn't exist
315  if(!hasWire) continue;
316  float xpos = tcc.detprop->ConvertTicksToX(tp.Pos[1]/tcc.unitsPerTick, plane, tpc, cstat);
317  float posPlusRMS = tp.Pos[1] + TPHitsRMSTime(slc, tp, kUsedHits);
318  float rms = tcc.detprop->ConvertTicksToX(posPlusRMS/tcc.unitsPerTick, plane, tpc, cstat) - xpos;
319  if(rms < tcc.match3DCuts[0]) rms = tcc.match3DCuts[0];
320  if(icnt == slc.mallTraj.size()) break;
321  slc.mallTraj[icnt].xlo = xpos - rms;
322  slc.mallTraj[icnt].xhi = xpos + rms;
323  slc.mallTraj[icnt].dir = tp.Dir;
324  slc.mallTraj[icnt].ctp = tp.CTP;
325  slc.mallTraj[icnt].id = tjID;
326  slc.mallTraj[icnt].ipt = ipt;
327  slc.mallTraj[icnt].npts = tj.EndPt[1] - tj.EndPt[0] + 1;
328  slc.mallTraj[icnt].score = score;
329  ++icnt;
330  } // tp
331  } // tj
332 
333  if(icnt < slc.mallTraj.size()) slc.mallTraj.resize(icnt);
334 
335  // This is pretty self-explanatory
336  std::vector<SortEntry> sortVec(slc.mallTraj.size());
337  for(unsigned int ipt = 0; ipt < slc.mallTraj.size(); ++ipt) {
338  // populate the sort vector
339  sortVec[ipt].index = ipt;
340  sortVec[ipt].val = slc.mallTraj[ipt].xlo;
341  } // ipt
342  // sort by increasing xlo
343  std::sort(sortVec.begin(), sortVec.end(), valIncreasings);
344  // put slc.mallTraj into sorted order
345  auto tallTraj = slc.mallTraj;
346  for(unsigned int ii = 0; ii < sortVec.size(); ++ii) slc.mallTraj[ii] = tallTraj[sortVec[ii].index];
347 
348  } // FillmAllTraj
bool valIncreasings(SortEntry c1, SortEntry c2)
Definition: PFPUtils.cxx:13
TCConfig tcc
Definition: DataStructs.cxx: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
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
const detinfo::DetectorProperties * detprop
Definition: DataStructs.h:494
std::vector< float > match3DCuts
3D matching cuts
Definition: DataStructs.h:476
const geo::GeometryCore * geom
Definition: DataStructs.h:493
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
float TPHitsRMSTime(TCSlice &slc, TrajPoint &tp, HitStatus_t hitRequest)
Definition: Utils.cxx:3668
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
virtual double ConvertTicksToX(double ticks, int p, int t, int c) const =0
geo::PlaneID DecodeCTP(CTP_t CTP)
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
bool HasWire(geo::WireID const &wireid) const
Returns whether we have the specified wire.
bool tca::FillWireHitRange ( TCSlice slc)

Definition at line 3944 of file Utils.cxx.

References tca::TCEvent::allHits, tca::TCEvent::aveHitRMS, geo::CryostatID::Cryostat, debug, geo::GeometryCore::DetHalfHeight(), geo::GeometryCore::DetHalfWidth(), geo::GeometryCore::DetLength(), tca::TCConfig::detprop, detinfo::DetectorProperties::DriftVelocity(), detinfo::DetectorProperties::Efield(), evt, tca::TCSlice::firstWire, tca::TCConfig::geom, kDebug, tca::TCSlice::lastWire, geo::TPCGeo::LocalToWorld(), tca::TCConfig::maxPos0, tca::TCConfig::maxPos1, tca::TCConfig::modes, tca::TCSlice::nPlanes, geo::GeometryCore::Nplanes(), detinfo::DetectorProperties::NumberTimeSamples(), tca::TCSlice::nWires, geo::GeometryCore::Nwires(), geo::GeometryCore::PlaneWireToChannel(), detinfo::DetectorProperties::SamplingRate(), tca::TCSlice::slHits, tcc, detinfo::DetectorProperties::Temperature(), tca::DebugStuff::TPC, geo::TPCID::TPC, geo::GeometryCore::TPC(), tca::TCSlice::TPCID, tca::TCConfig::unitsPerTick, geo::GeometryCore::View(), tca::TCSlice::wireHitRange, tca::TCConfig::wirePitch, geo::GeometryCore::WirePitch(), tca::TCSlice::xHi, tca::TCSlice::xLo, tca::TCSlice::yHi, tca::TCSlice::yLo, tca::TCSlice::zHi, and tca::TCSlice::zLo.

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

3945  {
3946  // fills the WireHitRange vector. Slightly modified version of the one in ClusterCrawlerAlg.
3947  // Returns false if there was a serious error
3948 
3949  // determine the number of planes
3950  unsigned int cstat = slc.TPCID.Cryostat;
3951  unsigned int tpc = slc.TPCID.TPC;
3952  unsigned short nplanes = tcc.geom->Nplanes(tpc, cstat);
3953  slc.nPlanes = nplanes;
3954  if(nplanes > 3) {
3955  std::cout<<"FillWireHitRange: crazy nPlanes "<<nplanes<<"\n";
3956  return false;
3957  }
3958 
3959  // Y,Z limits of the detector
3960  double local[3] = {0.,0.,0.};
3961  double world[3] = {0.,0.,0.};
3962  const geo::TPCGeo &thetpc = tcc.geom->TPC(tpc, cstat);
3963  thetpc.LocalToWorld(local,world);
3964  // reduce the active area of the TPC by 1 cm to prevent wire boundary issues
3965  slc.xLo = world[0]-tcc.geom->DetHalfWidth(tpc,cstat) + 1;
3966  slc.xHi = world[0]+tcc.geom->DetHalfWidth(tpc,cstat) - 1;
3967  slc.yLo = world[1]-tcc.geom->DetHalfHeight(tpc,cstat) + 1;
3968  slc.yHi = world[1]+tcc.geom->DetHalfHeight(tpc,cstat) - 1;
3969  slc.zLo = world[2]-tcc.geom->DetLength(tpc,cstat)/2 + 1;
3970  slc.zHi = world[2]+tcc.geom->DetLength(tpc,cstat)/2 - 1;
3971 
3972  lariov::ChannelStatusProvider const& channelStatus = art::ServiceHandle<lariov::ChannelStatusService>()->GetProvider();
3973 
3974  // initialize everything
3975  slc.wireHitRange.resize(nplanes);
3976  slc.firstWire.resize(nplanes);
3977  slc.lastWire.resize(nplanes);
3978  slc.nWires.resize(nplanes);
3979  tcc.maxPos0.resize(nplanes);
3980  tcc.maxPos1.resize(nplanes);
3981  evt.aveHitRMS.resize(nplanes, nplanes);
3982 
3983  std::pair<int, int> flag;
3984  flag.first = -2; flag.second = -2;
3985 
3986  // Calculate tcc.unitsPerTick, the scale factor to convert a tick into
3987  // Wire Spacing Equivalent (WSE) units where the wire spacing in this plane = 1.
3988  // Strictly speaking this factor should be calculated for each plane to handle the
3989  // case where the wire spacing is different in each plane. Deal with this later if
3990  // the approximation used here fails.
3991 
3992  raw::ChannelID_t channel = tcc.geom->PlaneWireToChannel(0, 0, (int)tpc, (int)cstat);
3993  tcc.wirePitch = tcc.geom->WirePitch(tcc.geom->View(channel));
3994  float tickToDist = tcc.detprop->DriftVelocity(tcc.detprop->Efield(),tcc.detprop->Temperature());
3995  tickToDist *= 1.e-3 * tcc.detprop->SamplingRate(); // 1e-3 is conversion of 1/us to 1/ns
3996  tcc.unitsPerTick = tickToDist / tcc.wirePitch;
3997  for(unsigned short plane = 0; plane < nplanes; ++plane) {
3998  slc.firstWire[plane] = INT_MAX;
3999  slc.lastWire[plane] = 0;
4000  slc.nWires[plane] = tcc.geom->Nwires(plane, tpc, cstat);
4001  slc.wireHitRange[plane].resize(slc.nWires[plane], flag);
4002  tcc.maxPos0[plane] = (float)slc.nWires[plane] - 0.5;
4003  tcc.maxPos1[plane] = (float)tcc.detprop->NumberTimeSamples() * tcc.unitsPerTick;
4004  }
4005 
4006  // overwrite with the "dead wires" condition
4007  flag.first = -1; flag.second = -1;
4008  for(unsigned short ipl = 0; ipl < nplanes; ++ipl) {
4009  for(unsigned int wire = 0; wire < slc.nWires[ipl]; ++wire) {
4010  raw::ChannelID_t chan = tcc.geom->PlaneWireToChannel((int)ipl, (int)wire, (int)tpc, (int)cstat);
4011  if(!channelStatus.IsGood(chan)) slc.wireHitRange[ipl][wire] = flag;
4012  } // wire
4013  } // ipl
4014 
4015  unsigned int lastWire = 0, lastPlane = 0;
4016  for(unsigned int iht = 0; iht < slc.slHits.size(); ++iht) {
4017  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
4018  if(hit.WireID().Cryostat != cstat) continue;
4019  if(hit.WireID().TPC != tpc) continue;
4020  unsigned short plane = hit.WireID().Plane;
4021  unsigned int wire = hit.WireID().Wire;
4022  if(wire > slc.nWires[plane] - 1) {
4023  mf::LogWarning("TC")<<"FillWireHitRange: Invalid wire number "<<wire<<" > "<<slc.nWires[plane] - 1<<" in plane "<<plane<<" Quitting";
4024  return false;
4025  } // too large wire number
4026  if(plane == lastPlane && wire < lastWire) {
4027  mf::LogWarning("TC")<<"FillWireHitRange: Hits are not in increasing wire order. Quitting ";
4028  return false;
4029  } // hits out of order
4030  lastWire = wire;
4031  lastPlane = plane;
4032  if(slc.firstWire[plane] == INT_MAX) slc.firstWire[plane] = wire;
4033  if(slc.wireHitRange[plane][wire].first < 0) slc.wireHitRange[plane][wire].first = iht;
4034  slc.wireHitRange[plane][wire].second = iht + 1;
4035  slc.lastWire[plane] = wire + 1;
4036  } // iht
4037 
4038 // if(!CheckWireHitRange(tcs)) return false;
4039 
4040  // Find the average multiplicity 1 hit RMS and calculate the expected max RMS for each range
4041  if(tcc.modes[kDebug] && (int)tpc == debug.TPC) {
4042  std::cout<<"tpc "<<tpc<<" tcc.unitsPerTick "<<std::setprecision(3)<<tcc.unitsPerTick<<"\n";
4043  std::cout<<"Active volume (";
4044  std::cout<<std::fixed<<std::setprecision(1)<<slc.xLo<<" < X < "<<slc.xHi<<") (";
4045  std::cout<<std::fixed<<std::setprecision(1)<<slc.yLo<<" < Y < "<<slc.yHi<<") (";
4046  std::cout<<std::fixed<<std::setprecision(1)<<slc.zLo<<" < Z < "<<slc.zHi<<")\n";
4047  }
4048 
4049  return true;
4050 
4051  } // FillWireHitRange
geo::Length_t DetHalfWidth(geo::TPCID const &tpcid) const
Returns the half width of the active volume of the specified TPC.
std::vector< float > maxPos0
Definition: DataStructs.h:489
TCConfig tcc
Definition: DataStructs.cxx:6
Geometry information for a single TPC.
Definition: TPCGeo.h:37
virtual double SamplingRate() const =0
Returns the period of the TPC readout electronics clock.
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
unsigned int Nwires(unsigned int p, unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wires in the specified plane.
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
geo::Length_t DetHalfHeight(geo::TPCID const &tpcid) const
Returns the half height of the active volume of the specified TPC.
std::vector< float > maxPos1
Definition: DataStructs.h:490
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
const detinfo::DetectorProperties * detprop
Definition: DataStructs.h:494
DebugStuff debug
Definition: DebugStruct.cxx:4
std::vector< float > aveHitRMS
average RMS of an isolated hit
Definition: DataStructs.h:541
virtual double Temperature() const =0
geo::Length_t DetLength(geo::TPCID const &tpcid) const
Returns the length of the active volume of the specified TPC.
const geo::GeometryCore * geom
Definition: DataStructs.h:493
virtual unsigned int NumberTimeSamples() const =0
View_t View(geo::PlaneID const &pid) const
Returns the view (wire orientation) on the channels of specified TPC plane.
Detector simulation of raw signals on wires.
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
int TPC
Select TPC.
Definition: DebugStruct.h:20
raw::ChannelID_t PlaneWireToChannel(WireID const &wireid) const
Returns the ID of the TPC channel connected to the specified wire.
virtual double DriftVelocity(double efield=0., double temperature=0.) const =0
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
virtual double Efield(unsigned int planegap=0) const =0
Returns the nominal electric field in the specified volume.
TCEvent evt
Definition: DataStructs.cxx:5
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:27
master switch for turning on debug mode
Definition: DataStructs.h:449
void LocalToWorld(const double *tpc, double *world) const
Transform point from local TPC frame to world frame.
Definition: TPCGeo.h:490
void tca::Find2DVertices ( TCSlice slc,
const CTP_t inCTP,
unsigned short  pass 
)

Definition at line 114 of file TCVertex.cxx.

References AttachAnyTrajToVertex(), tca::VtxStore::ChiDOF, ChkVxTjs(), tca::VtxStore::CTP, tca::TrajPoint::CTP, tca::TCConfig::dbg2V, tca::TCConfig::dbgSlc, DeadWireCount(), debug, DecodeCTP(), FindHammerVertices(), FindHammerVertices2(), FitVertex(), tca::VtxStore::ID, IsCloseToVertex(), kFixed, kHaloTj, kKilled, kNewVtxCuts, kOnDeadWire, kShowerLike, kStepDir, kVtxIndPlnNoChg, tca::TCConfig::maxPos0, tca::TCConfig::maxPos1, MergeWithVertex(), tca::TCConfig::modes, MoveTPToWire(), NearestPtWithChg(), tca::TCSlice::nPlanes, 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, StoreVertex(), tcc, tca::TCSlice::tjs, tca::VtxStore::Topo, TrajClosestApproach(), TrajIntersection(), TrajLength(), TrajTrajDOCA(), tca::TCConfig::unitsPerTick, tca::TCConfig::useAlg, tca::TCConfig::vtx2DCuts, and tca::TCSlice::vtxs.

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  // tcc.vtx2DCuts 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  // 10 Require charge on wires between a vtx and the start of the tjs in induction planes? (1 = yes)
133 
134  if(tcc.vtx2DCuts[0] <= 0) return;
135  if(slc.tjs.size() < 2) return;
136 
137  bool firstPassCuts = (tcc.useAlg[kNewVtxCuts] && pass == 0);
138 
139  geo::PlaneID planeID = DecodeCTP(inCTP);
140 
141  // require charge between the vertex and the tj start points?
142  bool requireVtxTjChg = true;
143  if(tcc.vtx2DCuts[10] == 0 && int(planeID.Plane) < slc.nPlanes - 1) requireVtxTjChg = false;
144 
145  bool prt = (tcc.dbg2V && tcc.dbgSlc && debug.Plane == (int)planeID.Plane);
146  if(prt) {
147  mf::LogVerbatim("TC")<<"prt set for plane "<<planeID.Plane<<" in Find2DVertices. firstPassCuts? "<<firstPassCuts<<" requireVtxTjChg "<<requireVtxTjChg;
148  PrintAllTraj("F2DVi", slc, USHRT_MAX, slc.tjs.size());
149  }
150 
151  unsigned short maxShortTjLen = tcc.vtx2DCuts[0];
152  for(unsigned short it1 = 0; it1 < slc.tjs.size() - 1; ++it1) {
153  auto& tj1 = slc.tjs[it1];
154  if(tj1.AlgMod[kKilled] || tj1.AlgMod[kHaloTj]) continue;
155  if(tj1.SSID > 0 || tj1.AlgMod[kShowerLike]) continue;
156  if(tj1.CTP != inCTP) continue;
157  bool tj1Short = (TrajLength(tj1) < maxShortTjLen);
158  for(unsigned short end1 = 0; end1 < 2; ++end1) {
159  // vertex assignment exists?
160  if(tj1.VtxID[end1] > 0) continue;
161  // wrong end of a high energy electron?
162  if(tj1.PDGCode == 111 && end1 != tj1.StartEnd) continue;
163  // default condition is to use the end point to define the trajectory and direction
164  // at the end
165  short endPt1 = tj1.EndPt[end1];
166  float wire1 = tj1.Pts[endPt1].Pos[0];
167  // unless there are few points fitted, indicating that the trajectory fit
168  // may have been biased by the presence of another trajectory at the vertex or by
169  // other close unresolved tracks
170  if(tj1.Pts.size() > 6 && tj1.Pts[endPt1].NTPsFit < 4) {
171  if(end1 == 0 && endPt1 < int(tj1.Pts.size()) - 3) {
172  endPt1 += 3;
173  } else if (end1 == 1 && endPt1 >=3 ) {
174  endPt1 -= 3;
175  }
176  if(tj1.Pts[endPt1].Chg == 0) endPt1 = NearestPtWithChg(slc, tj1, endPt1);
177  } // few points fit at end1
178  TrajPoint tp1 = tj1.Pts[endPt1];
179  MoveTPToWire(tp1, wire1);
180  // re-purpose endPt1 to reference the end point. This will be used the find the point on
181  // tj1 that is closest to the vertex position
182  endPt1 = tj1.EndPt[end1];
183  short oendPt1 = tj1.EndPt[1-end1];
184  // reference to the other end of tj1
185  auto& otp1 = tj1.Pts[oendPt1];
186  for(unsigned short it2 = it1 + 1; it2 < slc.tjs.size(); ++it2) {
187  auto& tj2 = slc.tjs[it2];
188  if(tj2.AlgMod[kKilled] || tj2.AlgMod[kHaloTj]) continue;
189  if(tj2.SSID > 0 || tj2.AlgMod[kShowerLike]) continue;
190  if(tj2.CTP != inCTP) continue;
191  if(tj1.VtxID[end1] > 0) continue;
192  if(tj1.MCSMom < tcc.vtx2DCuts[5] && tj2.MCSMom < tcc.vtx2DCuts[5]) continue;
193  bool tj2Short = (TrajLength(tj2) < maxShortTjLen);
194  // find the end that is closer to tp1
195  unsigned short end2 = 0;
196  if(PosSep2(tj2.Pts[tj2.EndPt[1]].Pos, tp1.Pos) < PosSep2(tj2.Pts[tj2.EndPt[0]].Pos, tp1.Pos)) end2 = 1;
197  if(tj2.VtxID[end2] > 0) continue;
198  // wrong end of a high energy electron?
199  if(tj2.PDGCode == 111 && end2 != tj2.StartEnd) continue;
200  // check for a vertex between these tjs at the other ends
201  if(tj1.VtxID[1 - end1] > 0 && tj1.VtxID[1 - end1] == tj2.VtxID[1 - end2]) continue;
202  // see if the other ends are closer
203  unsigned short oendPt2 = tj2.EndPt[1-end2];
204  auto& otp2 = tj2.Pts[oendPt2];
205  if(PosSep2(otp1.Pos, otp2.Pos) < PosSep2(tp1.Pos, tj2.Pts[tj2.EndPt[end2]].Pos)) continue;
206  short endPt2 = tj2.EndPt[end2];
207  float wire2 = tj2.Pts[endPt2].Pos[0];
208  if(tj2.Pts.size() > 6 && tj2.Pts[endPt2].NTPsFit < 4) {
209  if(end2 == 0 && endPt2 < int(tj2.Pts.size()) - 3) {
210  endPt2 += 3;
211  } else if (end2 == 1 && endPt2 >= 3){
212  endPt2 -= 3;
213  }
214  if(tj2.Pts[endPt2].Chg == 0) endPt2 = NearestPtWithChg(slc, tj2, endPt2);
215  } // few points fit at end1
216  TrajPoint tp2 = tj2.Pts[endPt2];
217  MoveTPToWire(tp2, wire2);
218  // re-purpose endPt2
219  endPt2 = tj2.EndPt[end2];
220  // Rough first cut on the separation between the end points of the
221  // two trajectories
222  float sepCut = 100;
223  if(std::abs(tp1.Pos[0] - tp2.Pos[0]) > sepCut) continue;
224  if(std::abs(tp1.Pos[1] - tp2.Pos[1]) > sepCut) continue;
225  float wint, tint;
226  TrajIntersection(tp1, tp2, wint, tint);
227  // make sure this is inside the TPC.
228  if(wint < 0 || wint > tcc.maxPos0[planeID.Plane] - 3) continue;
229  if(tint < 0 || tint > tcc.maxPos1[planeID.Plane]) continue;
230  // Next cut on separation between the TPs and the intersection point
231  if(tj1Short || tj2Short) { sepCut = tcc.vtx2DCuts[1]; } else { sepCut = tcc.vtx2DCuts[2]; }
232  // NewVtxCuts: require close separation on the first pass
233  if(firstPassCuts) sepCut = tcc.vtx2DCuts[1];
234  Point2_t vPos {{wint, tint}};
235  float vt1Sep = PosSep(vPos, tp1.Pos);
236  float vt2Sep = PosSep(vPos, tp2.Pos);
237  float dwc1 = DeadWireCount(slc, wint, tp1.Pos[0], tp1.CTP);
238  float dwc2 = DeadWireCount(slc, wint, tp2.Pos[0], tp1.CTP);
239  vt1Sep -= dwc1;
240  vt2Sep -= dwc2;
241  bool vtxOnDeadWire = (DeadWireCount(slc, wint, wint, tp1.CTP) == 1);
242  if(prt && vt1Sep < 200 && vt2Sep < 200) {
243  mf::LogVerbatim myprt("TC");
244  myprt<<"F2DV candidate T"<<tj1.ID<<"_"<<end1<<"-T"<<tj2.ID<<"_"<<end2;
245  myprt<<" vtx pos "<<(int)wint<<":"<<(int)(tint/tcc.unitsPerTick)<<" tp1 "<<PrintPos(slc, tp1)<<" tp2 "<<PrintPos(slc, tp2);
246  myprt<<" dwc1 "<<dwc1<<" dwc2 "<<dwc2<<" on dead wire? "<<vtxOnDeadWire;
247  myprt<<" vt1Sep "<<vt1Sep<<" vt2Sep "<<vt2Sep<<" sepCut "<<sepCut;
248  }
249  if(vt1Sep > sepCut || vt2Sep > sepCut) continue;
250  // make sure that the other end isn't closer
251  if(PosSep(vPos, slc.tjs[it1].Pts[oendPt1].Pos) < vt1Sep) {
252  if(prt) mf::LogVerbatim("TC")<<" tj1 other end "<<PrintPos(slc, tj1.Pts[oendPt1])<<" is closer to the vertex";
253  continue;
254  }
255  if(PosSep(vPos, slc.tjs[it2].Pts[oendPt2].Pos) < vt2Sep) {
256  if(prt) mf::LogVerbatim("TC")<<" tj2 other end "<<PrintPos(slc, tj2.Pts[oendPt2])<<" is closer to the vertex";
257  continue;
258  }
259  // Ensure that the vertex position is close to the end of each Tj
260  unsigned short closePt1;
261  float doca1 = sepCut;
262  if(!TrajClosestApproach(tj1, wint, tint, closePt1, doca1)) continue;
263  // dpt1 (and dpt2) will be 0 if the vertex is at the end
264  short stepDir = -1;
265  if(tcc.modes[kStepDir]) stepDir = 1;
266  short dpt1 = stepDir * (closePt1 - endPt1);
267  if(prt) mf::LogVerbatim("TC")<<" endPt1 "<<endPt1<<" closePt1 "<<closePt1<<" dpt1 "<<dpt1<<" doca1 "<<doca1;
268  // BB April 19, 2018: require vertex to be near the end
269  if(dpt1 < -1) continue;
270  if(slc.tjs[it1].EndPt[1] > 4) {
271  if(dpt1 > 3) continue;
272  } else {
273  // tighter cut for short trajectories
274  if(dpt1 > 2) continue;
275  }
276  unsigned short closePt2;
277  float doca2 = sepCut;
278  if(!TrajClosestApproach(tj2, wint, tint, closePt2, doca2)) continue;
279  short dpt2 = stepDir * (closePt2 - endPt2);
280  if(prt) mf::LogVerbatim("TC")<<" endPt2 "<<endPt2<<" closePt2 "<<closePt2<<" dpt2 "<<dpt2<<" doca2 "<<doca2;
281  // BB April 19, 2018: require vertex to be near the end
282  if(dpt2 < -1) continue;
283  if(slc.tjs[it2].EndPt[1] > 4) {
284  if(dpt2 > 3) continue;
285  } else {
286  // tighter cut for short trajectories
287  if(dpt2 > 2) continue;
288  }
289  if(prt) mf::LogVerbatim("TC")<<" wint:tint "<<(int)wint<<":"<<(int)(tint/tcc.unitsPerTick);
290  bool fixVxPos = false;
291  if(requireVtxTjChg) {
292  // ensure that there is a signal between these TPs and the vertex on most of the wires
293  bool signalBetween = true;
294  short dpt = abs(wint - tp1.Pos[0]);
295  if(dpt > 2 && !SignalBetween(slc, tp1, wint, tcc.vtx2DCuts[6])) {
296  if(prt) mf::LogVerbatim("TC")<<" Fails SignalBetween for tp1 "<<dpt;
297  signalBetween = false;
298  }
299  dpt = abs(wint - tp2.Pos[0]);
300  if(dpt > 2 && !SignalBetween(slc, tp2, wint, tcc.vtx2DCuts[6])) {
301  if(prt) mf::LogVerbatim("TC")<<" Fails SignalBetween for tp2 "<<dpt;
302  signalBetween = false;
303  }
304  // consider the case where the intersection point is wrong because the
305  // end TP angles are screwed up but the Tjs are close to each other near the end
306  if(!signalBetween) {
307  unsigned short ipt1, ipt2;
308  float maxSep = 3;
309  bool isClose = TrajTrajDOCA(slc, tj1, tj2, ipt1, ipt2, maxSep, false);
310  // require that they are close at the correct end
311  if(isClose) isClose = (abs(ipt1 - endPt1) < 4 && abs(ipt2 - endPt2) < 4);
312  if(isClose) {
313  if(prt) mf::LogVerbatim("TC")<<" TrajTrajDOCA are close with minSep "<<maxSep<<" near "<<PrintPos(slc, tj1.Pts[ipt1].Pos)<<" "<<PrintPos(slc, tj2.Pts[ipt2].Pos);
314  // put the vertex at the TP that is closest to the intersection point
315  Point2_t vpos = {{wint, tint}};
316  if(PosSep2(tp1.Pos, vpos) < PosSep2(tp2.Pos, vpos)) {
317  wint = tp1.Pos[0];
318  tint = tp1.Pos[1];
319  } else {
320  wint = tp2.Pos[0];
321  tint = tp2.Pos[1];
322  }
323  fixVxPos = true;
324  if(prt) mf::LogVerbatim("TC")<<" new wint:tint "<<(int)wint<<":"<<(int)(tint/tcc.unitsPerTick);
325  } else {
326  // closest approach > 3
327  continue;
328  }
329  } // no signal between
330  } // requireVtxTjChg
331  // make a new temporary vertex
332  VtxStore aVtx;
333  aVtx.Pos[0] = wint;
334  aVtx.Pos[1] = tint;
335  aVtx.NTraj = 0;
336  aVtx.Pass = tj1.Pass;
337  // Topo 0 has this topology (<) and Topo 2 has this (>)
338  aVtx.Topo = 2 * end1;
339  aVtx.ChiDOF = 0;
340  aVtx.CTP = inCTP;
341  aVtx.Stat[kOnDeadWire] = vtxOnDeadWire;
342  // fix the vertex position if we needed to move it significantly, or if it is on a dead wire
343  aVtx.Stat[kFixed] = fixVxPos;
344  aVtx.Stat[kVtxIndPlnNoChg] = !requireVtxTjChg;
345  // try to fit it. We need to give it an ID to do that. Take the next
346  // available ID
347  unsigned short newVtxID = slc.vtxs.size() + 1;
348  aVtx.ID = newVtxID;
349  tj1.VtxID[end1] = newVtxID;
350  tj2.VtxID[end2] = newVtxID;
351  if(!FitVertex(slc, aVtx, prt)) {
352  tj1.VtxID[end1] = 0;
353  tj2.VtxID[end2] = 0;
354  continue;
355  }
356  // check proximity to nearby vertices
357  unsigned short mergeMeWithVx = IsCloseToVertex(slc, aVtx);
358  if(mergeMeWithVx > 0 && MergeWithVertex(slc, aVtx, mergeMeWithVx)) {
359  if(prt) mf::LogVerbatim("TC")<<" Merged with close vertex "<<mergeMeWithVx;
360  continue;
361  }
362  // Save it
363  if(!StoreVertex(slc, aVtx)) continue;
364  if(prt) {
365  mf::LogVerbatim myprt("TC");
366  myprt<<" New vtx 2V"<<aVtx.ID;
367  myprt<<" Tjs "<<tj1.ID<<"_"<<end1<<"-"<<tj2.ID<<"_"<<end2;
368  myprt<<" at "<<std::fixed<<std::setprecision(1)<<aVtx.Pos[0]<<":"<<aVtx.Pos[1]/tcc.unitsPerTick;
369  }
370  AttachAnyTrajToVertex(slc, slc.vtxs.size() - 1, prt);
371 /*
372  if(tcc.useAlg[kNewVtxCuts]) {
373  // try stepping away from the vertex
374  auto& newVx2 = slc.vtxs[slc.vtxs.size() - 1];
375  auto tjlist = GetAssns(slc, "2V", newVx2.ID, "T");
376  // count the number of long straight Tjs
377  unsigned short nlong = 0;
378  for(auto tjid : tjlist) {
379  auto& vtj = slc.tjs[tjid - 1];
380  unsigned short npts = vtj.EndPt[1] - vtj.EndPt[0] + 1;
381  if(npts > 20 && vtj.MCSMom > 100) ++nlong;
382  } // tjid
383  if(nlong > 1) {
384  std::cout<<"Try 2V"<<newVx2.ID<<" nlong "<<nlong<<"\n";
385  FindVtxTjs(slc, newVx2);
386  }
387  } // new cuts
388 */
389  SetVx2Score(slc);
390  } // it2
391  } // end1
392  } // it1
393 
394  // check the consistency of the Tjs for the newly added vertices
395  ChkVxTjs(slc, inCTP, prt);
396 
397  // only call these on the last pass
398  if(pass == USHRT_MAX) {
399  FindHammerVertices(slc, inCTP);
400  FindHammerVertices2(slc, inCTP);
401  }
402 
403  if(prt) PrintAllTraj("F2DVo", slc, USHRT_MAX, USHRT_MAX);
404 
405  } // Find2DVertices
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MergeWithVertex(TCSlice &slc, VtxStore &vx, unsigned short oVxID)
Definition: TCVertex.cxx:701
bool FitVertex(TCSlice &slc, VtxStore &vx, std::vector< TrajPoint > vxTp, bool prt)
Definition: TCVertex.cxx:2184
unsigned short IsCloseToVertex(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:3316
std::vector< float > maxPos0
Definition: DataStructs.h:489
TCConfig tcc
Definition: DataStructs.cxx:6
vertex position fixed manually - no fitting done
Definition: DataStructs.h:74
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
step from US -> DS (true) or DS -> US (false)
Definition: DataStructs.h:447
void PrintAllTraj(std::string someText, TCSlice &slc, unsigned short itj, unsigned short ipt, bool prtVtx)
Definition: Utils.cxx:5197
bool TrajClosestApproach(Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
Definition: Utils.cxx:2377
bool AttachAnyTrajToVertex(TCSlice &slc, unsigned short ivx, bool prt)
Definition: TCVertex.cxx:1868
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:507
float DeadWireCount(TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:1881
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:2093
bool TrajTrajDOCA(TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2175
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
std::vector< float > maxPos1
Definition: DataStructs.h:490
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
unsigned short NearestPtWithChg(TCSlice &slc, Trajectory &tj, unsigned short thePt)
Definition: Utils.cxx:2966
DebugStuff debug
Definition: DebugStruct.cxx:4
bool SignalBetween(TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2, const float &MinWireSignalFraction)
Definition: Utils.cxx:1671
bool dbg2V
debug 2D vertex finding
Definition: DataStructs.h:510
int Plane
Select plane.
Definition: DebugStruct.h:21
float TrajLength(Trajectory &tj)
Definition: Utils.cxx:2337
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1660
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
vertex quality is suspect - No requirement made on chg btw it and the Tj
Definition: DataStructs.h:79
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
Definition: Utils.cxx:2299
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2513
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
geo::PlaneID DecodeCTP(CTP_t CTP)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
void FindHammerVertices(TCSlice &slc, const CTP_t &inCTP)
Definition: TCVertex.cxx:1154
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:466
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2485
void FindHammerVertices2(TCSlice &slc, const CTP_t &inCTP)
Definition: TCVertex.cxx:979
void ChkVxTjs(TCSlice &slc, const CTP_t &inCTP, bool prt)
Definition: TCVertex.cxx:874
void tca::Find3DVertices ( TCSlice slc)

Definition at line 1392 of file TCVertex.cxx.

References CompleteIncomplete3DVertices(), CompleteIncomplete3DVerticesInGaps(), detinfo::DetectorProperties::ConvertTicksToX(), detinfo::DetectorProperties::ConvertXToTicks(), geo::CryostatID::Cryostat, tca::TCConfig::dbg3V, tca::TCConfig::dbgSlc, DecodeCTP(), tca::TCConfig::detprop, evt, FindCloseHits(), tca::TCConfig::geom, tca::TCEvent::globalS3ID, geo::GeometryCore::HasWire(), tca::Vtx3Store::ID, tca::SortEntry::index, geo::GeometryCore::IntersectionPoint(), kAllHits, kHaloTj, kKilled, kNewVtxCuts, kTjHiVx3Score, evd::kWire, geo::kX, tca::TCSlice::nPlanes, tca::TCSlice::nWires, geo::PlaneID::Plane, PrintHit(), tca::Vtx3Store::Score, SetVx2Score(), SetVx3Score(), tca::TCSlice::slHits, tcc, tca::TCSlice::tjs, geo::TPCID::TPC, tca::Vtx3Store::TPCID, tca::TCSlice::TPCID, tca::TCConfig::unitsPerTick, tca::TCConfig::useAlg, tca::SortEntry::val, valIncreasing(), tca::TCConfig::vtx2DCuts, tca::TCConfig::vtx3DCuts, tca::TCSlice::vtx3s, tca::TCSlice::vtxs, tca::Vtx3Store::Vx2ID, tca::VtxStore::Vx3ID, tca::Vtx3Store::Wire, geo::GeometryCore::WireCoordinate(), tca::TCConfig::wirePitch, tca::Vtx3Store::X, tca::Vtx3Store::XErr, y, tca::Vtx3Store::Y, tca::Vtx3Store::YErr, tca::TCSlice::yHi, tca::Vtx3Store::Z, z, tca::Vtx3Store::ZErr, and tca::TCSlice::zHi.

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

1393  {
1394  // Create 3D vertices from 2D vertices. 3D vertices that are matched
1395  // in all three planes have Vtx2ID > 0 for all planes. This function re-scores all
1396  // 2D and 3D vertices and flags Tjs that have high-score 3D vertices
1397 
1398  if(tcc.vtx3DCuts[0] < 0) return;
1399  if(slc.vtxs.size() < 2) return;
1400  bool newCuts = (tcc.vtx3DCuts.size() > 2);
1401 
1402  // create a array/vector of 2D vertex indices in each plane
1403  std::vector<std::vector<unsigned short>> vIndex(3);
1404  for(unsigned short ivx = 0; ivx < slc.vtxs.size(); ++ivx) {
1405  // obsolete vertex
1406  if(slc.vtxs[ivx].ID == 0) continue;
1407  geo::PlaneID planeID = DecodeCTP(slc.vtxs[ivx].CTP);
1408  unsigned short plane = planeID.Plane;
1409  if(plane > 2) continue;
1410  vIndex[plane].push_back(ivx);
1411  }
1412 
1413  unsigned short vtxInPln = 0;
1414  for(unsigned short plane = 0; plane < slc.nPlanes; ++plane) if(vIndex[plane].size() > 0) ++vtxInPln;
1415  if(vtxInPln < 2) return;
1416 
1417  float thirdPlanedXCut = 2 * tcc.vtx3DCuts[0];
1418  bool prt = (tcc.dbg3V && tcc.dbgSlc);
1419  if(prt) {
1420  mf::LogVerbatim("TC")<<"Inside Find3DVertices. dX cut "<<tcc.vtx3DCuts[0]<<" thirdPlanedXCut "<<thirdPlanedXCut;
1421 // PrintAllTraj("F3DV", slc, USHRT_MAX, slc.tjs.size());
1422  }
1423 
1424  size_t vsize = slc.vtxs.size();
1425  // vector of 2D vertices -> 3D vertices.
1426  std::vector<short> vPtr(vsize, -1);
1427  // fill temp vectors of 2D vertex X and X errors
1428  std::vector<float> vX(vsize, -100);
1429 
1430  for(unsigned short ivx = 0; ivx < vsize; ++ivx) {
1431  if(slc.vtxs[ivx].ID <= 0) continue;
1432  if(tcc.useAlg[kNewVtxCuts] && slc.vtxs[ivx].Score < tcc.vtx2DCuts[7]) continue;
1433  geo::PlaneID planeID = DecodeCTP(slc.vtxs[ivx].CTP);
1434  if(slc.vtxs[ivx].Pos[0] < -0.4) continue;
1435  unsigned int wire = std::nearbyint(slc.vtxs[ivx].Pos[0]);
1436  if(!tcc.geom->HasWire(geo::WireID(planeID, wire))) continue;
1437  // Convert 2D vertex time error to X error
1438  double ticks = slc.vtxs[ivx].Pos[1] / tcc.unitsPerTick;
1439  vX[ivx] = tcc.detprop->ConvertTicksToX(ticks, planeID);
1440  } // ivx
1441 
1442  // temp vector of all 2D vertex matches
1443  std::vector<Vtx3Store> v3temp;
1444 
1445  unsigned int cstat = slc.TPCID.Cryostat;
1446  unsigned int tpc = slc.TPCID.TPC;
1447 
1448  TrajPoint tp;
1449  float maxScore = 0;
1450  constexpr float maxSep = 4;
1451  // i, j, k indicates 3 different wire planes
1452  // compare vertices in each view
1453  for(unsigned short ipl = 0; ipl < 2; ++ipl) {
1454  for(unsigned short ii = 0; ii < vIndex[ipl].size(); ++ii) {
1455  unsigned short ivx = vIndex[ipl][ii];
1456  if(vX[ivx] < 0) continue;
1457  auto& ivx2 = slc.vtxs[ivx];
1458  if(ivx2.Pos[0] < -0.4) continue;
1459  unsigned int iWire = std::nearbyint(ivx2.Pos[0]);
1460  for(unsigned short jpl = ipl + 1; jpl < 3; ++jpl) {
1461  for(unsigned short jj = 0; jj < vIndex[jpl].size(); ++jj) {
1462  unsigned short jvx = vIndex[jpl][jj];
1463  if(vX[jvx] < 0) continue;
1464  auto& jvx2 = slc.vtxs[jvx];
1465  if(jvx2.Pos[0] < -0.4) continue;
1466  unsigned int jWire = std::nearbyint(jvx2.Pos[0]);
1467  float dX = std::abs(vX[ivx] - vX[jvx]);
1468  if(dX > tcc.vtx3DCuts[0]) continue;
1469  // see if this pair is already in the list
1470  //bool gotit = false;
1471  for(auto& v3t : v3temp) {
1472  unsigned short cnt = 0;
1473  if(std::find(v3t.Vx2ID.begin(), v3t.Vx2ID.end(), ivx2.ID) != v3t.Vx2ID.end()) ++cnt;
1474  if(std::find(v3t.Vx2ID.begin(), v3t.Vx2ID.end(), jvx2.ID) != v3t.Vx2ID.end()) ++cnt;
1475  if(cnt == slc.nPlanes) {
1476  //gotit = true;
1477  break;
1478  } // cnt == slc.nPlanes
1479  } // v3t
1480  if(prt) {
1481  mf::LogVerbatim("TC")<<"F3DV: ipl "<<ipl<<" i2V"<<ivx2.ID<<" iX "<<vX[ivx]
1482  <<" jpl "<<jpl<<" j2V"<<jvx2.ID<<" jvX "<<vX[jvx]<<" W:T "<<(int)jvx2.Pos[0]<<":"<<(int)jvx2.Pos[1]<<" dX "<<dX;
1483  }
1484  double y = -1000, z = -1000;
1485  tcc.geom->IntersectionPoint(iWire, jWire, ipl, jpl, cstat, tpc, y, z);
1486  if(y < slc.yLo || y > slc.yHi || z < slc.zLo || z > slc.zHi) continue;
1487  unsigned short kpl = 3 - ipl - jpl;
1488  float kX = 0.5 * (vX[ivx] + vX[jvx]);
1489  int kWire = -1;
1490  if(slc.nPlanes > 2) {
1491  kWire = (int)(tcc.geom->WireCoordinate(y, z, kpl, tpc, cstat) + 0.5);
1492  if(kWire < 0 || (unsigned int)kWire > slc.nWires[kpl]) continue;
1493  if(!tcc.geom->HasWire(geo::WireID(cstat, tpc, kpl, kWire))) continue;
1494  std::array<int, 2> wireWindow;
1495  std::array<float, 2> timeWindow;
1496  wireWindow[0] = kWire - maxSep;
1497  wireWindow[1] = kWire + maxSep;
1498  float time = tcc.detprop->ConvertXToTicks(kX, kpl, (int)tpc, (int)cstat) * tcc.unitsPerTick;
1499  timeWindow[0] = time - maxSep;
1500  timeWindow[1] = time + maxSep;
1501  bool hitsNear;
1502  std::vector<unsigned int> closeHits = FindCloseHits(slc, wireWindow, timeWindow, kpl, kAllHits, true, hitsNear);
1503  if(prt) {
1504  mf::LogVerbatim myprt("TC");
1505  myprt<<" Hits near "<<kpl<<":"<<kWire<<":"<<(int)(time/tcc.unitsPerTick)<<" = ";
1506  for(auto iht : closeHits) myprt<<" "<<PrintHit(slc.slHits[iht]);
1507  }
1508  if(!hitsNear) continue;
1509  } // 3-plane TPC
1510  // save this incomplete 3D vertex
1511  Vtx3Store v3d;
1512  // give it a non-zero ID so that SetVx3Score returns a valid score
1513  v3d.ID = 666;
1514  v3d.Vx2ID.resize(slc.nPlanes);
1515  v3d.Vx2ID[ipl] = ivx2.ID;
1516  v3d.Vx2ID[jpl] = jvx2.ID;
1517  if(slc.nPlanes == 2) v3d.Vx2ID[2] = -1;
1518  v3d.X = kX;
1519  // Use XErr to store dX
1520  v3d.XErr = dX;
1521  v3d.Y = y;
1522  v3d.Z = z;
1523  v3d.Wire = kWire;
1524  float posError = dX / tcc.vtx3DCuts[0];
1525  float vxScoreWght = 0;
1526  if(newCuts) {
1527  SetVx3Score(slc, v3d);
1528  vxScoreWght = tcc.vtx3DCuts[2] / v3d.Score;
1529  if(posError < 0.5) posError = 0;
1530  }
1531  v3d.Score = posError + vxScoreWght;
1532  v3d.TPCID = slc.TPCID;
1533  // push the incomplete vertex onto the list
1534  v3temp.push_back(v3d);
1535 
1536  if(prt) {
1537  mf::LogVerbatim myprt("TC");
1538  myprt<<"F3DV: 2 Plane match i2V";
1539  myprt<<slc.vtxs[ivx].ID<<" P:W:T "<<ipl<<":"<<(int)slc.vtxs[ivx].Pos[0]<<":"<<(int)slc.vtxs[ivx].Pos[1];
1540  myprt<<" j2V"<<slc.vtxs[jvx].ID<<" P:W:T "<<jpl<<":"<<(int)slc.vtxs[jvx].Pos[0]<<":"<<(int)slc.vtxs[jvx].Pos[1];
1541  myprt<<std::fixed<<std::setprecision(3);
1542  myprt<<" dX "<<dX<<" posError "<<posError<<" vxScoreWght "<<vxScoreWght<<" Score "<<v3d.Score;
1543  }
1544 
1545  if(slc.nPlanes == 2) continue;
1546 
1547  // look for a 3 plane match
1548  for(unsigned short kk = 0; kk < vIndex[kpl].size(); ++kk) {
1549  unsigned short kvx = vIndex[kpl][kk];
1550  if(vX[kvx] < 0) continue;
1551  float dX = std::abs(vX[kvx] - v3d.X);
1552  // Wire difference error
1553  float dW = tcc.wirePitch * std::abs(slc.vtxs[kvx].Pos[0] - kWire);
1554  if(prt) mf::LogVerbatim("TC")<<" k2V"<<kvx+1<<" dX "<<dX<<" dW "<<dW;
1555  if(dX > thirdPlanedXCut) continue;
1556  if(dW > tcc.vtx3DCuts[1]) continue;
1557  // put the Y,Z difference in YErr and ZErr
1558  double y = -1000, z = -1000;
1559  tcc.geom->IntersectionPoint(iWire, kWire, ipl, kpl, cstat, tpc, y, z);
1560  v3d.YErr = y - v3d.Y;
1561  v3d.ZErr = z - v3d.Z;
1562  v3d.Vx2ID[kpl] = slc.vtxs[kvx].ID;
1563  v3d.Wire = -1;
1564  // hijack the Score variable to hold the separation^2, weighted by the
1565  // vertex3DCuts
1566  dX = (vX[kvx] - v3d.X) / tcc.vtx3DCuts[0];
1567  float dY = v3d.YErr / tcc.vtx3DCuts[1];
1568  float dZ = v3d.ZErr / tcc.vtx3DCuts[1];
1569  posError = dX * dX + dY * dY + dZ * dZ;
1570  vxScoreWght = 0;
1571  if(newCuts) {
1572  SetVx3Score(slc, v3d);
1573  vxScoreWght = tcc.vtx3DCuts[2] / v3d.Score;
1574  if(posError < 0.5) posError = 0;
1575  } // newCuts
1576  v3d.Score = posError + vxScoreWght;
1577  if(v3d.Score > maxScore) maxScore = v3d.Score;
1578  v3temp.push_back(v3d);
1579  } // kk
1580  } // jj
1581  } // jpl
1582  } // ii
1583  } // ipl
1584 
1585  if(v3temp.empty()) return;
1586 
1587  // We will sort this list by increasing score. First add the maxScore for 2-plane matches so that
1588  // they are considered after the 3-plane matches
1589  maxScore += 1;
1590  for(auto& v3 : v3temp) if(v3.Wire >= 0) v3.Score += maxScore;
1591 
1592  if(prt) {
1593  mf::LogVerbatim("TC")<<"v3temp list";
1594  for(auto& v3 : v3temp) {
1595  if(slc.nPlanes == 2) {
1596  mf::LogVerbatim("TC")<<"2V"<<v3.Vx2ID[0]<<" 2V"<<v3.Vx2ID[1]<<" wire "<<v3.Wire<<" Score "<<v3.Score;
1597  } else {
1598  mf::LogVerbatim("TC")<<"2V"<<v3.Vx2ID[0]<<" 2V"<<v3.Vx2ID[1]<<" 2V"<<v3.Vx2ID[2]<<" wire "<<v3.Wire<<" Score "<<v3.Score;
1599  }
1600  } // v3
1601  }
1602  SortEntry sEntry;
1603  std::vector<SortEntry> sortVec(v3temp.size());
1604  for(unsigned short ivx = 0; ivx < v3temp.size(); ++ivx) {
1605  sEntry.index = ivx;
1606  sEntry.val = v3temp[ivx].Score;
1607  sortVec[ivx] = sEntry;
1608  } // ivx
1609  if(sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(), valIncreasing);
1610  // create a new vector of selected 3D vertices
1611  std::vector<Vtx3Store> v3sel;
1612  for(unsigned short ii = 0; ii < sortVec.size(); ++ii) {
1613  unsigned short ivx = sortVec[ii].index;
1614  // ensure that all 2D vertices are unique
1615  bool skipit = false;
1616  for(auto& v3 : v3sel) {
1617  for(unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
1618  if(v3temp[ivx].Vx2ID[ipl] == 0) continue;
1619  if(v3temp[ivx].Vx2ID[ipl] == v3.Vx2ID[ipl]) {
1620  skipit = true;
1621  break;
1622  }
1623  } // ipl
1624  if(skipit) break;
1625  } // v3
1626  if(skipit) continue;
1627  v3sel.push_back(v3temp[ivx]);
1628  } // ii
1629  v3temp.clear();
1630 
1631  if(prt) {
1632  mf::LogVerbatim myprt("TC");
1633  myprt<<"v3sel list\n";
1634  for(auto& v3d : v3sel) {
1635  for(auto vx2id : v3d.Vx2ID) if(vx2id > 0) myprt<<" 2V"<<vx2id;
1636  myprt<<" wire "<<v3d.Wire<<" Score "<<v3d.Score;
1637  myprt<<"\n";
1638  } // v3d
1639  } // prt
1640 
1641  // Count the number of incomplete vertices and store
1642  unsigned short ninc = 0;
1643  for(auto& vx3 : v3sel) {
1644  if(slc.nPlanes == 3 && vx3.Wire >= 0) ++ninc;
1645  vx3.ID = slc.vtx3s.size() + 1;
1646  ++evt.globalS3ID;
1647  vx3.UID = evt.globalS3ID;
1648  if(prt) {
1649  mf::LogVerbatim myprt("TC");
1650  myprt<<" 3V"<<vx3.ID;
1651  for(auto v2id : vx3.Vx2ID) myprt<<" 2V"<<v2id;
1652  myprt<<" wire "<<vx3.Wire;
1653  } // prt
1654  slc.vtx3s.push_back(vx3);
1655  // make the 2D -> 3D associations
1656  for(unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
1657  if(vx3.Vx2ID[ipl] == 0) continue;
1658  VtxStore& vx2 = slc.vtxs[vx3.Vx2ID[ipl]-1];
1659  vx2.Vx3ID = vx3.ID;
1660  } // ipl
1661  } // ivx
1662 
1663  // Try to complete incomplete vertices
1664  if(ninc > 0) {
1667  }
1668 
1669  // Score and flag Tjs that are attached to high-score vertices
1670  // First remove Tj vertex flags
1671  for(auto& tj : slc.tjs) {
1672  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
1673  geo::PlaneID planeID = DecodeCTP(tj.CTP);
1674  if(planeID.TPC != tpc || planeID.Cryostat != cstat) continue;
1675  tj.AlgMod[kTjHiVx3Score] = false;
1676  } // tj
1677  // Score the 2D vertices
1678  for(auto& vx2 : slc.vtxs) {
1679  if(vx2.ID == 0) continue;
1680  geo::PlaneID planeID = DecodeCTP(vx2.CTP);
1681  if(planeID.TPC != tpc || planeID.Cryostat != cstat) continue;
1682  SetVx2Score(slc, vx2);
1683  } // vx2
1684  // and the 3D vertices
1685  for(auto& vx3 : slc.vtx3s) {
1686  if(vx3.ID == 0) continue;
1687  SetVx3Score(slc, vx3);
1688  } // vx3
1689 
1690  } // Find3DVertices
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
static unsigned int kWire
std::vector< float > vtx3DCuts
2D vtx -> 3D vtx matching cuts
Definition: DataStructs.h:467
unsigned int index
Definition: StepUtils.cxx:5
TCConfig tcc
Definition: DataStructs.cxx:6
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
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:507
void SetVx3Score(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2483
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
bool dbg3V
debug 3D vertex finding
Definition: DataStructs.h:514
std::vector< unsigned int > FindCloseHits(TCSlice &slc, std::array< int, 2 > const &wireWindow, Point2_t const &timeWindow, const unsigned short plane, HitStatus_t hitRequest, bool usePeakTime, bool &hitsNear)
Definition: Utils.cxx:2496
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
const detinfo::DetectorProperties * detprop
Definition: DataStructs.h:494
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:5704
const geo::GeometryCore * geom
Definition: DataStructs.h:493
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
bool IntersectionPoint(geo::WireID const &wid1, geo::WireID const &wid2, double &y, double &z) const
Returns the intersection point of two wires.
void CompleteIncomplete3DVerticesInGaps(TCSlice &slc)
Definition: TCVertex.cxx:2669
virtual double ConvertTicksToX(double ticks, int p, int t, int c) const =0
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2513
float val
Definition: StepUtils.cxx:6
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:466
void CompleteIncomplete3DVertices(TCSlice &slc)
Definition: TCVertex.cxx:2759
TCEvent evt
Definition: DataStructs.cxx:5
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
bool valIncreasing(SortEntry c1, SortEntry c2)
Definition: Utils.cxx:15
bool HasWire(geo::WireID const &wireid) const
Returns whether we have the specified wire.
void tca::FindAlongTrans ( Point2_t  pos1,
Vector2_t  dir1,
Point2_t  pos2,
Point2_t alongTrans 
)

Definition at line 2817 of file Utils.cxx.

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

2818  {
2819  // Calculate the distance along and transverse to the direction vector dir1 from pos1 to pos2
2820  alongTrans[0] = 0;
2821  alongTrans[1] = 0;
2822  if(pos1[0] == pos2[0] && pos1[1] == pos2[1]) return;
2823  pos1[0] = pos2[0] - pos1[0];
2824  pos1[1] = pos2[1] - pos1[1];
2825  double sep = sqrt(pos1[0] * pos1[0] + pos1[1] * pos1[1]);
2826  if(sep < 1E-6) return;
2827  Vector2_t ptDir;
2828  ptDir[0] = pos1[0] / sep;
2829  ptDir[1] = pos1[1] / sep;
2830  SetMag(dir1, 1.0);
2831  double costh = DotProd(dir1, ptDir);
2832  if(costh > 1.0 || costh < -1.0) return;
2833  alongTrans[0] = costh * sep;
2834  double sinth = sqrt(1 - costh * costh);
2835  alongTrans[1] = sinth * sep;
2836  } // FindAlongTrans
Float_t E
Definition: plot.C:23
bool SetMag(Vector2_t &v1, double mag)
Definition: Utils.cxx:2805
std::array< double, 2 > Vector2_t
Definition: DataStructs.h:38
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:59
void tca::FindAlongTrans ( Point3_t  pos1,
Vector3_t  dir1,
Point3_t  pos2,
Point2_t alongTrans 
)

Definition at line 2849 of file PFPUtils.cxx.

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

Referenced by DotProd(), FindCompleteness(), FindParent(), FollowTp3s(), InShowerProb(), MergeSubShowers(), and ParentFOM().

2850  {
2851  // Calculate the distance along and transvers to the direction vector from pos1 to pos2
2852  alongTrans[0] = 0;
2853  alongTrans[1] = 0;
2854  if(pos1[0] == pos2[0] && pos1[1] == pos2[1] && pos1[2] == pos2[2]) return;
2855  auto ptDir = PointDirection(pos1, pos2);
2856  SetMag(dir1, 1.0);
2857  double costh = DotProd(dir1, ptDir);
2858  if(costh > 1) return;
2859  double sep = PosSep(pos1, pos2);
2860  if(sep < 1E-6) return;
2861  alongTrans[0] = costh * sep;
2862  double sinth = sqrt(1 - costh * costh);
2863  alongTrans[1] = sinth * sep;
2864  } // FindAlongTrans
Float_t E
Definition: plot.C:23
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:1643
bool SetMag(Vector3_t &v1, double mag)
Definition: PFPUtils.cxx:1670
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:59
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
std::vector< unsigned int > tca::FindCloseHits ( TCSlice slc,
std::array< int, 2 > const &  wireWindow,
Point2_t const &  timeWindow,
const unsigned short  plane,
HitStatus_t  hitRequest,
bool  usePeakTime,
bool &  hitsNear 
)

Definition at line 2496 of file Utils.cxx.

References tca::TCEvent::allHits, evt, tca::TCSlice::firstWire, kAllHits, kUnusedHits, kUsedHits, tca::TCSlice::lastWire, tca::TCSlice::slHits, tcc, tca::TCConfig::unitsPerTick, and tca::TCSlice::wireHitRange.

Referenced by AddLAHits(), ChkStopEndPts(), Find3DVertices(), FindVtxTjs(), FixTrajBegin(), Forecast(), and ReversePropagate().

2497  {
2498  // returns a vector of hits that are within the Window[Pos0][Pos1] in plane.
2499  // Note that hits on wire wireWindow[1] are returned as well. The definition of close
2500  // depends on setting of usePeakTime. If UsePeakTime is true, a hit is considered nearby if
2501  // the PeakTime is within the window. This is shown schematically here where
2502  // the time is on the horizontal axis and a "-" denotes a valid entry
2503  // timeWindow -----------------
2504  // hit PeakTime + close
2505  // hit PeakTime + not close
2506  // If usePeakTime is false, a hit is considered nearby if the hit StartTick and EndTick overlap with the timeWindow
2507  // Time window ---------
2508  // Hit StartTick-EndTick -------- close
2509  // Hit StartTick - EndTick -------- not close
2510 
2511  hitsNear = false;
2512  std::vector<unsigned int> closeHits;
2513  if(plane > slc.firstWire.size() - 1) return closeHits;
2514  // window in the wire coordinate
2515  int loWire = wireWindow[0];
2516  if(loWire < (int)slc.firstWire[plane]) loWire = slc.firstWire[plane];
2517  int hiWire = wireWindow[1];
2518  if(hiWire > (int)slc.lastWire[plane]-1) hiWire = slc.lastWire[plane]-1;
2519  // window in the time coordinate
2520  float minTick = timeWindow[0] / tcc.unitsPerTick;
2521  float maxTick = timeWindow[1] / tcc.unitsPerTick;
2522  for(int wire = loWire; wire <= hiWire; ++wire) {
2523  // Set hitsNear if the wire is dead
2524  if(slc.wireHitRange[plane][wire].first == -2) hitsNear = true;
2525  if(slc.wireHitRange[plane][wire].first < 0) continue;
2526  unsigned int firstHit = (unsigned int)slc.wireHitRange[plane][wire].first;
2527  unsigned int lastHit = (unsigned int)slc.wireHitRange[plane][wire].second;
2528  for(unsigned int iht = firstHit; iht < lastHit; ++iht) {
2529  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2530  if(usePeakTime) {
2531  if(hit.PeakTime() < minTick) continue;
2532  if(hit.PeakTime() > maxTick) break;
2533  } else {
2534  int hiLo = minTick;
2535  if(hit.StartTick() > hiLo) hiLo = hit.StartTick();
2536  int loHi = maxTick;
2537  if(hit.EndTick() < loHi) loHi = hit.EndTick();
2538  if(loHi < hiLo) continue;
2539  if(hiLo > loHi) break;
2540  }
2541  hitsNear = true;
2542  bool takeit = (hitRequest == kAllHits);
2543  if(hitRequest == kUsedHits && slc.slHits[iht].InTraj > 0) takeit = true;
2544  if(hitRequest == kUnusedHits && slc.slHits[iht].InTraj == 0) takeit = true;
2545  if(takeit) closeHits.push_back(iht);
2546  } // iht
2547  } // wire
2548  return closeHits;
2549  } // FindCloseHits
TCConfig tcc
Definition: DataStructs.cxx:6
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
bool tca::FindCloseHits ( TCSlice slc,
TrajPoint tp,
float const &  maxDelta,
HitStatus_t  hitRequest 
)

Definition at line 2552 of file Utils.cxx.

References tca::TCEvent::allHits, tca::TrajPoint::CTP, DecodeCTP(), tca::TrajPoint::Environment, evt, tca::TCSlice::firstWire, tca::TrajPoint::Hits, kAllHits, kEnvDeadWire, kUnusedHits, kUsedHits, tca::TCSlice::lastWire, geo::PlaneID::Plane, PointTrajDOCA(), tca::TrajPoint::Pos, tca::TCSlice::slHits, tcc, tca::TCSlice::tjs, tca::TCConfig::unitsPerTick, tca::TrajPoint::UseHit, tca::TCSlice::wireHitRange, and WireHitRangeOK().

Referenced by ChgFracNearPos(), and MakeHaloTj().

2553  {
2554  // Fills tp.Hits sets tp.UseHit true for hits that are close to tp.Pos. Returns true if there are
2555  // close hits OR if the wire at this position is dead
2556 
2557  tp.Hits.clear();
2558  tp.UseHit.reset();
2559  if(!WireHitRangeOK(slc, tp.CTP)) {
2560  return false;
2561  }
2562 
2563  geo::PlaneID planeID = DecodeCTP(tp.CTP);
2564  unsigned short ipl = planeID.Plane;
2565  if(tp.Pos[0] < -0.4) return false;
2566  unsigned int wire = std::nearbyint(tp.Pos[0]);
2567  if(wire < slc.firstWire[ipl]) return false;
2568  if(wire > slc.lastWire[ipl]-1) return false;
2569 
2570  // dead wire
2571  if(slc.wireHitRange[ipl][wire].first == -1) {
2572  tp.Environment[kEnvDeadWire] = true;
2573  return true;
2574  }
2575  tp.Environment[kEnvDeadWire] = false;
2576  // live wire with no hits
2577  if(slc.wireHitRange[ipl][wire].first == -2) return false;
2578 
2579  unsigned int firstHit = (unsigned int)slc.wireHitRange[ipl][wire].first;
2580  unsigned int lastHit = (unsigned int)slc.wireHitRange[ipl][wire].second;
2581 
2582  float fwire = wire;
2583  for(unsigned int iht = firstHit; iht < lastHit; ++iht) {
2584  if((unsigned int)slc.slHits[iht].InTraj > slc.tjs.size()) continue;
2585  bool useit = (hitRequest == kAllHits);
2586  if(hitRequest == kUsedHits && slc.slHits[iht].InTraj > 0) useit = true;
2587  if(hitRequest == kUnusedHits && slc.slHits[iht].InTraj == 0) useit = true;
2588  if(!useit) continue;
2589  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2590  float ftime = tcc.unitsPerTick * hit.PeakTime();
2591  float delta = PointTrajDOCA(slc, fwire, ftime, tp);
2592  if(delta < maxDelta) tp.Hits.push_back(iht);
2593  } // iht
2594  if(tp.Hits.size() > 16) {
2595  tp.Hits.resize(16);
2596  }
2597  // Set UseHit false. The calling routine should decide if these hits should be used
2598  tp.UseHit.reset();
2599  return (!tp.Hits.empty());
2600 
2601  } // FindCloseHits
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
bool WireHitRangeOK(TCSlice &slc, const CTP_t &inCTP)
Definition: Utils.cxx:4085
float PointTrajDOCA(TCSlice &slc, float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2280
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
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)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
std::vector< int > tca::FindCloseTjs ( TCSlice slc,
const TrajPoint fromTp,
const TrajPoint toTp,
const float &  maxDelta 
)

Definition at line 2604 of file Utils.cxx.

References tca::TCEvent::allHits, tca::TrajPoint::CTP, DecodeCTP(), evt, tca::TCSlice::firstWire, tca::TCSlice::lastWire, MakeBareTrajPoint(), MoveTPToWire(), geo::PlaneID::Plane, tca::TrajPoint::Pos, tca::TCSlice::slHits, tcc, tca::TCSlice::tjs, tmp, tca::TCConfig::unitsPerTick, and tca::TCSlice::wireHitRange.

Referenced by MakeJunkVertices().

2605  {
2606  // Returns a list of Tj IDs that have hits within distance maxDelta on a line drawn between the two Tps as shown
2607  // graphically here, where a "*" is a Tp and "|" and "-" are the boundaries of the region that is checked
2608  //
2609  // ---------------
2610  // | |
2611  // * *
2612  // | |
2613  // ---------------
2614  // If the wire positions of fromTp and toTp are the same, a different region is checked as shown here
2615  //
2616  // -----------
2617  // | |
2618  // | * |
2619  // | |
2620  // -----------
2621 
2622  std::vector<int> tmp;
2623  if(fromTp.Pos[0] < -0.4 || toTp.Pos[0] < -0.4) return tmp;
2624 
2625  TrajPoint tp;
2626  // Make the tp so that stepping is positive
2627  unsigned int firstWire, lastWire;
2628  if(toTp.Pos[0] > fromTp.Pos[0]) {
2629  if(!MakeBareTrajPoint(slc, fromTp, toTp, tp)) return tmp;
2630  firstWire = std::nearbyint(fromTp.Pos[0]);
2631  lastWire = std::nearbyint(toTp.Pos[0]);
2632  } else if(toTp.Pos[0] < fromTp.Pos[0]) {
2633  if(!MakeBareTrajPoint(slc, toTp, fromTp, tp)) return tmp;
2634  firstWire = std::nearbyint(toTp.Pos[0]);
2635  lastWire = std::nearbyint(fromTp.Pos[0]);
2636  } else {
2637  tp.Pos = fromTp.Pos;
2638  float tmp = fromTp.Pos[0] - maxDelta;
2639  if(tmp < 0) tmp = 0;
2640  firstWire = std::nearbyint(tmp);
2641  tmp = fromTp.Pos[0] + maxDelta;
2642  lastWire = std::nearbyint(tmp);
2643  }
2644 
2645  geo::PlaneID planeID = DecodeCTP(tp.CTP);
2646  unsigned short ipl = planeID.Plane;
2647 
2648  if(firstWire < slc.firstWire[ipl]) firstWire = slc.firstWire[ipl];
2649  if(firstWire > slc.lastWire[ipl]-1) return tmp;
2650  if(lastWire < slc.firstWire[ipl]) return tmp;
2651  if(lastWire > slc.lastWire[ipl]-1) lastWire = slc.lastWire[ipl]-1;
2652 
2653  for(unsigned int wire = firstWire; wire <= lastWire; ++wire) {
2654  if(slc.wireHitRange[ipl][wire].first == -1) continue;
2655  if(slc.wireHitRange[ipl][wire].first == -2) continue;
2656  MoveTPToWire(tp, (float)wire);
2657  // Find the tick range at this position
2658  float minTick = (tp.Pos[1] - maxDelta) / tcc.unitsPerTick;
2659  float maxTick = (tp.Pos[1] + maxDelta) / tcc.unitsPerTick;
2660  unsigned int firstHit = (unsigned int)slc.wireHitRange[ipl][wire].first;
2661  unsigned int lastHit = (unsigned int)slc.wireHitRange[ipl][wire].second;
2662  for(unsigned int iht = firstHit; iht < lastHit; ++iht) {
2663  if(slc.slHits[iht].InTraj <= 0) continue;
2664  if((unsigned int)slc.slHits[iht].InTraj > slc.tjs.size()) continue;
2665  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2666  if(hit.PeakTime() < minTick) continue;
2667  // Hits are sorted by increasing time so we can break when maxTick is reached
2668  if(hit.PeakTime() > maxTick) break;
2669  if(std::find(tmp.begin(), tmp.end(), slc.slHits[iht].InTraj) != tmp.end()) continue;
2670  tmp.push_back(slc.slHits[iht].InTraj);
2671  } // iht
2672  } // wire
2673 
2674  return tmp;
2675 
2676  } // FindCloseTjs
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
Float_t tmp
Definition: plot.C:37
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
Detector simulation of raw signals on wires.
bool MakeBareTrajPoint(TCSlice &slc, const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
Definition: Utils.cxx:3628
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2485
TCEvent evt
Definition: DataStructs.cxx:5
void tca::FindCompleteness ( TCSlice slc,
PFPStruct pfp,
bool  doFit,
bool  fillTp3s,
bool  prt 
)

Definition at line 737 of file PFPUtils.cxx.

References tca::TrajPoint3::AlongTrans, geo::CryostatID::Cryostat, DecodeCTP(), dir, tca::TrajPoint3::Dir, tca::PFPStruct::Dir, tca::PFPStruct::EffPur, trkf::fill(), FindAlongTrans(), Fit3D(), tca::TCConfig::geom, tca::PFPStruct::ID, MakeTp3(), tca::TCSlice::mallTraj, tca::TCConfig::match3DCuts, tca::TCSlice::nPlanes, geo::PlaneID::Plane, tca::TrajPoint3::Pos, tcc, tca::TrajPoint3::Tj2Pts, tca::PFPStruct::TjCompleteness, tca::PFPStruct::TjIDs, tca::TCSlice::tjs, tmp, tca::PFPStruct::Tp3s, geo::TPCID::TPC, geo::GeometryCore::WireCoordinate(), tca::TCSlice::wireHitRange, and tca::PFPStruct::XYZ.

Referenced by DefinePFP(), and FindPFParticles().

738  {
739  // Calculate the 3D-matching completeness of the set of Tjs in pfp.TjIDs and store in pfp.EffPur.
740  // The completeness for each Tj is put in pfp.TjCompleteness. The TP-weighted average completeness
741  // is put in pfp.EffPur. This function also fits the matching points to a 3D line and puts the
742  // position and direction in pfp.XYZ[0] and pfp.Dir[0]. The pfp.TP3s vector is optionally filled.
743 
744  if(pfp.TjIDs.size() < 2) return;
745  if(tcc.match3DCuts[0] <= 0) return;
746  // This function uses mallTraj but it isn't necessarily a failure if it doesn't exist
747  if(slc.mallTraj.size() < 6) return;
748 
749  pfp.TjCompleteness.resize(pfp.TjIDs.size());
750  std::fill(pfp.TjCompleteness.begin(), pfp.TjCompleteness.end(), 0);
751  if(fillTp3s) pfp.Tp3s.clear();
752 
753  bool twoPlanes = (slc.nPlanes == 2);
754  bool twoTjs = (pfp.TjIDs.size() == 2);
755  // decide if special handling of small angle pfps is required when filling Tp3s
756  bool smallAngle = false;
757  if(fillTp3s) {
758  smallAngle = (pfp.Dir[0][0] != 0 && std::abs(pfp.Dir[0][0]) < 0.1);
759 // if(pfp.Dir[0][0] == 0 && slc.DebugMode) std::cout<<"P"<<pfp.ID<<" Dir[0] isn't defined\n";
760  }
761  double yzcut = 1.5 * tcc.match3DCuts[0];
762 
763  // initialize the fit sums
764  Point3_t point;
765  Vector3_t dir;
766  if(doFit) Fit3D(0, point, dir, point, dir);
767 
768  // create a vector of bools for each tj for points that are matched in 3D
769  // cast the IDs into an unsigned short for faster comparing
770  std::vector<unsigned short> tjids(pfp.TjIDs.size());
771  // This vector is for matches in 3 planes
772  std::vector<std::vector<bool>> tjptMat3;
773  // This vector is for matches in 2 planes
774  std::vector<std::vector<bool>> tjptMat2;
775  // and the plane index
776  std::vector<unsigned short> tjplane;
777  // Set a maximum size for the TP3s vector
778  unsigned int maxTp3Size = 10000;
779  // Initialize the vectors
780  for(unsigned short itj = 0; itj < pfp.TjIDs.size(); ++itj) {
781  if(pfp.TjIDs[itj] <= 0) {
782  std::cout<<"FindCompleteness: Bad tjid "<<pfp.TjIDs[itj]<<"\n";
783  return;
784  }
785  tjids[itj] = pfp.TjIDs[itj];
786  auto& tj = slc.tjs[pfp.TjIDs[itj] - 1];
787  std::vector<bool> tmp(tj.Pts.size(), false);
788  tjptMat2.push_back(tmp);
789  if(!twoPlanes) tjptMat3.push_back(tmp);
790  tjplane.push_back(DecodeCTP(tj.CTP).Plane);
791  } // tjid
792 
793  for(unsigned int ipt = 0; ipt < slc.mallTraj.size() - 1; ++ipt) {
794  auto& iTjPt = slc.mallTraj[ipt];
795  unsigned short indx = 0;
796  for(indx = 0; indx < tjids.size(); ++indx) if(iTjPt.id == tjids[indx]) break;
797  // require that the Tj ID of this point be in the list
798  if(indx == tjids.size()) continue;
799  auto& itj = slc.tjs[iTjPt.id - 1];
800 // if(itj.AlgMod[kMat3D]) continue;
801  auto& itp = itj.Pts[iTjPt.ipt];
802  unsigned short iplane = DecodeCTP(itp.CTP).Plane;
803  unsigned short tpc = DecodeCTP(itp.CTP).TPC;
804  unsigned short cstat = DecodeCTP(itp.CTP).Cryostat;
805  for(unsigned int jpt = ipt + 1; jpt < slc.mallTraj.size() - 1; ++jpt) {
806  auto& jTjPt = slc.mallTraj[jpt];
807  // ensure that the planes are different
808  if(jTjPt.ctp == iTjPt.ctp) continue;
809  unsigned short jndx = 0;
810  for(jndx = 0; jndx < tjids.size(); ++jndx) if(jTjPt.id == tjids[jndx]) break;
811  // require that the Tj ID of this point be in the list
812  if(jndx == tjids.size()) continue;
813  // check for x range overlap. We know that jTjPt.xlo is > iTjPt.xlo because of the sort
814  if(jTjPt.xlo > iTjPt.xhi) continue;
815  // break out if the x range difference becomes large (5 cm)
816  if(jTjPt.xlo > iTjPt.xhi + 5) break;
817  auto& jtj = slc.tjs[jTjPt.id - 1];
818 // if(jtj.AlgMod[kMat3D]) continue;
819  auto& jtp = jtj.Pts[jTjPt.ipt];
820  TrajPoint3 ijtp3;
821  if(!MakeTp3(slc, itp, jtp, ijtp3, true)) continue;
822  ijtp3.Tj2Pts.resize(2);
823  ijtp3.Tj2Pts[0] = iTjPt;
824  ijtp3.Tj2Pts[1] = jTjPt;
825  // Set the 2-plane match bits
826  tjptMat2[indx][iTjPt.ipt] = true;
827  tjptMat2[jndx][jTjPt.ipt] = true;
828  if(twoPlanes) {
829  if(fillTp3s && pfp.Tp3s.size() < maxTp3Size) {
830  bool saveIt = true;
831  FindAlongTrans(pfp.XYZ[0], pfp.Dir[0], ijtp3.Pos, ijtp3.AlongTrans);
832  // cut on transverse distance
833  if(smallAngle) saveIt = ijtp3.AlongTrans[1] < 1;
834  if(saveIt) pfp.Tp3s.push_back(ijtp3);
835  }
836  if(doFit) Fit3D(1, ijtp3.Pos, ijtp3.Dir, point, dir);
837  continue;
838  }
839  // count it as a triple if this point is in a dead region
840  unsigned short jplane = DecodeCTP(jtp.CTP).Plane;
841  unsigned short kplane = 3 - iplane - jplane;
842  float fwire = tcc.geom->WireCoordinate(ijtp3.Pos[1], ijtp3.Pos[2], kplane, tpc, cstat);
843  if(fwire < -0.4) continue;
844  unsigned int kwire = std::nearbyint(fwire);
845  if(kwire < slc.wireHitRange[kplane].size() && slc.wireHitRange[kplane][kwire].first == -1) {
846  // accumulate the fit sums
847  if(doFit) Fit3D(1, ijtp3.Pos, ijtp3.Dir, point, dir);
848  // fill Tp3s?
849  if(fillTp3s && pfp.Tp3s.size() < maxTp3Size) {
850  bool saveIt = true;
851  FindAlongTrans(pfp.XYZ[0], pfp.Dir[0], ijtp3.Pos, ijtp3.AlongTrans);
852  if(smallAngle) saveIt = ijtp3.AlongTrans[1] < 1;
853  if(saveIt) pfp.Tp3s.push_back(ijtp3);
854  }
855  continue;
856  } // dead wire in kplane
857  for(unsigned int kpt = jpt + 1; kpt < slc.mallTraj.size(); ++kpt) {
858  auto& kTjPt = slc.mallTraj[kpt];
859  // ensure that the planes are different
860  if(kTjPt.ctp == iTjPt.ctp || kTjPt.ctp == jTjPt.ctp) continue;
861  // Look for this tj point in tjids
862  unsigned short kndx = 0;
863  for(kndx = 0; kndx < tjids.size(); ++kndx) if(kTjPt.id == tjids[kndx]) break;
864  // require that the Tj ID of this point be in the list if we aren't filling the Tp3s
865  if(!fillTp3s && kndx == tjids.size()) continue;
866  if(kTjPt.xlo > iTjPt.xhi) continue;
867  // break out if the x range difference becomes large
868  if(kTjPt.xlo > iTjPt.xhi + 5) break;
869  auto& ktj = slc.tjs[kTjPt.id - 1];
870 // if(ktj.AlgMod[kMat3D]) continue;
871  auto& ktp = ktj.Pts[kTjPt.ipt];
872  TrajPoint3 iktp3;
873  if(!MakeTp3(slc, itp, ktp, iktp3, true)) continue;
874  if(std::abs(ijtp3.Pos[1] - iktp3.Pos[1]) > yzcut) continue;
875  if(std::abs(ijtp3.Pos[2] - iktp3.Pos[2]) > yzcut) continue;
876  // make a copy of ijtp3 -> ijktp3
877  auto ijktp3 = ijtp3;
878  // add the Tj2Pt to it
879  ijktp3.Tj2Pts.push_back(kTjPt);
880  // accumulate the fit sums
881  if(doFit) Fit3D(1, iktp3.Pos, iktp3.Dir, point, dir);
882  // fill Tp3s?
883  if(fillTp3s && pfp.Tp3s.size() < maxTp3Size) {
884  // update the charge
885  ijktp3.dEdx = (2 * ijktp3.dEdx + ktp.Chg) / 3;
886  bool saveIt = true;
887  FindAlongTrans(pfp.XYZ[0], pfp.Dir[0], ijktp3.Pos, ijktp3.AlongTrans);
888  if(smallAngle) saveIt = ijktp3.AlongTrans[1] < 1;
889  if(saveIt) pfp.Tp3s.push_back(ijktp3);
890  }
891  // Set the 3-plane match bits
892  if(kndx == tjids.size()) continue;
893  tjptMat3[indx][iTjPt.ipt] = true;
894  tjptMat3[jndx][jTjPt.ipt] = true;
895  tjptMat3[kndx][kTjPt.ipt] = true;
896  } // kpt
897  } // jpt
898  } // ipt
899  // do the fit and put the results into the pfp
900  Fit3D(2, point, dir, pfp.XYZ[0], pfp.Dir[0]);
901  if(prt && doFit) {
902  mf::LogVerbatim myprt("TC");
903  myprt<<"FC: P"<<pfp.ID<<" fit pos "<<std::fixed<<std::setprecision(1)<<pfp.XYZ[0][0]<<" "<<pfp.XYZ[0][1]<<" "<<pfp.XYZ[0][2];
904  myprt<<" fit dir "<<std::setprecision(2)<<pfp.Dir[0][0]<<" "<<pfp.Dir[0][1]<<" "<<pfp.Dir[0][2];
905  myprt<<" Note: fit pos is the average position of all Tp3s - not the start or end.";
906  }
907  // now count the number of tj points were matched
908  // total number of points with charge in all Tjs
909  float tnpwc = 0;
910  // total number that are matched in 3D in 3 planes
911  float tcnt3 = 0;
912  // total number that are matched in 3D in 2 planes
913  float tcnt2 = 0;
914  for(unsigned short itj = 0; itj < tjids.size(); ++itj) {
915  auto& tj = slc.tjs[tjids[itj] - 1];
916  // counts for each tj
917  float npwc = 0;
918  float cnt2 = 0;
919  float cnt3 = 0;
920  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
921  if(tj.Pts[ipt].Chg <= 0) continue;
922  ++npwc;
923  if(tjptMat2[itj][ipt]) ++cnt2;
924  if(!twoPlanes && tjptMat3[itj][ipt]) ++cnt3;
925  } // ipt
926  if(twoTjs) {
927  pfp.TjCompleteness[itj] = cnt2 / npwc;
928  } else {
929  pfp.TjCompleteness[itj] = cnt3 / npwc;
930  }
931  tnpwc += npwc;
932  tcnt3 += cnt3;
933  tcnt2 += cnt2;
934  if(prt) {
935  mf::LogVerbatim myprt("TC");
936  myprt<<"FC: P"<<pfp.ID<<" T"<<tj.ID<<" npwc "<<npwc<<" cnt2 "<<cnt2<<" cnt3 "<<cnt3<<" PDGCode "<<tj.PDGCode;
937  myprt<<" MCSMom "<<tj.MCSMom<<" InShower? "<<tj.SSID;
938  myprt<<" TjCompleteness "<<std::setprecision(2)<<pfp.TjCompleteness[itj];
939  } // prt
940  } // itj
941  if(twoTjs) {
942  pfp.EffPur = tcnt2 / tnpwc;
943  } else {
944  pfp.EffPur = tcnt3 / tnpwc;
945  }
946 
947  } // FindCompleteness
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
void Fit3D(unsigned short mode, Point3_t point, Vector3_t dir, Point3_t &fitPos, Vector3_t &fitDir)
Definition: PFPUtils.cxx:1042
std::array< double, 3 > Point3_t
Definition: DataStructs.h:35
TCConfig tcc
Definition: DataStructs.cxx:6
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:2849
bool MakeTp3(TCSlice &slc, const TrajPoint &itp, const TrajPoint &jtp, TrajPoint3 &tp3, bool findDirection)
Definition: PFPUtils.cxx:1555
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
Float_t tmp
Definition: plot.C:37
std::vector< float > match3DCuts
3D matching cuts
Definition: DataStructs.h:476
void fill(const art::PtrVector< recob::Hit > &hits, int only_plane)
const geo::GeometryCore * geom
Definition: DataStructs.h:493
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)
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,
TCSlice slc,
const CTP_t inCTP,
std::vector< std::vector< int >> &  tjLists,
bool  prt 
)

Definition at line 3416 of file TCShower.cxx.

References tca::TCConfig::chargeCuts, DontCluster(), GetAssns(), greaterThan(), tca::Trajectory::ID, tca::TCSlice::ID, kHaloTj, kKilled, kMat3D, kShowerLike, kShowerTj, tca::Trajectory::MCSMom, MCSMom(), NumPtsWithCharge(), PFPDOCA(), tca::TCSlice::pfps, PosSep(), SetIntersection(), ShowerEnergy(), tca::TCConfig::showerTag, t1, t2, tcc, tca::TCSlice::tjs, tmp, TrajTrajDOCA(), and tca::TCConfig::wirePitch.

Referenced by FindShowers3D().

3417  {
3418  // Version 2 of TagShowerLike to try to improve the separation between close showers, e.g. from pi-zeros
3419  tjLists.clear();
3420  if(tcc.showerTag[0] <= 0) return;
3421 
3422  // take the average of the low and high charge RMS range to use as a cut
3423  float typicalChgRMS = 0.5 * (tcc.chargeCuts[1] + tcc.chargeCuts[2]);
3424 
3425  // clear out old tags and make a list of Tjs to consider
3426  std::vector<int> tjids;
3427  for(auto& tj : slc.tjs) {
3428  if(tj.CTP != inCTP) continue;
3429  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
3430  tj.AlgMod[kShowerLike] = false;
3431  if(tj.AlgMod[kShowerTj]) continue;
3432  short npwc = NumPtsWithCharge(slc, tj, false);
3433  // Don't expect any (primary) electron to be reconstructed as a single trajectory for
3434  // more than ~2 radiation lengths ~ 30 cm for uB ~ 100 wires
3435  if(npwc > 100) continue;
3436  // check MCSMom for longish Tjs
3437  if(npwc > 5) {
3438  // Increase the MCSMom cut if the Tj is long and the charge RMS is high to reduce sensitivity
3439  // to the fcl configuration. A primary electron may be reconstructed as one long Tj with large
3440  // charge rms and possibly high MCSMom or as several nearby shorter Tjs with lower charge rms
3441  float momCut = tcc.showerTag[1];
3442  if(tj.ChgRMS > typicalChgRMS) momCut *= tj.ChgRMS / typicalChgRMS;
3443  if(tj.MCSMom > momCut) continue;
3444  }
3445  // see if this tj is in a muon pfparticle that looks shower-like in this view
3446  if(tj.AlgMod[kMat3D]) {
3447  auto TInP = GetAssns(slc, "T", tj.ID, "P");
3448  if(!TInP.empty()) {
3449  auto& pfp = slc.pfps[TInP[0] - 1];
3450  if(pfp.PDGCode == 13 && MCSMom(slc, pfp.TjIDs) > 500) continue;
3451  } // TInP not empty
3452  } // 3D-matched
3453  tjids.push_back(tj.ID);
3454  } // tj
3455 
3456  if(tjids.size() < 2) return;
3457 
3458  struct ClosePair {
3459  float doca; // distance of closest approach between the tj pair
3460  int id1; // id of the first tj
3461  int id2; // id of the second tj
3462  unsigned short closePt1; // index of the closest point on tj1
3463  unsigned short closePt2; // index of the closest point on tj2
3464  bool used; // set true when this pair is used
3465  };
3466  // min separation between tjs
3467  std::vector<ClosePair> cps;
3468  // list of tjs that are close
3469  std::vector<int> closeTjs;
3470  for(unsigned short it1 = 0; it1 < tjids.size() - 1; ++it1) {
3471  Trajectory& t1 = slc.tjs[tjids[it1] - 1];
3472  bool t1TrackLike = (t1.MCSMom > tcc.showerTag[1]);
3473  auto T1InP = GetAssns(slc, "T", t1.ID, "P");
3474  for(unsigned short it2 = it1 + 1; it2 < tjids.size(); ++it2) {
3475  Trajectory& t2 = slc.tjs[tjids[it2] - 1];
3476  // require one of them to be not tracklike
3477  bool t2TrackLike = (t2.MCSMom > tcc.showerTag[1]);
3478  if(t1TrackLike && t2TrackLike) continue;
3479  unsigned short ipt1, ipt2;
3480  float doca = tcc.showerTag[2];
3481  // Find the separation between Tjs without considering dead wires
3482  TrajTrajDOCA(slc, t1, t2, ipt1, ipt2, doca, false);
3483  if(doca == tcc.showerTag[2]) continue;
3484  // see if they are close in 3D if that information exists
3485  if(!T1InP.empty()) {
3486  auto T2InP = GetAssns(slc, "T", t2.ID, "P");
3487  if(!T2InP.empty()) {
3488  auto& p1 = slc.pfps[T1InP[0] - 1];
3489  auto& p2 = slc.pfps[T2InP[0] - 1];
3490  unsigned short closePt1, closePt2;
3491  float doca = PFPDOCA(p1, p2, closePt1, closePt2);
3492 // float costh = DotProd(p1.Dir[0], p2.Dir[0]);
3493 // std::cout<<"chk T"<<t1.ID<<" T"<<t2.ID<<" doca "<<doca<<" costh "<<costh<<"\n";
3494  if(doca > tcc.showerTag[2] * tcc.wirePitch) continue;
3495  } // !T2InP.empty()
3496  } // !T1InP.empty()
3497 
3498  // add a new one
3499  ClosePair cp;
3500  cp.doca = doca;
3501  cp.id1 = t1.ID;
3502  cp.closePt1 = ipt1;
3503  cp.id2 = t2.ID;
3504  cp.closePt2 = ipt2;
3505  cp.used = false;
3506  cps.push_back(cp);
3507  if(std::find(closeTjs.begin(), closeTjs.end(), t1.ID) == closeTjs.end()) closeTjs.push_back(t1.ID);
3508  if(std::find(closeTjs.begin(), closeTjs.end(), t2.ID) == closeTjs.end()) closeTjs.push_back(t2.ID);
3509  } // it2 (t2)
3510  } // it1 (t1)
3511 
3512  if(cps.empty()) return;
3513 
3514  // sort tjList by decreasing length
3515  std::vector<SortEntry> sortVec(closeTjs.size());
3516  for(unsigned short ii = 0; ii < closeTjs.size(); ++ii) {
3517  sortVec[ii].index = ii;
3518  auto& tj = slc.tjs[closeTjs[ii] - 1];
3519  sortVec[ii].length = PosSep(tj.Pts[tj.EndPt[0]].Pos, tj.Pts[tj.EndPt[1]].Pos);
3520  } // ii
3521  std::sort(sortVec.begin(), sortVec.end(), greaterThan);
3522 
3523 
3524  // cluster them starting with the longest
3525  // a temp vector for DontCluster
3526  std::vector<int> tmp(1);
3527  for(unsigned short ii = 0; ii < sortVec.size(); ++ii) {
3528  unsigned short indx = sortVec[ii].index;
3529  auto& t1 = slc.tjs[closeTjs[indx] - 1];
3530  // already tagged?
3531  if(t1.AlgMod[kShowerLike]) continue;
3532 // float t1Len = sortVec[ii].length;
3533  // get the general direction
3534 // auto t1Dir = PointDirection(t1.Pts[t1.EndPt[0]].Pos, t1.Pts[t1.EndPt[1]].Pos);
3535  // start a list of clustered tjs
3536  std::vector<int> tlist;
3537  tlist.push_back(t1.ID);
3538  // try to add other close tjs
3539  bool added = true;
3540  while(added) {
3541  added = false;
3542  for(auto& cp : cps) {
3543  if(cp.used) continue;
3544  // is any ID in tlist equal to cp.id1 or cp.id2?
3545  bool isID1 = (std::find(tlist.begin(), tlist.end(), cp.id1) != tlist.end());
3546  bool isID2 = (std::find(tlist.begin(), tlist.end(), cp.id2) != tlist.end());
3547  if(!(isID1 || isID2)) continue;
3548  // determine which one is not in tlist and call it t2
3549  unsigned short t2id = cp.id1;
3550  if(isID1) t2id = cp.id2;
3551  auto& t2 = slc.tjs[t2id - 1];
3552  // already tagged?
3553  if(t2.AlgMod[kShowerLike]) continue;
3554  tmp[0] = t2.ID;
3555  if(DontCluster(slc, tmp, tlist)) continue;
3556  // don't cluster if this tj is closer to another long tj
3557  bool isCloser = false;
3558  for(auto& pcp : cps) {
3559  if(t1.ID == pcp.id1 || t1.ID == pcp.id2) continue;
3560  if(!(t2.ID == pcp.id1 || t2.ID == pcp.id2)) continue;
3561  unsigned short oid = pcp.id1;
3562  if(oid == t2.ID) oid = pcp.id2;
3563  auto otj = slc.tjs[oid - 1];
3564  float otjLen = PosSep(otj.Pts[otj.EndPt[0]].Pos, otj.Pts[otj.EndPt[1]].Pos);
3565 // std::cout<<"tid1 T"<<t1.ID<<" tid2 T"<<t2.ID<<" oid T"<<oid<<"\n";
3566  if(pcp.doca < cp.doca && otjLen > 10) isCloser = true;
3567  } // pcp
3568  if(isCloser) continue;
3569  if(std::find(tlist.begin(), tlist.end(), t2.ID) != tlist.end()) continue;
3570 // std::cout<<" add T"<<t2.ID<<" to "<<tjLists.size()<<"\n";
3571  tlist.push_back(t2.ID);
3572  // call it used
3573  cp.used = true;
3574  added = true;
3575  } // cp
3576  } // added
3577  if(tlist.size() > 1) {
3578  // tag them
3579  for(auto tjid : tlist) {
3580  auto& tj = slc.tjs[tjid - 1];
3581  tj.AlgMod[kShowerLike] = true;
3582  } // tjid
3583  // ignore wimpy cots (< 10 MeV)
3584  if(ShowerEnergy(slc, tlist) < 10) continue;
3585  tjLists.push_back(tlist);
3586  } // tlist.size() > 1
3587  } // ii
3588 /* This causes problems later on
3589  // Check for leftover tjs and add them if they are shower-like
3590  for(auto tjid : closeTjs) {
3591  auto& tj = slc.tjs[tjid - 1];
3592  if(tj.AlgMod[kShowerLike]) continue;
3593  std::vector<int> tlist(1, tjid);
3594  tj.AlgMod[kShowerLike] = true;
3595  // ignore wimpy cots (< 10 MeV)
3596  if(ShowerEnergy(slc, tlist) < 10) continue;
3597  tjLists.push_back(tlist);
3598  } // tjid
3599 */
3600  if(tjLists.size() < 2) return;
3601  // check consistency
3602  for(unsigned short ip = 0; ip < tjLists.size() - 1; ++ip) {
3603  auto& ilist = tjLists[ip];
3604  for(unsigned short jp = ip + 1; jp < tjLists.size(); ++jp) {
3605  auto& jlist = tjLists[jp];
3606  auto sij = SetIntersection(ilist, jlist);
3607  if(!sij.empty()) {
3608  std::cout<<"******** FindCots conflict:";
3609  for(auto tid : sij) std::cout<<" T"<<tid;
3610  std::cout<<" appears in multiple lists\n";
3611  }
3612  } // jp
3613  } // ip
3614 /*
3615  std::cout<<"FindCots inCTP "<<inCTP<<" tjLists size "<<tjLists.size()<<"\n";
3616  for(unsigned short ip = 0; ip < tjLists.size(); ++ip) {
3617  auto& tlist = tjLists[ip];
3618  std::cout<<"ip "<<ip;
3619  for(auto tid : tlist) {
3620  std::cout<<" T"<<tid;
3621  auto plist = GetAssns(slc, "T", tid, "P");
3622  if(!plist.empty()) std::cout<<"_P"<<plist[0];
3623  }
3624  std::cout<<"\n";
3625  } // ip
3626 */
3627 
3628  } // FindCots
bool greaterThan(SortEntry c1, SortEntry c2)
Definition: TCShower.cxx:9
TTree * t1
Definition: plottest35.C:26
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4279
short MCSMom(TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2914
TCConfig tcc
Definition: DataStructs.cxx:6
float PFPDOCA(const PFPStruct &pfp1, const PFPStruct &pfp2, unsigned short &close1, unsigned short &close2)
Definition: PFPUtils.cxx:1790
Float_t tmp
Definition: plot.C:37
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:231
bool DontCluster(TCSlice &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3313
bool TrajTrajDOCA(TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2175
std::vector< float > showerTag
[min MCSMom, max separation, min # Tj < separation] for a shower tag
Definition: DataStructs.h:474
float ShowerEnergy(TCSlice &slc, const std::vector< int > tjIDs)
Definition: TCShower.cxx:4382
TTree * t2
Definition: plottest35.C:36
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
std::vector< float > chargeCuts
Definition: DataStructs.h:478
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
void tca::FindHammerVertices ( TCSlice slc,
const CTP_t inCTP 
)

Definition at line 1154 of file TCVertex.cxx.

References ChgFracNearPos(), tca::VtxStore::ChiDOF, tca::VtxStore::CTP, tca::TCConfig::dbgAlg, tca::TCConfig::dbgSlc, DeltaAngle(), GetAssns(), tca::VtxStore::ID, tca::TCSlice::ID, kDebug, kHaloTj, kHamVx, kJunkTj, kKilled, kNewVtxCuts, kShowerLike, tca::TCConfig::modes, tca::VtxStore::NTraj, tca::VtxStore::Pass, tca::VtxStore::Pos, SetPDGCode(), SetVx2Score(), SplitTraj(), StoreVertex(), tcc, tca::TCSlice::tjs, tca::VtxStore::Topo, TrajPointTrajDOCA(), tca::TCConfig::useAlg, and tca::TCSlice::vtxs.

Referenced by Find2DVertices().

1155  {
1156  // Look for a trajectory that intersects another. Split
1157  // the trajectory and make a vertex. The convention used
1158  // is shown pictorially here. Trajectory tj1 must be longer
1159  // than tj2
1160  // tj2 ------
1161  // tj1 /
1162  // tj1 /
1163  // tj1 /
1164 
1165  if(!tcc.useAlg[kHamVx]) return;
1166 
1167  bool prt = (tcc.modes[kDebug] && tcc.dbgSlc && tcc.dbgAlg[kHamVx]);
1168 
1169  for(unsigned short it1 = 0; it1 < slc.tjs.size(); ++it1) {
1170  if(slc.tjs[it1].CTP != inCTP) continue;
1171  if(slc.tjs[it1].AlgMod[kKilled] || slc.tjs[it1].AlgMod[kHaloTj]) continue;
1172  if(slc.tjs[it1].AlgMod[kShowerLike]) continue;
1173  if(slc.tjs[it1].AlgMod[kJunkTj]) continue;
1174  if(slc.tjs[it1].PDGCode == 111) continue;
1175  // minimum length requirements
1176  unsigned short tj1len = slc.tjs[it1].EndPt[1] - slc.tjs[it1].EndPt[0] + 1;
1177  if(tj1len < 5) continue;
1178  // Check each end of tj1
1179  bool didaSplit = false;
1180  for(unsigned short end1 = 0; end1 < 2; ++end1) {
1181  // vertex assignment exists?
1182  if(slc.tjs[it1].VtxID[end1] > 0) continue;
1183  unsigned short endPt1 = slc.tjs[it1].EndPt[end1];
1184  for(unsigned short it2 = 0; it2 < slc.tjs.size(); ++it2) {
1185  if(slc.tjs[it2].CTP != inCTP) continue;
1186  if(it1 == it2) continue;
1187  if(slc.tjs[it2].AlgMod[kKilled] || slc.tjs[it2].AlgMod[kHaloTj]) continue;
1188  if(slc.tjs[it2].AlgMod[kJunkTj]) continue;
1189  if(slc.tjs[it2].PDGCode == 111) continue;
1190  // length of tj2 cut
1191  unsigned short tj2len = slc.tjs[it2].EndPt[1] - slc.tjs[it2].EndPt[0] + 1;
1192  if(tj2len < 6) continue;
1193  // ignore if tj1 is a lot shorter than tj2
1194 // if(tj1len < 0.5 * tj2len) continue;
1195  // ignore very long straight trajectories (probably a cosmic muon)
1196  unsigned short end20 = slc.tjs[it2].EndPt[0];
1197  unsigned short end21 = slc.tjs[it2].EndPt[1];
1198  if(tcc.useAlg[kNewVtxCuts]) {
1199  if(tj2len > 200 && slc.tjs[it2].PDGCode == 13) continue;
1200  } else {
1201  if(tj2len > 100 && DeltaAngle(slc.tjs[it2].Pts[end20].Ang, slc.tjs[it2].Pts[end21].Ang) < 0.2) continue;
1202  }
1203  // Require no vertex associated with itj2
1204 // if(slc.tjs[it2].VtxID[0] > 0 || slc.tjs[it2].VtxID[1] > 0) continue;
1205  float minDOCA = 5;
1206  float doca = minDOCA;
1207  unsigned short closePt2 = 0;
1208  TrajPointTrajDOCA(slc, slc.tjs[it1].Pts[endPt1], slc.tjs[it2], closePt2, doca);
1209  if(doca == minDOCA) continue;
1210  // ensure that the closest point is not near an end
1211  if(prt) mf::LogVerbatim("TC")<<"FHV: Candidate t"<<slc.tjs[it1].ID<<" t"<<slc.tjs[it2].ID<<" doca "<<doca<<" tj2.EndPt[0] "<<slc.tjs[it2].EndPt[0]<<" closePt2 "<<closePt2<<" tj2.EndPt[1] "<<slc.tjs[it2].EndPt[1];
1212  if(closePt2 < slc.tjs[it2].EndPt[0] + 3) continue;
1213  if(closePt2 > slc.tjs[it2].EndPt[1] - 3) continue;
1214  // make an angle cut
1215  float dang = DeltaAngle(slc.tjs[it1].Pts[endPt1].Ang, slc.tjs[it2].Pts[closePt2].Ang);
1216  if(prt) mf::LogVerbatim("TC")<<" dang "<<dang<<" imposing a hard cut of 0.4 for now ";
1217  if(dang < 0.4) continue;
1218  // check the cleanliness in this area
1219  std::vector<int> tjids(2);
1220  tjids[0] = slc.tjs[it1].ID;
1221  tjids[1] = slc.tjs[it2].ID;
1222  float chgFrac = ChgFracNearPos(slc, slc.tjs[it2].Pts[closePt2].Pos, tjids);
1223  if(prt) mf::LogVerbatim("TC")<<" chgFrac "<<chgFrac;
1224  if(chgFrac < 0.9) continue;
1225  // create a new vertex
1226  VtxStore aVtx;
1227  aVtx.Pos = slc.tjs[it2].Pts[closePt2].Pos;
1228  aVtx.NTraj = 3;
1229  aVtx.Pass = slc.tjs[it2].Pass;
1230  aVtx.Topo = 5;
1231  aVtx.ChiDOF = 0;
1232  aVtx.CTP = inCTP;
1233  aVtx.ID = slc.vtxs.size() + 1;
1234  if(!StoreVertex(slc, aVtx)) continue;
1235  unsigned short ivx = slc.vtxs.size() - 1;
1236  if(!SplitTraj(slc, it2, closePt2, ivx, prt)) {
1237  if(prt) mf::LogVerbatim("TC")<<"FHV: Failed to split trajectory";
1238  slc.vtxs.pop_back();
1239  continue;
1240  }
1241  slc.tjs[it1].VtxID[end1] = slc.vtxs[ivx].ID;
1242  slc.tjs[it1].AlgMod[kHamVx] = true;
1243  slc.tjs[it2].AlgMod[kHamVx] = true;
1244  unsigned short newTjIndex = slc.tjs.size() - 1;
1245  slc.tjs[newTjIndex].AlgMod[kHamVx] = true;
1246  SetVx2Score(slc);
1247  // Update the PDGCode for the chopped trajectory
1248  SetPDGCode(slc, it2, true);
1249  // and for the new trajectory
1250  SetPDGCode(slc, newTjIndex, true);
1251  if(prt) {
1252  auto& vx2 = slc.vtxs[ivx];
1253  mf::LogVerbatim myprt("TC");
1254  myprt<<" new 2V"<<vx2.ID<<" Score "<<vx2.Score<<" Tjs";
1255  auto tjlist = GetAssns(slc, "2V", vx2.ID, "T");
1256  for(auto tid : tjlist) myprt<<" t"<<tid;
1257  }
1258  didaSplit = true;
1259  break;
1260  } // tj2
1261  if(didaSplit) break;
1262  } // end1
1263  } // tj1
1264 
1265  } // FindHammerVertices
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4279
void TrajPointTrajDOCA(TCSlice &slc, TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
Definition: Utils.cxx:2155
TCConfig tcc
Definition: DataStructs.cxx:6
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1636
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:507
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:2093
void SetPDGCode(TCSlice &slc, unsigned short itj, bool tjDone)
Definition: Utils.cxx:3795
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
float ChgFracNearPos(TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2698
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2513
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:505
bool SplitTraj(TCSlice &slc, unsigned short itj, float XPos, bool makeVx2, bool prt)
Definition: Utils.cxx:2004
master switch for turning on debug mode
Definition: DataStructs.h:449
void tca::FindHammerVertices2 ( TCSlice slc,
const CTP_t inCTP 
)

Definition at line 979 of file TCVertex.cxx.

References AttachAnyTrajToVertex(), tca::VtxStore::ChiDOF, tca::VtxStore::CTP, tca::TCConfig::dbgAlg, tca::TCConfig::dbgSlc, DeltaAngle(), dir, tca::VtxStore::ID, kDebug, kHaloTj, kHamVx, kHamVx2, kJunkTj, kKilled, kNewVtxCuts, kShowerLike, MCSMom(), tca::TCConfig::modes, MoveTPToWire(), tca::VtxStore::NTraj, NumPtsWithCharge(), tca::VtxStore::Pass, PointTrajDOCA(), tca::VtxStore::Pos, PosSep(), PrintPos(), SetPDGCode(), SetVx2Score(), SignalAtTp(), SplitTraj(), StoreVertex(), tcc, tca::TCSlice::tjs, tmp, tca::VtxStore::Topo, TrajClosestApproach(), TrajIntersection(), TrajPointTrajDOCA(), tca::TCConfig::unitsPerTick, tca::TCConfig::useAlg, and tca::TCSlice::vtxs.

Referenced by Find2DVertices().

980  {
981  // Variant of FindHammerVertices with slightly different requirements:
982  // 1) tj1 is a straight trajectory with most of the points fit
983  // 2) No angle requirement between tj1 and tj2
984  // 3) Large charge near the intersection point X on tj2
985  // tj2 ---X---
986  // tj1 /
987  // tj1 /
988  // tj1 /
989  // minimum^2 DOCA of tj1 endpoint with tj2
990 
991  if(!tcc.useAlg[kHamVx2]) return;
992 
993  bool prt = (tcc.modes[kDebug] && tcc.dbgSlc && tcc.dbgAlg[kHamVx2]);
994  if(prt) mf::LogVerbatim("TC")<<"Inside HamVx2";
995 
996  for(unsigned short it1 = 0; it1 < slc.tjs.size(); ++it1) {
997  if(slc.tjs[it1].CTP != inCTP) continue;
998  if(slc.tjs[it1].AlgMod[kKilled] || slc.tjs[it1].AlgMod[kHaloTj]) continue;
999  if(slc.tjs[it1].AlgMod[kHamVx]) continue;
1000  if(slc.tjs[it1].AlgMod[kHamVx2]) continue;
1001  if(slc.tjs[it1].AlgMod[kJunkTj]) continue;
1002  if(slc.tjs[it1].PDGCode == 111) continue;
1003  unsigned short numPtsWithCharge1 = NumPtsWithCharge(slc, slc.tjs[it1], false);
1004  if(numPtsWithCharge1 < 6) continue;
1005  // Check each end of tj1
1006  bool didaSplit = false;
1007  for(unsigned short end1 = 0; end1 < 2; ++end1) {
1008  // vertex assignment exists?
1009  if(slc.tjs[it1].VtxID[end1] > 0) continue;
1010  unsigned short endPt1 = slc.tjs[it1].EndPt[end1];
1011  for(unsigned short it2 = 0; it2 < slc.tjs.size(); ++it2) {
1012  if(it1 == it2) continue;
1013  if(slc.tjs[it2].AlgMod[kKilled] || slc.tjs[it2].AlgMod[kHaloTj]) continue;
1014  if(slc.tjs[it2].AlgMod[kHamVx]) continue;
1015  if(slc.tjs[it2].AlgMod[kHamVx2]) continue;
1016  // require that both be in the same CTP
1017  if(slc.tjs[it2].CTP != inCTP) continue;
1018  if(slc.tjs[it2].AlgMod[kShowerLike]) continue;
1019  if(slc.tjs[it2].AlgMod[kJunkTj]) continue;
1020  if(slc.tjs[it2].PDGCode == 111) continue;
1021  unsigned short numPtsWithCharge2 = NumPtsWithCharge(slc, slc.tjs[it2], true);
1022  if(numPtsWithCharge2 < 6) continue;
1023  // ignore muon-like tjs
1024  if(tcc.useAlg[kNewVtxCuts] && numPtsWithCharge2 > 100 && slc.tjs[it2].MCSMom > 500) continue;
1025  // Find the minimum separation between tj1 and tj2
1026  float minDOCA = 5;
1027  float doca = minDOCA;
1028  unsigned short closePt2 = 0;
1029  TrajPointTrajDOCA(slc, slc.tjs[it1].Pts[endPt1], slc.tjs[it2], closePt2, doca);
1030  if(doca == minDOCA) continue;
1031  if(prt) {
1032  mf::LogVerbatim myprt("TC");
1033  auto& tj1 = slc.tjs[it1];
1034  auto& tj2 = slc.tjs[it2];
1035  myprt<<" FHV2 CTP"<<tj1.CTP;
1036  myprt<<" t"<<tj1.ID<<"_"<<end1<<" MCSMom "<<tj1.MCSMom<<" ChgRMS "<<tj1.ChgRMS;
1037  myprt<<" split t"<<tj2.ID<<"? MCSMom "<<tj2.MCSMom<<" ChgRMS "<<tj2.ChgRMS;
1038  myprt<<" doca "<<doca<<" tj2.EndPt[0] "<<tj2.EndPt[0]<<" closePt2 "<<closePt2;
1039  myprt<<" tj2.EndPt[1] "<<tj2.EndPt[1];
1040  } // prt
1041  // ensure that the closest point is not near an end
1042  if(closePt2 < slc.tjs[it2].EndPt[0] + 3) continue;
1043  if(closePt2 > slc.tjs[it2].EndPt[1] - 3) continue;
1044  // Find the intersection point between the tj1 end and tj2 closest Pt
1045  float wint, tint;
1046  TrajIntersection(slc.tjs[it1].Pts[endPt1], slc.tjs[it2].Pts[closePt2], wint, tint);
1047  // make an angle cut
1048  float dang = DeltaAngle(slc.tjs[it1].Pts[endPt1].Ang, slc.tjs[it2].Pts[closePt2].Ang);
1049  if(dang < 0.2) continue;
1050  // ensure that tj1 doesn't cross tj2 but ensuring that the closest point on tj1 is at closePt1
1051  doca = 5;
1052  unsigned short closePt1 = 0;
1053  TrajPointTrajDOCA(slc, slc.tjs[it2].Pts[closePt2], slc.tjs[it1], closePt1, doca);
1054  if(closePt1 != endPt1) continue;
1055  if(prt) mf::LogVerbatim("TC")<<" intersection W:T "<<(int)wint<<":"<<(int)(tint/tcc.unitsPerTick)<<" dang "<<dang;
1056  // Find the point on tj2 that is closest to this point, overwriting closePt
1057  doca = minDOCA;
1058  // the point on tj2 that is closest to the intersection point
1059  unsigned short intPt2;
1060  TrajClosestApproach(slc.tjs[it2], wint, tint, intPt2, doca);
1061  if(prt) mf::LogVerbatim("TC")<<" intPt2 on tj2 "<<intPt2<<" at Pos "<<PrintPos(slc, slc.tjs[it2].Pts[intPt2])<<" doca "<<doca;
1062  if(doca == minDOCA) continue;
1063  // find the MCSMom for both sections of tj2
1064  float mcsmom = slc.tjs[it2].MCSMom;
1065  float mcsmom1 = MCSMom(slc, slc.tjs[it2], slc.tjs[it2].EndPt[0], intPt2);
1066  float mcsmom2 = MCSMom(slc, slc.tjs[it2], intPt2, slc.tjs[it2].EndPt[1]);
1067  // require that the both MCSMoms be greater than
1068  if(prt) mf::LogVerbatim("TC")<<" Check MCSMom after split: mcsmom1 "<<mcsmom1<<" mcsmom2 "<<mcsmom2;
1069  if(mcsmom1 < mcsmom || mcsmom2 < mcsmom) continue;
1070  // start scanning for the point on tj2 that has the best IP with the end of tj1 in the direction
1071  // from closePt2 -> endPt2
1072  short dir = 1;
1073  if(intPt2 < closePt2) dir = -1;
1074  unsigned short nit = 0;
1075  unsigned short ipt = intPt2;
1076  float mostChg = slc.tjs[it2].Pts[ipt].Chg;
1077  if(prt) mf::LogVerbatim("TC")<<" ipt "<<ipt<<" at Pos "<<PrintPos(slc, slc.tjs[it2].Pts[ipt])<<" chg "<<mostChg;
1078  while(nit < 20) {
1079  ipt += dir;
1080  if(ipt < 3 || ipt > slc.tjs[it2].Pts.size() - 4) break;
1081  float delta = PointTrajDOCA(slc, slc.tjs[it2].Pts[ipt].Pos[0], slc.tjs[it2].Pts[ipt].Pos[1], slc.tjs[it1].Pts[endPt1]);
1082  float sep = PosSep(slc.tjs[it2].Pts[ipt].Pos, slc.tjs[it1].Pts[endPt1].Pos);
1083  float dang = delta / sep;
1084  float pull = dang / slc.tjs[it1].Pts[endPt1].DeltaRMS;
1085  // if(prt) mf::LogVerbatim("TC")<<" intPt2 "<<intPt2<<" at Pos "<<PrintPos(slc, slc.tjs[it2].Pts[ipt])<<" delta "<<delta<<" chg "<<slc.tjs[it2].Pts[ipt].Chg<<" pull "<<pull;
1086  if(pull < 2 && slc.tjs[it2].Pts[ipt].Chg > mostChg) {
1087  mostChg = slc.tjs[it2].Pts[ipt].Chg;
1088  intPt2 = ipt;
1089  }
1090  }
1091  // require a lot of charge in tj2 in this vicinity compared with the average.
1092  float chgPull = (mostChg - slc.tjs[it2].AveChg) / slc.tjs[it2].ChgRMS;
1093  if(prt) mf::LogVerbatim("TC")<<" chgPull at intersection point "<<chgPull;
1094  if(chgPull < 10) continue;
1095  // require a signal on every wire between it1 and intPt2
1096  TrajPoint ltp = slc.tjs[it1].Pts[endPt1];
1097  if(slc.tjs[it1].Pts[endPt1].Pos[0] < -0.4) continue;
1098  unsigned int fromWire = std::nearbyint(slc.tjs[it1].Pts[endPt1].Pos[0]);
1099  if(slc.tjs[it2].Pts[intPt2].Pos[0] < -0.4) continue;
1100  unsigned int toWire = std::nearbyint(slc.tjs[it2].Pts[intPt2].Pos[0]);
1101  if(fromWire > toWire) {
1102  unsigned int tmp = fromWire;
1103  fromWire = toWire;
1104  toWire = tmp;
1105  }
1106  bool skipIt = false;
1107  for(unsigned int wire = fromWire + 1; wire < toWire; ++wire) {
1108  MoveTPToWire(ltp, (float)wire);
1109  if(!SignalAtTp(slc, ltp)) {
1110  skipIt = true;
1111  break;
1112  }
1113  } // wire
1114  if(skipIt) continue;
1115  // we have a winner
1116  // create a new vertex
1117  VtxStore aVtx;
1118  aVtx.Pos = slc.tjs[it2].Pts[intPt2].Pos;
1119  aVtx.NTraj = 3;
1120  aVtx.Pass = slc.tjs[it2].Pass;
1121  aVtx.Topo = 6;
1122  aVtx.ChiDOF = 0;
1123  aVtx.CTP = inCTP;
1124  aVtx.ID = slc.vtxs.size() + 1;
1125  unsigned short ivx = slc.vtxs.size();
1126  if(!StoreVertex(slc, aVtx)) continue;
1127  if(!SplitTraj(slc, it2, intPt2, ivx, prt)) {
1128  if(prt) mf::LogVerbatim("TC")<<"FHV2: Failed to split trajectory";
1129  // we can just remove the vertex since no Tj VtxID association has been made yet
1130  slc.vtxs.pop_back();
1131  continue;
1132  }
1133  slc.tjs[it1].VtxID[end1] = slc.vtxs[ivx].ID;
1134  slc.tjs[it1].AlgMod[kHamVx2] = true;
1135  slc.tjs[it2].AlgMod[kHamVx2] = true;
1136  unsigned short newTjIndex = slc.tjs.size() - 1;
1137  slc.tjs[newTjIndex].AlgMod[kHamVx2] = true;
1138  AttachAnyTrajToVertex(slc, ivx, prt);
1139  SetVx2Score(slc);
1140  // Update the PDGCode for the chopped trajectory
1141  SetPDGCode(slc, it2, true);
1142  // and for the new trajectory
1143  SetPDGCode(slc, newTjIndex, true);
1144  if(prt) mf::LogVerbatim("TC")<<" FHV2: New vtx 2V"<<slc.vtxs[ivx].ID<<" Score "<<slc.vtxs[ivx].Score;
1145  didaSplit = true;
1146  break;
1147  } // it2
1148  if(didaSplit) break;
1149  } // end1
1150  } // it1
1151  } // FindHammerVertices2
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void TrajPointTrajDOCA(TCSlice &slc, TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
Definition: Utils.cxx:2155
short MCSMom(TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2914
TCConfig tcc
Definition: DataStructs.cxx:6
bool TrajClosestApproach(Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
Definition: Utils.cxx:2377
bool AttachAnyTrajToVertex(TCSlice &slc, unsigned short ivx, bool prt)
Definition: TCVertex.cxx:1868
Float_t tmp
Definition: plot.C:37
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1636
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:507
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:2093
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
bool SignalAtTp(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:1814
void SetPDGCode(TCSlice &slc, unsigned short itj, bool tjDone)
Definition: Utils.cxx:3795
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
Definition: Utils.cxx:2299
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2513
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
TDirectory * dir
Definition: macro.C:5
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:505
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2485
bool SplitTraj(TCSlice &slc, unsigned short itj, float XPos, bool makeVx2, bool prt)
Definition: Utils.cxx:2004
master switch for turning on debug mode
Definition: DataStructs.h:449
std::vector< unsigned short > tca::FindKinks ( TCSlice slc,
PFPStruct pfp,
double  sep,
bool  prt 
)

Definition at line 1901 of file PFPUtils.cxx.

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

Referenced by DotProd(), and Split3DKink().

1902  {
1903  // returns a vector of indices in pfp.Tp3s where kinks exist. The kink angle is calculated using
1904  // Tp3s separated by +/- sep (cm)
1905  std::vector<unsigned short> kinkPts;
1906  // look for a kink angle greater than angCut
1907  double angCut = 0.3;
1908  double kang = 0;
1909  unsigned short kStart = USHRT_MAX;
1910  // foundKink is set true after a kink is found to skip past some number of points after the kink
1911  bool foundKink = false;
1912  double kinkSep2 = 2 * sep * sep;
1913  for(unsigned short ipt = 1; ipt < pfp.Tp3s.size(); ++ipt) {
1914  // skip ahead after a kink?
1915  if(foundKink) {
1916  // location of the previously found kink
1917  unsigned short kpt = kinkPts[kinkPts.size() - 1];
1918  if(foundKink && PosSep2(pfp.Tp3s[ipt].Pos, pfp.Tp3s[kpt].Pos) < kinkSep2) continue;
1919  }
1920  foundKink = false;
1921  double dang = KinkAngle(slc, pfp.Tp3s, ipt, sep);
1922  if(dang < angCut && kStart == USHRT_MAX) continue;
1923  // found a kink larger than the cut. See if this is the onset of a kink
1924  if(kStart == USHRT_MAX) {
1925  // onset of a kink
1926  kStart = ipt;
1927  } else {
1928  // a kink was found. Keep scanning until delta angle (dang) is less than the maximum (kang)
1929  if(dang < kang) {
1930  unsigned short klen = ipt - kStart;
1931  if(prt) mf::LogVerbatim("TC")<<" findKinks: kink angle "<<kang<<" at point "<<ipt<<" klen "<<klen;
1932  kinkPts.push_back(ipt - 1);
1933  foundKink = true;
1934  kStart = USHRT_MAX;
1935  } // dang < kang
1936  } // kink found
1937  kang = dang;
1938  } // ipt
1939  return kinkPts;
1940  } // findKinks
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1660
double KinkAngle(TCSlice &slc, const std::vector< TrajPoint3 > &tp3s, unsigned short atPt, double sep)
Definition: PFPUtils.cxx:1943
void tca::FindMissedTjsInTp3s ( TCSlice slc,
PFPStruct pfp,
std::vector< int > &  missTjs,
std::vector< float > &  missFrac 
)

Definition at line 950 of file PFPUtils.cxx.

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

951  {
952  // compare the Tjs in pfp.TjIDs with the Tjs in Tp3s and return a list of Tjs
953  // in Tp3s that aren't in pfp.TjIDs
954  missTjs.clear();
955  missFrac.clear();
956  if(pfp.TjIDs.empty() || pfp.Tp3s.empty()) return;
957 
958  // determine the projection of the pfp direction vector in each plane.
959  // Don't try to merge if the projection is small
960  std::vector<float> projInPlane(slc.nPlanes);
961  for(unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
962  CTP_t inCTP = EncodeCTP(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
963  auto tp = MakeBareTP(slc, pfp.XYZ[0], pfp.Dir[0], inCTP);
964  projInPlane[plane] = tp.Delta;
965  } // plane
966 
967  std::vector<unsigned short> pfpTjs;
968  std::vector<unsigned short> usMissTjs;
969  std::vector<std::vector<bool>> misTjPtMat;
970  for(auto tjid : pfp.TjIDs) pfpTjs.push_back((unsigned short)tjid);
971  for(auto& tp3 : pfp.Tp3s) {
972  for(auto& tj2pt : tp3.Tj2Pts) {
973  if(std::find(pfpTjs.begin(), pfpTjs.end(), tj2pt.id) != pfpTjs.end()) continue;
974  // Tj isn't in pfp.TjIDs. See if we have it in the missed list
975  unsigned short mtjIndx = 0;
976  for(mtjIndx = 0; mtjIndx < usMissTjs.size(); ++mtjIndx) if(tj2pt.id == usMissTjs[mtjIndx]) break;
977  if(mtjIndx == usMissTjs.size()) {
978  // not in the misTjs list. Ensure that it isn't matched
979  auto& mtj = slc.tjs[tj2pt.id - 1];
980  if(mtj.AlgMod[kKilled] || mtj.AlgMod[kMat3D]) continue;
981  // add it to the list
982  usMissTjs.push_back(tj2pt.id);
983  // create the point match vector
984  std::vector<bool> ptMat(mtj.Pts.size(), false);
985  ptMat[tj2pt.ipt] = true;
986  misTjPtMat.push_back(ptMat);
987  } else {
988  if(tj2pt.ipt < misTjPtMat[mtjIndx].size()) misTjPtMat[mtjIndx][tj2pt.ipt] = true;
989  }
990  } // tj2pt
991  } // tp3
992  for(unsigned short im = 0; im < usMissTjs.size(); ++im) {
993  int mtjid = usMissTjs[im];
994  // calculate the fraction of points that are in Tp3s
995  float cnt = 0;
996  float mat = 0;
997  auto& mtj = slc.tjs[mtjid - 1];
998  // ignore if there is a high-score vertex between the missed tj and those in the pfp list
999  if(SharesHighScoreVx(slc, pfp, mtj)) continue;
1000  for(unsigned short ipt = mtj.EndPt[0]; ipt <= mtj.EndPt[1]; ++ipt) {
1001  auto& mtp = mtj.Pts[ipt];
1002  if(mtp.Chg <= 0) continue;
1003  ++cnt;
1004  if(misTjPtMat[im][ipt]) ++mat;
1005  } // ipt
1006  float frac = mat / cnt;
1007  // ignore if low fraction matched
1008  if(frac < 0.1) continue;
1009  // ignore if this would only extend the tj in this plane by a small amount
1010  float lenInPlane = 0;
1011  for(auto tjid : pfp.TjIDs) {
1012  auto& tj = slc.tjs[tjid - 1];
1013  if(tj.CTP != mtj.CTP) continue;
1014  float len = PosSep(tj.Pts[tj.EndPt[0]].Pos, tj.Pts[tj.EndPt[1]].Pos);
1015  if(len > lenInPlane) lenInPlane = len;
1016  } // tjid
1017  if(cnt < 0.05 * lenInPlane) continue;
1018  // check the direction vector projection in this plane
1019  if(projInPlane[DecodeCTP(mtj.CTP).Plane] < 0.1) continue;
1020  missTjs.push_back(mtjid);
1021  missFrac.push_back(frac);
1022  } // im
1023  } // FindMissedTjsInTp3s
TrajPoint MakeBareTP(TCSlice &slc, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
Definition: Utils.cxx:3523
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)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
bool SharesHighScoreVx(TCSlice &slc, const PFPStruct &pfp, const Trajectory &tj)
Definition: PFPUtils.cxx:1026
void tca::FindNearbyTjs ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct ss,
bool  prt 
)

Definition at line 3762 of file TCShower.cxx.

References tca::ShowerStruct::CTP, tca::ShowerStruct::Envelope, GetAssns(), tca::ShowerStruct::ID, tca::TCSlice::ID, kKilled, kShowerTj, tca::ShowerStruct::NearTjIDs, PointInsideEnvelope(), PointTrajDOCA(), tca::ShowerStruct::ShowerTjID, tca::ShowerStruct::TjIDs, tca::TCSlice::tjs, TrajTrajDOCA(), and tca::TCSlice::vtxs.

Referenced by FindShowers3D().

3763  {
3764  // Find Tjs that are near the shower but are not included in it
3765  ss.NearTjIDs.clear();
3766 
3767  // check for a valid envelope
3768  if(ss.Envelope.empty()) return;
3769  auto& stj = slc.tjs[ss.ShowerTjID - 1];
3770 
3771  std::string fcnLabel = inFcnLabel + ".FNTj";
3772 
3773  std::vector<int> ntj;
3774 
3775  // set max distance of closest approach ~ 5 radiation lengths ~200 WSE
3776  constexpr float fiveRadLen = 200;
3777 
3778  // look for vertices inside the envelope
3779  for(auto vx : slc.vtxs) {
3780  if(vx.CTP != ss.CTP) continue;
3781  if(vx.ID == 0) continue;
3782  if(!PointInsideEnvelope(vx.Pos, ss.Envelope)) continue;
3783 // auto vxTjIDs = GetVtxTjIDs(slc, vx);
3784  auto vxTjIDs = GetAssns(slc, "2V", vx.ID, "T");
3785  for(auto tjID : vxTjIDs) {
3786  // ignore those that are in the shower
3787  if(std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tjID) != ss.TjIDs.end()) continue;
3788  // or already in the list
3789  if(std::find(ntj.begin(), ntj.end(), tjID) != ntj.end()) continue;
3790  ntj.push_back(tjID);
3791  } // tjID
3792  } // vx
3793 
3794  // Check for tj points inside the envelope
3795  for(auto& tj : slc.tjs) {
3796  if(tj.CTP != ss.CTP) continue;
3797  if(tj.AlgMod[kKilled]) continue;
3798  // not a showerTj
3799  if(tj.AlgMod[kShowerTj]) continue;
3800  // make sure it's not in the shower
3801  if(std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tj.ID) != ss.TjIDs.end()) continue;
3802  // or already in the list
3803  if(std::find(ntj.begin(), ntj.end(), tj.ID) != ntj.end()) continue;
3804  // check proximity of long high MCSMom Tjs to the shower center
3805  if(tj.Pts.size() > 40 && tj.MCSMom > 200) {
3806  float delta = PointTrajDOCA(slc, stj.Pts[1].Pos[0], stj.Pts[1].Pos[1], tj.Pts[tj.EndPt[0]]);
3807  // TODO: This could be done much better
3808  if(delta < 20) {
3809  float doca = fiveRadLen;
3810  unsigned short spt = 0, ipt = 0;
3811  TrajTrajDOCA(slc, stj, tj, spt, ipt, doca);
3812  if(doca < fiveRadLen) {
3813  ntj.push_back(tj.ID);
3814  continue;
3815  }
3816  }
3817  } // long hi-MCSMom tj
3818  // don't need to check every point. Every third should be enough
3819  bool isInside = false;
3820  for(unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1]; ipt += 3) {
3821  if(PointInsideEnvelope(tj.Pts[ipt].Pos, ss.Envelope)) {
3822  isInside = true;
3823  break;
3824  }
3825  } // ipt
3826  // check the last point which was probably missed above
3827  if(!isInside) {
3828  unsigned short ipt = tj.EndPt[1];
3829  isInside = PointInsideEnvelope(tj.Pts[ipt].Pos, ss.Envelope);
3830  }
3831  if(isInside) ntj.push_back(tj.ID);
3832  } // tj
3833  if(ntj.size() > 1) std::sort(ntj.begin(), ntj.end());
3834  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Found "<<ntj.size()<<" Tjs near ss.ID "<<ss.ID;
3835  ss.NearTjIDs = ntj;
3836 
3837  } // FindNearbyTjs
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4279
Float_t ss
Definition: plot.C:23
bool TrajTrajDOCA(TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2175
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:2781
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
void tca::FindNeutralVertices ( TCSlice slc)

Definition at line 529 of file TCVertex.cxx.

References kVxNeutral, tca::TCConfig::neutralVxCuts, tca::TCSlice::nPlanes, tca::TCSlice::pfps, tcc, and tca::TCConfig::useAlg.

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

530  {
531  // Look for 2D neutral vertices between Tjs
532  if(!tcc.useAlg[kVxNeutral]) return;
533  if(tcc.neutralVxCuts.size() < 4) return;
534  if(slc.nPlanes < 3) return;
535  if(slc.pfps.size() < 2) return;
536 
537  /* TODO This algorithm needs work.
538 
539  bool prt = tcc.dbgVxNeutral && tcc.dbgSlc;
540 
541  struct CandVx {
542  unsigned short ip1;
543  unsigned short end1;
544  unsigned short ip2;
545  unsigned short end2;
546  Point3_t intersect;
547  float sepSum;
548  bool isValid;
549  };
550  std::vector<CandVx> candVxs;
551 
552  for(unsigned short ip1 = 0; ip1 < slc.pfps.size() - 1; ++ip1) {
553  auto& p1 = slc.pfps[ip1];
554  if(p1.ID == 0) continue;
555  if(p1.Tp3s.empty()) continue;
556  float len1 = PosSep(p1.XYZ[0], p1.XYZ[1]);
557  if(len1 < tcc.neutralVxCuts[3]) continue;
558  for(unsigned short end1 = 0; end1 < 2; ++end1) {
559  float cfne1 = ChgFracNearEnd(slc, p1, end1);
560  if(cfne1 < tcc.neutralVxCuts[0]) continue;
561  for(unsigned short ip2 = ip1 + 1; ip2 < slc.pfps.size(); ++ip2) {
562  auto& p2 = slc.pfps[ip2];
563  if(p2.ID == 0) continue;
564  if(p2.Tp3s.empty()) continue;
565  float len2 = PosSep(p2.XYZ[0], p2.XYZ[1]);
566  if(len2 < tcc.neutralVxCuts[3]) continue;
567  for(unsigned short end2 = 0; end2 < 2; ++end2) {
568  float cfne2 = ChgFracNearEnd(slc, p2, end2);
569  if(cfne2 < tcc.neutralVxCuts[0]) continue;
570  float vxDOCA = 1E6;
571  Point3_t intersect;
572  if(!PointDirIntersect(p1.XYZ[end1], p1.Dir[end1], p2.XYZ[end2], p2.Dir[end2], intersect, vxDOCA)) continue;
573  if(intersect[0] < slc.xLo || intersect[0] > slc.xHi) continue;
574  if(intersect[1] < slc.yLo || intersect[1] > slc.yHi) continue;
575  if(intersect[2] < slc.zLo || intersect[2] > slc.zHi) continue;
576  // ensure that the pfp end and the vertex are consistent
577  float sep1 = PosSep(intersect, p1.XYZ[end1]);
578  if(PosSep(intersect, p1.XYZ[1-end1]) < sep1) continue;
579  float sep2 = PosSep(intersect, p2.XYZ[end2]);
580  if(PosSep(intersect, p2.XYZ[1-end2]) < sep2) continue;
581  if(vxDOCA > tcc.neutralVxCuts[1]) continue;
582  // ensure that there isn't a lot of charge between the end of each pfp and the intersection point
583  float cfb1 = ChgFracBetween(slc, p1.XYZ[end1], intersect);
584  float cfb2 = ChgFracBetween(slc, p2.XYZ[end2], intersect);
585  if(prt) {
586  mf::LogVerbatim myprt("TC");
587  myprt<<"FNV: P"<<p1.ID<<"_"<<end1<<" sep1 "<<std::fixed<<std::setprecision(2)<<sep1;
588  myprt<<" cfne1 "<<cfne1<<" cfb1 "<<cfb1;
589  myprt<<" P"<<p2.ID<<"_"<<end2<<" sep2 "<<sep2<<" cfne2 "<<cfne2<<" cfb2 "<<cfb2;
590  myprt<<" intersect "<<intersect[0]<<" "<<intersect[1]<<" "<<intersect[2];
591  myprt<<" vxDOCA "<<vxDOCA;
592  } // prt
593  if(cfb1 > tcc.neutralVxCuts[2]) continue;
594  if(cfb2 > tcc.neutralVxCuts[2]) continue;
595  // check existing candidates
596  float sepSum = sep1 + sep2;
597  bool skipit = false;
598  for(auto& candVx : candVxs) {
599  if(!candVx.isValid) continue;
600  if(candVx.ip1 != ip1 && candVx.ip2 != ip2) continue;
601  // see if the separation sum is smaller
602  if(sepSum < candVx.sepSum) {
603  // flag the saved one as not valid
604  candVx.isValid = false;
605  } else {
606  skipit = true;
607  break;
608  }
609  } // candVx
610  if(skipit) continue;
611  CandVx candVx;
612  candVx.ip1 = ip1;
613  candVx.end1 = end1;
614  candVx.ip2 = ip2;
615  candVx.end2 = end2;
616  candVx.intersect = intersect;
617  candVx.sepSum = sep1 + sep2;
618  candVx.isValid = true;
619  candVxs.push_back(candVx);
620  if(prt) mf::LogVerbatim("TC")<<" candidate";
621  } // end2
622  } // ip2
623  } // end1
624  } // ip1
625 
626  if(candVxs.empty()) return;
627 
628  // Make vertices with the valid candidates
629  for(auto& candVx : candVxs) {
630  if(!candVx.isValid) continue;
631  Vtx3Store vx3;
632  auto& p1 = slc.pfps[candVx.ip1];
633  auto& p2 = slc.pfps[candVx.ip2];
634  vx3.TPCID = p1.TPCID;
635  vx3.Vx2ID.resize(slc.nPlanes);
636  vx3.ID = slc.vtx3s.size() + 1;
637  // try to improve the vertex position by fitting the Tjs in 2D
638  std::vector<TrajPoint> vxTps;
639  Vector3_t dir = {{0, 0, 0}};
640  for(unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
641  vxTps.clear();
642  CTP_t inCTP = EncodeCTP(p1.TPCID.Cryostat, p1.TPCID.TPC, plane);
643  // Need the position in this plane to find the closest end
644  auto vtp = MakeBareTP(slc, candVx.intersect, dir, inCTP);
645  if(vtp.Pos[0] < 0) continue;
646  for(auto tid : p1.TjIDs) {
647  auto& tj = slc.tjs[tid - 1];
648  if(tj.CTP != vtp.CTP) continue;
649  unsigned short end = CloseEnd(slc, tj, vtp.Pos);
650  auto vxTp = tj.Pts[tj.EndPt[end]];
651  vxTp.Step = tid;
652  vxTp.AngleCode = end;
653  vxTps.push_back(vxTp);
654  } // tid
655  for(auto tid : p2.TjIDs) {
656  auto& tj = slc.tjs[tid - 1];
657  if(tj.CTP != vtp.CTP) continue;
658  unsigned short end = CloseEnd(slc, tj, vtp.Pos);
659  auto vxTp = tj.Pts[tj.EndPt[end]];
660  vxTp.Step = tid;
661  vxTp.AngleCode = end;
662  vxTps.push_back(vxTp);
663  } // tid
664  if(vxTps.size() < 2) continue;
665  VtxStore vx2;
666  vx2.CTP = inCTP;
667  vx2.Topo = 11;
668  if(!FitVertex(slc, vx2, vxTps, prt)) {
669  if(prt) mf::LogVerbatim("TC")<<"FNV: vertex fit failed";
670  continue;
671  } // fit failed
672  vx2.ID = slc.vtxs.size() + 1;
673  for(auto& vxTp : vxTps) {
674  int tid = vxTp.Step;
675  auto& tj = slc.tjs[tid - 1];
676  tj.VtxID[vxTp.AngleCode] = vx2.ID;
677  }
678  if(prt) mf::LogVerbatim("TC")<<"FNV: 2V fit inCTP "<<inCTP<<" pos "<<PrintPos(slc, vx2.Pos);
679  vx2.Vx3ID = vx3.ID;
680  vx3.Vx2ID[plane] = vx2.ID;
681  SetVx2Score(slc, vx2);
682  if(!StoreVertex(slc, vx2)) {
683  if(prt) mf::LogVerbatim("TC")<<"FNV: store vertex failed";
684  continue;
685  } // StoreVertex failed
686  } // plane
687  vx3.X = candVx.intersect[0];
688  vx3.Y = candVx.intersect[1];
689  vx3.Z = candVx.intersect[2];
690  vx3.Primary = true;
691  SetVx3Score(slc, vx3);
692  ++evt.globalS3ID;
693  vx3.UID = evt.globalS3ID;
694  slc.vtx3s.push_back(vx3);
695  if(prt) mf::LogVerbatim("TC")<<"FNV: P"<<p1.ID<<"_"<<candVx.end1<<" P"<<p2.ID<<"_"<<candVx.end2<<" -> 3V"<<vx3.ID;
696  } // candVx
697 */
698  } // FindNeutralVertices
TCConfig tcc
Definition: DataStructs.cxx:6
std::vector< float > neutralVxCuts
Definition: DataStructs.h:469
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
bool tca::FindParent ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 1668 of file TCShower.cxx.

References ChgFracBetween(), tca::ShowerStruct3D::ChgPos, ChgToMeV(), tca::ShowerStruct3D::CotIDs, tca::TCSlice::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::TCSlice::nPlanes, tca::ShowerStruct3D::ParentID, tca::TCSlice::pfps, PointDirection(), PosSep(), PosSep2(), SetParent(), ShowerEnergy(), ShowerParams(), tca::TCConfig::showerParentReader, tca::TCConfig::showerParentVars, tca::TCSlice::showers, ss, tca::ShowerStruct3D::Start, tcc, tca::TCSlice::tjs, geo::TPCID::TPC, tca::ShowerStruct3D::TPCID, UpdateShower(), tca::TCConfig::useAlg, and tca::ShowerStruct3D::Vx3ID.

Referenced by FindShowers3D().

1669  {
1670  // look for a parent pfp for the shower.The 2D showers associated with it
1671  // The parent should be at the start of the shower (shend = 0) if it is well-defined
1672  // (has small AspectRatio and small DirectionFOM). A search is also made for a parent at
1673  // the "wrong" end of the shower (shend = 1). The best one at the wrong end is used if
1674  // no parent is found at the shower start and the shower is poorly defined.
1675  //
1676  // This function returns false if there was a failure. Not finding a parent is not a failure
1677 
1678  if(ss3.ID == 0) return false;
1679  if(ss3.CotIDs.size() < 2) return false;
1680  // Use the MVA reader
1681  if(!tcc.showerParentReader) return false;
1682  if(tcc.showerParentVars.size() != 9) return false;
1683  // don't call this function when studying this function. See TCTruth StudyShowerParents
1684  if(!tcc.useAlg[kShwrParent]) return false;
1685 
1686  std::string fcnLabel = inFcnLabel + ".FPar";
1687 // MCParticleListUtils mcpu{slc};
1688 // int truPFP = mcpu.PrimaryElectronPFPID(slc);
1689  int truPFP = 0;
1690 
1691 
1692  double energy = ShowerEnergy(ss3);
1693  // the energy is probably under-estimated since there isn't a parent yet.
1694  energy *= 1.2;
1695  double shMaxAlong, along95;
1696  ShowerParams(energy, shMaxAlong, along95);
1697  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" Estimated energy "<<(int)energy<<" MeV shMaxAlong "<<shMaxAlong<<" along95 "<<along95<<" truPFP "<<truPFP;
1698 
1699  // look for the pfp that has a reasonable probability of being in the shower but with the
1700  // minimum along distance from the shower center.
1701  // This image explains the concept. The *'s represents the points in 2D showers that define
1702  // the charge center in 3D, ChgPos. We are looking for a pfp parent denoted by ----. The end
1703  // that is farthest from ChgPos is labeled P (pfp.XYZ[pend] in the code). The expected distance
1704  // from the shower start to shower Max, shMaxAlong, is found from ShowerParams. The longitudinal
1705  // and transverse distance of P relative to the shower center is alongTrans. The first cut on a
1706  // candidate parent is made requiring that D (alongTrans[0]) > 0.5 * shMaxAlong.
1707  //
1708  // __________shend = 0________________ __________shend = 1________________
1709  // **********
1710  // ****** ****** ****** ******
1711  // P-----*****ChgPos****** ** *****ChgPos******-------P
1712  // ******** ******* *******
1713  // |----> along |---> along
1714  // |<----D------>| |<----D------>|
1715  // |<----shMaxAlong--->| |<----shMaxAlong--->|
1716  //
1717  // Candidate parent ID for each end and the FOM
1718  std::array<int, 2> parID {{0, 0}};
1719  std::array<float, 2> parFOM {{-1E6, -1E6}};
1720 
1721  // temp vector to flag pfps that are already parents - indexed by ID
1722  std::vector<bool> isParent(slc.pfps.size() + 1, false);
1723  for(auto& oldSS3 : slc.showers) {
1724  if(oldSS3.ID == 0) continue;
1725  isParent[oldSS3.ParentID] = true;
1726  } // pfp
1727 
1728  // put the tjs associated with this shower in a flat vector
1729  auto TjsInSS3 = GetAssns(slc, "3S", ss3.ID, "T");
1730  if(TjsInSS3.empty()) return false;
1731 
1732  for(auto& pfp : slc.pfps) {
1733  if(pfp.ID == 0) continue;
1734  bool dprt = (pfp.ID == truPFP);
1735  if(pfp.TPCID != ss3.TPCID) continue;
1736  // ignore neutrinos
1737  if(pfp.PDGCode == 14 || pfp.PDGCode == 14) continue;
1738  // ignore shower pfps
1739  if(pfp.PDGCode == 1111) continue;
1740  // ignore existing parents
1741  if(isParent[pfp.ID]) continue;
1742  // check for inconsistent pfp - shower tjs
1743  if(DontCluster(slc, pfp.TjIDs, TjsInSS3)) continue;
1744  // ignore if the pfp energy is larger than the shower energy
1745  float pfpEnergy = 0;
1746  float minEnergy = 1E6;
1747  for(auto tid : pfp.TjIDs) {
1748  auto& tj = slc.tjs[tid - 1];
1749  float energy = ChgToMeV(tj.TotChg);
1750  pfpEnergy += energy;
1751  if(energy < minEnergy) minEnergy = energy;
1752  }
1753  pfpEnergy -= minEnergy;
1754  pfpEnergy /= (float)(pfp.TjIDs.size() - 1);
1755  if(dprt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" P"<<pfp.ID<<" E "<<pfpEnergy;
1756  if(pfpEnergy > energy) continue;
1757  // find the end that is farthest away
1758  unsigned short pEnd = FarEnd(slc, pfp, ss3.ChgPos);
1759  auto pToS = PointDirection(pfp.XYZ[pEnd], ss3.ChgPos);
1760  double costh1 = std::abs(DotProd(pToS, ss3.Dir));
1761  if(costh1 < 0.4) continue;
1762  float costh2 = DotProd(pToS, pfp.Dir[pEnd]);
1763  // distance^2 between the pfp end and the shower start, charge center, and shower end
1764  float distToStart2 = PosSep2(pfp.XYZ[pEnd], ss3.Start);
1765  float distToChgPos2 = PosSep2(pfp.XYZ[pEnd], ss3.ChgPos);
1766  float distToEnd2 = PosSep2(pfp.XYZ[pEnd], ss3.End);
1767  if(dprt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" P"<<pfp.ID<<"_"<<pEnd<<" distToStart "<<sqrt(distToStart2)<<" distToChgPos "<<sqrt(distToChgPos2)<<" distToEnd "<<sqrt(distToEnd2);
1768  // find the end of the shower closest to the pfp
1769  unsigned short shEnd = 0;
1770  if(distToEnd2 < distToStart2) shEnd = 1;
1771  // This can't be a parent if the pfp end is closer to the shower center than the start or the end
1772  if(shEnd == 0 && distToChgPos2 < distToStart2) continue;
1773  if(shEnd == 1 && distToChgPos2 < distToEnd2) continue;
1774  if(dprt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<"_"<<shEnd<<" P"<<pfp.ID<<"_"<<pEnd<<" costh1 "<<costh1;
1775  Point2_t alongTrans;
1776  // find the longitudinal and transverse components of the pfp start point relative to the
1777  // shower center
1778  FindAlongTrans(ss3.ChgPos, ss3.Dir, pfp.XYZ[pEnd], alongTrans);
1779  if(dprt) mf::LogVerbatim("TC")<<fcnLabel<<" alongTrans "<<alongTrans[0]<<" "<<alongTrans[1];
1780  // find the probability this point is inside the shower. Offset by the expected
1781  // shower max distance. distToShowerMax will be > 0 if the pfp end is closer to
1782  // ChgPos than expected from the parameterization
1783  float distToShowerMax = shMaxAlong - std::abs(alongTrans[0]);
1784  float prob = InShowerProbLong(energy, distToShowerMax);
1785  if(dprt) mf::LogVerbatim("TC")<<fcnLabel<<" prob "<<prob;
1786  if(prob < 0.1) continue;
1787  float chgFrac = 0;
1788  float totSep = 0;
1789  // find the charge fraction btw the pfp start and the point that is
1790  // half the distance to the charge center in each plane
1791  for(unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
1792  CTP_t inCTP = EncodeCTP(ss3.TPCID.Cryostat, ss3.TPCID.TPC, plane);
1793  int ssid = 0;
1794  for(auto cid : ss3.CotIDs) {
1795  auto& ss = slc.cots[cid - 1];
1796  if(ss.CTP != inCTP) continue;
1797  ssid = ss.ID;
1798  break;
1799  } // cid
1800  if(ssid == 0) continue;
1801  auto tpFrom = MakeBareTP(slc, pfp.XYZ[pEnd], pToS, inCTP);
1802  auto& ss = slc.cots[ssid - 1];
1803  auto& stp1 = slc.tjs[ss.ShowerTjID - 1].Pts[1];
1804  float sep = PosSep(tpFrom.Pos, stp1.Pos);
1805  float toPos = tpFrom.Pos[0] + 0.5 * tpFrom.Dir[0] * sep;
1806  float cf = ChgFracBetween(slc, tpFrom, toPos);
1807  // weight by the separation in the plane
1808  totSep += sep;
1809  chgFrac += sep * cf;
1810  } // plane
1811  if(totSep > 0) chgFrac /= totSep;
1812 /*
1813  tcc.showerParentReader->AddVariable("fShEnergy", &tcc.showerParentVars[0]);
1814  tcc.showerParentReader->AddVariable("fPfpEnergy", &tcc.showerParentVars[1]);
1815  tcc.showerParentReader->AddVariable("fMCSMom", &tcc.showerParentVars[2]);
1816  tcc.showerParentReader->AddVariable("fPfpLen", &tcc.showerParentVars[3]);
1817  tcc.showerParentReader->AddVariable("fSep", &tcc.showerParentVars[4]);
1818  tcc.showerParentReader->AddVariable("fDang1", &tcc.showerParentVars[5]);
1819  tcc.showerParentReader->AddVariable("fDang2", &tcc.showerParentVars[6]);
1820  tcc.showerParentReader->AddVariable("fChgFrac", &tcc.showerParentVars[7]);
1821  tcc.showerParentReader->AddVariable("fInShwrProb", &tcc.showerParentVars[8]);
1822 */
1823  // load the MVA variables
1825  tcc.showerParentVars[1] = pfpEnergy;
1826  tcc.showerParentVars[2] = MCSMom(slc, pfp.TjIDs);
1827  tcc.showerParentVars[3] = PosSep(pfp.XYZ[0], pfp.XYZ[1]);
1828  tcc.showerParentVars[4] = sqrt(distToChgPos2);
1829  tcc.showerParentVars[5] = acos(costh1);
1830  tcc.showerParentVars[6] = acos(costh2);
1831  tcc.showerParentVars[7] = chgFrac;
1832  tcc.showerParentVars[8] = prob;
1833  float candParFOM = tcc.showerParentReader->EvaluateMVA("BDT");
1834 /*
1835  // use the overall pfp direction instead of the starting direction. It may not be so
1836  // good if the shower develops quickly
1837  auto pfpDir = PointDirection(pfp.XYZ[pEnd], pfp.XYZ[1 - pEnd]);
1838  costh = DotProd(pfpDir, ss3.Dir);
1839  if(dprt) mf::LogVerbatim("TC")<<fcnLabel<<" pfpDir "<<pfpDir[0]<<" "<<pfpDir[1]<<" "<<pfpDir[2]<<" costh "<<costh;
1840  if(std::abs(costh) < 0.6) continue;
1841 */
1842  // find the parentFOM
1843 // float candParFOM = ParentFOM(fcnLabel, slc, pfp, pEnd, ss3, prt);
1844 
1845  if(prt) {
1846  mf::LogVerbatim myprt("TC");
1847  myprt<<fcnLabel;
1848  myprt<<" 3S"<<ss3.ID<<"_"<<shEnd;
1849  myprt<<" P"<<pfp.ID<<"_"<<pEnd<<" ParentVars";
1850  for(auto var : tcc.showerParentVars) myprt<<" "<<std::fixed<<std::setprecision(2)<<var;
1851  myprt<<" candParFOM "<<candParFOM;
1852  } // prt
1853  if(candParFOM > parFOM[shEnd]) {
1854  parFOM[shEnd] = candParFOM;
1855  parID[shEnd] = pfp.ID;
1856  }
1857  } // pfp
1858 
1859  if(parID[0] == 0 && parID[1] == 0) return true;
1860 
1861  // decide which to use
1862  int bestPFP = 0;
1863  // find the average DirectionFOM to help decide
1864  float aveDirFOM = 0;
1865  float fom3D = 0;
1866  for(auto cid : ss3.CotIDs) aveDirFOM += slc.cots[cid - 1].DirectionFOM;
1867  aveDirFOM /= (float)ss3.CotIDs.size();
1868  if(prt) {
1869  mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" parID[0] "<<parID[0]<<" fom "<<parFOM[0]<<" parID[1] "<<parID[1]<<" fom "<<parFOM[1]<<" aveDirFOM "<<aveDirFOM;
1870  }
1871  if(parID[0] > 0 && parID[1] > 0 && aveDirFOM > 0.3) {
1872  // candidates at both ends and the direction is not well known. Take
1873  // the one with the best FOM
1874  bestPFP = parID[0];
1875  fom3D = parFOM[0];
1876  if(parFOM[1] > parFOM[0]) {
1877  bestPFP = parID[1];
1878  fom3D = parFOM[1];
1879  }
1880  } else if(parID[0] > 0) {
1881  bestPFP = parID[0];
1882  fom3D = parFOM[0];
1883  } else {
1884  bestPFP = parID[1];
1885  fom3D = parFOM[1];
1886  }
1887  if(bestPFP == 0) return true;
1888 
1889  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" setting P"<<bestPFP<<" as the parent "<<fom3D;
1890 
1891  // make local copies so we can recover from a failure
1892  auto oldSS3 = ss3;
1893  std::vector<ShowerStruct> oldSS(ss3.CotIDs.size());
1894  for(unsigned short ii = 0; ii < ss3.CotIDs.size(); ++ii) {
1895  oldSS[ii] = slc.cots[ss3.CotIDs[ii] - 1];
1896  }
1897 
1898  ss3.ParentID = bestPFP;
1899  auto& pfp = slc.pfps[bestPFP - 1];
1900  unsigned short pend = FarEnd(slc, pfp, ss3.ChgPos);
1901  ss3.Vx3ID = pfp.Vx3ID[pend];
1902 
1903  if(SetParent(fcnLabel, slc, pfp, ss3, prt) && UpdateShower(fcnLabel, slc, ss3, prt)) {
1904  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" successful update";
1905  return true;
1906  }
1907 
1908  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" Failed. Recovering...";
1909  ss3 = oldSS3;
1910  for(unsigned short ii = 0; ii < oldSS.size(); ++ii) {
1911  auto& ss = oldSS[ii];
1912  slc.cots[ss.ID - 1] = ss;
1913  } // ii
1914  return false;
1915 
1916  } // FindParent
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4279
double InShowerProbLong(double showerEnergy, double along)
Definition: TCShower.cxx:2049
short MCSMom(TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2914
TCConfig tcc
Definition: DataStructs.cxx:6
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:2849
Float_t ss
Definition: plot.C:23
bool SetParent(std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1919
bool DontCluster(TCSlice &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3313
TrajPoint MakeBareTP(TCSlice &slc, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
Definition: Utils.cxx:3523
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1230
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
float ShowerEnergy(TCSlice &slc, const std::vector< int > tjIDs)
Definition: TCShower.cxx:4382
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:1643
TMVA::Reader * showerParentReader
Definition: DataStructs.h:496
std::vector< float > showerParentVars
Definition: DataStructs.h:497
double energy
Definition: plottest35.C:25
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1660
unsigned short FarEnd(TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3032
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:59
unsigned int CTP_t
Definition: DataStructs.h:41
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
Definition: TCShower.cxx:2015
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
float ChgToMeV(float chg)
Definition: TCShower.cxx:4395
float ChgFracBetween(TCSlice &slc, Point3_t pos1, Point3_t pos2)
Definition: PFPUtils.cxx:2957
void tca::FindPFParticles ( TCSlice slc)

Definition at line 1998 of file PFPUtils.cxx.

References AnalyzePFP(), CreatePFP(), geo::CryostatID::Cryostat, tca::TCConfig::dbgPFP, tca::TCConfig::dbgSlc, DefinePFP(), tca::PFPStruct::Dir, EncodeCTP(), FindCompleteness(), FindXMatches(), tca::PFPStruct::ID, tca::SortEntry::index, kEnvFlag, kKilled, kMat3D, kTestBeam, MakeBareTP(), tca::TCConfig::match3DCuts, Match3DVtxTjs(), tca::TCSlice::matchVec, tca::PFPStruct::MatchVecIndex, MaxTjLen(), MCSMom(), tca::TCConfig::modes, tca::TCSlice::nPlanes, tca::PFPStruct::PDGCode, PDGCodeVote(), SetIntersection(), Split3DKink(), StorePFP(), tcc, tca::PFPStruct::TjCompleteness, tca::PFPStruct::TjIDs, tca::TCSlice::tjs, geo::TPCID::TPC, tca::PFPStruct::TPCID, tca::SortEntry::val, valDecreasings(), and tca::PFPStruct::XYZ.

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

1999  {
2000  // Match Tjs in 3D and create PFParticles
2001 
2002  if(tcc.match3DCuts[0] <= 0) return;
2003 
2004  bool prt = (tcc.dbgPFP && tcc.dbgSlc);
2005 
2006  if(prt) mf::LogVerbatim("TC")<<" inside FindPFParticles";
2007  // clear matchVec
2008  slc.matchVec.clear();
2009  // clear the kEnvFlag bits on all Tjs. The bit will be set true when a TP is
2010  // used in a PFParticle Tp3
2011  for(auto& tj : slc.tjs) {
2012  for(auto& tp : tj.Pts) tp.Environment[kEnvFlag] = false;
2013  } // tj
2014 
2015  // Match these points in 3D and put the results in slc.matchVec
2016  std::vector<MatchStruct> matVec;
2017  // first look for 3-plane matches in a 3-plane TPC
2018  if(slc.nPlanes == 3) {
2019  // Match Tjs with high quality vertices first and the leftovers next
2020  for(short maxScore = 0; maxScore < 2; ++maxScore) FindXMatches(slc, 3, maxScore, matVec, prt);
2021  } // 3-plane TPC
2022  // Make 2-plane matches if we haven't hit the user-defined size limit
2023  if(matVec.size() < tcc.match3DCuts[4]) {
2024  // 2-plane TPC or 2-plane matches in a 3-plane TPC
2025  if(slc.nPlanes == 2) {
2026  for(short maxScore = 0; maxScore < 2; ++maxScore) FindXMatches(slc, 2, maxScore, matVec, prt);
2027  } else {
2028  // Make one attempt at 2-plane matches in a 3-plane TPC, setting maxScore large
2029  FindXMatches(slc, 2, 3, matVec, prt);
2030  }
2031  } // can add more combinations
2032 
2033  if(matVec.empty()) return;
2034 
2035  // sort by decreasing number of matched points
2036  if(matVec.size() > 1) {
2037  PFPStruct pfp = CreatePFP(slc);
2038  std::vector<int> dum1;
2039  std::vector<float> dum2;
2040  std::vector<SortEntry> sortVec(matVec.size());
2041  for(unsigned int ii = 0; ii < matVec.size(); ++ii) {
2042  sortVec[ii].index = ii;
2043  auto& ms = matVec[ii];
2044  sortVec[ii].val = ms.Count;
2045  // de-weight two-plane matches
2046  if(ms.TjIDs.size() == 2) sortVec[ii].val /= 2;
2047  } // ii
2048  std::sort(sortVec.begin(), sortVec.end(), valDecreasings);
2049  std::vector<MatchStruct> tmpVec;
2050  tmpVec.reserve(matVec.size());
2051  for(unsigned int ii = 0; ii < matVec.size(); ++ii) {
2052  tmpVec.push_back(matVec[sortVec[ii].index]);
2053  } // ii
2054  matVec = tmpVec;
2055  } // sort matVec
2056 
2057  // put the maybe OK matches into tjs
2058  PFPStruct pfp = CreatePFP(slc);
2059  for(auto& ms : matVec) {
2060  if(ms.Count < 2) continue;
2061  // check for duplicates
2062  bool skipit = false;
2063  for(auto& oms : slc.matchVec) {
2064  if(ms.TjIDs == oms.TjIDs) {
2065  skipit = true;
2066  break;
2067  }
2068  } // oms
2069  if(skipit) continue;
2070  // Find completeness, do the fit, don't fill Tp3s, don't print
2071  pfp.TjIDs = ms.TjIDs;
2072  FindCompleteness(slc, pfp, true, false, false);
2073  // save the info in matchStruct
2074  ms.TjCompleteness = pfp.TjCompleteness;
2075  ms.Pos = pfp.XYZ[0];
2076  ms.Dir = pfp.Dir[0];
2077  slc.matchVec.push_back(ms);
2078  }
2079  if(slc.matchVec.empty()) return;
2080 
2081  if(prt) {
2082  mf::LogVerbatim myprt("TC");
2083  myprt<<"FPFP: slc.matchVec\n";
2084  unsigned short cnt = 0;
2085  PFPStruct pfp = CreatePFP(slc);
2086  std::vector<int> dum1;
2087  std::vector<float> dum2;
2088  for(unsigned int ii = 0; ii < slc.matchVec.size(); ++ii) {
2089  auto& ms = slc.matchVec[ii];
2090  if(ms.Count == 0) continue;
2091  myprt<<std::setw(4)<<ii<<" Count "<<std::setw(5)<<(int)ms.Count;
2092  myprt<<" Tj ID-UID:";
2093  for(auto& tjid : ms.TjIDs) {
2094  myprt<<" t"<<tjid<<"-T"<<slc.tjs[tjid-1].UID;
2095  }
2096  myprt<<" Comp ";
2097  for(unsigned short itj = 0; itj < ms.TjCompleteness.size(); ++itj) {
2098  myprt<<std::setprecision(2)<<std::setw(6)<<ms.TjCompleteness[itj];
2099  }
2100  myprt<<" Pos ("<<std::setprecision(0)<<std::fixed;
2101  myprt<<ms.Pos[0]<<", "<<ms.Pos[1]<<", "<<ms.Pos[2];
2102  myprt<<") Dir "<<std::setprecision(2)<<std::setw(6)<<ms.Dir[0]<<std::setw(6)<<ms.Dir[1]<<std::setw(6)<<ms.Dir[2];
2103  myprt<<" projInPlane";
2104  for(unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
2105  CTP_t inCTP = EncodeCTP(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
2106  auto tp = MakeBareTP(slc, ms.Pos, ms.Dir, inCTP);
2107  myprt<<" "<<std::setprecision(2)<<tp.Delta;
2108  } // plane
2109  myprt<<" maxTjLen "<<(int)MaxTjLen(slc, ms.TjIDs);
2110  myprt<<" MCSMom "<<MCSMom(slc, ms.TjIDs);
2111  myprt<<" PDGCodeVote "<<PDGCodeVote(slc, ms.TjIDs, false);
2112  myprt<<"\n";
2113  ++cnt;
2114  if(cnt == 500 || ms.Count < 2) {
2115  myprt<<"...stopped printing after 500 entries or Count < 2";
2116  break;
2117  }
2118  } // ii
2119  } // prt
2120 
2121  // create the list of associations to matches that will be converted to PFParticles
2122  // Start with large count tj matches that have a consistent PDGCode and no vertex attachments
2123  // and high completeness
2124  if(slc.matchVec.size() > 1 && slc.matchVec[0].Count > 2 * slc.matchVec[1].Count) {
2125  auto& ms = slc.matchVec[0];
2126  int pdgCode = PDGCodeVote(slc, ms.TjIDs, prt);
2127  bool hasVx = false;
2128  for(auto tid : ms.TjIDs) {
2129  auto& tj = slc.tjs[tid - 1];
2130  if(tj.VtxID[0] > 0 || tj.VtxID[1] > 0) hasVx = true;
2131  } // tid
2132  if(pdgCode != 0 && !hasVx) {
2133  float minCompleteness = 1;
2134  for(unsigned short itj = 0; itj < ms.TjCompleteness.size(); ++itj) {
2135  if(ms.TjCompleteness[itj] < minCompleteness) minCompleteness = ms.TjCompleteness[itj];
2136  } // itj
2137  if(minCompleteness > 0.5) {
2138  PFPStruct pfp = CreatePFP(slc);
2139  pfp.TjIDs = ms.TjIDs;
2140  // note that the ms position is the average position of all 3D matched Tp3s at this point.
2141  // It is not the start position. This will be determined in DefinePFP.
2142  pfp.XYZ[0] = ms.Pos;
2143  pfp.Dir[0] = ms.Dir;
2144  pfp.MatchVecIndex = 0;
2145  // Set the PDGCode so DefinePFP can ignore incompatible matches
2146  pfp.PDGCode = pdgCode;
2147  if(DefinePFP("FPFP", slc, pfp, prt) && AnalyzePFP(slc, pfp, prt) && StorePFP(slc, pfp)) {
2148  ms.Count = 0;
2149  // clobber MatchStructs that use the Tjs in this pfp
2150  for(auto& allms : slc.matchVec) {
2151  auto shared = SetIntersection(allms.TjIDs, pfp.TjIDs);
2152  if(!shared.empty()) allms.Count = 0;
2153  } // allms
2154  } // define/analyze/store PFP
2155  else {
2156  if(prt) mf::LogVerbatim("TC")<<" Define/Analyze/Store PFP failed";
2157  } // define/analyze/store PFP
2158  } // minCompleteness > 0.5
2159  } // pdgCode != 0
2160  } // large count on the first matchVec
2161 
2162  // Next consider Tjs attached to 3D vertices. This is only done when reconstructing neutrino events
2163  if(!tcc.modes[kTestBeam]) {
2164  Match3DVtxTjs(slc, prt);
2165  }
2166 
2167  // define the PFParticleList
2168  for(unsigned int indx = 0; indx < slc.matchVec.size(); ++indx) {
2169  auto& ms = slc.matchVec[indx];
2170  // ignore dead matches
2171  if(ms.Count == 0) continue;
2172  // skip this match if any of the trajectories is already matched or merged and killed
2173  bool skipit = false;
2174  // check for muons and delta rays or InShower Tjs
2175  bool has13 = false;
2176  bool has11 = false;
2177  for(unsigned short itj = 0; itj < ms.TjIDs.size(); ++itj) {
2178  if(ms.TjIDs[itj] <= 0 || ms.TjIDs[itj] > (int)slc.tjs.size()) {
2179  std::cout<<"FindPFParticles: bogus ms TjID "<<ms.TjIDs[itj]<<"\n";
2180  return;
2181  }
2182  auto& tj = slc.tjs[ms.TjIDs[itj] - 1];
2183  if(tj.AlgMod[kMat3D] || tj.AlgMod[kKilled]) skipit = true;
2184  // skip low TjCompleteness
2185  if(ms.TjCompleteness.empty()) {
2186  std::cout<<"FindPFParticles: ms.TjCompleteness is empty\n";
2187  return;
2188  }
2189  if(ms.TjCompleteness[itj] < 0.1) skipit = true;
2190  if(tj.PDGCode == 13) has13 = true;
2191  if(tj.PDGCode == 11) has11 = true;
2192  } // tjID
2193  if(skipit) continue;
2194  if(has13 && has11) continue;
2195  int pdgCode = PDGCodeVote(slc, ms.TjIDs, prt);
2196  PFPStruct pfp = CreatePFP(slc);
2197  pfp.TjIDs = ms.TjIDs;
2198  // note that the ms position is the average position of all 3D matched Tp3s at this point.
2199  // It is not the start position. This will be determined in DefinePFP.
2200  pfp.XYZ[0] = ms.Pos;
2201  pfp.Dir[0] = ms.Dir;
2202  pfp.MatchVecIndex = indx;
2203  // Set the PDGCode so DefinePFP can ignore incompatible matches
2204  pfp.PDGCode = pdgCode;
2205  // set the PDGCode to ensure that delta rays aren't merged with muons. PDGCodeVote
2206  // returns 0 if the vote is mixed
2207  if(has13) pfp.PDGCode = 13;
2208  if(has11) pfp.PDGCode = 11;
2209  if(!DefinePFP("FPFP", slc, pfp, prt)) {
2210  if(prt) mf::LogVerbatim("TC")<<" DefinePFP failed";
2211  continue;
2212  }
2213  double sep = 1;
2214  Split3DKink(slc, pfp, sep, prt);
2215  if(!AnalyzePFP(slc, pfp, prt)) continue;
2216  if(!StorePFP(slc, pfp)) {
2217  if(prt) mf::LogVerbatim("TC")<<" StorePFP failed P"<<pfp.ID;
2218  continue;
2219  }
2220  ms.Count = 0;
2221  // clobber MatchStructs that use the Tjs in this pfp
2222  for(auto& allms : slc.matchVec) {
2223  auto shared = SetIntersection(allms.TjIDs, pfp.TjIDs);
2224  if(!shared.empty()) allms.Count = 0;
2225  } // allms
2226  } // indx
2227 
2228 // MatchMissedTjs(slc);
2229 
2230  } // FindPFParticles
Expect tracks entering from the front face. Don&#39;t create neutrino PFParticles.
Definition: DataStructs.h:448
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
int PDGCodeVote(TCSlice &slc, std::vector< int > &tjIDs, bool prt)
Definition: Utils.cxx:372
void FindCompleteness(TCSlice &slc, PFPStruct &pfp, bool doFit, bool fillTp3s, bool prt)
Definition: PFPUtils.cxx:737
short MCSMom(TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2914
TCConfig tcc
Definition: DataStructs.cxx:6
void FindXMatches(TCSlice &slc, unsigned short numPlanes, short maxScore, std::vector< MatchStruct > &matVec, bool prt)
Definition: PFPUtils.cxx:1355
a general purpose flag bit used in 3D matching
Definition: DataStructs.h:442
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:507
bool Split3DKink(TCSlice &slc, PFPStruct &pfp, double sep, bool prt)
Definition: PFPUtils.cxx:1811
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:231
TrajPoint MakeBareTP(TCSlice &slc, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
Definition: Utils.cxx:3523
float MaxTjLen(TCSlice &slc, std::vector< int > &tjIDs)
Definition: Utils.cxx:2322
bool DefinePFP(std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:2233
bool valDecreasings(SortEntry c1, SortEntry c2)
Definition: PFPUtils.cxx:12
std::vector< float > match3DCuts
3D matching cuts
Definition: DataStructs.h:476
bool AnalyzePFP(TCSlice &slc, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:2421
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
unsigned int CTP_t
Definition: DataStructs.h:41
PFPStruct CreatePFP(TCSlice &slc)
Definition: PFPUtils.cxx:1973
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
bool StorePFP(TCSlice &slc, PFPStruct &pfp)
Definition: PFPUtils.cxx:2749
void Match3DVtxTjs(TCSlice &slc, bool prt)
Definition: TCVertex.cxx:1693
bool tca::FindShowers3D ( TCSlice slc)

Definition at line 286 of file TCShower.cxx.

References AddTjsInsideEnvelope(), ChkAssns(), tca::TCSlice::cots, CreateSS(), geo::CryostatID::Cryostat, tca::DebugStuff::CTP, tca::TCConfig::dbg2S, tca::TCConfig::dbg3S, tca::TCConfig::dbgSlc, debug, DefineDontCluster(), EncodeCTP(), FindCots(), FindNearbyTjs(), FindParent(), tca::TCConfig::geom, kSaveShowerTree, MakeShowerObsolete(), Match2DShowers(), MergeNearby2DShowers(), MergeOverlap(), MergeShowerChain(), MergeSubShowers(), MergeSubShowersTj(), tca::TCConfig::modes, geo::TPCGeo::Nplanes(), tca::TCSlice::nPlanes, Print2DShowers(), PrintAllTraj(), PrintPFPs(), Reconcile3D(), SaveAllCots(), SaveTjInfo(), ShowerEnergy(), tca::TCSlice::showers, tca::TCConfig::showerTag, ss, StoreShower(), tcc, geo::TPCID::TPC, geo::GeometryCore::TPC(), tca::TCSlice::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 = (tcc.showerTag[0] == 2) || (tcc.showerTag[0] == 4);
292  if(!reconstruct) return false;
293 
294  bool prt2S = (tcc.dbgSlc && tcc.dbg2S);
295  bool prt3S = (tcc.dbgSlc && tcc.dbg3S);
296 
297  std::string fcnLabel = "FS";
298 
299  geo::TPCGeo const& TPC = tcc.geom->TPC(slc.TPCID);
300  // check for already-existing showers
301  for(unsigned short plane = 0; plane < TPC.Nplanes(); ++plane) {
302  CTP_t inCTP = EncodeCTP(slc.TPCID.Cryostat, slc.TPCID.TPC, plane);
303  for(auto& ss : slc.cots) if(ss.CTP == inCTP) return false;
304  }
305 
306  if(prt2S) {
307  PrintPFPs("FSi", slc);
308  PrintAllTraj("FSi", slc, USHRT_MAX, 0);
309  }
310 
311  // define a list of tjs that shouldn't be clustered in the same shower because
312  // they are matched to pfp particles that are likely parents of 3D showers
313  DefineDontCluster(slc, prt2S);
314 
315  // lists of Tj IDs in plane, (list1, list2, list3, ...)
316  std::vector<std::vector<std::vector<int>>> bigList(slc.nPlanes);
317  for(unsigned short plane = 0; plane < TPC.Nplanes(); ++plane) {
318  CTP_t inCTP = EncodeCTP(slc.TPCID.Cryostat, slc.TPCID.TPC, plane);
319  std::vector<std::vector<int>> tjList;
320  // Make lists of lists of ShowerLike tjs that will become showers
321  FindCots(fcnLabel, slc, inCTP, tjList, prt2S);
322  SaveTjInfo(slc, tjList, "TJL");
323  if(tjList.empty()) continue;
324  bigList[plane] = tjList;
325  } // plane
326  unsigned short nPlanesWithShowers = 0;
327  for(unsigned short plane = 0; plane < TPC.Nplanes(); ++plane) if(!bigList.empty()) ++nPlanesWithShowers;
328  if(nPlanesWithShowers < 2) return false;
329  for(unsigned short plane = 0; plane < TPC.Nplanes(); ++plane) {
330  CTP_t inCTP = EncodeCTP(slc.TPCID.Cryostat, slc.TPCID.TPC, plane);
331  // print detailed debug info for one plane
332  bool prtCTP = (prt2S && inCTP == debug.CTP);
333  // Create a shower for each one
334  for(auto& tjl : bigList[plane]) {
335  if(tjl.empty()) continue;
336  if(prtCTP) {
337  mf::LogVerbatim myprt("TC");
338  myprt<<"Plane "<<plane<<" tjList";
339  for(auto& tjID : tjl) myprt<<" "<<tjID;
340  }
341  auto ss = CreateSS(slc, tjl);
342  if(ss.ID == 0) continue;
343  if(!UpdateShower(fcnLabel, slc, ss, prtCTP)) continue;
344  SaveTjInfo(slc, ss, "DS");
345  FindNearbyTjs(fcnLabel, slc, ss, prtCTP);
346  // don't try to do anything else here until all of the showers are defined
347  if(!StoreShower(fcnLabel, slc, ss)) {
348  std::cout<<fcnLabel<<" StoreShower failed 2S"<<ss.ID<<"\n";
349  MakeShowerObsolete(fcnLabel, slc, ss, prtCTP);
350  }
351  } // tjl
352  ChkAssns(fcnLabel, slc);
353  // try to merge showers in this plane using the lists of nearby Tjs
354  if(inCTP == UINT_MAX) continue;
355  if(slc.cots.empty()) continue;
356  if(prtCTP) Print2DShowers("tjl", slc, inCTP, false);
357  MergeShowerChain(fcnLabel, slc, inCTP, prtCTP);
358  SaveAllCots(slc, inCTP, "MSC");
359  if(prtCTP) Print2DShowers("MSCo", slc, inCTP, false);
360  MergeOverlap(fcnLabel, slc, inCTP, prtCTP);
361  SaveAllCots(slc, inCTP, "MO");
362  if(prtCTP) Print2DShowers("MO", slc, inCTP, false);
363  MergeNearby2DShowers(fcnLabel, slc, inCTP, prtCTP);
364  SaveAllCots(slc, inCTP, "MSS");
365  // merge sub-showers with other showers
366  MergeSubShowers(fcnLabel, slc, inCTP, prtCTP);
367  // merge sub-showers with shower-like tjs
368  MergeSubShowersTj(fcnLabel, slc, inCTP, prtCTP);
369  SaveAllCots(slc, inCTP, "MNrby");
370  if(prtCTP) Print2DShowers("Nrby", slc, inCTP, false);
371  bool tryMerge = false;
372  for(unsigned short ii = 0; ii < slc.cots.size(); ++ii) {
373  auto& ss = slc.cots[ii];
374  if(ss.ID == 0) continue;
375  if(ss.CTP != inCTP) continue;
376  if(AddTjsInsideEnvelope(fcnLabel, slc, ss, prtCTP)) tryMerge = true;
377  if (tcc.modes[kSaveShowerTree]) SaveAllCots(slc, inCTP, "Merge");
378  }
379  if(tryMerge) MergeNearby2DShowers(fcnLabel, slc, inCTP, prtCTP);
380  SaveAllCots(slc, inCTP, "ATj2");
381  if(prtCTP) Print2DShowers("ATIE", slc, inCTP, false);
382  } // plane
383  if(slc.cots.empty()) return false;
384  if(prt3S) Print2DShowers("B4", slc, USHRT_MAX, false);
385  // Match in 3D, make 3D showers and define them
386  Match2DShowers(fcnLabel, slc, prt3S);
387  SaveAllCots(slc, "M2DS");
388  // Reconcile pfp and shower assns before the Parent search
389  Reconcile3D(fcnLabel, slc, false, prt3S);
390  SaveAllCots(slc, "R3D");
391 // std::cout<<"Add function to check for neutrino vertex inside showers\n";
392  for(auto& ss3 : slc.showers) {
393  if(ss3.ID == 0) continue;
394  FindParent(fcnLabel, slc, ss3, prt3S);
395  } // ss3
396  // Reconcile pfp and shower assns again
397  Reconcile3D(fcnLabel, slc, true, prt3S);
398  if(prt3S) Print2DShowers("M2DS", slc, USHRT_MAX, false);
399  SaveAllCots(slc, "FP");
400 
401  // kill low energy 3D showers
402  for(auto& ss3 : slc.showers) {
403  if(ss3.ID == 0) continue;
404  bool killMe = (ShowerEnergy(ss3) < tcc.showerTag[3]);
405  if(killMe) MakeShowerObsolete(fcnLabel, slc, ss3, prt3S);
406  } // ss3
407 
408  // kill 2D showers that are either below threshold or have only one tj
409  for(auto& ss : slc.cots) {
410  if(ss.ID == 0) continue;
411  if(ss.SS3ID > 0) continue;
412  bool killMe = (ss.TjIDs.size() == 1 || ss.Energy < tcc.showerTag[3]);
413  // too small aspect ratio -> something track-like with some shower-like fuzz
414  if(ss.AspectRatio < tcc.showerTag[10]) killMe = true;
415  if(killMe) MakeShowerObsolete(fcnLabel, slc, ss, prt3S);
416  } // ss
417 
418  unsigned short nNewShowers = 0;
419  for(auto& ss : slc.cots) {
420  if(ss.ID == 0) continue;
421  if(ss.TjIDs.empty()) continue;
422  SaveTjInfo(slc, ss, "Done");
423  ++nNewShowers;
424  } // ss
425 
426  return (nNewShowers > 0);
427 
428  } // FindShowers3D
void MergeNearby2DShowers(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
Definition: TCShower.cxx:2374
void MergeShowerChain(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
Definition: TCShower.cxx:2573
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4560
TCConfig tcc
Definition: DataStructs.cxx:6
unsigned int Nplanes() const
Number of planes in this tpc.
Definition: TPCGeo.h:145
Geometry information for a single TPC.
Definition: TPCGeo.h:37
Float_t ss
Definition: plot.C:23
void PrintAllTraj(std::string someText, TCSlice &slc, unsigned short itj, unsigned short ipt, bool prtVtx)
Definition: Utils.cxx:5197
bool Reconcile3D(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:580
void SaveAllCots(TCSlice &slc, const CTP_t &inCTP, std::string someText)
Definition: TCShTree.cxx:165
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:507
void PrintPFPs(std::string someText, TCSlice &slc)
Definition: Utils.cxx:5661
ShowerStruct CreateSS(TCSlice &slc, const std::vector< int > &tjl)
Definition: TCShower.cxx:4514
std::vector< float > showerTag
[min MCSMom, max separation, min # Tj < separation] for a shower tag
Definition: DataStructs.h:474
save shower tree
Definition: DataStructs.h:456
void FindCots(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, std::vector< std::vector< int >> &tjLists, bool prt)
Definition: TCShower.cxx:3416
void MergeSubShowersTj(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
Definition: TCShower.cxx:2699
void MakeShowerObsolete(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3266
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1230
float ShowerEnergy(TCSlice &slc, const std::vector< int > tjIDs)
Definition: TCShower.cxx:4382
DebugStuff debug
Definition: DebugStruct.cxx:4
void SaveTjInfo(TCSlice &slc, std::vector< std::vector< int >> &tjList, std::string stageName)
Definition: TCShTree.cxx:5
void FindNearbyTjs(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3762
void MergeOverlap(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
Definition: TCShower.cxx:2461
const geo::GeometryCore * geom
Definition: DataStructs.h:493
bool AddTjsInsideEnvelope(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3929
bool StoreShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss)
Definition: TCShower.cxx:4449
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
bool FindParent(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1668
unsigned int CTP_t
Definition: DataStructs.h:41
void Match2DShowers(std::string inFcnLabel, TCSlice &slc, bool prt)
Definition: TCShower.cxx:882
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
void DefineDontCluster(TCSlice &slc, bool prt)
Definition: TCShower.cxx:3329
void MergeSubShowers(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
Definition: TCShower.cxx:2810
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
void Print2DShowers(std::string someText, TCSlice &slc, CTP_t inCTP, bool printKilledShowers)
Definition: TCShower.cxx:4648
CTP_t CTP
set to an invalid CTP
Definition: DebugStruct.h:22
bool tca::FindShowerStart ( TCSlice slc,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 45 of file TCShower.cxx.

References tca::ShowerStruct3D::ChgPos, tca::ShowerStruct3D::CotIDs, tca::TCSlice::cots, tca::ShowerStruct3D::Dir, DotProd(), tca::ShowerStruct3D::End, tca::ShowerStruct3D::ID, tca::ShowerStruct3D::Len, MakeBareTP(), tca::ShowerStruct3D::OpenAngle, PosSep(), ReverseShower(), ss, tca::ShowerStruct3D::Start, tcc, tca::TCSlice::tjs, tca::TCSlice::vtx3s, tca::ShowerStruct3D::Vx3ID, and tca::TCConfig::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 = slc.cots[cid - 1];
69  // Find the position, direction and projection in this plane
70  auto& stj = slc.tjs[ss.ShowerTjID - 1];
71  auto chgCtrTP = MakeBareTP(slc, 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", slc, useCID, prt);
95  }
96 
97  // now define the start and length
98  auto& ss = slc.cots[useCID - 1];
99  auto& stj = slc.tjs[ss.ShowerTjID - 1];
100 
101  auto chgCtrTP = MakeBareTP(slc, ss3.ChgPos, ss3.Dir, stj.CTP);
102  if(ss3.Vx3ID > 0) {
103  auto& vx3 = slc.vtx3s[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 = tcc.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 = tcc.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
void ReverseShower(std::string inFcnLabel, TCSlice &slc, int cotID, bool prt)
Definition: TCShower.cxx:3230
TCConfig tcc
Definition: DataStructs.cxx:6
Float_t ss
Definition: plot.C:23
TrajPoint MakeBareTP(TCSlice &slc, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
Definition: Utils.cxx:3523
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:59
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
void tca::FindSoftKink ( TCSlice slc,
Trajectory tj 
)

Definition at line 2211 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::TCConfig::dbgStp, DeltaAngle(), tca::Trajectory::EndPt, tca::Trajectory::ID, tca::TCConfig::kinkCuts, kNewStpCuts, kSoftKink, kStiffEl, tca::Trajectory::MCSMom, MCSMom(), PrintPos(), tca::Trajectory::Pts, SetEndPoints(), tca::Trajectory::Strategy, tcc, UnsetUsedHits(), and tca::TCConfig::useAlg.

2212  {
2213  // Looks for a soft kink in the trajectory and truncates it if one is found.
2214  // This is best done after FixTrajBegin has been called.
2215 
2216  if(!tcc.useAlg[kSoftKink]) return;
2217  if(tcc.useAlg[kNewStpCuts] && tj.Strategy[kStiffEl]) return;
2218  if(tj.Pts.size() < 15) return;
2219  if(tj.MCSMom < 100) return;
2220 
2221  float dang = DeltaAngle(tj.Pts[tj.EndPt[0]].Ang, tj.Pts[tj.EndPt[1]].Ang);
2222 
2223  if(tcc.dbgStp) {
2224  mf::LogVerbatim("TC")<<"FindSoftKink: "<<tj.ID<<" dang "<<dang<<" cut "<<0.5 * tcc.kinkCuts[0];
2225  }
2226  if(dang < 0.5 * tcc.kinkCuts[0]) return;
2227  // require at least 5 points fitted at the end of the trajectory
2228  unsigned short endPt = tj.EndPt[1];
2229  if(tj.Pts[endPt].NTPsFit < 5) return;
2230  if(tj.Pts[endPt].NTPsFit > endPt) return;
2231  // Estimate where where the kink would be
2232  unsigned short kinkPt = endPt - tj.Pts[endPt].NTPsFit;
2233  // Require at least 5 points in the trajectory before the kink
2234  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" kinkPt "<<kinkPt<<" NTPsFit at kinkPt "<<tj.Pts[kinkPt].NTPsFit<<" max "<<0.5 * kinkPt;
2235  if(kinkPt < 5) return;
2236  // require fewer points fitted in this region compared the number of points prior to it
2237  if(tj.Pts[kinkPt].NTPsFit > 0.5 * kinkPt) return;
2238  // scan back until we find the maximum number of points fitted
2239  unsigned short maxPtsFit = tj.Pts[kinkPt].NTPsFit;
2240  unsigned short atPt = kinkPt;
2241  for(unsigned short ipt = kinkPt; kinkPt > tj.EndPt[0] + 5; --ipt) {
2242  if(tj.Pts[ipt].NTPsFit > maxPtsFit) {
2243  maxPtsFit = tj.Pts[ipt].NTPsFit;
2244  atPt = ipt;
2245  }
2246  // stop scanning when the max starts falling
2247  if(tj.Pts[ipt].NTPsFit < maxPtsFit) break;
2248  if(ipt == 0) break;
2249  } // ipt
2250  if(atPt < 5) return;
2251  // require the trajectory be straight before the kink - the section we are going to keep
2252  if(MCSMom(slc, tj, tj.EndPt[0], atPt) < 500) return;
2253  // release the hits in TPs after this point
2254  for(unsigned short ipt = atPt; ipt < tj.Pts.size(); ++ipt) UnsetUsedHits(slc, tj.Pts[ipt]);
2255  // Truncate the trajectory at this point
2256  tj.Pts.resize(atPt + 1);
2257  SetEndPoints(tj);
2258  tj.AlgMod[kSoftKink] = true;
2259  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" truncated trajectory at "<<PrintPos(slc, tj.Pts[tj.Pts.size()-1]);
2260 
2261  } // FindSoftKinks
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
std::vector< float > kinkCuts
kink angle, nPts fit, (alternate) kink angle significance
Definition: DataStructs.h:475
short MCSMom(TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2914
TCConfig tcc
Definition: DataStructs.cxx:6
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1162
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1636
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
use the stiff electron strategy
Definition: DataStructs.h:418
void tca::FindStartChg ( std::string  inFcnLabel,
TCSlice slc,
int  cotID,
bool  prt 
)

Definition at line 4076 of file TCShower.cxx.

References tca::ShowerStruct::AspectRatio, tca::TCSlice::cots, tca::ShowerStruct::DirectionFOM, tca::ShowerStruct::ID, tca::ShowerStruct::ParentID, tca::TCConfig::showerTag, tca::ShowerStruct::ShowerTjID, ss, StartChgVec(), tcc, tca::ShowerStruct::TjIDs, and tca::TCSlice::tjs.

4077  {
4078  // Finds the charge at the start of a shower and puts it in AveChg of the first
4079  // point of the shower Tj. This is only done when there is no parent.
4080  if(cotID > (int)slc.cots.size()) return;
4081 
4082  ShowerStruct& ss = slc.cots[cotID - 1];
4083  if(ss.ID == 0) return;
4084  if(ss.TjIDs.empty()) return;
4085  if(ss.ShowerTjID == 0) return;
4086  if(ss.ParentID > 0) return;
4087  auto& stp0 = slc.tjs[ss.ShowerTjID - 1].Pts[0];
4088 
4089  std::string fcnLabel = inFcnLabel + ".FSC";
4090 
4091  stp0.AveChg = 0;
4092 
4093  if(ss.AspectRatio > tcc.showerTag[10] || ss.DirectionFOM > tcc.showerTag[9]) {
4094  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Not possible due to poor AspectRatio "<<ss.AspectRatio<<" or ss.DirectionFOM "<<ss.DirectionFOM;
4095  return;
4096  }
4097 
4098  // Create and fill a vector of the charge at the beginning of the shower in 1 WSE bins
4099  auto schg = StartChgVec(slc, cotID, prt);
4100  if(schg.empty()) return;
4101 
4102  // Look for two consecutive charge entries. Use the second one
4103  // for the initial guess at the charge
4104  unsigned short startPt = USHRT_MAX;
4105  float chg = 0;
4106  for(unsigned short ii = 0; ii < schg.size() - 1; ++ii) {
4107  if(schg[ii] > 0 && schg[ii + 1] > 0) {
4108  startPt = ii + 1;
4109  chg = schg[ii + 1];
4110  break;
4111  }
4112  }
4113  if(startPt == USHRT_MAX) return;
4114 
4115  // get an initial average and rms using all the points
4116  float ave = 0;
4117  float rms = 0;
4118  float cnt = 0;
4119  for(unsigned short ii = startPt; ii < schg.size() - 1; ++ii) {
4120  ave += schg[ii];
4121  rms += schg[ii] * schg[ii];
4122  ++cnt;
4123  } // ii
4124  ave /= cnt;
4125  rms = rms - cnt * ave * ave;
4126  if(rms < 0) return;
4127  rms = sqrt(rms / (cnt - 1));
4128 
4129  if(prt) {
4130  mf::LogVerbatim myprt("TC");
4131  myprt<<fcnLabel<<" schg:";
4132  for(unsigned short ii = 0; ii < 20; ++ii) myprt<<" "<<(int)schg[ii];
4133  myprt<<"\n First guess at the charge "<<(int)chg<<" average charge of all bins "<<(int)ave<<" rms "<<(int)rms;
4134  }
4135 
4136  // initial guess at the charge rms
4137  rms = 0.8 * chg;
4138 
4139  // Correct for dead wires in this region - maybe later...
4140 // unsigned short nDeadWires = DeadWireCount();
4141 
4142  unsigned short nBinsAverage = 5;
4143  double maxChg = 2 * chg;
4144  for(unsigned short nit = 0; nit < 2; ++nit) {
4145  double sum = 0;
4146  double sum2 = 0;
4147  double cnt = 0;
4148  for(unsigned short ii = startPt; ii < schg.size() - 1; ++ii) {
4149  // break if we find 2 consecutive high charge points
4150  if(schg[ii] > maxChg && schg[ii + 1] > maxChg) break;
4151  // or two zeros
4152  if(schg[ii] == 0 && schg[ii + 1] == 0) break;
4153  if(schg[ii] > maxChg) continue;
4154  sum += schg[ii];
4155  sum2 += schg[ii] * schg[ii];
4156  ++cnt;
4157  if(cnt == nBinsAverage) break;
4158  } // ii
4159  // check for a failure
4160  if(cnt < 3) {
4161  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" nit "<<nit<<" cnt "<<cnt<<" is too low. sum "<<(int)sum<<" maxChg "<<(int)maxChg;
4162  // try to recover. Pick the next point
4163  ++startPt;
4164  chg = schg[startPt];
4165  maxChg = 2 * chg;
4166  continue;
4167  }
4168  // convert sum to the average charge
4169  chg = sum / cnt;
4170  double arg = sum2 - cnt * chg * chg;
4171  if(arg < 0) break;
4172  rms = sqrt(arg / (cnt - 1));
4173  // don't allow the rms to get crazy
4174  double maxrms = 0.5 * sum;
4175  if(rms > maxrms) rms = maxrms;
4176  maxChg = chg + 2 * rms;
4177  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" nit "<<nit<<" cnt "<<cnt<<" chg "<<(int)chg<<" rms "<<(int)rms<<" maxChg "<<(int)maxChg<<" nBinsAverage "<<nBinsAverage;
4178  nBinsAverage = 20;
4179  } // nit
4180 
4181  stp0.AveChg = chg;
4182 
4183  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 2S"<<cotID<<" Starting charge "<<(int)stp0.AveChg<<" startPt "<<startPt;
4184 
4185  } // FindStartChg
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
Float_t ss
Definition: plot.C:23
for(int i=0;i< 401;i++)
std::vector< float > showerTag
[min MCSMom, max separation, min # Tj < separation] for a shower tag
Definition: DataStructs.h:474
if(nlines<=0)
std::vector< float > StartChgVec(TCSlice &slc, int cotID, bool prt)
Definition: TCShower.cxx:4188
void tca::FindUseHits ( TCSlice slc,
Trajectory tj,
unsigned short  ipt,
float  maxDelta,
bool  useChg 
)

Definition at line 1923 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::TCEvent::allHits, tca::TrajPoint::AngleCode, tca::TrajPoint::AveChg, tca::Trajectory::AveChg, tca::TCConfig::chargeCuts, tca::Trajectory::ChgRMS, tca::TCConfig::dbgStp, tca::TrajPoint::Delta, tca::TrajPoint::Dir, tca::Trajectory::EndPt, evt, ExpectedHitsRMS(), GetHitMultiplet(), tca::TrajPoint::Hits, HitsRMSTick(), HitTimeErr(), tca::Trajectory::ID, kNewStpCuts, kRvPrp, kStiffEl, kUnusedHits, LongPulseHit(), tca::Trajectory::MCSMom, tca::Trajectory::PDGCode, PointTrajDOCA(), tca::TrajPoint::Pos, PrintHit(), tca::Trajectory::Pts, tca::TCSlice::slHits, tca::Trajectory::Strategy, tcc, TPHitsRMSTick(), tca::TCConfig::unitsPerTick, tca::TCConfig::useAlg, and tca::TrajPoint::UseHit.

Referenced by AddHits().

1924  {
1925  // Hits have been associated with trajectory point ipt but none are used. Here we will
1926  // decide which hits to use.
1927 
1928  if(ipt > tj.Pts.size() - 1) return;
1929  TrajPoint& tp = tj.Pts[ipt];
1930 
1931  if(tp.Hits.empty()) return;
1932 /* Nov 6, 2018. This is a bad idea if widely separated hits were associated with the TP
1933  // Use all available hits on the last pass for the first few points when starting out
1934  if(ipt < 3 && tj.Pass == tcc.minPts.size() - 1) {
1935  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1936  unsigned int iht = tp.Hits[ii];
1937  if(slc.slHits[iht].InTraj > 0) continue;
1938  tp.UseHit[ii] = true;
1939  slc.slHits[iht].InTraj = tj.ID;
1940  }
1941  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"FUH: Using all hits on seed trajectory on the last pass";
1942  return;
1943  } // last pass for the first two points
1944 */
1945  // don't check charge when starting out
1946  if(ipt < 5) useChg = false;
1947  float chgPullCut = 1000;
1948  if(useChg) chgPullCut = tcc.chargeCuts[0];
1949  // open it up for RevProp, since we might be following a stopping track
1950  if(tj.AlgMod[kRvPrp]) chgPullCut *= 2;
1951  if(tj.MCSMom < 30) chgPullCut *= 2;
1952 
1953  bool ignoreLongPulseHits = false;
1954  unsigned short npts = tj.EndPt[1] - tj.EndPt[0] + 1;
1955  if(tcc.useAlg[kNewStpCuts] && (npts < 10 || tj.AlgMod[kRvPrp])) ignoreLongPulseHits = true;
1956 
1957  float expectedHitsRMS = ExpectedHitsRMS(slc, tp);
1958  if(tcc.dbgStp) {
1959  mf::LogVerbatim("TC")<<"FUH: maxDelta "<<maxDelta<<" useChg requested "<<useChg<<" Norm AveChg "<<(int)tp.AveChg<<" tj.ChgRMS "<<std::setprecision(2)<<tj.ChgRMS<<" chgPullCut "<<chgPullCut<<" TPHitsRMS "<<(int)TPHitsRMSTick(slc, tp, kUnusedHits)<<" ExpectedHitsRMS "<<(int)expectedHitsRMS<<" AngCode "<<tp.AngleCode;
1960  }
1961 
1962  // inverse of the path length for normalizing hit charge to 1 WSE unit
1963  float pathInv = std::abs(tp.Dir[0]);
1964  if(pathInv < 0.05) pathInv = 0.05;
1965 
1966  // Find the hit that has the smallest delta and the number of available hits
1967  tp.Delta = maxDelta;
1968  float delta;
1969  unsigned short imbest = USHRT_MAX;
1970  std::vector<float> deltas(tp.Hits.size(), 100);
1971  // keep track of the best delta - even if it is used
1972  float bestDelta = maxDelta;
1973  unsigned short nAvailable = 0;
1974  unsigned short firstAvailable = USHRT_MAX;
1975  unsigned short lastAvailable = USHRT_MAX;
1976  unsigned short firstUsed = USHRT_MAX;
1977  unsigned short imBadRecoHit = USHRT_MAX;
1978  bool bestHitLongPulse = false;
1979  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1980  tp.UseHit[ii] = false;
1981  unsigned int iht = tp.Hits[ii];
1982  delta = PointTrajDOCA(slc, iht, tp);
1983  if(delta < bestDelta) bestDelta = delta;
1984  if(slc.slHits[iht].InTraj > 0) {
1985  if(firstUsed == USHRT_MAX) firstUsed = ii;
1986  continue;
1987  }
1988  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1989  if(ignoreLongPulseHits && LongPulseHit(hit)) continue;
1990  if(hit.GoodnessOfFit() < 0 || hit.GoodnessOfFit() > 100) imBadRecoHit = ii;
1991  if(firstAvailable == USHRT_MAX) firstAvailable = ii;
1992  lastAvailable = ii;
1993  ++nAvailable;
1994  if(tcc.dbgStp) {
1995  if(useChg) {
1996  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" "<<ii<<" "<<PrintHit(slc.slHits[iht])<<" delta "<<delta<<" Norm Chg "<<(int)(hit.Integral() * pathInv);
1997  } else {
1998  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" "<<ii<<" "<<PrintHit(slc.slHits[iht])<<" delta "<<delta;
1999  }
2000  } // tcc.dbgStp
2001  deltas[ii] = delta;
2002  if(delta < tp.Delta) {
2003  tp.Delta = delta;
2004  imbest = ii;
2005  bestHitLongPulse = LongPulseHit(hit);
2006  }
2007  } // ii
2008 
2009  float chgWght = 0.5;
2010 
2011  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" firstAvailable "<<firstAvailable<<" lastAvailable "<<lastAvailable<<" firstUsed "<<firstUsed<<" imbest "<<imbest<<" single hit. tp.Delta "<<std::setprecision(2)<<tp.Delta<<" bestDelta "<<bestDelta<<" path length "<<1 / pathInv<<" imBadRecoHit "<<imBadRecoHit;
2012  if(imbest == USHRT_MAX || nAvailable == 0) return;
2013  unsigned int bestDeltaHit = tp.Hits[imbest];
2014 
2015  // just use the best hit if we are tracking a high energy electron and the best hit is a long pulse hit
2016  if(tj.Strategy[kStiffEl] && bestHitLongPulse) {
2017  tp.UseHit[imbest] = true;
2018  slc.slHits[bestDeltaHit].InTraj = tj.ID;
2019  return;
2020  }
2021 
2022  // Don't try to use a multiplet if a hit in the middle is in a different trajectory
2023  if(tp.Hits.size() > 2 && nAvailable > 1 && firstUsed != USHRT_MAX && firstAvailable < firstUsed && lastAvailable > firstUsed) {
2024  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" A hit in the middle of the multiplet is used. Use only the best hit";
2025  tp.UseHit[imbest] = true;
2026  slc.slHits[bestDeltaHit].InTraj = tj.ID;
2027  return;
2028  } // Used hit inside multiplet
2029 
2030  if(tp.AngleCode == 1) {
2031  // Get the hits that are in the same multiplet as bestDeltaHit
2032  std::vector<unsigned int> hitsInMultiplet;
2033  unsigned short localIndex;
2034  GetHitMultiplet(slc, bestDeltaHit, hitsInMultiplet, localIndex);
2035  if(tcc.dbgStp) {
2036  mf::LogVerbatim myprt("TC");
2037  myprt<<" bestDeltaHit "<<PrintHit(slc.slHits[bestDeltaHit]);
2038  myprt<<" in multiplet:";
2039  for(auto& iht : hitsInMultiplet) myprt<<" "<<PrintHit(slc.slHits[iht]);
2040  }
2041  // Consider the case where a bad reco hit might be better. It is probably wider and
2042  // has more charge
2043  if(imBadRecoHit != USHRT_MAX) {
2044  unsigned int iht = tp.Hits[imBadRecoHit];
2045  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2046  if(hit.RMS() > HitsRMSTick(slc, hitsInMultiplet, kUnusedHits)) {
2047  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Using imBadRecoHit "<<PrintHit(slc.slHits[iht]);
2048  tp.UseHit[imBadRecoHit] = true;
2049  slc.slHits[iht].InTraj = tj.ID;
2050  return;
2051  }
2052  } // bad reco hit
2053  // Use the hits in the multiplet instead
2054  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2055  unsigned int iht = tp.Hits[ii];
2056  if(slc.slHits[iht].InTraj > 0) continue;
2057  if(std::find(hitsInMultiplet.begin(), hitsInMultiplet.end(), iht) == hitsInMultiplet.end()) continue;
2058  tp.UseHit[ii] = true;
2059  slc.slHits[iht].InTraj = tj.ID;
2060  } // ii
2061  return;
2062  } // isLA
2063 
2064  // don't use the best UNUSED hit if the best delta is for a USED hit and it is much better
2065  // TY: ignore for RevProp
2066  if(bestDelta < 0.5 * tp.Delta && !tj.AlgMod[kRvPrp]) return;
2067 
2068  if(!useChg || (useChg && (tj.AveChg <= 0 || tj.ChgRMS <= 0))) {
2069  // necessary quantities aren't available for more careful checking
2070  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" tj.AveChg "<<tj.AveChg<<" or tj.ChgRMS "<<tj.ChgRMS<<". Use the best hit";
2071  tp.UseHit[imbest] = true;
2072  slc.slHits[bestDeltaHit].InTraj = tj.ID;
2073  return;
2074  }
2075 
2076  // Don't try to get fancy if we are tracking a stiff tj
2077  if(tj.PDGCode == 13 && bestDelta < 0.5) {
2078  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Tracking muon. Use the best hit";
2079  tp.UseHit[imbest] = true;
2080  slc.slHits[bestDeltaHit].InTraj = tj.ID;
2081  return;
2082  }
2083 
2084  // The best hit is the only one available or this is a small angle trajectory
2085  if(nAvailable == 1 || tp.AngleCode == 0) {
2086  auto& hit = (*evt.allHits)[slc.slHits[bestDeltaHit].allHitsIndex];
2087  float aveChg = tp.AveChg;
2088  if(aveChg <= 0) aveChg = tj.AveChg;
2089  if(aveChg <= 0) aveChg = hit.Integral();
2090  float chgRMS = tj.ChgRMS;
2091  if(chgRMS < 0.2) chgRMS = 0.2;
2092  float bestDeltaHitChgPull = std::abs(hit.Integral() * pathInv / aveChg - 1) / chgRMS;
2093  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" bestDeltaHitChgPull "<<bestDeltaHitChgPull<<" chgPullCut "<<chgPullCut;
2094  if(bestDeltaHitChgPull < chgPullCut || tp.Delta < 0.1) {
2095  tp.UseHit[imbest] = true;
2096  slc.slHits[bestDeltaHit].InTraj = tj.ID;
2097  } // good charge or very good delta
2098  return;
2099  } // bestDeltaHitMultiplicity == 1
2100 
2101  // Find the expected width for the angle of this TP (ticks)
2102  float expectedWidth = ExpectedHitsRMS(slc, tp);
2103 
2104  // Handle two available hits
2105  if(nAvailable == 2) {
2106  // See if these two are in the same multiplet and both are available
2107  std::vector<unsigned int> tHits;
2108  unsigned short localIndex;
2109  GetHitMultiplet(slc, bestDeltaHit, tHits, localIndex);
2110  // ombest is the index of the other hit in tp.Hits that is in the same multiplet as bestDeltaHit
2111  // if we find it
2112  unsigned short ombest = USHRT_MAX;
2113  unsigned int otherHit = INT_MAX;
2114  if(tHits.size() == 2) {
2115  otherHit = tHits[1 - localIndex];
2116  // get the index of this hit in tp.Hits
2117  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2118  if(slc.slHits[tp.Hits[ii]].InTraj > 0) continue;
2119  if(tp.Hits[ii] == otherHit) {
2120  ombest = ii;
2121  break;
2122  }
2123  } // ii
2124  } // tHits.size() == 2
2125  if(tcc.dbgStp) {
2126  mf::LogVerbatim("TC")<<" Doublet: imbest "<<imbest<<" ombest "<<ombest;
2127  }
2128  // The other hit exists in the tp and it is available
2129  if(ombest < tp.Hits.size()) {
2130  // compare the best delta hit and the other hit separately and the doublet as a merged pair
2131  float bestHitDeltaErr = std::abs(tp.Dir[1]) * 0.17 + std::abs(tp.Dir[0]) * HitTimeErr(slc, bestDeltaHit);
2132  // Construct a FOM starting with the delta pull
2133  float bestDeltaHitFOM = deltas[imbest] / bestHitDeltaErr;
2134  if(bestDeltaHitFOM < 0.5) bestDeltaHitFOM = 0.5;
2135  // multiply by the charge pull if it is significant
2136  auto& hit = (*evt.allHits)[slc.slHits[bestDeltaHit].allHitsIndex];
2137  float bestDeltaHitChgPull = std::abs(hit.Integral() * pathInv / tp.AveChg - 1) / tj.ChgRMS;
2138  if(bestDeltaHitChgPull > 1) bestDeltaHitFOM *= chgWght * bestDeltaHitChgPull;
2139  // scale by the ratio
2140  float rmsRat = hit.RMS() / expectedWidth;
2141  if(rmsRat < 1) rmsRat = 1 / rmsRat;
2142  bestDeltaHitFOM *= rmsRat;
2143  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" bestDeltaHit FOM "<<deltas[imbest]/bestHitDeltaErr<<" bestDeltaHitChgPull "<<bestDeltaHitChgPull<<" rmsRat "<<rmsRat<<" bestDeltaHitFOM "<<bestDeltaHitFOM;
2144  // Now do the same for the other hit
2145  float otherHitDeltaErr = std::abs(tp.Dir[1]) * 0.17 + std::abs(tp.Dir[0]) * HitTimeErr(slc, otherHit);
2146  float otherHitFOM = deltas[ombest] / otherHitDeltaErr;
2147  if(otherHitFOM < 0.5) otherHitFOM = 0.5;
2148  auto& ohit = (*evt.allHits)[slc.slHits[otherHit].allHitsIndex];
2149  float otherHitChgPull = std::abs(ohit.Integral() * pathInv / tp.AveChg - 1) / tj.ChgRMS;
2150  if(otherHitChgPull > 1) otherHitFOM *= chgWght * otherHitChgPull;
2151  rmsRat = ohit.RMS() / expectedWidth;
2152  if(rmsRat < 1) rmsRat = 1 / rmsRat;
2153  otherHitFOM *= rmsRat;
2154  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" otherHit FOM "<<deltas[ombest]/otherHitDeltaErr<<" otherHitChgPull "<<otherHitChgPull<<" rmsRat "<<rmsRat<<" otherHitFOM "<<otherHitFOM;
2155  // And for the doublet
2156  float doubletChg = hit.Integral() + ohit.Integral();
2157  float doubletTime = (hit.Integral() * hit.PeakTime() + ohit.Integral() * ohit.PeakTime()) / doubletChg;
2158  doubletChg *= pathInv;
2159  doubletTime *= tcc.unitsPerTick;
2160  float doubletWidthTick = TPHitsRMSTick(slc, tp, kUnusedHits);
2161  float doubletRMSTimeErr = doubletWidthTick * tcc.unitsPerTick;
2162  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" doublet Chg "<<doubletChg<<" doubletTime "<<doubletTime<<" doubletRMSTimeErr "<<doubletRMSTimeErr;
2163  float doubletFOM = PointTrajDOCA(slc, tp.Pos[0], doubletTime, tp) / doubletRMSTimeErr;
2164  if(doubletFOM < 0.5) doubletFOM = 0.5;
2165  float doubletChgPull = std::abs(doubletChg * pathInv / tp.AveChg - 1) / tj.ChgRMS;
2166  if(doubletChgPull > 1) doubletFOM *= chgWght * doubletChgPull;
2167  rmsRat = doubletWidthTick / expectedWidth;
2168  if(rmsRat < 1) rmsRat = 1 / rmsRat;
2169  doubletFOM *= rmsRat;
2170  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" doublet FOM "<<PointTrajDOCA(slc, tp.Pos[0], doubletTime, tp)/doubletRMSTimeErr<<" doubletChgPull "<<doubletChgPull<<" rmsRat "<<rmsRat<<" doubletFOM "<<doubletFOM;
2171  if(doubletFOM < bestDeltaHitFOM && doubletFOM < otherHitFOM) {
2172  tp.UseHit[imbest] = true;
2173  slc.slHits[bestDeltaHit].InTraj = tj.ID;
2174  tp.UseHit[ombest] = true;
2175  slc.slHits[otherHit].InTraj = tj.ID;
2176  } else {
2177  // the doublet is not the best
2178  if(bestDeltaHitFOM < otherHitFOM) {
2179  tp.UseHit[imbest] = true;
2180  slc.slHits[bestDeltaHit].InTraj = tj.ID;
2181  } else {
2182  tp.UseHit[ombest] = true;
2183  slc.slHits[otherHit].InTraj = tj.ID;
2184  } // otherHit is the best
2185  } // doublet is not the best
2186  } else {
2187  // the other hit isn't available. Just use the singlet
2188  tp.UseHit[imbest] = true;
2189  slc.slHits[bestDeltaHit].InTraj = tj.ID;
2190  }
2191  return;
2192  } // nAvailable == 2
2193  float hitsWidth = TPHitsRMSTick(slc, tp, kUnusedHits);
2194  float maxTick = tp.Pos[1] / tcc.unitsPerTick + 0.6 * expectedWidth;
2195  float minTick = tp.Pos[1] / tcc.unitsPerTick - 0.6 * expectedWidth;
2196  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Multiplet: hitsWidth "<<hitsWidth<<" expectedWidth "<<expectedWidth<<" tick range "<<(int)minTick<<" "<<(int)maxTick;
2197  // use all of the hits in the tick window
2198  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2199  unsigned int iht = tp.Hits[ii];
2200  if(slc.slHits[iht].InTraj > 0) continue;
2201  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2202  if(hit.PeakTime() < minTick) continue;
2203  if(hit.PeakTime() > maxTick) continue;
2204  tp.UseHit[ii] = true;
2205  slc.slHits[iht].InTraj = tj.ID;
2206  }
2207 
2208  } // FindUseHits
float HitsRMSTick(TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
Definition: Utils.cxx:3706
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
float ExpectedHitsRMS(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:1802
for(int i=0;i< 401;i++)
bool LongPulseHit(const recob::Hit &hit)
Definition: Utils.cxx:3936
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:5704
Detector simulation of raw signals on wires.
float HitTimeErr(TCSlice &slc, unsigned int iht)
Definition: StepUtils.cxx:1693
std::vector< float > chargeCuts
Definition: DataStructs.h:478
art::PtrVector< recob::Hit > Hits
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
float TPHitsRMSTick(TCSlice &slc, TrajPoint &tp, HitStatus_t hitRequest)
Definition: Utils.cxx:3674
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
use the stiff electron strategy
Definition: DataStructs.h:418
void GetHitMultiplet(TCSlice &slc, unsigned int theHit, std::vector< unsigned int > &hitsInMultiplet, unsigned short &localIndex)
Definition: StepUtils.cxx:1580
TCEvent evt
Definition: DataStructs.cxx:5
void tca::FindVtxTjs ( TCSlice slc,
VtxStore vx2 
)

Definition at line 409 of file TCVertex.cxx.

References tca::Trajectory::AlgMod, tca::TCEvent::allHits, CheckTraj(), tca::VtxStore::CTP, tca::TCConfig::dbg2V, tca::TCConfig::dbgAlg, DecodeCTP(), tca::Trajectory::EndPt, evt, FindCloseHits(), tca::TrajPoint::Hits, tca::VtxStore::ID, tca::Trajectory::ID, InTrajOK(), tca::Trajectory::IsGood, tca::TCSlice::isValid, kChkInTraj, kUnusedHits, kVtxTj, kVtxTrjTried, tca::TCConfig::minPts, MoveTPToWire(), NumPtsWithCharge(), tca::Trajectory::Pass, geo::PlaneID::Plane, tca::VtxStore::Pos, PrintHeader(), PrintHit(), PrintTrajPoint(), tca::Trajectory::Pts, ReleaseHits(), tca::VtxStore::Score, tca::TCSlice::slHits, StartTraj(), tca::VtxStore::Stat, StepAway(), tca::Trajectory::StepDir, StoreTraj(), tcc, tca::TCConfig::unitsPerTick, tca::TCConfig::useAlg, tca::TrajPoint::UseHit, valDecreasing(), tca::TCConfig::vtx2DCuts, and tca::Trajectory::VtxID.

410  {
411  // Look for available hits in the vicinity of this vertex and try to make
412  // a vertex trajectory from them
413 
414  if(!tcc.useAlg[kVtxTj]) return;
415 
416  if(vx2.Stat[kVtxTrjTried]) return;
417  // ignore low score
418  if(vx2.Score < tcc.vtx2DCuts[7]) return;
419 
420  bool prt = (tcc.dbg2V || tcc.dbgAlg[kVtxTj]);
421 
422  std::array<int, 2> wireWindow;
423  std::array<float, 2> timeWindow;
424 
425  // on the first try we look for small angle trajectories which will have hits
426  // with a large wire window and a small time window
427  // Vertex2DCuts fcl input usage
428  // 0 User definition of a short Tj => max number of Tj points
429  // 1 max separation between a vertex and the start of a trajectory for a user-defined short Tj
430  // 2 max separation for a user-defined long Tj
431  // 3 max position pull when attaching a Tj to a vertex
432  // 4 max position error for creating a Tj or attaching Tjs to an existing vertex
433  // 5 Min MCSMom of Tjs that can be used to create a vertex
434  // 6 min frac of Points/Wire between a vtx and a Tj. Ideally one if the efficiency is good
435  // 7 min Score
436  // 8 ID of a vertex for printing special debugging information
437  wireWindow[0] = std::nearbyint(vx2.Pos[0] - tcc.vtx2DCuts[1]);
438  wireWindow[1] = std::nearbyint(vx2.Pos[0] + tcc.vtx2DCuts[1]);
439  timeWindow[0] = vx2.Pos[1] - tcc.vtx2DCuts[1];
440  timeWindow[1] = vx2.Pos[1] + tcc.vtx2DCuts[1];
441 
442  geo::PlaneID planeID = DecodeCTP(vx2.CTP);
443  unsigned short ipl = planeID.Plane;
444 
445  if(prt) mf::LogVerbatim("TC")<<"inside FindVtxTjs 2v"<<vx2.ID<<" Window "<<wireWindow[0]<<" "<<wireWindow[1]<<" "<<timeWindow[0]/tcc.unitsPerTick<<" "<<timeWindow[1]/tcc.unitsPerTick<<" in plane "<<ipl;
446 
447  // find nearby available hits
448  bool hitsNear;
449  std::vector<unsigned int> closeHits = FindCloseHits(slc, wireWindow, timeWindow, ipl, kUnusedHits, true, hitsNear);
450  if(prt) {
451  mf::LogVerbatim myprt("TC");
452  myprt<<"closeHits";
453  for(auto& iht : closeHits) myprt<<" "<<PrintHit(slc.slHits[iht]);
454  }
455  if(closeHits.empty()) return;
456  // sort by distance from the vertex
457  std::vector<SortEntry> sortVec(closeHits.size());
458  SortEntry sortEntry;
459  for(unsigned short ii = 0; ii < closeHits.size(); ++ii) {
460  unsigned int iht = closeHits[ii];
461  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
462  float dw = hit.WireID().Wire - vx2.Pos[0];
463  float dt = tcc.unitsPerTick * hit.PeakTime() - vx2.Pos[1];
464  float d2 = dw * dw + dt * dt;
465  sortEntry.index = ii;
466  sortEntry.val = d2;
467  sortVec[ii] = sortEntry;
468  } // ii
469  std::sort(sortVec.begin(), sortVec.end(), valDecreasing);
470  unsigned int vWire = std::nearbyint(vx2.Pos[0]);
471  int vTick = vx2.Pos[1]/tcc.unitsPerTick;
472  if(prt) PrintHeader("FVT");
473  for(unsigned short ii = 0; ii < closeHits.size(); ++ii) {
474  unsigned int iht = closeHits[sortVec[ii].index];
475  if(slc.slHits[iht].InTraj > 0) continue;
476  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
477  // the direction will be poorly defined if a hit is very close to the vertex and it is in this list.
478  // Ignore these hits
479  if(hit.WireID().Wire == vWire) {
480  // on the vertex wire. Check for a close time
481  if(abs(hit.PeakTime() - vTick) < 10) continue;
482  } // hit on vtx wire
483  float toWire = hit.WireID().Wire;
484  float toTick = hit.PeakTime();
485  // assume the last pass and fix it later after the angle is calculated
486  unsigned short pass = tcc.minPts.size() - 1;
487  Trajectory tj;
488  if(!StartTraj(slc, tj, vx2.Pos[0], vx2.Pos[1]/tcc.unitsPerTick, toWire, toTick, vx2.CTP, pass)) continue;
489  // ensure that the first TP is good
490  if(tj.Pts[0].Pos[0] < 0) continue;
491  tj.VtxID[0] = vx2.ID;
492  TrajPoint tp = tj.Pts[0];
493  // Move the Pt to the hit
494  MoveTPToWire(tp, toWire);
495  // attach the hit
496  tp.Hits.push_back(iht);
497  tp.UseHit[tp.Hits.size()-1] = true;
498  slc.slHits[iht].InTraj = tj.ID;
499  tp.UseHit[tp.Hits.size()-1] = false;
500  if(prt) PrintTrajPoint("FVT", slc, 0, tj.StepDir, tj.Pass, tp);
501  // Step away and see what happens
502  StepAway(slc, tj);
503  // check for a major failure
504  if(!slc.isValid) return;
505  // Check the quality of the trajectory
506  CheckTraj(slc, tj);
507  if(!tj.IsGood || NumPtsWithCharge(slc, tj, true) < 2) {
508  if(prt) mf::LogVerbatim("TC")<<" xxxxxxx Not enough points "<<NumPtsWithCharge(slc, tj, true)<<" minimum "<<tcc.minPts[tj.Pass]<<" or !IsGood";
509  ReleaseHits(slc, tj);
510  continue;
511  }
512  tj.AlgMod[kVtxTj] = true;
513  slc.isValid = StoreTraj(slc, tj);
514  if(tcc.useAlg[kChkInTraj]) {
515  slc.isValid = InTrajOK(slc, "FVT");
516  if(!slc.isValid) {
517  mf::LogVerbatim("TC")<<"InTrajOK failed in FindVtxTjs";
518  return;
519  }
520  }
521  if(prt) mf::LogVerbatim("TC")<<"FindVtxTjs: calling StoreTraj with npts "<<tj.EndPt[1];
522  } // ii
523 
524  // Flag this as tried so we don't try again
525  vx2.Stat[kVtxTrjTried] = true;
526  } // FindVtxTjs
void ReleaseHits(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:1150
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void StepAway(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:15
bool InTrajOK(TCSlice &slc, std::string someText)
Definition: Utils.cxx:1333
FindVtxTraj algorithm tried.
Definition: DataStructs.h:73
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
bool StoreTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:1175
bool StartTraj(TCSlice &slc, Trajectory &tj, unsigned int fromhit, unsigned int tohit, unsigned short pass)
Definition: Utils.cxx:4431
std::vector< unsigned int > FindCloseHits(TCSlice &slc, std::array< int, 2 > const &wireWindow, Point2_t const &timeWindow, const unsigned short plane, HitStatus_t hitRequest, bool usePeakTime, bool &hitsNear)
Definition: Utils.cxx:2496
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
bool dbg2V
debug 2D vertex finding
Definition: DataStructs.h:510
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:5704
std::vector< unsigned short > minPts
min number of Pts required to make a trajectory
Definition: DataStructs.h:483
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
Detector simulation of raw signals on wires.
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
void CheckTraj(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:911
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
geo::PlaneID DecodeCTP(CTP_t CTP)
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:505
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:466
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2485
TCEvent evt
Definition: DataStructs.cxx:5
void PrintHeader(std::string someText)
Definition: Utils.cxx:5535
void PrintTrajPoint(std::string someText, TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, TrajPoint const &tp)
Definition: Utils.cxx:5541
bool valDecreasing(SortEntry c1, SortEntry c2)
Definition: Utils.cxx:14
void tca::FindXMatches ( TCSlice slc,
unsigned short  numPlanes,
short  maxScore,
std::vector< MatchStruct > &  matVec,
bool  prt 
)

Definition at line 1355 of file PFPUtils.cxx.

References detinfo::DetectorProperties::ConvertXToTicks(), tca::MatchStruct::Count, geo::CryostatID::Cryostat, tca::TrajPoint::CTP, DecodeCTP(), DeltaAngle(), tca::TCConfig::detprop, tca::TrajPoint3::Dir, EncodeCTP(), tca::TCConfig::geom, tca::SortEntry::index, MakeTp3(), tca::TCSlice::mallTraj, tca::TCConfig::match3DCuts, tca::TCConfig::maxPos0, tca::TCSlice::nPlanes, geo::PlaneID::Plane, tca::TrajPoint::Pos, tca::TrajPoint3::Pos, SignalAtTp(), tcc, tca::MatchStruct::TjIDs, tca::TCSlice::tjs, geo::TPCID::TPC, tca::TCConfig::unitsPerTick, valDecreasings(), and geo::GeometryCore::WireCoordinate().

Referenced by FindPFParticles().

1356  {
1357  // This function matches trajectory points in slc.mallTraj using the X position. These points should
1358  // have already been sorted by increasing X by the function that created mallTraj.
1359 
1360  if(slc.mallTraj.empty()) return;
1361  if(tcc.match3DCuts[0] <= 0) return;
1362  if(numPlanes < 2) return;
1363 
1364  int cstat = DecodeCTP(slc.mallTraj[0].ctp).Cryostat;
1365  int tpc = DecodeCTP(slc.mallTraj[0].ctp).TPC;
1366  constexpr float twopi = 2 * M_PI;
1367  constexpr float piOver2 = M_PI / 2;
1368 
1369  // create a temp vector to check for duplicates
1370  auto inMatVec = matVec;
1371  std::vector<MatchStruct> temp;
1372 
1373  // the minimum number of points for matching
1374  unsigned short minPts = 2;
1375  // override this with the user minimum for 2-plane matches
1376  if(numPlanes == 2) minPts = tcc.match3DCuts[2];
1377 
1378  // max number of match combos left
1379  unsigned int nAvailable = 0;
1380  if(matVec.size() < tcc.match3DCuts[4]) nAvailable = tcc.match3DCuts[4] - matVec.size();
1381  if(nAvailable == 0 || nAvailable > tcc.match3DCuts[4]) return;
1382 
1383  // these cuts presume that the resolution in X is better than it is in Y and Z
1384  float xcut = tcc.match3DCuts[0];
1385  double yzcut = 1.5 * xcut;
1386  for(unsigned int ipt = 0; ipt < slc.mallTraj.size() - 1; ++ipt) {
1387  auto& iTjPt = slc.mallTraj[ipt];
1388  // length cut
1389  if(iTjPt.npts < minPts) continue;
1390  // look for matches using Tjs that have the correct score
1391  if(iTjPt.score < 0 || iTjPt.score > maxScore) continue;
1392  auto& itp = slc.tjs[iTjPt.id - 1].Pts[iTjPt.ipt];
1393  unsigned short iplane = DecodeCTP(itp.CTP).Plane;
1394  for(unsigned int jpt = ipt + 1; jpt < slc.mallTraj.size() - 1; ++jpt) {
1395  auto& jTjPt = slc.mallTraj[jpt];
1396  // ensure that the planes are different
1397  if(jTjPt.ctp == iTjPt.ctp) continue;
1398  // length cut
1399  if(jTjPt.npts < minPts) continue;
1400  // score cut
1401  if(jTjPt.score < 0 || jTjPt.score > maxScore) continue;
1402  // check for x range overlap. We know that jTjPt.xlo is >= iTjPt.xlo because of the sort
1403  if(jTjPt.xlo > iTjPt.xhi) continue;
1404  // break out if the x range difference becomes large (5 cm)
1405  if(jTjPt.xlo > iTjPt.xhi + 5) break;
1406  auto& jtp = slc.tjs[jTjPt.id - 1].Pts[jTjPt.ipt];
1407  unsigned short jplane = DecodeCTP(jtp.CTP).Plane;
1408  TrajPoint3 tp3;
1409  if(!MakeTp3(slc, itp, jtp, tp3, false)) continue;
1410  // count weight is one for a two-plane match
1411  float cntWght = 1;
1412  if(numPlanes == 3) {
1413  // numPlanes == 3
1414  for(unsigned int kpt = jpt + 1; kpt < slc.mallTraj.size(); ++kpt) {
1415  auto& kTjPt = slc.mallTraj[kpt];
1416  // ensure that the planes are different
1417  if(kTjPt.ctp == iTjPt.ctp || kTjPt.ctp == jTjPt.ctp) continue;
1418  if(kTjPt.score < 0 || kTjPt.score > maxScore) continue;
1419  if(kTjPt.xlo > iTjPt.xhi) continue;
1420  // break out if the x range difference becomes large
1421  if(kTjPt.xlo > iTjPt.xhi + 5) break;
1422  auto& ktp = slc.tjs[kTjPt.id - 1].Pts[kTjPt.ipt];
1423  unsigned short kplane = DecodeCTP(ktp.CTP).Plane;
1424  TrajPoint3 iktp3;
1425  if(!MakeTp3(slc, itp, ktp, iktp3, false)) continue;
1426  if(std::abs(tp3.Pos[1] - iktp3.Pos[1]) > yzcut) continue;
1427  if(std::abs(tp3.Pos[2] - iktp3.Pos[2]) > yzcut) continue;
1428  float dang = 0;
1429  if(tcc.match3DCuts[1] > 0) {
1430  dang = std::abs(DeltaAngle(tp3.Dir, iktp3.Dir));
1431  while(dang > M_PI) dang -= twopi;
1432  if(dang > piOver2) dang = M_PI - dang;
1433  float mcsmom = slc.tjs[iTjPt.id - 1].MCSMom + slc.tjs[jTjPt.id - 1].MCSMom + slc.tjs[kTjPt.id - 1].MCSMom;
1434  mcsmom /= 3;
1435  if(mcsmom > 150 && dang > tcc.match3DCuts[1]) continue;
1436  }
1437  // we have a match.
1438  // Just fill temp. See if the Tj IDs are in the match list.
1439  // first check the input matVec
1440  bool gotit = false;
1441  for(auto& ms : inMatVec) {
1442  if(ms.TjIDs.size() != 3) continue;
1443  if(iTjPt.id == ms.TjIDs[iplane] && jTjPt.id == ms.TjIDs[jplane] && kTjPt.id == ms.TjIDs[kplane]) {
1444  gotit = true;
1445  break;
1446  }
1447  } // ms
1448  if(gotit) continue;
1449  // Triple match count = 2 de-weighted by delta angle
1450  cntWght = 2 - dang;
1451  if(cntWght <= 0) continue;
1452  // next check the temp vector
1453  unsigned short indx = 0;
1454  for(indx = 0; indx < temp.size(); ++indx) {
1455  auto& ms = temp[indx];
1456  if(iTjPt.id != ms.TjIDs[iplane]) continue;
1457  if(jTjPt.id != ms.TjIDs[jplane]) continue;
1458  if(kTjPt.id != ms.TjIDs[kplane]) continue;
1459  ms.Count += cntWght;
1460  break;
1461  } // indx
1462  if(indx == temp.size()) {
1463  // not found in the match vector so add it
1464  MatchStruct ms;
1465  ms.TjIDs.resize(3);
1466  // Note that we can put the Tj IDs in plane-order since there are 3 of them
1467  // This is not the case when there are 2 planes
1468  ms.TjIDs[iplane] = iTjPt.id;
1469  ms.TjIDs[jplane] = jTjPt.id;
1470  ms.TjIDs[kplane] = kTjPt.id;
1471  ms.Count = cntWght;
1472  temp.push_back(ms);
1473  // give up if there are too many
1474  if(temp.size() > nAvailable) break;
1475  } // not found in the list
1476  } // kpt
1477  // numPlanes == 3
1478  } else {
1479  // 2-plane TPC or 2-plane match in a 3-plane TPC
1480  if(slc.nPlanes == 3) {
1481  // See if there is a signal at this point.
1482  unsigned short kplane = 3 - iplane - jplane;
1483  float fkwire = tcc.geom->WireCoordinate(tp3.Pos[1], tp3.Pos[2], kplane, tpc, cstat);
1484  if(fkwire < 0 || fkwire > tcc.maxPos0[kplane]) continue;
1485  TrajPoint tpk;
1486  tpk.CTP = EncodeCTP(cstat, tpc, kplane);
1487  tpk.Pos[0] = fkwire;
1488  float xp = 0.5 * (iTjPt.xlo + iTjPt.xhi);
1489  tpk.Pos[1] = tcc.detprop->ConvertXToTicks(xp, kplane, tpc, cstat) * tcc.unitsPerTick;
1490  // Note that SignalAtTp assumes that a signal exists if the wire is dead
1491  if(!SignalAtTp(slc, tpk)) continue;
1492  }
1493  // Just fill temp. See if the Tj IDs are in the match list
1494  bool gotit = false;
1495  for(auto& ms : inMatVec) {
1496  if(std::find(ms.TjIDs.begin(), ms.TjIDs.end(), iTjPt.id) != ms.TjIDs.end() &&
1497  std::find(ms.TjIDs.begin(), ms.TjIDs.end(), jTjPt.id) != ms.TjIDs.end()) {
1498  gotit = true;
1499  break;
1500  }
1501  } // ms
1502  if(gotit) continue;
1503  unsigned short indx = 0;
1504  for(indx = 0; indx < temp.size(); ++indx) {
1505  auto& ms = temp[indx];
1506  if(std::find(ms.TjIDs.begin(), ms.TjIDs.end(), iTjPt.id) != ms.TjIDs.end() &&
1507  std::find(ms.TjIDs.begin(), ms.TjIDs.end(), jTjPt.id) != ms.TjIDs.end()) break;
1508  } // indx
1509  if(indx == temp.size()) {
1510  MatchStruct ms;
1511  ms.TjIDs.resize(2);
1512  // Here we put the Tj IDs in no particular order
1513  ms.TjIDs[0] = iTjPt.id;
1514  ms.TjIDs[1] = jTjPt.id;
1515  ms.Count = 1;
1516  temp.push_back(ms);
1517  } // not found in the list
1518  else {
1519  ++temp[indx].Count;
1520  }
1521  } // 2-plane TPC
1522  // give up if there are too many
1523  if(temp.size() > nAvailable) break;
1524  } // jpt
1525  // give up if there are too many
1526  if(temp.size() > nAvailable) break;
1527  } // ipt
1528 
1529  // temp
1530 
1531  if(temp.empty()) return;
1532 
1533  if(temp.size() == 1) {
1534  matVec.push_back(temp[0]);
1535  } else {
1536  // multiple entries - need to sort by decreasing match count
1537  std::vector<SortEntry> sortVec(temp.size());
1538  for(unsigned int indx = 0; indx < sortVec.size(); ++indx) {
1539  sortVec[indx].index = indx;
1540  sortVec[indx].val = temp[indx].Count;
1541  } // indx
1542  std::sort(sortVec.begin(), sortVec.end(), valDecreasings);
1543  // Re-order temp
1544  auto tmpVec = temp;
1545  for(unsigned int ii = 0; ii < sortVec.size(); ++ii) temp[ii] = tmpVec[sortVec[ii].index];
1546  // insert it after the triple matches
1547  matVec.insert(matVec.end(), temp.begin(), temp.end());
1548  } // temp size > 1
1549 
1550  if(prt) mf::LogVerbatim("TC")<<"FindXMatches: Found "<<temp.size()<<" matches";
1551 
1552  } // FindXMatches
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< float > maxPos0
Definition: DataStructs.h:489
TCConfig tcc
Definition: DataStructs.cxx:6
bool MakeTp3(TCSlice &slc, const TrajPoint &itp, const TrajPoint &jtp, TrajPoint3 &tp3, bool findDirection)
Definition: PFPUtils.cxx:1555
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1636
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
const detinfo::DetectorProperties * detprop
Definition: DataStructs.h:494
bool valDecreasings(SortEntry c1, SortEntry c2)
Definition: PFPUtils.cxx:12
bool SignalAtTp(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:1814
std::vector< float > match3DCuts
3D matching cuts
Definition: DataStructs.h:476
const geo::GeometryCore * geom
Definition: DataStructs.h:493
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
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 ( TCSlice slc)

Definition at line 131 of file TCShower.cxx.

References ChkAssns(), tca::TCSlice::cots, CreatePFP(), DecodeCTP(), evd::details::end(), GetAssns(), GetSliceIndex(), tca::TCSlice::ID, kKilled, kUsedHits, tca::TCSlice::pfps, geo::PlaneID::Plane, PutTrajHitsInVector(), tca::TCSlice::showers, slices, ss, tca::TCSlice::tjs, TransferTjHits(), tca::TCSlice::vtx3s, tca::Trajectory::VtxID, and tca::TCSlice::vtxs.

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

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 : slc.showers) {
142  if(ss3.ID == 0) continue;
143  noShowers = false;
144  }
145  if(noShowers) return;
146 
147  ChkAssns("Fin3D", slc);
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 : slc.showers) {
153  if(ss3.ID == 0) continue;
154  if(ss3.PFPIndex != USHRT_MAX) {
155  std::cout<<"Finish3DShowers 3S"<<ss3.ID<<" already has a pfp associated with it...\n";
156  continue;
157  }
158  auto showerPFP = CreatePFP(slc);
159  showerPFP.TjIDs.resize(ss3.CotIDs.size());
160  for(unsigned short ii = 0; ii < ss3.CotIDs.size(); ++ii) {
161  unsigned short cid = ss3.CotIDs[ii];
162  if(cid == 0 || cid > slc.cots.size()) {
163  std::cout<<"Finish3DShowers 3S"<<ss3.ID<<" has an invalid cots ID"<<cid<<"\n";
164  return;
165  }
166  auto& ss = slc.cots[cid - 1];
167  auto& stj = slc.tjs[ss.ShowerTjID - 1];
168  showerPFP.TjIDs[ii] = stj.ID;
169  } // ci
170  showerPFP.PDGCode = 1111;
171  showerPFP.XYZ[0] = ss3.Start;
172  showerPFP.Dir[0] = ss3.Dir;
173  showerPFP.DirErr[0] = ss3.DirErr;
174  showerPFP.Vx3ID[0] = ss3.Vx3ID;
175  showerPFP.XYZ[1] = ss3.End;
176  showerPFP.Dir[1] = ss3.Dir;
177  // dEdx is indexed by plane for pfps and by 2D shower index for 3D showers
178  for(auto cid : ss3.CotIDs) {
179  auto& ss = slc.cots[cid - 1];
180  unsigned short plane = DecodeCTP(ss.CTP).Plane;
181  auto& stj = slc.tjs[ss.ShowerTjID - 1];
182  showerPFP.dEdx[0][plane] = stj.dEdx[0];
183  showerPFP.dEdxErr[0][plane] = 0.3 * stj.dEdx[0];
184  } // ci
185  ss3.PFPIndex = slc.pfps.size();
186  if(ss3.ParentID > 0) {
187  // see if this is a daughter
188  auto& dtrPFP = slc.pfps[ss3.ParentID - 1];
189  if(dtrPFP.ParentUID > 0) {
190  // Transfer the daughter <-> parent assn
191  auto slcIndx = GetSliceIndex("P", dtrPFP.ParentUID);
192  auto& parPFP = slices[slcIndx.first].pfps[slcIndx.second];
193  showerPFP.ParentUID = parPFP.UID;
194  std::replace(parPFP.DtrUIDs.begin(), parPFP.DtrUIDs.end(), dtrPFP.UID, showerPFP.UID);
195  dtrPFP.ParentUID = 0;
196  } // dtrPFP.ParentID > 0
197  } // ss3.ParentID > 0
198  slc.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(slc, false)) return;
204 
205  // Associate shower Tj hits with 3D showers
206  for(auto& ss3 : slc.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 = slc.cots[cid - 1];
211  for(auto tjid : ss.TjIDs) {
212  Trajectory& tj = slc.tjs[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 = slc.vtxs[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 = slc.vtx3s[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(!slc.pfps.empty()) {
236  for(auto& pfp : slc.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 = slc.tjs[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 = slc.tjs[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 : slc.vtxs) {
259  if(vx2.ID == 0) continue;
260  auto vxtjs = GetAssns(slc, "2V", vx2.ID, "T");
261  if(vxtjs.empty()) vx2.ID = 0;
262  } // vx2
263 
264  // kill orphan vertices
265  for(auto& vx3 : slc.vtx3s) {
266  if(vx3.ID == 0) continue;
267  auto vxtjs = GetAssns(slc, "3V", vx3.ID, "T");
268  if(vxtjs.empty()) {
269  vx3.ID = 0;
270  continue;
271  }
272  } // vx3
273 
274  // check
275  for(auto& pfp : slc.pfps) {
276  if(pfp.ID == 0) continue;
277  if(pfp.PDGCode != 1111) continue;
278  if(pfp.Vx3ID[0] > 0 && slc.vtx3s[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(TCSlice &slc, bool prt)
Definition: TCShower.cxx:4318
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4279
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4560
std::vector< unsigned int > PutTrajHitsInVector(Trajectory const &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2416
Float_t ss
Definition: plot.C:23
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
std::vector< TCSlice > slices
Definition: DataStructs.cxx:10
PFPStruct CreatePFP(TCSlice &slc)
Definition: PFPUtils.cxx:1973
geo::PlaneID DecodeCTP(CTP_t CTP)
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:4496
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool tca::Fit2D ( short  mode,
Point2_t  inPt,
float &  inPtErr,
Vector2_t outVec,
Vector2_t outVecErr,
float &  chiDOF 
)

Definition at line 4536 of file Utils.cxx.

References B.

Referenced by ChgSlope(), ChkStop(), DotProd(), and MakeJunkTraj().

4537  {
4538  // Fit points to a 2D line.
4539  // Mode = 0: Initialize
4540  // Mode = 1: Accumulate
4541  // Mode = 2: Accumulate and store to calculate chiDOF
4542  // Mode = -1: Fit and put results in outVec and chiDOF
4543 
4544  static double sum, sumx, sumy, sumx2, sumy2, sumxy;
4545  static unsigned short cnt;
4546  static std::vector<Point2_t> fitPts;
4547  static std::vector<double> fitWghts;
4548 
4549  if(mode == 0) {
4550  // initialize
4551  cnt = 0;
4552  sum = 0.; sumx = 0.; sumy = 0.;
4553  sumx2 = 0.; sumy2 = 0.; sumxy = 0;
4554  fitPts.resize(0);
4555  fitWghts.resize(0);
4556  return true;
4557  } // mode == 0
4558 
4559  if(mode > 0) {
4560  if(inPtErr <= 0.) return false;
4561  ++cnt;
4562  double wght = 1 / (inPtErr * inPtErr);
4563  sum += wght;
4564  sumx += wght * inPt[0];
4565  sumx2 += wght * inPt[0] * inPt[0];
4566  sumy += wght * inPt[1];
4567  sumy2 += wght * inPt[1] * inPt[1];
4568  sumxy += wght * inPt[0] * inPt[1];
4569  if(mode == 1) return true;
4570  fitPts.push_back(inPt);
4571  fitWghts.push_back(wght);
4572  return true;
4573  } // Accumulate
4574 
4575  if(cnt < 2) return false;
4576  // do the fit
4577  double delta = sum * sumx2 - sumx * sumx;
4578  if(delta == 0.) return false;
4579  double A = (sumx2 * sumy - sumx * sumxy) / delta;
4580  double B = (sumxy * sum - sumx * sumy) / delta;
4581  outVec[0] = A;
4582  outVec[1] = B;
4583  chiDOF = 0;
4584  if(cnt == 2 || fitPts.empty()) return true;
4585 
4586  // calculate errors and chiDOF
4587  if(fitPts.size() != cnt) return false;
4588  double ndof = cnt - 2;
4589  double varnce = (sumy2 + A*A*sum + B*B*sumx2 - 2 * (A*sumy + B*sumxy - A*B*sumx)) / ndof;
4590  if(varnce > 0.) {
4591  outVecErr[0] = sqrt(varnce * sumx2 / delta);
4592  outVecErr[1] = sqrt(varnce * sum / delta);
4593  } else {
4594  outVecErr[0] = 0.;
4595  outVecErr[1] = 0.;
4596  }
4597  sum = 0.;
4598  // calculate chisq
4599  for(unsigned short ii = 0; ii < fitPts.size(); ++ii) {
4600  double arg = fitPts[ii][1] - A - B * fitPts[ii][0];
4601  sum += fitWghts[ii] * arg * arg;
4602  }
4603  chiDOF = sum / ndof;
4604  fitPts.resize(0);
4605  fitWghts.resize(0);
4606  return true;
4607 
4608  } // Fit2D
Int_t B
Definition: plot.C:25
void tca::Fit3D ( unsigned short  mode,
Point3_t  point,
Vector3_t  dir,
Point3_t fitPos,
Vector3_t fitDir 
)

Definition at line 1042 of file PFPUtils.cxx.

References SetMag().

Referenced by FindCompleteness().

1043  {
1044  // initialize, accumulate and fit the points. The code to fit the direction using the positions
1045  // of the points is commented out and replaced with a simple average of the directions of the points
1046 
1047  // 3D fit sum variables
1048  static double fSum, fSumx, fSumy, fSumz;
1049 // static double fSumx2, fSumy2, fSumz2, fSumxz, fSumyz;
1050  // average the direction vectors
1051  static double fSumDir0, fSumDir1, fSumDir2;
1052 
1053  if(mode == 0) {
1054  fSum = 0; fSumx = 0; fSumy = 0; fSumz = 0;
1055 // fSumx2 = 0; fSumy2 = 0; fSumz2 = 0; fSumxz = 0; fSumyz = 0;
1056  fSumDir0 = 0; fSumDir1 = 0; fSumDir2 = 0;
1057  return;
1058  }
1059  // accumulate
1060  if(mode == 1) {
1061  fSum += 1;
1062  fSumx += point[0];
1063  fSumy += point[1];
1064  fSumz += point[2];
1065 /*
1066  fSumx2 += point[0] * point[0];
1067  fSumy2 += point[1] * point[1];
1068  fSumz2 += point[2] * point[2];
1069  fSumxz += point[0] * point[2];
1070  fSumyz += point[1] * point[2];
1071 */
1072  fSumDir0 += dir[0];
1073  fSumDir1 += dir[1];
1074  fSumDir2 += dir[2];
1075  return;
1076  }
1077 
1078  if(fSum < 2) return;
1079  // just use the average for the position
1080  fitPos[0] = fSumx / fSum;
1081  fitPos[1] = fSumy / fSum;
1082  fitPos[2] = fSumz / fSum;
1083  // and for the direction
1084  fitDir = {{fSumDir0, fSumDir1, fSumDir2}};
1085  SetMag(fitDir, 1);
1086  } // Fit3D
bool SetMag(Vector3_t &v1, double mag)
Definition: PFPUtils.cxx:1670
TDirectory * dir
Definition: macro.C:5
bool tca::FitTp3 ( TCSlice slc,
TrajPoint3 tp3,
const std::vector< Tj2Pt > &  tj2pts 
)

Definition at line 646 of file PFPUtils.cxx.

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

647  {
648  // Fits the vector of Tj2Pts points and puts the results into tp3. This code is adapted
649  // from TrackLineFitAlg: SVD fit adapted from $ROOTSYS/tutorials/matrix/solveLinear.C
650  // Fit equation is w = A(X)v, where w is a vector of hit wires, A is
651  // a matrix to calculate a track projected to a point at X, and v is
652  // a vector (Yo, Zo, dY/dX, dZ/dX).
653  if(tj2pts.size() < 4) return false;
654 
655  const unsigned int nvars = 4;
656  unsigned int npts = tj2pts.size();
657  TMatrixD A(npts, nvars);
658  // vector holding the Wire number
659  TVectorD w(npts);
660 
661  double x0 = 0;
662  for(auto& tj2pt : tj2pts) {
663  auto& tp = slc.tjs[tj2pt.id - 1].Pts[tj2pt.ipt];
664  geo::PlaneID planeID = DecodeCTP(tp.CTP);
665  x0 += tcc.detprop->ConvertTicksToX(tp.Pos[1]/tcc.unitsPerTick, planeID);
666  }
667  x0 /= (double)tj2pts.size();
668 
669  unsigned short ninpl[3] = {0};
670  unsigned short nok = 0;
671  double wght = 1;
672  for(unsigned short ipt = 0; ipt < tj2pts.size(); ++ipt) {
673  auto& tj2pt = tj2pts[ipt];
674  auto& tp = slc.tjs[tj2pt.id - 1].Pts[tj2pt.ipt];
675  geo::PlaneID planeID = DecodeCTP(tp.CTP);
676  unsigned int cstat = planeID.Cryostat;
677  unsigned int tpc = planeID.TPC;
678  unsigned int plane = planeID.Plane;
679  // get the wire plane offset
680  double off = tcc.geom->WireCoordinate(0, 0, plane, tpc, cstat);
681  // get the "cosine-like" component
682  double cw = tcc.geom->WireCoordinate(1, 0, plane, tpc, cstat) - off;
683  // the "sine-like" component
684  double sw = tcc.geom->WireCoordinate(0, 1, plane, tpc, cstat) - off;
685  double x = tcc.detprop->ConvertTicksToX(tp.Pos[1]/tcc.unitsPerTick, planeID) - x0;
686  A[ipt][0] = wght * cw;
687  A[ipt][1] = wght * sw;
688  A[ipt][2] = wght * cw * x;
689  A[ipt][3] = wght * sw * x;
690  w[ipt] = wght * (tp.Pos[0] - off);
691  ++ninpl[plane];
692  // need at least two points in a plane
693  if(ninpl[plane] == 2) ++nok;
694  } // ipt
695 
696  // need at least 2 planes with at least two points
697  if(nok < 2) return false;
698 
699  TDecompSVD svd(A);
700  bool ok;
701  TVectorD tVec = svd.Solve(w, ok);
702 
703  // Calculate Chi/DOF here
704 // tp3.ChiDOF = 1;
705 
706  Vector3_t fitDir;
707  double norm = sqrt(1 + tVec[2] * tVec[2] + tVec[3] * tVec[3]);
708  fitDir[0] = 1 / norm;
709  fitDir[1] = tVec[2] / norm;
710  fitDir[2] = tVec[3] / norm;
711 
712  Point3_t fitPos;
713  fitPos[0] = x0;
714  fitPos[1] = tVec[0];
715  fitPos[2] = tVec[1];
716  // move it to the same Z position as tp3.Pos
717  if(tp3.Pos[2] != 0) {
718  double dz = tp3.Pos[2] - fitPos[2];
719  fitPos[0] += dz * fitDir[0] / fitDir[2];
720  fitPos[1] += dz * fitDir[1] / fitDir[2];
721  fitPos[2] += dz;
722  }
723 
724  if(PosSep2(fitPos, tp3.Pos) > 5) {
725  std::cout<<"Crazy fitPos "<<PosSep(fitPos, tp3.Pos)<<"\n";
726 // tp3.ChiDOF = 10;
727  return false;
728  }
729 
730  tp3.Pos = fitPos;
731  tp3.Dir = fitDir;
732 
733  return true;
734  } // FitTp3
Float_t x
Definition: compare.C:6
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
std::array< double, 3 > Point3_t
Definition: DataStructs.h:35
TCConfig tcc
Definition: DataStructs.cxx: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
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
const detinfo::DetectorProperties * detprop
Definition: DataStructs.h:494
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1660
const geo::GeometryCore * geom
Definition: DataStructs.h:493
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
virtual double ConvertTicksToX(double ticks, int p, int t, int c) const =0
Float_t sw
Definition: plot.C:23
Float_t norm
geo::PlaneID DecodeCTP(CTP_t CTP)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
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 ( TCSlice slc,
const std::vector< TrajPoint3 > &  tp3s,
Point3_t pos,
Vector3_t dir,
float &  rCorr 
)

Definition at line 556 of file PFPUtils.cxx.

References dir.

557  {
558  return FitTp3s(slc, tp3s, 0, tp3s.size(), pos, dir, rCorr);
559  } // FitTp3s
bool FitTp3s(TCSlice &slc, const std::vector< TrajPoint3 > &tp3s, unsigned short fromPt, unsigned short toPt, Point3_t &pos, Vector3_t &dir, float &rCorr)
Definition: PFPUtils.cxx:562
TDirectory * dir
Definition: macro.C:5
bool tca::FitTp3s ( TCSlice slc,
const std::vector< TrajPoint3 > &  tp3s,
unsigned short  fromPt,
unsigned short  toPt,
Point3_t pos,
Vector3_t dir,
float &  rCorr 
)

Definition at line 562 of file PFPUtils.cxx.

References detinfo::DetectorProperties::ConvertTicksToX(), geo::CryostatID::Cryostat, DecodeCTP(), tca::TCConfig::detprop, tca::TCConfig::geom, norm, tca::TCSlice::nPlanes, geo::PlaneID::Plane, sw, tcc, tca::TCSlice::tjs, geo::TPCID::TPC, tca::TCConfig::unitsPerTick, w, geo::GeometryCore::WireCoordinate(), and x.

563  {
564  // Fits the Tj2Pts points in Tp3s to a line
565  if(tp3s.size() < 3) return false;
566  if(fromPt >= toPt) return false;
567  if(toPt > tp3s.size()) return false;
568 
569  // temp vectors to ensure that a TP is only used once
570  std::vector<unsigned short> useID;
571  std::vector<unsigned short> useIpt;
572  std::vector<unsigned short> cntInPln(slc.nPlanes);
573  for(unsigned short ipt = fromPt; ipt < toPt; ++ipt) {
574  auto& tp3 = tp3s[ipt];
575  for(auto& tj2pt : tp3.Tj2Pts) {
576  bool isUsed = false;
577  for(unsigned short ii = 0; ii < useID.size(); ++ii) {
578  if(tj2pt.id == useID[ii] && tj2pt.ipt == useIpt[ii]) isUsed = true;
579  } // ii
580  if(isUsed) continue;
581  // add it to the list
582  useID.push_back(tj2pt.id);
583  useIpt.push_back(tj2pt.ipt);
584  auto& tj = slc.tjs[tj2pt.id - 1];
585  ++cntInPln[DecodeCTP(tj.CTP).Plane];
586  } // tj2pt
587  } // ipt
588  // ensure there are at least two points in at least two planes
589  unsigned short enufInPlane = 0;
590  for(unsigned short plane = 0; plane < slc.nPlanes; ++plane) if(cntInPln[plane] > 1) ++enufInPlane;
591  if(enufInPlane < 2) return false;
592 
593  const unsigned int nvars = 4;
594  unsigned int npts = useID.size();
595  TMatrixD A(npts, nvars);
596  // vector holding the Wire number
597  TVectorD w(npts);
598 
599  // X origin
600  double x0 = 0;
601  for(unsigned short ipt = 0; ipt < useID.size(); ++ipt) {
602  auto& tp = slc.tjs[useID[ipt] - 1].Pts[useIpt[ipt]];
603  geo::PlaneID planeID = DecodeCTP(tp.CTP);
604  x0 += tcc.detprop->ConvertTicksToX(tp.Pos[1]/tcc.unitsPerTick, planeID);
605  }
606  x0 /= (double)useID.size();
607 
608  double wght = 1;
609  for(unsigned short ipt = 0; ipt < useID.size(); ++ipt) {
610  auto& tp = slc.tjs[useID[ipt] - 1].Pts[useIpt[ipt]];
611  geo::PlaneID planeID = DecodeCTP(tp.CTP);
612  unsigned int cstat = planeID.Cryostat;
613  unsigned int tpc = planeID.TPC;
614  unsigned int plane = planeID.Plane;
615  // get the wire plane offset
616  double off = tcc.geom->WireCoordinate(0, 0, plane, tpc, cstat);
617  // get the "cosine-like" component
618  double cw = tcc.geom->WireCoordinate(1, 0, plane, tpc, cstat) - off;
619  // the "sine-like" component
620  double sw = tcc.geom->WireCoordinate(0, 1, plane, tpc, cstat) - off;
621  double x = tcc.detprop->ConvertTicksToX(tp.Pos[1]/tcc.unitsPerTick, planeID) - x0;
622  A[ipt][0] = wght * cw;
623  A[ipt][1] = wght * sw;
624  A[ipt][2] = wght * cw * x;
625  A[ipt][3] = wght * sw * x;
626  w[ipt] = wght * (tp.Pos[0] - off);
627  } // ipt
628 
629  TDecompSVD svd(A);
630  bool ok;
631  TVectorD tVec = svd.Solve(w, ok);
632  double norm = sqrt(1 + tVec[2] * tVec[2] + tVec[3] * tVec[3]);
633  dir[0] = 1 / norm;
634  dir[1] = tVec[2] / norm;
635  dir[2] = tVec[3] / norm;
636  pos[0] = x0;
637  pos[1] = tVec[0];
638  pos[2] = tVec[1];
639  rCorr = 1;
640 // std::cout<<"FTP3s: "<<useID.size()<<" cntInPln "<<cntInPln[0]<<" "<<cntInPln[1]<<" "<<cntInPln[2]<<"\n";
641  return true;
642 
643  } // FitTp3s
Float_t x
Definition: compare.C:6
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
TCConfig tcc
Definition: DataStructs.cxx: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
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
const detinfo::DetectorProperties * detprop
Definition: DataStructs.h:494
const geo::GeometryCore * geom
Definition: DataStructs.h:493
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
virtual double ConvertTicksToX(double ticks, int p, int t, int c) const =0
Float_t sw
Definition: plot.C:23
Float_t norm
TDirectory * dir
Definition: macro.C:5
geo::PlaneID DecodeCTP(CTP_t CTP)
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 ( TCSlice slc,
Trajectory tj 
)

Definition at line 753 of file Utils.cxx.

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

Referenced by EndMerge(), GottaKink(), HiEndDelta(), MaskBadTPs(), MaskedHitsOK(), UpdateStiffEl(), and UpdateTraj().

754  {
755  // Jacket around FitTraj to fit the leading edge of the supplied trajectory
756  unsigned short originPt = tj.EndPt[1];
757  unsigned short npts = tj.Pts[originPt].NTPsFit;
758  TrajPoint tpFit;
759  unsigned short fitDir = -1;
760  FitTraj(slc, tj, originPt, npts, fitDir, tpFit);
761  tj.Pts[originPt] = tpFit;
762 
763  } // FitTraj
void FitTraj(TCSlice &slc, Trajectory &tj, unsigned short originPt, unsigned short npts, short fitDir, TrajPoint &tpFit)
Definition: Utils.cxx:766
void tca::FitTraj ( TCSlice slc,
Trajectory tj,
unsigned short  originPt,
unsigned short  npts,
short  fitDir,
TrajPoint tpFit 
)

Definition at line 766 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().

767  {
768  // Fit the supplied trajectory using HitPos positions with the origin at originPt.
769  // The npts is interpreted as the number of points on each side of the origin
770  // The allowed modes are as follows, where i denotes a TP that is included, . denotes
771  // a TP with no hits, and x denotes a TP that is not included
772  //TP 012345678 fitDir originPt npts
773  // Oiiixxxxx 1 0 4 << npts in the fit
774  // xi.iiOxxx -1 5 4
775  // xiiiOiiix 0 4 4 << 2 * npts + 1 points in the fit
776  // xxxiO.ixx 0 4 1
777  // 0iiixxxxx 0 0 4
778  // This routine puts the results into tp if the fit is successfull. The
779  // fit "direction" is in increasing order along the trajectory from 0 to tj.Pts.size() - 1.
780 
781  // static const float twoPi = 2 * M_PI;
782 
783  if(originPt > tj.Pts.size() - 1) {
784  mf::LogWarning("TC")<<"FitTraj: Requesting fit of invalid TP "<<originPt;
785  return;
786  }
787 
788  // copy the origin TP into the fit TP
789  tpFit = tj.Pts[originPt];
790  // Assume that the fit will fail
791  tpFit.FitChi = 999;
792  if(fitDir < -1 || fitDir > 1) return;
793 
794  std::vector<double> x, y;
795  Point2_t origin = tj.Pts[originPt].HitPos;
796  // Use TP position if there aren't any hits on it
797  if(tj.Pts[originPt].Chg == 0) origin = tj.Pts[originPt].Pos;
798 
799  // simple two point case
800  if(NumPtsWithCharge(slc, tj, false) == 2) {
801  for(unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1]; ++ipt) {
802  if(tj.Pts[ipt].Chg == 0) continue;
803  double xx = tj.Pts[ipt].HitPos[0] - origin[0];
804  double yy = tj.Pts[ipt].HitPos[1] - origin[1];
805  x.push_back(xx);
806  y.push_back(yy);
807  } // ii
808  if(x.size() != 2) return;
809  if(x[0] == x[1]) {
810  // Either + or - pi/2
811  tpFit.Ang = M_PI/2;
812  if(y[1] < y[0]) tpFit.Ang = -tpFit.Ang;
813  } else {
814  double dx = x[1] - x[0];
815  double dy = y[1] - y[0];
816  tpFit.Ang = atan2(dy, dx);
817  }
818  tpFit.Dir[0] = cos(tpFit.Ang);
819  tpFit.Dir[1] = sin(tpFit.Ang);
820  tpFit.Pos[0] += origin[0];
821  tpFit.Pos[1] += origin[1];
822  tpFit.AngErr = 0.01;
823  tpFit.FitChi = 0.01;
824  SetAngleCode(tpFit);
825  return;
826  } // two points
827 
828  std::vector<double> w, q;
829  std::array<double, 2> dir;
830  double xx, yy, xr, yr;
831  double chgWt;
832 
833  // Rotate the traj hit position into the coordinate system defined by the
834  // originPt traj point, where x = along the trajectory, y = transverse
835  double rotAngle = tj.Pts[originPt].Ang;
836  double cs = cos(-rotAngle);
837  double sn = sin(-rotAngle);
838 
839  // enter the originPT hit info if it exists
840  if(tj.Pts[originPt].Chg > 0) {
841  xx = tj.Pts[originPt].HitPos[0] - origin[0];
842  yy = tj.Pts[originPt].HitPos[1] - origin[1];
843  xr = cs * xx - sn * yy;
844  yr = sn * xx + cs * yy;
845  x.push_back(xr);
846  y.push_back(yr);
847  chgWt = tj.Pts[originPt].ChgPull;
848  if(chgWt < 1) chgWt = 1;
849  chgWt *= chgWt;
850  w.push_back(chgWt * tj.Pts[originPt].HitPosErr2);
851  }
852 
853  // correct npts to account for the origin point
854  if(fitDir != 0) --npts;
855 
856  // step in the + direction first
857  if(fitDir != -1) {
858  unsigned short cnt = 0;
859  for(unsigned short ipt = originPt + 1; ipt < tj.Pts.size(); ++ipt) {
860  if(tj.Pts[ipt].Chg == 0) continue;
861  xx = tj.Pts[ipt].HitPos[0] - origin[0];
862  yy = tj.Pts[ipt].HitPos[1] - origin[1];
863  xr = cs * xx - sn * yy;
864  yr = sn * xx + cs * yy;
865  x.push_back(xr);
866  y.push_back(yr);
867  chgWt = tj.Pts[ipt].ChgPull;
868  if(chgWt < 1) chgWt = 1;
869  chgWt *= chgWt;
870  w.push_back(chgWt * tj.Pts[ipt].HitPosErr2);
871  ++cnt;
872  if(cnt == npts) break;
873  } // ipt
874  } // fitDir != -1
875 
876  // step in the - direction next
877  if(fitDir != 1 && originPt > 0) {
878  unsigned short cnt = 0;
879  for(unsigned short ii = 1; ii < tj.Pts.size(); ++ii) {
880  unsigned short ipt = originPt - ii;
881  if(ipt > tj.Pts.size() - 1) continue;
882  if(tj.Pts[ipt].Chg == 0) continue;
883  xx = tj.Pts[ipt].HitPos[0] - origin[0];
884  yy = tj.Pts[ipt].HitPos[1] - origin[1];
885  xr = cs * xx - sn * yy;
886  yr = sn * xx + cs * yy;
887  x.push_back(xr);
888  y.push_back(yr);
889  chgWt = tj.Pts[ipt].ChgPull;
890  if(chgWt < 1) chgWt = 1;
891  chgWt *= chgWt;
892  w.push_back(chgWt * tj.Pts[ipt].HitPosErr2);
893  ++cnt;
894  if(cnt == npts) break;
895  if(ipt == 0) break;
896  } // ipt
897  } // fitDir != -1
898 
899  // Not enough points to define a line?
900  if(x.size() < 2) return;
901 
902  double sum = 0.;
903  double sumx = 0.;
904  double sumy = 0.;
905  double sumxy = 0.;
906  double sumx2 = 0.;
907  double sumy2 = 0.;
908 
909  // weight by the charge ratio and accumulate sums
910  double wght;
911  for(unsigned short ipt = 0; ipt < x.size(); ++ipt) {
912  if(w[ipt] < 0.00001) w[ipt] = 0.00001;
913  wght = 1 / w[ipt];
914  sum += wght;
915  sumx += wght * x[ipt];
916  sumy += wght * y[ipt];
917  sumx2 += wght * x[ipt] * x[ipt];
918  sumy2 += wght * y[ipt] * y[ipt];
919  sumxy += wght * x[ipt] * y[ipt];
920  }
921  // calculate coefficients and std dev
922  double delta = sum * sumx2 - sumx * sumx;
923  if(delta == 0) return;
924  // A is the intercept
925  double A = (sumx2 * sumy - sumx * sumxy) / delta;
926  // B is the slope
927  double B = (sumxy * sum - sumx * sumy) / delta;
928 
929  // The chisq will be set below if there are enough points. Don't allow it to be 0
930  // so we can take Chisq ratios later
931  tpFit.FitChi = 0.01;
932  double newang = atan(B);
933  dir[0] = cos(newang);
934  dir[1] = sin(newang);
935  // rotate back into the (w,t) coordinate system
936  cs = cos(rotAngle);
937  sn = sin(rotAngle);
938  tpFit.Dir[0] = cs * dir[0] - sn * dir[1];
939  tpFit.Dir[1] = sn * dir[0] + cs * dir[1];
940  // ensure that the direction is consistent with the originPt direction
941  bool flipDir = false;
942  if(AngleRange(tj.Pts[originPt]) > 0) {
943  flipDir = std::signbit(tpFit.Dir[1]) != std::signbit(tj.Pts[originPt].Dir[1]);
944  } else {
945  flipDir = std::signbit(tpFit.Dir[0]) != std::signbit(tj.Pts[originPt].Dir[0]);
946  }
947  if(flipDir) {
948  tpFit.Dir[0] = -tpFit.Dir[0];
949  tpFit.Dir[1] = -tpFit.Dir[1];
950  }
951  tpFit.Ang = atan2(tpFit.Dir[1], tpFit.Dir[0]);
952  SetAngleCode(tpFit);
953  // 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();
954 
955  // rotate (0, intcpt) into (W,T) coordinates
956  tpFit.Pos[0] = -sn * A + origin[0];
957  tpFit.Pos[1] = cs * A + origin[1];
958  // force the origin to be at origin[0]
959  if(tpFit.AngleCode < 2) MoveTPToWire(tpFit, origin[0]);
960 
961  if(x.size() < 3) return;
962 
963  // Calculate chisq/DOF
964  double ndof = x.size() - 2;
965  double varnce = (sumy2 + A*A*sum + B*B*sumx2 - 2 * (A*sumy + B*sumxy - A*B*sumx)) / ndof;
966  if(varnce > 0.) {
967  // Intercept error is not used
968  // InterceptError = sqrt(varnce * sumx2 / delta);
969  double slopeError = sqrt(varnce * sum / delta);
970  tpFit.AngErr = std::abs(atan(slopeError));
971  } else {
972  tpFit.AngErr = 0.01;
973  }
974  sum = 0;
975  // calculate chisq
976  double arg;
977  for(unsigned short ii = 0; ii < y.size(); ++ii) {
978  arg = y[ii] - A - B * x[ii];
979  sum += arg * arg / w[ii];
980  }
981  tpFit.FitChi = sum / ndof;
982 
983  } // 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(TrajPoint &tp)
Definition: Utils.cxx:722
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:1871
TDirectory * dir
Definition: macro.C:5
unsigned short AngleRange(float angle)
Definition: Utils.cxx:739
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2485
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 ( TCSlice slc,
VtxStore vx,
bool  prt 
)

Definition at line 2131 of file TCVertex.cxx.

References tca::VtxStore::CTP, tca::VtxStore::ID, kFixed, kHaloTj, kKilled, kNewVtxCuts, kNoFitToVx, kPhoton, tca::VtxStore::Stat, tcc, tca::TCSlice::tjs, and tca::TCConfig::useAlg.

Referenced by AttachTrajToVertex(), EndMerge(), Find2DVertices(), MergeWithVertex(), and SplitTrajCrossingVertices().

2132  {
2133  // A poor-mans fitting scheme. If the fitted vertex position error is within the supplied
2134  // value, the position and errors are updated and we return true, otherwise the vertex is
2135  // left unchanged and we return false
2136 
2137  // tcc.vtx2DCuts fcl input usage
2138  // 0 = maximum length of a short trajectory
2139  // 1 = max vertex - trajectory separation for short trajectories
2140  // 2 = max vertex - trajectory separation for long trajectories
2141  // 3 = max position pull for adding TJs to a vertex
2142  // 4 = max allowed vertex position error
2143  // 5 = min MCSMom
2144  // 6 = min Pts/Wire fraction
2145 
2146  if(vx.Stat[kFixed]) {
2147  if(prt) mf::LogVerbatim("TC")<<" vertex position fixed. No fit allowed";
2148  return true;
2149  }
2150 
2151  // Create a vector of trajectory points that will be used to fit the vertex position
2152  std::vector<TrajPoint> vxTp;
2153  for(auto& tj : slc.tjs) {
2154  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
2155  if(tj.CTP != vx.CTP) continue;
2156  if(tj.AlgMod[kPhoton]) continue;
2157  if(tj.AlgMod[kNoFitToVx]) continue;
2158  bool added = false;
2159  if(tj.VtxID[0] == vx.ID) {
2160  vxTp.push_back(tj.Pts[tj.EndPt[0]]);
2161  added = true;
2162  }
2163  if(tj.VtxID[1] == vx.ID) {
2164  vxTp.push_back(tj.Pts[tj.EndPt[1]]);
2165  added = true;
2166  }
2167  // stash the ID in Step to help debugging
2168  if(added) {
2169  auto& tp = vxTp[vxTp.size()-1];
2170  if(tj.ID > 0) tp.Step = (int)tj.ID;
2171  // inflate the angle errors for Tjs with few fitted points
2172  if(tcc.useAlg[kNewVtxCuts] && tp.NTPsFit < 4) tp.AngErr *= 4;
2173  }
2174  } // tj
2175 
2176  bool success = FitVertex(slc, vx, vxTp, prt);
2177 
2178  if(!success) return false;
2179  return true;
2180 
2181  } // FitVertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool FitVertex(TCSlice &slc, VtxStore &vx, std::vector< TrajPoint > vxTp, bool prt)
Definition: TCVertex.cxx:2184
TCConfig tcc
Definition: DataStructs.cxx:6
vertex position fixed manually - no fitting done
Definition: DataStructs.h:74
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
bool tca::FitVertex ( TCSlice slc,
VtxStore vx,
std::vector< TrajPoint vxTp,
bool  prt 
)

Definition at line 2184 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, tcc, tmp, tca::VtxStore::Topo, TrajIntersection(), TrajPointVertexPull(), tca::TCConfig::unitsPerTick, and tca::TCConfig::vtx2DCuts.

2185  {
2186  // Variant of FitVertex that fits the passed trajectory points to a vertex position but doesn't
2187  // require using information in TJStuff
2188 
2189  // tcc.vtx2DCuts fcl input usage
2190  // 0 = maximum length of a short trajectory
2191  // 1 = max vertex - trajectory separation for short trajectories
2192  // 2 = max vertex - trajectory separation for long trajectories
2193  // 3 = max position pull for adding TJs to a vertex
2194  // 4 = max allowed vertex position error
2195  // 5 = min MCSMom
2196  // 6 = min Pts/Wire fraction
2197  // 7 min Score
2198  // 8 Min charge fraction near a merge point (not a vertex)
2199  // 9 max MCSmom asymmetry for a merge
2200 
2201 
2202  vx.NTraj = vxTp.size();
2203 
2204  if(vxTp.size() < 2) return false;
2205 
2206  if(prt) {
2207  PrintHeader("FV");
2208  for(auto& tp : vxTp) PrintTrajPoint("FV", slc, 0, 1, 1, tp);
2209  }
2210 
2211  // Find trajectory intersections pair-wise tweaking the angle and position(?) within
2212  // +/- 1 sigma
2213  double sum0 = 0, sum02 = 0;
2214  double sum1 = 0, sum12 = 0;
2215  double sumw = 0;
2216  double wgt;
2217  double cnt = 0;
2218  // a temporary TP for tweaking the angle
2219  TrajPoint tmp;
2220  // another point to check for a signal at each intersection
2221  TrajPoint intTp;
2222  intTp.CTP = vxTp[0].CTP;
2223  for(unsigned short itj = 0; itj < vxTp.size() - 1; ++itj) {
2224  for(unsigned short jtj = itj + 1; jtj < vxTp.size(); ++jtj) {
2225  float p0, p1;
2226  TrajIntersection(vxTp[itj], vxTp[jtj], p0, p1);
2227  intTp.Pos[0] = p0; intTp.Pos[1] = p1;
2228  wgt = 1;
2229  // accumulate
2230  sum0 += wgt * p0; sum02 += wgt * p0 * p0;
2231  sum1 += wgt * p1; sum12 += wgt * p1 * p1; sumw += wgt; ++cnt;
2232  // tweak the itj angle +
2233  tmp = vxTp[itj];
2234  tmp.Ang += tmp.AngErr;
2235  tmp.Dir[0] = cos(tmp.Ang); tmp.Dir[1] = sin(tmp.Ang);
2236  TrajIntersection(tmp, vxTp[jtj], p0, p1);
2237  intTp.Pos[0] = p0; intTp.Pos[1] = p1;
2238  // adjust the weight for 4 points at +/1 1 sigma = 0.607 / 4
2239  wgt = 0.152;
2240  // accumulate
2241  sum0 += wgt * p0; sum02 += wgt * p0 * p0;
2242  sum1 += wgt * p1; sum12 += wgt * p1 * p1; sumw += wgt; ++cnt;
2243  // tweak the itj angle -
2244  tmp = vxTp[itj];
2245  tmp.Ang -= 2 * tmp.AngErr;
2246  tmp.Dir[0] = cos(tmp.Ang); tmp.Dir[1] = sin(tmp.Ang);
2247  TrajIntersection(tmp, vxTp[jtj], p0, p1);
2248  intTp.Pos[0] = p0; intTp.Pos[1] = p1;
2249  // accumulate
2250  sum0 += wgt * p0; sum02 += wgt * p0 * p0;
2251  sum1 += wgt * p1; sum12 += wgt * p1 * p1; sumw += wgt; ++cnt;
2252  // Repeat this process with jtj
2253  // tweak the jtj angle +
2254  tmp = vxTp[jtj];
2255  tmp.Ang += tmp.AngErr;
2256  tmp.Dir[0] = cos(tmp.Ang); tmp.Dir[1] = sin(tmp.Ang);
2257  TrajIntersection(vxTp[itj], tmp, p0, p1);
2258  intTp.Pos[0] = p0; intTp.Pos[1] = p1;
2259  // accumulate
2260  sum0 += wgt * p0; sum02 += wgt * p0 * p0;
2261  sum1 += wgt * p1; sum12 += wgt * p1 * p1; sumw += wgt; ++cnt;
2262  // tweak the itj angle -
2263  tmp = vxTp[itj];
2264  tmp.Ang -= 2 * tmp.AngErr;
2265  tmp.Dir[0] = cos(tmp.Ang); tmp.Dir[1] = sin(tmp.Ang);
2266  TrajIntersection(vxTp[itj], tmp, p0, p1);
2267  intTp.Pos[0] = p0; intTp.Pos[1] = p1;
2268  // accumulate
2269  sum0 += wgt * p0; sum02 += wgt * p0 * p0;
2270  sum1 += wgt * p1; sum12 += wgt * p1 * p1; sumw += wgt; ++cnt;
2271  } // jtj
2272  } // itj
2273 
2274  if(sumw == 0) return false;
2275 
2276  double vxP0 = sum0 / sumw;
2277  double vxP1 = sum1 / sumw;
2278  double vxP0rms = sqrt((sum02 - sumw * vxP0 * vxP0) / sumw);
2279  double vxP1rms = sqrt((sum12 - sumw * vxP1 * vxP1) / sumw);
2280  double rootN = sqrt(cnt);
2281  vxP0rms /= rootN;
2282  vxP1rms /= rootN;
2283  // don't let the errors get too small
2284  if(vxP0rms < 0.5) vxP0rms = 0.5;
2285  if(vxP1rms < 0.5) vxP1rms = 0.5;
2286 
2287  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]/tcc.unitsPerTick<<" out wire "<<vxP0<<" +/- "<<vxP0rms<<" ticks "<<vxP1/tcc.unitsPerTick<<"+/-"<<vxP1rms/tcc.unitsPerTick;
2288 
2289  // apply Vertex2DCuts if this isn't a neutral vertex (which is expected to have very large
2290  // errors)
2291  if(vx.Topo != 11) {
2292  float inflate = 1;
2293  if(vx.Stat[kOnDeadWire]) inflate = 1.5;
2294  if(vxP0rms > inflate * tcc.vtx2DCuts[4] || vxP1rms > inflate * tcc.vtx2DCuts[4]) {
2295  if(prt) mf::LogVerbatim("TC")<<" fit failed. Max allowed position error "<<inflate * tcc.vtx2DCuts[4];
2296  return false;
2297  }
2298  } // not a neutral vertex
2299 
2300  vx.Pos[0] = vxP0;
2301  vx.PosErr[0] = vxP0rms;
2302  vx.Pos[1] = vxP1;
2303  vx.PosErr[1] = vxP1rms;
2304 
2305  // Calculate chisq
2306  vx.ChiDOF = 0;
2307  for(unsigned short itj = 0; itj < vxTp.size(); ++itj) {
2308  vx.ChiDOF += TrajPointVertexPull(slc, vxTp[itj], vx);
2309  } // itj
2310  vx.ChiDOF /= (float)vxTp.size();
2311 
2312  if(prt) {
2313  mf::LogVerbatim myprt("TC");
2314  myprt<<"Pull";
2315  for(unsigned short itj = 0; itj < vxTp.size(); ++itj) {
2316  float pull = TrajPointVertexPull(slc, vxTp[itj], vx);
2317  myprt<<" "<<PrintPos(slc, vxTp[itj])<<" - "<<std::fixed<<std::setprecision(2)<<pull;
2318  } // itj
2319  myprt<<" ChiDOF "<<vx.ChiDOF;
2320  }
2321  return true;
2322 
2323  } // FitVertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
float TrajPointVertexPull(TCSlice &slc, const TrajPoint &tp, const VtxStore &vx)
Definition: TCVertex.cxx:2029
Float_t tmp
Definition: plot.C:37
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
Definition: Utils.cxx:2299
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:466
void PrintHeader(std::string someText)
Definition: Utils.cxx:5535
void PrintTrajPoint(std::string someText, TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, TrajPoint const &tp)
Definition: Utils.cxx:5541
void tca::FixTrajBegin ( TCSlice slc,
Trajectory tj 
)

Definition at line 2988 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::TrajPoint::AngleCode, ChkStopEndPts(), tca::TrajPoint::CTP, tca::TCConfig::dbgStp, DecodeCTP(), tca::TrajPoint::DeltaRMS, tca::TrajPoint::Dir, tca::Trajectory::EndPt, FindCloseHits(), FixTrajBegin(), tca::TrajPoint::Hits, tca::Trajectory::IsGood, kFixBegin, kFTBRvProp, kJunkTj, kKilled, kNewStpCuts, kRvPrp, kUnusedHits, NumPtsWithCharge(), tca::TCSlice::nWires, tca::Trajectory::Pass, geo::PlaneID::Plane, tca::TrajPoint::Pos, PrintPos(), PrintTrajPoint(), tca::Trajectory::Pts, tca::TCConfig::qualityCuts, ReversePropagate(), seeds, SetEndPoints(), tca::Trajectory::StepDir, tcc, TrimEndPts(), UnsetUsedHits(), tca::TCConfig::useAlg, tca::TrajPoint::UseHit, tca::TCConfig::VLAStepSize, and tca::TCSlice::wireHitRange.

2989  {
2990  // Update the parameters at the beginning of the trajectory. The first
2991  // points may not belong to this trajectory since they were added when there was
2992  // little information. This information may be updated later if ReversePropagate is used
2993 
2994  if(!tcc.useAlg[kFixBegin]) return;
2995  if(tj.AlgMod[kJunkTj]) return;
2996 
2997  // don't do anything if this tj has been modified by ReversePropagate
2998  if(tj.AlgMod[kRvPrp]) return;
2999 
3000  // don't bother with really short tjs
3001  if(tj.Pts.size() < 3) return;
3002 
3003  unsigned short atPt = tj.EndPt[1];
3004  unsigned short maxPtsFit = 0;
3005  for(unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1]; ++ipt) {
3006  if(tj.Pts[ipt].Chg == 0) continue;
3007  if(tj.Pts[ipt].NTPsFit > maxPtsFit) {
3008  maxPtsFit = tj.Pts[ipt].NTPsFit;
3009  atPt = ipt;
3010  // no reason to continue if there are a good number of points fitted
3011  if(maxPtsFit > 20) break;
3012  }
3013  } // ipt
3014  // find the first point that is in this fit
3015  unsigned short firstPtFit = tj.EndPt[0];
3016  unsigned short cnt = 0;
3017  for(unsigned short ii = 1; ii < tj.Pts.size(); ++ii) {
3018  if(ii > atPt) break;
3019  unsigned short ipt = atPt - ii;
3020  if(tj.Pts[ipt].Chg == 0) continue;
3021  ++cnt;
3022  if(cnt == maxPtsFit) {
3023  firstPtFit = ipt;
3024  break;
3025  } // full count
3026  } // ii
3027 
3028  bool needsRevProp = firstPtFit > 3;
3029  unsigned short nPtsLeft = NumPtsWithCharge(slc, tj, false) - firstPtFit;
3030  if(tcc.useAlg[kNewStpCuts] && needsRevProp) needsRevProp = (nPtsLeft > 5);
3031  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"FTB: firstPtFit "<<PrintPos(slc, tj.Pts[firstPtFit].Pos)<<" atPt "<<PrintPos(slc, tj.Pts[atPt].Pos)<<" nPts left after trimming "<<nPtsLeft;
3032 
3033  if(!needsRevProp) {
3034  // check one wire on the other side of EndPt[0] to see if there are hits that are available which could
3035  // be picked up by reverse propagation
3036  TrajPoint tp = tj.Pts[0];
3037  tp.Hits.clear();
3038  tp.UseHit.reset();
3039  // Move the TP "backwards"
3040  double stepSize = tcc.VLAStepSize;
3041  if(tp.AngleCode < 2) stepSize = std::abs(1/tp.Dir[0]);
3042  tp.Pos[0] -= tp.Dir[0] * stepSize * tj.StepDir;
3043  tp.Pos[1] -= tp.Dir[1] * stepSize * tj.StepDir;
3044  if(tcc.useAlg[kNewStpCuts]) {
3045  // launch RevProp if this wire is dead
3046  unsigned int wire = std::nearbyint(tp.Pos[0]);
3047  unsigned short plane = DecodeCTP(tp.CTP).Plane;
3048  needsRevProp = (wire < slc.nWires[plane] && slc.wireHitRange[plane][wire].first == -1);
3049  if(tcc.dbgStp && needsRevProp) mf::LogVerbatim("TC")<<"FTB: Previous wire "<<wire<<" is dead. Call ReversePropagate";
3050  } // NewStpCuts
3051  if(!needsRevProp) {
3052  // check for hits on a not-dead wire
3053  float maxDelta = 3 * tp.DeltaRMS;
3054  if(FindCloseHits(slc, tp, maxDelta, kUnusedHits) && !tp.Hits.empty()) {
3055  needsRevProp = true;
3056  if(tcc.dbgStp) {
3057  mf::LogVerbatim("TC")<<"FTB: Close unused hits found near EndPt[0] "<<tp.Hits.size()<<". Call ReversePropagate";
3058  PrintTrajPoint("FTB", slc, 0, tj.StepDir, tj.Pass, tp);
3059  }
3060  }
3061  } // !needsRevProp
3062  } // !needsRevProp
3063 
3064  if(tcc.dbgStp) {
3065  mf::LogVerbatim("TC")<<"FTB: maxPtsFit "<<maxPtsFit<<" at point "<<atPt<<" firstPtFit "<<firstPtFit<<" Needs ReversePropagate? "<<needsRevProp;
3066  }
3067 
3068  if(tcc.useAlg[kFTBRvProp] && needsRevProp) {
3069  // lop off the points before firstPtFit and reverse propagate
3070  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" clobber TPs "<<PrintPos(slc, tj.Pts[0])<<" to "<<PrintPos(slc, tj.Pts[firstPtFit])<<". Call TrimEndPts then ReversePropagate ";
3071  // first save the first TP on this trajectory. We will try to re-use it if
3072  // it isn't used during reverse propagation
3073  if(tcc.useAlg[kNewStpCuts]) seeds.push_back(tj.Pts[0]);
3074  for(unsigned short ipt = 0; ipt <= firstPtFit; ++ipt) UnsetUsedHits(slc, tj.Pts[ipt]);
3075  SetEndPoints(tj);
3076  tj.AlgMod[kFTBRvProp] = true;
3077  // Check for quality and trim if necessary before reverse propagation
3078  TrimEndPts("RPi", slc, tj, tcc.qualityCuts, tcc.dbgStp);
3079  if(tj.AlgMod[kKilled]) {
3080  tj.IsGood = false;
3081  return;
3082  }
3083  ReversePropagate(slc, tj);
3084  ChkStopEndPts(slc, tj, tcc.dbgStp);
3085  }
3086  // Clean up the first points if no reverse propagation was done
3087  if(!tj.AlgMod[kRvPrp]) FixTrajBegin(slc, tj, atPt);
3088 
3089  } // FixTrajBegin
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
std::vector< float > qualityCuts
Min points/wire, min consecutive pts after a gap.
Definition: DataStructs.h:479
TCConfig tcc
Definition: DataStructs.cxx:6
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1162
std::vector< unsigned int > FindCloseHits(TCSlice &slc, std::array< int, 2 > const &wireWindow, Point2_t const &timeWindow, const unsigned short plane, HitStatus_t hitRequest, bool usePeakTime, bool &hitsNear)
Definition: Utils.cxx:2496
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
void FixTrajBegin(TCSlice &slc, Trajectory &tj, unsigned short atPt)
Definition: StepUtils.cxx:3092
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
void TrimEndPts(std::string fcnLabel, TCSlice &slc, Trajectory &tj, const std::vector< float > &fQualityCuts, bool prt)
Definition: Utils.cxx:1511
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
std::vector< TrajPoint > seeds
Definition: DataStructs.cxx:11
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
float VLAStepSize
Definition: DataStructs.h:502
geo::PlaneID DecodeCTP(CTP_t CTP)
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
void ChkStopEndPts(TCSlice &slc, Trajectory &tj, bool prt)
Definition: StepUtils.cxx:1711
void ReversePropagate(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:1414
void PrintTrajPoint(std::string someText, TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, TrajPoint const &tp)
Definition: Utils.cxx:5541
void tca::FixTrajBegin ( TCSlice slc,
Trajectory tj,
unsigned short  atPt 
)

Definition at line 3092 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::TrajPoint::Ang, tca::TrajPoint::AngErr, tca::TrajPoint::AngleCode, tca::Trajectory::AveChg, tca::Trajectory::ChgRMS, tca::TCConfig::dbgStp, tca::TrajPoint::Dir, tca::Trajectory::EndPt, kBragg, kFixBegin, kJunkTj, kNewStpCuts, tca::Trajectory::MCSMom, NumPtsWithCharge(), tca::Trajectory::PDGCode, PointTrajDOCA(), tca::TrajPoint::Pos, PrintPos(), PrintStopFlag(), tca::Trajectory::Pts, SetEndPoints(), tca::Trajectory::StopFlag, tcc, UnsetUsedHits(), tca::TCConfig::useAlg, and tca::Trajectory::VtxID.

Referenced by CheckStiffEl(), CheckTraj(), and FixTrajBegin().

3093  {
3094  // Update the parameters at the beginning of the trajectory starting at point atPt
3095 
3096  if(!tcc.useAlg[kFixBegin]) return;
3097  // ignore short trajectories
3098  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
3099  if(npwc < 6) return;
3100  // ignore somewhat longer trajectories that are curly
3101  if(npwc < 10 && tj.MCSMom < 100) return;
3102  // ignore shower-like trajectories
3103  if(tj.PDGCode == 11) return;
3104  // ignore junk trajectories
3105  if(tj.AlgMod[kJunkTj]) return;
3106  // ignore stopping trajectories
3107  if(tj.StopFlag[0][kBragg]) return;
3108 
3109 
3110  unsigned short firstPt = tj.EndPt[0];
3111 
3112  if(atPt == tj.EndPt[0]) return;
3113 
3114  // Default is to use DeltaRMS of the last point on the Tj
3115  float maxDelta = 4 * tj.Pts[tj.EndPt[1]].DeltaRMS;
3116  if(tcc.useAlg[kNewStpCuts]) {
3117  // 10/2/2018 BB Change requirement
3118  // Find the max DeltaRMS of points from atPt to EndPt[1]
3119  float maxDeltaRMS = 0;
3120  for(unsigned short ipt = atPt; ipt <= tj.EndPt[1]; ++ipt) {
3121  if(tj.Pts[ipt].DeltaRMS > maxDeltaRMS) maxDeltaRMS = tj.Pts[ipt].DeltaRMS;
3122  } // ipt
3123  maxDelta = 3 * maxDeltaRMS;
3124  } // kNewStpCuts
3125 
3126  if(tcc.dbgStp) {
3127  mf::LogVerbatim("TC")<<"FixTrajBegin: atPt "<<atPt<<" firstPt "<<firstPt<<" Stops at end 0? "<<PrintStopFlag(tj, 0)<<" start vertex "<<tj.VtxID[0]<<" maxDelta "<<maxDelta;
3128  }
3129 
3130  // update the trajectory for all the points up to atPt
3131  // assume that we will use all of these points
3132  bool maskedPts = false;
3133  for(unsigned short ii = 1; ii < tj.Pts.size(); ++ii) {
3134  if(ii > atPt) break;
3135  unsigned int ipt = atPt - ii;
3136  TrajPoint& tp = tj.Pts[ipt];
3137  tp.Dir = tj.Pts[atPt].Dir;
3138  tp.Ang = tj.Pts[atPt].Ang;
3139  tp.AngErr = tj.Pts[atPt].AngErr;
3140  tp.AngleCode = tj.Pts[atPt].AngleCode;
3141  // Correct the projected time to the wire
3142  float dw = tp.Pos[0] - tj.Pts[atPt].Pos[0];
3143  if(tp.Dir[0] != 0) tp.Pos[1] = tj.Pts[atPt].Pos[1] + dw * tp.Dir[1] / tp.Dir[0];
3144  tj.Pts[ipt].Delta = PointTrajDOCA(slc, tj.Pts[ipt].HitPos[0], tj.Pts[ipt].HitPos[1], tj.Pts[ipt]);
3145  tj.Pts[ipt].DeltaRMS = tj.Pts[atPt].DeltaRMS;
3146  tj.Pts[ipt].NTPsFit = tj.Pts[atPt].NTPsFit;
3147  tj.Pts[ipt].FitChi = tj.Pts[atPt].FitChi;
3148  tj.Pts[ipt].AveChg = tj.Pts[atPt].AveChg;
3149  tj.Pts[ipt].ChgPull = (tj.Pts[ipt].Chg / tj.AveChg - 1) / tj.ChgRMS;
3150  bool maskThisPt = (tj.Pts[ipt].Delta > maxDelta);
3151  if(maskThisPt) maskedPts = true;
3152  if(tcc.useAlg[kNewStpCuts]) {
3153  // 10/1/18 BB only mask off the bad point. Not all of them to the end
3154  if(maskThisPt) {
3155  UnsetUsedHits(slc, tp);
3156  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" mask off "<<PrintPos(slc, tj.Pts[ipt].Pos)<<" "<<tj.Pts[ipt].Delta;
3157  } // maskThisPt
3158  } else {
3159  // old cuts - mask off all points to the beginning
3160  if(maskedPts) {
3161  UnsetUsedHits(slc, tp);
3162  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" mask off "<<PrintPos(slc, tj.Pts[ipt].Pos)<<" "<<tj.Pts[ipt].Delta;
3163  } // maskedPts
3164  } // old cuts
3165  if(ipt == 0) break;
3166  } // ii
3167  if(maskedPts) SetEndPoints(tj);
3168  tj.AlgMod[kFixBegin] = true;
3169 
3170  } // FixTrajBegin
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
TCConfig tcc
Definition: DataStructs.cxx:6
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1162
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
std::string PrintStopFlag(const Trajectory &tj, unsigned short end)
Definition: Utils.cxx:5677
void tca::FixTrajEnd ( TCSlice slc,
Trajectory tj,
unsigned short  atPt 
)

Definition at line 3173 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::TrajPoint::Ang, tca::TrajPoint::AngErr, tca::TrajPoint::AngleCode, tca::Trajectory::AveChg, tca::Trajectory::ChgRMS, tca::TCConfig::dbgStp, tca::TrajPoint::Dir, tca::Trajectory::EndPt, kBragg, kFixEnd, kJunkTj, tca::Trajectory::MCSMom, NumPtsWithCharge(), tca::Trajectory::PDGCode, PointTrajDOCA(), tca::TrajPoint::Pos, PrintTrajectory(), tca::Trajectory::Pts, tca::Trajectory::StopFlag, tcc, and tca::TCConfig::useAlg.

3174  {
3175  // Update the parameters at the end of the trajectory starting at point atPt
3176 
3177  if(!tcc.useAlg[kFixEnd]) return;
3178  // ignore short trajectories
3179  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
3180  if(npwc < 6) return;
3181  // ignore somewhat longer trajectories that are curly
3182  if(npwc < 10 && tj.MCSMom < 100) return;
3183  // ignore shower-like trajectories
3184  if(tj.PDGCode == 11) return;
3185  // ignore junk trajectories
3186  if(tj.AlgMod[kJunkTj]) return;
3187  // ingore stopping trajectories
3188  if(tj.StopFlag[1][kBragg]) return;
3189 
3190  if(tcc.dbgStp) {
3191  mf::LogVerbatim("TC")<<"FixTrajEnd: atPt "<<atPt;
3192  }
3193 
3194  if(atPt == tj.EndPt[1]) return;
3195 
3196  // update the trajectory for all the intervening points
3197  for(unsigned short ipt = atPt + 1; ipt <= tj.EndPt[1]; ++ipt) {
3198  TrajPoint& tp = tj.Pts[ipt];
3199  tp.Dir = tj.Pts[atPt].Dir;
3200  tp.Ang = tj.Pts[atPt].Ang;
3201  tp.AngErr = tj.Pts[atPt].AngErr;
3202  tp.AngleCode = tj.Pts[atPt].AngleCode;
3203  // Correct the projected time to the wire
3204  float dw = tp.Pos[0] - tj.Pts[atPt].Pos[0];
3205  if(tp.Dir[0] != 0) tp.Pos[1] = tj.Pts[atPt].Pos[1] + dw * tp.Dir[1] / tp.Dir[0];
3206  tj.Pts[ipt].Delta = PointTrajDOCA(slc, tj.Pts[ipt].HitPos[0], tj.Pts[ipt].HitPos[1], tj.Pts[ipt]);
3207  tj.Pts[ipt].DeltaRMS = tj.Pts[atPt].DeltaRMS;
3208  tj.Pts[ipt].NTPsFit = tj.Pts[atPt].NTPsFit;
3209  tj.Pts[ipt].FitChi = tj.Pts[atPt].FitChi;
3210  tj.Pts[ipt].AveChg = tj.Pts[atPt].AveChg;
3211  tj.Pts[ipt].ChgPull = (tj.Pts[ipt].Chg / tj.AveChg - 1) / tj.ChgRMS;
3212  if(tcc.dbgStp) {
3213  PrintTrajectory("FTE", slc, tj, ipt);
3214  }
3215  } // ipt
3216  tj.AlgMod[kFixEnd] = true;
3217 
3218  } // FixTrajEnd
void PrintTrajectory(std::string someText, TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:5455
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
void tca::FollowTp3s ( TCSlice slc,
PFPStruct pfp,
bool  prt 
)

Definition at line 405 of file PFPUtils.cxx.

References detinfo::DetectorProperties::ConvertXToTicks(), geo::CryostatID::Cryostat, DecodeCTP(), tca::TCConfig::detprop, tca::PFPStruct::Dir, FindAlongTrans(), tca::TCConfig::geom, kEnvFlag, tca::TCSlice::nPlanes, geo::PlaneID::Plane, PointDirection(), PosSep(), PosSep2(), SetMag(), tcc, tca::PFPStruct::TjIDs, tca::TCSlice::tjs, tca::PFPStruct::Tp3s, geo::TPCID::TPC, tca::PFPStruct::TPCID, tca::TCConfig::unitsPerTick, tca::TCSlice::vtx3s, tca::PFPStruct::Vx3ID, geo::GeometryCore::WireCoordinate(), tca::TCConfig::wirePitch, and tca::PFPStruct::XYZ.

Referenced by DefinePFP().

406  {
407  // Step through the set of Tp3s on this pfp to create a trajectory. The start and end points
408  // are assumed to be Tp3s[0] and Tp3s[Tp3s.size()-1] respectively.
409 
410  if(pfp.Tp3s.size() < 2) return;
411 
412  unsigned short startPt = 0;
413  unsigned short endPt = pfp.Tp3s.size() - 1;
414  // divide the trajectory in 5 cm long sections. The average position of the Tp3s in
415  // each section will be found. Tp3s
416  constexpr float sectionLen = 5;
417  float endAlong = pfp.Tp3s[0].AlongTrans[0] + sectionLen;
418  std::vector<Vector3_t> sectionPos;
419  sectionPos.push_back(pfp.Tp3s[0].Pos);
420  std::vector<unsigned short> sectionPt;
421  sectionPt.push_back(0);
422  for(unsigned short section = 0; section < 100; ++section) {
423  // a point to find the average position in this section
424  Point3_t avePos {{0,0,0}};
425  Vector3_t aveDir {{0,0,0}};
426  unsigned short cnt = 0;
427  for(unsigned short ipt = startPt; ipt < endPt; ++ipt) {
428  auto& tp3 = pfp.Tp3s[ipt];
429  // The path length along the direction vector from the start point to the end
430  // point was stashed in dEdxErr
431  // remove outliers
432  if(tp3.AlongTrans[1] > 2) continue;
433  if(tp3.AlongTrans[0] < endAlong) {
434  // still in the same section - sum and continue
435  for(unsigned short xyz = 0; xyz < 3; ++xyz) {
436  avePos[xyz] += tp3.Pos[xyz];
437  aveDir[xyz] += tp3.Dir[xyz];
438  }
439  ++cnt;
440  continue;
441  }
442  // entered the next section. Check for a failure
443  if(cnt == 0) continue;
444  // calculate the average position
445  for(unsigned short xyz = 0; xyz < 3; ++xyz) avePos[xyz] /= cnt;
446  SetMag(aveDir, 1);
447 /*
448  std::cout<<"Section "<<section<<" cnt "<<cnt<<" avePos"<<std::fixed<<std::setprecision(1);
449  std::cout<<" "<<avePos[0]<<" "<<avePos[1]<<" "<<avePos[2];
450  std::cout<<" aveDir "<<std::setprecision(2)<<aveDir[0]<<" "<<aveDir[1]<<" "<<aveDir[2]<<"\n";
451 */
452  sectionPos.push_back(avePos);
453  sectionPt.push_back(ipt);
454  startPt = ipt;
455  endAlong += sectionLen;
456  break;
457  } // ipt
458  } // section
459  sectionPos.push_back(pfp.Tp3s[endPt].Pos);
460  sectionPt.push_back(pfp.Tp3s.size() - 1);
461 /*
462  for(unsigned short ipt = 0; ipt < sectionPos.size(); ++ipt) {
463  std::cout<<ipt<<" sectionPt "<<sectionPt[ipt]<<" sectionPos "<<" "<<sectionPos[ipt][0]<<" "<<sectionPos[ipt][1]<<" "<<sectionPos[ipt][2]<<"\n";
464  } // ipt
465 */
466  // set the general purpose flag bit false (unused) for all Tj Pts. This will be set true
467  // when a Tp is used in a Tp3
468  for(auto tjid : pfp.TjIDs) {
469  auto& tj = slc.tjs[tjid - 1];
470  for(auto& tp : tj.Pts) tp.Environment[kEnvFlag] = false;
471  } // tjid
472  // set the bits true for the first point
473  for(auto tj2pt : pfp.Tp3s[0].Tj2Pts) {
474  slc.tjs[tj2pt.id - 1].Pts[tj2pt.ipt].Environment[kEnvFlag] = true;
475  }
476  // create a vector of new Tp3s that will replace pfp.Tp3s
477  std::vector<TrajPoint3> ntp3;
478  ntp3.push_back(pfp.Tp3s[0]);
479  // 2D position (WSE units) of the TPs at the start of this section. We will require that all 2D TPs are
480  // less than sectionLen (in WSE units) from this point.
481  std::vector<Point2_t> startPos2D(slc.nPlanes);
482  // collect Tp3s in each section
483  unsigned short lastPtAdded = 0;
484  for(unsigned short section = 1; section < sectionPt.size(); ++section) {
485  Point3_t startPos = sectionPos[section - 1];
486  Point3_t endPos = sectionPos[section];
487  auto startDir = PointDirection(startPos, endPos);
488  // define the pfp start direction
489  if(section == 1) pfp.Dir[0] = startDir;
490  // and the end direction
491  pfp.Dir[1] = startDir;
492 // std::cout<<"Section "<<section<<" startDir "<<std::fixed<<std::setprecision(2)<<startDir[0]<<" "<<startDir[1]<<" "<<startDir[2]<<"\n";
493  // define the 2D positions for this point in each plane
494  for(unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
495  geo::PlaneID planeID = geo::PlaneID(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
496  startPos2D[plane][0] = tcc.geom->WireCoordinate(sectionPos[section - 1][1], sectionPos[section - 1][2], planeID);
497  startPos2D[plane][1] = tcc.detprop->ConvertXToTicks(sectionPos[section - 1][0], planeID) * tcc.unitsPerTick;
498  } // plane
499  for(unsigned short ipt = sectionPt[section - 1]; ipt < sectionPt[section]; ++ipt) {
500  auto& tp3 = pfp.Tp3s[ipt];
501  // count the number of Tps in this Tp3 that are already used in the trajectory
502  unsigned short nused = 0;
503  bool big2DSep = false;
504  for(auto tj2pt : pfp.Tp3s[ipt].Tj2Pts) {
505  auto& tp = slc.tjs[tj2pt.id - 1].Pts[tj2pt.ipt];
506  if(tp.Environment[kEnvFlag]) ++nused;
507  unsigned short plane = DecodeCTP(tp.CTP).Plane;
508  float sep2D = PosSep(startPos2D[plane], tp.Pos) * tcc.wirePitch;
509  if(sep2D > sectionLen) big2DSep = true;
510  } // tj2pt
511  if(big2DSep || nused > 1) continue;
512  Point2_t alongTrans;
513  FindAlongTrans(startPos, startDir, tp3.Pos, alongTrans);
514  if(alongTrans[1] > 0.5) continue;
515 /*
516  std::cout<<section<<" ipt "<<ipt<<" trans "<<alongTrans[1]<<" tj_ipt";
517  for(auto tj2pt : tp3.Tj2Pts) std::cout<<" "<<tj2pt.id - 1<<"_"<<tj2pt.ipt;
518  std::cout<<"\n";
519 */
520  tp3.AlongTrans = alongTrans;
521  // don't clobber the original direction
522 // tp3.Dir = dir;
523  ntp3.push_back(tp3);
524  // set the flag
525  for(auto tj2pt : tp3.Tj2Pts) slc.tjs[tj2pt.id - 1].Pts[tj2pt.ipt].Environment[kEnvFlag] = true;
526  lastPtAdded = ipt;
527  } // ipt
528  } // section
529 
530  if(lastPtAdded != endPt) ntp3.push_back(pfp.Tp3s[endPt]);
531 
532  if(prt) {
533  float len = PosSep(ntp3[0].Pos, ntp3[ntp3.size()-1].Pos);
534  mf::LogVerbatim("TC")<<"FollowTp3s: Tp3s size in "<<pfp.Tp3s.size()<<" size out "<<ntp3.size()<<" len "<<std::fixed<<std::setprecision(2)<<len;
535  }
536 
537  // reverse if necessary to be consistent with a vertex
538  if(pfp.Vx3ID[0] > 0) {
539  auto& vx3 = slc.vtx3s[pfp.Vx3ID[0] - 1];
540  Point3_t vpos = {{vx3.X, vx3.Y, vx3.Z}};
541  auto& firstTp3Pos = ntp3[0].Pos;
542  auto& lastTp3Pos = ntp3[ntp3.size() - 1].Pos;
543  if(PosSep2(lastTp3Pos, vpos) < PosSep2(firstTp3Pos, vpos)) std::reverse(ntp3.begin(), ntp3.end());
544  } // pfp.Vx3ID[0] > 0
545 
546  pfp.Tp3s = ntp3;
547  // The directions were set above. Set the start and end positions. Note that the start position
548  // may have been previously determined by a vertex but that is now superseded by the actual start
549  // of the pfp
550  pfp.XYZ[0] = ntp3[0].Pos;
551  pfp.XYZ[1] = ntp3[ntp3.size()-1].Pos;
552 // if(prt) PrintTp3s("FTp3o", slc, pfp, -1);
553 
554  } // FollowTp3s
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::array< double, 3 > Point3_t
Definition: DataStructs.h:35
TCConfig tcc
Definition: DataStructs.cxx:6
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:2849
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:442
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
const detinfo::DetectorProperties * detprop
Definition: DataStructs.h:494
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:1643
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1660
const geo::GeometryCore * geom
Definition: DataStructs.h:493
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:1670
geo::PlaneID DecodeCTP(CTP_t CTP)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
std::array< double, 3 > Vector3_t
Definition: DataStructs.h:36
void tca::Forecast ( TCSlice slc,
Trajectory tj 
)

Definition at line 404 of file StepUtils.cxx.

References tca::Trajectory::AveChg, tca::Trajectory::ChgRMS, ChgSlope(), ChkStop(), tca::Trajectory::CTP, tca::TCConfig::dbgStp, DecodeCTP(), DefineHitPos(), tca::Trajectory::EndPt, evt, FindCloseHits(), tca::TCSlice::firstWire, tca::Trajectory::ID, kAllHits, kBragg, kEnvDeadWire, kEnvNearShower, tca::TCSlice::lastWire, tca::Trajectory::MCSMom, MCSMom(), MoveTPToWire(), NumPtsWithCharge(), tca::Trajectory::PDGCode, geo::PlaneID::Plane, PointTrajDOCA(), PrintPos(), tca::Trajectory::Pts, SetEndPoints(), tca::Trajectory::StopFlag, tcc, tjfs, tca::Trajectory::TotChg, UpdateTjChgProperties(), and tca::TCEvent::WorkID.

Referenced by StepAway().

405  {
406  // Extrapolate the last TP of tj by many steps and return a forecast of what is ahead
407  // -1 error or not sure
408  // ~1 track-like with a slight chance of showers
409  // >2 shower-like
410  // nextForecastUpdate is set to the number of points on the trajectory when this function should
411  // be called again
412 
413  if(tj.Pts[tj.EndPt[1]].AngleCode == 2) return;
414  // add a new forecast
415  tjfs.resize(tjfs.size() + 1);
416  // assume there is insufficient info to make a decision
417  auto& tjf = tjfs[tjfs.size() - 1];
418  tjf.outlook = -1;
419  tjf.nextForecastUpdate = USHRT_MAX;
420 
421  unsigned short minShPts = 3;
422 
423  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
424  unsigned short istp = 0;
425  unsigned short nMissed = 0;
426 
427  bool doPrt = tcc.dbgStp;
428  // turn off annoying output from DefineHitPos
429  if(doPrt) tcc.dbgStp = false;
430  // find the minimum average TP charge. This will be used to calculate the
431  // 'effective number of hits' on a wire = total charge on the wire within the
432  // window / (minimum average TP charge). This is intended to reduce the sensitivity
433  // of this metric to the hit finder configuration
434  float minAveChg = 1E6;
435  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
436  if(tj.Pts[ipt].AveChg <= 0) continue;
437  if(tj.Pts[ipt].AveChg > minAveChg) continue;
438  minAveChg = tj.Pts[ipt].AveChg;
439  } // ipt
440  if(minAveChg <= 0 || minAveChg == 1E6) return;
441  // start a forecast Tj comprised of the points in the forecast envelope
442  Trajectory fctj;
443  fctj.CTP = tj.CTP;
444  fctj.ID = evt.WorkID;
445  // make a local copy of the last point
446  auto tp = tj.Pts[tj.EndPt[1]];
447  // Use the hits position instead of the fitted position so that a bad
448  // fit doesn't screw up the forecast.
449  float forecastWin0 = std::abs(tp.Pos[1] - tp.HitPos[1]);
450  if(forecastWin0 < 1) forecastWin0 = 1;
451  tp.Pos = tp.HitPos;
452  double stepSize = std::abs(1/tp.Dir[0]);
453  float window = 10 * stepSize;
454  if(doPrt) {
455  mf::LogVerbatim("TC")<<"Forecast T"<<tj.ID<<" PDGCode "<<tj.PDGCode<<" npwc "<<npwc<<" minAveChg "<<(int)minAveChg<<" stepSize "<<std::setprecision(2)<<stepSize<<" window "<<window;
456  mf::LogVerbatim("TC")<<" stp ___Pos____ nTPH Chg ChgPull Delta DRMS chgWid nTkLk nShLk";
457  }
458  unsigned short plane = DecodeCTP(tp.CTP).Plane;
459  float totHits = 0;
460  fctj.TotChg = 0;
461  float maxChg = 0;
462  unsigned short maxChgPt = 0;
463  unsigned short leavesNear = USHRT_MAX;
464  bool leavesBeforeEnd = false;
465  unsigned short showerStartNear = USHRT_MAX;
466  unsigned short showerEndNear = USHRT_MAX;
467  unsigned short nShLike = 0;
468  unsigned short nTkLike = 0;
469  unsigned short trimPts = 0;
470  for(istp = 0; istp < 1000; ++istp) {
471  // move the local TP position by one step in the right direction
472  for(unsigned short iwt = 0; iwt < 2; ++iwt) tp.Pos[iwt] += tp.Dir[iwt] * stepSize;
473  unsigned int wire = std::nearbyint(tp.Pos[0]);
474  if(wire < slc.firstWire[plane]) break;
475  if(wire > slc.lastWire[plane]-1) break;
476  MoveTPToWire(tp, (float)wire);
477  ++tp.Step;
478  if(FindCloseHits(slc, tp, window, kAllHits)) {
479  // Found hits or the wire is dead
480  // set all hits used so that we can use DefineHitPos. Note that
481  // the hit InTraj is not used or tested in DefineHitPos so this doesn't
482  // screw up any assns
483  if(!tp.Environment[kEnvDeadWire]) {
484  nMissed = 0;
485  tp.UseHit.set();
486  DefineHitPos(slc, tp);
487  fctj.TotChg += tp.Chg;
488  tp.Delta = PointTrajDOCA(slc, tp.HitPos[0], tp.HitPos[1], tp);
489  tp.DeltaRMS = tp.Delta / window;
490  tp.Environment.reset();
491  totHits += tp.Hits.size();
492  if(tp.Chg > maxChg) {
493  maxChg = tp.Chg;
494  maxChgPt = fctj.Pts.size();
495  }
496  // Note that ChgPull uses the average charge and charge RMS of the
497  // trajectory before it entered the forecast envelope
498  tp.ChgPull = (tp.Chg / minAveChg - 1) / tj.ChgRMS;
499  if((tp.ChgPull > 3 && tp.Hits.size() > 1) || tp.ChgPull > 10) {
500  ++nShLike;
501  // break if the tj was tracklike before this point
502  if(nShLike > minShPts && nTkLike >= minShPts) {
503  trimPts = minShPts;
504  showerStartNear = npwc + fctj.Pts.size() - minShPts;
505  if(doPrt) {
506  mf::LogVerbatim("TC")<<"showerlike was tracklike - break";
507  }
508  break;
509  }
510  // not track-like anymore
511  if(nShLike >= minShPts) nTkLike = 0;
512  // break if it approaches the side of the envelope
513  if(tp.DeltaRMS > 0.8) {
514  leavesNear = npwc + fctj.Pts.size();
515  leavesBeforeEnd = true;
516  break;
517  }
518  tp.Environment[kEnvNearShower] = true;
519  // flag a showerlike TP so it isn't used in the MCSMom calculation
520  tp.HitPosErr2 = 100;
521  } else {
522  ++nTkLike;
523  // break if the tj was shower-like before this point
524  if(nTkLike > minShPts && nShLike >= minShPts) {
525  trimPts = minShPts;
526  showerEndNear = npwc + fctj.Pts.size() - minShPts;
527  if(doPrt) {
528  mf::LogVerbatim("TC")<<"tracklike was showerlike - break";
529  }
530  break;
531  }
532  // not shower-like anymore
533  if(nTkLike >= minShPts) nShLike = 0;
534  // break if it approaches the side of the envelope
535  if(tp.DeltaRMS > 0.9) {
536  leavesNear = npwc + fctj.Pts.size();
537  leavesBeforeEnd = true;
538  break;
539  }
540  }
541  fctj.Pts.push_back(tp);
542  if(doPrt) {
543  mf::LogVerbatim myprt("TC");
544  myprt<<std::setw(4)<<npwc + fctj.Pts.size()<<" "<<PrintPos(slc, tp);
545  myprt<<std::setw(5)<<tp.Hits.size();
546  myprt<<std::setw(5)<<(int)tp.Chg;
547  myprt<<std::fixed<<std::setprecision(1);
548  myprt<<std::setw(8)<<tp.ChgPull;
549  myprt<<std::setw(8)<<tp.Delta;
550  myprt<<std::setw(8)<<std::setprecision(2)<<tp.DeltaRMS;
551  myprt<<std::setw(8)<<sqrt(tp.HitPosErr2);
552  myprt<<std::setw(6)<<nTkLike;
553  myprt<<std::setw(6)<<nShLike;
554  } // doPrt
555  } else {
556 // if(doPrt) std::cout<<istp<<" Pos "<<PrintPos(slc, tp)<<" window "<<window<<" dead wire\n";
557  }
558  } else {
559  // no hits found
560  ++nMissed;
561  if(nMissed == 10) {
562  if(doPrt) mf::LogVerbatim("TC")<<"No hits found after 10 steps - break";
563  break;
564  }
565  } // no hits found
566  } // istp
567  // not enuf info to make a forecast
568  tcc.dbgStp = doPrt;
569  if(fctj.Pts.size() < 6) return;
570  // truncate and re-calculate totChg?
571  if(trimPts > 0) {
572  // truncate the forecast trajectory
573  fctj.Pts.resize(fctj.Pts.size() - trimPts);
574  // recalculate the total charge
575  fctj.TotChg = 0;
576  for(auto& tp : fctj.Pts) fctj.TotChg += tp.Chg;
577  } // showerEndNear != USHRT_MAX
578  SetEndPoints(fctj);
579  fctj.MCSMom = MCSMom(slc, fctj);
580  tjf.MCSMom = fctj.MCSMom;
581  if(maxChgPt > 0.3 * fctj.Pts.size() && maxChg > 3 * tj.AveChg) {
582  // find the charge slope from the beginning to the maxChgPt if it is well away
583  // from the start and it is very large
584  ChgSlope(slc, fctj, fctj.EndPt[0], maxChgPt, tjf.chgSlope, tjf.chgSlopeErr, tjf.chgFitChiDOF);
585  } else {
586  ChgSlope(slc, fctj, tjf.chgSlope, tjf.chgSlopeErr, tjf.chgFitChiDOF);
587  }
588  ChkStop(slc, fctj);
589  UpdateTjChgProperties("Fc", slc, fctj, false);
590  tjf.chgRMS = fctj.ChgRMS;
591  tjf.endBraggPeak = fctj.StopFlag[1][kBragg];
592  // Set outlook = Estimate of the number of hits per wire
593  tjf.outlook = fctj.TotChg / (fctj.Pts.size() * tj.AveChg);
594  // assume we got to the end
595  tjf.nextForecastUpdate = npwc + fctj.Pts.size();
596  tjf.leavesBeforeEnd = leavesBeforeEnd;
597  tjf.foundShower = false;
598  if(leavesNear < tjf.nextForecastUpdate) {
599  // left the side
600  tjf.nextForecastUpdate = leavesNear;
601  } else if(showerStartNear < tjf.nextForecastUpdate) {
602  // found a shower start
603  tjf.nextForecastUpdate = showerStartNear;
604  tjf.foundShower = true;
605  } else if(showerEndNear < tjf.nextForecastUpdate) {
606  // found a shower end
607  tjf.nextForecastUpdate = showerEndNear;
608  }
609  nShLike = 0;
610  for(auto& tp : fctj.Pts) if(tp.Environment[kEnvNearShower]) ++nShLike;
611  tjf.showerLikeFraction = (float)nShLike / (float)fctj.Pts.size();
612 
613  if(doPrt) {
614  mf::LogVerbatim myprt("TC");
615  myprt<<"Forecast T"<<tj.ID<<" tj.AveChg "<<(int)tj.AveChg;
616  myprt<<" start "<<PrintPos(slc, tj.Pts[tj.EndPt[1]])<<" cnt "<<fctj.Pts.size()<<" totChg "<<(int)fctj.TotChg;
617  myprt<<" last pos "<<PrintPos(slc, tp);
618  myprt<<" MCSMom "<<tjf.MCSMom;
619  myprt<<" outlook "<<std::fixed<<std::setprecision(2)<<tjf.outlook;
620  myprt<<" chgSlope "<<std::setprecision(1)<<tjf.chgSlope<<" +/- "<<tjf.chgSlopeErr;
621  myprt<<" chgRMS "<<std::setprecision(1)<<tjf.chgRMS;
622  myprt<<" endBraggPeak "<<tjf.endBraggPeak;
623  myprt<<" chiDOF "<<tjf.chgFitChiDOF;
624  myprt<<" showerLike fraction "<<tjf.showerLikeFraction;
625  myprt<<" nextForecastUpdate "<<tjf.nextForecastUpdate;
626  myprt<<" leavesBeforeEnd? "<<tjf.leavesBeforeEnd;
627  myprt<<" foundShower? "<<tjf.foundShower;
628  }
629 
630  } // Forecast
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
short MCSMom(TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2914
TCConfig tcc
Definition: DataStructs.cxx:6
std::vector< unsigned int > FindCloseHits(TCSlice &slc, std::array< int, 2 > const &wireWindow, Point2_t const &timeWindow, const unsigned short plane, HitStatus_t hitRequest, bool usePeakTime, bool &hitsNear)
Definition: Utils.cxx:2496
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1840
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3196
void ChkStop(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:3952
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
std::vector< TjForecast > tjfs
Definition: DataStructs.cxx:7
void ChgSlope(TCSlice &slc, Trajectory &tj, float &slope, float &slopeErr, float &chiDOF)
Definition: Utils.cxx:1288
geo::PlaneID DecodeCTP(CTP_t CTP)
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2485
TCEvent evt
Definition: DataStructs.cxx:5
std::vector< int > tca::GetAssns ( TCSlice slc,
std::string  type1Name,
int  id,
std::string  type2Name 
)

Definition at line 4279 of file Utils.cxx.

References tca::TCSlice::cots, evd::details::end(), kHaloTj, kKilled, kMat3D, tca::TCSlice::pfps, SetIntersection(), tca::TCSlice::showers, ss, tca::TCSlice::tjs, tmp, tca::TCSlice::vtx3s, and tca::TCSlice::vtxs.

Referenced by ChkVxTjs(), CompleteIncomplete3DVertices(), CompleteIncompleteShower(), DefineDontCluster(), DefinePFPParents(), DotProd(), FindCots(), FindHammerVertices(), FindNearbyTjs(), FindParent(), Finish3DShowers(), KillVerticesInShower(), MergeNearby2DShowers(), ParentFOM(), Print3V(), PrintAllTraj(), Reconcile3D(), SetParent(), and TagShowerLike().

4280  {
4281  // returns a list of IDs of objects (slc, vertices, pfps, etc) with type1Name that are in slc with
4282  // type2Name. This is intended to be a general purpose replacement for specific functions like GetVtxTjIDs, etc
4283 
4284  std::vector<int> tmp;
4285  if(id <= 0) return tmp;
4286  unsigned int uid = id;
4287 
4288  if(type1Name == "T" && uid <= slc.tjs.size() && type2Name == "P") {
4289  // return a list of PFPs that have the tj in TjIDs, P -> T<ID>
4290  for(auto& pfp : slc.pfps) {
4291  if(pfp.ID <= 0) continue;
4292  if(std::find(pfp.TjIDs.begin(), pfp.TjIDs.end(), id) != pfp.TjIDs.end()) tmp.push_back(pfp.ID);
4293  } // pf
4294  return tmp;
4295  } // P -> T
4296 
4297  if(type1Name == "P" && uid <= slc.pfps.size() && (type2Name == "2S" || type2Name == "3S")) {
4298  // return a list of 3D or 2D showers with the assn 3S -> 2S -> T -> P<ID> or 2S -> T -> P.
4299  auto& pfp = slc.pfps[uid - 1];
4300  // First form a list of 2S -> T -> P<ID>
4301  std::vector<int> ssid;
4302  for(auto& ss : slc.cots) {
4303  if(ss.ID <= 0) continue;
4304  auto shared = SetIntersection(ss.TjIDs, pfp.TjIDs);
4305  if(!shared.empty() && std::find(ssid.begin(), ssid.end(), ss.ID) == ssid.end()) ssid.push_back(ss.ID);
4306  } // ss
4307  if(type2Name == "2S") return ssid;
4308  for(auto& ss3 : slc.showers) {
4309  if(ss3.ID <= 0) continue;
4310  auto shared = SetIntersection(ss3.CotIDs, ssid);
4311  if(!shared.empty() && std::find(tmp.begin(), tmp.end(), ss3.ID) == tmp.end()) tmp.push_back(ss3.ID);
4312  } // ss3
4313  return tmp;
4314  } // 3S -> 2S -> T -> P
4315 
4316  if(type1Name == "2V" && uid <= slc.vtxs.size() && type2Name == "T" ) {
4317  // 2V -> T
4318  for(auto& tj : slc.tjs) {
4319  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
4320  for(unsigned short end = 0; end < 2; ++end) {
4321  if(tj.VtxID[end] != id) continue;
4322  if(std::find(tmp.begin(), tmp.end(), tj.ID) == tmp.end()) tmp.push_back(tj.ID);
4323  } // end
4324  } // tj
4325  return tmp;
4326  } // 2V -> T
4327 
4328  if(type1Name == "3V" && uid <= slc.vtx3s.size() && type2Name == "P") {
4329  for(auto& pfp : slc.pfps) {
4330  if(pfp.ID == 0) continue;
4331  for(unsigned short end = 0; end < 2; ++end) {
4332  if(pfp.Vx3ID[end] != id) continue;
4333  // encode the end with the ID
4334  if(std::find(tmp.begin(), tmp.end(), pfp.ID) == tmp.end()) tmp.push_back(pfp.ID);
4335  } // end
4336  } // pfp
4337  return tmp;
4338  } // 3V -> P
4339 
4340  if(type1Name == "3V" && uid <= slc.vtx3s.size() && type2Name == "T") {
4341  // 3V -> T
4342  for(auto& tj : slc.tjs) {
4343  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
4344  for(unsigned short end = 0; end < 2; ++end) {
4345  if(tj.VtxID[end] > 0 && tj.VtxID[end] <= slc.vtxs.size()) {
4346  auto& vx2 = slc.vtxs[tj.VtxID[end] - 1];
4347  if(vx2.Vx3ID != id) continue;
4348  if(std::find(tmp.begin(), tmp.end(), tj.ID) == tmp.end()) tmp.push_back(tj.ID);
4349  }
4350  } // end
4351  } // tj
4352  return tmp;
4353  } // 3V -> T
4354 
4355  if(type1Name == "3V" && uid <= slc.vtx3s.size() && type2Name == "2V") {
4356  // 3V -> 2V
4357  for(auto& vx2 : slc.vtxs) {
4358  if(vx2.ID == 0) continue;
4359  if(vx2.Vx3ID == id) tmp.push_back(vx2.ID);
4360  } // vx2
4361  return tmp;
4362  } // 3V -> 2V
4363 
4364  if(type1Name == "3S" && uid <= slc.showers.size() && type2Name == "T") {
4365  // 3S -> T
4366  auto& ss3 = slc.showers[uid - 1];
4367  if(ss3.ID == 0) return tmp;
4368  for(auto cid : ss3.CotIDs) {
4369  auto& ss = slc.cots[cid - 1];
4370  if(ss.ID == 0) continue;
4371  tmp.insert(tmp.end(), ss.TjIDs.begin(), ss.TjIDs.end());
4372  } // cid
4373  return tmp;
4374  } // 3S -> T
4375 
4376  // This isn't strictly necessary but do it for consistency
4377  if(type1Name == "2S" && uid <= slc.cots.size() && type2Name == "T") {
4378  // 2S -> T
4379  auto& ss = slc.cots[uid - 1];
4380  return ss.TjIDs;
4381  } // 2S -> T
4382 
4383  if(type1Name == "3S" && uid <= slc.showers.size() && type2Name == "P") {
4384  // 3S -> P
4385  auto& ss3 = slc.showers[uid - 1];
4386  if(ss3.ID == 0) return tmp;
4387  for(auto cid : ss3.CotIDs) {
4388  auto& ss = slc.cots[cid - 1];
4389  if(ss.ID == 0) continue;
4390  for(auto tid : ss.TjIDs) {
4391  auto& tj = slc.tjs[tid - 1];
4392  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
4393  if(!tj.AlgMod[kMat3D]) continue;
4394  for(auto& pfp : slc.pfps) {
4395  if(pfp.ID <= 0) continue;
4396  if(std::find(pfp.TjIDs.begin(), pfp.TjIDs.end(), tj.ID) == pfp.TjIDs.end()) continue;
4397  if(std::find(tmp.begin(), tmp.end(), pfp.ID) == tmp.end()) tmp.push_back(pfp.ID);
4398  } // pf
4399  } // tid
4400  } // cid
4401  return tmp;
4402  } // 3S -> P
4403 
4404  if(type1Name == "T" && uid <= slc.tjs.size() && type2Name == "2S") {
4405  // T -> 2S
4406  for(auto& ss : slc.cots) {
4407  if(ss.ID == 0) continue;
4408  if(std::find(ss.TjIDs.begin(), ss.TjIDs.end(), id) != ss.TjIDs.end()) tmp.push_back(ss.ID);
4409  } // ss
4410  return tmp;
4411  } // T -> 2S
4412 
4413  if(type1Name == "T" && uid <= slc.tjs.size() && type2Name == "3S") {
4414  // T -> 3S
4415  for(auto& ss : slc.cots) {
4416  if(ss.ID == 0) continue;
4417  if(std::find(ss.TjIDs.begin(), ss.TjIDs.end(), id) == ss.TjIDs.end()) continue;
4418  if(ss.SS3ID > 0) tmp.push_back(ss.SS3ID);
4419  } // ss
4420  return tmp;
4421  } // T -> 3S
4422 
4423  std::cout<<"GetAssns doesn't know about "<<type1Name<<" -> "<<type2Name<<" assns, or id "<<id<<" is not valid.\n";
4424 
4425  return tmp;
4426 
4427  } // 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:231
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
int tca::GetCotID ( TCSlice slc,
int  ShowerTjID 
)

Definition at line 4359 of file TCShower.cxx.

References tca::TCSlice::cots.

Referenced by MergeShowerTjsAndStore().

4360  {
4361  for(unsigned short ii = 0; ii < slc.cots.size(); ++ii) {
4362  if(ShowerTjID == slc.cots[ii].ShowerTjID) return ii + 1;
4363  } // iii
4364  return 0;
4365 
4366  } // GetCotID
void tca::GetHitMultiplet ( TCSlice slc,
unsigned int  theHit,
std::vector< unsigned int > &  hitsInMultiplet 
)

Definition at line 1573 of file StepUtils.cxx.

References GetHitMultiplet().

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

1574  {
1575  unsigned short localIndex;
1576  GetHitMultiplet(slc, theHit, hitsInMultiplet, localIndex);
1577  } // GetHitMultiplet
void GetHitMultiplet(TCSlice &slc, unsigned int theHit, std::vector< unsigned int > &hitsInMultiplet, unsigned short &localIndex)
Definition: StepUtils.cxx:1580
void tca::GetHitMultiplet ( TCSlice slc,
unsigned int  theHit,
std::vector< unsigned int > &  hitsInMultiplet,
unsigned short &  localIndex 
)

Definition at line 1580 of file StepUtils.cxx.

References tca::TCEvent::allHits, tca::TCEvent::aveHitRMS, evt, tca::TCConfig::multHitSep, tca::TCSlice::slHits, tcc, and tmp.

Referenced by AddHits(), FindUseHits(), GetHitMultiplet(), and IsGhost().

1581  {
1582  hitsInMultiplet.clear();
1583  localIndex = 0;
1584  if(theHit > slc.slHits.size() - 1) return;
1585  if(slc.slHits[theHit].InTraj == SHRT_MAX) return;
1586  hitsInMultiplet.resize(1);
1587  hitsInMultiplet[0] = theHit;
1588 
1589  auto& hit = (*evt.allHits)[slc.slHits[theHit].allHitsIndex];
1590  unsigned int theWire = hit.WireID().Wire;
1591  unsigned short ipl = hit.WireID().Plane;
1592  float theTime = hit.PeakTime();
1593  float theRMS = hit.RMS();
1594  float narrowHitCut = 1.5 * evt.aveHitRMS[ipl];
1595  bool theHitIsNarrow = (theRMS < narrowHitCut);
1596  float maxPeak = hit.PeakAmplitude();
1597  unsigned short imTall = theHit;
1598  unsigned short nNarrow = 0;
1599  if(theHitIsNarrow) nNarrow = 1;
1600  // look for hits < theTime but within hitSep
1601  if(theHit > 0) {
1602  for(unsigned int iht = theHit - 1; iht != 0; --iht) {
1603  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1604  if(hit.WireID().Wire != theWire) break;
1605  if(hit.WireID().Plane != ipl) break;
1606  float hitSep = tcc.multHitSep * theRMS;
1607  float rms = hit.RMS();
1608  if(rms > theRMS) {
1609  hitSep = tcc.multHitSep * rms;
1610  theRMS = rms;
1611  }
1612  float dTick = std::abs(hit.PeakTime() - theTime);
1613  if(dTick > hitSep) break;
1614  hitsInMultiplet.push_back(iht);
1615  if(rms < narrowHitCut) ++nNarrow;
1616  float peakAmp = hit.PeakAmplitude();
1617  if(peakAmp > maxPeak) {
1618  maxPeak = peakAmp;
1619  imTall = iht;
1620  }
1621  theTime = hit.PeakTime();
1622  if(iht == 0) break;
1623  } // iht
1624  } // iht > 0
1625  localIndex = hitsInMultiplet.size() - 1;
1626  // reverse the order so that hitsInMuliplet will be
1627  // returned in increasing time order
1628  if(hitsInMultiplet.size() > 1) std::reverse(hitsInMultiplet.begin(), hitsInMultiplet.end());
1629  // look for hits > theTime but within hitSep
1630  theTime = hit.PeakTime();
1631  theRMS = hit.RMS();
1632  for(unsigned int iht = theHit + 1; iht < slc.slHits.size(); ++iht) {
1633  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1634  if(hit.WireID().Wire != theWire) break;
1635  if(hit.WireID().Plane != ipl) break;
1636  if(slc.slHits[iht].InTraj == SHRT_MAX) continue;
1637  float hitSep = tcc.multHitSep * theRMS;
1638  float rms = hit.RMS();
1639  if(rms > theRMS) {
1640  hitSep = tcc.multHitSep * rms;
1641  theRMS = rms;
1642  }
1643  float dTick = std::abs(hit.PeakTime() - theTime);
1644  if(dTick > hitSep) break;
1645  hitsInMultiplet.push_back(iht);
1646  if(rms < narrowHitCut) ++nNarrow;
1647  float peakAmp = hit.PeakAmplitude();
1648  if(peakAmp > maxPeak) {
1649  maxPeak = peakAmp;
1650  imTall = iht;
1651  }
1652  theTime = hit.PeakTime();
1653  } // iht
1654  if(hitsInMultiplet.size() == 1) return;
1655 
1656  if(hitsInMultiplet.size() > 16) {
1657  // Found > 16 hits in a multiplet which would be bad for UseHit. Truncate it
1658  hitsInMultiplet.resize(16);
1659  return;
1660  }
1661 
1662  // Don't make a multiplet that includes a tall narrow hit with short fat hits
1663  if(nNarrow == hitsInMultiplet.size()) return;
1664  if(nNarrow == 0) return;
1665 
1666  if(theHitIsNarrow && theHit == imTall) {
1667  // theHit is narrow and it is the highest amplitude hit in the multiplet. Ignore any
1668  // others that are short and fat
1669  auto tmp = hitsInMultiplet;
1670  tmp.resize(1);
1671  tmp[0] = theHit;
1672  hitsInMultiplet = tmp;
1673  } else {
1674  // theHit is not narrow and it is not the tallest. Ignore a single hit if it is
1675  // the tallest and narrow
1676  auto& hit = (*evt.allHits)[slc.slHits[imTall].allHitsIndex];
1677  if(hit.RMS() < narrowHitCut) {
1678  unsigned short killMe = 0;
1679  for(unsigned short ii = 0; ii < hitsInMultiplet.size(); ++ii) {
1680  if(hitsInMultiplet[ii] == imTall) {
1681  killMe = ii;
1682  break;
1683  }
1684  } // ii
1685  hitsInMultiplet.erase(hitsInMultiplet.begin() + killMe);
1686  } // slc.slHits[imTall].RMS < narrowHitCut
1687  } // narrow / tall test
1688 
1689  } // GetHitMultiplet
TCConfig tcc
Definition: DataStructs.cxx:6
Float_t tmp
Definition: plot.C:37
std::vector< float > aveHitRMS
average RMS of an isolated hit
Definition: DataStructs.h:541
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
float multHitSep
preferentially "merge" hits with < this separation
Definition: DataStructs.h:491
TCEvent evt
Definition: DataStructs.cxx:5
int tca::GetOrigin ( TCSlice slc,
PFPStruct pfp 
)

Definition at line 77 of file TCCR.cxx.

References tca::TCEvent::allHits, tca::TCHit::allHitsIndex, cheat::BackTrackerService::ChannelToTrackIDEs(), evt, tca::TCConfig::geom, simb::MCTruth::Origin(), geo::origin(), geo::GeometryCore::PlaneWireToChannel(), tca::Trajectory::Pts, tca::TCSlice::slHits, tcc, tca::PFPStruct::TjIDs, tca::TCSlice::tjs, and cheat::ParticleInventoryService::TrackIdToMCTruth_P().

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 = slc.tjs[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& slhit = slc.slHits[iht];
92  auto& hit = (*evt.allHits)[slhit.allHitsIndex];
93  raw::ChannelID_t channel = tcc.geom->PlaneWireToChannel((int)hit.WireID().Plane, (int)hit.WireID().Wire, (int)hit.WireID().TPC, (int)hit.WireID().Cryostat);
94  double startTick = hit.PeakTime() - hit.RMS();
95  double endTick = hit.PeakTime() + hit.RMS();
96  // get a list of track IDEs that are close to this hit
97  std::vector<sim::TrackIDE> tides;
98  tides = bt_serv->ChannelToTrackIDEs(channel, startTick, endTick);
99  for(auto itide = tides.begin(); itide != tides.end(); ++itide) {
100  omap[pi_serv->TrackIdToMCTruth_P(itide->trackID)->Origin()] += itide->energy;
101  }
102  }
103  }
104  }
105 
106  float maxe = -1;
107  int origin = 0;
108  for (auto & i : omap){
109  if (i.second > maxe){
110  maxe = i.second;
111  origin = i.first;
112  }
113  }
114  return origin;
115  }
TCConfig tcc
Definition: DataStructs.cxx:6
simb::Origin_t Origin() const
Definition: MCTruth.h:71
const geo::GeometryCore * geom
Definition: DataStructs.h:493
Detector simulation of raw signals on wires.
raw::ChannelID_t PlaneWireToChannel(WireID const &wireid) const
Returns the ID of the TPC channel connected to the specified wire.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
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 ( TCSlice slc,
int  tjID 
)

Definition at line 1127 of file Utils.cxx.

References tca::TCSlice::pfps.

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

1128  {
1129  if(slc.pfps.empty()) return USHRT_MAX;
1130  for(unsigned int ipfp = 0; ipfp < slc.pfps.size(); ++ipfp) {
1131  const auto& pfp = slc.pfps[ipfp];
1132  if(std::find(pfp.TjIDs.begin(), pfp.TjIDs.end(), tjID) != pfp.TjIDs.end()) return ipfp;
1133  } // indx
1134  return USHRT_MAX;
1135  } // GetPFPIndex
std::vector< unsigned short > tca::GetPFPVertices ( const TCSlice slc,
const PFPStruct pfp 
)

Definition at line 3267 of file TCVertex.cxx.

References evd::details::end(), tca::PFPStruct::TjIDs, tca::TCSlice::tjs, tmp, and tca::TCSlice::vtxs.

3268  {
3269  // returns a list of 3D vertices that are attached to Tjs in this pfp. No check is
3270  // made of the actual vertex attachment of the pfp.
3271  std::vector<unsigned short> tmp;
3272  if(pfp.TjIDs.empty()) return tmp;
3273  for(auto tjid : pfp.TjIDs) {
3274  auto& tj = slc.tjs[tjid - 1];
3275  for(unsigned short end = 0; end < 2; ++end) {
3276  if(tj.VtxID[end] == 0) continue;
3277  auto& vx2 = slc.vtxs[tj.VtxID[end] - 1];
3278  if(vx2.Vx3ID == 0) continue;
3279  if(std::find(tmp.begin(), tmp.end(), vx2.Vx3ID) != tmp.end()) continue;
3280  tmp.push_back(vx2.Vx3ID);
3281  } // end
3282  } // tjid
3283  return tmp;
3284  } // GetPFPVertices
Float_t tmp
Definition: plot.C:37
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
std::pair< unsigned short, unsigned short > tca::GetSliceIndex ( std::string  typeName,
int  uID 
)

Definition at line 4496 of file Utils.cxx.

References slices.

Referenced by DotProd(), Finish3DShowers(), MakeHaloTj(), PrimaryUID(), Print2V(), Print3S(), Print3V(), PrintP(), PrintT(), Reconcile3D(), and StitchPFPs().

4497  {
4498  // returns the slice index and product index of a data product having typeName and unique ID uID
4499  for(unsigned short isl = 0; isl < slices.size(); ++isl) {
4500  auto& slc = slices[isl];
4501  if(typeName == "T") {
4502  for(unsigned short indx = 0; indx < slc.tjs.size(); ++indx) {
4503  if(slc.tjs[indx].UID == uID) { return std::make_pair(isl, indx); }
4504  }
4505  } // T
4506  if(typeName == "P") {
4507  for(unsigned short indx = 0; indx < slc.pfps.size(); ++indx) {
4508  if(slc.pfps[indx].UID == uID) { return std::make_pair(isl, indx); }
4509  }
4510  } // P
4511  if(typeName == "2V") {
4512  for(unsigned short indx = 0; indx < slc.vtxs.size(); ++indx) {
4513  if(slc.vtxs[indx].UID == uID) { return std::make_pair(isl, indx); }
4514  }
4515  } // 2V
4516  if(typeName == "3V") {
4517  for(unsigned short indx = 0; indx < slc.vtx3s.size(); ++indx) {
4518  if(slc.vtx3s[indx].UID == uID) { return std::make_pair(isl, indx); }
4519  }
4520  } // 3V
4521  if(typeName == "2S") {
4522  for(unsigned short indx = 0; indx < slc.cots.size(); ++indx) {
4523  if(slc.cots[indx].UID == uID) { return std::make_pair(isl, indx); }
4524  }
4525  } // 2S
4526  if(typeName == "3S") {
4527  for(unsigned short indx = 0; indx < slc.showers.size(); ++indx) {
4528  if(slc.showers[indx].UID == uID) { return std::make_pair(isl, indx); }
4529  }
4530  } // T
4531  } // isl
4532  return std::make_pair(USHRT_MAX, USHRT_MAX);
4533  } // GetSliceIndex
std::vector< TCSlice > slices
Definition: DataStructs.cxx:10
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  }
ShowerTreeVars stv
Definition: DataStructs.cxx:8
std::vector< std::string > StageName
Definition: DataStructs.h:325
std::vector< int > tca::GetVtxTjIDs ( const TCSlice slc,
const VtxStore vx2 
)

Definition at line 3226 of file TCVertex.cxx.

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

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

3227  {
3228  // returns a list of trajectory IDs that are attached to vx2
3229  std::vector<int> tmp;
3230  if(vx2.ID == 0) return tmp;
3231  for(auto& tj : slc.tjs) {
3232  if(tj.AlgMod[kKilled]) continue;
3233  if(tj.CTP != vx2.CTP) continue;
3234  for(unsigned short end = 0; end < 2; ++end) {
3235  if(tj.VtxID[end] == vx2.ID) tmp.push_back(tj.ID);
3236  } // end
3237  } // tj
3238  return tmp;
3239  } // 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 TCSlice slc,
const Vtx3Store vx3,
float &  score 
)

Definition at line 3243 of file TCVertex.cxx.

References GetVtxTjIDs(), tca::Vtx3Store::ID, tmp, and tca::TCSlice::vtxs.

3244  {
3245  // returns a list of Tjs in all planes that are attached to vx3
3246  std::vector<int> tmp;
3247  if(vx3.ID == 0) return tmp;
3248  float nvx2 = 0;
3249  score = 0;
3250  for(auto& vx2 : slc.vtxs) {
3251  if(vx2.ID == 0) continue;
3252  if(vx2.Vx3ID != vx3.ID) continue;
3253  auto vtxTjID2 = GetVtxTjIDs(slc, vx2);
3254  tmp.insert(tmp.end(), vtxTjID2.begin(), vtxTjID2.end());
3255  score += vx2.Score;
3256  ++nvx2;
3257  } // vx2
3258  if(nvx2 < 1) return tmp;
3259  // find the average score
3260  score /= nvx2;
3261  // sort by increasing ID
3262  std::sort(tmp.begin(), tmp.end());
3263  return tmp;
3264  } // GetVtxTjIDs
Float_t tmp
Definition: plot.C:37
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:3243
void tca::GottaKink ( TCSlice slc,
Trajectory tj,
unsigned short &  killPts 
)

Definition at line 2842 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::TrajPoint::Ang, tca::TrajPoint::AngErr, tca::TCConfig::dbgStp, tca::Trajectory::EndPt, FitTraj(), kAtKink, tca::TCConfig::kinkCuts, kNewStpCuts, kNoKinkChk, kRvPrp, kSlowing, kStiffEl, kStiffMu, tca::Trajectory::MCSMom, MCSMom(), MCSThetaRMS(), NumPtsWithCharge(), tca::Trajectory::PDGCode, PrintPos(), tca::Trajectory::Pts, tca::Trajectory::StopFlag, tca::Trajectory::Strategy, tcc, TrajPointSeparation(), and tca::TCConfig::useAlg.

Referenced by CheckHiMultUnusedHits(), and StepAway().

2843  {
2844  // Checks the last few points on the trajectory and returns with the number of
2845  // points (killPts) that should be killed (aka masked) at the end
2846  // tcc.kinkCuts
2847  // 0 = kink angle cut (radians)
2848  // 1 = kink angle significance cut
2849  // 2 = nPts fit at the end of the tj
2850  // Kink angle cut = tcc.kinkCuts[0] + tcc.kinkCuts[1] * MCSThetaRMS
2851 
2852  killPts = 0;
2853 
2854  // don't apply kink cuts if this looks a high energy electron
2855  if(tj.Strategy[kStiffEl] || tj.Strategy[kStiffMu]) return;
2856 
2857  // decide whether to turn kink checking back on
2858  if(tcc.kinkCuts[0] > 0 && tj.EndPt[1] == 20) {
2859  if(MCSMom(slc, tj, 10, 19) > 50) tj.AlgMod[kNoKinkChk] = false;
2860  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"GottaKink turn kink checking back on? "<<tj.AlgMod[kNoKinkChk]<<" with MCSMom "<<MCSMom(slc, tj, 10, 19);
2861  }
2862  if(tj.AlgMod[kNoKinkChk]) return;
2863 
2864  // we need at least 2 * kinkCuts[2] points with charge to find a kink
2865  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
2866  unsigned short nPtsFit = tcc.kinkCuts[2];
2867  // fit more points if this is a muon
2868  if(tcc.useAlg[kNewStpCuts] && tj.PDGCode == 13) nPtsFit += 2;
2869  if(npwc < 2 * nPtsFit) return;
2870  unsigned short lastPt = tj.EndPt[1];
2871  if(tj.Pts[lastPt].Chg == 0) return;
2872 
2873  // MCSThetaRMS is the scattering angle for the entire length of the trajectory. Convert
2874  // this to the scattering angle for one WSE unit
2875  float thetaRMS = MCSThetaRMS(slc, tj, tj.EndPt[0], tj.EndPt[1]) / sqrt(TrajPointSeparation(tj.Pts[tj.EndPt[0]], tj.Pts[lastPt]));
2876  float kinkAngCut = tcc.kinkCuts[0] + tcc.kinkCuts[1] * thetaRMS;
2877  // relax this a bit when doing RevProp
2878  if(tj.AlgMod[kRvPrp]) kinkAngCut *= 1.3;
2879 
2880  // modify for stopping tracks
2881  if(tj.Strategy[kSlowing]) {
2882  nPtsFit = 3;
2883  kinkAngCut *= 3;
2884  }
2885 
2886  // find the point where a kink is expected and fit the points after that point
2887  unsigned short kinkPt = 0;
2888  unsigned short cnt = 0;
2889  float endChg = 0;
2890  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
2891  unsigned short ipt = tj.EndPt[1] - ii - 1;
2892  // stay away from the starting points which may be skewed if this is a
2893  // stopping track
2894  if(ipt <= tj.EndPt[0] + 2) break;
2895  if(tj.Pts[ipt].Chg <= 0) continue;
2896  ++cnt;
2897  endChg += tj.Pts[ipt].Chg;
2898  if(cnt == nPtsFit) {
2899  kinkPt = ipt;
2900  break;
2901  }
2902  } // ii
2903  if(kinkPt == 0 || cnt == 0) return;
2904  // fit the last nPtsFit points
2905  unsigned short fitDir = -1;
2906  TrajPoint tpFit;
2907  FitTraj(slc, tj, lastPt, nPtsFit, fitDir, tpFit);
2908  float dang = std::abs(tj.Pts[kinkPt].Ang - tpFit.Ang);
2909  // Calculate the average charge of the last ~3 points
2910  endChg /= cnt;
2911  float err = tj.Pts[kinkPt].AngErr;
2912  if(tpFit.AngErr > err) err = tpFit.AngErr;
2913  if(tj.Strategy[kSlowing]) err *= 2;
2914  float kinkSig = dang / err;
2915  float endChgAsym = (endChg - tj.Pts[kinkPt].AveChg) / (endChg + tj.Pts[kinkPt].AveChg);
2916  if(tcc.dbgStp) {
2917  mf::LogVerbatim myprt("TC");
2918  myprt<<"GottaKink kinkPt "<<PrintPos(slc, tj.Pts[kinkPt]);
2919  myprt<<std::setprecision(3);
2920  myprt<<" Ang before "<<tj.Pts[kinkPt].Ang<<" Err "<<tj.Pts[kinkPt].AngErr;
2921  myprt<<" AveChg "<<(int)tj.Pts[kinkPt].AveChg;
2922  myprt<<" Ang after "<<tpFit.Ang<<" Err "<<tpFit.AngErr;
2923  myprt<<" endChg "<<endChg;
2924  myprt<<" dang "<<dang;
2925  myprt<<" kinkAngCut "<<kinkAngCut;
2926  myprt<<" kinkSig "<<kinkSig;
2927  myprt<<" endChgAsym "<<endChgAsym;
2928  } // dbgStp
2929 
2930  if(tcc.useAlg[kNewStpCuts] && npwc < 20) {
2931  // improvements(?) for short tjs where the kink angle is a bit low but the kink
2932  // angle significance is high
2933  bool foundKink = (dang > 0.8 * kinkAngCut && kinkSig > 5);
2934  if(tcc.dbgStp && foundKink) {
2935  } // debug
2936  if(foundKink) {
2937  killPts = nPtsFit;
2938  tj.StopFlag[1][kAtKink] = true;
2939  tj.AlgMod[kNewStpCuts] = true;
2940  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Found a short Tj kink";
2941  return;
2942  }
2943  } // kNewStpCuts and short tj
2944 
2945  if(tcc.useAlg[kNewStpCuts] && tj.PDGCode == 13 && dang > kinkAngCut) {
2946  // New muon cuts. There is probably a delta-ray at the end if there is a kink
2947  // that is not really large and the end charge is high - Not a kink.
2948  // chgAsym = 0.2 corresponds to an average charge after the kink points that is
2949  // 50% larger than the charge before the kink point
2950  if(dang < 2 * kinkAngCut && endChgAsym > 0.2) return;
2951  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Found a muon Tj kink. Calling it not-a-kink";
2952  killPts = nPtsFit;
2953  tj.StopFlag[1][kAtKink] = true;
2954  tj.AlgMod[kNewStpCuts] = true;
2955  return;
2956  } // kNewStpCuts and muon with a kink
2957 
2958  if(dang > kinkAngCut) {
2959  killPts = nPtsFit;
2960  tj.StopFlag[1][kAtKink] = true;
2961  }
2962 
2963  if(killPts > 0) {
2964  // See if we are tracking a low momentum particle in which case we should just
2965  // turn off kink checking
2966  if(tcc.useAlg[kNoKinkChk] && tj.EndPt[1] < 20) {
2967  // Find MCSMom if it hasn't been done
2968  if(tj.MCSMom < 0) tj.MCSMom = MCSMom(slc, tj);
2969  if(tj.MCSMom < 50) {
2970  killPts = 0;
2971  tj.StopFlag[1][kAtKink] = false;
2972  tj.AlgMod[kNoKinkChk] = true;
2973  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"GottaKink turning off kink checking. MCSMom "<<tj.MCSMom;
2974  }
2975  } // turn off kink check
2976  // Don't stop if the last few points had high charge pull and we are tracking a muon, but do mask off the hits
2977  if(killPts > 0 && tj.PDGCode == 13 && tj.Pts[lastPt].ChgPull > 2 && tj.Pts[lastPt-1].ChgPull > 2) tj.StopFlag[1][kAtKink] = false;
2978  // Don't keep stepping or mask off any TPs if we hit a kink while doing RevProp
2979  if(tj.AlgMod[kRvPrp]) killPts = 0;
2980  }
2981 
2982  if(tcc.dbgStp && tj.StopFlag[1][kAtKink]) mf::LogVerbatim("TC")<<"GottaKink killPts "<<killPts;
2983 // if(tcc.dbgStp) mf::LogVerbatim("TC")<<"GottaKink "<<kinkPt<<" Pos "<<PrintPos(slc, tj.Pts[kinkPt])<<" dang "<<std::fixed<<std::setprecision(2)<<dang<<" cut "<<kinkAngCut<<" tpFit chi "<<tpFit.FitChi<<" killPts "<<killPts<<" GottaKink? "<<tj.StopFlag[1][kAtKink]<<" MCSMom "<<tj.MCSMom<<" thetaRMS "<<thetaRMS;
2984 
2985  } // GottaKink
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< float > kinkCuts
kink angle, nPts fit, (alternate) kink angle significance
Definition: DataStructs.h:475
short MCSMom(TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2914
TCConfig tcc
Definition: DataStructs.cxx:6
float TrajPointSeparation(TrajPoint &tp1, TrajPoint &tp2)
Definition: Utils.cxx:2368
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
use the slowing-down strategy
Definition: DataStructs.h:420
void FitTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:753
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
float MCSThetaRMS(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:2984
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
use the stiff electron strategy
Definition: DataStructs.h:418
use the stiff muon strategy
Definition: DataStructs.h:419
bool tca::HasDuplicateHits ( TCSlice slc,
Trajectory const &  tj,
bool  prt 
)

Definition at line 2469 of file Utils.cxx.

References kAllHits, PrintHit(), PutTrajHitsInVector(), and tca::TCSlice::slHits.

Referenced by CheckTraj(), and MergeAndStore().

2470  {
2471  // returns true if a hit is associated with more than one TP
2472  auto tjHits = PutTrajHitsInVector(tj, kAllHits);
2473  for(unsigned short ii = 0; ii < tjHits.size() - 1; ++ii) {
2474  for(unsigned short jj = ii + 1; jj < tjHits.size(); ++jj) {
2475  if(tjHits[ii] == tjHits[jj]) {
2476  if(prt) mf::LogVerbatim("TC")<<"HDH: Hit "<<PrintHit(slc.slHits[ii])<<" is a duplicate "<<ii<<" "<<jj;
2477  return true;
2478  }
2479  } // jj
2480  } // ii
2481  return false;
2482  } // HasDuplicateHits
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< unsigned int > PutTrajHitsInVector(Trajectory const &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2416
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:5704
void tca::HiEndDelta ( TCSlice slc,
Trajectory tj 
)

Definition at line 2566 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::TrajPoint::Ang, tca::TrajPoint::AngErr, tca::TrajPoint::AngleCode, tca::TrajPoint::Chg, tca::TCConfig::dbgStp, tca::TrajPoint::Delta, tca::TrajPoint::DeltaRMS, tca::TrajPoint::Dir, tca::Trajectory::EndPt, tca::TrajPoint::FitChi, FitTraj(), tca::TrajPoint::HitPos, kBragg, kHED, kStiffEl, tca::Trajectory::MCSMom, tca::TrajPoint::NTPsFit, tca::Trajectory::Pass, PointTrajDOCA(), tca::TrajPoint::Pos, PrintTrajPoint(), tca::Trajectory::Pts, tca::Trajectory::StepDir, tca::Trajectory::StopFlag, tca::Trajectory::Strategy, tcc, and tca::TCConfig::useAlg.

Referenced by CheckTraj().

2567  {
2568  // Modify the trajectory at the end if there is a consistent increase in delta. It
2569  // is called from CheckTraj.
2570  // This needs to be done carefully...
2571 
2572  if(!tcc.useAlg[kHED]) return;
2573  if(tj.StopFlag[1][kBragg]) return;
2574  if(tj.Strategy[kStiffEl]) return;
2575  // Only consider long high momentum.
2576  if(tj.MCSMom < 100) return;
2577  if(tj.Pts.size() < 50) return;
2578 
2579  unsigned short ept = tj.EndPt[1];
2580 
2581  TrajPoint& lastTp = tj.Pts[ept];
2582 
2583  if(lastTp.AngleCode > 1) return;
2584  if(lastTp.FitChi < 1) return;
2585 
2586  unsigned short npts = USHRT_MAX;
2587  float lastDelta = lastTp.Delta;
2588  // check the last 20 points on the trajectory for a systematic increase in Delta and FitChi
2589  for(unsigned short ii = 1; ii < 20; ++ii) {
2590  unsigned short ipt = ept - ii;
2591  TrajPoint& tp = tj.Pts[ipt];
2592  if(tp.Chg == 0) continue;
2593  if(tp.FitChi < 1 || tp.Delta > lastDelta) {
2594  npts = ii;
2595  break;
2596  }
2597  lastDelta = tp.Delta;
2598  } // ii
2599 
2600  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"HED: last point FitChi "<<lastTp.FitChi<<" NTPsFit "<<lastTp.NTPsFit<<" new npts "<<npts;
2601 
2602  // something bad happened
2603  if(npts == USHRT_MAX) return;
2604  // The Tj end has some other problem
2605  if(npts < 4) return;
2606 
2607  // re-fit the end of the trajectory
2608  lastTp.NTPsFit = npts;
2609  FitTraj(slc, tj);
2610  if(tcc.dbgStp) PrintTrajPoint("HED", slc, ept, tj.StepDir, tj.Pass, lastTp);
2611  // update the last points
2612  for(unsigned short ii = 1; ii <= npts; ++ii) {
2613  unsigned short ipt = ept - ii;
2614  TrajPoint& tp = tj.Pts[ipt];
2615  if(tp.Chg == 0) continue;
2616  tp.Dir = tj.Pts[ept].Dir;
2617  tp.Ang = tj.Pts[ept].Ang;
2618  tp.AngErr = tj.Pts[ept].AngErr;
2619  tp.AngleCode = tj.Pts[ept].AngleCode;
2620  // Correct the projected time to the wire
2621  float dw = tp.Pos[0] - tj.Pts[ept].Pos[0];
2622  if(tp.Dir[0] != 0) tp.Pos[1] = tj.Pts[ept].Pos[1] + dw * tp.Dir[1] / tp.Dir[0];
2623  tp.Delta = PointTrajDOCA(slc, tp.HitPos[0], tp.HitPos[1], tp);
2624  tp.DeltaRMS = tj.Pts[ept].DeltaRMS;
2625  tp.NTPsFit = tj.Pts[ept].NTPsFit;
2626  tp.FitChi = tj.Pts[ept].FitChi;
2627  if(tcc.dbgStp) PrintTrajPoint("HED", slc, ipt, tj.StepDir, tj.Pass, tp);
2628  } // ii
2629 
2630  tj.AlgMod[kHED] = true;
2631 
2632  } // HiEndDelta
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
void FitTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:753
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
use the stiff electron strategy
Definition: DataStructs.h:418
void PrintTrajPoint(std::string someText, TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, TrajPoint const &tp)
Definition: Utils.cxx:5541
float tca::HitSep2 ( TCSlice slc,
unsigned int  iht,
unsigned int  jht 
)

Definition at line 2239 of file Utils.cxx.

References tca::TCEvent::allHits, evt, tca::TCSlice::slHits, tcc, and tca::TCConfig::unitsPerTick.

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

2240  {
2241  // returns the separation^2 between two hits in WSE units
2242  if(iht > slc.slHits.size()-1 || jht > slc.slHits.size()-1) return 1E6;
2243  auto& ihit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2244  auto& jhit = (*evt.allHits)[slc.slHits[jht].allHitsIndex];
2245  float dw = (float)ihit.WireID().Wire - (float)jhit.WireID().Wire;
2246  float dt = (ihit.PeakTime() - jhit.PeakTime()) * tcc.unitsPerTick;
2247  return dw * dw + dt * dt;
2248  } // HitSep2
TCConfig tcc
Definition: DataStructs.cxx:6
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
float tca::HitsPosTick ( TCSlice slc,
const std::vector< unsigned int > &  hitsInMultiplet,
float &  sum,
HitStatus_t  hitRequest 
)

Definition at line 3742 of file Utils.cxx.

References tca::TCEvent::allHits, evt, kAllHits, kUnusedHits, kUsedHits, and tca::TCSlice::slHits.

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

3743  {
3744  // returns the position and the charge
3745  float pos = 0;
3746  sum = 0;
3747  for(unsigned short ii = 0; ii < hitsInMultiplet.size(); ++ii) {
3748  unsigned int iht = hitsInMultiplet[ii];
3749  bool useit = (hitRequest == kAllHits);
3750  if(hitRequest == kUsedHits && slc.slHits[iht].InTraj > 0) useit = true;
3751  if(hitRequest == kUnusedHits && slc.slHits[iht].InTraj == 0) useit = true;
3752  if(!useit) continue;
3753  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
3754  float chg = hit.Integral();
3755  pos += chg * hit.PeakTime();
3756  sum += chg;
3757  } // ii
3758  if(sum == 0) return 0;
3759  return pos / sum;
3760  } // HitsPosTick
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
float tca::HitsPosTime ( TCSlice slc,
const std::vector< unsigned int > &  hitsInMultiplet,
float &  sum,
HitStatus_t  hitRequest 
)

Definition at line 3736 of file Utils.cxx.

References HitsPosTick(), tcc, and tca::TCConfig::unitsPerTick.

Referenced by DotProd().

3737  {
3738  return tcc.unitsPerTick * HitsPosTick(slc, hitsInMultiplet, sum, hitRequest);
3739  } // HitsPosTime
TCConfig tcc
Definition: DataStructs.cxx:6
float HitsPosTick(TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, float &sum, HitStatus_t hitRequest)
Definition: Utils.cxx:3742
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
float tca::HitsRMSTick ( TCSlice slc,
const std::vector< unsigned int > &  hitsInMultiplet,
HitStatus_t  hitRequest 
)

Definition at line 3706 of file Utils.cxx.

References tca::TCEvent::allHits, evt, kAllHits, kUnusedHits, kUsedHits, and tca::TCSlice::slHits.

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

3707  {
3708  if(hitsInMultiplet.empty()) return 0;
3709 
3710  if(hitsInMultiplet.size() == 1) {
3711  auto& hit = (*evt.allHits)[slc.slHits[hitsInMultiplet[0]].allHitsIndex];
3712  return hit.RMS();
3713  }
3714 
3715  float minVal = 9999;
3716  float maxVal = 0;
3717  for(unsigned short ii = 0; ii < hitsInMultiplet.size(); ++ii) {
3718  unsigned int iht = hitsInMultiplet[ii];
3719  bool useit = (hitRequest == kAllHits);
3720  if(hitRequest == kUsedHits && slc.slHits[iht].InTraj > 0) useit = true;
3721  if(hitRequest == kUnusedHits && slc.slHits[iht].InTraj == 0) useit = true;
3722  if(!useit) continue;
3723  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
3724  float cv = hit.PeakTime();
3725  float rms = hit.RMS();
3726  float arg = cv - rms;
3727  if(arg < minVal) minVal = arg;
3728  arg = cv + rms;
3729  if(arg > maxVal) maxVal = arg;
3730  } // ii
3731  if(maxVal == 0) return 0;
3732  return (maxVal - minVal) / 2;
3733  } // HitsRMSTick
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
float tca::HitsRMSTime ( TCSlice slc,
const std::vector< unsigned int > &  hitsInMultiplet,
HitStatus_t  hitRequest 
)

Definition at line 3700 of file Utils.cxx.

References HitsRMSTick(), tcc, and tca::TCConfig::unitsPerTick.

Referenced by DotProd(), and HitsTimeErr2().

3701  {
3702  return tcc.unitsPerTick * HitsRMSTick(slc, hitsInMultiplet, hitRequest);
3703  } // HitsRMSTick
float HitsRMSTick(TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
Definition: Utils.cxx:3706
TCConfig tcc
Definition: DataStructs.cxx:6
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
float tca::HitsTimeErr2 ( TCSlice slc,
const std::vector< unsigned int > &  hitVec 
)

Definition at line 1701 of file StepUtils.cxx.

References tca::TCConfig::hitErrFac, HitsRMSTime(), kUnusedHits, and tcc.

Referenced by DefineHitPos().

1702  {
1703  // Estimates the error^2 of the time using all hits in hitVec
1704  if(hitVec.empty()) return 0;
1705  float err = tcc.hitErrFac * HitsRMSTime(slc, hitVec, kUnusedHits);
1706  return err * err;
1707  } // HitsTimeErr2
float HitsRMSTime(TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
Definition: Utils.cxx:3700
TCConfig tcc
Definition: DataStructs.cxx:6
float tca::HitTimeErr ( TCSlice slc,
unsigned int  iht 
)

Definition at line 1693 of file StepUtils.cxx.

References tca::TCEvent::allHits, evt, tca::TCConfig::hitErrFac, tca::TCSlice::slHits, tcc, and tca::TCConfig::unitsPerTick.

Referenced by DefineHitPos(), and FindUseHits().

1694  {
1695  if(iht > slc.slHits.size() - 1) return 0;
1696  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1697  return hit.RMS() * tcc.unitsPerTick * tcc.hitErrFac * hit.Multiplicity();
1698  } // HitTimeErr
TCConfig tcc
Definition: DataStructs.cxx:6
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
double tca::InShowerProb ( double  showerEnergy,
double  along,
double  trans 
)
float tca::InShowerProb ( TCSlice slc,
const ShowerStruct3D ss3,
const PFPStruct pfp 
)

Definition at line 2103 of file TCShower.cxx.

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

2104  {
2105  // returns a likelihood (0 - 1) that the pfp particle belongs in shower ss3
2106 
2107  if(ss3.ID == 0 || pfp.ID == 0) return 0;
2108  float sum = 0;
2109  float cnt = 0;
2110  for(auto cid : ss3.CotIDs) {
2111  auto& ss = slc.cots[cid - 1];
2112  if(ss.ID == 0) continue;
2113  for(auto tid : pfp.TjIDs) {
2114  auto& tj = slc.tjs[tid - 1];
2115  if(tj.CTP != ss.CTP) continue;
2116 // std::cout<<"3S"<<ss3.ID<<" P"<<pfp.ID<<" ";
2117  sum += InShowerProb(slc, ss, tj);
2118  ++cnt;
2119  } // tid
2120  } //cid
2121  if(cnt == 0) return 0;
2122  return sum / cnt;
2123 
2124  } // InShowerProb
Float_t ss
Definition: plot.C:23
float InShowerProb(TCSlice &slc, const ShowerStruct &ss, const Trajectory &tj)
Definition: TCShower.cxx:2127
float tca::InShowerProb ( TCSlice slc,
const ShowerStruct ss,
const Trajectory tj 
)

Definition at line 2127 of file TCShower.cxx.

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

Referenced by InShowerProb(), and Reconcile3D().

2128  {
2129  // returns a likelihood (0 - 1) that the tj particle belongs in shower ss
2130  // Keep it simple: construct a FOM, take the inverse and limit it to the range 0 - 1
2131  if(ss.ID == 0 || tj.ID == 0) return 0;
2132  if(ss.CTP != tj.CTP) return 0;
2133 
2134  auto& stj = slc.tjs[ss.ShowerTjID - 1];
2135  if(stj.Pts.size() != 3) return 0;
2136  unsigned short closePt1, closePt2;
2137  float doca = 1E6;
2138  TrajTrajDOCA(slc, stj, tj, closePt1, closePt2, doca);
2139  if(doca == 1E6) return 0;
2140  float showerLen = PosSep(stj.Pts[0].Pos, stj.Pts[2].Pos);
2141  // make a rough separation cut. Return a small but non-zero value
2142  if(doca > 5 * showerLen) return 0.01;
2143  auto& stp = stj.Pts[closePt1];
2144  if(stp.DeltaRMS == 0) return 0;
2145  auto& ttp = tj.Pts[closePt2];
2146  Point2_t alongTrans;
2147  FindAlongTrans(stp.Pos, stp.Dir, ttp.Pos, alongTrans);
2148 // std::cout<<"ISP: 2S"<<ss.ID<<" T"<<tj.ID<<" showerLen "<<(int)showerLen<<" closePt "<<closePt1;
2149 // std::cout<<" closePt "<<closePt2<<" along "<<std::fixed<<std::setprecision(1)<<alongTrans[0]<<" "<<alongTrans[1];
2150  float rms = stp.DeltaRMS;
2151  if(rms < 1) rms = 1;
2152  float arg = alongTrans[1] / rms;
2153  float radProb = exp(-0.5 * arg * arg);
2154 // std::cout<<" rms "<<rms<<" radProb "<<std::setprecision(3)<<radProb;
2155  // This is a fake but may be OK if this function is called before the shower is well-defined
2156  rms = showerLen;
2157  arg = alongTrans[0] / rms;
2158  float longProb = exp(-0.5 * arg * arg);
2159 // std::cout<<" longProb "<<std::setprecision(3)<<longProb;
2160  float costh = std::abs(DotProd(stp.Dir, ttp.Dir));
2161 // std::cout<<" costh "<<std::setprecision(3)<<costh;
2162  float prob = radProb * longProb * costh;
2163 // std::cout<<" InShowerProb "<<std::setprecision(3)<<prob<<"\n";
2164  return prob;
2165 
2166  } // InShowerProb
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:2849
Float_t ss
Definition: plot.C:23
bool TrajTrajDOCA(TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2175
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:59
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
double tca::InShowerProbLong ( double  showerEnergy,
double  along 
)

Definition at line 2049 of file TCShower.cxx.

References ShowerParams().

Referenced by FindParent(), InShowerProbParam(), MergeSubShowers(), and ParentFOM().

2050  {
2051  // Returns the likelihood that the point at position along (cm) is inside an EM shower
2052  // having showerEnergy (MeV). The variable along is relative to shower max.
2053 
2054  if(showerEnergy < 10) return 0;
2055 
2056  double shMaxAlong, shE95Along;
2057  ShowerParams(showerEnergy, shMaxAlong, shE95Along);
2058  // 50% of the shower energy is deposited between 0 < shMaxAlong < 1, which should be obvious considering
2059  // that is the definition of the shower max, so the probability should be ~1 at shMaxAlong = 1.
2060  // The Geant study shows that 95% of the energy is contained within 2.5 * shMax and has a small dependence
2061  // on the shower energy, which is modeled in ShowerParams. This function uses a
2062  // sigmoid likelihood function is constructed with these constraints using the scaling variable tau
2063  double tau = (along + shMaxAlong) / shMaxAlong;
2064  if(tau < -1 || tau > 4) return 0;
2065 
2066  double tauHalf, width;
2067  if(tau > 0) {
2068  tauHalf = 1.7;
2069  width = 0.35;
2070  } else {
2071  // Allow for some uncertainty in the shower start position
2072  tau = -tau;
2073  tauHalf = 0.2;
2074  width = 0.1;
2075  }
2076 
2077  double prob = 1 / (1 + exp((tau - tauHalf)/width));
2078  return prob;
2079 
2080  } // InShowrProbLong
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
Definition: TCShower.cxx:2015
double tca::InShowerProbParam ( double  showerEnergy,
double  along,
double  trans 
)

Definition at line 2097 of file TCShower.cxx.

References InShowerProbLong(), and InShowerProbTrans().

2098  {
2099  return InShowerProbLong(showerEnergy, along) * InShowerProbTrans(showerEnergy, along, trans);
2100  } // InShowerProbParam
double InShowerProbLong(double showerEnergy, double along)
Definition: TCShower.cxx:2049
double InShowerProbTrans(double showerEnergy, double along, double trans)
Definition: TCShower.cxx:2083
double tca::InShowerProbTrans ( double  showerEnergy,
double  along,
double  trans 
)

Definition at line 2083 of file TCShower.cxx.

References ShowerParamTransRMS().

Referenced by InShowerProbParam(), and MergeSubShowers().

2084  {
2085  // Returns the likelihood that the point, (along, trans) (cm), is inside an EM shower having energy showerEnergy (MeV)
2086  // where along is relative to the shower start position and trans is the radial distance.
2087 
2088  if(showerEnergy < 10) return 0;
2089  double rms = ShowerParamTransRMS(showerEnergy, along);
2090  trans = std::abs(trans);
2091  double prob = exp(-0.5 * trans / rms);
2092  return prob;
2093 
2094  } // InShowerProbTrans
double ShowerParamTransRMS(double showerEnergy, double along)
Definition: TCShower.cxx:2035
bool tca::InsideFV ( TCSlice slc,
PFPStruct pfp,
unsigned short  end 
)

Definition at line 2810 of file PFPUtils.cxx.

References evd::details::end(), tca::PFPStruct::ID, tca::TCSlice::xHi, tca::TCSlice::xLo, tca::PFPStruct::XYZ, tca::TCSlice::yHi, tca::TCSlice::yLo, tca::TCSlice::zHi, and tca::TCSlice::zLo.

Referenced by DotProd(), PrintP(), and StitchPFPs().

2811  {
2812  // returns true if the end of the pfp is inside the fiducial volume of the TPC
2813  if(pfp.ID <= 0) return false;
2814  if(end > 1) return false;
2815 
2816  float abit = 5;
2817  auto& pos1 = pfp.XYZ[end];
2818  return (pos1[0] > slc.xLo + abit && pos1[0] < slc.xHi - abit &&
2819  pos1[1] > slc.yLo + abit && pos1[1] < slc.yHi - abit &&
2820  pos1[2] > slc.zLo + abit && pos1[2] < slc.zHi - abit);
2821 
2822  } // InsideFV
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool tca::InsideTPC ( const Point3_t pos,
geo::TPCID inTPCID 
)

Definition at line 2825 of file PFPUtils.cxx.

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

Referenced by DotProd(), and PrintPFP().

2826  {
2827  // determine which TPC this point is in. This function returns false
2828  // if the point is not inside any TPC
2829  float abit = 5;
2830  for (const geo::TPCID& tpcid: tcc.geom->IterateTPCIDs()) {
2831  const geo::TPCGeo& TPC = tcc.geom->TPC(tpcid);
2832  double local[3] = {0.,0.,0.};
2833  double world[3] = {0.,0.,0.};
2834  TPC.LocalToWorld(local,world);
2835  // reduce the active area of the TPC by a bit to be consistent with FillWireHitRange
2836  if(pos[0] < world[0]-tcc.geom->DetHalfWidth(tpcid) + abit) continue;
2837  if(pos[0] > world[0]+tcc.geom->DetHalfWidth(tpcid) - abit) continue;
2838  if(pos[1] < world[1]-tcc.geom->DetHalfHeight(tpcid) + abit) continue;
2839  if(pos[1] > world[1]+tcc.geom->DetHalfHeight(tpcid) - abit) continue;
2840  if(pos[2] < world[2]-tcc.geom->DetLength(tpcid)/2 + abit) continue;
2841  if(pos[2] > world[2]+tcc.geom->DetLength(tpcid)/2 - abit) continue;
2842  inTPCID = tpcid;
2843  return true;
2844  } // tpcid
2845  return false;
2846  } // InsideTPC
geo::Length_t DetHalfWidth(geo::TPCID const &tpcid) const
Returns the half width of the active volume of the specified TPC.
TCConfig tcc
Definition: DataStructs.cxx:6
Geometry information for a single TPC.
Definition: TPCGeo.h:37
IteratorBox< TPC_id_iterator,&GeometryCore::begin_TPC_id,&GeometryCore::end_TPC_id > IterateTPCIDs() const
Enables ranged-for loops on all TPC IDs of the detector.
geo::Length_t DetHalfHeight(geo::TPCID const &tpcid) const
Returns the half height of the active volume of the specified TPC.
geo::Length_t DetLength(geo::TPCID const &tpcid) const
Returns the length of the active volume of the specified TPC.
const geo::GeometryCore * geom
Definition: DataStructs.h:493
The data type to uniquely identify a TPC.
Definition: geo_types.h:195
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
void LocalToWorld(const double *tpc, double *world) const
Transform point from local TPC frame to world frame.
Definition: TPCGeo.h:490
bool tca::InTrajOK ( TCSlice slc,
std::string  someText 
)

Definition at line 1333 of file Utils.cxx.

References AlgBitNames, evd::details::end(), kKilled, kUsedHits, PrintHit(), PrintTrajectory(), PutTrajHitsInVector(), tca::TCSlice::slHits, tca::TCSlice::tjs, and tca::TCSlice::vtxs.

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

1334  {
1335  // Check slc.tjs -> InTraj associations
1336 
1337  unsigned short tID;
1338  unsigned int iht;
1339  unsigned short itj = 0;
1340  std::vector<unsigned int> tHits;
1341  std::vector<unsigned int> atHits;
1342  for(auto& tj : slc.tjs) {
1343  // ignore abandoned trajectories
1344  if(tj.AlgMod[kKilled]) continue;
1345  tID = tj.ID;
1346  if(tj.AlgMod[kKilled]) {
1347  std::cout<<someText<<" ChkInTraj hit size mis-match in tj ID "<<tj.ID<<" AlgBitNames";
1348  for(unsigned short ib = 0; ib < AlgBitNames.size(); ++ib) if(tj.AlgMod[ib]) std::cout<<" "<<AlgBitNames[ib];
1349  std::cout<<"\n";
1350  continue;
1351  }
1352  tHits = PutTrajHitsInVector(tj, kUsedHits);
1353  if(tHits.size() < 2) {
1354  std::cout<<someText<<" ChkInTraj: Insufficient hits in traj "<<tj.ID<<"\n";
1355  PrintTrajectory("CIT", slc, tj, USHRT_MAX);
1356  continue;
1357  }
1358  std::sort(tHits.begin(), tHits.end());
1359  atHits.clear();
1360  for(iht = 0; iht < slc.slHits.size(); ++iht) {
1361  if(slc.slHits[iht].InTraj == tID) atHits.push_back(iht);
1362  } // iht
1363  if(atHits.size() < 2) {
1364  std::cout<<someText<<" ChkInTraj: Insufficient hits in atHits in traj "<<tj.ID<<" Killing it\n";
1365  tj.AlgMod[kKilled] = true;
1366  continue;
1367  }
1368  if(!std::equal(tHits.begin(), tHits.end(), atHits.begin())) {
1369  mf::LogVerbatim myprt("TC");
1370  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";
1371  myprt<<"AlgMods: ";
1372  for(unsigned short ib = 0; ib < AlgBitNames.size(); ++ib) if(tj.AlgMod[ib]) myprt<<" "<<AlgBitNames[ib];
1373  myprt<<"\n";
1374  myprt<<"index inTraj UseHit \n";
1375  for(iht = 0; iht < atHits.size(); ++iht) {
1376  myprt<<"iht "<<iht<<" "<<PrintHit(slc.slHits[atHits[iht]]);
1377  if(iht < tHits.size()) myprt<<" "<<PrintHit(slc.slHits[tHits[iht]]);
1378  if(atHits[iht] != tHits[iht]) myprt<<" <<< "<<atHits[iht]<<" != "<<tHits[iht];
1379  myprt<<"\n";
1380  } // iht
1381  if(tHits.size() > atHits.size()) {
1382  for(iht = atHits.size(); iht < atHits.size(); ++iht) {
1383  myprt<<"atHits "<<iht<<" "<<PrintHit(slc.slHits[atHits[iht]])<<"\n";
1384  } // iht
1385  PrintTrajectory("CIT", slc, tj, USHRT_MAX);
1386  } // tHit.size > atHits.size()
1387  return false;
1388  }
1389  // check the VtxID
1390  for(unsigned short end = 0; end < 2; ++end) {
1391  if(tj.VtxID[end] > slc.vtxs.size()) {
1392  mf::LogVerbatim("TC")<<someText<<" ChkInTraj: Bad VtxID "<<tj.ID;
1393  std::cout<<someText<<" ChkInTraj: Bad VtxID "<<tj.ID<<" vtx size "<<slc.vtxs.size()<<"\n";
1394  tj.AlgMod[kKilled] = true;
1395  PrintTrajectory("CIT", slc, tj, USHRT_MAX);
1396  return false;
1397  }
1398  } // end
1399  ++itj;
1400  } // tj
1401  return true;
1402 
1403  } // InTrajOK
void PrintTrajectory(std::string someText, TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:5455
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
const std::vector< std::string > AlgBitNames
Definition: DataStructs.cxx:13
std::vector< unsigned int > PutTrajHitsInVector(Trajectory const &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2416
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:5704
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
unsigned short tca::IsCloseToVertex ( TCSlice slc,
VtxStore inVx2 
)

Definition at line 3297 of file TCVertex.cxx.

References tca::VtxStore::CTP, tcc, VertexVertexPull(), tca::TCConfig::vtx2DCuts, and tca::TCSlice::vtxs.

Referenced by Find2DVertices().

3298  {
3299  // Returns the ID of a 2D vertex having the minimum pull < user-specified cut
3300 
3301  float minPull = tcc.vtx2DCuts[3];
3302  unsigned short imBest = 0;
3303  for(auto& vx2 : slc.vtxs) {
3304  if(vx2.CTP != inVx2.CTP) continue;
3305  if(vx2.ID <= 0) continue;
3306  float pull = VertexVertexPull(slc, inVx2, vx2);
3307  if(pull < minPull) {
3308  minPull = pull;
3309  imBest = vx2.ID;
3310  }
3311  } // vx2
3312  return imBest;
3313  } // IsCloseToVertex
TCConfig tcc
Definition: DataStructs.cxx:6
float VertexVertexPull(TCSlice &slc, const VtxStore &vx1, const VtxStore &vx2)
Definition: TCVertex.cxx:2080
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:466
unsigned short tca::IsCloseToVertex ( TCSlice slc,
Vtx3Store vx3 
)

Definition at line 3316 of file TCVertex.cxx.

References tcc, VertexVertexPull(), tca::TCConfig::vtx3DCuts, tca::TCSlice::vtx3s, and tca::Vtx3Store::X.

3317  {
3318  // Returns the ID of a 3D vertex having the minimum pull < user-specified cut
3319 
3320  float minPull = tcc.vtx3DCuts[1];
3321  unsigned short imBest = 0;
3322  for(auto& oldvx3 : slc.vtx3s) {
3323  if(oldvx3.ID == 0) continue;
3324  if(std::abs(oldvx3.X - vx3.X) > tcc.vtx3DCuts[0]) continue;
3325  float pull = VertexVertexPull(slc, vx3, oldvx3);
3326  if(pull < minPull) {
3327  minPull = pull;
3328  imBest = oldvx3.ID;
3329  }
3330  } // oldvx3
3331  return imBest;
3332 
3333  } // IsCloseToVertex
std::vector< float > vtx3DCuts
2D vtx -> 3D vtx matching cuts
Definition: DataStructs.h:467
TCConfig tcc
Definition: DataStructs.cxx:6
float VertexVertexPull(TCSlice &slc, const VtxStore &vx1, const VtxStore &vx2)
Definition: TCVertex.cxx:2080
bool tca::IsGhost ( TCSlice slc,
Trajectory tj 
)

Definition at line 3221 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::TCConfig::dbgStp, tca::Trajectory::EndPt, tca::Trajectory::ID, tca::Trajectory::IsGood, kKilled, kStiffEl, kUseGhostHits, tca::Trajectory::MCSMom, MCSMom(), tca::TCConfig::minPts, MoveTPToWire(), tca::Trajectory::Pass, tca::Trajectory::PDGCode, tca::TrajPoint::Pos, PrintTrajectory(), tca::Trajectory::Pts, tca::TCConfig::qualityCuts, SetEndPoints(), tca::TCSlice::slHits, tca::Trajectory::Strategy, tcc, tca::TCSlice::tjs, TrimEndPts(), UnsetUsedHits(), and tca::TCConfig::useAlg.

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

3222  {
3223  // Sees if trajectory tj shares many hits with another trajectory and if so merges them.
3224 
3225  if(!tcc.useAlg[kUseGhostHits]) return false;
3226  // ensure that tj is not a saved trajectory
3227  if(tj.ID > 0) return true;
3228  // or an already killed trajectory
3229  if(tj.AlgMod[kKilled]) return true;
3230  if(tj.Pts.size() < 3) return false;
3231  if(tj.Strategy[kStiffEl]) return false;
3232 
3233  // vectors of traj IDs, and the occurrence count
3234  std::vector<int> tID;
3235  std::vector<unsigned short> tCnt;
3236 
3237  unsigned short hitCnt = 0;
3238  unsigned short nAvailable = 0;
3239  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
3240  for(unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
3241  // ignore hits used by this trajectory
3242  if(tj.Pts[ipt].UseHit[ii]) {
3243  ++hitCnt;
3244  continue;
3245  }
3246  unsigned int iht = tj.Pts[ipt].Hits[ii];
3247  if(slc.slHits[iht].InTraj > 0 && (unsigned int)slc.slHits[iht].InTraj <= slc.tjs.size()) {
3248  int tjid = slc.slHits[iht].InTraj;
3249  unsigned short indx;
3250  for(indx = 0; indx < tID.size(); ++indx) if(tID[indx] == tjid) break;
3251  if(indx == tID.size()) {
3252  tID.push_back(tjid);
3253  tCnt.push_back(1);
3254  } else {
3255  ++tCnt[indx];
3256  }
3257  } else {
3258  ++nAvailable;
3259  }
3260  } // ii
3261  } // ipt
3262 
3263  // Call it a ghost if > 1/3 of the hits are used by another trajectory
3264  hitCnt /= 3;
3265  int oldTjID = INT_MAX;
3266 
3267  if(tcc.dbgStp) {
3268  mf::LogVerbatim myprt("TC");
3269  myprt<<"IsGhost tj hits size cut "<<hitCnt<<" tID_tCnt";
3270  for(unsigned short ii = 0; ii < tCnt.size(); ++ii) myprt<<" "<<tID[ii]<<"_"<<tCnt[ii];
3271  myprt<<"\nAvailable hits "<<nAvailable;
3272  } // prt
3273 
3274  for(unsigned short ii = 0; ii < tCnt.size(); ++ii) {
3275  if(tCnt[ii] > hitCnt) {
3276  oldTjID = tID[ii];
3277  hitCnt = tCnt[ii];
3278  }
3279  } // ii
3280  if(oldTjID == INT_MAX) return false;
3281  int oldTjIndex = oldTjID - 1;
3282 
3283  // See if this looks like a short delta-ray on a long muon
3284  Trajectory& oTj = slc.tjs[oldTjIndex];
3285  if(oTj.PDGCode == 13 && hitCnt < 0.1 * oTj.Pts.size()) return false;
3286 
3287  // See if there are gaps in this trajectory indicating that it is really a ghost and not
3288  // just a crossing trajectory
3289  // find the range of wires spanned by oTj
3290  int wire0 = INT_MAX;
3291  int wire1 = 0;
3292  for(auto& otp : oTj.Pts) {
3293  int wire = std::nearbyint(otp.Pos[0]);
3294  if(wire < wire0) wire0 = wire;
3295  if(wire > wire1) wire1 = wire;
3296  } // tp
3297 
3298  int nwires = wire1 - wire0 + 1;
3299  std::vector<float> oTjPos1(nwires, -1);
3300  unsigned short nMissedWires = 0;
3301  for(unsigned short ipt = oTj.EndPt[0]; ipt <= oTj.EndPt[1]; ++ipt) {
3302  if(oTj.Pts[ipt].Chg == 0) continue;
3303  int wire = std::nearbyint(oTj.Pts[ipt].Pos[0]);
3304  int indx = wire - wire0;
3305  if(indx < 0 || indx > nwires - 1) continue;
3306  oTjPos1[indx] = oTj.Pts[ipt].Pos[1];
3307  ++nMissedWires;
3308  } // ipt
3309  // count the number of ghost TPs
3310  unsigned short ngh = 0;
3311  // and the number with Delta > 0 relative to oTj
3312  unsigned short nghPlus = 0;
3313  // keep track of the first point and last point appearance of oTj
3314  unsigned short firstPtInoTj = USHRT_MAX;
3315  unsigned short lastPtInoTj = 0;
3316  TrajPoint tp = tj.Pts[tj.EndPt[0]];
3317  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
3318  if(tj.Pts[ipt].Chg > 0) {
3319  tp = tj.Pts[ipt];
3320  continue;
3321  }
3322  int wire = std::nearbyint(tj.Pts[ipt].Pos[0]);
3323  int indx = wire - wire0;
3324  if(indx < 0 || indx > nwires - 1) continue;
3325  if(oTjPos1[indx] > 0) {
3326  // ensure that the hits in this tp are used in oTj
3327  bool HitInoTj = false;
3328  for(unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
3329  unsigned int iht = tj.Pts[ipt].Hits[ii];
3330  if(slc.slHits[iht].InTraj == oldTjID) HitInoTj = true;
3331  } // ii
3332  if(HitInoTj) {
3333  ++ngh;
3334  MoveTPToWire(tp, tj.Pts[ipt].Pos[0]);
3335  if(tp.Pos[1] > oTjPos1[indx]) ++nghPlus;
3336  if(firstPtInoTj == USHRT_MAX) firstPtInoTj = ipt;
3337  lastPtInoTj = ipt;
3338  }
3339  } // oTjHasChg[indx]
3340  } // ipt
3341 
3342  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Number of missed wires in oTj gaps "<<nMissedWires<<" Number of ghost hits in these gaps "<<ngh<<" nghPlus "<<nghPlus<<" cut "<<0.2 * nMissedWires;
3343 
3344  if(ngh < 0.2 * nMissedWires) return false;
3345  if(firstPtInoTj > lastPtInoTj) return false;
3346 
3347  // require all of the tj TPs to be on either the + or - side of the oTj trajectory
3348  if(!(nghPlus > 0.8 * ngh || nghPlus < 0.2 * ngh) ) return false;
3349 
3350  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Trajectory is a ghost of "<<oldTjID<<" first point in oTj "<<firstPtInoTj<<" last point "<<lastPtInoTj;
3351 
3352  // unset all of the shared hits
3353  for(unsigned short ipt = firstPtInoTj; ipt <= lastPtInoTj; ++ipt) {
3354  if(tj.Pts[ipt].Chg == 0) continue;
3355  UnsetUsedHits(slc, tj.Pts[ipt]);
3356  if(tcc.dbgStp) PrintTrajectory("IG", slc, tj, ipt);
3357  }
3358  // see how many points are left at the end
3359  ngh = 0;
3360  for(unsigned short ipt = lastPtInoTj; ipt <= tj.Pts.size(); ++ipt) {
3361  if(tj.Pts[ipt].Chg > 0) ++ngh;
3362  } // ipt
3363  // clobber those too?
3364  if(ngh > 0 && ngh < tcc.minPts[tj.Pass]) {
3365  for(unsigned short ipt = lastPtInoTj; ipt <= tj.EndPt[1]; ++ipt) {
3366  if(tj.Pts[ipt].Chg > 0) UnsetUsedHits(slc, tj.Pts[ipt]);
3367  } // ipt
3368  }
3369  SetEndPoints(tj);
3370  tj.Pts.resize(tj.EndPt[1] + 1);
3371  slc.tjs[oldTjIndex].AlgMod[kUseGhostHits] = true;
3372  TrimEndPts("IG", slc, tj, tcc.qualityCuts, tcc.dbgStp);
3373  if(tj.AlgMod[kKilled]) {
3374  tj.IsGood = false;
3375  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Failed quality cuts";
3376  return true;
3377  }
3378  tj.MCSMom = MCSMom(slc, tj);
3379  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" New tj size "<<tj.Pts.size();
3380  return true;
3381 
3382  } // IsGhost
void PrintTrajectory(std::string someText, TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:5455
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
short MCSMom(TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2914
std::vector< float > qualityCuts
Min points/wire, min consecutive pts after a gap.
Definition: DataStructs.h:479
TCConfig tcc
Definition: DataStructs.cxx:6
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1162
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
std::vector< unsigned short > minPts
min number of Pts required to make a trajectory
Definition: DataStructs.h:483
void TrimEndPts(std::string fcnLabel, TCSlice &slc, Trajectory &tj, const std::vector< float > &fQualityCuts, bool prt)
Definition: Utils.cxx:1511
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
use the stiff electron strategy
Definition: DataStructs.h:418
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2485
bool tca::IsGhost ( TCSlice slc,
std::vector< unsigned int > &  tHits 
)

Definition at line 3385 of file StepUtils.cxx.

References tca::TCConfig::dbgAlg, tca::TCConfig::dbgStp, GetHitMultiplet(), kUseGhostHits, tca::TCSlice::slHits, tcc, tca::TCSlice::tjs, and tca::TCConfig::useAlg.

Referenced by CheckTraj().

3386  {
3387  // Called by FindJunkTraj to see if the passed hits are close to an existing
3388  // trajectory and if so, they will be used in that other trajectory
3389 
3390  if(!tcc.useAlg[kUseGhostHits]) return false;
3391 
3392  if(tHits.size() < 2) return false;
3393 
3394  bool prt = (tcc.dbgStp || tcc.dbgAlg[kUseGhostHits]);
3395 
3396  // find all nearby hits
3397  std::vector<unsigned int> hitsInMuliplet, nearbyHits;
3398  for(auto iht : tHits) {
3399  GetHitMultiplet(slc, iht, hitsInMuliplet);
3400  // prevent double counting
3401  for(auto mht : hitsInMuliplet) {
3402  if(std::find(nearbyHits.begin(), nearbyHits.end(), mht) == nearbyHits.end()) {
3403  nearbyHits.push_back(mht);
3404  }
3405  } // mht
3406  } // iht
3407 
3408  // vectors of traj IDs, and the occurrence count
3409  std::vector<unsigned int> tID, tCnt;
3410  for(auto iht : nearbyHits) {
3411  if(slc.slHits[iht].InTraj <= 0) continue;
3412  unsigned int tid = slc.slHits[iht].InTraj;
3413  unsigned short indx = 0;
3414  for(indx = 0; indx < tID.size(); ++indx) if(tID[indx] == tid) break;
3415  if(indx == tID.size()) {
3416  tID.push_back(tid);
3417  tCnt.push_back(1);
3418  } else {
3419  ++tCnt[indx];
3420  }
3421  } // iht
3422  if(tCnt.empty()) return false;
3423 
3424  // Call it a ghost if > 50% of the hits are used by another trajectory
3425  unsigned short tCut = 0.5 * tHits.size();
3426  int tid = INT_MAX;
3427 
3428  if(prt) {
3429  mf::LogVerbatim myprt("TC");
3430  myprt<<"IsGhost tHits size "<<tHits.size()<<" cut fraction "<<tCut<<" tID_tCnt";
3431  for(unsigned short ii = 0; ii < tCnt.size(); ++ii) myprt<<" "<<tID[ii]<<"_"<<tCnt[ii];
3432  } // prt
3433 
3434  for(unsigned short ii = 0; ii < tCnt.size(); ++ii) {
3435  if(tCnt[ii] > tCut) {
3436  tid = tID[ii];
3437  break;
3438  }
3439  } // ii
3440  if(tid > (int)slc.tjs.size()) return false;
3441 
3442  if(prt) mf::LogVerbatim("TC")<<" is ghost of trajectory "<<tid;
3443 
3444  // Use all hits in tHits that are found in itj
3445  for(auto& tp : slc.tjs[tid - 1].Pts) {
3446  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3447  unsigned int iht = tp.Hits[ii];
3448  if(slc.slHits[iht].InTraj != 0) continue;
3449  for(unsigned short jj = 0; jj < tHits.size(); ++jj) {
3450  unsigned int tht = tHits[jj];
3451  if(tht != iht) continue;
3452  tp.UseHit[ii] = true;
3453  slc.slHits[iht].InTraj = tid;
3454  break;
3455  } // jj
3456  } // ii
3457  } // tp
3458  slc.tjs[tid - 1].AlgMod[kUseGhostHits] = true;
3459  return true;
3460 
3461  } // IsGhost
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:505
void GetHitMultiplet(TCSlice &slc, unsigned int theHit, std::vector< unsigned int > &hitsInMultiplet, unsigned short &localIndex)
Definition: StepUtils.cxx:1580
bool tca::IsShowerLike ( TCSlice slc,
const std::vector< int >  TjIDs 
)

Definition at line 2002 of file TCShower.cxx.

References kShowerLike, and tca::TCSlice::tjs.

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

2003  {
2004  // Vote for the list of Tjs (assumed associated with a PFParticle) being shower-like
2005  if(TjIDs.empty()) return false;
2006  unsigned short cnt = 0;
2007  for(auto tid : TjIDs) {
2008  if(tid <= 0 || tid > (int)slc.tjs.size()) continue;
2009  if(slc.tjs[tid - 1].AlgMod[kShowerLike] > 0) ++cnt;
2010  } // tjid
2011  return (cnt > 1);
2012  } // IsInShower
void tca::KillPoorVertices ( TCSlice slc)

Definition at line 2418 of file TCVertex.cxx.

References MakeVertexObsolete(), tcc, tca::TCConfig::vtx2DCuts, tca::TCSlice::vtx3s, and tca::TCSlice::vtxs.

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

2419  {
2420  // kill 2D vertices that have low score and are not attached to a high-score 3D vertex
2421  if(slc.vtxs.empty()) return;
2422  for(auto& vx : slc.vtxs) {
2423  if(vx.ID == 0) continue;
2424  if(vx.Score > tcc.vtx2DCuts[7]) continue;
2425  if(vx.Vx3ID > 0) {
2426  auto& vx3 = slc.vtx3s[vx.Vx3ID - 1];
2427  if(vx3.Primary) continue;
2428  if(slc.vtx3s[vx.Vx3ID - 1].Score >= tcc.vtx2DCuts[7]) continue;
2429  }
2430  MakeVertexObsolete("KPV", slc, vx, false);
2431  } // vx
2432 
2433  } // KillPoorVertices
bool MakeVertexObsolete(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:3208
TCConfig tcc
Definition: DataStructs.cxx:6
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:466
void tca::KillVerticesInShower ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct ss,
bool  prt 
)

Definition at line 702 of file TCShower.cxx.

References tca::ShowerStruct::CTP, tca::TCSlice::dontCluster, tca::ShowerStruct::Envelope, GetAssns(), tca::ShowerStruct::ID, tca::TCSlice::ID, kKillInShowerVx, MakeVertexObsolete(), PointInsideEnvelope(), tcc, tca::TCSlice::tjs, tca::TCConfig::useAlg, tca::TCSlice::vtx3s, and tca::TCSlice::vtxs.

Referenced by MergeShowersAndStore().

703  {
704  // make the vertices inside the shower envelope obsolete and update dontCluster
705  if(ss.ID == 0) return;
706  if(!tcc.useAlg[kKillInShowerVx]) return;
707  std::string fcnLabel = inFcnLabel + ".KVIS";
708 
709  for(auto& vx2 : slc.vtxs) {
710  if(vx2.ID == 0) continue;
711  if(vx2.CTP != ss.CTP) continue;
712  // ensure it isn't associated with a neutrino vertex
713  if(vx2.Vx3ID > 0 && slc.vtx3s[vx2.Vx3ID - 1].Neutrino) continue;
714  if(!PointInsideEnvelope(vx2.Pos, ss.Envelope)) continue;
715  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Clobber 2V"<<vx2.ID<<" -> 3V"<<vx2.Vx3ID<<" inside 2S"<<ss.ID;
716  // update dontCluster
717  for(auto& dc : slc.dontCluster) {
718  if(dc.TjIDs[0] == 0) continue;
719  if(dc.Vx2ID != vx2.ID) continue;
720  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Remove T"<<dc.TjIDs[0]<<"-T"<<dc.TjIDs[0]<<" in dontCluster";
721  dc.TjIDs[0] = 0;
722  dc.TjIDs[1] = 0;
723  } // dc
724  if(vx2.Vx3ID > 0) {
725  auto TIn3V = GetAssns(slc, "3V", vx2.Vx3ID, "T");
726  for(auto tid : TIn3V) slc.tjs[tid - 1].AlgMod[kKillInShowerVx] = true;
727  auto& vx3 = slc.vtx3s[vx2.Vx3ID - 1];
728  MakeVertexObsolete(slc, vx3);
729  } else {
730  auto TIn2V = GetAssns(slc, "2V", vx2.ID, "T");
731  for(auto tid : TIn2V) slc.tjs[tid - 1].AlgMod[kKillInShowerVx] = true;
732  MakeVertexObsolete("KVIS", slc, vx2, true);
733  }
734  } // vx2
735 
736  } // KillVerticesInShower
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:3120
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4279
TCConfig tcc
Definition: DataStructs.cxx:6
Float_t ss
Definition: plot.C:23
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:2781
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
double tca::KinkAngle ( TCSlice slc,
const std::vector< TrajPoint3 > &  tp3s,
unsigned short  atPt,
double  sep 
)

Definition at line 1943 of file PFPUtils.cxx.

References DeltaAngle(), and PosSep2().

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

1944  {
1945  // calculate a kink angle at the TjPt
1946  if(tp3s.empty()) return -1;
1947  if(atPt < 1 || atPt > tp3s.size() - 2) return -1;
1948  double sep2 = sep * sep;
1949  unsigned short pt1 = USHRT_MAX;
1950  for(unsigned short ii = 1; ii < tp3s.size(); ++ii) {
1951  unsigned short ipt = atPt - ii;
1952  if(PosSep2(tp3s[atPt].Pos, tp3s[ipt].Pos) > sep2) {
1953  pt1 = ipt;
1954  break;
1955  }
1956  if(ipt == 0) break;
1957  } // ii
1958  if(pt1 == USHRT_MAX) return -1;
1959  unsigned short pt2 = USHRT_MAX;
1960  for(unsigned short ii = 1; ii < tp3s.size(); ++ii) {
1961  unsigned short ipt = atPt + ii;
1962  if(ipt == tp3s.size()) break;
1963  if(PosSep2(tp3s[atPt].Pos, tp3s[ipt].Pos) > sep2) {
1964  pt2 = ipt;
1965  break;
1966  }
1967  } // ii
1968  if(pt2 == USHRT_MAX) return -1;
1969  return DeltaAngle(tp3s[pt1].Dir, tp3s[pt2].Dir);
1970  } // KinkAngle
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1636
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1660
float tca::LengthInCTP ( TCSlice slc,
std::vector< int > &  tjids,
CTP_t  inCTP 
)

Definition at line 1135 of file PFPUtils.cxx.

References PosSep2(), and tca::TCSlice::tjs.

1136  {
1137  // Calculates the maximum length between the end points of Tjs in the list of tjids in inCTP
1138  if(tjids.empty()) return 0;
1139  // put the end point positions into a vector
1140  std::vector<Point2_t> endPos;
1141  for(auto tjid : tjids) {
1142  auto& tj = slc.tjs[tjid - 1];
1143  if(tj.CTP != inCTP) continue;
1144  endPos.push_back(tj.Pts[tj.EndPt[0]].Pos);
1145  endPos.push_back(tj.Pts[tj.EndPt[1]].Pos);
1146  } // tjid
1147  if(endPos.size() < 2) return 0;
1148  float extent = 0;
1149  for(unsigned short pt1 = 0; pt1 < endPos.size() - 1; ++pt1) {
1150  for(unsigned short pt2 = pt1 + 1; pt2 < endPos.size(); ++pt2) {
1151  float sep = PosSep2(endPos[pt1], endPos[pt2]);
1152  if(sep > extent) extent = sep;
1153  } // pt2
1154  } // pt1
1155  return sqrt(extent);
1156  } // LengthInCTP
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1660
bool tca::LineLineIntersect ( Point3_t  p1,
Point3_t  p2,
Point3_t  p3,
Point3_t  p4,
Point3_t intersect,
float &  doca 
)

Definition at line 2879 of file PFPUtils.cxx.

References min, and PosSep().

Referenced by DotProd(), and PointDirIntersect().

2880  {
2881  /*
2882  Calculate the line segment PaPb that is the shortest route between
2883  two lines P1P2 and P3P4. Calculate also the values of mua and mub where
2884  Pa = P1 + mua (P2 - P1)
2885  Pb = P3 + mub (P4 - P3)
2886  Return FALSE if no solution exists.
2887  http://paulbourke.net/geometry/pointlineplane/
2888  */
2889 
2890  Point3_t p13, p43, p21;
2891  double d1343,d4321,d1321,d4343,d2121;
2892  double numer,denom;
2893  constexpr double EPS = std::numeric_limits<double>::min();
2894 
2895  p13[0] = p1[0] - p3[0];
2896  p13[1] = p1[1] - p3[1];
2897  p13[2] = p1[2] - p3[2];
2898  p43[0] = p4[0] - p3[0];
2899  p43[1] = p4[1] - p3[1];
2900  p43[2] = p4[2] - p3[2];
2901  if (std::abs(p43[0]) < EPS && std::abs(p43[1]) < EPS && std::abs(p43[2]) < EPS) return(false);
2902  p21[0] = p2[0] - p1[0];
2903  p21[1] = p2[1] - p1[1];
2904  p21[2] = p2[2] - p1[2];
2905  if (std::abs(p21[0]) < EPS && std::abs(p21[1]) < EPS && std::abs(p21[2]) < EPS) return(false);
2906 
2907  d1343 = p13[0] * p43[0] + p13[1] * p43[1] + p13[2] * p43[2];
2908  d4321 = p43[0] * p21[0] + p43[1] * p21[1] + p43[2] * p21[2];
2909  d1321 = p13[0] * p21[0] + p13[1] * p21[1] + p13[2] * p21[2];
2910  d4343 = p43[0] * p43[0] + p43[1] * p43[1] + p43[2] * p43[2];
2911  d2121 = p21[0] * p21[0] + p21[1] * p21[1] + p21[2] * p21[2];
2912 
2913  denom = d2121 * d4343 - d4321 * d4321;
2914  if (std::abs(denom) < EPS) return(false);
2915  numer = d1343 * d4321 - d1321 * d4343;
2916 
2917  double mua = numer / denom;
2918  double mub = (d1343 + d4321 * mua) / d4343;
2919 
2920  intersect[0] = p1[0] + mua * p21[0];
2921  intersect[1] = p1[1] + mua * p21[1];
2922  intersect[2] = p1[2] + mua * p21[2];
2923  Point3_t pb;
2924  pb[0] = p3[0] + mub * p43[0];
2925  pb[1] = p3[1] + mub * p43[1];
2926  pb[2] = p3[2] + mub * p43[2];
2927  doca = PosSep(intersect, pb);
2928  // average the closest points
2929  for(unsigned short xyz = 0; xyz < 3; ++xyz) intersect[xyz] += pb[xyz];
2930  for(unsigned short xyz = 0; xyz < 3; ++xyz) intersect[xyz] /= 2;
2931  return true;
2932  } // 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:1654
bool tca::LongPulseHit ( const recob::Hit hit)

Definition at line 3936 of file Utils.cxx.

References recob::Hit::GoodnessOfFit(), and recob::Hit::Multiplicity().

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

3937  {
3938  // return true if the hit is in a long pulse indicating that it's position
3939  // and charge are not well known
3940  return ((hit.GoodnessOfFit() < 0 || hit.GoodnessOfFit() > 50) && hit.Multiplicity() > 5);
3941  }
float GoodnessOfFit() const
Degrees of freedom in the determination of the hit signal shape (-1 by default)
Definition: Hit.h:229
short int Multiplicity() const
How many hits could this one be shared with.
Definition: Hit.h:227
TrajPoint tca::MakeBareTP ( TCSlice slc,
Point3_t pos,
Vector3_t dir,
CTP_t  inCTP 
)

Definition at line 3523 of file Utils.cxx.

References tca::TrajPoint::Ang, detinfo::DetectorProperties::ConvertXToTicks(), tca::TrajPoint::CTP, DecodeCTP(), tca::TrajPoint::Delta, tca::TCConfig::detprop, tca::TrajPoint::Dir, tca::TCConfig::geom, tca::TCConfig::maxPos0, norm, geo::PlaneID::Plane, tca::TrajPoint::Pos, tcc, tca::TCConfig::unitsPerTick, and geo::GeometryCore::WireCoordinate().

Referenced by DotProd(), FindMissedTjsInTp3s(), FindParent(), FindPFParticles(), FindShowerStart(), Print3S(), PrintShowers(), and SetParent().

3524  {
3525  // Projects the space point defined by pos and dir into the CTP and returns it in the form of a trajectory point.
3526  // The TP Pos[0] is set to a negative number if the point has an invalid wire position but doesn't return an
3527  // error if the position is on a dead wire. The projection of the direction vector in CTP is stored in tp.Delta.
3528  TrajPoint tp;
3529  tp.Pos = {{0,0}};
3530  tp.Dir = {{0,1}};
3531  tp.CTP = inCTP;
3532  geo::PlaneID planeID = DecodeCTP(inCTP);
3533 
3534  tp.Pos[0] = tcc.geom->WireCoordinate(pos[1], pos[2], planeID);
3535  if(tp.Pos[0] < 0 || (!tcc.maxPos0.empty() && tp.Pos[0] > tcc.maxPos0[planeID.Plane])) {
3536  tp.Pos[0] = -1;
3537  return tp;
3538  }
3539  tp.Pos[1] = tcc.detprop->ConvertXToTicks(pos[0], planeID) * tcc.unitsPerTick;
3540 
3541  // now find the direction if dir is defined
3542  if(dir[0] == 0 && dir[1] == 0 && dir[2] == 0) return tp;
3543  // Make a point at the origin and one 100 units away
3544  // BUG the double brace syntax is required to work around clang bug 21629
3545  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
3546  Point3_t ori3 = {{0.0, 0.0, 0.0}};
3547  Point3_t pos3 = {{100 * dir[0], 100 * dir[1], 100 * dir[2]}};
3548  // 2D position of ori3 and the pos3 projection
3549  std::array<double, 2> ori2;
3550  std::array<double, 2> pos2;
3551  std::array<double, 2> dir2;
3552  // the wire coordinates
3553  ori2[0] = tcc.geom->WireCoordinate(ori3[1], ori3[2], planeID);
3554  pos2[0] = tcc.geom->WireCoordinate(pos3[1], pos3[2], planeID);
3555  // the time coordinates
3556  ori2[1] = tcc.detprop->ConvertXToTicks(ori3[0], planeID) * tcc.unitsPerTick;
3557  pos2[1] = tcc.detprop->ConvertXToTicks(pos3[0], planeID) * tcc.unitsPerTick;
3558 
3559  dir2[0] = pos2[0] - ori2[0];
3560  dir2[1] = pos2[1] - ori2[1];
3561 
3562  double norm = sqrt(dir2[0] * dir2[0] + dir2[1] * dir2[1]);
3563  tp.Dir[0] = dir2[0] / norm;
3564  tp.Dir[1] = dir2[1] / norm;
3565  tp.Ang = atan2(dir2[1], dir2[0]);
3566  tp.Delta = norm / 100;
3567 
3568  // The Orth vectors are not unit normalized so we need to correct for this
3569  double w0 = tcc.geom->WireCoordinate(0, 0, planeID);
3570  // cosine-like component
3571  double cs = tcc.geom->WireCoordinate(1, 0, planeID) - w0;
3572  // sine-like component
3573  double sn = tcc.geom->WireCoordinate(0, 1, planeID) - w0;
3574  norm = sqrt(cs * cs + sn * sn);
3575  tp.Delta /= norm;
3576 
3577  return tp;
3578  } // MakeBareTP
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
std::vector< float > maxPos0
Definition: DataStructs.h:489
std::array< double, 3 > Point3_t
Definition: DataStructs.h:35
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
const detinfo::DetectorProperties * detprop
Definition: DataStructs.h:494
const geo::GeometryCore * geom
Definition: DataStructs.h:493
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)
bool tca::MakeBareTrajPoint ( TCSlice slc,
unsigned int  fromHit,
unsigned int  toHit,
TrajPoint tp 
)

Definition at line 3581 of file Utils.cxx.

References tca::TCEvent::allHits, EncodeCTP(), evt, MakeBareTrajPoint(), and tca::TCSlice::slHits.

Referenced by DotProd(), EndMerge(), FillGaps(), MergeShowerChain(), and ParentFOM().

3582  {
3583  if(fromHit > slc.slHits.size() - 1) return false;
3584  if(toHit > slc.slHits.size() - 1) return false;
3585  auto& fhit = (*evt.allHits)[slc.slHits[fromHit].allHitsIndex];
3586  auto& thit = (*evt.allHits)[slc.slHits[toHit].allHitsIndex];
3587  CTP_t tCTP = EncodeCTP(fhit.WireID());
3588  return MakeBareTrajPoint(slc, (float)fhit.WireID().Wire, fhit.PeakTime(),
3589  (float)thit.WireID().Wire, thit.PeakTime(), tCTP, tp);
3590 
3591  } // MakeBareTrajPoint
unsigned int CTP_t
Definition: DataStructs.h:41
bool MakeBareTrajPoint(TCSlice &slc, const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
Definition: Utils.cxx:3628
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
TCEvent evt
Definition: DataStructs.cxx:5
bool tca::MakeBareTrajPoint ( TCSlice slc,
float  fromWire,
float  fromTick,
float  toWire,
float  toTick,
CTP_t  tCTP,
TrajPoint tp 
)

Definition at line 3594 of file Utils.cxx.

References tca::TrajPoint::Ang, tca::TrajPoint::CTP, tca::TrajPoint::Dir, norm, tca::TrajPoint::Pos, tcc, and tca::TCConfig::unitsPerTick.

3595  {
3596  tp.CTP = tCTP;
3597  tp.Pos[0] = fromWire;
3598  tp.Pos[1] = tcc.unitsPerTick * fromTick;
3599  tp.Dir[0] = toWire - fromWire;
3600  tp.Dir[1] = tcc.unitsPerTick * (toTick - fromTick);
3601  double norm = sqrt(tp.Dir[0] * tp.Dir[0] + tp.Dir[1] * tp.Dir[1]);
3602  if(norm == 0) return false;
3603  tp.Dir[0] /= norm;
3604  tp.Dir[1] /= norm;
3605  tp.Ang = atan2(tp.Dir[1], tp.Dir[0]);
3606  return true;
3607  } // MakeBareTrajPoint
TCConfig tcc
Definition: DataStructs.cxx:6
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
Float_t norm
bool tca::MakeBareTrajPoint ( const Point2_t fromPos,
const Point2_t toPos,
TrajPoint tpOut 
)

Definition at line 3610 of file Utils.cxx.

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

3611  {
3612  tpOut.Pos = fromPos;
3613  tpOut.Dir = PointDirection(fromPos, toPos);
3614 /*
3615  tpOut.Dir[0] = toPos[0] - fromPos[0];
3616  tpOut.Dir[1] = toPos[1] - fromPos[1];
3617  double norm = sqrt(tpOut.Dir[0] * tpOut.Dir[0] + tpOut.Dir[1] * tpOut.Dir[1]);
3618  if(norm == 0) return false;
3619  tpOut.Dir[0] /= norm;
3620  tpOut.Dir[1] /= norm;
3621 */
3622  tpOut.Ang = atan2(tpOut.Dir[1], tpOut.Dir[0]);
3623  return true;
3624 
3625  } // MakeBareTrajPoint
Vector2_t PointDirection(const Point2_t p1, const Point2_t p2)
Definition: Utils.cxx:3655
bool tca::MakeBareTrajPoint ( TCSlice slc,
const TrajPoint tpIn1,
const TrajPoint tpIn2,
TrajPoint tpOut 
)

Definition at line 3628 of file Utils.cxx.

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

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

3629  {
3630  tpOut.CTP = tpIn1.CTP;
3631  tpOut.Pos = tpIn1.Pos;
3632  tpOut.Dir = PointDirection(tpIn1.Pos, tpIn2.Pos);
3633 /*
3634  tpOut.Dir[0] = tpIn2.Pos[0] - tpIn1.Pos[0];
3635  tpOut.Dir[1] = tpIn2.Pos[1] - tpIn1.Pos[1];
3636  double norm = sqrt(tpOut.Dir[0] * tpOut.Dir[0] + tpOut.Dir[1] * tpOut.Dir[1]);
3637  if(norm == 0) return false;
3638  tpOut.Dir[0] /= norm;
3639  tpOut.Dir[1] /= norm;
3640 */
3641  tpOut.Ang = atan2(tpOut.Dir[1], tpOut.Dir[0]);
3642  return true;
3643  } // MakeBareTrajPoint
Vector2_t PointDirection(const Point2_t p1, const Point2_t p2)
Definition: Utils.cxx:3655
void tca::MakeHaloTj ( TCSlice slc,
Trajectory muTj,
bool  prt 
)

Definition at line 20 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::ChgRMS, tca::Trajectory::CTP, DefineHitPos(), tca::Trajectory::EndPt, evt, FindCloseHits(), GetPFPIndex(), GetSliceIndex(), tca::TCEvent::globalTjID, tca::Trajectory::ID, tca::TCSlice::ID, kAllHits, kDeltaRay, kHaloTj, kKilled, kMat3D, MakeTrajectoryObsolete(), tca::TCConfig::muonTag, tca::Trajectory::ParentID, tca::Trajectory::Pass, tca::Trajectory::PDGCode, tca::TCSlice::pfps, PointTrajDOCA(), PrintTrajectory(), tca::Trajectory::Pts, tca::TCSlice::slHits, slices, tca::Trajectory::StartEnd, tca::Trajectory::StepDir, tcc, tca::TCSlice::tjs, tca::Trajectory::TotChg, tca::Trajectory::UID, tca::TCConfig::useAlg, and tca::Trajectory::WorkID.

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

21  {
22  // Creates a "halo trajectory" around a muon tj consisting of hits and trajectories
23  // that are within MuonTag[4] distance. The halo tj is a virtual clone of muTj in the
24  // sense that it has the same number of points and the same start and end points.
25 
26  if(tcc.muonTag.size() < 5) return;
27  if(tcc.muonTag[4] <= 0) return;
28  if(!tcc.useAlg[kHaloTj]) return;
29 
30  if(muTj.PDGCode != 13) return;
31 
32  // check for daughter delta-rays
33  std::vector<int> dtrs;
34  for(auto& dtj : slc.tjs) {
35  if(dtj.AlgMod[kKilled]) continue;
36  if(dtj.ParentID != muTj.ID) continue;
37  dtrs.push_back(dtj.ID);
38  if(!dtj.AlgMod[kDeltaRay]) continue;
39  if(prt) std::cout<<"MakeHaloTj: Killing delta-ray T"<<dtj.ID<<"\n";
40  // Kill a delta-ray PFParticle?
41  if(dtj.AlgMod[kMat3D]) {
42  unsigned short pfpIndex = GetPFPIndex(slc, dtj.ID);
43  if(pfpIndex == USHRT_MAX) {
44  if(prt) std::cout<<" No PFP found for 3D-matched delta-ray\n";
45  } else {
46  auto& pfp = slc.pfps[pfpIndex];
47  if(prt) std::cout<<" Killing delta-ray PFParticle P"<<pfp.UID<<"\n";
48  pfp.ID = 0;
49  // correct the parent -> daughter assn
50  if(pfp.ParentUID > 0) {
51  auto parentIndx = GetSliceIndex("P", pfp.ParentUID);
52  if(parentIndx.first != USHRT_MAX) {
53  auto& parent = slices[parentIndx.first].pfps[parentIndx.second];
54  std::vector<int> newDtrUIDs;
55  for(auto uid : parent.DtrUIDs) if(uid != dtj.UID) newDtrUIDs.push_back(uid);
56  parent.DtrUIDs = newDtrUIDs;
57  } // parent found
58  } // correct the parent
59  } // kill PFParticle
60  } // kill
61  MakeTrajectoryObsolete(slc, (unsigned int)(dtj.ID - 1));
62  } // dtj
63 
64  // make a copy
65  Trajectory tj;
66  tj.CTP = muTj.CTP;
67  // We can't use StoreTraj so variables need to be defined here
68  tj.ID = slc.tjs.size() + 1;
69  tj.WorkID = muTj.WorkID;
70  // increment the global ID
71  ++evt.globalTjID;
72  tj.UID = evt.globalTjID;
73  tj.PDGCode = 11;
74  tj.Pass = muTj.Pass;
75  tj.StepDir = muTj.StepDir;
76  tj.StartEnd = muTj.StartEnd;
77  tj.TotChg = 0;
78  tj.ChgRMS = 0;
79  tj.EndPt[0] = 0;
80  tj.ParentID = muTj.ID;
81  tj.AlgMod.reset();
82  tj.AlgMod[kHaloTj] = true;
83  // start a list of tjs that have points near the muon
84  std::vector<int> closeTjs;
85  for(unsigned short ipt = muTj.EndPt[0]; ipt <= muTj.EndPt[1]; ++ipt) {
86  auto tp = muTj.Pts[ipt];
87  tp.Hits.resize(0);
88  tp.UseHit.reset();
89  tp.Chg = 0; tp.AveChg = 0; tp.ChgPull = 0;
90  tp.Delta = 0; tp.DeltaRMS = 0;
91  tp.FitChi = 0; tp.NTPsFit = 0;
92  float window = tcc.muonTag[4];
93  if(tp.Dir[0] != 0) window *= std::abs(1/tp.Dir[0]);
94  if(!FindCloseHits(slc, tp, window, kAllHits)) continue;
95  // add unused hits to the point and look for close tjs
96  bool hitsAdded = false;
97  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
98  unsigned int iht = tp.Hits[ii];
99  auto inTraj = slc.slHits[iht].InTraj;
100  if(inTraj < 0) continue;
101  if(inTraj == 0) {
102  tp.UseHit[ii] = true;
103  slc.slHits[iht].InTraj = tj.ID;
104  hitsAdded = true;
105  } else {
106  // add to the closeTjs list
107  if(inTraj != muTj.ID && std::find(closeTjs.begin(), closeTjs.end(), inTraj) == closeTjs.end()) closeTjs.push_back(inTraj);
108  }
109  } // ii
110  if(hitsAdded) {
111  DefineHitPos(slc, tp);
112  tp.Delta = PointTrajDOCA(slc, tp.HitPos[0], tp.HitPos[1], tp);
113  tj.TotChg += tp.Chg;
114  tj.Pts.push_back(tp);
115  } // hitsAdded
116  } // ipt
117  if(tj.Pts.empty()) return;
118  tj.EndPt[1] = tj.Pts.size() - 1;
119  if(prt) {
120  std::cout<<"MHTj: T"<<muTj.ID<<" npts "<<tj.Pts.size()<<" close";
121  for(auto tid : closeTjs) std::cout<<" T"<<tid;
122  std::cout<<"\n";
123  PrintTrajectory("DM", slc, tj, USHRT_MAX);
124  }
125  slc.tjs.push_back(tj);
126  } // MakeHaloTj
void PrintTrajectory(std::string someText, TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:5455
TCConfig tcc
Definition: DataStructs.cxx:6
float PointTrajDOCA(TCSlice &slc, float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2280
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1840
unsigned short GetPFPIndex(TCSlice &slc, int tjID)
Definition: Utils.cxx:1127
void MakeTrajectoryObsolete(TCSlice &slc, unsigned int itj)
Definition: Utils.cxx:1922
std::vector< TCSlice > slices
Definition: DataStructs.cxx:10
bool FindCloseHits(TCSlice &slc, TrajPoint &tp, float const &maxDelta, HitStatus_t hitRequest)
Definition: Utils.cxx:2552
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
std::vector< short > muonTag
min length and min MCSMom for a muon tag
Definition: DataStructs.h:471
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:4496
TCEvent evt
Definition: DataStructs.cxx:5
void tca::MakeJunkTjVertices ( TCSlice slc,
const CTP_t inCTP 
)
bool tca::MakeJunkTraj ( TCSlice slc,
std::vector< unsigned int >  tHits 
)

Definition at line 4223 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::TCEvent::allHits, tca::Trajectory::CTP, tca::TCConfig::dbgAlg, tca::TCConfig::dbgStp, DefineHitPos(), evt, Fit2D(), tca::Trajectory::IsGood, kJunkTj, tca::TCConfig::minPts, PrintTrajectory(), tca::Trajectory::Pts, ReleaseHits(), SetAngleCode(), SetEndPoints(), tca::TCSlice::slHits, StartTraj(), StoreTraj(), tcc, tca::TCConfig::unitsPerTick, tca::TCConfig::useAlg, and valsDecreasing().

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

4224  {
4225  if(!tcc.useAlg[kJunkTj]) return false;
4226  // Make a crummy trajectory using the provided hits
4227 
4228  if(tHits.size() < 2) return false;
4229 
4230  bool prt = (tcc.dbgStp || tcc.dbgAlg[kJunkTj]);
4231 
4232  // Start the trajectory using the first and last hits to
4233  // define a starting direction. Use the last pass settings
4234  Trajectory work;
4235  unsigned short pass = tcc.minPts.size() - 1;
4236  if(!StartTraj(slc, work, tHits[0], tHits[tHits.size()-1], pass)) return false;
4237  // make a TP for every hit
4238  work.Pts.resize(tHits.size());
4239  // fit all of the hits to a line
4240  Point2_t inPt;
4241  Vector2_t outVec, outVecErr;
4242  float inPtErr = 1, chiDOF;
4243  // initialize
4244  Fit2D(0, inPt, inPtErr, outVec, outVecErr, chiDOF);
4245  std::vector<Point2_t> fitPts(tHits.size());
4246  for(unsigned short ii = 0; ii < tHits.size(); ++ii) {
4247  unsigned int iht = tHits[ii];
4248  if(slc.slHits[iht].InTraj == SHRT_MAX) return false;
4249  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
4250  inPt[0] = hit.WireID().Wire;
4251  inPt[1] = hit.PeakTime() * tcc.unitsPerTick;
4252  fitPts[ii] = inPt;
4253  // accumulate. Don't store the points since we don't care about chisq
4254  Fit2D(1, inPt, inPtErr, outVec, outVecErr, chiDOF);
4255  } // ii
4256  if(!Fit2D(-1, inPt, inPtErr, outVec, outVecErr, chiDOF)) return false;
4257 
4258  if(prt) mf::LogVerbatim("TC")<<" tHits line fit Angle "<<atan(outVec[1]);
4259  // A rough estimate of the trajectory angle
4260  work.Pts[0].Ang = atan(outVec[1]);
4261  work.Pts[0].Dir[0] = cos(work.Pts[0].Ang);
4262  work.Pts[0].Dir[1] = sin(work.Pts[0].Ang);
4263  SetAngleCode(work.Pts[0]);
4264  // clone this information for all of the other points
4265  for(unsigned short ipt = 1; ipt < work.Pts.size(); ++ipt) {
4266  auto& tp = work.Pts[ipt];
4267  tp.CTP = work.CTP;
4268  tp.Ang = work.Pts[0].Ang;
4269  tp.Dir = work.Pts[0].Dir;
4270  tp.AngleCode = work.Pts[0].AngleCode;
4271  } // ipt
4272  // Rotate the hits into this coordinate system to find the start and end
4273  // points and general direction
4274  double cs = cos(-work.Pts[0].Ang);
4275  double sn = sin(-work.Pts[0].Ang);
4276  float tAlong, minAlong = 1E6, maxAlong = -1E6;
4277  // sort the hits by the distance along the general direction
4278  std::vector<SortEntry> sortVec(tHits.size());
4279  SortEntry sortEntry;
4280  for(unsigned short ii = 0; ii < fitPts.size(); ++ii) {
4281  tAlong = cs * fitPts[ii][0] - sn * fitPts[ii][1];
4282  if(tAlong < minAlong) minAlong = tAlong;
4283  if(tAlong > maxAlong) maxAlong = tAlong;
4284  sortEntry.index = ii;
4285  sortEntry.val = tAlong;
4286  sortVec[ii] = sortEntry;
4287  } // ii
4288  std::sort(sortVec.begin(), sortVec.end(), valsDecreasing);
4289  // put a hit into each TP
4290  for(unsigned short ipt = 0; ipt < work.Pts.size(); ++ipt) {
4291  auto& tp = work.Pts[ipt];
4292  tp.Hits.resize(1);
4293  tp.Hits[0] = tHits[sortVec[ipt].index];
4294  tp.UseHit[0] = true;
4295  DefineHitPos(slc, tp);
4296  // Just use the hit position as the tj position
4297  tp.Pos = tp.HitPos;
4298  } // ipt
4299  SetEndPoints(work);
4300  work.AlgMod[kJunkTj] = true;
4301  work.IsGood = true;
4302  if(prt) {
4303  PrintTrajectory("MJT", slc, work, USHRT_MAX);
4304  }
4305  // Finally push it onto slc.tjs
4306  if(!StoreTraj(slc, work)) {
4307  ReleaseHits(slc, work);
4308  return false;
4309  }
4310  return true;
4311  } // MakeJunkTraj
void PrintTrajectory(std::string someText, TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:5455
void ReleaseHits(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:1150
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
bool valsDecreasing(SortEntry c1, SortEntry c2)
Definition: StepUtils.cxx:9
TCConfig tcc
Definition: DataStructs.cxx:6
bool StoreTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:1175
void SetAngleCode(TrajPoint &tp)
Definition: Utils.cxx:722
bool StartTraj(TCSlice &slc, Trajectory &tj, unsigned int fromhit, unsigned int tohit, unsigned short pass)
Definition: Utils.cxx:4431
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1840
bool Fit2D(short mode, Point2_t inPt, float &inPtErr, Vector2_t &outVec, Vector2_t &outVecErr, float &chiDOF)
Definition: Utils.cxx:4536
std::vector< unsigned short > minPts
min number of Pts required to make a trajectory
Definition: DataStructs.h:483
std::array< double, 2 > Vector2_t
Definition: DataStructs.h:38
Detector simulation of raw signals on wires.
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:505
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
void tca::MakeJunkVertices ( TCSlice slc,
const CTP_t inCTP 
)

Definition at line 14 of file TCVertex.cxx.

References close(), tca::VtxStore::CTP, tca::TCConfig::dbgSlc, tca::TCConfig::dbgVxJunk, DecodeCTP(), FindCloseTjs(), tca::VtxStore::ID, kFixed, kHaloTj, kJunkTj, kJunkVx, kKilled, kShowerLike, geo::PlaneID::Plane, tca::VtxStore::Pos, tca::VtxStore::PosErr, PosSep(), tca::VtxStore::Score, SignalBetween(), tca::VtxStore::Stat, StoreVertex(), tcc, tca::TCSlice::tjs, tca::VtxStore::Topo, TrajLength(), tca::TCConfig::unitsPerTick, tca::TCConfig::useAlg, tca::TCConfig::vtx2DCuts, and tca::TCSlice::vtxs.

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

15  {
16  // Vertices between poorly reconstructed tjs (especially junk slc) 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(tcc.vtx2DCuts[0] <= 0) return;
21  if(!tcc.useAlg[kJunkVx]) return;
22  if(slc.tjs.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 = (tcc.dbgVxJunk && tcc.dbgSlc);
29  if(prt) {
30  mf::LogVerbatim("TC")<<"MakeJunkVertices: prt set for plane "<<planeID.Plane<<" maxSep btw tjs "<<maxSep;
31 // PrintAllTraj("MJTi", slc, debug, USHRT_MAX, slc.tjs.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 = tcc.vtx2DCuts[7] + 0.1;
48 
49  // look at both ends of long tjs
50  for(unsigned short it1 = 0; it1 < slc.tjs.size() - 1; ++it1) {
51  auto& tj1 = slc.tjs[it1];
52  if(tj1.AlgMod[kKilled] || tj1.AlgMod[kHaloTj]) 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(slc, 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 = slc.tjs[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(slc, tp1, tp2, 0.8);
85  if(!signalBetween) continue;
86  if(junkVx.ID == USHRT_MAX) {
87  // define the new vertex
88  junkVx.ID = slc.vtxs.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(slc, junkVx)) {
96  mf::LogVerbatim("TC")<<"MJV: StoreVertex failed";
97  for(auto& tj : slc.tjs) {
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]/tcc.unitsPerTick;
106  } // prt
107  junkVx.ID = USHRT_MAX;
108  } // end1
109  } // it1
110 
111  } // MakeJunkVertices
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
vertex position fixed manually - no fitting done
Definition: DataStructs.h:74
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:507
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:2093
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
bool SignalBetween(TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2, const float &MinWireSignalFraction)
Definition: Utils.cxx:1671
std::vector< int > FindCloseTjs(TCSlice &slc, const TrajPoint &fromTp, const TrajPoint &toTp, const float &maxDelta)
Definition: Utils.cxx:2604
float TrajLength(Trajectory &tj)
Definition: Utils.cxx:2337
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
in close()
geo::PlaneID DecodeCTP(CTP_t CTP)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:466
void tca::MakeShowerObsolete ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 3242 of file TCShower.cxx.

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

3243  {
3244  // set the ss3 ID = 0 and remove 2D shower -> 3D shower associations. The 2D showers are not
3245  // declared obsolete
3246  for(auto cid : ss3.CotIDs) {
3247  if(cid == 0 || (unsigned short)cid > slc.cots.size()) continue;
3248  auto& ss = slc.cots[cid - 1];
3249  if(ss.SS3ID > 0 && ss.SS3ID != ss3.ID) {
3250  std::cout<<"MakeShowerObsolete: 3S"<<ss3.ID<<" -> 2S"<<ss.ID<<" SS3ID 3S"<<ss.SS3ID<<" != "<<ss3.ID<<"\n";
3251  continue;
3252  }
3253  ss.SS3ID = 0;
3254  } // cid
3255  if(prt) {
3256  std::string fcnLabel = inFcnLabel + ".MSO";
3257  mf::LogVerbatim("TC")<<fcnLabel<<" Killed 3S"<<ss3.ID;
3258  }
3259  if(ss3.PFPIndex < slc.pfps.size()) {
3260  std::cout<<"MakeShowerObsolete: 3S"<<ss3.ID<<" -> P"<<ss3.PFPIndex+1<<" assn exists but maybe shouldn't...";
3261  }
3262  ss3.ID = 0;
3263  } // MakeShowerObsolete
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
Float_t ss
Definition: plot.C:23
void tca::MakeShowerObsolete ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct ss,
bool  prt 
)

Definition at line 3266 of file TCShower.cxx.

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

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

3267  {
3268  // Gracefully kills the shower and the associated shower Tj
3269 
3270  if(ss.ID == 0) return;
3271 
3272  std::string fcnLabel = inFcnLabel + ".MSO";
3273 
3274  auto& stp1 = slc.tjs[ss.ShowerTjID - 1].Pts[1];
3275  if(!stp1.Hits.empty()) {
3276  std::cout<<fcnLabel<<" Trying to kill shower "<<ss.ID<<" that has hits associated with it. Don't do this...\n";
3277  }
3278 
3279  // clear a 3S -> 2S assn
3280  if(ss.SS3ID > 0 && ss.SS3ID <= (int)slc.showers.size()) {
3281  auto& ss3 = slc.showers[ss.SS3ID - 1];
3282  std::vector<int> newCIDs;
3283  for(auto cid : ss3.CotIDs) {
3284  if(cid != ss.ID) newCIDs.push_back(cid);
3285  } // cid
3286  ss3.CotIDs = newCIDs;
3287  } // ss3 assn exists
3288 
3289  // Kill the shower Tj if it exists. This also releases the hits
3290  if(ss.ShowerTjID > 0) MakeTrajectoryObsolete(slc, ss.ShowerTjID - 1);
3291 
3292  // Restore the original InShower Tjs
3293  // Unset the killed bit
3294  for(auto& tjID : ss.TjIDs) {
3295  Trajectory& tj = slc.tjs[tjID - 1];
3296  tj.AlgMod[kKilled] = false;
3297  // clear all of the shower-related bits
3298  tj.SSID = 0;
3299  tj.AlgMod[kShwrParent] = false;
3300  tj.AlgMod[kMergeOverlap] = false;
3301  tj.AlgMod[kMergeSubShowers] = false;
3302  tj.AlgMod[kMergeNrShowers] = false;
3303  tj.AlgMod[kMergeShChain] = false;
3304  } // tjID
3305  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Killed 2S"<<ss.ID<<" and ST"<<ss.ShowerTjID;
3306  ss.ID = 0;
3307  // No reason to do this
3308 // ss.TjIDs.clear();
3309 
3310  } // MakeShowerObsolete
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
Float_t ss
Definition: plot.C:23
void MakeTrajectoryObsolete(TCSlice &slc, unsigned int itj)
Definition: Utils.cxx:1922
bool tca::MakeTp3 ( TCSlice slc,
const TrajPoint itp,
const TrajPoint jtp,
TrajPoint3 tp3,
bool  findDirection 
)

Definition at line 1555 of file PFPUtils.cxx.

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

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

1556  {
1557  // Make a 3D trajectory point using two 2D trajectory points
1558  tp3.Dir = {{999.0, 999.0, 999.0}};
1559  tp3.Pos = {{999.0, 999.0, 999.0}};
1560  geo::PlaneID iPlnID = DecodeCTP(itp.CTP);
1561  geo::PlaneID jPlnID = DecodeCTP(jtp.CTP);
1562  double upt = tcc.unitsPerTick;
1563  double ix = tcc.detprop->ConvertTicksToX(itp.Pos[1] / upt, iPlnID);
1564  double jx = tcc.detprop->ConvertTicksToX(jtp.Pos[1] / upt, jPlnID);
1565 
1566  // don't continue if the points are wildly far apart in X
1567  if(std::abs(ix - jx) > 20) return false;
1568  tp3.Pos[0] = 0.5 * (ix + jx);
1569  // determine the wire orientation and offsets using WireCoordinate
1570  // wire = yp * OrthY + zp * OrthZ - Wire0 = cs * yp + sn * zp - wire0
1571  // wire offset
1572  double iw0 = tcc.geom->WireCoordinate(0, 0, iPlnID);
1573  // cosine-like component
1574  double ics = tcc.geom->WireCoordinate(1, 0, iPlnID) - iw0;
1575  // sine-like component
1576  double isn = tcc.geom->WireCoordinate(0, 1, iPlnID) - iw0;
1577  double jw0 = tcc.geom->WireCoordinate(0, 0, jPlnID);
1578  double jcs = tcc.geom->WireCoordinate(1, 0, jPlnID) - jw0;
1579  double jsn = tcc.geom->WireCoordinate(0, 1, jPlnID) - jw0;
1580  double den = isn * jcs - ics * jsn;
1581  if(den == 0) return false;
1582  double iPos0 = itp.Pos[0];
1583  double jPos0 = jtp.Pos[0];
1584  // Find the Z position of the intersection
1585  tp3.Pos[2] = (jcs * (iPos0 - iw0) - ics * (jPos0 - jw0)) / den;
1586  // and the Y position
1587  bool useI = std::abs(ics) > std::abs(jcs);
1588  if(useI) {
1589  tp3.Pos[1] = (iPos0 - iw0 - isn * tp3.Pos[2]) / ics;
1590  } else {
1591  tp3.Pos[1] = (jPos0 - jw0 - jsn * tp3.Pos[2]) / jcs;
1592  }
1593 
1594  // Now find the direction. Protect against large angles first
1595  if(jtp.Dir[1] == 0) {
1596  // Going either in the +X direction or -X direction
1597  if(jtp.Dir[0] > 0) { tp3.Dir[0] = 1; } else { tp3.Dir[0] = -1; }
1598  tp3.Dir[1] = 0;
1599  tp3.Dir[2] = 0;
1600  return true;
1601  } // jtp.Dir[1] == 0
1602 
1603  // stuff the average TP charge into dEdx
1604  tp3.dEdx = 0.5 * (itp.Chg + jtp.Chg);
1605 
1606  if(!findDirection) return true;
1607 
1608  // make a copy of itp and shift it by many wires to avoid precision problems
1609  double itp2_0 = itp.Pos[0] + 100;
1610  double itp2_1 = itp.Pos[1];
1611  if(std::abs(itp.Dir[0]) > 0.01) itp2_1 += 100 * itp.Dir[1] / itp.Dir[0];
1612  // Create a second Point3 for the shifted point
1613  Point3_t pos2;
1614  // Find the X position corresponding to the shifted point
1615  pos2[0] = tcc.detprop->ConvertTicksToX(itp2_1 / upt, iPlnID);
1616  // Convert X to Ticks in the j plane and then to WSE units
1617  double jtp2Pos1 = tcc.detprop->ConvertXToTicks(pos2[0], jPlnID) * upt;
1618  // Find the wire position (Pos0) in the j plane that this corresponds to
1619  double jtp2Pos0 = (jtp2Pos1 - jtp.Pos[1]) * (jtp.Dir[0] / jtp.Dir[1]) + jtp.Pos[0];
1620  // Find the Y,Z position using itp2 and jtp2Pos0
1621  pos2[2] = (jcs * (itp2_0 - iw0) - ics * (jtp2Pos0 - jw0)) / den;
1622  if(useI) {
1623  pos2[1] = (itp2_0 - iw0 - isn * pos2[2]) / ics;
1624  } else {
1625  pos2[1] = (jtp2Pos0 - jw0 - jsn * pos2[2]) / jcs;
1626  }
1627  double sep = PosSep(tp3.Pos, pos2);
1628  if(sep == 0) return false;
1629  for(unsigned short ixyz = 0; ixyz < 3; ++ixyz) tp3.Dir[ixyz] = (pos2[ixyz] - tp3.Pos[ixyz]) /sep;
1630 
1631  return true;
1632 
1633  } // MakeTP3
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
std::array< double, 3 > Point3_t
Definition: DataStructs.h:35
TCConfig tcc
Definition: DataStructs.cxx:6
Float_t den
Definition: plot.C:37
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
const detinfo::DetectorProperties * detprop
Definition: DataStructs.h:494
const geo::GeometryCore * geom
Definition: DataStructs.h:493
virtual double ConvertTicksToX(double ticks, int p, int t, int c) const =0
geo::PlaneID DecodeCTP(CTP_t CTP)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
void tca::MakeTrajectoryObsolete ( TCSlice slc,
unsigned int  itj 
)

Definition at line 1922 of file Utils.cxx.

References kKilled, tca::TCSlice::slHits, and tca::TCSlice::tjs.

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

1923  {
1924  // Note that this does not change the state of UseHit to allow
1925  // resurrecting the trajectory later (RestoreObsoleteTrajectory)
1926  if(itj > slc.tjs.size() - 1) return;
1927  int killTjID = slc.tjs[itj].ID;
1928  for(auto& hit : slc.slHits) if(hit.InTraj == killTjID) hit.InTraj = 0;
1929  slc.tjs[itj].AlgMod[kKilled] = true;
1930  } // MakeTrajectoryObsolete
Detector simulation of raw signals on wires.
bool tca::MakeVertexObsolete ( std::string  fcnLabel,
TCSlice slc,
VtxStore vx2,
bool  forceKill 
)

Definition at line 3120 of file TCVertex.cxx.

References tca::VtxStore::CTP, tca::TCConfig::dbg2V, tca::TCConfig::dbg3V, DecodeCTP(), evd::details::end(), tca::VtxStore::ID, tca::Vtx3Store::ID, kEnvOverlap, kHaloTj, kHiVx3Score, kKilled, kPhoton, kTjHiVx3Score, tca::TCSlice::nPlanes, tca::TCSlice::pfps, geo::PlaneID::Plane, tca::VtxStore::Pos, SetVx3Score(), tcc, tca::TCSlice::tjs, tca::TCConfig::vtx2DCuts, tca::TCSlice::vtx3s, tca::TCSlice::vtxs, tca::Vtx3Store::Vx2ID, tca::VtxStore::Vx3ID, and tca::Vtx3Store::Wire.

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

3121  {
3122  // Makes a 2D vertex obsolete
3123 
3124  // check for a high-score 3D vertex
3125  bool hasHighScoreVx3 = (vx2.Vx3ID > 0);
3126  if(hasHighScoreVx3 && !forceKill && slc.vtx3s[vx2.Vx3ID - 1].Score >= tcc.vtx2DCuts[7]) return false;
3127 
3128  if(tcc.dbg2V || tcc.dbg3V) {
3129  mf::LogVerbatim("TC")<<fcnLabel<<" MVO: killing 2V"<<vx2.ID;
3130  }
3131 
3132  // Kill it
3133  int vx2id = vx2.ID;
3134  if(vx2.Vx3ID > 0) {
3135  auto& vx3 = slc.vtx3s[vx2.Vx3ID - 1];
3136  for(auto& v3v2id : vx3.Vx2ID) if(v3v2id == vx2.ID) v3v2id = 0;
3137  }
3138  vx2.ID = 0;
3139  for(auto& tj : slc.tjs) {
3140  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
3141  for(unsigned short end = 0; end < 2; ++end) {
3142  if(tj.VtxID[end] != vx2id) continue;
3143  tj.VtxID[end] = 0;
3144  tj.AlgMod[kPhoton] = false;
3145  // clear the kEnvOverlap bits on the TPs
3146  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
3147  if(end == 0) {
3148  unsigned short ipt = tj.EndPt[0] + ii;
3149  auto& tp = tj.Pts[ipt];
3150  if(!tp.Environment[kEnvOverlap]) break;
3151  if(ipt == tj.EndPt[1]) break;
3152  } else {
3153  unsigned short ipt = tj.EndPt[1] - ii;
3154  auto& tp = tj.Pts[ipt];
3155  if(!tp.Environment[kEnvOverlap]) break;
3156  if(ipt == tj.EndPt[0]) break;
3157  }
3158  } // ii
3159  if(tj.AlgMod[kTjHiVx3Score]) {
3160  // see if the vertex at the other end is high-score and if so, preserve the state
3161  unsigned short oend = 1 - end;
3162  if(tj.VtxID[oend] > 0) {
3163  auto& ovx2 = slc.vtxs[tj.VtxID[oend] - 1];
3164  if(!ovx2.Stat[kHiVx3Score]) tj.AlgMod[kTjHiVx3Score] = false;
3165  } // vertex at the other end
3166  } // tj.AlgMod[kTjHiVx3Score]
3167  } // end
3168  } // tj
3169 
3170  if(!hasHighScoreVx3) return true;
3171 
3172  // update the affected 3D vertex
3173  Vtx3Store& vx3 = slc.vtx3s[vx2.Vx3ID - 1];
3174  // make the 3D vertex incomplete
3175  geo::PlaneID planeID = DecodeCTP(vx2.CTP);
3176  unsigned short plane = planeID.Plane;
3177  if(vx3.Vx2ID[plane] != vx2id) return true;
3178  vx3.Vx2ID[plane] = 0;
3179  vx3.Wire = vx2.Pos[0];
3180  // Ensure that there are at least two 2D vertices left
3181  unsigned short n2D = 0;
3182  for(unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
3183  if(vx3.Vx2ID[plane] > 0) ++n2D;
3184  } // plane
3185 
3186  if(n2D > 1) {
3187  // 3D vertex is incomplete
3188  // correct the score
3189  SetVx3Score(slc, vx3);
3190  return true;
3191  }
3192 
3193  // 3D vertex is obsolete
3194  // Detach the all remaining 2D vertices from the 3D vertex
3195  for(auto& vx2 : slc.vtxs) {
3196  if(vx2.ID == 0) continue;
3197  if(vx2.Vx3ID == vx3.ID) vx2.Vx3ID = 0;
3198  } // vx2
3199  for(auto& pfp : slc.pfps) {
3200  for(unsigned short end = 0; end < 2; ++end) if(pfp.Vx3ID[end] == vx3.ID) pfp.Vx3ID[end] = 0;
3201  } // pfp
3202  vx3.ID = 0;
3203  return true;
3204 
3205  } // MakeVertexObsolete
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
matched to a high-score 3D vertex
Definition: DataStructs.h:76
void SetVx3Score(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2483
bool dbg3V
debug 3D vertex finding
Definition: DataStructs.h:514
bool dbg2V
debug 2D vertex finding
Definition: DataStructs.h:510
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:466
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool tca::MakeVertexObsolete ( TCSlice slc,
Vtx3Store vx3 
)

Definition at line 3208 of file TCVertex.cxx.

References tca::Vtx3Store::ID, MakeVertexObsolete(), tca::TCSlice::vtx3s, tca::TCSlice::vtxs, and tca::Vtx3Store::Vx2ID.

3209  {
3210  // Deletes a 3D vertex and 2D vertices in all planes
3211  // The 2D and 3D vertices are NOT killed if forceKill is false and the 3D vertex
3212  // has a high score
3213  if(vx3.ID == 0) return true;
3214  if(vx3.ID > int(slc.vtx3s.size())) return false;
3215 
3216  for(auto vx2id : vx3.Vx2ID) {
3217  if(vx2id == 0 || vx2id > (int)slc.vtxs.size()) continue;
3218  auto& vx2 = slc.vtxs[vx2id - 1];
3219  MakeVertexObsolete("MVO3", slc, vx2, true);
3220  }
3221  vx3.ID = 0;
3222  return true;
3223  } // MakeVertexObsolete
bool MakeVertexObsolete(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:3208
void tca::MaskBadTPs ( TCSlice slc,
Trajectory tj,
float const &  maxChi 
)

Definition at line 2665 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::TrajPoint::Chg, tca::TCConfig::dbgAlg, tca::TCConfig::dbgStp, tca::TrajPoint::Delta, tca::TrajPoint::FitChi, FitTraj(), tca::Trajectory::IsGood, kMaskBadTPs, kRvPrp, tca::TrajPoint::NTPsFit, tca::Trajectory::Pts, tcc, UnsetUsedHits(), and tca::TCConfig::useAlg.

Referenced by UpdateTraj().

2666  {
2667  // Remove TPs that have the worst values of delta until the fit chisq < maxChi
2668 
2669  if(!tcc.useAlg[kMaskBadTPs]) return;
2670  //don't use this function for reverse propagation
2671  if(!tcc.useAlg[kRvPrp]) return;
2672 
2673  bool prt = (tcc.dbgStp || tcc.dbgAlg[kMaskBadTPs]);
2674 
2675  if(tj.Pts.size() < 3) {
2676  // mf::LogError("TC")<<"MaskBadTPs: Trajectory ID "<<tj.ID<<" too short to mask hits ";
2677  tj.IsGood = false;
2678  return;
2679  }
2680  unsigned short nit = 0;
2681  TrajPoint& lastTP = tj.Pts[tj.Pts.size() - 1];
2682  while(lastTP.FitChi > maxChi && nit < 3) {
2683  float maxDelta = 0;
2684  unsigned short imBad = USHRT_MAX;
2685  unsigned short cnt = 0;
2686  for(unsigned short ii = 1; ii < tj.Pts.size(); ++ii) {
2687  unsigned short ipt = tj.Pts.size() - 1 - ii;
2688  TrajPoint& tp = tj.Pts[ipt];
2689  if(tp.Chg == 0) continue;
2690  if(tp.Delta > maxDelta) {
2691  maxDelta = tp.Delta;
2692  imBad = ipt;
2693  }
2694  ++cnt;
2695  if(cnt == tp.NTPsFit) break;
2696  } // ii
2697  if(imBad == USHRT_MAX) return;
2698  if(prt) mf::LogVerbatim("TC")<<"MaskBadTPs: lastTP.FitChi "<<lastTP.FitChi<<" Mask point "<<imBad;
2699  // mask the point
2700  UnsetUsedHits(slc, tj.Pts[imBad]);
2701  FitTraj(slc, tj);
2702  if(prt) mf::LogVerbatim("TC")<<" after FitTraj "<<lastTP.FitChi;
2703  tj.AlgMod[kMaskBadTPs] = true;
2704  ++nit;
2705  } // lastTP.FItChi > maxChi && nit < 3
2706 
2707  } // MaskBadTPs
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1162
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
void FitTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:753
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:505
bool tca::MaskedHitsOK ( TCSlice slc,
Trajectory tj 
)

Definition at line 2710 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::TCEvent::allHits, tca::TCConfig::dbgStp, DefineHitPos(), tca::Trajectory::EndPt, evt, FitTraj(), tca::TrajPoint::Hits, tca::Trajectory::ID, kMaskHits, tca::TCConfig::minPtsFit, tca::TrajPoint::NTPsFit, tca::Trajectory::Pass, PrintTrajectory(), tca::Trajectory::Pts, SetEndPoints(), tca::TCSlice::slHits, tcc, UpdateTjChgProperties(), tca::TCConfig::useAlg, and tca::TrajPoint::UseHit.

Referenced by StepAway().

2711  {
2712  // The hits in the TP at the end of the trajectory were masked off. Decide whether to continue stepping with the
2713  // current configuration (true) or whether to stop and possibly try with the next pass settings (false)
2714 
2715  if(!tcc.useAlg[kMaskHits]) return true;
2716 
2717  unsigned short lastPt = tj.Pts.size() - 1;
2718  if(tj.Pts[lastPt].Chg > 0) return true;
2719  unsigned short endPt = tj.EndPt[1];
2720 
2721  // count the number of points w/o used hits and the number with one unused hit
2722  unsigned short nMasked = 0;
2723  unsigned short nOneHit = 0;
2724  unsigned short nOKChg = 0;
2725  unsigned short nOKDelta = 0;
2726  // number of points with Pos > HitPos
2727  unsigned short nPosDelta = 0;
2728  // number of points with Delta increasing vs ipt
2729  unsigned short nDeltaIncreasing = 0;
2730  // Fake this a bit to simplify comparing the counts
2731  float prevDelta = tj.Pts[endPt].Delta;
2732  float maxOKDelta = 10 * tj.Pts[endPt].DeltaRMS;
2733  float maxOKChg = 0;
2734  // find the maximum charge point on the trajectory
2735  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) if(tj.Pts[ipt].Chg > maxOKChg) maxOKChg = tj.Pts[ipt].Chg;
2736  for(unsigned short ii = 1; ii < tj.Pts.size(); ++ii) {
2737  unsigned short ipt = tj.Pts.size() - ii;
2738  auto& tp = tj.Pts[ipt];
2739  if(tp.Chg > 0) break;
2740  unsigned short nUnusedHits = 0;
2741  float chg = 0;
2742  for(unsigned short jj = 0; jj < tp.Hits.size(); ++jj) {
2743  unsigned int iht = tp.Hits[jj];
2744  if(slc.slHits[iht].InTraj != 0) continue;
2745  ++nUnusedHits;
2746  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2747  chg += hit.Integral();
2748  } // jj
2749  if(chg < maxOKChg) ++nOKChg;
2750  if(nUnusedHits == 1) ++nOneHit;
2751  if(tp.Delta < maxOKDelta) ++nOKDelta;
2752  // count the number of points with Pos time > HitPos time
2753  if(tp.Pos[1] > tp.HitPos[1]) ++nPosDelta;
2754  // The number of increasing delta points: Note implied absolute value
2755  if(tp.Delta < prevDelta) ++nDeltaIncreasing;
2756  prevDelta = tp.Delta;
2757  ++nMasked;
2758  } // ii
2759 
2760  // determine if the hits are wandering away from the trajectory direction. This will result in
2761  // nPosDelta either being ~0 or ~equal to the number of masked points. nPosDelta should have something
2762  // in between these two extremes if we are stepping through a messy region
2763  bool driftingAway = nMasked > 2 && (nPosDelta == 0 || nPosDelta == nMasked);
2764  // Note that nDeltaIncreasing is always positive
2765  if(driftingAway && nDeltaIncreasing < nMasked - 1) driftingAway = false;
2766 
2767  if(tcc.dbgStp) {
2768  mf::LogVerbatim("TC")<<"MHOK: nMasked "<<nMasked<<" nOneHit "<<nOneHit<<" nOKChg "<<nOKChg<<" nOKDelta "<<nOKDelta<<" nPosDelta "<<nPosDelta<<" nDeltaIncreasing "<<nDeltaIncreasing<<" driftingAway? "<<driftingAway;
2769  }
2770 
2771  if(!driftingAway) {
2772  if(nMasked < 8 || nOneHit < 8) return true;
2773  if(nOKDelta != nMasked) return true;
2774  if(nOKChg != nMasked) return true;
2775  }
2776 
2777  // we would like to reduce the number of fitted points to a minimum and include
2778  // the masked hits, but we can only do that if there are enough points
2779  if(tj.Pts[endPt].NTPsFit <= tcc.minPtsFit[tj.Pass]) {
2780  // stop stepping if we have masked off more points than are in the fit
2781  if(nMasked > tj.Pts[endPt].NTPsFit) return false;
2782  return true;
2783  }
2784  // Reduce the number of points fit and try to include the points
2785  unsigned short newNTPSFit;
2786  if(tj.Pts[endPt].NTPsFit > 2 * tcc.minPtsFit[tj.Pass]) {
2787  newNTPSFit = tj.Pts[endPt].NTPsFit / 2;
2788  } else {
2789  newNTPSFit = tcc.minPtsFit[tj.Pass];
2790  }
2791  for(unsigned ipt = endPt + 1; ipt < tj.Pts.size(); ++ipt) {
2792  TrajPoint& tp = tj.Pts[ipt];
2793  for(unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
2794  unsigned int iht = tp.Hits[ii];
2795  if(slc.slHits[iht].InTraj == 0) {
2796  tp.UseHit[ii] = true;
2797  slc.slHits[iht].InTraj = tj.ID;
2798  break;
2799  }
2800  } // ii
2801  DefineHitPos(slc, tp);
2802  SetEndPoints(tj);
2803  tp.NTPsFit = newNTPSFit;
2804  FitTraj(slc, tj);
2805  if(tcc.dbgStp) PrintTrajectory("MHOK", slc, tj, ipt);
2806  } // ipt
2807 
2808  tj.AlgMod[kMaskHits] = true;
2809  UpdateTjChgProperties("MHOK", slc, tj, tcc.dbgStp);
2810  return true;
2811 
2812  } // MaskedHitsOK
void PrintTrajectory(std::string someText, TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:5455
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
std::vector< unsigned short > minPtsFit
Reconstruct in several passes.
Definition: DataStructs.h:482
TCConfig tcc
Definition: DataStructs.cxx:6
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1840
void FitTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:753
Detector simulation of raw signals on wires.
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3196
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
void tca::MaskTrajEndPoints ( TCSlice slc,
Trajectory tj,
unsigned short  nPts 
)

Definition at line 3887 of file StepUtils.cxx.

References ChkMichel(), tca::TCConfig::dbgStp, tca::Trajectory::EndPt, tca::Trajectory::ID, tca::Trajectory::IsGood, PointTrajDOCA(), PrintPos(), tca::Trajectory::Pts, SetEndPoints(), tcc, TrajPointSeparation(), and UnsetUsedHits().

Referenced by CheckHiMultUnusedHits(), and StepAway().

3888  {
3889 
3890  // Masks off (sets all hits not-Used) nPts trajectory points at the leading edge of the
3891  // trajectory, presumably because the fit including this points is poor. The position, direction
3892  // and Delta of the last nPts points is updated as well
3893 
3894  if(tj.Pts.size() < 3) {
3895  mf::LogError("TC")<<"MaskTrajEndPoints: Trajectory ID "<<tj.ID<<" too short to mask hits ";
3896  tj.IsGood = false;
3897  return;
3898  }
3899  if(nPts > tj.Pts.size() - 2) {
3900  mf::LogError("TC")<<"MaskTrajEndPoints: Trying to mask too many points "<<nPts<<" Pts.size "<<tj.Pts.size();
3901  tj.IsGood = false;
3902  return;
3903  }
3904 
3905  // find the last good point (with charge)
3906  unsigned short lastGoodPt = USHRT_MAX ;
3907 
3908  if (!ChkMichel(slc, tj, lastGoodPt)){ //did not find michel electron
3909  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
3910  unsigned short ipt = tj.EndPt[1] - nPts - ii;
3911  if(tj.Pts[ipt].Chg > 0) {
3912  lastGoodPt = ipt;
3913  break;
3914  }
3915  if(ipt == 0) break;
3916  } // ii
3917  }
3918  if(tcc.dbgStp) {
3919  mf::LogVerbatim("TC")<<"MTEP: lastGoodPt "<<lastGoodPt<<" Pts size "<<tj.Pts.size()<<" tj.IsGood "<<tj.IsGood;
3920  }
3921  if(lastGoodPt == USHRT_MAX) return;
3922  tj.EndPt[1] = lastGoodPt;
3923 
3924  //for(unsigned short ii = 0; ii < nPts; ++ii) {
3925  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
3926  unsigned short ipt = tj.Pts.size() - 1 - ii;
3927  if (ipt==lastGoodPt) break;
3928  UnsetUsedHits(slc, tj.Pts[ipt]);
3929  // Reset the position and direction of the masked off points
3930  tj.Pts[ipt].Dir = tj.Pts[lastGoodPt].Dir;
3931  if(tj.Pts[lastGoodPt].AngleCode == 2) {
3932  // Very large angle: Move by path length
3933  float path = TrajPointSeparation(tj.Pts[lastGoodPt], tj.Pts[ipt]);
3934  tj.Pts[ipt].Pos[0] = tj.Pts[lastGoodPt].Pos[0] + path * tj.Pts[ipt].Dir[0];
3935  tj.Pts[ipt].Pos[1] = tj.Pts[lastGoodPt].Pos[1] + path * tj.Pts[ipt].Dir[1];
3936  } else {
3937  // Not large angle: Move by wire
3938  float dw = tj.Pts[ipt].Pos[0] - tj.Pts[lastGoodPt].Pos[0];
3939  // Correct the projected time to the wire
3940  float newpos = tj.Pts[lastGoodPt].Pos[1] + dw * tj.Pts[ipt].Dir[1] / tj.Pts[ipt].Dir[0];
3941  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"MTEP: ipt "<<ipt<<" Pos[0] "<<tj.Pts[ipt].Pos[0]<<". Move Pos[1] from "<<tj.Pts[ipt].Pos[1]<<" to "<<newpos;
3942  tj.Pts[ipt].Pos[1] = tj.Pts[lastGoodPt].Pos[1] + dw * tj.Pts[ipt].Dir[1] / tj.Pts[ipt].Dir[0];
3943  }
3944  tj.Pts[ipt].Delta = PointTrajDOCA(slc, tj.Pts[ipt].HitPos[0], tj.Pts[ipt].HitPos[1], tj.Pts[ipt]);
3945  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" masked ipt "<<ipt<<" Pos "<<PrintPos(slc, tj.Pts[ipt])<<" Chg "<<tj.Pts[ipt].Chg;
3946  } // ii
3947  SetEndPoints(tj);
3948 
3949  } // MaskTrajEndPoints
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
TCConfig tcc
Definition: DataStructs.cxx:6
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1162
float TrajPointSeparation(TrajPoint &tp1, TrajPoint &tp2)
Definition: Utils.cxx:2368
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
bool ChkMichel(TCSlice &slc, Trajectory &tj, unsigned short &lastGoodPt)
Definition: StepUtils.cxx:4049
void tca::Match2DShowers ( std::string  inFcnLabel,
TCSlice slc,
bool  prt 
)

Definition at line 882 of file TCShower.cxx.

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

Referenced by FindShowers3D().

883  {
884  // Match 2D showers using position and direction to create 3D showers
885 
886  std::string fcnLabel = inFcnLabel + ".M2DS";
887  if(prt) mf::LogVerbatim("TC")<<fcnLabel;
888 
889  float fomCut = 2;
890 
891  ChkAssns(fcnLabel, slc);
892 
893  // sort the showers by decreasing energy and increasing AspectRatio so that the 3D direction is defined
894  // by the first matching pair
895  std::vector<SortEntry> sortVec;
896  for(unsigned short indx = 0; indx < slc.cots.size(); ++indx) {
897  auto& ss = slc.cots[indx];
898  if(ss.ID == 0) continue;
899  // already matched?
900  if(ss.SS3ID > 0) continue;
901  if(ss.TjIDs.empty()) continue;
902  SortEntry se;
903  se.index = indx;
904  se.length = ss.Energy / ss.AspectRatio;
905  sortVec.push_back(se);
906  } // indx
907  if(sortVec.size() < 2) return;
908  std::sort(sortVec.begin(), sortVec.end(), greaterThan);
909 
910  // Look for a 3D match using the 2D shower charge centers
911  for(unsigned short ii = 0; ii < sortVec.size() - 1; ++ii) {
912  unsigned short iIndx = sortVec[ii].index;
913  auto& iss = slc.cots[iIndx];
914  // already matched?
915  if(iss.SS3ID > 0) continue;
916  Trajectory& istj = slc.tjs[iss.ShowerTjID - 1];
917  geo::PlaneID iplaneID = DecodeCTP(iss.CTP);
918  for(unsigned short jj = 0; jj < sortVec.size(); ++jj) {
919  if(iss.SS3ID > 0) break;
920  unsigned short jIndx = sortVec[jj].index;
921  ShowerStruct& jss = slc.cots[jIndx];
922  // already matched?
923  if(iss.SS3ID > 0) break;
924  if(jss.SS3ID > 0) continue;
925  if(jss.CTP == iss.CTP) continue;
926  Trajectory& jstj = slc.tjs[jss.ShowerTjID - 1];
927  TrajPoint3 tp3;
928  if(!MakeTp3(slc, istj.Pts[1], jstj.Pts[1], tp3, true)) continue;
929  float fomij = Match3DFOM(fcnLabel, slc, iss.ID, jss.ID, prt);
930  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" i2S"<<iss.ID<<" j2S"<<jss.ID<<" fomij "<<fomij<<" fomCut "<<fomCut;
931  if(fomij > fomCut) continue;
932  geo::PlaneID jplaneID = DecodeCTP(jss.CTP);
933  if(slc.nPlanes == 2) {
934  ShowerStruct3D ss3 = CreateSS3(slc);
935  ss3.ChgPos = tp3.Pos;
936  ss3.Dir = tp3.Dir;
937  ss3.CotIDs.resize(2);
938  ss3.CotIDs[0] = iss.ID;
939  ss3.CotIDs[1] = jss.ID;
940  ss3.Energy.resize(2);
941  ss3.Energy[0] = iss.Energy;
942  ss3.Energy[1] = jss.Energy;
943  ss3.MatchFOM = fomij;
944  ss3.PFPIndex = USHRT_MAX;
945  if(!StoreShower(fcnLabel, slc, ss3)) continue;
946  if(prt) mf::LogVerbatim("TC")<<" new 2-plane TPC 3S"<<ss3.ID<<" with fomij "<<fomij;
947  continue;
948  } // 2-plane TPC
949  float bestFOM = fomCut;
950  unsigned short bestck = USHRT_MAX;
951  for(unsigned short ck = 0; ck < slc.cots.size(); ++ck) {
952  ShowerStruct& kss = slc.cots[ck];
953  if(kss.ID == iss.ID || kss.ID == jss.ID) continue;
954  if(kss.CTP == iss.CTP || kss.CTP == jss.CTP) continue;
955  if(kss.ID == 0) continue;
956  if(kss.TjIDs.empty()) continue;
957  if(kss.SS3ID > 0) continue;
958  Trajectory& kstj = slc.tjs[kss.ShowerTjID - 1];
959  TrajPoint3 iktp3;
960  MakeTp3(slc, istj.Pts[1], kstj.Pts[1], iktp3, true);
961  float fomik = Match3DFOM(fcnLabel, slc, iss.ID, kss.ID, prt);
962  if(fomik > bestFOM) continue;
963  float sep = PosSep(tp3.Pos, iktp3.Pos);
964  if(sep > 50) {
965  if(prt) mf::LogVerbatim("TC")<<" 2S"<<iss.ID<<" 2S"<<jss.ID<<" 2S"<<kss.ID<<" Large stp[1] point separation "<<(int)sep;
966  continue;
967  }
968  bestFOM = fomik;
969  bestck = ck;
970  } // ck
971  // 3-plane TPC below
972  ShowerStruct3D ss3 = CreateSS3(slc);
973  // Define ss3 using the tp3 found with the first pair
974  ss3.ChgPos = tp3.Pos;
975  ss3.Dir = tp3.Dir;
976  ss3.MatchFOM = bestFOM;
977  if(bestck == USHRT_MAX) {
978  // showers match in 2 planes
979  ss3.CotIDs.resize(2);
980  ss3.CotIDs[0] = iss.ID;
981  ss3.CotIDs[1] = jss.ID;
982  ss3.Energy[iplaneID.Plane] = iss.Energy;
983  ss3.Energy[jplaneID.Plane] = jss.Energy;
984  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";
985  // ignore this 3D match if the shower can't be completed
986  if(!CompleteIncompleteShower(fcnLabel, slc, ss3, prt)) continue;
987  iss.SS3ID = ss3.ID;
988  jss.SS3ID = ss3.ID;
989  } else {
990  // showers match in 3 planes
991  unsigned short ck = bestck;
992  ShowerStruct& kss = slc.cots[ck];
993  ss3.CotIDs.resize(3);
994  ss3.CotIDs[0] = iss.ID;
995  ss3.CotIDs[1] = jss.ID;
996  ss3.CotIDs[2] = kss.ID;
997  geo::PlaneID kplaneID = DecodeCTP(kss.CTP);
998  ss3.Energy[iplaneID.Plane] = iss.Energy;
999  ss3.Energy[jplaneID.Plane] = jss.Energy;
1000  ss3.Energy[kplaneID.Plane] = kss.Energy;
1001  slc.cots[ck].SS3ID = ss3.ID;
1002  if(prt) mf::LogVerbatim("TC")<<" new 3-plane 3S"<<ss3.ID<<" using 2S"<<iss.ID<<" 2S"<<jss.ID<<" 2S"<<slc.cots[ck].ID<<" with FOM "<<ss3.MatchFOM;
1003  }
1004  ss3.MatchFOM = 0.5 * (fomij + bestFOM);
1005  // sort the IDs
1006  std::sort(ss3.CotIDs.begin(), ss3.CotIDs.end());
1007  // Set the 3S -> 2S assns and store it
1008  if(!StoreShower(fcnLabel, slc, ss3)) {
1009  MakeShowerObsolete(fcnLabel, slc, ss3, prt);
1010  continue;
1011  }
1012  // make a reference to the stored shower
1013  auto& nss3 = slc.showers[slc.showers.size() - 1];
1014  if(nss3.NeedsUpdate) UpdateShower(fcnLabel, slc, nss3, prt);
1015  // reconcile tj -> 2S -> 3S and tj -> pfps
1016  if(!Reconcile3D(fcnLabel, slc, nss3, prt)) {
1017  MakeShowerObsolete(fcnLabel, slc, nss3, prt);
1018  continue;
1019  }
1020  if(nss3.NeedsUpdate) UpdateShower(fcnLabel, slc, nss3, prt);
1021  if(prt) mf::LogVerbatim("TC")<<" 3S"<<nss3.ID<<" updated";
1022  break;
1023  } // cj
1024  } // ci
1025 
1026  ChkAssns(fcnLabel, slc);
1027 
1028  if(prt) PrintShowers("M2DS", slc);
1029 
1030  } // Match2DShowers
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool greaterThan(SortEntry c1, SortEntry c2)
Definition: TCShower.cxx:9
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4560
unsigned int index
Definition: StepUtils.cxx:5
ShowerStruct3D CreateSS3(TCSlice &slc)
Definition: TCShower.cxx:4495
void PrintShowers(std::string fcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4611
bool MakeTp3(TCSlice &slc, const TrajPoint &itp, const TrajPoint &jtp, TrajPoint3 &tp3, bool findDirection)
Definition: PFPUtils.cxx:1555
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
Float_t ss
Definition: plot.C:23
float length
Definition: TCShower.cxx:6
bool Reconcile3D(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:580
void MakeShowerObsolete(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3266
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1230
float Match3DFOM(std::string inFcnLabel, TCSlice &slc, int icid, int jcid, bool prt)
Definition: TCShower.cxx:1377
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
bool StoreShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss)
Definition: TCShower.cxx:4449
geo::PlaneID DecodeCTP(CTP_t CTP)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
bool CompleteIncompleteShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:739
float tca::Match3DFOM ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 1345 of file TCShower.cxx.

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

1346  {
1347  float fom = 0;
1348  float cnt = 0;
1349  for(unsigned short ii = 0; ii < ss3.CotIDs.size() - 1; ++ii) {
1350  unsigned short icid = ss3.CotIDs[ii];
1351  for(unsigned short jj = ii + 1; jj < ss3.CotIDs.size(); ++jj) {
1352  unsigned short jcid = ss3.CotIDs[jj];
1353  fom += Match3DFOM(inFcnLabel, slc, icid, jcid, prt);
1354  ++cnt;
1355  } // cj
1356  } // ci
1357  if(cnt == 0) return 100;
1358  return fom / cnt;
1359  } // Match3DFOM
float Match3DFOM(std::string inFcnLabel, TCSlice &slc, int icid, int jcid, bool prt)
Definition: TCShower.cxx:1377
float tca::Match3DFOM ( std::string  inFcnLabel,
TCSlice slc,
int  icid,
int  jcid,
int  kcid,
bool  prt 
)

Definition at line 1362 of file TCShower.cxx.

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

1364  {
1365  if(icid == 0 || icid > (int)slc.cots.size()) return 100;
1366  if(jcid == 0 || jcid > (int)slc.cots.size()) return 100;
1367  if(kcid == 0 || kcid > (int)slc.cots.size()) return 100;
1368 
1369  float ijfom = Match3DFOM(inFcnLabel, slc, icid, jcid, prt);
1370  float jkfom = Match3DFOM(inFcnLabel, slc, jcid, kcid, prt);
1371 
1372  return 0.5 * (ijfom + jkfom);
1373 
1374  } // Match3DFOM
float Match3DFOM(std::string inFcnLabel, TCSlice &slc, int icid, int jcid, bool prt)
Definition: TCShower.cxx:1377
float tca::Match3DFOM ( std::string  inFcnLabel,
TCSlice slc,
int  icid,
int  jcid,
bool  prt 
)

Definition at line 1377 of file TCShower.cxx.

References detinfo::DetectorProperties::ConvertTicksToX(), tca::TCSlice::cots, DecodeCTP(), tca::TCConfig::detprop, tcc, tca::TCSlice::tjs, and tca::TCConfig::unitsPerTick.

Referenced by Match2DShowers(), and Match3DFOM().

1378  {
1379  // returns a Figure of Merit for a 3D match of two showers
1380  if(icid == 0 || icid > (int)slc.cots.size()) return 100;
1381  if(jcid == 0 || jcid > (int)slc.cots.size()) return 100;
1382 
1383  auto& iss = slc.cots[icid - 1];
1384  auto& istj = slc.tjs[iss.ShowerTjID - 1];
1385  auto& jss = slc.cots[jcid - 1];
1386  auto& jstj = slc.tjs[jss.ShowerTjID - 1];
1387 
1388  if(iss.CTP == jss.CTP) return 100;
1389 
1390  std::string fcnLabel = inFcnLabel + ".MFOM";
1391 
1392  float energyAsym = std::abs(iss.Energy - jss.Energy) / (iss.Energy + jss.Energy);
1393 
1394  // don't apply the asymmetry cut on low energy showers
1395  if((iss.Energy > 200 || jss.Energy > 200) && energyAsym > 0.5) return 50;
1396 
1397  geo::PlaneID iPlnID = DecodeCTP(iss.CTP);
1398  geo::PlaneID jPlnID = DecodeCTP(jss.CTP);
1399 
1400  // compare match at the charge center
1401  float ix = tcc.detprop->ConvertTicksToX(istj.Pts[1].Pos[1] / tcc.unitsPerTick, iPlnID);
1402  float jx = tcc.detprop->ConvertTicksToX(jstj.Pts[1].Pos[1] / tcc.unitsPerTick, jPlnID);
1403  float pos1fom = std::abs(ix - jx) / 10;
1404 
1405  float mfom = energyAsym * pos1fom;
1406 
1407  if(prt) {
1408  mf::LogVerbatim myprt("TC");
1409  myprt<<fcnLabel<<" i2S"<<iss.ID<<" j2S"<<jss.ID;
1410  myprt<<std::fixed<<std::setprecision(2);
1411 // myprt<<" pos0fom "<<pos0fom;
1412  myprt<<" pos1fom "<<pos1fom;
1413 // myprt<<" pos2fom "<<pos2fom;
1414  myprt<<" energyAsym "<<energyAsym;
1415  myprt<<" mfom "<<mfom;
1416  }
1417 
1418  return mfom;
1419  } // Madtch3DFOM
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
const detinfo::DetectorProperties * detprop
Definition: DataStructs.h:494
virtual double ConvertTicksToX(double ticks, int p, int t, int c) const =0
geo::PlaneID DecodeCTP(CTP_t CTP)
void tca::Match3DVtxTjs ( TCSlice slc,
bool  prt 
)

Definition at line 1693 of file TCVertex.cxx.

References AnalyzePFP(), CreatePFP(), DefinePFP(), tca::PFPStruct::Dir, GetVtxTjIDs(), tca::PFPStruct::ID, tca::SortEntry::index, kHaloTj, kKilled, kM3DVxTj, kMat3D, tca::TCSlice::matchVec, tca::PFPStruct::MatchVecIndex, tca::TCSlice::nPlanes, tca::PFPStruct::PDGCode, PDGCodeVote(), PrintPFP(), SetDifference(), SetIntersection(), Split3DKink(), StorePFP(), tcc, tca::PFPStruct::TjIDs, tca::TCSlice::tjs, tmp, tca::TCConfig::useAlg, tca::SortEntry::val, valDecreasing(), tca::TCConfig::vtx2DCuts, tca::TCSlice::vtx3s, tca::PFPStruct::Vx3ID, and tca::PFPStruct::XYZ.

Referenced by FindPFParticles().

1694  {
1695  // Matches Tjs that are attached to 2D vertices that are matched in 3D. This function does not attempt
1696  // to determine the appropriate ends of matched Tjs when there is a 3D vertex at both ends.
1697 
1698  if(!tcc.useAlg[kM3DVxTj]) return;
1699  if(slc.vtx3s.empty()) return;
1700  if(slc.matchVec.empty()) return;
1701 
1702  // sort the vertices by decreasing score
1703  std::vector<SortEntry> sortVec;
1704  for(unsigned short iv3 = 0; iv3 < slc.vtx3s.size(); ++iv3) {
1705  auto& vx3 = slc.vtx3s[iv3];
1706  if(vx3.ID == 0) continue;
1707  // put the TjIDs into a vector for matching
1708  float score = 0;
1709  auto v3TjIDs = GetVtxTjIDs(slc, vx3, score);
1710  if(v3TjIDs.empty()) continue;
1711  if(score < tcc.vtx2DCuts[7]) continue;
1712  SortEntry se;
1713  se.index = iv3;
1714  se.val = score;
1715  sortVec.push_back(se);
1716  } // vx3
1717  if(sortVec.empty()) return;
1718  if(sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(), valDecreasing);
1719 
1720  for(unsigned short ii = 0; ii < sortVec.size(); ++ii) {
1721  auto& vx3 = slc.vtx3s[sortVec[ii].index];
1722  float score = 0;
1723  std::vector<int> v3TjIDs = GetVtxTjIDs(slc, vx3, score);
1724  if(prt) {
1725  mf::LogVerbatim myprt("TC");
1726  myprt<<"M3DVTj 3V"<<vx3.ID<<" score "<<score<<" Tjs";
1727  for(auto& tjID : v3TjIDs) myprt<<" T"<<tjID;
1728  }
1729  for(unsigned int ims = 0; ims < slc.matchVec.size(); ++ims) {
1730  auto& ms = slc.matchVec[ims];
1731  if(ms.Count == 0) continue;
1732  bool skipit = false;
1733  for(auto tjid : ms.TjIDs) {
1734  auto& tj = slc.tjs[tjid - 1];
1735  if(tj.AlgMod[kMat3D]) skipit = true;
1736  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) skipit = true;
1737  }
1738  if(skipit) continue;
1739  std::vector<int> shared = SetIntersection(ms.TjIDs, v3TjIDs);
1740  if(shared.size() < 2) continue;
1741  if(prt) mf::LogVerbatim("TC")<<" ims "<<ims<<" shared size "<<shared.size();
1742  PFPStruct pfp = CreatePFP(slc);
1743  pfp.TjIDs = ms.TjIDs;
1744  pfp.Vx3ID[0] = vx3.ID;
1745  // note that the ms position is the average position of all 3D matched Tp3s at this point.
1746  // It is not the start position. This will be determined in DefinePFP.
1747  pfp.XYZ[0] = ms.Pos;
1748  pfp.Dir[0] = ms.Dir;
1749  pfp.MatchVecIndex = ims;
1750  if(prt) mf::LogVerbatim("TC")<<"M3DVTj: pfp P"<<pfp.ID<<" 3V"<<vx3.ID<<" ims "<<ims;
1751  // Set the PDGCode so DefinePFP can ignore incompatible matches
1752  pfp.PDGCode = PDGCodeVote(slc, pfp.TjIDs, prt);
1753  // make a copy of the TjIDs to test for changes
1754  auto saveTjIDs = pfp.TjIDs;
1755  if(!DefinePFP("M3DVTj1", slc, pfp, prt)) continue;
1756  // separation distance (cm) for kink detection.
1757  double sep = 1;
1758  bool didSplit = Split3DKink(slc, pfp, sep, prt);
1759  if(prt) PrintPFP("M3D", slc, pfp, true);
1760  if(!didSplit && shared.size() != ms.TjIDs.size()) {
1761  // Try to repair the PFParticle by merging the Tj that was in the match list but
1762  // wasn't attached to the vertex. Hopefully there aren't more than one...
1763  auto tjNotInVx = SetDifference(ms.TjIDs, shared);
1764  }
1765  AnalyzePFP(slc, pfp, prt);
1766  if(!StorePFP(slc, pfp)) continue;
1767  if(pfp.TjIDs != saveTjIDs) {
1768  // v3TjIDs is wrong if Tjs were merged so re-make it.
1769  auto tmp = GetVtxTjIDs(slc, vx3, score);
1770  v3TjIDs.clear();
1771  // then re-build it
1772  for(auto tjid : tmp) {
1773  auto& tj = slc.tjs[tjid - 1];
1774  if(!tj.AlgMod[kMat3D]) v3TjIDs.push_back(tjid);
1775  } // tjid
1776  if(v3TjIDs.size() < 2) break;
1777  } // pfp.TjIDs != saveTjIDs
1778  ms.Count = 0;
1779  // clobber MatchStructs that use the Tjs in this pfp
1780  for(auto& allms : slc.matchVec) {
1781  auto mfpfp = SetIntersection(allms.TjIDs, pfp.TjIDs);
1782  if(!mfpfp.empty()) allms.Count = 0;
1783  } // allms
1784  auto leftover = SetDifference(v3TjIDs, pfp.TjIDs);
1785  if(prt) {
1786  mf::LogVerbatim myprt("TC");
1787  myprt<<" leftover";
1788  for(auto tjid : leftover) myprt<<" T"<<tjid;
1789  }
1790  if(leftover.size() < 2) break;
1791  // keep looking using the leftovers
1792  v3TjIDs = leftover;
1793  } // ims
1794  if(v3TjIDs.size() > 1 && v3TjIDs.size() <= slc.nPlanes) {
1795  // a last-ditch attempt
1796  PFPStruct pfp = CreatePFP(slc);
1797  // put the available leftovers in
1798  for(auto& tjid : v3TjIDs) {
1799  auto& tj = slc.tjs[tjid - 1];
1800  if(tj.AlgMod[kMat3D]) continue;
1801  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
1802  pfp.TjIDs.push_back(tjid);
1803  } // tjid
1804  if(pfp.TjIDs.size() < 2) continue;
1805  pfp.Vx3ID[0] = vx3.ID;
1806  if(!DefinePFP("M3DVTj2", slc, pfp, prt)) continue;
1807  Split3DKink(slc, pfp, 1, prt);
1808  AnalyzePFP(slc, pfp, prt);
1809  if(prt) PrintPFP("left", slc, pfp, true);
1810  if(!StorePFP(slc, pfp)) continue;
1811  }
1812  } // ims
1813  } // Match3DVtxTjs
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
int PDGCodeVote(TCSlice &slc, std::vector< int > &tjIDs, bool prt)
Definition: Utils.cxx:372
unsigned int index
Definition: StepUtils.cxx:5
TCConfig tcc
Definition: DataStructs.cxx:6
void PrintPFP(std::string someText, TCSlice &slc, const PFPStruct &pfp, bool printHeader)
Definition: Utils.cxx:5587
Float_t tmp
Definition: plot.C:37
bool Split3DKink(TCSlice &slc, PFPStruct &pfp, double sep, bool prt)
Definition: PFPUtils.cxx:1811
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:231
bool DefinePFP(std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:2233
bool AnalyzePFP(TCSlice &slc, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:2421
float val
Definition: StepUtils.cxx:6
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
PFPStruct CreatePFP(TCSlice &slc)
Definition: PFPUtils.cxx:1973
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:3243
std::vector< T > SetDifference(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:253
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:466
bool StorePFP(TCSlice &slc, PFPStruct &pfp)
Definition: PFPUtils.cxx:2749
bool valDecreasing(SortEntry c1, SortEntry c2)
Definition: Utils.cxx:14
unsigned short tca::MatchVecIndex ( TCSlice slc,
int  tjID 
)

Definition at line 1138 of file Utils.cxx.

References tca::TCSlice::matchVec.

1139  {
1140  // returns the index into the tjs.matchVec vector of the first 3D match that
1141  // includes tjID
1142  for(unsigned int ims = 0; ims < slc.matchVec.size(); ++ims) {
1143  const auto& ms = slc.matchVec[ims];
1144  if(std::find(ms.TjIDs.begin(), ms.TjIDs.end(), tjID) != ms.TjIDs.end()) return ims;
1145  } // indx
1146  return USHRT_MAX;
1147  } // MatchVecIndex
float tca::MaxChargeAsymmetry ( TCSlice slc,
std::vector< int > &  tjIDs 
)

Definition at line 340 of file Utils.cxx.

References DecodeCTP(), tca::TCSlice::nPlanes, geo::PlaneID::Plane, tca::TCSlice::tjs, and UpdateTjChgProperties().

341  {
342  // calculates the maximum charge asymmetry in all planes using the supplied list of Tjs
343  if(tjIDs.size() < 2) return 1;
344  std::vector<float> plnchg(slc.nPlanes);
345  for(auto tjid : tjIDs) {
346  if(tjid <= 0 || tjid > (int)slc.tjs.size()) return 1;
347  auto& tj = slc.tjs[tjid - 1];
348  if(tj.TotChg == 0) UpdateTjChgProperties("MCA", slc, tj, false);
349  unsigned short plane = DecodeCTP(tj.CTP).Plane;
350  plnchg[plane] += tj.TotChg;
351  } // tjid
352  float aveChg = 0;
353  float cnt = 0;
354  for(unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
355  if(plnchg[plane] == 0) continue;
356  aveChg += plnchg[plane];
357  ++cnt;
358  } // plane
359  if(cnt < 2) return 1;
360  aveChg /= cnt;
361  float maxAsym = 0;
362  for(unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
363  // ignore zeros
364  if(plnchg[plane] == 0) continue;
365  float asym = std::abs(plnchg[plane] - aveChg) / (plnchg[plane] + aveChg);
366  if(asym > maxAsym) maxAsym = asym;
367  } // plane
368  return maxAsym;
369  } // MaxChargeAsymmetry
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3196
geo::PlaneID DecodeCTP(CTP_t CTP)
float tca::MaxHitDelta ( TCSlice slc,
Trajectory tj 
)

Definition at line 2734 of file Utils.cxx.

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

Referenced by CheckHiMultUnusedHits(), and FillGaps().

2735  {
2736  float delta, md = 0;
2737  unsigned short ii;
2738  unsigned int iht;
2739  for(auto& tp : tj.Pts) {
2740  for(ii = 0; ii < tp.Hits.size(); ++ii) {
2741  if(!tp.UseHit[ii]) continue;
2742  iht = tp.Hits[ii];
2743  delta = PointTrajDOCA(slc, iht, tp);
2744  if(delta > md) md = delta;
2745  } // ii
2746  } // pts
2747  return md;
2748  } // MaxHitDelta
float PointTrajDOCA(TCSlice &slc, float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2280
float tca::MaxTjLen ( TCSlice slc,
std::vector< int > &  tjIDs 
)

Definition at line 2322 of file Utils.cxx.

References PosSep2(), and tca::TCSlice::tjs.

Referenced by DefinePFP(), and FindPFParticles().

2323  {
2324  // returns the length of the longest Tj in the supplied list
2325  if(tjIDs.empty()) return 0;
2326  float maxLen = 0;
2327  for(auto tjid : tjIDs) {
2328  if(tjid < 1 || tjid > (int)slc.tjs.size()) continue;
2329  auto& tj = slc.tjs[tjid - 1];
2330  float sep2 = PosSep2(tj.Pts[tj.EndPt[0]].Pos, tj.Pts[tj.EndPt[1]].Pos);
2331  if(sep2 > maxLen) maxLen = sep2;
2332  } // tj
2333  return sqrt(maxLen);
2334  } // MaxTjLen
float PosSep2(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2359
short tca::MCSMom ( TCSlice slc,
const std::vector< int > &  tjIDs 
)

Definition at line 2914 of file Utils.cxx.

References tca::TCSlice::tjs.

Referenced by CheckTraj(), DefinePFP(), DotProd(), FillGaps(), FindCots(), FindHammerVertices2(), FindParent(), FindPFParticles(), FindSoftKink(), Forecast(), GottaKink(), IsGhost(), MergeNearby2DShowers(), MergePFPTjs(), MergeSubShowersTj(), UpdateStiffEl(), and UpdateTraj().

2915  {
2916  // Find the average MCSMom of the trajectories
2917  if(tjIDs.empty()) return 0;
2918  float summ = 0;
2919  float suml = 0;
2920  for(auto tjid : tjIDs) {
2921  auto& tj = slc.tjs[tjid - 1];
2922  float npts = tj.EndPt[1] - tj.EndPt[0] + 1;
2923  summ += npts * tj.MCSMom;
2924  suml += npts;
2925  } // tjid
2926  return (short)(summ / suml);
2927  } // MCSMom
short tca::MCSMom ( TCSlice slc,
Trajectory tj 
)

Definition at line 2930 of file Utils.cxx.

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

2931  {
2932  return MCSMom(slc, tj, tj.EndPt[0], tj.EndPt[1]);
2933  } // MCSMom
short MCSMom(TCSlice &slc, Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:2936
short tca::MCSMom ( TCSlice slc,
Trajectory tj,
unsigned short  firstPt,
unsigned short  lastPt 
)

Definition at line 2936 of file Utils.cxx.

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

Referenced by MCSMom(), PrintP(), PrintPFP(), and SplitTraj().

2937  {
2938  // Estimate the trajectory momentum using Multiple Coulomb Scattering ala PDG RPP
2939 
2940  if(firstPt == lastPt) return 0;
2941  if(firstPt > lastPt) std::swap(firstPt, lastPt);
2942 
2943  firstPt = NearestPtWithChg(slc, tj, firstPt);
2944  lastPt = NearestPtWithChg(slc, tj, lastPt);
2945  if(firstPt >= lastPt) return 0;
2946 
2947  if(firstPt < tj.EndPt[0]) return 0;
2948  if(lastPt > tj.EndPt[1]) return 0;
2949  // Can't do this with only 2 points
2950  if(NumPtsWithCharge(slc, tj, false, firstPt, lastPt) < 3) return 0;
2951  // Ignore junk Tjs
2952  if(tj.AlgMod[kJunkTj]) return 0;
2953 
2954  double tjLen = TrajPointSeparation(tj.Pts[firstPt], tj.Pts[lastPt]);
2955  if(tjLen < 1) return 0;
2956  // mom calculated in MeV
2957  double thetaRMS = MCSThetaRMS(slc, tj, firstPt, lastPt);
2958  if(thetaRMS < 0.001) return 999;
2959  double mom = 13.8 * sqrt(tjLen / 14) / thetaRMS;
2960  if(mom > 999) mom = 999;
2961  return (short)mom;
2962  } // MCSMom
float TrajPointSeparation(TrajPoint &tp1, TrajPoint &tp2)
Definition: Utils.cxx:2368
unsigned short NearestPtWithChg(TCSlice &slc, Trajectory &tj, unsigned short thePt)
Definition: Utils.cxx:2966
double MCSThetaRMS(TCSlice &slc, Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:2998
void swap(art::HLTGlobalStatus &lhs, art::HLTGlobalStatus &rhs)
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:1871
float tca::MCSThetaRMS ( TCSlice slc,
Trajectory tj 
)

Definition at line 2984 of file Utils.cxx.

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

Referenced by DotProd(), EndMerge(), and GottaKink().

2985  {
2986  // This returns the MCS scattering angle expected for one WSE unit of travel along the trajectory.
2987  // It is used to define kink and vertex cuts. This should probably be named something different to
2988  // prevent confusion
2989 
2990  float tps = TrajPointSeparation(tj.Pts[tj.EndPt[0]], tj.Pts[tj.EndPt[1]]);
2991  if(tps < 1) return 1;
2992 
2993  return MCSThetaRMS(slc, tj, tj.EndPt[0], tj.EndPt[1]) / sqrt(tps);
2994 
2995  } // MCSThetaRMS
float TrajPointSeparation(TrajPoint &tp1, TrajPoint &tp2)
Definition: Utils.cxx:2368
double MCSThetaRMS(TCSlice &slc, Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:2998
double tca::MCSThetaRMS ( TCSlice slc,
Trajectory tj,
unsigned short  firstPt,
unsigned short  lastPt 
)

Definition at line 2998 of file Utils.cxx.

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

Referenced by MCSMom(), and MCSThetaRMS().

2999  {
3000  // This returns the MCS scattering angle expected for the length of the trajectory
3001  // spanned by firstPt to lastPt. It is used primarily to calculate MCSMom
3002 
3003  if(firstPt < tj.EndPt[0]) return 1;
3004  if(lastPt > tj.EndPt[1]) return 1;
3005 
3006  firstPt = NearestPtWithChg(slc, tj, firstPt);
3007  lastPt = NearestPtWithChg(slc, tj, lastPt);
3008  if(firstPt >= lastPt) return 1;
3009 
3010  double sigmaS;
3011  unsigned short cnt;
3012  TjDeltaRMS(slc, tj, firstPt, lastPt, sigmaS, cnt);
3013  if(sigmaS < 0) return 1;
3014  // BB 11/26/2018 A bad idea
3015  // require that cnt is a significant fraction of the total number of charged points
3016  // so that we don't get erroneously high MCSMom when there are large gaps.
3017  // This is the number of points expected in the count if there are no gaps
3018 // unsigned short numPts = lastPt - firstPt - 1;
3019  // return the previously calculated value of MCSMom
3020 // if(numPts > 5 && cnt < 0.7 * numPts) return tj.MCSMom;
3021  double tjLen = TrajPointSeparation(tj.Pts[firstPt], tj.Pts[lastPt]);
3022  if(tjLen < 1) return 1;
3023  // Theta_o = 4 * sqrt(3) * sigmaS / path
3024  return (6.8 * sigmaS / tjLen);
3025 
3026  } // MCSThetaRMS
void TjDeltaRMS(TCSlice &slc, Trajectory &tj, unsigned short firstPt, unsigned short lastPt, double &rms, unsigned short &cnt)
Definition: Utils.cxx:3029
float TrajPointSeparation(TrajPoint &tp1, TrajPoint &tp2)
Definition: Utils.cxx:2368
unsigned short NearestPtWithChg(TCSlice &slc, Trajectory &tj, unsigned short thePt)
Definition: Utils.cxx:2966
bool tca::MergeAndStore ( TCSlice slc,
unsigned int  itj1,
unsigned int  itj2,
bool  doPrt 
)

Not allowed

Definition at line 4095 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::EndPt, GetPFPIndex(), HasDuplicateHits(), tca::Trajectory::ID, kBragg, kDeltaRay, kHaloTj, 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(), tca::TCSlice::tjs, TrajPointTrajDOCA(), UpdateMatchStructs(), tca::Trajectory::VtxID, tca::TCSlice::vtxs, and tca::Trajectory::WorkID.

Referenced by ChkVxTjs(), DotProd(), EndMerge(), and MergeTjIntoPFP().

4096  {
4097  // Merge the two trajectories in allTraj and store them. Returns true if it was successfull.
4098  // Merging is done between the end (end = 1) of tj1 and the beginning (end = 0) of tj2. This function preserves the
4099  // AlgMod state of itj1.
4100  // The itj1 -> itj2 merge order is reversed if end1 of itj2 is closer to end0 of itj1
4101 
4102  if(itj1 > slc.tjs.size() - 1) return false;
4103  if(itj2 > slc.tjs.size() - 1) return false;
4104  if(slc.tjs[itj1].AlgMod[kKilled] || slc.tjs[itj2].AlgMod[kKilled]) return false;
4105  if(slc.tjs[itj1].AlgMod[kHaloTj] || slc.tjs[itj2].AlgMod[kHaloTj]) return false;
4106 
4107  // Merging shower Tjs requires merging the showers as well.
4108  if(slc.tjs[itj1].AlgMod[kShowerTj] || slc.tjs[itj2].AlgMod[kShowerTj]) return MergeShowerTjsAndStore(slc, itj1, itj2, doPrt);
4109 
4110  // Ensure that the order of 3D-matched Tjs is consistent with the convention that
4111  unsigned short pfp1 = GetPFPIndex(slc, slc.tjs[itj1].ID);
4112  unsigned short pfp2 = GetPFPIndex(slc, slc.tjs[itj2].ID);
4113  if(pfp1 != USHRT_MAX || pfp2 != USHRT_MAX) {
4114  if(pfp1 != USHRT_MAX && pfp2 != USHRT_MAX) {
4115 // std::cout<<"MAS: Both tjs are used in a PFParticle. Need PFParticle merging code to do this. pfps size "<<slc.pfps.size()<<"\n";
4116  return false;
4117  }
4118  // Swap so that the order of tj1 is preserved. Tj2 may be reversed to be consistent
4119  if(pfp1 == USHRT_MAX) std::swap(itj1, itj2);
4120  } // one or both used in a PFParticle
4121 
4122  // make copies so they can be trimmed as needed
4123  Trajectory tj1 = slc.tjs[itj1];
4124  Trajectory tj2 = slc.tjs[itj2];
4125 
4126  // ensure that these are in the same step order
4127  if(tj2.StepDir != tj1.StepDir) ReverseTraj(slc, tj2);
4128 
4129  Point2_t tp1e0 = tj1.Pts[tj1.EndPt[0]].Pos;
4130  Point2_t tp1e1 = tj1.Pts[tj1.EndPt[1]].Pos;
4131  Point2_t tp2e0 = tj2.Pts[tj2.EndPt[0]].Pos;
4132  Point2_t tp2e1 = tj2.Pts[tj2.EndPt[1]].Pos;
4133 
4134  if(doPrt) {
4135  mf::LogVerbatim("TC")<<"MergeAndStore: tj1 T"<<tj1.ID<<" tj2 T"<<tj2.ID<<" at merge points "<<PrintPos(slc, tp1e1)<<" "<<PrintPos(slc, tp2e0);
4136  }
4137 
4138  // swap the order so that abs(tj1end1 - tj2end0) is less than abs(tj2end1 - tj1end0)
4139  if(PosSep2(tp1e1, tp2e0) > PosSep2(tp2e1, tp1e0)) {
4140  std::swap(tj1, tj2);
4141  std::swap(tp1e0, tp2e0);
4142  std::swap(tp1e1, tp2e1);
4143  if(doPrt) mf::LogVerbatim("TC")<<" swapped the order. Merge points "<<PrintPos(slc, tp1e1)<<" "<<PrintPos(slc, tp2e0);
4144  }
4145 
4146  // Here is what we are looking for, where - indicates a TP with charge.
4147  // Note that this graphic is in the stepping direction (+1 = +wire direction)
4148  // tj1: 0------------1
4149  // tj2: 0-----------1
4150  // Another possibility with overlap
4151  // tj1: 0-------------1
4152  // tj2: 0--------------1
4153 
4154  if(tj1.StepDir > 1) {
4155  // Not allowed
4156  // tj1: 0---------------------------1
4157  // tj2: 0------1
4158  if(tp2e0[0] > tp1e0[0] && tp2e1[0] < tp1e1[0]) return false;
4160  // tj1: 0------1
4161  // tj2: 0---------------------------1
4162  if(tp1e0[0] > tp2e0[0] && tp1e1[0] < tp2e1[0]) return false;
4163  } else {
4164  // same as above but with ends reversed
4165  if(tp2e1[0] > tp1e1[0] && tp2e0[0] < tp1e0[0]) return false;
4166  if(tp1e1[0] > tp2e1[0] && tp1e0[0] < tp2e0[0]) return false;
4167  }
4168 
4169  if(tj1.VtxID[1] > 0 && tj2.VtxID[0] == tj1.VtxID[1]) {
4170  auto& vx = slc.vtxs[tj1.VtxID[1] - 1];
4171  if(!MakeVertexObsolete("MAS", slc, vx, false)) {
4172  if(doPrt) mf::LogVerbatim("TC")<<"MergeAndStore: Found a good vertex between Tjs "<<tj1.VtxID[1]<<" No merging";
4173  return false;
4174  }
4175  }
4176 
4177  if(tj1.StopFlag[1][kBragg]) {
4178  if(doPrt) mf::LogVerbatim("TC")<<"MergeAndStore: You are merging the end of trajectory T"<<tj1.ID<<" with a Bragg peak. Not merging\n";
4179  return false;
4180  }
4181 
4182  // remove any points at the end of tj1 that don't have used hits
4183  tj1.Pts.resize(tj1.EndPt[1] + 1);
4184 
4185  // determine if they overlap by finding the point on tj2 that is closest
4186  // to the end point of tj1.
4187  TrajPoint& endtj1TP = tj1.Pts[tj1.EndPt[1]];
4188  // Set minSep large so that dead wire regions are accounted for
4189  float minSep = 1000;
4190  unsigned short tj2ClosePt = 0;
4191  // Note that TrajPointTrajDOCA only considers TPs that have charge
4192  TrajPointTrajDOCA(slc, endtj1TP, tj2, tj2ClosePt, minSep);
4193  if(doPrt) mf::LogVerbatim("TC")<<" Merge point tj1 "<<PrintPos(slc, endtj1TP)<<" tj2ClosePt "<<tj2ClosePt<<" Pos "<<PrintPos(slc, tj2.Pts[tj2ClosePt]);
4194  // check for full overlap
4195  if(tj2ClosePt > tj2.EndPt[1]) return false;
4196 
4197  // The approach is to append tj2 to tj1, store tj1 as a new trajectory,
4198  // and re-assign all hits to the new trajectory
4199 
4200  // First ensure that any hit will appear only once in the merged trajectory in the overlap region
4201  // whether it is used or unused. The point on tj2 where the merge will begin, tj2ClosePt, will be
4202  // increased until this condition is met.
4203  // Make a temporary vector of tj1 hits in the end points for simpler searching
4204  std::vector<unsigned int> tj1Hits;
4205  for(unsigned short ii = 0; ii < tj1.Pts.size(); ++ii) {
4206  // only go back a few points in tj1
4207  if(ii > 10) break;
4208  unsigned short ipt = tj1.Pts.size() - 1 - ii;
4209  tj1Hits.insert(tj1Hits.end(), tj1.Pts[ipt].Hits.begin(), tj1.Pts[ipt].Hits.end());
4210  if(ipt == 0) break;
4211  } // ii
4212 
4213  bool bumpedPt = true;
4214  while(bumpedPt) {
4215  bumpedPt = false;
4216  for(unsigned short ii = 0; ii < tj2.Pts[tj2ClosePt].Hits.size(); ++ii) {
4217  unsigned int iht = tj2.Pts[tj2ClosePt].Hits[ii];
4218  if(std::find(tj1Hits.begin(), tj1Hits.end(), iht) != tj1Hits.end()) bumpedPt = true;
4219  } // ii
4220  if(bumpedPt && tj2ClosePt < tj2.EndPt[1]) {
4221  ++tj2ClosePt;
4222  } else {
4223  break;
4224  }
4225  } // bumpedPt
4226  if(doPrt) mf::LogVerbatim("TC")<<" revised tj2ClosePt "<<tj2ClosePt;
4227  // append tj2 hits to tj1
4228 
4229  tj1.Pts.insert(tj1.Pts.end(), tj2.Pts.begin() + tj2ClosePt, tj2.Pts.end());
4230  // re-define the end points
4231  SetEndPoints(tj1);
4232  tj1.StopFlag[1] = tj2.StopFlag[1];
4233 
4234  // A more exhaustive check that hits only appear once
4235  if(HasDuplicateHits(slc, tj1, doPrt)) {
4236  if(doPrt) {
4237  mf::LogVerbatim("TC")<<"MergeAndStore found duplicate hits. Coding error";
4238  PrintTrajectory("MAS", slc, tj1, USHRT_MAX);
4239  PrintTrajectory("tj1", slc, slc.tjs[itj1], USHRT_MAX);
4240  PrintTrajectory("tj2", slc, slc.tjs[itj2], USHRT_MAX);
4241  }
4242  return false;
4243  }
4244  if(tj2.VtxID[1] > 0) {
4245  // move the end vertex of tj2 to the end of tj1
4246  tj1.VtxID[1] = tj2.VtxID[1];
4247  }
4248  // Transfer some of the AlgMod bits
4249  if(tj2.AlgMod[kMichel]) tj1.AlgMod[kMichel] = true;
4250  if(tj2.AlgMod[kDeltaRay]) {
4251  tj1.AlgMod[kDeltaRay] = true;
4252  tj1.ParentID = tj2.ParentID;
4253  }
4254  // keep track of the IDs before they are clobbered
4255  int tj1ID = tj1.ID;
4256  int tj2ID = tj2.ID;
4257  // kill the original trajectories
4258  MakeTrajectoryObsolete(slc, itj1);
4259  MakeTrajectoryObsolete(slc, itj2);
4260  // Do this so that StoreTraj keeps the correct WorkID (of itj1)
4261  tj1.ID = tj1.WorkID;
4262  SetPDGCode(slc, tj1, true);
4263  if(!StoreTraj(slc, tj1)) return false;
4264  int newTjID = slc.tjs.size();
4265  // Use the ParentID to trace which new Tj is superseding the merged ones
4266  tj1.ParentID = newTjID;
4267  tj2.ParentID = newTjID;
4268  // update match structs if they exist
4269  UpdateMatchStructs(slc, tj1.ID, newTjID);
4270  UpdateMatchStructs(slc, tj2.ID, newTjID);
4271  if(doPrt) mf::LogVerbatim("TC")<<" MAS success. Created T"<<newTjID;
4272  // Transfer the ParentIDs of any other Tjs that refer to Tj1 and Tj2 to the new Tj
4273  for(auto& tj : slc.tjs) if(tj.ParentID == tj1ID || tj.ParentID == tj2ID) tj.ParentID = newTjID;
4274 
4275  return true;
4276  } // MergeAndStore
void PrintTrajectory(std::string someText, TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:5455
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:3120
void TrajPointTrajDOCA(TCSlice &slc, TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
Definition: Utils.cxx:2155
bool StoreTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:1175
void SetPDGCode(TCSlice &slc, Trajectory &tj, bool tjDone)
Definition: Utils.cxx:3802
std::string PrintPos(TCSlice &slc, const Point2_t &pos)
Definition: Utils.cxx:5718
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
bool MergeShowerTjsAndStore(TCSlice &slc, unsigned short istj, unsigned short jstj, bool prt)
Definition: TCShower.cxx:3060
unsigned short GetPFPIndex(TCSlice &slc, int tjID)
Definition: Utils.cxx:1127
void UpdateMatchStructs(TCSlice &slc, int oldTj, int newTj)
Definition: PFPUtils.cxx:160
void MakeTrajectoryObsolete(TCSlice &slc, unsigned int itj)
Definition: Utils.cxx:1922
void ReverseTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:2751
float PosSep2(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2359
void swap(art::HLTGlobalStatus &lhs, art::HLTGlobalStatus &rhs)
bool HasDuplicateHits(TCSlice &slc, Trajectory const &tj, bool prt)
Definition: Utils.cxx:2469
void tca::MergeGhostTjs ( TCSlice slc,
CTP_t  inCTP 
)

Definition at line 1955 of file Utils.cxx.

References kAllHits, kHaloTj, kKilled, kMrgGhost, PutTrajHitsInVector(), tca::TCSlice::slHits, tcc, tca::TCSlice::tjs, and tca::TCConfig::useAlg.

1956  {
1957  // Merges short Tjs that share many hits with a longer Tj
1958  if(!tcc.useAlg[kMrgGhost]) return;
1959 
1960  for(auto& shortTj : slc.tjs) {
1961  if(shortTj.AlgMod[kKilled] || shortTj.AlgMod[kHaloTj]) continue;
1962  if(shortTj.CTP != inCTP) continue;
1963  unsigned short spts = shortTj.EndPt[1] - shortTj.EndPt[0];
1964  if(spts > 20) continue;
1965  // ignore delta rays
1966  if(shortTj.PDGCode == 11) continue;
1967  // ignore InShower Tjs
1968  if(shortTj.SSID > 0) continue;
1969  auto tjhits = PutTrajHitsInVector(shortTj, kAllHits);
1970  if(tjhits.empty()) continue;
1971  std::vector<int> tids;
1972  std::vector<unsigned short> tcnt;
1973  for(auto iht : tjhits) {
1974  auto& hit = slc.slHits[iht];
1975  if(hit.InTraj <= 0) continue;
1976  if((unsigned int)hit.InTraj > slc.tjs.size()) continue;
1977  if(hit.InTraj == shortTj.ID) continue;
1978  unsigned short indx = 0;
1979  for(indx = 0; indx < tids.size(); ++indx) if(hit.InTraj == tids[indx]) break;
1980  if(indx == tids.size()) {
1981  tids.push_back(hit.InTraj);
1982  tcnt.push_back(1);
1983  } else {
1984  ++tcnt[indx];
1985  }
1986  } // iht
1987  if(tids.empty()) continue;
1988  // find the max count for Tjs that are longer than this one
1989  unsigned short maxcnt = 0;
1990  for(unsigned short indx = 0; indx < tids.size(); ++indx) {
1991  if(tcnt[indx] > maxcnt) {
1992  auto& ltj = slc.tjs[tids[indx] - 1];
1993  unsigned short lpts = ltj.EndPt[1] - ltj.EndPt[0];
1994  if(lpts < spts) continue;
1995  maxcnt = tcnt[indx];
1996  }
1997  } // indx
1998  float hitFrac = (float)maxcnt / (float)tjhits.size();
1999  if(hitFrac < 0.1) continue;
2000  } // shortTj
2001  } // MergeGhostTjs
TCConfig tcc
Definition: DataStructs.cxx:6
std::vector< unsigned int > PutTrajHitsInVector(Trajectory const &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2416
Detector simulation of raw signals on wires.
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
void tca::MergeNearby2DShowers ( std::string  inFcnLabel,
TCSlice slc,
const CTP_t inCTP,
bool  prt 
)

Definition at line 2374 of file TCShower.cxx.

References AddTj(), tca::Trajectory::AlgMod, ChkAssns(), tca::TCSlice::cots, tca::ShowerStruct::CTP, DontCluster(), GetAssns(), tca::ShowerStruct::ID, tca::TCSlice::ID, kMat3D, kMergeNrShowers, MCSMom(), MergeShowersAndStore(), tca::ShowerStruct::NearTjIDs, tca::TCSlice::pfps, SetIntersection(), tca::ShowerStruct::ShowerTjID, ss, tcc, tca::ShowerStruct::TjIDs, tca::TCSlice::tjs, and tca::TCConfig::useAlg.

Referenced by FindShowers3D().

2375  {
2376  if(!tcc.useAlg[kMergeNrShowers]) return;
2377  if(slc.cots.empty()) return;
2378 
2379  std::string fcnLabel = inFcnLabel + ".MNS";
2380 
2381  if(prt) {
2382  mf::LogVerbatim myprt("TC");
2383  myprt<<fcnLabel<<" list";
2384  for(auto& ss : slc.cots) {
2385  if(ss.CTP != inCTP) continue;
2386  if(ss.ID == 0) continue;
2387  myprt<<" ss.ID "<<ss.ID<<" NearTjs";
2388  for(auto& id : ss.NearTjIDs) myprt<<" "<<id;
2389  myprt<<"\n";
2390  }
2391  } // prt
2392 
2393  bool keepMerging = true;
2394  while(keepMerging) {
2395  keepMerging = false;
2396  for(unsigned short ci1 = 0; ci1 < slc.cots.size() - 1; ++ci1) {
2397  ShowerStruct& ss1 = slc.cots[ci1];
2398  if(ss1.CTP != inCTP) continue;
2399  if(ss1.ID == 0) continue;
2400  if(ss1.TjIDs.empty()) continue;
2401  // put the inshower tjs and the nearby tjs into one list
2402  std::vector<int> ss1list = ss1.TjIDs;
2403  ss1list.insert(ss1list.end(), ss1.NearTjIDs.begin(), ss1.NearTjIDs.end());
2404  for(unsigned short ci2 = ci1 + 1; ci2 < slc.cots.size(); ++ci2) {
2405  ShowerStruct& ss2 = slc.cots[ci2];
2406  if(ss2.CTP != inCTP) continue;
2407  if(ss2.ID == 0) continue;
2408  if(ss2.TjIDs.empty()) continue;
2409  if(DontCluster(slc, ss1.TjIDs, ss2.TjIDs)) continue;
2410  std::vector<int> ss2list = ss2.TjIDs;
2411  ss2list.insert(ss2list.end(), ss2.NearTjIDs.begin(), ss2.NearTjIDs.end());
2412  std::vector<int> shared = SetIntersection(ss1list, ss2list);
2413  if(shared.empty()) continue;
2414  if(prt) {
2415  mf::LogVerbatim myprt("TC");
2416  myprt<<fcnLabel<<" Merge 2S"<<ss2.ID<<" into 2S"<<ss1.ID<<"? shared nearby:";
2417  for(auto tjid : shared) myprt<<" T"<<tjid;
2418  } // prt
2419  // add the shared Tjs to ss1 if they meet the requirements
2420  bool doMerge = false;
2421  for(auto& tjID : shared) {
2422  bool inSS1 = (std::find(ss1.TjIDs.begin(), ss1.TjIDs.end(), tjID) != ss1.TjIDs.end());
2423  bool inSS2 = (std::find(ss2.TjIDs.begin(), ss2.TjIDs.end(), tjID) != ss2.TjIDs.end());
2424  if(inSS1 && !inSS2) doMerge = true;
2425  if(!inSS1 && inSS2) doMerge = true;
2426  // need to add it?
2427  if(inSS1 || inSS2) continue;
2428  auto& tj = slc.tjs[tjID - 1];
2429  // ignore long muons
2430  if(tj.PDGCode == 13 && tj.Pts.size() > 100 && tj.ChgRMS < 0.5) {
2431  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" T"<<tj.ID<<" looks like a muon. Don't add it";
2432  continue;
2433  }
2434  // see if it looks like a muon in 3D
2435  if(tj.AlgMod[kMat3D]) {
2436  auto TInP = GetAssns(slc, "T", tj.ID, "P");
2437  if(!TInP.empty()) {
2438  auto& pfp = slc.pfps[TInP[0] - 1];
2439  if(pfp.PDGCode == 13 && MCSMom(slc, pfp.TjIDs) > 500) continue;
2440  } // TInP not empty
2441  } // 3D matched
2442  if(AddTj(fcnLabel, slc, tjID, ss1, false, prt)) doMerge = true;
2443  } // tjID
2444  if(!doMerge) continue;
2445  if(MergeShowersAndStore(fcnLabel, slc, ss1.ID, ss2.ID, prt)) {
2446  Trajectory& stj = slc.tjs[ss1.ShowerTjID - 1];
2447  stj.AlgMod[kMergeNrShowers] = true;
2448  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" success";
2449  keepMerging = true;
2450  break;
2451  }
2452  } // ci2
2453  } // ci1
2454  } // keepMerging
2455 
2456  ChkAssns(fcnLabel, slc);
2457 
2458  } //MergeNearby2DShowers
bool AddTj(std::string inFcnLabel, TCSlice &slc, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1552
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4279
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4560
short MCSMom(TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2914
TCConfig tcc
Definition: DataStructs.cxx:6
Float_t ss
Definition: plot.C:23
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:231
bool DontCluster(TCSlice &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3313
bool MergeShowersAndStore(std::string inFcnLabel, TCSlice &slc, int icotID, int jcotID, bool prt)
Definition: TCShower.cxx:2985
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
void tca::MergeOverlap ( std::string  inFcnLabel,
TCSlice slc,
const CTP_t inCTP,
bool  prt 
)

Definition at line 2461 of file TCShower.cxx.

References tca::Trajectory::AlgMod, ChkAssns(), close(), tca::TCSlice::cots, DontCluster(), DotProd(), tca::TCSlice::ID, kMergeOverlap, MergeShowersAndStore(), PointInsideEnvelope(), PosSep(), PosSep2(), tca::TCConfig::showerTag, tcc, tca::TCSlice::tjs, and tca::TCConfig::useAlg.

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

2462  {
2463  // Merge showers whose envelopes overlap each other
2464 
2465  /*
2466  # 0 Mode (<= 0 OFF, 1 = find showers before 3D match, 2 = find showers after 3D match)
2467  # 1 Max Tj MCSMom for a shower tag
2468  # 2 Max separation
2469  # 3 Min energy (MeV)
2470  # 4 rms width factor
2471  # 5 Min shower 1/2 width (WSE units)
2472  # 6 Min total Tj Pts
2473  # 7 Min Tjs
2474  # 8 max parent FOM
2475  # 9 max direction FOM
2476  # 10 max aspect ratio
2477  # 11 Debug in CTP (>10 debug cotID + 10)
2478  */
2479 
2480  if(tcc.showerTag[2] <= 0) return;
2481  if(!tcc.useAlg[kMergeOverlap]) return;
2482  if(slc.cots.empty()) return;
2483 
2484  std::string fcnLabel = inFcnLabel + ".MO";
2485 
2486  // Require that the maximum separation is about two radiation lengths
2487  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" checking using separation cut "<<tcc.showerTag[2];
2488 
2489  float sepCut2 = tcc.showerTag[2] * tcc.showerTag[2];
2490 
2491  // Iterate if a merge is done
2492  bool didMerge = true;
2493  while(didMerge) {
2494  didMerge = false;
2495  // See if the envelopes overlap
2496  for(unsigned short ict = 0; ict < slc.cots.size() - 1; ++ict) {
2497  auto& iss = slc.cots[ict];
2498  if(iss.ID == 0) continue;
2499  if(iss.TjIDs.empty()) continue;
2500  if(iss.CTP != inCTP) continue;
2501  for(unsigned short jct = ict + 1; jct < slc.cots.size(); ++jct) {
2502  auto& jss = slc.cots[jct];
2503  if(jss.ID == 0) continue;
2504  if(jss.TjIDs.empty()) continue;
2505  if(jss.CTP != iss.CTP) continue;
2506  if(DontCluster(slc, iss.TjIDs, jss.TjIDs)) continue;
2507  bool doMerge = false;
2508  for(auto& ivx : iss.Envelope) {
2509  doMerge = PointInsideEnvelope(ivx, jss.Envelope);
2510  if(doMerge) break;
2511  } // ivx
2512  if(!doMerge) {
2513  for(auto& jvx : jss.Envelope) {
2514  doMerge = PointInsideEnvelope(jvx, iss.Envelope);
2515  if(doMerge) break;
2516  } // ivx
2517  }
2518  if(!doMerge) {
2519  // check proximity between the envelopes
2520  for(auto& ivx : iss.Envelope) {
2521  for(auto& jvx : jss.Envelope) {
2522  if(PosSep2(ivx, jvx) < sepCut2) {
2523  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Envelopes 2S"<<iss.ID<<" 2S"<<jss.ID<<" are close "<<PosSep(ivx, jvx)<<" cut "<<tcc.showerTag[2];
2524  doMerge = true;
2525  break;
2526  }
2527  } // jvx
2528  if(doMerge) break;
2529  } // ivx
2530  } // !domerge
2531  if(!doMerge) continue;
2532  // check the relative positions and angle differences. Determine which tps are the
2533  // closest. Don't merge if the closest points are at the shower start and the angle
2534  // difference is large
2535  unsigned short iClosePt = 0;
2536  unsigned short jClosePt = 0;
2537  float close = 1E6;
2538  auto& istj = slc.tjs[iss.ShowerTjID - 1];
2539  auto& jstj = slc.tjs[jss.ShowerTjID - 1];
2540  for(unsigned short ipt = 0; ipt < 3; ++ipt) {
2541  for(unsigned short jpt = 0; jpt < 3; ++jpt) {
2542  float sep = PosSep2(istj.Pts[ipt].Pos, jstj.Pts[jpt].Pos);
2543  if(sep < close) {
2544  close = sep;
2545  iClosePt = ipt;
2546  jClosePt = jpt;
2547  }
2548  } // jpt
2549  } // ipt
2550  float costh = DotProd(istj.Pts[0].Dir, jstj.Pts[0].Dir);
2551  if(iClosePt == 0 && jClosePt == 0 && costh < 0.955) {
2552  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" showers are close at the start points with costh "<<costh<<". Don't merge";
2553  continue;
2554  }
2555  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Merge "<<iss.ID<<" and "<<jss.ID;
2556  if(MergeShowersAndStore(fcnLabel, slc, iss.ID, jss.ID, prt)) {
2557  Trajectory& stj = slc.tjs[iss.ShowerTjID - 1];
2558  stj.AlgMod[kMergeOverlap] = true;
2559  didMerge = true;
2560  break;
2561  } else {
2562  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Merge failed";
2563  }
2564  } // jct
2565  } // ict
2566  } // didMerge
2567 
2568  ChkAssns(fcnLabel, slc);
2569 
2570  } // MergeOverlap
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4560
TCConfig tcc
Definition: DataStructs.cxx:6
bool DontCluster(TCSlice &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3313
std::vector< float > showerTag
[min MCSMom, max separation, min # Tj < separation] for a shower tag
Definition: DataStructs.h:474
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:2781
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1660
bool MergeShowersAndStore(std::string inFcnLabel, TCSlice &slc, int icotID, int jcotID, bool prt)
Definition: TCShower.cxx:2985
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:59
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
in close()
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
bool tca::MergePFPTjs ( TCSlice slc,
PFPStruct pfp,
bool  prt 
)

Definition at line 1203 of file PFPUtils.cxx.

References tca::Trajectory::AlgMod, geo::CryostatID::Cryostat, tca::Trajectory::CTP, DecodeCTP(), EncodeCTP(), evd::details::end(), tca::TCConfig::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(), tcc, tca::PFPStruct::TjIDs, tca::TCSlice::tjs, tca::PFPStruct::Tp3s, geo::TPCID::TPC, geo::GeometryCore::TPC(), tca::PFPStruct::TPCID, UpdateMatchStructs(), UpdateTp3s(), tca::Trajectory::VtxID, and tca::TCSlice::vtxs.

Referenced by DefinePFP().

1204  {
1205  // Checks the list of Tjs in pfp.TjIDs and merges those that are in
1206  // the same plane. This function uses the ordering of Tps which should
1207  // have been sorted
1208  if(pfp.TjIDs.empty()) return false;
1209  if(pfp.Tp3s.empty()) return false;
1210 
1211  geo::TPCGeo const& TPC = tcc.geom->TPC(pfp.TPCID);
1212  unsigned short nplanes = TPC.Nplanes();
1213 
1214  // see if anything needs to be done
1215  std::vector<unsigned short> cntInPln(nplanes);
1216  bool itsOK = true;
1217  for(auto tjid : pfp.TjIDs) {
1218  auto& tj = slc.tjs[tjid - 1];
1219  unsigned short plane = DecodeCTP(tj.CTP).Plane;
1220  ++cntInPln[plane];
1221  if(cntInPln[plane] > 1) itsOK = false;
1222  }
1223  if(itsOK) return true;
1224 
1225  // vector of tj IDs that will replace pfp.TjIDs
1226  std::vector<int> newTjIDs;
1227 
1228  if(prt) {
1229  mf::LogVerbatim myprt("TC");
1230  myprt<<"MergePFPTjs: P"<<pfp.ID<<" in";
1231  for(auto tjid : pfp.TjIDs) myprt<<" T"<<tjid;
1232  }
1233 
1234  for(unsigned short plane = 0; plane < nplanes; ++plane) {
1235  CTP_t inCTP = EncodeCTP(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
1236  // save the TjIDs as unsigned short to match with Tj2Pts
1237  std::vector<unsigned short> tjids;
1238  for(auto tjid : pfp.TjIDs) if(slc.tjs[tjid - 1].CTP == inCTP) tjids.push_back((unsigned short)tjid);
1239  // Only one tj in this plane. No need to merge
1240  if(tjids.size() == 1) {
1241  newTjIDs.push_back((int)tjids[0]);
1242  continue;
1243  }
1244  // no tjs in this plane
1245  if(tjids.size() == 0) continue;
1246  // find the first ID and ipt of Tjs in this plane as they are
1247  // encountered while iterating through Tp3s. This scheme assumes that the Tp3s have
1248  // been sorted by distance from the start and the Tjs are broken end-to-end. This
1249  // information will be used to determine if Tjs need to be reversed before inserting
1250  // the points in to the merged trajectory
1251  // Tj ID first ipt
1252  std::vector<std::array<unsigned short, 2>> firstPts;
1253  for(unsigned short itp3 = 0; itp3 < pfp.Tp3s.size(); ++itp3) {
1254  auto& tp3 = pfp.Tp3s[itp3];
1255  for(auto& tj2pt : tp3.Tj2Pts) {
1256  unsigned short tjIndx = 0;
1257  for(tjIndx = 0; tjIndx < tjids.size(); ++tjIndx) if(tj2pt.id == tjids[tjIndx]) break;
1258  if(tjIndx == tjids.size()) continue;
1259  // look for this tj in firstPts
1260  unsigned short firstPtsIndx = 0;
1261  for(firstPtsIndx = 0; firstPtsIndx < firstPts.size(); ++firstPtsIndx) if(tj2pt.id == firstPts[firstPtsIndx][0]) break;
1262  if(firstPtsIndx == firstPts.size()) {
1263  // not found so add it
1264  std::array<unsigned short, 2> firstPt {{tj2pt.id, tj2pt.ipt}};
1265  firstPts.push_back(firstPt);
1266  }
1267  } // tj2pt
1268  } // itp3
1269  if(firstPts.empty()) continue;
1270  // create a new merged trajectory
1271  Trajectory mtj;
1272  // give it a bogus ID
1273  mtj.ID = -6666;
1274  mtj.CTP = inCTP;
1275  mtj.StepDir = 1;
1276  bool first = true;
1277  for(auto firstPt : firstPts) {
1278  // make a copy so we can reverse it and drop it if the merge fails
1279  auto tj = slc.tjs[firstPt[0] - 1];
1280  unsigned short midPt = 0.5 * (tj.EndPt[0] + tj.EndPt[1]);
1281  if(firstPt[1] > midPt) ReverseTraj(slc, tj);
1282  // Transfer vertices to mtj
1283  if(first) {
1284  first = false;
1285  mtj.VtxID[0] = tj.VtxID[0];
1286  }
1287  mtj.VtxID[1] = tj.VtxID[1];
1288  // insert the points at the end
1289  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1290  auto& tp = tj.Pts[ipt];
1291  if(tp.Chg <= 0) continue;
1292  mtj.Pts.push_back(tp);
1293  }
1294  } // firstPt
1295  mtj.AlgMod[kMat3DMerge] = true;
1296  SetEndPoints(mtj);
1297  mtj.MCSMom = MCSMom(slc, mtj);
1298  SetPDGCode(slc, mtj, true);
1299  if(prt) {
1300  mf::LogVerbatim myprt("TC");
1301  myprt<<" P"<<pfp.ID<<" try to merge";
1302  for(auto tjid : tjids) {
1303  auto& tj = slc.tjs[tjid - 1];
1304  myprt<<" T"<<tjid<<" MCSMom "<<tj.MCSMom;
1305  }
1306  myprt<<" -> T"<<slc.tjs.size() + 1;
1307  myprt<<" MCSMom "<<mtj.MCSMom;
1308  }
1309  // kill the broken tjs and update the pfp TP3s
1310  for(auto tjid : tjids) {
1311  auto& tj = slc.tjs[tjid - 1];
1312  if(tj.SSID > 0) mtj.SSID = tj.SSID;
1313  MakeTrajectoryObsolete(slc, tjid - 1);
1314  }
1315  // save the new one
1316  if(!StoreTraj(slc, mtj)) {
1317  std::cout<<"MergePFPTjs: StoreTraj failed P"<<pfp.ID<<"\n";
1318  return false;
1319  }
1320  int newTjID = slc.tjs.size();
1321  newTjIDs.push_back(newTjID);
1322  // prepare to clobber vertices
1323  std::vector<unsigned short> vxlist;
1324  for(auto tjid : tjids) {
1325  // update the stored match struct and Tp3s
1326  UpdateMatchStructs(slc, tjid, newTjID);
1327  // Update the Tp3s of this pfp
1328  UpdateTp3s(slc, pfp, tjid, newTjID);
1329  auto& tj = slc.tjs[tjid - 1];
1330  for(unsigned short end = 0; end < 2; ++end) {
1331  if(tj.VtxID[end] == 0) continue;
1332  if(std::find(vxlist.begin(), vxlist.end(), tj.VtxID[end]) != vxlist.end()) {
1333  auto& vx2 = slc.vtxs[tj.VtxID[end] - 1];
1334 // std::cout<<"P"<<pfp.ID<<" Clobber 2V"<<vx2.ID<<"\n";
1335  MakeVertexObsolete("MPTJ", slc, vx2, true);
1336  } else {
1337  vxlist.push_back(tj.VtxID[end]);
1338  }
1339  } // end
1340  } // tjid
1341  } // plane
1342 
1343  pfp.TjIDs = newTjIDs;
1344 
1345  if(prt) {
1346  mf::LogVerbatim myprt("TC");
1347  myprt<<"MergePFPTjs: P"<<pfp.ID<<" out";
1348  for(auto tjid : pfp.TjIDs) myprt<<" T"<<tjid;
1349  PrintPFP("MPTJ", slc, pfp, true);
1350  }
1351  return true;
1352  } // MergePFPTjs
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:3120
short MCSMom(TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2914
TCConfig tcc
Definition: DataStructs.cxx:6
unsigned int Nplanes() const
Number of planes in this tpc.
Definition: TPCGeo.h:145
void PrintPFP(std::string someText, TCSlice &slc, const PFPStruct &pfp, bool printHeader)
Definition: Utils.cxx:5587
Geometry information for a single TPC.
Definition: TPCGeo.h:37
bool StoreTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:1175
void UpdateTp3s(TCSlice &slc, PFPStruct &pfp, int oldTj, int newTj)
Definition: PFPUtils.cxx:229
void UpdateMatchStructs(TCSlice &slc, int oldTj, int newTj)
Definition: PFPUtils.cxx:160
void MakeTrajectoryObsolete(TCSlice &slc, unsigned int itj)
Definition: Utils.cxx:1922
void SetPDGCode(TCSlice &slc, unsigned short itj, bool tjDone)
Definition: Utils.cxx:3795
const geo::GeometryCore * geom
Definition: DataStructs.h:493
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
void ReverseTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:2751
unsigned int CTP_t
Definition: DataStructs.h:41
geo::PlaneID DecodeCTP(CTP_t CTP)
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)
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
void tca::MergeShowerChain ( std::string  inFcnLabel,
TCSlice slc,
const CTP_t inCTP,
bool  prt 
)

Definition at line 2573 of file TCShower.cxx.

References ChkAssns(), tca::TCSlice::cots, tca::ShowerStruct::CTP, DontCluster(), tca::ShowerStruct::Energy, tca::ShowerStruct::ID, kMergeShChain, lessThan(), MakeBareTrajPoint(), MergeShowers(), PointTrajDOCA(), PosSep(), PrintPos(), tca::ShowerStruct::ShowerTjID, tcc, tca::ShowerStruct::TjIDs, tca::TCSlice::tjs, and tca::TCConfig::useAlg.

Referenced by FindShowers3D().

2574  {
2575  // Merge chains of 3 or more showers that lie on a line
2576 
2577  if(!tcc.useAlg[kMergeShChain]) return;
2578 
2579  std::string fcnLabel = inFcnLabel + ".MSC";
2580 
2581  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<": MergeShowerChain inCTP "<<inCTP;
2582 
2583  std::vector<int> sids;
2584  std::vector<TrajPoint> tpList;
2585  for(unsigned short ict = 0; ict < slc.cots.size(); ++ict) {
2586  ShowerStruct& iss = slc.cots[ict];
2587  if(iss.ID == 0) continue;
2588  if(iss.TjIDs.empty()) continue;
2589  if(iss.CTP != inCTP) continue;
2590  // ignore wimpy showers
2591  if(iss.Energy < 50) continue;
2592  // save the shower ID
2593  sids.push_back(iss.ID);
2594  // and the shower center TP
2595  tpList.push_back(slc.tjs[iss.ShowerTjID - 1].Pts[1]);
2596  } // ict
2597  if(sids.size() < 3) return;
2598 
2599  // sort by wire so the chain order is reasonable
2600  std::vector<SortEntry> sortVec(sids.size());
2601  for(unsigned short ii = 0; ii < sortVec.size(); ++ii) {
2602  sortVec[ii].index = ii;
2603  sortVec[ii].length = tpList[ii].Pos[0];
2604  }
2605  std::sort(sortVec.begin(), sortVec.end(), lessThan);
2606  auto tsids = sids;
2607  auto ttpList = tpList;
2608  for(unsigned short ii = 0; ii < sortVec.size(); ++ii) {
2609  unsigned short indx = sortVec[ii].index;
2610  sids[ii] = tsids[indx];
2611  tpList[ii] = ttpList[indx];
2612  }
2613 
2614  // TODO: These cuts should be generalized somehow
2615  float minSep = 150;
2616  float maxDelta = 30;
2617  for(unsigned short ii = 0; ii < sids.size() - 2; ++ii) {
2618  auto& iss = slc.cots[sids[ii] - 1];
2619  if(iss.ID == 0) continue;
2620  unsigned short jj = ii + 1;
2621  auto& jss = slc.cots[sids[jj] - 1];
2622  if(jss.ID == 0) continue;
2623  std::vector<int> chain;
2624  float sepij = PosSep(tpList[ii].Pos, tpList[jj].Pos);
2625  if(sepij > minSep) continue;
2626  bool skipit = DontCluster(slc, iss.TjIDs, jss.TjIDs);
2627  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" i2S"<<iss.ID<<" "<<PrintPos(slc, tpList[ii].Pos)<<" j2S"<<jss.ID<<" "<<PrintPos(slc, tpList[jj].Pos)<<" sepij "<<sepij<<" skipit? "<<skipit;
2628  if(skipit) continue;
2629  // draw a line between these points
2630  TrajPoint tp;
2631  MakeBareTrajPoint(slc, tpList[ii], tpList[jj], tp);
2632 // PrintTrajPoint("ij", slc, 0, 1, 0, tp);
2633  for(unsigned short kk = jj + 1; kk < sids.size(); ++kk) {
2634  auto& kss = slc.cots[sids[kk] - 1];
2635  if(kss.ID == 0) continue;
2636  if(DontCluster(slc, iss.TjIDs, kss.TjIDs)) continue;
2637  if(DontCluster(slc, jss.TjIDs, kss.TjIDs)) continue;
2638  float sepjk = PosSep(tpList[jj].Pos, tpList[kk].Pos);
2639  float delta = PointTrajDOCA(slc, tpList[kk].Pos[0], tpList[kk].Pos[1], tp);
2640  if(prt) {
2641  mf::LogVerbatim myprt("TC");
2642  myprt<<fcnLabel<<" k2S"<<kss.ID<<" "<<PrintPos(slc, tpList[kk].Pos)<<" sepjk "<<sepjk<<" delta "<<delta;
2643  if(sepjk > minSep || delta > maxDelta) {
2644  myprt<<" failed separation "<<minSep<<" or delta cut "<<maxDelta;
2645  } else {
2646  myprt<<" add to the chain";
2647  }
2648  } // prt
2649  if(sepjk > minSep || delta > maxDelta) {
2650  // clear a short chain?
2651  if(chain.size() > 2) {
2652  // merge this chain
2653  int newID = MergeShowers(fcnLabel, slc, chain, prt);
2654  if(prt) {
2655  mf::LogVerbatim myprt("TC");
2656  myprt<<fcnLabel<<" merged chain";
2657  for(auto ssID : chain) myprt<<" 2S"<<ssID;
2658  myprt<<" -> 2S"<<newID;
2659  } // prt
2660  } // long chain
2661  chain.clear();
2662  break;
2663  } else {
2664  // add this shower to the chain
2665  if(chain.empty()) {
2666  chain.resize(3);
2667  chain[0] = sids[ii]; chain[1] = sids[jj]; chain[2] = sids[kk];
2668  } else {
2669  chain.push_back(sids[kk]);
2670  }
2671  // Refine the TP position and direction
2672  MakeBareTrajPoint(slc, tpList[ii], tpList[kk], tp);
2673 // PrintTrajPoint("ik", slc, 0, 0, chain.size(), tp);
2674  } // add to an existing chain
2675  } // kk
2676  // push the last one
2677  if(chain.size() > 2) {
2678  int newID = MergeShowers(fcnLabel, slc, chain, prt);
2679 /*
2680  if(newID > 0) {
2681  auto& newss = slc.cots[newID - 1];
2682  if(AddTjsInsideEnvelope(fcnLabel, slc, newss, prt)) UpdateShower(fcnLabel, slc, newss, prt);
2683  }
2684 */
2685  if(prt) {
2686  mf::LogVerbatim myprt("TC");
2687  myprt<<fcnLabel<<" merged chain";
2688  for(auto ssID : chain) myprt<<" "<<ssID;
2689  myprt<<" -> new ssID "<<newID;
2690  } // prt
2691  } // long chain
2692  } // ii
2693 
2694  ChkAssns(fcnLabel, slc);
2695 
2696  } // MergeShowerChain
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeBareTrajPoint(TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:3581
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4560
TCConfig tcc
Definition: DataStructs.cxx:6
bool DontCluster(TCSlice &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3313
bool lessThan(SortEntry c1, SortEntry c2)
Definition: TCShower.cxx:10
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
int MergeShowers(std::string inFcnLabel, TCSlice &slc, std::vector< int > ssIDs, bool prt)
Definition: TCShower.cxx:2917
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
int tca::MergeShowers ( std::string  inFcnLabel,
TCSlice slc,
std::vector< int >  ssIDs,
bool  prt 
)

Definition at line 2917 of file TCShower.cxx.

References tca::TCSlice::cots, CreateSS(), kKilled, MakeShowerObsolete(), ss, StoreShower(), tca::TCSlice::tjs, and UpdateShower().

Referenced by MergeShowerChain().

2918  {
2919  // merge a list of showers and return the ID of the merged shower.
2920  // Returns 0 if there was a failure.
2921 
2922  std::string fcnLabel = inFcnLabel + ".MS";
2923  if(ssIDs.size() < 2) return 0;
2924  // check for a valid ID
2925  for(auto ssID : ssIDs) if(ssID <= 0 || ssID > (int)slc.cots.size()) return 0;
2926  // check for the same CTP and consistent assns
2927  int ss3Assn = 0;
2928  auto& ss0 = slc.cots[ssIDs[0] - 1];
2929  std::vector<int> tjl;
2930  for(auto ssID : ssIDs) {
2931  auto& ss = slc.cots[ssID - 1];
2932  if(ss.CTP != ss0.CTP) return 0;
2933  tjl.insert(tjl.end(), ss.TjIDs.begin(), ss.TjIDs.end());
2934  if(ss.SS3ID > 0 && ss3Assn == 0) ss3Assn = ss.SS3ID;
2935  if(ss.SS3ID > 0 && ss.SS3ID != ss3Assn) {
2936  std::cout<<fcnLabel<<" Assn conflict \n";
2937  return 0;
2938  }
2939  } // ssID
2940  // ensure the InShower Tjs are valid
2941  for(auto tjID : tjl) {
2942  auto& tj = slc.tjs[tjID - 1];
2943  if(tj.CTP != ss0.CTP || tj.AlgMod[kKilled]) {
2944  std::cout<<fcnLabel<<" bad InShower T"<<tjID<<"\n";
2945  return 0;
2946  }
2947  } // tjID
2948 
2949  // mark the old showers killed
2950  for(auto ssID : ssIDs) {
2951  auto& ss = slc.cots[ssID - 1];
2952  ss.ID = 0;
2953  // kill the shower Tj
2954  auto& stj = slc.tjs[ss.ShowerTjID - 1];
2955  stj.AlgMod[kKilled] = true;
2956  } // tjID
2957 
2958  // in with the new
2959  auto newss = CreateSS(slc, tjl);
2960  if(newss.ID == 0) return 0;
2961 
2962  for(auto tid : tjl) {
2963  auto& tj = slc.tjs[tid - 1];
2964  tj.SSID = newss.ID;
2965  } // tid
2966  newss.SS3ID = ss3Assn;
2967 
2968  // define the new shower
2969  if(!UpdateShower(fcnLabel, slc, newss, prt)) {
2970  std::cout<<fcnLabel<<" UpdateShower failed\n";
2971  MakeShowerObsolete(fcnLabel, slc, newss, prt);
2972  return 0;
2973  }
2974  // store it
2975  if(!StoreShower(fcnLabel, slc, newss)) {
2976  std::cout<<fcnLabel<<" StoreShower failed\n";
2977  MakeShowerObsolete(fcnLabel, slc, newss, prt);
2978  return 0;
2979  }
2980  return newss.ID;
2981 
2982  } // MergeShowers
Float_t ss
Definition: plot.C:23
ShowerStruct CreateSS(TCSlice &slc, const std::vector< int > &tjl)
Definition: TCShower.cxx:4514
void MakeShowerObsolete(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3266
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1230
bool StoreShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss)
Definition: TCShower.cxx:4449
bool tca::MergeShowersAndStore ( std::string  inFcnLabel,
TCSlice slc,
int  icotID,
int  jcotID,
bool  prt 
)

Definition at line 2985 of file TCShower.cxx.

References tca::TCSlice::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::TCSlice::tjs, tca::ShowerStruct::TruParentID, and UpdateShower().

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

2986  {
2987  // Merge showers using shower indices. The icotID shower is modified in-place.
2988  // The jcotID shower is declared obsolete. This function also re-defines the shower and
2989  // preserves the icotID Parent ID.
2990 
2991  if(icotID <= 0 || icotID > (int)slc.cots.size()) return false;
2992  ShowerStruct& iss = slc.cots[icotID - 1];
2993  if(iss.ID == 0) return false;
2994  if(iss.TjIDs.empty()) return false;
2995  if(iss.ShowerTjID <= 0) return false;
2996 
2997  if(jcotID <= 0 || jcotID > (int)slc.cots.size()) return false;
2998  ShowerStruct& jss = slc.cots[jcotID - 1];
2999  if(jss.TjIDs.empty()) return false;
3000  if(jss.ID == 0) return false;
3001  if(jss.ShowerTjID <= 0) return false;
3002 
3003  if(iss.CTP != jss.CTP) return false;
3004 
3005  std::string fcnLabel = inFcnLabel + ".MSAS";
3006 
3007  if(iss.SS3ID > 0 && jss.SS3ID > 0 && iss.SS3ID != jss.SS3ID) {
3008  std::cout<<fcnLabel<<" Error: 2S"<<iss.ID<<" and S"<<jss.ID<<" have different 2S -> 3S assns\n";
3009  return false;
3010  }
3011 
3012  Trajectory& itj = slc.tjs[iss.ShowerTjID - 1];
3013  Trajectory& jtj = slc.tjs[jss.ShowerTjID - 1];
3014  if(!itj.Pts[1].Hits.empty() || !jtj.Pts[1].Hits.empty()) {
3015  std::cout<<fcnLabel<<" Error: These shower Tjs have hits! T"<<itj.ID<<" T"<<jtj.ID<<"\n";
3016  return false;
3017  }
3018 
3019  iss.TjIDs.insert(iss.TjIDs.end(), jss.TjIDs.begin(), jss.TjIDs.end());
3020  // make a new trajectory using itj as a template
3021  Trajectory ktj = itj;
3022  ktj.ID = slc.tjs.size() + 1;
3023 
3024  slc.tjs.push_back(ktj);
3025  // kill jtj
3026  MakeTrajectoryObsolete(slc, iss.ShowerTjID - 1);
3027  MakeTrajectoryObsolete(slc, jss.ShowerTjID - 1);
3028  slc.tjs[iss.ShowerTjID - 1].ParentID = ktj.ID;
3029  slc.tjs[jss.ShowerTjID - 1].ParentID = ktj.ID;
3030  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" killed stj T"<<iss.ShowerTjID<<" and T"<<jss.ShowerTjID<<" new T"<<ktj.ID;
3031  // revise the shower
3032  iss.ShowerTjID = ktj.ID;
3033  // transfer the list of Tj IDs
3034  iss.TjIDs.insert(iss.TjIDs.end(), jss.TjIDs.begin(), jss.TjIDs.begin());
3035  std::sort(iss.TjIDs.begin(), iss.TjIDs.end());
3036  // correct the assn
3037  for(auto tid : iss.TjIDs) {
3038  auto& tj = slc.tjs[tid - 1];
3039  tj.SSID = iss.ID;
3040  } // tid
3041  // transfer a 2S -> 3S assn
3042  if(iss.SS3ID == 0 && jss.SS3ID > 0) iss.SS3ID = jss.SS3ID;
3043  // merge the list of nearby Tjs
3044  iss.NearTjIDs.insert(iss.NearTjIDs.end(), jss.NearTjIDs.begin(), jss.NearTjIDs.end());
3045  // transfer the TruParentID if it is in jss
3046  if(jss.TruParentID > 0) iss.TruParentID = jss.TruParentID;
3047 // iss.ParentID = 0;
3048  iss.NeedsUpdate = true;
3049  // force a full update
3050  iss.ShPts.clear();
3051  jss.ID = 0;
3052  bool success = UpdateShower(fcnLabel, slc, iss, prt);
3053  KillVerticesInShower(fcnLabel, slc, iss, prt);
3054 
3055  return success;
3056 
3057  } // MergeShowersAndStore
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void KillVerticesInShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:702
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1230
void MakeTrajectoryObsolete(TCSlice &slc, unsigned int itj)
Definition: Utils.cxx:1922
bool tca::MergeShowerTjsAndStore ( TCSlice slc,
unsigned short  istj,
unsigned short  jstj,
bool  prt 
)

Definition at line 3060 of file TCShower.cxx.

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

Referenced by MergeAndStore().

3061  {
3062  // Merge showers using showerTj indices
3063  // This function is called from MergeAndStore whose function is to merge two line-like
3064  // trajectories and store them. This function was called because at least one of the
3065  // trajectories is a shower Tj. Assume that the decision to merge them has been made elsewhere.
3066 
3067  if(istj > slc.tjs.size() - 1) return false;
3068  if(jstj > slc.tjs.size() - 1) return false;
3069 
3070  Trajectory& itj = slc.tjs[istj];
3071  Trajectory& jtj = slc.tjs[jstj];
3072 
3073  std::string fcnLabel = "MSTJ";
3074 
3075  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" MergeShowerTjsAndStore Tj IDs "<<itj.ID<<" "<<jtj.ID;
3076 
3077  // First we check to make sure that both are shower Tjs.
3078  if(!itj.AlgMod[kShowerTj] && !jtj.AlgMod[kShowerTj]) {
3079  if(prt) mf::LogVerbatim("TC")<<" One of these isn't a shower Tj";
3080  return false;
3081  }
3082 
3083  // We need to keep the convention used in MergeAndStore to create a new merged trajectory
3084  // and kill the two fragments. This doesn't require making a new shower however. We can just
3085  // re-purpose one of the existing showers
3086  int icotID = GetCotID(slc, itj.ID);
3087  if(icotID == 0) return false;
3088  ShowerStruct& iss = slc.cots[icotID - 1];
3089  if(iss.ID == 0) return false;
3090  if(iss.TjIDs.empty()) return false;
3091  int jcotID = GetCotID(slc, jtj.ID);
3092  if(jcotID == 0) return false;
3093  ShowerStruct& jss = slc.cots[jcotID - 1];
3094  if(jss.ID == 0) return false;
3095  if(jss.TjIDs.empty()) return false;
3096 
3097  return MergeShowersAndStore(fcnLabel, slc, icotID, jcotID, prt);
3098 
3099  } // MergeShowerTjsAndStore
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
int GetCotID(TCSlice &slc, int ShowerTjID)
Definition: TCShower.cxx:4359
bool MergeShowersAndStore(std::string inFcnLabel, TCSlice &slc, int icotID, int jcotID, bool prt)
Definition: TCShower.cxx:2985
void tca::MergeSubShowers ( std::string  inFcnLabel,
TCSlice slc,
const CTP_t inCTP,
bool  prt 
)

Definition at line 2810 of file TCShower.cxx.

References tca::Trajectory::AlgMod, tca::ShowerStruct::AspectRatio, ChkAssns(), tca::TCSlice::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::TCConfig::showerTag, tca::ShowerStruct::ShowerTjID, ss, tcc, tca::ShowerStruct::TjIDs, tca::TCSlice::tjs, tca::TCConfig::useAlg, and tca::TCConfig::wirePitch.

Referenced by FindShowers3D().

2811  {
2812  // Merge small showers that are downstream of larger showers
2813 
2814  if(!tcc.useAlg[kMergeSubShowers]) return;
2815 
2816  std::string fcnLabel = inFcnLabel + ".MSS";
2817  bool newCuts = (tcc.showerTag[0] == 4);
2818  constexpr float radLen = 14 / 0.3;
2819 
2820  if(prt) {
2821  if(newCuts) {
2822  mf::LogVerbatim("TC")<<fcnLabel<<" MergeSubShowers checking using ShowerParams";
2823  } else {
2824  mf::LogVerbatim("TC")<<fcnLabel<<" MergeSubShowers checking using radiation length cut ";
2825  }
2826  } // prt
2827 
2828  bool keepMerging = true;
2829  while(keepMerging) {
2830  keepMerging = false;
2831  // sort by decreasing energy
2832  std::vector<SortEntry> sortVec;
2833  for(auto& ss : slc.cots) {
2834  if(ss.ID == 0) continue;
2835  if(ss.CTP != inCTP) continue;
2836  SortEntry se;
2837  se.index = ss.ID - 1;
2838  se.length = ss.Energy;
2839  sortVec.push_back(se);
2840  } // ss
2841  if(sortVec.size() < 2) return;
2842  std::sort(sortVec.begin(), sortVec.end(), greaterThan);
2843  for(unsigned short ii = 0; ii < sortVec.size() - 1; ++ii) {
2844  ShowerStruct& iss = slc.cots[sortVec[ii].index];
2845  if(iss.ID == 0) continue;
2846  // this shouldn't be done to showers that are ~round
2847  if(iss.AspectRatio > 0.5) continue;
2848  TrajPoint& istp1 = slc.tjs[iss.ShowerTjID - 1].Pts[1];
2849  double shMaxAlong, along95;
2850  ShowerParams((double)iss.Energy, shMaxAlong, along95);
2851  // convert along95 to a separation btw shower max and along95
2852  along95 -= shMaxAlong;
2853  // convert to WSE
2854  along95 /= tcc.wirePitch;
2855  for(unsigned short jj = ii + 1; jj < sortVec.size(); ++jj) {
2856  ShowerStruct& jss = slc.cots[sortVec[jj].index];
2857  if(jss.ID == 0) continue;
2858  if(DontCluster(slc, iss.TjIDs, jss.TjIDs)) continue;
2859  TrajPoint& jstp1 = slc.tjs[jss.ShowerTjID - 1].Pts[1];
2860  if(newCuts) {
2861  // find the longitudinal and transverse separation using the higher energy
2862  // shower which probably is better defined.
2863  Point2_t alongTrans;
2864  FindAlongTrans(istp1.Pos, istp1.Dir, jstp1.Pos, alongTrans);
2865  // the lower energy shower is at the wrong end of the higher energy shower if alongTrans[0] < 0
2866  if(alongTrans[0] < 0) continue;
2867  // increase the cut if the second shower is < 10% of the first shower
2868  float alongCut = along95;
2869  if(jss.Energy < 0.1 * iss.Energy) alongCut *= 1.5;
2870  float probLong = InShowerProbLong(iss.Energy, alongTrans[0]);
2871  float probTran = InShowerProbTrans(iss.Energy, alongTrans[0], alongTrans[1]);
2872  if(prt) {
2873  mf::LogVerbatim myprt("TC");
2874  myprt<<fcnLabel<<" Candidate i2S"<<iss.ID<<" E = "<<(int)iss.Energy<<" j2S"<<jss.ID<<" E = "<<(int)jss.Energy;
2875  myprt<<" along "<<std::fixed<<std::setprecision(1)<<alongTrans[0]<<" trans "<<alongTrans[1];
2876  myprt<<" alongCut "<<alongCut<<" probLong "<<probLong<<" probTran "<<probTran;
2877  } // prt
2878  // TODO: fix ShowerParams so we can use the likelihood cut instead
2879  if(alongTrans[0] > alongCut) continue;
2880  if(alongTrans[1] > alongTrans[0]) continue;
2881  } else {
2882  // old cuts
2883  float sep = PosSep(istp1.Pos, jstp1.Pos);
2884  float trad = sep / radLen;
2885  // Find the IP between them using the projection of the one with the lowest aspect ratio
2886  float delta = 9999;
2887  if(iss.AspectRatio < jss.AspectRatio) {
2888  delta = PointTrajDOCA(slc, jstp1.Pos[0], jstp1.Pos[1], istp1);
2889  } else {
2890  delta = PointTrajDOCA(slc, istp1.Pos[0], istp1.Pos[1], jstp1);
2891  }
2892  // See if delta is consistent with the cone angle of the i shower
2893  float dang = delta / sep;
2894  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Candidate i2S"<<iss.ID<<" j2S"<<jss.ID<<" separation "<<(int)sep<<" radiation lengths "<<trad<<" delta "<<delta<<" dang "<<dang;
2895  if(trad > 3) continue;
2896  // There must be a correlation between dang and the energy of these showers...
2897  if(dang > 0.3) continue;
2898  } // old cuts
2899 
2900  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Merge them. Re-find shower center, etc";
2901  if(MergeShowersAndStore(fcnLabel, slc, iss.ID, jss.ID, prt)) {
2902  Trajectory& stj = slc.tjs[iss.ShowerTjID - 1];
2903  stj.AlgMod[kMergeSubShowers] = true;
2904  keepMerging = true;
2905  break;
2906  }
2907  } // jj
2908  if(keepMerging) break;
2909  } // ii
2910  } // keepMerging
2911 
2912  ChkAssns(fcnLabel, slc);
2913 
2914  } // MergeSubShowers
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool greaterThan(SortEntry c1, SortEntry c2)
Definition: TCShower.cxx:9
double InShowerProbLong(double showerEnergy, double along)
Definition: TCShower.cxx:2049
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4560
unsigned int index
Definition: StepUtils.cxx:5
TCConfig tcc
Definition: DataStructs.cxx:6
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:2849
Float_t ss
Definition: plot.C:23
float length
Definition: TCShower.cxx:6
double InShowerProbTrans(double showerEnergy, double along, double trans)
Definition: TCShower.cxx:2083
bool DontCluster(TCSlice &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3313
std::vector< float > showerTag
[min MCSMom, max separation, min # Tj < separation] for a shower tag
Definition: DataStructs.h:474
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
bool MergeShowersAndStore(std::string inFcnLabel, TCSlice &slc, int icotID, int jcotID, bool prt)
Definition: TCShower.cxx:2985
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
Definition: TCShower.cxx:2015
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
void tca::MergeSubShowersTj ( std::string  inFcnLabel,
TCSlice slc,
const CTP_t inCTP,
bool  prt 
)

Definition at line 2699 of file TCShower.cxx.

References AddTj(), ChgToMeV(), ChkAssns(), tca::TCSlice::cots, DontCluster(), FarEnd(), kHaloTj, kKilled, kMergeSubShowersTj, mat, MCSMom(), NumPtsWithCharge(), PointTrajDOCA(), PosSep(), tca::TCConfig::showerTag, ss, tcc, tca::TCSlice::tjs, and tca::TCConfig::useAlg.

Referenced by FindShowers3D().

2700  {
2701  // merge small showers that are downstream of shower-like tjs. This algorithm is written
2702  // for low-energy showers with are likely to be sparse and poorly defined.
2703 
2704  if(!tcc.useAlg[kMergeSubShowersTj]) return;
2705 
2706  std::string fcnLabel = inFcnLabel + ".MSSTj";
2707 
2708  struct TjSS {
2709  int ssID;
2710  int tjID;
2711  float dang;
2712  };
2713  std::vector<TjSS> tjss;
2714 
2715  // temp vector for DontCluster
2716  std::vector<int> tjid(1);
2717  for(auto& ss : slc.cots) {
2718  if(ss.ID == 0) continue;
2719  if(ss.CTP != inCTP) continue;
2720  // TODO: Evaluate this cut
2721  if(ss.Energy > 300) continue;
2722  auto& stj = slc.tjs[ss.ShowerTjID - 1];
2723  auto stp0 = stj.Pts[0];
2724  float bestDang = 0.3;
2725  int bestTj = 0;
2726  // look for a Tj that has higher energy than the shower
2727  for(auto& tj : slc.tjs) {
2728  if(tj.AlgMod[kKilled]) continue;
2729  if(tj.AlgMod[kHaloTj]) continue;
2730  if(tj.CTP != ss.CTP) continue;
2731  // require that it isn't in any shower
2732  if(tj.SSID > 0) continue;
2733  // require it to be not short
2734  if(NumPtsWithCharge(slc, tj, false) < 10) continue;
2735  // and satisfy the ShowerLike MCSMom cut. It is unlikely to be tagged shower-like
2736  if(tj.MCSMom > tcc.showerTag[1]) continue;
2737  // check consistency
2738  tjid[0] = tj.ID;
2739  if(DontCluster(slc, tjid, ss.TjIDs)) continue;
2740  float tjEnergy = ChgToMeV(tj.TotChg);
2741  // find the end that is furthest away from the shower center
2742  unsigned short farEnd = FarEnd(slc, tj, stj.Pts[1].Pos);
2743  // compare MCSMom at the far end and the near end
2744  unsigned short midpt = 0.5 * (tj.EndPt[0] + tj.EndPt[1]);
2745  float mom1 = MCSMom(slc, tj, tj.EndPt[farEnd], midpt);
2746  float mom2 = MCSMom(slc, tj, tj.EndPt[1 - farEnd], midpt);
2747  float asym = (mom1 - mom2) / (mom1 + mom2);
2748  auto& farTP = tj.Pts[tj.EndPt[farEnd]];
2749  // IP btw the far end TP and the shower center
2750  float doca = PointTrajDOCA(slc, stp0.Pos[0], stp0.Pos[1], farTP);
2751  float sep = PosSep(farTP.Pos, stp0.Pos);
2752  float dang = doca / sep;
2753  if(prt) {
2754  mf::LogVerbatim myprt("TC");
2755  myprt<<fcnLabel<<" Candidate 2S"<<ss.ID<<" T"<<tj.ID<<"_"<<farEnd;
2756  myprt<<" ShEnergy "<<(int)ss.Energy<<" tjEnergy "<<(int)tjEnergy;
2757  myprt<<" doca "<<doca<<" sep "<<sep<<" dang "<<dang<<" asym "<<asym;
2758  }
2759  if(tjEnergy < ss.Energy) continue;
2760  if(asym < 0.5) continue;
2761  // TODO: This should be done more carefully
2762  // separation cut 100 WSE ~ 30 cm in uB
2763  if(sep > 100) continue;
2764  if(dang > bestDang) continue;
2765  bestDang = dang;
2766  bestTj = tj.ID;
2767  } // tj
2768  if(bestTj == 0) continue;
2769  TjSS match;
2770  match.ssID = ss.ID;
2771  match.tjID = bestTj;
2772  match.dang = bestDang;
2773  tjss.push_back(match);
2774  } // ss
2775 
2776  if(tjss.empty()) return;
2777 
2778  // ensure that a tj is only put in one shower
2779  bool keepGoing = true;
2780  while(keepGoing) {
2781  keepGoing = false;
2782  float bestDang = 0.3;
2783  int bestMatch = 0;
2784  for(unsigned short mat = 0; mat < tjss.size(); ++mat) {
2785  auto& match = tjss[mat];
2786  // already used
2787  if(match.dang < 0) continue;
2788  if(match.dang < bestDang) bestMatch = mat;
2789  } // mat
2790  if(bestMatch > 0) {
2791  auto& match = tjss[bestMatch];
2792  auto& ss = slc.cots[match.ssID - 1];
2793  if(!AddTj(fcnLabel, slc, match.tjID, ss, true, prt)) {
2794  if(prt) mf::LogVerbatim("TC")<<" Failed";
2795  continue;
2796  }
2797  match.dang = -1;
2798  // set the AlgMod bit
2799  auto& stj = slc.tjs[ss.ShowerTjID - 1];
2800  stj.AlgMod[kMergeSubShowersTj] = true;
2801  keepGoing = true;
2802  } // found bestMatch
2803  } // keepGoing
2804 
2805  ChkAssns(fcnLabel, slc);
2806 
2807  } // MergeSubShowersTj
bool AddTj(std::string inFcnLabel, TCSlice &slc, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1552
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4560
short MCSMom(TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2914
TCConfig tcc
Definition: DataStructs.cxx:6
Float_t ss
Definition: plot.C:23
bool DontCluster(TCSlice &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3313
std::vector< float > showerTag
[min MCSMom, max separation, min # Tj < separation] for a shower tag
Definition: DataStructs.h:474
Float_t mat
Definition: plot.C:40
unsigned short FarEnd(TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3032
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
float ChgToMeV(float chg)
Definition: TCShower.cxx:4395
bool tca::MergeTjIntoPFP ( TCSlice slc,
int  mtjid,
PFPStruct pfp,
bool  prt 
)

Definition at line 507 of file Utils.cxx.

References MergeAndStore(), tca::PFPStruct::TjIDs, and tca::TCSlice::tjs.

508  {
509  // Tries to merge Tj with ID tjid into PFParticle pfp
510  if(mtjid > (int)slc.tjs.size()) return false;
511  auto& mtj = slc.tjs[mtjid - 1];
512  // find the Tj in pfp.TjIDs which it should be merged with
513  int otjid = 0;
514  for(auto tjid : pfp.TjIDs) {
515  auto& otj = slc.tjs[tjid - 1];
516  if(otj.CTP == mtj.CTP) {
517  otjid = tjid;
518  break;
519  }
520  } // tjid
521  if(otjid == 0) return false;
522  if(MergeAndStore(slc, otjid - 1, mtjid - 1, prt)) {
523  int newtjid = slc.tjs.size();
524  if(prt) mf::LogVerbatim("TC")<<"MergeTjIntoPFP: merged T"<<otjid<<" with T"<<mtjid<<" -> T"<<newtjid;
525  std::replace(pfp.TjIDs.begin(), pfp.TjIDs.begin(), otjid, newtjid);
526  return true;
527  } else {
528  if(prt) mf::LogVerbatim("TC")<<"MergeTjIntoPFP: merge T"<<otjid<<" with T"<<mtjid<<" failed ";
529  return false;
530  }
531  } // MergeTjIntoPFP
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MergeAndStore(TCSlice &slc, unsigned int itj1, unsigned int itj2, bool doPrt)
Definition: Utils.cxx:4095
void tca::MergeTjList ( std::vector< std::vector< int >> &  tjList)

Definition at line 1422 of file TCShower.cxx.

1423  {
1424  // Merge the lists of Tjs in the lists if they share a common Tj ID
1425 
1426  if(tjList.size() < 2) return;
1427 
1428  bool didMerge = true;
1429  while(didMerge) {
1430  didMerge = false;
1431  for(unsigned short itl = 0; itl < tjList.size() - 1; ++itl) {
1432  if(tjList[itl].empty()) continue;
1433  for(unsigned short jtl = itl + 1; jtl < tjList.size(); ++jtl) {
1434  if(tjList[itl].empty()) continue;
1435  auto& itList = tjList[itl];
1436  auto& jtList = tjList[jtl];
1437  // See if the j Tj is in the i tjList
1438  bool jtjInItjList = false;
1439  for(auto& jtj : jtList) {
1440  if(std::find(itList.begin(), itList.end(), jtj) != itList.end()) {
1441  jtjInItjList = true;
1442  break;
1443  }
1444  if(jtjInItjList) break;
1445  } // jtj
1446  if(jtjInItjList) {
1447  // append the jtList to itList
1448  itList.insert(itList.end(), jtList.begin(), jtList.end());
1449  // clear jtList
1450  jtList.clear();
1451  didMerge = true;
1452  }
1453  } // jtl
1454  } // itl
1455  } // didMerge
1456 
1457  // erase the deleted elements
1458  unsigned short imEmpty = 0;
1459  while(imEmpty < tjList.size()) {
1460  for(imEmpty = 0; imEmpty < tjList.size(); ++imEmpty) if(tjList[imEmpty].empty()) break;
1461  if(imEmpty < tjList.size()) tjList.erase(tjList.begin() + imEmpty);
1462  } // imEmpty < tjList.size()
1463 
1464  // sort the lists by increasing ID and remove duplicates
1465  for(auto& tjl : tjList) {
1466  std::sort(tjl.begin(), tjl.end());
1467  auto last = std::unique(tjl.begin(), tjl.end());
1468  tjl.erase(last, tjl.end());
1469  } // tjl
1470 
1471  } // MergeTjList
void tca::MergeTjList2 ( std::string  inFcnLabel,
TCSlice slc,
std::vector< std::vector< int >> &  tjList,
bool  prt 
)
bool tca::MergeWithVertex ( TCSlice slc,
VtxStore vx,
unsigned short  oVxID 
)

Definition at line 701 of file TCVertex.cxx.

References tca::VtxStore::ChiDOF, CloseEnd(), tca::VtxStore::CTP, tca::TCConfig::dbgSlc, tca::TCConfig::dbgVxMerge, evd::details::end(), FitVertex(), GetVtxTjIDs(), tca::VtxStore::ID, tca::SortEntry::index, kFixed, kHaloTj, kKilled, kVtxMerged, kVxMerge, NearestPtWithChg(), NumPtsWithCharge(), tca::VtxStore::Pos, tca::VtxStore::PosErr, PrintPos(), SetVx2Score(), tca::VtxStore::Stat, tcc, tca::TCSlice::tjs, tmp, tca::TCConfig::useAlg, valDecreasing(), and tca::TCSlice::vtxs.

Referenced by Find2DVertices().

702  {
703  // Attempts to merge the trajectories attached to vx with an existing 2D vertex
704  // referenced by existingVxID. This function doesn't use the existing end0/end1 vertex association.
705  // It returns true if the merging was successful in which case the calling function should
706  // not store vx. The calling function needs to have set VtxID to vx.ID for tjs that are currently attached
707  // to vx. It assumed that vx hasn't yet been pushed onto slc.vtxs
708 
709  if(!tcc.useAlg[kVxMerge]) return false;
710 
711  bool prt = tcc.dbgVxMerge && tcc.dbgSlc;
712 
713  if(oVxID > slc.vtxs.size()) return false;
714  auto& oVx = slc.vtxs[oVxID - 1];
715  if(vx.CTP != oVx.CTP) return false;
716 
717  // get a list of tjs attached to both vertices
718  std::vector<int> tjlist = GetVtxTjIDs(slc, vx);
719 // auto tjlist = GetAssns(slc, "2V", vx.ID, "T");
720  if(tjlist.empty()) return false;
721  std::vector<int> tmp = GetVtxTjIDs(slc, oVx);
722 // auto tmp = GetAssns(slc, "2V", oVx.ID, "T");
723  if(tmp.empty()) return false;
724  for(auto tjid : tmp) {
725  if(std::find(tjlist.begin(), tjlist.end(), tjid) == tjlist.end()) tjlist.push_back(tjid);
726  } // tjid
727  if(tjlist.size() < 2) return false;
728  // handle the simple case
729  if(tjlist.size() == 2) {
730  // Unset the fixed bit
731  vx.Stat[kFixed] = false;
732  oVx.Stat[kFixed] = false;
733  // assign the vx tjs to oVx
734  for(auto tjid : tjlist) {
735  auto& tj = slc.tjs[tjid - 1];
736  for(unsigned short end = 0; end < 2; ++end) {
737  if(tj.VtxID[end] == vx.ID) tj.VtxID[end] = oVx.ID;
738  } // end
739  } // tjid
740  if(!FitVertex(slc, oVx, prt)) {
741  if(prt) mf::LogVerbatim("TC")<<"MWV: merge failed "<<vx.ID<<" and existing "<<oVx.ID;
742  return false;
743  }
744  return true;
745  } // size = 2
746 
747  // sort by decreasing length
748  std::vector<SortEntry> sortVec(tjlist.size());
749  for(unsigned int indx = 0; indx < sortVec.size(); ++indx) {
750  sortVec[indx].index = indx;
751  auto& tj = slc.tjs[tjlist[indx] - 1];
752  sortVec[indx].val = tj.Pts.size();
753  } // indx
754  std::sort(sortVec.begin(), sortVec.end(), valDecreasing);
755  // re-order the list of Tjs
756  auto ttl = tjlist;
757  for(unsigned short ii = 0; ii < sortVec.size(); ++ii) tjlist[ii] = ttl[sortVec[ii].index];
758  // Create a local vertex using the two longest slc, then add the shorter ones
759  // until the pull reaches the cut
760  VtxStore aVx;
761  aVx.CTP = vx.CTP;
762  std::vector<TrajPoint> tjpts(tjlist.size());
763  // determine which point on each Tj that will be used in the vertex fit and stash it in
764  // the traj point Step variable. This requires knowing the real position of the merged vertex
765  // which we estimate by averaging
766  std::array<float, 2> vpos;
767  vpos[0] = 0.5 * (vx.Pos[0] + oVx.Pos[0]);
768  vpos[1] = 0.5 * (vx.Pos[1] + oVx.Pos[1]);
769  for(unsigned short ii = 0; ii < tjpts.size(); ++ii) {
770  auto& tj = slc.tjs[tjlist[ii] - 1];
771  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
772  unsigned short end = CloseEnd(slc, tj, vpos);
773  // assume that we will use the end point of the tj
774  unsigned short endPt = tj.EndPt[end];
775  if(npwc > 6 && tj.Pts[endPt].NTPsFit < 4) {
776  if(end == 0) {
777  endPt += 3;
778  } else {
779  endPt -= 3;
780  }
781  endPt = NearestPtWithChg(slc, tj, endPt);
782  } // few points fit at the end
783  if(endPt < tj.EndPt[0]) endPt = tj.EndPt[0];
784  if(endPt > tj.EndPt[1]) endPt = tj.EndPt[1];
785  // define tjpts
786  tjpts[ii].CTP = tj.CTP;
787  tjpts[ii].Pos = tj.Pts[endPt].Pos;
788  tjpts[ii].Dir = tj.Pts[endPt].Dir;
789  tjpts[ii].Ang = tj.Pts[endPt].Ang;
790  tjpts[ii].AngErr = tj.Pts[endPt].AngErr;
791  // stash the point in Step
792  tjpts[ii].Step = endPt;
793  // and the end in AngleCode
794  tjpts[ii].AngleCode = end;
795  // stash the ID in Hits
796  tjpts[ii].Hits.resize(1, tj.ID);
797  } // tjid
798  if(prt) {
799  mf::LogVerbatim myprt("TC");
800  myprt<<"MWV: "<<oVxID;
801  myprt<<" Fit TPs";
802  for(unsigned short ii = 0; ii < tjpts.size(); ++ii) {
803  auto& tjpt = tjpts[ii];
804  myprt<<" "<<tjlist[ii]<<"_"<<tjpt.Step<<"_"<<PrintPos(slc, tjpt.Pos);
805  }
806  } // prt
807  // create a subset of the first two for the first fit
808  auto fitpts = tjpts;
809  fitpts.resize(2);
810  if(!FitVertex(slc, aVx, fitpts, prt)) {
811  if(prt) mf::LogVerbatim("TC")<<"MWV: first fit failed ";
812  return false;
813  }
814  // Fit and add tjs to the vertex
815  bool needsUpdate = false;
816  for(unsigned short ii = 2; ii < tjlist.size(); ++ii) {
817  fitpts.push_back(tjpts[ii]);
818  if(FitVertex(slc, aVx, fitpts, prt)) {
819  needsUpdate = false;
820  } else {
821  // remove the last Tj point and keep going
822  fitpts.pop_back();
823  needsUpdate = true;
824  }
825  } // ii
826 
827  if(needsUpdate) FitVertex(slc, aVx, fitpts, prt);
828  if(prt) mf::LogVerbatim("TC")<<"MWV: done "<<vx.ID<<" and existing "<<oVx.ID;
829 
830  // update. Remove old associations
831  for(auto& tj : slc.tjs) {
832  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
833  if(tj.CTP != vx.CTP) continue;
834  for(unsigned short end = 0; end < 2; ++end) {
835  if(tj.VtxID[end] == vx.ID) tj.VtxID[end] = 0;
836  if(tj.VtxID[end] == oVxID) tj.VtxID[end] = 0;
837  }
838  } // tj
839  // set the new associations
840  for(unsigned short ii = 0; ii < fitpts.size(); ++ii) {
841  auto& tjpt = fitpts[ii];
842  unsigned short end = tjpt.AngleCode;
843  auto& tj = slc.tjs[tjpt.Hits[0] - 1];
844  if(tj.VtxID[end] != 0) {
845  std::cout<<"MWV: coding error. tj "<<tj.ID<<" end "<<end<<" VtxID "<<tj.VtxID[end]<<" != 0\n";
846  return false;
847  }
848  tj.VtxID[end] = oVxID;
849  } // ii
850 
851  // Update oVx
852  oVx.Pos = aVx.Pos;
853  oVx.PosErr = aVx.PosErr;
854  oVx.ChiDOF = aVx.ChiDOF;
855  oVx.NTraj = fitpts.size();
856  // Update the score and the charge fraction
857  SetVx2Score(slc, oVx);
858  oVx.Stat[kVtxMerged] = true;
859  oVx.Stat[kFixed] = false;
860  if(prt) {
861  mf::LogVerbatim myprt("TC");
862  myprt<<"MWV: "<<oVxID;
863  myprt<<" Done TPs";
864  for(unsigned short ii = 0; ii < fitpts.size(); ++ii) {
865  auto& tjpt = fitpts[ii];
866  myprt<<" "<<tjpt.Hits[0]<<"_"<<tjpt.AngleCode<<"_"<<PrintPos(slc, tjpt.Pos);
867  }
868  } // prt
869 
870  return true;
871  } // MergeWithVertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool FitVertex(TCSlice &slc, VtxStore &vx, std::vector< TrajPoint > vxTp, bool prt)
Definition: TCVertex.cxx:2184
TCConfig tcc
Definition: DataStructs.cxx:6
vertex position fixed manually - no fitting done
Definition: DataStructs.h:74
Float_t tmp
Definition: plot.C:37
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:507
unsigned short NearestPtWithChg(TCSlice &slc, Trajectory &tj, unsigned short thePt)
Definition: Utils.cxx:2966
unsigned short CloseEnd(TCSlice &slc, const Trajectory &tj, const Point2_t &pos)
Definition: Utils.cxx:2251
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2513
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:3243
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool valDecreasing(SortEntry c1, SortEntry c2)
Definition: Utils.cxx:14
void tca::MoveTPToWire ( TrajPoint tp,
float  wire 
)

Definition at line 2485 of file Utils.cxx.

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

Referenced by AddHits(), Find2DVertices(), FindCloseTjs(), FindHammerVertices2(), FindVtxTjs(), FitTraj(), Forecast(), IsGhost(), and ReversePropagate().

2486  {
2487  // Project TP to a "wire position" Pos[0] and update Pos[1]
2488  if(tp.Dir[0] == 0) return;
2489  float dw = wire - tp.Pos[0];
2490  if(std::abs(dw) < 0.01) return;
2491  tp.Pos[0] = wire;
2492  tp.Pos[1] += dw * tp.Dir[1] / tp.Dir[0];
2493  } // MoveTPToWire
unsigned short tca::NearestPtWithChg ( TCSlice slc,
Trajectory tj,
unsigned short  thePt 
)

Definition at line 2966 of file Utils.cxx.

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

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

2967  {
2968  // returns a point near thePt which has charge
2969  if(thePt > tj.EndPt[1]) return thePt;
2970  if(tj.Pts[thePt].Chg > 0) return thePt;
2971 
2972  short endPt0 = tj.EndPt[0];
2973  short endPt1 = tj.EndPt[1];
2974  for(short off = 1; off < 10; ++off) {
2975  short ipt = thePt + off;
2976  if(ipt <= endPt1 && tj.Pts[ipt].Chg > 0) return (unsigned short)ipt;
2977  ipt = thePt - off;
2978  if(ipt >= endPt0 && tj.Pts[ipt].Chg > 0) return (unsigned short)ipt;
2979  } // off
2980  return thePt;
2981  } // NearestPtWithChg
int tca::NeutrinoPrimaryTjID ( TCSlice slc,
const Trajectory tj 
)

Definition at line 441 of file Utils.cxx.

References tca::Trajectory::AlgMod, evd::details::end(), kHaloTj, kKilled, tca::Trajectory::ParentID, PrimaryID(), tca::TCSlice::tjs, tca::TCSlice::vtx3s, and tca::TCSlice::vtxs.

Referenced by AddTjsInsideEnvelope(), PrintAllTraj(), and PrintT().

442  {
443  // Returns the ID of the grandparent of this tj that is a primary tj that is attached
444  // to the neutrino vertex. 0 is returned if this condition is not met.
445  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) return -1;
446  if(tj.ParentID <= 0) return -1;
447  int primID = PrimaryID(slc, tj);
448  if(primID <= 0 || primID > (int)slc.tjs.size()) return -1;
449 
450  // We have the ID of the primary tj. Now see if it is attached to the neutrino vertex
451  auto& ptj = slc.tjs[primID - 1];
452  for(unsigned short end = 0; end < 2; ++end) {
453  if(ptj.VtxID[end] == 0) continue;
454  auto& vx2 = slc.vtxs[ptj.VtxID[end] - 1];
455  if(vx2.Vx3ID == 0) continue;
456  auto& vx3 = slc.vtx3s[vx2.Vx3ID - 1];
457  if(vx3.Neutrino) return primID;
458  } // end
459  return -1;
460  } // NeutrinoPrimaryTjUID
int PrimaryID(TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:463
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
unsigned short tca::NumDeltaRays ( TCSlice slc,
const Trajectory tj 
)

Definition at line 413 of file Utils.cxx.

References tca::Trajectory::ID, kDeltaRay, kHaloTj, kKilled, and tca::TCSlice::tjs.

414  {
415  // returns the number of delta rays that have this tj as a parent
416  unsigned short cnt = 0;
417  for(auto& dtj : slc.tjs) {
418  if(dtj.AlgMod[kKilled] || dtj.AlgMod[kHaloTj]) continue;
419  if(!dtj.AlgMod[kDeltaRay]) continue;
420  if(dtj.ParentID == tj.ID) ++cnt;
421  } // tj
422  return cnt;
423  } // NumDeltaRays
unsigned short tca::NumDeltaRays ( TCSlice slc,
std::vector< int > &  tjIDs 
)

Definition at line 426 of file Utils.cxx.

References kDeltaRay, kHaloTj, kKilled, and tca::TCSlice::tjs.

427  {
428  // Count the number of delta-rays that have a Tj in the list of TjIDs as a parent.
429  if(tjIDs.empty()) return 0;
430  if(tjIDs[0] <= 0 || tjIDs[0] > (int)slc.tjs.size()) return 0;
431  unsigned short cnt = 0;
432  for(auto& tj : slc.tjs) {
433  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
434  if(!tj.AlgMod[kDeltaRay]) continue;
435  if(std::find(tjIDs.begin(), tjIDs.end(), tj.ParentID) != tjIDs.end()) ++cnt;
436  } // tj
437  return cnt;
438  } // NumDeltaRays
unsigned short tca::NumHitsInTP ( const TrajPoint tp,
HitStatus_t  hitRequest 
)

Definition at line 3775 of file Utils.cxx.

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

Referenced by AddHits(), CheckHiMultUnusedHits(), and DotProd().

3776  {
3777  // Counts the number of hits of the specified type in tp
3778  if(tp.Hits.empty()) return 0;
3779 
3780  if(hitRequest == kAllHits) return tp.Hits.size();
3781 
3782  unsigned short nhits = 0;
3783  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3784  if(hitRequest == kUsedHits) {
3785  if(tp.UseHit[ii]) ++nhits;
3786  } else {
3787  // looking for unused hits
3788  if(!tp.UseHit[ii]) ++nhits;
3789  }
3790  } // ii
3791  return nhits;
3792  } // NumHitsInTP
unsigned short tca::NumPtsWithCharge ( TCSlice slc,
const Trajectory tj,
bool  includeDeadWires 
)

Definition at line 1863 of file Utils.cxx.

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

Referenced by AnalyzePFP(), CheckHiMultUnusedHits(), CheckStiffEl(), CheckTraj(), CompleteIncomplete3DVertices(), EndMerge(), FillmAllTraj(), FindCots(), FindHammerVertices2(), FindVtxTjs(), FixTrajBegin(), FixTrajEnd(), Forecast(), GottaKink(), MergeSubShowersTj(), MergeWithVertex(), tca::TrajClusterAlg::ReconstructAllTraj(), SetStrategy(), SplitTrajCrossingVertices(), StepAway(), TagShowerLike(), and UpdateTraj().

1864  {
1865  unsigned short firstPt = tj.EndPt[0];
1866  unsigned short lastPt = tj.EndPt[1];
1867  return NumPtsWithCharge(slc, tj, includeDeadWires, firstPt, lastPt);
1868  }
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:1871
unsigned short tca::NumPtsWithCharge ( TCSlice slc,
const Trajectory tj,
bool  includeDeadWires,
unsigned short  firstPt,
unsigned short  lastPt 
)

Definition at line 1871 of file Utils.cxx.

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

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

1872  {
1873  unsigned short ntp = 0;
1874  for(unsigned short ipt = firstPt; ipt <= lastPt; ++ipt) if(tj.Pts[ipt].Chg > 0) ++ntp;
1875  // Add the count of deadwires
1876  if(includeDeadWires) ntp += DeadWireCount(slc, tj.Pts[firstPt], tj.Pts[lastPt]);
1877  return ntp;
1878  } // NumPtsWithCharge
float DeadWireCount(TCSlice &slc, const float &inWirePos1, const float &inWirePos2, CTP_t tCTP)
Definition: Utils.cxx:1887
unsigned short tca::NumUsedHitsInTj ( TCSlice slc,
const Trajectory tj 
)

Definition at line 3763 of file Utils.cxx.

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

Referenced by DotProd().

3764  {
3765  if(tj.AlgMod[kKilled]) return 0;
3766  if(tj.Pts.empty()) return 0;
3767  unsigned short nhits = 0;
3768  for(auto& tp : tj.Pts) {
3769  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) if(tp.UseHit[ii]) ++nhits;
3770  } // tp
3771  return nhits;
3772  } // NumHitsInTj
float tca::OverlapFraction ( TCSlice slc,
const Trajectory tj1,
const Trajectory tj2 
)

Definition at line 664 of file Utils.cxx.

References tca::Trajectory::Pts.

Referenced by CompatibleMerge(), and EndMerge().

665  {
666  // returns the fraction of wires spanned by two trajectories
667  float minWire = 1E6;
668  float maxWire = -1E6;
669 
670  float cnt1 = 0;
671  for(auto& tp : tj1.Pts) {
672  if(tp.Chg == 0) continue;
673  if(tp.Pos[0] < 0) continue;
674  if(tp.Pos[0] < minWire) minWire = tp.Pos[0];
675  if(tp.Pos[0] > maxWire) maxWire = tp.Pos[0];
676  ++cnt1;
677  }
678  if(cnt1 == 0) return 0;
679  float cnt2 = 0;
680  for(auto& tp : tj2.Pts) {
681  if(tp.Chg == 0) continue;
682  if(tp.Pos[0] < 0) continue;
683  if(tp.Pos[0] < minWire) minWire = tp.Pos[0];
684  if(tp.Pos[0] > maxWire) maxWire = tp.Pos[0];
685  ++cnt2;
686  }
687  if(cnt2 == 0) return 0;
688  int span = maxWire - minWire;
689  if(span <= 0) return 0;
690  std::vector<unsigned short> wcnt(span);
691  for(auto& tp : tj1.Pts) {
692  if(tp.Chg == 0) continue;
693  if(tp.Pos[0] < -0.4) continue;
694  int indx = std::nearbyint(tp.Pos[0] - minWire);
695  if(indx < 0 || indx > span - 1) continue;
696  ++wcnt[indx];
697  }
698  for(auto& tp : tj2.Pts) {
699  if(tp.Chg == 0) continue;
700  if(tp.Pos[0] < -0.4) continue;
701  int indx = std::nearbyint(tp.Pos[0] - minWire);
702  if(indx < 0 || indx > span - 1) continue;
703  ++wcnt[indx];
704  }
705  float cntOverlap = 0;
706  for(auto cnt : wcnt) if(cnt > 1) ++cntOverlap;
707  if(cnt1 < cnt2) {
708  return cntOverlap / cnt1;
709  } else {
710  return cntOverlap / cnt2;
711  }
712 
713  } // OverlapFraction
float tca::ParentFOM ( std::string  inFcnLabel,
TCSlice slc,
PFPStruct pfp,
unsigned short  pend,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 2169 of file TCShower.cxx.

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

2170  {
2171  // Returns an average weighted parent FOM for all trajectories in the pfp being a parent of the 2D showers in ss3
2172  if(ss3.ID == 0) return 1000;
2173  float sum = 0;
2174  float wsum = 0;
2175  std::string fcnLabel = inFcnLabel + ".P3FOM";
2176  float dum1, dum2;
2177  for(auto cid : ss3.CotIDs) {
2178  auto& ss = slc.cots[cid - 1];
2179  if(ss.ID == 0) continue;
2180  // look for the 3D matched tj in this CTP
2181  int tjid = 0;
2182  for(auto tid : pfp.TjIDs) {
2183  auto& tj = slc.tjs[tid - 1];
2184  if(tj.ID == 0) continue;
2185  if(tj.CTP == ss.CTP) tjid = tid;
2186  } // tid
2187  if(tjid == 0) continue;
2188  auto& ptj = slc.tjs[tjid - 1];
2189  auto& stj = slc.tjs[ss.ShowerTjID - 1];
2190  // determine which end is farthest away from the shower center
2191  unsigned short ptjEnd = FarEnd(slc, ptj, stj.Pts[1].Pos);
2192  auto& farTP = ptj.Pts[ptj.EndPt[ptjEnd]];
2193  float chgCtrSep2 = PosSep2(farTP.Pos, stj.Pts[1].Pos);
2194  if(chgCtrSep2 < PosSep2(farTP.Pos, stj.Pts[0].Pos) && chgCtrSep2 < PosSep2(farTP.Pos, stj.Pts[2].Pos)) continue;
2195  float fom = ParentFOM(fcnLabel, slc, ptj, ptjEnd, ss, dum1, dum2, prt);
2196  // ignore failures
2197  if(fom > 50) continue;
2198  // weight by the 1/aspect ratio
2199  float wt = 1;
2200  if(ss.AspectRatio > 0) wt = 1 / ss.AspectRatio;
2201  sum += wt * fom;
2202  wsum += wt;
2203  } // cid
2204  if(wsum == 0) return 100;
2205  float fom = sum / wsum;
2206  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" P"<<pfp.ID<<" fom "<<std::fixed<<std::setprecision(3)<<fom;
2207  return fom;
2208  } // ParentFOM
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
Float_t ss
Definition: plot.C:23
float ParentFOM(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, unsigned short &tjEnd, ShowerStruct &ss, float &tp1Sep, float &vx2Score, bool prt)
Definition: TCShower.cxx:2211
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1660
unsigned short FarEnd(TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3032
float tca::ParentFOM ( std::string  inFcnLabel,
TCSlice slc,
Trajectory tj,
unsigned short &  tjEnd,
ShowerStruct ss,
float &  tp1Sep,
float &  vx2Score,
bool  prt 
)

Definition at line 2211 of file TCShower.cxx.

References 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, tcc, tca::ShowerStruct::TjIDs, tca::TCSlice::tjs, tca::Trajectory::VtxID, tca::TCSlice::vtxs, and tca::TCConfig::wirePitch.

Referenced by ParentFOM(), and SetParent().

2212  {
2213  // returns a FOM for the trajectory at the end point being the parent of ss and the end which
2214  // was matched.
2215 
2216  vx2Score = 0;
2217  tp1Sep = 0;
2218 
2219  if(tjEnd > 1) return 1000;
2220  if(ss.Energy == 0) return 1000;
2221 
2222  if(ss.ID == 0) return 1000;
2223  if(ss.TjIDs.empty()) return 1000;
2224  if(ss.ShowerTjID == 0) return 1000;
2225 
2226  std::string fcnLabel = inFcnLabel + ".PFOM";
2227 
2228  if(ss.AspectRatio > 0.5) {
2229  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 2S"<<ss.ID<<" poor AspectRatio "<<ss.AspectRatio<<" FOM not calculated";
2230  return 100;
2231  }
2232 
2233  float fom = 0;
2234  float cnt = 0;
2235  auto& stj = slc.tjs[ss.ShowerTjID - 1];
2236  TrajPoint& stp0 = stj.Pts[0];
2237  // Shower charge center TP
2238  TrajPoint& stp1 = stj.Pts[1];
2239  // get the end that is farthest away from the shower center
2240  tjEnd = FarEnd(slc, tj, stp1.Pos);
2241  // prospective parent TP
2242  TrajPoint& ptp = tj.Pts[tj.EndPt[tjEnd]];
2243  // find the along and trans components in WSE units relative to the
2244  // shower center
2245  Point2_t alongTrans;
2246  FindAlongTrans(stp1.Pos, stp1.Dir, ptp.Pos, alongTrans);
2247  // We can return here if the shower direction is well defined and
2248  // alongTrans[0] is > 0
2249  if(ss.AspectRatio < 0.2 && ss.DirectionFOM < 0.5 && alongTrans[0] > 0) return 100;
2250  tp1Sep = std::abs(alongTrans[0]);
2251  // Find the expected shower start relative to shower max (cm)
2252  double shMaxAlong, shE95Along;
2253  ShowerParams(ss.Energy, shMaxAlong, shE95Along);
2254  double alongcm = tcc.wirePitch * tp1Sep;
2255  // InShowerProbLong expects the longitudinal distance relative to shower max so it
2256  // should be < 0
2257  float prob = InShowerProbLong(ss.Energy, -alongcm);
2258  if(prob < 0.05) return 100;
2259  // The transverse position must certainly be less than the longitudinal distance
2260  // to shower max.
2261  if(alongTrans[1] > shMaxAlong) return 100;
2262  // longitudinal contribution to fom with 1 Xo error error (14 cm)
2263  float longFOM = std::abs(alongcm + shMaxAlong) / 14;
2264  fom += longFOM;
2265  ++cnt;
2266  // transverse contribution
2267  float transFOM = -1;
2268  if(stp0.DeltaRMS > 0) {
2269  transFOM = alongTrans[1] / stp0.DeltaRMS;
2270  fom += transFOM;
2271  ++cnt;
2272  }
2273  // make a tp between the supposed parent TP and the shower center
2274  TrajPoint tp;
2275  if(!MakeBareTrajPoint(slc, ptp, stp1, tp)) return 100;
2276  // we have three angles to compare. The ptp angle, the shower angle and
2277  // the tp angle.
2278  float dang1 = DeltaAngle(ptp.Ang, stp1.Ang);
2279  float dang1FOM = dang1 / 0.1;
2280  fom += dang1FOM;
2281  ++cnt;
2282  float dang2 = DeltaAngle(ptp.Ang, tp.Ang);
2283  float dang2FOM = dang1 / 0.1;
2284  fom += dang2FOM;
2285  ++cnt;
2286  // the environment near the parent start should be clean.
2287  std::vector<int> tjlist(1);
2288  tjlist[0] = tj.ID;
2289  // check for a vertex at this end and include the vertex tjs if the vertex is close
2290  // to the expected shower max position
2291  float vx2Sep = 0;
2292  // put in a largish FOM value for Tjs that don't have a vertex
2293  float vxFOM = 10;
2294  if(tj.VtxID[tjEnd] > 0) {
2295  VtxStore& vx2 = slc.vtxs[tj.VtxID[tjEnd] - 1];
2296  vx2Sep = PosSep(vx2.Pos, stp1.Pos);
2297  vx2Score = vx2.Score;
2298  tjlist = GetAssns(slc, "2V", vx2.ID, "T");
2299 // tjlist = GetVtxTjIDs(slc, vx2);
2300  vxFOM = std::abs(shMaxAlong - vx2Sep) / 20;
2301  } // 2D vertex exists
2302  fom += vxFOM;
2303  ++cnt;
2304  float chgFrac = ChgFracNearPos(slc, ptp.Pos, tjlist);
2305  float chgFracFOM = (1 - chgFrac) / 0.1;
2306  fom += chgFracFOM;
2307  ++cnt;
2308  // Fraction of wires that have a signal between the parent start and the shower center
2309  float chgFracBtw = ChgFracBetween(slc, ptp, stp1.Pos[0]);
2310  float chgFrcBtwFOM = (1 - chgFrac) / 0.05;
2311  fom += chgFrcBtwFOM;
2312  ++cnt;
2313 
2314  // take the average
2315  fom /= cnt;
2316  // divide by the InShowerProbability
2317  fom /= prob;
2318 
2319  if(prt) {
2320  mf::LogVerbatim myprt("TC");
2321  myprt<<fcnLabel;
2322  myprt<<" 2S"<<ss.ID;
2323  myprt<<" T"<<tj.ID<<"_"<<tjEnd<<" Pos "<<PrintPos(slc, ptp);
2324  myprt<<std::fixed<<std::setprecision(2);
2325  myprt<<" along "<<std::fixed<<std::setprecision(1)<<alongTrans[0]<<" fom "<<longFOM;
2326  myprt<<" trans "<<alongTrans[1]<<" fom "<<transFOM;
2327  myprt<<" prob "<<prob;
2328  myprt<<" dang1 "<<dang1<<" fom "<<dang1FOM;
2329  myprt<<" dang2 "<<dang2<<" fom "<<dang2FOM;
2330  myprt<<" vx2Score "<<vx2Score<<" fom "<<vxFOM;
2331  myprt<<" chgFrac "<<chgFrac<<" fom "<<chgFracFOM;
2332  myprt<<" chgFracBtw "<<chgFracBtw<<" fom "<<chgFrcBtwFOM;
2333  myprt<<" FOM "<<fom;
2334  }
2335  return fom;
2336 
2337  } // ParentFOM
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeBareTrajPoint(TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:3581
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4279
double InShowerProbLong(double showerEnergy, double along)
Definition: TCShower.cxx:2049
TCConfig tcc
Definition: DataStructs.cxx:6
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:2849
Float_t ss
Definition: plot.C:23
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1636
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
unsigned short FarEnd(TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3032
float ChgFracNearPos(TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2698
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
Definition: TCShower.cxx:2015
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
float ChgFracBetween(TCSlice &slc, Point3_t pos1, Point3_t pos2)
Definition: PFPUtils.cxx:2957
unsigned short tca::PDGCodeIndex ( int  PDGCode)

Definition at line 1908 of file Utils.cxx.

Referenced by tca::TruthMatcher::MatchAndSum().

1909  {
1910  unsigned short pdg = abs(PDGCode);
1911  if(pdg == 11) return 0; // electron
1912  if(pdg == 13) return 1; // muon
1913  if(pdg == 211) return 2; // pion
1914  if(pdg == 321) return 3; // kaon
1915  if(pdg == 2212) return 4; // proton
1916 
1917  return USHRT_MAX;
1918 
1919  } // PDGCodeIndex
int tca::PDGCodeVote ( TCSlice slc,
std::vector< int > &  tjIDs,
bool  prt 
)

Definition at line 372 of file Utils.cxx.

References tca::TCSlice::tjs, and TrajLength().

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

373  {
374  // Returns the most likely PDGCode for the set of Tjs provided
375  // The PDG codes are:
376  // 0 = your basic track-like trajectory
377  // 11 = Tagged delta-ray
378  // 13 = Tagged muon
379  // 211 = pion-like. There exists a Bragg peak at an end with a vertex
380  // 2212 = proton-like. There exists a Bragg peak at an end without a vertex
381  std::array<int, 5> codeList = {{0, 11, 13, 111, 211}};
382  unsigned short codeIndex = 0;
383  if(tjIDs.empty()) return codeList[codeIndex];
384 
385  std::array<unsigned short, 5> cnts;
386  cnts.fill(0);
387  // Count Bragg peaks. This assumes that the Tjs are in order...
388 // std::array<unsigned short, 2> stopCnt {{0, 0}};
389  float maxLen = 0;
390  for(auto tjid : tjIDs) {
391  if(tjid <= 0 || tjid > (int)slc.tjs.size()) continue;
392  auto& tj = slc.tjs[tjid - 1];
393  for(unsigned short ii = 0; ii < 5; ++ii) if(tj.PDGCode == codeList[ii]) ++cnts[ii];
394  // count InShower Tjs with PDGCode not set (yet)
395 // if(tj.PDGCode != 11 && tj.AlgMod[kShowerLike]) ++cnts[1];
396 // for(unsigned short end = 0; end < 2; ++end) if(tj.StopFlag[end][kBragg]) ++stopCnt[end];
397  float len = TrajLength(tj);
398  if(len > maxLen) maxLen = len;
399  } // tjid
400  unsigned maxCnt = 0;
401  // ignore the first PDG code in the list (the default)
402  for(unsigned short ii = 1; ii < 5; ++ii) {
403  if(cnts[ii] > maxCnt) {
404  maxCnt = cnts[ii];
405  codeIndex = ii;
406  }
407  } // ii
408 
409  return codeList[codeIndex];
410  } // PDGCodeVote
float TrajLength(Trajectory &tj)
Definition: Utils.cxx:2337
float tca::PFPDOCA ( const PFPStruct pfp1,
const PFPStruct pfp2,
unsigned short &  close1,
unsigned short &  close2 
)

Definition at line 1790 of file PFPUtils.cxx.

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

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

1791  {
1792  // returns the Distance of Closest Approach between two PFParticles.
1793  close1 = USHRT_MAX;
1794  close2 = USHRT_MAX;
1795  float minSep2 = 1E8;
1796  for(unsigned short ipt1 = 0; ipt1 < pfp1.Tp3s.size(); ++ipt1) {
1797  auto& tp1 = pfp1.Tp3s[ipt1];
1798  for(unsigned short ipt2 = 0; ipt2 < pfp2.Tp3s.size(); ++ipt2) {
1799  auto& tp2 = pfp2.Tp3s[ipt2];
1800  float sep2 = PosSep2(tp1.Pos, tp2.Pos);
1801  if(sep2 > minSep2) continue;
1802  minSep2 = sep2;
1803  close1 = ipt1;
1804  close2 = ipt2;
1805  } // tp2
1806  } // tp1
1807  return sqrt(minSep2);
1808  } // PFPDOCA
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1660
void tca::PFPVertexCheck ( TCSlice slc)

Definition at line 2502 of file PFPUtils.cxx.

References evt, tca::TCEvent::globalS3ID, tca::Vtx3Store::ID, tca::TCSlice::isValid, tca::TCSlice::nPlanes, tca::TCSlice::pfps, tca::Vtx3Store::Primary, tca::Vtx3Store::TPCID, geo::TPCID::TPCID(), tca::Vtx3Store::UID, tca::TCSlice::vtx3s, tca::Vtx3Store::Vx2ID, tca::Vtx3Store::Wire, tca::Vtx3Store::X, tca::Vtx3Store::Y, and tca::Vtx3Store::Z.

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

2503  {
2504  // Ensure that all PFParticles have a start vertex. It is possible for
2505  // PFParticles to be attached to a 3D vertex that is later killed.
2506  if(!slc.isValid) return;
2507 
2508  for(auto& pfp : slc.pfps) {
2509  if(pfp.ID == 0) continue;
2510  if(pfp.Vx3ID[0] > 0) continue;
2511  Vtx3Store vx3;
2512  vx3.TPCID = pfp.TPCID;
2513  vx3.Vx2ID.resize(slc.nPlanes);
2514  // Flag it as a PFP vertex that isn't required to have matched 2D vertices
2515  vx3.Wire = -2;
2516  vx3.X = pfp.XYZ[0][0];
2517  vx3.Y = pfp.XYZ[0][1];
2518  vx3.Z = pfp.XYZ[0][2];
2519  vx3.ID = slc.vtx3s.size() + 1;
2520  vx3.Primary = false;
2521  ++evt.globalS3ID;
2522  vx3.UID = evt.globalS3ID;
2523  slc.vtx3s.push_back(vx3);
2524 // std::cout<<"PFPVertexCheck: P"<<pfp.ID<<" create 3V"<<vx3.ID<<"\n";
2525  pfp.Vx3ID[0] = vx3.ID;
2526  } // pfp
2527  } // PFPVertexCheck
TCEvent evt
Definition: DataStructs.cxx:5
bool tca::PFPVxTjOK ( TCSlice slc,
PFPStruct pfp,
bool  prt 
)

Definition at line 2366 of file PFPUtils.cxx.

References GetVtxTjIDs(), tca::PFPStruct::ID, SetIntersection(), tca::PFPStruct::TjIDs, tca::TCSlice::tjs, tmp, tca::TCSlice::vtx3s, tca::TCSlice::vtxs, and tca::PFPStruct::Vx3ID.

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

2367  {
2368  // Checks the PFP Vx3 -> Vx2 -> Tj assignment to see if there is more
2369  // than one tj in a plane in the pfp.TjIDs list that is attached to the same 2D vertex.
2370  // This problem is fixed by removing the shorter tj from the TjIDs list. This function
2371  // return true if nothing was done to TjIDs
2372  if(pfp.ID == 0) return true;
2373  if(pfp.TjIDs.empty()) return true;
2374  if(pfp.Vx3ID[0] <= 0 || pfp.Vx3ID[0] > (int)slc.vtx3s.size()) return true;
2375 
2376  auto& vx3 = slc.vtx3s[pfp.Vx3ID[0] - 1];
2377  std::vector<int> killMe;
2378  for(auto vx2id : vx3.Vx2ID) {
2379  if(vx2id == 0) continue;
2380  auto& vx2 = slc.vtxs[vx2id - 1];
2381  auto tjlist = GetVtxTjIDs(slc, vx2);
2382  auto setInt = SetIntersection(pfp.TjIDs, tjlist);
2383 /*
2384  std::cout<<"PVTC: P"<<pfp.ID<<" Tjs";
2385  for(auto tid : pfp.TjIDs) std::cout<<" T"<<tid;
2386  std::cout<<" set Intersection";
2387  for(auto tid : setInt) std::cout<<" T"<<tid;
2388  std::cout<<"\n";
2389 */
2390  if(setInt.size() < 2) continue;
2391  // find the longest one
2392  int imLong = 0;
2393  unsigned short lenth = 0;
2394  for(auto tid : setInt) {
2395  auto& tj = slc.tjs[tid - 1];
2396  unsigned short npts = tj.EndPt[1] - tj.EndPt[0] + 1;
2397  if(npts < lenth) continue;
2398  lenth = npts;
2399  imLong = tj.ID;
2400  } // tid
2401  if(imLong == 0) continue;
2402  // add the others to the killMe list
2403  for(auto tid : setInt) if(tid != imLong) killMe.push_back(tid);
2404  } // vx2id
2405  if(killMe.empty()) return true;
2406  if(prt) {
2407  mf::LogVerbatim myprt("TC");
2408  myprt<<"PVTC: P"<<pfp.ID<<" removing short tjs attached to a vertex:";
2409  for(auto tid : killMe) myprt<<" T"<<tid;
2410  }
2411  // re-create the TjIDs vector
2412  std::vector<int> tmp;
2413  for(auto tid : pfp.TjIDs) {
2414  if(std::find(killMe.begin(), killMe.end(), tid) == killMe.end()) tmp.push_back(tid);
2415  } // tid
2416  pfp.TjIDs = tmp;
2417  return false;
2418  } // 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:231
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const VtxStore &vx2)
Definition: TCVertex.cxx:3226
Vector3_t tca::PointDirection ( const Point3_t  p1,
const Point3_t  p2 
)

Definition at line 1643 of file PFPUtils.cxx.

References dir, and SetMag().

Referenced by ChgFracBetween(), CreateFakePFP(), DefineDontCluster(), DotProd(), FindAlongTrans(), FindParent(), FollowTp3s(), and UpdateShower().

1644  {
1645  // Finds the direction vector between the two points from p1 to p2
1646  Vector3_t dir;
1647  for(unsigned short xyz = 0; xyz < 3; ++xyz) dir[xyz] = p2[xyz] - p1[xyz];
1648  if(dir[0] == 0 && dir[1] == 0 && dir[2] == 0) return dir;
1649  if(!SetMag(dir, 1)) { dir[0] = 0; dir[1] = 0; dir[3] = 0; }
1650  return dir;
1651  } // PointDirection
bool SetMag(Vector3_t &v1, double mag)
Definition: PFPUtils.cxx:1670
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 3655 of file Utils.cxx.

References dir, and norm.

Referenced by MakeBareTrajPoint().

3656  {
3657  // Finds the direction vector between the two points from p1 to p2
3658  Vector2_t dir;
3659  for(unsigned short xyz = 0; xyz < 2; ++xyz) dir[xyz] = p2[xyz] - p1[xyz];
3660  if(dir[0] == 0 && dir[1] == 0) return dir;
3661  double norm = sqrt(dir[0] * dir[0] + dir[1] * dir[1]);
3662  dir[0] /= norm;
3663  dir[1] /= norm;
3664  return dir;
3665  } // 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 2867 of file PFPUtils.cxx.

References LineLineIntersect().

Referenced by DotProd().

2868  {
2869  // Point - vector version
2870  Point3_t p1End, p2End;
2871  for(unsigned short xyz = 0; xyz < 3; ++xyz) {
2872  p1End[xyz] = p1[xyz] + 10 * p1Dir[xyz];
2873  p2End[xyz] = p2[xyz] + 10 * p2Dir[xyz];
2874  }
2875  return LineLineIntersect(p1, p1End, p2, p2End, intersect, doca);
2876  } // 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:2879
bool tca::PointInsideEnvelope ( const Point2_t Point,
const std::vector< Point2_t > &  Envelope 
)

Definition at line 2781 of file Utils.cxx.

References DeltaAngle().

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

2782  {
2783  // returns true if the Point is within the Envelope polygon. Entries in Envelope are the
2784  // Pos[0], Pos[1] locations of the polygon vertices. This is based on the algorithm that the
2785  // sum of the angles of a vector between a point and the vertices will be 2 * pi for an interior
2786  // point and 0 for an exterior point
2787 
2788  Point2_t p1, p2;
2789  unsigned short nvx = Envelope.size();
2790  double angleSum = 0;
2791  for(unsigned short ii = 0; ii < Envelope.size(); ++ii) {
2792  p1[0] = Envelope[ii][0] - Point[0];
2793  p1[1] = Envelope[ii][1] - Point[1];
2794  p2[0] = Envelope[(ii+1)%nvx][0] - Point[0];
2795  p2[1] = Envelope[(ii+1)%nvx][1] - Point[1];
2796  angleSum += DeltaAngle(p1, p2);
2797  }
2798  if(abs(angleSum) < M_PI) return false;
2799  return true;
2800 
2801  } // 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:2858
float tca::PointTrajDOCA ( TCSlice slc,
unsigned int  iht,
TrajPoint const &  tp 
)

Definition at line 2270 of file Utils.cxx.

References tca::TCEvent::allHits, evt, PointTrajDOCA2(), tca::TCSlice::slHits, tcc, and tca::TCConfig::unitsPerTick.

Referenced by AddHits(), CheckHiMultUnusedHits(), ChkVxTjs(), CompleteIncomplete3DVerticesInGaps(), EndMerge(), FillGaps(), FindHammerVertices2(), FindNearbyTjs(), FindUseHits(), FixTrajBegin(), FixTrajEnd(), Forecast(), HiEndDelta(), MaskTrajEndPoints(), MergeShowerChain(), MergeSubShowers(), MergeSubShowersTj(), SplitTrajCrossingVertices(), TrajPointVertexPull(), UpdateDeltaRMS(), UpdateStiffEl(), UpdateTraj(), and VtxHitsSwap().

2271  {
2272  if(iht > slc.slHits.size() - 1) return 1E6;
2273  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2274  float wire = hit.WireID().Wire;
2275  float time = hit.PeakTime() * tcc.unitsPerTick;
2276  return sqrt(PointTrajDOCA2(slc, wire, time, tp));
2277  } // PointTrajDOCA
TCConfig tcc
Definition: DataStructs.cxx:6
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
float PointTrajDOCA2(TCSlice &slc, float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2286
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
float tca::PointTrajDOCA ( TCSlice slc,
float  wire,
float  time,
TrajPoint const &  tp 
)

Definition at line 2280 of file Utils.cxx.

References PointTrajDOCA2().

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

2281  {
2282  return sqrt(PointTrajDOCA2(slc, wire, time, tp));
2283  } // PointTrajDOCA
float PointTrajDOCA2(TCSlice &slc, float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2286
float tca::PointTrajDOCA2 ( TCSlice slc,
float  wire,
float  time,
TrajPoint const &  tp 
)

Definition at line 2286 of file Utils.cxx.

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

Referenced by PointTrajDOCA(), and TjDeltaRMS().

2287  {
2288  // returns the distance of closest approach squared between a (wire, time(WSE)) point
2289  // and a trajectory point
2290 
2291  double t = (double)(wire - tp.Pos[0]) * tp.Dir[0] + (double)(time - tp.Pos[1]) * tp.Dir[1];
2292  double dw = tp.Pos[0] + t * tp.Dir[0] - wire;
2293  double dt = tp.Pos[1] + t * tp.Dir[1] - time;
2294  return (float)(dw * dw + dt * dt);
2295 
2296  } // PointTrajDOCA2
float tca::PointTrajSep2 ( float  wire,
float  time,
TrajPoint const &  tp 
)

Definition at line 2262 of file Utils.cxx.

References tca::TrajPoint::Pos.

2263  {
2264  float dw = wire - tp.Pos[0];
2265  float dt = time - tp.Pos[1];
2266  return dw * dw + dt * dt;
2267  }
void tca::PosInPlane ( const TCSlice slc,
const Vtx3Store vx3,
unsigned short  plane,
Point2_t pos 
)

Definition at line 3287 of file TCVertex.cxx.

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

Referenced by AttachPFPToVertex(), Print3V(), and PrintAllTraj().

3288  {
3289  // returns the 2D position of the vertex in the plane
3290  pos[0] = tcc.geom->WireCoordinate(vx3.Y, vx3.Z, plane, vx3.TPCID.TPC, vx3.TPCID.Cryostat);
3291  pos[1] = tcc.detprop->ConvertXToTicks(vx3.X, plane, vx3.TPCID.TPC, vx3.TPCID.Cryostat) * tcc.unitsPerTick;
3292 
3293  } // PosInPlane
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
TCConfig tcc
Definition: DataStructs.cxx:6
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
const detinfo::DetectorProperties * detprop
Definition: DataStructs.h:494
const geo::GeometryCore * geom
Definition: DataStructs.h:493
float tca::PosSep ( const Point2_t pos1,
const Point2_t pos2 
)

Definition at line 2353 of file Utils.cxx.

References PosSep2().

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

2354  {
2355  return sqrt(PosSep2(pos1, pos2));
2356  } // PosSep
float PosSep2(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2359
double tca::PosSep2 ( const Point3_t pos1,
const Point3_t pos2 
)

Definition at line 1660 of file PFPUtils.cxx.

Referenced by AttachTrajToVertex(), DotProd(), EndMerge(), FarEnd(), Find2DVertices(), FindKinks(), FindParent(), FitTp3(), FollowTp3s(), KinkAngle(), LengthInCTP(), MergeOverlap(), ParentFOM(), PFPDOCA(), PosSep(), StepAway(), StitchPFPs(), TrajPointVertexPull(), and UpdateShower().

1661  {
1662  // returns the separation distance^2 between two positions in 3D
1663  double d0 = pos1[0] - pos2[0];
1664  double d1 = pos1[1] - pos2[1];
1665  double d2 = pos1[2] - pos2[2];
1666  return d0*d0 + d1*d1 + d2*d2;
1667  } // PosSep2
float tca::PosSep2 ( const Point2_t pos1,
const Point2_t pos2 
)

Definition at line 2359 of file Utils.cxx.

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

2360  {
2361  // returns the separation distance^2 between two positions
2362  float d0 = pos1[0] - pos2[0];
2363  float d1 = pos1[1] - pos2[1];
2364  return d0*d0+d1*d1;
2365  } // PosSep2
int tca::PrimaryID ( TCSlice slc,
const Trajectory tj 
)

Definition at line 463 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::ID, kHaloTj, kKilled, tca::Trajectory::ParentID, and tca::TCSlice::tjs.

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

464  {
465  // Returns the ID of the grandparent trajectory of this trajectory that is a primary
466  // trajectory (i.e. whose ParentID = 0).
467  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) return -1;
468  if(tj.ParentID < 0 || tj.ParentID > (int)slc.tjs.size()) return -1;
469  if(tj.ParentID == 0) return tj.ID;
470  int parid = tj.ParentID;
471  for(unsigned short nit = 0; nit < 10; ++nit) {
472  if(parid < 1 || parid > (int)slc.tjs.size()) break;
473  auto& tj = slc.tjs[parid - 1];
474  if(tj.ParentID < 0 || tj.ParentID > (int)slc.tjs.size()) return -1;
475  if(tj.ParentID == 0) return tj.ID;
476  parid = tj.ParentID;
477  } // nit
478  return -1;
479  } // PrimaryID
int tca::PrimaryUID ( TCSlice slc,
const PFPStruct pfp 
)

Definition at line 482 of file Utils.cxx.

References GetSliceIndex(), tca::PFPStruct::ID, tca::PFPStruct::ParentUID, slices, and tca::PFPStruct::UID.

Referenced by PrintPFP().

483  {
484  // returns the UID of the most upstream PFParticle (that is not a neutrino)
485 
486  if(int(pfp.ParentUID) == pfp.UID || pfp.ParentUID <= 0) return pfp.ID;
487  int paruid = pfp.ParentUID;
488  int dtruid = pfp.UID;
489  unsigned short nit = 0;
490  while(true) {
491  auto slcIndx = GetSliceIndex("P", paruid);
492  auto& parent = slices[slcIndx.first].pfps[slcIndx.second];
493  // found a neutrino
494  if(parent.PDGCode == 14 || parent.PDGCode == 12) return dtruid;
495  // found a primary PFParticle?
496  if(parent.ParentUID == 0) return parent.UID;
497  if(int(parent.ParentUID) == parent.UID) return parent.UID;
498  dtruid = parent.UID;
499  paruid = parent.ParentUID;
500  if(paruid < 0) return 0;
501  ++nit;
502  if(nit == 10) return 0;
503  }
504  } // PrimaryUID
std::vector< TCSlice > slices
Definition: DataStructs.cxx:10
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:4496
void tca::Print2DShowers ( std::string  someText,
TCSlice slc,
CTP_t  inCTP,
bool  printKilledShowers 
)

Definition at line 4648 of file TCShower.cxx.

References tca::TCSlice::cots, tca::TCSlice::dontCluster, DontCluster(), nlines, PrintShower(), ss, tcc, util::flags::to_string(), and tca::TCConfig::unitsPerTick.

Referenced by FindShowers3D(), and Reconcile3D().

4649  {
4650  // Prints a one-line summary of 2D showers
4651  if(slc.cots.empty()) return;
4652 
4653  mf::LogVerbatim myprt("TC");
4654 
4655  // see how many lines were are going to print
4656  bool printAllCTP = (inCTP == USHRT_MAX);
4657  if(!printAllCTP) {
4658  unsigned short nlines = 0;
4659  for(const auto& ss : slc.cots) {
4660  if(!printAllCTP && ss.CTP != inCTP) continue;
4661  if(!printKilledShowers && ss.ID == 0) continue;
4662  ++nlines;
4663  } // ss
4664  if(nlines == 0) {
4665  myprt<<someText<<" Print2DShowers: Nothing to print";
4666  return;
4667  }
4668  } // !printAllCTP
4669 
4670  bool printHeader = true;
4671  bool printExtras = false;
4672  for(unsigned short ict = 0; ict < slc.cots.size(); ++ict) {
4673  const auto& ss = slc.cots[ict];
4674  if(!printAllCTP && ss.CTP != inCTP) continue;
4675  if(!printKilledShowers && ss.ID == 0) continue;
4676  PrintShower(someText, slc, ss, printHeader, printExtras);
4677  printHeader = false;
4678  } // ss
4679  // List of Tjs
4680  for(unsigned short ict = 0; ict < slc.cots.size(); ++ict) {
4681  const auto& ss = slc.cots[ict];
4682  if(!printAllCTP && ss.CTP != inCTP) continue;
4683  if(!printKilledShowers && ss.ID == 0) continue;
4684  myprt<<someText<<std::fixed;
4685  std::string sid = "2S" + std::to_string(ss.ID);
4686  myprt<<std::setw(5)<<sid;
4687  myprt<<" Tjs";
4688  for(auto id : ss.TjIDs) myprt<<" T"<<id;
4689  myprt<<"\n";
4690  } // ict
4691  // Print the envelopes
4692  for(unsigned short ict = 0; ict < slc.cots.size(); ++ict) {
4693  const auto& ss = slc.cots[ict];
4694  if(!printAllCTP && ss.CTP != inCTP) continue;
4695  if(!printKilledShowers && ss.ID == 0) continue;
4696  myprt<<someText<<std::fixed;
4697  std::string sid = "2S" + std::to_string(ss.ID);
4698  myprt<<std::setw(5)<<sid;
4699  myprt<<" Envelope";
4700  for(auto& vtx : ss.Envelope) myprt<<" "<<(int)vtx[0]<<":"<<(int)(vtx[1]/tcc.unitsPerTick);
4701  myprt<<"\n";
4702  } // ict
4703  // List of nearby Tjs
4704  for(unsigned short ict = 0; ict < slc.cots.size(); ++ict) {
4705  const auto& ss = slc.cots[ict];
4706  if(!printAllCTP && ss.CTP != inCTP) continue;
4707  if(!printKilledShowers && ss.ID == 0) continue;
4708  myprt<<someText<<std::fixed;
4709  std::string sid = "2S" + std::to_string(ss.ID);
4710  myprt<<std::setw(5)<<sid;
4711  myprt<<" Nearby";
4712  for(auto id : ss.NearTjIDs) myprt<<" T"<<id;
4713  myprt<<"\n";
4714  } // ict
4715  // don't cluster list
4716  myprt<<"DontCluster";
4717  for(auto& dc : slc.dontCluster) {
4718  if(dc.TjIDs[0] > 0) myprt<<" T"<<dc.TjIDs[0]<<"-T"<<dc.TjIDs[1];
4719  } // dc
4720  myprt<<"\nDontCluster";
4721  for(unsigned short ict = 0; ict < slc.cots.size(); ++ict) {
4722  const auto& iss = slc.cots[ict];
4723  if(iss.ID == 0) continue;
4724  for(unsigned short jct = ict + 1; jct < slc.cots.size(); ++jct) {
4725  const auto& jss = slc.cots[jct];
4726  if(jss.ID == 0) continue;
4727  if(DontCluster(slc, iss.TjIDs, jss.TjIDs)) myprt<<" 2S"<<iss.ID<<"-2S"<<jss.ID;
4728  } // jct
4729  } // ict
4730  } // Print2DShowers
TCConfig tcc
Definition: DataStructs.cxx:6
Float_t ss
Definition: plot.C:23
void PrintShower(std::string someText, TCSlice &slc, const ShowerStruct &ss, bool printHeader, bool printExtras)
Definition: TCShower.cxx:4733
bool DontCluster(TCSlice &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3313
nlines
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Definition: BitMask.h:187
void tca::Print2V ( std::string  someText,
mf::LogVerbatim myprt,
VtxStore vx2 
)

Definition at line 5026 of file Utils.cxx.

References tca::VtxStore::ChiDOF, tca::VtxStore::CTP, debug, DecodeCTP(), evd::details::end(), GetSliceIndex(), tca::VtxStore::ID, kKilled, tca::VtxStore::NTraj, tca::VtxStore::Pass, tca::DebugStuff::Plane, geo::PlaneID::Plane, tca::VtxStore::Pos, tca::VtxStore::PosErr, art::right(), tca::VtxStore::Score, slices, tca::VtxStore::Stat, tcc, tca::VtxStore::TjChgFrac, util::flags::to_string(), tca::VtxStore::Topo, tca::VtxStore::UID, tca::TCConfig::unitsPerTick, VtxBitNames, and tca::VtxStore::Vx3ID.

Referenced by DotProd(), and PrintAll().

5027  {
5028  // print a 2D vertex on one line
5029  if(vx2.ID <= 0) return;
5030  if(debug.Plane >= 0 && debug.Plane != (int)DecodeCTP(vx2.CTP).Plane) return;
5031  auto sIndx = GetSliceIndex("2V", vx2.UID);
5032  if(sIndx.first == USHRT_MAX) return;
5033  auto& slc = slices[sIndx.first];
5034 // myprt<<someText;
5035  std::string str = std::to_string(slc.ID) + ":" + std::to_string(sIndx.first) + ":" + std::to_string(vx2.ID);
5036  str += "/" + std::to_string(vx2.UID);
5037  myprt<<std::right<<std::setw(12)<<std::fixed<<str;
5038  myprt<<std::right<<std::setw(6)<<vx2.CTP;
5039  myprt<<std::right<<std::setw(8)<<std::setprecision(0)<<std::nearbyint(vx2.Pos[0]);
5040  myprt<<std::right<<std::setw(5)<<std::setprecision(1)<<vx2.PosErr[0];
5041  myprt<<std::right<<std::setw(8)<<std::setprecision(0)<<std::nearbyint(vx2.Pos[1]/tcc.unitsPerTick);
5042  myprt<<std::right<<std::setw(5)<<std::setprecision(1)<<vx2.PosErr[1]/tcc.unitsPerTick;
5043  myprt<<std::right<<std::setw(7)<<vx2.ChiDOF;
5044  myprt<<std::right<<std::setw(5)<<vx2.NTraj;
5045  myprt<<std::right<<std::setw(5)<<vx2.Pass;
5046  myprt<<std::right<<std::setw(6)<<vx2.Topo;
5047  myprt<<std::right<<std::setw(9)<<std::setprecision(2)<<vx2.TjChgFrac;
5048  myprt<<std::right<<std::setw(6)<<std::setprecision(1)<<vx2.Score;
5049  int v3id = 0;
5050  if(vx2.Vx3ID > 0) v3id = slc.vtx3s[vx2.Vx3ID - 1].UID;
5051  myprt<<std::right<<std::setw(5)<<v3id;
5052  myprt<<" ";
5053  // display the traj IDs
5054  for(unsigned short ii = 0; ii < slc.tjs.size(); ++ii) {
5055  auto const& tj = slc.tjs[ii];
5056  if(tj.AlgMod[kKilled]) continue;
5057  for(unsigned short end = 0; end < 2; ++end) {
5058  if(tj.VtxID[end] != (short)vx2.ID) continue;
5059  std::string tid = " T" + std::to_string(tj.UID) + "_" + std::to_string(end);
5060  myprt<<std::right<<std::setw(6)<<tid;
5061  } // end
5062  } // ii
5063  // Special flags. Ignore the first flag bit (0 = kVtxTrjTried) which is done for every vertex
5064  for(unsigned short ib = 1; ib < VtxBitNames.size(); ++ib) if(vx2.Stat[ib]) myprt<<" "<<VtxBitNames[ib];
5065  myprt<<"\n";
5066  } // Print2V
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:112
TCConfig tcc
Definition: DataStructs.cxx:6
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
DebugStuff debug
Definition: DebugStruct.cxx:4
int Plane
Select plane.
Definition: DebugStruct.h:21
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
std::vector< TCSlice > slices
Definition: DataStructs.cxx:10
const std::vector< std::string > VtxBitNames
Definition: DataStructs.cxx:91
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)
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:4496
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void tca::Print3S ( std::string  someText,
mf::LogVerbatim myprt,
ShowerStruct3D ss3 
)

Definition at line 5069 of file Utils.cxx.

References tca::ShowerStruct3D::ChgPos, tca::ShowerStruct3D::CotIDs, geo::CryostatID::Cryostat, tca::ShowerStruct3D::Dir, EncodeCTP(), GetSliceIndex(), tca::ShowerStruct3D::ID, MakeBareTP(), tca::ShowerStruct3D::NeedsUpdate, PrintPos(), slices, ss, util::flags::to_string(), geo::TPCID::TPC, tca::ShowerStruct3D::TPCID, tca::ShowerStruct3D::UID, and tca::ShowerStruct3D::Vx3ID.

Referenced by DotProd(), and PrintAll().

5070  {
5071  if(ss3.ID <= 0) return;
5072  auto sIndx = GetSliceIndex("3S", ss3.UID);
5073  if(sIndx.first == USHRT_MAX) return;
5074  auto& slc = slices[sIndx.first];
5075 // myprt<<someText;
5076  std::string str = std::to_string(slc.ID) + ":" + std::to_string(sIndx.first) + ":" + std::to_string(ss3.ID);
5077  str += "/" + std::to_string(ss3.UID);
5078  myprt<<std::fixed<<std::setw(12)<<str;
5079  str = "--";
5080  if(ss3.Vx3ID > 0) str = "3V" + std::to_string(slc.vtx3s[ss3.Vx3ID-1].UID);
5081  myprt<<std::setw(6)<<str;
5082  for(unsigned short xyz = 0; xyz < 3; ++xyz) myprt<<std::setprecision(0)<<std::setw(5)<<ss3.ChgPos[xyz];
5083  for(unsigned short xyz = 0; xyz < 3; ++xyz) myprt<<std::setprecision(2)<<std::setw(5)<<ss3.Dir[xyz];
5084  std::vector<float> projInPlane(slc.nPlanes);
5085  for(unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
5086  CTP_t inCTP = EncodeCTP(ss3.TPCID.Cryostat, ss3.TPCID.TPC, plane);
5087  auto tp = MakeBareTP(slc, ss3.ChgPos, ss3.Dir, inCTP);
5088  myprt<<" "<<PrintPos(slc, tp.Pos);
5089  projInPlane[plane] = tp.Delta;
5090  } // plane
5091  for(unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
5092  myprt<<std::setprecision(2)<<std::setw(5)<<projInPlane[plane];
5093  } // plane
5094  for(auto cid : ss3.CotIDs) {
5095  auto& ss = slc.cots[cid - 1];
5096  str = "2S" + std::to_string(ss.UID);
5097  myprt<<std::setw(5)<<str;
5098 /*
5099  auto& stj = slc.tjs[ss.ShowerTjID - 1];
5100  myprt<<" ST"<<stj.ID;
5101  myprt<<" "<<PrintPos(slc, stj.Pts[stj.EndPt[0]].Pos)<<" - "<<PrintPos(slc, stj.Pts[stj.EndPt[1]].Pos);
5102 */
5103  } // ci
5104  if(ss3.NeedsUpdate) myprt<<" *** Needs update";
5105  myprt<<"\n";
5106  } // Print3S
Float_t ss
Definition: plot.C:23
std::string PrintPos(TCSlice &slc, const Point2_t &pos)
Definition: Utils.cxx:5718
TrajPoint MakeBareTP(TCSlice &slc, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
Definition: Utils.cxx:3523
std::vector< TCSlice > slices
Definition: DataStructs.cxx:10
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
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:4496
void tca::Print3V ( std::string  someText,
mf::LogVerbatim myprt,
Vtx3Store vx3 
)

Definition at line 4959 of file Utils.cxx.

References geo::CryostatID::Cryostat, evd::details::end(), GetAssns(), GetSliceIndex(), tca::Vtx3Store::ID, kVtxTruMatch, tca::Vtx3Store::Neutrino, PosInPlane(), tca::Vtx3Store::Primary, PrintPos(), art::right(), tca::Vtx3Store::Score, slices, util::flags::to_string(), geo::TPCID::TPC, tca::Vtx3Store::TPCID, tca::Vtx3Store::UID, 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(), and PrintAll().

4960  {
4961  // print a 3D vertex on one line
4962  if(vx3.ID <= 0) return;
4963  auto sIndx = GetSliceIndex("3V", vx3.UID);
4964  if(sIndx.first == USHRT_MAX) return;
4965  auto& slc = slices[sIndx.first];
4966 // myprt<<someText;
4967  std::string str = std::to_string(slc.ID) + ":" + std::to_string(sIndx.first) + ":" + std::to_string(vx3.ID);
4968  str += "/" + std::to_string(vx3.UID);
4969  myprt<<std::right<<std::setw(12)<<std::fixed<<str;
4970  myprt<<std::setprecision(1);
4971  myprt<<std::right<<std::setw(7)<<vx3.TPCID.Cryostat;
4972  myprt<<std::right<<std::setw(5)<<vx3.TPCID.TPC;
4973  myprt<<std::right<<std::setw(8)<<vx3.X;
4974  myprt<<std::right<<std::setw(8)<<vx3.Y;
4975  myprt<<std::right<<std::setw(8)<<vx3.Z;
4976  myprt<<std::right<<std::setw(5)<<vx3.XErr;
4977  myprt<<std::right<<std::setw(5)<<vx3.YErr;
4978  myprt<<std::right<<std::setw(5)<<vx3.ZErr;
4979  for(auto vx2id : vx3.Vx2ID) {
4980  if(vx2id > 0) {
4981  str = "2V" + std::to_string(slc.vtxs[vx2id - 1].UID);
4982  myprt<<std::right<<std::setw(5)<<str;
4983  } else {
4984  myprt<<" --";
4985  }
4986  } // vx2id
4987  myprt<<std::right<<std::setw(5)<<vx3.Wire;
4988  unsigned short nTruMatch = 0;
4989  for(unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
4990  if(vx3.Vx2ID[ipl] == 0) continue;
4991  unsigned short iv2 = vx3.Vx2ID[ipl] - 1;
4992  if(slc.vtxs[iv2].Stat[kVtxTruMatch]) ++nTruMatch;
4993  } // ipl
4994  myprt<<std::right<<std::setw(6)<<std::setprecision(1)<<vx3.Score;
4995  myprt<<std::setw(6)<<vx3.Primary;
4996  myprt<<std::setw(4)<<vx3.Neutrino;
4997  myprt<<std::right<<std::setw(5)<<nTruMatch;
4998  Point2_t pos;
4999  for(unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
5000  PosInPlane(slc, vx3, plane, pos);
5001  myprt<<" "<<PrintPos(slc, pos);
5002  } // plane
5003  if(vx3.Wire == -2) {
5004  // find the Tjs that are attached to it
5005  for(unsigned short end = 0; end < 2; ++end) {
5006  for(auto& pfp : slc.pfps) {
5007  if(pfp.Vx3ID[end] == vx3.ID) {
5008  for(auto tjID : pfp.TjIDs) {
5009  auto& tj = slc.tjs[tjID - 1];
5010  myprt<<" T"<<tj.UID;
5011  } // tjID
5012  } // pfp.Vx3ID[0] == vx3.ID
5013  } // pfp
5014  } // end
5015  } else {
5016  auto vxtjs = GetAssns(slc, "3V", vx3.ID, "T");
5017  for(auto tjid : vxtjs) {
5018  auto& tj = slc.tjs[tjid - 1];
5019  myprt<<" T"<<tj.UID;
5020  }
5021  } // vx3.Wire != -2
5022  myprt<<"\n";
5023  } // Print3V
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:112
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4279
std::string PrintPos(TCSlice &slc, const Point2_t &pos)
Definition: Utils.cxx:5718
tagged as a vertex between Tjs that are matched to MC truth neutrino interaction particles ...
Definition: DataStructs.h:77
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
std::vector< TCSlice > slices
Definition: DataStructs.cxx:10
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Definition: BitMask.h:187
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:4496
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void PosInPlane(const TCSlice &slc, const Vtx3Store &vx3, unsigned short plane, Point2_t &pos)
Definition: TCVertex.cxx:3287
void tca::PrintAll ( std::string  someText,
const std::vector< simb::MCParticle * > &  mcpList 
)

Definition at line 4774 of file Utils.cxx.

References debug, sim::ParticleList::EveId(), cheat::ParticleInventoryService::ParticleList(), Print2V(), Print3S(), Print3V(), PrintP(), PrintT(), tca::DebugStuff::Slice, and slices.

Referenced by DotProd(), export_G4VSensitiveDetector(), and cluster::TrajCluster::produce().

4775  {
4776  // print everything in all slices
4777  bool prt3V = false;
4778  bool prt2V = false;
4779  bool prtT = false;
4780  bool prtP = false;
4781  bool prtS3 = false;
4782  //bool prtS2 = false;
4783  for(size_t isl = 0; isl < slices.size(); ++isl) {
4784  if(debug.Slice >= 0 && int(isl) != debug.Slice) continue;
4785  auto& slc = slices[isl];
4786  if(!slc.vtx3s.empty()) prt3V = true;
4787  if(!slc.vtxs.empty()) prt2V = true;
4788  if(!slc.tjs.empty()) prtT = true;
4789  if(!slc.pfps.empty()) prtP = true;
4790  if(!slc.showers.empty()) prtS3 = true;
4791  //if(!slc.cots.empty()) prtS2 = true;
4792  } // slc
4793  mf::LogVerbatim myprt("TC");
4794  myprt<<"Debug report from caller "<<someText<<"\n";
4795  if(!mcpList.empty()) {
4797  myprt<<"************ "<<mcpList.size()<<" MCParticles (> 10 MeV) ************\n";
4798  myprt<<" mcpindx PDG KE eveIndx Process\n";
4799  for(unsigned int imcp = 0; imcp < mcpList.size(); ++imcp) {
4800  auto& mcp = mcpList[imcp];
4801  int pdg = abs(mcp->PdgCode());
4802  if(pdg > 3000) continue;
4803  float TMeV = 1000 * (mcp->E() - mcp->Mass());
4804  if(TMeV < 10) continue;
4805  myprt<<std::setw(8)<<imcp;
4806  myprt<<std::setw(5)<<pdg;
4807  myprt<<std::setw(6)<<(int)TMeV;
4808  int eveID = pi_serv->ParticleList().EveId(mcp->TrackId());
4809  int eveIndx = -1;
4810  for(unsigned int jmcp = 0; jmcp < mcpList.size(); ++jmcp) {
4811  if(mcpList[jmcp]->TrackId() == eveID) {
4812  eveIndx = jmcp;
4813  break;
4814  }
4815  } // jmcp
4816  myprt<<std::setw(8)<<eveIndx;
4817  myprt<<" "<<mcp->Process();
4818  myprt<<"\n";
4819  } // imcp
4820  } // mcpList not empty
4821  myprt<<" 'prodID' = <sliceID>:<subSliceIndex>:<productID>/<productUID>\n";
4822  if(prtS3) {
4823  myprt<<"************ Showers ************\n";
4824  myprt<<" prodID Vtx parUID ___ChgPos____ ______Dir_____ ____posInPln____ ___projInPln____ 2D shower UIDs\n";
4825  for(size_t isl = 0; isl < slices.size(); ++isl) {
4826  if(debug.Slice >= 0 && int(isl) != debug.Slice) continue;
4827  auto& slc = slices[isl];
4828  if(slc.showers.empty()) continue;
4829  for(auto& ss3 : slc.showers) Print3S(someText, myprt, ss3);
4830  } // slc
4831  } // prtS3
4832  if(prtP) {
4833  bool printHeader = true;
4834  for(size_t isl = 0; isl < slices.size(); ++isl) {
4835  if(debug.Slice >= 0 && int(isl) != debug.Slice) continue;
4836  auto& slc = slices[isl];
4837  if(slc.pfps.empty()) continue;
4838  for(auto& pfp : slc.pfps) PrintP(someText, myprt, pfp, printHeader);
4839  } // slc
4840  } // prtS3
4841  if(prt3V) {
4842  // print out 3D vertices
4843  myprt<<"****** 3D vertices ******************************************__2DVtx_UID__*******\n";
4844  myprt<<" prodID Cstat TPC X Y Z XEr YEr ZEr pln0 pln1 pln2 Wire score Prim? Nu? nTru";
4845  myprt<<" ___________2D_Pos____________ _____Tj UIDs________\n";
4846  for(size_t isl = 0; isl < slices.size(); ++isl) {
4847  if(debug.Slice >= 0 && int(isl) != debug.Slice) continue;
4848  auto& slc = slices[isl];
4849  if(slc.vtx3s.empty()) continue;
4850  for(auto& vx3 : slc.vtx3s) Print3V(someText, myprt, vx3);
4851  } // slc
4852  } // prt3V
4853  if(prt2V) {
4854  // print out 2D vertices
4855  myprt<<"************ 2D vertices ************\n";
4856  myprt<<" prodID CTP wire err tick err ChiDOF NTj Pass Topo ChgFrac Score v3D Tj UIDs\n";
4857  for(size_t isl = 0; isl < slices.size(); ++isl) {
4858  if(debug.Slice >= 0 && int(isl) != debug.Slice) continue;
4859  auto& slc = slices[isl];
4860  if(slc.vtxs.empty()) continue;
4861  for(auto& vx2 : slc.vtxs) Print2V(someText, myprt, vx2);
4862  } // slc
4863  } // prt2V
4864  if(prtT) {
4865  bool printHeader = true;
4866  for(size_t isl = 0; isl < slices.size(); ++isl) {
4867  if(debug.Slice >= 0 && int(isl) != debug.Slice) continue;
4868  auto& slc = slices[isl];
4869  if(slc.tjs.empty()) continue;
4870  for(auto& tj : slc.tjs) PrintT(someText, myprt, tj, printHeader);
4871  } // slc
4872  } // prtT
4873  } // PrintAll
void PrintT(std::string someText, mf::LogVerbatim &myprt, Trajectory &tj, bool &printHeader)
Definition: Utils.cxx:5109
void PrintP(std::string someText, mf::LogVerbatim &myprt, PFPStruct &pfp, bool &printHeader)
Definition: Utils.cxx:4876
void Print3V(std::string someText, mf::LogVerbatim &myprt, Vtx3Store &vx3)
Definition: Utils.cxx:4959
int EveId(const int trackID) const
void Print2V(std::string someText, mf::LogVerbatim &myprt, VtxStore &vx2)
Definition: Utils.cxx:5026
DebugStuff debug
Definition: DebugStruct.cxx:4
std::vector< TCSlice > slices
Definition: DataStructs.cxx:10
void Print3S(std::string someText, mf::LogVerbatim &myprt, ShowerStruct3D &ss3)
Definition: Utils.cxx:5069
void tca::PrintAllTraj ( std::string  someText,
TCSlice slc,
unsigned short  itj,
unsigned short  ipt,
bool  prtVtx 
)

Definition at line 5197 of file Utils.cxx.

References AlgBitNames, geo::CryostatID::Cryostat, debug, DecodeCTP(), evd::details::end(), GetAssns(), tca::Vtx3Store::ID, kAtKink, kAtTj, kAtVtx, kBragg, kEnvNearTj, kKilled, kVtxTruMatch, tca::Vtx3Store::Neutrino, NeutrinoPrimaryTjID(), tca::TCSlice::nPlanes, tca::TCSlice::pfps, tca::DebugStuff::Plane, geo::PlaneID::Plane, PosInPlane(), tca::Vtx3Store::Primary, PrimaryID(), PrintHeader(), PrintPos(), PrintTrajPoint(), art::right(), tca::Vtx3Store::Score, tcc, tca::TCSlice::tjs, tmp, util::flags::to_string(), geo::TPCID::TPC, tca::Vtx3Store::TPCID, tca::TCConfig::unitsPerTick, tca::TCSlice::vtx3s, VtxBitNames, tca::TCSlice::vtxs, 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(), and FindShowers3D().

5198  {
5199 
5200  mf::LogVerbatim myprt("TC");
5201 
5202  if(prtVtx) {
5203  if(!slc.vtx3s.empty()) {
5204  // print out 3D vertices
5205  myprt<<someText<<"****** 3D vertices ******************************************__2DVtx_ID__*******\n";
5206  myprt<<someText<<" Vtx Cstat TPC X Y Z XEr YEr ZEr pln0 pln1 pln2 Wire score Prim? Nu? nTru";
5207  myprt<<" ___________2D_Pos____________ _____Tjs________\n";
5208  for(unsigned short iv = 0; iv < slc.vtx3s.size(); ++iv) {
5209  if(slc.vtx3s[iv].ID == 0) continue;
5210  const Vtx3Store& vx3 = slc.vtx3s[iv];
5211  myprt<<someText;
5212  std::string vid = "3v" + std::to_string(vx3.ID);
5213  myprt<<std::right<<std::setw(5)<<std::fixed<<vid;
5214  myprt<<std::setprecision(1);
5215  myprt<<std::right<<std::setw(7)<<vx3.TPCID.Cryostat;
5216  myprt<<std::right<<std::setw(5)<<vx3.TPCID.TPC;
5217  myprt<<std::right<<std::setw(8)<<vx3.X;
5218  myprt<<std::right<<std::setw(8)<<vx3.Y;
5219  myprt<<std::right<<std::setw(8)<<vx3.Z;
5220  myprt<<std::right<<std::setw(5)<<vx3.XErr;
5221  myprt<<std::right<<std::setw(5)<<vx3.YErr;
5222  myprt<<std::right<<std::setw(5)<<vx3.ZErr;
5223  myprt<<std::right<<std::setw(5)<<vx3.Vx2ID[0];
5224  myprt<<std::right<<std::setw(5)<<vx3.Vx2ID[1];
5225  myprt<<std::right<<std::setw(5)<<vx3.Vx2ID[2];
5226  myprt<<std::right<<std::setw(5)<<vx3.Wire;
5227  unsigned short nTruMatch = 0;
5228  for(unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
5229  if(vx3.Vx2ID[ipl] == 0) continue;
5230  unsigned short iv2 = vx3.Vx2ID[ipl] - 1;
5231  if(slc.vtxs[iv2].Stat[kVtxTruMatch]) ++nTruMatch;
5232  } // ipl
5233  myprt<<std::right<<std::setw(6)<<std::setprecision(1)<<vx3.Score;
5234  myprt<<std::setw(6)<<vx3.Primary;
5235  myprt<<std::setw(4)<<vx3.Neutrino;
5236  myprt<<std::right<<std::setw(5)<<nTruMatch;
5237  Point2_t pos;
5238  for(unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
5239  PosInPlane(slc, vx3, plane, pos);
5240  myprt<<" "<<PrintPos(slc, pos);
5241  } // plane
5242  if(vx3.Wire == -2) {
5243  // find the Tjs that are attached to it
5244  for(auto& pfp : slc.pfps) {
5245  if(pfp.Vx3ID[0] == slc.vtx3s[iv].ID) {
5246  for(auto& tjID : pfp.TjIDs) myprt<<" t"<<tjID;
5247  }
5248  if(pfp.Vx3ID[1] == slc.vtx3s[iv].ID) {
5249  for(auto& tjID : pfp.TjIDs) myprt<<" t"<<tjID;
5250  }
5251  } // ipfp
5252  } else {
5253  auto vxtjs = GetAssns(slc, "3V", vx3.ID, "T");
5254  for(auto tjid : vxtjs) myprt<<" t"<<tjid;
5255  }
5256  myprt<<"\n";
5257  }
5258  } // slc.vtx3s.size
5259  if(!slc.vtxs.empty()) {
5260  bool foundOne = false;
5261  for(unsigned short iv = 0; iv < slc.vtxs.size(); ++iv) {
5262  auto& vx2 = slc.vtxs[iv];
5263  if(debug.Plane < 3 && debug.Plane != (int)DecodeCTP(vx2.CTP).Plane) continue;
5264  if(vx2.NTraj == 0) continue;
5265  foundOne = true;
5266  } // iv
5267  if(foundOne) {
5268  // print out 2D vertices
5269  myprt<<someText<<"************ 2D vertices ************\n";
5270  myprt<<someText<<" ID CTP wire err tick err ChiDOF NTj Pass Topo ChgFrac Score v3D TjIDs\n";
5271  for(auto& vx2 : slc.vtxs) {
5272  if(vx2.ID == 0) continue;
5273  if(debug.Plane < 3 && debug.Plane != (int)DecodeCTP(vx2.CTP).Plane) continue;
5274  myprt<<someText;
5275  std::string vid = "2v" + std::to_string(vx2.ID);
5276  myprt<<std::right<<std::setw(5)<<std::fixed<<vid;
5277  myprt<<std::right<<std::setw(6)<<vx2.CTP;
5278  myprt<<std::right<<std::setw(8)<<std::setprecision(0)<<std::nearbyint(vx2.Pos[0]);
5279  myprt<<std::right<<std::setw(5)<<std::setprecision(1)<<vx2.PosErr[0];
5280  myprt<<std::right<<std::setw(8)<<std::setprecision(0)<<std::nearbyint(vx2.Pos[1]/tcc.unitsPerTick);
5281  myprt<<std::right<<std::setw(5)<<std::setprecision(1)<<vx2.PosErr[1]/tcc.unitsPerTick;
5282  myprt<<std::right<<std::setw(7)<<vx2.ChiDOF;
5283  myprt<<std::right<<std::setw(5)<<vx2.NTraj;
5284  myprt<<std::right<<std::setw(5)<<vx2.Pass;
5285  myprt<<std::right<<std::setw(6)<<vx2.Topo;
5286  myprt<<std::right<<std::setw(9)<<std::setprecision(2)<<vx2.TjChgFrac;
5287  myprt<<std::right<<std::setw(6)<<std::setprecision(1)<<vx2.Score;
5288  myprt<<std::right<<std::setw(5)<<vx2.Vx3ID;
5289  myprt<<" ";
5290  // display the traj IDs
5291  for(unsigned short ii = 0; ii < slc.tjs.size(); ++ii) {
5292  auto const& aTj = slc.tjs[ii];
5293  if(debug.Plane < 3 && debug.Plane != (int)DecodeCTP(aTj.CTP).Plane) continue;
5294  if(aTj.AlgMod[kKilled]) continue;
5295  for(unsigned short end = 0; end < 2; ++end) {
5296  if(aTj.VtxID[end] != (short)vx2.ID) continue;
5297  std::string tid = " t" + std::to_string(aTj.ID) + "_" + std::to_string(end);
5298  myprt<<std::right<<std::setw(6)<<tid;
5299  } // end
5300  } // ii
5301  // Special flags. Ignore the first flag bit (0 = kVtxTrjTried) which is done for every vertex
5302  for(unsigned short ib = 1; ib < VtxBitNames.size(); ++ib) if(vx2.Stat[ib]) myprt<<" "<<VtxBitNames[ib];
5303  myprt<<"\n";
5304  } // iv
5305  }
5306  } // slc.vtxs.size
5307  }
5308 
5309  if(slc.tjs.empty()) {
5310  mf::LogVerbatim("TC")<<someText<<" No allTraj trajectories to print";
5311  return;
5312  }
5313 
5314  // Print all trajectories in slc.tjs if itj == USHRT_MAX
5315  // Print a single traj (itj) and a single TP (ipt) or all TPs (USHRT_MAX)
5316  if(itj == USHRT_MAX) {
5317  // Print summary trajectory information
5318  std::vector<unsigned int> tmp;
5319 // 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";
5320  myprt<<someText<<" UID 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";
5321  for(unsigned short ii = 0; ii < slc.tjs.size(); ++ii) {
5322  auto& aTj = slc.tjs[ii];
5323  if(debug.Plane >=0 && debug.Plane < 3 && debug.Plane != (int)DecodeCTP(aTj.CTP).Plane) continue;
5324  myprt<<someText<<" ";
5325  std::string tid;
5326  if(aTj.AlgMod[kKilled]) { tid = "k" + std::to_string(aTj.UID); } else { tid = "t" + std::to_string(aTj.UID); }
5327  myprt<<std::fixed<<std::setw(5)<<tid;
5328  myprt<<std::setw(6)<<aTj.CTP;
5329  myprt<<std::setw(5)<<aTj.Pass;
5330 // myprt<<std::setw(5)<<aTj.Pts.size();
5331  myprt<<std::setw(5)<<aTj.EndPt[1] - aTj.EndPt[0] + 1;
5332  unsigned short endPt0 = aTj.EndPt[0];
5333  auto& tp0 = aTj.Pts[endPt0];
5334  int itick = tp0.Pos[1]/tcc.unitsPerTick;
5335  if(itick < 0) itick = 0;
5336  myprt<<std::setw(6)<<(int)(tp0.Pos[0]+0.5)<<":"<<itick; // W:T
5337  if(itick < 10) { myprt<<" "; }
5338  if(itick < 100) { myprt<<" "; }
5339  if(itick < 1000) { myprt<<" "; }
5340  myprt<<std::setw(6)<<std::setprecision(2)<<tp0.Ang;
5341  myprt<<std::setw(2)<<tp0.AngleCode;
5342  if(aTj.StopFlag[0][kBragg]) {
5343  myprt<<"B";
5344  } else if(aTj.StopFlag[0][kAtVtx]) {
5345  myprt<<"V";
5346  } else if(aTj.StopFlag[0][kAtKink]) {
5347  myprt<<"K";
5348  } else if(aTj.StopFlag[0][kAtTj]) {
5349  myprt<<"T";
5350  } else {
5351  myprt<<" ";
5352  }
5353  myprt<<std::setw(5)<<(int)tp0.AveChg;
5354  // Print the fraction of points in the first half that are in a shower
5355  float frac = 0;
5356  float cnt = 0;
5357  unsigned short midPt = 0.5 * (aTj.EndPt[0] + aTj.EndPt[1]);
5358  for(unsigned short ipt = aTj.EndPt[0]; ipt < midPt; ++ipt) {
5359  auto& tp = aTj.Pts[ipt];
5360 // if(tp.Environment[kEnvNearShower]) ++frac;
5361  if(tp.Environment[kEnvNearTj]) ++frac;
5362  ++cnt;
5363  } // ipt
5364  if(cnt > 0) frac /= cnt;
5365  myprt<<std::setw(5)<<std::setprecision(1)<<frac;
5366 /* print NearInShower fraction instead
5367  unsigned short prec = 1;
5368  if(aTj.dEdx[0] > 99) prec = 0;
5369  myprt<<std::setw(5)<<std::setprecision(prec)<<aTj.dEdx[0];
5370 */
5371  unsigned short endPt1 = aTj.EndPt[1];
5372  auto& tp1 = aTj.Pts[endPt1];
5373  itick = tp1.Pos[1]/tcc.unitsPerTick;
5374  myprt<<std::setw(6)<<(int)(tp1.Pos[0]+0.5)<<":"<<itick; // W:T
5375  if(itick < 10) { myprt<<" "; }
5376  if(itick < 100) { myprt<<" "; }
5377  if(itick < 1000) { myprt<<" "; }
5378  myprt<<std::setw(6)<<std::setprecision(2)<<tp1.Ang;
5379  myprt<<std::setw(2)<<tp1.AngleCode;
5380  if(aTj.StopFlag[1][kBragg]) {
5381  myprt<<"B";
5382  } else if(aTj.StopFlag[1][kAtVtx]) {
5383  myprt<<"V";
5384  } else {
5385  myprt<<" ";
5386  }
5387  myprt<<std::setw(5)<<(int)tp1.AveChg;
5388  // Print the fraction of points in the second half that are NearInShower
5389  frac = 0;
5390  cnt = 0;
5391  for(unsigned short ipt = midPt; ipt <= aTj.EndPt[1]; ++ipt) {
5392  auto& tp = aTj.Pts[ipt];
5393 // if(tp.Environment[kEnvNearShower]) ++frac;
5394  if(tp.Environment[kEnvNearTj]) ++frac;
5395  ++cnt;
5396  } // ipt
5397  if(cnt > 0) frac /= cnt;
5398  myprt<<std::setw(5)<<std::setprecision(1)<<frac;
5399 /*
5400  prec = 1;
5401  if(aTj.dEdx[1] > 99) prec = 0;
5402  myprt<<std::setw(5)<<std::setprecision(prec)<<aTj.dEdx[1];
5403 */
5404  myprt<<std::setw(7)<<std::setprecision(1)<<aTj.TotChg/1000;
5405  myprt<<std::setw(7)<<std::setprecision(2)<<aTj.ChgRMS;
5406  myprt<<std::setw(5)<<aTj.MCSMom;
5407  myprt<<std::setw(4)<<aTj.StepDir;
5408  myprt<<std::setw(4)<<aTj.VtxID[0];
5409  myprt<<std::setw(4)<<aTj.VtxID[1];
5410  myprt<<std::setw(5)<<aTj.PDGCode;
5411  myprt<<std::setw(7)<<std::setprecision(1)<<aTj.DirFOM;
5412  myprt<<std::setw(5)<<aTj.ParentID;
5413  myprt<<std::setw(5)<<PrimaryID(slc, aTj);
5414  myprt<<std::setw(6)<<NeutrinoPrimaryTjID(slc, aTj);
5415  int truKE = 0;
5416  int pdg = 0;
5417 /*
5418  if(aTj.mcpListIndex < evt.mcpList.size()) {
5419  auto& mcp = evt.mcpList[aTj.mcpListIndex];
5420  truKE = 1000 * (mcp->E() - mcp->Mass());
5421  pdg = mcp->PdgCode();
5422  }
5423 */
5424  myprt<<std::setw(6)<<pdg;
5425  myprt<<std::setw(6)<<std::setprecision(2)<<aTj.EffPur;
5426  myprt<<std::setw(5)<<truKE;
5427  myprt<<std::setw(7)<<aTj.WorkID;
5428  for(unsigned short ib = 0; ib < AlgBitNames.size(); ++ib) if(aTj.AlgMod[ib]) myprt<<" "<<AlgBitNames[ib];
5429  myprt<<"\n";
5430  } // ii
5431  return;
5432  } // itj > slc.tjs.size()-1
5433 
5434  if(itj > slc.tjs.size()-1) return;
5435 
5436  auto const& aTj = slc.tjs[itj];
5437 
5438  mf::LogVerbatim("TC")<<"Print slc.tjs["<<itj<<"] Vtx[0] "<<aTj.VtxID[0]<<" Vtx[1] "<<aTj.VtxID[1];
5439  myprt<<"AlgBits";
5440  for(unsigned short ib = 0; ib < AlgBitNames.size(); ++ib) if(aTj.AlgMod[ib]) myprt<<" "<<AlgBitNames[ib];
5441  myprt<<"\n";
5442 
5443  PrintHeader(someText);
5444  if(ipt == USHRT_MAX) {
5445  // print all points
5446  for(unsigned short ii = 0; ii < aTj.Pts.size(); ++ii) PrintTrajPoint(someText, slc, ii, aTj.StepDir, aTj.Pass, aTj.Pts[ii]);
5447  } else {
5448  // print just one
5449  PrintTrajPoint(someText, slc, ipt, aTj.StepDir, aTj.Pass, aTj.Pts[ipt]);
5450  }
5451  } // 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
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4279
const std::vector< std::string > AlgBitNames
Definition: DataStructs.cxx:13
TCConfig tcc
Definition: DataStructs.cxx:6
int NeutrinoPrimaryTjID(TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:441
Float_t tmp
Definition: plot.C:37
std::string PrintPos(TCSlice &slc, const Point2_t &pos)
Definition: Utils.cxx:5718
int PrimaryID(TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:463
tagged as a vertex between Tjs that are matched to MC truth neutrino interaction particles ...
Definition: DataStructs.h:77
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
DebugStuff debug
Definition: DebugStruct.cxx:4
int Plane
Select plane.
Definition: DebugStruct.h:21
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
const std::vector< std::string > VtxBitNames
Definition: DataStructs.cxx:91
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)
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void PosInPlane(const TCSlice &slc, const Vtx3Store &vx3, unsigned short plane, Point2_t &pos)
Definition: TCVertex.cxx:3287
void PrintHeader(std::string someText)
Definition: Utils.cxx:5535
void PrintTrajPoint(std::string someText, TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, TrajPoint const &tp)
Definition: Utils.cxx:5541
void tca::PrintHeader ( std::string  someText)

Definition at line 5535 of file Utils.cxx.

Referenced by DotProd(), FindVtxTjs(), FitVertex(), PrintAllTraj(), lar_content::LArFormattingHelper::PrintRule(), and PrintTrajectory().

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

Definition at line 5704 of file Utils.cxx.

References tca::TCEvent::allHits, tca::TCHit::allHitsIndex, evt, tca::TCHit::InTraj, and util::flags::to_string().

Referenced by cluster::ClusterCrawlerAlg::AddHit(), AddHits(), cluster::ClusterCrawlerAlg::AddLAHit(), AddLAHits(), CheckHiMultUnusedHits(), tca::TrajClusterAlg::ChkInTraj(), ChkStopEndPts(), cluster::ClusterCrawlerAlg::ClusterLoop(), DotProd(), FillGaps(), Find3DVertices(), tca::TrajClusterAlg::FindJunkTraj(), FindUseHits(), FindVtxTjs(), HasDuplicateHits(), InTrajOK(), cluster::ClusterCrawlerAlg::MergeOverlap(), tca::TrajClusterAlg::ReconstructAllTraj(), ReversePropagate(), and StoreTraj().

5705  {
5706  if(tch.allHitsIndex > (*evt.allHits).size() - 1) return "NA";
5707  auto& hit = (*evt.allHits)[tch.allHitsIndex];
5708  return std::to_string(hit.WireID().Plane) + ":" + std::to_string(hit.WireID().Wire) + ":" + std::to_string((int)hit.PeakTime()) + "_" + std::to_string(tch.InTraj);
5709  } // 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
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
std::string tca::PrintHitShort ( const TCHit tch)

Definition at line 5696 of file Utils.cxx.

References tca::TCEvent::allHits, tca::TCHit::allHitsIndex, evt, and util::flags::to_string().

Referenced by DotProd().

5697  {
5698  if(tch.allHitsIndex > (*evt.allHits).size() - 1) return "NA";
5699  auto& hit = (*evt.allHits)[tch.allHitsIndex];
5700  return std::to_string(hit.WireID().Plane) + ":" + std::to_string(hit.WireID().Wire) + ":" + std::to_string((int)hit.PeakTime());
5701  } // 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
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
void tca::PrintP ( std::string  someText,
mf::LogVerbatim myprt,
PFPStruct pfp,
bool &  printHeader 
)

Definition at line 4876 of file Utils.cxx.

References tca::PFPStruct::dEdx, tca::PFPStruct::Dir, tca::PFPStruct::DtrUIDs, tca::PFPStruct::EffPur, GetSliceIndex(), tca::PFPStruct::ID, InsideFV(), IsShowerLike(), SortEntry::length, tca::PFPStruct::mcpListIndex, MCSMom(), tca::PFPStruct::ParentUID, tca::PFPStruct::PDGCode, PosSep(), art::right(), slices, tca::PFPStruct::TjIDs, tca::PFPStruct::TjUIDs, util::flags::to_string(), tca::PFPStruct::Tp3s, tca::PFPStruct::UID, tca::PFPStruct::Vx3ID, and tca::PFPStruct::XYZ.

Referenced by DotProd(), PrintAll(), and StitchPFPs().

4877  {
4878  if(pfp.ID <= 0) return;
4879  if(printHeader) {
4880  myprt<<"************ PFParticles ************\n";
4881  myprt<<" prodID sVx _____sPos____ CS _______sDir______ ____sdEdx_____ eVx _____ePos____ CS _______eDir______ ____edEdx_____ MCS Len nTp3 SLk? PDG mcpIndx Par E*P\n";
4882  printHeader = false;
4883  } // printHeader
4884  auto sIndx = GetSliceIndex("P", pfp.UID);
4885  if(sIndx.first == USHRT_MAX) return;
4886  auto& slc = slices[sIndx.first];
4887 // myprt<<someText;
4888  std::string str = std::to_string(slc.ID) + ":" + std::to_string(sIndx.first) + ":" + std::to_string(pfp.ID);
4889  str += "/" + std::to_string(pfp.UID);
4890  myprt<<std::setw(12)<<str;
4891  // start and end stuff
4892  for(unsigned short startend = 0; startend < 2; ++startend) {
4893  str = "--";
4894  if(pfp.Vx3ID[startend] > 0) str = "3V" + std::to_string(slc.vtx3s[pfp.Vx3ID[startend]-1].UID);
4895  myprt<<std::setw(6)<<str;
4896  myprt<<std::fixed<<std::right<<std::setprecision(0);
4897  myprt<<std::setw(5)<<pfp.XYZ[startend][0];
4898  myprt<<std::setw(5)<<pfp.XYZ[startend][1];
4899  myprt<<std::setw(5)<<pfp.XYZ[startend][2];
4900  // print character for Outside or Inside the FV
4901  if(InsideFV(slc, pfp, startend)) {
4902  myprt<<" I";
4903  } else {
4904  myprt<<" O";
4905  }
4906  myprt<<std::fixed<<std::right<<std::setprecision(2);
4907  myprt<<std::setw(6)<<pfp.Dir[startend][0];
4908  myprt<<std::setw(6)<<pfp.Dir[startend][1];
4909  myprt<<std::setw(6)<<pfp.Dir[startend][2];
4910  for(auto& dedx : pfp.dEdx[startend]) {
4911  if(dedx < 50) {
4912  myprt<<std::setw(5)<<std::setprecision(1)<<dedx;
4913  } else {
4914  myprt<<std::setw(5)<<std::setprecision(0)<<dedx;
4915  }
4916  } // dedx
4917  if (pfp.dEdx[startend].size()<3){
4918  for(size_t i = 0; i<3-pfp.dEdx[startend].size(); ++i){
4919  myprt<<std::setw(6)<<' ';
4920  }
4921  }
4922  } // startend
4923  // global stuff
4924  myprt<<std::setw(7)<<MCSMom(slc, pfp.TjIDs);
4925  float length = PosSep(pfp.XYZ[0], pfp.XYZ[1]);
4926  if(length < 100) {
4927  myprt<<std::setw(5)<<std::setprecision(1)<<length;
4928  } else {
4929  myprt<<std::setw(5)<<std::setprecision(0)<<length;
4930  }
4931  myprt<<std::setw(5)<<std::setprecision(2)<<pfp.Tp3s.size();
4932  myprt<<std::setw(3)<<IsShowerLike(slc, pfp.TjIDs);
4933  myprt<<std::setw(5)<<pfp.PDGCode;
4934  if(pfp.mcpListIndex == UINT_MAX) {
4935  myprt<<" --";
4936  } else {
4937  myprt<<std::setw(8)<<pfp.mcpListIndex;
4938  }
4939  myprt<<std::setw(4)<<pfp.ParentUID;
4940 // myprt<<std::setw(5)<<PrimaryUID(slc, pfp);
4941  myprt<<std::setw(5)<<std::setprecision(2)<<pfp.EffPur;
4942  if(!pfp.TjIDs.empty()) {
4943  if(pfp.TjUIDs.empty()) {
4944  // print Tjs in one TPC
4945  for(auto tjid : pfp.TjIDs) myprt<<" T"<<slc.tjs[tjid - 1].UID;
4946  } else {
4947  // print Tjs in all TPCs (if this is called after FinishEvent)
4948  for(auto tjuid : pfp.TjUIDs) myprt<<" T"<<tjuid;
4949  }
4950  } // TjIDs exist
4951  if(!pfp.DtrUIDs.empty()) {
4952  myprt<<" dtrs";
4953  for(auto dtruid : pfp.DtrUIDs) myprt<<" P"<<dtruid;
4954  } // dtr ids exist
4955  myprt<<"\n";
4956  } // PrintP
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:112
float PosSep(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2353
bool IsShowerLike(TCSlice &slc, const std::vector< int > TjIDs)
Definition: TCShower.cxx:2002
std::vector< TCSlice > slices
Definition: DataStructs.cxx:10
bool InsideFV(TCSlice &slc, PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:2810
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Definition: BitMask.h:187
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:4496
short MCSMom(TCSlice &slc, Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:2936
void tca::PrintPFP ( std::string  someText,
TCSlice slc,
const PFPStruct pfp,
bool  printHeader 
)

Definition at line 5587 of file Utils.cxx.

References tca::PFPStruct::dEdx, tca::PFPStruct::Dir, tca::PFPStruct::DtrUIDs, tca::PFPStruct::EffPur, tca::PFPStruct::ID, InsideTPC(), IsShowerLike(), SortEntry::length, MCSMom(), tca::PFPStruct::ParentUID, tca::PFPStruct::PDGCode, PosSep(), PrimaryUID(), art::right(), tca::PFPStruct::TjIDs, util::flags::to_string(), tca::PFPStruct::Tp3s, tca::PFPStruct::Vx3ID, and tca::PFPStruct::XYZ.

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

5588  {
5589  mf::LogVerbatim myprt("TC");
5590  if(printHeader) {
5591  myprt<<someText;
5592  myprt<<" PFP sVx ________sPos_______ CS _______sDir______ ____sdEdx_____ eVx ________ePos_______ CS _______eDir______ ____edEdx____ Len nTp3 MCSMom ShLike? PDG mcpIndx Par Prim E*P\n";
5593  }
5594  myprt<<someText;
5595  std::string pid = "P" + std::to_string(pfp.ID);
5596  myprt<<std::setw(5)<<pid;
5597  // start and end stuff
5598  for(unsigned short startend = 0; startend < 2; ++startend) {
5599  myprt<<std::setw(4)<<pfp.Vx3ID[startend];
5600  myprt<<std::fixed<<std::right<<std::setprecision(1);
5601  myprt<<std::setw(7)<<pfp.XYZ[startend][0];
5602  myprt<<std::setw(7)<<pfp.XYZ[startend][1];
5603  myprt<<std::setw(7)<<pfp.XYZ[startend][2];
5604  // print character for Outside or Inside the FV
5605  geo::TPCID tpcid;
5606  if(InsideTPC(pfp.XYZ[startend], tpcid)) {
5607  myprt<<" I";
5608  } else {
5609  myprt<<" O";
5610  }
5611  myprt<<std::fixed<<std::right<<std::setprecision(2);
5612  myprt<<std::setw(6)<<pfp.Dir[startend][0];
5613  myprt<<std::setw(6)<<pfp.Dir[startend][1];
5614  myprt<<std::setw(6)<<pfp.Dir[startend][2];
5615  for(auto& dedx : pfp.dEdx[startend]) {
5616  if(dedx < 50) {
5617  myprt<<std::setw(5)<<std::setprecision(1)<<dedx;
5618  } else {
5619  myprt<<std::setw(5)<<std::setprecision(0)<<dedx;
5620  }
5621  } // dedx
5622  if (pfp.dEdx[startend].size()<3){
5623  for(size_t i = 0; i<3-pfp.dEdx[startend].size(); ++i){
5624  myprt<<std::setw(6)<<' ';
5625  }
5626  }
5627  } // startend
5628  // global stuff
5629 // myprt<<std::setw(5)<<pfp.BestPlane;
5630  float length = PosSep(pfp.XYZ[0], pfp.XYZ[1]);
5631  if(length < 100) {
5632  myprt<<std::setw(5)<<std::setprecision(1)<<length;
5633  } else {
5634  myprt<<std::setw(5)<<std::setprecision(0)<<length;
5635  }
5636  myprt<<std::setw(5)<<std::setprecision(2)<<pfp.Tp3s.size();
5637  myprt<<std::setw(7)<<MCSMom(slc, pfp.TjIDs);
5638  myprt<<std::setw(5)<<IsShowerLike(slc, pfp.TjIDs);
5639  myprt<<std::setw(5)<<pfp.PDGCode;
5640 /*
5641  if(pfp.mcpListIndex < evt.mcpList.size()) {
5642  myprt<<std::setw(8)<<pfp.mcpListIndex;
5643  } else {
5644  myprt<<" NA";
5645  }
5646 */
5647  myprt<<" NA";
5648  myprt<<std::setw(4)<<pfp.ParentUID;
5649  myprt<<std::setw(5)<<PrimaryUID(slc, pfp);
5650  myprt<<std::setw(5)<<std::setprecision(2)<<pfp.EffPur;
5651  if(!pfp.TjIDs.empty()) {
5652  for(auto& tjID : pfp.TjIDs) myprt<<" T"<<tjID;
5653  }
5654  if(!pfp.DtrUIDs.empty()) {
5655  myprt<<" dtrs";
5656  for(auto& dtrUID : pfp.DtrUIDs) myprt<<" P"<<dtrUID;
5657  }
5658  } // 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
bool InsideTPC(const Point3_t &pos, geo::TPCID &inTPCID)
Definition: PFPUtils.cxx:2825
float PosSep(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2353
bool IsShowerLike(TCSlice &slc, const std::vector< int > TjIDs)
Definition: TCShower.cxx:2002
The data type to uniquely identify a TPC.
Definition: geo_types.h:195
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Definition: BitMask.h:187
short MCSMom(TCSlice &slc, Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:2936
int PrimaryUID(TCSlice &slc, const PFPStruct &pfp)
Definition: Utils.cxx:482
void tca::PrintPFPs ( std::string  someText,
TCSlice slc 
)

Definition at line 5661 of file Utils.cxx.

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

Referenced by DotProd(), and FindShowers3D().

5662  {
5663  if(slc.pfps.empty()) return;
5664 
5665  mf::LogVerbatim myprt("TC");
5666  myprt<<someText;
5667  myprt<<" PFP sVx ________sPos_______ ______sDir______ ______sdEdx_____ eVx ________ePos_______ ______eDir______ ______edEdx_____ BstPln PDG TruPDG Par Prim E*P\n";
5668  bool printHeader = true;
5669  for(auto& pfp : slc.pfps) {
5670  PrintPFP(someText, slc, pfp, printHeader);
5671  printHeader = false;
5672  } // im
5673 
5674  } // PrintPFPs
void PrintPFP(std::string someText, TCSlice &slc, const PFPStruct &pfp, bool printHeader)
Definition: Utils.cxx:5587
std::string tca::PrintPos ( TCSlice slc,
const TrajPoint tp 
)
std::string tca::PrintPos ( TCSlice slc,
const Point2_t pos 
)

Definition at line 5718 of file Utils.cxx.

References tcc, util::flags::to_string(), and tca::TCConfig::unitsPerTick.

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

5719  {
5720  unsigned int wire = 0;
5721  if(pos[0] > -0.4) wire = std::nearbyint(pos[0]);
5722  int time = std::nearbyint(pos[1]/tcc.unitsPerTick);
5723  return std::to_string(wire) + ":" + std::to_string(time);
5724  } // PrintPos
TCConfig tcc
Definition: DataStructs.cxx:6
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
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,
TCSlice slc,
const ShowerStruct ss,
bool  printHeader,
bool  printExtras 
)

Definition at line 4733 of file TCShower.cxx.

References 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::TCSlice::pfps, PrintPos(), tca::TCSlice::showers, tca::ShowerStruct::ShowerTjID, tca::ShowerStruct::SS3ID, tcc, tca::ShowerStruct::TjIDs, tca::TCSlice::tjs, util::flags::to_string(), tca::ShowerStruct::TruParentID, and tca::TCConfig::unitsPerTick.

Referenced by Print2DShowers().

4734  {
4735  // print a single shower and a header (optional) and the extra variables like TjIDs, envelope, etc
4736  mf::LogVerbatim myprt("TC");
4737 
4738  if(printHeader) {
4739  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";
4740  } // printHeader
4741 
4742  myprt<<someText<<std::fixed;
4743  std::string sid = "2S" + std::to_string(ss.ID);
4744  myprt<<std::setw(5)<<sid;
4745  myprt<<std::setw(6)<<ss.CTP;
4746  sid = "NA";
4747  if(ss.ParentID > 0) sid = "T" + std::to_string(ss.ParentID);
4748  myprt<<std::setw(7)<<sid;
4749  myprt<<std::setw(7)<<std::setprecision(2)<<ss.ParentFOM;
4750  myprt<<std::setw(9)<<ss.TruParentID;
4751  myprt<<std::setw(7)<<(int)ss.Energy;
4752  myprt<<std::setw(5)<<ss.TjIDs.size();
4753  myprt<<std::setw(6)<<std::setprecision(2)<<ss.DirectionFOM;
4754  myprt<<std::setw(7)<<std::setprecision(2)<<ss.AspectRatio;
4755  const auto& stj = slc.tjs[ss.ShowerTjID - 1];
4756  std::string tid = "T" + std::to_string(stj.ID);
4757  myprt<<std::setw(5)<<tid;
4758  std::string vid = "NA";
4759  if(stj.VtxID[0] > 0) vid = "2V" + std::to_string(stj.VtxID[0]);
4760  myprt<<std::setw(5)<<vid;
4761  for(auto& spt : stj.Pts) {
4762  myprt<<std::setw(10)<<PrintPos(slc, spt.Pos);
4763  myprt<<std::setw(7)<<std::fixed<<std::setprecision(1)<<spt.Chg/1000;
4764  // myprt<<std::setw(5)<<spt.NTPsFit;
4765  myprt<<std::setw(5)<<std::setprecision(1)<<spt.DeltaRMS;
4766  } // spt
4767  myprt<<std::setw(6)<<std::setprecision(2)<<stj.Pts[1].Ang;
4768  std::string sss = "NA";
4769  if(ss.SS3ID > 0) sss = "3S" + std::to_string(ss.SS3ID);
4770  myprt<<std::setw(6)<<sss;
4771  if(ss.SS3ID > 0 && ss.SS3ID < (int)slc.showers.size()) {
4772  auto& ss3 = slc.showers[ss.SS3ID - 1];
4773  if(ss3.PFPIndex >= 0 && ss3.PFPIndex < slc.pfps.size()) {
4774  std::string pid = "P" + std::to_string(ss3.PFPIndex + 1);
4775  myprt<<std::setw(6)<<pid;
4776  } else {
4777  myprt<<std::setw(6)<<"NA";
4778  }
4779  } else {
4780  myprt<<std::setw(6)<<"NA";
4781  }
4782  if(ss.NeedsUpdate) myprt<<" *** Needs update";
4783 
4784  if(!printExtras) return;
4785  myprt<<"\n";
4786 
4787  myprt<<someText<<std::fixed;
4788  sid = "2S" + std::to_string(ss.ID);
4789  myprt<<std::setw(5)<<sid;
4790  myprt<<" Tjs";
4791  for(auto id : ss.TjIDs) myprt<<" T"<<id;
4792  myprt<<"\n";
4793  myprt<<someText<<std::fixed;
4794  sid = "2S" + std::to_string(ss.ID);
4795  myprt<<std::setw(5)<<sid;
4796  myprt<<" Envelope";
4797  for(auto& vtx : ss.Envelope) myprt<<" "<<(int)vtx[0]<<":"<<(int)(vtx[1]/tcc.unitsPerTick);
4798  myprt<<"\n";
4799  myprt<<someText<<std::fixed;
4800  sid = "2S" + std::to_string(ss.ID);
4801  myprt<<std::setw(5)<<sid;
4802  myprt<<" Nearby";
4803  for(auto id : ss.NearTjIDs) myprt<<" T"<<id;
4804 
4805  } // PrintShower
TCConfig tcc
Definition: DataStructs.cxx:6
Float_t ss
Definition: plot.C:23
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Definition: BitMask.h:187
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
void tca::PrintShowers ( std::string  fcnLabel,
TCSlice slc 
)

Definition at line 4611 of file TCShower.cxx.

References tca::TCSlice::cots, EncodeCTP(), MakeBareTP(), tca::TCSlice::nPlanes, PrintPos(), tca::TCSlice::showers, ss, and tca::TCSlice::tjs.

Referenced by Match2DShowers().

4612  {
4613  if(slc.showers.empty()) return;
4614  mf::LogVerbatim myprt("TC");
4615  myprt<<fcnLabel<<" 3D showers \n";
4616  for(auto& ss3 : slc.showers) {
4617  myprt<<fcnLabel<<" 3S"<<ss3.ID<<" 3V"<<ss3.Vx3ID;
4618  myprt<<" parentID "<<ss3.ParentID;
4619  myprt<<" ChgPos"<<std::fixed;
4620  for(unsigned short xyz = 0; xyz < 3; ++xyz) myprt<<" "<<std::setprecision(0)<<ss3.ChgPos[xyz];
4621  myprt<<" Dir";
4622  for(unsigned short xyz = 0; xyz < 3; ++xyz) myprt<<" "<<std::setprecision(2)<<ss3.Dir[xyz];
4623  myprt<<" posInPlane";
4624  std::vector<float> projInPlane(slc.nPlanes);
4625  for(unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
4626  CTP_t inCTP = EncodeCTP(ss3.TPCID.Cryostat, ss3.TPCID.TPC, plane);
4627  auto tp = MakeBareTP(slc, ss3.ChgPos, ss3.Dir, inCTP);
4628  myprt<<" "<<PrintPos(slc, tp.Pos);
4629  projInPlane[plane] = tp.Delta;
4630  } // plane
4631  myprt<<" projInPlane";
4632  for(unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
4633  myprt<<" "<<std::fixed<<std::setprecision(2)<<projInPlane[plane];
4634  } // plane
4635  for(auto cid : ss3.CotIDs) {
4636  auto& ss = slc.cots[cid - 1];
4637  myprt<<"\n 2S"<<ss.ID;
4638  auto& stj = slc.tjs[ss.ShowerTjID - 1];
4639  myprt<<" ST"<<stj.ID;
4640  myprt<<" "<<PrintPos(slc, stj.Pts[stj.EndPt[0]].Pos)<<" - "<<PrintPos(slc, stj.Pts[stj.EndPt[1]].Pos);
4641  } // ci
4642  if(ss3.NeedsUpdate) myprt<<" *** Needs update";
4643  myprt<<"\n";
4644  } // sss3
4645  } // PrintShowers
Float_t ss
Definition: plot.C:23
TrajPoint MakeBareTP(TCSlice &slc, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
Definition: Utils.cxx:3523
unsigned int CTP_t
Definition: DataStructs.h:41
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
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 5677 of file Utils.cxx.

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

Referenced by DotProd(), FixTrajBegin(), and PrintTrajectory().

5678  {
5679  if(end > 1) return "Invalid end";
5680  std::string tmp;
5681  bool first = true;
5682  for(unsigned short ib = 0; ib < StopFlagNames.size(); ++ib) {
5683  if(tj.StopFlag[end][ib]) {
5684  if(first) {
5685  tmp = std::to_string(end) + ":" + StopFlagNames[ib];
5686  first = false;
5687  } else {
5688  tmp += "," + StopFlagNames[ib];
5689  }
5690  }
5691  } // ib
5692  return tmp;
5693  } // PrintStopFlag
Float_t tmp
Definition: plot.C:37
const std::vector< std::string > StopFlagNames
Definition: DataStructs.cxx:82
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::PrintT ( std::string  someText,
mf::LogVerbatim myprt,
Trajectory tj,
bool &  printHeader 
)

Definition at line 5109 of file Utils.cxx.

References AlgBitNames, tca::Trajectory::AlgMod, tca::Trajectory::ChgRMS, tca::Trajectory::CTP, tca::Trajectory::DirFOM, tca::Trajectory::EffPur, tca::Trajectory::EndPt, GetSliceIndex(), tca::Trajectory::ID, kAtKink, kAtTj, kAtVtx, kBragg, tca::Trajectory::mcpListIndex, tca::Trajectory::MCSMom, NeutrinoPrimaryTjID(), tca::Trajectory::ParentID, tca::Trajectory::Pass, tca::Trajectory::PDGCode, PrimaryID(), tca::Trajectory::Pts, slices, tca::Trajectory::StepDir, tca::Trajectory::StopFlag, tcc, util::flags::to_string(), tca::Trajectory::TotChg, tca::Trajectory::UID, tca::TCConfig::unitsPerTick, tca::Trajectory::VtxID, and tca::Trajectory::WorkID.

Referenced by DotProd(), and PrintAll().

5110  {
5111  // print a 2D vertex on one line
5112  if(tj.ID <= 0) return;
5113 // if(tj.AlgMod[kKilled]) return;
5114 
5115  if(printHeader) {
5116  myprt<<"************ Trajectories ************\n";
5117  myprt<<" prodID CTP Pass Pts W:T Ang CS AveQ W:T Ang CS AveQ Chg(k) chgRMS Mom SDr __Vtx__ PDG DirFOM Par Pri NuPar E*P mcpIndex WorkID \n";
5118  printHeader = false;
5119  }
5120  auto sIndx = GetSliceIndex("T", tj.UID);
5121  if(sIndx.first == USHRT_MAX) return;
5122  auto& slc = slices[sIndx.first];
5123 // myprt<<someText;
5124  std::string str = std::to_string(slc.ID) + ":" + std::to_string(sIndx.first) + ":" + std::to_string(tj.ID);
5125  str += "/" + std::to_string(tj.UID);
5126  myprt<<std::fixed<<std::setw(12)<<str;
5127  myprt<<std::setw(6)<<tj.CTP;
5128  myprt<<std::setw(5)<<tj.Pass;
5129  // myprt<<std::setw(5)<<tj.Pts.size();
5130  myprt<<std::setw(5)<<tj.EndPt[1] - tj.EndPt[0] + 1;
5131  unsigned short endPt0 = tj.EndPt[0];
5132  auto& tp0 = tj.Pts[endPt0];
5133  int itick = tp0.Pos[1]/tcc.unitsPerTick;
5134  if(itick < 0) itick = 0;
5135  myprt<<std::setw(6)<<(int)(tp0.Pos[0]+0.5)<<":"<<itick; // W:T
5136  if(itick < 10) { myprt<<" "; }
5137  if(itick < 100) { myprt<<" "; }
5138  if(itick < 1000) { myprt<<" "; }
5139  myprt<<std::setw(6)<<std::setprecision(2)<<tp0.Ang;
5140  myprt<<std::setw(2)<<tp0.AngleCode;
5141  if(tj.StopFlag[0][kBragg]) {
5142  myprt<<"B";
5143  } else if(tj.StopFlag[0][kAtVtx]) {
5144  myprt<<"V";
5145  } else if(tj.StopFlag[0][kAtKink]) {
5146  myprt<<"K";
5147  } else if(tj.StopFlag[0][kAtTj]) {
5148  myprt<<"T";
5149  } else {
5150  myprt<<" ";
5151  }
5152  myprt<<std::setw(5)<<(int)tp0.AveChg;
5153  unsigned short endPt1 = tj.EndPt[1];
5154  auto& tp1 = tj.Pts[endPt1];
5155  itick = tp1.Pos[1]/tcc.unitsPerTick;
5156  myprt<<std::setw(6)<<(int)(tp1.Pos[0]+0.5)<<":"<<itick; // W:T
5157  if(itick < 10) { myprt<<" "; }
5158  if(itick < 100) { myprt<<" "; }
5159  if(itick < 1000) { myprt<<" "; }
5160  myprt<<std::setw(6)<<std::setprecision(2)<<tp1.Ang;
5161  myprt<<std::setw(2)<<tp1.AngleCode;
5162  if(tj.StopFlag[1][kBragg]) {
5163  myprt<<"B";
5164  } else if(tj.StopFlag[1][kAtVtx]) {
5165  myprt<<"V";
5166  } else {
5167  myprt<<" ";
5168  }
5169  myprt<<std::setw(5)<<(int)tp1.AveChg;
5170  myprt<<std::setw(7)<<std::setprecision(1)<<tj.TotChg/1000;
5171  myprt<<std::setw(7)<<std::setprecision(2)<<tj.ChgRMS;
5172  myprt<<std::setw(5)<<tj.MCSMom;
5173  myprt<<std::setw(4)<<tj.StepDir;
5174  int vxid = 0;
5175  if(tj.VtxID[0] > 0) vxid = slc.vtxs[tj.VtxID[0]-1].UID;
5176  myprt<<std::setw(4)<<vxid;
5177  vxid = 0;
5178  if(tj.VtxID[1] > 0) vxid = slc.vtxs[tj.VtxID[1]-1].UID;
5179  myprt<<std::setw(4)<<vxid;
5180  myprt<<std::setw(5)<<tj.PDGCode;
5181  myprt<<std::setw(7)<<std::setprecision(1)<<tj.DirFOM;
5182  myprt<<std::setw(5)<<tj.ParentID;
5183  myprt<<std::setw(5)<<PrimaryID(slc, tj);
5184  myprt<<std::setw(6)<<NeutrinoPrimaryTjID(slc, tj);
5185  myprt<<std::setw(6)<<std::setprecision(2)<<tj.EffPur;
5186  if(tj.mcpListIndex == UINT_MAX) {
5187  myprt<<" --";
5188  } else {
5189  myprt<<std::setw(6)<<tj.mcpListIndex;
5190  }
5191  myprt<<std::setw(7)<<tj.WorkID;
5192  for(unsigned short ib = 0; ib < AlgBitNames.size(); ++ib) if(tj.AlgMod[ib]) myprt<<" "<<AlgBitNames[ib];
5193  myprt<<"\n";
5194  } // PrintT
const std::vector< std::string > AlgBitNames
Definition: DataStructs.cxx:13
TCConfig tcc
Definition: DataStructs.cxx:6
int NeutrinoPrimaryTjID(TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:441
int PrimaryID(TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:463
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
std::vector< TCSlice > slices
Definition: DataStructs.cxx:10
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Definition: BitMask.h:187
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:4496
void tca::PrintTp3 ( std::string  someText,
TCSlice slc,
const TrajPoint3 tp3 
)

Definition at line 3041 of file PFPUtils.cxx.

References tca::TrajPoint3::Dir, tca::TrajPoint3::Pos, PrintPos(), tca::TrajPoint3::Tj2Pts, and tca::TCSlice::tjs.

Referenced by DotProd(), and SetStart().

3042  {
3043  mf::LogVerbatim myprt("TC");
3044  myprt<<someText<<" Pos"<<std::fixed<<std::setprecision(1);
3045  myprt<<std::setw(6)<<tp3.Pos[0]<<std::setw(6)<<tp3.Pos[1]<<std::setw(6)<<tp3.Pos[2];
3046  myprt<<" Dir"<<std::fixed<<std::setprecision(3);
3047  myprt<<std::setw(7)<<tp3.Dir[0]<<std::setw(7)<<tp3.Dir[1]<<std::setw(7)<<tp3.Dir[2];
3048  myprt<<" tj_ipt";
3049  for(auto tj2pt : tp3.Tj2Pts) {
3050  auto& tj = slc.tjs[tj2pt.id - 1];
3051  auto& tp = tj.Pts[tj2pt.ipt];
3052  myprt<<" "<<tj.ID<<"_"<<PrintPos(slc, tp);
3053  } // tj2pt
3054  } // PrintTp3
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
void tca::PrintTp3s ( std::string  someText,
TCSlice slc,
const PFPStruct pfp,
short  printPts 
)

Definition at line 3057 of file PFPUtils.cxx.

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

Referenced by DotProd().

3058  {
3059  if(pfp.Tp3s.empty()) return;
3060  mf::LogVerbatim myprt("TC");
3061  if(printPts < 0) {
3062  // print the head if we are print all points
3063  myprt<<someText<<" pfp P"<<pfp.ID<<"\n";
3064  myprt<<someText<<" ipt ________Pos________ Path ________Dir_______ along trans dang Kink Tj_ipt \n";
3065  }
3066  // print the start
3067  myprt<<someText<<" ";
3068  myprt<<std::fixed<<std::setprecision(1);
3069  myprt<<std::setw(7)<<pfp.XYZ[0][0]<<std::setw(7)<<pfp.XYZ[0][1]<<std::setw(7)<<pfp.XYZ[0][2];
3070  myprt<<" ";
3071  myprt<<std::fixed<<std::setprecision(2);
3072  myprt<<std::setw(7)<<pfp.Dir[0][0]<<std::setw(7)<<pfp.Dir[0][1]<<std::setw(7)<<pfp.Dir[0][2];
3073  myprt<<" <--- pfp.XYZ[0] \n";
3074 
3075  unsigned short fromPt = 0;
3076  unsigned short toPt = pfp.Tp3s.size() - 1;
3077  if(printPts >= 0) fromPt = toPt;
3078  Vector3_t prevDir = pfp.Dir[0];
3079  for(unsigned short ipt = fromPt; ipt <= toPt; ++ipt) {
3080  auto tp3 = pfp.Tp3s[ipt];
3081  myprt<<someText<<std::setw(4)<<ipt;
3082  myprt<<std::fixed<<std::setprecision(1);
3083  myprt<<std::setw(7)<<tp3.Pos[0]<<std::setw(7)<<tp3.Pos[1]<<std::setw(7)<<tp3.Pos[2];
3084  myprt<<std::setprecision(1)<<std::setw(5)<<PosSep(tp3.Pos, pfp.XYZ[0]);
3085  myprt<<std::setprecision(2)<<std::setw(7)<<tp3.Dir[0]<<std::setw(7)<<tp3.Dir[1]<<std::setw(7)<<tp3.Dir[2];
3086  myprt<<std::setprecision(1)<<std::setw(6)<<tp3.AlongTrans[0];
3087  myprt<<std::setprecision(1)<<std::setw(6)<<tp3.AlongTrans[1];
3088  myprt<<std::setprecision(2)<<std::setw(7)<<DeltaAngle(prevDir, tp3.Dir);
3089  prevDir = tp3.Dir;
3090  // Calculate the kink angle at point ipt, using the two points that are
3091  // +/- 1 cm on either side of that point
3092  double sep = 1;
3093  myprt<<std::setprecision(2)<<std::setw(7)<<KinkAngle(slc, pfp.Tp3s, ipt, sep);
3094  for(auto tj2pt : tp3.Tj2Pts) {
3095  auto& tj = slc.tjs[tj2pt.id - 1];
3096  auto& tp = tj.Pts[tj2pt.ipt];
3097  myprt<<" "<<tj.ID<<"_"<<tj2pt.ipt<<"_"<<PrintPos(slc, tp);
3098  } // tj2pt
3099  myprt<<"\n";
3100  } // ipt
3101  // print the end
3102  myprt<<someText<<" ";
3103  myprt<<std::fixed<<std::setprecision(1);
3104  myprt<<std::setw(7)<<pfp.XYZ[1][0]<<std::setw(7)<<pfp.XYZ[1][1]<<std::setw(7)<<pfp.XYZ[1][2];
3105  myprt<<" ";
3106  myprt<<std::fixed<<std::setprecision(2);
3107  myprt<<std::setw(7)<<pfp.Dir[1][0]<<std::setw(7)<<pfp.Dir[1][1]<<std::setw(7)<<pfp.Dir[1][2];
3108  myprt<<" <--- pfp.XYZ[1]. Length "<<PosSep(pfp.XYZ[0], pfp.XYZ[1])<<"\n";
3109  } // PrintTp3s
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1636
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
double KinkAngle(TCSlice &slc, const std::vector< TrajPoint3 > &tp3s, unsigned short atPt, double sep)
Definition: PFPUtils.cxx:1943
std::array< double, 3 > Vector3_t
Definition: DataStructs.h:36
void tca::PrintTrajectory ( std::string  someText,
TCSlice slc,
const Trajectory tj,
unsigned short  tPoint 
)

Definition at line 5455 of file Utils.cxx.

References AlgBitNames, tca::Trajectory::AlgMod, tca::ShowerStruct::Angle, tca::ShowerStruct::AngleErr, tca::ShowerStruct::AspectRatio, tca::ShowerStruct::ChgDensity, tca::TCSlice::cots, tca::Trajectory::CTP, tca::ShowerStruct::DirectionFOM, tca::Trajectory::EndPt, tca::ShowerStruct::Energy, tca::ShowerStruct::Envelope, tca::ShowerStruct::EnvelopeArea, tca::Trajectory::ID, kShowerTj, 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, tcc, tca::ShowerStruct::TjIDs, tca::ShowerStruct::TruParentID, tca::Trajectory::UID, tca::TCConfig::unitsPerTick, tca::Trajectory::VtxID, and tca::Trajectory::WorkID.

Referenced by CheckHiMultUnusedHits(), CheckTraj(), ChkChgAsymmetry(), tca::TrajClusterAlg::ChkInTraj(), DotProd(), FixTrajEnd(), InTrajOK(), IsGhost(), MakeHaloTj(), MakeJunkTraj(), MaskedHitsOK(), MergeAndStore(), tca::TrajClusterAlg::ReconstructAllTraj(), StepAway(), and TrimEndPts().

5456  {
5457  // prints one or all trajectory points on tj
5458 
5459  int trupdg = 0;
5460 // if(tj.mcpListIndex < evt.mcpList.size()) trupdg = evt.mcpList[tj.mcpListIndex]->PdgCode();
5461 
5462  if(tPoint == USHRT_MAX) {
5463  if(tj.ID < 0) {
5464  mf::LogVerbatim myprt("TC");
5465  myprt<<someText<<" ";
5466  myprt<<"Work: UID "<<tj.UID<<" CTP "<<tj.CTP<<" StepDir "<<tj.StepDir<<" PDG "<<tj.PDGCode<<" TruPDG "<<trupdg<<" slc.vtxs "<<tj.VtxID[0]<<" "<<tj.VtxID[1]<<" nPts "<<tj.Pts.size()<<" EndPts "<<tj.EndPt[0]<<" "<<tj.EndPt[1];
5467  myprt<<" MCSMom "<<tj.MCSMom;
5468  myprt<<" StopFlags "<<PrintStopFlag(tj, 0)<<" "<<PrintStopFlag(tj, 1);
5469  myprt<<" AlgMod names:";
5470  for(unsigned short ib = 0; ib < AlgBitNames.size(); ++ib) if(tj.AlgMod[ib]) myprt<<" "<<AlgBitNames[ib];
5471  } else {
5472  mf::LogVerbatim myprt("TC");
5473  myprt<<someText<<" ";
5474  myprt<<"slc.tjs: UID "<<tj.UID<<" WorkID "<<tj.WorkID<<" StepDir "<<tj.StepDir<<" PDG "<<tj.PDGCode<<" TruPDG "<<trupdg<<" slc.vtxs "<<tj.VtxID[0]<<" "<<tj.VtxID[1]<<" nPts "<<tj.Pts.size()<<" EndPts "<<tj.EndPt[0]<<" "<<tj.EndPt[1];
5475  myprt<<" MCSMom "<<tj.MCSMom;
5476  myprt<<" StopFlags "<<PrintStopFlag(tj, 0)<<" "<<PrintStopFlag(tj, 1);
5477  myprt<<" AlgMod names:";
5478  for(unsigned short ib = 0; ib < AlgBitNames.size(); ++ib) if(tj.AlgMod[ib]) myprt<<" "<<AlgBitNames[ib];
5479  }
5480  PrintHeader(someText);
5481  for(unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) PrintTrajPoint(someText, slc, ipt, tj.StepDir, tj.Pass, tj.Pts[ipt]);
5482  // See if this trajectory is a shower Tj
5483  if(tj.AlgMod[kShowerTj]) {
5484  for(unsigned short ic = 0; ic < slc.cots.size(); ++ic) {
5485  if(slc.cots[ic].TjIDs.empty()) continue;
5486  // only print out the info for the correct Tj
5487  if(slc.cots[ic].ShowerTjID != tj.ID) continue;
5488  const ShowerStruct& ss = slc.cots[ic];
5489  mf::LogVerbatim myprt("TC");
5490  myprt<<"cots index "<<ic<<" ";
5491  myprt<<someText<<" Envelope";
5492  if(ss.Envelope.empty()) {
5493  myprt<<" NA";
5494  } else {
5495  for(auto& vtx : ss.Envelope) myprt<<" "<<(int)vtx[0]<<":"<<(int)(vtx[1]/tcc.unitsPerTick);
5496  }
5497  myprt<<" Energy "<<(int)ss.Energy;
5498  myprt<<" Area "<<std::fixed<<std::setprecision(1)<<(int)ss.EnvelopeArea<<" ChgDensity "<<ss.ChgDensity;
5499  myprt<<"\nInShower TjIDs";
5500  for(auto& tjID : ss.TjIDs) {
5501  myprt<<" "<<tjID;
5502  } // tjIDA_Klystron_4U
5503 
5504  myprt<<"\n";
5505  myprt<<"NearTjIDs";
5506  for(auto& tjID : ss.NearTjIDs) {
5507  myprt<<" "<<tjID;
5508  } // tjID
5509  myprt<<"\n";
5510  myprt<<"\n";
5511  myprt<<"Angle "<<std::fixed<<std::setprecision(2)<<ss.Angle<<" +/- "<<ss.AngleErr;
5512  myprt<<" AspectRatio "<<std::fixed<<std::setprecision(2)<<ss.AspectRatio;
5513  myprt<<" DirectionFOM "<<std::fixed<<std::setprecision(2)<<ss.DirectionFOM;
5514  if(ss.ParentID > 0) {
5515  myprt<<" Parent Tj "<<ss.ParentID<<" FOM "<<ss.ParentFOM;
5516  } else {
5517  myprt<<" No parent";
5518  }
5519  myprt<<" TruParentID "<<ss.TruParentID<<" SS3ID "<<ss.SS3ID<<"\n";
5520  if(ss.NeedsUpdate) myprt<<"*********** This shower needs to be updated ***********";
5521  myprt<<"................................................";
5522  } // ic
5523  } // Shower Tj
5524  } else {
5525  // just print one traj point
5526  if(tPoint > tj.Pts.size() -1) {
5527  mf::LogVerbatim("TC")<<"Can't print non-existent traj point "<<tPoint;
5528  return;
5529  }
5530  PrintTrajPoint(someText, slc, tPoint, tj.StepDir, tj.Pass, tj.Pts[tPoint]);
5531  }
5532  } // PrintTrajectory
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
const std::vector< std::string > AlgBitNames
Definition: DataStructs.cxx:13
TCConfig tcc
Definition: DataStructs.cxx:6
Float_t ss
Definition: plot.C:23
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
std::string PrintStopFlag(const Trajectory &tj, unsigned short end)
Definition: Utils.cxx:5677
void PrintHeader(std::string someText)
Definition: Utils.cxx:5535
void PrintTrajPoint(std::string someText, TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, TrajPoint const &tp)
Definition: Utils.cxx:5541
void tca::PrintTrajPoint ( std::string  someText,
TCSlice slc,
unsigned short  ipt,
short  dir,
unsigned short  pass,
TrajPoint const &  tp 
)

Definition at line 5541 of file Utils.cxx.

References tca::TCEvent::allHits, 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, evt, tca::TrajPoint::FitChi, tca::TrajPoint::Hits, tca::TrajPoint::NTPsFit, tca::TrajPoint::Pos, tca::TCSlice::slHits, tca::TrajPoint::Step, tcc, tca::TCConfig::unitsPerTick, and tca::TrajPoint::UseHit.

Referenced by DotProd(), FillGaps(), FindVtxTjs(), FitVertex(), FixTrajBegin(), HiEndDelta(), PrintAllTraj(), PrintTrajectory(), SplitTrajCrossingVertices(), and StepAway().

5542  {
5543  mf::LogVerbatim myprt("TC");
5544  myprt<<someText<<" TRP"<<std::fixed;
5545  myprt<<pass;
5546  if(dir > 0) { myprt<<"+"; } else { myprt<<"-"; }
5547  myprt<<std::setw(6)<<tp.CTP;
5548  myprt<<std::setw(5)<<ipt;
5549  myprt<<std::setw(5)<<tp.Step;
5550  myprt<<std::setw(7)<<std::setprecision(1)<<tp.Pos[0]<<":"<<tp.Pos[1]/tcc.unitsPerTick; // W:T
5551  if(tp.Pos[1] < 10) { myprt<<" "; }
5552  if(tp.Pos[1] < 100) { myprt<<" "; }
5553  if(tp.Pos[1] < 1000) { myprt<<" "; }
5554  myprt<<std::setw(6)<<std::setprecision(2)<<tp.Delta;
5555  myprt<<std::setw(6)<<std::setprecision(2)<<tp.DeltaRMS;
5556  myprt<<std::setw(6)<<std::setprecision(2)<<tp.Ang;
5557  myprt<<std::setw(2)<<tp.AngleCode;
5558  myprt<<std::setw(6)<<std::setprecision(2)<<tp.AngErr;
5559  myprt<<std::setw(6)<<std::setprecision(2)<<tp.Dir[0];
5560  myprt<<std::setw(6)<<std::setprecision(2)<<tp.Dir[1];
5561  myprt<<std::setw(7)<<(int)tp.Chg;
5562  myprt<<std::setw(8)<<(int)tp.AveChg;
5563  myprt<<std::setw(6)<<std::setprecision(1)<<tp.ChgPull;
5564  myprt<<std::setw(7)<<tp.FitChi;
5565  myprt<<std::setw(6)<<tp.NTPsFit;
5566  // print the hits associated with this traj point
5567  if(tp.Hits.size() > 16) {
5568  // don't print too many hits (e.g. from a shower Tj)
5569  myprt<<" "<<tp.Hits.size()<<" shower hits";
5570  } else {
5571  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
5572  unsigned int iht = tp.Hits[ii];
5573  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
5574  myprt<<" "<<hit.WireID().Wire<<":"<<(int)hit.PeakTime();
5575  if(tp.UseHit[ii]) {
5576  // Distinguish used hits from nearby hits
5577  myprt<<"_";
5578  } else {
5579  myprt<<"x";
5580  }
5581  myprt<<slc.slHits[iht].InTraj;
5582  } // iht
5583  }
5584  } // PrintTrajPoint
TCConfig tcc
Definition: DataStructs.cxx:6
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
Detector simulation of raw signals on wires.
TDirectory * dir
Definition: macro.C:5
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
std::vector< unsigned int > tca::PutTrajHitsInVector ( Trajectory const &  tj,
HitStatus_t  hitRequest 
)

Definition at line 2416 of file Utils.cxx.

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

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

2417  {
2418  // Put hits in each trajectory point into a flat vector
2419  std::vector<unsigned int> hitVec;
2420 
2421  // special handling for shower trajectories. UseHit isn't valid
2422  if(tj.AlgMod[kShowerTj]) {
2423  for(auto& tp : tj.Pts) hitVec.insert(hitVec.end(), tp.Hits.begin(), tp.Hits.end());
2424  return hitVec;
2425  } // shower Tj
2426 
2427  // reserve under the assumption that there will be one hit per point
2428  hitVec.reserve(tj.Pts.size());
2429  for(unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) {
2430  for(unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
2431  unsigned int iht = tj.Pts[ipt].Hits[ii];
2432  bool useit = (hitRequest == kAllHits);
2433  if(tj.Pts[ipt].UseHit[ii] && hitRequest == kUsedHits) useit = true;
2434  if(!tj.Pts[ipt].UseHit[ii] && hitRequest == kUnusedHits) useit = true;
2435  if(useit) hitVec.push_back(iht);
2436  } // iht
2437  } // ipt
2438  return hitVec;
2439  } // PutTrajHitsInVector
bool tca::Reconcile3D ( std::string  inFcnLabel,
TCSlice slc,
bool  parentSearchDone,
bool  prt 
)

Definition at line 431 of file TCShower.cxx.

References AddPFP(), ChkAssns(), tca::TCSlice::cots, evd::details::end(), GetAssns(), GetSliceIndex(), tca::TCSlice::ID, InShowerProb(), kMat3D, MakeShowerObsolete(), MergeShowersAndStore(), tca::TCSlice::pfps, Print2DShowers(), RemovePFP(), SetIntersection(), ShowerEnergy(), tca::TCSlice::showers, slices, ss, tca::TCSlice::tjs, and UpdateShower().

432  {
433  // Reconcile pfp and shower assns
434 
435  std::string fcnLabel = inFcnLabel + ".R3D2";
436 
437  if(prt) Print2DShowers("R3D2i", slc, USHRT_MAX, false);
438 
439  // consider them pair-wise
440  if(slc.showers.size() > 1) {
441  for(unsigned short ii = 0; ii < slc.showers.size() - 1; ++ii) {
442  auto iss3 = slc.showers[ii];
443  if(iss3.ID == 0) continue;
444  auto iPInSS3 = GetAssns(slc, "3S", iss3.ID, "P");
445  if(prt) {
446  mf::LogVerbatim myprt("TC");
447  myprt<<fcnLabel<<" 3S"<<iss3.ID<<" ->";
448  for(auto pid : iPInSS3) myprt<<" P"<<pid;
449  } // prt
450  for(unsigned short jj = ii + 1; jj < slc.showers.size(); ++jj) {
451  auto jss3 = slc.showers[jj];
452  if(jss3.ID == 0) continue;
453  auto jPInSS3 = GetAssns(slc, "3S", jss3.ID, "P");
454  auto shared = SetIntersection(iPInSS3, jPInSS3);
455  if(shared.empty()) continue;
456  if(prt) {
457  mf::LogVerbatim myprt("TC");
458  myprt<<fcnLabel<<" Conflict i3S"<<iss3.ID<<" and j3S"<<jss3.ID<<" share";
459  for(auto pid : shared) myprt<<" P"<<pid;
460  } // prt
461  // Compare the InShower likelihoods
462  for(auto pid : shared) {
463  auto& pfp = slc.pfps[pid - 1];
464  float iProb = InShowerProb(slc, iss3, pfp);
465  float jProb = InShowerProb(slc, jss3, pfp);
466  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" i3S"<<iss3.ID<<" prob "<<std::setprecision(3)<<iProb<<" j3S"<<jss3.ID<<" prob "<<jProb;
467  if(iProb > jProb) {
468  // remove the remnants of pfp from jss3
469  RemovePFP(fcnLabel, slc, pfp, jss3, true, prt);
470  // and add them to iss3
471  AddPFP(fcnLabel, slc, pfp.ID, iss3, true, prt);
472  } else {
473  RemovePFP(fcnLabel, slc, pfp, iss3, true, prt);
474  AddPFP(fcnLabel, slc, pfp.ID, jss3, true, prt);
475  }
476  } // pid
477  } // jj
478  } // ii
479  } // > 1 shower
480 
481  // Look for an in-shower pfp that is not the shower parent that is attached to a vertex.
482  // Remove the attachment and any parent - daughter assn
483  if(parentSearchDone) {
484  for(auto& ss3 : slc.showers) {
485  if(ss3.ID == 0) continue;
486  auto PIn3S = GetAssns(slc, "3S", ss3.ID, "P");
487  for(auto pid : PIn3S) {
488  if(pid == ss3.ParentID) continue;
489  auto& pfp = slc.pfps[pid - 1];
490  for(unsigned short end = 0; end < 2; ++end) {
491  if(pfp.Vx3ID[end] <= 0) continue;
492  if(prt) {
493  mf::LogVerbatim myprt("TC");
494  myprt<<fcnLabel<<" Detach 3S"<<ss3.ID<<" -> P"<<pfp.ID<<"_"<<end<<" -> 3V"<<pfp.Vx3ID[end];
495  if(pfp.ParentUID > 0) myprt<<" ->Parent P"<<pfp.ParentUID;
496  }
497  // remove P -> P parent-daughter assn
498  pfp.Vx3ID[end] = 0;
499  if(pfp.ParentUID > 0) {
500  auto slcIndx = GetSliceIndex("P", pfp.ParentUID);
501  auto& parentPFP = slices[slcIndx.first].pfps[slcIndx.second];
502  std::vector<int> newDtrUIDs;
503  for(auto did : parentPFP.DtrUIDs) if(did != pfp.UID) newDtrUIDs.push_back(did);
504  parentPFP.DtrUIDs = newDtrUIDs;
505  } // pfp Parent exists
506  } // end
507  } // pid
508  } // ss3
509  } // parentSearchDone
510 
511  // now look for 2D showers that not matched in 3D and have tjs
512  // that are 3D-matched
513  for(auto& ss : slc.cots) {
514  if(ss.ID == 0) continue;
515  if(ss.SS3ID > 0) continue;
516  std::vector<int> matchedTjs;
517  for(auto tid : ss.TjIDs) if(slc.tjs[tid - 1].AlgMod[kMat3D]) matchedTjs.push_back(tid);
518  if(matchedTjs.empty()) continue;
519  // try to merge it with an existing 3D-matched shower
520  int mergeWith3S = 0;
521  // The merge is compatible if it only matches to one shower
522  bool isCompatible = true;
523  for(auto tid : matchedTjs) {
524  auto TInP = GetAssns(slc, "T", tid, "P");
525  if(TInP.empty()) continue;
526  // do some more checking. See what other showers the Tjs in the pfp
527  // may belong to in other planes
528  auto PIn3S = GetAssns(slc, "P", TInP[0], "3S");
529  for(auto sid : PIn3S) {
530  // require that the energy be lower
531  auto& ss3 = slc.showers[sid - 1];
532  if(ss.Energy > ShowerEnergy(ss3)) continue;
533  if(mergeWith3S == 0) mergeWith3S = sid;
534  if(mergeWith3S > 0 && mergeWith3S != sid) isCompatible = false;
535  } // sid
536  } // tid
537  if(prt) {
538  mf::LogVerbatim myprt("TC");
539  myprt<<fcnLabel<<" 2S"<<ss.ID<<" is not 3D-matched but has 3D-matched Tjs:";
540  for(auto tid : matchedTjs) {
541  myprt<<" T"<<tid;
542  auto TInP = GetAssns(slc, "T", tid, "P");
543  if(!TInP.empty()) {
544  myprt<<"->P"<<TInP[0];
545  } // TInP not empty
546  } // tid
547  } // prt
548  if(mergeWith3S == 0 && ss.Energy < 50) {
549  // kill it
550  MakeShowerObsolete(fcnLabel, slc, ss, prt);
551  } else if(mergeWith3S > 0 && isCompatible) {
552  auto& ss3 = slc.showers[mergeWith3S - 1];
553  for(auto cid : ss3.CotIDs) {
554  auto& oss = slc.cots[cid - 1];
555  if(oss.CTP != ss.CTP) continue;
556  if(!MergeShowersAndStore(fcnLabel, slc, oss.ID, ss.ID, prt)) {
557  std::cout<<fcnLabel<<" Merge failed\n";
558  }
559  if(!UpdateShower(fcnLabel, slc, oss, prt)) {
560  std::cout<<fcnLabel<<" UpdateShower failed\n";
561  }
562  ss3.NeedsUpdate = true;
563  if(!UpdateShower(fcnLabel, slc, ss3, prt)) {
564  std::cout<<fcnLabel<<" UpdateShower failed\n";
565  }
566  break;
567  } // cid
568  } // mergeWith3S > 0
569  } // ss
570 
571 
572  if(prt) Print2DShowers("R3D2o", slc, USHRT_MAX, false);
573 
574  ChkAssns(fcnLabel, slc);
575 
576  return true;
577  } // Reconcile3D
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4279
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4560
Float_t ss
Definition: plot.C:23
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:231
void MakeShowerObsolete(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3266
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1230
float ShowerEnergy(TCSlice &slc, const std::vector< int > tjIDs)
Definition: TCShower.cxx:4382
float InShowerProb(TCSlice &slc, const ShowerStruct &ss, const Trajectory &tj)
Definition: TCShower.cxx:2127
bool AddPFP(std::string inFcnLabel, TCSlice &slc, int pID, ShowerStruct3D &ss3, bool doUpdate, bool prt)
Definition: TCShower.cxx:1498
std::vector< TCSlice > slices
Definition: DataStructs.cxx:10
bool MergeShowersAndStore(std::string inFcnLabel, TCSlice &slc, int icotID, int jcotID, bool prt)
Definition: TCShower.cxx:2985
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:4496
bool RemovePFP(std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, ShowerStruct3D &ss3, bool doUpdate, bool prt)
Definition: TCShower.cxx:1475
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void Print2DShowers(std::string someText, TCSlice &slc, CTP_t inCTP, bool printKilledShowers)
Definition: TCShower.cxx:4648
bool tca::Reconcile3D ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 580 of file TCShower.cxx.

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

Referenced by FindShowers3D(), and Match2DShowers().

581  {
582  // checks consistency between pfparticles, showers and tjs associated with ss3
583  if(ss3.ID == 0) return false;
584  // it isn't a failure if there is a 3D shower in two planes
585  if(ss3.CotIDs.size() < 3) return true;
586  std::string fcnLabel = inFcnLabel + ".R3D";
587 
588  if(prt) Print2DShowers("R3Di", slc, USHRT_MAX, false);
589 
590  // make local copies so we can recover from a failure
591  auto oldSS3 = ss3;
592  std::vector<ShowerStruct> oldSS(ss3.CotIDs.size());
593  for(unsigned short ii = 0; ii < ss3.CotIDs.size(); ++ii) {
594  oldSS[ii] = slc.cots[ss3.CotIDs[ii] - 1];
595  }
596 
597  std::vector<std::vector<int>> plist(ss3.CotIDs.size());
598  for(unsigned short ci = 0; ci < ss3.CotIDs.size(); ++ci) {
599  auto& ss = slc.cots[ss3.CotIDs[ci] - 1];
600  for(auto tid : ss.TjIDs) {
601  auto tToP = GetAssns(slc, "T", tid, "P");
602  if(tToP.empty()) continue;
603  // there should only be one pfp for a tj
604  int pid = tToP[0];
605  if(std::find(plist[ci].begin(), plist[ci].end(), pid) == plist[ci].end()) plist[ci].push_back(pid);
606  } // tid
607  } // ci
608  // count the occurrence of each pfp
609  std::vector<std::array<int, 2>> p_cnt;
610  for(auto& pl : plist) {
611  for(auto pid : pl) {
612  unsigned short indx = 0;
613  for(indx = 0; indx < p_cnt.size(); ++indx) if(p_cnt[indx][0] == pid) break;
614  if(indx == p_cnt.size()) {
615  // not found so add it
616  p_cnt.push_back(std::array<int,2> {{pid, 1}});
617  } else {
618  ++p_cnt[indx][1];
619  }
620  } // pid
621  } // pl
622  if(prt) {
623  mf::LogVerbatim myprt("TC");
624  myprt<<fcnLabel<<" 3S"<<ss3.ID<<"\n";
625  for(unsigned short ci = 0; ci < ss3.CotIDs.size(); ++ci) {
626  myprt<<" -> 2S"<<ss3.CotIDs[ci]<<" ->";
627  for(auto pid : plist[ci]) myprt<<" P"<<pid;
628  myprt<<"\n";
629  } // ci
630  myprt<<" P<ID>_count:";
631  for(auto& pc : p_cnt) myprt<<" P"<<pc[0]<<"_"<<pc[1];
632  } // prt
633 
634  for(auto& pc : p_cnt) {
635  // matched in all planes?
636  if(pc[1] == (int)ss3.CotIDs.size()) continue;
637  if(pc[1] == 2) {
638  // missing a tj in a plane or is this a two-plane pfp?
639  auto& pfp = slc.pfps[pc[0] - 1];
640  if(pfp.TjIDs.size() > 2) {
641  // ensure that none of the tjs in this pfp are included in a different shower
642  auto PIn2S = GetAssns(slc, "P", pfp.ID, "2S");
643  auto sDiff = SetDifference(PIn2S, ss3.CotIDs);
644  // Not sure if this can happen
645 // if(sDiff.size() > 1) {std::cout<<fcnLabel<<" sDiff size > 2. Is this possible?\n";}
646  if(!sDiff.empty() && std::find(ss3.CotIDs.begin(), ss3.CotIDs.end(), sDiff[0]) == ss3.CotIDs.end()) continue;
647  if(prt) {
648  mf::LogVerbatim myprt("TC");
649  myprt<<fcnLabel<<" 3S"<<ss3.ID<<" P"<<pfp.ID<<" ->";
650  for(auto sid : PIn2S) myprt<<" 2S"<<sid;
651  myprt<<" sDiff";
652  for(auto sid : sDiff) myprt<<" 2S"<<sid;
653  } // prt
654  // missed a tj in a 2D shower so "add the PFP to the shower" and update it
655  if(AddPFP(fcnLabel, slc, pfp.ID, ss3, true, prt)) {
656  // Update the local copies
657  oldSS3 = ss3;
658  if(ss3.CotIDs.size() != oldSS.size()) {
659  std::cout<<fcnLabel<<" Major failure...";
660  return false;
661  }
662  for(unsigned short ii = 0; ii < ss3.CotIDs.size(); ++ii) oldSS[ii] = slc.cots[ss3.CotIDs[ii] - 1];
663  } else {
664  // restore the previous state
665  ss3 = oldSS3;
666  for(unsigned short ii = 0; ii < oldSS.size(); ++ii) {
667  auto& ss = oldSS[ii];
668  slc.cots[ss.ID - 1] = ss;
669  } // ii
670  } // AddPFP failed
671  } // pfp.TjIDs.size() > 2
672  } else {
673  // only one occurrence. check proximity to ss3
674  auto& pfp = slc.pfps[pc[0] - 1];
675  unsigned short nearEnd = 1 - FarEnd(slc, pfp, ss3.ChgPos);
676  float prob = InShowerProb(slc, ss3, pfp);
677  float sep = PosSep(pfp.XYZ[nearEnd], ss3.ChgPos);
678  if(prt) {
679  mf::LogVerbatim myprt("TC");
680  myprt<<fcnLabel<<" one occurrence: P"<<pfp.ID<<"_"<<nearEnd<<" closest to ChgPos";
681  myprt<<" ChgPos "<<std::fixed<<std::setprecision(1)<<ss3.ChgPos[0]<<" "<<ss3.ChgPos[1]<<" "<<ss3.ChgPos[2];
682  myprt<<" sep "<<sep;
683  myprt<<" InShowerProb "<<prob;
684  } // prt
685  if(sep < 30 && prob > 0.3 && AddPFP(fcnLabel, slc, pfp.ID, ss3, true, prt)) {
686  if(prt) mf::LogVerbatim("TC")<<" AddPFP success";
687  } else if(!RemovePFP(fcnLabel, slc, pfp, ss3, true, prt)) {
688  std::cout<<"RemovePFP failed \n";
689  }
690  } // only one occurrence.
691  } // pc
692 
693  if(!UpdateShower(fcnLabel, slc, ss3, prt)) return false;
694  ChkAssns(fcnLabel, slc);
695  if(prt) Print2DShowers("R3Do", slc, USHRT_MAX, false);
696 
697  return true;
698 
699  } // Reconcile3D
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4279
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4560
Float_t ss
Definition: plot.C:23
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1230
std::vector< evd::details::RawDigitInfo_t >::const_iterator begin(RawDigitCacheDataClass const &cache)
float InShowerProb(TCSlice &slc, const ShowerStruct &ss, const Trajectory &tj)
Definition: TCShower.cxx:2127
unsigned short FarEnd(TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3032
bool AddPFP(std::string inFcnLabel, TCSlice &slc, int pID, ShowerStruct3D &ss3, bool doUpdate, bool prt)
Definition: TCShower.cxx:1498
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
bool RemovePFP(std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, ShowerStruct3D &ss3, bool doUpdate, bool prt)
Definition: TCShower.cxx:1475
std::vector< T > SetDifference(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:253
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void Print2DShowers(std::string someText, TCSlice &slc, CTP_t inCTP, bool printKilledShowers)
Definition: TCShower.cxx:4648
void tca::ReleaseHits ( TCSlice slc,
Trajectory tj 
)

Definition at line 1150 of file Utils.cxx.

References tca::Trajectory::ID, tca::Trajectory::Pts, and tca::TCSlice::slHits.

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

1151  {
1152  // Sets InTraj[] = 0 for all TPs in work. Called when abandoning work
1153  for(auto& tp : tj.Pts) {
1154  for(auto iht : tp.Hits) {
1155  if(slc.slHits[iht].InTraj == tj.ID) slc.slHits[iht].InTraj = 0;
1156  }
1157  } // tp
1158 
1159  } // ReleaseWorkHits
bool tca::RemovePFP ( std::string  inFcnLabel,
TCSlice slc,
int  pID,
ShowerStruct3D ss3,
bool  doUpdate,
bool  prt 
)
bool tca::RemovePFP ( std::string  inFcnLabel,
TCSlice slc,
PFPStruct pfp,
ShowerStruct3D ss3,
bool  doUpdate,
bool  prt 
)

Definition at line 1475 of file TCShower.cxx.

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

Referenced by Reconcile3D().

1476  {
1477  // removes the tjs in the pfp from the ss3 2D showers and optionally update. This function only returns
1478  // false if there was a failure. The absence of any pfp Tjs in ss3 is not considered a failure
1479 
1480  if(pfp.ID == 0 || ss3.ID == 0) return false;
1481 
1482  std::string fcnLabel = inFcnLabel + ".RemP";
1483  for(auto tid : pfp.TjIDs) {
1484  for(auto cid : ss3.CotIDs) {
1485  auto& ss = slc.cots[cid - 1];
1486  if(std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tid) == ss.TjIDs.end()) continue;
1487  if(!RemoveTj(fcnLabel, slc, tid, ss, doUpdate, prt)) return false;
1488  ss3.NeedsUpdate = true;
1489  } // cid
1490  } // ptid
1491 
1492  if(doUpdate && ss3.NeedsUpdate) UpdateShower(fcnLabel, slc, ss3, prt);
1493  return true;
1494 
1495  } // Remove PFP
Float_t ss
Definition: plot.C:23
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1230
bool RemoveTj(std::string inFcnLabel, TCSlice &slc, int TjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1620
bool tca::RemoveTj ( std::string  inFcnLabel,
TCSlice slc,
int  TjID,
ShowerStruct ss,
bool  doUpdate,
bool  prt 
)

Definition at line 1620 of file TCShower.cxx.

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

Referenced by RemovePFP().

1621  {
1622  // Removes the Tj from a shower
1623 
1624  if(TjID > (int)slc.tjs.size()) return false;
1625 
1626  std::string fcnLabel = inFcnLabel + ".RTj";
1627 
1628  // make sure it isn't already in a shower
1629  Trajectory& tj = slc.tjs[TjID - 1];
1630 
1631  if(tj.SSID != ss.ID) {
1632  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Can't Remove T"<<TjID<<" from 2S"<<ss.ID<<" because it's not in this shower";
1633  // This isn't a failure
1634  return true;
1635  }
1636  tj.AlgMod[kShwrParent] = false;
1637 
1638  bool gotit = false;
1639  for(unsigned short ii = 0; ii < ss.TjIDs.size(); ++ii) {
1640  if(TjID == ss.TjIDs[ii]) {
1641  ss.TjIDs.erase(ss.TjIDs.begin() + ii);
1642  gotit = true;
1643  break;
1644  }
1645  } // ii
1646  if(!gotit) return false;
1647  tj.SSID = 0;
1648  // Removing a parent Tj?
1649  if(TjID == ss.ParentID) ss.ParentID = 0;
1650  // re-build everything?
1651  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Remove T"<<TjID<<" from 2S"<<ss.ID;
1652  // removed the only tj
1653  if(ss.TjIDs.empty()) {
1654  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Removed the last Tj. Killing 2S"<<ss.ID;
1655  MakeShowerObsolete(fcnLabel, slc, ss, prt);
1656  return true;
1657  }
1658  // clear out the shower points to force a complete update when UpdateShower is next called
1659  ss.ShPts.clear();
1660  if(doUpdate) {
1661  ss.NeedsUpdate = true;
1662  return UpdateShower(fcnLabel, slc, ss, prt);
1663  }
1664  return true;
1665  } // RemoveTj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
Float_t ss
Definition: plot.C:23
void MakeShowerObsolete(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3266
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1230
void tca::RestoreObsoleteTrajectory ( TCSlice slc,
unsigned int  itj 
)

Definition at line 1933 of file Utils.cxx.

References kKilled, tca::TCSlice::slHits, and tca::TCSlice::tjs.

1934  {
1935  if(itj > slc.tjs.size() - 1) return;
1936  if(!slc.tjs[itj].AlgMod[kKilled]) {
1937  mf::LogWarning("TC")<<"RestoreObsoleteTrajectory: Trying to restore not-obsolete trajectory "<<slc.tjs[itj].ID;
1938  return;
1939  }
1940  unsigned int iht;
1941  for(auto& tp : slc.tjs[itj].Pts) {
1942  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1943  if(tp.UseHit[ii]) {
1944  iht = tp.Hits[ii];
1945  if(slc.slHits[iht].InTraj == 0) {
1946  slc.slHits[iht].InTraj = slc.tjs[itj].ID;
1947  }
1948  }
1949  } // ii
1950  } // tp
1951  slc.tjs[itj].AlgMod[kKilled] = false;
1952  } // RestoreObsoleteTrajectory
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
void tca::Reverse3DMatchTjs ( TCSlice slc,
PFPStruct pfp,
bool  prt 
)

Definition at line 1078 of file Utils.cxx.

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

1079  {
1080  // Return true if the 3D matched hits in the trajectories in slc.pfps are in the wrong order in terms of the
1081  // physics standpoint, e.g. dQ/dx, muon delta-ray tag, cosmic rays entering the detector, etc.
1082 
1083  // Don't reverse showers
1084  if(pfp.PDGCode == 1111) return;
1085 
1086  bool reverseMe = false;
1087 
1088  // look for stopping Tjs for contained PFParticles
1089  if(!reverseMe) {
1090  unsigned short braggCnt0 = 0;
1091  unsigned short braggCnt1 = 0;
1092  for(auto& tjID : pfp.TjIDs) {
1093  auto& tj = slc.tjs[tjID - 1];
1094  if(tj.StopFlag[0][kBragg]) ++braggCnt0;
1095  if(tj.StopFlag[1][kBragg]) ++braggCnt1;
1096  }
1097  if(braggCnt0 > 0 || braggCnt1 > 0) {
1098  pfp.PDGCode = 2212;
1099  // Vote for a Bragg peak at the beginning. It should be at the end
1100  if(braggCnt0 > braggCnt1) reverseMe = true;
1101  } // found a Bragg Peak
1102  } // look for stopping Tjs
1103 
1104  if(!reverseMe) return;
1105 
1106  // All of the trajectories should be reversed
1107  for(auto& tjID : pfp.TjIDs) {
1108  unsigned short itj = tjID - 1;
1109  Trajectory& tj = slc.tjs[itj];
1110  tj.AlgMod[kMat3D] = false;
1111  ReverseTraj(slc, tj);
1112  tj.AlgMod[kMat3D] = true;
1113  } // tjID
1114  // swap the matchVec end info also
1115  std::swap(pfp.XYZ[0], pfp.XYZ[1]);
1116  std::swap(pfp.Dir[0], pfp.Dir[1]);
1117  std::swap(pfp.DirErr[0], pfp.DirErr[1]);
1118  std::swap(pfp.dEdx[0], pfp.dEdx[1]);
1119  std::swap(pfp.dEdxErr[0], pfp.dEdxErr[1]);
1120  std::swap(pfp.Vx3ID[0], pfp.Vx3ID[1]);
1121 
1122  return;
1123 
1124  } // Reverse3DMatchTjs
void ReverseTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:2751
void swap(art::HLTGlobalStatus &lhs, art::HLTGlobalStatus &rhs)
void tca::ReversePFP ( TCSlice slc,
PFPStruct pfp 
)

Definition at line 2935 of file PFPUtils.cxx.

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

Referenced by DotProd(), and StitchPFPs().

2936  {
2937  std::swap(pfp.XYZ[0], pfp.XYZ[1]);
2938  std::swap(pfp.Dir[0], pfp.Dir[1]);
2939  for(unsigned short xyz = 0; xyz < 3; ++xyz) {
2940  pfp.Dir[0][xyz] *= -1;
2941  pfp.Dir[1][xyz] *= -1;
2942  }
2943  std::swap(pfp.DirErr[0], pfp.DirErr[1]);
2944  std::swap(pfp.dEdx[0], pfp.dEdx[1]);
2945  std::swap(pfp.dEdxErr[0], pfp.dEdxErr[1]);
2946  std::swap(pfp.Vx3ID[0], pfp.Vx3ID[1]);
2947  std::reverse(pfp.Tp3s.begin(), pfp.Tp3s.end());
2948  for(auto& tp3 : pfp.Tp3s) {
2949  for(unsigned short xyz = 0; xyz < 3; ++xyz) {
2950  tp3.Dir[xyz] *= -1;
2951  tp3.Dir[xyz] *= -1;
2952  } // xyz
2953  } // tp3
2954  } // ReversePFP
void swap(art::HLTGlobalStatus &lhs, art::HLTGlobalStatus &rhs)
void tca::ReversePropagate ( TCSlice slc,
Trajectory tj 
)

Definition at line 1414 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, ChkStop(), ChkStopEndPts(), tca::Trajectory::CTP, tca::TCConfig::dbgAlg, tca::TCConfig::dbgStp, DecodeCTP(), tca::Trajectory::EndPt, FindCloseHits(), tca::TCSlice::firstWire, tca::TrajPoint::Hits, tca::Trajectory::ID, tca::Trajectory::IsGood, kNormal, kRvPrp, kUnusedHits, tca::TCSlice::lastWire, MoveTPToWire(), geo::PlaneID::Plane, PrintHit(), PrintPos(), tca::Trajectory::Pts, ReverseTraj(), SetEndPoints(), tca::TCSlice::slHits, StepAway(), tca::Trajectory::StepDir, tca::Trajectory::Strategy, tcc, tca::TCConfig::useAlg, tca::TrajPoint::UseHit, and tca::TCSlice::wireHitRange.

Referenced by FixTrajBegin().

1415  {
1416  // Reverse the trajectory and step in the opposite direction. The
1417  // updated trajectory is returned if this process is successful
1418 
1419  if(!tcc.useAlg[kRvPrp]) return;
1420 
1421  if(tj.Pts.size() < 6) return;
1422  // only do this once
1423  if(tj.AlgMod[kRvPrp]) return;
1424 
1425  // This code can't handle VLA trajectories
1426  if(tj.Pts[tj.EndPt[0]].AngleCode == 2) return;
1427 
1428  bool prt = (tcc.dbgStp || tcc.dbgAlg[kRvPrp]);
1429 
1430  if(tj.EndPt[0] > 0) {
1431  tj.Pts.erase(tj.Pts.begin(), tj.Pts.begin() + tj.EndPt[0]);
1432  SetEndPoints(tj);
1433  }
1434 
1435  if(prt) mf::LogVerbatim("TC")<<"ReversePropagate: Prepping Tj "<<tj.ID<<" incoming StepDir "<<tj.StepDir;
1436 
1437  short stepDir = tj.StepDir;
1438 
1439  // find the wire on which EndPt resides
1440  unsigned int wire0 = std::nearbyint(tj.Pts[0].Pos[0]);
1441  unsigned int nextWire = wire0 - tj.StepDir;
1442 
1443  // check for dead wires
1444  geo::PlaneID planeID = DecodeCTP(tj.CTP);
1445  unsigned short ipl = planeID.Plane;
1446  while(nextWire > slc.firstWire[ipl] && nextWire < slc.lastWire[ipl]) {
1447  if(slc.wireHitRange[ipl][nextWire].first >= 0) break;
1448  nextWire -= tj.StepDir;
1449  }
1450  if(nextWire == slc.lastWire[ipl] - 1) return;
1451  // clone the first point
1452  TrajPoint tp = tj.Pts[0];
1453  // strip off the hits
1454  tp.Hits.clear(); tp.UseHit.reset();
1455  // move it to the next wire
1456  MoveTPToWire(tp, (float)nextWire);
1457  // find close unused hits near this position
1458  float maxDelta = 10 * tj.Pts[tj.EndPt[1]].DeltaRMS;
1459  if(!FindCloseHits(slc, tp, maxDelta, kUnusedHits)) return;
1460  if(prt) mf::LogVerbatim("TC")<<" nUnused hits "<<tp.Hits.size()<<" at Pos "<<PrintPos(slc, tp);
1461  if(tp.Hits.empty()) return;
1462  // There are hits on the next wire. Make a copy, reverse it and try
1463  // to extend it with StepAway
1464  if(prt) {
1465  mf::LogVerbatim myprt("TC");
1466  myprt<<" tp.Hits ";
1467  for(auto& iht : tp.Hits) myprt<<" "<<PrintHit(slc.slHits[iht])<<"_"<<slc.slHits[iht].InTraj;
1468  } // tcc.dbgStp
1469  //
1470  // Make a working copy of tj
1471  Trajectory tjWork = tj;
1472  // So the first shall be last and the last shall be first
1473  ReverseTraj(slc, tjWork);
1474  // Flag it to use special cuts in StepAway
1475  tjWork.AlgMod[kRvPrp] = true;
1476  // save the strategy word and set it to normal
1477  auto saveStrategy = tjWork.Strategy;
1478  tjWork.Strategy.reset();
1479  tjWork.Strategy[kNormal] = true;
1480  // Reduce the number of fitted points to a small number
1481  unsigned short lastPt = tjWork.Pts.size() - 1;
1482  if(lastPt < 4) return;
1483  // update the charge
1484  float chg = 0;
1485  float cnt = 0;
1486  for(unsigned short ii = 0; ii < 4; ++ii) {
1487  unsigned short ipt = lastPt - ii;
1488  if(tjWork.Pts[ipt].Chg == 0) continue;
1489  chg += tjWork.Pts[ipt].Chg;
1490  ++cnt;
1491  } // ii
1492  if(cnt == 0) return;
1493  if(cnt > 1) tjWork.Pts[lastPt].AveChg = chg / cnt;
1494  StepAway(slc, tjWork);
1495  if(!tj.IsGood) {
1496  if(prt) mf::LogVerbatim("TC")<<" ReversePropagate StepAway failed";
1497  return;
1498  }
1499  tjWork.Strategy = saveStrategy;
1500  // check the new stopping point
1501  ChkStopEndPts(slc, tjWork, tcc.dbgStp);
1502  // restore the original direction
1503  if(tjWork.StepDir != stepDir) ReverseTraj(slc, tjWork);
1504  tj = tjWork;
1505  // TODO: Maybe UpdateTjChgProperties should be called here
1506  // re-check the ends
1507  ChkStop(slc, tj);
1508  if(prt) {
1509  mf::LogVerbatim("TC")<<" ReversePropagate success. Outgoing StepDir "<<tj.StepDir;
1510 // if(tj.Pts.size() < 50) PrintTrajectory("RP", slc, tj, USHRT_MAX);
1511  }
1512 
1513  } // ReversePropagate
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void StepAway(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:15
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
std::vector< unsigned int > FindCloseHits(TCSlice &slc, std::array< int, 2 > const &wireWindow, Point2_t const &timeWindow, const unsigned short plane, HitStatus_t hitRequest, bool usePeakTime, bool &hitsNear)
Definition: Utils.cxx:2496
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:5704
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
void ReverseTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:2751
void ChkStop(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:3952
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
geo::PlaneID DecodeCTP(CTP_t CTP)
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:505
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2485
void ChkStopEndPts(TCSlice &slc, Trajectory &tj, bool prt)
Definition: StepUtils.cxx:1711
void tca::ReverseShower ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct ss,
bool  prt 
)

Definition at line 3201 of file TCShower.cxx.

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

3202  {
3203  // Reverses the shower and the shower tj
3204 
3205  if(ss.ID == 0) return;
3206  if(ss.TjIDs.empty()) return;
3207 
3208  std::string fcnLabel = inFcnLabel + ".RevSh";
3209 
3210  std::reverse(ss.ShPts.begin(), ss.ShPts.end());
3211  // change the sign of RotPos
3212  for(auto& sspt : ss.ShPts) {
3213  sspt.RotPos[0] = -sspt.RotPos[0];
3214  sspt.RotPos[1] = -sspt.RotPos[1];
3215  }
3216  // flip the shower angle
3217  if(ss.Angle > 0) {
3218  ss.Angle -= M_PI;
3219  } else {
3220  ss.Angle += M_PI;
3221  }
3222  if(ss.DirectionFOM != 0) ss.DirectionFOM = 1 / ss.DirectionFOM;
3223  auto& stj = slc.tjs[ss.ShowerTjID - 1];
3224  ReverseTraj(slc, stj);
3225  DefineEnvelope(fcnLabel, slc, ss, prt);
3226  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Reversed shower. Shower angle = "<<ss.Angle;
3227  } // ReverseShower
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
Float_t ss
Definition: plot.C:23
void DefineEnvelope(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3869
void ReverseTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:2751
void tca::ReverseShower ( std::string  inFcnLabel,
TCSlice slc,
int  cotID,
bool  prt 
)

Definition at line 3230 of file TCShower.cxx.

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

Referenced by FindShowerStart(), and UpdateShower().

3231  {
3232  // Reverses the shower and the shower tj
3233 
3234  if(cotID > (int)slc.cots.size()) return;
3235  ShowerStruct& ss = slc.cots[cotID - 1];
3236  if(ss.ID == 0) return;
3237  ReverseShower(inFcnLabel, slc, ss, prt);
3238 
3239  }
void ReverseShower(std::string inFcnLabel, TCSlice &slc, int cotID, bool prt)
Definition: TCShower.cxx:3230
Float_t ss
Definition: plot.C:23
void tca::ReverseTraj ( TCSlice slc,
Trajectory tj 
)

Definition at line 2751 of file Utils.cxx.

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

Referenced by DefineTjParents(), EndMerge(), MergeAndStore(), MergePFPTjs(), Reverse3DMatchTjs(), ReversePropagate(), ReverseShower(), StorePFP(), and TagDeltaRays().

2752  {
2753  // reverse the trajectory
2754  if(tj.Pts.empty()) return;
2755  // reverse the crawling direction flag
2756  tj.StepDir = -tj.StepDir;
2757  tj.DirFOM = 1 - tj.DirFOM;
2758  // Vertices
2759  std::swap(tj.VtxID[0], tj.VtxID[1]);
2760  // trajectory points
2761  std::reverse(tj.Pts.begin(), tj.Pts.end());
2762  // reverse the stop flag
2763  std::reverse(tj.StopFlag.begin(), tj.StopFlag.end());
2764  std::swap(tj.dEdx[0], tj.dEdx[1]);
2765  // reverse the direction vector on all points
2766  for(unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) {
2767  if(tj.Pts[ipt].Dir[0] != 0) tj.Pts[ipt].Dir[0] = -tj.Pts[ipt].Dir[0];
2768  if(tj.Pts[ipt].Dir[1] != 0) tj.Pts[ipt].Dir[1] = -tj.Pts[ipt].Dir[1];
2769  if(tj.Pts[ipt].Ang > 0) {
2770  tj.Pts[ipt].Ang -= M_PI;
2771  } else {
2772  tj.Pts[ipt].Ang += M_PI;
2773  }
2774  } // ipt
2775  if(tj.StartEnd == 0 || tj.StartEnd == 1) tj.StartEnd = 1 - tj.StartEnd;
2776  SetEndPoints(tj);
2777  UpdateMatchStructs(slc, tj.ID, tj.ID);
2778  } // ReverseTraj
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
void UpdateMatchStructs(TCSlice &slc, int oldTj, int newTj)
Definition: PFPUtils.cxx:160
void swap(art::HLTGlobalStatus &lhs, art::HLTGlobalStatus &rhs)
void tca::SaveAllCots ( TCSlice slc,
const CTP_t inCTP,
std::string  someText 
)

Definition at line 165 of file TCShTree.cxx.

References tca::TCSlice::cots, kSaveShowerTree, tca::TCConfig::modes, SaveTjInfo(), ss, and tcc.

Referenced by FindShowers3D().

165  {
166  if(!tcc.modes[kSaveShowerTree]) return;
167  for(unsigned short cotIndex = 0; cotIndex < slc.cots.size(); ++cotIndex) {
168  auto& ss = slc.cots[cotIndex];
169  if (ss.CTP != inCTP) continue;
170  if(ss.ID == 0) continue;
171  SaveTjInfo(slc, ss, someText);
172  } // cotIndex
173  } // SaveAllCots
TCConfig tcc
Definition: DataStructs.cxx:6
Float_t ss
Definition: plot.C:23
void SaveTjInfo(TCSlice &slc, const ShowerStruct &ss, std::string stageName)
Definition: TCShTree.cxx:47
save shower tree
Definition: DataStructs.h:456
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
void tca::SaveAllCots ( TCSlice slc,
std::string  someText 
)

Definition at line 176 of file TCShTree.cxx.

References tca::TCSlice::cots, kSaveShowerTree, tca::TCConfig::modes, SaveTjInfo(), ss, and tcc.

176  {
177  if(!tcc.modes[kSaveShowerTree]) return;
178  for(unsigned short cotIndex = 0; cotIndex < slc.cots.size(); ++cotIndex) {
179  auto& ss = slc.cots[cotIndex];
180  if(ss.ID == 0) continue;
181  SaveTjInfo(slc, ss, someText);
182  } // cotIndex
183  }
TCConfig tcc
Definition: DataStructs.cxx:6
Float_t ss
Definition: plot.C:23
void SaveTjInfo(TCSlice &slc, const ShowerStruct &ss, std::string stageName)
Definition: TCShTree.cxx:47
save shower tree
Definition: DataStructs.h:456
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
void tca::SaveCRInfo ( TCSlice slc,
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::TCSlice::crt, tca::TCConfig::geom, GetOrigin(), kSaveCRTree, max, geo::BoxBoundedGeo::MaxY(), geo::BoxBoundedGeo::MaxZ(), min, geo::BoxBoundedGeo::MinY(), geo::BoxBoundedGeo::MinZ(), tca::TCConfig::modes, tcc, geo::GeometryCore::TPC(), and tca::PFPStruct::XYZ.

8  {
9 
10  //Check the origin of pfp
11  if (tcc.modes[kSaveCRTree]){
12  if (fIsRealData){
13  slc.crt.cr_origin.push_back(-1);
14  }
15  else{
16  slc.crt.cr_origin.push_back(GetOrigin(slc, pfp));
17  }
18  }
19 
20  // save the xmin and xmax of each pfp
21  slc.crt.cr_pfpxmin.push_back(std::min(pfp.XYZ[0][0], pfp.XYZ[1][0]));
22  slc.crt.cr_pfpxmax.push_back(std::max(pfp.XYZ[0][0], pfp.XYZ[1][0]));
23 
24  //find max
25  const geo::TPCGeo &tpc = tcc.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  slc.crt.cr_pfpyzmindis.push_back(mindis0+mindis1);
38 
39  if (slc.crt.cr_pfpxmin.back()<-2||
40  slc.crt.cr_pfpxmax.back()>260||
41  slc.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 = slc.allTraj[tjID - 1];
52  TrajPoint& beginPoint = tj.Pts[tj.EndPt[0]];
53  TrajPoint& endPoint = tj.Pts[tj.EndPt[1]];
54  if (beginPoint.Pos[1]/slc.unitsPerTick<minx){
55  minx = beginPoint.Pos[1]/slc.unitsPerTick;
56  }
57  if (beginPoint.Pos[1]/slc.unitsPerTick>maxx){
58  maxx = beginPoint.Pos[1]/slc.unitsPerTick;
59  }
60  if (endPoint.Pos[1]/slc.unitsPerTick<minx){
61  minx = endPoint.Pos[1]/slc.unitsPerTick;
62  }
63  if (endPoint.Pos[1]/slc.unitsPerTick>maxx){
64  maxx = endPoint.Pos[1]/slc.unitsPerTick;
65  }
66  } // tjID
67 
68  slc.crt.cr_pfpmintick.push_back(minx);
69  slc.crt.cr_pfpmaxtick.push_back(maxx);
70  */
71 // std::cout<<pfp.mcpListIndex<<std::endl;
72 // std::cout<<pfp.XYZ[0][0]<<" "<<pfp.XYZ[1][0]<<std::endl;
73 
74  }
TCConfig tcc
Definition: DataStructs.cxx:6
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(TCSlice &slc, PFPStruct &pfp)
Definition: TCCR.cxx:77
const geo::GeometryCore * geom
Definition: DataStructs.h:493
double MaxY() const
Returns the world y coordinate of the end of the box.
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
save cosmic ray tree
Definition: DataStructs.h:454
Int_t min
Definition: plot.C:26
double MaxZ() const
Returns the world z coordinate of the end of the box.
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
double MinY() const
Returns the world y coordinate of the start of the box.
void tca::SaveTjInfo ( TCSlice slc,
std::vector< std::vector< int >> &  tjList,
std::string  stageName 
)

Definition at line 5 of file TCShTree.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::CTP, tca::ShowerTreeVars::Envelope, tca::ShowerTreeVars::EnvPlane, tca::ShowerTreeVars::EnvShowerID, tca::ShowerTreeVars::EnvStage, GetStageNum(), tca::Trajectory::ID, kKilled, kSaveShowerTree, tca::TCConfig::modes, SaveTjInfoStuff(), tca::ShowerTreeVars::ShowerID, stv, tcc, and tca::TCSlice::tjs.

Referenced by FindShowers3D(), and SaveAllCots().

6  {
7  if(!tcc.modes[kSaveShowerTree]) return;
8  if(tjList.empty()) return;
9  int stageNum = GetStageNum(stv, stageName);
10 
11  // get the CTP from the first tj
12  CTP_t inCTP = slc.tjs[tjList[0][0] - 1].CTP;
13  for(unsigned short it1 = 0; it1 < slc.tjs.size(); ++it1) {
14  Trajectory& tj1 = slc.tjs[it1];
15  if(tj1.CTP != inCTP) continue;
16  if(tj1.AlgMod[kKilled]) continue;
17 
18  SaveTjInfoStuff(slc, 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  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  stv.Envelope.push_back(-999);
40  stv.EnvStage.push_back(stageNum);
41  stv.EnvPlane.push_back(-1);
42  stv.EnvShowerID.push_back(-1);
43  }
44 
45  } // SaveTjInfo (tjlist)
std::vector< int > EnvStage
Definition: DataStructs.h:330
void SaveTjInfoStuff(TCSlice &slc, Trajectory &tj, int stageNum, std::string stageName)
Definition: TCShTree.cxx:131
TCConfig tcc
Definition: DataStructs.cxx:6
std::vector< int > ShowerID
Definition: DataStructs.h:322
ShowerTreeVars stv
Definition: DataStructs.cxx:8
save shower tree
Definition: DataStructs.h:456
std::vector< float > Envelope
Definition: DataStructs.h:328
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
std::vector< int > EnvPlane
Definition: DataStructs.h:329
unsigned int CTP_t
Definition: DataStructs.h:41
int GetStageNum(ShowerTreeVars &stv, std::string stageName)
Definition: TCShTree.cxx:185
std::vector< int > EnvShowerID
Definition: DataStructs.h:331
void tca::SaveTjInfo ( TCSlice slc,
const ShowerStruct ss,
std::string  stageName 
)

Definition at line 47 of file TCShTree.cxx.

References tca::Trajectory::AlgMod, 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, kSaveShowerTree, kShowerTj, tca::TCConfig::modes, tca::ShowerStruct::ParentID, geo::PlaneID::Plane, tca::ShowerTreeVars::PlaneNum, SaveTjInfoStuff(), tca::ShowerTreeVars::ShowerID, tca::ShowerStruct::ShowerTjID, tca::ShowerTreeVars::StageNum, stv, tcc, tca::ShowerTreeVars::TjID, tca::ShowerStruct::TjIDs, tca::TCSlice::tjs, and tca::TCConfig::unitsPerTick.

47  {
48  if(!tcc.modes[kSaveShowerTree]) return;
49  int stageNum = GetStageNum(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 < slc.tjs.size(); ++it1) {
57 
58  Trajectory& tj1 = slc.tjs[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 < stv.TjID.size(); ++i) {
69  if (stv.StageNum.at(i) != (int)stageNum) continue;
70  if (stv.PlaneNum.at(i) != (short)DecodeCTP(ss.CTP).Plane) continue;
71 
72  if (stv.TjID.at(i) == trajID) {
73  tjIndex = i;
74  if (stv.IsShowerTj.at(tjIndex) == 1) isShowerTj = true;
75  //beenDoneBefore = true;
76  break;
77  }
78  }
79 
80  if (isShowerTj) continue;
81  if (tjIndex == -1) SaveTjInfoStuff(slc, 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) stv.ShowerID.back() = ss.ID;
87  else stv.ShowerID.at(tjIndex) = ss.ID;
88  }
89 
90  if (it1 == (ss.ShowerTjID - 1)) stv.IsShowerTj.back() = 1;
91  else if (tj1.AlgMod[kShowerTj]) 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  stv.ShowerID.back() = ss.ID;
97  stv.IsShowerParent.back() = 1;
98  }
99  else {
100  stv.ShowerID.at(tjIndex) = ss.ID;
101  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  stv.EnvStage.push_back(stageNum);
116  stv.EnvPlane.push_back(iPlnID.Plane);
117  stv.EnvShowerID.push_back(ss.ID);
118  }
119 
120  stv.Envelope.push_back(ss.Envelope[0][0]);
121  stv.Envelope.push_back(ss.Envelope[0][1]/tcc.unitsPerTick);
122  stv.Envelope.push_back(ss.Envelope[1][0]);
123  stv.Envelope.push_back(ss.Envelope[1][1]/tcc.unitsPerTick);
124  stv.Envelope.push_back(ss.Envelope[2][0]);
125  stv.Envelope.push_back(ss.Envelope[2][1]/tcc.unitsPerTick);
126  stv.Envelope.push_back(ss.Envelope[3][0]);
127  stv.Envelope.push_back(ss.Envelope[3][1]/tcc.unitsPerTick);
128 
129  } // SaveTjInfo (cots)
std::vector< int > EnvStage
Definition: DataStructs.h:330
void SaveTjInfoStuff(TCSlice &slc, Trajectory &tj, int stageNum, std::string stageName)
Definition: TCShTree.cxx:131
std::vector< int > IsShowerParent
Definition: DataStructs.h:323
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
Float_t ss
Definition: plot.C:23
std::vector< int > ShowerID
Definition: DataStructs.h:322
ShowerTreeVars stv
Definition: DataStructs.cxx:8
save shower tree
Definition: DataStructs.h:456
std::vector< int > TjID
Definition: DataStructs.h:320
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
std::vector< float > Envelope
Definition: DataStructs.h:328
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
std::vector< int > EnvPlane
Definition: DataStructs.h:329
std::vector< int > StageNum
Definition: DataStructs.h:324
geo::PlaneID DecodeCTP(CTP_t CTP)
int GetStageNum(ShowerTreeVars &stv, std::string stageName)
Definition: TCShTree.cxx:185
std::vector< int > EnvShowerID
Definition: DataStructs.h:331
std::vector< int > IsShowerTj
Definition: DataStructs.h:321
std::vector< short > PlaneNum
Definition: DataStructs.h:318
void tca::SaveTjInfoStuff ( TCSlice slc,
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, kSaveShowerTree, tca::Trajectory::MCSMom, tca::ShowerTreeVars::MCSMom, tca::TCConfig::modes, tca::ShowerTreeVars::nPlanes, tca::TCSlice::nPlanes, tca::ShowerTreeVars::nStages, geo::PlaneID::Plane, tca::ShowerTreeVars::PlaneNum, tca::TrajPoint::Pos, tca::Trajectory::Pts, tca::ShowerTreeVars::ShowerID, tca::ShowerTreeVars::StageNum, stv, tcc, tca::ShowerTreeVars::TjID, tca::TCConfig::unitsPerTick, and tca::Trajectory::VtxID.

Referenced by SaveTjInfo().

131  {
132  if(!tcc.modes[kSaveShowerTree]) return;
133 
134  TrajPoint& beginPoint = tj.Pts[tj.EndPt[0]];
135  TrajPoint& endPoint = tj.Pts[tj.EndPt[1]];
136 
137  stv.BeginWir.push_back(std::nearbyint(beginPoint.Pos[0]));
138  stv.BeginTim.push_back(std::nearbyint(beginPoint.Pos[1]/tcc.unitsPerTick));
139  stv.BeginAng.push_back(beginPoint.Ang);
140  stv.BeginChg.push_back(beginPoint.Chg);
141  stv.BeginVtx.push_back(tj.VtxID[0]);
142 
143  stv.EndWir.push_back(std::nearbyint(endPoint.Pos[0]));
144  stv.EndTim.push_back(std::nearbyint(endPoint.Pos[1]/tcc.unitsPerTick));
145  stv.EndAng.push_back(endPoint.Ang);
146  stv.EndChg.push_back(endPoint.Chg);
147  stv.EndVtx.push_back(tj.VtxID[1]);
148 
149  stv.MCSMom.push_back(tj.MCSMom);
150  stv.TjID.push_back(tj.ID);
151  stv.IsShowerTj.push_back(-1);
152 
153  stv.ShowerID.push_back(-1);
154  stv.IsShowerParent.push_back(-1);
155  stv.StageNum.push_back(stageNum);
156  stv.nStages = stageNum;
157  geo::PlaneID iPlnID = DecodeCTP(tj.CTP);
158  stv.PlaneNum.push_back(iPlnID.Plane);
159 
160  stv.nPlanes = slc.nPlanes;
161 
162  } // SaveTjInfoStuff
std::vector< int > IsShowerParent
Definition: DataStructs.h:323
std::vector< float > EndWir
Definition: DataStructs.h:310
std::vector< float > EndAng
Definition: DataStructs.h:312
std::vector< float > BeginTim
Definition: DataStructs.h:306
TCConfig tcc
Definition: DataStructs.cxx:6
std::vector< float > BeginAng
Definition: DataStructs.h:307
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
std::vector< float > EndTim
Definition: DataStructs.h:311
std::vector< int > ShowerID
Definition: DataStructs.h:322
ShowerTreeVars stv
Definition: DataStructs.cxx:8
save shower tree
Definition: DataStructs.h:456
std::vector< int > TjID
Definition: DataStructs.h:320
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
std::vector< short > BeginVtx
Definition: DataStructs.h:309
std::vector< short > EndVtx
Definition: DataStructs.h:314
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
std::vector< float > BeginChg
Definition: DataStructs.h:308
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
std::vector< short > MCSMom
Definition: DataStructs.h:316
std::vector< int > StageNum
Definition: DataStructs.h:324
unsigned short nPlanes
Definition: DataStructs.h:334
std::vector< float > BeginWir
Definition: DataStructs.h:305
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< float > EndChg
Definition: DataStructs.h:313
std::vector< int > IsShowerTj
Definition: DataStructs.h:321
std::vector< short > PlaneNum
Definition: DataStructs.h:318
void tca::ScoreVertices ( TCSlice slc)

Definition at line 2391 of file TCVertex.cxx.

References kHaloTj, kHiVx3Score, kKilled, kTjHiVx3Score, SetVx2Score(), SetVx3Score(), tca::TCSlice::tjs, tca::TCSlice::vtx3s, and tca::TCSlice::vtxs.

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

2392  {
2393  // reset all 3D vertex, 2D vertex and Tj high-score vertex bits in tpcid
2394 
2395  // reset the 2D vertex status bits
2396  for(auto& vx : slc.vtxs) {
2397  if(vx.ID == 0) continue;
2398  vx.Stat[kHiVx3Score] = false;
2399  } // vx
2400  // and the tj bits
2401  for(auto& tj : slc.tjs) {
2402  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
2403  tj.AlgMod[kTjHiVx3Score] = false;
2404  } // tj
2405  // Score the 2D vertices
2406  for(auto& vx : slc.vtxs) {
2407  if(vx.ID == 0) continue;
2408  SetVx2Score(slc, vx);
2409  } // vx
2410  // Score the 3D vertices
2411  for(auto& vx3 : slc.vtx3s) {
2412  if(vx3.ID == 0) continue;
2413  SetVx3Score(slc, vx3);
2414  } // vx3
2415  } // ScoreVertices
matched to a high-score 3D vertex
Definition: DataStructs.h:76
void SetVx3Score(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2483
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2513
void tca::SetAngleCode ( TrajPoint tp)

Definition at line 722 of file Utils.cxx.

References tca::TrajPoint::Ang, tca::TrajPoint::AngleCode, AngleRange(), tca::TCConfig::angleRanges, and tcc.

Referenced by FitTraj(), MakeJunkTraj(), StartTraj(), and UpdateTraj().

723  {
724  unsigned short ar = AngleRange(tp.Ang);
725  if(ar == tcc.angleRanges.size() - 1) {
726  // Very large angle
727  tp.AngleCode = 2;
728  } else if(tcc.angleRanges.size() > 2 && ar == tcc.angleRanges.size() - 2) {
729  // Large angle
730  tp.AngleCode = 1;
731  } else {
732  // Small angle
733  tp.AngleCode = 0;
734  }
735 
736  } // SetAngleCode
TCConfig tcc
Definition: DataStructs.cxx:6
std::vector< float > angleRanges
list of max angles for each angle range
Definition: DataStructs.h:486
unsigned short AngleRange(float angle)
Definition: Utils.cxx:739
template<typename T >
std::vector< T > tca::SetDifference ( const std::vector< T > &  set1,
const std::vector< T > &  set2 
)

Definition at line 253 of file Utils.h.

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

254  {
255  // returns the elements of set1 and set2 that are different
256  std::vector<T> different;
257  if(set1.empty() && set2.empty()) return different;
258  if(!set1.empty() && set2.empty()) return set1;
259  if(set1.empty() && !set2.empty()) return set2;
260  for(auto element1 : set1) {
261  // check for a common element
262  if(std::find(set2.begin(), set2.end(), element1) != set2.end()) continue;
263  // check for a duplicate
264  if(std::find(different.begin(), different.end(), element1) != different.end()) continue;
265  different.push_back(element1);
266  } // element1
267  for(auto element2 : set2) {
268  // check for a common element
269  if(std::find(set1.begin(), set1.end(), element2) != set1.end()) continue;
270  // check for a duplicate
271  if(std::find(different.begin(), different.end(), element2) != different.end()) continue;
272  different.push_back(element2);
273  } // element1
274  return different;
275  } // SetDifference
void tca::SetEndPoints ( Trajectory tj)

Definition at line 2864 of file Utils.cxx.

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

Referenced by AddHits(), AddLAHits(), CheckHiMultEndHits(), CheckHiMultUnusedHits(), CheckTraj(), ChkChgAsymmetry(), ChkStopEndPts(), DotProd(), FindSoftKink(), FixTrajBegin(), Forecast(), IsGhost(), MakeJunkTraj(), MaskedHitsOK(), MaskTrajEndPoints(), MergeAndStore(), MergePFPTjs(), ReversePropagate(), ReverseTraj(), SplitHiChgHits(), SplitTraj(), StepAway(), StoreTraj(), TrimEndPts(), UpdateTraj(), and VtxHitsSwap().

2865  {
2866  // Find the first (last) TPs, EndPt[0] (EndPt[1], that have charge
2867 
2868  // don't mess with showerTjs or halo tjs
2869  if(tj.AlgMod[kShowerTj] || tj.AlgMod[kHaloTj]) return;
2870 
2871  tj.EndPt[0] = 0; tj.EndPt[1] = 0;
2872  if(tj.Pts.size() == 0) return;
2873 
2874  // check the end point pointers
2875  for(unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) {
2876  if(tj.Pts[ipt].Chg != 0) {
2877  tj.EndPt[0] = ipt;
2878  break;
2879  }
2880  }
2881  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
2882  unsigned short ipt = tj.Pts.size() - 1 - ii;
2883  if(tj.Pts[ipt].Chg != 0) {
2884  tj.EndPt[1] = ipt;
2885  break;
2886  }
2887  }
2888  } // SetEndPoints
void tca::SetHighScoreBits ( TCSlice slc,
Vtx3Store vx3 
)

Definition at line 2436 of file TCVertex.cxx.

References evd::details::end(), GetVtxTjIDs(), tca::VtxStore::ID, tca::Vtx3Store::ID, kHiVx3Score, kTjHiVx3Score, tca::TCSlice::nPlanes, tca::VtxStore::Stat, tca::TCSlice::tjs, tmp, tca::TCSlice::vtxs, and tca::Vtx3Store::Vx2ID.

Referenced by SetVx3Score().

2437  {
2438  // Sets the tj and 2D vertex score bits to true
2439 
2440  if(vx3.ID == 0) return;
2441 
2442  for(unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
2443  if(vx3.Vx2ID[ipl] <= 0) continue;
2444  VtxStore& vx2 = slc.vtxs[vx3.Vx2ID[ipl] - 1];
2445  vx2.Stat[kHiVx3Score] = false;
2446  // transfer this to all attached tjs and vertices attached to those tjs
2447  std::vector<int> tjlist = GetVtxTjIDs(slc, vx2);
2448  std::vector<int> vxlist;
2449  while(true) {
2450  // tag Tjs and make a list of attached vertices whose high-score
2451  // bit needs to be set
2452  vxlist.clear();
2453  for(auto tjid : tjlist) {
2454  auto& tj = slc.tjs[tjid - 1];
2455  tj.AlgMod[kTjHiVx3Score] = true;
2456  for(unsigned short end = 0; end < 2; ++end) {
2457  if(tj.VtxID[end] == 0) continue;
2458  auto& vx2 = slc.vtxs[tj.VtxID[end] - 1];
2459  if(vx2.Stat[kHiVx3Score]) continue;
2460  vx2.Stat[kHiVx3Score] = true;
2461  vxlist.push_back(vx2.ID);
2462  } // end
2463  } // tjid
2464 
2465  if(vxlist.empty()) break;
2466  // re-build tjlist using vxlist
2467  std::vector<int> newtjlist;
2468  for(auto vxid : vxlist) {
2469  auto& vx2 = slc.vtxs[vxid - 1];
2470  auto tmp = GetVtxTjIDs(slc, vx2);
2471  for(auto tjid : tmp) {
2472  if(std::find(tjlist.begin(), tjlist.end(), tjid) == tjlist.end()) newtjlist.push_back(tjid);
2473  } // tjid
2474  } // vxid
2475  if(newtjlist.empty()) break;
2476  tjlist = newtjlist;
2477  } // true
2478  } // ipl
2479 
2480  } // SetHighScoreBits
matched to a high-score 3D vertex
Definition: DataStructs.h:76
Float_t tmp
Definition: plot.C:37
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:3243
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 231 of file Utils.h.

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

232  {
233  // returns a vector containing the elements of set1 and set2 that are common. This function
234  // is a replacement for std::set_intersection which fails in the following situation:
235  // set1 = {11 12 17 18} and set2 = {6 12 18}
236  // There is no requirement that the elements be sorted, unlike std::set_intersection
237  std::vector<T> shared;
238 
239  if(set1.empty()) return shared;
240  if(set2.empty()) return shared;
241  for(auto element1 : set1) {
242  // check for a common element
243  if(std::find(set2.begin(), set2.end(), element1) == set2.end()) continue;
244  // check for a duplicate
245  if(std::find(shared.begin(), shared.end(), element1) != shared.end()) continue;
246  shared.push_back(element1);
247  } // element1
248  return shared;
249  } // SetIntersection
bool tca::SetMag ( Vector3_t v1,
double  mag 
)

Definition at line 1670 of file PFPUtils.cxx.

References den.

Referenced by DotProd(), FindAlongTrans(), Fit3D(), FollowTp3s(), PointDirection(), and UpdateShower().

1671  {
1672  double den = v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2];
1673  if(den == 0) return false;
1674  den = sqrt(den);
1675 
1676  v1[0] *= mag / den;
1677  v1[1] *= mag / den;
1678  v1[2] *= mag / den;
1679  return true;
1680  } // SetMag
Float_t den
Definition: plot.C:37
bool tca::SetMag ( Vector2_t v1,
double  mag 
)

Definition at line 2805 of file Utils.cxx.

References den.

Referenced by FindAlongTrans().

2806  {
2807  double den = v1[0] * v1[0] + v1[1] * v1[1];
2808  if(den == 0) return false;
2809  den = sqrt(den);
2810 
2811  v1[0] *= mag / den;
2812  v1[1] *= mag / den;
2813  return true;
2814  } // SetMag
Float_t den
Definition: plot.C:37
bool tca::SetParent ( std::string  inFcnLabel,
TCSlice slc,
PFPStruct pfp,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 1919 of file TCShower.cxx.

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

Referenced by FindParent().

1920  {
1921  // set the pfp as the parent of ss3. The calling function should do the error recovery
1922  if(pfp.ID == 0 || ss3.ID == 0) return false;
1923  if(ss3.CotIDs.empty()) return false;
1924 
1925  std::string fcnLabel = inFcnLabel + ".SP";
1926 
1927  for(auto cid : ss3.CotIDs) {
1928  auto& ss = slc.cots[cid - 1];
1929  auto& stj = slc.tjs[ss.ShowerTjID - 1];
1930  stj.VtxID[0] = 0;
1931  if(ss.ParentID > 0) {
1932  auto& oldParent = slc.tjs[ss.ParentID - 1];
1933  oldParent.AlgMod[kShwrParent] = false;
1934  ss.ParentID = 0;
1935  ss.ParentFOM = 10;
1936  } // remove old parents
1937  // add new parents
1938  for(auto tjid : pfp.TjIDs) {
1939  auto& tj = slc.tjs[tjid - 1];
1940  if(tj.CTP != ss.CTP) continue;
1941  if(std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tjid) == ss.TjIDs.end()) {
1942  // Add the tj but don't update yet
1943  if(!AddTj(fcnLabel, slc, tjid, ss, false, prt)) return false;
1944  } // parent not in ss
1945  // Don't define it to be the parent if it is short and the pfp projection in this plane is low
1946  unsigned short pEnd = FarEnd(slc, pfp, ss3.ChgPos);
1947  auto tp = MakeBareTP(slc, pfp.XYZ[0], pfp.Dir[pEnd], tj.CTP);
1948  unsigned short npts = tj.EndPt[1] - tj.EndPt[0] + 1;
1949  if(tp.Delta > 0.5 || npts > 20) {
1950  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" parent P"<<pfp.ID<<" -> T"<<tjid<<" -> 2S"<<ss.ID<<" parent";
1951  } else {
1952  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" parent P"<<pfp.ID<<" -> T"<<tjid<<" low projection in plane "<<tp.Delta<<". Not a parent";
1953  continue;
1954  }
1955  ss.ParentID = tjid;
1956  ss.NeedsUpdate = true;
1957  // set the ss start vertex
1958  if(ss3.Vx3ID > 0) {
1959  auto& vx3 = slc.vtx3s[ss3.Vx3ID - 1];
1960  auto v2list = GetAssns(slc, "3V", vx3.ID, "2V");
1961  for(unsigned short end = 0; end < 2; ++end) {
1962  if(tj.VtxID[end] <= 0) continue;
1963  if(std::find(v2list.begin(), v2list.end(), tj.VtxID[end]) != v2list.end()) stj.VtxID[0] = tj.VtxID[end];
1964  } // end
1965  } // ss3.Vx3ID > 0
1966  // and update
1967  if(!UpdateShower(fcnLabel, slc, ss, prt)) return false;
1968  } // tjid
1969  } // cid
1970  ss3.ParentID = pfp.ID;
1971 
1972  unsigned short pEnd = FarEnd(slc, pfp, ss3.ChgPos);
1973  ss3.Vx3ID = pfp.Vx3ID[pEnd];
1974  float fom3D = ParentFOM(fcnLabel, slc, pfp, pEnd, ss3, prt);
1975  for(auto cid : ss3.CotIDs) slc.cots[cid - 1].ParentFOM = fom3D;
1976 
1977  return true;
1978  } // SetParent
bool AddTj(std::string inFcnLabel, TCSlice &slc, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1552
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4279
Float_t ss
Definition: plot.C:23
TrajPoint MakeBareTP(TCSlice &slc, Point3_t &pos, Vector3_t &dir, CTP_t inCTP)
Definition: Utils.cxx:3523
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1230
float ParentFOM(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, unsigned short &tjEnd, ShowerStruct &ss, float &tp1Sep, float &vx2Score, bool prt)
Definition: TCShower.cxx:2211
unsigned short FarEnd(TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3032
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void tca::SetPDGCode ( TCSlice slc,
unsigned short  itj,
bool  tjDone 
)

Definition at line 3795 of file Utils.cxx.

References SetPDGCode(), and tca::TCSlice::tjs.

Referenced by CompleteIncomplete3DVertices(), DotProd(), FindHammerVertices(), FindHammerVertices2(), MergePFPTjs(), and StepAway().

3796  {
3797  if(itj > slc.tjs.size() - 1) return;
3798  SetPDGCode(slc, slc.tjs[itj], tjDone);
3799  }
void SetPDGCode(TCSlice &slc, Trajectory &tj, bool tjDone)
Definition: Utils.cxx:3802
void tca::SetPDGCode ( TCSlice slc,
Trajectory tj,
bool  tjDone 
)

Definition at line 3802 of file Utils.cxx.

References tca::Trajectory::ID, kStiffEl, kStiffMu, tca::Trajectory::MCSMom, tca::TCConfig::muonTag, NumPtsWithCharge(), tca::Trajectory::PDGCode, tca::Trajectory::Strategy, and tcc.

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

3803  {
3804  // Sets the PDG code for the supplied trajectory. Note that the existing
3805  // PDG code is left unchanged if these cuts are not met
3806 
3807  short npwc = NumPtsWithCharge(slc, tj, false);
3808  if(npwc < 6) {
3809  tj.PDGCode = 0;
3810  return;
3811  }
3812 
3813  if(tj.Strategy[kStiffEl]) {
3814  tj.PDGCode = 111;
3815  return;
3816  }
3817  if(tj.Strategy[kStiffMu]) {
3818  tj.PDGCode = 13;
3819  return;
3820  }
3821 
3822 // tj.PDGCode = 0;
3823  if(tcc.muonTag[0] <= 0) return;
3824  // Special handling of very long straight trajectories, e.g. uB cosmic rays
3825  bool isAMuon = (npwc > (unsigned short)tcc.muonTag[0] && tj.MCSMom > tcc.muonTag[1]);
3826  // anything really really long must be a muon
3827  if(npwc > 500) isAMuon = true;
3828  if(tj.PDGCode != 0 && tj.PDGCode != 13 && isAMuon) {
3829  std::cout<<"T"<<tj.ID<<" changing PDGCode from "<<tj.PDGCode<<" to 13. Is this wise?\n";
3830  }
3831  if(isAMuon) tj.PDGCode = 13;
3832 
3833  } // SetPDGCode
TCConfig tcc
Definition: DataStructs.cxx:6
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:1871
std::vector< short > muonTag
min length and min MCSMom for a muon tag
Definition: DataStructs.h:471
use the stiff electron strategy
Definition: DataStructs.h:418
use the stiff muon strategy
Definition: DataStructs.h:419
bool tca::SetStart ( TCSlice slc,
PFPStruct pfp,
bool  prt 
)

Definition at line 351 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().

352  {
353  // Analyzes the space point collection and the Tjs in the pfp to find a new start
354  // position. The Tp3s found in FindCompleteness are ordered by increasing X. The general direction
355  // pfp.Dir[0] and the average position of all points in Tp3s was stored in pfp.XYZ[0]. This function
356  // rotates each tp3 into this coordinate system to determine (along, trans) for each point. The min (max)
357  // value of along defines the start (end) of the trajectory.
358 
359  if(pfp.ID <= 0 || pfp.TjIDs.empty()) return false;
360  if(pfp.Tp3s.size() < 2) return false;
361 
362  // The projection along the general direction relative to the average position was found
363  // in FillCompleteness. Now
364  float minAlong = 1E6;
365  unsigned short minPt = 0;
366  float maxAlong = -1E6;
367  unsigned short maxPt = 0;
368  std::vector<SortEntry> sortVec(pfp.Tp3s.size());
369  for(unsigned short ipt = 0; ipt < pfp.Tp3s.size(); ++ipt) {
370  auto& tp3 = pfp.Tp3s[ipt];
371  sortVec[ipt].index = ipt;
372  sortVec[ipt].val = tp3.AlongTrans[0];
373  // find the min (max)
374  if(tp3.AlongTrans[0] < minAlong) {
375  minAlong = tp3.AlongTrans[0];
376  minPt = ipt;
377  }
378  if(tp3.AlongTrans[0] > maxAlong) {
379  maxAlong = tp3.AlongTrans[0];
380  maxPt = ipt;
381  }
382  } // tp3
383 
384  pfp.XYZ[0] = pfp.Tp3s[minPt].Pos;
385  pfp.XYZ[1] = pfp.Tp3s[maxPt].Pos;
386 
387  if(prt) {
388  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];
389  PrintTp3("minPt", slc, pfp.Tp3s[minPt]);
390  PrintTp3("maxPt", slc, pfp.Tp3s[maxPt]);
391  }
392 
393  std::sort(sortVec.begin(), sortVec.end(), valIncreasings);
394  // put them into order
395  std::vector<TrajPoint3> temp;
396  for(unsigned short ii = 0; ii < sortVec.size(); ++ii) temp.push_back(pfp.Tp3s[sortVec[ii].index]);
397  pfp.Tp3s = temp;
398 // PrintTp3s("SNS", slc, pfp, -1);
399 
400  return true;
401 
402  } // SetStart
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void PrintTp3(std::string someText, TCSlice &slc, const TrajPoint3 &tp3)
Definition: PFPUtils.cxx:3041
bool valIncreasings(SortEntry c1, SortEntry c2)
Definition: PFPUtils.cxx:13
void tca::SetStrategy ( TCSlice slc,
Trajectory tj 
)

Definition at line 303 of file StepUtils.cxx.

References ChgSlope(), tca::TCConfig::dbgStp, tca::Trajectory::EndPt, kSlowing, kStiffEl, kStiffMu, tca::Trajectory::MCSMom, NumPtsWithCharge(), tca::Trajectory::Pts, tca::Trajectory::StartEnd, tca::Trajectory::Strategy, tcc, and tjfs.

Referenced by StepAway().

304  {
305  // Determine if the tracking strategy is appropriate and make some tweaks if it isn't
306  if(tjfs.empty()) return;
307  // analyze the last forecast
308  auto& tjf = tjfs[tjfs.size() - 1];
309 
310  auto& lastTP = tj.Pts[tj.EndPt[1]];
311  // Stay in Slowing strategy if we are in it and reduce the number of points fit further
312  if(tj.Strategy[kSlowing]) {
313  lastTP.NTPsFit = 5;
314  return;
315  }
316 
317  float npwc = NumPtsWithCharge(slc, tj, false);
318  bool tkLike = (tjf.outlook < 1.5);
319  // A showering-electron-like trajectory
320  bool shLike = (tjf.outlook > 2 && tjf.chgSlope > 0);
321  // This cut picks up a 240 MeV electron
322  if(!shLike) shLike = tjf.showerLikeFraction > 0.4;
323  float momRat = 0;
324  if(tj.MCSMom > 0) momRat = (float)tjf.MCSMom / (float)tj.MCSMom;
325  if(tcc.dbgStp) {
326  mf::LogVerbatim myprt("TC");
327  myprt<<"SetStrategy: npwc "<<npwc<<" outlook "<<tjf.outlook;
328  myprt<<" tj MCSMom "<<tj.MCSMom<<" forecast MCSMom "<<tjf.MCSMom;
329  myprt<<" momRat "<<std::fixed<<std::setprecision(2)<<momRat;
330  myprt<<" tkLike? "<<tkLike<<" showerLike? "<<shLike;
331  myprt<<" leavesBeforeEnd? "<<tjf.leavesBeforeEnd<<" endBraggPeak? "<<tjf.endBraggPeak;
332  }
333  if(tjf.outlook < 0) return;
334  // Look for a long clean muon in the forecast
335  if(tkLike && tj.MCSMom > 200 && tjf.MCSMom > 800 && tjf.nextForecastUpdate > 50 && tjf.chgFitChiDOF < 10) {
336  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"SetStrategy: Use the StiffMu strategy";
337  tj.Strategy.reset();
338  tj.Strategy[kStiffMu] = true;
339  return;
340  } // StiffMu
341  bool notStiff = (!tj.Strategy[kStiffEl] && !tj.Strategy[kStiffMu]);
342  if(notStiff && !shLike && tj.MCSMom < 100 && tjf.MCSMom < 100) {
343  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"SetStrategy: Low MCSMom. Use the Slowing Tj strategy";
344  tj.Strategy.reset();
345  tj.Strategy[kSlowing] = true;
346  lastTP.NTPsFit = 5;
347  return;
348  } // tracklike with > 1 forecast
349  if(notStiff && tkLike && tj.MCSMom < 200 && momRat < 0.7) {
350  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"SetStrategy: Low MCSMom & low momRat. Use the Slowing Tj strategy";
351  tj.Strategy.reset();
352  tj.Strategy[kSlowing] = true;
353  lastTP.NTPsFit = 5;
354  return;
355  } // tracklike with > 1 forecast
356  if(!tjf.leavesBeforeEnd && tjf.endBraggPeak) {
357  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"SetStrategy: Found a Bragg peak. Use the Slowing Tj strategy";
358  tj.Strategy.reset();
359  tj.Strategy[kSlowing] = true;
360  lastTP.NTPsFit = 5;
361  return;
362  } // tracklike with Bragg peak
363  if(npwc > 100 && tkLike && tjf.leavesBeforeEnd) {
364  // A long track-like trajectory that has many points fit and the outlook is track-like and
365  // it leaves the forecast polygon. Don't change the strategy but decrease the number of points fit
366  lastTP.NTPsFit /= 2;
367  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"SetStrategy: Long track-like wandered out of forecast envelope. Reduce NTPsFit to "<<lastTP.NTPsFit;
368  return;
369  }
370  // a track-like trajectory that has high MCSMom in the forecast and hits a shower
371  if(tkLike && tjf.MCSMom > 600 && (tjf.foundShower || tjf.chgFitChiDOF > 20)) {
372  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"SetStrategy: high MCSMom "<<tjf.MCSMom<<" and a shower ahead. Use the StiffEl strategy";
373  tj.Strategy.reset();
374  tj.Strategy[kStiffEl] = true;
375  // we think we know the direction (towards the shower) so startEnd is 0
376  tj.StartEnd = 0;
377  return;
378  } // Stiff electron
379  if(shLike) {
380  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"SetStrategy: Inside a shower. Use the StiffEl strategy";
381  tj.Strategy.reset();
382  tj.Strategy[kStiffEl] = true;
383  // we think we know the direction (towards the shower) so startEnd is 0
384  tj.StartEnd = 0;
385  return;
386  }
387  // A curvy trajectory (not nessecarily track-like) with a consistent increase in charge
388  if(tkLike && tjf.MCSMom < 100 && !tjf.leavesBeforeEnd) {
389  // find the charge slope of the trajectory
390  float chgSlope, chgSlopeErr, chiDOF;
391  ChgSlope(slc, tj, chgSlope, chgSlopeErr, chiDOF);
392  // a significant increase in the charge in the reconstructed tj, which continues in the
393  // forecase polygon. TODO: use chgSlopeErr?
394  if(chgSlope > 3 * chgSlopeErr && (tjf.chgSlope > 3 * tjf.chgSlopeErr)) {
395  tj.Strategy.reset();
396  tj.Strategy[kSlowing] = true;
397  lastTP.NTPsFit = 5;
398  }
399  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"SetStrategy: Curvy? tj chgSlope "<<chgSlope<<" +/ "<<chgSlopeErr<<" forecast chgSlope "<<tjf.chgSlope<<" +/- "<<tjf.chgSlopeErr<<" Slowing? "<<tj.Strategy[kSlowing];
400  } // Slowing
401  } // SetStrategy
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
use the slowing-down strategy
Definition: DataStructs.h:420
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
std::vector< TjForecast > tjfs
Definition: DataStructs.cxx:7
void ChgSlope(TCSlice &slc, Trajectory &tj, float &slope, float &slopeErr, float &chiDOF)
Definition: Utils.cxx:1288
use the stiff electron strategy
Definition: DataStructs.h:418
use the stiff muon strategy
Definition: DataStructs.h:419
void tca::SetVx2Score ( TCSlice slc)

Definition at line 2504 of file TCVertex.cxx.

References tca::TCSlice::vtxs.

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

2505  {
2506  // A version that sets the score of the last added vertex
2507  if(slc.vtxs.empty()) return;
2508  auto& vx2 = slc.vtxs[slc.vtxs.size() - 1];
2509  SetVx2Score(slc, vx2);
2510  } // SetVx2Score
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2513
void tca::SetVx2Score ( TCSlice slc,
VtxStore vx2 
)

Definition at line 2513 of file TCVertex.cxx.

References tca::Trajectory::AlgMod, ChgFracNearPos(), tca::Trajectory::ChgRMS, tca::VtxStore::CTP, tca::TCConfig::dbg2V, tca::TCConfig::dbgSlc, debug, DecodeCTP(), DeltaAngle(), tca::Trajectory::EndPt, GetVtxTjIDs(), tca::VtxStore::ID, kBragg, kJunkTj, kNewVtxCuts, kShowerLike, kShowerTj, tca::Trajectory::MCSMom, tca::Trajectory::PDGCode, tca::DebugStuff::Plane, geo::PlaneID::Plane, tca::VtxStore::Pos, tca::VtxStore::PosErr, tca::Trajectory::Pts, tca::VtxStore::Score, tca::Trajectory::StopFlag, tcc, tca::VtxStore::TjChgFrac, tca::TCSlice::tjs, tca::VtxStore::Topo, tca::TCConfig::useAlg, tca::TCConfig::vtx2DCuts, tca::TCSlice::vtx3s, tca::Trajectory::VtxID, tca::TCConfig::vtxScoreWeights, and tca::VtxStore::Vx3ID.

2514  {
2515  // Calculate the 2D vertex score
2516  if(vx2.ID == 0) return;
2517 
2518  // Don't score vertices from CheckTrajBeginChg, MakeJunkVertices or Neutral vertices. Set to the minimum
2519  if(vx2.Topo == 8 || vx2.Topo == 9 || vx2.Topo == 11) {
2520  vx2.Score = tcc.vtx2DCuts[7] + 0.1;
2521  auto vtxTjID = GetVtxTjIDs(slc, vx2);
2522  vx2.TjChgFrac = ChgFracNearPos(slc, vx2.Pos, vtxTjID);
2523  return;
2524  }
2525 
2526  // Cuts on Tjs attached to vertices
2527  constexpr float maxChgRMS = 0.25;
2528  constexpr float momBin = 50;
2529 
2530  vx2.Score = -1000;
2531  vx2.TjChgFrac = 0;
2532  if(vx2.ID == 0) return;
2533  if(tcc.vtxScoreWeights.size() < 4) return;
2534 
2535  auto vtxTjIDs = GetVtxTjIDs(slc, vx2);
2536  if(vtxTjIDs.empty()) return;
2537 
2538  // Vertex position error
2539  float vpeScore = -tcc.vtxScoreWeights[0] * (vx2.PosErr[0] + vx2.PosErr[1]);
2540 
2541  unsigned short m3Dcnt = 0;
2542  if(vx2.Vx3ID > 0) {
2543  m3Dcnt = 1;
2544  // Add another if the 3D vertex is complete
2545  unsigned short ivx3 = vx2.Vx3ID - 1;
2546  if(slc.vtx3s[ivx3].Wire < 0) m3Dcnt = 2;
2547  }
2548  float m3DScore = tcc.vtxScoreWeights[1] * m3Dcnt;
2549 
2550  vx2.TjChgFrac = ChgFracNearPos(slc, vx2.Pos, vtxTjIDs);
2551  float cfScore = tcc.vtxScoreWeights[2] * vx2.TjChgFrac;
2552 
2553  // Define a weight for each Tj
2554  std::vector<int> tjids;
2555  std::vector<float> tjwts;
2556  unsigned short cnt13 = 0;
2557  for(auto tjid : vtxTjIDs) {
2558  Trajectory& tj = slc.tjs[tjid - 1];
2559  // Feb 22 Ignore short Tjs and junk tjs
2560  if(tj.AlgMod[kJunkTj]) continue;
2561  unsigned short lenth = tj.EndPt[1] - tj.EndPt[0] + 1;
2562  if(lenth < 3) continue;
2563  float wght = (float)tj.MCSMom / momBin;
2564  if(!tcc.useAlg[kNewVtxCuts] && wght > 10) wght = 10;
2565  // weight by the first tagged muon
2566  if(tj.PDGCode == 13) {
2567  ++cnt13;
2568  if(tcc.useAlg[kNewVtxCuts] && cnt13 == 1) wght *= 2;
2569  }
2570  // weight by charge rms
2571  if(tj.ChgRMS < maxChgRMS) ++wght;
2572  // Shower Tj
2573  if(tj.AlgMod[kShowerTj]) ++wght;
2574  // ShowerLike
2575  if(tj.AlgMod[kShowerLike]) --wght;
2576  tjids.push_back(tjid);
2577  tjwts.push_back(wght);
2578  } // tjid
2579 
2580  if(tjids.empty()) return;
2581 
2582  float tjScore = 0;
2583  float sum = 0;
2584  float cnt = 0;
2585  for(unsigned short it1 = 0; it1 < tjids.size() - 1; ++it1) {
2586  Trajectory& tj1 = slc.tjs[tjids[it1] - 1];
2587  float wght1 = tjwts[it1];
2588  // the end that has a vertex
2589  unsigned short end1 = 0;
2590  if(tj1.VtxID[1] == vx2.ID) end1 = 1;
2591  unsigned short endPt1 = tj1.EndPt[end1];
2592  // bump up the weight if there is a Bragg peak at the other end
2593  unsigned short oend1 = 1 - end1;
2594  if(tj1.StopFlag[oend1][kBragg]) ++wght1;
2595  float ang1 = tj1.Pts[endPt1].Ang;
2596  float ang1Err2 = tj1.Pts[endPt1].AngErr * tj1.Pts[endPt1].AngErr;
2597  for(unsigned short it2 = it1 + 1; it2 < tjids.size(); ++it2) {
2598  Trajectory& tj2 = slc.tjs[tjids[it2] - 1];
2599  float wght2 = tjwts[it2];
2600  unsigned end2 = 0;
2601  if(tj2.VtxID[1] == vx2.ID) end2 = 1;
2602  // bump up the weight if there is a Bragg peak at the other end
2603  unsigned short oend2 = 1 - end2;
2604  if(tj2.StopFlag[oend2][kBragg]) ++wght2;
2605  unsigned short endPt2 = tj2.EndPt[end2];
2606  float ang2 = tj2.Pts[endPt2].Ang;
2607  float ang2Err2 = tj2.Pts[endPt2].AngErr * tj2.Pts[endPt2].AngErr;
2608  float dang = DeltaAngle(ang1, ang2);
2609  float dangErr = 0.5 * sqrt(ang1Err2 + ang2Err2);
2610  if((dang / dangErr) > 3 && wght1 > 0 && wght2 > 0) {
2611  sum += wght1 + wght2;
2612  ++cnt;
2613  }
2614  } // it2
2615  } // it1
2616  if(cnt > 0) {
2617  sum /= cnt;
2618  tjScore = tcc.vtxScoreWeights[3] * sum;
2619  }
2620  vx2.Score = vpeScore + m3DScore + cfScore + tjScore;
2621  if(tcc.dbg2V && tcc.dbgSlc && (int)DecodeCTP(vx2.CTP).Plane == debug.Plane) {
2622  // last call after vertices have been matched to the truth. Use to optimize vtxScoreWeights using
2623  // an ntuple
2624  mf::LogVerbatim myprt("TC");
2625  myprt<<" SVx2W 2v"<<vx2.ID;
2626 /*
2627  myprt<<" m3Dcnt "<<m3Dcnt;
2628  myprt<<" PosErr "<<std::fixed<<std::setprecision(2)<<(vx2.PosErr[0] + vx2.PosErr[1]);
2629  myprt<<" TjChgFrac "<<std::fixed<<std::setprecision(3)<<vx2.TjChgFrac;
2630  myprt<<" sum "<<std::fixed<<std::setprecision(1)<<sum;
2631  myprt<<" cnt "<<(int)cnt;
2632 */
2633  myprt<<std::fixed<<std::setprecision(1);
2634  myprt<<" vpeScore "<<vpeScore<<" m3DScore "<<m3DScore;
2635  myprt<<" cfScore "<<cfScore<<" tjScore "<<tjScore;
2636  myprt<<" Score "<<vx2.Score;
2637  }
2638  } // SetVx2Score
TCConfig tcc
Definition: DataStructs.cxx:6
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1636
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:507
DebugStuff debug
Definition: DebugStruct.cxx:4
bool dbg2V
debug 2D vertex finding
Definition: DataStructs.h:510
int Plane
Select plane.
Definition: DebugStruct.h:21
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
float ChgFracNearPos(TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2698
std::vector< float > vtxScoreWeights
Definition: DataStructs.h:468
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:3243
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:466
void tca::SetVx3Score ( TCSlice slc,
Vtx3Store vx3 
)

Definition at line 2483 of file TCVertex.cxx.

References tca::Vtx3Store::ID, tca::TCSlice::nPlanes, tca::VtxStore::Score, tca::Vtx3Store::Score, SetHighScoreBits(), tcc, tca::TCConfig::vtx2DCuts, tca::TCSlice::vtxs, and tca::Vtx3Store::Vx2ID.

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

2484  {
2485  // Calculate the 3D vertex score and flag Tjs that are attached to high score vertices as defined
2486  // by Vertex2DCuts
2487 
2488  if(vx3.ID == 0) return;
2489 
2490  vx3.Score = 0;
2491  for(unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
2492  if(vx3.Vx2ID[ipl] <= 0) continue;
2493  VtxStore& vx2 = slc.vtxs[vx3.Vx2ID[ipl] - 1];
2494  vx3.Score += vx2.Score;
2495  } // ipl
2496  vx3.Score /= (float)slc.nPlanes;
2497  // don't allow it to get too small or negative
2498  if(vx3.Score < 0.001) vx3.Score = 0.001;
2499  if(vx3.Score > tcc.vtx2DCuts[7]) SetHighScoreBits(slc, vx3);
2500 
2501  } // SetVx3Score
TCConfig tcc
Definition: DataStructs.cxx:6
void SetHighScoreBits(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2436
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:466
bool tca::SharesHighScoreVx ( TCSlice slc,
const PFPStruct pfp,
const Trajectory tj 
)

Definition at line 1026 of file PFPUtils.cxx.

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

Referenced by DefinePFP(), and FindMissedTjsInTp3s().

1027  {
1028  // returns true if tj with tjID shares a high-score 3D vertex with any
1029  // tj in pfp.TjIDs
1030  for(unsigned short end = 0; end < 2; ++end) {
1031  if(tj.VtxID[end] == 0) continue;
1032  auto& vx2 = slc.vtxs[tj.VtxID[end] - 1];
1033  if(!vx2.Stat[kHiVx3Score]) continue;
1034  std::vector<int> vtjlist = GetVtxTjIDs(slc, vx2);
1035  auto shared = SetIntersection(vtjlist, pfp.TjIDs);
1036  if(!shared.empty()) return true;
1037  } // end
1038  return false;
1039  } // SharesHighScoreVx
matched to a high-score 3D vertex
Definition: DataStructs.h:76
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:231
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const VtxStore &vx2)
Definition: TCVertex.cxx:3226
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
double tca::ShowerEnergy ( const ShowerStruct3D ss3)

Definition at line 4369 of file TCShower.cxx.

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

Referenced by showerreco::ShowerCalo::~ShowerCalo().

4370  {
4371  if(ss3.ID == 0) return 0;
4372  if(ss3.Energy.empty()) return 0;
4373  double ave = 0;
4374  for(auto e : ss3.Energy) {
4375  ave += e;
4376  } // e
4377  ave /= ss3.Energy.size();
4378  return ave;
4379  } // ShowerEnergy
Float_t e
Definition: plot.C:34
float tca::ShowerEnergy ( TCSlice slc,
const std::vector< int >  tjIDs 
)

Definition at line 4382 of file TCShower.cxx.

References ChgToMeV(), and tca::TCSlice::tjs.

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

4383  {
4384  // Calculate energy using the total charge of all hits in each tj in the shower
4385  if(tjIDs.empty()) return 0;
4386  float sum = 0;
4387  for(auto tid : tjIDs) {
4388  auto& tj = slc.tjs[tid - 1];
4389  sum += tj.TotChg;
4390  } // tid
4391  return ChgToMeV(sum);
4392  } // ShowerEnergy
float ChgToMeV(float chg)
Definition: TCShower.cxx:4395
void tca::ShowerParams ( double  showerEnergy,
double &  shMaxAlong,
double &  along95 
)

Definition at line 2015 of file TCShower.cxx.

References scale.

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

2016  {
2017  // Returns summary properties of photon showers parameterized in the energy range 50 MeV < E_gamma < 1 GeV:
2018  // shMaxAlong = the longitudinal distance (cm) between the start of the shower and the center of charge
2019  // along95 = the longitudinal distance (cm) between the start of the shower and 95% energy containment
2020  // all units are in cm
2021  if(showerEnergy < 10) {
2022  shMaxAlong = 0;
2023  along95 = 0;
2024  return;
2025  }
2026 // shMaxAlong = 7.0 * log(showerEnergy / 15);
2027  shMaxAlong = 16 * log(showerEnergy / 15);
2028  // The 95% containment is reduced a bit at higher energy
2029  double scale = 2.75 - 9.29E-4 * showerEnergy;
2030  if(scale < 2) scale = 2;
2031  along95 = scale * shMaxAlong;
2032  } // ShowerParams
Double_t scale
Definition: plot.C:25
double tca::ShowerParamTransRMS ( double  showerEnergy,
double  along 
)

Definition at line 2035 of file TCShower.cxx.

References ShowerParams().

Referenced by InShowerProbTrans().

2036  {
2037  // returns the pareameterized width rms of a shower at along relative to the shower max
2038  double shMaxAlong, shE95Along;
2039  ShowerParams(showerEnergy, shMaxAlong, shE95Along);
2040  if(shMaxAlong <= 0) return 0;
2041  double tau = (along + shMaxAlong) / shMaxAlong;
2042  // The shower width is modeled as a simple cone that scales with tau
2043  double rms = -0.4 + 2.5 * tau;
2044  if(rms < 0.5) rms = 0.5;
2045  return rms;
2046  } // ShowerParamTransRMS
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
Definition: TCShower.cxx:2015
bool tca::SignalAtTp ( TCSlice slc,
TrajPoint const &  tp 
)
bool tca::SignalAtTp ( TCSlice slc,
const TrajPoint tp 
)

Definition at line 1814 of file Utils.cxx.

References tca::TCEvent::allHits, tca::TrajPoint::CTP, DecodeCTP(), tca::TrajPoint::Dir, evt, tca::TCConfig::maxPos1, tca::TCSlice::nWires, geo::PlaneID::Plane, tca::TrajPoint::Pos, tca::TCSlice::slHits, tcc, tca::TCConfig::unitsPerTick, and tca::TCSlice::wireHitRange.

Referenced by ChgFracBetween(), FindHammerVertices2(), FindXMatches(), SignalBetween(), and StepAway().

1815  {
1816  // returns true if there is a hit near tp.Pos
1817 
1818  if(tp.Pos[0] < -0.4) return false;
1819  unsigned int wire = std::nearbyint(tp.Pos[0]);
1820  geo::PlaneID planeID = DecodeCTP(tp.CTP);
1821  unsigned int ipl = planeID.Plane;
1822  if(wire >= slc.nWires[ipl]) return false;
1823  if(tp.Pos[1] > tcc.maxPos1[ipl]) return false;
1824  // Assume dead wires have a signal
1825  if(slc.wireHitRange[ipl][wire].first == -1) return true;
1826  float projTick = (float)(tp.Pos[1] / tcc.unitsPerTick);
1827  float tickRange = 0;
1828  if(std::abs(tp.Dir[1]) != 0) {
1829  tickRange = std::abs(0.5 / tp.Dir[1]) / tcc.unitsPerTick;
1830  // don't let it get too large
1831  if(tickRange > 40) tickRange = 40;
1832  }
1833  float loTpTick = projTick - tickRange;
1834  float hiTpTick = projTick + tickRange;
1835  unsigned int firstHit = (unsigned int)slc.wireHitRange[ipl][wire].first;
1836  unsigned int lastHit = (unsigned int)slc.wireHitRange[ipl][wire].second;
1837 
1838  for(unsigned int iht = firstHit; iht < lastHit; ++iht) {
1839  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1840  if(projTick < hit.PeakTime()) {
1841  float loHitTick = hit.PeakTime() - 3 * hit.RMS();
1842  if(hiTpTick > loHitTick) return true;
1843  } else {
1844  float hiHitTick = hit.PeakTime() + 3 * hit.RMS();
1845  if(loTpTick < hiHitTick) return true;
1846  }
1847  } // iht
1848  return false;
1849 
1850  } // SignalAtTp
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
std::vector< float > maxPos1
Definition: DataStructs.h:490
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
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)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
bool tca::SignalBetween ( TCSlice slc,
const TrajPoint tp1,
const TrajPoint tp2,
const float &  MinWireSignalFraction 
)

Definition at line 1671 of file Utils.cxx.

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

Referenced by AttachTrajToVertex(), EndMerge(), Find2DVertices(), and MakeJunkVertices().

1672  {
1673  // Returns true if there is a signal on > MinWireSignalFraction of the wires between tp1 and tp2.
1674  if(MinWireSignalFraction == 0) return true;
1675 
1676  if(tp1.Pos[0] < -0.4 || tp2.Pos[0] < -0.4) return false;
1677  int fromWire = std::nearbyint(tp1.Pos[0]);
1678  int toWire = std::nearbyint(tp2.Pos[0]);
1679 
1680  if(fromWire == toWire) {
1681  TrajPoint tp = tp1;
1682  // check for a signal midway between
1683  tp.Pos[1] = 0.5 * (tp1.Pos[1] + tp2.Pos[1]);
1684  return SignalAtTp(slc, tp);
1685  }
1686  // define a trajectory point located at tp1 that has a direction towards tp2
1687  TrajPoint tp;
1688  if(!MakeBareTrajPoint(slc, tp1, tp2, tp)) return true;
1689  return SignalBetween(slc, tp, toWire, MinWireSignalFraction);
1690  } // SignalBetween
bool SignalBetween(TCSlice &slc, TrajPoint tp, float toPos0, const float &MinWireSignalFraction)
Definition: Utils.cxx:1695
bool SignalAtTp(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:1814
bool MakeBareTrajPoint(TCSlice &slc, const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
Definition: Utils.cxx:3628
bool tca::SignalBetween ( TCSlice slc,
TrajPoint  tp,
float  toPos0,
const float &  MinWireSignalFraction 
)

Definition at line 1695 of file Utils.cxx.

References ChgFracBetween().

Referenced by SignalBetween().

1696  {
1697  // Returns true if there is a signal on > MinWireSignalFraction of the wires between tp and toPos0.
1698  return ChgFracBetween(slc, tp, toPos0) >= MinWireSignalFraction;
1699  } // SignalBetween
float ChgFracBetween(TCSlice &slc, TrajPoint tp, float toPos0)
Definition: Utils.cxx:1702
bool tca::Split3DKink ( TCSlice slc,
PFPStruct pfp,
double  sep,
bool  prt 
)

Definition at line 1811 of file PFPUtils.cxx.

References AttachAnyTrajToVertex(), tca::VtxStore::CTP, DecodeCTP(), evt, FindKinks(), tca::TCEvent::globalS3ID, tca::VtxStore::ID, tca::Vtx3Store::ID, KinkAngle(), kSplit3DKink, tca::PFPStruct::NeedsUpdate, tca::TCSlice::nPlanes, geo::PlaneID::Plane, tca::VtxStore::Pos, SplitTraj(), StoreVertex(), tcc, tca::PFPStruct::TjIDs, tca::TCSlice::tjs, tca::VtxStore::Topo, tca::PFPStruct::Tp3s, tca::Vtx3Store::TPCID, tca::PFPStruct::TPCID, tca::Vtx3Store::UID, tca::TCConfig::useAlg, tca::TCSlice::vtx3s, tca::TCSlice::vtxs, tca::Vtx3Store::Vx2ID, tca::Vtx3Store::X, tca::Vtx3Store::Y, and tca::Vtx3Store::Z.

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

1812  {
1813  // Finds kinks in the PFParticle, splits slc, creates 2D vertices and forces a rebuild if any are found
1814  if(pfp.Tp3s.empty()) return false;
1815  if(!tcc.useAlg[kSplit3DKink]) return false;
1816 
1817  auto kinkPts = FindKinks(slc, pfp, sep, prt);
1818  if(kinkPts.empty()) return false;
1819  if(prt) mf::LogVerbatim("TC")<<"Split3DKink found a kink at Tp3s point "<<kinkPts[0];
1820 
1821  // Only split the biggest angle kink
1822  double big = 0;
1823  unsigned short kpt = 0;
1824  for(auto ipt : kinkPts) {
1825  double dang = KinkAngle(slc, pfp.Tp3s, ipt, sep);
1826  if(dang > big) {
1827  big = dang;
1828  kpt = ipt;
1829  }
1830  } // ipt
1831  if(kpt < 1 || kpt > pfp.Tp3s.size() - 1) return false;
1832  // determine which tjs need to be split
1833  std::vector<unsigned short> tjids;
1834  std::vector<unsigned short> vx2ids;
1835  // inspect a few Tp3s near the kink point to get a list of Tjs
1836  for(unsigned short ipt = kpt; ipt < kpt + 2; ++ipt) {
1837  auto& tp3 = pfp.Tp3s[ipt];
1838  for(auto& tp2 : tp3.Tj2Pts) {
1839  // see if this Tj id is in the list
1840  if(std::find(tjids.begin(), tjids.end(), tp2.id) != tjids.end()) continue;
1841  // ensure that it is pfp.TjIDs
1842  if(std::find(pfp.TjIDs.begin(), pfp.TjIDs.end(), tp2.id) == pfp.TjIDs.end()) continue;
1843  tjids.push_back(tp2.id);
1844  auto& tj = slc.tjs[tp2.id - 1];
1845  auto& tp = tj.Pts[tp2.ipt];
1846  unsigned short closeEnd = USHRT_MAX;
1847  if(tp2.ipt < tj.EndPt[0] + 2) closeEnd = 0;
1848  if(tp2.ipt > tj.EndPt[1] - 2) closeEnd = 1;
1849  if(closeEnd < 2) {
1850  // No split is needed and there should be a vertex at this end of the Tj that
1851  // should be associated with a 3D vertex that we will construct
1852  if(tj.VtxID[closeEnd] == 0) {
1853 // std::cout<<Split3DKink: TODO Tj "<<tj.ID<<" has no vertex attached on end "<<closeEnd<<". Write some code.\n";
1854  return false;
1855  }
1856  vx2ids.push_back(tj.VtxID[closeEnd]);
1857  if(prt) mf::LogVerbatim("TC")<<" tj "<<tj.ID<<" use existing 2V"<<tj.VtxID[closeEnd];
1858  } else {
1859  // make a 2D vertex at this point
1860  VtxStore vx2;
1861  vx2.ID = slc.vtxs.size() + 1;
1862  vx2.CTP = tj.CTP;
1863  vx2.Topo = 10;
1864  vx2.Pos = tp.Pos;
1865  if(!StoreVertex(slc, vx2)) return false;
1866  if(!SplitTraj(slc, tp2.id - 1, tp2.ipt, slc.vtxs.size() - 1, prt)) return false;
1867  vx2ids.push_back(vx2.ID);
1868  AttachAnyTrajToVertex(slc, slc.vtxs.size() - 1, prt);
1869  if(prt) mf::LogVerbatim("TC")<<" tj "<<tj.ID<<" new 2V"<<vx2.ID;
1870  }
1871  } // tp2
1872  } // ipt
1873 
1874  if(vx2ids.size() != slc.nPlanes) {
1875 // std::cout<<"Split3DKink: TODO pfp "<<pfp.ID<<" only has "<<vx2ids.size()<<" 2D vertices. \n";
1876  return false;
1877  }
1878  Vtx3Store vx3;
1879  vx3.TPCID = pfp.TPCID;
1880  vx3.Vx2ID.resize(slc.nPlanes);
1881  vx3.ID = slc.vtx3s.size() + 1;
1882  vx3.X = pfp.Tp3s[kpt].Pos[0];
1883  vx3.Y = pfp.Tp3s[kpt].Pos[1];
1884  vx3.Z = pfp.Tp3s[kpt].Pos[2];
1885  for(auto vx2id : vx2ids) {
1886  if(vx2id == 0) continue;
1887  auto& vx2 = slc.vtxs[vx2id - 1];
1888  unsigned short plane = DecodeCTP(vx2.CTP).Plane;
1889  vx3.Vx2ID[plane] = vx2id;
1890  vx2.Vx3ID = vx3.ID;
1891  } // vx2id
1892  ++evt.globalS3ID;
1893  vx3.UID = evt.globalS3ID;
1894  slc.vtx3s.push_back(vx3);
1895  // mark this as needing an update
1896  pfp.NeedsUpdate = true;
1897  return true;
1898  } // Split3DKink
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
bool AttachAnyTrajToVertex(TCSlice &slc, unsigned short ivx, bool prt)
Definition: TCVertex.cxx:1868
std::vector< unsigned short > FindKinks(TCSlice &slc, PFPStruct &pfp, double sep, bool prt)
Definition: PFPUtils.cxx:1901
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:2093
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
geo::PlaneID DecodeCTP(CTP_t CTP)
double KinkAngle(TCSlice &slc, const std::vector< TrajPoint3 > &tp3s, unsigned short atPt, double sep)
Definition: PFPUtils.cxx:1943
TCEvent evt
Definition: DataStructs.cxx:5
bool SplitTraj(TCSlice &slc, unsigned short itj, float XPos, bool makeVx2, bool prt)
Definition: Utils.cxx:2004
void tca::SplitHiChgHits ( TCSlice slc,
Trajectory tj 
)

Definition at line 4120 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::VtxStore::ChiDOF, tca::VtxStore::CTP, tca::Trajectory::CTP, tca::TCConfig::dbgAlg, tca::TCConfig::dbgStp, evd::details::end(), tca::Trajectory::EndPt, tca::VtxStore::ID, tca::Trajectory::ID, kKilled, kSplitHiChgHits, max, min, tca::VtxStore::NTraj, tca::VtxStore::Pass, tca::Trajectory::Pass, tca::VtxStore::Pos, PrintPos(), tca::Trajectory::Pts, SetEndPoints(), SetVx2Score(), tca::TCSlice::slHits, StoreVertex(), tcc, tca::TCSlice::tjs, tca::VtxStore::Topo, TpSumHitChg(), tca::TCConfig::useAlg, tca::Trajectory::VtxID, and tca::TCSlice::vtxs.

Referenced by ChkHiChgHits().

4120  {
4121 
4122  // Check allTraj trajectories in the current CTP and split high charge hits
4123  if(!tcc.useAlg[kSplitHiChgHits]) return;
4124  // Only do it once
4125  if (tj.AlgMod[kSplitHiChgHits]) return;
4126  if(tj.AlgMod[kKilled]) return;
4127  //Ignore short trajectories
4128  if (tj.EndPt[1]<10) return;
4129 
4130  bool prt = (tcc.dbgStp || tcc.dbgAlg[kSplitHiChgHits]);
4131 
4132  for(unsigned short end = 0; end < 2; ++end) {
4133  if(prt) mf::LogVerbatim("TC")<<"SplitHiChghits "<<end<<" "<<tj.VtxID[end];
4134  float hichg = 0;
4135  unsigned short tp = tj.EndPt[end];
4136  unsigned short nlohits = 0;
4137  unsigned short lastHiTP = USHRT_MAX;
4138  while (tp != tj.EndPt[1-end]){
4139  float ptchg = TpSumHitChg(slc, tj.Pts[tp]);
4140  if (prt) mf::LogVerbatim("TC")<<"SplitHiChgHits "<<tp<<" "<<ptchg<<" "<<PrintPos(slc, tj.Pts[tp]);
4141  if (ptchg){
4142  if (tp == tj.EndPt[end]){
4143  hichg = ptchg;
4144  lastHiTP = tp;
4145  }
4146  else if (ptchg>0.4*hichg){
4147  if (!nlohits){
4148  hichg = ptchg;
4149  lastHiTP = tp;
4150  }
4151  else{
4152  break;
4153  }
4154  }
4155  else ++nlohits;
4156  }
4157  if (end==0){
4158  ++tp;
4159  }
4160  else{
4161  --tp;
4162  }
4163  }
4164  //if (tcc.dbgStp) mf::LogVerbatim("TC")<<"SplitHiChgHits "<<end<<" "<<nlohits;
4165  if (nlohits>4&&lastHiTP!=USHRT_MAX){
4166  //Create new vertex
4167  VtxStore aVtx;
4168  aVtx.Pos = tj.Pts[lastHiTP].Pos;
4169  aVtx.NTraj = 2;
4170  aVtx.Pass = tj.Pass;
4171  aVtx.Topo = 7;
4172  aVtx.ChiDOF = 0;
4173  aVtx.CTP = tj.CTP;
4174  aVtx.ID = slc.vtxs.size() + 1;
4175  if(!StoreVertex(slc, aVtx)) {
4176  if(prt) mf::LogVerbatim("TC")<<" Failed storing vertex "<<tj.VtxID[end];
4177  return;
4178  }
4179 
4180  // make a copy
4181  Trajectory newTj = tj;
4182  newTj.ID = slc.tjs.size() + 1;
4183 
4184  // keep high charge hits, reassign other hits to the new trajectory
4185  unsigned short tp1 = lastHiTP+1;
4186  if (end==1) tp1 = lastHiTP-1;
4187  for (unsigned short ipt = std::min(tj.EndPt[1-end], tp1); ipt <= std::max(tj.EndPt[1-end], tp1); ++ipt){
4188  tj.Pts[ipt].Chg = 0;
4189  for (unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
4190  if(!tj.Pts[ipt].UseHit[ii]) continue;
4191  unsigned int iht = tj.Pts[ipt].Hits[ii];
4192  // This shouldn't happen but check anyway
4193  if(slc.slHits[iht].InTraj != tj.ID) continue;
4194  slc.slHits[iht].InTraj = newTj.ID;
4195  tj.Pts[ipt].UseHit[ii] = false;
4196  }//ii
4197  }//ipt
4198  SetEndPoints(tj);
4199  tj.VtxID[1-end] = aVtx.ID;
4200  tj.AlgMod[kSplitHiChgHits] = true;
4201  if(prt) {
4202  mf::LogVerbatim("TC")<<"Splitting trajectory ID "<<tj.ID<<" new EndPts "<<tj.EndPt[0]<<" to "<<tj.EndPt[1];
4203  }
4204 
4205  for (unsigned short ipt = std::min(newTj.EndPt[end], lastHiTP); ipt <= std::max(newTj.EndPt[end], lastHiTP); ++ipt){
4206  newTj.Pts[ipt].Chg = 0;
4207  for (unsigned short ii = 0; ii < newTj.Pts[ipt].Hits.size(); ++ii) {
4208  newTj.Pts[ipt].UseHit[ii] = false;
4209  }//ii
4210  }//ipt
4211  SetEndPoints(newTj);
4212  newTj.VtxID[end] = aVtx.ID;
4213  newTj.AlgMod[kSplitHiChgHits] = true;
4214  slc.tjs.push_back(newTj);
4215  SetVx2Score(slc);
4216 
4217  break;
4218  }
4219  }
4220  }
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
TCConfig tcc
Definition: DataStructs.cxx:6
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:2093
Int_t max
Definition: plot.C:27
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
float TpSumHitChg(TCSlice &slc, TrajPoint const &tp)
Definition: Utils.cxx:1853
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
Int_t min
Definition: plot.C:26
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:505
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
void SetVx2Score(TCSlice &slc)
Definition: TCVertex.cxx:2504
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool tca::SplitTraj ( TCSlice slc,
unsigned short  itj,
float  XPos,
bool  makeVx2,
bool  prt 
)

Definition at line 2004 of file Utils.cxx.

References detinfo::DetectorProperties::ConvertXToTicks(), tca::VtxStore::CTP, DecodeCTP(), tca::TCConfig::detprop, tca::VtxStore::NTraj, tca::VtxStore::Pos, SplitTraj(), StoreVertex(), tcc, tca::TCSlice::tjs, tca::VtxStore::Topo, tca::TCConfig::unitsPerTick, and tca::TCSlice::vtxs.

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

2005  {
2006  // Splits the trajectory at an X position and optionally creates a 2D vertex at the split point
2007  if(itj > slc.tjs.size()-1) return false;
2008 
2009  auto& tj = slc.tjs[itj];
2010  geo::PlaneID planeID = DecodeCTP(tj.CTP);
2011  float atPos1 = tcc.detprop->ConvertXToTicks(XPos, planeID) * tcc.unitsPerTick;
2012  unsigned short atPt = USHRT_MAX;
2013  for(unsigned short ipt = tj.EndPt[0] + 1; ipt <= tj.EndPt[1]; ++ipt) {
2014  if(tj.Pts[ipt].Pos[1] > tj.Pts[ipt - 1].Pos[1]) {
2015  // positive slope
2016  if(tj.Pts[ipt - 1].Pos[1] < atPos1 && tj.Pts[ipt].Pos[1] >= atPos1) {
2017  atPt = ipt;
2018  break;
2019  }
2020  } else {
2021  // negative slope
2022  if(tj.Pts[ipt - 1].Pos[1] >= atPos1 && tj.Pts[ipt].Pos[1] < atPos1) {
2023  atPt = ipt;
2024  break;
2025  }
2026  } // negative slope
2027  } // ipt
2028  if(atPt == USHRT_MAX) return false;
2029  unsigned short vx2Index = USHRT_MAX;
2030  if(makeVx2) {
2031  VtxStore newVx2;
2032  newVx2.CTP = tj.CTP;
2033  newVx2.Pos[0] = 0.5 * (tj.Pts[atPt - 1].Pos[0] + tj.Pts[atPt].Pos[0]);
2034  newVx2.Pos[1] = 0.5 * (tj.Pts[atPt - 1].Pos[1] + tj.Pts[atPt].Pos[1]);
2035  newVx2.Topo = 10;
2036  newVx2.NTraj = 2;
2037  if(StoreVertex(slc, newVx2)) vx2Index = slc.vtxs.size() - 1;
2038  } // makeVx2
2039  return SplitTraj(slc, itj, atPt, vx2Index, prt);
2040  } // SplitTraj
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:2093
virtual double ConvertXToTicks(double X, int p, int t, int c) const =0
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
const detinfo::DetectorProperties * detprop
Definition: DataStructs.h:494
bool SplitTraj(TCSlice &slc, unsigned short itj, unsigned short pos, unsigned short ivx, bool prt)
Definition: Utils.cxx:2043
geo::PlaneID DecodeCTP(CTP_t CTP)
bool tca::SplitTraj ( TCSlice slc,
unsigned short  itj,
unsigned short  pos,
unsigned short  ivx,
bool  prt 
)

Definition at line 2043 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::EndPt, evt, tca::TCEvent::globalTjID, tca::Trajectory::ID, kSplit, tca::Trajectory::MCSMom, MCSMom(), tca::Trajectory::ParentID, tca::Trajectory::PDGCode, tca::Trajectory::Pts, SetEndPoints(), SetPDGCode(), tca::TCSlice::slHits, tca::TCSlice::tjs, tca::Trajectory::UID, UpdateMatchStructs(), UpdateTjChgProperties(), tca::Trajectory::VtxID, and tca::TCSlice::vtxs.

Referenced by CheckTrajBeginChg(), and SplitTraj().

2044  {
2045  // Splits the trajectory itj in the slc.tjs vector into two trajectories at position pos. Splits
2046  // the trajectory and associates the ends to the supplied vertex.
2047  // Here is an example where itj has 9 points and we will split at pos = 4
2048  // itj (0 1 2 3 4 5 6 7 8) -> new traj (0 1 2 3) + new traj (4 5 6 7 8)
2049 
2050  if(itj > slc.tjs.size()-1) return false;
2051  if(pos < slc.tjs[itj].EndPt[0] + 1 || pos > slc.tjs[itj].EndPt[1] - 1) return false;
2052  if(ivx != USHRT_MAX && ivx > slc.vtxs.size() - 1) return false;
2053 
2054  Trajectory& tj = slc.tjs[itj];
2055 
2056  // Reset the PDG Code if we are splitting a tagged muon
2057  bool splittingMuon = (tj.PDGCode == 13);
2058  if(splittingMuon) tj.PDGCode = 0;
2059 
2060  if(prt) {
2061  mf::LogVerbatim myprt("TC");
2062  myprt<<"SplitTraj: Split T"<<tj.ID<<" at point "<<pos;
2063  if(ivx < slc.vtxs.size()) myprt<<" with Vtx 2V"<<slc.vtxs[ivx].ID;
2064  }
2065 
2066  // ensure that there will be at least 3 TPs on each trajectory
2067  unsigned short ipt, ii, ntp = 0;
2068  for(ipt = 0; ipt < pos; ++ipt) {
2069  if(tj.Pts[ipt].Chg > 0) ++ntp;
2070  if(ntp > 2) break;
2071  } // ipt
2072  if(ntp < 3) {
2073  if(prt) mf::LogVerbatim("TC")<<" Split point to small at begin "<<ntp<<" pos "<<pos<<" ID ";
2074  return false;
2075  }
2076  ntp = 0;
2077  for(ipt = pos + 1; ipt < tj.Pts.size(); ++ipt) {
2078  if(tj.Pts[ipt].Chg > 0) ++ntp;
2079  if(ntp > 2) break;
2080  } // ipt
2081  if(ntp < 3) {
2082  if(prt) mf::LogVerbatim("TC")<<" Split point too small at end "<<ntp<<" pos "<<pos<<" EndPt "<<tj.EndPt[1];
2083  return false;
2084  }
2085 
2086  // make a copy that will become the Tj after the split point
2087  Trajectory newTj = tj;
2088  newTj.ID = slc.tjs.size() + 1;
2089  ++evt.globalTjID;
2090  newTj.UID = evt.globalTjID;
2091  // make another copy in case something goes wrong
2092  Trajectory oldTj = tj;
2093 
2094  // Leave the first section of tj in place. Re-assign the hits
2095  // to the new trajectory
2096  unsigned int iht;
2097  for(ipt = pos + 1; ipt < tj.Pts.size(); ++ipt) {
2098  tj.Pts[ipt].Chg = 0;
2099  for(ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
2100  if(!tj.Pts[ipt].UseHit[ii]) continue;
2101  iht = tj.Pts[ipt].Hits[ii];
2102  // This shouldn't happen but check anyway
2103  if(slc.slHits[iht].InTraj != tj.ID) continue;
2104  slc.slHits[iht].InTraj = newTj.ID;
2105  tj.Pts[ipt].UseHit[ii] = false;
2106  } // ii
2107  } // ipt
2108  SetEndPoints(tj);
2109  tj.MCSMom = MCSMom(slc, tj);
2110  UpdateTjChgProperties("ST", slc, tj, prt);
2111  if(splittingMuon) SetPDGCode(slc, tj, true);
2112 
2113  // Append 3 points from the end of tj onto the
2114  // beginning of newTj so that hits can be swapped between
2115  // them later
2116  unsigned short eraseSize = pos - 2;
2117  if(eraseSize > newTj.Pts.size() - 1) {
2118  tj = oldTj;
2119  return false;
2120  }
2121 
2122  if(ivx < slc.vtxs.size()) tj.VtxID[1] = slc.vtxs[ivx].ID;
2123  tj.AlgMod[kSplit] = true;
2124  if(prt) {
2125  mf::LogVerbatim("TC")<<" Splitting T"<<tj.ID<<" new EndPts "<<tj.EndPt[0]<<" to "<<tj.EndPt[1];
2126  }
2127 
2128  // erase the TPs at the beginning of the new trajectory
2129  newTj.Pts.erase(newTj.Pts.begin(), newTj.Pts.begin() + eraseSize);
2130  // unset the first 3 TP hits
2131  for(ipt = 0; ipt < 3; ++ipt) {
2132  for(ii = 0; ii < newTj.Pts[ipt].Hits.size(); ++ii) newTj.Pts[ipt].UseHit[ii] = false;
2133  newTj.Pts[ipt].Chg = 0;
2134  } // ipt
2135  SetEndPoints(newTj);
2136  newTj.MCSMom = MCSMom(slc, newTj);
2137  UpdateTjChgProperties("ST", slc, newTj, prt);
2138  if(splittingMuon) SetPDGCode(slc, newTj, true);
2139  if(ivx < slc.vtxs.size()) newTj.VtxID[0] = slc.vtxs[ivx].ID;
2140  newTj.AlgMod[kSplit] = true;
2141  newTj.ParentID = 0;
2142  // save the ID before push_back in case the tj reference gets lost
2143  int tjid = tj.ID;
2144  slc.tjs.push_back(newTj);
2145  UpdateMatchStructs(slc, tjid, newTj.ID);
2146 
2147  if(prt) {
2148  mf::LogVerbatim("TC")<<" newTj T"<<newTj.ID<<" EndPts "<<newTj.EndPt[0]<<" to "<<newTj.EndPt[1];
2149  }
2150  return true;
2151 
2152  } // SplitTraj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
void SetPDGCode(TCSlice &slc, Trajectory &tj, bool tjDone)
Definition: Utils.cxx:3802
void UpdateMatchStructs(TCSlice &slc, int oldTj, int newTj)
Definition: PFPUtils.cxx:160
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3196
TCEvent evt
Definition: DataStructs.cxx:5
short MCSMom(TCSlice &slc, Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:2936
void tca::SplitTrajCrossingVertices ( TCSlice slc,
CTP_t  inCTP 
)

Definition at line 1268 of file TCVertex.cxx.

References tca::TCConfig::dbgAlg, tca::TCConfig::dbgSlc, DecodeCTP(), DeltaAngle(), evd::details::end(), FitVertex(), GetVtxTjIDs(), kDebug, kDeltaRay, kHaloTj, tca::TCConfig::kinkCuts, kKilled, kOnDeadWire, kSplitTjCVx, MakeVertexObsolete(), tca::TCConfig::modes, NumPtsWithCharge(), geo::PlaneID::Plane, PointTrajDOCA(), PrintTrajPoint(), SplitTraj(), tcc, tca::TCSlice::tjs, TrajClosestApproach(), tca::TCConfig::useAlg, tca::TCConfig::vtx2DCuts, and tca::TCSlice::vtxs.

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

1269  {
1270  // This is kind of self-explanatory...
1271 
1272  if(!tcc.useAlg[kSplitTjCVx]) return;
1273 
1274  if(slc.vtxs.empty()) return;
1275  if(slc.tjs.empty()) return;
1276 
1277  constexpr float docaCut = 4;
1278 
1279  bool prt = (tcc.modes[kDebug] && tcc.dbgSlc && tcc.dbgAlg[kSplitTjCVx]);
1280  if(prt) mf::LogVerbatim("TC")<<"Inside SplitTrajCrossingVertices inCTP "<<inCTP;
1281 
1282  geo::PlaneID planeID = DecodeCTP(inCTP);
1283 
1284  unsigned short nTraj = slc.tjs.size();
1285  for(unsigned short itj = 0; itj < nTraj; ++itj) {
1286  // NOTE: Don't use a reference variable because it may get lost if the tj is split
1287 // auto& tj = slc.tjs[itj];
1288  if(slc.tjs[itj].CTP != inCTP) continue;
1289  // obsolete trajectory
1290  if(slc.tjs[itj].AlgMod[kKilled] || slc.tjs[itj].AlgMod[kHaloTj]) continue;
1291  if(slc.tjs[itj].AlgMod[kSplitTjCVx]) continue;
1292  // too short
1293  if(slc.tjs[itj].EndPt[1] < 6) continue;
1294  for(unsigned short iv = 0; iv < slc.vtxs.size(); ++iv) {
1295  auto& vx2 = slc.vtxs[iv];
1296  // obsolete vertex
1297  if(vx2.NTraj == 0) continue;
1298  // trajectory already associated with vertex
1299  if(slc.tjs[itj].VtxID[0] == vx2.ID ||
1300  slc.tjs[itj].VtxID[1] == vx2.ID) continue;
1301  // not in the cryostat/tpc/plane
1302  if(slc.tjs[itj].CTP != vx2.CTP) continue;
1303  // poor quality
1304  if(vx2.Score < tcc.vtx2DCuts[7]) continue;
1305  float doca = docaCut;
1306  // make the cut significantly larger if the vertex is in a dead
1307  // wire gap to get the first TP that is just outside the gap.
1308  if(vx2.Stat[kOnDeadWire]) doca = 100;
1309  unsigned short closePt = 0;
1310  if(!TrajClosestApproach(slc.tjs[itj], vx2.Pos[0], vx2.Pos[1], closePt, doca)) continue;
1311  if(vx2.Stat[kOnDeadWire]) {
1312  // special handling for vertices in dead wire regions. Find the IP between
1313  // the closest point on the Tj and the vertex
1314  doca = PointTrajDOCA(slc, vx2.Pos[0], vx2.Pos[1], slc.tjs[itj].Pts[closePt]);
1315  }
1316  if(doca > docaCut) continue;
1317  if(prt) mf::LogVerbatim("TC")<<" doca "<<doca<<" btw T"<<slc.tjs[itj].ID<<" and 2V"<<slc.vtxs[iv].ID<<" closePt "<<closePt<<" in plane "<<planeID.Plane;
1318  // compare the length of the Tjs used to make the vertex with the length of the
1319  // Tj that we want to split. Don't allow a vertex using very short Tjs to split a long
1320  // Tj in the 3rd plane
1321  auto vxtjs = GetVtxTjIDs(slc, vx2);
1322  if(vxtjs.empty()) continue;
1323  unsigned short maxPts = 0;
1324  // ensure that there is a large angle between a Tj already attached to the vertex and the
1325  // tj that we want to split. We might be considering a delta-ray here
1326  float maxdang = 0;
1327  float tjAng = slc.tjs[itj].Pts[closePt].Ang;
1328  for(auto tjid : vxtjs) {
1329  auto& vtj = slc.tjs[tjid - 1];
1330  if(vtj.AlgMod[kDeltaRay]) continue;
1331  unsigned short npwc = NumPtsWithCharge(slc, vtj, false);
1332  if(npwc > maxPts) maxPts = npwc;
1333  unsigned short end = 0;
1334  if(vtj.VtxID[1] == slc.vtxs[iv].ID) end = 1;
1335  auto& vtp = vtj.Pts[vtj.EndPt[end]];
1336  float dang = DeltaAngle(vtp.Ang, tjAng);
1337  if(dang > maxdang) maxdang = dang;
1338  } // tjid
1339  // skip this operation if any of the Tjs in the split list are > 3 * maxPts
1340  maxPts *= 3;
1341  bool skipit = false;
1342  if(NumPtsWithCharge(slc, slc.tjs[itj], false) > maxPts && maxPts < 100) skipit = true;
1343  if(!skipit && maxdang < tcc.kinkCuts[0]) skipit = true;
1344  if(prt) mf::LogVerbatim("TC")<<" maxPts "<<maxPts<<" vxtjs[0] "<<vxtjs[0]<<" maxdang "<<maxdang<<" skipit? "<<skipit;
1345  if(skipit) {
1346  // kill the vertex?
1347  if(doca < 1) MakeVertexObsolete("STCV", slc, vx2, true);
1348  continue;
1349  }
1350 
1351  // make some adjustments to closePt
1352  if(vx2.Stat[kOnDeadWire]) {
1353  // ensure that the tj will be split at the gap. The closePt point may be
1354  // on the wrong side of it
1355  auto& closeTP = slc.tjs[itj].Pts[closePt];
1356  if(slc.tjs[itj].StepDir > 0 && closePt > slc.tjs[itj].EndPt[0]) {
1357  if(closeTP.Pos[0] > vx2.Pos[0]) --closePt;
1358  } else if(slc.tjs[itj].StepDir < 0 && closePt < slc.tjs[itj].EndPt[1]) {
1359  if(closeTP.Pos[0] < vx2.Pos[0]) ++closePt;
1360  }
1361  } else {
1362  // improve closePt based on vertex position
1363  // check if closePt and EndPt[1] are the two sides of vertex
1364  // take dot product of closePt-vtx and EndPt[1]-vtx
1365  if ((slc.tjs[itj].Pts[closePt].Pos[0]-vx2.Pos[0])*(slc.tjs[itj].Pts[slc.tjs[itj].EndPt[1]].Pos[0]-vx2.Pos[0]) + (slc.tjs[itj].Pts[closePt].Pos[1]-vx2.Pos[1])*(slc.tjs[itj].Pts[slc.tjs[itj].EndPt[1]].Pos[1]-vx2.Pos[1]) <0 && closePt < slc.tjs[itj].EndPt[1] - 1) ++closePt;
1366  else if ((slc.tjs[itj].Pts[closePt].Pos[0]-vx2.Pos[0])*(slc.tjs[itj].Pts[slc.tjs[itj].EndPt[0]].Pos[0]-vx2.Pos[0]) + (slc.tjs[itj].Pts[closePt].Pos[1]-vx2.Pos[1])*(slc.tjs[itj].Pts[slc.tjs[itj].EndPt[0]].Pos[1]-slc.vtxs[iv].Pos[1]) <0 && closePt > slc.tjs[itj].EndPt[0] + 1) --closePt;
1367  }
1368 
1369 
1370  if(prt) {
1371  mf::LogVerbatim("TC")<<"Good doca "<<doca<<" btw T"<<slc.tjs[itj].ID<<" and 2V"<<vx2.ID<<" closePt "<<closePt<<" in plane "<<planeID.Plane<<" CTP "<<slc.vtxs[iv].CTP;
1372  PrintTrajPoint("STCV", slc, closePt, 1, slc.tjs[itj].Pass, slc.tjs[itj].Pts[closePt]);
1373  }
1374  // ensure that the closest point is not near an end
1375  if(closePt < slc.tjs[itj].EndPt[0] + 3) continue;
1376  if(closePt > slc.tjs[itj].EndPt[1] - 3) continue;
1377  if(!SplitTraj(slc, itj, closePt, iv, prt)) {
1378  if(prt) mf::LogVerbatim("TC")<<"SplitTrajCrossingVertices: Failed to split trajectory";
1379  continue;
1380  }
1381  slc.tjs[itj].AlgMod[kSplitTjCVx] = true;
1382  unsigned short newTjIndex = slc.tjs.size() - 1;
1383  slc.tjs[newTjIndex].AlgMod[kSplitTjCVx] = true;
1384  // re-fit the vertex position
1385  FitVertex(slc, vx2, prt);
1386  } // iv
1387  } // itj
1388 
1389  } // SplitTrajCrossingVertices
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeVertexObsolete(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:3208
bool FitVertex(TCSlice &slc, VtxStore &vx, std::vector< TrajPoint > vxTp, bool prt)
Definition: TCVertex.cxx:2184
std::vector< float > kinkCuts
kink angle, nPts fit, (alternate) kink angle significance
Definition: DataStructs.h:475
TCConfig tcc
Definition: DataStructs.cxx:6
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:2377
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1636
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:507
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:3243
geo::PlaneID DecodeCTP(CTP_t CTP)
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:505
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:466
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool SplitTraj(TCSlice &slc, unsigned short itj, float XPos, bool makeVx2, bool prt)
Definition: Utils.cxx:2004
master switch for turning on debug mode
Definition: DataStructs.h:449
void PrintTrajPoint(std::string someText, TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, TrajPoint const &tp)
Definition: Utils.cxx:5541
std::vector< float > tca::StartChgVec ( TCSlice slc,
int  cotID,
bool  prt 
)

Definition at line 4188 of file TCShower.cxx.

References tca::TCEvent::allHits, tca::ShowerStruct::Angle, tca::TCSlice::cots, evt, tca::ShowerStruct::ID, tca::ShowerStruct::ParentID, tca::TrajPoint::Pos, tca::ShowerStruct::ShowerTjID, tca::ShowerStruct::ShPts, tca::TCSlice::slHits, ss, tcc, tca::ShowerStruct::TjIDs, tca::TCSlice::tjs, and tca::TCConfig::unitsPerTick.

Referenced by FindStartChg().

4189  {
4190  // Returns a histogram vector of the charge in bins of 1 WSE unit at the start of the shower
4191 
4192  ShowerStruct& ss = slc.cots[cotID - 1];
4193  constexpr unsigned short nbins = 20;
4194  std::vector<float> schg(nbins);
4195  if(ss.ID == 0) return schg;
4196  if(ss.TjIDs.empty()) return schg;
4197  TrajPoint& stp1 = slc.tjs[ss.ShowerTjID-1].Pts[1];
4198 
4199  // move the min along point back by 2 WSE so that most of the charge in the hits in the
4200  // first point is included in the histogram
4201  float minAlong = ss.ShPts[0].RotPos[0] - 2;
4202 
4203  float maxTrans = 4;
4204  // Tighten up on the maximum allowed transverse position if there is a parent
4205  if(ss.ParentID > 0) maxTrans = 1;
4206  float cs = cos(-ss.Angle);
4207  float sn = sin(-ss.Angle);
4208  std::array<float, 2> chgPos;
4209  float along, arg;
4210 
4211  for(auto& sspt : ss.ShPts) {
4212  unsigned short indx = (unsigned short)((sspt.RotPos[0] - minAlong));
4213  if(indx > nbins - 1) break;
4214  // Count the charge if it is within a few WSE transverse from the shower axis
4215  if(std::abs(sspt.RotPos[1]) > maxTrans) continue;
4216  unsigned int iht = sspt.HitIndex;
4217  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
4218  float peakTime = hit.PeakTime();
4219  float amp = hit.PeakAmplitude();
4220  float rms = hit.RMS();
4221  chgPos[0] = hit.WireID().Wire - stp1.Pos[0];
4222  for(float time = peakTime - 2.5 * rms; time < peakTime + 2.5 * rms; ++time) {
4223  chgPos[1] = time * tcc.unitsPerTick - stp1.Pos[1];
4224  along = cs * chgPos[0] - sn * chgPos[1];
4225  if(along < minAlong) continue;
4226  indx = (unsigned short)(along - minAlong);
4227  if(indx > nbins - 1) continue;
4228  arg = (time - peakTime) / rms;
4229  schg[indx] += amp * exp(-0.5 * arg * arg);
4230  } // time
4231  } // sspt
4232 
4233  return schg;
4234  } // StartChgVec
TCConfig tcc
Definition: DataStructs.cxx:6
Float_t ss
Definition: plot.C:23
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
bool tca::StartTraj ( TCSlice slc,
Trajectory tj,
unsigned int  fromhit,
unsigned int  tohit,
unsigned short  pass 
)

Definition at line 4431 of file Utils.cxx.

References tca::TCEvent::allHits, tca::TCConfig::dbgDump, tca::TCConfig::dbgSlc, tca::TCConfig::dbgStp, debug, EncodeCTP(), evt, ExpectedHitsRMS(), tca::Trajectory::ID, kDebug, tca::TCConfig::modes, tca::Trajectory::Pts, tca::TCSlice::slHits, StartTraj(), tca::Trajectory::StepDir, tcc, and tca::DebugStuff::WorkID.

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

4432  {
4433  // Start a trajectory located at fromHit with direction pointing to toHit
4434 
4435  auto& fromHit = (*evt.allHits)[slc.slHits[fromhit].allHitsIndex];
4436  auto& toHit = (*evt.allHits)[slc.slHits[tohit].allHitsIndex];
4437  float fromWire = fromHit.WireID().Wire;
4438  float fromTick = fromHit.PeakTime();
4439  float toWire = toHit.WireID().Wire;
4440  float toTick = toHit.PeakTime();
4441  CTP_t tCTP = EncodeCTP(fromHit.WireID());
4442  bool success = StartTraj(slc, tj, fromWire, fromTick, toWire, toTick, tCTP, pass);
4443  if(!success) return false;
4444  // turn on debugging using the WorkID?
4445  if(tcc.modes[kDebug] && !tcc.dbgStp && !tcc.dbgDump && tcc.dbgSlc && tj.ID == debug.WorkID) tcc.dbgStp = true;
4446  if(tcc.dbgStp) {
4447  auto& tp = tj.Pts[0];
4448  mf::LogVerbatim("TC")<<"StartTraj T"<<tj.ID<<" from "<<(int)fromWire<<":"<<(int)fromTick<<" -> "<<(int)toWire<<":"<<(int)toTick<<" StepDir "<<tj.StepDir<<" dir "<<tp.Dir[0]<<" "<<tp.Dir[1]<<" ang "<<tp.Ang<<" AngleCode "<<tp.AngleCode<<" angErr "<<tp.AngErr<<" ExpectedHitsRMS "<<ExpectedHitsRMS(slc, tp);
4449  } // tcc.dbgStp
4450  return true;
4451  } // StartTraj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
float ExpectedHitsRMS(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:1802
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:507
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
int WorkID
Select the StartWorkID for debugging.
Definition: DebugStruct.h:26
DebugStuff debug
Definition: DebugStruct.cxx:4
bool StartTraj(TCSlice &slc, Trajectory &tj, float fromWire, float fromTick, float toWire, float toTick, CTP_t &tCTP, unsigned short pass)
Definition: Utils.cxx:4454
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
unsigned int CTP_t
Definition: DataStructs.h:41
TDirectory * dir
Definition: macro.C:5
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:45
TCEvent evt
Definition: DataStructs.cxx:5
master switch for turning on debug mode
Definition: DataStructs.h:449
bool tca::StartTraj ( TCSlice slc,
Trajectory tj,
float  fromWire,
float  fromTick,
float  toWire,
float  toTick,
CTP_t tCTP,
unsigned short  pass 
)

Definition at line 4454 of file Utils.cxx.

References tca::TrajPoint::Ang, tca::TrajPoint::AngErr, tca::TrajPoint::AngleCode, tca::Trajectory::CTP, tca::TCConfig::dbgDump, tca::TCConfig::dbgSlc, tca::TCConfig::dbgStp, debug, tca::TrajPoint::Dir, evt, ExpectedHitsRMS(), tca::Trajectory::ID, kDebug, kNormal, MakeBareTrajPoint(), tca::TCConfig::modes, tca::Trajectory::ParentID, tca::Trajectory::Pass, tca::Trajectory::Pts, SetAngleCode(), tca::Trajectory::StepDir, tca::Trajectory::Strategy, tcc, tca::DebugStuff::WorkID, and tca::TCEvent::WorkID.

Referenced by StartTraj().

4455  {
4456  // Start a simple (seed) trajectory going from (fromWire, toTick) to (toWire, toTick).
4457 
4458  // decrement the work ID so we can use it for debugging problems
4459  --evt.WorkID;
4460  if(evt.WorkID == INT_MIN) evt.WorkID = -1;
4461  tj.ID = evt.WorkID;
4462  tj.Pass = pass;
4463  // Assume we are stepping in the positive WSE units direction
4464  short stepdir = 1;
4465  int fWire = std::nearbyint(fromWire);
4466  int tWire = std::nearbyint(toWire);
4467  if(tWire < fWire) {
4468  stepdir = -1;
4469  } else if(tWire == fWire) {
4470  // on the same wire
4471  if(toTick < fromTick) stepdir = -1;
4472  }
4473  tj.StepDir = stepdir;
4474  tj.CTP = tCTP;
4475  tj.ParentID = -1;
4476  tj.Strategy.reset();
4477  tj.Strategy[kNormal] = true;
4478 
4479  // create a trajectory point
4480  TrajPoint tp;
4481  if(!MakeBareTrajPoint(slc, fromWire, fromTick, toWire, toTick, tCTP, tp)) return false;
4482  SetAngleCode(tp);
4483  tp.AngErr = 0.1;
4484  tj.Pts.push_back(tp);
4485  // turn on debugging using the WorkID?
4486  if(tcc.modes[kDebug] && !tcc.dbgStp && !tcc.dbgDump && tcc.dbgSlc && tj.ID == debug.WorkID) tcc.dbgStp = true;
4487  if(tcc.dbgStp) {
4488  auto& tp = tj.Pts[0];
4489  mf::LogVerbatim("TC")<<"StartTraj T"<<tj.ID<<" from "<<(int)fromWire<<":"<<(int)fromTick<<" -> "<<(int)toWire<<":"<<(int)toTick<<" StepDir "<<tj.StepDir<<" dir "<<tp.Dir[0]<<" "<<tp.Dir[1]<<" ang "<<tp.Ang<<" AngleCode "<<tp.AngleCode<<" angErr "<<tp.AngErr<<" ExpectedHitsRMS "<<ExpectedHitsRMS(slc, tp);
4490  } // tcc.dbgStp
4491  return true;
4492 
4493  } // StartTraj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
float ExpectedHitsRMS(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:1802
void SetAngleCode(TrajPoint &tp)
Definition: Utils.cxx:722
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:507
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
int WorkID
Select the StartWorkID for debugging.
Definition: DebugStruct.h:26
DebugStuff debug
Definition: DebugStruct.cxx:4
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
bool MakeBareTrajPoint(TCSlice &slc, const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
Definition: Utils.cxx:3628
TDirectory * dir
Definition: macro.C:5
TCEvent evt
Definition: DataStructs.cxx:5
master switch for turning on debug mode
Definition: DataStructs.h:449
void tca::StepAway ( TCSlice slc,
Trajectory tj 
)

Definition at line 15 of file StepUtils.cxx.

References AddHits(), tca::Trajectory::AlgMod, tca::TrajPoint::AngleCode, AttachTrajToVertex(), tca::TrajPoint::Chg, tca::TrajPoint::CTP, tca::Trajectory::CTP, tca::TCConfig::dbg2V, tca::TCConfig::dbgStp, DeadWireCount(), DecodeCTP(), DefineHitPos(), DeltaAngle(), tca::TrajPoint::Dir, tca::TCConfig::doForecast, tca::Trajectory::EndPt, tca::TrajPoint::FitChi, Forecast(), GottaKink(), tca::TrajPoint::Hits, tca::Trajectory::ID, tca::Trajectory::IsGood, kAtKink, kAtTj, kAtVtx, kNewStpCuts, kRvPrp, kSignal, kSlowing, kStopBadFits, MaskedHitsOK(), tca::Trajectory::MaskedLastTP, MaskTrajEndPoints(), tca::TCConfig::maxAngleCode, tca::TCConfig::maxChi, tca::TCConfig::maxPos0, tca::TCConfig::maxPos1, tca::TCConfig::maxWireSkipNoSignal, tca::TCConfig::maxWireSkipWithSignal, tca::Trajectory::MCSMom, tca::TCConfig::minMCSMom, tca::TCConfig::minPtsFit, tca::TCConfig::muonTag, tca::Trajectory::NeedsUpdate, NumPtsWithCharge(), tca::Trajectory::Pass, tca::Trajectory::PDGCode, geo::PlaneID::Plane, tca::TrajPoint::Pos, PosSep2(), PrintPos(), PrintTrajectory(), PrintTrajPoint(), tca::Trajectory::Pts, SetEndPoints(), SetPDGCode(), SetStrategy(), SignalAtTp(), tca::TCSlice::slHits, tca::TrajPoint::Step, tca::Trajectory::StepDir, tca::Trajectory::StopFlag, StopIfBadFits(), tca::Trajectory::Strategy, StrategyBitNames, tcc, tjfs, TPNearVertex(), TrajPointSeparation(), tca::TCConfig::unitsPerTick, UnsetUsedHits(), UpdateTraj(), tca::TCConfig::useAlg, tca::TrajPoint::UseHit, tca::TCConfig::VLAStepSize, and tca::TCSlice::vtxs.

Referenced by FindVtxTjs(), tca::TrajClusterAlg::ReconstructAllTraj(), and ReversePropagate().

16  {
17  // Step along the direction specified in the traj vector in steps of size step
18  // (wire spacing equivalents). Find hits between the last trajectory point and
19  // the last trajectory point + step. A new trajectory point is added if hits are
20  // found. Stepping continues until no signal is found for two consecutive steps
21  // or until a wire or time boundary is reached.
22 
23  tj.IsGood = false;
24  if(tj.Pts.empty()) return;
25 
26  unsigned short plane = DecodeCTP(tj.CTP).Plane;
27 
28  unsigned short lastPtWithUsedHits = tj.EndPt[1];
29 
30  unsigned short lastPt = lastPtWithUsedHits;
31  // Construct a local TP from the last TP that will be moved on each step.
32  // Only the Pos and Dir variables will be used
33  TrajPoint ltp;
34  ltp.CTP = tj.CTP;
35  ltp.Pos = tj.Pts[lastPt].Pos;
36  ltp.Dir = tj.Pts[lastPt].Dir;
37  // A second TP is cloned from the leading TP of tj, updated with hits, fit
38  // parameters,etc and possibly pushed onto tj as the next TP
39  TrajPoint tp;
40 
41  // assume it is good from here on
42  tj.IsGood = true;
43 
44  unsigned short nMissedSteps = 0;
45  // Use MaxChi chisq cut for stiff trajectories
46  bool useMaxChiCut = (tj.PDGCode == 13 || !tj.Strategy[kSlowing]);
47 
48  // Get the first forecast when there are 6 points with charge
49  tjfs.resize(1);
50  tjfs[0].nextForecastUpdate = 6;
51 
52  for(unsigned short step = 1; step < 10000; ++step) {
53  // Get a forecast of what is ahead.
54 // unsigned short span = tj.EndPt[1] - tj.EndPt[0] + 1;
55  unsigned short span = NumPtsWithCharge(slc, tj, false);
56  if(tcc.doForecast && !tj.AlgMod[kRvPrp] && span == tjfs[tjfs.size() - 1].nextForecastUpdate) {
57  Forecast(slc, tj);
58  SetStrategy(slc, tj);
59  SetPDGCode(slc, tj, false);
60  }
61  // make a copy of the previous TP
62  lastPt = tj.Pts.size() - 1;
63  tp = tj.Pts[lastPt];
64  ++tp.Step;
65  double stepSize = tcc.VLAStepSize;
66  if(tp.AngleCode < 2) stepSize = std::abs(1/ltp.Dir[0]);
67  // move the local TP position by one step in the right direction
68  for(unsigned short iwt = 0; iwt < 2; ++iwt) ltp.Pos[iwt] += ltp.Dir[iwt] * stepSize;
69 
70  unsigned short ivx = TPNearVertex(slc, ltp);
71  if(ivx != USHRT_MAX) {
72  // Trajectory stops near a vertex so make the assignment
73  if(AttachTrajToVertex(slc, tj, slc.vtxs[ivx], tcc.dbgStp || tcc.dbg2V)) tj.StopFlag[1][kAtVtx] = true;
74  break;
75  }
76 
77  // copy this position into tp
78  tp.Pos = ltp.Pos;
79  tp.Dir = ltp.Dir;
80  if(tcc.dbgStp) {
81  mf::LogVerbatim myprt("TC");
82  myprt<<"StepAway "<<step<<" Pos "<<tp.Pos[0]<<" "<<tp.Pos[1]<<" Dir "<<tp.Dir[0]<<" "<<tp.Dir[1]<<" stepSize "<<stepSize<<" AngCode "<<tp.AngleCode<<" Strategy";
83  for(unsigned short ibt = 0; ibt < StrategyBitNames.size(); ++ibt) {
84  if(tj.Strategy[ibt]) myprt<<" "<<StrategyBitNames[ibt];
85  } // ib
86  } // tcc.dbgStp
87  // hit the boundary of the TPC?
88  if(tp.Pos[0] < 0 || tp.Pos[0] > tcc.maxPos0[plane] ||
89  tp.Pos[1] < 0 || tp.Pos[1] > tcc.maxPos1[plane]) break;
90  // remove the old hits and other stuff
91  tp.Hits.clear();
92  tp.UseHit.reset();
93  tp.FitChi = 0; tp.Chg = 0;
94  // append to the trajectory
95  tj.Pts.push_back(tp);
96  // update the index of the last TP
97  lastPt = tj.Pts.size() - 1;
98  // look for hits
99  bool sigOK = false;
100  AddHits(slc, tj, lastPt, sigOK);
101  // Check the stop flag
102  if(tj.StopFlag[1][kAtTj]) break;
103  // If successfull, AddHits has defined UseHit for this TP,
104  // set the trajectory endpoints, and define HitPos.
105  if(tj.Pts[lastPt].Hits.empty()) {
106  // Require three points with charge on adjacent wires for small angle
107  // stepping.
108  if(tj.Pts[lastPt].AngleCode == 0 && lastPt == 2) return;
109  // No close hits added.
110  ++nMissedSteps;
111  // First check for no signal in the vicinity
112  if(lastPt > 0) {
113  // break if this is a reverse propagate activity and there was no signal (not on a dead wire)
114  if(!sigOK && tj.AlgMod[kRvPrp]) break;
115  // Ensure that there is a signal here after missing a number of steps on a LA trajectory
116  if(tj.Pts[lastPt].AngleCode > 0 && nMissedSteps > 4 && !SignalAtTp(slc, ltp)) {
117  tj.StopFlag[1][kSignal] = false;
118  break;
119  }
120  // the last point with hits (used or not) is the previous point
121  unsigned short lastPtWithHits = lastPt - 1;
122  float tps = TrajPointSeparation(tj.Pts[lastPtWithHits], ltp);
123  float dwc = DeadWireCount(slc, ltp, tj.Pts[lastPtWithHits]);
124  float nMissedWires = tps * std::abs(ltp.Dir[0]) - dwc;
125  float maxWireSkip = tcc.maxWireSkipNoSignal;
126  if(tj.PDGCode == 13) maxWireSkip = tcc.muonTag[2];
127  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" StepAway: no signal at ltp "<<PrintPos(slc, ltp)<<" nMissedWires "<<std::fixed<<std::setprecision(1)<<nMissedWires<<" dead wire count "<<dwc<<" maxWireSkip "<<maxWireSkip<<" tj.PDGCode "<<tj.PDGCode;
128  if(nMissedWires > maxWireSkip) {
129  // We passed a number of wires without adding hits and are ready to quit.
130  // First see if there is one good unused hit on the end TP and if so use it
131  // lastPtWithHits + 1 == lastPt && tj.Pts[lastPtWithHits].Chg == 0 && tj.Pts[lastPtWithHits].Hits.size() == 1
132  if(tj.EndPt[1] < tj.Pts.size() - 1 && tj.Pts[tj.EndPt[1]+1].Hits.size() == 1) {
133  unsigned short lastLonelyPoint = tj.EndPt[1] + 1;
134  unsigned int iht = tj.Pts[lastLonelyPoint].Hits[0];
135  if(slc.slHits[iht].InTraj == 0 && tj.Pts[lastLonelyPoint].Delta < 3 * tj.Pts[lastLonelyPoint].DeltaRMS) {
136  slc.slHits[iht].InTraj = tj.ID;
137  tj.Pts[lastLonelyPoint].UseHit[0] = true;
138  DefineHitPos(slc, tj.Pts[lastLonelyPoint]);
139  SetEndPoints(tj);
140  if(tcc.dbgStp) {
141  mf::LogVerbatim("TC")<<" Added a Last Lonely Hit before breaking ";
142  PrintTrajPoint("LLH", slc, lastPt, tj.StepDir, tj.Pass, tj.Pts[lastLonelyPoint]);
143  }
144  }
145  }
146  break;
147  }
148  } // lastPt > 0
149  // no sense keeping this TP on tj if no hits were added
150  tj.Pts.pop_back();
151  continue;
152  } // tj.Pts[lastPt].Hits.empty()
153  // ensure that we actually moved
154  if(lastPt > 0 && PosSep2(tj.Pts[lastPt].Pos, tj.Pts[lastPt-1].Pos) < 0.1) return;
155  // Found hits at this location so reset the missed steps counter
156  nMissedSteps = 0;
157  // Update the last point fit, etc using the just added hit(s)
158  UpdateTraj(slc, tj);
159  // a failure occurred
160  if(tj.NeedsUpdate) return;
161  if(tj.Pts[lastPt].Chg == 0) {
162  // There are points on the trajectory by none used in the last step. See
163  // how long this has been going on
164  float tps = TrajPointSeparation(tj.Pts[tj.EndPt[1]], ltp);
165  float dwc = DeadWireCount(slc, ltp, tj.Pts[tj.EndPt[1]]);
166  float nMissedWires = tps * std::abs(ltp.Dir[0]) - dwc;
167  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Hits exist on the trajectory but are not used. Missed wires "<<std::nearbyint(nMissedWires)<<" dead wire count "<<(int)dwc;
168  // break if this is a reverse propagate activity with no dead wires
169  if(tj.AlgMod[kRvPrp] && dwc == 0) break;
170  if(nMissedWires > tcc.maxWireSkipWithSignal) break;
171  // try this out
172  if(!MaskedHitsOK(slc, tj)) {
173  return;
174  }
175  // check for a series of bad fits and stop stepping
176  if(tcc.useAlg[kStopBadFits] && nMissedWires > 4 && StopIfBadFits(slc, tj)) break;
177  // Keep stepping
178  if(tcc.dbgStp) {
179  if(tj.AlgMod[kRvPrp]) {
180  PrintTrajectory("RP", slc, tj, lastPt);
181  } else {
182  PrintTrajectory("SC", slc, tj, lastPt);
183  }
184  }
185  continue;
186  } // tp.Hits.empty()
187  if(tj.Pts.size() == 3) {
188  // ensure that the last hit added is in the same direction as the first two.
189  // This is a simple way of doing it
190  bool badTj = (PosSep2(tj.Pts[0].HitPos, tj.Pts[2].HitPos) < PosSep2(tj.Pts[0].HitPos, tj.Pts[1].HitPos));
191  // ensure that this didn't start as a small angle trajectory and immediately turn
192  // into a large angle one
193  if(!badTj && tj.Pts[lastPt].AngleCode > tcc.maxAngleCode[tj.Pass]) badTj = true;
194  // check for a large change in angle
195  if(!badTj) {
196  float dang = DeltaAngle(tj.Pts[0].Ang, tj.Pts[2].Ang);
197  if(dang > 0.5) badTj = false;
198  }
199  //check for a wacky delta
200  if(!badTj && tj.Pts[2].Delta > 2) badTj = true;
201  if(badTj) {
202  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Bad Tj found on the third point. Quit stepping.";
203  tj.IsGood = false;
204  return;
205  }
206  } // tj.Pts.size() == 3
207  // Update the local TP with the updated position and direction
208  ltp.Pos = tj.Pts[lastPt].Pos;
209  ltp.Dir = tj.Pts[lastPt].Dir;
210  if(tj.MaskedLastTP) {
211  // see if TPs have been masked off many times and if the
212  // environment is clean. If so, return and try with next pass
213  // cuts
214  if(!MaskedHitsOK(slc, tj)) {
215  if(tcc.dbgStp) {
216  if(tj.AlgMod[kRvPrp]) {
217  PrintTrajectory("RP", slc, tj, lastPt);
218  } else {
219  PrintTrajectory("SC", slc, tj, lastPt);
220  }
221  }
222  return;
223  }
224  // Don't bother with the rest of the checking below if we
225  // set all hits not used on this TP
226  if(tcc.dbgStp) {
227  if(tj.AlgMod[kRvPrp]) {
228  PrintTrajectory("RP", slc, tj, lastPt);
229  } else {
230  PrintTrajectory("SC", slc, tj, lastPt);
231  }
232  }
233  continue;
234  }
235  // We have added a TP with hits
236  // assume that we aren't going to kill the point we just added, or any
237  // of the previous points...
238  unsigned short killPts = 0;
239  // assume that we should keep going after killing points
240  bool keepGoing = true;
241  // check for a kink. Stop crawling if one is found
242  GottaKink(slc, tj, killPts);
243  if(tj.StopFlag[1][kAtKink]) {
244  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" stop at kink with killPts "<<killPts;
245  keepGoing = false;
246  }
247  // See if the Chisq/DOF exceeds the maximum.
248  // UpdateTraj should have reduced the number of points fit
249  // as much as possible for this pass, so this trajectory is in trouble.
250  if(killPts == 0 && tj.Pts[lastPt].FitChi > tcc.maxChi && useMaxChiCut) {
251  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" bad FitChi "<<tj.Pts[lastPt].FitChi<<" cut "<<tcc.maxChi;
252  if(tcc.useAlg[kNewStpCuts]) {
253  // remove the last point before quitting
254  UnsetUsedHits(slc, tj.Pts[lastPt]);
255  SetEndPoints(tj);
256  }
257  tj.IsGood = (NumPtsWithCharge(slc, tj, true) > tcc.minPtsFit[tj.Pass]);
258  return;
259  }
260  // print the local tp unless we have killing to do
261  if(killPts == 0) {
262  if(tcc.dbgStp) {
263  if(tj.AlgMod[kRvPrp]) {
264  PrintTrajectory("RP", slc, tj, lastPt);
265  } else {
266  PrintTrajectory("SC", slc, tj, lastPt);
267  }
268  }
269  } else {
270  MaskTrajEndPoints(slc, tj, killPts);
271  if(!tj.IsGood) return;
272  unsigned int onWire = (float)(std::nearbyint(tj.Pts[lastPt].Pos[0]));
273  float nSteps = (float)(step - tj.Pts[lastPt - killPts].Step);
274  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"TRP killing "<<killPts<<" after "<<nSteps<<" steps from prev TP. Current tp.Pos "<<tp.Pos[0]<<" "<<tp.Pos[1];
275  // move the position
276  tj.Pts[lastPt].Pos[0] += nSteps * tj.Pts[lastPt].Dir[0];
277  tj.Pts[lastPt].Pos[1] += nSteps * tj.Pts[lastPt].Dir[1];
278  if(tj.Pts[lastPt].AngleCode == 0) {
279  // put the TP at the wire position prior to the move
280  float dw = onWire - tj.Pts[lastPt].Pos[0];
281  tj.Pts[lastPt].Pos[0] = onWire;
282  tj.Pts[lastPt].Pos[1] += dw * tj.Pts[lastPt].Dir[1] / tj.Pts[lastPt].Dir[0];
283  }
284  // check the MCSMom after we going
285  if(tj.Pts.size() > 20 && tj.Pass < tcc.minMCSMom.size() && tj.MCSMom < tcc.minMCSMom[tj.Pass]) break;
286  // copy to the local trajectory point
287  ltp.Pos = tj.Pts[lastPt].Pos;
288  ltp.Dir = tj.Pts[lastPt].Dir;
289  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" New ltp.Pos "<<ltp.Pos[0]<<" "<<ltp.Pos[1]<<" ticks "<<(int)ltp.Pos[1]/tcc.unitsPerTick;
290  if(!keepGoing) break;
291  }
292  } // step
293 
294  // Do a more carefull treatment
295  // This is the wrong place to do this.
296 // SetPDGCode(slc, tj, true);
297 
298  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"End StepAway with tj size "<<tj.Pts.size()<<" isGood = "<<tj.IsGood;
299 
300  } // StepAway
void PrintTrajectory(std::string someText, TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:5455
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MaskedHitsOK(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2710
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
void UpdateTraj(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:655
std::vector< float > maxPos0
Definition: DataStructs.h:489
std::vector< unsigned short > minPtsFit
Reconstruct in several passes.
Definition: DataStructs.h:482
void AddHits(TCSlice &slc, Trajectory &tj, unsigned short ipt, bool &sigOK)
Definition: StepUtils.cxx:1091
TCConfig tcc
Definition: DataStructs.cxx:6
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1162
void SetStrategy(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:303
float maxWireSkipWithSignal
max number of wires to skip with a signal on them
Definition: DataStructs.h:500
float TrajPointSeparation(TrajPoint &tp1, TrajPoint &tp2)
Definition: Utils.cxx:2368
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:1636
float DeadWireCount(TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:1881
bool doForecast
See TCMode_t above.
Definition: DataStructs.h:525
std::vector< unsigned short > maxAngleCode
max allowed angle code for each pass
Definition: DataStructs.h:484
const std::vector< std::string > StrategyBitNames
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
std::vector< float > maxPos1
Definition: DataStructs.h:490
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
use the slowing-down strategy
Definition: DataStructs.h:420
std::vector< short > minMCSMom
Min MCSMom for each pass.
Definition: DataStructs.h:485
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1840
bool dbg2V
debug 2D vertex finding
Definition: DataStructs.h:510
bool SignalAtTp(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:1814
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1660
void SetPDGCode(TCSlice &slc, unsigned short itj, bool tjDone)
Definition: Utils.cxx:3795
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
void GottaKink(TCSlice &slc, Trajectory &tj, unsigned short &killPts)
Definition: StepUtils.cxx:2842
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
bool StopIfBadFits(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2815
float maxWireSkipNoSignal
max number of wires to skip w/o a signal on them
Definition: DataStructs.h:499
std::vector< TjForecast > tjfs
Definition: DataStructs.cxx:7
bool AttachTrajToVertex(TCSlice &slc, Trajectory &tj, VtxStore &vx, bool prt)
Definition: TCVertex.cxx:1893
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
float VLAStepSize
Definition: DataStructs.h:502
std::vector< short > muonTag
min length and min MCSMom for a muon tag
Definition: DataStructs.h:471
void Forecast(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:404
geo::PlaneID DecodeCTP(CTP_t CTP)
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
unsigned short TPNearVertex(TCSlice &slc, const TrajPoint &tp)
Definition: TCVertex.cxx:1816
void MaskTrajEndPoints(TCSlice &slc, Trajectory &tj, unsigned short nPts)
Definition: StepUtils.cxx:3887
void PrintTrajPoint(std::string someText, TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, TrajPoint const &tp)
Definition: Utils.cxx:5541
void tca::StitchPFPs ( )

Definition at line 16 of file PFPUtils.cxx.

References tca::TCConfig::dbgStitch, debug, DotProd(), evd::details::end(), tca::TCConfig::geom, GetSliceIndex(), InsideFV(), geo::GeometryCore::NTPC(), tca::TCConfig::pfpStitchCuts, PosSep2(), PrintP(), ReversePFP(), tca::DebugStuff::Slice, slices, tcc, and tmp.

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

17  {
18  // Stitch PFParticles in different TPCs. This does serious damage to PFPStruct and should
19  // only be called from TrajCluster module just before making PFParticles to put in the event
20  if(slices.size() < 2) return;
21  if(tcc.geom->NTPC() == 1) return;
22  if(tcc.pfpStitchCuts.size() < 2) return;
23  if(tcc.pfpStitchCuts[0] <= 0) return;
24 
25  bool prt = tcc.dbgStitch;
26 
27  if(prt) {
28  mf::LogVerbatim myprt("TC");
29  std::string fcnLabel = "SP";
30  myprt<<fcnLabel<<" cuts "<<sqrt(tcc.pfpStitchCuts[0])<<" "<<tcc.pfpStitchCuts[1]<<"\n";
31  bool printHeader = true;
32  for(size_t isl = 0; isl < slices.size(); ++isl) {
33  if(debug.Slice >= 0 && int(isl) != debug.Slice) continue;
34  auto& slc = slices[isl];
35  if(slc.pfps.empty()) continue;
36  for(auto& pfp : slc.pfps) PrintP(fcnLabel, myprt, pfp, printHeader);
37  } // slc
38  } // prt
39 
40  // lists of pfp UIDs to stitch
41  std::vector<std::vector<int>> stLists;
42  for(unsigned short sl1 = 0; sl1 < slices.size() - 1; ++sl1) {
43  auto& slc1 = slices[sl1];
44  for(unsigned short sl2 = sl1 + 1; sl2 < slices.size(); ++sl2) {
45  auto& slc2 = slices[sl2];
46  // look for PFParticles in the same recob::Slice
47  if(slc1.ID != slc2.ID) continue;
48  for(auto& p1 : slc1.pfps) {
49  if(p1.ID <= 0) continue;
50  // Can't stitch shower PFPs
51  if(p1.PDGCode == 1111) continue;
52  for(auto& p2 : slc2.pfps) {
53  if(p2.ID <= 0) continue;
54  // Can't stitch shower PFPs
55  if(p2.PDGCode == 1111) continue;
56  float maxSep2 = tcc.pfpStitchCuts[0];
57  float maxCth = tcc.pfpStitchCuts[1];
58  bool gotit = false;
59  for(unsigned short e1 = 0; e1 < 2; ++e1) {
60  auto& pos1 = p1.XYZ[e1];
61  // require the end to be close to a TPC boundary
62  if(InsideFV(slc1, p1, e1)) continue;
63  auto& dir1 = p1.Dir[e1];
64  for(unsigned short e2 = 0; e2 < 2; ++e2) {
65  auto& pos2 = p2.XYZ[e2];
66  // require the end to be close to a TPC boundary
67  if(InsideFV(slc2, p2, e2)) continue;
68  auto& dir2 = p2.Dir[e2];
69  float sep = PosSep2(pos1, pos2);
70  if(sep > maxSep2) continue;
71  float cth = std::abs(DotProd(dir1, dir2));
72  if(cth < maxCth) continue;
73  maxSep2 = sep;
74  maxCth = cth;
75  gotit = true;
76  } // e2
77  } // e1
78  if(!gotit) continue;
79  if(prt) {
80  mf::LogVerbatim myprt("TC");
81  myprt<<"Stitch slice "<<slc1.ID<<" P"<<p1.UID<<" TPC "<<p1.TPCID.TPC;
82  myprt<<" and P"<<p2.UID<<" TPC "<<p2.TPCID.TPC;
83  myprt<<" sep "<<sqrt(maxSep2)<<" maxCth "<<maxCth;
84  }
85  // see if either of these are in a list
86  bool added = false;
87  for(auto& pm : stLists) {
88  bool p1InList = (std::find(pm.begin(), pm.end(), p1.UID) != pm.end());
89  bool p2InList = (std::find(pm.begin(), pm.end(), p2.UID) != pm.end());
90  if(p1InList || p2InList) {
91  if(p1InList) pm.push_back(p2.UID);
92  if(p2InList) pm.push_back(p1.UID);
93  added = true;
94  }
95  } // pm
96  if(added) continue;
97  // start a new list
98  std::vector<int> tmp(2);
99  tmp[0] = p1.UID;
100  tmp[1] = p2.UID;
101  stLists.push_back(tmp);
102  break;
103  } // p2
104  } // p1
105  } // sl2
106  } // sl1
107  if(stLists.empty()) return;
108 
109  for(auto& stl : stLists) {
110  // Find the endpoints of the stitched pfp
111  float minZ = 1E6;
112  std::pair<unsigned short, unsigned short> minZIndx;
113  unsigned short minZEnd = 2;
114  for(auto puid : stl) {
115  auto slcIndex = GetSliceIndex("P", puid);
116  if(slcIndex.first == USHRT_MAX) continue;
117  auto& pfp = slices[slcIndex.first].pfps[slcIndex.second];
118  for(unsigned short end = 0; end < 2; ++end) {
119  if(pfp.XYZ[end][2] < minZ) { minZ = pfp.XYZ[end][2]; minZIndx = slcIndex; minZEnd = end; }
120  } // end
121  } // puid
122  if(minZEnd > 1) continue;
123  // preserve the pfp with the min Z position
124  auto& pfp = slices[minZIndx.first].pfps[minZIndx.second];
125  if(prt) mf::LogVerbatim("TC")<<"SP: P"<<pfp.UID;
126  // reverse it if necessary
127  if(minZEnd != 0) ReversePFP(slices[minZIndx.first], pfp);
128  // add the Tjs in the other slices to it
129  for(auto puid : stl) {
130  if(puid == pfp.UID) continue;
131  auto sIndx = GetSliceIndex("P", puid);
132  if(sIndx.first == USHRT_MAX) continue;
133  auto& opfp = slices[sIndx.first].pfps[sIndx.second];
134  if(prt) mf::LogVerbatim("TC")<<" +P"<<opfp.UID;
135  pfp.TjUIDs.insert(pfp.TjUIDs.end(), opfp.TjUIDs.begin(), opfp.TjUIDs.end());
136  if(prt) mf::LogVerbatim();
137  // Check for parents and daughters
138  if(opfp.ParentUID > 0) {
139  auto pSlcIndx = GetSliceIndex("P", opfp.ParentUID);
140  if(pSlcIndx.first < slices.size()) {
141  auto& parpfp = slices[pSlcIndx.first].pfps[pSlcIndx.second];
142  std::replace(parpfp.DtrUIDs.begin(), parpfp.DtrUIDs.begin(), opfp.UID, pfp.UID);
143  } // valid pSlcIndx
144  } // has a parent
145  for(auto dtruid : opfp.DtrUIDs) {
146  auto dSlcIndx = GetSliceIndex("P", dtruid);
147  if(dSlcIndx.first < slices.size()) {
148  auto& dtrpfp = slices[dSlcIndx.first].pfps[dSlcIndx.second];
149  dtrpfp.ParentUID = pfp.UID;
150  } // valid dSlcIndx
151  } // dtruid
152  // declare it obsolete
153  opfp.ID = 0;
154  } // puid
155  } // stl
156 
157  } // StitchPFPs
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool dbgStitch
debug PFParticle stitching
Definition: DataStructs.h:520
TCConfig tcc
Definition: DataStructs.cxx:6
void PrintP(std::string someText, mf::LogVerbatim &myprt, PFPStruct &pfp, bool &printHeader)
Definition: Utils.cxx:4876
Float_t tmp
Definition: plot.C:37
DebugStuff debug
Definition: DebugStruct.cxx:4
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1660
const geo::GeometryCore * geom
Definition: DataStructs.h:493
std::vector< TCSlice > slices
Definition: DataStructs.cxx:10
unsigned int NTPC(unsigned int cstat=0) const
Returns the total number of TPCs in the specified cryostat.
bool InsideFV(TCSlice &slc, PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:2810
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:59
std::vector< float > pfpStitchCuts
cuts for stitching between TPCs
Definition: DataStructs.h:480
void ReversePFP(TCSlice &slc, PFPStruct &pfp)
Definition: PFPUtils.cxx:2935
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:4496
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool tca::StopIfBadFits ( TCSlice slc,
Trajectory tj 
)

Definition at line 2815 of file StepUtils.cxx.

References tca::TCConfig::dbgStp, tca::Trajectory::EndPt, tca::Trajectory::MCSMom, tca::Trajectory::PDGCode, tca::Trajectory::Pts, and tcc.

Referenced by StepAway().

2816  {
2817  // Returns true if there are a number of Tps that were not used in the trajectory because the fit was poor and the
2818  // charge pull is not really high. This
2819 
2820  // don't consider muons
2821  if(tj.PDGCode == 13) return false;
2822  // or long straight Tjs
2823  if(tj.Pts.size() > 40 && tj.MCSMom > 200) return false;
2824 
2825  unsigned short nBadFit = 0;
2826  unsigned short nHiChg = 0;
2827  unsigned short cnt = 0;
2828  for(unsigned short ipt = tj.Pts.size() - 1; ipt > tj.EndPt[1]; --ipt ) {
2829  if(tj.Pts[ipt].FitChi > 2) ++nBadFit;
2830  if(tj.Pts[ipt].ChgPull > 3) ++nHiChg;
2831  ++cnt;
2832  if(cnt == 5) break;
2833  } // ipt
2834 
2835  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"StopIfBadFits: nBadFit "<<nBadFit<<" nHiChg "<<nHiChg;
2836  if(nBadFit > 3 && nHiChg == 0) return true;
2837  return false;
2838 
2839  } // StopIfBadFits
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
bool tca::StorePFP ( TCSlice slc,
PFPStruct pfp 
)

Definition at line 2749 of file PFPUtils.cxx.

References tca::PFPStruct::BestPlane, evt, FilldEdx(), tca::TCEvent::globalPFPID, tca::PFPStruct::ID, kMat3D, tca::PFPStruct::NeedsUpdate, tca::PFPStruct::PDGCode, tca::TCSlice::pfps, ReverseTraj(), tca::PFPStruct::TjIDs, tca::TCSlice::tjs, tca::PFPStruct::Tp3s, and tca::PFPStruct::UID.

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

2750  {
2751  // stores the PFParticle in TJStuff
2752  if(pfp.ID < int(slc.pfps.size())) return false;
2753  bool neutrinoPFP = pfp.PDGCode == 12 || pfp.PDGCode == 14;
2754  if(!neutrinoPFP) {
2755  if(pfp.TjIDs.empty()) return false;
2756  if(pfp.PDGCode != 1111 && pfp.Tp3s.size() < 2) return false;
2757  }
2758  // check the ID and correct it if it is wrong
2759  if(pfp.ID != (int)slc.pfps.size() + 1) pfp.ID = slc.pfps.size() + 1;
2760  ++evt.globalPFPID;
2761  pfp.UID = evt.globalPFPID;
2762  // check the Tjs and set the 3D match flag
2763  for(auto tjid : pfp.TjIDs) {
2764  auto& tj = slc.tjs[tjid - 1];
2765  if(tj.AlgMod[kMat3D]) return false;
2766  tj.AlgMod[kMat3D] = true;
2767  } // tjid
2768 
2769  if(!pfp.Tp3s.empty()) {
2770  // ensure that the Tj points are in increasing order and reverse them if they aren't. This
2771  // presumes that the space points have been ordered from pfp start to pfp end
2772  std::vector<int> tjids;
2773  // list of tj points to check for increasing (or decreasing) order
2774  std::vector<short> firstIpt;
2775  std::vector<short> lastIpt;
2776  for(auto& Tp3 : pfp.Tp3s) {
2777  for(auto& tj2pt : Tp3.Tj2Pts) {
2778  int tjid = tj2pt.id;
2779  // check for the first occurrence
2780  unsigned short ii = 0;
2781  for(ii = 0; ii < tjids.size(); ++ii) if(tjid == tjids[ii]) break;
2782  if(ii < tjids.size()) {
2783  // exists in the list. Keep track of the last point
2784  lastIpt[ii] = tj2pt.ipt;
2785  continue;
2786  }
2787  tjids.push_back(tjid);
2788  firstIpt.push_back((short)tj2pt.ipt);
2789  lastIpt.push_back((short)tj2pt.ipt);
2790  } // tjpt
2791  } // spt
2792  // reverse Tjs if necessary so that end0 is at the start of the pfp
2793  for(unsigned short ii = 0; ii < tjids.size(); ++ii) {
2794  // ignore Tjs that aren't associated with this pfp
2795  if(std::find(pfp.TjIDs.begin(), pfp.TjIDs.end(), tjids[ii]) == pfp.TjIDs.end()) continue;
2796  auto& tj = slc.tjs[tjids[ii] - 1];
2797  if(lastIpt[ii] < firstIpt[ii]) ReverseTraj(slc, tj);
2798  } // ii
2799  } // Tp3s exist
2800 
2801  if(pfp.BestPlane < 0) FilldEdx(slc, pfp);
2802 
2803  if(pfp.NeedsUpdate) std::cout<<"StorePFP: stored P"<<pfp.ID<<" but NeedsUpdate is true...\n";
2804 
2805  slc.pfps.push_back(pfp);
2806  return true;
2807  } // StorePFP
void FilldEdx(TCSlice &slc, TrajPoint3 &tp3)
Definition: PFPUtils.cxx:1743
void ReverseTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:2751
TCEvent evt
Definition: DataStructs.cxx:5
bool tca::StoreShower ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct3D ss3 
)

Definition at line 4403 of file TCShower.cxx.

References tca::ShowerStruct3D::CotIDs, tca::TCSlice::cots, evt, tca::TCEvent::globalS3ID, tca::ShowerStruct3D::ID, tca::TCSlice::showers, ss, and tca::ShowerStruct3D::UID.

4404  {
4405  // Store a 3D shower. This function sets the 3S -> 2S assns using CotIDs and ensures
4406  // that the 2S -> 3S assns are OK.
4407 
4408  std::string fcnLabel = inFcnLabel + ".S3S";
4409  if(ss3.ID <= 0) {
4410  std::cout<<fcnLabel<<" Invalid ID";
4411  return false;
4412  }
4413  if(ss3.CotIDs.size() < 2) {
4414  std::cout<<fcnLabel<<" not enough CotIDs";
4415  return false;
4416  }
4417 
4418  // check the 2S -> 3S assns
4419  for(auto& ss : slc.cots) {
4420  if(ss.ID == 0) continue;
4421  if(ss.SS3ID == ss3.ID && std::find(ss3.CotIDs.begin(), ss3.CotIDs.end(), ss.ID) == ss3.CotIDs.end()) {
4422  std::cout<<fcnLabel<<" Bad assn: 2S"<<ss.ID<<" -> 3S"<<ss3.ID<<" but it's not inCotIDs.\n";
4423  return false;
4424  }
4425  } // ss
4426 
4427  // check the 3S -> 2S assns
4428  for(auto cid : ss3.CotIDs) {
4429  if(cid <= 0 || cid > (int)slc.cots.size()) return false;
4430  auto& ss = slc.cots[cid - 1];
4431  if(ss.SS3ID > 0 && ss.SS3ID != ss3.ID) {
4432  std::cout<<fcnLabel<<" Bad assn: 3S"<<ss3.ID<<" -> 2S"<<cid<<" but 2S -> 3S"<<ss.SS3ID<<"\n";
4433  return false;
4434  }
4435  } // cid
4436 
4437  // set the 2S -> 3S assns
4438  for(auto cid : ss3.CotIDs) slc.cots[cid - 1].SS3ID = ss3.ID;
4439 
4440  ++evt.globalS3ID;
4441  ss3.UID = evt.globalS3ID;
4442 
4443  slc.showers.push_back(ss3);
4444  return true;
4445 
4446  } // StoreShower
Float_t ss
Definition: plot.C:23
TCEvent evt
Definition: DataStructs.cxx:5
bool tca::StoreShower ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct ss 
)

Definition at line 4449 of file TCShower.cxx.

References tca::Trajectory::AlgMod, tca::TCSlice::cots, evt, tca::TCEvent::globalS2ID, tca::Trajectory::ID, tca::ShowerStruct::ID, kShwrParent, tca::ShowerStruct::ParentID, tca::Trajectory::SSID, tca::ShowerStruct::TjIDs, tca::TCSlice::tjs, and tca::ShowerStruct::UID.

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

4450  {
4451  // Store a ShowerStruct
4452  std::string fcnLabel = inFcnLabel + ".S2S";
4453  if(ss.ID <= 0) {
4454  std::cout<<fcnLabel<<" Invalid ID";
4455  return false;
4456  }
4457  if(ss.TjIDs.empty()) {
4458  std::cout<<fcnLabel<<" Fail: No TjIDs in 2S"<<ss.ID<<"\n";
4459  return false;
4460  }
4461  if(ss.ParentID > 0) {
4462  if(ss.ParentID > (int)slc.tjs.size()) {
4463  std::cout<<fcnLabel<<" Fail: 2S"<<ss.ID<<" has an invalid ParentID T"<<ss.ParentID<<"\n";
4464  return false;
4465  }
4466  if(std::find(ss.TjIDs.begin(), ss.TjIDs.end(), ss.ParentID) != ss.TjIDs.end()) {
4467  std::cout<<fcnLabel<<" Fail: 2S"<<ss.ID<<" ParentID is not in TjIDs.\n";
4468  return false;
4469  }
4470  } // ss.ParentID > 0
4471 
4472  // check the ID
4473  if(ss.ID != (int)slc.cots.size() + 1) {
4474  std::cout<<fcnLabel<<" Correcting the ID 2S"<<ss.ID<<" -> 2S"<<slc.cots.size() + 1;
4475  ss.ID = slc.cots.size() + 1;
4476  }
4477 
4478  // set the tj shower bits
4479  for(auto& tjID : ss.TjIDs) {
4480  Trajectory& tj = slc.tjs[tjID - 1];
4481  tj.SSID = ss.ID;
4482  tj.AlgMod[kShwrParent] = false;
4483  if(tj.ID == ss.ParentID) tj.AlgMod[kShwrParent] = true;
4484  } // tjID
4485 
4486  ++evt.globalS2ID;
4487  ss.UID = evt.globalS2ID;
4488 
4489  slc.cots.push_back(ss);
4490  return true;
4491 
4492  } // StoreShower
Float_t ss
Definition: plot.C:23
TCEvent evt
Definition: DataStructs.cxx:5
bool tca::StoreTraj ( TCSlice slc,
Trajectory tj 
)

Definition at line 1175 of file Utils.cxx.

References AlgBitNames, tca::Trajectory::AlgMod, tca::TCConfig::dbgSlc, debug, tca::Trajectory::DirFOM, tca::Trajectory::EndPt, evt, tca::TCEvent::globalTjID, tca::DebugStuff::Hit, tca::Trajectory::ID, kDebug, tca::TCConfig::modes, tca::Trajectory::ParentID, PrintHit(), tca::Trajectory::Pts, ReleaseHits(), SetEndPoints(), tca::TCSlice::slHits, tca::Trajectory::StepDir, tcc, TjDirFOM(), tca::TCSlice::tjs, tca::Trajectory::UID, UpdateTjChgProperties(), and tca::Trajectory::WorkID.

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

1176  {
1177 
1178  if(!(tj.StepDir == 1 || tj.StepDir == -1)) {
1179  mf::LogError("TC")<<"StoreTraj: Invalid StepDir "<<tj.StepDir;
1180  return false;
1181  }
1182 
1183  if(slc.tjs.size() >= USHRT_MAX) {
1184  mf::LogError("TC")<<"StoreTraj: Too many trajectories "<<slc.tjs.size();
1185  return false;
1186  }
1187 
1188  // This shouldn't be necessary but do it anyway
1189  SetEndPoints(tj);
1190 
1191  if(tj.EndPt[1] <= tj.EndPt[0]) return false;
1192  if(tj.EndPt[1] > tj.Pts.size()) return false;
1193  unsigned short npts = tj.EndPt[1] - tj.EndPt[0] + 1;
1194  if(npts < 2) return false;
1195 
1196  auto& endTp0 = tj.Pts[tj.EndPt[0]];
1197  auto& endTp1 = tj.Pts[tj.EndPt[1]];
1198 
1199  // Calculate the charge near the end and beginning if necessary. This must be a short
1200  // trajectory. Find the average using 4 points
1201  if(endTp0.AveChg <= 0) {
1202  unsigned short cnt = 0;
1203  float sum = 0;
1204  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1205  if(tj.Pts[ipt].Chg == 0) continue;
1206  sum += tj.Pts[ipt].Chg;
1207  ++cnt;
1208  if(cnt == 4) break;
1209  }
1210  tj.Pts[tj.EndPt[0]].AveChg = sum / (float)cnt;
1211  }
1212  if(endTp1.AveChg <= 0 && npts < 5) endTp1.AveChg = endTp0.AveChg;
1213  if(endTp1.AveChg <= 0) {
1214  float sum = 0;
1215  unsigned short cnt = 0;
1216  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
1217  short ipt = tj.EndPt[1] - ii;
1218  if(ipt < 0) break;
1219  if(tj.Pts[ipt].Chg == 0) continue;
1220  sum += tj.Pts[ipt].Chg;
1221  ++cnt;
1222  if(cnt == 4) break;
1223  if(ipt == 0) break;
1224  } // ii
1225  tj.Pts[tj.EndPt[1]].AveChg = sum / (float)cnt;
1226  } // begin charge == end charge
1227 
1228 
1229  tj.DirFOM = TjDirFOM(slc, tj, false);
1230  UpdateTjChgProperties("ST", slc, tj, false);
1231 
1232  int trID = slc.tjs.size() + 1;
1233 
1234  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1235  for(unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
1236  if(tj.Pts[ipt].UseHit[ii]) {
1237  unsigned int iht = tj.Pts[ipt].Hits[ii];
1238  if(iht > slc.slHits.size() - 1) {
1239  std::cout<<"StoreTraj bad iht "<<iht<<" slHits size "<<slc.slHits.size()<<" tj.ID "<<tj.ID<<"\n";
1240  ReleaseHits(slc, tj);
1241  return false;
1242  }
1243  if(slc.slHits[iht].InTraj > 0) {
1244  std::cout<<"StoreTraj fail "<<iht<<" "<<slc.slHits[iht].InTraj<<" WorkID "<<tj.WorkID<<" InTraj "<<slc.slHits[iht].InTraj;
1245  std::cout<<" algs ";
1246  for(unsigned short ib = 0; ib < AlgBitNames.size(); ++ib) if(tj.AlgMod[ib]) std::cout<<" "<<AlgBitNames[ib];
1247  std::cout<<"\n";
1248  ReleaseHits(slc, tj);
1249  return false;
1250  } // error
1251  slc.slHits[iht].InTraj = trID;
1252  }
1253  } // ii
1254  } // ipt
1255 
1256  // ensure that inTraj is clean for the ID
1257  for(unsigned int iht = 0; iht < slc.slHits.size(); ++iht) {
1258  if(slc.slHits[iht].InTraj == tj.ID) {
1259  mf::LogWarning("TC")<<"StoreTraj: Hit "<<PrintHit(slc.slHits[iht])<<" thinks it belongs to T"<<tj.ID<<" but it isn't in the Tj\n";
1260 // PrintTrajectory("ST", tjs, tj, USHRT_MAX);
1261  return false;
1262  }
1263  } // iht
1264 
1265  tj.WorkID = tj.ID;
1266  tj.ID = trID;
1267  // increment the global ID
1268  ++evt.globalTjID;
1269  tj.UID = evt.globalTjID;
1270  // Don't clobber the ParentID if it was defined by the calling function
1271  if(tj.ParentID == 0) tj.ParentID = trID;
1272  slc.tjs.push_back(tj);
1273  if(tcc.modes[kDebug] && tcc.dbgSlc && debug.Hit != UINT_MAX) {
1274  // print some debug info
1275  for(unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) {
1276  for(unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
1277  unsigned int iht = tj.Pts[ipt].Hits[ii];
1278  if(slc.slHits[iht].allHitsIndex == debug.Hit) std::cout<<"Debug hit appears in trajectory w WorkID "<<tj.WorkID<<" UseHit "<<tj.Pts[ipt].UseHit[ii]<<"\n";
1279  } // ii
1280  } // ipt
1281  } // debug.Hit ...
1282 
1283  return true;
1284 
1285  } // StoreTraj
void ReleaseHits(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:1150
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
float TjDirFOM(TCSlice &slc, const Trajectory &tj, bool prt)
Definition: Utils.cxx:986
const std::vector< std::string > AlgBitNames
Definition: DataStructs.cxx:13
TCConfig tcc
Definition: DataStructs.cxx:6
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:507
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
unsigned int Hit
set to the hit index in evt.allHits if a Plane:Wire:Tick match is found
Definition: DebugStruct.h:25
DebugStuff debug
Definition: DebugStruct.cxx:4
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:5704
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3196
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:524
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
TCEvent evt
Definition: DataStructs.cxx:5
master switch for turning on debug mode
Definition: DataStructs.h:449
bool tca::StoreVertex ( TCSlice slc,
VtxStore vx 
)

Definition at line 2093 of file TCVertex.cxx.

References tca::VtxStore::CTP, evt, tca::TCEvent::globalS2ID, tca::VtxStore::ID, kKilled, tca::VtxStore::NTraj, tca::TCSlice::tjs, tca::VtxStore::Topo, tca::VtxStore::UID, and tca::TCSlice::vtxs.

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

2094  {
2095  // jacket around the push to ensure that the Tj and vtx CTP is consistent.
2096  // The calling function should score the vertex after the trajectories are attached
2097 
2098  if(vx.ID != int(slc.vtxs.size() + 1)) {
2099  mf::LogVerbatim("TC")<<"StoreVertex: Invalid ID "<<vx.ID<<" It should be "<<slc.vtxs.size() + 1;
2100  return false;
2101  }
2102 
2103  ++evt.globalS2ID;
2104  vx.UID = evt.globalS2ID;
2105 
2106  unsigned short nvxtj = 0;
2107  unsigned short nok = 0;
2108  for(auto& tj : slc.tjs) {
2109  if(tj.AlgMod[kKilled]) continue;
2110  if(vx.ID == tj.VtxID[0] || vx.ID == tj.VtxID[1]) ++nvxtj;
2111  if(vx.CTP != tj.CTP) continue;
2112  if(vx.ID == tj.VtxID[0] || vx.ID == tj.VtxID[1]) ++nok;
2113  } // tj
2114 
2115  if(nok != nvxtj) {
2116  mf::LogVerbatim("TC")<<"StoreVertex: vertex "<<vx.ID<<" Topo "<<vx.Topo<<" has inconsistent CTP code "<<vx.CTP<<" with one or more Tjs\n";
2117  for(auto& tj : slc.tjs) {
2118  if(tj.AlgMod[kKilled]) continue;
2119  if(tj.VtxID[0] == vx.ID) tj.VtxID[0] = 0;
2120  if(tj.VtxID[1] == vx.ID) tj.VtxID[1] = 0;
2121  }
2122  return false;
2123  }
2124  vx.NTraj = nok;
2125  slc.vtxs.push_back(vx);
2126  return true;
2127 
2128  } // StoreVertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCEvent evt
Definition: DataStructs.cxx:5
void tca::TagDeltaRays ( TCSlice slc,
const CTP_t inCTP 
)

Definition at line 3065 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::CTP, tca::TCConfig::dbgDeltaRayTag, tca::TCConfig::dbgSlc, DeltaAngle(), tca::TCConfig::deltaRayTag, tca::Trajectory::EndPt, tca::Trajectory::ID, kDeltaRay, kHaloTj, tca::TCConfig::kinkCuts, kKilled, tca::Trajectory::MCSMom, tca::Trajectory::ParentID, tca::Trajectory::PDGCode, PointTrajDOCA(), PosSep(), PrintPos(), tca::Trajectory::Pts, ReverseTraj(), tca::Trajectory::StepDir, tcc, tca::TCSlice::tjs, TrajTrajDOCA(), tca::TCConfig::useAlg, and tca::TCConfig::vtx2DCuts.

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

3066  {
3067  // DeltaRayTag vector elements
3068  // [0] = max separation of both endpoints from a muon
3069  // [1] = minimum MCSMom
3070  // [2] = maximum MCSMom
3071 
3072  if(!tcc.useAlg[kDeltaRay]) return;
3073  if(tcc.deltaRayTag[0] < 0) return;
3074  if(tcc.deltaRayTag.size() < 3) return;
3075 
3076  bool prt = (tcc.dbgDeltaRayTag && tcc.dbgSlc);
3077 
3078  // double the user-defined separation cut. We will require that at least one of the ends of
3079  // a delta ray be within the user-defined cut and allow
3080  float maxSep = 2 * tcc.deltaRayTag[0];
3081  float maxMinSep = tcc.deltaRayTag[0];
3082  unsigned short minMom = tcc.deltaRayTag[1];
3083  unsigned short maxMom = tcc.deltaRayTag[2];
3084  unsigned short minMuonLength = 2 * tcc.vtx2DCuts[2];
3085  unsigned short minpts = 4;
3086  if(prt) mf::LogVerbatim("TC")<<"TagDeltaRays: maxSep "<<maxSep<<" maxMinSep "<<maxMinSep<<" Mom range "<<minMom<<" to "<<maxMom<<" minpts "<<minpts;
3087 
3088  for(unsigned short itj = 0; itj < slc.tjs.size(); ++itj) {
3089  Trajectory& muTj = slc.tjs[itj];
3090  if(muTj.CTP != inCTP) continue;
3091  if(muTj.AlgMod[kKilled] || muTj.AlgMod[kHaloTj]) continue;
3092  if(muTj.PDGCode != 13) continue;
3093  if(prt) mf::LogVerbatim("TC")<<"TagDeltaRays: Muon T"<<muTj.ID<<" EndPts "<<PrintPos(slc, muTj.Pts[muTj.EndPt[0]])<<"-"<<PrintPos(slc, muTj.Pts[muTj.EndPt[1]]);
3094  // min length
3095  if(muTj.EndPt[1] - muTj.EndPt[0] < minMuonLength) continue;
3096  auto& mtp0 = muTj.Pts[muTj.EndPt[0]];
3097  auto& mtp1 = muTj.Pts[muTj.EndPt[1]];
3098  // Found a muon, now look for delta rays
3099  for(unsigned short jtj = 0; jtj < slc.tjs.size(); ++jtj) {
3100  if(jtj == itj) continue;
3101  Trajectory& dtj = slc.tjs[jtj];
3102  if(dtj.AlgMod[kKilled] || dtj.AlgMod[kHaloTj]) continue;
3103  if(dtj.CTP != inCTP) continue;
3104  if(dtj.PDGCode == 13) continue;
3105  // MCSMom cut
3106  if(dtj.MCSMom < minMom) continue;
3107  if(dtj.MCSMom > maxMom) continue;
3108  if(dtj.EndPt[1] - dtj.EndPt[0] < minpts) continue;
3109  // some rough cuts to require that the delta ray is within the
3110  // ends of the muon
3111  auto& dtp0 = dtj.Pts[dtj.EndPt[0]];
3112  auto& dtp1 = dtj.Pts[dtj.EndPt[1]];
3113  if(muTj.StepDir > 0) {
3114  if(dtp0.Pos[0] < mtp0.Pos[0]) continue;
3115  if(dtp1.Pos[0] > mtp1.Pos[0]) continue;
3116  } else {
3117  if(dtp0.Pos[0] > mtp0.Pos[0]) continue;
3118  if(dtp1.Pos[0] < mtp1.Pos[0]) continue;
3119  }
3120  // find the minimum separation
3121  float doca = maxMinSep;
3122  unsigned short mpt = 0;
3123  unsigned short dpt = 0;
3124  TrajTrajDOCA(slc, muTj, dtj, mpt, dpt, doca, false);
3125  if(doca == maxMinSep) continue;
3126  auto& dTp = dtj.Pts[dpt];
3127  // cut on the distance from the muon ends
3128  if(PosSep(dTp.Pos, mtp0.Pos) < tcc.vtx2DCuts[2]) continue;
3129  if(PosSep(dTp.Pos, mtp1.Pos) < tcc.vtx2DCuts[2]) continue;
3130  // make an angle cut at this point. A delta-ray should have a small angle
3131  float dang = DeltaAngle(muTj.Pts[mpt].Ang, dtj.Pts[dpt].Ang);
3132  if(prt) mf::LogVerbatim("TC")<<" dRay? T"<<dtj.ID<<" at "<<PrintPos(slc, dtj.Pts[dpt].Pos)<<" dang "<<dang<<" doca "<<doca;
3133  // ignore the angle cut if the separation is small and the delta ray MCSMom is low
3134  bool closeDeltaRay = (doca < 2 && dtj.MCSMom < 20);
3135  if(!closeDeltaRay && dang > tcc.kinkCuts[0]) continue;
3136  unsigned short oend = 0;
3137  // check the delta at the end of the delta-ray that is farthest away from the
3138  // closest point
3139  if(dpt > 0.5 * (dtj.EndPt[0] + dtj.EndPt[1])) oend = 1;
3140  auto& farEndTP = dtj.Pts[dtj.EndPt[oend]];
3141  float farEndDelta = PointTrajDOCA(slc, farEndTP.Pos[0], farEndTP.Pos[1], muTj.Pts[mpt]);
3142  if(prt) mf::LogVerbatim("TC")<<" farEnd "<<PrintPos(slc, farEndTP.Pos)<<" farEndDelta "<<farEndDelta;
3143  if(farEndDelta > maxSep) continue;
3144  if(prt) mf::LogVerbatim("TC")<<" delta ray "<<dtj.ID<<" parent -> "<<muTj.ID;
3145  dtj.ParentID = muTj.ID;
3146  dtj.PDGCode = 11;
3147  dtj.AlgMod[kDeltaRay] = true;
3148  // Set the start of the delta-ray to be end 0
3149  if(oend != 1) ReverseTraj(slc, dtj);
3150  } // jtj
3151  } // itj
3152 
3153  } // TagDeltaRays
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< float > kinkCuts
kink angle, nPts fit, (alternate) kink angle significance
Definition: DataStructs.h:475
float PosSep(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2353
TCConfig tcc
Definition: DataStructs.cxx:6
bool TrajTrajDOCA(TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep, bool considerDeadWires)
Definition: Utils.cxx:2181
bool dbgDeltaRayTag
Definition: DataStructs.h:516
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:507
float PointTrajDOCA(TCSlice &slc, float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2280
std::string PrintPos(TCSlice &slc, const Point2_t &pos)
Definition: Utils.cxx:5718
void ReverseTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:2751
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
std::vector< short > deltaRayTag
min length, min MCSMom and min separation (WSE) for a delta ray tag
Definition: DataStructs.h:470
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:466
double DeltaAngle(double Ang1, double Ang2)
Definition: Utils.cxx:2858
void tca::TagJunkTj ( TCSlice slc,
Trajectory tj,
bool  prt 
)

Definition at line 2442 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::ID, kJunkTj, kNewStpCuts, tca::Trajectory::PDGCode, tca::Trajectory::Pts, tcc, and tca::TCConfig::useAlg.

Referenced by CheckTraj().

2443  {
2444  // Characterizes the trajectory as a junk tj even though it may not
2445  // have been reconstructed in FindJunkTraj. The distinguishing feature is
2446  // that it is short and has many used hits in each trajectory point.
2447 
2448  // Don't bother if it is too long
2449  if(tj.Pts.size() > 10) return;
2450  if(tcc.useAlg[kNewStpCuts] && tj.PDGCode == 111) return;
2451  // count the number of points that have many used hits
2452  unsigned short nhm = 0;
2453  unsigned short npwc = 0;
2454  for(auto& tp : tj.Pts) {
2455  if(tp.Chg == 0) continue;
2456  ++npwc;
2457  unsigned short nused = 0;
2458  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2459  if(tp.UseHit[ii]) ++nused;
2460  } // ii
2461  if(nused > 3) ++nhm;
2462  } // tp
2463  // Set the junkTj bit if most of the hits are used in most of the tps
2464  if(nhm > 0.5 * npwc) tj.AlgMod[kJunkTj] = true;
2465  if(prt) mf::LogVerbatim("TC")<<"TGT: T"<<tj.ID<<" npwc "<<npwc<<" nhm "<<nhm<<" junk? "<<tj.AlgMod[kJunkTj];
2466  } // TagJunkTj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:6
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
void tca::TagShowerLike ( std::string  inFcnLabel,
TCSlice slc,
const CTP_t inCTP 
)

Definition at line 3631 of file TCShower.cxx.

References evd::details::begin(), tca::TCConfig::chargeCuts, tca::DebugStuff::CTP, tca::TCConfig::dbg2S, tca::TCConfig::dbgSlc, debug, evd::details::end(), tca::Trajectory::EndPt, FarEnd(), GetAssns(), tca::Trajectory::ID, tca::TCSlice::ID, kBragg, kHaloTj, kKilled, kShowerLike, kShowerTj, MakeVertexObsolete(), NumPtsWithCharge(), PosSep(), tca::Trajectory::Pts, tca::TCConfig::showerTag, tcc, tca::TCSlice::tjs, TrajTrajDOCA(), and tca::TCSlice::vtxs.

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

3632  {
3633  // Tag Tjs as InShower if they have MCSMom < ShowerTag[1] and there are more than
3634  // ShowerTag[6] other Tjs with a separation < ShowerTag[2].
3635 
3636  if(tcc.showerTag[0] <= 0) return;
3637  if(slc.tjs.size() > 20000) return;
3638  // evaluate different cuts
3639  bool newCuts = (tcc.showerTag[0] > 2);
3640  float typicalChgRMS = 0.5 * (tcc.chargeCuts[1] + tcc.chargeCuts[2]);
3641 
3642  bool prt = (tcc.dbgSlc && tcc.dbg2S && inCTP == debug.CTP);
3643 
3644  // clear out old tags and make a list of Tjs to consider
3645  std::vector<std::vector<int>> tjLists;
3646  std::vector<int> tjids;
3647  for(auto& tj : slc.tjs) {
3648  if(tj.CTP != inCTP) continue;
3649  if(tj.AlgMod[kKilled]) continue;
3650  if(tj.AlgMod[kHaloTj]) continue;
3651  tj.AlgMod[kShowerLike] = false;
3652  if(tj.AlgMod[kShowerTj]) continue;
3653  // ignore Tjs with Bragg peaks
3654  bool skipit = false;
3655  for(unsigned short end = 0; end < 2; ++end) if(tj.StopFlag[end][kBragg]) skipit = true;
3656  if(skipit) continue;
3657  short npwc = NumPtsWithCharge(slc, tj, false);
3658  if(newCuts) {
3659  // evaluate different cuts
3660  // Don't expect any (primary) electron to be reconstructed as a single trajectory for
3661  // more than ~2 radiation lengths ~ 30 cm for uB ~ 100 wires
3662  if(npwc > 100) continue;
3663  // allow short Tjs.
3664  if(npwc > 5) {
3665  // Increase the MCSMom cut if the Tj is long and the charge RMS is high to reduce sensitivity
3666  // to the fcl configuration. A primary electron may be reconstructed as one long Tj with large
3667  // charge rms and possibly high MCSMom or as several nearby shorter Tjs with lower charge rms
3668  float momCut = tcc.showerTag[1];
3669  if(tj.ChgRMS > typicalChgRMS) momCut *= tj.ChgRMS / typicalChgRMS;
3670  if(tj.MCSMom > momCut) continue;
3671  }
3672  } else {
3673  if(npwc < 3) continue;
3674  if(npwc > 4 && tj.MCSMom > tcc.showerTag[1]) continue;
3675  }
3676  tjids.push_back(tj.ID);
3677  } // tj
3678 
3679  if(tjids.size() < 2) return;
3680 
3681  for(unsigned short it1 = 0; it1 < tjids.size() - 1; ++it1) {
3682  Trajectory& tj1 = slc.tjs[tjids[it1] - 1];
3683  float len1 = PosSep(tj1.Pts[tj1.EndPt[1]].Pos, tj1.Pts[tj1.EndPt[0]].Pos);
3684  for(unsigned short it2 = it1 + 1; it2 < tjids.size(); ++it2) {
3685  Trajectory& tj2 = slc.tjs[tjids[it2] - 1];
3686  unsigned short ipt1, ipt2;
3687  float doca = tcc.showerTag[2];
3688  // Find the separation between Tjs without considering dead wires
3689  TrajTrajDOCA(slc, tj1, tj2, ipt1, ipt2, doca, false);
3690  if(doca == tcc.showerTag[2]) continue;
3691  // make tighter cuts for user-defined short Tjs
3692  float len2 = PosSep(tj2.Pts[tj2.EndPt[1]].Pos, tj2.Pts[tj2.EndPt[0]].Pos);
3693  if(!newCuts) {
3694  if(len1 < len2 && len1 < doca) {
3695  if(len1 < doca) continue;
3696  } else {
3697  if(len2 < doca) continue;
3698  }
3699  } // !newCuts
3700  // found a close pair. See if one of these is in an existing cluster of Tjs
3701  bool inlist = false;
3702  for(unsigned short it = 0; it < tjLists.size(); ++it) {
3703  bool tj1InList = (std::find(tjLists[it].begin(), tjLists[it].end(), tj1.ID) != tjLists[it].end());
3704  bool tj2InList = (std::find(tjLists[it].begin(), tjLists[it].end(), tj2.ID) != tjLists[it].end());
3705  if(tj1InList || tj2InList) {
3706  // add the one that is not in the list
3707  if(!tj1InList) tjLists[it].push_back(tj1.ID);
3708  if(!tj2InList) tjLists[it].push_back(tj2.ID);
3709  inlist = true;
3710  break;
3711  }
3712  if(inlist) break;
3713  } // it
3714  // start a new list with this pair?
3715  if(!inlist) {
3716  std::vector<int> newlist(2);
3717  newlist[0] = tj1.ID;
3718  newlist[1] = tj2.ID;
3719  tjLists.push_back(newlist);
3720  }
3721  } // it2
3722  } // it1
3723  if(tjLists.empty()) return;
3724 
3725  // mark them all as ShowerLike Tjs
3726  unsigned short nsh = 0;
3727  for(auto& tjl : tjLists) {
3728  nsh += tjl.size();
3729  for(auto& tjID : tjl) {
3730  auto& tj = slc.tjs[tjID - 1];
3731  tj.AlgMod[kShowerLike] = true;
3732  } // tjid
3733  } // tjl
3734 
3735  // kill vertices with more than 1 shower-like tj that is close to the
3736  // vertex
3737  unsigned short nkill = 0;
3738  for(auto& vx2 : slc.vtxs) {
3739  if(vx2.ID == 0) continue;
3740  if(vx2.CTP != inCTP) continue;
3741  auto TInV2 = GetAssns(slc, "2V", vx2.ID, "T");
3742  unsigned short nsl = 0;
3743  bool has111 = false;
3744  for(auto tid : TInV2) {
3745  auto& tj = slc.tjs[tid - 1];
3746  if(tj.PDGCode == 111) has111 = true;
3747  if(tj.AlgMod[kShowerLike]) {
3748  unsigned short nearEnd = 1 - FarEnd(slc, tj, vx2.Pos);
3749  if(PosSep(tj.Pts[tj.EndPt[nearEnd]].Pos, vx2.Pos) < 6) ++nsl;
3750  }
3751  } // tid
3752  if(nsl < 2) continue;
3753  if(has111) continue;
3754  MakeVertexObsolete("TSL", slc, vx2, true);
3755  ++nkill;
3756  } // vx2
3757  if(prt) mf::LogVerbatim("TC")<<"TagShowerLike tagged "<<nsh<<" Tjs and killed "<<nkill<<" vertices in CTP "<<inCTP;
3758 
3759  } // TagShowerLike
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:3120
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4279
TCConfig tcc
Definition: DataStructs.cxx:6
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:507
bool TrajTrajDOCA(TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2175
std::vector< float > showerTag
[min MCSMom, max separation, min # Tj < separation] for a shower tag
Definition: DataStructs.h:474
DebugStuff debug
Definition: DebugStruct.cxx:4
std::vector< evd::details::RawDigitInfo_t >::const_iterator begin(RawDigitCacheDataClass const &cache)
unsigned short FarEnd(TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3032
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
std::vector< float > chargeCuts
Definition: DataStructs.h:478
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
CTP_t CTP
set to an invalid CTP
Definition: DebugStruct.h:22
void tca::TjDeltaRMS ( TCSlice slc,
Trajectory tj,
unsigned short  firstPt,
unsigned short  lastPt,
double &  rms,
unsigned short &  cnt 
)

Definition at line 3029 of file Utils.cxx.

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

Referenced by DotProd(), ElectronLikelihood(), and MCSThetaRMS().

3030  {
3031  // returns the rms scatter of points around a line formed by the firstPt and lastPt of the trajectory
3032 
3033  rms = -1;
3034  if(firstPt < tj.EndPt[0]) return;
3035  if(lastPt > tj.EndPt[1]) return;
3036 
3037  firstPt = NearestPtWithChg(slc, tj, firstPt);
3038  lastPt = NearestPtWithChg(slc, tj, lastPt);
3039  if(firstPt >= lastPt) return;
3040 
3041  TrajPoint tmp;
3042  // make a bare trajectory point to define a line between firstPt and lastPt.
3043  // Use the position of the hits at these points
3044  TrajPoint firstTP = tj.Pts[firstPt];
3045  firstTP.Pos = firstTP.HitPos;
3046  TrajPoint lastTP = tj.Pts[lastPt];
3047  lastTP.Pos = lastTP.HitPos;
3048  if(!MakeBareTrajPoint(slc, firstTP, lastTP, tmp)) return;
3049  // sum up the deviations^2
3050  double dsum = 0;
3051  cnt = 0;
3052  for(unsigned short ipt = firstPt + 1; ipt < lastPt; ++ipt) {
3053  if(tj.Pts[ipt].Chg == 0) continue;
3054  // ignore points with large error
3055  if(tcc.useAlg[kNewStpCuts] && tj.Pts[ipt].HitPosErr2 > 4) continue;
3056  dsum += PointTrajDOCA2(slc, tj.Pts[ipt].HitPos[0], tj.Pts[ipt].HitPos[1], tmp);
3057  ++cnt;
3058  } // ipt
3059  if(cnt < 2) return;
3060  rms = sqrt(dsum / (double)cnt);
3061 
3062  } // TjDeltaRMS
TCConfig tcc
Definition: DataStructs.cxx:6
Float_t tmp
Definition: plot.C:37
unsigned short NearestPtWithChg(TCSlice &slc, Trajectory &tj, unsigned short thePt)
Definition: Utils.cxx:2966
float PointTrajDOCA2(TCSlice &slc, float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2286
bool MakeBareTrajPoint(TCSlice &slc, const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
Definition: Utils.cxx:3628
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
float tca::TjDirFOM ( TCSlice slc,
const Trajectory tj,
bool  prt 
)

Definition at line 986 of file Utils.cxx.

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

Referenced by StoreTraj().

987  {
988  // Calculate a FOM for the tj to be going from EndPt[0] -> EndPt[1] (FOM = 1)
989  // or EndPt[1] -> EndPt[0] (FOM = -1) by finding the overall charge slope, weighted
990  // by the presence of nearby InShower Tjs
991  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) return 0;
992  if(tj.EndPt[1] - tj.EndPt[0] < 8) return 0;
993 
994  std::vector<double> x, y;
995  Point2_t origin = tj.Pts[tj.EndPt[0]].HitPos;
996  std::vector<double> w, q;
997 
998  unsigned short firstPt = tj.EndPt[0] + 2;
999  unsigned short lastPt = tj.EndPt[1] - 2;
1000  if(lastPt < firstPt + 3) return 0;
1001  // don't include end points
1002  for(unsigned short ipt = firstPt; ipt <= lastPt; ++ipt) {
1003  auto& tp = tj.Pts[ipt];
1004  if(tp.Chg <= 0) continue;
1005  // only consider points that don't overlap with other tjs
1006  if(tp.Environment[kEnvOverlap]) continue;
1007  double sep = PosSep(tp.Pos, origin);
1008  x.push_back(sep);
1009  y.push_back((double)tp.Chg);
1010  double wght = 0.2 * tp.Chg;
1011  w.push_back(wght * wght);
1012  } // tp
1013  if(w.size() < 3) return 0;
1014 
1015  double sum = 0.;
1016  double sumx = 0.;
1017  double sumy = 0.;
1018  double sumxy = 0.;
1019  double sumx2 = 0.;
1020  double sumy2 = 0.;
1021 
1022  // weight by the charge ratio and accumulate sums
1023  double wght;
1024  for(unsigned short ipt = 0; ipt < x.size(); ++ipt) {
1025  wght = 1 / w[ipt];
1026  sum += wght;
1027  sumx += wght * x[ipt];
1028  sumy += wght * y[ipt];
1029  sumx2 += wght * x[ipt] * x[ipt];
1030  sumy2 += wght * y[ipt] * y[ipt];
1031  sumxy += wght * x[ipt] * y[ipt];
1032  }
1033  // calculate coefficients and std dev
1034  double delta = sum * sumx2 - sumx * sumx;
1035  if(delta == 0) return 0;
1036  // A is the intercept
1037  double A = (sumx2 * sumy - sumx * sumxy) / delta;
1038  // B is the slope
1039  double B = (sumxy * sum - sumx * sumy) / delta;
1040 
1041  // Calculate the FOM
1042  double ndof = x.size() - 2;
1043  double varnce = (sumy2 + A*A*sum + B*B*sumx2 - 2 * (A*sumy + B*sumxy - A*B*sumx)) / ndof;
1044  if(varnce <= 0) return 0;
1045  double BErr = sqrt(varnce * sum / delta);
1046  // scale the error so that the significance is +/-1 when the slope is 3 * error
1047  // Note that the error is correct only if the average Chi/DOF = 1 which is probably not the case
1048  float slopeSig = B / (3 * BErr);
1049  if(slopeSig > 1) slopeSig = 1;
1050  if(slopeSig < -1) slopeSig = -1;
1051  // rescale it to be in the range of 0 - 1
1052  slopeSig = (1 + slopeSig) / 2;
1053 
1054  if(prt) {
1055  mf::LogVerbatim myprt("TC");
1056  myprt<<"TjDir: T"<<tj.ID<<" slope "<<std::fixed<<std::setprecision(1)<<B<<" error "<<BErr<<" DirFOM "<<slopeSig;
1057  myprt<<" using points from "<<PrintPos(slc, tj.Pts[firstPt])<<" "<<PrintPos(slc, tj.Pts[lastPt]);
1058  } // prt
1059  return slopeSig;
1060 
1061  } // TjDirFOM
Float_t x
Definition: compare.C:6
float PosSep(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2353
Float_t y
Definition: compare.C:6
Int_t B
Definition: plot.C:25
std::string PrintPos(TCSlice &slc, const Point2_t &pos)
Definition: Utils.cxx:5718
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
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 ( TCSlice slc,
TrajPoint tp,
HitStatus_t  hitRequest 
)

Definition at line 3674 of file Utils.cxx.

References tca::TCEvent::allHits, evt, tca::TrajPoint::Hits, kAllHits, kUnusedHits, kUsedHits, tca::TCSlice::slHits, and tca::TrajPoint::UseHit.

Referenced by DotProd(), FindUseHits(), and TPHitsRMSTime().

3675  {
3676  // Estimate the RMS of all hits associated with a trajectory point
3677  // without a lot of calculation
3678  if(tp.Hits.empty()) return 0;
3679  float minVal = 9999;
3680  float maxVal = 0;
3681  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3682  bool useit = (hitRequest == kAllHits);
3683  if(hitRequest == kUsedHits && tp.UseHit[ii]) useit = true;
3684  if(hitRequest == kUnusedHits && !tp.UseHit[ii]) useit = true;
3685  if(!useit) continue;
3686  unsigned int iht = tp.Hits[ii];
3687  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
3688  float cv = hit.PeakTime();
3689  float rms = hit.RMS();
3690  float arg = cv - rms;
3691  if(arg < minVal) minVal = arg;
3692  arg = cv + rms;
3693  if(arg > maxVal) maxVal = arg;
3694  } // ii
3695  if(maxVal == 0) return 0;
3696  return (maxVal - minVal) / 2;
3697  } // TPHitsRMSTick
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
float tca::TPHitsRMSTime ( TCSlice slc,
TrajPoint tp,
HitStatus_t  hitRequest 
)

Definition at line 3668 of file Utils.cxx.

References tcc, TPHitsRMSTick(), and tca::TCConfig::unitsPerTick.

Referenced by DotProd(), and FillmAllTraj().

3669  {
3670  return tcc.unitsPerTick * TPHitsRMSTick(slc, tp, hitRequest);
3671  } // TPHitsRMSTime
TCConfig tcc
Definition: DataStructs.cxx:6
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
float TPHitsRMSTick(TCSlice &slc, TrajPoint &tp, HitStatus_t hitRequest)
Definition: Utils.cxx:3674
unsigned short tca::TPNearVertex ( TCSlice slc,
const TrajPoint tp 
)

Definition at line 1816 of file TCVertex.cxx.

References tca::TrajPoint::CTP, tca::TrajPoint::Pos, and tca::TCSlice::vtxs.

Referenced by StepAway().

1817  {
1818  // Returns the index of a vertex if tp is nearby
1819  for(unsigned short ivx = 0; ivx < slc.vtxs.size(); ++ivx) {
1820  if(slc.vtxs[ivx].ID == 0) continue;
1821  if(slc.vtxs[ivx].CTP != tp.CTP) continue;
1822  if(std::abs(slc.vtxs[ivx].Pos[0] - tp.Pos[0]) > 1.2) continue;
1823  if(std::abs(slc.vtxs[ivx].Pos[1] - tp.Pos[1]) > 1.2) continue;
1824  return ivx;
1825  } // ivx
1826  return USHRT_MAX;
1827  } // TPNearVertex
float tca::TpSumHitChg ( TCSlice slc,
TrajPoint const &  tp 
)

Definition at line 1853 of file Utils.cxx.

References tca::TCEvent::allHits, evt, tca::TrajPoint::Hits, tca::TCSlice::slHits, and tca::TrajPoint::UseHit.

Referenced by SplitHiChgHits(), and VtxHitsSwap().

1853  {
1854  float totchg = 0;
1855  for (size_t i = 0; i<tp.Hits.size(); ++i){
1856  if (!tp.UseHit[i]) continue;
1857  totchg += (*evt.allHits)[slc.slHits[tp.Hits[i]].allHitsIndex].Integral();
1858  }
1859  return totchg;
1860  } // TpSumHitChg
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
bool tca::TrajClosestApproach ( Trajectory const &  tj,
float  x,
float  y,
unsigned short &  closePt,
float &  DOCA 
)

Definition at line 2377 of file Utils.cxx.

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

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

2378  {
2379  // find the closest approach between a trajectory tj and a point (x,y). Returns
2380  // the index of the closest trajectory point and the distance. Returns false if none
2381  // of the points on the tj are within DOCA
2382 
2383  float close2 = DOCA * DOCA;
2384  closePt = 0;
2385  bool foundClose = false;
2386 
2387  for(unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1] + 1; ++ipt) {
2388  if(tj.Pts[ipt].Chg == 0) continue;
2389  float dx = tj.Pts[ipt].Pos[0] - x;
2390  if(std::abs(dx) > DOCA) continue;
2391  float dy = tj.Pts[ipt].Pos[1] - y;
2392  if(std::abs(dy) > DOCA) continue;
2393  float sep2 = dx * dx + dy * dy;
2394  if(sep2 < close2) {
2395  close2 = sep2;
2396  closePt = ipt;
2397  foundClose = true;
2398  }
2399  } // ipt
2400 
2401  DOCA = sqrt(close2);
2402  return foundClose;
2403 
2404  } // TrajClosestApproach
Float_t x
Definition: compare.C:6
Float_t y
Definition: compare.C:6
bool tca::TrajHitsOK ( TCSlice slc,
const std::vector< unsigned int > &  iHitsInMultiplet,
const std::vector< unsigned int > &  jHitsInMultiplet 
)

Definition at line 1736 of file Utils.cxx.

References tca::TCEvent::allHits, evt, HitsPosTick(), kAllHits, and tca::TCSlice::slHits.

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

1737  {
1738  // Hits (assume to be on adjacent wires have an acceptable signal overlap
1739 
1740  if(iHitsInMultiplet.empty() || jHitsInMultiplet.empty()) return false;
1741 
1742  float sum;
1743  float cvI = HitsPosTick(slc, iHitsInMultiplet, sum, kAllHits);
1744  float minI = 1E6;
1745  float maxI = 0;
1746  for(auto& iht : iHitsInMultiplet) {
1747  auto const& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1748  float cv = hit.PeakTime();
1749  float rms = hit.RMS();
1750  float arg = cv - 3.1 * rms;
1751  if(arg < minI) minI = arg;
1752  arg = cv + 3.1 * rms;
1753  if(arg > maxI) maxI = arg;
1754  }
1755 
1756  float cvJ = HitsPosTick(slc, jHitsInMultiplet, sum, kAllHits);
1757  float minJ = 1E6;
1758  float maxJ = 0;
1759  for(auto& jht : jHitsInMultiplet) {
1760  auto& hit = (*evt.allHits)[slc.slHits[jht].allHitsIndex];
1761  float cv = hit.PeakTime();
1762  float rms = hit.RMS();
1763  float arg = cv - 3.1 * rms;
1764  if(arg < minJ) minJ = arg;
1765  arg = cv + 3.1 * rms;
1766  if(arg > maxJ) maxJ = arg;
1767  }
1768 
1769  if(cvI < cvJ) {
1770  if(maxI > minJ) return true;
1771  } else {
1772  if(minI < maxJ) return true;
1773  }
1774  return false;
1775  } // TrajHitsOK
float HitsPosTick(TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, float &sum, HitStatus_t hitRequest)
Definition: Utils.cxx:3742
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
bool tca::TrajHitsOK ( TCSlice slc,
const unsigned int  iht,
const unsigned int  jht 
)

Definition at line 1778 of file Utils.cxx.

References tca::TCEvent::allHits, evt, and tca::TCSlice::slHits.

1779  {
1780  // ensure that two adjacent hits have an acceptable overlap
1781  if(iht > slc.slHits.size() - 1) return false;
1782  if(jht > slc.slHits.size() - 1) return false;
1783  // require that they be on adjacent wires
1784  auto& ihit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1785  auto& jhit = (*evt.allHits)[slc.slHits[jht].allHitsIndex];
1786  int iwire = ihit.WireID().Wire;
1787  int jwire = jhit.WireID().Wire;
1788  if(std::abs(iwire - jwire) > 1) return false;
1789  if(ihit.PeakTime() > jhit.PeakTime()) {
1790  float minISignal = ihit.PeakTime() - 3 * ihit.RMS();
1791  float maxJSignal = jhit.PeakTime() + 3 * ihit.RMS();
1792  if(maxJSignal > minISignal) return true;
1793  } else {
1794  float maxISignal = ihit.PeakTime() + 3 * ihit.RMS();
1795  float minJSignal = jhit.PeakTime() - 3 * ihit.RMS();
1796  if(minJSignal > maxISignal) return true;
1797  }
1798  return false;
1799  } // TrajHitsOK
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
TCEvent evt
Definition: DataStructs.cxx:5
void tca::TrajIntersection ( TrajPoint const &  tp1,
TrajPoint const &  tp2,
Point2_t pos 
)

Definition at line 2299 of file Utils.cxx.

References TrajIntersection().

Referenced by EndMerge(), Find2DVertices(), FindHammerVertices2(), and FitVertex().

2300  {
2301  TrajIntersection(tp1, tp2, pos[0], pos[1]);
2302  } // TrajIntersection
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, float &x, float &y)
Definition: Utils.cxx:2304
void tca::TrajIntersection ( TrajPoint const &  tp1,
TrajPoint const &  tp2,
float &  x,
float &  y 
)

Definition at line 2304 of file Utils.cxx.

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

Referenced by TrajIntersection().

2305  {
2306  // returns the intersection position, (x,y), of two trajectory points
2307 
2308  x = -9999; y = -9999;
2309 
2310  double arg1 = tp1.Pos[0] * tp1.Dir[1] - tp1.Pos[1] * tp1.Dir[0];
2311  double arg2 = tp2.Pos[0] * tp1.Dir[1] - tp2.Pos[1] * tp1.Dir[0];
2312  double arg3 = tp2.Dir[0] * tp1.Dir[1] - tp2.Dir[1] * tp1.Dir[0];
2313  if(arg3 == 0) return;
2314  double s = (arg1 - arg2) / arg3;
2315 
2316  x = (float)(tp2.Pos[0] + s * tp2.Dir[0]);
2317  y = (float)(tp2.Pos[1] + s * tp2.Dir[1]);
2318 
2319  } // 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 ( TCSlice slc,
Trajectory tj,
bool  prt 
)

Definition at line 2891 of file Utils.cxx.

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

Referenced by DotProd(), and UpdateTraj().

2892  {
2893  // Returns true if the trajectory has low hit multiplicity and is in a
2894  // clean environment
2895  unsigned short nUsed = 0;
2896  unsigned short nTotHits = 0;
2897  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2898  TrajPoint& tp = tj.Pts[ipt];
2899  nTotHits += tp.Hits.size();
2900  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2901  if(tp.UseHit[ii]) ++nUsed;
2902  } // ii
2903  } // ipt
2904  if(nTotHits == 0) return false;
2905  float fracUsed = (float)nUsed / (float)nTotHits;
2906  if(prt) mf::LogVerbatim("TC")<<"TrajIsClean: nTotHits "<<nTotHits<<" nUsed "<<nUsed<<" fracUsed "<<fracUsed;
2907 
2908  if(fracUsed > 0.9) return true;
2909  return false;
2910 
2911  } // TrajIsClean
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float tca::TrajLength ( Trajectory tj)

Definition at line 2337 of file Utils.cxx.

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

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

2338  {
2339  float len = 0, dx, dy;
2340  unsigned short ipt;
2341  unsigned short prevPt = tj.EndPt[0];
2342  for(ipt = tj.EndPt[0] + 1; ipt < tj.EndPt[1] + 1; ++ipt) {
2343  if(tj.Pts[ipt].Chg == 0) continue;
2344  dx = tj.Pts[ipt].Pos[0] - tj.Pts[prevPt].Pos[0];
2345  dy = tj.Pts[ipt].Pos[1] - tj.Pts[prevPt].Pos[1];
2346  len += sqrt(dx * dx + dy * dy);
2347  prevPt = ipt;
2348  }
2349  return len;
2350  } // TrajLength
float tca::TrajPointSeparation ( TrajPoint tp1,
TrajPoint tp2 
)

Definition at line 2368 of file Utils.cxx.

References tca::TrajPoint::Pos.

Referenced by EndMerge(), GottaKink(), MaskTrajEndPoints(), tca::TruthMatcher::MatchTruth(), MCSMom(), MCSThetaRMS(), and StepAway().

2369  {
2370  // Returns the separation distance between two trajectory points
2371  float dx = tp1.Pos[0] - tp2.Pos[0];
2372  float dy = tp1.Pos[1] - tp2.Pos[1];
2373  return sqrt(dx * dx + dy * dy);
2374  } // TrajPointSeparation
void tca::TrajPointTrajDOCA ( TCSlice slc,
TrajPoint const &  tp,
Trajectory const &  tj,
unsigned short &  closePt,
float &  minSep 
)

Definition at line 2155 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().

2156  {
2157  // Finds the point, ipt, on trajectory tj that is closest to trajpoint tp
2158  float best = minSep * minSep;
2159  closePt = USHRT_MAX;
2160  float dw, dt, dp2;
2161  unsigned short ipt;
2162  for(ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2163  dw = tj.Pts[ipt].Pos[0] - tp.Pos[0];
2164  dt = tj.Pts[ipt].Pos[1] - tp.Pos[1];
2165  dp2 = dw * dw + dt * dt;
2166  if(dp2 < best) {
2167  best = dp2;
2168  closePt = ipt;
2169  }
2170  } // ipt
2171  minSep = sqrt(best);
2172  } // TrajPointTrajDOCA
float tca::TrajPointVertexPull ( TCSlice slc,
const TrajPoint tp,
const VtxStore vx 
)

Definition at line 2029 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().

2030  {
2031  // Calculates the position pull between a trajectory point and a vertex
2032 
2033  // impact parameter between them
2034  double ip = PointTrajDOCA(slc, vx.Pos[0], vx.Pos[1], tp);
2035  // separation^2
2036  double sep2 = PosSep2(vx.Pos, tp.Pos);
2037 
2038  // Find the projection of the vertex error ellipse in a coordinate system
2039  // along the TP direction
2040  double vxErrW = vx.PosErr[0] * tp.Dir[1];
2041  double vxErrT = vx.PosErr[1] * tp.Dir[0];
2042  double vxErr2 = vxErrW * vxErrW + vxErrT * vxErrT;
2043  // add the TP position error^2
2044  vxErr2 += tp.HitPosErr2;
2045 
2046  // close together so ignore the TP projection error and return
2047  // the pull using the vertex error and TP position error
2048  if(sep2 < 1) return (float)(ip/sqrt(vxErr2));
2049 
2050  double dang = ip / sqrt(sep2);
2051 
2052  // calculate the angle error.
2053  // Start with the vertex error^2
2054  double angErr = vxErr2 / sep2;
2055  // Add the TP angle error^2
2056  angErr += tp.AngErr * tp.AngErr;
2057  if(angErr == 0) return 999;
2058  angErr = sqrt(angErr);
2059  return (float)(dang / angErr);
2060 
2061  } // TrajPointVertexPull
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1660
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
bool tca::TrajTrajDOCA ( TCSlice slc,
const Trajectory tj1,
const Trajectory tj2,
unsigned short &  ipt1,
unsigned short &  ipt2,
float &  minSep 
)

Definition at line 2175 of file Utils.cxx.

References TrajTrajDOCA().

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

2176  {
2177  return TrajTrajDOCA(slc, tj1, tj2, ipt1, ipt2, minSep, false);
2178  } // TrajTrajDOCA
bool TrajTrajDOCA(TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep, bool considerDeadWires)
Definition: Utils.cxx:2181
bool tca::TrajTrajDOCA ( TCSlice slc,
const Trajectory tj1,
const Trajectory tj2,
unsigned short &  ipt1,
unsigned short &  ipt2,
float &  minSep,
bool  considerDeadWires 
)

Definition at line 2181 of file Utils.cxx.

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

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

2182  {
2183  // Find the Distance Of Closest Approach between two trajectories less than minSep
2184  // start with some rough cuts to minimize the use of the more expensive checking. This
2185  // function returns true if the DOCA is less than minSep
2186  for(unsigned short iwt = 0; iwt < 2; ++iwt) {
2187  // Apply box cuts on the ends of the trajectories
2188  // The Lo/Hi wire(time) at each end of tj1
2189  float wt0 = tj1.Pts[tj1.EndPt[0]].Pos[iwt];
2190  float wt1 = tj1.Pts[tj1.EndPt[1]].Pos[iwt];
2191  float lowt1 = wt0;
2192  float hiwt1 = wt1;
2193  if(wt1 < lowt1) {
2194  lowt1 = wt1;
2195  hiwt1 = wt0;
2196  }
2197  // The Lo/Hi wire(time) at each end of tj2
2198  wt0 = tj2.Pts[tj2.EndPt[0]].Pos[iwt];
2199  wt1 = tj2.Pts[tj2.EndPt[1]].Pos[iwt];
2200  float lowt2 = wt0;
2201  float hiwt2 = wt1;
2202  if(wt1 < lowt2) {
2203  lowt2 = wt1;
2204  hiwt2 = wt0;
2205  }
2206  // Check for this configuration
2207  // loWire1.......hiWire1 minSep loWire2....hiWire2
2208  // loTime1.......hiTime1 minSep loTime2....hiTime2
2209  if(lowt2 > hiwt1 + minSep) return false;
2210  // and the other
2211  if(lowt1 > hiwt2 + minSep) return false;
2212  } // iwt
2213 
2214  float best = minSep * minSep;
2215  ipt1 = 0; ipt2 = 0;
2216  float dwc = 0;
2217  bool isClose = false;
2218  for(unsigned short i1 = tj1.EndPt[0]; i1 < tj1.EndPt[1] + 1; ++i1) {
2219  for(unsigned short i2 = tj2.EndPt[0]; i2 < tj2.EndPt[1] + 1; ++i2) {
2220  if(considerDeadWires) dwc = DeadWireCount(slc, tj1.Pts[i1], tj2.Pts[i2]);
2221  float dw = tj1.Pts[i1].Pos[0] - tj2.Pts[i2].Pos[0] - dwc;
2222  if(std::abs(dw) > minSep) continue;
2223  float dt = tj1.Pts[i1].Pos[1] - tj2.Pts[i2].Pos[1];
2224  if(std::abs(dt) > minSep) continue;
2225  float dp2 = dw * dw + dt * dt;
2226  if(dp2 < best) {
2227  best = dp2;
2228  ipt1 = i1;
2229  ipt2 = i2;
2230  isClose = true;
2231  }
2232  } // i2
2233  } // i1
2234  minSep = sqrt(best);
2235  return isClose;
2236  } // TrajTrajDOCA
float DeadWireCount(TCSlice &slc, const float &inWirePos1, const float &inWirePos2, CTP_t tCTP)
Definition: Utils.cxx:1887
bool tca::TransferTjHits ( TCSlice slc,
bool  prt 
)

Definition at line 4318 of file TCShower.cxx.

References tca::TCSlice::cots, tca::Trajectory::ID, kKilled, kShowerTj, kUsedHits, tca::Trajectory::Pts, PutTrajHitsInVector(), tca::TCSlice::slHits, ss, and tca::TCSlice::tjs.

Referenced by Finish3DShowers().

4319  {
4320  // Transfer InShower hits in all TPCs and planes to the shower Tjs
4321 
4322  bool newShowers = false;
4323  for(auto& ss : slc.cots) {
4324  if(ss.ID == 0) continue;
4325  if(ss.ShowerTjID == 0) continue;
4326  // Tp 1 of stj will get all of the shower hits
4327  Trajectory& stj = slc.tjs[ss.ShowerTjID - 1];
4328  if(!stj.Pts[1].Hits.empty()) {
4329  std::cout<<"TTjH: ShowerTj T"<<stj.ID<<" already has "<<stj.Pts[1].Hits.size()<<" hits\n";
4330  continue;
4331  }
4332  // Note that UseHit is not used since the size is limited to 16
4333  for(auto& tjID : ss.TjIDs) {
4334  unsigned short itj = tjID - 1;
4335  if(slc.tjs[itj].AlgMod[kShowerTj]) {
4336  std::cout<<"TTjH: Coding error. T"<<tjID<<" is a ShowerTj but is in TjIDs\n";
4337  continue;
4338  }
4339  if(slc.tjs[itj].SSID <= 0) {
4340  std::cout<<"TTjH: Coding error. Trying to transfer T"<<tjID<<" hits but it isn't an InShower Tj\n";
4341  continue;
4342  }
4343  auto thits = PutTrajHitsInVector(slc.tjs[itj], kUsedHits);
4344  // associate all hits with the charge center TP
4345  stj.Pts[1].Hits.insert(stj.Pts[1].Hits.end(), thits.begin(), thits.end());
4346  // kill Tjs that are in showers
4347  slc.tjs[itj].AlgMod[kKilled] = true;
4348  } // tjID
4349  // re-assign the hit -> stj association
4350  for(auto& iht : stj.Pts[1].Hits) slc.slHits[iht].InTraj = stj.ID;
4351  newShowers = true;
4352  } // ss
4353 
4354  if(prt) mf::LogVerbatim("TC")<<"TTJH: success? "<<newShowers;
4355  return newShowers;
4356  } // TransferTjHits
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< unsigned int > PutTrajHitsInVector(Trajectory const &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2416
Float_t ss
Definition: plot.C:23
void tca::TrimEndPts ( std::string  fcnLabel,
TCSlice slc,
Trajectory tj,
const std::vector< float > &  fQualityCuts,
bool  prt 
)

Definition at line 1511 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::CTP, DecodeCTP(), tca::Trajectory::EndPt, tca::Trajectory::ID, kNewStpCuts, kTEP, NumPtsWithCharge(), tca::TCSlice::nWires, tca::Trajectory::PDGCode, geo::PlaneID::Plane, PrintTrajectory(), tca::Trajectory::Pts, SetEndPoints(), tca::Trajectory::StepDir, tcc, UnsetUsedHits(), tca::TCConfig::useAlg, and tca::TCSlice::wireHitRange.

Referenced by CheckTraj(), FixTrajBegin(), and IsGhost().

1512  {
1513  // Trim the hits off the end until there are at least MinPts consecutive hits at the end
1514  // and the fraction of hits on the trajectory exceeds fQualityCuts[0]
1515  // Minimum length requirement accounting for dead wires where - denotes a wire with a point
1516  // and D is a dead wire. Here is an example with minPts = 3
1517  // ---DDDDD--- is OK
1518  // ----DD-DD-- is OK
1519  // ----DDD-D-- is OK
1520  // ----DDDDD-- is not OK
1521 
1522  if(!tcc.useAlg[kTEP]) return;
1523  if(tcc.useAlg[kNewStpCuts] && tj.PDGCode == 111) return;
1524 
1525  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
1526  short minPts = fQualityCuts[1];
1527  if(minPts < 1) return;
1528  if(npwc < minPts) return;
1529 
1530  // handle short tjs
1531  if(npwc == minPts + 1) {
1532  unsigned short endPt1 = tj.EndPt[1];
1533  auto& tp = tj.Pts[endPt1];
1534  auto& ptp = tj.Pts[endPt1 - 1];
1535  // remove the last point if the previous point has no charge or if
1536  // it isn't on the next wire
1537  float dwire = std::abs(ptp.Pos[0] - tp.Pos[0]);
1538  if(ptp.Chg == 0 || dwire > 1.1) {
1539  UnsetUsedHits(slc, tp);
1540  SetEndPoints(tj);
1541  tj.AlgMod[kTEP] = true;
1542  }
1543  return;
1544  } // short tj
1545 
1546  // find the separation between adjacent points, starting at the end
1547  short lastPt = 0;
1548  for(lastPt = tj.EndPt[1]; lastPt >= minPts; --lastPt) {
1549  // check for an error
1550  if(lastPt == 1) break;
1551  if(tj.Pts[lastPt].Chg == 0) continue;
1552  // number of adjacent points on adjacent wires
1553  unsigned short nadj = 0;
1554  unsigned short npwc = 0;
1555  for(short ipt = lastPt - minPts; ipt < lastPt; ++ipt) {
1556  if(ipt < 2) break;
1557  // the current point
1558  auto& tp = tj.Pts[ipt];
1559  // the previous point
1560  auto& ptp = tj.Pts[ipt - 1];
1561  if(tp.Chg > 0 && ptp.Chg > 0) {
1562  ++npwc;
1563  if(std::abs(tp.Pos[0] - ptp.Pos[0]) < 1.5) ++nadj;
1564  }
1565  } // ipt
1566  float ntpwc = NumPtsWithCharge(slc, tj, true, tj.EndPt[0], lastPt);
1567  float nwires = std::abs(tj.Pts[tj.EndPt[0]].Pos[0] - tj.Pts[lastPt].Pos[0]) + 1;
1568  float hitFrac = ntpwc / nwires;
1569  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<"-TEP: T"<<tj.ID<<" lastPt "<<lastPt<<" npwc "<<npwc<<" ntpwc "<<ntpwc<<" nadj "<<nadj<<" hitFrac "<<hitFrac;
1570  if(tcc.useAlg[kNewStpCuts]) {
1571  // use new cuts
1572  if(hitFrac > fQualityCuts[0] && ntpwc > minPts) break;
1573  } else {
1574  if(hitFrac > fQualityCuts[0] && npwc == minPts && nadj == minPts) break;
1575  }
1576  } // lastPt
1577 
1578  // trim the last point if it just after a dead wire.
1579  if(tj.Pts[lastPt].Pos[0] > -0.4) {
1580  unsigned int prevWire = std::nearbyint(tj.Pts[lastPt].Pos[0]);
1581  if(tj.StepDir > 0) {
1582  --prevWire;
1583  } else {
1584  ++prevWire;
1585  }
1586  if(prt) {
1587  mf::LogVerbatim("TC")<<fcnLabel<<"-TEP: is prevWire "<<prevWire<<" dead? ";
1588  }
1589  unsigned short plane = DecodeCTP(tj.CTP).Plane;
1590  if(prevWire < slc.nWires[plane] && slc.wireHitRange[plane][prevWire].first == -1) --lastPt;
1591  } // valid Pos[0]
1592 
1593  // Nothing needs to be done
1594  if(lastPt == tj.EndPt[1]) {
1595  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<"-TEPo: Tj is OK";
1596  return;
1597  }
1598 
1599  // clear the points after lastPt
1600  for(unsigned short ipt = lastPt + 1; ipt <= tj.EndPt[1]; ++ipt) UnsetUsedHits(slc, tj.Pts[ipt]);
1601  SetEndPoints(tj);
1602  tj.AlgMod[kTEP] = true;
1603  if(prt) {
1604  fcnLabel += "-TEPo";
1605  PrintTrajectory(fcnLabel, slc, tj, USHRT_MAX);
1606  }
1607 
1608  } // TrimEndPts
void PrintTrajectory(std::string someText, TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:5455
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
TCConfig tcc
Definition: DataStructs.cxx:6
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1162
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:1871
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
geo::PlaneID DecodeCTP(CTP_t CTP)
float tca::TwoTPAngle ( TrajPoint tp1,
TrajPoint tp2 
)

Definition at line 2407 of file Utils.cxx.

References tca::TrajPoint::Pos.

2408  {
2409  // Calculates the angle of a line between two TPs
2410  float dw = tp2.Pos[0] - tp1.Pos[0];
2411  float dt = tp2.Pos[1] - tp1.Pos[1];
2412  return atan2(dw, dt);
2413  } // TwoTPAngle
void tca::UnsetUsedHits ( TCSlice slc,
TrajPoint tp 
)

Definition at line 1162 of file Utils.cxx.

References tca::TrajPoint::Chg, tca::TrajPoint::Hits, tca::TCSlice::slHits, and tca::TrajPoint::UseHit.

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

1163  {
1164  // Sets InTraj = 0 and UseHit false for all used hits in tp
1165  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1166  if(tp.UseHit[ii]) {
1167  slc.slHits[tp.Hits[ii]].InTraj = 0;
1168  tp.UseHit[ii] = false;
1169  } // UseHit
1170  } // ii
1171  tp.Chg = 0;
1172  } // UnsetUsedHits
void tca::UpdateDeltaRMS ( TCSlice slc,
Trajectory tj 
)

Definition at line 2635 of file StepUtils.cxx.

References tca::TrajPoint::Chg, tca::TrajPoint::DeltaRMS, tca::Trajectory::EndPt, tca::TrajPoint::NTPsFit, PointTrajDOCA(), and tca::Trajectory::Pts.

Referenced by UpdateStiffEl(), and UpdateTraj().

2636  {
2637  // Estimate the Delta RMS of the TPs on the end of tj.
2638 
2639  unsigned int lastPt = tj.EndPt[1];
2640  TrajPoint& lastTP = tj.Pts[lastPt];
2641 
2642  if(lastTP.Chg == 0) return;
2643  if(lastPt < 6) return;
2644 
2645  unsigned short ii, ipt, cnt = 0;
2646  float sum = 0;
2647  for(ii = 1; ii < tj.Pts.size(); ++ii) {
2648  ipt = lastPt - ii;
2649  if(ipt > tj.Pts.size() - 1) break;
2650  if(tj.Pts[ipt].Chg == 0) continue;
2651  sum += PointTrajDOCA(slc, tj.Pts[ipt].Pos[0], tj.Pts[ipt].Pos[1], lastTP);
2652  ++cnt;
2653  if(cnt == lastTP.NTPsFit) break;
2654  if(ipt == 0) break;
2655  }
2656  if(cnt < 3) return;
2657  // RMS of Gaussian distribution is ~1.2 x the average
2658  // of a one-sided Gaussian distribution (since Delta is > 0)
2659  lastTP.DeltaRMS = 1.2 * sum / (float)cnt;
2660  if(lastTP.DeltaRMS < 0.02) lastTP.DeltaRMS = 0.02;
2661 
2662  } // UpdateDeltaRMS
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
void tca::UpdateMatchStructs ( TCSlice slc,
int  oldTj,
int  newTj 
)

Definition at line 160 of file PFPUtils.cxx.

References detinfo::DetectorProperties::ConvertTicksToX(), DecodeCTP(), tca::TCConfig::detprop, tca::TCSlice::mallTraj, tca::TCSlice::pfps, tcc, tca::TCSlice::tjs, and tca::TCConfig::unitsPerTick.

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

161  {
162  // Replaces tjid and ipt references in slc.matchVec and slc.pfps from
163  // oldTj to newTj. This function is called when Tjs are split or merged
164  // or if a Tj is reversed (in which case oldTj = newTj).
165  // The method used is to match the trajectory point positions
166  if(oldTj <= 0 || oldTj > (int)slc.tjs.size()) return;
167  if(newTj <= 0 || newTj > (int)slc.tjs.size()) return;
168  if(slc.mallTraj.empty() && slc.pfps.empty()) return;
169 
170  // convert from int to unsigned short
171  int oldtjid = oldTj;
172  int newtjid = newTj;
173  auto& ntj = slc.tjs[newTj - 1];
174  unsigned short npts = ntj.EndPt[1] - ntj.EndPt[0] + 1;
175  // put the X positions of the new Tj into a vector for matching
176  std::vector<float> xpos(ntj.Pts.size());
177  geo::PlaneID planeID = DecodeCTP(ntj.CTP);
178  for(unsigned short npt = ntj.EndPt[0]; npt <= ntj.EndPt[1]; ++npt) {
179  auto& ntp = ntj.Pts[npt];
180  if(ntp.Chg <= 0) continue;
181  xpos[npt] = tcc.detprop->ConvertTicksToX(ntp.Pos[1]/tcc.unitsPerTick, planeID);
182  } // npt
183 
184  if(!slc.mallTraj.empty()) {
185  for(unsigned int ipt = 0; ipt < slc.mallTraj.size(); ++ipt) {
186  auto& tj2pt = slc.mallTraj[ipt];
187  if(tj2pt.id > slc.tjs.size()) continue;
188  if(tj2pt.id != oldtjid) continue;
189  // Found the old Tj. Now find the point
190  for(unsigned short npt = ntj.EndPt[0]; npt <= ntj.EndPt[1]; ++npt) {
191  auto& ntp = ntj.Pts[npt];
192  if(ntp.Chg <= 0) continue;
193  if(std::nearbyint(ntp.Pos[0]) == tj2pt.wire && xpos[npt] > tj2pt.xlo && xpos[npt] < tj2pt.xhi) {
194  tj2pt.id = newtjid;
195  tj2pt.ipt = npt;
196  tj2pt.npts = npts;
197  break;
198  } // points match
199  } // npt
200  } // ipt
201  } // !slc.mallTraj.empty()
202 
203  // Update pfp space points
204  if(!slc.pfps.empty()) {
205  for(auto& pfp : slc.pfps) {
206  for(auto& tp3 : pfp.Tp3s) {
207  // check each of the Tj2Pts associated with this space point
208  for(auto& tj2pt : tp3.Tj2Pts) {
209  if(tj2pt.id > slc.tjs.size()) continue;
210  if(tj2pt.id != oldtjid) continue;
211  // look for the corresponding point (wire) on the new Tj
212  for(unsigned short npt = ntj.EndPt[0]; npt <= ntj.EndPt[1]; ++npt) {
213  auto& ntp = ntj.Pts[npt];
214  if(std::nearbyint(ntp.Pos[0]) == tj2pt.wire && xpos[npt] > tj2pt.xlo && xpos[npt] < tj2pt.xhi) {
215  tj2pt.id = newtjid;
216  tj2pt.ipt = npt;
217  tj2pt.npts = npts;
218  break;
219  }
220  } // npt
221  } // tj2pt
222  } // tp3
223  } // pfp
224  } // pfps exists
225 
226  } // UpdateMatchStructs
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
const detinfo::DetectorProperties * detprop
Definition: DataStructs.h:494
virtual double ConvertTicksToX(double ticks, int p, int t, int c) const =0
geo::PlaneID DecodeCTP(CTP_t CTP)
bool tca::UpdateShower ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct ss,
bool  prt 
)

Definition at line 1033 of file TCShower.cxx.

References tca::TCEvent::allHits, AnalyzeRotPos(), tca::ShowerStruct::Angle, tca::ShowerStruct::AspectRatio, B, tca::ShowerPoint::Chg, ChgToMeV(), tca::ShowerStruct::CTP, DefineEnvelope(), tca::ShowerStruct::DirectionFOM, tca::ShowerStruct::Energy, evt, FarEnd(), 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, tca::TCSlice::slHits, ss, tcc, tca::ShowerPoint::TID, tca::ShowerStruct::TjIDs, tca::TCSlice::tjs, tca::TCConfig::unitsPerTick, tca::TrajPoint::UseHit, and xx.

1034  {
1035  // This is intended to be a single function replacement for FCC, FA, USWP, etc. The calling
1036  // function should have set NeedsUpdate true. A complete re-build is done if the ShPts vector
1037  // is empty. This is only required if a tj is removed from the shower. When adding a tj
1038  // to the shower the AddTj function appends the tj points to ShPts but doesn't fill
1039  // the ShPts RotPos values.
1040  // This function doesn't alter or check associations btw showers and tjs.
1041 
1042  if(ss.ID == 0) return false;
1043  if(ss.TjIDs.empty()) return false;
1044  if(ss.ShowerTjID <= 0 || ss.ShowerTjID > (int)slc.tjs.size()) return false;
1045  if(ss.ParentID > 0 && ss.ParentID > (int)slc.tjs.size()) return false;
1046  auto& stj = slc.tjs[ss.ShowerTjID - 1];
1047  if(stj.Pts.size() != 3) return false;
1048 
1049  std::string fcnLabel = inFcnLabel + ".U2S";
1050 
1051  if(!ss.NeedsUpdate && !ss.ShPts.empty()) {
1052 // std::cout<<fcnLabel<<" 2S"<<ss.ID<<" doesn't need an update\n";
1053  return true;
1054  }
1055 
1056  // initialize the variables that will be defined in this function
1057  ss.Energy = 0; // This is just ShowerEnergy(stj.TotChg) and could be deleted
1058  ss.AspectRatio = 10;
1059  // Direction FOM (0 = good). This is a property of the shower shape and is not
1060  // defined by the presence or absence of a parent tj start point
1061  ss.DirectionFOM = 10;
1062  // Total charge of all hits in the shower
1063  stj.TotChg = 0;
1064  for(auto& stp : stj.Pts) {
1065  // Shower start, charge center, and shower end
1066  stp.Pos = {{0.0, 0.0}};
1067  // Charge weighted average of hits this section (TP) along the shower
1068  stp.HitPos = {{0.0, 0.0}};
1069  // Direction from the start to the charge center - same for all TPs
1070  stp.Dir = {{0.0, 0.0}};
1071  // Hit charge in each section
1072  stp.Chg = 0;
1073  // transverse rms of hit positions relative to HitPos in this section
1074  stp.DeltaRMS = 0;
1075  // number of hits in this section
1076  stp.NTPsFit = 0;
1077  } // stp
1078 
1079  ss.ShPts.clear();
1080  for(auto tjid : ss.TjIDs) {
1081  if(tjid <= 0 || tjid > (int)slc.tjs.size()) return false;
1082  auto& tj = slc.tjs[tjid - 1];
1083  if(tj.CTP != ss.CTP) return false;
1084  if(tj.AlgMod[kShowerTj]) return false;
1085  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1086  TrajPoint& tp = tj.Pts[ipt];
1087  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1088  if(!tp.UseHit[ii]) continue;
1089  unsigned int iht = tp.Hits[ii];
1090  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1091  if(hit.Integral() <= 0) continue;
1092  ShowerPoint shpt;
1093  shpt.HitIndex = iht;
1094  shpt.TID = tj.ID;
1095  shpt.Chg = hit.Integral();
1096  shpt.Pos[0] = hit.WireID().Wire;
1097  shpt.Pos[1] = hit.PeakTime() * tcc.unitsPerTick;
1098  ss.ShPts.push_back(shpt);
1099  } // ii
1100  } // ipt
1101  } // tjid
1102  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 2S"<<ss.ID<<" nShPts "<<ss.ShPts.size();
1103 
1104  if(ss.ShPts.size() < 3) return false;
1105 
1106  // find the charge center and total charge
1107  auto& stp1 = stj.Pts[1];
1108  for(auto& shpt : ss.ShPts) {
1109  stp1.Pos[0] += shpt.Chg * shpt.Pos[0];
1110  stp1.Pos[1] += shpt.Chg * shpt.Pos[1];
1111  stj.TotChg += shpt.Chg;
1112  } // shpt
1113  if(stj.TotChg <= 0) return false;
1114  stp1.Pos[0] /= stj.TotChg;
1115  stp1.Pos[1] /= stj.TotChg;
1116  ss.Energy = ChgToMeV(stj.TotChg);
1117  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 2S"<<ss.ID<<" Chg ctr "<<PrintPos(slc, stp1.Pos)<<" Energy "<<(int)ss.Energy<<" MeV";
1118 
1119  // find the direction using the shower parent if one exists
1120  if(ss.ParentID > 0) {
1121  // Set the direction to be the start of the parent to the shower center
1122  auto& ptj = slc.tjs[ss.ParentID - 1];
1123  // find the parent end farthest away from the charge center
1124  unsigned short pend = FarEnd(slc, ptj, stp1.Pos);
1125  auto& ptp = ptj.Pts[ptj.EndPt[pend]];
1126  stp1.Dir = PointDirection(ptp.Pos, stp1.Pos);
1127  stp1.Ang = atan2(stp1.Dir[1], stp1.Dir[0]);
1128  } else {
1129  // find the shower direction using the points
1130  double sum = 0.;
1131  double sumx = 0.;
1132  double sumy = 0.;
1133  double sumxy = 0.;
1134  double sumx2 = 0.;
1135  double sumy2 = 0.;
1136  for(auto& shpt : ss.ShPts) {
1137  sum += shpt.Chg;
1138  double xx = shpt.Pos[0] - stp1.Pos[0];
1139  double yy = shpt.Pos[1] - stp1.Pos[1];
1140  sumx += shpt.Chg * xx;
1141  sumy += shpt.Chg * yy;
1142  sumxy += shpt.Chg * xx * yy;
1143  sumx2 += shpt.Chg * xx * xx;
1144  sumy2 += shpt.Chg * yy * yy;
1145  } // shpt
1146  double delta = sum * sumx2 - sumx * sumx;
1147  if(delta == 0) return false;
1148  // A is the intercept (This should be ~0 )
1149 // double A = (sumx2 * sumy - sumx * sumxy) / delta;
1150  // B is the slope
1151  double B = (sumxy * sum - sumx * sumy) / delta;
1152  stp1.Ang = atan(B);
1153  stp1.Dir[0] = cos(stp1.Ang);
1154  stp1.Dir[1] = sin(stp1.Ang);
1155  } // no shower parent
1156 
1157  // TODO: ss.Angle should be eliminated. The shower tj Ang should be used instead
1158  ss.Angle = stp1.Ang;
1159  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 2S"<<ss.ID<<" dir "<<std::fixed<<std::setprecision(2)<<stp1.Dir[0]<<" "<<stp1.Dir[1]<<" Angle "<<stp1.Ang;
1160  for(unsigned short ipt = 0; ipt < 3; ++ipt) {
1161  if(ipt == 1) continue;
1162  stj.Pts[ipt].Dir = stp1.Dir;
1163  stj.Pts[ipt].Ang = stp1.Ang;
1164  } // ipt
1165 
1166  // fill the RotPos vector and sort
1167  std::vector<SortEntry> sortVec(ss.ShPts.size());
1168  unsigned short indx = 0;
1169  double cs = cos(-stp1.Ang);
1170  double sn = sin(-stp1.Ang);
1171  for(auto& shpt : ss.ShPts) {
1172  double xx = shpt.Pos[0] - stp1.Pos[0];
1173  double yy = shpt.Pos[1] - stp1.Pos[1];
1174  shpt.RotPos[0] = cs * xx - sn * yy;
1175  shpt.RotPos[1] = sn * xx + cs * yy;
1176  sortVec[indx].index = indx;
1177  sortVec[indx].length = shpt.RotPos[0];
1178  ++indx;
1179  } // shpt
1180  std::sort(sortVec.begin(), sortVec.end(), lessThan);
1181  // put the points vector into the sorted order
1182  auto tPts = ss.ShPts;
1183  for(unsigned short ii = 0; ii < ss.ShPts.size(); ++ii) ss.ShPts[ii] = tPts[sortVec[ii].index];
1184 
1185  // Calculate the aspect ratio
1186  Point2_t alongTrans {{0.0, 0.0}};
1187  for(auto& shpt : ss.ShPts) {
1188  alongTrans[0] += shpt.Chg * std::abs(shpt.RotPos[0]);
1189  alongTrans[1] += shpt.Chg * std::abs(shpt.RotPos[1]);
1190  } // shpt
1191  alongTrans[0] /= stj.TotChg;
1192  alongTrans[1] /= stj.TotChg;
1193  if(alongTrans[1] == 0) return false;
1194  ss.AspectRatio = alongTrans[1] / alongTrans[0];
1195  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 2S"<<ss.ID<<" AspectRatio "<<ss.AspectRatio;
1196 
1197  // analyze the charge in three sections. Fill the stj HitPos and find DeltaRMS
1198  if(!AnalyzeRotPos(fcnLabel, slc, ss, prt)) return false;
1199 
1200  // Reverse the shower direction if needed and define the start point
1201  if(ss.ParentID > 0) {
1202  // The direction was defined by the start of a parent to the charge center. Check the consistency
1203  // with ShPts and reverse if needed
1204  auto& ptj = slc.tjs[ss.ParentID - 1];
1205  // find the parent end farthest away from the charge center
1206  unsigned short pend = FarEnd(slc, ptj, stp1.Pos);
1207  auto& ptp = ptj.Pts[ptj.EndPt[pend]];
1208  auto& firstShPt = ss.ShPts[0];
1209  auto& lastShPt = ss.ShPts[ss.ShPts.size() - 1];
1210  if(PosSep2(ptp.Pos, lastShPt.Pos) < PosSep2(ptp.Pos, firstShPt.Pos)) ReverseShower(fcnLabel, slc, ss, prt);
1211  stj.Pts[0].Pos = ptp.Pos;
1212  } else {
1213  // no parent exists. Compare the DeltaRMS at the ends
1214  if(stj.Pts[2].DeltaRMS < stj.Pts[0].DeltaRMS) ReverseShower(fcnLabel, slc, ss, prt);
1215  stj.Pts[0].Pos = ss.ShPts[0].Pos;
1216  } // no parent
1217 
1218  if(stj.Pts[2].DeltaRMS > 0) ss.DirectionFOM = stj.Pts[0].DeltaRMS / stj.Pts[2].DeltaRMS;
1219  // define the end point
1220  stj.Pts[2].Pos = ss.ShPts[ss.ShPts.size() - 1].Pos;
1221 
1222  DefineEnvelope(fcnLabel, slc, ss, prt);
1223  ss.NeedsUpdate = false;
1224  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 2S"<<ss.ID<<" updated";
1225  return true;
1226 
1227  } // UpdateShower
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
Double_t xx
Definition: macro.C:12
void ReverseShower(std::string inFcnLabel, TCSlice &slc, int cotID, bool prt)
Definition: TCShower.cxx:3230
TCConfig tcc
Definition: DataStructs.cxx:6
Int_t B
Definition: plot.C:25
Float_t ss
Definition: plot.C:23
void DefineEnvelope(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3869
std::array< float, 2 > Point2_t
Definition: DataStructs.h:37
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:1643
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1660
unsigned short FarEnd(TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3032
Detector simulation of raw signals on wires.
bool lessThan(SortEntry c1, SortEntry c2)
Definition: TCShower.cxx:10
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
bool AnalyzeRotPos(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3102
float ChgToMeV(float chg)
Definition: TCShower.cxx:4395
TCEvent evt
Definition: DataStructs.cxx:5
bool tca::UpdateShower ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 1230 of file TCShower.cxx.

References tca::ShowerStruct3D::ChgPos, tca::ShowerStruct3D::CotIDs, tca::TCSlice::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::TCSlice::pfps, geo::PlaneID::Plane, tca::TrajPoint3::Pos, PosSep(), SetMag(), ss, tca::ShowerStruct3D::Start, tca::TCSlice::tjs, and tca::ShowerStruct3D::Vx3ID.

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

1231  {
1232  // Updates the 3D shower presumably because the 2D showers were changed or need to be updated.
1233  // This function returns false if there was a failure.
1234 
1235  if(ss3.ID == 0) return false;
1236  if(ss3.CotIDs.size() < 2) return false;
1237 
1238  std::string fcnLabel = inFcnLabel + ".U3S";
1239 
1240  // see if any of the 2D showers need an update
1241  for(auto cid : ss3.CotIDs) {
1242  auto& ss = slc.cots[cid - 1];
1243  if(ss.NeedsUpdate && prt) std::cout<<fcnLabel<<" ********* 3S"<<ss3.ID<<" 2S"<<ss.ID<<" needs an update...\n";
1244  UpdateShower(fcnLabel, slc, ss, prt);
1245  } // ci
1246 
1247  // check consistency
1248  if(ss3.ParentID > 0) {
1249  auto& pfp = slc.pfps[ss3.ParentID - 1];
1250  unsigned short pend = FarEnd(slc, pfp, ss3.ChgPos);
1251  if(pfp.Vx3ID[pend] != ss3.Vx3ID) {
1252  if(prt) std::cout<<fcnLabel<<" ********* 3S"<<ss3.ID<<" has parent P"<<ss3.ParentID<<" with a vertex that is not attached the shower\n";
1253  }
1254  } // ss3.ParentID > 0
1255 
1256  // Find the average position and direction using pairs of 2D shower Tjs
1257  std::array<Point3_t, 3> pos;
1258  // the direction of all points in 2D showers is the same
1259  Vector3_t dir;
1260  std::array<double, 3> chg;
1261  for(unsigned short ipt = 0; ipt < 3; ++ipt) {
1262  chg[ipt] = 0;
1263  for(unsigned short xyz = 0; xyz < 3; ++xyz) {
1264  pos[ipt][xyz] = 0;
1265  dir[xyz] = 0;
1266  }
1267  } // ipt
1268 
1269  for(unsigned short ii = 0; ii < ss3.CotIDs.size() - 1; ++ii) {
1270  unsigned short ciid = ss3.CotIDs[ii];
1271  auto& iss = slc.cots[ciid - 1];
1272  // make a local copy of the trajectory so we can replace Pos with HitPos = charge center
1273  auto istj = slc.tjs[iss.ShowerTjID - 1];
1274  for(auto& tp : istj.Pts) tp.Pos = tp.HitPos;
1275  for(unsigned short jj = ii + 1; jj < ss3.CotIDs.size(); ++jj) {
1276  unsigned short cjid = ss3.CotIDs[jj];
1277  auto& jss = slc.cots[cjid - 1];
1278  auto jstj = slc.tjs[jss.ShowerTjID - 1];
1279  for(auto& tp : jstj.Pts) tp.Pos = tp.HitPos;
1280  TrajPoint3 tp3;
1281  for(unsigned short ipt = 0; ipt < 3; ++ipt) {
1282  if(!MakeTp3(slc, istj.Pts[ipt], jstj.Pts[ipt], tp3, true)) continue;
1283  double ptchg = 0.5 * (istj.Pts[ipt].Chg + jstj.Pts[ipt].Chg);
1284  chg[ipt] += ptchg;
1285  for(unsigned short xyz = 0; xyz < 3; ++xyz) {
1286  pos[ipt][xyz] += ptchg * tp3.Pos[xyz];
1287  dir[xyz] += ptchg * tp3.Dir[xyz];
1288  } // xyz
1289  } // ipt
1290  } // jj
1291  } // ii
1292 
1293  unsigned short nok = 0;
1294  for(unsigned short ipt = 0; ipt < 3; ++ipt) {
1295  if(chg[ipt] == 0) continue;
1296  for(unsigned short xyz = 0; xyz < 3; ++xyz) pos[ipt][xyz] /= chg[ipt];
1297  SetMag(dir, 1);
1298  ++nok;
1299  } // ipt
1300 
1301  if(nok != 3) {
1302 // if(prt) std::cout<<fcnLabel<<" ********* 3S"<<ss3.ID<<" Can't find 3 points that match in 3D. \n";
1303  return false;
1304  }
1305  ss3.ChgPos = pos[1];
1306 
1307  if(ss3.ParentID > 0) {
1308  // There is a 3D-matched pfp at the shower start. The end that is farthest away from the
1309  // shower center should be shower start
1310  auto& pfp = slc.pfps[ss3.ParentID - 1];
1311  unsigned short pend = FarEnd(slc, pfp, ss3.ChgPos);
1312  ss3.Start = pfp.XYZ[pend];
1313  // TODO: use charge weighted average of shower direction and pfp direction?
1314  ss3.Dir = dir;
1315  } else {
1316  ss3.Dir = dir;
1317  ss3.Start = pos[0];
1318  }
1319  // define the end
1320  ss3.End = pos[2];
1321  ss3.Len = PosSep(ss3.Start, ss3.End);
1322 
1323  // dE/dx, energy, etc
1324  for(auto cid : ss3.CotIDs) {
1325  auto& ss = slc.cots[cid - 1];
1326  auto& stj = slc.tjs[ss.ShowerTjID - 1];
1327  unsigned short plane = DecodeCTP(ss.CTP).Plane;
1328  ss3.Energy[plane] = ss.Energy;
1329  // TODO: calculate the errors in some better way
1330  ss3.EnergyErr[plane] = 0.3 * ss.Energy;
1331  // TODO: what does MIPEnergy mean anyway?
1332  ss3.MIPEnergy[plane] = ss3.EnergyErr[plane];
1333  ss3.MIPEnergyErr[plane] = ss.Energy;
1334  ss3.dEdx[plane] = stj.dEdx[0];
1335  ss3.dEdxErr[plane] = 0.3 * stj.dEdx[0];
1336  } // ci
1337 
1338  ss3.NeedsUpdate = false;
1339  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" 3S"<<ss3.ID<<" updated";
1340  return true;
1341 
1342  } // UpdateShower
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeTp3(TCSlice &slc, const TrajPoint &itp, const TrajPoint &jtp, TrajPoint3 &tp3, bool findDirection)
Definition: PFPUtils.cxx:1555
Float_t ss
Definition: plot.C:23
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1230
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
unsigned short FarEnd(TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3032
bool SetMag(Vector3_t &v1, double mag)
Definition: PFPUtils.cxx:1670
TDirectory * dir
Definition: macro.C:5
geo::PlaneID DecodeCTP(CTP_t CTP)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:1654
std::array< double, 3 > Vector3_t
Definition: DataStructs.h:36
void tca::UpdateStiffEl ( TCSlice slc,
Trajectory tj 
)

Definition at line 633 of file StepUtils.cxx.

References tca::TrajPoint::AngleCode, tca::TCConfig::dbgStp, tca::TrajPoint::Delta, tca::Trajectory::EndPt, tca::TrajPoint::FitChi, FitTraj(), tca::TrajPoint::HitPos, kStiffEl, tca::Trajectory::MCSMom, MCSMom(), tca::Trajectory::NeedsUpdate, tca::TrajPoint::NTPsFit, tca::Trajectory::PDGCode, PointTrajDOCA(), tca::Trajectory::Pts, tca::Trajectory::Strategy, tcc, UpdateDeltaRMS(), and UpdateTjChgProperties().

Referenced by UpdateTraj().

634  {
635  // A different stategy for updating a high energy electron trajectories
636  if(!tj.Strategy[kStiffEl]) return;
637  TrajPoint& lastTP = tj.Pts[tj.EndPt[1]];
638  // Set the lastPT delta before doing the fit
639  lastTP.Delta = PointTrajDOCA(slc, lastTP.HitPos[0], lastTP.HitPos[1], lastTP);
640  if(tj.Pts.size() < 30) lastTP.NTPsFit += 1;
641  FitTraj(slc, tj);
642  UpdateTjChgProperties("UET", slc, tj, tcc.dbgStp);
643  UpdateDeltaRMS(slc, tj);
644 // SetAngleCode(lastTP);
645  tj.MCSMom = MCSMom(slc, tj);
646  if(tcc.dbgStp) {
647  mf::LogVerbatim("TC")<<"UpdateStiffEl: lastPt "<<tj.EndPt[1]<<" Delta "<<lastTP.Delta<<" AngleCode "<<lastTP.AngleCode<<" FitChi "<<lastTP.FitChi<<" NTPsFit "<<lastTP.NTPsFit<<" MCSMom "<<tj.MCSMom;
648  }
649  tj.NeedsUpdate = false;
650  tj.PDGCode = 111;
651  return;
652  } // UpdateStiffTj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
short MCSMom(TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2914
TCConfig tcc
Definition: DataStructs.cxx:6
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
void FitTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:753
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3196
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
use the stiff electron strategy
Definition: DataStructs.h:418
void UpdateDeltaRMS(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2635
void tca::UpdateTjChgProperties ( std::string  inFcnLabel,
TCSlice slc,
Trajectory tj,
bool  prt 
)

Definition at line 3196 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::TCEvent::allHits, tca::Trajectory::AveChg, tca::Trajectory::ChgRMS, evd::details::end(), tca::Trajectory::EndPt, evt, kEnvNearTj, kEnvOverlap, kEnvUnusedHits, kHaloTj, kKilled, kPhoton, tca::Trajectory::NeedsUpdate, tca::TCConfig::nPtsAve, tca::Trajectory::Pts, tca::TCSlice::slHits, tcc, tca::Trajectory::TotChg, tca::Trajectory::VtxID, and tca::TCSlice::vtxs.

Referenced by AddLAHits(), ChkStopEndPts(), DotProd(), Forecast(), MaskedHitsOK(), MaxChargeAsymmetry(), SplitTraj(), StoreTraj(), UpdateStiffEl(), UpdateTraj(), and UpdateVxEnvironment().

3197  {
3198  // Updates properties of the tj that are affected when the TP environment
3199  // is changed. The most likely reason for a change is when the tj is attached to a
3200  // vertex in which case the Environment kEnvOverlap bit may be set by the UpdateVxEnvironment
3201  // function in which case this function is called.
3202  // The kEnvNearShower bit may be set by TagShowerTjs but this doesn't affect the
3203  // calculation of the properties of this Tj.tcc.maxPos0 This function simply sets the kEnvUnusedHits bit
3204  // for all TPs.
3205  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) return;
3206 
3207  std::string fcnLabel = inFcnLabel + ".UpTjProp";
3208 
3209  // first (un)set some bits
3210  for(auto& tp : tj.Pts) {
3211  if(tp.Chg <= 0) continue;
3212  tp.Environment[kEnvUnusedHits] = false;
3213  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3214  if(tp.UseHit[ii]) continue;
3215  unsigned int iht = tp.Hits[ii];
3216  if(slc.slHits[iht].InTraj == 0) {
3217  tp.Environment[kEnvUnusedHits] = true;
3218  } else {
3219  tp.Environment[kEnvNearTj] = true;
3220  }
3221  } // ii
3222  } // tp
3223 
3224  // Update the tj charge variables. The concept is explained by this graphic where
3225  // each column is a wire, Q = a TP with charge, q = a TP with charge that is an
3226  // EnvOverlap region, x = a wire that has a TP with Chg = 0 or a wire that has no TP
3227  // because the wire is dead, o = an EnvOverlap region, V = vertex attached to end. You should
3228  // imagine that all 3 tjs come from the same vertex
3229  // 01234567890123456789 npwc cnt range
3230  // VooooQQQQxxxQQQ 7 7 0 - 14
3231  // VqqqqQQQQxxxQQQQQQQQ 16 12 0 - 19
3232  // VooQQQ 3 3 0 - 5
3233  // The average is first calculated using Ave = sum(Q) / npwc
3234  // TotChg is calculated using
3235  tj.TotChg = 0;
3236  tj.AveChg = 0;
3237  tj.ChgRMS = 0.5;
3238 
3239  // These variables are used to calculate the average and rms using valid points with charge
3240  double vcnt = 0;
3241  double vsum = 0;
3242  double vsum2 = 0;
3243  // Reject a single large charge TP
3244  float bigChg = 0;
3245  for(unsigned short ipt = tj.EndPt[0] + 1; ipt < tj.EndPt[1]; ++ipt) {
3246  auto& tp = tj.Pts[ipt];
3247  if(tp.Chg > bigChg) bigChg = tp.Chg;
3248  } // ipt
3249  // variables for calculating the backup quanties. These are only used if npwc < 3
3250  double bcnt = 0;
3251  double bsum = 0;
3252  double bsum2 = 0;
3253  // don't include the end points
3254  for(unsigned short ipt = tj.EndPt[0] + 1; ipt < tj.EndPt[1]; ++ipt) {
3255  auto& tp = tj.Pts[ipt];
3256  if(tp.Chg <= 0) continue;
3257  // ignore the single large charge TP
3258  if(tp.Chg == bigChg) continue;
3259  // accumulate a backup sum in case most of the points are overlapped. Note that
3260  // tp.Chg has an angle correction, which is why the hit integral is summed
3261  // below. We don't care about this detail for the backup sum
3262  bsum += tp.Chg;
3263  bsum2 += tp.Chg * tp.Chg;
3264  if(tp.Chg > bigChg) bigChg = tp.Chg;
3265  ++bcnt;
3266  // Skip TPs that overlap with TPs on other Tjs. A correction will be made below
3267  if(tj.Pts[ipt].Environment[kEnvOverlap]) continue;
3268  ++vcnt;
3269  double tpchg = 0;
3270  for(unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
3271  if(!tp.UseHit[ii]) continue;
3272  unsigned int iht = tp.Hits[ii];
3273  tpchg += (*evt.allHits)[slc.slHits[iht].allHitsIndex].Integral();
3274  } // ii
3275  vsum += tpchg;
3276  vsum2 += tpchg * tpchg;
3277  } // ipt
3278 
3279  if(bcnt == 0) return;
3280 
3281  if(vcnt < 3) {
3282  // use the backup sum
3283  tj.TotChg = bsum;
3284  tj.AveChg = bsum / bcnt;
3285  if(vcnt > 2) {
3286  double arg = bsum2 - bcnt * tj.AveChg * tj.AveChg;
3287  if(arg > 0) tj.ChgRMS = sqrt(arg / (bcnt - 1));
3288  }
3289  for(auto& tp : tj.Pts) tp.AveChg = tj.AveChg;
3290  return;
3291  } // low npwc
3292 
3293  double nWires = tj.EndPt[1] - tj.EndPt[0] + 1;
3294  if(nWires < 2) return;
3295  // correct for wires missing near vertices.
3296  // Count the number of wires between vertices at the ends and the first wire
3297  // that has charge. This code assumes that there should be one TP on each wire
3298  if(!tj.AlgMod[kPhoton]) {
3299  for(unsigned short end = 0; end < 2; ++end) {
3300  if(tj.VtxID[end] == 0) continue;
3301  auto& tp = tj.Pts[tj.EndPt[end]];
3302  auto& vx2 = slc.vtxs[tj.VtxID[end] - 1];
3303  int dw = std::abs(tp.Pos[0] - vx2.Pos[0]);
3304  // This assumes that the vertex is not inside the wire boundaries of the tj
3305  nWires += dw;
3306  } // end
3307  } // not a photon Tj
3308 
3309  tj.AveChg = vsum / vcnt;
3310  // calculate the total charge using the tj wire range
3311  tj.TotChg = nWires * tj.AveChg;
3312  // calculate the rms
3313  double arg = vsum2 - vcnt * tj.AveChg * tj.AveChg;
3314  double rms = 0.5;
3315  if(arg > 0) rms = sqrt(arg / (vcnt - 1));
3316  rms /= tj.AveChg;
3317  // don't let it be an unrealistically low value. It could be crazy large however.
3318  if(rms < 0.1) rms = 0.1;
3319  // Don't let the calculated charge RMS dominate until it is well known; after there are 5 - 10 valid TPs.
3320  // Set the starting charge rms = 0.5
3321  if(vcnt < 10) {
3322  double defFrac = 1 / vcnt;
3323  rms = defFrac * 0.5 + (1 - defFrac) * rms;
3324  }
3325  tj.ChgRMS = rms;
3326 
3327  // Update the TP charge pulls.
3328  // Don't let the calculated charge RMS dominate the default
3329  // RMS until it is well known. Start with 50% error on the
3330  // charge RMS
3331  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
3332  auto& tp = tj.Pts[ipt];
3333  if(tp.Chg <= 0) continue;
3334  tp.ChgPull = (tp.Chg / tj.AveChg - 1) / tj.ChgRMS;
3335  } // ipt
3336 
3337  // update the local charge average using NPtsAve of the preceding points.
3338  // Handle short Tjs first.
3339  if(vcnt < tcc.nPtsAve) {
3340  for(auto& tp : tj.Pts) tp.AveChg = tj.AveChg;
3341  return;
3342  }
3343 
3344  // Set the local average to 0 first
3345  for(auto& tp : tj.Pts) tp.AveChg = 0;
3346  // Enter the local average on the points where an average can be calculated
3347  unsigned short nptsave = tcc.nPtsAve;
3348  unsigned short minPt = tj.EndPt[0] + nptsave;
3349  float lastAve = 0;
3350  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
3351  unsigned short ipt = tj.EndPt[1] - ii;
3352  if(ipt < minPt) break;
3353  float cnt = 0;
3354  float sum = 0;
3355  for(unsigned short iii = 0; iii < nptsave; ++iii) {
3356  unsigned short iipt = ipt - iii;
3357  // Don't include the charge of the first point
3358  if(iipt == tj.EndPt[0]) break;
3359  auto& tp = tj.Pts[iipt];
3360  if(tp.Chg <= 0) continue;
3361  sum += tp.Chg;
3362  ++cnt;
3363  } // iii
3364  if(cnt > 2) {
3365  tj.Pts[ipt].AveChg = sum / cnt;
3366  lastAve = tj.Pts[ipt].AveChg;
3367  }
3368  } // ii
3369  // Fill in the points where no average was calculated
3370  for(unsigned short ii = tj.EndPt[0]; ii <= tj.EndPt[1]; ++ii) {
3371  unsigned short ipt = tj.EndPt[1] - ii;
3372  auto& tp = tj.Pts[ipt];
3373  if(tp.AveChg == 0) {
3374  tp.AveChg = lastAve;
3375  } else {
3376  lastAve = tp.AveChg;
3377  }
3378  } // ii
3379 
3380  tj.NeedsUpdate = false;
3381 
3382  } // UpdateTjChgProperties
TCConfig tcc
Definition: DataStructs.cxx:6
short nPtsAve
dump trajectory points
Definition: DataStructs.h:523
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:536
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
TCEvent evt
Definition: DataStructs.cxx:5
void tca::UpdateTp3s ( TCSlice slc,
PFPStruct pfp,
int  oldTj,
int  newTj 
)

Definition at line 229 of file PFPUtils.cxx.

References detinfo::DetectorProperties::ConvertTicksToX(), DecodeCTP(), tca::TCConfig::detprop, tca::TCSlice::mallTraj, tcc, tca::TCSlice::tjs, tca::PFPStruct::Tp3s, and tca::TCConfig::unitsPerTick.

Referenced by MergePFPTjs().

230  {
231  // Replaces occurrences of oldTj with newTj in the pfp vector of Tp3s
232  if(oldTj <= 0 || oldTj > (int)slc.tjs.size()) return;
233  if(newTj <= 0 || newTj > (int)slc.tjs.size()) return;
234  if(slc.mallTraj.empty() && pfp.Tp3s.empty()) return;
235 
236  // convert from int to unsigned short
237  unsigned short oldtjid = oldTj;
238  unsigned short newtjid = newTj;
239  auto& ntj = slc.tjs[newTj - 1];
240  unsigned short npts = ntj.EndPt[1] - ntj.EndPt[0] + 1;
241  // put the X positions of the new Tj into a vector for matching
242  std::vector<float> xpos(ntj.Pts.size());
243  geo::PlaneID planeID = DecodeCTP(ntj.CTP);
244  for(unsigned short npt = ntj.EndPt[0]; npt <= ntj.EndPt[1]; ++npt) {
245  auto& ntp = ntj.Pts[npt];
246  if(ntp.Chg <= 0) continue;
247  xpos[npt] = tcc.detprop->ConvertTicksToX(ntp.Pos[1]/tcc.unitsPerTick, planeID);
248  } // npt
249 
250  for(auto& tp3 : pfp.Tp3s) {
251  // check each of the Tj2Pts associated with this space point
252  for(auto& tj2pt : tp3.Tj2Pts) {
253  if(tj2pt.id > slc.tjs.size()) continue;
254  if(tj2pt.id != oldtjid) continue;
255  // look for the corresponding point (wire) on the new Tj
256  for(unsigned short npt = ntj.EndPt[0]; npt <= ntj.EndPt[1]; ++npt) {
257  auto& ntp = ntj.Pts[npt];
258  if(std::nearbyint(ntp.Pos[0]) == tj2pt.wire && xpos[npt] > tj2pt.xlo && xpos[npt] < tj2pt.xhi) {
259  tj2pt.id = newtjid;
260  tj2pt.ipt = npt;
261  tj2pt.npts = npts;
262  break;
263  }
264  } // npt
265  } // tj2pt
266  } // tp3
267 
268  } // UpdateTp3s
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:488
const detinfo::DetectorProperties * detprop
Definition: DataStructs.h:494
virtual double ConvertTicksToX(double ticks, int p, int t, int c) const =0
geo::PlaneID DecodeCTP(CTP_t CTP)
void tca::UpdateTraj ( TCSlice slc,
Trajectory tj 
)

Definition at line 655 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::TrajPoint::AngErr, tca::TrajPoint::AngleCode, tca::TrajPoint::Chg, tca::Trajectory::CTP, tca::TCConfig::dbgStp, DeadWireCount(), DefineHitPos(), tca::TrajPoint::Delta, tca::TrajPoint::Dir, tca::Trajectory::EndPt, tca::TrajPoint::FitChi, FitTraj(), tca::TrajPoint::HitPos, kNewStpCuts, kRvPrp, kSlowing, kStiffEl, MaskBadTPs(), tca::Trajectory::MaskedLastTP, tca::TCConfig::maxChi, tca::Trajectory::MCSMom, MCSMom(), tca::TCConfig::minPtsFit, tca::TCConfig::muonTag, tca::Trajectory::NeedsUpdate, tca::TrajPoint::NTPsFit, NumPtsWithCharge(), tca::Trajectory::Pass, tca::Trajectory::PDGCode, PointTrajDOCA(), tca::TrajPoint::Pos, tca::Trajectory::Pts, SetAngleCode(), SetEndPoints(), tca::Trajectory::Strategy, tcc, TrajIsClean(), UnsetUsedHits(), UpdateDeltaRMS(), UpdateStiffEl(), UpdateTjChgProperties(), and tca::TCConfig::useAlg.

Referenced by CheckHiMultUnusedHits(), and StepAway().

656  {
657  // Updates the last added trajectory point fit, average hit rms, etc.
658 
659  tj.NeedsUpdate = true;
660  tj.MaskedLastTP = false;
661 
662  if(tj.EndPt[1] < 1) return;
663 
664  if(tj.Strategy[kStiffEl]) {
665  UpdateStiffEl(slc, tj);
666  return;
667  }
668  unsigned int lastPt = tj.EndPt[1];
669  TrajPoint& lastTP = tj.Pts[lastPt];
670  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
671 
672  // find the previous TP that has hits (and was therefore in the fit)
673  unsigned short prevPtWithHits = USHRT_MAX;
674  unsigned short firstFitPt = tj.EndPt[0];
675  for(unsigned short ii = 1; ii < tj.Pts.size(); ++ii) {
676  unsigned short ipt = lastPt - ii;
677  if(tj.Pts[ipt].Chg > 0) {
678  prevPtWithHits = ipt;
679  break;
680  }
681  if(ipt == 0) break;
682  } // ii
683  if(prevPtWithHits == USHRT_MAX) return;
684 
685  // define the FitChi threshold above which something will be done
686  float maxChi = 2;
687  unsigned short minPtsFit = tcc.minPtsFit[tj.Pass];
688  // just starting out?
689  if(lastPt < 4) minPtsFit = 2;
690  bool cleanMuon = (tj.PDGCode == 13 && TrajIsClean(slc, tj, tcc.dbgStp) && !tj.Strategy[kSlowing]);
691  // was !TrajIsClean...
692  if(cleanMuon) {
693  // Fitting a clean muon
694  maxChi = tcc.maxChi;
695  minPtsFit = lastPt / 3;
696  }
697 
698  // Set the lastPT delta before doing the fit
699  lastTP.Delta = PointTrajDOCA(slc, lastTP.HitPos[0], lastTP.HitPos[1], lastTP);
700 
701  // update MCSMom. First ensure that nothing bad has happened
702  if(npwc > 3 && tj.Pts[lastPt].Chg > 0 && !tj.Strategy[kSlowing]) {
703  short newMCSMom = MCSMom(slc, tj);
704  short minMCSMom = 0.6 * tj.MCSMom;
705  if(tcc.useAlg[kNewStpCuts]) minMCSMom = 0.5 * tj.MCSMom;
706  if(lastPt > 10 && newMCSMom < minMCSMom) {
707  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"UpdateTraj: MCSMom took a nose-dive "<<newMCSMom;
708  UnsetUsedHits(slc, lastTP);
709  DefineHitPos(slc, lastTP);
710  SetEndPoints(tj);
711  tj.NeedsUpdate = false;
712  return;
713  }
714  tj.MCSMom = newMCSMom;
715  } // npwc > 3
716 
717 
718  if(tcc.dbgStp) {
719  mf::LogVerbatim("TC")<<"UpdateTraj: lastPt "<<lastPt<<" lastTP.Delta "<<lastTP.Delta<<" previous point with hits "<<prevPtWithHits<<" tj.Pts size "<<tj.Pts.size()<<" AngleCode "<<lastTP.AngleCode<<" PDGCode "<<tj.PDGCode<<" maxChi "<<maxChi<<" minPtsFit "<<minPtsFit<<" MCSMom "<<tj.MCSMom;
720  }
721 
722  UpdateTjChgProperties("UT", slc, tj, tcc.dbgStp);
723 
724  if(lastPt == 1) {
725  // Handle the second trajectory point. No error calculation. Just update
726  // the position and direction
727  lastTP.NTPsFit = 2;
728  FitTraj(slc, tj);
729  lastTP.FitChi = 0.01;
730  lastTP.AngErr = tj.Pts[0].AngErr;
731  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"UpdateTraj: Second traj point pos "<<lastTP.Pos[0]<<" "<<lastTP.Pos[1]<<" dir "<<lastTP.Dir[0]<<" "<<lastTP.Dir[1];
732  tj.NeedsUpdate = false;
733  SetAngleCode(lastTP);
734  return;
735  }
736 
737  if(lastPt == 2) {
738  // Third trajectory point. Keep it simple
739  lastTP.NTPsFit = 3;
740  FitTraj(slc, tj);
741  tj.NeedsUpdate = false;
742  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"UpdateTraj: Third traj point fit "<<lastTP.FitChi;
743  SetAngleCode(lastTP);
744  return;
745  }
746 
747  // Fit with > 2 TPs
748  // Keep adding hits until Chi/DOF exceeds 1
749  if(tj.Pts[prevPtWithHits].FitChi < 1 && !tj.Strategy[kSlowing]) lastTP.NTPsFit += 1;
750  // Reduce the number of points fit if the trajectory is long and chisq is getting a bit larger
751  if(lastPt > 20 && tj.Pts[prevPtWithHits].FitChi > 1.5 && lastTP.NTPsFit > minPtsFit) lastTP.NTPsFit -= 2;
752  // don't let long muon fits get too long
753  if(tcc.useAlg[kNewStpCuts] && cleanMuon && lastPt > 200 && tj.Pts[prevPtWithHits].FitChi > 1.0) lastTP.NTPsFit -= 2;
754 
755  FitTraj(slc, tj);
756 
757  // don't get too fancy when we are starting out
758  if(lastPt < 6) {
759  tj.NeedsUpdate = false;
760  UpdateDeltaRMS(slc, tj);
761  SetAngleCode(lastTP);
762  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Return with lastTP.FitChi "<<lastTP.FitChi<<" Chg "<<lastTP.Chg;
763  return;
764  }
765 
766  // find the first point that was fit.
767  unsigned short cnt = 0;
768  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
769  unsigned short ipt = lastPt - ii;
770  if(tj.Pts[ipt].Chg > 0) {
771  firstFitPt = ipt;
772  ++cnt;
773  }
774  if(cnt == lastTP.NTPsFit) break;
775  if(ipt == 0) break;
776  }
777 
778  unsigned short ndead = DeadWireCount(slc, lastTP.HitPos[0], tj.Pts[firstFitPt].HitPos[0], tj.CTP);
779  if(lastTP.FitChi > 1.5 && tj.Pts.size() > 6) {
780  // A large chisq jump can occur if we just jumped a large block of dead wires. In
781  // this case we don't want to mask off the last TP but reduce the number of fitted points
782  // This count will be off if there a lot of dead or missing wires...
783  // reduce the number of points significantly
784  if(ndead > 5 && !cleanMuon) {
785  if(lastTP.NTPsFit > 5) lastTP.NTPsFit = 5;
786  } else {
787  // Have a longish trajectory and chisq was a bit large.
788  // Was this a sudden occurrence and the fraction of TPs are included
789  // in the fit? If so, we should mask off this
790  // TP and keep going. If these conditions aren't met, we
791  // should reduce the number of fitted points
792  float chirat = 0;
793  if(prevPtWithHits != USHRT_MAX && tj.Pts[prevPtWithHits].FitChi > 0) chirat = lastTP.FitChi / tj.Pts[prevPtWithHits].FitChi;
794  // Don't mask hits when doing RevProp. Reduce NTPSFit instead
795  tj.MaskedLastTP = (chirat > 1.5 && lastTP.NTPsFit > 0.3 * NumPtsWithCharge(slc, tj, false) && !tj.AlgMod[kRvPrp]);
796  // BB April 19, 2018: Don't mask TPs on low MCSMom Tjs
797  if(tj.MaskedLastTP && tj.MCSMom < 30) tj.MaskedLastTP = false;
798  if(tcc.dbgStp) {
799  mf::LogVerbatim("TC")<<" First fit chisq too large "<<lastTP.FitChi<<" prevPtWithHits chisq "<<tj.Pts[prevPtWithHits].FitChi<<" chirat "<<chirat<<" NumPtsWithCharge "<<NumPtsWithCharge(slc, tj, false)<<" tj.MaskedLastTP "<<tj.MaskedLastTP;
800  }
801  // we should also mask off the last TP if there aren't enough hits
802  // to satisfy the minPtsFit constraint
803  if(!tj.MaskedLastTP && NumPtsWithCharge(slc, tj, true) < minPtsFit) tj.MaskedLastTP = true;
804  } // few dead wires
805  } // lastTP.FitChi > 2 ...
806 
807  // Deal with a really long trajectory that is in trouble (uB cosmic).
808  if(tj.PDGCode == 13 && lastTP.FitChi > tcc.maxChi) {
809  if(lastTP.NTPsFit > 1.3 * tcc.muonTag[0]) {
810  lastTP.NTPsFit *= 0.8;
811  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Muon - Reduce NTPsFit "<<lastPt;
812  } else {
813  tj.MaskedLastTP = true;
814  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Muon - mask last point "<<lastPt;
815  }
816  }
817 
818  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"UpdateTraj: First fit "<<lastTP.Pos[0]<<" "<<lastTP.Pos[1]<<" dir "<<lastTP.Dir[0]<<" "<<lastTP.Dir[1]<<" FitChi "<<lastTP.FitChi<<" NTPsFit "<<lastTP.NTPsFit<<" ndead wires "<<ndead<<" tj.MaskedLastTP "<<tj.MaskedLastTP;
819  if(tj.MaskedLastTP) {
820  UnsetUsedHits(slc, lastTP);
821  DefineHitPos(slc, lastTP);
822  SetEndPoints(tj);
823  lastPt = tj.EndPt[1];
824  lastTP.NTPsFit -= 1;
825  FitTraj(slc, tj);
826  UpdateTjChgProperties("UT", slc, tj, tcc.dbgStp);
827  SetAngleCode(lastTP);
828  return;
829  } else {
830  // a more gradual change in chisq. Maybe reduce the number of points
831  unsigned short newNTPSFit = lastTP.NTPsFit;
832  // reduce the number of points fit to keep Chisq/DOF < 2 adhering to the pass constraint
833  // and also a minimum number of points fit requirement for long muons
834  float prevChi = lastTP.FitChi;
835  unsigned short ntry = 0;
836  float chiCut = 1.5;
837  while(lastTP.FitChi > chiCut && lastTP.NTPsFit > minPtsFit) {
838  if(lastTP.NTPsFit > 15) {
839  newNTPSFit = 0.7 * newNTPSFit;
840  } else if(lastTP.NTPsFit > 4) {
841  newNTPSFit -= 2;
842  } else {
843  newNTPSFit -= 1;
844  }
845  if(lastTP.NTPsFit < 3) newNTPSFit = 2;
846  if(newNTPSFit < minPtsFit) newNTPSFit = minPtsFit;
847  lastTP.NTPsFit = newNTPSFit;
848  // BB April 19: try to add a last lonely hit on a low MCSMom tj on the last try
849  if(newNTPSFit == minPtsFit && tj.MCSMom < 30) chiCut = 2;
850  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Bad FitChi "<<lastTP.FitChi<<" Reduced NTPsFit to "<<lastTP.NTPsFit<<" Pass "<<tj.Pass<<" chiCut "<<chiCut;
851  FitTraj(slc, tj);
852  tj.NeedsUpdate = true;
853  if(lastTP.FitChi > prevChi) {
854  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Chisq is increasing "<<lastTP.FitChi<<" Try to remove an earlier bad hit";
855  MaskBadTPs(slc, tj, chiCut);
856  ++ntry;
857  if(ntry == 2) break;
858  }
859  prevChi = lastTP.FitChi;
860  if(lastTP.NTPsFit == minPtsFit) break;
861  } // lastTP.FitChi > 2 && lastTP.NTPsFit > 2
862  }
863  // last ditch attempt if things look bad. Drop the last hit
864  if(tj.Pts.size() > tcc.minPtsFit[tj.Pass] && lastTP.FitChi > maxChi) {
865  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Last try. Drop last TP "<<lastTP.FitChi<<" NTPsFit "<<lastTP.NTPsFit;
866  UnsetUsedHits(slc, lastTP);
867  DefineHitPos(slc, lastTP);
868  SetEndPoints(tj);
869  lastPt = tj.EndPt[1];
870  FitTraj(slc, tj);
871  tj.MaskedLastTP = true;
872  }
873 
874  if(tj.NeedsUpdate) UpdateTjChgProperties("UT", slc, tj, tcc.dbgStp);
875 
876  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Fit done. Chi "<<lastTP.FitChi<<" NTPsFit "<<lastTP.NTPsFit;
877 
878  if(tj.EndPt[0] == tj.EndPt[1]) return;
879 
880  // Don't let the angle error get too small too soon. Stepping would stop if the first
881  // few hits on a low momentum wandering track happen to have a very good fit to a straight line.
882  // We will do this by averaging the default starting value of AngErr of the first TP with the current
883  // value from FitTraj.
884  if(lastPt < 14) {
885  float defFrac = 1 / (float)(tj.EndPt[1]);
886  lastTP.AngErr = defFrac * tj.Pts[0].AngErr + (1 - defFrac) * lastTP.AngErr;
887  }
888 
889  UpdateDeltaRMS(slc, tj);
890  SetAngleCode(lastTP);
891 
892  tj.NeedsUpdate = false;
893  return;
894 
895  } // UpdateTraj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
std::vector< unsigned short > minPtsFit
Reconstruct in several passes.
Definition: DataStructs.h:482
short MCSMom(TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:2914
TCConfig tcc
Definition: DataStructs.cxx:6
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1162
void SetAngleCode(TrajPoint &tp)
Definition: Utils.cxx:722
float DeadWireCount(TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:1881
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:508
use the slowing-down strategy
Definition: DataStructs.h:420
bool TrajIsClean(TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:2891
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1840
void FitTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:753
void UpdateStiffEl(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:633
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3196
unsigned short NumPtsWithCharge(TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:1863
void MaskBadTPs(TCSlice &slc, Trajectory &tj, float const &maxChi)
Definition: StepUtils.cxx:2665
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
std::vector< short > muonTag
min length and min MCSMom for a muon tag
Definition: DataStructs.h:471
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
use the stiff electron strategy
Definition: DataStructs.h:418
void UpdateDeltaRMS(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2635
void tca::UpdateVxEnvironment ( std::string  inFcnLabel,
TCSlice slc,
VtxStore vx2,
bool  prt 
)

Definition at line 3385 of file Utils.cxx.

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

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

3386  {
3387  // Update the Environment each TP on trajectories near the vertex. This is called when
3388  // the Tj has been added to a vertex to identify nearby trajectories that contribute to
3389  // the charge on TPs near the vertex.
3390  if(vx2.ID == 0) return;
3391  if(vx2.Stat[kOnDeadWire]) return;
3392 
3393  std::string fcnLabel = inFcnLabel + ".UpVxProp";
3394 
3395  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" UpdateTjEnvironment check Tjs attached to vx2 "<<vx2.ID;
3396 
3397  std::vector<int> tjlist;
3398  std::vector<unsigned short> tjends;
3399  if(vx2.Pos[0] < -0.4) return;
3400  unsigned int vxWire = std::nearbyint(vx2.Pos[0]);
3401  unsigned int loWire = vxWire;
3402  unsigned int hiWire = vxWire;
3403  for(auto& tj : slc.tjs) {
3404  if(tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
3405  if(tj.CTP != vx2.CTP) continue;
3406  // ignore photon Tjs
3407  if(tj.AlgMod[kPhoton]) continue;
3408  for(unsigned short end = 0; end < 2; ++end) {
3409  if(tj.VtxID[end] != vx2.ID) continue;
3410  tjlist.push_back(tj.ID);
3411  tjends.push_back(end);
3412  if(tj.Pts[tj.EndPt[end]].Pos[0] < -0.4) return;
3413  unsigned int endWire = std::nearbyint(tj.Pts[tj.EndPt[end]].Pos[0]);
3414  if(endWire < loWire) loWire = endWire;
3415  if(endWire > hiWire) hiWire = endWire;
3416  } // end
3417  } // tj
3418  if(tjlist.size() < 2) return;
3419  if(hiWire < loWire + 1) return;
3420  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" check Tjs on wires in the range "<<loWire<<" to "<<hiWire;
3421 
3422  // create a vector of TPs between loWire and hiWire for every tj in the list
3423  // wire TP
3424  std::vector<std::vector<TrajPoint>> wire_tjpt;
3425  // companion vector of IDs
3426  std::vector<int> tjids;
3427  // populate this vector with TPs on Tjs that are in this range
3428  unsigned short nwires = hiWire - loWire + 1;
3429  for(unsigned short itj = 0; itj < tjlist.size(); ++itj) {
3430  auto& tj = slc.tjs[tjlist[itj] - 1];
3431  unsigned short end = tjends[itj];
3432  std::vector<TrajPoint> tjpt(nwires);
3433  // first enter valid TPs in the range
3434  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
3435  unsigned short ipt;
3436  if(end == 0) { ipt = tj.EndPt[0] + ii; } else { ipt = tj.EndPt[1] - ii; }
3437  if(ipt > tj.Pts.size() - 1) break;
3438  // Make a copy of the TP so we can alter it
3439  auto tp = tj.Pts[ipt];
3440  if(tp.Chg <= 0) continue;
3441  tp.Chg = 1;
3442  tp.Hits.clear();
3443  if(tp.Pos[0] < -0.4) continue;
3444  unsigned int wire = std::nearbyint(tp.Pos[0]);
3445  unsigned short indx = wire - loWire;
3446  if(indx > nwires - 1) break;
3447  tp.Step = ipt;
3448  // We will use NTPsFit to count the number of neighboring TPs
3449  tp.NTPsFit = 0;
3450  tjpt[indx] = tp;
3451  } // ii
3452  // next make TPs on the wires that don't have real TPs
3453  TrajPoint ltp;
3454  // put ltp at the vertex position with direction towards the end point
3455  MakeBareTrajPoint(vx2.Pos, tj.Pts[tj.EndPt[end]].Pos, ltp);
3456  if(ltp.Dir[0] == 0) continue;
3457  if(ltp.Pos[0] < -0.4) continue;
3458  unsigned int wire = std::nearbyint(ltp.Pos[0]);
3459  ltp.Chg = 0;
3460  unsigned short indx = wire - loWire;
3461  // Break if we found a real TP
3462  if(tjpt[indx].Chg == 0) tjpt[indx] = ltp;
3463  double stepSize = std::abs(1/ltp.Dir[0]);
3464  for(unsigned short ii = 0; ii < nwires; ++ii) {
3465  // move the local TP position by one step in the right direction
3466  for(unsigned short iwt = 0; iwt < 2; ++iwt) ltp.Pos[iwt] += ltp.Dir[iwt] * stepSize;
3467  if(ltp.Pos[0] < -0.4) break;
3468  wire = std::nearbyint(ltp.Pos[0]);
3469  if(wire < loWire || wire > hiWire) break;
3470  indx = wire - loWire;
3471  if(tjpt[indx].Chg > 0) continue;
3472  tjpt[indx]= ltp;
3473  } // ii
3474  if(prt) {
3475  mf::LogVerbatim myprt("TC");
3476  myprt<<fcnLabel<<" T"<<tj.ID;
3477  for(auto& tp : tjpt) myprt<<" "<<PrintPos(slc, tp.Pos)<<"_"<<tp.Step<<"_"<<(int)tp.Chg;
3478  }
3479  wire_tjpt.push_back(tjpt);
3480  tjids.push_back(tj.ID);
3481  } // itj
3482 
3483  // iterate over the wires in the range
3484  for(unsigned short indx = 0; indx < nwires; ++indx) {
3485  // count the number of valid points on this wire
3486  unsigned short npts = 0;
3487  // count the number of points on this wire that have charge
3488  unsigned short npwc = 0;
3489  for(unsigned short itj = 0; itj < wire_tjpt.size(); ++itj) {
3490  if(wire_tjpt[itj][indx].Pos[0] == 0) continue;
3491  // found a valid point
3492  ++npts;
3493  if(wire_tjpt[itj][indx].Chg > 0) ++npwc;
3494  } // itj
3495  // no valid points
3496 // if(prt) mf::LogVerbatim("TC")<<" wire "<<loWire + indx<<" npts "<<npts<<" npwc "<<npwc;
3497  if(npts == 0) continue;
3498  // all valid points have charge
3499  if(npwc == npts) continue;
3500  // re-find the valid points with charge and set the kEnvOverlap bit
3501  for(unsigned short itj = 0; itj < wire_tjpt.size(); ++itj) {
3502  if(wire_tjpt[itj][indx].Pos[0] == 0) continue;
3503  if(wire_tjpt[itj][indx].Chg == 0) continue;
3504  auto& tj = slc.tjs[tjids[itj] - 1];
3505  unsigned short ipt = wire_tjpt[itj][indx].Step;
3506  tj.Pts[ipt].Environment[kEnvOverlap] = true;
3507  tj.NeedsUpdate = true;
3508  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Set kEnvOverlap bit on T"<<tj.ID<<" ipt "<<ipt;
3509  } // itj
3510  } // indx
3511 
3512  // update the charge rms for those tjs whose environment was changed above (or elsewhere)
3513  for(auto tjid : tjids) {
3514  auto& tj = slc.tjs[tjid - 1];
3515  if(!tj.NeedsUpdate) continue;
3516  if(tj.CTP != vx2.CTP) continue;
3517  UpdateTjChgProperties(fcnLabel, slc, tj, prt);
3518  } // tjid
3519 
3520  } // UpdateVxEnvironment
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::string PrintPos(TCSlice &slc, const Point2_t &pos)
Definition: Utils.cxx:5718
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3196
bool MakeBareTrajPoint(TCSlice &slc, const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
Definition: Utils.cxx:3628
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool tca::valDecreasing ( SortEntry  c1,
SortEntry  c2 
)

Definition at line 10 of file TCVertex.cxx.

References tca::SortEntry::val.

Referenced by FindVtxTjs(), Match3DVtxTjs(), and MergeWithVertex().

10 { return (c1.val > c2.val);}
float val
Definition: StepUtils.cxx:6
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: StepUtils.cxx:6
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: StepUtils.cxx:6
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: StepUtils.cxx:6
float tca::VertexVertexPull ( TCSlice slc,
const Vtx3Store vx1,
const Vtx3Store vx2 
)

Definition at line 2064 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().

2065  {
2066  // Calculates the position pull between two vertices
2067  double dx = vx1.X - vx2.X;
2068  double dy = vx1.Y - vx2.Y;
2069  double dz = vx1.Z - vx2.Z;
2070  double dxErr2 = (vx1.XErr * vx1.XErr + vx2.XErr * vx2.XErr) / 2;
2071  double dyErr2 = (vx1.YErr * vx1.YErr + vx2.YErr * vx2.YErr) / 2;
2072  double dzErr2 = (vx1.ZErr * vx1.ZErr + vx2.ZErr * vx2.ZErr) / 2;
2073  dx = dx * dx / dxErr2;
2074  dy = dy * dy / dyErr2;
2075  dz = dz * dz / dzErr2;
2076  return (float)(sqrt(dx + dy + dz)/3);
2077  }
float tca::VertexVertexPull ( TCSlice slc,
const VtxStore vx1,
const VtxStore vx2 
)

Definition at line 2080 of file TCVertex.cxx.

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

2081  {
2082  // Calculates the position pull between two vertices
2083  double dw = vx1.Pos[0] - vx2.Pos[0];
2084  double dt = vx1.Pos[1] - vx2.Pos[1];
2085  double dwErr2 = (vx1.PosErr[0] * vx1.PosErr[0] + vx2.PosErr[0] * vx2.PosErr[0]) / 2;
2086  double dtErr2 = (vx1.PosErr[1] * vx1.PosErr[1] + vx2.PosErr[1] * vx2.PosErr[1]) / 2;
2087  dw = dw * dw / dwErr2;
2088  dt = dt * dt / dtErr2;
2089  return (float)sqrt(dw + dt);
2090  }
void tca::VtxHitsSwap ( TCSlice slc,
const CTP_t  inCTP 
)

Definition at line 2962 of file TCVertex.cxx.

References tca::Trajectory::AlgMod, tca::VtxStore::CTP, tca::TCConfig::dbg2V, tca::TCConfig::dbgAlg, debug, DecodeCTP(), evd::details::end(), tca::Trajectory::EndPt, tca::TrajPoint::Hits, tca::VtxStore::ID, tca::Trajectory::ID, kHaloTj, kKilled, kVtxHitsSwap, tca::VtxStore::NTraj, tca::DebugStuff::Plane, geo::PlaneID::Plane, PointTrajDOCA(), tca::VtxStore::Pos, PrintPos(), tca::Trajectory::Pts, SetEndPoints(), tca::TCSlice::slHits, tcc, tca::TCSlice::tjs, TpSumHitChg(), tca::TCConfig::useAlg, tca::TrajPoint::UseHit, tca::Trajectory::VtxID, and tca::TCSlice::vtxs.

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

2962  {
2963 
2964  if(!tcc.useAlg[kVtxHitsSwap]) return;
2965 
2966  geo::PlaneID planeID = DecodeCTP(inCTP);
2967 
2968  bool prt = ((tcc.dbg2V && debug.Plane == (int)planeID.Plane) || tcc.dbgAlg[kVtxHitsSwap]);
2969  for (unsigned short iv = 0; iv < slc.vtxs.size(); ++iv){
2970  VtxStore& rvx = slc.vtxs[iv];
2971  if(rvx.CTP != inCTP) continue;
2972  // Only consider vertex with two trajectories
2973  if(rvx.NTraj != 2) continue;
2974  if (prt) mf::LogVerbatim("TC")<<"VtxHitsSwap: 2V"<<rvx.ID<<" Pos[0]: "<<rvx.Pos[0]<<" "<<rvx.Pos[1];
2975  std::array<unsigned short, 2> tjlist{{0,0}};
2976  for(unsigned short itj = 0; itj < slc.tjs.size(); ++itj) {
2977  if(slc.tjs[itj].AlgMod[kKilled] || slc.tjs[itj].AlgMod[kHaloTj]) continue;
2978  if(slc.tjs[itj].CTP != rvx.CTP) continue;
2979  Trajectory& tj = slc.tjs[itj];
2980  // ensure that the ID is OK so the code below doesn't choke
2981  for(unsigned short end = 0; end < 2; ++end) {
2982  if(tj.VtxID[end] == rvx.ID) {
2983  tjlist[end] = itj;
2984  }
2985  }
2986  }//all trajectories
2987 
2988  //Ignore short trajectories
2989  if (slc.tjs[tjlist[0]].EndPt[1]<5||
2990  slc.tjs[tjlist[1]].EndPt[1]<5) continue;
2991 
2992  for (unsigned short i = 0; i<2; ++i){
2993 
2994  //First check if first hit should be swapped
2995  Trajectory& tj0 = slc.tjs[tjlist[i]];
2996  Trajectory& tj1 = slc.tjs[tjlist[1-i]];
2997  unsigned short endPt0 = slc.tjs[tjlist[i]].EndPt[i];
2998  unsigned short endPt1 = slc.tjs[tjlist[1-i]].EndPt[1-i];
2999  //first TP on first trajectory
3000  float chg0 = TpSumHitChg(slc, tj0.Pts[endPt0]);
3001  float w0 = tj0.Pts[endPt0].Pos[0];
3002  //if (vtxPrt) mf::LogVerbatim("TC")<<PrintPos(slc, tj0.Pts[endPt0]);
3003  //second TP on first trajectory
3004  float chg1 = 0;
3005  float w1 = 0;
3006  unsigned short j = endPt0;
3007  while (j!=tj0.EndPt[1-i]){
3008  if (i==0) ++j;
3009  else --j;
3010  if (tj0.Pts[j].Chg){
3011  chg1 = TpSumHitChg(slc, tj0.Pts[j]);
3012  w1 = tj0.Pts[j].Pos[0];
3013  //if (vtxPrt) mf::LogVerbatim("TC")<<PrintPos(slc, tj0.Pts[j]);
3014  break;
3015  }
3016  }
3017  //first TP on second trajectory
3018  float chg2 = TpSumHitChg(slc,tj1.Pts[endPt1]);
3019  float w2 = tj1.Pts[endPt1].Pos[0];
3020  //DOCA between first TP on first TJ and first TP on second TJ
3021  float delta = 1000;
3022  for (size_t k = 0; k<tj0.Pts[endPt0].Hits.size(); ++k){
3023  if (!tj0.Pts[endPt0].UseHit[k]) continue;
3024  float this_delta = PointTrajDOCA(slc, tj0.Pts[endPt0].Hits[k], tj1.Pts[endPt1]);
3025  if (this_delta<delta) delta = this_delta;
3026  }
3027  // if (vtxPrt) mf::LogVerbatim("TC")<<PrintPos(slc, tj1.Pts[endPt1]);
3028  //if (vtxPrt) mf::LogVerbatim("TC")<<chg0<<" "<<chg1<<" "<<chg2<<" "<<delta;
3029  if (chg0>0&&std::abs((chg0-chg1)/chg0)-std::abs((chg0-chg2)/chg0)>0.2&&delta<1.5&&std::abs(w2-w1)<1.5){
3030  if (prt) {
3031  mf::LogVerbatim("TC")<<" chg0 = "<<chg0<<" chg1 = "<<chg1<<" chg2 = "<<chg2<<" delta = "<<delta<<" w0 = "<<w0<<" w1 = "<<w1<<" w2 = "<<w2;
3032  mf::LogVerbatim("TC")<<" Moving TP "<<PrintPos(slc, tj0.Pts[endPt0])<<" from TJ "<<tj0.ID<<" to TJ "<<tj1.ID;
3033  }
3034  //Add first TP of first trajectory to the second trajectory
3035  TrajPoint tp = tj0.Pts[endPt0];
3036  for (size_t j = 0; j<tp.Hits.size(); ++j){
3037  if (!tp.UseHit[j]) continue;
3038  slc.slHits[tp.Hits[j]].InTraj = tj1.ID;
3039  }
3040  if (i==0){
3041  //append to the end
3042  tj1.Pts.push_back(tp);
3043  }
3044  else{
3045  //insert at the beginning
3046  tj1.Pts.insert(tj1.Pts.begin(), tp);
3047  }
3048  SetEndPoints(tj1);
3049 
3050  //Remove first TP from first trajectory
3051  tj0.Pts[endPt0].Chg = 0;
3052  for (size_t j = 0; j<tj0.Pts[endPt0].Hits.size(); ++j){
3053  tj0.Pts[endPt0].UseHit[j] = false;
3054  }
3055  SetEndPoints(tj0);
3056  tj0.AlgMod[kVtxHitsSwap] = true;
3057  tj1.AlgMod[kVtxHitsSwap] = true;
3058  break;
3059  }
3060 
3061  //Now Check if the beginning of the first trajectory should be moved to the second trajectory.
3062  j = endPt0;
3063  std::vector<unsigned short> tplist;
3064  while (j!=tj0.EndPt[1-i]){
3065  if (tj0.Pts[j].Chg){
3066  float delta = 1000;
3067  for (size_t k = 0; k<tj0.Pts[j].Hits.size(); ++k){
3068  if (!tj0.Pts[j].UseHit[k]) continue;
3069  float this_delta = PointTrajDOCA(slc, tj0.Pts[j].Hits[k], tj1.Pts[endPt1]);
3070  if (this_delta<delta) delta = this_delta;
3071  //if (vtxPrt) mf::LogVerbatim("TC")<<j<<" "<<k<<" "<<PrintPos(slc, tj0.Pts[j])<<" "<<PointTrajDOCA(slc, tj0.Pts[j].Hits[k], tj1.Pts[endPt1]);
3072  }
3073  if (delta < 0.3 && tj0.Pts[j].Delta > 1.0 && (j==endPt0 || !tplist.empty())){
3074  tplist.push_back(j);
3075  }
3076  else break;
3077  }
3078  if (i==0) ++j;
3079  else --j;
3080  }
3081  //if (vtxPrt) mf::LogVerbatim("TC")<<tplist.size();
3082  //Need at least two TPs to make this change
3083  if (tplist.size()>1){
3084  if (prt) mf::LogVerbatim("TC")<<" Moving "<<tplist.size()<<" TPs from TJ "<<tj0.ID<<" to TJ "<<tj1.ID;
3085  //Append TPs to the second TJ
3086  for (unsigned short j = 0; j<tplist.size(); ++j){
3087  TrajPoint tp = tj0.Pts[tplist[j]];
3088  for (size_t k = 0; k<tp.Hits.size(); ++k){
3089  if (!tp.UseHit[k]) continue;
3090  slc.slHits[tp.Hits[k]].InTraj = tj1.ID;
3091  }
3092  if (i==0){
3093  //append to the end
3094  tj1.Pts.push_back(tp);
3095  }
3096  else{
3097  //insert at the beginning
3098  tj1.Pts.insert(tj1.Pts.begin(), tp);
3099  }
3100  }
3101  SetEndPoints(tj1);
3102 
3103  //Remove TPs from first trajectory
3104  for (unsigned short j = 0; j<tplist.size(); ++j){
3105  tj0.Pts[tplist[j]].Chg = 0;
3106  for (size_t k = 0; k<tj0.Pts[tplist[j]].Hits.size(); ++k){
3107  tj0.Pts[tplist[j]].UseHit[k] = false;
3108  }
3109  }
3110  SetEndPoints(tj0);
3111  tj0.AlgMod[kVtxHitsSwap] = true;
3112  tj1.AlgMod[kVtxHitsSwap] = true;
3113  break;
3114  }
3115  }//loop over two trajectories
3116  }//loop over vertices
3117  }
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:2864
TCConfig tcc
Definition: DataStructs.cxx:6
The data type to uniquely identify a Plane.
Definition: geo_types.h:250
DebugStuff debug
Definition: DebugStruct.cxx:4
bool dbg2V
debug 2D vertex finding
Definition: DataStructs.h:510
int Plane
Select plane.
Definition: DebugStruct.h:21
float TpSumHitChg(TCSlice &slc, TrajPoint const &tp)
Definition: Utils.cxx:1853
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:504
geo::PlaneID DecodeCTP(CTP_t CTP)
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:505
std::string PrintPos(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:5712
float PointTrajDOCA(TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2270
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
unsigned short tca::Vx3Topo ( TCSlice slc,
Vtx3Store vx3 
)

Definition at line 2641 of file TCVertex.cxx.

References tca::Vtx3Store::ID, tca::TCSlice::vtxs, and tca::Vtx3Store::Vx2ID.

2642  {
2643  // Returns the most common value of Topo for the 2D vertices that are matched
2644  // to this 3D vertex. This **might** be a useful measure to identify neutrino interaction
2645  // vertices
2646 
2647  if(vx3.ID == 0) return USHRT_MAX;
2648  // Consider Topo values between 0 and 9
2649  std::array<short, 10> cnts;
2650  cnts.fill(0);
2651  for(auto vx2id : vx3.Vx2ID) {
2652  if(vx2id == 0) continue;
2653  auto& vx2 = slc.vtxs[vx2id - 1];
2654  if(vx2.Topo < 0 || vx2.Topo > 9) continue;
2655  ++cnts[vx2.Topo];
2656  } // vx2id
2657  short most = 0;
2658  unsigned short theMost = USHRT_MAX;
2659  for(unsigned short itp = 0; itp < 10; ++itp) {
2660  if(cnts[itp] > most) {
2661  most = cnts[itp];
2662  theMost = itp;
2663  }
2664  } // itp
2665  return theMost;
2666  } // Vx3Topo
bool tca::WireHitRangeOK ( TCSlice slc,
const CTP_t inCTP 
)

Definition at line 4085 of file Utils.cxx.

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

Referenced by DotProd(), and FindCloseHits().

4086  {
4087  // returns true if the passed CTP code is consistent with the CT code of the WireHitRangeVector
4088  geo::PlaneID planeID = DecodeCTP(inCTP);
4089  if(planeID.Cryostat != slc.TPCID.Cryostat) return false;
4090  if(planeID.TPC != slc.TPCID.TPC) return false;
4091  return true;
4092  }
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)
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
unsigned short tca::WiresSkippedInCTP ( TCSlice slc,
std::vector< int > &  tjids,
CTP_t  inCTP 
)

Definition at line 1089 of file PFPUtils.cxx.

References evd::details::end(), and tca::TCSlice::tjs.

1090  {
1091  // counts the number of wires between the end points of all Tjs in the list of tjids
1092  // in inCTP where there is no TP with charge
1093  if(tjids.empty()) return 0;
1094 
1095  // find the min and max Pos[0] positions
1096  float fLoWire = 1E6;
1097  float fHiWire = -1E6;
1098  for(auto tjid : tjids) {
1099  auto& tj = slc.tjs[tjid - 1];
1100  if(tj.CTP != inCTP) continue;
1101  for(unsigned short end = 0; end < 2; ++end) {
1102  float endWire = tj.Pts[tj.EndPt[end]].Pos[0];
1103  if(endWire < -0.4) continue;
1104  if(endWire < fLoWire) fLoWire = endWire;
1105  if(endWire > fHiWire) fHiWire = endWire;
1106  } // end
1107  } // tjid
1108  if(fLoWire >= fHiWire) return 0;
1109  unsigned int loWire = std::nearbyint(fLoWire);
1110  unsigned short nWires = std::nearbyint(fHiWire) - loWire + 1;
1111  std::vector<bool> ptOnWire(nWires, false);
1112 
1113  // count the number of points with charge on all Tjs
1114  float npwc = 0;
1115  for(auto tjid : tjids) {
1116  auto& tj = slc.tjs[tjid - 1];
1117  if(tj.CTP != inCTP) continue;
1118  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1119  auto& tp = tj.Pts[ipt];
1120  if(tp.Chg <= 0) continue;
1121  if(tp.Pos[0] < -0.4) continue;
1122  ++npwc;
1123  unsigned short indx = std::nearbyint(tp.Pos[0]) - loWire;
1124  if(indx < nWires) ptOnWire[indx] = true;
1125  } // ipt
1126  } // tjid
1127  if(npwc == 0) return 0;
1128  float nskip = 0;
1129  for(unsigned short indx = 0; indx < nWires; ++indx) if(!ptOnWire[indx]) ++nskip;
1130  return (nskip / npwc);
1131 
1132  } // WiresSkippedInCTP
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
bool tca::WrongSplitTj ( std::string  inFcnLabel,
TCSlice slc,
Trajectory tj,
unsigned short  tjEnd,
ShowerStruct ss,
bool  prt 
)

Definition at line 2340 of file TCShower.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::ID, kComp3DVx, tca::Trajectory::VtxID, and tca::TCSlice::vtxs.

2341  {
2342  // Returns true if the trajectory was split by a 3D vertex match and the end of this trajectory is further
2343  // away from the shower than the partner trajectory
2344  // Here is a cartoon showing what we are trying to prevent. The shower is represented by a box. The trajectory
2345  // that is shown as (---*---) was originally reconstructed as a single trajectory. It was later split at the * position
2346  // 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
2347  // the shower. Tj is more likely to be the real parent
2348  //
2349  // 1111111111 2222222 TjID
2350  // 0 1 0 1 Tj end
2351  // --------------
2352  // | |
2353  // ----------*------- |
2354  // | |
2355  // --------------
2356  if(!tj.AlgMod[kComp3DVx]) return false;
2357  if(tjEnd > 1) return false;
2358 
2359  std::string fcnLabel = inFcnLabel + ".WSTj";
2360 
2361  // See if the other end is the end that was split. It should have a vertex with Topo = 8 or 11
2362  unsigned short otherEnd = 1 - tjEnd;
2363 // if(prt) mf::LogVerbatim("TC")<<"WSTj: otherEnd "<<otherEnd<<" vtxID "<<tj.VtxID[otherEnd];
2364  if(tj.VtxID[otherEnd] == 0) return false;
2365  unsigned short ivx = tj.VtxID[otherEnd] - 1;
2366  // A vertex exists but not a 3D split vertex
2367  if(slc.vtxs[ivx].Topo != 8 && slc.vtxs[ivx].Topo != 10) return false;
2368  if(prt) mf::LogVerbatim("TC")<<fcnLabel<<" Primary candidate "<<tj.ID<<" was split by a 3D vertex";
2369  return true;
2370 
2371  } // 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().

TCEvent tca::evt

Definition at line 5 of file DataStructs.cxx.

Referenced by AddHits(), AddLooseHits(), AddTj(), AnalyzeHits(), tca::TruthMatcher::CanReconstruct(), cluster::HoughBaseAlg::ChargeInfo_t::ChargeInfo_t(), ChgFracNearPos(), lar_pandora::LArPandoraHelper::CollectSeeds(), anab::FVectorReader< T, N >::create(), art::PtrMaker< T >::create(), util::CreateAssn(), tca::TrajClusterAlg::CreateSlice(), DefineHitPos(), tca::TrajClusterAlg::DefineShTree(), evd::MCBriefPad::Draw(), evd::TQPad::Draw(), evd::CalorPad::Draw(), evd::Display3DPad::Draw(), evd::TWireProjPad::Draw(), evd::Ortho3DPad::Draw(), evd::RecoBaseDrawer::DrawShower3D(), evd::RecoBaseDrawer::DrawShowerOrtho(), evd::RecoBaseDrawer::DrawTrack3D(), evd::RecoBaseDrawer::DrawTrackOrtho(), evd::RecoBaseDrawer::DrawTrackVertexAssns2D(), DumpTj(), evd::details::RawDigitCacheDataClass::empty(), ExpectedHitsRMS(), FilldEdx(), FillGaps(), FillWireHitRange(), Find3DVertices(), FindCloseHits(), FindCloseTjs(), FindUseHits(), FindVtxTjs(), Forecast(), GetHitMultiplet(), cluster::ClusterMergeHelper::GetManager(), GetOrigin(), evdb::ButtonBar::GoTo(), evd::HeaderDrawer::Header(), HitSep2(), HitsPosTick(), HitsRMSTick(), HitTimeErr(), trkf::PMAlgTrackMaker::init(), lar_pandora::LArPandoraEventDump::PandoraData::LoadAssociation(), main(), MakeBareTrajPoint(), MakeHaloTj(), MakeJunkTraj(), MaskedHitsOK(), tca::TruthMatcher::MatchAndSum(), tca::TruthMatcher::MatchTruth(), tca::TrajClusterAlg::MergeTPHits(), tca::TrajClusterAlg::MergeTPHitsOnWire(), evdb::DisplayWindow::OpenWindow(), mvapid::MVAAlg::SumDistance2::operator()(), PFPVertexCheck(), PointTrajDOCA(), PrintHit(), PrintHitShort(), PrintTrajPoint(), cheat::BackTrackerService::priv_PrepEvent(), event::EventMaker::produce(), trkf::TrackStitcher::produce(), trkf::PMAlgTrackMaker::produce(), evd::RecoBaseDrawer::Prong2D(), cheat::BackTrackerService::provider(), cheat::ParticleInventoryService::provider(), cheat::PhotonBackTrackerService::provider(), art::PtrMaker< T >::PtrMaker(), tca::TrajClusterAlg::reconfigure(), tca::TrajClusterAlg::ReconstructAllTraj(), evdb::ScanFrame::Record(), tca::TrajClusterAlg::RunTrajClusterAlg(), evd::TWireProjPad::SaveHitList(), evd::TWireProjPad::SaveSeedList(), rndm::NuRandomService::seedEngine(), evd::TWireProjPad::SelectOneHit(), util::EventChangeTracker_t::set(), anab::FVectorWriter< 4 >::setDataTag(), evdb::EventHolder::SetEvent(), tca::TrajClusterAlg::SetInputHits(), cluster::ClusterMatchAlg::SetMCTruthModName(), SignalAtTp(), util::DetectorPropertiesServiceArgoNeuT::SimpleBoundary(), Split3DKink(), SplitTraj(), StartChgVec(), StartTraj(), StorePFP(), StoreShower(), StoreTraj(), StoreVertex(), TPHitsRMSTick(), TpSumHitChg(), TrajHitsOK(), UpdateShower(), UpdateTjChgProperties(), and detsim::SimDriftElectrons::~SimDriftElectrons().

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

Definition at line 82 of file DataStructs.cxx.

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

const std::vector< std::string > tca::StrategyBitNames
Initial value:
{
"Normal",
"StiffEl",
"StiffMu",
"Slowing"
}

Definition at line 101 of file DataStructs.cxx.

Referenced by StepAway().

TCConfig tca::tcc

Definition at line 6 of file DataStructs.cxx.

Referenced by AddCloseTjsToList(), AddHits(), AddLAHits(), AddLooseHits(), AddTj(), AnalyzeHits(), AngleRange(), AttachAnyTrajToVertex(), AttachTrajToVertex(), tca::TruthMatcher::CanReconstruct(), CheckHiMultEndHits(), CheckHiMultUnusedHits(), CheckStiffEl(), CheckTraj(), CheckTrajBeginChg(), ChgFracBetween(), ChgFracNearEnd(), ChkChgAsymmetry(), ChkHiChgHits(), tca::TrajClusterAlg::ChkInTraj(), ChkMichel(), ChkStop(), ChkStopEndPts(), ChkVxTjs(), CompatibleMerge(), CompleteIncomplete3DVertices(), CompleteIncomplete3DVerticesInGaps(), CompleteIncompleteShower(), tca::TrajClusterAlg::CreateSlice(), DecodeDebugString(), DefineDontCluster(), DefineEnvelope(), DefineHitPos(), DefinePFP(), DefinePFPParents(), DefineTjParents(), DumpTj(), EndMerge(), ExpectedHitsRMS(), FilldEdx(), FillGaps(), FillmAllTraj(), FillWireHitRange(), Find2DVertices(), Find3DVertices(), FindCloseHits(), FindCloseTjs(), FindCompleteness(), FindCots(), FindHammerVertices(), FindHammerVertices2(), tca::TrajClusterAlg::FindJunkTraj(), tca::TrajClusterAlg::FindMissedVxTjs(), FindNeutralVertices(), FindParent(), FindPFParticles(), FindShowers3D(), FindShowerStart(), FindSoftKink(), FindStartChg(), FindUseHits(), FindVtxTjs(), FindXMatches(), FitTp3(), FitTp3s(), FitVertex(), FixTrajBegin(), FixTrajEnd(), FollowTp3s(), Forecast(), GetHitMultiplet(), GetOrigin(), GottaKink(), HiEndDelta(), HitSep2(), HitsPosTime(), HitsRMSTime(), HitsTimeErr2(), HitTimeErr(), InsideTPC(), IsCloseToVertex(), IsGhost(), KillPoorVertices(), KillVerticesInShower(), MakeBareTP(), MakeBareTrajPoint(), MakeHaloTj(), MakeJunkTraj(), MakeJunkVertices(), MakeTp3(), MakeVertexObsolete(), MaskBadTPs(), MaskedHitsOK(), MaskTrajEndPoints(), Match3DFOM(), Match3DVtxTjs(), tca::TruthMatcher::MatchAndSum(), tca::TruthMatcher::MatchTruth(), MergeGhostTjs(), MergeNearby2DShowers(), MergeOverlap(), MergePFPTjs(), MergeShowerChain(), MergeSubShowers(), MergeSubShowersTj(), MergeWithVertex(), ParentFOM(), PointTrajDOCA(), PosInPlane(), Print2DShowers(), Print2V(), PrintAllTraj(), PrintPos(), PrintShower(), PrintT(), PrintTrajectory(), PrintTrajPoint(), cluster::TrajCluster::produce(), tca::TrajClusterAlg::reconfigure(), tca::TrajClusterAlg::ReconstructAllTraj(), ReversePropagate(), tca::TrajClusterAlg::RunTrajClusterAlg(), SaveAllCots(), SaveCRInfo(), SaveTjInfo(), SaveTjInfoStuff(), SetAngleCode(), tca::TrajClusterAlg::SetInputHits(), SetPDGCode(), SetStrategy(), SetVx2Score(), SetVx3Score(), SignalAtTp(), Split3DKink(), SplitHiChgHits(), SplitTraj(), SplitTrajCrossingVertices(), StartChgVec(), StartTraj(), StepAway(), StitchPFPs(), StopIfBadFits(), StoreTraj(), TagDeltaRays(), TagJunkTj(), TagShowerLike(), TjDeltaRMS(), TPHitsRMSTime(), tca::TrajClusterAlg::TrajClusterAlg(), TrimEndPts(), UpdateMatchStructs(), UpdateShower(), UpdateStiffEl(), UpdateTjChgProperties(), UpdateTp3s(), UpdateTraj(), and VtxHitsSwap().

std::vector< TjForecast > tca::tjfs

Definition at line 7 of file DataStructs.cxx.

Referenced by Forecast(), SetStrategy(), and StepAway().

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",
"VtxIndPlnNoChg"
}

Definition at line 91 of file DataStructs.cxx.

Referenced by Print2V(), and PrintAllTraj().