All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Namespaces | Classes | Typedefs | Enumerations | Functions | Variables
tca Namespace Reference

Namespaces

 detail
 

Classes

struct  VtxStore
 struct of temporary 2D vertices (end points) More...
 
struct  Vtx3Store
 struct of temporary 3D vertices More...
 
struct  TCWireIntersection
 
struct  Tj2Pt
 
struct  TrajPoint
 
struct  ParFit
 
struct  Trajectory
 
struct  TjForecast
 
struct  TrajPoint3
 
struct  SectionFit
 
struct  TP3D
 
struct  MatchStruct
 
struct  PFPStruct
 
struct  ShowerPoint
 
struct  ShowerStruct
 
struct  ShowerStruct3D
 
struct  DontClusterStruct
 
struct  ShowerTreeVars
 
struct  CRTreeVars
 
struct  TCConfig
 
struct  TCHit
 
struct  TCEvent
 
struct  TCSlice
 
struct  DebugStuff
 
struct  HistStuff
 
class  TrajClusterAlg
 

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::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, bool prt)
 
bool ReSection (detinfo::DetectorClocksData const &clockData, 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::DetectorClocksData const &clockData, 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, float &chiDOF)
 
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::DetectorClocksData const &clockData, 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 (TCSlice &slc, PFPStruct &pfp)
 
void FillmAllTraj (detinfo::DetectorPropertiesData const &detProp, TCSlice &slc)
 
TP3D MakeTP3D (detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, 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, const TCSlice &slc, PFPStruct &pfp, TP3D &tp3d)
 
float PointPull (const PFPStruct &pfp, const TP3D &tp3d)
 
PFPStruct CreatePFP (const TCSlice &slc)
 
void PFPVertexCheck (TCSlice &slc)
 
void DefinePFPParents (TCSlice &slc, bool prt)
 
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 TCSlice &slc, 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 &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 (TCSlice &slc, Trajectory &tj)
 
void MaskBadTPs (TCSlice &slc, Trajectory &tj, float const &maxChi)
 
bool MaskedHitsOK (TCSlice &slc, Trajectory &tj)
 
bool StopIfBadFits (TCSlice &slc, Trajectory &tj)
 
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 (TCSlice &slc, const Trajectory &tj)
 
void EndMerge (TCSlice &slc, CTP_t inCTP, bool lastPass)
 
void MaskTrajEndPoints (TCSlice &slc, Trajectory &tj, unsigned short nPts)
 
void ChkStop (TCSlice &slc, Trajectory &tj)
 
bool ChkMichel (TCSlice &slc, Trajectory &tj, unsigned short &lastGoodPt)
 
bool MakeJunkTraj (TCSlice &slc, std::vector< unsigned int > tHits)
 
void SaveCRInfo (detinfo::DetectorClocksData const &clockData, TCSlice &slc, PFPStruct &pfp, bool prt, 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 &slc, const std::vector< int > TjIDs)
 
void ShowerParams (double showerEnergy, double &shMaxAlong, double &along95)
 
double ShowerParamTransRMS (double showerEnergy, double along)
 
double InShowerProbLong (double showerEnergy, double along)
 
double InShowerProbTrans (double showerEnergy, double along, double trans)
 
double InShowerProbParam (double showerEnergy, double along, double trans)
 
float InShowerProb (TCSlice &slc, const ShowerStruct3D &ss3, const PFPStruct &pfp)
 
float InShowerProb (TCSlice &slc, const ShowerStruct &ss, const Trajectory &tj)
 
float ParentFOM (std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, unsigned short pend, ShowerStruct3D &ss3, bool prt)
 
float ParentFOM (std::string inFcnLabel, TCSlice &slc, Trajectory &tj, unsigned short &tjEnd, ShowerStruct &ss, float &tp1Sep, float &vx2Score, bool prt)
 
bool WrongSplitTj (std::string inFcnLabel, TCSlice &slc, Trajectory &tj, unsigned short tjEnd, ShowerStruct &ss, bool prt)
 
void MergeNearby2DShowers (std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
 
void MergeOverlap (std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
 
void MergeShowerChain (std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
 
void MergeSubShowersTj (std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
 
void MergeSubShowers (std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
 
int MergeShowers (std::string inFcnLabel, TCSlice &slc, std::vector< int > ssIDs, bool prt)
 
bool MergeShowersAndStore (std::string inFcnLabel, TCSlice &slc, int icotID, int jcotID, bool prt)
 
bool MergeShowerTjsAndStore (TCSlice &slc, unsigned short istj, unsigned short jstj, bool prt)
 
bool AnalyzeRotPos (std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
 
void ReverseShower (std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
 
void ReverseShower (std::string inFcnLabel, TCSlice &slc, int cotID, bool prt)
 
void MakeShowerObsolete (std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
 
void MakeShowerObsolete (std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
 
bool DontCluster (TCSlice &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
 
void TagShowerLike (std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP)
 
void FindNearbyTjs (std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
 
void AddCloseTjsToList (TCSlice &slc, unsigned short itj, std::vector< int > list)
 
void DefineEnvelope (std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
 
bool AddTjsInsideEnvelope (std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
 
bool AddLooseHits (TCSlice &slc, int cotID, bool prt)
 
void FindStartChg (std::string inFcnLabel, TCSlice &slc, int cotID, bool prt)
 
std::vector< float > StartChgVec (TCSlice &slc, int cotID, bool prt)
 
void DumpShowerPts (TCSlice &slc, int cotID)
 
bool TransferTjHits (TCSlice &slc, bool prt)
 
int GetCotID (TCSlice &slc, int ShowerTjID)
 
double ShowerEnergy (const ShowerStruct3D &ss3)
 
float ShowerEnergy (TCSlice &slc, const std::vector< int > tjIDs)
 
float ChgToMeV (float chg)
 
bool StoreShower (std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3)
 
bool StoreShower (std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss)
 
ShowerStruct3D CreateSS3 (TCSlice &slc)
 
ShowerStruct CreateSS (TCSlice &slc, const std::vector< int > &tjl)
 
bool ChkAssns (std::string inFcnLabel, TCSlice &slc)
 
void PrintShowers (detinfo::DetectorPropertiesData const &detProp, std::string fcnLabel, TCSlice &slc)
 
void Print2DShowers (std::string someText, TCSlice &slc, CTP_t inCTP, bool printKilledShowers)
 
void PrintShower (std::string someText, TCSlice &slc, const ShowerStruct &ss, bool printHeader, bool printExtras)
 
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, std::string stageName)
 
void SaveAllCots (TCSlice &slc, const CTP_t &inCTP, std::string someText)
 
void SaveAllCots (TCSlice &slc, std::string someText)
 
int GetStageNum (ShowerTreeVars &stv, std::string stageName)
 
void ClearShowerTree (ShowerTreeVars &stv)
 
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 TCSlice &slc, const TrajPoint &tp, const VtxStore &vx)
 
float VertexVertexPull (const TCSlice &slc, const Vtx3Store &vx1, const Vtx3Store &vx2)
 
float VertexVertexPull (const TCSlice &slc, const VtxStore &vx1, const VtxStore &vx2)
 
bool StoreVertex (TCSlice &slc, VtxStore &vx)
 
bool FitVertex (TCSlice &slc, VtxStore &vx, bool prt)
 
bool FitVertex (TCSlice &slc, VtxStore &vx, std::vector< TrajPoint > &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 (TCSlice &slc, 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 TCSlice &slc, 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 > &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 TCSlice &slc, const PFPStruct &pfp)
 
bool MergeTjIntoPFP (TCSlice &slc, int mtjid, PFPStruct &pfp, bool prt)
 
float PointPull (TCSlice &slc, Point2_t pos, float chg, const Trajectory &tj)
 
bool CompatibleMerge (const TCSlice &slc, std::vector< int > &tjIDs, bool prt)
 
bool CompatibleMerge (const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, bool prt)
 
float OverlapFraction (const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2)
 
unsigned short AngleRange (TrajPoint const &tp)
 
void SetAngleCode (TrajPoint &tp)
 
unsigned short AngleRange (float angle)
 
void FitTraj (TCSlice &slc, Trajectory &tj)
 
void FitTraj (TCSlice &slc, Trajectory &tj, unsigned short originPt, unsigned short npts, short fitDir, TrajPoint &tpFit)
 
unsigned short GetPFPIndex (const TCSlice &slc, int tjID)
 
void ReleaseHits (TCSlice &slc, Trajectory &tj)
 
void UnsetUsedHits (TCSlice &slc, TrajPoint &tp)
 
bool StoreTraj (TCSlice &slc, Trajectory &tj)
 
void FitPar (const TCSlice &slc, 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 &slc, Trajectory &tj, bool prt)
 
void ChkChgAsymmetry (TCSlice &slc, Trajectory &tj, bool prt)
 
bool SignalBetween (const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2, const float &MinWireSignalFraction)
 
bool SignalBetween (const TCSlice &slc, TrajPoint tp, float toPos0, const float &MinWireSignalFraction)
 
float ChgFracBetween (const TCSlice &slc, TrajPoint tp, float toPos0)
 
bool TrajHitsOK (TCSlice &slc, const std::vector< unsigned int > &iHitsInMultiplet, const std::vector< unsigned int > &jHitsInMultiplet)
 
bool TrajHitsOK (TCSlice &slc, const unsigned int iht, const unsigned int jht)
 
float ExpectedHitsRMS (TCSlice &slc, const TrajPoint &tp)
 
bool 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 (const TCSlice &slc, 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 TCSlice &slc, 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 (const TCSlice &slc, float wire, float time, TrajPoint const &tp)
 
float PointTrajDOCA2 (const TCSlice &slc, float wire, float time, TrajPoint const &tp)
 
void TrajIntersection (TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
 
void TrajIntersection (TrajPoint const &tp1, TrajPoint const &tp2, float &x, float &y)
 
float MaxTjLen (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 (TCSlice &slc, 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 &slc, TrajPoint &tp, float const &maxDelta, HitStatus_t hitRequest)
 
unsigned short NearbyCleanPt (const TCSlice &slc, 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 &slc, Trajectory &tj1, unsigned short end1, Trajectory &tj2, unsigned short end2, unsigned short nPtsFit, bool useChg, bool prt)
 
float KinkSignificance (TCSlice &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 (TCSlice &slc, Trajectory &tj)
 
bool PointInsideEnvelope (const Point2_t &Point, const std::vector< Point2_t > &Envelope)
 
bool SetMag (Vector2_t &v1, double mag)
 
void FindAlongTrans (Point2_t pos1, Vector2_t dir1, Point2_t pos2, Point2_t &alongTrans)
 
double DeltaAngle (const Point2_t &p1, const Point2_t &p2)
 
double DeltaAngle2 (double Ang1, double Ang2)
 
double DeltaAngle (double Ang1, double Ang2)
 
void SetEndPoints (Trajectory &tj)
 
bool TrajIsClean (TCSlice &slc, Trajectory &tj, bool prt)
 
short MCSMom (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 TCSlice &slc, const Trajectory &tj, unsigned short thePt)
 
float MCSThetaRMS (const TCSlice &slc, const Trajectory &tj)
 
double MCSThetaRMS (const TCSlice &slc, const Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
 
void TjDeltaRMS (const TCSlice &slc, 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 &slc, Trajectory &tj, bool prt)
 
void UpdateVxEnvironment (TCSlice &slc)
 
void UpdateVxEnvironment (TCSlice &slc, VtxStore &vx2, bool prt)
 
TrajPoint MakeBareTP (detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const Point3_t &pos, CTP_t inCTP)
 
TrajPoint MakeBareTP (detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, 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 (const TCSlice &slc, float fromWire, float fromTick, float toWire, float toTick, CTP_t tCTP, TrajPoint &tp)
 
bool MakeBareTrajPoint (const Point2_t &fromPos, const Point2_t &toPos, TrajPoint &tpOut)
 
bool MakeBareTrajPoint (const TCSlice &slc, const TrajPoint &tpIn1, const TrajPoint &tpIn2, TrajPoint &tpOut)
 
unsigned short FarEnd (TCSlice &slc, const Trajectory &tj, const Point2_t &pos)
 
Vector2_t PointDirection (const Point2_t p1, const Point2_t p2)
 
float TPHitsRMSTime (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 NumUsedHitsInTj (const TCSlice &slc, const Trajectory &tj)
 
unsigned short NumHitsInTP (const TrajPoint &tp, HitStatus_t hitRequest)
 
void SetPDGCode (TCSlice &slc, unsigned short itj)
 
void SetPDGCode (TCSlice &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 &slc, const CTP_t &inCTP)
 
bool MergeAndStore (TCSlice &slc, unsigned int itj1, unsigned int itj2, bool doPrt)
 
std::vector< int > GetAssns (TCSlice &slc, std::string type1Name, int id, std::string type2Name)
 
bool StartTraj (TCSlice &slc, Trajectory &tj, unsigned int fromhit, unsigned int tohit, unsigned short pass)
 
bool StartTraj (TCSlice &slc, Trajectory &tj, float fromWire, float fromTick, float toWire, float toTick, CTP_t &tCTP, unsigned short pass)
 
std::pair< unsigned short,
unsigned short > 
GetSliceIndex (std::string typeName, int uID)
 
bool Fit2D (short mode, Point2_t inPt, float &inPtErr, Vector2_t &outVec, Vector2_t &outVecErr, float &chiDOF)
 
bool DecodeDebugString (std::string strng)
 
void DumpTj ()
 
void PrintDebugMode ()
 
void PrintAll (detinfo::DetectorPropertiesData const &detProp, std::string someText)
 
void PrintP (std::string someText, mf::LogVerbatim &myprt, PFPStruct &pfp, bool &printHeader)
 
void Print3V (detinfo::DetectorPropertiesData const &detProp, std::string someText, mf::LogVerbatim &myprt, Vtx3Store &vx3, bool &printHeader)
 
void Print2V (std::string someText, mf::LogVerbatim &myprt, VtxStore &vx2, bool &printHeader)
 
void Print3S (detinfo::DetectorPropertiesData const &detProp, std::string someText, mf::LogVerbatim &myprt, ShowerStruct3D &ss3)
 
void PrintT (std::string someText, mf::LogVerbatim &myprt, Trajectory &tj, bool &printHeader)
 
void PrintAllTraj (detinfo::DetectorPropertiesData const &detProp, std::string someText, TCSlice &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 &slc, const PFPStruct &pfp, bool printHeader)
 
void PrintPFPs (std::string someText, TCSlice &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 TCSlice &slc, const TrajPoint &tp)
 
std::string PrintPos (const TCSlice &slc, const Point2_t &pos)
 
void ChkMissedKink (TCSlice &slc, Trajectory &tj, bool prt)
 
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
 
const std::vector< std::string > VtxBitNames
 
const std::vector< std::string > StrategyBitNames
 
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 426 of file DataStructs.h.

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

don't mess with this line

Definition at line 507 of file DataStructs.h.

507  {
508  kSignal,
509  kAtKink,
510  kAtVtx,
511  kBragg,
512  kAtTj,
513  kOutFV,
514  kNoFitVx,
515  kFlagBitSize ///< don't mess with this line
516  } EndFlag_t;
don&#39;t mess with this line
Definition: DataStructs.h:515
EndFlag_t
Definition: DataStructs.h:507
Enumerator
kCanSection 
kNeedsUpdate 
kSmallAngle 

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

499  {
500  kNormal,
501  kStiffEl, ///< use the stiff electron strategy
502  kStiffMu, ///< use the stiff muon strategy
503  kSlowing ///< use the slowing-down strategy
504  } Strategy_t;
Strategy_t
Definition: DataStructs.h:499
use the slowing-down strategy
Definition: DataStructs.h:503
use the stiff electron strategy
Definition: DataStructs.h:501
use the stiff muon strategy
Definition: DataStructs.h:502
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 530 of file DataStructs.h.

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

Definition at line 266 of file DataStructs.h.

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

519  {
521  kEnvNearMuon,
523  kEnvOverlap,
525  kEnvNearSrcHit, ///< TP is near a hit in the srcHit collection but no allHit hit exists (DUNE disambiguation error)
526  kEnvFlag ///< a general purpose flag bit used in 3D matching
527  } TPEnvironment_t;
a general purpose flag bit used in 3D matching
Definition: DataStructs.h:526
TP is near a hit in the srcHit collection but no allHit hit exists (DUNE disambiguation error) ...
Definition: DataStructs.h:525
TPEnvironment_t
Definition: DataStructs.h:519
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 91 of file DataStructs.h.

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

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

3460  {
3461  // Searches the trajectory points for hits that are used in a different trajectory and add
3462  // them to the list if any are found, and the MCSMomentum is not too large
3463  if (itj > slc.tjs.size() - 1) return;
3464 
3465  //short maxMom = (short)(2 * tcc.showerTag[1]);
3466  short maxMom = tcc.showerTag[1];
3467  //XL: why is maxMom is twice of the shower tag [1]?
3468  for (auto& tp : slc.tjs[itj].Pts) {
3469  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3470  // ignore hits that are used in this trajectory
3471  if (tp.UseHit[ii]) continue;
3472  unsigned int iht = tp.Hits[ii];
3473  // ignore if there is no hit -> Tj association
3474  if (slc.slHits[iht].InTraj <= 0) continue;
3475  if ((unsigned int)slc.slHits[iht].InTraj > slc.tjs.size()) continue;
3476  // check the momentum
3477  Trajectory& tj = slc.tjs[slc.slHits[iht].InTraj - 1];
3478  if (tj.MCSMom > maxMom) continue;
3479  // if(tj.AlgMod[kTjHiVx3Score]) continue;
3480  // see if it is already in the list
3481  if (std::find(list.begin(), list.end(), slc.slHits[iht].InTraj) != list.end()) continue;
3482  list.push_back(slc.slHits[iht].InTraj);
3483  } // ii
3484  } // tp
3485  } // AddCloseTjsToList
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:558
void tca::AddHits ( TCSlice &  slc,
Trajectory &  tj,
unsigned short  ipt,
bool &  sigOK 
)

Definition at line 1039 of file StepUtils.cxx.

1040  {
1041  // Try to add hits to the trajectory point ipt on the supplied
1042  // trajectory
1043 
1044  // assume failure
1045  sigOK = false;
1046 
1047  if(tj.Pts.empty()) return;
1048  if(ipt > tj.Pts.size() - 1) return;
1049 
1050  // Call large angle hit finding if the last tp is large angle
1051  if(tj.Pts[ipt].AngleCode == 2) {
1052  AddLAHits(slc, tj, ipt, sigOK);
1053  return;
1054  }
1055 
1056  TrajPoint& tp = tj.Pts[ipt];
1057  std::vector<unsigned int> closeHits;
1058  unsigned int lastPtWithUsedHits = tj.EndPt[1];
1059 
1060  unsigned short plane = DecodeCTP(tj.CTP).Plane;
1061  unsigned int wire = std::nearbyint(tp.Pos[0]);
1062  if(wire < slc.firstWire[plane] || wire > slc.lastWire[plane]-1) return;
1063  // Move the TP to this wire
1064  MoveTPToWire(tp, (float)wire);
1065 
1066  // find the projection error to this point. Note that if this is the first
1067  // TP, lastPtWithUsedHits = 0, so the projection error is 0
1068  float dw = tp.Pos[0] - tj.Pts[lastPtWithUsedHits].Pos[0];
1069  float dt = tp.Pos[1] - tj.Pts[lastPtWithUsedHits].Pos[1];
1070  float dpos = sqrt(dw * dw + dt * dt);
1071  float projErr = dpos * tj.Pts[lastPtWithUsedHits].AngErr;
1072  // Add this to the Delta RMS factor and construct a cut
1073  float deltaCut = 3 * (projErr + tp.DeltaRMS);
1074 
1075  // The delta cut shouldn't be less than the delta of hits added on the previous step
1076  float minDeltaCut = 1.1 * tj.Pts[lastPtWithUsedHits].Delta;
1077  if(deltaCut < minDeltaCut) deltaCut = minDeltaCut;
1078 
1079  deltaCut *= tcc.projectionErrFactor;
1080  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" AddHits: calculated deltaCut "<<deltaCut<<" dw "<<dw<<" dpos "<<dpos;
1081 
1082  if(deltaCut < 0.5) deltaCut = 0.5;
1083  if(deltaCut > 3) deltaCut = 3;
1084 
1085  // TY: open it up for RevProp, since we might be following a stopping track
1086  if(tj.AlgMod[kRvPrp]) deltaCut *= 2;
1087 
1088  // loosen up a bit if we just passed a block of dead wires
1089  bool passedDeadWires = (abs(dw) > 20 && DeadWireCount(slc, tp.Pos[0], tj.Pts[lastPtWithUsedHits].Pos[0], tj.CTP) > 10);
1090  if(passedDeadWires) deltaCut *= 2;
1091  // open it up for StiffEl and Slowing strategies
1092  if(tj.Strategy[kStiffEl] || tj.Strategy[kSlowing]) deltaCut = 3;
1093 
1094  // Create a larger cut to use in case there is nothing close
1095  float bigDelta = 2 * deltaCut;
1096  unsigned int imBig = UINT_MAX;
1097  tp.Delta = deltaCut;
1098  // ignore all hits with delta larger than maxDeltaCut
1099  float maxDeltaCut = 2 * bigDelta;
1100  // apply some limits
1101  if(!passedDeadWires && maxDeltaCut > 3) {
1102  maxDeltaCut = 3;
1103  bigDelta = 1.5;
1104  }
1105 
1106  // projected time in ticks for testing the existence of a hit signal
1107  raw::TDCtick_t rawProjTick = (float)(tp.Pos[1] / tcc.unitsPerTick);
1108  if(tcc.dbgStp) {
1109  mf::LogVerbatim("TC")<<" AddHits: wire "<<wire<<" tp.Pos[0] "<<tp.Pos[0]<<" projTick "<<rawProjTick<<" deltaRMS "<<tp.DeltaRMS<<" tp.Dir[0] "<<tp.Dir[0]<<" deltaCut "<<deltaCut<<" dpos "<<dpos<<" projErr "<<projErr<<" ExpectedHitsRMS "<<ExpectedHitsRMS(slc, tp);
1110  }
1111 
1112  std::vector<unsigned int> hitsInMultiplet;
1113 
1114  geo::PlaneID planeID = DecodeCTP(tj.CTP);
1115  unsigned int ipl = planeID.Plane;
1116  if(wire > slc.lastWire[ipl]) return;
1117  // Assume a signal exists on a dead wire
1118  if(!evt.goodWire[ipl][wire]) sigOK = true;
1119  if(slc.wireHitRange[ipl][wire].first == UINT_MAX) return;
1120  unsigned int firstHit = slc.wireHitRange[ipl][wire].first;
1121  unsigned int lastHit = slc.wireHitRange[ipl][wire].second;
1122  float fwire = wire;
1123  for(unsigned int iht = firstHit; iht <= lastHit; ++iht) {
1124  if(slc.slHits[iht].InTraj == tj.ID) continue;
1125  if(slc.slHits[iht].InTraj == SHRT_MAX) continue;
1126  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1127  if(rawProjTick > hit.StartTick() && rawProjTick < hit.EndTick()) sigOK = true;
1128  float ftime = tcc.unitsPerTick * hit.PeakTime();
1129  float delta = PointTrajDOCA(slc, fwire, ftime, tp);
1130  // increase the delta cut if this is a long pulse hit
1131  bool longPulseHit = LongPulseHit(hit);
1132  if(longPulseHit) {
1133  if(delta > 3) continue;
1134  } else {
1135  if(delta > maxDeltaCut) continue;
1136  }
1137  float dt = std::abs(ftime - tp.Pos[1]);
1138  GetHitMultiplet(slc, iht, hitsInMultiplet, false);
1139  if(tcc.dbgStp && delta < 100 && dt < 100) {
1140  mf::LogVerbatim myprt("TC");
1141  myprt<<" iht "<<iht;
1142  myprt<<" "<<PrintHit(slc.slHits[iht]);
1143  myprt<<" delta "<<std::fixed<<std::setprecision(2)<<delta<<" deltaCut "<<deltaCut<<" dt "<<dt;
1144  myprt<<" BB Mult "<<hitsInMultiplet.size()<<" RMS "<<std::setprecision(1)<<hit.RMS();
1145  myprt<<" Chi "<<std::setprecision(1)<<hit.GoodnessOfFit();
1146  myprt<<" InTraj "<<slc.slHits[iht].InTraj;
1147  myprt<<" Chg "<<(int)hit.Integral();
1148  myprt<<" Signal? "<<sigOK;
1149  }
1150  if(slc.slHits[iht].InTraj == 0 && delta < bigDelta && hitsInMultiplet.size() < 3 && !tj.AlgMod[kRvPrp]) {
1151  // An available hit that is just outside the window that is not part of a large multiplet
1152  bigDelta = delta;
1153  imBig = iht;
1154  }
1155  if(longPulseHit) {
1156  if(delta > 3) continue;
1157  } else {
1158  if(delta > deltaCut) continue;
1159  }
1160 
1161  if(std::find(closeHits.begin(), closeHits.end(), iht) != closeHits.end()) continue;
1162  closeHits.push_back(iht);
1163  if(hitsInMultiplet.size() > 1) {
1164  // include all the hits in a multiplet
1165  for(auto& jht : hitsInMultiplet) {
1166  if(slc.slHits[jht].InTraj == tj.ID) continue;
1167  if(std::find(closeHits.begin(), closeHits.end(), jht) != closeHits.end()) continue;
1168  closeHits.push_back(jht);
1169  } // jht
1170  } // multiplicity > 1
1171  } // iht
1172 
1173  if(tcc.dbgStp) {
1174  mf::LogVerbatim myprt("TC");
1175  myprt<<"closeHits ";
1176  for(auto iht : closeHits) myprt<<" "<<PrintHit(slc.slHits[iht]);
1177  if(imBig < slc.slHits.size()) {
1178  myprt<<" imBig "<<PrintHit(slc.slHits[imBig]);
1179  } else {
1180  myprt<<" imBig "<<imBig;
1181  }
1182  }
1183  // check the srcHit collection if it is defined. Add the TP to the trajectory if
1184  // there is NO hit in the allHits collection but there is a hit in srcHit collection. We
1185  // can't use it for fitting, etc however
1186  bool nearSrcHit = false;
1187  if(!sigOK) nearSrcHit = NearbySrcHit(planeID, wire, (float)rawProjTick, (float)rawProjTick);
1188  sigOK = sigOK || !closeHits.empty() || nearSrcHit;
1189 
1190  if(!sigOK) {
1191  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" no signal on any wire at tp.Pos "<<tp.Pos[0]<<" "<<tp.Pos[1]<<" tick "<<(int)tp.Pos[1]/tcc.unitsPerTick<<" closeHits size "<<closeHits.size();
1192  return;
1193  }
1194  if(imBig < slc.slHits.size() && closeHits.empty()) {
1195  closeHits.push_back(imBig);
1196  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Added bigDelta hit "<<PrintHit(slc.slHits[imBig])<<" w delta = "<<bigDelta;
1197  }
1198  if(closeHits.size() > 16) closeHits.resize(16);
1199  if(nearSrcHit) tp.Environment[kEnvNearSrcHit] = true;
1200  tp.Hits.insert(tp.Hits.end(), closeHits.begin(), closeHits.end());
1201 
1202  // reset UseHit and assume that none of these hits will be used (yet)
1203  tp.UseHit.reset();
1204  // decide which of these hits should be used in the fit. Use a generous maximum delta
1205  // and require a charge check if we're not just starting out
1206  bool useChg = true;
1207  if(tj.Strategy[kStiffEl] || tj.Strategy[kSlowing]) useChg = false;
1208  FindUseHits(slc, tj, ipt, 10, useChg);
1209  DefineHitPos(slc, tp);
1210  SetEndPoints(tj);
1211  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" number of close hits "<<closeHits.size()<<" used hits "<<NumHitsInTP(tp, kUsedHits);
1212  } // AddHits
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3413
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
void FindUseHits(TCSlice &slc, Trajectory &tj, unsigned short ipt, float maxDelta, bool useChg)
Definition: StepUtils.cxx:1757
float ExpectedHitsRMS(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:1947
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2572
process_name hit
Definition: cheaterreco.fcl:51
bool LongPulseHit(const recob::Hit &hit)
Definition: Utils.cxx:4452
int TDCtick_t
Type representing a TDC tick.
Definition: RawTypes.h:25
float projectionErrFactor
Definition: DataStructs.h:583
T abs(T value)
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
use the slowing-down strategy
Definition: DataStructs.h:503
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2141
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1672
TP is near a hit in the srcHit collection but no allHit hit exists (DUNE disambiguation error) ...
Definition: DataStructs.h:525
void GetHitMultiplet(const TCSlice &slc, unsigned int theHit, std::vector< unsigned int > &hitsInMultiplet, bool useLongPulseHits)
Definition: StepUtils.cxx:1415
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:630
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6516
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
unsigned short NumHitsInTP(const TrajPoint &tp, HitStatus_t hitRequest)
Definition: Utils.cxx:4328
void AddLAHits(TCSlice &slc, Trajectory &tj, unsigned short ipt, bool &sigOK)
Definition: StepUtils.cxx:1216
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
use the stiff electron strategy
Definition: DataStructs.h:501
bool NearbySrcHit(geo::PlaneID plnID, unsigned int wire, float loTick, float hiTick)
Definition: Utils.cxx:2071
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2831
TCEvent evt
Definition: DataStructs.cxx:8
void tca::AddLAHits ( TCSlice &  slc,
Trajectory &  tj,
unsigned short  ipt,
bool &  sigOK 
)

Definition at line 1216 of file StepUtils.cxx.

1217  {
1218  // Very Large Angle version of AddHits to be called for the last angle range
1219 
1220  if(ipt > tj.Pts.size() - 1) return;
1221  TrajPoint& tp = tj.Pts[ipt];
1222  tp.Hits.clear();
1223  tp.UseHit.reset();
1224  sigOK = false;
1225 
1226  unsigned short plane = DecodeCTP(tj.CTP).Plane;
1227 
1228  // look at adjacent wires for larger angle trajectories
1229  // We will check the most likely wire first
1230  std::vector<int> wires(1);
1231  wires[0] = std::nearbyint(tp.Pos[0]);
1232  if(wires[0] < 0 || wires[0] > (int)slc.lastWire[plane]-1) return;
1233 
1234  if(tp.AngleCode != 2) {
1235  mf::LogVerbatim("TC")<<"AddLAHits called with a bad angle code. "<<tp.AngleCode<<" Don't do this";
1236  return;
1237  }
1238  // and the adjacent wires next in the most likely order only
1239  // after the first two points have been defined
1240  if(ipt > 1) {
1241  if(tp.Dir[0] > 0) {
1242  if(wires[0] < (int)slc.lastWire[plane]-1) wires.push_back(wires[0] + 1);
1243  if(wires[0] > 0) wires.push_back(wires[0] - 1);
1244  } else {
1245  if(wires[0] > 0) wires.push_back(wires[0] - 1);
1246  if(wires[0] < (int)slc.lastWire[plane]-1) wires.push_back(wires[0] + 1);
1247  }
1248  } // ipt > 0 ...
1249 
1250  if(tcc.dbgStp) {
1251  mf::LogVerbatim myprt("TC");
1252  myprt<<" AddLAHits: Pos "<<PrintPos(slc, tp)<<" tp.AngleCode "<<tp.AngleCode<<" Wires under consideration";
1253  for(auto& wire : wires) myprt<<" "<<wire;
1254  }
1255 
1256  // a temporary tp that we can move around
1257  TrajPoint ltp = tp;
1258  // do this while testing
1259  sigOK = false;
1260 
1261  tp.Hits.clear();
1262  std::array<int, 2> wireWindow;
1263  std::array<float, 2> timeWindow;
1264  float pos1Window = tcc.VLAStepSize/2;
1265  timeWindow[0] = ltp.Pos[1] - pos1Window;
1266  timeWindow[1] = ltp.Pos[1] + pos1Window;
1267  // Put the existing hits in to a vector so we can ensure that they aren't added again
1268  std::vector<unsigned int> oldHits = PutTrajHitsInVector(tj, kAllHits);
1269 
1270  for(unsigned short ii = 0; ii < wires.size(); ++ii) {
1271  int wire = wires[ii];
1272  if(wire < 0 || wire > (int)slc.lastWire[plane]) continue;
1273  // Assume a signal exists on a dead wire
1274  if(slc.wireHitRange[plane][wire].first == UINT_MAX) sigOK = true;
1275  if(slc.wireHitRange[plane][wire].first == UINT_MAX) continue;
1276  wireWindow[0] = wire;
1277  wireWindow[1] = wire;
1278  bool hitsNear;
1279  // Look for hits using the requirement that the timeWindow overlaps with the hit StartTick and EndTick
1280  std::vector<unsigned int> closeHits = FindCloseHits(slc, wireWindow, timeWindow, plane, kAllHits, true, hitsNear);
1281  if(hitsNear) sigOK = true;
1282  for(auto& iht : closeHits) {
1283  // Ensure that none of these hits are already used by this trajectory
1284  if(slc.slHits[iht].InTraj == tj.ID) continue;
1285  // or in another trajectory in any previously added point
1286  if(std::find(oldHits.begin(), oldHits.end(), iht) != oldHits.end()) continue;
1287  tp.Hits.push_back(iht);
1288  }
1289  } // ii
1290 
1291  if(tcc.dbgStp) {
1292  mf::LogVerbatim myprt("TC");
1293  myprt<<" LAPos "<<PrintPos(slc, ltp)<<" Tick window "<<(int)(timeWindow[0]/tcc.unitsPerTick)<<" to "<<(int)(timeWindow[1]/tcc.unitsPerTick);
1294  for(auto& iht : tp.Hits) myprt<<" "<<PrintHit(slc.slHits[iht]);
1295  } // prt
1296 
1297  // no hits found
1298  if(tp.Hits.empty()) return;
1299 
1300  if(tp.Hits.size() > 16) tp.Hits.resize(16);
1301 
1302  tp.UseHit.reset();
1303  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1304  unsigned int iht = tp.Hits[ii];
1305  if(slc.slHits[iht].InTraj != 0) continue;
1306  tp.UseHit[ii] = true;
1307  slc.slHits[iht].InTraj = tj.ID;
1308  } // ii
1309  DefineHitPos(slc, tp);
1310  SetEndPoints(tj);
1311  UpdateTjChgProperties("ALAH", slc, tj, tcc.dbgStp);
1312 
1313  } // AddLAHits
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3413
std::vector< unsigned int > PutTrajHitsInVector(const Trajectory &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2754
TCConfig tcc
Definition: DataStructs.cxx:9
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1672
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:2843
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6516
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3673
float VLAStepSize
Definition: DataStructs.h:584
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 3627 of file TCShower.cxx.

3628  {
3629  // Add hits that are inside the envelope to the shower if they are loose, i.e. not
3630  // used by any trajectory. This function returns true if the set of hits is different than
3631  // the current set. The calling function should update the shower if this is the case.
3632 
3633  ShowerStruct& ss = slc.cots[cotID - 1];
3634  if (ss.Envelope.empty()) return false;
3635  if (ss.ID == 0) return false;
3636  if (ss.TjIDs.empty()) return false;
3637 
3638  geo::PlaneID planeID = DecodeCTP(ss.CTP);
3639  unsigned short ipl = planeID.Plane;
3640 
3641  Trajectory& stj = slc.tjs[ss.ShowerTjID - 1];
3642  TrajPoint& stp0 = stj.Pts[0];
3643  // start a list of new hits
3644  std::vector<unsigned int> newHits;
3645 
3646  // look for hits inside the envelope. Find the range of wires that spans the envelope
3647  float fLoWire = 1E6;
3648  float fHiWire = 0;
3649  // and the range of ticks
3650  float loTick = 1E6;
3651  float hiTick = 0;
3652  for (auto& vtx : ss.Envelope) {
3653  if (vtx[0] < fLoWire) fLoWire = vtx[0];
3654  if (vtx[0] > fHiWire) fHiWire = vtx[0];
3655  if (vtx[1] < loTick) loTick = vtx[1];
3656  if (vtx[1] > hiTick) hiTick = vtx[1];
3657  } // vtx
3658  loTick /= tcc.unitsPerTick;
3659  hiTick /= tcc.unitsPerTick;
3660  unsigned int loWire = std::nearbyint(fLoWire);
3661  unsigned int hiWire = std::nearbyint(fHiWire) + 1;
3662  if (hiWire > slc.lastWire[ipl] - 1) hiWire = slc.lastWire[ipl] - 1;
3663  std::array<float, 2> point;
3664  for (unsigned int wire = loWire; wire < hiWire; ++wire) {
3665  // skip bad wires or no hits on the wire
3666  if (slc.wireHitRange[ipl][wire].first == UINT_MAX) continue;
3667  unsigned int firstHit = slc.wireHitRange[ipl][wire].first;
3668  unsigned int lastHit = slc.wireHitRange[ipl][wire].second;
3669  for (unsigned int iht = firstHit; iht < lastHit; ++iht) {
3670  // used in a trajectory?
3671  if (slc.slHits[iht].InTraj != 0) continue;
3672  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
3673  // inside the tick range?
3674  if (hit.PeakTime() < loTick) continue;
3675  // Note that hits are sorted by increasing time so we can break here
3676  if (hit.PeakTime() > hiTick) break;
3677  // see if this hit is inside the envelope
3678  point[0] = hit.WireID().Wire;
3679  point[1] = hit.PeakTime() * tcc.unitsPerTick;
3680  if (!PointInsideEnvelope(point, ss.Envelope)) continue;
3681  newHits.push_back(iht);
3682  } // iht
3683  } // wire
3684 
3685  // no new hits and no old hits. Nothing to do
3686  if (newHits.empty()) {
3687  if (prt) mf::LogVerbatim("TC") << "ALH: No new loose hits found";
3688  return false;
3689  }
3690 
3691  // Update
3692  stp0.Hits.insert(stp0.Hits.end(), newHits.begin(), newHits.end());
3693  for (auto& iht : newHits)
3694  slc.slHits[iht].InTraj = stj.ID;
3695 
3696  if (prt)
3697  mf::LogVerbatim("TC") << "ALH: Added " << stp0.Hits.size() << " hits to stj " << stj.ID;
3698  return true;
3699 
3700  } // AddLooseHits
then if[["$THISISATEST"==1]]
Definition: neoSmazza.sh:95
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
process_name hit
Definition: cheaterreco.fcl:51
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:3323
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
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 1386 of file TCShower.cxx.

1392  {
1393  // Add the tjs in the pfp with id = pID to the 2D showers in ss3 and optionally update everything. This
1394  // function returns true if the addition was successful or if the Tjs in the pfp are already in ss3.
1395  // This function returns false if there was a failure. There isn't any error recovery.
1396 
1397  std::string fcnLabel = inFcnLabel + ".AddP";
1398 
1399  if (pID <= 0 || pID > (int)slc.pfps.size()) return false;
1400  auto& pfp = slc.pfps[pID - 1];
1401 
1402  if (pfp.TPCID != ss3.TPCID) {
1403  mf::LogVerbatim("TC") << fcnLabel << " P" << pID << " is in the wrong TPC for 3S" << ss3.ID;
1404  return false;
1405  }
1406 
1407  for (auto tid : pfp.TjIDs) {
1408  auto& tj = slc.tjs[tid - 1];
1409  // is this tj in a 2D shower that is in a 3D shower that is not this shower?
1410  if (tj.SSID > 0) {
1411  auto& ss = slc.cots[tj.SSID - 1];
1412  if (ss.SS3ID > 0 && ss.SS3ID != ss3.ID) {
1413  if (prt)
1414  mf::LogVerbatim("TC") << fcnLabel << " Conflict: 3S" << ss3.ID << " adding P" << pfp.ID
1415  << " -> T" << tid << " is in 2S" << tj.SSID << " that is in 3S"
1416  << ss.SS3ID << " that is not this shower";
1417  return false;
1418  } // conflict
1419  // tj is in the correct 2D shower so nothing needs to be done
1420  if (prt)
1421  mf::LogVerbatim("TC") << fcnLabel << " 3S" << ss3.ID << " adding P" << pfp.ID << " -> T"
1422  << tid << " is in the correct shower 2S" << tj.SSID;
1423  continue;
1424  } // pfp tj is in a shower
1425  if (prt) {
1426  mf::LogVerbatim myprt("TC");
1427  myprt << fcnLabel << " 3S" << ss3.ID << " adding P" << pfp.ID << " -> T" << tid;
1428  myprt << " tj.SSID 2S" << tj.SSID;
1429  } // prt
1430  // add it to the shower in the correct CTP
1431  for (auto& cid : ss3.CotIDs) {
1432  auto& ss = slc.cots[cid - 1];
1433  if (ss.CTP != tj.CTP) continue;
1434  // Add it to the shower.
1435  AddTj(fcnLabel, slc, tid, ss, doUpdate, prt);
1436  ss3.NeedsUpdate = true;
1437  break;
1438  } // cid
1439  } // tid
1440 
1441  if (doUpdate && ss3.NeedsUpdate) UpdateShower(fcnLabel, slc, ss3, prt);
1442  return true;
1443 
1444  } // AddPFP
bool AddTj(std::string inFcnLabel, TCSlice &slc, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1448
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:913
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 1838 of file PFPUtils.cxx.

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

Definition at line 1448 of file TCShower.cxx.

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

Definition at line 3551 of file TCShower.cxx.

3552  {
3553  // This function adds Tjs to the shower. It updates the shower parameters.
3554 
3555  if (ss.Envelope.empty()) return false;
3556  if (ss.ID == 0) return false;
3557  if (ss.TjIDs.empty()) return false;
3558 
3559  std::string fcnLabel = inFcnLabel + ".ATIE";
3560 
3561  if (prt) mf::LogVerbatim("TC") << fcnLabel << " Checking 2S" << ss.ID;
3562 
3563  std::vector<int> tmp(1);
3564  unsigned short nadd = 0;
3565  for (auto& tj : slc.tjs) {
3566  if (tj.CTP != ss.CTP) continue;
3567  if (tj.AlgMod[kKilled]) continue;
3568  if (tj.SSID > 0) continue;
3569  if (tj.AlgMod[kShowerTj]) continue;
3570  // See if this Tjs is attached to a neutrino vertex.
3571  if (tj.ParentID == 0) continue;
3572  int neutPrimTj = NeutrinoPrimaryTjID(slc, tj);
3573  if (neutPrimTj > 0 && neutPrimTj != tj.ID) {
3574  // The Tj is connected to a primary Tj that is associated with a neutrino primary.
3575  // Don't allow tjs to be added to the shower that are not connected to this neutrino primary (if
3576  // one exists)
3577  if (ss.ParentID > 0 && neutPrimTj != ss.ParentID) continue;
3578  } // neutrino primary tj
3579  // This shouldn't be necessary but ensure that the Tj ID appears only once in ss.TjIDs
3580  if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tj.ID) != ss.TjIDs.end()) continue;
3581  // check consistency
3582  tmp[0] = tj.ID;
3583  if (DontCluster(slc, tmp, ss.TjIDs)) continue;
3584  // See if both ends are outside the envelope
3585  bool end0Inside = PointInsideEnvelope(tj.Pts[tj.EndPt[0]].Pos, ss.Envelope);
3586  bool end1Inside = PointInsideEnvelope(tj.Pts[tj.EndPt[1]].Pos, ss.Envelope);
3587  if (!end0Inside && !end1Inside) continue;
3588  if (end0Inside && end1Inside) {
3589  // TODO: See if the Tj direction is compatible with the shower?
3590  if (AddTj(fcnLabel, slc, tj.ID, ss, false, prt)) ++nadd;
3591  ++nadd;
3592  continue;
3593  } // both ends inside
3594  // Require high momentum Tjs be aligned with the shower axis
3595  // TODO also require high momentum Tjs close to the shower axis?
3596 
3597  if (tj.MCSMom > 200) {
3598  float tjAngle = tj.Pts[tj.EndPt[0]].Ang;
3599  float dangPull = std::abs(tjAngle - ss.AngleErr) / ss.AngleErr;
3600  if (prt)
3601  mf::LogVerbatim("TC") << fcnLabel << " high MCSMom " << tj.MCSMom << " dangPull "
3602  << dangPull;
3603  if (dangPull > 2) continue;
3604  } // high momentum
3605  if (AddTj(fcnLabel, slc, tj.ID, ss, false, prt)) { ++nadd; }
3606  else {
3607  if (prt) mf::LogVerbatim("TC") << fcnLabel << " AddTj failed to add T" << tj.ID;
3608  }
3609  } // tj
3610 
3611  if (nadd > 0) {
3612  if (prt) mf::LogVerbatim("TC") << fcnLabel << " Added " << nadd << " trajectories ";
3613  ss.NeedsUpdate = true;
3614  UpdateShower(fcnLabel, slc, ss, prt);
3615  return true;
3616  }
3617  else {
3618  if (prt) mf::LogVerbatim("TC") << fcnLabel << " No new trajectories added to envelope ";
3619  ss.NeedsUpdate = false;
3620  return false;
3621  }
3622 
3623  } // AddTjsInsideEnvelope
bool AddTj(std::string inFcnLabel, TCSlice &slc, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1448
bool DontCluster(TCSlice &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3258
T abs(T value)
int NeutrinoPrimaryTjID(const TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:444
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:3323
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:913
bool tca::AnalyzeHits ( )

Definition at line 4394 of file Utils.cxx.

4395  {
4396  // Find the average hit rms by analyzing the full hit collection. This
4397  // only needs to be done once per job.
4398 
4399  if ((*evt.allHits).empty()) return true;
4400  // no sense re-calculating it if it's been done
4401  if (evt.aveHitRMSValid) return true;
4402 
4403  unsigned short cstat = (*evt.allHits)[0].WireID().Cryostat;
4404  unsigned short tpc = (*evt.allHits)[0].WireID().TPC;
4405 
4406  unsigned short nplanes = tcc.geom->Nplanes(tpc, cstat);
4407  evt.aveHitRMS.resize(nplanes);
4408  std::vector<float> cnt(nplanes, 0);
4409  for (unsigned short iht = 0; iht < (*evt.allHits).size(); ++iht) {
4410  auto& hit = (*evt.allHits)[iht];
4411  unsigned short plane = hit.WireID().Plane;
4412  if (plane > nplanes - 1) return false;
4413  if (cnt[plane] > 200) continue;
4414  // require multiplicity one
4415  if (hit.Multiplicity() != 1) continue;
4416  // not-crazy Chisq/DOF
4417  if (hit.GoodnessOfFit() < 0 || hit.GoodnessOfFit() > 500) continue;
4418  // don't let a lot of runt hits screw up the calculation
4419  if (hit.PeakAmplitude() < 1) continue;
4420  evt.aveHitRMS[plane] += hit.RMS();
4421  ++cnt[plane];
4422  // quit if enough hits are found
4423  bool allDone = true;
4424  for (unsigned short plane = 0; plane < nplanes; ++plane)
4425  if (cnt[plane] < 200) allDone = false;
4426  if (allDone) break;
4427  } // iht
4428 
4429  // assume there are enough hits in each plane
4430  evt.aveHitRMSValid = true;
4431  for (unsigned short plane = 0; plane < nplanes; ++plane) {
4432  if (cnt[plane] > 4) { evt.aveHitRMS[plane] /= cnt[plane]; }
4433  else {
4434  evt.aveHitRMS[plane] = 10;
4435  evt.aveHitRMSValid = false;
4436  } // cnt too low
4437  } // plane
4438 
4439  if (tcc.modes[kDebug]) {
4440  std::cout << "Analyze hits aveHitRMS";
4441  std::cout << std::fixed << std::setprecision(1);
4442  for (auto rms : evt.aveHitRMS)
4443  std::cout << " " << rms;
4444  std::cout << " aveHitRMSValid? " << evt.aveHitRMSValid << "\n";
4445  }
4446 
4447  return true;
4448  } // Analyze hits
TCConfig tcc
Definition: DataStructs.cxx:9
std::size_t size(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:561
process_name hit
Definition: cheaterreco.fcl:51
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
std::vector< float > aveHitRMS
average RMS of an isolated hit
Definition: DataStructs.h:638
const geo::GeometryCore * geom
Definition: DataStructs.h:576
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:607
bool aveHitRMSValid
set true when the average hit RMS is well-known
Definition: DataStructs.h:647
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
TCEvent evt
Definition: DataStructs.cxx:8
master switch for turning on debug mode
Definition: DataStructs.h:533
BEGIN_PROLOG could also be cout
bool tca::AnalyzeRotPos ( std::string  inFcnLabel,
TCSlice &  slc,
ShowerStruct &  ss,
bool  prt 
)

Definition at line 3062 of file TCShower.cxx.

3063  {
3064  // The RotPos vector was filled and sorted by increasing distance along the shower axis.
3065  // This function divides the RotPos points into 3 sections and puts the transverse rms width in the
3066  // three sections into the shower Tj TrajPoint DeltaRMS variable. It also calculates the charge and number of shower
3067  // points closest to each TrajPoint. The
3068 
3069  if (ss.ID == 0) return false;
3070  if (ss.ShPts.empty()) return false;
3071  Trajectory& stj = slc.tjs[ss.ShowerTjID - 1];
3072  if (stj.Pts.size() != 3) return false;
3073 
3074  std::string fcnLabel = inFcnLabel + ".ARP";
3075 
3076  for (auto& tp : stj.Pts) {
3077  tp.Chg = 0;
3078  tp.DeltaRMS = 0;
3079  tp.NTPsFit = 0;
3080  tp.HitPos = {{0.0, 0.0}};
3081  }
3082 
3083  float minAlong = ss.ShPts[0].RotPos[0];
3084  float maxAlong = ss.ShPts[ss.ShPts.size() - 1].RotPos[0];
3085  float sectionLength = (maxAlong - minAlong) / 3;
3086  float sec0 = minAlong + sectionLength;
3087  float sec2 = maxAlong - sectionLength;
3088  // iterate over the shower points (aka hits)
3089  for (auto& spt : ss.ShPts) {
3090  // The point on the shower Tj to which the charge will assigned
3091  unsigned short ipt = 0;
3092  if (spt.RotPos[0] < sec0) {
3093  // closest to point 0
3094  ipt = 0;
3095  }
3096  else if (spt.RotPos[0] > sec2) {
3097  // closest to point 2
3098  ipt = 2;
3099  }
3100  else {
3101  // closest to point 1
3102  ipt = 1;
3103  }
3104  stj.Pts[ipt].Chg += spt.Chg;
3105  // Average the absolute value of the transverse position in lieu of
3106  // using the sum of the squares. The result is ~15% higher than the actual
3107  // rms which is OK since this is used to find the transverse size of the shower
3108  // which is not a precisely defined quantity anyway
3109  stj.Pts[ipt].DeltaRMS += spt.Chg * std::abs(spt.RotPos[1]);
3110  ++stj.Pts[ipt].NTPsFit;
3111  // Average the charge center at each point
3112  stj.Pts[ipt].HitPos[0] += spt.Chg * spt.Pos[0];
3113  stj.Pts[ipt].HitPos[1] += spt.Chg * spt.Pos[1];
3114  } // spt
3115 
3116  for (auto& tp : stj.Pts) {
3117  if (tp.Chg > 0) {
3118  tp.DeltaRMS /= tp.Chg;
3119  tp.HitPos[0] /= tp.Chg;
3120  tp.HitPos[1] /= tp.Chg;
3121  }
3122  } // tp
3123 
3124  // require that there is charge in point 0 and 2. Point 1 may not have charge if
3125  // we are constructing a sparse shower that is not yet well-defined
3126  if (stj.Pts[0].Chg == 0 || stj.Pts[2].Chg == 0) return false;
3127 
3128  // ensure that the charge center is defined
3129  if (stj.Pts[1].Chg == 0) {
3130  // do a simple interpolation
3131  stj.Pts[1].HitPos[0] = 0.5 * (stj.Pts[0].HitPos[0] + stj.Pts[2].HitPos[0]);
3132  stj.Pts[1].HitPos[1] = 0.5 * (stj.Pts[0].HitPos[1] + stj.Pts[2].HitPos[1]);
3133  }
3134  if (stj.Pts[2].DeltaRMS > 0) { ss.DirectionFOM = stj.Pts[0].DeltaRMS / stj.Pts[2].DeltaRMS; }
3135  else {
3136  ss.DirectionFOM = 10;
3137  }
3138  if (prt) {
3139  mf::LogVerbatim myprt("TC");
3140  myprt << fcnLabel << " 2S" << ss.ID;
3141  myprt << " HitPos[0] " << std::fixed << std::setprecision(1);
3142  myprt << stj.Pts[1].HitPos[0] << " " << stj.Pts[1].HitPos[1] << " " << stj.Pts[1].HitPos[2];
3143  myprt << " DeltaRMS " << std::setprecision(2);
3144  myprt << stj.Pts[0].DeltaRMS << " " << stj.Pts[1].DeltaRMS << " " << stj.Pts[2].DeltaRMS;
3145  myprt << " DirectionFOM " << std::fixed << std::setprecision(2) << ss.DirectionFOM;
3146  }
3147  return true;
3148 
3149  } // AnalyzeRotPos
T abs(T value)
unsigned short tca::AngleRange ( TrajPoint const &  tp)

Definition at line 766 of file Utils.cxx.

767  {
768  return AngleRange(tp.Ang);
769  }
unsigned short AngleRange(TrajPoint const &tp)
Definition: Utils.cxx:766
unsigned short tca::AngleRange ( float  angle)

Definition at line 793 of file Utils.cxx.

794  {
795  // returns the index of the angle range
796  if (angle > M_PI) angle = M_PI;
797  if (angle < -M_PI) angle = M_PI;
798  if (angle < 0) angle = -angle;
799  if (angle > M_PI / 2) angle = M_PI - angle;
800  for (unsigned short ir = 0; ir < tcc.angleRanges.size(); ++ir) {
801  if (angle < tcc.angleRanges[ir]) return ir;
802  }
803  return tcc.angleRanges.size() - 1;
804  } // AngleRange
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< float > angleRanges
list of max angles for each angle range
Definition: DataStructs.h:569
finds tracks best matching by angle
bool tca::AttachAnyTrajToVertex ( TCSlice &  slc,
unsigned short  ivx,
bool  prt 
)

Definition at line 1683 of file TCVertex.cxx.

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

Definition at line 1641 of file TCVertex.cxx.

1642  {
1643  // Try to attach a tj that is stored in slc.tjs with any vertex
1644  if (tjID <= 0 || tjID > (int)slc.tjs.size()) return false;
1645  if (slc.vtxs.empty()) return false;
1646  auto& tj = slc.tjs[tjID - 1];
1647  if (tj.AlgMod[kKilled]) return false;
1648  if (tcc.vtx2DCuts[0] <= 0) return false;
1649 
1650  unsigned short bestVx = USHRT_MAX;
1651  // Construct a FOM = (TP-Vtx pull) * (TP-Vtx sep + 1) * (Vtx Score).
1652  // The +1 keeps FOM from being 0
1653  float bestFOM = 2 * tcc.vtx2DCuts[3] * (tcc.vtx2DCuts[0] + 1) * tcc.vtx2DCuts[7];
1654  for (unsigned short ivx = 0; ivx < slc.vtxs.size(); ++ivx) {
1655  auto& vx = slc.vtxs[ivx];
1656  if (vx.ID == 0) continue;
1657  if (vx.CTP != tj.CTP) continue;
1658  // make some rough cuts
1659  std::array<float, 2> sep;
1660  sep[0] = PosSep(vx.Pos, tj.Pts[tj.EndPt[0]].Pos);
1661  sep[1] = PosSep(vx.Pos, tj.Pts[tj.EndPt[1]].Pos);
1662  unsigned short end = 0;
1663  if (sep[1] < sep[0]) end = 1;
1664  if (sep[end] > 100) continue;
1665  if (tj.VtxID[end] > 0) continue;
1666  auto& tp = tj.Pts[tj.EndPt[end]];
1667  // Pad the separation a bit so we don't get zero
1668  float fom = TrajPointVertexPull(slc, tp, vx) * (sep[end] + 1) * vx.Score;
1669  if (fom > bestFOM) continue;
1670  if (prt)
1671  mf::LogVerbatim("TC") << "AAVTT: T" << tjID << " 2V" << vx.ID << " FOM " << fom << " cut "
1672  << bestFOM;
1673  bestVx = ivx;
1674  bestFOM = fom;
1675  } // vx
1676  if (bestVx > slc.vtxs.size() - 1) return false;
1677  auto& vx = slc.vtxs[bestVx];
1678  return AttachTrajToVertex(slc, tj, vx, prt);
1679  } // AttachAnyVertexToTraj
then if[["$THISISATEST"==1]]
Definition: neoSmazza.sh:95
float TrajPointVertexPull(const TCSlice &slc, const TrajPoint &tp, const VtxStore &vx)
Definition: TCVertex.cxx:1851
TCConfig tcc
Definition: DataStructs.cxx:9
for($it=0;$it< $RaceTrack_number;$it++)
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
bool AttachTrajToVertex(TCSlice &slc, Trajectory &tj, VtxStore &vx, bool prt)
Definition: TCVertex.cxx:1728
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2565
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:550
bool tca::AttachToAnyVertex ( TCSlice &  slc,
PFPStruct &  pfp,
float  maxSep,
bool  prt 
)

Definition at line 1583 of file TCVertex.cxx.

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

Definition at line 1728 of file TCVertex.cxx.

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

Definition at line 2650 of file PFPUtils.cxx.

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

Definition at line 1444 of file Utils.cxx.

1445  {
1446  // Searches the stored trajectory for a Bragg Peak and kink and splits it
1447  if (!tcc.useAlg[kBraggSplit]) return false;
1448  if (itj > slc.tjs.size() - 1) return false;
1449  if (tcc.chkStopCuts.size() < 4) return false;
1450  if (tcc.chkStopCuts[3] <= 0) return false;
1451  unsigned short nPtsToCheck = tcc.chkStopCuts[1];
1452  auto& tj = slc.tjs[itj];
1453  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
1454  if (npwc < 4) return false;
1455  if (npwc < nPtsToCheck) nPtsToCheck = npwc;
1456  // do a rough ChgPull check first
1457  float maxPull = 2;
1458  unsigned short maxPullPt = USHRT_MAX;
1459  for (unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1]; ++ipt) {
1460  auto& tp = tj.Pts[ipt];
1461  if (tp.ChgPull < maxPull) continue;
1462  maxPull = tp.ChgPull;
1463  maxPullPt = ipt;
1464  } // ipt
1465  if (maxPullPt == USHRT_MAX) return false;
1466  short dpt;
1467  if (maxPullPt < 0.5 * (tj.EndPt[0] + tj.EndPt[1])) { dpt = maxPullPt - tj.EndPt[0]; }
1468  else {
1469  dpt = tj.EndPt[1] - maxPullPt;
1470  }
1471  if (dpt < 3) return false;
1472  bool prt = (tcc.dbgSlc && (tcc.dbgStp || tcc.dbgAlg[kBraggSplit]));
1473  if (prt)
1474  mf::LogVerbatim("TC") << "BS: T" << tj.ID << " maxPull " << maxPull << " at "
1475  << PrintPos(slc, tj.Pts[maxPullPt]) << " dpt " << dpt;
1476  unsigned short breakPt = USHRT_MAX;
1477  float bestFOM = tcc.chkStopCuts[3];
1478  unsigned short bestBragg = 0;
1479  unsigned short nPtsFit = tcc.kinkCuts[0];
1480  TrajPoint tp1, tp2;
1481  ParFit chgFit1, chgFit2;
1482  for (unsigned short ipt = maxPullPt - 2; ipt <= maxPullPt + 2; ++ipt) {
1483  FitTraj(slc, tj, ipt - 1, nPtsFit, -1, tp1);
1484  if (tp1.FitChi > 10) continue;
1485  FitTraj(slc, tj, ipt + 1, nPtsFit, 1, tp2);
1486  if (tp2.FitChi > 10) continue;
1487  float dang = std::abs(tp1.Ang - tp2.Ang);
1488  FitPar(slc, tj, ipt - 1, nPtsToCheck, -1, chgFit1, 1);
1489  if (chgFit1.ChiDOF > 100) continue;
1490  chgFit1.ParSlp = -chgFit1.ParSlp;
1491  FitPar(slc, tj, ipt + 1, nPtsToCheck, 1, chgFit2, 1);
1492  if (chgFit2.ChiDOF > 100) continue;
1493  chgFit2.ParSlp = -chgFit2.ParSlp;
1494  // require a large positive slope on at least one side
1495  if (chgFit1.ParSlp < tcc.chkStopCuts[0] && chgFit2.ParSlp < tcc.chkStopCuts[0]) continue;
1496  // assume it is on side 1
1497  unsigned short bragg = 1;
1498  float bchi = chgFit1.ChiDOF;
1499  if (chgFit2.ParSlp > chgFit1.ParSlp) {
1500  bragg = 2;
1501  bchi = chgFit2.ChiDOF;
1502  }
1503  float chgAsym = std::abs(chgFit1.Par0 - chgFit2.Par0) / (chgFit1.Par0 + chgFit2.Par0);
1504  float slpAsym = std::abs(chgFit1.ParSlp - chgFit2.ParSlp) / (chgFit1.ParSlp + chgFit2.ParSlp);
1505  if (bchi < 1) bchi = 1;
1506  float fom = 10 * dang * chgAsym * slpAsym / bchi;
1507  if (prt) {
1508  mf::LogVerbatim myprt("TC");
1509  myprt << "pt " << PrintPos(slc, tj.Pts[ipt]) << " " << std::setprecision(2) << dang;
1510  myprt << " chg1 " << (int)chgFit1.Par0 << " slp " << chgFit1.ParSlp << " chi "
1511  << chgFit1.ChiDOF;
1512  myprt << " chg2 " << (int)chgFit2.Par0 << " slp " << chgFit2.ParSlp << " chi "
1513  << chgFit2.ChiDOF;
1514  myprt << " chgAsym " << chgAsym;
1515  myprt << " slpAsym " << slpAsym;
1516  myprt << " fom " << fom;
1517  myprt << " bragg " << bragg;
1518  }
1519  if (fom < bestFOM) continue;
1520  bestFOM = fom;
1521  breakPt = ipt;
1522  bestBragg = bragg;
1523  } // ipt
1524  if (breakPt == USHRT_MAX) return false;
1525  if (prt)
1526  mf::LogVerbatim("TC") << " breakPt " << PrintPos(slc, tj.Pts[breakPt]) << " bragg "
1527  << bestBragg;
1528  // Create a vertex at the break point
1529  VtxStore aVtx;
1530  aVtx.Pos = tj.Pts[breakPt].Pos;
1531  aVtx.NTraj = 2;
1532  aVtx.Pass = tj.Pass;
1533  aVtx.Topo = 12;
1534  aVtx.ChiDOF = 0;
1535  aVtx.CTP = tj.CTP;
1536  aVtx.ID = slc.vtxs.size() + 1;
1537  aVtx.Stat[kFixed] = true;
1538  unsigned short ivx = slc.vtxs.size();
1539  if (!StoreVertex(slc, aVtx)) return false;
1540  if (!SplitTraj(slc, itj, breakPt, ivx, prt)) {
1541  if (prt) mf::LogVerbatim("TC") << "BS: Failed to split trajectory";
1542  MakeVertexObsolete("BS", slc, slc.vtxs[ivx], false);
1543  return false;
1544  }
1545  SetVx2Score(slc);
1546  slc.tjs[itj].AlgMod[kBraggSplit] = true;
1547  unsigned short otj = slc.tjs.size() - 1;
1548  if (bestBragg == 2) std::swap(itj, otj);
1549  slc.tjs[itj].PDGCode = 211;
1550  slc.tjs[itj].EndFlag[1][kBragg] = true;
1551  slc.tjs[otj].PDGCode = 13;
1552  return true;
1553  } // BraggSplit
void FitPar(const TCSlice &slc, const Trajectory &tj, unsigned short originPt, unsigned short npts, short fitDir, ParFit &pFit, unsigned short usePar)
Definition: Utils.cxx:1219
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:2726
std::vector< float > kinkCuts
kink finder algorithm
Definition: DataStructs.h:559
TCConfig tcc
Definition: DataStructs.cxx:9
vertex position fixed manually - no fitting done
Definition: DataStructs.h:93
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:590
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:1918
T abs(T value)
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
void FitTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:808
bool SplitTraj(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, unsigned short itj, float XPos, bool makeVx2, bool prt)
Definition: Utils.cxx:2272
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:587
std::vector< float > chkStopCuts
Bragg peak finder configuration.
Definition: DataStructs.h:557
void SetVx2Score(TCSlice &slc)
Definition: TCVertex.cxx:2264
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2116
bool tca::CanSection ( const TCSlice &  slc,
const PFPStruct &  pfp 
)

Definition at line 1343 of file PFPUtils.cxx.

1344  {
1345  // analyze the TP3D vector to determine if it can be reconstructed in 3D in more than one section with
1346  // the requirement that there are at least 3 points in two planes
1347  if (pfp.AlgMod[kJunk3D]) return false;
1348  if (pfp.AlgMod[kSmallAngle]) return false;
1349  if (pfp.TP3Ds.size() < 12) return false;
1350  unsigned short toPt = Find3DRecoRange(slc, pfp, 0, 3, 1);
1351  if (toPt > pfp.TP3Ds.size()) return false;
1352  unsigned short nextToPt = Find3DRecoRange(slc, pfp, toPt, 3, 1);
1353  if (nextToPt > pfp.TP3Ds.size()) return false;
1354  return true;
1355  } // CanSection
unsigned short Find3DRecoRange(const TCSlice &slc, const PFPStruct &pfp, unsigned short fromPt, unsigned short min2DPts, short dir)
Definition: PFPUtils.cxx:1359
void tca::CheckHiMultEndHits ( TCSlice &  slc,
Trajectory &  tj 
)

Definition at line 2309 of file StepUtils.cxx.

2310  {
2311  // mask off high multiplicity TPs at the end
2312  if(!tcc.useAlg[kCHMEH]) return;
2313  if(tj.EndFlag[1][kBragg]) return;
2314  if(tj.Pts.size() < 10) return;
2315  if(tj.Pts[tj.EndPt[1]].AngleCode == 0) return;
2316  // find the average multiplicity in the first half
2317  unsigned short aveMult= 0;
2318  unsigned short ipt, nhalf = tj.Pts.size() / 2;
2319  unsigned short cnt = 0;
2320  for(auto& tp : tj.Pts) {
2321  if(tp.Chg == 0) continue;
2322  aveMult += tp.Hits.size();
2323  ++cnt;
2324  if(cnt == nhalf) break;
2325  } // pt
2326  if(cnt == 0) return;
2327  aveMult /= cnt;
2328  if(aveMult == 0) aveMult = 1;
2329  // convert this into a cut
2330  aveMult *= 3;
2331  cnt = 0;
2332  for(ipt = tj.EndPt[1]; ipt > tj.EndPt[0]; --ipt) {
2333  if(tj.Pts[ipt].Chg == 0) continue;
2334  if(tj.Pts[ipt].Hits.size() > aveMult) {
2335  UnsetUsedHits(slc, tj.Pts[ipt]);
2336  ++cnt;
2337  continue;
2338  }
2339  break;
2340  } // ipt
2341  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"CHMEH multiplicity cut "<<aveMult<<" number of TPs masked off "<<cnt;
2342  if(cnt > 0) {
2343  tj.AlgMod[kCHMEH] = true;
2344  SetEndPoints(tj);
2345  }
2346  } // CheckHiMultEndHits
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3413
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1075
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
void tca::CheckHiMultUnusedHits ( TCSlice &  slc,
Trajectory &  tj 
)

Definition at line 2167 of file StepUtils.cxx.

2168  {
2169  // Check for many unused hits in high multiplicity TPs in work and try to use them
2170 
2171  if(!tcc.useAlg[kCHMUH]) return;
2172 
2173  // This code might do bad things to short trajectories
2174  if(NumPtsWithCharge(slc, tj, true) < 6) return;
2175  if(tj.EndPt[0] == tj.EndPt[1]) return;
2176  // Angle code 0 tjs shouldn't have any high multiplicity hits added to them
2177  if(tj.Pts[tj.EndPt[1]].AngleCode == 0) return;
2178 
2179  // count the number of unused hits multiplicity > 1 hits and decide
2180  // if the unused hits should be used. This may trigger another
2181  // call to StepAway
2182  unsigned short ii, stopPt;
2183  // Use this to see if the high multiplicity Pts are mostly near
2184  // the end or further upstream
2185  unsigned short lastMult1Pt = USHRT_MAX;
2186  // the number of TPs with > 1 hit (HiMult)
2187  unsigned short nHiMultPt = 0;
2188  // the total number of hits associated with HiMult TPs
2189  unsigned short nHiMultPtHits = 0;
2190  // the total number of used hits associated with HiMult TPs
2191  unsigned short nHiMultPtUsedHits = 0;
2192  unsigned int iht;
2193  // start counting at the leading edge and break if a hit
2194  // is found that is used in a trajectory
2195  bool doBreak = false;
2196  unsigned short jj;
2197  for(ii = 1; ii < tj.Pts.size(); ++ii) {
2198  stopPt = tj.EndPt[1] - ii;
2199  for(jj = 0; jj < tj.Pts[stopPt].Hits.size(); ++jj) {
2200  iht = tj.Pts[stopPt].Hits[jj];
2201  if(slc.slHits[iht].InTraj > 0) {
2202  doBreak = true;
2203  break;
2204  }
2205  } // jj
2206  if(doBreak) break;
2207  // require 2 consecutive multiplicity = 1 points
2208  if(lastMult1Pt == USHRT_MAX && tj.Pts[stopPt].Hits.size() == 1 && tj.Pts[stopPt-1].Hits.size() == 1) lastMult1Pt = stopPt;
2209  if(tj.Pts[stopPt].Hits.size() > 1) {
2210  ++nHiMultPt;
2211  nHiMultPtHits += tj.Pts[stopPt].Hits.size();
2212  nHiMultPtUsedHits += NumHitsInTP(tj.Pts[stopPt], kUsedHits);
2213  } // high multiplicity TP
2214  // stop looking when two consecutive single multiplicity TPs are found
2215  if(lastMult1Pt != USHRT_MAX) break;
2216  if(stopPt == 1) break;
2217  } // ii
2218  // Don't do this if there aren't a lot of high multiplicity TPs
2219  float fracHiMult = (float)nHiMultPt / (float)ii;
2220  if(lastMult1Pt != USHRT_MAX) {
2221  float nchk = tj.EndPt[1] - lastMult1Pt + 1;
2222  fracHiMult = (float)nHiMultPt / nchk;
2223  } else {
2224  fracHiMult = (float)nHiMultPt / (float)ii;
2225  }
2226  float fracHitsUsed = 0;
2227  if(nHiMultPt > 0 && nHiMultPtHits > 0) fracHitsUsed = (float)nHiMultPtUsedHits / (float)nHiMultPtHits;
2228  // Use this to limit the number of points fit for trajectories that
2229  // are close the LA tracking cut
2230  ii = tj.EndPt[1];
2231  bool sortaLargeAngle = (AngleRange(tj.Pts[ii]) == 1);
2232 
2233  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"CHMUH: First InTraj stopPt "<<stopPt<<" fracHiMult "<<fracHiMult<<" fracHitsUsed "<<fracHitsUsed<<" lastMult1Pt "<<lastMult1Pt<<" sortaLargeAngle "<<sortaLargeAngle;
2234  if(fracHiMult < 0.3) return;
2235  if(fracHitsUsed > 0.98) return;
2236 
2237  float maxDelta = 2.5 * MaxHitDelta(slc, tj);
2238 
2239  if(tcc.dbgStp) {
2240  mf::LogVerbatim("TC")<<" Pts size "<<tj.Pts.size()<<" nHiMultPt "<<nHiMultPt<<" nHiMultPtHits "<<nHiMultPtHits<<" nHiMultPtUsedHits "<<nHiMultPtUsedHits<<" sortaLargeAngle "<<sortaLargeAngle<<" maxHitDelta "<<maxDelta;
2241  }
2242 
2243  // Use next pass cuts if available
2244  if(sortaLargeAngle && tj.Pass < tcc.minPtsFit.size()-1) ++tj.Pass;
2245 
2246  // Make a copy of tj in case something bad happens
2247  Trajectory TjCopy = tj;
2248  // and the list of used hits
2249  auto inTrajHits = PutTrajHitsInVector(tj, kUsedHits);
2250  unsigned short ipt;
2251 
2252  // unset the used hits from stopPt + 1 to the end
2253  for(ipt = stopPt + 1; ipt < tj.Pts.size(); ++ipt) UnsetUsedHits(slc, tj.Pts[ipt]);
2254  SetEndPoints(tj);
2255  float delta;
2256  bool added;
2257  for(ipt = stopPt + 1; ipt < tj.Pts.size(); ++ipt) {
2258  // add hits that are within maxDelta and re-fit at each point
2259  added = false;
2260  for(ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
2261  iht = tj.Pts[ipt].Hits[ii];
2262  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" ipt "<<ipt<<" hit "<<PrintHit(slc.slHits[iht])<<" inTraj "<<slc.slHits[iht].InTraj<<" delta "<<PointTrajDOCA(slc, iht, tj.Pts[ipt]);
2263  if(slc.slHits[iht].InTraj != 0) continue;
2264  delta = PointTrajDOCA(slc, iht, tj.Pts[ipt]);
2265  if(delta > maxDelta) continue;
2266  if (!NumHitsInTP(TjCopy.Pts[ipt], kUsedHits)||TjCopy.Pts[ipt].UseHit[ii]){
2267  tj.Pts[ipt].UseHit[ii] = true;
2268  slc.slHits[iht].InTraj = tj.ID;
2269  added = true;
2270  }
2271  } // ii
2272  if(added) DefineHitPos(slc, tj.Pts[ipt]);
2273  if(tj.Pts[ipt].Chg == 0) continue;
2274  tj.EndPt[1] = ipt;
2275  // This will be incremented by one in UpdateTraj
2276  if(sortaLargeAngle) tj.Pts[ipt].NTPsFit = 2;
2277  UpdateTraj(slc, tj);
2278  if(tj.NeedsUpdate) {
2279  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"UpdateTraj failed on point "<<ipt;
2280  // Clobber the used hits from the corrupted points in tj
2281  for(unsigned short jpt = stopPt + 1; jpt <= ipt; ++jpt) {
2282  for(unsigned short jj = 0; jj < tj.Pts[jpt].Hits.size(); ++jj) {
2283  if(tj.Pts[jpt].UseHit[jj]) slc.slHits[tj.Pts[jpt].Hits[jj]].InTraj = 0;
2284  } // jj
2285  } // jpt
2286  // restore the original trajectory
2287  tj = TjCopy;
2288  // restore the hits
2289  for(unsigned short jpt = stopPt + 1; jpt <= ipt; ++jpt) {
2290  for(unsigned short jj = 0; jj < tj.Pts[jpt].Hits.size(); ++jj) {
2291  if(tj.Pts[jpt].UseHit[jj]) slc.slHits[tj.Pts[jpt].Hits[jj]].InTraj = tj.ID;
2292  } // jj
2293  } // jpt
2294  return;
2295  }
2296  GottaKink(slc, tj, true);
2297  if(tcc.dbgStp) PrintTrajectory("CHMUH", slc, tj, ipt);
2298  } // ipt
2299  // if we made it here it must be OK
2300  SetEndPoints(tj);
2301  // Try to extend it, unless there was a kink
2302  if(tj.EndFlag[1][kAtKink]) return;
2303  // trim the end points although this shouldn't happen
2304  if(tj.EndPt[1] != tj.Pts.size() - 1) tj.Pts.resize(tj.EndPt[1] + 1);
2305  tj.AlgMod[kCHMUH] = true;
2306  } // CheckHiMultUnusedHits
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3413
void UpdateTraj(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:669
std::vector< unsigned int > PutTrajHitsInVector(const Trajectory &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2754
std::vector< unsigned short > minPtsFit
Reconstruct in several passes.
Definition: DataStructs.h:565
TCConfig tcc
Definition: DataStructs.cxx:9
void PrintTrajectory(std::string someText, const TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:6195
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1075
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2572
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1672
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6516
unsigned short NumHitsInTP(const TrajPoint &tp, HitStatus_t hitRequest)
Definition: Utils.cxx:4328
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
float MaxHitDelta(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:3276
bool GottaKink(TCSlice &slc, Trajectory &tj, bool doTrim)
Definition: StepUtils.cxx:2556
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2116
unsigned short AngleRange(TrajPoint const &tp)
Definition: Utils.cxx:766
void tca::CheckStiffEl ( TCSlice &  slc,
Trajectory &  tj 
)

Definition at line 916 of file StepUtils.cxx.

917  {
918  if(!tj.Strategy[kStiffEl]) return;
919  if(tcc.dbgStp) {
920  mf::LogVerbatim("TC")<<"inside CheckStiffTj with NumPtsWithCharge = "<<NumPtsWithCharge(slc, tj, false);
921  }
922  // Fill in any gaps with hits that were skipped, most likely delta rays on muon tracks
923  FillGaps(slc, tj);
924  // Update the trajectory parameters at the beginning of the trajectory
925  ChkBegin(slc, tj);
926  } // CheckStiffTj
TCConfig tcc
Definition: DataStructs.cxx:9
void FillGaps(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2033
void ChkBegin(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2674
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
use the stiff electron strategy
Definition: DataStructs.h:501
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2116
void tca::CheckTraj ( TCSlice &  slc,
Trajectory &  tj 
)

Definition at line 929 of file StepUtils.cxx.

930  {
931  // Check the quality of the trajectory and possibly trim it or flag it for deletion
932 
933  if(!tj.IsGood) return;
934 
935  // ensure that the end points are defined
936  SetEndPoints(tj);
937  if(tj.EndPt[0] == tj.EndPt[1]) return;
938 
939  if(tj.Strategy[kStiffEl]) {
940  CheckStiffEl(slc, tj);
941  return;
942  }
943 
944  if(tcc.dbgStp) {
945  mf::LogVerbatim("TC")<<"inside CheckTraj with NumPtsWithCharge = "<<NumPtsWithCharge(slc, tj, false);
946  }
947 
948  if(NumPtsWithCharge(slc, tj, false) < tcc.minPts[tj.Pass]) {
949  tj.IsGood = false;
950  return;
951  }
952 
953  // reduce nPtsFit to the minimum and check for a large angle kink near the ends
954 // ChkEndKink(slc, tj, tcc.dbgStp);
955 
956  // Look for a charge asymmetry between points on both sides of a high-
957  // charge point and trim points in the vicinity
958  ChkChgAsymmetry(slc, tj, tcc.dbgStp);
959 
960  // flag this tj as a junk Tj (even though it wasn't created in FindJunkTraj).
961  // Drop it and let FindJunkTraj do it's job
962  TagJunkTj(slc, tj, tcc.dbgStp);
963  if(tj.AlgMod[kJunkTj]) {
964  tj.IsGood = false;
965  return;
966  }
967 
968  tj.MCSMom = MCSMom(slc, tj);
969 
970  // See if the points at the stopping end can be included in the Tj
971  ChkStopEndPts(slc, tj, tcc.dbgStp);
972 
973  // remove any points at the end that don't have charge
974  tj.Pts.resize(tj.EndPt[1] + 1);
975 
976  // Ensure that a hit only appears once in the TJ
977  if(HasDuplicateHits(slc, tj, tcc.dbgStp)) {
978  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" HasDuplicateHits ";
979  tj.IsGood = false;
980  return;
981  }
982 
983  // See if this is a ghost trajectory
984  if(IsGhost(slc, tj)) {
985  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" CT: Ghost trajectory - trimmed hits ";
986  if(!tj.IsGood) return;
987  }
988 
989  if(tj.AlgMod[kJunkTj]) return;
990 
991  // checks are different for Very Large Angle trajectories
992  bool isVLA = (tj.Pts[tj.EndPt[1]].AngleCode == 2);
993 
994  tj.Pts.resize(tj.EndPt[1] + 1);
995 
996  // Fill in any gaps with hits that were skipped, most likely delta rays on muon tracks
997  if(!isVLA) FillGaps(slc, tj);
998 
999  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" CheckTraj MCSMom "<<tj.MCSMom<<" isVLA? "<<isVLA<<" NumPtsWithCharge "<<NumPtsWithCharge(slc, tj, false)<<" Min Req'd "<<tcc.minPts[tj.Pass];
1000 
1001  // Trim the end points until the TJ meets the quality cuts
1002  TrimEndPts("CT", slc, tj, tcc.qualityCuts, tcc.dbgStp);
1003  if(tj.AlgMod[kKilled]) {
1004  tj.IsGood = false;
1005  return;
1006  }
1007 
1008  TrimHiChgEndPts(slc, tj, tcc.dbgStp);
1009 
1010  // Check for a Bragg peak at both ends. This may be used by FixBegin.
1011  ChkStop(slc, tj);
1012 
1013  // Update the trajectory parameters at the beginning of the trajectory
1014  ChkBegin(slc, tj);
1015 
1016  // ignore short trajectories
1017  if(tj.EndPt[1] < 4) return;
1018 
1019  // final quality check
1020  float npwc = NumPtsWithCharge(slc, tj, true);
1021  float npts = tj.EndPt[1] - tj.EndPt[0] + 1;
1022  float frac = npwc / npts;
1023  tj.IsGood = (frac >= tcc.qualityCuts[0]);
1024  if(tj.IsGood && tj.Pass < tcc.minMCSMom.size() && !tj.Strategy[kSlowing]) tj.IsGood = (tj.MCSMom >= tcc.minMCSMom[tj.Pass]);
1025  if(tcc.dbgStp) {
1026  mf::LogVerbatim("TC")<<"CheckTraj: fraction of points with charge "<<frac<<" good traj? "<<tj.IsGood;
1027  }
1028  if(!tj.IsGood || !slc.isValid) return;
1029 
1030  // lop off high multiplicity hits at the end
1031  CheckHiMultEndHits(slc, tj);
1032 
1033  // Check for a Bragg peak at both ends. This may be used by FixBegin.
1034  ChkStop(slc, tj);
1035 
1036  } // CheckTraj
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3468
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3413
bool IsGhost(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2865
std::vector< float > qualityCuts
Min points/wire, min consecutive pts after a gap.
Definition: DataStructs.h:563
TCConfig tcc
Definition: DataStructs.cxx:9
void FillGaps(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2033
void ChkBegin(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2674
void ChkChgAsymmetry(TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:1741
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
use the slowing-down strategy
Definition: DataStructs.h:503
std::vector< short > minMCSMom
Min MCSMom for each pass.
Definition: DataStructs.h:568
void CheckStiffEl(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:916
void TagJunkTj(TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:2782
std::vector< unsigned short > minPts
min number of Pts required to make a trajectory
Definition: DataStructs.h:566
void TrimEndPts(std::string fcnLabel, TCSlice &slc, Trajectory &tj, const std::vector< float > &fQualityCuts, bool prt)
Definition: Utils.cxx:1600
void ChkStop(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:3705
void TrimHiChgEndPts(TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:1557
use the stiff electron strategy
Definition: DataStructs.h:501
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2116
void ChkStopEndPts(TCSlice &slc, Trajectory &tj, bool prt)
Definition: StepUtils.cxx:1562
void CheckHiMultEndHits(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2309
bool HasDuplicateHits(const TCSlice &slc, Trajectory const &tj, bool prt)
Definition: Utils.cxx:2812
void tca::CheckTrajBeginChg ( TCSlice &  slc,
unsigned short  itj 
)

Definition at line 1337 of file Utils.cxx.

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

Definition at line 1841 of file Utils.cxx.

1842  {
1843  // Returns the fraction of wires between tp.Pos[0] and toPos0 that have a hit
1844  // on the line defined by tp.Pos and tp.Dir
1845 
1846  if (tp.Pos[0] < -0.4 || toPos0 < -0.4) return 0;
1847  int fromWire = std::nearbyint(tp.Pos[0]);
1848  int toWire = std::nearbyint(toPos0);
1849 
1850  if (fromWire == toWire) return SignalAtTp(tp);
1851 
1852  int nWires = abs(toWire - fromWire) + 1;
1853 
1854  if (std::abs(tp.Dir[0]) < 0.001) tp.Dir[0] = 0.001;
1855  float stepSize = std::abs(1 / tp.Dir[0]);
1856  // ensure that we step in the right direction
1857  if (toWire > fromWire && tp.Dir[0] < 0) stepSize = -stepSize;
1858  if (toWire < fromWire && tp.Dir[0] > 0) stepSize = -stepSize;
1859  float nsig = 0;
1860  float num = 0;
1861  for (unsigned short cnt = 0; cnt < nWires; ++cnt) {
1862  ++num;
1863  if (SignalAtTp(tp)) ++nsig;
1864  tp.Pos[0] += tp.Dir[0] * stepSize;
1865  tp.Pos[1] += tp.Dir[1] * stepSize;
1866  } // cnt
1867  float sigFrac = nsig / num;
1868  return sigFrac;
1869  } // ChgFracBetween
bool SignalAtTp(TrajPoint &tp)
Definition: Utils.cxx:2004
T abs(T value)
float tca::ChgFracBetween ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice &  slc,
Point3_t  pos1,
Point3_t  pos2 
)

Definition at line 3197 of file PFPUtils.cxx.

3201  {
3202  // Step between pos1 and pos2 and find the fraction of the points that have nearby hits
3203  // in each plane. This function returns -1 if something is fishy, but this doesn't mean
3204  // that there is no charge. Note that there is no check for charge precisely at the pos1 and pos2
3205  // positions
3206  float sep = PosSep(pos1, pos2);
3207  if (sep == 0) return -1;
3208  unsigned short nstep = sep / tcc.wirePitch;
3209  auto dir = PointDirection(pos1, pos2);
3210  float sum = 0;
3211  float cnt = 0;
3212  TrajPoint tp;
3213  for (unsigned short step = 0; step < nstep; ++step) {
3214  for (unsigned short xyz = 0; xyz < 3; ++xyz)
3215  pos1[xyz] += tcc.wirePitch * dir[xyz];
3216  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
3217  tp.CTP = EncodeCTP(slc.TPCID.Cryostat, slc.TPCID.TPC, plane);
3218  tp.Pos[0] =
3219  tcc.geom->WireCoordinate(pos1[1], pos1[2], plane, slc.TPCID.TPC, slc.TPCID.Cryostat);
3220  tp.Pos[1] = detProp.ConvertXToTicks(pos1[0], plane, slc.TPCID.TPC, slc.TPCID.Cryostat) *
3221  tcc.unitsPerTick;
3222  ++cnt;
3223  if (SignalAtTp(tp)) ++sum;
3224  } // plane
3225  } // step
3226  if (cnt == 0) return -1;
3227  return sum / cnt;
3228  } // ChgFracBetween
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
bool SignalAtTp(TrajPoint &tp)
Definition: Utils.cxx:2004
TCConfig tcc
Definition: DataStructs.cxx:9
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:2548
for($it=0;$it< $RaceTrack_number;$it++)
const geo::GeometryCore * geom
Definition: DataStructs.h:576
tuple dir
Definition: dropbox.py:28
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2565
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:52
auto const detProp
float tca::ChgFracNearEnd ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice &  slc,
const PFPStruct &  pfp,
unsigned short  end 
)

Definition at line 3232 of file PFPUtils.cxx.

3236  {
3237  // returns the charge fraction near the end of the pfp. Note that this function
3238  // assumes that there is only one Tj in a plane.
3239  if (pfp.ID == 0) return 0;
3240  if (pfp.TjIDs.empty()) return 0;
3241  if (end < 0 || end > 1) return 0;
3242  if (pfp.TPCID != slc.TPCID) return 0;
3243  if (pfp.SectionFits.empty()) return 0;
3244 
3245  float sum = 0;
3246  float cnt = 0;
3247  // keep track of the lowest value and maybe reject it
3248  float lo = 1;
3249  float hi = 0;
3250  auto pos3 = PosAtEnd(pfp, end);
3251  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
3252  CTP_t inCTP = EncodeCTP(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
3253  std::vector<int> tjids(1);
3254  for (auto tjid : pfp.TjIDs) {
3255  auto& tj = slc.tjs[tjid - 1];
3256  if (tj.CTP != inCTP) continue;
3257  tjids[0] = tjid;
3258  Point2_t pos2;
3259  geo::PlaneID planeID = geo::PlaneID(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
3260  pos2[0] = tcc.geom->WireCoordinate(pos3[1], pos3[2], planeID);
3261  if (pos2[0] < -0.4) continue;
3262  // check for dead wires
3263  unsigned int wire = std::nearbyint(pos2[0]);
3264  if (wire > slc.nWires[plane]) continue;
3265  if (slc.wireHitRange[plane][wire].first == UINT_MAX) continue;
3266  pos2[1] = detProp.ConvertXToTicks(pos3[0], planeID) * tcc.unitsPerTick;
3267  float cf = ChgFracNearPos(slc, pos2, tjids);
3268  if (cf < lo) lo = cf;
3269  if (cf > hi) hi = cf;
3270  sum += cf;
3271  ++cnt;
3272  } // tjid
3273  } // plane
3274  if (cnt == 0) return 0;
3275  if (cnt > 1 && lo < 0.3 && hi > 0.8) {
3276  sum -= lo;
3277  --cnt;
3278  }
3279  return sum / cnt;
3280  } // ChgFracNearEnd
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3293
IDparameter< geo::PlaneID > PlaneID
Member type of validated geo::PlaneID parameter.
std::array< float, 2 > Point2_t
Definition: DataStructs.h:43
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
float ChgFracNearPos(const TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3236
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
const geo::GeometryCore * geom
Definition: DataStructs.h:576
unsigned int CTP_t
Definition: DataStructs.h:47
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:52
auto const detProp
float tca::ChgFracNearPos ( const TCSlice &  slc,
const Point2_t &  pos,
const std::vector< int > &  tjIDs 
)

Definition at line 3236 of file Utils.cxx.

3237  {
3238  // returns the fraction of the charge in the region around pos that is associated with
3239  // the list of Tj IDs
3240  if (tjIDs.empty()) return 0;
3241  std::array<int, 2> wireWindow;
3242  Point2_t timeWindow;
3243  // 1/2 size of the region
3244  constexpr float NNDelta = 5;
3245  wireWindow[0] = pos[0] - NNDelta;
3246  wireWindow[1] = pos[0] + NNDelta;
3247  timeWindow[0] = pos[1] - NNDelta;
3248  timeWindow[1] = pos[1] + NNDelta;
3249  // do some checking
3250  for (auto& tjID : tjIDs)
3251  if (tjID <= 0 || tjID > (int)slc.tjs.size()) return 0;
3252  // Determine which plane we are in
3253  geo::PlaneID planeID = DecodeCTP(slc.tjs[tjIDs[0] - 1].CTP);
3254  // get a list of all hits in this region
3255  bool hitsNear;
3256  std::vector<unsigned int> closeHits =
3257  FindCloseHits(slc, wireWindow, timeWindow, planeID.Plane, kAllHits, true, hitsNear);
3258  if (closeHits.empty()) return 0;
3259  float chg = 0;
3260  float tchg = 0;
3261  // Add the hit charge in the box
3262  // All hits in the box, and all hits associated with the Tjs
3263  for (auto& iht : closeHits) {
3264  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
3265  chg += hit.Integral();
3266  if (slc.slHits[iht].InTraj == 0) continue;
3267  if (std::find(tjIDs.begin(), tjIDs.end(), slc.slHits[iht].InTraj) != tjIDs.end())
3268  tchg += hit.Integral();
3269  } // iht
3270  if (chg == 0) return 0;
3271  return tchg / chg;
3272  } // ChgFracNearPos
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
process_name hit
Definition: cheaterreco.fcl:51
std::array< float, 2 > Point2_t
Definition: DataStructs.h:43
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:2843
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
TCEvent evt
Definition: DataStructs.cxx:8
float tca::ChgToMeV ( float  chg)

Definition at line 3982 of file TCShower.cxx.

3983  {
3984  // Conversion from shower charge to energy in MeV. The calibration factor
3985  // was found by processing 500 pizero events with StudyPiZeros using StudyMode
3986  return 0.012 * chg;
3987  }
bool tca::ChkAssns ( std::string  inFcnLabel,
TCSlice &  slc 
)

Definition at line 4157 of file TCShower.cxx.

4158  {
4159  // check tj - ss assns
4160 
4161  std::string fcnLabel = inFcnLabel + ".ChkAssns";
4162  for (auto& ss : slc.cots) {
4163  if (ss.ID == 0) continue;
4164  for (auto tid : ss.TjIDs) {
4165  auto& tj = slc.tjs[tid - 1];
4166  if (tj.SSID != ss.ID) {
4167  std::cout << fcnLabel << " ***** Error: 2S" << ss.ID << " -> TjIDs T" << tid
4168  << " != tj.SSID 2S" << tj.SSID << "\n";
4169  return false;
4170  }
4171  } // tid
4172  // check 2S -> 3S
4173  if (ss.SS3ID > 0 && ss.SS3ID <= (int)slc.showers.size()) {
4174  auto& ss3 = slc.showers[ss.SS3ID - 1];
4175  if (std::find(ss3.CotIDs.begin(), ss3.CotIDs.end(), ss.ID) == ss3.CotIDs.end()) {
4176  std::cout << fcnLabel << " ***** Error: 2S" << ss.ID << " -> 3S" << ss.SS3ID
4177  << " but the shower says no\n";
4178  return false;
4179  }
4180  } // ss.SS3ID > 0
4181  } // ss
4182  for (auto& tj : slc.tjs) {
4183  if (tj.AlgMod[kKilled]) continue;
4184  if (tj.SSID < 0) {
4185  std::cout << fcnLabel << " ***** Error: T" << tj.ID << " tj.SSID is fubar\n";
4186  tj.SSID = 0;
4187  return false;
4188  }
4189  if (tj.SSID == 0) continue;
4190  auto& ss = slc.cots[tj.SSID - 1];
4191  if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tj.ID) != ss.TjIDs.end()) continue;
4192  std::cout << fcnLabel << " ***** Error: T" << tj.ID << " tj.SSID = 2S" << tj.SSID
4193  << " but the shower says no\n";
4194  return false;
4195  } // tj
4196 
4197  for (auto& ss3 : slc.showers) {
4198  if (ss3.ID == 0) continue;
4199  for (auto cid : ss3.CotIDs) {
4200  auto& ss = slc.cots[cid - 1];
4201  if (ss.SS3ID != ss3.ID) {
4202  std::cout << fcnLabel << " ***** Error: 3S" << ss3.ID << " -> 2S" << cid
4203  << " but it thinks it belongs to 3S" << ss.SS3ID << "\n";
4204  return false;
4205  }
4206  } // cid
4207  } // ss3
4208  return true;
4209  } // ChkAssns
BEGIN_PROLOG could also be cout
void tca::ChkBegin ( TCSlice &  slc,
Trajectory &  tj 
)

Definition at line 2674 of file StepUtils.cxx.

2675  {
2676  // Check the parameters at the start of the trajectory. The first
2677  // points may not belong to this trajectory since they were added when there was
2678  // little information. This information may be updated later if ReversePropagate is used
2679 
2680  if(!tcc.useAlg[kFixBegin]) return;
2681  if(tj.AlgMod[kJunkTj]) return;
2682 
2683  // don't do anything if this tj has been modified by ReversePropagate
2684  if(tj.AlgMod[kRvPrp]) return;
2685 
2686  // don't bother with really short tjs
2687  if(tj.Pts.size() < 3) return;
2688 
2689  unsigned short atPt = tj.EndPt[1];
2690  unsigned short maxPtsFit = 0;
2691  unsigned short firstGoodChgPullPt = USHRT_MAX;
2692  for(unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1]; ++ipt) {
2693  auto& tp = tj.Pts[ipt];
2694  if(tp.Chg == 0) continue;
2695  if(tp.AveChg > 0 && firstGoodChgPullPt == USHRT_MAX) {
2696  if(std::abs(tp.ChgPull) < tcc.chargeCuts[0]) firstGoodChgPullPt = ipt;
2697  } // find the first good charge pull point
2698  if(tp.NTPsFit > maxPtsFit) {
2699  maxPtsFit = tp.NTPsFit;
2700  atPt = ipt;
2701  // no reason to continue if there are a good number of points fitted
2702  if(maxPtsFit > 20) break;
2703  }
2704  } // ipt
2705  // find the first point that is in this fit
2706  unsigned short firstPtFit = tj.EndPt[0];
2707  unsigned short cnt = 0;
2708  for(unsigned short ii = 1; ii < tj.Pts.size(); ++ii) {
2709  if(ii > atPt) break;
2710  unsigned short ipt = atPt - ii;
2711  if(tj.Pts[ipt].Chg == 0) continue;
2712  ++cnt;
2713  if(cnt == maxPtsFit) {
2714  firstPtFit = ipt;
2715  break;
2716  } // full count
2717  } // ii
2718 
2719  bool needsRevProp = firstPtFit > 3;
2720  unsigned short nPtsLeft = NumPtsWithCharge(slc, tj, false) - firstPtFit;
2721  if(needsRevProp) {
2722  needsRevProp = (nPtsLeft > 5);
2723  }
2724  if(tcc.dbgStp) {
2725  mf::LogVerbatim myprt("TC");
2726  myprt<<"CB: firstPtFit "<<firstPtFit<<" at "<<PrintPos(slc, tj.Pts[firstPtFit].Pos);
2727  myprt<<" atPt "<<PrintPos(slc, tj.Pts[atPt].Pos);
2728  myprt<<" nPts with charge "<<nPtsLeft;
2729  myprt<<" firstGoodChgPullPt "<<firstGoodChgPullPt;
2730  if(firstGoodChgPullPt != USHRT_MAX) myprt<<" at "<<PrintPos(slc,tj.Pts[firstGoodChgPullPt]);
2731  myprt<<" needsRevProp? "<<needsRevProp;
2732  }
2733 
2734  if(!needsRevProp && firstGoodChgPullPt == USHRT_MAX) {
2735  // check one wire on the other side of EndPt[0] to see if there are hits that are available which could
2736  // be picked up by reverse propagation
2737  TrajPoint tp = tj.Pts[0];
2738  tp.Hits.clear();
2739  tp.UseHit.reset();
2740  // Move the TP "backwards"
2741  double stepSize = tcc.VLAStepSize;
2742  if(tp.AngleCode < 2) stepSize = std::abs(1/tp.Dir[0]);
2743  tp.Pos[0] -= tp.Dir[0] * stepSize * tj.StepDir;
2744  tp.Pos[1] -= tp.Dir[1] * stepSize * tj.StepDir;
2745  // launch RevProp if this wire is dead
2746  unsigned int wire = std::nearbyint(tp.Pos[0]);
2747  unsigned short plane = DecodeCTP(tp.CTP).Plane;
2748  needsRevProp = (wire < slc.nWires[plane] && !evt.goodWire[plane][wire]);
2749  if(tcc.dbgStp && needsRevProp) mf::LogVerbatim("TC")<<"CB: Previous wire "<<wire<<" is dead. Call ReversePropagate";
2750  if(!needsRevProp && firstGoodChgPullPt != USHRT_MAX) {
2751  // check for hits on a not-dead wire
2752  // BB May 20, 2019 Do this more carefully
2753  float maxDelta = 2 * tp.DeltaRMS;
2754  if(FindCloseHits(slc, tp, maxDelta, kAllHits) && !tp.Hits.empty()) {
2755  // count used and unused hits
2756  unsigned short nused = 0;
2757  for(auto iht : tp.Hits) if(slc.slHits[iht].InTraj > 0) ++nused;
2758  if(nused == 0) {
2759  needsRevProp = true;
2760  if(tcc.dbgStp) {
2761  mf::LogVerbatim("TC")<<"CB: Found "<<tp.Hits.size()-nused<<" close unused hits found near EndPt[0] "<<PrintPos(slc, tp)<<". Call ReversePropagate";
2762  } // tcc.dbgStp
2763  } // nused = 0
2764  } // Close hits exist
2765  } // !needsRevProp
2766  } // !needsRevProp
2767 
2768  if(tcc.dbgStp) {
2769  mf::LogVerbatim("TC")<<"CB: maxPtsFit "<<maxPtsFit<<" at point "<<atPt<<" firstPtFit "<<firstPtFit<<" Needs ReversePropagate? "<<needsRevProp;
2770  }
2771 
2772  if(tcc.useAlg[kFTBRvProp] && needsRevProp) {
2773  // lop off the points before firstPtFit and reverse propagate
2774  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" clobber TPs "<<PrintPos(slc, tj.Pts[0])<<" to "<<PrintPos(slc, tj.Pts[firstPtFit])<<". Call TrimEndPts then ReversePropagate ";
2775  // first save the first TP on this trajectory. We will try to re-use it if
2776  // it isn't used during reverse propagation
2777  seeds.push_back(tj.Pts[0]);
2778  for(unsigned short ipt = 0; ipt <= firstPtFit; ++ipt) UnsetUsedHits(slc, tj.Pts[ipt]);
2779  SetEndPoints(tj);
2780  tj.AlgMod[kFTBRvProp] = true;
2781  // Check for quality and trim if necessary before reverse propagation
2782  TrimEndPts("RPi", slc, tj, tcc.qualityCuts, tcc.dbgStp);
2783  if(tj.AlgMod[kKilled]) {
2784  tj.IsGood = false;
2785  return;
2786  }
2787  ReversePropagate(slc, tj);
2788  ChkStopEndPts(slc, tj, tcc.dbgStp);
2789  }
2790  if(firstGoodChgPullPt != USHRT_MAX && firstGoodChgPullPt > atPt) atPt = firstGoodChgPullPt;
2791  // Update the fit parameters of the first points if no reverse propagation was done
2792  if(!tj.AlgMod[kRvPrp]) FixBegin(slc, tj, atPt);
2793 
2794  } // ChkBegin
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3413
std::vector< float > qualityCuts
Min points/wire, min consecutive pts after a gap.
Definition: DataStructs.h:563
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1075
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
T abs(T value)
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:630
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:2843
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
void FixBegin(TCSlice &slc, Trajectory &tj, unsigned short atPt)
Definition: StepUtils.cxx:2797
void TrimEndPts(std::string fcnLabel, TCSlice &slc, Trajectory &tj, const std::vector< float > &fQualityCuts, bool prt)
Definition: Utils.cxx:1600
std::vector< float > chargeCuts
Definition: DataStructs.h:562
std::vector< TrajPoint > seeds
Definition: DataStructs.cxx:14
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
float VLAStepSize
Definition: DataStructs.h:584
geo::PlaneID DecodeCTP(CTP_t CTP)
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2116
TCEvent evt
Definition: DataStructs.cxx:8
void ChkStopEndPts(TCSlice &slc, Trajectory &tj, bool prt)
Definition: StepUtils.cxx:1562
void ReversePropagate(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:1316
void tca::ChkChgAsymmetry ( TCSlice &  slc,
Trajectory &  tj,
bool  prt 
)

Definition at line 1741 of file Utils.cxx.

1742  {
1743  // looks for a high-charge point in the trajectory which may be due to the
1744  // trajectory crossing an interaction vertex. The properties of points on the opposite
1745  // sides of the high-charge point are analyzed. If significant differences are found, all points
1746  // near the high-charge point are removed as well as those from that point to the end
1747  if (!tcc.useAlg[kChkChgAsym]) return;
1748  if (tj.PDGCode == 111) return;
1749  unsigned short npts = tj.EndPt[1] - tj.EndPt[0];
1750  if (prt) mf::LogVerbatim("TC") << " Inside ChkChgAsymmetry T" << tj.ID;
1751  // ignore long tjs
1752  if (npts > 50) return;
1753  // ignore short tjs
1754  if (npts < 8) return;
1755  // require the charge pull > 5
1756  float bigPull = 5;
1757  unsigned short atPt = 0;
1758  // Don't consider the first/last few points in case there is a Bragg peak
1759  for (unsigned short ipt = tj.EndPt[0] + 2; ipt <= tj.EndPt[1] - 2; ++ipt) {
1760  auto& tp = tj.Pts[ipt];
1761  if (tp.ChgPull > bigPull) {
1762  bigPull = tp.ChgPull;
1763  atPt = ipt;
1764  }
1765  } // ipt
1766  if (atPt == 0) return;
1767  // require that this point be near the DS end
1768  if ((atPt - tj.EndPt[0]) < 0.5 * npts) return;
1769  if (prt)
1770  mf::LogVerbatim("TC") << "CCA: T" << tj.ID << " Large Chg point at " << atPt
1771  << ". Check charge asymmetry around it.";
1772  unsigned short nchk = 0;
1773  unsigned short npos = 0;
1774  unsigned short nneg = 0;
1775  for (short ii = 1; ii < 5; ++ii) {
1776  short iplu = atPt + ii;
1777  if (iplu > tj.EndPt[1]) break;
1778  short ineg = atPt - ii;
1779  if (ineg < tj.EndPt[0]) break;
1780  if (tj.Pts[iplu].Chg == 0) continue;
1781  if (tj.Pts[ineg].Chg == 0) continue;
1782  float asym = (tj.Pts[iplu].Chg - tj.Pts[ineg].Chg) / (tj.Pts[iplu].Chg + tj.Pts[ineg].Chg);
1783  ++nchk;
1784  if (asym > 0.5) ++npos;
1785  if (asym < -0.5) ++nneg;
1786  if (prt)
1787  mf::LogVerbatim("TC") << " ineg " << ineg << " iplu " << iplu << " asym " << asym
1788  << " nchk " << nchk;
1789  } // ii
1790  if (nchk < 3) return;
1791  // require most of the points be very positive or very negative
1792  nchk -= 2;
1793  bool doTrim = (nneg > nchk) || (npos > nchk);
1794  if (!doTrim) return;
1795  // remove all the points at the end starting at the one just before the peak if the pull is not so good
1796  auto& prevTP = tj.Pts[atPt - 1];
1797  if (std::abs(prevTP.ChgPull) > 2) --atPt;
1798  for (unsigned short ipt = atPt; ipt <= tj.EndPt[1]; ++ipt)
1799  UnsetUsedHits(slc, tj.Pts[ipt]);
1800  SetEndPoints(tj);
1801  tj.AlgMod[kChkChgAsym] = true;
1802  if (prt) PrintTrajectory("CCA", slc, tj, USHRT_MAX);
1803  } // ChkChgAsymmetry
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3413
TCConfig tcc
Definition: DataStructs.cxx:9
void PrintTrajectory(std::string someText, const TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:6195
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1075
T abs(T value)
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
void tca::ChkEndKink ( TCSlice &  slc,
Trajectory &  tj,
bool  prt 
)

Definition at line 1707 of file Utils.cxx.

1708  {
1709  // look for large-angle kink near the end
1710  if (!tcc.useAlg[kEndKink]) return;
1711  if (tj.PDGCode == 111) return;
1712  if (tj.EndPt[1] - tj.EndPt[0] < 6) return;
1713 
1714  if (prt) mf::LogVerbatim("TC") << "CEK: Inside ChkEndKinks T" << tj.ID << " ";
1715 
1716  float maxSig = tcc.kinkCuts[1];
1717  unsigned short withNptsFit = 0;
1718  unsigned short nPtsFit = tcc.kinkCuts[0];
1719  bool useChg = (tcc.kinkCuts[2] > 0);
1720  for (unsigned short nptsf = 3; nptsf < nPtsFit; ++nptsf) {
1721  unsigned short ipt = tj.EndPt[1] - nptsf;
1722  float ks = KinkSignificance(slc, tj, ipt, nptsf, useChg, prt);
1723  if (ks > maxSig) {
1724  maxSig = ks;
1725  withNptsFit = nptsf;
1726  }
1727  } // nptsf
1728  if (withNptsFit > 0) {
1729  unsigned short ipt = tj.EndPt[1] - withNptsFit;
1730  std::cout << "CEK: T" << tj.ID << " ipt " << ipt;
1731  float ks = KinkSignificance(slc, tj, ipt, withNptsFit, false, prt);
1732  auto& tp = tj.Pts[ipt];
1733  std::cout << " " << PrintPos(slc, tp) << " withNptsFit " << withNptsFit << " ks " << ks
1734  << "\n";
1735  }
1736 
1737  } // ChkEndKink
std::vector< float > kinkCuts
kink finder algorithm
Definition: DataStructs.h:559
TCConfig tcc
Definition: DataStructs.cxx:9
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
float KinkSignificance(TCSlice &slc, Trajectory &tj1, unsigned short end1, Trajectory &tj2, unsigned short end2, unsigned short nPtsFit, bool useChg, bool prt)
Definition: Utils.cxx:3056
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
BEGIN_PROLOG could also be cout
bool tca::ChkMichel ( TCSlice &  slc,
Trajectory &  tj,
unsigned short &  lastGoodPt 
)

Definition at line 3811 of file StepUtils.cxx.

3811  {
3812 
3813  if(!tcc.useAlg[kMichel]) return false;
3814  if(tj.PDGCode == 11 || tj.PDGCode == 111) return false;
3815 
3816  bool prt = (tcc.dbgStp || tcc.dbgAlg[kMichel]);
3817 
3818  //find number of hits that are consistent with Michel electron
3819  unsigned short nmichelhits = 0;
3820  //find number of hits that are consistent with Bragg peak
3821  unsigned short nbragghits = 0;
3822  float lastChg = 0;
3823 
3824  bool isfirsthit = true;
3825  unsigned short braggpeak = 0;
3826 
3827  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
3828  if (ii>tj.EndPt[1]) continue;
3829  unsigned short ipt = tj.EndPt[1] - ii;
3830  if (tj.Pts[ipt].Chg>0){
3831  if (isfirsthit){
3832  isfirsthit = false;
3833  if (tj.Pts[ipt].ChgPull<0){
3834  ++nmichelhits;
3835  }
3836  }
3837  else{
3838  if (tj.Pts[ipt].ChgPull<0&&nmichelhits&&!nbragghits){//still Michel
3839  ++nmichelhits;
3840  }
3841  else{
3842  if (!nbragghits){
3843  ++nbragghits; //Last Bragg peak hit
3844  lastChg = tj.Pts[ipt].Chg;
3845  braggpeak = ipt;
3846  }
3847  else if (tj.Pts[ipt].Chg<lastChg){ //still Bragg peak
3848  ++nbragghits;
3849  lastChg = tj.Pts[ipt].Chg;
3850  }
3851  else break;
3852  }
3853  }
3854  }
3855  }
3856  if(prt) mf::LogVerbatim("TC")<<"ChkMichel Michel hits: "<<nmichelhits<<" Bragg peak hits: "<<nbragghits;
3857  if (nmichelhits>0&&nbragghits>2){//find Michel topology
3858  lastGoodPt = braggpeak;
3859  tj.AlgMod[kMichel] = true;
3860  return true;
3861  }
3862  else{
3863  return false;
3864  }
3865  }
TCConfig tcc
Definition: DataStructs.cxx:9
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:587
void tca::ChkMissedKink ( TCSlice &  slc,
Trajectory &  tj,
bool  prt 
)
void tca::ChkStop ( TCSlice &  slc,
Trajectory &  tj 
)

Definition at line 3705 of file StepUtils.cxx.

3706  {
3707  // Sets the EndFlag[kBragg] bits on the trajectory by identifying the Bragg peak
3708  // at each end. This function checks both ends, finding the point with the highest charge nearest the
3709  // end and considering the first (when end = 0) 4 points or last 4 points (when end = 1). The next
3710  // 5 - 10 points (fChkStop[0]) are fitted to a line, Q(x - x0) = Qo + (x - x0) * slope where x0 is the
3711  // wire position of the highest charge point. A large negative slope indicates that there is a Bragg
3712  // peak at the end.
3713 
3714  tj.EndFlag[0][kBragg] = false;
3715  tj.EndFlag[1][kBragg] = false;
3716  if(!tcc.useAlg[kChkStop]) return;
3717  if(tcc.chkStopCuts[0] < 0) return;
3718 
3719  if(tj.Strategy[kStiffEl]) return;
3720 
3721  // ignore trajectories that are very large angle at both ends
3722  if(tj.Pts[tj.EndPt[0]].AngleCode == 2 || tj.Pts[tj.EndPt[1]].AngleCode == 2) return;
3723 
3724  unsigned short nPtsToCheck = tcc.chkStopCuts[1];
3725  if(tj.Pts.size() < 6) return;
3726 
3727  bool prt = (tcc.dbgStp || tcc.dbgAlg[kChkStop]);
3728 
3729  if(prt) {
3730  mf::LogVerbatim("TC")<<"ChkStop: T"<<tj.ID<<" requiring "<<nPtsToCheck<<" points with charge slope > "<<tcc.chkStopCuts[0]<<" Chg/WSEU";
3731  }
3732 
3733  // find the highest charge hit in the first 3 points at each end
3734  for(unsigned short end = 0; end < 2; ++end) {
3735  tj.EndFlag[end][kBragg] = false;
3736  // require that the end point is reasonably clean
3737  auto& endTP = tj.Pts[tj.EndPt[end]];
3738  if(endTP.Hits.size() > 2) continue;
3739  if(endTP.Environment[kEnvUnusedHits]) continue;
3740  short dir = 1 - 2 * end;
3741  // find the point with the highest charge considering the first 3 points
3742  float big = 0;
3743  unsigned short hiPt = 0;
3744  float wire0 = 0;
3745  for(unsigned short ii = 0; ii < 5; ++ii) {
3746  short ipt = tj.EndPt[end] + ii * dir;
3747  if(ipt < tj.EndPt[0] || ipt > tj.EndPt[1]) break;
3748  TrajPoint& tp = tj.Pts[ipt];
3749  if(tp.Chg > big) {
3750  big = tp.Chg;
3751  wire0 = tp.Pos[0];
3752  hiPt = ipt;
3753  }
3754  } // ii
3755  // ensure that the high point is closer to the end that is being
3756  // considered than to the other end
3757  short dpt0 = hiPt - tj.EndPt[0];
3758  short dpt1 = tj.EndPt[1] - hiPt;
3759  if(end == 0 && dpt1 <= dpt0) continue;
3760  if(end == 1 && dpt0 <= dpt1) continue;
3761  if(prt) mf::LogVerbatim("TC")<<" end "<<end<<" wire0 "<<wire0<<" Chg "<<big<<" hiPt "<<hiPt;
3762  float prevChg = big;
3763  // prepare to do the fit
3764  Point2_t inPt;
3765  Vector2_t outVec, outVecErr;
3766  float chgErr, chiDOF;
3767  // Initialize
3768  Fit2D(0, inPt, chgErr, outVec, outVecErr, chiDOF);
3769  unsigned short cnt = 0;
3770  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
3771  short ipt = hiPt + ii * dir;
3772  if(ipt < tj.EndPt[0] || ipt > tj.EndPt[1]) break;
3773  TrajPoint& tp = tj.Pts[ipt];
3774  if(tp.Chg == 0) continue;
3775  // quit if the charge is much larger than the previous charge
3776  if(tp.Chg > 1.5 * prevChg) continue;
3777  prevChg = tp.Chg;
3778  // Accumulate and save points
3779  inPt[0] = std::abs(tp.Pos[0] - wire0);
3780  inPt[1] = tp.Chg;
3781  // Assume 20% point-to-point charge fluctuations
3782  chgErr = 0.2 * tp.Chg;
3783  if(!Fit2D(2, inPt, chgErr, outVec, outVecErr, chiDOF)) break;
3784  ++cnt;
3785  if(cnt == nPtsToCheck) break;
3786  } // ii
3787  if(cnt < nPtsToCheck) continue;
3788  // do the fit and get the results
3789  if(!Fit2D(-1, inPt, chgErr, outVec, outVecErr, chiDOF)) continue;
3790  // check for really bad chidof indicating a major failure
3791  if(chiDOF > 500) continue;
3792  // The charge slope is negative for a stopping track in the way that the fit was constructed.
3793  // Flip the sign so we can make a cut against tcc.chkStopCuts[0] which is positive.
3794  outVec[1] = -outVec[1];
3795  bool itStops = (outVec[1] > tcc.chkStopCuts[0] && chiDOF < tcc.chkStopCuts[2] && outVec[1] > 2.5 * outVecErr[1]);
3796  if(itStops) {
3797  tj.EndFlag[end][kBragg] = true;
3798  tj.AlgMod[kChkStop] = true;
3799  if(tj.PDGCode == 11) tj.PDGCode = 0;
3800  // Put the charge at the end into tp.AveChg
3801  tj.Pts[tj.EndPt[end]].AveChg = outVec[0];
3802  if(prt) mf::LogVerbatim("TC")<<" end "<<end<<" fit chidof "<<chiDOF<<" slope "<<outVec[1]<<" +/- "<<outVecErr[1]<<" stopping";
3803  } else {
3804  if(prt) mf::LogVerbatim("TC")<<" end "<<end<<" fit chidof "<<chiDOF<<" slope "<<outVec[1]<<" +/- "<<outVecErr[1]<<" Not stopping";
3805  }
3806  } // end
3807 
3808  } // ChkStop
TCConfig tcc
Definition: DataStructs.cxx:9
T abs(T value)
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
std::array< float, 2 > Point2_t
Definition: DataStructs.h:43
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
bool Fit2D(short mode, Point2_t inPt, float &inPtErr, Vector2_t &outVec, Vector2_t &outVecErr, float &chiDOF)
Definition: Utils.cxx:5129
std::array< double, 2 > Vector2_t
Definition: DataStructs.h:44
tuple dir
Definition: dropbox.py:28
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:587
use the stiff electron strategy
Definition: DataStructs.h:501
std::vector< float > chkStopCuts
Bragg peak finder configuration.
Definition: DataStructs.h:557
void tca::ChkStopEndPts ( TCSlice &  slc,
Trajectory &  tj,
bool  prt 
)

Definition at line 1562 of file StepUtils.cxx.

1563  {
1564  // Analyze the end of the Tj after crawling has stopped to see if any of the points
1565  // should be used
1566 
1567  if(tj.EndFlag[1][kAtKink]) return;
1568  if(!tcc.useAlg[kChkStopEP]) return;
1569  if(tj.AlgMod[kJunkTj]) return;
1570  if(tj.Strategy[kStiffEl]) return;
1571 
1572  unsigned short endPt = tj.EndPt[1];
1573  // ignore VLA Tjs
1574  if(tj.Pts[endPt].AngleCode > 1) return;
1575  // don't get too carried away with this
1576  if(tj.Pts.size() - endPt > 10) return;
1577 
1578  // Get a list of hits a few wires beyond the last point on the Tj
1579  geo::PlaneID planeID = DecodeCTP(tj.CTP);
1580  unsigned short plane = planeID.Plane;
1581 
1582  // find the last point that has hits on it
1583  unsigned short lastPt = tj.Pts.size() - 1;
1584  for(lastPt = tj.Pts.size() - 1; lastPt >= tj.EndPt[1]; --lastPt) if(!tj.Pts[lastPt].Hits.empty()) break;
1585  auto& lastTP = tj.Pts[lastPt];
1586 
1587  if(tcc.dbgStp) {
1588  mf::LogVerbatim("TC")<<"CSEP: checking "<<tj.ID<<" endPt "<<endPt<<" Pts size "<<tj.Pts.size()<<" lastPt Pos "<<PrintPos(slc, lastTP.Pos);
1589  }
1590  TrajPoint ltp;
1591  ltp.CTP = tj.CTP;
1592  ltp.Pos = tj.Pts[endPt].Pos;
1593  ltp.Dir = tj.Pts[endPt].Dir;
1594  double stepSize = std::abs(1/ltp.Dir[0]);
1595  std::array<int, 2> wireWindow;
1596  std::array<float, 2> timeWindow;
1597  std::vector<int> closeHits;
1598  bool isClean = true;
1599  for(unsigned short step = 0; step < 10; ++step) {
1600  for(unsigned short iwt = 0; iwt < 2; ++iwt) ltp.Pos[iwt] += ltp.Dir[iwt] * stepSize;
1601  int wire = std::nearbyint(ltp.Pos[0]);
1602  wireWindow[0] = wire;
1603  wireWindow[1] = wire;
1604  timeWindow[0] = ltp.Pos[1] - 5;
1605  timeWindow[1] = ltp.Pos[1] + 5;
1606  bool hitsNear;
1607  auto tmp = FindCloseHits(slc, wireWindow, timeWindow, plane, kAllHits, true, hitsNear);
1608  // add close hits that are not associated with this tj
1609  for(auto iht : tmp) if(slc.slHits[iht].InTraj != tj.ID) closeHits.push_back(iht);
1610  float nWiresPast = 0;
1611  // Check beyond the end of the trajectory to see if there are hits there
1612  if(ltp.Dir[0] > 0) {
1613  // stepping +
1614  nWiresPast = ltp.Pos[0] - lastTP.Pos[0];
1615  } else {
1616  // stepping -
1617  nWiresPast = lastTP.Pos[0] - ltp.Pos[0];
1618  }
1619  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Found "<<tmp.size()<<" hits near pos "<<PrintPos(slc, ltp.Pos)<<" nWiresPast "<<nWiresPast;
1620  if(nWiresPast > 0.5) {
1621  if(!tmp.empty()) isClean = false;
1622  if(nWiresPast > 1.5) break;
1623  } // nWiresPast > 0.5
1624  } // step
1625 
1626  // count the number of available hits
1627  unsigned short nAvailable = 0;
1628  for(auto iht : closeHits) if(slc.slHits[iht].InTraj == 0) ++nAvailable;
1629 
1630  if(tcc.dbgStp) {
1631  mf::LogVerbatim myprt("TC");
1632  myprt<<"closeHits";
1633  for(auto iht : closeHits) myprt<<" "<<PrintHit(slc.slHits[iht]);
1634  myprt<<" nAvailable "<<nAvailable;
1635  myprt<<" isClean "<<isClean;
1636  } // prt
1637 
1638  if(!isClean || nAvailable != closeHits.size()) return;
1639 
1640  unsigned short originalEndPt = tj.EndPt[1] + 1;
1641  // looks clean so use all the hits
1642  for(unsigned short ipt = originalEndPt; ipt <= lastPt; ++ipt) {
1643  auto& tp = tj.Pts[ipt];
1644  bool hitsAdded = false;
1645  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1646  // This shouldn't happen but check anyway
1647  if(slc.slHits[tp.Hits[ii]].InTraj != 0) continue;
1648  tp.UseHit[ii] = true;
1649  slc.slHits[tp.Hits[ii]].InTraj = tj.ID;
1650  hitsAdded = true;
1651  } // ii
1652  if(hitsAdded) DefineHitPos(slc, tp);
1653  } // ipt
1654  tj.AlgMod[kChkStopEP] = true;
1655  SetEndPoints(tj);
1656  // Re-fitting the end might be a good idea but it's probably not necessary. The
1657  // values of Delta should have already been filled
1658 
1659  // require a Bragg peak
1660  ChkStop(slc, tj);
1661  if(!tj.EndFlag[1][kBragg]) {
1662  // restore the original
1663  for(unsigned short ipt = originalEndPt; ipt <= lastPt; ++ipt) UnsetUsedHits(slc, tj.Pts[ipt]);
1664  SetEndPoints(tj);
1665  } // no Bragg Peak
1666 
1667  UpdateTjChgProperties("CSEP", slc, tj, prt);
1668 
1669  } // ChkStopEndPts
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3413
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1075
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
T abs(T value)
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1672
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:2843
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6516
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3673
void ChkStop(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:3705
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
geo::PlaneID DecodeCTP(CTP_t CTP)
use the stiff electron strategy
Definition: DataStructs.h:501
bool tca::ChkVtxAssociations ( TCSlice &  slc,
const CTP_t &  inCTP 
)

Definition at line 2071 of file TCVertex.cxx.

2072  {
2073  // Check the associations
2074 
2075  // check the 2D -> 3D associations
2076  geo::PlaneID planeID = DecodeCTP(inCTP);
2077  unsigned short plane = planeID.Plane;
2078  for (auto& vx2 : slc.vtxs) {
2079  if (vx2.CTP != inCTP) continue;
2080  if (vx2.ID == 0) continue;
2081  if (vx2.Vx3ID == 0) continue;
2082  if (vx2.Vx3ID > int(slc.vtx3s.size())) {
2083  mf::LogVerbatim("TC") << "ChkVtxAssociations: Invalid vx2.Vx3ID " << vx2.Vx3ID
2084  << " in 2D vtx " << vx2.ID;
2085  return false;
2086  }
2087  auto& vx3 = slc.vtx3s[vx2.Vx3ID - 1];
2088  if (vx3.ID == 0) {
2089  mf::LogVerbatim("TC") << "ChkVtxAssociations: 2V" << vx2.ID << " thinks it is matched to 3V"
2090  << vx3.ID << " but vx3 is obsolete";
2091  return false;
2092  }
2093  if (vx3.Vx2ID[plane] != vx2.ID) {
2094  mf::LogVerbatim("TC") << "ChkVtxAssociations: 2V" << vx2.ID << " thinks it is matched to 3V"
2095  << vx3.ID << " but vx3 says no!";
2096  return false;
2097  }
2098  } // vx2
2099  // check the 3D -> 2D associations
2100  for (auto& vx3 : slc.vtx3s) {
2101  if (vx3.ID == 0) continue;
2102  if (vx3.Vx2ID[plane] == 0) continue;
2103  if (vx3.Vx2ID[plane] > (int)slc.vtxs.size()) {
2104  mf::LogVerbatim("TC") << "ChkVtxAssociations: Invalid vx3.Vx2ID " << vx3.Vx2ID[plane]
2105  << " in CTP " << inCTP;
2106  return false;
2107  }
2108  auto& vx2 = slc.vtxs[vx3.Vx2ID[plane] - 1];
2109  if (vx2.Vx3ID != vx3.ID) {
2110  mf::LogVerbatim("TC") << "ChkVtxAssociations: 3V" << vx3.ID << " thinks it is matched to 2V"
2111  << vx2.ID << " but vx2 says no!";
2112  return false;
2113  }
2114  } // vx3
2115 
2116  // check the Tj -> 2D associations
2117  for (auto& tj : slc.tjs) {
2118  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
2119  for (unsigned short end = 0; end < 2; ++end) {
2120  if (tj.VtxID[end] == 0) continue;
2121  if (tj.VtxID[end] > slc.vtxs.size()) {
2122  mf::LogVerbatim("TC") << "ChkVtxAssociations: T" << tj.ID << " thinks it is matched to 2V"
2123  << tj.VtxID[end] << " on end " << end
2124  << " but no vertex exists. Recovering";
2125  tj.VtxID[end] = 0;
2126  return false;
2127  }
2128  unsigned short ivx = tj.VtxID[end] - 1;
2129  auto& vx2 = slc.vtxs[ivx];
2130  if (vx2.ID == 0) {
2131  mf::LogVerbatim("TC") << "ChkVtxAssociations: T" << tj.ID << " thinks it is matched to 2V"
2132  << tj.VtxID[end] << " on end " << end
2133  << " but the vertex is killed. Fixing the Tj";
2134  tj.VtxID[end] = 0;
2135  return false;
2136  }
2137  } // end
2138  } // tj
2139 
2140  return true;
2141 
2142  } // ChkVtxAssociations
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
geo::PlaneID DecodeCTP(CTP_t CTP)
void tca::ClearCRInfo ( TCSlice &  slc)

Definition at line 118 of file TCCR.cxx.

119  {
120  slc.crt.cr_origin.clear();
121  slc.crt.cr_pfpxmin.clear();
122  slc.crt.cr_pfpxmax.clear();
123  slc.crt.cr_pfpyzmindis.clear();
124  }
void tca::ClearShowerTree ( ShowerTreeVars &  stv)

Definition at line 212 of file TCShTree.cxx.

212  {
213  stv.BeginWir.clear();
214  stv.BeginTim.clear();
215  stv.BeginAng.clear();
216  stv.BeginChg.clear();
217  stv.BeginVtx.clear();
218  stv.EndWir.clear();
219  stv.EndTim.clear();
220  stv.EndAng.clear();
221  stv.EndChg.clear();
222  stv.EndVtx.clear();
223  stv.MCSMom.clear();
224  stv.PlaneNum.clear();
225  stv.TjID.clear();
226  stv.IsShowerTj.clear();
227  stv.ShowerID.clear();
228  stv.IsShowerParent.clear();
229  stv.StageNum.clear();
230  stv.Envelope.clear();
231  stv.EnvPlane.clear();
232  stv.EnvStage.clear();
233  stv.EnvShowerID.clear();
234 
235  return;
236 
237  } // ClearShowerTree
std::vector< int > EnvStage
Definition: DataStructs.h:411
std::vector< int > IsShowerParent
Definition: DataStructs.h:404
std::vector< float > EndWir
Definition: DataStructs.h:391
std::vector< float > EndAng
Definition: DataStructs.h:393
std::vector< float > BeginTim
Definition: DataStructs.h:387
std::vector< float > BeginAng
Definition: DataStructs.h:388
std::vector< float > EndTim
Definition: DataStructs.h:392
std::vector< int > ShowerID
Definition: DataStructs.h:403
ShowerTreeVars stv
Definition: DataStructs.cxx:11
std::vector< int > TjID
Definition: DataStructs.h:401
std::vector< short > BeginVtx
Definition: DataStructs.h:390
std::vector< short > EndVtx
Definition: DataStructs.h:395
std::vector< float > Envelope
Definition: DataStructs.h:409
std::vector< float > BeginChg
Definition: DataStructs.h:389
std::vector< int > EnvPlane
Definition: DataStructs.h:410
std::vector< short > MCSMom
Definition: DataStructs.h:397
std::vector< int > StageNum
Definition: DataStructs.h:405
std::vector< float > BeginWir
Definition: DataStructs.h:386
std::vector< float > EndChg
Definition: DataStructs.h:394
std::vector< int > EnvShowerID
Definition: DataStructs.h:412
std::vector< int > IsShowerTj
Definition: DataStructs.h:402
std::vector< short > PlaneNum
Definition: DataStructs.h:399
unsigned short tca::CloseEnd ( const TCSlice &  slc,
const Trajectory &  tj,
const Point2_t &  pos 
)

Definition at line 2551 of file Utils.cxx.

2552  {
2553  unsigned short endPt = tj.EndPt[0];
2554  auto& tp0 = tj.Pts[endPt];
2555  endPt = tj.EndPt[1];
2556  auto& tp1 = tj.Pts[endPt];
2557  if (PosSep2(tp0.Pos, pos) < PosSep2(tp1.Pos, pos)) return 0;
2558  return 1;
2559  } // CloseEnd
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2572
bool tca::CompatibleMerge ( const TCSlice &  slc,
std::vector< int > &  tjIDs,
bool  prt 
)

Definition at line 580 of file Utils.cxx.

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

Definition at line 652 of file Utils.cxx.

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

Definition at line 2490 of file TCVertex.cxx.

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

Definition at line 2396 of file TCVertex.cxx.

2397  {
2398 
2399  if (!tcc.useAlg[kComp3DVxIG]) return;
2400  if (slc.nPlanes != 3) return;
2401 
2402  bool prt = (tcc.modes[kDebug] && tcc.dbgSlc && tcc.dbgAlg[kComp3DVxIG]);
2403  if (prt) mf::LogVerbatim("TC") << "Inside CI3DVIG:";
2404 
2405  for (unsigned short iv3 = 0; iv3 < slc.vtx3s.size(); ++iv3) {
2406  Vtx3Store& vx3 = slc.vtx3s[iv3];
2407  // ignore obsolete vertices
2408  if (vx3.ID == 0) continue;
2409  // check for a completed 3D vertex
2410  if (vx3.Wire < 0) continue;
2411  unsigned short mPlane = USHRT_MAX;
2412  for (unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
2413  if (vx3.Vx2ID[ipl] > 0) continue;
2414  mPlane = ipl;
2415  break;
2416  } // ipl
2417  if (mPlane == USHRT_MAX) continue;
2418  CTP_t mCTP = EncodeCTP(vx3.TPCID.Cryostat, vx3.TPCID.TPC, mPlane);
2419  // require that the missing vertex be in a large block of dead wires
2420  float dwc = DeadWireCount(slc, vx3.Wire - 4, vx3.Wire + 4, mCTP);
2421  if (dwc < 5) continue;
2422  // X position of the purported missing vertex
2423  VtxStore aVtx;
2424  aVtx.ID = slc.vtxs.size() + 1;
2425  aVtx.Pos[0] = vx3.Wire;
2426  aVtx.Pos[1] = detProp.ConvertXToTicks(vx3.X, mPlane, vx3.TPCID.TPC, vx3.TPCID.Cryostat) *
2427  tcc.unitsPerTick;
2428  aVtx.CTP = mCTP;
2429  aVtx.Topo = 4;
2430  aVtx.NTraj = 0;
2431  // Give it a bogus pass to indicate it wasn't created while stepping
2432  aVtx.Pass = 9;
2433  if (prt)
2434  mf::LogVerbatim("TC") << "CI3DVIG: Incomplete vertex " << iv3 << " in plane " << mPlane
2435  << " wire " << vx3.Wire << " Made 2D vertex ";
2436  std::vector<int> tjIDs;
2437  std::vector<unsigned short> tjEnds;
2438  for (unsigned short itj = 0; itj < slc.tjs.size(); ++itj) {
2439  if (slc.tjs[itj].CTP != mCTP) continue;
2440  if (slc.tjs[itj].AlgMod[kKilled] || slc.tjs[itj].AlgMod[kHaloTj]) continue;
2441  for (unsigned short end = 0; end < 2; ++end) {
2442  unsigned short ept = slc.tjs[itj].EndPt[end];
2443  TrajPoint& tp = slc.tjs[itj].Pts[ept];
2444  unsigned short oept = slc.tjs[itj].EndPt[1 - end];
2445  TrajPoint& otp = slc.tjs[itj].Pts[oept];
2446  // ensure that this is the end closest to the vertex
2447  if (std::abs(tp.Pos[0] - aVtx.Pos[0]) > std::abs(otp.Pos[0] - aVtx.Pos[0])) continue;
2448  float doca = PointTrajDOCA(slc, aVtx.Pos[0], aVtx.Pos[1], tp);
2449  if (doca > 2) continue;
2450  float dwc = DeadWireCount(slc, aVtx.Pos[0], tp.Pos[0], tp.CTP);
2451  float ptSep;
2452  if (aVtx.Pos[0] > tp.Pos[0]) { ptSep = aVtx.Pos[0] - tp.Pos[0] - dwc; }
2453  else {
2454  ptSep = tp.Pos[0] - aVtx.Pos[0] - dwc;
2455  }
2456  if (prt)
2457  mf::LogVerbatim("TC") << "CI3DVIG: tj ID " << slc.tjs[itj].ID << " doca " << doca
2458  << " ptSep " << ptSep;
2459  if (ptSep < -2 || ptSep > 2) continue;
2460  // don't clobber an existing association
2461  if (slc.tjs[itj].VtxID[end] > 0) continue;
2462  tjIDs.push_back(slc.tjs[itj].ID);
2463  tjEnds.push_back(end);
2464  } // end
2465  } // itj
2466  if (!tjIDs.empty()) {
2467  // Determine how messy this region is
2468  aVtx.TjChgFrac = ChgFracNearPos(slc, aVtx.Pos, tjIDs);
2469  if (aVtx.TjChgFrac < 0.7) continue;
2470  aVtx.Vx3ID = vx3.ID;
2471  // Save the 2D vertex
2472  if (!StoreVertex(slc, aVtx)) continue;
2473  for (unsigned short ii = 0; ii < tjIDs.size(); ++ii) {
2474  unsigned short itj = tjIDs[ii] - 1;
2475  slc.tjs[itj].VtxID[tjEnds[ii]] = aVtx.ID;
2476  slc.tjs[itj].AlgMod[kComp3DVxIG] = true;
2477  } // ii
2478  SetVx2Score(slc);
2479  vx3.Vx2ID[mPlane] = aVtx.ID;
2480  vx3.Wire = -1;
2481  if (prt)
2482  mf::LogVerbatim("TC") << "CI3DVIG: new vtx 2V" << aVtx.ID << " points to 3V" << vx3.ID;
2483  }
2484  } // vx3
2485 
2486  } // CompleteIncomplete3DVerticesInGaps
TCConfig tcc
Definition: DataStructs.cxx:9
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2572
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:590
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:1918
T abs(T value)
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2141
float ChgFracNearPos(const TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3236
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:607
unsigned int CTP_t
Definition: DataStructs.h:47
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:587
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:52
void SetVx2Score(TCSlice &slc)
Definition: TCVertex.cxx:2264
master switch for turning on debug mode
Definition: DataStructs.h:533
auto const detProp
bool tca::CompleteIncompleteShower ( std::string  inFcnLabel,
TCSlice &  slc,
ShowerStruct3D &  ss3,
bool  prt 
)

Definition at line 756 of file TCShower.cxx.

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

Definition at line 35 of file TCShower.cxx.

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

Definition at line 1309 of file PFPUtils.cxx.

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

Definition at line 2824 of file PFPUtils.cxx.

2825  {
2826  // The calling function should define the size of pfp.TjIDs
2827  PFPStruct pfp;
2828  pfp.ID = slc.pfps.size() + 1;
2829  pfp.ParentUID = 0;
2830  pfp.TPCID = slc.TPCID;
2831  // initialize arrays for both ends
2832  if (slc.nPlanes < 4) {
2833  pfp.dEdx[0].resize(slc.nPlanes, -1);
2834  pfp.dEdx[1].resize(slc.nPlanes, -1);
2835  pfp.dEdxErr[0].resize(slc.nPlanes, -1);
2836  pfp.dEdxErr[1].resize(slc.nPlanes, -1);
2837  }
2838  // create a single section fit to hold the start/end positions and direction
2839  pfp.SectionFits.resize(1);
2840  return pfp;
2841  } // CreatePFP
ShowerStruct tca::CreateSS ( TCSlice &  slc,
const std::vector< int > &  tjl 
)

Definition at line 4110 of file TCShower.cxx.

4111  {
4112  // Create a shower and shower Tj using Tjs in the list. If tjl is empty a
4113  // MC cheat shower is created inCTP. Note that inCTP is only used if tjl is empty.
4114  // A companion shower tj is created and stored but the ShowerStruct is not.
4115  ShowerStruct ss;
4116 
4117  // Create the shower tj
4118  Trajectory stj;
4119  stj.CTP = slc.tjs[tjl[0] - 1].CTP;
4120 
4121  // with three points
4122  stj.Pts.resize(3);
4123  for (auto& stp : stj.Pts) {
4124  stp.CTP = stj.CTP;
4125  // set all UseHit bits true so we don't get confused
4126  stp.UseHit.set();
4127  }
4128  stj.EndPt[0] = 0;
4129  stj.EndPt[1] = 2;
4130  stj.ID = slc.tjs.size() + 1;
4131  // Declare that stj is a shower Tj
4132  stj.AlgMod[kShowerTj] = true;
4133  stj.PDGCode = 1111;
4134  slc.tjs.push_back(stj);
4135  // define the ss
4136  ss.ID = slc.cots.size() + 1;
4137  ss.CTP = stj.CTP;
4138  // assign all TJ IDs to this ShowerStruct
4139  ss.TjIDs = tjl;
4140  // declare them to be InShower
4141  for (auto tjid : tjl) {
4142  auto& tj = slc.tjs[tjid - 1];
4143  if (tj.CTP != stj.CTP) {
4144  ss.ID = 0;
4145  return ss;
4146  }
4147  tj.SSID = ss.ID;
4148  } // tjid
4149  ss.ShowerTjID = stj.ID;
4150  ss.Envelope.resize(4);
4151  return ss;
4152 
4153  } // CreateSS
ShowerStruct3D tca::CreateSS3 ( TCSlice &  slc)

Definition at line 4090 of file TCShower.cxx.

4091  {
4092  // create a 3D shower and size the vectors that are indexed by plane
4093 
4094  ShowerStruct3D ss3;
4095  ss3.TPCID = slc.TPCID;
4096  ss3.ID = slc.showers.size() + 1;
4097  ss3.Energy.resize(slc.nPlanes);
4098  ss3.EnergyErr.resize(slc.nPlanes);
4099  ss3.MIPEnergy.resize(slc.nPlanes);
4100  ss3.MIPEnergyErr.resize(slc.nPlanes);
4101  ss3.dEdx.resize(slc.nPlanes);
4102  ss3.dEdxErr.resize(slc.nPlanes);
4103 
4104  return ss3;
4105 
4106  } // CreateSS3
TP3D tca::CreateTP3D ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice &  slc,
int  tjID,
unsigned short  tpIndex 
)

Definition at line 2723 of file PFPUtils.cxx.

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

Definition at line 3217 of file StepUtils.cxx.

3218  {
3219  // Create a trajectory point by averaging the position and direction of all
3220  // TPs in the trajectory. This is used in LastEndMerge
3221  TrajPoint tjtp;
3222  // set the charge invalid
3223  tjtp.Chg = -1;
3224  if(tj.AlgMod[kKilled]) return tjtp;
3225  // stash the ID in the Step
3226  tjtp.Step = tj.ID;
3227  tjtp.CTP = tj.CTP;
3228  tjtp.Pos[0] = 0;
3229  tjtp.Pos[1] = 0;
3230  tjtp.Dir[0] = 0;
3231  tjtp.Dir[1] = 0;
3232  float cnt = 0;
3233  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
3234  auto& tp = tj.Pts[ipt];
3235  if(tp.Chg <= 0) continue;
3236  tjtp.Pos[0] += tp.Pos[0];
3237  tjtp.Pos[1] += tp.Pos[1];
3238  tjtp.Dir[1] += tp.Dir[1];
3239  ++cnt;
3240  } // ipt
3241  tjtp.Pos[0] /= cnt;
3242  tjtp.Pos[1] /= cnt;
3243  tjtp.Dir[1] /= cnt;
3244  double arg = 1 - tjtp.Dir[1] * tjtp.Dir[1];
3245  if(arg < 0) arg = 0;
3246  tjtp.Dir[0] = sqrt(arg);
3247  tjtp.Ang = atan2(tjtp.Dir[1], tjtp.Dir[0]);
3248  tjtp.Chg = 1;
3249  return tjtp;
3250  } // CreateTjTP
float tca::DeadWireCount ( const TCSlice &  slc,
const TrajPoint &  tp1,
const TrajPoint &  tp2 
)

Definition at line 2141 of file Utils.cxx.

2142  {
2143  return DeadWireCount(slc, tp1.Pos[0], tp2.Pos[0], tp1.CTP);
2144  } // DeadWireCount
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2141
float tca::DeadWireCount ( const TCSlice &  slc,
const float &  inWirePos1,
const float &  inWirePos2,
CTP_t  tCTP 
)

Definition at line 2148 of file Utils.cxx.

2149  {
2150  if (inWirePos1 < -0.4 || inWirePos2 < -0.4) return 0;
2151  unsigned int inWire1 = std::nearbyint(inWirePos1);
2152  unsigned int inWire2 = std::nearbyint(inWirePos2);
2153  geo::PlaneID planeID = DecodeCTP(tCTP);
2154  unsigned short plane = planeID.Plane;
2155  if (inWire1 > slc.nWires[plane] || inWire2 > slc.nWires[plane]) return 0;
2156  if (inWire1 > inWire2) {
2157  // put in increasing order
2158  unsigned int tmp = inWire1;
2159  inWire1 = inWire2;
2160  inWire2 = tmp;
2161  } // inWire1 > inWire2
2162  ++inWire2;
2163  unsigned int wire, ndead = 0;
2164  for (wire = inWire1; wire < inWire2; ++wire)
2165  if (!evt.goodWire[plane][wire]) ++ndead;
2166  return ndead;
2167  } // DeadWireCount
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:630
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
geo::PlaneID DecodeCTP(CTP_t CTP)
TCEvent evt
Definition: DataStructs.cxx:8
geo::PlaneID tca::DecodeCTP ( CTP_t  CTP)

Definition at line 116 of file DataStructs.cxx.

116  {
117  auto const cryo = (CTP / Cpad);
118  return geo::PlaneID(
119  /* Cryostat */ cryo,
120  /* TPC */ (CTP - cryo * Cpad) / Tpad,
121  /* Plane */ (CTP % 10)
122  );
123  }
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 5216 of file Utils.cxx.

5217  {
5218  // try to unpack the string as Cryostat:TPC:Plane:Wire:Tick or something
5219  // like Slice:<slice index>
5220 
5221  if (strng == "instruct") {
5222  std::cout << "****** Unrecognized DebugConfig. Here are your options\n";
5223  std::cout << " 'C:T:P:W:Tick' where C = cryostat, T = TPC, W = wire, Tick (+/-5) to debug "
5224  "stepping (DUNE)\n";
5225  std::cout << " 'P:W:Tick' for single cryostat/TPC detectors (uB, LArIAT, etc)\n";
5226  std::cout << " 'WorkID <id> <slice index>' where <id> is a tj work ID (< 0) in slice <slice "
5227  "index> (default = 0)\n";
5228  std::cout << " 'Merge <CTP>' to debug trajectory merging\n";
5229  std::cout << " '2V <CTP>' to debug 2D vertex finding\n";
5230  std::cout << " '3V' to debug 3D vertex finding\n";
5231  std::cout << " 'VxMerge' to debug 2D vertex merging\n";
5232  std::cout << " 'JunkVx' to debug 2D junk vertex finder\n";
5233  std::cout << " 'PFP' to debug 3D matching and PFParticles\n";
5234  std::cout << " 'MVI <MVI> <MVI Iteration>' for detailed debugging of one PFP MatchVecIndex\n";
5235  std::cout << " 'DeltaRay' to debug delta ray tagging\n";
5236  std::cout << " 'Muon' to debug muon tagging\n";
5237  std::cout << " '2S <CTP>' to debug a 2D shower in CTP\n";
5238  std::cout << " 'Reco TPC <TPC>' to only reconstruct hits in the specified TPC\n";
5239  std::cout << " 'Reco Slice <ID>' to reconstruct all sub-slices in the recob::Slice with the "
5240  "specified ID\n";
5241  std::cout << " 'SubSlice <sub-slice index>' where <slice index> restricts output to the "
5242  "specified sub-slice index\n";
5243  std::cout << " 'Stitch' to debug PFParticle stitching between TPCs\n";
5244  std::cout << " 'Sum' or 'Summary' to print a debug summary report\n";
5245  std::cout << " 'Dump <WorkID>' or 'Dump <UID>' to print all TPs in the trajectory to "
5246  "tcdump<UID>.csv\n";
5247  std::cout << " Note: Algs with debug printing include HamVx, HamVx2, SplitTjCVx, Comp3DVx, "
5248  "Comp3DVxIG, VtxHitsSwap\n";
5249  std::cout << " Set SkipAlgs: [\"bogusText\"] to print a list of algorithm names\n";
5250  return false;
5251  } // instruct
5252 
5253  // handle the simple cases that don't need decoding
5254  if (strng.find("3V") != std::string::npos) {
5255  tcc.dbg3V = true;
5256  tcc.modes[kDebug] = true;
5257  return true;
5258  }
5259  if (strng.find("3S") != std::string::npos) {
5260  tcc.dbg3S = true;
5261  tcc.modes[kDebug] = true;
5262  return true;
5263  }
5264  if (strng.find("VxMerge") != std::string::npos) {
5265  tcc.dbgVxMerge = true;
5266  tcc.modes[kDebug] = true;
5267  return true;
5268  }
5269  if (strng.find("JunkVx") != std::string::npos) {
5270  tcc.dbgVxJunk = true;
5271  tcc.modes[kDebug] = true;
5272  return true;
5273  }
5274  if (strng.find("DeltaRay") != std::string::npos) {
5275  tcc.dbgDeltaRayTag = true;
5276  tcc.modes[kDebug] = true;
5277  return true;
5278  }
5279  if (strng.find("Muon") != std::string::npos) {
5280  tcc.dbgMuonTag = true;
5281  tcc.modes[kDebug] = true;
5282  return true;
5283  }
5284  if (strng.find("Stitch") != std::string::npos) {
5285  tcc.dbgStitch = true;
5286  tcc.modes[kDebug] = true;
5287  return true;
5288  }
5289  if (strng.find("HamVx") != std::string::npos) {
5290  tcc.dbgAlg[kHamVx] = true;
5291  tcc.modes[kDebug] = true;
5292  return true;
5293  }
5294  if (strng.find("HamVx2") != std::string::npos) {
5295  tcc.dbgAlg[kHamVx2] = true;
5296  tcc.modes[kDebug] = true;
5297  return true;
5298  }
5299  if (strng.find("Sum") != std::string::npos) {
5300  tcc.dbgSummary = true;
5301  tcc.modes[kDebug] = true;
5302  return true;
5303  }
5304 
5305  std::vector<std::string> words;
5306  boost::split(words, strng, boost::is_any_of(" :"), boost::token_compress_on);
5307  if (words.size() == 5) {
5308  // configure for DUNE
5309  debug.Cryostat = std::stoi(words[0]);
5310  debug.TPC = std::stoi(words[1]);
5311  debug.Plane = std::stoi(words[2]);
5312  debug.Wire = std::stoi(words[3]);
5313  debug.Tick = std::stoi(words[4]);
5314  tcc.modes[kDebug] = true;
5315  tcc.dbgStp = true;
5316  // also dump this tj
5317  tcc.dbgDump = true;
5318  return true;
5319  } // nums.size() == 5
5320  if (words[0] == "PFP" || words[0] == "MVI") {
5321  tcc.dbgPFP = true;
5322  tcc.modes[kDebug] = true;
5323  // Use debug.Hit to identify the matchVec index
5324  if (words.size() > 2) {
5325  debug.MVI = std::stoi(words[1]);
5326  if (words.size() == 3) debug.MVI_Iter = std::stoi(words[2]);
5327  }
5328  return true;
5329  } // PFP
5330  if (words.size() == 2 && words[0] == "Dump") {
5331  debug.WorkID = std::stoi(words[1]);
5332  debug.Slice = 0;
5333  tcc.modes[kDebug] = true;
5334  tcc.dbgDump = true;
5335  return true;
5336  }
5337  if (words.size() > 1 && words[0] == "WorkID") {
5338  debug.WorkID = std::stoi(words[1]);
5339  if (debug.WorkID >= 0) return false;
5340  // default to sub-slice index 0
5341  debug.Slice = 0;
5342  if (words.size() > 2) debug.Slice = std::stoi(words[2]);
5343  tcc.modes[kDebug] = true;
5344  // dbgStp is set true after debug.WorkID is found
5345  tcc.dbgStp = false;
5346  return true;
5347  } // words.size() == 3 && words[0] == "WorkID"
5348  if (words.size() == 3 && words[0] == "Reco" && words[1] == "TPC") {
5349  tcc.recoTPC = std::stoi(words[2]);
5350  tcc.modes[kDebug] = true;
5351  std::cout << "Reconstructing only in TPC " << tcc.recoTPC << "\n";
5352  return true;
5353  }
5354  if (words.size() == 3 && words[0] == "Reco" && words[1] == "Slice") {
5355  tcc.recoSlice = std::stoi(words[1]);
5356  std::cout << "Reconstructing Slice " << tcc.recoSlice << "\n";
5357  return true;
5358  }
5359  if (words.size() == 3) {
5360  // configure for uB, LArIAT, etc
5361  debug.Cryostat = 0;
5362  debug.TPC = 0;
5363  debug.Plane = std::stoi(words[0]);
5364  debug.Wire = std::stoi(words[1]);
5365  debug.Tick = std::stoi(words[2]);
5366  debug.CTP = EncodeCTP(debug.Cryostat, debug.TPC, debug.Plane);
5367  tcc.modes[kDebug] = true;
5368  tcc.dbgStp = true;
5369  return true;
5370  }
5371  if (words.size() == 2 && words[0] == "Merge") {
5372  debug.CTP = std::stoi(words[1]);
5373  tcc.dbgMrg = true;
5374  tcc.modes[kDebug] = true;
5375  return true;
5376  }
5377  if (words.size() == 2 && words[0] == "2V") {
5378  debug.CTP = std::stoi(words[1]);
5379  tcc.dbg2V = true;
5380  tcc.modes[kDebug] = true;
5381  return true;
5382  }
5383  if (words.size() == 2 && words[0] == "2S") {
5384  debug.CTP = std::stoi(words[1]);
5385  tcc.dbg2S = true;
5386  tcc.modes[kDebug] = true;
5387  return true;
5388  }
5389  // Slice could apply to several debug options.
5390  if (words.size() == 2 && words[0] == "SubSlice") {
5391  debug.Slice = std::stoi(words[1]);
5392  return true;
5393  }
5394  return false;
5395  } // DecodeDebugString
bool dbgStitch
debug PFParticle stitching
Definition: DataStructs.h:603
short recoTPC
only reconstruct in the seleted TPC
Definition: DataStructs.h:589
TCConfig tcc
Definition: DataStructs.cxx:9
bool dbgDeltaRayTag
Definition: DataStructs.h:599
bool dbg3V
debug 3D vertex finding
Definition: DataStructs.h:597
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
bool dbg2V
debug 2D vertex finding
Definition: DataStructs.h:593
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:607
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:587
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:52
short recoSlice
only reconstruct the slice with ID (0 = all)
Definition: DataStructs.h:588
bool dbgSummary
print a summary report
Definition: DataStructs.h:604
master switch for turning on debug mode
Definition: DataStructs.h:533
BEGIN_PROLOG could also be cout
float tca::dEdx ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
const TCSlice &  slc,
TP3D &  tp3d 
)

Definition at line 2687 of file PFPUtils.cxx.

2691  {
2692  if (!tp3d.Flags[kTP3DGood]) return 0;
2693  if (tp3d.TjID > (int)slc.slHits.size()) return 0;
2694  if (tp3d.TjID <= 0) return 0;
2695 
2696  auto& tp = slc.tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
2697  if (tp.Environment[kEnvOverlap]) return 0;
2698 
2699  double dQ = 0.;
2700  double time = 0;
2701  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2702  if (!tp.UseHit[ii]) continue;
2703  auto& hit = (*evt.allHits)[slc.slHits[tp.Hits[ii]].allHitsIndex];
2704  dQ += hit.Integral();
2705  } // ii
2706  time = tp.Pos[1] / tcc.unitsPerTick;
2707  geo::PlaneID plnID = DecodeCTP(tp.CTP);
2708  if (dQ == 0) return 0;
2709  double angleToVert = tcc.geom->Plane(plnID).ThetaZ() - 0.5 * ::util::pi<>();
2710  double cosgamma =
2711  std::abs(std::sin(angleToVert) * tp3d.Dir[1] + std::cos(angleToVert) * tp3d.Dir[2]);
2712  if (cosgamma < 1.E-5) return 0;
2713  double dx = tcc.geom->WirePitch(plnID) / cosgamma;
2714  double dQdx = dQ / dx;
2715  double t0 = 0;
2716  float dedx = tcc.caloAlg->dEdx_AREA(clockData, detProp, dQdx, time, plnID.Plane, t0);
2717  if (std::isinf(dedx)) dedx = 0;
2718  return dedx;
2719  } // dEdx
calo::CalorimetryAlg * caloAlg
Definition: DataStructs.h:577
PlaneGeo const & Plane(unsigned int const p, unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified wire.
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
process_name E
process_name hit
Definition: cheaterreco.fcl:51
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
double ThetaZ() const
Angle of the wires from positive z axis; .
Definition: PlaneGeo.cxx:726
T abs(T value)
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
const geo::GeometryCore * geom
Definition: DataStructs.h:576
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
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
auto const detProp
void tca::DefineDontCluster ( TCSlice &  slc,
bool  prt 
)
void tca::DefineEnvelope ( std::string  inFcnLabel,
TCSlice &  slc,
ShowerStruct &  ss,
bool  prt 
)

Definition at line 3489 of file TCShower.cxx.

3490  {
3491 
3492  if (ss.ID == 0) return;
3493  if (ss.TjIDs.empty()) return;
3494  Trajectory& stj = slc.tjs[ss.ShowerTjID - 1];
3495  // shower Tj isn't fully defined yet
3496  if (stj.Pts[0].Pos[0] == 0) return;
3497 
3498  std::string fcnLabel = inFcnLabel + ".DE";
3499 
3500  ss.Envelope.resize(4);
3501  TrajPoint& stp0 = stj.Pts[0];
3502  TrajPoint& stp1 = stj.Pts[1];
3503  TrajPoint& stp2 = stj.Pts[2];
3504 
3505  // construct the Envelope polygon. Start with a rectangle using the fixed 1/2 width fcl input
3506  // expanded by the rms width at each end to create a polygon. The polygon is constructed along
3507  // the Pos[0] direction and then rotated into the ShowerTj direction. Use sTp1 as the origin.
3508  // First vertex
3509  ss.Envelope[0][0] = -PosSep(stp0.Pos, stp1.Pos);
3510  ss.Envelope[0][1] = tcc.showerTag[5] + tcc.showerTag[4] * stp0.DeltaRMS;
3511  // second vertex
3512  ss.Envelope[1][0] = PosSep(stp1.Pos, stp2.Pos);
3513  ss.Envelope[1][1] = tcc.showerTag[5] + tcc.showerTag[4] * stp2.DeltaRMS;
3514  // third and fourth are reflections of the first and second
3515  ss.Envelope[2][0] = ss.Envelope[1][0];
3516  ss.Envelope[2][1] = -ss.Envelope[1][1];
3517  ss.Envelope[3][0] = ss.Envelope[0][0];
3518  ss.Envelope[3][1] = -ss.Envelope[0][1];
3519 
3520  float length = ss.Envelope[1][0] - ss.Envelope[0][0];
3521  float width = ss.Envelope[0][1] + ss.Envelope[1][1];
3522  ss.EnvelopeArea = length * width;
3523 
3524  // Rotate into the stp1 coordinate system
3525  float cs = cos(stp1.Ang);
3526  float sn = sin(stp1.Ang);
3527  for (auto& vtx : ss.Envelope) {
3528  // Rotate along the stj shower axis
3529  float pos0 = cs * vtx[0] - sn * vtx[1];
3530  float pos1 = sn * vtx[0] + cs * vtx[1];
3531  // translate
3532  vtx[0] = pos0 + stp1.Pos[0];
3533  vtx[1] = pos1 + stp1.Pos[1];
3534  } // vtx
3535  // Find the charge density inside the envelope
3536  ss.ChgDensity = (stp0.Chg + stp1.Chg + stp2.Chg) / ss.EnvelopeArea;
3537  if (prt) {
3538  mf::LogVerbatim myprt("TC");
3539  myprt << fcnLabel << " 2S" << ss.ID << " Envelope";
3540  for (auto& vtx : ss.Envelope)
3541  myprt << " " << (int)vtx[0] << ":" << (int)(vtx[1] / tcc.unitsPerTick);
3542  myprt << " Area " << (int)ss.EnvelopeArea;
3543  myprt << " ChgDensity " << ss.ChgDensity;
3544  }
3545  // This is the last function used to update a shower
3546  ss.NeedsUpdate = false;
3547  } // DefineEnvelope
then if[["$THISISATEST"==1]]
Definition: neoSmazza.sh:95
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:558
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2565
void tca::DefineHitPos ( TCSlice &  slc,
TrajPoint &  tp 
)

Definition at line 1672 of file StepUtils.cxx.

1673  {
1674  // defines HitPos, HitPosErr2 and Chg for the used hits in the trajectory point
1675 
1676  tp.Chg = 0;
1677  if(tp.Hits.empty()) return;
1678 
1679  unsigned short nused = 0;
1680  unsigned int iht = 0;
1681  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1682  if(!tp.UseHit[ii]) continue;
1683  ++nused;
1684  iht = tp.Hits[ii];
1685  if(iht >= slc.slHits.size()) return;
1686  if(slc.slHits[iht].allHitsIndex >= (*evt.allHits).size()) return;
1687  }
1688  if(nused == 0) return;
1689 
1690  // don't bother with rest of this if there is only one hit since it can
1691  // only reside on one wire
1692  if(nused == 1) {
1693  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1694  tp.Chg = hit.Integral();
1695  tp.HitPos[0] = hit.WireID().Wire;
1696  tp.HitPos[1] = hit.PeakTime() * tcc.unitsPerTick;
1697  if(LongPulseHit(hit)) {
1698  // give it a huge error^2 since the position is not well defined
1699  tp.HitPosErr2 = 100;
1700  } else {
1701  // Normalize to 1 WSE path length
1702  float pathInv = std::abs(tp.Dir[0]);
1703  if(pathInv < 0.05) pathInv = 0.05;
1704  tp.Chg *= pathInv;
1705  float wireErr = tp.Dir[1] * 0.289;
1706  float timeErr = tp.Dir[0] * HitTimeErr(slc, iht);
1707  tp.HitPosErr2 = wireErr * wireErr + timeErr * timeErr;
1708  }
1709  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"DefineHitPos: singlet "<<std::fixed<<std::setprecision(1)<<tp.HitPos[0]<<":"<<(int)(tp.HitPos[1]/tcc.unitsPerTick)<<" ticks. HitPosErr "<<sqrt(tp.HitPosErr2);
1710  return;
1711  } // nused == 1
1712 
1713  // multiple hits possibly on different wires
1714  std::vector<unsigned int> hitVec;
1715  tp.Chg = 0;
1716  std::array<float, 2> newpos;
1717  float chg;
1718  newpos[0] = 0;
1719  newpos[1] = 0;
1720  // Find the wire range for hits used in the TP
1721  unsigned int loWire = INT_MAX;
1722  unsigned int hiWire = 0;
1723  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1724  if(!tp.UseHit[ii]) continue;
1725  unsigned int iht = tp.Hits[ii];
1726  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1727  chg = hit.Integral();
1728  unsigned int wire = hit.WireID().Wire;
1729  if(wire < loWire) loWire = wire;
1730  if(wire > hiWire) hiWire = wire;
1731  newpos[0] += chg * wire;
1732  newpos[1] += chg * hit.PeakTime();
1733  tp.Chg += chg;
1734  hitVec.push_back(iht);
1735  } // ii
1736 
1737  if(tp.Chg == 0) return;
1738 
1739  tp.HitPos[0] = newpos[0] / tp.Chg;
1740  tp.HitPos[1] = newpos[1] * tcc.unitsPerTick / tp.Chg;
1741  // Normalize to 1 WSE path length
1742  float pathInv = std::abs(tp.Dir[0]);
1743  if(pathInv < 0.05) pathInv = 0.05;
1744  tp.Chg *= pathInv;
1745  // Error is the wire error (1/sqrt(12))^2 if all hits are on one wire.
1746  // Scale it by the wire range
1747  float dWire = 1 + hiWire - loWire;
1748  float wireErr = tp.Dir[1] * dWire * 0.289;
1749  float timeErr2 = tp.Dir[0] * tp.Dir[0] * HitsTimeErr2(slc, hitVec);
1750  tp.HitPosErr2 = wireErr * wireErr + timeErr2;
1751  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"DefineHitPos: multiplet "<<std::fixed<<std::setprecision(1)<<tp.HitPos[0]<<":"<<(int)(tp.HitPos[1]/tcc.unitsPerTick)<<" ticks. HitPosErr "<<sqrt(tp.HitPosErr2);
1752 
1753  } // DefineHitPos
TCConfig tcc
Definition: DataStructs.cxx:9
float HitTimeErr(const TCSlice &slc, unsigned int iht)
Definition: StepUtils.cxx:1544
process_name hit
Definition: cheaterreco.fcl:51
bool LongPulseHit(const recob::Hit &hit)
Definition: Utils.cxx:4452
T abs(T value)
float HitsTimeErr2(const TCSlice &slc, const std::vector< unsigned int > &hitVec)
Definition: StepUtils.cxx:1552
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
TCEvent evt
Definition: DataStructs.cxx:8
void tca::DefinePFPParents ( TCSlice &  slc,
bool  prt 
)

Definition at line 2884 of file PFPUtils.cxx.

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

Definition at line 168 of file Utils.cxx.

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

Definition at line 2540 of file PFPUtils.cxx.

2541  {
2542  if (v1[0] == v2[0] && v1[1] == v2[1] && v1[2] == v2[2]) return 0;
2543  return acos(DotProd(v1, v2));
2544  }
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:128
double tca::DeltaAngle ( const Point2_t &  p1,
const Point2_t &  p2 
)

Definition at line 3383 of file Utils.cxx.

3384  {
3385  // angle between two points
3386  double ang1 = atan2(p1[1], p1[0]);
3387  double ang2 = atan2(p2[1], p2[0]);
3388  return DeltaAngle2(ang1, ang2);
3389  } // DeltaAngle
double DeltaAngle2(double Ang1, double Ang2)
Definition: Utils.cxx:3393
physics associatedGroupsWithLeft p1
double tca::DeltaAngle ( double  Ang1,
double  Ang2 
)

Definition at line 3406 of file Utils.cxx.

3407  {
3408  return std::abs(std::remainder(Ang1 - Ang2, M_PI));
3409  }
T abs(T value)
double tca::DeltaAngle2 ( double  Ang1,
double  Ang2 
)

Definition at line 3393 of file Utils.cxx.

3394  {
3395  constexpr double twopi = 2 * M_PI;
3396  double dang = Ang1 - Ang2;
3397  while (dang > M_PI)
3398  dang -= twopi;
3399  while (dang < -M_PI)
3400  dang += twopi;
3401  return dang;
3402  }
Vector3_t tca::DirAtEnd ( const PFPStruct &  pfp,
unsigned short  end 
)

Definition at line 3284 of file PFPUtils.cxx.

3285  {
3286  if (end > 1 || pfp.SectionFits.empty()) return {{0., 0., 0.}};
3287  if (end == 0) return pfp.SectionFits[0].Dir;
3288  return pfp.SectionFits[pfp.SectionFits.size() - 1].Dir;
3289  } // PosAtEnd
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
bool tca::DontCluster ( TCSlice &  slc,
const std::vector< int > &  tjlist1,
const std::vector< int > &  tjlist2 
)

Definition at line 3258 of file TCShower.cxx.

3259  {
3260  // returns true if a pair of tjs in the two lists are in the dontCluster vector
3261  if (tjlist1.empty() || tjlist2.empty()) return false;
3262  if (slc.dontCluster.empty()) return false;
3263  for (auto tid1 : tjlist1) {
3264  for (auto tid2 : tjlist2) {
3265  int ttid1 = tid1;
3266  if (ttid1 > tid2) std::swap(ttid1, tid2);
3267  for (auto& dc : slc.dontCluster)
3268  if (dc.TjIDs[0] == ttid1 && dc.TjIDs[1] == tid2) return true;
3269  } // dc
3270  } // tid1
3271  return false;
3272  } // DontCluster
double tca::DotProd ( const Vector3_t &  v1,
const Vector3_t &  v2 
)
inline

Definition at line 128 of file PFPUtils.h.

129  {
130  return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
131  }
double tca::DotProd ( const Vector2_t &  v1,
const Vector2_t &  v2 
)
inline

Definition at line 237 of file larreco/larreco/RecoAlg/TCAlg/Utils.h.

238  {
239  return v1[0] * v2[0] + v1[1] * v2[1];
240  }
void tca::DumpShowerPts ( std::string  inFcnLabel,
TCSlice &  slc,
int  cotID 
)
void tca::DumpShowerPts ( TCSlice &  slc,
int  cotID 
)

Definition at line 3875 of file TCShower.cxx.

3876  {
3877  // Print the shower points to the screen. The user should probably pipe the output to a text file
3878  // then grep this file for the character string PTS which is piped to a text file which can then be
3879  // imported into Excel, etc
3880  // Finds the charge at the start of a shower
3881  if (cotID > (int)slc.cots.size()) return;
3882 
3883  ShowerStruct& ss = slc.cots[cotID - 1];
3884  if (ss.ID == 0) return;
3885  if (ss.TjIDs.empty()) return;
3886  std::cout << "PTS Pos0 Pos1 RPos0 RPos1 Chg TID\n";
3887  for (auto& pt : ss.ShPts) {
3888  std::cout << "PTS " << std::fixed << std::setprecision(1) << pt.Pos[0] << " " << pt.Pos[1]
3889  << " " << pt.RotPos[0] << " " << pt.RotPos[1];
3890  std::cout << " " << (int)pt.Chg << " " << pt.TID;
3891  std::cout << "\n";
3892  }
3893 
3894  } // DumpShowerPts
BEGIN_PROLOG could also be cout
void tca::DumpTj ( )

Definition at line 5400 of file Utils.cxx.

5401  {
5402  // Dump all of the points in a trajectory to the output in a form that can
5403  // be imported by another application, e.g. Excel
5404  // Search for the trajectory with the specified WorkID or Unique ID
5405 
5406  for (auto& slc : slices) {
5407  for (auto& tj : slc.tjs) {
5408  if (tj.WorkID != debug.WorkID && tj.UID != debug.WorkID) continue;
5409  // print a header
5410  std::ofstream outfile;
5411  std::string fname = "tcdump" + std::to_string(tj.UID) + ".csv";
5412  outfile.open(fname, std::ios::out | std::ios::trunc);
5413  outfile << "Dump trajectory T" << tj.UID << " WorkID " << tj.WorkID;
5414  outfile << " ChgRMS " << std::setprecision(2) << tj.ChgRMS;
5415  outfile << "\n";
5416  outfile << "Wire, Chg T" << tj.UID
5417  << ", totChg, Tick, Delta, NTPsFit, Ang, ChiDOF, KinkSig, HitPosErr\n";
5418  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
5419  auto& tp = tj.Pts[ipt];
5420  outfile << std::fixed;
5421  outfile << std::setprecision(0) << std::nearbyint(tp.Pos[0]);
5422  outfile << "," << (int)tp.Chg;
5423  // total charge near the TP
5424  float totChg = 0;
5425  for (auto iht : tp.Hits) {
5426  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
5427  totChg += hit.Integral();
5428  }
5429  outfile << "," << (int)totChg;
5430  outfile << "," << std::setprecision(0) << std::nearbyint(tp.Pos[1] / tcc.unitsPerTick);
5431  outfile << "," << std::setprecision(2) << tp.Delta;
5432  outfile << "," << tp.NTPsFit;
5433  outfile << "," << std::setprecision(3) << tp.Ang;
5434  outfile << "," << std::setprecision(2) << tp.FitChi;
5435  outfile << "," << std::setprecision(2) << tp.KinkSig;
5436  outfile << "," << std::setprecision(2) << sqrt(tp.HitPosErr2);
5437  outfile << "\n";
5438  } // ipt
5439  outfile.close();
5440  std::cout << "Points on T" << tj.UID << " dumped to " << fname << "\n";
5441  tcc.dbgDump = false;
5442  return;
5443  } // tj
5444  } // slc
5445 
5446  } // DumpTj
string fname
Definition: demo.py:5
TCConfig tcc
Definition: DataStructs.cxx:9
process_name hit
Definition: cheaterreco.fcl:51
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
for($it=0;$it< $RaceTrack_number;$it++)
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
std::string to_string(WindowPattern const &pattern)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
TCEvent evt
Definition: DataStructs.cxx:8
BEGIN_PROLOG could also be cout
float tca::ElectronLikelihood ( const TCSlice &  slc,
const Trajectory &  tj 
)

Definition at line 3216 of file Utils.cxx.

3217  {
3218  // returns a number between 0 (not electron-like) and 1 (electron-like)
3219  if (NumPtsWithCharge(slc, tj, false) < 8) return -1;
3220  if (tj.EndFlag[0][kBragg] || tj.EndFlag[1][kBragg]) return 0;
3221 
3222  unsigned short midPt = 0.5 * (tj.EndPt[0] + tj.EndPt[1]);
3223  double rms0 = 0, rms1 = 0;
3224  unsigned short cnt;
3225  TjDeltaRMS(slc, tj, tj.EndPt[0], midPt, rms0, cnt);
3226  TjDeltaRMS(slc, tj, midPt, tj.EndPt[1], rms1, cnt);
3227  float asym = std::abs(rms0 - rms1) / (rms0 + rms1);
3228  float chgFact = (tj.ChgRMS - 0.1) * 5;
3229  float elh = 5 * asym * chgFact;
3230  if (elh > 1) elh = 1;
3231  return elh;
3232  } // ElectronLikelihood
T abs(T value)
void TjDeltaRMS(const TCSlice &slc, const Trajectory &tj, unsigned short firstPt, unsigned short lastPt, double &rms, unsigned short &cnt)
Definition: Utils.cxx:3584
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2116
CTP_t tca::EncodeCTP ( unsigned int  cryo,
unsigned int  tpc,
unsigned int  plane 
)
inline

Definition at line 52 of file DataStructs.h.

53  {
54  return cryo * Cpad + tpc * Tpad + plane;
55  }
constexpr unsigned int Tpad
Definition: DataStructs.h:48
constexpr unsigned int Cpad
Definition: DataStructs.h:49
CTP_t tca::EncodeCTP ( const geo::PlaneID planeID)
inline

Definition at line 57 of file DataStructs.h.

58  {
59  return EncodeCTP(planeID.Cryostat, planeID.TPC, planeID.Plane);
60  }
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:212
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:52
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:406
CTP_t tca::EncodeCTP ( const geo::WireID wireID)
inline

Definition at line 62 of file DataStructs.h.

63  {
64  return EncodeCTP(wireID.Cryostat, wireID.TPC, wireID.Plane);
65  }
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:212
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:52
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:406
void tca::EndMerge ( TCSlice &  slc,
CTP_t  inCTP,
bool  lastPass 
)

Definition at line 3253 of file StepUtils.cxx.

3254  {
3255  // Merges trajectories end-to-end or makes vertices. Does a more careful check on the last pass
3256 
3257  if(slc.tjs.size() < 2) return;
3258  if(!tcc.useAlg[kMerge]) return;
3259 
3260  bool prt = (tcc.dbgMrg && tcc.dbgSlc && inCTP == debug.CTP);
3261  if(prt) mf::LogVerbatim("TC")<<"inside EndMerge slice "<<slices.size()-1<<" inCTP "<<inCTP<<" nTjs "<<slc.tjs.size()<<" lastPass? "<<lastPass;
3262 
3263  // Ensure that all tjs are in the same order
3264  short tccStepDir = 1;
3265  if(!tcc.modes[kStepDir]) tccStepDir = -1;
3266  for(auto& tj : slc.tjs) {
3267  if(tj.AlgMod[kKilled]) continue;
3268  if(tj.CTP != inCTP) continue;
3269  if(tj.StepDir != tccStepDir) ReverseTraj(slc, tj);
3270  } // tj
3271 
3272  unsigned short maxShortTjLen = tcc.vtx2DCuts[0];
3273 
3274  // temp vector for checking the fraction of hits near a merge point
3275  std::vector<int> tjlist(2);
3276 
3277  float minChgRMS = 0.5 * (tcc.chargeCuts[1] + tcc.chargeCuts[2]);
3278 
3279  // iterate whenever a merge occurs since tjs will change. This is not necessary
3280  // when a vertex is created however.
3281  bool iterate = true;
3282  while(iterate) {
3283  iterate = false;
3284  for(unsigned int it1 = 0; it1 < slc.tjs.size(); ++it1) {
3285  auto& tj1 = slc.tjs[it1];
3286  if(tj1.AlgMod[kKilled]) continue;
3287  if(tj1.CTP != inCTP) continue;
3288  // don't try to merge high energy electrons
3289  if(tj1.PDGCode == 111) continue;
3290  for(unsigned short end1 = 0; end1 < 2; ++end1) {
3291  // no merge if there is a vertex at the end
3292  if(tj1.VtxID[end1] > 0) continue;
3293  // make a copy of tp1 so we can mess with it
3294  TrajPoint tp1 = tj1.Pts[tj1.EndPt[end1]];
3295  // do a local fit on the lastpass only using the last 3 points
3296  if(lastPass && tp1.NTPsFit > 3) {
3297  // make a local copy of the tj
3298  auto ttj = slc.tjs[it1];
3299  auto& lastTP = ttj.Pts[ttj.EndPt[end1]];
3300  // fit the last 3 points
3301  lastTP.NTPsFit = 3;
3302  FitTraj(slc, ttj);
3303  tp1 = ttj.Pts[ttj.EndPt[end1]];
3304  } // last pass
3305  bool isVLA = (tp1.AngleCode == 2);
3306  float bestFOM = 5;
3307  if(isVLA) bestFOM = 20;
3308  float bestDOCA;
3309  unsigned int imbest = UINT_MAX;
3310  for(unsigned int it2 = 0; it2 < slc.tjs.size(); ++it2) {
3311  if(it1 == it2) continue;
3312  auto& tj2 = slc.tjs[it2];
3313  // check for consistent direction
3314  if(tj1.StepDir != tj2.StepDir) continue;
3315  if(tj2.AlgMod[kKilled]) continue;
3316  if(tj2.CTP != inCTP) continue;
3317  // don't try to merge high energy electrons
3318  if(tj2.PDGCode == 111) continue;
3319  float olf = OverlapFraction(slc, tj1, tj2);
3320  if(olf > 0.25) continue;
3321  unsigned short end2 = 1 - end1;
3322  // check for a vertex at this end
3323  if(tj2.VtxID[end2] > 0) continue;
3324  TrajPoint& tp2 = tj2.Pts[tj2.EndPt[end2]];
3325  TrajPoint& tp2OtherEnd = tj2.Pts[tj2.EndPt[end1]];
3326  // ensure that the other end isn't closer
3327  if(std::abs(tp2OtherEnd.Pos[0] - tp1.Pos[0]) < std::abs(tp2.Pos[0] - tp1.Pos[0])) continue;
3328  // ensure that the order is correct
3329  if(tj1.StepDir > 0) {
3330  if(tp2.Pos[0] < tp1.Pos[0] - 2) continue;
3331  } else {
3332  if(tp2.Pos[0] > tp1.Pos[0] + 2) continue;
3333  }
3334  // ensure that there is a signal on most of the wires between these points
3335  if(!SignalBetween(slc, tp1, tp2, 0.8)) {
3336  continue;
3337  }
3338  // Find the distance of closest approach for small angle merging
3339  // Inflate the doca cut if we are bridging a block of dead wires
3340  float dang = DeltaAngle(tp1.Ang, tp2.Ang);
3341  float doca = 15;
3342  if(isVLA) {
3343  // compare the minimum separation between Large Angle trajectories using a generous cut
3344  unsigned short ipt1, ipt2;
3345  TrajTrajDOCA(slc, tj1, tj2, ipt1, ipt2, doca);
3346  // if(prt) mf::LogVerbatim("TC")<<" isVLA check ipt1 "<<ipt1<<" ipt2 "<<ipt2<<" doca "<<doca;
3347  } else {
3348  // small angle
3349  doca = PointTrajDOCA(slc, tp1.Pos[0], tp1.Pos[1], tp2);
3350  }
3351  float fom = dang * doca;
3352  if(fom < bestFOM) {
3353  bestFOM = fom;
3354  bestDOCA = doca;
3355  imbest = it2;
3356  }
3357  } // it2
3358  // No merge/vertex candidates
3359  if(imbest == UINT_MAX) continue;
3360 
3361  // Make angle adjustments to tp1.
3362  unsigned int it2 = imbest;
3363  auto& tj2 = slc.tjs[imbest];
3364  unsigned short end2 = 1 - end1;
3365  bool loMCSMom = (tj1.MCSMom + tj2.MCSMom) < 150;
3366  // Don't use the angle at the end Pt for high momentum long trajectories in case there is a little kink at the end
3367  if(tj1.Pts.size() > 50 && tj1.MCSMom > 100) {
3368  if(end1 == 0) {
3369  tp1.Ang = tj1.Pts[tj1.EndPt[0] + 2].Ang;
3370  } else {
3371  tp1.Ang = tj1.Pts[tj1.EndPt[1] - 2].Ang;
3372  }
3373  } else if(loMCSMom) {
3374  // Low momentum - calculate the angle using the two Pts at the end
3375  unsigned short pt1, pt2;
3376  if(end1 == 0) {
3377  pt1 = tj1.EndPt[0];
3378  pt2 = pt1 + 1;
3379  } else {
3380  pt2 = tj1.EndPt[1];
3381  pt1 = pt2 - 1;
3382  }
3383  TrajPoint tpdir;
3384  if(MakeBareTrajPoint(slc, tj1.Pts[pt1], tj1.Pts[pt2], tpdir)) tp1.Ang = tpdir.Ang;
3385  } // low MCSMom
3386  // Now do the same for tj2
3387  TrajPoint tp2 = tj2.Pts[tj2.EndPt[end2]];
3388  if(tj2.Pts.size() > 50 && tj2.MCSMom > 100) {
3389  if(end1 == 0) {
3390  tp2.Ang = tj2.Pts[tj2.EndPt[0] + 2].Ang;
3391  } else {
3392  tp2.Ang = tj2.Pts[tj2.EndPt[1] - 2].Ang;
3393  }
3394  } else if(loMCSMom) {
3395  // Low momentum - calculate the angle using the two Pts at the end
3396  unsigned short pt1, pt2;
3397  if(end2 == 0) {
3398  pt1 = tj2.EndPt[0];
3399  pt2 = pt1 + 1;
3400  } else {
3401  pt2 = tj2.EndPt[1];
3402  pt1 = pt2 - 1;
3403  }
3404  TrajPoint tpdir;
3405  if(MakeBareTrajPoint(slc, tj2.Pts[pt1], tj2.Pts[pt2], tpdir)) tp2.Ang = tpdir.Ang;
3406  } // low MCSMom
3407 
3408  if(!isVLA && !SignalBetween(slc, tp1, tp2, 0.99)) continue;
3409 
3410  // decide whether to merge or make a vertex
3411  // protect against angles > pi/2
3412  float dang = acos(DotProd(tp1.Dir, tp2.Dir));
3413  float sep = PosSep(tp1.Pos, tp2.Pos);
3414  // ignore this pair if the gap between them is much longer than the length of the shortest Tj
3415  float len1 = TrajLength(slc.tjs[it1]);
3416  float len2 = TrajLength(slc.tjs[it2]);
3417  if(len1 < len2 && sep > 3 * len1) continue;
3418  if(len2 < len1 && sep > 3 * len2) continue;
3419 
3420  // default cuts for locMCSMom condition
3421  float dangCut = 1;
3422  float docaCut = 2;
3423  float kinkSig = -1;
3424  if(!loMCSMom) {
3425  unsigned short nPtsFit = tcc.kinkCuts[0];
3426  bool useChg = (tcc.kinkCuts[2] > 0);
3427  kinkSig = KinkSignificance(slc, tj1, end1, tj2, end2, nPtsFit, useChg, prt);
3428  }
3429  docaCut = 1.5;
3430  if(isVLA) docaCut = 15;
3431  float chgPull = 0;
3432  if(tp1.AveChg > tp2.AveChg) {
3433  chgPull = (tp1.AveChg / tp2.AveChg - 1) / minChgRMS;
3434  } else {
3435  chgPull = (tp2.AveChg / tp1.AveChg - 1) / minChgRMS;
3436  }
3437  // open up the cuts on the last pass
3438  float chgFracCut = tcc.vtx2DCuts[8];
3439  float chgPullCut = tcc.chargeCuts[0];
3440  if(lastPass) {
3441  docaCut *= 2;
3442  chgFracCut *= 0.5;
3443  chgPullCut *= 1.5;
3444  }
3445 
3446  // check the merge cuts. Start with doca and dang requirements
3447  bool doMerge = bestDOCA < docaCut && dang < dangCut;
3448  bool showerTjs = tj1.PDGCode == 11 || tj2.PDGCode == 11;
3449  bool hiMCSMom = tj1.MCSMom > 200 || tj2.MCSMom > 200;
3450  // add a charge similarity requirement if not shower-like or low momentum or not LA
3451  if(doMerge && !showerTjs && hiMCSMom && chgPull > tcc.chargeCuts[0] && !isVLA) doMerge = false;
3452  // ignore the charge pull cut if both are high momentum and dang is really small
3453  if(!doMerge && tj1.MCSMom > 900 && tj2.MCSMom > 900 && dang < 0.1 && bestDOCA < docaCut) doMerge = true;
3454 
3455  // do not merge if chgPull is really high
3456  if(doMerge && chgPull > 2 * chgPullCut) doMerge = false;
3457  float dwc = DeadWireCount(slc, tp1, tp2);
3458 
3459  if(doMerge) {
3460  if(lastPass) {
3461  // last pass cuts are looser but ensure that the tj after merging meets the quality cut
3462  float npwc = NumPtsWithCharge(slc, tj1, true) + NumPtsWithCharge(slc, tj2, true);
3463  auto& tp1OtherEnd = tj1.Pts[tj1.EndPt[1 - end1]];
3464  auto& tp2OtherEnd = tj2.Pts[tj2.EndPt[1 - end2]];
3465  float nwires = std::abs(tp1OtherEnd.Pos[0] - tp2OtherEnd.Pos[0]);
3466  if(nwires == 0) nwires = 1;
3467  float hitFrac = npwc / nwires;
3468  doMerge = (hitFrac > tcc.qualityCuts[0]);
3469  } else {
3470  // don't merge if the gap between them is longer than the length of the shortest Tj
3471  if(len1 < len2) {
3472  if(sep > len1) doMerge = false;
3473  } else {
3474  if(sep > len2) doMerge = false;
3475  }
3476  if(prt) mf::LogVerbatim("TC")<<" merge check sep "<<sep<<" len1 "<<len1<<" len2 "<<len2<<" dead wire count "<<dwc<<" Merge? "<<doMerge;
3477  } // not lastPass
3478  } // doMerge
3479 
3480  // Require a large charge fraction near a merge point
3481  tjlist[0] = slc.tjs[it1].ID;
3482  tjlist[1] = slc.tjs[it2].ID;
3483  float chgFrac = ChgFracNearPos(slc, tp1.Pos, tjlist);
3484  if(doMerge && bestDOCA > 1 && chgFrac < chgFracCut) doMerge = false;
3485 
3486  // Check the MCSMom asymmetry and don't merge if it is higher than the user-specified cut
3487  float momAsym = std::abs(tj1.MCSMom - tj2.MCSMom) / (float)(tj1.MCSMom + tj2.MCSMom);
3488  if(doMerge && momAsym > tcc.vtx2DCuts[9]) doMerge = false;
3489  if(doMerge && (tj1.EndFlag[end1][kAtKink] || tj2.EndFlag[end2][kAtKink])) {
3490  // don't merge if a kink exists and the tjs are not too long
3491  if(len1 < 40 && len2 < 40) doMerge = false;
3492  // Kink on one + Bragg at other end of the other
3493  if(tj1.EndFlag[end1][kAtKink] && tj2.EndFlag[1-end2][kBragg]) doMerge = false;
3494  if(tj1.EndFlag[1-end1][kBragg] && tj2.EndFlag[end2][kAtKink]) doMerge = false;
3495  }
3496 
3497  // decide if we should make a vertex instead
3498  bool doVtx = false;
3499  if(!doMerge) {
3500  // check for a significant kink
3501  doVtx = (kinkSig > tcc.kinkCuts[1]);
3502  // and a less significant kink but very close separation
3503  doVtx = (kinkSig > 0.5 * tcc.kinkCuts[1] && sep < 2);
3504  } // !doMerge
3505 
3506  if(prt) {
3507  mf::LogVerbatim myprt("TC");
3508  myprt<<" EM: T"<<slc.tjs[it1].ID<<"_"<<end1<<" - T"<<slc.tjs[it2].ID<<"_"<<end2<<" tp1-tp2 "<<PrintPos(slc, tp1)<<"-"<<PrintPos(slc, tp2);
3509  myprt<<" FOM "<<std::fixed<<std::setprecision(2)<<bestFOM;
3510  myprt<<" DOCA "<<std::setprecision(1)<<bestDOCA;
3511  myprt<<" cut "<<docaCut<<" isVLA? "<<isVLA;
3512  myprt<<" dang "<<std::setprecision(2)<<dang<<" dangCut "<<dangCut;
3513  myprt<<" chgPull "<<std::setprecision(1)<<chgPull<<" Cut "<<chgPullCut;
3514  myprt<<" chgFrac "<<std::setprecision(2)<<chgFrac;
3515  myprt<<" momAsym "<<momAsym;
3516  myprt<<" kinkSig "<<std::setprecision(1)<<kinkSig;
3517  myprt<<" doMerge? "<<doMerge;
3518  myprt<<" doVtx? "<<doVtx;
3519  }
3520 
3521  if(bestDOCA > docaCut) continue;
3522 
3523  if(doMerge) {
3524  if(prt) mf::LogVerbatim("TC")<<" Merge ";
3525  bool didMerge = false;
3526  if(end1 == 1) {
3527  didMerge = MergeAndStore(slc, it1, it2, tcc.dbgMrg);
3528  } else {
3529  didMerge = MergeAndStore(slc, it2, it1, tcc.dbgMrg);
3530  }
3531  if(didMerge) {
3532  // Set the end merge flag for the killed trajectories to aid tracing merges
3533  tj1.AlgMod[kMerge] = true;
3534  tj2.AlgMod[kMerge] = true;
3535  iterate = true;
3536  } // Merge and store successfull
3537  else {
3538  if(prt) mf::LogVerbatim("TC")<<" MergeAndStore failed ";
3539  }
3540  } else if(doVtx) {
3541  // create a vertex instead if it passes the vertex cuts
3542  VtxStore aVtx;
3543  aVtx.CTP = slc.tjs[it1].CTP;
3544  aVtx.ID = slc.vtxs.size() + 1;
3545  // keep it simple if tp1 and tp2 are very close or if the angle between them
3546  // is small
3547  if(prt) {
3548  mf::LogVerbatim("TC")<<" candidate 2V"<<aVtx.ID<<" dang "<<dang<<" sep "<<PosSep(tp1.Pos, tp2.Pos);
3549  }
3550  bool fix2V = (PosSep(tp1.Pos, tp2.Pos) < 3 || dang < 0.1);
3551  if(fix2V) {
3552  aVtx.Pos[0] = 0.5 * (tp1.Pos[0] + tp2.Pos[0]);
3553  aVtx.Pos[1] = 0.5 * (tp1.Pos[1] + tp2.Pos[1]);
3554  aVtx.Stat[kFixed] = true;
3555  aVtx.PosErr[0] = std::abs(tp1.Pos[0] - tp2.Pos[0]);
3556  aVtx.PosErr[1] = std::abs(tp1.Pos[1] - tp2.Pos[1]);
3557  } else {
3558  float sepCut = tcc.vtx2DCuts[1];
3559  bool tj1Short = (slc.tjs[it1].EndPt[1] - slc.tjs[it1].EndPt[0] < maxShortTjLen);
3560  bool tj2Short = (slc.tjs[it2].EndPt[1] - slc.tjs[it2].EndPt[0] < maxShortTjLen);
3561  if(tj1Short || tj2Short) sepCut = tcc.vtx2DCuts[1];
3562  TrajIntersection(tp1, tp2, aVtx.Pos);
3563  float dw = aVtx.Pos[0] - tp1.Pos[0];
3564  if(std::abs(dw) > sepCut) continue;
3565  float dt = aVtx.Pos[1] - tp1.Pos[1];
3566  if(std::abs(dt) > sepCut) continue;
3567  dw = aVtx.Pos[0] - tp2.Pos[0];
3568  if(std::abs(dw) > sepCut) continue;
3569  dt = aVtx.Pos[1] - tp2.Pos[1];
3570  if(std::abs(dt) > sepCut) continue;
3571  // ensure that the vertex is not closer to the other end if the tj is short
3572  // but not too short
3573  if(tj1Short && len1 > 4) {
3574  TrajPoint otp1 = slc.tjs[it1].Pts[slc.tjs[it1].EndPt[1-end1]];
3575  if(PosSep2(otp1.Pos, aVtx.Pos) < PosSep2(tp1.Pos, aVtx.Pos)) continue;
3576  }
3577  if(tj2Short && len2 > 4) {
3578  TrajPoint otp2 = slc.tjs[it2].Pts[slc.tjs[it2].EndPt[1-end2]];
3579  if(PosSep2(otp2.Pos, aVtx.Pos) < PosSep2(tp2.Pos, aVtx.Pos)) continue;
3580  }
3581  // we expect the vertex to be between tp1 and tp2
3582  if(aVtx.Pos[0] < tp1.Pos[0] && aVtx.Pos[0] < tp2.Pos[0]) {
3583  aVtx.Pos[0] = std::min(tp1.Pos[0], tp2.Pos[0]);
3584  aVtx.Stat[kFixed] = true;
3585  }
3586  if(aVtx.Pos[0] > tp1.Pos[0] && aVtx.Pos[0] > tp2.Pos[0]) {
3587  aVtx.Pos[0] = std::max(tp1.Pos[0], tp2.Pos[0]);
3588  aVtx.Stat[kFixed] = true;
3589  }
3590  } // Tps not so close
3591  // We got this far. Try a vertex fit to ensure that the errors are reasonable
3592  slc.tjs[it1].VtxID[end1] = aVtx.ID;
3593  slc.tjs[it2].VtxID[end2] = aVtx.ID;
3594  if(!aVtx.Stat[kFixed] && !FitVertex(slc, aVtx, prt)) {
3595  // back out
3596  slc.tjs[it1].VtxID[end1] = 0;
3597  slc.tjs[it2].VtxID[end2] = 0;
3598  if(prt) mf::LogVerbatim("TC")<<" Vertex fit failed ";
3599  continue;
3600  }
3601  aVtx.NTraj = 2;
3602  aVtx.Pass = slc.tjs[it1].Pass;
3603  aVtx.Topo = end1 + end2;
3604  tj1.AlgMod[kMerge] = true;
3605  tj2.AlgMod[kMerge] = true;
3606  if(!StoreVertex(slc, aVtx)) continue;
3607  SetVx2Score(slc);
3608  if(prt) {
3609  auto& newVx = slc.vtxs[slc.vtxs.size() - 1];
3610  mf::LogVerbatim("TC")<<" New 2V"<<newVx.ID<<" at "<<(int)newVx.Pos[0]<<":"<<(int)(newVx.Pos[1]/tcc.unitsPerTick)<<" Score "<<newVx.Score;
3611  }
3612  // check the score and kill it if it is below the cut
3613  // BB Oct 1, 2019. Don't kill the vertex in this function since it is
3614  // called before short trajectories are reconstructed
3615  auto& newVx2 = slc.vtxs[slc.vtxs.size() - 1];
3616  if(newVx2.Score < tcc.vtx2DCuts[7] && CompatibleMerge(slc, tj1, tj2, prt)) {
3617  if(prt) {
3618  mf::LogVerbatim myprt("TC");
3619  myprt<<" Bad vertex: Bad score? "<<(newVx2.Score < tcc.vtx2DCuts[7]);
3620  myprt<<" cut "<<tcc.vtx2DCuts[7];
3621  myprt<<" CompatibleMerge? "<<CompatibleMerge(slc, tj1, tj2, prt);
3622  }
3623  slc.tjs[it1].VtxID[end1] = 0;
3624  slc.tjs[it2].VtxID[end2] = 0;
3625  MakeVertexObsolete("EM", slc, newVx2, true);
3626  bool didMerge = false;
3627  if(end1 == 1) {
3628  didMerge = MergeAndStore(slc, it1, it2, tcc.dbgMrg);
3629  } else {
3630  didMerge = MergeAndStore(slc, it2, it1, tcc.dbgMrg);
3631  }
3632  if(didMerge) {
3633  // Set the end merge flag for the killed trajectories to aid tracing merges
3634  tj1.AlgMod[kMerge] = true;
3635  tj1.AlgMod[kMerge] = true;
3636  iterate = true;
3637  } // Merge and store successfull
3638  else {
3639  if(prt) mf::LogVerbatim("TC")<<" MergeAndStore failed ";
3640  }
3641  } // OK score
3642  } // create a vertex
3643  if(tj1.AlgMod[kKilled]) break;
3644  } // end1
3645  } // it1
3646  } // iterate
3647 
3648  } // EndMerge
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:2726
std::vector< float > kinkCuts
kink finder algorithm
Definition: DataStructs.h:559
bool FitVertex(TCSlice &slc, VtxStore &vx, bool prt)
Definition: TCVertex.cxx:1954
std::vector< float > qualityCuts
Min points/wire, min consecutive pts after a gap.
Definition: DataStructs.h:563
TCConfig tcc
Definition: DataStructs.cxx:9
vertex position fixed manually - no fitting done
Definition: DataStructs.h:93
step from US -&gt; DS (true) or DS -&gt; US (false)
Definition: DataStructs.h:531
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2572
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:2540
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:590
bool MakeBareTrajPoint(const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:4110
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:1918
float OverlapFraction(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2)
Definition: Utils.cxx:713
bool CompatibleMerge(const TCSlice &slc, std::vector< int > &tjIDs, bool prt)
Definition: Utils.cxx:580
T abs(T value)
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2141
float KinkSignificance(TCSlice &slc, Trajectory &tj1, unsigned short end1, Trajectory &tj2, unsigned short end2, unsigned short nPtsFit, bool useChg, bool prt)
Definition: Utils.cxx:3056
float ChgFracNearPos(const TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3236
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2572
void FitTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:808
void ReverseTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:3294
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:607
std::vector< float > chargeCuts
Definition: DataStructs.h:562
bool MergeAndStore(TCSlice &slc, unsigned int itj1, unsigned int itj2, bool doPrt)
Definition: Utils.cxx:4664
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
Definition: Utils.cxx:2604
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:128
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
float TrajLength(const Trajectory &tj)
Definition: Utils.cxx:2646
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2565
void SetVx2Score(TCSlice &slc)
Definition: TCVertex.cxx:2264
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:550
bool SignalBetween(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2, const float &MinWireSignalFraction)
Definition: Utils.cxx:1807
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2116
bool TrajTrajDOCA(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2460
float tca::ExpectedHitsRMS ( TCSlice &  slc,
const TrajPoint &  tp 
)

Definition at line 1947 of file Utils.cxx.

1948  {
1949  // returns the expected RMS of hits for the trajectory point in ticks
1950  if (std::abs(tp.Dir[0]) > 0.001) {
1951  geo::PlaneID planeID = DecodeCTP(tp.CTP);
1952  return 1.5 * evt.aveHitRMS[planeID.Plane] +
1953  2 * std::abs(tp.Dir[1] / tp.Dir[0]) / tcc.unitsPerTick;
1954  }
1955  else {
1956  return 500;
1957  }
1958  } // ExpectedHitsRMS
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
T abs(T value)
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
std::vector< float > aveHitRMS
average RMS of an isolated hit
Definition: DataStructs.h:638
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
geo::PlaneID DecodeCTP(CTP_t CTP)
TCEvent evt
Definition: DataStructs.cxx:8
unsigned short tca::FarEnd ( const TCSlice &  slc,
const PFPStruct &  pfp,
const Point3_t &  pos 
)

Definition at line 3339 of file PFPUtils.cxx.

3340  {
3341  // Returns the end (0 or 1) of the pfp that is furthest away from the position pos
3342  if (pfp.ID == 0) return 0;
3343  if (pfp.TP3Ds.empty()) return 0;
3344  auto& pos0 = pfp.TP3Ds[0].Pos;
3345  auto& pos1 = pfp.TP3Ds[pfp.TP3Ds.size() - 1].Pos;
3346  if (PosSep2(pos1, pos) > PosSep2(pos0, pos)) return 1;
3347  return 0;
3348  } // FarEnd
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2572
unsigned short tca::FarEnd ( TCSlice &  slc,
const Trajectory &  tj,
const Point2_t &  pos 
)

Definition at line 4177 of file Utils.cxx.

4178  {
4179  // Returns the end (0 or 1) of the Tj that is furthest away from the position pos
4180  if (tj.ID == 0) return 0;
4181  if (PosSep2(tj.Pts[tj.EndPt[1]].Pos, pos) > PosSep2(tj.Pts[tj.EndPt[0]].Pos, pos)) return 1;
4182  return 0;
4183  } // FarEnd
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2572
void tca::FilldEdx ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
const TCSlice &  slc,
PFPStruct &  pfp 
)

Definition at line 2597 of file PFPUtils.cxx.

2601  {
2602  // Fills dE/dx variables in the pfp struct
2603 
2604  // don't attempt to find dE/dx at the end of a shower
2605  unsigned short numEnds = 2;
2606  if (pfp.PDGCode == 1111) numEnds = 1;
2607 
2608  // set dE/dx to 0 to indicate that a valid dE/dx is expected
2609  for (unsigned short end = 0; end < numEnds; ++end) {
2610  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane)
2611  pfp.dEdx[end][plane] = 0;
2612  } // end
2613 
2614  // square of the maximum length that is used for finding the average dE/dx
2615  float maxSep2 = 5 * tcc.wirePitch;
2616  maxSep2 *= maxSep2;
2617 
2618  for (unsigned short end = 0; end < numEnds; ++end) {
2619  std::vector<float> cnt(slc.nPlanes);
2620  short dir = 1 - 2 * end;
2621  auto endPos = PosAtEnd(pfp, end);
2622  for (std::size_t ii = 0; ii < pfp.TP3Ds.size(); ++ii) {
2623  unsigned short ipt;
2624  if (dir > 0) { ipt = ii; }
2625  else {
2626  ipt = pfp.TP3Ds.size() - ii - 1;
2627  }
2628  if (ipt >= pfp.TP3Ds.size()) break;
2629  auto& tp3d = pfp.TP3Ds[ipt];
2630  if (tp3d.Flags[kTP3DBad]) continue;
2631  if (PosSep2(tp3d.Pos, endPos) > maxSep2) break;
2632  // require good points
2633  if (!tp3d.Flags[kTP3DGood]) continue;
2634  float dedx = dEdx(clockData, detProp, slc, tp3d);
2635  if (dedx < 0.5) continue;
2636  unsigned short plane = DecodeCTP(tp3d.CTP).Plane;
2637  pfp.dEdx[end][plane] += dedx;
2638  ++cnt[plane];
2639  } // ii
2640  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
2641  if (cnt[plane] == 0) continue;
2642  pfp.dEdx[end][plane] /= cnt[plane];
2643  } // plane
2644  } // end
2645 
2646  } // FilldEdx
TCConfig tcc
Definition: DataStructs.cxx:9
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3293
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2572
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
float dEdx(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, TP3D &tp3d)
Definition: PFPUtils.cxx:2687
tuple dir
Definition: dropbox.py:28
geo::PlaneID DecodeCTP(CTP_t CTP)
auto const detProp
void tca::FillGaps ( TCSlice &  slc,
Trajectory &  tj 
)

Definition at line 2033 of file StepUtils.cxx.

2034  {
2035  // Fill in any gaps in the trajectory with close hits regardless of charge (well maybe not quite that)
2036 
2037  if(!tcc.useAlg[kFillGaps]) return;
2038  if(tj.AlgMod[kJunkTj]) return;
2039  if(tj.ChgRMS <= 0) return;
2040 
2041  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
2042  if(npwc < 8) return;
2043 
2044  // don't consider the last few points since they would be trimmed
2045  unsigned short toPt = tj.EndPt[1] - 2;
2046  if(!tj.EndFlag[1][kBragg]) {
2047  // Don't fill gaps (with high-charge hits) near the end. Find the last point near the
2048  // end that would have normal charge if all the hit were added
2049  unsigned short cnt = 0;
2050  for(unsigned short ipt = tj.EndPt[1] - 2; ipt > tj.EndPt[0]; --ipt) {
2051  auto& tp = tj.Pts[ipt];
2052  float chg = tp.Chg;
2053  if(chg == 0) {
2054  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2055  unsigned int iht = tp.Hits[ii];
2056  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2057  chg += hit.Integral();
2058  }
2059  } // chg == 0
2060  float chgPull = (chg / tj.AveChg - 1) / tj.ChgRMS;
2061  if(chgPull < 2) {
2062  toPt = ipt;
2063  break;
2064  }
2065  ++cnt;
2066  if(cnt > 20) break;
2067  } // ipt
2068  } // !tj.EndFlag[1][kBragg]
2069 
2070  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"FG: Check Tj "<<tj.ID<<" from "<<PrintPos(slc, tj.Pts[tj.EndPt[0]])<<" to "<<PrintPos(slc, tj.Pts[toPt]);
2071 
2072  // start with the first point that has charge
2073  short firstPtWithChg = tj.EndPt[0];
2074  bool first = true;
2075  float maxDelta = 1;
2076  // don't let MCSMom suffer too much while filling gaps
2077  short minMCSMom = 0.7 * tj.MCSMom;
2078  while(firstPtWithChg < toPt) {
2079  short nextPtWithChg = firstPtWithChg + 1;
2080  // find the next point with charge
2081  for(nextPtWithChg = firstPtWithChg + 1; nextPtWithChg < tj.EndPt[1]; ++nextPtWithChg) {
2082  if(tj.Pts[nextPtWithChg].Chg > 0) break;
2083  } // nextPtWithChg
2084  if(nextPtWithChg == firstPtWithChg + 1) {
2085  // the next point has charge
2086  ++firstPtWithChg;
2087  continue;
2088  }
2089  // Found a gap. Require at least two consecutive points with charge after the gap
2090  if(nextPtWithChg < (tj.EndPt[1] - 1) && tj.Pts[nextPtWithChg + 1].Chg == 0) {
2091  firstPtWithChg = nextPtWithChg;
2092  continue;
2093  }
2094  // Make a bare trajectory point at firstPtWithChg that points to nextPtWithChg
2095  TrajPoint tp;
2096  if(!MakeBareTrajPoint(slc, tj.Pts[firstPtWithChg], tj.Pts[nextPtWithChg], tp)) {
2097  tj.IsGood = false;
2098  return;
2099  }
2100  // Find the maximum delta between hits and the trajectory Pos for all
2101  // hits on this trajectory
2102  if(first) {
2103  maxDelta = 2.5 * MaxHitDelta(slc, tj);
2104  first = false;
2105  } // first
2106  // define a loose charge cut using the average charge at the first point with charge
2107  float maxChg = tj.Pts[firstPtWithChg].AveChg * (1 + 2 * tcc.chargeCuts[0] * tj.ChgRMS);
2108  // Eliminate the charge cut altogether if we are close to an end
2109  if(tj.Pts.size() < 10) {
2110  maxChg = 1E6;
2111  } else {
2112  short chgCutPt = tj.EndPt[0] + 5;
2113  if(firstPtWithChg < chgCutPt) {
2114  // gap is near end 0
2115  maxChg = 1E6;
2116  } else {
2117  // check for gap near end 1
2118  chgCutPt = tj.EndPt[1] - 5;
2119  if(chgCutPt < tj.EndPt[0]) chgCutPt = tj.EndPt[0];
2120  if(nextPtWithChg > chgCutPt) maxChg = 1E6;
2121  }
2122  }
2123 
2124  // fill in the gap
2125  for(unsigned short mpt = firstPtWithChg + 1; mpt < nextPtWithChg; ++mpt) {
2126  if(tj.Pts[mpt].Chg > 0) {
2127  mf::LogVerbatim("TC")<<"FillGaps coding error: firstPtWithChg "<<firstPtWithChg<<" mpt "<<mpt<<" nextPtWithChg "<<nextPtWithChg;
2128  slc.isValid = false;
2129  return;
2130  }
2131  bool filled = false;
2132  float chg = 0;
2133  for(unsigned short ii = 0; ii < tj.Pts[mpt].Hits.size(); ++ii) {
2134  unsigned int iht = tj.Pts[mpt].Hits[ii];
2135  if(slc.slHits[iht].InTraj > 0) continue;
2136  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2137  float delta = PointTrajDOCA(slc, iht, tp);
2138  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" FG: "<<PrintPos(slc,tj.Pts[mpt])<<" hit "<<PrintHit(slc.slHits[iht])<<" delta "<<delta<<" maxDelta "<<maxDelta<<" Chg "<<hit.Integral()<<" maxChg "<<maxChg;
2139  if(delta > maxDelta) continue;
2140  tj.Pts[mpt].UseHit[ii] = true;
2141  slc.slHits[iht].InTraj = tj.ID;
2142  chg += hit.Integral();
2143  filled = true;
2144  } // ii
2145  if(chg > maxChg || MCSMom(slc, tj) < minMCSMom) {
2146  // don't use these hits after all
2147  UnsetUsedHits(slc, tj.Pts[mpt]);
2148  filled = false;
2149  }
2150  if(filled) {
2151  DefineHitPos(slc, tj.Pts[mpt]);
2152  tj.AlgMod[kFillGaps] = true;
2153  if(tcc.dbgStp) {
2154  PrintTP("FG", slc, mpt, tj.StepDir, tj.Pass, tj.Pts[mpt]);
2155  mf::LogVerbatim("TC")<<"Check MCSMom "<<MCSMom(slc, tj);
2156  }
2157  } // filled
2158  } // mpt
2159  firstPtWithChg = nextPtWithChg;
2160  } // firstPtWithChg
2161 
2162  if(tj.AlgMod[kFillGaps]) tj.MCSMom = MCSMom(slc, tj);
2163 
2164  } // FillGaps
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3468
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:6296
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1075
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2572
process_name hit
Definition: cheaterreco.fcl:51
bool MakeBareTrajPoint(const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:4110
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1672
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6516
std::vector< float > chargeCuts
Definition: DataStructs.h:562
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
float MaxHitDelta(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:3276
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2116
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 1745 of file PFPUtils.cxx.

1750  {
1751  // Look for gaps in each plane in the TP3Ds vector in planes in which
1752  // the projection of the pfp angle is large (~> 60 degrees). Hits
1753  // reconstructed at large angles are poorly reconstructed which results
1754  // in poorly reconstructed 2D trajectories
1755 
1756  if (pfp.ID <= 0) return;
1757  if (pfp.TP3Ds.empty()) return;
1758  if (pfp.SectionFits.empty()) return;
1759  if (!tcc.useAlg[kFillGaps3D]) return;
1760  if (pfp.Flags[kJunk3D]) return;
1761  if (pfp.Flags[kSmallAngle]) return;
1762 
1763  // Only print APIR details if MVI is set
1764  bool foundMVI = (tcc.dbgPFP && pfp.MVI == debug.MVI);
1765 
1766  // make a copy in case something goes wrong
1767  auto pWork = pfp;
1768 
1769  unsigned short nPtsAdded = 0;
1770  unsigned short fromPt = 0;
1771  unsigned short toPt = pWork.TP3Ds.size();
1772  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
1773  CTP_t inCTP = EncodeCTP(pWork.TPCID.Cryostat, pWork.TPCID.TPC, plane);
1774  unsigned short nWires, nAdd;
1775  AddPointsInRange(clockData,
1776  detProp,
1777  slc,
1778  pWork,
1779  fromPt,
1780  toPt,
1781  inCTP,
1782  tcc.match3DCuts[4],
1783  nWires,
1784  nAdd,
1785  foundMVI);
1786  if (pWork.Flags[kNeedsUpdate]) Update(clockData, detProp, slc, pWork, prt);
1787  nPtsAdded += nAdd;
1788  } // plane
1789  if (prt) mf::LogVerbatim("TC") << "FG3D P" << pWork.ID << " added " << nPtsAdded << " points";
1790  if (pWork.Flags[kNeedsUpdate] && !Update(clockData, detProp, slc, pWork, prt)) return;
1791  pfp = pWork;
1792  return;
1793  } // FillGaps3D
TCConfig tcc
Definition: DataStructs.cxx:9
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:1838
std::vector< float > match3DCuts
3D matching cuts
Definition: DataStructs.h:560
unsigned int CTP_t
Definition: DataStructs.h:47
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:52
auto const detProp
bool Update(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, bool prt)
Definition: PFPUtils.cxx:1057
void tca::FillmAllTraj ( detinfo::DetectorPropertiesData const &  detProp,
TCSlice &  slc 
)

Definition at line 2382 of file PFPUtils.cxx.

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

Definition at line 4461 of file Utils.cxx.

4462  {
4463  // Defines the local vector of dead wires and the low-high range of hits in each wire in
4464  // the TPCID in TCEvent. Note that there is no requirement that the allHits collection is sorted. Care should
4465  // be taken when looping over hits using this range - see SignalAtTp
4466 
4467  // see if this function was called in the current TPCID. There is nothing that needs to
4468  // be done if that is the case
4469  if (inTPCID == evt.TPCID) return;
4470 
4471  evt.TPCID = inTPCID;
4472  unsigned short nplanes = tcc.geom->Nplanes(inTPCID);
4473  unsigned int cstat = inTPCID.Cryostat;
4474  unsigned int tpc = inTPCID.TPC;
4475  if (tcc.useChannelStatus) {
4476  lariov::ChannelStatusProvider const& channelStatus =
4477  art::ServiceHandle<lariov::ChannelStatusService>()->GetProvider();
4478  evt.goodWire.resize(nplanes);
4479  for (unsigned short pln = 0; pln < nplanes; ++pln) {
4480  unsigned int nwires = tcc.geom->Nwires(pln, tpc, cstat);
4481  // set all wires dead
4482  evt.goodWire[pln].resize(nwires, false);
4483  for (unsigned int wire = 0; wire < nwires; ++wire) {
4484  raw::ChannelID_t chan =
4485  tcc.geom->PlaneWireToChannel((int)pln, (int)wire, (int)tpc, (int)cstat);
4486  evt.goodWire[pln][wire] = channelStatus.IsGood(chan);
4487  } // wire
4488  } // pln
4489  }
4490  else {
4491  // resize and set every channel good
4492  evt.goodWire.resize(nplanes);
4493  for (unsigned short pln = 0; pln < nplanes; ++pln) {
4494  unsigned int nwires = tcc.geom->Nwires(pln, tpc, cstat);
4495  evt.goodWire[pln].resize(nwires, true);
4496  } // pln
4497  } // don't use channelStatus
4498 
4499  // there is no need to define evt.wireHitRange if the hit collection is not sliced. The function
4500  // SignalAtTP will then use the (smaller) slc.WireHitRange instead of evt.wireHitRange
4501  if (!evt.expectSlicedHits) return;
4502 
4503  // define the size of evt.wireHitRange
4504  evt.wireHitRange.resize(nplanes);
4505  for (unsigned short pln = 0; pln < nplanes; ++pln) {
4506  unsigned int nwires = tcc.geom->Nwires(pln, tpc, cstat);
4507  evt.wireHitRange[pln].resize(nwires);
4508  for (unsigned int wire = 0; wire < nwires; ++wire)
4509  evt.wireHitRange[pln][wire] = {UINT_MAX, UINT_MAX};
4510  } // pln
4511 
4512  // next define the wireHitRange values. Make one loop through the allHits collection
4513  unsigned int nBadWireFix = 0;
4514  for (unsigned int iht = 0; iht < (*evt.allHits).size(); ++iht) {
4515  auto& hit = (*evt.allHits)[iht];
4516  auto wid = hit.WireID();
4517  if (wid.Cryostat != cstat) continue;
4518  if (wid.TPC != tpc) continue;
4519  unsigned short pln = wid.Plane;
4520  unsigned int wire = wid.Wire;
4521  // Check the goodWire status and correct it if it's wrong
4522  if (!evt.goodWire[pln][wire]) {
4523  evt.goodWire[pln][wire] = true;
4524  ++nBadWireFix;
4525  } // not goodWire
4526  if (evt.wireHitRange[pln][wire].first == UINT_MAX) evt.wireHitRange[pln][wire].first = iht;
4527  evt.wireHitRange[pln][wire].second = iht;
4528  } // iht
4529  if (nBadWireFix > 0 && tcc.modes[kDebug]) {
4530  std::cout << "FillWireHitRange found hits on " << nBadWireFix
4531  << " wires that were declared not-good by the ChannelStatus service. Fixed it...\n";
4532  }
4533  } // FillWireHitRange
geo::TPCID TPCID
Definition: DataStructs.h:621
TCConfig tcc
Definition: DataStructs.cxx:9
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:212
std::size_t size(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:561
process_name hit
Definition: cheaterreco.fcl:51
bool expectSlicedHits
info passed from the module - used to (not) define wireHitRange
Definition: DataStructs.h:648
unsigned int Nwires(unsigned int p, unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wires in the specified plane.
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:630
virtual bool IsGood(raw::ChannelID_t channel) const
Returns whether the specified channel is physical and good.
const geo::GeometryCore * geom
Definition: DataStructs.h:576
Class providing information about the quality of channels.
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:607
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:622
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:406
std::vector< std::vector< std::pair< unsigned int, unsigned int > > > wireHitRange
Definition: DataStructs.h:626
bool useChannelStatus
Definition: DataStructs.h:609
master switch for turning on debug mode
Definition: DataStructs.h:533
BEGIN_PROLOG could also be cout
bool tca::FillWireHitRange ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
TCSlice &  slc 
)

Definition at line 4537 of file Utils.cxx.

4540  {
4541  // fills the WireHitRange vector. Slightly modified version of the one in ClusterCrawlerAlg.
4542  // Returns false if there was a serious error
4543 
4544  // determine the number of planes
4545  unsigned int cstat = slc.TPCID.Cryostat;
4546  unsigned int tpc = slc.TPCID.TPC;
4547  unsigned short nplanes = tcc.geom->Nplanes(tpc, cstat);
4548  slc.nPlanes = nplanes;
4549  if (nplanes > 3) return false;
4550 
4551  // Y,Z limits of the detector
4552  double local[3] = {0., 0., 0.};
4553  double world[3] = {0., 0., 0.};
4554  const geo::TPCGeo& thetpc = tcc.geom->TPC(tpc, cstat);
4555  thetpc.LocalToWorld(local, world);
4556  // reduce the active area of the TPC by 1 cm to prevent wire boundary issues
4557  slc.xLo = world[0] - tcc.geom->DetHalfWidth(tpc, cstat) + 1;
4558  slc.xHi = world[0] + tcc.geom->DetHalfWidth(tpc, cstat) - 1;
4559  slc.yLo = world[1] - tcc.geom->DetHalfHeight(tpc, cstat) + 1;
4560  slc.yHi = world[1] + tcc.geom->DetHalfHeight(tpc, cstat) - 1;
4561  slc.zLo = world[2] - tcc.geom->DetLength(tpc, cstat) / 2 + 1;
4562  slc.zHi = world[2] + tcc.geom->DetLength(tpc, cstat) / 2 - 1;
4563 
4564  // initialize everything
4565  slc.wireHitRange.resize(nplanes);
4566  slc.firstWire.resize(nplanes);
4567  slc.lastWire.resize(nplanes);
4568  slc.nWires.resize(nplanes);
4569  tcc.maxPos0.resize(nplanes);
4570  tcc.maxPos1.resize(nplanes);
4571  evt.aveHitRMS.resize(nplanes, nplanes);
4572 
4573  std::pair<unsigned int, unsigned int> flag;
4574  flag.first = UINT_MAX;
4575  flag.second = UINT_MAX;
4576 
4577  // Calculate tcc.unitsPerTick, the scale factor to convert a tick into
4578  // Wire Spacing Equivalent (WSE) units where the wire spacing in this plane = 1.
4579  // Strictly speaking this factor should be calculated for each plane to handle the
4580  // case where the wire spacing is different in each plane. Deal with this later if
4581  // the approximation used here fails.
4582 
4583  raw::ChannelID_t channel = tcc.geom->PlaneWireToChannel(0, 0, (int)tpc, (int)cstat);
4584  tcc.wirePitch = tcc.geom->WirePitch(tcc.geom->View(channel));
4585  float tickToDist = detProp.DriftVelocity(detProp.Efield(), detProp.Temperature());
4586  tickToDist *= 1.e-3 * sampling_rate(clockData); // 1e-3 is conversion of 1/us to 1/ns
4587  tcc.unitsPerTick = tickToDist / tcc.wirePitch;
4588  for (unsigned short plane = 0; plane < nplanes; ++plane) {
4589  slc.firstWire[plane] = UINT_MAX;
4590  slc.lastWire[plane] = 0;
4591  slc.nWires[plane] = tcc.geom->Nwires(plane, tpc, cstat);
4592  slc.wireHitRange[plane].resize(slc.nWires[plane], flag);
4593  tcc.maxPos0[plane] = (float)slc.nWires[plane] - 0.5;
4594  tcc.maxPos1[plane] = (float)detProp.NumberTimeSamples() * tcc.unitsPerTick;
4595  }
4596 
4597  unsigned int lastWire = 0, lastPlane = 0;
4598  for (unsigned int iht = 0; iht < slc.slHits.size(); ++iht) {
4599  unsigned int ahi = slc.slHits[iht].allHitsIndex;
4600  if (ahi > (*evt.allHits).size() - 1) return false;
4601  auto& hit = (*evt.allHits)[ahi];
4602  if (hit.WireID().Cryostat != cstat) continue;
4603  if (hit.WireID().TPC != tpc) continue;
4604  unsigned short plane = hit.WireID().Plane;
4605  unsigned int wire = hit.WireID().Wire;
4606  if (wire > slc.nWires[plane] - 1) {
4607  mf::LogWarning("TC") << "FillWireHitRange: Invalid wire number " << wire << " > "
4608  << slc.nWires[plane] - 1 << " in plane " << plane << " Quitting";
4609  return false;
4610  } // too large wire number
4611  if (plane == lastPlane && wire < lastWire) {
4612  mf::LogWarning("TC")
4613  << "FillWireHitRange: Hits are not in increasing wire order. Quitting ";
4614  return false;
4615  } // hits out of order
4616  lastWire = wire;
4617  lastPlane = plane;
4618  if (slc.firstWire[plane] == UINT_MAX) slc.firstWire[plane] = wire;
4619  if (slc.wireHitRange[plane][wire].first == UINT_MAX)
4620  slc.wireHitRange[plane][wire].first = iht;
4621  slc.wireHitRange[plane][wire].second = iht;
4622  slc.lastWire[plane] = wire + 1;
4623  } // iht
4624  // check
4625  unsigned int slhitsSize = slc.slHits.size();
4626  for (unsigned short plane = 0; plane < nplanes; ++plane) {
4627  for (unsigned int wire = slc.firstWire[plane]; wire < slc.lastWire[plane]; ++wire) {
4628  if (slc.wireHitRange[plane][wire].first == UINT_MAX) continue;
4629  if (slc.wireHitRange[plane][wire].first > slhitsSize - 1 &&
4630  slc.wireHitRange[plane][wire].second > slhitsSize)
4631  return false;
4632  } // wire
4633  } // plane
4634 
4635  // Find the average multiplicity 1 hit RMS and calculate the expected max RMS for each range
4636  if (tcc.modes[kDebug] && (int)tpc == debug.TPC) {
4637  // Note that this function is called before the slice is pushed into slices so the index
4638  // isn't decremented by 1
4639  std::cout << "Slice ID/Index " << slc.ID << "/" << slices.size() << " tpc " << tpc
4640  << " tcc.unitsPerTick " << std::setprecision(3) << tcc.unitsPerTick;
4641  std::cout << " Active volume (";
4642  std::cout << std::fixed << std::setprecision(1) << slc.xLo << " < X < " << slc.xHi << ") (";
4643  std::cout << std::fixed << std::setprecision(1) << slc.yLo << " < Y < " << slc.yHi << ") (";
4644  std::cout << std::fixed << std::setprecision(1) << slc.zLo << " < Z < " << slc.zHi << ")\n";
4645  }
4646 
4647  return true;
4648 
4649  } // FillWireHitRange
geo::Length_t DetHalfWidth(geo::TPCID const &tpcid) const
Returns the half width of the active volume of the specified TPC.
std::vector< float > maxPos0
Definition: DataStructs.h:572
then echo unknown compiler flag
TCConfig tcc
Definition: DataStructs.cxx:9
Geometry information for a single TPC.
Definition: TPCGeo.h:38
process_name hit
Definition: cheaterreco.fcl:51
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
unsigned int Nwires(unsigned int p, unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wires in the specified plane.
then local
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
geo::Length_t DetHalfHeight(geo::TPCID const &tpcid) const
Returns the half height of the active volume of the specified TPC.
std::vector< float > maxPos1
Definition: DataStructs.h:573
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
std::vector< float > aveHitRMS
average RMS of an isolated hit
Definition: DataStructs.h:638
geo::Length_t DetLength(geo::TPCID const &tpcid) const
Returns the length of the active volume of the specified TPC.
const geo::GeometryCore * geom
Definition: DataStructs.h:576
View_t View(geo::PlaneID const &pid) const
Returns the view (wire orientation) on the channels of specified TPC plane.
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:607
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:622
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
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:533
void LocalToWorld(const double *tpc, double *world) const
Transform point from local TPC frame to world frame.
Definition: TPCGeo.h:563
BEGIN_PROLOG could also be cout
auto const detProp
void tca::FillWireIntersections ( TCSlice &  slc)

Definition at line 612 of file PFPUtils.cxx.

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

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

Definition at line 1359 of file PFPUtils.cxx.

1364  {
1365  // Scans the TP3Ds vector starting at fromPt until it finds min2DPts in two planes. It returns
1366  // with the index of that point (+1) in the TP3Ds vector. The dir variable defines the scan direction in
1367  // the TP3Ds vector
1368  if (fromPt > pfp.TP3Ds.size() - 1) return USHRT_MAX;
1369  if (pfp.TP3Ds.size() < 2 * min2DPts) return USHRT_MAX;
1370  if (dir == 0) return USHRT_MAX;
1371 
1372  std::vector<unsigned short> cntInPln(slc.nPlanes);
1373  for (std::size_t ii = 0; ii < pfp.TP3Ds.size(); ++ii) {
1374  unsigned short ipt = fromPt + ii;
1375  if (dir < 0) ipt = fromPt - ii;
1376  if (ipt >= pfp.TP3Ds.size()) break;
1377  auto& tp3d = pfp.TP3Ds[ipt];
1378  if (!tp3d.Flags[kTP3DGood]) continue;
1379  unsigned short plane = DecodeCTP(slc.tjs[tp3d.TjID - 1].CTP).Plane;
1380  ++cntInPln[plane];
1381  unsigned short enufInPlane = 0;
1382  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane)
1383  if (cntInPln[plane] >= min2DPts) ++enufInPlane;
1384  if (enufInPlane > 1) return ipt + 1;
1385  if (dir < 0 && ipt == 0) break;
1386  } // ipt
1387  return USHRT_MAX;
1388  } // Find3DRecoRange
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
tuple dir
Definition: dropbox.py:28
geo::PlaneID DecodeCTP(CTP_t CTP)
void tca::Find3DVertices ( detinfo::DetectorPropertiesData const &  detProp,
TCSlice &  slc 
)

Definition at line 1268 of file TCVertex.cxx.

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

Definition at line 3097 of file PFPUtils.cxx.

3098  {
3099  // Calculate the distance along and transvers to the direction vector from pos1 to pos2
3100  alongTrans[0] = 0;
3101  alongTrans[1] = 0;
3102  if (pos1[0] == pos2[0] && pos1[1] == pos2[1] && pos1[2] == pos2[2]) return;
3103  auto ptDir = PointDirection(pos1, pos2);
3104  SetMag(dir1, 1.0);
3105  double costh = DotProd(dir1, ptDir);
3106  if (costh > 1) costh = 1;
3107  double sep = PosSep(pos1, pos2);
3108  alongTrans[0] = costh * sep;
3109  double sinth = sqrt(1 - costh * costh);
3110  alongTrans[1] = sinth * sep;
3111  } // FindAlongTrans
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:2548
bool SetMag(Vector3_t &v1, double mag)
Definition: PFPUtils.cxx:2583
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:128
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2565
void tca::FindAlongTrans ( Point2_t  pos1,
Vector2_t  dir1,
Point2_t  pos2,
Point2_t &  alongTrans 
)

Definition at line 3360 of file Utils.cxx.

3361  {
3362  // Calculate the distance along and transverse to the direction vector dir1 from pos1 to pos2
3363  alongTrans[0] = 0;
3364  alongTrans[1] = 0;
3365  if (pos1[0] == pos2[0] && pos1[1] == pos2[1]) return;
3366  pos1[0] = pos2[0] - pos1[0];
3367  pos1[1] = pos2[1] - pos1[1];
3368  double sep = sqrt(pos1[0] * pos1[0] + pos1[1] * pos1[1]);
3369  if (sep < 1E-6) return;
3370  Vector2_t ptDir;
3371  ptDir[0] = pos1[0] / sep;
3372  ptDir[1] = pos1[1] / sep;
3373  SetMag(dir1, 1.0);
3374  double costh = DotProd(dir1, ptDir);
3375  if (costh > 1.0 || costh < -1.0) return;
3376  alongTrans[0] = costh * sep;
3377  double sinth = sqrt(1 - costh * costh);
3378  alongTrans[1] = sinth * sep;
3379  } // FindAlongTrans
process_name E
bool SetMag(Vector3_t &v1, double mag)
Definition: PFPUtils.cxx:2583
std::array< double, 2 > Vector2_t
Definition: DataStructs.h:44
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:128
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 2843 of file Utils.cxx.

2850  {
2851  // returns a vector of hits that are within the Window[Pos0][Pos1] in plane.
2852  // Note that hits on wire wireWindow[1] are returned as well. The definition of close
2853  // depends on setting of usePeakTime. If UsePeakTime is true, a hit is considered nearby if
2854  // the PeakTime is within the window. This is shown schematically here where
2855  // the time is on the horizontal axis and a "-" denotes a valid entry
2856  // timeWindow -----------------
2857  // hit PeakTime + close
2858  // hit PeakTime + not close
2859  // If usePeakTime is false, a hit is considered nearby if the hit StartTick and EndTick overlap with the timeWindow
2860  // Time window ---------
2861  // Hit StartTick-EndTick -------- close
2862  // Hit StartTick - EndTick -------- not close
2863 
2864  hitsNear = false;
2865  std::vector<unsigned int> closeHits;
2866  if (plane > slc.firstWire.size() - 1) return closeHits;
2867  // window in the wire coordinate
2868  int loWire = wireWindow[0];
2869  if (loWire < (int)slc.firstWire[plane]) loWire = slc.firstWire[plane];
2870  int hiWire = wireWindow[1];
2871  if (hiWire > (int)slc.lastWire[plane] - 1) hiWire = slc.lastWire[plane] - 1;
2872  // window in the time coordinate
2873  float minTick = timeWindow[0] / tcc.unitsPerTick;
2874  float maxTick = timeWindow[1] / tcc.unitsPerTick;
2875  for (int wire = loWire; wire <= hiWire; ++wire) {
2876  // Set hitsNear if the wire is dead
2877  if (!evt.goodWire[plane][wire]) hitsNear = true;
2878  if (slc.wireHitRange[plane][wire].first == UINT_MAX) continue;
2879  unsigned int firstHit = slc.wireHitRange[plane][wire].first;
2880  unsigned int lastHit = slc.wireHitRange[plane][wire].second;
2881  for (unsigned int iht = firstHit; iht <= lastHit; ++iht) {
2882  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2883  if (usePeakTime) {
2884  if (hit.PeakTime() < minTick) continue;
2885  if (hit.PeakTime() > maxTick) break;
2886  }
2887  else {
2888  int hiLo = minTick;
2889  if (hit.StartTick() > hiLo) hiLo = hit.StartTick();
2890  int loHi = maxTick;
2891  if (hit.EndTick() < loHi) loHi = hit.EndTick();
2892  if (loHi < hiLo) continue;
2893  if (hiLo > loHi) break;
2894  }
2895  hitsNear = true;
2896  bool takeit = (hitRequest == kAllHits);
2897  if (hitRequest == kUsedHits && slc.slHits[iht].InTraj > 0) takeit = true;
2898  if (hitRequest == kUnusedHits && slc.slHits[iht].InTraj == 0) takeit = true;
2899  if (takeit) closeHits.push_back(iht);
2900  } // iht
2901  } // wire
2902  return closeHits;
2903  } // FindCloseHits
then if[["$THISISATEST"==1]]
Definition: neoSmazza.sh:95
TCConfig tcc
Definition: DataStructs.cxx:9
process_name hit
Definition: cheaterreco.fcl:51
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:630
for($it=0;$it< $RaceTrack_number;$it++)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
TCEvent evt
Definition: DataStructs.cxx:8
bool tca::FindCloseHits ( TCSlice &  slc,
TrajPoint &  tp,
float const &  maxDelta,
HitStatus_t  hitRequest 
)

Definition at line 2907 of file Utils.cxx.

2908  {
2909  // Fills tp.Hits sets tp.UseHit true for hits that are close to tp.Pos. Returns true if there are
2910  // close hits OR if the wire at this position is dead
2911 
2912  tp.Hits.clear();
2913  tp.UseHit.reset();
2914  tp.Environment.reset();
2915  if (!WireHitRangeOK(slc, tp.CTP)) { return false; }
2916 
2917  if (tp.Pos[0] < -0.4) return false;
2918  unsigned short plane = DecodeCTP(tp.CTP).Plane;
2919  unsigned int wire = std::nearbyint(tp.Pos[0]);
2920  if (wire < slc.firstWire[plane]) return false;
2921  if (wire > slc.lastWire[plane] - 1) return false;
2922 
2923  // dead wire
2924  if (!evt.goodWire[plane][wire]) {
2925  tp.Environment[kEnvNotGoodWire] = true;
2926  return true;
2927  }
2928  tp.Environment[kEnvNotGoodWire] = false;
2929  // live wire with no hits
2930  if (slc.wireHitRange[plane][wire].first == UINT_MAX) return false;
2931 
2932  unsigned int firstHit = slc.wireHitRange[plane][wire].first;
2933  unsigned int lastHit = slc.wireHitRange[plane][wire].second;
2934 
2935  float fwire = wire;
2936  for (unsigned int iht = firstHit; iht <= lastHit; ++iht) {
2937  if ((unsigned int)slc.slHits[iht].InTraj > slc.tjs.size()) continue;
2938  bool useit = (hitRequest == kAllHits);
2939  if (hitRequest == kUsedHits && slc.slHits[iht].InTraj > 0) useit = true;
2940  if (hitRequest == kUnusedHits && slc.slHits[iht].InTraj == 0) useit = true;
2941  if (!useit) continue;
2942  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2943  float ftime = tcc.unitsPerTick * hit.PeakTime();
2944  float delta = PointTrajDOCA(slc, fwire, ftime, tp);
2945  if (delta < maxDelta) tp.Hits.push_back(iht);
2946  } // iht
2947  if (tp.Hits.size() > 16) { tp.Hits.resize(16); }
2948  // Set UseHit false. The calling routine should decide if these hits should be used
2949  tp.UseHit.reset();
2950  return (!tp.Hits.empty());
2951 
2952  } // FindCloseHits
TCConfig tcc
Definition: DataStructs.cxx:9
bool WireHitRangeOK(TCSlice &slc, const CTP_t &inCTP)
Definition: Utils.cxx:4653
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2572
process_name hit
Definition: cheaterreco.fcl:51
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:630
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
TCEvent evt
Definition: DataStructs.cxx:8
std::vector< int > tca::FindCloseTjs ( const TCSlice &  slc,
const TrajPoint &  fromTp,
const TrajPoint &  toTp,
const float &  maxDelta 
)

Definition at line 2977 of file Utils.cxx.

2981  {
2982  // Returns a list of Tj IDs that have hits within distance maxDelta on a line drawn between the two Tps as shown
2983  // graphically here, where a "*" is a Tp and "|" and "-" are the boundaries of the region that is checked
2984  //
2985  // ---------------
2986  // | |
2987  // * *
2988  // | |
2989  // ---------------
2990  // If the wire positions of fromTp and toTp are the same, a different region is checked as shown here
2991  //
2992  // -----------
2993  // | |
2994  // | * |
2995  // | |
2996  // -----------
2997 
2998  std::vector<int> tmp;
2999  if (fromTp.Pos[0] < -0.4 || toTp.Pos[0] < -0.4) return tmp;
3000 
3001  TrajPoint tp;
3002  // Make the tp so that stepping is positive
3003  unsigned int firstWire, lastWire;
3004  if (toTp.Pos[0] > fromTp.Pos[0]) {
3005  if (!MakeBareTrajPoint(slc, fromTp, toTp, tp)) return tmp;
3006  firstWire = std::nearbyint(fromTp.Pos[0]);
3007  lastWire = std::nearbyint(toTp.Pos[0]);
3008  }
3009  else if (toTp.Pos[0] < fromTp.Pos[0]) {
3010  if (!MakeBareTrajPoint(slc, toTp, fromTp, tp)) return tmp;
3011  firstWire = std::nearbyint(toTp.Pos[0]);
3012  lastWire = std::nearbyint(fromTp.Pos[0]);
3013  }
3014  else {
3015  tp.Pos = fromTp.Pos;
3016  float tmp = fromTp.Pos[0] - maxDelta;
3017  if (tmp < 0) tmp = 0;
3018  firstWire = std::nearbyint(tmp);
3019  tmp = fromTp.Pos[0] + maxDelta;
3020  lastWire = std::nearbyint(tmp);
3021  }
3022 
3023  unsigned short plane = DecodeCTP(tp.CTP).Plane;
3024 
3025  if (firstWire < slc.firstWire[plane]) firstWire = slc.firstWire[plane];
3026  if (firstWire > slc.lastWire[plane] - 1) return tmp;
3027  if (lastWire < slc.firstWire[plane]) return tmp;
3028  if (lastWire > slc.lastWire[plane] - 1) lastWire = slc.lastWire[plane] - 1;
3029 
3030  for (unsigned int wire = firstWire; wire <= lastWire; ++wire) {
3031  if (slc.wireHitRange[plane][wire].first == UINT_MAX) continue;
3032  MoveTPToWire(tp, (float)wire);
3033  // Find the tick range at this position
3034  float minTick = (tp.Pos[1] - maxDelta) / tcc.unitsPerTick;
3035  float maxTick = (tp.Pos[1] + maxDelta) / tcc.unitsPerTick;
3036  unsigned int firstHit = slc.wireHitRange[plane][wire].first;
3037  unsigned int lastHit = slc.wireHitRange[plane][wire].second;
3038  for (unsigned int iht = firstHit; iht <= lastHit; ++iht) {
3039  if (slc.slHits[iht].InTraj <= 0) continue;
3040  if ((unsigned int)slc.slHits[iht].InTraj > slc.tjs.size()) continue;
3041  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
3042  if (hit.PeakTime() < minTick) continue;
3043  // Hits are sorted by increasing time so we can break when maxTick is reached
3044  if (hit.PeakTime() > maxTick) break;
3045  if (std::find(tmp.begin(), tmp.end(), slc.slHits[iht].InTraj) != tmp.end()) continue;
3046  tmp.push_back(slc.slHits[iht].InTraj);
3047  } // iht
3048  } // wire
3049 
3050  return tmp;
3051 
3052  } // FindCloseTjs
then if[["$THISISATEST"==1]]
Definition: neoSmazza.sh:95
TCConfig tcc
Definition: DataStructs.cxx:9
process_name hit
Definition: cheaterreco.fcl:51
bool MakeBareTrajPoint(const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:4110
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2831
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 797 of file TCVertex.cxx.

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

Definition at line 604 of file TCVertex.cxx.

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

Definition at line 3380 of file TCShower.cxx.

3381  {
3382  // Find Tjs that are near the shower but are not included in it
3383  ss.NearTjIDs.clear();
3384 
3385  // check for a valid envelope
3386  if (ss.Envelope.empty()) return;
3387  auto& stj = slc.tjs[ss.ShowerTjID - 1];
3388 
3389  std::string fcnLabel = inFcnLabel + ".FNTj";
3390 
3391  std::vector<int> ntj;
3392 
3393  // set max distance of closest approach ~ 5 radiation lengths ~200 WSE
3394  constexpr float fiveRadLen = 200;
3395 
3396  // look for vertices inside the envelope
3397  for (auto vx : slc.vtxs) {
3398  if (vx.CTP != ss.CTP) continue;
3399  if (vx.ID == 0) continue;
3400  if (!PointInsideEnvelope(vx.Pos, ss.Envelope)) continue;
3401  auto vxTjIDs = GetAssns(slc, "2V", vx.ID, "T");
3402  for (auto tjID : vxTjIDs) {
3403  // ignore those that are in the shower
3404  if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tjID) != ss.TjIDs.end()) continue;
3405  // or already in the list
3406  if (std::find(ntj.begin(), ntj.end(), tjID) != ntj.end()) continue;
3407  ntj.push_back(tjID);
3408  } // tjID
3409  } // vx
3410 
3411  // Check for tj points inside the envelope
3412  for (auto& tj : slc.tjs) {
3413  if (tj.CTP != ss.CTP) continue;
3414  if (tj.AlgMod[kKilled]) continue;
3415  // not a showerTj
3416  if (tj.AlgMod[kShowerTj]) continue;
3417  // make sure it's not in the shower
3418  if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tj.ID) != ss.TjIDs.end()) continue;
3419  // or already in the list
3420  if (std::find(ntj.begin(), ntj.end(), tj.ID) != ntj.end()) continue;
3421  // check proximity of long high MCSMom Tjs to the shower center
3422  if (tj.Pts.size() > 40 && tj.MCSMom > 200) {
3423  float delta = PointTrajDOCA(slc, stj.Pts[1].Pos[0], stj.Pts[1].Pos[1], tj.Pts[tj.EndPt[0]]);
3424  // TODO: This could be done much better
3425  if (delta < 20) {
3426  float doca = fiveRadLen;
3427  unsigned short spt = 0, ipt = 0;
3428  TrajTrajDOCA(slc, stj, tj, spt, ipt, doca);
3429  if (doca < fiveRadLen) {
3430  ntj.push_back(tj.ID);
3431  continue;
3432  }
3433  }
3434  } // long hi-MCSMom tj
3435  // don't need to check every point. Every third should be enough
3436  bool isInside = false;
3437  for (unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1]; ipt += 3) {
3438  if (PointInsideEnvelope(tj.Pts[ipt].Pos, ss.Envelope)) {
3439  isInside = true;
3440  break;
3441  }
3442  } // ipt
3443  // check the last point which was probably missed above
3444  if (!isInside) {
3445  unsigned short ipt = tj.EndPt[1];
3446  isInside = PointInsideEnvelope(tj.Pts[ipt].Pos, ss.Envelope);
3447  }
3448  if (isInside) ntj.push_back(tj.ID);
3449  } // tj
3450  if (ntj.size() > 1) std::sort(ntj.begin(), ntj.end());
3451  if (prt)
3452  mf::LogVerbatim("TC") << fcnLabel << " Found " << ntj.size() << " Tjs near ss.ID " << ss.ID;
3453  ss.NearTjIDs = ntj;
3454 
3455  } // FindNearbyTjs
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4849
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2572
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:3323
bool TrajTrajDOCA(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2460
bool tca::FindParent ( detinfo::DetectorPropertiesData const &  detProp,
std::string  inFcnLabel,
TCSlice &  slc,
ShowerStruct3D &  ss3,
bool  prt 
)

Definition at line 1577 of file TCShower.cxx.

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

Definition at line 191 of file PFPUtils.cxx.

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

Definition at line 289 of file TCShower.cxx.

290  {
291  // Find 2D showers using 3D-matched trajectories. This returns true if showers were found
292  // which requires re-doing the 3D trajectory match
293 
294  bool reconstruct = (tcc.showerTag[0] == 2) || (tcc.showerTag[0] == 4);
295  if (!reconstruct) return false;
296 
297  bool prt2S = (tcc.dbgSlc && tcc.dbg2S);
298  bool prt3S = (tcc.dbgSlc && tcc.dbg3S);
299 
300  std::string fcnLabel = "FS";
301 
302  geo::TPCGeo const& TPC = tcc.geom->TPC(slc.TPCID);
303  // check for already-existing showers
304  for (unsigned short plane = 0; plane < TPC.Nplanes(); ++plane) {
305  CTP_t inCTP = EncodeCTP(slc.TPCID.Cryostat, slc.TPCID.TPC, plane);
306  for (auto& ss : slc.cots)
307  if (ss.CTP == inCTP) return false;
308  }
309 
310  if (prt2S) {
311  PrintPFPs("FSi", slc);
312  PrintAllTraj(detProp, "FSi", slc, USHRT_MAX, 0);
313  }
314 
315  // lists of Tj IDs in plane, (list1, list2, list3, ...)
316  std::vector<std::vector<std::vector<int>>> bigList(slc.nPlanes);
317  for (unsigned short plane = 0; plane < TPC.Nplanes(); ++plane) {
318  std::vector<std::vector<int>> tjList;
319  // Make lists of lists of ShowerLike tjs that will become showers
320  // FindCots(fcnLabel, slc, inCTP, tjList, prt2S);
321  SaveTjInfo(slc, tjList, "TJL");
322  if (tjList.empty()) continue;
323  bigList[plane] = tjList;
324  } // plane
325  unsigned short nPlanesWithShowers = 0;
326  for (unsigned short plane = 0; plane < TPC.Nplanes(); ++plane)
327  if (!bigList.empty()) ++nPlanesWithShowers;
328  if (nPlanesWithShowers < 2) return false;
329  for (unsigned short plane = 0; plane < TPC.Nplanes(); ++plane) {
330  CTP_t inCTP = EncodeCTP(slc.TPCID.Cryostat, slc.TPCID.TPC, plane);
331  // print detailed debug info for one plane
332  bool prtCTP = (prt2S && inCTP == debug.CTP);
333  // Create a shower for each one
334  for (auto& tjl : bigList[plane]) {
335  if (tjl.empty()) continue;
336  if (prtCTP) {
337  mf::LogVerbatim myprt("TC");
338  myprt << "Plane " << plane << " tjList";
339  for (auto& tjID : tjl)
340  myprt << " " << tjID;
341  }
342  auto ss = CreateSS(slc, tjl);
343  if (ss.ID == 0) continue;
344  if (!UpdateShower(fcnLabel, slc, ss, prtCTP)) continue;
345  SaveTjInfo(slc, ss, "DS");
346  FindNearbyTjs(fcnLabel, slc, ss, prtCTP);
347  // don't try to do anything else here until all of the showers are defined
348  if (!StoreShower(fcnLabel, slc, ss)) MakeShowerObsolete(fcnLabel, slc, ss, prtCTP);
349  } // tjl
350  ChkAssns(fcnLabel, slc);
351  // try to merge showers in this plane using the lists of nearby Tjs
352  if (inCTP == UINT_MAX) continue;
353  if (slc.cots.empty()) continue;
354  if (prtCTP) Print2DShowers("tjl", slc, inCTP, false);
355  MergeShowerChain(fcnLabel, slc, inCTP, prtCTP);
356  SaveAllCots(slc, inCTP, "MSC");
357  if (prtCTP) Print2DShowers("MSCo", slc, inCTP, false);
358  MergeOverlap(fcnLabel, slc, inCTP, prtCTP);
359  SaveAllCots(slc, inCTP, "MO");
360  if (prtCTP) Print2DShowers("MO", slc, inCTP, false);
361  MergeNearby2DShowers(fcnLabel, slc, inCTP, prtCTP);
362  SaveAllCots(slc, inCTP, "MSS");
363  // merge sub-showers with other showers
364  MergeSubShowers(fcnLabel, slc, inCTP, prtCTP);
365  // merge sub-showers with shower-like tjs
366  MergeSubShowersTj(fcnLabel, slc, inCTP, prtCTP);
367  SaveAllCots(slc, inCTP, "MNrby");
368  if (prtCTP) Print2DShowers("Nrby", slc, inCTP, false);
369  bool tryMerge = false;
370  for (unsigned short ii = 0; ii < slc.cots.size(); ++ii) {
371  auto& ss = slc.cots[ii];
372  if (ss.ID == 0) continue;
373  if (ss.CTP != inCTP) continue;
374  if (AddTjsInsideEnvelope(fcnLabel, slc, ss, prtCTP)) tryMerge = true;
375  if (tcc.modes[kSaveShowerTree]) SaveAllCots(slc, inCTP, "Merge");
376  }
377  if (tryMerge) MergeNearby2DShowers(fcnLabel, slc, inCTP, prtCTP);
378  SaveAllCots(slc, inCTP, "ATj2");
379  if (prtCTP) Print2DShowers("ATIE", slc, inCTP, false);
380  } // plane
381  if (slc.cots.empty()) return false;
382  if (prt3S) Print2DShowers("B4", slc, USHRT_MAX, false);
383  // Match in 3D, make 3D showers and define them
384  // Match2DShowers(fcnLabel, slc, prt3S);
385  SaveAllCots(slc, "M2DS");
386  // Reconcile pfp and shower assns before the Parent search
387  Reconcile3D(fcnLabel, slc, false, prt3S);
388  SaveAllCots(slc, "R3D");
389  for (auto& ss3 : slc.showers) {
390  if (ss3.ID == 0) continue;
391  FindParent(detProp, fcnLabel, slc, ss3, prt3S);
392  } // ss3
393  // Reconcile pfp and shower assns again
394  Reconcile3D(fcnLabel, slc, true, prt3S);
395  if (prt3S) Print2DShowers("M2DS", slc, USHRT_MAX, false);
396  SaveAllCots(slc, "FP");
397 
398  // kill low energy 3D showers
399  for (auto& ss3 : slc.showers) {
400  if (ss3.ID == 0) continue;
401  bool killMe = (ShowerEnergy(ss3) < tcc.showerTag[3]);
402  if (killMe) MakeShowerObsolete(fcnLabel, slc, ss3, prt3S);
403  } // ss3
404 
405  // kill 2D showers that are either below threshold or have only one tj
406  for (auto& ss : slc.cots) {
407  if (ss.ID == 0) continue;
408  if (ss.SS3ID > 0) continue;
409  bool killMe = (ss.TjIDs.size() == 1 || ss.Energy < tcc.showerTag[3]);
410  // too small aspect ratio -> something track-like with some shower-like fuzz
411  if (ss.AspectRatio < tcc.showerTag[10]) killMe = true;
412  if (killMe) MakeShowerObsolete(fcnLabel, slc, ss, prt3S);
413  } // ss
414 
415  unsigned short nNewShowers = 0;
416  for (auto& ss : slc.cots) {
417  if (ss.ID == 0) continue;
418  if (ss.TjIDs.empty()) continue;
419  SaveTjInfo(slc, ss, "Done");
420  ++nNewShowers;
421  } // ss
422 
423  return (nNewShowers > 0);
424 
425  } // FindShowers3D
void MergeNearby2DShowers(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
Definition: TCShower.cxx:2310
bool FindParent(detinfo::DetectorPropertiesData const &detProp, std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1577
void MergeShowerChain(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
Definition: TCShower.cxx:2524
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4157
TCConfig tcc
Definition: DataStructs.cxx:9
unsigned int Nplanes() const
Number of planes in this tpc.
Definition: TPCGeo.h:165
Geometry information for a single TPC.
Definition: TPCGeo.h:38
void SaveAllCots(TCSlice &slc, const CTP_t &inCTP, std::string someText)
Definition: TCShTree.cxx:174
double ShowerEnergy(const ShowerStruct3D &ss3)
Definition: TCShower.cxx:3954
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:590
void PrintPFPs(std::string someText, TCSlice &slc)
Definition: Utils.cxx:6444
BEGIN_PROLOG TPC
ShowerStruct CreateSS(TCSlice &slc, const std::vector< int > &tjl)
Definition: TCShower.cxx:4110
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:558
save shower tree
Definition: DataStructs.h:540
void MergeSubShowersTj(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
Definition: TCShower.cxx:2655
void PrintAllTraj(detinfo::DetectorPropertiesData const &detProp, std::string someText, TCSlice &slc, unsigned short itj, unsigned short ipt, bool prtVtx)
Definition: Utils.cxx:5952
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:3380
void MergeOverlap(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
Definition: TCShower.cxx:2403
const geo::GeometryCore * geom
Definition: DataStructs.h:576
bool AddTjsInsideEnvelope(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3551
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:607
unsigned int CTP_t
Definition: DataStructs.h:47
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:52
void MergeSubShowers(std::string inFcnLabel, TCSlice &slc, const CTP_t &inCTP, bool prt)
Definition: TCShower.cxx:2767
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:913
void Print2DShowers(std::string someText, TCSlice &slc, CTP_t inCTP, bool printKilledShowers)
Definition: TCShower.cxx:4254
auto const detProp
void MakeShowerObsolete(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:3194
bool StoreShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3)
Definition: TCShower.cxx:3991
bool Reconcile3D(std::string inFcnLabel, TCSlice &slc, bool parentSearchDone, bool prt)
Definition: TCShower.cxx:429
bool tca::FindShowerStart ( detinfo::DetectorPropertiesData const &  detProp,
TCSlice &  slc,
ShowerStruct3D &  ss3,
bool  prt 
)

Definition at line 62 of file TCShower.cxx.

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

Definition at line 3704 of file TCShower.cxx.

3705  {
3706  // Finds the charge at the start of a shower and puts it in AveChg of the first
3707  // point of the shower Tj. This is only done when there is no parent.
3708  if (cotID > (int)slc.cots.size()) return;
3709 
3710  ShowerStruct& ss = slc.cots[cotID - 1];
3711  if (ss.ID == 0) return;
3712  if (ss.TjIDs.empty()) return;
3713  if (ss.ShowerTjID == 0) return;
3714  if (ss.ParentID > 0) return;
3715  auto& stp0 = slc.tjs[ss.ShowerTjID - 1].Pts[0];
3716 
3717  std::string fcnLabel = inFcnLabel + ".FSC";
3718 
3719  stp0.AveChg = 0;
3720 
3721  if (ss.AspectRatio > tcc.showerTag[10] || ss.DirectionFOM > tcc.showerTag[9]) {
3722  if (prt)
3723  mf::LogVerbatim("TC") << fcnLabel << " Not possible due to poor AspectRatio "
3724  << ss.AspectRatio << " or ss.DirectionFOM " << ss.DirectionFOM;
3725  return;
3726  }
3727 
3728  // Create and fill a vector of the charge at the beginning of the shower in 1 WSE bins
3729  auto schg = StartChgVec(slc, cotID, prt);
3730  if (schg.empty()) return;
3731 
3732  // Look for two consecutive charge entries. Use the second one
3733  // for the initial guess at the charge
3734  unsigned short startPt = USHRT_MAX;
3735  float chg = 0;
3736  for (unsigned short ii = 0; ii < schg.size() - 1; ++ii) {
3737  if (schg[ii] > 0 && schg[ii + 1] > 0) {
3738  startPt = ii + 1;
3739  chg = schg[ii + 1];
3740  break;
3741  }
3742  }
3743  if (startPt == USHRT_MAX) return;
3744 
3745  // get an initial average and rms using all the points
3746  float ave = 0;
3747  float rms = 0;
3748  float cnt = 0;
3749  for (unsigned short ii = startPt; ii < schg.size() - 1; ++ii) {
3750  ave += schg[ii];
3751  rms += schg[ii] * schg[ii];
3752  ++cnt;
3753  } // ii
3754  ave /= cnt;
3755  rms = rms - cnt * ave * ave;
3756  if (rms < 0) return;
3757  rms = sqrt(rms / (cnt - 1));
3758 
3759  if (prt) {
3760  mf::LogVerbatim myprt("TC");
3761  myprt << fcnLabel << " schg:";
3762  for (unsigned short ii = 0; ii < 20; ++ii)
3763  myprt << " " << (int)schg[ii];
3764  myprt << "\n First guess at the charge " << (int)chg << " average charge of all bins "
3765  << (int)ave << " rms " << (int)rms;
3766  }
3767 
3768  // initial guess at the charge rms
3769  rms = 0.8 * chg;
3770 
3771  unsigned short nBinsAverage = 5;
3772  double maxChg = 2 * chg;
3773  for (unsigned short nit = 0; nit < 2; ++nit) {
3774  double sum = 0;
3775  double sum2 = 0;
3776  double cnt = 0;
3777  for (unsigned short ii = startPt; ii < schg.size() - 1; ++ii) {
3778  // break if we find 2 consecutive high charge points
3779  if (schg[ii] > maxChg && schg[ii + 1] > maxChg) break;
3780  // or two zeros
3781  if (schg[ii] == 0 && schg[ii + 1] == 0) break;
3782  if (schg[ii] > maxChg) continue;
3783  sum += schg[ii];
3784  sum2 += schg[ii] * schg[ii];
3785  ++cnt;
3786  if (cnt == nBinsAverage) break;
3787  } // ii
3788  // check for a failure
3789  if (cnt < 3) {
3790  if (prt)
3791  mf::LogVerbatim("TC") << fcnLabel << " nit " << nit << " cnt " << cnt
3792  << " is too low. sum " << (int)sum << " maxChg " << (int)maxChg;
3793  // try to recover. Pick the next point
3794  ++startPt;
3795  chg = schg[startPt];
3796  maxChg = 2 * chg;
3797  continue;
3798  }
3799  // convert sum to the average charge
3800  chg = sum / cnt;
3801  double arg = sum2 - cnt * chg * chg;
3802  if (arg < 0) break;
3803  rms = sqrt(arg / (cnt - 1));
3804  // don't allow the rms to get crazy
3805  double maxrms = 0.5 * sum;
3806  if (rms > maxrms) rms = maxrms;
3807  maxChg = chg + 2 * rms;
3808  if (prt)
3809  mf::LogVerbatim("TC") << fcnLabel << " nit " << nit << " cnt " << cnt << " chg " << (int)chg
3810  << " rms " << (int)rms << " maxChg " << (int)maxChg
3811  << " nBinsAverage " << nBinsAverage;
3812  nBinsAverage = 20;
3813  } // nit
3814 
3815  stp0.AveChg = chg;
3816 
3817  if (prt)
3818  mf::LogVerbatim("TC") << fcnLabel << " 2S" << cotID << " Starting charge " << (int)stp0.AveChg
3819  << " startPt " << startPt;
3820 
3821  } // FindStartChg
then if[["$THISISATEST"==1]]
Definition: neoSmazza.sh:95
see a below echo S(symbol in a section other than those above)
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:558
for($it=0;$it< $RaceTrack_number;$it++)
std::vector< float > StartChgVec(TCSlice &slc, int cotID, bool prt)
Definition: TCShower.cxx:3825
shift break
Definition: just_cmake.sh:60
void tca::FindUseHits ( TCSlice &  slc,
Trajectory &  tj,
unsigned short  ipt,
float  maxDelta,
bool  useChg 
)

Definition at line 1757 of file StepUtils.cxx.

1758  {
1759  // Hits have been associated with trajectory point ipt but none are used. Here we will
1760  // decide which hits to use.
1761 
1762  if(ipt > tj.Pts.size() - 1) return;
1763  TrajPoint& tp = tj.Pts[ipt];
1764 
1765  if(tp.Hits.empty()) return;
1766  // don't check charge when starting out
1767  if(ipt < 5) useChg = false;
1768  float chgPullCut = 1000;
1769  if(useChg) chgPullCut = tcc.chargeCuts[0];
1770  // open it up for RevProp, since we might be following a stopping track
1771  if(tj.AlgMod[kRvPrp]) chgPullCut *= 2;
1772  if(tj.MCSMom < 30) chgPullCut *= 2;
1773 
1774  bool ignoreLongPulseHits = false;
1775  unsigned short npts = tj.EndPt[1] - tj.EndPt[0] + 1;
1776  if(npts < 10 || tj.AlgMod[kRvPrp]) ignoreLongPulseHits = true;
1777  float expectedHitsRMS = ExpectedHitsRMS(slc, tp);
1778  if(tcc.dbgStp) {
1779  mf::LogVerbatim("TC")<<"FUH: maxDelta "<<maxDelta<<" useChg requested "<<useChg<<" Norm AveChg "<<(int)tp.AveChg<<" tj.ChgRMS "<<std::setprecision(2)<<tj.ChgRMS<<" chgPullCut "<<chgPullCut<<" TPHitsRMS "<<(int)TPHitsRMSTick(slc, tp, kUnusedHits)<<" ExpectedHitsRMS "<<(int)expectedHitsRMS<<" AngCode "<<tp.AngleCode;
1780  }
1781 
1782  // inverse of the path length for normalizing hit charge to 1 WSE unit
1783  float pathInv = std::abs(tp.Dir[0]);
1784  if(pathInv < 0.05) pathInv = 0.05;
1785 
1786  // Find the hit that has the smallest delta and the number of available hits
1787  tp.Delta = maxDelta;
1788  float delta;
1789  unsigned short imbest = USHRT_MAX;
1790  std::vector<float> deltas(tp.Hits.size(), 100);
1791  // keep track of the best delta - even if it is used
1792  float bestDelta = maxDelta;
1793  unsigned short nAvailable = 0;
1794  unsigned short firstAvailable = USHRT_MAX;
1795  unsigned short lastAvailable = USHRT_MAX;
1796  unsigned short firstUsed = USHRT_MAX;
1797  unsigned short imBadRecoHit = USHRT_MAX;
1798  bool bestHitLongPulse = false;
1799  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1800  tp.UseHit[ii] = false;
1801  unsigned int iht = tp.Hits[ii];
1802  if(iht >= slc.slHits.size()) continue;
1803  if(slc.slHits[iht].allHitsIndex >= (*evt.allHits).size()) continue;
1804  delta = PointTrajDOCA(slc, iht, tp);
1805  if(delta < bestDelta) bestDelta = delta;
1806  if(slc.slHits[iht].InTraj > 0) {
1807  if(firstUsed == USHRT_MAX) firstUsed = ii;
1808  continue;
1809  }
1810  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1811  if(ignoreLongPulseHits && LongPulseHit(hit)) continue;
1812  if(hit.GoodnessOfFit() < 0 || hit.GoodnessOfFit() > 100) imBadRecoHit = ii;
1813  if(firstAvailable == USHRT_MAX) firstAvailable = ii;
1814  lastAvailable = ii;
1815  ++nAvailable;
1816  if(tcc.dbgStp) {
1817  if(useChg) {
1818  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" "<<ii<<" "<<PrintHit(slc.slHits[iht])<<" delta "<<delta<<" Norm Chg "<<(int)(hit.Integral() * pathInv);
1819  } else {
1820  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" "<<ii<<" "<<PrintHit(slc.slHits[iht])<<" delta "<<delta;
1821  }
1822  } // tcc.dbgStp
1823  deltas[ii] = delta;
1824  if(delta < tp.Delta) {
1825  tp.Delta = delta;
1826  imbest = ii;
1827  bestHitLongPulse = LongPulseHit(hit);
1828  }
1829  } // ii
1830 
1831  float chgWght = 0.5;
1832 
1833  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" firstAvailable "<<firstAvailable<<" lastAvailable "<<lastAvailable<<" firstUsed "<<firstUsed<<" imbest "<<imbest<<" single hit. tp.Delta "<<std::setprecision(2)<<tp.Delta<<" bestDelta "<<bestDelta<<" path length "<<1 / pathInv<<" imBadRecoHit "<<imBadRecoHit;
1834  if(imbest == USHRT_MAX || nAvailable == 0) return;
1835  unsigned int bestDeltaHit = tp.Hits[imbest];
1836 
1837  // just use the best hit if we are tracking a high energy electron and the best hit is a long pulse hit
1838  if(tj.Strategy[kStiffEl] && bestHitLongPulse) {
1839  tp.UseHit[imbest] = true;
1840  slc.slHits[bestDeltaHit].InTraj = tj.ID;
1841  return;
1842  }
1843 
1844  // Don't try to use a multiplet if a hit in the middle is in a different trajectory
1845  if(tp.Hits.size() > 2 && nAvailable > 1 && firstUsed != USHRT_MAX && firstAvailable < firstUsed && lastAvailable > firstUsed) {
1846  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" A hit in the middle of the multiplet is used. Use only the best hit";
1847  tp.UseHit[imbest] = true;
1848  slc.slHits[bestDeltaHit].InTraj = tj.ID;
1849  return;
1850  } // Used hit inside multiplet
1851 
1852  if(tp.AngleCode == 1) {
1853  // Get the hits that are in the same multiplet as bestDeltaHit
1854  std::vector<unsigned int> hitsInMultiplet;
1855  GetHitMultiplet(slc, bestDeltaHit, hitsInMultiplet, false);
1856  if(tcc.dbgStp) {
1857  mf::LogVerbatim myprt("TC");
1858  myprt<<" bestDeltaHit "<<PrintHit(slc.slHits[bestDeltaHit]);
1859  myprt<<" in multiplet:";
1860  for(auto& iht : hitsInMultiplet) myprt<<" "<<PrintHit(slc.slHits[iht]);
1861  }
1862  // Consider the case where a bad reco hit might be better. It is probably wider and
1863  // has more charge
1864  if(imBadRecoHit != USHRT_MAX) {
1865  unsigned int iht = tp.Hits[imBadRecoHit];
1866  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1867  if(hit.RMS() > HitsRMSTick(slc, hitsInMultiplet, kUnusedHits)) {
1868  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Using imBadRecoHit "<<PrintHit(slc.slHits[iht]);
1869  tp.UseHit[imBadRecoHit] = true;
1870  slc.slHits[iht].InTraj = tj.ID;
1871  return;
1872  }
1873  } // bad reco hit
1874  // Use the hits in the multiplet instead
1875  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1876  unsigned int iht = tp.Hits[ii];
1877  if(slc.slHits[iht].InTraj > 0) continue;
1878  if(std::find(hitsInMultiplet.begin(), hitsInMultiplet.end(), iht) == hitsInMultiplet.end()) continue;
1879  tp.UseHit[ii] = true;
1880  slc.slHits[iht].InTraj = tj.ID;
1881  } // ii
1882  return;
1883  } // isLA
1884 
1885  // don't use the best UNUSED hit if the best delta is for a USED hit and it is much better
1886  // TY: ignore for RevProp
1887  if(bestDelta < 0.5 * tp.Delta && !tj.AlgMod[kRvPrp]) return;
1888 
1889  if(!useChg || (useChg && (tj.AveChg <= 0 || tj.ChgRMS <= 0))) {
1890  // necessary quantities aren't available for more careful checking
1891  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" tj.AveChg "<<tj.AveChg<<" or tj.ChgRMS "<<tj.ChgRMS<<". Use the best hit";
1892  tp.UseHit[imbest] = true;
1893  slc.slHits[bestDeltaHit].InTraj = tj.ID;
1894  return;
1895  }
1896 
1897  // Don't try to get fancy if we are tracking a stiff tj
1898  if(tj.PDGCode == 13 && bestDelta < 0.5) {
1899  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Tracking muon. Use the best hit";
1900  tp.UseHit[imbest] = true;
1901  slc.slHits[bestDeltaHit].InTraj = tj.ID;
1902  return;
1903  }
1904 
1905  // The best hit is the only one available or this is a small angle trajectory
1906  if(nAvailable == 1 || tp.AngleCode == 0) {
1907  auto& hit = (*evt.allHits)[slc.slHits[bestDeltaHit].allHitsIndex];
1908  float aveChg = tp.AveChg;
1909  if(aveChg <= 0) aveChg = tj.AveChg;
1910  if(aveChg <= 0) aveChg = hit.Integral();
1911  float chgRMS = tj.ChgRMS;
1912  if(chgRMS < 0.2) chgRMS = 0.2;
1913  float bestDeltaHitChgPull = std::abs(hit.Integral() * pathInv / aveChg - 1) / chgRMS;
1914  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" bestDeltaHitChgPull "<<bestDeltaHitChgPull<<" chgPullCut "<<chgPullCut;
1915  if(bestDeltaHitChgPull < chgPullCut || tp.Delta < 0.1) {
1916  tp.UseHit[imbest] = true;
1917  slc.slHits[bestDeltaHit].InTraj = tj.ID;
1918  } // good charge or very good delta
1919  return;
1920  } // bestDeltaHitMultiplicity == 1
1921 
1922  // Find the expected width for the angle of this TP (ticks)
1923  float expectedWidth = ExpectedHitsRMS(slc, tp);
1924 
1925  // Handle two available hits
1926  if(nAvailable == 2) {
1927  // See if these two are in the same multiplet and both are available
1928  std::vector<unsigned int> tHits;
1929  GetHitMultiplet(slc, bestDeltaHit, tHits, false);
1930  // ombest is the index of the other hit in tp.Hits that is in the same multiplet as bestDeltaHit
1931  // if we find it
1932  unsigned short ombest = USHRT_MAX;
1933  unsigned int otherHit = INT_MAX;
1934  if(tHits.size() == 2) {
1935  unsigned short localIndex = 0;
1936  if(tHits[0] == bestDeltaHit) localIndex = 1;
1937  otherHit = tHits[1 - localIndex];
1938  // get the index of this hit in tp.Hits
1939  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1940  if(slc.slHits[tp.Hits[ii]].InTraj > 0) continue;
1941  if(tp.Hits[ii] == otherHit) {
1942  ombest = ii;
1943  break;
1944  }
1945  } // ii
1946  } // tHits.size() == 2
1947  if(tcc.dbgStp) {
1948  mf::LogVerbatim("TC")<<" Doublet: imbest "<<imbest<<" ombest "<<ombest;
1949  }
1950  // The other hit exists in the tp and it is available
1951  if(ombest < tp.Hits.size()) {
1952  // compare the best delta hit and the other hit separately and the doublet as a merged pair
1953  float bestHitDeltaErr = std::abs(tp.Dir[1]) * 0.17 + std::abs(tp.Dir[0]) * HitTimeErr(slc, bestDeltaHit);
1954  // Construct a FOM starting with the delta pull
1955  float bestDeltaHitFOM = deltas[imbest] / bestHitDeltaErr;
1956  if(bestDeltaHitFOM < 0.5) bestDeltaHitFOM = 0.5;
1957  // multiply by the charge pull if it is significant
1958  auto& hit = (*evt.allHits)[slc.slHits[bestDeltaHit].allHitsIndex];
1959  float bestDeltaHitChgPull = std::abs(hit.Integral() * pathInv / tp.AveChg - 1) / tj.ChgRMS;
1960  if(bestDeltaHitChgPull > 1) bestDeltaHitFOM *= chgWght * bestDeltaHitChgPull;
1961  // scale by the ratio
1962  float rmsRat = hit.RMS() / expectedWidth;
1963  if(rmsRat < 1) rmsRat = 1 / rmsRat;
1964  bestDeltaHitFOM *= rmsRat;
1965  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" bestDeltaHit FOM "<<deltas[imbest]/bestHitDeltaErr<<" bestDeltaHitChgPull "<<bestDeltaHitChgPull<<" rmsRat "<<rmsRat<<" bestDeltaHitFOM "<<bestDeltaHitFOM;
1966  // Now do the same for the other hit
1967  float otherHitDeltaErr = std::abs(tp.Dir[1]) * 0.17 + std::abs(tp.Dir[0]) * HitTimeErr(slc, otherHit);
1968  float otherHitFOM = deltas[ombest] / otherHitDeltaErr;
1969  if(otherHitFOM < 0.5) otherHitFOM = 0.5;
1970  auto& ohit = (*evt.allHits)[slc.slHits[otherHit].allHitsIndex];
1971  float otherHitChgPull = std::abs(ohit.Integral() * pathInv / tp.AveChg - 1) / tj.ChgRMS;
1972  if(otherHitChgPull > 1) otherHitFOM *= chgWght * otherHitChgPull;
1973  rmsRat = ohit.RMS() / expectedWidth;
1974  if(rmsRat < 1) rmsRat = 1 / rmsRat;
1975  otherHitFOM *= rmsRat;
1976  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" otherHit FOM "<<deltas[ombest]/otherHitDeltaErr<<" otherHitChgPull "<<otherHitChgPull<<" rmsRat "<<rmsRat<<" otherHitFOM "<<otherHitFOM;
1977  // And for the doublet
1978  float doubletChg = hit.Integral() + ohit.Integral();
1979  float doubletTime = (hit.Integral() * hit.PeakTime() + ohit.Integral() * ohit.PeakTime()) / doubletChg;
1980  doubletChg *= pathInv;
1981  doubletTime *= tcc.unitsPerTick;
1982  float doubletWidthTick = TPHitsRMSTick(slc, tp, kUnusedHits);
1983  float doubletRMSTimeErr = doubletWidthTick * tcc.unitsPerTick;
1984  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" doublet Chg "<<doubletChg<<" doubletTime "<<doubletTime<<" doubletRMSTimeErr "<<doubletRMSTimeErr;
1985  float doubletFOM = PointTrajDOCA(slc, tp.Pos[0], doubletTime, tp) / doubletRMSTimeErr;
1986  if(doubletFOM < 0.5) doubletFOM = 0.5;
1987  float doubletChgPull = std::abs(doubletChg * pathInv / tp.AveChg - 1) / tj.ChgRMS;
1988  if(doubletChgPull > 1) doubletFOM *= chgWght * doubletChgPull;
1989  rmsRat = doubletWidthTick / expectedWidth;
1990  if(rmsRat < 1) rmsRat = 1 / rmsRat;
1991  doubletFOM *= rmsRat;
1992  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" doublet FOM "<<PointTrajDOCA(slc, tp.Pos[0], doubletTime, tp)/doubletRMSTimeErr<<" doubletChgPull "<<doubletChgPull<<" rmsRat "<<rmsRat<<" doubletFOM "<<doubletFOM;
1993  if(doubletFOM < bestDeltaHitFOM && doubletFOM < otherHitFOM) {
1994  tp.UseHit[imbest] = true;
1995  slc.slHits[bestDeltaHit].InTraj = tj.ID;
1996  tp.UseHit[ombest] = true;
1997  slc.slHits[otherHit].InTraj = tj.ID;
1998  } else {
1999  // the doublet is not the best
2000  if(bestDeltaHitFOM < otherHitFOM) {
2001  tp.UseHit[imbest] = true;
2002  slc.slHits[bestDeltaHit].InTraj = tj.ID;
2003  } else {
2004  tp.UseHit[ombest] = true;
2005  slc.slHits[otherHit].InTraj = tj.ID;
2006  } // otherHit is the best
2007  } // doublet is not the best
2008  } else {
2009  // the other hit isn't available. Just use the singlet
2010  tp.UseHit[imbest] = true;
2011  slc.slHits[bestDeltaHit].InTraj = tj.ID;
2012  }
2013  return;
2014  } // nAvailable == 2
2015  float hitsWidth = TPHitsRMSTick(slc, tp, kUnusedHits);
2016  float maxTick = tp.Pos[1] / tcc.unitsPerTick + 0.6 * expectedWidth;
2017  float minTick = tp.Pos[1] / tcc.unitsPerTick - 0.6 * expectedWidth;
2018  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Multiplet: hitsWidth "<<hitsWidth<<" expectedWidth "<<expectedWidth<<" tick range "<<(int)minTick<<" "<<(int)maxTick;
2019  // use all of the hits in the tick window
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  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2024  if(hit.PeakTime() < minTick) continue;
2025  if(hit.PeakTime() > maxTick) continue;
2026  tp.UseHit[ii] = true;
2027  slc.slHits[iht].InTraj = tj.ID;
2028  }
2029 
2030  } // FindUseHits
TCConfig tcc
Definition: DataStructs.cxx:9
float HitTimeErr(const TCSlice &slc, unsigned int iht)
Definition: StepUtils.cxx:1544
float ExpectedHitsRMS(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:1947
std::size_t size(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:561
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2572
process_name hit
Definition: cheaterreco.fcl:51
bool LongPulseHit(const recob::Hit &hit)
Definition: Utils.cxx:4452
T abs(T value)
float HitsRMSTick(const TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
Definition: Utils.cxx:4246
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
void GetHitMultiplet(const TCSlice &slc, unsigned int theHit, std::vector< unsigned int > &hitsInMultiplet, bool useLongPulseHits)
Definition: StepUtils.cxx:1415
for($it=0;$it< $RaceTrack_number;$it++)
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6516
std::vector< float > chargeCuts
Definition: DataStructs.h:562
art::PtrVector< recob::Hit > Hits
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
use the stiff electron strategy
Definition: DataStructs.h:501
TCEvent evt
Definition: DataStructs.cxx:8
float TPHitsRMSTick(const TCSlice &slc, const TrajPoint &tp, HitStatus_t hitRequest)
Definition: Utils.cxx:4209
void tca::Finish3DShowers ( TCSlice &  slc)

Definition at line 156 of file TCShower.cxx.

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

Definition at line 5129 of file Utils.cxx.

5135  {
5136  // Fit points to a 2D line.
5137  // Mode = 0: Initialize
5138  // Mode = 1: Accumulate
5139  // Mode = 2: Accumulate and store to calculate chiDOF
5140  // Mode = -1: Fit and put results in outVec and chiDOF
5141 
5142  static double sum, sumx, sumy, sumx2, sumy2, sumxy;
5143  static unsigned short cnt;
5144  static std::vector<Point2_t> fitPts;
5145  static std::vector<double> fitWghts;
5146 
5147  if (mode == 0) {
5148  // initialize
5149  cnt = 0;
5150  sum = 0.;
5151  sumx = 0.;
5152  sumy = 0.;
5153  sumx2 = 0.;
5154  sumy2 = 0.;
5155  sumxy = 0;
5156  fitPts.resize(0);
5157  fitWghts.resize(0);
5158  return true;
5159  } // mode == 0
5160 
5161  if (mode > 0) {
5162  if (inPtErr <= 0.) return false;
5163  ++cnt;
5164  double wght = 1 / (inPtErr * inPtErr);
5165  sum += wght;
5166  sumx += wght * inPt[0];
5167  sumx2 += wght * inPt[0] * inPt[0];
5168  sumy += wght * inPt[1];
5169  sumy2 += wght * inPt[1] * inPt[1];
5170  sumxy += wght * inPt[0] * inPt[1];
5171  if (mode == 1) return true;
5172  fitPts.push_back(inPt);
5173  fitWghts.push_back(wght);
5174  return true;
5175  } // Accumulate
5176 
5177  if (cnt < 2) return false;
5178  // do the fit
5179  double delta = sum * sumx2 - sumx * sumx;
5180  if (delta == 0.) return false;
5181  double A = (sumx2 * sumy - sumx * sumxy) / delta;
5182  double B = (sumxy * sum - sumx * sumy) / delta;
5183  outVec[0] = A;
5184  outVec[1] = B;
5185  chiDOF = 0;
5186  if (cnt == 2 || fitPts.empty()) return true;
5187 
5188  // calculate errors and chiDOF
5189  if (fitPts.size() != cnt) return false;
5190  double ndof = cnt - 2;
5191  double varnce =
5192  (sumy2 + A * A * sum + B * B * sumx2 - 2 * (A * sumy + B * sumxy - A * B * sumx)) / ndof;
5193  if (varnce > 0.) {
5194  outVecErr[0] = sqrt(varnce * sumx2 / delta);
5195  outVecErr[1] = sqrt(varnce * sum / delta);
5196  }
5197  else {
5198  outVecErr[0] = 0.;
5199  outVecErr[1] = 0.;
5200  }
5201  sum = 0.;
5202  // calculate chisq
5203  for (unsigned short ii = 0; ii < fitPts.size(); ++ii) {
5204  double arg = fitPts[ii][1] - A - B * fitPts[ii][0];
5205  sum += fitWghts[ii] * arg * arg;
5206  }
5207  chiDOF = sum / ndof;
5208  fitPts.resize(0);
5209  fitWghts.resize(0);
5210  return true;
5211 
5212  } // Fit2D
const char mode
Definition: noise_ana.cxx:20
float A
Definition: dedx.py:137
void tca::FitPar ( const TCSlice &  slc,
const Trajectory &  tj,
unsigned short  originPt,
unsigned short  npts,
short  fitDir,
ParFit &  pFit,
unsigned short  usePar 
)

Definition at line 1219 of file Utils.cxx.

1226  {
1227  // Fit a TP parameter, like Chg or Delta, to a line using the points starting at originPT.
1228  // Currently supported values of usePar are Chg (1) and Delta (2)
1229 
1230  pFit.ChiDOF = 999;
1231  pFit.AvePar = 0.;
1232  if (originPt > tj.Pts.size() - 1) return;
1233  if (fitDir != 1 && fitDir != -1) return;
1234  Point2_t inPt;
1235  Vector2_t outVec, outVecErr;
1236  float pErr, chiDOF;
1237  Fit2D(0, inPt, pErr, outVec, outVecErr, chiDOF);
1238  unsigned short cnt = 0;
1239  for (unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
1240  unsigned short ipt = originPt + ii * fitDir;
1241  if (ipt < tj.EndPt[0] || ipt > tj.EndPt[1]) break;
1242  auto& tp = tj.Pts[ipt];
1243  if (tp.Chg <= 0) continue;
1244  // Accumulate and save points
1245  inPt[0] = std::abs(tp.Pos[0] - tj.Pts[originPt].Pos[0]);
1246  float parVal = tp.Chg;
1247  // Assume errors are 10% for a charge fit
1248  pErr = 0.1 * parVal;
1249  if (usePar > 1) {
1250  parVal = tp.Delta;
1251  // use the TP hit position error for a Delta Fit
1252  pErr = sqrt(tp.HitPosErr2);
1253  }
1254  inPt[1] = parVal;
1255  pFit.AvePar += parVal;
1256  if (!Fit2D(2, inPt, pErr, outVec, outVecErr, chiDOF)) break;
1257  ++cnt;
1258  if (cnt == npts) break;
1259  } // ii
1260  if (cnt < npts) return;
1261  // do the fit and get the results
1262  if (!Fit2D(-1, inPt, pErr, outVec, outVecErr, chiDOF)) return;
1263  pFit.Pos = tj.Pts[originPt].Pos;
1264  pFit.Par0 = outVec[0];
1265  pFit.AvePar /= (float)cnt;
1266  pFit.ParErr = outVecErr[0];
1267  pFit.Pos = tj.Pts[originPt].Pos;
1268  pFit.ParSlp = outVec[1];
1269  pFit.ParSlpErr = outVecErr[1];
1270  pFit.ChiDOF = chiDOF;
1271  pFit.nPtsFit = cnt;
1272  } // FitPar
T abs(T value)
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:5129
std::array< double, 2 > Vector2_t
Definition: DataStructs.h:44
bool tca::FitSection ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
const TCSlice &  slc,
PFPStruct &  pfp,
unsigned short  sfIndex 
)

Definition at line 1414 of file PFPUtils.cxx.

1419  {
1420  // Fits the TP3D points in the selected section to a 3D line with the origin at the center of
1421  // the section
1422  if (pfp.TP3Ds.size() < 4) return false;
1423  if (sfIndex >= pfp.SectionFits.size()) return false;
1424  // don't fit a small angle PFP
1425  if(pfp.Flags[kSmallAngle]) return true;
1426 
1427  unsigned short fromPt = USHRT_MAX;
1428  unsigned short npts = 0;
1429  GetRange(pfp, sfIndex, fromPt, npts);
1430  if (fromPt == USHRT_MAX) return false;
1431  if (npts < 4) return false;
1432 
1433  // check for errors
1434  for (unsigned short ipt = fromPt; ipt < fromPt + npts; ++ipt) {
1435  auto& tp3d = pfp.TP3Ds[ipt];
1436  if (tp3d.SFIndex != sfIndex) return false;
1437  } // ipt
1438 
1439  // fit these points and update
1440  float chiDOF = 999;
1441  return FitTP3Ds(detProp, slc, pfp, fromPt, npts, sfIndex, chiDOF);
1442 
1443  } // FitSection
void GetRange(const PFPStruct &pfp, unsigned short sfIndex, unsigned short &fromPt, unsigned short &npts)
Definition: PFPUtils.cxx:1392
SectionFit FitTP3Ds(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const std::vector< TP3D > &tp3ds, unsigned short fromPt, short fitDir, unsigned short nPtsFit)
Definition: PFPUtils.cxx:1447
auto const detProp
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 1447 of file PFPUtils.cxx.

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

Definition at line 1587 of file PFPUtils.cxx.

1594  {
1595  // Fit points in the pfp.TP3Ds vector fromPt. This function
1596  // doesn't update the TP3Ds unless sfIndex refers to a valid SectionFit in the pfp.
1597  // No check is made to ensure that the TP3D SFIndex variable is compatible with sfIndex
1598 
1599  if (nPtsFit < 5) return false;
1600  if (fromPt + nPtsFit > pfp.TP3Ds.size()) return false;
1601 
1602  auto sf = FitTP3Ds(detProp, slc, pfp.TP3Ds, fromPt, 1, nPtsFit);
1603  if (sf.ChiDOF > 900) return false;
1604 
1605  // don't update the pfp?
1606  if (sfIndex >= pfp.SectionFits.size()) return true;
1607 
1608  // update the pfp Sectionfit
1609  pfp.SectionFits[sfIndex] = sf;
1610  // update the TP3Ds
1611  // project this 3D vector into a TP in every plane
1612  std::vector<TrajPoint> plnTP(slc.nPlanes);
1613  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
1614  CTP_t inCTP = EncodeCTP(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
1615  plnTP[plane] = MakeBareTP(detProp, slc, sf.Pos, sf.Dir, inCTP);
1616  } // plane
1617  Point3_t pos;
1618  bool needsSort = false;
1619  double prevAlong = 0;
1620  for (unsigned short ipt = fromPt; ipt < fromPt + nPtsFit; ++ipt) {
1621  auto& tp3d = pfp.TP3Ds[ipt];
1622  unsigned short plane = DecodeCTP(tp3d.CTP).Plane;
1623  double dw = tp3d.Wire - plnTP[plane].Pos[0];
1624  // dt/dW was stored in DeltaRMS by MakeBareTP
1625  double t = dw * plnTP[plane].DeltaRMS;
1626  if (ipt == fromPt) { prevAlong = t; }
1627  else {
1628  if (t < prevAlong) needsSort = true;
1629  prevAlong = t;
1630  }
1631  for (unsigned short xyz = 0; xyz < 3; ++xyz)
1632  pos[xyz] = sf.Pos[xyz] + t * sf.Dir[xyz];
1633  // Note that the tp3d position is directly above the wire position and not the
1634  // distance of closest approach. The Delta variable is the difference in the
1635  // drift direction in cm
1636  double delta = pos[0] - tp3d.TPX;
1637  tp3d.Pos = pos;
1638  tp3d.Dir = sf.Dir;
1639  tp3d.along = t;
1640  if (tp3d.Flags[kTP3DGood]) sf.ChiDOF += delta * delta / tp3d.TPXErr2;
1641  } // ipt
1642  if (needsSort) SortSection(pfp, sfIndex);
1643  pfp.SectionFits[sfIndex].NeedsUpdate = false;
1644  return true;
1645 
1646  } // FitTP3Ds
then if[["$THISISATEST"==1]]
Definition: neoSmazza.sh:95
std::array< double, 3 > Point3_t
Definition: DataStructs.h:41
bool SortSection(PFPStruct &pfp, unsigned short sfIndex)
Definition: PFPUtils.cxx:2028
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const Point3_t &pos, CTP_t inCTP)
Definition: Utils.cxx:4027
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
SectionFit FitTP3Ds(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const std::vector< TP3D > &tp3ds, unsigned short fromPt, short fitDir, unsigned short nPtsFit)
Definition: PFPUtils.cxx:1447
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:52
auto const detProp
void tca::FitTraj ( TCSlice &  slc,
Trajectory &  tj 
)

Definition at line 808 of file Utils.cxx.

809  {
810  // Jacket around FitTraj to fit the leading edge of the supplied trajectory
811  unsigned short originPt = tj.EndPt[1];
812  unsigned short npts = tj.Pts[originPt].NTPsFit;
813  TrajPoint tpFit;
814  unsigned short fitDir = -1;
815  FitTraj(slc, tj, originPt, npts, fitDir, tpFit);
816  tj.Pts[originPt] = tpFit;
817 
818  } // FitTraj
void FitTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:808
void tca::FitTraj ( TCSlice &  slc,
Trajectory &  tj,
unsigned short  originPt,
unsigned short  npts,
short  fitDir,
TrajPoint &  tpFit 
)

Definition at line 822 of file Utils.cxx.

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

Definition at line 1954 of file TCVertex.cxx.

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

Definition at line 2004 of file TCVertex.cxx.

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

Definition at line 2797 of file StepUtils.cxx.

2798  {
2799  // Update the parameters at the beginning of the trajectory starting at point atPt
2800 
2801  if(!tcc.useAlg[kFixBegin]) return;
2802  // ignore short trajectories
2803  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
2804  if(npwc < 6) return;
2805  // ignore shower-like trajectories
2806  if(tj.PDGCode == 11) return;
2807  // ignore junk trajectories
2808  if(tj.AlgMod[kJunkTj]) return;
2809  unsigned short firstPt = tj.EndPt[0];
2810 
2811  if(atPt == tj.EndPt[0]) return;
2812 
2813  // Default is to use DeltaRMS of the last point on the Tj
2814  float maxDelta = 4 * tj.Pts[tj.EndPt[1]].DeltaRMS;
2815 
2816  // Find the max DeltaRMS of points from atPt to EndPt[1]
2817  float maxDeltaRMS = 0;
2818  for(unsigned short ipt = atPt; ipt <= tj.EndPt[1]; ++ipt) {
2819  if(tj.Pts[ipt].DeltaRMS > maxDeltaRMS) maxDeltaRMS = tj.Pts[ipt].DeltaRMS;
2820  } // ipt
2821  maxDelta = 3 * maxDeltaRMS;
2822 
2823  if(tcc.dbgStp) {
2824  mf::LogVerbatim("TC")<<"FB: atPt "<<atPt<<" firstPt "<<firstPt<<" Stops at end 0? "<<PrintEndFlag(tj, 0)<<" start vertex "<<tj.VtxID[0]<<" maxDelta "<<maxDelta;
2825  }
2826 
2827  // update the trajectory for all the points up to atPt
2828  // assume that we will use all of these points
2829  bool maskedPts = false;
2830  for(unsigned short ii = 1; ii < tj.Pts.size(); ++ii) {
2831  if(ii > atPt) break;
2832  unsigned int ipt = atPt - ii;
2833  TrajPoint& tp = tj.Pts[ipt];
2834  tp.Dir = tj.Pts[atPt].Dir;
2835  tp.Ang = tj.Pts[atPt].Ang;
2836  tp.AngErr = tj.Pts[atPt].AngErr;
2837  tp.AngleCode = tj.Pts[atPt].AngleCode;
2838  // Correct the projected time to the wire
2839  float dw = tp.Pos[0] - tj.Pts[atPt].Pos[0];
2840  if(tp.Dir[0] != 0) tp.Pos[1] = tj.Pts[atPt].Pos[1] + dw * tp.Dir[1] / tp.Dir[0];
2841  tj.Pts[ipt].Delta = PointTrajDOCA(slc, tj.Pts[ipt].HitPos[0], tj.Pts[ipt].HitPos[1], tj.Pts[ipt]);
2842  tj.Pts[ipt].DeltaRMS = tj.Pts[atPt].DeltaRMS;
2843  tj.Pts[ipt].NTPsFit = tj.Pts[atPt].NTPsFit;
2844  tj.Pts[ipt].FitChi = tj.Pts[atPt].FitChi;
2845  tj.Pts[ipt].AveChg = tj.Pts[atPt].AveChg;
2846  tj.Pts[ipt].ChgPull = (tj.Pts[ipt].Chg / tj.AveChg - 1) / tj.ChgRMS;
2847  bool badChg = (std::abs(tj.Pts[ipt].ChgPull) > tcc.chargeCuts[0]);
2848  bool maskThisPt = (tj.Pts[ipt].Delta > maxDelta || badChg);
2849  if(maskThisPt) {
2850  UnsetUsedHits(slc, tp);
2851  maskedPts = true;
2852  }
2853  if(tcc.dbgStp) {
2854  mf::LogVerbatim myprt("TC");
2855  myprt<<" Point "<<PrintPos(slc, tj.Pts[ipt].Pos)<<" Delta "<<tj.Pts[ipt].Delta<<" ChgPull "<<tj.Pts[ipt].ChgPull<<" maskThisPt? "<<maskThisPt;
2856  }
2857  if(ipt == 0) break;
2858  } // ii
2859  if(maskedPts) SetEndPoints(tj);
2860  tj.AlgMod[kFixBegin] = true;
2861 
2862  } // FixBegin
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3413
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1075
std::string PrintEndFlag(const PFPStruct &pfp, unsigned short end)
Definition: Utils.cxx:6463
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2572
T abs(T value)
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
std::vector< float > chargeCuts
Definition: DataStructs.h:562
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2116
void tca::Forecast ( TCSlice &  slc,
const Trajectory &  tj 
)

Definition at line 436 of file StepUtils.cxx.

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

Definition at line 4849 of file Utils.cxx.

4850  {
4851  // returns a list of IDs of objects (slc, vertices, pfps, etc) with type1Name that are in slc with
4852  // type2Name. This is intended to be a general purpose replacement for specific functions like GetVtxTjIDs, etc
4853 
4854  std::vector<int> tmp;
4855  if (id <= 0) return tmp;
4856  unsigned int uid = id;
4857 
4858  if (type1Name == "T" && uid <= slc.tjs.size() && type2Name == "P") {
4859  // return a list of PFPs that have the tj in TjIDs, P -> T<ID>
4860  for (auto& pfp : slc.pfps) {
4861  if (pfp.ID <= 0) continue;
4862  if (std::find(pfp.TjIDs.begin(), pfp.TjIDs.end(), id) != pfp.TjIDs.end())
4863  tmp.push_back(pfp.ID);
4864  } // pf
4865  return tmp;
4866  } // P -> T
4867 
4868  if (type1Name == "P" && uid <= slc.pfps.size() && (type2Name == "2S" || type2Name == "3S")) {
4869  // return a list of 3D or 2D showers with the assn 3S -> 2S -> T -> P<ID> or 2S -> T -> P.
4870  auto& pfp = slc.pfps[uid - 1];
4871  // First form a list of 2S -> T -> P<ID>
4872  std::vector<int> ssid;
4873  for (auto& ss : slc.cots) {
4874  if (ss.ID <= 0) continue;
4875  auto shared = SetIntersection(ss.TjIDs, pfp.TjIDs);
4876  if (!shared.empty() && std::find(ssid.begin(), ssid.end(), ss.ID) == ssid.end())
4877  ssid.push_back(ss.ID);
4878  } // ss
4879  if (type2Name == "2S") return ssid;
4880  for (auto& ss3 : slc.showers) {
4881  if (ss3.ID <= 0) continue;
4882  auto shared = SetIntersection(ss3.CotIDs, ssid);
4883  if (!shared.empty() && std::find(tmp.begin(), tmp.end(), ss3.ID) == tmp.end())
4884  tmp.push_back(ss3.ID);
4885  } // ss3
4886  return tmp;
4887  } // 3S -> 2S -> T -> P
4888 
4889  if (type1Name == "2V" && uid <= slc.vtxs.size() && type2Name == "T") {
4890  // 2V -> T
4891  for (auto& tj : slc.tjs) {
4892  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
4893  for (unsigned short end = 0; end < 2; ++end) {
4894  if (tj.VtxID[end] != id) continue;
4895  if (std::find(tmp.begin(), tmp.end(), tj.ID) == tmp.end()) tmp.push_back(tj.ID);
4896  } // end
4897  } // tj
4898  return tmp;
4899  } // 2V -> T
4900 
4901  if (type1Name == "3V" && uid <= slc.vtx3s.size() && type2Name == "P") {
4902  for (auto& pfp : slc.pfps) {
4903  if (pfp.ID == 0) continue;
4904  for (unsigned short end = 0; end < 2; ++end) {
4905  if (pfp.Vx3ID[end] != id) continue;
4906  // encode the end with the ID
4907  if (std::find(tmp.begin(), tmp.end(), pfp.ID) == tmp.end()) tmp.push_back(pfp.ID);
4908  } // end
4909  } // pfp
4910  return tmp;
4911  } // 3V -> P
4912 
4913  if (type1Name == "3V" && uid <= slc.vtx3s.size() && type2Name == "T") {
4914  // 3V -> T
4915  for (auto& tj : slc.tjs) {
4916  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
4917  for (unsigned short end = 0; end < 2; ++end) {
4918  if (tj.VtxID[end] > 0 && tj.VtxID[end] <= slc.vtxs.size()) {
4919  auto& vx2 = slc.vtxs[tj.VtxID[end] - 1];
4920  if (vx2.Vx3ID != id) continue;
4921  if (std::find(tmp.begin(), tmp.end(), tj.ID) == tmp.end()) tmp.push_back(tj.ID);
4922  }
4923  } // end
4924  } // tj
4925  return tmp;
4926  } // 3V -> T
4927 
4928  if (type1Name == "3V" && uid <= slc.vtx3s.size() && type2Name == "2V") {
4929  // 3V -> 2V
4930  for (auto& vx2 : slc.vtxs) {
4931  if (vx2.ID == 0) continue;
4932  if (vx2.Vx3ID == id) tmp.push_back(vx2.ID);
4933  } // vx2
4934  return tmp;
4935  } // 3V -> 2V
4936 
4937  if (type1Name == "3S" && uid <= slc.showers.size() && type2Name == "T") {
4938  // 3S -> T
4939  auto& ss3 = slc.showers[uid - 1];
4940  if (ss3.ID == 0) return tmp;
4941  for (auto cid : ss3.CotIDs) {
4942  auto& ss = slc.cots[cid - 1];
4943  if (ss.ID == 0) continue;
4944  tmp.insert(tmp.end(), ss.TjIDs.begin(), ss.TjIDs.end());
4945  } // cid
4946  return tmp;
4947  } // 3S -> T
4948 
4949  // This isn't strictly necessary but do it for consistency
4950  if (type1Name == "2S" && uid <= slc.cots.size() && type2Name == "T") {
4951  // 2S -> T
4952  auto& ss = slc.cots[uid - 1];
4953  return ss.TjIDs;
4954  } // 2S -> T
4955 
4956  if (type1Name == "3S" && uid <= slc.showers.size() && type2Name == "P") {
4957  // 3S -> P
4958  auto& ss3 = slc.showers[uid - 1];
4959  if (ss3.ID == 0) return tmp;
4960  for (auto cid : ss3.CotIDs) {
4961  auto& ss = slc.cots[cid - 1];
4962  if (ss.ID == 0) continue;
4963  for (auto tid : ss.TjIDs) {
4964  auto& tj = slc.tjs[tid - 1];
4965  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
4966  if (!tj.AlgMod[kMat3D]) continue;
4967  for (auto& pfp : slc.pfps) {
4968  if (pfp.ID <= 0) continue;
4969  if (std::find(pfp.TjIDs.begin(), pfp.TjIDs.end(), tj.ID) == pfp.TjIDs.end()) continue;
4970  if (std::find(tmp.begin(), tmp.end(), pfp.ID) == tmp.end()) tmp.push_back(pfp.ID);
4971  } // pf
4972  } // tid
4973  } // cid
4974  return tmp;
4975  } // 3S -> P
4976 
4977  if (type1Name == "T" && uid <= slc.tjs.size() && type2Name == "2S") {
4978  // T -> 2S
4979  for (auto& ss : slc.cots) {
4980  if (ss.ID == 0) continue;
4981  if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), id) != ss.TjIDs.end()) tmp.push_back(ss.ID);
4982  } // ss
4983  return tmp;
4984  } // T -> 2S
4985 
4986  if (type1Name == "T" && uid <= slc.tjs.size() && type2Name == "3S") {
4987  // T -> 3S
4988  for (auto& ss : slc.cots) {
4989  if (ss.ID == 0) continue;
4990  if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), id) == ss.TjIDs.end()) continue;
4991  if (ss.SS3ID > 0) tmp.push_back(ss.SS3ID);
4992  } // ss
4993  return tmp;
4994  } // T -> 3S
4995 
4996  return tmp;
4997  } // GetAssns
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
int tca::GetCotID ( TCSlice &  slc,
int  ShowerTjID 
)

Definition at line 3943 of file TCShower.cxx.

3944  {
3945  for (unsigned short ii = 0; ii < slc.cots.size(); ++ii) {
3946  if (ShowerTjID == slc.cots[ii].ShowerTjID) return ii + 1;
3947  } // iii
3948  return 0;
3949 
3950  } // GetCotID
void tca::GetHitMultiplet ( const TCSlice &  slc,
unsigned int  theHit,
std::vector< unsigned int > &  hitsInMultiplet,
bool  useLongPulseHits 
)

Definition at line 1415 of file StepUtils.cxx.

1416  {
1417  // This function attempts to return a list of hits in the current slice that are close to the
1418  // hit specified by theHit and that are similar to it. If theHit is a high-pulseheight hit (aka imTall)
1419  // and has an RMS similar to a hit on a small angle trajectory (aka Narrow) and is embedded in a series of
1420  // nearby low-pulseheight wide hits, the hit multiplet will consist of the single Tall and Narrow hit. On the
1421  // other hand, if theHit references a short and not-narrow hit, all of the hits in the series of nearby
1422  // hits will be returned. The localIndex is the index of theHit in hitsInMultiplet and shouldn't be
1423  // confused with the recob::Hit LocalIndex
1424  hitsInMultiplet.clear();
1425  // check for flagrant errors
1426  if(theHit >= slc.slHits.size()) return;
1427  if(slc.slHits[theHit].InTraj == INT_MAX) return;
1428  if(slc.slHits[theHit].allHitsIndex >= (*evt.allHits).size()) return;
1429 
1430  auto& hit = (*evt.allHits)[slc.slHits[theHit].allHitsIndex];
1431  // handle long-pulse hits
1432  if(useLongPulseHits && LongPulseHit(hit)) {
1433  // return everything in the multiplet as defined by the hit finder, but check for errors
1434  short int hitMult = hit.Multiplicity();
1435  unsigned int lIndex = hit.LocalIndex();
1436  unsigned int firstHit = 0;
1437  if(lIndex < theHit) firstHit = theHit - lIndex;
1438  for(unsigned int ii = firstHit; ii < firstHit + hitMult; ++ii) {
1439  if(ii >= slc.slHits.size()) break;
1440  auto& tmp = (*evt.allHits)[slc.slHits[ii].allHitsIndex];
1441  if(tmp.Multiplicity() == hitMult) hitsInMultiplet.push_back(ii);
1442  } // ii
1443  return;
1444  } // LongPulseHit
1445 
1446  hitsInMultiplet.resize(1);
1447  hitsInMultiplet[0] = theHit;
1448  unsigned int theWire = hit.WireID().Wire;
1449  unsigned short ipl = hit.WireID().Plane;
1450 
1451  float theTime = hit.PeakTime();
1452  float theRMS = hit.RMS();
1453  float narrowHitCut = 1.5 * evt.aveHitRMS[ipl];
1454  bool theHitIsNarrow = (theRMS < narrowHitCut);
1455  float maxPeak = hit.PeakAmplitude();
1456  unsigned int imTall = theHit;
1457  unsigned short nNarrow = 0;
1458  if(theHitIsNarrow) nNarrow = 1;
1459  // look for hits < theTime but within hitSep
1460  if(theHit > 0) {
1461  for(unsigned int iht = theHit - 1; iht != 0; --iht) {
1462  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1463  if(hit.WireID().Wire != theWire) break;
1464  if(hit.WireID().Plane != ipl) break;
1465  float hitSep = tcc.multHitSep * theRMS;
1466  float rms = hit.RMS();
1467  if(rms > theRMS) {
1468  hitSep = tcc.multHitSep * rms;
1469  theRMS = rms;
1470  }
1471  float dTick = std::abs(hit.PeakTime() - theTime);
1472  if(dTick > hitSep) break;
1473  hitsInMultiplet.push_back(iht);
1474  if(rms < narrowHitCut) ++nNarrow;
1475  float peakAmp = hit.PeakAmplitude();
1476  if(peakAmp > maxPeak) {
1477  maxPeak = peakAmp;
1478  imTall = iht;
1479  }
1480  theTime = hit.PeakTime();
1481  if(iht == 0) break;
1482  } // iht
1483  } // iht > 0
1484  // reverse the order so that hitsInMuliplet will be
1485  // returned in increasing time order
1486  if(hitsInMultiplet.size() > 1) std::reverse(hitsInMultiplet.begin(), hitsInMultiplet.end());
1487  // look for hits > theTime but within hitSep
1488  theTime = hit.PeakTime();
1489  theRMS = hit.RMS();
1490  for(unsigned int iht = theHit + 1; iht < slc.slHits.size(); ++iht) {
1491  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1492  if(hit.WireID().Wire != theWire) break;
1493  if(hit.WireID().Plane != ipl) break;
1494  if(slc.slHits[iht].InTraj == INT_MAX) continue;
1495  float hitSep = tcc.multHitSep * theRMS;
1496  float rms = hit.RMS();
1497  if(rms > theRMS) {
1498  hitSep = tcc.multHitSep * rms;
1499  theRMS = rms;
1500  }
1501  float dTick = std::abs(hit.PeakTime() - theTime);
1502  if(dTick > hitSep) break;
1503  hitsInMultiplet.push_back(iht);
1504  if(rms < narrowHitCut) ++nNarrow;
1505  float peakAmp = hit.PeakAmplitude();
1506  if(peakAmp > maxPeak) {
1507  maxPeak = peakAmp;
1508  imTall = iht;
1509  }
1510  theTime = hit.PeakTime();
1511  } // iht
1512  if(hitsInMultiplet.size() == 1) return;
1513 
1514  // Don't make a multiplet that includes a tall narrow hit with short fat hits
1515  if(nNarrow == hitsInMultiplet.size()) return;
1516  if(nNarrow == 0) return;
1517 
1518  if(theHitIsNarrow && theHit == imTall) {
1519  // theHit is narrow and it is the highest amplitude hit in the multiplet. Ignore any
1520  // others that are short and fat
1521  auto tmp = hitsInMultiplet;
1522  tmp.resize(1);
1523  tmp[0] = theHit;
1524  hitsInMultiplet = tmp;
1525  } else {
1526  // theHit is not narrow and it is not the tallest. Ignore a single hit if it is
1527  // the tallest and narrow
1528  auto& hit = (*evt.allHits)[slc.slHits[imTall].allHitsIndex];
1529  if(hit.RMS() < narrowHitCut) {
1530  unsigned short killMe = 0;
1531  for(unsigned short ii = 0; ii < hitsInMultiplet.size(); ++ii) {
1532  if(hitsInMultiplet[ii] == imTall) {
1533  killMe = ii;
1534  break;
1535  }
1536  } // ii
1537  hitsInMultiplet.erase(hitsInMultiplet.begin() + killMe);
1538  } // slc.slHits[imTall].RMS < narrowHitCut
1539  } // narrow / tall test
1540 
1541  } // GetHitMultiplet
TCConfig tcc
Definition: DataStructs.cxx:9
process_name hit
Definition: cheaterreco.fcl:51
bool LongPulseHit(const recob::Hit &hit)
Definition: Utils.cxx:4452
T abs(T value)
std::vector< float > aveHitRMS
average RMS of an isolated hit
Definition: DataStructs.h:638
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
float multHitSep
preferentially &quot;merge&quot; hits with &lt; this separation
Definition: DataStructs.h:574
TCEvent evt
Definition: DataStructs.cxx:8
int tca::GetOrigin ( detinfo::DetectorClocksData const &  clockData,
TCSlice &  slc,
PFPStruct &  pfp 
)

Definition at line 72 of file TCCR.cxx.

73  {
74 
75  art::ServiceHandle<cheat::BackTrackerService const> bt_serv;
76  art::ServiceHandle<cheat::ParticleInventoryService const> pi_serv;
77 
78  std::map<int, float> omap; //<origin, energy>
79 
80  for (auto& tjID : pfp.TjIDs) {
81 
82  Trajectory& tj = slc.tjs[tjID - 1];
83  for (auto& tp : tj.Pts) {
84  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
85  if (!tp.UseHit[ii]) continue;
86  unsigned int iht = tp.Hits[ii];
87  TCHit& slhit = slc.slHits[iht];
88  auto& hit = (*evt.allHits)[slhit.allHitsIndex];
89  raw::ChannelID_t channel = tcc.geom->PlaneWireToChannel((int)hit.WireID().Plane,
90  (int)hit.WireID().Wire,
91  (int)hit.WireID().TPC,
92  (int)hit.WireID().Cryostat);
93  double startTick = hit.PeakTime() - hit.RMS();
94  double endTick = hit.PeakTime() + hit.RMS();
95  // get a list of track IDEs that are close to this hit
96  std::vector<sim::TrackIDE> tides;
97  tides = bt_serv->ChannelToTrackIDEs(clockData, channel, startTick, endTick);
98  for (auto itide = tides.begin(); itide != tides.end(); ++itide) {
99  omap[pi_serv->TrackIdToMCTruth_P(itide->trackID)->Origin()] += itide->energy;
100  }
101  }
102  }
103  }
104 
105  float maxe = -1;
106  int origin = 0;
107  for (auto& i : omap) {
108  if (i.second > maxe) {
109  maxe = i.second;
110  origin = i.first;
111  }
112  }
113  return origin;
114  }
TCConfig tcc
Definition: DataStructs.cxx:9
process_name hit
Definition: cheaterreco.fcl:51
const geo::GeometryCore * geom
Definition: DataStructs.h:576
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:622
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:227
unsigned short tca::GetPFPIndex ( const TCSlice &  slc,
int  tjID 
)

Definition at line 1050 of file Utils.cxx.

1051  {
1052  if (slc.pfps.empty()) return USHRT_MAX;
1053  for (unsigned int ipfp = 0; ipfp < slc.pfps.size(); ++ipfp) {
1054  const auto& pfp = slc.pfps[ipfp];
1055  if (std::find(pfp.TjIDs.begin(), pfp.TjIDs.end(), tjID) != pfp.TjIDs.end()) return ipfp;
1056  } // indx
1057  return USHRT_MAX;
1058  } // GetPFPIndex
void tca::GetRange ( const PFPStruct &  pfp,
unsigned short  sfIndex,
unsigned short &  fromPt,
unsigned short &  npts 
)

Definition at line 1392 of file PFPUtils.cxx.

1396  {
1397  fromPt = USHRT_MAX;
1398  if (sfIndex >= pfp.SectionFits.size()) return;
1399  if (pfp.TP3Ds.empty()) return;
1400  fromPt = USHRT_MAX;
1401  npts = 0;
1402  // Note that no test is made for not-good TP3Ds here since that would give a wrong npts count
1403  for (std::size_t ipt = 0; ipt < pfp.TP3Ds.size(); ++ipt) {
1404  auto& tp3d = pfp.TP3Ds[ipt];
1405  if (tp3d.SFIndex < sfIndex) continue;
1406  if (tp3d.SFIndex > sfIndex) break;
1407  if (fromPt == USHRT_MAX) fromPt = ipt;
1408  ++npts;
1409  } // ipt
1410  } // GetRange
std::pair< unsigned short, unsigned short > tca::GetSliceIndex ( std::string  typeName,
int  uID 
)

Definition at line 5088 of file Utils.cxx.

5089  {
5090  // returns the slice index and product index of a data product having typeName and unique ID uID
5091  for (unsigned short isl = 0; isl < slices.size(); ++isl) {
5092  auto& slc = slices[isl];
5093  if (typeName == "T") {
5094  for (unsigned short indx = 0; indx < slc.tjs.size(); ++indx) {
5095  if (slc.tjs[indx].UID == uID) { return std::make_pair(isl, indx); }
5096  }
5097  } // T
5098  if (typeName == "P") {
5099  for (unsigned short indx = 0; indx < slc.pfps.size(); ++indx) {
5100  if (slc.pfps[indx].UID == uID) { return std::make_pair(isl, indx); }
5101  }
5102  } // P
5103  if (typeName == "2V") {
5104  for (unsigned short indx = 0; indx < slc.vtxs.size(); ++indx) {
5105  if (slc.vtxs[indx].UID == uID) { return std::make_pair(isl, indx); }
5106  }
5107  } // 2V
5108  if (typeName == "3V") {
5109  for (unsigned short indx = 0; indx < slc.vtx3s.size(); ++indx) {
5110  if (slc.vtx3s[indx].UID == uID) { return std::make_pair(isl, indx); }
5111  }
5112  } // 3V
5113  if (typeName == "2S") {
5114  for (unsigned short indx = 0; indx < slc.cots.size(); ++indx) {
5115  if (slc.cots[indx].UID == uID) { return std::make_pair(isl, indx); }
5116  }
5117  } // 2S
5118  if (typeName == "3S") {
5119  for (unsigned short indx = 0; indx < slc.showers.size(); ++indx) {
5120  if (slc.showers[indx].UID == uID) { return std::make_pair(isl, indx); }
5121  }
5122  } // T
5123  } // isl
5124  return std::make_pair(USHRT_MAX, USHRT_MAX);
5125  } // GetSliceIndex
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
int tca::GetStageNum ( ShowerTreeVars &  stv,
std::string  stageName 
)

Definition at line 194 of file TCShTree.cxx.

194  {
195  int stageNum;
196  bool existingStage = false;
197  for (unsigned short i = 0; i < stv.StageName.size(); ++i) {
198  if (stv.StageName.at(i) == stageName) {
199  existingStage = true;
200  stageNum = i+1;
201  }
202  }
203 
204  if (!existingStage) {
205  stv.StageName.push_back(stageName);
206  stageNum = stv.StageName.size();
207  }
208 
209  return stageNum;
210  }
ShowerTreeVars stv
Definition: DataStructs.cxx:11
std::vector< std::string > StageName
Definition: DataStructs.h:406
std::vector< int > tca::GetVtxTjIDs ( const TCSlice &  slc,
const VtxStore &  vx2 
)

Definition at line 2837 of file TCVertex.cxx.

2838  {
2839  // returns a list of trajectory IDs that are attached to vx2
2840  std::vector<int> tmp;
2841  if (vx2.ID == 0) return tmp;
2842  for (auto& tj : slc.tjs) {
2843  if (tj.AlgMod[kKilled]) continue;
2844  if (tj.CTP != vx2.CTP) continue;
2845  for (unsigned short end = 0; end < 2; ++end) {
2846  if (tj.VtxID[end] == vx2.ID) tmp.push_back(tj.ID);
2847  } // end
2848  } // tj
2849  return tmp;
2850  } // GetVtxTjIDs
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
std::vector< int > tca::GetVtxTjIDs ( const TCSlice &  slc,
const Vtx3Store &  vx3,
float &  score 
)

Definition at line 2854 of file TCVertex.cxx.

2855  {
2856  // returns a list of Tjs in all planes that are attached to vx3
2857  std::vector<int> tmp;
2858  if (vx3.ID == 0) return tmp;
2859  float nvx2 = 0;
2860  score = 0;
2861  for (auto& vx2 : slc.vtxs) {
2862  if (vx2.ID == 0) continue;
2863  if (vx2.Vx3ID != vx3.ID) continue;
2864  auto vtxTjID2 = GetVtxTjIDs(slc, vx2);
2865  tmp.insert(tmp.end(), vtxTjID2.begin(), vtxTjID2.end());
2866  score += vx2.Score;
2867  ++nvx2;
2868  } // vx2
2869  if (nvx2 < 1) return tmp;
2870  // find the average score
2871  score /= nvx2;
2872  // sort by increasing ID
2873  std::sort(tmp.begin(), tmp.end());
2874  return tmp;
2875  } // GetVtxTjIDs
BEGIN_PROLOG or score(default)}sbnd_crttrackmatchingalg_crID
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const VtxStore &vx2)
Definition: TCVertex.cxx:2837
bool tca::GottaKink ( TCSlice &  slc,
Trajectory &  tj,
bool  doTrim 
)

Definition at line 2556 of file StepUtils.cxx.

2557  {
2558  // This function returns true if it detects a kink in the trajectory
2559  // This function trims the points after a kink if one is found if doTrim is true.
2560 
2561  // tcc.kinkCuts[] fcl configuration
2562  // 0 = Number of TPs to fit at the end
2563  // 1 = Min kink significance
2564  // 2 = Use charge in significance calculation if > 0
2565  // 3 = 3D kink fit length (cm) - used in PFPUtils/SplitAtKinks
2566 
2567  // don't look for kinks if this looks a high energy electron
2568  // BB Jan 2, 2020: Return true if a kink was found but don't set the
2569  // stop-at-kink end flag
2570  if(tj.Strategy[kStiffEl]) return false;
2571  // Need at least 2 * kinkCuts[2] points with charge to find a kink
2572  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
2573  unsigned short nPtsFit = tcc.kinkCuts[0];
2574  // Set nPtsFit for slowing tjs to the last TP NTPsFit
2575  if(tj.Strategy[kSlowing]) nPtsFit = tj.Pts[tj.EndPt[1]].NTPsFit;
2576  if(npwc < 2 * nPtsFit) return false;
2577 
2578  bool useCharge = (tcc.kinkCuts[2] > 0);
2579 
2580  // find the point where a kink is expected and fit the points after that point
2581  unsigned short fitPt = USHRT_MAX;
2582  unsigned short cnt = 0;
2583  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
2584  unsigned short ipt = tj.EndPt[1] - ii - 1;
2585  // stay away from the starting points which may be skewed if this is a
2586  // stopping track
2587  if(ipt <= tj.EndPt[0] + 2) break;
2588  if(tj.Pts[ipt].Chg <= 0) continue;
2589  ++cnt;
2590  // Note that the fitPt is not included in the fits in the kink significance so we need
2591  // one more point
2592  if(cnt > nPtsFit) {
2593  fitPt = ipt;
2594  break;
2595  }
2596  } // ii
2597  if(fitPt == USHRT_MAX) {
2598  if(tcc.dbgStp) {
2599  mf::LogVerbatim myprt("TC");
2600  myprt<<"GKv2 fitPt not valid. Counted "<<cnt<<" points. Need "<<nPtsFit;
2601  } // tcc.dbgStp
2602  return false;
2603  }
2604 
2605  tj.Pts[fitPt].KinkSig = KinkSignificance(slc, tj, fitPt, nPtsFit, useCharge, tcc.dbgStp);
2606 
2607  bool thisPtHasKink = (tj.Pts[fitPt].KinkSig > tcc.kinkCuts[1]);
2608  bool prevPtHasKink = (tj.Pts[fitPt - 1].KinkSig > tcc.kinkCuts[1]);
2609  if(tcc.dbgStp) {
2610  mf::LogVerbatim myprt("TC");
2611  myprt<<"GKv2 fitPt "<<fitPt<<" "<<PrintPos(slc, tj.Pts[fitPt]);
2612  myprt<<std::fixed<<std::setprecision(5);
2613  myprt<<" KinkSig "<<std::setprecision(5)<<tj.Pts[fitPt].KinkSig;
2614  myprt<<" prevPt significance "<<tj.Pts[fitPt - 1].KinkSig;
2615  if(!thisPtHasKink && !prevPtHasKink) myprt<<" no kink";
2616  if(thisPtHasKink && !prevPtHasKink) myprt<<" -> Start kink region";
2617  if(thisPtHasKink && prevPtHasKink) myprt<<" -> Inside kink region";
2618  if(!thisPtHasKink && prevPtHasKink) myprt<<" -> End kink region";
2619  } // dbgStp
2620  // See if we just passed a series of points having a high kink significance. If so,
2621  // then find the point with the maximum value and call that the kink point
2622  // Don't declare a kink (yet)
2623  if(thisPtHasKink) return false;
2624  // neither points are kink-like
2625  if(!prevPtHasKink) return false;
2626 
2627  // We have left a kink region. Find the point with the max likelihood and call
2628  // that the kink point
2629  float maxSig = tcc.kinkCuts[1];
2630  unsigned short kinkRegionLength = 0;
2631  unsigned short maxKinkPt = USHRT_MAX;
2632  for(unsigned short ipt = fitPt - 1; ipt > tj.EndPt[0]; --ipt) {
2633  auto& tp = tj.Pts[ipt];
2634  if(tp.KinkSig < 0) continue;
2635  if(tp.KinkSig > maxSig) {
2636  // track the max significance
2637  maxSig = tp.KinkSig;
2638  maxKinkPt = ipt;
2639  } // tp.KinkSig > maxSig
2640  // find the start of the kink region
2641  if(tp.KinkSig < tcc.kinkCuts[1]) break;
2642  ++kinkRegionLength;
2643  } // ipt
2644  if(maxKinkPt == USHRT_MAX) return false;
2645  // Require that the candidate kink be above the cut threshold for more than one point.
2646  // Scale the requirement by the number of points in the fit
2647  unsigned short kinkRegionLengthMin = 1 + nPtsFit / 5;
2648  if(tj.Strategy[kStiffMu]) kinkRegionLengthMin = 1 + nPtsFit / 3;
2649  if(kinkRegionLength < kinkRegionLengthMin) {
2650  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"GKv2: kink region too short "<<kinkRegionLength<<" Min "<<kinkRegionLengthMin;
2651  return false;
2652  }
2653  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"GKv2: kink at "<<PrintPos(slc, tj.Pts[maxKinkPt])<<std::setprecision(3)<<" maxSig "<<maxSig<<" kinkRegionLength "<<kinkRegionLength<<" Min "<<kinkRegionLengthMin;
2654  // don't alter the tj unless doTrim is true
2655  if(!doTrim) return true;
2656  // trim the points
2657  for(unsigned short ipt = maxKinkPt + 1; ipt <= tj.EndPt[1]; ++ipt) UnsetUsedHits(slc, tj.Pts[ipt]);
2658  SetEndPoints(tj);
2659  // trim another point if the charge of the last two points is wildly dissimilar
2660  float lastChg = tj.Pts[tj.EndPt[1]].Chg;
2661  float prevChg = tj.Pts[tj.EndPt[1] - 1].Chg;
2662  float chgAsym = std::abs(lastChg - prevChg) / (lastChg + prevChg);
2663  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"GKv2: last point after trim "<<PrintPos(slc, tj.Pts[tj.EndPt[1]])<<" chgAsym "<<chgAsym;
2664  if(chgAsym > 0.1) {
2665  UnsetUsedHits(slc, tj.Pts[tj.EndPt[1]]);
2666  SetEndPoints(tj);
2667  }
2668  tj.EndFlag[1][kAtKink] = true;
2669  return true;
2670 
2671  } // GottaKink
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3413
std::vector< float > kinkCuts
kink finder algorithm
Definition: DataStructs.h:559
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1075
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
T abs(T value)
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
use the slowing-down strategy
Definition: DataStructs.h:503
float KinkSignificance(TCSlice &slc, Trajectory &tj1, unsigned short end1, Trajectory &tj2, unsigned short end2, unsigned short nPtsFit, bool useChg, bool prt)
Definition: Utils.cxx:3056
use the stiff electron strategy
Definition: DataStructs.h:501
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2116
use the stiff muon strategy
Definition: DataStructs.h:502
bool tca::HasDuplicateHits ( const TCSlice &  slc,
Trajectory const &  tj,
bool  prt 
)

Definition at line 2812 of file Utils.cxx.

2813  {
2814  // returns true if a hit is associated with more than one TP
2815  auto tjHits = PutTrajHitsInVector(tj, kAllHits);
2816  for (unsigned short ii = 0; ii < tjHits.size() - 1; ++ii) {
2817  for (unsigned short jj = ii + 1; jj < tjHits.size(); ++jj) {
2818  if (tjHits[ii] == tjHits[jj]) {
2819  if (prt)
2820  mf::LogVerbatim("TC") << "HDH: Hit " << PrintHit(slc.slHits[ii]) << " is a duplicate "
2821  << ii << " " << jj;
2822  return true;
2823  }
2824  } // jj
2825  } // ii
2826  return false;
2827  } // HasDuplicateHits
std::vector< unsigned int > PutTrajHitsInVector(const Trajectory &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2754
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6516
float tca::HitSep2 ( const TCSlice &  slc,
unsigned int  iht,
unsigned int  jht 
)

Definition at line 2538 of file Utils.cxx.

2539  {
2540  // returns the separation^2 between two hits in WSE units
2541  if (iht > slc.slHits.size() - 1 || jht > slc.slHits.size() - 1) return 1E6;
2542  auto& ihit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2543  auto& jhit = (*evt.allHits)[slc.slHits[jht].allHitsIndex];
2544  float dw = (float)ihit.WireID().Wire - (float)jhit.WireID().Wire;
2545  float dt = (ihit.PeakTime() - jhit.PeakTime()) * tcc.unitsPerTick;
2546  return dw * dw + dt * dt;
2547  } // HitSep2
TCConfig tcc
Definition: DataStructs.cxx:9
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
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 4289 of file Utils.cxx.

4293  {
4294  // returns the position and the charge
4295  float pos = 0;
4296  sum = 0;
4297  for (unsigned short ii = 0; ii < hitsInMultiplet.size(); ++ii) {
4298  unsigned int iht = hitsInMultiplet[ii];
4299  bool useit = (hitRequest == kAllHits);
4300  if (hitRequest == kUsedHits && slc.slHits[iht].InTraj > 0) useit = true;
4301  if (hitRequest == kUnusedHits && slc.slHits[iht].InTraj == 0) useit = true;
4302  if (!useit) continue;
4303  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
4304  float chg = hit.Integral();
4305  pos += chg * hit.PeakTime();
4306  sum += chg;
4307  } // ii
4308  if (sum <= 0) return -1;
4309  return pos / sum;
4310  } // HitsPosTick
process_name hit
Definition: cheaterreco.fcl:51
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
TCEvent evt
Definition: DataStructs.cxx:8
float tca::HitsPosTime ( const TCSlice &  slc,
const std::vector< unsigned int > &  hitsInMultiplet,
float &  sum,
HitStatus_t  hitRequest 
)

Definition at line 4279 of file Utils.cxx.

4283  {
4284  return tcc.unitsPerTick * HitsPosTick(slc, hitsInMultiplet, sum, hitRequest);
4285  } // HitsPosTime
TCConfig tcc
Definition: DataStructs.cxx:9
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
float HitsPosTick(const TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, float &sum, HitStatus_t hitRequest)
Definition: Utils.cxx:4289
float tca::HitsRMSTick ( const TCSlice &  slc,
const std::vector< unsigned int > &  hitsInMultiplet,
HitStatus_t  hitRequest 
)

Definition at line 4246 of file Utils.cxx.

4249  {
4250  if (hitsInMultiplet.empty()) return 0;
4251 
4252  if (hitsInMultiplet.size() == 1) {
4253  auto& hit = (*evt.allHits)[slc.slHits[hitsInMultiplet[0]].allHitsIndex];
4254  return hit.RMS();
4255  }
4256 
4257  float minVal = 9999;
4258  float maxVal = 0;
4259  for (unsigned short ii = 0; ii < hitsInMultiplet.size(); ++ii) {
4260  unsigned int iht = hitsInMultiplet[ii];
4261  bool useit = (hitRequest == kAllHits);
4262  if (hitRequest == kUsedHits && slc.slHits[iht].InTraj > 0) useit = true;
4263  if (hitRequest == kUnusedHits && slc.slHits[iht].InTraj == 0) useit = true;
4264  if (!useit) continue;
4265  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
4266  float cv = hit.PeakTime();
4267  float rms = hit.RMS();
4268  float arg = cv - rms;
4269  if (arg < minVal) minVal = arg;
4270  arg = cv + rms;
4271  if (arg > maxVal) maxVal = arg;
4272  } // ii
4273  if (maxVal == 0) return 0;
4274  return (maxVal - minVal) / 2;
4275  } // HitsRMSTick
process_name hit
Definition: cheaterreco.fcl:51
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
TCEvent evt
Definition: DataStructs.cxx:8
float tca::HitsRMSTime ( const TCSlice &  slc,
const std::vector< unsigned int > &  hitsInMultiplet,
HitStatus_t  hitRequest 
)

Definition at line 4237 of file Utils.cxx.

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

Definition at line 1552 of file StepUtils.cxx.

1553  {
1554  // Estimates the error^2 of the time using all hits in hitVec
1555  if(hitVec.empty()) return 0;
1556  float err = tcc.hitErrFac * HitsRMSTime(slc, hitVec, kUnusedHits);
1557  return err * err;
1558  } // HitsTimeErr2
TCConfig tcc
Definition: DataStructs.cxx:9
EResult err(const char *call)
float HitsRMSTime(const TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, HitStatus_t hitRequest)
Definition: Utils.cxx:4237
float tca::HitTimeErr ( const TCSlice &  slc,
unsigned int  iht 
)

Definition at line 1544 of file StepUtils.cxx.

1545  {
1546  if(iht > slc.slHits.size() - 1) return 0;
1547  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1548  return hit.RMS() * tcc.unitsPerTick * tcc.hitErrFac * hit.Multiplicity();
1549  } // HitTimeErr
TCConfig tcc
Definition: DataStructs.cxx:9
process_name hit
Definition: cheaterreco.fcl:51
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
TCEvent evt
Definition: DataStructs.cxx:8
unsigned short tca::InsertTP3D ( PFPStruct &  pfp,
TP3D &  tp3d 
)

Definition at line 1989 of file PFPUtils.cxx.

1990  {
1991  // inserts the tp3d into the section defined by tp3d.SFIndex
1992  if (tp3d.SFIndex >= pfp.SectionFits.size()) return USHRT_MAX;
1993  // Find the first occurrence of this SFIndex
1994  std::size_t ipt = 0;
1995  for (ipt = 0; ipt < pfp.TP3Ds.size(); ++ipt)
1996  if (tp3d.SFIndex == pfp.TP3Ds[ipt].SFIndex) break;
1997  if (ipt == pfp.TP3Ds.size()) return USHRT_MAX;
1998  // next see if we can insert it so that re-sorting of this section isn't required
1999  auto lastTP3D = pfp.TP3Ds.back();
2000  if (ipt == 0 && tp3d.along < pfp.TP3Ds[0].along) {
2001  // insert at the beginning. No search needs to be done
2002  }
2003  else if (tp3d.SFIndex == lastTP3D.SFIndex && tp3d.along > lastTP3D.along) {
2004  // insert at the end. Use push_back and return
2005  pfp.TP3Ds.push_back(tp3d);
2006  pfp.SectionFits[tp3d.SFIndex].NeedsUpdate = true;
2007  pfp.Flags[kNeedsUpdate] = true;
2008  return pfp.TP3Ds.size() - 1;
2009  }
2010  else {
2011  for (std::size_t iipt = ipt; iipt < pfp.TP3Ds.size() - 1; ++iipt) {
2012  // break out if the next point is in a different section
2013  if (pfp.TP3Ds[iipt + 1].SFIndex != tp3d.SFIndex) break;
2014  if (tp3d.along > pfp.TP3Ds[iipt].along && tp3d.along < pfp.TP3Ds[iipt + 1].along) {
2015  ipt = iipt + 1;
2016  break;
2017  }
2018  } // iipt
2019  } // insert in the middle
2020  pfp.TP3Ds.insert(pfp.TP3Ds.begin() + ipt, tp3d);
2021  pfp.SectionFits[tp3d.SFIndex].NeedsUpdate = true;
2022  pfp.Flags[kNeedsUpdate] = true;
2023  return ipt;
2024  } // InsertTP3D
double tca::InShowerProb ( double  showerEnergy,
double  along,
double  trans 
)
float tca::InShowerProb ( TCSlice &  slc,
const ShowerStruct3D &  ss3,
const PFPStruct &  pfp 
)

Definition at line 2016 of file TCShower.cxx.

2017  {
2018  // returns a likelihood (0 - 1) that the pfp particle belongs in shower ss3
2019 
2020  if (ss3.ID == 0 || pfp.ID == 0) return 0;
2021  float sum = 0;
2022  float cnt = 0;
2023  for (auto cid : ss3.CotIDs) {
2024  auto& ss = slc.cots[cid - 1];
2025  if (ss.ID == 0) continue;
2026  for (auto tid : pfp.TjIDs) {
2027  auto& tj = slc.tjs[tid - 1];
2028  if (tj.CTP != ss.CTP) continue;
2029  sum += InShowerProb(slc, ss, tj);
2030  ++cnt;
2031  } // tid
2032  } //cid
2033  if (cnt == 0) return 0;
2034  return sum / cnt;
2035 
2036  } // InShowerProb
float InShowerProb(TCSlice &slc, const ShowerStruct3D &ss3, const PFPStruct &pfp)
Definition: TCShower.cxx:2016
float tca::InShowerProb ( TCSlice &  slc,
const ShowerStruct &  ss,
const Trajectory &  tj 
)

Definition at line 2040 of file TCShower.cxx.

2041  {
2042  // returns a likelihood (0 - 1) that the tj particle belongs in shower ss
2043  // Keep it simple: construct a FOM, take the inverse and limit it to the range 0 - 1
2044  if (ss.ID == 0 || tj.ID == 0) return 0;
2045  if (ss.CTP != tj.CTP) return 0;
2046 
2047  auto& stj = slc.tjs[ss.ShowerTjID - 1];
2048  if (stj.Pts.size() != 3) return 0;
2049  unsigned short closePt1, closePt2;
2050  float doca = 1E6;
2051  TrajTrajDOCA(slc, stj, tj, closePt1, closePt2, doca);
2052  if (doca == 1E6) return 0;
2053  float showerLen = PosSep(stj.Pts[0].Pos, stj.Pts[2].Pos);
2054  // make a rough separation cut. Return a small but non-zero value
2055  if (doca > 5 * showerLen) return 0.01;
2056  auto& stp = stj.Pts[closePt1];
2057  if (stp.DeltaRMS == 0) return 0;
2058  auto& ttp = tj.Pts[closePt2];
2059  Point2_t alongTrans;
2060  FindAlongTrans(stp.Pos, stp.Dir, ttp.Pos, alongTrans);
2061  float rms = stp.DeltaRMS;
2062  if (rms < 1) rms = 1;
2063  float arg = alongTrans[1] / rms;
2064  float radProb = exp(-0.5 * arg * arg);
2065  // This is a fake but may be OK if this function is called before the shower is well-defined
2066  rms = showerLen;
2067  arg = alongTrans[0] / rms;
2068  float longProb = exp(-0.5 * arg * arg);
2069  float costh = std::abs(DotProd(stp.Dir, ttp.Dir));
2070  float prob = radProb * longProb * costh;
2071  return prob;
2072 
2073  } // InShowerProb
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:3097
T abs(T value)
std::array< float, 2 > Point2_t
Definition: DataStructs.h:43
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:128
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2565
bool TrajTrajDOCA(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2460
double tca::InShowerProbLong ( double  showerEnergy,
double  along 
)

Definition at line 1958 of file TCShower.cxx.

1959  {
1960  // Returns the likelihood that the point at position along (cm) is inside an EM shower
1961  // having showerEnergy (MeV). The variable along is relative to shower max.
1962 
1963  if (showerEnergy < 10) return 0;
1964 
1965  double shMaxAlong, shE95Along;
1966  ShowerParams(showerEnergy, shMaxAlong, shE95Along);
1967  // 50% of the shower energy is deposited between 0 < shMaxAlong < 1, which should be obvious considering
1968  // that is the definition of the shower max, so the probability should be ~1 at shMaxAlong = 1.
1969  // The Geant study shows that 95% of the energy is contained within 2.5 * shMax and has a small dependence
1970  // on the shower energy, which is modeled in ShowerParams. This function uses a
1971  // sigmoid likelihood function is constructed with these constraints using the scaling variable tau
1972  double tau = (along + shMaxAlong) / shMaxAlong;
1973  if (tau < -1 || tau > 4) return 0;
1974 
1975  double tauHalf, width;
1976  if (tau > 0) {
1977  tauHalf = 1.7;
1978  width = 0.35;
1979  }
1980  else {
1981  // Allow for some uncertainty in the shower start position
1982  tau = -tau;
1983  tauHalf = 0.2;
1984  width = 0.1;
1985  }
1986 
1987  double prob = 1 / (1 + exp((tau - tauHalf) / width));
1988  return prob;
1989 
1990  } // InShowrProbLong
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
Definition: TCShower.cxx:1923
double tca::InShowerProbParam ( double  showerEnergy,
double  along,
double  trans 
)

Definition at line 2009 of file TCShower.cxx.

2010  {
2011  return InShowerProbLong(showerEnergy, along) * InShowerProbTrans(showerEnergy, along, trans);
2012  } // InShowerProbParam
double InShowerProbLong(double showerEnergy, double along)
Definition: TCShower.cxx:1958
double InShowerProbTrans(double showerEnergy, double along, double trans)
Definition: TCShower.cxx:1994
double tca::InShowerProbTrans ( double  showerEnergy,
double  along,
double  trans 
)

Definition at line 1994 of file TCShower.cxx.

1995  {
1996  // Returns the likelihood that the point, (along, trans) (cm), is inside an EM shower having energy showerEnergy (MeV)
1997  // where along is relative to the shower start position and trans is the radial distance.
1998 
1999  if (showerEnergy < 10) return 0;
2000  double rms = ShowerParamTransRMS(showerEnergy, along);
2001  trans = std::abs(trans);
2002  double prob = exp(-0.5 * trans / rms);
2003  return prob;
2004 
2005  } // InShowerProbTrans
double ShowerParamTransRMS(double showerEnergy, double along)
Definition: TCShower.cxx:1943
T abs(T value)
bool tca::InsideFV ( const TCSlice &  slc,
const PFPStruct &  pfp,
unsigned short  end 
)

Definition at line 3045 of file PFPUtils.cxx.

3046  {
3047  // returns true if the end of the pfp is inside the fiducial volume of the TPC
3048  if (pfp.ID <= 0) return false;
3049  if (end > 1) return false;
3050  if (pfp.SectionFits.empty()) return false;
3051  // require that the points are sorted which ensures that the start and end points
3052  // are the first and last points in the TP3Ds vector
3053  if (pfp.Flags[kNeedsUpdate]) return false;
3054  bool neutrinoPFP = pfp.PDGCode == 12 || pfp.PDGCode == 14;
3055 
3056  float abit = 5;
3057  Point3_t pos;
3058  if (neutrinoPFP) { pos = pfp.SectionFits[0].Pos; }
3059  else if (end == 0) {
3060  pos = pfp.TP3Ds[0].Pos;
3061  }
3062  else {
3063  pos = pfp.TP3Ds[pfp.TP3Ds.size() - 1].Pos;
3064  }
3065  return (pos[0] > slc.xLo + abit && pos[0] < slc.xHi - abit && pos[1] > slc.yLo + abit &&
3066  pos[1] < slc.yHi - abit && pos[2] > slc.zLo + abit && pos[2] < slc.zHi - abit);
3067 
3068  } // InsideFV
std::array< double, 3 > Point3_t
Definition: DataStructs.h:41
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
bool tca::InsideTPC ( const Point3_t &  pos,
geo::TPCID inTPCID 
)

Definition at line 3072 of file PFPUtils.cxx.

3073  {
3074  // determine which TPC this point is in. This function returns false
3075  // if the point is not inside any TPC
3076  float abit = 5;
3077  for (const geo::TPCID& tpcid : tcc.geom->IterateTPCIDs()) {
3078  const geo::TPCGeo& TPC = tcc.geom->TPC(tpcid);
3079  double local[3] = {0., 0., 0.};
3080  double world[3] = {0., 0., 0.};
3081  TPC.LocalToWorld(local, world);
3082  // reduce the active area of the TPC by a bit to be consistent with FillWireHitRange
3083  if (pos[0] < world[0] - tcc.geom->DetHalfWidth(tpcid) + abit) continue;
3084  if (pos[0] > world[0] + tcc.geom->DetHalfWidth(tpcid) - abit) continue;
3085  if (pos[1] < world[1] - tcc.geom->DetHalfHeight(tpcid) + abit) continue;
3086  if (pos[1] > world[1] + tcc.geom->DetHalfHeight(tpcid) - abit) continue;
3087  if (pos[2] < world[2] - tcc.geom->DetLength(tpcid) / 2 + abit) continue;
3088  if (pos[2] > world[2] + tcc.geom->DetLength(tpcid) / 2 - abit) continue;
3089  inTPCID = tpcid;
3090  return true;
3091  } // tpcid
3092  return false;
3093  } // InsideTPC
geo::Length_t DetHalfWidth(geo::TPCID const &tpcid) const
Returns the half width of the active volume of the specified TPC.
TCConfig tcc
Definition: DataStructs.cxx:9
Geometry information for a single TPC.
Definition: TPCGeo.h:38
BEGIN_PROLOG TPC
IteratorBox< TPC_id_iterator,&GeometryCore::begin_TPC_id,&GeometryCore::end_TPC_id > IterateTPCIDs() const
Enables ranged-for loops on all TPC IDs of the detector.
then local
geo::Length_t DetHalfHeight(geo::TPCID const &tpcid) const
Returns the half height of the active volume of the specified TPC.
geo::Length_t DetLength(geo::TPCID const &tpcid) const
Returns the length of the active volume of the specified TPC.
const geo::GeometryCore * geom
Definition: DataStructs.h:576
The data type to uniquely identify a TPC.
Definition: geo_types.h:386
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
void LocalToWorld(const double *tpc, double *world) const
Transform point from local TPC frame to world frame.
Definition: TPCGeo.h:563
bool tca::InTrajOK ( TCSlice &  slc,
std::string  someText 
)

Definition at line 1276 of file Utils.cxx.

1277  {
1278  // Check slc.tjs -> InTraj associations
1279 
1280  unsigned short tID;
1281  unsigned int iht;
1282  unsigned short itj = 0;
1283  std::vector<unsigned int> tHits;
1284  std::vector<unsigned int> atHits;
1285  for (auto& tj : slc.tjs) {
1286  // ignore abandoned trajectories
1287  if (tj.AlgMod[kKilled]) continue;
1288  tID = tj.ID;
1289  tHits = PutTrajHitsInVector(tj, kUsedHits);
1290  if (tHits.size() < 2) continue;
1291  std::sort(tHits.begin(), tHits.end());
1292  atHits.clear();
1293  for (iht = 0; iht < slc.slHits.size(); ++iht) {
1294  if (slc.slHits[iht].InTraj == tID) atHits.push_back(iht);
1295  } // iht
1296  if (atHits.size() < 2) continue;
1297  if (!std::equal(tHits.begin(), tHits.end(), atHits.begin())) {
1298  mf::LogVerbatim myprt("TC");
1299  myprt << someText << " ChkInTraj failed: inTraj - UseHit mis-match for T" << tID
1300  << " tj.WorkID " << tj.WorkID << " atHits size " << atHits.size() << " tHits size "
1301  << tHits.size() << " in CTP " << tj.CTP << "\n";
1302  myprt << "AlgMods: ";
1303  for (unsigned short ib = 0; ib < AlgBitNames.size(); ++ib)
1304  if (tj.AlgMod[ib]) myprt << " " << AlgBitNames[ib];
1305  myprt << "\n";
1306  myprt << "index inTraj UseHit \n";
1307  for (iht = 0; iht < atHits.size(); ++iht) {
1308  myprt << "iht " << iht << " " << PrintHit(slc.slHits[atHits[iht]]);
1309  if (iht < tHits.size()) myprt << " " << PrintHit(slc.slHits[tHits[iht]]);
1310  if (atHits[iht] != tHits[iht]) myprt << " <<< " << atHits[iht] << " != " << tHits[iht];
1311  myprt << "\n";
1312  } // iht
1313  if (tHits.size() > atHits.size()) {
1314  for (iht = atHits.size(); iht < atHits.size(); ++iht) {
1315  myprt << "atHits " << iht << " " << PrintHit(slc.slHits[atHits[iht]]) << "\n";
1316  } // iht
1317  PrintTrajectory("CIT", slc, tj, USHRT_MAX);
1318  } // tHit.size > atHits.size()
1319  return false;
1320  }
1321  // check the VtxID
1322  for (unsigned short end = 0; end < 2; ++end) {
1323  if (tj.VtxID[end] > slc.vtxs.size()) {
1324  mf::LogVerbatim("TC") << someText << " ChkInTraj: Bad VtxID " << tj.ID;
1325  tj.AlgMod[kKilled] = true;
1326  return false;
1327  }
1328  } // end
1329  ++itj;
1330  } // tj
1331  return true;
1332 
1333  } // InTrajOK
std::vector< unsigned int > PutTrajHitsInVector(const Trajectory &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2754
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:6195
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6516
bool equal(double a, double b)
Comparison tolerance, in centimeters.
unsigned short tca::IsCloseToVertex ( const TCSlice &  slc,
const VtxStore &  inVx2 
)

Definition at line 2894 of file TCVertex.cxx.

2895  {
2896  // Returns the ID of a 2D vertex having the minimum pull < user-specified cut
2897 
2898  float minPull = tcc.vtx2DCuts[3];
2899  unsigned short imBest = 0;
2900  for (auto& vx2 : slc.vtxs) {
2901  if (vx2.CTP != inVx2.CTP) continue;
2902  if (vx2.ID <= 0) continue;
2903  float pull = VertexVertexPull(slc, inVx2, vx2);
2904  if (pull < minPull) {
2905  minPull = pull;
2906  imBest = vx2.ID;
2907  }
2908  } // vx2
2909  return imBest;
2910  } // IsCloseToVertex
TCConfig tcc
Definition: DataStructs.cxx:9
float VertexVertexPull(const TCSlice &slc, const Vtx3Store &vx1, const Vtx3Store &vx2)
Definition: TCVertex.cxx:1887
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:550
unsigned short tca::IsCloseToVertex ( const TCSlice &  slc,
const Vtx3Store &  vx3 
)

Definition at line 2914 of file TCVertex.cxx.

2915  {
2916  // Returns the ID of a 3D vertex having the minimum pull < user-specified cut
2917 
2918  float minPull = tcc.vtx3DCuts[1];
2919  unsigned short imBest = 0;
2920  for (auto& oldvx3 : slc.vtx3s) {
2921  if (oldvx3.ID == 0) continue;
2922  if (std::abs(oldvx3.X - vx3.X) > tcc.vtx3DCuts[0]) continue;
2923  float pull = VertexVertexPull(slc, vx3, oldvx3);
2924  if (pull < minPull) {
2925  minPull = pull;
2926  imBest = oldvx3.ID;
2927  }
2928  } // oldvx3
2929  return imBest;
2930 
2931  } // IsCloseToVertex
std::vector< float > vtx3DCuts
2D vtx -&gt; 3D vtx matching cuts
Definition: DataStructs.h:551
TCConfig tcc
Definition: DataStructs.cxx:9
T abs(T value)
float VertexVertexPull(const TCSlice &slc, const Vtx3Store &vx1, const Vtx3Store &vx2)
Definition: TCVertex.cxx:1887
bool tca::IsGhost ( TCSlice &  slc,
Trajectory &  tj 
)

Definition at line 2865 of file StepUtils.cxx.

2866  {
2867  // Sees if trajectory tj shares many hits with another trajectory and if so merges them.
2868 
2869  if(!tcc.useAlg[kUseGhostHits]) return false;
2870  // ensure that tj is not a saved trajectory
2871  if(tj.ID > 0) return true;
2872  // or an already killed trajectory
2873  if(tj.AlgMod[kKilled]) return true;
2874  if(tj.Pts.size() < 3) return false;
2875  if(tj.Strategy[kStiffEl]) return false;
2876 
2877  // vectors of traj IDs, and the occurrence count
2878  std::vector<int> tID;
2879  std::vector<unsigned short> tCnt;
2880 
2881  unsigned short hitCnt = 0;
2882  unsigned short nAvailable = 0;
2883  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2884  for(unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
2885  // ignore hits used by this trajectory
2886  if(tj.Pts[ipt].UseHit[ii]) {
2887  ++hitCnt;
2888  continue;
2889  }
2890  unsigned int iht = tj.Pts[ipt].Hits[ii];
2891  if(slc.slHits[iht].InTraj > 0 && (unsigned int)slc.slHits[iht].InTraj <= slc.tjs.size()) {
2892  int tjid = slc.slHits[iht].InTraj;
2893  unsigned short indx;
2894  for(indx = 0; indx < tID.size(); ++indx) if(tID[indx] == tjid) break;
2895  if(indx == tID.size()) {
2896  tID.push_back(tjid);
2897  tCnt.push_back(1);
2898  } else {
2899  ++tCnt[indx];
2900  }
2901  } else {
2902  ++nAvailable;
2903  }
2904  } // ii
2905  } // ipt
2906 
2907  // Call it a ghost if > 1/3 of the hits are used by another trajectory
2908  hitCnt /= 3;
2909  int oldTjID = INT_MAX;
2910 
2911  if(tcc.dbgStp) {
2912  mf::LogVerbatim myprt("TC");
2913  myprt<<"IsGhost tj hits size cut "<<hitCnt<<" tID_tCnt";
2914  for(unsigned short ii = 0; ii < tCnt.size(); ++ii) myprt<<" "<<tID[ii]<<"_"<<tCnt[ii];
2915  myprt<<"\nAvailable hits "<<nAvailable;
2916  } // prt
2917 
2918  for(unsigned short ii = 0; ii < tCnt.size(); ++ii) {
2919  if(tCnt[ii] > hitCnt) {
2920  oldTjID = tID[ii];
2921  hitCnt = tCnt[ii];
2922  }
2923  } // ii
2924  if(oldTjID == INT_MAX) return false;
2925  int oldTjIndex = oldTjID - 1;
2926 
2927  // See if this looks like a short delta-ray on a long muon
2928  Trajectory& oTj = slc.tjs[oldTjIndex];
2929  if(oTj.PDGCode == 13 && hitCnt < 0.1 * oTj.Pts.size()) return false;
2930 
2931  // See if there are gaps in this trajectory indicating that it is really a ghost and not
2932  // just a crossing trajectory
2933  // find the range of wires spanned by oTj
2934  int wire0 = INT_MAX;
2935  int wire1 = 0;
2936  for(auto& otp : oTj.Pts) {
2937  int wire = std::nearbyint(otp.Pos[0]);
2938  if(wire < wire0) wire0 = wire;
2939  if(wire > wire1) wire1 = wire;
2940  } // tp
2941 
2942  int nwires = wire1 - wire0 + 1;
2943  std::vector<float> oTjPos1(nwires, -1);
2944  unsigned short nMissedWires = 0;
2945  for(unsigned short ipt = oTj.EndPt[0]; ipt <= oTj.EndPt[1]; ++ipt) {
2946  if(oTj.Pts[ipt].Chg == 0) continue;
2947  int wire = std::nearbyint(oTj.Pts[ipt].Pos[0]);
2948  int indx = wire - wire0;
2949  if(indx < 0 || indx > nwires - 1) continue;
2950  oTjPos1[indx] = oTj.Pts[ipt].Pos[1];
2951  ++nMissedWires;
2952  } // ipt
2953  // count the number of ghost TPs
2954  unsigned short ngh = 0;
2955  // and the number with Delta > 0 relative to oTj
2956  unsigned short nghPlus = 0;
2957  // keep track of the first point and last point appearance of oTj
2958  unsigned short firstPtInoTj = USHRT_MAX;
2959  unsigned short lastPtInoTj = 0;
2960  TrajPoint tp = tj.Pts[tj.EndPt[0]];
2961  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2962  if(tj.Pts[ipt].Chg > 0) {
2963  tp = tj.Pts[ipt];
2964  continue;
2965  }
2966  int wire = std::nearbyint(tj.Pts[ipt].Pos[0]);
2967  int indx = wire - wire0;
2968  if(indx < 0 || indx > nwires - 1) continue;
2969  if(oTjPos1[indx] > 0) {
2970  // ensure that the hits in this tp are used in oTj
2971  bool HitInoTj = false;
2972  for(unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
2973  unsigned int iht = tj.Pts[ipt].Hits[ii];
2974  if(slc.slHits[iht].InTraj == oldTjID) HitInoTj = true;
2975  } // ii
2976  if(HitInoTj) {
2977  ++ngh;
2978  MoveTPToWire(tp, tj.Pts[ipt].Pos[0]);
2979  if(tp.Pos[1] > oTjPos1[indx]) ++nghPlus;
2980  if(firstPtInoTj == USHRT_MAX) firstPtInoTj = ipt;
2981  lastPtInoTj = ipt;
2982  }
2983  } // oTjHasChg[indx]
2984  } // ipt
2985 
2986  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Number of missed wires in oTj gaps "<<nMissedWires<<" Number of ghost hits in these gaps "<<ngh<<" nghPlus "<<nghPlus<<" cut "<<0.2 * nMissedWires;
2987 
2988  if(ngh < 0.2 * nMissedWires) return false;
2989  if(firstPtInoTj > lastPtInoTj) return false;
2990 
2991  // require all of the tj TPs to be on either the + or - side of the oTj trajectory
2992  if(!(nghPlus > 0.8 * ngh || nghPlus < 0.2 * ngh) ) return false;
2993 
2994  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Trajectory is a ghost of "<<oldTjID<<" first point in oTj "<<firstPtInoTj<<" last point "<<lastPtInoTj;
2995 
2996  // unset all of the shared hits
2997  for(unsigned short ipt = firstPtInoTj; ipt <= lastPtInoTj; ++ipt) {
2998  if(tj.Pts[ipt].Chg == 0) continue;
2999  UnsetUsedHits(slc, tj.Pts[ipt]);
3000  if(tcc.dbgStp) PrintTrajectory("IG", slc, tj, ipt);
3001  }
3002  // see how many points are left at the end
3003  ngh = 0;
3004  for(unsigned short ipt = lastPtInoTj; ipt <= tj.EndPt[1]; ++ipt) {
3005  if(tj.Pts[ipt].Chg > 0) ++ngh;
3006  } // ipt
3007  // clobber those too?
3008  if(ngh > 0 && ngh < tcc.minPts[tj.Pass]) {
3009  for(unsigned short ipt = lastPtInoTj; ipt <= tj.EndPt[1]; ++ipt) {
3010  if(tj.Pts[ipt].Chg > 0) UnsetUsedHits(slc, tj.Pts[ipt]);
3011  } // ipt
3012  }
3013  SetEndPoints(tj);
3014  tj.Pts.resize(tj.EndPt[1] + 1);
3015  slc.tjs[oldTjIndex].AlgMod[kUseGhostHits] = true;
3016  TrimEndPts("IG", slc, tj, tcc.qualityCuts, tcc.dbgStp);
3017  if(tj.AlgMod[kKilled]) {
3018  tj.IsGood = false;
3019  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Failed quality cuts";
3020  return true;
3021  }
3022  tj.MCSMom = MCSMom(slc, tj);
3023  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" New tj size "<<tj.Pts.size();
3024  return true;
3025 
3026  } // IsGhost
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3468
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3413
std::vector< float > qualityCuts
Min points/wire, min consecutive pts after a gap.
Definition: DataStructs.h:563
TCConfig tcc
Definition: DataStructs.cxx:9
void PrintTrajectory(std::string someText, const TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:6195
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1075
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
std::vector< unsigned short > minPts
min number of Pts required to make a trajectory
Definition: DataStructs.h:566
void TrimEndPts(std::string fcnLabel, TCSlice &slc, Trajectory &tj, const std::vector< float > &fQualityCuts, bool prt)
Definition: Utils.cxx:1600
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
use the stiff electron strategy
Definition: DataStructs.h:501
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2831
bool tca::IsGhost ( TCSlice &  slc,
std::vector< unsigned int > &  tHits 
)

Definition at line 3029 of file StepUtils.cxx.

3030  {
3031  // Called by FindJunkTraj to see if the passed hits are close to an existing
3032  // trajectory and if so, they will be used in that other trajectory
3033 
3034  if(!tcc.useAlg[kUseGhostHits]) return false;
3035 
3036  if(tHits.size() < 2) return false;
3037 
3038  bool prt = (tcc.dbgStp || tcc.dbgAlg[kUseGhostHits]);
3039 
3040  // find all nearby hits
3041  std::vector<unsigned int> hitsInMuliplet, nearbyHits;
3042  for(auto iht : tHits) {
3043  GetHitMultiplet(slc, iht, hitsInMuliplet, false);
3044  // prevent double counting
3045  for(auto mht : hitsInMuliplet) {
3046  if(std::find(nearbyHits.begin(), nearbyHits.end(), mht) == nearbyHits.end()) {
3047  nearbyHits.push_back(mht);
3048  }
3049  } // mht
3050  } // iht
3051 
3052  // vectors of traj IDs, and the occurrence count
3053  std::vector<unsigned int> tID, tCnt;
3054  for(auto iht : nearbyHits) {
3055  if(slc.slHits[iht].InTraj <= 0) continue;
3056  unsigned int tid = slc.slHits[iht].InTraj;
3057  unsigned short indx = 0;
3058  for(indx = 0; indx < tID.size(); ++indx) if(tID[indx] == tid) break;
3059  if(indx == tID.size()) {
3060  tID.push_back(tid);
3061  tCnt.push_back(1);
3062  } else {
3063  ++tCnt[indx];
3064  }
3065  } // iht
3066  if(tCnt.empty()) return false;
3067 
3068  // Call it a ghost if > 50% of the hits are used by another trajectory
3069  unsigned short tCut = 0.5 * tHits.size();
3070  int tid = INT_MAX;
3071 
3072  if(prt) {
3073  mf::LogVerbatim myprt("TC");
3074  myprt<<"IsGhost tHits size "<<tHits.size()<<" cut fraction "<<tCut<<" tID_tCnt";
3075  for(unsigned short ii = 0; ii < tCnt.size(); ++ii) myprt<<" "<<tID[ii]<<"_"<<tCnt[ii];
3076  } // prt
3077 
3078  for(unsigned short ii = 0; ii < tCnt.size(); ++ii) {
3079  if(tCnt[ii] > tCut) {
3080  tid = tID[ii];
3081  break;
3082  }
3083  } // ii
3084  if(tid > (int)slc.tjs.size()) return false;
3085 
3086  if(prt) mf::LogVerbatim("TC")<<" is ghost of trajectory "<<tid;
3087 
3088  // Use all hits in tHits that are found in itj
3089  for(auto& tp : slc.tjs[tid - 1].Pts) {
3090  for(unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3091  unsigned int iht = tp.Hits[ii];
3092  if(slc.slHits[iht].InTraj != 0) continue;
3093  for(unsigned short jj = 0; jj < tHits.size(); ++jj) {
3094  unsigned int tht = tHits[jj];
3095  if(tht != iht) continue;
3096  tp.UseHit[ii] = true;
3097  slc.slHits[iht].InTraj = tid;
3098  break;
3099  } // jj
3100  } // ii
3101  } // tp
3102  slc.tjs[tid - 1].AlgMod[kUseGhostHits] = true;
3103  return true;
3104 
3105  } // IsGhost
TCConfig tcc
Definition: DataStructs.cxx:9
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
void GetHitMultiplet(const TCSlice &slc, unsigned int theHit, std::vector< unsigned int > &hitsInMultiplet, bool useLongPulseHits)
Definition: StepUtils.cxx:1415
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:587
bool tca::IsShowerLike ( TCSlice &  slc,
const std::vector< int >  TjIDs 
)

Definition at line 1909 of file TCShower.cxx.

1910  {
1911  // Vote for the list of Tjs (assumed associated with a PFParticle) being shower-like
1912  if (TjIDs.empty()) return false;
1913  unsigned short cnt = 0;
1914  for (auto tid : TjIDs) {
1915  if (tid <= 0 || tid > (int)slc.tjs.size()) continue;
1916  if (slc.tjs[tid - 1].AlgMod[kShowerLike] > 0) ++cnt;
1917  } // tjid
1918  return (cnt > 1);
1919  } // IsInShower
void tca::KillPoorVertices ( TCSlice &  slc)

Definition at line 2174 of file TCVertex.cxx.

2175  {
2176  // kill 2D vertices that have low score and are not attached to a high-score 3D vertex
2177  if (slc.vtxs.empty()) return;
2178  for (auto& vx : slc.vtxs) {
2179  if (vx.ID == 0) continue;
2180  if (vx.Score > tcc.vtx2DCuts[7]) continue;
2181  if (vx.Vx3ID > 0) {
2182  auto& vx3 = slc.vtx3s[vx.Vx3ID - 1];
2183  if (vx3.Primary) continue;
2184  if (slc.vtx3s[vx.Vx3ID - 1].Score >= tcc.vtx2DCuts[7]) continue;
2185  }
2186  MakeVertexObsolete("KPV", slc, vx, false);
2187  } // vx
2188 
2189  } // KillPoorVertices
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:2726
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:550
void tca::KillVerticesInShower ( std::string  inFcnLabel,
TCSlice &  slc,
ShowerStruct &  ss,
bool  prt 
)

Definition at line 711 of file TCShower.cxx.

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

Definition at line 3056 of file Utils.cxx.

3064  {
3065  // returns the significance of a potential kink between the ends of two trajectories. This
3066  // is used when deciding to either merge trajectories or make a vertex between them
3067 
3068  if (tj1.CTP != tj2.CTP) return -1;
3069  if (end1 > 1 || end2 > 1) return -1;
3070 
3071  // construct a temporary trajectory to allow using the standard KinkSignificance function.
3072  // The first nPtsFit points are comprised of TPs from tj1 and the last nPtsFits points are from tj2
3073  Trajectory tj;
3074  tj.ID = 666;
3075  tj.CTP = tj1.CTP;
3076  short dir = 1;
3077  if (end1 == 1) dir = -1;
3078  unsigned short cnt = 0;
3079  // add tj1 points to the trajectory
3080  for (short ii = 0; ii < (short)tj1.Pts.size(); ++ii) {
3081  short ipt = tj1.EndPt[end1] + dir * ii;
3082  if (ipt < 0) break;
3083  if (ipt >= (short)tj1.Pts.size()) break;
3084  auto& tp = tj1.Pts[ipt];
3085  if (tp.Chg <= 0) continue;
3086  tj.Pts.push_back(tp);
3087  ++cnt;
3088  if (cnt == nPtsFit + 1) break;
3089  } // ipt
3090  if (cnt < nPtsFit) return -1;
3091  // add tj2 points to the trajectory
3092  dir = 1;
3093  if (end2 == 1) dir = -1;
3094  cnt = 0;
3095  for (short ii = 0; ii < (short)tj2.Pts.size(); ++ii) {
3096  short ipt = tj2.EndPt[end2] + dir * ii;
3097  if (ipt < 0) break;
3098  if (ipt >= (short)tj2.Pts.size()) break;
3099  auto& tp = tj2.Pts[ipt];
3100  if (tp.Chg <= 0) continue;
3101  tj.Pts.push_back(tp);
3102  ++cnt;
3103  if (cnt == nPtsFit + 1) break;
3104  } // ipt
3105  tj.EndPt[0] = 0;
3106  tj.EndPt[1] = tj.Pts.size() - 1;
3107  return KinkSignificance(slc, tj, nPtsFit, nPtsFit, useChg, prt);
3108  } // KinkSignificance
float KinkSignificance(TCSlice &slc, Trajectory &tj1, unsigned short end1, Trajectory &tj2, unsigned short end2, unsigned short nPtsFit, bool useChg, bool prt)
Definition: Utils.cxx:3056
tuple dir
Definition: dropbox.py:28
float tca::KinkSignificance ( TCSlice &  slc,
Trajectory &  tj,
unsigned short  kinkPt,
unsigned short  nPtsFit,
bool  useChg,
bool  prt 
)

Definition at line 3112 of file Utils.cxx.

3118  {
3119  // returns a kink significance in the trajectory at the presumed kink point kinkPt
3120  // using angle and (optional) charge asymmetry. The returned value is negative if there is insufficient
3121  // information.
3122  //
3123  // Check the limits
3124  if (kinkPt < tj.EndPt[0] + 2) return -1;
3125  if (kinkPt > tj.EndPt[1] - 2) return -1;
3126 
3127  // This function requires knowledge of the DOF of the line fit
3128  if (nPtsFit < 3) return -1;
3129  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
3130  // need enough points to do a fit on each sideof the presumed kink point
3131  if (npwc < 2 * nPtsFit + 1) return -1;
3132 
3133  // The hit charge uncertainty is 0.12 - 0.15 (neglecting 2ndry interactions) for hadrons.
3134  // This translates into an error on the charge
3135  // asymmetry of about 0.07, or about 0.6 * the charge uncertainty
3136  double chgRMS = 0.07;
3137  // An additional contribution to the rms is the dependence on the DOF of the fit.
3138  // Apply a factor to the significance similar to (and simpler than) the Students t-distribution
3139  // This will increase the angle and charge error rms by 1.3 (1.05) when nPtsFit = 3 (8)
3140  double tFactor = 1 + 0.3 / double(nPtsFit - 2);
3141  chgRMS *= tFactor;
3142 
3143  // Fit the trajectory direction on the + side
3144  short fitDir = 1;
3145  TrajPoint tpPos;
3146  FitTraj(slc, tj, kinkPt, nPtsFit, fitDir, tpPos);
3147  if (tpPos.FitChi > 900) return -1;
3148  // repeat the trajectory fit on the - side
3149  fitDir = -1;
3150  TrajPoint tpNeg;
3151  FitTraj(slc, tj, kinkPt, nPtsFit, fitDir, tpNeg);
3152  if (tpNeg.FitChi > 900) return -1;
3153  double angErr = tpNeg.AngErr;
3154  if (tpPos.AngErr > angErr) angErr = tpPos.AngErr;
3155  angErr *= tFactor;
3156  double dang = DeltaAngle(tpPos.Ang, tpNeg.Ang);
3157  double dangSig = dang / angErr;
3158 
3159  double chgAsym = 0;
3160  double chgSig = 0;
3161  if (useChg) {
3162  // Sum the charge Neg and Pos, excluding the kinkPt
3163  double chgNeg = 0;
3164  unsigned short cntNeg = 0;
3165  for (unsigned short ipt = kinkPt - 1; ipt >= tj.EndPt[0]; --ipt) {
3166  auto& tp = tj.Pts[ipt];
3167  if (tp.Chg <= 0) continue;
3168  chgNeg += tp.Chg;
3169  ++cntNeg;
3170  if (cntNeg == nPtsFit) break;
3171  if (ipt == 0) break;
3172  } // ipt
3173  if (cntNeg != nPtsFit) {
3174  if (prt) mf::LogVerbatim("TC") << " KL: Bad cntNeg " << cntNeg << " != " << nPtsFit;
3175  return -1;
3176  }
3177  // now Pos
3178  double chgPos = 0;
3179  unsigned short cntPos = 0;
3180  for (unsigned short ipt = kinkPt + 1; ipt <= tj.EndPt[1]; ++ipt) {
3181  auto& tp = tj.Pts[ipt];
3182  if (tp.Chg <= 0) continue;
3183  chgPos += tp.Chg;
3184  ++cntPos;
3185  if (cntPos == nPtsFit) break;
3186  } // ipt
3187  if (cntPos != nPtsFit) {
3188  if (prt) mf::LogVerbatim("TC") << " KL: Bad cntPos " << cntPos << " != " << nPtsFit;
3189  return -1;
3190  }
3191  chgNeg /= (float)nPtsFit;
3192  chgPos /= (float)nPtsFit;
3193  // The charge asymmetry varies between 0 and 1;
3194  chgAsym = std::abs(chgPos - chgNeg) / (chgPos + chgNeg);
3195  // calculate the charge asymmetry significance
3196  chgSig = chgAsym / chgRMS;
3197  } // useChg
3198  double kinkSig = sqrt(dangSig * dangSig + chgSig * chgSig);
3199 
3200  if (prt) {
3201  mf::LogVerbatim myprt("TC");
3202  myprt << "KL: T" << tj.ID << " kinkPt " << PrintPos(slc, tj.Pts[kinkPt]);
3203  myprt << " nPtsFit " << nPtsFit;
3204  myprt << " dang " << std::fixed << std::setprecision(3) << dang;
3205  myprt << std::fixed << std::setprecision(3) << " angErr " << angErr;
3206  myprt << std::setprecision(2) << " sig " << dangSig;
3207  myprt << " chgAsym " << chgAsym;
3208  myprt << " chgSig " << chgSig;
3209  myprt << " kinkSig " << kinkSig;
3210  }
3211  return (float)kinkSig;
3212  } // KinkSignificance
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:2540
T abs(T value)
void FitTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:808
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2116
void tca::LastEndMerge ( TCSlice &  slc,
CTP_t  inCTP 
)

Definition at line 3108 of file StepUtils.cxx.

3109  {
3110  // last ditch attempt to merge long straight broken trajectories by averaging
3111  // all points in the trajectory and applying tight angle and separation cuts.
3112  if(slc.tjs.size() < 2) return;
3113  if(!tcc.useAlg[kLastEndMerge]) return;
3114 
3115  bool prt = tcc.dbgAlg[kLastEndMerge];
3116 
3117  // create an averaged TP for each long Trajectory
3118  std::vector<TrajPoint> tjTP;
3119  for(auto& tj : slc.tjs) {
3120  if(tj.AlgMod[kKilled]) continue;
3121  if(tj.CTP != inCTP) continue;
3122  if(tj.Pts.size() < 10) continue;
3123  if(tj.MCSMom < 100) continue;
3124  auto tjtp = CreateTPFromTj(slc, tj);
3125  if(tjtp.Chg < 0) continue;
3126  tjTP.push_back(tjtp);
3127  } // tj
3128  if(tjTP.size() < 2) return;
3129 
3130  if(prt) {
3131  mf::LogVerbatim myprt("TC");
3132  myprt<<"inside LastEndMerge slice "<<slices.size()-1<<" inCTP "<<inCTP<<" tjTPs";
3133  for(auto& tjtp : tjTP) myprt<<" T"<<tjtp.Step;
3134  }
3135 
3136  for(unsigned short pt1 = 0; pt1 < tjTP.size() - 1; ++pt1) {
3137  auto& tp1 = tjTP[pt1];
3138  auto& tj1 = slc.tjs[tp1.Step - 1];
3139  if(tj1.AlgMod[kKilled]) continue;
3140  for(unsigned short pt2 = pt1 + 1; pt2 < tjTP.size(); ++pt2) {
3141  auto& tp2 = tjTP[pt2];
3142  auto& tj2 = slc.tjs[tp2.Step - 1];
3143  if(tj2.AlgMod[kKilled]) continue;
3144  float dang = DeltaAngle(tp1.Ang, tp2.Ang);
3145  // make an angle cut
3146  if(prt && dang < 0.5) mf::LogVerbatim("TC")<<" T"<<tj1.ID<<" T"<<tj2.ID<<" dang "<<dang;
3147  if(dang > 0.2) continue;
3148  // and an impact parameter cut
3149  unsigned short ipt1, ipt2;
3150  float ip12 = PointTrajDOCA(slc, tp1.Pos[0], tp1.Pos[1], tp2);
3151  float ip21 = PointTrajDOCA(slc, tp2.Pos[0], tp2.Pos[1], tp1);
3152  if(prt) mf::LogVerbatim("TC")<<" ip12 "<<ip12<<" ip21 "<<ip21;
3153  if(ip12 > 15 && ip21 > 15) continue;
3154  float minSep = 100;
3155  // find the separation considering dead wires
3156  TrajTrajDOCA(slc, tj1, tj2, ipt1, ipt2, minSep, false);
3157  if(minSep == 100) continue;
3158  if(ipt1 >= tj1.Pts.size() || ipt2 >= tj2.Pts.size()) continue;
3159  float dwc = DeadWireCount(slc, tj1.Pts[ipt1], tj2.Pts[ipt2]);
3160  if(prt) mf::LogVerbatim("TC")<<" minSep "<<minSep<<" dwc "<<dwc;
3161  minSep -= dwc;
3162  if(minSep > 5) continue;
3163  // finally require that the proximate points are close to the ends
3164  float sep10 = PosSep(tj1.Pts[ipt1].Pos, tj1.Pts[tj1.EndPt[0]].Pos);
3165  float sep11 = PosSep(tj1.Pts[ipt1].Pos, tj1.Pts[tj1.EndPt[1]].Pos);
3166  if(sep10 > 5 && sep11 > 5) continue;
3167  unsigned short end1 = 0;
3168  if(sep11 < sep10) end1 = 1;
3169  float sep20 = PosSep(tj2.Pts[ipt2].Pos, tj2.Pts[tj2.EndPt[0]].Pos);
3170  float sep21 = PosSep(tj2.Pts[ipt2].Pos, tj2.Pts[tj2.EndPt[1]].Pos);
3171  if(sep20 > 5 && sep21 > 5) continue;
3172  unsigned short end2 = 0;
3173  if(sep21 < sep20) end2 = 1;
3174  // don't merge if there is a kink
3175  if(tj1.EndFlag[end1][kAtKink] || tj2.EndFlag[end2][kAtKink]) continue;
3176  if(prt) {
3177  mf::LogVerbatim myprt("TC");
3178  myprt<<"LEM: T"<<tj1.ID<<"_"<<PrintPos(slc, tp1);
3179  if(tj1.VtxID[end1] > 0) myprt<<"->2V"<<tj1.VtxID[end1];
3180  myprt<<" T"<<tj2.ID<<"_"<<PrintPos(slc, tp2);
3181  if(tj2.VtxID[end2] > 0) myprt<<"->2V"<<tj2.VtxID[end2];
3182  myprt<<" dang "<<std::setprecision(2)<<dang<<" ip12 "<<ip12;
3183  myprt<<" ip21 "<<ip21;
3184  myprt<<" minSep "<<minSep;
3185  myprt<<" end sep1 "<<sep10<<" "<<sep11;
3186  myprt<<" end sep2 "<<sep20<<" "<<sep21;
3187  } // prt
3188  if(tj1.VtxID[end1] > 0) {
3189  auto& vx2 = slc.vtxs[tj1.VtxID[end1] - 1];
3190  MakeVertexObsolete("LEM", slc, vx2, true);
3191  }
3192  if(tj2.VtxID[end2] > 0 && tj2.VtxID[end2] != tj1.VtxID[end1]) {
3193  auto& vx2 = slc.vtxs[tj2.VtxID[end2] - 1];
3194  MakeVertexObsolete("LEM", slc, vx2, true);
3195  }
3196  // remove Bragg flags
3197  tj1.EndFlag[end1][kBragg] = false;
3198  tj2.EndFlag[end2][kBragg] = false;
3199  unsigned int it1 = tj1.ID - 1;
3200  unsigned int it2 = tj2.ID - 1;
3201  if(!MergeAndStore(slc, it1, it2, tcc.dbgMrg)) continue;
3202  // set the AlgMod bit
3203  auto& ntj = slc.tjs[slc.tjs.size() - 1];
3204  ntj.AlgMod[kLastEndMerge] = true;
3205  // create a tp for this tj and add it to the list
3206  auto tjtp = CreateTPFromTj(slc, ntj);
3207  if(tjtp.Chg < 0) continue;
3208  if(prt) mf::LogVerbatim("TC")<<" added T"<<ntj.ID<<" to the merge list";
3209  tjTP.push_back(tjtp);
3210  break;
3211  } // pt1
3212  } // pt1
3213 
3214  } // LastEndMerge
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:2726
TCConfig tcc
Definition: DataStructs.cxx:9
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2572
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:2540
TrajPoint CreateTPFromTj(TCSlice &slc, const Trajectory &tj)
Definition: StepUtils.cxx:3217
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2141
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
bool MergeAndStore(TCSlice &slc, unsigned int itj1, unsigned int itj2, bool doPrt)
Definition: Utils.cxx:4664
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2565
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:587
bool TrajTrajDOCA(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2460
float tca::Length ( const PFPStruct &  pfp)

Definition at line 3304 of file PFPUtils.cxx.

3305  {
3306  if (pfp.TP3Ds.empty()) return 0;
3307  return PosSep(pfp.TP3Ds[0].Pos, pfp.TP3Ds[pfp.TP3Ds.size() - 1].Pos);
3308  } // Length
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2565
bool tca::LineLineIntersect ( Point3_t  p1,
Point3_t  p2,
Point3_t  p3,
Point3_t  p4,
Point3_t &  intersect,
float &  doca 
)

Definition at line 3133 of file PFPUtils.cxx.

3139  {
3140  /*
3141  Calculate the line segment PaPb that is the shortest route between
3142  two lines P1P2 and P3P4. Calculate also the values of mua and mub where
3143  Pa = P1 + mua (P2 - P1)
3144  Pb = P3 + mub (P4 - P3)
3145  Return FALSE if no solution exists.
3146  http://paulbourke.net/geometry/pointlineplane/
3147  */
3148 
3149  Point3_t p13, p43, p21;
3150  double d1343, d4321, d1321, d4343, d2121;
3151  double numer, denom;
3152  constexpr double EPS = std::numeric_limits<double>::min();
3153 
3154  p13[0] = p1[0] - p3[0];
3155  p13[1] = p1[1] - p3[1];
3156  p13[2] = p1[2] - p3[2];
3157  p43[0] = p4[0] - p3[0];
3158  p43[1] = p4[1] - p3[1];
3159  p43[2] = p4[2] - p3[2];
3160  if (std::abs(p43[0]) < EPS && std::abs(p43[1]) < EPS && std::abs(p43[2]) < EPS) return (false);
3161  p21[0] = p2[0] - p1[0];
3162  p21[1] = p2[1] - p1[1];
3163  p21[2] = p2[2] - p1[2];
3164  if (std::abs(p21[0]) < EPS && std::abs(p21[1]) < EPS && std::abs(p21[2]) < EPS) return (false);
3165 
3166  d1343 = p13[0] * p43[0] + p13[1] * p43[1] + p13[2] * p43[2];
3167  d4321 = p43[0] * p21[0] + p43[1] * p21[1] + p43[2] * p21[2];
3168  d1321 = p13[0] * p21[0] + p13[1] * p21[1] + p13[2] * p21[2];
3169  d4343 = p43[0] * p43[0] + p43[1] * p43[1] + p43[2] * p43[2];
3170  d2121 = p21[0] * p21[0] + p21[1] * p21[1] + p21[2] * p21[2];
3171 
3172  denom = d2121 * d4343 - d4321 * d4321;
3173  if (std::abs(denom) < EPS) return (false);
3174  numer = d1343 * d4321 - d1321 * d4343;
3175 
3176  double mua = numer / denom;
3177  double mub = (d1343 + d4321 * mua) / d4343;
3178 
3179  intersect[0] = p1[0] + mua * p21[0];
3180  intersect[1] = p1[1] + mua * p21[1];
3181  intersect[2] = p1[2] + mua * p21[2];
3182  Point3_t pb;
3183  pb[0] = p3[0] + mub * p43[0];
3184  pb[1] = p3[1] + mub * p43[1];
3185  pb[2] = p3[2] + mub * p43[2];
3186  doca = PosSep(intersect, pb);
3187  // average the closest points
3188  for (unsigned short xyz = 0; xyz < 3; ++xyz)
3189  intersect[xyz] += pb[xyz];
3190  for (unsigned short xyz = 0; xyz < 3; ++xyz)
3191  intersect[xyz] /= 2;
3192  return true;
3193  } // LineLineIntersect
std::array< double, 3 > Point3_t
Definition: DataStructs.h:41
T abs(T value)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2565
physics associatedGroupsWithLeft p1
bool tca::LongPulseHit ( const recob::Hit hit)

Definition at line 4452 of file Utils.cxx.

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

Definition at line 4027 of file Utils.cxx.

4031  {
4032  // A version to use when the 2D direction isn't required
4033  TrajPoint tp;
4034  tp.Pos = {{0, 0}};
4035  tp.Dir = {{0, 1}};
4036  tp.CTP = inCTP;
4037  geo::PlaneID planeID = DecodeCTP(inCTP);
4038 
4039  tp.Pos[0] = tcc.geom->WireCoordinate(pos[1], pos[2], planeID);
4040  tp.Pos[1] = detProp.ConvertXToTicks(pos[0], planeID) * tcc.unitsPerTick;
4041  return tp;
4042  } // MakeBareTP
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
const geo::GeometryCore * geom
Definition: DataStructs.h:576
geo::PlaneID DecodeCTP(CTP_t CTP)
auto const detProp
TrajPoint tca::MakeBareTP ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice &  slc,
const Point3_t &  pos,
const Vector3_t &  dir,
CTP_t  inCTP 
)

Definition at line 4046 of file Utils.cxx.

4051  {
4052  // Projects the space point defined by pos and dir into the CTP and returns
4053  // it in the form of a trajectory point. The TP Pos[0] is set to a negative
4054  // number if the point has an invalid wire position but doesn't return an
4055  // error if the position is on a dead wire. The projection of the direction
4056  // vector in CTP is stored in tp.Delta.
4057  TrajPoint tp;
4058  tp.Pos = {{-1, 0}};
4059  tp.Dir = {{0, 1}};
4060  tp.CTP = inCTP;
4061  geo::PlaneID planeID = DecodeCTP(inCTP);
4062 
4063  tp.Pos[0] = tcc.geom->WireCoordinate(pos[1], pos[2], planeID);
4064  tp.Pos[1] = detProp.ConvertXToTicks(pos[0], planeID) * tcc.unitsPerTick;
4065 
4066  // now find the direction if dir is defined
4067  if (dir[0] == 0 && dir[1] == 0 && dir[2] == 0) return tp;
4068 
4069  // Make a point at the origin and one 100 units away
4070  Point3_t ori3 = {{0.0, 0.0, 0.0}};
4071  Point3_t pos3 = {{100 * dir[0], 100 * dir[1], 100 * dir[2]}};
4072  // 2D position of ori3 and the pos3 projection
4073  std::array<double, 2> ori2;
4074  std::array<double, 2> pos2;
4075  std::array<double, 2> dir2;
4076  // the wire coordinates
4077  ori2[0] = tcc.geom->WireCoordinate(ori3[1], ori3[2], planeID);
4078  pos2[0] = tcc.geom->WireCoordinate(pos3[1], pos3[2], planeID);
4079  // the time coordinates
4080  ori2[1] = detProp.ConvertXToTicks(ori3[0], planeID) * tcc.unitsPerTick;
4081  pos2[1] = detProp.ConvertXToTicks(pos3[0], planeID) * tcc.unitsPerTick;
4082 
4083  dir2[0] = pos2[0] - ori2[0];
4084  dir2[1] = pos2[1] - ori2[1];
4085 
4086  double norm = sqrt(dir2[0] * dir2[0] + dir2[1] * dir2[1]);
4087  tp.Dir[0] = dir2[0] / norm;
4088  tp.Dir[1] = dir2[1] / norm;
4089  tp.Ang = atan2(dir2[1], dir2[0]);
4090  tp.Delta = norm / 100;
4091 
4092  // The Orth vectors are not unit normalized so we need to correct for this
4093  double w0 = tcc.geom->WireCoordinate(0, 0, planeID);
4094  // cosine-like component
4095  double cs = tcc.geom->WireCoordinate(1, 0, planeID) - w0;
4096  // sine-like component
4097  double sn = tcc.geom->WireCoordinate(0, 1, planeID) - w0;
4098  norm = sqrt(cs * cs + sn * sn);
4099  tp.Delta /= norm;
4100 
4101  // Stasb dt/dWire in DeltaRMS. This is used in PFPUtils/FitSection to find the
4102  // distance along a 3D line given the wire number in a plane
4103  tp.DeltaRMS = 100 / (pos2[0] - ori2[0]);
4104  return tp;
4105 
4106  } // MakeBareTP
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
std::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:472
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
const geo::GeometryCore * geom
Definition: DataStructs.h:576
auto norm(Vector const &v)
Return norm of the specified vector.
tuple dir
Definition: dropbox.py:28
geo::PlaneID DecodeCTP(CTP_t CTP)
auto const detProp
bool tca::MakeBareTrajPoint ( const TCSlice &  slc,
unsigned int  fromHit,
unsigned int  toHit,
TrajPoint &  tp 
)

Definition at line 4110 of file Utils.cxx.

4111  {
4112  if (fromHit > slc.slHits.size() - 1) return false;
4113  if (toHit > slc.slHits.size() - 1) return false;
4114  auto& fhit = (*evt.allHits)[slc.slHits[fromHit].allHitsIndex];
4115  auto& thit = (*evt.allHits)[slc.slHits[toHit].allHitsIndex];
4116  CTP_t tCTP = EncodeCTP(fhit.WireID());
4117  return MakeBareTrajPoint(slc,
4118  (float)fhit.WireID().Wire,
4119  fhit.PeakTime(),
4120  (float)thit.WireID().Wire,
4121  thit.PeakTime(),
4122  tCTP,
4123  tp);
4124 
4125  } // MakeBareTrajPoint
bool MakeBareTrajPoint(const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:4110
unsigned int CTP_t
Definition: DataStructs.h:47
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:52
TCEvent evt
Definition: DataStructs.cxx:8
bool tca::MakeBareTrajPoint ( const TCSlice &  slc,
float  fromWire,
float  fromTick,
float  toWire,
float  toTick,
CTP_t  tCTP,
TrajPoint &  tp 
)

Definition at line 4129 of file Utils.cxx.

4136  {
4137  tp.CTP = tCTP;
4138  tp.Pos[0] = fromWire;
4139  tp.Pos[1] = tcc.unitsPerTick * fromTick;
4140  tp.Dir[0] = toWire - fromWire;
4141  tp.Dir[1] = tcc.unitsPerTick * (toTick - fromTick);
4142  double norm = sqrt(tp.Dir[0] * tp.Dir[0] + tp.Dir[1] * tp.Dir[1]);
4143  if (norm == 0) return false;
4144  tp.Dir[0] /= norm;
4145  tp.Dir[1] /= norm;
4146  tp.Ang = atan2(tp.Dir[1], tp.Dir[0]);
4147  return true;
4148  } // MakeBareTrajPoint
TCConfig tcc
Definition: DataStructs.cxx:9
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
auto norm(Vector const &v)
Return norm of the specified vector.
bool tca::MakeBareTrajPoint ( const Point2_t &  fromPos,
const Point2_t &  toPos,
TrajPoint &  tpOut 
)

Definition at line 4152 of file Utils.cxx.

4153  {
4154  tpOut.Pos = fromPos;
4155  tpOut.Dir = PointDirection(fromPos, toPos);
4156  tpOut.Ang = atan2(tpOut.Dir[1], tpOut.Dir[0]);
4157  return true;
4158 
4159  } // MakeBareTrajPoint
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:2548
bool tca::MakeBareTrajPoint ( const TCSlice &  slc,
const TrajPoint &  tpIn1,
const TrajPoint &  tpIn2,
TrajPoint &  tpOut 
)

Definition at line 4163 of file Utils.cxx.

4167  {
4168  tpOut.CTP = tpIn1.CTP;
4169  tpOut.Pos = tpIn1.Pos;
4170  tpOut.Dir = PointDirection(tpIn1.Pos, tpIn2.Pos);
4171  tpOut.Ang = atan2(tpOut.Dir[1], tpOut.Dir[0]);
4172  return true;
4173  } // MakeBareTrajPoint
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:2548
void tca::MakeHaloTj ( TCSlice &  slc,
Trajectory &  muTj,
bool  prt 
)

Definition at line 47 of file Utils.cxx.

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

Definition at line 3868 of file StepUtils.cxx.

3869  {
3870  if(!tcc.useAlg[kJunkTj]) return false;
3871  // Make a crummy trajectory using the provided hits
3872 
3873  if(tHits.size() < 2) return false;
3874 
3875  bool prt = false;
3876  if(tcc.dbgAlg[kJunkTj]) {
3877  for(unsigned short ii = 0; ii < tHits.size(); ++ii) {
3878  if(slc.slHits[tHits[ii]].allHitsIndex == debug.Hit) {
3879  prt = true;
3880  break;
3881  }
3882  } // ii
3883  if(prt) std::cout<<"MakeJunkTraj found debug hit\n";
3884  } // tcc.dbgAlg[kJunkTj]
3885 
3886  // Start the trajectory using the first and last hits to
3887  // define a starting direction. Use the last pass settings
3888  Trajectory work;
3889  unsigned short pass = tcc.minPts.size() - 1;
3890  if(!StartTraj(slc, work, tHits[0], tHits[tHits.size()-1], pass)) return false;
3891  // make a TP for every hit
3892  work.Pts.resize(tHits.size());
3893  // and put a hit into each one
3894  for(unsigned short ii = 0; ii < tHits.size(); ++ii) {
3895  auto& tp = work.Pts[ii];
3896  unsigned int iht = tHits[ii];
3897  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
3898  tp.CTP = EncodeCTP(hit.WireID());
3899  if(tp.CTP != work.CTP) return false;
3900  tp.Hits.push_back(iht);
3901  tp.UseHit[0] = true;
3902  // don't use DefineHitPos here because the angle isn't really known yet. Just
3903  // define enough information to do a fit
3904  tp.HitPos[0] = hit.WireID().Wire;
3905  tp.HitPos[1] = hit.PeakTime() * tcc.unitsPerTick;
3906  tp.HitPosErr2 = 100;
3907  tp.Chg = hit.Integral();
3908  tp.Step = ii;
3909  tp.NTPsFit = tHits.size();
3910  // flag long-pulse hits
3911  if(LongPulseHit(hit)) tp.Environment[kEnvUnusedHits] = true;
3912  } // ii
3913  work.EndPt[0] = 0;
3914  work.EndPt[1] = tHits.size() - 1;
3915  // do an initial fit. The fit results are put in the last TP.
3916  FitTraj(slc, work);
3917  auto& lastTP = work.Pts.back();
3918  // Prepare to sort along the general direction. First find the
3919  // along and transverse position (Delta) of each TP and calculate DeltaRMS
3920  double sum = 0.;
3921  double sum2 = 0.;
3922  for(auto& tp : work.Pts) {
3923  Point2_t at;
3924  FindAlongTrans(lastTP.Pos, lastTP.Dir, tp.HitPos, at);
3925  sum += at[1];
3926  sum2 += at[1] * at[1];
3927  // store the along distance in AveChg for now
3928  tp.AveChg = at[0];
3929  tp.Delta = at[1];
3930  if(tp.Step != lastTP.Step) {
3931  tp.FitChi = lastTP.FitChi;
3932  tp.Dir = lastTP.Dir;
3933  tp.Ang = lastTP.Ang;
3934  tp.Pos[0] = lastTP.Pos[0] + at[0] * lastTP.Dir[0];
3935  tp.Pos[1] = lastTP.Pos[1] + at[0] * lastTP.Dir[1];
3936  }
3937  } // tp
3938  double npts = tHits.size();
3939  sum /= npts;
3940  double arg = sum2 - npts * sum * sum;
3941  if(arg <= 0) return false;
3942  float rms = sqrt(arg) / (npts - 1);
3943  // apply a loose Delta cut
3944  float transCut = sum + 3 * rms;
3945  std::vector<SortEntry> sortVec;
3946  SortEntry se;
3947  work.TotChg = 0;
3948  work.NeedsUpdate = false;
3949  for(auto& tp : work.Pts) {
3950  if(tp.Delta > transCut && !tp.Environment[kEnvUnusedHits]) {
3951  work.NeedsUpdate = true;
3952  continue;
3953  }
3954  se.index = tp.Step;
3955  se.val = tp.AveChg;
3956  sortVec.push_back(se);
3957  tp.DeltaRMS = rms;
3958  work.TotChg += tp.Chg;
3959  } // tp
3960  if(sortVec.size() < 3) return false;
3961  std::sort(sortVec.begin(), sortVec.end(), valsDecreasing);
3962  std::vector<TrajPoint> ntps(sortVec.size());
3963  for(unsigned short ipt = 0; ipt < sortVec.size(); ++ipt) ntps[ipt] = work.Pts[sortVec[ipt].index];
3964  work.Pts = ntps;
3965  sum = work.TotChg / (double)ntps.size();
3966  if(work.NeedsUpdate) {
3967  work.EndPt[1] = work.Pts.size() - 1;
3968  UpdateTraj(slc, work);
3969  } // needs update
3970  work.AlgMod[kJunkTj] = true;
3971  work.IsGood = true;
3972  if(prt) {
3973  PrintTrajectory("MJT", slc, work, USHRT_MAX);
3974  }
3975  // Store it
3976  return StoreTraj(slc, work);
3977  } // MakeJunkTraj
void UpdateTraj(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:669
TCConfig tcc
Definition: DataStructs.cxx:9
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:3097
void PrintTrajectory(std::string someText, const TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:6195
bool StoreTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:1089
bool StartTraj(TCSlice &slc, Trajectory &tj, unsigned int fromhit, unsigned int tohit, unsigned short pass)
Definition: Utils.cxx:5001
process_name hit
Definition: cheaterreco.fcl:51
bool LongPulseHit(const recob::Hit &hit)
Definition: Utils.cxx:4452
std::array< float, 2 > Point2_t
Definition: DataStructs.h:43
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
void FitTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:808
std::vector< unsigned short > minPts
min number of Pts required to make a trajectory
Definition: DataStructs.h:566
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:587
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
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:52
TCEvent evt
Definition: DataStructs.cxx:8
BEGIN_PROLOG could also be cout
void tca::MakeJunkVertices ( TCSlice &  slc,
const CTP_t &  inCTP 
)

Definition at line 31 of file TCVertex.cxx.

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

Definition at line 268 of file PFPUtils.cxx.

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

Definition at line 513 of file PFPUtils.cxx.

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

Definition at line 3194 of file TCShower.cxx.

3195  {
3196  // set the ss3 ID = 0 and remove 2D shower -> 3D shower associations. The 2D showers are not
3197  // declared obsolete
3198  for (auto cid : ss3.CotIDs) {
3199  if (cid == 0 || (unsigned short)cid > slc.cots.size()) continue;
3200  auto& ss = slc.cots[cid - 1];
3201  if (ss.SS3ID > 0 && ss.SS3ID != ss3.ID) continue;
3202  ss.SS3ID = 0;
3203  } // cid
3204  if (prt) {
3205  std::string fcnLabel = inFcnLabel + ".MSO";
3206  mf::LogVerbatim("TC") << fcnLabel << " Killed 3S" << ss3.ID;
3207  }
3208  ss3.ID = 0;
3209  } // MakeShowerObsolete
void tca::MakeShowerObsolete ( std::string  inFcnLabel,
TCSlice &  slc,
ShowerStruct &  ss,
bool  prt 
)

Definition at line 3213 of file TCShower.cxx.

3214  {
3215  // Gracefully kills the shower and the associated shower Tj
3216 
3217  if (ss.ID == 0) return;
3218 
3219  std::string fcnLabel = inFcnLabel + ".MSO";
3220 
3221  auto& stp1 = slc.tjs[ss.ShowerTjID - 1].Pts[1];
3222  if (!stp1.Hits.empty()) return;
3223 
3224  // clear a 3S -> 2S assn
3225  if (ss.SS3ID > 0 && ss.SS3ID <= (int)slc.showers.size()) {
3226  auto& ss3 = slc.showers[ss.SS3ID - 1];
3227  std::vector<int> newCIDs;
3228  for (auto cid : ss3.CotIDs) {
3229  if (cid != ss.ID) newCIDs.push_back(cid);
3230  } // cid
3231  ss3.CotIDs = newCIDs;
3232  } // ss3 assn exists
3233 
3234  // Kill the shower Tj if it exists. This also releases the hits
3235  if (ss.ShowerTjID > 0) MakeTrajectoryObsolete(slc, ss.ShowerTjID - 1);
3236 
3237  // Restore the original InShower Tjs
3238  // Unset the killed bit
3239  for (auto& tjID : ss.TjIDs) {
3240  Trajectory& tj = slc.tjs[tjID - 1];
3241  tj.AlgMod[kKilled] = false;
3242  // clear all of the shower-related bits
3243  tj.SSID = 0;
3244  tj.AlgMod[kShwrParent] = false;
3245  tj.AlgMod[kMergeOverlap] = false;
3246  tj.AlgMod[kMergeSubShowers] = false;
3247  tj.AlgMod[kMergeNrShowers] = false;
3248  tj.AlgMod[kMergeShChain] = false;
3249  } // tjID
3250  if (prt)
3251  mf::LogVerbatim("TC") << fcnLabel << " Killed 2S" << ss.ID << " and ST" << ss.ShowerTjID;
3252  ss.ID = 0;
3253 
3254  } // MakeShowerObsolete
void MakeTrajectoryObsolete(TCSlice &slc, unsigned int itj)
Definition: Utils.cxx:2184
bool tca::MakeSmallAnglePFP ( detinfo::DetectorPropertiesData const &  detProp,
TCSlice &  slc,
PFPStruct &  pfp,
bool  prt 
)

Definition at line 2206 of file PFPUtils.cxx.

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

Definition at line 2448 of file PFPUtils.cxx.

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

Definition at line 2125 of file PFPUtils.cxx.

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

Definition at line 2184 of file Utils.cxx.

2185  {
2186  // Note that this does not change the state of UseHit to allow
2187  // resurrecting the trajectory later (RestoreObsoleteTrajectory)
2188  if (itj > slc.tjs.size() - 1) return;
2189  int killTjID = slc.tjs[itj].ID;
2190  for (auto& hit : slc.slHits)
2191  if (hit.InTraj == killTjID) hit.InTraj = 0;
2192  slc.tjs[itj].AlgMod[kKilled] = true;
2193  } // MakeTrajectoryObsolete
process_name hit
Definition: cheaterreco.fcl:51
bool tca::MakeVertexObsolete ( std::string  fcnLabel,
TCSlice &  slc,
VtxStore &  vx2,
bool  forceKill 
)

Definition at line 2726 of file TCVertex.cxx.

2727  {
2728  // Makes a 2D vertex obsolete
2729 
2730  // check for a high-score 3D vertex
2731  bool hasHighScoreVx3 = (vx2.Vx3ID > 0);
2732  if (hasHighScoreVx3 && !forceKill && slc.vtx3s[vx2.Vx3ID - 1].Score >= tcc.vtx2DCuts[7])
2733  return false;
2734 
2735  if (tcc.dbg2V || tcc.dbg3V) {
2736  mf::LogVerbatim("TC") << fcnLabel << " MVO: killing 2V" << vx2.ID;
2737  }
2738 
2739  // Kill it
2740  int vx2id = vx2.ID;
2741  if (vx2.Vx3ID > 0) {
2742  auto& vx3 = slc.vtx3s[vx2.Vx3ID - 1];
2743  for (auto& v3v2id : vx3.Vx2ID)
2744  if (v3v2id == vx2.ID) v3v2id = 0;
2745  }
2746  vx2.ID = 0;
2747  for (auto& tj : slc.tjs) {
2748  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
2749  for (unsigned short end = 0; end < 2; ++end) {
2750  if (tj.VtxID[end] != vx2id) continue;
2751  tj.VtxID[end] = 0;
2752  tj.AlgMod[kPhoton] = false;
2753  // clear the kEnvOverlap bits on the TPs
2754  for (unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
2755  if (end == 0) {
2756  unsigned short ipt = tj.EndPt[0] + ii;
2757  auto& tp = tj.Pts[ipt];
2758  if (!tp.Environment[kEnvOverlap]) break;
2759  if (ipt == tj.EndPt[1]) break;
2760  }
2761  else {
2762  unsigned short ipt = tj.EndPt[1] - ii;
2763  auto& tp = tj.Pts[ipt];
2764  if (!tp.Environment[kEnvOverlap]) break;
2765  if (ipt == tj.EndPt[0]) break;
2766  }
2767  } // ii
2768  if (tj.AlgMod[kTjHiVx3Score]) {
2769  // see if the vertex at the other end is high-score and if so, preserve the state
2770  unsigned short oend = 1 - end;
2771  if (tj.VtxID[oend] > 0) {
2772  auto& ovx2 = slc.vtxs[tj.VtxID[oend] - 1];
2773  if (!ovx2.Stat[kHiVx3Score]) tj.AlgMod[kTjHiVx3Score] = false;
2774  } // vertex at the other end
2775  } // tj.AlgMod[kTjHiVx3Score]
2776  } // end
2777  } // tj
2778 
2779  if (!hasHighScoreVx3) return true;
2780 
2781  // update the affected 3D vertex
2782  Vtx3Store& vx3 = slc.vtx3s[vx2.Vx3ID - 1];
2783  // make the 3D vertex incomplete
2784  geo::PlaneID planeID = DecodeCTP(vx2.CTP);
2785  unsigned short plane = planeID.Plane;
2786  if (vx3.Vx2ID[plane] != vx2id) return true;
2787  vx3.Vx2ID[plane] = 0;
2788  vx3.Wire = vx2.Pos[0];
2789  // Ensure that there are at least two 2D vertices left
2790  unsigned short n2D = 0;
2791  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane)
2792  if (vx3.Vx2ID[plane] > 0) ++n2D;
2793 
2794  if (n2D > 1) {
2795  // 3D vertex is incomplete
2796  // correct the score
2797  SetVx3Score(slc, vx3);
2798  return true;
2799  }
2800 
2801  // 3D vertex is obsolete
2802  // Detach all remaining 2D vertices from the 3D vertex
2803  for (auto& vx2 : slc.vtxs) {
2804  if (vx2.ID == 0) continue;
2805  if (vx2.Vx3ID == vx3.ID) vx2.Vx3ID = 0;
2806  } // vx2
2807  for (auto& pfp : slc.pfps) {
2808  for (unsigned short end = 0; end < 2; ++end)
2809  if (pfp.Vx3ID[end] == vx3.ID) pfp.Vx3ID[end] = 0;
2810  } // pfp
2811  vx3.ID = 0;
2812  return true;
2813 
2814  } // MakeVertexObsolete
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
matched to a high-score 3D vertex
Definition: DataStructs.h:95
void SetVx3Score(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2242
bool dbg3V
debug 3D vertex finding
Definition: DataStructs.h:597
bool dbg2V
debug 2D vertex finding
Definition: DataStructs.h:593
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:550
bool tca::MakeVertexObsolete ( TCSlice &  slc,
Vtx3Store &  vx3 
)

Definition at line 2818 of file TCVertex.cxx.

2819  {
2820  // Deletes a 3D vertex and 2D vertices in all planes
2821  // The 2D and 3D vertices are NOT killed if forceKill is false and the 3D vertex
2822  // has a high score
2823  if (vx3.ID <= 0) return true;
2824  if (vx3.ID > int(slc.vtx3s.size())) return false;
2825 
2826  for (auto vx2id : vx3.Vx2ID) {
2827  if (vx2id == 0 || vx2id > (int)slc.vtxs.size()) continue;
2828  auto& vx2 = slc.vtxs[vx2id - 1];
2829  MakeVertexObsolete("MVO3", slc, vx2, true);
2830  }
2831  vx3.ID = 0;
2832  return true;
2833  } // MakeVertexObsolete
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:2726
void tca::MaskBadTPs ( TCSlice &  slc,
Trajectory &  tj,
float const &  maxChi 
)

Definition at line 2379 of file StepUtils.cxx.

2380  {
2381  // Remove TPs that have the worst values of delta until the fit chisq < maxChi
2382 
2383  if(!tcc.useAlg[kMaskBadTPs]) return;
2384  //don't use this function for reverse propagation
2385  if(!tcc.useAlg[kRvPrp]) return;
2386 
2387  bool prt = (tcc.dbgStp || tcc.dbgAlg[kMaskBadTPs]);
2388 
2389  if(tj.Pts.size() < 3) {
2390  // mf::LogError("TC")<<"MaskBadTPs: Trajectory ID "<<tj.ID<<" too short to mask hits ";
2391  tj.IsGood = false;
2392  return;
2393  }
2394  unsigned short nit = 0;
2395  TrajPoint& lastTP = tj.Pts[tj.Pts.size() - 1];
2396  while(lastTP.FitChi > maxChi && nit < 3) {
2397  float maxDelta = 0;
2398  unsigned short imBad = USHRT_MAX;
2399  unsigned short cnt = 0;
2400  for(unsigned short ii = 1; ii < tj.Pts.size(); ++ii) {
2401  unsigned short ipt = tj.Pts.size() - 1 - ii;
2402  TrajPoint& tp = tj.Pts[ipt];
2403  if(tp.Chg == 0) continue;
2404  if(tp.Delta > maxDelta) {
2405  maxDelta = tp.Delta;
2406  imBad = ipt;
2407  }
2408  ++cnt;
2409  if(cnt == tp.NTPsFit) break;
2410  } // ii
2411  if(imBad == USHRT_MAX) return;
2412  if(prt) mf::LogVerbatim("TC")<<"MaskBadTPs: lastTP.FitChi "<<lastTP.FitChi<<" Mask point "<<imBad;
2413  // mask the point
2414  UnsetUsedHits(slc, tj.Pts[imBad]);
2415  FitTraj(slc, tj);
2416  if(prt) mf::LogVerbatim("TC")<<" after FitTraj "<<lastTP.FitChi;
2417  tj.AlgMod[kMaskBadTPs] = true;
2418  ++nit;
2419  } // lastTP.FItChi > maxChi && nit < 3
2420 
2421  } // MaskBadTPs
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1075
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
void FitTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:808
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:587
bool tca::MaskedHitsOK ( TCSlice &  slc,
Trajectory &  tj 
)

Definition at line 2424 of file StepUtils.cxx.

2425  {
2426  // The hits in the TP at the end of the trajectory were masked off. Decide whether to continue stepping with the
2427  // current configuration (true) or whether to stop and possibly try with the next pass settings (false)
2428 
2429  if(!tcc.useAlg[kMaskHits]) return true;
2430 
2431  unsigned short lastPt = tj.Pts.size() - 1;
2432  if(tj.Pts[lastPt].Chg > 0) return true;
2433  unsigned short endPt = tj.EndPt[1];
2434 
2435  // count the number of points w/o used hits and the number with one unused hit
2436  unsigned short nMasked = 0;
2437  unsigned short nOneHit = 0;
2438  unsigned short nOKChg = 0;
2439  unsigned short nOKDelta = 0;
2440  // number of points with Pos > HitPos
2441  unsigned short nPosDelta = 0;
2442  // number of points with Delta increasing vs ipt
2443  unsigned short nDeltaIncreasing = 0;
2444  // Fake this a bit to simplify comparing the counts
2445  float prevDelta = tj.Pts[endPt].Delta;
2446  float maxOKDelta = 10 * tj.Pts[endPt].DeltaRMS;
2447  float maxOKChg = 0;
2448  // find the maximum charge point on the trajectory
2449  for(unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) if(tj.Pts[ipt].Chg > maxOKChg) maxOKChg = tj.Pts[ipt].Chg;
2450  for(unsigned short ii = 1; ii < tj.Pts.size(); ++ii) {
2451  unsigned short ipt = tj.Pts.size() - ii;
2452  auto& tp = tj.Pts[ipt];
2453  if(tp.Chg > 0) break;
2454  unsigned short nUnusedHits = 0;
2455  float chg = 0;
2456  for(unsigned short jj = 0; jj < tp.Hits.size(); ++jj) {
2457  unsigned int iht = tp.Hits[jj];
2458  if(slc.slHits[iht].InTraj != 0) continue;
2459  ++nUnusedHits;
2460  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2461  chg += hit.Integral();
2462  } // jj
2463  if(chg < maxOKChg) ++nOKChg;
2464  if(nUnusedHits == 1) ++nOneHit;
2465  if(tp.Delta < maxOKDelta) ++nOKDelta;
2466  // count the number of points with Pos time > HitPos time
2467  if(tp.Pos[1] > tp.HitPos[1]) ++nPosDelta;
2468  // The number of increasing delta points: Note implied absolute value
2469  if(tp.Delta < prevDelta) ++nDeltaIncreasing;
2470  prevDelta = tp.Delta;
2471  ++nMasked;
2472  } // ii
2473 
2474  // determine if the hits are wandering away from the trajectory direction. This will result in
2475  // nPosDelta either being ~0 or ~equal to the number of masked points. nPosDelta should have something
2476  // in between these two extremes if we are stepping through a messy region
2477  bool driftingAway = nMasked > 2 && (nPosDelta == 0 || nPosDelta == nMasked);
2478  // Note that nDeltaIncreasing is always positive
2479  if(driftingAway && nDeltaIncreasing < nMasked - 1) driftingAway = false;
2480 
2481  if(tcc.dbgStp) {
2482  mf::LogVerbatim("TC")<<"MHOK: nMasked "<<nMasked<<" nOneHit "<<nOneHit<<" nOKChg "<<nOKChg<<" nOKDelta "<<nOKDelta<<" nPosDelta "<<nPosDelta<<" nDeltaIncreasing "<<nDeltaIncreasing<<" driftingAway? "<<driftingAway;
2483  }
2484 
2485  if(!driftingAway) {
2486  if(nMasked < 8 || nOneHit < 8) return true;
2487  if(nOKDelta != nMasked) return true;
2488  if(nOKChg != nMasked) return true;
2489  }
2490 
2491  // we would like to reduce the number of fitted points to a minimum and include
2492  // the masked hits, but we can only do that if there are enough points
2493  if(tj.Pts[endPt].NTPsFit <= tcc.minPtsFit[tj.Pass]) {
2494  // stop stepping if we have masked off more points than are in the fit
2495  if(nMasked > tj.Pts[endPt].NTPsFit) return false;
2496  return true;
2497  }
2498  // Reduce the number of points fit and try to include the points
2499  unsigned short newNTPSFit;
2500  if(tj.Pts[endPt].NTPsFit > 2 * tcc.minPtsFit[tj.Pass]) {
2501  newNTPSFit = tj.Pts[endPt].NTPsFit / 2;
2502  } else {
2503  newNTPSFit = tcc.minPtsFit[tj.Pass];
2504  }
2505  for(unsigned ipt = endPt + 1; ipt < tj.Pts.size(); ++ipt) {
2506  TrajPoint& tp = tj.Pts[ipt];
2507  for(unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
2508  unsigned int iht = tp.Hits[ii];
2509  if(slc.slHits[iht].InTraj == 0) {
2510  tp.UseHit[ii] = true;
2511  slc.slHits[iht].InTraj = tj.ID;
2512  break;
2513  }
2514  } // ii
2515  DefineHitPos(slc, tp);
2516  SetEndPoints(tj);
2517  tp.NTPsFit = newNTPSFit;
2518  FitTraj(slc, tj);
2519  if(tcc.dbgStp) PrintTrajectory("MHOK", slc, tj, ipt);
2520  } // ipt
2521 
2522  tj.AlgMod[kMaskHits] = true;
2523  UpdateTjChgProperties("MHOK", slc, tj, tcc.dbgStp);
2524  return true;
2525 
2526  } // MaskedHitsOK
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3413
std::vector< unsigned short > minPtsFit
Reconstruct in several passes.
Definition: DataStructs.h:565
TCConfig tcc
Definition: DataStructs.cxx:9
void PrintTrajectory(std::string someText, const TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:6195
process_name hit
Definition: cheaterreco.fcl:51
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1672
void FitTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:808
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3673
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
TCEvent evt
Definition: DataStructs.cxx:8
void tca::MaskTrajEndPoints ( TCSlice &  slc,
Trajectory &  tj,
unsigned short  nPts 
)

Definition at line 3651 of file StepUtils.cxx.

3652  {
3653 
3654  // Masks off (sets all hits not-Used) nPts trajectory points at the leading edge of the
3655  // trajectory, presumably because the fit including this points is poor. The position, direction
3656  // and Delta of the last nPts points is updated as well
3657 
3658  if(tj.EndFlag[1][kAtKink]) return;
3659  if(tj.Pts.size() < 3) {
3660  mf::LogError("TC")<<"MaskTrajEndPoints: Trajectory ID "<<tj.ID<<" too short to mask hits ";
3661  return;
3662  }
3663  if(nPts > tj.Pts.size() - 2) {
3664  mf::LogError("TC")<<"MaskTrajEndPoints: Trying to mask too many points "<<nPts<<" Pts.size "<<tj.Pts.size();
3665  return;
3666  }
3667 
3668  // find the last good point (with charge)
3669  unsigned short lastGoodPt = USHRT_MAX ;
3670 
3671  if(tcc.dbgStp) {
3672  mf::LogVerbatim("TC")<<"MTEP: lastGoodPt "<<lastGoodPt<<" Pts size "<<tj.Pts.size()<<" tj.IsGood "<<tj.IsGood;
3673  }
3674  if(lastGoodPt == USHRT_MAX) return;
3675  tj.EndPt[1] = lastGoodPt;
3676 
3677  //for(unsigned short ii = 0; ii < nPts; ++ii) {
3678  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
3679  unsigned short ipt = tj.Pts.size() - 1 - ii;
3680  if (ipt==lastGoodPt) break;
3681  UnsetUsedHits(slc, tj.Pts[ipt]);
3682  // Reset the position and direction of the masked off points
3683  tj.Pts[ipt].Dir = tj.Pts[lastGoodPt].Dir;
3684  if(tj.Pts[lastGoodPt].AngleCode == 2) {
3685  // Very large angle: Move by path length
3686  float path = TrajPointSeparation(tj.Pts[lastGoodPt], tj.Pts[ipt]);
3687  tj.Pts[ipt].Pos[0] = tj.Pts[lastGoodPt].Pos[0] + path * tj.Pts[ipt].Dir[0];
3688  tj.Pts[ipt].Pos[1] = tj.Pts[lastGoodPt].Pos[1] + path * tj.Pts[ipt].Dir[1];
3689  } else {
3690  // Not large angle: Move by wire
3691  float dw = tj.Pts[ipt].Pos[0] - tj.Pts[lastGoodPt].Pos[0];
3692  // Correct the projected time to the wire
3693  float newpos = tj.Pts[lastGoodPt].Pos[1] + dw * tj.Pts[ipt].Dir[1] / tj.Pts[ipt].Dir[0];
3694  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"MTEP: ipt "<<ipt<<" Pos[0] "<<tj.Pts[ipt].Pos[0]<<". Move Pos[1] from "<<tj.Pts[ipt].Pos[1]<<" to "<<newpos;
3695  tj.Pts[ipt].Pos[1] = tj.Pts[lastGoodPt].Pos[1] + dw * tj.Pts[ipt].Dir[1] / tj.Pts[ipt].Dir[0];
3696  }
3697  tj.Pts[ipt].Delta = PointTrajDOCA(slc, tj.Pts[ipt].HitPos[0], tj.Pts[ipt].HitPos[1], tj.Pts[ipt]);
3698  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" masked ipt "<<ipt<<" Pos "<<PrintPos(slc, tj.Pts[ipt])<<" Chg "<<tj.Pts[ipt].Chg;
3699  } // ii
3700  SetEndPoints(tj);
3701 
3702  } // MaskTrajEndPoints
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3413
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1075
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
float TrajPointSeparation(const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2680
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2572
BEGIN_PROLOG triggeremu_data_config_icarus settings PMTADCthresholds sequence::icarus_stage0_multiTPC_TPC physics sequence::icarus_stage0_EastHits_TPC physics sequence::icarus_stage0_WestHits_TPC physics producers purityana0 caloskimCalorimetryCryoE physics caloskimCalorimetryCryoW physics path
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
void tca::Match2DShowers ( std::string  inFcnLabel,
TCSlice &  slc,
bool  prt 
)
void tca::Match2Planes ( TCSlice &  slc,
std::vector< MatchStruct > &  matVec 
)

Definition at line 945 of file PFPUtils.cxx.

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

Definition at line 1211 of file TCShower.cxx.

1216  {
1217  float fom = 0;
1218  float cnt = 0;
1219  for (unsigned short ii = 0; ii < ss3.CotIDs.size() - 1; ++ii) {
1220  unsigned short icid = ss3.CotIDs[ii];
1221  for (unsigned short jj = ii + 1; jj < ss3.CotIDs.size(); ++jj) {
1222  unsigned short jcid = ss3.CotIDs[jj];
1223  fom += Match3DFOM(detProp, inFcnLabel, slc, icid, jcid, prt);
1224  ++cnt;
1225  } // cj
1226  } // ci
1227  if (cnt == 0) return 100;
1228  return fom / cnt;
1229  } // Match3DFOM
float Match3DFOM(detinfo::DetectorPropertiesData const &detProp, std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1211
auto const detProp
float tca::Match3DFOM ( detinfo::DetectorPropertiesData const &  detProp,
std::string  inFcnLabel,
TCSlice &  slc,
int  icid,
int  jcid,
int  kcid,
bool  prt 
)

Definition at line 1233 of file TCShower.cxx.

1240  {
1241  if (icid == 0 || icid > (int)slc.cots.size()) return 100;
1242  if (jcid == 0 || jcid > (int)slc.cots.size()) return 100;
1243  if (kcid == 0 || kcid > (int)slc.cots.size()) return 100;
1244 
1245  float ijfom = Match3DFOM(detProp, inFcnLabel, slc, icid, jcid, prt);
1246  float jkfom = Match3DFOM(detProp, inFcnLabel, slc, jcid, kcid, prt);
1247 
1248  return 0.5 * (ijfom + jkfom);
1249 
1250  } // Match3DFOM
float Match3DFOM(detinfo::DetectorPropertiesData const &detProp, std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:1211
auto const detProp
float tca::Match3DFOM ( detinfo::DetectorPropertiesData const &  detProp,
std::string  inFcnLabel,
TCSlice &  slc,
int  icid,
int  jcid,
bool  prt 
)

Definition at line 1254 of file TCShower.cxx.

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

Definition at line 814 of file PFPUtils.cxx.

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

Definition at line 701 of file PFPUtils.cxx.

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 -&gt; Hits assns by plane.
Definition: DataStructs.h:633
std::vector< float > match3DCuts
3D matching cuts
Definition: DataStructs.h:560
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
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:2116
TCEvent evt
Definition: DataStructs.cxx:8
bool SptInTPC(const std::array< unsigned int, 3 > &sptHits, unsigned int tpc)
Definition: PFPUtils.cxx:793
float tca::MaxChargeAsymmetry ( TCSlice &  slc,
std::vector< int > &  tjIDs 
)

Definition at line 374 of file Utils.cxx.

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

Definition at line 3276 of file Utils.cxx.

3277  {
3278  float delta, md = 0;
3279  unsigned short ii;
3280  unsigned int iht;
3281  for (auto& tp : tj.Pts) {
3282  for (ii = 0; ii < tp.Hits.size(); ++ii) {
3283  if (!tp.UseHit[ii]) continue;
3284  iht = tp.Hits[ii];
3285  delta = PointTrajDOCA(slc, iht, tp);
3286  if (delta > md) md = delta;
3287  } // ii
3288  } // pts
3289  return md;
3290  } // MaxHitDelta
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2572
float tca::MaxTjLen ( const TCSlice &  slc,
std::vector< int > &  tjIDs 
)

Definition at line 2630 of file Utils.cxx.

2631  {
2632  // returns the length of the longest Tj in the supplied list
2633  if (tjIDs.empty()) return 0;
2634  float maxLen = 0;
2635  for (auto tjid : tjIDs) {
2636  if (tjid < 1 || tjid > (int)slc.tjs.size()) continue;
2637  auto& tj = slc.tjs[tjid - 1];
2638  float sep2 = PosSep2(tj.Pts[tj.EndPt[0]].Pos, tj.Pts[tj.EndPt[1]].Pos);
2639  if (sep2 > maxLen) maxLen = sep2;
2640  } // tj
2641  return sqrt(maxLen);
2642  } // MaxTjLen
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2572
short tca::MCSMom ( const TCSlice &  slc,
const std::vector< int > &  tjIDs 
)

Definition at line 3468 of file Utils.cxx.

3469  {
3470  // Find the average MCSMom of the trajectories
3471  if (tjIDs.empty()) return 0;
3472  float summ = 0;
3473  float suml = 0;
3474  for (auto tjid : tjIDs) {
3475  auto& tj = slc.tjs[tjid - 1];
3476  float npts = tj.EndPt[1] - tj.EndPt[0] + 1;
3477  summ += npts * tj.MCSMom;
3478  suml += npts;
3479  } // tjid
3480  return (short)(summ / suml);
3481  } // MCSMom
short tca::MCSMom ( const TCSlice &  slc,
const Trajectory &  tj 
)

Definition at line 3485 of file Utils.cxx.

3486  {
3487  return MCSMom(slc, tj, tj.EndPt[0], tj.EndPt[1]);
3488  } // MCSMom
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3468
short tca::MCSMom ( const TCSlice &  slc,
const Trajectory &  tj,
unsigned short  firstPt,
unsigned short  lastPt 
)

Definition at line 3492 of file Utils.cxx.

3493  {
3494  // Estimate the trajectory momentum using Multiple Coulomb Scattering ala PDG RPP
3495 
3496  if (firstPt == lastPt) return 0;
3497  if (firstPt > lastPt) std::swap(firstPt, lastPt);
3498 
3499  firstPt = NearestPtWithChg(slc, tj, firstPt);
3500  lastPt = NearestPtWithChg(slc, tj, lastPt);
3501  if (firstPt >= lastPt) return 0;
3502 
3503  if (firstPt < tj.EndPt[0]) return 0;
3504  if (lastPt > tj.EndPt[1]) return 0;
3505  // Can't do this with only 2 points
3506  if (NumPtsWithCharge(slc, tj, false, firstPt, lastPt) < 3) return 0;
3507  // Ignore junk Tjs
3508  if (tj.AlgMod[kJunkTj]) return 0;
3509 
3510  double tjLen = TrajPointSeparation(tj.Pts[firstPt], tj.Pts[lastPt]);
3511  if (tjLen < 1) return 0;
3512  // mom calculated in MeV
3513  double thetaRMS = MCSThetaRMS(slc, tj, firstPt, lastPt);
3514  if (thetaRMS < 0.001) return 999;
3515  double mom = 13.8 * sqrt(tjLen / 14) / thetaRMS;
3516  if (mom > 999) mom = 999;
3517  return (short)mom;
3518  } // MCSMom
float TrajPointSeparation(const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2680
float MCSThetaRMS(const TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:3541
unsigned short NearestPtWithChg(const TCSlice &slc, const Trajectory &tj, unsigned short thePt)
Definition: Utils.cxx:3522
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2116
float tca::MCSThetaRMS ( const TCSlice &  slc,
const Trajectory &  tj 
)

Definition at line 3541 of file Utils.cxx.

3542  {
3543  // This returns the MCS scattering angle expected for one WSE unit of travel along the trajectory.
3544  // It is used to define kink and vertex cuts. This should probably be named something different to
3545  // prevent confusion
3546 
3547  float tps = TrajPointSeparation(tj.Pts[tj.EndPt[0]], tj.Pts[tj.EndPt[1]]);
3548  if (tps < 1) return 1;
3549 
3550  return MCSThetaRMS(slc, tj, tj.EndPt[0], tj.EndPt[1]) / sqrt(tps);
3551 
3552  } // MCSThetaRMS
float TrajPointSeparation(const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2680
float MCSThetaRMS(const TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:3541
double tca::MCSThetaRMS ( const TCSlice &  slc,
const Trajectory &  tj,
unsigned short  firstPt,
unsigned short  lastPt 
)

Definition at line 3556 of file Utils.cxx.

3560  {
3561  // This returns the MCS scattering angle expected for the length of the trajectory
3562  // spanned by firstPt to lastPt. It is used primarily to calculate MCSMom
3563 
3564  if (firstPt < tj.EndPt[0]) return 1;
3565  if (lastPt > tj.EndPt[1]) return 1;
3566 
3567  firstPt = NearestPtWithChg(slc, tj, firstPt);
3568  lastPt = NearestPtWithChg(slc, tj, lastPt);
3569  if (firstPt >= lastPt) return 1;
3570 
3571  double sigmaS;
3572  unsigned short cnt;
3573  TjDeltaRMS(slc, tj, firstPt, lastPt, sigmaS, cnt);
3574  if (sigmaS < 0) return 1;
3575  double tjLen = TrajPointSeparation(tj.Pts[firstPt], tj.Pts[lastPt]);
3576  if (tjLen < 1) return 1;
3577  // Theta_o = 4 * sqrt(3) * sigmaS / path
3578  return (6.8 * sigmaS / tjLen);
3579 
3580  } // MCSThetaRMS
float TrajPointSeparation(const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2680
unsigned short NearestPtWithChg(const TCSlice &slc, const Trajectory &tj, unsigned short thePt)
Definition: Utils.cxx:3522
void TjDeltaRMS(const TCSlice &slc, const Trajectory &tj, unsigned short firstPt, unsigned short lastPt, double &rms, unsigned short &cnt)
Definition: Utils.cxx:3584
bool tca::MergeAndStore ( TCSlice &  slc,
unsigned int  itj1,
unsigned int  itj2,
bool  doPrt 
)

Not allowed

Definition at line 4664 of file Utils.cxx.

4665  {
4666  // Merge the two trajectories in allTraj and store them. Returns true if it was successfull.
4667  // Merging is done between the end (end = 1) of tj1 and the beginning (end = 0) of tj2. This function preserves the
4668  // AlgMod state of itj1.
4669  // The itj1 -> itj2 merge order is reversed if end1 of itj2 is closer to end0 of itj1
4670 
4671  if (itj1 > slc.tjs.size() - 1) return false;
4672  if (itj2 > slc.tjs.size() - 1) return false;
4673  if (slc.tjs[itj1].AlgMod[kKilled] || slc.tjs[itj2].AlgMod[kKilled]) return false;
4674  if (slc.tjs[itj1].AlgMod[kHaloTj] || slc.tjs[itj2].AlgMod[kHaloTj]) return false;
4675 
4676  // Merging shower Tjs requires merging the showers as well.
4677  if (slc.tjs[itj1].AlgMod[kShowerTj] || slc.tjs[itj2].AlgMod[kShowerTj])
4678  return MergeShowerTjsAndStore(slc, itj1, itj2, doPrt);
4679 
4680  // Ensure that the order of 3D-matched Tjs is consistent with the convention that
4681  unsigned short pfp1 = GetPFPIndex(slc, slc.tjs[itj1].ID);
4682  unsigned short pfp2 = GetPFPIndex(slc, slc.tjs[itj2].ID);
4683  if (pfp1 != USHRT_MAX || pfp2 != USHRT_MAX) {
4684  if (pfp1 != USHRT_MAX && pfp2 != USHRT_MAX) return false;
4685  // Swap so that the order of tj1 is preserved. Tj2 may be reversed to be consistent
4686  if (pfp1 == USHRT_MAX) std::swap(itj1, itj2);
4687  } // one or both used in a PFParticle
4688 
4689  // make copies so they can be trimmed as needed
4690  Trajectory tj1 = slc.tjs[itj1];
4691  Trajectory tj2 = slc.tjs[itj2];
4692 
4693  // ensure that these are in the same step order
4694  if (tj2.StepDir != tj1.StepDir) ReverseTraj(slc, tj2);
4695 
4696  Point2_t tp1e0 = tj1.Pts[tj1.EndPt[0]].Pos;
4697  Point2_t tp1e1 = tj1.Pts[tj1.EndPt[1]].Pos;
4698  Point2_t tp2e0 = tj2.Pts[tj2.EndPt[0]].Pos;
4699  Point2_t tp2e1 = tj2.Pts[tj2.EndPt[1]].Pos;
4700 
4701  if (doPrt) {
4702  mf::LogVerbatim("TC") << "MergeAndStore: T" << tj1.ID << " and T" << tj2.ID
4703  << " at merge points " << PrintPos(slc, tp1e1) << " "
4704  << PrintPos(slc, tp2e0);
4705  }
4706 
4707  // swap the order so that abs(tj1end1 - tj2end0) is less than abs(tj2end1 - tj1end0)
4708  if (PosSep2(tp1e1, tp2e0) > PosSep2(tp2e1, tp1e0)) {
4709  std::swap(tj1, tj2);
4710  std::swap(tp1e0, tp2e0);
4711  std::swap(tp1e1, tp2e1);
4712  if (doPrt)
4713  mf::LogVerbatim("TC") << " swapped the order. Merge points " << PrintPos(slc, tp1e1) << " "
4714  << PrintPos(slc, tp2e0);
4715  }
4716 
4717  // Here is what we are looking for, where - indicates a TP with charge.
4718  // Note that this graphic is in the stepping direction (+1 = +wire direction)
4719  // tj1: 0------------1
4720  // tj2: 0-----------1
4721  // Another possibility with overlap
4722  // tj1: 0-------------1
4723  // tj2: 0--------------1
4724 
4725  if (tj1.StepDir > 1) {
4726  // Not allowed
4727  // tj1: 0---------------------------1
4728  // tj2: 0------1
4729  if (tp2e0[0] > tp1e0[0] && tp2e1[0] < tp1e1[0]) return false;
4730  /// Not allowed
4731  // tj1: 0------1
4732  // tj2: 0---------------------------1
4733  if (tp1e0[0] > tp2e0[0] && tp1e1[0] < tp2e1[0]) return false;
4734  }
4735  else {
4736  // same as above but with ends reversed
4737  if (tp2e1[0] > tp1e1[0] && tp2e0[0] < tp1e0[0]) return false;
4738  if (tp1e1[0] > tp2e1[0] && tp1e0[0] < tp2e0[0]) return false;
4739  }
4740 
4741  if (tj1.VtxID[1] > 0 && tj2.VtxID[0] == tj1.VtxID[1]) {
4742  auto& vx = slc.vtxs[tj1.VtxID[1] - 1];
4743  if (!MakeVertexObsolete("MAS", slc, vx, false)) {
4744  if (doPrt)
4745  mf::LogVerbatim("TC") << "MergeAndStore: Found a good vertex between Tjs " << tj1.VtxID[1]
4746  << " No merging";
4747  return false;
4748  }
4749  }
4750 
4751  if (tj1.EndFlag[1][kBragg]) {
4752  if (doPrt)
4753  mf::LogVerbatim("TC") << "MergeAndStore: You are merging the end of trajectory T" << tj1.ID
4754  << " with a Bragg peak. Not merging\n";
4755  return false;
4756  }
4757 
4758  // remove any points at the end of tj1 that don't have used hits
4759  tj1.Pts.resize(tj1.EndPt[1] + 1);
4760 
4761  // determine if they overlap by finding the point on tj2 that is closest
4762  // to the end point of tj1.
4763  TrajPoint& endtj1TP = tj1.Pts[tj1.EndPt[1]];
4764  // Set minSep large so that dead wire regions are accounted for
4765  float minSep = 1000;
4766  unsigned short tj2ClosePt = 0;
4767  // Note that TrajPointTrajDOCA only considers TPs that have charge
4768  TrajPointTrajDOCA(slc, endtj1TP, tj2, tj2ClosePt, minSep);
4769  if (doPrt)
4770  mf::LogVerbatim("TC") << " Merge point tj1 " << PrintPos(slc, endtj1TP) << " tj2ClosePt "
4771  << tj2ClosePt << " Pos " << PrintPos(slc, tj2.Pts[tj2ClosePt]);
4772  // check for full overlap
4773  if (tj2ClosePt > tj2.EndPt[1]) return false;
4774 
4775  // The approach is to append tj2 to tj1, store tj1 as a new trajectory,
4776  // and re-assign all hits to the new trajectory
4777 
4778  // First ensure that any hit will appear only once in the merged trajectory in the overlap region
4779  // whether it is used or unused. The point on tj2 where the merge will begin, tj2ClosePt, will be
4780  // increased until this condition is met.
4781  // Make a temporary vector of tj1 hits in the end points for simpler searching
4782  std::vector<unsigned int> tj1Hits;
4783  for (unsigned short ii = 0; ii < tj1.Pts.size(); ++ii) {
4784  // only go back a few points in tj1
4785  if (ii > 10) break;
4786  unsigned short ipt = tj1.Pts.size() - 1 - ii;
4787  tj1Hits.insert(tj1Hits.end(), tj1.Pts[ipt].Hits.begin(), tj1.Pts[ipt].Hits.end());
4788  if (ipt == 0) break;
4789  } // ii
4790 
4791  bool bumpedPt = true;
4792  while (bumpedPt) {
4793  bumpedPt = false;
4794  for (unsigned short ii = 0; ii < tj2.Pts[tj2ClosePt].Hits.size(); ++ii) {
4795  unsigned int iht = tj2.Pts[tj2ClosePt].Hits[ii];
4796  if (std::find(tj1Hits.begin(), tj1Hits.end(), iht) != tj1Hits.end()) bumpedPt = true;
4797  } // ii
4798  if (bumpedPt && tj2ClosePt < tj2.EndPt[1]) { ++tj2ClosePt; }
4799  else {
4800  break;
4801  }
4802  } // bumpedPt
4803  if (doPrt) mf::LogVerbatim("TC") << " revised tj2ClosePt " << tj2ClosePt;
4804  // append tj2 hits to tj1
4805 
4806  tj1.Pts.insert(tj1.Pts.end(), tj2.Pts.begin() + tj2ClosePt, tj2.Pts.end());
4807  // re-define the end points
4808  SetEndPoints(tj1);
4809  tj1.EndFlag[1] = tj2.EndFlag[1];
4810 
4811  // A more exhaustive check that hits only appear once
4812  if (HasDuplicateHits(slc, tj1, doPrt)) return false;
4813  if (tj2.VtxID[1] > 0) {
4814  // move the end vertex of tj2 to the end of tj1
4815  tj1.VtxID[1] = tj2.VtxID[1];
4816  }
4817  // Transfer some of the AlgMod bits
4818  if (tj2.AlgMod[kMichel]) tj1.AlgMod[kMichel] = true;
4819  if (tj2.AlgMod[kDeltaRay]) {
4820  tj1.AlgMod[kDeltaRay] = true;
4821  tj1.ParentID = tj2.ParentID;
4822  }
4823  // keep track of the IDs before they are clobbered
4824  int tj1ID = tj1.ID;
4825  int tj2ID = tj2.ID;
4826  // kill the original trajectories
4827  MakeTrajectoryObsolete(slc, itj1);
4828  MakeTrajectoryObsolete(slc, itj2);
4829  // Do this so that StoreTraj keeps the correct WorkID (of itj1)
4830  tj1.ID = tj1.WorkID;
4831  SetPDGCode(slc, tj1);
4832  tj1.NeedsUpdate = true;
4833  if (!StoreTraj(slc, tj1)) return false;
4834  int newTjID = slc.tjs.size();
4835  // Use the ParentID to trace which new Tj is superseding the merged ones
4836  tj1.ParentID = newTjID;
4837  tj2.ParentID = newTjID;
4838  if (doPrt) mf::LogVerbatim("TC") << " MAS success. Created T" << newTjID;
4839  // Transfer the ParentIDs of any other Tjs that refer to Tj1 and Tj2 to the new Tj
4840  for (auto& tj : slc.tjs)
4841  if (tj.ParentID == tj1ID || tj.ParentID == tj2ID) tj.ParentID = newTjID;
4842  // try to attach it to a vertex
4843  AttachAnyVertexToTraj(slc, newTjID, doPrt);
4844  return true;
4845  } // MergeAndStore
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3413
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:2726
bool AttachAnyVertexToTraj(TCSlice &slc, int tjID, bool prt)
Definition: TCVertex.cxx:1641
void SetPDGCode(TCSlice &slc, unsigned short itj)
Definition: Utils.cxx:4350
bool StoreTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:1089
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
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:3017
void MakeTrajectoryObsolete(TCSlice &slc, unsigned int itj)
Definition: Utils.cxx:2184
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2572
unsigned short GetPFPIndex(const TCSlice &slc, int tjID)
Definition: Utils.cxx:1050
void TrajPointTrajDOCA(const TCSlice &slc, TrajPoint const &tp, Trajectory const &tj, unsigned short &closePt, float &minSep)
Definition: Utils.cxx:2435
void ReverseTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:3294
bool HasDuplicateHits(const TCSlice &slc, Trajectory const &tj, bool prt)
Definition: Utils.cxx:2812
void tca::MergeGhostTjs ( TCSlice &  slc,
CTP_t  inCTP 
)

Definition at line 2220 of file Utils.cxx.

2221  {
2222  // Merges short Tjs that share many hits with a longer Tj
2223  if (!tcc.useAlg[kMrgGhost]) return;
2224 
2225  for (auto& shortTj : slc.tjs) {
2226  if (shortTj.AlgMod[kKilled] || shortTj.AlgMod[kHaloTj]) continue;
2227  if (shortTj.CTP != inCTP) continue;
2228  unsigned short spts = shortTj.EndPt[1] - shortTj.EndPt[0];
2229  if (spts > 20) continue;
2230  // ignore delta rays
2231  if (shortTj.PDGCode == 11) continue;
2232  // ignore InShower Tjs
2233  if (shortTj.SSID > 0) continue;
2234  auto tjhits = PutTrajHitsInVector(shortTj, kAllHits);
2235  if (tjhits.empty()) continue;
2236  std::vector<int> tids;
2237  std::vector<unsigned short> tcnt;
2238  for (auto iht : tjhits) {
2239  auto& hit = slc.slHits[iht];
2240  if (hit.InTraj <= 0) continue;
2241  if ((unsigned int)hit.InTraj > slc.tjs.size()) continue;
2242  if (hit.InTraj == shortTj.ID) continue;
2243  unsigned short indx = 0;
2244  for (indx = 0; indx < tids.size(); ++indx)
2245  if (hit.InTraj == tids[indx]) break;
2246  if (indx == tids.size()) {
2247  tids.push_back(hit.InTraj);
2248  tcnt.push_back(1);
2249  }
2250  else {
2251  ++tcnt[indx];
2252  }
2253  } // iht
2254  if (tids.empty()) continue;
2255  // find the max count for Tjs that are longer than this one
2256  unsigned short maxcnt = 0;
2257  for (unsigned short indx = 0; indx < tids.size(); ++indx) {
2258  if (tcnt[indx] > maxcnt) {
2259  auto& ltj = slc.tjs[tids[indx] - 1];
2260  unsigned short lpts = ltj.EndPt[1] - ltj.EndPt[0];
2261  if (lpts < spts) continue;
2262  maxcnt = tcnt[indx];
2263  }
2264  } // indx
2265  float hitFrac = (float)maxcnt / (float)tjhits.size();
2266  if (hitFrac < 0.1) continue;
2267  } // shortTj
2268  } // MergeGhostTjs
std::vector< unsigned int > PutTrajHitsInVector(const Trajectory &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2754
TCConfig tcc
Definition: DataStructs.cxx:9
process_name hit
Definition: cheaterreco.fcl:51
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
void tca::MergeNearby2DShowers ( std::string  inFcnLabel,
TCSlice &  slc,
const CTP_t &  inCTP,
bool  prt 
)

Definition at line 2310 of file TCShower.cxx.

2311  {
2312  if (!tcc.useAlg[kMergeNrShowers]) return;
2313  if (slc.cots.empty()) return;
2314 
2315  std::string fcnLabel = inFcnLabel + ".MNS";
2316 
2317  if (prt) {
2318  mf::LogVerbatim myprt("TC");
2319  myprt << fcnLabel << " list";
2320  for (auto& ss : slc.cots) {
2321  if (ss.CTP != inCTP) continue;
2322  if (ss.ID == 0) continue;
2323  myprt << " ss.ID " << ss.ID << " NearTjs";
2324  for (auto& id : ss.NearTjIDs)
2325  myprt << " " << id;
2326  myprt << "\n";
2327  }
2328  } // prt
2329 
2330  bool keepMerging = true;
2331  while (keepMerging) {
2332  keepMerging = false;
2333  for (unsigned short ci1 = 0; ci1 < slc.cots.size() - 1; ++ci1) {
2334  ShowerStruct& ss1 = slc.cots[ci1];
2335  if (ss1.CTP != inCTP) continue;
2336  if (ss1.ID == 0) continue;
2337  if (ss1.TjIDs.empty()) continue;
2338  // put the inshower tjs and the nearby tjs into one list
2339  std::vector<int> ss1list = ss1.TjIDs;
2340  ss1list.insert(ss1list.end(), ss1.NearTjIDs.begin(), ss1.NearTjIDs.end());
2341  for (unsigned short ci2 = ci1 + 1; ci2 < slc.cots.size(); ++ci2) {
2342  ShowerStruct& ss2 = slc.cots[ci2];
2343  if (ss2.CTP != inCTP) continue;
2344  if (ss2.ID == 0) continue;
2345  if (ss2.TjIDs.empty()) continue;
2346  if (DontCluster(slc, ss1.TjIDs, ss2.TjIDs)) continue;
2347  std::vector<int> ss2list = ss2.TjIDs;
2348  ss2list.insert(ss2list.end(), ss2.NearTjIDs.begin(), ss2.NearTjIDs.end());
2349  std::vector<int> shared = SetIntersection(ss1list, ss2list);
2350  if (shared.empty()) continue;
2351  if (prt) {
2352  mf::LogVerbatim myprt("TC");
2353  myprt << fcnLabel << " Merge 2S" << ss2.ID << " into 2S" << ss1.ID
2354  << "? shared nearby:";
2355  for (auto tjid : shared)
2356  myprt << " T" << tjid;
2357  } // prt
2358  // add the shared Tjs to ss1 if they meet the requirements
2359  bool doMerge = false;
2360  for (auto& tjID : shared) {
2361  bool inSS1 = (std::find(ss1.TjIDs.begin(), ss1.TjIDs.end(), tjID) != ss1.TjIDs.end());
2362  bool inSS2 = (std::find(ss2.TjIDs.begin(), ss2.TjIDs.end(), tjID) != ss2.TjIDs.end());
2363  if (inSS1 && !inSS2) doMerge = true;
2364  if (!inSS1 && inSS2) doMerge = true;
2365  // need to add it?
2366  if (inSS1 || inSS2) continue;
2367  auto& tj = slc.tjs[tjID - 1];
2368  // ignore long muons
2369  if (tj.PDGCode == 13 && tj.Pts.size() > 100 && tj.ChgRMS < 0.5) {
2370  if (prt)
2371  mf::LogVerbatim("TC")
2372  << fcnLabel << " T" << tj.ID << " looks like a muon. Don't add it";
2373  continue;
2374  }
2375  // see if it looks like a muon in 3D
2376  if (tj.AlgMod[kMat3D]) {
2377  auto TInP = GetAssns(slc, "T", tj.ID, "P");
2378  if (!TInP.empty()) {
2379  auto& pfp = slc.pfps[TInP[0] - 1];
2380  if (pfp.PDGCode == 13 && MCSMom(slc, pfp.TjIDs) > 500) continue;
2381  } // TInP not empty
2382  } // 3D matched
2383  if (AddTj(fcnLabel, slc, tjID, ss1, false, prt)) doMerge = true;
2384  } // tjID
2385  if (!doMerge) continue;
2386  if (MergeShowersAndStore(fcnLabel, slc, ss1.ID, ss2.ID, prt)) {
2387  Trajectory& stj = slc.tjs[ss1.ShowerTjID - 1];
2388  stj.AlgMod[kMergeNrShowers] = true;
2389  if (prt) mf::LogVerbatim("TC") << fcnLabel << " success";
2390  keepMerging = true;
2391  break;
2392  }
2393  } // ci2
2394  } // ci1
2395  } // keepMerging
2396 
2397  ChkAssns(fcnLabel, slc);
2398 
2399  } //MergeNearby2DShowers
bool AddTj(std::string inFcnLabel, TCSlice &slc, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1448
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3468
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4849
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4157
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< T > SetIntersection(const std::vector< T > &set1, const std::vector< T > &set2)
bool DontCluster(TCSlice &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3258
bool MergeShowersAndStore(std::string inFcnLabel, TCSlice &slc, int icotID, int jcotID, bool prt)
Definition: TCShower.cxx:2946
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
void tca::MergeOverlap ( std::string  inFcnLabel,
TCSlice &  slc,
const CTP_t &  inCTP,
bool  prt 
)

Definition at line 2403 of file TCShower.cxx.

2404  {
2405  // Merge showers whose envelopes overlap each other
2406 
2407  /*
2408  # 0 Mode (<= 0 OFF, 1 = find showers before 3D match, 2 = find showers after 3D match)
2409  # 1 Max Tj MCSMom for a shower tag
2410  # 2 Max separation
2411  # 3 Min energy (MeV)
2412  # 4 rms width factor
2413  # 5 Min shower 1/2 width (WSE units)
2414  # 6 Min total Tj Pts
2415  # 7 Min Tjs
2416  # 8 max parent FOM
2417  # 9 max direction FOM
2418  # 10 max aspect ratio
2419  # 11 Debug in CTP (>10 debug cotID + 10)
2420  */
2421 
2422  if (tcc.showerTag[2] <= 0) return;
2423  if (!tcc.useAlg[kMergeOverlap]) return;
2424  if (slc.cots.empty()) return;
2425 
2426  std::string fcnLabel = inFcnLabel + ".MO";
2427 
2428  // Require that the maximum separation is about two radiation lengths
2429  if (prt)
2430  mf::LogVerbatim("TC") << fcnLabel << " checking using separation cut " << tcc.showerTag[2];
2431 
2432  float sepCut2 = tcc.showerTag[2] * tcc.showerTag[2];
2433 
2434  // Iterate if a merge is done
2435  bool didMerge = true;
2436  while (didMerge) {
2437  didMerge = false;
2438  // See if the envelopes overlap
2439  for (unsigned short ict = 0; ict < slc.cots.size() - 1; ++ict) {
2440  auto& iss = slc.cots[ict];
2441  if (iss.ID == 0) continue;
2442  if (iss.TjIDs.empty()) continue;
2443  if (iss.CTP != inCTP) continue;
2444  for (unsigned short jct = ict + 1; jct < slc.cots.size(); ++jct) {
2445  auto& jss = slc.cots[jct];
2446  if (jss.ID == 0) continue;
2447  if (jss.TjIDs.empty()) continue;
2448  if (jss.CTP != iss.CTP) continue;
2449  if (DontCluster(slc, iss.TjIDs, jss.TjIDs)) continue;
2450  bool doMerge = false;
2451  for (auto& ivx : iss.Envelope) {
2452  doMerge = PointInsideEnvelope(ivx, jss.Envelope);
2453  if (doMerge) break;
2454  } // ivx
2455  if (!doMerge) {
2456  for (auto& jvx : jss.Envelope) {
2457  doMerge = PointInsideEnvelope(jvx, iss.Envelope);
2458  if (doMerge) break;
2459  } // ivx
2460  }
2461  if (!doMerge) {
2462  // check proximity between the envelopes
2463  for (auto& ivx : iss.Envelope) {
2464  for (auto& jvx : jss.Envelope) {
2465  if (PosSep2(ivx, jvx) < sepCut2) {
2466  if (prt)
2467  mf::LogVerbatim("TC")
2468  << fcnLabel << " Envelopes 2S" << iss.ID << " 2S" << jss.ID << " are close "
2469  << PosSep(ivx, jvx) << " cut " << tcc.showerTag[2];
2470  doMerge = true;
2471  break;
2472  }
2473  } // jvx
2474  if (doMerge) break;
2475  } // ivx
2476  } // !domerge
2477  if (!doMerge) continue;
2478  // check the relative positions and angle differences. Determine which tps are the
2479  // closest. Don't merge if the closest points are at the shower start and the angle
2480  // difference is large
2481  unsigned short iClosePt = 0;
2482  unsigned short jClosePt = 0;
2483  float close = 1E6;
2484  auto& istj = slc.tjs[iss.ShowerTjID - 1];
2485  auto& jstj = slc.tjs[jss.ShowerTjID - 1];
2486  for (unsigned short ipt = 0; ipt < 3; ++ipt) {
2487  for (unsigned short jpt = 0; jpt < 3; ++jpt) {
2488  float sep = PosSep2(istj.Pts[ipt].Pos, jstj.Pts[jpt].Pos);
2489  if (sep < close) {
2490  close = sep;
2491  iClosePt = ipt;
2492  jClosePt = jpt;
2493  }
2494  } // jpt
2495  } // ipt
2496  float costh = DotProd(istj.Pts[0].Dir, jstj.Pts[0].Dir);
2497  if (iClosePt == 0 && jClosePt == 0 && costh < 0.955) {
2498  if (prt)
2499  mf::LogVerbatim("TC")
2500  << fcnLabel << " showers are close at the start points with costh " << costh
2501  << ". Don't merge";
2502  continue;
2503  }
2504  if (prt) mf::LogVerbatim("TC") << fcnLabel << " Merge " << iss.ID << " and " << jss.ID;
2505  if (MergeShowersAndStore(fcnLabel, slc, iss.ID, jss.ID, prt)) {
2506  Trajectory& stj = slc.tjs[iss.ShowerTjID - 1];
2507  stj.AlgMod[kMergeOverlap] = true;
2508  didMerge = true;
2509  break;
2510  }
2511  else {
2512  if (prt) mf::LogVerbatim("TC") << fcnLabel << " Merge failed";
2513  }
2514  } // jct
2515  } // ict
2516  } // didMerge
2517 
2518  ChkAssns(fcnLabel, slc);
2519 
2520  } // MergeOverlap
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4157
TCConfig tcc
Definition: DataStructs.cxx:9
bool DontCluster(TCSlice &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3258
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:558
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:3323
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2572
bool MergeShowersAndStore(std::string inFcnLabel, TCSlice &slc, int icotID, int jcotID, bool prt)
Definition: TCShower.cxx:2946
double DotProd(const Vector3_t &v1, const Vector3_t &v2)
Definition: PFPUtils.h:128
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2565
print OUTPUT<< EOF;< setup name="Default"version="1.0">< worldref="volWorld"/></setup ></gdml > EOF close(OUTPUT)
void tca::MergeShowerChain ( std::string  inFcnLabel,
TCSlice &  slc,
const CTP_t &  inCTP,
bool  prt 
)

Definition at line 2524 of file TCShower.cxx.

2525  {
2526  // Merge chains of 3 or more showers that lie on a line
2527 
2528  if (!tcc.useAlg[kMergeShChain]) return;
2529 
2530  std::string fcnLabel = inFcnLabel + ".MSC";
2531 
2532  if (prt) mf::LogVerbatim("TC") << fcnLabel << ": MergeShowerChain inCTP " << inCTP;
2533 
2534  std::vector<int> sids;
2535  std::vector<TrajPoint> tpList;
2536  for (unsigned short ict = 0; ict < slc.cots.size(); ++ict) {
2537  ShowerStruct& iss = slc.cots[ict];
2538  if (iss.ID == 0) continue;
2539  if (iss.TjIDs.empty()) continue;
2540  if (iss.CTP != inCTP) continue;
2541  // ignore wimpy showers
2542  if (iss.Energy < 50) continue;
2543  // save the shower ID
2544  sids.push_back(iss.ID);
2545  // and the shower center TP
2546  tpList.push_back(slc.tjs[iss.ShowerTjID - 1].Pts[1]);
2547  } // ict
2548  if (sids.size() < 3) return;
2549 
2550  // sort by wire so the chain order is reasonable
2551  std::vector<SortEntry> sortVec(sids.size());
2552  for (unsigned short ii = 0; ii < sortVec.size(); ++ii) {
2553  sortVec[ii].index = ii;
2554  sortVec[ii].val = tpList[ii].Pos[0];
2555  }
2556  std::sort(sortVec.begin(), sortVec.end(), valsDecreasing);
2557  auto tsids = sids;
2558  auto ttpList = tpList;
2559  for (unsigned short ii = 0; ii < sortVec.size(); ++ii) {
2560  unsigned short indx = sortVec[ii].index;
2561  sids[ii] = tsids[indx];
2562  tpList[ii] = ttpList[indx];
2563  }
2564 
2565  // TODO: These cuts should be generalized somehow
2566  float minSep = 150;
2567  float maxDelta = 30;
2568  for (unsigned short ii = 0; ii < sids.size() - 2; ++ii) {
2569  auto& iss = slc.cots[sids[ii] - 1];
2570  if (iss.ID == 0) continue;
2571  unsigned short jj = ii + 1;
2572  auto& jss = slc.cots[sids[jj] - 1];
2573  if (jss.ID == 0) continue;
2574  std::vector<int> chain;
2575  float sepij = PosSep(tpList[ii].Pos, tpList[jj].Pos);
2576  if (sepij > minSep) continue;
2577  bool skipit = DontCluster(slc, iss.TjIDs, jss.TjIDs);
2578  if (prt)
2579  mf::LogVerbatim("TC") << fcnLabel << " i2S" << iss.ID << " "
2580  << PrintPos(slc, tpList[ii].Pos) << " j2S" << jss.ID << " "
2581  << PrintPos(slc, tpList[jj].Pos) << " sepij " << sepij << " skipit? "
2582  << skipit;
2583  if (skipit) continue;
2584  // draw a line between these points
2585  TrajPoint tp;
2586  MakeBareTrajPoint(slc, tpList[ii], tpList[jj], tp);
2587  for (unsigned short kk = jj + 1; kk < sids.size(); ++kk) {
2588  auto& kss = slc.cots[sids[kk] - 1];
2589  if (kss.ID == 0) continue;
2590  if (DontCluster(slc, iss.TjIDs, kss.TjIDs)) continue;
2591  if (DontCluster(slc, jss.TjIDs, kss.TjIDs)) continue;
2592  float sepjk = PosSep(tpList[jj].Pos, tpList[kk].Pos);
2593  float delta = PointTrajDOCA(slc, tpList[kk].Pos[0], tpList[kk].Pos[1], tp);
2594  if (prt) {
2595  mf::LogVerbatim myprt("TC");
2596  myprt << fcnLabel << " k2S" << kss.ID << " " << PrintPos(slc, tpList[kk].Pos)
2597  << " sepjk " << sepjk << " delta " << delta;
2598  if (sepjk > minSep || delta > maxDelta) {
2599  myprt << " failed separation " << minSep << " or delta cut " << maxDelta;
2600  }
2601  else {
2602  myprt << " add to the chain";
2603  }
2604  } // prt
2605  if (sepjk > minSep || delta > maxDelta) {
2606  // clear a short chain?
2607  if (chain.size() > 2) {
2608  // merge this chain
2609  int newID = MergeShowers(fcnLabel, slc, chain, prt);
2610  if (prt) {
2611  mf::LogVerbatim myprt("TC");
2612  myprt << fcnLabel << " merged chain";
2613  for (auto ssID : chain)
2614  myprt << " 2S" << ssID;
2615  myprt << " -> 2S" << newID;
2616  } // prt
2617  } // long chain
2618  chain.clear();
2619  break;
2620  }
2621  else {
2622  // add this shower to the chain
2623  if (chain.empty()) {
2624  chain.resize(3);
2625  chain[0] = sids[ii];
2626  chain[1] = sids[jj];
2627  chain[2] = sids[kk];
2628  }
2629  else {
2630  chain.push_back(sids[kk]);
2631  }
2632  // Refine the TP position and direction
2633  MakeBareTrajPoint(slc, tpList[ii], tpList[kk], tp);
2634  } // add to an existing chain
2635  } // kk
2636  // push the last one
2637  if (chain.size() > 2) {
2638  int newID = MergeShowers(fcnLabel, slc, chain, prt);
2639  if (prt) {
2640  mf::LogVerbatim myprt("TC");
2641  myprt << fcnLabel << " merged chain";
2642  for (auto ssID : chain)
2643  myprt << " " << ssID;
2644  myprt << " -> new ssID " << newID;
2645  } // prt
2646  } // long chain
2647  } // ii
2648 
2649  ChkAssns(fcnLabel, slc);
2650 
2651  } // MergeShowerChain
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4157
TCConfig tcc
Definition: DataStructs.cxx:9
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2572
bool MakeBareTrajPoint(const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:4110
bool DontCluster(TCSlice &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3258
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
int MergeShowers(std::string inFcnLabel, TCSlice &slc, std::vector< int > ssIDs, bool prt)
Definition: TCShower.cxx:2884
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2565
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 2884 of file TCShower.cxx.

2885  {
2886  // merge a list of showers and return the ID of the merged shower.
2887  // Returns 0 if there was a failure.
2888 
2889  std::string fcnLabel = inFcnLabel + ".MS";
2890  if (ssIDs.size() < 2) return 0;
2891  // check for a valid ID
2892  for (auto ssID : ssIDs)
2893  if (ssID <= 0 || ssID > (int)slc.cots.size()) return 0;
2894  // check for the same CTP and consistent assns
2895  int ss3Assn = 0;
2896  auto& ss0 = slc.cots[ssIDs[0] - 1];
2897  std::vector<int> tjl;
2898  for (auto ssID : ssIDs) {
2899  auto& ss = slc.cots[ssID - 1];
2900  if (ss.CTP != ss0.CTP) return 0;
2901  tjl.insert(tjl.end(), ss.TjIDs.begin(), ss.TjIDs.end());
2902  if (ss.SS3ID > 0 && ss3Assn == 0) ss3Assn = ss.SS3ID;
2903  if (ss.SS3ID > 0 && ss.SS3ID != ss3Assn) return 0;
2904  } // ssID
2905  // ensure the InShower Tjs are valid
2906  for (auto tjID : tjl) {
2907  auto& tj = slc.tjs[tjID - 1];
2908  if (tj.CTP != ss0.CTP || tj.AlgMod[kKilled]) return 0;
2909  } // tjID
2910 
2911  // mark the old showers killed
2912  for (auto ssID : ssIDs) {
2913  auto& ss = slc.cots[ssID - 1];
2914  ss.ID = 0;
2915  // kill the shower Tj
2916  auto& stj = slc.tjs[ss.ShowerTjID - 1];
2917  stj.AlgMod[kKilled] = true;
2918  } // tjID
2919 
2920  // in with the new
2921  auto newss = CreateSS(slc, tjl);
2922  if (newss.ID == 0) return 0;
2923 
2924  for (auto tid : tjl) {
2925  auto& tj = slc.tjs[tid - 1];
2926  tj.SSID = newss.ID;
2927  } // tid
2928  newss.SS3ID = ss3Assn;
2929 
2930  // define the new shower
2931  if (!UpdateShower(fcnLabel, slc, newss, prt)) {
2932  MakeShowerObsolete(fcnLabel, slc, newss, prt);
2933  return 0;
2934  }
2935  // store it
2936  if (!StoreShower(fcnLabel, slc, newss)) {
2937  MakeShowerObsolete(fcnLabel, slc, newss, prt);
2938  return 0;
2939  }
2940  return newss.ID;
2941 
2942  } // MergeShowers
ShowerStruct CreateSS(TCSlice &slc, const std::vector< int > &tjl)
Definition: TCShower.cxx:4110
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:913
void MakeShowerObsolete(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:3194
bool StoreShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct3D &ss3)
Definition: TCShower.cxx:3991
bool tca::MergeShowersAndStore ( std::string  inFcnLabel,
TCSlice &  slc,
int  icotID,
int  jcotID,
bool  prt 
)

Definition at line 2946 of file TCShower.cxx.

2947  {
2948  // Merge showers using shower indices. The icotID shower is modified in-place.
2949  // The jcotID shower is declared obsolete. This function also re-defines the shower and
2950  // preserves the icotID Parent ID.
2951 
2952  if (icotID <= 0 || icotID > (int)slc.cots.size()) return false;
2953  ShowerStruct& iss = slc.cots[icotID - 1];
2954  if (iss.ID == 0) return false;
2955  if (iss.TjIDs.empty()) return false;
2956  if (iss.ShowerTjID <= 0) return false;
2957 
2958  if (jcotID <= 0 || jcotID > (int)slc.cots.size()) return false;
2959  ShowerStruct& jss = slc.cots[jcotID - 1];
2960  if (jss.TjIDs.empty()) return false;
2961  if (jss.ID == 0) return false;
2962  if (jss.ShowerTjID <= 0) return false;
2963 
2964  if (iss.CTP != jss.CTP) return false;
2965 
2966  std::string fcnLabel = inFcnLabel + ".MSAS";
2967 
2968  if (iss.SS3ID > 0 && jss.SS3ID > 0 && iss.SS3ID != jss.SS3ID) return false;
2969 
2970  Trajectory& itj = slc.tjs[iss.ShowerTjID - 1];
2971  Trajectory& jtj = slc.tjs[jss.ShowerTjID - 1];
2972  if (!itj.Pts[1].Hits.empty() || !jtj.Pts[1].Hits.empty()) return false;
2973 
2974  iss.TjIDs.insert(iss.TjIDs.end(), jss.TjIDs.begin(), jss.TjIDs.end());
2975  // make a new trajectory using itj as a template
2976  Trajectory ktj = itj;
2977  ktj.ID = slc.tjs.size() + 1;
2978 
2979  slc.tjs.push_back(ktj);
2980  // kill jtj
2981  MakeTrajectoryObsolete(slc, iss.ShowerTjID - 1);
2982  MakeTrajectoryObsolete(slc, jss.ShowerTjID - 1);
2983  slc.tjs[iss.ShowerTjID - 1].ParentID = ktj.ID;
2984  slc.tjs[jss.ShowerTjID - 1].ParentID = ktj.ID;
2985  if (prt)
2986  mf::LogVerbatim("TC") << fcnLabel << " killed stj T" << iss.ShowerTjID << " and T"
2987  << jss.ShowerTjID << " new T" << ktj.ID;
2988  // revise the shower
2989  iss.ShowerTjID = ktj.ID;
2990  // transfer the list of Tj IDs
2991  iss.TjIDs.insert(iss.TjIDs.end(), jss.TjIDs.begin(), jss.TjIDs.begin());
2992  std::sort(iss.TjIDs.begin(), iss.TjIDs.end());
2993  // correct the assn
2994  for (auto tid : iss.TjIDs) {
2995  auto& tj = slc.tjs[tid - 1];
2996  tj.SSID = iss.ID;
2997  } // tid
2998  // transfer a 2S -> 3S assn
2999  if (iss.SS3ID == 0 && jss.SS3ID > 0) iss.SS3ID = jss.SS3ID;
3000  // merge the list of nearby Tjs
3001  iss.NearTjIDs.insert(iss.NearTjIDs.end(), jss.NearTjIDs.begin(), jss.NearTjIDs.end());
3002  // transfer the TruParentID if it is in jss
3003  if (jss.TruParentID > 0) iss.TruParentID = jss.TruParentID;
3004  iss.NeedsUpdate = true;
3005  // force a full update
3006  iss.ShPts.clear();
3007  jss.ID = 0;
3008  bool success = UpdateShower(fcnLabel, slc, iss, prt);
3009  KillVerticesInShower(fcnLabel, slc, iss, prt);
3010 
3011  return success;
3012 
3013  } // MergeShowersAndStore
void KillVerticesInShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:711
void MakeTrajectoryObsolete(TCSlice &slc, unsigned int itj)
Definition: Utils.cxx:2184
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:913
bool tca::MergeShowerTjsAndStore ( TCSlice &  slc,
unsigned short  istj,
unsigned short  jstj,
bool  prt 
)

Definition at line 3017 of file TCShower.cxx.

3018  {
3019  // Merge showers using showerTj indices
3020  // This function is called from MergeAndStore whose function is to merge two line-like
3021  // trajectories and store them. This function was called because at least one of the
3022  // trajectories is a shower Tj. Assume that the decision to merge them has been made elsewhere.
3023 
3024  if (istj > slc.tjs.size() - 1) return false;
3025  if (jstj > slc.tjs.size() - 1) return false;
3026 
3027  Trajectory& itj = slc.tjs[istj];
3028  Trajectory& jtj = slc.tjs[jstj];
3029 
3030  std::string fcnLabel = "MSTJ";
3031 
3032  if (prt)
3033  mf::LogVerbatim("TC") << fcnLabel << " MergeShowerTjsAndStore Tj IDs " << itj.ID << " "
3034  << jtj.ID;
3035 
3036  // First we check to make sure that both are shower Tjs.
3037  if (!itj.AlgMod[kShowerTj] && !jtj.AlgMod[kShowerTj]) {
3038  if (prt) mf::LogVerbatim("TC") << " One of these isn't a shower Tj";
3039  return false;
3040  }
3041 
3042  // We need to keep the convention used in MergeAndStore to create a new merged trajectory
3043  // and kill the two fragments. This doesn't require making a new shower however. We can just
3044  // re-purpose one of the existing showers
3045  int icotID = GetCotID(slc, itj.ID);
3046  if (icotID == 0) return false;
3047  ShowerStruct& iss = slc.cots[icotID - 1];
3048  if (iss.ID == 0) return false;
3049  if (iss.TjIDs.empty()) return false;
3050  int jcotID = GetCotID(slc, jtj.ID);
3051  if (jcotID == 0) return false;
3052  ShowerStruct& jss = slc.cots[jcotID - 1];
3053  if (jss.ID == 0) return false;
3054  if (jss.TjIDs.empty()) return false;
3055 
3056  return MergeShowersAndStore(fcnLabel, slc, icotID, jcotID, prt);
3057 
3058  } // MergeShowerTjsAndStore
int GetCotID(TCSlice &slc, int ShowerTjID)
Definition: TCShower.cxx:3943
bool MergeShowersAndStore(std::string inFcnLabel, TCSlice &slc, int icotID, int jcotID, bool prt)
Definition: TCShower.cxx:2946
void tca::MergeSubShowers ( std::string  inFcnLabel,
TCSlice &  slc,
const CTP_t &  inCTP,
bool  prt 
)

Definition at line 2767 of file TCShower.cxx.

2768  {
2769  // Merge small showers that are downstream of larger showers
2770 
2771  if (!tcc.useAlg[kMergeSubShowers]) return;
2772 
2773  std::string fcnLabel = inFcnLabel + ".MSS";
2774  bool newCuts = (tcc.showerTag[0] == 4);
2775  constexpr float radLen = 14 / 0.3;
2776 
2777  if (prt) {
2778  if (newCuts) {
2779  mf::LogVerbatim("TC") << fcnLabel << " MergeSubShowers checking using ShowerParams";
2780  }
2781  else {
2782  mf::LogVerbatim("TC") << fcnLabel
2783  << " MergeSubShowers checking using radiation length cut ";
2784  }
2785  } // prt
2786 
2787  bool keepMerging = true;
2788  while (keepMerging) {
2789  keepMerging = false;
2790  // sort by decreasing energy
2791  std::vector<SortEntry> sortVec;
2792  for (auto& ss : slc.cots) {
2793  if (ss.ID == 0) continue;
2794  if (ss.CTP != inCTP) continue;
2795  SortEntry se;
2796  se.index = ss.ID - 1;
2797  se.val = ss.Energy;
2798  sortVec.push_back(se);
2799  } // ss
2800  if (sortVec.size() < 2) return;
2801  std::sort(sortVec.begin(), sortVec.end(), valsIncreasing);
2802  for (unsigned short ii = 0; ii < sortVec.size() - 1; ++ii) {
2803  ShowerStruct& iss = slc.cots[sortVec[ii].index];
2804  if (iss.ID == 0) continue;
2805  // this shouldn't be done to showers that are ~round
2806  if (iss.AspectRatio > 0.5) continue;
2807  TrajPoint& istp1 = slc.tjs[iss.ShowerTjID - 1].Pts[1];
2808  double shMaxAlong, along95;
2809  ShowerParams((double)iss.Energy, shMaxAlong, along95);
2810  // convert along95 to a separation btw shower max and along95
2811  along95 -= shMaxAlong;
2812  // convert to WSE
2813  along95 /= tcc.wirePitch;
2814  for (unsigned short jj = ii + 1; jj < sortVec.size(); ++jj) {
2815  ShowerStruct& jss = slc.cots[sortVec[jj].index];
2816  if (jss.ID == 0) continue;
2817  if (DontCluster(slc, iss.TjIDs, jss.TjIDs)) continue;
2818  TrajPoint& jstp1 = slc.tjs[jss.ShowerTjID - 1].Pts[1];
2819  if (newCuts) {
2820  // find the longitudinal and transverse separation using the higher energy
2821  // shower which probably is better defined.
2822  Point2_t alongTrans;
2823  FindAlongTrans(istp1.Pos, istp1.Dir, jstp1.Pos, alongTrans);
2824  // the lower energy shower is at the wrong end of the higher energy shower if alongTrans[0] < 0
2825  if (alongTrans[0] < 0) continue;
2826  // increase the cut if the second shower is < 10% of the first shower
2827  float alongCut = along95;
2828  if (jss.Energy < 0.1 * iss.Energy) alongCut *= 1.5;
2829  float probLong = InShowerProbLong(iss.Energy, alongTrans[0]);
2830  float probTran = InShowerProbTrans(iss.Energy, alongTrans[0], alongTrans[1]);
2831  if (prt) {
2832  mf::LogVerbatim myprt("TC");
2833  myprt << fcnLabel << " Candidate i2S" << iss.ID << " E = " << (int)iss.Energy
2834  << " j2S" << jss.ID << " E = " << (int)jss.Energy;
2835  myprt << " along " << std::fixed << std::setprecision(1) << alongTrans[0] << " trans "
2836  << alongTrans[1];
2837  myprt << " alongCut " << alongCut << " probLong " << probLong << " probTran "
2838  << probTran;
2839  } // prt
2840  if (alongTrans[0] > alongCut) continue;
2841  if (alongTrans[1] > alongTrans[0]) continue;
2842  }
2843  else {
2844  // old cuts
2845  float sep = PosSep(istp1.Pos, jstp1.Pos);
2846  float trad = sep / radLen;
2847  // Find the IP between them using the projection of the one with the lowest aspect ratio
2848  float delta = 9999;
2849  if (iss.AspectRatio < jss.AspectRatio) {
2850  delta = PointTrajDOCA(slc, jstp1.Pos[0], jstp1.Pos[1], istp1);
2851  }
2852  else {
2853  delta = PointTrajDOCA(slc, istp1.Pos[0], istp1.Pos[1], jstp1);
2854  }
2855  // See if delta is consistent with the cone angle of the i shower
2856  float dang = delta / sep;
2857  if (prt)
2858  mf::LogVerbatim("TC") << fcnLabel << " Candidate i2S" << iss.ID << " j2S" << jss.ID
2859  << " separation " << (int)sep << " radiation lengths " << trad
2860  << " delta " << delta << " dang " << dang;
2861  if (trad > 3) continue;
2862  // There must be a correlation between dang and the energy of these showers...
2863  if (dang > 0.3) continue;
2864  } // old cuts
2865 
2866  if (prt) mf::LogVerbatim("TC") << fcnLabel << " Merge them. Re-find shower center, etc";
2867  if (MergeShowersAndStore(fcnLabel, slc, iss.ID, jss.ID, prt)) {
2868  Trajectory& stj = slc.tjs[iss.ShowerTjID - 1];
2869  stj.AlgMod[kMergeSubShowers] = true;
2870  keepMerging = true;
2871  break;
2872  }
2873  } // jj
2874  if (keepMerging) break;
2875  } // ii
2876  } // keepMerging
2877 
2878  ChkAssns(fcnLabel, slc);
2879 
2880  } // MergeSubShowers
double InShowerProbLong(double showerEnergy, double along)
Definition: TCShower.cxx:1958
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4157
TCConfig tcc
Definition: DataStructs.cxx:9
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:3097
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2572
double InShowerProbTrans(double showerEnergy, double along, double trans)
Definition: TCShower.cxx:1994
bool DontCluster(TCSlice &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3258
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:558
std::array< float, 2 > Point2_t
Definition: DataStructs.h:43
bool valsIncreasing(const SortEntry &c1, const SortEntry &c2)
Definition: Utils.cxx:39
bool MergeShowersAndStore(std::string inFcnLabel, TCSlice &slc, int icotID, int jcotID, bool prt)
Definition: TCShower.cxx:2946
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
Definition: TCShower.cxx:1923
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2565
void tca::MergeSubShowersTj ( std::string  inFcnLabel,
TCSlice &  slc,
const CTP_t &  inCTP,
bool  prt 
)

Definition at line 2655 of file TCShower.cxx.

2656  {
2657  // merge small showers that are downstream of shower-like tjs. This algorithm is written
2658  // for low-energy showers with are likely to be sparse and poorly defined.
2659 
2660  if (!tcc.useAlg[kMergeSubShowersTj]) return;
2661 
2662  std::string fcnLabel = inFcnLabel + ".MSSTj";
2663 
2664  struct TjSS {
2665  int ssID;
2666  int tjID;
2667  float dang;
2668  };
2669  std::vector<TjSS> tjss;
2670 
2671  // temp vector for DontCluster
2672  std::vector<int> tjid(1);
2673  for (auto& ss : slc.cots) {
2674  if (ss.ID == 0) continue;
2675  if (ss.CTP != inCTP) continue;
2676  // TODO: Evaluate this cut
2677  if (ss.Energy > 300) continue;
2678  auto& stj = slc.tjs[ss.ShowerTjID - 1];
2679  auto stp0 = stj.Pts[0];
2680  float bestDang = 0.3;
2681  int bestTj = 0;
2682  // look for a Tj that has higher energy than the shower
2683  for (auto& tj : slc.tjs) {
2684  if (tj.AlgMod[kKilled]) continue;
2685  if (tj.AlgMod[kHaloTj]) continue;
2686  if (tj.CTP != ss.CTP) continue;
2687  // require that it isn't in any shower
2688  if (tj.SSID > 0) continue;
2689  // require it to be not short
2690  if (NumPtsWithCharge(slc, tj, false) < 10) continue;
2691  // and satisfy the ShowerLike MCSMom cut. It is unlikely to be tagged shower-like
2692  if (tj.MCSMom > tcc.showerTag[1]) continue;
2693  // check consistency
2694  tjid[0] = tj.ID;
2695  if (DontCluster(slc, tjid, ss.TjIDs)) continue;
2696  float tjEnergy = ChgToMeV(tj.TotChg);
2697  // find the end that is furthest away from the shower center
2698  unsigned short farEnd = FarEnd(slc, tj, stj.Pts[1].Pos);
2699  // compare MCSMom at the far end and the near end
2700  unsigned short midpt = 0.5 * (tj.EndPt[0] + tj.EndPt[1]);
2701  float mom1 = MCSMom(slc, tj, tj.EndPt[farEnd], midpt);
2702  float mom2 = MCSMom(slc, tj, tj.EndPt[1 - farEnd], midpt);
2703  float asym = (mom1 - mom2) / (mom1 + mom2);
2704  auto& farTP = tj.Pts[tj.EndPt[farEnd]];
2705  // IP btw the far end TP and the shower center
2706  float doca = PointTrajDOCA(slc, stp0.Pos[0], stp0.Pos[1], farTP);
2707  float sep = PosSep(farTP.Pos, stp0.Pos);
2708  float dang = doca / sep;
2709  if (prt) {
2710  mf::LogVerbatim myprt("TC");
2711  myprt << fcnLabel << " Candidate 2S" << ss.ID << " T" << tj.ID << "_" << farEnd;
2712  myprt << " ShEnergy " << (int)ss.Energy << " tjEnergy " << (int)tjEnergy;
2713  myprt << " doca " << doca << " sep " << sep << " dang " << dang << " asym " << asym;
2714  }
2715  if (tjEnergy < ss.Energy) continue;
2716  if (asym < 0.5) continue;
2717  // TODO: This should be done more carefully
2718  // separation cut 100 WSE ~ 30 cm in uB
2719  if (sep > 100) continue;
2720  if (dang > bestDang) continue;
2721  bestDang = dang;
2722  bestTj = tj.ID;
2723  } // tj
2724  if (bestTj == 0) continue;
2725  TjSS match;
2726  match.ssID = ss.ID;
2727  match.tjID = bestTj;
2728  match.dang = bestDang;
2729  tjss.push_back(match);
2730  } // ss
2731 
2732  if (tjss.empty()) return;
2733 
2734  // ensure that a tj is only put in one shower
2735  bool keepGoing = true;
2736  while (keepGoing) {
2737  keepGoing = false;
2738  float bestDang = 0.3;
2739  int bestMatch = 0;
2740  for (unsigned short mat = 0; mat < tjss.size(); ++mat) {
2741  auto& match = tjss[mat];
2742  // already used
2743  if (match.dang < 0) continue;
2744  if (match.dang < bestDang) bestMatch = mat;
2745  } // mat
2746  if (bestMatch > 0) {
2747  auto& match = tjss[bestMatch];
2748  auto& ss = slc.cots[match.ssID - 1];
2749  if (!AddTj(fcnLabel, slc, match.tjID, ss, true, prt)) {
2750  if (prt) mf::LogVerbatim("TC") << " Failed";
2751  continue;
2752  }
2753  match.dang = -1;
2754  // set the AlgMod bit
2755  auto& stj = slc.tjs[ss.ShowerTjID - 1];
2756  stj.AlgMod[kMergeSubShowersTj] = true;
2757  keepGoing = true;
2758  } // found bestMatch
2759  } // keepGoing
2760 
2761  ChkAssns(fcnLabel, slc);
2762 
2763  } // MergeSubShowersTj
bool AddTj(std::string inFcnLabel, TCSlice &slc, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1448
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3468
unsigned short FarEnd(const TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3339
bool ChkAssns(std::string inFcnLabel, TCSlice &slc)
Definition: TCShower.cxx:4157
TCConfig tcc
Definition: DataStructs.cxx:9
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2572
bool DontCluster(TCSlice &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3258
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:558
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2565
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2116
float ChgToMeV(float chg)
Definition: TCShower.cxx:3982
bool tca::MergeTjIntoPFP ( TCSlice &  slc,
int  mtjid,
PFPStruct &  pfp,
bool  prt 
)

Definition at line 513 of file Utils.cxx.

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

Definition at line 1303 of file TCShower.cxx.

1304  {
1305  // Merge the lists of Tjs in the lists if they share a common Tj ID
1306 
1307  if (tjList.size() < 2) return;
1308 
1309  bool didMerge = true;
1310  while (didMerge) {
1311  didMerge = false;
1312  for (unsigned short itl = 0; itl < tjList.size() - 1; ++itl) {
1313  if (tjList[itl].empty()) continue;
1314  for (unsigned short jtl = itl + 1; jtl < tjList.size(); ++jtl) {
1315  if (tjList[itl].empty()) continue;
1316  auto& itList = tjList[itl];
1317  auto& jtList = tjList[jtl];
1318  // See if the j Tj is in the i tjList
1319  bool jtjInItjList = false;
1320  for (auto& jtj : jtList) {
1321  if (std::find(itList.begin(), itList.end(), jtj) != itList.end()) {
1322  jtjInItjList = true;
1323  break;
1324  }
1325  if (jtjInItjList) break;
1326  } // jtj
1327  if (jtjInItjList) {
1328  // append the jtList to itList
1329  itList.insert(itList.end(), jtList.begin(), jtList.end());
1330  // clear jtList
1331  jtList.clear();
1332  didMerge = true;
1333  }
1334  } // jtl
1335  } // itl
1336  } // didMerge
1337 
1338  // erase the deleted elements
1339  unsigned short imEmpty = 0;
1340  while (imEmpty < tjList.size()) {
1341  for (imEmpty = 0; imEmpty < tjList.size(); ++imEmpty)
1342  if (tjList[imEmpty].empty()) break;
1343  if (imEmpty < tjList.size()) tjList.erase(tjList.begin() + imEmpty);
1344  } // imEmpty < tjList.size()
1345 
1346  // sort the lists by increasing ID and remove duplicates
1347  for (auto& tjl : tjList) {
1348  std::sort(tjl.begin(), tjl.end());
1349  auto last = std::unique(tjl.begin(), tjl.end());
1350  tjl.erase(last, tjl.end());
1351  } // tjl
1352 
1353  } // MergeTjList
bool empty(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:555
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 435 of file TCVertex.cxx.

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

Definition at line 2831 of file Utils.cxx.

2832  {
2833  // Project TP to a "wire position" Pos[0] and update Pos[1]
2834  if (tp.Dir[0] == 0) return;
2835  float dw = wire - tp.Pos[0];
2836  if (std::abs(dw) < 0.01) return;
2837  tp.Pos[0] = wire;
2838  tp.Pos[1] += dw * tp.Dir[1] / tp.Dir[0];
2839  } // MoveTPToWire
T abs(T value)
unsigned short tca::NearbyCleanPt ( const TCSlice &  slc,
const Trajectory &  tj,
unsigned short  end 
)

Definition at line 2956 of file Utils.cxx.

2957  {
2958  // Searches for a TP near the end (or beginnin) that doesn't have the kEnvOverlap bit set
2959  // with the intent that a fit of a vertex position using this tj will be minimally
2960  // biased if there are no nearby hits from other tjs. A search is done from the
2961  // supplied nearPt moving in the + direction if nearPt == tj.EndPt[0] and moving in
2962  // the - direction if nearPt == tj.EndPt[1]
2963  if (end > 1) return USHRT_MAX;
2964  short dir = 1;
2965  if (end == 1) dir = -1;
2966  for (short ii = 0; ii < (short)tj.Pts.size(); ++ii) {
2967  short ipt = tj.EndPt[end] + dir * ii;
2968  if (ipt < 0 || ipt >= (short)tj.Pts.size()) return USHRT_MAX;
2969  auto& tp = tj.Pts[ipt];
2970  if (!tp.Environment[kEnvOverlap]) return ipt;
2971  } // ii
2972  return tj.EndPt[end];
2973  } // FindCleanPt
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
tuple dir
Definition: dropbox.py:28
bool tca::NearbySrcHit ( geo::PlaneID  plnID,
unsigned int  wire,
float  loTick,
float  hiTick 
)

Definition at line 2071 of file Utils.cxx.

2072  {
2073  // Look for a hit on wid in the srcHits collection that has a tick in the range. This
2074  // is a DUNE-specific function in which hit disambiguation is done in the U and V planes
2075  if (evt.srcHits == NULL) return false;
2076  unsigned int pln = plnID.Plane;
2077  if (pln == 2) return false;
2078 
2079  unsigned int cstat = plnID.Cryostat;
2080  unsigned int tpc = plnID.TPC;
2081  // get a valid range of hits to search
2082  if (evt.tpcSrcHitRange[tpc].first >= (*evt.srcHits).size()) return false;
2083  if (evt.tpcSrcHitRange[tpc].second >= (*evt.srcHits).size()) return false;
2084  raw::ChannelID_t chan = tcc.geom->PlaneWireToChannel((int)pln, (int)wire, (int)tpc, (int)cstat);
2085  float atTick = 0.5 * (loTick + hiTick);
2086  for (unsigned int iht = evt.tpcSrcHitRange[tpc].first; iht <= evt.tpcSrcHitRange[tpc].second;
2087  ++iht) {
2088  auto& hit = (*evt.srcHits)[iht];
2089  if (hit.Channel() != chan) continue;
2090  if (atTick < hit.PeakTime()) {
2091  float loHitTick = hit.PeakTime() - 3 * hit.RMS();
2092  if (hiTick > loHitTick) return true;
2093  }
2094  else {
2095  float hiHitTick = hit.PeakTime() + 3 * hit.RMS();
2096  if (loTick < hiHitTick) return true;
2097  }
2098  } // iht
2099  return false;
2100  } // NearbySrcHit
TCConfig tcc
Definition: DataStructs.cxx:9
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:212
std::vector< std::pair< unsigned int, unsigned int > > tpcSrcHitRange
Definition: DataStructs.h:628
process_name hit
Definition: cheaterreco.fcl:51
const geo::GeometryCore * geom
Definition: DataStructs.h:576
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
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:623
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:406
unsigned short tca::NearestPtWithChg ( const TCSlice &  slc,
const Trajectory &  tj,
unsigned short  thePt 
)

Definition at line 3522 of file Utils.cxx.

3523  {
3524  // returns a point near thePt which has charge
3525  if (thePt > tj.EndPt[1]) return thePt;
3526  if (tj.Pts[thePt].Chg > 0) return thePt;
3527 
3528  short endPt0 = tj.EndPt[0];
3529  short endPt1 = tj.EndPt[1];
3530  for (short off = 1; off < 10; ++off) {
3531  short ipt = thePt + off;
3532  if (ipt <= endPt1 && tj.Pts[ipt].Chg > 0) return (unsigned short)ipt;
3533  ipt = thePt - off;
3534  if (ipt >= endPt0 && tj.Pts[ipt].Chg > 0) return (unsigned short)ipt;
3535  } // off
3536  return thePt;
3537  } // NearestPtWithChg
int tca::NeutrinoPrimaryTjID ( const TCSlice &  slc,
const Trajectory &  tj 
)

Definition at line 444 of file Utils.cxx.

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

Definition at line 4328 of file Utils.cxx.

4329  {
4330  // Counts the number of hits of the specified type in tp
4331  if (tp.Hits.empty()) return 0;
4332 
4333  if (hitRequest == kAllHits) return tp.Hits.size();
4334 
4335  unsigned short nhits = 0;
4336  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
4337  if (hitRequest == kUsedHits) {
4338  if (tp.UseHit[ii]) ++nhits;
4339  }
4340  else {
4341  // looking for unused hits
4342  if (!tp.UseHit[ii]) ++nhits;
4343  }
4344  } // ii
4345  return nhits;
4346  } // NumHitsInTP
unsigned short tca::NumPtsWithCharge ( const TCSlice &  slc,
const Trajectory &  tj,
bool  includeDeadWires 
)

Definition at line 2116 of file Utils.cxx.

2117  {
2118  unsigned short firstPt = tj.EndPt[0];
2119  unsigned short lastPt = tj.EndPt[1];
2120  return NumPtsWithCharge(slc, tj, includeDeadWires, firstPt, lastPt);
2121  }
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2116
unsigned short tca::NumPtsWithCharge ( const TCSlice &  slc,
const Trajectory &  tj,
bool  includeDeadWires,
unsigned short  firstPt,
unsigned short  lastPt 
)

Definition at line 2125 of file Utils.cxx.

2130  {
2131  unsigned short ntp = 0;
2132  for (unsigned short ipt = firstPt; ipt <= lastPt; ++ipt)
2133  if (tj.Pts[ipt].Chg > 0) ++ntp;
2134  // Add the count of deadwires
2135  if (includeDeadWires) ntp += DeadWireCount(slc, tj.Pts[firstPt], tj.Pts[lastPt]);
2136  return ntp;
2137  } // NumPtsWithCharge
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2141
unsigned short tca::NumUsedHitsInTj ( const TCSlice &  slc,
const Trajectory &  tj 
)

Definition at line 4314 of file Utils.cxx.

4315  {
4316  if (tj.AlgMod[kKilled]) return 0;
4317  if (tj.Pts.empty()) return 0;
4318  unsigned short nhits = 0;
4319  for (auto& tp : tj.Pts) {
4320  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii)
4321  if (tp.UseHit[ii]) ++nhits;
4322  } // tp
4323  return nhits;
4324  } // NumHitsInTj
float tca::OverlapFraction ( const TCSlice &  slc,
const Trajectory &  tj1,
const Trajectory &  tj2 
)

Definition at line 713 of file Utils.cxx.

714  {
715  // returns the fraction of wires spanned by two trajectories
716  float minWire = 1E6;
717  float maxWire = -1E6;
718 
719  float cnt1 = 0;
720  for (auto& tp : tj1.Pts) {
721  if (tp.Chg == 0) continue;
722  if (tp.Pos[0] < 0) continue;
723  if (tp.Pos[0] < minWire) minWire = tp.Pos[0];
724  if (tp.Pos[0] > maxWire) maxWire = tp.Pos[0];
725  ++cnt1;
726  }
727  if (cnt1 == 0) return 0;
728  float cnt2 = 0;
729  for (auto& tp : tj2.Pts) {
730  if (tp.Chg == 0) continue;
731  if (tp.Pos[0] < 0) continue;
732  if (tp.Pos[0] < minWire) minWire = tp.Pos[0];
733  if (tp.Pos[0] > maxWire) maxWire = tp.Pos[0];
734  ++cnt2;
735  }
736  if (cnt2 == 0) return 0;
737  int span = maxWire - minWire;
738  if (span <= 0) return 0;
739  std::vector<unsigned short> wcnt(span);
740  for (auto& tp : tj1.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  for (auto& tp : tj2.Pts) {
748  if (tp.Chg == 0) continue;
749  if (tp.Pos[0] < -0.4) continue;
750  int indx = std::nearbyint(tp.Pos[0] - minWire);
751  if (indx < 0 || indx > span - 1) continue;
752  ++wcnt[indx];
753  }
754  float cntOverlap = 0;
755  for (auto cnt : wcnt)
756  if (cnt > 1) ++cntOverlap;
757  if (cnt1 < cnt2) { return cntOverlap / cnt1; }
758  else {
759  return cntOverlap / cnt2;
760  }
761 
762  } // OverlapFraction
float tca::ParentFOM ( std::string  inFcnLabel,
TCSlice &  slc,
PFPStruct &  pfp,
unsigned short  pend,
ShowerStruct3D &  ss3,
bool  prt 
)

Definition at line 2077 of file TCShower.cxx.

2083  {
2084  // Returns an average weighted parent FOM for all trajectories in the pfp being a parent of the 2D showers in ss3
2085  if (ss3.ID == 0) return 1000;
2086  float sum = 0;
2087  float wsum = 0;
2088  std::string fcnLabel = inFcnLabel + ".P3FOM";
2089  float dum1, dum2;
2090  for (auto cid : ss3.CotIDs) {
2091  auto& ss = slc.cots[cid - 1];
2092  if (ss.ID == 0) continue;
2093  // look for the 3D matched tj in this CTP
2094  int tjid = 0;
2095  for (auto tid : pfp.TjIDs) {
2096  auto& tj = slc.tjs[tid - 1];
2097  if (tj.ID == 0) continue;
2098  if (tj.CTP == ss.CTP) tjid = tid;
2099  } // tid
2100  if (tjid == 0) continue;
2101  auto& ptj = slc.tjs[tjid - 1];
2102  auto& stj = slc.tjs[ss.ShowerTjID - 1];
2103  // determine which end is farthest away from the shower center
2104  unsigned short ptjEnd = FarEnd(slc, ptj, stj.Pts[1].Pos);
2105  auto& farTP = ptj.Pts[ptj.EndPt[ptjEnd]];
2106  float chgCtrSep2 = PosSep2(farTP.Pos, stj.Pts[1].Pos);
2107  if (chgCtrSep2 < PosSep2(farTP.Pos, stj.Pts[0].Pos) &&
2108  chgCtrSep2 < PosSep2(farTP.Pos, stj.Pts[2].Pos))
2109  continue;
2110  float fom = ParentFOM(fcnLabel, slc, ptj, ptjEnd, ss, dum1, dum2, prt);
2111  // ignore failures
2112  if (fom > 50) continue;
2113  // weight by the 1/aspect ratio
2114  float wt = 1;
2115  if (ss.AspectRatio > 0) wt = 1 / ss.AspectRatio;
2116  sum += wt * fom;
2117  wsum += wt;
2118  } // cid
2119  if (wsum == 0) return 100;
2120  float fom = sum / wsum;
2121  if (prt)
2122  mf::LogVerbatim("TC") << fcnLabel << " 3S" << ss3.ID << " P" << pfp.ID << " fom "
2123  << std::fixed << std::setprecision(3) << fom;
2124  return fom;
2125  } // ParentFOM
unsigned short FarEnd(const TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3339
float ParentFOM(std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, unsigned short pend, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:2077
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2572
float tca::ParentFOM ( std::string  inFcnLabel,
TCSlice &  slc,
Trajectory &  tj,
unsigned short &  tjEnd,
ShowerStruct &  ss,
float &  tp1Sep,
float &  vx2Score,
bool  prt 
)

Definition at line 2129 of file TCShower.cxx.

2137  {
2138  // returns a FOM for the trajectory at the end point being the parent of ss and the end which
2139  // was matched.
2140 
2141  vx2Score = 0;
2142  tp1Sep = 0;
2143 
2144  if (tjEnd > 1) return 1000;
2145  if (ss.Energy == 0) return 1000;
2146 
2147  if (ss.ID == 0) return 1000;
2148  if (ss.TjIDs.empty()) return 1000;
2149  if (ss.ShowerTjID == 0) return 1000;
2150 
2151  std::string fcnLabel = inFcnLabel + ".PFOM";
2152 
2153  if (ss.AspectRatio > 0.5) {
2154  if (prt)
2155  mf::LogVerbatim("TC") << fcnLabel << " 2S" << ss.ID << " poor AspectRatio "
2156  << ss.AspectRatio << " FOM not calculated";
2157  return 100;
2158  }
2159 
2160  float fom = 0;
2161  float cnt = 0;
2162  auto& stj = slc.tjs[ss.ShowerTjID - 1];
2163  TrajPoint& stp0 = stj.Pts[0];
2164  // Shower charge center TP
2165  TrajPoint& stp1 = stj.Pts[1];
2166  // get the end that is farthest away from the shower center
2167  tjEnd = FarEnd(slc, tj, stp1.Pos);
2168  // prospective parent TP
2169  TrajPoint& ptp = tj.Pts[tj.EndPt[tjEnd]];
2170  // find the along and trans components in WSE units relative to the
2171  // shower center
2172  Point2_t alongTrans;
2173  FindAlongTrans(stp1.Pos, stp1.Dir, ptp.Pos, alongTrans);
2174  // We can return here if the shower direction is well defined and
2175  // alongTrans[0] is > 0
2176  if (ss.AspectRatio < 0.2 && ss.DirectionFOM < 0.5 && alongTrans[0] > 0) return 100;
2177  tp1Sep = std::abs(alongTrans[0]);
2178  // Find the expected shower start relative to shower max (cm)
2179  double shMaxAlong, shE95Along;
2180  ShowerParams(ss.Energy, shMaxAlong, shE95Along);
2181  double alongcm = tcc.wirePitch * tp1Sep;
2182  // InShowerProbLong expects the longitudinal distance relative to shower max so it
2183  // should be < 0
2184  float prob = InShowerProbLong(ss.Energy, -alongcm);
2185  if (prob < 0.05) return 100;
2186  // The transverse position must certainly be less than the longitudinal distance
2187  // to shower max.
2188  if (alongTrans[1] > shMaxAlong) return 100;
2189  // longitudinal contribution to fom with 1 Xo error error (14 cm)
2190  float longFOM = std::abs(alongcm + shMaxAlong) / 14;
2191  fom += longFOM;
2192  ++cnt;
2193  // transverse contribution
2194  float transFOM = -1;
2195  if (stp0.DeltaRMS > 0) {
2196  transFOM = alongTrans[1] / stp0.DeltaRMS;
2197  fom += transFOM;
2198  ++cnt;
2199  }
2200  // make a tp between the supposed parent TP and the shower center
2201  TrajPoint tp;
2202  if (!MakeBareTrajPoint(slc, ptp, stp1, tp)) return 100;
2203  // we have three angles to compare. The ptp angle, the shower angle and
2204  // the tp angle.
2205  float dang1 = DeltaAngle(ptp.Ang, stp1.Ang);
2206  float dang1FOM = dang1 / 0.1;
2207  fom += dang1FOM;
2208  ++cnt;
2209  float dang2 = DeltaAngle(ptp.Ang, tp.Ang);
2210  float dang2FOM = dang1 / 0.1;
2211  fom += dang2FOM;
2212  ++cnt;
2213  // the environment near the parent start should be clean.
2214  std::vector<int> tjlist(1);
2215  tjlist[0] = tj.ID;
2216  // check for a vertex at this end and include the vertex tjs if the vertex is close
2217  // to the expected shower max position
2218  float vx2Sep = 0;
2219  // put in a largish FOM value for Tjs that don't have a vertex
2220  float vxFOM = 10;
2221  if (tj.VtxID[tjEnd] > 0) {
2222  VtxStore& vx2 = slc.vtxs[tj.VtxID[tjEnd] - 1];
2223  vx2Sep = PosSep(vx2.Pos, stp1.Pos);
2224  vx2Score = vx2.Score;
2225  tjlist = GetAssns(slc, "2V", vx2.ID, "T");
2226  vxFOM = std::abs(shMaxAlong - vx2Sep) / 20;
2227  } // 2D vertex exists
2228  fom += vxFOM;
2229  ++cnt;
2230  float chgFrac = ChgFracNearPos(slc, ptp.Pos, tjlist);
2231  float chgFracFOM = (1 - chgFrac) / 0.1;
2232  fom += chgFracFOM;
2233  ++cnt;
2234  // Fraction of wires that have a signal between the parent start and the shower center
2235  float chgFracBtw = ChgFracBetween(slc, ptp, stp1.Pos[0]);
2236  float chgFrcBtwFOM = (1 - chgFrac) / 0.05;
2237  fom += chgFrcBtwFOM;
2238  ++cnt;
2239 
2240  // take the average
2241  fom /= cnt;
2242  // divide by the InShowerProbability
2243  fom /= prob;
2244 
2245  if (prt) {
2246  mf::LogVerbatim myprt("TC");
2247  myprt << fcnLabel;
2248  myprt << " 2S" << ss.ID;
2249  myprt << " T" << tj.ID << "_" << tjEnd << " Pos " << PrintPos(slc, ptp);
2250  myprt << std::fixed << std::setprecision(2);
2251  myprt << " along " << std::fixed << std::setprecision(1) << alongTrans[0] << " fom "
2252  << longFOM;
2253  myprt << " trans " << alongTrans[1] << " fom " << transFOM;
2254  myprt << " prob " << prob;
2255  myprt << " dang1 " << dang1 << " fom " << dang1FOM;
2256  myprt << " dang2 " << dang2 << " fom " << dang2FOM;
2257  myprt << " vx2Score " << vx2Score << " fom " << vxFOM;
2258  myprt << " chgFrac " << chgFrac << " fom " << chgFracFOM;
2259  myprt << " chgFracBtw " << chgFracBtw << " fom " << chgFrcBtwFOM;
2260  myprt << " FOM " << fom;
2261  }
2262  return fom;
2263 
2264  } // ParentFOM
unsigned short FarEnd(const TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3339
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4849
double InShowerProbLong(double showerEnergy, double along)
Definition: TCShower.cxx:1958
TCConfig tcc
Definition: DataStructs.cxx:9
void FindAlongTrans(Point3_t pos1, Vector3_t dir1, Point3_t pos2, Point2_t &alongTrans)
Definition: PFPUtils.cxx:3097
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:2540
bool MakeBareTrajPoint(const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:4110
T abs(T value)
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:3236
float ChgFracBetween(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, Point3_t pos1, Point3_t pos2)
Definition: PFPUtils.cxx:3197
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
Definition: TCShower.cxx:1923
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2565
unsigned short tca::PDGCodeIndex ( int  PDGCode)

Definition at line 2171 of file Utils.cxx.

2172  {
2173  unsigned short pdg = abs(PDGCode);
2174  if (pdg == 11) return 0; // electron
2175  if (pdg == 13) return 1; // muon
2176  if (pdg == 211) return 2; // pion
2177  if (pdg == 321) return 3; // kaon
2178  if (pdg == 2212) return 4; // proton
2179  return USHRT_MAX;
2180  } // PDGCodeIndex
var pdg
Definition: selectors.fcl:14
T abs(T value)
int tca::PDGCodeVote ( const TCSlice &  slc,
const std::vector< int > &  tjIDs 
)

Definition at line 407 of file Utils.cxx.

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

Definition at line 3352 of file PFPUtils.cxx.

3356  {
3357  // returns a vote using PDG code assignments from dE/dx. A PDGCode of -1 is
3358  // returned if there was a failure and returns 0 if no decision can be made
3359  if (pfp.TP3Ds.empty()) return -1;
3360 
3361  // try to do better using dE/dx
3362  float dEdXAve = 0;
3363  float dEdXRms = 0;
3364  Average_dEdX(clockData, detProp, slc, pfp, dEdXAve, dEdXRms);
3365  if (dEdXAve < 0) return 0;
3366  // looks like a proton if dE/dx is high and the rms is low
3367  dEdXRms /= dEdXAve;
3368  float length = Length(pfp);
3369  float mcsmom = 0;
3370  float chgrms = 0;
3371  float cnt = 0;
3372  for (auto tjid : pfp.TjIDs) {
3373  auto& tj = slc.tjs[tjid - 1];
3374  float el = ElectronLikelihood(slc, tj);
3375  if (el <= 0) continue;
3376  mcsmom += MCSMom(slc, tj);
3377  chgrms += tj.ChgRMS;
3378  ++cnt;
3379  } // tjid
3380  if (cnt < 2) return 0;
3381  mcsmom /= cnt;
3382  chgrms /= cnt;
3383  int vote = 0;
3384  // call anything longer than 150 cm a muon
3385  if (length > 150) vote = 13;
3386  // or shorter with low dE/dx and really straight
3387  if (vote == 0 && length > 50 && dEdXAve < 2.5 && mcsmom > 500) vote = 13;
3388  // protons have high dE/dx, high MCSMom and low charge rms
3389  if (vote == 0 && dEdXAve > 3.0 && mcsmom > 200 && chgrms < 0.4) vote = 2212;
3390  // electrons have low MCSMom and large charge RMS
3391  if (vote == 0 && mcsmom < 50 && chgrms > 0.4) vote = 11;
3392  return vote;
3393  } // PDGCodeVote
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3468
float Length(const PFPStruct &pfp)
Definition: PFPUtils.cxx:3304
void Average_dEdX(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, float &dEdXAve, float &dEdXRms)
Definition: PFPUtils.cxx:2650
float ElectronLikelihood(const TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:3216
auto const detProp
void tca::PFPVertexCheck ( TCSlice &  slc)

Definition at line 2845 of file PFPUtils.cxx.

2846  {
2847  // Ensure that all PFParticles have a start vertex. It is possible for
2848  // PFParticles to be attached to a 3D vertex that is later killed.
2849  if (!slc.isValid) return;
2850  if (slc.pfps.empty()) return;
2851 
2852  for (auto& pfp : slc.pfps) {
2853  if (pfp.ID == 0) continue;
2854  if (pfp.Vx3ID[0] > 0) continue;
2855  if (pfp.SectionFits.empty()) continue;
2856  Vtx3Store vx3;
2857  vx3.TPCID = pfp.TPCID;
2858  vx3.Vx2ID.resize(slc.nPlanes);
2859  // Flag it as a PFP vertex that isn't required to have matched 2D vertices
2860  vx3.Wire = -2;
2861  Point3_t startPos;
2862  if (pfp.TP3Ds.empty()) {
2863  // must be a neutrino pfp
2864  startPos = pfp.SectionFits[0].Pos;
2865  }
2866  else if (!pfp.TP3Ds.empty()) {
2867  // normal pfp
2868  startPos = pfp.TP3Ds[0].Pos;
2869  }
2870  vx3.X = startPos[0];
2871  vx3.Y = startPos[1];
2872  vx3.Z = startPos[2];
2873  vx3.ID = slc.vtx3s.size() + 1;
2874  vx3.Primary = false;
2875  ++evt.global3V_UID;
2876  vx3.UID = evt.global3V_UID;
2877  slc.vtx3s.push_back(vx3);
2878  pfp.Vx3ID[0] = vx3.ID;
2879  } // pfp
2880  } // 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 2548 of file PFPUtils.cxx.

2549  {
2550  // Finds the direction vector between the two points from p1 to p2
2551  Vector3_t dir;
2552  for (unsigned short xyz = 0; xyz < 3; ++xyz)
2553  dir[xyz] = p2[xyz] - p1[xyz];
2554  if (dir[0] == 0 && dir[1] == 0 && dir[2] == 0) return dir;
2555  if (!SetMag(dir, 1)) {
2556  dir[0] = 0;
2557  dir[1] = 0;
2558  dir[3] = 0;
2559  }
2560  return dir;
2561  } // PointDirection
bool SetMag(Vector3_t &v1, double mag)
Definition: PFPUtils.cxx:2583
tuple dir
Definition: dropbox.py:28
std::array< double, 3 > Vector3_t
Definition: DataStructs.h:42
physics associatedGroupsWithLeft p1
Vector2_t tca::PointDirection ( const Point2_t  p1,
const Point2_t  p2 
)

Definition at line 4187 of file Utils.cxx.

4188  {
4189  // Finds the direction vector between the two points from p1 to p2
4190  Vector2_t dir;
4191  for (unsigned short xyz = 0; xyz < 2; ++xyz)
4192  dir[xyz] = p2[xyz] - p1[xyz];
4193  if (dir[0] == 0 && dir[1] == 0) return dir;
4194  double norm = sqrt(dir[0] * dir[0] + dir[1] * dir[1]);
4195  dir[0] /= norm;
4196  dir[1] /= norm;
4197  return dir;
4198  } // PointDirection
std::array< double, 2 > Vector2_t
Definition: DataStructs.h:44
auto norm(Vector const &v)
Return norm of the specified vector.
tuple dir
Definition: dropbox.py:28
physics associatedGroupsWithLeft p1
bool tca::PointDirIntersect ( Point3_t  p1,
Vector3_t  p1Dir,
Point3_t  p2,
Vector3_t  p2Dir,
Point3_t &  intersect,
float &  doca 
)

Definition at line 3115 of file PFPUtils.cxx.

3121  {
3122  // Point - vector version
3123  Point3_t p1End, p2End;
3124  for (unsigned short xyz = 0; xyz < 3; ++xyz) {
3125  p1End[xyz] = p1[xyz] + 10 * p1Dir[xyz];
3126  p2End[xyz] = p2[xyz] + 10 * p2Dir[xyz];
3127  }
3128  return LineLineIntersect(p1, p1End, p2, p2End, intersect, doca);
3129  } // 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:3133
physics associatedGroupsWithLeft p1
bool tca::PointInsideEnvelope ( const Point2_t &  Point,
const std::vector< Point2_t > &  Envelope 
)

Definition at line 3323 of file Utils.cxx.

3324  {
3325  // returns true if the Point is within the Envelope polygon. Entries in Envelope are the
3326  // Pos[0], Pos[1] locations of the polygon vertices. This is based on the algorithm that the
3327  // sum of the angles of a vector between a point and the vertices will be 2 * pi for an interior
3328  // point and 0 for an exterior point
3329 
3330  Point2_t p1, p2;
3331  unsigned short nvx = Envelope.size();
3332  double angleSum = 0;
3333  for (unsigned short ii = 0; ii < Envelope.size(); ++ii) {
3334  p1[0] = Envelope[ii][0] - Point[0];
3335  p1[1] = Envelope[ii][1] - Point[1];
3336  p2[0] = Envelope[(ii + 1) % nvx][0] - Point[0];
3337  p2[1] = Envelope[(ii + 1) % nvx][1] - Point[1];
3338  angleSum += DeltaAngle(p1, p2);
3339  }
3340  if (abs(angleSum) < M_PI) return false;
3341  return true;
3342 
3343  } // InsideEnvelope
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:2540
T abs(T value)
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:44
physics associatedGroupsWithLeft p1
float tca::PointPull ( TCSlice &  slc,
Point2_t  pos,
float  chg,
const Trajectory &  tj 
)

Definition at line 546 of file Utils.cxx.

547  {
548  // returns the combined position and charge pull for the charge at pos
549  // relative to the Tj closest to that point using a loose requirement on position separation.
550  if (tj.AlgMod[kKilled]) return 100;
551  if (tj.AveChg <= 0) return 100;
552  // find the closest point on the tj to pos
553  unsigned short closePt = USHRT_MAX;
554  float close = 1000;
555  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
556  auto& tp = tj.Pts[ipt];
557  float sep2 = PosSep2(pos, tp.Pos);
558  if (sep2 > close) continue;
559  close = sep2;
560  closePt = ipt;
561  } // ipt
562  if (closePt == USHRT_MAX) return 100;
563  // find the delta between the projection of the Tj close TP to inTP
564  auto& tp = tj.Pts[closePt];
565  float delta = PointTrajDOCA(slc, pos[0], pos[1], tp);
566  // estimate the proejcted position error (roughly)
567  float posErr = tp.DeltaRMS;
568  if (tp.AngErr > 0 && close > 10) posErr += sqrt(tp.AngErr * sqrt(close));
569  if (posErr < 0.1) posErr = 0.1;
570  float posPull = delta / posErr;
571  float chgErr = tj.ChgRMS;
572  if (chgErr < 0.15) chgErr = 0.15;
573  float chgPull = std::abs(chg / tj.AveChg - 1) / chgErr;
574  // return a simple average
575  return 0.5 * (posPull + chgPull);
576  } // PointPull
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2572
T abs(T value)
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2572
print OUTPUT<< EOF;< setup name="Default"version="1.0">< worldref="volWorld"/></setup ></gdml > EOF close(OUTPUT)
float tca::PointPull ( const PFPStruct &  pfp,
const TP3D &  tp3d 
)

Definition at line 2815 of file PFPUtils.cxx.

2816  {
2817  // returns the pull that the tp3d will cause in the pfp section fit. This
2818  // currently only uses position but eventually will include charge
2819  return std::abs(tp3d.Pos[0] - tp3d.TPX) / sqrt(tp3d.TPXErr2);
2820  } // PointPull
T abs(T value)
float tca::PointTrajDOCA ( const TCSlice &  slc,
unsigned int  iht,
TrajPoint const &  tp 
)

Definition at line 2572 of file Utils.cxx.

2573  {
2574  if (iht > slc.slHits.size() - 1) return 1E6;
2575  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2576  float wire = hit.WireID().Wire;
2577  float time = hit.PeakTime() * tcc.unitsPerTick;
2578  return sqrt(PointTrajDOCA2(slc, wire, time, tp));
2579  } // PointTrajDOCA
TCConfig tcc
Definition: DataStructs.cxx:9
process_name hit
Definition: cheaterreco.fcl:51
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
float PointTrajDOCA2(const TCSlice &slc, float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2590
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
TCEvent evt
Definition: DataStructs.cxx:8
float tca::PointTrajDOCA ( const TCSlice &  slc,
float  wire,
float  time,
TrajPoint const &  tp 
)

Definition at line 2583 of file Utils.cxx.

2584  {
2585  return sqrt(PointTrajDOCA2(slc, wire, time, tp));
2586  } // PointTrajDOCA
float PointTrajDOCA2(const TCSlice &slc, float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2590
float tca::PointTrajDOCA2 ( const TCSlice &  slc,
float  wire,
float  time,
TrajPoint const &  tp 
)

Definition at line 2590 of file Utils.cxx.

2591  {
2592  // returns the distance of closest approach squared between a (wire, time(WSE)) point
2593  // and a trajectory point
2594 
2595  double t = (double)(wire - tp.Pos[0]) * tp.Dir[0] + (double)(time - tp.Pos[1]) * tp.Dir[1];
2596  double dw = tp.Pos[0] + t * tp.Dir[0] - wire;
2597  double dt = tp.Pos[1] + t * tp.Dir[1] - time;
2598  return (float)(dw * dw + dt * dt);
2599 
2600  } // PointTrajDOCA2
float tca::PointTrajSep2 ( float  wire,
float  time,
TrajPoint const &  tp 
)

Definition at line 2563 of file Utils.cxx.

2564  {
2565  float dw = wire - tp.Pos[0];
2566  float dt = time - tp.Pos[1];
2567  return dw * dw + dt * dt;
2568  }
Point3_t tca::PosAtEnd ( const PFPStruct &  pfp,
unsigned short  end 
)

Definition at line 3293 of file PFPUtils.cxx.

3294  {
3295  if (end > 1 || pfp.SectionFits.empty()) return {{0., 0., 0.}};
3296  // handle a neutrino pfp that doesn't have any TP3Ds
3297  if (pfp.TP3Ds.empty()) return pfp.SectionFits[0].Pos;
3298  if (end == 0) return pfp.TP3Ds[0].Pos;
3299  return pfp.TP3Ds[pfp.TP3Ds.size() - 1].Pos;
3300  } // PosAtEnd
then if[["$THISISATEST"==1]]
Definition: neoSmazza.sh:95
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
void tca::PosInPlane ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice &  slc,
const Vtx3Store &  vx3,
unsigned short  plane,
Point2_t &  pos 
)

Definition at line 2879 of file TCVertex.cxx.

2884  {
2885  // returns the 2D position of the vertex in the plane
2886  pos[0] = tcc.geom->WireCoordinate(vx3.Y, vx3.Z, plane, vx3.TPCID.TPC, vx3.TPCID.Cryostat);
2887  pos[1] =
2888  detProp.ConvertXToTicks(vx3.X, plane, vx3.TPCID.TPC, vx3.TPCID.Cryostat) * tcc.unitsPerTick;
2889 
2890  } // PosInPlane
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
TCConfig tcc
Definition: DataStructs.cxx:9
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
const geo::GeometryCore * geom
Definition: DataStructs.h:576
auto const detProp
double tca::PosSep ( const Point3_t &  pos1,
const Point3_t &  pos2 
)

Definition at line 2565 of file PFPUtils.cxx.

2566  {
2567  return sqrt(PosSep2(pos1, pos2));
2568  } // PosSep
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2572
float tca::PosSep ( const Point2_t &  pos1,
const Point2_t &  pos2 
)

Definition at line 2663 of file Utils.cxx.

2664  {
2665  return sqrt(PosSep2(pos1, pos2));
2666  } // PosSep
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2572
double tca::PosSep2 ( const Point3_t &  pos1,
const Point3_t &  pos2 
)

Definition at line 2572 of file PFPUtils.cxx.

2573  {
2574  // returns the separation distance^2 between two positions in 3D
2575  double d0 = pos1[0] - pos2[0];
2576  double d1 = pos1[1] - pos2[1];
2577  double d2 = pos1[2] - pos2[2];
2578  return d0 * d0 + d1 * d1 + d2 * d2;
2579  } // PosSep2
float tca::PosSep2 ( const Point2_t &  pos1,
const Point2_t &  pos2 
)

Definition at line 2670 of file Utils.cxx.

2671  {
2672  // returns the separation distance^2 between two positions
2673  float d0 = pos1[0] - pos2[0];
2674  float d1 = pos1[1] - pos2[1];
2675  return d0 * d0 + d1 * d1;
2676  } // PosSep2
int tca::PrimaryID ( const TCSlice &  slc,
const Trajectory &  tj 
)

Definition at line 467 of file Utils.cxx.

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 TCSlice &  slc,
const PFPStruct &  pfp 
)

Definition at line 487 of file Utils.cxx.

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

Definition at line 4254 of file TCShower.cxx.

4255  {
4256  // Prints a one-line summary of 2D showers
4257  if (slc.cots.empty()) return;
4258 
4259  mf::LogVerbatim myprt("TC");
4260 
4261  // see how many lines were are going to print
4262  bool printAllCTP = (inCTP == USHRT_MAX);
4263  if (!printAllCTP) {
4264  unsigned short nlines = 0;
4265  for (const auto& ss : slc.cots) {
4266  if (!printAllCTP && ss.CTP != inCTP) continue;
4267  if (!printKilledShowers && ss.ID == 0) continue;
4268  ++nlines;
4269  } // ss
4270  if (nlines == 0) {
4271  myprt << someText << " Print2DShowers: Nothing to print";
4272  return;
4273  }
4274  } // !printAllCTP
4275 
4276  bool printHeader = true;
4277  bool printExtras = false;
4278  for (unsigned short ict = 0; ict < slc.cots.size(); ++ict) {
4279  const auto& ss = slc.cots[ict];
4280  if (!printAllCTP && ss.CTP != inCTP) continue;
4281  if (!printKilledShowers && ss.ID == 0) continue;
4282  PrintShower(someText, slc, ss, printHeader, printExtras);
4283  printHeader = false;
4284  } // ss
4285  // List of Tjs
4286  for (unsigned short ict = 0; ict < slc.cots.size(); ++ict) {
4287  const auto& ss = slc.cots[ict];
4288  if (!printAllCTP && ss.CTP != inCTP) continue;
4289  if (!printKilledShowers && ss.ID == 0) continue;
4290  myprt << someText << std::fixed;
4291  std::string sid = "2S" + std::to_string(ss.ID);
4292  myprt << std::setw(5) << sid;
4293  myprt << " Tjs";
4294  for (auto id : ss.TjIDs)
4295  myprt << " T" << id;
4296  myprt << "\n";
4297  } // ict
4298  // Print the envelopes
4299  for (unsigned short ict = 0; ict < slc.cots.size(); ++ict) {
4300  const auto& ss = slc.cots[ict];
4301  if (!printAllCTP && ss.CTP != inCTP) continue;
4302  if (!printKilledShowers && ss.ID == 0) continue;
4303  myprt << someText << std::fixed;
4304  std::string sid = "2S" + std::to_string(ss.ID);
4305  myprt << std::setw(5) << sid;
4306  myprt << " Envelope";
4307  for (auto& vtx : ss.Envelope)
4308  myprt << " " << (int)vtx[0] << ":" << (int)(vtx[1] / tcc.unitsPerTick);
4309  myprt << "\n";
4310  } // ict
4311  // List of nearby Tjs
4312  for (unsigned short ict = 0; ict < slc.cots.size(); ++ict) {
4313  const auto& ss = slc.cots[ict];
4314  if (!printAllCTP && ss.CTP != inCTP) continue;
4315  if (!printKilledShowers && ss.ID == 0) continue;
4316  myprt << someText << std::fixed;
4317  std::string sid = "2S" + std::to_string(ss.ID);
4318  myprt << std::setw(5) << sid;
4319  myprt << " Nearby";
4320  for (auto id : ss.NearTjIDs)
4321  myprt << " T" << id;
4322  myprt << "\n";
4323  } // ict
4324  // don't cluster list
4325  myprt << "DontCluster";
4326  for (auto& dc : slc.dontCluster) {
4327  if (dc.TjIDs[0] > 0) myprt << " T" << dc.TjIDs[0] << "-T" << dc.TjIDs[1];
4328  } // dc
4329  myprt << "\nDontCluster";
4330  for (unsigned short ict = 0; ict < slc.cots.size(); ++ict) {
4331  const auto& iss = slc.cots[ict];
4332  if (iss.ID == 0) continue;
4333  for (unsigned short jct = ict + 1; jct < slc.cots.size(); ++jct) {
4334  const auto& jss = slc.cots[jct];
4335  if (jss.ID == 0) continue;
4336  if (DontCluster(slc, iss.TjIDs, jss.TjIDs)) myprt << " 2S" << iss.ID << "-2S" << jss.ID;
4337  } // jct
4338  } // ict
4339  } // Print2DShowers
TCConfig tcc
Definition: DataStructs.cxx:9
void PrintShower(std::string someText, TCSlice &slc, const ShowerStruct &ss, bool printHeader, bool printExtras)
Definition: TCShower.cxx:4343
bool DontCluster(TCSlice &slc, const std::vector< int > &tjlist1, const std::vector< int > &tjlist2)
Definition: TCShower.cxx:3258
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
std::string to_string(WindowPattern const &pattern)
void tca::Print2V ( std::string  someText,
mf::LogVerbatim &  myprt,
VtxStore &  vx2,
bool &  printHeader 
)

Definition at line 5768 of file Utils.cxx.

5769  {
5770  // print a 2D vertex on one line
5771  if (vx2.ID <= 0) return;
5772  if (debug.CTP != UINT_MAX && vx2.CTP != debug.CTP) return;
5773  auto sIndx = GetSliceIndex("2V", vx2.UID);
5774  if (sIndx.first == USHRT_MAX) return;
5775  auto& slc = slices[sIndx.first];
5776  if (printHeader) {
5777  myprt << "************ 2D vertices ************\n";
5778  myprt << " prodID CTP wire err tick err ChiDOF NTj Pass Topo ChgFrac Score "
5779  " v3D Tj UIDs\n";
5780  printHeader = false;
5781  }
5782  std::string str = "2V" + std::to_string(vx2.ID) + "/2VU" + std::to_string(vx2.UID);
5783  myprt << std::right << std::setw(12) << std::fixed << str;
5784  myprt << std::right << std::setw(6) << vx2.CTP;
5785  myprt << std::right << std::setw(8) << std::setprecision(0) << std::nearbyint(vx2.Pos[0]);
5786  myprt << std::right << std::setw(5) << std::setprecision(1) << vx2.PosErr[0];
5787  myprt << std::right << std::setw(8) << std::setprecision(0)
5788  << std::nearbyint(vx2.Pos[1] / tcc.unitsPerTick);
5789  myprt << std::right << std::setw(5) << std::setprecision(1) << vx2.PosErr[1] / tcc.unitsPerTick;
5790  myprt << std::right << std::setw(7) << vx2.ChiDOF;
5791  myprt << std::right << std::setw(5) << vx2.NTraj;
5792  myprt << std::right << std::setw(5) << vx2.Pass;
5793  myprt << std::right << std::setw(6) << vx2.Topo;
5794  myprt << std::right << std::setw(9) << std::setprecision(2) << vx2.TjChgFrac;
5795  myprt << std::right << std::setw(6) << std::setprecision(1) << vx2.Score;
5796  int v3id = 0;
5797  if (vx2.Vx3ID > 0) v3id = slc.vtx3s[vx2.Vx3ID - 1].UID;
5798  myprt << std::right << std::setw(5) << v3id;
5799  myprt << " ";
5800  // display the traj IDs
5801  for (unsigned short ii = 0; ii < slc.tjs.size(); ++ii) {
5802  auto const& tj = slc.tjs[ii];
5803  if (tj.AlgMod[kKilled]) continue;
5804  for (unsigned short end = 0; end < 2; ++end) {
5805  if (tj.VtxID[end] != (short)vx2.ID) continue;
5806  std::string tid = " TU" + std::to_string(tj.UID) + "_" + std::to_string(end);
5807  myprt << std::right << std::setw(6) << tid;
5808  } // end
5809  } // ii
5810  myprt << " Stat:";
5811  // Special flags. Ignore the first flag bit (0 = kVxTrjTried) which is done for every vertex
5812  for (unsigned short ib = 1; ib < VtxBitNames.size(); ++ib)
5813  if (vx2.Stat[ib]) myprt << " " << VtxBitNames[ib];
5814  myprt << "\n";
5815  } // Print2V
TCConfig tcc
Definition: DataStructs.cxx:9
walls no right
Definition: selectors.fcl:105
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
const std::vector< std::string > VtxBitNames
Definition: DataStructs.cxx:98
std::string to_string(WindowPattern const &pattern)
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:5088
void tca::Print3S ( detinfo::DetectorPropertiesData const &  detProp,
std::string  someText,
mf::LogVerbatim &  myprt,
ShowerStruct3D &  ss3 
)

Definition at line 5819 of file Utils.cxx.

5823  {
5824  if (ss3.ID <= 0) return;
5825  auto sIndx = GetSliceIndex("3S", ss3.UID);
5826  if (sIndx.first == USHRT_MAX) return;
5827  auto& slc = slices[sIndx.first];
5828  std::string str =
5829  std::to_string(slc.ID) + ":" + std::to_string(sIndx.first) + ":" + std::to_string(ss3.ID);
5830  str += "/" + std::to_string(ss3.UID);
5831  myprt << std::fixed << std::setw(12) << str;
5832  str = "--";
5833  if (ss3.Vx3ID > 0) str = "3V" + std::to_string(slc.vtx3s[ss3.Vx3ID - 1].UID);
5834  myprt << std::setw(6) << str;
5835  for (unsigned short xyz = 0; xyz < 3; ++xyz)
5836  myprt << std::setprecision(0) << std::setw(5) << ss3.ChgPos[xyz];
5837  for (unsigned short xyz = 0; xyz < 3; ++xyz)
5838  myprt << std::setprecision(2) << std::setw(5) << ss3.Dir[xyz];
5839  std::vector<float> projInPlane(slc.nPlanes);
5840  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
5841  CTP_t inCTP = EncodeCTP(ss3.TPCID.Cryostat, ss3.TPCID.TPC, plane);
5842  auto tp = MakeBareTP(detProp, slc, ss3.ChgPos, ss3.Dir, inCTP);
5843  myprt << " " << PrintPos(slc, tp.Pos);
5844  projInPlane[plane] = tp.Delta;
5845  } // plane
5846  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
5847  myprt << std::setprecision(2) << std::setw(5) << projInPlane[plane];
5848  } // plane
5849  for (auto cid : ss3.CotIDs) {
5850  auto& ss = slc.cots[cid - 1];
5851  str = "2SU" + std::to_string(ss.UID);
5852  myprt << std::setw(5) << str;
5853  } // ci
5854  if (ss3.NeedsUpdate) myprt << " *** Needs update";
5855  myprt << "\n";
5856  } // Print3S
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const Point3_t &pos, CTP_t inCTP)
Definition: Utils.cxx:4027
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
unsigned int CTP_t
Definition: DataStructs.h:47
std::string to_string(WindowPattern const &pattern)
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:52
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:5088
auto const detProp
void tca::Print3V ( detinfo::DetectorPropertiesData const &  detProp,
std::string  someText,
mf::LogVerbatim &  myprt,
Vtx3Store &  vx3,
bool &  printHeader 
)

Definition at line 5691 of file Utils.cxx.

5696  {
5697  // print a 3D vertex on one line
5698  if (vx3.ID <= 0) return;
5699  auto sIndx = GetSliceIndex("3V", vx3.UID);
5700  if (sIndx.first == USHRT_MAX) return;
5701  auto& slc = slices[sIndx.first];
5702  if (printHeader) {
5703  myprt
5704  << "****** 3D vertices ******************************************__2DVtx_UID__*******\n";
5705  myprt << " prodID Cstat TPC X Y Z pln0 pln1 pln2 Wire score "
5706  "Prim? Nu? nTru";
5707  myprt << " ___________2D_Pos____________ _____Tj UIDs________\n";
5708  printHeader = false;
5709  }
5710  std::string str = "3V" + std::to_string(vx3.ID) + "/3VU" + std::to_string(vx3.UID);
5711  myprt << std::right << std::setw(12) << std::fixed << str;
5712  myprt << std::setprecision(0);
5713  myprt << std::right << std::setw(7) << vx3.TPCID.Cryostat;
5714  myprt << std::right << std::setw(5) << vx3.TPCID.TPC;
5715  myprt << std::right << std::setw(8) << vx3.X;
5716  myprt << std::right << std::setw(8) << vx3.Y;
5717  myprt << std::right << std::setw(8) << vx3.Z;
5718  for (auto vx2id : vx3.Vx2ID) {
5719  if (vx2id > 0) {
5720  str = "2VU" + std::to_string(slc.vtxs[vx2id - 1].UID);
5721  myprt << std::right << std::setw(7) << str;
5722  }
5723  else {
5724  myprt << " --";
5725  }
5726  } // vx2id
5727  myprt << std::right << std::setw(5) << vx3.Wire;
5728  unsigned short nTruMatch = 0;
5729  for (unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
5730  if (vx3.Vx2ID[ipl] == 0) continue;
5731  unsigned short iv2 = vx3.Vx2ID[ipl] - 1;
5732  if (slc.vtxs[iv2].Stat[kVxTruMatch]) ++nTruMatch;
5733  } // ipl
5734  myprt << std::right << std::setw(6) << std::setprecision(1) << vx3.Score;
5735  myprt << std::setw(6) << vx3.Primary;
5736  myprt << std::setw(4) << vx3.Neutrino;
5737  myprt << std::right << std::setw(5) << nTruMatch;
5738  Point2_t pos;
5739  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
5740  PosInPlane(detProp, slc, vx3, plane, pos);
5741  myprt << " " << PrintPos(slc, pos);
5742  } // plane
5743  if (vx3.Wire == -2) {
5744  // find the Tjs that are attached to it
5745  for (unsigned short end = 0; end < 2; ++end) {
5746  for (auto& pfp : slc.pfps) {
5747  if (pfp.Vx3ID[end] == vx3.ID) {
5748  for (auto tjID : pfp.TjIDs) {
5749  auto& tj = slc.tjs[tjID - 1];
5750  myprt << " T" << tj.UID;
5751  } // tjID
5752  } // pfp.Vx3ID[0] == vx3.ID
5753  } // pfp
5754  } // end
5755  }
5756  else {
5757  auto vxtjs = GetAssns(slc, "3V", vx3.ID, "T");
5758  for (auto tjid : vxtjs) {
5759  auto& tj = slc.tjs[tjid - 1];
5760  myprt << " TU" << tj.UID;
5761  }
5762  } // vx3.Wire != -2
5763  myprt << "\n";
5764  } // Print3V
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4849
tagged as a vertex between Tjs that are matched to MC truth neutrino interaction particles ...
Definition: DataStructs.h:96
walls no right
Definition: selectors.fcl:105
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
void PosInPlane(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const Vtx3Store &vx3, unsigned short plane, Point2_t &pos)
Definition: TCVertex.cxx:2879
std::array< float, 2 > Point2_t
Definition: DataStructs.h:43
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
std::string to_string(WindowPattern const &pattern)
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:5088
auto const detProp
void tca::PrintAll ( detinfo::DetectorPropertiesData const &  detProp,
std::string  someText 
)

Definition at line 5521 of file Utils.cxx.

5522  {
5523  // print everything in all slices
5524  bool prt3V = false;
5525  bool prt2V = false;
5526  bool prtT = false;
5527  bool prtP = false;
5528  bool prtS3 = false;
5529  for (size_t isl = 0; isl < slices.size(); ++isl) {
5530  if (debug.Slice >= 0 && int(isl) != debug.Slice) continue;
5531  auto& slc = slices[isl];
5532  if (!slc.vtx3s.empty()) prt3V = true;
5533  if (!slc.vtxs.empty()) prt2V = true;
5534  if (!slc.tjs.empty()) prtT = true;
5535  if (!slc.pfps.empty()) prtP = true;
5536  if (!slc.showers.empty()) prtS3 = true;
5537  } // slc
5538  mf::LogVerbatim myprt("TC");
5539  myprt << "Debug report from caller " << someText << "\n";
5540  myprt << " 'prodID' = <sliceID>:<subSliceIndex>:<productID>/<productUID>\n";
5541  if (prtS3) {
5542  myprt << "************ Showers ************\n";
5543  myprt << " prodID Vtx parUID ___ChgPos____ ______Dir_____ ____posInPln____ "
5544  "___projInPln____ 2D shower UIDs\n";
5545  for (size_t isl = 0; isl < slices.size(); ++isl) {
5546  if (debug.Slice >= 0 && int(isl) != debug.Slice) continue;
5547  auto& slc = slices[isl];
5548  if (slc.showers.empty()) continue;
5549  for (auto& ss3 : slc.showers)
5550  Print3S(detProp, someText, myprt, ss3);
5551  } // slc
5552  } // prtS3
5553  if (prtP) {
5554  bool printHeader = true;
5555  for (size_t isl = 0; isl < slices.size(); ++isl) {
5556  if (debug.Slice >= 0 && int(isl) != debug.Slice) continue;
5557  auto& slc = slices[isl];
5558  if (slc.pfps.empty()) continue;
5559  for (auto& pfp : slc.pfps)
5560  PrintP(someText, myprt, pfp, printHeader);
5561  } // slc
5562  } // prtS3
5563  if (prt3V) {
5564  bool printHeader = true;
5565  myprt << "****** 3D vertices "
5566  "******************************************__2DVtx_UID__*******\n";
5567  myprt << " prodID Cstat TPC X Y Z XEr YEr "
5568  "ZEr pln0 pln1 pln2 Wire score Prim? Nu? nTru";
5569  myprt << " ___________2D_Pos____________ _____Tj UIDs________\n";
5570  for (size_t isl = 0; isl < slices.size(); ++isl) {
5571  if (debug.Slice >= 0 && int(isl) != debug.Slice) continue;
5572  auto& slc = slices[isl];
5573  if (slc.vtx3s.empty()) continue;
5574  for (auto& vx3 : slc.vtx3s)
5575  Print3V(detProp, someText, myprt, vx3, printHeader);
5576  } // slc
5577  } // prt3V
5578  if (prt2V) {
5579  bool printHeader = true;
5580  myprt << "************ 2D vertices ************\n";
5581  myprt << " prodID CTP wire err tick err ChiDOF NTj Pass "
5582  " Topo ChgFrac Score v3D Tj UIDs\n";
5583  for (size_t isl = 0; isl < slices.size(); ++isl) {
5584  if (debug.Slice >= 0 && int(isl) != debug.Slice) continue;
5585  auto& slc = slices[isl];
5586  if (slc.vtxs.empty()) continue;
5587  for (auto& vx2 : slc.vtxs)
5588  Print2V(someText, myprt, vx2, printHeader);
5589  } // slc
5590  } // prt2V
5591  if (prtT) {
5592  bool printHeader = true;
5593  for (size_t isl = 0; isl < slices.size(); ++isl) {
5594  if (debug.Slice >= 0 && int(isl) != debug.Slice) continue;
5595  auto& slc = slices[isl];
5596  if (slc.tjs.empty()) continue;
5597  for (auto& tj : slc.tjs)
5598  PrintT(someText, myprt, tj, printHeader);
5599  } // slc
5600  } // prtT
5601  } // PrintAll
void Print2V(std::string someText, mf::LogVerbatim &myprt, VtxStore &vx2, bool &printHeader)
Definition: Utils.cxx:5768
void Print3V(detinfo::DetectorPropertiesData const &detProp, std::string someText, mf::LogVerbatim &myprt, Vtx3Store &vx3, bool &printHeader)
Definition: Utils.cxx:5691
void PrintT(std::string someText, mf::LogVerbatim &myprt, Trajectory &tj, bool &printHeader)
Definition: Utils.cxx:5860
void PrintP(std::string someText, mf::LogVerbatim &myprt, PFPStruct &pfp, bool &printHeader)
Definition: Utils.cxx:5605
void Print3S(detinfo::DetectorPropertiesData const &detProp, std::string someText, mf::LogVerbatim &myprt, ShowerStruct3D &ss3)
Definition: Utils.cxx:5819
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
auto const detProp
void tca::PrintAllTraj ( detinfo::DetectorPropertiesData const &  detProp,
std::string  someText,
TCSlice &  slc,
unsigned short  itj,
unsigned short  ipt,
bool  prtVtx 
)

Definition at line 5952 of file Utils.cxx.

5958  {
5959 
5960  mf::LogVerbatim myprt("TC");
5961 
5962  if (prtVtx) {
5963  if (!slc.vtx3s.empty()) {
5964  // print out 3D vertices
5965  myprt
5966  << someText
5967  << "****** 3D vertices ******************************************__2DVtx_ID__*******\n";
5968  myprt << someText
5969  << " Vtx Cstat TPC X Y Z XEr YEr ZEr pln0 pln1 pln2 Wire "
5970  "score Prim? Nu? nTru";
5971  myprt << " ___________2D_Pos____________ _____Tjs________\n";
5972  for (unsigned short iv = 0; iv < slc.vtx3s.size(); ++iv) {
5973  if (slc.vtx3s[iv].ID == 0) continue;
5974  const Vtx3Store& vx3 = slc.vtx3s[iv];
5975  myprt << someText;
5976  std::string vid = "3v" + std::to_string(vx3.ID);
5977  myprt << std::right << std::setw(5) << std::fixed << vid;
5978  myprt << std::setprecision(1);
5979  myprt << std::right << std::setw(7) << vx3.TPCID.Cryostat;
5980  myprt << std::right << std::setw(5) << vx3.TPCID.TPC;
5981  myprt << std::right << std::setw(8) << vx3.X;
5982  myprt << std::right << std::setw(8) << vx3.Y;
5983  myprt << std::right << std::setw(8) << vx3.Z;
5984  myprt << std::right << std::setw(5) << vx3.XErr;
5985  myprt << std::right << std::setw(5) << vx3.YErr;
5986  myprt << std::right << std::setw(5) << vx3.ZErr;
5987  myprt << std::right << std::setw(5) << vx3.Vx2ID[0];
5988  myprt << std::right << std::setw(5) << vx3.Vx2ID[1];
5989  myprt << std::right << std::setw(5) << vx3.Vx2ID[2];
5990  myprt << std::right << std::setw(5) << vx3.Wire;
5991  unsigned short nTruMatch = 0;
5992  for (unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
5993  if (vx3.Vx2ID[ipl] == 0) continue;
5994  unsigned short iv2 = vx3.Vx2ID[ipl] - 1;
5995  if (slc.vtxs[iv2].Stat[kVxTruMatch]) ++nTruMatch;
5996  } // ipl
5997  myprt << std::right << std::setw(6) << std::setprecision(1) << vx3.Score;
5998  myprt << std::setw(6) << vx3.Primary;
5999  myprt << std::setw(4) << vx3.Neutrino;
6000  myprt << std::right << std::setw(5) << nTruMatch;
6001  Point2_t pos;
6002  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
6003  PosInPlane(detProp, slc, vx3, plane, pos);
6004  myprt << " " << PrintPos(slc, pos);
6005  } // plane
6006  if (vx3.Wire == -2) {
6007  // find the Tjs that are attached to it
6008  for (auto& pfp : slc.pfps) {
6009  if (pfp.Vx3ID[0] == slc.vtx3s[iv].ID) {
6010  for (auto& tjID : pfp.TjIDs)
6011  myprt << " t" << tjID;
6012  }
6013  if (pfp.Vx3ID[1] == slc.vtx3s[iv].ID) {
6014  for (auto& tjID : pfp.TjIDs)
6015  myprt << " t" << tjID;
6016  }
6017  } // ipfp
6018  }
6019  else {
6020  auto vxtjs = GetAssns(slc, "3V", vx3.ID, "T");
6021  for (auto tjid : vxtjs)
6022  myprt << " t" << tjid;
6023  }
6024  myprt << "\n";
6025  }
6026  } // slc.vtx3s.size
6027  if (!slc.vtxs.empty()) {
6028  bool foundOne = false;
6029  for (unsigned short iv = 0; iv < slc.vtxs.size(); ++iv) {
6030  auto& vx2 = slc.vtxs[iv];
6031  if (debug.Plane < 3 && debug.Plane != (int)DecodeCTP(vx2.CTP).Plane) continue;
6032  if (vx2.NTraj == 0) continue;
6033  foundOne = true;
6034  } // iv
6035  if (foundOne) {
6036  // print out 2D vertices
6037  myprt << someText << "************ 2D vertices ************\n";
6038  myprt << someText
6039  << " ID CTP wire err tick err ChiDOF NTj Pass Topo ChgFrac Score v3D "
6040  "TjIDs\n";
6041  for (auto& vx2 : slc.vtxs) {
6042  if (vx2.ID == 0) continue;
6043  if (debug.Plane < 3 && debug.Plane != (int)DecodeCTP(vx2.CTP).Plane) continue;
6044  myprt << someText;
6045  std::string vid = "2v" + std::to_string(vx2.ID);
6046  myprt << std::right << std::setw(5) << std::fixed << vid;
6047  myprt << std::right << std::setw(6) << vx2.CTP;
6048  myprt << std::right << std::setw(8) << std::setprecision(0)
6049  << std::nearbyint(vx2.Pos[0]);
6050  myprt << std::right << std::setw(5) << std::setprecision(1) << vx2.PosErr[0];
6051  myprt << std::right << std::setw(8) << std::setprecision(0)
6052  << std::nearbyint(vx2.Pos[1] / tcc.unitsPerTick);
6053  myprt << std::right << std::setw(5) << std::setprecision(1)
6054  << vx2.PosErr[1] / tcc.unitsPerTick;
6055  myprt << std::right << std::setw(7) << vx2.ChiDOF;
6056  myprt << std::right << std::setw(5) << vx2.NTraj;
6057  myprt << std::right << std::setw(5) << vx2.Pass;
6058  myprt << std::right << std::setw(6) << vx2.Topo;
6059  myprt << std::right << std::setw(9) << std::setprecision(2) << vx2.TjChgFrac;
6060  myprt << std::right << std::setw(6) << std::setprecision(1) << vx2.Score;
6061  myprt << std::right << std::setw(5) << vx2.Vx3ID;
6062  myprt << " ";
6063  // display the traj IDs
6064  for (unsigned short ii = 0; ii < slc.tjs.size(); ++ii) {
6065  auto const& aTj = slc.tjs[ii];
6066  if (debug.Plane < 3 && debug.Plane != (int)DecodeCTP(aTj.CTP).Plane) continue;
6067  if (aTj.AlgMod[kKilled]) continue;
6068  for (unsigned short end = 0; end < 2; ++end) {
6069  if (aTj.VtxID[end] != (short)vx2.ID) continue;
6070  std::string tid = " t" + std::to_string(aTj.ID) + "_" + std::to_string(end);
6071  myprt << std::right << std::setw(6) << tid;
6072  } // end
6073  } // ii
6074  // Special flags. Ignore the first flag bit (0 = kVxTrjTried) which is done for every vertex
6075  for (unsigned short ib = 1; ib < VtxBitNames.size(); ++ib)
6076  if (vx2.Stat[ib]) myprt << " " << VtxBitNames[ib];
6077  myprt << "\n";
6078  } // iv
6079  }
6080  } // slc.vtxs.size
6081  }
6082 
6083  if (slc.tjs.empty()) {
6084  mf::LogVerbatim("TC") << someText << " No allTraj trajectories to print";
6085  return;
6086  }
6087 
6088  // Print all trajectories in slc.tjs if itj == USHRT_MAX
6089  // Print a single traj (itj) and a single TP (ipt) or all TPs (USHRT_MAX)
6090  if (itj == USHRT_MAX) {
6091  // Print summary trajectory information
6092  myprt << "Tj AngleCode-EndFlag (EF) decoder: <AngleCode> + <reason for stopping>";
6093  myprt << " (B=Bragg Peak, V=Vertex, A=AngleKink, C=ChargeKink, T=Trajectory)\n";
6094  std::vector<unsigned int> tmp;
6095  myprt << someText
6096  << " UID CTP Pass Pts W:T Ang EF AveQ W:T Ang EF AveQ Chg(k) "
6097  "chgRMS Mom SDr __Vtx__ PDG Par Pri NuPar WorkID \n";
6098  for (unsigned short ii = 0; ii < slc.tjs.size(); ++ii) {
6099  auto& aTj = slc.tjs[ii];
6100  if (debug.CTP != UINT_MAX && aTj.CTP != debug.CTP) continue;
6101  myprt << someText << " ";
6102  std::string tid;
6103  if (aTj.AlgMod[kKilled]) { tid = "k" + std::to_string(aTj.UID); }
6104  else {
6105  tid = "t" + std::to_string(aTj.UID);
6106  }
6107  myprt << std::fixed << std::setw(5) << tid;
6108  myprt << std::setw(6) << aTj.CTP;
6109  myprt << std::setw(5) << aTj.Pass;
6110  myprt << std::setw(5) << aTj.EndPt[1] - aTj.EndPt[0] + 1;
6111  unsigned short endPt0 = aTj.EndPt[0];
6112  auto& tp0 = aTj.Pts[endPt0];
6113  int itick = tp0.Pos[1] / tcc.unitsPerTick;
6114  if (itick < 0) itick = 0;
6115  myprt << std::setw(6) << (int)(tp0.Pos[0] + 0.5) << ":" << itick; // W:T
6116  if (itick < 10) { myprt << " "; }
6117  if (itick < 100) { myprt << " "; }
6118  if (itick < 1000) { myprt << " "; }
6119  myprt << std::setw(6) << std::setprecision(2) << tp0.Ang;
6120  myprt << std::setw(2) << tp0.AngleCode;
6121  if (aTj.EndFlag[0][kBragg]) { myprt << "B"; }
6122  else if (aTj.EndFlag[0][kAtVtx]) {
6123  myprt << "V";
6124  }
6125  else if (aTj.EndFlag[0][kAtKink]) {
6126  myprt << "K";
6127  }
6128  else if (aTj.EndFlag[0][kAtTj]) {
6129  myprt << "T";
6130  }
6131  else {
6132  myprt << " ";
6133  }
6134  myprt << std::setw(5) << (int)tp0.AveChg;
6135  unsigned short endPt1 = aTj.EndPt[1];
6136  auto& tp1 = aTj.Pts[endPt1];
6137  itick = tp1.Pos[1] / tcc.unitsPerTick;
6138  myprt << std::setw(6) << (int)(tp1.Pos[0] + 0.5) << ":" << itick; // W:T
6139  if (itick < 10) { myprt << " "; }
6140  if (itick < 100) { myprt << " "; }
6141  if (itick < 1000) { myprt << " "; }
6142  myprt << std::setw(6) << std::setprecision(2) << tp1.Ang;
6143  myprt << std::setw(2) << tp1.AngleCode;
6144  if (aTj.EndFlag[1][kBragg]) { myprt << "B"; }
6145  else if (aTj.EndFlag[1][kAtVtx]) {
6146  myprt << "V";
6147  }
6148  else {
6149  myprt << " ";
6150  }
6151  myprt << std::setw(5) << (int)tp1.AveChg;
6152  myprt << std::setw(7) << std::setprecision(1) << aTj.TotChg / 1000;
6153  myprt << std::setw(7) << std::setprecision(2) << aTj.ChgRMS;
6154  myprt << std::setw(5) << aTj.MCSMom;
6155  myprt << std::setw(4) << aTj.StepDir;
6156  myprt << std::setw(4) << aTj.VtxID[0];
6157  myprt << std::setw(4) << aTj.VtxID[1];
6158  myprt << std::setw(5) << aTj.PDGCode;
6159  myprt << std::setw(5) << aTj.ParentID;
6160  myprt << std::setw(5) << PrimaryID(slc, aTj);
6161  myprt << std::setw(6) << NeutrinoPrimaryTjID(slc, aTj);
6162  myprt << std::setw(7) << aTj.WorkID;
6163  for (unsigned short ib = 0; ib < AlgBitNames.size(); ++ib)
6164  if (aTj.AlgMod[ib]) myprt << " " << AlgBitNames[ib];
6165  myprt << "\n";
6166  } // ii
6167  return;
6168  } // itj > slc.tjs.size()-1
6169 
6170  if (itj > slc.tjs.size() - 1) return;
6171 
6172  auto const& aTj = slc.tjs[itj];
6173 
6174  mf::LogVerbatim("TC") << "Print slc.tjs[" << itj << "] Vtx[0] " << aTj.VtxID[0] << " Vtx[1] "
6175  << aTj.VtxID[1];
6176  myprt << "AlgBits";
6177  for (unsigned short ib = 0; ib < AlgBitNames.size(); ++ib)
6178  if (aTj.AlgMod[ib]) myprt << " " << AlgBitNames[ib];
6179  myprt << "\n";
6180 
6181  PrintTPHeader(someText);
6182  if (ipt == USHRT_MAX) {
6183  // print all points
6184  for (unsigned short ii = 0; ii < aTj.Pts.size(); ++ii)
6185  PrintTP(someText, slc, ii, aTj.StepDir, aTj.Pass, aTj.Pts[ii]);
6186  }
6187  else {
6188  // print just one
6189  PrintTP(someText, slc, ipt, aTj.StepDir, aTj.Pass, aTj.Pts[ipt]);
6190  }
6191  } // PrintAllTraj
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4849
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:96
TCConfig tcc
Definition: DataStructs.cxx:9
walls no right
Definition: selectors.fcl:105
void PrintTP(std::string someText, const TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, const TrajPoint &tp)
Definition: Utils.cxx:6296
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
void PosInPlane(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const Vtx3Store &vx3, unsigned short plane, Point2_t &pos)
Definition: TCVertex.cxx:2879
int NeutrinoPrimaryTjID(const TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:444
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:571
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
const std::vector< std::string > VtxBitNames
Definition: DataStructs.cxx:98
std::string to_string(WindowPattern const &pattern)
geo::PlaneID DecodeCTP(CTP_t CTP)
void PrintTPHeader(std::string someText)
Definition: Utils.cxx:6287
auto const detProp
void tca::PrintClusters ( )
void tca::PrintDebugMode ( )

Definition at line 5450 of file Utils.cxx.

5451  {
5452  // print the debug mode configuration to the screen
5453  std::cout << "*** TrajCluster debug mode configuration in";
5454  std::cout << " CTP=";
5455  if (debug.CTP == UINT_MAX) { std::cout << "NA"; }
5456  else {
5457  std::cout << debug.CTP;
5458  }
5459  std::cout << " Cryostat=" << debug.Cryostat;
5460  std::cout << " TPC=" << debug.TPC;
5461  std::cout << " Plane=" << debug.Plane;
5462  std::cout << " Wire=" << debug.Wire;
5463  std::cout << " Tick=" << debug.Tick;
5464  std::cout << " Hit=";
5465  if (debug.Hit == UINT_MAX) { std::cout << "NA"; }
5466  else {
5467  std::cout << debug.Hit;
5468  }
5469  std::cout << " WorkID=";
5470  if (debug.WorkID == 0) { std::cout << "NA"; }
5471  else {
5472  std::cout << debug.WorkID;
5473  }
5474  std::cout << " Slice=";
5475  if (debug.Slice == -1) { std::cout << "All"; }
5476  else {
5477  std::cout << debug.Slice;
5478  }
5479  std::cout << "\n";
5480  std::cout << "*** tcc.dbg modes:";
5481  if (tcc.dbgSlc) std::cout << " dbgSlc";
5482  if (tcc.dbgStp) std::cout << " dbgStp";
5483  if (tcc.dbgMrg) std::cout << " dbgMrg";
5484  if (tcc.dbg2V) std::cout << " dbg2V";
5485  if (tcc.dbg2S) std::cout << " dbg2S";
5486  if (tcc.dbgVxNeutral) std::cout << " dbgVxNeutral";
5487  if (tcc.dbgVxMerge) std::cout << " dbgVxMerge";
5488  if (tcc.dbgVxJunk) std::cout << " dbgVxJunk";
5489  if (tcc.dbg3V) std::cout << " dbg3V";
5490  if (tcc.dbgPFP) std::cout << " dbgPFP";
5491  if (tcc.dbgDeltaRayTag) std::cout << " dbgDeltaRayTag";
5492  if (tcc.dbgMuonTag) std::cout << " dbgMuonTag";
5493  if (tcc.dbgStitch) std::cout << " dbgStitch";
5494  if (tcc.dbgSummary) std::cout << " dbgSummary";
5495  if (tcc.dbgDump) std::cout << " dbgDump";
5496  std::cout << "\n";
5497  std::cout << "*** Using algs:";
5498  unsigned short cnt = 0;
5499  for (unsigned short ib = 0; ib < AlgBitNames.size(); ++ib) {
5500  if (tcc.useAlg[ib] && ib != kKilled) {
5501  ++cnt;
5502  if (cnt % 10 == 0) std::cout << "\n ";
5503  std::cout << " " << AlgBitNames[ib];
5504  }
5505  }
5506  std::cout << "\n";
5507  std::cout << "*** Skipping algs:";
5508  cnt = 0;
5509  for (unsigned short ib = 0; ib < AlgBitNames.size(); ++ib) {
5510  if (!tcc.useAlg[ib] && ib != kKilled) {
5511  ++cnt;
5512  if (cnt % 10 == 0) std::cout << "\n ";
5513  std::cout << " " << AlgBitNames[ib];
5514  }
5515  }
5516  std::cout << "\n";
5517  } // PrintDebugMode
bool dbgStitch
debug PFParticle stitching
Definition: DataStructs.h:603
const std::vector< std::string > AlgBitNames
Definition: DataStructs.cxx:16
TCConfig tcc
Definition: DataStructs.cxx:9
bool dbgDeltaRayTag
Definition: DataStructs.h:599
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:590
bool dbg3V
debug 3D vertex finding
Definition: DataStructs.h:597
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
bool dbg2V
debug 2D vertex finding
Definition: DataStructs.h:593
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
bool dbgSummary
print a summary report
Definition: DataStructs.h:604
BEGIN_PROLOG could also be cout
std::string tca::PrintEndFlag ( const PFPStruct &  pfp,
unsigned short  end 
)

Definition at line 6463 of file Utils.cxx.

6464  {
6465  if (end > 1) return "Invalid end";
6466  std::string tmp;
6467  bool first = true;
6468  for (unsigned short ib = 0; ib < EndFlagNames.size(); ++ib) {
6469  if (pfp.EndFlag[end][ib]) {
6470  if (first) {
6471  tmp = std::to_string(end) + ":" + EndFlagNames[ib];
6472  first = false;
6473  }
6474  else {
6475  tmp += "," + EndFlagNames[ib];
6476  }
6477  }
6478  } // ib
6479  if (first) tmp = " none";
6480  return tmp;
6481  } // PrintEndFlag
const std::vector< std::string > EndFlagNames
Definition: DataStructs.cxx:88
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
std::string to_string(WindowPattern const &pattern)
std::string tca::PrintEndFlag ( const Trajectory &  tj,
unsigned short  end 
)

Definition at line 6485 of file Utils.cxx.

6486  {
6487  if (end > 1) return "Invalid end";
6488  std::string tmp;
6489  bool first = true;
6490  for (unsigned short ib = 0; ib < EndFlagNames.size(); ++ib) {
6491  if (tj.EndFlag[end][ib]) {
6492  if (first) {
6493  tmp = std::to_string(end) + ":" + EndFlagNames[ib];
6494  first = false;
6495  }
6496  else {
6497  tmp += "," + EndFlagNames[ib];
6498  }
6499  }
6500  } // ib
6501  return tmp;
6502  } // PrintEndFlag
const std::vector< std::string > EndFlagNames
Definition: DataStructs.cxx:88
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
std::string to_string(WindowPattern const &pattern)
std::string tca::PrintHit ( const TCHit &  tch)

Definition at line 6516 of file Utils.cxx.

6517  {
6518  if (tch.allHitsIndex > (*evt.allHits).size() - 1) return "NA";
6519  auto& hit = (*evt.allHits)[tch.allHitsIndex];
6520  return std::to_string(hit.WireID().Plane) + ":" + std::to_string(hit.WireID().Wire) + ":" +
6521  std::to_string((int)hit.PeakTime()) + "_" + std::to_string(tch.InTraj);
6522  } // PrintHit
process_name hit
Definition: cheaterreco.fcl:51
std::string to_string(WindowPattern const &pattern)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
TCEvent evt
Definition: DataStructs.cxx:8
std::string tca::PrintHitShort ( const TCHit &  tch)

Definition at line 6506 of file Utils.cxx.

6507  {
6508  if (tch.allHitsIndex > (*evt.allHits).size() - 1) return "NA";
6509  auto& hit = (*evt.allHits)[tch.allHitsIndex];
6510  return std::to_string(hit.WireID().Plane) + ":" + std::to_string(hit.WireID().Wire) + ":" +
6511  std::to_string((int)hit.PeakTime());
6512  } // PrintHit
process_name hit
Definition: cheaterreco.fcl:51
std::string to_string(WindowPattern const &pattern)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
TCEvent evt
Definition: DataStructs.cxx:8
void tca::PrintP ( std::string  someText,
mf::LogVerbatim &  myprt,
PFPStruct &  pfp,
bool &  printHeader 
)

Definition at line 5605 of file Utils.cxx.

5606  {
5607  if (pfp.ID <= 0) return;
5608  if (printHeader) {
5609  myprt << "************ PFParticles ************\n";
5610  myprt << " prodID sVx _____sPos____ CS _______sDir______ ____sdEdx_____ eVx "
5611  "_____ePos____ CS ____edEdx_____ MVI MCSMom Len nTP3 nSec SLk? PDG Par \n";
5612  printHeader = false;
5613  } // printHeader
5614  auto sIndx = GetSliceIndex("P", pfp.UID);
5615  if (sIndx.first == USHRT_MAX) return;
5616  auto& slc = slices[sIndx.first];
5617  std::string str =
5618  std::to_string(slc.ID) + ":" + std::to_string(sIndx.first) + ":" + std::to_string(pfp.ID);
5619  str += "/" + std::to_string(pfp.UID);
5620  myprt << std::setw(12) << str;
5621  // start and end stuff
5622  for (unsigned short end = 0; end < 2; ++end) {
5623  str = "--";
5624  if (pfp.Vx3ID[end] > 0) str = "3V" + std::to_string(slc.vtx3s[pfp.Vx3ID[end] - 1].UID);
5625  myprt << std::setw(6) << str;
5626  myprt << std::fixed << std::right << std::setprecision(0);
5627  auto pos = PosAtEnd(pfp, end);
5628  myprt << std::setw(5) << pos[0];
5629  myprt << std::setw(5) << pos[1];
5630  myprt << std::setw(5) << pos[2];
5631  // print character for Outside or Inside the FV
5632  if (InsideFV(slc, pfp, end)) { myprt << " I"; }
5633  else {
5634  myprt << " O";
5635  }
5636  // only print the starting direction
5637  if (end == 0) {
5638  myprt << std::fixed << std::right << std::setprecision(2);
5639  auto dir = DirAtEnd(pfp, end);
5640  myprt << std::setw(6) << dir[0];
5641  myprt << std::setw(6) << dir[1];
5642  myprt << std::setw(6) << dir[2];
5643  } // end == 0
5644  for (auto& dedx : pfp.dEdx[end]) {
5645  if (dedx < 50) { myprt << std::setw(5) << std::setprecision(1) << dedx; }
5646  else {
5647  myprt << std::setw(5) << std::setprecision(0) << dedx;
5648  }
5649  } // dedx
5650  if (pfp.dEdx[end].size() < 3) {
5651  for (size_t i = 0; i < 3 - pfp.dEdx[end].size(); ++i) {
5652  myprt << std::setw(6) << ' ';
5653  }
5654  }
5655  } // startend
5656  myprt << std::setw(6) << pfp.MVI;
5657  // global stuff
5658  myprt << std::setw(7) << MCSMom(slc, pfp.TjIDs);
5659  float length = Length(pfp);
5660  if (length < 100) { myprt << std::setw(5) << std::setprecision(1) << length; }
5661  else {
5662  myprt << std::setw(5) << std::setprecision(0) << length;
5663  }
5664  myprt << std::setw(5) << pfp.TP3Ds.size();
5665  myprt << std::setw(5) << pfp.SectionFits.size();
5666  myprt << std::setw(5) << IsShowerLike(slc, pfp.TjIDs);
5667  myprt << std::setw(5) << pfp.PDGCode;
5668  myprt << std::setw(4) << pfp.ParentUID;
5669  if (!pfp.TjIDs.empty()) {
5670  if (pfp.TjUIDs.empty()) {
5671  // print Tjs in one TPC
5672  for (auto tjid : pfp.TjIDs)
5673  myprt << " TU" << slc.tjs[tjid - 1].UID;
5674  }
5675  else {
5676  // print Tjs in all TPCs (if this is called after FinishEvent)
5677  for (auto tjuid : pfp.TjUIDs)
5678  myprt << " TU" << tjuid;
5679  }
5680  } // TjIDs exist
5681  if (!pfp.DtrUIDs.empty()) {
5682  myprt << " dtrs";
5683  for (auto dtruid : pfp.DtrUIDs)
5684  myprt << " PU" << dtruid;
5685  } // dtr ids exist
5686  myprt << "\n";
5687  } // PrintP
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3468
float Length(const PFPStruct &pfp)
Definition: PFPUtils.cxx:3304
bool InsideFV(const TCSlice &slc, const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3045
walls no right
Definition: selectors.fcl:105
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3293
bool IsShowerLike(TCSlice &slc, const std::vector< int > TjIDs)
Definition: TCShower.cxx:1909
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
tuple dir
Definition: dropbox.py:28
std::string to_string(WindowPattern const &pattern)
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:5088
Vector3_t DirAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3284
void tca::PrintPFP ( std::string  someText,
TCSlice &  slc,
const PFPStruct &  pfp,
bool  printHeader 
)

Definition at line 6373 of file Utils.cxx.

6374  {
6375  mf::LogVerbatim myprt("TC");
6376  if (printHeader) {
6377  myprt << someText;
6378  myprt << " PFP sVx ________sPos_______ EF _______sDir______ ____sdEdx_____ eVx "
6379  "________ePos_______ EF _______eDir______ ____edEdx____ Len nTp3 MCSMom ShLike? "
6380  "PDG Par Prim\n";
6381  }
6382  myprt << someText;
6383  std::string pid = "P" + std::to_string(pfp.ID);
6384  myprt << std::setw(5) << pid;
6385  // start and end stuff
6386  for (unsigned short end = 0; end < 2; ++end) {
6387  myprt << std::setw(4) << pfp.Vx3ID[end];
6388  myprt << std::fixed << std::right << std::setprecision(1);
6389  auto pos = PosAtEnd(pfp, end);
6390  myprt << std::setw(7) << pos[0];
6391  myprt << std::setw(7) << pos[1];
6392  myprt << std::setw(7) << pos[2];
6393  // print characters that encode the EndFlag
6394  std::string ef;
6395  if (pfp.EndFlag[end][kOutFV]) { ef = "O"; }
6396  else {
6397  ef = "I";
6398  }
6399  if (pfp.EndFlag[end][kBragg]) ef += "B";
6400  myprt << std::setw(6) << ef;
6401  myprt << std::fixed << std::right << std::setprecision(2);
6402  auto dir = DirAtEnd(pfp, end);
6403  myprt << std::setw(6) << dir[0];
6404  myprt << std::setw(6) << dir[1];
6405  myprt << std::setw(6) << dir[2];
6406  for (auto& dedx : pfp.dEdx[end]) {
6407  if (dedx < 50) { myprt << std::setw(5) << std::setprecision(1) << dedx; }
6408  else {
6409  myprt << std::setw(5) << std::setprecision(0) << dedx;
6410  }
6411  } // dedx
6412  if (pfp.dEdx[end].size() < 3) {
6413  for (size_t i = 0; i < 3 - pfp.dEdx[end].size(); ++i) {
6414  myprt << std::setw(6) << ' ';
6415  }
6416  }
6417  } // startend
6418  // global stuff
6419  float length = Length(pfp);
6420  if (length < 100) { myprt << std::setw(5) << std::setprecision(1) << length; }
6421  else {
6422  myprt << std::setw(5) << std::setprecision(0) << length;
6423  }
6424  myprt << std::setw(5) << std::setprecision(2) << pfp.TP3Ds.size();
6425  myprt << std::setw(7) << MCSMom(slc, pfp.TjIDs);
6426  myprt << std::setw(5) << IsShowerLike(slc, pfp.TjIDs);
6427  myprt << std::setw(5) << pfp.PDGCode;
6428  myprt << " NA";
6429  myprt << std::setw(4) << pfp.ParentUID;
6430  myprt << std::setw(5) << PrimaryUID(slc, pfp);
6431  if (!pfp.TjIDs.empty()) {
6432  for (auto& tjID : pfp.TjIDs)
6433  myprt << " T" << tjID;
6434  }
6435  if (!pfp.DtrUIDs.empty()) {
6436  myprt << " dtrs";
6437  for (auto& dtrUID : pfp.DtrUIDs)
6438  myprt << " P" << dtrUID;
6439  }
6440  } // PrintPFP
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3468
float Length(const PFPStruct &pfp)
Definition: PFPUtils.cxx:3304
walls no right
Definition: selectors.fcl:105
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3293
bool IsShowerLike(TCSlice &slc, const std::vector< int > TjIDs)
Definition: TCShower.cxx:1909
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
tuple dir
Definition: dropbox.py:28
std::string to_string(WindowPattern const &pattern)
int PrimaryUID(const TCSlice &slc, const PFPStruct &pfp)
Definition: Utils.cxx:487
Vector3_t DirAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3284
void tca::PrintPFPs ( std::string  someText,
TCSlice &  slc 
)

Definition at line 6444 of file Utils.cxx.

6445  {
6446  if (slc.pfps.empty()) return;
6447 
6448  mf::LogVerbatim myprt("TC");
6449  myprt << someText;
6450  myprt
6451  << " PFP sVx ________sPos_______ ______sDir______ ______sdEdx_____ eVx "
6452  "________ePos_______ ______eDir______ ______edEdx_____ BstPln PDG TruPDG Par Prim E*P\n";
6453  bool printHeader = true;
6454  for (auto& pfp : slc.pfps) {
6455  PrintPFP(someText, slc, pfp, printHeader);
6456  printHeader = false;
6457  } // im
6458 
6459  } // PrintPFPs
void PrintPFP(std::string someText, TCSlice &slc, const PFPStruct &pfp, bool printHeader)
Definition: Utils.cxx:6373
std::string tca::PrintPos ( const TCSlice &  slc,
const TrajPoint &  tp 
)

Definition at line 6526 of file Utils.cxx.

6527  {
6528  return std::to_string(DecodeCTP(tp.CTP).Plane) + ":" + PrintPos(slc, tp.Pos);
6529  } // PrintPos
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
std::string to_string(WindowPattern const &pattern)
geo::PlaneID DecodeCTP(CTP_t CTP)
std::string tca::PrintPos ( const TCSlice &  slc,
const Point2_t &  pos 
)

Definition at line 6533 of file Utils.cxx.

6534  {
6535  unsigned int wire = 0;
6536  if (pos[0] > -0.4) wire = std::nearbyint(pos[0]);
6537  int time = std::nearbyint(pos[1] / tcc.unitsPerTick);
6538  return std::to_string(wire) + ":" + std::to_string(time);
6539  } // PrintPos
TCConfig tcc
Definition: DataStructs.cxx:9
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
std::string to_string(WindowPattern const &pattern)
void tca::PrintShower ( std::string  someText,
TCSlice &  slc,
const ShowerStruct &  ss,
bool  printHeader,
bool  printExtras 
)

Definition at line 4343 of file TCShower.cxx.

4348  {
4349  // print a single shower and a header (optional) and the extra variables like TjIDs, envelope, etc
4350  mf::LogVerbatim myprt("TC");
4351 
4352  if (printHeader) {
4353  myprt << someText
4354  << " ID CTP ParID ParFOM TruParID Energy nTjs dFOM AspRat stj vx0 __Pos0___ "
4355  "Chg(k) dRMS __Pos1___ Chg(k) dRMS __Pos2___ Chg(k) dRMS Angle SS3ID PFPID\n";
4356  } // printHeader
4357 
4358  myprt << someText << std::fixed;
4359  std::string sid = "2S" + std::to_string(ss.ID);
4360  myprt << std::setw(5) << sid;
4361  myprt << std::setw(6) << ss.CTP;
4362  sid = "NA";
4363  if (ss.ParentID > 0) sid = "T" + std::to_string(ss.ParentID);
4364  myprt << std::setw(7) << sid;
4365  myprt << std::setw(7) << std::setprecision(2) << ss.ParentFOM;
4366  myprt << std::setw(9) << ss.TruParentID;
4367  myprt << std::setw(7) << (int)ss.Energy;
4368  myprt << std::setw(5) << ss.TjIDs.size();
4369  myprt << std::setw(6) << std::setprecision(2) << ss.DirectionFOM;
4370  myprt << std::setw(7) << std::setprecision(2) << ss.AspectRatio;
4371  const auto& stj = slc.tjs[ss.ShowerTjID - 1];
4372  std::string tid = "T" + std::to_string(stj.ID);
4373  myprt << std::setw(5) << tid;
4374  std::string vid = "NA";
4375  if (stj.VtxID[0] > 0) vid = "2V" + std::to_string(stj.VtxID[0]);
4376  myprt << std::setw(5) << vid;
4377  for (auto& spt : stj.Pts) {
4378  myprt << std::setw(10) << PrintPos(slc, spt.Pos);
4379  myprt << std::setw(7) << std::fixed << std::setprecision(1) << spt.Chg / 1000;
4380  // myprt<<std::setw(5)<<spt.NTPsFit;
4381  myprt << std::setw(5) << std::setprecision(1) << spt.DeltaRMS;
4382  } // spt
4383  myprt << std::setw(6) << std::setprecision(2) << stj.Pts[1].Ang;
4384  std::string sss = "NA";
4385  if (ss.SS3ID > 0) sss = "3S" + std::to_string(ss.SS3ID);
4386  myprt << std::setw(6) << sss;
4387  if (ss.SS3ID > 0 && ss.SS3ID < (int)slc.showers.size()) {
4388  auto& ss3 = slc.showers[ss.SS3ID - 1];
4389  if (ss3.PFPIndex >= 0 && ss3.PFPIndex < slc.pfps.size()) {
4390  std::string pid = "P" + std::to_string(ss3.PFPIndex + 1);
4391  myprt << std::setw(6) << pid;
4392  }
4393  else {
4394  myprt << std::setw(6) << "NA";
4395  }
4396  }
4397  else {
4398  myprt << std::setw(6) << "NA";
4399  }
4400  if (ss.NeedsUpdate) myprt << " *** Needs update";
4401 
4402  if (!printExtras) return;
4403  myprt << "\n";
4404 
4405  myprt << someText << std::fixed;
4406  sid = "2S" + std::to_string(ss.ID);
4407  myprt << std::setw(5) << sid;
4408  myprt << " Tjs";
4409  for (auto id : ss.TjIDs)
4410  myprt << " T" << id;
4411  myprt << "\n";
4412  myprt << someText << std::fixed;
4413  sid = "2S" + std::to_string(ss.ID);
4414  myprt << std::setw(5) << sid;
4415  myprt << " Envelope";
4416  for (auto& vtx : ss.Envelope)
4417  myprt << " " << (int)vtx[0] << ":" << (int)(vtx[1] / tcc.unitsPerTick);
4418  myprt << "\n";
4419  myprt << someText << std::fixed;
4420  sid = "2S" + std::to_string(ss.ID);
4421  myprt << std::setw(5) << sid;
4422  myprt << " Nearby";
4423  for (auto id : ss.NearTjIDs)
4424  myprt << " T" << id;
4425 
4426  } // PrintShower
TCConfig tcc
Definition: DataStructs.cxx:9
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
std::string to_string(WindowPattern const &pattern)
void tca::PrintShowers ( detinfo::DetectorPropertiesData const &  detProp,
std::string  fcnLabel,
TCSlice &  slc 
)

Definition at line 4213 of file TCShower.cxx.

4214  {
4215  if (slc.showers.empty()) return;
4216  mf::LogVerbatim myprt("TC");
4217  myprt << fcnLabel << " 3D showers \n";
4218  for (auto& ss3 : slc.showers) {
4219  myprt << fcnLabel << " 3S" << ss3.ID << " 3V" << ss3.Vx3ID;
4220  myprt << " parentID " << ss3.ParentID;
4221  myprt << " ChgPos" << std::fixed;
4222  for (unsigned short xyz = 0; xyz < 3; ++xyz)
4223  myprt << " " << std::setprecision(0) << ss3.ChgPos[xyz];
4224  myprt << " Dir";
4225  for (unsigned short xyz = 0; xyz < 3; ++xyz)
4226  myprt << " " << std::setprecision(2) << ss3.Dir[xyz];
4227  myprt << " posInPlane";
4228  std::vector<float> projInPlane(slc.nPlanes);
4229  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
4230  CTP_t inCTP = EncodeCTP(ss3.TPCID.Cryostat, ss3.TPCID.TPC, plane);
4231  auto tp = MakeBareTP(detProp, slc, ss3.ChgPos, ss3.Dir, inCTP);
4232  myprt << " " << PrintPos(slc, tp.Pos);
4233  projInPlane[plane] = tp.Delta;
4234  } // plane
4235  myprt << " projInPlane";
4236  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
4237  myprt << " " << std::fixed << std::setprecision(2) << projInPlane[plane];
4238  } // plane
4239  for (auto cid : ss3.CotIDs) {
4240  auto& ss = slc.cots[cid - 1];
4241  myprt << "\n 2S" << ss.ID;
4242  auto& stj = slc.tjs[ss.ShowerTjID - 1];
4243  myprt << " ST" << stj.ID;
4244  myprt << " " << PrintPos(slc, stj.Pts[stj.EndPt[0]].Pos) << " - "
4245  << PrintPos(slc, stj.Pts[stj.EndPt[1]].Pos);
4246  } // ci
4247  if (ss3.NeedsUpdate) myprt << " *** Needs update";
4248  myprt << "\n";
4249  } // sss3
4250  } // PrintShowers
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const Point3_t &pos, CTP_t inCTP)
Definition: Utils.cxx:4027
unsigned int CTP_t
Definition: DataStructs.h:47
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:52
auto const detProp
void tca::PrintT ( std::string  someText,
mf::LogVerbatim &  myprt,
Trajectory &  tj,
bool &  printHeader 
)

Definition at line 5860 of file Utils.cxx.

5861  {
5862  // print a 2D vertex on one line
5863  if (tj.ID <= 0) return;
5864  if (debug.CTP != UINT_MAX && tj.CTP != debug.CTP) return;
5865  if (printHeader) {
5866  myprt << "************ Trajectories ************\n";
5867  myprt << "Tj AngleCode-EndFlag decoder (EF): <AngleCode> + <reason for stopping>";
5868  myprt << " (B=Bragg Peak, V=Vertex, A=AngleKink, C=ChargeKink, T=Trajectory)\n";
5869  myprt << " prodID CTP Pass Pts W:T Ang EF AveQ W:T Ang EF AveQ "
5870  "Chg(k) chgRMS Mom __Vtx__ PDG eLike Par Pri NuPar WorkID \n";
5871  printHeader = false;
5872  }
5873  auto sIndx = GetSliceIndex("T", tj.UID);
5874  if (sIndx.first == USHRT_MAX) return;
5875  auto& slc = slices[sIndx.first];
5876  std::string str = "T" + std::to_string(tj.ID) + "/TU" + std::to_string(tj.UID);
5877  myprt << std::fixed << std::setw(12) << str;
5878  myprt << std::setw(6) << tj.CTP;
5879  myprt << std::setw(5) << tj.Pass;
5880  myprt << std::setw(5) << tj.EndPt[1] - tj.EndPt[0] + 1;
5881  unsigned short endPt0 = tj.EndPt[0];
5882  auto& tp0 = tj.Pts[endPt0];
5883  int itick = tp0.Pos[1] / tcc.unitsPerTick;
5884  if (itick < 0) itick = 0;
5885  myprt << std::setw(6) << (int)(tp0.Pos[0] + 0.5) << ":" << itick; // W:T
5886  if (itick < 10) { myprt << " "; }
5887  if (itick < 100) { myprt << " "; }
5888  if (itick < 1000) { myprt << " "; }
5889  myprt << std::setw(6) << std::setprecision(2) << tp0.Ang;
5890  myprt << std::setw(2) << tp0.AngleCode;
5891  if (tj.EndFlag[0][kBragg]) { myprt << "B"; }
5892  else if (tj.EndFlag[0][kAtVtx]) {
5893  myprt << "V";
5894  }
5895  else if (tj.EndFlag[0][kAtKink]) {
5896  myprt << "K";
5897  }
5898  else if (tj.EndFlag[0][kAtTj]) {
5899  myprt << "T";
5900  }
5901  else {
5902  myprt << " ";
5903  }
5904  myprt << std::setw(5) << (int)tp0.AveChg;
5905  unsigned short endPt1 = tj.EndPt[1];
5906  auto& tp1 = tj.Pts[endPt1];
5907  itick = tp1.Pos[1] / tcc.unitsPerTick;
5908  myprt << std::setw(6) << (int)(tp1.Pos[0] + 0.5) << ":" << itick; // W:T
5909  if (itick < 10) { myprt << " "; }
5910  if (itick < 100) { myprt << " "; }
5911  if (itick < 1000) { myprt << " "; }
5912  myprt << std::setw(6) << std::setprecision(2) << tp1.Ang;
5913  myprt << std::setw(2) << tp1.AngleCode;
5914  if (tj.EndFlag[1][kBragg]) { myprt << "B"; }
5915  else if (tj.EndFlag[1][kAtVtx]) {
5916  myprt << "V";
5917  }
5918  else if (tj.EndFlag[1][kAtKink]) {
5919  myprt << "K";
5920  }
5921  else if (tj.EndFlag[1][kAtTj]) {
5922  myprt << "T";
5923  }
5924  else {
5925  myprt << " ";
5926  }
5927  myprt << std::setw(5) << (int)tp1.AveChg;
5928  myprt << std::setw(7) << std::setprecision(1) << tj.TotChg / 1000;
5929  myprt << std::setw(7) << std::setprecision(2) << tj.ChgRMS;
5930  myprt << std::setw(5) << tj.MCSMom;
5931  int vxid = 0;
5932  if (tj.VtxID[0] > 0) vxid = slc.vtxs[tj.VtxID[0] - 1].UID;
5933  myprt << std::setw(4) << vxid;
5934  vxid = 0;
5935  if (tj.VtxID[1] > 0) vxid = slc.vtxs[tj.VtxID[1] - 1].UID;
5936  myprt << std::setw(4) << vxid;
5937  myprt << std::setw(5) << tj.PDGCode;
5938  myprt << std::setw(7) << std::setprecision(2) << ElectronLikelihood(slc, tj);
5939  myprt << std::setw(5) << tj.ParentID;
5940  myprt << std::setw(5) << PrimaryID(slc, tj);
5941  myprt << std::setw(6) << NeutrinoPrimaryTjID(slc, tj);
5942  myprt << std::setw(7) << tj.WorkID;
5943  for (unsigned short ib = 0; ib < AlgBitNames.size(); ++ib)
5944  if (tj.AlgMod[ib]) myprt << " " << AlgBitNames[ib];
5945  for (unsigned short ib = 0; ib < StrategyBitNames.size(); ++ib)
5946  if (tj.Strategy[ib]) myprt << " " << StrategyBitNames[ib];
5947  myprt << "\n";
5948  } // PrintT
const std::vector< std::string > AlgBitNames
Definition: DataStructs.cxx:16
TCConfig tcc
Definition: DataStructs.cxx:9
const std::vector< std::string > StrategyBitNames
int NeutrinoPrimaryTjID(const TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:444
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:571
float ElectronLikelihood(const TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:3216
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
std::string to_string(WindowPattern const &pattern)
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:5088
void tca::PrintTP ( std::string  someText,
const TCSlice &  slc,
unsigned short  ipt,
short  dir,
unsigned short  pass,
const TrajPoint &  tp 
)

Definition at line 6296 of file Utils.cxx.

6302  {
6303  mf::LogVerbatim myprt("TC");
6304  myprt << someText << " TRP" << std::fixed;
6305  myprt << pass;
6306  if (dir > 0) { myprt << "+"; }
6307  else {
6308  myprt << "-";
6309  }
6310  myprt << std::setw(6) << tp.CTP;
6311  myprt << std::setw(5) << ipt;
6312  myprt << std::setw(5) << tp.Step;
6313  myprt << std::setw(6) << std::setprecision(2) << tp.Delta;
6314  myprt << std::setw(6) << std::setprecision(2) << tp.DeltaRMS;
6315  myprt << std::setw(6) << std::setprecision(2) << tp.Ang;
6316  myprt << std::setw(2) << tp.AngleCode;
6317  myprt << std::setw(6) << std::setprecision(2) << tp.AngErr;
6318  myprt << std::setw(6) << std::setprecision(2) << tp.Dir[0];
6319  myprt << std::setw(6) << std::setprecision(2) << tp.Dir[1];
6320  myprt << std::setw(7) << (int)tp.Chg;
6321  myprt << std::setw(8) << (int)tp.AveChg;
6322  myprt << std::setw(6) << std::setprecision(1) << tp.ChgPull;
6323  myprt << std::setw(7) << tp.FitChi;
6324  myprt << std::setw(6) << tp.NTPsFit;
6325  myprt << std::setw(7) << std::setprecision(3) << tp.KinkSig;
6326  // print the hits associated with this traj point
6327  if (tp.Hits.size() > 16) {
6328  // don't print too many hits (e.g. from a shower Tj)
6329  myprt << " " << tp.Hits.size() << " shower hits";
6330  }
6331  else {
6332  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
6333  unsigned int iht = tp.Hits[ii];
6334  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
6335  myprt << " " << hit.WireID().Wire << ":" << (int)hit.PeakTime();
6336  if (tp.UseHit[ii]) {
6337  // Distinguish used hits from nearby hits
6338  myprt << "_";
6339  }
6340  else {
6341  myprt << "x";
6342  }
6343  myprt << "T" << slc.slHits[iht].InTraj;
6344  } // iht
6345  if (tp.InPFP > 0) myprt << " inP" << tp.InPFP;
6346  }
6347  // print Environment
6348  if (tp.Environment.any()) myprt << " Env: " << TPEnvString(tp);
6349  } // PrintTP
process_name hit
Definition: cheaterreco.fcl:51
std::string TPEnvString(const TrajPoint &tp)
Definition: Utils.cxx:6353
tuple dir
Definition: dropbox.py:28
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
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 3397 of file PFPUtils.cxx.

3403  {
3404  if (pfp.TP3Ds.empty()) return;
3405  mf::LogVerbatim myprt("TC");
3406  myprt << someText << " pfp P" << pfp.ID << " MVI " << pfp.MVI;
3407  for (auto tid : pfp.TjIDs)
3408  myprt << " T" << tid;
3409  myprt << " Flags: CanSection? " << pfp.Flags[kCanSection];
3410  myprt << " NeedsUpdate? " << pfp.Flags[kNeedsUpdate];
3411  myprt << " Algs:";
3412  for (unsigned short ib = 0; ib < pAlgModSize; ++ib) {
3413  if (pfp.AlgMod[ib]) myprt << " " << AlgBitNames[ib];
3414  } // ib
3415  myprt << "\n";
3416  if (!pfp.SectionFits.empty()) {
3417  myprt << someText
3418  << " SFI ________Pos________ ________Dir_______ _____EndPos________ ChiDOF NPts "
3419  "NeedsUpdate?\n";
3420  for (std::size_t sfi = 0; sfi < pfp.SectionFits.size(); ++sfi) {
3421  myprt << someText << std::setw(4) << sfi;
3422  auto& sf = pfp.SectionFits[sfi];
3423  myprt << std::fixed << std::setprecision(1);
3424  unsigned short startPt = 0, endPt = 0;
3425  if (SectionStartEnd(pfp, sfi, startPt, endPt)) {
3426  auto& start = pfp.TP3Ds[startPt].Pos;
3427  myprt << std::setw(7) << start[0] << std::setw(7) << start[1] << std::setw(7) << start[2];
3428  }
3429  else {
3430  myprt << " Invalid";
3431  }
3432  myprt << std::fixed << std::setprecision(2);
3433  myprt << std::setw(7) << sf.Dir[0] << std::setw(7) << sf.Dir[1] << std::setw(7)
3434  << sf.Dir[2];
3435  myprt << std::fixed << std::setprecision(1);
3436  if (endPt < pfp.TP3Ds.size()) {
3437  auto& end = pfp.TP3Ds[endPt].Pos;
3438  myprt << std::setw(7) << end[0] << std::setw(7) << end[1] << std::setw(7) << end[2];
3439  }
3440  else {
3441  myprt << " Invalid";
3442  }
3443  myprt << std::setprecision(1) << std::setw(6) << sf.ChiDOF;
3444  myprt << std::setw(6) << sf.NPts;
3445  myprt << std::setw(6) << sf.NeedsUpdate;
3446  myprt << "\n";
3447  } // sec
3448  } // SectionFits
3449  if (printPts < 0) {
3450  // print the head if we print all points
3451  myprt<<someText<<" Note: GBH = TP3D Flags. G = Good, B = Bad, H = High dE/dx \n";
3452  myprt<<someText<<" ipt SFI ________Pos________ Delta Pull GBH Path along dE/dx S? T_ipt_P:W:T\n";
3453  }
3454  unsigned short fromPt = 0;
3455  unsigned short toPt = pfp.TP3Ds.size() - 1;
3456  if (printPts >= 0) fromPt = toPt;
3457  // temp kink angle for each point
3458  std::vector<float> dang(pfp.TP3Ds.size(), -1);
3459  for (unsigned short ipt = fromPt; ipt <= toPt; ++ipt) {
3460  auto tp3d = pfp.TP3Ds[ipt];
3461  myprt << someText << std::setw(4) << ipt;
3462  myprt << std::setw(4) << tp3d.SFIndex;
3463  myprt << std::fixed << std::setprecision(1);
3464  myprt << std::setw(7) << tp3d.Pos[0] << std::setw(7) << tp3d.Pos[1] << std::setw(7)
3465  << tp3d.Pos[2];
3466  myprt << std::setprecision(1) << std::setw(6) << (tp3d.Pos[0] - tp3d.TPX);
3467  float pull = PointPull(pfp, tp3d);
3468  myprt << std::setprecision(1) << std::setw(6) << pull;
3469  myprt << std::setw(3) << tp3d.Flags[kTP3DGood] << tp3d.Flags[kTP3DBad];
3470  myprt << std::setw(7) << std::setprecision(1) << PosSep(tp3d.Pos, pfp.TP3Ds[0].Pos);
3471  myprt << std::setw(7) << std::setprecision(1) << tp3d.along;
3472  myprt << std::setw(6) << std::setprecision(2) << dEdx(clockData, detProp, slc, tp3d);
3473  // print SignalAtTP in each plane
3474  myprt << " ";
3475  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
3476  CTP_t inCTP = EncodeCTP(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
3477  auto tp = MakeBareTP(detProp, slc, tp3d.Pos, inCTP);
3478  myprt << " " << SignalAtTp(tp);
3479  } // plane
3480  if (tp3d.TjID > 0) {
3481  auto& tp = slc.tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
3482  myprt << " T" << tp3d.TjID << "_" << tp3d.TPIndex << "_" << PrintPos(slc, tp) << " "
3483  << TPEnvString(tp);
3484  }
3485  else {
3486  myprt << " UNDEFINED";
3487  }
3488  myprt << "\n";
3489  } // ipt
3490  } // PrintTP3Ds
const std::vector< std::string > AlgBitNames
Definition: DataStructs.cxx:16
bool SignalAtTp(TrajPoint &tp)
Definition: Utils.cxx:2004
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
std::string TPEnvString(const TrajPoint &tp)
Definition: Utils.cxx:6353
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const Point3_t &pos, CTP_t inCTP)
Definition: Utils.cxx:4027
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
bool SectionStartEnd(const PFPStruct &pfp, unsigned short sfIndex, unsigned short &startPt, unsigned short &endPt)
Definition: PFPUtils.cxx:3312
constexpr unsigned int pAlgModSize
Definition: DataStructs.h:280
float dEdx(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, TP3D &tp3d)
Definition: PFPUtils.cxx:2687
float PointPull(const PFPStruct &pfp, const TP3D &tp3d)
Definition: PFPUtils.cxx:2815
unsigned int CTP_t
Definition: DataStructs.h:47
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2565
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:52
auto const detProp
void tca::PrintTPHeader ( std::string  someText)

Definition at line 6287 of file Utils.cxx.

6288  {
6289  mf::LogVerbatim("TC") << someText
6290  << " TRP CTP Ind Stp Delta RMS Ang C Err Dir0 Dir1 Q "
6291  " AveQ Pull FitChi NTPF KinkSig Hits ";
6292  } // PrintTPHeader
void tca::PrintTrajectory ( std::string  someText,
const TCSlice &  slc,
const Trajectory &  tj,
unsigned short  tPoint 
)

Definition at line 6195 of file Utils.cxx.

6199  {
6200  // prints one or all trajectory points on tj
6201 
6202  if (tPoint == USHRT_MAX) {
6203  if (tj.ID < 0) {
6204  mf::LogVerbatim myprt("TC");
6205  myprt << someText << " ";
6206  myprt << "Work: UID " << tj.UID << " CTP " << tj.CTP << " StepDir " << tj.StepDir
6207  << " PDG " << tj.PDGCode << " slc.vtxs " << tj.VtxID[0] << " " << tj.VtxID[1]
6208  << " nPts " << tj.Pts.size() << " EndPts " << tj.EndPt[0] << " " << tj.EndPt[1];
6209  myprt << " MCSMom " << tj.MCSMom;
6210  myprt << " EndFlags " << PrintEndFlag(tj, 0) << " " << PrintEndFlag(tj, 1);
6211  myprt << " AlgMods:";
6212  for (unsigned short ib = 0; ib < AlgBitNames.size(); ++ib)
6213  if (tj.AlgMod[ib]) myprt << " " << AlgBitNames[ib];
6214  }
6215  else {
6216  mf::LogVerbatim myprt("TC");
6217  myprt << someText << " ";
6218  myprt << "slcID " << slc.ID << " T" << tj.ID << " uT" << tj.UID << " WorkID " << tj.WorkID
6219  << " StepDir " << tj.StepDir << " PDG " << tj.PDGCode << " VtxID " << tj.VtxID[0]
6220  << " " << tj.VtxID[1] << " nPts " << tj.Pts.size() << " EndPts " << tj.EndPt[0] << " "
6221  << tj.EndPt[1];
6222  myprt << " MCSMom " << tj.MCSMom;
6223  myprt << " EndFlags " << PrintEndFlag(tj, 0) << " " << PrintEndFlag(tj, 1);
6224  myprt << " AlgMods:";
6225  for (unsigned short ib = 0; ib < AlgBitNames.size(); ++ib)
6226  if (tj.AlgMod[ib]) myprt << " " << AlgBitNames[ib];
6227  }
6228  PrintTPHeader(someText);
6229  for (unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt)
6230  PrintTP(someText, slc, ipt, tj.StepDir, tj.Pass, tj.Pts[ipt]);
6231  // See if this trajectory is a shower Tj
6232  if (tj.AlgMod[kShowerTj]) {
6233  for (unsigned short ic = 0; ic < slc.cots.size(); ++ic) {
6234  if (slc.cots[ic].TjIDs.empty()) continue;
6235  // only print out the info for the correct Tj
6236  if (slc.cots[ic].ShowerTjID != tj.ID) continue;
6237  const ShowerStruct& ss = slc.cots[ic];
6238  mf::LogVerbatim myprt("TC");
6239  myprt << "cots index " << ic << " ";
6240  myprt << someText << " Envelope";
6241  if (ss.Envelope.empty()) { myprt << " NA"; }
6242  else {
6243  for (auto& vtx : ss.Envelope)
6244  myprt << " " << (int)vtx[0] << ":" << (int)(vtx[1] / tcc.unitsPerTick);
6245  }
6246  myprt << " Energy " << (int)ss.Energy;
6247  myprt << " Area " << std::fixed << std::setprecision(1) << (int)ss.EnvelopeArea
6248  << " ChgDensity " << ss.ChgDensity;
6249  myprt << "\nInShower TjIDs";
6250  for (auto& tjID : ss.TjIDs) {
6251  myprt << " " << tjID;
6252  } // tjID
6253 
6254  myprt << "\n";
6255  myprt << "NearTjIDs";
6256  for (auto& tjID : ss.NearTjIDs) {
6257  myprt << " " << tjID;
6258  } // tjID
6259  myprt << "\n";
6260  myprt << "\n";
6261  myprt << "Angle " << std::fixed << std::setprecision(2) << ss.Angle << " +/- "
6262  << ss.AngleErr;
6263  myprt << " AspectRatio " << std::fixed << std::setprecision(2) << ss.AspectRatio;
6264  myprt << " DirectionFOM " << std::fixed << std::setprecision(2) << ss.DirectionFOM;
6265  if (ss.ParentID > 0) { myprt << " Parent Tj " << ss.ParentID << " FOM " << ss.ParentFOM; }
6266  else {
6267  myprt << " No parent";
6268  }
6269  myprt << " TruParentID " << ss.TruParentID << " SS3ID " << ss.SS3ID << "\n";
6270  if (ss.NeedsUpdate) myprt << "*********** This shower needs to be updated ***********";
6271  myprt << "................................................";
6272  } // ic
6273  } // Shower Tj
6274  }
6275  else {
6276  // just print one traj point
6277  if (tPoint > tj.Pts.size() - 1) {
6278  mf::LogVerbatim("TC") << "Can't print non-existent traj point " << tPoint;
6279  return;
6280  }
6281  PrintTP(someText, slc, tPoint, tj.StepDir, tj.Pass, tj.Pts[tPoint]);
6282  }
6283  } // PrintTrajectory
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:6296
std::string PrintEndFlag(const PFPStruct &pfp, unsigned short end)
Definition: Utils.cxx:6463
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
for($it=0;$it< $RaceTrack_number;$it++)
void PrintTPHeader(std::string someText)
Definition: Utils.cxx:6287
std::vector< unsigned int > tca::PutHitsInVector ( const TCSlice &  slc,
PFPStruct const &  pfp,
HitStatus_t  hitRequest 
)

Definition at line 2731 of file Utils.cxx.

2732  {
2733  // Put hits with the assn P -> TP3D -> TP -> Hit into a vector
2734  std::vector<unsigned int> hitVec;
2735  if (pfp.TP3Ds.empty()) return hitVec;
2736 
2737  for (auto& tp3d : pfp.TP3Ds) {
2738  if (tp3d.Flags[kTP3DBad]) continue;
2739  if (tp3d.TjID <= 0) continue;
2740  auto& tp = slc.tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
2741  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2742  unsigned int iht = tp.Hits[ii];
2743  bool useit = (hitRequest == kAllHits);
2744  if (tp.UseHit[ii] && hitRequest == kUsedHits) useit = true;
2745  if (!tp.UseHit[ii] && hitRequest == kUnusedHits) useit = true;
2746  if (useit) hitVec.push_back(iht);
2747  }
2748  } // tp3d
2749  return hitVec;
2750  } // PutHitsInVector
std::vector< unsigned int > tca::PutTrajHitsInVector ( const Trajectory &  tj,
HitStatus_t  hitRequest 
)

Definition at line 2754 of file Utils.cxx.

2755  {
2756  // Put hits (which are indexed into slHits) in each trajectory point into a flat vector
2757  std::vector<unsigned int> hitVec;
2758 
2759  // special handling for shower trajectories. UseHit isn't valid
2760  if (tj.AlgMod[kShowerTj]) {
2761  for (auto& tp : tj.Pts)
2762  hitVec.insert(hitVec.end(), tp.Hits.begin(), tp.Hits.end());
2763  return hitVec;
2764  } // shower Tj
2765 
2766  // reserve under the assumption that there will be one hit per point
2767  hitVec.reserve(tj.Pts.size());
2768  for (unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) {
2769  for (unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
2770  unsigned int iht = tj.Pts[ipt].Hits[ii];
2771  bool useit = (hitRequest == kAllHits);
2772  if (tj.Pts[ipt].UseHit[ii] && hitRequest == kUsedHits) useit = true;
2773  if (!tj.Pts[ipt].UseHit[ii] && hitRequest == kUnusedHits) useit = true;
2774  if (useit) hitVec.push_back(iht);
2775  } // iht
2776  } // ipt
2777  return hitVec;
2778  } // PutTrajHitsInVector
void tca::Reconcile2Vs ( TCSlice &  slc)

Definition at line 1067 of file TCVertex.cxx.

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

Definition at line 1163 of file TCVertex.cxx.

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

Definition at line 429 of file TCShower.cxx.

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

Definition at line 577 of file TCShower.cxx.

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

Definition at line 427 of file PFPUtils.cxx.

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

Definition at line 474 of file PFPUtils.cxx.

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

Definition at line 1650 of file PFPUtils.cxx.

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

Definition at line 2089 of file PFPUtils.cxx.

2092  {
2093  // try to recover from a poor initial fit
2094  if(pfp.AlgMod[kSmallAngle]) return;
2095  if(pfp.SectionFits.size() != 1) return;
2096  if(pfp.TP3Ds.size() < 20) return;
2097  if(!CanSection(slc, pfp)) return;
2098 
2099  // make a copy
2100  auto p2 = pfp;
2101  // try two sections
2102  p2.SectionFits.resize(2);
2103  unsigned short halfPt = p2.TP3Ds.size() / 2;
2104  for(unsigned short ipt = halfPt; ipt < p2.TP3Ds.size(); ++ipt) p2.TP3Ds[ipt].SFIndex = 1;
2105  // Confirm that both sections can be reconstructed
2106  unsigned short toPt = Find3DRecoRange(slc, p2, 0, 3, 1);
2107  if(toPt > p2.TP3Ds.size()) return;
2108  toPt = Find3DRecoRange(slc, p2, halfPt, 3, 1);
2109  if(toPt > p2.TP3Ds.size()) return;
2110  if(!FitSection(clockData, detProp, slc, p2, 0) || !FitSection(clockData, detProp, slc, p2, 1)) {
2111  if(prt) {
2112  mf::LogVerbatim myprt("TC");
2113  myprt << "Recover failed MVI " << p2.MVI << " in TPC " << p2.TPCID.TPC;
2114  for(auto tid : p2.TjIDs) myprt << " T" << tid;
2115  } // prt
2116  return;
2117  }
2118  if(prt) mf::LogVerbatim("TC")<<"Recover: P" << pfp.ID << " success";
2119  pfp = p2;
2120 
2121  } // Recover
bool CanSection(const TCSlice &slc, const PFPStruct &pfp)
Definition: PFPUtils.cxx:1343
unsigned short Find3DRecoRange(const TCSlice &slc, const PFPStruct &pfp, unsigned short fromPt, unsigned short min2DPts, short dir)
Definition: PFPUtils.cxx:1359
bool FitSection(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, unsigned short sfIndex)
Definition: PFPUtils.cxx:1414
auto const detProp
bool tca::RefineVtxPosition ( TCSlice &  slc,
const Trajectory &  tj,
unsigned short &  nearPt,
short  nPtsToChk,
bool  prt 
)

Definition at line 2690 of file TCVertex.cxx.

2695  {
2696  // The tj has been slated to be split somewhere near point nearPt. This function will move
2697  // the near point a bit to the most likely point of a vertex
2698 
2699  float maxChg = tj.Pts[nearPt].Chg;
2700  short maxChgPt = nearPt;
2701  unsigned short fromPt = tj.EndPt[0];
2702  short spt = (short)nearPt - (short)nPtsToChk;
2703  if (spt > (short)fromPt) fromPt = nearPt - nPtsToChk;
2704  unsigned short toPt = nearPt + nPtsToChk;
2705  if (toPt > tj.EndPt[1]) toPt = tj.EndPt[1];
2706 
2707  for (short ipt = fromPt; ipt <= toPt; ++ipt) {
2708  if (ipt < tj.EndPt[0] || ipt > tj.EndPt[1]) continue;
2709  auto& tp = tj.Pts[ipt];
2710  if (tp.Chg > maxChg) {
2711  maxChg = tp.Chg;
2712  maxChgPt = ipt;
2713  }
2714  if (prt)
2715  mf::LogVerbatim("TC") << "RVP: ipt " << ipt << " Pos " << tp.CTP << ":"
2716  << PrintPos(slc, tp.Pos) << " chg " << (int)tp.Chg << " nhits "
2717  << tp.Hits.size();
2718  } // ipt
2719  if (nearPt == maxChgPt) return false;
2720  nearPt = maxChgPt;
2721  return true;
2722  } //RefineVtxPosition
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
void tca::ReleaseHits ( TCSlice &  slc,
Trajectory &  tj 
)

Definition at line 1062 of file Utils.cxx.

1063  {
1064  // Sets InTraj[] = 0 for all TPs in work. Called when abandoning work
1065  for (auto& tp : tj.Pts) {
1066  for (auto iht : tp.Hits) {
1067  if (slc.slHits[iht].InTraj == tj.ID) slc.slHits[iht].InTraj = 0;
1068  }
1069  } // tp
1070 
1071  } // 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 1357 of file TCShower.cxx.

1363  {
1364  // removes the tjs in the pfp from the ss3 2D showers and optionally update. This function only returns
1365  // false if there was a failure. The absence of any pfp Tjs in ss3 is not considered a failure
1366 
1367  if (pfp.ID == 0 || ss3.ID == 0) return false;
1368 
1369  std::string fcnLabel = inFcnLabel + ".RemP";
1370  for (auto tid : pfp.TjIDs) {
1371  for (auto cid : ss3.CotIDs) {
1372  auto& ss = slc.cots[cid - 1];
1373  if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tid) == ss.TjIDs.end()) continue;
1374  if (!RemoveTj(fcnLabel, slc, tid, ss, doUpdate, prt)) return false;
1375  ss3.NeedsUpdate = true;
1376  } // cid
1377  } // ptid
1378 
1379  if (doUpdate && ss3.NeedsUpdate) UpdateShower(fcnLabel, slc, ss3, prt);
1380  return true;
1381 
1382  } // Remove PFP
bool RemoveTj(std::string inFcnLabel, TCSlice &slc, int TjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1521
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:913
bool tca::RemoveTj ( std::string  inFcnLabel,
TCSlice &  slc,
int  TjID,
ShowerStruct &  ss,
bool  doUpdate,
bool  prt 
)

Definition at line 1521 of file TCShower.cxx.

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

Definition at line 1112 of file PFPUtils.cxx.

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

Definition at line 2197 of file Utils.cxx.

2198  {
2199  if (itj > slc.tjs.size() - 1) return;
2200  if (!slc.tjs[itj].AlgMod[kKilled]) {
2201  mf::LogWarning("TC")
2202  << "RestoreObsoleteTrajectory: Trying to restore not-obsolete trajectory "
2203  << slc.tjs[itj].ID;
2204  return;
2205  }
2206  unsigned int iht;
2207  for (auto& tp : slc.tjs[itj].Pts) {
2208  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2209  if (tp.UseHit[ii]) {
2210  iht = tp.Hits[ii];
2211  if (slc.slHits[iht].InTraj == 0) { slc.slHits[iht].InTraj = slc.tjs[itj].ID; }
2212  }
2213  } // ii
2214  } // tp
2215  slc.tjs[itj].AlgMod[kKilled] = false;
2216  } // RestoreObsoleteTrajectory
void tca::Reverse ( TCSlice &  slc,
PFPStruct &  pfp 
)

Definition at line 2360 of file PFPUtils.cxx.

2361  {
2362  // reverse the PFParticle
2363  std::reverse(pfp.TP3Ds.begin(), pfp.TP3Ds.end());
2364  std::reverse(pfp.SectionFits.begin(), pfp.SectionFits.end());
2365  for (std::size_t sfi = 0; sfi < pfp.SectionFits.size(); ++sfi) {
2366  auto& sf = pfp.SectionFits[sfi];
2367  // flip the direction vector
2368  for (unsigned short xyz = 0; xyz < 3; ++xyz)
2369  sf.Dir[xyz] *= -1;
2370  } // sf
2371  // correct the along variable
2372  for (auto& tp3d : pfp.TP3Ds)
2373  tp3d.along *= -1;
2374  std::swap(pfp.dEdx[0], pfp.dEdx[1]);
2375  std::swap(pfp.dEdxErr[0], pfp.dEdxErr[1]);
2376  std::swap(pfp.Vx3ID[0], pfp.Vx3ID[1]);
2377  std::swap(pfp.EndFlag[0], pfp.EndFlag[1]);
2378  } // Reverse
void tca::ReversePropagate ( TCSlice &  slc,
Trajectory &  tj 
)

Definition at line 1316 of file StepUtils.cxx.

1317  {
1318  // Reverse the trajectory and step in the opposite direction. The
1319  // updated trajectory is returned if this process is successful
1320 
1321  if(!tcc.useAlg[kRvPrp]) return;
1322 
1323  if(tj.Pts.size() < 6) return;
1324  // only do this once
1325  if(tj.AlgMod[kRvPrp]) return;
1326 
1327  // This code can't handle VLA trajectories
1328  if(tj.Pts[tj.EndPt[0]].AngleCode == 2) return;
1329 
1330  bool prt = (tcc.dbgStp || tcc.dbgAlg[kRvPrp]);
1331 
1332  // this function requires the first TP be included in the trajectory.
1333  if(tj.EndPt[0] > 0) {
1334  tj.Pts.erase(tj.Pts.begin(), tj.Pts.begin() + tj.EndPt[0]);
1335  SetEndPoints(tj);
1336  }
1337 
1338  if(prt) mf::LogVerbatim("TC")<<"ReversePropagate: Prepping Tj "<<tj.ID<<" incoming StepDir "<<tj.StepDir;
1339 
1340  short stepDir = tj.StepDir;
1341 
1342  // find the wire on which the first TP resides
1343  unsigned int wire0 = std::nearbyint(tj.Pts[0].Pos[0]);
1344  unsigned int nextWire = wire0 - tj.StepDir;
1345 
1346  // check for dead wires
1347  geo::PlaneID planeID = DecodeCTP(tj.CTP);
1348  unsigned short ipl = planeID.Plane;
1349  while(nextWire > slc.firstWire[ipl] && nextWire < slc.lastWire[ipl]) {
1350  if(evt.goodWire[ipl][nextWire]) break;
1351  nextWire -= tj.StepDir;
1352  }
1353  if(nextWire == slc.lastWire[ipl] - 1) return;
1354  // clone the first point
1355  TrajPoint tp = tj.Pts[0];
1356  // strip off the hits
1357  tp.Hits.clear(); tp.UseHit.reset();
1358  // move it to the next wire (in the opposite direction of the step direction)
1359  MoveTPToWire(tp, (float)nextWire);
1360  // find close unused hits near this position
1361  float maxDelta = 10 * tj.Pts[tj.EndPt[1]].DeltaRMS;
1362  if(!FindCloseHits(slc, tp, maxDelta, kUnusedHits)) return;
1363  if(prt) mf::LogVerbatim("TC")<<" nUnused hits "<<tp.Hits.size()<<" at Pos "<<PrintPos(slc, tp);
1364  if(tp.Hits.empty()) return;
1365  // There are hits on the next wire. Make a working copy of the trajectory, reverse it and try
1366  // to extend it with StepAway
1367  if(prt) {
1368  mf::LogVerbatim myprt("TC");
1369  myprt<<" tp.Hits ";
1370  for(auto& iht : tp.Hits) myprt<<" "<<PrintHit(slc.slHits[iht])<<"_"<<slc.slHits[iht].InTraj;
1371  } // tcc.dbgStp
1372  //
1373  // Make a working copy of tj
1374  Trajectory tjWork = tj;
1375  // So the first shall be last and the last shall be first
1376  ReverseTraj(slc, tjWork);
1377  // Flag it to use special cuts in StepAway
1378  tjWork.AlgMod[kRvPrp] = true;
1379  // save the strategy word and set it to normal
1380  auto saveStrategy = tjWork.Strategy;
1381  tjWork.Strategy.reset();
1382  tjWork.Strategy[kNormal] = true;
1383  // Reduce the number of fitted points to a small number
1384  unsigned short lastPt = tjWork.Pts.size() - 1;
1385  if(lastPt < 4) return;
1386  // update the charge
1387  float chg = 0;
1388  float cnt = 0;
1389  for(unsigned short ii = 0; ii < 4; ++ii) {
1390  unsigned short ipt = lastPt - ii;
1391  if(tjWork.Pts[ipt].Chg == 0) continue;
1392  chg += tjWork.Pts[ipt].Chg;
1393  ++cnt;
1394  } // ii
1395  if(cnt == 0) return;
1396  if(cnt > 1) tjWork.Pts[lastPt].AveChg = chg / cnt;
1397  StepAway(slc, tjWork);
1398  if(!tj.IsGood) {
1399  if(prt) mf::LogVerbatim("TC")<<" ReversePropagate StepAway failed";
1400  return;
1401  }
1402  tjWork.Strategy = saveStrategy;
1403  // check the new stopping point
1404  ChkStopEndPts(slc, tjWork, tcc.dbgStp);
1405  // restore the original direction
1406  if(tjWork.StepDir != stepDir) ReverseTraj(slc, tjWork);
1407  tj = tjWork;
1408  // TODO: Maybe UpdateTjChgProperties should be called here
1409  // re-check the ends
1410  ChkStop(slc, tj);
1411 
1412  } // ReversePropagate
void StepAway(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:30
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3413
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:630
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:2843
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6516
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
void ReverseTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:3294
void ChkStop(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:3705
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
geo::PlaneID DecodeCTP(CTP_t CTP)
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:587
void MoveTPToWire(TrajPoint &tp, float wire)
Definition: Utils.cxx:2831
TCEvent evt
Definition: DataStructs.cxx:8
void ChkStopEndPts(TCSlice &slc, Trajectory &tj, bool prt)
Definition: StepUtils.cxx:1562
void tca::ReverseShower ( std::string  inFcnLabel,
TCSlice &  slc,
ShowerStruct &  ss,
bool  prt 
)

Definition at line 3153 of file TCShower.cxx.

3154  {
3155  // Reverses the shower and the shower tj
3156 
3157  if (ss.ID == 0) return;
3158  if (ss.TjIDs.empty()) return;
3159 
3160  std::string fcnLabel = inFcnLabel + ".RevSh";
3161 
3162  std::reverse(ss.ShPts.begin(), ss.ShPts.end());
3163  // change the sign of RotPos
3164  for (auto& sspt : ss.ShPts) {
3165  sspt.RotPos[0] = -sspt.RotPos[0];
3166  sspt.RotPos[1] = -sspt.RotPos[1];
3167  }
3168  // flip the shower angle
3169  if (ss.Angle > 0) { ss.Angle -= M_PI; }
3170  else {
3171  ss.Angle += M_PI;
3172  }
3173  if (ss.DirectionFOM != 0) ss.DirectionFOM = 1 / ss.DirectionFOM;
3174  auto& stj = slc.tjs[ss.ShowerTjID - 1];
3175  ReverseTraj(slc, stj);
3176  DefineEnvelope(fcnLabel, slc, ss, prt);
3177  if (prt) mf::LogVerbatim("TC") << fcnLabel << " Reversed shower. Shower angle = " << ss.Angle;
3178  } // ReverseShower
void DefineEnvelope(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3489
void ReverseTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:3294
void tca::ReverseShower ( std::string  inFcnLabel,
TCSlice &  slc,
int  cotID,
bool  prt 
)

Definition at line 3182 of file TCShower.cxx.

3183  {
3184  // Reverses the shower and the shower tj
3185 
3186  if (cotID > (int)slc.cots.size()) return;
3187  ShowerStruct& ss = slc.cots[cotID - 1];
3188  if (ss.ID == 0) return;
3189  ReverseShower(inFcnLabel, slc, ss, prt);
3190  }
void ReverseShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3153
void tca::ReverseTraj ( TCSlice &  slc,
Trajectory &  tj 
)

Definition at line 3294 of file Utils.cxx.

3295  {
3296  // reverse the trajectory
3297  if (tj.Pts.empty()) return;
3298  // reverse the crawling direction flag
3299  tj.StepDir = -tj.StepDir;
3300  // Vertices
3301  std::swap(tj.VtxID[0], tj.VtxID[1]);
3302  // trajectory points
3303  std::reverse(tj.Pts.begin(), tj.Pts.end());
3304  // reverse the stop flag
3305  std::reverse(tj.EndFlag.begin(), tj.EndFlag.end());
3306  std::swap(tj.dEdx[0], tj.dEdx[1]);
3307  // reverse the direction vector on all points
3308  for (unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) {
3309  if (tj.Pts[ipt].Dir[0] != 0) tj.Pts[ipt].Dir[0] = -tj.Pts[ipt].Dir[0];
3310  if (tj.Pts[ipt].Dir[1] != 0) tj.Pts[ipt].Dir[1] = -tj.Pts[ipt].Dir[1];
3311  if (tj.Pts[ipt].Ang > 0) { tj.Pts[ipt].Ang -= M_PI; }
3312  else {
3313  tj.Pts[ipt].Ang += M_PI;
3314  }
3315  } // ipt
3316  if (tj.StartEnd == 0 || tj.StartEnd == 1) tj.StartEnd = 1 - tj.StartEnd;
3317  SetEndPoints(tj);
3318  // UpdateMatchStructs(slc, tj.ID, tj.ID);
3319  } // ReverseTraj
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3413
void tca::SaveAllCots ( TCSlice &  slc,
const CTP_t &  inCTP,
std::string  someText 
)

Definition at line 174 of file TCShTree.cxx.

174  {
175  if(!tcc.modes[kSaveShowerTree]) return;
176  for(unsigned short cotIndex = 0; cotIndex < slc.cots.size(); ++cotIndex) {
177  auto& ss = slc.cots[cotIndex];
178  if (ss.CTP != inCTP) continue;
179  if(ss.ID == 0) continue;
180  SaveTjInfo(slc, ss, someText);
181  } // cotIndex
182  } // SaveAllCots
TCConfig tcc
Definition: DataStructs.cxx:9
save shower tree
Definition: DataStructs.h:540
void SaveTjInfo(TCSlice &slc, std::vector< std::vector< int >> &tjList, std::string stageName)
Definition: TCShTree.cxx:14
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:607
void tca::SaveAllCots ( TCSlice &  slc,
std::string  someText 
)

Definition at line 185 of file TCShTree.cxx.

185  {
186  if(!tcc.modes[kSaveShowerTree]) return;
187  for(unsigned short cotIndex = 0; cotIndex < slc.cots.size(); ++cotIndex) {
188  auto& ss = slc.cots[cotIndex];
189  if(ss.ID == 0) continue;
190  SaveTjInfo(slc, ss, someText);
191  } // cotIndex
192  }
TCConfig tcc
Definition: DataStructs.cxx:9
save shower tree
Definition: DataStructs.h:540
void SaveTjInfo(TCSlice &slc, std::vector< std::vector< int >> &tjList, std::string stageName)
Definition: TCShTree.cxx:14
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:607
void tca::SaveCRInfo ( detinfo::DetectorClocksData const &  clockData,
TCSlice &  slc,
PFPStruct &  pfp,
bool  prt,
bool  fIsRealData 
)

Definition at line 26 of file TCCR.cxx.

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

Definition at line 14 of file TCShTree.cxx.

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, stageName);
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:411
void SaveTjInfoStuff(TCSlice &slc, Trajectory &tj, int stageNum, std::string stageName)
Definition: TCShTree.cxx:140
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< int > ShowerID
Definition: DataStructs.h:403
ShowerTreeVars stv
Definition: DataStructs.cxx:11
save shower tree
Definition: DataStructs.h:540
std::vector< float > Envelope
Definition: DataStructs.h:409
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:607
std::vector< int > EnvPlane
Definition: DataStructs.h:410
unsigned int CTP_t
Definition: DataStructs.h:47
int GetStageNum(ShowerTreeVars &stv, std::string stageName)
Definition: TCShTree.cxx:194
std::vector< int > EnvShowerID
Definition: DataStructs.h:412
void tca::SaveTjInfo ( TCSlice &  slc,
const ShowerStruct &  ss,
std::string  stageName 
)

Definition at line 56 of file TCShTree.cxx.

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

Definition at line 140 of file TCShTree.cxx.

140  {
141  if(!tcc.modes[kSaveShowerTree]) return;
142 
143  TrajPoint& beginPoint = tj.Pts[tj.EndPt[0]];
144  TrajPoint& endPoint = tj.Pts[tj.EndPt[1]];
145 
146  stv.BeginWir.push_back(std::nearbyint(beginPoint.Pos[0]));
147  stv.BeginTim.push_back(std::nearbyint(beginPoint.Pos[1]/tcc.unitsPerTick));
148  stv.BeginAng.push_back(beginPoint.Ang);
149  stv.BeginChg.push_back(beginPoint.Chg);
150  stv.BeginVtx.push_back(tj.VtxID[0]);
151 
152  stv.EndWir.push_back(std::nearbyint(endPoint.Pos[0]));
153  stv.EndTim.push_back(std::nearbyint(endPoint.Pos[1]/tcc.unitsPerTick));
154  stv.EndAng.push_back(endPoint.Ang);
155  stv.EndChg.push_back(endPoint.Chg);
156  stv.EndVtx.push_back(tj.VtxID[1]);
157 
158  stv.MCSMom.push_back(tj.MCSMom);
159  stv.TjID.push_back(tj.ID);
160  stv.IsShowerTj.push_back(-1);
161 
162  stv.ShowerID.push_back(-1);
163  stv.IsShowerParent.push_back(-1);
164  stv.StageNum.push_back(stageNum);
165  stv.nStages = stageNum;
166  geo::PlaneID iPlnID = DecodeCTP(tj.CTP);
167  stv.PlaneNum.push_back(iPlnID.Plane);
168 
169  stv.nPlanes = slc.nPlanes;
170 
171  } // SaveTjInfoStuff
std::vector< int > IsShowerParent
Definition: DataStructs.h:404
std::vector< float > EndWir
Definition: DataStructs.h:391
std::vector< float > EndAng
Definition: DataStructs.h:393
std::vector< float > BeginTim
Definition: DataStructs.h:387
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< float > BeginAng
Definition: DataStructs.h:388
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
std::vector< float > EndTim
Definition: DataStructs.h:392
std::vector< int > ShowerID
Definition: DataStructs.h:403
ShowerTreeVars stv
Definition: DataStructs.cxx:11
save shower tree
Definition: DataStructs.h:540
std::vector< int > TjID
Definition: DataStructs.h:401
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
std::vector< short > BeginVtx
Definition: DataStructs.h:390
std::vector< short > EndVtx
Definition: DataStructs.h:395
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
std::vector< float > BeginChg
Definition: DataStructs.h:389
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:607
std::vector< short > MCSMom
Definition: DataStructs.h:397
std::vector< int > StageNum
Definition: DataStructs.h:405
unsigned short nPlanes
Definition: DataStructs.h:415
std::vector< float > BeginWir
Definition: DataStructs.h:386
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< float > EndChg
Definition: DataStructs.h:394
std::vector< int > IsShowerTj
Definition: DataStructs.h:402
std::vector< short > PlaneNum
Definition: DataStructs.h:399
void tca::ScoreVertices ( TCSlice &  slc)

Definition at line 2146 of file TCVertex.cxx.

2147  {
2148  // reset all 3D vertex, 2D vertex and Tj high-score vertex bits in tpcid
2149 
2150  // reset the 2D vertex status bits
2151  for (auto& vx : slc.vtxs) {
2152  if (vx.ID == 0) continue;
2153  vx.Stat[kHiVx3Score] = false;
2154  } // vx
2155  // and the tj bits
2156  for (auto& tj : slc.tjs) {
2157  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
2158  tj.AlgMod[kTjHiVx3Score] = false;
2159  } // tj
2160  // Score the 2D vertices
2161  for (auto& vx : slc.vtxs) {
2162  if (vx.ID == 0) continue;
2163  SetVx2Score(slc, vx);
2164  } // vx
2165  // Score the 3D vertices
2166  for (auto& vx3 : slc.vtx3s) {
2167  if (vx3.ID == 0) continue;
2168  SetVx3Score(slc, vx3);
2169  } // vx3
2170  } // ScoreVertices
matched to a high-score 3D vertex
Definition: DataStructs.h:95
void SetVx3Score(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2242
void SetVx2Score(TCSlice &slc)
Definition: TCVertex.cxx:2264
bool tca::SectionStartEnd ( const PFPStruct &  pfp,
unsigned short  sfIndex,
unsigned short &  startPt,
unsigned short &  endPt 
)

Definition at line 3312 of file PFPUtils.cxx.

3316  {
3317  // this assumes that the TP3Ds vector is sorted
3318  startPt = USHRT_MAX;
3319  endPt = USHRT_MAX;
3320  if (sfIndex >= pfp.SectionFits.size()) return false;
3321 
3322  bool first = true;
3323  for (std::size_t ipt = 0; ipt < pfp.TP3Ds.size(); ++ipt) {
3324  auto& tp3d = pfp.TP3Ds[ipt];
3325  if (tp3d.SFIndex < sfIndex) continue;
3326  if (first) {
3327  first = false;
3328  startPt = ipt;
3329  } // first
3330  if (tp3d.SFIndex > sfIndex) break;
3331  endPt = ipt;
3332  } // ipt
3333  return true;
3334 
3335  } // SectionStartEnd
void tca::SetAngleCode ( TrajPoint &  tp)

Definition at line 773 of file Utils.cxx.

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

Definition at line 431 of file larreco/larreco/RecoAlg/TCAlg/Utils.h.

432  {
433  // returns the elements of set1 and set2 that are different
434  std::vector<T> different;
435  if (set1.empty() && set2.empty()) return different;
436  if (!set1.empty() && set2.empty()) return set1;
437  if (set1.empty() && !set2.empty()) return set2;
438  for (auto element1 : set1) {
439  // check for a common element
440  if (std::find(set2.begin(), set2.end(), element1) != set2.end()) continue;
441  // check for a duplicate
442  if (std::find(different.begin(), different.end(), element1) != different.end()) continue;
443  different.push_back(element1);
444  } // element1
445  for (auto element2 : set2) {
446  // check for a common element
447  if (std::find(set1.begin(), set1.end(), element2) != set1.end()) continue;
448  // check for a duplicate
449  if (std::find(different.begin(), different.end(), element2) != different.end()) continue;
450  different.push_back(element2);
451  } // element1
452  return different;
453  } // SetDifference
void tca::SetEndPoints ( Trajectory &  tj)

Definition at line 3413 of file Utils.cxx.

3414  {
3415  // Find the first (last) TPs, EndPt[0] (EndPt[1], that have charge
3416 
3417  // don't mess with showerTjs or halo tjs
3418  if (tj.AlgMod[kShowerTj] || tj.AlgMod[kHaloTj]) return;
3419 
3420  tj.EndPt[0] = 0;
3421  tj.EndPt[1] = 0;
3422  if (tj.Pts.size() == 0) return;
3423 
3424  // check the end point pointers
3425  for (unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) {
3426  if (tj.Pts[ipt].Chg != 0) {
3427  tj.EndPt[0] = ipt;
3428  break;
3429  }
3430  }
3431  for (unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
3432  unsigned short ipt = tj.Pts.size() - 1 - ii;
3433  if (tj.Pts[ipt].Chg != 0) {
3434  tj.EndPt[1] = ipt;
3435  break;
3436  }
3437  }
3438  } // SetEndPoints
void tca::SetHighScoreBits ( TCSlice &  slc,
Vtx3Store &  vx3 
)

Definition at line 2193 of file TCVertex.cxx.

2194  {
2195  // Sets the tj and 2D vertex score bits to true
2196 
2197  if (vx3.ID == 0) return;
2198 
2199  for (unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
2200  if (vx3.Vx2ID[ipl] <= 0) continue;
2201  VtxStore& vx2 = slc.vtxs[vx3.Vx2ID[ipl] - 1];
2202  vx2.Stat[kHiVx3Score] = false;
2203  // transfer this to all attached tjs and vertices attached to those tjs
2204  std::vector<int> tjlist = GetVtxTjIDs(slc, vx2);
2205  std::vector<int> vxlist;
2206  while (true) {
2207  // tag Tjs and make a list of attached vertices whose high-score
2208  // bit needs to be set
2209  vxlist.clear();
2210  for (auto tjid : tjlist) {
2211  auto& tj = slc.tjs[tjid - 1];
2212  tj.AlgMod[kTjHiVx3Score] = true;
2213  for (unsigned short end = 0; end < 2; ++end) {
2214  if (tj.VtxID[end] == 0) continue;
2215  auto& vx2 = slc.vtxs[tj.VtxID[end] - 1];
2216  if (vx2.Stat[kHiVx3Score]) continue;
2217  vx2.Stat[kHiVx3Score] = true;
2218  vxlist.push_back(vx2.ID);
2219  } // end
2220  } // tjid
2221 
2222  if (vxlist.empty()) break;
2223  // re-build tjlist using vxlist
2224  std::vector<int> newtjlist;
2225  for (auto vxid : vxlist) {
2226  auto& vx2 = slc.vtxs[vxid - 1];
2227  auto tmp = GetVtxTjIDs(slc, vx2);
2228  for (auto tjid : tmp) {
2229  if (std::find(tjlist.begin(), tjlist.end(), tjid) == tjlist.end())
2230  newtjlist.push_back(tjid);
2231  } // tjid
2232  } // vxid
2233  if (newtjlist.empty()) break;
2234  tjlist = newtjlist;
2235  } // true
2236  } // ipl
2237 
2238  } // SetHighScoreBits
matched to a high-score 3D vertex
Definition: DataStructs.h:95
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const VtxStore &vx2)
Definition: TCVertex.cxx:2837
template<typename T >
std::vector< T > tca::SetIntersection ( const std::vector< T > &  set1,
const std::vector< T > &  set2 
)

Definition at line 408 of file larreco/larreco/RecoAlg/TCAlg/Utils.h.

409  {
410  // returns a vector containing the elements of set1 and set2 that are common. This function
411  // is a replacement for std::set_intersection which fails in the following situation:
412  // set1 = {11 12 17 18} and set2 = {6 12 18}
413  // There is no requirement that the elements be sorted, unlike std::set_intersection
414  std::vector<T> shared;
415 
416  if (set1.empty()) return shared;
417  if (set2.empty()) return shared;
418  for (auto element1 : set1) {
419  // check for a common element
420  if (std::find(set2.begin(), set2.end(), element1) == set2.end()) continue;
421  // check for a duplicate
422  if (std::find(shared.begin(), shared.end(), element1) != shared.end()) continue;
423  shared.push_back(element1);
424  } // element1
425  return shared;
426  } // SetIntersection
bool tca::SetMag ( Vector3_t &  v1,
double  mag 
)

Definition at line 2583 of file PFPUtils.cxx.

2584  {
2585  double den = v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2];
2586  if (den == 0) return false;
2587  den = sqrt(den);
2588 
2589  v1[0] *= mag / den;
2590  v1[1] *= mag / den;
2591  v1[2] *= mag / den;
2592  return true;
2593  } // SetMag
bool tca::SetMag ( Vector2_t &  v1,
double  mag 
)

Definition at line 3347 of file Utils.cxx.

3348  {
3349  double den = v1[0] * v1[0] + v1[1] * v1[1];
3350  if (den == 0) return false;
3351  den = sqrt(den);
3352 
3353  v1[0] *= mag / den;
3354  v1[1] *= mag / den;
3355  return true;
3356  } // SetMag
bool tca::SetParent ( detinfo::DetectorPropertiesData const &  detProp,
std::string  inFcnLabel,
TCSlice &  slc,
PFPStruct &  pfp,
ShowerStruct3D &  ss3,
bool  prt 
)

Definition at line 1832 of file TCShower.cxx.

1838  {
1839  // set the pfp as the parent of ss3. The calling function should do the error recovery
1840  if (pfp.ID == 0 || ss3.ID == 0) return false;
1841  if (ss3.CotIDs.empty()) return false;
1842 
1843  std::string fcnLabel = inFcnLabel + ".SP";
1844 
1845  for (auto cid : ss3.CotIDs) {
1846  auto& ss = slc.cots[cid - 1];
1847  auto& stj = slc.tjs[ss.ShowerTjID - 1];
1848  stj.VtxID[0] = 0;
1849  if (ss.ParentID > 0) {
1850  auto& oldParent = slc.tjs[ss.ParentID - 1];
1851  oldParent.AlgMod[kShwrParent] = false;
1852  ss.ParentID = 0;
1853  ss.ParentFOM = 10;
1854  } // remove old parents
1855  // add new parents
1856  for (auto tjid : pfp.TjIDs) {
1857  auto& tj = slc.tjs[tjid - 1];
1858  if (tj.CTP != ss.CTP) continue;
1859  if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), tjid) == ss.TjIDs.end()) {
1860  // Add the tj but don't update yet
1861  if (!AddTj(fcnLabel, slc, tjid, ss, false, prt)) return false;
1862  } // parent not in ss
1863  // Don't define it to be the parent if it is short and the pfp projection in this plane is low
1864  auto pos = PosAtEnd(pfp, 0);
1865  auto dir = DirAtEnd(pfp, 0);
1866  auto tp = MakeBareTP(detProp, slc, pos, dir, tj.CTP);
1867  unsigned short npts = tj.EndPt[1] - tj.EndPt[0] + 1;
1868  if (tp.Delta > 0.5 || npts > 20) {
1869  if (prt)
1870  mf::LogVerbatim("TC") << fcnLabel << " 3S" << ss3.ID << " parent P" << pfp.ID << " -> T"
1871  << tjid << " -> 2S" << ss.ID << " parent";
1872  }
1873  else {
1874  if (prt)
1875  mf::LogVerbatim("TC") << fcnLabel << " 3S" << ss3.ID << " parent P" << pfp.ID << " -> T"
1876  << tjid << " low projection in plane " << tp.Delta
1877  << ". Not a parent";
1878  continue;
1879  }
1880  ss.ParentID = tjid;
1881  ss.NeedsUpdate = true;
1882  // set the ss start vertex
1883  if (ss3.Vx3ID > 0) {
1884  auto& vx3 = slc.vtx3s[ss3.Vx3ID - 1];
1885  auto v2list = GetAssns(slc, "3V", vx3.ID, "2V");
1886  for (unsigned short end = 0; end < 2; ++end) {
1887  if (tj.VtxID[end] <= 0) continue;
1888  if (std::find(v2list.begin(), v2list.end(), tj.VtxID[end]) != v2list.end())
1889  stj.VtxID[0] = tj.VtxID[end];
1890  } // end
1891  } // ss3.Vx3ID > 0
1892  // and update
1893  if (!UpdateShower(fcnLabel, slc, ss, prt)) return false;
1894  } // tjid
1895  } // cid
1896  ss3.ParentID = pfp.ID;
1897 
1898  unsigned short pEnd = FarEnd(slc, pfp, ss3.ChgPos);
1899  ss3.Vx3ID = pfp.Vx3ID[pEnd];
1900  float fom3D = ParentFOM(fcnLabel, slc, pfp, pEnd, ss3, prt);
1901  for (auto cid : ss3.CotIDs)
1902  slc.cots[cid - 1].ParentFOM = fom3D;
1903 
1904  return true;
1905  } // SetParent
bool AddTj(std::string inFcnLabel, TCSlice &slc, int tjID, ShowerStruct &ss, bool doUpdate, bool prt)
Definition: TCShower.cxx:1448
unsigned short FarEnd(const TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3339
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4849
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3293
float ParentFOM(std::string inFcnLabel, TCSlice &slc, PFPStruct &pfp, unsigned short pend, ShowerStruct3D &ss3, bool prt)
Definition: TCShower.cxx:2077
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const Point3_t &pos, CTP_t inCTP)
Definition: Utils.cxx:4027
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
tuple dir
Definition: dropbox.py:28
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:913
Vector3_t DirAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3284
auto const detProp
void tca::SetPDGCode ( TCSlice &  slc,
unsigned short  itj 
)

Definition at line 4350 of file Utils.cxx.

4351  {
4352  if (itj > slc.tjs.size() - 1) return;
4353  SetPDGCode(slc, slc.tjs[itj]);
4354  }
void SetPDGCode(TCSlice &slc, unsigned short itj)
Definition: Utils.cxx:4350
void tca::SetPDGCode ( TCSlice &  slc,
Trajectory &  tj 
)

Definition at line 4358 of file Utils.cxx.

4359  {
4360  // Sets the PDG code for the supplied trajectory. Note that the existing
4361  // PDG code is left unchanged if these cuts are not met
4362 
4363  short npwc = NumPtsWithCharge(slc, tj, false);
4364  if (npwc < 6) {
4365  tj.PDGCode = 0;
4366  return;
4367  }
4368 
4369  if (tj.Strategy[kStiffEl] && ElectronLikelihood(slc, tj) > tcc.showerTag[6]) {
4370  tj.PDGCode = 111;
4371  return;
4372  }
4373  if (tj.Strategy[kStiffMu]) {
4374  tj.PDGCode = 13;
4375  return;
4376  }
4377 
4378  if (tcc.showerTag[6] > 0 && ElectronLikelihood(slc, tj) > tcc.showerTag[6]) {
4379  tj.PDGCode = 11;
4380  return;
4381  }
4382 
4383  if (tcc.muonTag[0] <= 0) return;
4384  // Special handling of very long straight trajectories, e.g. uB cosmic rays
4385  bool isAMuon = (npwc > (unsigned short)tcc.muonTag[0] && tj.MCSMom > tcc.muonTag[1]);
4386  // anything really really long must be a muon
4387  if (npwc > 500) isAMuon = true;
4388  if (isAMuon) tj.PDGCode = 13;
4389 
4390  } // SetPDGCode
TCConfig tcc
Definition: DataStructs.cxx:9
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:558
float ElectronLikelihood(const TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:3216
std::vector< short > muonTag
Definition: DataStructs.h:555
use the stiff electron strategy
Definition: DataStructs.h:501
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2116
use the stiff muon strategy
Definition: DataStructs.h:502
bool tca::SetSection ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice &  slc,
PFPStruct &  pfp,
TP3D &  tp3d 
)

Definition at line 2770 of file PFPUtils.cxx.

2774  {
2775  // Determine which SectionFit this tp3d should reside in, then calculate
2776  // the 3D position and the distance from the center of the SectionFit
2777 
2778  if (tp3d.Wire < 0) return false;
2779  if (pfp.SectionFits.empty()) return false;
2780  if (pfp.SectionFits[0].Pos[0] == -10.0) return false;
2781  if(pfp.Flags[kSmallAngle]) return true;
2782 
2783  auto plnID = DecodeCTP(tp3d.CTP);
2784 
2785  if (pfp.SectionFits.size() == 1) { tp3d.SFIndex = 0; }
2786  else {
2787  // Find the section center that is closest to this point in the wire coordinate
2788  float best = 1E6;
2789  for (std::size_t sfi = 0; sfi < pfp.SectionFits.size(); ++sfi) {
2790  auto& sf = pfp.SectionFits[sfi];
2791  float sfWire = tcc.geom->WireCoordinate(sf.Pos[1], sf.Pos[2], plnID);
2792  float sep = std::abs(sfWire - tp3d.Wire);
2793  if (sep < best) {
2794  best = sep;
2795  tp3d.SFIndex = sfi;
2796  }
2797  } // sfi
2798  } // pfp.SectionFits.size() > 1
2799  auto& sf = pfp.SectionFits[tp3d.SFIndex];
2800  auto plnTP = MakeBareTP(detProp, slc, sf.Pos, sf.Dir, tp3d.CTP);
2801  // the number of wires relative to the SectionFit center
2802  double dw = tp3d.Wire - plnTP.Pos[0];
2803  // dt/dW was stored in DeltaRMS
2804  double t = dw * plnTP.DeltaRMS;
2805  // define the 3D position
2806  for (unsigned short xyz = 0; xyz < 3; ++xyz)
2807  tp3d.Pos[xyz] = sf.Pos[xyz] + t * sf.Dir[xyz];
2808  tp3d.along = t;
2809  tp3d.Flags[kTP3DGood] = true;
2810  return true;
2811  } // SetSection
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
TCConfig tcc
Definition: DataStructs.cxx:9
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const Point3_t &pos, CTP_t inCTP)
Definition: Utils.cxx:4027
T abs(T value)
const geo::GeometryCore * geom
Definition: DataStructs.h:576
geo::PlaneID DecodeCTP(CTP_t CTP)
auto const detProp
void tca::SetStrategy ( TCSlice &  slc,
Trajectory &  tj 
)

Definition at line 340 of file StepUtils.cxx.

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

Definition at line 3626 of file Utils.cxx.

3627  {
3628  // This function is called after tj reconstruction is completed to set TP Environment
3629  // bits that are dependent on reconstruction, just kEnvNearMuon for now. This bit is
3630  // set for all TPs that are within 5 wire-equivalents of a muon
3631 
3632  std::array<int, 2> wireWindow;
3633  Point2_t timeWindow;
3634  unsigned short plane = DecodeCTP(inCTP).Plane;
3635  //
3636  float delta = 5;
3637 
3638  for (auto& mutj : slc.tjs) {
3639  if (mutj.AlgMod[kKilled]) continue;
3640  if (mutj.CTP != inCTP) continue;
3641  if (mutj.PDGCode != 13) continue;
3642  unsigned short nnear = 0;
3643  for (unsigned short ipt = mutj.EndPt[0]; ipt <= mutj.EndPt[1]; ++ipt) {
3644  auto& tp = mutj.Pts[ipt];
3645  wireWindow[0] = tp.Pos[0];
3646  wireWindow[1] = tp.Pos[0];
3647  timeWindow[0] = tp.Pos[1] - delta;
3648  timeWindow[1] = tp.Pos[1] + delta;
3649  // get a list of all hits in this region
3650  bool hitsNear;
3651  auto closeHits =
3652  FindCloseHits(slc, wireWindow, timeWindow, plane, kAllHits, true, hitsNear);
3653  if (closeHits.empty()) continue;
3654  for (auto iht : closeHits) {
3655  auto inTraj = slc.slHits[iht].InTraj;
3656  if (inTraj <= 0) continue;
3657  if (inTraj == mutj.ID) continue;
3658  auto& dtj = slc.tjs[inTraj - 1];
3659  if (dtj.PDGCode == 13) continue;
3660  for (unsigned short jpt = dtj.EndPt[0]; jpt <= dtj.EndPt[1]; ++jpt) {
3661  auto& dtp = dtj.Pts[jpt];
3662  if (std::find(dtp.Hits.begin(), dtp.Hits.end(), iht) == dtp.Hits.end()) continue;
3663  dtp.Environment[kEnvNearMuon] = true;
3664  ++nnear;
3665  } // jpt
3666  } // iht
3667  } // ipt
3668  } // mutj
3669  } // SetTPEnvironment
std::array< float, 2 > Point2_t
Definition: DataStructs.h:43
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:2843
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
geo::PlaneID DecodeCTP(CTP_t CTP)
void tca::SetVx2Score ( TCSlice &  slc)

Definition at line 2264 of file TCVertex.cxx.

2265  {
2266  // A version that sets the score of the last added vertex
2267  if (slc.vtxs.empty()) return;
2268  auto& vx2 = slc.vtxs[slc.vtxs.size() - 1];
2269  SetVx2Score(slc, vx2);
2270  } // SetVx2Score
void SetVx2Score(TCSlice &slc)
Definition: TCVertex.cxx:2264
void tca::SetVx2Score ( TCSlice &  slc,
VtxStore &  vx2 
)

Definition at line 2274 of file TCVertex.cxx.

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

Definition at line 2242 of file TCVertex.cxx.

2243  {
2244  // Calculate the 3D vertex score and flag Tjs that are attached to high score vertices as defined
2245  // by vtx2DCuts
2246 
2247  if (vx3.ID == 0) return;
2248 
2249  vx3.Score = 0;
2250  for (unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
2251  if (vx3.Vx2ID[ipl] <= 0) continue;
2252  VtxStore& vx2 = slc.vtxs[vx3.Vx2ID[ipl] - 1];
2253  vx3.Score += vx2.Score;
2254  } // ipl
2255  vx3.Score /= (float)slc.nPlanes;
2256  // don't allow it to get too small or negative
2257  if (vx3.Score < 0.001) vx3.Score = 0.001;
2258  if (vx3.Score > tcc.vtx2DCuts[7]) SetHighScoreBits(slc, vx3);
2259 
2260  } // SetVx3Score
then if[["$THISISATEST"==1]]
Definition: neoSmazza.sh:95
TCConfig tcc
Definition: DataStructs.cxx:9
void SetHighScoreBits(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2193
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:550
double tca::ShowerEnergy ( const ShowerStruct3D &  ss3)

Definition at line 3954 of file TCShower.cxx.

3955  {
3956  if (ss3.ID == 0) return 0;
3957  if (ss3.Energy.empty()) return 0;
3958  double ave = 0;
3959  for (auto e : ss3.Energy) {
3960  ave += e;
3961  } // e
3962  ave /= ss3.Energy.size();
3963  return ave;
3964  } // ShowerEnergy
do i e
float tca::ShowerEnergy ( TCSlice &  slc,
const std::vector< int >  tjIDs 
)

Definition at line 3968 of file TCShower.cxx.

3969  {
3970  // Calculate energy using the total charge of all hits in each tj in the shower
3971  if (tjIDs.empty()) return 0;
3972  float sum = 0;
3973  for (auto tid : tjIDs) {
3974  auto& tj = slc.tjs[tid - 1];
3975  sum += tj.TotChg;
3976  } // tid
3977  return ChgToMeV(sum);
3978  } // ShowerEnergy
float ChgToMeV(float chg)
Definition: TCShower.cxx:3982
void tca::ShowerParams ( double  showerEnergy,
double &  shMaxAlong,
double &  along95 
)

Definition at line 1923 of file TCShower.cxx.

1924  {
1925  // Returns summary properties of photon showers parameterized in the energy range 50 MeV < E_gamma < 1 GeV:
1926  // shMaxAlong = the longitudinal distance (cm) between the start of the shower and the center of charge
1927  // along95 = the longitudinal distance (cm) between the start of the shower and 95% energy containment
1928  // all units are in cm
1929  if (showerEnergy < 10) {
1930  shMaxAlong = 0;
1931  along95 = 0;
1932  return;
1933  }
1934  shMaxAlong = 16 * log(showerEnergy / 15);
1935  // The 95% containment is reduced a bit at higher energy
1936  double scale = 2.75 - 9.29E-4 * showerEnergy;
1937  if (scale < 2) scale = 2;
1938  along95 = scale * shMaxAlong;
1939  } // ShowerParams
double tca::ShowerParamTransRMS ( double  showerEnergy,
double  along 
)

Definition at line 1943 of file TCShower.cxx.

1944  {
1945  // returns the pareameterized width rms of a shower at along relative to the shower max
1946  double shMaxAlong, shE95Along;
1947  ShowerParams(showerEnergy, shMaxAlong, shE95Along);
1948  if (shMaxAlong <= 0) return 0;
1949  double tau = (along + shMaxAlong) / shMaxAlong;
1950  // The shower width is modeled as a simple cone that scales with tau
1951  double rms = -0.4 + 2.5 * tau;
1952  if (rms < 0.5) rms = 0.5;
1953  return rms;
1954  } // ShowerParamTransRMS
void ShowerParams(double showerEnergy, double &shMaxAlong, double &along95)
Definition: TCShower.cxx:1923
bool tca::SignalAtTp ( TrajPoint &  tp)

Definition at line 2004 of file Utils.cxx.

2005  {
2006  // returns true if there is a hit near tp.Pos by searching through the full hit collection (if there
2007  // are multiple slices) or through the last slice (if there is only one slice)
2008 
2009  tp.Environment[kEnvNearSrcHit] = false;
2010 
2011  // just check the hits in the last slice
2012  if (evt.wireHitRange.empty()) {
2013  const auto& slc = slices[slices.size() - 1];
2014  return SignalAtTpInSlc(slc, tp);
2015  }
2016 
2017  if (tp.Pos[0] < -0.4) return false;
2018  geo::PlaneID planeID = DecodeCTP(tp.CTP);
2019  unsigned short pln = planeID.Plane;
2020  unsigned int wire = std::nearbyint(tp.Pos[0]);
2021  if (wire > evt.goodWire[pln].size() - 1) return false;
2022  // assume there is a signal on a dead wire
2023  if (!evt.goodWire[pln][wire]) return true;
2024 
2025  // check the proximity of all of the hits in the range
2026  float projTick = (float)(tp.Pos[1] / tcc.unitsPerTick);
2027  float tickRange = 0;
2028  if (std::abs(tp.Dir[1]) != 0) {
2029  tickRange = std::abs(0.5 / tp.Dir[1]) / tcc.unitsPerTick;
2030  // don't let it get too large
2031  if (tickRange > 40) tickRange = 40;
2032  }
2033  float loTpTick = projTick - tickRange;
2034  float hiTpTick = projTick + tickRange;
2035 
2036  // no signal here if there are no hits on this wire
2037  if (evt.wireHitRange[pln][wire].first == UINT_MAX) return false;
2038 
2039  for (unsigned int iht = evt.wireHitRange[pln][wire].first;
2040  iht <= evt.wireHitRange[pln][wire].second;
2041  ++iht) {
2042  auto& hit = (*evt.allHits)[iht];
2043  // We wouldn't need to make this check if hits were sorted
2044  const auto& wid = hit.WireID();
2045  if (wid.Cryostat != planeID.Cryostat) continue;
2046  if (wid.TPC != planeID.TPC) continue;
2047  if (wid.Plane != planeID.Plane) continue;
2048  if (projTick < hit.PeakTime()) {
2049  float loHitTick = hit.PeakTime() - 3 * hit.RMS();
2050  if (hiTpTick > loHitTick) return true;
2051  }
2052  else {
2053  float hiHitTick = hit.PeakTime() + 3 * hit.RMS();
2054  if (loTpTick < hiHitTick) return true;
2055  }
2056  } // iht
2057  // No hit was found near projTick. Search through the source hits collection
2058  // (if it is defined) for a hit that may have been removed by disambiguation
2059  // Use the srcHit collection if it is available
2060  if (evt.srcHits != NULL) {
2061  if (NearbySrcHit(planeID, wire, loTpTick, hiTpTick)) {
2062  tp.Environment[kEnvNearSrcHit] = true;
2063  return true;
2064  } // NearbySrcHit
2065  } // evt.srcHits != NULL
2066  return false;
2067  } // SignalAtTp
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:212
process_name hit
Definition: cheaterreco.fcl:51
T abs(T value)
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
TP is near a hit in the srcHit collection but no allHit hit exists (DUNE disambiguation error) ...
Definition: DataStructs.h:525
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:630
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
std::vector< recob::Hit > const * srcHits
Definition: DataStructs.h:623
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
bool SignalAtTpInSlc(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:1962
bool NearbySrcHit(geo::PlaneID plnID, unsigned int wire, float loTick, float hiTick)
Definition: Utils.cxx:2071
TCEvent evt
Definition: DataStructs.cxx:8
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:406
std::vector< std::vector< std::pair< unsigned int, unsigned int > > > wireHitRange
Definition: DataStructs.h:626
bool tca::SignalAtTpInSlc ( const TCSlice &  slc,
const TrajPoint &  tp 
)

Definition at line 1962 of file Utils.cxx.

1963  {
1964  // Version of SignalAtTP that only checks the hit collection in the current slice
1965 
1966  if (tp.Pos[0] < -0.4) return false;
1967  geo::PlaneID planeID = DecodeCTP(tp.CTP);
1968  unsigned short pln = planeID.Plane;
1969  unsigned int wire = std::nearbyint(tp.Pos[0]);
1970  if (wire > evt.goodWire[pln].size() - 1) return false;
1971  // assume there is a signal on a dead wire
1972  if (!evt.goodWire[pln][wire]) return true;
1973  // no signal here if there are no hits on this wire
1974  if (slc.wireHitRange[pln][wire].first == UINT_MAX) return false;
1975  // check the proximity of all of the hits in the range
1976  float projTick = (float)(tp.Pos[1] / tcc.unitsPerTick);
1977  float tickRange = 0;
1978  if (std::abs(tp.Dir[1]) != 0) {
1979  tickRange = std::abs(0.5 / tp.Dir[1]) / tcc.unitsPerTick;
1980  // don't let it get too large
1981  if (tickRange > 40) tickRange = 40;
1982  }
1983  float loTpTick = projTick - tickRange;
1984  float hiTpTick = projTick + tickRange;
1985  for (unsigned int iht = slc.wireHitRange[pln][wire].first;
1986  iht <= slc.wireHitRange[pln][wire].second;
1987  ++iht) {
1988  unsigned int ahi = slc.slHits[iht].allHitsIndex;
1989  auto& hit = (*evt.allHits)[ahi];
1990  if (projTick < hit.PeakTime()) {
1991  float loHitTick = hit.PeakTime() - 3 * hit.RMS();
1992  if (hiTpTick > loHitTick) return true;
1993  }
1994  else {
1995  float hiHitTick = hit.PeakTime() + 3 * hit.RMS();
1996  if (loTpTick < hiHitTick) return true;
1997  }
1998  } // iht
1999  return false;
2000  } // SignalAtTpInSlc
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
process_name hit
Definition: cheaterreco.fcl:51
T abs(T value)
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:630
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
TCEvent evt
Definition: DataStructs.cxx:8
bool tca::SignalBetween ( const TCSlice &  slc,
const TrajPoint &  tp1,
const TrajPoint &  tp2,
const float &  MinWireSignalFraction 
)

Definition at line 1807 of file Utils.cxx.

1811  {
1812  // Returns true if there is a signal on > MinWireSignalFraction of the wires between tp1 and tp2.
1813  if (MinWireSignalFraction == 0) return true;
1814 
1815  if (tp1.Pos[0] < -0.4 || tp2.Pos[0] < -0.4) return false;
1816  int fromWire = std::nearbyint(tp1.Pos[0]);
1817  int toWire = std::nearbyint(tp2.Pos[0]);
1818 
1819  if (fromWire == toWire) {
1820  TrajPoint tp = tp1;
1821  // check for a signal midway between
1822  tp.Pos[1] = 0.5 * (tp1.Pos[1] + tp2.Pos[1]);
1823  return SignalAtTp(tp);
1824  }
1825  // define a trajectory point located at tp1 that has a direction towards tp2
1826  TrajPoint tp;
1827  if (!MakeBareTrajPoint(slc, tp1, tp2, tp)) return true;
1828  return SignalBetween(slc, tp, toWire, MinWireSignalFraction);
1829  } // SignalBetween
bool SignalAtTp(TrajPoint &tp)
Definition: Utils.cxx:2004
bool MakeBareTrajPoint(const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:4110
bool SignalBetween(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2, const float &MinWireSignalFraction)
Definition: Utils.cxx:1807
bool tca::SignalBetween ( const TCSlice &  slc,
TrajPoint  tp,
float  toPos0,
const float &  MinWireSignalFraction 
)

Definition at line 1833 of file Utils.cxx.

1834  {
1835  // Returns true if there is a signal on > MinWireSignalFraction of the wires between tp and toPos0.
1836  return ChgFracBetween(slc, tp, toPos0) >= MinWireSignalFraction;
1837  } // SignalBetween
float ChgFracBetween(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, Point3_t pos1, Point3_t pos2)
Definition: PFPUtils.cxx:3197
bool tca::SortSection ( PFPStruct &  pfp,
unsigned short  sfIndex 
)

Definition at line 2028 of file PFPUtils.cxx.

2029  {
2030  // sorts the TP3Ds by the distance from the start of a fit section
2031 
2032  if (sfIndex > pfp.SectionFits.size() - 1) return false;
2033  auto& sf = pfp.SectionFits[sfIndex];
2034  if (sf.Pos[0] == 0.0 && sf.Pos[1] == 0.0 && sf.Pos[2] == 0.0) return false;
2035 
2036  // a temp vector of points in this section
2037  std::vector<TP3D> temp;
2038  // and the index into TP3Ds
2039  std::vector<unsigned short> indx;
2040  // See if the along variable is monotonically increasing
2041  float prevAlong = 0;
2042  bool first = true;
2043  bool needsSort = false;
2044  for (std::size_t ii = 0; ii < pfp.TP3Ds.size(); ++ii) {
2045  auto& tp3d = pfp.TP3Ds[ii];
2046  if (tp3d.SFIndex != sfIndex) continue;
2047  if (first) {
2048  first = false;
2049  prevAlong = tp3d.along;
2050  }
2051  else {
2052  if (tp3d.along < prevAlong) needsSort = true;
2053  prevAlong = tp3d.along;
2054  }
2055  temp.push_back(tp3d);
2056  indx.push_back(ii);
2057  } // tp3d
2058  if (temp.empty()) return false;
2059  // no sort needed?
2060  if (temp.size() == 1) return true;
2061  if (!needsSort) {
2062  sf.NeedsUpdate = false;
2063  return true;
2064  }
2065  // see if the points are not-contiguous
2066  bool contiguous = true;
2067  for (std::size_t ipt = 1; ipt < indx.size(); ++ipt) {
2068  if (indx[ipt] != indx[ipt - 1] + 1) contiguous = false;
2069  } // ipt
2070  if (!contiguous) { return false; }
2071 
2072  std::vector<SortEntry> sortVec(temp.size());
2073  for (std::size_t ii = 0; ii < temp.size(); ++ii) {
2074  sortVec[ii].index = ii;
2075  sortVec[ii].val = temp[ii].along;
2076  } // ipt
2077  std::sort(sortVec.begin(), sortVec.end(), valsIncreasing);
2078  for (std::size_t ii = 0; ii < temp.size(); ++ii) {
2079  // overwrite the tp3d
2080  auto& tp3d = pfp.TP3Ds[indx[ii]];
2081  tp3d = temp[sortVec[ii].index];
2082  } // ii
2083  sf.NeedsUpdate = false;
2084  return true;
2085  } // SortSection
bool valsIncreasing(const SortEntry &c1, const SortEntry &c2)
Definition: Utils.cxx:39
bool tca::SplitTraj ( detinfo::DetectorPropertiesData const &  detProp,
TCSlice &  slc,
unsigned short  itj,
float  XPos,
bool  makeVx2,
bool  prt 
)

Definition at line 2272 of file Utils.cxx.

2278  {
2279  // Splits the trajectory at an X position and optionally creates a 2D vertex
2280  // at the split point
2281  if (itj > slc.tjs.size() - 1) return false;
2282 
2283  auto& tj = slc.tjs[itj];
2284  geo::PlaneID planeID = DecodeCTP(tj.CTP);
2285  float atPos1 = detProp.ConvertXToTicks(XPos, planeID) * tcc.unitsPerTick;
2286  unsigned short atPt = USHRT_MAX;
2287  for (unsigned short ipt = tj.EndPt[0] + 1; ipt <= tj.EndPt[1]; ++ipt) {
2288  if (tj.Pts[ipt].Pos[1] > tj.Pts[ipt - 1].Pos[1]) {
2289  // positive slope
2290  if (tj.Pts[ipt - 1].Pos[1] < atPos1 && tj.Pts[ipt].Pos[1] >= atPos1) {
2291  atPt = ipt;
2292  break;
2293  }
2294  }
2295  else {
2296  // negative slope
2297  if (tj.Pts[ipt - 1].Pos[1] >= atPos1 && tj.Pts[ipt].Pos[1] < atPos1) {
2298  atPt = ipt;
2299  break;
2300  }
2301  } // negative slope
2302  } // ipt
2303  if (atPt == USHRT_MAX) return false;
2304  unsigned short vx2Index = USHRT_MAX;
2305  if (makeVx2) {
2306  VtxStore newVx2;
2307  newVx2.CTP = tj.CTP;
2308  newVx2.Pos[0] = 0.5 * (tj.Pts[atPt - 1].Pos[0] + tj.Pts[atPt].Pos[0]);
2309  newVx2.Pos[1] = 0.5 * (tj.Pts[atPt - 1].Pos[1] + tj.Pts[atPt].Pos[1]);
2310  newVx2.Topo = 10;
2311  newVx2.NTraj = 2;
2312  if (StoreVertex(slc, newVx2)) vx2Index = slc.vtxs.size() - 1;
2313  } // makeVx2
2314  return SplitTraj(slc, itj, atPt, vx2Index, prt);
2315  } // SplitTraj
TCConfig tcc
Definition: DataStructs.cxx:9
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:1918
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
bool SplitTraj(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, unsigned short itj, float XPos, bool makeVx2, bool prt)
Definition: Utils.cxx:2272
geo::PlaneID DecodeCTP(CTP_t CTP)
auto const detProp
bool tca::SplitTraj ( TCSlice &  slc,
unsigned short  itj,
unsigned short  pos,
unsigned short  ivx,
bool  prt 
)

Definition at line 2319 of file Utils.cxx.

2320  {
2321  // Splits the trajectory itj in the slc.tjs vector into two trajectories at position pos. Splits
2322  // the trajectory and associates the ends to the supplied vertex.
2323  // Here is an example where itj has 9 points and we will split at pos = 4
2324  // itj (0 1 2 3 4 5 6 7 8) -> new traj (0 1 2 3) + new traj (4 5 6 7 8)
2325 
2326  if (itj > slc.tjs.size() - 1) return false;
2327  if (pos < slc.tjs[itj].EndPt[0] + 1 || pos > slc.tjs[itj].EndPt[1] - 1) return false;
2328  if (ivx != USHRT_MAX && ivx > slc.vtxs.size() - 1) return false;
2329 
2330  Trajectory& tj = slc.tjs[itj];
2331 
2332  // Reset the PDG Code if we are splitting a tagged muon
2333  bool splittingMuon = (tj.PDGCode == 13);
2334  if (splittingMuon) tj.PDGCode = 0;
2335 
2336  if (prt) {
2337  mf::LogVerbatim myprt("TC");
2338  myprt << "SplitTraj: Split T" << tj.ID << " at point " << PrintPos(slc, tj.Pts[pos]);
2339  if (ivx < slc.vtxs.size()) myprt << " with Vtx 2V" << slc.vtxs[ivx].ID;
2340  }
2341 
2342  // ensure that there will be at least 3 TPs on each trajectory
2343  unsigned short ntp = 0;
2344  for (unsigned short ipt = 0; ipt <= pos; ++ipt) {
2345  if (tj.Pts[ipt].Chg > 0) ++ntp;
2346  if (ntp > 2) break;
2347  } // ipt
2348  if (ntp < 3) {
2349  if (prt) mf::LogVerbatim("TC") << " Split point to small at begin " << ntp << " pos " << pos;
2350  return false;
2351  }
2352  ntp = 0;
2353  for (unsigned short ipt = pos + 1; ipt <= tj.EndPt[1]; ++ipt) {
2354  if (tj.Pts[ipt].Chg > 0) ++ntp;
2355  if (ntp > 2) break;
2356  } // ipt
2357  if (ntp < 3) {
2358  if (prt)
2359  mf::LogVerbatim("TC") << " Split point too small at end " << ntp << " pos " << pos
2360  << " EndPt " << tj.EndPt[1];
2361  return false;
2362  }
2363 
2364  // make a copy that will become the Tj after the split point
2365  Trajectory newTj = tj;
2366  newTj.ID = slc.tjs.size() + 1;
2367  ++evt.globalT_UID;
2368  newTj.UID = evt.globalT_UID;
2369  // make another copy in case something goes wrong
2370  Trajectory oldTj = tj;
2371 
2372  // Leave the first section of tj in place. Re-assign the hits
2373  // to the new trajectory
2374  unsigned int iht;
2375  for (unsigned short ipt = pos + 1; ipt <= tj.EndPt[1]; ++ipt) {
2376  tj.Pts[ipt].Chg = 0;
2377  for (unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
2378  if (!tj.Pts[ipt].UseHit[ii]) continue;
2379  iht = tj.Pts[ipt].Hits[ii];
2380  // This shouldn't happen but check anyway
2381  if (slc.slHits[iht].InTraj != tj.ID) continue;
2382  slc.slHits[iht].InTraj = newTj.ID;
2383  tj.Pts[ipt].UseHit[ii] = false;
2384  } // ii
2385  } // ipt
2386  SetEndPoints(tj);
2387  // Update MCSMom and charge properties
2388  tj.MCSMom = MCSMom(slc, tj);
2389  UpdateTjChgProperties("ST", slc, tj, prt);
2390  if (splittingMuon) SetPDGCode(slc, tj);
2391 
2392  // Append 3 points from the end of tj onto the
2393  // beginning of newTj so that hits can be swapped between
2394  // them later
2395  unsigned short eraseSize = pos - 2;
2396  if (eraseSize > newTj.Pts.size() - 1) {
2397  tj = oldTj;
2398  return false;
2399  }
2400 
2401  if (ivx < slc.vtxs.size()) tj.VtxID[1] = slc.vtxs[ivx].ID;
2402  tj.AlgMod[kSplit] = true;
2403  if (prt) {
2404  mf::LogVerbatim("TC") << " Splitting T" << tj.ID << " new EndPts " << tj.EndPt[0] << " to "
2405  << tj.EndPt[1];
2406  }
2407 
2408  // erase the TPs at the beginning of the new trajectory
2409  newTj.Pts.erase(newTj.Pts.begin(), newTj.Pts.begin() + eraseSize);
2410  // unset the first 3 TP hits
2411  for (unsigned short ipt = 0; ipt < 3; ++ipt) {
2412  for (unsigned short ii = 0; ii < newTj.Pts[ipt].Hits.size(); ++ii)
2413  newTj.Pts[ipt].UseHit[ii] = false;
2414  newTj.Pts[ipt].Chg = 0;
2415  } // ipt
2416  SetEndPoints(newTj);
2417  newTj.MCSMom = MCSMom(slc, newTj);
2418  UpdateTjChgProperties("ST", slc, newTj, prt);
2419  if (splittingMuon) SetPDGCode(slc, newTj);
2420  if (ivx < slc.vtxs.size()) newTj.VtxID[0] = slc.vtxs[ivx].ID;
2421  newTj.AlgMod[kSplit] = true;
2422  newTj.ParentID = 0;
2423  slc.tjs.push_back(newTj);
2424 
2425  if (prt) {
2426  mf::LogVerbatim("TC") << " newTj T" << newTj.ID << " EndPts " << newTj.EndPt[0] << " to "
2427  << newTj.EndPt[1];
2428  }
2429  return true;
2430 
2431  } // SplitTraj
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3468
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3413
then if[["$THISISATEST"==1]]
Definition: neoSmazza.sh:95
void SetPDGCode(TCSlice &slc, unsigned short itj)
Definition: Utils.cxx:4350
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3673
TCEvent evt
Definition: DataStructs.cxx:8
void tca::SplitTrajCrossingVertices ( TCSlice &  slc,
CTP_t  inCTP 
)

Definition at line 923 of file TCVertex.cxx.

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

Definition at line 793 of file PFPUtils.cxx.

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

Definition at line 3825 of file TCShower.cxx.

3826  {
3827  // Returns a histogram vector of the charge in bins of 1 WSE unit at the start of the shower
3828 
3829  ShowerStruct& ss = slc.cots[cotID - 1];
3830  constexpr unsigned short nbins = 20;
3831  std::vector<float> schg(nbins);
3832  if (ss.ID == 0) return schg;
3833  if (ss.TjIDs.empty()) return schg;
3834  TrajPoint& stp1 = slc.tjs[ss.ShowerTjID - 1].Pts[1];
3835 
3836  // move the min along point back by 2 WSE so that most of the charge in the hits in the
3837  // first point is included in the histogram
3838  float minAlong = ss.ShPts[0].RotPos[0] - 2;
3839 
3840  float maxTrans = 4;
3841  // Tighten up on the maximum allowed transverse position if there is a parent
3842  if (ss.ParentID > 0) maxTrans = 1;
3843  float cs = cos(-ss.Angle);
3844  float sn = sin(-ss.Angle);
3845  std::array<float, 2> chgPos;
3846  float along, arg;
3847 
3848  for (auto& sspt : ss.ShPts) {
3849  unsigned short indx = (unsigned short)((sspt.RotPos[0] - minAlong));
3850  if (indx > nbins - 1) break;
3851  // Count the charge if it is within a few WSE transverse from the shower axis
3852  if (std::abs(sspt.RotPos[1]) > maxTrans) continue;
3853  unsigned int iht = sspt.HitIndex;
3854  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
3855  float peakTime = hit.PeakTime();
3856  float amp = hit.PeakAmplitude();
3857  float rms = hit.RMS();
3858  chgPos[0] = hit.WireID().Wire - stp1.Pos[0];
3859  for (float time = peakTime - 2.5 * rms; time < peakTime + 2.5 * rms; ++time) {
3860  chgPos[1] = time * tcc.unitsPerTick - stp1.Pos[1];
3861  along = cs * chgPos[0] - sn * chgPos[1];
3862  if (along < minAlong) continue;
3863  indx = (unsigned short)(along - minAlong);
3864  if (indx > nbins - 1) continue;
3865  arg = (time - peakTime) / rms;
3866  schg[indx] += amp * exp(-0.5 * arg * arg);
3867  } // time
3868  } // sspt
3869 
3870  return schg;
3871  } // StartChgVec
TCConfig tcc
Definition: DataStructs.cxx:9
process_name hit
Definition: cheaterreco.fcl:51
T abs(T value)
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
TCEvent evt
Definition: DataStructs.cxx:8
bool tca::StartTraj ( TCSlice &  slc,
Trajectory &  tj,
unsigned int  fromhit,
unsigned int  tohit,
unsigned short  pass 
)

Definition at line 5001 of file Utils.cxx.

5006  {
5007  // Start a trajectory located at fromHit with direction pointing to toHit
5008 
5009  auto& fromHit = (*evt.allHits)[slc.slHits[fromhit].allHitsIndex];
5010  auto& toHit = (*evt.allHits)[slc.slHits[tohit].allHitsIndex];
5011  float fromWire = fromHit.WireID().Wire;
5012  float fromTick = fromHit.PeakTime();
5013  float toWire = toHit.WireID().Wire;
5014  float toTick = toHit.PeakTime();
5015  CTP_t tCTP = EncodeCTP(fromHit.WireID());
5016  bool success = StartTraj(slc, tj, fromWire, fromTick, toWire, toTick, tCTP, pass);
5017  if (!success) return false;
5018  // turn on debugging using the WorkID?
5019  if (tcc.modes[kDebug] && !tcc.dbgStp && !tcc.dbgDump && tcc.dbgSlc && tj.ID == debug.WorkID)
5020  tcc.dbgStp = true;
5021  if (tcc.dbgStp) {
5022  auto& tp = tj.Pts[0];
5023  mf::LogVerbatim("TC") << "StartTraj T" << tj.ID << " from " << (int)fromWire << ":"
5024  << (int)fromTick << " -> " << (int)toWire << ":" << (int)toTick
5025  << " StepDir " << tj.StepDir << " dir " << tp.Dir[0] << " " << tp.Dir[1]
5026  << " ang " << tp.Ang << " AngleCode " << tp.AngleCode << " angErr "
5027  << tp.AngErr << " ExpectedHitsRMS " << ExpectedHitsRMS(slc, tp);
5028  } // tcc.dbgStp
5029  return true;
5030  } // StartTraj
TCConfig tcc
Definition: DataStructs.cxx:9
float ExpectedHitsRMS(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:1947
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:590
bool StartTraj(TCSlice &slc, Trajectory &tj, unsigned int fromhit, unsigned int tohit, unsigned short pass)
Definition: Utils.cxx:5001
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
tuple dir
Definition: dropbox.py:28
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:607
unsigned int CTP_t
Definition: DataStructs.h:47
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:52
TCEvent evt
Definition: DataStructs.cxx:8
master switch for turning on debug mode
Definition: DataStructs.h:533
BEGIN_PROLOG don t mess with this pandoraTrackGausCryoW true
bool tca::StartTraj ( TCSlice &  slc,
Trajectory &  tj,
float  fromWire,
float  fromTick,
float  toWire,
float  toTick,
CTP_t &  tCTP,
unsigned short  pass 
)

Definition at line 5034 of file Utils.cxx.

5042  {
5043  // Start a simple (seed) trajectory going from (fromWire, toTick) to (toWire, toTick).
5044 
5045  // decrement the work ID so we can use it for debugging problems
5046  --evt.WorkID;
5047  if (evt.WorkID == INT_MIN) evt.WorkID = -1;
5048  tj.ID = evt.WorkID;
5049  tj.Pass = pass;
5050  // Assume we are stepping in the positive WSE units direction
5051  short stepdir = 1;
5052  int fWire = std::nearbyint(fromWire);
5053  int tWire = std::nearbyint(toWire);
5054  if (tWire < fWire) { stepdir = -1; }
5055  else if (tWire == fWire) {
5056  // on the same wire
5057  if (toTick < fromTick) stepdir = -1;
5058  }
5059  tj.StepDir = stepdir;
5060  tj.CTP = tCTP;
5061  tj.ParentID = -1;
5062  tj.Strategy.reset();
5063  tj.Strategy[kNormal] = true;
5064 
5065  // create a trajectory point
5066  TrajPoint tp;
5067  if (!MakeBareTrajPoint(slc, fromWire, fromTick, toWire, toTick, tCTP, tp)) return false;
5068  SetAngleCode(tp);
5069  tp.AngErr = 0.1;
5070  tj.Pts.push_back(tp);
5071  // turn on debugging using the WorkID?
5072  if (tcc.modes[kDebug] && !tcc.dbgStp && !tcc.dbgDump && tcc.dbgSlc && tj.ID == debug.WorkID)
5073  tcc.dbgStp = true;
5074  if (tcc.dbgStp) {
5075  auto& tp = tj.Pts[0];
5076  mf::LogVerbatim("TC") << "StartTraj T" << tj.ID << " from " << (int)fromWire << ":"
5077  << (int)fromTick << " -> " << (int)toWire << ":" << (int)toTick
5078  << " StepDir " << tj.StepDir << " dir " << tp.Dir[0] << " " << tp.Dir[1]
5079  << " ang " << tp.Ang << " AngleCode " << tp.AngleCode << " angErr "
5080  << tp.AngErr << " ExpectedHitsRMS " << ExpectedHitsRMS(slc, tp);
5081  } // tcc.dbgStp
5082  return true;
5083 
5084  } // StartTraj
TCConfig tcc
Definition: DataStructs.cxx:9
float ExpectedHitsRMS(TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:1947
void SetAngleCode(TrajPoint &tp)
Definition: Utils.cxx:773
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:590
bool MakeBareTrajPoint(const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:4110
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
tuple dir
Definition: dropbox.py:28
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:607
TCEvent evt
Definition: DataStructs.cxx:8
master switch for turning on debug mode
Definition: DataStructs.h:533
BEGIN_PROLOG don t mess with this pandoraTrackGausCryoW true
void tca::StepAway ( TCSlice &  slc,
Trajectory &  tj 
)

Definition at line 30 of file StepUtils.cxx.

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] && npwc == tjfs[tjfs.size() - 1].nextForecastUpdate) {
73  Forecast(slc, tj);
74  SetStrategy(slc, tj);
75  SetPDGCode(slc, tj);
76  }
77  // make a copy of the previous TP
78  lastPt = tj.Pts.size() - 1;
79  tp = tj.Pts[lastPt];
80  ++tp.Step;
81  double stepSize = tcc.VLAStepSize;
82  if(tp.AngleCode < 2) stepSize = std::abs(1/ltp.Dir[0]);
83  // move the local TP position by one step in the right direction
84  for(unsigned short iwt = 0; iwt < 2; ++iwt) ltp.Pos[iwt] += ltp.Dir[iwt] * stepSize;
85  // copy this position into tp
86  tp.Pos = ltp.Pos;
87  tp.Dir = ltp.Dir;
88  if(tcc.dbgStp) {
89  mf::LogVerbatim myprt("TC");
90  myprt<<"StepAway "<<step<<" Pos "<<tp.Pos[0]<<" "<<tp.Pos[1]<<" Dir "<<tp.Dir[0]<<" "<<tp.Dir[1]<<" stepSize "<<stepSize<<" AngCode "<<tp.AngleCode<<" Strategy";
91  for(unsigned short ibt = 0; ibt < StrategyBitNames.size(); ++ibt) {
92  if(tj.Strategy[ibt]) myprt<<" "<<StrategyBitNames[ibt];
93  } // ib
94  } // tcc.dbgStp
95  // hit the boundary of the TPC?
96  if(tp.Pos[0] < 0 || tp.Pos[0] > tcc.maxPos0[plane] ||
97  tp.Pos[1] < 0 || tp.Pos[1] > tcc.maxPos1[plane]) break;
98  // remove the old hits and other stuff
99  tp.Hits.clear();
100  tp.UseHit.reset();
101  tp.FitChi = 0; tp.Chg = 0;
102  tp.Environment.reset();
103  unsigned int wire = std::nearbyint(tp.Pos[0]);
104  if(!evt.goodWire[plane][wire]) tp.Environment[kEnvNotGoodWire] = true;
105  // append to the trajectory
106  tj.Pts.push_back(tp);
107  // update the index of the last TP
108  lastPt = tj.Pts.size() - 1;
109  // look for hits
110  bool sigOK = false;
111  AddHits(slc, tj, lastPt, sigOK);
112  // Check the stop flag
113  if(tj.EndFlag[1][kAtTj]) break;
114  // If successfull, AddHits has defined UseHit for this TP,
115  // set the trajectory endpoints, and define HitPos.
116  if(tj.Pts[lastPt].Hits.empty() && !tj.Pts[lastPt].Environment[kEnvNearSrcHit]) {
117  // Require three points with charge on adjacent wires for small angle
118  // stepping.
119  if(tj.Pts[lastPt].AngleCode == 0 && lastPt == 2) return;
120  // No close hits added.
121  ++nMissedSteps;
122  // First check for no signal in the vicinity. AddHits checks the hit collection for
123  // the current slice. This version of SignalAtTp checks the allHits collection.
124  sigOK = SignalAtTp(ltp);
125  if(lastPt > 0) {
126  // break if this is a reverse propagate activity and there was no signal (not on a dead wire)
127  if(!sigOK && tj.AlgMod[kRvPrp]) break;
128  // Ensure that there is a signal here after missing a number of steps on a LA trajectory
129  if(tj.Pts[lastPt].AngleCode > 0 && nMissedSteps > 4 && !sigOK) break;
130  // the last point with hits (used or not) is the previous point
131  unsigned short lastPtWithHits = lastPt - 1;
132  float tps = TrajPointSeparation(tj.Pts[lastPtWithHits], ltp);
133  float dwc = DeadWireCount(slc, ltp, tj.Pts[lastPtWithHits]);
134  float nMissedWires = tps * std::abs(ltp.Dir[0]) - dwc;
135  float maxWireSkip = tcc.maxWireSkipNoSignal;
136  if(sigOK) maxWireSkip = tcc.maxWireSkipWithSignal;
137  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" StepAway: no hits found at ltp "<<PrintPos(slc, ltp)
138  <<" nMissedWires "<<std::fixed<<std::setprecision(1)<<nMissedWires
139  <<" dead wire count "<<dwc<<" maxWireSkip "<<maxWireSkip<<" tj.PDGCode "<<tj.PDGCode;
140  if(nMissedWires > maxWireSkip) {
141  // We passed a number of wires without adding hits and are ready to quit.
142  // First see if there is one good unused hit on the end TP and if so use it
143  // lastPtWithHits + 1 == lastPt && tj.Pts[lastPtWithHits].Chg == 0 && tj.Pts[lastPtWithHits].Hits.size() == 1
144  if(tj.EndPt[1] < tj.Pts.size() - 1 && tj.Pts[tj.EndPt[1]+1].Hits.size() == 1) {
145  unsigned short lastLonelyPoint = tj.EndPt[1] + 1;
146  unsigned int iht = tj.Pts[lastLonelyPoint].Hits[0];
147  if(slc.slHits[iht].InTraj == 0 && tj.Pts[lastLonelyPoint].Delta < 3 * tj.Pts[lastLonelyPoint].DeltaRMS) {
148  slc.slHits[iht].InTraj = tj.ID;
149  tj.Pts[lastLonelyPoint].UseHit[0] = true;
150  DefineHitPos(slc, tj.Pts[lastLonelyPoint]);
151  SetEndPoints(tj);
152  if(tcc.dbgStp) {
153  mf::LogVerbatim("TC")<<" Added a Last Lonely Hit before breaking ";
154  PrintTP("LLH", slc, lastPt, tj.StepDir, tj.Pass, tj.Pts[lastLonelyPoint]);
155  }
156  }
157  }
158  break;
159  }
160  } // lastPt > 0
161  // no sense keeping this TP on tj if no hits were added
162  tj.Pts.pop_back();
163  continue;
164  } // tj.Pts[lastPt].Hits.empty()
165  // ensure that we actually moved
166  if(lastPt > 0 && PosSep2(tj.Pts[lastPt].Pos, tj.Pts[lastPt-1].Pos) < 0.1) return;
167  // Found hits at this location so reset the missed steps counter
168  nMissedSteps = 0;
169  // Update the last point fit, etc using the just added hit(s)
170  UpdateTraj(slc, tj);
171  // a failure occurred
172  if(tj.NeedsUpdate) return;
173  if(tj.Pts[lastPt].Chg == 0) {
174  // There are points on the trajectory by none used in the last step. See
175  // how long this has been going on
176  float tps = TrajPointSeparation(tj.Pts[tj.EndPt[1]], ltp);
177  float dwc = DeadWireCount(slc, ltp, tj.Pts[tj.EndPt[1]]);
178  float nMissedWires = tps * std::abs(ltp.Dir[0]) - dwc;
179  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Hits exist on the trajectory but are not used. Missed wires "<<std::nearbyint(nMissedWires)<<" dead wire count "<<(int)dwc;
180  // break if this is a reverse propagate activity with no dead wires
181  if(tj.AlgMod[kRvPrp] && dwc == 0) break;
182  if(nMissedWires > tcc.maxWireSkipWithSignal) break;
183  // try this out
184  if(!MaskedHitsOK(slc, tj)) {
185  return;
186  }
187  // check for a series of bad fits and stop stepping
188  if(tcc.useAlg[kStopBadFits] && nMissedWires > 4 && StopIfBadFits(slc, tj)) break;
189  // Keep stepping
190  if(tcc.dbgStp) {
191  if(tj.AlgMod[kRvPrp]) {
192  PrintTrajectory("RP", slc, tj, lastPt);
193  } else {
194  PrintTrajectory("SC", slc, tj, lastPt);
195  }
196  }
197  continue;
198  } // tp.Hits.empty()
199  if(tj.Pts.size() == 3) {
200  // ensure that the last hit added is in the same direction as the first two.
201  // This is a simple way of doing it
202  bool badTj = (PosSep2(tj.Pts[0].HitPos, tj.Pts[2].HitPos) < PosSep2(tj.Pts[0].HitPos, tj.Pts[1].HitPos));
203  // ensure that this didn't start as a small angle trajectory and immediately turn
204  // into a large angle one
205  if(!badTj && tj.Pts[lastPt].AngleCode > tcc.maxAngleCode[tj.Pass]) badTj = true;
206  // check for a large change in angle
207  if(!badTj) {
208  float dang = DeltaAngle(tj.Pts[0].Ang, tj.Pts[2].Ang);
209  if(dang > 0.5) badTj = false;
210  }
211  //check for a wacky delta
212  if(!badTj && tj.Pts[2].Delta > 2) badTj = true;
213  if(badTj) {
214  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Bad Tj found on the third point. Quit stepping.";
215  tj.IsGood = false;
216  return;
217  }
218  } // tj.Pts.size() == 3
219  // Update the local TP with the updated position and direction
220  ltp.Pos = tj.Pts[lastPt].Pos;
221  ltp.Dir = tj.Pts[lastPt].Dir;
222  if(tj.MaskedLastTP) {
223  // see if TPs have been masked off many times and if the
224  // environment is clean. If so, return and try with next pass
225  // cuts
226  if(!MaskedHitsOK(slc, tj)) {
227  if(tcc.dbgStp) {
228  if(tj.AlgMod[kRvPrp]) {
229  PrintTrajectory("RP", slc, tj, lastPt);
230  } else {
231  PrintTrajectory("SC", slc, tj, lastPt);
232  }
233  }
234  return;
235  }
236  if(tcc.dbgStp) {
237  if(tj.AlgMod[kRvPrp]) {
238  PrintTrajectory("RP", slc, tj, lastPt);
239  } else {
240  PrintTrajectory("SC", slc, tj, lastPt);
241  }
242  }
243  continue;
244  }
245  // We have added a TP with hits
246  // check for a kink. Stop crawling if one is found
247  GottaKink(slc, tj, true);
248  if(tj.EndFlag[1][kAtKink]) {
249  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" stop at kink";
250  break;
251  }
252  // See if the Chisq/DOF exceeds the maximum.
253  // UpdateTraj should have reduced the number of points fit
254  // as much as possible for this pass, so this trajectory is in trouble.
255  if(tj.Pts[lastPt].FitChi > tcc.maxChi && useMaxChiCut) {
256  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" bad FitChi "<<tj.Pts[lastPt].FitChi<<" cut "<<tcc.maxChi;
257  // remove the last point before quitting
258  UnsetUsedHits(slc, tj.Pts[lastPt]);
259  SetEndPoints(tj);
260  tj.IsGood = (NumPtsWithCharge(slc, tj, true) > tcc.minPtsFit[tj.Pass]);
261  break;
262  }
263  if(tcc.dbgStp) {
264  if(tj.AlgMod[kRvPrp]) {
265  PrintTrajectory("RP", slc, tj, lastPt);
266  } else {
267  PrintTrajectory("SC", slc, tj, lastPt);
268  }
269  } // tcc.dbgStp
270  } // step
271 
272  SetPDGCode(slc, tj);
273 
274  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"End StepAway with tj size "<<tj.Pts.size();
275 
276  } // StepAway
void Forecast(TCSlice &slc, const Trajectory &tj)
Definition: StepUtils.cxx:436
bool MaskedHitsOK(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2424
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3413
void UpdateTraj(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:669
std::vector< float > maxPos0
Definition: DataStructs.h:572
std::vector< unsigned short > minPtsFit
Reconstruct in several passes.
Definition: DataStructs.h:565
bool SignalAtTp(TrajPoint &tp)
Definition: Utils.cxx:2004
void SetPDGCode(TCSlice &slc, unsigned short itj)
Definition: Utils.cxx:4350
void AddHits(TCSlice &slc, Trajectory &tj, unsigned short ipt, bool &sigOK)
Definition: StepUtils.cxx:1039
TCConfig tcc
Definition: DataStructs.cxx:9
void PrintTrajectory(std::string someText, const TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:6195
void PrintTP(std::string someText, const TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, const TrajPoint &tp)
Definition: Utils.cxx:6296
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1075
bool StopShort(TCSlice &slc, Trajectory &tj, bool prt)
Definition: StepUtils.cxx:279
void SetStrategy(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:340
float maxWireSkipWithSignal
max number of wires to skip with a signal on them
Definition: DataStructs.h:582
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
float TrajPointSeparation(const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2680
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:2540
bool doForecast
See TCMode_t above.
Definition: DataStructs.h:608
std::vector< unsigned short > maxAngleCode
max allowed angle code for each pass
Definition: DataStructs.h:567
T abs(T value)
const std::vector< std::string > StrategyBitNames
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
std::vector< float > maxPos1
Definition: DataStructs.h:573
use the slowing-down strategy
Definition: DataStructs.h:503
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2141
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1672
TP is near a hit in the srcHit collection but no allHit hit exists (DUNE disambiguation error) ...
Definition: DataStructs.h:525
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:630
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2572
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
bool StopIfBadFits(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2529
float maxWireSkipNoSignal
max number of wires to skip w/o a signal on them
Definition: DataStructs.h:581
std::vector< TjForecast > tjfs
Definition: DataStructs.cxx:10
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
float VLAStepSize
Definition: DataStructs.h:584
geo::PlaneID DecodeCTP(CTP_t CTP)
bool GottaKink(TCSlice &slc, Trajectory &tj, bool doTrim)
Definition: StepUtils.cxx:2556
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2116
TCEvent evt
Definition: DataStructs.cxx:8
void tca::StitchPFPs ( )

Definition at line 42 of file PFPUtils.cxx.

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

Definition at line 2529 of file StepUtils.cxx.

2530  {
2531  // Returns true if there are a number of Tps that were not used in the trajectory because the fit was poor and the
2532  // charge pull is not really high. This
2533 
2534  // don't consider muons
2535  if(tj.PDGCode == 13) return false;
2536  // or long straight Tjs
2537  if(tj.Pts.size() > 40 && tj.MCSMom > 200) return false;
2538 
2539  unsigned short nBadFit = 0;
2540  unsigned short nHiChg = 0;
2541  unsigned short cnt = 0;
2542  for(unsigned short ipt = tj.Pts.size() - 1; ipt > tj.EndPt[1]; --ipt ) {
2543  if(tj.Pts[ipt].FitChi > 2) ++nBadFit;
2544  if(tj.Pts[ipt].ChgPull > 3) ++nHiChg;
2545  ++cnt;
2546  if(cnt == 5) break;
2547  } // ipt
2548 
2549  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"StopIfBadFits: nBadFit "<<nBadFit<<" nHiChg "<<nHiChg;
2550  if(nBadFit > 3 && nHiChg == 0) return true;
2551  return false;
2552 
2553  } // StopIfBadFits
TCConfig tcc
Definition: DataStructs.cxx:9
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
bool tca::StopShort ( TCSlice &  slc,
Trajectory &  tj,
bool  prt 
)

Definition at line 279 of file StepUtils.cxx.

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

Definition at line 3004 of file PFPUtils.cxx.

3005  {
3006  // stores the PFParticle in the slice
3007  bool neutrinoPFP = (pfp.PDGCode == 12 || pfp.PDGCode == 14);
3008  if (!neutrinoPFP) {
3009  if (pfp.TjIDs.empty()) return false;
3010  if (pfp.PDGCode != 1111 && pfp.TP3Ds.size() < 2) return false;
3011  }
3012 
3013  if(pfp.Flags[kSmallAngle]) {
3014  // Make the PFP -> TP assn
3015  for(auto& tp3d : pfp.TP3Ds) {
3016  if(tp3d.TPIndex != USHRT_MAX) slc.tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex].InPFP = pfp.ID;
3017  }
3018  }
3019 
3020  // ensure that the InPFP flag is set
3021  unsigned short nNotSet = 0;
3022  for (auto& tp3d : pfp.TP3Ds) {
3023  if (tp3d.Flags[kTP3DBad]) continue;
3024  auto& tp = slc.tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
3025  if (tp.InPFP != pfp.ID) ++nNotSet;
3026  } // tp3d
3027  if (nNotSet > 0) return false;
3028  // check the ID and correct it if it is wrong
3029  if (pfp.ID != (int)slc.pfps.size() + 1) pfp.ID = slc.pfps.size() + 1;
3030  ++evt.globalP_UID;
3031  pfp.UID = evt.globalP_UID;
3032 
3033  // set the 3D match flag
3034  for (auto tjid : pfp.TjIDs) {
3035  auto& tj = slc.tjs[tjid - 1];
3036  tj.AlgMod[kMat3D] = true;
3037  } // tjid
3038 
3039  slc.pfps.push_back(pfp);
3040  return true;
3041  } // StorePFP
TCEvent evt
Definition: DataStructs.cxx:8
bool tca::StoreShower ( std::string  inFcnLabel,
TCSlice &  slc,
ShowerStruct3D &  ss3 
)

Definition at line 3991 of file TCShower.cxx.

3992  {
3993  // Store a 3D shower. This function sets the 3S -> 2S assns using CotIDs and ensures
3994  // that the 2S -> 3S assns are OK.
3995 
3996  std::string fcnLabel = inFcnLabel + ".S3S";
3997  if (ss3.ID <= 0) {
3998  std::cout << fcnLabel << " Invalid ID";
3999  return false;
4000  }
4001  if (ss3.CotIDs.size() < 2) {
4002  std::cout << fcnLabel << " not enough CotIDs";
4003  return false;
4004  }
4005 
4006  // check the 2S -> 3S assns
4007  for (auto& ss : slc.cots) {
4008  if (ss.ID == 0) continue;
4009  if (ss.SS3ID == ss3.ID &&
4010  std::find(ss3.CotIDs.begin(), ss3.CotIDs.end(), ss.ID) == ss3.CotIDs.end()) {
4011  std::cout << fcnLabel << " Bad assn: 2S" << ss.ID << " -> 3S" << ss3.ID
4012  << " but it's not inCotIDs.\n";
4013  return false;
4014  }
4015  } // ss
4016 
4017  // check the 3S -> 2S assns
4018  for (auto cid : ss3.CotIDs) {
4019  if (cid <= 0 || cid > (int)slc.cots.size()) return false;
4020  auto& ss = slc.cots[cid - 1];
4021  if (ss.SS3ID > 0 && ss.SS3ID != ss3.ID) {
4022  std::cout << fcnLabel << " Bad assn: 3S" << ss3.ID << " -> 2S" << cid << " but 2S -> 3S"
4023  << ss.SS3ID << "\n";
4024  return false;
4025  }
4026  } // cid
4027 
4028  // set the 2S -> 3S assns
4029  for (auto cid : ss3.CotIDs)
4030  slc.cots[cid - 1].SS3ID = ss3.ID;
4031 
4032  ++evt.global3S_UID;
4033  ss3.UID = evt.global3S_UID;
4034 
4035  slc.showers.push_back(ss3);
4036  return true;
4037 
4038  } // StoreShower
TCEvent evt
Definition: DataStructs.cxx:8
BEGIN_PROLOG could also be cout
bool tca::StoreShower ( std::string  inFcnLabel,
TCSlice &  slc,
ShowerStruct &  ss 
)

Definition at line 4042 of file TCShower.cxx.

4043  {
4044  // Store a ShowerStruct
4045  std::string fcnLabel = inFcnLabel + ".S2S";
4046  if (ss.ID <= 0) {
4047  std::cout << fcnLabel << " Invalid ID";
4048  return false;
4049  }
4050  if (ss.TjIDs.empty()) {
4051  std::cout << fcnLabel << " Fail: No TjIDs in 2S" << ss.ID << "\n";
4052  return false;
4053  }
4054  if (ss.ParentID > 0) {
4055  if (ss.ParentID > (int)slc.tjs.size()) {
4056  std::cout << fcnLabel << " Fail: 2S" << ss.ID << " has an invalid ParentID T" << ss.ParentID
4057  << "\n";
4058  return false;
4059  }
4060  if (std::find(ss.TjIDs.begin(), ss.TjIDs.end(), ss.ParentID) != ss.TjIDs.end()) {
4061  std::cout << fcnLabel << " Fail: 2S" << ss.ID << " ParentID is not in TjIDs.\n";
4062  return false;
4063  }
4064  } // ss.ParentID > 0
4065 
4066  // check the ID
4067  if (ss.ID != (int)slc.cots.size() + 1) {
4068  std::cout << fcnLabel << " Correcting the ID 2S" << ss.ID << " -> 2S" << slc.cots.size() + 1;
4069  ss.ID = slc.cots.size() + 1;
4070  }
4071 
4072  // set the tj shower bits
4073  for (auto& tjID : ss.TjIDs) {
4074  Trajectory& tj = slc.tjs[tjID - 1];
4075  tj.SSID = ss.ID;
4076  tj.AlgMod[kShwrParent] = false;
4077  if (tj.ID == ss.ParentID) tj.AlgMod[kShwrParent] = true;
4078  } // tjID
4079 
4080  ++evt.global2S_UID;
4081  ss.UID = evt.global2S_UID;
4082 
4083  slc.cots.push_back(ss);
4084  return true;
4085 
4086  } // StoreShower
TCEvent evt
Definition: DataStructs.cxx:8
BEGIN_PROLOG could also be cout
bool tca::StoreTraj ( TCSlice &  slc,
Trajectory &  tj 
)

Definition at line 1089 of file Utils.cxx.

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

Definition at line 1918 of file TCVertex.cxx.

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

Definition at line 2782 of file Utils.cxx.

2783  {
2784  // Characterizes the trajectory as a junk tj even though it may not
2785  // have been reconstructed in FindJunkTraj. The distinguishing feature is
2786  // that it is short and has many used hits in each trajectory point.
2787 
2788  // Don't bother if it is too long
2789  if (tj.Pts.size() > 10) return;
2790  if (tj.PDGCode == 111) return;
2791  // count the number of points that have many used hits
2792  unsigned short nhm = 0;
2793  unsigned short npwc = 0;
2794  for (auto& tp : tj.Pts) {
2795  if (tp.Chg == 0) continue;
2796  ++npwc;
2797  unsigned short nused = 0;
2798  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2799  if (tp.UseHit[ii]) ++nused;
2800  } // ii
2801  if (nused > 3) ++nhm;
2802  } // tp
2803  // Set the junkTj bit if most of the hits are used in most of the tps
2804  if (nhm > 0.5 * npwc) tj.AlgMod[kJunkTj] = true;
2805  if (prt)
2806  mf::LogVerbatim("TC") << "TGT: T" << tj.ID << " npwc " << npwc << " nhm " << nhm << " junk? "
2807  << tj.AlgMod[kJunkTj];
2808  } // TagJunkTj
void tca::TagShowerLike ( std::string  inFcnLabel,
TCSlice &  slc,
const CTP_t &  inCTP 
)

Definition at line 3276 of file TCShower.cxx.

3277  {
3278  // Tag Tjs as InShower if they have MCSMom < ShowerTag[1] and there are more than
3279  // ShowerTag[6] other Tjs with a separation < ShowerTag[2].
3280 
3281  if (tcc.showerTag[0] <= 0) return;
3282  if (slc.tjs.size() > 20000) return;
3283  float typicalChgRMS = 0.5 * (tcc.chargeCuts[1] + tcc.chargeCuts[2]);
3284 
3285  bool prt = (tcc.dbgSlc && tcc.dbg2S && inCTP == debug.CTP);
3286 
3287  // clear out old tags and make a list of Tjs to consider
3288  std::vector<std::vector<int>> tjLists;
3289  std::vector<int> tjids;
3290  for (auto& tj : slc.tjs) {
3291  if (tj.CTP != inCTP) continue;
3292  if (tj.AlgMod[kKilled]) continue;
3293  if (tj.AlgMod[kHaloTj]) continue;
3294  tj.AlgMod[kShowerLike] = false;
3295  if (tj.AlgMod[kShowerTj]) continue;
3296  // ignore Tjs with Bragg peaks
3297  bool skipit = false;
3298  for (unsigned short end = 0; end < 2; ++end)
3299  if (tj.EndFlag[end][kBragg]) skipit = true;
3300  if (skipit) continue;
3301  short npwc = NumPtsWithCharge(slc, tj, false);
3302  // Don't expect any (primary) electron to be reconstructed as a single trajectory for
3303  // more than ~2 radiation lengths ~ 30 cm for uB ~ 100 wires
3304  if (npwc > 100) continue;
3305  // allow short Tjs.
3306  if (npwc > 5) {
3307  // Increase the MCSMom cut if the Tj is long and the charge RMS is high to reduce sensitivity
3308  // to the fcl configuration. A primary electron may be reconstructed as one long Tj with large
3309  // charge rms and possibly high MCSMom or as several nearby shorter Tjs with lower charge rms
3310  float momCut = tcc.showerTag[1];
3311  if (tj.ChgRMS > typicalChgRMS) momCut *= tj.ChgRMS / typicalChgRMS;
3312  if (tj.MCSMom > momCut) continue;
3313  }
3314  tjids.push_back(tj.ID);
3315  } // tj
3316 
3317  if (tjids.size() < 2) return;
3318 
3319  for (unsigned short it1 = 0; it1 < tjids.size() - 1; ++it1) {
3320  Trajectory& tj1 = slc.tjs[tjids[it1] - 1];
3321  for (unsigned short it2 = it1 + 1; it2 < tjids.size(); ++it2) {
3322  Trajectory& tj2 = slc.tjs[tjids[it2] - 1];
3323  unsigned short ipt1, ipt2;
3324  float doca = tcc.showerTag[2];
3325  // Find the separation between Tjs without considering dead wires
3326  TrajTrajDOCA(slc, tj1, tj2, ipt1, ipt2, doca, false);
3327  if (doca == tcc.showerTag[2]) continue;
3328  // make tighter cuts for user-defined short Tjs
3329  // found a close pair. See if one of these is in an existing cluster of Tjs
3330  bool inlist = false;
3331  for (unsigned short it = 0; it < tjLists.size(); ++it) {
3332  bool tj1InList =
3333  (std::find(tjLists[it].begin(), tjLists[it].end(), tj1.ID) != tjLists[it].end());
3334  bool tj2InList =
3335  (std::find(tjLists[it].begin(), tjLists[it].end(), tj2.ID) != tjLists[it].end());
3336  if (tj1InList || tj2InList) {
3337  // add the one that is not in the list
3338  if (!tj1InList) tjLists[it].push_back(tj1.ID);
3339  if (!tj2InList) tjLists[it].push_back(tj2.ID);
3340  inlist = true;
3341  break;
3342  }
3343  if (inlist) break;
3344  } // it
3345  // start a new list with this pair?
3346  if (!inlist) {
3347  std::vector<int> newlist(2);
3348  newlist[0] = tj1.ID;
3349  newlist[1] = tj2.ID;
3350  tjLists.push_back(newlist);
3351  }
3352  } // it2
3353  } // it1
3354  if (tjLists.empty()) return;
3355 
3356  // mark them all as ShowerLike Tjs
3357  for (auto& tjl : tjLists) {
3358  // ignore small clusters
3359  if (tjl.size() < 3) continue;
3360  for (auto& tjID : tjl) {
3361  auto& tj = slc.tjs[tjID - 1];
3362  tj.AlgMod[kShowerLike] = true;
3363  } // tjid
3364  } // tjl
3365 
3366  if (prt) {
3367  unsigned short nsh = 0;
3368  for (auto& tjl : tjLists) {
3369  for (auto& tjID : tjl) {
3370  auto& tj = slc.tjs[tjID - 1];
3371  if (tj.AlgMod[kShowerLike]) ++nsh;
3372  } // tjid
3373  } // tjl
3374  mf::LogVerbatim("TC") << "TagShowerLike tagged " << nsh << " Tjs vertices in CTP " << inCTP;
3375  } // prt
3376  } // TagShowerLike
TCConfig tcc
Definition: DataStructs.cxx:9
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:590
std::vector< float > showerTag
shower-like trajectory tagging + shower reconstruction
Definition: DataStructs.h:558
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
std::vector< float > chargeCuts
Definition: DataStructs.h:562
auto begin(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:573
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2116
bool TrajTrajDOCA(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2460
bool tca::TCIntersectionPoint ( unsigned int  wir1,
unsigned int  wir2,
unsigned int  pln1,
unsigned int  pln2,
float &  y,
float &  z 
)

Definition at line 669 of file PFPUtils.cxx.

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

Definition at line 3584 of file Utils.cxx.

3590  {
3591  // returns the rms scatter of points around a line formed by the firstPt and lastPt of the trajectory
3592 
3593  rms = -1;
3594  if (firstPt < tj.EndPt[0]) return;
3595  if (lastPt > tj.EndPt[1]) return;
3596 
3597  firstPt = NearestPtWithChg(slc, tj, firstPt);
3598  lastPt = NearestPtWithChg(slc, tj, lastPt);
3599  if (firstPt >= lastPt) return;
3600 
3601  TrajPoint tmp;
3602  // make a bare trajectory point to define a line between firstPt and lastPt.
3603  // Use the position of the hits at these points
3604  TrajPoint firstTP = tj.Pts[firstPt];
3605  firstTP.Pos = firstTP.HitPos;
3606  TrajPoint lastTP = tj.Pts[lastPt];
3607  lastTP.Pos = lastTP.HitPos;
3608  if (!MakeBareTrajPoint(slc, firstTP, lastTP, tmp)) return;
3609  // sum up the deviations^2
3610  double dsum = 0;
3611  cnt = 0;
3612  for (unsigned short ipt = firstPt + 1; ipt < lastPt; ++ipt) {
3613  if (tj.Pts[ipt].Chg == 0) continue;
3614  // ignore points with large error
3615  if (tj.Pts[ipt].HitPosErr2 > 4) continue;
3616  dsum += PointTrajDOCA2(slc, tj.Pts[ipt].HitPos[0], tj.Pts[ipt].HitPos[1], tmp);
3617  ++cnt;
3618  } // ipt
3619  if (cnt < 2) return;
3620  rms = sqrt(dsum / (double)cnt);
3621 
3622  } // TjDeltaRMS
bool MakeBareTrajPoint(const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:4110
float PointTrajDOCA2(const TCSlice &slc, float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2590
unsigned short NearestPtWithChg(const TCSlice &slc, const Trajectory &tj, unsigned short thePt)
Definition: Utils.cxx:3522
std::string tca::TPEnvString ( const TrajPoint &  tp)

Definition at line 6353 of file Utils.cxx.

6354  {
6355  // Print environment bits in human-readable format
6356  std::string str = "";
6357  for (unsigned short ib = 0; ib < 8; ++ib) {
6358  // There aren't any bit names for Environment_t
6359  if (!tp.Environment[ib]) continue;
6360  if (ib == kEnvNotGoodWire) str += " NoGdwire";
6361  if (ib == kEnvNearMuon) str += " NearMuon";
6362  if (ib == kEnvNearShower) str += " NearShower";
6363  if (ib == kEnvOverlap) str += " Overlap";
6364  if (ib == kEnvUnusedHits) str += " UnusedHits";
6365  if (ib == kEnvNearSrcHit) str += " NearSrcHit";
6366  if (ib == kEnvFlag) str += " Flag";
6367  } // ib
6368  return str;
6369  } // TPEnvironment
a general purpose flag bit used in 3D matching
Definition: DataStructs.h:526
TP is near a hit in the srcHit collection but no allHit hit exists (DUNE disambiguation error) ...
Definition: DataStructs.h:525
float tca::TPHitsRMSTick ( const TCSlice &  slc,
const TrajPoint &  tp,
HitStatus_t  hitRequest 
)

Definition at line 4209 of file Utils.cxx.

4210  {
4211  // Estimate the RMS of all hits associated with a trajectory point
4212  // without a lot of calculation. Note that this returns a value that is
4213  // closer to a FWHM, not the RMS
4214  if (tp.Hits.empty()) return 0;
4215  float minVal = 9999;
4216  float maxVal = 0;
4217  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
4218  bool useit = (hitRequest == kAllHits);
4219  if (hitRequest == kUsedHits && tp.UseHit[ii]) useit = true;
4220  if (hitRequest == kUnusedHits && !tp.UseHit[ii]) useit = true;
4221  if (!useit) continue;
4222  unsigned int iht = tp.Hits[ii];
4223  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
4224  float cv = hit.PeakTime();
4225  float rms = hit.RMS();
4226  float arg = cv - rms;
4227  if (arg < minVal) minVal = arg;
4228  arg = cv + rms;
4229  if (arg > maxVal) maxVal = arg;
4230  } // ii
4231  if (maxVal == 0) return 0;
4232  return (maxVal - minVal) / 2;
4233  } // TPHitsRMSTick
process_name hit
Definition: cheaterreco.fcl:51
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
TCEvent evt
Definition: DataStructs.cxx:8
float tca::TPHitsRMSTime ( const TCSlice &  slc,
const TrajPoint &  tp,
HitStatus_t  hitRequest 
)

Definition at line 4202 of file Utils.cxx.

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

Definition at line 1568 of file TCVertex.cxx.

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

Definition at line 2104 of file Utils.cxx.

2105  {
2106  float totchg = 0;
2107  for (size_t i = 0; i < tp.Hits.size(); ++i) {
2108  if (!tp.UseHit[i]) continue;
2109  totchg += (*evt.allHits)[slc.slHits[tp.Hits[i]].allHitsIndex].Integral();
2110  }
2111  return totchg;
2112  } // TpSumHitChg
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
TCEvent evt
Definition: DataStructs.cxx:8
bool tca::TrajClosestApproach ( Trajectory const &  tj,
float  x,
float  y,
unsigned short &  closePt,
float &  DOCA 
)

Definition at line 2690 of file Utils.cxx.

2691  {
2692  // find the closest approach between a trajectory tj and a point (x,y). Returns
2693  // the index of the closest trajectory point and the distance. Returns false if none
2694  // of the points on the tj are within DOCA
2695 
2696  float close2 = DOCA * DOCA;
2697  closePt = 0;
2698  bool foundClose = false;
2699 
2700  for (unsigned short ipt = tj.EndPt[0]; ipt < tj.EndPt[1] + 1; ++ipt) {
2701  if (tj.Pts[ipt].Chg == 0) continue;
2702  float dx = tj.Pts[ipt].Pos[0] - x;
2703  if (std::abs(dx) > DOCA) continue;
2704  float dy = tj.Pts[ipt].Pos[1] - y;
2705  if (std::abs(dy) > DOCA) continue;
2706  float sep2 = dx * dx + dy * dy;
2707  if (sep2 < close2) {
2708  close2 = sep2;
2709  closePt = ipt;
2710  foundClose = true;
2711  }
2712  } // ipt
2713 
2714  DOCA = sqrt(close2);
2715  return foundClose;
2716 
2717  } // TrajClosestApproach
process_name opflash particleana ie x
T abs(T value)
process_name opflash particleana ie ie y
bool tca::TrajHitsOK ( TCSlice &  slc,
const std::vector< unsigned int > &  iHitsInMultiplet,
const std::vector< unsigned int > &  jHitsInMultiplet 
)

Definition at line 1873 of file Utils.cxx.

1876  {
1877  // Hits (assume to be on adjacent wires have an acceptable signal overlap
1878 
1879  if (iHitsInMultiplet.empty() || jHitsInMultiplet.empty()) return false;
1880 
1881  float sum;
1882  float cvI = HitsPosTick(slc, iHitsInMultiplet, sum, kAllHits);
1883  if (cvI < 0) return false;
1884  float minI = 1E6;
1885  float maxI = 0;
1886  for (auto& iht : iHitsInMultiplet) {
1887  auto const& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1888  float cv = hit.PeakTime();
1889  float rms = hit.RMS();
1890  float arg = cv - 3.1 * rms;
1891  if (arg < minI) minI = arg;
1892  arg = cv + 3.1 * rms;
1893  if (arg > maxI) maxI = arg;
1894  }
1895 
1896  float cvJ = HitsPosTick(slc, jHitsInMultiplet, sum, kAllHits);
1897  if (cvJ < 0) return false;
1898  float minJ = 1E6;
1899  float maxJ = 0;
1900  for (auto& jht : jHitsInMultiplet) {
1901  auto& hit = (*evt.allHits)[slc.slHits[jht].allHitsIndex];
1902  float cv = hit.PeakTime();
1903  float rms = hit.RMS();
1904  float arg = cv - 3.1 * rms;
1905  if (arg < minJ) minJ = arg;
1906  arg = cv + 3.1 * rms;
1907  if (arg > maxJ) maxJ = arg;
1908  }
1909 
1910  if (cvI < cvJ) {
1911  if (maxI > minJ) return true;
1912  }
1913  else {
1914  if (minI < maxJ) return true;
1915  }
1916  return false;
1917  } // TrajHitsOK
process_name hit
Definition: cheaterreco.fcl:51
float HitsPosTick(const TCSlice &slc, const std::vector< unsigned int > &hitsInMultiplet, float &sum, HitStatus_t hitRequest)
Definition: Utils.cxx:4289
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
TCEvent evt
Definition: DataStructs.cxx:8
bool tca::TrajHitsOK ( TCSlice &  slc,
const unsigned int  iht,
const unsigned int  jht 
)

Definition at line 1921 of file Utils.cxx.

1922  {
1923  // ensure that two adjacent hits have an acceptable overlap
1924  if (iht > slc.slHits.size() - 1) return false;
1925  if (jht > slc.slHits.size() - 1) return false;
1926  // require that they be on adjacent wires
1927  auto& ihit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
1928  auto& jhit = (*evt.allHits)[slc.slHits[jht].allHitsIndex];
1929  int iwire = ihit.WireID().Wire;
1930  int jwire = jhit.WireID().Wire;
1931  if (std::abs(iwire - jwire) > 1) return false;
1932  if (ihit.PeakTime() > jhit.PeakTime()) {
1933  float minISignal = ihit.PeakTime() - 3 * ihit.RMS();
1934  float maxJSignal = jhit.PeakTime() + 3 * ihit.RMS();
1935  if (maxJSignal > minISignal) return true;
1936  }
1937  else {
1938  float maxISignal = ihit.PeakTime() + 3 * ihit.RMS();
1939  float minJSignal = jhit.PeakTime() - 3 * ihit.RMS();
1940  if (minJSignal > maxISignal) return true;
1941  }
1942  return false;
1943  } // TrajHitsOK
T abs(T value)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
TCEvent evt
Definition: DataStructs.cxx:8
void tca::TrajIntersection ( TrajPoint const &  tp1,
TrajPoint const &  tp2,
Point2_t &  pos 
)

Definition at line 2604 of file Utils.cxx.

2605  {
2606  TrajIntersection(tp1, tp2, pos[0], pos[1]);
2607  } // TrajIntersection
void TrajIntersection(TrajPoint const &tp1, TrajPoint const &tp2, Point2_t &pos)
Definition: Utils.cxx:2604
void tca::TrajIntersection ( TrajPoint const &  tp1,
TrajPoint const &  tp2,
float &  x,
float &  y 
)

Definition at line 2610 of file Utils.cxx.

2611  {
2612  // returns the intersection position, (x,y), of two trajectory points
2613 
2614  x = -9999;
2615  y = -9999;
2616 
2617  double arg1 = tp1.Pos[0] * tp1.Dir[1] - tp1.Pos[1] * tp1.Dir[0];
2618  double arg2 = tp2.Pos[0] * tp1.Dir[1] - tp2.Pos[1] * tp1.Dir[0];
2619  double arg3 = tp2.Dir[0] * tp1.Dir[1] - tp2.Dir[1] * tp1.Dir[0];
2620  if (arg3 == 0) return;
2621  double s = (arg1 - arg2) / arg3;
2622 
2623  x = (float)(tp2.Pos[0] + s * tp2.Dir[0]);
2624  y = (float)(tp2.Pos[1] + s * tp2.Dir[1]);
2625 
2626  } // TrajIntersection
process_name opflash particleana ie x
process_name opflash particleana ie ie y
then echo File list $list not found else cat $list while read file do echo $file sed s
Definition: file_to_url.sh:60
bool tca::TrajIsClean ( TCSlice &  slc,
Trajectory &  tj,
bool  prt 
)

Definition at line 3442 of file Utils.cxx.

3443  {
3444  // Returns true if the trajectory has low hit multiplicity and is in a
3445  // clean environment
3446  unsigned short nUsed = 0;
3447  unsigned short nTotHits = 0;
3448  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
3449  TrajPoint& tp = tj.Pts[ipt];
3450  nTotHits += tp.Hits.size();
3451  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3452  if (tp.UseHit[ii]) ++nUsed;
3453  } // ii
3454  } // ipt
3455  if (nTotHits == 0) return false;
3456  float fracUsed = (float)nUsed / (float)nTotHits;
3457  if (prt)
3458  mf::LogVerbatim("TC") << "TrajIsClean: nTotHits " << nTotHits << " nUsed " << nUsed
3459  << " fracUsed " << fracUsed;
3460 
3461  if (fracUsed > 0.9) return true;
3462  return false;
3463 
3464  } // TrajIsClean
float tca::TrajLength ( const Trajectory &  tj)

Definition at line 2646 of file Utils.cxx.

2647  {
2648  float len = 0, dx, dy;
2649  unsigned short ipt;
2650  unsigned short prevPt = tj.EndPt[0];
2651  for (ipt = tj.EndPt[0] + 1; ipt < tj.EndPt[1] + 1; ++ipt) {
2652  if (tj.Pts[ipt].Chg == 0) continue;
2653  dx = tj.Pts[ipt].Pos[0] - tj.Pts[prevPt].Pos[0];
2654  dy = tj.Pts[ipt].Pos[1] - tj.Pts[prevPt].Pos[1];
2655  len += sqrt(dx * dx + dy * dy);
2656  prevPt = ipt;
2657  }
2658  return len;
2659  } // TrajLength
float tca::TrajPointSeparation ( const TrajPoint &  tp1,
const TrajPoint &  tp2 
)

Definition at line 2680 of file Utils.cxx.

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

Definition at line 2435 of file Utils.cxx.

2440  {
2441  // Finds the point, ipt, on trajectory tj that is closest to trajpoint tp
2442  float best = minSep * minSep;
2443  closePt = USHRT_MAX;
2444  float dw, dt, dp2;
2445  unsigned short ipt;
2446  for (ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2447  dw = tj.Pts[ipt].Pos[0] - tp.Pos[0];
2448  dt = tj.Pts[ipt].Pos[1] - tp.Pos[1];
2449  dp2 = dw * dw + dt * dt;
2450  if (dp2 < best) {
2451  best = dp2;
2452  closePt = ipt;
2453  }
2454  } // ipt
2455  minSep = sqrt(best);
2456  } // TrajPointTrajDOCA
float tca::TrajPointVertexPull ( const TCSlice &  slc,
const TrajPoint &  tp,
const VtxStore &  vx 
)

Definition at line 1851 of file TCVertex.cxx.

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

Definition at line 2460 of file Utils.cxx.

2466  {
2467  return TrajTrajDOCA(slc, tj1, tj2, ipt1, ipt2, minSep, false);
2468  } // TrajTrajDOCA
bool TrajTrajDOCA(const TCSlice &slc, const Trajectory &tj1, const Trajectory &tj2, unsigned short &ipt1, unsigned short &ipt2, float &minSep)
Definition: Utils.cxx:2460
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 2472 of file Utils.cxx.

2479  {
2480  // Find the Distance Of Closest Approach between two trajectories less than minSep
2481  // start with some rough cuts to minimize the use of the more expensive checking. This
2482  // function returns true if the DOCA is less than minSep
2483  for (unsigned short iwt = 0; iwt < 2; ++iwt) {
2484  // Apply box cuts on the ends of the trajectories
2485  // The Lo/Hi wire(time) at each end of tj1
2486  float wt0 = tj1.Pts[tj1.EndPt[0]].Pos[iwt];
2487  float wt1 = tj1.Pts[tj1.EndPt[1]].Pos[iwt];
2488  float lowt1 = wt0;
2489  float hiwt1 = wt1;
2490  if (wt1 < lowt1) {
2491  lowt1 = wt1;
2492  hiwt1 = wt0;
2493  }
2494  // The Lo/Hi wire(time) at each end of tj2
2495  wt0 = tj2.Pts[tj2.EndPt[0]].Pos[iwt];
2496  wt1 = tj2.Pts[tj2.EndPt[1]].Pos[iwt];
2497  float lowt2 = wt0;
2498  float hiwt2 = wt1;
2499  if (wt1 < lowt2) {
2500  lowt2 = wt1;
2501  hiwt2 = wt0;
2502  }
2503  // Check for this configuration
2504  // loWire1.......hiWire1 minSep loWire2....hiWire2
2505  // loTime1.......hiTime1 minSep loTime2....hiTime2
2506  if (lowt2 > hiwt1 + minSep) return false;
2507  // and the other
2508  if (lowt1 > hiwt2 + minSep) return false;
2509  } // iwt
2510 
2511  float best = minSep * minSep;
2512  ipt1 = 0;
2513  ipt2 = 0;
2514  float dwc = 0;
2515  bool isClose = false;
2516  for (unsigned short i1 = tj1.EndPt[0]; i1 < tj1.EndPt[1] + 1; ++i1) {
2517  for (unsigned short i2 = tj2.EndPt[0]; i2 < tj2.EndPt[1] + 1; ++i2) {
2518  if (considerDeadWires) dwc = DeadWireCount(slc, tj1.Pts[i1], tj2.Pts[i2]);
2519  float dw = tj1.Pts[i1].Pos[0] - tj2.Pts[i2].Pos[0] - dwc;
2520  if (std::abs(dw) > minSep) continue;
2521  float dt = tj1.Pts[i1].Pos[1] - tj2.Pts[i2].Pos[1];
2522  if (std::abs(dt) > minSep) continue;
2523  float dp2 = dw * dw + dt * dt;
2524  if (dp2 < best) {
2525  best = dp2;
2526  ipt1 = i1;
2527  ipt2 = i2;
2528  isClose = true;
2529  }
2530  } // i2
2531  } // i1
2532  minSep = sqrt(best);
2533  return isClose;
2534  } // TrajTrajDOCA
T abs(T value)
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2141
bool tca::TransferTjHits ( TCSlice &  slc,
bool  prt 
)

Definition at line 3898 of file TCShower.cxx.

3899  {
3900  // Transfer InShower hits in all TPCs and planes to the shower Tjs
3901 
3902  bool newShowers = false;
3903  for (auto& ss : slc.cots) {
3904  if (ss.ID == 0) continue;
3905  if (ss.ShowerTjID == 0) continue;
3906  // Tp 1 of stj will get all of the shower hits
3907  Trajectory& stj = slc.tjs[ss.ShowerTjID - 1];
3908  if (!stj.Pts[1].Hits.empty()) {
3909  std::cout << "TTjH: ShowerTj T" << stj.ID << " already has " << stj.Pts[1].Hits.size()
3910  << " hits\n";
3911  continue;
3912  }
3913  // Note that UseHit is not used since the size is limited to 16
3914  for (auto& tjID : ss.TjIDs) {
3915  unsigned short itj = tjID - 1;
3916  if (slc.tjs[itj].AlgMod[kShowerTj]) {
3917  std::cout << "TTjH: Coding error. T" << tjID << " is a ShowerTj but is in TjIDs\n";
3918  continue;
3919  }
3920  if (slc.tjs[itj].SSID <= 0) {
3921  std::cout << "TTjH: Coding error. Trying to transfer T" << tjID
3922  << " hits but it isn't an InShower Tj\n";
3923  continue;
3924  }
3925  auto thits = PutTrajHitsInVector(slc.tjs[itj], kUsedHits);
3926  // associate all hits with the charge center TP
3927  stj.Pts[1].Hits.insert(stj.Pts[1].Hits.end(), thits.begin(), thits.end());
3928  // kill Tjs that are in showers
3929  slc.tjs[itj].AlgMod[kKilled] = true;
3930  } // tjID
3931  // re-assign the hit -> stj association
3932  for (auto& iht : stj.Pts[1].Hits)
3933  slc.slHits[iht].InTraj = stj.ID;
3934  newShowers = true;
3935  } // ss
3936 
3937  if (prt) mf::LogVerbatim("TC") << "TTJH: success? " << newShowers;
3938  return newShowers;
3939  } // TransferTjHits
std::vector< unsigned int > PutTrajHitsInVector(const Trajectory &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2754
BEGIN_PROLOG could also be cout
void tca::TrimEndPts ( std::string  fcnLabel,
TCSlice &  slc,
Trajectory &  tj,
const std::vector< float > &  fQualityCuts,
bool  prt 
)

Definition at line 1600 of file Utils.cxx.

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

Definition at line 1557 of file Utils.cxx.

1558  {
1559  // Trim points at the end if the charge pull is too high
1560  if (!tcc.useAlg[kTHCEP]) return;
1561  // don't consider long electrons
1562  if (tj.PDGCode == 111) return;
1563  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
1564  // only consider long tjs
1565  if (npwc < 50) return;
1566  // that don't have a Bragg peak
1567  if (tj.EndFlag[1][kBragg]) return;
1568 
1569  // only look at the last points that would have not been considered by GottaKink
1570  unsigned short nPtsMax = tcc.kinkCuts[0];
1571  if (nPtsMax > 8) nPtsMax = 8;
1572 
1573  // find the first point with a high charge pull starting at nPtsMax points before the end
1574  // and count the number of high charge pull points
1575  float cntBad = 0;
1576  unsigned short firstBad = USHRT_MAX;
1577  for (unsigned short ii = 0; ii < nPtsMax; ++ii) {
1578  unsigned short ipt = tj.EndPt[1] - nPtsMax + ii;
1579  auto& tp = tj.Pts[ipt];
1580  if (tp.Chg <= 0) continue;
1581  if (tp.ChgPull < 3) continue;
1582  ++cntBad;
1583  if (firstBad == USHRT_MAX) firstBad = ipt;
1584  } // ii
1585  if (firstBad == USHRT_MAX) return;
1586  // total number of points from the first bad point to the end
1587  float cntTot = tj.EndPt[1] - firstBad;
1588  // fraction of those poins that are bad
1589  float fracBad = cntBad / cntTot;
1590  if (fracBad < 0.5) return;
1591  if (prt)
1592  mf::LogVerbatim("TC") << "THCEP: Trim points starting at " << PrintPos(slc, tj.Pts[firstBad]);
1593  for (unsigned short ipt = firstBad; ipt <= tj.EndPt[1]; ++ipt)
1594  UnsetUsedHits(slc, tj.Pts[ipt]);
1595  tj.AlgMod[kTHCEP] = true;
1596  } // TrimHiChgEndPts
std::vector< float > kinkCuts
kink finder algorithm
Definition: DataStructs.h:559
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1075
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. &lt; 0 to turn off.
Definition: DataStructs.h:586
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2116
float tca::TwoTPAngle ( const TrajPoint &  tp1,
const TrajPoint &  tp2 
)

Definition at line 2721 of file Utils.cxx.

2722  {
2723  // Calculates the angle of a line between two TPs
2724  float dw = tp2.Pos[0] - tp1.Pos[0];
2725  float dt = tp2.Pos[1] - tp1.Pos[1];
2726  return atan2(dw, dt);
2727  } // TwoTPAngle
void tca::UnsetUsedHits ( TCSlice &  slc,
TrajPoint &  tp 
)

Definition at line 1075 of file Utils.cxx.

1076  {
1077  // Sets InTraj = 0 and UseHit false for all used hits in tp
1078  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
1079  if (tp.UseHit[ii]) {
1080  slc.slHits[tp.Hits[ii]].InTraj = 0;
1081  tp.UseHit[ii] = false;
1082  } // UseHit
1083  } // ii
1084  tp.Chg = 0;
1085  } // UnsetUsedHits
bool tca::Update ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
const TCSlice &  slc,
PFPStruct &  pfp,
bool  prt 
)

Definition at line 1057 of file PFPUtils.cxx.

1062  {
1063  // This function only updates SectionFits that need to be re-sorted or re-fit. It returns
1064  // false if there was a serious error indicating that the pfp should be abandoned
1065  if (pfp.TP3Ds.empty() || pfp.SectionFits.empty()) return false;
1066 
1067  // special handling for small angle tracks
1068  if(pfp.AlgMod[kSmallAngle]) {
1069  for(unsigned short sfi = 0; sfi < pfp.SectionFits.size(); ++sfi) {
1070  auto& sf = pfp.SectionFits[sfi];
1071  if (!sf.NeedsUpdate) continue;
1072  if (!SortSection(pfp, sfi)) return false;
1073  sf.NPts = 0;
1074  sf.ChiDOF = 0;
1075  for(unsigned short ipt = 0; ipt < pfp.TP3Ds.size(); ++ipt) {
1076  auto& tp3d = pfp.TP3Ds[ipt];
1077  if(tp3d.SFIndex < sfi) continue;
1078  if(tp3d.SFIndex > sfi) break;
1079  ++sf.NPts;
1080  double delta = tp3d.Pos[0] - tp3d.TPX;
1081  sf.ChiDOF += delta * delta / tp3d.TPXErr2;
1082  } // ipt
1083  if(sf.NPts < 5) {
1084  sf.ChiDOF = 0;
1085  } else {
1086  sf.ChiDOF /= (float)(sf.NPts - 4);
1087  }
1088  sf.NeedsUpdate = false;
1089  } // sfi
1090  pfp.Flags[kNeedsUpdate] = false;
1091  return true;
1092  } // kSmallAngle
1093 
1094  for (std::size_t sfi = 0; sfi < pfp.SectionFits.size(); ++sfi) {
1095  auto& sf = pfp.SectionFits[sfi];
1096  if (!sf.NeedsUpdate) continue;
1097  if (!FitSection(clockData, detProp, slc, pfp, sfi)) return false;
1098  if (!SortSection(pfp, sfi)) return false;
1099  sf.NeedsUpdate = false;
1100  } // sfi
1101 
1102  // ensure that all points (good or not) have a valid SFIndex
1103  for (auto& tp3d : pfp.TP3Ds) {
1104  if (tp3d.SFIndex >= pfp.SectionFits.size()) SetSection(detProp, slc, pfp, tp3d);
1105  } // tp3d
1106  pfp.Flags[kNeedsUpdate] = false;
1107  return true;
1108  } // Update
bool SetSection(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, TP3D &tp3d)
Definition: PFPUtils.cxx:2770
bool SortSection(PFPStruct &pfp, unsigned short sfIndex)
Definition: PFPUtils.cxx:2028
bool FitSection(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, PFPStruct &pfp, unsigned short sfIndex)
Definition: PFPUtils.cxx:1414
auto const detProp
void tca::UpdateDeltaRMS ( TCSlice &  slc,
Trajectory &  tj 
)

Definition at line 2349 of file StepUtils.cxx.

2350  {
2351  // Estimate the Delta RMS of the TPs on the end of tj.
2352 
2353  unsigned int lastPt = tj.EndPt[1];
2354  TrajPoint& lastTP = tj.Pts[lastPt];
2355 
2356  if(lastTP.Chg == 0) return;
2357  if(lastPt < 6) return;
2358 
2359  unsigned short ii, ipt, cnt = 0;
2360  float sum = 0;
2361  for(ii = 1; ii < tj.Pts.size(); ++ii) {
2362  ipt = lastPt - ii;
2363  if(ipt > tj.Pts.size() - 1) break;
2364  if(tj.Pts[ipt].Chg == 0) continue;
2365  sum += PointTrajDOCA(slc, tj.Pts[ipt].Pos[0], tj.Pts[ipt].Pos[1], lastTP);
2366  ++cnt;
2367  if(cnt == lastTP.NTPsFit) break;
2368  if(ipt == 0) break;
2369  }
2370  if(cnt < 3) return;
2371  // RMS of Gaussian distribution is ~1.2 x the average
2372  // of a one-sided Gaussian distribution (since Delta is > 0)
2373  lastTP.DeltaRMS = 1.2 * sum / (float)cnt;
2374  if(lastTP.DeltaRMS < 0.02) lastTP.DeltaRMS = 0.02;
2375 
2376  } // UpdateDeltaRMS
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2572
bool tca::UpdateShower ( std::string  inFcnLabel,
TCSlice &  slc,
ShowerStruct &  ss,
bool  prt 
)

Definition at line 913 of file TCShower.cxx.

914  {
915  // This is intended to be a single function replacement for FCC, FA, USWP, etc. The calling
916  // function should have set NeedsUpdate true. A complete re-build is done if the ShPts vector
917  // is empty. This is only required if a tj is removed from the shower. When adding a tj
918  // to the shower the AddTj function appends the tj points to ShPts but doesn't fill
919  // the ShPts RotPos values.
920  // This function doesn't alter or check associations btw showers and tjs.
921 
922  if (ss.ID == 0) return false;
923  if (ss.TjIDs.empty()) return false;
924  if (ss.ShowerTjID <= 0 || ss.ShowerTjID > (int)slc.tjs.size()) return false;
925  if (ss.ParentID > 0 && ss.ParentID > (int)slc.tjs.size()) return false;
926  auto& stj = slc.tjs[ss.ShowerTjID - 1];
927  if (stj.Pts.size() != 3) return false;
928 
929  std::string fcnLabel = inFcnLabel + ".U2S";
930 
931  if (!ss.NeedsUpdate && !ss.ShPts.empty()) return true;
932 
933  // initialize the variables that will be defined in this function
934  ss.Energy = 0; // This is just ShowerEnergy(stj.TotChg) and could be deleted
935  ss.AspectRatio = 10;
936  // Direction FOM (0 = good). This is a property of the shower shape and is not
937  // defined by the presence or absence of a parent tj start point
938  ss.DirectionFOM = 10;
939  // Total charge of all hits in the shower
940  stj.TotChg = 0;
941  for (auto& stp : stj.Pts) {
942  // Shower start, charge center, and shower end
943  stp.Pos = {{0.0, 0.0}};
944  // Charge weighted average of hits this section (TP) along the shower
945  stp.HitPos = {{0.0, 0.0}};
946  // Direction from the start to the charge center - same for all TPs
947  stp.Dir = {{0.0, 0.0}};
948  // Hit charge in each section
949  stp.Chg = 0;
950  // transverse rms of hit positions relative to HitPos in this section
951  stp.DeltaRMS = 0;
952  // number of hits in this section
953  stp.NTPsFit = 0;
954  } // stp
955 
956  ss.ShPts.clear();
957  for (auto tjid : ss.TjIDs) {
958  if (tjid <= 0 || tjid > (int)slc.tjs.size()) return false;
959  auto& tj = slc.tjs[tjid - 1];
960  if (tj.CTP != ss.CTP) return false;
961  if (tj.AlgMod[kShowerTj]) return false;
962  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
963  TrajPoint& tp = tj.Pts[ipt];
964  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
965  if (!tp.UseHit[ii]) continue;
966  unsigned int iht = tp.Hits[ii];
967  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
968  if (hit.Integral() <= 0) continue;
969  ShowerPoint shpt;
970  shpt.HitIndex = iht;
971  shpt.TID = tj.ID;
972  shpt.Chg = hit.Integral();
973  shpt.Pos[0] = hit.WireID().Wire;
974  shpt.Pos[1] = hit.PeakTime() * tcc.unitsPerTick;
975  ss.ShPts.push_back(shpt);
976  } // ii
977  } // ipt
978  } // tjid
979  if (prt) mf::LogVerbatim("TC") << fcnLabel << " 2S" << ss.ID << " nShPts " << ss.ShPts.size();
980 
981  if (ss.ShPts.size() < 3) return false;
982 
983  // find the charge center and total charge
984  auto& stp1 = stj.Pts[1];
985  for (auto& shpt : ss.ShPts) {
986  stp1.Pos[0] += shpt.Chg * shpt.Pos[0];
987  stp1.Pos[1] += shpt.Chg * shpt.Pos[1];
988  stj.TotChg += shpt.Chg;
989  } // shpt
990  if (stj.TotChg <= 0) return false;
991  stp1.Pos[0] /= stj.TotChg;
992  stp1.Pos[1] /= stj.TotChg;
993  ss.Energy = ChgToMeV(stj.TotChg);
994  if (prt)
995  mf::LogVerbatim("TC") << fcnLabel << " 2S" << ss.ID << " Chg ctr " << PrintPos(slc, stp1.Pos)
996  << " Energy " << (int)ss.Energy << " MeV";
997 
998  // find the direction using the shower parent if one exists
999  if (ss.ParentID > 0) {
1000  // Set the direction to be the start of the parent to the shower center
1001  auto& ptj = slc.tjs[ss.ParentID - 1];
1002  // find the parent end farthest away from the charge center
1003  unsigned short pend = FarEnd(slc, ptj, stp1.Pos);
1004  auto& ptp = ptj.Pts[ptj.EndPt[pend]];
1005  stp1.Dir = PointDirection(ptp.Pos, stp1.Pos);
1006  stp1.Ang = atan2(stp1.Dir[1], stp1.Dir[0]);
1007  }
1008  else {
1009  // find the shower direction using the points
1010  double sum = 0.;
1011  double sumx = 0.;
1012  double sumy = 0.;
1013  double sumxy = 0.;
1014  double sumx2 = 0.;
1015  double sumy2 = 0.;
1016  for (auto& shpt : ss.ShPts) {
1017  sum += shpt.Chg;
1018  double xx = shpt.Pos[0] - stp1.Pos[0];
1019  double yy = shpt.Pos[1] - stp1.Pos[1];
1020  sumx += shpt.Chg * xx;
1021  sumy += shpt.Chg * yy;
1022  sumxy += shpt.Chg * xx * yy;
1023  sumx2 += shpt.Chg * xx * xx;
1024  sumy2 += shpt.Chg * yy * yy;
1025  } // shpt
1026  double delta = sum * sumx2 - sumx * sumx;
1027  if (delta == 0) return false;
1028  // A is the intercept (This should be ~0 )
1029  // double A = (sumx2 * sumy - sumx * sumxy) / delta;
1030  // B is the slope
1031  double B = (sumxy * sum - sumx * sumy) / delta;
1032  stp1.Ang = atan(B);
1033  stp1.Dir[0] = cos(stp1.Ang);
1034  stp1.Dir[1] = sin(stp1.Ang);
1035  } // no shower parent
1036 
1037  // TODO: ss.Angle should be eliminated. The shower tj Ang should be used instead
1038  ss.Angle = stp1.Ang;
1039  if (prt)
1040  mf::LogVerbatim("TC") << fcnLabel << " 2S" << ss.ID << " dir " << std::fixed
1041  << std::setprecision(2) << stp1.Dir[0] << " " << stp1.Dir[1]
1042  << " Angle " << stp1.Ang;
1043  for (unsigned short ipt = 0; ipt < 3; ++ipt) {
1044  if (ipt == 1) continue;
1045  stj.Pts[ipt].Dir = stp1.Dir;
1046  stj.Pts[ipt].Ang = stp1.Ang;
1047  } // ipt
1048 
1049  // fill the RotPos vector and sort
1050  std::vector<SortEntry> sortVec(ss.ShPts.size());
1051  unsigned short indx = 0;
1052  double cs = cos(-stp1.Ang);
1053  double sn = sin(-stp1.Ang);
1054  for (auto& shpt : ss.ShPts) {
1055  double xx = shpt.Pos[0] - stp1.Pos[0];
1056  double yy = shpt.Pos[1] - stp1.Pos[1];
1057  shpt.RotPos[0] = cs * xx - sn * yy;
1058  shpt.RotPos[1] = sn * xx + cs * yy;
1059  sortVec[indx].index = indx;
1060  sortVec[indx].val = shpt.RotPos[0];
1061  ++indx;
1062  } // shpt
1063  std::sort(sortVec.begin(), sortVec.end(), valsDecreasing);
1064  // put the points vector into the sorted order
1065  auto tPts = ss.ShPts;
1066  for (unsigned short ii = 0; ii < ss.ShPts.size(); ++ii)
1067  ss.ShPts[ii] = tPts[sortVec[ii].index];
1068 
1069  // Calculate the aspect ratio
1070  Point2_t alongTrans{{0.0, 0.0}};
1071  for (auto& shpt : ss.ShPts) {
1072  alongTrans[0] += shpt.Chg * std::abs(shpt.RotPos[0]);
1073  alongTrans[1] += shpt.Chg * std::abs(shpt.RotPos[1]);
1074  } // shpt
1075  alongTrans[0] /= stj.TotChg;
1076  alongTrans[1] /= stj.TotChg;
1077  if (alongTrans[1] == 0) return false;
1078  ss.AspectRatio = alongTrans[1] / alongTrans[0];
1079  if (prt)
1080  mf::LogVerbatim("TC") << fcnLabel << " 2S" << ss.ID << " AspectRatio " << ss.AspectRatio;
1081 
1082  // analyze the charge in three sections. Fill the stj HitPos and find DeltaRMS
1083  if (!AnalyzeRotPos(fcnLabel, slc, ss, prt)) return false;
1084 
1085  // Reverse the shower direction if needed and define the start point
1086  if (ss.ParentID > 0) {
1087  // The direction was defined by the start of a parent to the charge center. Check the consistency
1088  // with ShPts and reverse if needed
1089  auto& ptj = slc.tjs[ss.ParentID - 1];
1090  // find the parent end farthest away from the charge center
1091  unsigned short pend = FarEnd(slc, ptj, stp1.Pos);
1092  auto& ptp = ptj.Pts[ptj.EndPt[pend]];
1093  auto& firstShPt = ss.ShPts[0];
1094  auto& lastShPt = ss.ShPts[ss.ShPts.size() - 1];
1095  if (PosSep2(ptp.Pos, lastShPt.Pos) < PosSep2(ptp.Pos, firstShPt.Pos))
1096  ReverseShower(fcnLabel, slc, ss, prt);
1097  stj.Pts[0].Pos = ptp.Pos;
1098  }
1099  else {
1100  // no parent exists. Compare the DeltaRMS at the ends
1101  if (stj.Pts[2].DeltaRMS < stj.Pts[0].DeltaRMS) ReverseShower(fcnLabel, slc, ss, prt);
1102  stj.Pts[0].Pos = ss.ShPts[0].Pos;
1103  } // no parent
1104 
1105  if (stj.Pts[2].DeltaRMS > 0) ss.DirectionFOM = stj.Pts[0].DeltaRMS / stj.Pts[2].DeltaRMS;
1106  // define the end point
1107  stj.Pts[2].Pos = ss.ShPts[ss.ShPts.size() - 1].Pos;
1108 
1109  DefineEnvelope(fcnLabel, slc, ss, prt);
1110  ss.NeedsUpdate = false;
1111  if (prt) mf::LogVerbatim("TC") << fcnLabel << " 2S" << ss.ID << " updated";
1112  return true;
1113 
1114  } // UpdateShower
unsigned short FarEnd(const TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3339
then if[["$THISISATEST"==1]]
Definition: neoSmazza.sh:95
void ReverseShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3153
TCConfig tcc
Definition: DataStructs.cxx:9
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
process_name hit
Definition: cheaterreco.fcl:51
void DefineEnvelope(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3489
T abs(T value)
std::array< float, 2 > Point2_t
Definition: DataStructs.h:43
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:571
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:2548
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2572
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
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:3062
float ChgToMeV(float chg)
Definition: TCShower.cxx:3982
TCEvent evt
Definition: DataStructs.cxx:8
bool tca::UpdateShower ( std::string  inFcnLabel,
TCSlice &  slc,
ShowerStruct3D &  ss3,
bool  prt 
)

Definition at line 1118 of file TCShower.cxx.

1119  {
1120  // Updates the 3D shower presumably because the 2D showers were changed or need to be updated.
1121  // This function returns false if there was a failure.
1122 
1123  if (ss3.ID == 0) return false;
1124  if (ss3.CotIDs.size() < 2) return false;
1125 
1126  std::string fcnLabel = inFcnLabel + ".U3S";
1127 
1128  // see if any of the 2D showers need an update
1129  for (auto cid : ss3.CotIDs) {
1130  auto& ss = slc.cots[cid - 1];
1131  if (ss.NeedsUpdate && prt)
1132  std::cout << fcnLabel << " ********* 3S" << ss3.ID << " 2S" << ss.ID
1133  << " needs an update...\n";
1134  UpdateShower(fcnLabel, slc, ss, prt);
1135  } // ci
1136 
1137  // check consistency
1138  if (ss3.ParentID > 0) {
1139  auto& pfp = slc.pfps[ss3.ParentID - 1];
1140  unsigned short pend = FarEnd(slc, pfp, ss3.ChgPos);
1141  if (pfp.Vx3ID[pend] != ss3.Vx3ID) {
1142  if (prt)
1143  std::cout << fcnLabel << " ********* 3S" << ss3.ID << " has parent P" << ss3.ParentID
1144  << " with a vertex that is not attached the shower\n";
1145  }
1146  } // ss3.ParentID > 0
1147 
1148  // Find the average position and direction using pairs of 2D shower Tjs
1149  std::array<Point3_t, 3> pos;
1150  // the direction of all points in 2D showers is the same
1151  Vector3_t dir;
1152  std::array<double, 3> chg;
1153  for (unsigned short ipt = 0; ipt < 3; ++ipt) {
1154  chg[ipt] = 0;
1155  for (unsigned short xyz = 0; xyz < 3; ++xyz) {
1156  pos[ipt][xyz] = 0;
1157  dir[xyz] = 0;
1158  }
1159  } // ipt
1160  unsigned short nok = 0;
1161  for (unsigned short ipt = 0; ipt < 3; ++ipt) {
1162  if (chg[ipt] == 0) continue;
1163  for (unsigned short xyz = 0; xyz < 3; ++xyz)
1164  pos[ipt][xyz] /= chg[ipt];
1165  SetMag(dir, 1);
1166  ++nok;
1167  } // ipt
1168 
1169  if (nok != 3) return false;
1170  ss3.ChgPos = pos[1];
1171 
1172  if (ss3.ParentID > 0) {
1173  // There is a 3D-matched pfp at the shower start. The end that is farthest away from the
1174  // shower center should be shower start
1175  auto& pfp = slc.pfps[ss3.ParentID - 1];
1176  unsigned short pend = FarEnd(slc, pfp, ss3.ChgPos);
1177  ss3.Start = PosAtEnd(pfp, pend);
1178  ss3.Dir = dir;
1179  }
1180  else {
1181  ss3.Dir = dir;
1182  ss3.Start = pos[0];
1183  }
1184  // define the end
1185  ss3.End = pos[2];
1186  ss3.Len = PosSep(ss3.Start, ss3.End);
1187 
1188  // dE/dx, energy, etc
1189  for (auto cid : ss3.CotIDs) {
1190  auto& ss = slc.cots[cid - 1];
1191  auto& stj = slc.tjs[ss.ShowerTjID - 1];
1192  unsigned short plane = DecodeCTP(ss.CTP).Plane;
1193  ss3.Energy[plane] = ss.Energy;
1194  // TODO: calculate the errors in some better way
1195  ss3.EnergyErr[plane] = 0.3 * ss.Energy;
1196  // TODO: what does MIPEnergy mean anyway?
1197  ss3.MIPEnergy[plane] = ss3.EnergyErr[plane];
1198  ss3.MIPEnergyErr[plane] = ss.Energy;
1199  ss3.dEdx[plane] = stj.dEdx[0];
1200  ss3.dEdxErr[plane] = 0.3 * stj.dEdx[0];
1201  } // ci
1202 
1203  ss3.NeedsUpdate = false;
1204  if (prt) mf::LogVerbatim("TC") << fcnLabel << " 3S" << ss3.ID << " updated";
1205  return true;
1206 
1207  } // UpdateShower
unsigned short FarEnd(const TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3339
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3293
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
bool SetMag(Vector3_t &v1, double mag)
Definition: PFPUtils.cxx:2583
tuple dir
Definition: dropbox.py:28
geo::PlaneID DecodeCTP(CTP_t CTP)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2565
std::array< double, 3 > Vector3_t
Definition: DataStructs.h:42
bool UpdateShower(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:913
BEGIN_PROLOG could also be cout
void tca::UpdateStiffEl ( TCSlice &  slc,
Trajectory &  tj 
)

Definition at line 648 of file StepUtils.cxx.

649  {
650  // A different stategy for updating a high energy electron trajectories
651  if(!tj.Strategy[kStiffEl]) return;
652  TrajPoint& lastTP = tj.Pts[tj.EndPt[1]];
653  // Set the lastPT delta before doing the fit
654  lastTP.Delta = PointTrajDOCA(slc, lastTP.HitPos[0], lastTP.HitPos[1], lastTP);
655  if(tj.Pts.size() < 30) lastTP.NTPsFit += 1;
656  FitTraj(slc, tj);
657  UpdateTjChgProperties("UET", slc, tj, tcc.dbgStp);
658  UpdateDeltaRMS(slc, tj);
659  tj.MCSMom = MCSMom(slc, tj);
660  if(tcc.dbgStp) {
661  mf::LogVerbatim("TC")<<"UpdateStiffEl: lastPt "<<tj.EndPt[1]<<" Delta "<<lastTP.Delta<<" AngleCode "<<lastTP.AngleCode<<" FitChi "<<lastTP.FitChi<<" NTPsFit "<<lastTP.NTPsFit<<" MCSMom "<<tj.MCSMom;
662  }
663  tj.NeedsUpdate = false;
664  tj.PDGCode = 111;
665  return;
666  } // UpdateStiffTj
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3468
TCConfig tcc
Definition: DataStructs.cxx:9
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2572
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
void FitTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:808
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3673
use the stiff electron strategy
Definition: DataStructs.h:501
void UpdateDeltaRMS(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2349
void tca::UpdateTjChgProperties ( std::string  inFcnLabel,
TCSlice &  slc,
Trajectory &  tj,
bool  prt 
)

Definition at line 3673 of file Utils.cxx.

3674  {
3675  // Updates properties of the tj that are affected when the TP environment
3676  // is changed. The most likely reason for a change is when the tj is attached to a
3677  // vertex in which case the Environment kEnvOverlap bit may be set by the UpdateVxEnvironment
3678  // function in which case this function is called.
3679  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) return;
3680 
3681  // first (un)set some bits
3682  for (auto& tp : tj.Pts) {
3683  if (tp.Chg <= 0) continue;
3684  tp.Environment[kEnvUnusedHits] = false;
3685  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
3686  if (tp.UseHit[ii]) continue;
3687  unsigned int iht = tp.Hits[ii];
3688  if (slc.slHits[iht].InTraj == 0) tp.Environment[kEnvUnusedHits] = true;
3689  } // ii
3690  } // tp
3691 
3692  // Update the tj charge variables. The concept is explained by this graphic where
3693  // each column is a wire, Q = a TP with charge, q = a TP with charge that is an
3694  // EnvOverlap region, x = a wire that has a TP with Chg = 0 or a wire that has no TP
3695  // because the wire is dead, o = an EnvOverlap region, V = vertex attached to end. You should
3696  // imagine that all 3 tjs come from the same vertex
3697  // 01234567890123456789 npwc cnt range
3698  // VooooQQQQxxxQQQ 7 7 0 - 14
3699  // VqqqqQQQQxxxQQQQQQQQ 16 12 0 - 19
3700  // VooQQQ 3 3 0 - 5
3701  // The average is first calculated using Ave = sum(Q) / npwc
3702  // TotChg is calculated using
3703  tj.TotChg = 0;
3704  tj.AveChg = 0;
3705  tj.ChgRMS = 0.5;
3706 
3707  // These variables are used to calculate the average and rms using valid points with charge
3708  double vcnt = 0;
3709  double vsum = 0;
3710  double vsum2 = 0;
3711  // Reject a single large charge TP
3712  float bigChg = 0;
3713  for (unsigned short ipt = tj.EndPt[0] + 1; ipt < tj.EndPt[1]; ++ipt) {
3714  auto& tp = tj.Pts[ipt];
3715  if (tp.Chg > bigChg) bigChg = tp.Chg;
3716  } // ipt
3717  // variables for calculating the backup quanties. These are only used if npwc < 3
3718  double bcnt = 0;
3719  double bsum = 0;
3720  double bsum2 = 0;
3721  // don't include the end points
3722  for (unsigned short ipt = tj.EndPt[0] + 1; ipt < tj.EndPt[1]; ++ipt) {
3723  auto& tp = tj.Pts[ipt];
3724  if (tp.Chg <= 0) continue;
3725  // ignore the single large charge TP
3726  if (tp.Chg == bigChg) continue;
3727  // accumulate a backup sum in case most of the points are overlapped. Note that
3728  // tp.Chg has an angle correction, which is why the hit integral is summed
3729  // below. We don't care about this detail for the backup sum
3730  bsum += tp.Chg;
3731  bsum2 += tp.Chg * tp.Chg;
3732  if (tp.Chg > bigChg) bigChg = tp.Chg;
3733  ++bcnt;
3734  // Skip TPs that overlap with TPs on other Tjs. A correction will be made below
3735  if (tj.Pts[ipt].Environment[kEnvOverlap]) continue;
3736  ++vcnt;
3737  double tpchg = 0;
3738  for (unsigned short ii = 0; ii < tj.Pts[ipt].Hits.size(); ++ii) {
3739  if (!tp.UseHit[ii]) continue;
3740  unsigned int iht = tp.Hits[ii];
3741  tpchg += (*evt.allHits)[slc.slHits[iht].allHitsIndex].Integral();
3742  } // ii
3743  vsum += tpchg;
3744  vsum2 += tpchg * tpchg;
3745  } // ipt
3746 
3747  if (bcnt == 0) return;
3748 
3749  if (vcnt < 3) {
3750  // use the backup sum
3751  tj.TotChg = bsum;
3752  tj.AveChg = bsum / bcnt;
3753  if (vcnt > 2) {
3754  double arg = bsum2 - bcnt * tj.AveChg * tj.AveChg;
3755  if (arg > 0) tj.ChgRMS = sqrt(arg / (bcnt - 1));
3756  }
3757  for (auto& tp : tj.Pts)
3758  tp.AveChg = tj.AveChg;
3759  if (prt)
3760  mf::LogVerbatim("TC") << inFcnLabel << ".UpdateTjChgProperties: backup sum Set tj.AveChg "
3761  << (int)tj.AveChg << " ChgRMS " << tj.ChgRMS;
3762  return;
3763  } // low npwc
3764 
3765  double nWires = tj.EndPt[1] - tj.EndPt[0] + 1;
3766  if (nWires < 2) return;
3767  // correct for wires missing near vertices.
3768  // Count the number of wires between vertices at the ends and the first wire
3769  // that has charge. This code assumes that there should be one TP on each wire
3770  if (!tj.AlgMod[kPhoton]) {
3771  for (unsigned short end = 0; end < 2; ++end) {
3772  if (tj.VtxID[end] == 0) continue;
3773  auto& tp = tj.Pts[tj.EndPt[end]];
3774  auto& vx2 = slc.vtxs[tj.VtxID[end] - 1];
3775  int dw = std::abs(tp.Pos[0] - vx2.Pos[0]);
3776  // This assumes that the vertex is not inside the wire boundaries of the tj
3777  nWires += dw;
3778  } // end
3779  } // not a photon Tj
3780 
3781  tj.AveChg = vsum / vcnt;
3782  // calculate the total charge using the tj wire range
3783  tj.TotChg = nWires * tj.AveChg;
3784  // calculate the rms
3785  double arg = vsum2 - vcnt * tj.AveChg * tj.AveChg;
3786  double rms = 0.5;
3787  if (arg > 0) rms = sqrt(arg / (vcnt - 1));
3788  rms /= tj.AveChg;
3789  // don't let it be an unrealistically low value. It could be crazy large however.
3790  if (rms < 0.1) rms = 0.1;
3791  // Don't let the calculated charge RMS dominate until it is well known; after there are 5 - 10 valid TPs.
3792  // Set the starting charge rms = 0.5
3793  if (vcnt < 10) {
3794  double defFrac = 1 / vcnt;
3795  rms = defFrac * 0.5 + (1 - defFrac) * rms;
3796  }
3797  tj.ChgRMS = rms;
3798  if (prt)
3799  mf::LogVerbatim("TC") << inFcnLabel << ".UpdateTjChgProperties: Set tj.AveChg "
3800  << (int)tj.AveChg << " ChgRMS " << tj.ChgRMS;
3801 
3802  // Update the TP charge pulls.
3803  // Don't let the calculated charge RMS dominate the default
3804  // RMS until it is well known. Start with 50% error on the
3805  // charge RMS
3806  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
3807  auto& tp = tj.Pts[ipt];
3808  if (tp.Chg <= 0) continue;
3809  tp.ChgPull = (tp.Chg / tj.AveChg - 1) / tj.ChgRMS;
3810  } // ipt
3811 
3812  // update the local charge average using NPtsAve of the preceding points.
3813  // Handle short Tjs first.
3814  if (vcnt < tcc.nPtsAve) {
3815  for (auto& tp : tj.Pts)
3816  tp.AveChg = tj.AveChg;
3817  return;
3818  }
3819 
3820  // Set the local average to 0 first
3821  for (auto& tp : tj.Pts)
3822  tp.AveChg = 0;
3823  // Enter the local average on the points where an average can be calculated
3824  unsigned short nptsave = tcc.nPtsAve;
3825  unsigned short minPt = tj.EndPt[0] + nptsave;
3826  float lastAve = 0;
3827  for (unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
3828  unsigned short ipt = tj.EndPt[1] - ii;
3829  if (ipt < minPt) break;
3830  float cnt = 0;
3831  float sum = 0;
3832  for (unsigned short iii = 0; iii < nptsave; ++iii) {
3833  unsigned short iipt = ipt - iii;
3834  // Don't include the charge of the first point
3835  if (iipt == tj.EndPt[0]) break;
3836  auto& tp = tj.Pts[iipt];
3837  if (tp.Chg <= 0) continue;
3838  sum += tp.Chg;
3839  ++cnt;
3840  } // iii
3841  if (cnt > 2) {
3842  tj.Pts[ipt].AveChg = sum / cnt;
3843  lastAve = tj.Pts[ipt].AveChg;
3844  }
3845  } // ii
3846  // Fill in the points where no average was calculated
3847  for (unsigned short ii = tj.EndPt[0]; ii <= tj.EndPt[1]; ++ii) {
3848  unsigned short ipt = tj.EndPt[1] - ii;
3849  auto& tp = tj.Pts[ipt];
3850  if (tp.AveChg == 0) { tp.AveChg = lastAve; }
3851  else {
3852  lastAve = tp.AveChg;
3853  }
3854  } // ii
3855 
3856  tj.NeedsUpdate = false;
3857 
3858  } // UpdateTjChgProperties
TCConfig tcc
Definition: DataStructs.cxx:9
T abs(T value)
short nPtsAve
dump trajectory points
Definition: DataStructs.h:606
for($it=0;$it< $RaceTrack_number;$it++)
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:622
TCEvent evt
Definition: DataStructs.cxx:8
void tca::UpdateTraj ( TCSlice &  slc,
Trajectory &  tj 
)

Definition at line 669 of file StepUtils.cxx.

670  {
671  // Updates the last added trajectory point fit, average hit rms, etc.
672 
673  tj.NeedsUpdate = true;
674  tj.MaskedLastTP = false;
675 
676  if(tj.EndPt[1] < 1) return;
677 
678  if(tj.Strategy[kStiffEl]) {
679  UpdateStiffEl(slc, tj);
680  return;
681  }
682  unsigned int lastPt = tj.EndPt[1];
683  TrajPoint& lastTP = tj.Pts[lastPt];
684  // nothing needs to be done if the last point has no hits but is near a hit in the
685  // srcHit collection
686  if(lastTP.Hits.empty() && lastTP.Environment[kEnvNearSrcHit]) {
687  tj.NeedsUpdate = false;
688  return;
689  }
690  unsigned short npwc = NumPtsWithCharge(slc, tj, false);
691 
692  // find the previous TP that has hits (and was therefore in the fit)
693  unsigned short prevPtWithHits = USHRT_MAX;
694  unsigned short firstFitPt = tj.EndPt[0];
695  for(unsigned short ii = 1; ii < tj.Pts.size(); ++ii) {
696  unsigned short ipt = lastPt - ii;
697  if(tj.Pts[ipt].Chg > 0) {
698  prevPtWithHits = ipt;
699  break;
700  }
701  if(ipt == 0) break;
702  } // ii
703  if(prevPtWithHits == USHRT_MAX) return;
704 
705  // define the FitChi threshold above which something will be done
706  float maxChi = 2;
707  unsigned short minPtsFit = tcc.minPtsFit[tj.Pass];
708  // just starting out?
709  if(lastPt < 4) minPtsFit = 2;
710  bool cleanMuon = (tj.PDGCode == 13 && TrajIsClean(slc, tj, tcc.dbgStp) && !tj.Strategy[kSlowing]);
711  // was !TrajIsClean...
712  if(cleanMuon) {
713  // Fitting a clean muon
714  maxChi = tcc.maxChi;
715  minPtsFit = lastPt / 3;
716  }
717 
718  // Set the lastPT delta before doing the fit
719  lastTP.Delta = PointTrajDOCA(slc, lastTP.HitPos[0], lastTP.HitPos[1], lastTP);
720 
721  // update MCSMom. First ensure that nothing bad has happened
722  if(npwc > 3 && tj.Pts[lastPt].Chg > 0 && !tj.Strategy[kSlowing]) {
723  short newMCSMom = MCSMom(slc, tj);
724  short minMCSMom = 0.5 * tj.MCSMom;
725  if(lastPt > 10 && newMCSMom < minMCSMom) {
726  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"UT: MCSMom took a nose-dive "<<newMCSMom;
727  UnsetUsedHits(slc, lastTP);
728  DefineHitPos(slc, lastTP);
729  SetEndPoints(tj);
730  tj.NeedsUpdate = false;
731  return;
732  }
733  tj.MCSMom = newMCSMom;
734  } // npwc > 3
735 
736  if(tcc.dbgStp) {
737  mf::LogVerbatim("TC")<<"UT: lastPt "<<lastPt<<" lastTP.Delta "<<lastTP.Delta<<" previous point with hits "<<prevPtWithHits<<" tj.Pts size "<<tj.Pts.size()<<" AngleCode "<<lastTP.AngleCode<<" PDGCode "<<tj.PDGCode<<" maxChi "<<maxChi<<" minPtsFit "<<minPtsFit<<" MCSMom "<<tj.MCSMom;
738  }
739 
740  UpdateTjChgProperties("UT", slc, tj, tcc.dbgStp);
741 
742  if(lastPt == 1) {
743  // Handle the second trajectory point. No error calculation. Just update
744  // the position and direction
745  lastTP.NTPsFit = 2;
746  FitTraj(slc, tj);
747  lastTP.FitChi = 0.01;
748  lastTP.AngErr = tj.Pts[0].AngErr;
749  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"UT: Second traj point pos "<<lastTP.Pos[0]<<" "<<lastTP.Pos[1]<<" dir "<<lastTP.Dir[0]<<" "<<lastTP.Dir[1];
750  tj.NeedsUpdate = false;
751  SetAngleCode(lastTP);
752  return;
753  }
754 
755  if(lastPt == 2) {
756  // Third trajectory point. Keep it simple
757  lastTP.NTPsFit = 3;
758  FitTraj(slc, tj);
759  tj.NeedsUpdate = false;
760  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"UT: Third traj point fit "<<lastTP.FitChi;
761  SetAngleCode(lastTP);
762  return;
763  }
764 
765  // Fit with > 2 TPs
766  // Keep adding hits until Chi/DOF exceeds 1
767  if(tj.Pts[prevPtWithHits].FitChi < 1 && !tj.Strategy[kSlowing]) lastTP.NTPsFit += 1;
768  // Reduce the number of points fit if the trajectory is long and chisq is getting a bit larger
769  if(lastPt > 20 && tj.Pts[prevPtWithHits].FitChi > 1.5 && lastTP.NTPsFit > minPtsFit) lastTP.NTPsFit -= 2;
770  // don't let long muon fits get too long
771  if(cleanMuon && lastPt > 200 && tj.Pts[prevPtWithHits].FitChi > 1.0) lastTP.NTPsFit -= 2;
772  FitTraj(slc, tj);
773 
774  // don't get too fancy when we are starting out
775  if(lastPt < 6) {
776  tj.NeedsUpdate = false;
777  UpdateDeltaRMS(slc, tj);
778  SetAngleCode(lastTP);
779  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Return with lastTP.FitChi "<<lastTP.FitChi<<" Chg "<<lastTP.Chg;
780  return;
781  }
782 
783  // find the first point that was fit.
784  unsigned short cnt = 0;
785  for(unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
786  unsigned short ipt = lastPt - ii;
787  if(tj.Pts[ipt].Chg > 0) {
788  firstFitPt = ipt;
789  ++cnt;
790  }
791  if(cnt == lastTP.NTPsFit) break;
792  if(ipt == 0) break;
793  }
794 
795  unsigned short ndead = DeadWireCount(slc, lastTP.HitPos[0], tj.Pts[firstFitPt].HitPos[0], tj.CTP);
796  if(lastTP.FitChi > 1.5 && tj.Pts.size() > 6) {
797  // A large chisq jump can occur if we just jumped a large block of dead wires. In
798  // this case we don't want to mask off the last TP but reduce the number of fitted points
799  // This count will be off if there a lot of dead or missing wires...
800  // reduce the number of points significantly
801  if(ndead > 5 && !cleanMuon) {
802  if(lastTP.NTPsFit > 5) lastTP.NTPsFit = 5;
803  } else {
804  // Have a longish trajectory and chisq was a bit large.
805  // Was this a sudden occurrence and the fraction of TPs are included
806  // in the fit? If so, we should mask off this
807  // TP and keep going. If these conditions aren't met, we
808  // should reduce the number of fitted points
809  float chirat = 0;
810  if(prevPtWithHits != USHRT_MAX && tj.Pts[prevPtWithHits].FitChi > 0) chirat = lastTP.FitChi / tj.Pts[prevPtWithHits].FitChi;
811  // Don't mask hits when doing RevProp. Reduce NTPSFit instead
812  tj.MaskedLastTP = (chirat > 1.5 && lastTP.NTPsFit > 0.3 * NumPtsWithCharge(slc, tj, false) && !tj.AlgMod[kRvPrp]);
813  // BB April 19, 2018: Don't mask TPs on low MCSMom Tjs
814  if(tj.MaskedLastTP && tj.MCSMom < 30) tj.MaskedLastTP = false;
815  if(tcc.dbgStp) {
816  mf::LogVerbatim("TC")<<" First fit chisq too large "<<lastTP.FitChi<<" prevPtWithHits chisq "<<tj.Pts[prevPtWithHits].FitChi<<" chirat "<<chirat<<" NumPtsWithCharge "<<NumPtsWithCharge(slc, tj, false)<<" tj.MaskedLastTP "<<tj.MaskedLastTP;
817  }
818  // we should also mask off the last TP if there aren't enough hits
819  // to satisfy the minPtsFit constraint
820  if(!tj.MaskedLastTP && NumPtsWithCharge(slc, tj, true) < minPtsFit) tj.MaskedLastTP = true;
821  } // few dead wires
822  } // lastTP.FitChi > 2 ...
823 
824  // Deal with a really long trajectory that is in trouble (uB cosmic).
825  if(tj.PDGCode == 13 && lastTP.FitChi > tcc.maxChi) {
826  if(lastTP.NTPsFit > 1.3 * tcc.muonTag[0]) {
827  lastTP.NTPsFit *= 0.8;
828  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Muon - Reduce NTPsFit "<<lastPt;
829  } else {
830  tj.MaskedLastTP = true;
831  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Muon - mask last point "<<lastPt;
832  }
833  }
834 
835  if(tcc.dbgStp) mf::LogVerbatim("TC")<<"UT: First fit "<<lastTP.Pos[0]<<" "<<lastTP.Pos[1]<<" dir "<<lastTP.Dir[0]<<" "<<lastTP.Dir[1]<<" FitChi "<<lastTP.FitChi<<" NTPsFit "<<lastTP.NTPsFit<<" ndead wires "<<ndead<<" tj.MaskedLastTP "<<tj.MaskedLastTP;
836  if(tj.MaskedLastTP) {
837  UnsetUsedHits(slc, lastTP);
838  DefineHitPos(slc, lastTP);
839  SetEndPoints(tj);
840  lastPt = tj.EndPt[1];
841  lastTP.NTPsFit -= 1;
842  FitTraj(slc, tj);
843  UpdateTjChgProperties("UT", slc, tj, tcc.dbgStp);
844  SetAngleCode(lastTP);
845  return;
846  } else {
847  // a more gradual change in chisq. Maybe reduce the number of points
848  unsigned short newNTPSFit = lastTP.NTPsFit;
849  // reduce the number of points fit to keep Chisq/DOF < 2 adhering to the pass constraint
850  // and also a minimum number of points fit requirement for long muons
851  float prevChi = lastTP.FitChi;
852  unsigned short ntry = 0;
853  float chiCut = 1.5;
854  if(tj.Strategy[kStiffMu]) chiCut = 5;
855  while(lastTP.FitChi > chiCut && lastTP.NTPsFit > minPtsFit) {
856  if(lastTP.NTPsFit > 15) {
857  newNTPSFit = 0.7 * newNTPSFit;
858  } else if(lastTP.NTPsFit > 4) {
859  newNTPSFit -= 2;
860  } else {
861  newNTPSFit -= 1;
862  }
863  if(lastTP.NTPsFit < 3) newNTPSFit = 2;
864  if(newNTPSFit < minPtsFit) newNTPSFit = minPtsFit;
865  lastTP.NTPsFit = newNTPSFit;
866  // BB April 19: try to add a last lonely hit on a low MCSMom tj on the last try
867  if(newNTPSFit == minPtsFit && tj.MCSMom < 30) chiCut = 2;
868  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Bad FitChi "<<lastTP.FitChi<<" Reduced NTPsFit to "<<lastTP.NTPsFit<<" Pass "<<tj.Pass<<" chiCut "<<chiCut;
869  FitTraj(slc, tj);
870  tj.NeedsUpdate = true;
871  if(lastTP.FitChi > prevChi) {
872  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Chisq is increasing "<<lastTP.FitChi<<" Try to remove an earlier bad hit";
873  MaskBadTPs(slc, tj, chiCut);
874  ++ntry;
875  if(ntry == 2) break;
876  }
877  prevChi = lastTP.FitChi;
878  if(lastTP.NTPsFit == minPtsFit) break;
879  } // lastTP.FitChi > 2 && lastTP.NTPsFit > 2
880  }
881  // last ditch attempt if things look bad. Drop the last hit
882  if(tj.Pts.size() > tcc.minPtsFit[tj.Pass] && lastTP.FitChi > maxChi) {
883  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Last try. Drop last TP "<<lastTP.FitChi<<" NTPsFit "<<lastTP.NTPsFit;
884  UnsetUsedHits(slc, lastTP);
885  DefineHitPos(slc, lastTP);
886  SetEndPoints(tj);
887  lastPt = tj.EndPt[1];
888  FitTraj(slc, tj);
889  tj.MaskedLastTP = true;
890  }
891 
892  if(tj.NeedsUpdate) UpdateTjChgProperties("UT", slc, tj, tcc.dbgStp);
893 
894  if(tcc.dbgStp) mf::LogVerbatim("TC")<<" Fit done. Chi "<<lastTP.FitChi<<" NTPsFit "<<lastTP.NTPsFit;
895 
896  if(tj.EndPt[0] == tj.EndPt[1]) return;
897 
898  // Don't let the angle error get too small too soon. Stepping would stop if the first
899  // few hits on a low momentum wandering track happen to have a very good fit to a straight line.
900  // We will do this by averaging the default starting value of AngErr of the first TP with the current
901  // value from FitTraj.
902  if(lastPt < 14) {
903  float defFrac = 1 / (float)(tj.EndPt[1]);
904  lastTP.AngErr = defFrac * tj.Pts[0].AngErr + (1 - defFrac) * lastTP.AngErr;
905  }
906 
907  UpdateDeltaRMS(slc, tj);
908  SetAngleCode(lastTP);
909 
910  tj.NeedsUpdate = false;
911  return;
912 
913  } // UpdateTraj
short MCSMom(const TCSlice &slc, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3468
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3413
std::vector< unsigned short > minPtsFit
Reconstruct in several passes.
Definition: DataStructs.h:565
TCConfig tcc
Definition: DataStructs.cxx:9
void UnsetUsedHits(TCSlice &slc, TrajPoint &tp)
Definition: Utils.cxx:1075
void SetAngleCode(TrajPoint &tp)
Definition: Utils.cxx:773
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2572
bool dbgStp
debug stepping using debug.Cryostat, debug.TPC, etc
Definition: DataStructs.h:591
use the slowing-down strategy
Definition: DataStructs.h:503
bool TrajIsClean(TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3442
float DeadWireCount(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2)
Definition: Utils.cxx:2141
void DefineHitPos(TCSlice &slc, TrajPoint &tp)
Definition: StepUtils.cxx:1672
TP is near a hit in the srcHit collection but no allHit hit exists (DUNE disambiguation error) ...
Definition: DataStructs.h:525
void FitTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:808
void UpdateStiffEl(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:648
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3673
void MaskBadTPs(TCSlice &slc, Trajectory &tj, float const &maxChi)
Definition: StepUtils.cxx:2379
std::vector< short > muonTag
Definition: DataStructs.h:555
use the stiff electron strategy
Definition: DataStructs.h:501
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2116
void UpdateDeltaRMS(TCSlice &slc, Trajectory &tj)
Definition: StepUtils.cxx:2349
use the stiff muon strategy
Definition: DataStructs.h:502
void tca::UpdateVxEnvironment ( TCSlice &  slc)

Definition at line 3862 of file Utils.cxx.

3863  {
3864  // Set the kEnvOverlap bit true for all TPs that are close to other
3865  // trajectories that are close to vertices. The positions of TPs that
3866  // overlap are biased and shouldn't be used in a vertex fit. Also, these
3867  // TPs shouldn't be used to calculate dE/dx. The kEnvOverlap bit is first cleared
3868  // for ALL TPs and then set for ALL 2D vertices
3869 
3870  for (auto& tj : slc.tjs) {
3871  if (tj.AlgMod[kKilled]) continue;
3872  for (auto& tp : tj.Pts)
3873  tp.Environment[kEnvOverlap] = false;
3874  } // tj
3875 
3876  for (auto& vx : slc.vtxs) {
3877  if (vx.ID <= 0) continue;
3878  UpdateVxEnvironment(slc, vx, false);
3879  } // vx
3880 
3881  } // UpdateVxEnvironment
void UpdateVxEnvironment(TCSlice &slc)
Definition: Utils.cxx:3862
void tca::UpdateVxEnvironment ( TCSlice &  slc,
VtxStore &  vx2,
bool  prt 
)

Definition at line 3885 of file Utils.cxx.

3886  {
3887  // Update the Environment each TP on trajectories near the vertex
3888 
3889  if (vx2.ID == 0) return;
3890  if (vx2.Stat[kOnDeadWire]) return;
3891 
3892  if (prt) mf::LogVerbatim("TC") << "UpdateVxEnvironment check Tjs attached to vx2 " << vx2.ID;
3893 
3894  std::vector<int> tjlist;
3895  std::vector<unsigned short> tjends;
3896  if (vx2.Pos[0] < -0.4) return;
3897  unsigned int vxWire = std::nearbyint(vx2.Pos[0]);
3898  unsigned int loWire = vxWire;
3899  unsigned int hiWire = vxWire;
3900  for (auto& tj : slc.tjs) {
3901  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
3902  if (tj.CTP != vx2.CTP) continue;
3903  // ignore photon Tjs
3904  if (tj.AlgMod[kPhoton]) continue;
3905  for (unsigned short end = 0; end < 2; ++end) {
3906  if (tj.VtxID[end] != vx2.ID) continue;
3907  tjlist.push_back(tj.ID);
3908  tjends.push_back(end);
3909  if (tj.Pts[tj.EndPt[end]].Pos[0] < -0.4) return;
3910  unsigned int endWire = std::nearbyint(tj.Pts[tj.EndPt[end]].Pos[0]);
3911  if (endWire < loWire) loWire = endWire;
3912  if (endWire > hiWire) hiWire = endWire;
3913  } // end
3914  } // tj
3915  if (tjlist.size() < 2) return;
3916  if (hiWire < loWire + 1) return;
3917  if (prt)
3918  mf::LogVerbatim("TC") << " check Tjs on wires in the range " << loWire << " to " << hiWire;
3919 
3920  // create a vector of TPs between loWire and hiWire for every tj in the list
3921  // wire TP
3922  std::vector<std::vector<TrajPoint>> wire_tjpt;
3923  // companion vector of IDs
3924  std::vector<int> tjids;
3925  // populate this vector with TPs on Tjs that are in this range
3926  unsigned short nwires = hiWire - loWire + 1;
3927  for (unsigned short itj = 0; itj < tjlist.size(); ++itj) {
3928  auto& tj = slc.tjs[tjlist[itj] - 1];
3929  unsigned short end = tjends[itj];
3930  std::vector<TrajPoint> tjpt(nwires);
3931  // first enter valid TPs in the range
3932  for (unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
3933  unsigned short ipt;
3934  if (end == 0) { ipt = tj.EndPt[0] + ii; }
3935  else {
3936  ipt = tj.EndPt[1] - ii;
3937  }
3938  if (ipt > tj.Pts.size() - 1) break;
3939  // Make a copy of the TP so we can alter it
3940  auto tp = tj.Pts[ipt];
3941  if (tp.Chg <= 0) continue;
3942  tp.Chg = 1;
3943  tp.Hits.clear();
3944  if (tp.Pos[0] < -0.4) continue;
3945  unsigned int wire = std::nearbyint(tp.Pos[0]);
3946  unsigned short indx = wire - loWire;
3947  if (indx > nwires - 1) break;
3948  tp.Step = ipt;
3949  // We will use NTPsFit to count the number of neighboring TPs
3950  tp.NTPsFit = 0;
3951  tjpt[indx] = tp;
3952  } // ii
3953  // next make TPs on the wires that don't have real TPs
3954  TrajPoint ltp;
3955  // put ltp at the vertex position with direction towards the end point
3956  MakeBareTrajPoint(vx2.Pos, tj.Pts[tj.EndPt[end]].Pos, ltp);
3957  if (ltp.Dir[0] == 0) continue;
3958  if (ltp.Pos[0] < -0.4) continue;
3959  unsigned int wire = std::nearbyint(ltp.Pos[0]);
3960  ltp.Chg = 0;
3961  unsigned short indx = wire - loWire;
3962  // Break if we found a real TP
3963  if (tjpt[indx].Chg == 0) tjpt[indx] = ltp;
3964  double stepSize = std::abs(1 / ltp.Dir[0]);
3965  for (unsigned short ii = 0; ii < nwires; ++ii) {
3966  // move the local TP position by one step in the right direction
3967  for (unsigned short iwt = 0; iwt < 2; ++iwt)
3968  ltp.Pos[iwt] += ltp.Dir[iwt] * stepSize;
3969  if (ltp.Pos[0] < -0.4) break;
3970  wire = std::nearbyint(ltp.Pos[0]);
3971  if (wire < loWire || wire > hiWire) break;
3972  indx = wire - loWire;
3973  if (tjpt[indx].Chg > 0) continue;
3974  tjpt[indx] = ltp;
3975  } // ii
3976  if (prt) {
3977  mf::LogVerbatim myprt("TC");
3978  myprt << " T" << tj.ID;
3979  for (auto& tp : tjpt)
3980  myprt << " " << PrintPos(slc, tp.Pos) << "_" << tp.Step << "_" << (int)tp.Chg;
3981  }
3982  wire_tjpt.push_back(tjpt);
3983  tjids.push_back(tj.ID);
3984  } // itj
3985 
3986  // iterate over the wires in the range
3987  for (unsigned short indx = 0; indx < nwires; ++indx) {
3988  // count the number of valid points on this wire
3989  unsigned short npts = 0;
3990  // count the number of points on this wire that have charge
3991  unsigned short npwc = 0;
3992  for (unsigned short itj = 0; itj < wire_tjpt.size(); ++itj) {
3993  if (wire_tjpt[itj][indx].Pos[0] == 0) continue;
3994  // found a valid point
3995  ++npts;
3996  if (wire_tjpt[itj][indx].Chg > 0) ++npwc;
3997  } // itj
3998  // no valid points
3999  if (npts == 0) continue;
4000  // all valid points have charge
4001  if (npwc == npts) continue;
4002  // re-find the valid points with charge and set the kEnvOverlap bit
4003  for (unsigned short itj = 0; itj < wire_tjpt.size(); ++itj) {
4004  if (wire_tjpt[itj][indx].Pos[0] == 0) continue;
4005  if (wire_tjpt[itj][indx].Chg == 0) continue;
4006  auto& tj = slc.tjs[tjids[itj] - 1];
4007  unsigned short ipt = wire_tjpt[itj][indx].Step;
4008  tj.Pts[ipt].Environment[kEnvOverlap] = true;
4009  tj.NeedsUpdate = true;
4010  if (prt) mf::LogVerbatim("TC") << " Set kEnvOverlap bit on T" << tj.ID << " ipt " << ipt;
4011  } // itj
4012  } // indx
4013 
4014  // update the charge rms for those tjs whose environment was changed above
4015  // (or elsewhere)
4016  for (auto tjid : tjids) {
4017  auto& tj = slc.tjs[tjid - 1];
4018  if (!tj.NeedsUpdate) continue;
4019  if (tj.CTP != vx2.CTP) continue;
4020  UpdateTjChgProperties("UVxE", slc, tj, prt);
4021  } // tjid
4022 
4023  } // UpdateVxEnvironment
then if[["$THISISATEST"==1]]
Definition: neoSmazza.sh:95
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6526
bool MakeBareTrajPoint(const TCSlice &slc, unsigned int fromHit, unsigned int toHit, TrajPoint &tp)
Definition: Utils.cxx:4110
T abs(T value)
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
void UpdateTjChgProperties(std::string inFcnLabel, TCSlice &slc, Trajectory &tj, bool prt)
Definition: Utils.cxx:3673
bool tca::ValidTwoPlaneMatch ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice &  slc,
const PFPStruct &  pfp 
)

Definition at line 1797 of file PFPUtils.cxx.

1800  {
1801  // This function checks the third plane in the PFP when only two Tjs are 3D-matched to
1802  // ensure that the reason for the lack of a 3rd plane match is that it is in a dead region.
1803  // This function should be used after an initial fit is done and the TP3Ds are sorted
1804  if (pfp.TjIDs.size() != 2) return false;
1805  if (slc.nPlanes != 3) return false;
1806  if (pfp.TP3Ds.empty()) return false;
1807 
1808  // find the third plane
1809  std::vector<unsigned short> planes;
1810  for (auto tid : pfp.TjIDs)
1811  planes.push_back(DecodeCTP(slc.tjs[tid - 1].CTP).Plane);
1812  unsigned short thirdPlane = 3 - planes[0] - planes[1];
1813  CTP_t inCTP = EncodeCTP(slc.TPCID.Cryostat, slc.TPCID.TPC, thirdPlane);
1814  // Project the 3D position at the start into the third plane
1815  auto tp = MakeBareTP(detProp, slc, pfp.TP3Ds[0].Pos, inCTP);
1816  unsigned int wire0 = 0;
1817  if (tp.Pos[0] > 0) wire0 = std::nearbyint(tp.Pos[0]);
1818  if (wire0 > slc.nWires[thirdPlane]) wire0 = slc.nWires[thirdPlane];
1819  // Do the same for the end
1820  unsigned short lastPt = pfp.TP3Ds.size() - 1;
1821  tp = MakeBareTP(detProp, slc, pfp.TP3Ds[lastPt].Pos, inCTP);
1822  unsigned int wire1 = 0;
1823  if (tp.Pos[0] > 0) wire1 = std::nearbyint(tp.Pos[0]);
1824  if (wire1 > slc.nWires[thirdPlane]) wire1 = slc.nWires[thirdPlane];
1825  if (wire0 == wire1) return !evt.goodWire[thirdPlane][wire0];
1826  if (wire1 < wire0) std::swap(wire0, wire1);
1827  // count the number of good wires
1828  int dead = 0;
1829  int wires = wire1 - wire0;
1830  for (unsigned int wire = wire0; wire < wire1; ++wire)
1831  if (!evt.goodWire[thirdPlane][wire]) ++dead;
1832  // require that most of the wires are dead
1833  return (dead > 0.8 * wires);
1834  } // ValidTwoPlaneMatch
TrajPoint MakeBareTP(detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, const Point3_t &pos, CTP_t inCTP)
Definition: Utils.cxx:4027
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:630
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
BEGIN_PROLOG Z planes
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:52
TCEvent evt
Definition: DataStructs.cxx:8
auto const detProp
float tca::VertexVertexPull ( const TCSlice &  slc,
const Vtx3Store &  vx1,
const Vtx3Store &  vx2 
)

Definition at line 1887 of file TCVertex.cxx.

1888  {
1889  // Calculates the position pull between two vertices
1890  double dx = vx1.X - vx2.X;
1891  double dy = vx1.Y - vx2.Y;
1892  double dz = vx1.Z - vx2.Z;
1893  double dxErr2 = (vx1.XErr * vx1.XErr + vx2.XErr * vx2.XErr) / 2;
1894  double dyErr2 = (vx1.YErr * vx1.YErr + vx2.YErr * vx2.YErr) / 2;
1895  double dzErr2 = (vx1.ZErr * vx1.ZErr + vx2.ZErr * vx2.ZErr) / 2;
1896  dx = dx * dx / dxErr2;
1897  dy = dy * dy / dyErr2;
1898  dz = dz * dz / dzErr2;
1899  return (float)(sqrt(dx + dy + dz) / 3);
1900  }
float tca::VertexVertexPull ( const TCSlice &  slc,
const VtxStore &  vx1,
const VtxStore &  vx2 
)

Definition at line 1904 of file TCVertex.cxx.

1905  {
1906  // Calculates the position pull between two vertices
1907  double dw = vx1.Pos[0] - vx2.Pos[0];
1908  double dt = vx1.Pos[1] - vx2.Pos[1];
1909  double dwErr2 = (vx1.PosErr[0] * vx1.PosErr[0] + vx2.PosErr[0] * vx2.PosErr[0]) / 2;
1910  double dtErr2 = (vx1.PosErr[1] * vx1.PosErr[1] + vx2.PosErr[1] * vx2.PosErr[1]) / 2;
1911  dw = dw * dw / dwErr2;
1912  dt = dt * dt / dtErr2;
1913  return (float)sqrt(dw + dt);
1914  }
bool tca::WireHitRangeOK ( TCSlice &  slc,
const CTP_t &  inCTP 
)

Definition at line 4653 of file Utils.cxx.

4654  {
4655  // returns true if the passed CTP code is consistent with the CT code of the WireHitRangeVector
4656  geo::PlaneID planeID = DecodeCTP(inCTP);
4657  if (planeID.Cryostat != slc.TPCID.Cryostat) return false;
4658  if (planeID.TPC != slc.TPCID.TPC) return false;
4659  return true;
4660  }
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:212
geo::PlaneID DecodeCTP(CTP_t CTP)
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:406
bool tca::WrongSplitTj ( std::string  inFcnLabel,
TCSlice &  slc,
Trajectory &  tj,
unsigned short  tjEnd,
ShowerStruct &  ss,
bool  prt 
)

Definition at line 2268 of file TCShower.cxx.

2274  {
2275  // Returns true if the trajectory was split by a 3D vertex match and the end of this trajectory is further
2276  // away from the shower than the partner trajectory
2277  // Here is a cartoon showing what we are trying to prevent. The shower is represented by a box. The trajectory
2278  // that is shown as (---*---) was originally reconstructed as a single trajectory. It was later split at the * position
2279  // 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
2280  // the shower. Tj is more likely to be the real parent
2281  //
2282  // 1111111111 2222222 TjID
2283  // 0 1 0 1 Tj end
2284  // --------------
2285  // | |
2286  // ----------*------- |
2287  // | |
2288  // --------------
2289  if (!tj.AlgMod[kComp3DVx]) return false;
2290  if (tjEnd > 1) return false;
2291 
2292  std::string fcnLabel = inFcnLabel + ".WSTj";
2293 
2294  // See if the other end is the end that was split. It should have a vertex with Topo = 8 or 11
2295  unsigned short otherEnd = 1 - tjEnd;
2296  // if(prt) mf::LogVerbatim("TC")<<"WSTj: otherEnd "<<otherEnd<<" vtxID "<<tj.VtxID[otherEnd];
2297  if (tj.VtxID[otherEnd] == 0) return false;
2298  unsigned short ivx = tj.VtxID[otherEnd] - 1;
2299  // A vertex exists but not a 3D split vertex
2300  if (slc.vtxs[ivx].Topo != 8 && slc.vtxs[ivx].Topo != 10) return false;
2301  if (prt)
2302  mf::LogVerbatim("TC") << fcnLabel << " Primary candidate " << tj.ID
2303  << " was split by a 3D vertex";
2304  return true;
2305 
2306  } // WrongSplitTj

Variable Documentation

const std::vector< std::string > tca::AlgBitNames

Definition at line 16 of file DataStructs.cxx.

constexpr unsigned int tca::Cpad = 10000

Definition at line 49 of file DataStructs.h.

DebugStuff tca::debug

Definition at line 4 of file DebugStruct.cxx.

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

Definition at line 88 of file DataStructs.cxx.

TCEvent tca::evt

Definition at line 8 of file DataStructs.cxx.

constexpr unsigned int tca::pAlgModSize = 6

Definition at line 280 of file DataStructs.h.

std::vector< TrajPoint > tca::seeds

Definition at line 14 of file DataStructs.cxx.

std::vector< TCSlice > tca::slices

Definition at line 13 of file DataStructs.cxx.

const std::vector< std::string > tca::StrategyBitNames
Initial value:
{
"Normal",
"StiffEl",
"StiffMu",
"Slowing"
}

Definition at line 109 of file DataStructs.cxx.

ShowerTreeVars tca::stv

Definition at line 11 of file DataStructs.cxx.

TCConfig tca::tcc

Definition at line 9 of file DataStructs.cxx.

std::vector< TjForecast > tca::tjfs

Definition at line 10 of file DataStructs.cxx.

constexpr unsigned int tca::Tpad = 10

Definition at line 48 of file DataStructs.h.

const std::vector< std::string > tca::VtxBitNames
Initial value:
{
"VxTrjTried",
"Fixed",
"OnDeadWire",
"HiVx3Score",
"VxTruMatch",
"VxMerged",
"VxIndPlnNoChg",
"VxEnvOK"
}

Definition at line 98 of file DataStructs.cxx.