LArSoft  v10_04_05
Liquid Argon Software toolkit - https://larsoft.org/
tca Namespace Reference

Namespaces

 detail
 

Classes

struct  CRTreeVars
 
struct  DebugStuff
 
struct  DontClusterStruct
 
struct  HistStuff
 
struct  MatchStruct
 
struct  ParFit
 
struct  PFPStruct
 
struct  SectionFit
 
struct  ShowerPoint
 
struct  ShowerStruct
 
struct  ShowerStruct3D
 
struct  ShowerTreeVars
 
struct  TCConfig
 
struct  TCEvent
 
struct  TCHit
 
struct  TCSlice
 
struct  TCWireIntersection
 
struct  Tj2Pt
 
struct  TjForecast
 
struct  TP3D
 
class  TrajClusterAlg
 
struct  Trajectory
 
struct  TrajPoint
 
struct  TrajPoint3
 
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)
 
void StitchPFPs ()
 
void FindPFParticles (detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, TCSlice &slc)
 
void MakePFParticles (detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, std::vector< MatchStruct > matVec, unsigned short matVec_Iter)
 
bool ReconcileTPs (TCSlice &slc, PFPStruct &pfp, bool prt)
 
void ReconcileTPs (TCSlice &slc)
 
void MakePFPTjs (TCSlice &slc)
 
void FillWireIntersections (TCSlice &slc)
 
bool TCIntersectionPoint (unsigned int wir1, unsigned int wir2, unsigned int pln1, unsigned int pln2, float &y, float &z)
 
void Match3PlanesSpt (TCSlice &slc, std::vector< MatchStruct > &matVec)
 
bool SptInTPC (const std::array< unsigned int, 3 > &sptHits, unsigned int tpc)
 
void Match3Planes (TCSlice &slc, std::vector< MatchStruct > &matVec)
 
void Match2Planes (TCSlice &slc, std::vector< MatchStruct > &matVec)
 
bool Update (detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp)
 
bool ReSection (detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, bool prt)
 
void CountBadPoints (const TCSlice &slc, const PFPStruct &pfp, unsigned short fromPt, unsigned short toPt, unsigned short &nBadPts, unsigned short &firstBadPt)
 
bool CanSection (const TCSlice &slc, const PFPStruct &pfp)
 
unsigned short Find3DRecoRange (const TCSlice &slc, const PFPStruct &pfp, unsigned short fromPt, unsigned short min2DPts, short dir)
 
void GetRange (const PFPStruct &pfp, unsigned short sfIndex, unsigned short &fromPt, unsigned short &npts)
 
bool FitSection (detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, unsigned short sfIndex)
 
SectionFit FitTP3Ds (detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const std::vector< TP3D > &tp3ds, unsigned short fromPt, short fitDir, unsigned short nPtsFit)
 
bool FitTP3Ds (detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, unsigned short fromPt, unsigned short nPtsFit, unsigned short sfIndex)
 
void ReconcileVertices (TCSlice &slc, PFPStruct &pfp, bool prt)
 
void FillGaps3D (detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, PFPStruct &pfp, bool prt)
 
bool ValidTwoPlaneMatch (detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const PFPStruct &pfp)
 
void AddPointsInRange (detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, PFPStruct &pfp, unsigned short fromPt, unsigned short toPt, CTP_t inCTP, float maxPull, unsigned short &nWires, unsigned short &nAdd, bool prt)
 
unsigned short InsertTP3D (PFPStruct &pfp, TP3D &tp3d)
 
bool SortSection (PFPStruct &pfp, unsigned short sfIndex)
 
void Recover (detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, PFPStruct &pfp, bool prt)
 
bool MakeTP3Ds (detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, PFPStruct &pfp, bool prt)
 
bool MakeSmallAnglePFP (detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, PFPStruct &pfp, bool prt)
 
void Reverse (PFPStruct &pfp)
 
void FillmAllTraj (detinfo::DetectorPropertiesData const &detProp, TCSlice &slc)
 
TP3D MakeTP3D (detinfo::DetectorPropertiesData const &detProp, const TrajPoint &itp, const TrajPoint &jtp)
 
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 (detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp)
 
void Average_dEdX (detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, float &dEdXAve, float &dEdXRms)
 
float dEdx (detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, TP3D &tp3d)
 
TP3D CreateTP3D (detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, int tjID, unsigned short tpIndex)
 
bool SetSection (detinfo::DetectorPropertiesData const &detProp, PFPStruct &pfp, TP3D &tp3d)
 
float PointPull (const TP3D &tp3d)
 
PFPStruct CreatePFP (const TCSlice &slc)
 
void PFPVertexCheck (TCSlice &slc)
 
void DefinePFPParents (TCSlice &slc)
 
bool StorePFP (TCSlice &slc, PFPStruct &pfp)
 
bool InsideFV (const TCSlice &slc, const 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)
 
float ChgFracBetween (detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, Point3_t pos1, Point3_t pos2)
 
float ChgFracNearEnd (detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const PFPStruct &pfp, unsigned short end)
 
Vector3_t DirAtEnd (const PFPStruct &pfp, unsigned short end)
 
Point3_t PosAtEnd (const PFPStruct &pfp, unsigned short end)
 
float Length (const PFPStruct &pfp)
 
bool SectionStartEnd (const PFPStruct &pfp, unsigned short sfIndex, unsigned short &startPt, unsigned short &endPt)
 
unsigned short FarEnd (const PFPStruct &pfp, const Point3_t &pos)
 
int PDGCodeVote (detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp)
 
void PrintTP3Ds (detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, std::string someText, const TCSlice &slc, const PFPStruct &pfp, short printPts)
 
double DotProd (const Vector3_t &v1, const Vector3_t &v2)
 
void StepAway (TCSlice &slc, Trajectory &tj)
 
bool StopShort (TCSlice &slc, Trajectory &tj, bool prt)
 
void SetStrategy (TCSlice &slc, Trajectory &tj)
 
void Forecast (TCSlice &slc, const Trajectory &tj)
 
void UpdateStiffEl (TCSlice const &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 (const TCSlice &slc, unsigned int theHit, std::vector< unsigned int > &hitsInMultiplet, bool useLongPulseHits)
 
float HitTimeErr (const TCSlice &slc, unsigned int iht)
 
float HitsTimeErr2 (const 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 FillGaps (TCSlice &slc, Trajectory &tj)
 
void CheckHiMultUnusedHits (TCSlice &slc, Trajectory &tj)
 
void CheckHiMultEndHits (TCSlice &slc, Trajectory &tj)
 
void UpdateDeltaRMS (Trajectory &tj)
 
void MaskBadTPs (TCSlice &slc, Trajectory &tj, float const &maxChi)
 
bool MaskedHitsOK (TCSlice &slc, Trajectory &tj)
 
bool StopIfBadFits (Trajectory &tj)
 
bool GottaKink (TCSlice &slc, Trajectory &tj, bool doTrim)
 
void ChkBegin (TCSlice &slc, Trajectory &tj)
 
void FixBegin (TCSlice &slc, Trajectory &tj, unsigned short atPt)
 
bool IsGhost (TCSlice &slc, Trajectory &tj)
 
bool IsGhost (TCSlice &slc, std::vector< unsigned int > &tHits)
 
void LastEndMerge (TCSlice &slc, CTP_t inCTP)
 
TrajPoint CreateTPFromTj (const Trajectory &tj)
 
void EndMerge (TCSlice &slc, CTP_t inCTP, bool lastPass)
 
void MaskTrajEndPoints (TCSlice &slc, Trajectory &tj, unsigned short nPts)
 
void ChkStop (Trajectory &tj)
 
bool ChkMichel (Trajectory &tj, unsigned short &lastGoodPt)
 
bool MakeJunkTraj (TCSlice &slc, std::vector< unsigned int > tHits)
 
void SaveCRInfo (detinfo::DetectorClocksData const &clockData, TCSlice &slc, PFPStruct &pfp, bool fIsRealData)
 
int GetOrigin (detinfo::DetectorClocksData const &clockData, TCSlice &slc, PFPStruct &pfp)
 
void ClearCRInfo (TCSlice &slc)
 
void ConfigureMVA (TCConfig &tcc, std::string fMVAShowerParentWeights)
 
bool FindShowerStart (detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
 
void Finish3DShowers (TCSlice &slc)
 
bool FindShowers3D (detinfo::DetectorPropertiesData const &detProp, 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)
 
bool UpdateShower (std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
 
bool UpdateShower (std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
 
float Match3DFOM (detinfo::DetectorPropertiesData const &detProp, std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
 
float Match3DFOM (detinfo::DetectorPropertiesData const &detProp, std::string inFcnLabel, TCSlice &slc, int icid, int jcid, int kcid, bool prt)
 
float Match3DFOM (detinfo::DetectorPropertiesData const &detProp, 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 (detinfo::DetectorPropertiesData const &detProp, std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
 
bool SetParent (detinfo::DetectorPropertiesData const &detProp, std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, ShowerStruct3D &ss3, bool prt)
 
bool IsShowerLike (TCSlice const &slc, std::vector< int > const &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, 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, 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 const &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
 
void TagShowerLike (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)
 
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 (detinfo::DetectorPropertiesData const &detProp, std::string fcnLabel, TCSlice const &slc)
 
void Print2DShowers (std::string someText, TCSlice const &slc, CTP_t inCTP, bool printKilledShowers)
 
void PrintShower (std::string someText, TCSlice const &slc, const ShowerStruct &ss, bool printHeader, bool printExtras)
 
void Match2DShowers (std::string inFcnLabel, TCSlice &slc, bool prt)
 
void DefineDontCluster (TCSlice &slc, bool prt)
 
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 FindCots (std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, std::vector< std::vector< int >> &tjLists, bool prt)
 
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)
 
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)
 
void MakeJunkVertices (TCSlice &slc, const CTP_t &inCTP)
 
void Find2DVertices (detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, const CTP_t &inCTP, unsigned short pass)
 
bool MergeWithVertex (TCSlice &slc, VtxStore &vx, unsigned short oVxID)
 
void FindHammerVertices2 (TCSlice &slc, const CTP_t &inCTP)
 
void FindHammerVertices (TCSlice &slc, const CTP_t &inCTP)
 
void SplitTrajCrossingVertices (TCSlice &slc, CTP_t inCTP)
 
void Reconcile2Vs (TCSlice &slc)
 
bool Reconcile2VTs (TCSlice &slc, std::vector< int > &vx2cls, bool prt)
 
void Find3DVertices (detinfo::DetectorPropertiesData const &detProp, TCSlice &slc)
 
unsigned short TPNearVertex (const TCSlice &slc, const TrajPoint &tp)
 
bool AttachToAnyVertex (TCSlice &slc, PFPStruct &pfp, float maxSep, bool prt)
 
bool AttachAnyVertexToTraj (TCSlice &slc, int tjID, bool prt)
 
bool AttachAnyTrajToVertex (TCSlice &slc, unsigned short ivx, bool prt)
 
bool AttachTrajToVertex (TCSlice &slc, Trajectory &tj, VtxStore &vx, bool prt)
 
float TrajPointVertexPull (const TrajPoint &tp, const VtxStore &vx)
 
float VertexVertexPull (const Vtx3Store &vx1, const Vtx3Store &vx2)
 
float VertexVertexPull (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 > &vxTPs, 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)
 
void CompleteIncomplete3DVerticesInGaps (detinfo::DetectorPropertiesData const &detProp, TCSlice &slc)
 
void CompleteIncomplete3DVertices (detinfo::DetectorPropertiesData const &detProp, TCSlice &slc)
 
bool RefineVtxPosition (const Trajectory &tj, unsigned short &nearPt, short nPtsToChk, bool prt)
 
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)
 
void PosInPlane (detinfo::DetectorPropertiesData const &detProp, const Vtx3Store &vx3, unsigned short plane, Point2_t &pos)
 
unsigned short IsCloseToVertex (const TCSlice &slc, const VtxStore &inVx2)
 
unsigned short IsCloseToVertex (const TCSlice &slc, const 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 > const &tjIDs)
 
int PDGCodeVote (const TCSlice &slc, const std::vector< int > &tjIDs)
 
int NeutrinoPrimaryTjID (const TCSlice &slc, const Trajectory &tj)
 
int PrimaryID (const TCSlice &slc, const Trajectory &tj)
 
int PrimaryUID (const PFPStruct &pfp)
 
bool MergeTjIntoPFP (TCSlice &slc, int mtjid, PFPStruct &pfp, bool prt)
 
float PointPull (Point2_t pos, float chg, const Trajectory &tj)
 
bool CompatibleMerge (const TCSlice &slc, std::vector< int > const &tjIDs, bool prt)
 
bool CompatibleMerge (const Trajectory &tj1, const Trajectory &tj2, bool prt)
 
float OverlapFraction (const Trajectory &tj1, const Trajectory &tj2)
 
unsigned short AngleRange (TrajPoint const &tp)
 
void SetAngleCode (TrajPoint &tp)
 
unsigned short AngleRange (float angle)
 
void FitTraj (TCSlice const &slc, Trajectory &tj)
 
void FitTraj (TCSlice const &slc, Trajectory &tj, unsigned short originPt, unsigned short npts, short fitDir, TrajPoint &tpFit)
 
unsigned short GetPFPIndex (const TCSlice &slc, int tjID)
 
void ReleaseHits (TCSlice &slc, Trajectory const &tj)
 
void UnsetUsedHits (TCSlice &slc, TrajPoint &tp)
 
bool StoreTraj (TCSlice &slc, Trajectory &tj)
 
void FitPar (const Trajectory &tj, unsigned short originPt, unsigned short npts, short fitDir, ParFit &pFit, unsigned short usePar)
 
bool InTrajOK (TCSlice &slc, std::string someText)
 
void CheckTrajBeginChg (TCSlice &slc, unsigned short itj)
 
bool BraggSplit (TCSlice &slc, unsigned short itj)
 
void TrimHiChgEndPts (TCSlice &slc, Trajectory &tj, bool prt)
 
void TrimEndPts (std::string fcnLabel, TCSlice &slc, Trajectory &tj, const std::vector< float > &fQualityCuts, bool prt)
 
void ChkEndKink (TCSlice const &slc, Trajectory &tj, bool prt)
 
void ChkChgAsymmetry (TCSlice &slc, Trajectory &tj, bool prt)
 
bool SignalBetween (const TrajPoint &tp1, const TrajPoint &tp2, const float MinWireSignalFraction)
 
bool SignalBetween (TrajPoint tp, float toPos0, const float MinWireSignalFraction)
 
float ChgFracBetween (TrajPoint tp, float toPos0)
 
bool TrajHitsOK (TCSlice const &slc, const std::vector< unsigned int > &iHitsInMultiplet, const std::vector< unsigned int > &jHitsInMultiplet)
 
bool TrajHitsOK (TCSlice const &slc, const unsigned int iht, const unsigned int jht)
 
float ExpectedHitsRMS (const TrajPoint &tp)
 
bool SignalAtTpInSlc (const TCSlice &slc, const TrajPoint &tp)
 
bool SignalAtTp (TrajPoint &tp)
 
bool NearbySrcHit (geo::PlaneID plnID, unsigned int wire, float loTick, float hiTick)
 
float TpSumHitChg (const TCSlice &slc, TrajPoint const &tp)
 
unsigned short NumPtsWithCharge (const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
 
unsigned short NumPtsWithCharge (const TCSlice &slc, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
 
float DeadWireCount (const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
 
float DeadWireCount (const 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 (detinfo::DetectorPropertiesData const &detProp, 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 (TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
 
bool TrajTrajDOCA (const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
 
bool TrajTrajDOCA (const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep, bool considerDeadWires)
 
float HitSep2 (const TCSlice &slc, unsigned int iht, unsigned int jht)
 
unsigned short CloseEnd (const Trajectory &tj, const Point2_t &pos)
 
float PointTrajSep2 (float wire, float time, TrajPoint const &tp)
 
float PointTrajDOCA (const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
 
float PointTrajDOCA (float wire, float time, TrajPoint const &tp)
 
float PointTrajDOCA2 (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 (const TCSlice &slc, std::vector< int > &tjIDs)
 
float TrajLength (const Trajectory &tj)
 
float PosSep (const Point2_t &pos1, const Point2_t &pos2)
 
float PosSep2 (const Point2_t &pos1, const Point2_t &pos2)
 
float TrajPointSeparation (const TrajPoint &tp1, const TrajPoint &tp2)
 
bool TrajClosestApproach (Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
 
float TwoTPAngle (const TrajPoint &tp1, const TrajPoint &tp2)
 
std::vector< unsigned int > PutHitsInVector (const TCSlice &slc, PFPStruct const &pfp, HitStatus_t hitRequest)
 
std::vector< unsigned int > PutTrajHitsInVector (const Trajectory &tj, HitStatus_t hitRequest)
 
void TagJunkTj (Trajectory &tj, bool prt)
 
bool HasDuplicateHits (const TCSlice &slc, Trajectory const &tj, bool prt)
 
void MoveTPToWire (TrajPoint &tp, float wire)
 
std::vector< unsigned int > FindCloseHits (const 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 const &slc, TrajPoint &tp, float const maxDelta, HitStatus_t hitRequest)
 
unsigned short NearbyCleanPt (const Trajectory &tj, unsigned short end)
 
std::vector< int > FindCloseTjs (const TCSlice &slc, const TrajPoint &fromTp, const TrajPoint &toTp, const float &maxDelta)
 
float KinkSignificance (TCSlice const &slc, Trajectory const &tj1, unsigned short end1, Trajectory const &tj2, unsigned short end2, unsigned short nPtsFit, bool useChg, bool prt)
 
float KinkSignificance (TCSlice const &slc, Trajectory &tj, unsigned short kinkPt, unsigned short nPtsFit, bool useChg, bool prt)
 
float ElectronLikelihood (const TCSlice &slc, const Trajectory &tj)
 
float ChgFracNearPos (const TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
 
float MaxHitDelta (TCSlice &slc, Trajectory &tj)
 
void ReverseTraj (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 (Trajectory const &tj, bool prt)
 
short MCSMom (const TCSlice &slc, const std::vector< int > &tjIDs)
 
short MCSMom (const TCSlice &slc, const Trajectory &tj)
 
short MCSMom (const TCSlice &slc, const Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
 
unsigned short NearestPtWithChg (const Trajectory &tj, unsigned short thePt)
 
float MCSThetaRMS (const Trajectory &tj)
 
double MCSThetaRMS (const Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
 
void TjDeltaRMS (const Trajectory &tj, unsigned short firstPt, unsigned short lastPt, double &rms, unsigned short &cnt)
 
void SetTPEnvironment (TCSlice &slc, CTP_t inCTP)
 
void UpdateTjChgProperties (std::string inFcnLabel, TCSlice const &slc, Trajectory &tj, bool prt)
 
void UpdateVxEnvironment (TCSlice &slc)
 
void UpdateVxEnvironment (TCSlice &slc, VtxStore &vx2, bool prt)
 
TrajPoint MakeBareTP (detinfo::DetectorPropertiesData const &detProp, const Point3_t &pos, CTP_t inCTP)
 
TrajPoint MakeBareTP (detinfo::DetectorPropertiesData const &detProp, const Point3_t &pos, const Vector3_t &dir, CTP_t inCTP)
 
bool MakeBareTrajPoint (const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
 
bool MakeBareTrajPoint (float fromWire, float fromTick, float toWire, float toTick, CTP_t tCTP, TrajPoint &tp)
 
bool MakeBareTrajPoint (const Point2_t &fromPos, const Point2_t &toPos, TrajPoint &tpOut)
 
bool MakeBareTrajPoint (const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
 
unsigned short FarEnd (const Trajectory &tj, const Point2_t &pos)
 
Vector2_t PointDirection (const Point2_t p1, const Point2_t p2)
 
float TPHitsRMSTime (const TCSlice &slc, const TrajPoint &tp, HitStatus_t hitRequest)
 
float TPHitsRMSTick (const TCSlice &slc, const TrajPoint &tp, HitStatus_t hitRequest)
 
float HitsRMSTime (const TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
 
float HitsRMSTick (const TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
 
float HitsPosTime (const TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, float &sum, HitStatus_t hitRequest)
 
float HitsPosTick (const TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, float &sum, HitStatus_t hitRequest)
 
unsigned short NumHitsInTP (const TrajPoint &tp, HitStatus_t hitRequest)
 
void SetPDGCode (TCSlice &slc, unsigned short itj)
 
void SetPDGCode (TCSlice const &slc, Trajectory &tj)
 
bool AnalyzeHits ()
 
bool LongPulseHit (const recob::Hit &hit)
 
void FillWireHitRange (geo::TPCID inTPCID)
 
bool FillWireHitRange (detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, TCSlice &slc)
 
bool WireHitRangeOK (TCSlice const &slc, const CTP_t &inCTP)
 
bool MergeAndStore (TCSlice &slc, unsigned int itj1, unsigned int itj2, bool doPrt)
 
std::vector< int > GetAssns (TCSlice const &slc, std::string type1Name, int id, std::string type2Name)
 
bool StartTraj (TCSlice const &slc, Trajectory &tj, unsigned int fromhit, unsigned int tohit, unsigned short pass)
 
bool StartTraj (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 PrintDebugMode ()
 
void PrintAll (detinfo::DetectorPropertiesData const &detProp, std::string someText)
 
void PrintP (mf::LogVerbatim &myprt, PFPStruct const &pfp, bool &printHeader)
 
void Print3V (detinfo::DetectorPropertiesData const &detProp, mf::LogVerbatim &myprt, Vtx3Store const &vx3, bool &printHeader)
 
void Print2V (mf::LogVerbatim &myprt, VtxStore const &vx2, bool &printHeader)
 
void Print3S (detinfo::DetectorPropertiesData const &detProp, mf::LogVerbatim &myprt, ShowerStruct3D const &ss3)
 
void PrintT (mf::LogVerbatim &myprt, Trajectory const &tj, bool &printHeader)
 
void PrintAllTraj (detinfo::DetectorPropertiesData const &detProp, std::string someText, TCSlice const &slc, unsigned short itj, unsigned short ipt, bool prtVtx)
 
void PrintTrajectory (std::string someText, const TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
 
void PrintTPHeader (std::string someText)
 
void PrintTP (std::string someText, const TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, const TrajPoint &tp)
 
std::string TPEnvString (const TrajPoint &tp)
 
void PrintPFP (std::string someText, TCSlice const &slc, const PFPStruct &pfp, bool printHeader)
 
void PrintPFPs (std::string someText, TCSlice const &slc)
 
std::string PrintEndFlag (const PFPStruct &pfp, unsigned short end)
 
std::string PrintEndFlag (const Trajectory &tj, unsigned short end)
 
std::string PrintHitShort (const TCHit &tch)
 
std::string PrintHit (const TCHit &tch)
 
std::string PrintPos (const TrajPoint &tp)
 
std::string PrintPos (const Point2_t &pos)
 
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,
  kVxTruMatch, kVxMerged, kVxIndPlnNoChg, kVxEnvOK,
  kVxBitSize
}
 
enum  TP3DFlags_t { kTP3DGood, kTP3DBad, kTP3DHiDEdx }
 
enum  PFPFlags_t { kCanSection, kNeedsUpdate, kSmallAngle }
 
enum  AlgBit_t {
  kFillGaps3D, kKink3D, kTEP3D, kJunk3D,
  kRTPs3D, kMat3D, kMaskHits, kMaskBadTPs,
  kMichel, kDeltaRay, kCTStepChk, kRvPrp,
  kCHMUH, kSplit, kComp3DVx, kComp3DVxIG,
  kHamBragg, kHamVx, kHamVx2, kJunkVx,
  kJunkTj, kKilled, kMerge, kLastEndMerge,
  kTEP, kTHCEP, kEndKink, kCHMEH,
  kFillGaps, kUseGhostHits, kMrgGhost, kChkInTraj,
  kStopBadFits, kFixBegin, kFTBChg, kBeginChg,
  kFixEnd, kBraggSplit, kUUH, kVtxTj,
  kChkVxTj, kPhoton, kHaloTj, kNoFitToVx,
  kVxMerge, kVxNeutral, kNoKinkChk, kChkStop,
  kChkStopEP, kChkChgAsym, kFTBRvProp, kTjHiVx3Score,
  kVtxHitsSwap, kSplitHiChgHits, kShowerLike, kKillInShowerVx,
  kShowerTj, kShwrParent, kMergeOverlap, kMergeSubShowers,
  kMergeSubShowersTj, kMergeNrShowers, kMergeShChain, kCompleteShower,
  kSplitTjCVx, kMakePFPTjs, kStopShort, kReconcile2Vs,
  kFTBMod, kAlgBitSize
}
 
enum  Strategy_t { kNormal, kStiffEl, kStiffMu, kSlowing }
 
enum  EndFlag_t {
  kSignal, kAtKink, kAtVtx, kBragg,
  kAtTj, kOutFV, kNoFitVx, kFlagBitSize
}
 
enum  TPEnvironment_t {
  kEnvNotGoodWire, kEnvNearMuon, kEnvNearShower, kEnvOverlap,
  kEnvUnusedHits, kEnvNearSrcHit, 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 > EndFlagNames {"Signal", "AtKink", "AtVtx", "Bragg", "AtTj", "OutFV", "NoFitVx"}
 
const std::vector< std::string > VtxBitNames
 
const std::vector< std::string > StrategyBitNames {"Normal", "StiffEl", "StiffMu", "Slowing"}
 
constexpr unsigned int pAlgModSize = 6
 

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 45 of file DataStructs.h.

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

Definition at line 41 of file DataStructs.h.

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

Definition at line 39 of file DataStructs.h.

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

Definition at line 42 of file DataStructs.h.

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

Definition at line 40 of file DataStructs.h.

Enumeration Type Documentation

Enumerator
kFillGaps3D 
kKink3D 
kTEP3D 
kJunk3D 
kRTPs3D 
kMat3D 
kMaskHits 
kMaskBadTPs 
kMichel 
kDeltaRay 
kCTStepChk 
kRvPrp 
kCHMUH 
kSplit 
kComp3DVx 
kComp3DVxIG 
kHamBragg 
kHamVx 
kHamVx2 
kJunkVx 
kJunkTj 
kKilled 
kMerge 
kLastEndMerge 
kTEP 
kTHCEP 
kEndKink 
kCHMEH 
kFillGaps 
kUseGhostHits 
kMrgGhost 
kChkInTraj 
kStopBadFits 
kFixBegin 
kFTBChg 
kBeginChg 
kFixEnd 
kBraggSplit 
kUUH 
kVtxTj 
kChkVxTj 
kPhoton 
kHaloTj 
kNoFitToVx 
kVxMerge 
kVxNeutral 
kNoKinkChk 
kChkStop 
kChkStopEP 
kChkChgAsym 
kFTBRvProp 
kTjHiVx3Score 
kVtxHitsSwap 
kSplitHiChgHits 
kShowerLike 
kKillInShowerVx 
kShowerTj 
kShwrParent 
kMergeOverlap 
kMergeSubShowers 
kMergeSubShowersTj 
kMergeNrShowers 
kMergeShChain 
kCompleteShower 
kSplitTjCVx 
kMakePFPTjs 
kStopShort 
kReconcile2Vs 
kFTBMod 
kAlgBitSize 

don't mess with this line

Definition at line 417 of file DataStructs.h.

417  {
418  kFillGaps3D, // 3D algorithms for PFPs (bitset size limited to 8 bits)
419  kKink3D,
420  kTEP3D,
421  kJunk3D,
422  kRTPs3D,
423  kMat3D, // 2D algorithms for Tjs here and below
424  kMaskHits,
425  kMaskBadTPs,
426  kMichel,
427  kDeltaRay,
428  kCTStepChk,
429  kRvPrp,
430  kCHMUH,
431  kSplit,
432  kComp3DVx,
433  kComp3DVxIG,
434  kHamBragg,
435  kHamVx,
436  kHamVx2,
437  kJunkVx,
438  kJunkTj,
439  kKilled,
440  kMerge,
442  kTEP,
443  kTHCEP,
444  kEndKink,
445  kCHMEH,
446  kFillGaps,
448  kMrgGhost,
449  kChkInTraj,
450  kStopBadFits,
451  kFixBegin,
452  kFTBChg,
453  kBeginChg,
454  kFixEnd,
455  kBraggSplit,
456  kUUH,
457  kVtxTj,
458  kChkVxTj,
459  kPhoton,
460  kHaloTj,
461  kNoFitToVx,
462  kVxMerge,
463  kVxNeutral,
464  kNoKinkChk,
465  kChkStop,
466  kChkStopEP,
467  kChkChgAsym,
468  kFTBRvProp,
470  kVtxHitsSwap,
472  kShowerLike,
474  kShowerTj,
475  kShwrParent,
482  kSplitTjCVx,
483  kMakePFPTjs,
484  kStopShort,
486  kFTBMod,
487  kAlgBitSize
488  } AlgBit_t;
AlgBit_t
Definition: DataStructs.h:417
don&#39;t mess with this line
Definition: DataStructs.h:487
Enumerator
kSignal 
kAtKink 
kAtVtx 
kBragg 
kAtTj 
kOutFV 
kNoFitVx 
kFlagBitSize 

don't mess with this line

Definition at line 498 of file DataStructs.h.

498  {
499  kSignal,
500  kAtKink,
501  kAtVtx,
502  kBragg,
503  kAtTj,
504  kOutFV,
505  kNoFitVx,
506  kFlagBitSize
507  } EndFlag_t;
don&#39;t mess with this line
Definition: DataStructs.h:506
EndFlag_t
Definition: DataStructs.h:498
Enumerator
kAllHits 
kUsedHits 
kUnusedHits 

Definition at line 42 of file Utils.h.

42  {
43  kAllHits,
44  kUsedHits,
46  } HitStatus_t;
HitStatus_t
Definition: Utils.h:42
Enumerator
kCanSection 
kNeedsUpdate 
kSmallAngle 

Definition at line 300 of file DataStructs.h.

Enumerator
kNormal 
kStiffEl 

use the stiff electron strategy

kStiffMu 

use the stiff muon strategy

kSlowing 

use the slowing-down strategy

Definition at line 490 of file DataStructs.h.

490  {
491  kNormal,
492  kStiffEl,
493  kStiffMu,
494  kSlowing
495  } Strategy_t;
Strategy_t
Definition: DataStructs.h:490
use the slowing-down strategy
Definition: DataStructs.h:494
use the stiff electron strategy
Definition: DataStructs.h:492
use the stiff muon strategy
Definition: DataStructs.h:493
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 521 of file DataStructs.h.

521  {
522  kStepDir,
523  kTestBeam,
524  kDebug,
525  kStudy1,
526  kStudy2,
527  kStudy3,
528  kStudy4,
529  kSaveCRTree,
530  kTagCosmics,
532  } TCModes_t;
Expect tracks entering from the front face. Don&#39;t create neutrino PFParticles.
Definition: DataStructs.h:523
step from US -> DS (true) or DS -> US (false)
Definition: DataStructs.h:522
call study functions to develop cuts, etc
Definition: DataStructs.h:527
save shower tree
Definition: DataStructs.h:531
call study functions to develop cuts, etc
Definition: DataStructs.h:528
TCModes_t
Definition: DataStructs.h:521
save cosmic ray tree
Definition: DataStructs.h:529
call study functions to develop cuts, etc
Definition: DataStructs.h:526
call study functions to develop cuts, etc (see TCTruth.cxx)
Definition: DataStructs.h:525
master switch for turning on debug mode
Definition: DataStructs.h:524
tag cosmic rays
Definition: DataStructs.h:530
Enumerator
kTP3DGood 
kTP3DBad 
kTP3DHiDEdx 

Definition at line 261 of file DataStructs.h.

261  {
262  kTP3DGood, // Is good for fitting and calorimetry
263  kTP3DBad, // Should be removed from the trajectory
264  kTP3DHiDEdx // Has high dE/dx
265  } TP3DFlags_t;
TP3DFlags_t
Definition: DataStructs.h:261
Enumerator
kEnvNotGoodWire 
kEnvNearMuon 
kEnvNearShower 
kEnvOverlap 
kEnvUnusedHits 
kEnvNearSrcHit 

TP is near a hit in the srcHit collection but no allHit hit exists (DUNE disambiguation error)

kEnvFlag 

a general purpose flag bit used in 3D matching

Definition at line 510 of file DataStructs.h.

510  {
512  kEnvNearMuon,
514  kEnvOverlap,
517  kEnvFlag
518  } TPEnvironment_t;
a general purpose flag bit used in 3D matching
Definition: DataStructs.h:517
TP is near a hit in the srcHit collection but no allHit hit exists (DUNE disambiguation error) ...
Definition: DataStructs.h:516
TPEnvironment_t
Definition: DataStructs.h:510
Enumerator
kVtxTrjTried 

FindVtxTraj algorithm tried.

kFixed 

vertex position fixed manually - no fitting done

kOnDeadWire 
kHiVx3Score 

matched to a high-score 3D vertex

kVxTruMatch 

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

kVxMerged 
kVxIndPlnNoChg 

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

kVxEnvOK 

the environment near the vertex was checked - See UpdateVxEnvironment

kVxBitSize 

don't mess with this line

Definition at line 86 of file DataStructs.h.

86  {
87  kVtxTrjTried,
88  kFixed,
90  kHiVx3Score,
91  kVxTruMatch,
92  kVxMerged,
94  kVxEnvOK,
95  kVxBitSize
96  } VtxBit_t;
FindVtxTraj algorithm tried.
Definition: DataStructs.h:87
tagged as a vertex between Tjs that are matched to MC truth neutrino interaction particles ...
Definition: DataStructs.h:91
vertex position fixed manually - no fitting done
Definition: DataStructs.h:88
matched to a high-score 3D vertex
Definition: DataStructs.h:90
VtxBit_t
Definition: DataStructs.h:86
don&#39;t mess with this line
Definition: DataStructs.h:95
the environment near the vertex was checked - See UpdateVxEnvironment
Definition: DataStructs.h:94
vertex quality is suspect - No requirement made on chg btw it and the Tj
Definition: DataStructs.h:93

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 3413 of file TCShower.cxx.

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

3414  {
3415  // Searches the trajectory points for hits that are used in a different trajectory and add
3416  // them to the list if any are found, and the MCSMomentum is not too large
3417  if (itj > slc.tjs.size() - 1) return;
3418 
3419  //short maxMom = (short)(2 * tcc.showerTag[1]);
3420  short maxMom = tcc.showerTag[1];
3421  //XL: why is maxMom is twice of the shower tag [1]?
3422  for (auto& tp : slc.tjs[itj].Pts) {
3423  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3424  // ignore hits that are used in this trajectory
3425  if (tp.UseHit[ii]) continue;
3426  unsigned int iht = tp.Hits[ii];
3427  // ignore if there is no hit -> Tj association
3428  if (slc.slHits[iht].InTraj <= 0) continue;
3429  if ((unsigned int)slc.slHits[iht].InTraj > slc.tjs.size()) continue;
3430  // check the momentum
3431  Trajectory& tj = slc.tjs[slc.slHits[iht].InTraj - 1];
3432  if (tj.MCSMom > maxMom) continue;
3433  // if(tj.AlgMod[kTjHiVx3Score]) continue;
3434  // see if it is already in the list
3435  if (std::find(list.begin(), list.end(), slc.slHits[iht].InTraj) != list.end()) continue;
3436  list.push_back(slc.slHits[iht].InTraj);
3437  } // ii
3438  } // tp
3439  } // AddCloseTjsToList
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:549
void tca::AddHits ( TCSlice slc,
Trajectory tj,
unsigned short  ipt,
bool &  sigOK 
)

Definition at line 1113 of file StepUtils.cxx.

References util::abs(), 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, tca::TrajPoint::Environment, evt, ExpectedHitsRMS(), FindUseHits(), tca::TCSlice::firstWire, GetHitMultiplet(), tca::TCEvent::goodWire, tca::TrajPoint::Hits, tca::Trajectory::ID, if(), kEnvNearSrcHit, kRvPrp, kSlowing, kStiffEl, kUsedHits, tca::TCSlice::lastWire, LongPulseHit(), MoveTPToWire(), NearbySrcHit(), NumHitsInTP(), geo::PlaneID::Plane, PointTrajDOCA(), tca::TrajPoint::Pos, PrintHit(), tca::TCConfig::projectionErrFactor, tca::Trajectory::Pts, SetEndPoints(), tca::TCSlice::slHits, tca::Trajectory::Strategy, tcc, tca::TCConfig::unitsPerTick, tca::TrajPoint::UseHit, and tca::TCSlice::wireHitRange.

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

1114  {
1115  // Try to add hits to the trajectory point ipt on the supplied
1116  // trajectory
1117 
1118  // assume failure
1119  sigOK = false;
1120 
1121  if (tj.Pts.empty()) return;
1122  if (ipt > tj.Pts.size() - 1) return;
1123 
1124  // Call large angle hit finding if the last tp is large angle
1125  if (tj.Pts[ipt].AngleCode == 2) {
1126  AddLAHits(slc, tj, ipt, sigOK);
1127  return;
1128  }
1129 
1130  TrajPoint& tp = tj.Pts[ipt];
1131  std::vector<unsigned int> closeHits;
1132  unsigned int lastPtWithUsedHits = tj.EndPt[1];
1133 
1134  unsigned short plane = DecodeCTP(tj.CTP).Plane;
1135  unsigned int wire = std::nearbyint(tp.Pos[0]);
1136  if (wire < slc.firstWire[plane] || wire > slc.lastWire[plane] - 1) return;
1137  // Move the TP to this wire
1138  MoveTPToWire(tp, (float)wire);
1139 
1140  // find the projection error to this point. Note that if this is the first
1141  // TP, lastPtWithUsedHits = 0, so the projection error is 0
1142  float dw = tp.Pos[0] - tj.Pts[lastPtWithUsedHits].Pos[0];
1143  float dt = tp.Pos[1] - tj.Pts[lastPtWithUsedHits].Pos[1];
1144  float dpos = sqrt(dw * dw + dt * dt);
1145  float projErr = dpos * tj.Pts[lastPtWithUsedHits].AngErr;
1146  // Add this to the Delta RMS factor and construct a cut
1147  float deltaCut = 3 * (projErr + tp.DeltaRMS);
1148 
1149  // The delta cut shouldn't be less than the delta of hits added on the previous step
1150  float minDeltaCut = 1.1 * tj.Pts[lastPtWithUsedHits].Delta;
1151  if (deltaCut < minDeltaCut) deltaCut = minDeltaCut;
1152 
1153  deltaCut *= tcc.projectionErrFactor;
1154  if (tcc.dbgStp)
1155  mf::LogVerbatim("TC") << " AddHits: calculated deltaCut " << deltaCut << " dw " << dw
1156  << " dpos " << dpos;
1157 
1158  if (deltaCut < 0.5) deltaCut = 0.5;
1159  if (deltaCut > 3) deltaCut = 3;
1160 
1161  // TY: open it up for RevProp, since we might be following a stopping track
1162  if (tj.AlgMod[kRvPrp]) deltaCut *= 2;
1163 
1164  // loosen up a bit if we just passed a block of dead wires
1165  bool passedDeadWires =
1166  (abs(dw) > 20 &&
1167  DeadWireCount(slc, tp.Pos[0], tj.Pts[lastPtWithUsedHits].Pos[0], tj.CTP) > 10);
1168  if (passedDeadWires) deltaCut *= 2;
1169  // open it up for StiffEl and Slowing strategies
1170  if (tj.Strategy[kStiffEl] || tj.Strategy[kSlowing]) deltaCut = 3;
1171 
1172  // Create a larger cut to use in case there is nothing close
1173  float bigDelta = 2 * deltaCut;
1174  unsigned int imBig = UINT_MAX;
1175  tp.Delta = deltaCut;
1176  // ignore all hits with delta larger than maxDeltaCut
1177  float maxDeltaCut = 2 * bigDelta;
1178  // apply some limits
1179  if (!passedDeadWires && maxDeltaCut > 3) {
1180  maxDeltaCut = 3;
1181  bigDelta = 1.5;
1182  }
1183 
1184  // projected time in ticks for testing the existence of a hit signal
1185  raw::TDCtick_t rawProjTick = (float)(tp.Pos[1] / tcc.unitsPerTick);
1186  if (tcc.dbgStp) {
1187  mf::LogVerbatim("TC") << " AddHits: wire " << wire << " tp.Pos[0] " << tp.Pos[0]
1188  << " projTick " << rawProjTick << " deltaRMS " << tp.DeltaRMS
1189  << " tp.Dir[0] " << tp.Dir[0] << " deltaCut " << deltaCut << " dpos "
1190  << dpos << " projErr " << projErr << " ExpectedHitsRMS "
1191  << ExpectedHitsRMS(tp);
1192  }
1193 
1194  std::vector<unsigned int> hitsInMultiplet;
1195 
1196  geo::PlaneID planeID = DecodeCTP(tj.CTP);
1197  unsigned int ipl = planeID.Plane;
1198  if (wire > slc.lastWire[ipl]) return;
1199  // Assume a signal exists on a dead wire
1200  if (!evt.goodWire[ipl][wire]) sigOK = true;
1201  if (slc.wireHitRange[ipl][wire].first == UINT_MAX) return;
1202  unsigned int firstHit = slc.wireHitRange[ipl][wire].first;
1203  unsigned int lastHit = slc.wireHitRange[ipl][wire].second;
1204  float fwire = wire;
1205  for (unsigned int iht = firstHit; iht <= lastHit; ++iht) {
1206  if (slc.slHits[iht].InTraj == tj.ID) continue;
1207  if (slc.slHits[iht].InTraj == SHRT_MAX) continue;
1208  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1209  if (rawProjTick > hit.StartTick() && rawProjTick < hit.EndTick()) sigOK = true;
1210  float ftime = tcc.unitsPerTick * hit.PeakTime();
1211  float delta = PointTrajDOCA(fwire, ftime, tp);
1212  // increase the delta cut if this is a long pulse hit
1213  bool longPulseHit = LongPulseHit(hit);
1214  if (longPulseHit) {
1215  if (delta > 3) continue;
1216  }
1217  else {
1218  if (delta > maxDeltaCut) continue;
1219  }
1220  float dt = std::abs(ftime - tp.Pos[1]);
1221  GetHitMultiplet(slc, iht, hitsInMultiplet, false);
1222  if (tcc.dbgStp && delta < 100 && dt < 100) {
1223  mf::LogVerbatim myprt("TC");
1224  myprt << " iht " << iht;
1225  myprt << " " << PrintHit(slc.slHits[iht]);
1226  myprt << " delta " << std::fixed << std::setprecision(2) << delta << " deltaCut "
1227  << deltaCut << " dt " << dt;
1228  myprt << " BB Mult " << hitsInMultiplet.size() << " RMS " << std::setprecision(1)
1229  << hit.RMS();
1230  myprt << " Chi " << std::setprecision(1) << hit.GoodnessOfFit();
1231  myprt << " InTraj " << slc.slHits[iht].InTraj;
1232  myprt << " Chg " << (int)hit.Integral();
1233  myprt << " Signal? " << sigOK;
1234  }
1235  if (slc.slHits[iht].InTraj == 0 && delta < bigDelta && hitsInMultiplet.size() < 3 &&
1236  !tj.AlgMod[kRvPrp]) {
1237  // An available hit that is just outside the window that is not part of a large multiplet
1238  bigDelta = delta;
1239  imBig = iht;
1240  }
1241  if (longPulseHit) {
1242  if (delta > 3) continue;
1243  }
1244  else {
1245  if (delta > deltaCut) continue;
1246  }
1247 
1248  if (std::find(closeHits.begin(), closeHits.end(), iht) != closeHits.end()) continue;
1249  closeHits.push_back(iht);
1250  if (hitsInMultiplet.size() > 1) {
1251  // include all the hits in a multiplet
1252  for (auto& jht : hitsInMultiplet) {
1253  if (slc.slHits[jht].InTraj == tj.ID) continue;
1254  if (std::find(closeHits.begin(), closeHits.end(), jht) != closeHits.end()) continue;
1255  closeHits.push_back(jht);
1256  } // jht
1257  } // multiplicity > 1
1258  } // iht
1259 
1260  if (tcc.dbgStp) {
1261  mf::LogVerbatim myprt("TC");
1262  myprt << "closeHits ";
1263  for (auto iht : closeHits)
1264  myprt << " " << PrintHit(slc.slHits[iht]);
1265  if (imBig < slc.slHits.size()) { myprt << " imBig " << PrintHit(slc.slHits[imBig]); }
1266  else {
1267  myprt << " imBig " << imBig;
1268  }
1269  }
1270  // check the srcHit collection if it is defined. Add the TP to the trajectory if
1271  // there is NO hit in the allHits collection but there is a hit in srcHit collection. We
1272  // can't use it for fitting, etc however
1273  bool nearSrcHit = false;
1274  if (!sigOK) nearSrcHit = NearbySrcHit(planeID, wire, (float)rawProjTick, (float)rawProjTick);
1275  sigOK = sigOK || !closeHits.empty() || nearSrcHit;
1276 
1277  if (!sigOK) {
1278  if (tcc.dbgStp)
1279  mf::LogVerbatim("TC") << " no signal on any wire at tp.Pos " << tp.Pos[0] << " "
1280  << tp.Pos[1] << " tick " << (int)tp.Pos[1] / tcc.unitsPerTick
1281  << " closeHits size " << closeHits.size();
1282  return;
1283  }
1284  if (imBig < slc.slHits.size() && closeHits.empty()) {
1285  closeHits.push_back(imBig);
1286  if (tcc.dbgStp)
1287  mf::LogVerbatim("TC") << " Added bigDelta hit " << PrintHit(slc.slHits[imBig])
1288  << " w delta = " << bigDelta;
1289  }
1290  if (closeHits.size() > 16) closeHits.resize(16);
1291  if (nearSrcHit) tp.Environment[kEnvNearSrcHit] = true;
1292  tp.Hits.insert(tp.Hits.end(), closeHits.begin(), closeHits.end());
1293 
1294  // reset UseHit and assume that none of these hits will be used (yet)
1295  tp.UseHit.reset();
1296  // decide which of these hits should be used in the fit. Use a generous maximum delta
1297  // and require a charge check if we're not just starting out
1298  bool useChg = true;
1299  if (tj.Strategy[kStiffEl] || tj.Strategy[kSlowing]) useChg = false;
1300  FindUseHits(slc, tj, ipt, 10, useChg);
1301  DefineHitPos(slc, tp);
1302  SetEndPoints(tj);
1303  if (tcc.dbgStp)
1304  mf::LogVerbatim("TC") << " number of close hits " << closeHits.size() << " used hits "
1305  << NumHitsInTP(tp, kUsedHits);
1306  } // AddHits
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
constexpr auto abs(T v)
Returns the absolute value of the argument.
void FindUseHits(TCSlice &slc, Trajectory &tj, unsigned short ipt, float maxDelta, bool useChg)
Definition: StepUtils.cxx:1882
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2514
bool LongPulseHit(const recob::Hit &hit)
Definition: Utils.cxx:4317
int TDCtick_t
Type representing a TDC tick.
Definition: RawTypes.h:25
float projectionErrFactor
Definition: DataStructs.h:575
if(nlines<=0)
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
use the slowing-down strategy
Definition: DataStructs.h:494
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2095
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1791
TP is near a hit in the srcHit collection but no allHit hit exists (DUNE disambiguation error) ...
Definition: DataStructs.h:516
void GetHitMultiplet(const TCSlice &slc, unsigned int theHit, std::vector< unsigned int > &hitsInMultiplet, bool useLongPulseHits)
Definition: StepUtils.cxx:1521
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:622
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6347
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
float ExpectedHitsRMS(const TrajPoint &tp)
Definition: Utils.cxx:1911
unsigned short NumHitsInTP(const TrajPoint &tp, HitStatus_t hitRequest)
Definition: Utils.cxx:4198
Detector simulation of raw signals on wires.
void AddLAHits(TCSlice &slc, Trajectory &tj, unsigned short ipt, bool &sigOK)
Definition: StepUtils.cxx:1309
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
use the stiff electron strategy
Definition: DataStructs.h:492
bool NearbySrcHit(geo::PlaneID plnID, unsigned int wire, float loTick, float hiTick)
Definition: Utils.cxx:2030
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2763
TCEvent evt
Definition: DataStructs.cxx:8
void tca::AddLAHits ( TCSlice slc,
Trajectory tj,
unsigned short  ipt,
bool &  sigOK 
)

Definition at line 1309 of file StepUtils.cxx.

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

Referenced by AddHits().

1310  {
1311  // Very Large Angle version of AddHits to be called for the last angle range
1312 
1313  if (ipt > tj.Pts.size() - 1) return;
1314  TrajPoint& tp = tj.Pts[ipt];
1315  tp.Hits.clear();
1316  tp.UseHit.reset();
1317  sigOK = false;
1318 
1319  unsigned short plane = DecodeCTP(tj.CTP).Plane;
1320 
1321  // look at adjacent wires for larger angle trajectories
1322  // We will check the most likely wire first
1323  std::vector<int> wires(1);
1324  wires[0] = std::nearbyint(tp.Pos[0]);
1325  if (wires[0] < 0 || wires[0] > (int)slc.lastWire[plane] - 1) return;
1326 
1327  if (tp.AngleCode != 2) {
1328  mf::LogVerbatim("TC") << "AddLAHits called with a bad angle code. " << tp.AngleCode
1329  << " Don't do this";
1330  return;
1331  }
1332  // and the adjacent wires next in the most likely order only
1333  // after the first two points have been defined
1334  if (ipt > 1) {
1335  if (tp.Dir[0] > 0) {
1336  if (wires[0] < (int)slc.lastWire[plane] - 1) wires.push_back(wires[0] + 1);
1337  if (wires[0] > 0) wires.push_back(wires[0] - 1);
1338  }
1339  else {
1340  if (wires[0] > 0) wires.push_back(wires[0] - 1);
1341  if (wires[0] < (int)slc.lastWire[plane] - 1) wires.push_back(wires[0] + 1);
1342  }
1343  } // ipt > 0 ...
1344 
1345  if (tcc.dbgStp) {
1346  mf::LogVerbatim myprt("TC");
1347  myprt << " AddLAHits: Pos " << PrintPos(tp) << " tp.AngleCode " << tp.AngleCode
1348  << " Wires under consideration";
1349  for (auto& wire : wires)
1350  myprt << " " << wire;
1351  }
1352 
1353  // a temporary tp that we can move around
1354  TrajPoint ltp = tp;
1355  // do this while testing
1356  sigOK = false;
1357 
1358  tp.Hits.clear();
1359  std::array<int, 2> wireWindow;
1360  std::array<float, 2> timeWindow;
1361  float pos1Window = tcc.VLAStepSize / 2;
1362  timeWindow[0] = ltp.Pos[1] - pos1Window;
1363  timeWindow[1] = ltp.Pos[1] + pos1Window;
1364  // Put the existing hits in to a vector so we can ensure that they aren't added again
1365  std::vector<unsigned int> oldHits = PutTrajHitsInVector(tj, kAllHits);
1366 
1367  for (unsigned short ii = 0; ii < wires.size(); ++ii) {
1368  int wire = wires[ii];
1369  if (wire < 0 || wire > (int)slc.lastWire[plane]) continue;
1370  // Assume a signal exists on a dead wire
1371  if (slc.wireHitRange[plane][wire].first == UINT_MAX) sigOK = true;
1372  if (slc.wireHitRange[plane][wire].first == UINT_MAX) continue;
1373  wireWindow[0] = wire;
1374  wireWindow[1] = wire;
1375  bool hitsNear;
1376  // Look for hits using the requirement that the timeWindow overlaps with the hit StartTick and EndTick
1377  std::vector<unsigned int> closeHits =
1378  FindCloseHits(slc, wireWindow, timeWindow, plane, kAllHits, true, hitsNear);
1379  if (hitsNear) sigOK = true;
1380  for (auto& iht : closeHits) {
1381  // Ensure that none of these hits are already used by this trajectory
1382  if (slc.slHits[iht].InTraj == tj.ID) continue;
1383  // or in another trajectory in any previously added point
1384  if (std::find(oldHits.begin(), oldHits.end(), iht) != oldHits.end()) continue;
1385  tp.Hits.push_back(iht);
1386  }
1387  } // ii
1388 
1389  if (tcc.dbgStp) {
1390  mf::LogVerbatim myprt("TC");
1391  myprt << " LAPos " << PrintPos(ltp) << " Tick window "
1392  << (int)(timeWindow[0] / tcc.unitsPerTick) << " to "
1393  << (int)(timeWindow[1] / tcc.unitsPerTick);
1394  for (auto& iht : tp.Hits)
1395  myprt << " " << PrintHit(slc.slHits[iht]);
1396  } // prt
1397 
1398  // no hits found
1399  if (tp.Hits.empty()) return;
1400 
1401  if (tp.Hits.size() > 16) tp.Hits.resize(16);
1402 
1403  tp.UseHit.reset();
1404  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1405  unsigned int iht = tp.Hits[ii];
1406  if (slc.slHits[iht].InTraj != 0) continue;
1407  tp.UseHit[ii] = true;
1408  slc.slHits[iht].InTraj = tj.ID;
1409  } // ii
1410  DefineHitPos(slc, tp);
1411  SetEndPoints(tj);
1412  UpdateTjChgProperties("ALAH", slc, tj, tcc.dbgStp);
1413 
1414  } // AddLAHits
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
std::vector< unsigned int > PutTrajHitsInVector(const Trajectory &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2689
TCConfig tcc
Definition: DataStructs.cxx:9
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1791
std::vector< unsigned int > FindCloseHits(const 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:2774
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6347
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice const &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3577
float VLAStepSize
Definition: DataStructs.h:576
geo::PlaneID DecodeCTP(CTP_t CTP)
bool tca::AddLooseHits ( std::string  inFcnLabel,
TCSlice slc,
int  cotID,
bool  prt 
)
bool tca::AddLooseHits ( TCSlice slc,
int  cotID,
bool  prt 
)

Definition at line 3578 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, if(), tca::TCSlice::lastWire, geo::PlaneID::Plane, PointInsideEnvelope(), tca::Trajectory::Pts, tca::ShowerStruct::ShowerTjID, tca::TCSlice::slHits, tcc, tca::ShowerStruct::TjIDs, tca::TCSlice::tjs, tca::TCConfig::unitsPerTick, and tca::TCSlice::wireHitRange.

3579  {
3580  // Add hits that are inside the envelope to the shower if they are loose, i.e. not
3581  // used by any trajectory. This function returns true if the set of hits is different than
3582  // the current set. The calling function should update the shower if this is the case.
3583 
3584  ShowerStruct& ss = slc.cots[cotID - 1];
3585  if (ss.Envelope.empty()) return false;
3586  if (ss.ID == 0) return false;
3587  if (ss.TjIDs.empty()) return false;
3588 
3589  geo::PlaneID planeID = DecodeCTP(ss.CTP);
3590  unsigned short ipl = planeID.Plane;
3591 
3592  Trajectory& stj = slc.tjs[ss.ShowerTjID - 1];
3593  TrajPoint& stp0 = stj.Pts[0];
3594  // start a list of new hits
3595  std::vector<unsigned int> newHits;
3596 
3597  // look for hits inside the envelope. Find the range of wires that spans the envelope
3598  float fLoWire = 1E6;
3599  float fHiWire = 0;
3600  // and the range of ticks
3601  float loTick = 1E6;
3602  float hiTick = 0;
3603  for (auto& vtx : ss.Envelope) {
3604  if (vtx[0] < fLoWire) fLoWire = vtx[0];
3605  if (vtx[0] > fHiWire) fHiWire = vtx[0];
3606  if (vtx[1] < loTick) loTick = vtx[1];
3607  if (vtx[1] > hiTick) hiTick = vtx[1];
3608  } // vtx
3609  loTick /= tcc.unitsPerTick;
3610  hiTick /= tcc.unitsPerTick;
3611  unsigned int loWire = std::nearbyint(fLoWire);
3612  unsigned int hiWire = std::nearbyint(fHiWire) + 1;
3613  if (hiWire > slc.lastWire[ipl] - 1) hiWire = slc.lastWire[ipl] - 1;
3614  std::array<float, 2> point;
3615  for (unsigned int wire = loWire; wire < hiWire; ++wire) {
3616  // skip bad wires or no hits on the wire
3617  if (slc.wireHitRange[ipl][wire].first == UINT_MAX) continue;
3618  unsigned int firstHit = slc.wireHitRange[ipl][wire].first;
3619  unsigned int lastHit = slc.wireHitRange[ipl][wire].second;
3620  for (unsigned int iht = firstHit; iht < lastHit; ++iht) {
3621  // used in a trajectory?
3622  if (slc.slHits[iht].InTraj != 0) continue;
3623  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
3624  // inside the tick range?
3625  if (hit.PeakTime() < loTick) continue;
3626  // Note that hits are sorted by increasing time so we can break here
3627  if (hit.PeakTime() > hiTick) break;
3628  // see if this hit is inside the envelope
3629  point[0] = hit.WireID().Wire;
3630  point[1] = hit.PeakTime() * tcc.unitsPerTick;
3631  if (!PointInsideEnvelope(point, ss.Envelope)) continue;
3632  newHits.push_back(iht);
3633  } // iht
3634  } // wire
3635 
3636  // no new hits and no old hits. Nothing to do
3637  if (newHits.empty()) {
3638  if (prt) mf::LogVerbatim("TC") << "ALH: No new loose hits found";
3639  return false;
3640  }
3641 
3642  // Update
3643  stp0.Hits.insert(stp0.Hits.end(), newHits.begin(), newHits.end());
3644  for (auto& iht : newHits)
3645  slc.slHits[iht].InTraj = stj.ID;
3646 
3647  if (prt)
3648  mf::LogVerbatim("TC") << "ALH: Added " << stp0.Hits.size() << " hits to stj " << stj.ID;
3649  return true;
3650 
3651  } // AddLooseHits
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
if(nlines<=0)
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:3246
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
Detector simulation of raw signals on wires.
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
bool tca::AddPFP ( std::string  inFcnLabel,
TCSlice slc,
int  pID,
ShowerStruct3D ss3,
bool  doUpdate,
bool  prt 
)

Definition at line 1368 of file TCShower.cxx.

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

Referenced by Reconcile3D().

1374  {
1375  // Add the tjs in the pfp with id = pID to the 2D showers in ss3 and optionally update everything. This
1376  // function returns true if the addition was successful or if the Tjs in the pfp are already in ss3.
1377  // This function returns false if there was a failure. There isn't any error recovery.
1378 
1379  std::string fcnLabel = inFcnLabel + ".AddP";
1380 
1381  if (pID <= 0 || pID > (int)slc.pfps.size()) return false;
1382  auto& pfp = slc.pfps[pID - 1];
1383 
1384  if (pfp.TPCID != ss3.TPCID) {
1385  mf::LogVerbatim("TC") << fcnLabel << " P" << pID << " is in the wrong TPC for 3S" << ss3.ID;
1386  return false;
1387  }
1388 
1389  for (auto tid : pfp.TjIDs) {
1390  auto& tj = slc.tjs[tid - 1];
1391  // is this tj in a 2D shower that is in a 3D shower that is not this shower?
1392  if (tj.SSID > 0) {
1393  auto& ss = slc.cots[tj.SSID - 1];
1394  if (ss.SS3ID > 0 && ss.SS3ID != ss3.ID) {
1395  if (prt)
1396  mf::LogVerbatim("TC") << fcnLabel << " Conflict: 3S" << ss3.ID << " adding P" << pfp.ID
1397  << " -> T" << tid << " is in 2S" << tj.SSID << " that is in 3S"
1398  << ss.SS3ID << " that is not this shower";
1399  return false;
1400  } // conflict
1401  // tj is in the correct 2D shower so nothing needs to be done
1402  if (prt)
1403  mf::LogVerbatim("TC") << fcnLabel << " 3S" << ss3.ID << " adding P" << pfp.ID << " -> T"
1404  << tid << " is in the correct shower 2S" << tj.SSID;
1405  continue;
1406  } // pfp tj is in a shower
1407  if (prt) {
1408  mf::LogVerbatim myprt("TC");
1409  myprt << fcnLabel << " 3S" << ss3.ID << " adding P" << pfp.ID << " -> T" << tid;
1410  myprt << " tj.SSID 2S" << tj.SSID;
1411  } // prt
1412  // add it to the shower in the correct CTP
1413  for (auto& cid : ss3.CotIDs) {
1414  auto& ss = slc.cots[cid - 1];
1415  if (ss.CTP != tj.CTP) continue;
1416  // Add it to the shower.
1417  AddTj(fcnLabel, slc, tid, ss, doUpdate, prt);
1418  ss3.NeedsUpdate = true;
1419  break;
1420  } // cid
1421  } // tid
1422 
1423  if (doUpdate && ss3.NeedsUpdate) UpdateShower(fcnLabel, slc, ss3, prt);
1424  return true;
1425 
1426  } // AddPFP
bool AddTj(std::string inFcnLabel, TCSlice &slc, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1429
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1106
void tca::AddPointsInRange ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
TCSlice slc,
PFPStruct pfp,
unsigned short  fromPt,
unsigned short  toPt,
CTP_t  inCTP,
float  maxPull,
unsigned short &  nWires,
unsigned short &  nAdd,
bool  prt 
)

Definition at line 1811 of file PFPUtils.cxx.

References Average_dEdX(), CreateTP3D(), DecodeCTP(), dEdx(), FindCloseHits(), tca::PFPStruct::ID, tca::TCSlice::ID, InsertTP3D(), kEnvNotGoodWire, kEnvOverlap, kUsedHits, MakeBareTP(), MoveTPToWire(), tca::TCSlice::nWires, geo::PlaneID::Plane, PointPull(), tca::TP3D::Pos, PrintPos(), tca::PFPStruct::SectionFits, SetAngleCode(), SetSection(), tca::TP3D::SFIndex, tca::TCSlice::slHits, tca::TP3D::TjID, tca::TCSlice::tjs, tca::PFPStruct::TP3Ds, tca::TP3D::TPIndex, and tca::TP3D::TPX.

Referenced by FillGaps3D().

1822  {
1823  // Try to insert 2D trajectory points into the 3D trajectory point vector pfp.TP3Ds.
1824  // This function inserts new TP3Ds and sets the NeedsUpdate flags true.
1825  // The calling function should call Update
1826  // Note that maxPull is used for the charge pull as well as the position pull
1827  nWires = 0;
1828  nAdd = 0;
1829  if (fromPt > toPt) return;
1830  if (toPt >= pfp.TP3Ds.size()) toPt = pfp.TP3Ds.size() - 1;
1831 
1832  // Find the average dE/dx so we can apply a generous min/max dE/dx cut
1833  float dEdXAve = 0;
1834  float dEdXRms = 0;
1835  Average_dEdX(clockData, detProp, slc, pfp, dEdXAve, dEdXRms);
1836  float dEdxMin = 0.5, dEdxMax = 50.;
1837  if (dEdXAve > 0.5) {
1838  dEdxMin = dEdXAve - maxPull * dEdXRms;
1839  if (dEdxMin < 0.5) dEdxMin = 0.5;
1840  dEdxMax = dEdXAve + maxPull * dEdXRms;
1841  if (dEdxMax > 50.) dEdxMax = 50.;
1842  } // dEdXAve > 0.5
1843 
1844  // Split the range into sub-ranges; one for each SectionFit and make 2D TPs at the
1845  // start of each sub-range.
1846  std::vector<TrajPoint> sfTPs;
1847  // form a list of TPs that are used in this CTP
1848  std::vector<std::pair<int, unsigned short>> tpUsed;
1849  for (auto& tp3d : pfp.TP3Ds) {
1850  if (tp3d.CTP != inCTP) continue;
1851  tpUsed.push_back(std::make_pair(tp3d.TjID, tp3d.TPIndex));
1852  } // tp3d
1853  unsigned int toWire = 0;
1854  unsigned int fromWire = UINT_MAX;
1855 
1856  unsigned short inSF = USHRT_MAX;
1857  unsigned short pln = DecodeCTP(inCTP).Plane;
1858  for (unsigned short ipt = 0; ipt < pfp.TP3Ds.size(); ++ipt) {
1859  auto& tp3d = pfp.TP3Ds[ipt];
1860  // Skip if not the last point and we already found a point in this SectionFit
1861  if (ipt < pfp.TP3Ds.size() - 1 && tp3d.SFIndex == inSF) continue;
1862  unsigned int wire;
1863  if (tp3d.CTP == inCTP) {
1864  // Found the first tp3d in a new SectionFit and it is in the right CTP
1865  auto& tp = slc.tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
1866  sfTPs.push_back(tp);
1867  wire = std::nearbyint(tp.Pos[0]);
1868  if (wire >= slc.nWires[pln]) break;
1869  }
1870  else {
1871  // Found the first tp3d in a new SectionFit and it is in a different CTP.
1872  // Make a TP in the right CTP
1873  auto tp = MakeBareTP(detProp, tp3d.Pos, tp3d.Dir, inCTP);
1874  wire = std::nearbyint(tp.Pos[0]);
1875  if (wire >= slc.nWires[pln]) break;
1876  sfTPs.push_back(tp);
1877  }
1878  if (wire < fromWire) fromWire = wire;
1879  if (wire > toWire) toWire = wire;
1880  inSF = tp3d.SFIndex;
1881  } // tp3d
1882  if (sfTPs.empty()) return;
1883  // reverse the vector if necessary so the wires will be in increasing order
1884  if (sfTPs.size() > 1 && sfTPs[0].Pos[0] > sfTPs.back().Pos[0]) {
1885  std::reverse(sfTPs.begin(), sfTPs.end());
1886  }
1887 
1888  // set a generous search window in WSE units
1889  float window = 50;
1890 
1891  if (prt)
1892  mf::LogVerbatim("TC") << "APIR: inCTP " << inCTP << " fromWire " << fromWire << " toWire "
1893  << toWire;
1894 
1895  // iterate over the sub-ranges
1896  for (unsigned short subr = 0; subr < sfTPs.size(); ++subr) {
1897  auto& fromTP = sfTPs[subr];
1898  unsigned int toWireInSF = toWire;
1899  if (subr < sfTPs.size() - 1) toWireInSF = std::nearbyint(sfTPs[subr + 1].Pos[0]);
1900  SetAngleCode(fromTP);
1901  unsigned int fromWire = std::nearbyint(fromTP.Pos[0]);
1902  if (fromWire > toWire) continue;
1903  if (prt)
1904  mf::LogVerbatim("TC") << " inCTP " << inCTP << " subr " << subr << " fromWire " << fromWire
1905  << " toWireInSF " << toWireInSF;
1906  for (unsigned int wire = fromWire; wire <= toWireInSF; ++wire) {
1907  MoveTPToWire(fromTP, (float)wire);
1908  if (!FindCloseHits(slc, fromTP, window, kUsedHits)) continue;
1909  if (fromTP.Environment[kEnvNotGoodWire]) continue;
1910  float bestPull = maxPull;
1911  TP3D bestTP3D;
1912  for (auto iht : fromTP.Hits) {
1913  if (slc.slHits[iht].InTraj <= 0) continue;
1914  // this hit is used in a TP so find the tpIndex
1915  auto& utj = slc.tjs[slc.slHits[iht].InTraj - 1];
1916  unsigned short tpIndex = 0;
1917  for (tpIndex = utj.EndPt[0]; tpIndex <= utj.EndPt[1]; ++tpIndex) {
1918  auto& utp = utj.Pts[tpIndex];
1919  if (utp.Chg <= 0) continue;
1920  // This doesn't check for UseHit true but that is probably ok here
1921  if (std::find(utp.Hits.begin(), utp.Hits.end(), iht) != utp.Hits.end()) break;
1922  } // ipt
1923  if (tpIndex > utj.EndPt[1]) continue;
1924  // see if it is already used in this pfp
1925  std::pair<int, unsigned short> tppr = std::make_pair(utj.ID, tpIndex);
1926  if (std::find(tpUsed.begin(), tpUsed.end(), tppr) != tpUsed.end()) continue;
1927  tpUsed.push_back(tppr);
1928  auto& utp = utj.Pts[tpIndex];
1929  // see if it is used in a different PFP
1930  if (utp.InPFP > 0) continue;
1931  // or if it overlaps another trajectory near a 2D vertex
1932  if (utp.Environment[kEnvOverlap]) continue;
1933  auto newTP3D = CreateTP3D(detProp, slc, utj.ID, tpIndex);
1934  if (!SetSection(detProp, pfp, newTP3D)) continue;
1935  // set the direction to the direction of the SectionFit it is in so we can calculate dE/dx
1936  newTP3D.Dir = pfp.SectionFits[newTP3D.SFIndex].Dir;
1937  float pull = PointPull(newTP3D);
1938  float dedx = dEdx(clockData, detProp, slc, newTP3D);
1939  // Require a good pull and a consistent dE/dx (MeV/cm)
1940  bool useIt = (pull < bestPull && dedx > dEdxMin && dedx < dEdxMax);
1941  if (!useIt) continue;
1942  bestTP3D = newTP3D;
1943  bestPull = pull;
1944  } // iht
1945  if (bestPull < maxPull) {
1946  if (prt && bestPull < 10) {
1947  mf::LogVerbatim myprt("TC");
1948  auto& tp = slc.tjs[bestTP3D.TjID - 1].Pts[bestTP3D.TPIndex];
1949  myprt << "APIR: P" << pfp.ID << " added TP " << PrintPos(tp);
1950  myprt << " pull " << std::fixed << std::setprecision(2) << bestPull;
1951  myprt << " dx " << bestTP3D.TPX - bestTP3D.Pos[0] << " in section " << bestTP3D.SFIndex;
1952  }
1953  if (InsertTP3D(pfp, bestTP3D) == USHRT_MAX) continue;
1954  ++nAdd;
1955  } // bestPull < maxPull
1956  } // wire
1957  } // subr
1958  } // AddPointsInRange
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void Average_dEdX(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, float &dEdXAve, float &dEdXRms)
Definition: PFPUtils.cxx:2635
void SetAngleCode(TrajPoint &tp)
Definition: Utils.cxx:765
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
std::vector< unsigned int > FindCloseHits(const 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:2774
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const Point3_t &pos, CTP_t inCTP)
Definition: Utils.cxx:3928
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
float dEdx(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, TP3D &tp3d)
Definition: PFPUtils.cxx:2671
unsigned short InsertTP3D(PFPStruct &pfp, TP3D &tp3d)
Definition: PFPUtils.cxx:1961
TP3D CreateTP3D(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, int tjID, unsigned short tpIndex)
Definition: PFPUtils.cxx:2706
geo::PlaneID DecodeCTP(CTP_t CTP)
float PointPull(const TP3D &tp3d)
Definition: PFPUtils.cxx:2794
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2763
bool SetSection(detinfo::DetectorPropertiesData const &detProp, PFPStruct &pfp, TP3D &tp3d)
Definition: PFPUtils.cxx:2752
bool tca::AddTj ( std::string  inFcnLabel,
TCSlice slc,
int  tjID,
ShowerStruct ss,
bool  doUpdate,
bool  prt 
)

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

1435  {
1436  // Adds the Tj to the shower and optionally updates the shower variables
1437 
1438  if (tjID <= 0 || tjID > (int)slc.tjs.size()) return false;
1439 
1440  std::string fcnLabel = inFcnLabel + ".AddT";
1441 
1442  Trajectory& tj = slc.tjs[tjID - 1];
1443 
1444  if (tj.CTP != ss.CTP) {
1445  mf::LogVerbatim("TC") << fcnLabel << " T" << tjID << " is in the wrong CTP for 2S" << ss.ID;
1446  return false;
1447  }
1448 
1449  if (tj.SSID > 0) {
1450  if (tj.SSID == ss.ID) {
1451  if (prt) mf::LogVerbatim("TC") << fcnLabel << " T" << tjID << " is already in 2S" << ss.ID;
1452  return true;
1453  }
1454  else {
1455  if (prt)
1456  mf::LogVerbatim("TC") << fcnLabel << " Can't add T" << tjID << " to 2S" << ss.ID
1457  << ". it is already used in 2S" << tj.SSID;
1458  return false;
1459  }
1460  } // tj.SSID > 0
1461 
1462  ss.TjIDs.push_back(tjID);
1463  tj.SSID = ss.ID;
1464  std::sort(ss.TjIDs.begin(), ss.TjIDs.end());
1465  // remove this ID from the NearTjIDs list
1466  for (unsigned short ii = 0; ii < ss.NearTjIDs.size(); ++ii) {
1467  if (ss.NearTjIDs[ii] == tjID) ss.NearTjIDs.erase(ss.NearTjIDs.begin() + ii);
1468  }
1469  // count the hits in the TPs
1470  unsigned short cnt = 0;
1471  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1472  TrajPoint& tp = tj.Pts[ipt];
1473  if (tp.Chg == 0) continue;
1474  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii)
1475  if (tp.UseHit[ii]) ++cnt;
1476  } // ipt
1477  unsigned short newSize = ss.ShPts.size() + cnt;
1478  cnt = ss.ShPts.size();
1479  ss.ShPts.resize(newSize);
1480  // now add them
1481  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1482  TrajPoint& tp = tj.Pts[ipt];
1483  if (tp.Chg == 0) continue;
1484  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1485  if (tp.UseHit[ii]) {
1486  unsigned int iht = tp.Hits[ii];
1487  ss.ShPts[cnt].HitIndex = iht;
1488  ss.ShPts[cnt].TID = tj.ID;
1489  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1490  ss.ShPts[cnt].Chg = hit.Integral();
1491  ss.ShPts[cnt].Pos[0] = hit.WireID().Wire;
1492  ss.ShPts[cnt].Pos[1] = hit.PeakTime() * tcc.unitsPerTick;
1493  ++cnt;
1494  }
1495  }
1496  } // ipt
1497  if (prt) mf::LogVerbatim("TC") << fcnLabel << " Added T" << tj.ID << " to 2S" << ss.ID;
1498  ss.NeedsUpdate = true;
1499 
1500  if (doUpdate) return UpdateShower(fcnLabel, slc, ss, prt);
1501  return true;
1502 
1503  } // AddTj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1106
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
bool tca::AddTjsInsideEnvelope ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct ss,
bool  prt 
)

Definition at line 3503 of file TCShower.cxx.

References util::abs(), 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().

3504  {
3505  // This function adds Tjs to the shower. It updates the shower parameters.
3506 
3507  if (ss.Envelope.empty()) return false;
3508  if (ss.ID == 0) return false;
3509  if (ss.TjIDs.empty()) return false;
3510 
3511  std::string fcnLabel = inFcnLabel + ".ATIE";
3512 
3513  if (prt) mf::LogVerbatim("TC") << fcnLabel << " Checking 2S" << ss.ID;
3514 
3515  std::vector<int> tmp(1);
3516  unsigned short nadd = 0;
3517  for (auto& tj : slc.tjs) {
3518  if (tj.CTP != ss.CTP) continue;
3519  if (tj.AlgMod[kKilled]) continue;
3520  if (tj.SSID > 0) continue;
3521  if (tj.AlgMod[kShowerTj]) continue;
3522  // See if this Tjs is attached to a neutrino vertex.
3523  if (tj.ParentID == 0) continue;
3524  int neutPrimTj = NeutrinoPrimaryTjID(slc, tj);
3525  if (neutPrimTj > 0 && neutPrimTj != tj.ID) {
3526  // The Tj is connected to a primary Tj that is associated with a neutrino primary.
3527  // Don't allow tjs to be added to the shower that are not connected to this neutrino primary (if
3528  // one exists)
3529  if (ss.ParentID > 0 && neutPrimTj != ss.ParentID) continue;
3530  } // neutrino primary tj
3531  // This shouldn't be necessary but ensure that the Tj ID appears only once in ss.TjIDs
3532  if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tj.ID) != ss.TjIDs.end()) continue;
3533  // check consistency
3534  tmp[0] = tj.ID;
3535  if (DontCluster(slc, tmp, ss.TjIDs)) continue;
3536  // See if both ends are outside the envelope
3537  bool end0Inside = PointInsideEnvelope(tj.Pts[tj.EndPt[0]].Pos, ss.Envelope);
3538  bool end1Inside = PointInsideEnvelope(tj.Pts[tj.EndPt[1]].Pos, ss.Envelope);
3539  if (!end0Inside && !end1Inside) continue;
3540  if (end0Inside && end1Inside) {
3541  // TODO: See if the Tj direction is compatible with the shower?
3542  if (AddTj(fcnLabel, slc, tj.ID, ss, false, prt)) ++nadd;
3543  ++nadd;
3544  continue;
3545  } // both ends inside
3546  // Require high momentum Tjs be aligned with the shower axis
3547  // TODO also require high momentum Tjs close to the shower axis?
3548 
3549  if (tj.MCSMom > 200) {
3550  float tjAngle = tj.Pts[tj.EndPt[0]].Ang;
3551  float dangPull = std::abs(tjAngle - ss.AngleErr) / ss.AngleErr;
3552  if (prt)
3553  mf::LogVerbatim("TC") << fcnLabel << " high MCSMom " << tj.MCSMom << " dangPull "
3554  << dangPull;
3555  if (dangPull > 2) continue;
3556  } // high momentum
3557  if (AddTj(fcnLabel, slc, tj.ID, ss, false, prt)) { ++nadd; }
3558  else {
3559  if (prt) mf::LogVerbatim("TC") << fcnLabel << " AddTj failed to add T" << tj.ID;
3560  }
3561  } // tj
3562 
3563  if (nadd > 0) {
3564  if (prt) mf::LogVerbatim("TC") << fcnLabel << " Added " << nadd << " trajectories ";
3565  ss.NeedsUpdate = true;
3566  UpdateShower(fcnLabel, slc, ss, prt);
3567  return true;
3568  }
3569  else {
3570  if (prt) mf::LogVerbatim("TC") << fcnLabel << " No new trajectories added to envelope ";
3571  ss.NeedsUpdate = false;
3572  return false;
3573  }
3574 
3575  } // AddTjsInsideEnvelope
bool AddTj(std::string inFcnLabel, TCSlice &slc, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1429
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
constexpr auto abs(T v)
Returns the absolute value of the argument.
bool DontCluster(TCSlice const &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3213
Float_t tmp
Definition: plot.C:35
int NeutrinoPrimaryTjID(const TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:446
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1106
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:3246
bool tca::AnalyzeHits ( )

Definition at line 4261 of file Utils.cxx.

References tca::TCEvent::allHits, tca::TCEvent::aveHitRMS, tca::TCEvent::aveHitRMSValid, evt, kDebug, tca::TCConfig::modes, geo::WireReadoutGeom::Nplanes(), util::size(), tcc, and tca::TCConfig::wireReadoutGeom.

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

4262  {
4263  // Find the average hit rms by analyzing the full hit collection. This
4264  // only needs to be done once per job.
4265 
4266  if ((*evt.allHits).empty()) return true;
4267  // no sense re-calculating it if it's been done
4268  if (evt.aveHitRMSValid) return true;
4269 
4270  auto const& wireid = (*evt.allHits)[0].WireID();
4271 
4272  unsigned short nplanes = tcc.wireReadoutGeom->Nplanes(wireid.asPlaneID());
4273  evt.aveHitRMS.resize(nplanes);
4274  std::vector<float> cnt(nplanes, 0);
4275  for (unsigned short iht = 0; iht < (*evt.allHits).size(); ++iht) {
4276  auto& hit = (*evt.allHits)[iht];
4277  unsigned short plane = hit.WireID().Plane;
4278  if (plane > nplanes - 1) return false;
4279  if (cnt[plane] > 200) continue;
4280  // require multiplicity one
4281  if (hit.Multiplicity() != 1) continue;
4282  // not-crazy Chisq/DOF
4283  if (hit.GoodnessOfFit() < 0 || hit.GoodnessOfFit() > 500) continue;
4284  // don't let a lot of runt hits screw up the calculation
4285  if (hit.PeakAmplitude() < 1) continue;
4286  evt.aveHitRMS[plane] += hit.RMS();
4287  ++cnt[plane];
4288  // quit if enough hits are found
4289  bool allDone = true;
4290  for (unsigned short plane = 0; plane < nplanes; ++plane)
4291  if (cnt[plane] < 200) allDone = false;
4292  if (allDone) break;
4293  } // iht
4294 
4295  // assume there are enough hits in each plane
4296  evt.aveHitRMSValid = true;
4297  for (unsigned short plane = 0; plane < nplanes; ++plane) {
4298  if (cnt[plane] > 4) { evt.aveHitRMS[plane] /= cnt[plane]; }
4299  else {
4300  evt.aveHitRMS[plane] = 10;
4301  evt.aveHitRMSValid = false;
4302  } // cnt too low
4303  } // plane
4304 
4305  if (tcc.modes[kDebug]) {
4306  std::cout << "Analyze hits aveHitRMS";
4307  std::cout << std::fixed << std::setprecision(1);
4308  for (auto rms : evt.aveHitRMS)
4309  std::cout << " " << rms;
4310  std::cout << " aveHitRMSValid? " << evt.aveHitRMSValid << "\n";
4311  }
4312 
4313  return true;
4314  } // Analyze hits
const geo::WireReadoutGeom * wireReadoutGeom
Definition: DataStructs.h:568
TCConfig tcc
Definition: DataStructs.cxx:9
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
std::vector< float > aveHitRMS
average RMS of an isolated hit
Definition: DataStructs.h:630
Detector simulation of raw signals on wires.
unsigned int Nplanes(TPCID const &tpcid=details::tpc_zero) const
Returns the total number of planes in the specified TPC.
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
bool aveHitRMSValid
set true when the average hit RMS is well-known
Definition: DataStructs.h:639
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
master switch for turning on debug mode
Definition: DataStructs.h:524
bool tca::AnalyzeRotPos ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct ss,
bool  prt 
)

Definition at line 3022 of file TCShower.cxx.

References util::abs(), tca::ShowerStruct::DirectionFOM, tca::ShowerStruct::ID, tca::Trajectory::Pts, tca::ShowerStruct::ShowerTjID, tca::ShowerStruct::ShPts, and tca::TCSlice::tjs.

Referenced by UpdateShower().

3023  {
3024  // The RotPos vector was filled and sorted by increasing distance along the shower axis.
3025  // This function divides the RotPos points into 3 sections and puts the transverse rms width in the
3026  // three sections into the shower Tj TrajPoint DeltaRMS variable. It also calculates the charge and number of shower
3027  // points closest to each TrajPoint. The
3028 
3029  if (ss.ID == 0) return false;
3030  if (ss.ShPts.empty()) return false;
3031  Trajectory& stj = slc.tjs[ss.ShowerTjID - 1];
3032  if (stj.Pts.size() != 3) return false;
3033 
3034  std::string fcnLabel = inFcnLabel + ".ARP";
3035 
3036  for (auto& tp : stj.Pts) {
3037  tp.Chg = 0;
3038  tp.DeltaRMS = 0;
3039  tp.NTPsFit = 0;
3040  tp.HitPos = {{0.0, 0.0}};
3041  }
3042 
3043  float minAlong = ss.ShPts[0].RotPos[0];
3044  float maxAlong = ss.ShPts[ss.ShPts.size() - 1].RotPos[0];
3045  float sectionLength = (maxAlong - minAlong) / 3;
3046  float sec0 = minAlong + sectionLength;
3047  float sec2 = maxAlong - sectionLength;
3048  // iterate over the shower points (aka hits)
3049  for (auto& spt : ss.ShPts) {
3050  // The point on the shower Tj to which the charge will assigned
3051  unsigned short ipt = 0;
3052  if (spt.RotPos[0] < sec0) {
3053  // closest to point 0
3054  ipt = 0;
3055  }
3056  else if (spt.RotPos[0] > sec2) {
3057  // closest to point 2
3058  ipt = 2;
3059  }
3060  else {
3061  // closest to point 1
3062  ipt = 1;
3063  }
3064  stj.Pts[ipt].Chg += spt.Chg;
3065  // Average the absolute value of the transverse position in lieu of
3066  // using the sum of the squares. The result is ~15% higher than the actual
3067  // rms which is OK since this is used to find the transverse size of the shower
3068  // which is not a precisely defined quantity anyway
3069  stj.Pts[ipt].DeltaRMS += spt.Chg * std::abs(spt.RotPos[1]);
3070  ++stj.Pts[ipt].NTPsFit;
3071  // Average the charge center at each point
3072  stj.Pts[ipt].HitPos[0] += spt.Chg * spt.Pos[0];
3073  stj.Pts[ipt].HitPos[1] += spt.Chg * spt.Pos[1];
3074  } // spt
3075 
3076  for (auto& tp : stj.Pts) {
3077  if (tp.Chg > 0) {
3078  tp.DeltaRMS /= tp.Chg;
3079  tp.HitPos[0] /= tp.Chg;
3080  tp.HitPos[1] /= tp.Chg;
3081  }
3082  } // tp
3083 
3084  // require that there is charge in point 0 and 2. Point 1 may not have charge if
3085  // we are constructing a sparse shower that is not yet well-defined
3086  if (stj.Pts[0].Chg == 0 || stj.Pts[2].Chg == 0) return false;
3087 
3088  // ensure that the charge center is defined
3089  if (stj.Pts[1].Chg == 0) {
3090  // do a simple interpolation
3091  stj.Pts[1].HitPos[0] = 0.5 * (stj.Pts[0].HitPos[0] + stj.Pts[2].HitPos[0]);
3092  stj.Pts[1].HitPos[1] = 0.5 * (stj.Pts[0].HitPos[1] + stj.Pts[2].HitPos[1]);
3093  }
3094  if (stj.Pts[2].DeltaRMS > 0) { ss.DirectionFOM = stj.Pts[0].DeltaRMS / stj.Pts[2].DeltaRMS; }
3095  else {
3096  ss.DirectionFOM = 10;
3097  }
3098  if (prt) {
3099  mf::LogVerbatim myprt("TC");
3100  myprt << fcnLabel << " 2S" << ss.ID;
3101  myprt << " HitPos[0] " << std::fixed << std::setprecision(1);
3102  myprt << stj.Pts[1].HitPos[0] << " " << stj.Pts[1].HitPos[1] << " " << stj.Pts[1].HitPos[2];
3103  myprt << " DeltaRMS " << std::setprecision(2);
3104  myprt << stj.Pts[0].DeltaRMS << " " << stj.Pts[1].DeltaRMS << " " << stj.Pts[2].DeltaRMS;
3105  myprt << " DirectionFOM " << std::fixed << std::setprecision(2) << ss.DirectionFOM;
3106  }
3107  return true;
3108 
3109  } // AnalyzeRotPos
constexpr auto abs(T v)
Returns the absolute value of the argument.
unsigned short tca::AngleRange ( TrajPoint const &  tp)

Definition at line 759 of file Utils.cxx.

References tca::TrajPoint::Ang.

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

760  {
761  return AngleRange(tp.Ang);
762  }
unsigned short AngleRange(float angle)
Definition: Utils.cxx:784
unsigned short tca::AngleRange ( float  angle)

Definition at line 784 of file Utils.cxx.

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

785  {
786  // returns the index of the angle range
787  if (angle > M_PI) angle = M_PI;
788  if (angle < -M_PI) angle = M_PI;
789  if (angle < 0) angle = -angle;
790  if (angle > M_PI / 2) angle = M_PI - angle;
791  for (unsigned short ir = 0; ir < tcc.angleRanges.size(); ++ir) {
792  if (angle < tcc.angleRanges[ir]) return ir;
793  }
794  return tcc.angleRanges.size() - 1;
795  } // AngleRange
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< float > angleRanges
list of max angles for each angle range
Definition: DataStructs.h:560
bool tca::AttachAnyTrajToVertex ( TCSlice slc,
unsigned short  ivx,
bool  prt 
)

Definition at line 1678 of file TCVertex.cxx.

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

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

1679  {
1680 
1681  if (ivx > slc.vtxs.size() - 1) return false;
1682  if (slc.vtxs[ivx].ID == 0) return false;
1683  if (tcc.vtx2DCuts[0] < 0) return false;
1684 
1685  VtxStore& vx = slc.vtxs[ivx];
1686  // Hammer vertices should be isolated and clean
1687  if (vx.Topo == 5 || vx.Topo == 6) return false;
1688 
1689  unsigned short bestTj = USHRT_MAX;
1690  // Construct a FOM = (TP-Vtx pull) * (TP-Vtx sep + 1).
1691  // The +1 keeps FOM from being 0
1692  float bestFOM = 2 * tcc.vtx2DCuts[3] * (tcc.vtx2DCuts[0] + 1);
1693  for (unsigned int itj = 0; itj < slc.tjs.size(); ++itj) {
1694  auto& tj = slc.tjs[itj];
1695  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
1696  if (tj.CTP != vx.CTP) continue;
1697  // make some rough cuts
1698  std::array<float, 2> sep;
1699  sep[0] = PosSep(vx.Pos, tj.Pts[tj.EndPt[0]].Pos);
1700  sep[1] = PosSep(vx.Pos, tj.Pts[tj.EndPt[1]].Pos);
1701  unsigned short end = 0;
1702  if (sep[1] < sep[0]) end = 1;
1703  if (sep[end] > 100) continue;
1704  if (tj.VtxID[end] > 0) continue;
1705  auto& tp = tj.Pts[tj.EndPt[end]];
1706  // Pad the separation a bit so we don't get zero
1707  float fom = TrajPointVertexPull(tp, vx) * (sep[end] + 1);
1708  if (fom > bestFOM) continue;
1709  if (prt) {
1710  mf::LogVerbatim("TC") << "AATTV: T" << tj.ID << " 2V" << vx.ID << " Topo " << vx.Topo
1711  << " FOM " << fom << " cut " << bestFOM;
1712  }
1713  bestTj = itj;
1714  bestFOM = fom;
1715  } // tj
1716  if (bestTj > slc.tjs.size() - 1) return false;
1717  auto& tj = slc.tjs[bestTj];
1718  return AttachTrajToVertex(slc, tj, vx, prt);
1719  } // AttachAnyTrajToVertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
bool AttachTrajToVertex(TCSlice &slc, Trajectory &tj, VtxStore &vx, bool prt)
Definition: TCVertex.cxx:1722
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:541
float TrajPointVertexPull(const TrajPoint &tp, const VtxStore &vx)
Definition: TCVertex.cxx:1844
bool tca::AttachAnyVertexToTraj ( TCSlice slc,
int  tjID,
bool  prt 
)

Definition at line 1637 of file TCVertex.cxx.

References AttachTrajToVertex(), util::end(), for(), if(), kKilled, PosSep(), tcc, tca::TCSlice::tjs, TrajPointVertexPull(), tca::TCConfig::vtx2DCuts, and tca::TCSlice::vtxs.

Referenced by MergeAndStore().

1638  {
1639  // Try to attach a tj that is stored in slc.tjs with any vertex
1640  if (tjID <= 0 || tjID > (int)slc.tjs.size()) return false;
1641  if (slc.vtxs.empty()) return false;
1642  auto& tj = slc.tjs[tjID - 1];
1643  if (tj.AlgMod[kKilled]) return false;
1644  if (tcc.vtx2DCuts[0] <= 0) return false;
1645 
1646  unsigned short bestVx = USHRT_MAX;
1647  // Construct a FOM = (TP-Vtx pull) * (TP-Vtx sep + 1) * (Vtx Score).
1648  // The +1 keeps FOM from being 0
1649  float bestFOM = 2 * tcc.vtx2DCuts[3] * (tcc.vtx2DCuts[0] + 1) * tcc.vtx2DCuts[7];
1650  for (unsigned short ivx = 0; ivx < slc.vtxs.size(); ++ivx) {
1651  auto& vx = slc.vtxs[ivx];
1652  if (vx.ID == 0) continue;
1653  if (vx.CTP != tj.CTP) continue;
1654  // make some rough cuts
1655  std::array<float, 2> sep;
1656  sep[0] = PosSep(vx.Pos, tj.Pts[tj.EndPt[0]].Pos);
1657  sep[1] = PosSep(vx.Pos, tj.Pts[tj.EndPt[1]].Pos);
1658  unsigned short end = 0;
1659  if (sep[1] < sep[0]) end = 1;
1660  if (sep[end] > 100) continue;
1661  if (tj.VtxID[end] > 0) continue;
1662  auto& tp = tj.Pts[tj.EndPt[end]];
1663  // Pad the separation a bit so we don't get zero
1664  float fom = TrajPointVertexPull(tp, vx) * (sep[end] + 1) * vx.Score;
1665  if (fom > bestFOM) continue;
1666  if (prt)
1667  mf::LogVerbatim("TC") << "AAVTT: T" << tjID << " 2V" << vx.ID << " FOM " << fom << " cut "
1668  << bestFOM;
1669  bestVx = ivx;
1670  bestFOM = fom;
1671  } // vx
1672  if (bestVx > slc.vtxs.size() - 1) return false;
1673  auto& vx = slc.vtxs[bestVx];
1674  return AttachTrajToVertex(slc, tj, vx, prt);
1675  } // AttachAnyVertexToTraj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
for(Int_t i=0;i< nentries;i++)
Definition: comparison.C:30
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
if(nlines<=0)
bool AttachTrajToVertex(TCSlice &slc, Trajectory &tj, VtxStore &vx, bool prt)
Definition: TCVertex.cxx:1722
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:541
float TrajPointVertexPull(const TrajPoint &tp, const VtxStore &vx)
Definition: TCVertex.cxx:1844
bool tca::AttachToAnyVertex ( TCSlice slc,
PFPStruct pfp,
float  maxSep,
bool  prt 
)

Definition at line 1580 of file TCVertex.cxx.

References util::abs(), dir, DirAtEnd(), DotProd(), util::end(), tca::PFPStruct::ID, Length(), PointDirection(), PosAtEnd(), PosSep(), tca::PFPStruct::TPCID, tca::TCSlice::vtx3s, and tca::PFPStruct::Vx3ID.

Referenced by ReconcileVertices().

1581  {
1582  // Attaches to any 3D vertex but doesn't require consistency with
1583  // PFP -> Tj -> 2V -> 3V assns
1584  if (pfp.ID <= 0) return false;
1585 
1586  float pLen = Length(pfp);
1587  if (pLen == 0) return false;
1588 
1589  // save the old assignents and clear them
1590  // auto oldVx3ID = pfp.Vx3ID;
1591  for (unsigned short end = 0; end < 2; ++end)
1592  pfp.Vx3ID[end] = 0;
1593  std::array<Point3_t, 2> endPos;
1594  endPos[0] = PosAtEnd(pfp, 0);
1595  endPos[1] = PosAtEnd(pfp, 1);
1596 
1597  std::array<float, 2> foms{{100., 100.}};
1598  std::array<int, 2> vtxs{{0}};
1599  for (auto& vx3 : slc.vtx3s) {
1600  if (vx3.ID <= 0) continue;
1601  if (vx3.TPCID != pfp.TPCID) continue;
1602  std::array<float, 2> sep;
1603  Point3_t vpos = {{vx3.X, vx3.Y, vx3.Z}};
1604  sep[0] = PosSep(vpos, endPos[0]);
1605  sep[1] = PosSep(vpos, endPos[1]);
1606  unsigned short end = 0;
1607  if (sep[1] < sep[0]) end = 1;
1608  // ignore if separation is too large
1609  if (sep[end] > 100) continue;
1610  // find the direction vector between these points
1611  auto vpDir = PointDirection(vpos, endPos[end]);
1612  auto dir = DirAtEnd(pfp, end);
1613  double dotp = std::abs(DotProd(vpDir, dir));
1614  float fom = dotp * sep[end];
1615  if (prt)
1616  mf::LogVerbatim("TC") << "ATAV: P" << pfp.ID << " end " << end << " 3V" << vx3.ID << " sep "
1617  << sep[end] << " fom " << fom << " maxSep " << maxSep;
1618  // ignore if separation is too large
1619  if (sep[end] > maxSep) continue;
1620  if (fom < foms[end]) {
1621  foms[end] = fom;
1622  vtxs[end] = vx3.ID;
1623  }
1624  } // vx3
1625  bool bingo = false;
1626  for (unsigned short end = 0; end < 2; ++end) {
1627  if (vtxs[end] == 0) continue;
1628  if (prt)
1629  mf::LogVerbatim("TC") << "ATAV: set P" << pfp.ID << " end " << end << " -> 3V" << vtxs[end];
1630  pfp.Vx3ID[end] = vtxs[end];
1631  bingo = true;
1632  } // end
1633  return bingo;
1634  } // AttachToAnyVertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float Length(const PFPStruct &pfp)
Definition: PFPUtils.cxx:3267
std::array< double, 3 > Point3_t
Definition: DataStructs.h:39
constexpr auto abs(T v)
Returns the absolute value of the argument.
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3257
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:2538
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:126
TDirectory * dir
Definition: macro.C:5
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
Vector3_t DirAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3249
bool tca::AttachTrajToVertex ( TCSlice slc,
Trajectory tj,
VtxStore vx,
bool  prt 
)

Definition at line 1722 of file TCVertex.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::ChgRMS, tca::VtxStore::CTP, tca::Trajectory::CTP, util::end(), tca::Trajectory::EndFlag, tca::Trajectory::EndPt, FitVertex(), tca::VtxStore::ID, tca::Trajectory::ID, kFixed, kHaloTj, kKilled, kNoFitVx, 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::vtx2DCuts, and tca::Trajectory::VtxID.

Referenced by AttachAnyTrajToVertex(), and AttachAnyVertexToTraj().

1723  {
1724  // Note that this function does not require a signal between the end of the Tj and the vertex
1725 
1726  // tcc.vtx2DCuts fcl input usage
1727  // 0 = maximum length of a short trajectory
1728  // 1 = max vertex - trajectory separation for short trajectories
1729  // 2 = max vertex - trajectory separation for long trajectories
1730  // 3 = max position pull for adding TJs to a vertex
1731  // 4 = max allowed vertex position error
1732  // 5 = min MCSMom
1733  // 6 = min Pts/Wire fraction
1734 
1735  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) return false;
1736  if (tj.CTP != vx.CTP) return false;
1737  // already attached?
1738  if (tj.VtxID[0] == vx.ID || tj.VtxID[1] == vx.ID) return false;
1739 
1740  unsigned short maxShortTjLen = tcc.vtx2DCuts[0];
1741  // square the separation cut to simplify testing in the loop
1742  float maxSepCutShort2 = tcc.vtx2DCuts[1] * tcc.vtx2DCuts[1];
1743  float maxSepCutLong2 = tcc.vtx2DCuts[2] * tcc.vtx2DCuts[2];
1744 
1745  // assume that end 0 is closest to the vertex
1746  unsigned short end = 0;
1747  float vtxTjSep2 = PosSep2(vx.Pos, tj.Pts[tj.EndPt[0]].Pos);
1748  float sep1 = PosSep2(vx.Pos, tj.Pts[tj.EndPt[1]].Pos);
1749  if (sep1 < vtxTjSep2) {
1750  // End 1 is closer
1751  end = 1;
1752  vtxTjSep2 = sep1;
1753  }
1754  // is there a vertex already assigned to this end?
1755  if (tj.VtxID[end] > 0) return false;
1756 
1757  // is the trajectory short?
1758  bool tjShort = (tj.EndPt[1] - tj.EndPt[0] < maxShortTjLen);
1759  // use the short Tj cut if the trajectory looks like an electron
1760  if (!tjShort && tj.ChgRMS > 0.5) tjShort = true;
1761  float closestApproach;
1762  // ignore bad separation between the closest tj end and the vertex
1763  if (tjShort) {
1764  if (vtxTjSep2 > maxSepCutShort2) return false;
1765  closestApproach = tcc.vtx2DCuts[1];
1766  }
1767  else {
1768  closestApproach = tcc.vtx2DCuts[2];
1769  if (vtxTjSep2 > maxSepCutLong2) return false;
1770  }
1771 
1772  // Calculate the pull on the vertex
1773  TrajPoint& tp = tj.Pts[tj.EndPt[end]];
1774  float tpVxPull = TrajPointVertexPull(tp, vx);
1775  bool signalBetween = SignalBetween(tp, vx.Pos[0], 0.8);
1776 
1777  // See if the vertex position is close to an end
1778  unsigned short closePt;
1779  TrajClosestApproach(tj, vx.Pos[0], vx.Pos[1], closePt, closestApproach);
1780  // count the number of points between the end of the trajectory and the vertex.
1781  // tj ------------- tj ------------
1782  // vx * >> dpt = 0 vx * >> dpt = 2
1783  short dpt;
1784  if (end == 0) { dpt = closePt - tj.EndPt[end]; }
1785  else {
1786  dpt = tj.EndPt[end] - closePt;
1787  }
1788 
1789  float length = TrajLength(tj);
1790  // don't attach it if the tj length is shorter than the separation distance
1791  if (length > 4 && length < closestApproach) return false;
1792 
1793  float pullCut = tcc.vtx2DCuts[3];
1794  // Dec 21, 2017 Loosen up the pull cut for short close slc. These are likely to
1795  // be poorly reconstructed. It is better to have them associated with the vertex
1796  // than not.
1797  if (tjShort) pullCut *= 2;
1798 
1799  if (prt) {
1800  mf::LogVerbatim myprt("TC");
1801  myprt << "ATTV: 2V" << vx.ID;
1802  myprt << " NTraj " << vx.NTraj;
1803  myprt << " oldTJs";
1804  for (unsigned short itj = 0; itj < slc.tjs.size(); ++itj) {
1805  Trajectory& tj = slc.tjs[itj];
1806  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
1807  if (tj.CTP != vx.CTP) continue;
1808  if (tj.VtxID[0] == vx.ID) myprt << " T" << tj.ID << "_0";
1809  if (tj.VtxID[1] == vx.ID) myprt << " T" << tj.ID << "_1";
1810  }
1811  myprt << " + T" << tj.ID << "_" << end << " vtxTjSep " << sqrt(vtxTjSep2) << " tpVxPull "
1812  << tpVxPull << " pullCut " << pullCut << " dpt " << dpt;
1813  }
1814  if (tpVxPull > pullCut) return false;
1815  if (dpt > 2) return true;
1816 
1817  // remove the fixed position flag if there are more than 2 tjs
1818  bool fixedBit = vx.Stat[kFixed];
1819  if (fixedBit && vx.NTraj < 2) vx.Stat[kFixed] = false;
1820 
1821  // Passed all the cuts. Attach it to the vertex and try a fit
1822  tj.VtxID[end] = vx.ID;
1823  // flag as a photon Tj so it isn't included in the fit
1824  tj.AlgMod[kPhoton] = !signalBetween;
1825  // make a copy of the vertex and fit it
1826  auto vxTmp = vx;
1827  if (FitVertex(slc, vxTmp, prt)) {
1828  SetVx2Score(slc, vxTmp);
1829  if (prt) mf::LogVerbatim("TC") << " Success";
1830  vx = vxTmp;
1831  return true;
1832  }
1833  // Keep the Tj -> Vx assn since we got this far, but don't include this end of the Tj in the fit
1834  tj.EndFlag[end][kNoFitVx] = true;
1835  if (prt)
1836  mf::LogVerbatim("TC") << " Poor fit. Keep T" << tj.ID << "-2V" << vx.ID
1837  << " assn with kNoFitVx";
1838  // restore the fixed flag
1839  vx.Stat[kFixed] = fixedBit;
1840  return true;
1841  } // AttachTrajToVertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
vertex position fixed manually - no fitting done
Definition: DataStructs.h:88
bool TrajClosestApproach(Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
Definition: Utils.cxx:2622
bool FitVertex(TCSlice &slc, VtxStore &vx, std::vector< TrajPoint > &vxTPs, bool prt)
Definition: TCVertex.cxx:1992
bool SignalBetween(const TrajPoint &tp1, const TrajPoint &tp2, const float MinWireSignalFraction)
Definition: Utils.cxx:1779
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2560
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2255
float TrajLength(const Trajectory &tj)
Definition: Utils.cxx:2582
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:541
float TrajPointVertexPull(const TrajPoint &tp, const VtxStore &vx)
Definition: TCVertex.cxx:1844
void tca::Average_dEdX ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
const TCSlice slc,
PFPStruct pfp,
float &  dEdXAve,
float &  dEdXRms 
)

Definition at line 2635 of file PFPUtils.cxx.

References dEdx(), kTP3DBad, kTP3DGood, sum, and tca::PFPStruct::TP3Ds.

Referenced by AddPointsInRange(), DotProd(), and PDGCodeVote().

2641  {
2642  // Return a simple average of dE/dx and rms using ALL points in all planes, not
2643  // just those at the ends ala FilldEdx
2644  dEdXAve = -1.;
2645  dEdXRms = -1.;
2646 
2647  double sum = 0;
2648  double sum2 = 0;
2649  double cnt = 0;
2650  for (auto& tp3d : pfp.TP3Ds) {
2651  if (!tp3d.Flags[kTP3DGood] || tp3d.Flags[kTP3DBad]) continue;
2652  double dedx = dEdx(clockData, detProp, slc, tp3d);
2653  if (dedx < 0.5 || dedx > 80.) continue;
2654  sum += dedx;
2655  sum2 += dedx * dedx;
2656  ++cnt;
2657  } // tp3d
2658  if (cnt < 3) return;
2659  dEdXAve = sum / cnt;
2660  // Use a default rms of 30% of the average
2661  dEdXRms = 0.3 * dEdXAve;
2662  double arg = sum2 - cnt * dEdXAve * dEdXAve;
2663  if (arg < 0) return;
2664  dEdXRms = sqrt(arg) / (cnt - 1);
2665  // don't return a too-small rms
2666  double minRms = 0.05 * dEdXAve;
2667  if (dEdXRms < minRms) dEdXRms = minRms;
2668  } // Average_dEdX
float dEdx(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, TP3D &tp3d)
Definition: PFPUtils.cxx:2671
Double_t sum
Definition: plot.C:31
bool tca::BraggSplit ( TCSlice slc,
unsigned short  itj 
)

Definition at line 1423 of file Utils.cxx.

References util::abs(), tca::TrajPoint::Ang, tca::VtxStore::ChiDOF, tca::ParFit::ChiDOF, tca::TCConfig::chkStopCuts, tca::VtxStore::CTP, tca::TCConfig::dbgAlg, tca::TCConfig::dbgSlc, tca::TCConfig::dbgStp, tca::TrajPoint::FitChi, FitPar(), FitTraj(), tca::VtxStore::ID, kBragg, kBraggSplit, kFixed, tca::TCConfig::kinkCuts, MakeVertexObsolete(), tca::VtxStore::NTraj, NumPtsWithCharge(), tca::ParFit::Par0, tca::ParFit::ParSlp, 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().

1424  {
1425  // Searches the stored trajectory for a Bragg Peak and kink and splits it
1426  if (!tcc.useAlg[kBraggSplit]) return false;
1427  if (itj > slc.tjs.size() - 1) return false;
1428  if (tcc.chkStopCuts.size() < 4) return false;
1429  if (tcc.chkStopCuts[3] <= 0) return false;
1430  unsigned short nPtsToCheck = tcc.chkStopCuts[1];
1431  auto& tj = slc.tjs[itj];
1432  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
1433  if (npwc < 4) return false;
1434  if (npwc < nPtsToCheck) nPtsToCheck = npwc;
1435  // do a rough ChgPull check first
1436  float maxPull = 2;
1437  unsigned short maxPullPt = USHRT_MAX;
1438  for (unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1]; ++ipt) {
1439  auto& tp = tj.Pts[ipt];
1440  if (tp.ChgPull < maxPull) continue;
1441  maxPull = tp.ChgPull;
1442  maxPullPt = ipt;
1443  } // ipt
1444  if (maxPullPt == USHRT_MAX) return false;
1445  short dpt;
1446  if (maxPullPt < 0.5 * (tj.EndPt[0] + tj.EndPt[1])) { dpt = maxPullPt - tj.EndPt[0]; }
1447  else {
1448  dpt = tj.EndPt[1] - maxPullPt;
1449  }
1450  if (dpt < 3) return false;
1451  bool prt = (tcc.dbgSlc && (tcc.dbgStp || tcc.dbgAlg[kBraggSplit]));
1452  if (prt)
1453  mf::LogVerbatim("TC") << "BS: T" << tj.ID << " maxPull " << maxPull << " at "
1454  << PrintPos(tj.Pts[maxPullPt]) << " dpt " << dpt;
1455  unsigned short breakPt = USHRT_MAX;
1456  float bestFOM = tcc.chkStopCuts[3];
1457  unsigned short bestBragg = 0;
1458  unsigned short nPtsFit = tcc.kinkCuts[0];
1459  TrajPoint tp1, tp2;
1460  ParFit chgFit1, chgFit2;
1461  for (unsigned short ipt = maxPullPt - 2; ipt <= maxPullPt + 2; ++ipt) {
1462  FitTraj(slc, tj, ipt - 1, nPtsFit, -1, tp1);
1463  if (tp1.FitChi > 10) continue;
1464  FitTraj(slc, tj, ipt + 1, nPtsFit, 1, tp2);
1465  if (tp2.FitChi > 10) continue;
1466  float dang = std::abs(tp1.Ang - tp2.Ang);
1467  FitPar(tj, ipt - 1, nPtsToCheck, -1, chgFit1, 1);
1468  if (chgFit1.ChiDOF > 100) continue;
1469  chgFit1.ParSlp = -chgFit1.ParSlp;
1470  FitPar(tj, ipt + 1, nPtsToCheck, 1, chgFit2, 1);
1471  if (chgFit2.ChiDOF > 100) continue;
1472  chgFit2.ParSlp = -chgFit2.ParSlp;
1473  // require a large positive slope on at least one side
1474  if (chgFit1.ParSlp < tcc.chkStopCuts[0] && chgFit2.ParSlp < tcc.chkStopCuts[0]) continue;
1475  // assume it is on side 1
1476  unsigned short bragg = 1;
1477  float bchi = chgFit1.ChiDOF;
1478  if (chgFit2.ParSlp > chgFit1.ParSlp) {
1479  bragg = 2;
1480  bchi = chgFit2.ChiDOF;
1481  }
1482  float chgAsym = std::abs(chgFit1.Par0 - chgFit2.Par0) / (chgFit1.Par0 + chgFit2.Par0);
1483  float slpAsym = std::abs(chgFit1.ParSlp - chgFit2.ParSlp) / (chgFit1.ParSlp + chgFit2.ParSlp);
1484  if (bchi < 1) bchi = 1;
1485  float fom = 10 * dang * chgAsym * slpAsym / bchi;
1486  if (prt) {
1487  mf::LogVerbatim myprt("TC");
1488  myprt << "pt " << PrintPos(tj.Pts[ipt]) << " " << std::setprecision(2) << dang;
1489  myprt << " chg1 " << (int)chgFit1.Par0 << " slp " << chgFit1.ParSlp << " chi "
1490  << chgFit1.ChiDOF;
1491  myprt << " chg2 " << (int)chgFit2.Par0 << " slp " << chgFit2.ParSlp << " chi "
1492  << chgFit2.ChiDOF;
1493  myprt << " chgAsym " << chgAsym;
1494  myprt << " slpAsym " << slpAsym;
1495  myprt << " fom " << fom;
1496  myprt << " bragg " << bragg;
1497  }
1498  if (fom < bestFOM) continue;
1499  bestFOM = fom;
1500  breakPt = ipt;
1501  bestBragg = bragg;
1502  } // ipt
1503  if (breakPt == USHRT_MAX) return false;
1504  if (prt)
1505  mf::LogVerbatim("TC") << " breakPt " << PrintPos(tj.Pts[breakPt]) << " bragg " << bestBragg;
1506  // Create a vertex at the break point
1507  VtxStore aVtx;
1508  aVtx.Pos = tj.Pts[breakPt].Pos;
1509  aVtx.NTraj = 2;
1510  aVtx.Pass = tj.Pass;
1511  aVtx.Topo = 12;
1512  aVtx.ChiDOF = 0;
1513  aVtx.CTP = tj.CTP;
1514  aVtx.ID = slc.vtxs.size() + 1;
1515  aVtx.Stat[kFixed] = true;
1516  unsigned short ivx = slc.vtxs.size();
1517  if (!StoreVertex(slc, aVtx)) return false;
1518  if (!SplitTraj(slc, itj, breakPt, ivx, prt)) {
1519  if (prt) mf::LogVerbatim("TC") << "BS: Failed to split trajectory";
1520  MakeVertexObsolete("BS", slc, slc.vtxs[ivx], false);
1521  return false;
1522  }
1523  SetVx2Score(slc);
1524  slc.tjs[itj].AlgMod[kBraggSplit] = true;
1525  unsigned short otj = slc.tjs.size() - 1;
1526  if (bestBragg == 2) std::swap(itj, otj);
1527  slc.tjs[itj].PDGCode = 211;
1528  slc.tjs[itj].EndFlag[1][kBragg] = true;
1529  slc.tjs[otj].PDGCode = 13;
1530  return true;
1531  } // BraggSplit
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:2698
std::vector< float > kinkCuts
kink finder algorithm
Definition: DataStructs.h:550
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:2080
TCConfig tcc
Definition: DataStructs.cxx:9
vertex position fixed manually - no fitting done
Definition: DataStructs.h:88
constexpr auto abs(T v)
Returns the absolute value of the argument.
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:1908
std::string PrintPos(const Point2_t &pos)
Definition: Utils.cxx:6362
void FitPar(const Trajectory &tj, unsigned short originPt, unsigned short npts, short fitDir, ParFit &pFit, unsigned short usePar)
Definition: Utils.cxx:1202
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
bool SplitTraj(TCSlice &slc, unsigned short itj, unsigned short pos, unsigned short ivx, bool prt)
Definition: Utils.cxx:2269
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:579
std::vector< float > chkStopCuts
Bragg peak finder configuration.
Definition: DataStructs.h:548
void swap(lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &a, lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &b)
void SetVx2Score(TCSlice &slc)
Definition: TCVertex.cxx:2246
void FitTraj(TCSlice const &slc, Trajectory &tj, unsigned short originPt, unsigned short npts, short fitDir, TrajPoint &tpFit)
Definition: Utils.cxx:811
bool tca::CanSection ( const TCSlice slc,
const PFPStruct pfp 
)

Definition at line 1323 of file PFPUtils.cxx.

References tca::PFPStruct::AlgMod, Find3DRecoRange(), kJunk3D, kSmallAngle, and tca::PFPStruct::TP3Ds.

Referenced by MakePFParticles(), and Recover().

1324  {
1325  // analyze the TP3D vector to determine if it can be reconstructed in 3D in more than one section with
1326  // the requirement that there are at least 3 points in two planes
1327  if (pfp.AlgMod[kJunk3D]) return false;
1328  if (pfp.AlgMod[kSmallAngle]) return false;
1329  if (pfp.TP3Ds.size() < 12) return false;
1330  unsigned short toPt = Find3DRecoRange(slc, pfp, 0, 3, 1);
1331  if (toPt > pfp.TP3Ds.size()) return false;
1332  unsigned short nextToPt = Find3DRecoRange(slc, pfp, toPt, 3, 1);
1333  if (nextToPt > pfp.TP3Ds.size()) return false;
1334  return true;
1335  } // CanSection
unsigned short Find3DRecoRange(const TCSlice &slc, const PFPStruct &pfp, unsigned short fromPt, unsigned short min2DPts, short dir)
Definition: PFPUtils.cxx:1338
void tca::CheckHiMultEndHits ( TCSlice slc,
Trajectory tj 
)

Definition at line 2500 of file StepUtils.cxx.

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

Referenced by CheckTraj().

2501  {
2502  // mask off high multiplicity TPs at the end
2503  if (!tcc.useAlg[kCHMEH]) return;
2504  if (tj.EndFlag[1][kBragg]) return;
2505  if (tj.Pts.size() < 10) return;
2506  if (tj.Pts[tj.EndPt[1]].AngleCode == 0) return;
2507  // find the average multiplicity in the first half
2508  unsigned short aveMult = 0;
2509  unsigned short ipt, nhalf = tj.Pts.size() / 2;
2510  unsigned short cnt = 0;
2511  for (auto& tp : tj.Pts) {
2512  if (tp.Chg == 0) continue;
2513  aveMult += tp.Hits.size();
2514  ++cnt;
2515  if (cnt == nhalf) break;
2516  } // pt
2517  if (cnt == 0) return;
2518  aveMult /= cnt;
2519  if (aveMult == 0) aveMult = 1;
2520  // convert this into a cut
2521  aveMult *= 3;
2522  cnt = 0;
2523  for (ipt = tj.EndPt[1]; ipt > tj.EndPt[0]; --ipt) {
2524  if (tj.Pts[ipt].Chg == 0) continue;
2525  if (tj.Pts[ipt].Hits.size() > aveMult) {
2526  UnsetUsedHits(slc, tj.Pts[ipt]);
2527  ++cnt;
2528  continue;
2529  }
2530  break;
2531  } // ipt
2532  if (tcc.dbgStp)
2533  mf::LogVerbatim("TC") << "CHMEH multiplicity cut " << aveMult << " number of TPs masked off "
2534  << cnt;
2535  if (cnt > 0) {
2536  tj.AlgMod[kCHMEH] = true;
2537  SetEndPoints(tj);
2538  }
2539  } // CheckHiMultEndHits
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1061
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
void tca::CheckHiMultUnusedHits ( TCSlice slc,
Trajectory tj 
)

Definition at line 2344 of file StepUtils.cxx.

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

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

Definition at line 983 of file StepUtils.cxx.

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

Referenced by CheckTraj().

984  {
985  if (!tj.Strategy[kStiffEl]) return;
986  if (tcc.dbgStp) {
987  mf::LogVerbatim("TC") << "inside CheckStiffTj with NumPtsWithCharge = "
988  << NumPtsWithCharge(slc, tj, false);
989  }
990  // Fill in any gaps with hits that were skipped, most likely delta rays on muon tracks
991  FillGaps(slc, tj);
992  // Update the trajectory parameters at the beginning of the trajectory
993  ChkBegin(slc, tj);
994  } // CheckStiffTj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
void FillGaps(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2204
void ChkBegin(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2882
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
use the stiff electron strategy
Definition: DataStructs.h:492
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
void tca::CheckTraj ( TCSlice slc,
Trajectory tj 
)

Definition at line 997 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, CheckHiMultEndHits(), CheckStiffEl(), ChkBegin(), ChkChgAsymmetry(), ChkStop(), ChkStopEndPts(), tca::TCConfig::dbgStp, tca::Trajectory::EndPt, FillGaps(), HasDuplicateHits(), IsGhost(), tca::Trajectory::IsGood, tca::TCSlice::isValid, kJunkTj, kKilled, kSlowing, kStiffEl, tca::Trajectory::MCSMom, MCSMom(), tca::TCConfig::minMCSMom, tca::TCConfig::minPts, NumPtsWithCharge(), tca::Trajectory::Pass, tca::Trajectory::Pts, tca::TCConfig::qualityCuts, SetEndPoints(), tca::Trajectory::Strategy, TagJunkTj(), tcc, TrimEndPts(), and TrimHiChgEndPts().

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

998  {
999  // Check the quality of the trajectory and possibly trim it or flag it for deletion
1000 
1001  if (!tj.IsGood) return;
1002 
1003  // ensure that the end points are defined
1004  SetEndPoints(tj);
1005  if (tj.EndPt[0] == tj.EndPt[1]) return;
1006 
1007  if (tj.Strategy[kStiffEl]) {
1008  CheckStiffEl(slc, tj);
1009  return;
1010  }
1011 
1012  if (tcc.dbgStp) {
1013  mf::LogVerbatim("TC") << "inside CheckTraj with NumPtsWithCharge = "
1014  << NumPtsWithCharge(slc, tj, false);
1015  }
1016 
1017  if (NumPtsWithCharge(slc, tj, false) < tcc.minPts[tj.Pass]) {
1018  tj.IsGood = false;
1019  return;
1020  }
1021 
1022  // reduce nPtsFit to the minimum and check for a large angle kink near the ends
1023  // ChkEndKink(slc, tj, tcc.dbgStp);
1024 
1025  // Look for a charge asymmetry between points on both sides of a high-
1026  // charge point and trim points in the vicinity
1027  ChkChgAsymmetry(slc, tj, tcc.dbgStp);
1028 
1029  // flag this tj as a junk Tj (even though it wasn't created in FindJunkTraj).
1030  // Drop it and let FindJunkTraj do it's job
1031  TagJunkTj(tj, tcc.dbgStp);
1032  if (tj.AlgMod[kJunkTj]) {
1033  tj.IsGood = false;
1034  return;
1035  }
1036 
1037  tj.MCSMom = MCSMom(slc, tj);
1038 
1039  // See if the points at the stopping end can be included in the Tj
1040  ChkStopEndPts(slc, tj, tcc.dbgStp);
1041 
1042  // remove any points at the end that don't have charge
1043  tj.Pts.resize(tj.EndPt[1] + 1);
1044 
1045  // Ensure that a hit only appears once in the TJ
1046  if (HasDuplicateHits(slc, tj, tcc.dbgStp)) {
1047  if (tcc.dbgStp) mf::LogVerbatim("TC") << " HasDuplicateHits ";
1048  tj.IsGood = false;
1049  return;
1050  }
1051 
1052  // See if this is a ghost trajectory
1053  if (IsGhost(slc, tj)) {
1054  if (tcc.dbgStp) mf::LogVerbatim("TC") << " CT: Ghost trajectory - trimmed hits ";
1055  if (!tj.IsGood) return;
1056  }
1057 
1058  if (tj.AlgMod[kJunkTj]) return;
1059 
1060  // checks are different for Very Large Angle trajectories
1061  bool isVLA = (tj.Pts[tj.EndPt[1]].AngleCode == 2);
1062 
1063  tj.Pts.resize(tj.EndPt[1] + 1);
1064 
1065  // Fill in any gaps with hits that were skipped, most likely delta rays on muon tracks
1066  if (!isVLA) FillGaps(slc, tj);
1067 
1068  if (tcc.dbgStp)
1069  mf::LogVerbatim("TC") << " CheckTraj MCSMom " << tj.MCSMom << " isVLA? " << isVLA
1070  << " NumPtsWithCharge " << NumPtsWithCharge(slc, tj, false)
1071  << " Min Req'd " << tcc.minPts[tj.Pass];
1072 
1073  // Trim the end points until the TJ meets the quality cuts
1074  TrimEndPts("CT", slc, tj, tcc.qualityCuts, tcc.dbgStp);
1075  if (tj.AlgMod[kKilled]) {
1076  tj.IsGood = false;
1077  return;
1078  }
1079 
1080  TrimHiChgEndPts(slc, tj, tcc.dbgStp);
1081 
1082  // Check for a Bragg peak at both ends. This may be used by FixBegin.
1083  ChkStop(tj);
1084 
1085  // Update the trajectory parameters at the beginning of the trajectory
1086  ChkBegin(slc, tj);
1087 
1088  // ignore short trajectories
1089  if (tj.EndPt[1] < 4) return;
1090 
1091  // final quality check
1092  float npwc = NumPtsWithCharge(slc, tj, true);
1093  float npts = tj.EndPt[1] - tj.EndPt[0] + 1;
1094  float frac = npwc / npts;
1095  tj.IsGood = (frac >= tcc.qualityCuts[0]);
1096  if (tj.IsGood && tj.Pass < tcc.minMCSMom.size() && !tj.Strategy[kSlowing])
1097  tj.IsGood = (tj.MCSMom >= tcc.minMCSMom[tj.Pass]);
1098  if (tcc.dbgStp) {
1099  mf::LogVerbatim("TC") << "CheckTraj: fraction of points with charge " << frac
1100  << " good traj? " << tj.IsGood;
1101  }
1102  if (!tj.IsGood || !slc.isValid) return;
1103 
1104  // lop off high multiplicity hits at the end
1105  CheckHiMultEndHits(slc, tj);
1106 
1107  // Check for a Bragg peak at both ends. This may be used by FixBegin.
1108  ChkStop(tj);
1109 
1110  } // CheckTraj
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3381
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void ChkStop(Trajectory &tj)
Definition: StepUtils.cxx:3972
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
std::vector< float > qualityCuts
Min points/wire, min consecutive pts after a gap.
Definition: DataStructs.h:554
TCConfig tcc
Definition: DataStructs.cxx:9
void FillGaps(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2204
void ChkBegin(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2882
bool IsGhost(TCSlice &slc, std::vector< unsigned int > &tHits)
Definition: StepUtils.cxx:3257
void ChkChgAsymmetry(TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:1714
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
use the slowing-down strategy
Definition: DataStructs.h:494
std::vector< short > minMCSMom
Min MCSMom for each pass.
Definition: DataStructs.h:559
void CheckStiffEl(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:983
std::vector< unsigned short > minPts
min number of Pts required to make a trajectory
Definition: DataStructs.h:557
void TrimEndPts(std::string fcnLabel, TCSlice &slc, Trajectory &tj, const std::vector< float > &fQualityCuts, bool prt)
Definition: Utils.cxx:1576
void TagJunkTj(Trajectory &tj, bool prt)
Definition: Utils.cxx:2716
void TrimHiChgEndPts(TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:1534
use the stiff electron strategy
Definition: DataStructs.h:492
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
void ChkStopEndPts(TCSlice &slc, Trajectory &tj, bool prt)
Definition: StepUtils.cxx:1671
void CheckHiMultEndHits(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2500
bool HasDuplicateHits(const TCSlice &slc, Trajectory const &tj, bool prt)
Definition: Utils.cxx:2745
void tca::CheckTrajBeginChg ( TCSlice slc,
unsigned short  itj 
)

Definition at line 1317 of file Utils.cxx.

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

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

1318  {
1319  // This function is called after the beginning of the tj has been inspected to see if
1320  // reverse propagation was warranted. Trajectory points at the beginning were removed by
1321  // this process.
1322  // A search has been made for a Bragg peak with nothing
1323  // found. Here we look for a charge pattern like the following, where C means large charge
1324  // and c means lower charge:
1325  // CCCCCCccccccc
1326  // The charge in the two regions should be fairly uniform.
1327 
1328  // This function may split the trajectory so it needs to have been stored
1329  if (itj > slc.tjs.size() - 1) return;
1330  auto& tj = slc.tjs[itj];
1331 
1332  if (!tcc.useAlg[kBeginChg]) return;
1333  if (tj.EndFlag[0][kBragg]) return;
1334  if (tj.AlgMod[kFTBRvProp]) return;
1335  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) return;
1336  if (tj.Pts.size() < 20) return;
1337 
1338  bool prt = (tcc.dbgSlc && (tcc.dbgStp || tcc.dbgAlg[kBeginChg]));
1339 
1340  // look for a large drop between the average charge near the beginning
1341  float chg2 = tj.Pts[tj.EndPt[0] + 2].AveChg;
1342  // and the average charge 15 points away
1343  float chg15 = tj.Pts[tj.EndPt[0] + 15].AveChg;
1344  if (chg2 < 3 * chg15) return;
1345 
1346  // find the point where the charge falls below the mid-point
1347  float midChg = 0.5 * (chg2 + chg15);
1348 
1349  unsigned short breakPt = USHRT_MAX;
1350  for (unsigned short ipt = tj.EndPt[0] + 3; ipt < 15; ++ipt) {
1351  float chgm2 = tj.Pts[ipt - 2].Chg;
1352  if (chgm2 == 0) continue;
1353  float chgm1 = tj.Pts[ipt - 1].Chg;
1354  if (chgm1 == 0) continue;
1355  float chgp1 = tj.Pts[ipt + 1].Chg;
1356  if (chgp1 == 0) continue;
1357  float chgp2 = tj.Pts[ipt + 2].Chg;
1358  if (chgp2 == 0) continue;
1359  if (chgm2 > midChg && chgm1 > midChg && chgp1 < midChg && chgp2 < midChg) {
1360  breakPt = ipt;
1361  break;
1362  }
1363  } // breakPt
1364  if (breakPt == USHRT_MAX) return;
1365  // check the charge and rms before and after the split
1366  std::array<double, 2> cnt, sum, sum2;
1367  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1368  auto& tp = tj.Pts[ipt];
1369  if (tp.Chg <= 0) continue;
1370  unsigned short end = 0;
1371  if (ipt > breakPt) end = 1;
1372  ++cnt[end];
1373  sum[end] += tp.Chg;
1374  sum2[end] += tp.Chg * tp.Chg;
1375  } // ipt
1376  for (unsigned short end = 0; end < 2; ++end) {
1377  if (cnt[end] < 3) return;
1378  double ave = sum[end] / cnt[end];
1379  double arg = sum2[end] - cnt[end] * ave * ave;
1380  if (arg <= 0) return;
1381  sum2[end] = sqrt(arg / (cnt[end] - 1));
1382  sum2[end] /= ave;
1383  sum[end] = ave;
1384  } // region
1385  bool doSplit = true;
1386  // don't split if this looks like an electron - no significant improvement
1387  // in the charge rms before and after
1388  if (tj.ChgRMS > 0.5 && sum2[0] > 0.3 && sum2[1] > 0.3) doSplit = false;
1389  if (prt) {
1390  mf::LogVerbatim myprt("TC");
1391  myprt << "CTBC: T" << tj.ID << " chgRMS " << tj.ChgRMS;
1392  myprt << " AveChg before split point " << (int)sum[0] << " rms " << sum2[0];
1393  myprt << " after " << (int)sum[1] << " rms " << sum2[1] << " doSplit? " << doSplit;
1394  } // prt
1395  if (!doSplit) return;
1396  // Create a vertex at the break point
1397  VtxStore aVtx;
1398  aVtx.Pos = tj.Pts[breakPt].Pos;
1399  aVtx.NTraj = 2;
1400  aVtx.Pass = tj.Pass;
1401  aVtx.Topo = 8;
1402  aVtx.ChiDOF = 0;
1403  aVtx.CTP = tj.CTP;
1404  aVtx.ID = slc.vtxs.size() + 1;
1405  aVtx.Stat[kFixed] = true;
1406  unsigned short ivx = slc.vtxs.size();
1407  if (!StoreVertex(slc, aVtx)) return;
1408  if (!SplitTraj(slc, itj, breakPt, ivx, prt)) {
1409  if (prt) mf::LogVerbatim("TC") << "CTBC: Failed to split trajectory";
1410  MakeVertexObsolete("CTBC", slc, slc.vtxs[ivx], false);
1411  return;
1412  }
1413  SetVx2Score(slc);
1414  slc.tjs[itj].AlgMod[kBeginChg] = true;
1415 
1416  if (prt)
1417  mf::LogVerbatim("TC") << "CTBC: Split T" << tj.ID << " at " << PrintPos(tj.Pts[breakPt].Pos)
1418  << "\n";
1419 
1420  } // CheckTrajBeginChg
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:2698
TCConfig tcc
Definition: DataStructs.cxx:9
vertex position fixed manually - no fitting done
Definition: DataStructs.h:88
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:1908
std::string PrintPos(const Point2_t &pos)
Definition: Utils.cxx:6362
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
bool SplitTraj(TCSlice &slc, unsigned short itj, unsigned short pos, unsigned short ivx, bool prt)
Definition: Utils.cxx:2269
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:579
void SetVx2Score(TCSlice &slc)
Definition: TCVertex.cxx:2246
Double_t sum
Definition: plot.C:31
float tca::ChgFracBetween ( TrajPoint  tp,
float  toPos0 
)

Definition at line 1808 of file Utils.cxx.

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

1809  {
1810  // Returns the fraction of wires between tp.Pos[0] and toPos0 that have a hit
1811  // on the line defined by tp.Pos and tp.Dir
1812 
1813  if (tp.Pos[0] < -0.4 || toPos0 < -0.4) return 0;
1814  int fromWire = std::nearbyint(tp.Pos[0]);
1815  int toWire = std::nearbyint(toPos0);
1816 
1817  if (fromWire == toWire) return SignalAtTp(tp);
1818 
1819  int nWires = abs(toWire - fromWire) + 1;
1820 
1821  if (std::abs(tp.Dir[0]) < 0.001) tp.Dir[0] = 0.001;
1822  float stepSize = std::abs(1 / tp.Dir[0]);
1823  // ensure that we step in the right direction
1824  if (toWire > fromWire && tp.Dir[0] < 0) stepSize = -stepSize;
1825  if (toWire < fromWire && tp.Dir[0] > 0) stepSize = -stepSize;
1826  float nsig = 0;
1827  float num = 0;
1828  for (unsigned short cnt = 0; cnt < nWires; ++cnt) {
1829  ++num;
1830  if (SignalAtTp(tp)) ++nsig;
1831  tp.Pos[0] += tp.Dir[0] * stepSize;
1832  tp.Pos[1] += tp.Dir[1] * stepSize;
1833  } // cnt
1834  float sigFrac = nsig / num;
1835  return sigFrac;
1836  } // ChgFracBetween
bool SignalAtTp(TrajPoint &tp)
Definition: Utils.cxx:1964
constexpr auto abs(T v)
Returns the absolute value of the argument.
float tca::ChgFracBetween ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice slc,
Point3_t  pos1,
Point3_t  pos2 
)

Definition at line 3163 of file PFPUtils.cxx.

References detinfo::DetectorPropertiesData::ConvertXToTicks(), geo::CryostatID::Cryostat, tca::TrajPoint::CTP, dir, EncodeCTP(), for(), tca::TCSlice::nPlanes, geo::WireReadoutGeom::Plane(), PointDirection(), tca::TrajPoint::Pos, PosSep(), SignalAtTp(), sum, tcc, geo::TPCID::TPC, tca::TCSlice::TPCID, tca::TCConfig::unitsPerTick, geo::PlaneGeo::WireCoordinate(), tca::TCConfig::wirePitch, and tca::TCConfig::wireReadoutGeom.

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

3167  {
3168  // Step between pos1 and pos2 and find the fraction of the points that have nearby hits
3169  // in each plane. This function returns -1 if something is fishy, but this doesn't mean
3170  // that there is no charge. Note that there is no check for charge precisely at the pos1 and pos2
3171  // positions
3172  float sep = PosSep(pos1, pos2);
3173  if (sep == 0) return -1;
3174  unsigned short nstep = sep / tcc.wirePitch;
3175  auto dir = PointDirection(pos1, pos2);
3176  float sum = 0;
3177  float cnt = 0;
3178  TrajPoint tp;
3179  for (unsigned short step = 0; step < nstep; ++step) {
3180  for (unsigned short xyz = 0; xyz < 3; ++xyz)
3181  pos1[xyz] += tcc.wirePitch * dir[xyz];
3182  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
3183  tp.CTP = EncodeCTP(slc.TPCID.Cryostat, slc.TPCID.TPC, plane);
3184  geo::PlaneID const planeID{slc.TPCID, plane};
3185  tp.Pos[0] =
3186  tcc.wireReadoutGeom->Plane(planeID).WireCoordinate(geo::Point_t{0, pos1[1], pos1[2]});
3187  tp.Pos[1] = detProp.ConvertXToTicks(pos1[0], planeID) * tcc.unitsPerTick;
3188  ++cnt;
3189  if (SignalAtTp(tp)) ++sum;
3190  } // plane
3191  } // step
3192  if (cnt == 0) return -1;
3193  return sum / cnt;
3194  } // ChgFracBetween
const geo::WireReadoutGeom * wireReadoutGeom
Definition: DataStructs.h:568
bool SignalAtTp(TrajPoint &tp)
Definition: Utils.cxx:1964
double WireCoordinate(Point_t const &point) const
Returns the coordinate of the point on the plane, in wire units.
Definition: PlaneGeo.h:704
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
for(Int_t i=0;i< nentries;i++)
Definition: comparison.C:30
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:2538
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:180
TDirectory * dir
Definition: macro.C:5
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:49
PlaneGeo const & Plane(TPCID const &tpcid, View_t view) const
Returns the specified wire.
Double_t sum
Definition: plot.C:31
constexpr TPCID()=default
Default constructor: an invalid TPC ID.
float tca::ChgFracNearEnd ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice slc,
const PFPStruct pfp,
unsigned short  end 
)

Definition at line 3197 of file PFPUtils.cxx.

References ChgFracNearPos(), detinfo::DetectorPropertiesData::ConvertXToTicks(), geo::CryostatID::Cryostat, EncodeCTP(), tca::PFPStruct::ID, tca::TCSlice::nPlanes, tca::TCSlice::nWires, geo::WireReadoutGeom::Plane(), PosAtEnd(), tca::PFPStruct::SectionFits, sum, tcc, tca::PFPStruct::TjIDs, tca::TCSlice::tjs, geo::TPCID::TPC, tca::PFPStruct::TPCID, tca::TCSlice::TPCID, tca::TCConfig::unitsPerTick, geo::PlaneGeo::WireCoordinate(), tca::TCSlice::wireHitRange, and tca::TCConfig::wireReadoutGeom.

Referenced by DotProd().

3201  {
3202  // returns the charge fraction near the end of the pfp. Note that this function
3203  // assumes that there is only one Tj in a plane.
3204  if (pfp.ID == 0) return 0;
3205  if (pfp.TjIDs.empty()) return 0;
3206  if (end > 1) return 0;
3207  if (pfp.TPCID != slc.TPCID) return 0;
3208  if (pfp.SectionFits.empty()) return 0;
3209 
3210  float sum = 0;
3211  float cnt = 0;
3212  // keep track of the lowest value and maybe reject it
3213  float lo = 1;
3214  float hi = 0;
3215  auto pos3 = PosAtEnd(pfp, end);
3216  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
3217  CTP_t inCTP = EncodeCTP(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
3218  std::vector<int> tjids(1);
3219  for (auto tjid : pfp.TjIDs) {
3220  auto& tj = slc.tjs[tjid - 1];
3221  if (tj.CTP != inCTP) continue;
3222  tjids[0] = tjid;
3223  Point2_t pos2;
3224  geo::PlaneID planeID = geo::PlaneID{pfp.TPCID, plane};
3225  pos2[0] =
3226  tcc.wireReadoutGeom->Plane(planeID).WireCoordinate(geo::Point_t{0, pos3[1], pos3[2]});
3227  if (pos2[0] < -0.4) continue;
3228  // check for dead wires
3229  unsigned int wire = std::nearbyint(pos2[0]);
3230  if (wire > slc.nWires[plane]) continue;
3231  if (slc.wireHitRange[plane][wire].first == UINT_MAX) continue;
3232  pos2[1] = detProp.ConvertXToTicks(pos3[0], planeID) * tcc.unitsPerTick;
3233  float cf = ChgFracNearPos(slc, pos2, tjids);
3234  if (cf < lo) lo = cf;
3235  if (cf > hi) hi = cf;
3236  sum += cf;
3237  ++cnt;
3238  } // tjid
3239  } // plane
3240  if (cnt == 0) return 0;
3241  if (cnt > 1 && lo < 0.3 && hi > 0.8) {
3242  sum -= lo;
3243  --cnt;
3244  }
3245  return sum / cnt;
3246  } // ChgFracNearEnd
const geo::WireReadoutGeom * wireReadoutGeom
Definition: DataStructs.h:568
double WireCoordinate(Point_t const &point) const
Returns the coordinate of the point on the plane, in wire units.
Definition: PlaneGeo.h:704
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3257
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
std::array< float, 2 > Point2_t
Definition: DataStructs.h:41
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
float ChgFracNearPos(const TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3163
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:180
unsigned int CTP_t
Definition: DataStructs.h:45
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:49
PlaneGeo const & Plane(TPCID const &tpcid, View_t view) const
Returns the specified wire.
Double_t sum
Definition: plot.C:31
constexpr TPCID()=default
Default constructor: an invalid TPC ID.
float tca::ChgFracNearPos ( const TCSlice slc,
const Point2_t pos,
const std::vector< int > &  tjIDs 
)

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

3164  {
3165  // returns the fraction of the charge in the region around pos that is associated with
3166  // the list of Tj IDs
3167  if (tjIDs.empty()) return 0;
3168  std::array<int, 2> wireWindow;
3169  Point2_t timeWindow;
3170  // 1/2 size of the region
3171  constexpr float NNDelta = 5;
3172  wireWindow[0] = pos[0] - NNDelta;
3173  wireWindow[1] = pos[0] + NNDelta;
3174  timeWindow[0] = pos[1] - NNDelta;
3175  timeWindow[1] = pos[1] + NNDelta;
3176  // do some checking
3177  for (auto& tjID : tjIDs)
3178  if (tjID <= 0 || tjID > (int)slc.tjs.size()) return 0;
3179  // Determine which plane we are in
3180  geo::PlaneID planeID = DecodeCTP(slc.tjs[tjIDs[0] - 1].CTP);
3181  // get a list of all hits in this region
3182  bool hitsNear;
3183  std::vector<unsigned int> closeHits =
3184  FindCloseHits(slc, wireWindow, timeWindow, planeID.Plane, kAllHits, true, hitsNear);
3185  if (closeHits.empty()) return 0;
3186  float chg = 0;
3187  float tchg = 0;
3188  // Add the hit charge in the box
3189  // All hits in the box, and all hits associated with the Tjs
3190  for (auto& iht : closeHits) {
3191  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
3192  chg += hit.Integral();
3193  if (slc.slHits[iht].InTraj == 0) continue;
3194  if (std::find(tjIDs.begin(), tjIDs.end(), slc.slHits[iht].InTraj) != tjIDs.end())
3195  tchg += hit.Integral();
3196  } // iht
3197  if (chg == 0) return 0;
3198  return tchg / chg;
3199  } // ChgFracNearPos
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
std::array< float, 2 > Point2_t
Definition: DataStructs.h:41
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
Detector simulation of raw signals on wires.
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
bool FindCloseHits(TCSlice const &slc, TrajPoint &tp, float const maxDelta, HitStatus_t hitRequest)
Definition: Utils.cxx:2837
float tca::ChgToMeV ( float  chg)

Definition at line 3925 of file TCShower.cxx.

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

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

Definition at line 4095 of file TCShower.cxx.

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

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

4096  {
4097  // check tj - ss assns
4098 
4099  std::string fcnLabel = inFcnLabel + ".ChkAssns";
4100  for (auto& ss : slc.cots) {
4101  if (ss.ID == 0) continue;
4102  for (auto tid : ss.TjIDs) {
4103  auto& tj = slc.tjs[tid - 1];
4104  if (tj.SSID != ss.ID) {
4105  std::cout << fcnLabel << " ***** Error: 2S" << ss.ID << " -> TjIDs T" << tid
4106  << " != tj.SSID 2S" << tj.SSID << "\n";
4107  return false;
4108  }
4109  } // tid
4110  // check 2S -> 3S
4111  if (ss.SS3ID > 0 && ss.SS3ID <= (int)slc.showers.size()) {
4112  auto& ss3 = slc.showers[ss.SS3ID - 1];
4113  if (std::find(ss3.CotIDs.begin(), ss3.CotIDs.end(), ss.ID) == ss3.CotIDs.end()) {
4114  std::cout << fcnLabel << " ***** Error: 2S" << ss.ID << " -> 3S" << ss.SS3ID
4115  << " but the shower says no\n";
4116  return false;
4117  }
4118  } // ss.SS3ID > 0
4119  } // ss
4120  for (auto& tj : slc.tjs) {
4121  if (tj.AlgMod[kKilled]) continue;
4122  if (tj.SSID < 0) {
4123  std::cout << fcnLabel << " ***** Error: T" << tj.ID << " tj.SSID is fubar\n";
4124  tj.SSID = 0;
4125  return false;
4126  }
4127  if (tj.SSID == 0) continue;
4128  auto& ss = slc.cots[tj.SSID - 1];
4129  if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tj.ID) != ss.TjIDs.end()) continue;
4130  std::cout << fcnLabel << " ***** Error: T" << tj.ID << " tj.SSID = 2S" << tj.SSID
4131  << " but the shower says no\n";
4132  return false;
4133  } // tj
4134 
4135  for (auto& ss3 : slc.showers) {
4136  if (ss3.ID == 0) continue;
4137  for (auto cid : ss3.CotIDs) {
4138  auto& ss = slc.cots[cid - 1];
4139  if (ss.SS3ID != ss3.ID) {
4140  std::cout << fcnLabel << " ***** Error: 3S" << ss3.ID << " -> 2S" << cid
4141  << " but it thinks it belongs to 3S" << ss.SS3ID << "\n";
4142  return false;
4143  }
4144  } // cid
4145  } // ss3
4146  return true;
4147  } // ChkAssns
void tca::ChkBegin ( TCSlice slc,
Trajectory tj 
)

Definition at line 2882 of file StepUtils.cxx.

References util::abs(), tca::Trajectory::AlgMod, tca::TrajPoint::AngleCode, tca::TCConfig::chargeCuts, ChkStopEndPts(), tca::TrajPoint::CTP, tca::TCConfig::dbgStp, DecodeCTP(), tca::TrajPoint::DeltaRMS, tca::TrajPoint::Dir, tca::Trajectory::EndPt, evt, FindCloseHits(), FixBegin(), tca::TCEvent::goodWire, tca::TrajPoint::Hits, tca::Trajectory::IsGood, kAllHits, kFixBegin, kFTBRvProp, kJunkTj, kKilled, kRvPrp, NumPtsWithCharge(), tca::TCSlice::nWires, geo::PlaneID::Plane, tca::TrajPoint::Pos, PrintPos(), tca::Trajectory::Pts, tca::TCConfig::qualityCuts, ReversePropagate(), seeds, SetEndPoints(), tca::TCSlice::slHits, tca::Trajectory::StepDir, tcc, TrimEndPts(), UnsetUsedHits(), tca::TCConfig::useAlg, tca::TrajPoint::UseHit, and tca::TCConfig::VLAStepSize.

Referenced by CheckStiffEl(), and CheckTraj().

2883  {
2884  // Check the parameters at the start of the trajectory. The first
2885  // points may not belong to this trajectory since they were added when there was
2886  // little information. This information may be updated later if ReversePropagate is used
2887 
2888  if (!tcc.useAlg[kFixBegin]) return;
2889  if (tj.AlgMod[kJunkTj]) return;
2890 
2891  // don't do anything if this tj has been modified by ReversePropagate
2892  if (tj.AlgMod[kRvPrp]) return;
2893 
2894  // don't bother with really short tjs
2895  if (tj.Pts.size() < 3) return;
2896 
2897  unsigned short atPt = tj.EndPt[1];
2898  unsigned short maxPtsFit = 0;
2899  unsigned short firstGoodChgPullPt = USHRT_MAX;
2900  for (unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1]; ++ipt) {
2901  auto& tp = tj.Pts[ipt];
2902  if (tp.Chg == 0) continue;
2903  if (tp.AveChg > 0 && firstGoodChgPullPt == USHRT_MAX) {
2904  if (std::abs(tp.ChgPull) < tcc.chargeCuts[0]) firstGoodChgPullPt = ipt;
2905  } // find the first good charge pull point
2906  if (tp.NTPsFit > maxPtsFit) {
2907  maxPtsFit = tp.NTPsFit;
2908  atPt = ipt;
2909  // no reason to continue if there are a good number of points fitted
2910  if (maxPtsFit > 20) break;
2911  }
2912  } // ipt
2913  // find the first point that is in this fit
2914  unsigned short firstPtFit = tj.EndPt[0];
2915  unsigned short cnt = 0;
2916  for (unsigned short ii = 1; ii < tj.Pts.size(); ++ii) {
2917  if (ii > atPt) break;
2918  unsigned short ipt = atPt - ii;
2919  if (tj.Pts[ipt].Chg == 0) continue;
2920  ++cnt;
2921  if (cnt == maxPtsFit) {
2922  firstPtFit = ipt;
2923  break;
2924  } // full count
2925  } // ii
2926 
2927  bool needsRevProp = firstPtFit > 3;
2928  unsigned short nPtsLeft = NumPtsWithCharge(slc, tj, false) - firstPtFit;
2929  if (needsRevProp) { needsRevProp = (nPtsLeft > 5); }
2930  if (tcc.dbgStp) {
2931  mf::LogVerbatim myprt("TC");
2932  myprt << "CB: firstPtFit " << firstPtFit << " at " << PrintPos(tj.Pts[firstPtFit].Pos);
2933  myprt << " atPt " << PrintPos(tj.Pts[atPt].Pos);
2934  myprt << " nPts with charge " << nPtsLeft;
2935  myprt << " firstGoodChgPullPt " << firstGoodChgPullPt;
2936  if (firstGoodChgPullPt != USHRT_MAX) myprt << " at " << PrintPos(tj.Pts[firstGoodChgPullPt]);
2937  myprt << " needsRevProp? " << needsRevProp;
2938  }
2939 
2940  if (!needsRevProp && firstGoodChgPullPt == USHRT_MAX) {
2941  // check one wire on the other side of EndPt[0] to see if there are hits that are available which could
2942  // be picked up by reverse propagation
2943  TrajPoint tp = tj.Pts[0];
2944  tp.Hits.clear();
2945  tp.UseHit.reset();
2946  // Move the TP "backwards"
2947  double stepSize = tcc.VLAStepSize;
2948  if (tp.AngleCode < 2) stepSize = std::abs(1 / tp.Dir[0]);
2949  tp.Pos[0] -= tp.Dir[0] * stepSize * tj.StepDir;
2950  tp.Pos[1] -= tp.Dir[1] * stepSize * tj.StepDir;
2951  // launch RevProp if this wire is dead
2952  unsigned int wire = std::nearbyint(tp.Pos[0]);
2953  unsigned short plane = DecodeCTP(tp.CTP).Plane;
2954  needsRevProp = (wire < slc.nWires[plane] && !evt.goodWire[plane][wire]);
2955  if (tcc.dbgStp && needsRevProp)
2956  mf::LogVerbatim("TC") << "CB: Previous wire " << wire << " is dead. Call ReversePropagate";
2957  if (!needsRevProp && firstGoodChgPullPt != USHRT_MAX) {
2958  // check for hits on a not-dead wire
2959  // BB May 20, 2019 Do this more carefully
2960  float maxDelta = 2 * tp.DeltaRMS;
2961  if (FindCloseHits(slc, tp, maxDelta, kAllHits) && !tp.Hits.empty()) {
2962  // count used and unused hits
2963  unsigned short nused = 0;
2964  for (auto iht : tp.Hits)
2965  if (slc.slHits[iht].InTraj > 0) ++nused;
2966  if (nused == 0) {
2967  needsRevProp = true;
2968  if (tcc.dbgStp) {
2969  mf::LogVerbatim("TC") << "CB: Found " << tp.Hits.size() - nused
2970  << " close unused hits found near EndPt[0] " << PrintPos(tp)
2971  << ". Call ReversePropagate";
2972  } // tcc.dbgStp
2973  } // nused = 0
2974  } // Close hits exist
2975  } // !needsRevProp
2976  } // !needsRevProp
2977 
2978  if (tcc.dbgStp) {
2979  mf::LogVerbatim("TC") << "CB: maxPtsFit " << maxPtsFit << " at point " << atPt
2980  << " firstPtFit " << firstPtFit << " Needs ReversePropagate? "
2981  << needsRevProp;
2982  }
2983 
2984  if (tcc.useAlg[kFTBRvProp] && needsRevProp) {
2985  // lop off the points before firstPtFit and reverse propagate
2986  if (tcc.dbgStp)
2987  mf::LogVerbatim("TC") << " clobber TPs " << PrintPos(tj.Pts[0]) << " to "
2988  << PrintPos(tj.Pts[firstPtFit])
2989  << ". Call TrimEndPts then ReversePropagate ";
2990  // first save the first TP on this trajectory. We will try to re-use it if
2991  // it isn't used during reverse propagation
2992  seeds.push_back(tj.Pts[0]);
2993  for (unsigned short ipt = 0; ipt <= firstPtFit; ++ipt)
2994  UnsetUsedHits(slc, tj.Pts[ipt]);
2995  SetEndPoints(tj);
2996  tj.AlgMod[kFTBRvProp] = true;
2997  // Check for quality and trim if necessary before reverse propagation
2998  TrimEndPts("RPi", slc, tj, tcc.qualityCuts, tcc.dbgStp);
2999  if (tj.AlgMod[kKilled]) {
3000  tj.IsGood = false;
3001  return;
3002  }
3003  ReversePropagate(slc, tj);
3004  ChkStopEndPts(slc, tj, tcc.dbgStp);
3005  }
3006  if (firstGoodChgPullPt != USHRT_MAX && firstGoodChgPullPt > atPt) atPt = firstGoodChgPullPt;
3007  // Update the fit parameters of the first points if no reverse propagation was done
3008  if (!tj.AlgMod[kRvPrp]) FixBegin(slc, tj, atPt);
3009 
3010  } // ChkBegin
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
std::vector< float > qualityCuts
Min points/wire, min consecutive pts after a gap.
Definition: DataStructs.h:554
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1061
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:622
std::vector< unsigned int > FindCloseHits(const 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:2774
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
void FixBegin(TCSlice &slc, Trajectory &tj, unsigned short atPt)
Definition: StepUtils.cxx:3013
void TrimEndPts(std::string fcnLabel, TCSlice &slc, Trajectory &tj, const std::vector< float > &fQualityCuts, bool prt)
Definition: Utils.cxx:1576
std::vector< float > chargeCuts
Definition: DataStructs.h:553
std::vector< TrajPoint > seeds
Definition: DataStructs.cxx:14
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
float VLAStepSize
Definition: DataStructs.h:576
geo::PlaneID DecodeCTP(CTP_t CTP)
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
TCEvent evt
Definition: DataStructs.cxx:8
void ChkStopEndPts(TCSlice &slc, Trajectory &tj, bool prt)
Definition: StepUtils.cxx:1671
void ReversePropagate(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:1417
void tca::ChkChgAsymmetry ( TCSlice slc,
Trajectory tj,
bool  prt 
)

Definition at line 1714 of file Utils.cxx.

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

Referenced by CheckTraj().

1715  {
1716  // looks for a high-charge point in the trajectory which may be due to the
1717  // trajectory crossing an interaction vertex. The properties of points on the opposite
1718  // sides of the high-charge point are analyzed. If significant differences are found, all points
1719  // near the high-charge point are removed as well as those from that point to the end
1720  if (!tcc.useAlg[kChkChgAsym]) return;
1721  if (tj.PDGCode == 111) return;
1722  unsigned short npts = tj.EndPt[1] - tj.EndPt[0];
1723  if (prt) mf::LogVerbatim("TC") << " Inside ChkChgAsymmetry T" << tj.ID;
1724  // ignore long tjs
1725  if (npts > 50) return;
1726  // ignore short tjs
1727  if (npts < 8) return;
1728  // require the charge pull > 5
1729  float bigPull = 5;
1730  unsigned short atPt = 0;
1731  // Don't consider the first/last few points in case there is a Bragg peak
1732  for (unsigned short ipt = tj.EndPt[0] + 2; ipt <= tj.EndPt[1] - 2; ++ipt) {
1733  auto& tp = tj.Pts[ipt];
1734  if (tp.ChgPull > bigPull) {
1735  bigPull = tp.ChgPull;
1736  atPt = ipt;
1737  }
1738  } // ipt
1739  if (atPt == 0) return;
1740  // require that this point be near the DS end
1741  if ((atPt - tj.EndPt[0]) < 0.5 * npts) return;
1742  if (prt)
1743  mf::LogVerbatim("TC") << "CCA: T" << tj.ID << " Large Chg point at " << atPt
1744  << ". Check charge asymmetry around it.";
1745  unsigned short nchk = 0;
1746  unsigned short npos = 0;
1747  unsigned short nneg = 0;
1748  for (short ii = 1; ii < 5; ++ii) {
1749  short iplu = atPt + ii;
1750  if (iplu > tj.EndPt[1]) break;
1751  short ineg = atPt - ii;
1752  if (ineg < tj.EndPt[0]) break;
1753  if (tj.Pts[iplu].Chg == 0) continue;
1754  if (tj.Pts[ineg].Chg == 0) continue;
1755  float asym = (tj.Pts[iplu].Chg - tj.Pts[ineg].Chg) / (tj.Pts[iplu].Chg + tj.Pts[ineg].Chg);
1756  ++nchk;
1757  if (asym > 0.5) ++npos;
1758  if (asym < -0.5) ++nneg;
1759  if (prt)
1760  mf::LogVerbatim("TC") << " ineg " << ineg << " iplu " << iplu << " asym " << asym
1761  << " nchk " << nchk;
1762  } // ii
1763  if (nchk < 3) return;
1764  // require most of the points be very positive or very negative
1765  nchk -= 2;
1766  bool doTrim = (nneg > nchk) || (npos > nchk);
1767  if (!doTrim) return;
1768  // remove all the points at the end starting at the one just before the peak if the pull is not so good
1769  auto& prevTP = tj.Pts[atPt - 1];
1770  if (std::abs(prevTP.ChgPull) > 2) --atPt;
1771  for (unsigned short ipt = atPt; ipt <= tj.EndPt[1]; ++ipt)
1772  UnsetUsedHits(slc, tj.Pts[ipt]);
1773  SetEndPoints(tj);
1774  tj.AlgMod[kChkChgAsym] = true;
1775  if (prt) PrintTrajectory("CCA", slc, tj, USHRT_MAX);
1776  } // ChkChgAsymmetry
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
TCConfig tcc
Definition: DataStructs.cxx:9
void PrintTrajectory(std::string someText, const TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:6035
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1061
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
void tca::ChkEndKink ( TCSlice const &  slc,
Trajectory tj,
bool  prt 
)

Definition at line 1682 of file Utils.cxx.

References tca::Trajectory::EndPt, tca::Trajectory::ID, kEndKink, tca::TCConfig::kinkCuts, KinkSignificance(), tca::Trajectory::PDGCode, PrintPos(), tca::Trajectory::Pts, tcc, and tca::TCConfig::useAlg.

1683  {
1684  // look for large-angle kink near the end
1685  if (!tcc.useAlg[kEndKink]) return;
1686  if (tj.PDGCode == 111) return;
1687  if (tj.EndPt[1] - tj.EndPt[0] < 6) return;
1688 
1689  if (prt) mf::LogVerbatim("TC") << "CEK: Inside ChkEndKinks T" << tj.ID << " ";
1690 
1691  float maxSig = tcc.kinkCuts[1];
1692  unsigned short withNptsFit = 0;
1693  unsigned short nPtsFit = tcc.kinkCuts[0];
1694  bool useChg = (tcc.kinkCuts[2] > 0);
1695  for (unsigned short nptsf = 3; nptsf < nPtsFit; ++nptsf) {
1696  unsigned short ipt = tj.EndPt[1] - nptsf;
1697  float ks = KinkSignificance(slc, tj, ipt, nptsf, useChg, prt);
1698  if (ks > maxSig) {
1699  maxSig = ks;
1700  withNptsFit = nptsf;
1701  }
1702  } // nptsf
1703  if (withNptsFit > 0) {
1704  unsigned short ipt = tj.EndPt[1] - withNptsFit;
1705  std::cout << "CEK: T" << tj.ID << " ipt " << ipt;
1706  float ks = KinkSignificance(slc, tj, ipt, withNptsFit, false, prt);
1707  auto& tp = tj.Pts[ipt];
1708  std::cout << " " << PrintPos(tp) << " withNptsFit " << withNptsFit << " ks " << ks << "\n";
1709  }
1710 
1711  } // ChkEndKink
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< float > kinkCuts
kink finder algorithm
Definition: DataStructs.h:550
float KinkSignificance(TCSlice const &slc, Trajectory &tj, unsigned short kinkPt, unsigned short nPtsFit, bool useChg, bool prt)
Definition: Utils.cxx:3041
TCConfig tcc
Definition: DataStructs.cxx:9
std::string PrintPos(const Point2_t &pos)
Definition: Utils.cxx:6362
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
bool tca::ChkMichel ( Trajectory tj,
unsigned short &  lastGoodPt 
)

Definition at line 4087 of file StepUtils.cxx.

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

4088  {
4089 
4090  if (!tcc.useAlg[kMichel]) return false;
4091  if (tj.PDGCode == 11 || tj.PDGCode == 111) return false;
4092 
4093  bool prt = (tcc.dbgStp || tcc.dbgAlg[kMichel]);
4094 
4095  //find number of hits that are consistent with Michel electron
4096  unsigned short nmichelhits = 0;
4097  //find number of hits that are consistent with Bragg peak
4098  unsigned short nbragghits = 0;
4099  float lastChg = 0;
4100 
4101  bool isfirsthit = true;
4102  unsigned short braggpeak = 0;
4103 
4104  for (unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
4105  if (ii > tj.EndPt[1]) continue;
4106  unsigned short ipt = tj.EndPt[1] - ii;
4107  if (tj.Pts[ipt].Chg > 0) {
4108  if (isfirsthit) {
4109  isfirsthit = false;
4110  if (tj.Pts[ipt].ChgPull < 0) { ++nmichelhits; }
4111  }
4112  else {
4113  if (tj.Pts[ipt].ChgPull < 0 && nmichelhits && !nbragghits) { //still Michel
4114  ++nmichelhits;
4115  }
4116  else {
4117  if (!nbragghits) {
4118  ++nbragghits; //Last Bragg peak hit
4119  lastChg = tj.Pts[ipt].Chg;
4120  braggpeak = ipt;
4121  }
4122  else if (tj.Pts[ipt].Chg < lastChg) { //still Bragg peak
4123  ++nbragghits;
4124  lastChg = tj.Pts[ipt].Chg;
4125  }
4126  else
4127  break;
4128  }
4129  }
4130  }
4131  }
4132  if (prt)
4133  mf::LogVerbatim("TC") << "ChkMichel Michel hits: " << nmichelhits
4134  << " Bragg peak hits: " << nbragghits;
4135  if (nmichelhits > 0 && nbragghits > 2) { //find Michel topology
4136  lastGoodPt = braggpeak;
4137  tj.AlgMod[kMichel] = true;
4138  return true;
4139  }
4140  else {
4141  return false;
4142  }
4143  }
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:579
void tca::ChkStop ( Trajectory tj)

Definition at line 3972 of file StepUtils.cxx.

References util::abs(), tca::Trajectory::AlgMod, tca::TrajPoint::Chg, tca::TCConfig::chkStopCuts, tca::TCConfig::dbgAlg, tca::TCConfig::dbgStp, dir, util::end(), tca::Trajectory::EndFlag, tca::Trajectory::EndPt, Fit2D(), tca::Trajectory::ID, kBragg, kChkStop, kEnvUnusedHits, kStiffEl, tca::Trajectory::PDGCode, tca::TrajPoint::Pos, tca::Trajectory::Pts, tca::Trajectory::Strategy, tcc, and tca::TCConfig::useAlg.

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

3973  {
3974  // Sets the EndFlag[kBragg] bits on the trajectory by identifying the Bragg peak
3975  // at each end. This function checks both ends, finding the point with the highest charge nearest the
3976  // end and considering the first (when end = 0) 4 points or last 4 points (when end = 1). The next
3977  // 5 - 10 points (fChkStop[0]) are fitted to a line, Q(x - x0) = Qo + (x - x0) * slope where x0 is the
3978  // wire position of the highest charge point. A large negative slope indicates that there is a Bragg
3979  // peak at the end.
3980 
3981  tj.EndFlag[0][kBragg] = false;
3982  tj.EndFlag[1][kBragg] = false;
3983  if (!tcc.useAlg[kChkStop]) return;
3984  if (tcc.chkStopCuts[0] < 0) return;
3985 
3986  if (tj.Strategy[kStiffEl]) return;
3987 
3988  // ignore trajectories that are very large angle at both ends
3989  if (tj.Pts[tj.EndPt[0]].AngleCode == 2 || tj.Pts[tj.EndPt[1]].AngleCode == 2) return;
3990 
3991  unsigned short nPtsToCheck = tcc.chkStopCuts[1];
3992  if (tj.Pts.size() < 6) return;
3993 
3994  bool prt = (tcc.dbgStp || tcc.dbgAlg[kChkStop]);
3995 
3996  if (prt) {
3997  mf::LogVerbatim("TC") << "ChkStop: T" << tj.ID << " requiring " << nPtsToCheck
3998  << " points with charge slope > " << tcc.chkStopCuts[0] << " Chg/WSEU";
3999  }
4000 
4001  // find the highest charge hit in the first 3 points at each end
4002  for (unsigned short end = 0; end < 2; ++end) {
4003  tj.EndFlag[end][kBragg] = false;
4004  // require that the end point is reasonably clean
4005  auto& endTP = tj.Pts[tj.EndPt[end]];
4006  if (endTP.Hits.size() > 2) continue;
4007  if (endTP.Environment[kEnvUnusedHits]) continue;
4008  short dir = 1 - 2 * end;
4009  // find the point with the highest charge considering the first 3 points
4010  float big = 0;
4011  unsigned short hiPt = 0;
4012  float wire0 = 0;
4013  for (unsigned short ii = 0; ii < 5; ++ii) {
4014  short ipt = tj.EndPt[end] + ii * dir;
4015  if (ipt < tj.EndPt[0] || ipt > tj.EndPt[1]) break;
4016  TrajPoint& tp = tj.Pts[ipt];
4017  if (tp.Chg > big) {
4018  big = tp.Chg;
4019  wire0 = tp.Pos[0];
4020  hiPt = ipt;
4021  }
4022  } // ii
4023  // ensure that the high point is closer to the end that is being
4024  // considered than to the other end
4025  short dpt0 = hiPt - tj.EndPt[0];
4026  short dpt1 = tj.EndPt[1] - hiPt;
4027  if (end == 0 && dpt1 <= dpt0) continue;
4028  if (end == 1 && dpt0 <= dpt1) continue;
4029  if (prt)
4030  mf::LogVerbatim("TC") << " end " << end << " wire0 " << wire0 << " Chg " << big << " hiPt "
4031  << hiPt;
4032  float prevChg = big;
4033  // prepare to do the fit
4034  Point2_t inPt;
4035  Vector2_t outVec, outVecErr;
4036  float chgErr, chiDOF;
4037  // Initialize
4038  Fit2D(0, inPt, chgErr, outVec, outVecErr, chiDOF);
4039  unsigned short cnt = 0;
4040  for (unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
4041  short ipt = hiPt + ii * dir;
4042  if (ipt < tj.EndPt[0] || ipt > tj.EndPt[1]) break;
4043  TrajPoint& tp = tj.Pts[ipt];
4044  if (tp.Chg == 0) continue;
4045  // quit if the charge is much larger than the previous charge
4046  if (tp.Chg > 1.5 * prevChg) continue;
4047  prevChg = tp.Chg;
4048  // Accumulate and save points
4049  inPt[0] = std::abs(tp.Pos[0] - wire0);
4050  inPt[1] = tp.Chg;
4051  // Assume 20% point-to-point charge fluctuations
4052  chgErr = 0.2 * tp.Chg;
4053  if (!Fit2D(2, inPt, chgErr, outVec, outVecErr, chiDOF)) break;
4054  ++cnt;
4055  if (cnt == nPtsToCheck) break;
4056  } // ii
4057  if (cnt < nPtsToCheck) continue;
4058  // do the fit and get the results
4059  if (!Fit2D(-1, inPt, chgErr, outVec, outVecErr, chiDOF)) continue;
4060  // check for really bad chidof indicating a major failure
4061  if (chiDOF > 500) continue;
4062  // The charge slope is negative for a stopping track in the way that the fit was constructed.
4063  // Flip the sign so we can make a cut against tcc.chkStopCuts[0] which is positive.
4064  outVec[1] = -outVec[1];
4065  bool itStops = (outVec[1] > tcc.chkStopCuts[0] && chiDOF < tcc.chkStopCuts[2] &&
4066  outVec[1] > 2.5 * outVecErr[1]);
4067  if (itStops) {
4068  tj.EndFlag[end][kBragg] = true;
4069  tj.AlgMod[kChkStop] = true;
4070  if (tj.PDGCode == 11) tj.PDGCode = 0;
4071  // Put the charge at the end into tp.AveChg
4072  tj.Pts[tj.EndPt[end]].AveChg = outVec[0];
4073  if (prt)
4074  mf::LogVerbatim("TC") << " end " << end << " fit chidof " << chiDOF << " slope "
4075  << outVec[1] << " +/- " << outVecErr[1] << " stopping";
4076  }
4077  else {
4078  if (prt)
4079  mf::LogVerbatim("TC") << " end " << end << " fit chidof " << chiDOF << " slope "
4080  << outVec[1] << " +/- " << outVecErr[1] << " Not stopping";
4081  }
4082  } // end
4083 
4084  } // ChkStop
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
constexpr auto abs(T v)
Returns the absolute value of the argument.
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
std::array< float, 2 > Point2_t
Definition: DataStructs.h:41
bool Fit2D(short mode, Point2_t inPt, float &inPtErr, Vector2_t &outVec, Vector2_t &outVecErr, float &chiDOF)
Definition: Utils.cxx:4982
std::array< double, 2 > Vector2_t
Definition: DataStructs.h:42
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
TDirectory * dir
Definition: macro.C:5
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:579
use the stiff electron strategy
Definition: DataStructs.h:492
std::vector< float > chkStopCuts
Bragg peak finder configuration.
Definition: DataStructs.h:548
void tca::ChkStopEndPts ( TCSlice slc,
Trajectory tj,
bool  prt 
)

Definition at line 1671 of file StepUtils.cxx.

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

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

1672  {
1673  // Analyze the end of the Tj after crawling has stopped to see if any of the points
1674  // should be used
1675 
1676  if (tj.EndFlag[1][kAtKink]) return;
1677  if (!tcc.useAlg[kChkStopEP]) return;
1678  if (tj.AlgMod[kJunkTj]) return;
1679  if (tj.Strategy[kStiffEl]) return;
1680 
1681  unsigned short endPt = tj.EndPt[1];
1682  // ignore VLA Tjs
1683  if (tj.Pts[endPt].AngleCode > 1) return;
1684  // don't get too carried away with this
1685  if (tj.Pts.size() - endPt > 10) return;
1686 
1687  // Get a list of hits a few wires beyond the last point on the Tj
1688  geo::PlaneID planeID = DecodeCTP(tj.CTP);
1689  unsigned short plane = planeID.Plane;
1690 
1691  // find the last point that has hits on it
1692  unsigned short lastPt = tj.Pts.size() - 1;
1693  for (lastPt = tj.Pts.size() - 1; lastPt >= tj.EndPt[1]; --lastPt)
1694  if (!tj.Pts[lastPt].Hits.empty()) break;
1695  auto& lastTP = tj.Pts[lastPt];
1696 
1697  if (tcc.dbgStp) {
1698  mf::LogVerbatim("TC") << "CSEP: checking " << tj.ID << " endPt " << endPt << " Pts size "
1699  << tj.Pts.size() << " lastPt Pos " << PrintPos(lastTP.Pos);
1700  }
1701  TrajPoint ltp;
1702  ltp.CTP = tj.CTP;
1703  ltp.Pos = tj.Pts[endPt].Pos;
1704  ltp.Dir = tj.Pts[endPt].Dir;
1705  double stepSize = std::abs(1 / ltp.Dir[0]);
1706  std::array<int, 2> wireWindow;
1707  std::array<float, 2> timeWindow;
1708  std::vector<int> closeHits;
1709  bool isClean = true;
1710  for (unsigned short step = 0; step < 10; ++step) {
1711  for (unsigned short iwt = 0; iwt < 2; ++iwt)
1712  ltp.Pos[iwt] += ltp.Dir[iwt] * stepSize;
1713  int wire = std::nearbyint(ltp.Pos[0]);
1714  wireWindow[0] = wire;
1715  wireWindow[1] = wire;
1716  timeWindow[0] = ltp.Pos[1] - 5;
1717  timeWindow[1] = ltp.Pos[1] + 5;
1718  bool hitsNear;
1719  auto tmp = FindCloseHits(slc, wireWindow, timeWindow, plane, kAllHits, true, hitsNear);
1720  // add close hits that are not associated with this tj
1721  for (auto iht : tmp)
1722  if (slc.slHits[iht].InTraj != tj.ID) closeHits.push_back(iht);
1723  float nWiresPast = 0;
1724  // Check beyond the end of the trajectory to see if there are hits there
1725  if (ltp.Dir[0] > 0) {
1726  // stepping +
1727  nWiresPast = ltp.Pos[0] - lastTP.Pos[0];
1728  }
1729  else {
1730  // stepping -
1731  nWiresPast = lastTP.Pos[0] - ltp.Pos[0];
1732  }
1733  if (tcc.dbgStp)
1734  mf::LogVerbatim("TC") << " Found " << tmp.size() << " hits near pos " << PrintPos(ltp.Pos)
1735  << " nWiresPast " << nWiresPast;
1736  if (nWiresPast > 0.5) {
1737  if (!tmp.empty()) isClean = false;
1738  if (nWiresPast > 1.5) break;
1739  } // nWiresPast > 0.5
1740  } // step
1741 
1742  // count the number of available hits
1743  unsigned short nAvailable = 0;
1744  for (auto iht : closeHits)
1745  if (slc.slHits[iht].InTraj == 0) ++nAvailable;
1746 
1747  if (tcc.dbgStp) {
1748  mf::LogVerbatim myprt("TC");
1749  myprt << "closeHits";
1750  for (auto iht : closeHits)
1751  myprt << " " << PrintHit(slc.slHits[iht]);
1752  myprt << " nAvailable " << nAvailable;
1753  myprt << " isClean " << isClean;
1754  } // prt
1755 
1756  if (!isClean || nAvailable != closeHits.size()) return;
1757 
1758  unsigned short originalEndPt = tj.EndPt[1] + 1;
1759  // looks clean so use all the hits
1760  for (unsigned short ipt = originalEndPt; ipt <= lastPt; ++ipt) {
1761  auto& tp = tj.Pts[ipt];
1762  bool hitsAdded = false;
1763  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1764  // This shouldn't happen but check anyway
1765  if (slc.slHits[tp.Hits[ii]].InTraj != 0) continue;
1766  tp.UseHit[ii] = true;
1767  slc.slHits[tp.Hits[ii]].InTraj = tj.ID;
1768  hitsAdded = true;
1769  } // ii
1770  if (hitsAdded) DefineHitPos(slc, tp);
1771  } // ipt
1772  tj.AlgMod[kChkStopEP] = true;
1773  SetEndPoints(tj);
1774  // Re-fitting the end might be a good idea but it's probably not necessary. The
1775  // values of Delta should have already been filled
1776 
1777  // require a Bragg peak
1778  ChkStop(tj);
1779  if (!tj.EndFlag[1][kBragg]) {
1780  // restore the original
1781  for (unsigned short ipt = originalEndPt; ipt <= lastPt; ++ipt)
1782  UnsetUsedHits(slc, tj.Pts[ipt]);
1783  SetEndPoints(tj);
1784  } // no Bragg Peak
1785 
1786  UpdateTjChgProperties("CSEP", slc, tj, prt);
1787 
1788  } // ChkStopEndPts
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void ChkStop(Trajectory &tj)
Definition: StepUtils.cxx:3972
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1061
constexpr auto abs(T v)
Returns the absolute value of the argument.
Float_t tmp
Definition: plot.C:35
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1791
std::vector< unsigned int > FindCloseHits(const 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:2774
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6347
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice const &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3577
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
geo::PlaneID DecodeCTP(CTP_t CTP)
use the stiff electron strategy
Definition: DataStructs.h:492
bool tca::ChkVtxAssociations ( TCSlice slc,
const CTP_t inCTP 
)

Definition at line 2058 of file TCVertex.cxx.

References DecodeCTP(), util::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().

2059  {
2060  // Check the associations
2061 
2062  // check the 2D -> 3D associations
2063  geo::PlaneID planeID = DecodeCTP(inCTP);
2064  unsigned short plane = planeID.Plane;
2065  for (auto& vx2 : slc.vtxs) {
2066  if (vx2.CTP != inCTP) continue;
2067  if (vx2.ID == 0) continue;
2068  if (vx2.Vx3ID == 0) continue;
2069  if (vx2.Vx3ID > int(slc.vtx3s.size())) {
2070  mf::LogVerbatim("TC") << "ChkVtxAssociations: Invalid vx2.Vx3ID " << vx2.Vx3ID
2071  << " in 2D vtx " << vx2.ID;
2072  return false;
2073  }
2074  auto& vx3 = slc.vtx3s[vx2.Vx3ID - 1];
2075  if (vx3.ID == 0) {
2076  mf::LogVerbatim("TC") << "ChkVtxAssociations: 2V" << vx2.ID << " thinks it is matched to 3V"
2077  << vx3.ID << " but vx3 is obsolete";
2078  return false;
2079  }
2080  if (vx3.Vx2ID[plane] != vx2.ID) {
2081  mf::LogVerbatim("TC") << "ChkVtxAssociations: 2V" << vx2.ID << " thinks it is matched to 3V"
2082  << vx3.ID << " but vx3 says no!";
2083  return false;
2084  }
2085  } // vx2
2086  // check the 3D -> 2D associations
2087  for (auto& vx3 : slc.vtx3s) {
2088  if (vx3.ID == 0) continue;
2089  if (vx3.Vx2ID[plane] == 0) continue;
2090  if (vx3.Vx2ID[plane] > (int)slc.vtxs.size()) {
2091  mf::LogVerbatim("TC") << "ChkVtxAssociations: Invalid vx3.Vx2ID " << vx3.Vx2ID[plane]
2092  << " in CTP " << inCTP;
2093  return false;
2094  }
2095  auto& vx2 = slc.vtxs[vx3.Vx2ID[plane] - 1];
2096  if (vx2.Vx3ID != vx3.ID) {
2097  mf::LogVerbatim("TC") << "ChkVtxAssociations: 3V" << vx3.ID << " thinks it is matched to 2V"
2098  << vx2.ID << " but vx2 says no!";
2099  return false;
2100  }
2101  } // vx3
2102 
2103  // check the Tj -> 2D associations
2104  for (auto& tj : slc.tjs) {
2105  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
2106  for (unsigned short end = 0; end < 2; ++end) {
2107  if (tj.VtxID[end] == 0) continue;
2108  if (tj.VtxID[end] > slc.vtxs.size()) {
2109  mf::LogVerbatim("TC") << "ChkVtxAssociations: T" << tj.ID << " thinks it is matched to 2V"
2110  << tj.VtxID[end] << " on end " << end
2111  << " but no vertex exists. Recovering";
2112  tj.VtxID[end] = 0;
2113  return false;
2114  }
2115  unsigned short ivx = tj.VtxID[end] - 1;
2116  auto& vx2 = slc.vtxs[ivx];
2117  if (vx2.ID == 0) {
2118  mf::LogVerbatim("TC") << "ChkVtxAssociations: T" << tj.ID << " thinks it is matched to 2V"
2119  << tj.VtxID[end] << " on end " << end
2120  << " but the vertex is killed. Fixing the Tj";
2121  tj.VtxID[end] = 0;
2122  return false;
2123  }
2124  } // end
2125  } // tj
2126 
2127  return true;
2128 
2129  } // ChkVtxAssociations
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
geo::PlaneID DecodeCTP(CTP_t CTP)
void tca::ClearCRInfo ( TCSlice slc)

Definition at line 108 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.

109  {
110  slc.crt.cr_origin.clear();
111  slc.crt.cr_pfpxmin.clear();
112  slc.crt.cr_pfpxmax.clear();
113  slc.crt.cr_pfpyzmindis.clear();
114  }
void tca::ClearShowerTree ( ShowerTreeVars stv)

Definition at line 219 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.

220  {
221  stv.BeginWir.clear();
222  stv.BeginTim.clear();
223  stv.BeginAng.clear();
224  stv.BeginChg.clear();
225  stv.BeginVtx.clear();
226  stv.EndWir.clear();
227  stv.EndTim.clear();
228  stv.EndAng.clear();
229  stv.EndChg.clear();
230  stv.EndVtx.clear();
231  stv.MCSMom.clear();
232  stv.PlaneNum.clear();
233  stv.TjID.clear();
234  stv.IsShowerTj.clear();
235  stv.ShowerID.clear();
236  stv.IsShowerParent.clear();
237  stv.StageNum.clear();
238  stv.Envelope.clear();
239  stv.EnvPlane.clear();
240  stv.EnvStage.clear();
241  stv.EnvShowerID.clear();
242 
243  return;
244 
245  } // ClearShowerTree
std::vector< int > EnvStage
Definition: DataStructs.h:402
std::vector< int > IsShowerParent
Definition: DataStructs.h:395
std::vector< float > EndWir
Definition: DataStructs.h:382
std::vector< float > EndAng
Definition: DataStructs.h:384
std::vector< float > BeginTim
Definition: DataStructs.h:378
std::vector< float > BeginAng
Definition: DataStructs.h:379
std::vector< float > EndTim
Definition: DataStructs.h:383
std::vector< int > ShowerID
Definition: DataStructs.h:394
ShowerTreeVars stv
Definition: DataStructs.cxx:11
std::vector< int > TjID
Definition: DataStructs.h:392
std::vector< short > BeginVtx
Definition: DataStructs.h:381
std::vector< short > EndVtx
Definition: DataStructs.h:386
std::vector< float > Envelope
Definition: DataStructs.h:400
std::vector< float > BeginChg
Definition: DataStructs.h:380
std::vector< int > EnvPlane
Definition: DataStructs.h:401
std::vector< short > MCSMom
Definition: DataStructs.h:388
std::vector< int > StageNum
Definition: DataStructs.h:396
std::vector< float > BeginWir
Definition: DataStructs.h:377
std::vector< float > EndChg
Definition: DataStructs.h:385
std::vector< int > EnvShowerID
Definition: DataStructs.h:403
std::vector< int > IsShowerTj
Definition: DataStructs.h:393
std::vector< short > PlaneNum
Definition: DataStructs.h:390
unsigned short tca::CloseEnd ( const Trajectory tj,
const Point2_t pos 
)

Definition at line 2495 of file Utils.cxx.

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

Referenced by MakePFPTjs(), and MergeWithVertex().

2496  {
2497  unsigned short endPt = tj.EndPt[0];
2498  auto& tp0 = tj.Pts[endPt];
2499  endPt = tj.EndPt[1];
2500  auto& tp1 = tj.Pts[endPt];
2501  if (PosSep2(tp0.Pos, pos) < PosSep2(tp1.Pos, pos)) return 0;
2502  return 1;
2503  } // CloseEnd
float PosSep2(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2604
bool tca::CompatibleMerge ( const TCSlice slc,
std::vector< int > const &  tjIDs,
bool  prt 
)

Definition at line 577 of file Utils.cxx.

References util::abs(), util::end(), tca::TCSlice::tjs, and TrajClosestApproach().

Referenced by EndMerge().

578  {
579  // Returns true if the last Tj in tjIDs has a topology consistent with it being
580  // merged with other Tjs in the same plane in the list. This is done by requiring that
581  // the closest TP between the last Tj and any other Tj is EndPt[0] or EndPt[1]. This is
582  // shown graphically here where the numbers represent the ID of a Tj that has a TP on a wire.
583  // Assume that TjIDs = {1, 2, 3, 4, 7} where T1 and T3 are in plane 0, T2 is in plane 1 and
584  // T4 is in plane 2. T7, in plane 0, was added to TjIDs with the intent of merging it with
585  // T1 and T3 into a single trajectory. This is a compatible merge if Tj7 has the following
586  // topology:
587  // 111111 333333 7777777
588  // This is an incompatible topology
589  // 111111 333333
590  // 7777777777
591  if (tjIDs.size() < 2) return false;
592  unsigned short lasttj = tjIDs[tjIDs.size() - 1] - 1;
593  auto const& mtj = slc.tjs[lasttj];
594  bool mtjIsShort = (mtj.Pts.size() < 5);
595  // minimum separation from each end of mtj
596  std::array<float, 2> minsep2{{1000, 1000}};
597  // ID of the Tj with the minimum separation
598  std::array<int, 2> minsepTj{{0, 0}};
599  // and the index of the point on that Tj
600  std::array<unsigned short, 2> minsepPt;
601  // determine the end of the closest Tj point. Start by assuming
602  // the closest Tj point is not near an end (end = 0);
603  std::array<unsigned short, 2> minsepEnd;
604  for (auto tjid : tjIDs) {
605  auto& tj = slc.tjs[tjid - 1];
606  if (tj.CTP != mtj.CTP) continue;
607  if (tj.ID == mtj.ID) continue;
608  for (unsigned short mend = 0; mend < 2; ++mend) {
609  Point2_t mendPos = mtj.Pts[mtj.EndPt[mend]].Pos;
610  float sep2 = minsep2[mend];
611  unsigned short closePt = 0;
612  if (!TrajClosestApproach(tj, mendPos[0], mendPos[1], closePt, sep2)) continue;
613  minsep2[mend] = sep2;
614  minsepTj[mend] = tjid;
615  minsepPt[mend] = closePt;
616  // set the end to a bogus value (not near an end)
617  minsepEnd[mend] = 2;
618  short dend0 = abs((short)closePt - tj.EndPt[0]);
619  short dend1 = abs((short)closePt - tj.EndPt[1]);
620  if (dend0 < dend1 && dend0 < 3) minsepEnd[mend] = 0;
621  if (dend1 < dend0 && dend1 < 3) minsepEnd[mend] = 1;
622  } // mend
623  } // tjid
624  // don't require that the minsepTjs be the same. This would reject this topology
625  // 111111 333333 7777777
626  // if mtj.ID = 3
627  bool isCompatible = (minsepEnd[0] != 2 && minsepEnd[1] != 2);
628  // check for large separation between the closest points for short Tjs
629  if (isCompatible && mtjIsShort) {
630  float minminsep = minsep2[0];
631  if (minsep2[1] < minminsep) minminsep = minsep2[1];
632  // require that the separation be less than sqrt(5)
633  isCompatible = minminsep < 5;
634  }
635  if (prt) {
636  mf::LogVerbatim myprt("TC");
637  myprt << "CompatibleMerge: T" << mtj.ID << " end";
638  for (unsigned short end = 0; end < 2; ++end)
639  myprt << " T" << minsepTj[end] << "_I" << minsepPt[end] << "_E" << minsepEnd[end]
640  << " minsep " << sqrt(minsep2[end]);
641  myprt << " Compatible? " << isCompatible;
642  } // prt
643  return isCompatible;
644 
645  } // CompatibleMerge
constexpr auto abs(T v)
Returns the absolute value of the argument.
bool TrajClosestApproach(Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
Definition: Utils.cxx:2622
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
std::array< float, 2 > Point2_t
Definition: DataStructs.h:41
bool tca::CompatibleMerge ( const Trajectory tj1,
const Trajectory tj2,
bool  prt 
)

Definition at line 648 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.

649  {
650  // returns true if the two Tjs are compatible with and end0-end1 merge. This function has many aspects of the
651  // compatibility checks done in EndMerge but with looser cuts.
652  if (tj1.AlgMod[kKilled] || tj2.AlgMod[kKilled]) return false;
653  if (tj1.AlgMod[kHaloTj] || tj2.AlgMod[kHaloTj]) return false;
654  if (tj1.CTP != tj2.CTP) return false;
655  unsigned short end1 = -1, end2 = 0;
656  float minLen = PosSep(tj1.Pts[tj1.EndPt[0]].Pos, tj1.Pts[tj1.EndPt[1]].Pos);
657  float len2 = PosSep(tj2.Pts[tj2.EndPt[0]].Pos, tj2.Pts[tj2.EndPt[1]].Pos);
658  if (len2 < minLen) minLen = len2;
659  minLen *= 1.2;
660  if (minLen > 10) minLen = 10;
661  for (unsigned short e1 = 0; e1 < 2; ++e1) {
662  auto& tp1 = tj1.Pts[tj1.EndPt[e1]];
663  for (unsigned short e2 = 0; e2 < 2; ++e2) {
664  auto& tp2 = tj2.Pts[tj2.EndPt[e2]];
665  float sep = PosSep(tp1.Pos, tp2.Pos);
666  if (sep < minLen) {
667  minLen = sep;
668  end1 = e1;
669  end2 = e2;
670  }
671  } // e2
672  } // e1
673  // require end to end
674  if (end2 != 1 - end1) return false;
675 
676  float overlapFraction = OverlapFraction(tj1, tj2);
677  if (overlapFraction > 0.25) {
678  if (prt)
679  mf::LogVerbatim("TC") << "CM: " << tj1.ID << " " << tj2.ID << " overlapFraction "
680  << overlapFraction << " > 0.25 ";
681  return false;
682  }
683 
684  auto& tp1 = tj1.Pts[tj1.EndPt[end1]];
685  auto& tp2 = tj2.Pts[tj2.EndPt[end2]];
686  float doca1 = PointTrajDOCA(tp1.Pos[0], tp1.Pos[1], tp2);
687  float doca2 = PointTrajDOCA(tp2.Pos[0], tp2.Pos[1], tp1);
688  if (doca1 > 2 && doca2 > 2) {
689  if (prt)
690  mf::LogVerbatim("TC") << "CM: " << tj1.ID << " " << tj2.ID << " Both docas > 2 " << doca1
691  << " " << doca2;
692  return false;
693  }
694 
695  float dang = DeltaAngle(tp1.Ang, tp2.Ang);
696  if (dang > 2 * tcc.kinkCuts[0]) {
697  if (prt)
698  mf::LogVerbatim("TC") << "CM: " << tj1.ID << " " << tj2.ID << " dang " << dang << " > "
699  << 2 * tcc.kinkCuts[0];
700  return false;
701  }
702 
703  return true;
704  } // CompatibleMerge
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< float > kinkCuts
kink finder algorithm
Definition: DataStructs.h:550
float PosSep(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2598
TCConfig tcc
Definition: DataStructs.cxx:9
float OverlapFraction(const Trajectory &tj1, const Trajectory &tj2)
Definition: Utils.cxx:707
float PointTrajDOCA(float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2524
double DeltaAngle(double Ang1, double Ang2)
Definition: Utils.cxx:3324
void tca::CompleteIncomplete3DVertices ( detinfo::DetectorPropertiesData const &  detProp,
TCSlice slc 
)

Definition at line 2470 of file TCVertex.cxx.

References AttachAnyTrajToVertex(), ChgFracNearPos(), detinfo::DetectorPropertiesData::ConvertXToTicks(), tca::VtxStore::CTP, tca::TCConfig::dbgAlg, tca::TCConfig::dbgSlc, EncodeCTP(), util::end(), GetAssns(), tca::VtxStore::ID, tca::TCSlice::ID, kComp3DVx, kDebug, kFixed, kHaloTj, kKilled, kVxIndPlnNoChg, MakeVertexObsolete(), tca::TCConfig::modes, tca::TCSlice::nPlanes, tca::VtxStore::NTraj, NumPtsWithCharge(), tca::VtxStore::Pass, tca::VtxStore::Pos, tca::TrajPoint::Pos, PrintPos(), RefineVtxPosition(), SetPDGCode(), SetVx2Score(), SplitTraj(), tca::VtxStore::Stat, StoreVertex(), tcc, tca::VtxStore::TjChgFrac, tca::TCSlice::tjs, util::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().

2471  {
2472  // Look for trajectories in a plane that lack a 2D vertex as listed in
2473  // 2DVtxID that are near the projected wire. This may trigger splitting trajectories,
2474  // assigning them to a new 2D vertex and completing 3D vertices
2475 
2476  if (!tcc.useAlg[kComp3DVx]) return;
2477  if (slc.nPlanes != 3) return;
2478 
2479  bool prt = (tcc.modes[kDebug] && tcc.dbgSlc && tcc.dbgAlg[kComp3DVx]);
2480 
2481  float maxdoca = 3;
2482  if (prt) mf::LogVerbatim("TC") << "Inside CI3DV with maxdoca set to " << maxdoca;
2483  unsigned short ivx3 = 0;
2484  for (auto& vx3 : slc.vtx3s) {
2485  // ignore obsolete vertices
2486  if (vx3.ID == 0) continue;
2487  // check for a completed 3D vertex
2488  if (vx3.Wire < 0) continue;
2489  unsigned short mPlane = USHRT_MAX;
2490  // look for vertices in the induction plane in which the charge requirement wasn't imposed
2491  bool indPlnNoChgVtx = false;
2492  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
2493  if (vx3.Vx2ID[plane] > 0) {
2494  auto& vx2 = slc.vtxs[vx3.Vx2ID[plane] - 1];
2495  if (vx2.Stat[kVxIndPlnNoChg]) indPlnNoChgVtx = true;
2496  continue;
2497  }
2498  mPlane = plane;
2499  } // ipl
2500  if (mPlane == USHRT_MAX) continue;
2501  if (indPlnNoChgVtx) continue;
2502  CTP_t mCTP = EncodeCTP(vx3.TPCID.Cryostat, vx3.TPCID.TPC, mPlane);
2503  // X position of the purported missing vertex
2504  // A TP for the missing 2D vertex
2505  TrajPoint vtp;
2506  vtp.Pos[0] = vx3.Wire;
2507  vtp.Pos[1] = detProp.ConvertXToTicks(vx3.X, mPlane, vx3.TPCID.TPC, vx3.TPCID.Cryostat) *
2508  tcc.unitsPerTick;
2509  if (prt)
2510  mf::LogVerbatim("TC") << "CI3DV 3V" << vx3.ID << " Pos " << mPlane << ":"
2511  << PrintPos(vtp.Pos);
2512  std::vector<int> tjIDs;
2513  std::vector<unsigned short> tjPts;
2514  for (auto& tj : slc.tjs) {
2515  if (tj.CTP != mCTP) continue;
2516  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
2517  if (tj.Pts.size() < 6) continue;
2518  if (tj.AlgMod[kComp3DVx]) continue;
2519  float doca = maxdoca;
2520  // find the closest distance between the vertex and the trajectory
2521  unsigned short closePt = 0;
2522  TrajPointTrajDOCA(vtp, tj, closePt, doca);
2523  if (closePt > tj.EndPt[1]) continue;
2524  // try to improve the location of the vertex by looking for a distinctive feature on the
2525  // trajectory, e.g. high multiplicity hits or larger than normal charge
2526  if (RefineVtxPosition(tj, closePt, 3, false)) vtp.Pos = tj.Pts[closePt].Pos;
2527  if (prt)
2528  mf::LogVerbatim("TC") << "CI3DV 3V" << vx3.ID << " candidate T" << tj.ID << " vtx pos "
2529  << PrintPos(vtp.Pos) << " doca " << doca << " closePt " << closePt;
2530  tjIDs.push_back(tj.ID);
2531  tjPts.push_back(closePt);
2532  } // itj
2533  if (tjIDs.empty()) continue;
2534  // compare the length of the Tjs used to make the vertex with the length of the
2535  // Tj that we want to split. Don't allow a vertex using very short Tjs to split a long
2536  // Tj in the 3rd plane
2537  auto vxtjs = GetAssns(slc, "3V", vx3.ID, "T");
2538  unsigned short maxPts = 0;
2539  unsigned short minPts = USHRT_MAX;
2540  for (auto tjid : vxtjs) {
2541  auto& tj = slc.tjs[tjid - 1];
2542  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
2543  if (npwc > maxPts) maxPts = npwc;
2544  if (npwc < minPts) minPts = npwc;
2545  } // tjid
2546  // skip this operation if any of the Tjs in the split list are > 3 * maxPts
2547  maxPts *= 3;
2548  bool skipit = false;
2549  for (auto tjid : tjIDs) {
2550  auto& tj = slc.tjs[tjid - 1];
2551  if (NumPtsWithCharge(slc, tj, false) > maxPts) skipit = true;
2552  } // tjid
2553  if (prt)
2554  mf::LogVerbatim("TC") << " maxPts " << maxPts << " skipit? " << skipit << " minPts "
2555  << minPts;
2556  if (skipit) continue;
2557  // 2D vertex
2558  VtxStore aVtx;
2559  unsigned short newVtxIndx = slc.vtxs.size();
2560  aVtx.ID = newVtxIndx + 1;
2561  aVtx.CTP = mCTP;
2562  aVtx.Topo = 3;
2563  aVtx.NTraj = 0;
2564  // Give it a bogus pass to indicate it wasn't created while stepping
2565  aVtx.Pass = 9;
2566  aVtx.Pos = vtp.Pos;
2567  // ensure this isn't in a messy region
2568  aVtx.TjChgFrac = ChgFracNearPos(slc, aVtx.Pos, tjIDs);
2569  if (prt)
2570  mf::LogVerbatim("TC") << " charge fraction near position " << aVtx.TjChgFrac
2571  << " cut if < 0.6";
2572  if (aVtx.TjChgFrac < 0.6) continue;
2573  if (!StoreVertex(slc, aVtx)) continue;
2574  // make a reference to the new vertex
2575  VtxStore& newVtx = slc.vtxs[slc.vtxs.size() - 1];
2576  if (prt) mf::LogVerbatim("TC") << " Stored new 2V" << newVtx.ID;
2577  // make a temporary copy so we can nudge it a bit if there is only one Tj
2578  std::array<float, 2> vpos = aVtx.Pos;
2579  for (unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2580  unsigned short itj = tjIDs[ii] - 1;
2581  unsigned short closePt = tjPts[ii];
2582  // determine which end is the closest
2583  unsigned short end = 1;
2584  // closest to the beginning?
2585  if (fabs(closePt - slc.tjs[itj].EndPt[0]) < fabs(closePt - slc.tjs[itj].EndPt[1])) end = 0;
2586  short dpt = fabs(closePt - slc.tjs[itj].EndPt[end]);
2587  if (prt) mf::LogVerbatim("TC") << " dpt " << dpt << " to end " << end;
2588  if (dpt < 2) {
2589  // close to an end
2590  if (slc.tjs[itj].VtxID[end] > 0) {
2591  // find the distance btw the existing vertex and the end of this tj
2592  auto& oldTj = slc.tjs[itj];
2593  auto& oldVx = slc.vtxs[oldTj.VtxID[end] - 1];
2594  short oldSep = fabs(oldVx.Pos[0] - oldTj.Pts[oldTj.EndPt[end]].Pos[0]);
2595  if (prt)
2596  mf::LogVerbatim("TC")
2597  << " T" << slc.tjs[itj].ID << " has vertex 2V" << slc.tjs[itj].VtxID[end]
2598  << " at end " << end << ". oldSep " << oldSep;
2599  if (dpt < oldSep) { MakeVertexObsolete("CI3DV", slc, oldVx, true); }
2600  else {
2601  continue;
2602  }
2603  } // slc.tjs[itj].VtxID[end] > 0
2604  slc.tjs[itj].VtxID[end] = slc.vtxs[newVtxIndx].ID;
2605  ++newVtx.NTraj;
2606  if (prt)
2607  mf::LogVerbatim("TC") << " attach Traj T" << slc.tjs[itj].ID << " at end " << end;
2608  slc.tjs[itj].AlgMod[kComp3DVx] = true;
2609  vpos = slc.tjs[itj].Pts[slc.tjs[itj].EndPt[end]].Pos;
2610  }
2611  else {
2612  // closePt is not near an end, so split the trajectory
2613  if (SplitTraj(slc, itj, closePt, newVtxIndx, prt)) {
2614  if (prt)
2615  mf::LogVerbatim("TC")
2616  << " SplitTraj success 2V" << slc.vtxs[newVtxIndx].ID << " at closePt " << closePt;
2617  // successfully split the Tj
2618  newVtx.NTraj += 2;
2619  }
2620  else {
2621  // split failed. Give up
2622  if (prt) mf::LogVerbatim("TC") << " SplitTraj failed";
2623  newVtx.NTraj = 0;
2624  break;
2625  }
2626  // Update the PDGCode for the chopped trajectory
2627  SetPDGCode(slc, itj);
2628  // and for the new trajectory
2629  SetPDGCode(slc, slc.tjs.size() - 1);
2630  } // closePt is not near an end, so split the trajectory
2631  slc.tjs[itj].AlgMod[kComp3DVx] = true;
2632  unsigned short newtj = slc.tjs.size() - 1;
2633  slc.tjs[newtj].AlgMod[kComp3DVx] = true;
2634  } // ii
2635  if (newVtx.NTraj == 0) {
2636  // A failure occurred. Recover
2637  if (prt) mf::LogVerbatim("TC") << " Failed. Recover and delete vertex " << newVtx.ID;
2638  MakeVertexObsolete("CI3DV", slc, newVtx, true);
2639  }
2640  else {
2641  // success
2642  vx3.Vx2ID[mPlane] = newVtx.ID;
2643  newVtx.Vx3ID = vx3.ID;
2644  vx3.Wire = -1;
2645  // set the vertex position to the start of the Tj if there is only one and fix it
2646  if (newVtx.NTraj == 1) {
2647  newVtx.Pos = vpos;
2648  newVtx.Stat[kFixed] = true;
2649  }
2650  AttachAnyTrajToVertex(slc, newVtx.ID - 1, prt);
2651  SetVx2Score(slc);
2652  if (prt) {
2653  mf::LogVerbatim myprt("TC");
2654  myprt << " Success: new 2V" << newVtx.ID << " at " << (int)newVtx.Pos[0] << ":"
2655  << (int)newVtx.Pos[1] / tcc.unitsPerTick;
2656  myprt << " points to 3V" << vx3.ID;
2657  myprt << " TjIDs:";
2658  for (auto& tjID : tjIDs)
2659  myprt << " T" << std::to_string(tjID);
2660  } // prt
2661  } // success
2662  ++ivx3;
2663  } // vx3
2664 
2665  } // CompleteIncomplete3DVertices
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeVertexObsolete(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2789
void SetPDGCode(TCSlice &slc, unsigned short itj)
Definition: Utils.cxx:4219
TCConfig tcc
Definition: DataStructs.cxx:9
vertex position fixed manually - no fitting done
Definition: DataStructs.h:88
bool AttachAnyTrajToVertex(TCSlice &slc, unsigned short ivx, bool prt)
Definition: TCVertex.cxx:1678
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:1908
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
float ChgFracNearPos(const TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3163
bool SplitTraj(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, unsigned short itj, float XPos, bool makeVx2, bool prt)
Definition: Utils.cxx:2223
vertex quality is suspect - No requirement made on chg btw it and the Tj
Definition: DataStructs.h:93
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
std::vector< int > GetAssns(TCSlice const &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4704
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2255
unsigned int CTP_t
Definition: DataStructs.h:45
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:579
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:49
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
void TrajPointTrajDOCA(TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
Definition: Utils.cxx:2384
master switch for turning on debug mode
Definition: DataStructs.h:524
bool RefineVtxPosition(const Trajectory &tj, unsigned short &nearPt, short nPtsToChk, bool prt)
Definition: TCVertex.cxx:2668
void tca::CompleteIncomplete3DVerticesInGaps ( detinfo::DetectorPropertiesData const &  detProp,
TCSlice slc 
)

Definition at line 2376 of file TCVertex.cxx.

References util::abs(), ChgFracNearPos(), detinfo::DetectorPropertiesData::ConvertXToTicks(), geo::CryostatID::Cryostat, tca::VtxStore::CTP, tca::TrajPoint::CTP, tca::TCConfig::dbgAlg, tca::TCConfig::dbgSlc, DeadWireCount(), EncodeCTP(), util::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().

2378  {
2379 
2380  if (!tcc.useAlg[kComp3DVxIG]) return;
2381  if (slc.nPlanes != 3) return;
2382 
2383  bool prt = (tcc.modes[kDebug] && tcc.dbgSlc && tcc.dbgAlg[kComp3DVxIG]);
2384  if (prt) mf::LogVerbatim("TC") << "Inside CI3DVIG:";
2385 
2386  for (unsigned short iv3 = 0; iv3 < slc.vtx3s.size(); ++iv3) {
2387  Vtx3Store& vx3 = slc.vtx3s[iv3];
2388  // ignore obsolete vertices
2389  if (vx3.ID == 0) continue;
2390  // check for a completed 3D vertex
2391  if (vx3.Wire < 0) continue;
2392  unsigned short mPlane = USHRT_MAX;
2393  for (unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
2394  if (vx3.Vx2ID[ipl] > 0) continue;
2395  mPlane = ipl;
2396  break;
2397  } // ipl
2398  if (mPlane == USHRT_MAX) continue;
2399  CTP_t mCTP = EncodeCTP(vx3.TPCID.Cryostat, vx3.TPCID.TPC, mPlane);
2400  // require that the missing vertex be in a large block of dead wires
2401  float dwc = DeadWireCount(slc, vx3.Wire - 4, vx3.Wire + 4, mCTP);
2402  if (dwc < 5) continue;
2403  // X position of the purported missing vertex
2404  VtxStore aVtx;
2405  aVtx.ID = slc.vtxs.size() + 1;
2406  aVtx.Pos[0] = vx3.Wire;
2407  aVtx.Pos[1] = detProp.ConvertXToTicks(vx3.X, mPlane, vx3.TPCID.TPC, vx3.TPCID.Cryostat) *
2408  tcc.unitsPerTick;
2409  aVtx.CTP = mCTP;
2410  aVtx.Topo = 4;
2411  aVtx.NTraj = 0;
2412  // Give it a bogus pass to indicate it wasn't created while stepping
2413  aVtx.Pass = 9;
2414  if (prt)
2415  mf::LogVerbatim("TC") << "CI3DVIG: Incomplete vertex " << iv3 << " in plane " << mPlane
2416  << " wire " << vx3.Wire << " Made 2D vertex ";
2417  std::vector<int> tjIDs;
2418  std::vector<unsigned short> tjEnds;
2419  for (unsigned short itj = 0; itj < slc.tjs.size(); ++itj) {
2420  if (slc.tjs[itj].CTP != mCTP) continue;
2421  if (slc.tjs[itj].AlgMod[kKilled] || slc.tjs[itj].AlgMod[kHaloTj]) continue;
2422  for (unsigned short end = 0; end < 2; ++end) {
2423  unsigned short ept = slc.tjs[itj].EndPt[end];
2424  TrajPoint& tp = slc.tjs[itj].Pts[ept];
2425  unsigned short oept = slc.tjs[itj].EndPt[1 - end];
2426  TrajPoint& otp = slc.tjs[itj].Pts[oept];
2427  // ensure that this is the end closest to the vertex
2428  if (std::abs(tp.Pos[0] - aVtx.Pos[0]) > std::abs(otp.Pos[0] - aVtx.Pos[0])) continue;
2429  float doca = PointTrajDOCA(aVtx.Pos[0], aVtx.Pos[1], tp);
2430  if (doca > 2) continue;
2431  float dwc = DeadWireCount(slc, aVtx.Pos[0], tp.Pos[0], tp.CTP);
2432  float ptSep;
2433  if (aVtx.Pos[0] > tp.Pos[0]) { ptSep = aVtx.Pos[0] - tp.Pos[0] - dwc; }
2434  else {
2435  ptSep = tp.Pos[0] - aVtx.Pos[0] - dwc;
2436  }
2437  if (prt)
2438  mf::LogVerbatim("TC") << "CI3DVIG: tj ID " << slc.tjs[itj].ID << " doca " << doca
2439  << " ptSep " << ptSep;
2440  if (ptSep < -2 || ptSep > 2) continue;
2441  // don't clobber an existing association
2442  if (slc.tjs[itj].VtxID[end] > 0) continue;
2443  tjIDs.push_back(slc.tjs[itj].ID);
2444  tjEnds.push_back(end);
2445  } // end
2446  } // itj
2447  if (!tjIDs.empty()) {
2448  // Determine how messy this region is
2449  aVtx.TjChgFrac = ChgFracNearPos(slc, aVtx.Pos, tjIDs);
2450  if (aVtx.TjChgFrac < 0.7) continue;
2451  aVtx.Vx3ID = vx3.ID;
2452  // Save the 2D vertex
2453  if (!StoreVertex(slc, aVtx)) continue;
2454  for (unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2455  unsigned short itj = tjIDs[ii] - 1;
2456  slc.tjs[itj].VtxID[tjEnds[ii]] = aVtx.ID;
2457  slc.tjs[itj].AlgMod[kComp3DVxIG] = true;
2458  } // ii
2459  SetVx2Score(slc);
2460  vx3.Vx2ID[mPlane] = aVtx.ID;
2461  vx3.Wire = -1;
2462  if (prt)
2463  mf::LogVerbatim("TC") << "CI3DVIG: new vtx 2V" << aVtx.ID << " points to 3V" << vx3.ID;
2464  }
2465  } // vx3
2466 
2467  } // CompleteIncomplete3DVerticesInGaps
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
constexpr auto abs(T v)
Returns the absolute value of the argument.
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2514
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:1908
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2095
float ChgFracNearPos(const TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3163
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2255
unsigned int CTP_t
Definition: DataStructs.h:45
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:579
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:49
master switch for turning on debug mode
Definition: DataStructs.h:524
bool tca::CompleteIncompleteShower ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 748 of file TCShower.cxx.

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

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

Definition at line 35 of file TCShower.cxx.

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

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

36  {
37  // Define the reference to the MVA reader used to determine the best
38  // shower parent PFParticle
39  cet::search_path sp("FW_SEARCH_PATH");
40  if (!tcc.showerParentReader) return;
41  std::string fullFileSpec;
42  sp.find_file(fMVAShowerParentWeights, fullFileSpec);
43  if (fullFileSpec == "") {
45  return;
46  }
47  tcc.showerParentVars.resize(9);
48  tcc.showerParentReader->AddVariable("fShEnergy", &tcc.showerParentVars[0]);
49  tcc.showerParentReader->AddVariable("fPfpEnergy", &tcc.showerParentVars[1]);
50  tcc.showerParentReader->AddVariable("fMCSMom", &tcc.showerParentVars[2]);
51  tcc.showerParentReader->AddVariable("fPfpLen", &tcc.showerParentVars[3]);
52  tcc.showerParentReader->AddVariable("fSep", &tcc.showerParentVars[4]);
53  tcc.showerParentReader->AddVariable("fDang1", &tcc.showerParentVars[5]);
54  tcc.showerParentReader->AddVariable("fDang2", &tcc.showerParentVars[6]);
55  tcc.showerParentReader->AddVariable("fChgFrac", &tcc.showerParentVars[7]);
56  tcc.showerParentReader->AddVariable("fInShwrProb", &tcc.showerParentVars[8]);
57  tcc.showerParentReader->BookMVA("BDT", fullFileSpec);
58  } // ConfigureTMVA
TCConfig tcc
Definition: DataStructs.cxx:9
TMVA::Reader * showerParentReader
Definition: DataStructs.h:570
std::vector< float > showerParentVars
Definition: DataStructs.h:571
void tca::CountBadPoints ( const TCSlice slc,
const PFPStruct pfp,
unsigned short  fromPt,
unsigned short  toPt,
unsigned short &  nBadPts,
unsigned short &  firstBadPt 
)

Definition at line 1290 of file PFPUtils.cxx.

References kEnvOverlap, kTP3DGood, tca::TCConfig::match3DCuts, PointPull(), tcc, tca::TCSlice::tjs, and tca::PFPStruct::TP3Ds.

1296  {
1297  // Count the number of points whose pull exceeds tcc.match3DCuts[4]
1298  firstBadPt = USHRT_MAX;
1299  nBadPts = 0;
1300  if (fromPt > pfp.TP3Ds.size() - 1) {
1301  nBadPts = USHRT_MAX;
1302  return;
1303  }
1304  if (toPt > pfp.TP3Ds.size()) toPt = pfp.TP3Ds.size();
1305  bool first = true;
1306  for (unsigned short ipt = fromPt; ipt < toPt; ++ipt) {
1307  auto& tp3d = pfp.TP3Ds[ipt];
1308  if (!tp3d.Flags[kTP3DGood]) continue;
1309  // don't clobber a point if it is on a TP that is overlapping another Tj. This will
1310  // happen for points close to a vertex and when trajectories cross
1311  auto& tp = slc.tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
1312  if (tp.Environment[kEnvOverlap]) continue;
1313  if (PointPull(tp3d) < tcc.match3DCuts[4]) continue;
1314  ++nBadPts;
1315  if (first) {
1316  first = false;
1317  firstBadPt = ipt;
1318  }
1319  } // ipt
1320  } // CountBadPoints
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< float > match3DCuts
3D matching cuts
Definition: DataStructs.h:551
float PointPull(const TP3D &tp3d)
Definition: PFPUtils.cxx:2794
PFPStruct tca::CreatePFP ( const TCSlice slc)

Definition at line 2802 of file PFPUtils.cxx.

References tca::PFPStruct::dEdx, tca::PFPStruct::dEdxErr, tca::PFPStruct::ID, tca::TCSlice::nPlanes, tca::PFPStruct::ParentUID, tca::TCSlice::pfps, tca::PFPStruct::SectionFits, tca::PFPStruct::TPCID, and tca::TCSlice::TPCID.

Referenced by DefineTjParents(), DotProd(), Finish3DShowers(), and MakePFParticles().

2803  {
2804  // The calling function should define the size of pfp.TjIDs
2805  PFPStruct pfp;
2806  pfp.ID = slc.pfps.size() + 1;
2807  pfp.ParentUID = 0;
2808  pfp.TPCID = slc.TPCID;
2809  // initialize arrays for both ends
2810  if (slc.nPlanes < 4) {
2811  pfp.dEdx[0].resize(slc.nPlanes, -1);
2812  pfp.dEdx[1].resize(slc.nPlanes, -1);
2813  pfp.dEdxErr[0].resize(slc.nPlanes, -1);
2814  pfp.dEdxErr[1].resize(slc.nPlanes, -1);
2815  }
2816  // create a single section fit to hold the start/end positions and direction
2817  pfp.SectionFits.resize(1);
2818  return pfp;
2819  } // CreatePFP
ShowerStruct tca::CreateSS ( TCSlice slc,
const std::vector< int > &  tjl 
)

Definition at line 4049 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, tca::ShowerStruct::TjIDs, and tca::TCSlice::tjs.

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

4050  {
4051  // Create a shower and shower Tj using Tjs in the list. If tjl is empty a
4052  // MC cheat shower is created inCTP. Note that inCTP is only used if tjl is empty.
4053  // A companion shower tj is created and stored but the ShowerStruct is not.
4054  ShowerStruct ss;
4055 
4056  // Create the shower tj
4057  Trajectory stj;
4058  stj.CTP = slc.tjs[tjl[0] - 1].CTP;
4059 
4060  // with three points
4061  stj.Pts.resize(3);
4062  for (auto& stp : stj.Pts) {
4063  stp.CTP = stj.CTP;
4064  // set all UseHit bits true so we don't get confused
4065  stp.UseHit.set();
4066  }
4067  stj.EndPt[0] = 0;
4068  stj.EndPt[1] = 2;
4069  stj.ID = slc.tjs.size() + 1;
4070  // Declare that stj is a shower Tj
4071  stj.AlgMod[kShowerTj] = true;
4072  stj.PDGCode = 1111;
4073  slc.tjs.push_back(stj);
4074  // define the ss
4075  ss.ID = slc.cots.size() + 1;
4076  ss.CTP = stj.CTP;
4077  // assign all TJ IDs to this ShowerStruct
4078  ss.TjIDs = tjl;
4079  // declare them to be InShower
4080  for (auto tjid : tjl) {
4081  auto& tj = slc.tjs[tjid - 1];
4082  if (tj.CTP != stj.CTP) {
4083  ss.ID = 0;
4084  return ss;
4085  }
4086  tj.SSID = ss.ID;
4087  } // tjid
4088  ss.ShowerTjID = stj.ID;
4089  ss.Envelope.resize(4);
4090  return ss;
4091 
4092  } // CreateSS
ShowerStruct3D tca::CreateSS3 ( TCSlice slc)

Definition at line 4030 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.

4031  {
4032  // create a 3D shower and size the vectors that are indexed by plane
4033 
4034  ShowerStruct3D ss3;
4035  ss3.TPCID = slc.TPCID;
4036  ss3.ID = slc.showers.size() + 1;
4037  ss3.Energy.resize(slc.nPlanes);
4038  ss3.EnergyErr.resize(slc.nPlanes);
4039  ss3.MIPEnergy.resize(slc.nPlanes);
4040  ss3.MIPEnergyErr.resize(slc.nPlanes);
4041  ss3.dEdx.resize(slc.nPlanes);
4042  ss3.dEdxErr.resize(slc.nPlanes);
4043 
4044  return ss3;
4045 
4046  } // CreateSS3
TP3D tca::CreateTP3D ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice slc,
int  tjID,
unsigned short  tpIndex 
)

Definition at line 2706 of file PFPUtils.cxx.

References detinfo::DetectorPropertiesData::ConvertTicksToX(), tca::TP3D::CTP, DecodeCTP(), tca::TP3D::Flags, GetHitMultiplet(), HitsRMSTime(), kAllHits, kTP3DBad, kTP3DGood, tcc, tca::TP3D::TjID, tca::TCSlice::tjs, TPHitsRMSTime(), tca::TP3D::TPIndex, tca::TP3D::TPX, tca::TP3D::TPXErr2, tca::TCConfig::unitsPerTick, tca::TP3D::Wire, and tca::TCConfig::wirePitch.

Referenced by AddPointsInRange(), DotProd(), MakeSmallAnglePFP(), and MakeTP3Ds().

2710  {
2711  // create a TP3D with a single TP. Note that the SectionFit in which it
2712  // should be placed and the 3D position can't be determined until the the TP3D is
2713  // associated with a pfp. See SetSection()
2714 
2715  TP3D tp3d;
2716  tp3d.Flags[kTP3DBad] = true;
2717  if (tjID <= 0 || tjID > (int)slc.tjs.size()) return tp3d;
2718  auto& tj = slc.tjs[tjID - 1];
2719  if (tpIndex < tj.EndPt[0] || tpIndex > tj.EndPt[1]) return tp3d;
2720  tp3d.TjID = tjID;
2721  tp3d.TPIndex = tpIndex;
2722  auto& tp2 = tj.Pts[tp3d.TPIndex];
2723  auto plnID = DecodeCTP(tp2.CTP);
2724  tp3d.CTP = tp2.CTP;
2725  double tick = tp2.HitPos[1] / tcc.unitsPerTick;
2726  tp3d.TPX = detProp.ConvertTicksToX(tick, plnID);
2727  // Get the RMS of the TP in WSE units and convert to cm
2728  float rms = TPHitsRMSTime(slc, tp2, kAllHits) * tcc.wirePitch;
2729  // inflate the error for large angle TPs
2730  if (tp2.AngleCode == 1) rms *= 2;
2731  // a more careful treatment for long-pulse hits
2732  if (tp2.AngleCode > 1) {
2733  std::vector<unsigned int> hitMultiplet;
2734  for (std::size_t ii = 0; ii < tp2.Hits.size(); ++ii) {
2735  if (!tp2.UseHit[ii]) continue;
2736  GetHitMultiplet(slc, tp2.Hits[ii], hitMultiplet, true);
2737  if (hitMultiplet.size() > 1) break;
2738  } // ii
2739  rms = HitsRMSTime(slc, hitMultiplet, kAllHits) * tcc.wirePitch;
2740  // the returned RMS is closer to the FWHM, so divide by 2
2741  rms /= 2;
2742  } // tp2.AngleCode > 1
2743  tp3d.TPXErr2 = rms * rms;
2744  tp3d.Wire = tp2.Pos[0];
2745  // Can't declare it good since Pos and SFIndex aren't defined
2746  tp3d.Flags[kTP3DGood] = false;
2747  tp3d.Flags[kTP3DBad] = false;
2748  return tp3d;
2749  } // CreateTP3D
TCConfig tcc
Definition: DataStructs.cxx:9
float TPHitsRMSTime(const TCSlice &slc, const TrajPoint &tp, HitStatus_t hitRequest)
Definition: Utils.cxx:4092
float HitsRMSTime(const TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
Definition: Utils.cxx:4125
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
void GetHitMultiplet(const TCSlice &slc, unsigned int theHit, std::vector< unsigned int > &hitsInMultiplet, bool useLongPulseHits)
Definition: StepUtils.cxx:1521
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
Definition: electronics.h:73
geo::PlaneID DecodeCTP(CTP_t CTP)
TrajPoint tca::CreateTPFromTj ( const Trajectory tj)

Definition at line 3450 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::TrajPoint::Ang, tca::TrajPoint::Chg, tca::TrajPoint::CTP, tca::Trajectory::CTP, tca::TrajPoint::Dir, tca::Trajectory::EndPt, tca::Trajectory::ID, kKilled, tca::TrajPoint::Pos, tca::Trajectory::Pts, and tca::TrajPoint::Step.

Referenced by LastEndMerge().

3451  {
3452  // Create a trajectory point by averaging the position and direction of all
3453  // TPs in the trajectory. This is used in LastEndMerge
3454  TrajPoint tjtp;
3455  // set the charge invalid
3456  tjtp.Chg = -1;
3457  if (tj.AlgMod[kKilled]) return tjtp;
3458  // stash the ID in the Step
3459  tjtp.Step = tj.ID;
3460  tjtp.CTP = tj.CTP;
3461  tjtp.Pos[0] = 0;
3462  tjtp.Pos[1] = 0;
3463  tjtp.Dir[0] = 0;
3464  tjtp.Dir[1] = 0;
3465  float cnt = 0;
3466  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
3467  auto& tp = tj.Pts[ipt];
3468  if (tp.Chg <= 0) continue;
3469  tjtp.Pos[0] += tp.Pos[0];
3470  tjtp.Pos[1] += tp.Pos[1];
3471  tjtp.Dir[1] += tp.Dir[1];
3472  ++cnt;
3473  } // ipt
3474  tjtp.Pos[0] /= cnt;
3475  tjtp.Pos[1] /= cnt;
3476  tjtp.Dir[1] /= cnt;
3477  double arg = 1 - tjtp.Dir[1] * tjtp.Dir[1];
3478  if (arg < 0) arg = 0;
3479  tjtp.Dir[0] = sqrt(arg);
3480  tjtp.Ang = atan2(tjtp.Dir[1], tjtp.Dir[0]);
3481  tjtp.Chg = 1;
3482  return tjtp;
3483  } // CreateTjTP
float tca::DeadWireCount ( const TCSlice slc,
const TrajPoint tp1,
const TrajPoint tp2 
)

Definition at line 2095 of file Utils.cxx.

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

Referenced by AddHits(), cluster::ClusterCrawlerAlg::CheckClusterHitFrac(), cluster::ClusterCrawlerAlg::ChkMerge(), CompleteIncomplete3DVerticesInGaps(), EndMerge(), Find2DVertices(), cluster::BlurredClusteringAlg::GetMinSize(), LastEndMerge(), NumPtsWithCharge(), StepAway(), TrajTrajDOCA(), and UpdateTraj().

2096  {
2097  return DeadWireCount(slc, tp1.Pos[0], tp2.Pos[0], tp1.CTP);
2098  } // DeadWireCount
float DeadWireCount(const TCSlice &slc, const float &inWirePos1, const float &inWirePos2, CTP_t tCTP)
Definition: Utils.cxx:2101
float tca::DeadWireCount ( const TCSlice slc,
const float &  inWirePos1,
const float &  inWirePos2,
CTP_t  tCTP 
)

Definition at line 2101 of file Utils.cxx.

References DecodeCTP(), evt, tca::TCEvent::goodWire, tca::TCSlice::nWires, geo::PlaneID::Plane, and tmp.

2105  {
2106  if (inWirePos1 < -0.4 || inWirePos2 < -0.4) return 0;
2107  unsigned int inWire1 = std::nearbyint(inWirePos1);
2108  unsigned int inWire2 = std::nearbyint(inWirePos2);
2109  geo::PlaneID planeID = DecodeCTP(tCTP);
2110  unsigned short plane = planeID.Plane;
2111  if (inWire1 > slc.nWires[plane] || inWire2 > slc.nWires[plane]) return 0;
2112  if (inWire1 > inWire2) {
2113  // put in increasing order
2114  unsigned int tmp = inWire1;
2115  inWire1 = inWire2;
2116  inWire2 = tmp;
2117  } // inWire1 > inWire2
2118  ++inWire2;
2119  unsigned int wire, ndead = 0;
2120  for (wire = inWire1; wire < inWire2; ++wire)
2121  if (!evt.goodWire[plane][wire]) ++ndead;
2122  return ndead;
2123  } // DeadWireCount
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
Float_t tmp
Definition: plot.C:35
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:622
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
geo::PlaneID DecodeCTP(CTP_t CTP)
TCEvent evt
Definition: DataStructs.cxx:8
geo::PlaneID tca::DecodeCTP ( CTP_t  CTP)

Definition at line 100 of file DataStructs.cxx.

References Cpad, and Tpad.

Referenced by AddHits(), AddLAHits(), AddLooseHits(), AddPointsInRange(), ChgFracNearPos(), ChkBegin(), ChkStopEndPts(), ChkVtxAssociations(), CompleteIncompleteShower(), CreateTP3D(), DeadWireCount(), dEdx(), EncodeCTP(), ExpectedHitsRMS(), FilldEdx(), FillmAllTraj(), Find2DVertices(), Find3DRecoRange(), Find3DVertices(), FindCloseHits(), FindCloseTjs(), tca::TrajClusterAlg::FindJunkTraj(), Finish3DShowers(), FitTP3Ds(), cluster::ClusterCrawlerAlg::FitVtx(), Forecast(), cluster::ClusterCrawlerAlg::GetHitRange(), MakeBareTP(), MakeJunkVertices(), MakePFPTjs(), MakeTP3D(), MakeVertexObsolete(), Match3DFOM(), MaxChargeAsymmetry(), PrintAllTraj(), PrintPos(), cluster::TrajCluster::produce(), Reconcile2Vs(), tca::TrajClusterAlg::ReconstructAllTraj(), ReversePropagate(), SaveTjInfo(), SaveTjInfoStuff(), SetSection(), SetTPEnvironment(), SignalAtTp(), SignalAtTpInSlc(), SplitTraj(), SplitTrajCrossingVertices(), StepAway(), TrimEndPts(), UpdateShower(), ValidTwoPlaneMatch(), cluster::ClusterCrawlerAlg::VtxMatch(), and WireHitRangeOK().

101  {
102  auto const cryo = (CTP / Cpad);
103  return geo::PlaneID(
104  /* Cryostat */ cryo,
105  /* TPC */ (CTP - cryo * Cpad) / Tpad,
106  /* Plane */ (CTP % 10));
107  }
IDparameter< geo::PlaneID > PlaneID
Member type of validated geo::PlaneID parameter.
constexpr unsigned int Tpad
Definition: DataStructs.h:46
constexpr unsigned int Cpad
Definition: DataStructs.h:47
bool tca::DecodeDebugString ( std::string  strng)

Definition at line 5068 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::dbgAlg, 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, EncodeCTP(), kDebug, kHamVx, kHamVx2, tca::TCConfig::modes, tca::DebugStuff::MVI, tca::DebugStuff::MVI_Iter, tca::DebugStuff::Plane, tca::TCConfig::recoSlice, tca::TCConfig::recoTPC, tca::DebugStuff::Slice, tcc, tca::DebugStuff::Tick, tca::DebugStuff::TPC, tca::DebugStuff::Wire, and tca::DebugStuff::WorkID.

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

5069  {
5070  // try to unpack the string as Cryostat:TPC:Plane:Wire:Tick or something
5071  // like Slice:<slice index>
5072 
5073  if (strng == "instruct") {
5074  std::cout << "****** Unrecognized DebugConfig. Here are your options\n";
5075  std::cout << " 'C:T:P:W:Tick' where C = cryostat, T = TPC, W = wire, Tick (+/-5) to debug "
5076  "stepping (DUNE)\n";
5077  std::cout << " 'P:W:Tick' for single cryostat/TPC detectors (uB, LArIAT, etc)\n";
5078  std::cout << " 'WorkID <id> <slice index>' where <id> is a tj work ID (< 0) in slice <slice "
5079  "index> (default = 0)\n";
5080  std::cout << " 'Merge <CTP>' to debug trajectory merging\n";
5081  std::cout << " '2V <CTP>' to debug 2D vertex finding\n";
5082  std::cout << " '3V' to debug 3D vertex finding\n";
5083  std::cout << " 'VxMerge' to debug 2D vertex merging\n";
5084  std::cout << " 'JunkVx' to debug 2D junk vertex finder\n";
5085  std::cout << " 'PFP' to debug 3D matching and PFParticles\n";
5086  std::cout << " 'MVI <MVI> <MVI Iteration>' for detailed debugging of one PFP MatchVecIndex\n";
5087  std::cout << " 'DeltaRay' to debug delta ray tagging\n";
5088  std::cout << " 'Muon' to debug muon tagging\n";
5089  std::cout << " '2S <CTP>' to debug a 2D shower in CTP\n";
5090  std::cout << " 'Reco TPC <TPC>' to only reconstruct hits in the specified TPC\n";
5091  std::cout << " 'Reco Slice <ID>' to reconstruct all sub-slices in the recob::Slice with the "
5092  "specified ID\n";
5093  std::cout << " 'SubSlice <sub-slice index>' where <slice index> restricts output to the "
5094  "specified sub-slice index\n";
5095  std::cout << " 'Stitch' to debug PFParticle stitching between TPCs\n";
5096  std::cout << " 'Sum' or 'Summary' to print a debug summary report\n";
5097  std::cout << " 'Dump <WorkID>' or 'Dump <UID>' to print all TPs in the trajectory to "
5098  "tcdump<UID>.csv\n";
5099  std::cout << " Note: Algs with debug printing include HamVx, HamVx2, SplitTjCVx, Comp3DVx, "
5100  "Comp3DVxIG, VtxHitsSwap\n";
5101  std::cout << " Set SkipAlgs: [\"bogusText\"] to print a list of algorithm names\n";
5102  return false;
5103  } // instruct
5104 
5105  // handle the simple cases that don't need decoding
5106  if (strng.find("3V") != std::string::npos) {
5107  tcc.dbg3V = true;
5108  tcc.modes[kDebug] = true;
5109  return true;
5110  }
5111  if (strng.find("3S") != std::string::npos) {
5112  tcc.dbg3S = true;
5113  tcc.modes[kDebug] = true;
5114  return true;
5115  }
5116  if (strng.find("VxMerge") != std::string::npos) {
5117  tcc.dbgVxMerge = true;
5118  tcc.modes[kDebug] = true;
5119  return true;
5120  }
5121  if (strng.find("JunkVx") != std::string::npos) {
5122  tcc.dbgVxJunk = true;
5123  tcc.modes[kDebug] = true;
5124  return true;
5125  }
5126  if (strng.find("DeltaRay") != std::string::npos) {
5127  tcc.dbgDeltaRayTag = true;
5128  tcc.modes[kDebug] = true;
5129  return true;
5130  }
5131  if (strng.find("Muon") != std::string::npos) {
5132  tcc.dbgMuonTag = true;
5133  tcc.modes[kDebug] = true;
5134  return true;
5135  }
5136  if (strng.find("Stitch") != std::string::npos) {
5137  tcc.dbgStitch = true;
5138  tcc.modes[kDebug] = true;
5139  return true;
5140  }
5141  if (strng.find("HamVx") != std::string::npos) {
5142  tcc.dbgAlg[kHamVx] = true;
5143  tcc.modes[kDebug] = true;
5144  return true;
5145  }
5146  if (strng.find("HamVx2") != std::string::npos) {
5147  tcc.dbgAlg[kHamVx2] = true;
5148  tcc.modes[kDebug] = true;
5149  return true;
5150  }
5151  if (strng.find("Sum") != std::string::npos) {
5152  tcc.dbgSummary = true;
5153  tcc.modes[kDebug] = true;
5154  return true;
5155  }
5156 
5157  std::vector<std::string> words;
5158  boost::split(words, strng, boost::is_any_of(" :"), boost::token_compress_on);
5159  if (words.size() == 5) {
5160  // configure for DUNE
5161  debug.Cryostat = std::stoi(words[0]);
5162  debug.TPC = std::stoi(words[1]);
5163  debug.Plane = std::stoi(words[2]);
5164  debug.Wire = std::stoi(words[3]);
5165  debug.Tick = std::stoi(words[4]);
5166  tcc.modes[kDebug] = true;
5167  tcc.dbgStp = true;
5168  // also dump this tj
5169  tcc.dbgDump = true;
5170  return true;
5171  } // nums.size() == 5
5172  if (words[0] == "PFP" || words[0] == "MVI") {
5173  tcc.dbgPFP = true;
5174  tcc.modes[kDebug] = true;
5175  // Use debug.Hit to identify the matchVec index
5176  if (words.size() > 2) {
5177  debug.MVI = std::stoi(words[1]);
5178  if (words.size() == 3) debug.MVI_Iter = std::stoi(words[2]);
5179  }
5180  return true;
5181  } // PFP
5182  if (words.size() == 2 && words[0] == "Dump") {
5183  debug.WorkID = std::stoi(words[1]);
5184  debug.Slice = 0;
5185  tcc.modes[kDebug] = true;
5186  tcc.dbgDump = true;
5187  return true;
5188  }
5189  if (words.size() > 1 && words[0] == "WorkID") {
5190  debug.WorkID = std::stoi(words[1]);
5191  if (debug.WorkID >= 0) return false;
5192  // default to sub-slice index 0
5193  debug.Slice = 0;
5194  if (words.size() > 2) debug.Slice = std::stoi(words[2]);
5195  tcc.modes[kDebug] = true;
5196  // dbgStp is set true after debug.WorkID is found
5197  tcc.dbgStp = false;
5198  return true;
5199  } // words.size() == 3 && words[0] == "WorkID"
5200  if (words.size() == 3 && words[0] == "Reco" && words[1] == "TPC") {
5201  tcc.recoTPC = std::stoi(words[2]);
5202  tcc.modes[kDebug] = true;
5203  std::cout << "Reconstructing only in TPC " << tcc.recoTPC << "\n";
5204  return true;
5205  }
5206  if (words.size() == 3 && words[0] == "Reco" && words[1] == "Slice") {
5207  tcc.recoSlice = std::stoi(words[1]);
5208  std::cout << "Reconstructing Slice " << tcc.recoSlice << "\n";
5209  return true;
5210  }
5211  if (words.size() == 3) {
5212  // configure for uB, LArIAT, etc
5213  debug.Cryostat = 0;
5214  debug.TPC = 0;
5215  debug.Plane = std::stoi(words[0]);
5216  debug.Wire = std::stoi(words[1]);
5217  debug.Tick = std::stoi(words[2]);
5219  tcc.modes[kDebug] = true;
5220  tcc.dbgStp = true;
5221  return true;
5222  }
5223  if (words.size() == 2 && words[0] == "Merge") {
5224  debug.CTP = std::stoi(words[1]);
5225  tcc.dbgMrg = true;
5226  tcc.modes[kDebug] = true;
5227  return true;
5228  }
5229  if (words.size() == 2 && words[0] == "2V") {
5230  debug.CTP = std::stoi(words[1]);
5231  tcc.dbg2V = true;
5232  tcc.modes[kDebug] = true;
5233  return true;
5234  }
5235  if (words.size() == 2 && words[0] == "2S") {
5236  debug.CTP = std::stoi(words[1]);
5237  tcc.dbg2S = true;
5238  tcc.modes[kDebug] = true;
5239  return true;
5240  }
5241  // Slice could apply to several debug options.
5242  if (words.size() == 2 && words[0] == "SubSlice") {
5243  debug.Slice = std::stoi(words[1]);
5244  return true;
5245  }
5246  return false;
5247  } // DecodeDebugString
bool dbgStitch
debug PFParticle stitching
Definition: DataStructs.h:595
short recoTPC
only reconstruct in the seleted TPC
Definition: DataStructs.h:581
TCConfig tcc
Definition: DataStructs.cxx:9
bool dbgDeltaRayTag
Definition: DataStructs.h:591
unsigned int MVI
MatchVec Index for detailed 3D matching.
Definition: DebugStruct.h:29
bool dbg3V
debug 3D vertex finding
Definition: DataStructs.h:589
int Cryostat
Select Cryostat.
Definition: DebugStruct.h:20
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
int Wire
Select hit Wire for debugging.
Definition: DebugStruct.h:24
int WorkID
Select the StartWorkID for debugging.
Definition: DebugStruct.h:28
DebugStuff debug
Definition: DebugStruct.cxx:4
bool dbg2V
debug 2D vertex finding
Definition: DataStructs.h:585
int Plane
Select plane.
Definition: DebugStruct.h:22
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
int Tick
Select hit PeakTime for debugging (< 0 for vertex finding)
Definition: DebugStruct.h:25
int TPC
Select TPC.
Definition: DebugStruct.h:21
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:579
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:49
unsigned short MVI_Iter
MVI iteration - see FindPFParticles.
Definition: DebugStruct.h:30
short recoSlice
only reconstruct the slice with ID (0 = all)
Definition: DataStructs.h:580
bool dbgSummary
print a summary report
Definition: DataStructs.h:596
master switch for turning on debug mode
Definition: DataStructs.h:524
CTP_t CTP
set to an invalid CTP
Definition: DebugStruct.h:23
float tca::dEdx ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
const TCSlice slc,
TP3D tp3d 
)

Definition at line 2671 of file PFPUtils.cxx.

References util::abs(), tca::TCEvent::allHits, tca::TCConfig::caloAlg, DecodeCTP(), calo::CalorimetryAlg::dEdx_AREA(), tca::TP3D::Dir, E, evt, tca::TP3D::Flags, kEnvOverlap, kTP3DGood, geo::WireReadoutGeom::Plane(), geo::PlaneID::Plane, tca::TCSlice::slHits, tcc, geo::PlaneGeo::ThetaZ(), tca::TP3D::TjID, tca::TCSlice::tjs, tca::TP3D::TPIndex, tca::TCConfig::unitsPerTick, geo::PlaneGeo::WirePitch(), and tca::TCConfig::wireReadoutGeom.

Referenced by AddPointsInRange(), lar::example::AnalysisExample::analyze(), Average_dEdX(), detinfo::DetectorPropertiesStandard::BirksCorrection(), calo::CalorimetryAlg::BirksCorrection(), lar_pandora::LArPandoraShowerCreation::BuildShower(), larg4::ISCalcSeparate::CalcIon(), larg4::ISCalcCorrelated::CalcIonAndScint(), mvapid::MVAAlg::CalcSegmentdEdxDist(), ShowerRecoTools::ShowerUnidirectiondEdx::CalculateElement(), ShowerRecoTools::ShowerTrajPointdEdx::CalculateElement(), detsim::ISCalculationSeparate::CalculateIonization(), larg4::ISCalculationSeparate::CalculateIonizationAndScintillation(), larg4::ISCalculationCorrelated::CalculateIonizationAndScintillation(), evd::AnalysisBaseDrawer::CalorShower(), opdet::FlashHypothesisCreator::CreateFlashHypothesesFromSegment(), DotProd(), evd::AnalysisBaseDrawer::DrawDeDx(), evd::AnalysisBaseDrawer::DrawKineticEnergy(), sim::DumpMCTracks::DumpMCTrack(), FilldEdx(), ShowerRecoTools::ShowerTrajPointdEdx::FinddEdxLength(), opdet::FlashHypothesisCalculator::FlashHypothesisCalculator(), opdet::FlashHypothesisCreator::FlashHypothesisCreator(), shwf::ShowerReco::LongTransEnergy(), shower::EMShowerAlg::MakeShower(), detinfo::DetectorPropertiesStandard::ModBoxCorrection(), calo::CalorimetryAlg::ModBoxCorrection(), PrintTP3Ds(), calo::ShowerCalorimetry::produce(), calo::Calorimetry::produce(), trkf::Track3DKalmanSPS::produce(), calo::GnocchiCalorimetry::produce(), sim::MCTrackRecoAlg::Reconstruct(), showerreco::ShowerRecoAlg::RecoOneShower(), and pid::PIDAAlg::RunPIDAAlg().

2675  {
2676  if (!tp3d.Flags[kTP3DGood]) return 0;
2677  if (tp3d.TjID > (int)slc.slHits.size()) return 0;
2678  if (tp3d.TjID <= 0) return 0;
2679 
2680  auto& tp = slc.tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
2681  if (tp.Environment[kEnvOverlap]) return 0;
2682 
2683  double dQ = 0.;
2684  double time = 0;
2685  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2686  if (!tp.UseHit[ii]) continue;
2687  auto& hit = (*evt.allHits)[slc.slHits[tp.Hits[ii]].allHitsIndex];
2688  dQ += hit.Integral();
2689  } // ii
2690  time = tp.Pos[1] / tcc.unitsPerTick;
2691  geo::PlaneID plnID = DecodeCTP(tp.CTP);
2692  if (dQ == 0) return 0;
2693  double angleToVert = tcc.wireReadoutGeom->Plane(plnID).ThetaZ() - 0.5 * ::util::pi<>();
2694  double cosgamma =
2695  std::abs(std::sin(angleToVert) * tp3d.Dir[1] + std::cos(angleToVert) * tp3d.Dir[2]);
2696  if (cosgamma < 1.E-5) return 0;
2697  double dx = tcc.wireReadoutGeom->Plane(plnID).WirePitch() / cosgamma;
2698  double dQdx = dQ / dx;
2699  double t0 = 0;
2700  float dedx = tcc.caloAlg->dEdx_AREA(clockData, detProp, dQdx, time, plnID.Plane, t0);
2701  if (std::isinf(dedx)) dedx = 0;
2702  return dedx;
2703  } // dEdx
calo::CalorimetryAlg * caloAlg
Definition: DataStructs.h:569
code to link reconstructed objects back to the MC truth information
const geo::WireReadoutGeom * wireReadoutGeom
Definition: DataStructs.h:568
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
constexpr auto abs(T v)
Returns the absolute value of the argument.
double ThetaZ() const
Angle of the wires from positive z axis; .
Definition: PlaneGeo.cxx:549
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
Float_t E
Definition: plot.C:20
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
Detector simulation of raw signals on wires.
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
double dEdx_AREA(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop, recob::Hit const &hit, double pitch, double T0=0) const
PlaneGeo const & Plane(TPCID const &tpcid, View_t view) const
Returns the specified wire.
TCEvent evt
Definition: DataStructs.cxx:8
double WirePitch() const
Return the wire pitch (in centimeters). It is assumed constant.
Definition: PlaneGeo.h:312
void tca::DefineDontCluster ( TCSlice slc,
bool  prt 
)
void tca::DefineEnvelope ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct ss,
bool  prt 
)

Definition at line 3442 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, if(), tca::ShowerStruct::NeedsUpdate, tca::TrajPoint::Pos, PosSep(), tca::Trajectory::Pts, tca::TCConfig::showerTag, tca::ShowerStruct::ShowerTjID, sn, tcc, tca::ShowerStruct::TjIDs, tca::TCSlice::tjs, and tca::TCConfig::unitsPerTick.

Referenced by ReverseShower(), and UpdateShower().

3443  {
3444 
3445  if (ss.ID == 0) return;
3446  if (ss.TjIDs.empty()) return;
3447  Trajectory& stj = slc.tjs[ss.ShowerTjID - 1];
3448  // shower Tj isn't fully defined yet
3449  if (stj.Pts[0].Pos[0] == 0) return;
3450 
3451  std::string fcnLabel = inFcnLabel + ".DE";
3452 
3453  ss.Envelope.resize(4);
3454  TrajPoint& stp0 = stj.Pts[0];
3455  TrajPoint& stp1 = stj.Pts[1];
3456  TrajPoint& stp2 = stj.Pts[2];
3457 
3458  // construct the Envelope polygon. Start with a rectangle using the fixed 1/2 width fcl input
3459  // expanded by the rms width at each end to create a polygon. The polygon is constructed along
3460  // the Pos[0] direction and then rotated into the ShowerTj direction. Use sTp1 as the origin.
3461  // First vertex
3462  ss.Envelope[0][0] = -PosSep(stp0.Pos, stp1.Pos);
3463  ss.Envelope[0][1] = tcc.showerTag[5] + tcc.showerTag[4] * stp0.DeltaRMS;
3464  // second vertex
3465  ss.Envelope[1][0] = PosSep(stp1.Pos, stp2.Pos);
3466  ss.Envelope[1][1] = tcc.showerTag[5] + tcc.showerTag[4] * stp2.DeltaRMS;
3467  // third and fourth are reflections of the first and second
3468  ss.Envelope[2][0] = ss.Envelope[1][0];
3469  ss.Envelope[2][1] = -ss.Envelope[1][1];
3470  ss.Envelope[3][0] = ss.Envelope[0][0];
3471  ss.Envelope[3][1] = -ss.Envelope[0][1];
3472 
3473  float length = ss.Envelope[1][0] - ss.Envelope[0][0];
3474  float width = ss.Envelope[0][1] + ss.Envelope[1][1];
3475  ss.EnvelopeArea = length * width;
3476 
3477  // Rotate into the stp1 coordinate system
3478  float cs = cos(stp1.Ang);
3479  float sn = sin(stp1.Ang);
3480  for (auto& vtx : ss.Envelope) {
3481  // Rotate along the stj shower axis
3482  float pos0 = cs * vtx[0] - sn * vtx[1];
3483  float pos1 = sn * vtx[0] + cs * vtx[1];
3484  // translate
3485  vtx[0] = pos0 + stp1.Pos[0];
3486  vtx[1] = pos1 + stp1.Pos[1];
3487  } // vtx
3488  // Find the charge density inside the envelope
3489  ss.ChgDensity = (stp0.Chg + stp1.Chg + stp2.Chg) / ss.EnvelopeArea;
3490  if (prt) {
3491  mf::LogVerbatim myprt("TC");
3492  myprt << fcnLabel << " 2S" << ss.ID << " Envelope";
3493  for (auto& vtx : ss.Envelope)
3494  myprt << " " << (int)vtx[0] << ":" << (int)(vtx[1] / tcc.unitsPerTick);
3495  myprt << " Area " << (int)ss.EnvelopeArea;
3496  myprt << " ChgDensity " << ss.ChgDensity;
3497  }
3498  // This is the last function used to update a shower
3499  ss.NeedsUpdate = false;
3500  } // DefineEnvelope
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:549
if(nlines<=0)
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
Float_t sn
Definition: plot.C:23
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
void tca::DefineHitPos ( TCSlice slc,
TrajPoint tp 
)

Definition at line 1791 of file StepUtils.cxx.

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

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

1792  {
1793  // defines HitPos, HitPosErr2 and Chg for the used hits in the trajectory point
1794 
1795  tp.Chg = 0;
1796  if (tp.Hits.empty()) return;
1797 
1798  unsigned short nused = 0;
1799  unsigned int iht = 0;
1800  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1801  if (!tp.UseHit[ii]) continue;
1802  ++nused;
1803  iht = tp.Hits[ii];
1804  if (iht >= slc.slHits.size()) return;
1805  if (slc.slHits[iht].allHitsIndex >= (*evt.allHits).size()) return;
1806  }
1807  if (nused == 0) return;
1808 
1809  // don't bother with rest of this if there is only one hit since it can
1810  // only reside on one wire
1811  if (nused == 1) {
1812  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1813  tp.Chg = hit.Integral();
1814  tp.HitPos[0] = hit.WireID().Wire;
1815  tp.HitPos[1] = hit.PeakTime() * tcc.unitsPerTick;
1816  if (LongPulseHit(hit)) {
1817  // give it a huge error^2 since the position is not well defined
1818  tp.HitPosErr2 = 100;
1819  }
1820  else {
1821  // Normalize to 1 WSE path length
1822  float pathInv = std::abs(tp.Dir[0]);
1823  if (pathInv < 0.05) pathInv = 0.05;
1824  tp.Chg *= pathInv;
1825  float wireErr = tp.Dir[1] * 0.289;
1826  float timeErr = tp.Dir[0] * HitTimeErr(slc, iht);
1827  tp.HitPosErr2 = wireErr * wireErr + timeErr * timeErr;
1828  }
1829  if (tcc.dbgStp)
1830  mf::LogVerbatim("TC") << "DefineHitPos: singlet " << std::fixed << std::setprecision(1)
1831  << tp.HitPos[0] << ":" << (int)(tp.HitPos[1] / tcc.unitsPerTick)
1832  << " ticks. HitPosErr " << sqrt(tp.HitPosErr2);
1833  return;
1834  } // nused == 1
1835 
1836  // multiple hits possibly on different wires
1837  std::vector<unsigned int> hitVec;
1838  tp.Chg = 0;
1839  std::array<float, 2> newpos;
1840  float chg;
1841  newpos[0] = 0;
1842  newpos[1] = 0;
1843  // Find the wire range for hits used in the TP
1844  unsigned int loWire = INT_MAX;
1845  unsigned int hiWire = 0;
1846  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1847  if (!tp.UseHit[ii]) continue;
1848  unsigned int iht = tp.Hits[ii];
1849  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1850  chg = hit.Integral();
1851  unsigned int wire = hit.WireID().Wire;
1852  if (wire < loWire) loWire = wire;
1853  if (wire > hiWire) hiWire = wire;
1854  newpos[0] += chg * wire;
1855  newpos[1] += chg * hit.PeakTime();
1856  tp.Chg += chg;
1857  hitVec.push_back(iht);
1858  } // ii
1859 
1860  if (tp.Chg == 0) return;
1861 
1862  tp.HitPos[0] = newpos[0] / tp.Chg;
1863  tp.HitPos[1] = newpos[1] * tcc.unitsPerTick / tp.Chg;
1864  // Normalize to 1 WSE path length
1865  float pathInv = std::abs(tp.Dir[0]);
1866  if (pathInv < 0.05) pathInv = 0.05;
1867  tp.Chg *= pathInv;
1868  // Error is the wire error (1/sqrt(12))^2 if all hits are on one wire.
1869  // Scale it by the wire range
1870  float dWire = 1 + hiWire - loWire;
1871  float wireErr = tp.Dir[1] * dWire * 0.289;
1872  float timeErr2 = tp.Dir[0] * tp.Dir[0] * HitsTimeErr2(slc, hitVec);
1873  tp.HitPosErr2 = wireErr * wireErr + timeErr2;
1874  if (tcc.dbgStp)
1875  mf::LogVerbatim("TC") << "DefineHitPos: multiplet " << std::fixed << std::setprecision(1)
1876  << tp.HitPos[0] << ":" << (int)(tp.HitPos[1] / tcc.unitsPerTick)
1877  << " ticks. HitPosErr " << sqrt(tp.HitPosErr2);
1878 
1879  } // DefineHitPos
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
float HitTimeErr(const TCSlice &slc, unsigned int iht)
Definition: StepUtils.cxx:1654
constexpr auto abs(T v)
Returns the absolute value of the argument.
bool LongPulseHit(const recob::Hit &hit)
Definition: Utils.cxx:4317
float HitsTimeErr2(const TCSlice &slc, const std::vector< unsigned int > &hitVec)
Definition: StepUtils.cxx:1662
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
void tca::DefinePFPParents ( TCSlice slc)

Definition at line 2860 of file PFPUtils.cxx.

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

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

2861  {
2862  /*
2863  This function reconciles vertices, PFParticles and slc, then
2864  defines the parent (j) - daughter (i) relationship and PDGCode. Here is a
2865  description of the conventions:
2866 
2867  V1 is the highest score 3D vertex in this tpcid so a neutrino PFParticle P1 is defined.
2868  V4 is a high-score vertex that has lower score than V1. It is declared to be a
2869  primary vertex because its score is higher than V5 and it is not associated with the
2870  neutrino interaction
2871  V6 was created to adhere to the convention that all PFParticles, in this case P9,
2872  be associated with a start vertex. There is no score for V6. P9 is it's own parent
2873  but is not a primary PFParticle.
2874 
2875  P1 - V1 - P2 - V2 - P4 - V3 - P5 V4 - P6 V6 - P9
2876  \ \
2877  P3 P7 - V5 - P8
2878 
2879  The PrimaryID in this table is the ID of the PFParticle that is attached to the
2880  primary vertex, which may or may not be a neutrino interaction vertex.
2881  The PrimaryID is returned by the PrimaryID function
2882  PFP parentID DtrIDs PrimaryID
2883  -----------------------------------
2884  P1 P1 P2, P3 P1
2885  P2 P1 P4 P2
2886  P3 P1 none P3
2887  P4 P2 P5 P2
2888  P5 P4 none P2
2889 
2890  P6 P6 none P6
2891  P7 P7 P8 P7
2892 
2893  P9 P9 none 0
2894 
2895  */
2896  if (slc.pfps.empty()) return;
2897  if (tcc.modes[kTestBeam]) return;
2898 
2899  int neutrinoPFPID = 0;
2900  for (auto& pfp : slc.pfps) {
2901  if (pfp.ID == 0) continue;
2902  if (!tcc.modes[kTestBeam] && neutrinoPFPID == 0 && (pfp.PDGCode == 12 || pfp.PDGCode == 14)) {
2903  neutrinoPFPID = pfp.ID;
2904  break;
2905  }
2906  } // pfp
2907 
2908  // define the end vertex if the Tjs have end vertices
2909  constexpr unsigned short end1 = 1;
2910  for (auto& pfp : slc.pfps) {
2911  if (pfp.ID == 0) continue;
2912  // already done?
2913  if (pfp.Vx3ID[end1] > 0) continue;
2914  // ignore shower-like pfps
2915  if (IsShowerLike(slc, pfp.TjIDs)) continue;
2916  // count 2D -> 3D matched vertices
2917  unsigned short cnt3 = 0;
2918  unsigned short vx3id = 0;
2919  // list of unmatched 2D vertices that should be merged
2920  std::vector<int> vx2ids;
2921  for (auto tjid : pfp.TjIDs) {
2922  auto& tj = slc.tjs[tjid - 1];
2923  if (tj.VtxID[end1] == 0) continue;
2924  auto& vx2 = slc.vtxs[tj.VtxID[end1] - 1];
2925  if (vx2.Vx3ID == 0) {
2926  if (vx2.Topo == 1 && vx2.NTraj == 2) vx2ids.push_back(vx2.ID);
2927  continue;
2928  }
2929  if (vx3id == 0) vx3id = vx2.Vx3ID;
2930  if (vx2.Vx3ID == vx3id) ++cnt3;
2931  } // tjid
2932  if (cnt3 > 1) {
2933  // ensure it isn't attached at the other end
2934  if (pfp.Vx3ID[1 - end1] == vx3id) continue;
2935  pfp.Vx3ID[end1] = vx3id;
2936  } // cnt3 > 1
2937  } // pfp
2938 
2939  // Assign a PDGCode to each PFParticle and look for a parent
2940  for (auto& pfp : slc.pfps) {
2941  if (pfp.ID == 0) continue;
2942  // skip a neutrino PFParticle
2943  if (pfp.PDGCode == 12 || pfp.PDGCode == 14 || pfp.PDGCode == 22) continue;
2944  // Define a PFP parent if there are two or more Tjs that are daughters of
2945  // Tjs that are used by the same PFParticle
2946  int pfpParentID = INT_MAX;
2947  unsigned short nParent = 0;
2948  for (auto tjid : pfp.TjIDs) {
2949  auto& tj = slc.tjs[tjid - 1];
2950  if (tj.ParentID <= 0) continue;
2951  auto parPFP = GetAssns(slc, "T", tj.ParentID, "P");
2952  if (parPFP.empty()) continue;
2953  if (pfpParentID == INT_MAX) pfpParentID = parPFP[0];
2954  if (parPFP[0] == pfpParentID) ++nParent;
2955  } // ii
2956  if (nParent > 1) {
2957  auto& ppfp = slc.pfps[pfpParentID - 1];
2958  // set the parent UID
2959  pfp.ParentUID = ppfp.UID;
2960  // add to the parent daughters list
2961  ppfp.DtrUIDs.push_back(pfp.UID);
2962  } // nParent > 1
2963  } // ipfp
2964  // associate primary PFParticles with a neutrino PFParticle
2965  if (neutrinoPFPID > 0) {
2966  auto& neutrinoPFP = slc.pfps[neutrinoPFPID - 1];
2967  int vx3id = neutrinoPFP.Vx3ID[1];
2968  for (auto& pfp : slc.pfps) {
2969  if (pfp.ID == 0 || pfp.ID == neutrinoPFPID) continue;
2970  if (pfp.Vx3ID[0] != vx3id) continue;
2971  pfp.ParentUID = (size_t)neutrinoPFPID;
2972  neutrinoPFP.DtrUIDs.push_back(pfp.ID);
2973  if (pfp.PDGCode == 111) neutrinoPFP.PDGCode = 12;
2974  } // pfp
2975  } // neutrino PFP exists
2976  } // DefinePFPParents
Expect tracks entering from the front face. Don&#39;t create neutrino PFParticles.
Definition: DataStructs.h:523
TCConfig tcc
Definition: DataStructs.cxx:9
bool IsShowerLike(TCSlice const &slc, std::vector< int > const &TjIDs)
Definition: TCShower.cxx:1891
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
std::vector< int > GetAssns(TCSlice const &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4704
void tca::DefineTjParents ( TCSlice slc,
bool  prt 
)

Definition at line 173 of file Utils.cxx.

References CreatePFP(), util::end(), GetVtxTjIDs(), kDeltaRay, kHaloTj, kKilled, kNeedsUpdate, kTestBeam, tca::TCConfig::match3DCuts, tca::TCConfig::modes, ReverseTraj(), StorePFP(), tcc, tca::TCSlice::tjs, TrajTrajDOCA(), tca::detail::valsDecreasing(), tca::TCConfig::vtx2DCuts, tca::TCSlice::vtx3s, and tca::TCSlice::vtxs.

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

174  {
175  /*
176  This function sets the ParentUID of Tjs in this tpcid to create a hierarchy. The highest Score
177  3D vertex in a chain of Tjs and vertices is declared the primary vertex; vx3.Primary = true. Tjs directly attached
178  to that vertex are declared Primary trajectories with ParentUID = 0. All other Tjs in the chain have ParentUID
179  set to the next upstream Tj to which it is attached by a vertex. In the graphical description below, V1 and V4 are
180  2D vertices that are matched to a high-score 3D vertex. The V1 Score is greater than the V2 Score and V3 Score.
181  V1 and V4 are declared to be primary vertices. T1, T2, T6 and T7 are declared to be primary Tjs
182 
183  V1 - T1 - V2 - T3 V4 - T6 / T8
184  \ \ /
185  T2 - V3 - T4 T7
186  \
187  T5
188 
189  This is represented as follows. The NeutrinoPrimaryTjID is defined by a function.
190  Tj ParentUID NeutrinoPrimaryTjID
191  -----------------------------------
192  T1 0 T1
193  T2 0 T2
194  T3 T1 T2
195  T4 T2 T2
196  T5 T2 T2
197  T6 0 -1
198  T7 0 -1
199  T8 -1 -1
200 */
201 
202  // don't do anything if this is test beam data
203  if (tcc.modes[kTestBeam]) return;
204 
205  // clear old information
206  for (auto& tj : slc.tjs) {
207  if (tj.AlgMod[kKilled]) continue;
208  // ignore delta rays
209  if (tj.AlgMod[kDeltaRay] || tj.AlgMod[kHaloTj]) continue;
210  tj.ParentID = 0;
211  } // tj
212 
213  // sort vertice by decreasing score
214  std::vector<int> temp;
215  for (auto& vx3 : slc.vtx3s) {
216  if (vx3.ID == 0) continue;
217  // clear the Primary flag while we are here
218  vx3.Primary = false;
219  temp.push_back(vx3.ID);
220  } // vx3
221  if (temp.empty()) return;
222 
223  // Make a master list of all Tjs that are attached to these vertices
224  std::vector<int> masterlist;
225  for (auto vx3id : temp) {
226  auto& vx3 = slc.vtx3s[vx3id - 1];
227  float score;
228  auto tjlist = GetVtxTjIDs(slc, vx3, score);
229  for (auto tjid : tjlist) {
230  auto& tj = slc.tjs[tjid - 1];
231  if (tj.ParentID != 0) tj.ParentID = 0;
232  if (std::find(masterlist.begin(), masterlist.end(), tjid) == masterlist.end())
233  masterlist.push_back(tjid);
234  } // tjid
235  } // vxid
236  if (prt) {
237  mf::LogVerbatim myprt("TC");
238  myprt << "DTP: masterlist Tjs";
239  for (auto tjid : masterlist)
240  myprt << " " << tjid;
241  }
242 
243  // Do the sort
244  std::vector<SortEntry> sortVec(temp.size());
245  for (unsigned short indx = 0; indx < temp.size(); ++indx) {
246  auto& vx3 = slc.vtx3s[temp[indx] - 1];
247  sortVec[indx].index = indx;
248  sortVec[indx].val = vx3.Score;
249  } // indx
250  if (sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(), valsDecreasing);
251  // put them into order
252  auto vlist = temp;
253  for (unsigned short indx = 0; indx < temp.size(); ++indx)
254  vlist[indx] = temp[sortVec[indx].index];
255 
256  // make a neutrino PFParticle to associate with the highest score vertex if it is high enough
257  if (tcc.match3DCuts[0] > 0) {
258  auto& vx3 = slc.vtx3s[vlist[0] - 1];
259  if (vx3.Score > tcc.vtx2DCuts[7]) {
260  auto neutrinoPFP = CreatePFP(slc);
261  // call it the neutrino vertex
262  vx3.Neutrino = true;
263  // put the vertex at the end of the neutrino
264  auto& sf = neutrinoPFP.SectionFits[0];
265  sf.Pos[0] = vx3.X;
266  sf.Pos[1] = vx3.Y;
267  sf.Pos[2] = vx3.Z;
268  sf.Dir[2] = 1;
269  // This may be set to 12 later on if a primary shower is reconstructed
270  neutrinoPFP.PDGCode = 14;
271  neutrinoPFP.Vx3ID[1] = vx3.ID;
272  neutrinoPFP.Vx3ID[0] = vx3.ID;
273  neutrinoPFP.Flags[kNeedsUpdate] = false;
274  // the rest of this will be defined later
275  if (!StorePFP(slc, neutrinoPFP)) return;
276  }
277  } // User wants to make PFParticles
278  // a temp vector to ensure that we only consider a vertex once
279  std::vector<bool> lookedAt3(slc.vtx3s.size() + 1, false);
280  std::vector<bool> lookedAt2(slc.vtxs.size() + 1, false);
281  // vector of parent-daughter pairs
282  std::vector<std::pair<int, int>> pardtr;
283  // Start with the highest score vertex
284  for (unsigned short indx = 0; indx < vlist.size(); ++indx) {
285  auto& vx3 = slc.vtx3s[vlist[indx] - 1];
286  if (lookedAt3[vx3.ID]) continue;
287  vx3.Primary = true;
288  lookedAt3[vx3.ID] = true;
289  // make a list of Tjs attached to this vertex
290  float score;
291  auto primTjList = GetVtxTjIDs(slc, vx3, score);
292  if (primTjList.empty()) continue;
293  pardtr.clear();
294  for (auto primTjID : primTjList) {
295  auto& primTj = slc.tjs[primTjID - 1];
296  // This isn't a primary tj if the parent ID isn't -1
297  if (primTj.ParentID != -1) continue;
298  if (prt) mf::LogVerbatim("TC") << "Vx3 " << vx3.ID << " Primary tj " << primTj.ID;
299  // declare this a primary tj
300  primTj.ParentID = 0;
301  // look for daughter tjs = those that are attached to a 2D vertex
302  // at the other end
303  for (unsigned short end = 0; end < 2; ++end) {
304  if (primTj.VtxID[end] == 0) continue;
305  auto& vx2 = slc.vtxs[primTj.VtxID[end] - 1];
306  if (vx2.Vx3ID == vx3.ID) continue;
307  // found a 2D vertex. Check for daughters
308  auto dtrList = GetVtxTjIDs(slc, vx2);
309  for (auto dtrID : dtrList) {
310  // ignore the primary tj
311  if (dtrID == primTjID) continue;
312  auto& dtj = slc.tjs[dtrID - 1];
313  if (dtj.ParentID != -1) continue;
314  pardtr.push_back(std::make_pair(primTjID, dtrID));
315  if (prt) mf::LogVerbatim("TC") << " primTj " << primTjID << " dtrID " << dtrID;
316  } // tjid
317  } // end
318  // Ensure that end 0 of the trajectory is attached to the primary vertex
319  for (unsigned short end = 0; end < 2; ++end) {
320  if (primTj.VtxID[end] == 0) continue;
321  auto& vx2 = slc.vtxs[primTj.VtxID[end] - 1];
322  if (vx2.Vx3ID == vx3.ID && end != 0) ReverseTraj(primTj);
323  } // end
324  } // tjid
325  if (pardtr.empty()) continue;
326  if (prt) {
327  mf::LogVerbatim myprt("TC");
328  myprt << " par_dtr";
329  for (auto pdtr : pardtr)
330  myprt << " " << pdtr.first << "_" << pdtr.second;
331  }
332  // iterate through the parent - daughter stack, removing the last pair when a
333  // ParentID is updated and adding pairs for new daughters
334  for (unsigned short nit = 0; nit < 100; ++nit) {
335  auto lastPair = pardtr[pardtr.size() - 1];
336  auto& dtj = slc.tjs[lastPair.second - 1];
337  dtj.ParentID = lastPair.first;
338  // reverse the daughter trajectory if necessary so that end 0 is closest to the parent
339  float doca = 100;
340  unsigned short dpt = 0, ppt = 0;
341  auto& ptj = slc.tjs[lastPair.first - 1];
342  // find the point on the daughter tj that is closest to the parent
343  TrajTrajDOCA(slc, dtj, ptj, dpt, ppt, doca);
344  // reverse the daughter if the closest point is near end 1 of the daughter
345  if (prt) mf::LogVerbatim("TC") << "Set parent " << ptj.ID << " dtr " << dtj.ID;
346  // remove that entry
347  pardtr.pop_back();
348  // Add entries for new daughters
349  for (unsigned short end = 0; end < 2; ++end) {
350  if (dtj.VtxID[end] == 0) continue;
351  auto& vx2 = slc.vtxs[dtj.VtxID[end] - 1];
352  if (lookedAt2[vx2.ID]) continue;
353  lookedAt2[vx2.ID] = true;
354  auto tjlist = GetVtxTjIDs(slc, vx2);
355  for (auto tjid : tjlist) {
356  if (tjid == dtj.ID || tjid == ptj.ID) continue;
357  pardtr.push_back(std::make_pair(dtj.ID, tjid));
358  if (prt) {
359  mf::LogVerbatim myprt("TC");
360  myprt << " add par_dtr";
361  for (auto pdtr : pardtr)
362  myprt << " " << pdtr.first << "_" << pdtr.second;
363  }
364  }
365  } // end
366  if (pardtr.empty()) break;
367  } // nit
368  } // indx
369  // check the master list
370  for (auto tjid : masterlist) {
371  auto& tj = slc.tjs[tjid - 1];
372  if (tj.ParentID < 0) tj.ParentID = tj.ID;
373  } // tjid
374 
375  } // DefineTjParents
Expect tracks entering from the front face. Don&#39;t create neutrino PFParticles.
Definition: DataStructs.h:523
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
PFPStruct CreatePFP(const TCSlice &slc)
Definition: PFPUtils.cxx:2802
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
std::vector< float > match3DCuts
3D matching cuts
Definition: DataStructs.h:551
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
bool TrajTrajDOCA(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep, bool considerDeadWires)
Definition: Utils.cxx:2418
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const VtxStore &vx2)
Definition: TCVertex.cxx:2807
bool valsDecreasing(const SortEntry &c1, const SortEntry &c2)
Definition: Utils.cxx:39
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:541
bool StorePFP(TCSlice &slc, PFPStruct &pfp)
Definition: PFPUtils.cxx:2979
void ReverseTraj(Trajectory &tj)
Definition: Utils.cxx:3219
double tca::DeltaAngle ( const Vector3_t  v1,
const Vector3_t  v2 
)

Definition at line 2531 of file PFPUtils.cxx.

References DotProd().

Referenced by CompatibleMerge(), DotProd(), EndMerge(), FindHammerVertices(), FindHammerVertices2(), KinkSignificance(), LastEndMerge(), ParentFOM(), PointInsideEnvelope(), SetVx2Score(), SplitTrajCrossingVertices(), and StepAway().

2532  {
2533  if (v1[0] == v2[0] && v1[1] == v2[1] && v1[2] == v2[2]) return 0;
2534  return acos(DotProd(v1, v2));
2535  }
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:126
double tca::DeltaAngle ( const Point2_t p1,
const Point2_t p2 
)

Definition at line 3303 of file Utils.cxx.

References DeltaAngle2().

3304  {
3305  // angle between two points
3306  double ang1 = atan2(p1[1], p1[0]);
3307  double ang2 = atan2(p2[1], p2[0]);
3308  return DeltaAngle2(ang1, ang2);
3309  } // DeltaAngle
double DeltaAngle2(double Ang1, double Ang2)
Definition: Utils.cxx:3312
double tca::DeltaAngle ( double  Ang1,
double  Ang2 
)

Definition at line 3324 of file Utils.cxx.

References util::abs().

3325  {
3326  return std::abs(std::remainder(Ang1 - Ang2, M_PI));
3327  }
constexpr auto abs(T v)
Returns the absolute value of the argument.
double tca::DeltaAngle2 ( double  Ang1,
double  Ang2 
)

Definition at line 3312 of file Utils.cxx.

Referenced by DeltaAngle(), and DotProd().

3313  {
3314  constexpr double twopi = 2 * M_PI;
3315  double dang = Ang1 - Ang2;
3316  while (dang > M_PI)
3317  dang -= twopi;
3318  while (dang < -M_PI)
3319  dang += twopi;
3320  return dang;
3321  }
Vector3_t tca::DirAtEnd ( const PFPStruct pfp,
unsigned short  end 
)

Definition at line 3249 of file PFPUtils.cxx.

References tca::PFPStruct::SectionFits.

Referenced by AttachToAnyVertex(), DotProd(), FindParent(), PrintP(), PrintPFP(), cluster::TrajCluster::produce(), SetParent(), and StitchPFPs().

3250  {
3251  if (end > 1 || pfp.SectionFits.empty()) return {{0., 0., 0.}};
3252  if (end == 0) return pfp.SectionFits[0].Dir;
3253  return pfp.SectionFits[pfp.SectionFits.size() - 1].Dir;
3254  } // PosAtEnd
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
bool tca::DontCluster ( TCSlice const &  slc,
const std::vector< int > &  tjlist1,
const std::vector< int > &  tjlist2 
)

Definition at line 3213 of file TCShower.cxx.

References tca::TCSlice::dontCluster.

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

3216  {
3217  // returns true if a pair of tjs in the two lists are in the dontCluster vector
3218  if (tjlist1.empty() || tjlist2.empty()) return false;
3219  if (slc.dontCluster.empty()) return false;
3220  for (auto tid1 : tjlist1) {
3221  for (auto tid2 : tjlist2) {
3222  int ttid1 = tid1;
3223  if (ttid1 > tid2) std::swap(ttid1, tid2);
3224  for (auto& dc : slc.dontCluster)
3225  if (dc.TjIDs[0] == ttid1 && dc.TjIDs[1] == tid2) return true;
3226  } // dc
3227  } // tid1
3228  return false;
3229  } // DontCluster
void swap(lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &a, lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &b)
void tca::DumpShowerPts ( std::string  inFcnLabel,
TCSlice slc,
int  cotID 
)
void tca::DumpShowerPts ( TCSlice slc,
int  cotID 
)

Definition at line 3823 of file TCShower.cxx.

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

3824  {
3825  // Print the shower points to the screen. The user should probably pipe the output to a text file
3826  // then grep this file for the character string PTS which is piped to a text file which can then be
3827  // imported into Excel, etc
3828  // Finds the charge at the start of a shower
3829  if (cotID > (int)slc.cots.size()) return;
3830 
3831  ShowerStruct& ss = slc.cots[cotID - 1];
3832  if (ss.ID == 0) return;
3833  if (ss.TjIDs.empty()) return;
3834  std::cout << "PTS Pos0 Pos1 RPos0 RPos1 Chg TID\n";
3835  for (auto& pt : ss.ShPts) {
3836  std::cout << "PTS " << std::fixed << std::setprecision(1) << pt.Pos[0] << " " << pt.Pos[1]
3837  << " " << pt.RotPos[0] << " " << pt.RotPos[1];
3838  std::cout << " " << (int)pt.Chg << " " << pt.TID;
3839  std::cout << "\n";
3840  }
3841 
3842  } // DumpShowerPts
TMarker * pt
Definition: egs.C:25
void tca::DumpTj ( )

Definition at line 5251 of file Utils.cxx.

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

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

5252  {
5253  // Dump all of the points in a trajectory to the output in a form that can
5254  // be imported by another application, e.g. Excel
5255  // Search for the trajectory with the specified WorkID or Unique ID
5256 
5257  for (auto const& slc : slices) {
5258  for (auto& tj : slc.tjs) {
5259  if (tj.WorkID != debug.WorkID && tj.UID != debug.WorkID) continue;
5260  // print a header
5261  std::ofstream outfile;
5262  std::string fname = "tcdump" + std::to_string(tj.UID) + ".csv";
5263  outfile.open(fname, std::ios::out | std::ios::trunc);
5264  outfile << "Dump trajectory T" << tj.UID << " WorkID " << tj.WorkID;
5265  outfile << " ChgRMS " << std::setprecision(2) << tj.ChgRMS;
5266  outfile << "\n";
5267  outfile << "Wire, Chg T" << tj.UID
5268  << ", totChg, Tick, Delta, NTPsFit, Ang, ChiDOF, KinkSig, HitPosErr\n";
5269  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
5270  auto& tp = tj.Pts[ipt];
5271  outfile << std::fixed;
5272  outfile << std::setprecision(0) << std::nearbyint(tp.Pos[0]);
5273  outfile << "," << (int)tp.Chg;
5274  // total charge near the TP
5275  float totChg = 0;
5276  for (auto iht : tp.Hits) {
5277  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
5278  totChg += hit.Integral();
5279  }
5280  outfile << "," << (int)totChg;
5281  outfile << "," << std::setprecision(0) << std::nearbyint(tp.Pos[1] / tcc.unitsPerTick);
5282  outfile << "," << std::setprecision(2) << tp.Delta;
5283  outfile << "," << tp.NTPsFit;
5284  outfile << "," << std::setprecision(3) << tp.Ang;
5285  outfile << "," << std::setprecision(2) << tp.FitChi;
5286  outfile << "," << std::setprecision(2) << tp.KinkSig;
5287  outfile << "," << std::setprecision(2) << sqrt(tp.HitPosErr2);
5288  outfile << "\n";
5289  } // ipt
5290  outfile.close();
5291  std::cout << "Points on T" << tj.UID << " dumped to " << fname << "\n";
5292  tcc.dbgDump = false;
5293  return;
5294  } // tj
5295  } // slc
5296 
5297  } // DumpTj
TCConfig tcc
Definition: DataStructs.cxx:9
for(Int_t i=0;i< nentries;i++)
Definition: comparison.C:30
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
int WorkID
Select the StartWorkID for debugging.
Definition: DebugStruct.h:28
DebugStuff debug
Definition: DebugStruct.cxx:4
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
float tca::ElectronLikelihood ( const TCSlice slc,
const Trajectory tj 
)

Definition at line 3144 of file Utils.cxx.

References util::abs(), tca::Trajectory::ChgRMS, tca::Trajectory::EndFlag, tca::Trajectory::EndPt, kBragg, NumPtsWithCharge(), and TjDeltaRMS().

Referenced by PDGCodeVote(), PrintT(), and SetPDGCode().

3145  {
3146  // returns a number between 0 (not electron-like) and 1 (electron-like)
3147  if (NumPtsWithCharge(slc, tj, false) < 8) return -1;
3148  if (tj.EndFlag[0][kBragg] || tj.EndFlag[1][kBragg]) return 0;
3149 
3150  unsigned short midPt = 0.5 * (tj.EndPt[0] + tj.EndPt[1]);
3151  double rms0 = 0, rms1 = 0;
3152  unsigned short cnt;
3153  TjDeltaRMS(tj, tj.EndPt[0], midPt, rms0, cnt);
3154  TjDeltaRMS(tj, midPt, tj.EndPt[1], rms1, cnt);
3155  float asym = std::abs(rms0 - rms1) / (rms0 + rms1);
3156  float chgFact = (tj.ChgRMS - 0.1) * 5;
3157  float elh = 5 * asym * chgFact;
3158  if (elh > 1) elh = 1;
3159  return elh;
3160  } // ElectronLikelihood
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:2080
constexpr auto abs(T v)
Returns the absolute value of the argument.
void TjDeltaRMS(const Trajectory &tj, unsigned short firstPt, unsigned short lastPt, double &rms, unsigned short &cnt)
Definition: Utils.cxx:3491
CTP_t tca::EncodeCTP ( const geo::PlaneID planeID)
inline

Definition at line 53 of file DataStructs.h.

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

54  {
55  return EncodeCTP(planeID.Cryostat, planeID.TPC, planeID.Plane);
56  }
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:195
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
CTP_t EncodeCTP(const geo::WireID &wireID)
Definition: DataStructs.h:57
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:315
CTP_t tca::EncodeCTP ( const geo::WireID wireID)
inline

Definition at line 57 of file DataStructs.h.

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

Referenced by EncodeCTP().

58  {
59  return EncodeCTP(wireID.Cryostat, wireID.TPC, wireID.Plane);
60  }
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:195
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
CTP_t EncodeCTP(const geo::WireID &wireID)
Definition: DataStructs.h:57
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:315
void tca::EndMerge ( TCSlice slc,
CTP_t  inCTP,
bool  lastPass 
)

Definition at line 3486 of file StepUtils.cxx.

References util::abs(), tca::TrajPoint::Ang, tca::TrajPoint::AngleCode, tca::TrajPoint::AveChg, tca::TCConfig::chargeCuts, ChgFracNearPos(), CompatibleMerge(), tca::DebugStuff::CTP, tca::VtxStore::CTP, tca::TCConfig::dbgMrg, tca::TCConfig::dbgSlc, DeadWireCount(), debug, DeltaAngle(), tca::TrajPoint::Dir, DotProd(), FitTraj(), FitVertex(), tca::VtxStore::ID, kAtKink, kBragg, kFixed, tca::TCConfig::kinkCuts, KinkSignificance(), kKilled, kMerge, kStepDir, MakeBareTrajPoint(), MakeVertexObsolete(), MergeAndStore(), tca::TCConfig::modes, tca::TrajPoint::NTPsFit, tca::VtxStore::NTraj, NumPtsWithCharge(), OverlapFraction(), tca::VtxStore::Pass, PointTrajDOCA(), tca::VtxStore::Pos, tca::TrajPoint::Pos, tca::VtxStore::PosErr, PosSep(), PosSep2(), PrintPos(), pt1, pt2, tca::TCConfig::qualityCuts, ReverseTraj(), SetVx2Score(), SignalBetween(), slices, tca::VtxStore::Stat, StoreVertex(), tcc, tca::TCSlice::tjs, tca::VtxStore::Topo, TrajIntersection(), TrajLength(), TrajTrajDOCA(), tca::TCConfig::unitsPerTick, tca::TCConfig::useAlg, tca::TCConfig::vtx2DCuts, and tca::TCSlice::vtxs.

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

3487  {
3488  // Merges trajectories end-to-end or makes vertices. Does a more careful check on the last pass
3489 
3490  if (slc.tjs.size() < 2) return;
3491  if (!tcc.useAlg[kMerge]) return;
3492 
3493  bool prt = (tcc.dbgMrg && tcc.dbgSlc && inCTP == debug.CTP);
3494  if (prt)
3495  mf::LogVerbatim("TC") << "inside EndMerge slice " << slices.size() - 1 << " inCTP " << inCTP
3496  << " nTjs " << slc.tjs.size() << " lastPass? " << lastPass;
3497 
3498  // Ensure that all tjs are in the same order
3499  short tccStepDir = 1;
3500  if (!tcc.modes[kStepDir]) tccStepDir = -1;
3501  for (auto& tj : slc.tjs) {
3502  if (tj.AlgMod[kKilled]) continue;
3503  if (tj.CTP != inCTP) continue;
3504  if (tj.StepDir != tccStepDir) ReverseTraj(tj);
3505  } // tj
3506 
3507  unsigned short maxShortTjLen = tcc.vtx2DCuts[0];
3508 
3509  // temp vector for checking the fraction of hits near a merge point
3510  std::vector<int> tjlist(2);
3511 
3512  float minChgRMS = 0.5 * (tcc.chargeCuts[1] + tcc.chargeCuts[2]);
3513 
3514  // iterate whenever a merge occurs since tjs will change. This is not necessary
3515  // when a vertex is created however.
3516  bool iterate = true;
3517  while (iterate) {
3518  iterate = false;
3519  for (unsigned int it1 = 0; it1 < slc.tjs.size(); ++it1) {
3520  auto* tj1 = &slc.tjs[it1];
3521  if (tj1->AlgMod[kKilled]) continue;
3522  if (tj1->CTP != inCTP) continue;
3523  // don't try to merge high energy electrons
3524  if (tj1->PDGCode == 111) continue;
3525  for (unsigned short end1 = 0; end1 < 2; ++end1) {
3526  // no merge if there is a vertex at the end
3527  if (tj1->VtxID[end1] > 0) continue;
3528  // make a copy of tp1 so we can mess with it
3529  TrajPoint tp1 = tj1->Pts[tj1->EndPt[end1]];
3530  // do a local fit on the lastpass only using the last 3 points
3531  if (lastPass && tp1.NTPsFit > 3) {
3532  // make a local copy of the tj
3533  auto ttj = slc.tjs[it1];
3534  auto& lastTP = ttj.Pts[ttj.EndPt[end1]];
3535  // fit the last 3 points
3536  lastTP.NTPsFit = 3;
3537  FitTraj(slc, ttj);
3538  tp1 = ttj.Pts[ttj.EndPt[end1]];
3539  } // last pass
3540  bool isVLA = (tp1.AngleCode == 2);
3541  float bestFOM = 5;
3542  if (isVLA) bestFOM = 20;
3543  float bestDOCA;
3544  unsigned int imbest = UINT_MAX;
3545  for (unsigned int it2 = 0; it2 < slc.tjs.size(); ++it2) {
3546  if (it1 == it2) continue;
3547  auto& tj2 = slc.tjs[it2];
3548  // check for consistent direction
3549  if (tj1->StepDir != tj2.StepDir) continue;
3550  if (tj2.AlgMod[kKilled]) continue;
3551  if (tj2.CTP != inCTP) continue;
3552  // don't try to merge high energy electrons
3553  if (tj2.PDGCode == 111) continue;
3554  float olf = OverlapFraction(*tj1, tj2);
3555  if (olf > 0.25) continue;
3556  unsigned short end2 = 1 - end1;
3557  // check for a vertex at this end
3558  if (tj2.VtxID[end2] > 0) continue;
3559  TrajPoint& tp2 = tj2.Pts[tj2.EndPt[end2]];
3560  TrajPoint& tp2OtherEnd = tj2.Pts[tj2.EndPt[end1]];
3561  // ensure that the other end isn't closer
3562  if (std::abs(tp2OtherEnd.Pos[0] - tp1.Pos[0]) < std::abs(tp2.Pos[0] - tp1.Pos[0]))
3563  continue;
3564  // ensure that the order is correct
3565  if (tj1->StepDir > 0) {
3566  if (tp2.Pos[0] < tp1.Pos[0] - 2) continue;
3567  }
3568  else {
3569  if (tp2.Pos[0] > tp1.Pos[0] + 2) continue;
3570  }
3571  // ensure that there is a signal on most of the wires between these points
3572  if (!SignalBetween(tp1, tp2, 0.8)) { continue; }
3573  // Find the distance of closest approach for small angle merging
3574  // Inflate the doca cut if we are bridging a block of dead wires
3575  float dang = DeltaAngle(tp1.Ang, tp2.Ang);
3576  float doca = 15;
3577  if (isVLA) {
3578  // compare the minimum separation between Large Angle trajectories using a generous cut
3579  unsigned short ipt1, ipt2;
3580  TrajTrajDOCA(slc, *tj1, tj2, ipt1, ipt2, doca);
3581  }
3582  else {
3583  // small angle
3584  doca = PointTrajDOCA(tp1.Pos[0], tp1.Pos[1], tp2);
3585  }
3586  float fom = dang * doca;
3587  if (fom < bestFOM) {
3588  bestFOM = fom;
3589  bestDOCA = doca;
3590  imbest = it2;
3591  }
3592  } // it2
3593  // No merge/vertex candidates
3594  if (imbest == UINT_MAX) continue;
3595 
3596  // Make angle adjustments to tp1.
3597  unsigned int it2 = imbest;
3598  auto* tj2 = &slc.tjs[imbest];
3599  unsigned short end2 = 1 - end1;
3600  bool loMCSMom = (tj1->MCSMom + tj2->MCSMom) < 150;
3601  // Don't use the angle at the end Pt for high momentum long trajectories in case there is a little kink at the end
3602  if (tj1->Pts.size() > 50 && tj1->MCSMom > 100) {
3603  if (end1 == 0) { tp1.Ang = tj1->Pts[tj1->EndPt[0] + 2].Ang; }
3604  else {
3605  tp1.Ang = tj1->Pts[tj1->EndPt[1] - 2].Ang;
3606  }
3607  }
3608  else if (loMCSMom) {
3609  // Low momentum - calculate the angle using the two Pts at the end
3610  unsigned short pt1, pt2;
3611  if (end1 == 0) {
3612  pt1 = tj1->EndPt[0];
3613  pt2 = pt1 + 1;
3614  }
3615  else {
3616  pt2 = tj1->EndPt[1];
3617  pt1 = pt2 - 1;
3618  }
3619  TrajPoint tpdir;
3620  if (MakeBareTrajPoint(tj1->Pts[pt1], tj1->Pts[pt2], tpdir)) tp1.Ang = tpdir.Ang;
3621  } // low MCSMom
3622  // Now do the same for tj2
3623  TrajPoint tp2 = tj2->Pts[tj2->EndPt[end2]];
3624  if (tj2->Pts.size() > 50 && tj2->MCSMom > 100) {
3625  if (end1 == 0) { tp2.Ang = tj2->Pts[tj2->EndPt[0] + 2].Ang; }
3626  else {
3627  tp2.Ang = tj2->Pts[tj2->EndPt[1] - 2].Ang;
3628  }
3629  }
3630  else if (loMCSMom) {
3631  // Low momentum - calculate the angle using the two Pts at the end
3632  unsigned short pt1, pt2;
3633  if (end2 == 0) {
3634  pt1 = tj2->EndPt[0];
3635  pt2 = pt1 + 1;
3636  }
3637  else {
3638  pt2 = tj2->EndPt[1];
3639  pt1 = pt2 - 1;
3640  }
3641  TrajPoint tpdir;
3642  if (MakeBareTrajPoint(tj2->Pts[pt1], tj2->Pts[pt2], tpdir)) tp2.Ang = tpdir.Ang;
3643  } // low MCSMom
3644 
3645  if (!isVLA && !SignalBetween(tp1, tp2, 0.99)) continue;
3646 
3647  // decide whether to merge or make a vertex
3648  // protect against angles > pi/2
3649  float dang = acos(DotProd(tp1.Dir, tp2.Dir));
3650  float sep = PosSep(tp1.Pos, tp2.Pos);
3651  // ignore this pair if the gap between them is much longer than the length of the shortest Tj
3652  float len1 = TrajLength(slc.tjs[it1]);
3653  float len2 = TrajLength(slc.tjs[it2]);
3654  if (len1 < len2 && sep > 3 * len1) continue;
3655  if (len2 < len1 && sep > 3 * len2) continue;
3656 
3657  // default cuts for locMCSMom condition
3658  float dangCut = 1;
3659  float docaCut = 2;
3660  float kinkSig = -1;
3661  if (!loMCSMom) {
3662  unsigned short nPtsFit = tcc.kinkCuts[0];
3663  bool useChg = (tcc.kinkCuts[2] > 0);
3664  kinkSig = KinkSignificance(slc, *tj1, end1, *tj2, end2, nPtsFit, useChg, prt);
3665  }
3666  docaCut = 1.5;
3667  if (isVLA) docaCut = 15;
3668  float chgPull = 0;
3669  if (tp1.AveChg > tp2.AveChg) { chgPull = (tp1.AveChg / tp2.AveChg - 1) / minChgRMS; }
3670  else {
3671  chgPull = (tp2.AveChg / tp1.AveChg - 1) / minChgRMS;
3672  }
3673  // open up the cuts on the last pass
3674  float chgFracCut = tcc.vtx2DCuts[8];
3675  float chgPullCut = tcc.chargeCuts[0];
3676  if (lastPass) {
3677  docaCut *= 2;
3678  chgFracCut *= 0.5;
3679  chgPullCut *= 1.5;
3680  }
3681 
3682  // check the merge cuts. Start with doca and dang requirements
3683  bool doMerge = bestDOCA < docaCut && dang < dangCut;
3684  bool showerTjs = tj1->PDGCode == 11 || tj2->PDGCode == 11;
3685  bool hiMCSMom = tj1->MCSMom > 200 || tj2->MCSMom > 200;
3686  // add a charge similarity requirement if not shower-like or low momentum or not LA
3687  if (doMerge && !showerTjs && hiMCSMom && chgPull > tcc.chargeCuts[0] && !isVLA)
3688  doMerge = false;
3689  // ignore the charge pull cut if both are high momentum and dang is really small
3690  if (!doMerge && tj1->MCSMom > 900 && tj2->MCSMom > 900 && dang < 0.1 &&
3691  bestDOCA < docaCut)
3692  doMerge = true;
3693 
3694  // do not merge if chgPull is really high
3695  if (doMerge && chgPull > 2 * chgPullCut) doMerge = false;
3696  float dwc = DeadWireCount(slc, tp1, tp2);
3697 
3698  if (doMerge) {
3699  if (lastPass) {
3700  // last pass cuts are looser but ensure that the tj after merging meets the quality cut
3701  float npwc = NumPtsWithCharge(slc, *tj1, true) + NumPtsWithCharge(slc, *tj2, true);
3702  auto& tp1OtherEnd = tj1->Pts[tj1->EndPt[1 - end1]];
3703  auto& tp2OtherEnd = tj2->Pts[tj2->EndPt[1 - end2]];
3704  float nwires = std::abs(tp1OtherEnd.Pos[0] - tp2OtherEnd.Pos[0]);
3705  if (nwires == 0) nwires = 1;
3706  float hitFrac = npwc / nwires;
3707  doMerge = (hitFrac > tcc.qualityCuts[0]);
3708  }
3709  else {
3710  // don't merge if the gap between them is longer than the length of the shortest Tj
3711  if (len1 < len2) {
3712  if (sep > len1) doMerge = false;
3713  }
3714  else {
3715  if (sep > len2) doMerge = false;
3716  }
3717  if (prt)
3718  mf::LogVerbatim("TC")
3719  << " merge check sep " << sep << " len1 " << len1 << " len2 " << len2
3720  << " dead wire count " << dwc << " Merge? " << doMerge;
3721  } // not lastPass
3722  } // doMerge
3723 
3724  // Require a large charge fraction near a merge point
3725  tjlist[0] = slc.tjs[it1].ID;
3726  tjlist[1] = slc.tjs[it2].ID;
3727  float chgFrac = ChgFracNearPos(slc, tp1.Pos, tjlist);
3728  if (doMerge && bestDOCA > 1 && chgFrac < chgFracCut) doMerge = false;
3729 
3730  // Check the MCSMom asymmetry and don't merge if it is higher than the user-specified cut
3731  float momAsym = std::abs(tj1->MCSMom - tj2->MCSMom) / (float)(tj1->MCSMom + tj2->MCSMom);
3732  if (doMerge && momAsym > tcc.vtx2DCuts[9]) doMerge = false;
3733  if (doMerge && (tj1->EndFlag[end1][kAtKink] || tj2->EndFlag[end2][kAtKink])) {
3734  // don't merge if a kink exists and the tjs are not too long
3735  if (len1 < 40 && len2 < 40) doMerge = false;
3736  // Kink on one + Bragg at other end of the other
3737  if (tj1->EndFlag[end1][kAtKink] && tj2->EndFlag[1 - end2][kBragg]) doMerge = false;
3738  if (tj1->EndFlag[1 - end1][kBragg] && tj2->EndFlag[end2][kAtKink]) doMerge = false;
3739  }
3740 
3741  // decide if we should make a vertex instead
3742  bool doVtx = false;
3743  if (!doMerge) {
3744  // check for a significant kink
3745  doVtx = (kinkSig > tcc.kinkCuts[1]);
3746  // and a less significant kink but very close separation
3747  doVtx = (kinkSig > 0.5 * tcc.kinkCuts[1] && sep < 2);
3748  } // !doMerge
3749 
3750  if (prt) {
3751  mf::LogVerbatim myprt("TC");
3752  myprt << " EM: T" << slc.tjs[it1].ID << "_" << end1 << " - T" << slc.tjs[it2].ID << "_"
3753  << end2 << " tp1-tp2 " << PrintPos(tp1) << "-" << PrintPos(tp2);
3754  myprt << " FOM " << std::fixed << std::setprecision(2) << bestFOM;
3755  myprt << " DOCA " << std::setprecision(1) << bestDOCA;
3756  myprt << " cut " << docaCut << " isVLA? " << isVLA;
3757  myprt << " dang " << std::setprecision(2) << dang << " dangCut " << dangCut;
3758  myprt << " chgPull " << std::setprecision(1) << chgPull << " Cut " << chgPullCut;
3759  myprt << " chgFrac " << std::setprecision(2) << chgFrac;
3760  myprt << " momAsym " << momAsym;
3761  myprt << " kinkSig " << std::setprecision(1) << kinkSig;
3762  myprt << " doMerge? " << doMerge;
3763  myprt << " doVtx? " << doVtx;
3764  }
3765 
3766  if (bestDOCA > docaCut) continue;
3767 
3768  if (doMerge) {
3769  if (prt) mf::LogVerbatim("TC") << " Merge ";
3770  bool didMerge = false;
3771  if (end1 == 1) { didMerge = MergeAndStore(slc, it1, it2, tcc.dbgMrg); }
3772  else {
3773  didMerge = MergeAndStore(slc, it2, it1, tcc.dbgMrg);
3774  }
3775  if (didMerge) {
3776  // If the merge succeeded, then the underlying slc.tjs vector may have been
3777  // reallocated, and we need to reset the pointers for tj1 and tj2.
3778  tj1 = &slc.tjs[it1];
3779  tj2 = &slc.tjs[it2];
3780 
3781  // Set the end merge flag for the killed trajectories to aid tracing merges
3782  tj1->AlgMod[kMerge] = true;
3783  tj2->AlgMod[kMerge] = true;
3784  iterate = true;
3785  } // Merge and store successfull
3786  else {
3787  if (prt) mf::LogVerbatim("TC") << " MergeAndStore failed ";
3788  }
3789  }
3790  else if (doVtx) {
3791  // create a vertex instead if it passes the vertex cuts
3792  VtxStore aVtx;
3793  aVtx.CTP = slc.tjs[it1].CTP;
3794  aVtx.ID = slc.vtxs.size() + 1;
3795  // keep it simple if tp1 and tp2 are very close or if the angle between them
3796  // is small
3797  if (prt) {
3798  mf::LogVerbatim("TC") << " candidate 2V" << aVtx.ID << " dang " << dang << " sep "
3799  << PosSep(tp1.Pos, tp2.Pos);
3800  }
3801  bool fix2V = (PosSep(tp1.Pos, tp2.Pos) < 3 || dang < 0.1);
3802  if (fix2V) {
3803  aVtx.Pos[0] = 0.5 * (tp1.Pos[0] + tp2.Pos[0]);
3804  aVtx.Pos[1] = 0.5 * (tp1.Pos[1] + tp2.Pos[1]);
3805  aVtx.Stat[kFixed] = true;
3806  aVtx.PosErr[0] = std::abs(tp1.Pos[0] - tp2.Pos[0]);
3807  aVtx.PosErr[1] = std::abs(tp1.Pos[1] - tp2.Pos[1]);
3808  }
3809  else {
3810  float sepCut = tcc.vtx2DCuts[1];
3811  bool tj1Short = (slc.tjs[it1].EndPt[1] - slc.tjs[it1].EndPt[0] < maxShortTjLen);
3812  bool tj2Short = (slc.tjs[it2].EndPt[1] - slc.tjs[it2].EndPt[0] < maxShortTjLen);
3813  if (tj1Short || tj2Short) sepCut = tcc.vtx2DCuts[1];
3814  TrajIntersection(tp1, tp2, aVtx.Pos);
3815  float dw = aVtx.Pos[0] - tp1.Pos[0];
3816  if (std::abs(dw) > sepCut) continue;
3817  float dt = aVtx.Pos[1] - tp1.Pos[1];
3818  if (std::abs(dt) > sepCut) continue;
3819  dw = aVtx.Pos[0] - tp2.Pos[0];
3820  if (std::abs(dw) > sepCut) continue;
3821  dt = aVtx.Pos[1] - tp2.Pos[1];
3822  if (std::abs(dt) > sepCut) continue;
3823  // ensure that the vertex is not closer to the other end if the tj is short
3824  // but not too short
3825  if (tj1Short && len1 > 4) {
3826  TrajPoint otp1 = slc.tjs[it1].Pts[slc.tjs[it1].EndPt[1 - end1]];
3827  if (PosSep2(otp1.Pos, aVtx.Pos) < PosSep2(tp1.Pos, aVtx.Pos)) continue;
3828  }
3829  if (tj2Short && len2 > 4) {
3830  TrajPoint otp2 = slc.tjs[it2].Pts[slc.tjs[it2].EndPt[1 - end2]];
3831  if (PosSep2(otp2.Pos, aVtx.Pos) < PosSep2(tp2.Pos, aVtx.Pos)) continue;
3832  }
3833  // we expect the vertex to be between tp1 and tp2
3834  if (aVtx.Pos[0] < tp1.Pos[0] && aVtx.Pos[0] < tp2.Pos[0]) {
3835  aVtx.Pos[0] = std::min(tp1.Pos[0], tp2.Pos[0]);
3836  aVtx.Stat[kFixed] = true;
3837  }
3838  if (aVtx.Pos[0] > tp1.Pos[0] && aVtx.Pos[0] > tp2.Pos[0]) {
3839  aVtx.Pos[0] = std::max(tp1.Pos[0], tp2.Pos[0]);
3840  aVtx.Stat[kFixed] = true;
3841  }
3842  } // Tps not so close
3843  // We got this far. Try a vertex fit to ensure that the errors are reasonable
3844  slc.tjs[it1].VtxID[end1] = aVtx.ID;
3845  slc.tjs[it2].VtxID[end2] = aVtx.ID;
3846  if (!aVtx.Stat[kFixed] && !FitVertex(slc, aVtx, prt)) {
3847  // back out
3848  slc.tjs[it1].VtxID[end1] = 0;
3849  slc.tjs[it2].VtxID[end2] = 0;
3850  if (prt) mf::LogVerbatim("TC") << " Vertex fit failed ";
3851  continue;
3852  }
3853  aVtx.NTraj = 2;
3854  aVtx.Pass = slc.tjs[it1].Pass;
3855  aVtx.Topo = end1 + end2;
3856  tj1->AlgMod[kMerge] = true;
3857  tj2->AlgMod[kMerge] = true;
3858  if (!StoreVertex(slc, aVtx)) continue;
3859  SetVx2Score(slc);
3860  if (prt) {
3861  auto& newVx = slc.vtxs[slc.vtxs.size() - 1];
3862  mf::LogVerbatim("TC")
3863  << " New 2V" << newVx.ID << " at " << (int)newVx.Pos[0] << ":"
3864  << (int)(newVx.Pos[1] / tcc.unitsPerTick) << " Score " << newVx.Score;
3865  }
3866  // check the score and kill it if it is below the cut
3867  // BB Oct 1, 2019. Don't kill the vertex in this function since it is
3868  // called before short trajectories are reconstructed
3869  auto& newVx2 = slc.vtxs[slc.vtxs.size() - 1];
3870  if (newVx2.Score < tcc.vtx2DCuts[7] && CompatibleMerge(*tj1, *tj2, prt)) {
3871  if (prt) {
3872  mf::LogVerbatim myprt("TC");
3873  myprt << " Bad vertex: Bad score? " << (newVx2.Score < tcc.vtx2DCuts[7]);
3874  myprt << " cut " << tcc.vtx2DCuts[7];
3875  myprt << " CompatibleMerge? " << CompatibleMerge(*tj1, *tj2, prt);
3876  }
3877  slc.tjs[it1].VtxID[end1] = 0;
3878  slc.tjs[it2].VtxID[end2] = 0;
3879  MakeVertexObsolete("EM", slc, newVx2, true);
3880  bool didMerge = false;
3881  if (end1 == 1) { didMerge = MergeAndStore(slc, it1, it2, tcc.dbgMrg); }
3882  else {
3883  didMerge = MergeAndStore(slc, it2, it1, tcc.dbgMrg);
3884  }
3885  if (didMerge) {
3886  // If the merge succeeded, then the underlying slc.tjs vector may have been
3887  // reallocated, and we need to reset the pointers for tj1 and tj2.
3888  tj1 = &slc.tjs[it1];
3889  tj2 = &slc.tjs[it2];
3890 
3891  // Set the end merge flag for the killed trajectories to aid tracing merges
3892  tj1->AlgMod[kMerge] = true;
3893  tj2->AlgMod[kMerge] = true;
3894  iterate = true;
3895  } // Merge and store successfull
3896  else {
3897  if (prt) mf::LogVerbatim("TC") << " MergeAndStore failed ";
3898  }
3899  } // OK score
3900  } // create a vertex
3901  if (tj1->AlgMod[kKilled]) break;
3902  } // end1
3903  } // it1
3904  } // iterate
3905 
3906  } // EndMerge
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void FitTraj(TCSlice const &slc, Trajectory &tj)
Definition: Utils.cxx:798
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:2698
std::vector< float > kinkCuts
kink finder algorithm
Definition: DataStructs.h:550
bool FitVertex(TCSlice &slc, VtxStore &vx, bool prt)
Definition: TCVertex.cxx:1943
std::vector< float > qualityCuts
Min points/wire, min consecutive pts after a gap.
Definition: DataStructs.h:554
TCConfig tcc
Definition: DataStructs.cxx:9
vertex position fixed manually - no fitting done
Definition: DataStructs.h:88
step from US -> DS (true) or DS -> US (false)
Definition: DataStructs.h:522
constexpr auto abs(T v)
Returns the absolute value of the argument.
bool CompatibleMerge(const TCSlice &slc, std::vector< int > const &tjIDs, bool prt)
Definition: Utils.cxx:577
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2514
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:2531
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
bool MakeBareTrajPoint(const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:4008
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:1908
bool SignalBetween(const TrajPoint &tp1, const TrajPoint &tp2, const float MinWireSignalFraction)
Definition: Utils.cxx:1779
float OverlapFraction(const Trajectory &tj1, const Trajectory &tj2)
Definition: Utils.cxx:707
TText * pt2
Definition: plot.C:64
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2095
DebugStuff debug
Definition: DebugStruct.cxx:4
float ChgFracNearPos(const TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3163
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2560
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
std::vector< float > chargeCuts
Definition: DataStructs.h:553
bool MergeAndStore(TCSlice &slc, unsigned int itj1, unsigned int itj2, bool doPrt)
Definition: Utils.cxx:4521
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
Definition: Utils.cxx:2543
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:126
float KinkSignificance(TCSlice const &slc, Trajectory const &tj1, unsigned short end1, Trajectory const &tj2, unsigned short end2, unsigned short nPtsFit, bool useChg, bool prt)
Definition: Utils.cxx:2986
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
float TrajLength(const Trajectory &tj)
Definition: Utils.cxx:2582
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
void SetVx2Score(TCSlice &slc)
Definition: TCVertex.cxx:2246
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:541
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
TText * pt1
Definition: plot.C:61
bool TrajTrajDOCA(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2407
CTP_t CTP
set to an invalid CTP
Definition: DebugStruct.h:23
void ReverseTraj(Trajectory &tj)
Definition: Utils.cxx:3219
float tca::ExpectedHitsRMS ( const TrajPoint tp)

Definition at line 1911 of file Utils.cxx.

References util::abs(), 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().

1912  {
1913  // returns the expected RMS of hits for the trajectory point in ticks
1914  if (std::abs(tp.Dir[0]) > 0.001) {
1915  geo::PlaneID planeID = DecodeCTP(tp.CTP);
1916  return 1.5 * evt.aveHitRMS[planeID.Plane] +
1917  2 * std::abs(tp.Dir[1] / tp.Dir[0]) / tcc.unitsPerTick;
1918  }
1919  return 500;
1920  } // ExpectedHitsRMS
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
constexpr auto abs(T v)
Returns the absolute value of the argument.
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
std::vector< float > aveHitRMS
average RMS of an isolated hit
Definition: DataStructs.h:630
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
geo::PlaneID DecodeCTP(CTP_t CTP)
TCEvent evt
Definition: DataStructs.cxx:8
unsigned short tca::FarEnd ( const PFPStruct pfp,
const Point3_t pos 
)

Definition at line 3300 of file PFPUtils.cxx.

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

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

3301  {
3302  // Returns the end (0 or 1) of the pfp that is furthest away from the position pos
3303  if (pfp.ID == 0) return 0;
3304  if (pfp.TP3Ds.empty()) return 0;
3305  auto& pos0 = pfp.TP3Ds[0].Pos;
3306  auto& pos1 = pfp.TP3Ds[pfp.TP3Ds.size() - 1].Pos;
3307  if (PosSep2(pos1, pos) > PosSep2(pos0, pos)) return 1;
3308  return 0;
3309  } // FarEnd
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2560
unsigned short tca::FarEnd ( const Trajectory tj,
const Point2_t pos 
)

Definition at line 4069 of file Utils.cxx.

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

4070  {
4071  // Returns the end (0 or 1) of the Tj that is furthest away from the position pos
4072  if (tj.ID == 0) return 0;
4073  if (PosSep2(tj.Pts[tj.EndPt[1]].Pos, pos) > PosSep2(tj.Pts[tj.EndPt[0]].Pos, pos)) return 1;
4074  return 0;
4075  } // FarEnd
float PosSep2(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2604
void tca::FilldEdx ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
const TCSlice slc,
PFPStruct pfp 
)

Definition at line 2583 of file PFPUtils.cxx.

References DecodeCTP(), tca::PFPStruct::dEdx, dEdx(), dir, util::end(), kTP3DBad, kTP3DGood, tca::TCSlice::nPlanes, tca::PFPStruct::PDGCode, geo::PlaneID::Plane, PosAtEnd(), PosSep2(), tcc, tca::PFPStruct::TP3Ds, and tca::TCConfig::wirePitch.

Referenced by DotProd(), and MakePFParticles().

2587  {
2588  // Fills dE/dx variables in the pfp struct
2589 
2590  // don't attempt to find dE/dx at the end of a shower
2591  unsigned short numEnds = 2;
2592  if (pfp.PDGCode == 1111) numEnds = 1;
2593 
2594  // set dE/dx to 0 to indicate that a valid dE/dx is expected
2595  for (unsigned short end = 0; end < numEnds; ++end) {
2596  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane)
2597  pfp.dEdx[end][plane] = 0;
2598  } // end
2599 
2600  // square of the maximum length that is used for finding the average dE/dx
2601  float maxSep2 = 5 * tcc.wirePitch;
2602  maxSep2 *= maxSep2;
2603 
2604  for (unsigned short end = 0; end < numEnds; ++end) {
2605  std::vector<float> cnt(slc.nPlanes);
2606  short dir = 1 - 2 * end;
2607  auto endPos = PosAtEnd(pfp, end);
2608  for (std::size_t ii = 0; ii < pfp.TP3Ds.size(); ++ii) {
2609  unsigned short ipt;
2610  if (dir > 0) { ipt = ii; }
2611  else {
2612  ipt = pfp.TP3Ds.size() - ii - 1;
2613  }
2614  if (ipt >= pfp.TP3Ds.size()) break;
2615  auto& tp3d = pfp.TP3Ds[ipt];
2616  if (tp3d.Flags[kTP3DBad]) continue;
2617  if (PosSep2(tp3d.Pos, endPos) > maxSep2) break;
2618  // require good points
2619  if (!tp3d.Flags[kTP3DGood]) continue;
2620  float dedx = dEdx(clockData, detProp, slc, tp3d);
2621  if (dedx < 0.5) continue;
2622  unsigned short plane = DecodeCTP(tp3d.CTP).Plane;
2623  pfp.dEdx[end][plane] += dedx;
2624  ++cnt[plane];
2625  } // ii
2626  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
2627  if (cnt[plane] == 0) continue;
2628  pfp.dEdx[end][plane] /= cnt[plane];
2629  } // plane
2630  } // end
2631 
2632  } // FilldEdx
TCConfig tcc
Definition: DataStructs.cxx:9
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3257
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2560
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
float dEdx(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, TP3D &tp3d)
Definition: PFPUtils.cxx:2671
TDirectory * dir
Definition: macro.C:5
geo::PlaneID DecodeCTP(CTP_t CTP)
void tca::FillGaps ( TCSlice slc,
Trajectory tj 
)

Definition at line 2204 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::TCEvent::allHits, tca::Trajectory::AveChg, tca::TCConfig::chargeCuts, tca::Trajectory::ChgRMS, tca::TCConfig::dbgStp, DefineHitPos(), tca::Trajectory::EndFlag, tca::Trajectory::EndPt, evt, tca::Trajectory::ID, if(), tca::Trajectory::IsGood, tca::TCSlice::isValid, kBragg, kFillGaps, kJunkTj, MakeBareTrajPoint(), MaxHitDelta(), tca::Trajectory::MCSMom, MCSMom(), NumPtsWithCharge(), tca::Trajectory::Pass, PointTrajDOCA(), PrintHit(), PrintPos(), PrintTP(), tca::Trajectory::Pts, tca::TCSlice::slHits, tca::Trajectory::StepDir, tcc, UnsetUsedHits(), and tca::TCConfig::useAlg.

Referenced by CheckStiffEl(), and CheckTraj().

2205  {
2206  // Fill in any gaps in the trajectory with close hits regardless of charge (well maybe not quite that)
2207 
2208  if (!tcc.useAlg[kFillGaps]) return;
2209  if (tj.AlgMod[kJunkTj]) return;
2210  if (tj.ChgRMS <= 0) return;
2211 
2212  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
2213  if (npwc < 8) return;
2214 
2215  // don't consider the last few points since they would be trimmed
2216  unsigned short toPt = tj.EndPt[1] - 2;
2217  if (!tj.EndFlag[1][kBragg]) {
2218  // Don't fill gaps (with high-charge hits) near the end. Find the last point near the
2219  // end that would have normal charge if all the hit were added
2220  unsigned short cnt = 0;
2221  for (unsigned short ipt = tj.EndPt[1] - 2; ipt > tj.EndPt[0]; --ipt) {
2222  auto& tp = tj.Pts[ipt];
2223  float chg = tp.Chg;
2224  if (chg == 0) {
2225  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2226  unsigned int iht = tp.Hits[ii];
2227  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2228  chg += hit.Integral();
2229  }
2230  } // chg == 0
2231  float chgPull = (chg / tj.AveChg - 1) / tj.ChgRMS;
2232  if (chgPull < 2) {
2233  toPt = ipt;
2234  break;
2235  }
2236  ++cnt;
2237  if (cnt > 20) break;
2238  } // ipt
2239  } // !tj.EndFlag[1][kBragg]
2240 
2241  if (tcc.dbgStp)
2242  mf::LogVerbatim("TC") << "FG: Check Tj " << tj.ID << " from " << PrintPos(tj.Pts[tj.EndPt[0]])
2243  << " to " << PrintPos(tj.Pts[toPt]);
2244 
2245  // start with the first point that has charge
2246  short firstPtWithChg = tj.EndPt[0];
2247  bool first = true;
2248  float maxDelta = 1;
2249  // don't let MCSMom suffer too much while filling gaps
2250  short minMCSMom = 0.7 * tj.MCSMom;
2251  while (firstPtWithChg < toPt) {
2252  short nextPtWithChg = firstPtWithChg + 1;
2253  // find the next point with charge
2254  for (nextPtWithChg = firstPtWithChg + 1; nextPtWithChg < tj.EndPt[1]; ++nextPtWithChg) {
2255  if (tj.Pts[nextPtWithChg].Chg > 0) break;
2256  } // nextPtWithChg
2257  if (nextPtWithChg == firstPtWithChg + 1) {
2258  // the next point has charge
2259  ++firstPtWithChg;
2260  continue;
2261  }
2262  // Found a gap. Require at least two consecutive points with charge after the gap
2263  if (nextPtWithChg < (tj.EndPt[1] - 1) && tj.Pts[nextPtWithChg + 1].Chg == 0) {
2264  firstPtWithChg = nextPtWithChg;
2265  continue;
2266  }
2267  // Make a bare trajectory point at firstPtWithChg that points to nextPtWithChg
2268  TrajPoint tp;
2269  if (!MakeBareTrajPoint(tj.Pts[firstPtWithChg], tj.Pts[nextPtWithChg], tp)) {
2270  tj.IsGood = false;
2271  return;
2272  }
2273  // Find the maximum delta between hits and the trajectory Pos for all
2274  // hits on this trajectory
2275  if (first) {
2276  maxDelta = 2.5 * MaxHitDelta(slc, tj);
2277  first = false;
2278  } // first
2279  // define a loose charge cut using the average charge at the first point with charge
2280  float maxChg = tj.Pts[firstPtWithChg].AveChg * (1 + 2 * tcc.chargeCuts[0] * tj.ChgRMS);
2281  // Eliminate the charge cut altogether if we are close to an end
2282  if (tj.Pts.size() < 10) { maxChg = 1E6; }
2283  else {
2284  short chgCutPt = tj.EndPt[0] + 5;
2285  if (firstPtWithChg < chgCutPt) {
2286  // gap is near end 0
2287  maxChg = 1E6;
2288  }
2289  else {
2290  // check for gap near end 1
2291  chgCutPt = tj.EndPt[1] - 5;
2292  if (chgCutPt < tj.EndPt[0]) chgCutPt = tj.EndPt[0];
2293  if (nextPtWithChg > chgCutPt) maxChg = 1E6;
2294  }
2295  }
2296 
2297  // fill in the gap
2298  for (unsigned short mpt = firstPtWithChg + 1; mpt < nextPtWithChg; ++mpt) {
2299  if (tj.Pts[mpt].Chg > 0) {
2300  mf::LogVerbatim("TC") << "FillGaps coding error: firstPtWithChg " << firstPtWithChg
2301  << " mpt " << mpt << " nextPtWithChg " << nextPtWithChg;
2302  slc.isValid = false;
2303  return;
2304  }
2305  bool filled = false;
2306  float chg = 0;
2307  for (unsigned short ii = 0; ii < tj.Pts[mpt].Hits.size(); ++ii) {
2308  unsigned int iht = tj.Pts[mpt].Hits[ii];
2309  if (slc.slHits[iht].InTraj > 0) continue;
2310  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2311  float delta = PointTrajDOCA(slc, iht, tp);
2312  if (tcc.dbgStp)
2313  mf::LogVerbatim("TC") << " FG: " << PrintPos(tj.Pts[mpt]) << " hit "
2314  << PrintHit(slc.slHits[iht]) << " delta " << delta << " maxDelta "
2315  << maxDelta << " Chg " << hit.Integral() << " maxChg " << maxChg;
2316  if (delta > maxDelta) continue;
2317  tj.Pts[mpt].UseHit[ii] = true;
2318  slc.slHits[iht].InTraj = tj.ID;
2319  chg += hit.Integral();
2320  filled = true;
2321  } // ii
2322  if (chg > maxChg || MCSMom(slc, tj) < minMCSMom) {
2323  // don't use these hits after all
2324  UnsetUsedHits(slc, tj.Pts[mpt]);
2325  filled = false;
2326  }
2327  if (filled) {
2328  DefineHitPos(slc, tj.Pts[mpt]);
2329  tj.AlgMod[kFillGaps] = true;
2330  if (tcc.dbgStp) {
2331  PrintTP("FG", slc, mpt, tj.StepDir, tj.Pass, tj.Pts[mpt]);
2332  mf::LogVerbatim("TC") << "Check MCSMom " << MCSMom(slc, tj);
2333  }
2334  } // filled
2335  } // mpt
2336  firstPtWithChg = nextPtWithChg;
2337  } // firstPtWithChg
2338 
2339  if (tj.AlgMod[kFillGaps]) tj.MCSMom = MCSMom(slc, tj);
2340 
2341  } // FillGaps
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3381
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
void PrintTP(std::string someText, const TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, const TrajPoint &tp)
Definition: Utils.cxx:6134
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1061
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2514
bool MakeBareTrajPoint(const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:4008
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
if(nlines<=0)
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1791
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6347
Detector simulation of raw signals on wires.
std::vector< float > chargeCuts
Definition: DataStructs.h:553
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
float MaxHitDelta(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:3202
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
TCEvent evt
Definition: DataStructs.cxx:8
void tca::FillGaps3D ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
TCSlice slc,
PFPStruct pfp,
bool  prt 
)

Definition at line 1720 of file PFPUtils.cxx.

References AddPointsInRange(), tca::TCConfig::dbgPFP, debug, EncodeCTP(), tca::PFPStruct::Flags, tca::PFPStruct::ID, kFillGaps3D, kJunk3D, kNeedsUpdate, kSmallAngle, tca::TCConfig::match3DCuts, tca::DebugStuff::MVI, tca::PFPStruct::MVI, tca::TCSlice::nPlanes, tca::PFPStruct::SectionFits, tcc, tca::PFPStruct::TP3Ds, Update(), and tca::TCConfig::useAlg.

Referenced by MakePFParticles().

1725  {
1726  // Look for gaps in each plane in the TP3Ds vector in planes in which
1727  // the projection of the pfp angle is large (~> 60 degrees). Hits
1728  // reconstructed at large angles are poorly reconstructed which results
1729  // in poorly reconstructed 2D trajectories
1730 
1731  if (pfp.ID <= 0) return;
1732  if (pfp.TP3Ds.empty()) return;
1733  if (pfp.SectionFits.empty()) return;
1734  if (!tcc.useAlg[kFillGaps3D]) return;
1735  if (pfp.Flags[kJunk3D]) return;
1736  if (pfp.Flags[kSmallAngle]) return;
1737 
1738  // Only print APIR details if MVI is set
1739  bool foundMVI = (tcc.dbgPFP && pfp.MVI == debug.MVI);
1740 
1741  // make a copy in case something goes wrong
1742  auto pWork = pfp;
1743 
1744  unsigned short nPtsAdded = 0;
1745  unsigned short fromPt = 0;
1746  unsigned short toPt = pWork.TP3Ds.size();
1747  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
1748  CTP_t inCTP = EncodeCTP(pWork.TPCID.Cryostat, pWork.TPCID.TPC, plane);
1749  unsigned short nWires, nAdd;
1750  AddPointsInRange(clockData,
1751  detProp,
1752  slc,
1753  pWork,
1754  fromPt,
1755  toPt,
1756  inCTP,
1757  tcc.match3DCuts[4],
1758  nWires,
1759  nAdd,
1760  foundMVI);
1761  if (pWork.Flags[kNeedsUpdate]) Update(detProp, slc, pWork);
1762  nPtsAdded += nAdd;
1763  } // plane
1764  if (prt) mf::LogVerbatim("TC") << "FG3D P" << pWork.ID << " added " << nPtsAdded << " points";
1765  if (pWork.Flags[kNeedsUpdate] && !Update(detProp, slc, pWork)) return;
1766  pfp = pWork;
1767  return;
1768  } // FillGaps3D
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
unsigned int MVI
MatchVec Index for detailed 3D matching.
Definition: DebugStruct.h:29
bool Update(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp)
Definition: PFPUtils.cxx:1048
void AddPointsInRange(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, PFPStruct &pfp, unsigned short fromPt, unsigned short toPt, CTP_t inCTP, float maxPull, unsigned short &nWires, unsigned short &nAdd, bool prt)
Definition: PFPUtils.cxx:1811
DebugStuff debug
Definition: DebugStruct.cxx:4
std::vector< float > match3DCuts
3D matching cuts
Definition: DataStructs.h:551
unsigned int CTP_t
Definition: DataStructs.h:45
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:49
void tca::FillmAllTraj ( detinfo::DetectorPropertiesData const &  detProp,
TCSlice slc 
)

Definition at line 2369 of file PFPUtils.cxx.

References detinfo::DetectorPropertiesData::ConvertTicksToX(), geo::CryostatID::Cryostat, DecodeCTP(), geo::WireReadoutGeom::HasWire(), tca::Tj2Pt::id, tca::Tj2Pt::ipt, kEnvNearMuon, kHaloTj, kKilled, kMat3D, tca::TCSlice::mallTraj, tca::TCConfig::match3DCuts, tca::Tj2Pt::npts, tca::Tj2Pt::plane, geo::PlaneID::Plane, tcc, tca::TCSlice::tjs, geo::TPCID::TPC, tca::TCSlice::TPCID, tca::TCConfig::unitsPerTick, tca::detail::valsIncreasing(), tca::Tj2Pt::wire, tca::TCConfig::wireReadoutGeom, tca::Tj2Pt::xhi, and tca::Tj2Pt::xlo.

Referenced by FindPFParticles().

2370  {
2371  // Fills the mallTraj vector with trajectory points in the tpc and sorts
2372  // them by increasing X
2373 
2374  int cstat = slc.TPCID.Cryostat;
2375  int tpc = slc.TPCID.TPC;
2376 
2377  // define mallTraj
2378  slc.mallTraj.clear();
2379  Tj2Pt tj2pt;
2380  unsigned short cnt = 0;
2381 
2382  // try to reduce CPU time by not attempting to match tjs that are near muons
2383  bool muFuzzCut = (tcc.match3DCuts.size() > 6 && tcc.match3DCuts[6] > 0);
2384 
2385  float rms = tcc.match3DCuts[0];
2386  for (auto& tj : slc.tjs) {
2387  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
2388  // ignore already matched
2389  if (tj.AlgMod[kMat3D]) continue;
2390  geo::PlaneID planeID = DecodeCTP(tj.CTP);
2391  if ((int)planeID.Cryostat != cstat) continue;
2392  if ((int)planeID.TPC != tpc) continue;
2393  int plane = planeID.Plane;
2394  if (tj.ID <= 0) continue;
2395  unsigned short tjID = tj.ID;
2396  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2397  auto& tp = tj.Pts[ipt];
2398  if (tp.Chg <= 0) continue;
2399  if (tp.Pos[0] < -0.4) continue;
2400  // ignore already matched
2401  if (tp.InPFP > 0) continue;
2402  if (muFuzzCut && tp.Environment[kEnvNearMuon]) continue;
2403  tj2pt.wire = std::nearbyint(tp.Pos[0]);
2404  ++cnt;
2405  // don't try matching if the wire doesn't exist
2406  if (!tcc.wireReadoutGeom->HasWire(geo::WireID(cstat, tpc, plane, tj2pt.wire))) continue;
2407  float xpos = detProp.ConvertTicksToX(tp.Pos[1] / tcc.unitsPerTick, plane, tpc, cstat);
2408  tj2pt.xlo = xpos - rms;
2409  tj2pt.xhi = xpos + rms;
2410  tj2pt.plane = plane;
2411  tj2pt.id = tjID;
2412  tj2pt.ipt = ipt;
2413  tj2pt.npts = tj.EndPt[1] - tj.EndPt[0] + 1;
2414  slc.mallTraj.push_back(tj2pt);
2415  } // tp
2416  } // tj
2417 
2418  // sort by increasing x
2419  std::vector<SortEntry> sortVec(slc.mallTraj.size());
2420  for (std::size_t ipt = 0; ipt < slc.mallTraj.size(); ++ipt) {
2421  // populate the sort vector
2422  sortVec[ipt].index = ipt;
2423  sortVec[ipt].val = slc.mallTraj[ipt].xlo;
2424  } // ipt
2425  // sort by increasing xlo
2426  std::sort(sortVec.begin(), sortVec.end(), valsIncreasing);
2427  // put slc.mallTraj into sorted order
2428  auto tallTraj = slc.mallTraj;
2429  for (std::size_t ii = 0; ii < sortVec.size(); ++ii)
2430  slc.mallTraj[ii] = tallTraj[sortVec[ii].index];
2431 
2432  } // FillmAllTraj
const geo::WireReadoutGeom * wireReadoutGeom
Definition: DataStructs.h:568
TCConfig tcc
Definition: DataStructs.cxx:9
bool HasWire(WireID const &wireid) const
Returns whether we have the specified wire.
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:195
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
std::vector< float > match3DCuts
3D matching cuts
Definition: DataStructs.h:551
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
bool valsIncreasing(const SortEntry &c1, const SortEntry &c2)
Definition: Utils.cxx:43
geo::PlaneID DecodeCTP(CTP_t CTP)
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:315
void tca::FillWireHitRange ( geo::TPCID  inTPCID)

Definition at line 4325 of file Utils.cxx.

References tca::TCEvent::allHits, evt, tca::TCEvent::expectSlicedHits, tca::TCEvent::goodWire, geo::Iterable< IterationPolicy, Transform >::Iterate(), kDebug, tca::TCConfig::modes, geo::WireReadoutGeom::Nplanes(), geo::WireReadoutGeom::Nwires(), geo::WireReadoutGeom::PlaneWireToChannel(), util::size(), tcc, tca::TCEvent::TPCID, tca::TCConfig::useChannelStatus, tca::TCEvent::wireHitRange, and tca::TCConfig::wireReadoutGeom.

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

4326  {
4327  // Defines the local vector of dead wires and the low-high range of hits in each wire in
4328  // the TPCID in TCEvent. Note that there is no requirement that the allHits collection is sorted. Care should
4329  // be taken when looping over hits using this range - see SignalAtTp
4330 
4331  // see if this function was called in the current TPCID. There is nothing that needs to
4332  // be done if that is the case
4333  if (inTPCID == evt.TPCID) return;
4334 
4335  evt.TPCID = inTPCID;
4336  unsigned short nplanes = tcc.wireReadoutGeom->Nplanes(inTPCID);
4337  if (tcc.useChannelStatus) {
4338  lariov::ChannelStatusProvider const& channelStatus =
4340  evt.goodWire.resize(nplanes);
4341  for (auto const& id : tcc.wireReadoutGeom->Iterate<geo::PlaneID>(inTPCID)) {
4342  unsigned int nwires = tcc.wireReadoutGeom->Nwires(id);
4343  // set all wires dead
4344  evt.goodWire[id.Plane].resize(nwires, false);
4345  for (unsigned int wire = 0; wire < nwires; ++wire) {
4347  evt.goodWire[id.Plane][wire] = channelStatus.IsGood(chan);
4348  } // wire
4349  } // pln
4350  }
4351  else {
4352  // resize and set every channel good
4353  evt.goodWire.resize(nplanes);
4354  for (auto const& id : tcc.wireReadoutGeom->Iterate<geo::PlaneID>(inTPCID)) {
4355  unsigned int nwires = tcc.wireReadoutGeom->Nwires(id);
4356  evt.goodWire[id.Plane].resize(nwires, true);
4357  } // pln
4358  } // don't use channelStatus
4359 
4360  // there is no need to define evt.wireHitRange if the hit collection is not sliced. The function
4361  // SignalAtTP will then use the (smaller) slc.WireHitRange instead of evt.wireHitRange
4362  if (!evt.expectSlicedHits) return;
4363 
4364  // define the size of evt.wireHitRange
4365  evt.wireHitRange.resize(nplanes);
4366  for (auto const& id : tcc.wireReadoutGeom->Iterate<geo::PlaneID>(inTPCID)) {
4367  unsigned int nwires = tcc.wireReadoutGeom->Nwires(id);
4368  evt.wireHitRange[id.Plane].resize(nwires);
4369  for (unsigned int wire = 0; wire < nwires; ++wire)
4370  evt.wireHitRange[id.Plane][wire] = {UINT_MAX, UINT_MAX};
4371  } // pln
4372 
4373  // next define the wireHitRange values. Make one loop through the allHits collection
4374  unsigned int nBadWireFix = 0;
4375  for (unsigned int iht = 0; iht < (*evt.allHits).size(); ++iht) {
4376  auto& hit = (*evt.allHits)[iht];
4377  auto const& wid = hit.WireID();
4378 
4379  if (static_cast<geo::TPCID const&>(wid) != inTPCID) continue;
4380  unsigned short pln = wid.Plane;
4381  unsigned int wire = wid.Wire;
4382  // Check the goodWire status and correct it if it's wrong
4383  if (!evt.goodWire[pln][wire]) {
4384  evt.goodWire[pln][wire] = true;
4385  ++nBadWireFix;
4386  } // not goodWire
4387  if (evt.wireHitRange[pln][wire].first == UINT_MAX) evt.wireHitRange[pln][wire].first = iht;
4388  evt.wireHitRange[pln][wire].second = iht;
4389  } // iht
4390  if (nBadWireFix > 0 && tcc.modes[kDebug]) {
4391  std::cout << "FillWireHitRange found hits on " << nBadWireFix
4392  << " wires that were declared not-good by the ChannelStatus service. Fixed it...\n";
4393  }
4394  } // FillWireHitRange
geo::TPCID TPCID
Definition: DataStructs.h:613
unsigned int Nwires(PlaneID const &planeid) const
Returns the total number of wires in the specified plane.
const geo::WireReadoutGeom * wireReadoutGeom
Definition: DataStructs.h:568
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
bool expectSlicedHits
info passed from the module - used to (not) define wireHitRange
Definition: DataStructs.h:640
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:622
virtual raw::ChannelID_t PlaneWireToChannel(WireID const &wireID) const =0
Returns the channel ID a wire is connected to.
Detector simulation of raw signals on wires.
unsigned int Nplanes(TPCID const &tpcid=details::tpc_zero) const
Returns the total number of planes in the specified TPC.
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
range_type< T > Iterate() const
Definition: Iterable.h:121
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
std::vector< std::vector< std::pair< unsigned int, unsigned int > > > wireHitRange
Definition: DataStructs.h:618
bool useChannelStatus
Definition: DataStructs.h:601
master switch for turning on debug mode
Definition: DataStructs.h:524
bool tca::FillWireHitRange ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
TCSlice slc 
)

Definition at line 4397 of file Utils.cxx.

References tca::TCEvent::allHits, tca::TCEvent::aveHitRMS, geo::CryostatID::Cryostat, debug, detinfo::DetectorPropertiesData::DriftVelocity(), detinfo::DetectorPropertiesData::Efield(), evt, tca::TCSlice::firstWire, tca::TCConfig::geom, tca::TCSlice::ID, kDebug, tca::TCSlice::lastWire, tca::TCConfig::maxPos0, tca::TCConfig::maxPos1, tca::TCConfig::modes, geo::WireReadoutGeom::Nplanes(), tca::TCSlice::nPlanes, detinfo::DetectorPropertiesData::NumberTimeSamples(), geo::WireReadoutGeom::Nwires(), tca::TCSlice::nWires, geo::WireReadoutGeom::Plane(), geo::WireReadoutGeom::PlaneWireToChannel(), detinfo::sampling_rate(), tca::TCSlice::slHits, slices, tcc, detinfo::DetectorPropertiesData::Temperature(), tca::DebugStuff::TPC, geo::TPCID::TPC, geo::GeometryCore::TPC(), tca::TCSlice::TPCID, tca::TCConfig::unitsPerTick, geo::WireReadoutGeom::View(), tca::TCSlice::wireHitRange, tca::TCConfig::wirePitch, tca::TCConfig::wireReadoutGeom, tca::TCSlice::xHi, tca::TCSlice::xLo, tca::TCSlice::yHi, tca::TCSlice::yLo, tca::TCSlice::zHi, and tca::TCSlice::zLo.

4400  {
4401  // fills the WireHitRange vector. Slightly modified version of the one in ClusterCrawlerAlg.
4402  // Returns false if there was a serious error
4403 
4404  // determine the number of planes
4405  unsigned int cstat = slc.TPCID.Cryostat;
4406  unsigned int tpc = slc.TPCID.TPC;
4407  auto const& tpcgeom = tcc.geom->TPC(slc.TPCID);
4408  unsigned short nplanes = tcc.wireReadoutGeom->Nplanes(slc.TPCID);
4409  slc.nPlanes = nplanes;
4410  if (nplanes > 3) return false;
4411 
4412  // Y,Z limits of the detector
4413  auto const world = tpcgeom.GetCenter();
4414 
4415  // reduce the active area of the TPC by 1 cm to prevent wire boundary issues
4416  slc.xLo = world.X() - tpcgeom.HalfWidth() + 1;
4417  slc.xHi = world.X() + tpcgeom.HalfWidth() - 1;
4418  slc.yLo = world.Y() - tpcgeom.HalfHeight() + 1;
4419  slc.yHi = world.Y() + tpcgeom.HalfHeight() - 1;
4420  slc.zLo = world.Z() - tpcgeom.Length() / 2 + 1;
4421  slc.zHi = world.Z() + tpcgeom.Length() / 2 - 1;
4422 
4423  // initialize everything
4424  slc.wireHitRange.resize(nplanes);
4425  slc.firstWire.resize(nplanes);
4426  slc.lastWire.resize(nplanes);
4427  slc.nWires.resize(nplanes);
4428  tcc.maxPos0.resize(nplanes);
4429  tcc.maxPos1.resize(nplanes);
4430  evt.aveHitRMS.resize(nplanes, nplanes);
4431 
4432  std::pair<unsigned int, unsigned int> flag{UINT_MAX, UINT_MAX};
4433 
4434  // Calculate tcc.unitsPerTick, the scale factor to convert a tick into
4435  // Wire Spacing Equivalent (WSE) units where the wire spacing in this plane = 1.
4436  // Strictly speaking this factor should be calculated for each plane to handle the
4437  // case where the wire spacing is different in each plane. Deal with this later if
4438  // the approximation used here fails.
4439 
4440  geo::PlaneID const plane_0{tpcgeom.ID(), 0};
4442  tcc.wirePitch =
4443  tcc.wireReadoutGeom->Plane({0, 0, tcc.wireReadoutGeom->View(channel)}).WirePitch();
4444  float tickToDist = detProp.DriftVelocity(detProp.Efield(), detProp.Temperature());
4445  tickToDist *= 1.e-3 * sampling_rate(clockData); // 1e-3 is conversion of 1/us to 1/ns
4446  tcc.unitsPerTick = tickToDist / tcc.wirePitch;
4447  for (unsigned short plane = 0; plane < nplanes; ++plane) {
4448  slc.firstWire[plane] = UINT_MAX;
4449  slc.lastWire[plane] = 0;
4450  slc.nWires[plane] = tcc.wireReadoutGeom->Nwires(geo::PlaneID{tpcgeom.ID(), plane});
4451  slc.wireHitRange[plane].resize(slc.nWires[plane], flag);
4452  tcc.maxPos0[plane] = (float)slc.nWires[plane] - 0.5;
4453  tcc.maxPos1[plane] = (float)detProp.NumberTimeSamples() * tcc.unitsPerTick;
4454  }
4455 
4456  unsigned int lastWire = 0, lastPlane = 0;
4457  for (unsigned int iht = 0; iht < slc.slHits.size(); ++iht) {
4458  unsigned int ahi = slc.slHits[iht].allHitsIndex;
4459  if (ahi > (*evt.allHits).size() - 1) return false;
4460  auto& hit = (*evt.allHits)[ahi];
4461  if (hit.WireID().Cryostat != cstat) continue;
4462  if (hit.WireID().TPC != tpc) continue;
4463  unsigned short plane = hit.WireID().Plane;
4464  unsigned int wire = hit.WireID().Wire;
4465  if (wire > slc.nWires[plane] - 1) {
4466  mf::LogWarning("TC") << "FillWireHitRange: Invalid wire number " << wire << " > "
4467  << slc.nWires[plane] - 1 << " in plane " << plane << " Quitting";
4468  return false;
4469  } // too large wire number
4470  if (plane == lastPlane && wire < lastWire) {
4471  mf::LogWarning("TC")
4472  << "FillWireHitRange: Hits are not in increasing wire order. Quitting ";
4473  return false;
4474  } // hits out of order
4475  lastWire = wire;
4476  lastPlane = plane;
4477  if (slc.firstWire[plane] == UINT_MAX) slc.firstWire[plane] = wire;
4478  if (slc.wireHitRange[plane][wire].first == UINT_MAX)
4479  slc.wireHitRange[plane][wire].first = iht;
4480  slc.wireHitRange[plane][wire].second = iht;
4481  slc.lastWire[plane] = wire + 1;
4482  } // iht
4483  // check
4484  unsigned int slhitsSize = slc.slHits.size();
4485  for (unsigned short plane = 0; plane < nplanes; ++plane) {
4486  for (unsigned int wire = slc.firstWire[plane]; wire < slc.lastWire[plane]; ++wire) {
4487  if (slc.wireHitRange[plane][wire].first == UINT_MAX) continue;
4488  if (slc.wireHitRange[plane][wire].first > slhitsSize - 1 &&
4489  slc.wireHitRange[plane][wire].second > slhitsSize)
4490  return false;
4491  } // wire
4492  } // plane
4493 
4494  // Find the average multiplicity 1 hit RMS and calculate the expected max RMS for each range
4495  if (tcc.modes[kDebug] && (int)tpc == debug.TPC) {
4496  // Note that this function is called before the slice is pushed into slices so the index
4497  // isn't decremented by 1
4498  std::cout << "Slice ID/Index " << slc.ID << "/" << slices.size() << " tpc " << tpc
4499  << " tcc.unitsPerTick " << std::setprecision(3) << tcc.unitsPerTick;
4500  std::cout << " Active volume (";
4501  std::cout << std::fixed << std::setprecision(1) << slc.xLo << " < X < " << slc.xHi << ") (";
4502  std::cout << std::fixed << std::setprecision(1) << slc.yLo << " < Y < " << slc.yHi << ") (";
4503  std::cout << std::fixed << std::setprecision(1) << slc.zLo << " < Z < " << slc.zHi << ")\n";
4504  }
4505 
4506  return true;
4507 
4508  } // FillWireHitRange
unsigned int Nwires(PlaneID const &planeid) const
Returns the total number of wires in the specified plane.
std::vector< float > maxPos0
Definition: DataStructs.h:563
const geo::WireReadoutGeom * wireReadoutGeom
Definition: DataStructs.h:568
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
std::vector< float > maxPos1
Definition: DataStructs.h:564
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
DebugStuff debug
Definition: DebugStruct.cxx:4
std::vector< float > aveHitRMS
average RMS of an isolated hit
Definition: DataStructs.h:630
virtual raw::ChannelID_t PlaneWireToChannel(WireID const &wireID) const =0
Returns the channel ID a wire is connected to.
const geo::GeometryCore * geom
Definition: DataStructs.h:567
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
Detector simulation of raw signals on wires.
unsigned int Nplanes(TPCID const &tpcid=details::tpc_zero) const
Returns the total number of planes in the specified TPC.
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
int TPC
Select TPC.
Definition: DebugStruct.h:21
View_t View(raw::ChannelID_t const channel) const
Returns the view (wire orientation) on the specified TPC channel.
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
PlaneGeo const & Plane(TPCID const &tpcid, View_t view) const
Returns the specified wire.
TCEvent evt
Definition: DataStructs.cxx:8
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
TPCGeo const & TPC(TPCID const &tpcid=details::tpc_zero) const
Returns the specified TPC.
Definition: GeometryCore.h:448
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
master switch for turning on debug mode
Definition: DataStructs.h:524
void tca::FillWireIntersections ( TCSlice slc)

Definition at line 607 of file PFPUtils.cxx.

References geo::CryostatID::Cryostat, tca::TCWireIntersection::dydw1, tca::TCWireIntersection::dydw2, tca::TCWireIntersection::dzdw1, tca::TCWireIntersection::dzdw2, evt, tca::TCSlice::nPlanes, tca::TCSlice::nWires, tca::TCWireIntersection::pln1, tca::TCWireIntersection::pln2, tcc, tca::TCWireIntersection::tpc, geo::TPCID::TPC, tca::TCSlice::TPCID, tca::TCWireIntersection::wir1, tca::TCWireIntersection::wir2, geo::WireReadoutGeom::WireIDsIntersect(), tca::TCEvent::wireIntersections, tca::TCConfig::wireReadoutGeom, tca::TCWireIntersection::y, and tca::TCWireIntersection::z.

Referenced by FindPFParticles().

608  {
609  // Find wire intersections and put them in evt.wireIntersections
610 
611  // see if anything needs to be done
612  if (!evt.wireIntersections.empty() && evt.wireIntersections[0].tpc == slc.TPCID.TPC) return;
613 
614  evt.wireIntersections.clear();
615 
616  unsigned int cstat = slc.TPCID.Cryostat;
617  unsigned int tpc = slc.TPCID.TPC;
618  // find the minMax number of wires in each plane of the TPC
619  unsigned int maxWire = slc.nWires[0];
620  for (auto nw : slc.nWires)
621  if (nw < maxWire) maxWire = nw;
622  // Start looking for intersections in the middle
623  unsigned int firstWire = maxWire / 2;
624 
625  // find a valid wire intersection in all plane combinations
626  std::vector<std::pair<unsigned short, unsigned short>> pln1pln2;
627  for (unsigned short pln1 = 0; pln1 < slc.nPlanes - 1; ++pln1) {
628  for (unsigned short pln2 = pln1 + 1; pln2 < slc.nPlanes; ++pln2) {
629  auto p1p2 = std::make_pair(pln1, pln2);
630  if (std::find(pln1pln2.begin(), pln1pln2.end(), p1p2) != pln1pln2.end()) continue;
631  // find two wires that have a valid intersection
632  for (unsigned int wire = firstWire; wire < maxWire; ++wire) {
633  auto const intersection00 = tcc.wireReadoutGeom->WireIDsIntersect(
634  geo::WireID{cstat, tpc, pln1, wire}, geo::WireID{cstat, tpc, pln2, wire});
635  if (!intersection00) continue;
636 
637  // increment by one wire in pln1 and find another valid intersection
638  auto const intersection10 = tcc.wireReadoutGeom->WireIDsIntersect(
639  geo::WireID{cstat, tpc, pln1, wire + 10}, geo::WireID{cstat, tpc, pln2, wire});
640  if (!intersection10) continue;
641 
642  // increment by one wire in pln2 and find another valid intersection
643  auto const intersection01 = tcc.wireReadoutGeom->WireIDsIntersect(
644  geo::WireID{cstat, tpc, pln1, wire}, geo::WireID{cstat, tpc, pln2, wire + 10});
645  if (!intersection01) continue;
646 
647  TCWireIntersection tcwi;
648  tcwi.tpc = tpc;
649  tcwi.pln1 = pln1;
650  tcwi.pln2 = pln2;
651  tcwi.wir1 = wire;
652  tcwi.wir2 = wire;
653  tcwi.y = intersection00->y;
654  tcwi.z = intersection00->z;
655  tcwi.dydw1 = (intersection10->y - intersection00->y) / 10;
656  tcwi.dzdw1 = (intersection10->z - intersection00->z) / 10;
657  tcwi.dydw2 = (intersection01->y - intersection00->y) / 10;
658  tcwi.dzdw2 = (intersection01->z - intersection00->z) / 10;
659  evt.wireIntersections.push_back(tcwi);
660  break;
661  } // wire
662  } // pln2
663  } // pln1
664  } // FillWireIntersections
const geo::WireReadoutGeom * wireReadoutGeom
Definition: DataStructs.h:568
TCConfig tcc
Definition: DataStructs.cxx:9
bool WireIDsIntersect(WireID const &wid1, WireID const &wid2, Point_t &intersection) const
Computes the intersection between two wires.
std::vector< TCWireIntersection > wireIntersections
Definition: DataStructs.h:631
TCEvent evt
Definition: DataStructs.cxx:8
void tca::Find2DVertices ( detinfo::DetectorPropertiesData const &  detProp,
TCSlice slc,
const CTP_t inCTP,
unsigned short  pass 
)

Definition at line 131 of file TCVertex.cxx.

References util::abs(), AttachAnyTrajToVertex(), tca::VtxStore::ChiDOF, tca::VtxStore::CTP, tca::TrajPoint::CTP, tca::TCConfig::dbg2V, tca::TCConfig::dbgSlc, DeadWireCount(), debug, DecodeCTP(), FindHammerVertices(), FindHammerVertices2(), FitVertex(), tca::VtxStore::ID, IsCloseToVertex(), kAtKink, kFixed, kHaloTj, kKilled, kOnDeadWire, kShowerLike, kStepDir, kVxIndPlnNoChg, 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::vtx2DCuts, and tca::TCSlice::vtxs.

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

135  {
136  // Find 2D vertices between pairs of tjs that have a same-end topology. Using an example
137  // where StepDir = 1 (end 0 is at small wire number) vertices will be found with Topo = 0
138  // with a vertex US of the ends (<) or Topo = 2 with a vertex DS of the ends (>). This is reversed
139  // if StepDir = -1. Vertices with Topo = 1 (/\) and (\/) are found in EndMerge.
140 
141  // tcc.vtx2DCuts fcl input usage
142  // 0 = maximum length of a short trajectory
143  // 1 = max vertex - trajectory separation for short trajectories
144  // 2 = max vertex - trajectory separation for long trajectories
145  // 3 = max position pull for adding TJs to a vertex
146  // 4 = max allowed vertex position error
147  // 5 = min MCSMom
148  // 6 = min Pts/Wire fraction
149  // 7 min Score
150  // 8 Min charge fraction near a merge point (not a vertex)
151  // 9 max MCSmom asymmetry for a merge
152  // 10 Require charge on wires between a vtx and the start of the tjs in induction planes? (1 = yes)
153 
154  if (tcc.vtx2DCuts[0] <= 0) return;
155  if (slc.tjs.size() < 2) return;
156 
157  bool firstPassCuts = (pass == 0);
158 
159  geo::PlaneID planeID = DecodeCTP(inCTP);
160 
161  // require charge between the vertex and the tj start points?
162  bool requireVtxTjChg = true;
163  if (tcc.vtx2DCuts[10] == 0 && int(planeID.Plane) < slc.nPlanes - 1) requireVtxTjChg = false;
164 
165  bool prt = (tcc.dbg2V && tcc.dbgSlc && debug.Plane == (int)planeID.Plane);
166  if (prt) {
167  mf::LogVerbatim("TC") << "prt set for CTP " << inCTP << " in Find2DVertices. firstPassCuts? "
168  << firstPassCuts << " requireVtxTjChg " << requireVtxTjChg;
169  PrintAllTraj(detProp, "F2DVi", slc, USHRT_MAX, slc.tjs.size());
170  }
171 
172  unsigned short maxShortTjLen = tcc.vtx2DCuts[0];
173  for (unsigned short it1 = 0; it1 < slc.tjs.size() - 1; ++it1) {
174  auto& tj1 = slc.tjs[it1];
175  if (tj1.AlgMod[kKilled] || tj1.AlgMod[kHaloTj]) continue;
176  if (tj1.SSID > 0 || tj1.AlgMod[kShowerLike]) continue;
177  if (tj1.CTP != inCTP) continue;
178  bool tj1Short = (TrajLength(tj1) < maxShortTjLen);
179  for (unsigned short end1 = 0; end1 < 2; ++end1) {
180  // vertex assignment exists?
181  if (tj1.VtxID[end1] > 0) continue;
182  // wrong end of a high energy electron?
183  if (tj1.PDGCode == 111 && end1 != tj1.StartEnd) continue;
184  // default condition is to use the end point to define the trajectory and direction
185  // at the end
186  short endPt1 = tj1.EndPt[end1];
187  float wire1 = tj1.Pts[endPt1].Pos[0];
188  // unless there are few points fitted, indicating that the trajectory fit
189  // may have been biased by the presence of another trajectory at the vertex or by
190  // other close unresolved tracks
191  if (tj1.Pts.size() > 6 && tj1.Pts[endPt1].NTPsFit < 4) {
192  if (end1 == 0 && endPt1 < int(tj1.Pts.size()) - 3) { endPt1 += 3; }
193  else if (end1 == 1 && endPt1 >= 3) {
194  endPt1 -= 3;
195  }
196  if (tj1.Pts[endPt1].Chg == 0) endPt1 = NearestPtWithChg(tj1, endPt1);
197  } // few points fit at end1
198  TrajPoint tp1 = tj1.Pts[endPt1];
199  MoveTPToWire(tp1, wire1);
200  // re-purpose endPt1 to reference the end point. This will be used the find the point on
201  // tj1 that is closest to the vertex position
202  endPt1 = tj1.EndPt[end1];
203  short oendPt1 = tj1.EndPt[1 - end1];
204  // reference to the other end of tj1
205  auto& otp1 = tj1.Pts[oendPt1];
206  for (unsigned short it2 = it1 + 1; it2 < slc.tjs.size(); ++it2) {
207  auto& tj2 = slc.tjs[it2];
208  if (tj2.AlgMod[kKilled] || tj2.AlgMod[kHaloTj]) continue;
209  if (tj2.SSID > 0 || tj2.AlgMod[kShowerLike]) continue;
210  if (tj2.CTP != inCTP) continue;
211  if (tj1.VtxID[end1] > 0) continue;
212  if (tj1.MCSMom < tcc.vtx2DCuts[5] && tj2.MCSMom < tcc.vtx2DCuts[5]) continue;
213  bool tj2Short = (TrajLength(tj2) < maxShortTjLen);
214  // find the end that is closer to tp1
215  unsigned short end2 = 0;
216  if (PosSep2(tj2.Pts[tj2.EndPt[1]].Pos, tp1.Pos) <
217  PosSep2(tj2.Pts[tj2.EndPt[0]].Pos, tp1.Pos))
218  end2 = 1;
219  if (tj2.VtxID[end2] > 0) continue;
220  // wrong end of a high energy electron?
221  if (tj2.PDGCode == 111 && end2 != tj2.StartEnd) continue;
222  // check for a vertex between these tjs at the other ends
223  if (tj1.VtxID[1 - end1] > 0 && tj1.VtxID[1 - end1] == tj2.VtxID[1 - end2]) continue;
224  // see if the other ends are closer
225  unsigned short oendPt2 = tj2.EndPt[1 - end2];
226  auto& otp2 = tj2.Pts[oendPt2];
227  if (PosSep2(otp1.Pos, otp2.Pos) < PosSep2(tp1.Pos, tj2.Pts[tj2.EndPt[end2]].Pos))
228  continue;
229  short endPt2 = tj2.EndPt[end2];
230  float wire2 = tj2.Pts[endPt2].Pos[0];
231  if (tj2.Pts.size() > 6 && tj2.Pts[endPt2].NTPsFit < 4) {
232  if (end2 == 0 && endPt2 < int(tj2.Pts.size()) - 3) { endPt2 += 3; }
233  else if (end2 == 1 && endPt2 >= 3) {
234  endPt2 -= 3;
235  }
236  if (tj2.Pts[endPt2].Chg == 0) endPt2 = NearestPtWithChg(tj2, endPt2);
237  } // few points fit at end1
238  TrajPoint tp2 = tj2.Pts[endPt2];
239  MoveTPToWire(tp2, wire2);
240  // re-purpose endPt2
241  endPt2 = tj2.EndPt[end2];
242  // Rough first cut on the separation between the end points of the
243  // two trajectories
244  float sepCut = 100;
245  if (std::abs(tp1.Pos[0] - tp2.Pos[0]) > sepCut) continue;
246  if (std::abs(tp1.Pos[1] - tp2.Pos[1]) > sepCut) continue;
247  float wint, tint;
248  TrajIntersection(tp1, tp2, wint, tint);
249  // make sure this is inside the TPC.
250  if (wint < 0 || wint > tcc.maxPos0[planeID.Plane] - 3) continue;
251  if (tint < 0 || tint > tcc.maxPos1[planeID.Plane]) continue;
252  // Next cut on separation between the TPs and the intersection point
253  if (tj1Short || tj2Short) { sepCut = tcc.vtx2DCuts[1]; }
254  else {
255  sepCut = tcc.vtx2DCuts[2];
256  }
257  // NewVtxCuts: require close separation on the first pass
258  if (firstPassCuts) sepCut = tcc.vtx2DCuts[1];
259  Point2_t vPos{{wint, tint}};
260  float vt1Sep = PosSep(vPos, tp1.Pos);
261  float vt2Sep = PosSep(vPos, tp2.Pos);
262  float dwc1 = DeadWireCount(slc, wint, tp1.Pos[0], tp1.CTP);
263  float dwc2 = DeadWireCount(slc, wint, tp2.Pos[0], tp1.CTP);
264  vt1Sep -= dwc1;
265  vt2Sep -= dwc2;
266  bool vtxOnDeadWire = (DeadWireCount(slc, wint, wint, tp1.CTP) == 1);
267  if (prt && vt1Sep < 200 && vt2Sep < 200) {
268  mf::LogVerbatim myprt("TC");
269  myprt << "F2DV candidate T" << tj1.ID << "_" << end1 << "-T" << tj2.ID << "_" << end2;
270  myprt << " vtx pos " << (int)wint << ":" << (int)(tint / tcc.unitsPerTick) << " tp1 "
271  << PrintPos(tp1) << " tp2 " << PrintPos(tp2);
272  myprt << " dwc1 " << dwc1 << " dwc2 " << dwc2 << " on dead wire? " << vtxOnDeadWire;
273  myprt << " vt1Sep " << vt1Sep << " vt2Sep " << vt2Sep << " sepCut " << sepCut;
274  }
275  if (vt1Sep > sepCut || vt2Sep > sepCut) continue;
276  // make sure that the other end isn't closer
277  if (PosSep(vPos, slc.tjs[it1].Pts[oendPt1].Pos) < vt1Sep) {
278  if (prt)
279  mf::LogVerbatim("TC")
280  << " tj1 other end " << PrintPos(tj1.Pts[oendPt1]) << " is closer to the vertex";
281  continue;
282  }
283  if (PosSep(vPos, slc.tjs[it2].Pts[oendPt2].Pos) < vt2Sep) {
284  if (prt)
285  mf::LogVerbatim("TC")
286  << " tj2 other end " << PrintPos(tj2.Pts[oendPt2]) << " is closer to the vertex";
287  continue;
288  }
289  // Ensure that the vertex position is close to the end of each Tj
290  unsigned short closePt1;
291  float doca1 = sepCut;
292  if (!TrajClosestApproach(tj1, wint, tint, closePt1, doca1)) continue;
293  // dpt1 (and dpt2) will be 0 if the vertex is at the end
294  short stepDir = -1;
295  if (tcc.modes[kStepDir]) stepDir = 1;
296  short dpt1 = stepDir * (closePt1 - endPt1);
297  if (prt)
298  mf::LogVerbatim("TC") << " endPt1 " << endPt1 << " closePt1 " << closePt1 << " dpt1 "
299  << dpt1 << " doca1 " << doca1;
300  if (dpt1 < -1) continue;
301  if (slc.tjs[it1].EndPt[1] > 4) {
302  if (dpt1 > 3) continue;
303  }
304  else {
305  // tighter cut for short trajectories
306  if (dpt1 > 2) continue;
307  }
308  unsigned short closePt2;
309  float doca2 = sepCut;
310  if (!TrajClosestApproach(tj2, wint, tint, closePt2, doca2)) continue;
311  short dpt2 = stepDir * (closePt2 - endPt2);
312  if (prt)
313  mf::LogVerbatim("TC") << " endPt2 " << endPt2 << " closePt2 " << closePt2 << " dpt2 "
314  << dpt2 << " doca2 " << doca2;
315  if (dpt2 < -1) continue;
316  if (slc.tjs[it2].EndPt[1] > 4) {
317  if (dpt2 > 3) continue;
318  }
319  else {
320  // tighter cut for short trajectories
321  if (dpt2 > 2) continue;
322  }
323  bool fixVxPos = false;
324  // fix the vertex position if there is a charge kink here
325  if (tj1.EndFlag[end1][kAtKink]) fixVxPos = true;
326  if (prt)
327  mf::LogVerbatim("TC") << " wint:tint " << (int)wint << ":"
328  << (int)(tint / tcc.unitsPerTick) << " fixVxPos? " << fixVxPos;
329  if (requireVtxTjChg) {
330  // ensure that there is a signal between these TPs and the vertex on most of the wires
331  bool signalBetween = true;
332  short dpt = abs(wint - tp1.Pos[0]);
333  if (dpt > 2 && !SignalBetween(tp1, wint, tcc.vtx2DCuts[6])) {
334  if (prt) mf::LogVerbatim("TC") << " Fails SignalBetween for tp1 " << dpt;
335  signalBetween = false;
336  }
337  dpt = abs(wint - tp2.Pos[0]);
338  if (dpt > 2 && !SignalBetween(tp2, wint, tcc.vtx2DCuts[6])) {
339  if (prt) mf::LogVerbatim("TC") << " Fails SignalBetween for tp2 " << dpt;
340  signalBetween = false;
341  }
342  // consider the case where the intersection point is wrong because the
343  // end TP angles are screwed up but the Tjs are close to each other near the end
344  if (!signalBetween) {
345  unsigned short ipt1, ipt2;
346  float maxSep = 3;
347  bool isClose = TrajTrajDOCA(slc, tj1, tj2, ipt1, ipt2, maxSep, false);
348  // require that they are close at the correct end
349  if (isClose) isClose = (abs(ipt1 - endPt1) < 4 && abs(ipt2 - endPt2) < 4);
350  if (isClose) {
351  if (prt)
352  mf::LogVerbatim("TC")
353  << " TrajTrajDOCA are close with minSep " << maxSep << " near "
354  << PrintPos(tj1.Pts[ipt1].Pos) << " " << PrintPos(tj2.Pts[ipt2].Pos);
355  // put the vertex at the TP that is closest to the intersection point
356  Point2_t vpos = {{wint, tint}};
357  if (PosSep2(tp1.Pos, vpos) < PosSep2(tp2.Pos, vpos)) {
358  wint = tp1.Pos[0];
359  tint = tp1.Pos[1];
360  }
361  else {
362  wint = tp2.Pos[0];
363  tint = tp2.Pos[1];
364  }
365  fixVxPos = true;
366  if (prt)
367  mf::LogVerbatim("TC")
368  << " new wint:tint " << (int)wint << ":" << (int)(tint / tcc.unitsPerTick);
369  }
370  else {
371  // closest approach > 3
372  continue;
373  }
374  } // no signal between
375  } // requireVtxTjChg
376  // make a new temporary vertex
377  VtxStore aVtx;
378  aVtx.Pos[0] = wint;
379  aVtx.Pos[1] = tint;
380  aVtx.NTraj = 0;
381  aVtx.Pass = tj1.Pass;
382  // Topo 0 has this topology (<) and Topo 2 has this (>)
383  aVtx.Topo = 2 * end1;
384  aVtx.ChiDOF = 0;
385  aVtx.CTP = inCTP;
386  aVtx.Stat[kOnDeadWire] = vtxOnDeadWire;
387  // fix the vertex position if we needed to move it significantly, or if it is on a dead wire
388  aVtx.Stat[kFixed] = fixVxPos;
389  aVtx.Stat[kVxIndPlnNoChg] = !requireVtxTjChg;
390  // try to fit it. We need to give it an ID to do that. Take the next
391  // available ID
392  unsigned short newVtxID = slc.vtxs.size() + 1;
393  aVtx.ID = newVtxID;
394  tj1.VtxID[end1] = newVtxID;
395  tj2.VtxID[end2] = newVtxID;
396  if (!FitVertex(slc, aVtx, prt)) {
397  tj1.VtxID[end1] = 0;
398  tj2.VtxID[end2] = 0;
399  continue;
400  }
401  // check proximity to nearby vertices
402  unsigned short mergeMeWithVx = IsCloseToVertex(slc, aVtx);
403  if (mergeMeWithVx > 0 && MergeWithVertex(slc, aVtx, mergeMeWithVx)) {
404  if (prt) mf::LogVerbatim("TC") << " Merged with close vertex " << mergeMeWithVx;
405  continue;
406  }
407  // Save it
408  if (!StoreVertex(slc, aVtx)) continue;
409  if (prt) {
410  mf::LogVerbatim myprt("TC");
411  myprt << " New vtx 2V" << aVtx.ID;
412  myprt << " Tjs " << tj1.ID << "_" << end1 << "-" << tj2.ID << "_" << end2;
413  myprt << " at " << std::fixed << std::setprecision(1) << aVtx.Pos[0] << ":"
414  << aVtx.Pos[1] / tcc.unitsPerTick;
415  }
416  AttachAnyTrajToVertex(slc, slc.vtxs.size() - 1, prt);
417  SetVx2Score(slc);
418  } // it2
419  } // end1
420  } // it1
421 
422  // only call these on the last pass
423  if (pass == USHRT_MAX) {
424  FindHammerVertices(slc, inCTP);
425  FindHammerVertices2(slc, inCTP);
426  }
427 
428  if (prt) PrintAllTraj(detProp, "F2DVo", slc, USHRT_MAX, USHRT_MAX);
429 
430  } // Find2DVertices
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MergeWithVertex(TCSlice &slc, VtxStore &vx, unsigned short oVxID)
Definition: TCVertex.cxx:433
std::vector< float > maxPos0
Definition: DataStructs.h:563
TCConfig tcc
Definition: DataStructs.cxx:9
vertex position fixed manually - no fitting done
Definition: DataStructs.h:88
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
step from US -> DS (true) or DS -> US (false)
Definition: DataStructs.h:522
constexpr auto abs(T v)
Returns the absolute value of the argument.
unsigned short IsCloseToVertex(const TCSlice &slc, const Vtx3Store &vx3)
Definition: TCVertex.cxx:2878
bool TrajClosestApproach(Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
Definition: Utils.cxx:2622
bool AttachAnyTrajToVertex(TCSlice &slc, unsigned short ivx, bool prt)
Definition: TCVertex.cxx:1678
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
bool FitVertex(TCSlice &slc, VtxStore &vx, std::vector< TrajPoint > &vxTPs, bool prt)
Definition: TCVertex.cxx:1992
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:1908
bool SignalBetween(const TrajPoint &tp1, const TrajPoint &tp2, const float MinWireSignalFraction)
Definition: Utils.cxx:1779
unsigned short NearestPtWithChg(const Trajectory &tj, unsigned short thePt)
Definition: Utils.cxx:3435
std::array< float, 2 > Point2_t
Definition: DataStructs.h:41
std::vector< float > maxPos1
Definition: DataStructs.h:564
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2095
DebugStuff debug
Definition: DebugStruct.cxx:4
bool dbg2V
debug 2D vertex finding
Definition: DataStructs.h:585
int Plane
Select plane.
Definition: DebugStruct.h:22
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2560
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
vertex quality is suspect - No requirement made on chg btw it and the Tj
Definition: DataStructs.h:93
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
Definition: Utils.cxx:2543
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2255
float TrajLength(const Trajectory &tj)
Definition: Utils.cxx:2582
geo::PlaneID DecodeCTP(CTP_t CTP)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
void FindHammerVertices(TCSlice &slc, const CTP_t &inCTP)
Definition: TCVertex.cxx:791
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:541
void PrintAllTraj(detinfo::DetectorPropertiesData const &detProp, std::string someText, TCSlice const &slc, unsigned short itj, unsigned short ipt, bool prtVtx)
Definition: Utils.cxx:5793
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2763
bool TrajTrajDOCA(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2407
void FindHammerVertices2(TCSlice &slc, const CTP_t &inCTP)
Definition: TCVertex.cxx:601
unsigned short tca::Find3DRecoRange ( const TCSlice slc,
const PFPStruct pfp,
unsigned short  fromPt,
unsigned short  min2DPts,
short  dir 
)

Definition at line 1338 of file PFPUtils.cxx.

References DecodeCTP(), kTP3DGood, tca::TCSlice::nPlanes, geo::PlaneID::Plane, tca::TCSlice::tjs, and tca::PFPStruct::TP3Ds.

Referenced by CanSection(), MakePFParticles(), Recover(), and ReSection().

1343  {
1344  // Scans the TP3Ds vector starting at fromPt until it finds min2DPts in two planes. It returns
1345  // with the index of that point (+1) in the TP3Ds vector. The dir variable defines the scan direction in
1346  // the TP3Ds vector
1347  if (fromPt > pfp.TP3Ds.size() - 1) return USHRT_MAX;
1348  if (pfp.TP3Ds.size() < 2 * min2DPts) return USHRT_MAX;
1349  if (dir == 0) return USHRT_MAX;
1350 
1351  std::vector<unsigned short> cntInPln(slc.nPlanes);
1352  for (std::size_t ii = 0; ii < pfp.TP3Ds.size(); ++ii) {
1353  unsigned short ipt = fromPt + ii;
1354  if (dir < 0) ipt = fromPt - ii;
1355  if (ipt >= pfp.TP3Ds.size()) break;
1356  auto& tp3d = pfp.TP3Ds[ipt];
1357  if (!tp3d.Flags[kTP3DGood]) continue;
1358  unsigned short plane = DecodeCTP(slc.tjs[tp3d.TjID - 1].CTP).Plane;
1359  ++cntInPln[plane];
1360  unsigned short enufInPlane = 0;
1361  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane)
1362  if (cntInPln[plane] >= min2DPts) ++enufInPlane;
1363  if (enufInPlane > 1) return ipt + 1;
1364  if (dir < 0 && ipt == 0) break;
1365  } // ipt
1366  return USHRT_MAX;
1367  } // Find3DRecoRange
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
TDirectory * dir
Definition: macro.C:5
geo::PlaneID DecodeCTP(CTP_t CTP)
void tca::Find3DVertices ( detinfo::DetectorPropertiesData const &  detProp,
TCSlice slc 
)

Definition at line 1258 of file TCVertex.cxx.

References util::abs(), CompleteIncomplete3DVertices(), CompleteIncomplete3DVerticesInGaps(), detinfo::DetectorPropertiesData::ConvertTicksToX(), detinfo::DetectorPropertiesData::ConvertXToTicks(), geo::CryostatID::Cryostat, tca::TCConfig::dbg3V, tca::TCConfig::dbgSlc, DecodeCTP(), evt, FindCloseHits(), tca::TCEvent::global3V_UID, tca::Vtx3Store::ID, tca::detail::SortEntry::index, kAllHits, kHaloTj, kKilled, kTjHiVx3Score, evd::kWire, geo::kX, tca::TCSlice::nPlanes, geo::WireReadoutGeom::Plane(), geo::PlaneID::Plane, PrintHit(), tca::Vtx3Store::Score, SetVx2Score(), SetVx3Score(), util::size(), tca::TCSlice::slHits, tcc, tca::TCSlice::tjs, geo::TPCID::TPC, tca::Vtx3Store::TPCID, tca::TCSlice::TPCID, tca::TCConfig::unitsPerTick, tca::detail::SortEntry::val, tca::detail::valsIncreasing(), tca::TCConfig::vtx2DCuts, tca::TCConfig::vtx3DCuts, tca::TCSlice::vtx3s, tca::TCSlice::vtxs, tca::Vtx3Store::Vx2ID, tca::VtxStore::Vx3ID, tca::Vtx3Store::Wire, geo::WireReadoutGeom::WireIDsIntersect(), tca::TCConfig::wirePitch, tca::TCConfig::wireReadoutGeom, 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().

1259  {
1260  // Create 3D vertices from 2D vertices. 3D vertices that are matched
1261  // in all three planes have Vtx2ID > 0 for all planes. This function re-scores all
1262  // 2D and 3D vertices and flags Tjs that have high-score 3D vertices
1263 
1264  if (tcc.vtx3DCuts[0] < 0) return;
1265  if (slc.vtxs.size() < 2) return;
1266 
1267  // create a array/vector of 2D vertex indices in each plane
1268  std::vector<std::vector<unsigned short>> vIndex(3);
1269  for (unsigned short ivx = 0; ivx < slc.vtxs.size(); ++ivx) {
1270  // obsolete vertex
1271  if (slc.vtxs[ivx].ID == 0) continue;
1272  geo::PlaneID planeID = DecodeCTP(slc.vtxs[ivx].CTP);
1273  if (planeID.TPC != slc.TPCID.TPC) continue;
1274  unsigned short plane = planeID.Plane;
1275  if (plane > 2) continue;
1276  vIndex[plane].push_back(ivx);
1277  }
1278 
1279  unsigned short vtxInPln = 0;
1280  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane)
1281  if (vIndex[plane].size() > 0) ++vtxInPln;
1282  if (vtxInPln < 2) return;
1283 
1284  float thirdPlanedXCut = 2 * tcc.vtx3DCuts[0];
1285  bool prt = (tcc.dbg3V && tcc.dbgSlc);
1286  if (prt) {
1287  mf::LogVerbatim("TC") << "Inside Find3DVertices. dX cut " << tcc.vtx3DCuts[0]
1288  << " thirdPlanedXCut " << thirdPlanedXCut;
1289  }
1290 
1291  size_t vsize = slc.vtxs.size();
1292  // vector of 2D vertices -> 3D vertices.
1293  std::vector<short> vPtr(vsize, -1);
1294  // fill temp vectors of 2D vertex X and X errors
1295  std::vector<float> vX(vsize, FLT_MAX);
1296 
1297  for (unsigned short ivx = 0; ivx < vsize; ++ivx) {
1298  if (slc.vtxs[ivx].ID <= 0) continue;
1299  if (slc.vtxs[ivx].Score < tcc.vtx2DCuts[7]) continue;
1300  if (slc.vtxs[ivx].Pos[0] < -0.4) continue;
1301  geo::PlaneID planeID = DecodeCTP(slc.vtxs[ivx].CTP);
1302  // Convert 2D vertex time error to X error
1303  double ticks = slc.vtxs[ivx].Pos[1] / tcc.unitsPerTick;
1304  vX[ivx] = detProp.ConvertTicksToX(ticks, planeID);
1305  } // ivx
1306 
1307  // temp vector of all 2D vertex matches
1308  std::vector<Vtx3Store> v3temp;
1309 
1310  unsigned int cstat = slc.TPCID.Cryostat;
1311  unsigned int tpc = slc.TPCID.TPC;
1312 
1313  TrajPoint tp;
1314  constexpr float maxSep = 4;
1315  float maxScore = 0;
1316  // i, j, k indicates 3 different wire planes
1317  // compare vertices in each view
1318  for (unsigned short ipl = 0; ipl < 2; ++ipl) {
1319  for (unsigned short ii = 0; ii < vIndex[ipl].size(); ++ii) {
1320  unsigned short ivx = vIndex[ipl][ii];
1321  if (vX[ivx] == FLT_MAX) continue;
1322  auto& ivx2 = slc.vtxs[ivx];
1323  if (ivx2.Pos[0] < -0.4) continue;
1324  unsigned int iWire = std::nearbyint(ivx2.Pos[0]);
1325  for (unsigned short jpl = ipl + 1; jpl < 3; ++jpl) {
1326  for (unsigned short jj = 0; jj < vIndex[jpl].size(); ++jj) {
1327  unsigned short jvx = vIndex[jpl][jj];
1328  if (vX[jvx] == FLT_MAX) continue;
1329  auto& jvx2 = slc.vtxs[jvx];
1330  if (jvx2.Pos[0] < -0.4) continue;
1331  unsigned int jWire = std::nearbyint(jvx2.Pos[0]);
1332  float dX = std::abs(vX[ivx] - vX[jvx]);
1333  if (dX > tcc.vtx3DCuts[0]) continue;
1334  if (prt) {
1335  mf::LogVerbatim("TC")
1336  << "F3DV: ipl " << ipl << " i2V" << ivx2.ID << " iX " << vX[ivx] << " jpl " << jpl
1337  << " j2V" << jvx2.ID << " jvX " << vX[jvx] << " W:T " << (int)jvx2.Pos[0] << ":"
1338  << (int)jvx2.Pos[1] << " dX " << dX;
1339  }
1340  double y = -1000, z = -1000;
1341  if (auto intersection = tcc.wireReadoutGeom->WireIDsIntersect(
1342  geo::WireID{cstat, tpc, ipl, iWire}, geo::WireID{cstat, tpc, jpl, jWire})) {
1343  y = intersection->y;
1344  z = intersection->z;
1345  }
1346  if (y < slc.yLo || y > slc.yHi || z < slc.zLo || z > slc.zHi) continue;
1347  unsigned short kpl = 3 - ipl - jpl;
1348  float kX = 0.5 * (vX[ivx] + vX[jvx]);
1349  int kWire = -1;
1350  if (slc.nPlanes > 2) {
1351  kWire =
1352  tcc.wireReadoutGeom->Plane({slc.TPCID, kpl}).WireCoordinate(geo::Point_t{0, y, z});
1353  std::array<int, 2> wireWindow;
1354  std::array<float, 2> timeWindow;
1355  wireWindow[0] = kWire - maxSep;
1356  wireWindow[1] = kWire + maxSep;
1357  float time =
1358  detProp.ConvertXToTicks(kX, kpl, (int)tpc, (int)cstat) * tcc.unitsPerTick;
1359  timeWindow[0] = time - maxSep;
1360  timeWindow[1] = time + maxSep;
1361  bool hitsNear;
1362  std::vector<unsigned int> closeHits =
1363  FindCloseHits(slc, wireWindow, timeWindow, kpl, kAllHits, true, hitsNear);
1364  if (prt) {
1365  mf::LogVerbatim myprt("TC");
1366  myprt << " Hits near " << kpl << ":" << kWire << ":"
1367  << (int)(time / tcc.unitsPerTick) << " = ";
1368  for (auto iht : closeHits)
1369  myprt << " " << PrintHit(slc.slHits[iht]);
1370  }
1371  if (!hitsNear) continue;
1372  } // 3-plane TPC
1373  // save this incomplete 3D vertex
1374  Vtx3Store v3d;
1375  // give it a non-zero ID so that SetVx3Score returns a valid score
1376  v3d.ID = 666;
1377  v3d.Vx2ID.resize(slc.nPlanes);
1378  v3d.Vx2ID[ipl] = ivx2.ID;
1379  v3d.Vx2ID[jpl] = jvx2.ID;
1380  if (slc.nPlanes == 2) v3d.Vx2ID[2] = -1;
1381  v3d.X = kX;
1382  // Use XErr to store dX
1383  v3d.XErr = dX;
1384  v3d.Y = y;
1385  v3d.Z = z;
1386  v3d.Wire = kWire;
1387  float posError = dX / tcc.vtx3DCuts[0];
1388  float vxScoreWght = 0;
1389  SetVx3Score(slc, v3d);
1390  vxScoreWght = tcc.vtx3DCuts[2] / v3d.Score;
1391  if (posError < 0.5) posError = 0;
1392  v3d.Score = posError + vxScoreWght;
1393  v3d.TPCID = slc.TPCID;
1394  // push the incomplete vertex onto the list
1395  v3temp.push_back(v3d);
1396 
1397  if (prt) {
1398  mf::LogVerbatim myprt("TC");
1399  myprt << " 2 Plane match i2V";
1400  myprt << slc.vtxs[ivx].ID << " P:W:T " << ipl << ":" << (int)slc.vtxs[ivx].Pos[0]
1401  << ":" << (int)slc.vtxs[ivx].Pos[1];
1402  myprt << " j2V" << slc.vtxs[jvx].ID << " P:W:T " << jpl << ":"
1403  << (int)slc.vtxs[jvx].Pos[0] << ":" << (int)slc.vtxs[jvx].Pos[1];
1404  myprt << std::fixed << std::setprecision(3);
1405  myprt << " dX " << dX << " posError " << posError << " vxScoreWght " << vxScoreWght
1406  << " Score " << v3d.Score;
1407  }
1408 
1409  if (slc.nPlanes == 2) continue;
1410 
1411  // look for a 3 plane match
1412  for (unsigned short kk = 0; kk < vIndex[kpl].size(); ++kk) {
1413  unsigned short kvx = vIndex[kpl][kk];
1414  float dX = std::abs(vX[kvx] - v3d.X);
1415  // Wire difference error
1416  float dW = tcc.wirePitch * std::abs(slc.vtxs[kvx].Pos[0] - kWire);
1417  if (dX > thirdPlanedXCut) continue;
1418  if (dW > tcc.vtx3DCuts[1]) continue;
1419  // put the Y,Z difference in YErr and ZErr
1420  double y = -1000, z = -1000;
1421  if (auto intersection = tcc.wireReadoutGeom->WireIDsIntersect(
1422  geo::WireID(cstat, tpc, ipl, iWire), geo::WireID(cstat, tpc, kpl, kWire))) {
1423  y = intersection->y;
1424  z = intersection->z;
1425  }
1426  v3d.YErr = y - v3d.Y;
1427  v3d.ZErr = z - v3d.Z;
1428  v3d.Vx2ID[kpl] = slc.vtxs[kvx].ID;
1429  v3d.Wire = -1;
1430  // hijack the Score variable to hold the separation^2, weighted by the
1431  // vertex3DCuts
1432  dX = (vX[kvx] - v3d.X) / tcc.vtx3DCuts[0];
1433  float dY = v3d.YErr / tcc.vtx3DCuts[1];
1434  float dZ = v3d.ZErr / tcc.vtx3DCuts[1];
1435  posError = dX * dX + dY * dY + dZ * dZ;
1436  vxScoreWght = 0;
1437  SetVx3Score(slc, v3d);
1438  vxScoreWght = tcc.vtx3DCuts[2] / v3d.Score;
1439  if (posError < 0.5) posError = 0;
1440  v3d.Score = posError + vxScoreWght;
1441  if (v3d.Score > maxScore) maxScore = v3d.Score;
1442  if (prt)
1443  mf::LogVerbatim("TC") << " k2V" << kvx + 1 << " dX " << dX << " dW " << dW
1444  << " 3D score " << v3d.Score;
1445  v3temp.push_back(v3d);
1446  } // kk
1447  } // jj
1448  } // jpl
1449  } // ii
1450  } // ipl
1451 
1452  if (v3temp.empty()) return;
1453 
1454  // We will sort this list by increasing score. First add the maxScore for 2-plane matches so that
1455  // they are considered after the 3-plane matches
1456  maxScore += 1;
1457  for (auto& v3 : v3temp)
1458  if (v3.Wire >= 0) v3.Score += maxScore;
1459 
1460  if (prt) {
1461  mf::LogVerbatim("TC") << "v3temp list";
1462  for (auto& v3 : v3temp) {
1463  if (slc.nPlanes == 2) {
1464  mf::LogVerbatim("TC") << "2V" << v3.Vx2ID[0] << " 2V" << v3.Vx2ID[1] << " wire "
1465  << v3.Wire << " Score " << v3.Score;
1466  }
1467  else {
1468  mf::LogVerbatim("TC") << "2V" << v3.Vx2ID[0] << " 2V" << v3.Vx2ID[1] << " 2V"
1469  << v3.Vx2ID[2] << " wire " << v3.Wire << " Score " << v3.Score;
1470  }
1471  } // v3
1472  }
1473  SortEntry sEntry;
1474  std::vector<SortEntry> sortVec(v3temp.size());
1475  for (unsigned short ivx = 0; ivx < v3temp.size(); ++ivx) {
1476  sEntry.index = ivx;
1477  sEntry.val = v3temp[ivx].Score;
1478  sortVec[ivx] = sEntry;
1479  } // ivx
1480  if (sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(), valsIncreasing);
1481  // create a new vector of selected 3D vertices
1482  std::vector<Vtx3Store> v3sel;
1483  for (unsigned short ii = 0; ii < sortVec.size(); ++ii) {
1484  unsigned short ivx = sortVec[ii].index;
1485  // ensure that all 2D vertices are unique
1486  bool skipit = false;
1487  for (auto& v3 : v3sel) {
1488  for (unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
1489  if (v3temp[ivx].Vx2ID[ipl] == 0) continue;
1490  if (v3temp[ivx].Vx2ID[ipl] == v3.Vx2ID[ipl]) {
1491  skipit = true;
1492  break;
1493  }
1494  } // ipl
1495  if (skipit) break;
1496  } // v3
1497  if (skipit) continue;
1498  v3sel.push_back(v3temp[ivx]);
1499  } // ii
1500  v3temp.clear();
1501 
1502  if (prt) {
1503  mf::LogVerbatim myprt("TC");
1504  myprt << "v3sel list\n";
1505  for (auto& v3d : v3sel) {
1506  for (auto vx2id : v3d.Vx2ID)
1507  if (vx2id > 0) myprt << " 2V" << vx2id;
1508  myprt << " wire " << v3d.Wire << " Score " << v3d.Score;
1509  myprt << "\n";
1510  } // v3d
1511  } // prt
1512 
1513  // Count the number of incomplete vertices and store
1514  unsigned short ninc = 0;
1515  for (auto& vx3 : v3sel) {
1516  if (slc.nPlanes == 3 && vx3.Wire >= 0) ++ninc;
1517  vx3.ID = slc.vtx3s.size() + 1;
1518  ++evt.global3V_UID;
1519  vx3.UID = evt.global3V_UID;
1520  if (prt) {
1521  mf::LogVerbatim myprt("TC");
1522  myprt << " 3V" << vx3.ID;
1523  for (auto v2id : vx3.Vx2ID)
1524  myprt << " 2V" << v2id;
1525  myprt << " wire " << vx3.Wire;
1526  } // prt
1527  slc.vtx3s.push_back(vx3);
1528  // make the 2D -> 3D associations
1529  for (unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
1530  if (vx3.Vx2ID[ipl] == 0) continue;
1531  VtxStore& vx2 = slc.vtxs[vx3.Vx2ID[ipl] - 1];
1532  vx2.Vx3ID = vx3.ID;
1533  } // ipl
1534  } // ivx
1535 
1536  // Try to complete incomplete vertices
1537  if (ninc > 0) {
1538  CompleteIncomplete3DVerticesInGaps(detProp, slc);
1539  CompleteIncomplete3DVertices(detProp, slc);
1540  }
1541 
1542  // Score and flag Tjs that are attached to high-score vertices
1543  // First remove Tj vertex flags
1544  for (auto& tj : slc.tjs) {
1545  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
1546  geo::PlaneID planeID = DecodeCTP(tj.CTP);
1547  if (planeID.TPC != tpc || planeID.Cryostat != cstat) continue;
1548  tj.AlgMod[kTjHiVx3Score] = false;
1549  } // tj
1550  // Score the 2D vertices
1551  for (auto& vx2 : slc.vtxs) {
1552  if (vx2.ID == 0) continue;
1553  geo::PlaneID planeID = DecodeCTP(vx2.CTP);
1554  if (planeID.TPC != tpc || planeID.Cryostat != cstat) continue;
1555  SetVx2Score(slc, vx2);
1556  } // vx2
1557  // and the 3D vertices
1558  for (auto& vx3 : slc.vtx3s) {
1559  if (vx3.ID == 0) continue;
1560  SetVx3Score(slc, vx3);
1561  } // vx3
1562 
1563  } // Find3DVertices
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
static unsigned int kWire
void CompleteIncomplete3DVerticesInGaps(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc)
Definition: TCVertex.cxx:2376
const geo::WireReadoutGeom * wireReadoutGeom
Definition: DataStructs.h:568
std::vector< float > vtx3DCuts
2D vtx -> 3D vtx matching cuts
Definition: DataStructs.h:542
TCConfig tcc
Definition: DataStructs.cxx:9
Float_t y
Definition: compare.C:6
Double_t z
Definition: plot.C:276
Planes which measure X direction.
Definition: geo_types.h:136
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
constexpr auto abs(T v)
Returns the absolute value of the argument.
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:195
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
void SetVx3Score(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2225
tick ticks
Alias for common language habits.
Definition: electronics.h:76
void CompleteIncomplete3DVertices(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc)
Definition: TCVertex.cxx:2470
bool dbg3V
debug 3D vertex finding
Definition: DataStructs.h:589
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
std::vector< unsigned int > FindCloseHits(const 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:2774
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6347
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
bool valsIncreasing(const SortEntry &c1, const SortEntry &c2)
Definition: Utils.cxx:43
bool WireIDsIntersect(WireID const &wid1, WireID const &wid2, Point_t &intersection) const
Computes the intersection between two wires.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:180
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2255
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:541
PlaneGeo const & Plane(TPCID const &tpcid, View_t view) const
Returns the specified wire.
TCEvent evt
Definition: DataStructs.cxx:8
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:315
void tca::FindAlongTrans ( Point3_t  pos1,
Vector3_t  dir1,
Point3_t  pos2,
Point2_t alongTrans 
)

Definition at line 3066 of file PFPUtils.cxx.

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

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

3067  {
3068  // Calculate the distance along and transvers to the direction vector from pos1 to pos2
3069  alongTrans[0] = 0;
3070  alongTrans[1] = 0;
3071  if (pos1[0] == pos2[0] && pos1[1] == pos2[1] && pos1[2] == pos2[2]) return;
3072  auto ptDir = PointDirection(pos1, pos2);
3073  SetMag(dir1, 1.0);
3074  double costh = DotProd(dir1, ptDir);
3075  if (costh > 1) costh = 1;
3076  double sep = PosSep(pos1, pos2);
3077  alongTrans[0] = costh * sep;
3078  double sinth = sqrt(1 - costh * costh);
3079  alongTrans[1] = sinth * sep;
3080  } // FindAlongTrans
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:2538
bool SetMag(Vector3_t &v1, double mag)
Definition: PFPUtils.cxx:2570
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:126
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
void tca::FindAlongTrans ( Point2_t  pos1,
Vector2_t  dir1,
Point2_t  pos2,
Point2_t alongTrans 
)

Definition at line 3281 of file Utils.cxx.

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

3282  {
3283  // Calculate the distance along and transverse to the direction vector dir1 from pos1 to pos2
3284  alongTrans[0] = 0;
3285  alongTrans[1] = 0;
3286  if (pos1[0] == pos2[0] && pos1[1] == pos2[1]) return;
3287  pos1[0] = pos2[0] - pos1[0];
3288  pos1[1] = pos2[1] - pos1[1];
3289  double sep = sqrt(pos1[0] * pos1[0] + pos1[1] * pos1[1]);
3290  if (sep < 1E-6) return;
3291  Vector2_t ptDir;
3292  ptDir[0] = pos1[0] / sep;
3293  ptDir[1] = pos1[1] / sep;
3294  SetMag(dir1, 1.0);
3295  double costh = DotProd(dir1, ptDir);
3296  if (costh > 1.0 || costh < -1.0) return;
3297  alongTrans[0] = costh * sep;
3298  double sinth = sqrt(1 - costh * costh);
3299  alongTrans[1] = sinth * sep;
3300  } // FindAlongTrans
bool SetMag(Vector2_t &v1, double mag)
Definition: Utils.cxx:3269
Float_t E
Definition: plot.C:20
std::array< double, 2 > Vector2_t
Definition: DataStructs.h:42
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:126
std::vector< unsigned int > tca::FindCloseHits ( const 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 2774 of file Utils.cxx.

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

Referenced by AddLAHits(), AddPointsInRange(), ChgFracNearPos(), ChkBegin(), ChkStopEndPts(), Find3DVertices(), Forecast(), MakeHaloTj(), ReversePropagate(), and SetTPEnvironment().

2781  {
2782  // returns a vector of hits that are within the Window[Pos0][Pos1] in plane.
2783  // Note that hits on wire wireWindow[1] are returned as well. The definition of close
2784  // depends on setting of usePeakTime. If UsePeakTime is true, a hit is considered nearby if
2785  // the PeakTime is within the window. This is shown schematically here where
2786  // the time is on the horizontal axis and a "-" denotes a valid entry
2787  // timeWindow -----------------
2788  // hit PeakTime + close
2789  // hit PeakTime + not close
2790  // If usePeakTime is false, a hit is considered nearby if the hit StartTick and EndTick overlap with the timeWindow
2791  // Time window ---------
2792  // Hit StartTick-EndTick -------- close
2793  // Hit StartTick - EndTick -------- not close
2794 
2795  hitsNear = false;
2796  std::vector<unsigned int> closeHits;
2797  if (plane > slc.firstWire.size() - 1) return closeHits;
2798  // window in the wire coordinate
2799  int loWire = wireWindow[0];
2800  if (loWire < (int)slc.firstWire[plane]) loWire = slc.firstWire[plane];
2801  int hiWire = wireWindow[1];
2802  if (hiWire > (int)slc.lastWire[plane] - 1) hiWire = slc.lastWire[plane] - 1;
2803  // window in the time coordinate
2804  float minTick = timeWindow[0] / tcc.unitsPerTick;
2805  float maxTick = timeWindow[1] / tcc.unitsPerTick;
2806  for (int wire = loWire; wire <= hiWire; ++wire) {
2807  // Set hitsNear if the wire is dead
2808  if (!evt.goodWire[plane][wire]) hitsNear = true;
2809  if (slc.wireHitRange[plane][wire].first == UINT_MAX) continue;
2810  unsigned int firstHit = slc.wireHitRange[plane][wire].first;
2811  unsigned int lastHit = slc.wireHitRange[plane][wire].second;
2812  for (unsigned int iht = firstHit; iht <= lastHit; ++iht) {
2813  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2814  if (usePeakTime) {
2815  if (hit.PeakTime() < minTick) continue;
2816  if (hit.PeakTime() > maxTick) break;
2817  }
2818  else {
2819  int hiLo = minTick;
2820  if (hit.StartTick() > hiLo) hiLo = hit.StartTick();
2821  int loHi = maxTick;
2822  if (hit.EndTick() < loHi) loHi = hit.EndTick();
2823  if (loHi < hiLo) continue;
2824  if (hiLo > loHi) break;
2825  }
2826  hitsNear = true;
2827  bool takeit = (hitRequest == kAllHits);
2828  if (hitRequest == kUsedHits && slc.slHits[iht].InTraj > 0) takeit = true;
2829  if (hitRequest == kUnusedHits && slc.slHits[iht].InTraj == 0) takeit = true;
2830  if (takeit) closeHits.push_back(iht);
2831  } // iht
2832  } // wire
2833  return closeHits;
2834  } // FindCloseHits
TCConfig tcc
Definition: DataStructs.cxx:9
for(Int_t i=0;i< nentries;i++)
Definition: comparison.C:30
if(nlines<=0)
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:622
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
bool tca::FindCloseHits ( TCSlice const &  slc,
TrajPoint tp,
float const  maxDelta,
HitStatus_t  hitRequest 
)

Definition at line 2837 of file Utils.cxx.

References tca::TCEvent::allHits, tca::TrajPoint::CTP, DecodeCTP(), tca::TrajPoint::Environment, evt, tca::TCSlice::firstWire, tca::TCEvent::goodWire, tca::TrajPoint::Hits, kAllHits, kEnvNotGoodWire, 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().

2841  {
2842  // Fills tp.Hits sets tp.UseHit true for hits that are close to tp.Pos. Returns true if there are
2843  // close hits OR if the wire at this position is dead
2844 
2845  tp.Hits.clear();
2846  tp.UseHit.reset();
2847  tp.Environment.reset();
2848  if (!WireHitRangeOK(slc, tp.CTP)) { return false; }
2849 
2850  if (tp.Pos[0] < -0.4) return false;
2851  unsigned short plane = DecodeCTP(tp.CTP).Plane;
2852  unsigned int wire = std::nearbyint(tp.Pos[0]);
2853  if (wire < slc.firstWire[plane]) return false;
2854  if (wire > slc.lastWire[plane] - 1) return false;
2855 
2856  // dead wire
2857  if (!evt.goodWire[plane][wire]) {
2858  tp.Environment[kEnvNotGoodWire] = true;
2859  return true;
2860  }
2861  tp.Environment[kEnvNotGoodWire] = false;
2862  // live wire with no hits
2863  if (slc.wireHitRange[plane][wire].first == UINT_MAX) return false;
2864 
2865  unsigned int firstHit = slc.wireHitRange[plane][wire].first;
2866  unsigned int lastHit = slc.wireHitRange[plane][wire].second;
2867 
2868  float fwire = wire;
2869  for (unsigned int iht = firstHit; iht <= lastHit; ++iht) {
2870  if ((unsigned int)slc.slHits[iht].InTraj > slc.tjs.size()) continue;
2871  bool useit = (hitRequest == kAllHits);
2872  if (hitRequest == kUsedHits && slc.slHits[iht].InTraj > 0) useit = true;
2873  if (hitRequest == kUnusedHits && slc.slHits[iht].InTraj == 0) useit = true;
2874  if (!useit) continue;
2875  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2876  float ftime = tcc.unitsPerTick * hit.PeakTime();
2877  float delta = PointTrajDOCA(fwire, ftime, tp);
2878  if (delta < maxDelta) tp.Hits.push_back(iht);
2879  } // iht
2880  if (tp.Hits.size() > 16) { tp.Hits.resize(16); }
2881  // Set UseHit false. The calling routine should decide if these hits should be used
2882  tp.UseHit.reset();
2883  return (!tp.Hits.empty());
2884 
2885  } // FindCloseHits
TCConfig tcc
Definition: DataStructs.cxx:9
float PointTrajDOCA(float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2524
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:622
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
Detector simulation of raw signals on wires.
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
bool WireHitRangeOK(TCSlice const &slc, const CTP_t &inCTP)
Definition: Utils.cxx:4511
std::vector< int > tca::FindCloseTjs ( const TCSlice slc,
const TrajPoint fromTp,
const TrajPoint toTp,
const float &  maxDelta 
)

Definition at line 2908 of file Utils.cxx.

References tca::TCEvent::allHits, tca::TrajPoint::CTP, DecodeCTP(), evt, tca::TCSlice::firstWire, if(), 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().

2912  {
2913  // Returns a list of Tj IDs that have hits within distance maxDelta on a line drawn between the two Tps as shown
2914  // graphically here, where a "*" is a Tp and "|" and "-" are the boundaries of the region that is checked
2915  //
2916  // ---------------
2917  // | |
2918  // * *
2919  // | |
2920  // ---------------
2921  // If the wire positions of fromTp and toTp are the same, a different region is checked as shown here
2922  //
2923  // -----------
2924  // | |
2925  // | * |
2926  // | |
2927  // -----------
2928 
2929  std::vector<int> tmp;
2930  if (fromTp.Pos[0] < -0.4 || toTp.Pos[0] < -0.4) return tmp;
2931 
2932  TrajPoint tp;
2933  // Make the tp so that stepping is positive
2934  unsigned int firstWire, lastWire;
2935  if (toTp.Pos[0] > fromTp.Pos[0]) {
2936  if (!MakeBareTrajPoint(fromTp, toTp, tp)) return tmp;
2937  firstWire = std::nearbyint(fromTp.Pos[0]);
2938  lastWire = std::nearbyint(toTp.Pos[0]);
2939  }
2940  else if (toTp.Pos[0] < fromTp.Pos[0]) {
2941  if (!MakeBareTrajPoint(toTp, fromTp, tp)) return tmp;
2942  firstWire = std::nearbyint(toTp.Pos[0]);
2943  lastWire = std::nearbyint(fromTp.Pos[0]);
2944  }
2945  else {
2946  tp.Pos = fromTp.Pos;
2947  float tmp = fromTp.Pos[0] - maxDelta;
2948  if (tmp < 0) tmp = 0;
2949  firstWire = std::nearbyint(tmp);
2950  tmp = fromTp.Pos[0] + maxDelta;
2951  lastWire = std::nearbyint(tmp);
2952  }
2953 
2954  unsigned short plane = DecodeCTP(tp.CTP).Plane;
2955 
2956  if (firstWire < slc.firstWire[plane]) firstWire = slc.firstWire[plane];
2957  if (firstWire > slc.lastWire[plane] - 1) return tmp;
2958  if (lastWire < slc.firstWire[plane]) return tmp;
2959  if (lastWire > slc.lastWire[plane] - 1) lastWire = slc.lastWire[plane] - 1;
2960 
2961  for (unsigned int wire = firstWire; wire <= lastWire; ++wire) {
2962  if (slc.wireHitRange[plane][wire].first == UINT_MAX) continue;
2963  MoveTPToWire(tp, (float)wire);
2964  // Find the tick range at this position
2965  float minTick = (tp.Pos[1] - maxDelta) / tcc.unitsPerTick;
2966  float maxTick = (tp.Pos[1] + maxDelta) / tcc.unitsPerTick;
2967  unsigned int firstHit = slc.wireHitRange[plane][wire].first;
2968  unsigned int lastHit = slc.wireHitRange[plane][wire].second;
2969  for (unsigned int iht = firstHit; iht <= lastHit; ++iht) {
2970  if (slc.slHits[iht].InTraj <= 0) continue;
2971  if ((unsigned int)slc.slHits[iht].InTraj > slc.tjs.size()) continue;
2972  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2973  if (hit.PeakTime() < minTick) continue;
2974  // Hits are sorted by increasing time so we can break when maxTick is reached
2975  if (hit.PeakTime() > maxTick) break;
2976  if (std::find(tmp.begin(), tmp.end(), slc.slHits[iht].InTraj) != tmp.end()) continue;
2977  tmp.push_back(slc.slHits[iht].InTraj);
2978  } // iht
2979  } // wire
2980 
2981  return tmp;
2982 
2983  } // FindCloseTjs
TCConfig tcc
Definition: DataStructs.cxx:9
Float_t tmp
Definition: plot.C:35
if(nlines<=0)
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
bool MakeBareTrajPoint(const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
Definition: Utils.cxx:4059
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
Detector simulation of raw signals on wires.
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2763
TCEvent evt
Definition: DataStructs.cxx:8
void tca::FindCots ( std::string  inFcnLabel,
TCSlice slc,
const CTP_t inCTP,
std::vector< std::vector< int >> &  tjLists,
bool  prt 
)
void tca::FindHammerVertices ( TCSlice slc,
const CTP_t inCTP 
)

Definition at line 791 of file TCVertex.cxx.

References util::abs(), 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, kShowerLike, MakeVertexObsolete(), tca::TCConfig::modes, tca::VtxStore::NTraj, tca::VtxStore::Pass, tca::VtxStore::Pos, PrintPos(), SetPDGCode(), SetVx2Score(), SplitTraj(), StoreVertex(), tcc, tca::TCSlice::tjs, tca::VtxStore::Topo, TrajClosestApproach(), TrajIntersection(), TrajPointTrajDOCA(), tca::TCConfig::useAlg, and tca::TCSlice::vtxs.

Referenced by Find2DVertices().

792  {
793  // Look for a trajectory that intersects another. Split
794  // the trajectory and make a vertex. The convention used
795  // is shown pictorially here. Trajectory tj1 must be longer
796  // than tj2
797  // tj2 ------
798  // tj1 /
799  // tj1 /
800  // tj1 /
801 
802  if (!tcc.useAlg[kHamVx]) return;
803 
804  bool prt = (tcc.modes[kDebug] && tcc.dbgSlc && tcc.dbgAlg[kHamVx]);
805  if (prt) { mf::LogVerbatim("TC") << "Inside HamVx inCTP " << inCTP; }
806 
807  for (unsigned short it1 = 0; it1 < slc.tjs.size(); ++it1) {
808  if (slc.tjs[it1].CTP != inCTP) continue;
809  if (slc.tjs[it1].AlgMod[kKilled] || slc.tjs[it1].AlgMod[kHaloTj]) continue;
810  if (slc.tjs[it1].AlgMod[kShowerLike]) continue;
811  if (slc.tjs[it1].AlgMod[kJunkTj]) continue;
812  if (slc.tjs[it1].PDGCode == 111) continue;
813  // minimum length requirements
814  unsigned short tj1len = slc.tjs[it1].EndPt[1] - slc.tjs[it1].EndPt[0] + 1;
815  if (tj1len < 5) continue;
816  // require high MCSMom
817  if (slc.tjs[it1].MCSMom < 50) continue;
818  if (prt) mf::LogVerbatim("TC") << "FHV: intersection T" << slc.tjs[it1].ID << " candidate";
819  // Check each end of tj1
820  bool didaSplit = false;
821  for (unsigned short end1 = 0; end1 < 2; ++end1) {
822  // vertex assignment exists?
823  if (slc.tjs[it1].VtxID[end1] > 0) continue;
824  unsigned short endPt1 = slc.tjs[it1].EndPt[end1];
825  for (unsigned short it2 = 0; it2 < slc.tjs.size(); ++it2) {
826  if (slc.tjs[it2].CTP != inCTP) continue;
827  if (it1 == it2) continue;
828  if (slc.tjs[it2].AlgMod[kKilled] || slc.tjs[it2].AlgMod[kHaloTj]) continue;
829  if (slc.tjs[it2].AlgMod[kJunkTj]) continue;
830  if (slc.tjs[it2].PDGCode == 111) continue;
831  // length of tj2 cut
832  unsigned short tj2len = slc.tjs[it2].EndPt[1] - slc.tjs[it2].EndPt[0] + 1;
833  if (tj2len < 6) continue;
834  // ignore very long straight trajectories (probably a cosmic muon)
835  if (tj2len > 200 && slc.tjs[it2].PDGCode == 13 && slc.tjs[it2].MCSMom > 600) continue;
836  float minDOCA = 5;
837  minDOCA /= std::abs(slc.tjs[it1].Pts[endPt1].Dir[0]);
838  float doca = minDOCA;
839  unsigned short closePt2 = 0;
840  TrajPointTrajDOCA(slc.tjs[it1].Pts[endPt1], slc.tjs[it2], closePt2, doca);
841  if (doca == minDOCA) continue;
842  // ensure that the closest point is not near an end
843  if (prt)
844  mf::LogVerbatim("TC") << "FHV: Candidate T" << slc.tjs[it1].ID << " T"
845  << slc.tjs[it2].ID << " doca " << doca << " tj2.EndPt[0] "
846  << slc.tjs[it2].EndPt[0] << " closePt2 " << closePt2
847  << " tj2.EndPt[1] " << slc.tjs[it2].EndPt[1];
848  if (closePt2 < slc.tjs[it2].EndPt[0] + 3) continue;
849  if (closePt2 > slc.tjs[it2].EndPt[1] - 3) continue;
850  // make an angle cut
851  float dang = DeltaAngle(slc.tjs[it1].Pts[endPt1].Ang, slc.tjs[it2].Pts[closePt2].Ang);
852  if (prt)
853  mf::LogVerbatim("TC") << " dang " << dang << " imposing a hard cut of 0.4 for now ";
854  if (dang < 0.4) continue;
855  // check the cleanliness in this area
856  std::vector<int> tjids(2);
857  tjids[0] = slc.tjs[it1].ID;
858  tjids[1] = slc.tjs[it2].ID;
859  float chgFrac = ChgFracNearPos(slc, slc.tjs[it2].Pts[closePt2].Pos, tjids);
860  if (prt) mf::LogVerbatim("TC") << " chgFrac " << chgFrac;
861  if (chgFrac < 0.9) continue;
862  Point2_t vxpos = slc.tjs[it2].Pts[closePt2].Pos;
863  // get a better estimate of the vertex position
865  slc.tjs[it1].Pts[endPt1], slc.tjs[it2].Pts[closePt2], vxpos[0], vxpos[1]);
866  // and a better estimate of the point on tj2 where the split should be made
867  doca = minDOCA;
868  TrajClosestApproach(slc.tjs[it2], vxpos[0], vxpos[1], closePt2, doca);
869  if (prt)
870  mf::LogVerbatim("TC") << " better pos " << PrintPos(vxpos) << " new closePt2 "
871  << closePt2;
872  // create a new vertex
873  VtxStore aVtx;
874  aVtx.Pos = vxpos;
875  aVtx.NTraj = 3;
876  aVtx.Pass = slc.tjs[it2].Pass;
877  aVtx.Topo = 5;
878  aVtx.ChiDOF = 0;
879  aVtx.CTP = inCTP;
880  aVtx.ID = slc.vtxs.size() + 1;
881  if (!StoreVertex(slc, aVtx)) continue;
882  unsigned short ivx = slc.vtxs.size() - 1;
883  if (!SplitTraj(slc, it2, closePt2, ivx, prt)) {
884  if (prt) mf::LogVerbatim("TC") << "FHV: Failed to split trajectory";
885  MakeVertexObsolete("HamVx", slc, slc.vtxs[slc.vtxs.size() - 1], true);
886  continue;
887  }
888  slc.tjs[it1].VtxID[end1] = slc.vtxs[ivx].ID;
889  slc.tjs[it1].AlgMod[kHamVx] = true;
890  slc.tjs[it2].AlgMod[kHamVx] = true;
891  unsigned short newTjIndex = slc.tjs.size() - 1;
892  slc.tjs[newTjIndex].AlgMod[kHamVx] = true;
893  SetVx2Score(slc);
894  // Update the PDGCode for the chopped trajectory
895  SetPDGCode(slc, it2);
896  // and for the new trajectory
897  SetPDGCode(slc, newTjIndex);
898  if (prt) {
899  auto& vx2 = slc.vtxs[ivx];
900  mf::LogVerbatim myprt("TC");
901  myprt << " new 2V" << vx2.ID << " Score " << vx2.Score << " Tjs";
902  auto tjlist = GetAssns(slc, "2V", vx2.ID, "T");
903  for (auto tid : tjlist)
904  myprt << " t" << tid;
905  }
906  didaSplit = true;
907  break;
908  } // tj2
909  if (didaSplit) break;
910  } // end1
911  } // tj1
912 
913  } // FindHammerVertices
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeVertexObsolete(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2789
void SetPDGCode(TCSlice &slc, unsigned short itj)
Definition: Utils.cxx:4219
TCConfig tcc
Definition: DataStructs.cxx:9
constexpr auto abs(T v)
Returns the absolute value of the argument.
bool TrajClosestApproach(Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
Definition: Utils.cxx:2622
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:2531
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:1908
std::array< float, 2 > Point2_t
Definition: DataStructs.h:41
float ChgFracNearPos(const TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3163
bool SplitTraj(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, unsigned short itj, float XPos, bool makeVx2, bool prt)
Definition: Utils.cxx:2223
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
std::vector< int > GetAssns(TCSlice const &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4704
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
Definition: Utils.cxx:2543
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2255
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:579
void TrajPointTrajDOCA(TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
Definition: Utils.cxx:2384
master switch for turning on debug mode
Definition: DataStructs.h:524
void tca::FindHammerVertices2 ( TCSlice slc,
const CTP_t inCTP 
)

Definition at line 601 of file TCVertex.cxx.

References AttachAnyTrajToVertex(), tca::VtxStore::ChiDOF, tca::VtxStore::CTP, tca::TCConfig::dbgAlg, tca::TCConfig::dbgSlc, DeltaAngle(), dir, tca::VtxStore::ID, if(), kDebug, kHaloTj, kHamVx, kHamVx2, kJunkTj, kKilled, kShowerLike, kTestBeam, MakeVertexObsolete(), 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().

602  {
603  // Variant of FindHammerVertices with slightly different requirements:
604  // 1) tj1 is a straight trajectory with most of the points fit
605  // 2) No angle requirement between tj1 and tj2
606  // 3) Large charge near the intersection point X on tj2
607  // tj2 ---X---
608  // tj1 /
609  // tj1 /
610  // tj1 /
611  // minimum^2 DOCA of tj1 endpoint with tj2
612 
613  if (!tcc.useAlg[kHamVx2]) return;
614  // This wasn't written for test beam events
615  if (tcc.modes[kTestBeam]) return;
616 
617  bool prt = (tcc.modes[kDebug] && tcc.dbgSlc && tcc.dbgAlg[kHamVx2]);
618  if (prt) mf::LogVerbatim("TC") << "Inside HamVx2";
619 
620  for (unsigned short it1 = 0; it1 < slc.tjs.size(); ++it1) {
621  if (slc.tjs[it1].CTP != inCTP) continue;
622  if (slc.tjs[it1].AlgMod[kKilled] || slc.tjs[it1].AlgMod[kHaloTj]) continue;
623  if (slc.tjs[it1].AlgMod[kHamVx]) continue;
624  if (slc.tjs[it1].AlgMod[kHamVx2]) continue;
625  if (slc.tjs[it1].AlgMod[kJunkTj]) continue;
626  if (slc.tjs[it1].PDGCode == 111) continue;
627  unsigned short numPtsWithCharge1 = NumPtsWithCharge(slc, slc.tjs[it1], false);
628  if (numPtsWithCharge1 < 6) continue;
629  // require high MCSMom
630  if (slc.tjs[it1].MCSMom < 200) continue;
631  // Check each end of tj1
632  bool didaSplit = false;
633  for (unsigned short end1 = 0; end1 < 2; ++end1) {
634  // vertex assignment exists?
635  if (slc.tjs[it1].VtxID[end1] > 0) continue;
636  unsigned short endPt1 = slc.tjs[it1].EndPt[end1];
637  for (unsigned short it2 = 0; it2 < slc.tjs.size(); ++it2) {
638  if (it1 == it2) continue;
639  if (slc.tjs[it2].AlgMod[kKilled] || slc.tjs[it2].AlgMod[kHaloTj]) continue;
640  if (slc.tjs[it2].AlgMod[kHamVx]) continue;
641  if (slc.tjs[it2].AlgMod[kHamVx2]) continue;
642  // require that both be in the same CTP
643  if (slc.tjs[it2].CTP != inCTP) continue;
644  if (slc.tjs[it2].AlgMod[kShowerLike]) continue;
645  if (slc.tjs[it2].AlgMod[kJunkTj]) continue;
646  if (slc.tjs[it2].PDGCode == 111) continue;
647  unsigned short numPtsWithCharge2 = NumPtsWithCharge(slc, slc.tjs[it2], true);
648  if (numPtsWithCharge2 < 6) continue;
649  // ignore muon-like tjs
650  if (numPtsWithCharge2 > 100 && slc.tjs[it2].MCSMom > 500) continue;
651  // Find the minimum separation between tj1 and tj2
652  float minDOCA = 5;
653  float doca = minDOCA;
654  unsigned short closePt2 = 0;
655  TrajPointTrajDOCA(slc.tjs[it1].Pts[endPt1], slc.tjs[it2], closePt2, doca);
656  if (doca == minDOCA) continue;
657  if (prt) {
658  mf::LogVerbatim myprt("TC");
659  auto& tj1 = slc.tjs[it1];
660  auto& tj2 = slc.tjs[it2];
661  myprt << " FHV2 CTP" << tj1.CTP;
662  myprt << " t" << tj1.ID << "_" << end1 << " MCSMom " << tj1.MCSMom << " ChgRMS "
663  << tj1.ChgRMS;
664  myprt << " split t" << tj2.ID << "? MCSMom " << tj2.MCSMom << " ChgRMS " << tj2.ChgRMS;
665  myprt << " doca " << doca << " tj2.EndPt[0] " << tj2.EndPt[0] << " closePt2 "
666  << closePt2;
667  myprt << " tj2.EndPt[1] " << tj2.EndPt[1];
668  } // prt
669  // ensure that the closest point is not near an end
670  if (closePt2 < slc.tjs[it2].EndPt[0] + 3) continue;
671  if (closePt2 > slc.tjs[it2].EndPt[1] - 3) continue;
672  // Find the intersection point between the tj1 end and tj2 closest Pt
673  float wint, tint;
674  TrajIntersection(slc.tjs[it1].Pts[endPt1], slc.tjs[it2].Pts[closePt2], wint, tint);
675  // make an angle cut
676  float dang = DeltaAngle(slc.tjs[it1].Pts[endPt1].Ang, slc.tjs[it2].Pts[closePt2].Ang);
677  if (dang < 0.2) continue;
678  // ensure that tj1 doesn't cross tj2 but ensuring that the closest point on tj1 is at closePt1
679  doca = 5;
680  unsigned short closePt1 = 0;
681  TrajPointTrajDOCA(slc.tjs[it2].Pts[closePt2], slc.tjs[it1], closePt1, doca);
682  if (closePt1 != endPt1) continue;
683  if (prt)
684  mf::LogVerbatim("TC") << " intersection W:T " << (int)wint << ":"
685  << (int)(tint / tcc.unitsPerTick) << " dang " << dang;
686  // Find the point on tj2 that is closest to this point, overwriting closePt
687  doca = minDOCA;
688  // the point on tj2 that is closest to the intersection point
689  unsigned short intPt2;
690  TrajClosestApproach(slc.tjs[it2], wint, tint, intPt2, doca);
691  if (prt)
692  mf::LogVerbatim("TC") << " intPt2 on tj2 " << intPt2 << " at Pos "
693  << PrintPos(slc.tjs[it2].Pts[intPt2]) << " doca " << doca;
694  if (doca == minDOCA) continue;
695  // find the MCSMom for both sections of tj2
696  float mcsmom = slc.tjs[it2].MCSMom;
697  float mcsmom1 = MCSMom(slc, slc.tjs[it2], slc.tjs[it2].EndPt[0], intPt2);
698  float mcsmom2 = MCSMom(slc, slc.tjs[it2], intPt2, slc.tjs[it2].EndPt[1]);
699  // require that the both MCSMoms be greater than
700  if (prt)
701  mf::LogVerbatim("TC") << " Check MCSMom after split: mcsmom1 " << mcsmom1 << " mcsmom2 "
702  << mcsmom2;
703  if (mcsmom1 < mcsmom || mcsmom2 < mcsmom) continue;
704  // start scanning for the point on tj2 that has the best IP with the end of tj1 in the direction
705  // from closePt2 -> endPt2
706  short dir = 1;
707  if (intPt2 < closePt2) dir = -1;
708  unsigned short nit = 0;
709  unsigned short ipt = intPt2;
710  float mostChg = slc.tjs[it2].Pts[ipt].Chg;
711  if (prt)
712  mf::LogVerbatim("TC") << " ipt " << ipt << " at Pos " << PrintPos(slc.tjs[it2].Pts[ipt])
713  << " chg " << mostChg;
714  while (nit < 20) {
715  ipt += dir;
716  if (ipt < 3 || ipt > slc.tjs[it2].Pts.size() - 4) break;
717  float delta = PointTrajDOCA(
718  slc.tjs[it2].Pts[ipt].Pos[0], slc.tjs[it2].Pts[ipt].Pos[1], slc.tjs[it1].Pts[endPt1]);
719  float sep = PosSep(slc.tjs[it2].Pts[ipt].Pos, slc.tjs[it1].Pts[endPt1].Pos);
720  float dang = delta / sep;
721  float pull = dang / slc.tjs[it1].Pts[endPt1].DeltaRMS;
722  if (pull < 2 && slc.tjs[it2].Pts[ipt].Chg > mostChg) {
723  mostChg = slc.tjs[it2].Pts[ipt].Chg;
724  intPt2 = ipt;
725  }
726  }
727  // require a lot of charge in tj2 in this vicinity compared with the average.
728  float chgPull = (mostChg - slc.tjs[it2].AveChg) / slc.tjs[it2].ChgRMS;
729  if (prt) mf::LogVerbatim("TC") << " chgPull at intersection point " << chgPull;
730  if (chgPull < 10) continue;
731  // require a signal on every wire between it1 and intPt2
732  TrajPoint ltp = slc.tjs[it1].Pts[endPt1];
733  if (slc.tjs[it1].Pts[endPt1].Pos[0] < -0.4) continue;
734  unsigned int fromWire = std::nearbyint(slc.tjs[it1].Pts[endPt1].Pos[0]);
735  if (slc.tjs[it2].Pts[intPt2].Pos[0] < -0.4) continue;
736  unsigned int toWire = std::nearbyint(slc.tjs[it2].Pts[intPt2].Pos[0]);
737  if (fromWire > toWire) {
738  unsigned int tmp = fromWire;
739  fromWire = toWire;
740  toWire = tmp;
741  }
742  bool skipIt = false;
743  for (unsigned int wire = fromWire + 1; wire < toWire; ++wire) {
744  MoveTPToWire(ltp, (float)wire);
745  if (!SignalAtTp(ltp)) {
746  skipIt = true;
747  break;
748  }
749  } // wire
750  if (skipIt) continue;
751  // we have a winner
752  // create a new vertex
753  VtxStore aVtx;
754  aVtx.Pos = slc.tjs[it2].Pts[intPt2].Pos;
755  aVtx.NTraj = 3;
756  aVtx.Pass = slc.tjs[it2].Pass;
757  aVtx.Topo = 6;
758  aVtx.ChiDOF = 0;
759  aVtx.CTP = inCTP;
760  aVtx.ID = slc.vtxs.size() + 1;
761  unsigned short ivx = slc.vtxs.size();
762  if (!StoreVertex(slc, aVtx)) continue;
763  if (!SplitTraj(slc, it2, intPt2, ivx, prt)) {
764  if (prt) mf::LogVerbatim("TC") << "FHV2: Failed to split trajectory";
765  MakeVertexObsolete("HamVx2", slc, slc.vtxs[ivx], true);
766  continue;
767  }
768  slc.tjs[it1].VtxID[end1] = slc.vtxs[ivx].ID;
769  slc.tjs[it1].AlgMod[kHamVx2] = true;
770  slc.tjs[it2].AlgMod[kHamVx2] = true;
771  unsigned short newTjIndex = slc.tjs.size() - 1;
772  slc.tjs[newTjIndex].AlgMod[kHamVx2] = true;
773  AttachAnyTrajToVertex(slc, ivx, prt);
774  SetVx2Score(slc);
775  // Update the PDGCode for the chopped trajectory
776  SetPDGCode(slc, it2);
777  // and for the new trajectory
778  SetPDGCode(slc, newTjIndex);
779  if (prt)
780  mf::LogVerbatim("TC") << " FHV2: New vtx 2V" << slc.vtxs[ivx].ID << " Score "
781  << slc.vtxs[ivx].Score;
782  didaSplit = true;
783  break;
784  } // it2
785  if (didaSplit) break;
786  } // end1
787  } // it1
788  } // FindHammerVertices2
Expect tracks entering from the front face. Don&#39;t create neutrino PFParticles.
Definition: DataStructs.h:523
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3381
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeVertexObsolete(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2789
bool SignalAtTp(TrajPoint &tp)
Definition: Utils.cxx:1964
void SetPDGCode(TCSlice &slc, unsigned short itj)
Definition: Utils.cxx:4219
TCConfig tcc
Definition: DataStructs.cxx:9
bool TrajClosestApproach(Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
Definition: Utils.cxx:2622
bool AttachAnyTrajToVertex(TCSlice &slc, unsigned short ivx, bool prt)
Definition: TCVertex.cxx:1678
Float_t tmp
Definition: plot.C:35
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2514
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:2531
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:1908
if(nlines<=0)
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
bool SplitTraj(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, unsigned short itj, float XPos, bool makeVx2, bool prt)
Definition: Utils.cxx:2223
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
Definition: Utils.cxx:2543
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2255
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
TDirectory * dir
Definition: macro.C:5
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:579
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2763
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
void TrajPointTrajDOCA(TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
Definition: Utils.cxx:2384
master switch for turning on debug mode
Definition: DataStructs.h:524
void tca::FindNearbyTjs ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct ss,
bool  prt 
)

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

3336  {
3337  // Find Tjs that are near the shower but are not included in it
3338  ss.NearTjIDs.clear();
3339 
3340  // check for a valid envelope
3341  if (ss.Envelope.empty()) return;
3342  auto& stj = slc.tjs[ss.ShowerTjID - 1];
3343 
3344  std::string fcnLabel = inFcnLabel + ".FNTj";
3345 
3346  std::vector<int> ntj;
3347 
3348  // set max distance of closest approach ~ 5 radiation lengths ~200 WSE
3349  constexpr float fiveRadLen = 200;
3350 
3351  // look for vertices inside the envelope
3352  for (auto vx : slc.vtxs) {
3353  if (vx.CTP != ss.CTP) continue;
3354  if (vx.ID == 0) continue;
3355  if (!PointInsideEnvelope(vx.Pos, ss.Envelope)) continue;
3356  auto vxTjIDs = GetAssns(slc, "2V", vx.ID, "T");
3357  for (auto tjID : vxTjIDs) {
3358  // ignore those that are in the shower
3359  if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tjID) != ss.TjIDs.end()) continue;
3360  // or already in the list
3361  if (std::find(ntj.begin(), ntj.end(), tjID) != ntj.end()) continue;
3362  ntj.push_back(tjID);
3363  } // tjID
3364  } // vx
3365 
3366  // Check for tj points inside the envelope
3367  for (auto& tj : slc.tjs) {
3368  if (tj.CTP != ss.CTP) continue;
3369  if (tj.AlgMod[kKilled]) continue;
3370  // not a showerTj
3371  if (tj.AlgMod[kShowerTj]) continue;
3372  // make sure it's not in the shower
3373  if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tj.ID) != ss.TjIDs.end()) continue;
3374  // or already in the list
3375  if (std::find(ntj.begin(), ntj.end(), tj.ID) != ntj.end()) continue;
3376  // check proximity of long high MCSMom Tjs to the shower center
3377  if (tj.Pts.size() > 40 && tj.MCSMom > 200) {
3378  float delta = PointTrajDOCA(stj.Pts[1].Pos[0], stj.Pts[1].Pos[1], tj.Pts[tj.EndPt[0]]);
3379  // TODO: This could be done much better
3380  if (delta < 20) {
3381  float doca = fiveRadLen;
3382  unsigned short spt = 0, ipt = 0;
3383  TrajTrajDOCA(slc, stj, tj, spt, ipt, doca);
3384  if (doca < fiveRadLen) {
3385  ntj.push_back(tj.ID);
3386  continue;
3387  }
3388  }
3389  } // long hi-MCSMom tj
3390  // don't need to check every point. Every third should be enough
3391  bool isInside = false;
3392  for (unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1]; ipt += 3) {
3393  if (PointInsideEnvelope(tj.Pts[ipt].Pos, ss.Envelope)) {
3394  isInside = true;
3395  break;
3396  }
3397  } // ipt
3398  // check the last point which was probably missed above
3399  if (!isInside) {
3400  unsigned short ipt = tj.EndPt[1];
3401  isInside = PointInsideEnvelope(tj.Pts[ipt].Pos, ss.Envelope);
3402  }
3403  if (isInside) ntj.push_back(tj.ID);
3404  } // tj
3405  if (ntj.size() > 1) std::sort(ntj.begin(), ntj.end());
3406  if (prt)
3407  mf::LogVerbatim("TC") << fcnLabel << " Found " << ntj.size() << " Tjs near ss.ID " << ss.ID;
3408  ss.NearTjIDs = ntj;
3409 
3410  } // FindNearbyTjs
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2514
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:3246
std::vector< int > GetAssns(TCSlice const &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4704
bool TrajTrajDOCA(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2407
bool tca::FindParent ( detinfo::DetectorPropertiesData const &  detProp,
std::string  inFcnLabel,
TCSlice slc,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 1561 of file TCShower.cxx.

References util::abs(), ChgFracBetween(), tca::ShowerStruct3D::ChgPos, ChgToMeV(), tca::ShowerStruct3D::CotIDs, tca::TCSlice::cots, geo::CryostatID::Cryostat, dir, tca::ShowerStruct3D::Dir, DirAtEnd(), 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(), PosAtEnd(), PosSep(), PosSep2(), SetParent(), ShowerEnergy(), ShowerParams(), tca::TCConfig::showerParentReader, tca::TCConfig::showerParentVars, tca::TCSlice::showers, tca::ShowerStruct3D::Start, tcc, tca::TCSlice::tjs, geo::TPCID::TPC, tca::ShowerStruct3D::TPCID, UpdateShower(), tca::TCConfig::useAlg, and tca::ShowerStruct3D::Vx3ID.

Referenced by FindShowers3D().

1566  {
1567  // look for a parent pfp for the shower.The 2D showers associated with it
1568  // The parent should be at the start of the shower (shend = 0) if it is well-defined
1569  // (has small AspectRatio and small DirectionFOM). A search is also made for a parent at
1570  // the "wrong" end of the shower (shend = 1). The best one at the wrong end is used if
1571  // no parent is found at the shower start and the shower is poorly defined.
1572  //
1573  // This function returns false if there was a failure. Not finding a parent is not a failure
1574 
1575  if (ss3.ID == 0) return false;
1576  if (ss3.CotIDs.size() < 2) return false;
1577  // Use the MVA reader
1578  if (!tcc.showerParentReader) return false;
1579  if (tcc.showerParentVars.size() != 9) return false;
1580  if (!tcc.useAlg[kShwrParent]) return false;
1581 
1582  std::string fcnLabel = inFcnLabel + ".FPar";
1583  int truPFP = 0;
1584 
1585  double energy = ShowerEnergy(ss3);
1586  // the energy is probably under-estimated since there isn't a parent yet.
1587  energy *= 1.2;
1588  double shMaxAlong, along95;
1589  ShowerParams(energy, shMaxAlong, along95);
1590  if (prt)
1591  mf::LogVerbatim("TC") << fcnLabel << " 3S" << ss3.ID << " Estimated energy " << (int)energy
1592  << " MeV shMaxAlong " << shMaxAlong << " along95 " << along95
1593  << " truPFP " << truPFP;
1594 
1595  // look for the pfp that has a reasonable probability of being in the shower but with the
1596  // minimum along distance from the shower center.
1597  // This image explains the concept. The *'s represents the points in 2D showers that define
1598  // the charge center in 3D, ChgPos. We are looking for a pfp parent denoted by ----. The end
1599  // that is farthest from ChgPos is labeled P (pfp.XYZ[pend] in the code). The expected distance
1600  // from the shower start to shower Max, shMaxAlong, is found from ShowerParams. The longitudinal
1601  // and transverse distance of P relative to the shower center is alongTrans. The first cut on a
1602  // candidate parent is made requiring that D (alongTrans[0]) > 0.5 * shMaxAlong.
1603  //
1604  // __________shend = 0________________ __________shend = 1________________
1605  // **********
1606  // ****** ****** ****** ******
1607  // P-----*****ChgPos****** ** *****ChgPos******-------P
1608  // ******** ******* *******
1609  // |----> along |---> along
1610  // |<----D------>| |<----D------>|
1611  // |<----shMaxAlong--->| |<----shMaxAlong--->|
1612  //
1613  // Candidate parent ID for each end and the FOM
1614  std::array<int, 2> parID{{0, 0}};
1615  std::array<float, 2> parFOM{{-1E6, -1E6}};
1616 
1617  // temp vector to flag pfps that are already parents - indexed by ID
1618  std::vector<bool> isParent(slc.pfps.size() + 1, false);
1619  for (auto& oldSS3 : slc.showers) {
1620  if (oldSS3.ID == 0) continue;
1621  isParent[oldSS3.ParentID] = true;
1622  } // pfp
1623 
1624  // put the tjs associated with this shower in a flat vector
1625  auto TjsInSS3 = GetAssns(slc, "3S", ss3.ID, "T");
1626  if (TjsInSS3.empty()) return false;
1627 
1628  for (auto& pfp : slc.pfps) {
1629  if (pfp.ID == 0) continue;
1630  bool dprt = (pfp.ID == truPFP);
1631  if (pfp.TPCID != ss3.TPCID) continue;
1632  // ignore neutrinos
1633  if (pfp.PDGCode == 14 || pfp.PDGCode == 14) continue;
1634  // ignore shower pfps
1635  if (pfp.PDGCode == 1111) continue;
1636  // ignore existing parents
1637  if (isParent[pfp.ID]) continue;
1638  // check for inconsistent pfp - shower tjs
1639  if (DontCluster(slc, pfp.TjIDs, TjsInSS3)) continue;
1640  // ignore if the pfp energy is larger than the shower energy
1641  float pfpEnergy = 0;
1642  float minEnergy = 1E6;
1643  for (auto tid : pfp.TjIDs) {
1644  auto& tj = slc.tjs[tid - 1];
1645  float energy = ChgToMeV(tj.TotChg);
1646  pfpEnergy += energy;
1647  if (energy < minEnergy) minEnergy = energy;
1648  }
1649  pfpEnergy -= minEnergy;
1650  pfpEnergy /= (float)(pfp.TjIDs.size() - 1);
1651  if (dprt)
1652  mf::LogVerbatim("TC") << fcnLabel << " 3S" << ss3.ID << " P" << pfp.ID << " E "
1653  << pfpEnergy;
1654  if (pfpEnergy > energy) continue;
1655  // find the end that is farthest away
1656  unsigned short pEnd = FarEnd(pfp, ss3.ChgPos);
1657  auto pos = PosAtEnd(pfp, pEnd);
1658  auto pToS = PointDirection(pos, ss3.ChgPos);
1659  double costh1 = std::abs(DotProd(pToS, ss3.Dir));
1660  if (costh1 < 0.4) continue;
1661  auto dir = DirAtEnd(pfp, pEnd);
1662  float costh2 = DotProd(pToS, dir);
1663  // distance^2 between the pfp end and the shower start, charge center, and shower end
1664  float distToStart2 = PosSep2(pos, ss3.Start);
1665  float distToChgPos2 = PosSep2(pos, ss3.ChgPos);
1666  float distToEnd2 = PosSep2(pos, ss3.End);
1667  if (dprt)
1668  mf::LogVerbatim("TC") << fcnLabel << " 3S" << ss3.ID << " P" << pfp.ID << "_" << pEnd
1669  << " distToStart " << sqrt(distToStart2) << " distToChgPos "
1670  << sqrt(distToChgPos2) << " distToEnd " << sqrt(distToEnd2);
1671  // find the end of the shower closest to the pfp
1672  unsigned short shEnd = 0;
1673  if (distToEnd2 < distToStart2) shEnd = 1;
1674  // This can't be a parent if the pfp end is closer to the shower center than the start or the end
1675  if (shEnd == 0 && distToChgPos2 < distToStart2) continue;
1676  if (shEnd == 1 && distToChgPos2 < distToEnd2) continue;
1677  if (dprt)
1678  mf::LogVerbatim("TC") << fcnLabel << " 3S" << ss3.ID << "_" << shEnd << " P" << pfp.ID
1679  << "_" << pEnd << " costh1 " << costh1;
1680  Point2_t alongTrans;
1681  // find the longitudinal and transverse components of the pfp start point relative to the
1682  // shower center
1683  FindAlongTrans(ss3.ChgPos, ss3.Dir, pos, alongTrans);
1684  if (dprt)
1685  mf::LogVerbatim("TC") << fcnLabel << " alongTrans " << alongTrans[0] << " "
1686  << alongTrans[1];
1687  // find the probability this point is inside the shower. Offset by the expected
1688  // shower max distance. distToShowerMax will be > 0 if the pfp end is closer to
1689  // ChgPos than expected from the parameterization
1690  float distToShowerMax = shMaxAlong - std::abs(alongTrans[0]);
1691  float prob = InShowerProbLong(energy, distToShowerMax);
1692  if (dprt) mf::LogVerbatim("TC") << fcnLabel << " prob " << prob;
1693  if (prob < 0.1) continue;
1694  float chgFrac = 0;
1695  float totSep = 0;
1696  // find the charge fraction btw the pfp start and the point that is
1697  // half the distance to the charge center in each plane
1698  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
1699  CTP_t inCTP = EncodeCTP(ss3.TPCID.Cryostat, ss3.TPCID.TPC, plane);
1700  int ssid = 0;
1701  for (auto cid : ss3.CotIDs) {
1702  auto& ss = slc.cots[cid - 1];
1703  if (ss.CTP != inCTP) continue;
1704  ssid = ss.ID;
1705  break;
1706  } // cid
1707  if (ssid == 0) continue;
1708  auto tpFrom = MakeBareTP(detProp, pos, pToS, inCTP);
1709  auto& ss = slc.cots[ssid - 1];
1710  auto& stp1 = slc.tjs[ss.ShowerTjID - 1].Pts[1];
1711  float sep = PosSep(tpFrom.Pos, stp1.Pos);
1712  float toPos = tpFrom.Pos[0] + 0.5 * tpFrom.Dir[0] * sep;
1713  float cf = ChgFracBetween(tpFrom, toPos);
1714  // weight by the separation in the plane
1715  totSep += sep;
1716  chgFrac += sep * cf;
1717  } // plane
1718  if (totSep > 0) chgFrac /= totSep;
1719  // load the MVA variables
1721  tcc.showerParentVars[1] = pfpEnergy;
1722  tcc.showerParentVars[2] = MCSMom(slc, pfp.TjIDs);
1723  auto startPos = PosAtEnd(pfp, 0);
1724  auto endPos = PosAtEnd(pfp, 1);
1725  tcc.showerParentVars[3] = PosSep(startPos, endPos);
1726  tcc.showerParentVars[4] = sqrt(distToChgPos2);
1727  tcc.showerParentVars[5] = acos(costh1);
1728  tcc.showerParentVars[6] = acos(costh2);
1729  tcc.showerParentVars[7] = chgFrac;
1730  tcc.showerParentVars[8] = prob;
1731  float candParFOM = tcc.showerParentReader->EvaluateMVA("BDT");
1732 
1733  if (prt) {
1734  mf::LogVerbatim myprt("TC");
1735  myprt << fcnLabel;
1736  myprt << " 3S" << ss3.ID << "_" << shEnd;
1737  myprt << " P" << pfp.ID << "_" << pEnd << " ParentVars";
1738  for (auto var : tcc.showerParentVars)
1739  myprt << " " << std::fixed << std::setprecision(2) << var;
1740  myprt << " candParFOM " << candParFOM;
1741  } // prt
1742  if (candParFOM > parFOM[shEnd]) {
1743  parFOM[shEnd] = candParFOM;
1744  parID[shEnd] = pfp.ID;
1745  }
1746  } // pfp
1747 
1748  if (parID[0] == 0 && parID[1] == 0) return true;
1749 
1750  // decide which to use
1751  int bestPFP = 0;
1752  // find the average DirectionFOM to help decide
1753  float aveDirFOM = 0;
1754  float fom3D = 0;
1755  for (auto cid : ss3.CotIDs)
1756  aveDirFOM += slc.cots[cid - 1].DirectionFOM;
1757  aveDirFOM /= (float)ss3.CotIDs.size();
1758  if (prt) {
1759  mf::LogVerbatim("TC") << fcnLabel << " 3S" << ss3.ID << " parID[0] " << parID[0] << " fom "
1760  << parFOM[0] << " parID[1] " << parID[1] << " fom " << parFOM[1]
1761  << " aveDirFOM " << aveDirFOM;
1762  }
1763  if (parID[0] > 0 && parID[1] > 0 && aveDirFOM > 0.3) {
1764  // candidates at both ends and the direction is not well known. Take
1765  // the one with the best FOM
1766  bestPFP = parID[0];
1767  fom3D = parFOM[0];
1768  if (parFOM[1] > parFOM[0]) {
1769  bestPFP = parID[1];
1770  fom3D = parFOM[1];
1771  }
1772  }
1773  else if (parID[0] > 0) {
1774  bestPFP = parID[0];
1775  fom3D = parFOM[0];
1776  }
1777  else {
1778  bestPFP = parID[1];
1779  fom3D = parFOM[1];
1780  }
1781  if (bestPFP == 0) return true;
1782 
1783  if (prt)
1784  mf::LogVerbatim("TC") << fcnLabel << " 3S" << ss3.ID << " setting P" << bestPFP
1785  << " as the parent " << fom3D;
1786 
1787  // make local copies so we can recover from a failure
1788  auto oldSS3 = ss3;
1789  std::vector<ShowerStruct> oldSS(ss3.CotIDs.size());
1790  for (unsigned short ii = 0; ii < ss3.CotIDs.size(); ++ii) {
1791  oldSS[ii] = slc.cots[ss3.CotIDs[ii] - 1];
1792  }
1793 
1794  ss3.ParentID = bestPFP;
1795  auto& pfp = slc.pfps[bestPFP - 1];
1796  unsigned short pend = FarEnd(pfp, ss3.ChgPos);
1797  ss3.Vx3ID = pfp.Vx3ID[pend];
1798 
1799  if (SetParent(detProp, fcnLabel, slc, pfp, ss3, prt) && UpdateShower(fcnLabel, slc, ss3, prt)) {
1800  if (prt) mf::LogVerbatim("TC") << fcnLabel << " 3S" << ss3.ID << " successful update";
1801  return true;
1802  }
1803 
1804  if (prt) mf::LogVerbatim("TC") << fcnLabel << " 3S" << ss3.ID << " Failed. Recovering...";
1805  ss3 = oldSS3;
1806  for (unsigned short ii = 0; ii < oldSS.size(); ++ii) {
1807  auto& ss = oldSS[ii];
1808  slc.cots[ss.ID - 1] = ss;
1809  } // ii
1810  return false;
1811 
1812  } // FindParent
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3381
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
double InShowerProbLong(double showerEnergy, double along)
Definition: TCShower.cxx:1937
TCConfig tcc
Definition: DataStructs.cxx:9
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:3066
constexpr auto abs(T v)
Returns the absolute value of the argument.
bool DontCluster(TCSlice const &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3213
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3257
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1106
std::array< float, 2 > Point2_t
Definition: DataStructs.h:41
float ShowerEnergy(TCSlice &slc, const std::vector< int > tjIDs)
Definition: TCShower.cxx:3912
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:2538
TMVA::Reader * showerParentReader
Definition: DataStructs.h:570
std::vector< float > showerParentVars
Definition: DataStructs.h:571
float ChgFracBetween(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, Point3_t pos1, Point3_t pos2)
Definition: PFPUtils.cxx:3163
double energy
Definition: plottest35.C:25
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const Point3_t &pos, CTP_t inCTP)
Definition: Utils.cxx:3928
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2560
unsigned short FarEnd(const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3300
std::vector< int > GetAssns(TCSlice const &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4704
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:126
unsigned int CTP_t
Definition: DataStructs.h:45
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
Definition: TCShower.cxx:1904
TDirectory * dir
Definition: macro.C:5
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:49
float ChgToMeV(float chg)
Definition: TCShower.cxx:3925
Vector3_t DirAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3249
bool SetParent(detinfo::DetectorPropertiesData const &detProp, std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1815
void tca::FindPFParticles ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
TCSlice slc 
)

Definition at line 190 of file PFPUtils.cxx.

References tca::TCConfig::dbgPFP, tca::TCConfig::dbgSlc, debug, evt, FillmAllTraj(), FillWireIntersections(), for(), MakePFParticles(), tca::TCSlice::mallTraj, Match2Planes(), tca::TCConfig::match3DCuts, Match3Planes(), tca::DebugStuff::MVI, tca::TCSlice::nPlanes, NumPtsWithCharge(), tca::TCSlice::pfps, PrintTP3Ds(), tca::TCEvent::sptHits, tcc, and tca::TCSlice::tjs.

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

193  {
194  // Match Tjs in 3D and create PFParticles
195 
196  if (tcc.match3DCuts[0] <= 0) return;
197 
199 
200  // clear the TP -> P assn Tjs so that all are considered
201  for (auto& tj : slc.tjs) {
202  for (auto& tp : tj.Pts)
203  tp.InPFP = 0;
204  } // tj
205 
206  bool prt = (tcc.dbgPFP && tcc.dbgSlc);
207 
208  // Match these points in 3D
209  std::vector<MatchStruct> matVec;
210 
211  // iterate twice (at most), looking for 3-plane matches in long tjs in 3-plane TPCs on the
212  // first iteration, 3-plane matches in short tjs on the second iteration.
213  // and 2-plane matches + dead regions in 3-plane TPCs on the last iteration
214  slc.mallTraj.clear();
215 
216  unsigned short maxNit = 2;
217  if (slc.nPlanes == 2) maxNit = 1;
218  if (std::nearbyint(tcc.match3DCuts[2]) == 0) maxNit = 1;
219  // fill the mAllTraj vector with TPs if we aren't using SpacePoints
220  if (evt.sptHits.empty()) FillmAllTraj(detProp, slc);
221  for (unsigned short nit = 0; nit < maxNit; ++nit) {
222  matVec.clear();
223  if (slc.nPlanes == 3 && nit == 0) {
224  // look for match triplets
225  Match3Planes(slc, matVec);
226  }
227  else {
228  // look for match doublets requiring a dead region in the 3rd plane for 3-plane TPCs
229  Match2Planes(slc, matVec);
230  }
231  if (matVec.empty()) continue;
232  if (prt) {
233  mf::LogVerbatim myprt("TC");
234  myprt << "nit " << nit << " MVI Count Tjs\n";
235  for (unsigned int indx = 0; indx < matVec.size(); ++indx) {
236  auto& ms = matVec[indx];
237  myprt << std::setw(5) << indx << std::setw(6) << (int)ms.Count;
238  for (auto tid : ms.TjIDs)
239  myprt << " T" << tid;
240  // count the number of TPs in all Tjs
241  float tpCnt = 0;
242  for (auto tid : ms.TjIDs) {
243  auto& tj = slc.tjs[tid - 1];
244  tpCnt += NumPtsWithCharge(slc, tj, false);
245  } // tid
246  float frac = ms.Count / tpCnt;
247  myprt << " matFrac " << std::fixed << std::setprecision(3) << frac;
248  myprt << "\n";
249  } // indx
250  } // prt
251  MakePFParticles(clockData, detProp, slc, matVec, nit);
252  } // nit
253 
254  // a last debug print
255  if (tcc.dbgPFP && debug.MVI != UINT_MAX) {
256  for (auto& pfp : slc.pfps)
257  if (tcc.dbgPFP && pfp.MVI == debug.MVI)
258  PrintTP3Ds(clockData, detProp, "FPFP", slc, pfp, -1);
259  } // last debug print
260 
261  slc.mallTraj.resize(0);
262 
263  } // FindPFParticles
void MakePFParticles(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, std::vector< MatchStruct > matVec, unsigned short matVec_Iter)
Definition: PFPUtils.cxx:266
TCConfig tcc
Definition: DataStructs.cxx:9
for(Int_t i=0;i< nentries;i++)
Definition: comparison.C:30
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
void Match2Planes(TCSlice &slc, std::vector< MatchStruct > &matVec)
Definition: PFPUtils.cxx:939
unsigned int MVI
MatchVec Index for detailed 3D matching.
Definition: DebugStruct.h:29
std::vector< std::array< unsigned int, 3 > > sptHits
SpacePoint -> Hits assns by plane.
Definition: DataStructs.h:625
DebugStuff debug
Definition: DebugStruct.cxx:4
void FillWireIntersections(TCSlice &slc)
Definition: PFPUtils.cxx:607
void Match3Planes(TCSlice &slc, std::vector< MatchStruct > &matVec)
Definition: PFPUtils.cxx:809
std::vector< float > match3DCuts
3D matching cuts
Definition: DataStructs.h:551
void FillmAllTraj(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc)
Definition: PFPUtils.cxx:2369
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
TCEvent evt
Definition: DataStructs.cxx:8
void PrintTP3Ds(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, std::string someText, const TCSlice &slc, const PFPStruct &pfp, short printPts)
Definition: PFPUtils.cxx:3356
bool tca::FindShowers3D ( detinfo::DetectorPropertiesData const &  detProp,
TCSlice slc 
)

Definition at line 286 of file TCShower.cxx.

References AddTjsInsideEnvelope(), ChkAssns(), tca::TCSlice::cots, CreateSS(), tca::DebugStuff::CTP, tca::TCConfig::dbg2S, tca::TCConfig::dbg3S, tca::TCConfig::dbgSlc, debug, EncodeCTP(), FindNearbyTjs(), FindParent(), geo::Iterable< IterationPolicy, Transform >::Iterate(), kSaveShowerTree, MakeShowerObsolete(), MergeNearby2DShowers(), MergeOverlap(), MergeShowerChain(), MergeSubShowers(), MergeSubShowersTj(), tca::TCConfig::modes, geo::WireReadoutGeom::Nplanes(), tca::TCSlice::nPlanes, Print2DShowers(), PrintAllTraj(), PrintPFPs(), Reconcile3D(), SaveAllCots(), SaveTjInfo(), ShowerEnergy(), tca::TCSlice::showers, tca::TCConfig::showerTag, StoreShower(), tcc, tca::TCSlice::TPCID, UpdateShower(), and tca::TCConfig::wireReadoutGeom.

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  // check for already-existing showers
300  for (auto const planeid : tcc.wireReadoutGeom->Iterate<geo::PlaneID>(slc.TPCID)) {
301  CTP_t inCTP = EncodeCTP(planeid.Cryostat, planeid.TPC, planeid.Plane);
302  for (auto& ss : slc.cots)
303  if (ss.CTP == inCTP) return false;
304  }
305 
306  if (prt2S) {
307  PrintPFPs("FSi", slc);
308  PrintAllTraj(detProp, "FSi", slc, USHRT_MAX, 0);
309  }
310 
311  // lists of Tj IDs in plane, (list1, list2, list3, ...)
312  std::vector<std::vector<std::vector<int>>> bigList(slc.nPlanes);
313  for (auto const planeid : tcc.wireReadoutGeom->Iterate<geo::PlaneID>(slc.TPCID)) {
314  std::vector<std::vector<int>> tjList;
315  // Make lists of lists of ShowerLike tjs that will become showers
316  // FindCots(fcnLabel, slc, inCTP, tjList, prt2S);
317  SaveTjInfo(slc, tjList, "TJL");
318  if (tjList.empty()) continue;
319  bigList[planeid.Plane] = tjList;
320  } // plane
321  unsigned short nPlanesWithShowers = 0;
322  if (!bigList.empty()) { nPlanesWithShowers = tcc.wireReadoutGeom->Nplanes(slc.TPCID); }
323  if (nPlanesWithShowers < 2) return false;
324 
325  for (auto const planeid : tcc.wireReadoutGeom->Iterate<geo::PlaneID>(slc.TPCID)) {
326  CTP_t inCTP = EncodeCTP(planeid.Cryostat, planeid.TPC, planeid.Plane);
327  // print detailed debug info for one plane
328  bool prtCTP = (prt2S && inCTP == debug.CTP);
329  // Create a shower for each one
330  for (auto& tjl : bigList[planeid.Plane]) {
331  if (tjl.empty()) continue;
332  if (prtCTP) {
333  mf::LogVerbatim myprt("TC");
334  myprt << "Plane " << planeid.Plane << " tjList";
335  for (auto& tjID : tjl)
336  myprt << " " << tjID;
337  }
338  auto ss = CreateSS(slc, tjl);
339  if (ss.ID == 0) continue;
340  if (!UpdateShower(fcnLabel, slc, ss, prtCTP)) continue;
341  SaveTjInfo(slc, ss, "DS");
342  FindNearbyTjs(fcnLabel, slc, ss, prtCTP);
343  // don't try to do anything else here until all of the showers are defined
344  if (!StoreShower(fcnLabel, slc, ss)) MakeShowerObsolete(fcnLabel, slc, ss, prtCTP);
345  } // tjl
346  ChkAssns(fcnLabel, slc);
347  // try to merge showers in this plane using the lists of nearby Tjs
348  if (inCTP == UINT_MAX) continue;
349  if (slc.cots.empty()) continue;
350  if (prtCTP) Print2DShowers("tjl", slc, inCTP, false);
351  MergeShowerChain(fcnLabel, slc, inCTP, prtCTP);
352  SaveAllCots(slc, inCTP, "MSC");
353  if (prtCTP) Print2DShowers("MSCo", slc, inCTP, false);
354  MergeOverlap(fcnLabel, slc, inCTP, prtCTP);
355  SaveAllCots(slc, inCTP, "MO");
356  if (prtCTP) Print2DShowers("MO", slc, inCTP, false);
357  MergeNearby2DShowers(fcnLabel, slc, inCTP, prtCTP);
358  SaveAllCots(slc, inCTP, "MSS");
359  // merge sub-showers with other showers
360  MergeSubShowers(fcnLabel, slc, inCTP, prtCTP);
361  // merge sub-showers with shower-like tjs
362  MergeSubShowersTj(fcnLabel, slc, inCTP, prtCTP);
363  SaveAllCots(slc, inCTP, "MNrby");
364  if (prtCTP) Print2DShowers("Nrby", slc, inCTP, false);
365  bool tryMerge = false;
366  for (unsigned short ii = 0; ii < slc.cots.size(); ++ii) {
367  auto& ss = slc.cots[ii];
368  if (ss.ID == 0) continue;
369  if (ss.CTP != inCTP) continue;
370  if (AddTjsInsideEnvelope(fcnLabel, slc, ss, prtCTP)) tryMerge = true;
371  if (tcc.modes[kSaveShowerTree]) SaveAllCots(slc, inCTP, "Merge");
372  }
373  if (tryMerge) MergeNearby2DShowers(fcnLabel, slc, inCTP, prtCTP);
374  SaveAllCots(slc, inCTP, "ATj2");
375  if (prtCTP) Print2DShowers("ATIE", slc, inCTP, false);
376  } // plane
377  if (slc.cots.empty()) return false;
378  if (prt3S) Print2DShowers("B4", slc, USHRT_MAX, false);
379  // Match in 3D, make 3D showers and define them
380  // Match2DShowers(fcnLabel, slc, prt3S);
381  SaveAllCots(slc, "M2DS");
382  // Reconcile pfp and shower assns before the Parent search
383  Reconcile3D(fcnLabel, slc, false, prt3S);
384  SaveAllCots(slc, "R3D");
385  for (auto& ss3 : slc.showers) {
386  if (ss3.ID == 0) continue;
387  FindParent(detProp, fcnLabel, slc, ss3, prt3S);
388  } // ss3
389  // Reconcile pfp and shower assns again
390  Reconcile3D(fcnLabel, slc, true, prt3S);
391  if (prt3S) Print2DShowers("M2DS", slc, USHRT_MAX, false);
392  SaveAllCots(slc, "FP");
393 
394  // kill low energy 3D showers
395  for (auto& ss3 : slc.showers) {
396  if (ss3.ID == 0) continue;
397  bool killMe = (ShowerEnergy(ss3) < tcc.showerTag[3]);
398  if (killMe) MakeShowerObsolete(fcnLabel, slc, ss3, prt3S);
399  } // ss3
400 
401  // kill 2D showers that are either below threshold or have only one tj
402  for (auto& ss : slc.cots) {
403  if (ss.ID == 0) continue;
404  if (ss.SS3ID > 0) continue;
405  bool killMe = (ss.TjIDs.size() == 1 || ss.Energy < tcc.showerTag[3]);
406  // too small aspect ratio -> something track-like with some shower-like fuzz
407  if (ss.AspectRatio < tcc.showerTag[10]) killMe = true;
408  if (killMe) MakeShowerObsolete(fcnLabel, slc, ss, prt3S);
409  } // ss
410 
411  unsigned short nNewShowers = 0;
412  for (auto& ss : slc.cots) {
413  if (ss.ID == 0) continue;
414  if (ss.TjIDs.empty()) continue;
415  SaveTjInfo(slc, ss, "Done");
416  ++nNewShowers;
417  } // ss
418 
419  return (nNewShowers > 0);
420 
421  } // FindShowers3D
void MergeNearby2DShowers(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
Definition: TCShower.cxx:2279
bool FindParent(detinfo::DetectorPropertiesData const &detProp, std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1561
void MergeShowerChain(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
Definition: TCShower.cxx:2491
const geo::WireReadoutGeom * wireReadoutGeom
Definition: DataStructs.h:568
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4095
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
bool Reconcile3D(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:571
void SaveAllCots(TCSlice &slc, const CTP_t &inCTP, std::string someText)
Definition: TCShTree.cxx:179
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
void PrintPFPs(std::string someText, TCSlice const &slc)
Definition: Utils.cxx:6279
ShowerStruct CreateSS(TCSlice &slc, const std::vector< int > &tjl)
Definition: TCShower.cxx:4049
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:549
save shower tree
Definition: DataStructs.h:531
void MergeSubShowersTj(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
Definition: TCShower.cxx:2620
void MakeShowerObsolete(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3169
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1106
float ShowerEnergy(TCSlice &slc, const std::vector< int > tjIDs)
Definition: TCShower.cxx:3912
DebugStuff debug
Definition: DebugStruct.cxx:4
void SaveTjInfo(TCSlice &slc, std::vector< std::vector< int >> &tjList, std::string stageName)
Definition: TCShTree.cxx:14
void FindNearbyTjs(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3335
void MergeOverlap(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
Definition: TCShower.cxx:2371
bool AddTjsInsideEnvelope(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3503
bool StoreShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss)
Definition: TCShower.cxx:3983
unsigned int Nplanes(TPCID const &tpcid=details::tpc_zero) const
Returns the total number of planes in the specified TPC.
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
unsigned int CTP_t
Definition: DataStructs.h:45
range_type< T > Iterate() const
Definition: Iterable.h:121
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:49
void MergeSubShowers(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
Definition: TCShower.cxx:2731
void PrintAllTraj(detinfo::DetectorPropertiesData const &detProp, std::string someText, TCSlice const &slc, unsigned short itj, unsigned short ipt, bool prtVtx)
Definition: Utils.cxx:5793
void Print2DShowers(std::string someText, TCSlice const &slc, CTP_t inCTP, bool printKilledShowers)
Definition: TCShower.cxx:4192
CTP_t CTP
set to an invalid CTP
Definition: DebugStruct.h:23
bool tca::FindShowerStart ( detinfo::DetectorPropertiesData const &  detProp,
TCSlice slc,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 61 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(), tca::ShowerStruct3D::Start, tcc, tca::TCSlice::tjs, tca::TCSlice::vtx3s, tca::ShowerStruct3D::Vx3ID, and tca::TCConfig::wirePitch.

65  {
66  // The shower ChgPos and Dir were found by the calling function but Dir
67  // may be inconsistent with the 2D shower directions
68  if (ss3.ID == 0) return false;
69 
70  if (prt) {
71  mf::LogVerbatim myprt("TC");
72  myprt << "Inside FSS: 3S" << ss3.ID << " ->";
73  for (auto cid : ss3.CotIDs)
74  myprt << " 2S" << cid;
75  myprt << " Vx 3V" << ss3.Vx3ID;
76  } // prt
77 
78  // find a parent Tj in the list of 2D showers that is the farthest away from the
79  // shower center
80  unsigned short useParentCID = 0;
81  float maxParentSep = 0;
82  unsigned short usePtSepCID = 0;
83  float maxPtSep = 0;
84  // assume that the 2D shower direction is consistent with the 3D shower direction. This
85  // variable is only used when no parent exists
86  bool dirOK = true;
87  for (auto cid : ss3.CotIDs) {
88  auto& ss = slc.cots[cid - 1];
89  // Find the position, direction and projection in this plane
90  auto& stj = slc.tjs[ss.ShowerTjID - 1];
91  auto chgCtrTP = MakeBareTP(detProp, ss3.ChgPos, ss3.Dir, stj.CTP);
92  // projection too small in this view?
93  if (chgCtrTP.Delta < 0.5) continue;
94  auto& startTP = stj.Pts[0];
95  float sep = PosSep(startTP.Pos, chgCtrTP.Pos);
96  if (ss.ParentID > 0) {
97  if (sep > maxParentSep) {
98  maxParentSep = sep;
99  useParentCID = cid;
100  }
101  }
102  else if (sep > maxPtSep) {
103  // no parent exists.
104  maxPtSep = sep;
105  usePtSepCID = cid;
106  float costh = DotProd(chgCtrTP.Dir, startTP.Dir);
107  if (costh < 0) dirOK = false;
108  }
109  } // ci
110  if (useParentCID == 0 && usePtSepCID == 0) return false;
111 
112  unsigned short useCID = useParentCID;
113  if (useCID == 0) {
114  useCID = usePtSepCID;
115  if (!dirOK) ReverseShower("FSS", slc, useCID, prt);
116  }
117 
118  // now define the start and length
119  auto& ss = slc.cots[useCID - 1];
120  auto& stj = slc.tjs[ss.ShowerTjID - 1];
121 
122  auto chgCtrTP = MakeBareTP(detProp, ss3.ChgPos, ss3.Dir, stj.CTP);
123  if (ss3.Vx3ID > 0) {
124  auto& vx3 = slc.vtx3s[ss3.Vx3ID - 1];
125  ss3.Start[0] = vx3.X;
126  ss3.Start[1] = vx3.Y;
127  ss3.Start[2] = vx3.Z;
128  }
129  else {
130  // no start vertex
131  auto& startTP = stj.Pts[0];
132  // The 2D separation btw the shower start and the shower center, converted
133  // to the 3D separation
134  float sep = tcc.wirePitch * PosSep(startTP.Pos, stj.Pts[1].Pos) / chgCtrTP.Delta;
135  // set the start position
136  for (unsigned short xyz = 0; xyz < 3; ++xyz)
137  ss3.Start[xyz] = ss3.ChgPos[xyz] - sep * ss3.Dir[xyz];
138  }
139  // now do the end position
140  auto& endTP = stj.Pts[2];
141  float sep = tcc.wirePitch * PosSep(endTP.Pos, chgCtrTP.Pos) / chgCtrTP.Delta;
142  for (unsigned short xyz = 0; xyz < 3; ++xyz)
143  ss3.End[xyz] = ss3.ChgPos[xyz] + sep * ss3.Dir[xyz];
144  ss3.Len = PosSep(ss3.Start, ss3.End);
145  auto& startTP = stj.Pts[0];
146  sep = PosSep(startTP.Pos, endTP.Pos);
147  ss3.OpenAngle = (endTP.DeltaRMS - startTP.DeltaRMS) / sep;
148  ss3.OpenAngle /= chgCtrTP.Delta;
149  return true;
150 
151  } // FindShowerStart
void ReverseShower(std::string inFcnLabel, TCSlice &slc, int cotID, bool prt)
Definition: TCShower.cxx:3140
TCConfig tcc
Definition: DataStructs.cxx:9
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const Point3_t &pos, CTP_t inCTP)
Definition: Utils.cxx:3928
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:126
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
void tca::FindStartChg ( std::string  inFcnLabel,
TCSlice slc,
int  cotID,
bool  prt 
)

Definition at line 3654 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, StartChgVec(), sum, tcc, tca::ShowerStruct::TjIDs, and tca::TCSlice::tjs.

3655  {
3656  // Finds the charge at the start of a shower and puts it in AveChg of the first
3657  // point of the shower Tj. This is only done when there is no parent.
3658  if (cotID > (int)slc.cots.size()) return;
3659 
3660  ShowerStruct& ss = slc.cots[cotID - 1];
3661  if (ss.ID == 0) return;
3662  if (ss.TjIDs.empty()) return;
3663  if (ss.ShowerTjID == 0) return;
3664  if (ss.ParentID > 0) return;
3665  auto& stp0 = slc.tjs[ss.ShowerTjID - 1].Pts[0];
3666 
3667  std::string fcnLabel = inFcnLabel + ".FSC";
3668 
3669  stp0.AveChg = 0;
3670 
3671  if (ss.AspectRatio > tcc.showerTag[10] || ss.DirectionFOM > tcc.showerTag[9]) {
3672  if (prt)
3673  mf::LogVerbatim("TC") << fcnLabel << " Not possible due to poor AspectRatio "
3674  << ss.AspectRatio << " or ss.DirectionFOM " << ss.DirectionFOM;
3675  return;
3676  }
3677 
3678  // Create and fill a vector of the charge at the beginning of the shower in 1 WSE bins
3679  auto schg = StartChgVec(slc, cotID);
3680  if (schg.empty()) return;
3681 
3682  // Look for two consecutive charge entries. Use the second one
3683  // for the initial guess at the charge
3684  unsigned short startPt = USHRT_MAX;
3685  float chg = 0;
3686  for (unsigned short ii = 0; ii < schg.size() - 1; ++ii) {
3687  if (schg[ii] > 0 && schg[ii + 1] > 0) {
3688  startPt = ii + 1;
3689  chg = schg[ii + 1];
3690  break;
3691  }
3692  }
3693  if (startPt == USHRT_MAX) return;
3694 
3695  // get an initial average and rms using all the points
3696  float ave = 0;
3697  float rms = 0;
3698  float cnt = 0;
3699  for (unsigned short ii = startPt; ii < schg.size() - 1; ++ii) {
3700  ave += schg[ii];
3701  rms += schg[ii] * schg[ii];
3702  ++cnt;
3703  } // ii
3704  ave /= cnt;
3705  rms = rms - cnt * ave * ave;
3706  if (rms < 0) return;
3707  rms = sqrt(rms / (cnt - 1));
3708 
3709  if (prt) {
3710  mf::LogVerbatim myprt("TC");
3711  myprt << fcnLabel << " schg:";
3712  for (unsigned short ii = 0; ii < 20; ++ii)
3713  myprt << " " << (int)schg[ii];
3714  myprt << "\n First guess at the charge " << (int)chg << " average charge of all bins "
3715  << (int)ave << " rms " << (int)rms;
3716  }
3717 
3718  // initial guess at the charge rms
3719  rms = 0.8 * chg;
3720 
3721  unsigned short nBinsAverage = 5;
3722  double maxChg = 2 * chg;
3723  for (unsigned short nit = 0; nit < 2; ++nit) {
3724  double sum = 0;
3725  double sum2 = 0;
3726  double cnt = 0;
3727  for (unsigned short ii = startPt; ii < schg.size() - 1; ++ii) {
3728  // break if we find 2 consecutive high charge points
3729  if (schg[ii] > maxChg && schg[ii + 1] > maxChg) break;
3730  // or two zeros
3731  if (schg[ii] == 0 && schg[ii + 1] == 0) break;
3732  if (schg[ii] > maxChg) continue;
3733  sum += schg[ii];
3734  sum2 += schg[ii] * schg[ii];
3735  ++cnt;
3736  if (cnt == nBinsAverage) break;
3737  } // ii
3738  // check for a failure
3739  if (cnt < 3) {
3740  if (prt)
3741  mf::LogVerbatim("TC") << fcnLabel << " nit " << nit << " cnt " << cnt
3742  << " is too low. sum " << (int)sum << " maxChg " << (int)maxChg;
3743  // try to recover. Pick the next point
3744  ++startPt;
3745  chg = schg[startPt];
3746  maxChg = 2 * chg;
3747  continue;
3748  }
3749  // convert sum to the average charge
3750  chg = sum / cnt;
3751  double arg = sum2 - cnt * chg * chg;
3752  if (arg < 0) break;
3753  rms = sqrt(arg / (cnt - 1));
3754  // don't allow the rms to get crazy
3755  double maxrms = 0.5 * sum;
3756  if (rms > maxrms) rms = maxrms;
3757  maxChg = chg + 2 * rms;
3758  if (prt)
3759  mf::LogVerbatim("TC") << fcnLabel << " nit " << nit << " cnt " << cnt << " chg " << (int)chg
3760  << " rms " << (int)rms << " maxChg " << (int)maxChg
3761  << " nBinsAverage " << nBinsAverage;
3762  nBinsAverage = 20;
3763  } // nit
3764 
3765  stp0.AveChg = chg;
3766 
3767  if (prt)
3768  mf::LogVerbatim("TC") << fcnLabel << " 2S" << cotID << " Starting charge " << (int)stp0.AveChg
3769  << " startPt " << startPt;
3770 
3771  } // FindStartChg
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
for(Int_t i=0;i< nentries;i++)
Definition: comparison.C:30
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:549
if(nlines<=0)
std::vector< float > StartChgVec(TCSlice &slc, int cotID)
Definition: TCShower.cxx:3774
Double_t sum
Definition: plot.C:31
void tca::FindUseHits ( TCSlice slc,
Trajectory tj,
unsigned short  ipt,
float  maxDelta,
bool  useChg 
)

Definition at line 1882 of file StepUtils.cxx.

References util::abs(), 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, if(), 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, and tca::TrajPoint::UseHit.

Referenced by AddHits().

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

Definition at line 154 of file TCShower.cxx.

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

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

155  {
156  // Finish defining the showers, create a companion PFParticle for each one.
157  // Note to the reader: This code doesn't use MakeVertexObsolete to kill vertices using the assumption
158  // that Finish3DShowers is being called after reconstruction is complete, in which case there is no
159  // need to re-calculate the 2D and 3D vertex score which could potentially screw up the decisions that have
160  // already been made.
161 
162  // See if any need to be finished
163  bool noShowers = true;
164  for (auto& ss3 : slc.showers) {
165  if (ss3.ID == 0) continue;
166  noShowers = false;
167  }
168  if (noShowers) return;
169 
170  ChkAssns("Fin3D", slc);
171 
172  // create a pfp and define the mother-daughter relationship. At this point, the shower parent PFP (if
173  // one exists) is a track-like pfp that might be the daughter of another pfp, e.g. the neutrino. This
174  // association is changed from shower ParentID -> parent pfp, to shower PFP -> parent pfp
175  for (auto& ss3 : slc.showers) {
176  if (ss3.ID == 0) continue;
177  if (ss3.PFPIndex != USHRT_MAX) continue;
178  auto showerPFP = CreatePFP(slc);
179  showerPFP.TjIDs.resize(ss3.CotIDs.size());
180  for (unsigned short ii = 0; ii < ss3.CotIDs.size(); ++ii) {
181  unsigned short cid = ss3.CotIDs[ii];
182  if (cid == 0 || cid > slc.cots.size()) return;
183  auto& ss = slc.cots[cid - 1];
184  auto& stj = slc.tjs[ss.ShowerTjID - 1];
185  showerPFP.TjIDs[ii] = stj.ID;
186  } // ci
187  showerPFP.PDGCode = 1111;
188  auto& sf = showerPFP.SectionFits[0];
189  sf.Pos = ss3.Start;
190  sf.Dir = ss3.Dir;
191  sf.DirErr = ss3.DirErr;
192  showerPFP.Vx3ID[0] = ss3.Vx3ID;
193  sf.Dir = ss3.Dir;
194  // dEdx is indexed by plane for pfps and by 2D shower index for 3D showers
195  for (auto cid : ss3.CotIDs) {
196  auto& ss = slc.cots[cid - 1];
197  unsigned short plane = DecodeCTP(ss.CTP).Plane;
198  auto& stj = slc.tjs[ss.ShowerTjID - 1];
199  showerPFP.dEdx[0][plane] = stj.dEdx[0];
200  showerPFP.dEdxErr[0][plane] = 0.3 * stj.dEdx[0];
201  } // ci
202  ss3.PFPIndex = slc.pfps.size();
203  if (ss3.ParentID > 0) {
204  // see if this is a daughter
205  auto& dtrPFP = slc.pfps[ss3.ParentID - 1];
206  if (dtrPFP.ParentUID > 0) {
207  // Transfer the daughter <-> parent assn
208  auto slcIndx = GetSliceIndex("P", dtrPFP.ParentUID);
209  auto& parPFP = slices[slcIndx.first].pfps[slcIndx.second];
210  showerPFP.ParentUID = parPFP.UID;
211  std::replace(parPFP.DtrUIDs.begin(), parPFP.DtrUIDs.end(), dtrPFP.UID, showerPFP.UID);
212  dtrPFP.ParentUID = 0;
213  } // dtrPFP.ParentID > 0
214  } // ss3.ParentID > 0
215  slc.pfps.push_back(showerPFP);
216  } // ss3
217 
218  // Transfer Tj hits from InShower Tjs to the shower Tj. This kills the InShower Tjs but doesn't consider how
219  // this action affects vertices
220  if (!TransferTjHits(slc, false)) return;
221 
222  // Associate shower Tj hits with 3D showers
223  for (auto& ss3 : slc.showers) {
224  if (ss3.ID == 0) continue;
225  for (unsigned short ii = 0; ii < ss3.CotIDs.size(); ++ii) {
226  unsigned short cid = ss3.CotIDs[ii];
227  auto& ss = slc.cots[cid - 1];
228  for (auto tjid : ss.TjIDs) {
229  Trajectory& tj = slc.tjs[tjid - 1];
230  auto tjHits = PutTrajHitsInVector(tj, kUsedHits);
231  ss3.Hits.insert(ss3.Hits.end(), tjHits.begin(), tjHits.end());
232  // kill vertices associated with the Tj unless it is the neutrino primary vtx
233  for (unsigned short end = 0; end < 2; ++end) {
234  if (tj.VtxID[end] == 0) continue;
235  auto& vx2 = slc.vtxs[tj.VtxID[end] - 1];
236  if (vx2.Vx3ID <= 0) {
237  // This is a 2D vertex that is not matched in 3D. Kill it. Shouldn't need to
238  // use MakeVertexObsolete here...
239  vx2.ID = 0;
240  continue;
241  }
242  // vx2 is matched in 3D. Kill it if it is NOT the neutrino primary
243  auto& vx3 = slc.vtx3s[vx2.Vx3ID - 1];
244  if (vx3.Neutrino) continue;
245  vx3.ID = 0;
246  } // end
247  } // tjid
248  } // ii
249  } // ss3
250 
251  // kill PFParticles
252  if (!slc.pfps.empty()) {
253  for (auto& pfp : slc.pfps) {
254  if (pfp.ID == 0) continue;
255  if (pfp.TjIDs.empty()) continue;
256  unsigned short ndead = 0;
257  for (auto tjid : pfp.TjIDs) {
258  auto& tj = slc.tjs[tjid - 1];
259  if (tj.AlgMod[kKilled]) ++ndead;
260  } // tjid
261  if (ndead == 0) continue;
262  pfp.ID = 0;
263  } // pfp
264  } // pfps not empty
265 
266  // kill orphan 2D vertices
267  for (auto& vx2 : slc.vtxs) {
268  if (vx2.ID == 0) continue;
269  auto vxtjs = GetAssns(slc, "2V", vx2.ID, "T");
270  if (vxtjs.empty()) vx2.ID = 0;
271  } // vx2
272 
273  // kill orphan vertices
274  for (auto& vx3 : slc.vtx3s) {
275  if (vx3.ID == 0) continue;
276  auto vxtjs = GetAssns(slc, "3V", vx3.ID, "T");
277  if (vxtjs.empty()) {
278  vx3.ID = 0;
279  continue;
280  }
281  } // vx3
282 
283  } // Finish3DShowers
bool TransferTjHits(TCSlice &slc, bool prt)
Definition: TCShower.cxx:3845
std::vector< unsigned int > PutTrajHitsInVector(const Trajectory &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2689
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4095
PFPStruct CreatePFP(const TCSlice &slc)
Definition: PFPUtils.cxx:2802
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
std::vector< int > GetAssns(TCSlice const &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4704
geo::PlaneID DecodeCTP(CTP_t CTP)
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:4942
bool tca::Fit2D ( short  mode,
Point2_t  inPt,
float &  inPtErr,
Vector2_t outVec,
Vector2_t outVecErr,
float &  chiDOF 
)

Definition at line 4982 of file Utils.cxx.

References sum.

Referenced by ChkStop(), DotProd(), and FitPar().

4988  {
4989  // Fit points to a 2D line.
4990  // Mode = 0: Initialize
4991  // Mode = 1: Accumulate
4992  // Mode = 2: Accumulate and store to calculate chiDOF
4993  // Mode = -1: Fit and put results in outVec and chiDOF
4994 
4995  static double sum, sumx, sumy, sumx2, sumy2, sumxy;
4996  static unsigned short cnt;
4997  static std::vector<Point2_t> fitPts;
4998  static std::vector<double> fitWghts;
4999 
5000  if (mode == 0) {
5001  // initialize
5002  cnt = 0;
5003  sum = 0.;
5004  sumx = 0.;
5005  sumy = 0.;
5006  sumx2 = 0.;
5007  sumy2 = 0.;
5008  sumxy = 0;
5009  fitPts.resize(0);
5010  fitWghts.resize(0);
5011  return true;
5012  } // mode == 0
5013 
5014  if (mode > 0) {
5015  if (inPtErr <= 0.) return false;
5016  ++cnt;
5017  double wght = 1 / (inPtErr * inPtErr);
5018  sum += wght;
5019  sumx += wght * inPt[0];
5020  sumx2 += wght * inPt[0] * inPt[0];
5021  sumy += wght * inPt[1];
5022  sumy2 += wght * inPt[1] * inPt[1];
5023  sumxy += wght * inPt[0] * inPt[1];
5024  if (mode == 1) return true;
5025  fitPts.push_back(inPt);
5026  fitWghts.push_back(wght);
5027  return true;
5028  } // Accumulate
5029 
5030  if (cnt < 2) return false;
5031  // do the fit
5032  double delta = sum * sumx2 - sumx * sumx;
5033  if (delta == 0.) return false;
5034  double A = (sumx2 * sumy - sumx * sumxy) / delta;
5035  double B = (sumxy * sum - sumx * sumy) / delta;
5036  outVec[0] = A;
5037  outVec[1] = B;
5038  chiDOF = 0;
5039  if (cnt == 2 || fitPts.empty()) return true;
5040 
5041  // calculate errors and chiDOF
5042  if (fitPts.size() != cnt) return false;
5043  double ndof = cnt - 2;
5044  double varnce =
5045  (sumy2 + A * A * sum + B * B * sumx2 - 2 * (A * sumy + B * sumxy - A * B * sumx)) / ndof;
5046  if (varnce > 0.) {
5047  outVecErr[0] = sqrt(varnce * sumx2 / delta);
5048  outVecErr[1] = sqrt(varnce * sum / delta);
5049  }
5050  else {
5051  outVecErr[0] = 0.;
5052  outVecErr[1] = 0.;
5053  }
5054  sum = 0.;
5055  // calculate chisq
5056  for (unsigned short ii = 0; ii < fitPts.size(); ++ii) {
5057  double arg = fitPts[ii][1] - A - B * fitPts[ii][0];
5058  sum += fitWghts[ii] * arg * arg;
5059  }
5060  chiDOF = sum / ndof;
5061  fitPts.resize(0);
5062  fitWghts.resize(0);
5063  return true;
5064 
5065  } // Fit2D
Double_t sum
Definition: plot.C:31
void tca::FitPar ( const Trajectory tj,
unsigned short  originPt,
unsigned short  npts,
short  fitDir,
ParFit pFit,
unsigned short  usePar 
)

Definition at line 1202 of file Utils.cxx.

References util::abs(), tca::ParFit::AvePar, tca::ParFit::ChiDOF, tca::Trajectory::EndPt, Fit2D(), tca::ParFit::nPtsFit, tca::ParFit::Par0, tca::ParFit::ParErr, tca::ParFit::ParSlp, tca::ParFit::ParSlpErr, tca::ParFit::Pos, and tca::Trajectory::Pts.

Referenced by BraggSplit(), Forecast(), and StopShort().

1208  {
1209  // Fit a TP parameter, like Chg or Delta, to a line using the points starting at originPT.
1210  // Currently supported values of usePar are Chg (1) and Delta (2)
1211 
1212  pFit.ChiDOF = 999;
1213  pFit.AvePar = 0.;
1214  if (originPt > tj.Pts.size() - 1) return;
1215  if (fitDir != 1 && fitDir != -1) return;
1216  Point2_t inPt;
1217  Vector2_t outVec, outVecErr;
1218  float pErr, chiDOF;
1219  Fit2D(0, inPt, pErr, outVec, outVecErr, chiDOF);
1220  unsigned short cnt = 0;
1221  for (unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
1222  unsigned short ipt = originPt + ii * fitDir;
1223  if (ipt < tj.EndPt[0] || ipt > tj.EndPt[1]) break;
1224  auto& tp = tj.Pts[ipt];
1225  if (tp.Chg <= 0) continue;
1226  // Accumulate and save points
1227  inPt[0] = std::abs(tp.Pos[0] - tj.Pts[originPt].Pos[0]);
1228  float parVal = tp.Chg;
1229  // Assume errors are 10% for a charge fit
1230  pErr = 0.1 * parVal;
1231  if (usePar > 1) {
1232  parVal = tp.Delta;
1233  // use the TP hit position error for a Delta Fit
1234  pErr = sqrt(tp.HitPosErr2);
1235  }
1236  inPt[1] = parVal;
1237  pFit.AvePar += parVal;
1238  if (!Fit2D(2, inPt, pErr, outVec, outVecErr, chiDOF)) break;
1239  ++cnt;
1240  if (cnt == npts) break;
1241  } // ii
1242  if (cnt < npts) return;
1243  // do the fit and get the results
1244  if (!Fit2D(-1, inPt, pErr, outVec, outVecErr, chiDOF)) return;
1245  pFit.Pos = tj.Pts[originPt].Pos;
1246  pFit.Par0 = outVec[0];
1247  pFit.AvePar /= (float)cnt;
1248  pFit.ParErr = outVecErr[0];
1249  pFit.Pos = tj.Pts[originPt].Pos;
1250  pFit.ParSlp = outVec[1];
1251  pFit.ParSlpErr = outVecErr[1];
1252  pFit.ChiDOF = chiDOF;
1253  pFit.nPtsFit = cnt;
1254  } // FitPar
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::array< float, 2 > Point2_t
Definition: DataStructs.h:41
bool Fit2D(short mode, Point2_t inPt, float &inPtErr, Vector2_t &outVec, Vector2_t &outVecErr, float &chiDOF)
Definition: Utils.cxx:4982
std::array< double, 2 > Vector2_t
Definition: DataStructs.h:42
bool tca::FitSection ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice slc,
PFPStruct pfp,
unsigned short  sfIndex 
)

Definition at line 1391 of file PFPUtils.cxx.

References FitTP3Ds(), tca::PFPStruct::Flags, GetRange(), kSmallAngle, tca::PFPStruct::SectionFits, and tca::PFPStruct::TP3Ds.

Referenced by MakePFParticles(), Recover(), ReSection(), and Update().

1395  {
1396  // Fits the TP3D points in the selected section to a 3D line with the origin at the center of
1397  // the section
1398  if (pfp.TP3Ds.size() < 4) return false;
1399  if (sfIndex >= pfp.SectionFits.size()) return false;
1400  // don't fit a small angle PFP
1401  if (pfp.Flags[kSmallAngle]) return true;
1402 
1403  unsigned short fromPt = USHRT_MAX;
1404  unsigned short npts = 0;
1405  GetRange(pfp, sfIndex, fromPt, npts);
1406  if (fromPt == USHRT_MAX) return false;
1407  if (npts < 4) return false;
1408 
1409  // check for errors
1410  for (unsigned short ipt = fromPt; ipt < fromPt + npts; ++ipt) {
1411  auto& tp3d = pfp.TP3Ds[ipt];
1412  if (tp3d.SFIndex != sfIndex) return false;
1413  } // ipt
1414 
1415  // fit these points and update
1416  return FitTP3Ds(detProp, slc, pfp, fromPt, npts, sfIndex);
1417 
1418  } // FitSection
bool FitTP3Ds(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, unsigned short fromPt, unsigned short nPtsFit, unsigned short sfIndex)
Definition: PFPUtils.cxx:1565
void GetRange(const PFPStruct &pfp, unsigned short sfIndex, unsigned short &fromPt, unsigned short &npts)
Definition: PFPUtils.cxx:1370
SectionFit tca::FitTP3Ds ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice slc,
const std::vector< TP3D > &  tp3ds,
unsigned short  fromPt,
short  fitDir,
unsigned short  nPtsFit 
)

Definition at line 1421 of file PFPUtils.cxx.

References tca::SectionFit::ChiDOF, geo::CryostatID::Cryostat, DecodeCTP(), tca::SectionFit::Dir, tca::SectionFit::DirErr, EncodeCTP(), kTP3DGood, MakeBareTP(), norm, tca::TCSlice::nPlanes, tca::SectionFit::NPts, geo::WireReadoutGeom::Plane(), geo::PlaneID::Plane, tca::SectionFit::Pos, tcc, geo::TPCID::TPC, tca::TCSlice::TPCID, w, weight, tca::TCConfig::wireReadoutGeom, and x.

Referenced by FitSection(), FitTP3Ds(), and ReSection().

1427  {
1428  // fits the points and returns the fit results in a SectionFit struct. This function assumes that the
1429  // vector of TP3Ds exists in the slc.TPCID
1430 
1431  SectionFit sf;
1432  sf.ChiDOF = 999;
1433  if (nPtsFit < 5) return sf;
1434  if (!(fitDir == -1 || fitDir == 1)) return sf;
1435  if (fitDir == 1 && fromPt + nPtsFit > tp3ds.size()) return sf;
1436  if (fitDir == -1 && fromPt < 3) return sf;
1437 
1438  // put the offset, cosine-like and sine-like components in a vector
1439  std::vector<std::array<double, 3>> ocs(slc.nPlanes);
1440  for (unsigned short p = 0; p < slc.nPlanes; ++p) {
1441  auto planeID = geo::PlaneID{slc.TPCID, p};
1442  auto const& plane = tcc.wireReadoutGeom->Plane(planeID);
1443  // plane offset
1444  ocs[p][0] = plane.WireCoordinate(geo::Point_t{0, 0, 0});
1445  // get the "cosine-like" component
1446  ocs[p][1] = plane.WireCoordinate(geo::Point_t{0, 1, 0}) - ocs[p][0];
1447  // the "sine-like" component
1448  ocs[p][2] = plane.WireCoordinate(geo::Point_t{0, 0, 1}) - ocs[p][0];
1449  } // plane
1450 
1451  const unsigned int nvars = 4;
1452  unsigned int npts = 0;
1453 
1454  // count the number of TPs in each plane
1455  std::vector<unsigned short> cntInPln(slc.nPlanes, 0);
1456  // and define the X position for the fit origin
1457  double x0 = 0.;
1458  for (short ii = 0; ii < nPtsFit; ++ii) {
1459  short ipt = fromPt + fitDir * ii;
1460  if (ipt < 0 || ipt >= (short)tp3ds.size()) break;
1461  auto& tp3d = tp3ds[ipt];
1462  if (!tp3d.Flags[kTP3DGood]) continue;
1463  if (tp3d.TPXErr2 < 0.0001) return sf;
1464  x0 += tp3d.TPX;
1465  unsigned short plane = DecodeCTP(tp3d.CTP).Plane;
1466  ++cntInPln[plane];
1467  ++npts;
1468  } // ipt
1469  if (npts < 6) return sf;
1470  // ensure there are at least three points in at least two planes
1471  unsigned short enufInPlane = 0;
1472  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane)
1473  if (cntInPln[plane] > 2) ++enufInPlane;
1474  if (enufInPlane < 2) return sf;
1475 
1476  x0 /= (double)npts;
1477 
1478  TMatrixD A(npts, nvars);
1479  // vector holding the Wire number
1480  TVectorD w(npts);
1481  unsigned short cnt = 0;
1482  double weight = 1;
1483  for (short ii = 0; ii < nPtsFit; ++ii) {
1484  short ipt = fromPt + fitDir * ii;
1485  auto& tp3d = tp3ds[ipt];
1486  if (!tp3d.Flags[kTP3DGood]) continue;
1487  unsigned short plane = DecodeCTP(tp3d.CTP).Plane;
1488  double x = tp3d.TPX - x0;
1489  A[cnt][0] = weight * ocs[plane][1];
1490  A[cnt][1] = weight * ocs[plane][2];
1491  A[cnt][2] = weight * ocs[plane][1] * x;
1492  A[cnt][3] = weight * ocs[plane][2] * x;
1493  w[cnt] = weight * (tp3d.Wire - ocs[plane][0]);
1494  ++cnt;
1495  } // ipt
1496 
1497  TDecompSVD svd(A);
1498  bool ok;
1499  TVectorD tVec = svd.Solve(w, ok);
1500  if (!ok) return sf;
1501  double norm = sqrt(1 + tVec[2] * tVec[2] + tVec[3] * tVec[3]);
1502 
1503  norm *= -1;
1504 
1505  sf.Dir[0] = 1 / norm;
1506  sf.Dir[1] = tVec[2] / norm;
1507  sf.Dir[2] = tVec[3] / norm;
1508  sf.Pos[0] = x0;
1509  sf.Pos[1] = tVec[0];
1510  sf.Pos[2] = tVec[1];
1511  sf.NPts = npts;
1512 
1513  // Calculate errors from sigma * (A^T * A)^(-1) where sigma is the
1514  // error on the wire number (= 1)
1515  TMatrixD AT(nvars, npts);
1516  AT.Transpose(A);
1517  TMatrixD ATA = AT * A;
1518  double* det = 0;
1519  try {
1520  ATA.Invert(det);
1521  }
1522  catch (...) {
1523  return sf;
1524  }
1525  sf.DirErr[1] = -sqrt(ATA[2][2]) / norm;
1526  sf.DirErr[2] = -sqrt(ATA[3][3]) / norm;
1527 
1528  // calculate ChiDOF
1529  sf.ChiDOF = 0;
1530  // project this 3D vector into a TP in every plane
1531  std::vector<TrajPoint> plnTP(slc.nPlanes);
1532  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
1533  CTP_t inCTP = EncodeCTP(slc.TPCID.Cryostat, slc.TPCID.TPC, plane);
1534  plnTP[plane] = MakeBareTP(detProp, sf.Pos, sf.Dir, inCTP);
1535  } // plane
1536  // a local position
1537  Point3_t pos;
1538  sf.DirErr[0] = 0.;
1539  for (short ii = 0; ii < nPtsFit; ++ii) {
1540  short ipt = fromPt + fitDir * ii;
1541  auto& tp3d = tp3ds[ipt];
1542  if (!tp3d.Flags[kTP3DGood]) continue;
1543  unsigned short plane = DecodeCTP(tp3d.CTP).Plane;
1544  double dw = tp3d.Wire - plnTP[plane].Pos[0];
1545  // dt/dW was stored in DeltaRMS by MakeBareTP
1546  double t = dw * plnTP[plane].DeltaRMS;
1547  for (unsigned short xyz = 0; xyz < 3; ++xyz)
1548  pos[xyz] = sf.Pos[xyz] + t * sf.Dir[xyz];
1549  // Note that the tp3d position is directly above the wire position and not the
1550  // point at the distance of closest approach. Delta is the difference in the
1551  // drift direction in cm
1552  double delta = pos[0] - tp3d.TPX;
1553  sf.ChiDOF += delta * delta / tp3d.TPXErr2;
1554  // estimate the X slope error ~ X direction vector with an overly simple average
1555  double dangErr = delta / dw;
1556  sf.DirErr[0] += dangErr * dangErr;
1557  } // indx
1558  sf.DirErr[0] = sqrt(sf.DirErr[0]) / (double)nPtsFit;
1559  sf.ChiDOF /= (float)(npts - 4);
1560  return sf;
1561 
1562  } // FitTP3Ds
Float_t x
Definition: compare.C:6
const geo::WireReadoutGeom * wireReadoutGeom
Definition: DataStructs.h:568
std::array< double, 3 > Point3_t
Definition: DataStructs.h:39
double WireCoordinate(Point_t const &point) const
Returns the coordinate of the point on the plane, in wire units.
Definition: PlaneGeo.h:704
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const Point3_t &pos, CTP_t inCTP)
Definition: Utils.cxx:3928
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:180
double weight
Definition: plottest35.C:25
unsigned int CTP_t
Definition: DataStructs.h:45
Float_t norm
geo::PlaneID DecodeCTP(CTP_t CTP)
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:49
PlaneGeo const & Plane(TPCID const &tpcid, View_t view) const
Returns the specified wire.
Float_t w
Definition: plot.C:20
constexpr TPCID()=default
Default constructor: an invalid TPC ID.
bool tca::FitTP3Ds ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice slc,
PFPStruct pfp,
unsigned short  fromPt,
unsigned short  nPtsFit,
unsigned short  sfIndex 
)

Definition at line 1565 of file PFPUtils.cxx.

References geo::CryostatID::Cryostat, DecodeCTP(), EncodeCTP(), FitTP3Ds(), if(), kTP3DGood, MakeBareTP(), tca::TCSlice::nPlanes, geo::PlaneID::Plane, tca::PFPStruct::SectionFits, SortSection(), tca::PFPStruct::TP3Ds, geo::TPCID::TPC, and tca::PFPStruct::TPCID.

1571  {
1572  // Fit points in the pfp.TP3Ds vector fromPt. This function
1573  // doesn't update the TP3Ds unless sfIndex refers to a valid SectionFit in the pfp.
1574  // No check is made to ensure that the TP3D SFIndex variable is compatible with sfIndex
1575 
1576  if (nPtsFit < 5) return false;
1577  if (fromPt + nPtsFit > pfp.TP3Ds.size()) return false;
1578 
1579  auto sf = FitTP3Ds(detProp, slc, pfp.TP3Ds, fromPt, 1, nPtsFit);
1580  if (sf.ChiDOF > 900) return false;
1581 
1582  // don't update the pfp?
1583  if (sfIndex >= pfp.SectionFits.size()) return true;
1584 
1585  // update the pfp Sectionfit
1586  pfp.SectionFits[sfIndex] = sf;
1587  // update the TP3Ds
1588  // project this 3D vector into a TP in every plane
1589  std::vector<TrajPoint> plnTP(slc.nPlanes);
1590  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
1591  CTP_t inCTP = EncodeCTP(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
1592  plnTP[plane] = MakeBareTP(detProp, sf.Pos, sf.Dir, inCTP);
1593  } // plane
1594  Point3_t pos;
1595  bool needsSort = false;
1596  double prevAlong = 0;
1597  for (unsigned short ipt = fromPt; ipt < fromPt + nPtsFit; ++ipt) {
1598  auto& tp3d = pfp.TP3Ds[ipt];
1599  unsigned short plane = DecodeCTP(tp3d.CTP).Plane;
1600  double dw = tp3d.Wire - plnTP[plane].Pos[0];
1601  // dt/dW was stored in DeltaRMS by MakeBareTP
1602  double t = dw * plnTP[plane].DeltaRMS;
1603  if (ipt == fromPt) { prevAlong = t; }
1604  else {
1605  if (t < prevAlong) needsSort = true;
1606  prevAlong = t;
1607  }
1608  for (unsigned short xyz = 0; xyz < 3; ++xyz)
1609  pos[xyz] = sf.Pos[xyz] + t * sf.Dir[xyz];
1610  // Note that the tp3d position is directly above the wire position and not the
1611  // distance of closest approach. The Delta variable is the difference in the
1612  // drift direction in cm
1613  double delta = pos[0] - tp3d.TPX;
1614  tp3d.Pos = pos;
1615  tp3d.Dir = sf.Dir;
1616  tp3d.along = t;
1617  if (tp3d.Flags[kTP3DGood]) sf.ChiDOF += delta * delta / tp3d.TPXErr2;
1618  } // ipt
1619  if (needsSort) SortSection(pfp, sfIndex);
1620  pfp.SectionFits[sfIndex].NeedsUpdate = false;
1621  return true;
1622 
1623  } // FitTP3Ds
std::array< double, 3 > Point3_t
Definition: DataStructs.h:39
bool SortSection(PFPStruct &pfp, unsigned short sfIndex)
Definition: PFPUtils.cxx:1999
bool FitTP3Ds(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, unsigned short fromPt, unsigned short nPtsFit, unsigned short sfIndex)
Definition: PFPUtils.cxx:1565
if(nlines<=0)
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const Point3_t &pos, CTP_t inCTP)
Definition: Utils.cxx:3928
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
unsigned int CTP_t
Definition: DataStructs.h:45
geo::PlaneID DecodeCTP(CTP_t CTP)
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:49
void tca::FitTraj ( TCSlice const &  slc,
Trajectory tj 
)

Definition at line 798 of file Utils.cxx.

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

Referenced by BraggSplit(), EndMerge(), KinkSignificance(), MakeJunkTraj(), MaskBadTPs(), MaskedHitsOK(), UpdateStiffEl(), and UpdateTraj().

799  {
800  // Jacket around FitTraj to fit the leading edge of the supplied trajectory
801  unsigned short originPt = tj.EndPt[1];
802  unsigned short npts = tj.Pts[originPt].NTPsFit;
803  TrajPoint tpFit;
804  unsigned short fitDir = -1;
805  FitTraj(slc, tj, originPt, npts, fitDir, tpFit);
806  tj.Pts[originPt] = tpFit;
807 
808  } // FitTraj
void FitTraj(TCSlice const &slc, Trajectory &tj, unsigned short originPt, unsigned short npts, short fitDir, TrajPoint &tpFit)
Definition: Utils.cxx:811
void tca::FitTraj ( TCSlice const &  slc,
Trajectory tj,
unsigned short  originPt,
unsigned short  npts,
short  fitDir,
TrajPoint tpFit 
)

Definition at line 811 of file Utils.cxx.

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

817  {
818  // Fit the supplied trajectory using HitPos positions with the origin at originPt.
819  // The npts is interpreted as the number of points on each side of the origin
820  // The allowed modes are as follows, where i denotes a TP that is included, . denotes
821  // a TP with no hits, and x denotes a TP that is not included
822  //TP 012345678 fitDir originPt npts
823  // Oiiixxxxx 1 0 4 << npts in the fit
824  // xi.iiOxxx -1 5 4
825  // xiiiOiiix 0 4 4 << 2 * npts + 1 points in the fit
826  // xxxiO.ixx 0 4 1
827  // 0iiixxxxx 0 0 4
828  // This routine puts the results into tp if the fit is successfull. The
829  // fit "direction" is in increasing order along the trajectory from 0 to tj.Pts.size() - 1.
830 
831  // static const float twoPi = 2 * M_PI;
832 
833  if (originPt > tj.Pts.size() - 1) {
834  mf::LogWarning("TC") << "FitTraj: Requesting fit of invalid TP " << originPt;
835  return;
836  }
837 
838  // copy the origin TP into the fit TP
839  tpFit = tj.Pts[originPt];
840  // Assume that the fit will fail
841  tpFit.FitChi = 999;
842  if (fitDir < -1 || fitDir > 1) return;
843 
844  std::vector<double> x, y;
845  Point2_t origin = tj.Pts[originPt].HitPos;
846  // Use TP position if there aren't any hits on it
847  if (tj.Pts[originPt].Chg == 0) origin = tj.Pts[originPt].Pos;
848 
849  // simple two point case
850  if (NumPtsWithCharge(slc, tj, false) == 2) {
851  for (unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1]; ++ipt) {
852  if (tj.Pts[ipt].Chg <= 0) continue;
853  double xx = tj.Pts[ipt].HitPos[0] - origin[0];
854  double yy = tj.Pts[ipt].HitPos[1] - origin[1];
855  x.push_back(xx);
856  y.push_back(yy);
857  } // ii
858  if (x.size() != 2) return;
859  if (x[0] == x[1]) {
860  // Either + or - pi/2
861  tpFit.Ang = M_PI / 2;
862  if (y[1] < y[0]) tpFit.Ang = -tpFit.Ang;
863  }
864  else {
865  double dx = x[1] - x[0];
866  double dy = y[1] - y[0];
867  tpFit.Ang = atan2(dy, dx);
868  }
869  tpFit.Dir[0] = cos(tpFit.Ang);
870  tpFit.Dir[1] = sin(tpFit.Ang);
871  tpFit.Pos[0] += origin[0];
872  tpFit.Pos[1] += origin[1];
873  tpFit.AngErr = 0.01;
874  tpFit.FitChi = 0.01;
875  SetAngleCode(tpFit);
876  return;
877  } // two points
878 
879  std::vector<double> w, q;
880  std::array<double, 2> dir;
881  double xx, yy, xr, yr;
882  double chgWt;
883 
884  // Rotate the traj hit position into the coordinate system defined by the
885  // originPt traj point, where x = along the trajectory, y = transverse
886  double rotAngle = tj.Pts[originPt].Ang;
887  double cs = cos(-rotAngle);
888  double sn = sin(-rotAngle);
889 
890  // enter the originPT hit info if it exists
891  if (tj.Pts[originPt].Chg > 0) {
892  xx = tj.Pts[originPt].HitPos[0] - origin[0];
893  yy = tj.Pts[originPt].HitPos[1] - origin[1];
894  xr = cs * xx - sn * yy;
895  yr = sn * xx + cs * yy;
896  x.push_back(xr);
897  y.push_back(yr);
898  chgWt = tj.Pts[originPt].ChgPull;
899  if (chgWt < 1) chgWt = 1;
900  chgWt *= chgWt;
901  w.push_back(chgWt * tj.Pts[originPt].HitPosErr2);
902  }
903 
904  // correct npts to account for the origin point
905  if (fitDir != 0) --npts;
906 
907  // step in the + direction first
908  if (fitDir != -1) {
909  unsigned short cnt = 0;
910  for (unsigned short ipt = originPt + 1; ipt < tj.Pts.size(); ++ipt) {
911  if (tj.Pts[ipt].Chg <= 0) continue;
912  xx = tj.Pts[ipt].HitPos[0] - origin[0];
913  yy = tj.Pts[ipt].HitPos[1] - origin[1];
914  xr = cs * xx - sn * yy;
915  yr = sn * xx + cs * yy;
916  x.push_back(xr);
917  y.push_back(yr);
918  chgWt = tj.Pts[ipt].ChgPull;
919  if (chgWt < 1) chgWt = 1;
920  chgWt *= chgWt;
921  w.push_back(chgWt * tj.Pts[ipt].HitPosErr2);
922  ++cnt;
923  if (cnt == npts) break;
924  } // ipt
925  } // fitDir != -1
926 
927  // step in the - direction next
928  if (fitDir != 1 && originPt > 0) {
929  unsigned short cnt = 0;
930  for (unsigned short ii = 1; ii < tj.Pts.size(); ++ii) {
931  unsigned short ipt = originPt - ii;
932  if (ipt > tj.Pts.size() - 1) continue;
933  if (tj.Pts[ipt].Chg == 0) continue;
934  xx = tj.Pts[ipt].HitPos[0] - origin[0];
935  yy = tj.Pts[ipt].HitPos[1] - origin[1];
936  xr = cs * xx - sn * yy;
937  yr = sn * xx + cs * yy;
938  x.push_back(xr);
939  y.push_back(yr);
940  chgWt = tj.Pts[ipt].ChgPull;
941  if (chgWt < 1) chgWt = 1;
942  chgWt *= chgWt;
943  w.push_back(chgWt * tj.Pts[ipt].HitPosErr2);
944  ++cnt;
945  if (cnt == npts) break;
946  if (ipt == 0) break;
947  } // ipt
948  } // fitDir != -1
949 
950  // Not enough points to define a line?
951  if (x.size() < 2) return;
952 
953  double sum = 0.;
954  double sumx = 0.;
955  double sumy = 0.;
956  double sumxy = 0.;
957  double sumx2 = 0.;
958  double sumy2 = 0.;
959 
960  // weight by the charge ratio and accumulate sums
961  double wght;
962  for (unsigned short ipt = 0; ipt < x.size(); ++ipt) {
963  if (w[ipt] < 0.00001) w[ipt] = 0.00001;
964  wght = 1 / w[ipt];
965  sum += wght;
966  sumx += wght * x[ipt];
967  sumy += wght * y[ipt];
968  sumx2 += wght * x[ipt] * x[ipt];
969  sumy2 += wght * y[ipt] * y[ipt];
970  sumxy += wght * x[ipt] * y[ipt];
971  }
972  // calculate coefficients and std dev
973  double delta = sum * sumx2 - sumx * sumx;
974  if (delta == 0) return;
975  // A is the intercept
976  double A = (sumx2 * sumy - sumx * sumxy) / delta;
977  // B is the slope
978  double B = (sumxy * sum - sumx * sumy) / delta;
979 
980  // The chisq will be set below if there are enough points. Don't allow it to be 0
981  // so we can take Chisq ratios later
982  tpFit.FitChi = 0.01;
983  double newang = atan(B);
984  dir[0] = cos(newang);
985  dir[1] = sin(newang);
986  // rotate back into the (w,t) coordinate system
987  cs = cos(rotAngle);
988  sn = sin(rotAngle);
989  tpFit.Dir[0] = cs * dir[0] - sn * dir[1];
990  tpFit.Dir[1] = sn * dir[0] + cs * dir[1];
991  // ensure that the direction is consistent with the originPt direction
992  bool flipDir = false;
993  if (AngleRange(tj.Pts[originPt]) > 0) {
994  flipDir = std::signbit(tpFit.Dir[1]) != std::signbit(tj.Pts[originPt].Dir[1]);
995  }
996  else {
997  flipDir = std::signbit(tpFit.Dir[0]) != std::signbit(tj.Pts[originPt].Dir[0]);
998  }
999  if (flipDir) {
1000  tpFit.Dir[0] = -tpFit.Dir[0];
1001  tpFit.Dir[1] = -tpFit.Dir[1];
1002  }
1003  tpFit.Ang = atan2(tpFit.Dir[1], tpFit.Dir[0]);
1004  SetAngleCode(tpFit);
1005 
1006  // rotate (0, intcpt) into (W,T) coordinates
1007  tpFit.Pos[0] = -sn * A + origin[0];
1008  tpFit.Pos[1] = cs * A + origin[1];
1009  // force the origin to be at origin[0]
1010  if (tpFit.AngleCode < 2) MoveTPToWire(tpFit, origin[0]);
1011 
1012  if (x.size() < 3) return;
1013 
1014  // Calculate chisq/DOF
1015  double ndof = x.size() - 2;
1016  double varnce =
1017  (sumy2 + A * A * sum + B * B * sumx2 - 2 * (A * sumy + B * sumxy - A * B * sumx)) / ndof;
1018  if (varnce > 0.) {
1019  // Intercept error is not used
1020  // InterceptError = sqrt(varnce * sumx2 / delta);
1021  double slopeError = sqrt(varnce * sum / delta);
1022  tpFit.AngErr = std::abs(atan(slopeError));
1023  }
1024  else {
1025  tpFit.AngErr = 0.01;
1026  }
1027  sum = 0;
1028  // calculate chisq
1029  double arg;
1030  for (unsigned short ii = 0; ii < y.size(); ++ii) {
1031  arg = y[ii] - A - B * x[ii];
1032  sum += arg * arg / w[ii];
1033  }
1034  tpFit.FitChi = sum / ndof;
1035  } // FitTraj
Float_t x
Definition: compare.C:6
Double_t xx
Definition: macro.C:12
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:2080
Float_t y
Definition: compare.C:6
constexpr auto abs(T v)
Returns the absolute value of the argument.
void SetAngleCode(TrajPoint &tp)
Definition: Utils.cxx:765
std::array< float, 2 > Point2_t
Definition: DataStructs.h:41
Float_t sn
Definition: plot.C:23
TDirectory * dir
Definition: macro.C:5
unsigned short AngleRange(float angle)
Definition: Utils.cxx:784
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2763
Double_t sum
Definition: plot.C:31
Float_t w
Definition: plot.C:20
constexpr Point origin()
Returns a origin position with a point of the specified type.
Definition: geo_vectors.h:229
bool tca::FitVertex ( TCSlice slc,
VtxStore vx,
bool  prt 
)

Definition at line 1943 of file TCVertex.cxx.

References tca::VtxStore::CTP, tca::VtxStore::ID, if(), kFixed, kHaloTj, kKilled, kNoFitVx, kPhoton, tca::VtxStore::Stat, and tca::TCSlice::tjs.

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

1944  {
1945  // Fit the vertex using T -> 2V assns
1946 
1947  // tcc.vtx2DCuts fcl input usage
1948  // 0 = maximum length of a short trajectory
1949  // 1 = max vertex - trajectory separation for short trajectories
1950  // 2 = max vertex - trajectory separation for long trajectories
1951  // 3 = max position pull for adding TJs to a vertex
1952  // 4 = max allowed vertex position error
1953  // 5 = min MCSMom
1954  // 6 = min Pts/Wire fraction
1955 
1956  if (vx.Stat[kFixed]) {
1957  if (prt) mf::LogVerbatim("TC") << " vertex position fixed. No fit allowed";
1958  return true;
1959  }
1960 
1961  // Create a vector of trajectory points that will be used to fit the vertex position
1962  std::vector<TrajPoint> vxTp;
1963  for (auto& tj : slc.tjs) {
1964  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
1965  if (tj.CTP != vx.CTP) continue;
1966  if (tj.AlgMod[kPhoton]) continue;
1967  bool added = false;
1968  if (tj.VtxID[0] == vx.ID && !tj.EndFlag[0][kNoFitVx]) {
1969  vxTp.push_back(tj.Pts[tj.EndPt[0]]);
1970  added = true;
1971  }
1972  if (tj.VtxID[1] == vx.ID && !tj.EndFlag[1][kNoFitVx]) {
1973  vxTp.push_back(tj.Pts[tj.EndPt[1]]);
1974  added = true;
1975  }
1976  // stash the ID in Step to help debugging
1977  if (added) {
1978  auto& tp = vxTp[vxTp.size() - 1];
1979  if (tj.ID > 0) tp.Step = (int)tj.ID;
1980  // inflate the angle errors for Tjs with few fitted points
1981  if (tp.NTPsFit < 4) tp.AngErr *= 4;
1982  }
1983  } // tj
1984 
1985  bool success = FitVertex(slc, vx, vxTp, prt);
1986 
1987  if (!success) return false;
1988  return true;
1989  } // FitVertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
vertex position fixed manually - no fitting done
Definition: DataStructs.h:88
bool FitVertex(TCSlice &slc, VtxStore &vx, std::vector< TrajPoint > &vxTPs, bool prt)
Definition: TCVertex.cxx:1992
if(nlines<=0)
bool tca::FitVertex ( TCSlice slc,
VtxStore vx,
std::vector< TrajPoint > &  vxTPs,
bool  prt 
)

Definition at line 1992 of file TCVertex.cxx.

References tca::VtxStore::ChiDOF, tca::VtxStore::Pos, tca::VtxStore::PosErr, PrintTP(), PrintTPHeader(), and TrajPointVertexPull().

1993  {
1994  // Version with LSQ fit. Each TP position (P0,P1) and slope S are fit to a vertex
1995  // at position (V0, V1), using the equation P1 = V1 + (P0 - V0) * S. This is put
1996  // in the form A * V = b. V is found using V = (A^T * A)^-1 * A^T * b. This is
1997  // usually done using the TDecompSVD Solve method but here we do it step-wise to
1998  // get access to the covariance matrix (A^T * A)^-1. The pull between the TP position
1999  // and the vertex position is stored in tp.Delta
2000 
2001  if (vxTPs.size() < 2) return false;
2002  if (vxTPs.size() == 2) {
2003  vx.ChiDOF = 0.;
2004  return true;
2005  }
2006 
2007  unsigned short npts = vxTPs.size();
2008  TMatrixD A(npts, 2);
2009  TVectorD b(npts);
2010  for (unsigned short itj = 0; itj < vxTPs.size(); ++itj) {
2011  auto& tp = vxTPs[itj];
2012  double dtdw = tp.Dir[1] / tp.Dir[0];
2013  double wt = 1 / (tp.AngErr * tp.AngErr);
2014  A(itj, 0) = -dtdw * wt;
2015  A(itj, 1) = 1. * wt;
2016  b(itj) = (tp.Pos[1] - tp.Pos[0] * dtdw) * wt;
2017  } // itj
2018 
2019  TMatrixD AT(2, npts);
2020  AT.Transpose(A);
2021  TMatrixD ATA = AT * A;
2022  double* det = 0;
2023  try {
2024  ATA.Invert(det);
2025  }
2026  catch (...) {
2027  return false;
2028  }
2029  if (det == NULL) return false;
2030  TVectorD vxPos = ATA * AT * b;
2031  vx.PosErr[0] = sqrt(ATA[0][0]);
2032  vx.PosErr[1] = sqrt(ATA[1][1]);
2033  vx.Pos[0] = vxPos[0];
2034  vx.Pos[1] = vxPos[1];
2035 
2036  // Calculate Chisq
2037  vx.ChiDOF = 0;
2038  if (vxTPs.size() > 2) {
2039  for (auto& tp : vxTPs) {
2040  // highjack TP Delta for the vertex pull
2041  tp.Delta = TrajPointVertexPull(tp, vx);
2042  vx.ChiDOF += tp.Delta;
2043  } // itj
2044  vx.ChiDOF /= (float)(vxTPs.size() - 2);
2045  } // vxTPs.size() > 2
2046 
2047  if (prt) {
2048  mf::LogVerbatim("TC") << "Note: TP - 2V pull is stored in TP.Delta";
2049  PrintTPHeader("FV");
2050  for (auto& tp : vxTPs)
2051  PrintTP("FV", slc, 0, 1, 1, tp);
2052  }
2053 
2054  return true;
2055  } // FitVertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void PrintTP(std::string someText, const TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, const TrajPoint &tp)
Definition: Utils.cxx:6134
float TrajPointVertexPull(const TrajPoint &tp, const VtxStore &vx)
Definition: TCVertex.cxx:1844
void PrintTPHeader(std::string someText)
Definition: Utils.cxx:6126
void tca::FixBegin ( TCSlice slc,
Trajectory tj,
unsigned short  atPt 
)

Definition at line 3013 of file StepUtils.cxx.

References util::abs(), tca::Trajectory::AlgMod, tca::TrajPoint::Ang, tca::TrajPoint::AngErr, tca::TrajPoint::AngleCode, tca::Trajectory::AveChg, tca::TCConfig::chargeCuts, tca::Trajectory::ChgRMS, tca::TCConfig::dbgStp, tca::TrajPoint::Dir, tca::Trajectory::EndPt, kFixBegin, kJunkTj, NumPtsWithCharge(), tca::Trajectory::PDGCode, PointTrajDOCA(), tca::TrajPoint::Pos, PrintEndFlag(), PrintPos(), tca::Trajectory::Pts, SetEndPoints(), tcc, UnsetUsedHits(), tca::TCConfig::useAlg, and tca::Trajectory::VtxID.

Referenced by ChkBegin().

3014  {
3015  // Update the parameters at the beginning of the trajectory starting at point atPt
3016 
3017  if (!tcc.useAlg[kFixBegin]) return;
3018  // ignore short trajectories
3019  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
3020  if (npwc < 6) return;
3021  // ignore shower-like trajectories
3022  if (tj.PDGCode == 11) return;
3023  // ignore junk trajectories
3024  if (tj.AlgMod[kJunkTj]) return;
3025  unsigned short firstPt = tj.EndPt[0];
3026 
3027  if (atPt == tj.EndPt[0]) return;
3028 
3029  // Default is to use DeltaRMS of the last point on the Tj
3030  float maxDelta = 4 * tj.Pts[tj.EndPt[1]].DeltaRMS;
3031 
3032  // Find the max DeltaRMS of points from atPt to EndPt[1]
3033  float maxDeltaRMS = 0;
3034  for (unsigned short ipt = atPt; ipt <= tj.EndPt[1]; ++ipt) {
3035  if (tj.Pts[ipt].DeltaRMS > maxDeltaRMS) maxDeltaRMS = tj.Pts[ipt].DeltaRMS;
3036  } // ipt
3037  maxDelta = 3 * maxDeltaRMS;
3038 
3039  if (tcc.dbgStp) {
3040  mf::LogVerbatim("TC") << "FB: atPt " << atPt << " firstPt " << firstPt << " Stops at end 0? "
3041  << PrintEndFlag(tj, 0) << " start vertex " << tj.VtxID[0]
3042  << " maxDelta " << maxDelta;
3043  }
3044 
3045  // update the trajectory for all the points up to atPt
3046  // assume that we will use all of these points
3047  bool maskedPts = false;
3048  for (unsigned short ii = 1; ii < tj.Pts.size(); ++ii) {
3049  if (ii > atPt) break;
3050  unsigned int ipt = atPt - ii;
3051  TrajPoint& tp = tj.Pts[ipt];
3052  tp.Dir = tj.Pts[atPt].Dir;
3053  tp.Ang = tj.Pts[atPt].Ang;
3054  tp.AngErr = tj.Pts[atPt].AngErr;
3055  tp.AngleCode = tj.Pts[atPt].AngleCode;
3056  // Correct the projected time to the wire
3057  float dw = tp.Pos[0] - tj.Pts[atPt].Pos[0];
3058  if (tp.Dir[0] != 0) tp.Pos[1] = tj.Pts[atPt].Pos[1] + dw * tp.Dir[1] / tp.Dir[0];
3059  tj.Pts[ipt].Delta = PointTrajDOCA(tj.Pts[ipt].HitPos[0], tj.Pts[ipt].HitPos[1], tj.Pts[ipt]);
3060  tj.Pts[ipt].DeltaRMS = tj.Pts[atPt].DeltaRMS;
3061  tj.Pts[ipt].NTPsFit = tj.Pts[atPt].NTPsFit;
3062  tj.Pts[ipt].FitChi = tj.Pts[atPt].FitChi;
3063  tj.Pts[ipt].AveChg = tj.Pts[atPt].AveChg;
3064  tj.Pts[ipt].ChgPull = (tj.Pts[ipt].Chg / tj.AveChg - 1) / tj.ChgRMS;
3065  bool badChg = (std::abs(tj.Pts[ipt].ChgPull) > tcc.chargeCuts[0]);
3066  bool maskThisPt = (tj.Pts[ipt].Delta > maxDelta || badChg);
3067  if (maskThisPt) {
3068  UnsetUsedHits(slc, tp);
3069  maskedPts = true;
3070  }
3071  if (tcc.dbgStp) {
3072  mf::LogVerbatim myprt("TC");
3073  myprt << " Point " << PrintPos(tj.Pts[ipt].Pos) << " Delta " << tj.Pts[ipt].Delta
3074  << " ChgPull " << tj.Pts[ipt].ChgPull << " maskThisPt? " << maskThisPt;
3075  }
3076  if (ipt == 0) break;
3077  } // ii
3078  if (maskedPts) SetEndPoints(tj);
3079  tj.AlgMod[kFixBegin] = true;
3080 
3081  } // FixBegin
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1061
std::string PrintEndFlag(const PFPStruct &pfp, unsigned short end)
Definition: Utils.cxx:6297
constexpr auto abs(T v)
Returns the absolute value of the argument.
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2514
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
std::vector< float > chargeCuts
Definition: DataStructs.h:553
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
void tca::Forecast ( TCSlice slc,
const Trajectory tj 
)

Definition at line 460 of file StepUtils.cxx.

References util::abs(), tca::Trajectory::AveChg, tca::Trajectory::ChgRMS, tca::ParFit::ChiDOF, ChkStop(), tca::Trajectory::CTP, tca::TCConfig::dbgStp, DecodeCTP(), DefineHitPos(), tca::Trajectory::EndFlag, tca::Trajectory::EndPt, evt, FindCloseHits(), tca::TCSlice::firstWire, FitPar(), tca::Trajectory::ID, if(), kAllHits, kBragg, kEnvNearShower, kEnvNotGoodWire, tca::TCSlice::lastWire, tca::Trajectory::MCSMom, MCSMom(), MoveTPToWire(), NumPtsWithCharge(), tca::ParFit::ParSlp, tca::ParFit::ParSlpErr, tca::Trajectory::PDGCode, geo::PlaneID::Plane, PointTrajDOCA(), PrintPos(), tca::Trajectory::Pts, SetEndPoints(), tca::TCConfig::showerTag, tcc, tjfs, tca::Trajectory::TotChg, UpdateTjChgProperties(), and tca::TCEvent::WorkID.

Referenced by StepAway().

461  {
462  // Extrapolate the last TP of tj by many steps and return a forecast of what is ahead
463  // -1 error or not sure
464  // ~1 track-like with a slight chance of showers
465  // >2 shower-like
466  // nextForecastUpdate is set to the number of points on the trajectory when this function should
467  // be called again
468 
469  if (tj.Pts[tj.EndPt[1]].AngleCode == 2) return;
470 
471  // add a new forecast
472  tjfs.resize(tjfs.size() + 1);
473  // assume there is insufficient info to make a decision
474  auto& tjf = tjfs[tjfs.size() - 1];
475  tjf.outlook = -1;
476  tjf.nextForecastUpdate = USHRT_MAX;
477 
478  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
479  unsigned short istp = 0;
480  unsigned short nMissed = 0;
481 
482  bool doPrt = tcc.dbgStp;
483  // turn off annoying output from DefineHitPos
484  if (doPrt) tcc.dbgStp = false;
485  // find the minimum average TP charge. This will be used to calculate the
486  // 'effective number of hits' on a wire = total charge on the wire within the
487  // window / (minimum average TP charge). This is intended to reduce the sensitivity
488  // of this metric to the hit finder configuration
489  float minAveChg = 1E6;
490  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
491  if (tj.Pts[ipt].AveChg <= 0) continue;
492  if (tj.Pts[ipt].AveChg > minAveChg) continue;
493  minAveChg = tj.Pts[ipt].AveChg;
494  } // ipt
495  if (minAveChg <= 0 || minAveChg == 1E6) return;
496  // start a forecast Tj comprised of the points in the forecast envelope
497  Trajectory fctj;
498  fctj.CTP = tj.CTP;
499  fctj.ID = evt.WorkID;
500  // make a local copy of the last point
501  auto ltp = tj.Pts[tj.EndPt[1]];
502  // Use the hits position instead of the fitted position so that a bad
503  // fit doesn't screw up the forecast.
504  float forecastWin0 = std::abs(ltp.Pos[1] - ltp.HitPos[1]);
505  if (forecastWin0 < 1) forecastWin0 = 1;
506  ltp.Pos = ltp.HitPos;
507  double stepSize = std::abs(1 / ltp.Dir[0]);
508  float window = tcc.showerTag[7] * stepSize;
509  if (doPrt) {
510  mf::LogVerbatim("TC") << "Forecast T" << tj.ID << " PDGCode " << tj.PDGCode << " npwc "
511  << npwc << " minAveChg " << (int)minAveChg << " stepSize "
512  << std::setprecision(2) << stepSize << " window " << window;
513  mf::LogVerbatim("TC")
514  << " stp ___Pos____ nTPH Chg ChgPull Delta DRMS chgWid nTkLk nShLk";
515  }
516  unsigned short plane = DecodeCTP(ltp.CTP).Plane;
517  fctj.TotChg = 0;
518  float maxChg = 0;
519  unsigned short maxChgPt = 0;
520  unsigned short leavesNear = USHRT_MAX;
521  bool leavesBeforeEnd = false;
522  unsigned short showerStartNear = USHRT_MAX;
523  unsigned short showerEndNear = USHRT_MAX;
524  float nShLike = 0;
525  float nTkLike = 0;
526  unsigned short trimPts = 0;
527  for (istp = 0; istp < 1000; ++istp) {
528  // move the local TP position by one step in the right direction
529  for (unsigned short iwt = 0; iwt < 2; ++iwt)
530  ltp.Pos[iwt] += ltp.Dir[iwt] * stepSize;
531  unsigned int wire = std::nearbyint(ltp.Pos[0]);
532  if (wire < slc.firstWire[plane]) break;
533  if (wire > slc.lastWire[plane] - 1) break;
534  MoveTPToWire(ltp, (float)wire);
535  ++ltp.Step;
536  if (FindCloseHits(slc, ltp, window, kAllHits)) {
537  // Found hits or the wire is dead
538  // set all hits used so that we can use DefineHitPos. Note that
539  // the hit InTraj is not used or tested in DefineHitPos so this doesn't
540  // screw up any assns
541  if (!ltp.Environment[kEnvNotGoodWire]) {
542  nMissed = 0;
543  ltp.UseHit.set();
544  DefineHitPos(slc, ltp);
545  fctj.TotChg += ltp.Chg;
546  ltp.Delta = PointTrajDOCA(ltp.HitPos[0], ltp.HitPos[1], ltp);
547  ltp.DeltaRMS = ltp.Delta / window;
548  ltp.Environment.reset();
549  if (ltp.Chg > maxChg) {
550  maxChg = ltp.Chg;
551  maxChgPt = fctj.Pts.size();
552  }
553  // Note that ChgPull uses the average charge and charge RMS of the
554  // trajectory before it entered the forecast envelope
555  ltp.ChgPull = (ltp.Chg / minAveChg - 1) / tj.ChgRMS;
556  if ((ltp.ChgPull > 3 && ltp.Hits.size() > 1) || ltp.ChgPull > 10) {
557  ++nShLike;
558  // break if it approaches the side of the envelope
559  ltp.Environment[kEnvNearShower] = true;
560  // flag a showerlike TP so it isn't used in the MCSMom calculation
561  ltp.HitPosErr2 = 100;
562  }
563  else {
564  ++nTkLike;
565  ltp.Environment[kEnvNearShower] = false;
566  }
567  if (fctj.Pts.size() > 10) {
568  float shFrac = nShLike / (nShLike + nTkLike);
569  if (shFrac > 0.5) {
570  if (doPrt) mf::LogVerbatim("TC") << "Getting showerlike - break";
571  break;
572  }
573  } // fctj.Pts.size() > 6
574  // break if it approaches the side of the envelope
575  if (ltp.DeltaRMS > 0.8) {
576  leavesNear = npwc + fctj.Pts.size();
577  if (doPrt) mf::LogVerbatim("TC") << "leaves before end - break";
578  leavesBeforeEnd = true;
579  break;
580  }
581  fctj.Pts.push_back(ltp);
582  if (doPrt) {
583  mf::LogVerbatim myprt("TC");
584  myprt << std::setw(4) << npwc + fctj.Pts.size() << " " << PrintPos(ltp);
585  myprt << std::setw(5) << ltp.Hits.size();
586  myprt << std::setw(5) << (int)ltp.Chg;
587  myprt << std::fixed << std::setprecision(1);
588  myprt << std::setw(8) << ltp.ChgPull;
589  myprt << std::setw(8) << ltp.Delta;
590  myprt << std::setw(8) << std::setprecision(2) << ltp.DeltaRMS;
591  myprt << std::setw(8) << sqrt(ltp.HitPosErr2);
592  myprt << std::setw(6) << (int)nTkLike;
593  myprt << std::setw(6) << (int)nShLike;
594  } // doPrt
595  }
596  }
597  else {
598  // no hits found
599  ++nMissed;
600  if (nMissed == 10) {
601  if (doPrt) mf::LogVerbatim("TC") << "No hits found after 10 steps - break";
602  break;
603  }
604  } // no hits found
605  } // istp
606  // not enuf info to make a forecast
607  tcc.dbgStp = doPrt;
608  if (fctj.Pts.size() < 3) return;
609  // truncate and re-calculate totChg?
610  if (trimPts > 0) {
611  // truncate the forecast trajectory
612  fctj.Pts.resize(fctj.Pts.size() - trimPts);
613  // recalculate the total charge
614  fctj.TotChg = 0;
615  for (auto& tp : fctj.Pts)
616  fctj.TotChg += tp.Chg;
617  } // showerEndNear != USHRT_MAX
618  SetEndPoints(fctj);
619  fctj.MCSMom = MCSMom(slc, fctj);
620  tjf.MCSMom = fctj.MCSMom;
621  ParFit chgFit;
622  if (maxChgPt > 0.3 * fctj.Pts.size() && maxChg > 3 * tj.AveChg) {
623  // find the charge slope from the beginning to the maxChgPt if it is well away
624  // from the start and it is very large
625  FitPar(fctj, 0, maxChgPt, 1, chgFit, 1);
626  }
627  else {
628  FitPar(fctj, 0, fctj.Pts.size(), 1, chgFit, 1);
629  }
630  tjf.chgSlope = chgFit.ParSlp;
631  tjf.chgSlopeErr = chgFit.ParSlpErr;
632  tjf.chgFitChiDOF = chgFit.ChiDOF;
633  ChkStop(fctj);
634  UpdateTjChgProperties("Fc", slc, fctj, false);
635  tjf.chgRMS = fctj.ChgRMS;
636  tjf.endBraggPeak = fctj.EndFlag[1][kBragg];
637  // Set outlook = Estimate of the number of hits per wire
638  tjf.outlook = fctj.TotChg / (fctj.Pts.size() * tj.AveChg);
639  // assume we got to the end
640  tjf.nextForecastUpdate = npwc + fctj.Pts.size();
641  tjf.leavesBeforeEnd = leavesBeforeEnd;
642  tjf.foundShower = false;
643  if (leavesNear < tjf.nextForecastUpdate) {
644  // left the side
645  tjf.nextForecastUpdate = leavesNear;
646  }
647  else if (showerStartNear < tjf.nextForecastUpdate) {
648  // found a shower start
649  tjf.nextForecastUpdate = showerStartNear;
650  tjf.foundShower = true;
651  }
652  else if (showerEndNear < tjf.nextForecastUpdate) {
653  // found a shower end
654  tjf.nextForecastUpdate = showerEndNear;
655  }
656  nShLike = 0;
657  for (auto& tp : fctj.Pts)
658  if (tp.Environment[kEnvNearShower]) ++nShLike;
659  tjf.showerLikeFraction = (float)nShLike / (float)fctj.Pts.size();
660 
661  if (doPrt) {
662  mf::LogVerbatim myprt("TC");
663  myprt << "Forecast T" << tj.ID << " tj.AveChg " << (int)tj.AveChg;
664  myprt << " start " << PrintPos(tj.Pts[tj.EndPt[1]]) << " cnt " << fctj.Pts.size()
665  << " totChg " << (int)fctj.TotChg;
666  myprt << " last pos " << PrintPos(ltp);
667  myprt << " MCSMom " << tjf.MCSMom;
668  myprt << " outlook " << std::fixed << std::setprecision(2) << tjf.outlook;
669  myprt << " chgSlope " << std::setprecision(1) << tjf.chgSlope << " +/- " << tjf.chgSlopeErr;
670  myprt << " chgRMS " << std::setprecision(1) << tjf.chgRMS;
671  myprt << " endBraggPeak " << tjf.endBraggPeak;
672  myprt << " chiDOF " << tjf.chgFitChiDOF;
673  myprt << " showerLike fraction " << tjf.showerLikeFraction;
674  myprt << " nextForecastUpdate " << tjf.nextForecastUpdate;
675  myprt << " leavesBeforeEnd? " << tjf.leavesBeforeEnd;
676  myprt << " foundShower? " << tjf.foundShower;
677  }
678 
679  } // Forecast
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3381
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void ChkStop(Trajectory &tj)
Definition: StepUtils.cxx:3972
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
TCConfig tcc
Definition: DataStructs.cxx:9
constexpr auto abs(T v)
Returns the absolute value of the argument.
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2514
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:549
void FitPar(const Trajectory &tj, unsigned short originPt, unsigned short npts, short fitDir, ParFit &pFit, unsigned short usePar)
Definition: Utils.cxx:1202
if(nlines<=0)
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1791
std::vector< unsigned int > FindCloseHits(const 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:2774
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice const &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3577
std::vector< TjForecast > tjfs
Definition: DataStructs.cxx:10
geo::PlaneID DecodeCTP(CTP_t CTP)
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2763
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
TCEvent evt
Definition: DataStructs.cxx:8
std::vector< int > tca::GetAssns ( TCSlice const &  slc,
std::string  type1Name,
int  id,
std::string  type2Name 
)

Definition at line 4704 of file Utils.cxx.

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

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

4708  {
4709  // returns a list of IDs of objects (slc, vertices, pfps, etc) with type1Name that are in slc with
4710  // type2Name. This is intended to be a general purpose replacement for specific functions like GetVtxTjIDs, etc
4711 
4712  std::vector<int> tmp;
4713  if (id <= 0) return tmp;
4714  unsigned int uid = id;
4715 
4716  if (type1Name == "T" && uid <= slc.tjs.size() && type2Name == "P") {
4717  // return a list of PFPs that have the tj in TjIDs, P -> T<ID>
4718  for (auto& pfp : slc.pfps) {
4719  if (pfp.ID <= 0) continue;
4720  if (std::find(pfp.TjIDs.begin(), pfp.TjIDs.end(), id) != pfp.TjIDs.end())
4721  tmp.push_back(pfp.ID);
4722  } // pf
4723  return tmp;
4724  } // P -> T
4725 
4726  if (type1Name == "P" && uid <= slc.pfps.size() && (type2Name == "2S" || type2Name == "3S")) {
4727  // return a list of 3D or 2D showers with the assn 3S -> 2S -> T -> P<ID> or 2S -> T -> P.
4728  auto& pfp = slc.pfps[uid - 1];
4729  // First form a list of 2S -> T -> P<ID>
4730  std::vector<int> ssid;
4731  for (auto& ss : slc.cots) {
4732  if (ss.ID <= 0) continue;
4733  auto shared = SetIntersection(ss.TjIDs, pfp.TjIDs);
4734  if (!shared.empty() && std::find(ssid.begin(), ssid.end(), ss.ID) == ssid.end())
4735  ssid.push_back(ss.ID);
4736  } // ss
4737  if (type2Name == "2S") return ssid;
4738  for (auto& ss3 : slc.showers) {
4739  if (ss3.ID <= 0) continue;
4740  auto shared = SetIntersection(ss3.CotIDs, ssid);
4741  if (!shared.empty() && std::find(tmp.begin(), tmp.end(), ss3.ID) == tmp.end())
4742  tmp.push_back(ss3.ID);
4743  } // ss3
4744  return tmp;
4745  } // 3S -> 2S -> T -> P
4746 
4747  if (type1Name == "2V" && uid <= slc.vtxs.size() && type2Name == "T") {
4748  // 2V -> T
4749  for (auto& tj : slc.tjs) {
4750  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
4751  for (unsigned short end = 0; end < 2; ++end) {
4752  if (tj.VtxID[end] != id) continue;
4753  if (std::find(tmp.begin(), tmp.end(), tj.ID) == tmp.end()) tmp.push_back(tj.ID);
4754  } // end
4755  } // tj
4756  return tmp;
4757  } // 2V -> T
4758 
4759  if (type1Name == "3V" && uid <= slc.vtx3s.size() && type2Name == "P") {
4760  for (auto& pfp : slc.pfps) {
4761  if (pfp.ID == 0) continue;
4762  for (unsigned short end = 0; end < 2; ++end) {
4763  if (pfp.Vx3ID[end] != id) continue;
4764  // encode the end with the ID
4765  if (std::find(tmp.begin(), tmp.end(), pfp.ID) == tmp.end()) tmp.push_back(pfp.ID);
4766  } // end
4767  } // pfp
4768  return tmp;
4769  } // 3V -> P
4770 
4771  if (type1Name == "3V" && uid <= slc.vtx3s.size() && type2Name == "T") {
4772  // 3V -> T
4773  for (auto& tj : slc.tjs) {
4774  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
4775  for (unsigned short end = 0; end < 2; ++end) {
4776  if (tj.VtxID[end] > 0 && tj.VtxID[end] <= slc.vtxs.size()) {
4777  auto& vx2 = slc.vtxs[tj.VtxID[end] - 1];
4778  if (vx2.Vx3ID != id) continue;
4779  if (std::find(tmp.begin(), tmp.end(), tj.ID) == tmp.end()) tmp.push_back(tj.ID);
4780  }
4781  } // end
4782  } // tj
4783  return tmp;
4784  } // 3V -> T
4785 
4786  if (type1Name == "3V" && uid <= slc.vtx3s.size() && type2Name == "2V") {
4787  // 3V -> 2V
4788  for (auto& vx2 : slc.vtxs) {
4789  if (vx2.ID == 0) continue;
4790  if (vx2.Vx3ID == id) tmp.push_back(vx2.ID);
4791  } // vx2
4792  return tmp;
4793  } // 3V -> 2V
4794 
4795  if (type1Name == "3S" && uid <= slc.showers.size() && type2Name == "T") {
4796  // 3S -> T
4797  auto& ss3 = slc.showers[uid - 1];
4798  if (ss3.ID == 0) return tmp;
4799  for (auto cid : ss3.CotIDs) {
4800  auto& ss = slc.cots[cid - 1];
4801  if (ss.ID == 0) continue;
4802  tmp.insert(tmp.end(), ss.TjIDs.begin(), ss.TjIDs.end());
4803  } // cid
4804  return tmp;
4805  } // 3S -> T
4806 
4807  // This isn't strictly necessary but do it for consistency
4808  if (type1Name == "2S" && uid <= slc.cots.size() && type2Name == "T") {
4809  // 2S -> T
4810  auto& ss = slc.cots[uid - 1];
4811  return ss.TjIDs;
4812  } // 2S -> T
4813 
4814  if (type1Name == "3S" && uid <= slc.showers.size() && type2Name == "P") {
4815  // 3S -> P
4816  auto& ss3 = slc.showers[uid - 1];
4817  if (ss3.ID == 0) return tmp;
4818  for (auto cid : ss3.CotIDs) {
4819  auto& ss = slc.cots[cid - 1];
4820  if (ss.ID == 0) continue;
4821  for (auto tid : ss.TjIDs) {
4822  auto& tj = slc.tjs[tid - 1];
4823  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
4824  if (!tj.AlgMod[kMat3D]) continue;
4825  for (auto& pfp : slc.pfps) {
4826  if (pfp.ID <= 0) continue;
4827  if (std::find(pfp.TjIDs.begin(), pfp.TjIDs.end(), tj.ID) == pfp.TjIDs.end()) continue;
4828  if (std::find(tmp.begin(), tmp.end(), pfp.ID) == tmp.end()) tmp.push_back(pfp.ID);
4829  } // pf
4830  } // tid
4831  } // cid
4832  return tmp;
4833  } // 3S -> P
4834 
4835  if (type1Name == "T" && uid <= slc.tjs.size() && type2Name == "2S") {
4836  // T -> 2S
4837  for (auto& ss : slc.cots) {
4838  if (ss.ID == 0) continue;
4839  if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), id) != ss.TjIDs.end()) tmp.push_back(ss.ID);
4840  } // ss
4841  return tmp;
4842  } // T -> 2S
4843 
4844  if (type1Name == "T" && uid <= slc.tjs.size() && type2Name == "3S") {
4845  // T -> 3S
4846  for (auto& ss : slc.cots) {
4847  if (ss.ID == 0) continue;
4848  if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), id) == ss.TjIDs.end()) continue;
4849  if (ss.SS3ID > 0) tmp.push_back(ss.SS3ID);
4850  } // ss
4851  return tmp;
4852  } // T -> 3S
4853 
4854  return tmp;
4855  } // GetAssns
Float_t tmp
Definition: plot.C:35
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:385
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
int tca::GetCotID ( TCSlice slc,
int  ShowerTjID 
)

Definition at line 3889 of file TCShower.cxx.

References tca::TCSlice::cots.

Referenced by MergeShowerTjsAndStore().

3890  {
3891  for (unsigned short ii = 0; ii < slc.cots.size(); ++ii) {
3892  if (ShowerTjID == slc.cots[ii].ShowerTjID) return ii + 1;
3893  } // iii
3894  return 0;
3895 
3896  } // GetCotID
void tca::GetHitMultiplet ( const TCSlice slc,
unsigned int  theHit,
std::vector< unsigned int > &  hitsInMultiplet,
bool  useLongPulseHits 
)

Definition at line 1521 of file StepUtils.cxx.

References util::abs(), tca::TCEvent::allHits, tca::TCEvent::aveHitRMS, evt, if(), LongPulseHit(), tca::TCConfig::multHitSep, tca::TCSlice::slHits, tcc, and tmp.

Referenced by AddHits(), CreateTP3D(), tca::TrajClusterAlg::FindJunkTraj(), FindUseHits(), IsGhost(), and tca::TrajClusterAlg::ReconstructAllTraj().

1525  {
1526  // This function attempts to return a list of hits in the current slice that are close to the
1527  // hit specified by theHit and that are similar to it. If theHit is a high-pulseheight hit (aka imTall)
1528  // and has an RMS similar to a hit on a small angle trajectory (aka Narrow) and is embedded in a series of
1529  // nearby low-pulseheight wide hits, the hit multiplet will consist of the single Tall and Narrow hit. On the
1530  // other hand, if theHit references a short and not-narrow hit, all of the hits in the series of nearby
1531  // hits will be returned. The localIndex is the index of theHit in hitsInMultiplet and shouldn't be
1532  // confused with the recob::Hit LocalIndex
1533  hitsInMultiplet.clear();
1534  // check for flagrant errors
1535  if (theHit >= slc.slHits.size()) return;
1536  if (slc.slHits[theHit].InTraj == INT_MAX) return;
1537  if (slc.slHits[theHit].allHitsIndex >= (*evt.allHits).size()) return;
1538 
1539  auto& hit = (*evt.allHits)[slc.slHits[theHit].allHitsIndex];
1540  // handle long-pulse hits
1541  if (useLongPulseHits && LongPulseHit(hit)) {
1542  // return everything in the multiplet as defined by the hit finder, but check for errors
1543  short int hitMult = hit.Multiplicity();
1544  unsigned int lIndex = hit.LocalIndex();
1545  unsigned int firstHit = 0;
1546  if (lIndex < theHit) firstHit = theHit - lIndex;
1547  for (unsigned int ii = firstHit; ii < firstHit + hitMult; ++ii) {
1548  if (ii >= slc.slHits.size()) break;
1549  auto& tmp = (*evt.allHits)[slc.slHits[ii].allHitsIndex];
1550  if (tmp.Multiplicity() == hitMult) hitsInMultiplet.push_back(ii);
1551  } // ii
1552  return;
1553  } // LongPulseHit
1554 
1555  hitsInMultiplet.resize(1);
1556  hitsInMultiplet[0] = theHit;
1557  unsigned int theWire = hit.WireID().Wire;
1558  unsigned short ipl = hit.WireID().Plane;
1559 
1560  float theTime = hit.PeakTime();
1561  float theRMS = hit.RMS();
1562  float narrowHitCut = 1.5 * evt.aveHitRMS[ipl];
1563  bool theHitIsNarrow = (theRMS < narrowHitCut);
1564  float maxPeak = hit.PeakAmplitude();
1565  unsigned int imTall = theHit;
1566  unsigned short nNarrow = 0;
1567  if (theHitIsNarrow) nNarrow = 1;
1568  // look for hits < theTime but within hitSep
1569  if (theHit > 0) {
1570  for (unsigned int iht = theHit - 1; iht != 0; --iht) {
1571  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1572  if (hit.WireID().Wire != theWire) break;
1573  if (hit.WireID().Plane != ipl) break;
1574  float hitSep = tcc.multHitSep * theRMS;
1575  float rms = hit.RMS();
1576  if (rms > theRMS) {
1577  hitSep = tcc.multHitSep * rms;
1578  theRMS = rms;
1579  }
1580  float dTick = std::abs(hit.PeakTime() - theTime);
1581  if (dTick > hitSep) break;
1582  hitsInMultiplet.push_back(iht);
1583  if (rms < narrowHitCut) ++nNarrow;
1584  float peakAmp = hit.PeakAmplitude();
1585  if (peakAmp > maxPeak) {
1586  maxPeak = peakAmp;
1587  imTall = iht;
1588  }
1589  theTime = hit.PeakTime();
1590  if (iht == 0) break;
1591  } // iht
1592  } // iht > 0
1593  // reverse the order so that hitsInMuliplet will be
1594  // returned in increasing time order
1595  if (hitsInMultiplet.size() > 1) std::reverse(hitsInMultiplet.begin(), hitsInMultiplet.end());
1596  // look for hits > theTime but within hitSep
1597  theTime = hit.PeakTime();
1598  theRMS = hit.RMS();
1599  for (unsigned int iht = theHit + 1; iht < slc.slHits.size(); ++iht) {
1600  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1601  if (hit.WireID().Wire != theWire) break;
1602  if (hit.WireID().Plane != ipl) break;
1603  if (slc.slHits[iht].InTraj == INT_MAX) continue;
1604  float hitSep = tcc.multHitSep * theRMS;
1605  float rms = hit.RMS();
1606  if (rms > theRMS) {
1607  hitSep = tcc.multHitSep * rms;
1608  theRMS = rms;
1609  }
1610  float dTick = std::abs(hit.PeakTime() - theTime);
1611  if (dTick > hitSep) break;
1612  hitsInMultiplet.push_back(iht);
1613  if (rms < narrowHitCut) ++nNarrow;
1614  float peakAmp = hit.PeakAmplitude();
1615  if (peakAmp > maxPeak) {
1616  maxPeak = peakAmp;
1617  imTall = iht;
1618  }
1619  theTime = hit.PeakTime();
1620  } // iht
1621  if (hitsInMultiplet.size() == 1) return;
1622 
1623  // Don't make a multiplet that includes a tall narrow hit with short fat hits
1624  if (nNarrow == hitsInMultiplet.size()) return;
1625  if (nNarrow == 0) return;
1626 
1627  if (theHitIsNarrow && theHit == imTall) {
1628  // theHit is narrow and it is the highest amplitude hit in the multiplet. Ignore any
1629  // others that are short and fat
1630  auto tmp = hitsInMultiplet;
1631  tmp.resize(1);
1632  tmp[0] = theHit;
1633  hitsInMultiplet = tmp;
1634  }
1635  else {
1636  // theHit is not narrow and it is not the tallest. Ignore a single hit if it is
1637  // the tallest and narrow
1638  auto& hit = (*evt.allHits)[slc.slHits[imTall].allHitsIndex];
1639  if (hit.RMS() < narrowHitCut) {
1640  unsigned short killMe = 0;
1641  for (unsigned short ii = 0; ii < hitsInMultiplet.size(); ++ii) {
1642  if (hitsInMultiplet[ii] == imTall) {
1643  killMe = ii;
1644  break;
1645  }
1646  } // ii
1647  hitsInMultiplet.erase(hitsInMultiplet.begin() + killMe);
1648  } // slc.slHits[imTall].RMS < narrowHitCut
1649  } // narrow / tall test
1650 
1651  } // GetHitMultiplet
TCConfig tcc
Definition: DataStructs.cxx:9
constexpr auto abs(T v)
Returns the absolute value of the argument.
Float_t tmp
Definition: plot.C:35
bool LongPulseHit(const recob::Hit &hit)
Definition: Utils.cxx:4317
if(nlines<=0)
std::vector< float > aveHitRMS
average RMS of an isolated hit
Definition: DataStructs.h:630
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
float multHitSep
preferentially "merge" hits with < this separation
Definition: DataStructs.h:565
TCEvent evt
Definition: DataStructs.cxx:8
int tca::GetOrigin ( detinfo::DetectorClocksData const &  clockData,
TCSlice slc,
PFPStruct pfp 
)

Definition at line 68 of file TCCR.cxx.

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

Referenced by SaveCRInfo().

69  {
72 
73  std::map<int, float> omap; //<origin, energy>
74 
75  for (auto& tjID : pfp.TjIDs) {
76  Trajectory& tj = slc.tjs[tjID - 1];
77  for (auto& tp : tj.Pts) {
78  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
79  if (!tp.UseHit[ii]) continue;
80  unsigned int iht = tp.Hits[ii];
81  TCHit& slhit = slc.slHits[iht];
82  auto& hit = (*evt.allHits)[slhit.allHitsIndex];
84  double startTick = hit.PeakTime() - hit.RMS();
85  double endTick = hit.PeakTime() + hit.RMS();
86  // get a list of track IDEs that are close to this hit
87  std::vector<sim::TrackIDE> tides;
88  tides = bt_serv->ChannelToTrackIDEs(clockData, channel, startTick, endTick);
89  for (auto itide = tides.begin(); itide != tides.end(); ++itide) {
90  omap[pi_serv->TrackIdToMCTruth_P(itide->trackID)->Origin()] += itide->energy;
91  }
92  }
93  }
94  }
95 
96  float maxe = -1;
97  int origin = 0;
98  for (auto& i : omap) {
99  if (i.second > maxe) {
100  maxe = i.second;
101  origin = i.first;
102  }
103  }
104  return origin;
105  }
const geo::WireReadoutGeom * wireReadoutGeom
Definition: DataStructs.h:568
TCConfig tcc
Definition: DataStructs.cxx:9
simb::Origin_t Origin() const
Definition: MCTruth.h:74
const art::Ptr< simb::MCTruth > & TrackIdToMCTruth_P(int id) const
virtual raw::ChannelID_t PlaneWireToChannel(WireID const &wireID) const =0
Returns the channel ID a wire is connected to.
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
constexpr Point origin()
Returns a origin position with a point of the specified type.
Definition: geo_vectors.h:229
std::vector< sim::TrackIDE > ChannelToTrackIDEs(detinfo::DetectorClocksData const &clockData, raw::ChannelID_t channel, const double hit_start_time, const double hit_end_time) const
unsigned short tca::GetPFPIndex ( const TCSlice slc,
int  tjID 
)

Definition at line 1038 of file Utils.cxx.

References tca::TCSlice::pfps.

Referenced by MakeHaloTj(), and MergeAndStore().

1039  {
1040  if (slc.pfps.empty()) return USHRT_MAX;
1041  for (unsigned int ipfp = 0; ipfp < slc.pfps.size(); ++ipfp) {
1042  const auto& pfp = slc.pfps[ipfp];
1043  if (std::find(pfp.TjIDs.begin(), pfp.TjIDs.end(), tjID) != pfp.TjIDs.end()) return ipfp;
1044  } // indx
1045  return USHRT_MAX;
1046  } // GetPFPIndex
void tca::GetRange ( const PFPStruct pfp,
unsigned short  sfIndex,
unsigned short &  fromPt,
unsigned short &  npts 
)

Definition at line 1370 of file PFPUtils.cxx.

References tca::PFPStruct::SectionFits, and tca::PFPStruct::TP3Ds.

Referenced by export_G4UIcommand(), and FitSection().

1374  {
1375  fromPt = USHRT_MAX;
1376  if (sfIndex >= pfp.SectionFits.size()) return;
1377  if (pfp.TP3Ds.empty()) return;
1378  fromPt = USHRT_MAX;
1379  npts = 0;
1380  // Note that no test is made for not-good TP3Ds here since that would give a wrong npts count
1381  for (std::size_t ipt = 0; ipt < pfp.TP3Ds.size(); ++ipt) {
1382  auto& tp3d = pfp.TP3Ds[ipt];
1383  if (tp3d.SFIndex < sfIndex) continue;
1384  if (tp3d.SFIndex > sfIndex) break;
1385  if (fromPt == USHRT_MAX) fromPt = ipt;
1386  ++npts;
1387  } // ipt
1388  } // GetRange
std::pair< unsigned short, unsigned short > tca::GetSliceIndex ( std::string  typeName,
int  uID 
)

Definition at line 4942 of file Utils.cxx.

References slices.

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

4943  {
4944  // returns the slice index and product index of a data product having typeName and unique ID uID
4945  for (unsigned short isl = 0; isl < slices.size(); ++isl) {
4946  auto& slc = slices[isl];
4947  if (typeName == "T") {
4948  for (unsigned short indx = 0; indx < slc.tjs.size(); ++indx) {
4949  if (slc.tjs[indx].UID == uID) { return std::make_pair(isl, indx); }
4950  }
4951  } // T
4952  if (typeName == "P") {
4953  for (unsigned short indx = 0; indx < slc.pfps.size(); ++indx) {
4954  if (slc.pfps[indx].UID == uID) { return std::make_pair(isl, indx); }
4955  }
4956  } // P
4957  if (typeName == "2V") {
4958  for (unsigned short indx = 0; indx < slc.vtxs.size(); ++indx) {
4959  if (slc.vtxs[indx].UID == uID) { return std::make_pair(isl, indx); }
4960  }
4961  } // 2V
4962  if (typeName == "3V") {
4963  for (unsigned short indx = 0; indx < slc.vtx3s.size(); ++indx) {
4964  if (slc.vtx3s[indx].UID == uID) { return std::make_pair(isl, indx); }
4965  }
4966  } // 3V
4967  if (typeName == "2S") {
4968  for (unsigned short indx = 0; indx < slc.cots.size(); ++indx) {
4969  if (slc.cots[indx].UID == uID) { return std::make_pair(isl, indx); }
4970  }
4971  } // 2S
4972  if (typeName == "3S") {
4973  for (unsigned short indx = 0; indx < slc.showers.size(); ++indx) {
4974  if (slc.showers[indx].UID == uID) { return std::make_pair(isl, indx); }
4975  }
4976  } // T
4977  } // isl
4978  return std::make_pair(USHRT_MAX, USHRT_MAX);
4979  } // GetSliceIndex
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
int tca::GetStageNum ( ShowerTreeVars stv,
std::string  stageName 
)

Definition at line 200 of file TCShTree.cxx.

References tca::ShowerTreeVars::StageName.

Referenced by SaveTjInfo().

201  {
202  int stageNum;
203  bool existingStage = false;
204  for (unsigned short i = 0; i < stv.StageName.size(); ++i) {
205  if (stv.StageName.at(i) == stageName) {
206  existingStage = true;
207  stageNum = i + 1;
208  }
209  }
210 
211  if (!existingStage) {
212  stv.StageName.push_back(stageName);
213  stageNum = stv.StageName.size();
214  }
215 
216  return stageNum;
217  }
ShowerTreeVars stv
Definition: DataStructs.cxx:11
std::vector< std::string > StageName
Definition: DataStructs.h:397
std::vector< int > tca::GetVtxTjIDs ( const TCSlice slc,
const VtxStore vx2 
)

Definition at line 2807 of file TCVertex.cxx.

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

Referenced by DefineTjParents(), GetVtxTjIDs(), MergeWithVertex(), SetHighScoreBits(), SetVx2Score(), and SplitTrajCrossingVertices().

2808  {
2809  // returns a list of trajectory IDs that are attached to vx2
2810  std::vector<int> tmp;
2811  if (vx2.ID == 0) return tmp;
2812  for (auto& tj : slc.tjs) {
2813  if (tj.AlgMod[kKilled]) continue;
2814  if (tj.CTP != vx2.CTP) continue;
2815  for (unsigned short end = 0; end < 2; ++end) {
2816  if (tj.VtxID[end] == vx2.ID) tmp.push_back(tj.ID);
2817  } // end
2818  } // tj
2819  return tmp;
2820  } // GetVtxTjIDs
Float_t tmp
Definition: plot.C:35
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
std::vector< int > tca::GetVtxTjIDs ( const TCSlice slc,
const Vtx3Store vx3,
float &  score 
)

Definition at line 2823 of file TCVertex.cxx.

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

2824  {
2825  // returns a list of Tjs in all planes that are attached to vx3
2826  std::vector<int> tmp;
2827  if (vx3.ID == 0) return tmp;
2828  float nvx2 = 0;
2829  score = 0;
2830  for (auto& vx2 : slc.vtxs) {
2831  if (vx2.ID == 0) continue;
2832  if (vx2.Vx3ID != vx3.ID) continue;
2833  auto vtxTjID2 = GetVtxTjIDs(slc, vx2);
2834  tmp.insert(tmp.end(), vtxTjID2.begin(), vtxTjID2.end());
2835  score += vx2.Score;
2836  ++nvx2;
2837  } // vx2
2838  if (nvx2 < 1) return tmp;
2839  // find the average score
2840  score /= nvx2;
2841  // sort by increasing ID
2842  std::sort(tmp.begin(), tmp.end());
2843  return tmp;
2844  } // GetVtxTjIDs
Float_t tmp
Definition: plot.C:35
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:2823
bool tca::GottaKink ( TCSlice slc,
Trajectory tj,
bool  doTrim 
)

Definition at line 2756 of file StepUtils.cxx.

References util::abs(), tca::TCConfig::dbgStp, tca::Trajectory::EndFlag, tca::Trajectory::EndPt, kAtKink, tca::TCConfig::kinkCuts, KinkSignificance(), kSlowing, kStiffEl, kStiffMu, NumPtsWithCharge(), PrintPos(), tca::Trajectory::Pts, SetEndPoints(), tca::Trajectory::Strategy, tcc, and UnsetUsedHits().

Referenced by CheckHiMultUnusedHits(), and StepAway().

2757  {
2758  // This function returns true if it detects a kink in the trajectory
2759  // This function trims the points after a kink if one is found if doTrim is true.
2760 
2761  // tcc.kinkCuts[] fcl configuration
2762  // 0 = Number of TPs to fit at the end
2763  // 1 = Min kink significance
2764  // 2 = Use charge in significance calculation if > 0
2765  // 3 = 3D kink fit length (cm) - used in PFPUtils/SplitAtKinks
2766 
2767  // don't look for kinks if this looks a high energy electron
2768  // BB Jan 2, 2020: Return true if a kink was found but don't set the
2769  // stop-at-kink end flag
2770  if (tj.Strategy[kStiffEl]) return false;
2771  // Need at least 2 * kinkCuts[2] points with charge to find a kink
2772  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
2773  unsigned short nPtsFit = tcc.kinkCuts[0];
2774  // Set nPtsFit for slowing tjs to the last TP NTPsFit
2775  if (tj.Strategy[kSlowing]) nPtsFit = tj.Pts[tj.EndPt[1]].NTPsFit;
2776  if (npwc < 2 * nPtsFit) return false;
2777 
2778  bool useCharge = (tcc.kinkCuts[2] > 0);
2779 
2780  // find the point where a kink is expected and fit the points after that point
2781  unsigned short fitPt = USHRT_MAX;
2782  unsigned short cnt = 0;
2783  for (unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
2784  unsigned short ipt = tj.EndPt[1] - ii - 1;
2785  // stay away from the starting points which may be skewed if this is a
2786  // stopping track
2787  if (ipt <= tj.EndPt[0] + 2) break;
2788  if (tj.Pts[ipt].Chg <= 0) continue;
2789  ++cnt;
2790  // Note that the fitPt is not included in the fits in the kink significance so we need
2791  // one more point
2792  if (cnt > nPtsFit) {
2793  fitPt = ipt;
2794  break;
2795  }
2796  } // ii
2797  if (fitPt == USHRT_MAX) {
2798  if (tcc.dbgStp) {
2799  mf::LogVerbatim myprt("TC");
2800  myprt << "GKv2 fitPt not valid. Counted " << cnt << " points. Need " << nPtsFit;
2801  } // tcc.dbgStp
2802  return false;
2803  }
2804 
2805  tj.Pts[fitPt].KinkSig = KinkSignificance(slc, tj, fitPt, nPtsFit, useCharge, tcc.dbgStp);
2806 
2807  bool thisPtHasKink = (tj.Pts[fitPt].KinkSig > tcc.kinkCuts[1]);
2808  bool prevPtHasKink = (tj.Pts[fitPt - 1].KinkSig > tcc.kinkCuts[1]);
2809  if (tcc.dbgStp) {
2810  mf::LogVerbatim myprt("TC");
2811  myprt << "GKv2 fitPt " << fitPt << " " << PrintPos(tj.Pts[fitPt]);
2812  myprt << std::fixed << std::setprecision(5);
2813  myprt << " KinkSig " << std::setprecision(5) << tj.Pts[fitPt].KinkSig;
2814  myprt << " prevPt significance " << tj.Pts[fitPt - 1].KinkSig;
2815  if (!thisPtHasKink && !prevPtHasKink) myprt << " no kink";
2816  if (thisPtHasKink && !prevPtHasKink) myprt << " -> Start kink region";
2817  if (thisPtHasKink && prevPtHasKink) myprt << " -> Inside kink region";
2818  if (!thisPtHasKink && prevPtHasKink) myprt << " -> End kink region";
2819  } // dbgStp
2820  // See if we just passed a series of points having a high kink significance. If so,
2821  // then find the point with the maximum value and call that the kink point
2822  // Don't declare a kink (yet)
2823  if (thisPtHasKink) return false;
2824  // neither points are kink-like
2825  if (!prevPtHasKink) return false;
2826 
2827  // We have left a kink region. Find the point with the max likelihood and call
2828  // that the kink point
2829  float maxSig = tcc.kinkCuts[1];
2830  unsigned short kinkRegionLength = 0;
2831  unsigned short maxKinkPt = USHRT_MAX;
2832  for (unsigned short ipt = fitPt - 1; ipt > tj.EndPt[0]; --ipt) {
2833  auto& tp = tj.Pts[ipt];
2834  if (tp.KinkSig < 0) continue;
2835  if (tp.KinkSig > maxSig) {
2836  // track the max significance
2837  maxSig = tp.KinkSig;
2838  maxKinkPt = ipt;
2839  } // tp.KinkSig > maxSig
2840  // find the start of the kink region
2841  if (tp.KinkSig < tcc.kinkCuts[1]) break;
2842  ++kinkRegionLength;
2843  } // ipt
2844  if (maxKinkPt == USHRT_MAX) return false;
2845  // Require that the candidate kink be above the cut threshold for more than one point.
2846  // Scale the requirement by the number of points in the fit
2847  unsigned short kinkRegionLengthMin = 1 + nPtsFit / 5;
2848  if (tj.Strategy[kStiffMu]) kinkRegionLengthMin = 1 + nPtsFit / 3;
2849  if (kinkRegionLength < kinkRegionLengthMin) {
2850  if (tcc.dbgStp)
2851  mf::LogVerbatim("TC") << "GKv2: kink region too short " << kinkRegionLength << " Min "
2852  << kinkRegionLengthMin;
2853  return false;
2854  }
2855  if (tcc.dbgStp)
2856  mf::LogVerbatim("TC") << "GKv2: kink at " << PrintPos(tj.Pts[maxKinkPt])
2857  << std::setprecision(3) << " maxSig " << maxSig << " kinkRegionLength "
2858  << kinkRegionLength << " Min " << kinkRegionLengthMin;
2859  // don't alter the tj unless doTrim is true
2860  if (!doTrim) return true;
2861  // trim the points
2862  for (unsigned short ipt = maxKinkPt + 1; ipt <= tj.EndPt[1]; ++ipt)
2863  UnsetUsedHits(slc, tj.Pts[ipt]);
2864  SetEndPoints(tj);
2865  // trim another point if the charge of the last two points is wildly dissimilar
2866  float lastChg = tj.Pts[tj.EndPt[1]].Chg;
2867  float prevChg = tj.Pts[tj.EndPt[1] - 1].Chg;
2868  float chgAsym = std::abs(lastChg - prevChg) / (lastChg + prevChg);
2869  if (tcc.dbgStp)
2870  mf::LogVerbatim("TC") << "GKv2: last point after trim " << PrintPos(tj.Pts[tj.EndPt[1]])
2871  << " chgAsym " << chgAsym;
2872  if (chgAsym > 0.1) {
2873  UnsetUsedHits(slc, tj.Pts[tj.EndPt[1]]);
2874  SetEndPoints(tj);
2875  }
2876  tj.EndFlag[1][kAtKink] = true;
2877  return true;
2878 
2879  } // GottaKink
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
std::vector< float > kinkCuts
kink finder algorithm
Definition: DataStructs.h:550
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1061
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
use the slowing-down strategy
Definition: DataStructs.h:494
float KinkSignificance(TCSlice const &slc, Trajectory const &tj1, unsigned short end1, Trajectory const &tj2, unsigned short end2, unsigned short nPtsFit, bool useChg, bool prt)
Definition: Utils.cxx:2986
use the stiff electron strategy
Definition: DataStructs.h:492
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
use the stiff muon strategy
Definition: DataStructs.h:493
bool tca::HasDuplicateHits ( const TCSlice slc,
Trajectory const &  tj,
bool  prt 
)

Definition at line 2745 of file Utils.cxx.

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

Referenced by CheckTraj(), and MergeAndStore().

2746  {
2747  // returns true if a hit is associated with more than one TP
2748  auto tjHits = PutTrajHitsInVector(tj, kAllHits);
2749  for (unsigned short ii = 0; ii < tjHits.size() - 1; ++ii) {
2750  for (unsigned short jj = ii + 1; jj < tjHits.size(); ++jj) {
2751  if (tjHits[ii] == tjHits[jj]) {
2752  if (prt)
2753  mf::LogVerbatim("TC") << "HDH: Hit " << PrintHit(slc.slHits[ii]) << " is a duplicate "
2754  << ii << " " << jj;
2755  return true;
2756  }
2757  } // jj
2758  } // ii
2759  return false;
2760  } // HasDuplicateHits
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< unsigned int > PutTrajHitsInVector(const Trajectory &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2689
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6347
float tca::HitSep2 ( const TCSlice slc,
unsigned int  iht,
unsigned int  jht 
)

Definition at line 2483 of file Utils.cxx.

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

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

2484  {
2485  // returns the separation^2 between two hits in WSE units
2486  if (iht > slc.slHits.size() - 1 || jht > slc.slHits.size() - 1) return 1E6;
2487  auto& ihit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2488  auto& jhit = (*evt.allHits)[slc.slHits[jht].allHitsIndex];
2489  float dw = (float)ihit.WireID().Wire - (float)jhit.WireID().Wire;
2490  float dt = (ihit.PeakTime() - jhit.PeakTime()) * tcc.unitsPerTick;
2491  return dw * dw + dt * dt;
2492  } // HitSep2
TCConfig tcc
Definition: DataStructs.cxx:9
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
float tca::HitsPosTick ( const TCSlice slc,
const std::vector< unsigned int > &  hitsInMultiplet,
float &  sum,
HitStatus_t  hitRequest 
)

Definition at line 4174 of file Utils.cxx.

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

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

4178  {
4179  // returns the position and the charge
4180  float pos = 0;
4181  sum = 0;
4182  for (unsigned short ii = 0; ii < hitsInMultiplet.size(); ++ii) {
4183  unsigned int iht = hitsInMultiplet[ii];
4184  bool useit = (hitRequest == kAllHits);
4185  if (hitRequest == kUsedHits && slc.slHits[iht].InTraj > 0) useit = true;
4186  if (hitRequest == kUnusedHits && slc.slHits[iht].InTraj == 0) useit = true;
4187  if (!useit) continue;
4188  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
4189  float chg = hit.Integral();
4190  pos += chg * hit.PeakTime();
4191  sum += chg;
4192  } // ii
4193  if (sum <= 0) return -1;
4194  return pos / sum;
4195  } // HitsPosTick
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
Double_t sum
Definition: plot.C:31
float tca::HitsPosTime ( const TCSlice slc,
const std::vector< unsigned int > &  hitsInMultiplet,
float &  sum,
HitStatus_t  hitRequest 
)

Definition at line 4165 of file Utils.cxx.

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

Referenced by DotProd().

4169  {
4170  return tcc.unitsPerTick * HitsPosTick(slc, hitsInMultiplet, sum, hitRequest);
4171  } // HitsPosTime
TCConfig tcc
Definition: DataStructs.cxx:9
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
float HitsPosTick(const TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, float &sum, HitStatus_t hitRequest)
Definition: Utils.cxx:4174
Double_t sum
Definition: plot.C:31
float tca::HitsRMSTick ( const TCSlice slc,
const std::vector< unsigned int > &  hitsInMultiplet,
HitStatus_t  hitRequest 
)

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

4136  {
4137  if (hitsInMultiplet.empty()) return 0;
4138 
4139  if (hitsInMultiplet.size() == 1) {
4140  auto& hit = (*evt.allHits)[slc.slHits[hitsInMultiplet[0]].allHitsIndex];
4141  return hit.RMS();
4142  }
4143 
4144  float minVal = 9999;
4145  float maxVal = 0;
4146  for (unsigned short ii = 0; ii < hitsInMultiplet.size(); ++ii) {
4147  unsigned int iht = hitsInMultiplet[ii];
4148  bool useit = (hitRequest == kAllHits);
4149  if (hitRequest == kUsedHits && slc.slHits[iht].InTraj > 0) useit = true;
4150  if (hitRequest == kUnusedHits && slc.slHits[iht].InTraj == 0) useit = true;
4151  if (!useit) continue;
4152  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
4153  float cv = hit.PeakTime();
4154  float rms = hit.RMS();
4155  float arg = cv - rms;
4156  if (arg < minVal) minVal = arg;
4157  arg = cv + rms;
4158  if (arg > maxVal) maxVal = arg;
4159  } // ii
4160  if (maxVal == 0) return 0;
4161  return (maxVal - minVal) / 2;
4162  } // HitsRMSTick
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
float tca::HitsRMSTime ( const TCSlice slc,
const std::vector< unsigned int > &  hitsInMultiplet,
HitStatus_t  hitRequest 
)

Definition at line 4125 of file Utils.cxx.

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

Referenced by CreateTP3D(), DotProd(), and HitsTimeErr2().

4128  {
4129  return tcc.unitsPerTick * HitsRMSTick(slc, hitsInMultiplet, hitRequest);
4130  } // HitsRMSTick
TCConfig tcc
Definition: DataStructs.cxx:9
float HitsRMSTick(const TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
Definition: Utils.cxx:4133
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
float tca::HitsTimeErr2 ( const TCSlice slc,
const std::vector< unsigned int > &  hitVec 
)

Definition at line 1662 of file StepUtils.cxx.

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

Referenced by DefineHitPos().

1663  {
1664  // Estimates the error^2 of the time using all hits in hitVec
1665  if (hitVec.empty()) return 0;
1666  float err = tcc.hitErrFac * HitsRMSTime(slc, hitVec, kUnusedHits);
1667  return err * err;
1668  } // HitsTimeErr2
TCConfig tcc
Definition: DataStructs.cxx:9
float HitsRMSTime(const TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
Definition: Utils.cxx:4125
float tca::HitTimeErr ( const TCSlice slc,
unsigned int  iht 
)

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

1655  {
1656  if (iht > slc.slHits.size() - 1) return 0;
1657  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1658  return hit.RMS() * tcc.unitsPerTick * tcc.hitErrFac * hit.Multiplicity();
1659  } // HitTimeErr
TCConfig tcc
Definition: DataStructs.cxx:9
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
unsigned short tca::InsertTP3D ( PFPStruct pfp,
TP3D tp3d 
)

Definition at line 1961 of file PFPUtils.cxx.

References tca::TP3D::along, tca::PFPStruct::Flags, kNeedsUpdate, tca::PFPStruct::SectionFits, tca::TP3D::SFIndex, and tca::PFPStruct::TP3Ds.

Referenced by AddPointsInRange().

1962  {
1963  // inserts the tp3d into the section defined by tp3d.SFIndex
1964  if (tp3d.SFIndex >= pfp.SectionFits.size()) return USHRT_MAX;
1965  // Find the first occurrence of this SFIndex
1966  std::size_t ipt = 0;
1967  for (ipt = 0; ipt < pfp.TP3Ds.size(); ++ipt)
1968  if (tp3d.SFIndex == pfp.TP3Ds[ipt].SFIndex) break;
1969  if (ipt == pfp.TP3Ds.size()) return USHRT_MAX;
1970  // next see if we can insert it so that re-sorting of this section isn't required
1971  auto lastTP3D = pfp.TP3Ds.back();
1972  if (ipt == 0 && tp3d.along < pfp.TP3Ds[0].along) {
1973  // insert at the beginning. No search needs to be done
1974  }
1975  else if (tp3d.SFIndex == lastTP3D.SFIndex && tp3d.along > lastTP3D.along) {
1976  // insert at the end. Use push_back and return
1977  pfp.TP3Ds.push_back(tp3d);
1978  pfp.SectionFits[tp3d.SFIndex].NeedsUpdate = true;
1979  pfp.Flags[kNeedsUpdate] = true;
1980  return pfp.TP3Ds.size() - 1;
1981  }
1982  else {
1983  for (std::size_t iipt = ipt; iipt < pfp.TP3Ds.size() - 1; ++iipt) {
1984  // break out if the next point is in a different section
1985  if (pfp.TP3Ds[iipt + 1].SFIndex != tp3d.SFIndex) break;
1986  if (tp3d.along > pfp.TP3Ds[iipt].along && tp3d.along < pfp.TP3Ds[iipt + 1].along) {
1987  ipt = iipt + 1;
1988  break;
1989  }
1990  } // iipt
1991  } // insert in the middle
1992  pfp.TP3Ds.insert(pfp.TP3Ds.begin() + ipt, tp3d);
1993  pfp.SectionFits[tp3d.SFIndex].NeedsUpdate = true;
1994  pfp.Flags[kNeedsUpdate] = true;
1995  return ipt;
1996  } // InsertTP3D
double tca::InShowerProb ( double  showerEnergy,
double  along,
double  trans 
)
float tca::InShowerProb ( TCSlice slc,
const ShowerStruct3D ss3,
const PFPStruct pfp 
)

Definition at line 1992 of file TCShower.cxx.

References tca::ShowerStruct3D::CotIDs, tca::TCSlice::cots, tca::PFPStruct::ID, tca::ShowerStruct3D::ID, sum, tca::PFPStruct::TjIDs, and tca::TCSlice::tjs.

Referenced by Reconcile3D().

1993  {
1994  // returns a likelihood (0 - 1) that the pfp particle belongs in shower ss3
1995 
1996  if (ss3.ID == 0 || pfp.ID == 0) return 0;
1997  float sum = 0;
1998  float cnt = 0;
1999  for (auto cid : ss3.CotIDs) {
2000  auto& ss = slc.cots[cid - 1];
2001  if (ss.ID == 0) continue;
2002  for (auto tid : pfp.TjIDs) {
2003  auto& tj = slc.tjs[tid - 1];
2004  if (tj.CTP != ss.CTP) continue;
2005  sum += InShowerProb(slc, ss, tj);
2006  ++cnt;
2007  } // tid
2008  } //cid
2009  if (cnt == 0) return 0;
2010  return sum / cnt;
2011 
2012  } // InShowerProb
float InShowerProb(TCSlice &slc, const ShowerStruct &ss, const Trajectory &tj)
Definition: TCShower.cxx:2015
Double_t sum
Definition: plot.C:31
float tca::InShowerProb ( TCSlice slc,
const ShowerStruct ss,
const Trajectory tj 
)

Definition at line 2015 of file TCShower.cxx.

References util::abs(), 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().

2016  {
2017  // returns a likelihood (0 - 1) that the tj particle belongs in shower ss
2018  // Keep it simple: construct a FOM, take the inverse and limit it to the range 0 - 1
2019  if (ss.ID == 0 || tj.ID == 0) return 0;
2020  if (ss.CTP != tj.CTP) return 0;
2021 
2022  auto& stj = slc.tjs[ss.ShowerTjID - 1];
2023  if (stj.Pts.size() != 3) return 0;
2024  unsigned short closePt1, closePt2;
2025  float doca = 1E6;
2026  TrajTrajDOCA(slc, stj, tj, closePt1, closePt2, doca);
2027  if (doca == 1E6) return 0;
2028  float showerLen = PosSep(stj.Pts[0].Pos, stj.Pts[2].Pos);
2029  // make a rough separation cut. Return a small but non-zero value
2030  if (doca > 5 * showerLen) return 0.01;
2031  auto& stp = stj.Pts[closePt1];
2032  if (stp.DeltaRMS == 0) return 0;
2033  auto& ttp = tj.Pts[closePt2];
2034  Point2_t alongTrans;
2035  FindAlongTrans(stp.Pos, stp.Dir, ttp.Pos, alongTrans);
2036  float rms = stp.DeltaRMS;
2037  if (rms < 1) rms = 1;
2038  float arg = alongTrans[1] / rms;
2039  float radProb = exp(-0.5 * arg * arg);
2040  // This is a fake but may be OK if this function is called before the shower is well-defined
2041  rms = showerLen;
2042  arg = alongTrans[0] / rms;
2043  float longProb = exp(-0.5 * arg * arg);
2044  float costh = std::abs(DotProd(stp.Dir, ttp.Dir));
2045  float prob = radProb * longProb * costh;
2046  return prob;
2047 
2048  } // InShowerProb
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:3066
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::array< float, 2 > Point2_t
Definition: DataStructs.h:41
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:126
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
bool TrajTrajDOCA(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2407
double tca::InShowerProbLong ( double  showerEnergy,
double  along 
)

Definition at line 1937 of file TCShower.cxx.

References ShowerParams().

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

1938  {
1939  // Returns the likelihood that the point at position along (cm) is inside an EM shower
1940  // having showerEnergy (MeV). The variable along is relative to shower max.
1941 
1942  if (showerEnergy < 10) return 0;
1943 
1944  double shMaxAlong, shE95Along;
1945  ShowerParams(showerEnergy, shMaxAlong, shE95Along);
1946  // 50% of the shower energy is deposited between 0 < shMaxAlong < 1, which should be obvious considering
1947  // that is the definition of the shower max, so the probability should be ~1 at shMaxAlong = 1.
1948  // The Geant study shows that 95% of the energy is contained within 2.5 * shMax and has a small dependence
1949  // on the shower energy, which is modeled in ShowerParams. This function uses a
1950  // sigmoid likelihood function is constructed with these constraints using the scaling variable tau
1951  double tau = (along + shMaxAlong) / shMaxAlong;
1952  if (tau < -1 || tau > 4) return 0;
1953 
1954  double tauHalf, width;
1955  if (tau > 0) {
1956  tauHalf = 1.7;
1957  width = 0.35;
1958  }
1959  else {
1960  // Allow for some uncertainty in the shower start position
1961  tau = -tau;
1962  tauHalf = 0.2;
1963  width = 0.1;
1964  }
1965 
1966  double prob = 1 / (1 + exp((tau - tauHalf) / width));
1967  return prob;
1968 
1969  } // InShowrProbLong
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
Definition: TCShower.cxx:1904
double tca::InShowerProbParam ( double  showerEnergy,
double  along,
double  trans 
)

Definition at line 1986 of file TCShower.cxx.

References InShowerProbLong(), and InShowerProbTrans().

1987  {
1988  return InShowerProbLong(showerEnergy, along) * InShowerProbTrans(showerEnergy, along, trans);
1989  } // InShowerProbParam
double InShowerProbLong(double showerEnergy, double along)
Definition: TCShower.cxx:1937
double InShowerProbTrans(double showerEnergy, double along, double trans)
Definition: TCShower.cxx:1972
double tca::InShowerProbTrans ( double  showerEnergy,
double  along,
double  trans 
)

Definition at line 1972 of file TCShower.cxx.

References util::abs(), and ShowerParamTransRMS().

Referenced by InShowerProbParam(), and MergeSubShowers().

1973  {
1974  // Returns the likelihood that the point, (along, trans) (cm), is inside an EM shower having energy showerEnergy (MeV)
1975  // where along is relative to the shower start position and trans is the radial distance.
1976 
1977  if (showerEnergy < 10) return 0;
1978  double rms = ShowerParamTransRMS(showerEnergy, along);
1979  trans = std::abs(trans);
1980  double prob = exp(-0.5 * trans / rms);
1981  return prob;
1982 
1983  } // InShowerProbTrans
constexpr auto abs(T v)
Returns the absolute value of the argument.
double ShowerParamTransRMS(double showerEnergy, double along)
Definition: TCShower.cxx:1923
bool tca::InsideFV ( const TCSlice slc,
const PFPStruct pfp,
unsigned short  end 
)

Definition at line 3019 of file PFPUtils.cxx.

References tca::PFPStruct::Flags, tca::PFPStruct::ID, kNeedsUpdate, tca::PFPStruct::PDGCode, tca::PFPStruct::SectionFits, tca::PFPStruct::TP3Ds, tca::TCSlice::xHi, tca::TCSlice::xLo, tca::TCSlice::yHi, tca::TCSlice::yLo, tca::TCSlice::zHi, and tca::TCSlice::zLo.

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

3020  {
3021  // returns true if the end of the pfp is inside the fiducial volume of the TPC
3022  if (pfp.ID <= 0) return false;
3023  if (end > 1) return false;
3024  if (pfp.SectionFits.empty()) return false;
3025  // require that the points are sorted which ensures that the start and end points
3026  // are the first and last points in the TP3Ds vector
3027  if (pfp.Flags[kNeedsUpdate]) return false;
3028  bool neutrinoPFP = pfp.PDGCode == 12 || pfp.PDGCode == 14;
3029 
3030  float abit = 5;
3031  Point3_t pos;
3032  if (neutrinoPFP) { pos = pfp.SectionFits[0].Pos; }
3033  else if (end == 0) {
3034  pos = pfp.TP3Ds[0].Pos;
3035  }
3036  else {
3037  pos = pfp.TP3Ds[pfp.TP3Ds.size() - 1].Pos;
3038  }
3039  return (pos[0] > slc.xLo + abit && pos[0] < slc.xHi - abit && pos[1] > slc.yLo + abit &&
3040  pos[1] < slc.yHi - abit && pos[2] > slc.zLo + abit && pos[2] < slc.zHi - abit);
3041 
3042  } // InsideFV
std::array< double, 3 > Point3_t
Definition: DataStructs.h:39
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
bool tca::InsideTPC ( const Point3_t pos,
geo::TPCID inTPCID 
)

Definition at line 3045 of file PFPUtils.cxx.

References tca::TCConfig::geom, geo::Iterable< IterationPolicy, Transform >::Iterate(), and tcc.

Referenced by DotProd(), MakePFParticles(), and MakeSmallAnglePFP().

3046  {
3047  // determine which TPC this point is in. This function returns false
3048  // if the point is not inside any TPC
3049  float abit = 5;
3050  for (const geo::TPCGeo& TPC : tcc.geom->Iterate<geo::TPCGeo>()) {
3051  auto const world = TPC.GetCenter();
3052  // reduce the active area of the TPC by a bit to be consistent with FillWireHitRange
3053  if (pos[0] < world.X() - TPC.HalfWidth() + abit) continue;
3054  if (pos[0] > world.X() + TPC.HalfWidth() - abit) continue;
3055  if (pos[1] < world.Y() - TPC.HalfHeight() + abit) continue;
3056  if (pos[1] > world.Y() + TPC.HalfHeight() - abit) continue;
3057  if (pos[2] < world.Z() - TPC.Length() / 2 + abit) continue;
3058  if (pos[2] > world.Z() + TPC.Length() / 2 - abit) continue;
3059  inTPCID = TPC.ID();
3060  return true;
3061  } // tpcid
3062  return false;
3063  } // InsideTPC
TCConfig tcc
Definition: DataStructs.cxx:9
Geometry information for a single TPC.
Definition: TPCGeo.h:33
const geo::GeometryCore * geom
Definition: DataStructs.h:567
range_type< T > Iterate() const
Definition: Iterable.h:121
bool tca::InTrajOK ( TCSlice slc,
std::string  someText 
)

Definition at line 1257 of file Utils.cxx.

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

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

1258  {
1259  // Check slc.tjs -> InTraj associations
1260 
1261  unsigned short tID;
1262  unsigned int iht;
1263  unsigned short itj = 0;
1264  std::vector<unsigned int> tHits;
1265  std::vector<unsigned int> atHits;
1266  for (auto& tj : slc.tjs) {
1267  // ignore abandoned trajectories
1268  if (tj.AlgMod[kKilled]) continue;
1269  tID = tj.ID;
1270  tHits = PutTrajHitsInVector(tj, kUsedHits);
1271  if (tHits.size() < 2) continue;
1272  std::sort(tHits.begin(), tHits.end());
1273  atHits.clear();
1274  for (iht = 0; iht < slc.slHits.size(); ++iht) {
1275  if (slc.slHits[iht].InTraj == tID) atHits.push_back(iht);
1276  } // iht
1277  if (atHits.size() < 2) continue;
1278  if (!std::equal(tHits.begin(), tHits.end(), atHits.begin())) {
1279  mf::LogVerbatim myprt("TC");
1280  myprt << someText << " ChkInTraj failed: inTraj - UseHit mis-match for T" << tID
1281  << " tj.WorkID " << tj.WorkID << " atHits size " << atHits.size() << " tHits size "
1282  << tHits.size() << " in CTP " << tj.CTP << "\n";
1283  myprt << "AlgMods: ";
1284  for (unsigned short ib = 0; ib < AlgBitNames.size(); ++ib)
1285  if (tj.AlgMod[ib]) myprt << " " << AlgBitNames[ib];
1286  myprt << "\n";
1287  myprt << "index inTraj UseHit \n";
1288  for (iht = 0; iht < atHits.size(); ++iht) {
1289  myprt << "iht " << iht << " " << PrintHit(slc.slHits[atHits[iht]]);
1290  if (iht < tHits.size()) myprt << " " << PrintHit(slc.slHits[tHits[iht]]);
1291  if (atHits[iht] != tHits[iht]) myprt << " <<< " << atHits[iht] << " != " << tHits[iht];
1292  myprt << "\n";
1293  } // iht
1294  if (tHits.size() > atHits.size()) {
1295  for (iht = atHits.size(); iht < atHits.size(); ++iht) {
1296  myprt << "atHits " << iht << " " << PrintHit(slc.slHits[atHits[iht]]) << "\n";
1297  } // iht
1298  PrintTrajectory("CIT", slc, tj, USHRT_MAX);
1299  } // tHit.size > atHits.size()
1300  return false;
1301  }
1302  // check the VtxID
1303  for (unsigned short end = 0; end < 2; ++end) {
1304  if (tj.VtxID[end] > slc.vtxs.size()) {
1305  mf::LogVerbatim("TC") << someText << " ChkInTraj: Bad VtxID " << tj.ID;
1306  tj.AlgMod[kKilled] = true;
1307  return false;
1308  }
1309  } // end
1310  ++itj;
1311  } // tj
1312  return true;
1313 
1314  } // InTrajOK
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< unsigned int > PutTrajHitsInVector(const Trajectory &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2689
const std::vector< std::string > AlgBitNames
Definition: DataStructs.cxx:16
void PrintTrajectory(std::string someText, const TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:6035
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6347
unsigned short tca::IsCloseToVertex ( const TCSlice slc,
const VtxStore inVx2 
)

Definition at line 2859 of file TCVertex.cxx.

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

Referenced by Find2DVertices().

2860  {
2861  // Returns the ID of a 2D vertex having the minimum pull < user-specified cut
2862 
2863  float minPull = tcc.vtx2DCuts[3];
2864  unsigned short imBest = 0;
2865  for (auto& vx2 : slc.vtxs) {
2866  if (vx2.CTP != inVx2.CTP) continue;
2867  if (vx2.ID <= 0) continue;
2868  float pull = VertexVertexPull(inVx2, vx2);
2869  if (pull < minPull) {
2870  minPull = pull;
2871  imBest = vx2.ID;
2872  }
2873  } // vx2
2874  return imBest;
2875  } // IsCloseToVertex
TCConfig tcc
Definition: DataStructs.cxx:9
float VertexVertexPull(const VtxStore &vx1, const VtxStore &vx2)
Definition: TCVertex.cxx:1895
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:541
unsigned short tca::IsCloseToVertex ( const TCSlice slc,
const Vtx3Store vx3 
)

Definition at line 2878 of file TCVertex.cxx.

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

2879  {
2880  // Returns the ID of a 3D vertex having the minimum pull < user-specified cut
2881 
2882  float minPull = tcc.vtx3DCuts[1];
2883  unsigned short imBest = 0;
2884  for (auto& oldvx3 : slc.vtx3s) {
2885  if (oldvx3.ID == 0) continue;
2886  if (std::abs(oldvx3.X - vx3.X) > tcc.vtx3DCuts[0]) continue;
2887  float pull = VertexVertexPull(vx3, oldvx3);
2888  if (pull < minPull) {
2889  minPull = pull;
2890  imBest = oldvx3.ID;
2891  }
2892  } // oldvx3
2893  return imBest;
2894 
2895  } // IsCloseToVertex
std::vector< float > vtx3DCuts
2D vtx -> 3D vtx matching cuts
Definition: DataStructs.h:542
TCConfig tcc
Definition: DataStructs.cxx:9
constexpr auto abs(T v)
Returns the absolute value of the argument.
float VertexVertexPull(const VtxStore &vx1, const VtxStore &vx2)
Definition: TCVertex.cxx:1895
bool tca::IsGhost ( TCSlice slc,
Trajectory tj 
)

Definition at line 3084 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 CheckTraj(), and tca::TrajClusterAlg::FindJunkTraj().

3085  {
3086  // Sees if trajectory tj shares many hits with another trajectory and if so merges them.
3087 
3088  if (!tcc.useAlg[kUseGhostHits]) return false;
3089  // ensure that tj is not a saved trajectory
3090  if (tj.ID > 0) return true;
3091  // or an already killed trajectory
3092  if (tj.AlgMod[kKilled]) return true;
3093  if (tj.Pts.size() < 3) return false;
3094  if (tj.Strategy[kStiffEl]) return false;
3095 
3096  // vectors of traj IDs, and the occurrence count
3097  std::vector<int> tID;
3098  std::vector<unsigned short> tCnt;
3099 
3100  unsigned short hitCnt = 0;
3101  unsigned short nAvailable = 0;
3102  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
3103  for (unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
3104  // ignore hits used by this trajectory
3105  if (tj.Pts[ipt].UseHit[ii]) {
3106  ++hitCnt;
3107  continue;
3108  }
3109  unsigned int iht = tj.Pts[ipt].Hits[ii];
3110  if (slc.slHits[iht].InTraj > 0 && (unsigned int)slc.slHits[iht].InTraj <= slc.tjs.size()) {
3111  int tjid = slc.slHits[iht].InTraj;
3112  unsigned short indx;
3113  for (indx = 0; indx < tID.size(); ++indx)
3114  if (tID[indx] == tjid) break;
3115  if (indx == tID.size()) {
3116  tID.push_back(tjid);
3117  tCnt.push_back(1);
3118  }
3119  else {
3120  ++tCnt[indx];
3121  }
3122  }
3123  else {
3124  ++nAvailable;
3125  }
3126  } // ii
3127  } // ipt
3128 
3129  // Call it a ghost if > 1/3 of the hits are used by another trajectory
3130  hitCnt /= 3;
3131  int oldTjID = INT_MAX;
3132 
3133  if (tcc.dbgStp) {
3134  mf::LogVerbatim myprt("TC");
3135  myprt << "IsGhost tj hits size cut " << hitCnt << " tID_tCnt";
3136  for (unsigned short ii = 0; ii < tCnt.size(); ++ii)
3137  myprt << " " << tID[ii] << "_" << tCnt[ii];
3138  myprt << "\nAvailable hits " << nAvailable;
3139  } // prt
3140 
3141  for (unsigned short ii = 0; ii < tCnt.size(); ++ii) {
3142  if (tCnt[ii] > hitCnt) {
3143  oldTjID = tID[ii];
3144  hitCnt = tCnt[ii];
3145  }
3146  } // ii
3147  if (oldTjID == INT_MAX) return false;
3148  int oldTjIndex = oldTjID - 1;
3149 
3150  // See if this looks like a short delta-ray on a long muon
3151  Trajectory& oTj = slc.tjs[oldTjIndex];
3152  if (oTj.PDGCode == 13 && hitCnt < 0.1 * oTj.Pts.size()) return false;
3153 
3154  // See if there are gaps in this trajectory indicating that it is really a ghost and not
3155  // just a crossing trajectory
3156  // find the range of wires spanned by oTj
3157  int wire0 = INT_MAX;
3158  int wire1 = 0;
3159  for (auto& otp : oTj.Pts) {
3160  int wire = std::nearbyint(otp.Pos[0]);
3161  if (wire < wire0) wire0 = wire;
3162  if (wire > wire1) wire1 = wire;
3163  } // tp
3164 
3165  int nwires = wire1 - wire0 + 1;
3166  std::vector<float> oTjPos1(nwires, -1);
3167  unsigned short nMissedWires = 0;
3168  for (unsigned short ipt = oTj.EndPt[0]; ipt <= oTj.EndPt[1]; ++ipt) {
3169  if (oTj.Pts[ipt].Chg == 0) continue;
3170  int wire = std::nearbyint(oTj.Pts[ipt].Pos[0]);
3171  int indx = wire - wire0;
3172  if (indx < 0 || indx > nwires - 1) continue;
3173  oTjPos1[indx] = oTj.Pts[ipt].Pos[1];
3174  ++nMissedWires;
3175  } // ipt
3176  // count the number of ghost TPs
3177  unsigned short ngh = 0;
3178  // and the number with Delta > 0 relative to oTj
3179  unsigned short nghPlus = 0;
3180  // keep track of the first point and last point appearance of oTj
3181  unsigned short firstPtInoTj = USHRT_MAX;
3182  unsigned short lastPtInoTj = 0;
3183  TrajPoint tp = tj.Pts[tj.EndPt[0]];
3184  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
3185  if (tj.Pts[ipt].Chg > 0) {
3186  tp = tj.Pts[ipt];
3187  continue;
3188  }
3189  int wire = std::nearbyint(tj.Pts[ipt].Pos[0]);
3190  int indx = wire - wire0;
3191  if (indx < 0 || indx > nwires - 1) continue;
3192  if (oTjPos1[indx] > 0) {
3193  // ensure that the hits in this tp are used in oTj
3194  bool HitInoTj = false;
3195  for (unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
3196  unsigned int iht = tj.Pts[ipt].Hits[ii];
3197  if (slc.slHits[iht].InTraj == oldTjID) HitInoTj = true;
3198  } // ii
3199  if (HitInoTj) {
3200  ++ngh;
3201  MoveTPToWire(tp, tj.Pts[ipt].Pos[0]);
3202  if (tp.Pos[1] > oTjPos1[indx]) ++nghPlus;
3203  if (firstPtInoTj == USHRT_MAX) firstPtInoTj = ipt;
3204  lastPtInoTj = ipt;
3205  }
3206  } // oTjHasChg[indx]
3207  } // ipt
3208 
3209  if (tcc.dbgStp)
3210  mf::LogVerbatim("TC") << " Number of missed wires in oTj gaps " << nMissedWires
3211  << " Number of ghost hits in these gaps " << ngh << " nghPlus "
3212  << nghPlus << " cut " << 0.2 * nMissedWires;
3213 
3214  if (ngh < 0.2 * nMissedWires) return false;
3215  if (firstPtInoTj > lastPtInoTj) return false;
3216 
3217  // require all of the tj TPs to be on either the + or - side of the oTj trajectory
3218  if (!(nghPlus > 0.8 * ngh || nghPlus < 0.2 * ngh)) return false;
3219 
3220  if (tcc.dbgStp)
3221  mf::LogVerbatim("TC") << " Trajectory is a ghost of " << oldTjID << " first point in oTj "
3222  << firstPtInoTj << " last point " << lastPtInoTj;
3223 
3224  // unset all of the shared hits
3225  for (unsigned short ipt = firstPtInoTj; ipt <= lastPtInoTj; ++ipt) {
3226  if (tj.Pts[ipt].Chg == 0) continue;
3227  UnsetUsedHits(slc, tj.Pts[ipt]);
3228  if (tcc.dbgStp) PrintTrajectory("IG", slc, tj, ipt);
3229  }
3230  // see how many points are left at the end
3231  ngh = 0;
3232  for (unsigned short ipt = lastPtInoTj; ipt <= tj.EndPt[1]; ++ipt) {
3233  if (tj.Pts[ipt].Chg > 0) ++ngh;
3234  } // ipt
3235  // clobber those too?
3236  if (ngh > 0 && ngh < tcc.minPts[tj.Pass]) {
3237  for (unsigned short ipt = lastPtInoTj; ipt <= tj.EndPt[1]; ++ipt) {
3238  if (tj.Pts[ipt].Chg > 0) UnsetUsedHits(slc, tj.Pts[ipt]);
3239  } // ipt
3240  }
3241  SetEndPoints(tj);
3242  tj.Pts.resize(tj.EndPt[1] + 1);
3243  slc.tjs[oldTjIndex].AlgMod[kUseGhostHits] = true;
3244  TrimEndPts("IG", slc, tj, tcc.qualityCuts, tcc.dbgStp);
3245  if (tj.AlgMod[kKilled]) {
3246  tj.IsGood = false;
3247  if (tcc.dbgStp) mf::LogVerbatim("TC") << " Failed quality cuts";
3248  return true;
3249  }
3250  tj.MCSMom = MCSMom(slc, tj);
3251  if (tcc.dbgStp) mf::LogVerbatim("TC") << " New tj size " << tj.Pts.size();
3252  return true;
3253 
3254  } // IsGhost
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3381
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
std::vector< float > qualityCuts
Min points/wire, min consecutive pts after a gap.
Definition: DataStructs.h:554
TCConfig tcc
Definition: DataStructs.cxx:9
void PrintTrajectory(std::string someText, const TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:6035
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1061
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
std::vector< unsigned short > minPts
min number of Pts required to make a trajectory
Definition: DataStructs.h:557
void TrimEndPts(std::string fcnLabel, TCSlice &slc, Trajectory &tj, const std::vector< float > &fQualityCuts, bool prt)
Definition: Utils.cxx:1576
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
use the stiff electron strategy
Definition: DataStructs.h:492
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2763
bool tca::IsGhost ( TCSlice slc,
std::vector< unsigned int > &  tHits 
)

Definition at line 3257 of file StepUtils.cxx.

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

3258  {
3259  // Called by FindJunkTraj to see if the passed hits are close to an existing
3260  // trajectory and if so, they will be used in that other trajectory
3261 
3262  if (!tcc.useAlg[kUseGhostHits]) return false;
3263 
3264  if (tHits.size() < 2) return false;
3265 
3266  bool prt = (tcc.dbgStp || tcc.dbgAlg[kUseGhostHits]);
3267 
3268  // find all nearby hits
3269  std::vector<unsigned int> hitsInMuliplet, nearbyHits;
3270  for (auto iht : tHits) {
3271  GetHitMultiplet(slc, iht, hitsInMuliplet, false);
3272  // prevent double counting
3273  for (auto mht : hitsInMuliplet) {
3274  if (std::find(nearbyHits.begin(), nearbyHits.end(), mht) == nearbyHits.end()) {
3275  nearbyHits.push_back(mht);
3276  }
3277  } // mht
3278  } // iht
3279 
3280  // vectors of traj IDs, and the occurrence count
3281  std::vector<unsigned int> tID, tCnt;
3282  for (auto iht : nearbyHits) {
3283  if (slc.slHits[iht].InTraj <= 0) continue;
3284  unsigned int tid = slc.slHits[iht].InTraj;
3285  unsigned short indx = 0;
3286  for (indx = 0; indx < tID.size(); ++indx)
3287  if (tID[indx] == tid) break;
3288  if (indx == tID.size()) {
3289  tID.push_back(tid);
3290  tCnt.push_back(1);
3291  }
3292  else {
3293  ++tCnt[indx];
3294  }
3295  } // iht
3296  if (tCnt.empty()) return false;
3297 
3298  // Call it a ghost if > 50% of the hits are used by another trajectory
3299  unsigned short tCut = 0.5 * tHits.size();
3300  int tid = INT_MAX;
3301 
3302  if (prt) {
3303  mf::LogVerbatim myprt("TC");
3304  myprt << "IsGhost tHits size " << tHits.size() << " cut fraction " << tCut << " tID_tCnt";
3305  for (unsigned short ii = 0; ii < tCnt.size(); ++ii)
3306  myprt << " " << tID[ii] << "_" << tCnt[ii];
3307  } // prt
3308 
3309  for (unsigned short ii = 0; ii < tCnt.size(); ++ii) {
3310  if (tCnt[ii] > tCut) {
3311  tid = tID[ii];
3312  break;
3313  }
3314  } // ii
3315  if (tid > (int)slc.tjs.size()) return false;
3316 
3317  if (prt) mf::LogVerbatim("TC") << " is ghost of trajectory " << tid;
3318 
3319  // Use all hits in tHits that are found in itj
3320  for (auto& tp : slc.tjs[tid - 1].Pts) {
3321  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3322  unsigned int iht = tp.Hits[ii];
3323  if (slc.slHits[iht].InTraj != 0) continue;
3324  for (unsigned short jj = 0; jj < tHits.size(); ++jj) {
3325  unsigned int tht = tHits[jj];
3326  if (tht != iht) continue;
3327  tp.UseHit[ii] = true;
3328  slc.slHits[iht].InTraj = tid;
3329  break;
3330  } // jj
3331  } // ii
3332  } // tp
3333  slc.tjs[tid - 1].AlgMod[kUseGhostHits] = true;
3334  return true;
3335 
3336  } // IsGhost
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
void GetHitMultiplet(const TCSlice &slc, unsigned int theHit, std::vector< unsigned int > &hitsInMultiplet, bool useLongPulseHits)
Definition: StepUtils.cxx:1521
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:579
bool tca::IsShowerLike ( TCSlice const &  slc,
std::vector< int > const &  TjIDs 
)

Definition at line 1891 of file TCShower.cxx.

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

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

1892  {
1893  // Vote for the list of Tjs (assumed associated with a PFParticle) being shower-like
1894  if (TjIDs.empty()) return false;
1895  unsigned short cnt = 0;
1896  for (auto tid : TjIDs) {
1897  if (tid <= 0 || tid > (int)slc.tjs.size()) continue;
1898  if (slc.tjs[tid - 1].AlgMod[kShowerLike] > 0) ++cnt;
1899  } // tjid
1900  return (cnt > 1);
1901  } // IsInShower
void tca::KillPoorVertices ( TCSlice slc)

Definition at line 2159 of file TCVertex.cxx.

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

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

2160  {
2161  // kill 2D vertices that have low score and are not attached to a high-score 3D vertex
2162  if (slc.vtxs.empty()) return;
2163  for (auto& vx : slc.vtxs) {
2164  if (vx.ID == 0) continue;
2165  if (vx.Score > tcc.vtx2DCuts[7]) continue;
2166  if (vx.Vx3ID > 0) {
2167  auto& vx3 = slc.vtx3s[vx.Vx3ID - 1];
2168  if (vx3.Primary) continue;
2169  if (slc.vtx3s[vx.Vx3ID - 1].Score >= tcc.vtx2DCuts[7]) continue;
2170  }
2171  MakeVertexObsolete("KPV", slc, vx, false);
2172  } // vx
2173 
2174  } // KillPoorVertices
bool MakeVertexObsolete(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2789
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:541
void tca::KillVerticesInShower ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct ss,
bool  prt 
)

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

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

Definition at line 2986 of file Utils.cxx.

References tca::Trajectory::CTP, dir, tca::Trajectory::EndPt, tca::Trajectory::ID, and tca::Trajectory::Pts.

Referenced by ChkEndKink(), EndMerge(), GottaKink(), and StoreTraj().

2994  {
2995  // returns the significance of a potential kink between the ends of two trajectories. This
2996  // is used when deciding to either merge trajectories or make a vertex between them
2997 
2998  if (tj1.CTP != tj2.CTP) return -1;
2999  if (end1 > 1 || end2 > 1) return -1;
3000 
3001  // construct a temporary trajectory to allow using the standard KinkSignificance function.
3002  // The first nPtsFit points are comprised of TPs from tj1 and the last nPtsFits points are from tj2
3003  Trajectory tj;
3004  tj.ID = 666;
3005  tj.CTP = tj1.CTP;
3006  short dir = 1;
3007  if (end1 == 1) dir = -1;
3008  unsigned short cnt = 0;
3009  // add tj1 points to the trajectory
3010  for (short ii = 0; ii < (short)tj1.Pts.size(); ++ii) {
3011  short ipt = tj1.EndPt[end1] + dir * ii;
3012  if (ipt < 0) break;
3013  if (ipt >= (short)tj1.Pts.size()) break;
3014  auto& tp = tj1.Pts[ipt];
3015  if (tp.Chg <= 0) continue;
3016  tj.Pts.push_back(tp);
3017  ++cnt;
3018  if (cnt == nPtsFit + 1) break;
3019  } // ipt
3020  if (cnt < nPtsFit) return -1;
3021  // add tj2 points to the trajectory
3022  dir = 1;
3023  if (end2 == 1) dir = -1;
3024  cnt = 0;
3025  for (short ii = 0; ii < (short)tj2.Pts.size(); ++ii) {
3026  short ipt = tj2.EndPt[end2] + dir * ii;
3027  if (ipt < 0) break;
3028  if (ipt >= (short)tj2.Pts.size()) break;
3029  auto& tp = tj2.Pts[ipt];
3030  if (tp.Chg <= 0) continue;
3031  tj.Pts.push_back(tp);
3032  ++cnt;
3033  if (cnt == nPtsFit + 1) break;
3034  } // ipt
3035  tj.EndPt[0] = 0;
3036  tj.EndPt[1] = tj.Pts.size() - 1;
3037  return KinkSignificance(slc, tj, nPtsFit, nPtsFit, useChg, prt);
3038  } // KinkSignificance
float KinkSignificance(TCSlice const &slc, Trajectory &tj, unsigned short kinkPt, unsigned short nPtsFit, bool useChg, bool prt)
Definition: Utils.cxx:3041
TDirectory * dir
Definition: macro.C:5
float tca::KinkSignificance ( TCSlice const &  slc,
Trajectory tj,
unsigned short  kinkPt,
unsigned short  nPtsFit,
bool  useChg,
bool  prt 
)

Definition at line 3041 of file Utils.cxx.

References util::abs(), tca::TrajPoint::Ang, tca::TrajPoint::AngErr, DeltaAngle(), tca::Trajectory::EndPt, tca::TrajPoint::FitChi, FitTraj(), tca::Trajectory::ID, NumPtsWithCharge(), PrintPos(), and tca::Trajectory::Pts.

3047  {
3048  // returns a kink significance in the trajectory at the presumed kink point kinkPt
3049  // using angle and (optional) charge asymmetry. The returned value is negative if there is insufficient
3050  // information.
3051  //
3052  // Check the limits
3053  if (kinkPt < tj.EndPt[0] + 2) return -1;
3054  if (kinkPt > tj.EndPt[1] - 2) return -1;
3055 
3056  // This function requires knowledge of the DOF of the line fit
3057  if (nPtsFit < 3) return -1;
3058  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
3059  // need enough points to do a fit on each sideof the presumed kink point
3060  if (npwc < 2 * nPtsFit + 1) return -1;
3061 
3062  // The hit charge uncertainty is 0.12 - 0.15 (neglecting 2ndry interactions) for hadrons.
3063  // This translates into an error on the charge
3064  // asymmetry of about 0.07, or about 0.6 * the charge uncertainty
3065  double chgRMS = 0.07;
3066  // An additional contribution to the rms is the dependence on the DOF of the fit.
3067  // Apply a factor to the significance similar to (and simpler than) the Students t-distribution
3068  // This will increase the angle and charge error rms by 1.3 (1.05) when nPtsFit = 3 (8)
3069  double tFactor = 1 + 0.3 / double(nPtsFit - 2);
3070  chgRMS *= tFactor;
3071 
3072  // Fit the trajectory direction on the + side
3073  short fitDir = 1;
3074  TrajPoint tpPos;
3075  FitTraj(slc, tj, kinkPt, nPtsFit, fitDir, tpPos);
3076  if (tpPos.FitChi > 900) return -1;
3077  // repeat the trajectory fit on the - side
3078  fitDir = -1;
3079  TrajPoint tpNeg;
3080  FitTraj(slc, tj, kinkPt, nPtsFit, fitDir, tpNeg);
3081  if (tpNeg.FitChi > 900) return -1;
3082  double angErr = tpNeg.AngErr;
3083  if (tpPos.AngErr > angErr) angErr = tpPos.AngErr;
3084  angErr *= tFactor;
3085  double dang = DeltaAngle(tpPos.Ang, tpNeg.Ang);
3086  double dangSig = dang / angErr;
3087 
3088  double chgAsym = 0;
3089  double chgSig = 0;
3090  if (useChg) {
3091  // Sum the charge Neg and Pos, excluding the kinkPt
3092  double chgNeg = 0;
3093  unsigned short cntNeg = 0;
3094  for (unsigned short ipt = kinkPt - 1; ipt >= tj.EndPt[0]; --ipt) {
3095  auto& tp = tj.Pts[ipt];
3096  if (tp.Chg <= 0) continue;
3097  chgNeg += tp.Chg;
3098  ++cntNeg;
3099  if (cntNeg == nPtsFit) break;
3100  if (ipt == 0) break;
3101  } // ipt
3102  if (cntNeg != nPtsFit) {
3103  if (prt) mf::LogVerbatim("TC") << " KL: Bad cntNeg " << cntNeg << " != " << nPtsFit;
3104  return -1;
3105  }
3106  // now Pos
3107  double chgPos = 0;
3108  unsigned short cntPos = 0;
3109  for (unsigned short ipt = kinkPt + 1; ipt <= tj.EndPt[1]; ++ipt) {
3110  auto& tp = tj.Pts[ipt];
3111  if (tp.Chg <= 0) continue;
3112  chgPos += tp.Chg;
3113  ++cntPos;
3114  if (cntPos == nPtsFit) break;
3115  } // ipt
3116  if (cntPos != nPtsFit) {
3117  if (prt) mf::LogVerbatim("TC") << " KL: Bad cntPos " << cntPos << " != " << nPtsFit;
3118  return -1;
3119  }
3120  chgNeg /= (float)nPtsFit;
3121  chgPos /= (float)nPtsFit;
3122  // The charge asymmetry varies between 0 and 1;
3123  chgAsym = std::abs(chgPos - chgNeg) / (chgPos + chgNeg);
3124  // calculate the charge asymmetry significance
3125  chgSig = chgAsym / chgRMS;
3126  } // useChg
3127  double kinkSig = sqrt(dangSig * dangSig + chgSig * chgSig);
3128 
3129  if (prt) {
3130  mf::LogVerbatim myprt("TC");
3131  myprt << "KL: T" << tj.ID << " kinkPt " << PrintPos(tj.Pts[kinkPt]);
3132  myprt << " nPtsFit " << nPtsFit;
3133  myprt << " dang " << std::fixed << std::setprecision(3) << dang;
3134  myprt << std::fixed << std::setprecision(3) << " angErr " << angErr;
3135  myprt << std::setprecision(2) << " sig " << dangSig;
3136  myprt << " chgAsym " << chgAsym;
3137  myprt << " chgSig " << chgSig;
3138  myprt << " kinkSig " << kinkSig;
3139  }
3140  return (float)kinkSig;
3141  } // KinkSignificance
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:2080
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::string PrintPos(const Point2_t &pos)
Definition: Utils.cxx:6362
void FitTraj(TCSlice const &slc, Trajectory &tj, unsigned short originPt, unsigned short npts, short fitDir, TrajPoint &tpFit)
Definition: Utils.cxx:811
double DeltaAngle(double Ang1, double Ang2)
Definition: Utils.cxx:3324
void tca::LastEndMerge ( TCSlice slc,
CTP_t  inCTP 
)

Definition at line 3339 of file StepUtils.cxx.

References CreateTPFromTj(), tca::TCConfig::dbgAlg, tca::TCConfig::dbgMrg, DeadWireCount(), DeltaAngle(), kAtKink, kBragg, kKilled, kLastEndMerge, MakeVertexObsolete(), MergeAndStore(), PointTrajDOCA(), PosSep(), PrintPos(), pt1, pt2, slices, tcc, tca::TCSlice::tjs, TrajTrajDOCA(), tca::TCConfig::useAlg, and tca::TCSlice::vtxs.

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

3340  {
3341  // last ditch attempt to merge long straight broken trajectories by averaging
3342  // all points in the trajectory and applying tight angle and separation cuts.
3343  if (slc.tjs.size() < 2) return;
3344  if (!tcc.useAlg[kLastEndMerge]) return;
3345 
3346  bool prt = tcc.dbgAlg[kLastEndMerge];
3347 
3348  // create an averaged TP for each long Trajectory
3349  std::vector<TrajPoint> tjTP;
3350  for (auto& tj : slc.tjs) {
3351  if (tj.AlgMod[kKilled]) continue;
3352  if (tj.CTP != inCTP) continue;
3353  if (tj.Pts.size() < 10) continue;
3354  if (tj.MCSMom < 100) continue;
3355  auto tjtp = CreateTPFromTj(tj);
3356  if (tjtp.Chg < 0) continue;
3357  tjTP.push_back(tjtp);
3358  } // tj
3359  if (tjTP.size() < 2) return;
3360 
3361  if (prt) {
3362  mf::LogVerbatim myprt("TC");
3363  myprt << "inside LastEndMerge slice " << slices.size() - 1 << " inCTP " << inCTP << " tjTPs";
3364  for (auto& tjtp : tjTP)
3365  myprt << " T" << tjtp.Step;
3366  }
3367 
3368  for (unsigned short pt1 = 0; pt1 < tjTP.size() - 1; ++pt1) {
3369  auto& tp1 = tjTP[pt1];
3370  auto& tj1 = slc.tjs[tp1.Step - 1];
3371  if (tj1.AlgMod[kKilled]) continue;
3372  for (unsigned short pt2 = pt1 + 1; pt2 < tjTP.size(); ++pt2) {
3373  auto& tp2 = tjTP[pt2];
3374  auto& tj2 = slc.tjs[tp2.Step - 1];
3375  if (tj2.AlgMod[kKilled]) continue;
3376  float dang = DeltaAngle(tp1.Ang, tp2.Ang);
3377  // make an angle cut
3378  if (prt && dang < 0.5)
3379  mf::LogVerbatim("TC") << " T" << tj1.ID << " T" << tj2.ID << " dang " << dang;
3380  if (dang > 0.2) continue;
3381  // and an impact parameter cut
3382  unsigned short ipt1, ipt2;
3383  float ip12 = PointTrajDOCA(tp1.Pos[0], tp1.Pos[1], tp2);
3384  float ip21 = PointTrajDOCA(tp2.Pos[0], tp2.Pos[1], tp1);
3385  if (prt) mf::LogVerbatim("TC") << " ip12 " << ip12 << " ip21 " << ip21;
3386  if (ip12 > 15 && ip21 > 15) continue;
3387  float minSep = 100;
3388  // find the separation considering dead wires
3389  TrajTrajDOCA(slc, tj1, tj2, ipt1, ipt2, minSep, false);
3390  if (minSep == 100) continue;
3391  if (ipt1 >= tj1.Pts.size() || ipt2 >= tj2.Pts.size()) continue;
3392  float dwc = DeadWireCount(slc, tj1.Pts[ipt1], tj2.Pts[ipt2]);
3393  if (prt) mf::LogVerbatim("TC") << " minSep " << minSep << " dwc " << dwc;
3394  minSep -= dwc;
3395  if (minSep > 5) continue;
3396  // finally require that the proximate points are close to the ends
3397  float sep10 = PosSep(tj1.Pts[ipt1].Pos, tj1.Pts[tj1.EndPt[0]].Pos);
3398  float sep11 = PosSep(tj1.Pts[ipt1].Pos, tj1.Pts[tj1.EndPt[1]].Pos);
3399  if (sep10 > 5 && sep11 > 5) continue;
3400  unsigned short end1 = 0;
3401  if (sep11 < sep10) end1 = 1;
3402  float sep20 = PosSep(tj2.Pts[ipt2].Pos, tj2.Pts[tj2.EndPt[0]].Pos);
3403  float sep21 = PosSep(tj2.Pts[ipt2].Pos, tj2.Pts[tj2.EndPt[1]].Pos);
3404  if (sep20 > 5 && sep21 > 5) continue;
3405  unsigned short end2 = 0;
3406  if (sep21 < sep20) end2 = 1;
3407  // don't merge if there is a kink
3408  if (tj1.EndFlag[end1][kAtKink] || tj2.EndFlag[end2][kAtKink]) continue;
3409  if (prt) {
3410  mf::LogVerbatim myprt("TC");
3411  myprt << "LEM: T" << tj1.ID << "_" << PrintPos(tp1);
3412  if (tj1.VtxID[end1] > 0) myprt << "->2V" << tj1.VtxID[end1];
3413  myprt << " T" << tj2.ID << "_" << PrintPos(tp2);
3414  if (tj2.VtxID[end2] > 0) myprt << "->2V" << tj2.VtxID[end2];
3415  myprt << " dang " << std::setprecision(2) << dang << " ip12 " << ip12;
3416  myprt << " ip21 " << ip21;
3417  myprt << " minSep " << minSep;
3418  myprt << " end sep1 " << sep10 << " " << sep11;
3419  myprt << " end sep2 " << sep20 << " " << sep21;
3420  } // prt
3421  if (tj1.VtxID[end1] > 0) {
3422  auto& vx2 = slc.vtxs[tj1.VtxID[end1] - 1];
3423  MakeVertexObsolete("LEM", slc, vx2, true);
3424  }
3425  if (tj2.VtxID[end2] > 0 && tj2.VtxID[end2] != tj1.VtxID[end1]) {
3426  auto& vx2 = slc.vtxs[tj2.VtxID[end2] - 1];
3427  MakeVertexObsolete("LEM", slc, vx2, true);
3428  }
3429  // remove Bragg flags
3430  tj1.EndFlag[end1][kBragg] = false;
3431  tj2.EndFlag[end2][kBragg] = false;
3432  unsigned int it1 = tj1.ID - 1;
3433  unsigned int it2 = tj2.ID - 1;
3434  if (!MergeAndStore(slc, it1, it2, tcc.dbgMrg)) continue;
3435  // set the AlgMod bit
3436  auto& ntj = slc.tjs[slc.tjs.size() - 1];
3437  ntj.AlgMod[kLastEndMerge] = true;
3438  // create a tp for this tj and add it to the list
3439  auto tjtp = CreateTPFromTj(ntj);
3440  if (tjtp.Chg < 0) continue;
3441  if (prt) mf::LogVerbatim("TC") << " added T" << ntj.ID << " to the merge list";
3442  tjTP.push_back(tjtp);
3443  break;
3444  } // pt1
3445  } // pt1
3446 
3447  } // LastEndMerge
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:2698
TCConfig tcc
Definition: DataStructs.cxx:9
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2514
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:2531
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
TText * pt2
Definition: plot.C:64
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2095
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
bool MergeAndStore(TCSlice &slc, unsigned int itj1, unsigned int itj2, bool doPrt)
Definition: Utils.cxx:4521
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:579
TText * pt1
Definition: plot.C:61
bool TrajTrajDOCA(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2407
TrajPoint CreateTPFromTj(const Trajectory &tj)
Definition: StepUtils.cxx:3450
bool tca::LineLineIntersect ( Point3_t  p1,
Point3_t  p2,
Point3_t  p3,
Point3_t  p4,
Point3_t intersect,
float &  doca 
)

Definition at line 3100 of file PFPUtils.cxx.

References util::abs(), and PosSep().

Referenced by DotProd(), and PointDirIntersect().

3106  {
3107  /*
3108  Calculate the line segment PaPb that is the shortest route between
3109  two lines P1P2 and P3P4. Calculate also the values of mua and mub where
3110  Pa = P1 + mua (P2 - P1)
3111  Pb = P3 + mub (P4 - P3)
3112  Return FALSE if no solution exists.
3113  http://paulbourke.net/geometry/pointlineplane/
3114  */
3115 
3116  Point3_t p13, p43, p21;
3117  double d1343, d4321, d1321, d4343, d2121;
3118  double numer, denom;
3119  constexpr double EPS = std::numeric_limits<double>::min();
3120 
3121  p13[0] = p1[0] - p3[0];
3122  p13[1] = p1[1] - p3[1];
3123  p13[2] = p1[2] - p3[2];
3124  p43[0] = p4[0] - p3[0];
3125  p43[1] = p4[1] - p3[1];
3126  p43[2] = p4[2] - p3[2];
3127  if (std::abs(p43[0]) < EPS && std::abs(p43[1]) < EPS && std::abs(p43[2]) < EPS) return (false);
3128  p21[0] = p2[0] - p1[0];
3129  p21[1] = p2[1] - p1[1];
3130  p21[2] = p2[2] - p1[2];
3131  if (std::abs(p21[0]) < EPS && std::abs(p21[1]) < EPS && std::abs(p21[2]) < EPS) return (false);
3132 
3133  d1343 = p13[0] * p43[0] + p13[1] * p43[1] + p13[2] * p43[2];
3134  d4321 = p43[0] * p21[0] + p43[1] * p21[1] + p43[2] * p21[2];
3135  d1321 = p13[0] * p21[0] + p13[1] * p21[1] + p13[2] * p21[2];
3136  d4343 = p43[0] * p43[0] + p43[1] * p43[1] + p43[2] * p43[2];
3137  d2121 = p21[0] * p21[0] + p21[1] * p21[1] + p21[2] * p21[2];
3138 
3139  denom = d2121 * d4343 - d4321 * d4321;
3140  if (std::abs(denom) < EPS) return (false);
3141  numer = d1343 * d4321 - d1321 * d4343;
3142 
3143  double mua = numer / denom;
3144  double mub = (d1343 + d4321 * mua) / d4343;
3145 
3146  intersect[0] = p1[0] + mua * p21[0];
3147  intersect[1] = p1[1] + mua * p21[1];
3148  intersect[2] = p1[2] + mua * p21[2];
3149  Point3_t pb;
3150  pb[0] = p3[0] + mub * p43[0];
3151  pb[1] = p3[1] + mub * p43[1];
3152  pb[2] = p3[2] + mub * p43[2];
3153  doca = PosSep(intersect, pb);
3154  // average the closest points
3155  for (unsigned short xyz = 0; xyz < 3; ++xyz)
3156  intersect[xyz] += pb[xyz];
3157  for (unsigned short xyz = 0; xyz < 3; ++xyz)
3158  intersect[xyz] /= 2;
3159  return true;
3160  } // LineLineIntersect
std::array< double, 3 > Point3_t
Definition: DataStructs.h:39
constexpr auto abs(T v)
Returns the absolute value of the argument.
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
bool tca::LongPulseHit ( const recob::Hit hit)

Definition at line 4317 of file Utils.cxx.

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

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

4318  {
4319  // return true if the hit is in a long pulse indicating that it's position
4320  // and charge are not well known
4321  return ((hit.GoodnessOfFit() < 0 || hit.GoodnessOfFit() > 50) && hit.Multiplicity() > 5);
4322  }
float GoodnessOfFit() const
Degrees of freedom in the determination of the hit signal shape (-1 by default)
Definition: Hit.h:270
short int Multiplicity() const
How many hits could this one be shared with.
Definition: Hit.h:262
TrajPoint tca::MakeBareTP ( detinfo::DetectorPropertiesData const &  detProp,
const Point3_t pos,
CTP_t  inCTP 
)

Definition at line 3928 of file Utils.cxx.

References detinfo::DetectorPropertiesData::ConvertXToTicks(), tca::TrajPoint::CTP, DecodeCTP(), tca::TrajPoint::Dir, geo::WireReadoutGeom::Plane(), tca::TrajPoint::Pos, tcc, tca::TCConfig::unitsPerTick, geo::PlaneGeo::WireCoordinate(), and tca::TCConfig::wireReadoutGeom.

Referenced by AddPointsInRange(), DotProd(), FindParent(), FindShowerStart(), FitTP3Ds(), MakePFParticles(), Print3S(), PrintShowers(), PrintTP3Ds(), SetParent(), SetSection(), and ValidTwoPlaneMatch().

3931  {
3932  // A version to use when the 2D direction isn't required
3933  TrajPoint tp;
3934  tp.Pos = {{0, 0}};
3935  tp.Dir = {{0, 1}};
3936  tp.CTP = inCTP;
3937  geo::PlaneID planeID = DecodeCTP(inCTP);
3938 
3939  tp.Pos[0] = tcc.wireReadoutGeom->Plane(planeID).WireCoordinate(geo::Point_t{0, pos[1], pos[2]});
3940  tp.Pos[1] = detProp.ConvertXToTicks(pos[0], planeID) * tcc.unitsPerTick;
3941  return tp;
3942  } // MakeBareTP
const geo::WireReadoutGeom * wireReadoutGeom
Definition: DataStructs.h:568
double WireCoordinate(Point_t const &point) const
Returns the coordinate of the point on the plane, in wire units.
Definition: PlaneGeo.h:704
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:180
geo::PlaneID DecodeCTP(CTP_t CTP)
PlaneGeo const & Plane(TPCID const &tpcid, View_t view) const
Returns the specified wire.
TrajPoint tca::MakeBareTP ( detinfo::DetectorPropertiesData const &  detProp,
const Point3_t pos,
const Vector3_t dir,
CTP_t  inCTP 
)

Definition at line 3945 of file Utils.cxx.

References tca::TrajPoint::Ang, detinfo::DetectorPropertiesData::ConvertXToTicks(), tca::TrajPoint::CTP, DecodeCTP(), tca::TrajPoint::Delta, tca::TrajPoint::DeltaRMS, tca::TrajPoint::Dir, norm, geo::WireReadoutGeom::Plane(), tca::TrajPoint::Pos, sn, tcc, tca::TCConfig::unitsPerTick, geo::PlaneGeo::WireCoordinate(), and tca::TCConfig::wireReadoutGeom.

3949  {
3950  // Projects the space point defined by pos and dir into the CTP and returns
3951  // it in the form of a trajectory point. The TP Pos[0] is set to a negative
3952  // number if the point has an invalid wire position but doesn't return an
3953  // error if the position is on a dead wire. The projection of the direction
3954  // vector in CTP is stored in tp.Delta.
3955  TrajPoint tp;
3956  tp.Pos = {{-1, 0}};
3957  tp.Dir = {{0, 1}};
3958  tp.CTP = inCTP;
3959  geo::PlaneID planeID = DecodeCTP(inCTP);
3960 
3961  tp.Pos[0] = tcc.wireReadoutGeom->Plane(planeID).WireCoordinate(geo::Point_t{0, pos[1], pos[2]});
3962  tp.Pos[1] = detProp.ConvertXToTicks(pos[0], planeID) * tcc.unitsPerTick;
3963 
3964  // now find the direction if dir is defined
3965  if (dir[0] == 0 && dir[1] == 0 && dir[2] == 0) return tp;
3966 
3967  // Make a point at the origin and one 100 units away
3968  Point3_t ori3 = {{0.0, 0.0, 0.0}};
3969  Point3_t pos3 = {{100 * dir[0], 100 * dir[1], 100 * dir[2]}};
3970  // 2D position of ori3 and the pos3 projection
3971  std::array<double, 2> ori2;
3972  std::array<double, 2> pos2;
3973  std::array<double, 2> dir2;
3974  // the wire coordinates
3975  auto const& plane = tcc.wireReadoutGeom->Plane(planeID);
3976  ori2[0] = plane.WireCoordinate(geo::Point_t{0, ori3[1], ori3[2]});
3977  pos2[0] = plane.WireCoordinate(geo::Point_t{0, pos3[1], pos3[2]});
3978  // the time coordinates
3979  ori2[1] = detProp.ConvertXToTicks(ori3[0], planeID) * tcc.unitsPerTick;
3980  pos2[1] = detProp.ConvertXToTicks(pos3[0], planeID) * tcc.unitsPerTick;
3981 
3982  dir2[0] = pos2[0] - ori2[0];
3983  dir2[1] = pos2[1] - ori2[1];
3984 
3985  double norm = sqrt(dir2[0] * dir2[0] + dir2[1] * dir2[1]);
3986  tp.Dir[0] = dir2[0] / norm;
3987  tp.Dir[1] = dir2[1] / norm;
3988  tp.Ang = atan2(dir2[1], dir2[0]);
3989  tp.Delta = norm / 100;
3990 
3991  // The Orth vectors are not unit normalized so we need to correct for this
3992  double w0 = plane.WireCoordinate(geo::Point_t{0, 0, 0});
3993  // cosine-like component
3994  double cs = plane.WireCoordinate(geo::Point_t{0, 1, 0}) - w0;
3995  // sine-like component
3996  double sn = plane.WireCoordinate(geo::Point_t{0, 0, 1}) - w0;
3997  norm = sqrt(cs * cs + sn * sn);
3998  tp.Delta /= norm;
3999 
4000  // Stasb dt/dWire in DeltaRMS. This is used in PFPUtils/FitSection to find the
4001  // distance along a 3D line given the wire number in a plane
4002  tp.DeltaRMS = 100 / (pos2[0] - ori2[0]);
4003  return tp;
4004 
4005  } // MakeBareTP
const geo::WireReadoutGeom * wireReadoutGeom
Definition: DataStructs.h:568
std::array< double, 3 > Point3_t
Definition: DataStructs.h:39
double WireCoordinate(Point_t const &point) const
Returns the coordinate of the point on the plane, in wire units.
Definition: PlaneGeo.h:704
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
Float_t sn
Definition: plot.C:23
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:180
Float_t norm
TDirectory * dir
Definition: macro.C:5
geo::PlaneID DecodeCTP(CTP_t CTP)
PlaneGeo const & Plane(TPCID const &tpcid, View_t view) const
Returns the specified wire.
bool tca::MakeBareTrajPoint ( const TCSlice slc,
unsigned int  fromHit,
unsigned int  toHit,
TrajPoint tp 
)

Definition at line 4008 of file Utils.cxx.

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

Referenced by DotProd(), EndMerge(), FillGaps(), FindCloseTjs(), MergeShowerChain(), ParentFOM(), SignalBetween(), StartTraj(), TjDeltaRMS(), and UpdateVxEnvironment().

4012  {
4013  if (fromHit > slc.slHits.size() - 1) return false;
4014  if (toHit > slc.slHits.size() - 1) return false;
4015  auto& fhit = (*evt.allHits)[slc.slHits[fromHit].allHitsIndex];
4016  auto& thit = (*evt.allHits)[slc.slHits[toHit].allHitsIndex];
4017  CTP_t tCTP = EncodeCTP(fhit.WireID());
4018  return MakeBareTrajPoint((float)fhit.WireID().Wire,
4019  fhit.PeakTime(),
4020  (float)thit.WireID().Wire,
4021  thit.PeakTime(),
4022  tCTP,
4023  tp);
4024 
4025  } // MakeBareTrajPoint
bool MakeBareTrajPoint(const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
Definition: Utils.cxx:4059
unsigned int CTP_t
Definition: DataStructs.h:45
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:49
TCEvent evt
Definition: DataStructs.cxx:8
bool tca::MakeBareTrajPoint ( float  fromWire,
float  fromTick,
float  toWire,
float  toTick,
CTP_t  tCTP,
TrajPoint tp 
)

Definition at line 4028 of file Utils.cxx.

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

4034  {
4035  tp.CTP = tCTP;
4036  tp.Pos[0] = fromWire;
4037  tp.Pos[1] = tcc.unitsPerTick * fromTick;
4038  tp.Dir[0] = toWire - fromWire;
4039  tp.Dir[1] = tcc.unitsPerTick * (toTick - fromTick);
4040  double norm = sqrt(tp.Dir[0] * tp.Dir[0] + tp.Dir[1] * tp.Dir[1]);
4041  if (norm == 0) return false;
4042  tp.Dir[0] /= norm;
4043  tp.Dir[1] /= norm;
4044  tp.Ang = atan2(tp.Dir[1], tp.Dir[0]);
4045  return true;
4046  } // MakeBareTrajPoint
TCConfig tcc
Definition: DataStructs.cxx:9
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
Float_t norm
bool tca::MakeBareTrajPoint ( const Point2_t fromPos,
const Point2_t toPos,
TrajPoint tpOut 
)

Definition at line 4049 of file Utils.cxx.

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

4050  {
4051  tpOut.Pos = fromPos;
4052  tpOut.Dir = PointDirection(fromPos, toPos);
4053  tpOut.Ang = atan2(tpOut.Dir[1], tpOut.Dir[0]);
4054  return true;
4055 
4056  } // MakeBareTrajPoint
Vector2_t PointDirection(const Point2_t p1, const Point2_t p2)
Definition: Utils.cxx:4078
bool tca::MakeBareTrajPoint ( const TrajPoint tpIn1,
const TrajPoint tpIn2,
TrajPoint tpOut 
)

Definition at line 4059 of file Utils.cxx.

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

4060  {
4061  tpOut.CTP = tpIn1.CTP;
4062  tpOut.Pos = tpIn1.Pos;
4063  tpOut.Dir = PointDirection(tpIn1.Pos, tpIn2.Pos);
4064  tpOut.Ang = atan2(tpOut.Dir[1], tpOut.Dir[0]);
4065  return true;
4066  } // MakeBareTrajPoint
Vector2_t PointDirection(const Point2_t p1, const Point2_t p2)
Definition: Utils.cxx:4078
void tca::MakeHaloTj ( TCSlice slc,
Trajectory muTj,
bool  prt 
)

Definition at line 53 of file Utils.cxx.

References util::abs(), tca::Trajectory::AlgMod, tca::Trajectory::ChgRMS, tca::Trajectory::CTP, DefineHitPos(), tca::Trajectory::EndPt, evt, FindCloseHits(), GetPFPIndex(), GetSliceIndex(), tca::TCEvent::globalT_UID, 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().

54  {
55  // Creates a "halo trajectory" around a muon tj consisting of hits and trajectories
56  // that are within MuonTag[4] distance. The halo tj is a virtual clone of muTj in the
57  // sense that it has the same number of points and the same start and end points.
58 
59  if (tcc.muonTag.size() < 5) return;
60  if (tcc.muonTag[4] <= 0) return;
61  if (!tcc.useAlg[kHaloTj]) return;
62 
63  if (muTj.PDGCode != 13) return;
64 
65  // check for daughter delta-rays
66  std::vector<int> dtrs;
67  for (auto& dtj : slc.tjs) {
68  if (dtj.AlgMod[kKilled]) continue;
69  if (dtj.ParentID != muTj.ID) continue;
70  dtrs.push_back(dtj.ID);
71  if (!dtj.AlgMod[kDeltaRay]) continue;
72  if (prt) mf::LogVerbatim("TC") << "MakeHaloTj: Killing delta-ray T" << dtj.ID;
73  // Kill a delta-ray PFParticle?
74  if (dtj.AlgMod[kMat3D]) {
75  unsigned short pfpIndex = GetPFPIndex(slc, dtj.ID);
76  if (pfpIndex == USHRT_MAX) {
77  if (prt) mf::LogVerbatim("TC") << " No PFP found for 3D-matched delta-ray";
78  }
79  else {
80  auto& pfp = slc.pfps[pfpIndex];
81  if (prt) mf::LogVerbatim("TC") << " Killing delta-ray PFParticle P" << pfp.UID;
82  pfp.ID = 0;
83  // correct the parent -> daughter assn
84  if (pfp.ParentUID > 0) {
85  auto parentIndx = GetSliceIndex("P", pfp.ParentUID);
86  if (parentIndx.first != USHRT_MAX) {
87  auto& parent = slices[parentIndx.first].pfps[parentIndx.second];
88  std::vector<int> newDtrUIDs;
89  for (auto uid : parent.DtrUIDs)
90  if (uid != dtj.UID) newDtrUIDs.push_back(uid);
91  parent.DtrUIDs = newDtrUIDs;
92  } // parent found
93  } // correct the parent
94  } // kill PFParticle
95  } // kill
96  MakeTrajectoryObsolete(slc, (unsigned int)(dtj.ID - 1));
97  } // dtj
98 
99  // make a copy
100  Trajectory tj;
101  tj.CTP = muTj.CTP;
102  // We can't use StoreTraj so variables need to be defined here
103  tj.ID = slc.tjs.size() + 1;
104  tj.WorkID = muTj.WorkID;
105  // increment the global ID
106  ++evt.globalT_UID;
107  tj.UID = evt.globalT_UID;
108  tj.PDGCode = 11;
109  tj.Pass = muTj.Pass;
110  tj.StepDir = muTj.StepDir;
111  tj.StartEnd = muTj.StartEnd;
112  tj.TotChg = 0;
113  tj.ChgRMS = 0;
114  tj.EndPt[0] = 0;
115  tj.ParentID = muTj.ID;
116  tj.AlgMod.reset();
117  tj.AlgMod[kHaloTj] = true;
118  // start a list of tjs that have points near the muon
119  std::vector<int> closeTjs;
120  for (unsigned short ipt = muTj.EndPt[0]; ipt <= muTj.EndPt[1]; ++ipt) {
121  auto tp = muTj.Pts[ipt];
122  tp.Hits.resize(0);
123  tp.UseHit.reset();
124  tp.Chg = 0;
125  tp.AveChg = 0;
126  tp.ChgPull = 0;
127  tp.Delta = 0;
128  tp.DeltaRMS = 0;
129  tp.FitChi = 0;
130  tp.NTPsFit = 0;
131  float window = tcc.muonTag[4];
132  if (tp.Dir[0] != 0) window *= std::abs(1 / tp.Dir[0]);
133  if (!FindCloseHits(slc, tp, window, kAllHits)) continue;
134  // add unused hits to the point and look for close tjs
135  bool hitsAdded = false;
136  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
137  unsigned int iht = tp.Hits[ii];
138  auto inTraj = slc.slHits[iht].InTraj;
139  if (inTraj < 0) continue;
140  if (inTraj == 0) {
141  tp.UseHit[ii] = true;
142  slc.slHits[iht].InTraj = tj.ID;
143  hitsAdded = true;
144  }
145  else {
146  // add to the closeTjs list
147  if (inTraj != muTj.ID &&
148  std::find(closeTjs.begin(), closeTjs.end(), inTraj) == closeTjs.end())
149  closeTjs.push_back(inTraj);
150  }
151  } // ii
152  if (hitsAdded) {
153  DefineHitPos(slc, tp);
154  tp.Delta = PointTrajDOCA(tp.HitPos[0], tp.HitPos[1], tp);
155  tj.TotChg += tp.Chg;
156  tj.Pts.push_back(tp);
157  } // hitsAdded
158  } // ipt
159  if (tj.Pts.empty()) return;
160  tj.EndPt[1] = tj.Pts.size() - 1;
161  if (prt) {
162  mf::LogVerbatim myprt("TC");
163  myprt << "MHTj: T" << muTj.ID << " npts " << tj.Pts.size() << " close";
164  for (auto tid : closeTjs)
165  myprt << " T" << tid;
166  myprt << "\n";
167  PrintTrajectory("DM", slc, tj, USHRT_MAX);
168  }
169  slc.tjs.push_back(tj);
170  } // MakeHaloTj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
void PrintTrajectory(std::string someText, const TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:6035
constexpr auto abs(T v)
Returns the absolute value of the argument.
float PointTrajDOCA(float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2524
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1791
void MakeTrajectoryObsolete(TCSlice &slc, unsigned int itj)
Definition: Utils.cxx:2138
unsigned short GetPFPIndex(const TCSlice &slc, int tjID)
Definition: Utils.cxx:1038
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
std::vector< short > muonTag
Definition: DataStructs.h:546
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:4942
TCEvent evt
Definition: DataStructs.cxx:8
bool FindCloseHits(TCSlice const &slc, TrajPoint &tp, float const maxDelta, HitStatus_t hitRequest)
Definition: Utils.cxx:2837
void tca::MakeJunkTjVertices ( TCSlice slc,
const CTP_t inCTP 
)
bool tca::MakeJunkTraj ( TCSlice slc,
std::vector< unsigned int >  tHits 
)

Definition at line 4146 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::TCEvent::allHits, tca::Trajectory::CTP, tca::TCConfig::dbgAlg, debug, EncodeCTP(), tca::Trajectory::EndPt, evt, FindAlongTrans(), FitTraj(), tca::DebugStuff::Hit, tca::detail::SortEntry::index, tca::Trajectory::IsGood, kEnvUnusedHits, kJunkTj, LongPulseHit(), tca::TCConfig::minPts, tca::Trajectory::NeedsUpdate, PrintTrajectory(), tca::Trajectory::Pts, tca::TCSlice::slHits, StartTraj(), StoreTraj(), sum, tcc, tca::Trajectory::TotChg, tca::TCConfig::unitsPerTick, UpdateTraj(), tca::TCConfig::useAlg, tca::detail::SortEntry::val, and tca::detail::valsDecreasing().

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

4147  {
4148  if (!tcc.useAlg[kJunkTj]) return false;
4149  // Make a crummy trajectory using the provided hits
4150 
4151  if (tHits.size() < 2) return false;
4152 
4153  bool prt = false;
4154  if (tcc.dbgAlg[kJunkTj]) {
4155  for (unsigned short ii = 0; ii < tHits.size(); ++ii) {
4156  if (slc.slHits[tHits[ii]].allHitsIndex == debug.Hit) {
4157  prt = true;
4158  break;
4159  }
4160  } // ii
4161  if (prt) std::cout << "MakeJunkTraj found debug hit\n";
4162  } // tcc.dbgAlg[kJunkTj]
4163 
4164  // Start the trajectory using the first and last hits to
4165  // define a starting direction. Use the last pass settings
4166  Trajectory work;
4167  unsigned short pass = tcc.minPts.size() - 1;
4168  if (!StartTraj(slc, work, tHits[0], tHits[tHits.size() - 1], pass)) return false;
4169  // make a TP for every hit
4170  work.Pts.resize(tHits.size());
4171  // and put a hit into each one
4172  for (unsigned short ii = 0; ii < tHits.size(); ++ii) {
4173  auto& tp = work.Pts[ii];
4174  unsigned int iht = tHits[ii];
4175  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
4176  tp.CTP = EncodeCTP(hit.WireID());
4177  if (tp.CTP != work.CTP) return false;
4178  tp.Hits.push_back(iht);
4179  tp.UseHit[0] = true;
4180  // don't use DefineHitPos here because the angle isn't really known yet. Just
4181  // define enough information to do a fit
4182  tp.HitPos[0] = hit.WireID().Wire;
4183  tp.HitPos[1] = hit.PeakTime() * tcc.unitsPerTick;
4184  tp.HitPosErr2 = 100;
4185  tp.Chg = hit.Integral();
4186  tp.Step = ii;
4187  tp.NTPsFit = tHits.size();
4188  // flag long-pulse hits
4189  if (LongPulseHit(hit)) tp.Environment[kEnvUnusedHits] = true;
4190  } // ii
4191  work.EndPt[0] = 0;
4192  work.EndPt[1] = tHits.size() - 1;
4193  // do an initial fit. The fit results are put in the last TP.
4194  FitTraj(slc, work);
4195  auto& lastTP = work.Pts.back();
4196  // Prepare to sort along the general direction. First find the
4197  // along and transverse position (Delta) of each TP and calculate DeltaRMS
4198  double sum = 0.;
4199  double sum2 = 0.;
4200  for (auto& tp : work.Pts) {
4201  Point2_t at;
4202  FindAlongTrans(lastTP.Pos, lastTP.Dir, tp.HitPos, at);
4203  sum += at[1];
4204  sum2 += at[1] * at[1];
4205  // store the along distance in AveChg for now
4206  tp.AveChg = at[0];
4207  tp.Delta = at[1];
4208  if (tp.Step != lastTP.Step) {
4209  tp.FitChi = lastTP.FitChi;
4210  tp.Dir = lastTP.Dir;
4211  tp.Ang = lastTP.Ang;
4212  tp.Pos[0] = lastTP.Pos[0] + at[0] * lastTP.Dir[0];
4213  tp.Pos[1] = lastTP.Pos[1] + at[0] * lastTP.Dir[1];
4214  }
4215  } // tp
4216  double npts = tHits.size();
4217  sum /= npts;
4218  double arg = sum2 - npts * sum * sum;
4219  if (arg <= 0) return false;
4220  float rms = sqrt(arg) / (npts - 1);
4221  // apply a loose Delta cut
4222  float transCut = sum + 3 * rms;
4223  std::vector<SortEntry> sortVec;
4224  SortEntry se;
4225  work.TotChg = 0;
4226  work.NeedsUpdate = false;
4227  for (auto& tp : work.Pts) {
4228  if (tp.Delta > transCut && !tp.Environment[kEnvUnusedHits]) {
4229  work.NeedsUpdate = true;
4230  continue;
4231  }
4232  se.index = tp.Step;
4233  se.val = tp.AveChg;
4234  sortVec.push_back(se);
4235  tp.DeltaRMS = rms;
4236  work.TotChg += tp.Chg;
4237  } // tp
4238  if (sortVec.size() < 3) return false;
4239  std::sort(sortVec.begin(), sortVec.end(), valsDecreasing);
4240  std::vector<TrajPoint> ntps(sortVec.size());
4241  for (unsigned short ipt = 0; ipt < sortVec.size(); ++ipt)
4242  ntps[ipt] = work.Pts[sortVec[ipt].index];
4243  work.Pts = ntps;
4244  sum = work.TotChg / (double)ntps.size();
4245  if (work.NeedsUpdate) {
4246  work.EndPt[1] = work.Pts.size() - 1;
4247  UpdateTraj(slc, work);
4248  } // needs update
4249  work.AlgMod[kJunkTj] = true;
4250  work.IsGood = true;
4251  if (prt) { PrintTrajectory("MJT", slc, work, USHRT_MAX); }
4252  // Store it
4253  return StoreTraj(slc, work);
4254  } // MakeJunkTraj
void FitTraj(TCSlice const &slc, Trajectory &tj)
Definition: Utils.cxx:798
void UpdateTraj(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:705
TCConfig tcc
Definition: DataStructs.cxx:9
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:3066
void PrintTrajectory(std::string someText, const TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:6035
bool StartTraj(TCSlice const &slc, Trajectory &tj, unsigned int fromhit, unsigned int tohit, unsigned short pass)
Definition: Utils.cxx:4858
bool StoreTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:1074
bool LongPulseHit(const recob::Hit &hit)
Definition: Utils.cxx:4317
unsigned int Hit
set to the hit index in evt.allHits if a Plane:Wire:Tick match is found
Definition: DebugStruct.h:26
std::array< float, 2 > Point2_t
Definition: DataStructs.h:41
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
DebugStuff debug
Definition: DebugStruct.cxx:4
std::vector< unsigned short > minPts
min number of Pts required to make a trajectory
Definition: DataStructs.h:557
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:578
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:579
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
bool valsDecreasing(const SortEntry &c1, const SortEntry &c2)
Definition: Utils.cxx:39
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:49
TCEvent evt
Definition: DataStructs.cxx:8
Double_t sum
Definition: plot.C:31
void tca::MakeJunkVertices ( TCSlice slc,
const CTP_t inCTP 
)

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

32  {
33  // Vertices between poorly reconstructed tjs (especially junk slc) and normal
34  // tjs can fail because the junk tj trajectory parameters are inaccurate. This function
35  // uses proximity and not pointing to make junk vertices
36  // Don't use this if standard vertex reconstruction is disabled
37  if (tcc.vtx2DCuts[0] <= 0) return;
38  if (!tcc.useAlg[kJunkVx]) return;
39  if (slc.tjs.size() < 2) return;
40 
41  // Look for tjs that are within maxSep of the end of a Tj
42  constexpr float maxSep = 4;
43 
44  geo::PlaneID planeID = DecodeCTP(inCTP);
45  bool prt = (tcc.dbgVxJunk && tcc.dbgSlc);
46  if (prt) {
47  mf::LogVerbatim("TC") << "MakeJunkVertices: prt set for plane " << planeID.Plane
48  << " maxSep btw tjs " << maxSep;
49  }
50 
51  // make a template vertex
52  VtxStore junkVx;
53  junkVx.CTP = inCTP;
54  junkVx.Topo = 9;
55  junkVx.Stat[kJunkVx] = true;
56  junkVx.Stat[kFixed] = true;
57  // set an invalid ID
58  junkVx.ID = USHRT_MAX;
59  // put in generous errors
60  junkVx.PosErr = {{2.0, 2.0}};
61  // define a minimal score so it won't get clobbered
62  junkVx.Score = tcc.vtx2DCuts[7] + 0.1;
63 
64  // look at both ends of long tjs
65  for (unsigned short it1 = 0; it1 < slc.tjs.size() - 1; ++it1) {
66  auto& tj1 = slc.tjs[it1];
67  if (tj1.AlgMod[kKilled] || tj1.AlgMod[kHaloTj]) continue;
68  if (tj1.SSID > 0 || tj1.AlgMod[kShowerLike]) continue;
69  if (tj1.CTP != inCTP) continue;
70  if (tj1.AlgMod[kJunkTj]) continue;
71  if (TrajLength(tj1) < 10) continue;
72  if (tj1.MCSMom < 100) continue;
73  for (unsigned short end1 = 0; end1 < 2; ++end1) {
74  // existing vertex?
75  if (tj1.VtxID[end1] > 0) continue;
76  auto& tp1 = tj1.Pts[tj1.EndPt[end1]];
77  // get a list of tjs in this vicinity
78  auto tjlist = FindCloseTjs(slc, tp1, tp1, maxSep);
79  if (tjlist.empty()) continue;
80  // set to an invalid ID
81  junkVx.ID = USHRT_MAX;
82  for (auto tj2id : tjlist) {
83  auto& tj2 = slc.tjs[tj2id - 1];
84  if (tj2.CTP != inCTP) continue;
85  if (tj2id == tj1.ID) continue;
86  if (tj2.SSID > 0 || tj2.AlgMod[kShowerLike]) continue;
87  float close = maxSep;
88  unsigned short closeEnd = USHRT_MAX;
89  for (unsigned short end2 = 0; end2 < 2; ++end2) {
90  auto& tp2 = tj2.Pts[tj2.EndPt[end2]];
91  float sep = PosSep(tp1.Pos, tp2.Pos);
92  if (sep < close) {
93  close = sep;
94  closeEnd = end2;
95  } // sep
96  } // end2
97  if (closeEnd > 1) continue;
98  auto& tp2 = tj2.Pts[tj2.EndPt[closeEnd]];
99  bool signalBetween = SignalBetween(tp1, tp2, 0.8);
100  if (!signalBetween) continue;
101  if (junkVx.ID == USHRT_MAX) {
102  // define the new vertex
103  junkVx.ID = slc.vtxs.size() + 1;
104  junkVx.Pos = tp1.Pos;
105  } // new vertex
106  tj2.VtxID[closeEnd] = junkVx.ID;
107  tj1.VtxID[end1] = junkVx.ID;
108  } // tjid
109  if (junkVx.ID == USHRT_MAX) continue;
110  if (!StoreVertex(slc, junkVx)) {
111  mf::LogVerbatim("TC") << "MJV: StoreVertex failed";
112  for (auto& tj : slc.tjs) {
113  if (tj.AlgMod[kKilled]) continue;
114  if (tj.VtxID[0] == junkVx.ID) tj.VtxID[0] = 0;
115  if (tj.VtxID[1] == junkVx.ID) tj.VtxID[1] = 0;
116  } // tj
117  continue;
118  } // StoreVertex failed
119  if (prt) {
120  mf::LogVerbatim("TC") << " New junk 2V" << junkVx.ID << " at " << std::fixed
121  << std::setprecision(1) << junkVx.Pos[0] << ":"
122  << junkVx.Pos[1] / tcc.unitsPerTick;
123  } // prt
124  junkVx.ID = USHRT_MAX;
125  } // end1
126  } // it1
127 
128  } // MakeJunkVertices
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
vertex position fixed manually - no fitting done
Definition: DataStructs.h:88
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:1908
bool SignalBetween(const TrajPoint &tp1, const TrajPoint &tp2, const float MinWireSignalFraction)
Definition: Utils.cxx:1779
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
in close()
float TrajLength(const Trajectory &tj)
Definition: Utils.cxx:2582
geo::PlaneID DecodeCTP(CTP_t CTP)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:541
std::vector< int > FindCloseTjs(const TCSlice &slc, const TrajPoint &fromTp, const TrajPoint &toTp, const float &maxDelta)
Definition: Utils.cxx:2908
void tca::MakePFParticles ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
TCSlice slc,
std::vector< MatchStruct matVec,
unsigned short  matVec_Iter 
)

Definition at line 266 of file PFPUtils.cxx.

References CanSection(), CreatePFP(), tca::TCConfig::dbgPFP, tca::TCConfig::dbgSlc, debug, EncodeCTP(), util::end(), evt, FilldEdx(), FillGaps3D(), Find3DRecoRange(), FitSection(), for(), tca::TCEvent::global3V_UID, tca::Vtx3Store::ID, InsideTPC(), kAtKink, kCanSection, kEnvOverlap, kJunk3D, kNeedsUpdate, kOutFV, kSmallAngle, kTP3DBad, kTP3DGood, MakeBareTP(), MakeTP3Ds(), tca::TCSlice::mallTraj, tca::TCConfig::match3DCuts, MaxTjLen(), MCSMom(), tca::DebugStuff::MVI, tca::DebugStuff::MVI_Iter, tca::TCSlice::nPlanes, PDGCodeVote(), tca::TCSlice::pfps, PosAtEnd(), tca::Vtx3Store::Primary, PrintTP3Ds(), ReconcileTPs(), ReconcileVertices(), Recover(), ReSection(), tca::Vtx3Store::Score, SortSection(), StorePFP(), tcc, tca::TCSlice::tjs, tca::Vtx3Store::TPCID, geo::TPCID::TPCID(), tca::Vtx3Store::UID, ValidTwoPlaneMatch(), tca::TCSlice::vtx3s, tca::Vtx3Store::Vx2ID, tca::Vtx3Store::Wire, tca::Vtx3Store::X, tca::Vtx3Store::Y, and tca::Vtx3Store::Z.

Referenced by FindPFParticles().

271  {
272  // Makes PFParticles using Tjs listed in matVec
273  if (matVec.empty()) return;
274 
275  bool prt = (tcc.dbgPFP && tcc.dbgSlc);
276 
277  // create a PFParticle for each valid match combination
278  for (std::size_t indx = 0; indx < matVec.size(); ++indx) {
279  // tone down the level of printing in ReSection
280  bool foundMVI = (tcc.dbgPFP && indx == debug.MVI && matVec_Iter == debug.MVI_Iter);
281  if (foundMVI) prt = true;
282  auto& ms = matVec[indx];
283  if (foundMVI) {
284  std::cout << "found MVI " << indx << " in MakePFParticles ms.Count = " << ms.Count << "\n";
285  }
286  // ignore dead matches
287  if (ms.Count == 0) continue;
288  // count the number of TPs that are available (not already 3D-matched) and used in a pfp
289  float npts = 0;
290  for (std::size_t itj = 0; itj < ms.TjIDs.size(); ++itj) {
291  auto& tj = slc.tjs[ms.TjIDs[itj] - 1];
292  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt)
293  if (tj.Pts[ipt].InPFP == 0) ++npts;
294  } // tjID
295  // Create a vector of PFPs for this match so that we can split it later on if a kink is found
296  std::vector<PFPStruct> pfpVec(1);
297  pfpVec[0] = CreatePFP(slc);
298  // Define the starting set of tjs that were matched. TPs from other tjs may be added later
299  pfpVec[0].TjIDs = ms.TjIDs;
300  pfpVec[0].MVI = indx;
301  // fill the TP3D points using the 2D trajectory points for Tjs in TjIDs. All
302  // points are put in one section
303  if (!MakeTP3Ds(detProp, slc, pfpVec[0], foundMVI)) {
304  if (foundMVI) mf::LogVerbatim("TC") << " MakeTP3Ds failed. Too many points already used ";
305  continue;
306  }
307  // fit all the points to get the general direction
308  if (!FitSection(detProp, slc, pfpVec[0], 0)) continue;
309  if (pfpVec[0].SectionFits[0].ChiDOF > 500 && !pfpVec[0].Flags[kSmallAngle]) {
310  if (foundMVI)
311  mf::LogVerbatim("TC") << " crazy high ChiDOF P" << pfpVec[0].ID << " "
312  << pfpVec[0].SectionFits[0].ChiDOF << "\n";
313  Recover(detProp, slc, pfpVec[0], foundMVI);
314  continue;
315  }
316  // sort the points by the distance along the general direction vector
317  if (!SortSection(pfpVec[0], 0)) continue;
318  // define a junk pfp to be short with low MCSMom. These are likely to be shower-like
319  // pfps. A simple 3D line fit will be done. No attempt will be made to reconstruct it
320  // in sections or to look for kinks
321  npts = pfpVec[0].TP3Ds.size();
322  pfpVec[0].AlgMod[kJunk3D] = (npts < 20 && MCSMom(slc, pfpVec[0].TjIDs) < 50) || (npts < 10);
323  if (prt) {
324  auto& pfp = pfpVec[0];
325  mf::LogVerbatim myprt("TC");
326  myprt << " indx " << matVec_Iter << "/" << indx << " Count " << std::setw(5)
327  << (int)ms.Count;
328  myprt << " P" << pfpVec[0].ID;
329  myprt << " ->";
330  for (auto& tjid : pfp.TjIDs)
331  myprt << " T" << tjid;
332  myprt << " projInPlane";
333  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
334  CTP_t inCTP = EncodeCTP(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
335  auto tp = MakeBareTP(detProp, pfp.SectionFits[0].Pos, pfp.SectionFits[0].Dir, inCTP);
336  myprt << " " << std::setprecision(2) << tp.Delta;
337  } // plane
338  myprt << " maxTjLen " << (int)MaxTjLen(slc, pfp.TjIDs);
339  myprt << " MCSMom " << MCSMom(slc, pfp.TjIDs);
340  myprt << " PDGCodeVote " << PDGCodeVote(clockData, detProp, slc, pfp);
341  myprt << " nTP3Ds " << pfp.TP3Ds.size();
342  myprt << " Reco3DRange "
343  << Find3DRecoRange(slc, pfp, 0, (unsigned short)tcc.match3DCuts[3], 1);
344  } // prt
345  if (foundMVI) { PrintTP3Ds(clockData, detProp, "FF", slc, pfpVec[0], -1); }
346  for (unsigned short ip = 0; ip < pfpVec.size(); ++ip) {
347  auto& pfp = pfpVec[ip];
348  // set the end flag bits
349  geo::TPCID tpcid;
350  for (unsigned short end = 0; end < 2; ++end) {
351  // first set them all to 0
352  pfp.EndFlag[end].reset();
353  auto pos = PosAtEnd(pfp, end);
354  if (!InsideTPC(pos, tpcid)) pfp.EndFlag[end][kOutFV] = true;
355  } // end
356  // Set kink flag and create a vertex between this pfp and the previous one that was stored
357  if (ip > 0) {
358  pfp.EndFlag[0][kAtKink] = true;
359  Vtx3Store vx3;
360  vx3.TPCID = pfp.TPCID;
361  vx3.X = pfp.TP3Ds[0].Pos[0];
362  vx3.Y = pfp.TP3Ds[0].Pos[1];
363  vx3.Z = pfp.TP3Ds[0].Pos[2];
364  // TODO: Errors, Score?
365  vx3.Score = 100;
366  vx3.Vx2ID.resize(slc.nPlanes);
367  vx3.Wire = -2;
368  vx3.ID = slc.vtx3s.size() + 1;
369  vx3.Primary = false;
370  ++evt.global3V_UID;
371  vx3.UID = evt.global3V_UID;
372  slc.vtx3s.push_back(vx3);
373  pfp.Vx3ID[0] = vx3.ID;
374  auto& prevPFP = slc.pfps[slc.pfps.size() - 1];
375  prevPFP.Vx3ID[1] = vx3.ID;
376  } // ip > 0
377  // check for a valid two-plane match with a Tj in the third plane for long pfps.
378  // For short pfps, it is possible that a Tj would be too short to be reconstructed
379  // in the third plane.
380  if (pfp.TjIDs.size() == 2 && slc.nPlanes == 3 && pfp.TP3Ds.size() > 20 &&
381  !ValidTwoPlaneMatch(detProp, slc, pfp)) {
382  continue;
383  }
384  // Skip this combination if it isn't reconstructable in 3D
385  if (Find3DRecoRange(slc, pfp, 0, (unsigned short)tcc.match3DCuts[3], 1) == USHRT_MAX)
386  continue;
387  // See if it possible to reconstruct in more than one section
388  pfp.Flags[kCanSection] = CanSection(slc, pfp);
389  // Do a fit in multiple sections if the initial fit is poor
390  if (pfp.SectionFits[0].ChiDOF < tcc.match3DCuts[5]) {
391  // Good fit with one section
392  pfp.Flags[kNeedsUpdate] = false;
393  }
394  else if (pfp.Flags[kCanSection]) {
395  if (!ReSection(detProp, slc, pfp, foundMVI)) continue;
396  } // CanSection
397  if (foundMVI) { PrintTP3Ds(clockData, detProp, "RS", slc, pfp, -1); }
398  // FillGaps3D looks for gaps in the TP3Ds vector caused by broken trajectories and
399  // inserts new TP3Ds if there are hits in the gaps. This search is only done in a
400  // plane if the projection of the pfp results in a large angle where 2D reconstruction
401  // is likely to be poor - not true for TCWork2
402  FillGaps3D(clockData, detProp, slc, pfp, foundMVI);
403  // Check the TP3D -> TP assn, resolve conflicts and set TP -> InPFP
404  if (!ReconcileTPs(slc, pfp, foundMVI)) continue;
405  // Look for mis-placed 2D and 3D vertices
406  ReconcileVertices(slc, pfp, foundMVI);
407  // Set isGood
408  for (auto& tp3d : pfp.TP3Ds) {
409  if (tp3d.Flags[kTP3DBad]) continue;
410  auto& tp = slc.tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
411  if (tp.Environment[kEnvOverlap]) tp3d.Flags[kTP3DGood] = false;
412  } // tp3d
413  FilldEdx(clockData, detProp, slc, pfp);
414  pfp.PDGCode = PDGCodeVote(clockData, detProp, slc, pfp);
415  if (tcc.dbgPFP && pfp.MVI == debug.MVI)
416  PrintTP3Ds(clockData, detProp, "STORE", slc, pfp, -1);
417  if (!StorePFP(slc, pfp)) break;
418  } // ip (iterate over split pfps)
419  } // indx (iterate over matchVec entries)
420  slc.mallTraj.resize(0);
421  } // MakePFParticles
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3381
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool InsideTPC(const Point3_t &pos, geo::TPCID &inTPCID)
Definition: PFPUtils.cxx:3045
bool SortSection(PFPStruct &pfp, unsigned short sfIndex)
Definition: PFPUtils.cxx:1999
TCConfig tcc
Definition: DataStructs.cxx:9
for(Int_t i=0;i< nentries;i++)
Definition: comparison.C:30
PFPStruct CreatePFP(const TCSlice &slc)
Definition: PFPUtils.cxx:2802
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3257
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
bool CanSection(const TCSlice &slc, const PFPStruct &pfp)
Definition: PFPUtils.cxx:1323
unsigned int MVI
MatchVec Index for detailed 3D matching.
Definition: DebugStruct.h:29
void FilldEdx(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp)
Definition: PFPUtils.cxx:2583
void ReconcileVertices(TCSlice &slc, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:1626
float MaxTjLen(const TCSlice &slc, std::vector< int > &tjIDs)
Definition: Utils.cxx:2567
unsigned short Find3DRecoRange(const TCSlice &slc, const PFPStruct &pfp, unsigned short fromPt, unsigned short min2DPts, short dir)
Definition: PFPUtils.cxx:1338
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
void ReconcileTPs(TCSlice &slc)
Definition: PFPUtils.cxx:470
void FillGaps3D(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:1720
int PDGCodeVote(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp)
Definition: PFPUtils.cxx:3312
DebugStuff debug
Definition: DebugStruct.cxx:4
bool MakeTP3Ds(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:2097
bool FitSection(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, unsigned short sfIndex)
Definition: PFPUtils.cxx:1391
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const Point3_t &pos, CTP_t inCTP)
Definition: Utils.cxx:3928
bool ReSection(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:1097
std::vector< float > match3DCuts
3D matching cuts
Definition: DataStructs.h:551
The data type to uniquely identify a TPC.
Definition: geo_types.h:306
void Recover(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:2059
bool ValidTwoPlaneMatch(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const PFPStruct &pfp)
Definition: PFPUtils.cxx:1771
unsigned int CTP_t
Definition: DataStructs.h:45
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:49
unsigned short MVI_Iter
MVI iteration - see FindPFParticles.
Definition: DebugStruct.h:30
TCEvent evt
Definition: DataStructs.cxx:8
bool StorePFP(TCSlice &slc, PFPStruct &pfp)
Definition: PFPUtils.cxx:2979
void PrintTP3Ds(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, std::string someText, const TCSlice &slc, const PFPStruct &pfp, short printPts)
Definition: PFPUtils.cxx:3356
void tca::MakePFPTjs ( TCSlice slc)

Definition at line 508 of file PFPUtils.cxx.

References CloseEnd(), geo::CryostatID::Cryostat, tca::TCConfig::dbgPFP, DecodeCTP(), EncodeCTP(), util::end(), evt, kMakePFPTjs, kMat3D, kTP3DBad, MakeTrajectoryObsolete(), MCSMom(), tca::TCSlice::nPlanes, tca::TCSlice::pfps, geo::PlaneID::Plane, StoreTraj(), tcc, tca::TCSlice::tjs, geo::TPCID::TPC, tca::TCSlice::TPCID, tca::TCConfig::useAlg, tca::TCSlice::vtx3s, tca::TCSlice::vtxs, and tca::TCEvent::WorkID.

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

509  {
510  // This function clobbers all of the tjs that are used in TP3Ds in the pfp and replaces
511  // them with new tjs that have a consistent set of TPs to prepare for putting them
512  // into the event. Note that none of the Tjs are attached to 2D vertices.
513  if (!tcc.useAlg[kMakePFPTjs]) return;
514 
515  // kill trajectories
516  std::vector<int> killme;
517  for (auto& pfp : slc.pfps) {
518  if (pfp.ID <= 0) continue;
519  for (auto& tp3d : pfp.TP3Ds) {
520  if (tp3d.TjID <= 0) continue;
521  if (tp3d.Flags[kTP3DBad]) continue;
522  if (std::find(killme.begin(), killme.end(), tp3d.TjID) == killme.end())
523  killme.push_back(tp3d.TjID);
524  } // tp3d
525  } // pfp
526 
527  bool prt = (tcc.dbgPFP);
528 
529  for (auto tid : killme)
530  MakeTrajectoryObsolete(slc, (unsigned int)(tid - 1));
531 
532  // Make template trajectories in each plane. These will be re-used by
533  // each PFParticle
534  std::vector<Trajectory> ptjs(slc.nPlanes);
535  // define the basic tj variables
536  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
537  ptjs[plane].Pass = 0;
538  ptjs[plane].CTP = EncodeCTP(slc.TPCID.Cryostat, slc.TPCID.TPC, plane);
539  // This Tj wasn't created by stepping
540  ptjs[plane].StepDir = 0;
541  // It was created by this function however
542  ptjs[plane].AlgMod[kMakePFPTjs] = true;
543  // and is 3D matched
544  ptjs[plane].AlgMod[kMat3D] = true;
545  } // plane
546 
547  // now make the new Tjs
548  for (auto& pfp : slc.pfps) {
549  if (pfp.ID <= 0) continue;
550  // initialize the tjs
551  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
552  ptjs[plane].Pts.clear();
553  --evt.WorkID;
554  if (evt.WorkID == INT_MIN) evt.WorkID = -1;
555  ptjs[plane].ID = evt.WorkID;
556  } // plane
557  pfp.TjIDs.clear();
558  // iterate through all of the TP3Ds, adding TPs to the TJ in the appropriate plane.
559  // The assumption here is that TP order reflects the TP3D order
560  for (auto& tp3d : pfp.TP3Ds) {
561  if (tp3d.TjID <= 0) continue;
562  if (tp3d.Flags[kTP3DBad]) continue;
563  // make a copy of the 2D TP
564  auto tp = slc.tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
565  if (tp.InPFP > 0 && tp.InPFP != pfp.ID) continue;
566  tp.InPFP = pfp.ID;
567  // the TP Step isn't useful anymore, so stash the original TJ ID into it
568  tp.Step = tp3d.TjID;
569  unsigned short plane = DecodeCTP(tp.CTP).Plane;
570  // append it to Pts
571  ptjs[plane].Pts.push_back(tp);
572  } // tp3d
573  // finish defining each of the Tjs and store them
574  // new tj ID indexed by plane
575  std::vector<int> tids(ptjs.size(), 0);
576  for (unsigned short plane = 0; plane < ptjs.size(); ++plane) {
577  auto& tj = ptjs[plane];
578  if (tj.Pts.size() < 2) continue;
579  tj.PDGCode = pfp.PDGCode;
580  tj.MCSMom = MCSMom(slc, tj);
581  if (!StoreTraj(slc, tj)) continue;
582  // associate it with the pfp
583  auto& newTj = slc.tjs.back();
584  pfp.TjIDs.push_back(newTj.ID);
585  tids[plane] = newTj.ID;
586  } // tj
587  // preserve the PFP -> 3V -> 2V -> T assns
588  for (unsigned short end = 0; end < 2; ++end) {
589  if (pfp.Vx3ID[end] <= 0) continue;
590  auto& vx3 = slc.vtx3s[pfp.Vx3ID[end] - 1];
591  for (unsigned short plane = 0; plane < ptjs.size(); ++plane) {
592  if (tids[plane] == 0) continue;
593  if (vx3.Vx2ID[plane] <= 0) continue;
594  auto& vx2 = slc.vtxs[vx3.Vx2ID[plane] - 1];
595  auto& tj = slc.tjs[tids[plane] - 1];
596  auto tend = CloseEnd(tj, vx2.Pos);
597  tj.VtxID[tend] = vx2.ID;
598  if (prt)
599  mf::LogVerbatim("TC") << "MPFPTjs: 3V" << vx3.ID << " -> 2V" << vx2.ID << " -> T"
600  << tj.ID << "_" << tend << " in plane " << plane;
601  } // plane
602  } // end
603  } // pfp
604  } // MakePFPTjs
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3381
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
bool StoreTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:1074
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
void MakeTrajectoryObsolete(TCSlice &slc, unsigned int itj)
Definition: Utils.cxx:2138
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
geo::PlaneID DecodeCTP(CTP_t CTP)
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:49
unsigned short CloseEnd(const Trajectory &tj, const Point2_t &pos)
Definition: Utils.cxx:2495
TCEvent evt
Definition: DataStructs.cxx:8
void tca::MakeShowerObsolete ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 3151 of file TCShower.cxx.

References tca::ShowerStruct3D::CotIDs, tca::TCSlice::cots, and tca::ShowerStruct3D::ID.

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

3152  {
3153  // set the ss3 ID = 0 and remove 2D shower -> 3D shower associations. The 2D showers are not
3154  // declared obsolete
3155  for (auto cid : ss3.CotIDs) {
3156  if (cid == 0 || (unsigned short)cid > slc.cots.size()) continue;
3157  auto& ss = slc.cots[cid - 1];
3158  if (ss.SS3ID > 0 && ss.SS3ID != ss3.ID) continue;
3159  ss.SS3ID = 0;
3160  } // cid
3161  if (prt) {
3162  std::string fcnLabel = inFcnLabel + ".MSO";
3163  mf::LogVerbatim("TC") << fcnLabel << " Killed 3S" << ss3.ID;
3164  }
3165  ss3.ID = 0;
3166  } // MakeShowerObsolete
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void tca::MakeShowerObsolete ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct ss,
bool  prt 
)

Definition at line 3169 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.

3170  {
3171  // Gracefully kills the shower and the associated shower Tj
3172 
3173  if (ss.ID == 0) return;
3174 
3175  std::string fcnLabel = inFcnLabel + ".MSO";
3176 
3177  auto& stp1 = slc.tjs[ss.ShowerTjID - 1].Pts[1];
3178  if (!stp1.Hits.empty()) return;
3179 
3180  // clear a 3S -> 2S assn
3181  if (ss.SS3ID > 0 && ss.SS3ID <= (int)slc.showers.size()) {
3182  auto& ss3 = slc.showers[ss.SS3ID - 1];
3183  std::vector<int> newCIDs;
3184  for (auto cid : ss3.CotIDs) {
3185  if (cid != ss.ID) newCIDs.push_back(cid);
3186  } // cid
3187  ss3.CotIDs = newCIDs;
3188  } // ss3 assn exists
3189 
3190  // Kill the shower Tj if it exists. This also releases the hits
3191  if (ss.ShowerTjID > 0) MakeTrajectoryObsolete(slc, ss.ShowerTjID - 1);
3192 
3193  // Restore the original InShower Tjs
3194  // Unset the killed bit
3195  for (auto& tjID : ss.TjIDs) {
3196  Trajectory& tj = slc.tjs[tjID - 1];
3197  tj.AlgMod[kKilled] = false;
3198  // clear all of the shower-related bits
3199  tj.SSID = 0;
3200  tj.AlgMod[kShwrParent] = false;
3201  tj.AlgMod[kMergeOverlap] = false;
3202  tj.AlgMod[kMergeSubShowers] = false;
3203  tj.AlgMod[kMergeNrShowers] = false;
3204  tj.AlgMod[kMergeShChain] = false;
3205  } // tjID
3206  if (prt)
3207  mf::LogVerbatim("TC") << fcnLabel << " Killed 2S" << ss.ID << " and ST" << ss.ShowerTjID;
3208  ss.ID = 0;
3209 
3210  } // MakeShowerObsolete
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void MakeTrajectoryObsolete(TCSlice &slc, unsigned int itj)
Definition: Utils.cxx:2138
bool tca::MakeSmallAnglePFP ( detinfo::DetectorPropertiesData const &  detProp,
TCSlice slc,
PFPStruct pfp,
bool  prt 
)

Definition at line 2189 of file PFPUtils.cxx.

References tca::PFPStruct::AlgMod, CreateTP3D(), util::end(), tca::PFPStruct::Flags, tca::PFPStruct::ID, if(), InsideTPC(), kCanSection, kSmallAngle, kTP3DBad, kTP3DGood, MakeTP3D(), NumPtsWithCharge(), PosSep(), tca::PFPStruct::SectionFits, SetMag(), SortSection(), tcc, tca::PFPStruct::TjIDs, tca::TCSlice::tjs, tca::PFPStruct::TjUIDs, tca::PFPStruct::TP3Ds, tca::PFPStruct::TPCID, tca::TCConfig::useAlg, and tca::detail::valsDecreasing().

Referenced by MakeTP3Ds().

2193  {
2194  // Create and populate the TP3Ds vector for a small-angle track. The standard track fit
2195  // will fail for these tracks. The kSmallAngle AlgMod bit
2196  // is set true. Assume that the calling function, MakeTP3Ds, has decided that this is a
2197  // small-angle track.
2198 
2199  if (!tcc.useAlg[kSmallAngle]) return false;
2200  if (pfp.TjIDs.size() < 2) return false;
2201 
2202  std::vector<SortEntry> sortVec(pfp.TjIDs.size());
2203  unsigned short sbCnt = 0;
2204  for (unsigned short itj = 0; itj < pfp.TjIDs.size(); ++itj) {
2205  sortVec[itj].index = itj;
2206  auto& tj = slc.tjs[pfp.TjIDs[itj] - 1];
2207  sortVec[itj].val = NumPtsWithCharge(slc, tj, false);
2208  if (pfp.TjUIDs[itj] > 0) ++sbCnt;
2209  } // ipt
2210  std::sort(sortVec.begin(), sortVec.end(), valsDecreasing);
2211 
2212  // Decide whether to use the inflection points to add another section. Inflection
2213  // points must exist in the two longest Tjs
2214  unsigned short tlIndex = sortVec[0].index;
2215  unsigned short nlIndex = sortVec[1].index;
2216  auto& tlong = slc.tjs[pfp.TjIDs[tlIndex] - 1];
2217  auto& nlong = slc.tjs[pfp.TjIDs[nlIndex] - 1];
2218  bool twoSections = (sbCnt > 1 && pfp.TjUIDs[tlIndex] > 0 && pfp.TjUIDs[nlIndex] > 0);
2219  unsigned short tStartPt = tlong.EndPt[0];
2220  unsigned short tEndPt = tlong.EndPt[1];
2221  unsigned short nStartPt = nlong.EndPt[0];
2222  unsigned short nEndPt = nlong.EndPt[1];
2223  if (twoSections) {
2224  pfp.SectionFits.resize(2);
2225  tEndPt = pfp.TjUIDs[tlIndex];
2226  nEndPt = pfp.TjUIDs[nlIndex];
2227  if (prt) {
2228  mf::LogVerbatim myprt("TC");
2229  myprt << "MakeSmallAnglePFP: creating two sections using points";
2230  myprt << " T" << tlong.ID << "_" << tEndPt;
2231  myprt << " T" << nlong.ID << "_" << nEndPt;
2232  } // prt
2233  } // two Sections
2234  std::vector<Point3_t> sfEndPos;
2235  for (unsigned short isf = 0; isf < pfp.SectionFits.size(); ++isf) {
2236  // get the start and end TPs in this section
2237  auto& ltp0 = tlong.Pts[tStartPt];
2238  auto& ltp1 = tlong.Pts[tEndPt];
2239  auto& ntp0 = nlong.Pts[nStartPt];
2240  auto& ntp1 = nlong.Pts[nEndPt];
2241  // Get the 3D end points
2242  auto start = MakeTP3D(detProp, ltp0, ntp0);
2243  auto end = MakeTP3D(detProp, ltp1, ntp1);
2244  if (!start.Flags[kTP3DGood] || !end.Flags[kTP3DGood]) {
2245  std::cout << " Start/end fail in section " << isf << ". Add recovery code\n";
2246  return false;
2247  } // failure
2248  if (!InsideTPC(start.Pos, pfp.TPCID)) {
2249  mf::LogVerbatim("TC") << " Start is outside the TPC " << start.Pos[0] << " " << start.Pos[1]
2250  << " " << start.Pos[2];
2251  }
2252  if (!InsideTPC(end.Pos, pfp.TPCID)) {
2253  mf::LogVerbatim("TC") << " End is outside the TPC " << end.Pos[0] << " " << end.Pos[1]
2254  << " " << end.Pos[2];
2255  }
2256  if (isf == 0) sfEndPos.push_back(start.Pos);
2257  sfEndPos.push_back(end.Pos);
2258  auto& sf = pfp.SectionFits[isf];
2259  // Find the start and end positions
2260  for (unsigned short xyz = 0; xyz < 3; ++xyz) {
2261  sf.Dir[xyz] = end.Pos[xyz] - start.Pos[xyz];
2262  sf.Pos[xyz] = (end.Pos[xyz] + start.Pos[xyz]) / 2.;
2263  }
2264  SetMag(sf.Dir, 1.);
2265  sf.ChiDOF = 0.;
2266  sf.NPts = 0;
2267  // move the start/end point indices
2268  tStartPt = tEndPt + 1;
2269  tEndPt = tlong.EndPt[1];
2270  nStartPt = nEndPt + 1;
2271  nEndPt = nlong.EndPt[1];
2272  } // isf
2273  // Create TP3Ds
2274  // a temporary vector to hold TP3Ds for the second SectionFit
2275  std::vector<TP3D> sf2pts;
2276  for (unsigned short itj = 0; itj < sortVec.size(); ++itj) {
2277  int tid = pfp.TjIDs[sortVec[itj].index];
2278  // don't add points for the Tj that doesn't have an inflection point. It is
2279  // probably broken and would probably be put in the wrong section
2280  if (twoSections && pfp.TjUIDs[sortVec[itj].index] < 0) continue;
2281  auto& tj = slc.tjs[tid - 1];
2282  unsigned short sb = tj.EndPt[1];
2283  if (twoSections && pfp.TjUIDs[sortVec[itj].index] > 0) sb = pfp.TjUIDs[sortVec[itj].index];
2284  // count the number of good TPs in each section
2285  std::vector<double> npwc(pfp.SectionFits.size(), 0);
2286  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2287  auto& tp = tj.Pts[ipt];
2288  if (tp.Chg <= 0) continue;
2289  if (ipt > sb) { ++npwc[1]; }
2290  else {
2291  ++npwc[0];
2292  }
2293  } // ipt
2294  double length = PosSep(sfEndPos[0], sfEndPos[1]);
2295  double step = length / npwc[0];
2296  double along = -length / 2;
2297  unsigned short sfi = 0;
2298  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2299  auto& tp = tj.Pts[ipt];
2300  if (tp.Chg <= 0) continue;
2301  auto tp3d = CreateTP3D(detProp, slc, tid, ipt);
2302  if (tp3d.Flags[kTP3DBad]) continue;
2303  if (ipt == sb + 1) {
2304  sfi = 1;
2305  length = PosSep(sfEndPos[1], sfEndPos[2]);
2306  step = length / npwc[1];
2307  along = -length / 2;
2308  }
2309  tp3d.SFIndex = sfi;
2310  auto& sf = pfp.SectionFits[sfi];
2311  ++sf.NPts;
2312  tp3d.along = along;
2313  for (unsigned short xyz = 0; xyz < 3; ++xyz)
2314  tp3d.Pos[xyz] = sf.Pos[xyz] + along * sf.Dir[xyz];
2315  tp3d.Dir = sf.Dir;
2316  along += step;
2317  double delta = tp3d.Pos[0] - tp3d.TPX;
2318  sf.ChiDOF += delta * delta / tp3d.TPXErr2;
2319  // Assume that all points are good
2320  tp3d.Flags[kTP3DGood] = true;
2321  if (sfi == 0) { pfp.TP3Ds.push_back(tp3d); }
2322  else {
2323  sf2pts.push_back(tp3d);
2324  }
2325  } // ipt
2326  } // tid
2327  if (pfp.TP3Ds.size() < 4) return false;
2328  for (auto& sf : pfp.SectionFits) {
2329  if (sf.NPts < 5) return false;
2330  sf.ChiDOF /= (float)(sf.NPts - 4);
2331  } // sf
2332  if (!SortSection(pfp, 0)) return false;
2333  if (!sf2pts.empty()) {
2334  // append the points and sort
2335  pfp.TP3Ds.insert(pfp.TP3Ds.end(), sf2pts.begin(), sf2pts.end());
2336  if (!SortSection(pfp, 1)) return false;
2337  } // two sections
2338  pfp.Flags[kCanSection] = false;
2339  pfp.AlgMod[kSmallAngle] = true;
2340  if (prt) {
2341  mf::LogVerbatim("TC") << "Created SmallAngle P" << pfp.ID << " with " << pfp.TP3Ds.size()
2342  << " points in " << pfp.SectionFits.size() << " sections\n";
2343  }
2344  return true;
2345  } // MakeSmallAnglePFP
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool InsideTPC(const Point3_t &pos, geo::TPCID &inTPCID)
Definition: PFPUtils.cxx:3045
bool SortSection(PFPStruct &pfp, unsigned short sfIndex)
Definition: PFPUtils.cxx:1999
TCConfig tcc
Definition: DataStructs.cxx:9
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
if(nlines<=0)
bool SetMag(Vector3_t &v1, double mag)
Definition: PFPUtils.cxx:2570
TP3D CreateTP3D(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, int tjID, unsigned short tpIndex)
Definition: PFPUtils.cxx:2706
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
TP3D MakeTP3D(detinfo::DetectorPropertiesData const &detProp, const TrajPoint &itp, const TrajPoint &jtp)
Definition: PFPUtils.cxx:2435
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
bool valsDecreasing(const SortEntry &c1, const SortEntry &c2)
Definition: Utils.cxx:39
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
TP3D tca::MakeTP3D ( detinfo::DetectorPropertiesData const &  detProp,
const TrajPoint itp,
const TrajPoint jtp 
)

Definition at line 2435 of file PFPUtils.cxx.

References util::abs(), detinfo::DetectorPropertiesData::ConvertTicksToX(), detinfo::DetectorPropertiesData::ConvertXToTicks(), tca::TrajPoint::CTP, tca::TP3D::CTP, DecodeCTP(), den, tca::TrajPoint::Dir, tca::TP3D::Dir, tca::TP3D::Flags, kTP3DGood, geo::WireReadoutGeom::Plane(), tca::TrajPoint::Pos, tca::TP3D::Pos, PosSep(), tcc, tca::TP3D::TjID, tca::TP3D::TPIndex, tca::TP3D::TPX, tca::TP3D::TPXErr2, tca::TCConfig::unitsPerTick, tca::TP3D::Wire, geo::PlaneGeo::WireCoordinate(), and tca::TCConfig::wireReadoutGeom.

Referenced by MakeSmallAnglePFP().

2438  {
2439  // Make a 3D trajectory point using two 2D trajectory points. The TP3D Pos and Wire
2440  // variables are defined using itp. The SectionFit variables are un-defined
2441  TP3D tp3d;
2442  tp3d.TPIndex = 0;
2443  tp3d.TjID = 0;
2444  tp3d.CTP = itp.CTP;
2445  // assume failure
2446  tp3d.Flags[kTP3DGood] = false;
2447  tp3d.Dir = {{0.0, 0.0, 1.0}};
2448  tp3d.Pos = {{999.0, 999.0, 999.0}};
2449  geo::PlaneID iPlnID = DecodeCTP(itp.CTP);
2450  geo::PlaneID jPlnID = DecodeCTP(jtp.CTP);
2451  if (iPlnID == jPlnID) return tp3d;
2452  double upt = tcc.unitsPerTick;
2453  double ix = detProp.ConvertTicksToX(itp.Pos[1] / upt, iPlnID);
2454  double jx = detProp.ConvertTicksToX(jtp.Pos[1] / upt, jPlnID);
2455 
2456  // don't continue if the points are wildly far apart in X
2457  double dx = std::abs(ix - jx);
2458  if (dx > 20) return tp3d;
2459  tp3d.Pos[0] = (ix + jx) / 2;
2460  tp3d.TPX = ix;
2461  // Fake the error
2462  tp3d.TPXErr2 = dx;
2463  // determine the wire orientation and offsets using WireCoordinate
2464  // wire = yp * OrthY + zp * OrthZ - Wire0 = cs * yp + sn * zp - wire0
2465  // wire offset
2466  auto const& iplane = tcc.wireReadoutGeom->Plane(iPlnID);
2467  auto const& jplane = tcc.wireReadoutGeom->Plane(jPlnID);
2468  double iw0 = iplane.WireCoordinate(geo::Point_t{0, 0, 0});
2469  // cosine-like component
2470  double ics = iplane.WireCoordinate(geo::Point_t{0, 1, 0}) - iw0;
2471  // sine-like component
2472  double isn = iplane.WireCoordinate(geo::Point_t{0, 0, 1}) - iw0;
2473  double jw0 = jplane.WireCoordinate(geo::Point_t{0, 0, 0});
2474  double jcs = jplane.WireCoordinate(geo::Point_t{0, 1, 0}) - jw0;
2475  double jsn = jplane.WireCoordinate(geo::Point_t{0, 0, 1}) - jw0;
2476  double den = isn * jcs - ics * jsn;
2477  if (den == 0) return tp3d;
2478  double iPos0 = itp.Pos[0];
2479  double jPos0 = jtp.Pos[0];
2480  // Find the Z position of the intersection
2481  tp3d.Pos[2] = (jcs * (iPos0 - iw0) - ics * (jPos0 - jw0)) / den;
2482  // and the Y position
2483  bool useI = std::abs(ics) > std::abs(jcs);
2484  if (useI) { tp3d.Pos[1] = (iPos0 - iw0 - isn * tp3d.Pos[2]) / ics; }
2485  else {
2486  tp3d.Pos[1] = (jPos0 - jw0 - jsn * tp3d.Pos[2]) / jcs;
2487  }
2488 
2489  // Now find the direction. Protect against large angles first
2490  if (jtp.Dir[1] == 0) {
2491  // Going either in the +X direction or -X direction
2492  if (jtp.Dir[0] > 0) { tp3d.Dir[0] = 1; }
2493  else {
2494  tp3d.Dir[0] = -1;
2495  }
2496  tp3d.Dir[1] = 0;
2497  tp3d.Dir[2] = 0;
2498  return tp3d;
2499  } // jtp.Dir[1] == 0
2500 
2501  tp3d.Wire = iPos0;
2502 
2503  // make a copy of itp and shift it by many wires to avoid precision problems
2504  double itp2_0 = itp.Pos[0] + 100;
2505  double itp2_1 = itp.Pos[1];
2506  if (std::abs(itp.Dir[0]) > 0.01) itp2_1 += 100 * itp.Dir[1] / itp.Dir[0];
2507  // Create a second Point3 for the shifted point
2508  Point3_t pos2;
2509  // Find the X position corresponding to the shifted point
2510  pos2[0] = detProp.ConvertTicksToX(itp2_1 / upt, iPlnID);
2511  // Convert X to Ticks in the j plane and then to WSE units
2512  double jtp2Pos1 = detProp.ConvertXToTicks(pos2[0], jPlnID) * upt;
2513  // Find the wire position (Pos0) in the j plane that this corresponds to
2514  double jtp2Pos0 = (jtp2Pos1 - jtp.Pos[1]) * (jtp.Dir[0] / jtp.Dir[1]) + jtp.Pos[0];
2515  // Find the Y,Z position using itp2 and jtp2Pos0
2516  pos2[2] = (jcs * (itp2_0 - iw0) - ics * (jtp2Pos0 - jw0)) / den;
2517  if (useI) { pos2[1] = (itp2_0 - iw0 - isn * pos2[2]) / ics; }
2518  else {
2519  pos2[1] = (jtp2Pos0 - jw0 - jsn * pos2[2]) / jcs;
2520  }
2521  double sep = PosSep(tp3d.Pos, pos2);
2522  if (sep == 0) return tp3d;
2523  for (unsigned short ixyz = 0; ixyz < 3; ++ixyz)
2524  tp3d.Dir[ixyz] = (pos2[ixyz] - tp3d.Pos[ixyz]) / sep;
2525  tp3d.Flags[kTP3DGood] = true;
2526  return tp3d;
2527 
2528  } // MakeTP3D
const geo::WireReadoutGeom * wireReadoutGeom
Definition: DataStructs.h:568
std::array< double, 3 > Point3_t
Definition: DataStructs.h:39
double WireCoordinate(Point_t const &point) const
Returns the coordinate of the point on the plane, in wire units.
Definition: PlaneGeo.h:704
TCConfig tcc
Definition: DataStructs.cxx:9
Float_t den
Definition: plot.C:35
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
constexpr auto abs(T v)
Returns the absolute value of the argument.
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:180
geo::PlaneID DecodeCTP(CTP_t CTP)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
PlaneGeo const & Plane(TPCID const &tpcid, View_t view) const
Returns the specified wire.
bool tca::MakeTP3Ds ( detinfo::DetectorPropertiesData const &  detProp,
TCSlice slc,
PFPStruct pfp,
bool  prt 
)

Definition at line 2097 of file PFPUtils.cxx.

References util::abs(), tca::PFPStruct::AlgMod, CreateTP3D(), tca::PFPStruct::ID, kJunkTj, kSmallAngle, kTP3DBad, kTP3DGood, MakeSmallAnglePFP(), tca::PFPStruct::MVI, tca::PFPStruct::SectionFits, tca::PFPStruct::TjIDs, tca::TCSlice::tjs, tca::PFPStruct::TjUIDs, and tca::PFPStruct::TP3Ds.

Referenced by MakePFParticles().

2101  {
2102  // Create and populate the TP3Ds vector. This function is called before the first
2103  // fit is done so the TP3D along variable can't be determined. It returns false
2104  // if a majority of the tj points in TjIDs are already assigned to a different pfp
2105  pfp.TP3Ds.clear();
2106  if (!pfp.TP3Ds.empty() || pfp.SectionFits.size() != 1) return false;
2107 
2108  // Look for TPs that are ~parallel to the wire plane and trajectory points
2109  // where the min/max Pos[1] value is not near an end.
2110  // number of Small Angle Tjs
2111  // stash the inflection point index in the TjUIDs vector
2112  pfp.TjUIDs.resize(pfp.TjIDs.size(), -1);
2113  // count TPs with charge in all of the Tjs
2114  float cnt = 0;
2115  // and the number of TPs available for use
2116  float avail = 0;
2117  // and the number of junk Tjs
2118  unsigned short nJunk = 0;
2119  unsigned short nSA = 0;
2120  for (unsigned short itj = 0; itj < pfp.TjIDs.size(); ++itj) {
2121  auto& tj = slc.tjs[pfp.TjIDs[itj] - 1];
2122  if (tj.AlgMod[kJunkTj]) ++nJunk;
2123  float posMin = 1E6;
2124  unsigned short iptMin = USHRT_MAX;
2125  float posMax = -1E6;
2126  unsigned short iptMax = USHRT_MAX;
2127  float aveAng = 0;
2128  float npwc = 0;
2129  for (unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1]; ++ipt) {
2130  auto& tp = tj.Pts[ipt];
2131  if (tp.Chg <= 0) continue;
2132  ++cnt;
2133  if (tp.InPFP > 0) continue;
2134  ++avail;
2135  if (tp.Pos[1] > posMax) {
2136  posMax = tp.Pos[1];
2137  iptMax = ipt;
2138  }
2139  if (tp.Pos[1] < posMin) {
2140  posMin = tp.Pos[1];
2141  iptMin = ipt;
2142  }
2143  aveAng += tp.Ang;
2144  ++npwc;
2145  } // ipt
2146  if (npwc == 0) continue;
2147  aveAng /= npwc;
2148  if (std::abs(aveAng) < 0.05) ++nSA;
2149  // No problem if the min/max points are near the ends
2150  if (iptMin > tj.EndPt[0] + 4 && iptMin < tj.EndPt[1] - 4) pfp.TjUIDs[itj] = iptMin;
2151  if (iptMax > tj.EndPt[0] + 4 && iptMax < tj.EndPt[1] - 4) pfp.TjUIDs[itj] = iptMax;
2152  } // tid
2153  if (avail < 0.8 * cnt) return false;
2154  // small angle trajectory?
2155  if (nSA > 1) pfp.AlgMod[kSmallAngle] = true;
2156  if (prt)
2157  mf::LogVerbatim("TC") << " P" << pfp.ID << " MVI " << pfp.MVI << " nJunkTj " << nJunk
2158  << " SmallAngle? " << pfp.AlgMod[kSmallAngle];
2159 
2160  if (pfp.AlgMod[kSmallAngle]) return MakeSmallAnglePFP(detProp, slc, pfp, prt);
2161 
2162  // Add the points associated with the Tjs that were used to create the PFP
2163  for (auto tid : pfp.TjIDs) {
2164  auto& tj = slc.tjs[tid - 1];
2165  // There is one TP for every hit in a junk Tj so we can skip one, if there is only one
2166  if (nJunk == 1 && tj.AlgMod[kJunkTj]) continue;
2167  // All of the Tj's may be junk, especially for those at very high angle, so the
2168  // X position of the TP's isn't high quality. Inflate the errors below.
2169  bool isJunk = tj.AlgMod[kJunkTj];
2170  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2171  auto& tp = tj.Pts[ipt];
2172  if (tp.Chg <= 0) continue;
2173  if (tp.InPFP > 0) continue;
2174  ++avail;
2175  auto tp3d = CreateTP3D(detProp, slc, tid, ipt);
2176  if (tp3d.Flags[kTP3DBad]) continue;
2177  tp3d.SFIndex = 0;
2178  if (isJunk) tp3d.TPXErr2 *= 4;
2179  // We need to assume that all points are good or the first fit will fail
2180  tp3d.Flags[kTP3DGood] = true;
2181  pfp.TP3Ds.push_back(tp3d);
2182  } // ipt
2183  } // tid
2184  if (prt) mf::LogVerbatim("TC") << " has " << pfp.TP3Ds.size() << " TP3Ds";
2185  return true;
2186  } // MakeTP3Ds
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
constexpr auto abs(T v)
Returns the absolute value of the argument.
bool MakeSmallAnglePFP(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:2189
TP3D CreateTP3D(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, int tjID, unsigned short tpIndex)
Definition: PFPUtils.cxx:2706
void tca::MakeTrajectoryObsolete ( TCSlice slc,
unsigned int  itj 
)

Definition at line 2138 of file Utils.cxx.

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

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

2139  {
2140  // Note that this does not change the state of UseHit to allow
2141  // resurrecting the trajectory later (RestoreObsoleteTrajectory)
2142  if (itj > slc.tjs.size() - 1) return;
2143  int killTjID = slc.tjs[itj].ID;
2144  for (auto& hit : slc.slHits)
2145  if (hit.InTraj == killTjID) hit.InTraj = 0;
2146  slc.tjs[itj].AlgMod[kKilled] = true;
2147  } // MakeTrajectoryObsolete
Detector simulation of raw signals on wires.
bool tca::MakeVertexObsolete ( std::string  fcnLabel,
TCSlice slc,
VtxStore vx2,
bool  forceKill 
)

Definition at line 2698 of file TCVertex.cxx.

References tca::VtxStore::CTP, tca::TCConfig::dbg2V, tca::TCConfig::dbg3V, DecodeCTP(), util::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 BraggSplit(), CheckTrajBeginChg(), CompleteIncomplete3DVertices(), EndMerge(), FindHammerVertices(), FindHammerVertices2(), KillPoorVertices(), KillVerticesInShower(), LastEndMerge(), MakeVertexObsolete(), MergeAndStore(), Reconcile2VTs(), ReconcileVertices(), and SplitTrajCrossingVertices().

2699  {
2700  // Makes a 2D vertex obsolete
2701 
2702  // check for a high-score 3D vertex
2703  bool hasHighScoreVx3 = (vx2.Vx3ID > 0);
2704  if (hasHighScoreVx3 && !forceKill && slc.vtx3s[vx2.Vx3ID - 1].Score >= tcc.vtx2DCuts[7])
2705  return false;
2706 
2707  if (tcc.dbg2V || tcc.dbg3V) {
2708  mf::LogVerbatim("TC") << fcnLabel << " MVO: killing 2V" << vx2.ID;
2709  }
2710 
2711  // Kill it
2712  int vx2id = vx2.ID;
2713  if (vx2.Vx3ID > 0) {
2714  auto& vx3 = slc.vtx3s[vx2.Vx3ID - 1];
2715  for (auto& v3v2id : vx3.Vx2ID)
2716  if (v3v2id == vx2.ID) v3v2id = 0;
2717  }
2718  vx2.ID = 0;
2719  for (auto& tj : slc.tjs) {
2720  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
2721  for (unsigned short end = 0; end < 2; ++end) {
2722  if (tj.VtxID[end] != vx2id) continue;
2723  tj.VtxID[end] = 0;
2724  tj.AlgMod[kPhoton] = false;
2725  // clear the kEnvOverlap bits on the TPs
2726  for (unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
2727  if (end == 0) {
2728  unsigned short ipt = tj.EndPt[0] + ii;
2729  auto& tp = tj.Pts[ipt];
2730  if (!tp.Environment[kEnvOverlap]) break;
2731  if (ipt == tj.EndPt[1]) break;
2732  }
2733  else {
2734  unsigned short ipt = tj.EndPt[1] - ii;
2735  auto& tp = tj.Pts[ipt];
2736  if (!tp.Environment[kEnvOverlap]) break;
2737  if (ipt == tj.EndPt[0]) break;
2738  }
2739  } // ii
2740  if (tj.AlgMod[kTjHiVx3Score]) {
2741  // see if the vertex at the other end is high-score and if so, preserve the state
2742  unsigned short oend = 1 - end;
2743  if (tj.VtxID[oend] > 0) {
2744  auto& ovx2 = slc.vtxs[tj.VtxID[oend] - 1];
2745  if (!ovx2.Stat[kHiVx3Score]) tj.AlgMod[kTjHiVx3Score] = false;
2746  } // vertex at the other end
2747  } // tj.AlgMod[kTjHiVx3Score]
2748  } // end
2749  } // tj
2750 
2751  if (!hasHighScoreVx3) return true;
2752 
2753  // update the affected 3D vertex
2754  Vtx3Store& vx3 = slc.vtx3s[vx2.Vx3ID - 1];
2755  // make the 3D vertex incomplete
2756  geo::PlaneID planeID = DecodeCTP(vx2.CTP);
2757  unsigned short plane = planeID.Plane;
2758  if (vx3.Vx2ID[plane] != vx2id) return true;
2759  vx3.Vx2ID[plane] = 0;
2760  vx3.Wire = vx2.Pos[0];
2761  // Ensure that there are at least two 2D vertices left
2762  unsigned short n2D = 0;
2763  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane)
2764  if (vx3.Vx2ID[plane] > 0) ++n2D;
2765 
2766  if (n2D > 1) {
2767  // 3D vertex is incomplete
2768  // correct the score
2769  SetVx3Score(slc, vx3);
2770  return true;
2771  }
2772 
2773  // 3D vertex is obsolete
2774  // Detach all remaining 2D vertices from the 3D vertex
2775  for (auto& vx2 : slc.vtxs) {
2776  if (vx2.ID == 0) continue;
2777  if (vx2.Vx3ID == vx3.ID) vx2.Vx3ID = 0;
2778  } // vx2
2779  for (auto& pfp : slc.pfps) {
2780  for (unsigned short end = 0; end < 2; ++end)
2781  if (pfp.Vx3ID[end] == vx3.ID) pfp.Vx3ID[end] = 0;
2782  } // pfp
2783  vx3.ID = 0;
2784  return true;
2785 
2786  } // MakeVertexObsolete
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
matched to a high-score 3D vertex
Definition: DataStructs.h:90
void SetVx3Score(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2225
bool dbg3V
debug 3D vertex finding
Definition: DataStructs.h:589
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
bool dbg2V
debug 2D vertex finding
Definition: DataStructs.h:585
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:541
bool tca::MakeVertexObsolete ( TCSlice slc,
Vtx3Store vx3 
)

Definition at line 2789 of file TCVertex.cxx.

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

2790  {
2791  // Deletes a 3D vertex and 2D vertices in all planes
2792  // The 2D and 3D vertices are NOT killed if forceKill is false and the 3D vertex
2793  // has a high score
2794  if (vx3.ID <= 0) return true;
2795  if (vx3.ID > int(slc.vtx3s.size())) return false;
2796 
2797  for (auto vx2id : vx3.Vx2ID) {
2798  if (vx2id == 0 || vx2id > (int)slc.vtxs.size()) continue;
2799  auto& vx2 = slc.vtxs[vx2id - 1];
2800  MakeVertexObsolete("MVO3", slc, vx2, true);
2801  }
2802  vx3.ID = 0;
2803  return true;
2804  } // MakeVertexObsolete
bool MakeVertexObsolete(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2789
void tca::MaskBadTPs ( TCSlice slc,
Trajectory tj,
float const &  maxChi 
)

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

2573  {
2574  // Remove TPs that have the worst values of delta until the fit chisq < maxChi
2575 
2576  if (!tcc.useAlg[kMaskBadTPs]) return;
2577  //don't use this function for reverse propagation
2578  if (!tcc.useAlg[kRvPrp]) return;
2579 
2580  bool prt = (tcc.dbgStp || tcc.dbgAlg[kMaskBadTPs]);
2581 
2582  if (tj.Pts.size() < 3) {
2583  // mf::LogError("TC")<<"MaskBadTPs: Trajectory ID "<<tj.ID<<" too short to mask hits ";
2584  tj.IsGood = false;
2585  return;
2586  }
2587  unsigned short nit = 0;
2588  TrajPoint& lastTP = tj.Pts[tj.Pts.size() - 1];
2589  while (lastTP.FitChi > maxChi && nit < 3) {
2590  float maxDelta = 0;
2591  unsigned short imBad = USHRT_MAX;
2592  unsigned short cnt = 0;
2593  for (unsigned short ii = 1; ii < tj.Pts.size(); ++ii) {
2594  unsigned short ipt = tj.Pts.size() - 1 - ii;
2595  TrajPoint& tp = tj.Pts[ipt];
2596  if (tp.Chg == 0) continue;
2597  if (tp.Delta > maxDelta) {
2598  maxDelta = tp.Delta;
2599  imBad = ipt;
2600  }
2601  ++cnt;
2602  if (cnt == tp.NTPsFit) break;
2603  } // ii
2604  if (imBad == USHRT_MAX) return;
2605  if (prt)
2606  mf::LogVerbatim("TC") << "MaskBadTPs: lastTP.FitChi " << lastTP.FitChi << " Mask point "
2607  << imBad;
2608  // mask the point
2609  UnsetUsedHits(slc, tj.Pts[imBad]);
2610  FitTraj(slc, tj);
2611  if (prt) mf::LogVerbatim("TC") << " after FitTraj " << lastTP.FitChi;
2612  tj.AlgMod[kMaskBadTPs] = true;
2613  ++nit;
2614  } // lastTP.FItChi > maxChi && nit < 3
2615 
2616  } // MaskBadTPs
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void FitTraj(TCSlice const &slc, Trajectory &tj)
Definition: Utils.cxx:798
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1061
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:579
bool tca::MaskedHitsOK ( TCSlice slc,
Trajectory tj 
)

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

2620  {
2621  // The hits in the TP at the end of the trajectory were masked off. Decide whether to continue stepping with the
2622  // current configuration (true) or whether to stop and possibly try with the next pass settings (false)
2623 
2624  if (!tcc.useAlg[kMaskHits]) return true;
2625 
2626  unsigned short lastPt = tj.Pts.size() - 1;
2627  if (tj.Pts[lastPt].Chg > 0) return true;
2628  unsigned short endPt = tj.EndPt[1];
2629 
2630  // count the number of points w/o used hits and the number with one unused hit
2631  unsigned short nMasked = 0;
2632  unsigned short nOneHit = 0;
2633  unsigned short nOKChg = 0;
2634  unsigned short nOKDelta = 0;
2635  // number of points with Pos > HitPos
2636  unsigned short nPosDelta = 0;
2637  // number of points with Delta increasing vs ipt
2638  unsigned short nDeltaIncreasing = 0;
2639  // Fake this a bit to simplify comparing the counts
2640  float prevDelta = tj.Pts[endPt].Delta;
2641  float maxOKDelta = 10 * tj.Pts[endPt].DeltaRMS;
2642  float maxOKChg = 0;
2643  // find the maximum charge point on the trajectory
2644  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt)
2645  if (tj.Pts[ipt].Chg > maxOKChg) maxOKChg = tj.Pts[ipt].Chg;
2646  for (unsigned short ii = 1; ii < tj.Pts.size(); ++ii) {
2647  unsigned short ipt = tj.Pts.size() - ii;
2648  auto& tp = tj.Pts[ipt];
2649  if (tp.Chg > 0) break;
2650  unsigned short nUnusedHits = 0;
2651  float chg = 0;
2652  for (unsigned short jj = 0; jj < tp.Hits.size(); ++jj) {
2653  unsigned int iht = tp.Hits[jj];
2654  if (slc.slHits[iht].InTraj != 0) continue;
2655  ++nUnusedHits;
2656  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2657  chg += hit.Integral();
2658  } // jj
2659  if (chg < maxOKChg) ++nOKChg;
2660  if (nUnusedHits == 1) ++nOneHit;
2661  if (tp.Delta < maxOKDelta) ++nOKDelta;
2662  // count the number of points with Pos time > HitPos time
2663  if (tp.Pos[1] > tp.HitPos[1]) ++nPosDelta;
2664  // The number of increasing delta points: Note implied absolute value
2665  if (tp.Delta < prevDelta) ++nDeltaIncreasing;
2666  prevDelta = tp.Delta;
2667  ++nMasked;
2668  } // ii
2669 
2670  // determine if the hits are wandering away from the trajectory direction. This will result in
2671  // nPosDelta either being ~0 or ~equal to the number of masked points. nPosDelta should have something
2672  // in between these two extremes if we are stepping through a messy region
2673  bool driftingAway = nMasked > 2 && (nPosDelta == 0 || nPosDelta == nMasked);
2674  // Note that nDeltaIncreasing is always positive
2675  if (driftingAway && nDeltaIncreasing < nMasked - 1) driftingAway = false;
2676 
2677  if (tcc.dbgStp) {
2678  mf::LogVerbatim("TC") << "MHOK: nMasked " << nMasked << " nOneHit " << nOneHit << " nOKChg "
2679  << nOKChg << " nOKDelta " << nOKDelta << " nPosDelta " << nPosDelta
2680  << " nDeltaIncreasing " << nDeltaIncreasing << " driftingAway? "
2681  << driftingAway;
2682  }
2683 
2684  if (!driftingAway) {
2685  if (nMasked < 8 || nOneHit < 8) return true;
2686  if (nOKDelta != nMasked) return true;
2687  if (nOKChg != nMasked) return true;
2688  }
2689 
2690  // we would like to reduce the number of fitted points to a minimum and include
2691  // the masked hits, but we can only do that if there are enough points
2692  if (tj.Pts[endPt].NTPsFit <= tcc.minPtsFit[tj.Pass]) {
2693  // stop stepping if we have masked off more points than are in the fit
2694  if (nMasked > tj.Pts[endPt].NTPsFit) return false;
2695  return true;
2696  }
2697  // Reduce the number of points fit and try to include the points
2698  unsigned short newNTPSFit;
2699  if (tj.Pts[endPt].NTPsFit > 2 * tcc.minPtsFit[tj.Pass]) {
2700  newNTPSFit = tj.Pts[endPt].NTPsFit / 2;
2701  }
2702  else {
2703  newNTPSFit = tcc.minPtsFit[tj.Pass];
2704  }
2705  for (unsigned ipt = endPt + 1; ipt < tj.Pts.size(); ++ipt) {
2706  TrajPoint& tp = tj.Pts[ipt];
2707  for (unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
2708  unsigned int iht = tp.Hits[ii];
2709  if (slc.slHits[iht].InTraj == 0) {
2710  tp.UseHit[ii] = true;
2711  slc.slHits[iht].InTraj = tj.ID;
2712  break;
2713  }
2714  } // ii
2715  DefineHitPos(slc, tp);
2716  SetEndPoints(tj);
2717  tp.NTPsFit = newNTPSFit;
2718  FitTraj(slc, tj);
2719  if (tcc.dbgStp) PrintTrajectory("MHOK", slc, tj, ipt);
2720  } // ipt
2721 
2722  tj.AlgMod[kMaskHits] = true;
2723  UpdateTjChgProperties("MHOK", slc, tj, tcc.dbgStp);
2724  return true;
2725 
2726  } // MaskedHitsOK
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void FitTraj(TCSlice const &slc, Trajectory &tj)
Definition: Utils.cxx:798
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
std::vector< unsigned short > minPtsFit
Reconstruct in several passes.
Definition: DataStructs.h:556
TCConfig tcc
Definition: DataStructs.cxx:9
void PrintTrajectory(std::string someText, const TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:6035
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1791
Detector simulation of raw signals on wires.
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice const &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3577
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
void tca::MaskTrajEndPoints ( TCSlice slc,
Trajectory tj,
unsigned short  nPts 
)

Definition at line 3909 of file StepUtils.cxx.

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

3910  {
3911 
3912  // Masks off (sets all hits not-Used) nPts trajectory points at the leading edge of the
3913  // trajectory, presumably because the fit including this points is poor. The position, direction
3914  // and Delta of the last nPts points is updated as well
3915 
3916  if (tj.EndFlag[1][kAtKink]) return;
3917  if (tj.Pts.size() < 3) {
3918  mf::LogError("TC") << "MaskTrajEndPoints: Trajectory ID " << tj.ID
3919  << " too short to mask hits ";
3920  return;
3921  }
3922  if (nPts > tj.Pts.size() - 2) {
3923  mf::LogError("TC") << "MaskTrajEndPoints: Trying to mask too many points " << nPts
3924  << " Pts.size " << tj.Pts.size();
3925  return;
3926  }
3927 
3928  // find the last good point (with charge)
3929  unsigned short lastGoodPt = USHRT_MAX;
3930 
3931  if (tcc.dbgStp) {
3932  mf::LogVerbatim("TC") << "MTEP: lastGoodPt " << lastGoodPt << " Pts size " << tj.Pts.size()
3933  << " tj.IsGood " << tj.IsGood;
3934  }
3935  if (lastGoodPt == USHRT_MAX) return;
3936  tj.EndPt[1] = lastGoodPt;
3937 
3938  //for(unsigned short ii = 0; ii < nPts; ++ii) {
3939  for (unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
3940  unsigned short ipt = tj.Pts.size() - 1 - ii;
3941  if (ipt == lastGoodPt) break;
3942  UnsetUsedHits(slc, tj.Pts[ipt]);
3943  // Reset the position and direction of the masked off points
3944  tj.Pts[ipt].Dir = tj.Pts[lastGoodPt].Dir;
3945  if (tj.Pts[lastGoodPt].AngleCode == 2) {
3946  // Very large angle: Move by path length
3947  float path = TrajPointSeparation(tj.Pts[lastGoodPt], tj.Pts[ipt]);
3948  tj.Pts[ipt].Pos[0] = tj.Pts[lastGoodPt].Pos[0] + path * tj.Pts[ipt].Dir[0];
3949  tj.Pts[ipt].Pos[1] = tj.Pts[lastGoodPt].Pos[1] + path * tj.Pts[ipt].Dir[1];
3950  }
3951  else {
3952  // Not large angle: Move by wire
3953  float dw = tj.Pts[ipt].Pos[0] - tj.Pts[lastGoodPt].Pos[0];
3954  // Correct the projected time to the wire
3955  float newpos = tj.Pts[lastGoodPt].Pos[1] + dw * tj.Pts[ipt].Dir[1] / tj.Pts[ipt].Dir[0];
3956  if (tcc.dbgStp)
3957  mf::LogVerbatim("TC") << "MTEP: ipt " << ipt << " Pos[0] " << tj.Pts[ipt].Pos[0]
3958  << ". Move Pos[1] from " << tj.Pts[ipt].Pos[1] << " to " << newpos;
3959  tj.Pts[ipt].Pos[1] =
3960  tj.Pts[lastGoodPt].Pos[1] + dw * tj.Pts[ipt].Dir[1] / tj.Pts[ipt].Dir[0];
3961  }
3962  tj.Pts[ipt].Delta = PointTrajDOCA(tj.Pts[ipt].HitPos[0], tj.Pts[ipt].HitPos[1], tj.Pts[ipt]);
3963  if (tcc.dbgStp)
3964  mf::LogVerbatim("TC") << " masked ipt " << ipt << " Pos " << PrintPos(tj.Pts[ipt])
3965  << " Chg " << tj.Pts[ipt].Chg;
3966  } // ii
3967  SetEndPoints(tj);
3968 
3969  } // MaskTrajEndPoints
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1061
float TrajPointSeparation(const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2613
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2514
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
void tca::Match2DShowers ( std::string  inFcnLabel,
TCSlice slc,
bool  prt 
)
void tca::Match2Planes ( TCSlice slc,
std::vector< MatchStruct > &  matVec 
)

Definition at line 939 of file PFPUtils.cxx.

References geo::CryostatID::Cryostat, tca::detail::SortEntry::index, tca::TCSlice::mallTraj, tca::TCConfig::match3DCuts, NumPtsWithCharge(), tcc, tca::TCSlice::tjs, geo::TPCID::TPC, tca::TCSlice::TPCID, tca::detail::SortEntry::val, tca::detail::valsDecreasing(), geo::WireReadoutGeom::WireIDsIntersect(), and tca::TCConfig::wireReadoutGeom.

Referenced by FindPFParticles().

940  {
941  // A simpler faster version of MatchPlanes that only creates two plane matches
942 
943  matVec.clear();
944  if (slc.mallTraj.empty()) return;
945 
946  int cstat = slc.TPCID.Cryostat;
947  int tpc = slc.TPCID.TPC;
948 
949  float xcut = tcc.match3DCuts[0];
950 
951  // the TJ IDs for one match
952  std::array<unsigned short, 2> tIDs;
953  // vector for matched Tjs
954  std::vector<std::array<unsigned short, 2>> mtIDs;
955  // and a matching vector for the count
956  std::vector<unsigned short> mCnt;
957  // ignore Tj matches after hitting a user-defined limit
958  unsigned short maxCnt = USHRT_MAX;
959  if (tcc.match3DCuts[1] < (float)USHRT_MAX) maxCnt = (unsigned short)tcc.match3DCuts[1];
960  // a list of those Tjs
961  std::vector<unsigned short> tMaxed;
962 
963  for (std::size_t ipt = 0; ipt < slc.mallTraj.size() - 1; ++ipt) {
964  auto& iTjPt = slc.mallTraj[ipt];
965  // see if we hit the maxCnt limit
966  if (std::find(tMaxed.begin(), tMaxed.end(), iTjPt.id) != tMaxed.end()) continue;
967  auto& itp = slc.tjs[iTjPt.id - 1].Pts[iTjPt.ipt];
968  unsigned short iPlane = iTjPt.plane;
969  unsigned int iWire = itp.Pos[0];
970  bool hitMaxCnt = false;
971  for (std::size_t jpt = ipt + 1; jpt < slc.mallTraj.size() - 1; ++jpt) {
972  auto& jTjPt = slc.mallTraj[jpt];
973  // ensure that the planes are different
974  if (jTjPt.plane == iTjPt.plane) continue;
975  // check for x range overlap. We know that jTjPt.xlo is >= iTjPt.xlo because of the sort
976  if (jTjPt.xlo > iTjPt.xhi) continue;
977  // break out if the x range difference becomes large
978  if (jTjPt.xlo > iTjPt.xhi + xcut) break;
979  // see if we hit the maxCnt limit
980  if (std::find(tMaxed.begin(), tMaxed.end(), jTjPt.id) != tMaxed.end()) continue;
981  auto& jtp = slc.tjs[jTjPt.id - 1].Pts[jTjPt.ipt];
982  unsigned short jPlane = jTjPt.plane;
983  unsigned int jWire = jtp.Pos[0];
984  if (!tcc.wireReadoutGeom->WireIDsIntersect(geo::WireID(cstat, tpc, iPlane, iWire),
985  geo::WireID(cstat, tpc, jPlane, jWire)))
986  continue;
987  tIDs[0] = iTjPt.id;
988  tIDs[1] = jTjPt.id;
989  // swap the order so that the == operator works correctly
990  if (tIDs[0] > tIDs[1]) std::swap(tIDs[0], tIDs[1]);
991  // look for it in the list
992  std::size_t indx = 0;
993  for (indx = 0; indx < mtIDs.size(); ++indx)
994  if (tIDs == mtIDs[indx]) break;
995  if (indx == mtIDs.size()) {
996  // not found so add it to mtIDs and add another element to mCnt
997  mtIDs.push_back(tIDs);
998  mCnt.push_back(0);
999  }
1000  ++mCnt[indx];
1001  if (mCnt[indx] == maxCnt) {
1002  // add the Tjs to the list
1003  tMaxed.insert(tMaxed.end(), tIDs[0]);
1004  tMaxed.insert(tMaxed.end(), tIDs[1]);
1005  hitMaxCnt = true;
1006  break;
1007  } // hit maxCnt
1008  if (hitMaxCnt) break;
1009  } // jpt
1010  } // ipt
1011 
1012  if (mCnt.empty()) return;
1013 
1014  std::vector<SortEntry> sortVec;
1015  for (std::size_t indx = 0; indx < mCnt.size(); ++indx) {
1016  auto& tIDs = mtIDs[indx];
1017  // count the number of TPs in all Tjs
1018  float tpCnt = 0;
1019  for (auto tid : tIDs) {
1020  auto& tj = slc.tjs[tid - 1];
1021  tpCnt += NumPtsWithCharge(slc, tj, false);
1022  } // tid
1023  float frac = mCnt[indx] / tpCnt;
1024  frac /= 2;
1025  // ignore matches with a very low match fraction
1026  if (frac < 0.05) continue;
1027  SortEntry se;
1028  se.index = indx;
1029  se.val = mCnt[indx];
1030  sortVec.push_back(se);
1031  } // ii
1032  if (sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(), valsDecreasing);
1033 
1034  matVec.resize(sortVec.size());
1035 
1036  for (std::size_t ii = 0; ii < sortVec.size(); ++ii) {
1037  unsigned short indx = sortVec[ii].index;
1038  auto& ms = matVec[ii];
1039  ms.Count = mCnt[indx];
1040  ms.TjIDs.resize(2);
1041  for (unsigned short plane = 0; plane < 2; ++plane)
1042  ms.TjIDs[plane] = (int)mtIDs[indx][plane];
1043  } // indx
1044 
1045  } // Match2Planes
const geo::WireReadoutGeom * wireReadoutGeom
Definition: DataStructs.h:568
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< float > match3DCuts
3D matching cuts
Definition: DataStructs.h:551
bool WireIDsIntersect(WireID const &wid1, WireID const &wid2, Point_t &intersection) const
Computes the intersection between two wires.
bool valsDecreasing(const SortEntry &c1, const SortEntry &c2)
Definition: Utils.cxx:39
void swap(lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &a, lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &b)
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
float tca::Match3DFOM ( detinfo::DetectorPropertiesData const &  detProp,
std::string  inFcnLabel,
TCSlice slc,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 1198 of file TCShower.cxx.

References tca::ShowerStruct3D::CotIDs.

Referenced by Match3DFOM().

1203  {
1204  float fom = 0;
1205  float cnt = 0;
1206  for (unsigned short ii = 0; ii < ss3.CotIDs.size() - 1; ++ii) {
1207  unsigned short icid = ss3.CotIDs[ii];
1208  for (unsigned short jj = ii + 1; jj < ss3.CotIDs.size(); ++jj) {
1209  unsigned short jcid = ss3.CotIDs[jj];
1210  fom += Match3DFOM(detProp, inFcnLabel, slc, icid, jcid, prt);
1211  ++cnt;
1212  } // cj
1213  } // ci
1214  if (cnt == 0) return 100;
1215  return fom / cnt;
1216  } // Match3DFOM
float Match3DFOM(detinfo::DetectorPropertiesData const &detProp, std::string inFcnLabel, TCSlice &slc, int icid, int jcid, bool prt)
Definition: TCShower.cxx:1239
float tca::Match3DFOM ( detinfo::DetectorPropertiesData const &  detProp,
std::string  inFcnLabel,
TCSlice slc,
int  icid,
int  jcid,
int  kcid,
bool  prt 
)

Definition at line 1219 of file TCShower.cxx.

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

1226  {
1227  if (icid == 0 || icid > (int)slc.cots.size()) return 100;
1228  if (jcid == 0 || jcid > (int)slc.cots.size()) return 100;
1229  if (kcid == 0 || kcid > (int)slc.cots.size()) return 100;
1230 
1231  float ijfom = Match3DFOM(detProp, inFcnLabel, slc, icid, jcid, prt);
1232  float jkfom = Match3DFOM(detProp, inFcnLabel, slc, jcid, kcid, prt);
1233 
1234  return 0.5 * (ijfom + jkfom);
1235 
1236  } // Match3DFOM
float Match3DFOM(detinfo::DetectorPropertiesData const &detProp, std::string inFcnLabel, TCSlice &slc, int icid, int jcid, bool prt)
Definition: TCShower.cxx:1239
float tca::Match3DFOM ( detinfo::DetectorPropertiesData const &  detProp,
std::string  inFcnLabel,
TCSlice slc,
int  icid,
int  jcid,
bool  prt 
)

Definition at line 1239 of file TCShower.cxx.

References util::abs(), detinfo::DetectorPropertiesData::ConvertTicksToX(), tca::TCSlice::cots, DecodeCTP(), tcc, tca::TCSlice::tjs, and tca::TCConfig::unitsPerTick.

1245  {
1246  // returns a Figure of Merit for a 3D match of two showers
1247  if (icid == 0 || icid > (int)slc.cots.size()) return 100;
1248  if (jcid == 0 || jcid > (int)slc.cots.size()) return 100;
1249 
1250  auto& iss = slc.cots[icid - 1];
1251  auto& istj = slc.tjs[iss.ShowerTjID - 1];
1252  auto& jss = slc.cots[jcid - 1];
1253  auto& jstj = slc.tjs[jss.ShowerTjID - 1];
1254 
1255  if (iss.CTP == jss.CTP) return 100;
1256 
1257  std::string fcnLabel = inFcnLabel + ".MFOM";
1258 
1259  float energyAsym = std::abs(iss.Energy - jss.Energy) / (iss.Energy + jss.Energy);
1260 
1261  // don't apply the asymmetry cut on low energy showers
1262  if ((iss.Energy > 200 || jss.Energy > 200) && energyAsym > 0.5) return 50;
1263 
1264  geo::PlaneID iPlnID = DecodeCTP(iss.CTP);
1265  geo::PlaneID jPlnID = DecodeCTP(jss.CTP);
1266 
1267  // compare match at the charge center
1268  float ix = detProp.ConvertTicksToX(istj.Pts[1].Pos[1] / tcc.unitsPerTick, iPlnID);
1269  float jx = detProp.ConvertTicksToX(jstj.Pts[1].Pos[1] / tcc.unitsPerTick, jPlnID);
1270  float pos1fom = std::abs(ix - jx) / 10;
1271 
1272  float mfom = energyAsym * pos1fom;
1273 
1274  if (prt) {
1275  mf::LogVerbatim myprt("TC");
1276  myprt << fcnLabel << " i2S" << iss.ID << " j2S" << jss.ID;
1277  myprt << std::fixed << std::setprecision(2);
1278  myprt << " pos1fom " << pos1fom;
1279  myprt << " energyAsym " << energyAsym;
1280  myprt << " mfom " << mfom;
1281  }
1282 
1283  return mfom;
1284  } // Madtch3DFOM
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
constexpr auto abs(T v)
Returns the absolute value of the argument.
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
geo::PlaneID DecodeCTP(CTP_t CTP)
void tca::Match3Planes ( TCSlice slc,
std::vector< MatchStruct > &  matVec 
)

Definition at line 809 of file PFPUtils.cxx.

References util::abs(), evt, tca::detail::SortEntry::index, evd::kPlane, evd::kWire, tca::TCSlice::mallTraj, tca::TCConfig::match3DCuts, Match3PlanesSpt(), tca::TCSlice::nPlanes, NumPtsWithCharge(), tca::TCEvent::sptHits, tcc, TCIntersectionPoint(), tca::TCSlice::tjs, tca::detail::SortEntry::val, tca::detail::valsDecreasing(), and tca::TCConfig::wirePitch.

Referenced by FindPFParticles().

810  {
811  // A simpler and faster version of MatchPlanes that only creates three plane matches
812 
813  if (slc.nPlanes != 3) return;
814 
815  // use SpacePoint -> Hit -> TP assns?
816  if (!evt.sptHits.empty()) {
817  Match3PlanesSpt(slc, matVec);
818  return;
819  }
820 
821  if (slc.mallTraj.empty()) return;
822  float xcut = tcc.match3DCuts[0];
823  double yzcut = 1.5 * tcc.wirePitch;
824 
825  // the TJ IDs for one match
826  std::array<unsigned short, 3> tIDs;
827  // vector for matched Tjs
828  std::vector<std::array<unsigned short, 3>> mtIDs;
829  // and a matching vector for the count
830  std::vector<unsigned short> mCnt;
831  // ignore Tj matches after hitting a user-defined limit
832  unsigned short maxCnt = USHRT_MAX;
833  if (tcc.match3DCuts[1] < (float)USHRT_MAX) maxCnt = (unsigned short)tcc.match3DCuts[1];
834  // a list of those Tjs
835  std::vector<unsigned short> tMaxed;
836 
837  for (std::size_t ipt = 0; ipt < slc.mallTraj.size() - 1; ++ipt) {
838  auto& iTjPt = slc.mallTraj[ipt];
839  // see if we hit the maxCnt limit
840  if (std::find(tMaxed.begin(), tMaxed.end(), iTjPt.id) != tMaxed.end()) continue;
841  auto& itp = slc.tjs[iTjPt.id - 1].Pts[iTjPt.ipt];
842  unsigned int iPlane = iTjPt.plane;
843  unsigned int iWire = std::nearbyint(itp.Pos[0]);
844  tIDs[iPlane] = iTjPt.id;
845  bool hitMaxCnt = false;
846  for (std::size_t jpt = ipt + 1; jpt < slc.mallTraj.size() - 1; ++jpt) {
847  auto& jTjPt = slc.mallTraj[jpt];
848  // ensure that the planes are different
849  if (jTjPt.plane == iTjPt.plane) continue;
850  // check for x range overlap. We know that jTjPt.xlo is >= iTjPt.xlo because of the sort
851  if (jTjPt.xlo > iTjPt.xhi) continue;
852  // break out if the x range difference becomes large
853  if (jTjPt.xlo > iTjPt.xhi + xcut) break;
854  // see if we hit the maxCnt limit
855  if (std::find(tMaxed.begin(), tMaxed.end(), jTjPt.id) != tMaxed.end()) continue;
856  auto& jtp = slc.tjs[jTjPt.id - 1].Pts[jTjPt.ipt];
857  unsigned short jPlane = jTjPt.plane;
858  unsigned int jWire = jtp.Pos[0];
859  Point2_t ijPos;
860  if (!TCIntersectionPoint(iWire, jWire, iPlane, jPlane, ijPos[0], ijPos[1])) continue;
861  tIDs[jPlane] = jTjPt.id;
862  for (std::size_t kpt = jpt + 1; kpt < slc.mallTraj.size(); ++kpt) {
863  auto& kTjPt = slc.mallTraj[kpt];
864  // ensure that the planes are different
865  if (kTjPt.plane == iTjPt.plane || kTjPt.plane == jTjPt.plane) continue;
866  if (kTjPt.xlo > iTjPt.xhi) continue;
867  // break out if the x range difference becomes large
868  if (kTjPt.xlo > iTjPt.xhi + xcut) break;
869  // see if we hit the maxCnt limit
870  if (std::find(tMaxed.begin(), tMaxed.end(), kTjPt.id) != tMaxed.end()) continue;
871  auto& ktp = slc.tjs[kTjPt.id - 1].Pts[kTjPt.ipt];
872  unsigned short kPlane = kTjPt.plane;
873  unsigned int kWire = ktp.Pos[0];
874  Point2_t ikPos;
875  if (!TCIntersectionPoint(iWire, kWire, iPlane, kPlane, ikPos[0], ikPos[1])) continue;
876  if (std::abs(ijPos[0] - ikPos[0]) > yzcut) continue;
877  if (std::abs(ijPos[1] - ikPos[1]) > yzcut) continue;
878  // we have a match
879  tIDs[kPlane] = kTjPt.id;
880  // look for it in the list
881  unsigned int indx = 0;
882  for (indx = 0; indx < mtIDs.size(); ++indx)
883  if (tIDs == mtIDs[indx]) break;
884  if (indx == mtIDs.size()) {
885  // not found so add it to mtIDs and add another element to mCnt
886  mtIDs.push_back(tIDs);
887  mCnt.push_back(0);
888  }
889  ++mCnt[indx];
890  if (mCnt[indx] == maxCnt) {
891  // add the Tjs to the list
892  tMaxed.insert(tMaxed.end(), tIDs[0]);
893  tMaxed.insert(tMaxed.end(), tIDs[1]);
894  tMaxed.insert(tMaxed.end(), tIDs[2]);
895  hitMaxCnt = true;
896  break;
897  } // hit maxCnt
898  } // kpt
899  if (hitMaxCnt) break;
900  } // jpt
901  } // ipt
902 
903  if (mCnt.empty()) return;
904 
905  std::vector<SortEntry> sortVec;
906  for (std::size_t indx = 0; indx < mCnt.size(); ++indx) {
907  auto& tIDs = mtIDs[indx];
908  // count the number of TPs in all Tjs
909  float tpCnt = 0;
910  for (auto tid : tIDs) {
911  auto& tj = slc.tjs[tid - 1];
912  tpCnt += NumPtsWithCharge(slc, tj, false);
913  } // tid
914  float frac = mCnt[indx] / tpCnt;
915  frac /= 3;
916  // ignore matches with a very low match fraction
917  if (frac < 0.05) continue;
918  SortEntry se;
919  se.index = indx;
920  se.val = mCnt[indx];
921  sortVec.push_back(se);
922  } // ii
923  if (sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(), valsDecreasing);
924 
925  matVec.resize(sortVec.size());
926 
927  for (std::size_t ii = 0; ii < sortVec.size(); ++ii) {
928  unsigned short indx = sortVec[ii].index;
929  auto& ms = matVec[ii];
930  ms.Count = mCnt[indx];
931  ms.TjIDs.resize(3);
932  for (unsigned short plane = 0; plane < 3; ++plane)
933  ms.TjIDs[plane] = (int)mtIDs[indx][plane];
934  } // indx
935 
936  } // Match3Planes
static unsigned int kWire
TCConfig tcc
Definition: DataStructs.cxx:9
constexpr auto abs(T v)
Returns the absolute value of the argument.
static unsigned int kPlane
std::vector< std::array< unsigned int, 3 > > sptHits
SpacePoint -> Hits assns by plane.
Definition: DataStructs.h:625
std::array< float, 2 > Point2_t
Definition: DataStructs.h:41
bool TCIntersectionPoint(unsigned int wir1, unsigned int wir2, unsigned int pln1, unsigned int pln2, float &y, float &z)
Definition: PFPUtils.cxx:667
std::vector< float > match3DCuts
3D matching cuts
Definition: DataStructs.h:551
bool valsDecreasing(const SortEntry &c1, const SortEntry &c2)
Definition: Utils.cxx:39
void Match3PlanesSpt(TCSlice &slc, std::vector< MatchStruct > &matVec)
Definition: PFPUtils.cxx:698
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
TCEvent evt
Definition: DataStructs.cxx:8
void tca::Match3PlanesSpt ( TCSlice slc,
std::vector< MatchStruct > &  matVec 
)

Definition at line 698 of file PFPUtils.cxx.

References tca::TCEvent::allHits, evt, tca::detail::SortEntry::index, tca::TCConfig::match3DCuts, NumPtsWithCharge(), tca::TCSlice::slHits, tca::TCEvent::sptHits, SptInTPC(), tcc, tca::TCSlice::tjs, geo::TPCID::TPC, tca::TCSlice::TPCID, tca::detail::SortEntry::val, and tca::detail::valsDecreasing().

Referenced by Match3Planes().

699  {
700  // fill matVec using SpacePoint -> Hit -> TP -> tj assns
701  if (evt.sptHits.empty()) return;
702 
703  // create a local vector of allHit -> Tj assns and populate it
704  std::vector<int> inTraj((*evt.allHits).size(), 0);
705  for (auto& tch : slc.slHits)
706  inTraj[tch.allHitsIndex] = tch.InTraj;
707 
708  // the TJ IDs for one match
709  std::array<int, 3> tIDs;
710  // vector for matched Tjs
711  std::vector<std::array<int, 3>> mtIDs;
712  // and a matching vector for the count
713  std::vector<unsigned short> mCnt;
714  // ignore Tj matches after hitting a user-defined limit
715  unsigned short maxCnt = USHRT_MAX;
716  if (tcc.match3DCuts[1] < (float)USHRT_MAX) maxCnt = (unsigned short)tcc.match3DCuts[1];
717  // a list of those Tjs
718  std::vector<unsigned short> tMaxed;
719 
720  unsigned int tpc = slc.TPCID.TPC;
721 
722  for (auto& sptHits : evt.sptHits) {
723  if (sptHits.size() != 3) continue;
724  // ensure that the SpacePoint is in the requested TPC
725  if (!SptInTPC(sptHits, tpc)) continue;
726  unsigned short cnt = 0;
727  for (unsigned short plane = 0; plane < 3; ++plane) {
728  unsigned int iht = sptHits[plane];
729  if (iht == UINT_MAX) continue;
730  if (inTraj[iht] <= 0) continue;
731  tIDs[plane] = inTraj[iht];
732  ++cnt;
733  } // iht
734  if (cnt != 3) continue;
735  // look for it in the list of tj combinations
736  unsigned short indx = 0;
737  for (indx = 0; indx < mtIDs.size(); ++indx)
738  if (tIDs == mtIDs[indx]) break;
739  if (indx == mtIDs.size()) {
740  // not found so add it to mtIDs and add another element to mCnt
741  mtIDs.push_back(tIDs);
742  mCnt.push_back(0);
743  }
744  ++mCnt[indx];
745  if (mCnt[indx] == maxCnt) {
746  // add the Tjs to the list
747  tMaxed.insert(tMaxed.end(), tIDs[0]);
748  tMaxed.insert(tMaxed.end(), tIDs[1]);
749  tMaxed.insert(tMaxed.end(), tIDs[2]);
750  break;
751  } // hit maxCnt
752  ++cnt;
753  } // sptHit
754 
755  std::vector<SortEntry> sortVec;
756  for (unsigned short indx = 0; indx < mCnt.size(); ++indx) {
757  auto& tIDs = mtIDs[indx];
758  // find the fraction of TPs on the shortest tj that are matched
759  float minTPCnt = USHRT_MAX;
760  for (auto tid : tIDs) {
761  auto& tj = slc.tjs[tid - 1];
762  float tpcnt = NumPtsWithCharge(slc, tj, false);
763  if (tpcnt < minTPCnt) minTPCnt = tpcnt;
764  } // tid
765  float frac = (float)mCnt[indx] / minTPCnt;
766  // ignore matches with a very low match fraction
767  if (frac < 0.05) continue;
768  SortEntry se;
769  se.index = indx;
770  se.val = mCnt[indx];
771  sortVec.push_back(se);
772  } // ii
773  if (sortVec.size() > 1) std::sort(sortVec.begin(), sortVec.end(), valsDecreasing);
774 
775  matVec.resize(sortVec.size());
776 
777  for (unsigned short ii = 0; ii < sortVec.size(); ++ii) {
778  unsigned short indx = sortVec[ii].index;
779  auto& ms = matVec[ii];
780  ms.Count = mCnt[indx];
781  ms.TjIDs.resize(3);
782  for (unsigned short plane = 0; plane < 3; ++plane)
783  ms.TjIDs[plane] = mtIDs[indx][plane];
784  } // indx
785 
786  } // Match3PlanesSpt
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< std::array< unsigned int, 3 > > sptHits
SpacePoint -> Hits assns by plane.
Definition: DataStructs.h:625
std::vector< float > match3DCuts
3D matching cuts
Definition: DataStructs.h:551
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
bool valsDecreasing(const SortEntry &c1, const SortEntry &c2)
Definition: Utils.cxx:39
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
TCEvent evt
Definition: DataStructs.cxx:8
bool SptInTPC(const std::array< unsigned int, 3 > &sptHits, unsigned int tpc)
Definition: PFPUtils.cxx:789
float tca::MaxChargeAsymmetry ( TCSlice slc,
std::vector< int > const &  tjIDs 
)

Definition at line 378 of file Utils.cxx.

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

379  {
380  // calculates the maximum charge asymmetry in all planes using the supplied list of Tjs
381  if (tjIDs.size() < 2) return 1;
382  std::vector<float> plnchg(slc.nPlanes);
383  for (auto tjid : tjIDs) {
384  if (tjid <= 0 || tjid > (int)slc.tjs.size()) return 1;
385  auto& tj = slc.tjs[tjid - 1];
386  if (tj.TotChg == 0) UpdateTjChgProperties("MCA", slc, tj, false);
387  unsigned short plane = DecodeCTP(tj.CTP).Plane;
388  plnchg[plane] += tj.TotChg;
389  } // tjid
390  float aveChg = 0;
391  float cnt = 0;
392  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
393  if (plnchg[plane] == 0) continue;
394  aveChg += plnchg[plane];
395  ++cnt;
396  } // plane
397  if (cnt < 2) return 1;
398  aveChg /= cnt;
399  float maxAsym = 0;
400  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
401  // ignore zeros
402  if (plnchg[plane] == 0) continue;
403  float asym = std::abs(plnchg[plane] - aveChg) / (plnchg[plane] + aveChg);
404  if (asym > maxAsym) maxAsym = asym;
405  } // plane
406  return maxAsym;
407  } // MaxChargeAsymmetry
constexpr auto abs(T v)
Returns the absolute value of the argument.
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice const &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3577
geo::PlaneID DecodeCTP(CTP_t CTP)
float tca::MaxHitDelta ( TCSlice slc,
Trajectory tj 
)

Definition at line 3202 of file Utils.cxx.

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

Referenced by CheckHiMultUnusedHits(), and FillGaps().

3203  {
3204  float delta, md = 0;
3205  unsigned short ii;
3206  unsigned int iht;
3207  for (auto& tp : tj.Pts) {
3208  for (ii = 0; ii < tp.Hits.size(); ++ii) {
3209  if (!tp.UseHit[ii]) continue;
3210  iht = tp.Hits[ii];
3211  delta = PointTrajDOCA(slc, iht, tp);
3212  if (delta > md) md = delta;
3213  } // ii
3214  } // pts
3215  return md;
3216  } // MaxHitDelta
float PointTrajDOCA(float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2524
float tca::MaxTjLen ( const TCSlice slc,
std::vector< int > &  tjIDs 
)

Definition at line 2567 of file Utils.cxx.

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

Referenced by MakePFParticles().

2568  {
2569  // returns the length of the longest Tj in the supplied list
2570  if (tjIDs.empty()) return 0;
2571  float maxLen = 0;
2572  for (auto tjid : tjIDs) {
2573  if (tjid < 1 || tjid > (int)slc.tjs.size()) continue;
2574  auto& tj = slc.tjs[tjid - 1];
2575  float sep2 = PosSep2(tj.Pts[tj.EndPt[0]].Pos, tj.Pts[tj.EndPt[1]].Pos);
2576  if (sep2 > maxLen) maxLen = sep2;
2577  } // tj
2578  return sqrt(maxLen);
2579  } // MaxTjLen
float PosSep2(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2604
short tca::MCSMom ( const TCSlice slc,
const std::vector< int > &  tjIDs 
)

Definition at line 3381 of file Utils.cxx.

References tca::TCSlice::tjs.

Referenced by CheckTraj(), DotProd(), FillGaps(), FindHammerVertices2(), FindParent(), Forecast(), IsGhost(), MakePFParticles(), MakePFPTjs(), MCSMom(), MergeNearby2DShowers(), MergeSubShowersTj(), PDGCodeVote(), PrintP(), PrintPFP(), SplitTraj(), UpdateStiffEl(), and UpdateTraj().

3382  {
3383  // Find the average MCSMom of the trajectories
3384  if (tjIDs.empty()) return 0;
3385  float summ = 0;
3386  float suml = 0;
3387  for (auto tjid : tjIDs) {
3388  auto& tj = slc.tjs[tjid - 1];
3389  float npts = tj.EndPt[1] - tj.EndPt[0] + 1;
3390  summ += npts * tj.MCSMom;
3391  suml += npts;
3392  } // tjid
3393  return (short)(summ / suml);
3394  } // MCSMom
short tca::MCSMom ( const TCSlice slc,
const Trajectory tj 
)

Definition at line 3397 of file Utils.cxx.

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

3398  {
3399  return MCSMom(slc, tj, tj.EndPt[0], tj.EndPt[1]);
3400  } // MCSMom
short MCSMom(const TCSlice &slc, const Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:3403
short tca::MCSMom ( const TCSlice slc,
const Trajectory tj,
unsigned short  firstPt,
unsigned short  lastPt 
)

Definition at line 3403 of file Utils.cxx.

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

3407  {
3408  // Estimate the trajectory momentum using Multiple Coulomb Scattering ala PDG RPP
3409 
3410  if (firstPt == lastPt) return 0;
3411  if (firstPt > lastPt) std::swap(firstPt, lastPt);
3412 
3413  firstPt = NearestPtWithChg(tj, firstPt);
3414  lastPt = NearestPtWithChg(tj, lastPt);
3415  if (firstPt >= lastPt) return 0;
3416 
3417  if (firstPt < tj.EndPt[0]) return 0;
3418  if (lastPt > tj.EndPt[1]) return 0;
3419  // Can't do this with only 2 points
3420  if (NumPtsWithCharge(slc, tj, false, firstPt, lastPt) < 3) return 0;
3421  // Ignore junk Tjs
3422  if (tj.AlgMod[kJunkTj]) return 0;
3423 
3424  double tjLen = TrajPointSeparation(tj.Pts[firstPt], tj.Pts[lastPt]);
3425  if (tjLen < 1) return 0;
3426  // mom calculated in MeV
3427  double thetaRMS = MCSThetaRMS(tj, firstPt, lastPt);
3428  if (thetaRMS < 0.001) return 999;
3429  double mom = 13.8 * sqrt(tjLen / 14) / thetaRMS;
3430  if (mom > 999) mom = 999;
3431  return (short)mom;
3432  } // MCSMom
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:2080
float TrajPointSeparation(const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2613
double MCSThetaRMS(const Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:3467
unsigned short NearestPtWithChg(const Trajectory &tj, unsigned short thePt)
Definition: Utils.cxx:3435
void swap(lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &a, lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &b)
float tca::MCSThetaRMS ( const Trajectory tj)

Definition at line 3453 of file Utils.cxx.

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

Referenced by DotProd(), and MCSMom().

3454  {
3455  // This returns the MCS scattering angle expected for one WSE unit of travel along the trajectory.
3456  // It is used to define kink and vertex cuts. This should probably be named something different to
3457  // prevent confusion
3458 
3459  float tps = TrajPointSeparation(tj.Pts[tj.EndPt[0]], tj.Pts[tj.EndPt[1]]);
3460  if (tps < 1) return 1;
3461 
3462  return MCSThetaRMS(tj, tj.EndPt[0], tj.EndPt[1]) / sqrt(tps);
3463 
3464  } // MCSThetaRMS
float TrajPointSeparation(const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2613
double MCSThetaRMS(const Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:3467
double tca::MCSThetaRMS ( const Trajectory tj,
unsigned short  firstPt,
unsigned short  lastPt 
)

Definition at line 3467 of file Utils.cxx.

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

3468  {
3469  // This returns the MCS scattering angle expected for the length of the trajectory
3470  // spanned by firstPt to lastPt. It is used primarily to calculate MCSMom
3471 
3472  if (firstPt < tj.EndPt[0]) return 1;
3473  if (lastPt > tj.EndPt[1]) return 1;
3474 
3475  firstPt = NearestPtWithChg(tj, firstPt);
3476  lastPt = NearestPtWithChg(tj, lastPt);
3477  if (firstPt >= lastPt) return 1;
3478 
3479  double sigmaS;
3480  unsigned short cnt;
3481  TjDeltaRMS(tj, firstPt, lastPt, sigmaS, cnt);
3482  if (sigmaS < 0) return 1;
3483  double tjLen = TrajPointSeparation(tj.Pts[firstPt], tj.Pts[lastPt]);
3484  if (tjLen < 1) return 1;
3485  // Theta_o = 4 * sqrt(3) * sigmaS / path
3486  return (6.8 * sigmaS / tjLen);
3487 
3488  } // MCSThetaRMS
float TrajPointSeparation(const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2613
unsigned short NearestPtWithChg(const Trajectory &tj, unsigned short thePt)
Definition: Utils.cxx:3435
void TjDeltaRMS(const Trajectory &tj, unsigned short firstPt, unsigned short lastPt, double &rms, unsigned short &cnt)
Definition: Utils.cxx:3491
bool tca::MergeAndStore ( TCSlice slc,
unsigned int  itj1,
unsigned int  itj2,
bool  doPrt 
)

Not allowed

Definition at line 4521 of file Utils.cxx.

References tca::Trajectory::AlgMod, AttachAnyVertexToTraj(), tca::Trajectory::EndFlag, tca::Trajectory::EndPt, GetPFPIndex(), HasDuplicateHits(), tca::Trajectory::ID, kBragg, kDeltaRay, kHaloTj, kKilled, kMichel, kShowerTj, MakeTrajectoryObsolete(), MakeVertexObsolete(), MergeShowerTjsAndStore(), tca::Trajectory::NeedsUpdate, tca::Trajectory::ParentID, PosSep2(), PrintPos(), tca::Trajectory::Pts, ReverseTraj(), SetEndPoints(), SetPDGCode(), tca::Trajectory::StepDir, StoreTraj(), tca::TCSlice::tjs, TrajPointTrajDOCA(), tca::Trajectory::VtxID, tca::TCSlice::vtxs, and tca::Trajectory::WorkID.

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

4522  {
4523  // Merge the two trajectories in allTraj and store them. Returns true if it was successfull.
4524  // Merging is done between the end (end = 1) of tj1 and the beginning (end = 0) of tj2. This function preserves the
4525  // AlgMod state of itj1.
4526  // The itj1 -> itj2 merge order is reversed if end1 of itj2 is closer to end0 of itj1
4527 
4528  if (itj1 > slc.tjs.size() - 1) return false;
4529  if (itj2 > slc.tjs.size() - 1) return false;
4530  if (slc.tjs[itj1].AlgMod[kKilled] || slc.tjs[itj2].AlgMod[kKilled]) return false;
4531  if (slc.tjs[itj1].AlgMod[kHaloTj] || slc.tjs[itj2].AlgMod[kHaloTj]) return false;
4532 
4533  // Merging shower Tjs requires merging the showers as well.
4534  if (slc.tjs[itj1].AlgMod[kShowerTj] || slc.tjs[itj2].AlgMod[kShowerTj])
4535  return MergeShowerTjsAndStore(slc, itj1, itj2, doPrt);
4536 
4537  // Ensure that the order of 3D-matched Tjs is consistent with the convention that
4538  unsigned short pfp1 = GetPFPIndex(slc, slc.tjs[itj1].ID);
4539  unsigned short pfp2 = GetPFPIndex(slc, slc.tjs[itj2].ID);
4540  if (pfp1 != USHRT_MAX || pfp2 != USHRT_MAX) {
4541  if (pfp1 != USHRT_MAX && pfp2 != USHRT_MAX) return false;
4542  // Swap so that the order of tj1 is preserved. Tj2 may be reversed to be consistent
4543  if (pfp1 == USHRT_MAX) std::swap(itj1, itj2);
4544  } // one or both used in a PFParticle
4545 
4546  // make copies so they can be trimmed as needed
4547  Trajectory tj1 = slc.tjs[itj1];
4548  Trajectory tj2 = slc.tjs[itj2];
4549 
4550  // ensure that these are in the same step order
4551  if (tj2.StepDir != tj1.StepDir) ReverseTraj(tj2);
4552 
4553  Point2_t tp1e0 = tj1.Pts[tj1.EndPt[0]].Pos;
4554  Point2_t tp1e1 = tj1.Pts[tj1.EndPt[1]].Pos;
4555  Point2_t tp2e0 = tj2.Pts[tj2.EndPt[0]].Pos;
4556  Point2_t tp2e1 = tj2.Pts[tj2.EndPt[1]].Pos;
4557 
4558  if (doPrt) {
4559  mf::LogVerbatim("TC") << "MergeAndStore: T" << tj1.ID << " and T" << tj2.ID
4560  << " at merge points " << PrintPos(tp1e1) << " " << PrintPos(tp2e0);
4561  }
4562 
4563  // swap the order so that abs(tj1end1 - tj2end0) is less than abs(tj2end1 - tj1end0)
4564  if (PosSep2(tp1e1, tp2e0) > PosSep2(tp2e1, tp1e0)) {
4565  std::swap(tj1, tj2);
4566  std::swap(tp1e0, tp2e0);
4567  std::swap(tp1e1, tp2e1);
4568  if (doPrt)
4569  mf::LogVerbatim("TC") << " swapped the order. Merge points " << PrintPos(tp1e1) << " "
4570  << PrintPos(tp2e0);
4571  }
4572 
4573  // Here is what we are looking for, where - indicates a TP with charge.
4574  // Note that this graphic is in the stepping direction (+1 = +wire direction)
4575  // tj1: 0------------1
4576  // tj2: 0-----------1
4577  // Another possibility with overlap
4578  // tj1: 0-------------1
4579  // tj2: 0--------------1
4580 
4581  if (tj1.StepDir > 1) {
4582  // Not allowed
4583  // tj1: 0---------------------------1
4584  // tj2: 0------1
4585  if (tp2e0[0] > tp1e0[0] && tp2e1[0] < tp1e1[0]) return false;
4587  // tj1: 0------1
4588  // tj2: 0---------------------------1
4589  if (tp1e0[0] > tp2e0[0] && tp1e1[0] < tp2e1[0]) return false;
4590  }
4591  else {
4592  // same as above but with ends reversed
4593  if (tp2e1[0] > tp1e1[0] && tp2e0[0] < tp1e0[0]) return false;
4594  if (tp1e1[0] > tp2e1[0] && tp1e0[0] < tp2e0[0]) return false;
4595  }
4596 
4597  if (tj1.VtxID[1] > 0 && tj2.VtxID[0] == tj1.VtxID[1]) {
4598  auto& vx = slc.vtxs[tj1.VtxID[1] - 1];
4599  if (!MakeVertexObsolete("MAS", slc, vx, false)) {
4600  if (doPrt)
4601  mf::LogVerbatim("TC") << "MergeAndStore: Found a good vertex between Tjs " << tj1.VtxID[1]
4602  << " No merging";
4603  return false;
4604  }
4605  }
4606 
4607  if (tj1.EndFlag[1][kBragg]) {
4608  if (doPrt)
4609  mf::LogVerbatim("TC") << "MergeAndStore: You are merging the end of trajectory T" << tj1.ID
4610  << " with a Bragg peak. Not merging\n";
4611  return false;
4612  }
4613 
4614  // remove any points at the end of tj1 that don't have used hits
4615  tj1.Pts.resize(tj1.EndPt[1] + 1);
4616 
4617  // determine if they overlap by finding the point on tj2 that is closest
4618  // to the end point of tj1.
4619  TrajPoint& endtj1TP = tj1.Pts[tj1.EndPt[1]];
4620  // Set minSep large so that dead wire regions are accounted for
4621  float minSep = 1000;
4622  unsigned short tj2ClosePt = 0;
4623  // Note that TrajPointTrajDOCA only considers TPs that have charge
4624  TrajPointTrajDOCA(endtj1TP, tj2, tj2ClosePt, minSep);
4625  if (doPrt)
4626  mf::LogVerbatim("TC") << " Merge point tj1 " << PrintPos(endtj1TP) << " tj2ClosePt "
4627  << tj2ClosePt << " Pos " << PrintPos(tj2.Pts[tj2ClosePt]);
4628  // check for full overlap
4629  if (tj2ClosePt > tj2.EndPt[1]) return false;
4630 
4631  // The approach is to append tj2 to tj1, store tj1 as a new trajectory,
4632  // and re-assign all hits to the new trajectory
4633 
4634  // First ensure that any hit will appear only once in the merged trajectory in the overlap region
4635  // whether it is used or unused. The point on tj2 where the merge will begin, tj2ClosePt, will be
4636  // increased until this condition is met.
4637  // Make a temporary vector of tj1 hits in the end points for simpler searching
4638  std::vector<unsigned int> tj1Hits;
4639  for (unsigned short ii = 0; ii < tj1.Pts.size(); ++ii) {
4640  // only go back a few points in tj1
4641  if (ii > 10) break;
4642  unsigned short ipt = tj1.Pts.size() - 1 - ii;
4643  tj1Hits.insert(tj1Hits.end(), tj1.Pts[ipt].Hits.begin(), tj1.Pts[ipt].Hits.end());
4644  if (ipt == 0) break;
4645  } // ii
4646 
4647  bool bumpedPt = true;
4648  while (bumpedPt) {
4649  bumpedPt = false;
4650  for (unsigned short ii = 0; ii < tj2.Pts[tj2ClosePt].Hits.size(); ++ii) {
4651  unsigned int iht = tj2.Pts[tj2ClosePt].Hits[ii];
4652  if (std::find(tj1Hits.begin(), tj1Hits.end(), iht) != tj1Hits.end()) bumpedPt = true;
4653  } // ii
4654  if (bumpedPt && tj2ClosePt < tj2.EndPt[1]) { ++tj2ClosePt; }
4655  else {
4656  break;
4657  }
4658  } // bumpedPt
4659  if (doPrt) mf::LogVerbatim("TC") << " revised tj2ClosePt " << tj2ClosePt;
4660  // append tj2 hits to tj1
4661 
4662  tj1.Pts.insert(tj1.Pts.end(), tj2.Pts.begin() + tj2ClosePt, tj2.Pts.end());
4663  // re-define the end points
4664  SetEndPoints(tj1);
4665  tj1.EndFlag[1] = tj2.EndFlag[1];
4666 
4667  // A more exhaustive check that hits only appear once
4668  if (HasDuplicateHits(slc, tj1, doPrt)) return false;
4669  if (tj2.VtxID[1] > 0) {
4670  // move the end vertex of tj2 to the end of tj1
4671  tj1.VtxID[1] = tj2.VtxID[1];
4672  }
4673  // Transfer some of the AlgMod bits
4674  if (tj2.AlgMod[kMichel]) tj1.AlgMod[kMichel] = true;
4675  if (tj2.AlgMod[kDeltaRay]) {
4676  tj1.AlgMod[kDeltaRay] = true;
4677  tj1.ParentID = tj2.ParentID;
4678  }
4679  // keep track of the IDs before they are clobbered
4680  int tj1ID = tj1.ID;
4681  int tj2ID = tj2.ID;
4682  // kill the original trajectories
4683  MakeTrajectoryObsolete(slc, itj1);
4684  MakeTrajectoryObsolete(slc, itj2);
4685  // Do this so that StoreTraj keeps the correct WorkID (of itj1)
4686  tj1.ID = tj1.WorkID;
4687  SetPDGCode(slc, tj1);
4688  tj1.NeedsUpdate = true;
4689  if (!StoreTraj(slc, tj1)) return false;
4690  int newTjID = slc.tjs.size();
4691  // Use the ParentID to trace which new Tj is superseding the merged ones
4692  tj1.ParentID = newTjID;
4693  tj2.ParentID = newTjID;
4694  if (doPrt) mf::LogVerbatim("TC") << " MAS success. Created T" << newTjID;
4695  // Transfer the ParentIDs of any other Tjs that refer to Tj1 and Tj2 to the new Tj
4696  for (auto& tj : slc.tjs)
4697  if (tj.ParentID == tj1ID || tj.ParentID == tj2ID) tj.ParentID = newTjID;
4698  // try to attach it to a vertex
4699  AttachAnyVertexToTraj(slc, newTjID, doPrt);
4700  return true;
4701  } // MergeAndStore
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:2698
bool AttachAnyVertexToTraj(TCSlice &slc, int tjID, bool prt)
Definition: TCVertex.cxx:1637
bool StoreTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:1074
std::string PrintPos(const Point2_t &pos)
Definition: Utils.cxx:6362
std::array< float, 2 > Point2_t
Definition: DataStructs.h:41
bool MergeShowerTjsAndStore(TCSlice &slc, unsigned short istj, unsigned short jstj, bool prt)
Definition: TCShower.cxx:2978
void MakeTrajectoryObsolete(TCSlice &slc, unsigned int itj)
Definition: Utils.cxx:2138
unsigned short GetPFPIndex(const TCSlice &slc, int tjID)
Definition: Utils.cxx:1038
float PosSep2(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2604
void swap(lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &a, lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &b)
void TrajPointTrajDOCA(TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
Definition: Utils.cxx:2384
void SetPDGCode(TCSlice const &slc, Trajectory &tj)
Definition: Utils.cxx:4226
bool HasDuplicateHits(const TCSlice &slc, Trajectory const &tj, bool prt)
Definition: Utils.cxx:2745
void ReverseTraj(Trajectory &tj)
Definition: Utils.cxx:3219
void tca::MergeGhostTjs ( TCSlice slc,
CTP_t  inCTP 
)

Definition at line 2172 of file Utils.cxx.

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

2173  {
2174  // Merges short Tjs that share many hits with a longer Tj
2175  if (!tcc.useAlg[kMrgGhost]) return;
2176 
2177  for (auto& shortTj : slc.tjs) {
2178  if (shortTj.AlgMod[kKilled] || shortTj.AlgMod[kHaloTj]) continue;
2179  if (shortTj.CTP != inCTP) continue;
2180  unsigned short spts = shortTj.EndPt[1] - shortTj.EndPt[0];
2181  if (spts > 20) continue;
2182  // ignore delta rays
2183  if (shortTj.PDGCode == 11) continue;
2184  // ignore InShower Tjs
2185  if (shortTj.SSID > 0) continue;
2186  auto tjhits = PutTrajHitsInVector(shortTj, kAllHits);
2187  if (tjhits.empty()) continue;
2188  std::vector<int> tids;
2189  std::vector<unsigned short> tcnt;
2190  for (auto iht : tjhits) {
2191  auto& hit = slc.slHits[iht];
2192  if (hit.InTraj <= 0) continue;
2193  if ((unsigned int)hit.InTraj > slc.tjs.size()) continue;
2194  if (hit.InTraj == shortTj.ID) continue;
2195  unsigned short indx = 0;
2196  for (indx = 0; indx < tids.size(); ++indx)
2197  if (hit.InTraj == tids[indx]) break;
2198  if (indx == tids.size()) {
2199  tids.push_back(hit.InTraj);
2200  tcnt.push_back(1);
2201  }
2202  else {
2203  ++tcnt[indx];
2204  }
2205  } // iht
2206  if (tids.empty()) continue;
2207  // find the max count for Tjs that are longer than this one
2208  unsigned short maxcnt = 0;
2209  for (unsigned short indx = 0; indx < tids.size(); ++indx) {
2210  if (tcnt[indx] > maxcnt) {
2211  auto& ltj = slc.tjs[tids[indx] - 1];
2212  unsigned short lpts = ltj.EndPt[1] - ltj.EndPt[0];
2213  if (lpts < spts) continue;
2214  maxcnt = tcnt[indx];
2215  }
2216  } // indx
2217  float hitFrac = (float)maxcnt / (float)tjhits.size();
2218  if (hitFrac < 0.1) continue;
2219  } // shortTj
2220  } // MergeGhostTjs
std::vector< unsigned int > PutTrajHitsInVector(const Trajectory &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2689
TCConfig tcc
Definition: DataStructs.cxx:9
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:578
void tca::MergeNearby2DShowers ( std::string  inFcnLabel,
TCSlice slc,
const CTP_t inCTP,
bool  prt 
)

Definition at line 2279 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, tcc, tca::ShowerStruct::TjIDs, tca::TCSlice::tjs, and tca::TCConfig::useAlg.

Referenced by FindShowers3D().

2280  {
2281  if (!tcc.useAlg[kMergeNrShowers]) return;
2282  if (slc.cots.empty()) return;
2283 
2284  std::string fcnLabel = inFcnLabel + ".MNS";
2285 
2286  if (prt) {
2287  mf::LogVerbatim myprt("TC");
2288  myprt << fcnLabel << " list";
2289  for (auto& ss : slc.cots) {
2290  if (ss.CTP != inCTP) continue;
2291  if (ss.ID == 0) continue;
2292  myprt << " ss.ID " << ss.ID << " NearTjs";
2293  for (auto& id : ss.NearTjIDs)
2294  myprt << " " << id;
2295  myprt << "\n";
2296  }
2297  } // prt
2298 
2299  bool keepMerging = true;
2300  while (keepMerging) {
2301  keepMerging = false;
2302  for (unsigned short ci1 = 0; ci1 < slc.cots.size() - 1; ++ci1) {
2303  ShowerStruct& ss1 = slc.cots[ci1];
2304  if (ss1.CTP != inCTP) continue;
2305  if (ss1.ID == 0) continue;
2306  if (ss1.TjIDs.empty()) continue;
2307  // put the inshower tjs and the nearby tjs into one list
2308  std::vector<int> ss1list = ss1.TjIDs;
2309  ss1list.insert(ss1list.end(), ss1.NearTjIDs.begin(), ss1.NearTjIDs.end());
2310  for (unsigned short ci2 = ci1 + 1; ci2 < slc.cots.size(); ++ci2) {
2311  ShowerStruct& ss2 = slc.cots[ci2];
2312  if (ss2.CTP != inCTP) continue;
2313  if (ss2.ID == 0) continue;
2314  if (ss2.TjIDs.empty()) continue;
2315  if (DontCluster(slc, ss1.TjIDs, ss2.TjIDs)) continue;
2316  std::vector<int> ss2list = ss2.TjIDs;
2317  ss2list.insert(ss2list.end(), ss2.NearTjIDs.begin(), ss2.NearTjIDs.end());
2318  std::vector<int> shared = SetIntersection(ss1list, ss2list);
2319  if (shared.empty()) continue;
2320  if (prt) {
2321  mf::LogVerbatim myprt("TC");
2322  myprt << fcnLabel << " Merge 2S" << ss2.ID << " into 2S" << ss1.ID
2323  << "? shared nearby:";
2324  for (auto tjid : shared)
2325  myprt << " T" << tjid;
2326  } // prt
2327  // add the shared Tjs to ss1 if they meet the requirements
2328  bool doMerge = false;
2329  for (auto& tjID : shared) {
2330  bool inSS1 = (std::find(ss1.TjIDs.begin(), ss1.TjIDs.end(), tjID) != ss1.TjIDs.end());
2331  bool inSS2 = (std::find(ss2.TjIDs.begin(), ss2.TjIDs.end(), tjID) != ss2.TjIDs.end());
2332  if (inSS1 && !inSS2) doMerge = true;
2333  if (!inSS1 && inSS2) doMerge = true;
2334  // need to add it?
2335  if (inSS1 || inSS2) continue;
2336  auto& tj = slc.tjs[tjID - 1];
2337  // ignore long muons
2338  if (tj.PDGCode == 13 && tj.Pts.size() > 100 && tj.ChgRMS < 0.5) {
2339  if (prt)
2340  mf::LogVerbatim("TC")
2341  << fcnLabel << " T" << tj.ID << " looks like a muon. Don't add it";
2342  continue;
2343  }
2344  // see if it looks like a muon in 3D
2345  if (tj.AlgMod[kMat3D]) {
2346  auto TInP = GetAssns(slc, "T", tj.ID, "P");
2347  if (!TInP.empty()) {
2348  auto& pfp = slc.pfps[TInP[0] - 1];
2349  if (pfp.PDGCode == 13 && MCSMom(slc, pfp.TjIDs) > 500) continue;
2350  } // TInP not empty
2351  } // 3D matched
2352  if (AddTj(fcnLabel, slc, tjID, ss1, false, prt)) doMerge = true;
2353  } // tjID
2354  if (!doMerge) continue;
2355  if (MergeShowersAndStore(fcnLabel, slc, ss1.ID, ss2.ID, prt)) {
2356  Trajectory& stj = slc.tjs[ss1.ShowerTjID - 1];
2357  stj.AlgMod[kMergeNrShowers] = true;
2358  if (prt) mf::LogVerbatim("TC") << fcnLabel << " success";
2359  keepMerging = true;
2360  break;
2361  }
2362  } // ci2
2363  } // ci1
2364  } // keepMerging
2365 
2366  ChkAssns(fcnLabel, slc);
2367 
2368  } //MergeNearby2DShowers
bool AddTj(std::string inFcnLabel, TCSlice &slc, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1429
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3381
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4095
TCConfig tcc
Definition: DataStructs.cxx:9
bool DontCluster(TCSlice const &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3213
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
Definition: Utils.h:385
bool MergeShowersAndStore(std::string inFcnLabel, TCSlice &slc, int icotID, int jcotID, bool prt)
Definition: TCShower.cxx:2908
std::vector< int > GetAssns(TCSlice const &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4704
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
void tca::MergeOverlap ( std::string  inFcnLabel,
TCSlice slc,
const CTP_t inCTP,
bool  prt 
)

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

2372  {
2373  // Merge showers whose envelopes overlap each other
2374 
2375  /*
2376  # 0 Mode (<= 0 OFF, 1 = find showers before 3D match, 2 = find showers after 3D match)
2377  # 1 Max Tj MCSMom for a shower tag
2378  # 2 Max separation
2379  # 3 Min energy (MeV)
2380  # 4 rms width factor
2381  # 5 Min shower 1/2 width (WSE units)
2382  # 6 Min total Tj Pts
2383  # 7 Min Tjs
2384  # 8 max parent FOM
2385  # 9 max direction FOM
2386  # 10 max aspect ratio
2387  # 11 Debug in CTP (>10 debug cotID + 10)
2388  */
2389 
2390  if (tcc.showerTag[2] <= 0) return;
2391  if (!tcc.useAlg[kMergeOverlap]) return;
2392  if (slc.cots.empty()) return;
2393 
2394  std::string fcnLabel = inFcnLabel + ".MO";
2395 
2396  // Require that the maximum separation is about two radiation lengths
2397  if (prt)
2398  mf::LogVerbatim("TC") << fcnLabel << " checking using separation cut " << tcc.showerTag[2];
2399 
2400  float sepCut2 = tcc.showerTag[2] * tcc.showerTag[2];
2401 
2402  // Iterate if a merge is done
2403  bool didMerge = true;
2404  while (didMerge) {
2405  didMerge = false;
2406  // See if the envelopes overlap
2407  for (unsigned short ict = 0; ict < slc.cots.size() - 1; ++ict) {
2408  auto& iss = slc.cots[ict];
2409  if (iss.ID == 0) continue;
2410  if (iss.TjIDs.empty()) continue;
2411  if (iss.CTP != inCTP) continue;
2412  for (unsigned short jct = ict + 1; jct < slc.cots.size(); ++jct) {
2413  auto& jss = slc.cots[jct];
2414  if (jss.ID == 0) continue;
2415  if (jss.TjIDs.empty()) continue;
2416  if (jss.CTP != iss.CTP) continue;
2417  if (DontCluster(slc, iss.TjIDs, jss.TjIDs)) continue;
2418  bool doMerge = false;
2419  for (auto& ivx : iss.Envelope) {
2420  doMerge = PointInsideEnvelope(ivx, jss.Envelope);
2421  if (doMerge) break;
2422  } // ivx
2423  if (!doMerge) {
2424  for (auto& jvx : jss.Envelope) {
2425  doMerge = PointInsideEnvelope(jvx, iss.Envelope);
2426  if (doMerge) break;
2427  } // ivx
2428  }
2429  if (!doMerge) {
2430  // check proximity between the envelopes
2431  for (auto& ivx : iss.Envelope) {
2432  for (auto& jvx : jss.Envelope) {
2433  if (PosSep2(ivx, jvx) < sepCut2) {
2434  if (prt)
2435  mf::LogVerbatim("TC")
2436  << fcnLabel << " Envelopes 2S" << iss.ID << " 2S" << jss.ID << " are close "
2437  << PosSep(ivx, jvx) << " cut " << tcc.showerTag[2];
2438  doMerge = true;
2439  break;
2440  }
2441  } // jvx
2442  if (doMerge) break;
2443  } // ivx
2444  } // !domerge
2445  if (!doMerge) continue;
2446  // check the relative positions and angle differences. Determine which tps are the
2447  // closest. Don't merge if the closest points are at the shower start and the angle
2448  // difference is large
2449  unsigned short iClosePt = 0;
2450  unsigned short jClosePt = 0;
2451  float close = 1E6;
2452  auto& istj = slc.tjs[iss.ShowerTjID - 1];
2453  auto& jstj = slc.tjs[jss.ShowerTjID - 1];
2454  for (unsigned short ipt = 0; ipt < 3; ++ipt) {
2455  for (unsigned short jpt = 0; jpt < 3; ++jpt) {
2456  float sep = PosSep2(istj.Pts[ipt].Pos, jstj.Pts[jpt].Pos);
2457  if (sep < close) {
2458  close = sep;
2459  iClosePt = ipt;
2460  jClosePt = jpt;
2461  }
2462  } // jpt
2463  } // ipt
2464  float costh = DotProd(istj.Pts[0].Dir, jstj.Pts[0].Dir);
2465  if (iClosePt == 0 && jClosePt == 0 && costh < 0.955) {
2466  if (prt)
2467  mf::LogVerbatim("TC")
2468  << fcnLabel << " showers are close at the start points with costh " << costh
2469  << ". Don't merge";
2470  continue;
2471  }
2472  if (prt) mf::LogVerbatim("TC") << fcnLabel << " Merge " << iss.ID << " and " << jss.ID;
2473  if (MergeShowersAndStore(fcnLabel, slc, iss.ID, jss.ID, prt)) {
2474  Trajectory& stj = slc.tjs[iss.ShowerTjID - 1];
2475  stj.AlgMod[kMergeOverlap] = true;
2476  didMerge = true;
2477  break;
2478  }
2479  else {
2480  if (prt) mf::LogVerbatim("TC") << fcnLabel << " Merge failed";
2481  }
2482  } // jct
2483  } // ict
2484  } // didMerge
2485 
2486  ChkAssns(fcnLabel, slc);
2487 
2488  } // MergeOverlap
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4095
TCConfig tcc
Definition: DataStructs.cxx:9
bool DontCluster(TCSlice const &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3213
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:549
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:3246
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2560
bool MergeShowersAndStore(std::string inFcnLabel, TCSlice &slc, int icotID, int jcotID, bool prt)
Definition: TCShower.cxx:2908
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:126
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
in close()
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
void tca::MergeShowerChain ( std::string  inFcnLabel,
TCSlice slc,
const CTP_t inCTP,
bool  prt 
)

Definition at line 2491 of file TCShower.cxx.

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

Referenced by FindShowers3D().

2492  {
2493  // Merge chains of 3 or more showers that lie on a line
2494 
2495  if (!tcc.useAlg[kMergeShChain]) return;
2496 
2497  std::string fcnLabel = inFcnLabel + ".MSC";
2498 
2499  if (prt) mf::LogVerbatim("TC") << fcnLabel << ": MergeShowerChain inCTP " << inCTP;
2500 
2501  std::vector<int> sids;
2502  std::vector<TrajPoint> tpList;
2503  for (unsigned short ict = 0; ict < slc.cots.size(); ++ict) {
2504  ShowerStruct& iss = slc.cots[ict];
2505  if (iss.ID == 0) continue;
2506  if (iss.TjIDs.empty()) continue;
2507  if (iss.CTP != inCTP) continue;
2508  // ignore wimpy showers
2509  if (iss.Energy < 50) continue;
2510  // save the shower ID
2511  sids.push_back(iss.ID);
2512  // and the shower center TP
2513  tpList.push_back(slc.tjs[iss.ShowerTjID - 1].Pts[1]);
2514  } // ict
2515  if (sids.size() < 3) return;
2516 
2517  // sort by wire so the chain order is reasonable
2518  std::vector<SortEntry> sortVec(sids.size());
2519  for (unsigned short ii = 0; ii < sortVec.size(); ++ii) {
2520  sortVec[ii].index = ii;
2521  sortVec[ii].val = tpList[ii].Pos[0];
2522  }
2523  std::sort(sortVec.begin(), sortVec.end(), valsDecreasing);
2524  auto tsids = sids;
2525  auto ttpList = tpList;
2526  for (unsigned short ii = 0; ii < sortVec.size(); ++ii) {
2527  unsigned short indx = sortVec[ii].index;
2528  sids[ii] = tsids[indx];
2529  tpList[ii] = ttpList[indx];
2530  }
2531 
2532  // TODO: These cuts should be generalized somehow
2533  float minSep = 150;
2534  float maxDelta = 30;
2535  for (unsigned short ii = 0; ii < sids.size() - 2; ++ii) {
2536  auto& iss = slc.cots[sids[ii] - 1];
2537  if (iss.ID == 0) continue;
2538  unsigned short jj = ii + 1;
2539  auto& jss = slc.cots[sids[jj] - 1];
2540  if (jss.ID == 0) continue;
2541  std::vector<int> chain;
2542  float sepij = PosSep(tpList[ii].Pos, tpList[jj].Pos);
2543  if (sepij > minSep) continue;
2544  bool skipit = DontCluster(slc, iss.TjIDs, jss.TjIDs);
2545  if (prt)
2546  mf::LogVerbatim("TC") << fcnLabel << " i2S" << iss.ID << " " << PrintPos(tpList[ii].Pos)
2547  << " j2S" << jss.ID << " " << PrintPos(tpList[jj].Pos) << " sepij "
2548  << sepij << " skipit? " << skipit;
2549  if (skipit) continue;
2550  // draw a line between these points
2551  TrajPoint tp;
2552  MakeBareTrajPoint(tpList[ii], tpList[jj], tp);
2553  for (unsigned short kk = jj + 1; kk < sids.size(); ++kk) {
2554  auto& kss = slc.cots[sids[kk] - 1];
2555  if (kss.ID == 0) continue;
2556  if (DontCluster(slc, iss.TjIDs, kss.TjIDs)) continue;
2557  if (DontCluster(slc, jss.TjIDs, kss.TjIDs)) continue;
2558  float sepjk = PosSep(tpList[jj].Pos, tpList[kk].Pos);
2559  float delta = PointTrajDOCA(tpList[kk].Pos[0], tpList[kk].Pos[1], tp);
2560  if (prt) {
2561  mf::LogVerbatim myprt("TC");
2562  myprt << fcnLabel << " k2S" << kss.ID << " " << PrintPos(tpList[kk].Pos) << " sepjk "
2563  << sepjk << " delta " << delta;
2564  if (sepjk > minSep || delta > maxDelta) {
2565  myprt << " failed separation " << minSep << " or delta cut " << maxDelta;
2566  }
2567  else {
2568  myprt << " add to the chain";
2569  }
2570  } // prt
2571  if (sepjk > minSep || delta > maxDelta) {
2572  // clear a short chain?
2573  if (chain.size() > 2) {
2574  // merge this chain
2575  int newID = MergeShowers(fcnLabel, slc, chain, prt);
2576  if (prt) {
2577  mf::LogVerbatim myprt("TC");
2578  myprt << fcnLabel << " merged chain";
2579  for (auto ssID : chain)
2580  myprt << " 2S" << ssID;
2581  myprt << " -> 2S" << newID;
2582  } // prt
2583  } // long chain
2584  chain.clear();
2585  break;
2586  }
2587  else {
2588  // add this shower to the chain
2589  if (chain.empty()) {
2590  chain.resize(3);
2591  chain[0] = sids[ii];
2592  chain[1] = sids[jj];
2593  chain[2] = sids[kk];
2594  }
2595  else {
2596  chain.push_back(sids[kk]);
2597  }
2598  // Refine the TP position and direction
2599  MakeBareTrajPoint(tpList[ii], tpList[kk], tp);
2600  } // add to an existing chain
2601  } // kk
2602  // push the last one
2603  if (chain.size() > 2) {
2604  int newID = MergeShowers(fcnLabel, slc, chain, prt);
2605  if (prt) {
2606  mf::LogVerbatim myprt("TC");
2607  myprt << fcnLabel << " merged chain";
2608  for (auto ssID : chain)
2609  myprt << " " << ssID;
2610  myprt << " -> new ssID " << newID;
2611  } // prt
2612  } // long chain
2613  } // ii
2614 
2615  ChkAssns(fcnLabel, slc);
2616 
2617  } // MergeShowerChain
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4095
TCConfig tcc
Definition: DataStructs.cxx:9
bool DontCluster(TCSlice const &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3213
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2514
bool MakeBareTrajPoint(const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:4008
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
int MergeShowers(std::string inFcnLabel, TCSlice &slc, std::vector< int > ssIDs, bool prt)
Definition: TCShower.cxx:2847
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
bool valsDecreasing(const SortEntry &c1, const SortEntry &c2)
Definition: Utils.cxx:39
int tca::MergeShowers ( std::string  inFcnLabel,
TCSlice slc,
std::vector< int >  ssIDs,
bool  prt 
)

Definition at line 2847 of file TCShower.cxx.

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

Referenced by MergeShowerChain().

2848  {
2849  // merge a list of showers and return the ID of the merged shower.
2850  // Returns 0 if there was a failure.
2851 
2852  std::string fcnLabel = inFcnLabel + ".MS";
2853  if (ssIDs.size() < 2) return 0;
2854  // check for a valid ID
2855  for (auto ssID : ssIDs)
2856  if (ssID <= 0 || ssID > (int)slc.cots.size()) return 0;
2857  // check for the same CTP and consistent assns
2858  int ss3Assn = 0;
2859  auto& ss0 = slc.cots[ssIDs[0] - 1];
2860  std::vector<int> tjl;
2861  for (auto ssID : ssIDs) {
2862  auto& ss = slc.cots[ssID - 1];
2863  if (ss.CTP != ss0.CTP) return 0;
2864  tjl.insert(tjl.end(), ss.TjIDs.begin(), ss.TjIDs.end());
2865  if (ss.SS3ID > 0 && ss3Assn == 0) ss3Assn = ss.SS3ID;
2866  if (ss.SS3ID > 0 && ss.SS3ID != ss3Assn) return 0;
2867  } // ssID
2868  // ensure the InShower Tjs are valid
2869  for (auto tjID : tjl) {
2870  auto& tj = slc.tjs[tjID - 1];
2871  if (tj.CTP != ss0.CTP || tj.AlgMod[kKilled]) return 0;
2872  } // tjID
2873 
2874  // mark the old showers killed
2875  for (auto ssID : ssIDs) {
2876  auto& ss = slc.cots[ssID - 1];
2877  ss.ID = 0;
2878  // kill the shower Tj
2879  auto& stj = slc.tjs[ss.ShowerTjID - 1];
2880  stj.AlgMod[kKilled] = true;
2881  } // tjID
2882 
2883  // in with the new
2884  auto newss = CreateSS(slc, tjl);
2885  if (newss.ID == 0) return 0;
2886 
2887  for (auto tid : tjl) {
2888  auto& tj = slc.tjs[tid - 1];
2889  tj.SSID = newss.ID;
2890  } // tid
2891  newss.SS3ID = ss3Assn;
2892 
2893  // define the new shower
2894  if (!UpdateShower(fcnLabel, slc, newss, prt)) {
2895  MakeShowerObsolete(fcnLabel, slc, newss, prt);
2896  return 0;
2897  }
2898  // store it
2899  if (!StoreShower(fcnLabel, slc, newss)) {
2900  MakeShowerObsolete(fcnLabel, slc, newss, prt);
2901  return 0;
2902  }
2903  return newss.ID;
2904 
2905  } // MergeShowers
ShowerStruct CreateSS(TCSlice &slc, const std::vector< int > &tjl)
Definition: TCShower.cxx:4049
void MakeShowerObsolete(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3169
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1106
bool StoreShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss)
Definition: TCShower.cxx:3983
bool tca::MergeShowersAndStore ( std::string  inFcnLabel,
TCSlice slc,
int  icotID,
int  jcotID,
bool  prt 
)

Definition at line 2908 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(), and MergeSubShowers().

2909  {
2910  // Merge showers using shower indices. The icotID shower is modified in-place.
2911  // The jcotID shower is declared obsolete. This function also re-defines the shower and
2912  // preserves the icotID Parent ID.
2913 
2914  if (icotID <= 0 || icotID > (int)slc.cots.size()) return false;
2915  ShowerStruct& iss = slc.cots[icotID - 1];
2916  if (iss.ID == 0) return false;
2917  if (iss.TjIDs.empty()) return false;
2918  if (iss.ShowerTjID <= 0) return false;
2919 
2920  if (jcotID <= 0 || jcotID > (int)slc.cots.size()) return false;
2921  ShowerStruct& jss = slc.cots[jcotID - 1];
2922  if (jss.TjIDs.empty()) return false;
2923  if (jss.ID == 0) return false;
2924  if (jss.ShowerTjID <= 0) return false;
2925 
2926  if (iss.CTP != jss.CTP) return false;
2927 
2928  std::string fcnLabel = inFcnLabel + ".MSAS";
2929 
2930  if (iss.SS3ID > 0 && jss.SS3ID > 0 && iss.SS3ID != jss.SS3ID) return false;
2931 
2932  Trajectory& itj = slc.tjs[iss.ShowerTjID - 1];
2933  Trajectory& jtj = slc.tjs[jss.ShowerTjID - 1];
2934  if (!itj.Pts[1].Hits.empty() || !jtj.Pts[1].Hits.empty()) return false;
2935 
2936  iss.TjIDs.insert(iss.TjIDs.end(), jss.TjIDs.begin(), jss.TjIDs.end());
2937  // make a new trajectory using itj as a template
2938  Trajectory ktj = itj;
2939  ktj.ID = slc.tjs.size() + 1;
2940 
2941  slc.tjs.push_back(ktj);
2942  // kill jtj
2943  MakeTrajectoryObsolete(slc, iss.ShowerTjID - 1);
2944  MakeTrajectoryObsolete(slc, jss.ShowerTjID - 1);
2945  slc.tjs[iss.ShowerTjID - 1].ParentID = ktj.ID;
2946  slc.tjs[jss.ShowerTjID - 1].ParentID = ktj.ID;
2947  if (prt)
2948  mf::LogVerbatim("TC") << fcnLabel << " killed stj T" << iss.ShowerTjID << " and T"
2949  << jss.ShowerTjID << " new T" << ktj.ID;
2950  // revise the shower
2951  iss.ShowerTjID = ktj.ID;
2952  // transfer the list of Tj IDs
2953  iss.TjIDs.insert(iss.TjIDs.end(), jss.TjIDs.begin(), jss.TjIDs.begin());
2954  std::sort(iss.TjIDs.begin(), iss.TjIDs.end());
2955  // correct the assn
2956  for (auto tid : iss.TjIDs) {
2957  auto& tj = slc.tjs[tid - 1];
2958  tj.SSID = iss.ID;
2959  } // tid
2960  // transfer a 2S -> 3S assn
2961  if (iss.SS3ID == 0 && jss.SS3ID > 0) iss.SS3ID = jss.SS3ID;
2962  // merge the list of nearby Tjs
2963  iss.NearTjIDs.insert(iss.NearTjIDs.end(), jss.NearTjIDs.begin(), jss.NearTjIDs.end());
2964  // transfer the TruParentID if it is in jss
2965  if (jss.TruParentID > 0) iss.TruParentID = jss.TruParentID;
2966  iss.NeedsUpdate = true;
2967  // force a full update
2968  iss.ShPts.clear();
2969  jss.ID = 0;
2970  bool success = UpdateShower(fcnLabel, slc, iss, prt);
2971  KillVerticesInShower(fcnLabel, slc, iss, prt);
2972 
2973  return success;
2974 
2975  } // MergeShowersAndStore
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void KillVerticesInShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:704
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1106
void MakeTrajectoryObsolete(TCSlice &slc, unsigned int itj)
Definition: Utils.cxx:2138
bool tca::MergeShowerTjsAndStore ( TCSlice slc,
unsigned short  istj,
unsigned short  jstj,
bool  prt 
)

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

2979  {
2980  // Merge showers using showerTj indices
2981  // This function is called from MergeAndStore whose function is to merge two line-like
2982  // trajectories and store them. This function was called because at least one of the
2983  // trajectories is a shower Tj. Assume that the decision to merge them has been made elsewhere.
2984 
2985  if (istj > slc.tjs.size() - 1) return false;
2986  if (jstj > slc.tjs.size() - 1) return false;
2987 
2988  Trajectory& itj = slc.tjs[istj];
2989  Trajectory& jtj = slc.tjs[jstj];
2990 
2991  std::string fcnLabel = "MSTJ";
2992 
2993  if (prt)
2994  mf::LogVerbatim("TC") << fcnLabel << " MergeShowerTjsAndStore Tj IDs " << itj.ID << " "
2995  << jtj.ID;
2996 
2997  // First we check to make sure that both are shower Tjs.
2998  if (!itj.AlgMod[kShowerTj] && !jtj.AlgMod[kShowerTj]) {
2999  if (prt) mf::LogVerbatim("TC") << " One of these isn't a shower Tj";
3000  return false;
3001  }
3002 
3003  // We need to keep the convention used in MergeAndStore to create a new merged trajectory
3004  // and kill the two fragments. This doesn't require making a new shower however. We can just
3005  // re-purpose one of the existing showers
3006  int icotID = GetCotID(slc, itj.ID);
3007  if (icotID == 0) return false;
3008  ShowerStruct& iss = slc.cots[icotID - 1];
3009  if (iss.ID == 0) return false;
3010  if (iss.TjIDs.empty()) return false;
3011  int jcotID = GetCotID(slc, jtj.ID);
3012  if (jcotID == 0) return false;
3013  ShowerStruct& jss = slc.cots[jcotID - 1];
3014  if (jss.ID == 0) return false;
3015  if (jss.TjIDs.empty()) return false;
3016 
3017  return MergeShowersAndStore(fcnLabel, slc, icotID, jcotID, prt);
3018 
3019  } // MergeShowerTjsAndStore
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
int GetCotID(TCSlice &slc, int ShowerTjID)
Definition: TCShower.cxx:3889
bool MergeShowersAndStore(std::string inFcnLabel, TCSlice &slc, int icotID, int jcotID, bool prt)
Definition: TCShower.cxx:2908
void tca::MergeSubShowers ( std::string  inFcnLabel,
TCSlice slc,
const CTP_t inCTP,
bool  prt 
)

Definition at line 2731 of file TCShower.cxx.

References tca::Trajectory::AlgMod, tca::ShowerStruct::AspectRatio, ChkAssns(), tca::TCSlice::cots, tca::TrajPoint::Dir, DontCluster(), tca::ShowerStruct::Energy, FindAlongTrans(), tca::ShowerStruct::ID, tca::detail::SortEntry::index, InShowerProbLong(), InShowerProbTrans(), kMergeSubShowers, MergeShowersAndStore(), PointTrajDOCA(), tca::TrajPoint::Pos, PosSep(), ShowerParams(), tca::TCConfig::showerTag, tca::ShowerStruct::ShowerTjID, tcc, tca::ShowerStruct::TjIDs, tca::TCSlice::tjs, tca::TCConfig::useAlg, tca::detail::SortEntry::val, tca::detail::valsIncreasing(), and tca::TCConfig::wirePitch.

Referenced by FindShowers3D().

2732  {
2733  // Merge small showers that are downstream of larger showers
2734 
2735  if (!tcc.useAlg[kMergeSubShowers]) return;
2736 
2737  std::string fcnLabel = inFcnLabel + ".MSS";
2738  bool newCuts = (tcc.showerTag[0] == 4);
2739  constexpr float radLen = 14 / 0.3;
2740 
2741  if (prt) {
2742  if (newCuts) {
2743  mf::LogVerbatim("TC") << fcnLabel << " MergeSubShowers checking using ShowerParams";
2744  }
2745  else {
2746  mf::LogVerbatim("TC") << fcnLabel
2747  << " MergeSubShowers checking using radiation length cut ";
2748  }
2749  } // prt
2750 
2751  bool keepMerging = true;
2752  while (keepMerging) {
2753  keepMerging = false;
2754  // sort by decreasing energy
2755  std::vector<SortEntry> sortVec;
2756  for (auto& ss : slc.cots) {
2757  if (ss.ID == 0) continue;
2758  if (ss.CTP != inCTP) continue;
2759  SortEntry se;
2760  se.index = ss.ID - 1;
2761  se.val = ss.Energy;
2762  sortVec.push_back(se);
2763  } // ss
2764  if (sortVec.size() < 2) return;
2765  std::sort(sortVec.begin(), sortVec.end(), valsIncreasing);
2766  for (unsigned short ii = 0; ii < sortVec.size() - 1; ++ii) {
2767  ShowerStruct& iss = slc.cots[sortVec[ii].index];
2768  if (iss.ID == 0) continue;
2769  // this shouldn't be done to showers that are ~round
2770  if (iss.AspectRatio > 0.5) continue;
2771  TrajPoint& istp1 = slc.tjs[iss.ShowerTjID - 1].Pts[1];
2772  double shMaxAlong, along95;
2773  ShowerParams((double)iss.Energy, shMaxAlong, along95);
2774  // convert along95 to a separation btw shower max and along95
2775  along95 -= shMaxAlong;
2776  // convert to WSE
2777  along95 /= tcc.wirePitch;
2778  for (unsigned short jj = ii + 1; jj < sortVec.size(); ++jj) {
2779  ShowerStruct& jss = slc.cots[sortVec[jj].index];
2780  if (jss.ID == 0) continue;
2781  if (DontCluster(slc, iss.TjIDs, jss.TjIDs)) continue;
2782  TrajPoint& jstp1 = slc.tjs[jss.ShowerTjID - 1].Pts[1];
2783  if (newCuts) {
2784  // find the longitudinal and transverse separation using the higher energy
2785  // shower which probably is better defined.
2786  Point2_t alongTrans;
2787  FindAlongTrans(istp1.Pos, istp1.Dir, jstp1.Pos, alongTrans);
2788  // the lower energy shower is at the wrong end of the higher energy shower if alongTrans[0] < 0
2789  if (alongTrans[0] < 0) continue;
2790  // increase the cut if the second shower is < 10% of the first shower
2791  float alongCut = along95;
2792  if (jss.Energy < 0.1 * iss.Energy) alongCut *= 1.5;
2793  float probLong = InShowerProbLong(iss.Energy, alongTrans[0]);
2794  float probTran = InShowerProbTrans(iss.Energy, alongTrans[0], alongTrans[1]);
2795  if (prt) {
2796  mf::LogVerbatim myprt("TC");
2797  myprt << fcnLabel << " Candidate i2S" << iss.ID << " E = " << (int)iss.Energy
2798  << " j2S" << jss.ID << " E = " << (int)jss.Energy;
2799  myprt << " along " << std::fixed << std::setprecision(1) << alongTrans[0] << " trans "
2800  << alongTrans[1];
2801  myprt << " alongCut " << alongCut << " probLong " << probLong << " probTran "
2802  << probTran;
2803  } // prt
2804  if (alongTrans[0] > alongCut) continue;
2805  if (alongTrans[1] > alongTrans[0]) continue;
2806  }
2807  else {
2808  // old cuts
2809  float sep = PosSep(istp1.Pos, jstp1.Pos);
2810  float trad = sep / radLen;
2811  // Find the IP between them using the projection of the one with the lowest aspect ratio
2812  float delta = 9999;
2813  if (iss.AspectRatio < jss.AspectRatio) {
2814  delta = PointTrajDOCA(jstp1.Pos[0], jstp1.Pos[1], istp1);
2815  }
2816  else {
2817  delta = PointTrajDOCA(istp1.Pos[0], istp1.Pos[1], jstp1);
2818  }
2819  // See if delta is consistent with the cone angle of the i shower
2820  float dang = delta / sep;
2821  if (prt)
2822  mf::LogVerbatim("TC") << fcnLabel << " Candidate i2S" << iss.ID << " j2S" << jss.ID
2823  << " separation " << (int)sep << " radiation lengths " << trad
2824  << " delta " << delta << " dang " << dang;
2825  if (trad > 3) continue;
2826  // There must be a correlation between dang and the energy of these showers...
2827  if (dang > 0.3) continue;
2828  } // old cuts
2829 
2830  if (prt) mf::LogVerbatim("TC") << fcnLabel << " Merge them. Re-find shower center, etc";
2831  if (MergeShowersAndStore(fcnLabel, slc, iss.ID, jss.ID, prt)) {
2832  Trajectory& stj = slc.tjs[iss.ShowerTjID - 1];
2833  stj.AlgMod[kMergeSubShowers] = true;
2834  keepMerging = true;
2835  break;
2836  }
2837  } // jj
2838  if (keepMerging) break;
2839  } // ii
2840  } // keepMerging
2841 
2842  ChkAssns(fcnLabel, slc);
2843 
2844  } // MergeSubShowers
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
double InShowerProbLong(double showerEnergy, double along)
Definition: TCShower.cxx:1937
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4095
TCConfig tcc
Definition: DataStructs.cxx:9
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:3066
bool DontCluster(TCSlice const &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3213
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2514
double InShowerProbTrans(double showerEnergy, double along, double trans)
Definition: TCShower.cxx:1972
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:549
std::array< float, 2 > Point2_t
Definition: DataStructs.h:41
bool valsIncreasing(const SortEntry &c1, const SortEntry &c2)
Definition: Utils.cxx:43
bool MergeShowersAndStore(std::string inFcnLabel, TCSlice &slc, int icotID, int jcotID, bool prt)
Definition: TCShower.cxx:2908
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
Definition: TCShower.cxx:1904
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
void tca::MergeSubShowersTj ( std::string  inFcnLabel,
TCSlice slc,
const CTP_t inCTP,
bool  prt 
)

Definition at line 2620 of file TCShower.cxx.

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

Referenced by FindShowers3D().

2621  {
2622  // merge small showers that are downstream of shower-like tjs. This algorithm is written
2623  // for low-energy showers with are likely to be sparse and poorly defined.
2624 
2625  if (!tcc.useAlg[kMergeSubShowersTj]) return;
2626 
2627  std::string fcnLabel = inFcnLabel + ".MSSTj";
2628 
2629  struct TjSS {
2630  int ssID;
2631  int tjID;
2632  float dang;
2633  };
2634  std::vector<TjSS> tjss;
2635 
2636  // temp vector for DontCluster
2637  std::vector<int> tjid(1);
2638  for (auto& ss : slc.cots) {
2639  if (ss.ID == 0) continue;
2640  if (ss.CTP != inCTP) continue;
2641  // TODO: Evaluate this cut
2642  if (ss.Energy > 300) continue;
2643  auto& stj = slc.tjs[ss.ShowerTjID - 1];
2644  auto stp0 = stj.Pts[0];
2645  float bestDang = 0.3;
2646  int bestTj = 0;
2647  // look for a Tj that has higher energy than the shower
2648  for (auto& tj : slc.tjs) {
2649  if (tj.AlgMod[kKilled]) continue;
2650  if (tj.AlgMod[kHaloTj]) continue;
2651  if (tj.CTP != ss.CTP) continue;
2652  // require that it isn't in any shower
2653  if (tj.SSID > 0) continue;
2654  // require it to be not short
2655  if (NumPtsWithCharge(slc, tj, false) < 10) continue;
2656  // and satisfy the ShowerLike MCSMom cut. It is unlikely to be tagged shower-like
2657  if (tj.MCSMom > tcc.showerTag[1]) continue;
2658  // check consistency
2659  tjid[0] = tj.ID;
2660  if (DontCluster(slc, tjid, ss.TjIDs)) continue;
2661  float tjEnergy = ChgToMeV(tj.TotChg);
2662  // find the end that is furthest away from the shower center
2663  unsigned short farEnd = FarEnd(tj, stj.Pts[1].Pos);
2664  // compare MCSMom at the far end and the near end
2665  unsigned short midpt = 0.5 * (tj.EndPt[0] + tj.EndPt[1]);
2666  float mom1 = MCSMom(slc, tj, tj.EndPt[farEnd], midpt);
2667  float mom2 = MCSMom(slc, tj, tj.EndPt[1 - farEnd], midpt);
2668  float asym = (mom1 - mom2) / (mom1 + mom2);
2669  auto& farTP = tj.Pts[tj.EndPt[farEnd]];
2670  // IP btw the far end TP and the shower center
2671  float doca = PointTrajDOCA(stp0.Pos[0], stp0.Pos[1], farTP);
2672  float sep = PosSep(farTP.Pos, stp0.Pos);
2673  float dang = doca / sep;
2674  if (prt) {
2675  mf::LogVerbatim myprt("TC");
2676  myprt << fcnLabel << " Candidate 2S" << ss.ID << " T" << tj.ID << "_" << farEnd;
2677  myprt << " ShEnergy " << (int)ss.Energy << " tjEnergy " << (int)tjEnergy;
2678  myprt << " doca " << doca << " sep " << sep << " dang " << dang << " asym " << asym;
2679  }
2680  if (tjEnergy < ss.Energy) continue;
2681  if (asym < 0.5) continue;
2682  // TODO: This should be done more carefully
2683  // separation cut 100 WSE ~ 30 cm in uB
2684  if (sep > 100) continue;
2685  if (dang > bestDang) continue;
2686  bestDang = dang;
2687  bestTj = tj.ID;
2688  } // tj
2689  if (bestTj == 0) continue;
2690  TjSS match;
2691  match.ssID = ss.ID;
2692  match.tjID = bestTj;
2693  match.dang = bestDang;
2694  tjss.push_back(match);
2695  } // ss
2696 
2697  if (tjss.empty()) return;
2698 
2699  // ensure that a tj is only put in one shower
2700  bool keepGoing = true;
2701  while (keepGoing) {
2702  keepGoing = false;
2703  float bestDang = 0.3;
2704  int bestMatch = 0;
2705  for (unsigned short mat = 0; mat < tjss.size(); ++mat) {
2706  auto& match = tjss[mat];
2707  // already used
2708  if (match.dang < 0) continue;
2709  if (match.dang < bestDang) bestMatch = mat;
2710  } // mat
2711  if (bestMatch > 0) {
2712  auto& match = tjss[bestMatch];
2713  auto& ss = slc.cots[match.ssID - 1];
2714  if (!AddTj(fcnLabel, slc, match.tjID, ss, true, prt)) {
2715  if (prt) mf::LogVerbatim("TC") << " Failed";
2716  continue;
2717  }
2718  match.dang = -1;
2719  // set the AlgMod bit
2720  auto& stj = slc.tjs[ss.ShowerTjID - 1];
2721  stj.AlgMod[kMergeSubShowersTj] = true;
2722  keepGoing = true;
2723  } // found bestMatch
2724  } // keepGoing
2725 
2726  ChkAssns(fcnLabel, slc);
2727 
2728  } // MergeSubShowersTj
bool AddTj(std::string inFcnLabel, TCSlice &slc, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1429
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3381
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4095
TCConfig tcc
Definition: DataStructs.cxx:9
bool DontCluster(TCSlice const &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3213
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2514
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:549
Float_t mat
Definition: plot.C:38
unsigned short FarEnd(const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3300
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
float ChgToMeV(float chg)
Definition: TCShower.cxx:3925
bool tca::MergeTjIntoPFP ( TCSlice slc,
int  mtjid,
PFPStruct pfp,
bool  prt 
)

Definition at line 512 of file Utils.cxx.

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

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

Definition at line 1287 of file TCShower.cxx.

References util::empty().

1288  {
1289  // Merge the lists of Tjs in the lists if they share a common Tj ID
1290 
1291  if (tjList.size() < 2) return;
1292 
1293  bool didMerge = true;
1294  while (didMerge) {
1295  didMerge = false;
1296  for (unsigned short itl = 0; itl < tjList.size() - 1; ++itl) {
1297  if (tjList[itl].empty()) continue;
1298  for (unsigned short jtl = itl + 1; jtl < tjList.size(); ++jtl) {
1299  if (tjList[itl].empty()) continue;
1300  auto& itList = tjList[itl];
1301  auto& jtList = tjList[jtl];
1302  // See if the j Tj is in the i tjList
1303  bool jtjInItjList = false;
1304  for (auto& jtj : jtList) {
1305  if (std::find(itList.begin(), itList.end(), jtj) != itList.end()) {
1306  jtjInItjList = true;
1307  break;
1308  }
1309  if (jtjInItjList) break;
1310  } // jtj
1311  if (jtjInItjList) {
1312  // append the jtList to itList
1313  itList.insert(itList.end(), jtList.begin(), jtList.end());
1314  // clear jtList
1315  jtList.clear();
1316  didMerge = true;
1317  }
1318  } // jtl
1319  } // itl
1320  } // didMerge
1321 
1322  // erase the deleted elements
1323  unsigned short imEmpty = 0;
1324  while (imEmpty < tjList.size()) {
1325  for (imEmpty = 0; imEmpty < tjList.size(); ++imEmpty)
1326  if (tjList[imEmpty].empty()) break;
1327  if (imEmpty < tjList.size()) tjList.erase(tjList.begin() + imEmpty);
1328  } // imEmpty < tjList.size()
1329 
1330  // sort the lists by increasing ID and remove duplicates
1331  for (auto& tjl : tjList) {
1332  std::sort(tjl.begin(), tjl.end());
1333  auto last = std::unique(tjl.begin(), tjl.end());
1334  tjl.erase(last, tjl.end());
1335  } // tjl
1336 
1337  } // MergeTjList
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:109
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 433 of file TCVertex.cxx.

References tca::VtxStore::ChiDOF, CloseEnd(), tca::VtxStore::CTP, tca::TCConfig::dbgSlc, tca::TCConfig::dbgVxMerge, util::end(), FitVertex(), GetVtxTjIDs(), tca::VtxStore::ID, kFixed, kHaloTj, kKilled, kVxMerge, kVxMerged, NearestPtWithChg(), NumPtsWithCharge(), tca::VtxStore::Pos, tca::VtxStore::PosErr, PrintPos(), SetVx2Score(), tca::VtxStore::Stat, tcc, tca::TCSlice::tjs, tmp, tca::TCConfig::useAlg, tca::detail::valsDecreasing(), and tca::TCSlice::vtxs.

Referenced by Find2DVertices().

434  {
435  // Attempts to merge the trajectories attached to vx with an existing 2D vertex
436  // referenced by existingVxID. This function doesn't use the existing end0/end1 vertex association.
437  // It returns true if the merging was successful in which case the calling function should
438  // not store vx. The calling function needs to have set VtxID to vx.ID for tjs that are currently attached
439  // to vx. It assumed that vx hasn't yet been pushed onto slc.vtxs
440 
441  if (!tcc.useAlg[kVxMerge]) return false;
442 
443  bool prt = tcc.dbgVxMerge && tcc.dbgSlc;
444 
445  if (oVxID > slc.vtxs.size()) return false;
446  auto& oVx = slc.vtxs[oVxID - 1];
447  if (vx.CTP != oVx.CTP) return false;
448 
449  // get a list of tjs attached to both vertices
450  std::vector<int> tjlist = GetVtxTjIDs(slc, vx);
451  if (tjlist.empty()) return false;
452  std::vector<int> tmp = GetVtxTjIDs(slc, oVx);
453  if (tmp.empty()) return false;
454  for (auto tjid : tmp) {
455  if (std::find(tjlist.begin(), tjlist.end(), tjid) == tjlist.end()) tjlist.push_back(tjid);
456  } // tjid
457  if (tjlist.size() < 2) return false;
458  // handle the simple case
459  if (tjlist.size() == 2) {
460  // Unset the fixed bit
461  vx.Stat[kFixed] = false;
462  oVx.Stat[kFixed] = false;
463  // assign the vx tjs to oVx
464  for (auto tjid : tjlist) {
465  auto& tj = slc.tjs[tjid - 1];
466  for (unsigned short end = 0; end < 2; ++end) {
467  if (tj.VtxID[end] == vx.ID) tj.VtxID[end] = oVx.ID;
468  } // end
469  } // tjid
470  if (!FitVertex(slc, oVx, prt)) {
471  if (prt)
472  mf::LogVerbatim("TC") << "MWV: merge failed " << vx.ID << " and existing " << oVx.ID;
473  return false;
474  }
475  return true;
476  } // size = 2
477 
478  // sort by decreasing length
479  std::vector<SortEntry> sortVec(tjlist.size());
480  for (unsigned int indx = 0; indx < sortVec.size(); ++indx) {
481  sortVec[indx].index = indx;
482  auto& tj = slc.tjs[tjlist[indx] - 1];
483  sortVec[indx].val = tj.Pts.size();
484  } // indx
485  std::sort(sortVec.begin(), sortVec.end(), valsDecreasing);
486  // re-order the list of Tjs
487  auto ttl = tjlist;
488  for (unsigned short ii = 0; ii < sortVec.size(); ++ii)
489  tjlist[ii] = ttl[sortVec[ii].index];
490  // Create a local vertex using the two longest slc, then add the shorter ones
491  // until the pull reaches the cut
492  VtxStore aVx;
493  aVx.CTP = vx.CTP;
494  std::vector<TrajPoint> tjpts(tjlist.size());
495  // determine which point on each Tj that will be used in the vertex fit and stash it in
496  // the traj point Step variable. This requires knowing the real position of the merged vertex
497  // which we estimate by averaging
498  std::array<float, 2> vpos;
499  vpos[0] = 0.5 * (vx.Pos[0] + oVx.Pos[0]);
500  vpos[1] = 0.5 * (vx.Pos[1] + oVx.Pos[1]);
501  for (unsigned short ii = 0; ii < tjpts.size(); ++ii) {
502  auto& tj = slc.tjs[tjlist[ii] - 1];
503  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
504  unsigned short end = CloseEnd(tj, vpos);
505  // assume that we will use the end point of the tj
506  unsigned short endPt = tj.EndPt[end];
507  if (npwc > 6 && tj.Pts[endPt].NTPsFit < 4) {
508  if (end == 0) { endPt += 3; }
509  else {
510  endPt -= 3;
511  }
512  endPt = NearestPtWithChg(tj, endPt);
513  } // few points fit at the end
514  if (endPt < tj.EndPt[0]) endPt = tj.EndPt[0];
515  if (endPt > tj.EndPt[1]) endPt = tj.EndPt[1];
516  // define tjpts
517  tjpts[ii].CTP = tj.CTP;
518  tjpts[ii].Pos = tj.Pts[endPt].Pos;
519  tjpts[ii].Dir = tj.Pts[endPt].Dir;
520  tjpts[ii].Ang = tj.Pts[endPt].Ang;
521  tjpts[ii].AngErr = tj.Pts[endPt].AngErr;
522  // stash the point in Step
523  tjpts[ii].Step = endPt;
524  // and the end in AngleCode
525  tjpts[ii].AngleCode = end;
526  // stash the ID in Hits
527  tjpts[ii].Hits.resize(1, tj.ID);
528  } // tjid
529  if (prt) {
530  mf::LogVerbatim myprt("TC");
531  myprt << "MWV: " << oVxID;
532  myprt << " Fit TPs";
533  for (unsigned short ii = 0; ii < tjpts.size(); ++ii) {
534  auto& tjpt = tjpts[ii];
535  myprt << " " << tjlist[ii] << "_" << tjpt.Step << "_" << PrintPos(tjpt.Pos);
536  }
537  } // prt
538  // create a subset of the first two for the first fit
539  auto fitpts = tjpts;
540  fitpts.resize(2);
541  if (!FitVertex(slc, aVx, fitpts, prt)) {
542  if (prt) mf::LogVerbatim("TC") << "MWV: first fit failed ";
543  return false;
544  }
545  // Fit and add tjs to the vertex
546  bool needsUpdate = false;
547  for (unsigned short ii = 2; ii < tjlist.size(); ++ii) {
548  fitpts.push_back(tjpts[ii]);
549  if (FitVertex(slc, aVx, fitpts, prt)) { needsUpdate = false; }
550  else {
551  // remove the last Tj point and keep going
552  fitpts.pop_back();
553  needsUpdate = true;
554  }
555  } // ii
556 
557  if (needsUpdate) FitVertex(slc, aVx, fitpts, prt);
558  if (prt) mf::LogVerbatim("TC") << "MWV: done " << vx.ID << " and existing " << oVx.ID;
559 
560  // update. Remove old associations
561  for (auto& tj : slc.tjs) {
562  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
563  if (tj.CTP != vx.CTP) continue;
564  for (unsigned short end = 0; end < 2; ++end) {
565  if (tj.VtxID[end] == vx.ID) tj.VtxID[end] = 0;
566  if (tj.VtxID[end] == oVxID) tj.VtxID[end] = 0;
567  }
568  } // tj
569  // set the new associations
570  for (unsigned short ii = 0; ii < fitpts.size(); ++ii) {
571  auto& tjpt = fitpts[ii];
572  unsigned short end = tjpt.AngleCode;
573  auto& tj = slc.tjs[tjpt.Hits[0] - 1];
574  if (tj.VtxID[end] != 0) return false;
575  tj.VtxID[end] = oVxID;
576  } // ii
577 
578  // Update oVx
579  oVx.Pos = aVx.Pos;
580  oVx.PosErr = aVx.PosErr;
581  oVx.ChiDOF = aVx.ChiDOF;
582  oVx.NTraj = fitpts.size();
583  // Update the score and the charge fraction
584  SetVx2Score(slc, oVx);
585  oVx.Stat[kVxMerged] = true;
586  oVx.Stat[kFixed] = false;
587  if (prt) {
588  mf::LogVerbatim myprt("TC");
589  myprt << "MWV: " << oVxID;
590  myprt << " Done TPs";
591  for (unsigned short ii = 0; ii < fitpts.size(); ++ii) {
592  auto& tjpt = fitpts[ii];
593  myprt << " " << tjpt.Hits[0] << "_" << tjpt.AngleCode << "_" << PrintPos(tjpt.Pos);
594  }
595  } // prt
596 
597  return true;
598  } // MergeWithVertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
vertex position fixed manually - no fitting done
Definition: DataStructs.h:88
Float_t tmp
Definition: plot.C:35
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
bool FitVertex(TCSlice &slc, VtxStore &vx, std::vector< TrajPoint > &vxTPs, bool prt)
Definition: TCVertex.cxx:1992
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
unsigned short NearestPtWithChg(const Trajectory &tj, unsigned short thePt)
Definition: Utils.cxx:3435
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2255
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:2823
bool valsDecreasing(const SortEntry &c1, const SortEntry &c2)
Definition: Utils.cxx:39
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
unsigned short CloseEnd(const Trajectory &tj, const Point2_t &pos)
Definition: Utils.cxx:2495
void tca::MoveTPToWire ( TrajPoint tp,
float  wire 
)

Definition at line 2763 of file Utils.cxx.

References util::abs(), tca::TrajPoint::Dir, and tca::TrajPoint::Pos.

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

2764  {
2765  // Project TP to a "wire position" Pos[0] and update Pos[1]
2766  if (tp.Dir[0] == 0) return;
2767  float dw = wire - tp.Pos[0];
2768  if (std::abs(dw) < 0.01) return;
2769  tp.Pos[0] = wire;
2770  tp.Pos[1] += dw * tp.Dir[1] / tp.Dir[0];
2771  } // MoveTPToWire
constexpr auto abs(T v)
Returns the absolute value of the argument.
unsigned short tca::NearbyCleanPt ( const Trajectory tj,
unsigned short  end 
)

Definition at line 2888 of file Utils.cxx.

References dir, util::end(), tca::Trajectory::EndPt, kEnvOverlap, and tca::Trajectory::Pts.

Referenced by Reconcile2VTs().

2889  {
2890  // Searches for a TP near the end (or beginnin) that doesn't have the kEnvOverlap bit set
2891  // with the intent that a fit of a vertex position using this tj will be minimally
2892  // biased if there are no nearby hits from other tjs. A search is done from the
2893  // supplied nearPt moving in the + direction if nearPt == tj.EndPt[0] and moving in
2894  // the - direction if nearPt == tj.EndPt[1]
2895  if (end > 1) return USHRT_MAX;
2896  short dir = 1;
2897  if (end == 1) dir = -1;
2898  for (short ii = 0; ii < (short)tj.Pts.size(); ++ii) {
2899  short ipt = tj.EndPt[end] + dir * ii;
2900  if (ipt < 0 || ipt >= (short)tj.Pts.size()) return USHRT_MAX;
2901  auto& tp = tj.Pts[ipt];
2902  if (!tp.Environment[kEnvOverlap]) return ipt;
2903  } // ii
2904  return tj.EndPt[end];
2905  } // FindCleanPt
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
TDirectory * dir
Definition: macro.C:5
bool tca::NearbySrcHit ( geo::PlaneID  plnID,
unsigned int  wire,
float  loTick,
float  hiTick 
)

Definition at line 2030 of file Utils.cxx.

References evt, geo::PlaneID::Plane, geo::WireReadoutGeom::PlaneWireToChannel(), tca::TCEvent::srcHits, tcc, geo::TPCID::TPC, tca::TCEvent::tpcSrcHitRange, and tca::TCConfig::wireReadoutGeom.

Referenced by AddHits(), and SignalAtTp().

2031  {
2032  // Look for a hit on wid in the srcHits collection that has a tick in the range. This
2033  // is a DUNE-specific function in which hit disambiguation is done in the U and V planes
2034  if (evt.srcHits == NULL) return false;
2035  unsigned int pln = plnID.Plane;
2036  if (pln == 2) return false;
2037 
2038  unsigned int tpc = plnID.TPC;
2039  // get a valid range of hits to search
2040  if (evt.tpcSrcHitRange[tpc].first >= (*evt.srcHits).size()) return false;
2041  if (evt.tpcSrcHitRange[tpc].second >= (*evt.srcHits).size()) return false;
2043  float atTick = 0.5 * (loTick + hiTick);
2044  for (unsigned int iht = evt.tpcSrcHitRange[tpc].first; iht <= evt.tpcSrcHitRange[tpc].second;
2045  ++iht) {
2046  auto& hit = (*evt.srcHits)[iht];
2047  if (hit.Channel() != chan) continue;
2048  if (atTick < hit.PeakTime()) {
2049  float loHitTick = hit.PeakTime() - 3 * hit.RMS();
2050  if (hiTick > loHitTick) return true;
2051  }
2052  else {
2053  float hiHitTick = hit.PeakTime() + 3 * hit.RMS();
2054  if (loTick < hiHitTick) return true;
2055  }
2056  } // iht
2057  return false;
2058  } // NearbySrcHit
const geo::WireReadoutGeom * wireReadoutGeom
Definition: DataStructs.h:568
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< std::pair< unsigned int, unsigned int > > tpcSrcHitRange
Definition: DataStructs.h:620
virtual raw::ChannelID_t PlaneWireToChannel(WireID const &wireID) const =0
Returns the channel ID a wire is connected to.
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * srcHits
Definition: DataStructs.h:615
TCEvent evt
Definition: DataStructs.cxx:8
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:315
unsigned short tca::NearestPtWithChg ( const Trajectory tj,
unsigned short  thePt 
)

Definition at line 3435 of file Utils.cxx.

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

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

3436  {
3437  // returns a point near thePt which has charge
3438  if (thePt > tj.EndPt[1]) return thePt;
3439  if (tj.Pts[thePt].Chg > 0) return thePt;
3440 
3441  short endPt0 = tj.EndPt[0];
3442  short endPt1 = tj.EndPt[1];
3443  for (short off = 1; off < 10; ++off) {
3444  short ipt = thePt + off;
3445  if (ipt <= endPt1 && tj.Pts[ipt].Chg > 0) return (unsigned short)ipt;
3446  ipt = thePt - off;
3447  if (ipt >= endPt0 && tj.Pts[ipt].Chg > 0) return (unsigned short)ipt;
3448  } // off
3449  return thePt;
3450  } // NearestPtWithChg
int tca::NeutrinoPrimaryTjID ( const TCSlice slc,
const Trajectory tj 
)

Definition at line 446 of file Utils.cxx.

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

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

447  {
448  // Returns the ID of the grandparent of this tj that is a primary tj that is attached
449  // to the neutrino vertex. 0 is returned if this condition is not met.
450  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) return -1;
451  if (tj.ParentID <= 0) return -1;
452  int primID = PrimaryID(slc, tj);
453  if (primID <= 0 || primID > (int)slc.tjs.size()) return -1;
454 
455  // We have the ID of the primary tj. Now see if it is attached to the neutrino vertex
456  auto& ptj = slc.tjs[primID - 1];
457  for (unsigned short end = 0; end < 2; ++end) {
458  if (ptj.VtxID[end] == 0) continue;
459  auto& vx2 = slc.vtxs[ptj.VtxID[end] - 1];
460  if (vx2.Vx3ID == 0) continue;
461  auto& vx3 = slc.vtx3s[vx2.Vx3ID - 1];
462  if (vx3.Neutrino) return primID;
463  } // end
464  return -1;
465  } // NeutrinoPrimaryTjUID
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
int PrimaryID(const TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:468
unsigned short tca::NumHitsInTP ( const TrajPoint tp,
HitStatus_t  hitRequest 
)

Definition at line 4198 of file Utils.cxx.

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

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

4199  {
4200  // Counts the number of hits of the specified type in tp
4201  if (tp.Hits.empty()) return 0;
4202 
4203  if (hitRequest == kAllHits) return tp.Hits.size();
4204 
4205  unsigned short nhits = 0;
4206  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
4207  if (hitRequest == kUsedHits) {
4208  if (tp.UseHit[ii]) ++nhits;
4209  }
4210  else {
4211  // looking for unused hits
4212  if (!tp.UseHit[ii]) ++nhits;
4213  }
4214  } // ii
4215  return nhits;
4216  } // NumHitsInTP
unsigned short tca::NumPtsWithCharge ( const TCSlice slc,
const Trajectory tj,
bool  includeDeadWires 
)

Definition at line 2072 of file Utils.cxx.

References tca::Trajectory::EndPt.

Referenced by BraggSplit(), CheckHiMultUnusedHits(), CheckStiffEl(), CheckTraj(), ChkBegin(), CompleteIncomplete3DVertices(), ElectronLikelihood(), EndMerge(), FillGaps(), FindHammerVertices2(), FindPFParticles(), FitTraj(), FixBegin(), Forecast(), GottaKink(), KinkSignificance(), MakeSmallAnglePFP(), Match2Planes(), Match3Planes(), Match3PlanesSpt(), MCSMom(), MergeSubShowersTj(), MergeWithVertex(), ReconcileTPs(), tca::TrajClusterAlg::ReconstructAllTraj(), SetPDGCode(), SetStrategy(), SplitTrajCrossingVertices(), StepAway(), StopShort(), TagShowerLike(), TrimEndPts(), TrimHiChgEndPts(), and UpdateTraj().

2073  {
2074  unsigned short firstPt = tj.EndPt[0];
2075  unsigned short lastPt = tj.EndPt[1];
2076  return NumPtsWithCharge(slc, tj, includeDeadWires, firstPt, lastPt);
2077  }
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:2080
unsigned short tca::NumPtsWithCharge ( const TCSlice slc,
const Trajectory tj,
bool  includeDeadWires,
unsigned short  firstPt,
unsigned short  lastPt 
)

Definition at line 2080 of file Utils.cxx.

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

2085  {
2086  unsigned short ntp = 0;
2087  for (unsigned short ipt = firstPt; ipt <= lastPt; ++ipt)
2088  if (tj.Pts[ipt].Chg > 0) ++ntp;
2089  // Add the count of deadwires
2090  if (includeDeadWires) ntp += DeadWireCount(slc, tj.Pts[firstPt], tj.Pts[lastPt]);
2091  return ntp;
2092  } // NumPtsWithCharge
float DeadWireCount(const TCSlice &slc, const float &inWirePos1, const float &inWirePos2, CTP_t tCTP)
Definition: Utils.cxx:2101
float tca::OverlapFraction ( const Trajectory tj1,
const Trajectory tj2 
)

Definition at line 707 of file Utils.cxx.

References tca::Trajectory::Pts, and util::span().

Referenced by CompatibleMerge(), and EndMerge().

708  {
709  // returns the fraction of wires spanned by two trajectories
710  float minWire = 1E6;
711  float maxWire = -1E6;
712 
713  float cnt1 = 0;
714  for (auto& tp : tj1.Pts) {
715  if (tp.Chg == 0) continue;
716  if (tp.Pos[0] < 0) continue;
717  if (tp.Pos[0] < minWire) minWire = tp.Pos[0];
718  if (tp.Pos[0] > maxWire) maxWire = tp.Pos[0];
719  ++cnt1;
720  }
721  if (cnt1 == 0) return 0;
722  float cnt2 = 0;
723  for (auto& tp : tj2.Pts) {
724  if (tp.Chg == 0) continue;
725  if (tp.Pos[0] < 0) continue;
726  if (tp.Pos[0] < minWire) minWire = tp.Pos[0];
727  if (tp.Pos[0] > maxWire) maxWire = tp.Pos[0];
728  ++cnt2;
729  }
730  if (cnt2 == 0) return 0;
731  int span = maxWire - minWire;
732  if (span <= 0) return 0;
733  std::vector<unsigned short> wcnt(span);
734  for (auto& tp : tj1.Pts) {
735  if (tp.Chg == 0) continue;
736  if (tp.Pos[0] < -0.4) continue;
737  int indx = std::nearbyint(tp.Pos[0] - minWire);
738  if (indx < 0 || indx > span - 1) continue;
739  ++wcnt[indx];
740  }
741  for (auto& tp : tj2.Pts) {
742  if (tp.Chg == 0) continue;
743  if (tp.Pos[0] < -0.4) continue;
744  int indx = std::nearbyint(tp.Pos[0] - minWire);
745  if (indx < 0 || indx > span - 1) continue;
746  ++wcnt[indx];
747  }
748  float cntOverlap = 0;
749  for (auto cnt : wcnt)
750  if (cnt > 1) ++cntOverlap;
751  if (cnt1 < cnt2) { return cntOverlap / cnt1; }
752  else {
753  return cntOverlap / cnt2;
754  }
755 
756  } // OverlapFraction
span(IterB &&b, IterE &&e, Adaptor &&adaptor) -> span< std::invoke_result_t< Adaptor, IterB >, std::invoke_result_t< Adaptor, IterE >>
float tca::ParentFOM ( std::string  inFcnLabel,
TCSlice slc,
PFPStruct pfp,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 2051 of file TCShower.cxx.

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

Referenced by SetParent().

2056  {
2057  // Returns an average weighted parent FOM for all trajectories in the pfp being a parent of the 2D showers in ss3
2058  if (ss3.ID == 0) return 1000;
2059  float sum = 0;
2060  float wsum = 0;
2061  std::string fcnLabel = inFcnLabel + ".P3FOM";
2062  float dum1, dum2;
2063  for (auto cid : ss3.CotIDs) {
2064  auto& ss = slc.cots[cid - 1];
2065  if (ss.ID == 0) continue;
2066  // look for the 3D matched tj in this CTP
2067  int tjid = 0;
2068  for (auto tid : pfp.TjIDs) {
2069  auto& tj = slc.tjs[tid - 1];
2070  if (tj.ID == 0) continue;
2071  if (tj.CTP == ss.CTP) tjid = tid;
2072  } // tid
2073  if (tjid == 0) continue;
2074  auto& ptj = slc.tjs[tjid - 1];
2075  auto& stj = slc.tjs[ss.ShowerTjID - 1];
2076  // determine which end is farthest away from the shower center
2077  unsigned short ptjEnd = FarEnd(ptj, stj.Pts[1].Pos);
2078  auto& farTP = ptj.Pts[ptj.EndPt[ptjEnd]];
2079  float chgCtrSep2 = PosSep2(farTP.Pos, stj.Pts[1].Pos);
2080  if (chgCtrSep2 < PosSep2(farTP.Pos, stj.Pts[0].Pos) &&
2081  chgCtrSep2 < PosSep2(farTP.Pos, stj.Pts[2].Pos))
2082  continue;
2083  float fom = ParentFOM(fcnLabel, slc, ptj, ptjEnd, ss, dum1, dum2, prt);
2084  // ignore failures
2085  if (fom > 50) continue;
2086  // weight by the 1/aspect ratio
2087  float wt = 1;
2088  if (ss.AspectRatio > 0) wt = 1 / ss.AspectRatio;
2089  sum += wt * fom;
2090  wsum += wt;
2091  } // cid
2092  if (wsum == 0) return 100;
2093  float fom = sum / wsum;
2094  if (prt)
2095  mf::LogVerbatim("TC") << fcnLabel << " 3S" << ss3.ID << " P" << pfp.ID << " fom "
2096  << std::fixed << std::setprecision(3) << fom;
2097  return fom;
2098  } // ParentFOM
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float ParentFOM(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, unsigned short &tjEnd, ShowerStruct &ss, float &tp1Sep, float &vx2Score, bool prt)
Definition: TCShower.cxx:2101
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2560
unsigned short FarEnd(const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3300
Double_t sum
Definition: plot.C:31
float tca::ParentFOM ( std::string  inFcnLabel,
TCSlice slc,
Trajectory tj,
unsigned short &  tjEnd,
ShowerStruct ss,
float &  tp1Sep,
float &  vx2Score,
bool  prt 
)

Definition at line 2101 of file TCShower.cxx.

References util::abs(), 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.

2109  {
2110  // returns a FOM for the trajectory at the end point being the parent of ss and the end which
2111  // was matched.
2112 
2113  vx2Score = 0;
2114  tp1Sep = 0;
2115 
2116  if (tjEnd > 1) return 1000;
2117  if (ss.Energy == 0) return 1000;
2118 
2119  if (ss.ID == 0) return 1000;
2120  if (ss.TjIDs.empty()) return 1000;
2121  if (ss.ShowerTjID == 0) return 1000;
2122 
2123  std::string fcnLabel = inFcnLabel + ".PFOM";
2124 
2125  if (ss.AspectRatio > 0.5) {
2126  if (prt)
2127  mf::LogVerbatim("TC") << fcnLabel << " 2S" << ss.ID << " poor AspectRatio "
2128  << ss.AspectRatio << " FOM not calculated";
2129  return 100;
2130  }
2131 
2132  float fom = 0;
2133  float cnt = 0;
2134  auto& stj = slc.tjs[ss.ShowerTjID - 1];
2135  TrajPoint& stp0 = stj.Pts[0];
2136  // Shower charge center TP
2137  TrajPoint& stp1 = stj.Pts[1];
2138  // get the end that is farthest away from the shower center
2139  tjEnd = FarEnd(tj, stp1.Pos);
2140  // prospective parent TP
2141  TrajPoint& ptp = tj.Pts[tj.EndPt[tjEnd]];
2142  // find the along and trans components in WSE units relative to the
2143  // shower center
2144  Point2_t alongTrans;
2145  FindAlongTrans(stp1.Pos, stp1.Dir, ptp.Pos, alongTrans);
2146  // We can return here if the shower direction is well defined and
2147  // alongTrans[0] is > 0
2148  if (ss.AspectRatio < 0.2 && ss.DirectionFOM < 0.5 && alongTrans[0] > 0) return 100;
2149  tp1Sep = std::abs(alongTrans[0]);
2150  // Find the expected shower start relative to shower max (cm)
2151  double shMaxAlong, shE95Along;
2152  ShowerParams(ss.Energy, shMaxAlong, shE95Along);
2153  double alongcm = tcc.wirePitch * tp1Sep;
2154  // InShowerProbLong expects the longitudinal distance relative to shower max so it
2155  // should be < 0
2156  float prob = InShowerProbLong(ss.Energy, -alongcm);
2157  if (prob < 0.05) return 100;
2158  // The transverse position must certainly be less than the longitudinal distance
2159  // to shower max.
2160  if (alongTrans[1] > shMaxAlong) return 100;
2161  // longitudinal contribution to fom with 1 Xo error error (14 cm)
2162  float longFOM = std::abs(alongcm + shMaxAlong) / 14;
2163  fom += longFOM;
2164  ++cnt;
2165  // transverse contribution
2166  float transFOM = -1;
2167  if (stp0.DeltaRMS > 0) {
2168  transFOM = alongTrans[1] / stp0.DeltaRMS;
2169  fom += transFOM;
2170  ++cnt;
2171  }
2172  // make a tp between the supposed parent TP and the shower center
2173  TrajPoint tp;
2174  if (!MakeBareTrajPoint(ptp, stp1, tp)) return 100;
2175  // we have three angles to compare. The ptp angle, the shower angle and
2176  // the tp angle.
2177  float dang1 = DeltaAngle(ptp.Ang, stp1.Ang);
2178  float dang1FOM = dang1 / 0.1;
2179  fom += dang1FOM;
2180  ++cnt;
2181  float dang2 = DeltaAngle(ptp.Ang, tp.Ang);
2182  float dang2FOM = dang1 / 0.1;
2183  fom += dang2FOM;
2184  ++cnt;
2185  // the environment near the parent start should be clean.
2186  std::vector<int> tjlist(1);
2187  tjlist[0] = tj.ID;
2188  // check for a vertex at this end and include the vertex tjs if the vertex is close
2189  // to the expected shower max position
2190  float vx2Sep = 0;
2191  // put in a largish FOM value for Tjs that don't have a vertex
2192  float vxFOM = 10;
2193  if (tj.VtxID[tjEnd] > 0) {
2194  VtxStore& vx2 = slc.vtxs[tj.VtxID[tjEnd] - 1];
2195  vx2Sep = PosSep(vx2.Pos, stp1.Pos);
2196  vx2Score = vx2.Score;
2197  tjlist = GetAssns(slc, "2V", vx2.ID, "T");
2198  vxFOM = std::abs(shMaxAlong - vx2Sep) / 20;
2199  } // 2D vertex exists
2200  fom += vxFOM;
2201  ++cnt;
2202  float chgFrac = ChgFracNearPos(slc, ptp.Pos, tjlist);
2203  float chgFracFOM = (1 - chgFrac) / 0.1;
2204  fom += chgFracFOM;
2205  ++cnt;
2206  // Fraction of wires that have a signal between the parent start and the shower center
2207  float chgFracBtw = ChgFracBetween(ptp, stp1.Pos[0]);
2208  float chgFrcBtwFOM = (1 - chgFrac) / 0.05;
2209  fom += chgFrcBtwFOM;
2210  ++cnt;
2211 
2212  // take the average
2213  fom /= cnt;
2214  // divide by the InShowerProbability
2215  fom /= prob;
2216 
2217  if (prt) {
2218  mf::LogVerbatim myprt("TC");
2219  myprt << fcnLabel;
2220  myprt << " 2S" << ss.ID;
2221  myprt << " T" << tj.ID << "_" << tjEnd << " Pos " << PrintPos(ptp);
2222  myprt << std::fixed << std::setprecision(2);
2223  myprt << " along " << std::fixed << std::setprecision(1) << alongTrans[0] << " fom "
2224  << longFOM;
2225  myprt << " trans " << alongTrans[1] << " fom " << transFOM;
2226  myprt << " prob " << prob;
2227  myprt << " dang1 " << dang1 << " fom " << dang1FOM;
2228  myprt << " dang2 " << dang2 << " fom " << dang2FOM;
2229  myprt << " vx2Score " << vx2Score << " fom " << vxFOM;
2230  myprt << " chgFrac " << chgFrac << " fom " << chgFracFOM;
2231  myprt << " chgFracBtw " << chgFracBtw << " fom " << chgFrcBtwFOM;
2232  myprt << " FOM " << fom;
2233  }
2234  return fom;
2235 
2236  } // ParentFOM
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
double InShowerProbLong(double showerEnergy, double along)
Definition: TCShower.cxx:1937
TCConfig tcc
Definition: DataStructs.cxx:9
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:3066
constexpr auto abs(T v)
Returns the absolute value of the argument.
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:2531
bool MakeBareTrajPoint(const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:4008
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
std::array< float, 2 > Point2_t
Definition: DataStructs.h:41
float ChgFracNearPos(const TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3163
float ChgFracBetween(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, Point3_t pos1, Point3_t pos2)
Definition: PFPUtils.cxx:3163
unsigned short FarEnd(const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3300
std::vector< int > GetAssns(TCSlice const &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4704
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
Definition: TCShower.cxx:1904
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
unsigned short tca::PDGCodeIndex ( int  PDGCode)

Definition at line 2126 of file Utils.cxx.

References util::abs().

2127  {
2128  unsigned short pdg = abs(PDGCode);
2129  if (pdg == 11) return 0; // electron
2130  if (pdg == 13) return 1; // muon
2131  if (pdg == 211) return 2; // pion
2132  if (pdg == 321) return 3; // kaon
2133  if (pdg == 2212) return 4; // proton
2134  return USHRT_MAX;
2135  } // PDGCodeIndex
constexpr auto abs(T v)
Returns the absolute value of the argument.
int tca::PDGCodeVote ( const TCSlice slc,
const std::vector< int > &  tjIDs 
)

Definition at line 410 of file Utils.cxx.

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

411  {
412  // Returns the most likely PDGCode for the set of Tjs provided
413  // The PDG codes are:
414  // 0 = your basic track-like trajectory
415  // 11 = Tagged delta-ray
416  // 13 = Tagged muon
417  // 211 = pion-like. There exists a Bragg peak at an end with a vertex
418  // 2212 = proton-like. There exists a Bragg peak at an end without a vertex
419  std::array<int, 5> codeList = {{0, 11, 13, 111, 211}};
420  unsigned short codeIndex = 0;
421  if (tjIDs.empty()) return codeList[codeIndex];
422 
423  std::array<unsigned short, 5> cnts;
424  cnts.fill(0);
425  float maxLen = 0;
426  for (auto tjid : tjIDs) {
427  if (tjid <= 0 || tjid > (int)slc.tjs.size()) continue;
428  auto& tj = slc.tjs[tjid - 1];
429  for (unsigned short ii = 0; ii < 5; ++ii)
430  if (tj.PDGCode == codeList[ii]) ++cnts[ii];
431  float len = TrajLength(tj);
432  if (len > maxLen) maxLen = len;
433  } // tjid
434  unsigned maxCnt = 0;
435  // ignore the first PDG code in the list (the default)
436  for (unsigned short ii = 1; ii < 5; ++ii) {
437  if (cnts[ii] > maxCnt) {
438  maxCnt = cnts[ii];
439  codeIndex = ii;
440  }
441  } // ii
442  return codeList[codeIndex];
443  } // PDGCodeVote
float TrajLength(const Trajectory &tj)
Definition: Utils.cxx:2582
int tca::PDGCodeVote ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
const TCSlice slc,
PFPStruct pfp 
)

Definition at line 3312 of file PFPUtils.cxx.

References Average_dEdX(), ElectronLikelihood(), Length(), MCSMom(), tca::PFPStruct::TjIDs, tca::TCSlice::tjs, and tca::PFPStruct::TP3Ds.

Referenced by DotProd(), and MakePFParticles().

3316  {
3317  // returns a vote using PDG code assignments from dE/dx. A PDGCode of -1 is
3318  // returned if there was a failure and returns 0 if no decision can be made
3319  if (pfp.TP3Ds.empty()) return -1;
3320 
3321  // try to do better using dE/dx
3322  float dEdXAve = 0;
3323  float dEdXRms = 0;
3324  Average_dEdX(clockData, detProp, slc, pfp, dEdXAve, dEdXRms);
3325  if (dEdXAve < 0) return 0;
3326  // looks like a proton if dE/dx is high and the rms is low
3327  dEdXRms /= dEdXAve;
3328  float length = Length(pfp);
3329  float mcsmom = 0;
3330  float chgrms = 0;
3331  float cnt = 0;
3332  for (auto tjid : pfp.TjIDs) {
3333  auto& tj = slc.tjs[tjid - 1];
3334  float el = ElectronLikelihood(slc, tj);
3335  if (el <= 0) continue;
3336  mcsmom += MCSMom(slc, tj);
3337  chgrms += tj.ChgRMS;
3338  ++cnt;
3339  } // tjid
3340  if (cnt < 2) return 0;
3341  mcsmom /= cnt;
3342  chgrms /= cnt;
3343  int vote = 0;
3344  // call anything longer than 150 cm a muon
3345  if (length > 150) vote = 13;
3346  // or shorter with low dE/dx and really straight
3347  if (vote == 0 && length > 50 && dEdXAve < 2.5 && mcsmom > 500) vote = 13;
3348  // protons have high dE/dx, high MCSMom and low charge rms
3349  if (vote == 0 && dEdXAve > 3.0 && mcsmom > 200 && chgrms < 0.4) vote = 2212;
3350  // electrons have low MCSMom and large charge RMS
3351  if (vote == 0 && mcsmom < 50 && chgrms > 0.4) vote = 11;
3352  return vote;
3353  } // PDGCodeVote
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3381
float Length(const PFPStruct &pfp)
Definition: PFPUtils.cxx:3267
void Average_dEdX(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, float &dEdXAve, float &dEdXRms)
Definition: PFPUtils.cxx:2635
float ElectronLikelihood(const TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:3144
void tca::PFPVertexCheck ( TCSlice slc)

Definition at line 2822 of file PFPUtils.cxx.

References evt, tca::TCEvent::global3V_UID, 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().

2823  {
2824  // Ensure that all PFParticles have a start vertex. It is possible for
2825  // PFParticles to be attached to a 3D vertex that is later killed.
2826  if (!slc.isValid) return;
2827  if (slc.pfps.empty()) return;
2828 
2829  for (auto& pfp : slc.pfps) {
2830  if (pfp.ID == 0) continue;
2831  if (pfp.Vx3ID[0] > 0) continue;
2832  if (pfp.SectionFits.empty()) continue;
2833  Vtx3Store vx3;
2834  vx3.TPCID = pfp.TPCID;
2835  vx3.Vx2ID.resize(slc.nPlanes);
2836  // Flag it as a PFP vertex that isn't required to have matched 2D vertices
2837  vx3.Wire = -2;
2838  Point3_t startPos;
2839  if (pfp.TP3Ds.empty()) {
2840  // must be a neutrino pfp
2841  startPos = pfp.SectionFits[0].Pos;
2842  }
2843  else if (!pfp.TP3Ds.empty()) {
2844  // normal pfp
2845  startPos = pfp.TP3Ds[0].Pos;
2846  }
2847  vx3.X = startPos[0];
2848  vx3.Y = startPos[1];
2849  vx3.Z = startPos[2];
2850  vx3.ID = slc.vtx3s.size() + 1;
2851  vx3.Primary = false;
2852  ++evt.global3V_UID;
2853  vx3.UID = evt.global3V_UID;
2854  slc.vtx3s.push_back(vx3);
2855  pfp.Vx3ID[0] = vx3.ID;
2856  } // pfp
2857  } // PFPVertexCheck
std::array< double, 3 > Point3_t
Definition: DataStructs.h:39
TCEvent evt
Definition: DataStructs.cxx:8
Vector3_t tca::PointDirection ( const Point3_t  p1,
const Point3_t  p2 
)

Definition at line 2538 of file PFPUtils.cxx.

References dir, and SetMag().

Referenced by AttachToAnyVertex(), ChgFracBetween(), DotProd(), FindAlongTrans(), FindParent(), MakeBareTrajPoint(), and UpdateShower().

2539  {
2540  // Finds the direction vector between the two points from p1 to p2
2541  Vector3_t dir;
2542  for (unsigned short xyz = 0; xyz < 3; ++xyz)
2543  dir[xyz] = p2[xyz] - p1[xyz];
2544  if (dir[0] == 0 && dir[1] == 0 && dir[2] == 0) return dir;
2545  if (!SetMag(dir, 1)) {
2546  dir[0] = 0;
2547  dir[1] = 0;
2548  dir[3] = 0;
2549  }
2550  return dir;
2551  } // PointDirection
bool SetMag(Vector3_t &v1, double mag)
Definition: PFPUtils.cxx:2570
TDirectory * dir
Definition: macro.C:5
std::array< double, 3 > Vector3_t
Definition: DataStructs.h:40
Vector2_t tca::PointDirection ( const Point2_t  p1,
const Point2_t  p2 
)

Definition at line 4078 of file Utils.cxx.

References dir, and norm.

4079  {
4080  // Finds the direction vector between the two points from p1 to p2
4081  Vector2_t dir;
4082  for (unsigned short xyz = 0; xyz < 2; ++xyz)
4083  dir[xyz] = p2[xyz] - p1[xyz];
4084  if (dir[0] == 0 && dir[1] == 0) return dir;
4085  double norm = sqrt(dir[0] * dir[0] + dir[1] * dir[1]);
4086  dir[0] /= norm;
4087  dir[1] /= norm;
4088  return dir;
4089  } // PointDirection
std::array< double, 2 > Vector2_t
Definition: DataStructs.h:42
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 3083 of file PFPUtils.cxx.

References LineLineIntersect().

Referenced by DotProd().

3089  {
3090  // Point - vector version
3091  Point3_t p1End, p2End;
3092  for (unsigned short xyz = 0; xyz < 3; ++xyz) {
3093  p1End[xyz] = p1[xyz] + 10 * p1Dir[xyz];
3094  p2End[xyz] = p2[xyz] + 10 * p2Dir[xyz];
3095  }
3096  return LineLineIntersect(p1, p1End, p2, p2End, intersect, doca);
3097  } // PointDirIntersect
std::array< double, 3 > Point3_t
Definition: DataStructs.h:39
bool LineLineIntersect(Point3_t p1, Point3_t p2, Point3_t p3, Point3_t p4, Point3_t &intersect, float &doca)
Definition: PFPUtils.cxx:3100
bool tca::PointInsideEnvelope ( const Point2_t Point,
const std::vector< Point2_t > &  Envelope 
)

Definition at line 3246 of file Utils.cxx.

References util::abs(), and DeltaAngle().

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

3247  {
3248  // returns true if the Point is within the Envelope polygon. Entries in Envelope are the
3249  // Pos[0], Pos[1] locations of the polygon vertices. This is based on the algorithm that the
3250  // sum of the angles of a vector between a point and the vertices will be 2 * pi for an interior
3251  // point and 0 for an exterior point
3252 
3253  Point2_t p1, p2;
3254  unsigned short nvx = Envelope.size();
3255  double angleSum = 0;
3256  for (unsigned short ii = 0; ii < Envelope.size(); ++ii) {
3257  p1[0] = Envelope[ii][0] - Point[0];
3258  p1[1] = Envelope[ii][1] - Point[1];
3259  p2[0] = Envelope[(ii + 1) % nvx][0] - Point[0];
3260  p2[1] = Envelope[(ii + 1) % nvx][1] - Point[1];
3261  angleSum += DeltaAngle(p1, p2);
3262  }
3263  if (abs(angleSum) < M_PI) return false;
3264  return true;
3265 
3266  } // InsideEnvelope
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::array< float, 2 > Point2_t
Definition: DataStructs.h:41
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:42
double DeltaAngle(double Ang1, double Ang2)
Definition: Utils.cxx:3324
float tca::PointPull ( Point2_t  pos,
float  chg,
const Trajectory tj 
)

Definition at line 544 of file Utils.cxx.

References util::abs(), tca::Trajectory::AlgMod, tca::Trajectory::AveChg, tca::Trajectory::ChgRMS, close(), tca::Trajectory::EndPt, kKilled, PointTrajDOCA(), PosSep2(), and tca::Trajectory::Pts.

545  {
546  // returns the combined position and charge pull for the charge at pos
547  // relative to the Tj closest to that point using a loose requirement on position separation.
548  if (tj.AlgMod[kKilled]) return 100;
549  if (tj.AveChg <= 0) return 100;
550  // find the closest point on the tj to pos
551  unsigned short closePt = USHRT_MAX;
552  float close = 1000;
553  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
554  auto& tp = tj.Pts[ipt];
555  float sep2 = PosSep2(pos, tp.Pos);
556  if (sep2 > close) continue;
557  close = sep2;
558  closePt = ipt;
559  } // ipt
560  if (closePt == USHRT_MAX) return 100;
561  // find the delta between the projection of the Tj close TP to inTP
562  auto& tp = tj.Pts[closePt];
563  float delta = PointTrajDOCA(pos[0], pos[1], tp);
564  // estimate the proejcted position error (roughly)
565  float posErr = tp.DeltaRMS;
566  if (tp.AngErr > 0 && close > 10) posErr += sqrt(tp.AngErr * sqrt(close));
567  if (posErr < 0.1) posErr = 0.1;
568  float posPull = delta / posErr;
569  float chgErr = tj.ChgRMS;
570  if (chgErr < 0.15) chgErr = 0.15;
571  float chgPull = std::abs(chg / tj.AveChg - 1) / chgErr;
572  // return a simple average
573  return 0.5 * (posPull + chgPull);
574  } // PointPull
constexpr auto abs(T v)
Returns the absolute value of the argument.
float PointTrajDOCA(float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2524
float PosSep2(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2604
in close()
float tca::PointPull ( const TP3D tp3d)

Definition at line 2794 of file PFPUtils.cxx.

References util::abs(), tca::TP3D::Pos, tca::TP3D::TPX, and tca::TP3D::TPXErr2.

Referenced by AddPointsInRange(), CountBadPoints(), DotProd(), and PrintTP3Ds().

2795  {
2796  // returns the pull that the tp3d will cause in the pfp section fit. This
2797  // currently only uses position but eventually will include charge
2798  return std::abs(tp3d.Pos[0] - tp3d.TPX) / sqrt(tp3d.TPXErr2);
2799  } // PointPull
constexpr auto abs(T v)
Returns the absolute value of the argument.
float tca::PointTrajDOCA ( const TCSlice slc,
unsigned int  iht,
TrajPoint const &  tp 
)

Definition at line 2514 of file Utils.cxx.

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

Referenced by AddHits(), CheckHiMultUnusedHits(), CompatibleMerge(), CompleteIncomplete3DVerticesInGaps(), EndMerge(), FillGaps(), FindCloseHits(), FindHammerVertices2(), FindNearbyTjs(), FindUseHits(), FixBegin(), Forecast(), LastEndMerge(), MakeHaloTj(), MaskTrajEndPoints(), MaxHitDelta(), MergeShowerChain(), MergeSubShowers(), MergeSubShowersTj(), PointPull(), SplitTrajCrossingVertices(), TrajPointVertexPull(), UpdateDeltaRMS(), UpdateStiffEl(), and UpdateTraj().

2515  {
2516  if (iht > slc.slHits.size() - 1) return 1E6;
2517  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2518  float wire = hit.WireID().Wire;
2519  float time = hit.PeakTime() * tcc.unitsPerTick;
2520  return sqrt(PointTrajDOCA2(wire, time, tp));
2521  } // PointTrajDOCA
TCConfig tcc
Definition: DataStructs.cxx:9
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
float PointTrajDOCA2(float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2530
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
float tca::PointTrajDOCA ( float  wire,
float  time,
TrajPoint const &  tp 
)

Definition at line 2524 of file Utils.cxx.

References PointTrajDOCA2().

2525  {
2526  return sqrt(PointTrajDOCA2(wire, time, tp));
2527  } // PointTrajDOCA
float PointTrajDOCA2(float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2530
float tca::PointTrajDOCA2 ( float  wire,
float  time,
TrajPoint const &  tp 
)

Definition at line 2530 of file Utils.cxx.

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

Referenced by PointTrajDOCA(), and TjDeltaRMS().

2531  {
2532  // returns the distance of closest approach squared between a (wire, time(WSE)) point
2533  // and a trajectory point
2534 
2535  double t = (double)(wire - tp.Pos[0]) * tp.Dir[0] + (double)(time - tp.Pos[1]) * tp.Dir[1];
2536  double dw = tp.Pos[0] + t * tp.Dir[0] - wire;
2537  double dt = tp.Pos[1] + t * tp.Dir[1] - time;
2538  return (float)(dw * dw + dt * dt);
2539 
2540  } // PointTrajDOCA2
float tca::PointTrajSep2 ( float  wire,
float  time,
TrajPoint const &  tp 
)

Definition at line 2506 of file Utils.cxx.

References tca::TrajPoint::Pos.

2507  {
2508  float dw = wire - tp.Pos[0];
2509  float dt = time - tp.Pos[1];
2510  return dw * dw + dt * dt;
2511  }
Point3_t tca::PosAtEnd ( const PFPStruct pfp,
unsigned short  end 
)

Definition at line 3257 of file PFPUtils.cxx.

References if(), tca::PFPStruct::SectionFits, and tca::PFPStruct::TP3Ds.

Referenced by AttachToAnyVertex(), ChgFracNearEnd(), DotProd(), FilldEdx(), FindParent(), MakePFParticles(), PrintP(), PrintPFP(), cluster::TrajCluster::produce(), Reconcile3D(), SetParent(), StitchPFPs(), and UpdateShower().

3258  {
3259  if (end > 1 || pfp.SectionFits.empty()) return {{0., 0., 0.}};
3260  // handle a neutrino pfp that doesn't have any TP3Ds
3261  if (pfp.TP3Ds.empty()) return pfp.SectionFits[0].Pos;
3262  if (end == 0) return pfp.TP3Ds[0].Pos;
3263  return pfp.TP3Ds[pfp.TP3Ds.size() - 1].Pos;
3264  } // PosAtEnd
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
if(nlines<=0)
void tca::PosInPlane ( detinfo::DetectorPropertiesData const &  detProp,
const Vtx3Store vx3,
unsigned short  plane,
Point2_t pos 
)

Definition at line 2847 of file TCVertex.cxx.

References detinfo::DetectorPropertiesData::ConvertXToTicks(), geo::WireReadoutGeom::Plane(), tcc, tca::Vtx3Store::TPCID, tca::TCConfig::unitsPerTick, geo::PlaneGeo::WireCoordinate(), tca::TCConfig::wireReadoutGeom, tca::Vtx3Store::X, tca::Vtx3Store::Y, and tca::Vtx3Store::Z.

Referenced by Print3V(), and PrintAllTraj().

2851  {
2852  // returns the 2D position of the vertex in the plane
2853  geo::PlaneID const planeID{vx3.TPCID, plane};
2854  pos[0] = tcc.wireReadoutGeom->Plane(planeID).WireCoordinate(geo::Point_t{0, vx3.Y, vx3.Z});
2855  pos[1] = detProp.ConvertXToTicks(vx3.X, planeID) * tcc.unitsPerTick;
2856  }
const geo::WireReadoutGeom * wireReadoutGeom
Definition: DataStructs.h:568
double WireCoordinate(Point_t const &point) const
Returns the coordinate of the point on the plane, in wire units.
Definition: PlaneGeo.h:704
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:180
PlaneGeo const & Plane(TPCID const &tpcid, View_t view) const
Returns the specified wire.
constexpr TPCID()=default
Default constructor: an invalid TPC ID.
float tca::PosSep ( const Point2_t pos1,
const Point2_t pos2 
)

Definition at line 2598 of file Utils.cxx.

References PosSep2().

2599  {
2600  return sqrt(PosSep2(pos1, pos2));
2601  } // PosSep
float PosSep2(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2604
double tca::PosSep2 ( const Point3_t pos1,
const Point3_t pos2 
)

Definition at line 2560 of file PFPUtils.cxx.

Referenced by AttachTrajToVertex(), CloseEnd(), DotProd(), EndMerge(), FarEnd(), FilldEdx(), Find2DVertices(), FindParent(), MaxTjLen(), MergeAndStore(), MergeOverlap(), ParentFOM(), PointPull(), PosSep(), StepAway(), StitchPFPs(), TrajPointVertexPull(), and UpdateShower().

2561  {
2562  // returns the separation distance^2 between two positions in 3D
2563  double d0 = pos1[0] - pos2[0];
2564  double d1 = pos1[1] - pos2[1];
2565  double d2 = pos1[2] - pos2[2];
2566  return d0 * d0 + d1 * d1 + d2 * d2;
2567  } // PosSep2
float tca::PosSep2 ( const Point2_t pos1,
const Point2_t pos2 
)

Definition at line 2604 of file Utils.cxx.

2605  {
2606  // returns the separation distance^2 between two positions
2607  float d0 = pos1[0] - pos2[0];
2608  float d1 = pos1[1] - pos2[1];
2609  return d0 * d0 + d1 * d1;
2610  } // PosSep2
int tca::PrimaryID ( const TCSlice slc,
const Trajectory tj 
)

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

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

Definition at line 487 of file Utils.cxx.

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

Referenced by PrintPFP().

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

Definition at line 4192 of file TCShower.cxx.

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

Referenced by FindShowers3D(), and Reconcile3D().

4196  {
4197  // Prints a one-line summary of 2D showers
4198  if (slc.cots.empty()) return;
4199 
4200  mf::LogVerbatim myprt("TC");
4201 
4202  // see how many lines were are going to print
4203  bool printAllCTP = (inCTP == USHRT_MAX);
4204  if (!printAllCTP) {
4205  unsigned short nlines = 0;
4206  for (const auto& ss : slc.cots) {
4207  if (!printAllCTP && ss.CTP != inCTP) continue;
4208  if (!printKilledShowers && ss.ID == 0) continue;
4209  ++nlines;
4210  } // ss
4211  if (nlines == 0) {
4212  myprt << someText << " Print2DShowers: Nothing to print";
4213  return;
4214  }
4215  } // !printAllCTP
4216 
4217  bool printHeader = true;
4218  bool printExtras = false;
4219  for (unsigned short ict = 0; ict < slc.cots.size(); ++ict) {
4220  const auto& ss = slc.cots[ict];
4221  if (!printAllCTP && ss.CTP != inCTP) continue;
4222  if (!printKilledShowers && ss.ID == 0) continue;
4223  PrintShower(someText, slc, ss, printHeader, printExtras);
4224  printHeader = false;
4225  } // ss
4226  // List of Tjs
4227  for (unsigned short ict = 0; ict < slc.cots.size(); ++ict) {
4228  const auto& ss = slc.cots[ict];
4229  if (!printAllCTP && ss.CTP != inCTP) continue;
4230  if (!printKilledShowers && ss.ID == 0) continue;
4231  myprt << someText << std::fixed;
4232  std::string sid = "2S" + std::to_string(ss.ID);
4233  myprt << std::setw(5) << sid;
4234  myprt << " Tjs";
4235  for (auto id : ss.TjIDs)
4236  myprt << " T" << id;
4237  myprt << "\n";
4238  } // ict
4239  // Print the envelopes
4240  for (unsigned short ict = 0; ict < slc.cots.size(); ++ict) {
4241  const auto& ss = slc.cots[ict];
4242  if (!printAllCTP && ss.CTP != inCTP) continue;
4243  if (!printKilledShowers && ss.ID == 0) continue;
4244  myprt << someText << std::fixed;
4245  std::string sid = "2S" + std::to_string(ss.ID);
4246  myprt << std::setw(5) << sid;
4247  myprt << " Envelope";
4248  for (auto& vtx : ss.Envelope)
4249  myprt << " " << (int)vtx[0] << ":" << (int)(vtx[1] / tcc.unitsPerTick);
4250  myprt << "\n";
4251  } // ict
4252  // List of nearby Tjs
4253  for (unsigned short ict = 0; ict < slc.cots.size(); ++ict) {
4254  const auto& ss = slc.cots[ict];
4255  if (!printAllCTP && ss.CTP != inCTP) continue;
4256  if (!printKilledShowers && ss.ID == 0) continue;
4257  myprt << someText << std::fixed;
4258  std::string sid = "2S" + std::to_string(ss.ID);
4259  myprt << std::setw(5) << sid;
4260  myprt << " Nearby";
4261  for (auto id : ss.NearTjIDs)
4262  myprt << " T" << id;
4263  myprt << "\n";
4264  } // ict
4265  // don't cluster list
4266  myprt << "DontCluster";
4267  for (auto& dc : slc.dontCluster) {
4268  if (dc.TjIDs[0] > 0) myprt << " T" << dc.TjIDs[0] << "-T" << dc.TjIDs[1];
4269  } // dc
4270  myprt << "\nDontCluster";
4271  for (unsigned short ict = 0; ict < slc.cots.size(); ++ict) {
4272  const auto& iss = slc.cots[ict];
4273  if (iss.ID == 0) continue;
4274  for (unsigned short jct = ict + 1; jct < slc.cots.size(); ++jct) {
4275  const auto& jss = slc.cots[jct];
4276  if (jss.ID == 0) continue;
4277  if (DontCluster(slc, iss.TjIDs, jss.TjIDs)) myprt << " 2S" << iss.ID << "-2S" << jss.ID;
4278  } // jct
4279  } // ict
4280  } // Print2DShowers
TCConfig tcc
Definition: DataStructs.cxx:9
bool DontCluster(TCSlice const &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3213
nlines
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
void PrintShower(std::string someText, TCSlice const &slc, const ShowerStruct &ss, bool printHeader, bool printExtras)
Definition: TCShower.cxx:4283
void tca::Print2V ( mf::LogVerbatim myprt,
VtxStore const &  vx2,
bool &  printHeader 
)

Definition at line 5613 of file Utils.cxx.

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

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

5614  {
5615  // print a 2D vertex on one line
5616  if (vx2.ID <= 0) return;
5617  if (debug.CTP != UINT_MAX && vx2.CTP != debug.CTP) return;
5618  auto sIndx = GetSliceIndex("2V", vx2.UID);
5619  if (sIndx.first == USHRT_MAX) return;
5620  auto const& slc = slices[sIndx.first];
5621  if (printHeader) {
5622  myprt << "************ 2D vertices ************\n";
5623  myprt << " prodID CTP wire err tick err ChiDOF NTj Pass Topo ChgFrac Score "
5624  " v3D Tj UIDs\n";
5625  printHeader = false;
5626  }
5627  std::string str = "2V" + std::to_string(vx2.ID) + "/2VU" + std::to_string(vx2.UID);
5628  myprt << std::right << std::setw(12) << std::fixed << str;
5629  myprt << std::right << std::setw(6) << vx2.CTP;
5630  myprt << std::right << std::setw(8) << std::setprecision(0) << std::nearbyint(vx2.Pos[0]);
5631  myprt << std::right << std::setw(5) << std::setprecision(1) << vx2.PosErr[0];
5632  myprt << std::right << std::setw(8) << std::setprecision(0)
5633  << std::nearbyint(vx2.Pos[1] / tcc.unitsPerTick);
5634  myprt << std::right << std::setw(5) << std::setprecision(1) << vx2.PosErr[1] / tcc.unitsPerTick;
5635  myprt << std::right << std::setw(7) << vx2.ChiDOF;
5636  myprt << std::right << std::setw(5) << vx2.NTraj;
5637  myprt << std::right << std::setw(5) << vx2.Pass;
5638  myprt << std::right << std::setw(6) << vx2.Topo;
5639  myprt << std::right << std::setw(9) << std::setprecision(2) << vx2.TjChgFrac;
5640  myprt << std::right << std::setw(6) << std::setprecision(1) << vx2.Score;
5641  int v3id = 0;
5642  if (vx2.Vx3ID > 0) v3id = slc.vtx3s[vx2.Vx3ID - 1].UID;
5643  myprt << std::right << std::setw(5) << v3id;
5644  myprt << " ";
5645  // display the traj IDs
5646  for (unsigned short ii = 0; ii < slc.tjs.size(); ++ii) {
5647  auto const& tj = slc.tjs[ii];
5648  if (tj.AlgMod[kKilled]) continue;
5649  for (unsigned short end = 0; end < 2; ++end) {
5650  if (tj.VtxID[end] != (short)vx2.ID) continue;
5651  std::string tid = " TU" + std::to_string(tj.UID) + "_" + std::to_string(end);
5652  myprt << std::right << std::setw(6) << tid;
5653  } // end
5654  } // ii
5655  myprt << " Stat:";
5656  // Special flags. Ignore the first flag bit (0 = kVxTrjTried) which is done for every vertex
5657  for (unsigned short ib = 1; ib < VtxBitNames.size(); ++ib)
5658  if (vx2.Stat[ib]) myprt << " " << VtxBitNames[ib];
5659  myprt << "\n";
5660  } // Print2V
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:102
TCConfig tcc
Definition: DataStructs.cxx:9
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
DebugStuff debug
Definition: DebugStruct.cxx:4
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
const std::vector< std::string > VtxBitNames
Definition: DataStructs.cxx:89
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:4942
CTP_t CTP
set to an invalid CTP
Definition: DebugStruct.h:23
void tca::Print3S ( detinfo::DetectorPropertiesData const &  detProp,
mf::LogVerbatim myprt,
ShowerStruct3D const &  ss3 
)

Definition at line 5663 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, util::to_string(), geo::TPCID::TPC, tca::ShowerStruct3D::TPCID, tca::ShowerStruct3D::UID, and tca::ShowerStruct3D::Vx3ID.

Referenced by DotProd(), and PrintAll().

5666  {
5667  if (ss3.ID <= 0) return;
5668  auto sIndx = GetSliceIndex("3S", ss3.UID);
5669  if (sIndx.first == USHRT_MAX) return;
5670  auto const& slc = slices[sIndx.first];
5671  std::string str =
5672  std::to_string(slc.ID) + ":" + std::to_string(sIndx.first) + ":" + std::to_string(ss3.ID);
5673  str += "/" + std::to_string(ss3.UID);
5674  myprt << std::fixed << std::setw(12) << str;
5675  str = "--";
5676  if (ss3.Vx3ID > 0) str = "3V" + std::to_string(slc.vtx3s[ss3.Vx3ID - 1].UID);
5677  myprt << std::setw(6) << str;
5678  for (unsigned short xyz = 0; xyz < 3; ++xyz)
5679  myprt << std::setprecision(0) << std::setw(5) << ss3.ChgPos[xyz];
5680  for (unsigned short xyz = 0; xyz < 3; ++xyz)
5681  myprt << std::setprecision(2) << std::setw(5) << ss3.Dir[xyz];
5682  std::vector<float> projInPlane(slc.nPlanes);
5683  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
5684  CTP_t inCTP = EncodeCTP(ss3.TPCID.Cryostat, ss3.TPCID.TPC, plane);
5685  auto tp = MakeBareTP(detProp, ss3.ChgPos, ss3.Dir, inCTP);
5686  myprt << " " << PrintPos(tp.Pos);
5687  projInPlane[plane] = tp.Delta;
5688  } // plane
5689  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
5690  myprt << std::setprecision(2) << std::setw(5) << projInPlane[plane];
5691  } // plane
5692  for (auto cid : ss3.CotIDs) {
5693  auto& ss = slc.cots[cid - 1];
5694  str = "2SU" + std::to_string(ss.UID);
5695  myprt << std::setw(5) << str;
5696  } // ci
5697  if (ss3.NeedsUpdate) myprt << " *** Needs update";
5698  myprt << "\n";
5699  } // Print3S
std::string PrintPos(const Point2_t &pos)
Definition: Utils.cxx:6362
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const Point3_t &pos, const Vector3_t &dir, CTP_t inCTP)
Definition: Utils.cxx:3945
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
unsigned int CTP_t
Definition: DataStructs.h:45
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:49
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:4942
void tca::Print3V ( detinfo::DetectorPropertiesData const &  detProp,
mf::LogVerbatim myprt,
Vtx3Store const &  vx3,
bool &  printHeader 
)

Definition at line 5538 of file Utils.cxx.

References geo::CryostatID::Cryostat, util::end(), GetAssns(), GetSliceIndex(), tca::Vtx3Store::ID, kVxTruMatch, tca::Vtx3Store::Neutrino, PosInPlane(), tca::Vtx3Store::Primary, PrintPos(), art::right(), tca::Vtx3Store::Score, slices, util::to_string(), geo::TPCID::TPC, tca::Vtx3Store::TPCID, tca::Vtx3Store::UID, tca::Vtx3Store::Vx2ID, tca::Vtx3Store::Wire, tca::Vtx3Store::X, tca::Vtx3Store::Y, and tca::Vtx3Store::Z.

Referenced by DotProd(), and PrintAll().

5542  {
5543  // print a 3D vertex on one line
5544  if (vx3.ID <= 0) return;
5545  auto sIndx = GetSliceIndex("3V", vx3.UID);
5546  if (sIndx.first == USHRT_MAX) return;
5547  auto const& slc = slices[sIndx.first];
5548  if (printHeader) {
5549  myprt
5550  << "****** 3D vertices ******************************************__2DVtx_UID__*******\n";
5551  myprt << " prodID Cstat TPC X Y Z pln0 pln1 pln2 Wire score "
5552  "Prim? Nu? nTru";
5553  myprt << " ___________2D_Pos____________ _____Tj UIDs________\n";
5554  printHeader = false;
5555  }
5556  std::string str = "3V" + std::to_string(vx3.ID) + "/3VU" + std::to_string(vx3.UID);
5557  myprt << std::right << std::setw(12) << std::fixed << str;
5558  myprt << std::setprecision(0);
5559  myprt << std::right << std::setw(7) << vx3.TPCID.Cryostat;
5560  myprt << std::right << std::setw(5) << vx3.TPCID.TPC;
5561  myprt << std::right << std::setw(8) << vx3.X;
5562  myprt << std::right << std::setw(8) << vx3.Y;
5563  myprt << std::right << std::setw(8) << vx3.Z;
5564  for (auto vx2id : vx3.Vx2ID) {
5565  if (vx2id > 0) {
5566  str = "2VU" + std::to_string(slc.vtxs[vx2id - 1].UID);
5567  myprt << std::right << std::setw(7) << str;
5568  }
5569  else {
5570  myprt << " --";
5571  }
5572  } // vx2id
5573  myprt << std::right << std::setw(5) << vx3.Wire;
5574  unsigned short nTruMatch = 0;
5575  for (unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
5576  if (vx3.Vx2ID[ipl] == 0) continue;
5577  unsigned short iv2 = vx3.Vx2ID[ipl] - 1;
5578  if (slc.vtxs[iv2].Stat[kVxTruMatch]) ++nTruMatch;
5579  } // ipl
5580  myprt << std::right << std::setw(6) << std::setprecision(1) << vx3.Score;
5581  myprt << std::setw(6) << vx3.Primary;
5582  myprt << std::setw(4) << vx3.Neutrino;
5583  myprt << std::right << std::setw(5) << nTruMatch;
5584  Point2_t pos;
5585  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
5586  PosInPlane(detProp, vx3, plane, pos);
5587  myprt << " " << PrintPos(pos);
5588  } // plane
5589  if (vx3.Wire == -2) {
5590  // find the Tjs that are attached to it
5591  for (unsigned short end = 0; end < 2; ++end) {
5592  for (auto& pfp : slc.pfps) {
5593  if (pfp.Vx3ID[end] == vx3.ID) {
5594  for (auto tjID : pfp.TjIDs) {
5595  auto& tj = slc.tjs[tjID - 1];
5596  myprt << " T" << tj.UID;
5597  } // tjID
5598  } // pfp.Vx3ID[0] == vx3.ID
5599  } // pfp
5600  } // end
5601  }
5602  else {
5603  auto vxtjs = GetAssns(slc, "3V", vx3.ID, "T");
5604  for (auto tjid : vxtjs) {
5605  auto& tj = slc.tjs[tjid - 1];
5606  myprt << " TU" << tj.UID;
5607  }
5608  } // vx3.Wire != -2
5609  myprt << "\n";
5610  } // Print3V
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:102
tagged as a vertex between Tjs that are matched to MC truth neutrino interaction particles ...
Definition: DataStructs.h:91
std::string PrintPos(const Point2_t &pos)
Definition: Utils.cxx:6362
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
std::array< float, 2 > Point2_t
Definition: DataStructs.h:41
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
std::vector< int > GetAssns(TCSlice const &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4704
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:4942
void PosInPlane(detinfo::DetectorPropertiesData const &detProp, const Vtx3Store &vx3, unsigned short plane, Point2_t &pos)
Definition: TCVertex.cxx:2847
void tca::PrintAll ( detinfo::DetectorPropertiesData const &  detProp,
std::string  someText 
)

Definition at line 5370 of file Utils.cxx.

References debug, Print2V(), Print3S(), Print3V(), PrintP(), PrintT(), tca::DebugStuff::Slice, and slices.

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

5371  {
5372  // print everything in all slices
5373  bool prt3V = false;
5374  bool prt2V = false;
5375  bool prtT = false;
5376  bool prtP = false;
5377  bool prtS3 = false;
5378  for (size_t isl = 0; isl < slices.size(); ++isl) {
5379  if (debug.Slice >= 0 && int(isl) != debug.Slice) continue;
5380  auto const& slc = slices[isl];
5381  if (!slc.vtx3s.empty()) prt3V = true;
5382  if (!slc.vtxs.empty()) prt2V = true;
5383  if (!slc.tjs.empty()) prtT = true;
5384  if (!slc.pfps.empty()) prtP = true;
5385  if (!slc.showers.empty()) prtS3 = true;
5386  } // slc
5387  mf::LogVerbatim myprt("TC");
5388  myprt << "Debug report from caller " << someText << "\n";
5389  myprt << " 'prodID' = <sliceID>:<subSliceIndex>:<productID>/<productUID>\n";
5390  if (prtS3) {
5391  myprt << "************ Showers ************\n";
5392  myprt << " prodID Vtx parUID ___ChgPos____ ______Dir_____ ____posInPln____ "
5393  "___projInPln____ 2D shower UIDs\n";
5394  for (size_t isl = 0; isl < slices.size(); ++isl) {
5395  if (debug.Slice >= 0 && int(isl) != debug.Slice) continue;
5396  auto const& slc = slices[isl];
5397  if (slc.showers.empty()) continue;
5398  for (auto& ss3 : slc.showers)
5399  Print3S(detProp, myprt, ss3);
5400  } // slc
5401  } // prtS3
5402  if (prtP) {
5403  bool printHeader = true;
5404  for (size_t isl = 0; isl < slices.size(); ++isl) {
5405  if (debug.Slice >= 0 && int(isl) != debug.Slice) continue;
5406  auto const& slc = slices[isl];
5407  if (slc.pfps.empty()) continue;
5408  for (auto& pfp : slc.pfps)
5409  PrintP(myprt, pfp, printHeader);
5410  } // slc
5411  } // prtS3
5412  if (prt3V) {
5413  bool printHeader = true;
5414  myprt << "****** 3D vertices "
5415  "******************************************__2DVtx_UID__*******\n";
5416  myprt << " prodID Cstat TPC X Y Z XEr YEr "
5417  "ZEr pln0 pln1 pln2 Wire score Prim? Nu? nTru";
5418  myprt << " ___________2D_Pos____________ _____Tj UIDs________\n";
5419  for (size_t isl = 0; isl < slices.size(); ++isl) {
5420  if (debug.Slice >= 0 && int(isl) != debug.Slice) continue;
5421  auto const& slc = slices[isl];
5422  if (slc.vtx3s.empty()) continue;
5423  for (auto& vx3 : slc.vtx3s)
5424  Print3V(detProp, myprt, vx3, printHeader);
5425  } // slc
5426  } // prt3V
5427  if (prt2V) {
5428  bool printHeader = true;
5429  myprt << "************ 2D vertices ************\n";
5430  myprt << " prodID CTP wire err tick err ChiDOF NTj Pass "
5431  " Topo ChgFrac Score v3D Tj UIDs\n";
5432  for (size_t isl = 0; isl < slices.size(); ++isl) {
5433  if (debug.Slice >= 0 && int(isl) != debug.Slice) continue;
5434  auto const& slc = slices[isl];
5435  if (slc.vtxs.empty()) continue;
5436  for (auto& vx2 : slc.vtxs)
5437  Print2V(myprt, vx2, printHeader);
5438  } // slc
5439  } // prt2V
5440  if (prtT) {
5441  bool printHeader = true;
5442  for (size_t isl = 0; isl < slices.size(); ++isl) {
5443  if (debug.Slice >= 0 && int(isl) != debug.Slice) continue;
5444  auto const& slc = slices[isl];
5445  if (slc.tjs.empty()) continue;
5446  for (auto& tj : slc.tjs)
5447  PrintT(myprt, tj, printHeader);
5448  } // slc
5449  } // prtT
5450  } // PrintAll
void Print2V(mf::LogVerbatim &myprt, VtxStore const &vx2, bool &printHeader)
Definition: Utils.cxx:5613
void Print3S(detinfo::DetectorPropertiesData const &detProp, mf::LogVerbatim &myprt, ShowerStruct3D const &ss3)
Definition: Utils.cxx:5663
DebugStuff debug
Definition: DebugStruct.cxx:4
void PrintT(mf::LogVerbatim &myprt, Trajectory const &tj, bool &printHeader)
Definition: Utils.cxx:5702
void PrintP(mf::LogVerbatim &myprt, PFPStruct const &pfp, bool &printHeader)
Definition: Utils.cxx:5453
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
void Print3V(detinfo::DetectorPropertiesData const &detProp, mf::LogVerbatim &myprt, Vtx3Store const &vx3, bool &printHeader)
Definition: Utils.cxx:5538
void tca::PrintAllTraj ( detinfo::DetectorPropertiesData const &  detProp,
std::string  someText,
TCSlice const &  slc,
unsigned short  itj,
unsigned short  ipt,
bool  prtVtx 
)

Definition at line 5793 of file Utils.cxx.

References AlgBitNames, geo::CryostatID::Cryostat, tca::DebugStuff::CTP, debug, DecodeCTP(), util::end(), GetAssns(), tca::Vtx3Store::ID, kAtKink, kAtTj, kAtVtx, kBragg, kKilled, kVxTruMatch, tca::Vtx3Store::Neutrino, NeutrinoPrimaryTjID(), tca::TCSlice::nPlanes, tca::TCSlice::pfps, tca::DebugStuff::Plane, geo::PlaneID::Plane, PosInPlane(), tca::Vtx3Store::Primary, PrimaryID(), PrintPos(), PrintTP(), PrintTPHeader(), art::right(), tca::Vtx3Store::Score, tcc, tca::TCSlice::tjs, tmp, util::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().

5799  {
5800 
5801  mf::LogVerbatim myprt("TC");
5802 
5803  if (prtVtx) {
5804  if (!slc.vtx3s.empty()) {
5805  // print out 3D vertices
5806  myprt
5807  << someText
5808  << "****** 3D vertices ******************************************__2DVtx_ID__*******\n";
5809  myprt << someText
5810  << " Vtx Cstat TPC X Y Z XEr YEr ZEr pln0 pln1 pln2 Wire "
5811  "score Prim? Nu? nTru";
5812  myprt << " ___________2D_Pos____________ _____Tjs________\n";
5813  for (unsigned short iv = 0; iv < slc.vtx3s.size(); ++iv) {
5814  if (slc.vtx3s[iv].ID == 0) continue;
5815  const Vtx3Store& vx3 = slc.vtx3s[iv];
5816  myprt << someText;
5817  std::string vid = "3v" + std::to_string(vx3.ID);
5818  myprt << std::right << std::setw(5) << std::fixed << vid;
5819  myprt << std::setprecision(1);
5820  myprt << std::right << std::setw(7) << vx3.TPCID.Cryostat;
5821  myprt << std::right << std::setw(5) << vx3.TPCID.TPC;
5822  myprt << std::right << std::setw(8) << vx3.X;
5823  myprt << std::right << std::setw(8) << vx3.Y;
5824  myprt << std::right << std::setw(8) << vx3.Z;
5825  myprt << std::right << std::setw(5) << vx3.XErr;
5826  myprt << std::right << std::setw(5) << vx3.YErr;
5827  myprt << std::right << std::setw(5) << vx3.ZErr;
5828  myprt << std::right << std::setw(5) << vx3.Vx2ID[0];
5829  myprt << std::right << std::setw(5) << vx3.Vx2ID[1];
5830  myprt << std::right << std::setw(5) << vx3.Vx2ID[2];
5831  myprt << std::right << std::setw(5) << vx3.Wire;
5832  unsigned short nTruMatch = 0;
5833  for (unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
5834  if (vx3.Vx2ID[ipl] == 0) continue;
5835  unsigned short iv2 = vx3.Vx2ID[ipl] - 1;
5836  if (slc.vtxs[iv2].Stat[kVxTruMatch]) ++nTruMatch;
5837  } // ipl
5838  myprt << std::right << std::setw(6) << std::setprecision(1) << vx3.Score;
5839  myprt << std::setw(6) << vx3.Primary;
5840  myprt << std::setw(4) << vx3.Neutrino;
5841  myprt << std::right << std::setw(5) << nTruMatch;
5842  Point2_t pos;
5843  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
5844  PosInPlane(detProp, vx3, plane, pos);
5845  myprt << " " << PrintPos(pos);
5846  } // plane
5847  if (vx3.Wire == -2) {
5848  // find the Tjs that are attached to it
5849  for (auto& pfp : slc.pfps) {
5850  if (pfp.Vx3ID[0] == slc.vtx3s[iv].ID) {
5851  for (auto& tjID : pfp.TjIDs)
5852  myprt << " t" << tjID;
5853  }
5854  if (pfp.Vx3ID[1] == slc.vtx3s[iv].ID) {
5855  for (auto& tjID : pfp.TjIDs)
5856  myprt << " t" << tjID;
5857  }
5858  } // ipfp
5859  }
5860  else {
5861  auto vxtjs = GetAssns(slc, "3V", vx3.ID, "T");
5862  for (auto tjid : vxtjs)
5863  myprt << " t" << tjid;
5864  }
5865  myprt << "\n";
5866  }
5867  } // slc.vtx3s.size
5868  if (!slc.vtxs.empty()) {
5869  bool foundOne = false;
5870  for (unsigned short iv = 0; iv < slc.vtxs.size(); ++iv) {
5871  auto& vx2 = slc.vtxs[iv];
5872  if (debug.Plane < 3 && debug.Plane != (int)DecodeCTP(vx2.CTP).Plane) continue;
5873  if (vx2.NTraj == 0) continue;
5874  foundOne = true;
5875  } // iv
5876  if (foundOne) {
5877  // print out 2D vertices
5878  myprt << someText << "************ 2D vertices ************\n";
5879  myprt << someText
5880  << " ID CTP wire err tick err ChiDOF NTj Pass Topo ChgFrac Score v3D "
5881  "TjIDs\n";
5882  for (auto& vx2 : slc.vtxs) {
5883  if (vx2.ID == 0) continue;
5884  if (debug.Plane < 3 && debug.Plane != (int)DecodeCTP(vx2.CTP).Plane) continue;
5885  myprt << someText;
5886  std::string vid = "2v" + std::to_string(vx2.ID);
5887  myprt << std::right << std::setw(5) << std::fixed << vid;
5888  myprt << std::right << std::setw(6) << vx2.CTP;
5889  myprt << std::right << std::setw(8) << std::setprecision(0)
5890  << std::nearbyint(vx2.Pos[0]);
5891  myprt << std::right << std::setw(5) << std::setprecision(1) << vx2.PosErr[0];
5892  myprt << std::right << std::setw(8) << std::setprecision(0)
5893  << std::nearbyint(vx2.Pos[1] / tcc.unitsPerTick);
5894  myprt << std::right << std::setw(5) << std::setprecision(1)
5895  << vx2.PosErr[1] / tcc.unitsPerTick;
5896  myprt << std::right << std::setw(7) << vx2.ChiDOF;
5897  myprt << std::right << std::setw(5) << vx2.NTraj;
5898  myprt << std::right << std::setw(5) << vx2.Pass;
5899  myprt << std::right << std::setw(6) << vx2.Topo;
5900  myprt << std::right << std::setw(9) << std::setprecision(2) << vx2.TjChgFrac;
5901  myprt << std::right << std::setw(6) << std::setprecision(1) << vx2.Score;
5902  myprt << std::right << std::setw(5) << vx2.Vx3ID;
5903  myprt << " ";
5904  // display the traj IDs
5905  for (unsigned short ii = 0; ii < slc.tjs.size(); ++ii) {
5906  auto const& aTj = slc.tjs[ii];
5907  if (debug.Plane < 3 && debug.Plane != (int)DecodeCTP(aTj.CTP).Plane) continue;
5908  if (aTj.AlgMod[kKilled]) continue;
5909  for (unsigned short end = 0; end < 2; ++end) {
5910  if (aTj.VtxID[end] != (short)vx2.ID) continue;
5911  std::string tid = " t" + std::to_string(aTj.ID) + "_" + std::to_string(end);
5912  myprt << std::right << std::setw(6) << tid;
5913  } // end
5914  } // ii
5915  // Special flags. Ignore the first flag bit (0 = kVxTrjTried) which is done for every vertex
5916  for (unsigned short ib = 1; ib < VtxBitNames.size(); ++ib)
5917  if (vx2.Stat[ib]) myprt << " " << VtxBitNames[ib];
5918  myprt << "\n";
5919  } // iv
5920  }
5921  } // slc.vtxs.size
5922  }
5923 
5924  if (slc.tjs.empty()) {
5925  mf::LogVerbatim("TC") << someText << " No allTraj trajectories to print";
5926  return;
5927  }
5928 
5929  // Print all trajectories in slc.tjs if itj == USHRT_MAX
5930  // Print a single traj (itj) and a single TP (ipt) or all TPs (USHRT_MAX)
5931  if (itj == USHRT_MAX) {
5932  // Print summary trajectory information
5933  myprt << "Tj AngleCode-EndFlag (EF) decoder: <AngleCode> + <reason for stopping>";
5934  myprt << " (B=Bragg Peak, V=Vertex, A=AngleKink, C=ChargeKink, T=Trajectory)\n";
5935  std::vector<unsigned int> tmp;
5936  myprt << someText
5937  << " UID CTP Pass Pts W:T Ang EF AveQ W:T Ang EF AveQ Chg(k) "
5938  "chgRMS Mom SDr __Vtx__ PDG Par Pri NuPar WorkID \n";
5939  for (unsigned short ii = 0; ii < slc.tjs.size(); ++ii) {
5940  auto& aTj = slc.tjs[ii];
5941  if (debug.CTP != UINT_MAX && aTj.CTP != debug.CTP) continue;
5942  myprt << someText << " ";
5943  std::string tid;
5944  if (aTj.AlgMod[kKilled]) { tid = "k" + std::to_string(aTj.UID); }
5945  else {
5946  tid = "t" + std::to_string(aTj.UID);
5947  }
5948  myprt << std::fixed << std::setw(5) << tid;
5949  myprt << std::setw(6) << aTj.CTP;
5950  myprt << std::setw(5) << aTj.Pass;
5951  myprt << std::setw(5) << aTj.EndPt[1] - aTj.EndPt[0] + 1;
5952  unsigned short endPt0 = aTj.EndPt[0];
5953  auto& tp0 = aTj.Pts[endPt0];
5954  int itick = tp0.Pos[1] / tcc.unitsPerTick;
5955  if (itick < 0) itick = 0;
5956  myprt << std::setw(6) << (int)(tp0.Pos[0] + 0.5) << ":" << itick; // W:T
5957  if (itick < 10) { myprt << " "; }
5958  if (itick < 100) { myprt << " "; }
5959  if (itick < 1000) { myprt << " "; }
5960  myprt << std::setw(6) << std::setprecision(2) << tp0.Ang;
5961  myprt << std::setw(2) << tp0.AngleCode;
5962  if (aTj.EndFlag[0][kBragg]) { myprt << "B"; }
5963  else if (aTj.EndFlag[0][kAtVtx]) {
5964  myprt << "V";
5965  }
5966  else if (aTj.EndFlag[0][kAtKink]) {
5967  myprt << "K";
5968  }
5969  else if (aTj.EndFlag[0][kAtTj]) {
5970  myprt << "T";
5971  }
5972  else {
5973  myprt << " ";
5974  }
5975  myprt << std::setw(5) << (int)tp0.AveChg;
5976  unsigned short endPt1 = aTj.EndPt[1];
5977  auto& tp1 = aTj.Pts[endPt1];
5978  itick = tp1.Pos[1] / tcc.unitsPerTick;
5979  myprt << std::setw(6) << (int)(tp1.Pos[0] + 0.5) << ":" << itick; // W:T
5980  if (itick < 10) { myprt << " "; }
5981  if (itick < 100) { myprt << " "; }
5982  if (itick < 1000) { myprt << " "; }
5983  myprt << std::setw(6) << std::setprecision(2) << tp1.Ang;
5984  myprt << std::setw(2) << tp1.AngleCode;
5985  if (aTj.EndFlag[1][kBragg]) { myprt << "B"; }
5986  else if (aTj.EndFlag[1][kAtVtx]) {
5987  myprt << "V";
5988  }
5989  else {
5990  myprt << " ";
5991  }
5992  myprt << std::setw(5) << (int)tp1.AveChg;
5993  myprt << std::setw(7) << std::setprecision(1) << aTj.TotChg / 1000;
5994  myprt << std::setw(7) << std::setprecision(2) << aTj.ChgRMS;
5995  myprt << std::setw(5) << aTj.MCSMom;
5996  myprt << std::setw(4) << aTj.StepDir;
5997  myprt << std::setw(4) << aTj.VtxID[0];
5998  myprt << std::setw(4) << aTj.VtxID[1];
5999  myprt << std::setw(5) << aTj.PDGCode;
6000  myprt << std::setw(5) << aTj.ParentID;
6001  myprt << std::setw(5) << PrimaryID(slc, aTj);
6002  myprt << std::setw(6) << NeutrinoPrimaryTjID(slc, aTj);
6003  myprt << std::setw(7) << aTj.WorkID;
6004  for (unsigned short ib = 0; ib < AlgBitNames.size(); ++ib)
6005  if (aTj.AlgMod[ib]) myprt << " " << AlgBitNames[ib];
6006  myprt << "\n";
6007  } // ii
6008  return;
6009  } // itj > slc.tjs.size()-1
6010 
6011  if (itj > slc.tjs.size() - 1) return;
6012 
6013  auto const& aTj = slc.tjs[itj];
6014 
6015  mf::LogVerbatim("TC") << "Print slc.tjs[" << itj << "] Vtx[0] " << aTj.VtxID[0] << " Vtx[1] "
6016  << aTj.VtxID[1];
6017  myprt << "AlgBits";
6018  for (unsigned short ib = 0; ib < AlgBitNames.size(); ++ib)
6019  if (aTj.AlgMod[ib]) myprt << " " << AlgBitNames[ib];
6020  myprt << "\n";
6021 
6022  PrintTPHeader(someText);
6023  if (ipt == USHRT_MAX) {
6024  // print all points
6025  for (unsigned short ii = 0; ii < aTj.Pts.size(); ++ii)
6026  PrintTP(someText, slc, ii, aTj.StepDir, aTj.Pass, aTj.Pts[ii]);
6027  }
6028  else {
6029  // print just one
6030  PrintTP(someText, slc, ipt, aTj.StepDir, aTj.Pass, aTj.Pts[ipt]);
6031  }
6032  } // 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:102
const std::vector< std::string > AlgBitNames
Definition: DataStructs.cxx:16
tagged as a vertex between Tjs that are matched to MC truth neutrino interaction particles ...
Definition: DataStructs.h:91
TCConfig tcc
Definition: DataStructs.cxx:9
void PrintTP(std::string someText, const TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, const TrajPoint &tp)
Definition: Utils.cxx:6134
Float_t tmp
Definition: plot.C:35
std::string PrintPos(const Point2_t &pos)
Definition: Utils.cxx:6362
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
int NeutrinoPrimaryTjID(const TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:446
int PrimaryID(const TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:468
std::array< float, 2 > Point2_t
Definition: DataStructs.h:41
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
DebugStuff debug
Definition: DebugStruct.cxx:4
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
int Plane
Select plane.
Definition: DebugStruct.h:22
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
std::vector< int > GetAssns(TCSlice const &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4704
const std::vector< std::string > VtxBitNames
Definition: DataStructs.cxx:89
geo::PlaneID DecodeCTP(CTP_t CTP)
void PrintTPHeader(std::string someText)
Definition: Utils.cxx:6126
CTP_t CTP
set to an invalid CTP
Definition: DebugStruct.h:23
void PosInPlane(detinfo::DetectorPropertiesData const &detProp, const Vtx3Store &vx3, unsigned short plane, Point2_t &pos)
Definition: TCVertex.cxx:2847
void tca::PrintDebugMode ( )

Definition at line 5300 of file Utils.cxx.

References AlgBitNames, tca::DebugStuff::Cryostat, tca::DebugStuff::CTP, tca::TCConfig::dbg2S, tca::TCConfig::dbg2V, tca::TCConfig::dbg3V, tca::TCConfig::dbgDeltaRayTag, tca::TCConfig::dbgDump, tca::TCConfig::dbgMrg, tca::TCConfig::dbgMuonTag, tca::TCConfig::dbgPFP, tca::TCConfig::dbgSlc, tca::TCConfig::dbgStitch, tca::TCConfig::dbgStp, tca::TCConfig::dbgSummary, tca::TCConfig::dbgVxJunk, tca::TCConfig::dbgVxMerge, tca::TCConfig::dbgVxNeutral, debug, tca::DebugStuff::Hit, kKilled, tca::DebugStuff::Plane, tca::DebugStuff::Slice, tcc, tca::DebugStuff::Tick, tca::DebugStuff::TPC, tca::TCConfig::useAlg, tca::DebugStuff::Wire, and tca::DebugStuff::WorkID.

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

5301  {
5302  // print the debug mode configuration to the screen
5303  std::cout << "*** TrajCluster debug mode configuration in";
5304  std::cout << " CTP=";
5305  if (debug.CTP == UINT_MAX) { std::cout << "NA"; }
5306  else {
5307  std::cout << debug.CTP;
5308  }
5309  std::cout << " Cryostat=" << debug.Cryostat;
5310  std::cout << " TPC=" << debug.TPC;
5311  std::cout << " Plane=" << debug.Plane;
5312  std::cout << " Wire=" << debug.Wire;
5313  std::cout << " Tick=" << debug.Tick;
5314  std::cout << " Hit=";
5315  if (debug.Hit == UINT_MAX) { std::cout << "NA"; }
5316  else {
5317  std::cout << debug.Hit;
5318  }
5319  std::cout << " WorkID=";
5320  if (debug.WorkID == 0) { std::cout << "NA"; }
5321  else {
5322  std::cout << debug.WorkID;
5323  }
5324  std::cout << " Slice=";
5325  if (debug.Slice == -1) { std::cout << "All"; }
5326  else {
5327  std::cout << debug.Slice;
5328  }
5329  std::cout << "\n";
5330  std::cout << "*** tcc.dbg modes:";
5331  if (tcc.dbgSlc) std::cout << " dbgSlc";
5332  if (tcc.dbgStp) std::cout << " dbgStp";
5333  if (tcc.dbgMrg) std::cout << " dbgMrg";
5334  if (tcc.dbg2V) std::cout << " dbg2V";
5335  if (tcc.dbg2S) std::cout << " dbg2S";
5336  if (tcc.dbgVxNeutral) std::cout << " dbgVxNeutral";
5337  if (tcc.dbgVxMerge) std::cout << " dbgVxMerge";
5338  if (tcc.dbgVxJunk) std::cout << " dbgVxJunk";
5339  if (tcc.dbg3V) std::cout << " dbg3V";
5340  if (tcc.dbgPFP) std::cout << " dbgPFP";
5341  if (tcc.dbgDeltaRayTag) std::cout << " dbgDeltaRayTag";
5342  if (tcc.dbgMuonTag) std::cout << " dbgMuonTag";
5343  if (tcc.dbgStitch) std::cout << " dbgStitch";
5344  if (tcc.dbgSummary) std::cout << " dbgSummary";
5345  if (tcc.dbgDump) std::cout << " dbgDump";
5346  std::cout << "\n";
5347  std::cout << "*** Using algs:";
5348  unsigned short cnt = 0;
5349  for (unsigned short ib = 0; ib < AlgBitNames.size(); ++ib) {
5350  if (tcc.useAlg[ib] && ib != kKilled) {
5351  ++cnt;
5352  if (cnt % 10 == 0) std::cout << "\n ";
5353  std::cout << " " << AlgBitNames[ib];
5354  }
5355  }
5356  std::cout << "\n";
5357  std::cout << "*** Skipping algs:";
5358  cnt = 0;
5359  for (unsigned short ib = 0; ib < AlgBitNames.size(); ++ib) {
5360  if (!tcc.useAlg[ib] && ib != kKilled) {
5361  ++cnt;
5362  if (cnt % 10 == 0) std::cout << "\n ";
5363  std::cout << " " << AlgBitNames[ib];
5364  }
5365  }
5366  std::cout << "\n";
5367  } // PrintDebugMode
bool dbgStitch
debug PFParticle stitching
Definition: DataStructs.h:595
const std::vector< std::string > AlgBitNames
Definition: DataStructs.cxx:16
TCConfig tcc
Definition: DataStructs.cxx:9
bool dbgDeltaRayTag
Definition: DataStructs.h:591
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
bool dbg3V
debug 3D vertex finding
Definition: DataStructs.h:589
unsigned int Hit
set to the hit index in evt.allHits if a Plane:Wire:Tick match is found
Definition: DebugStruct.h:26
int Cryostat
Select Cryostat.
Definition: DebugStruct.h:20
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
int Wire
Select hit Wire for debugging.
Definition: DebugStruct.h:24
int WorkID
Select the StartWorkID for debugging.
Definition: DebugStruct.h:28
DebugStuff debug
Definition: DebugStruct.cxx:4
bool dbg2V
debug 2D vertex finding
Definition: DataStructs.h:585
int Plane
Select plane.
Definition: DebugStruct.h:22
int Tick
Select hit PeakTime for debugging (< 0 for vertex finding)
Definition: DebugStruct.h:25
int TPC
Select TPC.
Definition: DebugStruct.h:21
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
bool dbgSummary
print a summary report
Definition: DataStructs.h:596
CTP_t CTP
set to an invalid CTP
Definition: DebugStruct.h:23
std::string tca::PrintEndFlag ( const PFPStruct pfp,
unsigned short  end 
)

Definition at line 6297 of file Utils.cxx.

References tca::PFPStruct::EndFlag, EndFlagNames, tmp, and util::to_string().

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

6298  {
6299  if (end > 1) return "Invalid end";
6300  std::string tmp;
6301  bool first = true;
6302  for (unsigned short ib = 0; ib < EndFlagNames.size(); ++ib) {
6303  if (pfp.EndFlag[end][ib]) {
6304  if (first) {
6305  tmp = std::to_string(end) + ":" + EndFlagNames[ib];
6306  first = false;
6307  }
6308  else {
6309  tmp += "," + EndFlagNames[ib];
6310  }
6311  }
6312  } // ib
6313  if (first) tmp = " none";
6314  return tmp;
6315  } // PrintEndFlag
Float_t tmp
Definition: plot.C:35
const std::vector< std::string > EndFlagNames
Definition: DataStructs.cxx:87
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
std::string tca::PrintEndFlag ( const Trajectory tj,
unsigned short  end 
)

Definition at line 6318 of file Utils.cxx.

References tca::Trajectory::EndFlag, EndFlagNames, tmp, and util::to_string().

6319  {
6320  if (end > 1) return "Invalid end";
6321  std::string tmp;
6322  bool first = true;
6323  for (unsigned short ib = 0; ib < EndFlagNames.size(); ++ib) {
6324  if (tj.EndFlag[end][ib]) {
6325  if (first) {
6326  tmp = std::to_string(end) + ":" + EndFlagNames[ib];
6327  first = false;
6328  }
6329  else {
6330  tmp += "," + EndFlagNames[ib];
6331  }
6332  }
6333  } // ib
6334  return tmp;
6335  } // PrintEndFlag
Float_t tmp
Definition: plot.C:35
const std::vector< std::string > EndFlagNames
Definition: DataStructs.cxx:87
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
std::string tca::PrintHit ( const TCHit tch)

Definition at line 6347 of file Utils.cxx.

References tca::TCEvent::allHits, tca::TCHit::allHitsIndex, evt, tca::TCHit::InTraj, and util::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(), HasDuplicateHits(), InTrajOK(), cluster::ClusterCrawlerAlg::MergeOverlap(), tca::TrajClusterAlg::ReconstructAllTraj(), ReversePropagate(), and StoreTraj().

6348  {
6349  if (tch.allHitsIndex > (*evt.allHits).size() - 1) return "NA";
6350  auto& hit = (*evt.allHits)[tch.allHitsIndex];
6351  return std::to_string(hit.WireID().Plane) + ":" + std::to_string(hit.WireID().Wire) + ":" +
6352  std::to_string((int)hit.PeakTime()) + "_" + std::to_string(tch.InTraj);
6353  } // PrintHit
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
std::string tca::PrintHitShort ( const TCHit tch)

Definition at line 6338 of file Utils.cxx.

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

Referenced by DotProd().

6339  {
6340  if (tch.allHitsIndex > (*evt.allHits).size() - 1) return "NA";
6341  auto& hit = (*evt.allHits)[tch.allHitsIndex];
6342  return std::to_string(hit.WireID().Plane) + ":" + std::to_string(hit.WireID().Wire) + ":" +
6343  std::to_string((int)hit.PeakTime());
6344  } // PrintHit
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
void tca::PrintP ( mf::LogVerbatim myprt,
PFPStruct const &  pfp,
bool &  printHeader 
)

Definition at line 5453 of file Utils.cxx.

References tca::PFPStruct::dEdx, dir, DirAtEnd(), tca::PFPStruct::DtrUIDs, util::end(), GetSliceIndex(), tca::PFPStruct::ID, InsideFV(), IsShowerLike(), Length(), MCSMom(), tca::PFPStruct::MVI, tca::PFPStruct::ParentUID, tca::PFPStruct::PDGCode, PosAtEnd(), art::right(), tca::PFPStruct::SectionFits, slices, tca::PFPStruct::TjIDs, tca::PFPStruct::TjUIDs, util::to_string(), tca::PFPStruct::TP3Ds, tca::PFPStruct::UID, and tca::PFPStruct::Vx3ID.

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

5454  {
5455  if (pfp.ID <= 0) return;
5456  if (printHeader) {
5457  myprt << "************ PFParticles ************\n";
5458  myprt << " prodID sVx _____sPos____ CS _______sDir______ ____sdEdx_____ eVx "
5459  "_____ePos____ CS ____edEdx_____ MVI MCSMom Len nTP3 nSec SLk? PDG Par \n";
5460  printHeader = false;
5461  } // printHeader
5462  auto sIndx = GetSliceIndex("P", pfp.UID);
5463  if (sIndx.first == USHRT_MAX) return;
5464  auto const& slc = slices[sIndx.first];
5465  std::string str =
5466  std::to_string(slc.ID) + ":" + std::to_string(sIndx.first) + ":" + std::to_string(pfp.ID);
5467  str += "/" + std::to_string(pfp.UID);
5468  myprt << std::setw(12) << str;
5469  // start and end stuff
5470  for (unsigned short end = 0; end < 2; ++end) {
5471  str = "--";
5472  if (pfp.Vx3ID[end] > 0) str = "3V" + std::to_string(slc.vtx3s[pfp.Vx3ID[end] - 1].UID);
5473  myprt << std::setw(6) << str;
5474  myprt << std::fixed << std::right << std::setprecision(0);
5475  auto pos = PosAtEnd(pfp, end);
5476  myprt << std::setw(5) << pos[0];
5477  myprt << std::setw(5) << pos[1];
5478  myprt << std::setw(5) << pos[2];
5479  // print character for Outside or Inside the FV
5480  if (InsideFV(slc, pfp, end)) { myprt << " I"; }
5481  else {
5482  myprt << " O";
5483  }
5484  // only print the starting direction
5485  if (end == 0) {
5486  myprt << std::fixed << std::right << std::setprecision(2);
5487  auto dir = DirAtEnd(pfp, end);
5488  myprt << std::setw(6) << dir[0];
5489  myprt << std::setw(6) << dir[1];
5490  myprt << std::setw(6) << dir[2];
5491  } // end == 0
5492  for (auto& dedx : pfp.dEdx[end]) {
5493  if (dedx < 50) { myprt << std::setw(5) << std::setprecision(1) << dedx; }
5494  else {
5495  myprt << std::setw(5) << std::setprecision(0) << dedx;
5496  }
5497  } // dedx
5498  if (pfp.dEdx[end].size() < 3) {
5499  for (size_t i = 0; i < 3 - pfp.dEdx[end].size(); ++i) {
5500  myprt << std::setw(6) << ' ';
5501  }
5502  }
5503  } // startend
5504  myprt << std::setw(6) << pfp.MVI;
5505  // global stuff
5506  myprt << std::setw(7) << MCSMom(slc, pfp.TjIDs);
5507  float length = Length(pfp);
5508  if (length < 100) { myprt << std::setw(5) << std::setprecision(1) << length; }
5509  else {
5510  myprt << std::setw(5) << std::setprecision(0) << length;
5511  }
5512  myprt << std::setw(5) << pfp.TP3Ds.size();
5513  myprt << std::setw(5) << pfp.SectionFits.size();
5514  myprt << std::setw(5) << IsShowerLike(slc, pfp.TjIDs);
5515  myprt << std::setw(5) << pfp.PDGCode;
5516  myprt << std::setw(4) << pfp.ParentUID;
5517  if (!pfp.TjIDs.empty()) {
5518  if (pfp.TjUIDs.empty()) {
5519  // print Tjs in one TPC
5520  for (auto tjid : pfp.TjIDs)
5521  myprt << " TU" << slc.tjs[tjid - 1].UID;
5522  }
5523  else {
5524  // print Tjs in all TPCs (if this is called after FinishEvent)
5525  for (auto tjuid : pfp.TjUIDs)
5526  myprt << " TU" << tjuid;
5527  }
5528  } // TjIDs exist
5529  if (!pfp.DtrUIDs.empty()) {
5530  myprt << " dtrs";
5531  for (auto dtruid : pfp.DtrUIDs)
5532  myprt << " PU" << dtruid;
5533  } // dtr ids exist
5534  myprt << "\n";
5535  } // PrintP
float Length(const PFPStruct &pfp)
Definition: PFPUtils.cxx:3267
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:102
bool InsideFV(const TCSlice &slc, const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3019
bool IsShowerLike(TCSlice const &slc, std::vector< int > const &TjIDs)
Definition: TCShower.cxx:1891
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3257
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
TDirectory * dir
Definition: macro.C:5
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:4942
short MCSMom(const TCSlice &slc, const Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:3403
Vector3_t DirAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3249
void tca::PrintPFP ( std::string  someText,
TCSlice const &  slc,
const PFPStruct pfp,
bool  printHeader 
)

Definition at line 6209 of file Utils.cxx.

References tca::PFPStruct::dEdx, dir, DirAtEnd(), tca::PFPStruct::DtrUIDs, util::end(), tca::PFPStruct::EndFlag, tca::PFPStruct::ID, IsShowerLike(), kBragg, kOutFV, Length(), MCSMom(), tca::PFPStruct::ParentUID, tca::PFPStruct::PDGCode, PosAtEnd(), PrimaryUID(), art::right(), tca::PFPStruct::TjIDs, util::to_string(), tca::PFPStruct::TP3Ds, and tca::PFPStruct::Vx3ID.

Referenced by DotProd(), and PrintPFPs().

6210  {
6211  mf::LogVerbatim myprt("TC");
6212  if (printHeader) {
6213  myprt << someText;
6214  myprt << " PFP sVx ________sPos_______ EF _______sDir______ ____sdEdx_____ eVx "
6215  "________ePos_______ EF _______eDir______ ____edEdx____ Len nTp3 MCSMom ShLike? "
6216  "PDG Par Prim\n";
6217  }
6218  myprt << someText;
6219  std::string pid = "P" + std::to_string(pfp.ID);
6220  myprt << std::setw(5) << pid;
6221  // start and end stuff
6222  for (unsigned short end = 0; end < 2; ++end) {
6223  myprt << std::setw(4) << pfp.Vx3ID[end];
6224  myprt << std::fixed << std::right << std::setprecision(1);
6225  auto pos = PosAtEnd(pfp, end);
6226  myprt << std::setw(7) << pos[0];
6227  myprt << std::setw(7) << pos[1];
6228  myprt << std::setw(7) << pos[2];
6229  // print characters that encode the EndFlag
6230  std::string ef;
6231  if (pfp.EndFlag[end][kOutFV]) { ef = "O"; }
6232  else {
6233  ef = "I";
6234  }
6235  if (pfp.EndFlag[end][kBragg]) ef += "B";
6236  myprt << std::setw(6) << ef;
6237  myprt << std::fixed << std::right << std::setprecision(2);
6238  auto dir = DirAtEnd(pfp, end);
6239  myprt << std::setw(6) << dir[0];
6240  myprt << std::setw(6) << dir[1];
6241  myprt << std::setw(6) << dir[2];
6242  for (auto& dedx : pfp.dEdx[end]) {
6243  if (dedx < 50) { myprt << std::setw(5) << std::setprecision(1) << dedx; }
6244  else {
6245  myprt << std::setw(5) << std::setprecision(0) << dedx;
6246  }
6247  } // dedx
6248  if (pfp.dEdx[end].size() < 3) {
6249  for (size_t i = 0; i < 3 - pfp.dEdx[end].size(); ++i) {
6250  myprt << std::setw(6) << ' ';
6251  }
6252  }
6253  } // startend
6254  // global stuff
6255  float length = Length(pfp);
6256  if (length < 100) { myprt << std::setw(5) << std::setprecision(1) << length; }
6257  else {
6258  myprt << std::setw(5) << std::setprecision(0) << length;
6259  }
6260  myprt << std::setw(5) << std::setprecision(2) << pfp.TP3Ds.size();
6261  myprt << std::setw(7) << MCSMom(slc, pfp.TjIDs);
6262  myprt << std::setw(5) << IsShowerLike(slc, pfp.TjIDs);
6263  myprt << std::setw(5) << pfp.PDGCode;
6264  myprt << " NA";
6265  myprt << std::setw(4) << pfp.ParentUID;
6266  myprt << std::setw(5) << PrimaryUID(pfp);
6267  if (!pfp.TjIDs.empty()) {
6268  for (auto& tjID : pfp.TjIDs)
6269  myprt << " T" << tjID;
6270  }
6271  if (!pfp.DtrUIDs.empty()) {
6272  myprt << " dtrs";
6273  for (auto& dtrUID : pfp.DtrUIDs)
6274  myprt << " P" << dtrUID;
6275  }
6276  } // PrintPFP
float Length(const PFPStruct &pfp)
Definition: PFPUtils.cxx:3267
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:102
bool IsShowerLike(TCSlice const &slc, std::vector< int > const &TjIDs)
Definition: TCShower.cxx:1891
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3257
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
int PrimaryUID(const PFPStruct &pfp)
Definition: Utils.cxx:487
TDirectory * dir
Definition: macro.C:5
short MCSMom(const TCSlice &slc, const Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:3403
Vector3_t DirAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3249
void tca::PrintPFPs ( std::string  someText,
TCSlice const &  slc 
)

Definition at line 6279 of file Utils.cxx.

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

Referenced by DotProd(), and FindShowers3D().

6280  {
6281  if (slc.pfps.empty()) return;
6282 
6283  mf::LogVerbatim myprt("TC");
6284  myprt << someText;
6285  myprt
6286  << " PFP sVx ________sPos_______ ______sDir______ ______sdEdx_____ eVx "
6287  "________ePos_______ ______eDir______ ______edEdx_____ BstPln PDG TruPDG Par Prim E*P\n";
6288  bool printHeader = true;
6289  for (auto& pfp : slc.pfps) {
6290  PrintPFP(someText, slc, pfp, printHeader);
6291  printHeader = false;
6292  } // im
6293 
6294  } // PrintPFPs
void PrintPFP(std::string someText, TCSlice const &slc, const PFPStruct &pfp, bool printHeader)
Definition: Utils.cxx:6209
std::string tca::PrintPos ( const Point2_t pos)

Definition at line 6362 of file Utils.cxx.

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

6363  {
6364  unsigned int wire = 0;
6365  if (pos[0] > -0.4) wire = std::nearbyint(pos[0]);
6366  int time = std::nearbyint(pos[1] / tcc.unitsPerTick);
6367  return std::to_string(wire) + ":" + std::to_string(time);
6368  } // PrintPos
TCConfig tcc
Definition: DataStructs.cxx:9
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
void tca::PrintShower ( std::string  someText,
TCSlice const &  slc,
const ShowerStruct ss,
bool  printHeader,
bool  printExtras 
)

Definition at line 4283 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::to_string(), tca::ShowerStruct::TruParentID, and tca::TCConfig::unitsPerTick.

Referenced by Print2DShowers().

4288  {
4289  // print a single shower and a header (optional) and the extra variables like TjIDs, envelope, etc
4290  mf::LogVerbatim myprt("TC");
4291 
4292  if (printHeader) {
4293  myprt << someText
4294  << " ID CTP ParID ParFOM TruParID Energy nTjs dFOM AspRat stj vx0 __Pos0___ "
4295  "Chg(k) dRMS __Pos1___ Chg(k) dRMS __Pos2___ Chg(k) dRMS Angle SS3ID PFPID\n";
4296  } // printHeader
4297 
4298  myprt << someText << std::fixed;
4299  std::string sid = "2S" + std::to_string(ss.ID);
4300  myprt << std::setw(5) << sid;
4301  myprt << std::setw(6) << ss.CTP;
4302  sid = "NA";
4303  if (ss.ParentID > 0) sid = "T" + std::to_string(ss.ParentID);
4304  myprt << std::setw(7) << sid;
4305  myprt << std::setw(7) << std::setprecision(2) << ss.ParentFOM;
4306  myprt << std::setw(9) << ss.TruParentID;
4307  myprt << std::setw(7) << (int)ss.Energy;
4308  myprt << std::setw(5) << ss.TjIDs.size();
4309  myprt << std::setw(6) << std::setprecision(2) << ss.DirectionFOM;
4310  myprt << std::setw(7) << std::setprecision(2) << ss.AspectRatio;
4311  const auto& stj = slc.tjs[ss.ShowerTjID - 1];
4312  std::string tid = "T" + std::to_string(stj.ID);
4313  myprt << std::setw(5) << tid;
4314  std::string vid = "NA";
4315  if (stj.VtxID[0] > 0) vid = "2V" + std::to_string(stj.VtxID[0]);
4316  myprt << std::setw(5) << vid;
4317  for (auto& spt : stj.Pts) {
4318  myprt << std::setw(10) << PrintPos(spt.Pos);
4319  myprt << std::setw(7) << std::fixed << std::setprecision(1) << spt.Chg / 1000;
4320  // myprt<<std::setw(5)<<spt.NTPsFit;
4321  myprt << std::setw(5) << std::setprecision(1) << spt.DeltaRMS;
4322  } // spt
4323  myprt << std::setw(6) << std::setprecision(2) << stj.Pts[1].Ang;
4324  std::string sss = "NA";
4325  if (ss.SS3ID > 0) sss = "3S" + std::to_string(ss.SS3ID);
4326  myprt << std::setw(6) << sss;
4327  if (ss.SS3ID > 0 && ss.SS3ID < (int)slc.showers.size()) {
4328  auto& ss3 = slc.showers[ss.SS3ID - 1];
4329  if (ss3.PFPIndex < slc.pfps.size()) {
4330  std::string pid = "P" + std::to_string(ss3.PFPIndex + 1);
4331  myprt << std::setw(6) << pid;
4332  }
4333  else {
4334  myprt << std::setw(6) << "NA";
4335  }
4336  }
4337  else {
4338  myprt << std::setw(6) << "NA";
4339  }
4340  if (ss.NeedsUpdate) myprt << " *** Needs update";
4341 
4342  if (!printExtras) return;
4343  myprt << "\n";
4344 
4345  myprt << someText << std::fixed;
4346  sid = "2S" + std::to_string(ss.ID);
4347  myprt << std::setw(5) << sid;
4348  myprt << " Tjs";
4349  for (auto id : ss.TjIDs)
4350  myprt << " T" << id;
4351  myprt << "\n";
4352  myprt << someText << std::fixed;
4353  sid = "2S" + std::to_string(ss.ID);
4354  myprt << std::setw(5) << sid;
4355  myprt << " Envelope";
4356  for (auto& vtx : ss.Envelope)
4357  myprt << " " << (int)vtx[0] << ":" << (int)(vtx[1] / tcc.unitsPerTick);
4358  myprt << "\n";
4359  myprt << someText << std::fixed;
4360  sid = "2S" + std::to_string(ss.ID);
4361  myprt << std::setw(5) << sid;
4362  myprt << " Nearby";
4363  for (auto id : ss.NearTjIDs)
4364  myprt << " T" << id;
4365 
4366  } // PrintShower
TCConfig tcc
Definition: DataStructs.cxx:9
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
void tca::PrintShowers ( detinfo::DetectorPropertiesData const &  detProp,
std::string  fcnLabel,
TCSlice const &  slc 
)

Definition at line 4150 of file TCShower.cxx.

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

4153  {
4154  if (slc.showers.empty()) return;
4155  mf::LogVerbatim myprt("TC");
4156  myprt << fcnLabel << " 3D showers \n";
4157  for (auto& ss3 : slc.showers) {
4158  myprt << fcnLabel << " 3S" << ss3.ID << " 3V" << ss3.Vx3ID;
4159  myprt << " parentID " << ss3.ParentID;
4160  myprt << " ChgPos" << std::fixed;
4161  for (unsigned short xyz = 0; xyz < 3; ++xyz)
4162  myprt << " " << std::setprecision(0) << ss3.ChgPos[xyz];
4163  myprt << " Dir";
4164  for (unsigned short xyz = 0; xyz < 3; ++xyz)
4165  myprt << " " << std::setprecision(2) << ss3.Dir[xyz];
4166  myprt << " posInPlane";
4167  std::vector<float> projInPlane(slc.nPlanes);
4168  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
4169  CTP_t inCTP = EncodeCTP(ss3.TPCID.Cryostat, ss3.TPCID.TPC, plane);
4170  auto tp = MakeBareTP(detProp, ss3.ChgPos, ss3.Dir, inCTP);
4171  myprt << " " << PrintPos(tp.Pos);
4172  projInPlane[plane] = tp.Delta;
4173  } // plane
4174  myprt << " projInPlane";
4175  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
4176  myprt << " " << std::fixed << std::setprecision(2) << projInPlane[plane];
4177  } // plane
4178  for (auto cid : ss3.CotIDs) {
4179  auto& ss = slc.cots[cid - 1];
4180  myprt << "\n 2S" << ss.ID;
4181  auto& stj = slc.tjs[ss.ShowerTjID - 1];
4182  myprt << " ST" << stj.ID;
4183  myprt << " " << PrintPos(stj.Pts[stj.EndPt[0]].Pos) << " - "
4184  << PrintPos(stj.Pts[stj.EndPt[1]].Pos);
4185  } // ci
4186  if (ss3.NeedsUpdate) myprt << " *** Needs update";
4187  myprt << "\n";
4188  } // sss3
4189  } // PrintShowers
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const Point3_t &pos, CTP_t inCTP)
Definition: Utils.cxx:3928
unsigned int CTP_t
Definition: DataStructs.h:45
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:49
void tca::PrintT ( mf::LogVerbatim myprt,
Trajectory const &  tj,
bool &  printHeader 
)

Definition at line 5702 of file Utils.cxx.

References AlgBitNames, tca::Trajectory::AlgMod, tca::Trajectory::ChgRMS, tca::DebugStuff::CTP, tca::Trajectory::CTP, debug, ElectronLikelihood(), tca::Trajectory::EndFlag, tca::Trajectory::EndPt, GetSliceIndex(), tca::Trajectory::ID, kAtKink, kAtTj, kAtVtx, kBragg, tca::Trajectory::MCSMom, NeutrinoPrimaryTjID(), tca::Trajectory::ParentID, tca::Trajectory::Pass, tca::Trajectory::PDGCode, PrimaryID(), tca::Trajectory::Pts, slices, tca::Trajectory::Strategy, StrategyBitNames, tcc, util::to_string(), tca::Trajectory::TotChg, tca::Trajectory::UID, tca::TCConfig::unitsPerTick, tca::Trajectory::VtxID, and tca::Trajectory::WorkID.

Referenced by DotProd(), and PrintAll().

5703  {
5704  // print a 2D vertex on one line
5705  if (tj.ID <= 0) return;
5706  if (debug.CTP != UINT_MAX && tj.CTP != debug.CTP) return;
5707  if (printHeader) {
5708  myprt << "************ Trajectories ************\n";
5709  myprt << "Tj AngleCode-EndFlag decoder (EF): <AngleCode> + <reason for stopping>";
5710  myprt << " (B=Bragg Peak, V=Vertex, A=AngleKink, C=ChargeKink, T=Trajectory)\n";
5711  myprt << " prodID CTP Pass Pts W:T Ang EF AveQ W:T Ang EF AveQ "
5712  "Chg(k) chgRMS Mom __Vtx__ PDG eLike Par Pri NuPar WorkID \n";
5713  printHeader = false;
5714  }
5715  auto sIndx = GetSliceIndex("T", tj.UID);
5716  if (sIndx.first == USHRT_MAX) return;
5717  auto const& slc = slices[sIndx.first];
5718  std::string str = "T" + std::to_string(tj.ID) + "/TU" + std::to_string(tj.UID);
5719  myprt << std::fixed << std::setw(12) << str;
5720  myprt << std::setw(6) << tj.CTP;
5721  myprt << std::setw(5) << tj.Pass;
5722  myprt << std::setw(5) << tj.EndPt[1] - tj.EndPt[0] + 1;
5723  unsigned short endPt0 = tj.EndPt[0];
5724  auto& tp0 = tj.Pts[endPt0];
5725  int itick = tp0.Pos[1] / tcc.unitsPerTick;
5726  if (itick < 0) itick = 0;
5727  myprt << std::setw(6) << (int)(tp0.Pos[0] + 0.5) << ":" << itick; // W:T
5728  if (itick < 10) { myprt << " "; }
5729  if (itick < 100) { myprt << " "; }
5730  if (itick < 1000) { myprt << " "; }
5731  myprt << std::setw(6) << std::setprecision(2) << tp0.Ang;
5732  myprt << std::setw(2) << tp0.AngleCode;
5733  if (tj.EndFlag[0][kBragg]) { myprt << "B"; }
5734  else if (tj.EndFlag[0][kAtVtx]) {
5735  myprt << "V";
5736  }
5737  else if (tj.EndFlag[0][kAtKink]) {
5738  myprt << "K";
5739  }
5740  else if (tj.EndFlag[0][kAtTj]) {
5741  myprt << "T";
5742  }
5743  else {
5744  myprt << " ";
5745  }
5746  myprt << std::setw(5) << (int)tp0.AveChg;
5747  unsigned short endPt1 = tj.EndPt[1];
5748  auto& tp1 = tj.Pts[endPt1];
5749  itick = tp1.Pos[1] / tcc.unitsPerTick;
5750  myprt << std::setw(6) << (int)(tp1.Pos[0] + 0.5) << ":" << itick; // W:T
5751  if (itick < 10) { myprt << " "; }
5752  if (itick < 100) { myprt << " "; }
5753  if (itick < 1000) { myprt << " "; }
5754  myprt << std::setw(6) << std::setprecision(2) << tp1.Ang;
5755  myprt << std::setw(2) << tp1.AngleCode;
5756  if (tj.EndFlag[1][kBragg]) { myprt << "B"; }
5757  else if (tj.EndFlag[1][kAtVtx]) {
5758  myprt << "V";
5759  }
5760  else if (tj.EndFlag[1][kAtKink]) {
5761  myprt << "K";
5762  }
5763  else if (tj.EndFlag[1][kAtTj]) {
5764  myprt << "T";
5765  }
5766  else {
5767  myprt << " ";
5768  }
5769  myprt << std::setw(5) << (int)tp1.AveChg;
5770  myprt << std::setw(7) << std::setprecision(1) << tj.TotChg / 1000;
5771  myprt << std::setw(7) << std::setprecision(2) << tj.ChgRMS;
5772  myprt << std::setw(5) << tj.MCSMom;
5773  int vxid = 0;
5774  if (tj.VtxID[0] > 0) vxid = slc.vtxs[tj.VtxID[0] - 1].UID;
5775  myprt << std::setw(4) << vxid;
5776  vxid = 0;
5777  if (tj.VtxID[1] > 0) vxid = slc.vtxs[tj.VtxID[1] - 1].UID;
5778  myprt << std::setw(4) << vxid;
5779  myprt << std::setw(5) << tj.PDGCode;
5780  myprt << std::setw(7) << std::setprecision(2) << ElectronLikelihood(slc, tj);
5781  myprt << std::setw(5) << tj.ParentID;
5782  myprt << std::setw(5) << PrimaryID(slc, tj);
5783  myprt << std::setw(6) << NeutrinoPrimaryTjID(slc, tj);
5784  myprt << std::setw(7) << tj.WorkID;
5785  for (unsigned short ib = 0; ib < AlgBitNames.size(); ++ib)
5786  if (tj.AlgMod[ib]) myprt << " " << AlgBitNames[ib];
5787  for (unsigned short ib = 0; ib < StrategyBitNames.size(); ++ib)
5788  if (tj.Strategy[ib]) myprt << " " << StrategyBitNames[ib];
5789  myprt << "\n";
5790  } // PrintT
const std::vector< std::string > AlgBitNames
Definition: DataStructs.cxx:16
TCConfig tcc
Definition: DataStructs.cxx:9
const std::vector< std::string > StrategyBitNames
Definition: DataStructs.cxx:98
int NeutrinoPrimaryTjID(const TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:446
int PrimaryID(const TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:468
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
DebugStuff debug
Definition: DebugStruct.cxx:4
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
float ElectronLikelihood(const TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:3144
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:4942
CTP_t CTP
set to an invalid CTP
Definition: DebugStruct.h:23
void tca::PrintTP ( std::string  someText,
const TCSlice slc,
unsigned short  ipt,
short  dir,
unsigned short  pass,
const TrajPoint tp 
)

Definition at line 6134 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, tca::TrajPoint::Environment, evt, tca::TrajPoint::FitChi, tca::TrajPoint::Hits, tca::TrajPoint::InPFP, tca::TrajPoint::KinkSig, tca::TrajPoint::NTPsFit, tca::TCSlice::slHits, tca::TrajPoint::Step, TPEnvString(), and tca::TrajPoint::UseHit.

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

6140  {
6141  mf::LogVerbatim myprt("TC");
6142  myprt << someText << " TRP" << std::fixed;
6143  myprt << pass;
6144  if (dir > 0) { myprt << "+"; }
6145  else {
6146  myprt << "-";
6147  }
6148  myprt << std::setw(6) << tp.CTP;
6149  myprt << std::setw(5) << ipt;
6150  myprt << std::setw(5) << tp.Step;
6151  myprt << std::setw(6) << std::setprecision(2) << tp.Delta;
6152  myprt << std::setw(6) << std::setprecision(2) << tp.DeltaRMS;
6153  myprt << std::setw(6) << std::setprecision(2) << tp.Ang;
6154  myprt << std::setw(2) << tp.AngleCode;
6155  myprt << std::setw(6) << std::setprecision(2) << tp.AngErr;
6156  myprt << std::setw(6) << std::setprecision(2) << tp.Dir[0];
6157  myprt << std::setw(6) << std::setprecision(2) << tp.Dir[1];
6158  myprt << std::setw(7) << (int)tp.Chg;
6159  myprt << std::setw(8) << (int)tp.AveChg;
6160  myprt << std::setw(6) << std::setprecision(1) << tp.ChgPull;
6161  myprt << std::setw(7) << tp.FitChi;
6162  myprt << std::setw(6) << tp.NTPsFit;
6163  myprt << std::setw(7) << std::setprecision(3) << tp.KinkSig;
6164  // print the hits associated with this traj point
6165  if (tp.Hits.size() > 16) {
6166  // don't print too many hits (e.g. from a shower Tj)
6167  myprt << " " << tp.Hits.size() << " shower hits";
6168  }
6169  else {
6170  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
6171  unsigned int iht = tp.Hits[ii];
6172  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
6173  myprt << " " << hit.WireID().Wire << ":" << (int)hit.PeakTime();
6174  if (tp.UseHit[ii]) {
6175  // Distinguish used hits from nearby hits
6176  myprt << "_";
6177  }
6178  else {
6179  myprt << "x";
6180  }
6181  myprt << "T" << slc.slHits[iht].InTraj;
6182  } // iht
6183  if (tp.InPFP > 0) myprt << " inP" << tp.InPFP;
6184  }
6185  // print Environment
6186  if (tp.Environment.any()) myprt << " Env: " << TPEnvString(tp);
6187  } // PrintTP
std::string TPEnvString(const TrajPoint &tp)
Definition: Utils.cxx:6190
Detector simulation of raw signals on wires.
TDirectory * dir
Definition: macro.C:5
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
void tca::PrintTP3Ds ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
std::string  someText,
const TCSlice slc,
const PFPStruct pfp,
short  printPts 
)

Definition at line 3356 of file PFPUtils.cxx.

References AlgBitNames, tca::PFPStruct::AlgMod, geo::CryostatID::Cryostat, dEdx(), EncodeCTP(), util::end(), tca::PFPStruct::Flags, tca::PFPStruct::ID, kCanSection, kNeedsUpdate, kTP3DBad, kTP3DGood, MakeBareTP(), tca::PFPStruct::MVI, tca::TCSlice::nPlanes, pAlgModSize, PointPull(), PosSep(), PrintPos(), tca::PFPStruct::SectionFits, SectionStartEnd(), SignalAtTp(), tca::PFPStruct::TjIDs, tca::TCSlice::tjs, tca::PFPStruct::TP3Ds, geo::TPCID::TPC, tca::PFPStruct::TPCID, and TPEnvString().

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

3362  {
3363  if (pfp.TP3Ds.empty()) return;
3364  mf::LogVerbatim myprt("TC");
3365  myprt << someText << " pfp P" << pfp.ID << " MVI " << pfp.MVI;
3366  for (auto tid : pfp.TjIDs)
3367  myprt << " T" << tid;
3368  myprt << " Flags: CanSection? " << pfp.Flags[kCanSection];
3369  myprt << " NeedsUpdate? " << pfp.Flags[kNeedsUpdate];
3370  myprt << " Algs:";
3371  for (unsigned short ib = 0; ib < pAlgModSize; ++ib) {
3372  if (pfp.AlgMod[ib]) myprt << " " << AlgBitNames[ib];
3373  } // ib
3374  myprt << "\n";
3375  if (!pfp.SectionFits.empty()) {
3376  myprt << someText
3377  << " SFI ________Pos________ ________Dir_______ _____EndPos________ ChiDOF NPts "
3378  "NeedsUpdate?\n";
3379  for (std::size_t sfi = 0; sfi < pfp.SectionFits.size(); ++sfi) {
3380  myprt << someText << std::setw(4) << sfi;
3381  auto& sf = pfp.SectionFits[sfi];
3382  myprt << std::fixed << std::setprecision(1);
3383  unsigned short startPt = 0, endPt = 0;
3384  if (SectionStartEnd(pfp, sfi, startPt, endPt)) {
3385  auto& start = pfp.TP3Ds[startPt].Pos;
3386  myprt << std::setw(7) << start[0] << std::setw(7) << start[1] << std::setw(7) << start[2];
3387  }
3388  else {
3389  myprt << " Invalid";
3390  }
3391  myprt << std::fixed << std::setprecision(2);
3392  myprt << std::setw(7) << sf.Dir[0] << std::setw(7) << sf.Dir[1] << std::setw(7)
3393  << sf.Dir[2];
3394  myprt << std::fixed << std::setprecision(1);
3395  if (endPt < pfp.TP3Ds.size()) {
3396  auto& end = pfp.TP3Ds[endPt].Pos;
3397  myprt << std::setw(7) << end[0] << std::setw(7) << end[1] << std::setw(7) << end[2];
3398  }
3399  else {
3400  myprt << " Invalid";
3401  }
3402  myprt << std::setprecision(1) << std::setw(6) << sf.ChiDOF;
3403  myprt << std::setw(6) << sf.NPts;
3404  myprt << std::setw(6) << sf.NeedsUpdate;
3405  myprt << "\n";
3406  } // sec
3407  } // SectionFits
3408  if (printPts < 0) {
3409  // print the head if we print all points
3410  myprt << someText << " Note: GBH = TP3D Flags. G = Good, B = Bad, H = High dE/dx \n";
3411  myprt
3412  << someText
3413  << " ipt SFI ________Pos________ Delta Pull GBH Path along dE/dx S? T_ipt_P:W:T\n";
3414  }
3415  unsigned short fromPt = 0;
3416  unsigned short toPt = pfp.TP3Ds.size() - 1;
3417  if (printPts >= 0) fromPt = toPt;
3418  // temp kink angle for each point
3419  std::vector<float> dang(pfp.TP3Ds.size(), -1);
3420  for (unsigned short ipt = fromPt; ipt <= toPt; ++ipt) {
3421  auto tp3d = pfp.TP3Ds[ipt];
3422  myprt << someText << std::setw(4) << ipt;
3423  myprt << std::setw(4) << tp3d.SFIndex;
3424  myprt << std::fixed << std::setprecision(1);
3425  myprt << std::setw(7) << tp3d.Pos[0] << std::setw(7) << tp3d.Pos[1] << std::setw(7)
3426  << tp3d.Pos[2];
3427  myprt << std::setprecision(1) << std::setw(6) << (tp3d.Pos[0] - tp3d.TPX);
3428  float pull = PointPull(tp3d);
3429  myprt << std::setprecision(1) << std::setw(6) << pull;
3430  myprt << std::setw(3) << tp3d.Flags[kTP3DGood] << tp3d.Flags[kTP3DBad];
3431  myprt << std::setw(7) << std::setprecision(1) << PosSep(tp3d.Pos, pfp.TP3Ds[0].Pos);
3432  myprt << std::setw(7) << std::setprecision(1) << tp3d.along;
3433  myprt << std::setw(6) << std::setprecision(2) << dEdx(clockData, detProp, slc, tp3d);
3434  // print SignalAtTP in each plane
3435  myprt << " ";
3436  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
3437  CTP_t inCTP = EncodeCTP(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
3438  auto tp = MakeBareTP(detProp, tp3d.Pos, inCTP);
3439  myprt << " " << SignalAtTp(tp);
3440  } // plane
3441  if (tp3d.TjID > 0) {
3442  auto& tp = slc.tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
3443  myprt << " T" << tp3d.TjID << "_" << tp3d.TPIndex << "_" << PrintPos(tp) << " "
3444  << TPEnvString(tp);
3445  }
3446  else {
3447  myprt << " UNDEFINED";
3448  }
3449  myprt << "\n";
3450  } // ipt
3451  } // PrintTP3Ds
const std::vector< std::string > AlgBitNames
Definition: DataStructs.cxx:16
bool SignalAtTp(TrajPoint &tp)
Definition: Utils.cxx:1964
std::string TPEnvString(const TrajPoint &tp)
Definition: Utils.cxx:6190
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const Point3_t &pos, CTP_t inCTP)
Definition: Utils.cxx:3928
bool SectionStartEnd(const PFPStruct &pfp, unsigned short sfIndex, unsigned short &startPt, unsigned short &endPt)
Definition: PFPUtils.cxx:3274
constexpr unsigned int pAlgModSize
Definition: DataStructs.h:275
float dEdx(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, TP3D &tp3d)
Definition: PFPUtils.cxx:2671
unsigned int CTP_t
Definition: DataStructs.h:45
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2554
float PointPull(const TP3D &tp3d)
Definition: PFPUtils.cxx:2794
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:49
void tca::PrintTPHeader ( std::string  someText)

Definition at line 6126 of file Utils.cxx.

Referenced by DotProd(), FitVertex(), PrintAllTraj(), and PrintTrajectory().

6127  {
6128  mf::LogVerbatim("TC") << someText
6129  << " TRP CTP Ind Stp Delta RMS Ang C Err Dir0 Dir1 Q "
6130  " AveQ Pull FitChi NTPF KinkSig Hits ";
6131  } // PrintTPHeader
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void tca::PrintTrajectory ( std::string  someText,
const TCSlice slc,
const Trajectory tj,
unsigned short  tPoint 
)

Definition at line 6035 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, for(), tca::Trajectory::ID, tca::TCSlice::ID, kShowerTj, tca::Trajectory::MCSMom, tca::ShowerStruct::NearTjIDs, tca::ShowerStruct::NeedsUpdate, tca::ShowerStruct::ParentFOM, tca::ShowerStruct::ParentID, tca::Trajectory::Pass, tca::Trajectory::PDGCode, PrintEndFlag(), PrintTP(), PrintTPHeader(), tca::Trajectory::Pts, 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(), ChkChgAsymmetry(), tca::TrajClusterAlg::ChkInTraj(), DotProd(), InTrajOK(), IsGhost(), MakeHaloTj(), MakeJunkTraj(), MaskedHitsOK(), tca::TrajClusterAlg::ReconstructAllTraj(), StepAway(), StopShort(), and TrimEndPts().

6039  {
6040  // prints one or all trajectory points on tj
6041 
6042  if (tPoint == USHRT_MAX) {
6043  if (tj.ID < 0) {
6044  mf::LogVerbatim myprt("TC");
6045  myprt << someText << " ";
6046  myprt << "Work: UID " << tj.UID << " CTP " << tj.CTP << " StepDir " << tj.StepDir
6047  << " PDG " << tj.PDGCode << " slc.vtxs " << tj.VtxID[0] << " " << tj.VtxID[1]
6048  << " nPts " << tj.Pts.size() << " EndPts " << tj.EndPt[0] << " " << tj.EndPt[1];
6049  myprt << " MCSMom " << tj.MCSMom;
6050  myprt << " EndFlags " << PrintEndFlag(tj, 0) << " " << PrintEndFlag(tj, 1);
6051  myprt << " AlgMods:";
6052  for (unsigned short ib = 0; ib < AlgBitNames.size(); ++ib)
6053  if (tj.AlgMod[ib]) myprt << " " << AlgBitNames[ib];
6054  }
6055  else {
6056  mf::LogVerbatim myprt("TC");
6057  myprt << someText << " ";
6058  myprt << "slcID " << slc.ID << " T" << tj.ID << " uT" << tj.UID << " WorkID " << tj.WorkID
6059  << " StepDir " << tj.StepDir << " PDG " << tj.PDGCode << " VtxID " << tj.VtxID[0]
6060  << " " << tj.VtxID[1] << " nPts " << tj.Pts.size() << " EndPts " << tj.EndPt[0] << " "
6061  << tj.EndPt[1];
6062  myprt << " MCSMom " << tj.MCSMom;
6063  myprt << " EndFlags " << PrintEndFlag(tj, 0) << " " << PrintEndFlag(tj, 1);
6064  myprt << " AlgMods:";
6065  for (unsigned short ib = 0; ib < AlgBitNames.size(); ++ib)
6066  if (tj.AlgMod[ib]) myprt << " " << AlgBitNames[ib];
6067  }
6068  PrintTPHeader(someText);
6069  for (unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt)
6070  PrintTP(someText, slc, ipt, tj.StepDir, tj.Pass, tj.Pts[ipt]);
6071  // See if this trajectory is a shower Tj
6072  if (tj.AlgMod[kShowerTj]) {
6073  for (unsigned short ic = 0; ic < slc.cots.size(); ++ic) {
6074  if (slc.cots[ic].TjIDs.empty()) continue;
6075  // only print out the info for the correct Tj
6076  if (slc.cots[ic].ShowerTjID != tj.ID) continue;
6077  const ShowerStruct& ss = slc.cots[ic];
6078  mf::LogVerbatim myprt("TC");
6079  myprt << "cots index " << ic << " ";
6080  myprt << someText << " Envelope";
6081  if (ss.Envelope.empty()) { myprt << " NA"; }
6082  else {
6083  for (auto& vtx : ss.Envelope)
6084  myprt << " " << (int)vtx[0] << ":" << (int)(vtx[1] / tcc.unitsPerTick);
6085  }
6086  myprt << " Energy " << (int)ss.Energy;
6087  myprt << " Area " << std::fixed << std::setprecision(1) << (int)ss.EnvelopeArea
6088  << " ChgDensity " << ss.ChgDensity;
6089  myprt << "\nInShower TjIDs";
6090  for (auto& tjID : ss.TjIDs) {
6091  myprt << " " << tjID;
6092  } // tjID
6093 
6094  myprt << "\n";
6095  myprt << "NearTjIDs";
6096  for (auto& tjID : ss.NearTjIDs) {
6097  myprt << " " << tjID;
6098  } // tjID
6099  myprt << "\n";
6100  myprt << "\n";
6101  myprt << "Angle " << std::fixed << std::setprecision(2) << ss.Angle << " +/- "
6102  << ss.AngleErr;
6103  myprt << " AspectRatio " << std::fixed << std::setprecision(2) << ss.AspectRatio;
6104  myprt << " DirectionFOM " << std::fixed << std::setprecision(2) << ss.DirectionFOM;
6105  if (ss.ParentID > 0) { myprt << " Parent Tj " << ss.ParentID << " FOM " << ss.ParentFOM; }
6106  else {
6107  myprt << " No parent";
6108  }
6109  myprt << " TruParentID " << ss.TruParentID << " SS3ID " << ss.SS3ID << "\n";
6110  if (ss.NeedsUpdate) myprt << "*********** This shower needs to be updated ***********";
6111  myprt << "................................................";
6112  } // ic
6113  } // Shower Tj
6114  }
6115  else {
6116  // just print one traj point
6117  if (tPoint > tj.Pts.size() - 1) {
6118  mf::LogVerbatim("TC") << "Can't print non-existent traj point " << tPoint;
6119  return;
6120  }
6121  PrintTP(someText, slc, tPoint, tj.StepDir, tj.Pass, tj.Pts[tPoint]);
6122  }
6123  } // PrintTrajectory
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
const std::vector< std::string > AlgBitNames
Definition: DataStructs.cxx:16
TCConfig tcc
Definition: DataStructs.cxx:9
void PrintTP(std::string someText, const TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, const TrajPoint &tp)
Definition: Utils.cxx:6134
for(Int_t i=0;i< nentries;i++)
Definition: comparison.C:30
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
std::string PrintEndFlag(const Trajectory &tj, unsigned short end)
Definition: Utils.cxx:6318
void PrintTPHeader(std::string someText)
Definition: Utils.cxx:6126
std::vector< unsigned int > tca::PutHitsInVector ( const TCSlice slc,
PFPStruct const &  pfp,
HitStatus_t  hitRequest 
)

Definition at line 2665 of file Utils.cxx.

References kAllHits, kTP3DBad, kUnusedHits, kUsedHits, tca::TCSlice::tjs, and tca::PFPStruct::TP3Ds.

2668  {
2669  // Put hits with the assn P -> TP3D -> TP -> Hit into a vector
2670  std::vector<unsigned int> hitVec;
2671  if (pfp.TP3Ds.empty()) return hitVec;
2672 
2673  for (auto& tp3d : pfp.TP3Ds) {
2674  if (tp3d.Flags[kTP3DBad]) continue;
2675  if (tp3d.TjID <= 0) continue;
2676  auto& tp = slc.tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
2677  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2678  unsigned int iht = tp.Hits[ii];
2679  bool useit = (hitRequest == kAllHits);
2680  if (tp.UseHit[ii] && hitRequest == kUsedHits) useit = true;
2681  if (!tp.UseHit[ii] && hitRequest == kUnusedHits) useit = true;
2682  if (useit) hitVec.push_back(iht);
2683  }
2684  } // tp3d
2685  return hitVec;
2686  } // PutHitsInVector
std::vector< unsigned int > tca::PutTrajHitsInVector ( const Trajectory tj,
HitStatus_t  hitRequest 
)

Definition at line 2689 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(), MergeGhostTjs(), and TransferTjHits().

2690  {
2691  // Put hits (which are indexed into slHits) in each trajectory point into a flat vector
2692  std::vector<unsigned int> hitVec;
2693 
2694  // special handling for shower trajectories. UseHit isn't valid
2695  if (tj.AlgMod[kShowerTj]) {
2696  for (auto& tp : tj.Pts)
2697  hitVec.insert(hitVec.end(), tp.Hits.begin(), tp.Hits.end());
2698  return hitVec;
2699  } // shower Tj
2700 
2701  // reserve under the assumption that there will be one hit per point
2702  hitVec.reserve(tj.Pts.size());
2703  for (unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) {
2704  for (unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
2705  unsigned int iht = tj.Pts[ipt].Hits[ii];
2706  bool useit = (hitRequest == kAllHits);
2707  if (tj.Pts[ipt].UseHit[ii] && hitRequest == kUsedHits) useit = true;
2708  if (!tj.Pts[ipt].UseHit[ii] && hitRequest == kUnusedHits) useit = true;
2709  if (useit) hitVec.push_back(iht);
2710  } // iht
2711  } // ipt
2712  return hitVec;
2713  } // PutTrajHitsInVector
void tca::Reconcile2Vs ( TCSlice slc)

Definition at line 1059 of file TCVertex.cxx.

References util::abs(), tca::TCConfig::dbg2V, tca::TCConfig::dbgSlc, DecodeCTP(), kReconcile2Vs, kVxEnvOK, tca::TCSlice::nPlanes, geo::PlaneID::Plane, Reconcile2VTs(), tcc, UpdateVxEnvironment(), tca::TCConfig::useAlg, and tca::TCSlice::vtxs.

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

1060  {
1061  // This function is called before Find3DVertices to identify (and possibly reconcile)
1062  // Tj and 2V inconsistencies using 2D and 3D(?) information
1063  if (!tcc.useAlg[kReconcile2Vs]) return;
1064  if (slc.vtxs.empty()) return;
1065 
1066  bool prt = (tcc.dbg2V && tcc.dbgSlc);
1067 
1068  // clusters of 2Vs
1069  std::vector<std::vector<int>> vx2Cls;
1070 
1071  // iterate over planes
1072  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
1073  // look for 2D vertices that are close to each other
1074  vx2Cls.clear();
1075  for (unsigned short ii = 0; ii < slc.vtxs.size() - 1; ++ii) {
1076  auto& i2v = slc.vtxs[ii];
1077  if (i2v.ID <= 0) continue;
1078  if (DecodeCTP(i2v.CTP).Plane != plane) continue;
1079  for (unsigned short jj = ii + 1; jj < slc.vtxs.size(); ++jj) {
1080  auto& j2v = slc.vtxs[jj];
1081  if (j2v.ID <= 0) continue;
1082  if (DecodeCTP(j2v.CTP).Plane != plane) continue;
1083  // make rough separation cuts
1084  float dp0 = std::abs(i2v.Pos[0] - j2v.Pos[0]);
1085  if (dp0 > 10) continue;
1086  float dp1 = std::abs(i2v.Pos[1] - j2v.Pos[1]);
1087  if (dp1 > 10) continue;
1088  // do a more careful look
1089  float err = i2v.PosErr[0];
1090  if (j2v.PosErr[0] > err) err = j2v.PosErr[0];
1091  float dp0Sig = dp0 / err;
1092  if (dp0Sig > 4) continue;
1093  err = i2v.PosErr[1];
1094  if (j2v.PosErr[1] > err) err = j2v.PosErr[1];
1095  float dp1Sig = dp1 / err;
1096  if (dp1Sig > 4) continue;
1097  // Look for one of the 2V IDs in a cluster
1098  bool gotit = false;
1099  for (auto& vx2cls : vx2Cls) {
1100  bool goti = (std::find(vx2cls.begin(), vx2cls.end(), i2v.ID) != vx2cls.end());
1101  bool gotj = (std::find(vx2cls.begin(), vx2cls.end(), j2v.ID) != vx2cls.end());
1102  if (goti && gotj) {
1103  gotit = true;
1104  break;
1105  }
1106  else if (goti) {
1107  vx2cls.push_back(j2v.ID);
1108  gotit = true;
1109  break;
1110  }
1111  else if (gotj) {
1112  gotit = true;
1113  vx2cls.push_back(i2v.ID);
1114  break;
1115  }
1116  } // vx2cls
1117  if (!gotit) {
1118  // start a new cluster with this pair
1119  std::vector<int> cls(2);
1120  cls[0] = i2v.ID;
1121  cls[1] = j2v.ID;
1122  vx2Cls.push_back(cls);
1123  } // !gotit
1124  } // jj
1125  } // ii
1126  if (vx2Cls.empty()) continue;
1127  if (prt) {
1128  mf::LogVerbatim myprt("TC");
1129  myprt << "2V clusters in plane " << plane;
1130  for (auto& vx2cls : vx2Cls) {
1131  myprt << "\n";
1132  for (auto vx2id : vx2cls)
1133  myprt << " 2V" << vx2id;
1134  } // vx2cls
1135  } // prt
1136  for (auto& vx2cls : vx2Cls) {
1137  Reconcile2VTs(slc, vx2cls, prt);
1138  } // vx2cls
1139  } // plane
1140 
1141  // See if any of the vertices have been altered. If so the environment near them,
1142  // specifically tagging overlapping trajectories, should be re-done
1143  bool VxEnvironmentNeedsUpdate = false;
1144  for (auto& vx : slc.vtxs) {
1145  if (vx.ID <= 0) continue;
1146  if (!vx.Stat[kVxEnvOK]) VxEnvironmentNeedsUpdate = true;
1147  } // vx
1148 
1149  if (VxEnvironmentNeedsUpdate) UpdateVxEnvironment(slc);
1150 
1151  } // Reconcile2Vs
TCConfig tcc
Definition: DataStructs.cxx:9
constexpr auto abs(T v)
Returns the absolute value of the argument.
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
the environment near the vertex was checked - See UpdateVxEnvironment
Definition: DataStructs.h:94
bool dbg2V
debug 2D vertex finding
Definition: DataStructs.h:585
bool Reconcile2VTs(TCSlice &slc, std::vector< int > &vx2cls, bool prt)
Definition: TCVertex.cxx:1154
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
void UpdateVxEnvironment(TCSlice &slc)
Definition: Utils.cxx:3765
geo::PlaneID DecodeCTP(CTP_t CTP)
bool tca::Reconcile2VTs ( TCSlice slc,
std::vector< int > &  vx2cls,
bool  prt 
)

Definition at line 1154 of file TCVertex.cxx.

References tca::VtxStore::ChiDOF, tca::VtxStore::CTP, util::end(), FarEnd(), FitVertex(), GetAssns(), tca::TCSlice::ID, kEnvOverlap, kVxEnvOK, MakeVertexObsolete(), NearbyCleanPt(), tca::VtxStore::Pos, tca::VtxStore::PosErr, tca::TCSlice::tjs, TrajPointVertexPull(), and tca::TCSlice::vtxs.

Referenced by Reconcile2Vs().

1155  {
1156  // The 2D vertices IDs in vx2cls were clustered by the calling function. This function
1157  // checks the T -> 2V assns and possibly changes it. It returns true if an assn is changed
1158  // or if a vertex in vx2cls is made obsolete, necessitating a change to the list of 2V
1159  // clusters
1160  if (vx2cls.size() < 2) return false;
1161 
1162  // Form a list of all Tjs associated with this 2V cluster
1163  std::vector<int> t2vList;
1164 
1165  CTP_t inCTP;
1166  for (auto vx2id : vx2cls) {
1167  auto& vx2 = slc.vtxs[vx2id - 1];
1168  inCTP = vx2.CTP;
1169  // vertex clobbered? If so, vertex clustering needs to be re-done
1170  if (vx2.ID <= 0) return true;
1171  auto tlist = GetAssns(slc, "2V", vx2.ID, "T");
1172  for (auto tid : tlist)
1173  if (std::find(t2vList.begin(), t2vList.end(), tid) == t2vList.end()) t2vList.push_back(tid);
1174  } // vx2id
1175  if (t2vList.size() < 3) return false;
1176 
1177  // Sum the T -> 2V pulls
1178  float sumPulls = 0;
1179  float cnt = 0;
1180  for (auto tid : t2vList) {
1181  auto& tj = slc.tjs[tid - 1];
1182  for (unsigned short end = 0; end < 2; ++end) {
1183  if (tj.VtxID[end] <= 0) continue;
1184  if (std::find(vx2cls.begin(), vx2cls.end(), tj.VtxID[end]) == vx2cls.end()) continue;
1185  auto& vx = slc.vtxs[tj.VtxID[end] - 1];
1186  unsigned short nearEnd = 1 - FarEnd(tj, vx.Pos);
1187  unsigned short fitPt = NearbyCleanPt(tj, nearEnd);
1188  if (fitPt == USHRT_MAX) return false;
1189  auto& tp = tj.Pts[fitPt];
1190  sumPulls += TrajPointVertexPull(tp, vx);
1191  ++cnt;
1192  } // end
1193  } // tid
1194 
1195  if (prt) {
1196  mf::LogVerbatim myprt("TC");
1197  myprt << "R2VTs: cluster:";
1198  for (auto vid : vx2cls)
1199  myprt << " 2V" << vid;
1200  myprt << " ->";
1201  for (auto tid : t2vList)
1202  myprt << " T" << tid;
1203  myprt << " sumPulls " << std::setprecision(2) << sumPulls << " cnt " << cnt;
1204  } // prt
1205 
1206  // try to fit all Tjs to one vertex. Find the average position of all of the
1207  // vertices. This will be used to find the end of the Tjs that are closest to the
1208  // presumed single vertex
1209  VtxStore oneVx;
1210  oneVx.CTP = inCTP;
1211  for (auto vid : vx2cls) {
1212  auto& vx = slc.vtxs[vid - 1];
1213  oneVx.Pos[0] += vx.Pos[0];
1214  oneVx.Pos[1] += vx.Pos[2];
1215  } // vid
1216  oneVx.Pos[0] /= vx2cls.size();
1217  oneVx.Pos[1] /= vx2cls.size();
1218  std::vector<TrajPoint> oneVxTPs(t2vList.size());
1219  for (unsigned short itj = 0; itj < t2vList.size(); ++itj) {
1220  auto& tj = slc.tjs[t2vList[itj] - 1];
1221  unsigned short nearEnd = 1 - FarEnd(tj, oneVx.Pos);
1222  unsigned short fitPt = NearbyCleanPt(tj, nearEnd);
1223  if (fitPt == USHRT_MAX) return false;
1224  oneVxTPs[itj] = tj.Pts[fitPt];
1225  // inflate the TP angle angle error if a TP without an overlap wasn't found
1226  if (oneVxTPs[itj].Environment[kEnvOverlap]) oneVxTPs[itj].AngErr *= 4;
1227  oneVxTPs[itj].Step = tj.ID;
1228  } // ii
1229  if (!FitVertex(slc, oneVx, oneVxTPs, prt)) return false;
1230 
1231  if (oneVx.ChiDOF < 3) {
1232  // Update the position of the first 2V in the list
1233  auto& vx = slc.vtxs[vx2cls[0] - 1];
1234  vx.Pos = oneVx.Pos;
1235  vx.PosErr = oneVx.PosErr;
1236  vx.NTraj = t2vList.size();
1237  vx.ChiDOF = oneVx.ChiDOF;
1238  vx.Topo = 14;
1239  // Set a flag that the environment near this vertex (and all other vertices in this slice)
1240  // should be revisited
1241  vx.Stat[kVxEnvOK] = false;
1242  for (unsigned short ivx = 1; ivx < vx2cls.size(); ++ivx) {
1243  auto& vx = slc.vtxs[vx2cls[ivx] - 1];
1244  MakeVertexObsolete("R2VTPs", slc, vx, true);
1245  } // ivx
1246  // now attach the trajectories
1247  for (auto tid : t2vList) {
1248  auto& tj = slc.tjs[tid - 1];
1249  unsigned short nearEnd = 1 - FarEnd(tj, vx.Pos);
1250  tj.VtxID[nearEnd] = vx.ID;
1251  } // tid
1252  return true;
1253  } // oneVx.ChiDOF < 3
1254  return false;
1255  } // Reconcile2VTs
bool MakeVertexObsolete(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2789
bool FitVertex(TCSlice &slc, VtxStore &vx, std::vector< TrajPoint > &vxTPs, bool prt)
Definition: TCVertex.cxx:1992
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
the environment near the vertex was checked - See UpdateVxEnvironment
Definition: DataStructs.h:94
unsigned short FarEnd(const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3300
unsigned short NearbyCleanPt(const Trajectory &tj, unsigned short end)
Definition: Utils.cxx:2888
std::vector< int > GetAssns(TCSlice const &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4704
unsigned int CTP_t
Definition: DataStructs.h:45
float TrajPointVertexPull(const TrajPoint &tp, const VtxStore &vx)
Definition: TCVertex.cxx:1844
bool tca::Reconcile3D ( std::string  inFcnLabel,
TCSlice slc,
bool  parentSearchDone,
bool  prt 
)

Definition at line 424 of file TCShower.cxx.

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

Referenced by FindShowers3D().

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

Definition at line 571 of file TCShower.cxx.

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

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

Definition at line 424 of file PFPUtils.cxx.

References tca::PFPStruct::Flags, tca::PFPStruct::ID, kRTPs3D, kSmallAngle, kTP3DBad, NumPtsWithCharge(), tcc, tca::PFPStruct::TjIDs, tca::TCSlice::tjs, tca::PFPStruct::TP3Ds, and tca::TCConfig::useAlg.

Referenced by MakePFParticles().

425  {
426  // Reconcile TP -> P assns before the pfp is stored. The TP3D -> TP is defined but
427  // the TP -> P assn may not have been done. This function overwrites the TjIDs
428  // vector to be the list of Tjs that contribute > 80% of their TPs to this pfp.
429  // This function returns true if the assns are consistent.
430 
431  if (!tcc.useAlg[kRTPs3D]) return true;
432  if (pfp.Flags[kSmallAngle]) return true;
433  if (pfp.TjIDs.empty()) return false;
434  if (pfp.TP3Ds.empty()) return false;
435  if (pfp.ID <= 0) return false;
436 
437  // Tj ID, TP count
438  std::vector<std::pair<int, float>> tjTPCnt;
439  for (auto& tp3d : pfp.TP3Ds) {
440  if (tp3d.Flags[kTP3DBad]) continue;
441  if (tp3d.TjID <= 0) return false;
442  // compare the TP3D -> TP -> P assn with the P -> TP assn
443  auto& tp = slc.tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
444  if (tp.InPFP > 0 && tp.InPFP != pfp.ID) return false;
445  // find the (Tj ID, TP count) pair in the list
446  unsigned short indx = 0;
447  for (indx = 0; indx < tjTPCnt.size(); ++indx)
448  if (tjTPCnt[indx].first == tp3d.TjID) break;
449  if (indx == tjTPCnt.size()) tjTPCnt.push_back(std::make_pair(tp3d.TjID, 0));
450  ++tjTPCnt[indx].second;
451  // make the TP -> P assn
452  tp.InPFP = pfp.ID;
453  } // tp3d
454 
455  std::vector<int> nTjIDs;
456  for (auto& tjtpcnt : tjTPCnt) {
457  auto& tj = slc.tjs[tjtpcnt.first - 1];
458  float npwc = NumPtsWithCharge(slc, tj, false);
459  if (tjtpcnt.second > 0.8 * npwc) nTjIDs.push_back(tjtpcnt.first);
460  } // tjtpcnt
461  if (prt) { mf::LogVerbatim("TC") << "RTPs3D: P" << pfp.ID << " nTjIDs " << nTjIDs.size(); }
462  // TODO: is this really a failure?
463  if (nTjIDs.size() < 2) { return false; }
464  pfp.TjIDs = nTjIDs;
465 
466  return true;
467  } // ReconcileTPs
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
void tca::ReconcileTPs ( TCSlice slc)

Definition at line 470 of file PFPUtils.cxx.

References kEnvOverlap, kRTPs3D, kSmallAngle, kTP3DBad, kTP3DGood, tca::TCSlice::pfps, tcc, tca::TCSlice::tjs, and tca::TCConfig::useAlg.

471  {
472  // Reconciles TP ownership conflicts between PFParticles
473  // Make a one-to-one TP -> P assn and look for one-to-many assns.
474  // Note: Comparing the pulls for a TP to two different PFParticles generally results
475  // in selecting the first PFParticle that was made which is not too surprising considering
476  // the order in which they were created. This comparison has been commented out in favor
477  // of simply keeping the old assn and removing the new one by setting IsBad true.
478 
479  if (!tcc.useAlg[kRTPs3D]) return;
480 
481  // make a list of T -> P assns
482  std::vector<int> TinP;
483  for (auto& pfp : slc.pfps) {
484  if (pfp.ID <= 0) continue;
485  if (pfp.Flags[kSmallAngle]) continue;
486  for (std::size_t ipt = 0; ipt < pfp.TP3Ds.size(); ++ipt) {
487  auto& tp3d = pfp.TP3Ds[ipt];
488  if (tp3d.TjID <= 0) continue;
489  if (std::find(TinP.begin(), TinP.end(), tp3d.TjID) == TinP.end()) TinP.push_back(tp3d.TjID);
490  auto& tp = slc.tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
491  if (tp.InPFP > 0) {
492  // an assn exists. Set the overlap bit and check consistency
493  tp.Environment[kEnvOverlap] = true;
494  // keep the previous assn (since it was created earlier and is more credible) and remove the new one
495  tp3d.Flags[kTP3DBad] = true;
496  tp3d.Flags[kTP3DGood] = false;
497  tp.InPFP = 0;
498  }
499  else {
500  // no assn exists
501  tp.InPFP = pfp.ID;
502  } // tp.InPFP > 0
503  } // ipt
504  } // pfp
505  } // ReconcileTPs
TCConfig tcc
Definition: DataStructs.cxx:9
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
void tca::ReconcileVertices ( TCSlice slc,
PFPStruct pfp,
bool  prt 
)

Definition at line 1626 of file PFPUtils.cxx.

References AttachToAnyVertex(), util::end(), tca::PFPStruct::Flags, tca::PFPStruct::ID, kJunk3D, kSmallAngle, kTP3DGood, MakeVertexObsolete(), tca::TCSlice::pfps, Reverse(), tcc, tca::TCSlice::tjs, tca::PFPStruct::TP3Ds, tca::TCConfig::vtx3DCuts, tca::TCSlice::vtxs, and tca::PFPStruct::Vx3ID.

Referenced by MakePFParticles().

1627  {
1628  // Checks for mis-placed 2D and 3D vertices and either attaches them
1629  // to a vertex or deletes(?) the vertex while attempting to preserve or
1630  // correct the P -> T -> 2V -> 3V assn. After this is done, the function
1631  // TCVertex/AttachToAnyVertex is called.
1632  // This function returns true if something was done to the pfp that requires
1633  // a re-definition of the pfp, e.g. adding or removing TP3Ds. Note that this
1634  // never occurs as the function is currently written
1635 
1636  if (tcc.vtx3DCuts.size() < 3) return;
1637  if (pfp.TP3Ds.empty()) return;
1638  if (pfp.Flags[kJunk3D]) return;
1639  if (pfp.Flags[kSmallAngle]) return;
1640 
1641  // first make a list of all Tjs
1642  std::vector<int> tjList;
1643  for (auto& tp3d : pfp.TP3Ds) {
1644  if (!tp3d.Flags[kTP3DGood]) continue;
1645  // ignore single hits
1646  if (tp3d.TjID <= 0) continue;
1647  if (std::find(tjList.begin(), tjList.end(), tp3d.TjID) == tjList.end())
1648  tjList.push_back(tp3d.TjID);
1649  } // tp3d
1650  // look for 3D vertices associated with these Tjs and list of
1651  // orphan 2D vertices - those that are not matched to 3D vertices
1652  std::vector<int> vx2List, vx3List;
1653  for (auto tid : tjList) {
1654  auto& tj = slc.tjs[tid - 1];
1655  for (unsigned short end = 0; end < 2; ++end) {
1656  if (tj.VtxID[end] <= 0) continue;
1657  auto& vx2 = slc.vtxs[tj.VtxID[end] - 1];
1658  if (vx2.Vx3ID > 0) {
1659  if (std::find(vx3List.begin(), vx3List.end(), vx2.Vx3ID) == vx3List.end())
1660  vx3List.push_back(vx2.Vx3ID);
1661  // 3D vertex exists
1662  }
1663  else {
1664  // no 3D vertex
1665  if (std::find(vx2List.begin(), vx2List.end(), tj.VtxID[end]) == vx2List.end())
1666  vx2List.push_back(tj.VtxID[end]);
1667  } // no 3D vertex
1668  } // end
1669  } // tid
1670  // no vertex reconciliation is necessary
1671  if (vx2List.empty() && vx3List.empty()) return;
1672  if (prt) {
1673  mf::LogVerbatim myprt("TC");
1674  myprt << "RV: P" << pfp.ID << " ->";
1675  for (auto tid : tjList)
1676  myprt << " T" << tid;
1677  myprt << " ->";
1678  for (auto vid : vx3List)
1679  myprt << " 3V" << vid;
1680  if (!vx2List.empty()) {
1681  myprt << " orphan";
1682  for (auto vid : vx2List)
1683  myprt << " 2V" << vid;
1684  }
1685  } // prt
1686  // Just kill the orphan 2D vertices regardless of their score.
1687  // This is an indicator that the vertex was created between two tjs
1688  // that maybe should have been reconstructed as one or alternatively
1689  // as two Tjs. This decision presumes the existence of a 3D kink
1690  // algorithm that doesn't yet exist...
1691  for (auto vid : vx2List) {
1692  auto& vx2 = slc.vtxs[vid - 1];
1693  MakeVertexObsolete("RV", slc, vx2, true);
1694  } // vx2List
1695  // ignore the T -> 2V -> 3V assns (if any exist) and try to directly
1696  // attach to 3D vertices at both ends
1697  AttachToAnyVertex(slc, pfp, tcc.vtx3DCuts[2], prt);
1698  // check for differences and while we are here, see if the pfp was attached
1699  // to a neutrino vertex and the direction is wrong
1700  int neutrinoVx = 0;
1701  if (!slc.pfps.empty()) {
1702  auto& npfp = slc.pfps[0];
1703  bool neutrinoPFP = (npfp.PDGCode == 12 || npfp.PDGCode == 14);
1704  if (neutrinoPFP) neutrinoVx = npfp.Vx3ID[0];
1705  } // pfps exist
1706  unsigned short neutrinoVxEnd = 2;
1707  for (unsigned short end = 0; end < 2; ++end) {
1708  // see if a vertex got attached
1709  if (pfp.Vx3ID[end] <= 0) continue;
1710  if (pfp.Vx3ID[end] == neutrinoVx) neutrinoVxEnd = end;
1711  // see if this is a vertex in the list using the T -> 2V -> 3V assns
1712  if (std::find(vx3List.begin(), vx3List.end(), pfp.Vx3ID[end]) != vx3List.end()) continue;
1713  } // end
1714  if (neutrinoVxEnd < 2 && neutrinoVxEnd != 0) Reverse(pfp);
1715 
1716  return;
1717  } // ReconcileVertices
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:2698
std::vector< float > vtx3DCuts
2D vtx -> 3D vtx matching cuts
Definition: DataStructs.h:542
TCConfig tcc
Definition: DataStructs.cxx:9
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
bool AttachToAnyVertex(TCSlice &slc, PFPStruct &pfp, float maxSep, bool prt)
Definition: TCVertex.cxx:1580
void Reverse(PFPStruct &pfp)
Definition: PFPUtils.cxx:2348
void tca::Recover ( detinfo::DetectorPropertiesData const &  detProp,
TCSlice slc,
PFPStruct pfp,
bool  prt 
)

Definition at line 2059 of file PFPUtils.cxx.

References tca::PFPStruct::AlgMod, CanSection(), Find3DRecoRange(), FitSection(), tca::PFPStruct::ID, kSmallAngle, tca::PFPStruct::SectionFits, and tca::PFPStruct::TP3Ds.

Referenced by MakePFParticles().

2063  {
2064  // try to recover from a poor initial fit
2065  if (pfp.AlgMod[kSmallAngle]) return;
2066  if (pfp.SectionFits.size() != 1) return;
2067  if (pfp.TP3Ds.size() < 20) return;
2068  if (!CanSection(slc, pfp)) return;
2069 
2070  // make a copy
2071  auto p2 = pfp;
2072  // try two sections
2073  p2.SectionFits.resize(2);
2074  unsigned short halfPt = p2.TP3Ds.size() / 2;
2075  for (unsigned short ipt = halfPt; ipt < p2.TP3Ds.size(); ++ipt)
2076  p2.TP3Ds[ipt].SFIndex = 1;
2077  // Confirm that both sections can be reconstructed
2078  unsigned short toPt = Find3DRecoRange(slc, p2, 0, 3, 1);
2079  if (toPt > p2.TP3Ds.size()) return;
2080  toPt = Find3DRecoRange(slc, p2, halfPt, 3, 1);
2081  if (toPt > p2.TP3Ds.size()) return;
2082  if (!FitSection(detProp, slc, p2, 0) || !FitSection(detProp, slc, p2, 1)) {
2083  if (prt) {
2084  mf::LogVerbatim myprt("TC");
2085  myprt << "Recover failed MVI " << p2.MVI << " in TPC " << p2.TPCID.TPC;
2086  for (auto tid : p2.TjIDs)
2087  myprt << " T" << tid;
2088  } // prt
2089  return;
2090  }
2091  if (prt) mf::LogVerbatim("TC") << "Recover: P" << pfp.ID << " success";
2092  pfp = p2;
2093 
2094  } // Recover
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool CanSection(const TCSlice &slc, const PFPStruct &pfp)
Definition: PFPUtils.cxx:1323
unsigned short Find3DRecoRange(const TCSlice &slc, const PFPStruct &pfp, unsigned short fromPt, unsigned short min2DPts, short dir)
Definition: PFPUtils.cxx:1338
bool FitSection(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, unsigned short sfIndex)
Definition: PFPUtils.cxx:1391
bool tca::RefineVtxPosition ( const Trajectory tj,
unsigned short &  nearPt,
short  nPtsToChk,
bool  prt 
)

Definition at line 2668 of file TCVertex.cxx.

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

Referenced by CompleteIncomplete3DVertices().

2669  {
2670  // The tj has been slated to be split somewhere near point nearPt. This function will move
2671  // the near point a bit to the most likely point of a vertex
2672 
2673  float maxChg = tj.Pts[nearPt].Chg;
2674  short maxChgPt = nearPt;
2675  unsigned short fromPt = tj.EndPt[0];
2676  short spt = (short)nearPt - (short)nPtsToChk;
2677  if (spt > (short)fromPt) fromPt = nearPt - nPtsToChk;
2678  unsigned short toPt = nearPt + nPtsToChk;
2679  if (toPt > tj.EndPt[1]) toPt = tj.EndPt[1];
2680 
2681  for (short ipt = fromPt; ipt <= toPt; ++ipt) {
2682  if (ipt < tj.EndPt[0] || ipt > tj.EndPt[1]) continue;
2683  auto& tp = tj.Pts[ipt];
2684  if (tp.Chg > maxChg) {
2685  maxChg = tp.Chg;
2686  maxChgPt = ipt;
2687  }
2688  if (prt)
2689  mf::LogVerbatim("TC") << "RVP: ipt " << ipt << " Pos " << tp.CTP << ":" << PrintPos(tp.Pos)
2690  << " chg " << (int)tp.Chg << " nhits " << tp.Hits.size();
2691  } // ipt
2692  if (nearPt == maxChgPt) return false;
2693  nearPt = maxChgPt;
2694  return true;
2695  } //RefineVtxPosition
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
void tca::ReleaseHits ( TCSlice slc,
Trajectory const &  tj 
)

Definition at line 1049 of file Utils.cxx.

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

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

1050  {
1051  // Sets InTraj[] = 0 for all TPs in work. Called when abandoning work
1052  for (auto const& tp : tj.Pts) {
1053  for (auto iht : tp.Hits) {
1054  if (slc.slHits[iht].InTraj == tj.ID) slc.slHits[iht].InTraj = 0;
1055  }
1056  } // tp
1057 
1058  } // 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 1340 of file TCShower.cxx.

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

Referenced by Reconcile3D().

1346  {
1347  // removes the tjs in the pfp from the ss3 2D showers and optionally update. This function only returns
1348  // false if there was a failure. The absence of any pfp Tjs in ss3 is not considered a failure
1349 
1350  if (pfp.ID == 0 || ss3.ID == 0) return false;
1351 
1352  std::string fcnLabel = inFcnLabel + ".RemP";
1353  for (auto tid : pfp.TjIDs) {
1354  for (auto cid : ss3.CotIDs) {
1355  auto& ss = slc.cots[cid - 1];
1356  if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tid) == ss.TjIDs.end()) continue;
1357  if (!RemoveTj(fcnLabel, slc, tid, ss, doUpdate, prt)) return false;
1358  ss3.NeedsUpdate = true;
1359  } // cid
1360  } // ptid
1361 
1362  if (doUpdate && ss3.NeedsUpdate) UpdateShower(fcnLabel, slc, ss3, prt);
1363  return true;
1364 
1365  } // Remove PFP
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1106
bool RemoveTj(std::string inFcnLabel, TCSlice &slc, int TjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1506
bool tca::RemoveTj ( std::string  inFcnLabel,
TCSlice slc,
int  TjID,
ShowerStruct ss,
bool  doUpdate,
bool  prt 
)

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

1512  {
1513  // Removes the Tj from a shower
1514 
1515  if (TjID > (int)slc.tjs.size()) return false;
1516 
1517  std::string fcnLabel = inFcnLabel + ".RTj";
1518 
1519  // make sure it isn't already in a shower
1520  Trajectory& tj = slc.tjs[TjID - 1];
1521 
1522  if (tj.SSID != ss.ID) {
1523  if (prt)
1524  mf::LogVerbatim("TC") << fcnLabel << " Can't Remove T" << TjID << " from 2S" << ss.ID
1525  << " because it's not in this shower";
1526  // This isn't a failure
1527  return true;
1528  }
1529  tj.AlgMod[kShwrParent] = false;
1530 
1531  bool gotit = false;
1532  for (unsigned short ii = 0; ii < ss.TjIDs.size(); ++ii) {
1533  if (TjID == ss.TjIDs[ii]) {
1534  ss.TjIDs.erase(ss.TjIDs.begin() + ii);
1535  gotit = true;
1536  break;
1537  }
1538  } // ii
1539  if (!gotit) return false;
1540  tj.SSID = 0;
1541  // Removing a parent Tj?
1542  if (TjID == ss.ParentID) ss.ParentID = 0;
1543  // re-build everything?
1544  if (prt) mf::LogVerbatim("TC") << fcnLabel << " Remove T" << TjID << " from 2S" << ss.ID;
1545  // removed the only tj
1546  if (ss.TjIDs.empty()) {
1547  if (prt) mf::LogVerbatim("TC") << fcnLabel << " Removed the last Tj. Killing 2S" << ss.ID;
1548  MakeShowerObsolete(fcnLabel, slc, ss, prt);
1549  return true;
1550  }
1551  // clear out the shower points to force a complete update when UpdateShower is next called
1552  ss.ShPts.clear();
1553  if (doUpdate) {
1554  ss.NeedsUpdate = true;
1555  return UpdateShower(fcnLabel, slc, ss, prt);
1556  }
1557  return true;
1558  } // RemoveTj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void MakeShowerObsolete(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3169
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1106
bool tca::ReSection ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice slc,
PFPStruct pfp,
bool  prt 
)

Definition at line 1097 of file PFPUtils.cxx.

References debug, Find3DRecoRange(), FitSection(), FitTP3Ds(), tca::PFPStruct::Flags, tca::PFPStruct::ID, if(), kCanSection, kNeedsUpdate, kSmallAngle, kTP3DGood, tca::TCConfig::match3DCuts, tca::DebugStuff::MVI, tca::PFPStruct::MVI, tca::PFPStruct::SectionFits, SortSection(), tcc, tca::PFPStruct::TP3Ds, and Update().

Referenced by MakePFParticles().

1101  {
1102  // Re-fit the TP3Ds in sections and add/remove sections to keep ChiDOF of each section close to 1.
1103  // This function only fails when there is a serious error, otherwise if reasonable fits cannot be
1104  // achieved, the CanSection flag is set false.
1105  if (pfp.SectionFits.empty()) return false;
1106  // This function shouldn't be called if this is the case but it isn't a major failure if it is
1107  if (!pfp.Flags[kCanSection]) return true;
1108  if (pfp.Flags[kSmallAngle]) return true;
1109  // Likewise this shouldn't be attempted if there aren't at least 3 points in 2 planes in 2 sections
1110  // but it isn't a failure
1111  if (pfp.TP3Ds.size() < 12) {
1112  pfp.Flags[kCanSection] = false;
1113  return true;
1114  }
1115 
1116  prt = (pfp.MVI == debug.MVI);
1117 
1118  // try to keep ChiDOF between chiLo and chiHi
1119  float chiLo = 0.5 * tcc.match3DCuts[5];
1120  float chiHi = 1.5 * tcc.match3DCuts[5];
1121 
1122  // clobber the old sections if more than one exists
1123  if (pfp.SectionFits.size() > 1) {
1124  // make one section
1125  pfp.SectionFits.resize(1);
1126  // put all of the points in it and fit
1127  for (auto& tp3d : pfp.TP3Ds) {
1128  tp3d.SFIndex = 0;
1129  tp3d.Flags[kTP3DGood] = true;
1130  }
1131  auto& sf = pfp.SectionFits[0];
1132  if (!FitSection(detProp, slc, pfp, 0)) { return false; }
1133  if (sf.ChiDOF < tcc.match3DCuts[5]) return true;
1134  } // > 1 SectionFit
1135  // sort by distance from the start
1136  if (!SortSection(pfp, 0)) return false;
1137  // require a minimum of 3 points in 2 planes
1138  unsigned short min2DPts = 3;
1139  unsigned short fromPt = 0;
1140  // set the section index to invalid for all points
1141  for (auto& tp3d : pfp.TP3Ds)
1142  tp3d.SFIndex = USHRT_MAX;
1143  // Guess how many points should be added in each iteration
1144  unsigned short nPtsToAdd = pfp.TP3Ds.size() / 4;
1145  // the actual number of points that will be fit in the section
1146  unsigned short nPts = nPtsToAdd;
1147  // the minimum number of points
1148  unsigned short nPtsMin = Find3DRecoRange(slc, pfp, fromPt, min2DPts, 1) - fromPt + 1;
1149  if (nPtsMin >= pfp.TP3Ds.size()) {
1150  pfp.Flags[kCanSection] = false;
1151  return true;
1152  }
1153  float chiDOF = 0;
1154  if (nPts < nPtsMin) nPts = nPtsMin;
1155  // Try to reduce the number of iterations for long pfps
1156  if (pfp.TP3Ds.size() > 100) {
1157  unsigned short nhalf = pfp.TP3Ds.size() / 2;
1158  FitTP3Ds(detProp, slc, pfp, fromPt, nhalf, USHRT_MAX);
1159  if (chiDOF < tcc.match3DCuts[5]) nPts = nhalf;
1160  }
1161  bool lastSection = false;
1162  for (unsigned short sfIndex = 0; sfIndex < 20; ++sfIndex) {
1163  // Try to add/remove points in each section no more than 20 times
1164  float chiDOFPrev = 0;
1165  short nHiChi = 0;
1166  for (unsigned short nit = 0; nit < 10; ++nit) {
1167  // Decide how many points to add or subtract after doing the fit
1168  unsigned short nPtsNext = nPts;
1169  if (!FitTP3Ds(detProp, slc, pfp, fromPt, nPts, USHRT_MAX)) { nPtsNext += 1.5 * nPtsToAdd; }
1170  else if (chiDOF < chiLo) {
1171  // low chiDOF
1172  if (nHiChi > 2) {
1173  // declare it close enough if several attempts were made
1174  nPtsNext = 0;
1175  }
1176  else {
1177  nPtsNext += nPtsToAdd;
1178  } // nHiChi < 2
1179  nHiChi = 0;
1180  }
1181  else if (chiDOF > chiHi) {
1182  // high chiDOF
1183  ++nHiChi;
1184  if (nHiChi == 1 && chiDOFPrev > tcc.match3DCuts[5]) {
1185  // reduce the number of points by 1/2 on the first attempt
1186  nPtsNext /= 2;
1187  }
1188  else {
1189  // that didn't work so start subtracting groups of points
1190  short npnext = (short)nPts - nHiChi * 5;
1191  // assume this won't work
1192  nPtsNext = 0;
1193  if (npnext > nPtsMin) nPtsNext = npnext;
1194  }
1195  }
1196  else {
1197  // just right
1198  nPtsNext = 0;
1199  }
1200  // check for passing the end
1201  if (fromPt + nPtsNext >= pfp.TP3Ds.size()) {
1202  nPtsNext = pfp.TP3Ds.size() - fromPt;
1203  lastSection = true;
1204  }
1205  if (prt) {
1206  mf::LogVerbatim myprt("TC");
1207  myprt << " RS: P" << pfp.ID << " sfi/nit/npts " << sfIndex << "/" << nit << "/" << nPts;
1208  myprt << std::fixed << std::setprecision(1) << " chiDOF " << chiDOF;
1209  myprt << " fromPt " << fromPt;
1210  myprt << " nPtsNext " << nPtsNext;
1211  myprt << " nHiChi " << nHiChi;
1212  myprt << " lastSection? " << lastSection;
1213  }
1214  if (nPtsNext == 0) break;
1215  // see if this is the last section
1216  if (lastSection) break;
1217  if (chiDOF == chiDOFPrev) {
1218  if (prt) mf::LogVerbatim("TC") << " MVI " << pfp.MVI << " chiDOF not changing\n";
1219  break;
1220  }
1221  nPts = nPtsNext;
1222  chiDOFPrev = chiDOF;
1223  } // nit
1224  // finished this section. Assign the points to it
1225  unsigned short toPt = fromPt + nPts;
1226  if (toPt > pfp.TP3Ds.size()) toPt = pfp.TP3Ds.size();
1227  for (unsigned short ipt = fromPt; ipt < toPt; ++ipt)
1228  pfp.TP3Ds[ipt].SFIndex = sfIndex;
1229  // See if there are enough points remaining to reconstruct another section if this isn't known
1230  // to be the last section
1231  if (!lastSection) {
1232  // this will be the first point in the next section
1233  unsigned short nextFromPt = fromPt + nPts;
1234  // See if it will have enough points to be reconstructed
1235  unsigned short nextToPtMin = Find3DRecoRange(slc, pfp, nextFromPt, min2DPts, 1);
1236  if (nextToPtMin == USHRT_MAX) {
1237  // not enough points so this is the last section
1238  lastSection = true;
1239  // assign the remaining points to the last section
1240  for (std::size_t ipt = nextFromPt; ipt < pfp.TP3Ds.size(); ++ipt)
1241  pfp.TP3Ds[ipt].SFIndex = sfIndex;
1242  }
1243  } // !lastSection
1244  // Do a final fit and update the points. Don't worry about a poor ChiDOF
1245  FitSection(detProp, slc, pfp, sfIndex);
1246  if (!SortSection(pfp, 0)) { return false; }
1247  if (lastSection) break;
1248  // Prepare for the next section.
1249  fromPt = fromPt + nPts;
1250  nPts = nPtsToAdd;
1251  nPtsMin = Find3DRecoRange(slc, pfp, fromPt, min2DPts, 1) - fromPt + 1;
1252  if (nPtsMin >= pfp.TP3Ds.size()) break;
1253  // add a new section
1254  pfp.SectionFits.resize(pfp.SectionFits.size() + 1);
1255  } // snit
1256 
1257  // see if the last sf is valid
1258  if (pfp.SectionFits.size() > 1 && pfp.SectionFits.back().ChiDOF < 0) {
1259  unsigned short badSFI = pfp.SectionFits.size() - 1;
1260  // remove it
1261  pfp.SectionFits.pop_back();
1262  for (std::size_t ipt = pfp.TP3Ds.size() - 1; ipt > 0; --ipt) {
1263  auto& tp3d = pfp.TP3Ds[ipt];
1264  if (tp3d.SFIndex < badSFI) break;
1265  --tp3d.SFIndex;
1266  }
1267  pfp.SectionFits.back().NeedsUpdate = true;
1268  } // bad last SF
1269 
1270  // Ensure that the points at the end are in the last section
1271  for (std::size_t ipt = pfp.TP3Ds.size() - 1; ipt > 0; --ipt) {
1272  auto& tp3d = pfp.TP3Ds[ipt];
1273  if (tp3d.SFIndex < pfp.SectionFits.size()) break;
1274  tp3d.SFIndex = pfp.SectionFits.size() - 1;
1275  pfp.Flags[kNeedsUpdate] = true;
1276  pfp.SectionFits[tp3d.SFIndex].NeedsUpdate = true;
1277  } // tp3d
1278 
1279  Update(detProp, slc, pfp);
1280 
1281  // set CanSection false if the chisq is poor in any section
1282  for (auto& sf : pfp.SectionFits) {
1283  if (sf.ChiDOF > tcc.match3DCuts[5]) pfp.Flags[kCanSection] = false;
1284  }
1285 
1286  return true;
1287  } // resection
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool SortSection(PFPStruct &pfp, unsigned short sfIndex)
Definition: PFPUtils.cxx:1999
TCConfig tcc
Definition: DataStructs.cxx:9
bool FitTP3Ds(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, unsigned short fromPt, unsigned short nPtsFit, unsigned short sfIndex)
Definition: PFPUtils.cxx:1565
unsigned int MVI
MatchVec Index for detailed 3D matching.
Definition: DebugStruct.h:29
bool Update(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp)
Definition: PFPUtils.cxx:1048
unsigned short Find3DRecoRange(const TCSlice &slc, const PFPStruct &pfp, unsigned short fromPt, unsigned short min2DPts, short dir)
Definition: PFPUtils.cxx:1338
if(nlines<=0)
DebugStuff debug
Definition: DebugStruct.cxx:4
bool FitSection(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, unsigned short sfIndex)
Definition: PFPUtils.cxx:1391
std::vector< float > match3DCuts
3D matching cuts
Definition: DataStructs.h:551
void tca::RestoreObsoleteTrajectory ( TCSlice slc,
unsigned int  itj 
)

Definition at line 2150 of file Utils.cxx.

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

2151  {
2152  if (itj > slc.tjs.size() - 1) return;
2153  if (!slc.tjs[itj].AlgMod[kKilled]) {
2154  mf::LogWarning("TC")
2155  << "RestoreObsoleteTrajectory: Trying to restore not-obsolete trajectory "
2156  << slc.tjs[itj].ID;
2157  return;
2158  }
2159  unsigned int iht;
2160  for (auto& tp : slc.tjs[itj].Pts) {
2161  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2162  if (tp.UseHit[ii]) {
2163  iht = tp.Hits[ii];
2164  if (slc.slHits[iht].InTraj == 0) { slc.slHits[iht].InTraj = slc.tjs[itj].ID; }
2165  }
2166  } // ii
2167  } // tp
2168  slc.tjs[itj].AlgMod[kKilled] = false;
2169  } // RestoreObsoleteTrajectory
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
void tca::Reverse ( PFPStruct pfp)

Definition at line 2348 of file PFPUtils.cxx.

References tca::PFPStruct::dEdx, tca::PFPStruct::dEdxErr, tca::PFPStruct::EndFlag, Reverse(), tca::PFPStruct::SectionFits, tca::PFPStruct::TP3Ds, and tca::PFPStruct::Vx3ID.

Referenced by ReconcileVertices(), and Reverse().

2349  {
2350  // reverse the PFParticle
2351  std::reverse(pfp.TP3Ds.begin(), pfp.TP3Ds.end());
2352  std::reverse(pfp.SectionFits.begin(), pfp.SectionFits.end());
2353  for (std::size_t sfi = 0; sfi < pfp.SectionFits.size(); ++sfi) {
2354  auto& sf = pfp.SectionFits[sfi];
2355  // flip the direction vector
2356  for (unsigned short xyz = 0; xyz < 3; ++xyz)
2357  sf.Dir[xyz] *= -1;
2358  } // sf
2359  // correct the along variable
2360  for (auto& tp3d : pfp.TP3Ds)
2361  tp3d.along *= -1;
2362  std::swap(pfp.dEdx[0], pfp.dEdx[1]);
2363  std::swap(pfp.dEdxErr[0], pfp.dEdxErr[1]);
2364  std::swap(pfp.Vx3ID[0], pfp.Vx3ID[1]);
2365  std::swap(pfp.EndFlag[0], pfp.EndFlag[1]);
2366  } // Reverse
void swap(lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &a, lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &b)
void tca::ReversePropagate ( TCSlice slc,
Trajectory tj 
)

Definition at line 1417 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, ChkStop(), ChkStopEndPts(), tca::Trajectory::CTP, tca::TCConfig::dbgAlg, tca::TCConfig::dbgStp, DecodeCTP(), tca::Trajectory::EndPt, evt, FindCloseHits(), tca::TCSlice::firstWire, tca::TCEvent::goodWire, 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, and tca::TrajPoint::UseHit.

Referenced by ChkBegin().

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

Definition at line 3112 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.

Referenced by FindShowerStart(), ReverseShower(), and UpdateShower().

3113  {
3114  // Reverses the shower and the shower tj
3115 
3116  if (ss.ID == 0) return;
3117  if (ss.TjIDs.empty()) return;
3118 
3119  std::string fcnLabel = inFcnLabel + ".RevSh";
3120 
3121  std::reverse(ss.ShPts.begin(), ss.ShPts.end());
3122  // change the sign of RotPos
3123  for (auto& sspt : ss.ShPts) {
3124  sspt.RotPos[0] = -sspt.RotPos[0];
3125  sspt.RotPos[1] = -sspt.RotPos[1];
3126  }
3127  // flip the shower angle
3128  if (ss.Angle > 0) { ss.Angle -= M_PI; }
3129  else {
3130  ss.Angle += M_PI;
3131  }
3132  if (ss.DirectionFOM != 0) ss.DirectionFOM = 1 / ss.DirectionFOM;
3133  auto& stj = slc.tjs[ss.ShowerTjID - 1];
3134  ReverseTraj(stj);
3135  DefineEnvelope(fcnLabel, slc, ss, prt);
3136  if (prt) mf::LogVerbatim("TC") << fcnLabel << " Reversed shower. Shower angle = " << ss.Angle;
3137  } // ReverseShower
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void DefineEnvelope(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3442
void ReverseTraj(Trajectory &tj)
Definition: Utils.cxx:3219
void tca::ReverseShower ( std::string  inFcnLabel,
TCSlice slc,
int  cotID,
bool  prt 
)

Definition at line 3140 of file TCShower.cxx.

References tca::TCSlice::cots, tca::ShowerStruct::ID, and ReverseShower().

3141  {
3142  // Reverses the shower and the shower tj
3143 
3144  if (cotID > (int)slc.cots.size()) return;
3145  ShowerStruct& ss = slc.cots[cotID - 1];
3146  if (ss.ID == 0) return;
3147  ReverseShower(inFcnLabel, slc, ss, prt);
3148  }
void ReverseShower(std::string inFcnLabel, TCSlice &slc, int cotID, bool prt)
Definition: TCShower.cxx:3140
void tca::ReverseTraj ( Trajectory tj)

Definition at line 3219 of file Utils.cxx.

References tca::Trajectory::dEdx, tca::Trajectory::EndFlag, tca::Trajectory::Pts, SetEndPoints(), tca::Trajectory::StartEnd, tca::Trajectory::StepDir, and tca::Trajectory::VtxID.

Referenced by DefineTjParents(), EndMerge(), MergeAndStore(), ReversePropagate(), and ReverseShower().

3220  {
3221  // reverse the trajectory
3222  if (tj.Pts.empty()) return;
3223  // reverse the crawling direction flag
3224  tj.StepDir = -tj.StepDir;
3225  // Vertices
3226  std::swap(tj.VtxID[0], tj.VtxID[1]);
3227  // trajectory points
3228  std::reverse(tj.Pts.begin(), tj.Pts.end());
3229  // reverse the stop flag
3230  std::reverse(tj.EndFlag.begin(), tj.EndFlag.end());
3231  std::swap(tj.dEdx[0], tj.dEdx[1]);
3232  // reverse the direction vector on all points
3233  for (unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) {
3234  if (tj.Pts[ipt].Dir[0] != 0) tj.Pts[ipt].Dir[0] = -tj.Pts[ipt].Dir[0];
3235  if (tj.Pts[ipt].Dir[1] != 0) tj.Pts[ipt].Dir[1] = -tj.Pts[ipt].Dir[1];
3236  if (tj.Pts[ipt].Ang > 0) { tj.Pts[ipt].Ang -= M_PI; }
3237  else {
3238  tj.Pts[ipt].Ang += M_PI;
3239  }
3240  } // ipt
3241  if (tj.StartEnd == 0 || tj.StartEnd == 1) tj.StartEnd = 1 - tj.StartEnd;
3242  SetEndPoints(tj);
3243  } // ReverseTraj
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
void swap(lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &a, lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &b)
void tca::SaveAllCots ( TCSlice slc,
const CTP_t inCTP,
std::string  someText 
)

Definition at line 179 of file TCShTree.cxx.

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

Referenced by FindShowers3D().

180  {
181  if (!tcc.modes[kSaveShowerTree]) return;
182  for (unsigned short cotIndex = 0; cotIndex < slc.cots.size(); ++cotIndex) {
183  auto& ss = slc.cots[cotIndex];
184  if (ss.CTP != inCTP) continue;
185  if (ss.ID == 0) continue;
186  SaveTjInfo(slc, ss, someText);
187  } // cotIndex
188  } // SaveAllCots
TCConfig tcc
Definition: DataStructs.cxx:9
void SaveTjInfo(TCSlice &slc, const ShowerStruct &ss, std::string stageName)
Definition: TCShTree.cxx:56
save shower tree
Definition: DataStructs.h:531
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
void tca::SaveAllCots ( TCSlice slc,
std::string  someText 
)

Definition at line 190 of file TCShTree.cxx.

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

191  {
192  if (!tcc.modes[kSaveShowerTree]) return;
193  for (unsigned short cotIndex = 0; cotIndex < slc.cots.size(); ++cotIndex) {
194  auto& ss = slc.cots[cotIndex];
195  if (ss.ID == 0) continue;
196  SaveTjInfo(slc, ss, someText);
197  } // cotIndex
198  }
TCConfig tcc
Definition: DataStructs.cxx:9
void SaveTjInfo(TCSlice &slc, const ShowerStruct &ss, std::string stageName)
Definition: TCShTree.cxx:56
save shower tree
Definition: DataStructs.h:531
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
void tca::SaveCRInfo ( detinfo::DetectorClocksData const &  clockData,
TCSlice slc,
PFPStruct pfp,
bool  fIsRealData 
)

Definition at line 26 of file TCCR.cxx.

References util::abs(), 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, geo::BoxBoundedGeo::MaxY(), geo::BoxBoundedGeo::MaxZ(), geo::BoxBoundedGeo::MinY(), geo::BoxBoundedGeo::MinZ(), tca::TCConfig::modes, tcc, tca::PFPStruct::TP3Ds, and geo::GeometryCore::TPC().

30  {
31  //Check the origin of pfp
32  if (tcc.modes[kSaveCRTree]) {
33  if (fIsRealData) { slc.crt.cr_origin.push_back(-1); }
34  else {
35  slc.crt.cr_origin.push_back(GetOrigin(clockData, slc, pfp));
36  }
37  }
38 
39  // save the xmin and xmax of each pfp
40  auto& startPos = pfp.TP3Ds[0].Pos;
41  auto& endPos = pfp.TP3Ds[pfp.TP3Ds.size() - 1].Pos;
42  slc.crt.cr_pfpxmin.push_back(std::min(startPos[0], endPos[0]));
43  slc.crt.cr_pfpxmax.push_back(std::max(startPos[0], endPos[0]));
44 
45  //find max
46  const geo::TPCGeo& tpc = tcc.geom->TPC();
47  float mindis0 = FLT_MAX;
48  float mindis1 = FLT_MAX;
49  if (std::abs(startPos[1] - tpc.MinY()) < mindis0) mindis0 = std::abs(startPos[1] - tpc.MinY());
50  if (std::abs(startPos[1] - tpc.MaxY()) < mindis0) mindis0 = std::abs(startPos[1] - tpc.MaxY());
51  if (std::abs(startPos[2] - tpc.MinZ()) < mindis0) mindis0 = std::abs(startPos[2] - tpc.MinZ());
52  if (std::abs(startPos[2] - tpc.MaxZ()) < mindis0) mindis0 = std::abs(startPos[2] - tpc.MaxZ());
53  if (std::abs(endPos[1] - tpc.MinY()) < mindis1) mindis1 = std::abs(endPos[1] - tpc.MinY());
54  if (std::abs(endPos[1] - tpc.MaxY()) < mindis1) mindis1 = std::abs(endPos[1] - tpc.MaxY());
55  if (std::abs(endPos[2] - tpc.MinZ()) < mindis1) mindis1 = std::abs(endPos[2] - tpc.MinZ());
56  if (std::abs(endPos[2] - tpc.MaxZ()) < mindis1) mindis1 = std::abs(endPos[2] - tpc.MaxZ());
57  slc.crt.cr_pfpyzmindis.push_back(mindis0 + mindis1);
58 
59  if (slc.crt.cr_pfpxmin.back() < -2 || slc.crt.cr_pfpxmax.back() > 260 ||
60  slc.crt.cr_pfpyzmindis.back() < 30) {
61  pfp.CosmicScore = 1.;
62  }
63  else
64  pfp.CosmicScore = 0;
65  }
TCConfig tcc
Definition: DataStructs.cxx:9
Geometry information for a single TPC.
Definition: TPCGeo.h:33
constexpr auto abs(T v)
Returns the absolute value of the argument.
int GetOrigin(detinfo::DetectorClocksData const &clockData, TCSlice &slc, PFPStruct &pfp)
Definition: TCCR.cxx:68
double MinZ() const
Returns the world z coordinate of the start of the box.
const geo::GeometryCore * geom
Definition: DataStructs.h:567
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:599
save cosmic ray tree
Definition: DataStructs.h:529
double MaxZ() const
Returns the world z coordinate of the end of the box.
TPCGeo const & TPC(TPCID const &tpcid=details::tpc_zero) const
Returns the specified TPC.
Definition: GeometryCore.h:448
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 14 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().

15  {
16  if (!tcc.modes[kSaveShowerTree]) return;
17  if (tjList.empty()) return;
18  int stageNum = GetStageNum(stv, stageName);
19 
20  // get the CTP from the first tj
21  CTP_t inCTP = slc.tjs[tjList[0][0] - 1].CTP;
22  for (unsigned short it1 = 0; it1 < slc.tjs.size(); ++it1) {
23  Trajectory& tj1 = slc.tjs[it1];
24  if (tj1.CTP != inCTP) continue;
25  if (tj1.AlgMod[kKilled]) continue;
26 
27  SaveTjInfoStuff(slc, tj1, stageNum);
28 
29  int trajID = tj1.ID;
30  bool inShower = false;
31 
32  for (size_t l1 = 0; l1 < tjList.size(); ++l1) {
33  if (inShower) break;
34  for (size_t l2 = 0; l2 < tjList[l1].size(); ++l2) {
35 
36  if (trajID == tjList[l1][l2]) {
37  stv.ShowerID.back() = l1;
38  inShower = true;
39  break;
40  }
41  } // end list loop 2
42  } // end list loop 1
43  } // end tjs loop
44  // add meaningless envelope to list for counting purposes
45  // envelopes are defined once DefineShower is called
46  // fill four times, one for each side of polygon
47  for (int i = 0; i < 8; i++) {
48  stv.Envelope.push_back(-999);
49  stv.EnvStage.push_back(stageNum);
50  stv.EnvPlane.push_back(-1);
51  stv.EnvShowerID.push_back(-1);
52  }
53 
54  } // SaveTjInfo (tjlist)
std::vector< int > EnvStage
Definition: DataStructs.h:402
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< int > ShowerID
Definition: DataStructs.h:394
ShowerTreeVars stv
Definition: DataStructs.cxx:11
save shower tree
Definition: DataStructs.h:531
std::vector< float > Envelope
Definition: DataStructs.h:400
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
std::vector< int > EnvPlane
Definition: DataStructs.h:401
unsigned int CTP_t
Definition: DataStructs.h:45
void SaveTjInfoStuff(TCSlice &slc, Trajectory &tj, int stageNum)
Definition: TCShTree.cxx:144
int GetStageNum(ShowerTreeVars &stv, std::string stageName)
Definition: TCShTree.cxx:200
std::vector< int > EnvShowerID
Definition: DataStructs.h:403
void tca::SaveTjInfo ( TCSlice slc,
const ShowerStruct ss,
std::string  stageName 
)

Definition at line 56 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.

57  {
58  if (!tcc.modes[kSaveShowerTree]) return;
59  int stageNum = GetStageNum(stv, stageName);
60 
61  // killed shower?
62  if (ss.ID == 0) return;
63 
64  bool noMatch = true;
65 
66  for (unsigned short it1 = 0; it1 < slc.tjs.size(); ++it1) {
67 
68  Trajectory& tj1 = slc.tjs[it1];
69 
70  if (tj1.AlgMod[kKilled]) continue;
71 
72  int trajID = tj1.ID;
73 
74  // check if this tj has already been added to the list
75  // for this particular stage and plane
76  int tjIndex = -1;
77  bool isShowerTj = false;
78  for (size_t i = 0; i < stv.TjID.size(); ++i) {
79  if (stv.StageNum.at(i) != (int)stageNum) continue;
80  if (stv.PlaneNum.at(i) != (short)DecodeCTP(ss.CTP).Plane) continue;
81 
82  if (stv.TjID.at(i) == trajID) {
83  tjIndex = i;
84  if (stv.IsShowerTj.at(tjIndex) == 1) isShowerTj = true;
85  //beenDoneBefore = true;
86  break;
87  }
88  }
89 
90  if (isShowerTj) continue;
91  if (tjIndex == -1) SaveTjInfoStuff(slc, tj1, stageNum);
92 
93  for (size_t i = 0; i < ss.TjIDs.size(); ++i) {
94  if (trajID == ss.TjIDs[i]) {
95  noMatch = false;
96  if (tjIndex == -1)
97  stv.ShowerID.back() = ss.ID;
98  else
99  stv.ShowerID.at(tjIndex) = ss.ID;
100  }
101 
102  if (it1 == (ss.ShowerTjID - 1))
103  stv.IsShowerTj.back() = 1;
104  else if (tj1.AlgMod[kShowerTj])
105  stv.IsShowerTj.back() = 1; // this is a better check
106  // check if tj is shower parent. if so, add to ttree
107  // and mark parent flag
108  if (trajID == ss.ParentID) {
109  if (tjIndex == -1) {
110  stv.ShowerID.back() = ss.ID;
111  stv.IsShowerParent.back() = 1;
112  }
113  else {
114  stv.ShowerID.at(tjIndex) = ss.ID;
115  stv.IsShowerParent.at(tjIndex) = 1;
116  }
117  break;
118  }
119  } // ss TjID loop
120  } // end tjs loop
121 
122  if (noMatch) return;
123 
124  // add envelope information to showertreevars
125  geo::PlaneID iPlnID = DecodeCTP(ss.CTP);
126 
127  for (int i = 0; i < 8; i++) {
128  stv.EnvStage.push_back(stageNum);
129  stv.EnvPlane.push_back(iPlnID.Plane);
130  stv.EnvShowerID.push_back(ss.ID);
131  }
132 
133  stv.Envelope.push_back(ss.Envelope[0][0]);
134  stv.Envelope.push_back(ss.Envelope[0][1] / tcc.unitsPerTick);
135  stv.Envelope.push_back(ss.Envelope[1][0]);
136  stv.Envelope.push_back(ss.Envelope[1][1] / tcc.unitsPerTick);
137  stv.Envelope.push_back(ss.Envelope[2][0]);
138  stv.Envelope.push_back(ss.Envelope[2][1] / tcc.unitsPerTick);
139  stv.Envelope.push_back(ss.Envelope[3][0]);
140  stv.Envelope.push_back(ss.Envelope[3][1] / tcc.unitsPerTick);
141 
142  } // SaveTjInfo (cots)
std::vector< int > EnvStage
Definition: DataStructs.h:402
std::vector< int > IsShowerParent
Definition: DataStructs.h:395
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
std::vector< int > ShowerID
Definition: DataStructs.h:394
ShowerTreeVars stv
Definition: DataStructs.cxx:11
save shower tree
Definition: DataStructs.h:531
std::vector< int > TjID
Definition: DataStructs.h:392
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
std::vector< float > Envelope
Definition: DataStructs.h:400
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
std::vector< int > EnvPlane
Definition: DataStructs.h:401
std::vector< int > StageNum
Definition: DataStructs.h:396
void SaveTjInfoStuff(TCSlice &slc, Trajectory &tj, int stageNum)
Definition: TCShTree.cxx:144
geo::PlaneID DecodeCTP(CTP_t CTP)
int GetStageNum(ShowerTreeVars &stv, std::string stageName)
Definition: TCShTree.cxx:200
std::vector< int > EnvShowerID
Definition: DataStructs.h:403
std::vector< int > IsShowerTj
Definition: DataStructs.h:393
std::vector< short > PlaneNum
Definition: DataStructs.h:390
void tca::SaveTjInfoStuff ( TCSlice slc,
Trajectory tj,
int  stageNum 
)

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

145  {
146  if (!tcc.modes[kSaveShowerTree]) return;
147 
148  TrajPoint& beginPoint = tj.Pts[tj.EndPt[0]];
149  TrajPoint& endPoint = tj.Pts[tj.EndPt[1]];
150 
151  stv.BeginWir.push_back(std::nearbyint(beginPoint.Pos[0]));
152  stv.BeginTim.push_back(std::nearbyint(beginPoint.Pos[1] / tcc.unitsPerTick));
153  stv.BeginAng.push_back(beginPoint.Ang);
154  stv.BeginChg.push_back(beginPoint.Chg);
155  stv.BeginVtx.push_back(tj.VtxID[0]);
156 
157  stv.EndWir.push_back(std::nearbyint(endPoint.Pos[0]));
158  stv.EndTim.push_back(std::nearbyint(endPoint.Pos[1] / tcc.unitsPerTick));
159  stv.EndAng.push_back(endPoint.Ang);
160  stv.EndChg.push_back(endPoint.Chg);
161  stv.EndVtx.push_back(tj.VtxID[1]);
162 
163  stv.MCSMom.push_back(tj.MCSMom);
164  stv.TjID.push_back(tj.ID);
165  stv.IsShowerTj.push_back(-1);
166 
167  stv.ShowerID.push_back(-1);
168  stv.IsShowerParent.push_back(-1);
169  stv.StageNum.push_back(stageNum);
170  stv.nStages = stageNum;
171  geo::PlaneID iPlnID = DecodeCTP(tj.CTP);
172  stv.PlaneNum.push_back(iPlnID.Plane);
173 
174  stv.nPlanes = slc.nPlanes;
175 
176  } // SaveTjInfoStuff
std::vector< int > IsShowerParent
Definition: DataStructs.h:395
std::vector< float > EndWir
Definition: DataStructs.h:382
std::vector< float > EndAng
Definition: DataStructs.h:384
std::vector< float > BeginTim
Definition: DataStructs.h:378
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< float > BeginAng
Definition: DataStructs.h:379
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
std::vector< float > EndTim
Definition: DataStructs.h:383
std::vector< int > ShowerID
Definition: DataStructs.h:394
ShowerTreeVars stv
Definition: DataStructs.cxx:11
save shower tree
Definition: DataStructs.h:531
std::vector< int > TjID
Definition: DataStructs.h:392
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
std::vector< short > BeginVtx
Definition: DataStructs.h:381
std::vector< short > EndVtx
Definition: DataStructs.h:386
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
std::vector< float > BeginChg
Definition: DataStructs.h:380
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
std::vector< short > MCSMom
Definition: DataStructs.h:388
std::vector< int > StageNum
Definition: DataStructs.h:396
unsigned short nPlanes
Definition: DataStructs.h:406
std::vector< float > BeginWir
Definition: DataStructs.h:377
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< float > EndChg
Definition: DataStructs.h:385
std::vector< int > IsShowerTj
Definition: DataStructs.h:393
std::vector< short > PlaneNum
Definition: DataStructs.h:390
void tca::ScoreVertices ( TCSlice slc)

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

2133  {
2134  // reset all 3D vertex, 2D vertex and Tj high-score vertex bits in tpcid
2135 
2136  // reset the 2D vertex status bits
2137  for (auto& vx : slc.vtxs) {
2138  if (vx.ID == 0) continue;
2139  vx.Stat[kHiVx3Score] = false;
2140  } // vx
2141  // and the tj bits
2142  for (auto& tj : slc.tjs) {
2143  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
2144  tj.AlgMod[kTjHiVx3Score] = false;
2145  } // tj
2146  // Score the 2D vertices
2147  for (auto& vx : slc.vtxs) {
2148  if (vx.ID == 0) continue;
2149  SetVx2Score(slc, vx);
2150  } // vx
2151  // Score the 3D vertices
2152  for (auto& vx3 : slc.vtx3s) {
2153  if (vx3.ID == 0) continue;
2154  SetVx3Score(slc, vx3);
2155  } // vx3
2156  } // ScoreVertices
matched to a high-score 3D vertex
Definition: DataStructs.h:90
void SetVx3Score(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2225
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2255
bool tca::SectionStartEnd ( const PFPStruct pfp,
unsigned short  sfIndex,
unsigned short &  startPt,
unsigned short &  endPt 
)

Definition at line 3274 of file PFPUtils.cxx.

References tca::PFPStruct::SectionFits, and tca::PFPStruct::TP3Ds.

Referenced by DotProd(), and PrintTP3Ds().

3278  {
3279  // this assumes that the TP3Ds vector is sorted
3280  startPt = USHRT_MAX;
3281  endPt = USHRT_MAX;
3282  if (sfIndex >= pfp.SectionFits.size()) return false;
3283 
3284  bool first = true;
3285  for (std::size_t ipt = 0; ipt < pfp.TP3Ds.size(); ++ipt) {
3286  auto& tp3d = pfp.TP3Ds[ipt];
3287  if (tp3d.SFIndex < sfIndex) continue;
3288  if (first) {
3289  first = false;
3290  startPt = ipt;
3291  } // first
3292  if (tp3d.SFIndex > sfIndex) break;
3293  endPt = ipt;
3294  } // ipt
3295  return true;
3296 
3297  } // SectionStartEnd
void tca::SetAngleCode ( TrajPoint tp)

Definition at line 765 of file Utils.cxx.

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

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

766  {
767  unsigned short ar = AngleRange(tp.Ang);
768  if (ar == tcc.angleRanges.size() - 1) {
769  // Very large angle
770  tp.AngleCode = 2;
771  }
772  else if (tcc.angleRanges.size() > 2 && ar == tcc.angleRanges.size() - 2) {
773  // Large angle
774  tp.AngleCode = 1;
775  }
776  else {
777  // Small angle
778  tp.AngleCode = 0;
779  }
780 
781  } // SetAngleCode
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< float > angleRanges
list of max angles for each angle range
Definition: DataStructs.h:560
unsigned short AngleRange(float angle)
Definition: Utils.cxx:784
template<typename T >
std::vector< T > tca::SetDifference ( const std::vector< T > &  set1,
const std::vector< T > &  set2 
)

Definition at line 407 of file Utils.h.

Referenced by DotProd(), and Reconcile3D().

408  {
409  // returns the elements of set1 and set2 that are different
410  std::vector<T> different;
411  if (set1.empty() && set2.empty()) return different;
412  if (!set1.empty() && set2.empty()) return set1;
413  if (set1.empty() && !set2.empty()) return set2;
414  for (auto element1 : set1) {
415  // check for a common element
416  if (std::find(set2.begin(), set2.end(), element1) != set2.end()) continue;
417  // check for a duplicate
418  if (std::find(different.begin(), different.end(), element1) != different.end()) continue;
419  different.push_back(element1);
420  } // element1
421  for (auto element2 : set2) {
422  // check for a common element
423  if (std::find(set1.begin(), set1.end(), element2) != set1.end()) continue;
424  // check for a duplicate
425  if (std::find(different.begin(), different.end(), element2) != different.end()) continue;
426  different.push_back(element2);
427  } // element1
428  return different;
429  } // SetDifference
void tca::SetEndPoints ( Trajectory tj)

Definition at line 3330 of file Utils.cxx.

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

Referenced by AddHits(), AddLAHits(), CheckHiMultEndHits(), CheckHiMultUnusedHits(), CheckTraj(), ChkBegin(), ChkChgAsymmetry(), ChkStopEndPts(), DotProd(), FixBegin(), Forecast(), GottaKink(), IsGhost(), MaskedHitsOK(), MaskTrajEndPoints(), MergeAndStore(), ReversePropagate(), ReverseTraj(), SplitTraj(), StepAway(), StopShort(), StoreTraj(), TrimEndPts(), and UpdateTraj().

3331  {
3332  // Find the first (last) TPs, EndPt[0] (EndPt[1], that have charge
3333 
3334  // don't mess with showerTjs or halo tjs
3335  if (tj.AlgMod[kShowerTj] || tj.AlgMod[kHaloTj]) return;
3336 
3337  tj.EndPt[0] = 0;
3338  tj.EndPt[1] = 0;
3339  if (tj.Pts.size() == 0) return;
3340 
3341  // check the end point pointers
3342  for (unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) {
3343  if (tj.Pts[ipt].Chg != 0) {
3344  tj.EndPt[0] = ipt;
3345  break;
3346  }
3347  }
3348  for (unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
3349  unsigned short ipt = tj.Pts.size() - 1 - ii;
3350  if (tj.Pts[ipt].Chg != 0) {
3351  tj.EndPt[1] = ipt;
3352  break;
3353  }
3354  }
3355  } // SetEndPoints
void tca::SetHighScoreBits ( TCSlice slc,
Vtx3Store vx3 
)

Definition at line 2177 of file TCVertex.cxx.

References util::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().

2178  {
2179  // Sets the tj and 2D vertex score bits to true
2180 
2181  if (vx3.ID == 0) return;
2182 
2183  for (unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
2184  if (vx3.Vx2ID[ipl] <= 0) continue;
2185  VtxStore& vx2 = slc.vtxs[vx3.Vx2ID[ipl] - 1];
2186  vx2.Stat[kHiVx3Score] = false;
2187  // transfer this to all attached tjs and vertices attached to those tjs
2188  std::vector<int> tjlist = GetVtxTjIDs(slc, vx2);
2189  std::vector<int> vxlist;
2190  while (true) {
2191  // tag Tjs and make a list of attached vertices whose high-score
2192  // bit needs to be set
2193  vxlist.clear();
2194  for (auto tjid : tjlist) {
2195  auto& tj = slc.tjs[tjid - 1];
2196  tj.AlgMod[kTjHiVx3Score] = true;
2197  for (unsigned short end = 0; end < 2; ++end) {
2198  if (tj.VtxID[end] == 0) continue;
2199  auto& vx2 = slc.vtxs[tj.VtxID[end] - 1];
2200  if (vx2.Stat[kHiVx3Score]) continue;
2201  vx2.Stat[kHiVx3Score] = true;
2202  vxlist.push_back(vx2.ID);
2203  } // end
2204  } // tjid
2205 
2206  if (vxlist.empty()) break;
2207  // re-build tjlist using vxlist
2208  std::vector<int> newtjlist;
2209  for (auto vxid : vxlist) {
2210  auto& vx2 = slc.vtxs[vxid - 1];
2211  auto tmp = GetVtxTjIDs(slc, vx2);
2212  for (auto tjid : tmp) {
2213  if (std::find(tjlist.begin(), tjlist.end(), tjid) == tjlist.end())
2214  newtjlist.push_back(tjid);
2215  } // tjid
2216  } // vxid
2217  if (newtjlist.empty()) break;
2218  tjlist = newtjlist;
2219  } // true
2220  } // ipl
2221 
2222  } // SetHighScoreBits
matched to a high-score 3D vertex
Definition: DataStructs.h:90
Float_t tmp
Definition: plot.C:35
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:2823
template<typename T >
std::vector< T > tca::SetIntersection ( const std::vector< T > &  set1,
const std::vector< T > &  set2 
)

Definition at line 385 of file Utils.h.

Referenced by CompleteIncompleteShower(), DotProd(), GetAssns(), MergeNearby2DShowers(), and Reconcile3D().

386  {
387  // returns a vector containing the elements of set1 and set2 that are common. This function
388  // is a replacement for std::set_intersection which fails in the following situation:
389  // set1 = {11 12 17 18} and set2 = {6 12 18}
390  // There is no requirement that the elements be sorted, unlike std::set_intersection
391  std::vector<T> shared;
392 
393  if (set1.empty()) return shared;
394  if (set2.empty()) return shared;
395  for (auto element1 : set1) {
396  // check for a common element
397  if (std::find(set2.begin(), set2.end(), element1) == set2.end()) continue;
398  // check for a duplicate
399  if (std::find(shared.begin(), shared.end(), element1) != shared.end()) continue;
400  shared.push_back(element1);
401  } // element1
402  return shared;
403  } // SetIntersection
bool tca::SetMag ( Vector3_t v1,
double  mag 
)

Definition at line 2570 of file PFPUtils.cxx.

References den.

Referenced by DotProd(), FindAlongTrans(), MakeSmallAnglePFP(), PointDirection(), and UpdateShower().

2571  {
2572  double den = v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2];
2573  if (den == 0) return false;
2574  den = sqrt(den);
2575 
2576  v1[0] *= mag / den;
2577  v1[1] *= mag / den;
2578  v1[2] *= mag / den;
2579  return true;
2580  } // SetMag
Float_t den
Definition: plot.C:35
bool tca::SetMag ( Vector2_t v1,
double  mag 
)

Definition at line 3269 of file Utils.cxx.

References den.

3270  {
3271  double den = v1[0] * v1[0] + v1[1] * v1[1];
3272  if (den == 0) return false;
3273  den = sqrt(den);
3274 
3275  v1[0] *= mag / den;
3276  v1[1] *= mag / den;
3277  return true;
3278  } // SetMag
Float_t den
Definition: plot.C:35
bool tca::SetParent ( detinfo::DetectorPropertiesData const &  detProp,
std::string  inFcnLabel,
TCSlice slc,
PFPStruct pfp,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 1815 of file TCShower.cxx.

References AddTj(), tca::ShowerStruct3D::ChgPos, tca::ShowerStruct3D::CotIDs, tca::TCSlice::cots, dir, DirAtEnd(), util::end(), FarEnd(), GetAssns(), tca::PFPStruct::ID, tca::ShowerStruct3D::ID, tca::TCSlice::ID, kShwrParent, MakeBareTP(), ParentFOM(), tca::ShowerStruct3D::ParentID, PosAtEnd(), tca::PFPStruct::TjIDs, tca::TCSlice::tjs, UpdateShower(), tca::TCSlice::vtx3s, tca::PFPStruct::Vx3ID, and tca::ShowerStruct3D::Vx3ID.

Referenced by FindParent().

1821  {
1822  // set the pfp as the parent of ss3. The calling function should do the error recovery
1823  if (pfp.ID == 0 || ss3.ID == 0) return false;
1824  if (ss3.CotIDs.empty()) return false;
1825 
1826  std::string fcnLabel = inFcnLabel + ".SP";
1827 
1828  for (auto cid : ss3.CotIDs) {
1829  auto& ss = slc.cots[cid - 1];
1830  auto& stj = slc.tjs[ss.ShowerTjID - 1];
1831  stj.VtxID[0] = 0;
1832  if (ss.ParentID > 0) {
1833  auto& oldParent = slc.tjs[ss.ParentID - 1];
1834  oldParent.AlgMod[kShwrParent] = false;
1835  ss.ParentID = 0;
1836  ss.ParentFOM = 10;
1837  } // remove old parents
1838  // add new parents
1839  for (auto tjid : pfp.TjIDs) {
1840  auto& tj = slc.tjs[tjid - 1];
1841  if (tj.CTP != ss.CTP) continue;
1842  if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tjid) == ss.TjIDs.end()) {
1843  // Add the tj but don't update yet
1844  if (!AddTj(fcnLabel, slc, tjid, ss, false, prt)) return false;
1845  } // parent not in ss
1846  // Don't define it to be the parent if it is short and the pfp projection in this plane is low
1847  auto pos = PosAtEnd(pfp, 0);
1848  auto dir = DirAtEnd(pfp, 0);
1849  auto tp = MakeBareTP(detProp, pos, dir, tj.CTP);
1850  unsigned short npts = tj.EndPt[1] - tj.EndPt[0] + 1;
1851  if (tp.Delta > 0.5 || npts > 20) {
1852  if (prt)
1853  mf::LogVerbatim("TC") << fcnLabel << " 3S" << ss3.ID << " parent P" << pfp.ID << " -> T"
1854  << tjid << " -> 2S" << ss.ID << " parent";
1855  }
1856  else {
1857  if (prt)
1858  mf::LogVerbatim("TC") << fcnLabel << " 3S" << ss3.ID << " parent P" << pfp.ID << " -> T"
1859  << tjid << " low projection in plane " << tp.Delta
1860  << ". Not a parent";
1861  continue;
1862  }
1863  ss.ParentID = tjid;
1864  ss.NeedsUpdate = true;
1865  // set the ss start vertex
1866  if (ss3.Vx3ID > 0) {
1867  auto& vx3 = slc.vtx3s[ss3.Vx3ID - 1];
1868  auto v2list = GetAssns(slc, "3V", vx3.ID, "2V");
1869  for (unsigned short end = 0; end < 2; ++end) {
1870  if (tj.VtxID[end] <= 0) continue;
1871  if (std::find(v2list.begin(), v2list.end(), tj.VtxID[end]) != v2list.end())
1872  stj.VtxID[0] = tj.VtxID[end];
1873  } // end
1874  } // ss3.Vx3ID > 0
1875  // and update
1876  if (!UpdateShower(fcnLabel, slc, ss, prt)) return false;
1877  } // tjid
1878  } // cid
1879  ss3.ParentID = pfp.ID;
1880 
1881  unsigned short pEnd = FarEnd(pfp, ss3.ChgPos);
1882  ss3.Vx3ID = pfp.Vx3ID[pEnd];
1883  float fom3D = ParentFOM(fcnLabel, slc, pfp, ss3, prt);
1884  for (auto cid : ss3.CotIDs)
1885  slc.cots[cid - 1].ParentFOM = fom3D;
1886 
1887  return true;
1888  } // SetParent
bool AddTj(std::string inFcnLabel, TCSlice &slc, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1429
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3257
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1106
float ParentFOM(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, unsigned short &tjEnd, ShowerStruct &ss, float &tp1Sep, float &vx2Score, bool prt)
Definition: TCShower.cxx:2101
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const Point3_t &pos, CTP_t inCTP)
Definition: Utils.cxx:3928
unsigned short FarEnd(const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3300
std::vector< int > GetAssns(TCSlice const &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4704
TDirectory * dir
Definition: macro.C:5
Vector3_t DirAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3249
void tca::SetPDGCode ( TCSlice slc,
unsigned short  itj 
)

Definition at line 4219 of file Utils.cxx.

References tca::TCSlice::tjs.

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

4220  {
4221  if (itj > slc.tjs.size() - 1) return;
4222  SetPDGCode(slc, slc.tjs[itj]);
4223  }
void SetPDGCode(TCSlice const &slc, Trajectory &tj)
Definition: Utils.cxx:4226
void tca::SetPDGCode ( TCSlice const &  slc,
Trajectory tj 
)

Definition at line 4226 of file Utils.cxx.

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

4227  {
4228  // Sets the PDG code for the supplied trajectory. Note that the existing
4229  // PDG code is left unchanged if these cuts are not met
4230 
4231  short npwc = NumPtsWithCharge(slc, tj, false);
4232  if (npwc < 6) {
4233  tj.PDGCode = 0;
4234  return;
4235  }
4236 
4237  if (tj.Strategy[kStiffEl] && ElectronLikelihood(slc, tj) > tcc.showerTag[6]) {
4238  tj.PDGCode = 111;
4239  return;
4240  }
4241  if (tj.Strategy[kStiffMu]) {
4242  tj.PDGCode = 13;
4243  return;
4244  }
4245 
4246  if (tcc.showerTag[6] > 0 && ElectronLikelihood(slc, tj) > tcc.showerTag[6]) {
4247  tj.PDGCode = 11;
4248  return;
4249  }
4250 
4251  if (tcc.muonTag[0] <= 0) return;
4252  // Special handling of very long straight trajectories, e.g. uB cosmic rays
4253  bool isAMuon = (npwc > (unsigned short)tcc.muonTag[0] && tj.MCSMom > tcc.muonTag[1]);
4254  // anything really really long must be a muon
4255  if (npwc > 500) isAMuon = true;
4256  if (isAMuon) tj.PDGCode = 13;
4257 
4258  } // SetPDGCode
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:2080
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:549
float ElectronLikelihood(const TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:3144
std::vector< short > muonTag
Definition: DataStructs.h:546
use the stiff electron strategy
Definition: DataStructs.h:492
use the stiff muon strategy
Definition: DataStructs.h:493
bool tca::SetSection ( detinfo::DetectorPropertiesData const &  detProp,
PFPStruct pfp,
TP3D tp3d 
)

Definition at line 2752 of file PFPUtils.cxx.

References util::abs(), tca::TP3D::along, tca::TP3D::CTP, DecodeCTP(), tca::TP3D::Flags, tca::PFPStruct::Flags, kSmallAngle, kTP3DGood, MakeBareTP(), geo::WireReadoutGeom::Plane(), tca::TP3D::Pos, tca::PFPStruct::SectionFits, tca::TP3D::SFIndex, tcc, tca::TP3D::Wire, geo::PlaneGeo::WireCoordinate(), and tca::TCConfig::wireReadoutGeom.

Referenced by AddPointsInRange(), DotProd(), and Update().

2753  {
2754  // Determine which SectionFit this tp3d should reside in, then calculate
2755  // the 3D position and the distance from the center of the SectionFit
2756 
2757  if (tp3d.Wire < 0) return false;
2758  if (pfp.SectionFits.empty()) return false;
2759  if (pfp.SectionFits[0].Pos[0] == -10.0) return false;
2760  if (pfp.Flags[kSmallAngle]) return true;
2761 
2762  auto plnID = DecodeCTP(tp3d.CTP);
2763 
2764  if (pfp.SectionFits.size() == 1) { tp3d.SFIndex = 0; }
2765  else {
2766  // Find the section center that is closest to this point in the wire coordinate
2767  float best = 1E6;
2768  for (std::size_t sfi = 0; sfi < pfp.SectionFits.size(); ++sfi) {
2769  auto& sf = pfp.SectionFits[sfi];
2770  float sfWire =
2771  tcc.wireReadoutGeom->Plane(plnID).WireCoordinate(geo::Point_t{0, sf.Pos[1], sf.Pos[2]});
2772  float sep = std::abs(sfWire - tp3d.Wire);
2773  if (sep < best) {
2774  best = sep;
2775  tp3d.SFIndex = sfi;
2776  }
2777  } // sfi
2778  } // pfp.SectionFits.size() > 1
2779  auto& sf = pfp.SectionFits[tp3d.SFIndex];
2780  auto plnTP = MakeBareTP(detProp, sf.Pos, sf.Dir, tp3d.CTP);
2781  // the number of wires relative to the SectionFit center
2782  double dw = tp3d.Wire - plnTP.Pos[0];
2783  // dt/dW was stored in DeltaRMS
2784  double t = dw * plnTP.DeltaRMS;
2785  // define the 3D position
2786  for (unsigned short xyz = 0; xyz < 3; ++xyz)
2787  tp3d.Pos[xyz] = sf.Pos[xyz] + t * sf.Dir[xyz];
2788  tp3d.along = t;
2789  tp3d.Flags[kTP3DGood] = true;
2790  return true;
2791  } // SetSection
const geo::WireReadoutGeom * wireReadoutGeom
Definition: DataStructs.h:568
double WireCoordinate(Point_t const &point) const
Returns the coordinate of the point on the plane, in wire units.
Definition: PlaneGeo.h:704
TCConfig tcc
Definition: DataStructs.cxx:9
constexpr auto abs(T v)
Returns the absolute value of the argument.
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const Point3_t &pos, CTP_t inCTP)
Definition: Utils.cxx:3928
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:180
geo::PlaneID DecodeCTP(CTP_t CTP)
PlaneGeo const & Plane(TPCID const &tpcid, View_t view) const
Returns the specified wire.
void tca::SetStrategy ( TCSlice slc,
Trajectory tj 
)

Definition at line 352 of file StepUtils.cxx.

References 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().

353  {
354  // Determine if the tracking strategy is appropriate and make some tweaks if it isn't
355  if (tjfs.empty()) return;
356  // analyze the last forecast
357  auto& tjf = tjfs[tjfs.size() - 1];
358 
359  auto& lastTP = tj.Pts[tj.EndPt[1]];
360  // Stay in Slowing strategy if we are in it and reduce the number of points fit further
361  if (tj.Strategy[kSlowing]) {
362  lastTP.NTPsFit = 5;
363  return;
364  }
365 
366  float npwc = NumPtsWithCharge(slc, tj, false);
367  // Keep using the StiffMu strategy if the tj is long and MCSMom is high
368  if (tj.Strategy[kStiffMu] && tj.MCSMom > 800 && npwc > 200) {
369  if (tcc.dbgStp) mf::LogVerbatim("TC") << "SetStrategy: Keep using the StiffMu strategy";
370  return;
371  }
372  bool tkLike = (tjf.outlook < 1.5);
373  // A showering-electron-like trajectory
374  bool chgIncreasing = (tjf.chgSlope > 0);
375  // A showering-electron-like trajectory
376  bool shLike = (tjf.outlook > 2 && chgIncreasing);
377  if (!shLike) shLike = tjf.showerLikeFraction > 0.5;
378  float momRat = 0;
379  if (tj.MCSMom > 0) momRat = (float)tjf.MCSMom / (float)tj.MCSMom;
380  if (tcc.dbgStp) {
381  mf::LogVerbatim myprt("TC");
382  myprt << "SetStrategy: npwc " << npwc << " outlook " << tjf.outlook;
383  myprt << " tj MCSMom " << tj.MCSMom << " forecast MCSMom " << tjf.MCSMom;
384  myprt << " momRat " << std::fixed << std::setprecision(2) << momRat;
385  myprt << " tkLike? " << tkLike << " shLike? " << shLike;
386  myprt << " chgIncreasing? " << chgIncreasing;
387  myprt << " leavesBeforeEnd? " << tjf.leavesBeforeEnd << " endBraggPeak? " << tjf.endBraggPeak;
388  myprt << " nextForecastUpdate " << tjf.nextForecastUpdate;
389  }
390  if (tjf.outlook < 0) return;
391  // Look for a long clean muon in the forecast
392  bool stiffMu = (tkLike && tjf.MCSMom > 600 && tjf.nextForecastUpdate > 100);
393  if (stiffMu) {
394  if (tcc.dbgStp)
395  mf::LogVerbatim("TC")
396  << "SetStrategy: High MCSMom, long forecast. Use the StiffMu strategy";
397  tj.Strategy.reset();
398  tj.Strategy[kStiffMu] = true;
399  return;
400  } // StiffMu
401  bool notStiff = (!tj.Strategy[kStiffEl] && !tj.Strategy[kStiffMu]);
402  if (notStiff && !shLike && tj.MCSMom < 100 && tjf.MCSMom < 100 && chgIncreasing) {
403  if (tcc.dbgStp)
404  mf::LogVerbatim("TC") << "SetStrategy: Low MCSMom. Use the Slowing Tj strategy";
405  tj.Strategy.reset();
406  tj.Strategy[kSlowing] = true;
407  lastTP.NTPsFit = 5;
408  return;
409  } // Low MCSMom
410  if (notStiff && !shLike && tj.MCSMom < 200 && momRat < 0.7 && chgIncreasing) {
411  if (tcc.dbgStp)
412  mf::LogVerbatim("TC")
413  << "SetStrategy: Low MCSMom & low momRat. Use the Slowing Tj strategy";
414  tj.Strategy.reset();
415  tj.Strategy[kSlowing] = true;
416  lastTP.NTPsFit = 5;
417  return;
418  } // low MCSMom
419  if (!tjf.leavesBeforeEnd && tjf.endBraggPeak) {
420  if (tcc.dbgStp)
421  mf::LogVerbatim("TC") << "SetStrategy: Found a Bragg peak. Use the Slowing Tj strategy";
422  tj.Strategy.reset();
423  tj.Strategy[kSlowing] = true;
424  lastTP.NTPsFit = 5;
425  return;
426  } // tracklike with Bragg peak
427  if (tkLike && tjf.nextForecastUpdate > 100 && tjf.leavesBeforeEnd && tjf.MCSMom < 500) {
428  // A long track-like trajectory that has many points fit and the outlook is track-like and
429  // it leaves the forecast polygon. Don't change the strategy but decrease the number of points fit
430  lastTP.NTPsFit /= 2;
431  if (tcc.dbgStp)
432  mf::LogVerbatim("TC")
433  << "SetStrategy: Long track-like wandered out of forecast envelope. Reduce NTPsFit to "
434  << lastTP.NTPsFit;
435  return;
436  } // fairly long and leaves the side
437  // a track-like trajectory that has high MCSMom in the forecast and hits a shower
438  if (tkLike && tjf.MCSMom > 600 && (tjf.foundShower || tjf.chgFitChiDOF > 20)) {
439  if (tcc.dbgStp)
440  mf::LogVerbatim("TC") << "SetStrategy: high MCSMom " << tjf.MCSMom
441  << " and a shower ahead. Use the StiffEl strategy";
442  tj.Strategy.reset();
443  tj.Strategy[kStiffEl] = true;
444  // we think we know the direction (towards the shower) so startEnd is 0
445  tj.StartEnd = 0;
446  return;
447  } // Stiff electron
448  if (shLike && !tjf.leavesBeforeEnd) {
449  if (tcc.dbgStp)
450  mf::LogVerbatim("TC") << "SetStrategy: Inside a shower. Use the StiffEl strategy";
451  tj.Strategy.reset();
452  tj.Strategy[kStiffEl] = true;
453  // we think we know the direction (towards the shower) so startEnd is 0
454  tj.StartEnd = 0;
455  return;
456  }
457  } // SetStrategy
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
use the slowing-down strategy
Definition: DataStructs.h:494
std::vector< TjForecast > tjfs
Definition: DataStructs.cxx:10
use the stiff electron strategy
Definition: DataStructs.h:492
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
use the stiff muon strategy
Definition: DataStructs.h:493
void tca::SetTPEnvironment ( TCSlice slc,
CTP_t  inCTP 
)

Definition at line 3531 of file Utils.cxx.

References DecodeCTP(), FindCloseHits(), kAllHits, kEnvNearMuon, kKilled, geo::PlaneID::Plane, tca::TCSlice::slHits, and tca::TCSlice::tjs.

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

3532  {
3533  // This function is called after tj reconstruction is completed to set TP Environment
3534  // bits that are dependent on reconstruction, just kEnvNearMuon for now. This bit is
3535  // set for all TPs that are within 5 wire-equivalents of a muon
3536 
3537  std::array<int, 2> wireWindow;
3538  Point2_t timeWindow;
3539  unsigned short plane = DecodeCTP(inCTP).Plane;
3540  //
3541  float delta = 5;
3542 
3543  for (auto& mutj : slc.tjs) {
3544  if (mutj.AlgMod[kKilled]) continue;
3545  if (mutj.CTP != inCTP) continue;
3546  if (mutj.PDGCode != 13) continue;
3547  unsigned short nnear = 0;
3548  for (unsigned short ipt = mutj.EndPt[0]; ipt <= mutj.EndPt[1]; ++ipt) {
3549  auto& tp = mutj.Pts[ipt];
3550  wireWindow[0] = tp.Pos[0];
3551  wireWindow[1] = tp.Pos[0];
3552  timeWindow[0] = tp.Pos[1] - delta;
3553  timeWindow[1] = tp.Pos[1] + delta;
3554  // get a list of all hits in this region
3555  bool hitsNear;
3556  auto closeHits =
3557  FindCloseHits(slc, wireWindow, timeWindow, plane, kAllHits, true, hitsNear);
3558  if (closeHits.empty()) continue;
3559  for (auto iht : closeHits) {
3560  auto inTraj = slc.slHits[iht].InTraj;
3561  if (inTraj <= 0) continue;
3562  if (inTraj == mutj.ID) continue;
3563  auto& dtj = slc.tjs[inTraj - 1];
3564  if (dtj.PDGCode == 13) continue;
3565  for (unsigned short jpt = dtj.EndPt[0]; jpt <= dtj.EndPt[1]; ++jpt) {
3566  auto& dtp = dtj.Pts[jpt];
3567  if (std::find(dtp.Hits.begin(), dtp.Hits.end(), iht) == dtp.Hits.end()) continue;
3568  dtp.Environment[kEnvNearMuon] = true;
3569  ++nnear;
3570  } // jpt
3571  } // iht
3572  } // ipt
3573  } // mutj
3574  } // SetTPEnvironment
std::array< float, 2 > Point2_t
Definition: DataStructs.h:41
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
geo::PlaneID DecodeCTP(CTP_t CTP)
bool FindCloseHits(TCSlice const &slc, TrajPoint &tp, float const maxDelta, HitStatus_t hitRequest)
Definition: Utils.cxx:2837
void tca::SetVx2Score ( TCSlice slc)

Definition at line 2246 of file TCVertex.cxx.

References tca::TCSlice::vtxs.

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

2247  {
2248  // A version that sets the score of the last added vertex
2249  if (slc.vtxs.empty()) return;
2250  auto& vx2 = slc.vtxs[slc.vtxs.size() - 1];
2251  SetVx2Score(slc, vx2);
2252  } // SetVx2Score
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2255
void tca::SetVx2Score ( TCSlice slc,
VtxStore vx2 
)

Definition at line 2255 of file TCVertex.cxx.

References tca::Trajectory::AlgMod, ChgFracNearPos(), tca::Trajectory::ChgRMS, tca::DebugStuff::CTP, tca::VtxStore::CTP, tca::TCConfig::dbg2V, tca::TCConfig::dbgSlc, debug, DeltaAngle(), tca::Trajectory::EndFlag, tca::Trajectory::EndPt, GetVtxTjIDs(), tca::VtxStore::ID, if(), kBragg, kJunkTj, kShowerLike, kShowerTj, tca::Trajectory::MCSMom, tca::Trajectory::PDGCode, tca::VtxStore::Pos, tca::VtxStore::PosErr, Print2V(), tca::Trajectory::Pts, tca::VtxStore::Score, sum, tcc, tca::VtxStore::TjChgFrac, tca::TCSlice::tjs, tca::VtxStore::Topo, tca::TCConfig::vtx2DCuts, tca::TCSlice::vtx3s, tca::Trajectory::VtxID, tca::TCConfig::vtxScoreWeights, and tca::VtxStore::Vx3ID.

2256  {
2257  // Calculate the 2D vertex score
2258  if (vx2.ID == 0) return;
2259 
2260  // Don't score vertices from CheckTrajBeginChg, MakeJunkVertices or Neutral vertices. Set to the minimum
2261  if (vx2.Topo == 8 || vx2.Topo == 9 || vx2.Topo == 11 || vx2.Topo == 12) {
2262  vx2.Score = tcc.vtx2DCuts[7] + 0.1;
2263  auto vtxTjID = GetVtxTjIDs(slc, vx2);
2264  vx2.TjChgFrac = ChgFracNearPos(slc, vx2.Pos, vtxTjID);
2265  return;
2266  }
2267 
2268  // Cuts on Tjs attached to vertices
2269  constexpr float maxChgRMS = 0.25;
2270  constexpr float momBin = 50;
2271 
2272  vx2.Score = -1000;
2273  vx2.TjChgFrac = 0;
2274  if (vx2.ID == 0) return;
2275  if (tcc.vtxScoreWeights.size() < 4) return;
2276 
2277  auto vtxTjIDs = GetVtxTjIDs(slc, vx2);
2278  if (vtxTjIDs.empty()) return;
2279 
2280  // Vertex position error
2281  float vpeScore = -tcc.vtxScoreWeights[0] * (vx2.PosErr[0] + vx2.PosErr[1]);
2282 
2283  unsigned short m3Dcnt = 0;
2284  if (vx2.Vx3ID > 0) {
2285  m3Dcnt = 1;
2286  // Add another if the 3D vertex is complete
2287  unsigned short ivx3 = vx2.Vx3ID - 1;
2288  if (slc.vtx3s[ivx3].Wire < 0) m3Dcnt = 2;
2289  }
2290  float m3DScore = tcc.vtxScoreWeights[1] * m3Dcnt;
2291 
2292  vx2.TjChgFrac = ChgFracNearPos(slc, vx2.Pos, vtxTjIDs);
2293  float cfScore = tcc.vtxScoreWeights[2] * vx2.TjChgFrac;
2294 
2295  // Define a weight for each Tj
2296  std::vector<int> tjids;
2297  std::vector<float> tjwts;
2298  unsigned short cnt13 = 0;
2299  for (auto tjid : vtxTjIDs) {
2300  Trajectory& tj = slc.tjs[tjid - 1];
2301  // Feb 22 Ignore short Tjs and junk tjs
2302  if (tj.AlgMod[kJunkTj]) continue;
2303  unsigned short lenth = tj.EndPt[1] - tj.EndPt[0] + 1;
2304  if (lenth < 3) continue;
2305  float wght = (float)tj.MCSMom / momBin;
2306  // weight by the first tagged muon
2307  if (tj.PDGCode == 13) {
2308  ++cnt13;
2309  if (cnt13 == 1) wght *= 2;
2310  }
2311  // weight by charge rms
2312  if (tj.ChgRMS < maxChgRMS) ++wght;
2313  // Shower Tj
2314  if (tj.AlgMod[kShowerTj]) ++wght;
2315  // ShowerLike
2316  if (tj.AlgMod[kShowerLike]) --wght;
2317  tjids.push_back(tjid);
2318  tjwts.push_back(wght);
2319  } // tjid
2320 
2321  if (tjids.empty()) return;
2322 
2323  float tjScore = 0;
2324  float sum = 0;
2325  float cnt = 0;
2326  for (unsigned short it1 = 0; it1 < tjids.size() - 1; ++it1) {
2327  Trajectory& tj1 = slc.tjs[tjids[it1] - 1];
2328  float wght1 = tjwts[it1];
2329  // the end that has a vertex
2330  unsigned short end1 = 0;
2331  if (tj1.VtxID[1] == vx2.ID) end1 = 1;
2332  unsigned short endPt1 = tj1.EndPt[end1];
2333  // bump up the weight if there is a Bragg peak at the other end
2334  unsigned short oend1 = 1 - end1;
2335  if (tj1.EndFlag[oend1][kBragg]) ++wght1;
2336  float ang1 = tj1.Pts[endPt1].Ang;
2337  float ang1Err2 = tj1.Pts[endPt1].AngErr * tj1.Pts[endPt1].AngErr;
2338  for (unsigned short it2 = it1 + 1; it2 < tjids.size(); ++it2) {
2339  Trajectory& tj2 = slc.tjs[tjids[it2] - 1];
2340  float wght2 = tjwts[it2];
2341  unsigned end2 = 0;
2342  if (tj2.VtxID[1] == vx2.ID) end2 = 1;
2343  // bump up the weight if there is a Bragg peak at the other end
2344  unsigned short oend2 = 1 - end2;
2345  if (tj2.EndFlag[oend2][kBragg]) ++wght2;
2346  unsigned short endPt2 = tj2.EndPt[end2];
2347  float ang2 = tj2.Pts[endPt2].Ang;
2348  float ang2Err2 = tj2.Pts[endPt2].AngErr * tj2.Pts[endPt2].AngErr;
2349  float dang = DeltaAngle(ang1, ang2);
2350  float dangErr = 0.5 * sqrt(ang1Err2 + ang2Err2);
2351  if ((dang / dangErr) > 3 && wght1 > 0 && wght2 > 0) {
2352  sum += wght1 + wght2;
2353  ++cnt;
2354  }
2355  } // it2
2356  } // it1
2357  if (cnt > 0) {
2358  sum /= cnt;
2359  tjScore = tcc.vtxScoreWeights[3] * sum;
2360  }
2361  vx2.Score = vpeScore + m3DScore + cfScore + tjScore;
2362  if (tcc.dbg2V && tcc.dbgSlc && vx2.CTP == debug.CTP) {
2363  // last call after vertices have been matched to the truth. Use to optimize vtxScoreWeights using
2364  // an ntuple
2365  mf::LogVerbatim myprt("TC");
2366  bool printHeader = true;
2367  Print2V(myprt, vx2, printHeader);
2368  myprt << std::fixed << std::setprecision(1);
2369  myprt << " vpeScore " << vpeScore << " m3DScore " << m3DScore;
2370  myprt << " cfScore " << cfScore << " tjScore " << tjScore;
2371  myprt << " Score " << vx2.Score;
2372  }
2373  } // SetVx2Score
TCConfig tcc
Definition: DataStructs.cxx:9
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:2531
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
void Print2V(mf::LogVerbatim &myprt, VtxStore const &vx2, bool &printHeader)
Definition: Utils.cxx:5613
if(nlines<=0)
DebugStuff debug
Definition: DebugStruct.cxx:4
bool dbg2V
debug 2D vertex finding
Definition: DataStructs.h:585
float ChgFracNearPos(const TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3163
std::vector< float > vtxScoreWeights
Definition: DataStructs.h:543
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:2823
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:541
Double_t sum
Definition: plot.C:31
CTP_t CTP
set to an invalid CTP
Definition: DebugStruct.h:23
void tca::SetVx3Score ( TCSlice slc,
Vtx3Store vx3 
)

Definition at line 2225 of file TCVertex.cxx.

References tca::Vtx3Store::ID, if(), 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().

2226  {
2227  // Calculate the 3D vertex score and flag Tjs that are attached to high score vertices as defined
2228  // by vtx2DCuts
2229 
2230  if (vx3.ID == 0) return;
2231 
2232  vx3.Score = 0;
2233  for (unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
2234  if (vx3.Vx2ID[ipl] <= 0) continue;
2235  VtxStore& vx2 = slc.vtxs[vx3.Vx2ID[ipl] - 1];
2236  vx3.Score += vx2.Score;
2237  } // ipl
2238  vx3.Score /= (float)slc.nPlanes;
2239  // don't allow it to get too small or negative
2240  if (vx3.Score < 0.001) vx3.Score = 0.001;
2241  if (vx3.Score > tcc.vtx2DCuts[7]) SetHighScoreBits(slc, vx3);
2242 
2243  } // SetVx3Score
TCConfig tcc
Definition: DataStructs.cxx:9
if(nlines<=0)
void SetHighScoreBits(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2177
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:541
double tca::ShowerEnergy ( const ShowerStruct3D ss3)

Definition at line 3899 of file TCShower.cxx.

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

Referenced by CompleteIncompleteShower(), FindParent(), FindShowers3D(), reco::shower::LArPandoraModularShowerCreation::produce(), Reconcile3D(), and showerreco::ShowerCalo::~ShowerCalo().

3900  {
3901  if (ss3.ID == 0) return 0;
3902  if (ss3.Energy.empty()) return 0;
3903  double ave = 0;
3904  for (auto e : ss3.Energy) {
3905  ave += e;
3906  } // e
3907  ave /= ss3.Energy.size();
3908  return ave;
3909  } // ShowerEnergy
Float_t e
Definition: plot.C:35
float tca::ShowerEnergy ( TCSlice slc,
const std::vector< int >  tjIDs 
)

Definition at line 3912 of file TCShower.cxx.

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

3913  {
3914  // Calculate energy using the total charge of all hits in each tj in the shower
3915  if (tjIDs.empty()) return 0;
3916  float sum = 0;
3917  for (auto tid : tjIDs) {
3918  auto& tj = slc.tjs[tid - 1];
3919  sum += tj.TotChg;
3920  } // tid
3921  return ChgToMeV(sum);
3922  } // ShowerEnergy
float ChgToMeV(float chg)
Definition: TCShower.cxx:3925
Double_t sum
Definition: plot.C:31
void tca::ShowerParams ( double  showerEnergy,
double &  shMaxAlong,
double &  along95 
)

Definition at line 1904 of file TCShower.cxx.

References scale.

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

1905  {
1906  // Returns summary properties of photon showers parameterized in the energy range 50 MeV < E_gamma < 1 GeV:
1907  // shMaxAlong = the longitudinal distance (cm) between the start of the shower and the center of charge
1908  // along95 = the longitudinal distance (cm) between the start of the shower and 95% energy containment
1909  // all units are in cm
1910  if (showerEnergy < 10) {
1911  shMaxAlong = 0;
1912  along95 = 0;
1913  return;
1914  }
1915  shMaxAlong = 16 * log(showerEnergy / 15);
1916  // The 95% containment is reduced a bit at higher energy
1917  double scale = 2.75 - 9.29E-4 * showerEnergy;
1918  if (scale < 2) scale = 2;
1919  along95 = scale * shMaxAlong;
1920  } // ShowerParams
Double_t scale
Definition: plot.C:24
double tca::ShowerParamTransRMS ( double  showerEnergy,
double  along 
)

Definition at line 1923 of file TCShower.cxx.

References ShowerParams().

Referenced by InShowerProbTrans().

1924  {
1925  // returns the pareameterized width rms of a shower at along relative to the shower max
1926  double shMaxAlong, shE95Along;
1927  ShowerParams(showerEnergy, shMaxAlong, shE95Along);
1928  if (shMaxAlong <= 0) return 0;
1929  double tau = (along + shMaxAlong) / shMaxAlong;
1930  // The shower width is modeled as a simple cone that scales with tau
1931  double rms = -0.4 + 2.5 * tau;
1932  if (rms < 0.5) rms = 0.5;
1933  return rms;
1934  } // ShowerParamTransRMS
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
Definition: TCShower.cxx:1904
bool tca::SignalAtTp ( TrajPoint tp)

Definition at line 1964 of file Utils.cxx.

References util::abs(), tca::TCEvent::allHits, geo::CryostatID::Cryostat, tca::TrajPoint::CTP, DecodeCTP(), tca::TrajPoint::Dir, tca::TrajPoint::Environment, evt, tca::TCEvent::goodWire, kEnvNearSrcHit, NearbySrcHit(), geo::PlaneID::Plane, tca::TrajPoint::Pos, SignalAtTpInSlc(), slices, tca::TCEvent::srcHits, tcc, geo::TPCID::TPC, tca::TCConfig::unitsPerTick, and tca::TCEvent::wireHitRange.

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

1965  {
1966  // returns true if there is a hit near tp.Pos by searching through the full hit collection (if there
1967  // are multiple slices) or through the last slice (if there is only one slice)
1968 
1969  tp.Environment[kEnvNearSrcHit] = false;
1970 
1971  // just check the hits in the last slice
1972  if (evt.wireHitRange.empty()) {
1973  const auto& slc = slices[slices.size() - 1];
1974  return SignalAtTpInSlc(slc, tp);
1975  }
1976 
1977  if (tp.Pos[0] < -0.4) return false;
1978  geo::PlaneID planeID = DecodeCTP(tp.CTP);
1979  unsigned short pln = planeID.Plane;
1980  unsigned int wire = std::nearbyint(tp.Pos[0]);
1981  if (wire > evt.goodWire[pln].size() - 1) return false;
1982  // assume there is a signal on a dead wire
1983  if (!evt.goodWire[pln][wire]) return true;
1984 
1985  // check the proximity of all of the hits in the range
1986  float projTick = (float)(tp.Pos[1] / tcc.unitsPerTick);
1987  float tickRange = 0;
1988  if (std::abs(tp.Dir[1]) != 0) {
1989  tickRange = std::abs(0.5 / tp.Dir[1]) / tcc.unitsPerTick;
1990  // don't let it get too large
1991  if (tickRange > 40) tickRange = 40;
1992  }
1993  float loTpTick = projTick - tickRange;
1994  float hiTpTick = projTick + tickRange;
1995 
1996  // no signal here if there are no hits on this wire
1997  if (evt.wireHitRange[pln][wire].first == UINT_MAX) return false;
1998 
1999  for (unsigned int iht = evt.wireHitRange[pln][wire].first;
2000  iht <= evt.wireHitRange[pln][wire].second;
2001  ++iht) {
2002  auto& hit = (*evt.allHits)[iht];
2003  // We wouldn't need to make this check if hits were sorted
2004  const auto& wid = hit.WireID();
2005  if (wid.Cryostat != planeID.Cryostat) continue;
2006  if (wid.TPC != planeID.TPC) continue;
2007  if (wid.Plane != planeID.Plane) continue;
2008  if (projTick < hit.PeakTime()) {
2009  float loHitTick = hit.PeakTime() - 3 * hit.RMS();
2010  if (hiTpTick > loHitTick) return true;
2011  }
2012  else {
2013  float hiHitTick = hit.PeakTime() + 3 * hit.RMS();
2014  if (loTpTick < hiHitTick) return true;
2015  }
2016  } // iht
2017  // No hit was found near projTick. Search through the source hits collection
2018  // (if it is defined) for a hit that may have been removed by disambiguation
2019  // Use the srcHit collection if it is available
2020  if (evt.srcHits != NULL) {
2021  if (NearbySrcHit(planeID, wire, loTpTick, hiTpTick)) {
2022  tp.Environment[kEnvNearSrcHit] = true;
2023  return true;
2024  } // NearbySrcHit
2025  } // evt.srcHits != NULL
2026  return false;
2027  } // SignalAtTp
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
constexpr auto abs(T v)
Returns the absolute value of the argument.
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:195
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
TP is near a hit in the srcHit collection but no allHit hit exists (DUNE disambiguation error) ...
Definition: DataStructs.h:516
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:622
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * srcHits
Definition: DataStructs.h:615
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
bool SignalAtTpInSlc(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:1923
bool NearbySrcHit(geo::PlaneID plnID, unsigned int wire, float loTick, float hiTick)
Definition: Utils.cxx:2030
TCEvent evt
Definition: DataStructs.cxx:8
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:315
std::vector< std::vector< std::pair< unsigned int, unsigned int > > > wireHitRange
Definition: DataStructs.h:618
bool tca::SignalAtTpInSlc ( const TCSlice slc,
const TrajPoint tp 
)

Definition at line 1923 of file Utils.cxx.

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

Referenced by SignalAtTp().

1924  {
1925  // Version of SignalAtTP that only checks the hit collection in the current slice
1926 
1927  if (tp.Pos[0] < -0.4) return false;
1928  geo::PlaneID planeID = DecodeCTP(tp.CTP);
1929  unsigned short pln = planeID.Plane;
1930  unsigned int wire = std::nearbyint(tp.Pos[0]);
1931  if (wire > evt.goodWire[pln].size() - 1) return false;
1932  // assume there is a signal on a dead wire
1933  if (!evt.goodWire[pln][wire]) return true;
1934  // no signal here if there are no hits on this wire
1935  if (slc.wireHitRange[pln][wire].first == UINT_MAX) return false;
1936  // check the proximity of all of the hits in the range
1937  float projTick = (float)(tp.Pos[1] / tcc.unitsPerTick);
1938  float tickRange = 0;
1939  if (std::abs(tp.Dir[1]) != 0) {
1940  tickRange = std::abs(0.5 / tp.Dir[1]) / tcc.unitsPerTick;
1941  // don't let it get too large
1942  if (tickRange > 40) tickRange = 40;
1943  }
1944  float loTpTick = projTick - tickRange;
1945  float hiTpTick = projTick + tickRange;
1946  for (unsigned int iht = slc.wireHitRange[pln][wire].first;
1947  iht <= slc.wireHitRange[pln][wire].second;
1948  ++iht) {
1949  unsigned int ahi = slc.slHits[iht].allHitsIndex;
1950  auto& hit = (*evt.allHits)[ahi];
1951  if (projTick < hit.PeakTime()) {
1952  float loHitTick = hit.PeakTime() - 3 * hit.RMS();
1953  if (hiTpTick > loHitTick) return true;
1954  }
1955  else {
1956  float hiHitTick = hit.PeakTime() + 3 * hit.RMS();
1957  if (loTpTick < hiHitTick) return true;
1958  }
1959  } // iht
1960  return false;
1961  } // SignalAtTpInSlc
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
constexpr auto abs(T v)
Returns the absolute value of the argument.
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:622
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
Detector simulation of raw signals on wires.
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
bool tca::SignalBetween ( const TrajPoint tp1,
const TrajPoint tp2,
const float  MinWireSignalFraction 
)

Definition at line 1779 of file Utils.cxx.

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

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

1780  {
1781  // Returns true if there is a signal on > MinWireSignalFraction of the wires between tp1 and tp2.
1782  if (MinWireSignalFraction == 0) return true;
1783 
1784  if (tp1.Pos[0] < -0.4 || tp2.Pos[0] < -0.4) return false;
1785  int fromWire = std::nearbyint(tp1.Pos[0]);
1786  int toWire = std::nearbyint(tp2.Pos[0]);
1787 
1788  if (fromWire == toWire) {
1789  TrajPoint tp = tp1;
1790  // check for a signal midway between
1791  tp.Pos[1] = 0.5 * (tp1.Pos[1] + tp2.Pos[1]);
1792  return SignalAtTp(tp);
1793  }
1794  // define a trajectory point located at tp1 that has a direction towards tp2
1795  TrajPoint tp;
1796  if (!MakeBareTrajPoint(tp1, tp2, tp)) return true;
1797  return SignalBetween(tp, toWire, MinWireSignalFraction);
1798  } // SignalBetween
bool SignalAtTp(TrajPoint &tp)
Definition: Utils.cxx:1964
bool MakeBareTrajPoint(const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
Definition: Utils.cxx:4059
bool SignalBetween(TrajPoint tp, float toPos0, const float MinWireSignalFraction)
Definition: Utils.cxx:1801
bool tca::SignalBetween ( TrajPoint  tp,
float  toPos0,
const float  MinWireSignalFraction 
)

Definition at line 1801 of file Utils.cxx.

References ChgFracBetween().

1802  {
1803  // Returns true if there is a signal on > MinWireSignalFraction of the wires between tp and toPos0.
1804  return ChgFracBetween(tp, toPos0) >= MinWireSignalFraction;
1805  } // SignalBetween
float ChgFracBetween(TrajPoint tp, float toPos0)
Definition: Utils.cxx:1808
bool tca::SortSection ( PFPStruct pfp,
unsigned short  sfIndex 
)

Definition at line 1999 of file PFPUtils.cxx.

References tca::PFPStruct::SectionFits, tca::PFPStruct::TP3Ds, and tca::detail::valsIncreasing().

Referenced by FitTP3Ds(), MakePFParticles(), MakeSmallAnglePFP(), ReSection(), and Update().

2000  {
2001  // sorts the TP3Ds by the distance from the start of a fit section
2002 
2003  if (sfIndex > pfp.SectionFits.size() - 1) return false;
2004  auto& sf = pfp.SectionFits[sfIndex];
2005  if (sf.Pos[0] == 0.0 && sf.Pos[1] == 0.0 && sf.Pos[2] == 0.0) return false;
2006 
2007  // a temp vector of points in this section
2008  std::vector<TP3D> temp;
2009  // and the index into TP3Ds
2010  std::vector<unsigned short> indx;
2011  // See if the along variable is monotonically increasing
2012  float prevAlong = 0;
2013  bool first = true;
2014  bool needsSort = false;
2015  for (std::size_t ii = 0; ii < pfp.TP3Ds.size(); ++ii) {
2016  auto& tp3d = pfp.TP3Ds[ii];
2017  if (tp3d.SFIndex != sfIndex) continue;
2018  if (first) {
2019  first = false;
2020  prevAlong = tp3d.along;
2021  }
2022  else {
2023  if (tp3d.along < prevAlong) needsSort = true;
2024  prevAlong = tp3d.along;
2025  }
2026  temp.push_back(tp3d);
2027  indx.push_back(ii);
2028  } // tp3d
2029  if (temp.empty()) return false;
2030  // no sort needed?
2031  if (temp.size() == 1) return true;
2032  if (!needsSort) {
2033  sf.NeedsUpdate = false;
2034  return true;
2035  }
2036  // see if the points are not-contiguous
2037  bool contiguous = true;
2038  for (std::size_t ipt = 1; ipt < indx.size(); ++ipt) {
2039  if (indx[ipt] != indx[ipt - 1] + 1) contiguous = false;
2040  } // ipt
2041  if (!contiguous) { return false; }
2042 
2043  std::vector<SortEntry> sortVec(temp.size());
2044  for (std::size_t ii = 0; ii < temp.size(); ++ii) {
2045  sortVec[ii].index = ii;
2046  sortVec[ii].val = temp[ii].along;
2047  } // ipt
2048  std::sort(sortVec.begin(), sortVec.end(), valsIncreasing);
2049  for (std::size_t ii = 0; ii < temp.size(); ++ii) {
2050  // overwrite the tp3d
2051  auto& tp3d = pfp.TP3Ds[indx[ii]];
2052  tp3d = temp[sortVec[ii].index];
2053  } // ii
2054  sf.NeedsUpdate = false;
2055  return true;
2056  } // SortSection
bool valsIncreasing(const SortEntry &c1, const SortEntry &c2)
Definition: Utils.cxx:43
bool tca::SplitTraj ( detinfo::DetectorPropertiesData const &  detProp,
TCSlice slc,
unsigned short  itj,
float  XPos,
bool  makeVx2,
bool  prt 
)

Definition at line 2223 of file Utils.cxx.

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

Referenced by BraggSplit(), CheckTrajBeginChg(), CompleteIncomplete3DVertices(), FindHammerVertices(), FindHammerVertices2(), and SplitTrajCrossingVertices().

2229  {
2230  // Splits the trajectory at an X position and optionally creates a 2D vertex
2231  // at the split point
2232  if (itj > slc.tjs.size() - 1) return false;
2233 
2234  auto& tj = slc.tjs[itj];
2235  geo::PlaneID planeID = DecodeCTP(tj.CTP);
2236  float atPos1 = detProp.ConvertXToTicks(XPos, planeID) * tcc.unitsPerTick;
2237  unsigned short atPt = USHRT_MAX;
2238  for (unsigned short ipt = tj.EndPt[0] + 1; ipt <= tj.EndPt[1]; ++ipt) {
2239  if (tj.Pts[ipt].Pos[1] > tj.Pts[ipt - 1].Pos[1]) {
2240  // positive slope
2241  if (tj.Pts[ipt - 1].Pos[1] < atPos1 && tj.Pts[ipt].Pos[1] >= atPos1) {
2242  atPt = ipt;
2243  break;
2244  }
2245  }
2246  else {
2247  // negative slope
2248  if (tj.Pts[ipt - 1].Pos[1] >= atPos1 && tj.Pts[ipt].Pos[1] < atPos1) {
2249  atPt = ipt;
2250  break;
2251  }
2252  } // negative slope
2253  } // ipt
2254  if (atPt == USHRT_MAX) return false;
2255  unsigned short vx2Index = USHRT_MAX;
2256  if (makeVx2) {
2257  VtxStore newVx2;
2258  newVx2.CTP = tj.CTP;
2259  newVx2.Pos[0] = 0.5 * (tj.Pts[atPt - 1].Pos[0] + tj.Pts[atPt].Pos[0]);
2260  newVx2.Pos[1] = 0.5 * (tj.Pts[atPt - 1].Pos[1] + tj.Pts[atPt].Pos[1]);
2261  newVx2.Topo = 10;
2262  newVx2.NTraj = 2;
2263  if (StoreVertex(slc, newVx2)) vx2Index = slc.vtxs.size() - 1;
2264  } // makeVx2
2265  return SplitTraj(slc, itj, atPt, vx2Index, prt);
2266  } // SplitTraj
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:1908
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
bool SplitTraj(TCSlice &slc, unsigned short itj, unsigned short pos, unsigned short ivx, bool prt)
Definition: Utils.cxx:2269
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 2269 of file Utils.cxx.

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

2270  {
2271  // Splits the trajectory itj in the slc.tjs vector into two trajectories at position pos. Splits
2272  // the trajectory and associates the ends to the supplied vertex.
2273  // Here is an example where itj has 9 points and we will split at pos = 4
2274  // itj (0 1 2 3 4 5 6 7 8) -> new traj (0 1 2 3) + new traj (4 5 6 7 8)
2275 
2276  if (itj > slc.tjs.size() - 1) return false;
2277  if (pos < slc.tjs[itj].EndPt[0] + 1 || pos > slc.tjs[itj].EndPt[1] - 1) return false;
2278  if (ivx != USHRT_MAX && ivx > slc.vtxs.size() - 1) return false;
2279 
2280  Trajectory& tj = slc.tjs[itj];
2281 
2282  // Reset the PDG Code if we are splitting a tagged muon
2283  bool splittingMuon = (tj.PDGCode == 13);
2284  if (splittingMuon) tj.PDGCode = 0;
2285 
2286  if (prt) {
2287  mf::LogVerbatim myprt("TC");
2288  myprt << "SplitTraj: Split T" << tj.ID << " at point " << PrintPos(tj.Pts[pos]);
2289  if (ivx < slc.vtxs.size()) myprt << " with Vtx 2V" << slc.vtxs[ivx].ID;
2290  }
2291 
2292  // ensure that there will be at least 3 TPs on each trajectory
2293  unsigned short ntp = 0;
2294  for (unsigned short ipt = 0; ipt <= pos; ++ipt) {
2295  if (tj.Pts[ipt].Chg > 0) ++ntp;
2296  if (ntp > 2) break;
2297  } // ipt
2298  if (ntp < 3) {
2299  if (prt) mf::LogVerbatim("TC") << " Split point to small at begin " << ntp << " pos " << pos;
2300  return false;
2301  }
2302  ntp = 0;
2303  for (unsigned short ipt = pos + 1; ipt <= tj.EndPt[1]; ++ipt) {
2304  if (tj.Pts[ipt].Chg > 0) ++ntp;
2305  if (ntp > 2) break;
2306  } // ipt
2307  if (ntp < 3) {
2308  if (prt)
2309  mf::LogVerbatim("TC") << " Split point too small at end " << ntp << " pos " << pos
2310  << " EndPt " << tj.EndPt[1];
2311  return false;
2312  }
2313 
2314  // make a copy that will become the Tj after the split point
2315  Trajectory newTj = tj;
2316  newTj.ID = slc.tjs.size() + 1;
2317  ++evt.globalT_UID;
2318  newTj.UID = evt.globalT_UID;
2319  // make another copy in case something goes wrong
2320  Trajectory oldTj = tj;
2321 
2322  // Leave the first section of tj in place. Re-assign the hits
2323  // to the new trajectory
2324  unsigned int iht;
2325  for (unsigned short ipt = pos + 1; ipt <= tj.EndPt[1]; ++ipt) {
2326  tj.Pts[ipt].Chg = 0;
2327  for (unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
2328  if (!tj.Pts[ipt].UseHit[ii]) continue;
2329  iht = tj.Pts[ipt].Hits[ii];
2330  // This shouldn't happen but check anyway
2331  if (slc.slHits[iht].InTraj != tj.ID) continue;
2332  slc.slHits[iht].InTraj = newTj.ID;
2333  tj.Pts[ipt].UseHit[ii] = false;
2334  } // ii
2335  } // ipt
2336  SetEndPoints(tj);
2337  // Update MCSMom and charge properties
2338  tj.MCSMom = MCSMom(slc, tj);
2339  UpdateTjChgProperties("ST", slc, tj, prt);
2340  if (splittingMuon) SetPDGCode(slc, tj);
2341 
2342  // Append 3 points from the end of tj onto the
2343  // beginning of newTj so that hits can be swapped between
2344  // them later
2345  unsigned short eraseSize = pos - 2;
2346  if (eraseSize > newTj.Pts.size() - 1) {
2347  tj = oldTj;
2348  return false;
2349  }
2350 
2351  if (ivx < slc.vtxs.size()) tj.VtxID[1] = slc.vtxs[ivx].ID;
2352  tj.AlgMod[kSplit] = true;
2353  if (prt) {
2354  mf::LogVerbatim("TC") << " Splitting T" << tj.ID << " new EndPts " << tj.EndPt[0] << " to "
2355  << tj.EndPt[1];
2356  }
2357 
2358  // erase the TPs at the beginning of the new trajectory
2359  newTj.Pts.erase(newTj.Pts.begin(), newTj.Pts.begin() + eraseSize);
2360  // unset the first 3 TP hits
2361  for (unsigned short ipt = 0; ipt < 3; ++ipt) {
2362  for (unsigned short ii = 0; ii < newTj.Pts[ipt].Hits.size(); ++ii)
2363  newTj.Pts[ipt].UseHit[ii] = false;
2364  newTj.Pts[ipt].Chg = 0;
2365  } // ipt
2366  SetEndPoints(newTj);
2367  newTj.MCSMom = MCSMom(slc, newTj);
2368  UpdateTjChgProperties("ST", slc, newTj, prt);
2369  if (splittingMuon) SetPDGCode(slc, newTj);
2370  if (ivx < slc.vtxs.size()) newTj.VtxID[0] = slc.vtxs[ivx].ID;
2371  newTj.AlgMod[kSplit] = true;
2372  newTj.ParentID = 0;
2373  slc.tjs.push_back(newTj);
2374 
2375  if (prt) {
2376  mf::LogVerbatim("TC") << " newTj T" << newTj.ID << " EndPts " << newTj.EndPt[0] << " to "
2377  << newTj.EndPt[1];
2378  }
2379  return true;
2380 
2381  } // SplitTraj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
std::string PrintPos(const Point2_t &pos)
Definition: Utils.cxx:6362
if(nlines<=0)
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice const &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3577
TCEvent evt
Definition: DataStructs.cxx:8
short MCSMom(const TCSlice &slc, const Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:3403
void SetPDGCode(TCSlice const &slc, Trajectory &tj)
Definition: Utils.cxx:4226
void tca::SplitTrajCrossingVertices ( TCSlice slc,
CTP_t  inCTP 
)

Definition at line 916 of file TCVertex.cxx.

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

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

917  {
918  // This is kind of self-explanatory...
919 
920  if (!tcc.useAlg[kSplitTjCVx]) return;
921 
922  if (slc.vtxs.empty()) return;
923  if (slc.tjs.empty()) return;
924 
925  constexpr float docaCut = 4;
926 
927  bool prt = (tcc.modes[kDebug] && tcc.dbgSlc && tcc.dbgAlg[kSplitTjCVx]);
928  if (prt) mf::LogVerbatim("TC") << "Inside SplitTrajCrossingVertices inCTP " << inCTP;
929 
930  geo::PlaneID planeID = DecodeCTP(inCTP);
931 
932  unsigned short nTraj = slc.tjs.size();
933  for (unsigned short itj = 0; itj < nTraj; ++itj) {
934  // NOTE: Don't use a reference variable because it may get lost if the tj is split
935  if (slc.tjs[itj].CTP != inCTP) continue;
936  // obsolete trajectory
937  if (slc.tjs[itj].AlgMod[kKilled] || slc.tjs[itj].AlgMod[kHaloTj]) continue;
938  if (slc.tjs[itj].AlgMod[kJunkTj]) continue;
939  if (slc.tjs[itj].AlgMod[kSplitTjCVx]) continue;
940  // too short
941  if (slc.tjs[itj].EndPt[1] < 6) continue;
942  for (unsigned short iv = 0; iv < slc.vtxs.size(); ++iv) {
943  auto& vx2 = slc.vtxs[iv];
944  // obsolete vertex
945  if (vx2.NTraj == 0) continue;
946  // trajectory already associated with vertex
947  if (slc.tjs[itj].VtxID[0] == vx2.ID || slc.tjs[itj].VtxID[1] == vx2.ID) continue;
948  // not in the cryostat/tpc/plane
949  if (slc.tjs[itj].CTP != vx2.CTP) continue;
950  // poor quality
951  if (vx2.Score < tcc.vtx2DCuts[7]) continue;
952  float doca = docaCut;
953  // make the cut significantly larger if the vertex is in a dead
954  // wire gap to get the first TP that is just outside the gap.
955  if (vx2.Stat[kOnDeadWire]) doca = 100;
956  unsigned short closePt = 0;
957  if (!TrajClosestApproach(slc.tjs[itj], vx2.Pos[0], vx2.Pos[1], closePt, doca)) continue;
958  if (vx2.Stat[kOnDeadWire]) {
959  // special handling for vertices in dead wire regions. Find the IP between
960  // the closest point on the Tj and the vertex
961  doca = PointTrajDOCA(vx2.Pos[0], vx2.Pos[1], slc.tjs[itj].Pts[closePt]);
962  }
963  if (doca > docaCut) continue;
964  if (prt)
965  mf::LogVerbatim("TC") << " doca " << doca << " btw T" << slc.tjs[itj].ID << " and 2V"
966  << slc.vtxs[iv].ID << " closePt " << closePt << " in plane "
967  << planeID.Plane;
968  // compare the length of the Tjs used to make the vertex with the length of the
969  // Tj that we want to split. Don't allow a vertex using very short Tjs to split a long
970  // Tj in the 3rd plane
971  auto vxtjs = GetVtxTjIDs(slc, vx2);
972  if (vxtjs.empty()) continue;
973  unsigned short maxPts = 0;
974  // ensure that there is a large angle between a Tj already attached to the vertex and the
975  // tj that we want to split. We might be considering a delta-ray here
976  float maxdang = 0.3;
977  float tjAng = slc.tjs[itj].Pts[closePt].Ang;
978  for (auto tjid : vxtjs) {
979  auto& vtj = slc.tjs[tjid - 1];
980  if (vtj.AlgMod[kDeltaRay]) continue;
981  unsigned short npwc = NumPtsWithCharge(slc, vtj, false);
982  if (npwc > maxPts) maxPts = npwc;
983  unsigned short end = 0;
984  if (vtj.VtxID[1] == slc.vtxs[iv].ID) end = 1;
985  auto& vtp = vtj.Pts[vtj.EndPt[end]];
986  float dang = DeltaAngle(vtp.Ang, tjAng);
987  if (dang > maxdang) maxdang = dang;
988  } // tjid
989  // skip this operation if any of the Tjs in the split list are > 3 * maxPts
990  maxPts *= 3;
991  bool skipit = false;
992  if (NumPtsWithCharge(slc, slc.tjs[itj], false) > maxPts && maxPts < 100) skipit = true;
993  if (!skipit && maxdang < 0.3) skipit = true;
994  if (prt)
995  mf::LogVerbatim("TC") << " maxPts " << maxPts << " vxtjs[0] " << vxtjs[0] << " maxdang "
996  << maxdang << " skipit? " << skipit;
997  if (skipit) {
998  // kill the vertex?
999  if (doca < 1) MakeVertexObsolete("STCV", slc, vx2, true);
1000  continue;
1001  }
1002 
1003  // make some adjustments to closePt
1004  if (vx2.Stat[kOnDeadWire]) {
1005  // ensure that the tj will be split at the gap. The closePt point may be
1006  // on the wrong side of it
1007  auto& closeTP = slc.tjs[itj].Pts[closePt];
1008  if (slc.tjs[itj].StepDir > 0 && closePt > slc.tjs[itj].EndPt[0]) {
1009  if (closeTP.Pos[0] > vx2.Pos[0]) --closePt;
1010  }
1011  else if (slc.tjs[itj].StepDir < 0 && closePt < slc.tjs[itj].EndPt[1]) {
1012  if (closeTP.Pos[0] < vx2.Pos[0]) ++closePt;
1013  }
1014  }
1015  else {
1016  // improve closePt based on vertex position
1017  // check if closePt and EndPt[1] are the two sides of vertex
1018  // take dot product of closePt-vtx and EndPt[1]-vtx
1019  if ((slc.tjs[itj].Pts[closePt].Pos[0] - vx2.Pos[0]) *
1020  (slc.tjs[itj].Pts[slc.tjs[itj].EndPt[1]].Pos[0] - vx2.Pos[0]) +
1021  (slc.tjs[itj].Pts[closePt].Pos[1] - vx2.Pos[1]) *
1022  (slc.tjs[itj].Pts[slc.tjs[itj].EndPt[1]].Pos[1] - vx2.Pos[1]) <
1023  0 &&
1024  closePt < slc.tjs[itj].EndPt[1] - 1)
1025  ++closePt;
1026  else if ((slc.tjs[itj].Pts[closePt].Pos[0] - vx2.Pos[0]) *
1027  (slc.tjs[itj].Pts[slc.tjs[itj].EndPt[0]].Pos[0] - vx2.Pos[0]) +
1028  (slc.tjs[itj].Pts[closePt].Pos[1] - vx2.Pos[1]) *
1029  (slc.tjs[itj].Pts[slc.tjs[itj].EndPt[0]].Pos[1] - slc.vtxs[iv].Pos[1]) <
1030  0 &&
1031  closePt > slc.tjs[itj].EndPt[0] + 1)
1032  --closePt;
1033  }
1034 
1035  if (prt) {
1036  mf::LogVerbatim("TC") << "Good doca " << doca << " btw T" << slc.tjs[itj].ID << " and 2V"
1037  << vx2.ID << " closePt " << closePt << " in plane " << planeID.Plane
1038  << " CTP " << slc.vtxs[iv].CTP;
1039  PrintTP("STCV", slc, closePt, 1, slc.tjs[itj].Pass, slc.tjs[itj].Pts[closePt]);
1040  }
1041  // ensure that the closest point is not near an end
1042  if (closePt < slc.tjs[itj].EndPt[0] + 3) continue;
1043  if (closePt > slc.tjs[itj].EndPt[1] - 3) continue;
1044  if (!SplitTraj(slc, itj, closePt, iv, prt)) {
1045  if (prt) mf::LogVerbatim("TC") << "SplitTrajCrossingVertices: Failed to split trajectory";
1046  continue;
1047  }
1048  slc.tjs[itj].AlgMod[kSplitTjCVx] = true;
1049  unsigned short newTjIndex = slc.tjs.size() - 1;
1050  slc.tjs[newTjIndex].AlgMod[kSplitTjCVx] = true;
1051  // re-fit the vertex position
1052  FitVertex(slc, vx2, prt);
1053  } // iv
1054  } // itj
1055 
1056  } // SplitTrajCrossingVertices
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeVertexObsolete(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2789
TCConfig tcc
Definition: DataStructs.cxx:9
void PrintTP(std::string someText, const TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, const TrajPoint &tp)
Definition: Utils.cxx:6134
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
bool TrajClosestApproach(Trajectory const &tj, float x, float y, unsigned short &closePt, float &DOCA)
Definition: Utils.cxx:2622
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2514
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:2531
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
bool FitVertex(TCSlice &slc, VtxStore &vx, std::vector< TrajPoint > &vxTPs, bool prt)
Definition: TCVertex.cxx:1992
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
bool SplitTraj(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, unsigned short itj, float XPos, bool makeVx2, bool prt)
Definition: Utils.cxx:2223
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:2823
geo::PlaneID DecodeCTP(CTP_t CTP)
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:579
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:541
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
master switch for turning on debug mode
Definition: DataStructs.h:524
bool tca::SptInTPC ( const std::array< unsigned int, 3 > &  sptHits,
unsigned int  tpc 
)

Definition at line 789 of file PFPUtils.cxx.

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

Referenced by Match3PlanesSpt().

790  {
791  // returns true if a hit referenced in sptHits resides in the requested tpc. We assume
792  // that if one does, then all of them do
793 
794  unsigned int ahi = UINT_MAX;
795  for (auto ii : sptHits)
796  if (ii != UINT_MAX) {
797  ahi = ii;
798  break;
799  }
800  if (ahi >= (*evt.allHits).size()) return false;
801  // get a reference to the hit and see if it is in the desired tpc
802  auto& hit = (*evt.allHits)[ahi];
803  if (hit.WireID().TPC == tpc) return true;
804  return false;
805 
806  } // SptInTPC
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
std::vector< float > tca::StartChgVec ( TCSlice slc,
int  cotID 
)

Definition at line 3774 of file TCShower.cxx.

References util::abs(), 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, sn, tcc, tca::ShowerStruct::TjIDs, tca::TCSlice::tjs, and tca::TCConfig::unitsPerTick.

Referenced by FindStartChg().

3775  {
3776  // Returns a histogram vector of the charge in bins of 1 WSE unit at the start of the shower
3777 
3778  ShowerStruct& ss = slc.cots[cotID - 1];
3779  constexpr unsigned short nbins = 20;
3780  std::vector<float> schg(nbins);
3781  if (ss.ID == 0) return schg;
3782  if (ss.TjIDs.empty()) return schg;
3783  TrajPoint& stp1 = slc.tjs[ss.ShowerTjID - 1].Pts[1];
3784 
3785  // move the min along point back by 2 WSE so that most of the charge in the hits in the
3786  // first point is included in the histogram
3787  float minAlong = ss.ShPts[0].RotPos[0] - 2;
3788 
3789  float maxTrans = 4;
3790  // Tighten up on the maximum allowed transverse position if there is a parent
3791  if (ss.ParentID > 0) maxTrans = 1;
3792  float cs = cos(-ss.Angle);
3793  float sn = sin(-ss.Angle);
3794  std::array<float, 2> chgPos;
3795  float along, arg;
3796 
3797  for (auto& sspt : ss.ShPts) {
3798  unsigned short indx = (unsigned short)((sspt.RotPos[0] - minAlong));
3799  if (indx > nbins - 1) break;
3800  // Count the charge if it is within a few WSE transverse from the shower axis
3801  if (std::abs(sspt.RotPos[1]) > maxTrans) continue;
3802  unsigned int iht = sspt.HitIndex;
3803  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
3804  float peakTime = hit.PeakTime();
3805  float amp = hit.PeakAmplitude();
3806  float rms = hit.RMS();
3807  chgPos[0] = hit.WireID().Wire - stp1.Pos[0];
3808  for (float time = peakTime - 2.5 * rms; time < peakTime + 2.5 * rms; ++time) {
3809  chgPos[1] = time * tcc.unitsPerTick - stp1.Pos[1];
3810  along = cs * chgPos[0] - sn * chgPos[1];
3811  if (along < minAlong) continue;
3812  indx = (unsigned short)(along - minAlong);
3813  if (indx > nbins - 1) continue;
3814  arg = (time - peakTime) / rms;
3815  schg[indx] += amp * exp(-0.5 * arg * arg);
3816  } // time
3817  } // sspt
3818 
3819  return schg;
3820  } // StartChgVec
TCConfig tcc
Definition: DataStructs.cxx:9
constexpr auto abs(T v)
Returns the absolute value of the argument.
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
Float_t sn
Definition: plot.C:23
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
bool tca::StartTraj ( TCSlice const &  slc,
Trajectory tj,
unsigned int  fromhit,
unsigned int  tohit,
unsigned short  pass 
)

Definition at line 4858 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, tca::Trajectory::StepDir, tcc, and tca::DebugStuff::WorkID.

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

4863  {
4864  // Start a trajectory located at fromHit with direction pointing to toHit
4865 
4866  auto& fromHit = (*evt.allHits)[slc.slHits[fromhit].allHitsIndex];
4867  auto& toHit = (*evt.allHits)[slc.slHits[tohit].allHitsIndex];
4868  float fromWire = fromHit.WireID().Wire;
4869  float fromTick = fromHit.PeakTime();
4870  float toWire = toHit.WireID().Wire;
4871  float toTick = toHit.PeakTime();
4872  CTP_t tCTP = EncodeCTP(fromHit.WireID());
4873  bool success = StartTraj(tj, fromWire, fromTick, toWire, toTick, tCTP, pass);
4874  if (!success) return false;
4875  // turn on debugging using the WorkID?
4876  if (tcc.modes[kDebug] && !tcc.dbgStp && !tcc.dbgDump && tcc.dbgSlc && tj.ID == debug.WorkID)
4877  tcc.dbgStp = true;
4878  if (tcc.dbgStp) {
4879  auto& tp = tj.Pts[0];
4880  mf::LogVerbatim("TC") << "StartTraj T" << tj.ID << " from " << (int)fromWire << ":"
4881  << (int)fromTick << " -> " << (int)toWire << ":" << (int)toTick
4882  << " StepDir " << tj.StepDir << " dir " << tp.Dir[0] << " " << tp.Dir[1]
4883  << " ang " << tp.Ang << " AngleCode " << tp.AngleCode << " angErr "
4884  << tp.AngErr << " ExpectedHitsRMS " << ExpectedHitsRMS(tp);
4885  } // tcc.dbgStp
4886  return true;
4887  } // StartTraj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
int WorkID
Select the StartWorkID for debugging.
Definition: DebugStruct.h:28
DebugStuff debug
Definition: DebugStruct.cxx:4
float ExpectedHitsRMS(const TrajPoint &tp)
Definition: Utils.cxx:1911
bool StartTraj(Trajectory &tj, float fromWire, float fromTick, float toWire, float toTick, CTP_t &tCTP, unsigned short pass)
Definition: Utils.cxx:4890
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
unsigned int CTP_t
Definition: DataStructs.h:45
TDirectory * dir
Definition: macro.C:5
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:49
TCEvent evt
Definition: DataStructs.cxx:8
master switch for turning on debug mode
Definition: DataStructs.h:524
bool tca::StartTraj ( Trajectory tj,
float  fromWire,
float  fromTick,
float  toWire,
float  toTick,
CTP_t tCTP,
unsigned short  pass 
)

Definition at line 4890 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.

4897  {
4898  // Start a simple (seed) trajectory going from (fromWire, toTick) to (toWire, toTick).
4899 
4900  // decrement the work ID so we can use it for debugging problems
4901  --evt.WorkID;
4902  if (evt.WorkID == INT_MIN) evt.WorkID = -1;
4903  tj.ID = evt.WorkID;
4904  tj.Pass = pass;
4905  // Assume we are stepping in the positive WSE units direction
4906  short stepdir = 1;
4907  int fWire = std::nearbyint(fromWire);
4908  int tWire = std::nearbyint(toWire);
4909  if (tWire < fWire) { stepdir = -1; }
4910  else if (tWire == fWire) {
4911  // on the same wire
4912  if (toTick < fromTick) stepdir = -1;
4913  }
4914  tj.StepDir = stepdir;
4915  tj.CTP = tCTP;
4916  tj.ParentID = -1;
4917  tj.Strategy.reset();
4918  tj.Strategy[kNormal] = true;
4919 
4920  // create a trajectory point
4921  TrajPoint tp;
4922  if (!MakeBareTrajPoint(fromWire, fromTick, toWire, toTick, tCTP, tp)) return false;
4923  SetAngleCode(tp);
4924  tp.AngErr = 0.1;
4925  tj.Pts.push_back(tp);
4926  // turn on debugging using the WorkID?
4927  if (tcc.modes[kDebug] && !tcc.dbgStp && !tcc.dbgDump && tcc.dbgSlc && tj.ID == debug.WorkID)
4928  tcc.dbgStp = true;
4929  if (tcc.dbgStp) {
4930  auto& tp = tj.Pts[0];
4931  mf::LogVerbatim("TC") << "StartTraj T" << tj.ID << " from " << (int)fromWire << ":"
4932  << (int)fromTick << " -> " << (int)toWire << ":" << (int)toTick
4933  << " StepDir " << tj.StepDir << " dir " << tp.Dir[0] << " " << tp.Dir[1]
4934  << " ang " << tp.Ang << " AngleCode " << tp.AngleCode << " angErr "
4935  << tp.AngErr << " ExpectedHitsRMS " << ExpectedHitsRMS(tp);
4936  } // tcc.dbgStp
4937  return true;
4938 
4939  } // StartTraj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
void SetAngleCode(TrajPoint &tp)
Definition: Utils.cxx:765
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
int WorkID
Select the StartWorkID for debugging.
Definition: DebugStruct.h:28
DebugStuff debug
Definition: DebugStruct.cxx:4
bool MakeBareTrajPoint(const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
Definition: Utils.cxx:4059
float ExpectedHitsRMS(const TrajPoint &tp)
Definition: Utils.cxx:1911
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
TDirectory * dir
Definition: macro.C:5
TCEvent evt
Definition: DataStructs.cxx:8
master switch for turning on debug mode
Definition: DataStructs.h:524
void tca::StepAway ( TCSlice slc,
Trajectory tj 
)

Definition at line 30 of file StepUtils.cxx.

References util::abs(), AddHits(), tca::Trajectory::AlgMod, tca::TrajPoint::AngleCode, tca::TrajPoint::Chg, tca::TrajPoint::CTP, tca::Trajectory::CTP, tca::TCConfig::dbgStp, DeadWireCount(), DecodeCTP(), DefineHitPos(), DeltaAngle(), tca::TrajPoint::Dir, tca::TCConfig::doForecast, tca::Trajectory::EndFlag, tca::Trajectory::EndPt, tca::TrajPoint::Environment, evt, tca::TrajPoint::FitChi, Forecast(), tca::TCEvent::goodWire, GottaKink(), tca::TrajPoint::Hits, tca::Trajectory::ID, if(), tca::Trajectory::IsGood, kAtKink, kAtTj, kEnvNearSrcHit, kEnvNotGoodWire, kRvPrp, kSlowing, kStopBadFits, MaskedHitsOK(), tca::Trajectory::MaskedLastTP, tca::TCConfig::maxAngleCode, tca::TCConfig::maxChi, tca::TCConfig::maxPos0, tca::TCConfig::maxPos1, tca::TCConfig::maxWireSkipNoSignal, tca::TCConfig::maxWireSkipWithSignal, tca::TCConfig::minPtsFit, tca::Trajectory::NeedsUpdate, NumPtsWithCharge(), tca::Trajectory::Pass, tca::Trajectory::PDGCode, geo::PlaneID::Plane, tca::TrajPoint::Pos, PosSep2(), PrintPos(), PrintTP(), PrintTrajectory(), tca::Trajectory::Pts, SetEndPoints(), SetPDGCode(), SetStrategy(), SignalAtTp(), tca::TCSlice::slHits, tca::TrajPoint::Step, tca::Trajectory::StepDir, StopIfBadFits(), StopShort(), tca::Trajectory::Strategy, StrategyBitNames, tcc, tjfs, TrajPointSeparation(), UnsetUsedHits(), UpdateTraj(), tca::TCConfig::useAlg, tca::TrajPoint::UseHit, and tca::TCConfig::VLAStepSize.

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

31  {
32  // Step along the direction specified in the traj vector in steps of size step
33  // (wire spacing equivalents). Find hits between the last trajectory point and
34  // the last trajectory point + step. A new trajectory point is added if hits are
35  // found. Stepping continues until no signal is found for two consecutive steps
36  // or until a wire or time boundary is reached.
37 
38  tj.IsGood = false;
39  if (tj.Pts.empty()) return;
40 
41  unsigned short plane = DecodeCTP(tj.CTP).Plane;
42 
43  unsigned short lastPtWithUsedHits = tj.EndPt[1];
44 
45  unsigned short lastPt = lastPtWithUsedHits;
46  // Construct a local TP from the last TP that will be moved on each step.
47  // Only the Pos and Dir variables will be used
48  TrajPoint ltp;
49  ltp.CTP = tj.CTP;
50  ltp.Pos = tj.Pts[lastPt].Pos;
51  ltp.Dir = tj.Pts[lastPt].Dir;
52  // A second TP is cloned from the leading TP of tj, updated with hits, fit
53  // parameters,etc and possibly pushed onto tj as the next TP
54  TrajPoint tp;
55 
56  // assume it is good from here on
57  tj.IsGood = true;
58 
59  unsigned short nMissedSteps = 0;
60  // Use MaxChi chisq cut for stiff trajectories
61  bool useMaxChiCut = (tj.PDGCode == 13 || !tj.Strategy[kSlowing]);
62 
63  // Get the first forecast when there are 6 points with charge
64  tjfs.resize(1);
65  tjfs[0].nextForecastUpdate = 6;
66 
67  for (unsigned short step = 1; step < 10000; ++step) {
68  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
69  // analyze the Tj when there are 6 points to see if we should stop
70  if (npwc == 6 && StopShort(slc, tj, tcc.dbgStp)) break;
71  // Get a forecast of what is ahead.
72  if (tcc.doForecast && !tj.AlgMod[kRvPrp] &&
73  npwc == tjfs[tjfs.size() - 1].nextForecastUpdate) {
74  Forecast(slc, tj);
75  SetStrategy(slc, tj);
76  SetPDGCode(slc, tj);
77  }
78  // make a copy of the previous TP
79  lastPt = tj.Pts.size() - 1;
80  tp = tj.Pts[lastPt];
81  ++tp.Step;
82  double stepSize = tcc.VLAStepSize;
83  if (tp.AngleCode < 2) stepSize = std::abs(1 / ltp.Dir[0]);
84  // move the local TP position by one step in the right direction
85  for (unsigned short iwt = 0; iwt < 2; ++iwt)
86  ltp.Pos[iwt] += ltp.Dir[iwt] * stepSize;
87  // copy this position into tp
88  tp.Pos = ltp.Pos;
89  tp.Dir = ltp.Dir;
90  if (tcc.dbgStp) {
91  mf::LogVerbatim myprt("TC");
92  myprt << "StepAway " << step << " Pos " << tp.Pos[0] << " " << tp.Pos[1] << " Dir "
93  << tp.Dir[0] << " " << tp.Dir[1] << " stepSize " << stepSize << " AngCode "
94  << tp.AngleCode << " Strategy";
95  for (unsigned short ibt = 0; ibt < StrategyBitNames.size(); ++ibt) {
96  if (tj.Strategy[ibt]) myprt << " " << StrategyBitNames[ibt];
97  } // ib
98  } // tcc.dbgStp
99  // hit the boundary of the TPC?
100  if (tp.Pos[0] < 0 || tp.Pos[0] > tcc.maxPos0[plane] || tp.Pos[1] < 0 ||
101  tp.Pos[1] > tcc.maxPos1[plane])
102  break;
103  // remove the old hits and other stuff
104  tp.Hits.clear();
105  tp.UseHit.reset();
106  tp.FitChi = 0;
107  tp.Chg = 0;
108  tp.Environment.reset();
109  unsigned int wire = std::nearbyint(tp.Pos[0]);
110  if (!evt.goodWire[plane][wire]) tp.Environment[kEnvNotGoodWire] = true;
111  // append to the trajectory
112  tj.Pts.push_back(tp);
113  // update the index of the last TP
114  lastPt = tj.Pts.size() - 1;
115  // look for hits
116  bool sigOK = false;
117  AddHits(slc, tj, lastPt, sigOK);
118  // Check the stop flag
119  if (tj.EndFlag[1][kAtTj]) break;
120  // If successfull, AddHits has defined UseHit for this TP,
121  // set the trajectory endpoints, and define HitPos.
122  if (tj.Pts[lastPt].Hits.empty() && !tj.Pts[lastPt].Environment[kEnvNearSrcHit]) {
123  // Require three points with charge on adjacent wires for small angle
124  // stepping.
125  if (tj.Pts[lastPt].AngleCode == 0 && lastPt == 2) return;
126  // No close hits added.
127  ++nMissedSteps;
128  // First check for no signal in the vicinity. AddHits checks the hit collection for
129  // the current slice. This version of SignalAtTp checks the allHits collection.
130  sigOK = SignalAtTp(ltp);
131  if (lastPt > 0) {
132  // break if this is a reverse propagate activity and there was no signal (not on a dead wire)
133  if (!sigOK && tj.AlgMod[kRvPrp]) break;
134  // Ensure that there is a signal here after missing a number of steps on a LA trajectory
135  if (tj.Pts[lastPt].AngleCode > 0 && nMissedSteps > 4 && !sigOK) break;
136  // the last point with hits (used or not) is the previous point
137  unsigned short lastPtWithHits = lastPt - 1;
138  float tps = TrajPointSeparation(tj.Pts[lastPtWithHits], ltp);
139  float dwc = DeadWireCount(slc, ltp, tj.Pts[lastPtWithHits]);
140  float nMissedWires = tps * std::abs(ltp.Dir[0]) - dwc;
141  float maxWireSkip = tcc.maxWireSkipNoSignal;
142  if (sigOK) maxWireSkip = tcc.maxWireSkipWithSignal;
143  if (tcc.dbgStp)
144  mf::LogVerbatim("TC") << " StepAway: no hits found at ltp " << PrintPos(ltp)
145  << " nMissedWires " << std::fixed << std::setprecision(1)
146  << nMissedWires << " dead wire count " << dwc << " maxWireSkip "
147  << maxWireSkip << " tj.PDGCode " << tj.PDGCode;
148  if (nMissedWires > maxWireSkip) {
149  // We passed a number of wires without adding hits and are ready to quit.
150  // First see if there is one good unused hit on the end TP and if so use it
151  // lastPtWithHits + 1 == lastPt && tj.Pts[lastPtWithHits].Chg == 0 && tj.Pts[lastPtWithHits].Hits.size() == 1
152  if (tj.EndPt[1] < tj.Pts.size() - 1 && tj.Pts[tj.EndPt[1] + 1].Hits.size() == 1) {
153  unsigned short lastLonelyPoint = tj.EndPt[1] + 1;
154  unsigned int iht = tj.Pts[lastLonelyPoint].Hits[0];
155  if (slc.slHits[iht].InTraj == 0 &&
156  tj.Pts[lastLonelyPoint].Delta < 3 * tj.Pts[lastLonelyPoint].DeltaRMS) {
157  slc.slHits[iht].InTraj = tj.ID;
158  tj.Pts[lastLonelyPoint].UseHit[0] = true;
159  DefineHitPos(slc, tj.Pts[lastLonelyPoint]);
160  SetEndPoints(tj);
161  if (tcc.dbgStp) {
162  mf::LogVerbatim("TC") << " Added a Last Lonely Hit before breaking ";
163  PrintTP("LLH", slc, lastPt, tj.StepDir, tj.Pass, tj.Pts[lastLonelyPoint]);
164  }
165  }
166  }
167  break;
168  }
169  } // lastPt > 0
170  // no sense keeping this TP on tj if no hits were added
171  tj.Pts.pop_back();
172  continue;
173  } // tj.Pts[lastPt].Hits.empty()
174  // ensure that we actually moved
175  if (lastPt > 0 && PosSep2(tj.Pts[lastPt].Pos, tj.Pts[lastPt - 1].Pos) < 0.1) return;
176  // Found hits at this location so reset the missed steps counter
177  nMissedSteps = 0;
178  // Update the last point fit, etc using the just added hit(s)
179  UpdateTraj(slc, tj);
180  // a failure occurred
181  if (tj.NeedsUpdate) return;
182  if (tj.Pts[lastPt].Chg == 0) {
183  // There are points on the trajectory by none used in the last step. See
184  // how long this has been going on
185  float tps = TrajPointSeparation(tj.Pts[tj.EndPt[1]], ltp);
186  float dwc = DeadWireCount(slc, ltp, tj.Pts[tj.EndPt[1]]);
187  float nMissedWires = tps * std::abs(ltp.Dir[0]) - dwc;
188  if (tcc.dbgStp)
189  mf::LogVerbatim("TC") << " Hits exist on the trajectory but are not used. Missed wires "
190  << std::nearbyint(nMissedWires) << " dead wire count " << (int)dwc;
191  // break if this is a reverse propagate activity with no dead wires
192  if (tj.AlgMod[kRvPrp] && dwc == 0) break;
193  if (nMissedWires > tcc.maxWireSkipWithSignal) break;
194  // try this out
195  if (!MaskedHitsOK(slc, tj)) { return; }
196  // check for a series of bad fits and stop stepping
197  if (tcc.useAlg[kStopBadFits] && nMissedWires > 4 && StopIfBadFits(tj)) break;
198  // Keep stepping
199  if (tcc.dbgStp) {
200  if (tj.AlgMod[kRvPrp]) { PrintTrajectory("RP", slc, tj, lastPt); }
201  else {
202  PrintTrajectory("SC", slc, tj, lastPt);
203  }
204  }
205  continue;
206  } // tp.Hits.empty()
207  if (tj.Pts.size() == 3) {
208  // ensure that the last hit added is in the same direction as the first two.
209  // This is a simple way of doing it
210  bool badTj = (PosSep2(tj.Pts[0].HitPos, tj.Pts[2].HitPos) <
211  PosSep2(tj.Pts[0].HitPos, tj.Pts[1].HitPos));
212  // ensure that this didn't start as a small angle trajectory and immediately turn
213  // into a large angle one
214  if (!badTj && tj.Pts[lastPt].AngleCode > tcc.maxAngleCode[tj.Pass]) badTj = true;
215  // check for a large change in angle
216  if (!badTj) {
217  float dang = DeltaAngle(tj.Pts[0].Ang, tj.Pts[2].Ang);
218  if (dang > 0.5) badTj = false;
219  }
220  //check for a wacky delta
221  if (!badTj && tj.Pts[2].Delta > 2) badTj = true;
222  if (badTj) {
223  if (tcc.dbgStp)
224  mf::LogVerbatim("TC") << " Bad Tj found on the third point. Quit stepping.";
225  tj.IsGood = false;
226  return;
227  }
228  } // tj.Pts.size() == 3
229  // Update the local TP with the updated position and direction
230  ltp.Pos = tj.Pts[lastPt].Pos;
231  ltp.Dir = tj.Pts[lastPt].Dir;
232  if (tj.MaskedLastTP) {
233  // see if TPs have been masked off many times and if the
234  // environment is clean. If so, return and try with next pass
235  // cuts
236  if (!MaskedHitsOK(slc, tj)) {
237  if (tcc.dbgStp) {
238  if (tj.AlgMod[kRvPrp]) { PrintTrajectory("RP", slc, tj, lastPt); }
239  else {
240  PrintTrajectory("SC", slc, tj, lastPt);
241  }
242  }
243  return;
244  }
245  if (tcc.dbgStp) {
246  if (tj.AlgMod[kRvPrp]) { PrintTrajectory("RP", slc, tj, lastPt); }
247  else {
248  PrintTrajectory("SC", slc, tj, lastPt);
249  }
250  }
251  continue;
252  }
253  // We have added a TP with hits
254  // check for a kink. Stop crawling if one is found
255  GottaKink(slc, tj, true);
256  if (tj.EndFlag[1][kAtKink]) {
257  if (tcc.dbgStp) mf::LogVerbatim("TC") << " stop at kink";
258  break;
259  }
260  // See if the Chisq/DOF exceeds the maximum.
261  // UpdateTraj should have reduced the number of points fit
262  // as much as possible for this pass, so this trajectory is in trouble.
263  if (tj.Pts[lastPt].FitChi > tcc.maxChi && useMaxChiCut) {
264  if (tcc.dbgStp)
265  mf::LogVerbatim("TC") << " bad FitChi " << tj.Pts[lastPt].FitChi << " cut "
266  << tcc.maxChi;
267  // remove the last point before quitting
268  UnsetUsedHits(slc, tj.Pts[lastPt]);
269  SetEndPoints(tj);
270  tj.IsGood = (NumPtsWithCharge(slc, tj, true) > tcc.minPtsFit[tj.Pass]);
271  break;
272  }
273  if (tcc.dbgStp) {
274  if (tj.AlgMod[kRvPrp]) { PrintTrajectory("RP", slc, tj, lastPt); }
275  else {
276  PrintTrajectory("SC", slc, tj, lastPt);
277  }
278  } // tcc.dbgStp
279  } // step
280 
281  SetPDGCode(slc, tj);
282 
283  if (tcc.dbgStp) mf::LogVerbatim("TC") << "End StepAway with tj size " << tj.Pts.size();
284 
285  } // StepAway
void Forecast(TCSlice &slc, const Trajectory &tj)
Definition: StepUtils.cxx:460
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MaskedHitsOK(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2619
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
void UpdateTraj(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:705
std::vector< float > maxPos0
Definition: DataStructs.h:563
std::vector< unsigned short > minPtsFit
Reconstruct in several passes.
Definition: DataStructs.h:556
bool SignalAtTp(TrajPoint &tp)
Definition: Utils.cxx:1964
void SetPDGCode(TCSlice &slc, unsigned short itj)
Definition: Utils.cxx:4219
void AddHits(TCSlice &slc, Trajectory &tj, unsigned short ipt, bool &sigOK)
Definition: StepUtils.cxx:1113
TCConfig tcc
Definition: DataStructs.cxx:9
void PrintTrajectory(std::string someText, const TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:6035
void PrintTP(std::string someText, const TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, const TrajPoint &tp)
Definition: Utils.cxx:6134
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1061
bool StopShort(TCSlice &slc, Trajectory &tj, bool prt)
Definition: StepUtils.cxx:288
void SetStrategy(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:352
constexpr auto abs(T v)
Returns the absolute value of the argument.
float maxWireSkipWithSignal
max number of wires to skip with a signal on them
Definition: DataStructs.h:574
float TrajPointSeparation(const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2613
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:2531
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
bool doForecast
See TCMode_t above.
Definition: DataStructs.h:600
std::vector< unsigned short > maxAngleCode
max allowed angle code for each pass
Definition: DataStructs.h:558
const std::vector< std::string > StrategyBitNames
Definition: DataStructs.cxx:98
if(nlines<=0)
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
std::vector< float > maxPos1
Definition: DataStructs.h:564
use the slowing-down strategy
Definition: DataStructs.h:494
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2095
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1791
TP is near a hit in the srcHit collection but no allHit hit exists (DUNE disambiguation error) ...
Definition: DataStructs.h:516
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:622
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2560
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
float maxWireSkipNoSignal
max number of wires to skip w/o a signal on them
Definition: DataStructs.h:573
std::vector< TjForecast > tjfs
Definition: DataStructs.cxx:10
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
float VLAStepSize
Definition: DataStructs.h:576
geo::PlaneID DecodeCTP(CTP_t CTP)
bool GottaKink(TCSlice &slc, Trajectory &tj, bool doTrim)
Definition: StepUtils.cxx:2756
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
TCEvent evt
Definition: DataStructs.cxx:8
bool StopIfBadFits(Trajectory &tj)
Definition: StepUtils.cxx:2729
void tca::StitchPFPs ( )

Definition at line 42 of file PFPUtils.cxx.

References util::abs(), tca::TCConfig::dbgStitch, debug, DirAtEnd(), DotProd(), util::end(), tca::TCConfig::geom, GetSliceIndex(), InsideFV(), geo::GeometryCore::NTPC(), tca::TCConfig::pfpStitchCuts, PosAtEnd(), PosSep2(), PrintP(), tca::DebugStuff::Slice, slices, tcc, and tmp.

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

43  {
44  // Stitch PFParticles in different TPCs. This does serious damage to PFPStruct and should
45  // only be called from TrajCluster module just before making PFParticles to put in the event
46  if (slices.size() < 2) return;
47  if (tcc.geom->NTPC() == 1) return;
48  if (tcc.pfpStitchCuts.size() < 2) return;
49  if (tcc.pfpStitchCuts[0] <= 0) return;
50 
51  bool prt = tcc.dbgStitch;
52 
53  if (prt) {
54  mf::LogVerbatim myprt("TC");
55  std::string fcnLabel = "SP";
56  myprt << fcnLabel << " cuts " << sqrt(tcc.pfpStitchCuts[0]) << " " << tcc.pfpStitchCuts[1]
57  << "\n";
58  bool printHeader = true;
59  for (size_t isl = 0; isl < slices.size(); ++isl) {
60  if (debug.Slice >= 0 && int(isl) != debug.Slice) continue;
61  auto& slc = slices[isl];
62  if (slc.pfps.empty()) continue;
63  for (auto& pfp : slc.pfps)
64  PrintP(myprt, pfp, printHeader);
65  } // slc
66  } // prt
67 
68  // lists of pfp UIDs to stitch
69  std::vector<std::vector<int>> stLists;
70  for (std::size_t sl1 = 0; sl1 < slices.size() - 1; ++sl1) {
71  auto& slc1 = slices[sl1];
72  for (std::size_t sl2 = sl1 + 1; sl2 < slices.size(); ++sl2) {
73  auto& slc2 = slices[sl2];
74  // look for PFParticles in the same recob::Slice
75  if (slc1.ID != slc2.ID) continue;
76  for (auto& p1 : slc1.pfps) {
77  if (p1.ID <= 0) continue;
78  // Can't stitch shower PFPs
79  if (p1.PDGCode == 1111) continue;
80  for (auto& p2 : slc2.pfps) {
81  if (p2.ID <= 0) continue;
82  // Can't stitch shower PFPs
83  if (p2.PDGCode == 1111) continue;
84  float maxSep2 = tcc.pfpStitchCuts[0];
85  float maxCth = tcc.pfpStitchCuts[1];
86  bool gotit = false;
87  for (unsigned short e1 = 0; e1 < 2; ++e1) {
88  auto pos1 = PosAtEnd(p1, e1);
89  // require the end to be close to a TPC boundary
90  if (InsideFV(slc1, p1, e1)) continue;
91  auto dir1 = DirAtEnd(p1, e1);
92  for (unsigned short e2 = 0; e2 < 2; ++e2) {
93  auto pos2 = PosAtEnd(p2, e2);
94  // require the end to be close to a TPC boundary
95  if (InsideFV(slc2, p2, e2)) continue;
96  auto dir2 = DirAtEnd(p2, e2);
97  float sep = PosSep2(pos1, pos2);
98  if (sep > maxSep2) continue;
99  float cth = std::abs(DotProd(dir1, dir2));
100  if (cth < maxCth) continue;
101  maxSep2 = sep;
102  maxCth = cth;
103  gotit = true;
104  } // e2
105  } // e1
106  if (!gotit) continue;
107  if (prt) {
108  mf::LogVerbatim myprt("TC");
109  myprt << "Stitch slice " << slc1.ID << " P" << p1.UID << " TPC " << p1.TPCID.TPC;
110  myprt << " and P" << p2.UID << " TPC " << p2.TPCID.TPC;
111  myprt << " sep " << sqrt(maxSep2) << " maxCth " << maxCth;
112  }
113  // see if either of these are in a list
114  bool added = false;
115  for (auto& pm : stLists) {
116  bool p1InList = (std::find(pm.begin(), pm.end(), p1.UID) != pm.end());
117  bool p2InList = (std::find(pm.begin(), pm.end(), p2.UID) != pm.end());
118  if (p1InList || p2InList) {
119  if (p1InList) pm.push_back(p2.UID);
120  if (p2InList) pm.push_back(p1.UID);
121  added = true;
122  }
123  } // pm
124  if (added) continue;
125  // start a new list
126  std::vector<int> tmp(2);
127  tmp[0] = p1.UID;
128  tmp[1] = p2.UID;
129  stLists.push_back(tmp);
130  break;
131  } // p2
132  } // p1
133  } // sl2
134  } // sl1
135  if (stLists.empty()) return;
136 
137  for (auto& stl : stLists) {
138  // Find the endpoints of the stitched pfp
139  float minZ = 1E6;
140  std::pair<unsigned short, unsigned short> minZIndx;
141  unsigned short minZEnd = 2;
142  for (auto puid : stl) {
143  auto slcIndex = GetSliceIndex("P", puid);
144  if (slcIndex.first == USHRT_MAX) continue;
145  auto& pfp = slices[slcIndex.first].pfps[slcIndex.second];
146  for (unsigned short end = 0; end < 2; ++end) {
147  auto pos = PosAtEnd(pfp, end);
148  if (pos[2] < minZ) {
149  minZ = pos[2];
150  minZIndx = slcIndex;
151  minZEnd = end;
152  }
153  } // end
154  } // puid
155  if (minZEnd > 1) continue;
156  // preserve the pfp with the min Z position
157  auto& pfp = slices[minZIndx.first].pfps[minZIndx.second];
158  if (prt) mf::LogVerbatim("TC") << "SP: P" << pfp.UID;
159  // add the Tjs in the other slices to it
160  for (auto puid : stl) {
161  if (puid == pfp.UID) continue;
162  auto sIndx = GetSliceIndex("P", puid);
163  if (sIndx.first == USHRT_MAX) continue;
164  auto& opfp = slices[sIndx.first].pfps[sIndx.second];
165  if (prt) mf::LogVerbatim("TC") << " +P" << opfp.UID;
166  pfp.TjUIDs.insert(pfp.TjUIDs.end(), opfp.TjUIDs.begin(), opfp.TjUIDs.end());
167  if (prt) mf::LogVerbatim();
168  // Check for parents and daughters
169  if (opfp.ParentUID > 0) {
170  auto pSlcIndx = GetSliceIndex("P", opfp.ParentUID);
171  if (pSlcIndx.first < slices.size()) {
172  auto& parpfp = slices[pSlcIndx.first].pfps[pSlcIndx.second];
173  std::replace(parpfp.DtrUIDs.begin(), parpfp.DtrUIDs.begin(), opfp.UID, pfp.UID);
174  } // valid pSlcIndx
175  } // has a parent
176  for (auto dtruid : opfp.DtrUIDs) {
177  auto dSlcIndx = GetSliceIndex("P", dtruid);
178  if (dSlcIndx.first < slices.size()) {
179  auto& dtrpfp = slices[dSlcIndx.first].pfps[dSlcIndx.second];
180  dtrpfp.ParentUID = pfp.UID;
181  } // valid dSlcIndx
182  } // dtruid
183  // declare it obsolete
184  opfp.ID = 0;
185  } // puid
186  } // stl
187 
188  } // StitchPFPs
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool dbgStitch
debug PFParticle stitching
Definition: DataStructs.h:595
bool InsideFV(const TCSlice &slc, const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3019
TCConfig tcc
Definition: DataStructs.cxx:9
unsigned int NTPC(CryostatID const &cryoid=details::cryostat_zero) const
Returns the total number of TPCs in the specified cryostat.
Definition: GeometryCore.h:416
constexpr auto abs(T v)
Returns the absolute value of the argument.
Float_t tmp
Definition: plot.C:35
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3257
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
DebugStuff debug
Definition: DebugStruct.cxx:4
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2560
const geo::GeometryCore * geom
Definition: DataStructs.h:567
void PrintP(mf::LogVerbatim &myprt, PFPStruct const &pfp, bool &printHeader)
Definition: Utils.cxx:5453
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:126
std::vector< float > pfpStitchCuts
cuts for stitching between TPCs
Definition: DataStructs.h:555
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:4942
Vector3_t DirAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3249
bool tca::StopIfBadFits ( Trajectory tj)

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

2730  {
2731  // Returns true if there are a number of Tps that were not used in the trajectory because the fit was poor and the
2732  // charge pull is not really high. This
2733 
2734  // don't consider muons
2735  if (tj.PDGCode == 13) return false;
2736  // or long straight Tjs
2737  if (tj.Pts.size() > 40 && tj.MCSMom > 200) return false;
2738 
2739  unsigned short nBadFit = 0;
2740  unsigned short nHiChg = 0;
2741  unsigned short cnt = 0;
2742  for (unsigned short ipt = tj.Pts.size() - 1; ipt > tj.EndPt[1]; --ipt) {
2743  if (tj.Pts[ipt].FitChi > 2) ++nBadFit;
2744  if (tj.Pts[ipt].ChgPull > 3) ++nHiChg;
2745  ++cnt;
2746  if (cnt == 5) break;
2747  } // ipt
2748 
2749  if (tcc.dbgStp)
2750  mf::LogVerbatim("TC") << "StopIfBadFits: nBadFit " << nBadFit << " nHiChg " << nHiChg;
2751 
2752  return nBadFit > 3 && nHiChg == 0;
2753  } // StopIfBadFits
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
bool tca::StopShort ( TCSlice slc,
Trajectory tj,
bool  prt 
)

Definition at line 288 of file StepUtils.cxx.

References tca::Trajectory::AlgMod, tca::ParFit::ChiDOF, tca::Trajectory::EndPt, FitPar(), kRvPrp, kStopShort, NumPtsWithCharge(), tca::ParFit::Par0, tca::ParFit::ParErr, tca::ParFit::ParSlp, tca::ParFit::ParSlpErr, PrintPos(), PrintTrajectory(), tca::Trajectory::Pts, SetEndPoints(), tcc, UnsetUsedHits(), UpdateTjChgProperties(), and tca::TCConfig::useAlg.

Referenced by StepAway().

289  {
290  // Analyze the trajectory when it is short (~6 points) to look for a pattern like
291  // this QQQqqq, where Q is a large charge hit and q is a low charge hit. If this
292  // pattern is found, this function removes the last 3 points and returns true.
293  // The calling function (e.g. StepAway) should decide what to do (e.g. stop stepping)
294 
295  // don't use this function during reverse propagation
296  if (tj.AlgMod[kRvPrp]) return false;
297  if (!tcc.useAlg[kStopShort]) return false;
298 
299  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
300  if (npwc > 10) return false;
301  ParFit chgFit;
302  FitPar(tj, tj.EndPt[0], npwc, 1, chgFit, 1);
303  if (prt) {
304  mf::LogVerbatim myprt("TC");
305  myprt << "StopShort: chgFit at " << PrintPos(tj.Pts[tj.EndPt[0]]);
306  myprt << " ChiDOF " << chgFit.ChiDOF;
307  myprt << " chg0 " << chgFit.Par0 << " +/- " << chgFit.ParErr;
308  myprt << " slp " << chgFit.ParSlp << " +/- " << chgFit.ParSlpErr;
309  } // prt
310  // Look for a poor charge fit ChiDOF and a significant negative slope. These cuts
311  // **should** prevent removing a genuine Bragg peak at the start, which should have
312  // a good ChiDOF
313  if (chgFit.ChiDOF < 2) return false;
314  if (chgFit.ParSlp > -20) return false;
315  if (prt) PrintTrajectory("SS", slc, tj, USHRT_MAX);
316  // Find the average charge using the first 3 points
317  float cnt = 0;
318  float aveChg = 0;
319  unsigned short lastHiPt = 0;
320  for (unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) {
321  auto& tp = tj.Pts[ipt];
322  if (tp.Chg <= 0) continue;
323  aveChg += tp.Chg;
324  ++cnt;
325  lastHiPt = ipt;
326  if (cnt == 3) break;
327  } // tp
328  if (cnt < 3) return false;
329  aveChg /= cnt;
330  if (prt)
331  mf::LogVerbatim("TC") << " aveChg " << (int)aveChg << " last TP AveChg "
332  << (int)tj.Pts[tj.EndPt[1]].AveChg;
333  // Look for a sudden drop in the charge (< 1/2)
334  unsigned short firstLoPt = lastHiPt + 1;
335  for (unsigned short ipt = lastHiPt + 1; ipt < tj.Pts.size(); ++ipt) {
336  auto& tp = tj.Pts[ipt];
337  if (tp.Chg <= 0 || tp.Chg > 0.5 * aveChg) continue;
338  firstLoPt = ipt;
339  break;
340  } // ipt
341  if (prt) mf::LogVerbatim("TC") << " stop tracking at " << PrintPos(tj.Pts[firstLoPt]);
342  // Remove everything from the firstLoPt to the end of the trajectory
343  for (unsigned short ipt = firstLoPt; ipt <= tj.EndPt[1]; ++ipt)
344  UnsetUsedHits(slc, tj.Pts[ipt]);
345  SetEndPoints(tj);
346  UpdateTjChgProperties("SS", slc, tj, prt);
347  tj.AlgMod[kStopShort] = true;
348  return true;
349  } // StopShort
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
TCConfig tcc
Definition: DataStructs.cxx:9
void PrintTrajectory(std::string someText, const TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:6035
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1061
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
void FitPar(const Trajectory &tj, unsigned short originPt, unsigned short npts, short fitDir, ParFit &pFit, unsigned short usePar)
Definition: Utils.cxx:1202
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice const &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3577
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
bool tca::StorePFP ( TCSlice slc,
PFPStruct pfp 
)

Definition at line 2979 of file PFPUtils.cxx.

References evt, tca::PFPStruct::Flags, tca::TCEvent::globalP_UID, tca::PFPStruct::ID, kMat3D, kSmallAngle, kTP3DBad, tca::PFPStruct::PDGCode, tca::TCSlice::pfps, tca::PFPStruct::TjIDs, tca::TCSlice::tjs, tca::PFPStruct::TP3Ds, and tca::PFPStruct::UID.

Referenced by DefineTjParents(), DotProd(), and MakePFParticles().

2980  {
2981  // stores the PFParticle in the slice
2982  bool neutrinoPFP = (pfp.PDGCode == 12 || pfp.PDGCode == 14);
2983  if (!neutrinoPFP) {
2984  if (pfp.TjIDs.empty()) return false;
2985  if (pfp.PDGCode != 1111 && pfp.TP3Ds.size() < 2) return false;
2986  }
2987 
2988  if (pfp.Flags[kSmallAngle]) {
2989  // Make the PFP -> TP assn
2990  for (auto& tp3d : pfp.TP3Ds) {
2991  if (tp3d.TPIndex != USHRT_MAX) slc.tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex].InPFP = pfp.ID;
2992  }
2993  }
2994 
2995  // ensure that the InPFP flag is set
2996  unsigned short nNotSet = 0;
2997  for (auto& tp3d : pfp.TP3Ds) {
2998  if (tp3d.Flags[kTP3DBad]) continue;
2999  auto& tp = slc.tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
3000  if (tp.InPFP != pfp.ID) ++nNotSet;
3001  } // tp3d
3002  if (nNotSet > 0) return false;
3003  // check the ID and correct it if it is wrong
3004  if (pfp.ID != (int)slc.pfps.size() + 1) pfp.ID = slc.pfps.size() + 1;
3005  ++evt.globalP_UID;
3006  pfp.UID = evt.globalP_UID;
3007 
3008  // set the 3D match flag
3009  for (auto tjid : pfp.TjIDs) {
3010  auto& tj = slc.tjs[tjid - 1];
3011  tj.AlgMod[kMat3D] = true;
3012  } // tjid
3013 
3014  slc.pfps.push_back(pfp);
3015  return true;
3016  } // StorePFP
TCEvent evt
Definition: DataStructs.cxx:8
bool tca::StoreShower ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct3D ss3 
)

Definition at line 3933 of file TCShower.cxx.

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

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

3934  {
3935  // Store a 3D shower. This function sets the 3S -> 2S assns using CotIDs and ensures
3936  // that the 2S -> 3S assns are OK.
3937 
3938  std::string fcnLabel = inFcnLabel + ".S3S";
3939  if (ss3.ID <= 0) {
3940  std::cout << fcnLabel << " Invalid ID";
3941  return false;
3942  }
3943  if (ss3.CotIDs.size() < 2) {
3944  std::cout << fcnLabel << " not enough CotIDs";
3945  return false;
3946  }
3947 
3948  // check the 2S -> 3S assns
3949  for (auto& ss : slc.cots) {
3950  if (ss.ID == 0) continue;
3951  if (ss.SS3ID == ss3.ID &&
3952  std::find(ss3.CotIDs.begin(), ss3.CotIDs.end(), ss.ID) == ss3.CotIDs.end()) {
3953  std::cout << fcnLabel << " Bad assn: 2S" << ss.ID << " -> 3S" << ss3.ID
3954  << " but it's not inCotIDs.\n";
3955  return false;
3956  }
3957  } // ss
3958 
3959  // check the 3S -> 2S assns
3960  for (auto cid : ss3.CotIDs) {
3961  if (cid <= 0 || cid > (int)slc.cots.size()) return false;
3962  auto& ss = slc.cots[cid - 1];
3963  if (ss.SS3ID > 0 && ss.SS3ID != ss3.ID) {
3964  std::cout << fcnLabel << " Bad assn: 3S" << ss3.ID << " -> 2S" << cid << " but 2S -> 3S"
3965  << ss.SS3ID << "\n";
3966  return false;
3967  }
3968  } // cid
3969 
3970  // set the 2S -> 3S assns
3971  for (auto cid : ss3.CotIDs)
3972  slc.cots[cid - 1].SS3ID = ss3.ID;
3973 
3974  ++evt.global3S_UID;
3975  ss3.UID = evt.global3S_UID;
3976 
3977  slc.showers.push_back(ss3);
3978  return true;
3979 
3980  } // StoreShower
TCEvent evt
Definition: DataStructs.cxx:8
bool tca::StoreShower ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct ss 
)

Definition at line 3983 of file TCShower.cxx.

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

3984  {
3985  // Store a ShowerStruct
3986  std::string fcnLabel = inFcnLabel + ".S2S";
3987  if (ss.ID <= 0) {
3988  std::cout << fcnLabel << " Invalid ID";
3989  return false;
3990  }
3991  if (ss.TjIDs.empty()) {
3992  std::cout << fcnLabel << " Fail: No TjIDs in 2S" << ss.ID << "\n";
3993  return false;
3994  }
3995  if (ss.ParentID > 0) {
3996  if (ss.ParentID > (int)slc.tjs.size()) {
3997  std::cout << fcnLabel << " Fail: 2S" << ss.ID << " has an invalid ParentID T" << ss.ParentID
3998  << "\n";
3999  return false;
4000  }
4001  if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), ss.ParentID) != ss.TjIDs.end()) {
4002  std::cout << fcnLabel << " Fail: 2S" << ss.ID << " ParentID is not in TjIDs.\n";
4003  return false;
4004  }
4005  } // ss.ParentID > 0
4006 
4007  // check the ID
4008  if (ss.ID != (int)slc.cots.size() + 1) {
4009  std::cout << fcnLabel << " Correcting the ID 2S" << ss.ID << " -> 2S" << slc.cots.size() + 1;
4010  ss.ID = slc.cots.size() + 1;
4011  }
4012 
4013  // set the tj shower bits
4014  for (auto& tjID : ss.TjIDs) {
4015  Trajectory& tj = slc.tjs[tjID - 1];
4016  tj.SSID = ss.ID;
4017  tj.AlgMod[kShwrParent] = false;
4018  if (tj.ID == ss.ParentID) tj.AlgMod[kShwrParent] = true;
4019  } // tjID
4020 
4021  ++evt.global2S_UID;
4022  ss.UID = evt.global2S_UID;
4023 
4024  slc.cots.push_back(ss);
4025  return true;
4026 
4027  } // StoreShower
TCEvent evt
Definition: DataStructs.cxx:8
bool tca::StoreTraj ( TCSlice slc,
Trajectory tj 
)

Definition at line 1074 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::TCConfig::dbgSlc, debug, tca::Trajectory::EndPt, evt, tca::TCEvent::globalT_UID, tca::DebugStuff::Hit, tca::Trajectory::ID, kDebug, tca::TCConfig::kinkCuts, KinkSignificance(), kJunkTj, tca::TCConfig::modes, tca::Trajectory::NeedsUpdate, tca::Trajectory::ParentID, PrintHit(), tca::Trajectory::Pts, ReleaseHits(), SetEndPoints(), tca::TCSlice::slHits, sum, tcc, tca::TCSlice::tjs, tca::Trajectory::UID, UpdateTjChgProperties(), and tca::Trajectory::WorkID.

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

1075  {
1076  // check for errors
1077  for (auto& tp : tj.Pts) {
1078  if (tp.Hits.size() > 16) return false;
1079  } // tp
1080 
1081  if (tj.NeedsUpdate) UpdateTjChgProperties("ST", slc, tj, false);
1082 
1083  // This shouldn't be necessary but do it anyway
1084  SetEndPoints(tj);
1085 
1086  if (slc.tjs.size() >= USHRT_MAX || tj.EndPt[1] <= tj.EndPt[0] || tj.EndPt[1] > tj.Pts.size()) {
1087  ReleaseHits(slc, tj);
1088  return false;
1089  }
1090 
1091  unsigned short npts = tj.EndPt[1] - tj.EndPt[0] + 1;
1092  if (npts < 2) return false;
1093 
1094  auto& endTp0 = tj.Pts[tj.EndPt[0]];
1095  auto& endTp1 = tj.Pts[tj.EndPt[1]];
1096 
1097  // ensure that angle errors are defined at both ends, ignoring junk Tjs
1098  if (!tj.AlgMod[kJunkTj]) {
1099  if (endTp0.AngErr == 0.1 && endTp1.AngErr != 0.1) { endTp0.AngErr = endTp1.AngErr; }
1100  else if (endTp0.AngErr != 0.1 && endTp1.AngErr == 0.1) {
1101  endTp1.AngErr = endTp0.AngErr;
1102  }
1103  } // not a junk Tj
1104 
1105  // Calculate the charge near the end and beginning if necessary. This must be a short
1106  // trajectory. Find the average using 4 points
1107  if (endTp0.AveChg <= 0) {
1108  unsigned short cnt = 0;
1109  float sum = 0;
1110  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1111  if (tj.Pts[ipt].Chg == 0) continue;
1112  sum += tj.Pts[ipt].Chg;
1113  ++cnt;
1114  if (cnt == 4) break;
1115  }
1116  tj.Pts[tj.EndPt[0]].AveChg = sum / (float)cnt;
1117  }
1118  if (endTp1.AveChg <= 0 && npts < 5) endTp1.AveChg = endTp0.AveChg;
1119  if (endTp1.AveChg <= 0) {
1120  float sum = 0;
1121  unsigned short cnt = 0;
1122  for (unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
1123  short ipt = tj.EndPt[1] - ii;
1124  if (ipt < 0) break;
1125  if (tj.Pts[ipt].Chg == 0) continue;
1126  sum += tj.Pts[ipt].Chg;
1127  ++cnt;
1128  if (cnt == 4) break;
1129  if (ipt == 0) break;
1130  } // ii
1131  tj.Pts[tj.EndPt[1]].AveChg = sum / (float)cnt;
1132  } // begin charge == end charge
1133 
1134  // update the kink significance
1135  if (!tj.AlgMod[kJunkTj]) {
1136  unsigned short nPtsFit = tcc.kinkCuts[0];
1137  bool useChg = (tcc.kinkCuts[2] > 0);
1138  if (npts > 2 * nPtsFit) {
1139  for (unsigned short ipt = tj.EndPt[0] + nPtsFit; ipt < tj.EndPt[1] - nPtsFit; ++ipt) {
1140  auto& tp = tj.Pts[ipt];
1141  if (tp.KinkSig < 0) tp.KinkSig = KinkSignificance(slc, tj, ipt, nPtsFit, useChg, false);
1142  }
1143  } // long trajectory
1144  } // not JunkTj
1145 
1146  UpdateTjChgProperties("ST", slc, tj, false);
1147 
1148  int trID = slc.tjs.size() + 1;
1149 
1150  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
1151  for (unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
1152  if (tj.Pts[ipt].UseHit[ii]) {
1153  unsigned int iht = tj.Pts[ipt].Hits[ii];
1154  if (iht > slc.slHits.size() - 1) {
1155  ReleaseHits(slc, tj);
1156  return false;
1157  }
1158  if (slc.slHits[iht].InTraj > 0) {
1159  ReleaseHits(slc, tj);
1160  return false;
1161  } // error
1162  slc.slHits[iht].InTraj = trID;
1163  }
1164  } // ii
1165  } // ipt
1166 
1167  // ensure that inTraj is clean for the ID
1168  for (unsigned int iht = 0; iht < slc.slHits.size(); ++iht) {
1169  if (slc.slHits[iht].InTraj == tj.ID) {
1170  mf::LogWarning("TC") << "StoreTraj: Hit " << PrintHit(slc.slHits[iht])
1171  << " thinks it belongs to T" << tj.ID << " but it isn't in the Tj\n";
1172  return false;
1173  }
1174  } // iht
1175 
1176  tj.WorkID = tj.ID;
1177  tj.ID = trID;
1178  // increment the global ID
1179  ++evt.globalT_UID;
1180  tj.UID = evt.globalT_UID;
1181  // Don't clobber the ParentID if it was defined by the calling function
1182  if (tj.ParentID == 0) tj.ParentID = trID;
1183  slc.tjs.push_back(tj);
1184  if (tcc.modes[kDebug] && tcc.dbgSlc && debug.Hit != UINT_MAX) {
1185  // print some debug info
1186  for (unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) {
1187  for (unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
1188  unsigned int iht = tj.Pts[ipt].Hits[ii];
1189  if (slc.slHits[iht].allHitsIndex == debug.Hit) {
1190  std::cout << "Debug hit appears in trajectory w WorkID " << tj.WorkID << " UseHit "
1191  << tj.Pts[ipt].UseHit[ii] << "\n";
1192  }
1193  } // ii
1194  } // ipt
1195  } // debug.Hit ...
1196 
1197  return true;
1198 
1199  } // StoreTraj
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
std::vector< float > kinkCuts
kink finder algorithm
Definition: DataStructs.h:550
float KinkSignificance(TCSlice const &slc, Trajectory &tj, unsigned short kinkPt, unsigned short nPtsFit, bool useChg, bool prt)
Definition: Utils.cxx:3041
TCConfig tcc
Definition: DataStructs.cxx:9
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
unsigned int Hit
set to the hit index in evt.allHits if a Plane:Wire:Tick match is found
Definition: DebugStruct.h:26
DebugStuff debug
Definition: DebugStruct.cxx:4
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6347
void ReleaseHits(TCSlice &slc, Trajectory const &tj)
Definition: Utils.cxx:1049
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:599
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice const &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3577
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
TCEvent evt
Definition: DataStructs.cxx:8
Double_t sum
Definition: plot.C:31
master switch for turning on debug mode
Definition: DataStructs.h:524
bool tca::StoreVertex ( TCSlice slc,
VtxStore vx 
)

Definition at line 1908 of file TCVertex.cxx.

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

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

1909  {
1910  // jacket around the push to ensure that the Tj and vtx CTP is consistent.
1911  // The calling function should score the vertex after the trajectories are attached
1912 
1913  if (vx.ID != int(slc.vtxs.size() + 1)) return false;
1914 
1915  ++evt.global2V_UID;
1916  vx.UID = evt.global2V_UID;
1917 
1918  unsigned short nvxtj = 0;
1919  unsigned short nok = 0;
1920  for (auto& tj : slc.tjs) {
1921  if (tj.AlgMod[kKilled]) continue;
1922  if (vx.ID == tj.VtxID[0] || vx.ID == tj.VtxID[1]) ++nvxtj;
1923  if (vx.CTP != tj.CTP) continue;
1924  if (vx.ID == tj.VtxID[0] || vx.ID == tj.VtxID[1]) ++nok;
1925  } // tj
1926 
1927  if (nok != nvxtj) {
1928  mf::LogVerbatim("TC") << "StoreVertex: vertex " << vx.ID << " Topo " << vx.Topo
1929  << " has inconsistent CTP code " << vx.CTP << " with one or more Tjs\n";
1930  for (auto& tj : slc.tjs) {
1931  if (tj.AlgMod[kKilled]) continue;
1932  if (tj.VtxID[0] == vx.ID) tj.VtxID[0] = 0;
1933  if (tj.VtxID[1] == vx.ID) tj.VtxID[1] = 0;
1934  }
1935  return false;
1936  }
1937  vx.NTraj = nok;
1938  slc.vtxs.push_back(vx);
1939  return true;
1940  } // StoreVertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCEvent evt
Definition: DataStructs.cxx:8
void tca::TagJunkTj ( Trajectory tj,
bool  prt 
)

Definition at line 2716 of file Utils.cxx.

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

Referenced by CheckTraj().

2717  {
2718  // Characterizes the trajectory as a junk tj even though it may not
2719  // have been reconstructed in FindJunkTraj. The distinguishing feature is
2720  // that it is short and has many used hits in each trajectory point.
2721 
2722  // Don't bother if it is too long
2723  if (tj.Pts.size() > 10) return;
2724  if (tj.PDGCode == 111) return;
2725  // count the number of points that have many used hits
2726  unsigned short nhm = 0;
2727  unsigned short npwc = 0;
2728  for (auto& tp : tj.Pts) {
2729  if (tp.Chg == 0) continue;
2730  ++npwc;
2731  unsigned short nused = 0;
2732  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2733  if (tp.UseHit[ii]) ++nused;
2734  } // ii
2735  if (nused > 3) ++nhm;
2736  } // tp
2737  // Set the junkTj bit if most of the hits are used in most of the tps
2738  if (nhm > 0.5 * npwc) tj.AlgMod[kJunkTj] = true;
2739  if (prt)
2740  mf::LogVerbatim("TC") << "TGT: T" << tj.ID << " npwc " << npwc << " nhm " << nhm << " junk? "
2741  << tj.AlgMod[kJunkTj];
2742  } // TagJunkTj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void tca::TagShowerLike ( TCSlice slc,
const CTP_t inCTP 
)

Definition at line 3232 of file TCShower.cxx.

References util::begin(), tca::TCConfig::chargeCuts, tca::DebugStuff::CTP, tca::TCConfig::dbg2S, tca::TCConfig::dbgSlc, debug, util::end(), tca::Trajectory::ID, kBragg, kHaloTj, kKilled, kShowerLike, kShowerTj, NumPtsWithCharge(), tca::TCConfig::showerTag, tcc, tca::TCSlice::tjs, and TrajTrajDOCA().

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

3233  {
3234  // Tag Tjs as InShower if they have MCSMom < ShowerTag[1] and there are more than
3235  // ShowerTag[6] other Tjs with a separation < ShowerTag[2].
3236 
3237  if (tcc.showerTag[0] <= 0) return;
3238  if (slc.tjs.size() > 20000) return;
3239  float typicalChgRMS = 0.5 * (tcc.chargeCuts[1] + tcc.chargeCuts[2]);
3240 
3241  bool prt = (tcc.dbgSlc && tcc.dbg2S && inCTP == debug.CTP);
3242 
3243  // clear out old tags and make a list of Tjs to consider
3244  std::vector<std::vector<int>> tjLists;
3245  std::vector<int> tjids;
3246  for (auto& tj : slc.tjs) {
3247  if (tj.CTP != inCTP) continue;
3248  if (tj.AlgMod[kKilled]) continue;
3249  if (tj.AlgMod[kHaloTj]) continue;
3250  tj.AlgMod[kShowerLike] = false;
3251  if (tj.AlgMod[kShowerTj]) continue;
3252  // ignore Tjs with Bragg peaks
3253  bool skipit = false;
3254  for (unsigned short end = 0; end < 2; ++end)
3255  if (tj.EndFlag[end][kBragg]) skipit = true;
3256  if (skipit) continue;
3257  short npwc = NumPtsWithCharge(slc, tj, false);
3258  // Don't expect any (primary) electron to be reconstructed as a single trajectory for
3259  // more than ~2 radiation lengths ~ 30 cm for uB ~ 100 wires
3260  if (npwc > 100) continue;
3261  // allow short Tjs.
3262  if (npwc > 5) {
3263  // Increase the MCSMom cut if the Tj is long and the charge RMS is high to reduce sensitivity
3264  // to the fcl configuration. A primary electron may be reconstructed as one long Tj with large
3265  // charge rms and possibly high MCSMom or as several nearby shorter Tjs with lower charge rms
3266  float momCut = tcc.showerTag[1];
3267  if (tj.ChgRMS > typicalChgRMS) momCut *= tj.ChgRMS / typicalChgRMS;
3268  if (tj.MCSMom > momCut) continue;
3269  }
3270  tjids.push_back(tj.ID);
3271  } // tj
3272 
3273  if (tjids.size() < 2) return;
3274 
3275  for (unsigned short it1 = 0; it1 < tjids.size() - 1; ++it1) {
3276  Trajectory& tj1 = slc.tjs[tjids[it1] - 1];
3277  for (unsigned short it2 = it1 + 1; it2 < tjids.size(); ++it2) {
3278  Trajectory& tj2 = slc.tjs[tjids[it2] - 1];
3279  unsigned short ipt1, ipt2;
3280  float doca = tcc.showerTag[2];
3281  // Find the separation between Tjs without considering dead wires
3282  TrajTrajDOCA(slc, tj1, tj2, ipt1, ipt2, doca, false);
3283  if (doca == tcc.showerTag[2]) continue;
3284  // make tighter cuts for user-defined short Tjs
3285  // found a close pair. See if one of these is in an existing cluster of Tjs
3286  bool inlist = false;
3287  for (unsigned short it = 0; it < tjLists.size(); ++it) {
3288  bool tj1InList =
3289  (std::find(tjLists[it].begin(), tjLists[it].end(), tj1.ID) != tjLists[it].end());
3290  bool tj2InList =
3291  (std::find(tjLists[it].begin(), tjLists[it].end(), tj2.ID) != tjLists[it].end());
3292  if (tj1InList || tj2InList) {
3293  // add the one that is not in the list
3294  if (!tj1InList) tjLists[it].push_back(tj1.ID);
3295  if (!tj2InList) tjLists[it].push_back(tj2.ID);
3296  inlist = true;
3297  break;
3298  }
3299  if (inlist) break;
3300  } // it
3301  // start a new list with this pair?
3302  if (!inlist) {
3303  std::vector<int> newlist(2);
3304  newlist[0] = tj1.ID;
3305  newlist[1] = tj2.ID;
3306  tjLists.push_back(newlist);
3307  }
3308  } // it2
3309  } // it1
3310  if (tjLists.empty()) return;
3311 
3312  // mark them all as ShowerLike Tjs
3313  for (auto& tjl : tjLists) {
3314  // ignore small clusters
3315  if (tjl.size() < 3) continue;
3316  for (auto& tjID : tjl) {
3317  auto& tj = slc.tjs[tjID - 1];
3318  tj.AlgMod[kShowerLike] = true;
3319  } // tjid
3320  } // tjl
3321 
3322  if (prt) {
3323  unsigned short nsh = 0;
3324  for (auto& tjl : tjLists) {
3325  for (auto& tjID : tjl) {
3326  auto& tj = slc.tjs[tjID - 1];
3327  if (tj.AlgMod[kShowerLike]) ++nsh;
3328  } // tjid
3329  } // tjl
3330  mf::LogVerbatim("TC") << "TagShowerLike tagged " << nsh << " Tjs vertices in CTP " << inCTP;
3331  } // prt
3332  } // TagShowerLike
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:582
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:549
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
DebugStuff debug
Definition: DebugStruct.cxx:4
std::vector< float > chargeCuts
Definition: DataStructs.h:553
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:69
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
bool TrajTrajDOCA(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2407
CTP_t CTP
set to an invalid CTP
Definition: DebugStruct.h:23
bool tca::TCIntersectionPoint ( unsigned int  wir1,
unsigned int  wir2,
unsigned int  pln1,
unsigned int  pln2,
float &  y,
float &  z 
)

Definition at line 667 of file PFPUtils.cxx.

References evt, and tca::TCEvent::wireIntersections.

Referenced by Match3Planes().

673  {
674  // A TrajCluster analog of geometry IntersectionPoint that uses local wireIntersections with
675  // float precision. The (y,z) position is only used to match TPs between planes - not for 3D fitting
676  if (evt.wireIntersections.empty()) return false;
677  if (pln1 == pln2) return false;
678 
679  if (pln1 > pln2) {
680  std::swap(pln1, pln2);
681  std::swap(wir1, wir2);
682  }
683 
684  for (auto& wi : evt.wireIntersections) {
685  if (wi.pln1 != pln1) continue;
686  if (wi.pln2 != pln2) continue;
687  // estimate the position using the wire differences
688  double dw1 = wir1 - wi.wir1;
689  double dw2 = wir2 - wi.wir2;
690  y = (float)(wi.y + dw1 * wi.dydw1 + dw2 * wi.dydw2);
691  z = (float)(wi.z + dw1 * wi.dzdw1 + dw2 * wi.dzdw2);
692  return true;
693  } // wi
694  return false;
695  } // TCIntersectionPoint
Float_t y
Definition: compare.C:6
Double_t z
Definition: plot.C:276
std::vector< TCWireIntersection > wireIntersections
Definition: DataStructs.h:631
void swap(lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &a, lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &b)
TCEvent evt
Definition: DataStructs.cxx:8
void tca::TjDeltaRMS ( const Trajectory tj,
unsigned short  firstPt,
unsigned short  lastPt,
double &  rms,
unsigned short &  cnt 
)

Definition at line 3491 of file Utils.cxx.

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

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

3496  {
3497  // returns the rms scatter of points around a line formed by the firstPt and lastPt of the trajectory
3498 
3499  rms = -1;
3500  if (firstPt < tj.EndPt[0]) return;
3501  if (lastPt > tj.EndPt[1]) return;
3502 
3503  firstPt = NearestPtWithChg(tj, firstPt);
3504  lastPt = NearestPtWithChg(tj, lastPt);
3505  if (firstPt >= lastPt) return;
3506 
3507  TrajPoint tmp;
3508  // make a bare trajectory point to define a line between firstPt and lastPt.
3509  // Use the position of the hits at these points
3510  TrajPoint firstTP = tj.Pts[firstPt];
3511  firstTP.Pos = firstTP.HitPos;
3512  TrajPoint lastTP = tj.Pts[lastPt];
3513  lastTP.Pos = lastTP.HitPos;
3514  if (!MakeBareTrajPoint(firstTP, lastTP, tmp)) return;
3515  // sum up the deviations^2
3516  double dsum = 0;
3517  cnt = 0;
3518  for (unsigned short ipt = firstPt + 1; ipt < lastPt; ++ipt) {
3519  if (tj.Pts[ipt].Chg == 0) continue;
3520  // ignore points with large error
3521  if (tj.Pts[ipt].HitPosErr2 > 4) continue;
3522  dsum += PointTrajDOCA2(tj.Pts[ipt].HitPos[0], tj.Pts[ipt].HitPos[1], tmp);
3523  ++cnt;
3524  } // ipt
3525  if (cnt < 2) return;
3526  rms = sqrt(dsum / (double)cnt);
3527 
3528  } // TjDeltaRMS
Float_t tmp
Definition: plot.C:35
unsigned short NearestPtWithChg(const Trajectory &tj, unsigned short thePt)
Definition: Utils.cxx:3435
float PointTrajDOCA2(float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2530
bool MakeBareTrajPoint(const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
Definition: Utils.cxx:4059
std::string tca::TPEnvString ( const TrajPoint tp)

Definition at line 6190 of file Utils.cxx.

References tca::TrajPoint::Environment, kEnvFlag, kEnvNearMuon, kEnvNearShower, kEnvNearSrcHit, kEnvNotGoodWire, kEnvOverlap, and kEnvUnusedHits.

Referenced by DotProd(), PrintTP(), and PrintTP3Ds().

6191  {
6192  // Print environment bits in human-readable format
6193  std::string str = "";
6194  for (unsigned short ib = 0; ib < 8; ++ib) {
6195  // There aren't any bit names for Environment_t
6196  if (!tp.Environment[ib]) continue;
6197  if (ib == kEnvNotGoodWire) str += " NoGdwire";
6198  if (ib == kEnvNearMuon) str += " NearMuon";
6199  if (ib == kEnvNearShower) str += " NearShower";
6200  if (ib == kEnvOverlap) str += " Overlap";
6201  if (ib == kEnvUnusedHits) str += " UnusedHits";
6202  if (ib == kEnvNearSrcHit) str += " NearSrcHit";
6203  if (ib == kEnvFlag) str += " Flag";
6204  } // ib
6205  return str;
6206  } // TPEnvironment
a general purpose flag bit used in 3D matching
Definition: DataStructs.h:517
TP is near a hit in the srcHit collection but no allHit hit exists (DUNE disambiguation error) ...
Definition: DataStructs.h:516
float tca::TPHitsRMSTick ( const TCSlice slc,
const TrajPoint tp,
HitStatus_t  hitRequest 
)

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

4099  {
4100  // Estimate the RMS of all hits associated with a trajectory point
4101  // without a lot of calculation. Note that this returns a value that is
4102  // closer to a FWHM, not the RMS
4103  if (tp.Hits.empty()) return 0;
4104  float minVal = 9999;
4105  float maxVal = 0;
4106  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
4107  bool useit = (hitRequest == kAllHits);
4108  if (hitRequest == kUsedHits && tp.UseHit[ii]) useit = true;
4109  if (hitRequest == kUnusedHits && !tp.UseHit[ii]) useit = true;
4110  if (!useit) continue;
4111  unsigned int iht = tp.Hits[ii];
4112  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
4113  float cv = hit.PeakTime();
4114  float rms = hit.RMS();
4115  float arg = cv - rms;
4116  if (arg < minVal) minVal = arg;
4117  arg = cv + rms;
4118  if (arg > maxVal) maxVal = arg;
4119  } // ii
4120  if (maxVal == 0) return 0;
4121  return (maxVal - minVal) / 2;
4122  } // TPHitsRMSTick
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
float tca::TPHitsRMSTime ( const TCSlice slc,
const TrajPoint tp,
HitStatus_t  hitRequest 
)

Definition at line 4092 of file Utils.cxx.

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

Referenced by CreateTP3D(), and DotProd().

4093  {
4094  return tcc.unitsPerTick * TPHitsRMSTick(slc, tp, hitRequest);
4095  } // TPHitsRMSTime
TCConfig tcc
Definition: DataStructs.cxx:9
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
float TPHitsRMSTick(const TCSlice &slc, const TrajPoint &tp, HitStatus_t hitRequest)
Definition: Utils.cxx:4098
unsigned short tca::TPNearVertex ( const TCSlice slc,
const TrajPoint tp 
)

Definition at line 1566 of file TCVertex.cxx.

References util::abs(), tca::TrajPoint::CTP, tca::TrajPoint::Pos, and tca::TCSlice::vtxs.

1567  {
1568  // Returns the index of a vertex if tp is nearby
1569  for (unsigned short ivx = 0; ivx < slc.vtxs.size(); ++ivx) {
1570  if (slc.vtxs[ivx].ID == 0) continue;
1571  if (slc.vtxs[ivx].CTP != tp.CTP) continue;
1572  if (std::abs(slc.vtxs[ivx].Pos[0] - tp.Pos[0]) > 1.2) continue;
1573  if (std::abs(slc.vtxs[ivx].Pos[1] - tp.Pos[1]) > 1.2) continue;
1574  return ivx;
1575  } // ivx
1576  return USHRT_MAX;
1577  } // TPNearVertex
constexpr auto abs(T v)
Returns the absolute value of the argument.
float tca::TpSumHitChg ( const TCSlice slc,
TrajPoint const &  tp 
)

Definition at line 2061 of file Utils.cxx.

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

2062  {
2063  float totchg = 0;
2064  for (size_t i = 0; i < tp.Hits.size(); ++i) {
2065  if (!tp.UseHit[i]) continue;
2066  totchg += (*evt.allHits)[slc.slHits[tp.Hits[i]].allHitsIndex].Integral();
2067  }
2068  return totchg;
2069  } // TpSumHitChg
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
bool tca::TrajClosestApproach ( Trajectory const &  tj,
float  x,
float  y,
unsigned short &  closePt,
float &  DOCA 
)

Definition at line 2622 of file Utils.cxx.

References util::abs(), tca::Trajectory::EndPt, tca::Trajectory::Pts, x, and y.

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

2627  {
2628  // find the closest approach between a trajectory tj and a point (x,y). Returns
2629  // the index of the closest trajectory point and the distance. Returns false if none
2630  // of the points on the tj are within DOCA
2631 
2632  float close2 = DOCA * DOCA;
2633  closePt = 0;
2634  bool foundClose = false;
2635 
2636  for (unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1] + 1; ++ipt) {
2637  if (tj.Pts[ipt].Chg == 0) continue;
2638  float dx = tj.Pts[ipt].Pos[0] - x;
2639  if (std::abs(dx) > DOCA) continue;
2640  float dy = tj.Pts[ipt].Pos[1] - y;
2641  if (std::abs(dy) > DOCA) continue;
2642  float sep2 = dx * dx + dy * dy;
2643  if (sep2 < close2) {
2644  close2 = sep2;
2645  closePt = ipt;
2646  foundClose = true;
2647  }
2648  } // ipt
2649 
2650  DOCA = sqrt(close2);
2651  return foundClose;
2652 
2653  } // TrajClosestApproach
Float_t x
Definition: compare.C:6
Float_t y
Definition: compare.C:6
constexpr auto abs(T v)
Returns the absolute value of the argument.
bool tca::TrajHitsOK ( TCSlice const &  slc,
const std::vector< unsigned int > &  iHitsInMultiplet,
const std::vector< unsigned int > &  jHitsInMultiplet 
)

Definition at line 1839 of file Utils.cxx.

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

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

1842  {
1843  // Hits (assume to be on adjacent wires have an acceptable signal overlap
1844 
1845  if (iHitsInMultiplet.empty() || jHitsInMultiplet.empty()) return false;
1846 
1847  float sum;
1848  float cvI = HitsPosTick(slc, iHitsInMultiplet, sum, kAllHits);
1849  if (cvI < 0) return false;
1850  float minI = 1E6;
1851  float maxI = 0;
1852  for (auto& iht : iHitsInMultiplet) {
1853  auto const& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1854  float cv = hit.PeakTime();
1855  float rms = hit.RMS();
1856  float arg = cv - 3.1 * rms;
1857  if (arg < minI) minI = arg;
1858  arg = cv + 3.1 * rms;
1859  if (arg > maxI) maxI = arg;
1860  }
1861 
1862  float cvJ = HitsPosTick(slc, jHitsInMultiplet, sum, kAllHits);
1863  if (cvJ < 0) return false;
1864  float minJ = 1E6;
1865  float maxJ = 0;
1866  for (auto& jht : jHitsInMultiplet) {
1867  auto& hit = (*evt.allHits)[slc.slHits[jht].allHitsIndex];
1868  float cv = hit.PeakTime();
1869  float rms = hit.RMS();
1870  float arg = cv - 3.1 * rms;
1871  if (arg < minJ) minJ = arg;
1872  arg = cv + 3.1 * rms;
1873  if (arg > maxJ) maxJ = arg;
1874  }
1875 
1876  if (cvI < cvJ) {
1877  if (maxI > minJ) return true;
1878  }
1879  else {
1880  if (minI < maxJ) return true;
1881  }
1882  return false;
1883  } // TrajHitsOK
float HitsPosTick(const TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, float &sum, HitStatus_t hitRequest)
Definition: Utils.cxx:4174
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
Double_t sum
Definition: plot.C:31
bool tca::TrajHitsOK ( TCSlice const &  slc,
const unsigned int  iht,
const unsigned int  jht 
)

Definition at line 1886 of file Utils.cxx.

References util::abs(), tca::TCEvent::allHits, evt, and tca::TCSlice::slHits.

1887  {
1888  // ensure that two adjacent hits have an acceptable overlap
1889  if (iht > slc.slHits.size() - 1) return false;
1890  if (jht > slc.slHits.size() - 1) return false;
1891  // require that they be on adjacent wires
1892  auto& ihit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1893  auto& jhit = (*evt.allHits)[slc.slHits[jht].allHitsIndex];
1894  int iwire = ihit.WireID().Wire;
1895  int jwire = jhit.WireID().Wire;
1896  if (std::abs(iwire - jwire) > 1) return false;
1897  if (ihit.PeakTime() > jhit.PeakTime()) {
1898  float minISignal = ihit.PeakTime() - 3 * ihit.RMS();
1899  float maxJSignal = jhit.PeakTime() + 3 * ihit.RMS();
1900  if (maxJSignal > minISignal) return true;
1901  }
1902  else {
1903  float maxISignal = ihit.PeakTime() + 3 * ihit.RMS();
1904  float minJSignal = jhit.PeakTime() - 3 * ihit.RMS();
1905  if (minJSignal > maxISignal) return true;
1906  }
1907  return false;
1908  } // TrajHitsOK
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
void tca::TrajIntersection ( TrajPoint const &  tp1,
TrajPoint const &  tp2,
Point2_t pos 
)

Definition at line 2543 of file Utils.cxx.

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

2544  {
2545  TrajIntersection(tp1, tp2, pos[0], pos[1]);
2546  } // TrajIntersection
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, float &x, float &y)
Definition: Utils.cxx:2548
void tca::TrajIntersection ( TrajPoint const &  tp1,
TrajPoint const &  tp2,
float &  x,
float &  y 
)

Definition at line 2548 of file Utils.cxx.

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

2549  {
2550  // returns the intersection position, (x,y), of two trajectory points
2551 
2552  x = -9999;
2553  y = -9999;
2554 
2555  double arg1 = tp1.Pos[0] * tp1.Dir[1] - tp1.Pos[1] * tp1.Dir[0];
2556  double arg2 = tp2.Pos[0] * tp1.Dir[1] - tp2.Pos[1] * tp1.Dir[0];
2557  double arg3 = tp2.Dir[0] * tp1.Dir[1] - tp2.Dir[1] * tp1.Dir[0];
2558  if (arg3 == 0) return;
2559  double s = (arg1 - arg2) / arg3;
2560 
2561  x = (float)(tp2.Pos[0] + s * tp2.Dir[0]);
2562  y = (float)(tp2.Pos[1] + s * tp2.Dir[1]);
2563 
2564  } // TrajIntersection
Float_t x
Definition: compare.C:6
Float_t y
Definition: compare.C:6
bool tca::TrajIsClean ( Trajectory const &  tj,
bool  prt 
)

Definition at line 3358 of file Utils.cxx.

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

Referenced by DotProd(), and UpdateTraj().

3359  {
3360  // Returns true if the trajectory has low hit multiplicity and is in a
3361  // clean environment
3362  unsigned short nUsed = 0;
3363  unsigned short nTotHits = 0;
3364  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
3365  TrajPoint const& tp = tj.Pts[ipt];
3366  nTotHits += tp.Hits.size();
3367  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3368  if (tp.UseHit[ii]) ++nUsed;
3369  } // ii
3370  } // ipt
3371  if (nTotHits == 0) return false;
3372  float fracUsed = (float)nUsed / (float)nTotHits;
3373  if (prt)
3374  mf::LogVerbatim("TC") << "TrajIsClean: nTotHits " << nTotHits << " nUsed " << nUsed
3375  << " fracUsed " << fracUsed;
3376 
3377  return fracUsed > 0.9;
3378  } // TrajIsClean
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float tca::TrajLength ( const Trajectory tj)

Definition at line 2582 of file Utils.cxx.

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

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

2583  {
2584  float len = 0, dx, dy;
2585  unsigned short ipt;
2586  unsigned short prevPt = tj.EndPt[0];
2587  for (ipt = tj.EndPt[0] + 1; ipt < tj.EndPt[1] + 1; ++ipt) {
2588  if (tj.Pts[ipt].Chg == 0) continue;
2589  dx = tj.Pts[ipt].Pos[0] - tj.Pts[prevPt].Pos[0];
2590  dy = tj.Pts[ipt].Pos[1] - tj.Pts[prevPt].Pos[1];
2591  len += sqrt(dx * dx + dy * dy);
2592  prevPt = ipt;
2593  }
2594  return len;
2595  } // TrajLength
float tca::TrajPointSeparation ( const TrajPoint tp1,
const TrajPoint tp2 
)

Definition at line 2613 of file Utils.cxx.

References tca::TrajPoint::Pos.

Referenced by MaskTrajEndPoints(), MCSMom(), MCSThetaRMS(), and StepAway().

2614  {
2615  // Returns the separation distance between two trajectory points
2616  float dx = tp1.Pos[0] - tp2.Pos[0];
2617  float dy = tp1.Pos[1] - tp2.Pos[1];
2618  return sqrt(dx * dx + dy * dy);
2619  } // TrajPointSeparation
void tca::TrajPointTrajDOCA ( TrajPoint const &  tp,
Trajectory const &  tj,
unsigned short &  closePt,
float &  minSep 
)

Definition at line 2384 of file Utils.cxx.

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

Referenced by CompleteIncomplete3DVertices(), FindHammerVertices(), FindHammerVertices2(), and MergeAndStore().

2388  {
2389  // Finds the point, ipt, on trajectory tj that is closest to trajpoint tp
2390  float best = minSep * minSep;
2391  closePt = USHRT_MAX;
2392  float dw, dt, dp2;
2393  unsigned short ipt;
2394  for (ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2395  dw = tj.Pts[ipt].Pos[0] - tp.Pos[0];
2396  dt = tj.Pts[ipt].Pos[1] - tp.Pos[1];
2397  dp2 = dw * dw + dt * dt;
2398  if (dp2 < best) {
2399  best = dp2;
2400  closePt = ipt;
2401  }
2402  } // ipt
2403  minSep = sqrt(best);
2404  } // TrajPointTrajDOCA
float tca::TrajPointVertexPull ( const TrajPoint tp,
const VtxStore vx 
)

Definition at line 1844 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 AttachAnyTrajToVertex(), AttachAnyVertexToTraj(), AttachTrajToVertex(), FitVertex(), and Reconcile2VTs().

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

Definition at line 2407 of file Utils.cxx.

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

2413  {
2414  return TrajTrajDOCA(slc, tj1, tj2, ipt1, ipt2, minSep, false);
2415  } // TrajTrajDOCA
bool TrajTrajDOCA(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep, bool considerDeadWires)
Definition: Utils.cxx:2418
bool tca::TrajTrajDOCA ( const TCSlice slc,
const Trajectory tj1,
const Trajectory tj2,
unsigned short &  ipt1,
unsigned short &  ipt2,
float &  minSep,
bool  considerDeadWires 
)

Definition at line 2418 of file Utils.cxx.

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

2425  {
2426  // Find the Distance Of Closest Approach between two trajectories less than minSep
2427  // start with some rough cuts to minimize the use of the more expensive checking. This
2428  // function returns true if the DOCA is less than minSep
2429  for (unsigned short iwt = 0; iwt < 2; ++iwt) {
2430  // Apply box cuts on the ends of the trajectories
2431  // The Lo/Hi wire(time) at each end of tj1
2432  float wt0 = tj1.Pts[tj1.EndPt[0]].Pos[iwt];
2433  float wt1 = tj1.Pts[tj1.EndPt[1]].Pos[iwt];
2434  float lowt1 = wt0;
2435  float hiwt1 = wt1;
2436  if (wt1 < lowt1) {
2437  lowt1 = wt1;
2438  hiwt1 = wt0;
2439  }
2440  // The Lo/Hi wire(time) at each end of tj2
2441  wt0 = tj2.Pts[tj2.EndPt[0]].Pos[iwt];
2442  wt1 = tj2.Pts[tj2.EndPt[1]].Pos[iwt];
2443  float lowt2 = wt0;
2444  float hiwt2 = wt1;
2445  if (wt1 < lowt2) {
2446  lowt2 = wt1;
2447  hiwt2 = wt0;
2448  }
2449  // Check for this configuration
2450  // loWire1.......hiWire1 minSep loWire2....hiWire2
2451  // loTime1.......hiTime1 minSep loTime2....hiTime2
2452  if (lowt2 > hiwt1 + minSep) return false;
2453  // and the other
2454  if (lowt1 > hiwt2 + minSep) return false;
2455  } // iwt
2456 
2457  float best = minSep * minSep;
2458  ipt1 = 0;
2459  ipt2 = 0;
2460  float dwc = 0;
2461  bool isClose = false;
2462  for (unsigned short i1 = tj1.EndPt[0]; i1 < tj1.EndPt[1] + 1; ++i1) {
2463  for (unsigned short i2 = tj2.EndPt[0]; i2 < tj2.EndPt[1] + 1; ++i2) {
2464  if (considerDeadWires) dwc = DeadWireCount(slc, tj1.Pts[i1], tj2.Pts[i2]);
2465  float dw = tj1.Pts[i1].Pos[0] - tj2.Pts[i2].Pos[0] - dwc;
2466  if (std::abs(dw) > minSep) continue;
2467  float dt = tj1.Pts[i1].Pos[1] - tj2.Pts[i2].Pos[1];
2468  if (std::abs(dt) > minSep) continue;
2469  float dp2 = dw * dw + dt * dt;
2470  if (dp2 < best) {
2471  best = dp2;
2472  ipt1 = i1;
2473  ipt2 = i2;
2474  isClose = true;
2475  }
2476  } // i2
2477  } // i1
2478  minSep = sqrt(best);
2479  return isClose;
2480  } // TrajTrajDOCA
constexpr auto abs(T v)
Returns the absolute value of the argument.
float DeadWireCount(const TCSlice &slc, const float &inWirePos1, const float &inWirePos2, CTP_t tCTP)
Definition: Utils.cxx:2101
bool tca::TransferTjHits ( TCSlice slc,
bool  prt 
)

Definition at line 3845 of file TCShower.cxx.

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

Referenced by Finish3DShowers().

3846  {
3847  // Transfer InShower hits in all TPCs and planes to the shower Tjs
3848 
3849  bool newShowers = false;
3850  for (auto& ss : slc.cots) {
3851  if (ss.ID == 0) continue;
3852  if (ss.ShowerTjID == 0) continue;
3853  // Tp 1 of stj will get all of the shower hits
3854  Trajectory& stj = slc.tjs[ss.ShowerTjID - 1];
3855  if (!stj.Pts[1].Hits.empty()) {
3856  std::cout << "TTjH: ShowerTj T" << stj.ID << " already has " << stj.Pts[1].Hits.size()
3857  << " hits\n";
3858  continue;
3859  }
3860  // Note that UseHit is not used since the size is limited to 16
3861  for (auto& tjID : ss.TjIDs) {
3862  unsigned short itj = tjID - 1;
3863  if (slc.tjs[itj].AlgMod[kShowerTj]) {
3864  std::cout << "TTjH: Coding error. T" << tjID << " is a ShowerTj but is in TjIDs\n";
3865  continue;
3866  }
3867  if (slc.tjs[itj].SSID <= 0) {
3868  std::cout << "TTjH: Coding error. Trying to transfer T" << tjID
3869  << " hits but it isn't an InShower Tj\n";
3870  continue;
3871  }
3872  auto thits = PutTrajHitsInVector(slc.tjs[itj], kUsedHits);
3873  // associate all hits with the charge center TP
3874  stj.Pts[1].Hits.insert(stj.Pts[1].Hits.end(), thits.begin(), thits.end());
3875  // kill Tjs that are in showers
3876  slc.tjs[itj].AlgMod[kKilled] = true;
3877  } // tjID
3878  // re-assign the hit -> stj association
3879  for (auto& iht : stj.Pts[1].Hits)
3880  slc.slHits[iht].InTraj = stj.ID;
3881  newShowers = true;
3882  } // ss
3883 
3884  if (prt) mf::LogVerbatim("TC") << "TTJH: success? " << newShowers;
3885  return newShowers;
3886  } // TransferTjHits
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< unsigned int > PutTrajHitsInVector(const Trajectory &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2689
void tca::TrimEndPts ( std::string  fcnLabel,
TCSlice slc,
Trajectory tj,
const std::vector< float > &  fQualityCuts,
bool  prt 
)

Definition at line 1576 of file Utils.cxx.

References util::abs(), tca::Trajectory::AlgMod, tca::Trajectory::CTP, DecodeCTP(), tca::Trajectory::EndFlag, tca::Trajectory::EndPt, evt, tca::TCEvent::goodWire, tca::Trajectory::ID, kAtKink, kTEP, NumPtsWithCharge(), tca::TCSlice::nWires, tca::Trajectory::PDGCode, geo::PlaneID::Plane, PrintTrajectory(), tca::Trajectory::Pts, SetEndPoints(), tca::Trajectory::StepDir, tcc, UnsetUsedHits(), and tca::TCConfig::useAlg.

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

1581  {
1582  // Trim the hits off the end until there are at least MinPts consecutive hits at the end
1583  // and the fraction of hits on the trajectory exceeds fQualityCuts[0]
1584  // Minimum length requirement accounting for dead wires where - denotes a wire with a point
1585  // and D is a dead wire. Here is an example with minPts = 3
1586  // ---DDDDD--- is OK
1587  // ----DD-DD-- is OK
1588  // ----DDD-D-- is OK
1589  // ----DDDDD-- is not OK
1590 
1591  if (!tcc.useAlg[kTEP]) return;
1592  if (tj.PDGCode == 111) return;
1593  if (tj.EndFlag[1][kAtKink]) return;
1594 
1595  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
1596  short minPts = fQualityCuts[1];
1597  if (minPts < 1) return;
1598  if (npwc < minPts) return;
1599  // don't consider short Tjs
1600  if (npwc < 8) return;
1601 
1602  // handle short tjs
1603  if (npwc == minPts + 1) {
1604  unsigned short endPt1 = tj.EndPt[1];
1605  auto& tp = tj.Pts[endPt1];
1606  auto& ptp = tj.Pts[endPt1 - 1];
1607  // remove the last point if the previous point has no charge or if
1608  // it isn't on the next wire
1609  float dwire = std::abs(ptp.Pos[0] - tp.Pos[0]);
1610  if (ptp.Chg == 0 || dwire > 1.1) {
1611  UnsetUsedHits(slc, tp);
1612  SetEndPoints(tj);
1613  tj.AlgMod[kTEP] = true;
1614  }
1615  return;
1616  } // short tj
1617 
1618  // find the separation between adjacent points, starting at the end
1619  short lastPt = 0;
1620  for (lastPt = tj.EndPt[1]; lastPt >= minPts; --lastPt) {
1621  // check for an error
1622  if (lastPt == 1) break;
1623  if (tj.Pts[lastPt].Chg == 0) continue;
1624  // number of points on adjacent wires
1625  unsigned short nadj = 0;
1626  unsigned short npwc = 0;
1627  for (short ipt = lastPt - minPts; ipt < lastPt; ++ipt) {
1628  if (ipt < 2) break;
1629  // the current point
1630  auto& tp = tj.Pts[ipt];
1631  // the previous point
1632  auto& ptp = tj.Pts[ipt - 1];
1633  if (tp.Chg > 0 && ptp.Chg > 0) {
1634  ++npwc;
1635  if (std::abs(tp.Pos[0] - ptp.Pos[0]) < 1.5) ++nadj;
1636  }
1637  } // ipt
1638  float ntpwc = NumPtsWithCharge(slc, tj, true, tj.EndPt[0], lastPt);
1639  float nwires = std::abs(tj.Pts[tj.EndPt[0]].Pos[0] - tj.Pts[lastPt].Pos[0]) + 1;
1640  float hitFrac = ntpwc / nwires;
1641  if (prt)
1642  mf::LogVerbatim("TC") << fcnLabel << "-TEP: T" << tj.ID << " lastPt " << lastPt << " npwc "
1643  << npwc << " ntpwc " << ntpwc << " nadj " << nadj << " hitFrac "
1644  << hitFrac;
1645  if (hitFrac > fQualityCuts[0] && npwc == minPts && nadj >= minPts - 1) break;
1646  } // lastPt
1647 
1648  if (prt) mf::LogVerbatim("TC") << " lastPt " << lastPt << " " << tj.EndPt[1] << "\n";
1649  // trim the last point if it just after a dead wire.
1650  if (tj.Pts[lastPt].Pos[0] > -0.4) {
1651  unsigned int prevWire = std::nearbyint(tj.Pts[lastPt].Pos[0]);
1652  if (tj.StepDir > 0) { --prevWire; }
1653  else {
1654  ++prevWire;
1655  }
1656  if (prt) {
1657  mf::LogVerbatim("TC") << fcnLabel << "-TEP: is prevWire " << prevWire << " dead? ";
1658  }
1659  unsigned short plane = DecodeCTP(tj.CTP).Plane;
1660  if (prevWire < slc.nWires[plane] && !evt.goodWire[plane][prevWire]) --lastPt;
1661  } // valid Pos[0]
1662 
1663  // Nothing needs to be done
1664  if (lastPt == tj.EndPt[1]) {
1665  if (prt) mf::LogVerbatim("TC") << fcnLabel << "-TEPo: Tj is OK";
1666  return;
1667  }
1668 
1669  // clear the points after lastPt
1670  for (unsigned short ipt = lastPt + 1; ipt <= tj.EndPt[1]; ++ipt)
1671  UnsetUsedHits(slc, tj.Pts[ipt]);
1672  SetEndPoints(tj);
1673  tj.AlgMod[kTEP] = true;
1674  if (prt) {
1675  fcnLabel += "-TEPo";
1676  PrintTrajectory(fcnLabel, slc, tj, USHRT_MAX);
1677  }
1678 
1679  } // TrimEndPts
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:2080
TCConfig tcc
Definition: DataStructs.cxx:9
void PrintTrajectory(std::string someText, const TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:6035
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1061
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:622
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
geo::PlaneID DecodeCTP(CTP_t CTP)
TCEvent evt
Definition: DataStructs.cxx:8
void tca::TrimHiChgEndPts ( TCSlice slc,
Trajectory tj,
bool  prt 
)

Definition at line 1534 of file Utils.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::EndFlag, tca::Trajectory::EndPt, kBragg, tca::TCConfig::kinkCuts, kTHCEP, NumPtsWithCharge(), tca::Trajectory::PDGCode, PrintPos(), tca::Trajectory::Pts, tcc, UnsetUsedHits(), and tca::TCConfig::useAlg.

Referenced by CheckTraj().

1535  {
1536  // Trim points at the end if the charge pull is too high
1537  if (!tcc.useAlg[kTHCEP]) return;
1538  // don't consider long electrons
1539  if (tj.PDGCode == 111) return;
1540  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
1541  // only consider long tjs
1542  if (npwc < 50) return;
1543  // that don't have a Bragg peak
1544  if (tj.EndFlag[1][kBragg]) return;
1545 
1546  // only look at the last points that would have not been considered by GottaKink
1547  unsigned short nPtsMax = tcc.kinkCuts[0];
1548  if (nPtsMax > 8) nPtsMax = 8;
1549 
1550  // find the first point with a high charge pull starting at nPtsMax points before the end
1551  // and count the number of high charge pull points
1552  float cntBad = 0;
1553  unsigned short firstBad = USHRT_MAX;
1554  for (unsigned short ii = 0; ii < nPtsMax; ++ii) {
1555  unsigned short ipt = tj.EndPt[1] - nPtsMax + ii;
1556  auto& tp = tj.Pts[ipt];
1557  if (tp.Chg <= 0) continue;
1558  if (tp.ChgPull < 3) continue;
1559  ++cntBad;
1560  if (firstBad == USHRT_MAX) firstBad = ipt;
1561  } // ii
1562  if (firstBad == USHRT_MAX) return;
1563  // total number of points from the first bad point to the end
1564  float cntTot = tj.EndPt[1] - firstBad;
1565  // fraction of those poins that are bad
1566  float fracBad = cntBad / cntTot;
1567  if (fracBad < 0.5) return;
1568  if (prt)
1569  mf::LogVerbatim("TC") << "THCEP: Trim points starting at " << PrintPos(tj.Pts[firstBad]);
1570  for (unsigned short ipt = firstBad; ipt <= tj.EndPt[1]; ++ipt)
1571  UnsetUsedHits(slc, tj.Pts[ipt]);
1572  tj.AlgMod[kTHCEP] = true;
1573  } // TrimHiChgEndPts
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< float > kinkCuts
kink finder algorithm
Definition: DataStructs.h:550
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:2080
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1061
std::string PrintPos(const Point2_t &pos)
Definition: Utils.cxx:6362
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:578
float tca::TwoTPAngle ( const TrajPoint tp1,
const TrajPoint tp2 
)

Definition at line 2656 of file Utils.cxx.

References tca::TrajPoint::Pos.

2657  {
2658  // Calculates the angle of a line between two TPs
2659  float dw = tp2.Pos[0] - tp1.Pos[0];
2660  float dt = tp2.Pos[1] - tp1.Pos[1];
2661  return atan2(dw, dt);
2662  } // TwoTPAngle
void tca::UnsetUsedHits ( TCSlice slc,
TrajPoint tp 
)

Definition at line 1061 of file Utils.cxx.

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

Referenced by CheckHiMultEndHits(), CheckHiMultUnusedHits(), ChkBegin(), ChkChgAsymmetry(), ChkStopEndPts(), FillGaps(), FixBegin(), GottaKink(), IsGhost(), MaskBadTPs(), MaskTrajEndPoints(), StepAway(), StopShort(), TrimEndPts(), TrimHiChgEndPts(), and UpdateTraj().

1062  {
1063  // Sets InTraj = 0 and UseHit false for all used hits in tp
1064  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1065  if (tp.UseHit[ii]) {
1066  slc.slHits[tp.Hits[ii]].InTraj = 0;
1067  tp.UseHit[ii] = false;
1068  } // UseHit
1069  } // ii
1070  tp.Chg = 0;
1071  } // UnsetUsedHits
bool tca::Update ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice slc,
PFPStruct pfp 
)

Definition at line 1048 of file PFPUtils.cxx.

References tca::PFPStruct::AlgMod, FitSection(), tca::PFPStruct::Flags, kNeedsUpdate, kSmallAngle, tca::PFPStruct::SectionFits, SetSection(), SortSection(), and tca::PFPStruct::TP3Ds.

Referenced by evd::details::RawDigitCacheDataClass::empty(), FillGaps3D(), ReSection(), and lariov::SIOVChannelStatusProvider::Status().

1049  {
1050  // This function only updates SectionFits that need to be re-sorted or re-fit. It returns
1051  // false if there was a serious error indicating that the pfp should be abandoned
1052  if (pfp.TP3Ds.empty() || pfp.SectionFits.empty()) return false;
1053 
1054  // special handling for small angle tracks
1055  if (pfp.AlgMod[kSmallAngle]) {
1056  for (unsigned short sfi = 0; sfi < pfp.SectionFits.size(); ++sfi) {
1057  auto& sf = pfp.SectionFits[sfi];
1058  if (!sf.NeedsUpdate) continue;
1059  if (!SortSection(pfp, sfi)) return false;
1060  sf.NPts = 0;
1061  sf.ChiDOF = 0;
1062  for (unsigned short ipt = 0; ipt < pfp.TP3Ds.size(); ++ipt) {
1063  auto& tp3d = pfp.TP3Ds[ipt];
1064  if (tp3d.SFIndex < sfi) continue;
1065  if (tp3d.SFIndex > sfi) break;
1066  ++sf.NPts;
1067  double delta = tp3d.Pos[0] - tp3d.TPX;
1068  sf.ChiDOF += delta * delta / tp3d.TPXErr2;
1069  } // ipt
1070  if (sf.NPts < 5) { sf.ChiDOF = 0; }
1071  else {
1072  sf.ChiDOF /= (float)(sf.NPts - 4);
1073  }
1074  sf.NeedsUpdate = false;
1075  } // sfi
1076  pfp.Flags[kNeedsUpdate] = false;
1077  return true;
1078  } // kSmallAngle
1079 
1080  for (std::size_t sfi = 0; sfi < pfp.SectionFits.size(); ++sfi) {
1081  auto& sf = pfp.SectionFits[sfi];
1082  if (!sf.NeedsUpdate) continue;
1083  if (!FitSection(detProp, slc, pfp, sfi)) return false;
1084  if (!SortSection(pfp, sfi)) return false;
1085  sf.NeedsUpdate = false;
1086  } // sfi
1087 
1088  // ensure that all points (good or not) have a valid SFIndex
1089  for (auto& tp3d : pfp.TP3Ds) {
1090  if (tp3d.SFIndex >= pfp.SectionFits.size()) SetSection(detProp, pfp, tp3d);
1091  } // tp3d
1092  pfp.Flags[kNeedsUpdate] = false;
1093  return true;
1094  } // Update
bool SortSection(PFPStruct &pfp, unsigned short sfIndex)
Definition: PFPUtils.cxx:1999
bool FitSection(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, unsigned short sfIndex)
Definition: PFPUtils.cxx:1391
bool SetSection(detinfo::DetectorPropertiesData const &detProp, PFPStruct &pfp, TP3D &tp3d)
Definition: PFPUtils.cxx:2752
void tca::UpdateDeltaRMS ( Trajectory tj)

Definition at line 2542 of file StepUtils.cxx.

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

Referenced by UpdateStiffEl(), and UpdateTraj().

2543  {
2544  // Estimate the Delta RMS of the TPs on the end of tj.
2545 
2546  unsigned int lastPt = tj.EndPt[1];
2547  TrajPoint& lastTP = tj.Pts[lastPt];
2548 
2549  if (lastTP.Chg == 0) return;
2550  if (lastPt < 6) return;
2551 
2552  unsigned short ii, ipt, cnt = 0;
2553  float sum = 0;
2554  for (ii = 1; ii < tj.Pts.size(); ++ii) {
2555  ipt = lastPt - ii;
2556  if (ipt > tj.Pts.size() - 1) break;
2557  if (tj.Pts[ipt].Chg == 0) continue;
2558  sum += PointTrajDOCA(tj.Pts[ipt].Pos[0], tj.Pts[ipt].Pos[1], lastTP);
2559  ++cnt;
2560  if (cnt == lastTP.NTPsFit) break;
2561  if (ipt == 0) break;
2562  }
2563  if (cnt < 3) return;
2564  // RMS of Gaussian distribution is ~1.2 x the average
2565  // of a one-sided Gaussian distribution (since Delta is > 0)
2566  lastTP.DeltaRMS = 1.2 * sum / (float)cnt;
2567  if (lastTP.DeltaRMS < 0.02) lastTP.DeltaRMS = 0.02;
2568 
2569  } // UpdateDeltaRMS
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2514
Double_t sum
Definition: plot.C:31
bool tca::UpdateShower ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct ss,
bool  prt 
)

Definition at line 904 of file TCShower.cxx.

References util::abs(), tca::TCEvent::allHits, AnalyzeRotPos(), tca::ShowerStruct::Angle, tca::ShowerStruct::AspectRatio, 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, if(), kShowerTj, tca::ShowerStruct::NeedsUpdate, tca::ShowerStruct::ParentID, PointDirection(), tca::ShowerPoint::Pos, PosSep2(), PrintPos(), ReverseShower(), tca::ShowerStruct::ShowerTjID, tca::ShowerStruct::ShPts, tca::TCSlice::slHits, sn, sum, tcc, tca::ShowerPoint::TID, tca::ShowerStruct::TjIDs, tca::TCSlice::tjs, tca::TCConfig::unitsPerTick, tca::TrajPoint::UseHit, tca::detail::valsDecreasing(), and xx.

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

905  {
906  // This is intended to be a single function replacement for FCC, FA, USWP, etc. The calling
907  // function should have set NeedsUpdate true. A complete re-build is done if the ShPts vector
908  // is empty. This is only required if a tj is removed from the shower. When adding a tj
909  // to the shower the AddTj function appends the tj points to ShPts but doesn't fill
910  // the ShPts RotPos values.
911  // This function doesn't alter or check associations btw showers and tjs.
912 
913  if (ss.ID == 0) return false;
914  if (ss.TjIDs.empty()) return false;
915  if (ss.ShowerTjID <= 0 || ss.ShowerTjID > (int)slc.tjs.size()) return false;
916  if (ss.ParentID > 0 && ss.ParentID > (int)slc.tjs.size()) return false;
917  auto& stj = slc.tjs[ss.ShowerTjID - 1];
918  if (stj.Pts.size() != 3) return false;
919 
920  std::string fcnLabel = inFcnLabel + ".U2S";
921 
922  if (!ss.NeedsUpdate && !ss.ShPts.empty()) return true;
923 
924  // initialize the variables that will be defined in this function
925  ss.Energy = 0; // This is just ShowerEnergy(stj.TotChg) and could be deleted
926  ss.AspectRatio = 10;
927  // Direction FOM (0 = good). This is a property of the shower shape and is not
928  // defined by the presence or absence of a parent tj start point
929  ss.DirectionFOM = 10;
930  // Total charge of all hits in the shower
931  stj.TotChg = 0;
932  for (auto& stp : stj.Pts) {
933  // Shower start, charge center, and shower end
934  stp.Pos = {{0.0, 0.0}};
935  // Charge weighted average of hits this section (TP) along the shower
936  stp.HitPos = {{0.0, 0.0}};
937  // Direction from the start to the charge center - same for all TPs
938  stp.Dir = {{0.0, 0.0}};
939  // Hit charge in each section
940  stp.Chg = 0;
941  // transverse rms of hit positions relative to HitPos in this section
942  stp.DeltaRMS = 0;
943  // number of hits in this section
944  stp.NTPsFit = 0;
945  } // stp
946 
947  ss.ShPts.clear();
948  for (auto tjid : ss.TjIDs) {
949  if (tjid <= 0 || tjid > (int)slc.tjs.size()) return false;
950  auto& tj = slc.tjs[tjid - 1];
951  if (tj.CTP != ss.CTP) return false;
952  if (tj.AlgMod[kShowerTj]) return false;
953  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
954  TrajPoint& tp = tj.Pts[ipt];
955  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
956  if (!tp.UseHit[ii]) continue;
957  unsigned int iht = tp.Hits[ii];
958  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
959  if (hit.Integral() <= 0) continue;
960  ShowerPoint shpt;
961  shpt.HitIndex = iht;
962  shpt.TID = tj.ID;
963  shpt.Chg = hit.Integral();
964  shpt.Pos[0] = hit.WireID().Wire;
965  shpt.Pos[1] = hit.PeakTime() * tcc.unitsPerTick;
966  ss.ShPts.push_back(shpt);
967  } // ii
968  } // ipt
969  } // tjid
970  if (prt) mf::LogVerbatim("TC") << fcnLabel << " 2S" << ss.ID << " nShPts " << ss.ShPts.size();
971 
972  if (ss.ShPts.size() < 3) return false;
973 
974  // find the charge center and total charge
975  auto& stp1 = stj.Pts[1];
976  for (auto& shpt : ss.ShPts) {
977  stp1.Pos[0] += shpt.Chg * shpt.Pos[0];
978  stp1.Pos[1] += shpt.Chg * shpt.Pos[1];
979  stj.TotChg += shpt.Chg;
980  } // shpt
981  if (stj.TotChg <= 0) return false;
982  stp1.Pos[0] /= stj.TotChg;
983  stp1.Pos[1] /= stj.TotChg;
984  ss.Energy = ChgToMeV(stj.TotChg);
985  if (prt)
986  mf::LogVerbatim("TC") << fcnLabel << " 2S" << ss.ID << " Chg ctr " << PrintPos(stp1.Pos)
987  << " Energy " << (int)ss.Energy << " MeV";
988 
989  // find the direction using the shower parent if one exists
990  if (ss.ParentID > 0) {
991  // Set the direction to be the start of the parent to the shower center
992  auto& ptj = slc.tjs[ss.ParentID - 1];
993  // find the parent end farthest away from the charge center
994  unsigned short pend = FarEnd(ptj, stp1.Pos);
995  auto& ptp = ptj.Pts[ptj.EndPt[pend]];
996  stp1.Dir = PointDirection(ptp.Pos, stp1.Pos);
997  stp1.Ang = atan2(stp1.Dir[1], stp1.Dir[0]);
998  }
999  else {
1000  // find the shower direction using the points
1001  double sum = 0.;
1002  double sumx = 0.;
1003  double sumy = 0.;
1004  double sumxy = 0.;
1005  double sumx2 = 0.;
1006  for (auto& shpt : ss.ShPts) {
1007  sum += shpt.Chg;
1008  double xx = shpt.Pos[0] - stp1.Pos[0];
1009  double yy = shpt.Pos[1] - stp1.Pos[1];
1010  sumx += shpt.Chg * xx;
1011  sumy += shpt.Chg * yy;
1012  sumxy += shpt.Chg * xx * yy;
1013  sumx2 += shpt.Chg * xx * xx;
1014  } // shpt
1015  double delta = sum * sumx2 - sumx * sumx;
1016  if (delta == 0) return false;
1017  // A is the intercept (This should be ~0 )
1018  // double A = (sumx2 * sumy - sumx * sumxy) / delta;
1019  // B is the slope
1020  double B = (sumxy * sum - sumx * sumy) / delta;
1021  stp1.Ang = atan(B);
1022  stp1.Dir[0] = cos(stp1.Ang);
1023  stp1.Dir[1] = sin(stp1.Ang);
1024  } // no shower parent
1025 
1026  // TODO: ss.Angle should be eliminated. The shower tj Ang should be used instead
1027  ss.Angle = stp1.Ang;
1028  if (prt)
1029  mf::LogVerbatim("TC") << fcnLabel << " 2S" << ss.ID << " dir " << std::fixed
1030  << std::setprecision(2) << stp1.Dir[0] << " " << stp1.Dir[1]
1031  << " Angle " << stp1.Ang;
1032  for (unsigned short ipt = 0; ipt < 3; ++ipt) {
1033  if (ipt == 1) continue;
1034  stj.Pts[ipt].Dir = stp1.Dir;
1035  stj.Pts[ipt].Ang = stp1.Ang;
1036  } // ipt
1037 
1038  // fill the RotPos vector and sort
1039  std::vector<SortEntry> sortVec(ss.ShPts.size());
1040  unsigned short indx = 0;
1041  double cs = cos(-stp1.Ang);
1042  double sn = sin(-stp1.Ang);
1043  for (auto& shpt : ss.ShPts) {
1044  double xx = shpt.Pos[0] - stp1.Pos[0];
1045  double yy = shpt.Pos[1] - stp1.Pos[1];
1046  shpt.RotPos[0] = cs * xx - sn * yy;
1047  shpt.RotPos[1] = sn * xx + cs * yy;
1048  sortVec[indx].index = indx;
1049  sortVec[indx].val = shpt.RotPos[0];
1050  ++indx;
1051  } // shpt
1052  std::sort(sortVec.begin(), sortVec.end(), valsDecreasing);
1053  // put the points vector into the sorted order
1054  auto tPts = ss.ShPts;
1055  for (unsigned short ii = 0; ii < ss.ShPts.size(); ++ii)
1056  ss.ShPts[ii] = tPts[sortVec[ii].index];
1057 
1058  // Calculate the aspect ratio
1059  Point2_t alongTrans{{0.0, 0.0}};
1060  for (auto& shpt : ss.ShPts) {
1061  alongTrans[0] += shpt.Chg * std::abs(shpt.RotPos[0]);
1062  alongTrans[1] += shpt.Chg * std::abs(shpt.RotPos[1]);
1063  } // shpt
1064  alongTrans[0] /= stj.TotChg;
1065  alongTrans[1] /= stj.TotChg;
1066  if (alongTrans[1] == 0) return false;
1067  ss.AspectRatio = alongTrans[1] / alongTrans[0];
1068  if (prt)
1069  mf::LogVerbatim("TC") << fcnLabel << " 2S" << ss.ID << " AspectRatio " << ss.AspectRatio;
1070 
1071  // analyze the charge in three sections. Fill the stj HitPos and find DeltaRMS
1072  if (!AnalyzeRotPos(fcnLabel, slc, ss, prt)) return false;
1073 
1074  // Reverse the shower direction if needed and define the start point
1075  if (ss.ParentID > 0) {
1076  // The direction was defined by the start of a parent to the charge center. Check the consistency
1077  // with ShPts and reverse if needed
1078  auto& ptj = slc.tjs[ss.ParentID - 1];
1079  // find the parent end farthest away from the charge center
1080  unsigned short pend = FarEnd(ptj, stp1.Pos);
1081  auto& ptp = ptj.Pts[ptj.EndPt[pend]];
1082  auto& firstShPt = ss.ShPts[0];
1083  auto& lastShPt = ss.ShPts[ss.ShPts.size() - 1];
1084  if (PosSep2(ptp.Pos, lastShPt.Pos) < PosSep2(ptp.Pos, firstShPt.Pos))
1085  ReverseShower(fcnLabel, slc, ss, prt);
1086  stj.Pts[0].Pos = ptp.Pos;
1087  }
1088  else {
1089  // no parent exists. Compare the DeltaRMS at the ends
1090  if (stj.Pts[2].DeltaRMS < stj.Pts[0].DeltaRMS) ReverseShower(fcnLabel, slc, ss, prt);
1091  stj.Pts[0].Pos = ss.ShPts[0].Pos;
1092  } // no parent
1093 
1094  if (stj.Pts[2].DeltaRMS > 0) ss.DirectionFOM = stj.Pts[0].DeltaRMS / stj.Pts[2].DeltaRMS;
1095  // define the end point
1096  stj.Pts[2].Pos = ss.ShPts[ss.ShPts.size() - 1].Pos;
1097 
1098  DefineEnvelope(fcnLabel, slc, ss, prt);
1099  ss.NeedsUpdate = false;
1100  if (prt) mf::LogVerbatim("TC") << fcnLabel << " 2S" << ss.ID << " updated";
1101  return true;
1102 
1103  } // 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:3140
TCConfig tcc
Definition: DataStructs.cxx:9
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6356
void DefineEnvelope(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3442
if(nlines<=0)
std::array< float, 2 > Point2_t
Definition: DataStructs.h:41
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:562
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:2538
Float_t sn
Definition: plot.C:23
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2560
unsigned short FarEnd(const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3300
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
bool valsDecreasing(const SortEntry &c1, const SortEntry &c2)
Definition: Utils.cxx:39
bool AnalyzeRotPos(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3022
float ChgToMeV(float chg)
Definition: TCShower.cxx:3925
TCEvent evt
Definition: DataStructs.cxx:8
Double_t sum
Definition: plot.C:31
bool tca::UpdateShower ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct3D ss3,
bool  prt 
)

Definition at line 1106 of file TCShower.cxx.

References tca::ShowerStruct3D::ChgPos, tca::ShowerStruct3D::CotIDs, tca::TCSlice::cots, DecodeCTP(), tca::ShowerStruct3D::dEdx, tca::ShowerStruct3D::dEdxErr, dir, tca::ShowerStruct3D::Dir, tca::ShowerStruct3D::End, tca::ShowerStruct3D::Energy, tca::ShowerStruct3D::EnergyErr, FarEnd(), tca::ShowerStruct3D::ID, tca::ShowerStruct3D::Len, tca::ShowerStruct3D::MIPEnergy, tca::ShowerStruct3D::MIPEnergyErr, tca::ShowerStruct3D::NeedsUpdate, tca::ShowerStruct3D::ParentID, tca::TCSlice::pfps, geo::PlaneID::Plane, PosAtEnd(), PosSep(), SetMag(), tca::ShowerStruct3D::Start, tca::TCSlice::tjs, UpdateShower(), and tca::ShowerStruct3D::Vx3ID.

1107  {
1108  // Updates the 3D shower presumably because the 2D showers were changed or need to be updated.
1109  // This function returns false if there was a failure.
1110 
1111  if (ss3.ID == 0) return false;
1112  if (ss3.CotIDs.size() < 2) return false;
1113 
1114  std::string fcnLabel = inFcnLabel + ".U3S";
1115 
1116  // see if any of the 2D showers need an update
1117  for (auto cid : ss3.CotIDs) {
1118  auto& ss = slc.cots[cid - 1];
1119  if (ss.NeedsUpdate && prt)
1120  std::cout << fcnLabel << " ********* 3S" << ss3.ID << " 2S" << ss.ID
1121  << " needs an update...\n";
1122  UpdateShower(fcnLabel, slc, ss, prt);
1123  } // ci
1124 
1125  // check consistency
1126  if (ss3.ParentID > 0) {
1127  auto& pfp = slc.pfps[ss3.ParentID - 1];
1128  unsigned short pend = FarEnd(pfp, ss3.ChgPos);
1129  if (pfp.Vx3ID[pend] != ss3.Vx3ID) {
1130  if (prt)
1131  std::cout << fcnLabel << " ********* 3S" << ss3.ID << " has parent P" << ss3.ParentID
1132  << " with a vertex that is not attached the shower\n";
1133  }
1134  } // ss3.ParentID > 0
1135 
1136  // Find the average position and direction using pairs of 2D shower Tjs
1137  std::array<Point3_t, 3> pos;
1138  // the direction of all points in 2D showers is the same
1139  Vector3_t dir;
1140  std::array<double, 3> chg;
1141  for (unsigned short ipt = 0; ipt < 3; ++ipt) {
1142  chg[ipt] = 0;
1143  for (unsigned short xyz = 0; xyz < 3; ++xyz) {
1144  pos[ipt][xyz] = 0;
1145  dir[xyz] = 0;
1146  }
1147  } // ipt
1148  unsigned short nok = 0;
1149  for (unsigned short ipt = 0; ipt < 3; ++ipt) {
1150  if (chg[ipt] == 0) continue;
1151  for (unsigned short xyz = 0; xyz < 3; ++xyz)
1152  pos[ipt][xyz] /= chg[ipt];
1153  SetMag(dir, 1);
1154  ++nok;
1155  } // ipt
1156 
1157  if (nok != 3) return false;
1158  ss3.ChgPos = pos[1];
1159 
1160  if (ss3.ParentID > 0) {
1161  // There is a 3D-matched pfp at the shower start. The end that is farthest away from the
1162  // shower center should be shower start
1163  auto& pfp = slc.pfps[ss3.ParentID - 1];
1164  unsigned short pend = FarEnd(pfp, ss3.ChgPos);
1165  ss3.Start = PosAtEnd(pfp, pend);
1166  ss3.Dir = dir;
1167  }
1168  else {
1169  ss3.Dir = dir;
1170  ss3.Start = pos[0];
1171  }
1172  // define the end
1173  ss3.End = pos[2];
1174  ss3.Len = PosSep(ss3.Start, ss3.End);
1175 
1176  // dE/dx, energy, etc
1177  for (auto cid : ss3.CotIDs) {
1178  auto& ss = slc.cots[cid - 1];
1179  auto& stj = slc.tjs[ss.ShowerTjID - 1];
1180  unsigned short plane = DecodeCTP(ss.CTP).Plane;
1181  ss3.Energy[plane] = ss.Energy;
1182  // TODO: calculate the errors in some better way
1183  ss3.EnergyErr[plane] = 0.3 * ss.Energy;
1184  // TODO: what does MIPEnergy mean anyway?
1185  ss3.MIPEnergy[plane] = ss3.EnergyErr[plane];
1186  ss3.MIPEnergyErr[plane] = ss.Energy;
1187  ss3.dEdx[plane] = stj.dEdx[0];
1188  ss3.dEdxErr[plane] = 0.3 * stj.dEdx[0];
1189  } // ci
1190 
1191  ss3.NeedsUpdate = false;
1192  if (prt) mf::LogVerbatim("TC") << fcnLabel << " 3S" << ss3.ID << " updated";
1193  return true;
1194 
1195  } // UpdateShower
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3257
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1106
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
bool SetMag(Vector3_t &v1, double mag)
Definition: PFPUtils.cxx:2570
unsigned short FarEnd(const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3300
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:2554
std::array< double, 3 > Vector3_t
Definition: DataStructs.h:40
void tca::UpdateStiffEl ( TCSlice const &  slc,
Trajectory tj 
)

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

683  {
684  // A different stategy for updating a high energy electron trajectories
685  if (!tj.Strategy[kStiffEl]) return;
686  TrajPoint& lastTP = tj.Pts[tj.EndPt[1]];
687  // Set the lastPT delta before doing the fit
688  lastTP.Delta = PointTrajDOCA(lastTP.HitPos[0], lastTP.HitPos[1], lastTP);
689  if (tj.Pts.size() < 30) lastTP.NTPsFit += 1;
690  FitTraj(slc, tj);
691  UpdateTjChgProperties("UET", slc, tj, tcc.dbgStp);
692  UpdateDeltaRMS(tj);
693  tj.MCSMom = MCSMom(slc, tj);
694  if (tcc.dbgStp) {
695  mf::LogVerbatim("TC") << "UpdateStiffEl: lastPt " << tj.EndPt[1] << " Delta " << lastTP.Delta
696  << " AngleCode " << lastTP.AngleCode << " FitChi " << lastTP.FitChi
697  << " NTPsFit " << lastTP.NTPsFit << " MCSMom " << tj.MCSMom;
698  }
699  tj.NeedsUpdate = false;
700  tj.PDGCode = 111;
701  return;
702  } // UpdateStiffTj
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3381
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void FitTraj(TCSlice const &slc, Trajectory &tj)
Definition: Utils.cxx:798
void UpdateDeltaRMS(Trajectory &tj)
Definition: StepUtils.cxx:2542
TCConfig tcc
Definition: DataStructs.cxx:9
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2514
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice const &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3577
use the stiff electron strategy
Definition: DataStructs.h:492
void tca::UpdateTjChgProperties ( std::string  inFcnLabel,
TCSlice const &  slc,
Trajectory tj,
bool  prt 
)

Definition at line 3577 of file Utils.cxx.

References util::abs(), tca::Trajectory::AlgMod, tca::TCEvent::allHits, tca::Trajectory::AveChg, tca::Trajectory::ChgRMS, util::end(), tca::Trajectory::EndPt, evt, for(), kEnvOverlap, kEnvUnusedHits, kHaloTj, kKilled, kPhoton, tca::Trajectory::NeedsUpdate, tca::TCConfig::nPtsAve, tca::Trajectory::Pts, tca::TCSlice::slHits, sum, tcc, tca::Trajectory::TotChg, tca::Trajectory::VtxID, and tca::TCSlice::vtxs.

Referenced by AddLAHits(), ChkStopEndPts(), DotProd(), Forecast(), MaskedHitsOK(), MaxChargeAsymmetry(), SplitTraj(), StopShort(), StoreTraj(), UpdateStiffEl(), UpdateTraj(), and UpdateVxEnvironment().

3578  {
3579  // Updates properties of the tj that are affected when the TP environment
3580  // is changed. The most likely reason for a change is when the tj is attached to a
3581  // vertex in which case the Environment kEnvOverlap bit may be set by the UpdateVxEnvironment
3582  // function in which case this function is called.
3583  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) return;
3584 
3585  // first (un)set some bits
3586  for (auto& tp : tj.Pts) {
3587  if (tp.Chg <= 0) continue;
3588  tp.Environment[kEnvUnusedHits] = false;
3589  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3590  if (tp.UseHit[ii]) continue;
3591  unsigned int iht = tp.Hits[ii];
3592  if (slc.slHits[iht].InTraj == 0) tp.Environment[kEnvUnusedHits] = true;
3593  } // ii
3594  } // tp
3595 
3596  // Update the tj charge variables. The concept is explained by this graphic where
3597  // each column is a wire, Q = a TP with charge, q = a TP with charge that is an
3598  // EnvOverlap region, x = a wire that has a TP with Chg = 0 or a wire that has no TP
3599  // because the wire is dead, o = an EnvOverlap region, V = vertex attached to end. You should
3600  // imagine that all 3 tjs come from the same vertex
3601  // 01234567890123456789 npwc cnt range
3602  // VooooQQQQxxxQQQ 7 7 0 - 14
3603  // VqqqqQQQQxxxQQQQQQQQ 16 12 0 - 19
3604  // VooQQQ 3 3 0 - 5
3605  // The average is first calculated using Ave = sum(Q) / npwc
3606  // TotChg is calculated using
3607  tj.TotChg = 0;
3608  tj.AveChg = 0;
3609  tj.ChgRMS = 0.5;
3610 
3611  // These variables are used to calculate the average and rms using valid points with charge
3612  double vcnt = 0;
3613  double vsum = 0;
3614  double vsum2 = 0;
3615  // Reject a single large charge TP
3616  float bigChg = 0;
3617  for (unsigned short ipt = tj.EndPt[0] + 1; ipt < tj.EndPt[1]; ++ipt) {
3618  auto& tp = tj.Pts[ipt];
3619  if (tp.Chg > bigChg) bigChg = tp.Chg;
3620  } // ipt
3621  // variables for calculating the backup quanties. These are only used if npwc < 3
3622  double bcnt = 0;
3623  double bsum = 0;
3624  double bsum2 = 0;
3625  // don't include the end points
3626  for (unsigned short ipt = tj.EndPt[0] + 1; ipt < tj.EndPt[1]; ++ipt) {
3627  auto& tp = tj.Pts[ipt];
3628  if (tp.Chg <= 0) continue;
3629  // ignore the single large charge TP
3630  if (tp.Chg == bigChg) continue;
3631  // accumulate a backup sum in case most of the points are overlapped. Note that
3632  // tp.Chg has an angle correction, which is why the hit integral is summed
3633  // below. We don't care about this detail for the backup sum
3634  bsum += tp.Chg;
3635  bsum2 += tp.Chg * tp.Chg;
3636  if (tp.Chg > bigChg) bigChg = tp.Chg;
3637  ++bcnt;
3638  // Skip TPs that overlap with TPs on other Tjs. A correction will be made below
3639  if (tj.Pts[ipt].Environment[kEnvOverlap]) continue;
3640  ++vcnt;
3641  double tpchg = 0;
3642  for (unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
3643  if (!tp.UseHit[ii]) continue;
3644  unsigned int iht = tp.Hits[ii];
3645  tpchg += (*evt.allHits)[slc.slHits[iht].allHitsIndex].Integral();
3646  } // ii
3647  vsum += tpchg;
3648  vsum2 += tpchg * tpchg;
3649  } // ipt
3650 
3651  if (bcnt == 0) return;
3652 
3653  if (vcnt < 3) {
3654  // use the backup sum
3655  tj.TotChg = bsum;
3656  tj.AveChg = bsum / bcnt;
3657  if (vcnt > 2) {
3658  double arg = bsum2 - bcnt * tj.AveChg * tj.AveChg;
3659  if (arg > 0) tj.ChgRMS = sqrt(arg / (bcnt - 1));
3660  }
3661  for (auto& tp : tj.Pts)
3662  tp.AveChg = tj.AveChg;
3663  if (prt)
3664  mf::LogVerbatim("TC") << inFcnLabel << ".UpdateTjChgProperties: backup sum Set tj.AveChg "
3665  << (int)tj.AveChg << " ChgRMS " << tj.ChgRMS;
3666  return;
3667  } // low npwc
3668 
3669  double nWires = tj.EndPt[1] - tj.EndPt[0] + 1;
3670  if (nWires < 2) return;
3671  // correct for wires missing near vertices.
3672  // Count the number of wires between vertices at the ends and the first wire
3673  // that has charge. This code assumes that there should be one TP on each wire
3674  if (!tj.AlgMod[kPhoton]) {
3675  for (unsigned short end = 0; end < 2; ++end) {
3676  if (tj.VtxID[end] == 0) continue;
3677  auto& tp = tj.Pts[tj.EndPt[end]];
3678  auto& vx2 = slc.vtxs[tj.VtxID[end] - 1];
3679  int dw = std::abs(tp.Pos[0] - vx2.Pos[0]);
3680  // This assumes that the vertex is not inside the wire boundaries of the tj
3681  nWires += dw;
3682  } // end
3683  } // not a photon Tj
3684 
3685  tj.AveChg = vsum / vcnt;
3686  // calculate the total charge using the tj wire range
3687  tj.TotChg = nWires * tj.AveChg;
3688  // calculate the rms
3689  double arg = vsum2 - vcnt * tj.AveChg * tj.AveChg;
3690  double rms = 0.5;
3691  if (arg > 0) rms = sqrt(arg / (vcnt - 1));
3692  rms /= tj.AveChg;
3693  // don't let it be an unrealistically low value. It could be crazy large however.
3694  if (rms < 0.1) rms = 0.1;
3695  // Don't let the calculated charge RMS dominate until it is well known; after there are 5 - 10 valid TPs.
3696  // Set the starting charge rms = 0.5
3697  if (vcnt < 10) {
3698  double defFrac = 1 / vcnt;
3699  rms = defFrac * 0.5 + (1 - defFrac) * rms;
3700  }
3701  tj.ChgRMS = rms;
3702  if (prt)
3703  mf::LogVerbatim("TC") << inFcnLabel << ".UpdateTjChgProperties: Set tj.AveChg "
3704  << (int)tj.AveChg << " ChgRMS " << tj.ChgRMS;
3705 
3706  // Update the TP charge pulls.
3707  // Don't let the calculated charge RMS dominate the default
3708  // RMS until it is well known. Start with 50% error on the
3709  // charge RMS
3710  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
3711  auto& tp = tj.Pts[ipt];
3712  if (tp.Chg <= 0) continue;
3713  tp.ChgPull = (tp.Chg / tj.AveChg - 1) / tj.ChgRMS;
3714  } // ipt
3715 
3716  // update the local charge average using NPtsAve of the preceding points.
3717  // Handle short Tjs first.
3718  if (vcnt < tcc.nPtsAve) {
3719  for (auto& tp : tj.Pts)
3720  tp.AveChg = tj.AveChg;
3721  return;
3722  }
3723 
3724  // Set the local average to 0 first
3725  for (auto& tp : tj.Pts)
3726  tp.AveChg = 0;
3727  // Enter the local average on the points where an average can be calculated
3728  unsigned short nptsave = tcc.nPtsAve;
3729  unsigned short minPt = tj.EndPt[0] + nptsave;
3730  float lastAve = 0;
3731  for (unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
3732  unsigned short ipt = tj.EndPt[1] - ii;
3733  if (ipt < minPt) break;
3734  float cnt = 0;
3735  float sum = 0;
3736  for (unsigned short iii = 0; iii < nptsave; ++iii) {
3737  unsigned short iipt = ipt - iii;
3738  // Don't include the charge of the first point
3739  if (iipt == tj.EndPt[0]) break;
3740  auto& tp = tj.Pts[iipt];
3741  if (tp.Chg <= 0) continue;
3742  sum += tp.Chg;
3743  ++cnt;
3744  } // iii
3745  if (cnt > 2) {
3746  tj.Pts[ipt].AveChg = sum / cnt;
3747  lastAve = tj.Pts[ipt].AveChg;
3748  }
3749  } // ii
3750  // Fill in the points where no average was calculated
3751  for (unsigned short ii = tj.EndPt[0]; ii <= tj.EndPt[1]; ++ii) {
3752  unsigned short ipt = tj.EndPt[1] - ii;
3753  auto& tp = tj.Pts[ipt];
3754  if (tp.AveChg == 0) { tp.AveChg = lastAve; }
3755  else {
3756  lastAve = tp.AveChg;
3757  }
3758  } // ii
3759 
3760  tj.NeedsUpdate = false;
3761 
3762  } // UpdateTjChgProperties
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
constexpr auto abs(T v)
Returns the absolute value of the argument.
for(Int_t i=0;i< nentries;i++)
Definition: comparison.C:30
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
short nPtsAve
dump trajectory points
Definition: DataStructs.h:598
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:614
TCEvent evt
Definition: DataStructs.cxx:8
Double_t sum
Definition: plot.C:31
void tca::UpdateTraj ( TCSlice slc,
Trajectory tj 
)

Definition at line 705 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::Environment, tca::TrajPoint::FitChi, FitTraj(), tca::TrajPoint::HitPos, tca::TrajPoint::Hits, kEnvNearSrcHit, kRvPrp, kSlowing, kStiffEl, kStiffMu, 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(), and UpdateTjChgProperties().

Referenced by CheckHiMultUnusedHits(), MakeJunkTraj(), and StepAway().

706  {
707  // Updates the last added trajectory point fit, average hit rms, etc.
708 
709  tj.NeedsUpdate = true;
710  tj.MaskedLastTP = false;
711 
712  if (tj.EndPt[1] < 1) return;
713 
714  if (tj.Strategy[kStiffEl]) {
715  UpdateStiffEl(slc, tj);
716  return;
717  }
718  unsigned int lastPt = tj.EndPt[1];
719  TrajPoint& lastTP = tj.Pts[lastPt];
720  // nothing needs to be done if the last point has no hits but is near a hit in the
721  // srcHit collection
722  if (lastTP.Hits.empty() && lastTP.Environment[kEnvNearSrcHit]) {
723  tj.NeedsUpdate = false;
724  return;
725  }
726  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
727 
728  // find the previous TP that has hits (and was therefore in the fit)
729  unsigned short prevPtWithHits = USHRT_MAX;
730  unsigned short firstFitPt = tj.EndPt[0];
731  for (unsigned short ii = 1; ii < tj.Pts.size(); ++ii) {
732  unsigned short ipt = lastPt - ii;
733  if (tj.Pts[ipt].Chg > 0) {
734  prevPtWithHits = ipt;
735  break;
736  }
737  if (ipt == 0) break;
738  } // ii
739  if (prevPtWithHits == USHRT_MAX) return;
740 
741  // define the FitChi threshold above which something will be done
742  float maxChi = 2;
743  unsigned short minPtsFit = tcc.minPtsFit[tj.Pass];
744  // just starting out?
745  if (lastPt < 4) minPtsFit = 2;
746  bool cleanMuon = (tj.PDGCode == 13 && TrajIsClean(tj, tcc.dbgStp) && !tj.Strategy[kSlowing]);
747  // was !TrajIsClean...
748  if (cleanMuon) {
749  // Fitting a clean muon
750  maxChi = tcc.maxChi;
751  minPtsFit = lastPt / 3;
752  }
753 
754  // Set the lastPT delta before doing the fit
755  lastTP.Delta = PointTrajDOCA(lastTP.HitPos[0], lastTP.HitPos[1], lastTP);
756 
757  // update MCSMom. First ensure that nothing bad has happened
758  if (npwc > 3 && tj.Pts[lastPt].Chg > 0 && !tj.Strategy[kSlowing]) {
759  short newMCSMom = MCSMom(slc, tj);
760  short minMCSMom = 0.5 * tj.MCSMom;
761  if (lastPt > 10 && newMCSMom < minMCSMom) {
762  if (tcc.dbgStp) mf::LogVerbatim("TC") << "UT: MCSMom took a nose-dive " << newMCSMom;
763  UnsetUsedHits(slc, lastTP);
764  DefineHitPos(slc, lastTP);
765  SetEndPoints(tj);
766  tj.NeedsUpdate = false;
767  return;
768  }
769  tj.MCSMom = newMCSMom;
770  } // npwc > 3
771 
772  if (tcc.dbgStp) {
773  mf::LogVerbatim("TC") << "UT: lastPt " << lastPt << " lastTP.Delta " << lastTP.Delta
774  << " previous point with hits " << prevPtWithHits << " tj.Pts size "
775  << tj.Pts.size() << " AngleCode " << lastTP.AngleCode << " PDGCode "
776  << tj.PDGCode << " maxChi " << maxChi << " minPtsFit " << minPtsFit
777  << " MCSMom " << tj.MCSMom;
778  }
779 
780  UpdateTjChgProperties("UT", slc, tj, tcc.dbgStp);
781 
782  if (lastPt == 1) {
783  // Handle the second trajectory point. No error calculation. Just update
784  // the position and direction
785  lastTP.NTPsFit = 2;
786  FitTraj(slc, tj);
787  lastTP.FitChi = 0.01;
788  lastTP.AngErr = tj.Pts[0].AngErr;
789  if (tcc.dbgStp)
790  mf::LogVerbatim("TC") << "UT: Second traj point pos " << lastTP.Pos[0] << " "
791  << lastTP.Pos[1] << " dir " << lastTP.Dir[0] << " " << lastTP.Dir[1];
792  tj.NeedsUpdate = false;
793  SetAngleCode(lastTP);
794  return;
795  }
796 
797  if (lastPt == 2) {
798  // Third trajectory point. Keep it simple
799  lastTP.NTPsFit = 3;
800  FitTraj(slc, tj);
801  tj.NeedsUpdate = false;
802  if (tcc.dbgStp) mf::LogVerbatim("TC") << "UT: Third traj point fit " << lastTP.FitChi;
803  SetAngleCode(lastTP);
804  return;
805  }
806 
807  // Fit with > 2 TPs
808  // Keep adding hits until Chi/DOF exceeds 1
809  if (tj.Pts[prevPtWithHits].FitChi < 1 && !tj.Strategy[kSlowing]) lastTP.NTPsFit += 1;
810  // Reduce the number of points fit if the trajectory is long and chisq is getting a bit larger
811  if (lastPt > 20 && tj.Pts[prevPtWithHits].FitChi > 1.5 && lastTP.NTPsFit > minPtsFit)
812  lastTP.NTPsFit -= 2;
813  // don't let long muon fits get too long
814  if (cleanMuon && lastPt > 200 && tj.Pts[prevPtWithHits].FitChi > 1.0) lastTP.NTPsFit -= 2;
815  FitTraj(slc, tj);
816 
817  // don't get too fancy when we are starting out
818  if (lastPt < 6) {
819  tj.NeedsUpdate = false;
820  UpdateDeltaRMS(tj);
821  SetAngleCode(lastTP);
822  if (tcc.dbgStp)
823  mf::LogVerbatim("TC") << " Return with lastTP.FitChi " << lastTP.FitChi << " Chg "
824  << lastTP.Chg;
825  return;
826  }
827 
828  // find the first point that was fit.
829  unsigned short cnt = 0;
830  for (unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
831  unsigned short ipt = lastPt - ii;
832  if (tj.Pts[ipt].Chg > 0) {
833  firstFitPt = ipt;
834  ++cnt;
835  }
836  if (cnt == lastTP.NTPsFit) break;
837  if (ipt == 0) break;
838  }
839 
840  unsigned short ndead =
841  DeadWireCount(slc, lastTP.HitPos[0], tj.Pts[firstFitPt].HitPos[0], tj.CTP);
842  if (lastTP.FitChi > 1.5 && tj.Pts.size() > 6) {
843  // A large chisq jump can occur if we just jumped a large block of dead wires. In
844  // this case we don't want to mask off the last TP but reduce the number of fitted points
845  // This count will be off if there a lot of dead or missing wires...
846  // reduce the number of points significantly
847  if (ndead > 5 && !cleanMuon) {
848  if (lastTP.NTPsFit > 5) lastTP.NTPsFit = 5;
849  }
850  else {
851  // Have a longish trajectory and chisq was a bit large.
852  // Was this a sudden occurrence and the fraction of TPs are included
853  // in the fit? If so, we should mask off this
854  // TP and keep going. If these conditions aren't met, we
855  // should reduce the number of fitted points
856  float chirat = 0;
857  if (prevPtWithHits != USHRT_MAX && tj.Pts[prevPtWithHits].FitChi > 0)
858  chirat = lastTP.FitChi / tj.Pts[prevPtWithHits].FitChi;
859  // Don't mask hits when doing RevProp. Reduce NTPSFit instead
860  tj.MaskedLastTP =
861  (chirat > 1.5 && lastTP.NTPsFit > 0.3 * NumPtsWithCharge(slc, tj, false) &&
862  !tj.AlgMod[kRvPrp]);
863  // BB April 19, 2018: Don't mask TPs on low MCSMom Tjs
864  if (tj.MaskedLastTP && tj.MCSMom < 30) tj.MaskedLastTP = false;
865  if (tcc.dbgStp) {
866  mf::LogVerbatim("TC") << " First fit chisq too large " << lastTP.FitChi
867  << " prevPtWithHits chisq " << tj.Pts[prevPtWithHits].FitChi
868  << " chirat " << chirat << " NumPtsWithCharge "
869  << NumPtsWithCharge(slc, tj, false) << " tj.MaskedLastTP "
870  << tj.MaskedLastTP;
871  }
872  // we should also mask off the last TP if there aren't enough hits
873  // to satisfy the minPtsFit constraint
874  if (!tj.MaskedLastTP && NumPtsWithCharge(slc, tj, true) < minPtsFit) tj.MaskedLastTP = true;
875  } // few dead wires
876  } // lastTP.FitChi > 2 ...
877 
878  // Deal with a really long trajectory that is in trouble (uB cosmic).
879  if (tj.PDGCode == 13 && lastTP.FitChi > tcc.maxChi) {
880  if (lastTP.NTPsFit > 1.3 * tcc.muonTag[0]) {
881  lastTP.NTPsFit *= 0.8;
882  if (tcc.dbgStp) mf::LogVerbatim("TC") << " Muon - Reduce NTPsFit " << lastPt;
883  }
884  else {
885  tj.MaskedLastTP = true;
886  if (tcc.dbgStp) mf::LogVerbatim("TC") << " Muon - mask last point " << lastPt;
887  }
888  }
889 
890  if (tcc.dbgStp)
891  mf::LogVerbatim("TC") << "UT: First fit " << lastTP.Pos[0] << " " << lastTP.Pos[1] << " dir "
892  << lastTP.Dir[0] << " " << lastTP.Dir[1] << " FitChi " << lastTP.FitChi
893  << " NTPsFit " << lastTP.NTPsFit << " ndead wires " << ndead
894  << " tj.MaskedLastTP " << tj.MaskedLastTP;
895  if (tj.MaskedLastTP) {
896  UnsetUsedHits(slc, lastTP);
897  DefineHitPos(slc, lastTP);
898  SetEndPoints(tj);
899  lastPt = tj.EndPt[1];
900  lastTP.NTPsFit -= 1;
901  FitTraj(slc, tj);
902  UpdateTjChgProperties("UT", slc, tj, tcc.dbgStp);
903  SetAngleCode(lastTP);
904  return;
905  }
906  else {
907  // a more gradual change in chisq. Maybe reduce the number of points
908  unsigned short newNTPSFit = lastTP.NTPsFit;
909  // reduce the number of points fit to keep Chisq/DOF < 2 adhering to the pass constraint
910  // and also a minimum number of points fit requirement for long muons
911  float prevChi = lastTP.FitChi;
912  unsigned short ntry = 0;
913  float chiCut = 1.5;
914  if (tj.Strategy[kStiffMu]) chiCut = 5;
915  while (lastTP.FitChi > chiCut && lastTP.NTPsFit > minPtsFit) {
916  if (lastTP.NTPsFit > 15) { newNTPSFit = 0.7 * newNTPSFit; }
917  else if (lastTP.NTPsFit > 4) {
918  newNTPSFit -= 2;
919  }
920  else {
921  newNTPSFit -= 1;
922  }
923  if (lastTP.NTPsFit < 3) newNTPSFit = 2;
924  if (newNTPSFit < minPtsFit) newNTPSFit = minPtsFit;
925  lastTP.NTPsFit = newNTPSFit;
926  // BB April 19: try to add a last lonely hit on a low MCSMom tj on the last try
927  if (newNTPSFit == minPtsFit && tj.MCSMom < 30) chiCut = 2;
928  if (tcc.dbgStp)
929  mf::LogVerbatim("TC") << " Bad FitChi " << lastTP.FitChi << " Reduced NTPsFit to "
930  << lastTP.NTPsFit << " Pass " << tj.Pass << " chiCut " << chiCut;
931  FitTraj(slc, tj);
932  tj.NeedsUpdate = true;
933  if (lastTP.FitChi > prevChi) {
934  if (tcc.dbgStp)
935  mf::LogVerbatim("TC") << " Chisq is increasing " << lastTP.FitChi
936  << " Try to remove an earlier bad hit";
937  MaskBadTPs(slc, tj, chiCut);
938  ++ntry;
939  if (ntry == 2) break;
940  }
941  prevChi = lastTP.FitChi;
942  if (lastTP.NTPsFit == minPtsFit) break;
943  } // lastTP.FitChi > 2 && lastTP.NTPsFit > 2
944  }
945  // last ditch attempt if things look bad. Drop the last hit
946  if (tj.Pts.size() > tcc.minPtsFit[tj.Pass] && lastTP.FitChi > maxChi) {
947  if (tcc.dbgStp)
948  mf::LogVerbatim("TC") << " Last try. Drop last TP " << lastTP.FitChi << " NTPsFit "
949  << lastTP.NTPsFit;
950  UnsetUsedHits(slc, lastTP);
951  DefineHitPos(slc, lastTP);
952  SetEndPoints(tj);
953  lastPt = tj.EndPt[1];
954  FitTraj(slc, tj);
955  tj.MaskedLastTP = true;
956  }
957 
958  if (tj.NeedsUpdate) UpdateTjChgProperties("UT", slc, tj, tcc.dbgStp);
959 
960  if (tcc.dbgStp)
961  mf::LogVerbatim("TC") << " Fit done. Chi " << lastTP.FitChi << " NTPsFit " << lastTP.NTPsFit;
962 
963  if (tj.EndPt[0] == tj.EndPt[1]) return;
964 
965  // Don't let the angle error get too small too soon. Stepping would stop if the first
966  // few hits on a low momentum wandering track happen to have a very good fit to a straight line.
967  // We will do this by averaging the default starting value of AngErr of the first TP with the current
968  // value from FitTraj.
969  if (lastPt < 14) {
970  float defFrac = 1 / (float)(tj.EndPt[1]);
971  lastTP.AngErr = defFrac * tj.Pts[0].AngErr + (1 - defFrac) * lastTP.AngErr;
972  }
973 
974  UpdateDeltaRMS(tj);
975  SetAngleCode(lastTP);
976 
977  tj.NeedsUpdate = false;
978  return;
979 
980  } // UpdateTraj
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3381
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void FitTraj(TCSlice const &slc, Trajectory &tj)
Definition: Utils.cxx:798
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3330
std::vector< unsigned short > minPtsFit
Reconstruct in several passes.
Definition: DataStructs.h:556
void UpdateDeltaRMS(Trajectory &tj)
Definition: StepUtils.cxx:2542
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1061
void SetAngleCode(TrajPoint &tp)
Definition: Utils.cxx:765
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2514
void UpdateStiffEl(TCSlice const &slc, Trajectory &tj)
Definition: StepUtils.cxx:682
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:583
use the slowing-down strategy
Definition: DataStructs.h:494
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2095
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1791
TP is near a hit in the srcHit collection but no allHit hit exists (DUNE disambiguation error) ...
Definition: DataStructs.h:516
void MaskBadTPs(TCSlice &slc, Trajectory &tj, float const &maxChi)
Definition: StepUtils.cxx:2572
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice const &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3577
std::vector< short > muonTag
Definition: DataStructs.h:546
use the stiff electron strategy
Definition: DataStructs.h:492
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2072
bool TrajIsClean(Trajectory const &tj, bool prt)
Definition: Utils.cxx:3358
use the stiff muon strategy
Definition: DataStructs.h:493
void tca::UpdateVxEnvironment ( TCSlice slc)

Definition at line 3765 of file Utils.cxx.

References kEnvOverlap, kKilled, tca::TCSlice::tjs, and tca::TCSlice::vtxs.

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

3766  {
3767  // Set the kEnvOverlap bit true for all TPs that are close to other
3768  // trajectories that are close to vertices. The positions of TPs that
3769  // overlap are biased and shouldn't be used in a vertex fit. Also, these
3770  // TPs shouldn't be used to calculate dE/dx. The kEnvOverlap bit is first cleared
3771  // for ALL TPs and then set for ALL 2D vertices
3772 
3773  for (auto& tj : slc.tjs) {
3774  if (tj.AlgMod[kKilled]) continue;
3775  for (auto& tp : tj.Pts)
3776  tp.Environment[kEnvOverlap] = false;
3777  } // tj
3778 
3779  for (auto& vx : slc.vtxs) {
3780  if (vx.ID <= 0) continue;
3781  UpdateVxEnvironment(slc, vx, false);
3782  } // vx
3783 
3784  } // UpdateVxEnvironment
void UpdateVxEnvironment(TCSlice &slc, VtxStore &vx2, bool prt)
Definition: Utils.cxx:3787
void tca::UpdateVxEnvironment ( TCSlice slc,
VtxStore vx2,
bool  prt 
)

Definition at line 3787 of file Utils.cxx.

References util::abs(), tca::TrajPoint::Chg, tca::VtxStore::CTP, tca::TrajPoint::Dir, util::end(), tca::VtxStore::ID, if(), kEnvOverlap, kHaloTj, kKilled, kOnDeadWire, kPhoton, MakeBareTrajPoint(), tca::VtxStore::Pos, tca::TrajPoint::Pos, PrintPos(), tca::VtxStore::Stat, tca::TCSlice::tjs, and UpdateTjChgProperties().

3788  {
3789  // Update the Environment each TP on trajectories near the vertex
3790 
3791  if (vx2.ID == 0) return;
3792  if (vx2.Stat[kOnDeadWire]) return;
3793 
3794  if (prt) mf::LogVerbatim("TC") << "UpdateVxEnvironment check Tjs attached to vx2 " << vx2.ID;
3795 
3796  std::vector<int> tjlist;
3797  std::vector<unsigned short> tjends;
3798  if (vx2.Pos[0] < -0.4) return;
3799  unsigned int vxWire = std::nearbyint(vx2.Pos[0]);
3800  unsigned int loWire = vxWire;
3801  unsigned int hiWire = vxWire;
3802  for (auto& tj : slc.tjs) {
3803  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
3804  if (tj.CTP != vx2.CTP) continue;
3805  // ignore photon Tjs
3806  if (tj.AlgMod[kPhoton]) continue;
3807  for (unsigned short end = 0; end < 2; ++end) {
3808  if (tj.VtxID[end] != vx2.ID) continue;
3809  tjlist.push_back(tj.ID);
3810  tjends.push_back(end);
3811  if (tj.Pts[tj.EndPt[end]].Pos[0] < -0.4) return;
3812  unsigned int endWire = std::nearbyint(tj.Pts[tj.EndPt[end]].Pos[0]);
3813  if (endWire < loWire) loWire = endWire;
3814  if (endWire > hiWire) hiWire = endWire;
3815  } // end
3816  } // tj
3817  if (tjlist.size() < 2) return;
3818  if (hiWire < loWire + 1) return;
3819  if (prt)
3820  mf::LogVerbatim("TC") << " check Tjs on wires in the range " << loWire << " to " << hiWire;
3821 
3822  // create a vector of TPs between loWire and hiWire for every tj in the list
3823  // wire TP
3824  std::vector<std::vector<TrajPoint>> wire_tjpt;
3825  // companion vector of IDs
3826  std::vector<int> tjids;
3827  // populate this vector with TPs on Tjs that are in this range
3828  unsigned short nwires = hiWire - loWire + 1;
3829  for (unsigned short itj = 0; itj < tjlist.size(); ++itj) {
3830  auto& tj = slc.tjs[tjlist[itj] - 1];
3831  unsigned short end = tjends[itj];
3832  std::vector<TrajPoint> tjpt(nwires);
3833  // first enter valid TPs in the range
3834  for (unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
3835  unsigned short ipt;
3836  if (end == 0) { ipt = tj.EndPt[0] + ii; }
3837  else {
3838  ipt = tj.EndPt[1] - ii;
3839  }
3840  if (ipt > tj.Pts.size() - 1) break;
3841  // Make a copy of the TP so we can alter it
3842  auto tp = tj.Pts[ipt];
3843  if (tp.Chg <= 0) continue;
3844  tp.Chg = 1;
3845  tp.Hits.clear();
3846  if (tp.Pos[0] < -0.4) continue;
3847  unsigned int wire = std::nearbyint(tp.Pos[0]);
3848  unsigned short indx = wire - loWire;
3849  if (indx > nwires - 1) break;
3850  tp.Step = ipt;
3851  // We will use NTPsFit to count the number of neighboring TPs
3852  tp.NTPsFit = 0;
3853  tjpt[indx] = tp;
3854  } // ii
3855  // next make TPs on the wires that don't have real TPs
3856  TrajPoint ltp;
3857  // put ltp at the vertex position with direction towards the end point
3858  MakeBareTrajPoint(vx2.Pos, tj.Pts[tj.EndPt[end]].Pos, ltp);
3859  if (ltp.Dir[0] == 0) continue;
3860  if (ltp.Pos[0] < -0.4) continue;
3861  unsigned int wire = std::nearbyint(ltp.Pos[0]);
3862  ltp.Chg = 0;
3863  unsigned short indx = wire - loWire;
3864  // Break if we found a real TP
3865  if (tjpt[indx].Chg == 0) tjpt[indx] = ltp;
3866  double stepSize = std::abs(1 / ltp.Dir[0]);
3867  for (unsigned short ii = 0; ii < nwires; ++ii) {
3868  // move the local TP position by one step in the right direction
3869  for (unsigned short iwt = 0; iwt < 2; ++iwt)
3870  ltp.Pos[iwt] += ltp.Dir[iwt] * stepSize;
3871  if (ltp.Pos[0] < -0.4) break;
3872  wire = std::nearbyint(ltp.Pos[0]);
3873  if (wire < loWire || wire > hiWire) break;
3874  indx = wire - loWire;
3875  if (tjpt[indx].Chg > 0) continue;
3876  tjpt[indx] = ltp;
3877  } // ii
3878  if (prt) {
3879  mf::LogVerbatim myprt("TC");
3880  myprt << " T" << tj.ID;
3881  for (auto& tp : tjpt)
3882  myprt << " " << PrintPos(tp.Pos) << "_" << tp.Step << "_" << (int)tp.Chg;
3883  }
3884  wire_tjpt.push_back(tjpt);
3885  tjids.push_back(tj.ID);
3886  } // itj
3887 
3888  // iterate over the wires in the range
3889  for (unsigned short indx = 0; indx < nwires; ++indx) {
3890  // count the number of valid points on this wire
3891  unsigned short npts = 0;
3892  // count the number of points on this wire that have charge
3893  unsigned short npwc = 0;
3894  for (unsigned short itj = 0; itj < wire_tjpt.size(); ++itj) {
3895  if (wire_tjpt[itj][indx].Pos[0] == 0) continue;
3896  // found a valid point
3897  ++npts;
3898  if (wire_tjpt[itj][indx].Chg > 0) ++npwc;
3899  } // itj
3900  // no valid points
3901  if (npts == 0) continue;
3902  // all valid points have charge
3903  if (npwc == npts) continue;
3904  // re-find the valid points with charge and set the kEnvOverlap bit
3905  for (unsigned short itj = 0; itj < wire_tjpt.size(); ++itj) {
3906  if (wire_tjpt[itj][indx].Pos[0] == 0) continue;
3907  if (wire_tjpt[itj][indx].Chg == 0) continue;
3908  auto& tj = slc.tjs[tjids[itj] - 1];
3909  unsigned short ipt = wire_tjpt[itj][indx].Step;
3910  tj.Pts[ipt].Environment[kEnvOverlap] = true;
3911  tj.NeedsUpdate = true;
3912  if (prt) mf::LogVerbatim("TC") << " Set kEnvOverlap bit on T" << tj.ID << " ipt " << ipt;
3913  } // itj
3914  } // indx
3915 
3916  // update the charge rms for those tjs whose environment was changed above
3917  // (or elsewhere)
3918  for (auto tjid : tjids) {
3919  auto& tj = slc.tjs[tjid - 1];
3920  if (!tj.NeedsUpdate) continue;
3921  if (tj.CTP != vx2.CTP) continue;
3922  UpdateTjChgProperties("UVxE", slc, tj, prt);
3923  } // tjid
3924 
3925  } // UpdateVxEnvironment
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::string PrintPos(const Point2_t &pos)
Definition: Utils.cxx:6362
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
if(nlines<=0)
bool MakeBareTrajPoint(const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
Definition: Utils.cxx:4059
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice const &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3577
bool tca::ValidTwoPlaneMatch ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice slc,
const PFPStruct pfp 
)

Definition at line 1771 of file PFPUtils.cxx.

References geo::CryostatID::Cryostat, DecodeCTP(), EncodeCTP(), evt, tca::TCEvent::goodWire, MakeBareTP(), tca::TCSlice::nPlanes, tca::TCSlice::nWires, geo::PlaneID::Plane, tca::PFPStruct::TjIDs, tca::TCSlice::tjs, tca::PFPStruct::TP3Ds, geo::TPCID::TPC, and tca::TCSlice::TPCID.

Referenced by MakePFParticles().

1774  {
1775  // This function checks the third plane in the PFP when only two Tjs are 3D-matched to
1776  // ensure that the reason for the lack of a 3rd plane match is that it is in a dead region.
1777  // This function should be used after an initial fit is done and the TP3Ds are sorted
1778  if (pfp.TjIDs.size() != 2) return false;
1779  if (slc.nPlanes != 3) return false;
1780  if (pfp.TP3Ds.empty()) return false;
1781 
1782  // find the third plane
1783  std::vector<unsigned short> planes;
1784  for (auto tid : pfp.TjIDs)
1785  planes.push_back(DecodeCTP(slc.tjs[tid - 1].CTP).Plane);
1786  unsigned short thirdPlane = 3 - planes[0] - planes[1];
1787  CTP_t inCTP = EncodeCTP(slc.TPCID.Cryostat, slc.TPCID.TPC, thirdPlane);
1788  // Project the 3D position at the start into the third plane
1789  auto tp = MakeBareTP(detProp, pfp.TP3Ds[0].Pos, inCTP);
1790  unsigned int wire0 = 0;
1791  if (tp.Pos[0] > 0) wire0 = std::nearbyint(tp.Pos[0]);
1792  if (wire0 > slc.nWires[thirdPlane]) wire0 = slc.nWires[thirdPlane];
1793  // Do the same for the end
1794  unsigned short lastPt = pfp.TP3Ds.size() - 1;
1795  tp = MakeBareTP(detProp, pfp.TP3Ds[lastPt].Pos, inCTP);
1796  unsigned int wire1 = 0;
1797  if (tp.Pos[0] > 0) wire1 = std::nearbyint(tp.Pos[0]);
1798  if (wire1 > slc.nWires[thirdPlane]) wire1 = slc.nWires[thirdPlane];
1799  if (wire0 == wire1) return !evt.goodWire[thirdPlane][wire0];
1800  if (wire1 < wire0) std::swap(wire0, wire1);
1801  // count the number of good wires
1802  int dead = 0;
1803  int wires = wire1 - wire0;
1804  for (unsigned int wire = wire0; wire < wire1; ++wire)
1805  if (!evt.goodWire[thirdPlane][wire]) ++dead;
1806  // require that most of the wires are dead
1807  return (dead > 0.8 * wires);
1808  } // ValidTwoPlaneMatch
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:622
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const Point3_t &pos, CTP_t inCTP)
Definition: Utils.cxx:3928
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
unsigned int CTP_t
Definition: DataStructs.h:45
geo::PlaneID DecodeCTP(CTP_t CTP)
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:49
void swap(lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &a, lar::deep_const_fwd_iterator_nested< CITER, INNERCONTEXTRACT > &b)
TCEvent evt
Definition: DataStructs.cxx:8
float tca::VertexVertexPull ( const Vtx3Store vx1,
const Vtx3Store vx2 
)

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

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

Definition at line 1895 of file TCVertex.cxx.

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

1896  {
1897  // Calculates the position pull between two vertices
1898  double dw = vx1.Pos[0] - vx2.Pos[0];
1899  double dt = vx1.Pos[1] - vx2.Pos[1];
1900  double dwErr2 = (vx1.PosErr[0] * vx1.PosErr[0] + vx2.PosErr[0] * vx2.PosErr[0]) / 2;
1901  double dtErr2 = (vx1.PosErr[1] * vx1.PosErr[1] + vx2.PosErr[1] * vx2.PosErr[1]) / 2;
1902  dw = dw * dw / dwErr2;
1903  dt = dt * dt / dtErr2;
1904  return (float)sqrt(dw + dt);
1905  }
bool tca::WireHitRangeOK ( TCSlice const &  slc,
const CTP_t inCTP 
)

Definition at line 4511 of file Utils.cxx.

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

Referenced by DotProd(), and FindCloseHits().

4512  {
4513  // returns true if the passed CTP code is consistent with the CT code of the WireHitRangeVector
4514  geo::PlaneID planeID = DecodeCTP(inCTP);
4515  if (planeID.Cryostat != slc.TPCID.Cryostat) return false;
4516  if (planeID.TPC != slc.TPCID.TPC) return false;
4517  return true;
4518  }
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:195
geo::PlaneID DecodeCTP(CTP_t CTP)
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:315
bool tca::WrongSplitTj ( std::string  inFcnLabel,
TCSlice slc,
Trajectory tj,
unsigned short  tjEnd,
bool  prt 
)

Definition at line 2239 of file TCShower.cxx.

References tca::Trajectory::AlgMod, tca::Trajectory::ID, kComp3DVx, tca::Trajectory::VtxID, and tca::TCSlice::vtxs.

2244  {
2245  // Returns true if the trajectory was split by a 3D vertex match and the end of this trajectory is further
2246  // away from the shower than the partner trajectory
2247  // Here is a cartoon showing what we are trying to prevent. The shower is represented by a box. The trajectory
2248  // that is shown as (---*---) was originally reconstructed as a single trajectory. It was later split at the * position
2249  // 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
2250  // the shower. Tj is more likely to be the real parent
2251  //
2252  // 1111111111 2222222 TjID
2253  // 0 1 0 1 Tj end
2254  // --------------
2255  // | |
2256  // ----------*------- |
2257  // | |
2258  // --------------
2259  if (!tj.AlgMod[kComp3DVx]) return false;
2260  if (tjEnd > 1) return false;
2261 
2262  std::string fcnLabel = inFcnLabel + ".WSTj";
2263 
2264  // See if the other end is the end that was split. It should have a vertex with Topo = 8 or 11
2265  unsigned short otherEnd = 1 - tjEnd;
2266  // if(prt) mf::LogVerbatim("TC")<<"WSTj: otherEnd "<<otherEnd<<" vtxID "<<tj.VtxID[otherEnd];
2267  if (tj.VtxID[otherEnd] == 0) return false;
2268  unsigned short ivx = tj.VtxID[otherEnd] - 1;
2269  // A vertex exists but not a 3D split vertex
2270  if (slc.vtxs[ivx].Topo != 8 && slc.vtxs[ivx].Topo != 10) return false;
2271  if (prt)
2272  mf::LogVerbatim("TC") << fcnLabel << " Primary candidate " << tj.ID
2273  << " was split by a 3D vertex";
2274  return true;
2275 
2276  } // WrongSplitTj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim

Variable Documentation

constexpr unsigned int tca::Cpad = 10000

Definition at line 47 of file DataStructs.h.

Referenced by DecodeCTP().

const std::vector< std::string > tca::EndFlagNames {"Signal", "AtKink", "AtVtx", "Bragg", "AtTj", "OutFV", "NoFitVx"}

Definition at line 87 of file DataStructs.cxx.

Referenced by PrintEndFlag(), and tca::TrajClusterAlg::TrajClusterAlg().

TCEvent tca::evt

Definition at line 8 of file DataStructs.cxx.

Referenced by AddHits(), AddLooseHits(), AddTj(), AnalyzeHits(), cheat::BackTracker::CanRun(), cluster::HoughBaseAlg::ChargeInfo_t::ChargeInfo_t(), ChgFracNearPos(), ChkBegin(), tca::TrajClusterAlg::ClearResults(), lar_pandora::LArPandoraHelper::CollectPFParticles(), anab::FVectorReader< T, N >::create(), art::PtrMaker< T >::create(), util::CreateAssn(), tca::TrajClusterAlg::CreateSlice(), DeadWireCount(), DECLARE_ART_SERVICE_INTERFACE_IMPL(), dEdx(), DefineHitPos(), tca::TrajClusterAlg::DefineShTree(), evd::MCBriefPad::Draw(), evd::Display3DPad::Draw(), evd::CalorPad::Draw(), evd::TQPad::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(), tca::TrajClusterAlg::ExpectSlicedHits(), FillGaps(), FillWireHitRange(), FillWireIntersections(), Find3DVertices(), FindCloseHits(), FindCloseTjs(), FindPFParticles(), FindUseHits(), Forecast(), GetHitMultiplet(), cluster::ClusterMergeHelper::GetManager(), GetOrigin(), lar_cluster3d::StandardHit3DBuilder::getTimeToExecute(), lar_cluster3d::SnippetHit3DBuilder::getTimeToExecute(), evdb::ButtonBar::GoTo(), evd::HeaderDrawer::Header(), HitSep2(), HitsPosTick(), HitsRMSTick(), HitTimeErr(), trkf::PMAlgTrackMaker::init(), lar_pandora::LArPandoraEventDump::PandoraData::LoadAssociation(), main(), MakeBareTrajPoint(), MakeHaloTj(), MakeJunkTraj(), MakePFParticles(), MakePFPTjs(), MaskedHitsOK(), Match3Planes(), Match3PlanesSpt(), tca::TrajClusterAlg::MergeTPHits(), tca::TrajClusterAlg::MergeTPHitsOnWire(), NearbySrcHit(), evdb::DisplayWindow::OpenWindow(), mvapid::MVAAlg::SumDistance2::operator()(), PFPVertexCheck(), PointTrajDOCA(), PrintHit(), PrintHitShort(), PrintTP(), cheat::BackTrackerService::priv_PrepEvent(), MCReco::produce(), reco::shower::LArPandoraModularShowerCreation::produce(), trkf::TrackStitcher::produce(), cluster::TrajCluster::produce(), trkf::PMAlgTrackMaker::produce(), evd::RecoBaseDrawer::Prong2D(), cheat::PhotonBackTrackerService::provider(), cheat::ParticleInventoryService::provider(), cheat::BackTrackerService::provider(), art::PtrMaker< T >::PtrMaker(), tca::TrajClusterAlg::ReconstructAllTraj(), evdb::ScanFrame::Record(), ReversePropagate(), 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(), tca::TrajClusterAlg::SetInputSpts(), cluster::ClusterMatchAlg::SetMCTruthModName(), tca::TrajClusterAlg::SetSourceHits(), SignalAtTp(), SignalAtTpInSlc(), SplitTraj(), SptInTPC(), StartChgVec(), StartTraj(), StepAway(), StorePFP(), StoreShower(), StoreTraj(), StoreVertex(), TCIntersectionPoint(), TPHitsRMSTick(), TpSumHitChg(), tca::TrajClusterAlg::TrajClusterAlg(), TrajHitsOK(), TrimEndPts(), UpdateShower(), UpdateTjChgProperties(), ValidTwoPlaneMatch(), and evgen::Decay0Gen::~Decay0Gen().

constexpr unsigned int tca::pAlgModSize = 6

Definition at line 275 of file DataStructs.h.

Referenced by PrintTP3Ds().

const std::vector< std::string > tca::StrategyBitNames {"Normal", "StiffEl", "StiffMu", "Slowing"}

Definition at line 98 of file DataStructs.cxx.

Referenced by PrintT(), and StepAway().

TCConfig tca::tcc

Definition at line 9 of file DataStructs.cxx.

Referenced by AddCloseTjsToList(), AddHits(), AddLAHits(), AddLooseHits(), AddTj(), AnalyzeHits(), AngleRange(), AttachAnyTrajToVertex(), AttachAnyVertexToTraj(), AttachTrajToVertex(), BraggSplit(), CheckHiMultEndHits(), CheckHiMultUnusedHits(), CheckStiffEl(), CheckTraj(), CheckTrajBeginChg(), ChgFracBetween(), ChgFracNearEnd(), ChkBegin(), ChkChgAsymmetry(), ChkEndKink(), tca::TrajClusterAlg::ChkInTraj(), ChkMichel(), ChkStop(), ChkStopEndPts(), CompatibleMerge(), CompleteIncomplete3DVertices(), CompleteIncomplete3DVerticesInGaps(), CompleteIncompleteShower(), CountBadPoints(), tca::TrajClusterAlg::CreateSlice(), CreateTP3D(), DecodeDebugString(), dEdx(), DefineEnvelope(), DefineHitPos(), DefinePFPParents(), DefineTjParents(), DumpTj(), EndMerge(), ExpectedHitsRMS(), FilldEdx(), FillGaps(), FillGaps3D(), FillmAllTraj(), FillWireHitRange(), FillWireIntersections(), Find2DVertices(), Find3DVertices(), FindCloseHits(), FindCloseTjs(), FindHammerVertices(), FindHammerVertices2(), tca::TrajClusterAlg::FindJunkTraj(), FindParent(), FindPFParticles(), FindShowers3D(), FindShowerStart(), FindStartChg(), FindUseHits(), FitTP3Ds(), FixBegin(), Forecast(), GetHitMultiplet(), GetOrigin(), GottaKink(), HitSep2(), HitsPosTime(), HitsRMSTime(), HitsTimeErr2(), HitTimeErr(), InsideTPC(), IsCloseToVertex(), IsGhost(), KillPoorVertices(), KillVerticesInShower(), LastEndMerge(), MakeBareTP(), MakeBareTrajPoint(), MakeHaloTj(), MakeJunkTraj(), MakeJunkVertices(), MakePFParticles(), MakePFPTjs(), MakeSmallAnglePFP(), MakeTP3D(), MakeVertexObsolete(), MaskBadTPs(), MaskedHitsOK(), MaskTrajEndPoints(), Match2Planes(), Match3DFOM(), Match3Planes(), Match3PlanesSpt(), MergeGhostTjs(), MergeNearby2DShowers(), MergeOverlap(), MergeShowerChain(), MergeSubShowers(), MergeSubShowersTj(), MergeWithVertex(), NearbySrcHit(), ParentFOM(), PointTrajDOCA(), PosInPlane(), Print2DShowers(), Print2V(), PrintAllTraj(), PrintDebugMode(), PrintPos(), PrintShower(), PrintT(), PrintTrajectory(), cluster::TrajCluster::produce(), Reconcile2Vs(), ReconcileTPs(), ReconcileVertices(), tca::TrajClusterAlg::ReconstructAllTraj(), ReSection(), ReversePropagate(), tca::TrajClusterAlg::RunTrajClusterAlg(), SaveAllCots(), SaveCRInfo(), SaveTjInfo(), SaveTjInfoStuff(), SetAngleCode(), tca::TrajClusterAlg::SetInputHits(), SetPDGCode(), SetSection(), tca::TrajClusterAlg::SetSourceHits(), SetStrategy(), SetVx2Score(), SetVx3Score(), SignalAtTp(), SignalAtTpInSlc(), SplitTraj(), SplitTrajCrossingVertices(), StartChgVec(), StartTraj(), StepAway(), StitchPFPs(), StopIfBadFits(), StopShort(), StoreTraj(), TagShowerLike(), TPHitsRMSTime(), tca::TrajClusterAlg::TrajClusterAlg(), TrimEndPts(), TrimHiChgEndPts(), UpdateShower(), UpdateStiffEl(), UpdateTjChgProperties(), and UpdateTraj().

std::vector< TjForecast > tca::tjfs

Definition at line 10 of file DataStructs.cxx.

Referenced by Forecast(), SetStrategy(), and StepAway().

constexpr unsigned int tca::Tpad = 10

Definition at line 46 of file DataStructs.h.

Referenced by DecodeCTP().

const std::vector< std::string > tca::VtxBitNames
Initial value:
{"VxTrjTried",
"Fixed",
"OnDeadWire",
"HiVx3Score",
"VxTruMatch",
"VxMerged",
"VxIndPlnNoChg",
"VxEnvOK"}

Definition at line 89 of file DataStructs.cxx.

Referenced by Print2V(), and PrintAllTraj().