LArSoft  v09_90_00
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 47 of file DataStructs.h.

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

Definition at line 43 of file DataStructs.h.

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

Definition at line 41 of file DataStructs.h.

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

Definition at line 44 of file DataStructs.h.

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

Definition at line 42 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 419 of file DataStructs.h.

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

don't mess with this line

Definition at line 500 of file DataStructs.h.

500  {
501  kSignal,
502  kAtKink,
503  kAtVtx,
504  kBragg,
505  kAtTj,
506  kOutFV,
507  kNoFitVx,
508  kFlagBitSize
509  } EndFlag_t;
don&#39;t mess with this line
Definition: DataStructs.h:508
EndFlag_t
Definition: DataStructs.h:500
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 302 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 492 of file DataStructs.h.

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

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

Definition at line 263 of file DataStructs.h.

263  {
264  kTP3DGood, // Is good for fitting and calorimetry
265  kTP3DBad, // Should be removed from the trajectory
266  kTP3DHiDEdx // Has high dE/dx
267  } TP3DFlags_t;
TP3DFlags_t
Definition: DataStructs.h:263
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 512 of file DataStructs.h.

512  {
514  kEnvNearMuon,
516  kEnvOverlap,
519  kEnvFlag
520  } TPEnvironment_t;
a general purpose flag bit used in 3D matching
Definition: DataStructs.h:519
TP is near a hit in the srcHit collection but no allHit hit exists (DUNE disambiguation error) ...
Definition: DataStructs.h:518
TPEnvironment_t
Definition: DataStructs.h:512
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 88 of file DataStructs.h.

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

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:551
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:3329
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
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:2513
bool LongPulseHit(const recob::Hit &hit)
Definition: Utils.cxx:4315
int TDCtick_t
Type representing a TDC tick.
Definition: RawTypes.h:25
float projectionErrFactor
Definition: DataStructs.h:576
if(nlines<=0)
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:564
use the slowing-down strategy
Definition: DataStructs.h:496
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2094
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:518
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:623
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6344
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
float ExpectedHitsRMS(const TrajPoint &tp)
Definition: Utils.cxx:1910
unsigned short NumHitsInTP(const TrajPoint &tp, HitStatus_t hitRequest)
Definition: Utils.cxx:4196
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:615
use the stiff electron strategy
Definition: DataStructs.h:494
bool NearbySrcHit(geo::PlaneID plnID, unsigned int wire, float loTick, float hiTick)
Definition: Utils.cxx:2029
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2762
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:3329
std::vector< unsigned int > PutTrajHitsInVector(const Trajectory &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2688
TCConfig tcc
Definition: DataStructs.cxx:9
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6353
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:564
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:2773
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6344
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice const &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3576
float VLAStepSize
Definition: DataStructs.h:577
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:463
if(nlines<=0)
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:564
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:3245
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
Detector simulation of raw signals on wires.
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:615
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 1817 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().

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

Definition at line 4259 of file Utils.cxx.

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

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

4260  {
4261  // Find the average hit rms by analyzing the full hit collection. This
4262  // only needs to be done once per job.
4263 
4264  if ((*evt.allHits).empty()) return true;
4265  // no sense re-calculating it if it's been done
4266  if (evt.aveHitRMSValid) return true;
4267 
4268  auto const& wireid = (*evt.allHits)[0].WireID();
4269 
4270  unsigned short nplanes = tcc.geom->Nplanes(wireid.asPlaneID());
4271  evt.aveHitRMS.resize(nplanes);
4272  std::vector<float> cnt(nplanes, 0);
4273  for (unsigned short iht = 0; iht < (*evt.allHits).size(); ++iht) {
4274  auto& hit = (*evt.allHits)[iht];
4275  unsigned short plane = hit.WireID().Plane;
4276  if (plane > nplanes - 1) return false;
4277  if (cnt[plane] > 200) continue;
4278  // require multiplicity one
4279  if (hit.Multiplicity() != 1) continue;
4280  // not-crazy Chisq/DOF
4281  if (hit.GoodnessOfFit() < 0 || hit.GoodnessOfFit() > 500) continue;
4282  // don't let a lot of runt hits screw up the calculation
4283  if (hit.PeakAmplitude() < 1) continue;
4284  evt.aveHitRMS[plane] += hit.RMS();
4285  ++cnt[plane];
4286  // quit if enough hits are found
4287  bool allDone = true;
4288  for (unsigned short plane = 0; plane < nplanes; ++plane)
4289  if (cnt[plane] < 200) allDone = false;
4290  if (allDone) break;
4291  } // iht
4292 
4293  // assume there are enough hits in each plane
4294  evt.aveHitRMSValid = true;
4295  for (unsigned short plane = 0; plane < nplanes; ++plane) {
4296  if (cnt[plane] > 4) { evt.aveHitRMS[plane] /= cnt[plane]; }
4297  else {
4298  evt.aveHitRMS[plane] = 10;
4299  evt.aveHitRMSValid = false;
4300  } // cnt too low
4301  } // plane
4302 
4303  if (tcc.modes[kDebug]) {
4304  std::cout << "Analyze hits aveHitRMS";
4305  std::cout << std::fixed << std::setprecision(1);
4306  for (auto rms : evt.aveHitRMS)
4307  std::cout << " " << rms;
4308  std::cout << " aveHitRMSValid? " << evt.aveHitRMSValid << "\n";
4309  }
4310 
4311  return true;
4312  } // Analyze hits
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:631
const geo::GeometryCore * geom
Definition: DataStructs.h:569
Detector simulation of raw signals on wires.
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:600
bool aveHitRMSValid
set true when the average hit RMS is well-known
Definition: DataStructs.h:640
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:615
unsigned int Nplanes(TPCID const &tpcid=tpc_zero) const
Returns the total number of planes in the specified TPC.
Definition: GeometryCore.h:977
TCEvent evt
Definition: DataStructs.cxx:8
master switch for turning on debug mode
Definition: DataStructs.h:526
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 758 of file Utils.cxx.

References tca::TrajPoint::Ang.

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

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

Definition at line 783 of file Utils.cxx.

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

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

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

1671  {
1672 
1673  if (ivx > slc.vtxs.size() - 1) return false;
1674  if (slc.vtxs[ivx].ID == 0) return false;
1675  if (tcc.vtx2DCuts[0] < 0) return false;
1676 
1677  VtxStore& vx = slc.vtxs[ivx];
1678  // Hammer vertices should be isolated and clean
1679  if (vx.Topo == 5 || vx.Topo == 6) return false;
1680 
1681  unsigned short bestTj = USHRT_MAX;
1682  // Construct a FOM = (TP-Vtx pull) * (TP-Vtx sep + 1).
1683  // The +1 keeps FOM from being 0
1684  float bestFOM = 2 * tcc.vtx2DCuts[3] * (tcc.vtx2DCuts[0] + 1);
1685  for (unsigned int itj = 0; itj < slc.tjs.size(); ++itj) {
1686  auto& tj = slc.tjs[itj];
1687  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
1688  if (tj.CTP != vx.CTP) continue;
1689  // make some rough cuts
1690  std::array<float, 2> sep;
1691  sep[0] = PosSep(vx.Pos, tj.Pts[tj.EndPt[0]].Pos);
1692  sep[1] = PosSep(vx.Pos, tj.Pts[tj.EndPt[1]].Pos);
1693  unsigned short end = 0;
1694  if (sep[1] < sep[0]) end = 1;
1695  if (sep[end] > 100) continue;
1696  if (tj.VtxID[end] > 0) continue;
1697  auto& tp = tj.Pts[tj.EndPt[end]];
1698  // Pad the separation a bit so we don't get zero
1699  float fom = TrajPointVertexPull(tp, vx) * (sep[end] + 1);
1700  if (fom > bestFOM) continue;
1701  if (prt) {
1702  mf::LogVerbatim("TC") << "AATTV: T" << tj.ID << " 2V" << vx.ID << " Topo " << vx.Topo
1703  << " FOM " << fom << " cut " << bestFOM;
1704  }
1705  bestTj = itj;
1706  bestFOM = fom;
1707  } // tj
1708  if (bestTj > slc.tjs.size() - 1) return false;
1709  auto& tj = slc.tjs[bestTj];
1710  return AttachTrajToVertex(slc, tj, vx, prt);
1711  } // 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:1714
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2558
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:543
float TrajPointVertexPull(const TrajPoint &tp, const VtxStore &vx)
Definition: TCVertex.cxx:1836
bool tca::AttachAnyVertexToTraj ( TCSlice slc,
int  tjID,
bool  prt 
)

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

1630  {
1631  // Try to attach a tj that is stored in slc.tjs with any vertex
1632  if (tjID <= 0 || tjID > (int)slc.tjs.size()) return false;
1633  if (slc.vtxs.empty()) return false;
1634  auto& tj = slc.tjs[tjID - 1];
1635  if (tj.AlgMod[kKilled]) return false;
1636  if (tcc.vtx2DCuts[0] <= 0) return false;
1637 
1638  unsigned short bestVx = USHRT_MAX;
1639  // Construct a FOM = (TP-Vtx pull) * (TP-Vtx sep + 1) * (Vtx Score).
1640  // The +1 keeps FOM from being 0
1641  float bestFOM = 2 * tcc.vtx2DCuts[3] * (tcc.vtx2DCuts[0] + 1) * tcc.vtx2DCuts[7];
1642  for (unsigned short ivx = 0; ivx < slc.vtxs.size(); ++ivx) {
1643  auto& vx = slc.vtxs[ivx];
1644  if (vx.ID == 0) continue;
1645  if (vx.CTP != tj.CTP) continue;
1646  // make some rough cuts
1647  std::array<float, 2> sep;
1648  sep[0] = PosSep(vx.Pos, tj.Pts[tj.EndPt[0]].Pos);
1649  sep[1] = PosSep(vx.Pos, tj.Pts[tj.EndPt[1]].Pos);
1650  unsigned short end = 0;
1651  if (sep[1] < sep[0]) end = 1;
1652  if (sep[end] > 100) continue;
1653  if (tj.VtxID[end] > 0) continue;
1654  auto& tp = tj.Pts[tj.EndPt[end]];
1655  // Pad the separation a bit so we don't get zero
1656  float fom = TrajPointVertexPull(tp, vx) * (sep[end] + 1) * vx.Score;
1657  if (fom > bestFOM) continue;
1658  if (prt)
1659  mf::LogVerbatim("TC") << "AAVTT: T" << tjID << " 2V" << vx.ID << " FOM " << fom << " cut "
1660  << bestFOM;
1661  bestVx = ivx;
1662  bestFOM = fom;
1663  } // vx
1664  if (bestVx > slc.vtxs.size() - 1) return false;
1665  auto& vx = slc.vtxs[bestVx];
1666  return AttachTrajToVertex(slc, tj, vx, prt);
1667  } // 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:1714
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2558
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:543
float TrajPointVertexPull(const TrajPoint &tp, const VtxStore &vx)
Definition: TCVertex.cxx:1836
bool tca::AttachToAnyVertex ( TCSlice slc,
PFPStruct pfp,
float  maxSep,
bool  prt 
)

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

1573  {
1574  // Attaches to any 3D vertex but doesn't require consistency with
1575  // PFP -> Tj -> 2V -> 3V assns
1576  if (pfp.ID <= 0) return false;
1577 
1578  float pLen = Length(pfp);
1579  if (pLen == 0) return false;
1580 
1581  // save the old assignents and clear them
1582  // auto oldVx3ID = pfp.Vx3ID;
1583  for (unsigned short end = 0; end < 2; ++end)
1584  pfp.Vx3ID[end] = 0;
1585  std::array<Point3_t, 2> endPos;
1586  endPos[0] = PosAtEnd(pfp, 0);
1587  endPos[1] = PosAtEnd(pfp, 1);
1588 
1589  std::array<float, 2> foms{{100., 100.}};
1590  std::array<int, 2> vtxs{{0}};
1591  for (auto& vx3 : slc.vtx3s) {
1592  if (vx3.ID <= 0) continue;
1593  if (vx3.TPCID != pfp.TPCID) continue;
1594  std::array<float, 2> sep;
1595  Point3_t vpos = {{vx3.X, vx3.Y, vx3.Z}};
1596  sep[0] = PosSep(vpos, endPos[0]);
1597  sep[1] = PosSep(vpos, endPos[1]);
1598  unsigned short end = 0;
1599  if (sep[1] < sep[0]) end = 1;
1600  // ignore if separation is too large
1601  if (sep[end] > 100) continue;
1602  // find the direction vector between these points
1603  auto vpDir = PointDirection(vpos, endPos[end]);
1604  auto dir = DirAtEnd(pfp, end);
1605  double dotp = std::abs(DotProd(vpDir, dir));
1606  float fom = dotp * sep[end];
1607  if (prt)
1608  mf::LogVerbatim("TC") << "ATAV: P" << pfp.ID << " end " << end << " 3V" << vx3.ID << " sep "
1609  << sep[end] << " fom " << fom << " maxSep " << maxSep;
1610  // ignore if separation is too large
1611  if (sep[end] > maxSep) continue;
1612  if (fom < foms[end]) {
1613  foms[end] = fom;
1614  vtxs[end] = vx3.ID;
1615  }
1616  } // vx3
1617  bool bingo = false;
1618  for (unsigned short end = 0; end < 2; ++end) {
1619  if (vtxs[end] == 0) continue;
1620  if (prt)
1621  mf::LogVerbatim("TC") << "ATAV: set P" << pfp.ID << " end " << end << " -> 3V" << vtxs[end];
1622  pfp.Vx3ID[end] = vtxs[end];
1623  bingo = true;
1624  } // end
1625  return bingo;
1626  } // AttachToAnyVertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float Length(const PFPStruct &pfp)
Definition: PFPUtils.cxx:3269
std::array< double, 3 > Point3_t
Definition: DataStructs.h:41
constexpr auto abs(T v)
Returns the absolute value of the argument.
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3259
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:2542
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:2558
Vector3_t DirAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3251
bool tca::AttachTrajToVertex ( TCSlice slc,
Trajectory tj,
VtxStore vx,
bool  prt 
)

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

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

Definition at line 2639 of file PFPUtils.cxx.

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

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

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

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

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

Definition at line 1330 of file PFPUtils.cxx.

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

Referenced by MakePFParticles(), and Recover().

1331  {
1332  // analyze the TP3D vector to determine if it can be reconstructed in 3D in more than one section with
1333  // the requirement that there are at least 3 points in two planes
1334  if (pfp.AlgMod[kJunk3D]) return false;
1335  if (pfp.AlgMod[kSmallAngle]) return false;
1336  if (pfp.TP3Ds.size() < 12) return false;
1337  unsigned short toPt = Find3DRecoRange(slc, pfp, 0, 3, 1);
1338  if (toPt > pfp.TP3Ds.size()) return false;
1339  unsigned short nextToPt = Find3DRecoRange(slc, pfp, toPt, 3, 1);
1340  if (nextToPt > pfp.TP3Ds.size()) return false;
1341  return true;
1342  } // CanSection
unsigned short Find3DRecoRange(const TCSlice &slc, const PFPStruct &pfp, unsigned short fromPt, unsigned short min2DPts, short dir)
Definition: PFPUtils.cxx:1345
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:3329
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1060
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
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:3329
void UpdateTraj(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:705
std::vector< unsigned int > PutTrajHitsInVector(const Trajectory &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2688
std::vector< unsigned short > minPtsFit
Reconstruct in several passes.
Definition: DataStructs.h:558
TCConfig tcc
Definition: DataStructs.cxx:9
void PrintTrajectory(std::string someText, const TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:6032
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1060
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2513
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1791
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6344
unsigned short NumHitsInTP(const TrajPoint &tp, HitStatus_t hitRequest)
Definition: Utils.cxx:4196
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
float MaxHitDelta(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:3201
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:2071
unsigned short AngleRange(TrajPoint const &tp)
Definition: Utils.cxx:758
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:584
use the stiff electron strategy
Definition: DataStructs.h:494
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2071
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:3380
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void ChkStop(Trajectory &tj)
Definition: StepUtils.cxx:3972
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3329
std::vector< float > qualityCuts
Min points/wire, min consecutive pts after a gap.
Definition: DataStructs.h:556
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:1713
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
use the slowing-down strategy
Definition: DataStructs.h:496
std::vector< short > minMCSMom
Min MCSMom for each pass.
Definition: DataStructs.h:561
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:559
void TrimEndPts(std::string fcnLabel, TCSlice &slc, Trajectory &tj, const std::vector< float > &fQualityCuts, bool prt)
Definition: Utils.cxx:1575
void TagJunkTj(Trajectory &tj, bool prt)
Definition: Utils.cxx:2715
void TrimHiChgEndPts(TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:1533
use the stiff electron strategy
Definition: DataStructs.h:494
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2071
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:2744
void tca::CheckTrajBeginChg ( TCSlice slc,
unsigned short  itj 
)

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

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

Definition at line 1807 of file Utils.cxx.

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

1808  {
1809  // Returns the fraction of wires between tp.Pos[0] and toPos0 that have a hit
1810  // on the line defined by tp.Pos and tp.Dir
1811 
1812  if (tp.Pos[0] < -0.4 || toPos0 < -0.4) return 0;
1813  int fromWire = std::nearbyint(tp.Pos[0]);
1814  int toWire = std::nearbyint(toPos0);
1815 
1816  if (fromWire == toWire) return SignalAtTp(tp);
1817 
1818  int nWires = abs(toWire - fromWire) + 1;
1819 
1820  if (std::abs(tp.Dir[0]) < 0.001) tp.Dir[0] = 0.001;
1821  float stepSize = std::abs(1 / tp.Dir[0]);
1822  // ensure that we step in the right direction
1823  if (toWire > fromWire && tp.Dir[0] < 0) stepSize = -stepSize;
1824  if (toWire < fromWire && tp.Dir[0] > 0) stepSize = -stepSize;
1825  float nsig = 0;
1826  float num = 0;
1827  for (unsigned short cnt = 0; cnt < nWires; ++cnt) {
1828  ++num;
1829  if (SignalAtTp(tp)) ++nsig;
1830  tp.Pos[0] += tp.Dir[0] * stepSize;
1831  tp.Pos[1] += tp.Dir[1] * stepSize;
1832  } // cnt
1833  float sigFrac = nsig / num;
1834  return sigFrac;
1835  } // ChgFracBetween
bool SignalAtTp(TrajPoint &tp)
Definition: Utils.cxx:1963
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 3166 of file PFPUtils.cxx.

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

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

3170  {
3171  // Step between pos1 and pos2 and find the fraction of the points that have nearby hits
3172  // in each plane. This function returns -1 if something is fishy, but this doesn't mean
3173  // that there is no charge. Note that there is no check for charge precisely at the pos1 and pos2
3174  // positions
3175  float sep = PosSep(pos1, pos2);
3176  if (sep == 0) return -1;
3177  unsigned short nstep = sep / tcc.wirePitch;
3178  auto dir = PointDirection(pos1, pos2);
3179  float sum = 0;
3180  float cnt = 0;
3181  TrajPoint tp;
3182  for (unsigned short step = 0; step < nstep; ++step) {
3183  for (unsigned short xyz = 0; xyz < 3; ++xyz)
3184  pos1[xyz] += tcc.wirePitch * dir[xyz];
3185  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
3186  tp.CTP = EncodeCTP(slc.TPCID.Cryostat, slc.TPCID.TPC, plane);
3187  geo::PlaneID const planeID{slc.TPCID, plane};
3188  tp.Pos[0] = tcc.geom->WireCoordinate(geo::Point_t{0, pos1[1], pos1[2]}, planeID);
3189  tp.Pos[1] = detProp.ConvertXToTicks(pos1[0], plane, slc.TPCID.TPC, slc.TPCID.Cryostat) *
3190  tcc.unitsPerTick;
3191  ++cnt;
3192  if (SignalAtTp(tp)) ++sum;
3193  } // plane
3194  } // step
3195  if (cnt == 0) return -1;
3196  return sum / cnt;
3197  } // ChgFracBetween
Length_t WireCoordinate(Point_t const &pos, PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
bool SignalAtTp(TrajPoint &tp)
Definition: Utils.cxx:1963
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
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:564
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:2542
const geo::GeometryCore * geom
Definition: DataStructs.h:569
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:2558
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:51
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 3200 of file PFPUtils.cxx.

References ChgFracNearPos(), detinfo::DetectorPropertiesData::ConvertXToTicks(), geo::CryostatID::Cryostat, EncodeCTP(), tca::TCConfig::geom, tca::PFPStruct::ID, tca::TCSlice::nPlanes, tca::TCSlice::nWires, 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::GeometryCore::WireCoordinate(), and tca::TCSlice::wireHitRange.

Referenced by DotProd().

3204  {
3205  // returns the charge fraction near the end of the pfp. Note that this function
3206  // assumes that there is only one Tj in a plane.
3207  if (pfp.ID == 0) return 0;
3208  if (pfp.TjIDs.empty()) return 0;
3209  if (end > 1) return 0;
3210  if (pfp.TPCID != slc.TPCID) return 0;
3211  if (pfp.SectionFits.empty()) return 0;
3212 
3213  float sum = 0;
3214  float cnt = 0;
3215  // keep track of the lowest value and maybe reject it
3216  float lo = 1;
3217  float hi = 0;
3218  auto pos3 = PosAtEnd(pfp, end);
3219  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
3220  CTP_t inCTP = EncodeCTP(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
3221  std::vector<int> tjids(1);
3222  for (auto tjid : pfp.TjIDs) {
3223  auto& tj = slc.tjs[tjid - 1];
3224  if (tj.CTP != inCTP) continue;
3225  tjids[0] = tjid;
3226  Point2_t pos2;
3227  geo::PlaneID planeID = geo::PlaneID{pfp.TPCID, plane};
3228  pos2[0] = tcc.geom->WireCoordinate(geo::Point_t{0, pos3[1], pos3[2]}, planeID);
3229  if (pos2[0] < -0.4) continue;
3230  // check for dead wires
3231  unsigned int wire = std::nearbyint(pos2[0]);
3232  if (wire > slc.nWires[plane]) continue;
3233  if (slc.wireHitRange[plane][wire].first == UINT_MAX) continue;
3234  pos2[1] = detProp.ConvertXToTicks(pos3[0], planeID) * tcc.unitsPerTick;
3235  float cf = ChgFracNearPos(slc, pos2, tjids);
3236  if (cf < lo) lo = cf;
3237  if (cf > hi) hi = cf;
3238  sum += cf;
3239  ++cnt;
3240  } // tjid
3241  } // plane
3242  if (cnt == 0) return 0;
3243  if (cnt > 1 && lo < 0.3 && hi > 0.8) {
3244  sum -= lo;
3245  --cnt;
3246  }
3247  return sum / cnt;
3248  } // ChgFracNearEnd
Length_t WireCoordinate(Point_t const &pos, PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3259
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:43
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:564
float ChgFracNearPos(const TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3162
const geo::GeometryCore * geom
Definition: DataStructs.h:569
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:47
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:51
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 3162 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().

3163  {
3164  // returns the fraction of the charge in the region around pos that is associated with
3165  // the list of Tj IDs
3166  if (tjIDs.empty()) return 0;
3167  std::array<int, 2> wireWindow;
3168  Point2_t timeWindow;
3169  // 1/2 size of the region
3170  constexpr float NNDelta = 5;
3171  wireWindow[0] = pos[0] - NNDelta;
3172  wireWindow[1] = pos[0] + NNDelta;
3173  timeWindow[0] = pos[1] - NNDelta;
3174  timeWindow[1] = pos[1] + NNDelta;
3175  // do some checking
3176  for (auto& tjID : tjIDs)
3177  if (tjID <= 0 || tjID > (int)slc.tjs.size()) return 0;
3178  // Determine which plane we are in
3179  geo::PlaneID planeID = DecodeCTP(slc.tjs[tjIDs[0] - 1].CTP);
3180  // get a list of all hits in this region
3181  bool hitsNear;
3182  std::vector<unsigned int> closeHits =
3183  FindCloseHits(slc, wireWindow, timeWindow, planeID.Plane, kAllHits, true, hitsNear);
3184  if (closeHits.empty()) return 0;
3185  float chg = 0;
3186  float tchg = 0;
3187  // Add the hit charge in the box
3188  // All hits in the box, and all hits associated with the Tjs
3189  for (auto& iht : closeHits) {
3190  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
3191  chg += hit.Integral();
3192  if (slc.slHits[iht].InTraj == 0) continue;
3193  if (std::find(tjIDs.begin(), tjIDs.end(), slc.slHits[iht].InTraj) != tjIDs.end())
3194  tchg += hit.Integral();
3195  } // iht
3196  if (chg == 0) return 0;
3197  return tchg / chg;
3198  } // ChgFracNearPos
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
std::array< float, 2 > Point2_t
Definition: DataStructs.h:43
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
Detector simulation of raw signals on wires.
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:615
TCEvent evt
Definition: DataStructs.cxx:8
bool FindCloseHits(TCSlice const &slc, TrajPoint &tp, float const maxDelta, HitStatus_t hitRequest)
Definition: Utils.cxx:2836
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:3329
std::vector< float > qualityCuts
Min points/wire, min consecutive pts after a gap.
Definition: DataStructs.h:556
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1060
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6353
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:623
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:2773
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
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:1575
std::vector< float > chargeCuts
Definition: DataStructs.h:555
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:579
float VLAStepSize
Definition: DataStructs.h:577
geo::PlaneID DecodeCTP(CTP_t CTP)
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2071
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 1713 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().

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

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

1682  {
1683  // look for large-angle kink near the end
1684  if (!tcc.useAlg[kEndKink]) return;
1685  if (tj.PDGCode == 111) return;
1686  if (tj.EndPt[1] - tj.EndPt[0] < 6) return;
1687 
1688  if (prt) mf::LogVerbatim("TC") << "CEK: Inside ChkEndKinks T" << tj.ID << " ";
1689 
1690  float maxSig = tcc.kinkCuts[1];
1691  unsigned short withNptsFit = 0;
1692  unsigned short nPtsFit = tcc.kinkCuts[0];
1693  bool useChg = (tcc.kinkCuts[2] > 0);
1694  for (unsigned short nptsf = 3; nptsf < nPtsFit; ++nptsf) {
1695  unsigned short ipt = tj.EndPt[1] - nptsf;
1696  float ks = KinkSignificance(slc, tj, ipt, nptsf, useChg, prt);
1697  if (ks > maxSig) {
1698  maxSig = ks;
1699  withNptsFit = nptsf;
1700  }
1701  } // nptsf
1702  if (withNptsFit > 0) {
1703  unsigned short ipt = tj.EndPt[1] - withNptsFit;
1704  std::cout << "CEK: T" << tj.ID << " ipt " << ipt;
1705  float ks = KinkSignificance(slc, tj, ipt, withNptsFit, false, prt);
1706  auto& tp = tj.Pts[ipt];
1707  std::cout << " " << PrintPos(tp) << " withNptsFit " << withNptsFit << " ks " << ks << "\n";
1708  }
1709 
1710  } // ChkEndKink
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< float > kinkCuts
kink finder algorithm
Definition: DataStructs.h:552
float KinkSignificance(TCSlice const &slc, Trajectory &tj, unsigned short kinkPt, unsigned short nPtsFit, bool useChg, bool prt)
Definition: Utils.cxx:3040
TCConfig tcc
Definition: DataStructs.cxx:9
std::string PrintPos(const Point2_t &pos)
Definition: Utils.cxx:6359
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
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:584
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:580
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:584
std::array< float, 2 > Point2_t
Definition: DataStructs.h:43
bool Fit2D(short mode, Point2_t inPt, float &inPtErr, Vector2_t &outVec, Vector2_t &outVecErr, float &chiDOF)
Definition: Utils.cxx:4979
std::array< double, 2 > Vector2_t
Definition: DataStructs.h:44
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
TDirectory * dir
Definition: macro.C:5
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:580
use the stiff electron strategy
Definition: DataStructs.h:494
std::vector< float > chkStopCuts
Bragg peak finder configuration.
Definition: DataStructs.h:550
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:3329
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1060
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:6353
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
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:2773
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6344
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice const &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3576
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
geo::PlaneID DecodeCTP(CTP_t CTP)
use the stiff electron strategy
Definition: DataStructs.h:494
bool tca::ChkVtxAssociations ( TCSlice slc,
const CTP_t inCTP 
)

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

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

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

112  {
113  slc.crt.cr_origin.clear();
114  slc.crt.cr_pfpxmin.clear();
115  slc.crt.cr_pfpxmax.clear();
116  slc.crt.cr_pfpyzmindis.clear();
117  }
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:404
std::vector< int > IsShowerParent
Definition: DataStructs.h:397
std::vector< float > EndWir
Definition: DataStructs.h:384
std::vector< float > EndAng
Definition: DataStructs.h:386
std::vector< float > BeginTim
Definition: DataStructs.h:380
std::vector< float > BeginAng
Definition: DataStructs.h:381
std::vector< float > EndTim
Definition: DataStructs.h:385
std::vector< int > ShowerID
Definition: DataStructs.h:396
ShowerTreeVars stv
Definition: DataStructs.cxx:11
std::vector< int > TjID
Definition: DataStructs.h:394
std::vector< short > BeginVtx
Definition: DataStructs.h:383
std::vector< short > EndVtx
Definition: DataStructs.h:388
std::vector< float > Envelope
Definition: DataStructs.h:402
std::vector< float > BeginChg
Definition: DataStructs.h:382
std::vector< int > EnvPlane
Definition: DataStructs.h:403
std::vector< short > MCSMom
Definition: DataStructs.h:390
std::vector< int > StageNum
Definition: DataStructs.h:398
std::vector< float > BeginWir
Definition: DataStructs.h:379
std::vector< float > EndChg
Definition: DataStructs.h:387
std::vector< int > EnvShowerID
Definition: DataStructs.h:405
std::vector< int > IsShowerTj
Definition: DataStructs.h:395
std::vector< short > PlaneNum
Definition: DataStructs.h:392
unsigned short tca::CloseEnd ( const Trajectory tj,
const Point2_t pos 
)

Definition at line 2494 of file Utils.cxx.

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

Referenced by MakePFPTjs(), and MergeWithVertex().

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

Definition at line 576 of file Utils.cxx.

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

Referenced by EndMerge().

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

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

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

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

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

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

2370  {
2371 
2372  if (!tcc.useAlg[kComp3DVxIG]) return;
2373  if (slc.nPlanes != 3) return;
2374 
2375  bool prt = (tcc.modes[kDebug] && tcc.dbgSlc && tcc.dbgAlg[kComp3DVxIG]);
2376  if (prt) mf::LogVerbatim("TC") << "Inside CI3DVIG:";
2377 
2378  for (unsigned short iv3 = 0; iv3 < slc.vtx3s.size(); ++iv3) {
2379  Vtx3Store& vx3 = slc.vtx3s[iv3];
2380  // ignore obsolete vertices
2381  if (vx3.ID == 0) continue;
2382  // check for a completed 3D vertex
2383  if (vx3.Wire < 0) continue;
2384  unsigned short mPlane = USHRT_MAX;
2385  for (unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
2386  if (vx3.Vx2ID[ipl] > 0) continue;
2387  mPlane = ipl;
2388  break;
2389  } // ipl
2390  if (mPlane == USHRT_MAX) continue;
2391  CTP_t mCTP = EncodeCTP(vx3.TPCID.Cryostat, vx3.TPCID.TPC, mPlane);
2392  // require that the missing vertex be in a large block of dead wires
2393  float dwc = DeadWireCount(slc, vx3.Wire - 4, vx3.Wire + 4, mCTP);
2394  if (dwc < 5) continue;
2395  // X position of the purported missing vertex
2396  VtxStore aVtx;
2397  aVtx.ID = slc.vtxs.size() + 1;
2398  aVtx.Pos[0] = vx3.Wire;
2399  aVtx.Pos[1] = detProp.ConvertXToTicks(vx3.X, mPlane, vx3.TPCID.TPC, vx3.TPCID.Cryostat) *
2400  tcc.unitsPerTick;
2401  aVtx.CTP = mCTP;
2402  aVtx.Topo = 4;
2403  aVtx.NTraj = 0;
2404  // Give it a bogus pass to indicate it wasn't created while stepping
2405  aVtx.Pass = 9;
2406  if (prt)
2407  mf::LogVerbatim("TC") << "CI3DVIG: Incomplete vertex " << iv3 << " in plane " << mPlane
2408  << " wire " << vx3.Wire << " Made 2D vertex ";
2409  std::vector<int> tjIDs;
2410  std::vector<unsigned short> tjEnds;
2411  for (unsigned short itj = 0; itj < slc.tjs.size(); ++itj) {
2412  if (slc.tjs[itj].CTP != mCTP) continue;
2413  if (slc.tjs[itj].AlgMod[kKilled] || slc.tjs[itj].AlgMod[kHaloTj]) continue;
2414  for (unsigned short end = 0; end < 2; ++end) {
2415  unsigned short ept = slc.tjs[itj].EndPt[end];
2416  TrajPoint& tp = slc.tjs[itj].Pts[ept];
2417  unsigned short oept = slc.tjs[itj].EndPt[1 - end];
2418  TrajPoint& otp = slc.tjs[itj].Pts[oept];
2419  // ensure that this is the end closest to the vertex
2420  if (std::abs(tp.Pos[0] - aVtx.Pos[0]) > std::abs(otp.Pos[0] - aVtx.Pos[0])) continue;
2421  float doca = PointTrajDOCA(aVtx.Pos[0], aVtx.Pos[1], tp);
2422  if (doca > 2) continue;
2423  float dwc = DeadWireCount(slc, aVtx.Pos[0], tp.Pos[0], tp.CTP);
2424  float ptSep;
2425  if (aVtx.Pos[0] > tp.Pos[0]) { ptSep = aVtx.Pos[0] - tp.Pos[0] - dwc; }
2426  else {
2427  ptSep = tp.Pos[0] - aVtx.Pos[0] - dwc;
2428  }
2429  if (prt)
2430  mf::LogVerbatim("TC") << "CI3DVIG: tj ID " << slc.tjs[itj].ID << " doca " << doca
2431  << " ptSep " << ptSep;
2432  if (ptSep < -2 || ptSep > 2) continue;
2433  // don't clobber an existing association
2434  if (slc.tjs[itj].VtxID[end] > 0) continue;
2435  tjIDs.push_back(slc.tjs[itj].ID);
2436  tjEnds.push_back(end);
2437  } // end
2438  } // itj
2439  if (!tjIDs.empty()) {
2440  // Determine how messy this region is
2441  aVtx.TjChgFrac = ChgFracNearPos(slc, aVtx.Pos, tjIDs);
2442  if (aVtx.TjChgFrac < 0.7) continue;
2443  aVtx.Vx3ID = vx3.ID;
2444  // Save the 2D vertex
2445  if (!StoreVertex(slc, aVtx)) continue;
2446  for (unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2447  unsigned short itj = tjIDs[ii] - 1;
2448  slc.tjs[itj].VtxID[tjEnds[ii]] = aVtx.ID;
2449  slc.tjs[itj].AlgMod[kComp3DVxIG] = true;
2450  } // ii
2451  SetVx2Score(slc);
2452  vx3.Vx2ID[mPlane] = aVtx.ID;
2453  vx3.Wire = -1;
2454  if (prt)
2455  mf::LogVerbatim("TC") << "CI3DVIG: new vtx 2V" << aVtx.ID << " points to 3V" << vx3.ID;
2456  }
2457  } // vx3
2458 
2459  } // 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:2513
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:583
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:1900
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:564
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2094
float ChgFracNearPos(const TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3162
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:600
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2247
unsigned int CTP_t
Definition: DataStructs.h:47
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:580
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:51
master switch for turning on debug mode
Definition: DataStructs.h:526
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:463
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:481
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:4701
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
geo::PlaneID DecodeCTP(CTP_t CTP)
void tca::ConfigureMVA ( TCConfig tcc,
std::string  fMVAShowerParentWeights 
)

Definition at line 34 of file TCShower.cxx.

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

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

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

Definition at line 1297 of file PFPUtils.cxx.

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

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

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

2806  {
2807  // The calling function should define the size of pfp.TjIDs
2808  PFPStruct pfp;
2809  pfp.ID = slc.pfps.size() + 1;
2810  pfp.ParentUID = 0;
2811  pfp.TPCID = slc.TPCID;
2812  // initialize arrays for both ends
2813  if (slc.nPlanes < 4) {
2814  pfp.dEdx[0].resize(slc.nPlanes, -1);
2815  pfp.dEdx[1].resize(slc.nPlanes, -1);
2816  pfp.dEdxErr[0].resize(slc.nPlanes, -1);
2817  pfp.dEdxErr[1].resize(slc.nPlanes, -1);
2818  }
2819  // create a single section fit to hold the start/end positions and direction
2820  pfp.SectionFits.resize(1);
2821  return pfp;
2822  } // 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 2710 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().

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

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

Definition at line 2100 of file Utils.cxx.

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

2104  {
2105  if (inWirePos1 < -0.4 || inWirePos2 < -0.4) return 0;
2106  unsigned int inWire1 = std::nearbyint(inWirePos1);
2107  unsigned int inWire2 = std::nearbyint(inWirePos2);
2108  geo::PlaneID planeID = DecodeCTP(tCTP);
2109  unsigned short plane = planeID.Plane;
2110  if (inWire1 > slc.nWires[plane] || inWire2 > slc.nWires[plane]) return 0;
2111  if (inWire1 > inWire2) {
2112  // put in increasing order
2113  unsigned int tmp = inWire1;
2114  inWire1 = inWire2;
2115  inWire2 = tmp;
2116  } // inWire1 > inWire2
2117  ++inWire2;
2118  unsigned int wire, ndead = 0;
2119  for (wire = inWire1; wire < inWire2; ++wire)
2120  if (!evt.goodWire[plane][wire]) ++ndead;
2121  return ndead;
2122  } // DeadWireCount
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
Float_t tmp
Definition: plot.C:35
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:623
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
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:48
constexpr unsigned int Cpad
Definition: DataStructs.h:49
bool tca::DecodeDebugString ( std::string  strng)

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

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

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

2679  {
2680  if (!tp3d.Flags[kTP3DGood]) return 0;
2681  if (tp3d.TjID > (int)slc.slHits.size()) return 0;
2682  if (tp3d.TjID <= 0) return 0;
2683 
2684  auto& tp = slc.tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
2685  if (tp.Environment[kEnvOverlap]) return 0;
2686 
2687  double dQ = 0.;
2688  double time = 0;
2689  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2690  if (!tp.UseHit[ii]) continue;
2691  auto& hit = (*evt.allHits)[slc.slHits[tp.Hits[ii]].allHitsIndex];
2692  dQ += hit.Integral();
2693  } // ii
2694  time = tp.Pos[1] / tcc.unitsPerTick;
2695  geo::PlaneID plnID = DecodeCTP(tp.CTP);
2696  if (dQ == 0) return 0;
2697  double angleToVert = tcc.geom->Plane(plnID).ThetaZ() - 0.5 * ::util::pi<>();
2698  double cosgamma =
2699  std::abs(std::sin(angleToVert) * tp3d.Dir[1] + std::cos(angleToVert) * tp3d.Dir[2]);
2700  if (cosgamma < 1.E-5) return 0;
2701  double dx = tcc.geom->WirePitch(plnID) / cosgamma;
2702  double dQdx = dQ / dx;
2703  double t0 = 0;
2704  float dedx = tcc.caloAlg->dEdx_AREA(clockData, detProp, dQdx, time, plnID.Plane, t0);
2705  if (std::isinf(dedx)) dedx = 0;
2706  return dedx;
2707  } // dEdx
calo::CalorimetryAlg * caloAlg
Definition: DataStructs.h:570
code to link reconstructed objects back to the MC truth information
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
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:646
PlaneGeo const & Plane(PlaneID const &planeid) const
Returns the specified wire.
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:564
Float_t E
Definition: plot.C:20
const geo::GeometryCore * geom
Definition: DataStructs.h:569
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
Detector simulation of raw signals on wires.
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:615
double dEdx_AREA(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop, recob::Hit const &hit, double pitch, double T0=0) const
TCEvent evt
Definition: DataStructs.cxx:8
Length_t WirePitch(PlaneID const &planeid=plane_zero) const
Returns the distance between two consecutive wires.
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:551
if(nlines<=0)
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:564
Float_t sn
Definition: plot.C:23
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2558
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:4315
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:584
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:564
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:615
TCEvent evt
Definition: DataStructs.cxx:8
void tca::DefinePFPParents ( TCSlice slc)

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

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

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

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

Definition at line 2535 of file PFPUtils.cxx.

References DotProd().

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

2536  {
2537  if (v1[0] == v2[0] && v1[1] == v2[1] && v1[2] == v2[2]) return 0;
2538  return acos(DotProd(v1, v2));
2539  }
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 3302 of file Utils.cxx.

References DeltaAngle2().

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

Definition at line 3323 of file Utils.cxx.

References util::abs().

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

Definition at line 3311 of file Utils.cxx.

Referenced by DeltaAngle(), and DotProd().

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

Definition at line 3251 of file PFPUtils.cxx.

References tca::PFPStruct::SectionFits.

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

3252  {
3253  if (end > 1 || pfp.SectionFits.empty()) return {{0., 0., 0.}};
3254  if (end == 0) return pfp.SectionFits[0].Dir;
3255  return pfp.SectionFits[pfp.SectionFits.size() - 1].Dir;
3256  } // 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 5248 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().

5249  {
5250  // Dump all of the points in a trajectory to the output in a form that can
5251  // be imported by another application, e.g. Excel
5252  // Search for the trajectory with the specified WorkID or Unique ID
5253 
5254  for (auto const& slc : slices) {
5255  for (auto& tj : slc.tjs) {
5256  if (tj.WorkID != debug.WorkID && tj.UID != debug.WorkID) continue;
5257  // print a header
5258  std::ofstream outfile;
5259  std::string fname = "tcdump" + std::to_string(tj.UID) + ".csv";
5260  outfile.open(fname, std::ios::out | std::ios::trunc);
5261  outfile << "Dump trajectory T" << tj.UID << " WorkID " << tj.WorkID;
5262  outfile << " ChgRMS " << std::setprecision(2) << tj.ChgRMS;
5263  outfile << "\n";
5264  outfile << "Wire, Chg T" << tj.UID
5265  << ", totChg, Tick, Delta, NTPsFit, Ang, ChiDOF, KinkSig, HitPosErr\n";
5266  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
5267  auto& tp = tj.Pts[ipt];
5268  outfile << std::fixed;
5269  outfile << std::setprecision(0) << std::nearbyint(tp.Pos[0]);
5270  outfile << "," << (int)tp.Chg;
5271  // total charge near the TP
5272  float totChg = 0;
5273  for (auto iht : tp.Hits) {
5274  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
5275  totChg += hit.Integral();
5276  }
5277  outfile << "," << (int)totChg;
5278  outfile << "," << std::setprecision(0) << std::nearbyint(tp.Pos[1] / tcc.unitsPerTick);
5279  outfile << "," << std::setprecision(2) << tp.Delta;
5280  outfile << "," << tp.NTPsFit;
5281  outfile << "," << std::setprecision(3) << tp.Ang;
5282  outfile << "," << std::setprecision(2) << tp.FitChi;
5283  outfile << "," << std::setprecision(2) << tp.KinkSig;
5284  outfile << "," << std::setprecision(2) << sqrt(tp.HitPosErr2);
5285  outfile << "\n";
5286  } // ipt
5287  outfile.close();
5288  std::cout << "Points on T" << tj.UID << " dumped to " << fname << "\n";
5289  tcc.dbgDump = false;
5290  return;
5291  } // tj
5292  } // slc
5293 
5294  } // 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:564
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:615
TCEvent evt
Definition: DataStructs.cxx:8
float tca::ElectronLikelihood ( const TCSlice slc,
const Trajectory tj 
)

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

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

Definition at line 55 of file DataStructs.h.

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

56  {
57  return EncodeCTP(planeID.Cryostat, planeID.TPC, planeID.Plane);
58  }
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:211
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
CTP_t EncodeCTP(const geo::WireID &wireID)
Definition: DataStructs.h:59
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:399
CTP_t tca::EncodeCTP ( const geo::WireID wireID)
inline

Definition at line 59 of file DataStructs.h.

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

Referenced by EncodeCTP().

60  {
61  return EncodeCTP(wireID.Cryostat, wireID.TPC, wireID.Plane);
62  }
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:211
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
CTP_t EncodeCTP(const geo::WireID &wireID)
Definition: DataStructs.h:59
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:399
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:797
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:2690
std::vector< float > kinkCuts
kink finder algorithm
Definition: DataStructs.h:552
bool FitVertex(TCSlice &slc, VtxStore &vx, bool prt)
Definition: TCVertex.cxx:1935
std::vector< float > qualityCuts
Min points/wire, min consecutive pts after a gap.
Definition: DataStructs.h:556
TCConfig tcc
Definition: DataStructs.cxx:9
vertex position fixed manually - no fitting done
Definition: DataStructs.h:90
step from US -> DS (true) or DS -> US (false)
Definition: DataStructs.h:524
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:576
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2513
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:2535
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:583
bool MakeBareTrajPoint(const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:4006
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6353
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:1900
bool SignalBetween(const TrajPoint &tp1, const TrajPoint &tp2, const float MinWireSignalFraction)
Definition: Utils.cxx:1778
float OverlapFraction(const Trajectory &tj1, const Trajectory &tj2)
Definition: Utils.cxx:706
TText * pt2
Definition: plot.C:64
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:564
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2094
DebugStuff debug
Definition: DebugStruct.cxx:4
float ChgFracNearPos(const TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3162
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2564
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:600
std::vector< float > chargeCuts
Definition: DataStructs.h:555
bool MergeAndStore(TCSlice &slc, unsigned int itj1, unsigned int itj2, bool doPrt)
Definition: Utils.cxx:4518
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
Definition: Utils.cxx:2542
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:2985
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
float TrajLength(const Trajectory &tj)
Definition: Utils.cxx:2581
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2558
void SetVx2Score(TCSlice &slc)
Definition: TCVertex.cxx:2238
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:543
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2071
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:2406
CTP_t CTP
set to an invalid CTP
Definition: DebugStruct.h:23
void ReverseTraj(Trajectory &tj)
Definition: Utils.cxx:3218
float tca::ExpectedHitsRMS ( const TrajPoint tp)

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

1911  {
1912  // returns the expected RMS of hits for the trajectory point in ticks
1913  if (std::abs(tp.Dir[0]) > 0.001) {
1914  geo::PlaneID planeID = DecodeCTP(tp.CTP);
1915  return 1.5 * evt.aveHitRMS[planeID.Plane] +
1916  2 * std::abs(tp.Dir[1] / tp.Dir[0]) / tcc.unitsPerTick;
1917  }
1918  return 500;
1919  } // ExpectedHitsRMS
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
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:564
std::vector< float > aveHitRMS
average RMS of an isolated hit
Definition: DataStructs.h:631
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
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 3302 of file PFPUtils.cxx.

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

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

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

Definition at line 4067 of file Utils.cxx.

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

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

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

2591  {
2592  // Fills dE/dx variables in the pfp struct
2593 
2594  // don't attempt to find dE/dx at the end of a shower
2595  unsigned short numEnds = 2;
2596  if (pfp.PDGCode == 1111) numEnds = 1;
2597 
2598  // set dE/dx to 0 to indicate that a valid dE/dx is expected
2599  for (unsigned short end = 0; end < numEnds; ++end) {
2600  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane)
2601  pfp.dEdx[end][plane] = 0;
2602  } // end
2603 
2604  // square of the maximum length that is used for finding the average dE/dx
2605  float maxSep2 = 5 * tcc.wirePitch;
2606  maxSep2 *= maxSep2;
2607 
2608  for (unsigned short end = 0; end < numEnds; ++end) {
2609  std::vector<float> cnt(slc.nPlanes);
2610  short dir = 1 - 2 * end;
2611  auto endPos = PosAtEnd(pfp, end);
2612  for (std::size_t ii = 0; ii < pfp.TP3Ds.size(); ++ii) {
2613  unsigned short ipt;
2614  if (dir > 0) { ipt = ii; }
2615  else {
2616  ipt = pfp.TP3Ds.size() - ii - 1;
2617  }
2618  if (ipt >= pfp.TP3Ds.size()) break;
2619  auto& tp3d = pfp.TP3Ds[ipt];
2620  if (tp3d.Flags[kTP3DBad]) continue;
2621  if (PosSep2(tp3d.Pos, endPos) > maxSep2) break;
2622  // require good points
2623  if (!tp3d.Flags[kTP3DGood]) continue;
2624  float dedx = dEdx(clockData, detProp, slc, tp3d);
2625  if (dedx < 0.5) continue;
2626  unsigned short plane = DecodeCTP(tp3d.CTP).Plane;
2627  pfp.dEdx[end][plane] += dedx;
2628  ++cnt[plane];
2629  } // ii
2630  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
2631  if (cnt[plane] == 0) continue;
2632  pfp.dEdx[end][plane] /= cnt[plane];
2633  } // plane
2634  } // end
2635 
2636  } // FilldEdx
TCConfig tcc
Definition: DataStructs.cxx:9
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3259
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:2564
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
float dEdx(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, TP3D &tp3d)
Definition: PFPUtils.cxx:2675
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:3380
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:6131
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1060
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2513
bool MakeBareTrajPoint(const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:4006
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6353
if(nlines<=0)
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1791
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6344
Detector simulation of raw signals on wires.
std::vector< float > chargeCuts
Definition: DataStructs.h:555
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
float MaxHitDelta(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:3201
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:615
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2071
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 1726 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().

1731  {
1732  // Look for gaps in each plane in the TP3Ds vector in planes in which
1733  // the projection of the pfp angle is large (~> 60 degrees). Hits
1734  // reconstructed at large angles are poorly reconstructed which results
1735  // in poorly reconstructed 2D trajectories
1736 
1737  if (pfp.ID <= 0) return;
1738  if (pfp.TP3Ds.empty()) return;
1739  if (pfp.SectionFits.empty()) return;
1740  if (!tcc.useAlg[kFillGaps3D]) return;
1741  if (pfp.Flags[kJunk3D]) return;
1742  if (pfp.Flags[kSmallAngle]) return;
1743 
1744  // Only print APIR details if MVI is set
1745  bool foundMVI = (tcc.dbgPFP && pfp.MVI == debug.MVI);
1746 
1747  // make a copy in case something goes wrong
1748  auto pWork = pfp;
1749 
1750  unsigned short nPtsAdded = 0;
1751  unsigned short fromPt = 0;
1752  unsigned short toPt = pWork.TP3Ds.size();
1753  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
1754  CTP_t inCTP = EncodeCTP(pWork.TPCID.Cryostat, pWork.TPCID.TPC, plane);
1755  unsigned short nWires, nAdd;
1756  AddPointsInRange(clockData,
1757  detProp,
1758  slc,
1759  pWork,
1760  fromPt,
1761  toPt,
1762  inCTP,
1763  tcc.match3DCuts[4],
1764  nWires,
1765  nAdd,
1766  foundMVI);
1767  if (pWork.Flags[kNeedsUpdate]) Update(detProp, slc, pWork);
1768  nPtsAdded += nAdd;
1769  } // plane
1770  if (prt) mf::LogVerbatim("TC") << "FG3D P" << pWork.ID << " added " << nPtsAdded << " points";
1771  if (pWork.Flags[kNeedsUpdate] && !Update(detProp, slc, pWork)) return;
1772  pfp = pWork;
1773  return;
1774  } // 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:1055
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:1817
DebugStuff debug
Definition: DebugStruct.cxx:4
std::vector< float > match3DCuts
3D matching cuts
Definition: DataStructs.h:553
unsigned int CTP_t
Definition: DataStructs.h:47
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:51
void tca::FillmAllTraj ( detinfo::DetectorPropertiesData const &  detProp,
TCSlice slc 
)

Definition at line 2375 of file PFPUtils.cxx.

References detinfo::DetectorPropertiesData::ConvertTicksToX(), geo::CryostatID::Cryostat, DecodeCTP(), tca::TCConfig::geom, geo::GeometryCore::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::Tj2Pt::xhi, and tca::Tj2Pt::xlo.

Referenced by FindPFParticles().

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

Definition at line 4323 of file Utils.cxx.

References tca::TCEvent::allHits, evt, tca::TCEvent::expectSlicedHits, tca::TCConfig::geom, tca::TCEvent::goodWire, geo::GeometryCore::Iterate(), kDebug, tca::TCConfig::modes, geo::GeometryCore::Nplanes(), geo::GeometryCore::Nwires(), geo::GeometryCore::PlaneWireToChannel(), util::size(), tcc, tca::TCEvent::TPCID, tca::TCConfig::useChannelStatus, and tca::TCEvent::wireHitRange.

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

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

Definition at line 4395 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::TPCGeo::Nplanes(), tca::TCSlice::nPlanes, detinfo::DetectorPropertiesData::NumberTimeSamples(), tca::TCSlice::nWires, geo::GeometryCore::Nwires(), geo::GeometryCore::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::GeometryCore::View(), tca::TCSlice::wireHitRange, tca::TCConfig::wirePitch, geo::GeometryCore::WirePitch(), tca::TCSlice::xHi, tca::TCSlice::xLo, tca::TCSlice::yHi, tca::TCSlice::yLo, tca::TCSlice::zHi, and tca::TCSlice::zLo.

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

Definition at line 606 of file PFPUtils.cxx.

References geo::CryostatID::Cryostat, tca::TCWireIntersection::dydw1, tca::TCWireIntersection::dydw2, tca::TCWireIntersection::dzdw1, tca::TCWireIntersection::dzdw2, evt, tca::TCConfig::geom, geo::GeometryCore::IntersectionPoint(), 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, tca::TCEvent::wireIntersections, tca::TCWireIntersection::y, and tca::TCWireIntersection::z.

Referenced by FindPFParticles().

607  {
608  // Find wire intersections and put them in evt.wireIntersections
609 
610  // see if anything needs to be done
611  if (!evt.wireIntersections.empty() && evt.wireIntersections[0].tpc == slc.TPCID.TPC) return;
612 
613  evt.wireIntersections.clear();
614 
615  unsigned int cstat = slc.TPCID.Cryostat;
616  unsigned int tpc = slc.TPCID.TPC;
617  // find the minMax number of wires in each plane of the TPC
618  unsigned int maxWire = slc.nWires[0];
619  for (auto nw : slc.nWires)
620  if (nw < maxWire) maxWire = nw;
621  // Start looking for intersections in the middle
622  unsigned int firstWire = maxWire / 2;
623 
624  // find a valid wire intersection in all plane combinations
625  std::vector<std::pair<unsigned short, unsigned short>> pln1pln2;
626  for (unsigned short pln1 = 0; pln1 < slc.nPlanes - 1; ++pln1) {
627  for (unsigned short pln2 = pln1 + 1; pln2 < slc.nPlanes; ++pln2) {
628  auto p1p2 = std::make_pair(pln1, pln2);
629  if (std::find(pln1pln2.begin(), pln1pln2.end(), p1p2) != pln1pln2.end()) continue;
630  // find two wires that have a valid intersection
631  for (unsigned int wire = firstWire; wire < maxWire; ++wire) {
632  double y00, z00;
633  if (!tcc.geom->IntersectionPoint(
634  geo::WireID{cstat, tpc, pln1, wire}, geo::WireID{cstat, tpc, pln2, wire}, y00, z00))
635  continue;
636  // increment by one wire in pln1 and find another valid intersection
637  double y10, z10;
638  if (!tcc.geom->IntersectionPoint(geo::WireID{cstat, tpc, pln1, wire + 10},
639  geo::WireID{cstat, tpc, pln2, wire},
640  y10,
641  z10))
642  continue;
643  // increment by one wire in pln2 and find another valid intersection
644  double y01, z01;
645  if (!tcc.geom->IntersectionPoint(geo::WireID{cstat, tpc, pln1, wire},
646  geo::WireID{cstat, tpc, pln2, wire + 10},
647  y01,
648  z01))
649  continue;
650  TCWireIntersection tcwi;
651  tcwi.tpc = tpc;
652  tcwi.pln1 = pln1;
653  tcwi.pln2 = pln2;
654  tcwi.wir1 = wire;
655  tcwi.wir2 = wire;
656  tcwi.y = y00;
657  tcwi.z = z00;
658  tcwi.dydw1 = (y10 - y00) / 10;
659  tcwi.dzdw1 = (z10 - z00) / 10;
660  tcwi.dydw2 = (y01 - y00) / 10;
661  tcwi.dzdw2 = (z01 - z00) / 10;
662  evt.wireIntersections.push_back(tcwi);
663  break;
664  } // wire
665  } // pln2
666  } // pln1
667  } // FillWireIntersections
TCConfig tcc
Definition: DataStructs.cxx:9
const geo::GeometryCore * geom
Definition: DataStructs.h:569
std::vector< TCWireIntersection > wireIntersections
Definition: DataStructs.h:632
bool IntersectionPoint(WireID const &wid1, WireID const &wid2, double &y, double &z) const
Returns the intersection point of two wires.
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 130 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().

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

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

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

Definition at line 1257 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::TCConfig::geom, tca::TCEvent::global3V_UID, tca::Vtx3Store::ID, tca::detail::SortEntry::index, geo::GeometryCore::IntersectionPoint(), kAllHits, kHaloTj, kKilled, kTjHiVx3Score, evd::kWire, geo::kX, tca::TCSlice::nPlanes, 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::GeometryCore::WireCoordinate(), tca::TCConfig::wirePitch, tca::Vtx3Store::X, tca::Vtx3Store::XErr, y, tca::Vtx3Store::Y, tca::Vtx3Store::YErr, tca::TCSlice::yHi, tca::Vtx3Store::Z, z, tca::Vtx3Store::ZErr, and tca::TCSlice::zHi.

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

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

Definition at line 3069 of file PFPUtils.cxx.

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

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

3070  {
3071  // Calculate the distance along and transvers to the direction vector from pos1 to pos2
3072  alongTrans[0] = 0;
3073  alongTrans[1] = 0;
3074  if (pos1[0] == pos2[0] && pos1[1] == pos2[1] && pos1[2] == pos2[2]) return;
3075  auto ptDir = PointDirection(pos1, pos2);
3076  SetMag(dir1, 1.0);
3077  double costh = DotProd(dir1, ptDir);
3078  if (costh > 1) costh = 1;
3079  double sep = PosSep(pos1, pos2);
3080  alongTrans[0] = costh * sep;
3081  double sinth = sqrt(1 - costh * costh);
3082  alongTrans[1] = sinth * sep;
3083  } // FindAlongTrans
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:2542
bool SetMag(Vector3_t &v1, double mag)
Definition: PFPUtils.cxx:2574
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:2558
void tca::FindAlongTrans ( Point2_t  pos1,
Vector2_t  dir1,
Point2_t  pos2,
Point2_t alongTrans 
)

Definition at line 3280 of file Utils.cxx.

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

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

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

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

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

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

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

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

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

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

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

Definition at line 285 of file TCShower.cxx.

References AddTjsInsideEnvelope(), ChkAssns(), tca::TCSlice::cots, CreateSS(), geo::CryostatID::Cryostat, tca::DebugStuff::CTP, tca::TCConfig::dbg2S, tca::TCConfig::dbg3S, tca::TCConfig::dbgSlc, debug, EncodeCTP(), FindNearbyTjs(), FindParent(), tca::TCConfig::geom, kSaveShowerTree, MakeShowerObsolete(), MergeNearby2DShowers(), MergeOverlap(), MergeShowerChain(), MergeSubShowers(), MergeSubShowersTj(), tca::TCConfig::modes, geo::TPCGeo::Nplanes(), tca::TCSlice::nPlanes, Print2DShowers(), PrintAllTraj(), PrintPFPs(), Reconcile3D(), SaveAllCots(), SaveTjInfo(), ShowerEnergy(), tca::TCSlice::showers, tca::TCConfig::showerTag, StoreShower(), tcc, geo::TPCID::TPC, geo::GeometryCore::TPC(), tca::TCSlice::TPCID, and UpdateShower().

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

286  {
287  // Find 2D showers using 3D-matched trajectories. This returns true if showers were found
288  // which requires re-doing the 3D trajectory match
289 
290  bool reconstruct = (tcc.showerTag[0] == 2) || (tcc.showerTag[0] == 4);
291  if (!reconstruct) return false;
292 
293  bool prt2S = (tcc.dbgSlc && tcc.dbg2S);
294  bool prt3S = (tcc.dbgSlc && tcc.dbg3S);
295 
296  std::string fcnLabel = "FS";
297 
298  geo::TPCGeo const& TPC = tcc.geom->TPC(slc.TPCID);
299  // check for already-existing showers
300  for (unsigned short plane = 0; plane < TPC.Nplanes(); ++plane) {
301  CTP_t inCTP = EncodeCTP(slc.TPCID.Cryostat, slc.TPCID.TPC, 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 (unsigned short plane = 0; plane < TPC.Nplanes(); ++plane) {
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[plane] = tjList;
320  } // plane
321  unsigned short nPlanesWithShowers = 0;
322  for (unsigned short plane = 0; plane < TPC.Nplanes(); ++plane)
323  if (!bigList.empty()) ++nPlanesWithShowers;
324  if (nPlanesWithShowers < 2) return false;
325  for (unsigned short plane = 0; plane < TPC.Nplanes(); ++plane) {
326  CTP_t inCTP = EncodeCTP(slc.TPCID.Cryostat, slc.TPCID.TPC, 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[plane]) {
331  if (tjl.empty()) continue;
332  if (prtCTP) {
333  mf::LogVerbatim myprt("TC");
334  myprt << "Plane " << 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
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4095
TCConfig tcc
Definition: DataStructs.cxx:9
unsigned int Nplanes() const
Number of planes in this tpc.
Definition: TPCGeo.h:137
Geometry information for a single TPC.
Definition: TPCGeo.h:36
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:583
void PrintPFPs(std::string someText, TCSlice const &slc)
Definition: Utils.cxx:6276
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:551
TPCGeo const & TPC(TPCID const &tpcid=tpc_zero) const
Returns the specified TPC.
Definition: GeometryCore.h:722
save shower tree
Definition: DataStructs.h:533
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
const geo::GeometryCore * geom
Definition: DataStructs.h:569
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
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:600
unsigned int CTP_t
Definition: DataStructs.h:47
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:51
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:5790
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 60 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.

64  {
65  // The shower ChgPos and Dir were found by the calling function but Dir
66  // may be inconsistent with the 2D shower directions
67  if (ss3.ID == 0) return false;
68 
69  if (prt) {
70  mf::LogVerbatim myprt("TC");
71  myprt << "Inside FSS: 3S" << ss3.ID << " ->";
72  for (auto cid : ss3.CotIDs)
73  myprt << " 2S" << cid;
74  myprt << " Vx 3V" << ss3.Vx3ID;
75  } // prt
76 
77  // find a parent Tj in the list of 2D showers that is the farthest away from the
78  // shower center
79  unsigned short useParentCID = 0;
80  float maxParentSep = 0;
81  unsigned short usePtSepCID = 0;
82  float maxPtSep = 0;
83  // assume that the 2D shower direction is consistent with the 3D shower direction. This
84  // variable is only used when no parent exists
85  bool dirOK = true;
86  for (auto cid : ss3.CotIDs) {
87  auto& ss = slc.cots[cid - 1];
88  // Find the position, direction and projection in this plane
89  auto& stj = slc.tjs[ss.ShowerTjID - 1];
90  auto chgCtrTP = MakeBareTP(detProp, ss3.ChgPos, ss3.Dir, stj.CTP);
91  // projection too small in this view?
92  if (chgCtrTP.Delta < 0.5) continue;
93  auto& startTP = stj.Pts[0];
94  float sep = PosSep(startTP.Pos, chgCtrTP.Pos);
95  if (ss.ParentID > 0) {
96  if (sep > maxParentSep) {
97  maxParentSep = sep;
98  useParentCID = cid;
99  }
100  }
101  else if (sep > maxPtSep) {
102  // no parent exists.
103  maxPtSep = sep;
104  usePtSepCID = cid;
105  float costh = DotProd(chgCtrTP.Dir, startTP.Dir);
106  if (costh < 0) dirOK = false;
107  }
108  } // ci
109  if (useParentCID == 0 && usePtSepCID == 0) return false;
110 
111  unsigned short useCID = useParentCID;
112  if (useCID == 0) {
113  useCID = usePtSepCID;
114  if (!dirOK) ReverseShower("FSS", slc, useCID, prt);
115  }
116 
117  // now define the start and length
118  auto& ss = slc.cots[useCID - 1];
119  auto& stj = slc.tjs[ss.ShowerTjID - 1];
120 
121  auto chgCtrTP = MakeBareTP(detProp, ss3.ChgPos, ss3.Dir, stj.CTP);
122  if (ss3.Vx3ID > 0) {
123  auto& vx3 = slc.vtx3s[ss3.Vx3ID - 1];
124  ss3.Start[0] = vx3.X;
125  ss3.Start[1] = vx3.Y;
126  ss3.Start[2] = vx3.Z;
127  }
128  else {
129  // no start vertex
130  auto& startTP = stj.Pts[0];
131  // The 2D separation btw the shower start and the shower center, converted
132  // to the 3D separation
133  float sep = tcc.wirePitch * PosSep(startTP.Pos, stj.Pts[1].Pos) / chgCtrTP.Delta;
134  // set the start position
135  for (unsigned short xyz = 0; xyz < 3; ++xyz)
136  ss3.Start[xyz] = ss3.ChgPos[xyz] - sep * ss3.Dir[xyz];
137  }
138  // now do the end position
139  auto& endTP = stj.Pts[2];
140  float sep = tcc.wirePitch * PosSep(endTP.Pos, chgCtrTP.Pos) / chgCtrTP.Delta;
141  for (unsigned short xyz = 0; xyz < 3; ++xyz)
142  ss3.End[xyz] = ss3.ChgPos[xyz] + sep * ss3.Dir[xyz];
143  ss3.Len = PosSep(ss3.Start, ss3.End);
144  auto& startTP = stj.Pts[0];
145  sep = PosSep(startTP.Pos, endTP.Pos);
146  ss3.OpenAngle = (endTP.DeltaRMS - startTP.DeltaRMS) / sep;
147  ss3.OpenAngle /= chgCtrTP.Delta;
148  return true;
149 
150  } // 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:3927
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:2558
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:551
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:2513
bool LongPulseHit(const recob::Hit &hit)
Definition: Utils.cxx:4315
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:4131
if(nlines<=0)
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:564
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:6344
float ExpectedHitsRMS(const TrajPoint &tp)
Definition: Utils.cxx:1910
Detector simulation of raw signals on wires.
std::vector< float > chargeCuts
Definition: DataStructs.h:555
art::PtrVector< recob::Hit > Hits
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:615
use the stiff electron strategy
Definition: DataStructs.h:494
TCEvent evt
Definition: DataStructs.cxx:8
float TPHitsRMSTick(const TCSlice &slc, const TrajPoint &tp, HitStatus_t hitRequest)
Definition: Utils.cxx:4096
void tca::Finish3DShowers ( TCSlice slc)

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

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

Definition at line 4979 of file Utils.cxx.

References sum.

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

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

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

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

1402  {
1403  // Fits the TP3D points in the selected section to a 3D line with the origin at the center of
1404  // the section
1405  if (pfp.TP3Ds.size() < 4) return false;
1406  if (sfIndex >= pfp.SectionFits.size()) return false;
1407  // don't fit a small angle PFP
1408  if (pfp.Flags[kSmallAngle]) return true;
1409 
1410  unsigned short fromPt = USHRT_MAX;
1411  unsigned short npts = 0;
1412  GetRange(pfp, sfIndex, fromPt, npts);
1413  if (fromPt == USHRT_MAX) return false;
1414  if (npts < 4) return false;
1415 
1416  // check for errors
1417  for (unsigned short ipt = fromPt; ipt < fromPt + npts; ++ipt) {
1418  auto& tp3d = pfp.TP3Ds[ipt];
1419  if (tp3d.SFIndex != sfIndex) return false;
1420  } // ipt
1421 
1422  // fit these points and update
1423  return FitTP3Ds(detProp, slc, pfp, fromPt, npts, sfIndex);
1424 
1425  } // FitSection
bool FitTP3Ds(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, unsigned short fromPt, unsigned short nPtsFit, unsigned short sfIndex)
Definition: PFPUtils.cxx:1571
void GetRange(const PFPStruct &pfp, unsigned short sfIndex, unsigned short &fromPt, unsigned short &npts)
Definition: PFPUtils.cxx:1377
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 1428 of file PFPUtils.cxx.

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

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

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

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

Definition at line 797 of file Utils.cxx.

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

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

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

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

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

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

Definition at line 1984 of file TCVertex.cxx.

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

1985  {
1986  // Version with LSQ fit. Each TP position (P0,P1) and slope S are fit to a vertex
1987  // at position (V0, V1), using the equation P1 = V1 + (P0 - V0) * S. This is put
1988  // in the form A * V = b. V is found using V = (A^T * A)^-1 * A^T * b. This is
1989  // usually done using the TDecompSVD Solve method but here we do it step-wise to
1990  // get access to the covariance matrix (A^T * A)^-1. The pull between the TP position
1991  // and the vertex position is stored in tp.Delta
1992 
1993  if (vxTPs.size() < 2) return false;
1994  if (vxTPs.size() == 2) {
1995  vx.ChiDOF = 0.;
1996  return true;
1997  }
1998 
1999  unsigned short npts = vxTPs.size();
2000  TMatrixD A(npts, 2);
2001  TVectorD b(npts);
2002  for (unsigned short itj = 0; itj < vxTPs.size(); ++itj) {
2003  auto& tp = vxTPs[itj];
2004  double dtdw = tp.Dir[1] / tp.Dir[0];
2005  double wt = 1 / (tp.AngErr * tp.AngErr);
2006  A(itj, 0) = -dtdw * wt;
2007  A(itj, 1) = 1. * wt;
2008  b(itj) = (tp.Pos[1] - tp.Pos[0] * dtdw) * wt;
2009  } // itj
2010 
2011  TMatrixD AT(2, npts);
2012  AT.Transpose(A);
2013  TMatrixD ATA = AT * A;
2014  double* det = 0;
2015  try {
2016  ATA.Invert(det);
2017  }
2018  catch (...) {
2019  return false;
2020  }
2021  if (det == NULL) return false;
2022  TVectorD vxPos = ATA * AT * b;
2023  vx.PosErr[0] = sqrt(ATA[0][0]);
2024  vx.PosErr[1] = sqrt(ATA[1][1]);
2025  vx.Pos[0] = vxPos[0];
2026  vx.Pos[1] = vxPos[1];
2027 
2028  // Calculate Chisq
2029  vx.ChiDOF = 0;
2030  if (vxTPs.size() > 2) {
2031  for (auto& tp : vxTPs) {
2032  // highjack TP Delta for the vertex pull
2033  tp.Delta = TrajPointVertexPull(tp, vx);
2034  vx.ChiDOF += tp.Delta;
2035  } // itj
2036  vx.ChiDOF /= (float)(vxTPs.size() - 2);
2037  } // vxTPs.size() > 2
2038 
2039  if (prt) {
2040  mf::LogVerbatim("TC") << "Note: TP - 2V pull is stored in TP.Delta";
2041  PrintTPHeader("FV");
2042  for (auto& tp : vxTPs)
2043  PrintTP("FV", slc, 0, 1, 1, tp);
2044  }
2045 
2046  return true;
2047  } // 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:6131
float TrajPointVertexPull(const TrajPoint &tp, const VtxStore &vx)
Definition: TCVertex.cxx:1836
void PrintTPHeader(std::string someText)
Definition: Utils.cxx:6123
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:3329
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1060
std::string PrintEndFlag(const PFPStruct &pfp, unsigned short end)
Definition: Utils.cxx:6294
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:2513
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6353
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
std::vector< float > chargeCuts
Definition: DataStructs.h:555
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2071
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:3380
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void ChkStop(Trajectory &tj)
Definition: StepUtils.cxx:3972
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3329
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:2513
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6353
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:551
void FitPar(const Trajectory &tj, unsigned short originPt, unsigned short npts, short fitDir, ParFit &pFit, unsigned short usePar)
Definition: Utils.cxx:1201
if(nlines<=0)
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
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:2773
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice const &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3576
std::vector< TjForecast > tjfs
Definition: DataStructs.cxx:10
geo::PlaneID DecodeCTP(CTP_t CTP)
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2762
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2071
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 4701 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().

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

Definition at line 69 of file TCCR.cxx.

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

Referenced by SaveCRInfo().

70  {
71 
74 
75  std::map<int, float> omap; //<origin, energy>
76 
77  for (auto& tjID : pfp.TjIDs) {
78 
79  Trajectory& tj = slc.tjs[tjID - 1];
80  for (auto& tp : tj.Pts) {
81  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
82  if (!tp.UseHit[ii]) continue;
83  unsigned int iht = tp.Hits[ii];
84  TCHit& slhit = slc.slHits[iht];
85  auto& hit = (*evt.allHits)[slhit.allHitsIndex];
86  raw::ChannelID_t channel = tcc.geom->PlaneWireToChannel(hit.WireID());
87  double startTick = hit.PeakTime() - hit.RMS();
88  double endTick = hit.PeakTime() + hit.RMS();
89  // get a list of track IDEs that are close to this hit
90  std::vector<sim::TrackIDE> tides;
91  tides = bt_serv->ChannelToTrackIDEs(clockData, channel, startTick, endTick);
92  for (auto itide = tides.begin(); itide != tides.end(); ++itide) {
93  omap[pi_serv->TrackIdToMCTruth_P(itide->trackID)->Origin()] += itide->energy;
94  }
95  }
96  }
97  }
98 
99  float maxe = -1;
100  int origin = 0;
101  for (auto& i : omap) {
102  if (i.second > maxe) {
103  maxe = i.second;
104  origin = i.first;
105  }
106  }
107  return origin;
108  }
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
const geo::GeometryCore * geom
Definition: DataStructs.h:569
Detector simulation of raw signals on wires.
raw::ChannelID_t PlaneWireToChannel(WireID const &wireid) const
Returns the ID of the TPC channel connected to the specified wire.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:615
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 1037 of file Utils.cxx.

References tca::TCSlice::pfps.

Referenced by MakeHaloTj(), and MergeAndStore().

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

Definition at line 1377 of file PFPUtils.cxx.

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

Referenced by export_G4UIcommand(), and FitSection().

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

Definition at line 4939 of file Utils.cxx.

References slices.

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

4940  {
4941  // returns the slice index and product index of a data product having typeName and unique ID uID
4942  for (unsigned short isl = 0; isl < slices.size(); ++isl) {
4943  auto& slc = slices[isl];
4944  if (typeName == "T") {
4945  for (unsigned short indx = 0; indx < slc.tjs.size(); ++indx) {
4946  if (slc.tjs[indx].UID == uID) { return std::make_pair(isl, indx); }
4947  }
4948  } // T
4949  if (typeName == "P") {
4950  for (unsigned short indx = 0; indx < slc.pfps.size(); ++indx) {
4951  if (slc.pfps[indx].UID == uID) { return std::make_pair(isl, indx); }
4952  }
4953  } // P
4954  if (typeName == "2V") {
4955  for (unsigned short indx = 0; indx < slc.vtxs.size(); ++indx) {
4956  if (slc.vtxs[indx].UID == uID) { return std::make_pair(isl, indx); }
4957  }
4958  } // 2V
4959  if (typeName == "3V") {
4960  for (unsigned short indx = 0; indx < slc.vtx3s.size(); ++indx) {
4961  if (slc.vtx3s[indx].UID == uID) { return std::make_pair(isl, indx); }
4962  }
4963  } // 3V
4964  if (typeName == "2S") {
4965  for (unsigned short indx = 0; indx < slc.cots.size(); ++indx) {
4966  if (slc.cots[indx].UID == uID) { return std::make_pair(isl, indx); }
4967  }
4968  } // 2S
4969  if (typeName == "3S") {
4970  for (unsigned short indx = 0; indx < slc.showers.size(); ++indx) {
4971  if (slc.showers[indx].UID == uID) { return std::make_pair(isl, indx); }
4972  }
4973  } // T
4974  } // isl
4975  return std::make_pair(USHRT_MAX, USHRT_MAX);
4976  } // 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:399
std::vector< int > tca::GetVtxTjIDs ( const TCSlice slc,
const VtxStore vx2 
)

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

2800  {
2801  // returns a list of trajectory IDs that are attached to vx2
2802  std::vector<int> tmp;
2803  if (vx2.ID == 0) return tmp;
2804  for (auto& tj : slc.tjs) {
2805  if (tj.AlgMod[kKilled]) continue;
2806  if (tj.CTP != vx2.CTP) continue;
2807  for (unsigned short end = 0; end < 2; ++end) {
2808  if (tj.VtxID[end] == vx2.ID) tmp.push_back(tj.ID);
2809  } // end
2810  } // tj
2811  return tmp;
2812  } // 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 2815 of file TCVertex.cxx.

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

2816  {
2817  // returns a list of Tjs in all planes that are attached to vx3
2818  std::vector<int> tmp;
2819  if (vx3.ID == 0) return tmp;
2820  float nvx2 = 0;
2821  score = 0;
2822  for (auto& vx2 : slc.vtxs) {
2823  if (vx2.ID == 0) continue;
2824  if (vx2.Vx3ID != vx3.ID) continue;
2825  auto vtxTjID2 = GetVtxTjIDs(slc, vx2);
2826  tmp.insert(tmp.end(), vtxTjID2.begin(), vtxTjID2.end());
2827  score += vx2.Score;
2828  ++nvx2;
2829  } // vx2
2830  if (nvx2 < 1) return tmp;
2831  // find the average score
2832  score /= nvx2;
2833  // sort by increasing ID
2834  std::sort(tmp.begin(), tmp.end());
2835  return tmp;
2836  } // GetVtxTjIDs
Float_t tmp
Definition: plot.C:35
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:2815
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:3329
std::vector< float > kinkCuts
kink finder algorithm
Definition: DataStructs.h:552
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1060
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6353
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
use the slowing-down strategy
Definition: DataStructs.h:496
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:2985
use the stiff electron strategy
Definition: DataStructs.h:494
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2071
use the stiff muon strategy
Definition: DataStructs.h:495
bool tca::HasDuplicateHits ( const TCSlice slc,
Trajectory const &  tj,
bool  prt 
)

Definition at line 2744 of file Utils.cxx.

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

Referenced by CheckTraj(), and MergeAndStore().

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

Definition at line 2482 of file Utils.cxx.

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

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

2483  {
2484  // returns the separation^2 between two hits in WSE units
2485  if (iht > slc.slHits.size() - 1 || jht > slc.slHits.size() - 1) return 1E6;
2486  auto& ihit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2487  auto& jhit = (*evt.allHits)[slc.slHits[jht].allHitsIndex];
2488  float dw = (float)ihit.WireID().Wire - (float)jhit.WireID().Wire;
2489  float dt = (ihit.PeakTime() - jhit.PeakTime()) * tcc.unitsPerTick;
2490  return dw * dw + dt * dt;
2491  } // HitSep2
TCConfig tcc
Definition: DataStructs.cxx:9
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:564
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:615
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 4172 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().

4176  {
4177  // returns the position and the charge
4178  float pos = 0;
4179  sum = 0;
4180  for (unsigned short ii = 0; ii < hitsInMultiplet.size(); ++ii) {
4181  unsigned int iht = hitsInMultiplet[ii];
4182  bool useit = (hitRequest == kAllHits);
4183  if (hitRequest == kUsedHits && slc.slHits[iht].InTraj > 0) useit = true;
4184  if (hitRequest == kUnusedHits && slc.slHits[iht].InTraj == 0) useit = true;
4185  if (!useit) continue;
4186  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
4187  float chg = hit.Integral();
4188  pos += chg * hit.PeakTime();
4189  sum += chg;
4190  } // ii
4191  if (sum <= 0) return -1;
4192  return pos / sum;
4193  } // HitsPosTick
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:615
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 4163 of file Utils.cxx.

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

Referenced by DotProd().

4167  {
4168  return tcc.unitsPerTick * HitsPosTick(slc, hitsInMultiplet, sum, hitRequest);
4169  } // HitsPosTime
TCConfig tcc
Definition: DataStructs.cxx:9
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:564
float HitsPosTick(const TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, float &sum, HitStatus_t hitRequest)
Definition: Utils.cxx:4172
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 4131 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().

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

Definition at line 4123 of file Utils.cxx.

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

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

4126  {
4127  return tcc.unitsPerTick * HitsRMSTick(slc, hitsInMultiplet, hitRequest);
4128  } // HitsRMSTick
TCConfig tcc
Definition: DataStructs.cxx:9
float HitsRMSTick(const TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
Definition: Utils.cxx:4131
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:564
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:4123
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:564
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:615
TCEvent evt
Definition: DataStructs.cxx:8
unsigned short tca::InsertTP3D ( PFPStruct pfp,
TP3D tp3d 
)

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

1968  {
1969  // inserts the tp3d into the section defined by tp3d.SFIndex
1970  if (tp3d.SFIndex >= pfp.SectionFits.size()) return USHRT_MAX;
1971  // Find the first occurrence of this SFIndex
1972  std::size_t ipt = 0;
1973  for (ipt = 0; ipt < pfp.TP3Ds.size(); ++ipt)
1974  if (tp3d.SFIndex == pfp.TP3Ds[ipt].SFIndex) break;
1975  if (ipt == pfp.TP3Ds.size()) return USHRT_MAX;
1976  // next see if we can insert it so that re-sorting of this section isn't required
1977  auto lastTP3D = pfp.TP3Ds.back();
1978  if (ipt == 0 && tp3d.along < pfp.TP3Ds[0].along) {
1979  // insert at the beginning. No search needs to be done
1980  }
1981  else if (tp3d.SFIndex == lastTP3D.SFIndex && tp3d.along > lastTP3D.along) {
1982  // insert at the end. Use push_back and return
1983  pfp.TP3Ds.push_back(tp3d);
1984  pfp.SectionFits[tp3d.SFIndex].NeedsUpdate = true;
1985  pfp.Flags[kNeedsUpdate] = true;
1986  return pfp.TP3Ds.size() - 1;
1987  }
1988  else {
1989  for (std::size_t iipt = ipt; iipt < pfp.TP3Ds.size() - 1; ++iipt) {
1990  // break out if the next point is in a different section
1991  if (pfp.TP3Ds[iipt + 1].SFIndex != tp3d.SFIndex) break;
1992  if (tp3d.along > pfp.TP3Ds[iipt].along && tp3d.along < pfp.TP3Ds[iipt + 1].along) {
1993  ipt = iipt + 1;
1994  break;
1995  }
1996  } // iipt
1997  } // insert in the middle
1998  pfp.TP3Ds.insert(pfp.TP3Ds.begin() + ipt, tp3d);
1999  pfp.SectionFits[tp3d.SFIndex].NeedsUpdate = true;
2000  pfp.Flags[kNeedsUpdate] = true;
2001  return ipt;
2002  } // 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:3069
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::array< float, 2 > Point2_t
Definition: DataStructs.h:43
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:2558
bool TrajTrajDOCA(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2406
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 3022 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().

3023  {
3024  // returns true if the end of the pfp is inside the fiducial volume of the TPC
3025  if (pfp.ID <= 0) return false;
3026  if (end > 1) return false;
3027  if (pfp.SectionFits.empty()) return false;
3028  // require that the points are sorted which ensures that the start and end points
3029  // are the first and last points in the TP3Ds vector
3030  if (pfp.Flags[kNeedsUpdate]) return false;
3031  bool neutrinoPFP = pfp.PDGCode == 12 || pfp.PDGCode == 14;
3032 
3033  float abit = 5;
3034  Point3_t pos;
3035  if (neutrinoPFP) { pos = pfp.SectionFits[0].Pos; }
3036  else if (end == 0) {
3037  pos = pfp.TP3Ds[0].Pos;
3038  }
3039  else {
3040  pos = pfp.TP3Ds[pfp.TP3Ds.size() - 1].Pos;
3041  }
3042  return (pos[0] > slc.xLo + abit && pos[0] < slc.xHi - abit && pos[1] > slc.yLo + abit &&
3043  pos[1] < slc.yHi - abit && pos[2] > slc.zLo + abit && pos[2] < slc.zHi - abit);
3044 
3045  } // InsideFV
std::array< double, 3 > Point3_t
Definition: DataStructs.h:41
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 3048 of file PFPUtils.cxx.

References tca::TCConfig::geom, geo::GeometryCore::Iterate(), and tcc.

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

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

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

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

Definition at line 2852 of file TCVertex.cxx.

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

Referenced by Find2DVertices().

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

Definition at line 2871 of file TCVertex.cxx.

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

2872  {
2873  // Returns the ID of a 3D vertex having the minimum pull < user-specified cut
2874 
2875  float minPull = tcc.vtx3DCuts[1];
2876  unsigned short imBest = 0;
2877  for (auto& oldvx3 : slc.vtx3s) {
2878  if (oldvx3.ID == 0) continue;
2879  if (std::abs(oldvx3.X - vx3.X) > tcc.vtx3DCuts[0]) continue;
2880  float pull = VertexVertexPull(vx3, oldvx3);
2881  if (pull < minPull) {
2882  minPull = pull;
2883  imBest = oldvx3.ID;
2884  }
2885  } // oldvx3
2886  return imBest;
2887 
2888  } // IsCloseToVertex
std::vector< float > vtx3DCuts
2D vtx -> 3D vtx matching cuts
Definition: DataStructs.h:544
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:1887
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:3380
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3329
std::vector< float > qualityCuts
Min points/wire, min consecutive pts after a gap.
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:6032
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1060
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
std::vector< unsigned short > minPts
min number of Pts required to make a trajectory
Definition: DataStructs.h:559
void TrimEndPts(std::string fcnLabel, TCSlice &slc, Trajectory &tj, const std::vector< float > &fQualityCuts, bool prt)
Definition: Utils.cxx:1575
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
use the stiff electron strategy
Definition: DataStructs.h:494
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2762
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:584
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:579
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:580
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 2151 of file TCVertex.cxx.

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

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

2152  {
2153  // kill 2D vertices that have low score and are not attached to a high-score 3D vertex
2154  if (slc.vtxs.empty()) return;
2155  for (auto& vx : slc.vtxs) {
2156  if (vx.ID == 0) continue;
2157  if (vx.Score > tcc.vtx2DCuts[7]) continue;
2158  if (vx.Vx3ID > 0) {
2159  auto& vx3 = slc.vtx3s[vx.Vx3ID - 1];
2160  if (vx3.Primary) continue;
2161  if (slc.vtx3s[vx.Vx3ID - 1].Score >= tcc.vtx2DCuts[7]) continue;
2162  }
2163  MakeVertexObsolete("KPV", slc, vx, false);
2164  } // vx
2165 
2166  } // KillPoorVertices
bool MakeVertexObsolete(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2781
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:543
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:2690
TCConfig tcc
Definition: DataStructs.cxx:9
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:3245
std::vector< int > GetAssns(TCSlice const &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4701
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
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 2985 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().

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

3046  {
3047  // returns a kink significance in the trajectory at the presumed kink point kinkPt
3048  // using angle and (optional) charge asymmetry. The returned value is negative if there is insufficient
3049  // information.
3050  //
3051  // Check the limits
3052  if (kinkPt < tj.EndPt[0] + 2) return -1;
3053  if (kinkPt > tj.EndPt[1] - 2) return -1;
3054 
3055  // This function requires knowledge of the DOF of the line fit
3056  if (nPtsFit < 3) return -1;
3057  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
3058  // need enough points to do a fit on each sideof the presumed kink point
3059  if (npwc < 2 * nPtsFit + 1) return -1;
3060 
3061  // The hit charge uncertainty is 0.12 - 0.15 (neglecting 2ndry interactions) for hadrons.
3062  // This translates into an error on the charge
3063  // asymmetry of about 0.07, or about 0.6 * the charge uncertainty
3064  double chgRMS = 0.07;
3065  // An additional contribution to the rms is the dependence on the DOF of the fit.
3066  // Apply a factor to the significance similar to (and simpler than) the Students t-distribution
3067  // This will increase the angle and charge error rms by 1.3 (1.05) when nPtsFit = 3 (8)
3068  double tFactor = 1 + 0.3 / double(nPtsFit - 2);
3069  chgRMS *= tFactor;
3070 
3071  // Fit the trajectory direction on the + side
3072  short fitDir = 1;
3073  TrajPoint tpPos;
3074  FitTraj(slc, tj, kinkPt, nPtsFit, fitDir, tpPos);
3075  if (tpPos.FitChi > 900) return -1;
3076  // repeat the trajectory fit on the - side
3077  fitDir = -1;
3078  TrajPoint tpNeg;
3079  FitTraj(slc, tj, kinkPt, nPtsFit, fitDir, tpNeg);
3080  if (tpNeg.FitChi > 900) return -1;
3081  double angErr = tpNeg.AngErr;
3082  if (tpPos.AngErr > angErr) angErr = tpPos.AngErr;
3083  angErr *= tFactor;
3084  double dang = DeltaAngle(tpPos.Ang, tpNeg.Ang);
3085  double dangSig = dang / angErr;
3086 
3087  double chgAsym = 0;
3088  double chgSig = 0;
3089  if (useChg) {
3090  // Sum the charge Neg and Pos, excluding the kinkPt
3091  double chgNeg = 0;
3092  unsigned short cntNeg = 0;
3093  for (unsigned short ipt = kinkPt - 1; ipt >= tj.EndPt[0]; --ipt) {
3094  auto& tp = tj.Pts[ipt];
3095  if (tp.Chg <= 0) continue;
3096  chgNeg += tp.Chg;
3097  ++cntNeg;
3098  if (cntNeg == nPtsFit) break;
3099  if (ipt == 0) break;
3100  } // ipt
3101  if (cntNeg != nPtsFit) {
3102  if (prt) mf::LogVerbatim("TC") << " KL: Bad cntNeg " << cntNeg << " != " << nPtsFit;
3103  return -1;
3104  }
3105  // now Pos
3106  double chgPos = 0;
3107  unsigned short cntPos = 0;
3108  for (unsigned short ipt = kinkPt + 1; ipt <= tj.EndPt[1]; ++ipt) {
3109  auto& tp = tj.Pts[ipt];
3110  if (tp.Chg <= 0) continue;
3111  chgPos += tp.Chg;
3112  ++cntPos;
3113  if (cntPos == nPtsFit) break;
3114  } // ipt
3115  if (cntPos != nPtsFit) {
3116  if (prt) mf::LogVerbatim("TC") << " KL: Bad cntPos " << cntPos << " != " << nPtsFit;
3117  return -1;
3118  }
3119  chgNeg /= (float)nPtsFit;
3120  chgPos /= (float)nPtsFit;
3121  // The charge asymmetry varies between 0 and 1;
3122  chgAsym = std::abs(chgPos - chgNeg) / (chgPos + chgNeg);
3123  // calculate the charge asymmetry significance
3124  chgSig = chgAsym / chgRMS;
3125  } // useChg
3126  double kinkSig = sqrt(dangSig * dangSig + chgSig * chgSig);
3127 
3128  if (prt) {
3129  mf::LogVerbatim myprt("TC");
3130  myprt << "KL: T" << tj.ID << " kinkPt " << PrintPos(tj.Pts[kinkPt]);
3131  myprt << " nPtsFit " << nPtsFit;
3132  myprt << " dang " << std::fixed << std::setprecision(3) << dang;
3133  myprt << std::fixed << std::setprecision(3) << " angErr " << angErr;
3134  myprt << std::setprecision(2) << " sig " << dangSig;
3135  myprt << " chgAsym " << chgAsym;
3136  myprt << " chgSig " << chgSig;
3137  myprt << " kinkSig " << kinkSig;
3138  }
3139  return (float)kinkSig;
3140  } // 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:2079
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::string PrintPos(const Point2_t &pos)
Definition: Utils.cxx:6359
void FitTraj(TCSlice const &slc, Trajectory &tj, unsigned short originPt, unsigned short npts, short fitDir, TrajPoint &tpFit)
Definition: Utils.cxx:810
double DeltaAngle(double Ang1, double Ang2)
Definition: Utils.cxx:3323
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:2690
TCConfig tcc
Definition: DataStructs.cxx:9
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2513
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:2535
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6353
TText * pt2
Definition: plot.C:64
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2094
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
bool MergeAndStore(TCSlice &slc, unsigned int itj1, unsigned int itj2, bool doPrt)
Definition: Utils.cxx:4518
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2558
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:580
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:2406
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 3103 of file PFPUtils.cxx.

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

Referenced by DotProd(), and PointDirIntersect().

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

Definition at line 4315 of file Utils.cxx.

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

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

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

Definition at line 3927 of file Utils.cxx.

References detinfo::DetectorPropertiesData::ConvertXToTicks(), tca::TrajPoint::CTP, DecodeCTP(), tca::TrajPoint::Dir, tca::TCConfig::geom, tca::TrajPoint::Pos, tcc, tca::TCConfig::unitsPerTick, and geo::GeometryCore::WireCoordinate().

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

3930  {
3931  // A version to use when the 2D direction isn't required
3932  TrajPoint tp;
3933  tp.Pos = {{0, 0}};
3934  tp.Dir = {{0, 1}};
3935  tp.CTP = inCTP;
3936  geo::PlaneID planeID = DecodeCTP(inCTP);
3937 
3938  tp.Pos[0] = tcc.geom->WireCoordinate(geo::Point_t{0, pos[1], pos[2]}, planeID);
3939  tp.Pos[1] = detProp.ConvertXToTicks(pos[0], planeID) * tcc.unitsPerTick;
3940  return tp;
3941  } // MakeBareTP
Length_t WireCoordinate(Point_t const &pos, PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:564
const geo::GeometryCore * geom
Definition: DataStructs.h:569
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)
TrajPoint tca::MakeBareTP ( detinfo::DetectorPropertiesData const &  detProp,
const Point3_t pos,
const Vector3_t dir,
CTP_t  inCTP 
)

Definition at line 3944 of file Utils.cxx.

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

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

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

4010  {
4011  if (fromHit > slc.slHits.size() - 1) return false;
4012  if (toHit > slc.slHits.size() - 1) return false;
4013  auto& fhit = (*evt.allHits)[slc.slHits[fromHit].allHitsIndex];
4014  auto& thit = (*evt.allHits)[slc.slHits[toHit].allHitsIndex];
4015  CTP_t tCTP = EncodeCTP(fhit.WireID());
4016  return MakeBareTrajPoint((float)fhit.WireID().Wire,
4017  fhit.PeakTime(),
4018  (float)thit.WireID().Wire,
4019  thit.PeakTime(),
4020  tCTP,
4021  tp);
4022 
4023  } // MakeBareTrajPoint
bool MakeBareTrajPoint(const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
Definition: Utils.cxx:4057
unsigned int CTP_t
Definition: DataStructs.h:47
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:615
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:51
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 4026 of file Utils.cxx.

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

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

Definition at line 4047 of file Utils.cxx.

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

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

Definition at line 4057 of file Utils.cxx.

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

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

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

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

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

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

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

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

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

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

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

Definition at line 2441 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, tca::TCConfig::geom, kTP3DGood, 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, and geo::GeometryCore::WireCoordinate().

Referenced by MakeSmallAnglePFP().

2444  {
2445  // Make a 3D trajectory point using two 2D trajectory points. The TP3D Pos and Wire
2446  // variables are defined using itp. The SectionFit variables are un-defined
2447  TP3D tp3d;
2448  tp3d.TPIndex = 0;
2449  tp3d.TjID = 0;
2450  tp3d.CTP = itp.CTP;
2451  // assume failure
2452  tp3d.Flags[kTP3DGood] = false;
2453  tp3d.Dir = {{0.0, 0.0, 1.0}};
2454  tp3d.Pos = {{999.0, 999.0, 999.0}};
2455  geo::PlaneID iPlnID = DecodeCTP(itp.CTP);
2456  geo::PlaneID jPlnID = DecodeCTP(jtp.CTP);
2457  if (iPlnID == jPlnID) return tp3d;
2458  double upt = tcc.unitsPerTick;
2459  double ix = detProp.ConvertTicksToX(itp.Pos[1] / upt, iPlnID);
2460  double jx = detProp.ConvertTicksToX(jtp.Pos[1] / upt, jPlnID);
2461 
2462  // don't continue if the points are wildly far apart in X
2463  double dx = std::abs(ix - jx);
2464  if (dx > 20) return tp3d;
2465  tp3d.Pos[0] = (ix + jx) / 2;
2466  tp3d.TPX = ix;
2467  // Fake the error
2468  tp3d.TPXErr2 = dx;
2469  // determine the wire orientation and offsets using WireCoordinate
2470  // wire = yp * OrthY + zp * OrthZ - Wire0 = cs * yp + sn * zp - wire0
2471  // wire offset
2472  double iw0 = tcc.geom->WireCoordinate(geo::Point_t{0, 0, 0}, iPlnID);
2473  // cosine-like component
2474  double ics = tcc.geom->WireCoordinate(geo::Point_t{0, 1, 0}, iPlnID) - iw0;
2475  // sine-like component
2476  double isn = tcc.geom->WireCoordinate(geo::Point_t{0, 0, 1}, iPlnID) - iw0;
2477  double jw0 = tcc.geom->WireCoordinate(geo::Point_t{0, 0, 0}, jPlnID);
2478  double jcs = tcc.geom->WireCoordinate(geo::Point_t{0, 1, 0}, jPlnID) - jw0;
2479  double jsn = tcc.geom->WireCoordinate(geo::Point_t{0, 0, 1}, jPlnID) - jw0;
2480  double den = isn * jcs - ics * jsn;
2481  if (den == 0) return tp3d;
2482  double iPos0 = itp.Pos[0];
2483  double jPos0 = jtp.Pos[0];
2484  // Find the Z position of the intersection
2485  tp3d.Pos[2] = (jcs * (iPos0 - iw0) - ics * (jPos0 - jw0)) / den;
2486  // and the Y position
2487  bool useI = std::abs(ics) > std::abs(jcs);
2488  if (useI) { tp3d.Pos[1] = (iPos0 - iw0 - isn * tp3d.Pos[2]) / ics; }
2489  else {
2490  tp3d.Pos[1] = (jPos0 - jw0 - jsn * tp3d.Pos[2]) / jcs;
2491  }
2492 
2493  // Now find the direction. Protect against large angles first
2494  if (jtp.Dir[1] == 0) {
2495  // Going either in the +X direction or -X direction
2496  if (jtp.Dir[0] > 0) { tp3d.Dir[0] = 1; }
2497  else {
2498  tp3d.Dir[0] = -1;
2499  }
2500  tp3d.Dir[1] = 0;
2501  tp3d.Dir[2] = 0;
2502  return tp3d;
2503  } // jtp.Dir[1] == 0
2504 
2505  tp3d.Wire = iPos0;
2506 
2507  // make a copy of itp and shift it by many wires to avoid precision problems
2508  double itp2_0 = itp.Pos[0] + 100;
2509  double itp2_1 = itp.Pos[1];
2510  if (std::abs(itp.Dir[0]) > 0.01) itp2_1 += 100 * itp.Dir[1] / itp.Dir[0];
2511  // Create a second Point3 for the shifted point
2512  Point3_t pos2;
2513  // Find the X position corresponding to the shifted point
2514  pos2[0] = detProp.ConvertTicksToX(itp2_1 / upt, iPlnID);
2515  // Convert X to Ticks in the j plane and then to WSE units
2516  double jtp2Pos1 = detProp.ConvertXToTicks(pos2[0], jPlnID) * upt;
2517  // Find the wire position (Pos0) in the j plane that this corresponds to
2518  double jtp2Pos0 = (jtp2Pos1 - jtp.Pos[1]) * (jtp.Dir[0] / jtp.Dir[1]) + jtp.Pos[0];
2519  // Find the Y,Z position using itp2 and jtp2Pos0
2520  pos2[2] = (jcs * (itp2_0 - iw0) - ics * (jtp2Pos0 - jw0)) / den;
2521  if (useI) { pos2[1] = (itp2_0 - iw0 - isn * pos2[2]) / ics; }
2522  else {
2523  pos2[1] = (jtp2Pos0 - jw0 - jsn * pos2[2]) / jcs;
2524  }
2525  double sep = PosSep(tp3d.Pos, pos2);
2526  if (sep == 0) return tp3d;
2527  for (unsigned short ixyz = 0; ixyz < 3; ++ixyz)
2528  tp3d.Dir[ixyz] = (pos2[ixyz] - tp3d.Pos[ixyz]) / sep;
2529  tp3d.Flags[kTP3DGood] = true;
2530  return tp3d;
2531 
2532  } // MakeTP3D
Length_t WireCoordinate(Point_t const &pos, PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
std::array< double, 3 > Point3_t
Definition: DataStructs.h:41
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:463
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:564
const geo::GeometryCore * geom
Definition: DataStructs.h:569
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:2558
bool tca::MakeTP3Ds ( detinfo::DetectorPropertiesData const &  detProp,
TCSlice slc,
PFPStruct pfp,
bool  prt 
)

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

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

Definition at line 2137 of file Utils.cxx.

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

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

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

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

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

Definition at line 2781 of file TCVertex.cxx.

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

2782  {
2783  // Deletes a 3D vertex and 2D vertices in all planes
2784  // The 2D and 3D vertices are NOT killed if forceKill is false and the 3D vertex
2785  // has a high score
2786  if (vx3.ID <= 0) return true;
2787  if (vx3.ID > int(slc.vtx3s.size())) return false;
2788 
2789  for (auto vx2id : vx3.Vx2ID) {
2790  if (vx2id == 0 || vx2id > (int)slc.vtxs.size()) continue;
2791  auto& vx2 = slc.vtxs[vx2id - 1];
2792  MakeVertexObsolete("MVO3", slc, vx2, true);
2793  }
2794  vx3.ID = 0;
2795  return true;
2796  } // MakeVertexObsolete
bool MakeVertexObsolete(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2781
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:797
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1060
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:580
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:797
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3329
std::vector< unsigned short > minPtsFit
Reconstruct in several passes.
Definition: DataStructs.h:558
TCConfig tcc
Definition: DataStructs.cxx:9
void PrintTrajectory(std::string someText, const TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:6032
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
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:3576
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:615
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:3329
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1060
float TrajPointSeparation(const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2612
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2513
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6353
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
void tca::Match2DShowers ( std::string  inFcnLabel,
TCSlice slc,
bool  prt 
)
void tca::Match2Planes ( TCSlice slc,
std::vector< MatchStruct > &  matVec 
)

Definition at line 942 of file PFPUtils.cxx.

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

Referenced by FindPFParticles().

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

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

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

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

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

Definition at line 377 of file Utils.cxx.

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

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

Definition at line 3201 of file Utils.cxx.

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

Referenced by CheckHiMultUnusedHits(), and FillGaps().

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

Definition at line 2566 of file Utils.cxx.

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

Referenced by MakePFParticles().

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

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

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

Definition at line 3396 of file Utils.cxx.

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

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

Definition at line 3402 of file Utils.cxx.

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

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

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

Referenced by DotProd(), and MCSMom().

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

Definition at line 3466 of file Utils.cxx.

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

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

Not allowed

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

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

Definition at line 2171 of file Utils.cxx.

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

2172  {
2173  // Merges short Tjs that share many hits with a longer Tj
2174  if (!tcc.useAlg[kMrgGhost]) return;
2175 
2176  for (auto& shortTj : slc.tjs) {
2177  if (shortTj.AlgMod[kKilled] || shortTj.AlgMod[kHaloTj]) continue;
2178  if (shortTj.CTP != inCTP) continue;
2179  unsigned short spts = shortTj.EndPt[1] - shortTj.EndPt[0];
2180  if (spts > 20) continue;
2181  // ignore delta rays
2182  if (shortTj.PDGCode == 11) continue;
2183  // ignore InShower Tjs
2184  if (shortTj.SSID > 0) continue;
2185  auto tjhits = PutTrajHitsInVector(shortTj, kAllHits);
2186  if (tjhits.empty()) continue;
2187  std::vector<int> tids;
2188  std::vector<unsigned short> tcnt;
2189  for (auto iht : tjhits) {
2190  auto& hit = slc.slHits[iht];
2191  if (hit.InTraj <= 0) continue;
2192  if ((unsigned int)hit.InTraj > slc.tjs.size()) continue;
2193  if (hit.InTraj == shortTj.ID) continue;
2194  unsigned short indx = 0;
2195  for (indx = 0; indx < tids.size(); ++indx)
2196  if (hit.InTraj == tids[indx]) break;
2197  if (indx == tids.size()) {
2198  tids.push_back(hit.InTraj);
2199  tcnt.push_back(1);
2200  }
2201  else {
2202  ++tcnt[indx];
2203  }
2204  } // iht
2205  if (tids.empty()) continue;
2206  // find the max count for Tjs that are longer than this one
2207  unsigned short maxcnt = 0;
2208  for (unsigned short indx = 0; indx < tids.size(); ++indx) {
2209  if (tcnt[indx] > maxcnt) {
2210  auto& ltj = slc.tjs[tids[indx] - 1];
2211  unsigned short lpts = ltj.EndPt[1] - ltj.EndPt[0];
2212  if (lpts < spts) continue;
2213  maxcnt = tcnt[indx];
2214  }
2215  } // indx
2216  float hitFrac = (float)maxcnt / (float)tjhits.size();
2217  if (hitFrac < 0.1) continue;
2218  } // shortTj
2219  } // MergeGhostTjs
std::vector< unsigned int > PutTrajHitsInVector(const Trajectory &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2688
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:579
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:3380
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:4701
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
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:551
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:3245
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2564
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:579
in close()
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2558
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:2513
bool MakeBareTrajPoint(const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:4006
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6353
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
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:2558
bool valsDecreasing(const SortEntry &c1, const SortEntry &c2)
Definition: Utils.cxx:38
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:2137
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:3069
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:2513
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:551
std::array< float, 2 > Point2_t
Definition: DataStructs.h:43
bool valsIncreasing(const SortEntry &c1, const SortEntry &c2)
Definition: Utils.cxx:42
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:579
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:2558
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:3380
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:2513
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:551
Float_t mat
Definition: plot.C:38
unsigned short FarEnd(const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3302
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2558
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2071
float ChgToMeV(float chg)
Definition: TCShower.cxx:3925
bool tca::MergeTjIntoPFP ( TCSlice slc,
int  mtjid,
PFPStruct pfp,
bool  prt 
)

Definition at line 511 of file Utils.cxx.

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

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

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

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

2763  {
2764  // Project TP to a "wire position" Pos[0] and update Pos[1]
2765  if (tp.Dir[0] == 0) return;
2766  float dw = wire - tp.Pos[0];
2767  if (std::abs(dw) < 0.01) return;
2768  tp.Pos[0] = wire;
2769  tp.Pos[1] += dw * tp.Dir[1] / tp.Dir[0];
2770  } // 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 2887 of file Utils.cxx.

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

Referenced by Reconcile2VTs().

2888  {
2889  // Searches for a TP near the end (or beginnin) that doesn't have the kEnvOverlap bit set
2890  // with the intent that a fit of a vertex position using this tj will be minimally
2891  // biased if there are no nearby hits from other tjs. A search is done from the
2892  // supplied nearPt moving in the + direction if nearPt == tj.EndPt[0] and moving in
2893  // the - direction if nearPt == tj.EndPt[1]
2894  if (end > 1) return USHRT_MAX;
2895  short dir = 1;
2896  if (end == 1) dir = -1;
2897  for (short ii = 0; ii < (short)tj.Pts.size(); ++ii) {
2898  short ipt = tj.EndPt[end] + dir * ii;
2899  if (ipt < 0 || ipt >= (short)tj.Pts.size()) return USHRT_MAX;
2900  auto& tp = tj.Pts[ipt];
2901  if (!tp.Environment[kEnvOverlap]) return ipt;
2902  } // ii
2903  return tj.EndPt[end];
2904  } // 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 2029 of file Utils.cxx.

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

Referenced by AddHits(), and SignalAtTp().

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

Definition at line 3434 of file Utils.cxx.

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

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

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

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

446  {
447  // Returns the ID of the grandparent of this tj that is a primary tj that is attached
448  // to the neutrino vertex. 0 is returned if this condition is not met.
449  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) return -1;
450  if (tj.ParentID <= 0) return -1;
451  int primID = PrimaryID(slc, tj);
452  if (primID <= 0 || primID > (int)slc.tjs.size()) return -1;
453 
454  // We have the ID of the primary tj. Now see if it is attached to the neutrino vertex
455  auto& ptj = slc.tjs[primID - 1];
456  for (unsigned short end = 0; end < 2; ++end) {
457  if (ptj.VtxID[end] == 0) continue;
458  auto& vx2 = slc.vtxs[ptj.VtxID[end] - 1];
459  if (vx2.Vx3ID == 0) continue;
460  auto& vx3 = slc.vtx3s[vx2.Vx3ID - 1];
461  if (vx3.Neutrino) return primID;
462  } // end
463  return -1;
464  } // 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:467
unsigned short tca::NumHitsInTP ( const TrajPoint tp,
HitStatus_t  hitRequest 
)

Definition at line 4196 of file Utils.cxx.

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

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

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

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

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

Definition at line 2079 of file Utils.cxx.

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

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

Definition at line 706 of file Utils.cxx.

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

Referenced by CompatibleMerge(), and EndMerge().

707  {
708  // returns the fraction of wires spanned by two trajectories
709  float minWire = 1E6;
710  float maxWire = -1E6;
711 
712  float cnt1 = 0;
713  for (auto& tp : tj1.Pts) {
714  if (tp.Chg == 0) continue;
715  if (tp.Pos[0] < 0) continue;
716  if (tp.Pos[0] < minWire) minWire = tp.Pos[0];
717  if (tp.Pos[0] > maxWire) maxWire = tp.Pos[0];
718  ++cnt1;
719  }
720  if (cnt1 == 0) return 0;
721  float cnt2 = 0;
722  for (auto& tp : tj2.Pts) {
723  if (tp.Chg == 0) continue;
724  if (tp.Pos[0] < 0) continue;
725  if (tp.Pos[0] < minWire) minWire = tp.Pos[0];
726  if (tp.Pos[0] > maxWire) maxWire = tp.Pos[0];
727  ++cnt2;
728  }
729  if (cnt2 == 0) return 0;
730  int span = maxWire - minWire;
731  if (span <= 0) return 0;
732  std::vector<unsigned short> wcnt(span);
733  for (auto& tp : tj1.Pts) {
734  if (tp.Chg == 0) continue;
735  if (tp.Pos[0] < -0.4) continue;
736  int indx = std::nearbyint(tp.Pos[0] - minWire);
737  if (indx < 0 || indx > span - 1) continue;
738  ++wcnt[indx];
739  }
740  for (auto& tp : tj2.Pts) {
741  if (tp.Chg == 0) continue;
742  if (tp.Pos[0] < -0.4) continue;
743  int indx = std::nearbyint(tp.Pos[0] - minWire);
744  if (indx < 0 || indx > span - 1) continue;
745  ++wcnt[indx];
746  }
747  float cntOverlap = 0;
748  for (auto cnt : wcnt)
749  if (cnt > 1) ++cntOverlap;
750  if (cnt1 < cnt2) { return cntOverlap / cnt1; }
751  else {
752  return cntOverlap / cnt2;
753  }
754 
755  } // OverlapFraction
span(IterB &&b, IterE &&e, Adaptor &&adaptor) -> span< decltype(adaptor(std::forward< IterB >(b))), decltype(adaptor(std::forward< IterE >(e))) >
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:2564
unsigned short FarEnd(const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3302
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:3069
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:2535
bool MakeBareTrajPoint(const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:4006
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6353
std::array< float, 2 > Point2_t
Definition: DataStructs.h:43
float ChgFracNearPos(const TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3162
float ChgFracBetween(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, Point3_t pos1, Point3_t pos2)
Definition: PFPUtils.cxx:3166
unsigned short FarEnd(const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3302
std::vector< int > GetAssns(TCSlice const &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4701
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:2558
unsigned short tca::PDGCodeIndex ( int  PDGCode)

Definition at line 2125 of file Utils.cxx.

References util::abs().

2126  {
2127  unsigned short pdg = abs(PDGCode);
2128  if (pdg == 11) return 0; // electron
2129  if (pdg == 13) return 1; // muon
2130  if (pdg == 211) return 2; // pion
2131  if (pdg == 321) return 3; // kaon
2132  if (pdg == 2212) return 4; // proton
2133  return USHRT_MAX;
2134  } // 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 409 of file Utils.cxx.

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

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

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

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

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

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

Definition at line 2542 of file PFPUtils.cxx.

References dir, and SetMag().

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

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

Definition at line 4076 of file Utils.cxx.

References dir, and norm.

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

References LineLineIntersect().

Referenced by DotProd().

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

Definition at line 3245 of file Utils.cxx.

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

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

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

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

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

Definition at line 2797 of file PFPUtils.cxx.

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

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

2798  {
2799  // returns the pull that the tp3d will cause in the pfp section fit. This
2800  // currently only uses position but eventually will include charge
2801  return std::abs(tp3d.Pos[0] - tp3d.TPX) / sqrt(tp3d.TPXErr2);
2802  } // 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 2513 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().

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

Definition at line 2523 of file Utils.cxx.

References PointTrajDOCA2().

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

Definition at line 2529 of file Utils.cxx.

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

Referenced by PointTrajDOCA(), and TjDeltaRMS().

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

Definition at line 2505 of file Utils.cxx.

References tca::TrajPoint::Pos.

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

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

3260  {
3261  if (end > 1 || pfp.SectionFits.empty()) return {{0., 0., 0.}};
3262  // handle a neutrino pfp that doesn't have any TP3Ds
3263  if (pfp.TP3Ds.empty()) return pfp.SectionFits[0].Pos;
3264  if (end == 0) return pfp.TP3Ds[0].Pos;
3265  return pfp.TP3Ds[pfp.TP3Ds.size() - 1].Pos;
3266  } // 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 2839 of file TCVertex.cxx.

References detinfo::DetectorPropertiesData::ConvertXToTicks(), tca::TCConfig::geom, tcc, tca::Vtx3Store::TPCID, tca::TCConfig::unitsPerTick, geo::GeometryCore::WireCoordinate(), tca::Vtx3Store::X, tca::Vtx3Store::Y, and tca::Vtx3Store::Z.

Referenced by Print3V(), and PrintAllTraj().

2843  {
2844  // returns the 2D position of the vertex in the plane
2845  geo::PlaneID const planeID{vx3.TPCID, plane};
2846  pos[0] = tcc.geom->WireCoordinate(geo::Point_t{0, vx3.Y, vx3.Z}, planeID);
2847  pos[1] = detProp.ConvertXToTicks(vx3.X, planeID) * tcc.unitsPerTick;
2848 
2849  } // PosInPlane
Length_t WireCoordinate(Point_t const &pos, PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:564
const geo::GeometryCore * geom
Definition: DataStructs.h:569
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
constexpr TPCID()=default
Default constructor: an invalid TPC ID.
float tca::PosSep ( const Point2_t pos1,
const Point2_t pos2 
)

Definition at line 2597 of file Utils.cxx.

References PosSep2().

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

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

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

Definition at line 2603 of file Utils.cxx.

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

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

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

Definition at line 486 of file Utils.cxx.

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

Referenced by PrintPFP().

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

5611  {
5612  // print a 2D vertex on one line
5613  if (vx2.ID <= 0) return;
5614  if (debug.CTP != UINT_MAX && vx2.CTP != debug.CTP) return;
5615  auto sIndx = GetSliceIndex("2V", vx2.UID);
5616  if (sIndx.first == USHRT_MAX) return;
5617  auto const& slc = slices[sIndx.first];
5618  if (printHeader) {
5619  myprt << "************ 2D vertices ************\n";
5620  myprt << " prodID CTP wire err tick err ChiDOF NTj Pass Topo ChgFrac Score "
5621  " v3D Tj UIDs\n";
5622  printHeader = false;
5623  }
5624  std::string str = "2V" + std::to_string(vx2.ID) + "/2VU" + std::to_string(vx2.UID);
5625  myprt << std::right << std::setw(12) << std::fixed << str;
5626  myprt << std::right << std::setw(6) << vx2.CTP;
5627  myprt << std::right << std::setw(8) << std::setprecision(0) << std::nearbyint(vx2.Pos[0]);
5628  myprt << std::right << std::setw(5) << std::setprecision(1) << vx2.PosErr[0];
5629  myprt << std::right << std::setw(8) << std::setprecision(0)
5630  << std::nearbyint(vx2.Pos[1] / tcc.unitsPerTick);
5631  myprt << std::right << std::setw(5) << std::setprecision(1) << vx2.PosErr[1] / tcc.unitsPerTick;
5632  myprt << std::right << std::setw(7) << vx2.ChiDOF;
5633  myprt << std::right << std::setw(5) << vx2.NTraj;
5634  myprt << std::right << std::setw(5) << vx2.Pass;
5635  myprt << std::right << std::setw(6) << vx2.Topo;
5636  myprt << std::right << std::setw(9) << std::setprecision(2) << vx2.TjChgFrac;
5637  myprt << std::right << std::setw(6) << std::setprecision(1) << vx2.Score;
5638  int v3id = 0;
5639  if (vx2.Vx3ID > 0) v3id = slc.vtx3s[vx2.Vx3ID - 1].UID;
5640  myprt << std::right << std::setw(5) << v3id;
5641  myprt << " ";
5642  // display the traj IDs
5643  for (unsigned short ii = 0; ii < slc.tjs.size(); ++ii) {
5644  auto const& tj = slc.tjs[ii];
5645  if (tj.AlgMod[kKilled]) continue;
5646  for (unsigned short end = 0; end < 2; ++end) {
5647  if (tj.VtxID[end] != (short)vx2.ID) continue;
5648  std::string tid = " TU" + std::to_string(tj.UID) + "_" + std::to_string(end);
5649  myprt << std::right << std::setw(6) << tid;
5650  } // end
5651  } // ii
5652  myprt << " Stat:";
5653  // Special flags. Ignore the first flag bit (0 = kVxTrjTried) which is done for every vertex
5654  for (unsigned short ib = 1; ib < VtxBitNames.size(); ++ib)
5655  if (vx2.Stat[ib]) myprt << " " << VtxBitNames[ib];
5656  myprt << "\n";
5657  } // 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:564
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:4939
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 5660 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().

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

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

5539  {
5540  // print a 3D vertex on one line
5541  if (vx3.ID <= 0) return;
5542  auto sIndx = GetSliceIndex("3V", vx3.UID);
5543  if (sIndx.first == USHRT_MAX) return;
5544  auto const& slc = slices[sIndx.first];
5545  if (printHeader) {
5546  myprt
5547  << "****** 3D vertices ******************************************__2DVtx_UID__*******\n";
5548  myprt << " prodID Cstat TPC X Y Z pln0 pln1 pln2 Wire score "
5549  "Prim? Nu? nTru";
5550  myprt << " ___________2D_Pos____________ _____Tj UIDs________\n";
5551  printHeader = false;
5552  }
5553  std::string str = "3V" + std::to_string(vx3.ID) + "/3VU" + std::to_string(vx3.UID);
5554  myprt << std::right << std::setw(12) << std::fixed << str;
5555  myprt << std::setprecision(0);
5556  myprt << std::right << std::setw(7) << vx3.TPCID.Cryostat;
5557  myprt << std::right << std::setw(5) << vx3.TPCID.TPC;
5558  myprt << std::right << std::setw(8) << vx3.X;
5559  myprt << std::right << std::setw(8) << vx3.Y;
5560  myprt << std::right << std::setw(8) << vx3.Z;
5561  for (auto vx2id : vx3.Vx2ID) {
5562  if (vx2id > 0) {
5563  str = "2VU" + std::to_string(slc.vtxs[vx2id - 1].UID);
5564  myprt << std::right << std::setw(7) << str;
5565  }
5566  else {
5567  myprt << " --";
5568  }
5569  } // vx2id
5570  myprt << std::right << std::setw(5) << vx3.Wire;
5571  unsigned short nTruMatch = 0;
5572  for (unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
5573  if (vx3.Vx2ID[ipl] == 0) continue;
5574  unsigned short iv2 = vx3.Vx2ID[ipl] - 1;
5575  if (slc.vtxs[iv2].Stat[kVxTruMatch]) ++nTruMatch;
5576  } // ipl
5577  myprt << std::right << std::setw(6) << std::setprecision(1) << vx3.Score;
5578  myprt << std::setw(6) << vx3.Primary;
5579  myprt << std::setw(4) << vx3.Neutrino;
5580  myprt << std::right << std::setw(5) << nTruMatch;
5581  Point2_t pos;
5582  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
5583  PosInPlane(detProp, vx3, plane, pos);
5584  myprt << " " << PrintPos(pos);
5585  } // plane
5586  if (vx3.Wire == -2) {
5587  // find the Tjs that are attached to it
5588  for (unsigned short end = 0; end < 2; ++end) {
5589  for (auto& pfp : slc.pfps) {
5590  if (pfp.Vx3ID[end] == vx3.ID) {
5591  for (auto tjID : pfp.TjIDs) {
5592  auto& tj = slc.tjs[tjID - 1];
5593  myprt << " T" << tj.UID;
5594  } // tjID
5595  } // pfp.Vx3ID[0] == vx3.ID
5596  } // pfp
5597  } // end
5598  }
5599  else {
5600  auto vxtjs = GetAssns(slc, "3V", vx3.ID, "T");
5601  for (auto tjid : vxtjs) {
5602  auto& tj = slc.tjs[tjid - 1];
5603  myprt << " TU" << tj.UID;
5604  }
5605  } // vx3.Wire != -2
5606  myprt << "\n";
5607  } // 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:93
std::string PrintPos(const Point2_t &pos)
Definition: Utils.cxx:6359
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:43
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:4701
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:4939
void PosInPlane(detinfo::DetectorPropertiesData const &detProp, const Vtx3Store &vx3, unsigned short plane, Point2_t &pos)
Definition: TCVertex.cxx:2839
void tca::PrintAll ( detinfo::DetectorPropertiesData const &  detProp,
std::string  someText 
)

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

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

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

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

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

5298  {
5299  // print the debug mode configuration to the screen
5300  std::cout << "*** TrajCluster debug mode configuration in";
5301  std::cout << " CTP=";
5302  if (debug.CTP == UINT_MAX) { std::cout << "NA"; }
5303  else {
5304  std::cout << debug.CTP;
5305  }
5306  std::cout << " Cryostat=" << debug.Cryostat;
5307  std::cout << " TPC=" << debug.TPC;
5308  std::cout << " Plane=" << debug.Plane;
5309  std::cout << " Wire=" << debug.Wire;
5310  std::cout << " Tick=" << debug.Tick;
5311  std::cout << " Hit=";
5312  if (debug.Hit == UINT_MAX) { std::cout << "NA"; }
5313  else {
5314  std::cout << debug.Hit;
5315  }
5316  std::cout << " WorkID=";
5317  if (debug.WorkID == 0) { std::cout << "NA"; }
5318  else {
5319  std::cout << debug.WorkID;
5320  }
5321  std::cout << " Slice=";
5322  if (debug.Slice == -1) { std::cout << "All"; }
5323  else {
5324  std::cout << debug.Slice;
5325  }
5326  std::cout << "\n";
5327  std::cout << "*** tcc.dbg modes:";
5328  if (tcc.dbgSlc) std::cout << " dbgSlc";
5329  if (tcc.dbgStp) std::cout << " dbgStp";
5330  if (tcc.dbgMrg) std::cout << " dbgMrg";
5331  if (tcc.dbg2V) std::cout << " dbg2V";
5332  if (tcc.dbg2S) std::cout << " dbg2S";
5333  if (tcc.dbgVxNeutral) std::cout << " dbgVxNeutral";
5334  if (tcc.dbgVxMerge) std::cout << " dbgVxMerge";
5335  if (tcc.dbgVxJunk) std::cout << " dbgVxJunk";
5336  if (tcc.dbg3V) std::cout << " dbg3V";
5337  if (tcc.dbgPFP) std::cout << " dbgPFP";
5338  if (tcc.dbgDeltaRayTag) std::cout << " dbgDeltaRayTag";
5339  if (tcc.dbgMuonTag) std::cout << " dbgMuonTag";
5340  if (tcc.dbgStitch) std::cout << " dbgStitch";
5341  if (tcc.dbgSummary) std::cout << " dbgSummary";
5342  if (tcc.dbgDump) std::cout << " dbgDump";
5343  std::cout << "\n";
5344  std::cout << "*** Using algs:";
5345  unsigned short cnt = 0;
5346  for (unsigned short ib = 0; ib < AlgBitNames.size(); ++ib) {
5347  if (tcc.useAlg[ib] && ib != kKilled) {
5348  ++cnt;
5349  if (cnt % 10 == 0) std::cout << "\n ";
5350  std::cout << " " << AlgBitNames[ib];
5351  }
5352  }
5353  std::cout << "\n";
5354  std::cout << "*** Skipping algs:";
5355  cnt = 0;
5356  for (unsigned short ib = 0; ib < AlgBitNames.size(); ++ib) {
5357  if (!tcc.useAlg[ib] && ib != kKilled) {
5358  ++cnt;
5359  if (cnt % 10 == 0) std::cout << "\n ";
5360  std::cout << " " << AlgBitNames[ib];
5361  }
5362  }
5363  std::cout << "\n";
5364  } // PrintDebugMode
bool dbgStitch
debug PFParticle stitching
Definition: DataStructs.h:596
const std::vector< std::string > AlgBitNames
Definition: DataStructs.cxx:16
TCConfig tcc
Definition: DataStructs.cxx:9
bool dbgDeltaRayTag
Definition: DataStructs.h:592
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:583
bool dbg3V
debug 3D vertex finding
Definition: DataStructs.h:590
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:584
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:586
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:579
bool dbgSummary
print a summary report
Definition: DataStructs.h:597
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 6294 of file Utils.cxx.

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

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

6295  {
6296  if (end > 1) return "Invalid end";
6297  std::string tmp;
6298  bool first = true;
6299  for (unsigned short ib = 0; ib < EndFlagNames.size(); ++ib) {
6300  if (pfp.EndFlag[end][ib]) {
6301  if (first) {
6302  tmp = std::to_string(end) + ":" + EndFlagNames[ib];
6303  first = false;
6304  }
6305  else {
6306  tmp += "," + EndFlagNames[ib];
6307  }
6308  }
6309  } // ib
6310  if (first) tmp = " none";
6311  return tmp;
6312  } // 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 6315 of file Utils.cxx.

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

6316  {
6317  if (end > 1) return "Invalid end";
6318  std::string tmp;
6319  bool first = true;
6320  for (unsigned short ib = 0; ib < EndFlagNames.size(); ++ib) {
6321  if (tj.EndFlag[end][ib]) {
6322  if (first) {
6323  tmp = std::to_string(end) + ":" + EndFlagNames[ib];
6324  first = false;
6325  }
6326  else {
6327  tmp += "," + EndFlagNames[ib];
6328  }
6329  }
6330  } // ib
6331  return tmp;
6332  } // 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 6344 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().

6345  {
6346  if (tch.allHitsIndex > (*evt.allHits).size() - 1) return "NA";
6347  auto& hit = (*evt.allHits)[tch.allHitsIndex];
6348  return std::to_string(hit.WireID().Plane) + ":" + std::to_string(hit.WireID().Wire) + ":" +
6349  std::to_string((int)hit.PeakTime()) + "_" + std::to_string(tch.InTraj);
6350  } // 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:615
TCEvent evt
Definition: DataStructs.cxx:8
std::string tca::PrintHitShort ( const TCHit tch)

Definition at line 6335 of file Utils.cxx.

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

Referenced by DotProd().

6336  {
6337  if (tch.allHitsIndex > (*evt.allHits).size() - 1) return "NA";
6338  auto& hit = (*evt.allHits)[tch.allHitsIndex];
6339  return std::to_string(hit.WireID().Plane) + ":" + std::to_string(hit.WireID().Wire) + ":" +
6340  std::to_string((int)hit.PeakTime());
6341  } // 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:615
TCEvent evt
Definition: DataStructs.cxx:8
void tca::PrintP ( mf::LogVerbatim myprt,
PFPStruct const &  pfp,
bool &  printHeader 
)

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

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

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

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

Definition at line 6276 of file Utils.cxx.

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

Referenced by DotProd(), and FindShowers3D().

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

Definition at line 6359 of file Utils.cxx.

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

6360  {
6361  unsigned int wire = 0;
6362  if (pos[0] > -0.4) wire = std::nearbyint(pos[0]);
6363  int time = std::nearbyint(pos[1] / tcc.unitsPerTick);
6364  return std::to_string(wire) + ":" + std::to_string(time);
6365  } // PrintPos
TCConfig tcc
Definition: DataStructs.cxx:9
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:564
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:6353
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:564
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:6353
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const Point3_t &pos, CTP_t inCTP)
Definition: Utils.cxx:3927
unsigned int CTP_t
Definition: DataStructs.h:47
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:51
void tca::PrintT ( mf::LogVerbatim myprt,
Trajectory const &  tj,
bool &  printHeader 
)

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

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

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

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

Definition at line 6123 of file Utils.cxx.

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

6124  {
6125  mf::LogVerbatim("TC") << someText
6126  << " TRP CTP Ind Stp Delta RMS Ang C Err Dir0 Dir1 Q "
6127  " AveQ Pull FitChi NTPF KinkSig Hits ";
6128  } // 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 6032 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().

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

Definition at line 2664 of file Utils.cxx.

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

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

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

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

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

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

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

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

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

Definition at line 469 of file PFPUtils.cxx.

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

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

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

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

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

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

Definition at line 2660 of file TCVertex.cxx.

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

Referenced by CompleteIncomplete3DVertices().

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

Definition at line 1048 of file Utils.cxx.

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

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

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

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

Definition at line 2149 of file Utils.cxx.

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

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

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

2355  {
2356  // reverse the PFParticle
2357  std::reverse(pfp.TP3Ds.begin(), pfp.TP3Ds.end());
2358  std::reverse(pfp.SectionFits.begin(), pfp.SectionFits.end());
2359  for (std::size_t sfi = 0; sfi < pfp.SectionFits.size(); ++sfi) {
2360  auto& sf = pfp.SectionFits[sfi];
2361  // flip the direction vector
2362  for (unsigned short xyz = 0; xyz < 3; ++xyz)
2363  sf.Dir[xyz] *= -1;
2364  } // sf
2365  // correct the along variable
2366  for (auto& tp3d : pfp.TP3Ds)
2367  tp3d.along *= -1;
2368  std::swap(pfp.dEdx[0], pfp.dEdx[1]);
2369  std::swap(pfp.dEdxErr[0], pfp.dEdxErr[1]);
2370  std::swap(pfp.Vx3ID[0], pfp.Vx3ID[1]);
2371  std::swap(pfp.EndFlag[0], pfp.EndFlag[1]);
2372  } // 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:3329
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6353
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:623
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:2773
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6344
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:579
geo::PlaneID DecodeCTP(CTP_t CTP)
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:580
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2762
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:3218
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:3218
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 3218 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().

3219  {
3220  // reverse the trajectory
3221  if (tj.Pts.empty()) return;
3222  // reverse the crawling direction flag
3223  tj.StepDir = -tj.StepDir;
3224  // Vertices
3225  std::swap(tj.VtxID[0], tj.VtxID[1]);
3226  // trajectory points
3227  std::reverse(tj.Pts.begin(), tj.Pts.end());
3228  // reverse the stop flag
3229  std::reverse(tj.EndFlag.begin(), tj.EndFlag.end());
3230  std::swap(tj.dEdx[0], tj.dEdx[1]);
3231  // reverse the direction vector on all points
3232  for (unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) {
3233  if (tj.Pts[ipt].Dir[0] != 0) tj.Pts[ipt].Dir[0] = -tj.Pts[ipt].Dir[0];
3234  if (tj.Pts[ipt].Dir[1] != 0) tj.Pts[ipt].Dir[1] = -tj.Pts[ipt].Dir[1];
3235  if (tj.Pts[ipt].Ang > 0) { tj.Pts[ipt].Ang -= M_PI; }
3236  else {
3237  tj.Pts[ipt].Ang += M_PI;
3238  }
3239  } // ipt
3240  if (tj.StartEnd == 0 || tj.StartEnd == 1) tj.StartEnd = 1 - tj.StartEnd;
3241  SetEndPoints(tj);
3242  } // ReverseTraj
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3329
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:533
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:600
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:533
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:600
void tca::SaveCRInfo ( detinfo::DetectorClocksData const &  clockData,
TCSlice slc,
PFPStruct pfp,
bool  fIsRealData 
)

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

29  {
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  //std::cout<<startPos[1]<<" "<<startPos[2]<<" "<<endPos[1]<<" "<<endPos[2]<<" "<<tpc.MinY()<<" "<<tpc.MaxY()<<" "<<tpc.MinZ()<<" "<<tpc.MaxZ()<<" "<<mindis0<<" "<<mindis1<<" "<<mindis0+mindis1<<std::endl;
58  slc.crt.cr_pfpyzmindis.push_back(mindis0 + mindis1);
59 
60  if (slc.crt.cr_pfpxmin.back() < -2 || slc.crt.cr_pfpxmax.back() > 260 ||
61  slc.crt.cr_pfpyzmindis.back() < 30) {
62  pfp.CosmicScore = 1.;
63  }
64  else
65  pfp.CosmicScore = 0;
66  }
TCConfig tcc
Definition: DataStructs.cxx:9
Geometry information for a single TPC.
Definition: TPCGeo.h:36
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:69
TPCGeo const & TPC(TPCID const &tpcid=tpc_zero) const
Returns the specified TPC.
Definition: GeometryCore.h:722
double MinZ() const
Returns the world z coordinate of the start of the box.
const geo::GeometryCore * geom
Definition: DataStructs.h:569
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:600
save cosmic ray tree
Definition: DataStructs.h:531
double MaxZ() const
Returns the world z coordinate of the end of the box.
double MinY() const
Returns the world y coordinate of the start of the box.
void tca::SaveTjInfo ( 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:404
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< int > ShowerID
Definition: DataStructs.h:396
ShowerTreeVars stv
Definition: DataStructs.cxx:11
save shower tree
Definition: DataStructs.h:533
std::vector< float > Envelope
Definition: DataStructs.h:402
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:600
std::vector< int > EnvPlane
Definition: DataStructs.h:403
unsigned int CTP_t
Definition: DataStructs.h:47
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:405
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:404
std::vector< int > IsShowerParent
Definition: DataStructs.h:397
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
std::vector< int > ShowerID
Definition: DataStructs.h:396
ShowerTreeVars stv
Definition: DataStructs.cxx:11
save shower tree
Definition: DataStructs.h:533
std::vector< int > TjID
Definition: DataStructs.h:394
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:564
std::vector< float > Envelope
Definition: DataStructs.h:402
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:600
std::vector< int > EnvPlane
Definition: DataStructs.h:403
std::vector< int > StageNum
Definition: DataStructs.h:398
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:405
std::vector< int > IsShowerTj
Definition: DataStructs.h:395
std::vector< short > PlaneNum
Definition: DataStructs.h:392
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:397
std::vector< float > EndWir
Definition: DataStructs.h:384
std::vector< float > EndAng
Definition: DataStructs.h:386
std::vector< float > BeginTim
Definition: DataStructs.h:380
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< float > BeginAng
Definition: DataStructs.h:381
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
std::vector< float > EndTim
Definition: DataStructs.h:385
std::vector< int > ShowerID
Definition: DataStructs.h:396
ShowerTreeVars stv
Definition: DataStructs.cxx:11
save shower tree
Definition: DataStructs.h:533
std::vector< int > TjID
Definition: DataStructs.h:394
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:564
std::vector< short > BeginVtx
Definition: DataStructs.h:383
std::vector< short > EndVtx
Definition: DataStructs.h:388
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
std::vector< float > BeginChg
Definition: DataStructs.h:382
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:600
std::vector< short > MCSMom
Definition: DataStructs.h:390
std::vector< int > StageNum
Definition: DataStructs.h:398
unsigned short nPlanes
Definition: DataStructs.h:408
std::vector< float > BeginWir
Definition: DataStructs.h:379
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< float > EndChg
Definition: DataStructs.h:387
std::vector< int > IsShowerTj
Definition: DataStructs.h:395
std::vector< short > PlaneNum
Definition: DataStructs.h:392
void tca::ScoreVertices ( TCSlice slc)

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

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

Definition at line 3276 of file PFPUtils.cxx.

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

Referenced by DotProd(), and PrintTP3Ds().

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

Definition at line 764 of file Utils.cxx.

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

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

765  {
766  unsigned short ar = AngleRange(tp.Ang);
767  if (ar == tcc.angleRanges.size() - 1) {
768  // Very large angle
769  tp.AngleCode = 2;
770  }
771  else if (tcc.angleRanges.size() > 2 && ar == tcc.angleRanges.size() - 2) {
772  // Large angle
773  tp.AngleCode = 1;
774  }
775  else {
776  // Small angle
777  tp.AngleCode = 0;
778  }
779 
780  } // SetAngleCode
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< float > angleRanges
list of max angles for each angle range
Definition: DataStructs.h:562
unsigned short AngleRange(float angle)
Definition: Utils.cxx:783
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 3329 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().

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

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

2170  {
2171  // Sets the tj and 2D vertex score bits to true
2172 
2173  if (vx3.ID == 0) return;
2174 
2175  for (unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
2176  if (vx3.Vx2ID[ipl] <= 0) continue;
2177  VtxStore& vx2 = slc.vtxs[vx3.Vx2ID[ipl] - 1];
2178  vx2.Stat[kHiVx3Score] = false;
2179  // transfer this to all attached tjs and vertices attached to those tjs
2180  std::vector<int> tjlist = GetVtxTjIDs(slc, vx2);
2181  std::vector<int> vxlist;
2182  while (true) {
2183  // tag Tjs and make a list of attached vertices whose high-score
2184  // bit needs to be set
2185  vxlist.clear();
2186  for (auto tjid : tjlist) {
2187  auto& tj = slc.tjs[tjid - 1];
2188  tj.AlgMod[kTjHiVx3Score] = true;
2189  for (unsigned short end = 0; end < 2; ++end) {
2190  if (tj.VtxID[end] == 0) continue;
2191  auto& vx2 = slc.vtxs[tj.VtxID[end] - 1];
2192  if (vx2.Stat[kHiVx3Score]) continue;
2193  vx2.Stat[kHiVx3Score] = true;
2194  vxlist.push_back(vx2.ID);
2195  } // end
2196  } // tjid
2197 
2198  if (vxlist.empty()) break;
2199  // re-build tjlist using vxlist
2200  std::vector<int> newtjlist;
2201  for (auto vxid : vxlist) {
2202  auto& vx2 = slc.vtxs[vxid - 1];
2203  auto tmp = GetVtxTjIDs(slc, vx2);
2204  for (auto tjid : tmp) {
2205  if (std::find(tjlist.begin(), tjlist.end(), tjid) == tjlist.end())
2206  newtjlist.push_back(tjid);
2207  } // tjid
2208  } // vxid
2209  if (newtjlist.empty()) break;
2210  tjlist = newtjlist;
2211  } // true
2212  } // ipl
2213 
2214  } // SetHighScoreBits
matched to a high-score 3D vertex
Definition: DataStructs.h:92
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:2815
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 2574 of file PFPUtils.cxx.

References den.

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

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

Definition at line 3268 of file Utils.cxx.

References den.

3269  {
3270  double den = v1[0] * v1[0] + v1[1] * v1[1];
3271  if (den == 0) return false;
3272  den = sqrt(den);
3273 
3274  v1[0] *= mag / den;
3275  v1[1] *= mag / den;
3276  return true;
3277  } // 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:3259
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:3927
unsigned short FarEnd(const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3302
std::vector< int > GetAssns(TCSlice const &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4701
TDirectory * dir
Definition: macro.C:5
Vector3_t DirAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3251
void tca::SetPDGCode ( TCSlice slc,
unsigned short  itj 
)

Definition at line 4217 of file Utils.cxx.

References tca::TCSlice::tjs.

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

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

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

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

Definition at line 2756 of file PFPUtils.cxx.

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

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

2757  {
2758  // Determine which SectionFit this tp3d should reside in, then calculate
2759  // the 3D position and the distance from the center of the SectionFit
2760 
2761  if (tp3d.Wire < 0) return false;
2762  if (pfp.SectionFits.empty()) return false;
2763  if (pfp.SectionFits[0].Pos[0] == -10.0) return false;
2764  if (pfp.Flags[kSmallAngle]) return true;
2765 
2766  auto plnID = DecodeCTP(tp3d.CTP);
2767 
2768  if (pfp.SectionFits.size() == 1) { tp3d.SFIndex = 0; }
2769  else {
2770  // Find the section center that is closest to this point in the wire coordinate
2771  float best = 1E6;
2772  for (std::size_t sfi = 0; sfi < pfp.SectionFits.size(); ++sfi) {
2773  auto& sf = pfp.SectionFits[sfi];
2774  float sfWire = tcc.geom->WireCoordinate(geo::Point_t{0, sf.Pos[1], sf.Pos[2]}, plnID);
2775  float sep = std::abs(sfWire - tp3d.Wire);
2776  if (sep < best) {
2777  best = sep;
2778  tp3d.SFIndex = sfi;
2779  }
2780  } // sfi
2781  } // pfp.SectionFits.size() > 1
2782  auto& sf = pfp.SectionFits[tp3d.SFIndex];
2783  auto plnTP = MakeBareTP(detProp, sf.Pos, sf.Dir, tp3d.CTP);
2784  // the number of wires relative to the SectionFit center
2785  double dw = tp3d.Wire - plnTP.Pos[0];
2786  // dt/dW was stored in DeltaRMS
2787  double t = dw * plnTP.DeltaRMS;
2788  // define the 3D position
2789  for (unsigned short xyz = 0; xyz < 3; ++xyz)
2790  tp3d.Pos[xyz] = sf.Pos[xyz] + t * sf.Dir[xyz];
2791  tp3d.along = t;
2792  tp3d.Flags[kTP3DGood] = true;
2793  return true;
2794  } // SetSection
Length_t WireCoordinate(Point_t const &pos, PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
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:3927
const geo::GeometryCore * geom
Definition: DataStructs.h:569
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)
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:584
use the slowing-down strategy
Definition: DataStructs.h:496
std::vector< TjForecast > tjfs
Definition: DataStructs.cxx:10
use the stiff electron strategy
Definition: DataStructs.h:494
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2071
use the stiff muon strategy
Definition: DataStructs.h:495
void tca::SetTPEnvironment ( TCSlice slc,
CTP_t  inCTP 
)

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

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

Definition at line 2238 of file TCVertex.cxx.

References tca::TCSlice::vtxs.

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

2239  {
2240  // A version that sets the score of the last added vertex
2241  if (slc.vtxs.empty()) return;
2242  auto& vx2 = slc.vtxs[slc.vtxs.size() - 1];
2243  SetVx2Score(slc, vx2);
2244  } // SetVx2Score
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2247
void tca::SetVx2Score ( TCSlice slc,
VtxStore vx2 
)

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

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

2218  {
2219  // Calculate the 3D vertex score and flag Tjs that are attached to high score vertices as defined
2220  // by vtx2DCuts
2221 
2222  if (vx3.ID == 0) return;
2223 
2224  vx3.Score = 0;
2225  for (unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
2226  if (vx3.Vx2ID[ipl] <= 0) continue;
2227  VtxStore& vx2 = slc.vtxs[vx3.Vx2ID[ipl] - 1];
2228  vx3.Score += vx2.Score;
2229  } // ipl
2230  vx3.Score /= (float)slc.nPlanes;
2231  // don't allow it to get too small or negative
2232  if (vx3.Score < 0.001) vx3.Score = 0.001;
2233  if (vx3.Score > tcc.vtx2DCuts[7]) SetHighScoreBits(slc, vx3);
2234 
2235  } // SetVx3Score
TCConfig tcc
Definition: DataStructs.cxx:9
if(nlines<=0)
void SetHighScoreBits(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2169
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:543
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 1963 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().

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

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

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

Definition at line 1778 of file Utils.cxx.

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

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

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

Definition at line 1800 of file Utils.cxx.

References ChgFracBetween().

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

Definition at line 2005 of file PFPUtils.cxx.

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

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

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

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

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

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

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

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

Definition at line 792 of file PFPUtils.cxx.

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

Referenced by Match3PlanesSpt().

793  {
794  // returns true if a hit referenced in sptHits resides in the requested tpc. We assume
795  // that if one does, then all of them do
796 
797  unsigned int ahi = UINT_MAX;
798  for (auto ii : sptHits)
799  if (ii != UINT_MAX) {
800  ahi = ii;
801  break;
802  }
803  if (ahi >= (*evt.allHits).size()) return false;
804  // get a reference to the hit and see if it is in the desired tpc
805  auto& hit = (*evt.allHits)[ahi];
806  if (hit.WireID().TPC == tpc) return true;
807  return false;
808 
809  } // SptInTPC
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:615
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:564
Float_t sn
Definition: plot.C:23
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:615
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 4855 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().

4860  {
4861  // Start a trajectory located at fromHit with direction pointing to toHit
4862 
4863  auto& fromHit = (*evt.allHits)[slc.slHits[fromhit].allHitsIndex];
4864  auto& toHit = (*evt.allHits)[slc.slHits[tohit].allHitsIndex];
4865  float fromWire = fromHit.WireID().Wire;
4866  float fromTick = fromHit.PeakTime();
4867  float toWire = toHit.WireID().Wire;
4868  float toTick = toHit.PeakTime();
4869  CTP_t tCTP = EncodeCTP(fromHit.WireID());
4870  bool success = StartTraj(tj, fromWire, fromTick, toWire, toTick, tCTP, pass);
4871  if (!success) return false;
4872  // turn on debugging using the WorkID?
4873  if (tcc.modes[kDebug] && !tcc.dbgStp && !tcc.dbgDump && tcc.dbgSlc && tj.ID == debug.WorkID)
4874  tcc.dbgStp = true;
4875  if (tcc.dbgStp) {
4876  auto& tp = tj.Pts[0];
4877  mf::LogVerbatim("TC") << "StartTraj T" << tj.ID << " from " << (int)fromWire << ":"
4878  << (int)fromTick << " -> " << (int)toWire << ":" << (int)toTick
4879  << " StepDir " << tj.StepDir << " dir " << tp.Dir[0] << " " << tp.Dir[1]
4880  << " ang " << tp.Ang << " AngleCode " << tp.AngleCode << " angErr "
4881  << tp.AngErr << " ExpectedHitsRMS " << ExpectedHitsRMS(tp);
4882  } // tcc.dbgStp
4883  return true;
4884  } // 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:583
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
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:1910
bool StartTraj(Trajectory &tj, float fromWire, float fromTick, float toWire, float toTick, CTP_t &tCTP, unsigned short pass)
Definition: Utils.cxx:4887
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:600
unsigned int CTP_t
Definition: DataStructs.h:47
TDirectory * dir
Definition: macro.C:5
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:615
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:51
TCEvent evt
Definition: DataStructs.cxx:8
master switch for turning on debug mode
Definition: DataStructs.h:526
bool tca::StartTraj ( Trajectory tj,
float  fromWire,
float  fromTick,
float  toWire,
float  toTick,
CTP_t tCTP,
unsigned short  pass 
)

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

4894  {
4895  // Start a simple (seed) trajectory going from (fromWire, toTick) to (toWire, toTick).
4896 
4897  // decrement the work ID so we can use it for debugging problems
4898  --evt.WorkID;
4899  if (evt.WorkID == INT_MIN) evt.WorkID = -1;
4900  tj.ID = evt.WorkID;
4901  tj.Pass = pass;
4902  // Assume we are stepping in the positive WSE units direction
4903  short stepdir = 1;
4904  int fWire = std::nearbyint(fromWire);
4905  int tWire = std::nearbyint(toWire);
4906  if (tWire < fWire) { stepdir = -1; }
4907  else if (tWire == fWire) {
4908  // on the same wire
4909  if (toTick < fromTick) stepdir = -1;
4910  }
4911  tj.StepDir = stepdir;
4912  tj.CTP = tCTP;
4913  tj.ParentID = -1;
4914  tj.Strategy.reset();
4915  tj.Strategy[kNormal] = true;
4916 
4917  // create a trajectory point
4918  TrajPoint tp;
4919  if (!MakeBareTrajPoint(fromWire, fromTick, toWire, toTick, tCTP, tp)) return false;
4920  SetAngleCode(tp);
4921  tp.AngErr = 0.1;
4922  tj.Pts.push_back(tp);
4923  // turn on debugging using the WorkID?
4924  if (tcc.modes[kDebug] && !tcc.dbgStp && !tcc.dbgDump && tcc.dbgSlc && tj.ID == debug.WorkID)
4925  tcc.dbgStp = true;
4926  if (tcc.dbgStp) {
4927  auto& tp = tj.Pts[0];
4928  mf::LogVerbatim("TC") << "StartTraj T" << tj.ID << " from " << (int)fromWire << ":"
4929  << (int)fromTick << " -> " << (int)toWire << ":" << (int)toTick
4930  << " StepDir " << tj.StepDir << " dir " << tp.Dir[0] << " " << tp.Dir[1]
4931  << " ang " << tp.Ang << " AngleCode " << tp.AngleCode << " angErr "
4932  << tp.AngErr << " ExpectedHitsRMS " << ExpectedHitsRMS(tp);
4933  } // tcc.dbgStp
4934  return true;
4935 
4936  } // StartTraj
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:9
void SetAngleCode(TrajPoint &tp)
Definition: Utils.cxx:764
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:583
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
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:4057
float ExpectedHitsRMS(const TrajPoint &tp)
Definition: Utils.cxx:1910
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:600
TDirectory * dir
Definition: macro.C:5
TCEvent evt
Definition: DataStructs.cxx:8
master switch for turning on debug mode
Definition: DataStructs.h:526
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:3329
void UpdateTraj(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:705
std::vector< float > maxPos0
Definition: DataStructs.h:565
std::vector< unsigned short > minPtsFit
Reconstruct in several passes.
Definition: DataStructs.h:558
bool SignalAtTp(TrajPoint &tp)
Definition: Utils.cxx:1963
void SetPDGCode(TCSlice &slc, unsigned short itj)
Definition: Utils.cxx:4217
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:6032
void PrintTP(std::string someText, const TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, const TrajPoint &tp)
Definition: Utils.cxx:6131
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1060
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:575
float TrajPointSeparation(const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2612
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:2535
std::string PrintPos(const TrajPoint &tp)
Definition: Utils.cxx:6353
bool doForecast
See TCMode_t above.
Definition: DataStructs.h:601
std::vector< unsigned short > maxAngleCode
max allowed angle code for each pass
Definition: DataStructs.h:560
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:584
std::vector< float > maxPos1
Definition: DataStructs.h:566
use the slowing-down strategy
Definition: DataStructs.h:496
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2094
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:518
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:623
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2564
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
float maxWireSkipNoSignal
max number of wires to skip w/o a signal on them
Definition: DataStructs.h:574
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:579
float VLAStepSize
Definition: DataStructs.h:577
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:2071
TCEvent evt
Definition: DataStructs.cxx:8
bool StopIfBadFits(Trajectory &tj)
Definition: StepUtils.cxx:2729
void tca::StitchPFPs ( )

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

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

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

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

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

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

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

Definition at line 2715 of file Utils.cxx.

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

Referenced by CheckTraj().

2716  {
2717  // Characterizes the trajectory as a junk tj even though it may not
2718  // have been reconstructed in FindJunkTraj. The distinguishing feature is
2719  // that it is short and has many used hits in each trajectory point.
2720 
2721  // Don't bother if it is too long
2722  if (tj.Pts.size() > 10) return;
2723  if (tj.PDGCode == 111) return;
2724  // count the number of points that have many used hits
2725  unsigned short nhm = 0;
2726  unsigned short npwc = 0;
2727  for (auto& tp : tj.Pts) {
2728  if (tp.Chg == 0) continue;
2729  ++npwc;
2730  unsigned short nused = 0;
2731  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2732  if (tp.UseHit[ii]) ++nused;
2733  } // ii
2734  if (nused > 3) ++nhm;
2735  } // tp
2736  // Set the junkTj bit if most of the hits are used in most of the tps
2737  if (nhm > 0.5 * npwc) tj.AlgMod[kJunkTj] = true;
2738  if (prt)
2739  mf::LogVerbatim("TC") << "TGT: T" << tj.ID << " npwc " << npwc << " nhm " << nhm << " junk? "
2740  << tj.AlgMod[kJunkTj];
2741  } // 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:583
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:551
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:555
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:2071
bool TrajTrajDOCA(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2406
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 670 of file PFPUtils.cxx.

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

Referenced by Match3Planes().

676  {
677  // A TrajCluster analog of geometry IntersectionPoint that uses local wireIntersections with
678  // float precision. The (y,z) position is only used to match TPs between planes - not for 3D fitting
679  if (evt.wireIntersections.empty()) return false;
680  if (pln1 == pln2) return false;
681 
682  if (pln1 > pln2) {
683  std::swap(pln1, pln2);
684  std::swap(wir1, wir2);
685  }
686 
687  for (auto& wi : evt.wireIntersections) {
688  if (wi.pln1 != pln1) continue;
689  if (wi.pln2 != pln2) continue;
690  // estimate the position using the wire differences
691  double dw1 = wir1 - wi.wir1;
692  double dw2 = wir2 - wi.wir2;
693  y = (float)(wi.y + dw1 * wi.dydw1 + dw2 * wi.dydw2);
694  z = (float)(wi.z + dw1 * wi.dzdw1 + dw2 * wi.dzdw2);
695  return true;
696  } // wi
697  return false;
698  } // TCIntersectionPoint
Float_t y
Definition: compare.C:6
Double_t z
Definition: plot.C:276
std::vector< TCWireIntersection > wireIntersections
Definition: DataStructs.h:632
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 3490 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().

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

Definition at line 6187 of file Utils.cxx.

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

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

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

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

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

Definition at line 4090 of file Utils.cxx.

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

Referenced by CreateTP3D(), and DotProd().

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

Definition at line 1558 of file TCVertex.cxx.

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

1559  {
1560  // Returns the index of a vertex if tp is nearby
1561  for (unsigned short ivx = 0; ivx < slc.vtxs.size(); ++ivx) {
1562  if (slc.vtxs[ivx].ID == 0) continue;
1563  if (slc.vtxs[ivx].CTP != tp.CTP) continue;
1564  if (std::abs(slc.vtxs[ivx].Pos[0] - tp.Pos[0]) > 1.2) continue;
1565  if (std::abs(slc.vtxs[ivx].Pos[1] - tp.Pos[1]) > 1.2) continue;
1566  return ivx;
1567  } // ivx
1568  return USHRT_MAX;
1569  } // 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 2060 of file Utils.cxx.

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

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

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

2626  {
2627  // find the closest approach between a trajectory tj and a point (x,y). Returns
2628  // the index of the closest trajectory point and the distance. Returns false if none
2629  // of the points on the tj are within DOCA
2630 
2631  float close2 = DOCA * DOCA;
2632  closePt = 0;
2633  bool foundClose = false;
2634 
2635  for (unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1] + 1; ++ipt) {
2636  if (tj.Pts[ipt].Chg == 0) continue;
2637  float dx = tj.Pts[ipt].Pos[0] - x;
2638  if (std::abs(dx) > DOCA) continue;
2639  float dy = tj.Pts[ipt].Pos[1] - y;
2640  if (std::abs(dy) > DOCA) continue;
2641  float sep2 = dx * dx + dy * dy;
2642  if (sep2 < close2) {
2643  close2 = sep2;
2644  closePt = ipt;
2645  foundClose = true;
2646  }
2647  } // ipt
2648 
2649  DOCA = sqrt(close2);
2650  return foundClose;
2651 
2652  } // 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 1838 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().

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

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

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

Definition at line 2542 of file Utils.cxx.

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

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

Definition at line 2547 of file Utils.cxx.

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

2548  {
2549  // returns the intersection position, (x,y), of two trajectory points
2550 
2551  x = -9999;
2552  y = -9999;
2553 
2554  double arg1 = tp1.Pos[0] * tp1.Dir[1] - tp1.Pos[1] * tp1.Dir[0];
2555  double arg2 = tp2.Pos[0] * tp1.Dir[1] - tp2.Pos[1] * tp1.Dir[0];
2556  double arg3 = tp2.Dir[0] * tp1.Dir[1] - tp2.Dir[1] * tp1.Dir[0];
2557  if (arg3 == 0) return;
2558  double s = (arg1 - arg2) / arg3;
2559 
2560  x = (float)(tp2.Pos[0] + s * tp2.Dir[0]);
2561  y = (float)(tp2.Pos[1] + s * tp2.Dir[1]);
2562 
2563  } // 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 3357 of file Utils.cxx.

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

Referenced by DotProd(), and UpdateTraj().

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

Definition at line 2581 of file Utils.cxx.

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

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

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

Definition at line 2612 of file Utils.cxx.

References tca::TrajPoint::Pos.

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

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

Definition at line 2383 of file Utils.cxx.

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

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

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

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

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

Definition at line 2406 of file Utils.cxx.

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

2412  {
2413  return TrajTrajDOCA(slc, tj1, tj2, ipt1, ipt2, minSep, false);
2414  } // 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:2417
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 2417 of file Utils.cxx.

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

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

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

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

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

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

Definition at line 2655 of file Utils.cxx.

References tca::TrajPoint::Pos.

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

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

1061  {
1062  // Sets InTraj = 0 and UseHit false for all used hits in tp
1063  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1064  if (tp.UseHit[ii]) {
1065  slc.slHits[tp.Hits[ii]].InTraj = 0;
1066  tp.UseHit[ii] = false;
1067  } // UseHit
1068  } // ii
1069  tp.Chg = 0;
1070  } // UnsetUsedHits
bool tca::Update ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice slc,
PFPStruct pfp 
)

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

1056  {
1057  // This function only updates SectionFits that need to be re-sorted or re-fit. It returns
1058  // false if there was a serious error indicating that the pfp should be abandoned
1059  if (pfp.TP3Ds.empty() || pfp.SectionFits.empty()) return false;
1060 
1061  // special handling for small angle tracks
1062  if (pfp.AlgMod[kSmallAngle]) {
1063  for (unsigned short sfi = 0; sfi < pfp.SectionFits.size(); ++sfi) {
1064  auto& sf = pfp.SectionFits[sfi];
1065  if (!sf.NeedsUpdate) continue;
1066  if (!SortSection(pfp, sfi)) return false;
1067  sf.NPts = 0;
1068  sf.ChiDOF = 0;
1069  for (unsigned short ipt = 0; ipt < pfp.TP3Ds.size(); ++ipt) {
1070  auto& tp3d = pfp.TP3Ds[ipt];
1071  if (tp3d.SFIndex < sfi) continue;
1072  if (tp3d.SFIndex > sfi) break;
1073  ++sf.NPts;
1074  double delta = tp3d.Pos[0] - tp3d.TPX;
1075  sf.ChiDOF += delta * delta / tp3d.TPXErr2;
1076  } // ipt
1077  if (sf.NPts < 5) { sf.ChiDOF = 0; }
1078  else {
1079  sf.ChiDOF /= (float)(sf.NPts - 4);
1080  }
1081  sf.NeedsUpdate = false;
1082  } // sfi
1083  pfp.Flags[kNeedsUpdate] = false;
1084  return true;
1085  } // kSmallAngle
1086 
1087  for (std::size_t sfi = 0; sfi < pfp.SectionFits.size(); ++sfi) {
1088  auto& sf = pfp.SectionFits[sfi];
1089  if (!sf.NeedsUpdate) continue;
1090  if (!FitSection(detProp, slc, pfp, sfi)) return false;
1091  if (!SortSection(pfp, sfi)) return false;
1092  sf.NeedsUpdate = false;
1093  } // sfi
1094 
1095  // ensure that all points (good or not) have a valid SFIndex
1096  for (auto& tp3d : pfp.TP3Ds) {
1097  if (tp3d.SFIndex >= pfp.SectionFits.size()) SetSection(detProp, pfp, tp3d);
1098  } // tp3d
1099  pfp.Flags[kNeedsUpdate] = false;
1100  return true;
1101  } // Update
bool SortSection(PFPStruct &pfp, unsigned short sfIndex)
Definition: PFPUtils.cxx:2005
bool FitSection(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, unsigned short sfIndex)
Definition: PFPUtils.cxx:1398
bool SetSection(detinfo::DetectorPropertiesData const &detProp, PFPStruct &pfp, TP3D &tp3d)
Definition: PFPUtils.cxx:2756
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:2513
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:6353
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:43
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:564
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:2542
Float_t sn
Definition: plot.C:23
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2564
unsigned short FarEnd(const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3302
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:615
bool valsDecreasing(const SortEntry &c1, const SortEntry &c2)
Definition: Utils.cxx:38
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:3259
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:481
bool SetMag(Vector3_t &v1, double mag)
Definition: PFPUtils.cxx:2574
unsigned short FarEnd(const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3302
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:2558
std::array< double, 3 > Vector3_t
Definition: DataStructs.h:42
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:3380
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void FitTraj(TCSlice const &slc, Trajectory &tj)
Definition: Utils.cxx:797
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:2513
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice const &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3576
use the stiff electron strategy
Definition: DataStructs.h:494
void tca::UpdateTjChgProperties ( std::string  inFcnLabel,
TCSlice const &  slc,
Trajectory tj,
bool  prt 
)

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

3577  {
3578  // Updates properties of the tj that are affected when the TP environment
3579  // is changed. The most likely reason for a change is when the tj is attached to a
3580  // vertex in which case the Environment kEnvOverlap bit may be set by the UpdateVxEnvironment
3581  // function in which case this function is called.
3582  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) return;
3583 
3584  // first (un)set some bits
3585  for (auto& tp : tj.Pts) {
3586  if (tp.Chg <= 0) continue;
3587  tp.Environment[kEnvUnusedHits] = false;
3588  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3589  if (tp.UseHit[ii]) continue;
3590  unsigned int iht = tp.Hits[ii];
3591  if (slc.slHits[iht].InTraj == 0) tp.Environment[kEnvUnusedHits] = true;
3592  } // ii
3593  } // tp
3594 
3595  // Update the tj charge variables. The concept is explained by this graphic where
3596  // each column is a wire, Q = a TP with charge, q = a TP with charge that is an
3597  // EnvOverlap region, x = a wire that has a TP with Chg = 0 or a wire that has no TP
3598  // because the wire is dead, o = an EnvOverlap region, V = vertex attached to end. You should
3599  // imagine that all 3 tjs come from the same vertex
3600  // 01234567890123456789 npwc cnt range
3601  // VooooQQQQxxxQQQ 7 7 0 - 14
3602  // VqqqqQQQQxxxQQQQQQQQ 16 12 0 - 19
3603  // VooQQQ 3 3 0 - 5
3604  // The average is first calculated using Ave = sum(Q) / npwc
3605  // TotChg is calculated using
3606  tj.TotChg = 0;
3607  tj.AveChg = 0;
3608  tj.ChgRMS = 0.5;
3609 
3610  // These variables are used to calculate the average and rms using valid points with charge
3611  double vcnt = 0;
3612  double vsum = 0;
3613  double vsum2 = 0;
3614  // Reject a single large charge TP
3615  float bigChg = 0;
3616  for (unsigned short ipt = tj.EndPt[0] + 1; ipt < tj.EndPt[1]; ++ipt) {
3617  auto& tp = tj.Pts[ipt];
3618  if (tp.Chg > bigChg) bigChg = tp.Chg;
3619  } // ipt
3620  // variables for calculating the backup quanties. These are only used if npwc < 3
3621  double bcnt = 0;
3622  double bsum = 0;
3623  double bsum2 = 0;
3624  // don't include the end points
3625  for (unsigned short ipt = tj.EndPt[0] + 1; ipt < tj.EndPt[1]; ++ipt) {
3626  auto& tp = tj.Pts[ipt];
3627  if (tp.Chg <= 0) continue;
3628  // ignore the single large charge TP
3629  if (tp.Chg == bigChg) continue;
3630  // accumulate a backup sum in case most of the points are overlapped. Note that
3631  // tp.Chg has an angle correction, which is why the hit integral is summed
3632  // below. We don't care about this detail for the backup sum
3633  bsum += tp.Chg;
3634  bsum2 += tp.Chg * tp.Chg;
3635  if (tp.Chg > bigChg) bigChg = tp.Chg;
3636  ++bcnt;
3637  // Skip TPs that overlap with TPs on other Tjs. A correction will be made below
3638  if (tj.Pts[ipt].Environment[kEnvOverlap]) continue;
3639  ++vcnt;
3640  double tpchg = 0;
3641  for (unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
3642  if (!tp.UseHit[ii]) continue;
3643  unsigned int iht = tp.Hits[ii];
3644  tpchg += (*evt.allHits)[slc.slHits[iht].allHitsIndex].Integral();
3645  } // ii
3646  vsum += tpchg;
3647  vsum2 += tpchg * tpchg;
3648  } // ipt
3649 
3650  if (bcnt == 0) return;
3651 
3652  if (vcnt < 3) {
3653  // use the backup sum
3654  tj.TotChg = bsum;
3655  tj.AveChg = bsum / bcnt;
3656  if (vcnt > 2) {
3657  double arg = bsum2 - bcnt * tj.AveChg * tj.AveChg;
3658  if (arg > 0) tj.ChgRMS = sqrt(arg / (bcnt - 1));
3659  }
3660  for (auto& tp : tj.Pts)
3661  tp.AveChg = tj.AveChg;
3662  if (prt)
3663  mf::LogVerbatim("TC") << inFcnLabel << ".UpdateTjChgProperties: backup sum Set tj.AveChg "
3664  << (int)tj.AveChg << " ChgRMS " << tj.ChgRMS;
3665  return;
3666  } // low npwc
3667 
3668  double nWires = tj.EndPt[1] - tj.EndPt[0] + 1;
3669  if (nWires < 2) return;
3670  // correct for wires missing near vertices.
3671  // Count the number of wires between vertices at the ends and the first wire
3672  // that has charge. This code assumes that there should be one TP on each wire
3673  if (!tj.AlgMod[kPhoton]) {
3674  for (unsigned short end = 0; end < 2; ++end) {
3675  if (tj.VtxID[end] == 0) continue;
3676  auto& tp = tj.Pts[tj.EndPt[end]];
3677  auto& vx2 = slc.vtxs[tj.VtxID[end] - 1];
3678  int dw = std::abs(tp.Pos[0] - vx2.Pos[0]);
3679  // This assumes that the vertex is not inside the wire boundaries of the tj
3680  nWires += dw;
3681  } // end
3682  } // not a photon Tj
3683 
3684  tj.AveChg = vsum / vcnt;
3685  // calculate the total charge using the tj wire range
3686  tj.TotChg = nWires * tj.AveChg;
3687  // calculate the rms
3688  double arg = vsum2 - vcnt * tj.AveChg * tj.AveChg;
3689  double rms = 0.5;
3690  if (arg > 0) rms = sqrt(arg / (vcnt - 1));
3691  rms /= tj.AveChg;
3692  // don't let it be an unrealistically low value. It could be crazy large however.
3693  if (rms < 0.1) rms = 0.1;
3694  // Don't let the calculated charge RMS dominate until it is well known; after there are 5 - 10 valid TPs.
3695  // Set the starting charge rms = 0.5
3696  if (vcnt < 10) {
3697  double defFrac = 1 / vcnt;
3698  rms = defFrac * 0.5 + (1 - defFrac) * rms;
3699  }
3700  tj.ChgRMS = rms;
3701  if (prt)
3702  mf::LogVerbatim("TC") << inFcnLabel << ".UpdateTjChgProperties: Set tj.AveChg "
3703  << (int)tj.AveChg << " ChgRMS " << tj.ChgRMS;
3704 
3705  // Update the TP charge pulls.
3706  // Don't let the calculated charge RMS dominate the default
3707  // RMS until it is well known. Start with 50% error on the
3708  // charge RMS
3709  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
3710  auto& tp = tj.Pts[ipt];
3711  if (tp.Chg <= 0) continue;
3712  tp.ChgPull = (tp.Chg / tj.AveChg - 1) / tj.ChgRMS;
3713  } // ipt
3714 
3715  // update the local charge average using NPtsAve of the preceding points.
3716  // Handle short Tjs first.
3717  if (vcnt < tcc.nPtsAve) {
3718  for (auto& tp : tj.Pts)
3719  tp.AveChg = tj.AveChg;
3720  return;
3721  }
3722 
3723  // Set the local average to 0 first
3724  for (auto& tp : tj.Pts)
3725  tp.AveChg = 0;
3726  // Enter the local average on the points where an average can be calculated
3727  unsigned short nptsave = tcc.nPtsAve;
3728  unsigned short minPt = tj.EndPt[0] + nptsave;
3729  float lastAve = 0;
3730  for (unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
3731  unsigned short ipt = tj.EndPt[1] - ii;
3732  if (ipt < minPt) break;
3733  float cnt = 0;
3734  float sum = 0;
3735  for (unsigned short iii = 0; iii < nptsave; ++iii) {
3736  unsigned short iipt = ipt - iii;
3737  // Don't include the charge of the first point
3738  if (iipt == tj.EndPt[0]) break;
3739  auto& tp = tj.Pts[iipt];
3740  if (tp.Chg <= 0) continue;
3741  sum += tp.Chg;
3742  ++cnt;
3743  } // iii
3744  if (cnt > 2) {
3745  tj.Pts[ipt].AveChg = sum / cnt;
3746  lastAve = tj.Pts[ipt].AveChg;
3747  }
3748  } // ii
3749  // Fill in the points where no average was calculated
3750  for (unsigned short ii = tj.EndPt[0]; ii <= tj.EndPt[1]; ++ii) {
3751  unsigned short ipt = tj.EndPt[1] - ii;
3752  auto& tp = tj.Pts[ipt];
3753  if (tp.AveChg == 0) { tp.AveChg = lastAve; }
3754  else {
3755  lastAve = tp.AveChg;
3756  }
3757  } // ii
3758 
3759  tj.NeedsUpdate = false;
3760 
3761  } // 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:599
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:615
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:3380
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
void FitTraj(TCSlice const &slc, Trajectory &tj)
Definition: Utils.cxx:797
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3329
std::vector< unsigned short > minPtsFit
Reconstruct in several passes.
Definition: DataStructs.h:558
void UpdateDeltaRMS(Trajectory &tj)
Definition: StepUtils.cxx:2542
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1060
void SetAngleCode(TrajPoint &tp)
Definition: Utils.cxx:764
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2513
void UpdateStiffEl(TCSlice const &slc, Trajectory &tj)
Definition: StepUtils.cxx:682
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:584
use the slowing-down strategy
Definition: DataStructs.h:496
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2094
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:518
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:3576
std::vector< short > muonTag
Definition: DataStructs.h:548
use the stiff electron strategy
Definition: DataStructs.h:494
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2071
bool TrajIsClean(Trajectory const &tj, bool prt)
Definition: Utils.cxx:3357
use the stiff muon strategy
Definition: DataStructs.h:495
void tca::UpdateVxEnvironment ( TCSlice slc)

Definition at line 3764 of file Utils.cxx.

References kEnvOverlap, kKilled, tca::TCSlice::tjs, and tca::TCSlice::vtxs.

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

3765  {
3766  // Set the kEnvOverlap bit true for all TPs that are close to other
3767  // trajectories that are close to vertices. The positions of TPs that
3768  // overlap are biased and shouldn't be used in a vertex fit. Also, these
3769  // TPs shouldn't be used to calculate dE/dx. The kEnvOverlap bit is first cleared
3770  // for ALL TPs and then set for ALL 2D vertices
3771 
3772  for (auto& tj : slc.tjs) {
3773  if (tj.AlgMod[kKilled]) continue;
3774  for (auto& tp : tj.Pts)
3775  tp.Environment[kEnvOverlap] = false;
3776  } // tj
3777 
3778  for (auto& vx : slc.vtxs) {
3779  if (vx.ID <= 0) continue;
3780  UpdateVxEnvironment(slc, vx, false);
3781  } // vx
3782 
3783  } // UpdateVxEnvironment
void UpdateVxEnvironment(TCSlice &slc, VtxStore &vx2, bool prt)
Definition: Utils.cxx:3786
void tca::UpdateVxEnvironment ( TCSlice slc,
VtxStore vx2,
bool  prt 
)

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

3787  {
3788  // Update the Environment each TP on trajectories near the vertex
3789 
3790  if (vx2.ID == 0) return;
3791  if (vx2.Stat[kOnDeadWire]) return;
3792 
3793  if (prt) mf::LogVerbatim("TC") << "UpdateVxEnvironment check Tjs attached to vx2 " << vx2.ID;
3794 
3795  std::vector<int> tjlist;
3796  std::vector<unsigned short> tjends;
3797  if (vx2.Pos[0] < -0.4) return;
3798  unsigned int vxWire = std::nearbyint(vx2.Pos[0]);
3799  unsigned int loWire = vxWire;
3800  unsigned int hiWire = vxWire;
3801  for (auto& tj : slc.tjs) {
3802  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
3803  if (tj.CTP != vx2.CTP) continue;
3804  // ignore photon Tjs
3805  if (tj.AlgMod[kPhoton]) continue;
3806  for (unsigned short end = 0; end < 2; ++end) {
3807  if (tj.VtxID[end] != vx2.ID) continue;
3808  tjlist.push_back(tj.ID);
3809  tjends.push_back(end);
3810  if (tj.Pts[tj.EndPt[end]].Pos[0] < -0.4) return;
3811  unsigned int endWire = std::nearbyint(tj.Pts[tj.EndPt[end]].Pos[0]);
3812  if (endWire < loWire) loWire = endWire;
3813  if (endWire > hiWire) hiWire = endWire;
3814  } // end
3815  } // tj
3816  if (tjlist.size() < 2) return;
3817  if (hiWire < loWire + 1) return;
3818  if (prt)
3819  mf::LogVerbatim("TC") << " check Tjs on wires in the range " << loWire << " to " << hiWire;
3820 
3821  // create a vector of TPs between loWire and hiWire for every tj in the list
3822  // wire TP
3823  std::vector<std::vector<TrajPoint>> wire_tjpt;
3824  // companion vector of IDs
3825  std::vector<int> tjids;
3826  // populate this vector with TPs on Tjs that are in this range
3827  unsigned short nwires = hiWire - loWire + 1;
3828  for (unsigned short itj = 0; itj < tjlist.size(); ++itj) {
3829  auto& tj = slc.tjs[tjlist[itj] - 1];
3830  unsigned short end = tjends[itj];
3831  std::vector<TrajPoint> tjpt(nwires);
3832  // first enter valid TPs in the range
3833  for (unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
3834  unsigned short ipt;
3835  if (end == 0) { ipt = tj.EndPt[0] + ii; }
3836  else {
3837  ipt = tj.EndPt[1] - ii;
3838  }
3839  if (ipt > tj.Pts.size() - 1) break;
3840  // Make a copy of the TP so we can alter it
3841  auto tp = tj.Pts[ipt];
3842  if (tp.Chg <= 0) continue;
3843  tp.Chg = 1;
3844  tp.Hits.clear();
3845  if (tp.Pos[0] < -0.4) continue;
3846  unsigned int wire = std::nearbyint(tp.Pos[0]);
3847  unsigned short indx = wire - loWire;
3848  if (indx > nwires - 1) break;
3849  tp.Step = ipt;
3850  // We will use NTPsFit to count the number of neighboring TPs
3851  tp.NTPsFit = 0;
3852  tjpt[indx] = tp;
3853  } // ii
3854  // next make TPs on the wires that don't have real TPs
3855  TrajPoint ltp;
3856  // put ltp at the vertex position with direction towards the end point
3857  MakeBareTrajPoint(vx2.Pos, tj.Pts[tj.EndPt[end]].Pos, ltp);
3858  if (ltp.Dir[0] == 0) continue;
3859  if (ltp.Pos[0] < -0.4) continue;
3860  unsigned int wire = std::nearbyint(ltp.Pos[0]);
3861  ltp.Chg = 0;
3862  unsigned short indx = wire - loWire;
3863  // Break if we found a real TP
3864  if (tjpt[indx].Chg == 0) tjpt[indx] = ltp;
3865  double stepSize = std::abs(1 / ltp.Dir[0]);
3866  for (unsigned short ii = 0; ii < nwires; ++ii) {
3867  // move the local TP position by one step in the right direction
3868  for (unsigned short iwt = 0; iwt < 2; ++iwt)
3869  ltp.Pos[iwt] += ltp.Dir[iwt] * stepSize;
3870  if (ltp.Pos[0] < -0.4) break;
3871  wire = std::nearbyint(ltp.Pos[0]);
3872  if (wire < loWire || wire > hiWire) break;
3873  indx = wire - loWire;
3874  if (tjpt[indx].Chg > 0) continue;
3875  tjpt[indx] = ltp;
3876  } // ii
3877  if (prt) {
3878  mf::LogVerbatim myprt("TC");
3879  myprt << " T" << tj.ID;
3880  for (auto& tp : tjpt)
3881  myprt << " " << PrintPos(tp.Pos) << "_" << tp.Step << "_" << (int)tp.Chg;
3882  }
3883  wire_tjpt.push_back(tjpt);
3884  tjids.push_back(tj.ID);
3885  } // itj
3886 
3887  // iterate over the wires in the range
3888  for (unsigned short indx = 0; indx < nwires; ++indx) {
3889  // count the number of valid points on this wire
3890  unsigned short npts = 0;
3891  // count the number of points on this wire that have charge
3892  unsigned short npwc = 0;
3893  for (unsigned short itj = 0; itj < wire_tjpt.size(); ++itj) {
3894  if (wire_tjpt[itj][indx].Pos[0] == 0) continue;
3895  // found a valid point
3896  ++npts;
3897  if (wire_tjpt[itj][indx].Chg > 0) ++npwc;
3898  } // itj
3899  // no valid points
3900  if (npts == 0) continue;
3901  // all valid points have charge
3902  if (npwc == npts) continue;
3903  // re-find the valid points with charge and set the kEnvOverlap bit
3904  for (unsigned short itj = 0; itj < wire_tjpt.size(); ++itj) {
3905  if (wire_tjpt[itj][indx].Pos[0] == 0) continue;
3906  if (wire_tjpt[itj][indx].Chg == 0) continue;
3907  auto& tj = slc.tjs[tjids[itj] - 1];
3908  unsigned short ipt = wire_tjpt[itj][indx].Step;
3909  tj.Pts[ipt].Environment[kEnvOverlap] = true;
3910  tj.NeedsUpdate = true;
3911  if (prt) mf::LogVerbatim("TC") << " Set kEnvOverlap bit on T" << tj.ID << " ipt " << ipt;
3912  } // itj
3913  } // indx
3914 
3915  // update the charge rms for those tjs whose environment was changed above
3916  // (or elsewhere)
3917  for (auto tjid : tjids) {
3918  auto& tj = slc.tjs[tjid - 1];
3919  if (!tj.NeedsUpdate) continue;
3920  if (tj.CTP != vx2.CTP) continue;
3921  UpdateTjChgProperties("UVxE", slc, tj, prt);
3922  } // tjid
3923 
3924  } // 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:6359
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:4057
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice const &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3576
bool tca::ValidTwoPlaneMatch ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice slc,
const PFPStruct pfp 
)

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

1780  {
1781  // This function checks the third plane in the PFP when only two Tjs are 3D-matched to
1782  // ensure that the reason for the lack of a 3rd plane match is that it is in a dead region.
1783  // This function should be used after an initial fit is done and the TP3Ds are sorted
1784  if (pfp.TjIDs.size() != 2) return false;
1785  if (slc.nPlanes != 3) return false;
1786  if (pfp.TP3Ds.empty()) return false;
1787 
1788  // find the third plane
1789  std::vector<unsigned short> planes;
1790  for (auto tid : pfp.TjIDs)
1791  planes.push_back(DecodeCTP(slc.tjs[tid - 1].CTP).Plane);
1792  unsigned short thirdPlane = 3 - planes[0] - planes[1];
1793  CTP_t inCTP = EncodeCTP(slc.TPCID.Cryostat, slc.TPCID.TPC, thirdPlane);
1794  // Project the 3D position at the start into the third plane
1795  auto tp = MakeBareTP(detProp, pfp.TP3Ds[0].Pos, inCTP);
1796  unsigned int wire0 = 0;
1797  if (tp.Pos[0] > 0) wire0 = std::nearbyint(tp.Pos[0]);
1798  if (wire0 > slc.nWires[thirdPlane]) wire0 = slc.nWires[thirdPlane];
1799  // Do the same for the end
1800  unsigned short lastPt = pfp.TP3Ds.size() - 1;
1801  tp = MakeBareTP(detProp, pfp.TP3Ds[lastPt].Pos, inCTP);
1802  unsigned int wire1 = 0;
1803  if (tp.Pos[0] > 0) wire1 = std::nearbyint(tp.Pos[0]);
1804  if (wire1 > slc.nWires[thirdPlane]) wire1 = slc.nWires[thirdPlane];
1805  if (wire0 == wire1) return !evt.goodWire[thirdPlane][wire0];
1806  if (wire1 < wire0) std::swap(wire0, wire1);
1807  // count the number of good wires
1808  int dead = 0;
1809  int wires = wire1 - wire0;
1810  for (unsigned int wire = wire0; wire < wire1; ++wire)
1811  if (!evt.goodWire[thirdPlane][wire]) ++dead;
1812  // require that most of the wires are dead
1813  return (dead > 0.8 * wires);
1814  } // ValidTwoPlaneMatch
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:623
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const Point3_t &pos, CTP_t inCTP)
Definition: Utils.cxx:3927
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:481
unsigned int CTP_t
Definition: DataStructs.h:47
geo::PlaneID DecodeCTP(CTP_t CTP)
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:51
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 1871 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().

1872  {
1873  // Calculates the position pull between two vertices
1874  double dx = vx1.X - vx2.X;
1875  double dy = vx1.Y - vx2.Y;
1876  double dz = vx1.Z - vx2.Z;
1877  double dxErr2 = (vx1.XErr * vx1.XErr + vx2.XErr * vx2.XErr) / 2;
1878  double dyErr2 = (vx1.YErr * vx1.YErr + vx2.YErr * vx2.YErr) / 2;
1879  double dzErr2 = (vx1.ZErr * vx1.ZErr + vx2.ZErr * vx2.ZErr) / 2;
1880  dx = dx * dx / dxErr2;
1881  dy = dy * dy / dyErr2;
1882  dz = dz * dz / dzErr2;
1883  return (float)(sqrt(dx + dy + dz) / 3);
1884  }
float tca::VertexVertexPull ( const VtxStore vx1,
const VtxStore vx2 
)

Definition at line 1887 of file TCVertex.cxx.

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

1888  {
1889  // Calculates the position pull between two vertices
1890  double dw = vx1.Pos[0] - vx2.Pos[0];
1891  double dt = vx1.Pos[1] - vx2.Pos[1];
1892  double dwErr2 = (vx1.PosErr[0] * vx1.PosErr[0] + vx2.PosErr[0] * vx2.PosErr[0]) / 2;
1893  double dtErr2 = (vx1.PosErr[1] * vx1.PosErr[1] + vx2.PosErr[1] * vx2.PosErr[1]) / 2;
1894  dw = dw * dw / dwErr2;
1895  dt = dt * dt / dtErr2;
1896  return (float)sqrt(dw + dt);
1897  }
bool tca::WireHitRangeOK ( TCSlice const &  slc,
const CTP_t inCTP 
)

Definition at line 4508 of file Utils.cxx.

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

Referenced by DotProd(), and FindCloseHits().

4509  {
4510  // returns true if the passed CTP code is consistent with the CT code of the WireHitRangeVector
4511  geo::PlaneID planeID = DecodeCTP(inCTP);
4512  if (planeID.Cryostat != slc.TPCID.Cryostat) return false;
4513  if (planeID.TPC != slc.TPCID.TPC) return false;
4514  return true;
4515  }
The data type to uniquely identify a Plane.
Definition: geo_types.h:463
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:211
geo::PlaneID DecodeCTP(CTP_t CTP)
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:399
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 49 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::CalorPad::Draw(), evd::Display3DPad::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 277 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 48 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().