Classes | Typedefs | Enumerations | Functions | Variables
tca Namespace Reference

Classes

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

Typedefs

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

Enumerations

enum  HitStatus_t { kAllHits, kUsedHits, kUnusedHits }
 

Functions

geo::PlaneID DecodeCTP (CTP_t CTP)
 
CTP_t EncodeCTP (unsigned int cryo, unsigned int tpc, unsigned int plane)
 
CTP_t EncodeCTP (const geo::PlaneID &planeID)
 
CTP_t EncodeCTP (const geo::WireID &wireID)
 
void StitchPFPs ()
 
void FindPFParticles (detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, TCSlice &slc)
 
void MakePFParticles (detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, std::vector< MatchStruct > matVec, unsigned short matVec_Iter)
 
bool ReconcileTPs (TCSlice &slc, PFPStruct &pfp, bool prt)
 
void ReconcileTPs (TCSlice &slc)
 
void MakePFPTjs (TCSlice &slc)
 
void FillWireIntersections (TCSlice &slc)
 
bool TCIntersectionPoint (unsigned int wir1, unsigned int wir2, unsigned int pln1, unsigned int pln2, float &y, float &z)
 
void Match3PlanesSpt (TCSlice &slc, std::vector< MatchStruct > &matVec)
 
bool SptInTPC (const std::array< unsigned int, 3 > &sptHits, unsigned int tpc)
 
void Match3Planes (TCSlice &slc, std::vector< MatchStruct > &matVec)
 
void Match2Planes (TCSlice &slc, std::vector< MatchStruct > &matVec)
 
bool Update (detinfo::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)
 
bool valDecreasing (SortEntry c1, SortEntry c2)
 
bool valIncreasing (SortEntry c1, SortEntry c2)
 
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::stringAlgBitNames
 
const std::vector< std::stringEndFlagNames
 
const std::vector< std::stringVtxBitNames
 
const std::vector< std::stringStrategyBitNames
 
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 49 of file DataStructs.h.

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

Definition at line 45 of file DataStructs.h.

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

Definition at line 43 of file DataStructs.h.

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

Definition at line 46 of file DataStructs.h.

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

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

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

don't mess with this line

Definition at line 509 of file DataStructs.h.

509  {
510  kSignal,
511  kAtKink,
512  kAtVtx,
513  kBragg,
514  kAtTj,
515  kOutFV,
516  kNoFitVx,
517  kFlagBitSize ///< don't mess with this line
518  } EndFlag_t;
don&#39;t mess with this line
Definition: DataStructs.h:517
EndFlag_t
Definition: DataStructs.h:509
Enumerator
kAllHits 
kUsedHits 
kUnusedHits 

Definition at line 40 of file Utils.h.

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

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

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

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

Definition at line 268 of file DataStructs.h.

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

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

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

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

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

Definition at line 1037 of file StepUtils.cxx.

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

Definition at line 1214 of file StepUtils.cxx.

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

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

Definition at line 1384 of file TCShower.cxx.

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

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

Definition at line 1446 of file TCShower.cxx.

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

Definition at line 3549 of file TCShower.cxx.

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

Definition at line 4392 of file Utils.cxx.

4393  {
4394  // Find the average hit rms by analyzing the full hit collection. This
4395  // only needs to be done once per job.
4396 
4397  if ((*evt.allHits).empty()) return true;
4398  // no sense re-calculating it if it's been done
4399  if (evt.aveHitRMSValid) return true;
4400 
4401  unsigned short cstat = (*evt.allHits)[0].WireID().Cryostat;
4402  unsigned short tpc = (*evt.allHits)[0].WireID().TPC;
4403 
4404  unsigned short nplanes = tcc.geom->Nplanes(tpc, cstat);
4405  evt.aveHitRMS.resize(nplanes);
4406  std::vector<float> cnt(nplanes, 0);
4407  for (unsigned short iht = 0; iht < (*evt.allHits).size(); ++iht) {
4408  auto& hit = (*evt.allHits)[iht];
4409  unsigned short plane = hit.WireID().Plane;
4410  if (plane > nplanes - 1) return false;
4411  if (cnt[plane] > 200) continue;
4412  // require multiplicity one
4413  if (hit.Multiplicity() != 1) continue;
4414  // not-crazy Chisq/DOF
4415  if (hit.GoodnessOfFit() < 0 || hit.GoodnessOfFit() > 500) continue;
4416  // don't let a lot of runt hits screw up the calculation
4417  if (hit.PeakAmplitude() < 1) continue;
4418  evt.aveHitRMS[plane] += hit.RMS();
4419  ++cnt[plane];
4420  // quit if enough hits are found
4421  bool allDone = true;
4422  for (unsigned short plane = 0; plane < nplanes; ++plane)
4423  if (cnt[plane] < 200) allDone = false;
4424  if (allDone) break;
4425  } // iht
4426 
4427  // assume there are enough hits in each plane
4428  evt.aveHitRMSValid = true;
4429  for (unsigned short plane = 0; plane < nplanes; ++plane) {
4430  if (cnt[plane] > 4) { evt.aveHitRMS[plane] /= cnt[plane]; }
4431  else {
4432  evt.aveHitRMS[plane] = 10;
4433  evt.aveHitRMSValid = false;
4434  } // cnt too low
4435  } // plane
4436 
4437  if (tcc.modes[kDebug]) {
4438  std::cout << "Analyze hits aveHitRMS";
4439  std::cout << std::fixed << std::setprecision(1);
4440  for (auto rms : evt.aveHitRMS)
4441  std::cout << " " << rms;
4442  std::cout << " aveHitRMSValid? " << evt.aveHitRMSValid << "\n";
4443  }
4444 
4445  return true;
4446  } // Analyze hits
double rms(sqlite3 *db, std::string const &table_name, std::string const &column_name)
Definition: statistics.cc:40
TCConfig tcc
Definition: DataStructs.cxx:8
Q_EXPORT QTSManip setprecision(int p)
Definition: qtextstream.h:343
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
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:640
const geo::GeometryCore * geom
Definition: DataStructs.h:578
Detector simulation of raw signals on wires.
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:609
bool aveHitRMSValid
set true when the average hit RMS is well-known
Definition: DataStructs.h:649
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:624
TCEvent evt
Definition: DataStructs.cxx:7
master switch for turning on debug mode
Definition: DataStructs.h:535
bool tca::AnalyzeRotPos ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct ss,
bool  prt 
)

Definition at line 3060 of file TCShower.cxx.

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

Definition at line 764 of file Utils.cxx.

765  {
766  return AngleRange(tp.Ang);
767  }
unsigned short AngleRange(float angle)
Definition: Utils.cxx:791
unsigned short tca::AngleRange ( float  angle)

Definition at line 791 of file Utils.cxx.

792  {
793  // returns the index of the angle range
794  if (angle > M_PI) angle = M_PI;
795  if (angle < -M_PI) angle = M_PI;
796  if (angle < 0) angle = -angle;
797  if (angle > M_PI / 2) angle = M_PI - angle;
798  for (unsigned short ir = 0; ir < tcc.angleRanges.size(); ++ir) {
799  if (angle < tcc.angleRanges[ir]) return ir;
800  }
801  return tcc.angleRanges.size() - 1;
802  } // AngleRange
TCConfig tcc
Definition: DataStructs.cxx:8
std::vector< float > angleRanges
list of max angles for each angle range
Definition: DataStructs.h:571
#define M_PI
Definition: includeROOT.h:54
bool tca::AttachAnyTrajToVertex ( TCSlice slc,
unsigned short  ivx,
bool  prt 
)

Definition at line 1697 of file TCVertex.cxx.

1698  {
1699 
1700  if (ivx > slc.vtxs.size() - 1) return false;
1701  if (slc.vtxs[ivx].ID == 0) return false;
1702  if (tcc.vtx2DCuts[0] < 0) return false;
1703 
1704  VtxStore& vx = slc.vtxs[ivx];
1705  // Hammer vertices should be isolated and clean
1706  if (vx.Topo == 5 || vx.Topo == 6) return false;
1707 
1708  unsigned short bestTj = USHRT_MAX;
1709  // Construct a FOM = (TP-Vtx pull) * (TP-Vtx sep + 1).
1710  // The +1 keeps FOM from being 0
1711  float bestFOM = 2 * tcc.vtx2DCuts[3] * (tcc.vtx2DCuts[0] + 1);
1712  for (unsigned int itj = 0; itj < slc.tjs.size(); ++itj) {
1713  auto& tj = slc.tjs[itj];
1714  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
1715  if (tj.CTP != vx.CTP) continue;
1716  // make some rough cuts
1717  std::array<float, 2> sep;
1718  sep[0] = PosSep(vx.Pos, tj.Pts[tj.EndPt[0]].Pos);
1719  sep[1] = PosSep(vx.Pos, tj.Pts[tj.EndPt[1]].Pos);
1720  unsigned short end = 0;
1721  if (sep[1] < sep[0]) end = 1;
1722  if (sep[end] > 100) continue;
1723  if (tj.VtxID[end] > 0) continue;
1724  auto& tp = tj.Pts[tj.EndPt[end]];
1725  // Pad the separation a bit so we don't get zero
1726  float fom = TrajPointVertexPull(slc, tp, vx) * (sep[end] + 1);
1727  if (fom > bestFOM) continue;
1728  if (prt) {
1729  mf::LogVerbatim("TC") << "AATTV: T" << tj.ID << " 2V" << vx.ID << " Topo " << vx.Topo
1730  << " FOM " << fom << " cut " << bestFOM;
1731  }
1732  bestTj = itj;
1733  bestFOM = fom;
1734  } // tj
1735  if (bestTj > slc.tjs.size() - 1) return false;
1736  auto& tj = slc.tjs[bestTj];
1737  return AttachTrajToVertex(slc, tj, vx, prt);
1738  } // AttachAnyTrajToVertex
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float TrajPointVertexPull(const TCSlice &slc, const TrajPoint &tp, const VtxStore &vx)
Definition: TCVertex.cxx:1865
TCConfig tcc
Definition: DataStructs.cxx:8
bool AttachTrajToVertex(TCSlice &slc, Trajectory &tj, VtxStore &vx, bool prt)
Definition: TCVertex.cxx:1742
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2564
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:552
bool tca::AttachAnyVertexToTraj ( TCSlice slc,
int  tjID,
bool  prt 
)

Definition at line 1655 of file TCVertex.cxx.

1656  {
1657  // Try to attach a tj that is stored in slc.tjs with any vertex
1658  if (tjID <= 0 || tjID > (int)slc.tjs.size()) return false;
1659  if (slc.vtxs.empty()) return false;
1660  auto& tj = slc.tjs[tjID - 1];
1661  if (tj.AlgMod[kKilled]) return false;
1662  if (tcc.vtx2DCuts[0] <= 0) return false;
1663 
1664  unsigned short bestVx = USHRT_MAX;
1665  // Construct a FOM = (TP-Vtx pull) * (TP-Vtx sep + 1) * (Vtx Score).
1666  // The +1 keeps FOM from being 0
1667  float bestFOM = 2 * tcc.vtx2DCuts[3] * (tcc.vtx2DCuts[0] + 1) * tcc.vtx2DCuts[7];
1668  for (unsigned short ivx = 0; ivx < slc.vtxs.size(); ++ivx) {
1669  auto& vx = slc.vtxs[ivx];
1670  if (vx.ID == 0) continue;
1671  if (vx.CTP != tj.CTP) continue;
1672  // make some rough cuts
1673  std::array<float, 2> sep;
1674  sep[0] = PosSep(vx.Pos, tj.Pts[tj.EndPt[0]].Pos);
1675  sep[1] = PosSep(vx.Pos, tj.Pts[tj.EndPt[1]].Pos);
1676  unsigned short end = 0;
1677  if (sep[1] < sep[0]) end = 1;
1678  if (sep[end] > 100) continue;
1679  if (tj.VtxID[end] > 0) continue;
1680  auto& tp = tj.Pts[tj.EndPt[end]];
1681  // Pad the separation a bit so we don't get zero
1682  float fom = TrajPointVertexPull(slc, tp, vx) * (sep[end] + 1) * vx.Score;
1683  if (fom > bestFOM) continue;
1684  if (prt)
1685  mf::LogVerbatim("TC") << "AAVTT: T" << tjID << " 2V" << vx.ID << " FOM " << fom << " cut "
1686  << bestFOM;
1687  bestVx = ivx;
1688  bestFOM = fom;
1689  } // vx
1690  if (bestVx > slc.vtxs.size() - 1) return false;
1691  auto& vx = slc.vtxs[bestVx];
1692  return AttachTrajToVertex(slc, tj, vx, prt);
1693  } // AttachAnyVertexToTraj
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float TrajPointVertexPull(const TCSlice &slc, const TrajPoint &tp, const VtxStore &vx)
Definition: TCVertex.cxx:1865
TCConfig tcc
Definition: DataStructs.cxx:8
bool AttachTrajToVertex(TCSlice &slc, Trajectory &tj, VtxStore &vx, bool prt)
Definition: TCVertex.cxx:1742
for(std::string line;std::getline(inFile, line);)
Definition: regex_t.cc:37
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2564
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:552
if(!yymsg) yymsg
bool tca::AttachToAnyVertex ( TCSlice slc,
PFPStruct pfp,
float  maxSep,
bool  prt 
)

Definition at line 1597 of file TCVertex.cxx.

1598  {
1599  // Attaches to any 3D vertex but doesn't require consistency with
1600  // PFP -> Tj -> 2V -> 3V assns
1601  if (pfp.ID <= 0) return false;
1602 
1603  float pLen = Length(pfp);
1604  if (pLen == 0) return false;
1605 
1606  // save the old assignents and clear them
1607  // auto oldVx3ID = pfp.Vx3ID;
1608  for (unsigned short end = 0; end < 2; ++end)
1609  pfp.Vx3ID[end] = 0;
1610  std::array<Point3_t, 2> endPos;
1611  endPos[0] = PosAtEnd(pfp, 0);
1612  endPos[1] = PosAtEnd(pfp, 1);
1613 
1614  std::array<float, 2> foms{{100., 100.}};
1615  std::array<int, 2> vtxs{{0}};
1616  for (auto& vx3 : slc.vtx3s) {
1617  if (vx3.ID <= 0) continue;
1618  if (vx3.TPCID != pfp.TPCID) continue;
1619  std::array<float, 2> sep;
1620  Point3_t vpos = {{vx3.X, vx3.Y, vx3.Z}};
1621  sep[0] = PosSep(vpos, endPos[0]);
1622  sep[1] = PosSep(vpos, endPos[1]);
1623  unsigned short end = 0;
1624  if (sep[1] < sep[0]) end = 1;
1625  // ignore if separation is too large
1626  if (sep[end] > 100) continue;
1627  // find the direction vector between these points
1628  auto vpDir = PointDirection(vpos, endPos[end]);
1629  auto dir = DirAtEnd(pfp, end);
1630  double dotp = std::abs(DotProd(vpDir, dir));
1631  float fom = dotp * sep[end];
1632  if (prt)
1633  mf::LogVerbatim("TC") << "ATAV: P" << pfp.ID << " end " << end << " 3V" << vx3.ID << " sep "
1634  << sep[end] << " fom " << fom << " maxSep " << maxSep;
1635  // ignore if separation is too large
1636  if (sep[end] > maxSep) continue;
1637  if (fom < foms[end]) {
1638  foms[end] = fom;
1639  vtxs[end] = vx3.ID;
1640  }
1641  } // vx3
1642  bool bingo = false;
1643  for (unsigned short end = 0; end < 2; ++end) {
1644  if (vtxs[end] == 0) continue;
1645  if (prt)
1646  mf::LogVerbatim("TC") << "ATAV: set P" << pfp.ID << " end " << end << " -> 3V" << vtxs[end];
1647  pfp.Vx3ID[end] = vtxs[end];
1648  bingo = true;
1649  } // end
1650  return bingo;
1651  } // AttachToAnyVertex
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float Length(const PFPStruct &pfp)
Definition: PFPUtils.cxx:3303
std::array< double, 3 > Point3_t
Definition: DataStructs.h:43
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3292
string dir
T abs(T value)
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:2547
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:2564
Vector3_t DirAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3283
bool tca::AttachTrajToVertex ( TCSlice slc,
Trajectory tj,
VtxStore vx,
bool  prt 
)

Definition at line 1742 of file TCVertex.cxx.

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

Definition at line 2649 of file PFPUtils.cxx.

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

Definition at line 1442 of file Utils.cxx.

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

Definition at line 1342 of file PFPUtils.cxx.

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

Definition at line 2307 of file StepUtils.cxx.

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

Definition at line 2165 of file StepUtils.cxx.

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

Definition at line 914 of file StepUtils.cxx.

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

Definition at line 927 of file StepUtils.cxx.

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

Definition at line 1335 of file Utils.cxx.

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

Definition at line 1839 of file Utils.cxx.

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

Definition at line 3196 of file PFPUtils.cxx.

3200  {
3201  // Step between pos1 and pos2 and find the fraction of the points that have nearby hits
3202  // in each plane. This function returns -1 if something is fishy, but this doesn't mean
3203  // that there is no charge. Note that there is no check for charge precisely at the pos1 and pos2
3204  // positions
3205  float sep = PosSep(pos1, pos2);
3206  if (sep == 0) return -1;
3207  unsigned short nstep = sep / tcc.wirePitch;
3208  auto dir = PointDirection(pos1, pos2);
3209  float sum = 0;
3210  float cnt = 0;
3211  TrajPoint tp;
3212  for (unsigned short step = 0; step < nstep; ++step) {
3213  for (unsigned short xyz = 0; xyz < 3; ++xyz)
3214  pos1[xyz] += tcc.wirePitch * dir[xyz];
3215  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
3216  tp.CTP = EncodeCTP(slc.TPCID.Cryostat, slc.TPCID.TPC, plane);
3217  tp.Pos[0] =
3218  tcc.geom->WireCoordinate(pos1[1], pos1[2], plane, slc.TPCID.TPC, slc.TPCID.Cryostat);
3219  tp.Pos[1] = detProp.ConvertXToTicks(pos1[0], plane, slc.TPCID.TPC, slc.TPCID.Cryostat) *
3220  tcc.unitsPerTick;
3221  ++cnt;
3222  if (SignalAtTp(tp)) ++sum;
3223  } // plane
3224  } // step
3225  if (cnt == 0) return -1;
3226  return sum / cnt;
3227  } // 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:2002
TCConfig tcc
Definition: DataStructs.cxx:8
string dir
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:573
Vector3_t PointDirection(const Point3_t p1, const Point3_t p2)
Definition: PFPUtils.cxx:2547
const geo::GeometryCore * geom
Definition: DataStructs.h:578
for(std::string line;std::getline(inFile, line);)
Definition: regex_t.cc:37
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2564
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:54
float tca::ChgFracNearEnd ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice slc,
const PFPStruct pfp,
unsigned short  end 
)

Definition at line 3231 of file PFPUtils.cxx.

3235  {
3236  // returns the charge fraction near the end of the pfp. Note that this function
3237  // assumes that there is only one Tj in a plane.
3238  if (pfp.ID == 0) return 0;
3239  if (pfp.TjIDs.empty()) return 0;
3240  if (end < 0 || end > 1) return 0;
3241  if (pfp.TPCID != slc.TPCID) return 0;
3242  if (pfp.SectionFits.empty()) return 0;
3243 
3244  float sum = 0;
3245  float cnt = 0;
3246  // keep track of the lowest value and maybe reject it
3247  float lo = 1;
3248  float hi = 0;
3249  auto pos3 = PosAtEnd(pfp, end);
3250  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane) {
3251  CTP_t inCTP = EncodeCTP(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
3252  std::vector<int> tjids(1);
3253  for (auto tjid : pfp.TjIDs) {
3254  auto& tj = slc.tjs[tjid - 1];
3255  if (tj.CTP != inCTP) continue;
3256  tjids[0] = tjid;
3257  Point2_t pos2;
3258  geo::PlaneID planeID = geo::PlaneID(pfp.TPCID.Cryostat, pfp.TPCID.TPC, plane);
3259  pos2[0] = tcc.geom->WireCoordinate(pos3[1], pos3[2], planeID);
3260  if (pos2[0] < -0.4) continue;
3261  // check for dead wires
3262  unsigned int wire = std::nearbyint(pos2[0]);
3263  if (wire > slc.nWires[plane]) continue;
3264  if (slc.wireHitRange[plane][wire].first == UINT_MAX) continue;
3265  pos2[1] = detProp.ConvertXToTicks(pos3[0], planeID) * tcc.unitsPerTick;
3266  float cf = ChgFracNearPos(slc, pos2, tjids);
3267  if (cf < lo) lo = cf;
3268  if (cf > hi) hi = cf;
3269  sum += cf;
3270  ++cnt;
3271  } // tjid
3272  } // plane
3273  if (cnt == 0) return 0;
3274  if (cnt > 1 && lo < 0.3 && hi > 0.8) {
3275  sum -= lo;
3276  --cnt;
3277  }
3278  return sum / cnt;
3279  } // 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.
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
TCConfig tcc
Definition: DataStructs.cxx:8
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:3292
std::array< float, 2 > Point2_t
Definition: DataStructs.h:45
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:573
float ChgFracNearPos(const TCSlice &slc, const Point2_t &pos, const std::vector< int > &tjIDs)
Definition: Utils.cxx:3234
const geo::GeometryCore * geom
Definition: DataStructs.h:578
unsigned int CTP_t
Definition: DataStructs.h:49
CTP_t EncodeCTP(unsigned int cryo, unsigned int tpc, unsigned int plane)
Definition: DataStructs.h:54
detail::Node< FrameID, bool > PlaneID
Definition: CRTID.h:125
float tca::ChgFracNearPos ( const TCSlice slc,
const Point2_t pos,
const std::vector< int > &  tjIDs 
)

Definition at line 3234 of file Utils.cxx.

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

Definition at line 3980 of file TCShower.cxx.

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

Definition at line 4155 of file TCShower.cxx.

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

Definition at line 2672 of file StepUtils.cxx.

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

Definition at line 1739 of file Utils.cxx.

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

Definition at line 1705 of file Utils.cxx.

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

Definition at line 3809 of file StepUtils.cxx.

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

Definition at line 3703 of file StepUtils.cxx.

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

Definition at line 1560 of file StepUtils.cxx.

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

Definition at line 2085 of file TCVertex.cxx.

2086  {
2087  // Check the associations
2088 
2089  // check the 2D -> 3D associations
2090  geo::PlaneID planeID = DecodeCTP(inCTP);
2091  unsigned short plane = planeID.Plane;
2092  for (auto& vx2 : slc.vtxs) {
2093  if (vx2.CTP != inCTP) continue;
2094  if (vx2.ID == 0) continue;
2095  if (vx2.Vx3ID == 0) continue;
2096  if (vx2.Vx3ID > int(slc.vtx3s.size())) {
2097  mf::LogVerbatim("TC") << "ChkVtxAssociations: Invalid vx2.Vx3ID " << vx2.Vx3ID
2098  << " in 2D vtx " << vx2.ID;
2099  return false;
2100  }
2101  auto& vx3 = slc.vtx3s[vx2.Vx3ID - 1];
2102  if (vx3.ID == 0) {
2103  mf::LogVerbatim("TC") << "ChkVtxAssociations: 2V" << vx2.ID << " thinks it is matched to 3V"
2104  << vx3.ID << " but vx3 is obsolete";
2105  return false;
2106  }
2107  if (vx3.Vx2ID[plane] != vx2.ID) {
2108  mf::LogVerbatim("TC") << "ChkVtxAssociations: 2V" << vx2.ID << " thinks it is matched to 3V"
2109  << vx3.ID << " but vx3 says no!";
2110  return false;
2111  }
2112  } // vx2
2113  // check the 3D -> 2D associations
2114  for (auto& vx3 : slc.vtx3s) {
2115  if (vx3.ID == 0) continue;
2116  if (vx3.Vx2ID[plane] == 0) continue;
2117  if (vx3.Vx2ID[plane] > (int)slc.vtxs.size()) {
2118  mf::LogVerbatim("TC") << "ChkVtxAssociations: Invalid vx3.Vx2ID " << vx3.Vx2ID[plane]
2119  << " in CTP " << inCTP;
2120  return false;
2121  }
2122  auto& vx2 = slc.vtxs[vx3.Vx2ID[plane] - 1];
2123  if (vx2.Vx3ID != vx3.ID) {
2124  mf::LogVerbatim("TC") << "ChkVtxAssociations: 3V" << vx3.ID << " thinks it is matched to 2V"
2125  << vx2.ID << " but vx2 says no!";
2126  return false;
2127  }
2128  } // vx3
2129 
2130  // check the Tj -> 2D associations
2131  for (auto& tj : slc.tjs) {
2132  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
2133  for (unsigned short end = 0; end < 2; ++end) {
2134  if (tj.VtxID[end] == 0) continue;
2135  if (tj.VtxID[end] > slc.vtxs.size()) {
2136  mf::LogVerbatim("TC") << "ChkVtxAssociations: T" << tj.ID << " thinks it is matched to 2V"
2137  << tj.VtxID[end] << " on end " << end
2138  << " but no vertex exists. Recovering";
2139  tj.VtxID[end] = 0;
2140  return false;
2141  }
2142  unsigned short ivx = tj.VtxID[end] - 1;
2143  auto& vx2 = slc.vtxs[ivx];
2144  if (vx2.ID == 0) {
2145  mf::LogVerbatim("TC") << "ChkVtxAssociations: T" << tj.ID << " thinks it is matched to 2V"
2146  << tj.VtxID[end] << " on end " << end
2147  << " but the vertex is killed. Fixing the Tj";
2148  tj.VtxID[end] = 0;
2149  return false;
2150  }
2151  } // end
2152  } // tj
2153 
2154  return true;
2155 
2156  } // ChkVtxAssociations
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
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 121 of file TCCR.cxx.

122  {
123  slc.crt.cr_origin.clear();
124  slc.crt.cr_pfpxmin.clear();
125  slc.crt.cr_pfpxmax.clear();
126  slc.crt.cr_pfpyzmindis.clear();
127  }
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:413
std::vector< int > IsShowerParent
Definition: DataStructs.h:406
std::vector< float > EndWir
Definition: DataStructs.h:393
std::vector< float > EndAng
Definition: DataStructs.h:395
std::vector< float > BeginTim
Definition: DataStructs.h:389
std::vector< float > BeginAng
Definition: DataStructs.h:390
std::vector< float > EndTim
Definition: DataStructs.h:394
std::vector< int > ShowerID
Definition: DataStructs.h:405
ShowerTreeVars stv
Definition: DataStructs.cxx:10
std::vector< int > TjID
Definition: DataStructs.h:403
std::vector< short > BeginVtx
Definition: DataStructs.h:392
std::vector< short > EndVtx
Definition: DataStructs.h:397
std::vector< float > Envelope
Definition: DataStructs.h:411
std::vector< float > BeginChg
Definition: DataStructs.h:391
std::vector< int > EnvPlane
Definition: DataStructs.h:412
std::vector< short > MCSMom
Definition: DataStructs.h:399
std::vector< int > StageNum
Definition: DataStructs.h:407
std::vector< float > BeginWir
Definition: DataStructs.h:388
std::vector< float > EndChg
Definition: DataStructs.h:396
std::vector< int > EnvShowerID
Definition: DataStructs.h:414
std::vector< int > IsShowerTj
Definition: DataStructs.h:404
std::vector< short > PlaneNum
Definition: DataStructs.h:401
unsigned short tca::CloseEnd ( const TCSlice slc,
const Trajectory tj,
const Point2_t pos 
)

Definition at line 2549 of file Utils.cxx.

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

Definition at line 578 of file Utils.cxx.

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

Definition at line 650 of file Utils.cxx.

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

Definition at line 2504 of file TCVertex.cxx.

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

Definition at line 2410 of file TCVertex.cxx.

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

Definition at line 754 of file TCShower.cxx.

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

Definition at line 33 of file TCShower.cxx.

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

Definition at line 1308 of file PFPUtils.cxx.

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

Definition at line 2823 of file PFPUtils.cxx.

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

Definition at line 4108 of file TCShower.cxx.

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

Definition at line 4088 of file TCShower.cxx.

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

Definition at line 2722 of file PFPUtils.cxx.

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

Definition at line 3215 of file StepUtils.cxx.

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

Definition at line 2139 of file Utils.cxx.

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

Definition at line 2146 of file Utils.cxx.

2147  {
2148  if (inWirePos1 < -0.4 || inWirePos2 < -0.4) return 0;
2149  unsigned int inWire1 = std::nearbyint(inWirePos1);
2150  unsigned int inWire2 = std::nearbyint(inWirePos2);
2151  geo::PlaneID planeID = DecodeCTP(tCTP);
2152  unsigned short plane = planeID.Plane;
2153  if (inWire1 > slc.nWires[plane] || inWire2 > slc.nWires[plane]) return 0;
2154  if (inWire1 > inWire2) {
2155  // put in increasing order
2156  unsigned int tmp = inWire1;
2157  inWire1 = inWire2;
2158  inWire2 = tmp;
2159  } // inWire1 > inWire2
2160  ++inWire2;
2161  unsigned int wire, ndead = 0;
2162  for (wire = inWire1; wire < inWire2; ++wire)
2163  if (!evt.goodWire[plane][wire]) ++ndead;
2164  return ndead;
2165  } // DeadWireCount
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
std::vector< std::vector< bool > > goodWire
Definition: DataStructs.h:632
string tmp
Definition: languages.py:63
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:7
geo::PlaneID tca::DecodeCTP ( CTP_t  CTP)

Definition at line 115 of file DataStructs.cxx.

115  {
116  auto const cryo = (CTP / Cpad);
117  return geo::PlaneID(
118  /* Cryostat */ cryo,
119  /* TPC */ (CTP - cryo * Cpad) / Tpad,
120  /* Plane */ (CTP % 10)
121  );
122  }
constexpr unsigned int Tpad
Definition: DataStructs.h:50
detail::Node< FrameID, bool > PlaneID
Definition: CRTID.h:125
constexpr unsigned int Cpad
Definition: DataStructs.h:51
bool tca::DecodeDebugString ( std::string  strng)

Definition at line 5214 of file Utils.cxx.

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

Definition at line 2686 of file PFPUtils.cxx.

2690  {
2691  if (!tp3d.Flags[kTP3DGood]) return 0;
2692  if (tp3d.TjID > (int)slc.slHits.size()) return 0;
2693  if (tp3d.TjID <= 0) return 0;
2694 
2695  auto& tp = slc.tjs[tp3d.TjID - 1].Pts[tp3d.TPIndex];
2696  if (tp.Environment[kEnvOverlap]) return 0;
2697 
2698  double dQ = 0.;
2699  double time = 0;
2700  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
2701  if (!tp.UseHit[ii]) continue;
2702  auto& hit = (*evt.allHits)[slc.slHits[tp.Hits[ii]].allHitsIndex];
2703  dQ += hit.Integral();
2704  } // ii
2705  time = tp.Pos[1] / tcc.unitsPerTick;
2706  geo::PlaneID plnID = DecodeCTP(tp.CTP);
2707  if (dQ == 0) return 0;
2708  double angleToVert = tcc.geom->Plane(plnID).ThetaZ() - 0.5 * ::util::pi<>();
2709  double cosgamma =
2710  std::abs(std::sin(angleToVert) * tp3d.Dir[1] + std::cos(angleToVert) * tp3d.Dir[2]);
2711  if (cosgamma < 1.E-5) return 0;
2712  double dx = tcc.geom->WirePitch(plnID) / cosgamma;
2713  double dQdx = dQ / dx;
2714  double t0 = 0;
2715  float dedx = tcc.caloAlg->dEdx_AREA(clockData, detProp, dQdx, time, plnID.Plane, t0);
2716  if (std::isinf(dedx)) dedx = 0;
2717  return dedx;
2718  } // dEdx
calo::CalorimetryAlg * caloAlg
Definition: DataStructs.h:579
code to link reconstructed objects back to the MC truth information
PlaneGeo const & Plane(unsigned int const p, unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified wire.
TCConfig tcc
Definition: DataStructs.cxx:8
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
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:573
const geo::GeometryCore * geom
Definition: DataStructs.h:578
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
Detector simulation of raw signals on wires.
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:624
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:7
void tca::DefineDontCluster ( TCSlice slc,
bool  prt 
)
void tca::DefineEnvelope ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct ss,
bool  prt 
)

Definition at line 3487 of file TCShower.cxx.

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

Definition at line 1670 of file StepUtils.cxx.

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

Definition at line 2883 of file PFPUtils.cxx.

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

Definition at line 166 of file Utils.cxx.

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

Definition at line 2539 of file PFPUtils.cxx.

2540  {
2541  if (v1[0] == v2[0] && v1[1] == v2[1] && v1[2] == v2[2]) return 0;
2542  return acos(DotProd(v1, v2));
2543  }
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 3381 of file Utils.cxx.

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

Definition at line 3404 of file Utils.cxx.

3405  {
3406  return std::abs(std::remainder(Ang1 - Ang2, M_PI));
3407  }
T abs(T value)
#define M_PI
Definition: includeROOT.h:54
double tca::DeltaAngle2 ( double  Ang1,
double  Ang2 
)

Definition at line 3391 of file Utils.cxx.

3392  {
3393  constexpr double twopi = 2 * M_PI;
3394  double dang = Ang1 - Ang2;
3395  while (dang > M_PI)
3396  dang -= twopi;
3397  while (dang < -M_PI)
3398  dang += twopi;
3399  return dang;
3400  }
int twopi
Definition: units.py:12
#define M_PI
Definition: includeROOT.h:54
Vector3_t tca::DirAtEnd ( const PFPStruct pfp,
unsigned short  end 
)

Definition at line 3283 of file PFPUtils.cxx.

3284  {
3285  if (end > 1 || pfp.SectionFits.empty()) return {{0., 0., 0.}};
3286  if (end == 0) return pfp.SectionFits[0].Dir;
3287  return pfp.SectionFits[pfp.SectionFits.size() - 1].Dir;
3288  } // PosAtEnd
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
bool tca::DontCluster ( TCSlice slc,
const std::vector< int > &  tjlist1,
const std::vector< int > &  tjlist2 
)

Definition at line 3256 of file TCShower.cxx.

3257  {
3258  // returns true if a pair of tjs in the two lists are in the dontCluster vector
3259  if (tjlist1.empty() || tjlist2.empty()) return false;
3260  if (slc.dontCluster.empty()) return false;
3261  for (auto tid1 : tjlist1) {
3262  for (auto tid2 : tjlist2) {
3263  int ttid1 = tid1;
3264  if (ttid1 > tid2) std::swap(ttid1, tid2);
3265  for (auto& dc : slc.dontCluster)
3266  if (dc.TjIDs[0] == ttid1 && dc.TjIDs[1] == tid2) return true;
3267  } // dc
3268  } // tid1
3269  return false;
3270  } // DontCluster
void swap(Handle< T > &a, Handle< T > &b)
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 234 of file Utils.h.

235  {
236  return v1[0] * v2[0] + v1[1] * v2[1];
237  }
void tca::DumpShowerPts ( std::string  inFcnLabel,
TCSlice slc,
int  cotID 
)
void tca::DumpShowerPts ( TCSlice slc,
int  cotID 
)

Definition at line 3873 of file TCShower.cxx.

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

Definition at line 5398 of file Utils.cxx.

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

Definition at line 3214 of file Utils.cxx.

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

Definition at line 54 of file DataStructs.h.

55  {
56  return cryo * Cpad + tpc * Tpad + plane;
57  }
constexpr unsigned int Tpad
Definition: DataStructs.h:50
constexpr unsigned int Cpad
Definition: DataStructs.h:51
CTP_t tca::EncodeCTP ( const geo::PlaneID planeID)
inline

Definition at line 59 of file DataStructs.h.

60  {
61  return EncodeCTP(planeID.Cryostat, planeID.TPC, planeID.Plane);
62  }
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(const geo::WireID &wireID)
Definition: DataStructs.h:64
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 64 of file DataStructs.h.

65  {
66  return EncodeCTP(wireID.Cryostat, wireID.TPC, wireID.Plane);
67  }
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(const geo::WireID &wireID)
Definition: DataStructs.h:64
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 3251 of file StepUtils.cxx.

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

Definition at line 1945 of file Utils.cxx.

1946  {
1947  // returns the expected RMS of hits for the trajectory point in ticks
1948  if (std::abs(tp.Dir[0]) > 0.001) {
1949  geo::PlaneID planeID = DecodeCTP(tp.CTP);
1950  return 1.5 * evt.aveHitRMS[planeID.Plane] +
1951  2 * std::abs(tp.Dir[1] / tp.Dir[0]) / tcc.unitsPerTick;
1952  }
1953  else {
1954  return 500;
1955  }
1956  } // ExpectedHitsRMS
TCConfig tcc
Definition: DataStructs.cxx:8
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:573
std::vector< float > aveHitRMS
average RMS of an isolated hit
Definition: DataStructs.h:640
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:7
unsigned short tca::FarEnd ( const TCSlice slc,
const PFPStruct pfp,
const Point3_t pos 
)

Definition at line 3338 of file PFPUtils.cxx.

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

Definition at line 4175 of file Utils.cxx.

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

Definition at line 2596 of file PFPUtils.cxx.

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

Definition at line 2031 of file StepUtils.cxx.

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

Definition at line 1744 of file PFPUtils.cxx.

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

Definition at line 2381 of file PFPUtils.cxx.

2382  {
2383  // Fills the mallTraj vector with trajectory points in the tpc and sorts
2384  // them by increasing X
2385 
2386  int cstat = slc.TPCID.Cryostat;
2387  int tpc = slc.TPCID.TPC;
2388 
2389  // define mallTraj
2390  slc.mallTraj.clear();
2391  Tj2Pt tj2pt;
2392  unsigned short cnt = 0;
2393 
2394  // try to reduce CPU time by not attempting to match tjs that are near muons
2395  bool muFuzzCut = (tcc.match3DCuts.size() > 6 && tcc.match3DCuts[6] > 0);
2396 
2397  float rms = tcc.match3DCuts[0];
2398  for (auto& tj : slc.tjs) {
2399  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
2400  // ignore already matched
2401  if (tj.AlgMod[kMat3D]) continue;
2402  geo::PlaneID planeID = DecodeCTP(tj.CTP);
2403  if ((int)planeID.Cryostat != cstat) continue;
2404  if ((int)planeID.TPC != tpc) continue;
2405  int plane = planeID.Plane;
2406  if (tj.ID <= 0) continue;
2407  unsigned short tjID = tj.ID;
2408  for (unsigned short ipt = tj.EndPt[0]; ipt <= tj.EndPt[1]; ++ipt) {
2409  auto& tp = tj.Pts[ipt];
2410  if (tp.Chg <= 0) continue;
2411  if (tp.Pos[0] < -0.4) continue;
2412  // ignore already matched
2413  if (tp.InPFP > 0) continue;
2414  if (muFuzzCut && tp.Environment[kEnvNearMuon]) continue;
2415  tj2pt.wire = std::nearbyint(tp.Pos[0]);
2416  ++cnt;
2417  // don't try matching if the wire doesn't exist
2418  if (!tcc.geom->HasWire(geo::WireID(cstat, tpc, plane, tj2pt.wire))) continue;
2419  float xpos = detProp.ConvertTicksToX(tp.Pos[1] / tcc.unitsPerTick, plane, tpc, cstat);
2420  tj2pt.xlo = xpos - rms;
2421  tj2pt.xhi = xpos + rms;
2422  tj2pt.plane = plane;
2423  tj2pt.id = tjID;
2424  tj2pt.ipt = ipt;
2425  tj2pt.npts = tj.EndPt[1] - tj.EndPt[0] + 1;
2426  slc.mallTraj.push_back(tj2pt);
2427  } // tp
2428  } // tj
2429 
2430  // sort by increasing x
2431  std::vector<SortEntry> sortVec(slc.mallTraj.size());
2432  for (std::size_t ipt = 0; ipt < slc.mallTraj.size(); ++ipt) {
2433  // populate the sort vector
2434  sortVec[ipt].index = ipt;
2435  sortVec[ipt].val = slc.mallTraj[ipt].xlo;
2436  } // ipt
2437  // sort by increasing xlo
2438  std::sort(sortVec.begin(), sortVec.end(), valsIncreasing);
2439  // put slc.mallTraj into sorted order
2440  auto tallTraj = slc.mallTraj;
2441  for (std::size_t ii = 0; ii < sortVec.size(); ++ii)
2442  slc.mallTraj[ii] = tallTraj[sortVec[ii].index];
2443 
2444  } // FillmAllTraj
double rms(sqlite3 *db, std::string const &table_name, std::string const &column_name)
Definition: statistics.cc:40
TH3F * xpos
Definition: doAna.cpp:29
TCConfig tcc
Definition: DataStructs.cxx:8
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:573
std::vector< float > match3DCuts
3D matching cuts
Definition: DataStructs.h:562
const geo::GeometryCore * geom
Definition: DataStructs.h:578
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
bool HasWire(geo::WireID const &wireid) const
Returns whether we have the specified wire.
void tca::FillWireHitRange ( geo::TPCID  inTPCID)

Definition at line 4459 of file Utils.cxx.

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

Definition at line 4535 of file Utils.cxx.

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

Definition at line 611 of file PFPUtils.cxx.

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

Definition at line 146 of file TCVertex.cxx.

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

Definition at line 1358 of file PFPUtils.cxx.

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

Definition at line 1282 of file TCVertex.cxx.

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

Definition at line 3096 of file PFPUtils.cxx.

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

Definition at line 3358 of file Utils.cxx.

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

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

Definition at line 2905 of file Utils.cxx.

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

Definition at line 2975 of file Utils.cxx.

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

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

Definition at line 618 of file TCVertex.cxx.

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

Definition at line 3378 of file TCShower.cxx.

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

Definition at line 1575 of file TCShower.cxx.

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

Definition at line 190 of file PFPUtils.cxx.

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

Definition at line 287 of file TCShower.cxx.

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

Definition at line 60 of file TCShower.cxx.

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

Definition at line 3702 of file TCShower.cxx.

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

Definition at line 1755 of file StepUtils.cxx.

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

Definition at line 154 of file TCShower.cxx.

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

Definition at line 5127 of file Utils.cxx.

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

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

Definition at line 1413 of file PFPUtils.cxx.

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

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

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

Definition at line 806 of file Utils.cxx.

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

Definition at line 820 of file Utils.cxx.

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

Definition at line 1968 of file TCVertex.cxx.

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

Definition at line 2018 of file TCVertex.cxx.

2019  {
2020  // Version with LSQ fit. Each TP position (P0,P1) and slope S are fit to a vertex
2021  // at position (V0, V1), using the equation P1 = V1 + (P0 - V0) * S. This is put
2022  // in the form A * V = b. V is found using V = (A^T * A)^-1 * A^T * b. This is
2023  // usually done using the TDecompSVD Solve method but here we do it step-wise to
2024  // get access to the covariance matrix (A^T * A)^-1. The pull between the TP position
2025  // and the vertex position is stored in tp.Delta
2026 
2027  if (vxTPs.size() < 2) return false;
2028  if (vxTPs.size() == 2) {
2029  vx.ChiDOF = 0.;
2030  return true;
2031  }
2032 
2033  unsigned short npts = vxTPs.size();
2034  TMatrixD A(npts, 2);
2035  TVectorD b(npts);
2036  for (unsigned short itj = 0; itj < vxTPs.size(); ++itj) {
2037  auto& tp = vxTPs[itj];
2038  double dtdw = tp.Dir[1] / tp.Dir[0];
2039  double wt = 1 / (tp.AngErr * tp.AngErr);
2040  A(itj, 0) = -dtdw * wt;
2041  A(itj, 1) = 1. * wt;
2042  b(itj) = (tp.Pos[1] - tp.Pos[0] * dtdw) * wt;
2043  } // itj
2044 
2045  TMatrixD AT(2, npts);
2046  AT.Transpose(A);
2047  TMatrixD ATA = AT * A;
2048  double* det = 0;
2049  try {
2050  ATA.Invert(det);
2051  }
2052  catch (...) {
2053  return false;
2054  }
2055  if (det == NULL) return false;
2056  TVectorD vxPos = ATA * AT * b;
2057  vx.PosErr[0] = sqrt(ATA[0][0]);
2058  vx.PosErr[1] = sqrt(ATA[1][1]);
2059  vx.Pos[0] = vxPos[0];
2060  vx.Pos[1] = vxPos[1];
2061 
2062  // Calculate Chisq
2063  vx.ChiDOF = 0;
2064  if (vxTPs.size() > 2) {
2065  for (auto& tp : vxTPs) {
2066  // highjack TP Delta for the vertex pull
2067  tp.Delta = TrajPointVertexPull(slc, tp, vx);
2068  vx.ChiDOF += tp.Delta;
2069  } // itj
2070  vx.ChiDOF /= (float)(vxTPs.size() - 2);
2071  } // vxTPs.size() > 2
2072 
2073  if (prt) {
2074  mf::LogVerbatim("TC") << "Note: TP - 2V pull is stored in TP.Delta";
2075  PrintTPHeader("FV");
2076  for (auto& tp : vxTPs)
2077  PrintTP("FV", slc, 0, 1, 1, tp);
2078  }
2079 
2080  return true;
2081  } // FitVertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float TrajPointVertexPull(const TCSlice &slc, const TrajPoint &tp, const VtxStore &vx)
Definition: TCVertex.cxx:1865
void PrintTP(std::string someText, const TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, const TrajPoint &tp)
Definition: Utils.cxx:6294
#define A
Definition: memgrp.cpp:38
static bool * b
Definition: config.cpp:1043
void PrintTPHeader(std::string someText)
Definition: Utils.cxx:6285
void tca::FixBegin ( TCSlice slc,
Trajectory tj,
unsigned short  atPt 
)

Definition at line 2795 of file StepUtils.cxx.

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

Definition at line 434 of file StepUtils.cxx.

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

Definition at line 4847 of file Utils.cxx.

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

Definition at line 3941 of file TCShower.cxx.

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

Definition at line 1413 of file StepUtils.cxx.

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

Definition at line 75 of file TCCR.cxx.

76  {
77 
80 
81  std::map<int, float> omap; //<origin, energy>
82 
83  for (auto& tjID : pfp.TjIDs) {
84 
85  Trajectory& tj = slc.tjs[tjID - 1];
86  for (auto& tp : tj.Pts) {
87  for (unsigned short ii = 0; ii < tp.Hits.size(); ++ii) {
88  if (!tp.UseHit[ii]) continue;
89  unsigned int iht = tp.Hits[ii];
90  TCHit& slhit = slc.slHits[iht];
91  auto& hit = (*evt.allHits)[slhit.allHitsIndex];
92  raw::ChannelID_t channel = tcc.geom->PlaneWireToChannel((int)hit.WireID().Plane,
93  (int)hit.WireID().Wire,
94  (int)hit.WireID().TPC,
95  (int)hit.WireID().Cryostat);
96  double startTick = hit.PeakTime() - hit.RMS();
97  double endTick = hit.PeakTime() + hit.RMS();
98  // get a list of track IDEs that are close to this hit
99  std::vector<sim::TrackIDE> tides;
100  tides = bt_serv->ChannelToTrackIDEs(clockData, channel, startTick, endTick);
101  for (auto itide = tides.begin(); itide != tides.end(); ++itide) {
102  omap[pi_serv->TrackIdToMCTruth_P(itide->trackID)->Origin()] += itide->energy;
103  }
104  }
105  }
106  }
107 
108  float maxe = -1;
109  int origin = 0;
110  for (auto& i : omap) {
111  if (i.second > maxe) {
112  maxe = i.second;
113  origin = i.first;
114  }
115  }
116  return origin;
117  }
TCConfig tcc
Definition: DataStructs.cxx:8
simb::Origin_t Origin() const
Definition: MCTruth.h:74
uint8_t channel
Definition: CRTFragment.hh:201
const art::Ptr< simb::MCTruth > & TrackIdToMCTruth_P(int id) const
const geo::GeometryCore * geom
Definition: DataStructs.h:578
Detector simulation of raw signals on wires.
raw::ChannelID_t PlaneWireToChannel(WireID const &wireid) const
Returns the ID of the TPC channel connected to the specified wire.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:624
TCEvent evt
Definition: DataStructs.cxx:7
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
std::vector< sim::TrackIDE > ChannelToTrackIDEs(detinfo::DetectorClocksData const &clockData, raw::ChannelID_t channel, const double hit_start_time, const double hit_end_time) const
unsigned short tca::GetPFPIndex ( const TCSlice slc,
int  tjID 
)

Definition at line 1048 of file Utils.cxx.

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

Definition at line 1391 of file PFPUtils.cxx.

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

Definition at line 5086 of file Utils.cxx.

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

Definition at line 2851 of file TCVertex.cxx.

2852  {
2853  // returns a list of trajectory IDs that are attached to vx2
2854  std::vector<int> tmp;
2855  if (vx2.ID == 0) return tmp;
2856  for (auto& tj : slc.tjs) {
2857  if (tj.AlgMod[kKilled]) continue;
2858  if (tj.CTP != vx2.CTP) continue;
2859  for (unsigned short end = 0; end < 2; ++end) {
2860  if (tj.VtxID[end] == vx2.ID) tmp.push_back(tj.ID);
2861  } // end
2862  } // tj
2863  return tmp;
2864  } // GetVtxTjIDs
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
string tmp
Definition: languages.py:63
std::vector< int > tca::GetVtxTjIDs ( const TCSlice slc,
const Vtx3Store vx3,
float &  score 
)

Definition at line 2868 of file TCVertex.cxx.

2869  {
2870  // returns a list of Tjs in all planes that are attached to vx3
2871  std::vector<int> tmp;
2872  if (vx3.ID == 0) return tmp;
2873  float nvx2 = 0;
2874  score = 0;
2875  for (auto& vx2 : slc.vtxs) {
2876  if (vx2.ID == 0) continue;
2877  if (vx2.Vx3ID != vx3.ID) continue;
2878  auto vtxTjID2 = GetVtxTjIDs(slc, vx2);
2879  tmp.insert(tmp.end(), vtxTjID2.begin(), vtxTjID2.end());
2880  score += vx2.Score;
2881  ++nvx2;
2882  } // vx2
2883  if (nvx2 < 1) return tmp;
2884  // find the average score
2885  score /= nvx2;
2886  // sort by increasing ID
2887  std::sort(tmp.begin(), tmp.end());
2888  return tmp;
2889  } // GetVtxTjIDs
string tmp
Definition: languages.py:63
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:2868
bool tca::GottaKink ( TCSlice slc,
Trajectory tj,
bool  doTrim 
)

Definition at line 2554 of file StepUtils.cxx.

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

Definition at line 2810 of file Utils.cxx.

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

Definition at line 2536 of file Utils.cxx.

2537  {
2538  // returns the separation^2 between two hits in WSE units
2539  if (iht > slc.slHits.size() - 1 || jht > slc.slHits.size() - 1) return 1E6;
2540  auto& ihit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2541  auto& jhit = (*evt.allHits)[slc.slHits[jht].allHitsIndex];
2542  float dw = (float)ihit.WireID().Wire - (float)jhit.WireID().Wire;
2543  float dt = (ihit.PeakTime() - jhit.PeakTime()) * tcc.unitsPerTick;
2544  return dw * dw + dt * dt;
2545  } // HitSep2
TCConfig tcc
Definition: DataStructs.cxx:8
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:573
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:624
TCEvent evt
Definition: DataStructs.cxx:7
float tca::HitsPosTick ( const TCSlice slc,
const std::vector< unsigned int > &  hitsInMultiplet,
float &  sum,
HitStatus_t  hitRequest 
)

Definition at line 4287 of file Utils.cxx.

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

Definition at line 4277 of file Utils.cxx.

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

Definition at line 4244 of file Utils.cxx.

4247  {
4248  if (hitsInMultiplet.empty()) return 0;
4249 
4250  if (hitsInMultiplet.size() == 1) {
4251  auto& hit = (*evt.allHits)[slc.slHits[hitsInMultiplet[0]].allHitsIndex];
4252  return hit.RMS();
4253  }
4254 
4255  float minVal = 9999;
4256  float maxVal = 0;
4257  for (unsigned short ii = 0; ii < hitsInMultiplet.size(); ++ii) {
4258  unsigned int iht = hitsInMultiplet[ii];
4259  bool useit = (hitRequest == kAllHits);
4260  if (hitRequest == kUsedHits && slc.slHits[iht].InTraj > 0) useit = true;
4261  if (hitRequest == kUnusedHits && slc.slHits[iht].InTraj == 0) useit = true;
4262  if (!useit) continue;
4263  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
4264  float cv = hit.PeakTime();
4265  float rms = hit.RMS();
4266  float arg = cv - rms;
4267  if (arg < minVal) minVal = arg;
4268  arg = cv + rms;
4269  if (arg > maxVal) maxVal = arg;
4270  } // ii
4271  if (maxVal == 0) return 0;
4272  return (maxVal - minVal) / 2;
4273  } // HitsRMSTick
double rms(sqlite3 *db, std::string const &table_name, std::string const &column_name)
Definition: statistics.cc:40
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:624
TCEvent evt
Definition: DataStructs.cxx:7
float tca::HitsRMSTime ( const TCSlice slc,
const std::vector< unsigned int > &  hitsInMultiplet,
HitStatus_t  hitRequest 
)

Definition at line 4235 of file Utils.cxx.

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

Definition at line 1550 of file StepUtils.cxx.

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

Definition at line 1542 of file StepUtils.cxx.

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

Definition at line 1988 of file PFPUtils.cxx.

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

Definition at line 2014 of file TCShower.cxx.

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

Definition at line 2038 of file TCShower.cxx.

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

Definition at line 1956 of file TCShower.cxx.

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

Definition at line 2007 of file TCShower.cxx.

2008  {
2009  return InShowerProbLong(showerEnergy, along) * InShowerProbTrans(showerEnergy, along, trans);
2010  } // InShowerProbParam
double InShowerProbLong(double showerEnergy, double along)
Definition: TCShower.cxx:1956
double InShowerProbTrans(double showerEnergy, double along, double trans)
Definition: TCShower.cxx:1992
double tca::InShowerProbTrans ( double  showerEnergy,
double  along,
double  trans 
)

Definition at line 1992 of file TCShower.cxx.

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

Definition at line 3044 of file PFPUtils.cxx.

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

Definition at line 3071 of file PFPUtils.cxx.

3072  {
3073  // determine which TPC this point is in. This function returns false
3074  // if the point is not inside any TPC
3075  float abit = 5;
3076  for (const geo::TPCID& tpcid : tcc.geom->IterateTPCIDs()) {
3077  const geo::TPCGeo& TPC = tcc.geom->TPC(tpcid);
3078  double local[3] = {0., 0., 0.};
3079  double world[3] = {0., 0., 0.};
3080  TPC.LocalToWorld(local, world);
3081  // reduce the active area of the TPC by a bit to be consistent with FillWireHitRange
3082  if (pos[0] < world[0] - tcc.geom->DetHalfWidth(tpcid) + abit) continue;
3083  if (pos[0] > world[0] + tcc.geom->DetHalfWidth(tpcid) - abit) continue;
3084  if (pos[1] < world[1] - tcc.geom->DetHalfHeight(tpcid) + abit) continue;
3085  if (pos[1] > world[1] + tcc.geom->DetHalfHeight(tpcid) - abit) continue;
3086  if (pos[2] < world[2] - tcc.geom->DetLength(tpcid) / 2 + abit) continue;
3087  if (pos[2] > world[2] + tcc.geom->DetLength(tpcid) / 2 - abit) continue;
3088  inTPCID = tpcid;
3089  return true;
3090  } // tpcid
3091  return false;
3092  } // 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:8
Geometry information for a single TPC.
Definition: TPCGeo.h:38
IteratorBox< TPC_id_iterator,&GeometryCore::begin_TPC_id,&GeometryCore::end_TPC_id > IterateTPCIDs() const
Enables ranged-for loops on all TPC IDs of the detector.
geo::Length_t DetHalfHeight(geo::TPCID const &tpcid) const
Returns the half height of the active volume of the specified TPC.
geo::Length_t DetLength(geo::TPCID const &tpcid) const
Returns the length of the active volume of the specified TPC.
const geo::GeometryCore * geom
Definition: DataStructs.h:578
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 1274 of file Utils.cxx.

1275  {
1276  // Check slc.tjs -> InTraj associations
1277 
1278  unsigned short tID;
1279  unsigned int iht;
1280  unsigned short itj = 0;
1281  std::vector<unsigned int> tHits;
1282  std::vector<unsigned int> atHits;
1283  for (auto& tj : slc.tjs) {
1284  // ignore abandoned trajectories
1285  if (tj.AlgMod[kKilled]) continue;
1286  tID = tj.ID;
1287  tHits = PutTrajHitsInVector(tj, kUsedHits);
1288  if (tHits.size() < 2) continue;
1289  std::sort(tHits.begin(), tHits.end());
1290  atHits.clear();
1291  for (iht = 0; iht < slc.slHits.size(); ++iht) {
1292  if (slc.slHits[iht].InTraj == tID) atHits.push_back(iht);
1293  } // iht
1294  if (atHits.size() < 2) continue;
1295  if (!std::equal(tHits.begin(), tHits.end(), atHits.begin())) {
1296  mf::LogVerbatim myprt("TC");
1297  myprt << someText << " ChkInTraj failed: inTraj - UseHit mis-match for T" << tID
1298  << " tj.WorkID " << tj.WorkID << " atHits size " << atHits.size() << " tHits size "
1299  << tHits.size() << " in CTP " << tj.CTP << "\n";
1300  myprt << "AlgMods: ";
1301  for (unsigned short ib = 0; ib < AlgBitNames.size(); ++ib)
1302  if (tj.AlgMod[ib]) myprt << " " << AlgBitNames[ib];
1303  myprt << "\n";
1304  myprt << "index inTraj UseHit \n";
1305  for (iht = 0; iht < atHits.size(); ++iht) {
1306  myprt << "iht " << iht << " " << PrintHit(slc.slHits[atHits[iht]]);
1307  if (iht < tHits.size()) myprt << " " << PrintHit(slc.slHits[tHits[iht]]);
1308  if (atHits[iht] != tHits[iht]) myprt << " <<< " << atHits[iht] << " != " << tHits[iht];
1309  myprt << "\n";
1310  } // iht
1311  if (tHits.size() > atHits.size()) {
1312  for (iht = atHits.size(); iht < atHits.size(); ++iht) {
1313  myprt << "atHits " << iht << " " << PrintHit(slc.slHits[atHits[iht]]) << "\n";
1314  } // iht
1315  PrintTrajectory("CIT", slc, tj, USHRT_MAX);
1316  } // tHit.size > atHits.size()
1317  return false;
1318  }
1319  // check the VtxID
1320  for (unsigned short end = 0; end < 2; ++end) {
1321  if (tj.VtxID[end] > slc.vtxs.size()) {
1322  mf::LogVerbatim("TC") << someText << " ChkInTraj: Bad VtxID " << tj.ID;
1323  tj.AlgMod[kKilled] = true;
1324  return false;
1325  }
1326  } // end
1327  ++itj;
1328  } // tj
1329  return true;
1330 
1331  } // InTrajOK
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< unsigned int > PutTrajHitsInVector(const Trajectory &tj, HitStatus_t hitRequest)
Definition: Utils.cxx:2752
const std::vector< std::string > AlgBitNames
Definition: DataStructs.cxx:15
void PrintTrajectory(std::string someText, const TCSlice &slc, const Trajectory &tj, unsigned short tPoint)
Definition: Utils.cxx:6193
std::string PrintHit(const TCHit &tch)
Definition: Utils.cxx:6514
unsigned short tca::IsCloseToVertex ( const TCSlice slc,
const VtxStore inVx2 
)

Definition at line 2908 of file TCVertex.cxx.

2909  {
2910  // Returns the ID of a 2D vertex having the minimum pull < user-specified cut
2911 
2912  float minPull = tcc.vtx2DCuts[3];
2913  unsigned short imBest = 0;
2914  for (auto& vx2 : slc.vtxs) {
2915  if (vx2.CTP != inVx2.CTP) continue;
2916  if (vx2.ID <= 0) continue;
2917  float pull = VertexVertexPull(slc, inVx2, vx2);
2918  if (pull < minPull) {
2919  minPull = pull;
2920  imBest = vx2.ID;
2921  }
2922  } // vx2
2923  return imBest;
2924  } // IsCloseToVertex
TCConfig tcc
Definition: DataStructs.cxx:8
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:552
float VertexVertexPull(const TCSlice &slc, const VtxStore &vx1, const VtxStore &vx2)
Definition: TCVertex.cxx:1918
unsigned short tca::IsCloseToVertex ( const TCSlice slc,
const Vtx3Store vx3 
)

Definition at line 2928 of file TCVertex.cxx.

2929  {
2930  // Returns the ID of a 3D vertex having the minimum pull < user-specified cut
2931 
2932  float minPull = tcc.vtx3DCuts[1];
2933  unsigned short imBest = 0;
2934  for (auto& oldvx3 : slc.vtx3s) {
2935  if (oldvx3.ID == 0) continue;
2936  if (std::abs(oldvx3.X - vx3.X) > tcc.vtx3DCuts[0]) continue;
2937  float pull = VertexVertexPull(slc, vx3, oldvx3);
2938  if (pull < minPull) {
2939  minPull = pull;
2940  imBest = oldvx3.ID;
2941  }
2942  } // oldvx3
2943  return imBest;
2944 
2945  } // IsCloseToVertex
std::vector< float > vtx3DCuts
2D vtx -> 3D vtx matching cuts
Definition: DataStructs.h:553
TCConfig tcc
Definition: DataStructs.cxx:8
T abs(T value)
float VertexVertexPull(const TCSlice &slc, const VtxStore &vx1, const VtxStore &vx2)
Definition: TCVertex.cxx:1918
bool tca::IsGhost ( TCSlice slc,
Trajectory tj 
)

Definition at line 2863 of file StepUtils.cxx.

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

Definition at line 3027 of file StepUtils.cxx.

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

Definition at line 1907 of file TCShower.cxx.

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

Definition at line 2188 of file TCVertex.cxx.

2189  {
2190  // kill 2D vertices that have low score and are not attached to a high-score 3D vertex
2191  if (slc.vtxs.empty()) return;
2192  for (auto& vx : slc.vtxs) {
2193  if (vx.ID == 0) continue;
2194  if (vx.Score > tcc.vtx2DCuts[7]) continue;
2195  if (vx.Vx3ID > 0) {
2196  auto& vx3 = slc.vtx3s[vx.Vx3ID - 1];
2197  if (vx3.Primary) continue;
2198  if (slc.vtx3s[vx.Vx3ID - 1].Score >= tcc.vtx2DCuts[7]) continue;
2199  }
2200  MakeVertexObsolete("KPV", slc, vx, false);
2201  } // vx
2202 
2203  } // KillPoorVertices
bool MakeVertexObsolete(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2832
TCConfig tcc
Definition: DataStructs.cxx:8
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:552
void tca::KillVerticesInShower ( std::string  inFcnLabel,
TCSlice slc,
ShowerStruct ss,
bool  prt 
)

Definition at line 709 of file TCShower.cxx.

710  {
711  // make the vertices inside the shower envelope obsolete and update dontCluster
712  if (ss.ID == 0) return;
713  if (!tcc.useAlg[kKillInShowerVx]) return;
714  std::string fcnLabel = inFcnLabel + ".KVIS";
715 
716  for (auto& vx2 : slc.vtxs) {
717  if (vx2.ID == 0) continue;
718  if (vx2.CTP != ss.CTP) continue;
719  // ensure it isn't associated with a neutrino vertex
720  if (vx2.Vx3ID > 0 && slc.vtx3s[vx2.Vx3ID - 1].Neutrino) continue;
721  if (!PointInsideEnvelope(vx2.Pos, ss.Envelope)) continue;
722  if (prt)
723  mf::LogVerbatim("TC") << fcnLabel << " Clobber 2V" << vx2.ID << " -> 3V" << vx2.Vx3ID
724  << " inside 2S" << ss.ID;
725  // update dontCluster
726  for (auto& dc : slc.dontCluster) {
727  if (dc.TjIDs[0] == 0) continue;
728  if (dc.Vx2ID != vx2.ID) continue;
729  if (prt)
730  mf::LogVerbatim("TC") << fcnLabel << " Remove T" << dc.TjIDs[0] << "-T" << dc.TjIDs[0]
731  << " in dontCluster";
732  dc.TjIDs[0] = 0;
733  dc.TjIDs[1] = 0;
734  } // dc
735  if (vx2.Vx3ID > 0) {
736  auto TIn3V = GetAssns(slc, "3V", vx2.Vx3ID, "T");
737  for (auto tid : TIn3V)
738  slc.tjs[tid - 1].AlgMod[kKillInShowerVx] = true;
739  auto& vx3 = slc.vtx3s[vx2.Vx3ID - 1];
740  MakeVertexObsolete(slc, vx3);
741  }
742  else {
743  auto TIn2V = GetAssns(slc, "2V", vx2.ID, "T");
744  for (auto tid : TIn2V)
745  slc.tjs[tid - 1].AlgMod[kKillInShowerVx] = true;
746  MakeVertexObsolete("KVIS", slc, vx2, true);
747  }
748  } // vx2
749 
750  } // KillVerticesInShower
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeVertexObsolete(std::string fcnLabel, TCSlice &slc, VtxStore &vx2, bool forceKill)
Definition: TCVertex.cxx:2740
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4847
std::string string
Definition: nybbler.cc:12
TCConfig tcc
Definition: DataStructs.cxx:8
bool PointInsideEnvelope(const Point2_t &Point, const std::vector< Point2_t > &Envelope)
Definition: Utils.cxx:3321
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:588
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 3054 of file Utils.cxx.

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

Definition at line 3110 of file Utils.cxx.

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

Definition at line 3106 of file StepUtils.cxx.

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

Definition at line 3303 of file PFPUtils.cxx.

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

Definition at line 3132 of file PFPUtils.cxx.

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

Definition at line 4450 of file Utils.cxx.

4451  {
4452  // return true if the hit is in a long pulse indicating that it's position
4453  // and charge are not well known
4454  return ((hit.GoodnessOfFit() < 0 || hit.GoodnessOfFit() > 50) && hit.Multiplicity() > 5);
4455  }
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 4025 of file Utils.cxx.

4029  {
4030  // A version to use when the 2D direction isn't required
4031  TrajPoint tp;
4032  tp.Pos = {{0, 0}};
4033  tp.Dir = {{0, 1}};
4034  tp.CTP = inCTP;
4035  geo::PlaneID planeID = DecodeCTP(inCTP);
4036 
4037  tp.Pos[0] = tcc.geom->WireCoordinate(pos[1], pos[2], planeID);
4038  tp.Pos[1] = detProp.ConvertXToTicks(pos[0], planeID) * tcc.unitsPerTick;
4039  return tp;
4040  } // 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:8
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:573
const geo::GeometryCore * geom
Definition: DataStructs.h:578
geo::PlaneID DecodeCTP(CTP_t CTP)
TrajPoint tca::MakeBareTP ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice slc,
const Point3_t pos,
const Vector3_t dir,
CTP_t  inCTP 
)

Definition at line 4044 of file Utils.cxx.

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

Definition at line 4108 of file Utils.cxx.

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

Definition at line 4127 of file Utils.cxx.

4134  {
4135  tp.CTP = tCTP;
4136  tp.Pos[0] = fromWire;
4137  tp.Pos[1] = tcc.unitsPerTick * fromTick;
4138  tp.Dir[0] = toWire - fromWire;
4139  tp.Dir[1] = tcc.unitsPerTick * (toTick - fromTick);
4140  double norm = sqrt(tp.Dir[0] * tp.Dir[0] + tp.Dir[1] * tp.Dir[1]);
4141  if (norm == 0) return false;
4142  tp.Dir[0] /= norm;
4143  tp.Dir[1] /= norm;
4144  tp.Ang = atan2(tp.Dir[1], tp.Dir[0]);
4145  return true;
4146  } // MakeBareTrajPoint
TCConfig tcc
Definition: DataStructs.cxx:8
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:573
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 4150 of file Utils.cxx.

4151  {
4152  tpOut.Pos = fromPos;
4153  tpOut.Dir = PointDirection(fromPos, toPos);
4154  tpOut.Ang = atan2(tpOut.Dir[1], tpOut.Dir[0]);
4155  return true;
4156 
4157  } // MakeBareTrajPoint
Vector2_t PointDirection(const Point2_t p1, const Point2_t p2)
Definition: Utils.cxx:4185
bool tca::MakeBareTrajPoint ( const TCSlice slc,
const TrajPoint tpIn1,
const TrajPoint tpIn2,
TrajPoint tpOut 
)

Definition at line 4161 of file Utils.cxx.

4165  {
4166  tpOut.CTP = tpIn1.CTP;
4167  tpOut.Pos = tpIn1.Pos;
4168  tpOut.Dir = PointDirection(tpIn1.Pos, tpIn2.Pos);
4169  tpOut.Ang = atan2(tpOut.Dir[1], tpOut.Dir[0]);
4170  return true;
4171  } // MakeBareTrajPoint
Vector2_t PointDirection(const Point2_t p1, const Point2_t p2)
Definition: Utils.cxx:4185
void tca::MakeHaloTj ( TCSlice slc,
Trajectory muTj,
bool  prt 
)

Definition at line 45 of file Utils.cxx.

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

Definition at line 3866 of file StepUtils.cxx.

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

Definition at line 45 of file TCVertex.cxx.

46  {
47  // Vertices between poorly reconstructed tjs (especially junk slc) and normal
48  // tjs can fail because the junk tj trajectory parameters are inaccurate. This function
49  // uses proximity and not pointing to make junk vertices
50  // Don't use this if standard vertex reconstruction is disabled
51  if (tcc.vtx2DCuts[0] <= 0) return;
52  if (!tcc.useAlg[kJunkVx]) return;
53  if (slc.tjs.size() < 2) return;
54 
55  // Look for tjs that are within maxSep of the end of a Tj
56  constexpr float maxSep = 4;
57 
58  geo::PlaneID planeID = DecodeCTP(inCTP);
59  bool prt = (tcc.dbgVxJunk && tcc.dbgSlc);
60  if (prt) {
61  mf::LogVerbatim("TC") << "MakeJunkVertices: prt set for plane " << planeID.Plane
62  << " maxSep btw tjs " << maxSep;
63  }
64 
65  // make a template vertex
66  VtxStore junkVx;
67  junkVx.CTP = inCTP;
68  junkVx.Topo = 9;
69  junkVx.Stat[kJunkVx] = true;
70  junkVx.Stat[kFixed] = true;
71  // set an invalid ID
72  junkVx.ID = USHRT_MAX;
73  // put in generous errors
74  junkVx.PosErr = {{2.0, 2.0}};
75  // define a minimal score so it won't get clobbered
76  junkVx.Score = tcc.vtx2DCuts[7] + 0.1;
77 
78  // look at both ends of long tjs
79  for (unsigned short it1 = 0; it1 < slc.tjs.size() - 1; ++it1) {
80  auto& tj1 = slc.tjs[it1];
81  if (tj1.AlgMod[kKilled] || tj1.AlgMod[kHaloTj]) continue;
82  if (tj1.SSID > 0 || tj1.AlgMod[kShowerLike]) continue;
83  if (tj1.CTP != inCTP) continue;
84  if (tj1.AlgMod[kJunkTj]) continue;
85  if (TrajLength(tj1) < 10) continue;
86  if (tj1.MCSMom < 100) continue;
87  for (unsigned short end1 = 0; end1 < 2; ++end1) {
88  // existing vertex?
89  if (tj1.VtxID[end1] > 0) continue;
90  auto& tp1 = tj1.Pts[tj1.EndPt[end1]];
91  // get a list of tjs in this vicinity
92  auto tjlist = FindCloseTjs(slc, tp1, tp1, maxSep);
93  if (tjlist.empty()) continue;
94  // set to an invalid ID
95  junkVx.ID = USHRT_MAX;
96  for (auto tj2id : tjlist) {
97  auto& tj2 = slc.tjs[tj2id - 1];
98  if (tj2.CTP != inCTP) continue;
99  if (tj2id == tj1.ID) continue;
100  if (tj2.SSID > 0 || tj2.AlgMod[kShowerLike]) continue;
101  float close = maxSep;
102  unsigned short closeEnd = USHRT_MAX;
103  for (unsigned short end2 = 0; end2 < 2; ++end2) {
104  auto& tp2 = tj2.Pts[tj2.EndPt[end2]];
105  float sep = PosSep(tp1.Pos, tp2.Pos);
106  if (sep < close) {
107  close = sep;
108  closeEnd = end2;
109  } // sep
110  } // end2
111  if (closeEnd > 1) continue;
112  auto& tp2 = tj2.Pts[tj2.EndPt[closeEnd]];
113  bool signalBetween = SignalBetween(slc, tp1, tp2, 0.8);
114  if (!signalBetween) continue;
115  if (junkVx.ID == USHRT_MAX) {
116  // define the new vertex
117  junkVx.ID = slc.vtxs.size() + 1;
118  junkVx.Pos = tp1.Pos;
119  } // new vertex
120  tj2.VtxID[closeEnd] = junkVx.ID;
121  tj1.VtxID[end1] = junkVx.ID;
122  } // tjid
123  if (junkVx.ID == USHRT_MAX) continue;
124  if (!StoreVertex(slc, junkVx)) {
125  mf::LogVerbatim("TC") << "MJV: StoreVertex failed";
126  for (auto& tj : slc.tjs) {
127  if (tj.AlgMod[kKilled]) continue;
128  if (tj.VtxID[0] == junkVx.ID) tj.VtxID[0] = 0;
129  if (tj.VtxID[1] == junkVx.ID) tj.VtxID[1] = 0;
130  } // tj
131  continue;
132  } // StoreVertex failed
133  if (prt) {
134  mf::LogVerbatim("TC") << " New junk 2V" << junkVx.ID << " at " << std::fixed
135  << std::setprecision(1) << junkVx.Pos[0] << ":"
136  << junkVx.Pos[1] / tcc.unitsPerTick;
137  } // prt
138  junkVx.ID = USHRT_MAX;
139  } // end1
140  } // it1
141 
142  } // MakeJunkVertices
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:8
vertex position fixed manually - no fitting done
Definition: DataStructs.h:95
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:592
bool StoreVertex(TCSlice &slc, VtxStore &vx)
Definition: TCVertex.cxx:1932
Q_EXPORT QTSManip setprecision(int p)
Definition: qtextstream.h:343
int close(int)
Closes the file descriptor fd.
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:573
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. < 0 to turn off.
Definition: DataStructs.h:588
float TrajLength(const Trajectory &tj)
Definition: Utils.cxx:2644
geo::PlaneID DecodeCTP(CTP_t CTP)
double PosSep(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2564
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:552
std::vector< int > FindCloseTjs(const TCSlice &slc, const TrajPoint &fromTp, const TrajPoint &toTp, const float &maxDelta)
Definition: Utils.cxx:2975
bool SignalBetween(const TCSlice &slc, const TrajPoint &tp1, const TrajPoint &tp2, const float &MinWireSignalFraction)
Definition: Utils.cxx:1805
void tca::MakePFParticles ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
TCSlice slc,
std::vector< MatchStruct matVec,
unsigned short  matVec_Iter 
)

Definition at line 267 of file PFPUtils.cxx.

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

Definition at line 512 of file PFPUtils.cxx.

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

Definition at line 3192 of file TCShower.cxx.

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

Definition at line 3211 of file TCShower.cxx.

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

Definition at line 2205 of file PFPUtils.cxx.

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

Definition at line 2447 of file PFPUtils.cxx.

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

Definition at line 2124 of file PFPUtils.cxx.

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

Definition at line 2182 of file Utils.cxx.

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

Definition at line 2740 of file TCVertex.cxx.

2741  {
2742  // Makes a 2D vertex obsolete
2743 
2744  // check for a high-score 3D vertex
2745  bool hasHighScoreVx3 = (vx2.Vx3ID > 0);
2746  if (hasHighScoreVx3 && !forceKill && slc.vtx3s[vx2.Vx3ID - 1].Score >= tcc.vtx2DCuts[7])
2747  return false;
2748 
2749  if (tcc.dbg2V || tcc.dbg3V) {
2750  mf::LogVerbatim("TC") << fcnLabel << " MVO: killing 2V" << vx2.ID;
2751  }
2752 
2753  // Kill it
2754  int vx2id = vx2.ID;
2755  if (vx2.Vx3ID > 0) {
2756  auto& vx3 = slc.vtx3s[vx2.Vx3ID - 1];
2757  for (auto& v3v2id : vx3.Vx2ID)
2758  if (v3v2id == vx2.ID) v3v2id = 0;
2759  }
2760  vx2.ID = 0;
2761  for (auto& tj : slc.tjs) {
2762  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
2763  for (unsigned short end = 0; end < 2; ++end) {
2764  if (tj.VtxID[end] != vx2id) continue;
2765  tj.VtxID[end] = 0;
2766  tj.AlgMod[kPhoton] = false;
2767  // clear the kEnvOverlap bits on the TPs
2768  for (unsigned short ii = 0; ii < tj.Pts.size(); ++ii) {
2769  if (end == 0) {
2770  unsigned short ipt = tj.EndPt[0] + ii;
2771  auto& tp = tj.Pts[ipt];
2772  if (!tp.Environment[kEnvOverlap]) break;
2773  if (ipt == tj.EndPt[1]) break;
2774  }
2775  else {
2776  unsigned short ipt = tj.EndPt[1] - ii;
2777  auto& tp = tj.Pts[ipt];
2778  if (!tp.Environment[kEnvOverlap]) break;
2779  if (ipt == tj.EndPt[0]) break;
2780  }
2781  } // ii
2782  if (tj.AlgMod[kTjHiVx3Score]) {
2783  // see if the vertex at the other end is high-score and if so, preserve the state
2784  unsigned short oend = 1 - end;
2785  if (tj.VtxID[oend] > 0) {
2786  auto& ovx2 = slc.vtxs[tj.VtxID[oend] - 1];
2787  if (!ovx2.Stat[kHiVx3Score]) tj.AlgMod[kTjHiVx3Score] = false;
2788  } // vertex at the other end
2789  } // tj.AlgMod[kTjHiVx3Score]
2790  } // end
2791  } // tj
2792 
2793  if (!hasHighScoreVx3) return true;
2794 
2795  // update the affected 3D vertex
2796  Vtx3Store& vx3 = slc.vtx3s[vx2.Vx3ID - 1];
2797  // make the 3D vertex incomplete
2798  geo::PlaneID planeID = DecodeCTP(vx2.CTP);
2799  unsigned short plane = planeID.Plane;
2800  if (vx3.Vx2ID[plane] != vx2id) return true;
2801  vx3.Vx2ID[plane] = 0;
2802  vx3.Wire = vx2.Pos[0];
2803  // Ensure that there are at least two 2D vertices left
2804  unsigned short n2D = 0;
2805  for (unsigned short plane = 0; plane < slc.nPlanes; ++plane)
2806  if (vx3.Vx2ID[plane] > 0) ++n2D;
2807 
2808  if (n2D > 1) {
2809  // 3D vertex is incomplete
2810  // correct the score
2811  SetVx3Score(slc, vx3);
2812  return true;
2813  }
2814 
2815  // 3D vertex is obsolete
2816  // Detach all remaining 2D vertices from the 3D vertex
2817  for (auto& vx2 : slc.vtxs) {
2818  if (vx2.ID == 0) continue;
2819  if (vx2.Vx3ID == vx3.ID) vx2.Vx3ID = 0;
2820  } // vx2
2821  for (auto& pfp : slc.pfps) {
2822  for (unsigned short end = 0; end < 2; ++end)
2823  if (pfp.Vx3ID[end] == vx3.ID) pfp.Vx3ID[end] = 0;
2824  } // pfp
2825  vx3.ID = 0;
2826  return true;
2827 
2828  } // MakeVertexObsolete
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCConfig tcc
Definition: DataStructs.cxx:8
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
matched to a high-score 3D vertex
Definition: DataStructs.h:97
void SetVx3Score(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2256
bool dbg3V
debug 3D vertex finding
Definition: DataStructs.h:599
bool dbg2V
debug 2D vertex finding
Definition: DataStructs.h:595
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:552
bool tca::MakeVertexObsolete ( TCSlice slc,
Vtx3Store vx3 
)

Definition at line 2832 of file TCVertex.cxx.

2833  {
2834  // Deletes a 3D vertex and 2D vertices in all planes
2835  // The 2D and 3D vertices are NOT killed if forceKill is false and the 3D vertex
2836  // has a high score
2837  if (vx3.ID <= 0) return true;
2838  if (vx3.ID > int(slc.vtx3s.size())) return false;
2839 
2840  for (auto vx2id : vx3.Vx2ID) {
2841  if (vx2id == 0 || vx2id > (int)slc.vtxs.size()) continue;
2842  auto& vx2 = slc.vtxs[vx2id - 1];
2843  MakeVertexObsolete("MVO3", slc, vx2, true);
2844  }
2845  vx3.ID = 0;
2846  return true;
2847  } // MakeVertexObsolete
bool MakeVertexObsolete(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2832
void tca::MaskBadTPs ( TCSlice slc,
Trajectory tj,
float const &  maxChi 
)

Definition at line 2377 of file StepUtils.cxx.

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

Definition at line 2422 of file StepUtils.cxx.

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

Definition at line 3649 of file StepUtils.cxx.

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

Definition at line 944 of file PFPUtils.cxx.

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

Definition at line 1209 of file TCShower.cxx.

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

Definition at line 1231 of file TCShower.cxx.

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

Definition at line 1252 of file TCShower.cxx.

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

Definition at line 813 of file PFPUtils.cxx.

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

Definition at line 700 of file PFPUtils.cxx.

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

Definition at line 372 of file Utils.cxx.

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

Definition at line 3274 of file Utils.cxx.

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

Definition at line 2628 of file Utils.cxx.

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

Definition at line 3466 of file Utils.cxx.

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

Definition at line 3483 of file Utils.cxx.

3484  {
3485  return MCSMom(slc, tj, tj.EndPt[0], tj.EndPt[1]);
3486  } // MCSMom
short MCSMom(const TCSlice &slc, const Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:3490
short tca::MCSMom ( const TCSlice slc,
const Trajectory tj,
unsigned short  firstPt,
unsigned short  lastPt 
)

Definition at line 3490 of file Utils.cxx.

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

Definition at line 3539 of file Utils.cxx.

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

Definition at line 3554 of file Utils.cxx.

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

Not allowed

Definition at line 4662 of file Utils.cxx.

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

Definition at line 2218 of file Utils.cxx.

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

Definition at line 2308 of file TCShower.cxx.

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

Definition at line 2401 of file TCShower.cxx.

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

Definition at line 2522 of file TCShower.cxx.

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

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

Definition at line 2944 of file TCShower.cxx.

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

Definition at line 3015 of file TCShower.cxx.

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

Definition at line 2765 of file TCShower.cxx.

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

Definition at line 2653 of file TCShower.cxx.

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

Definition at line 511 of file Utils.cxx.

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

Definition at line 1301 of file TCShower.cxx.

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

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

Definition at line 2829 of file Utils.cxx.

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

Definition at line 2954 of file Utils.cxx.

2955  {
2956  // Searches for a TP near the end (or beginnin) that doesn't have the kEnvOverlap bit set
2957  // with the intent that a fit of a vertex position using this tj will be minimally
2958  // biased if there are no nearby hits from other tjs. A search is done from the
2959  // supplied nearPt moving in the + direction if nearPt == tj.EndPt[0] and moving in
2960  // the - direction if nearPt == tj.EndPt[1]
2961  if (end > 1) return USHRT_MAX;
2962  short dir = 1;
2963  if (end == 1) dir = -1;
2964  for (short ii = 0; ii < (short)tj.Pts.size(); ++ii) {
2965  short ipt = tj.EndPt[end] + dir * ii;
2966  if (ipt < 0 || ipt >= (short)tj.Pts.size()) return USHRT_MAX;
2967  auto& tp = tj.Pts[ipt];
2968  if (!tp.Environment[kEnvOverlap]) return ipt;
2969  } // ii
2970  return tj.EndPt[end];
2971  } // FindCleanPt
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
string dir
bool tca::NearbySrcHit ( geo::PlaneID  plnID,
unsigned int  wire,
float  loTick,
float  hiTick 
)

Definition at line 2069 of file Utils.cxx.

2070  {
2071  // Look for a hit on wid in the srcHits collection that has a tick in the range. This
2072  // is a DUNE-specific function in which hit disambiguation is done in the U and V planes
2073  if (evt.srcHits == NULL) return false;
2074  unsigned int pln = plnID.Plane;
2075  if (pln == 2) return false;
2076 
2077  unsigned int cstat = plnID.Cryostat;
2078  unsigned int tpc = plnID.TPC;
2079  // get a valid range of hits to search
2080  if (evt.tpcSrcHitRange[tpc].first >= (*evt.srcHits).size()) return false;
2081  if (evt.tpcSrcHitRange[tpc].second >= (*evt.srcHits).size()) return false;
2082  raw::ChannelID_t chan = tcc.geom->PlaneWireToChannel((int)pln, (int)wire, (int)tpc, (int)cstat);
2083  float atTick = 0.5 * (loTick + hiTick);
2084  for (unsigned int iht = evt.tpcSrcHitRange[tpc].first; iht <= evt.tpcSrcHitRange[tpc].second;
2085  ++iht) {
2086  auto& hit = (*evt.srcHits)[iht];
2087  if (hit.Channel() != chan) continue;
2088  if (atTick < hit.PeakTime()) {
2089  float loHitTick = hit.PeakTime() - 3 * hit.RMS();
2090  if (hiTick > loHitTick) return true;
2091  }
2092  else {
2093  float hiHitTick = hit.PeakTime() + 3 * hit.RMS();
2094  if (loTick < hiHitTick) return true;
2095  }
2096  } // iht
2097  return false;
2098  } // NearbySrcHit
TCConfig tcc
Definition: DataStructs.cxx:8
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:212
std::vector< std::pair< unsigned int, unsigned int > > tpcSrcHitRange
Definition: DataStructs.h:630
const geo::GeometryCore * geom
Definition: DataStructs.h:578
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
Detector simulation of raw signals on wires.
raw::ChannelID_t PlaneWireToChannel(WireID const &wireid) const
Returns the ID of the TPC channel connected to the specified wire.
std::vector< recob::Hit > const * srcHits
Definition: DataStructs.h:625
TCEvent evt
Definition: DataStructs.cxx:7
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 3520 of file Utils.cxx.

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

Definition at line 442 of file Utils.cxx.

443  {
444  // Returns the ID of the grandparent of this tj that is a primary tj that is attached
445  // to the neutrino vertex. 0 is returned if this condition is not met.
446  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) return -1;
447  if (tj.ParentID <= 0) return -1;
448  int primID = PrimaryID(slc, tj);
449  if (primID <= 0 || primID > (int)slc.tjs.size()) return -1;
450 
451  // We have the ID of the primary tj. Now see if it is attached to the neutrino vertex
452  auto& ptj = slc.tjs[primID - 1];
453  for (unsigned short end = 0; end < 2; ++end) {
454  if (ptj.VtxID[end] == 0) continue;
455  auto& vx2 = slc.vtxs[ptj.VtxID[end] - 1];
456  if (vx2.Vx3ID == 0) continue;
457  auto& vx3 = slc.vtx3s[vx2.Vx3ID - 1];
458  if (vx3.Neutrino) return primID;
459  } // end
460  return -1;
461  } // NeutrinoPrimaryTjUID
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
int PrimaryID(const TCSlice &slc, const Trajectory &tj)
Definition: Utils.cxx:465
unsigned short tca::NumHitsInTP ( const TrajPoint tp,
HitStatus_t  hitRequest 
)

Definition at line 4326 of file Utils.cxx.

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

Definition at line 2114 of file Utils.cxx.

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

Definition at line 2123 of file Utils.cxx.

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

Definition at line 4312 of file Utils.cxx.

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

Definition at line 711 of file Utils.cxx.

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

Definition at line 2075 of file TCShower.cxx.

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

Definition at line 2127 of file TCShower.cxx.

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

Definition at line 2169 of file Utils.cxx.

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

Definition at line 405 of file Utils.cxx.

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

Definition at line 3351 of file PFPUtils.cxx.

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

Definition at line 2844 of file PFPUtils.cxx.

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

Definition at line 2547 of file PFPUtils.cxx.

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

Definition at line 4185 of file Utils.cxx.

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

Definition at line 3114 of file PFPUtils.cxx.

3120  {
3121  // Point - vector version
3122  Point3_t p1End, p2End;
3123  for (unsigned short xyz = 0; xyz < 3; ++xyz) {
3124  p1End[xyz] = p1[xyz] + 10 * p1Dir[xyz];
3125  p2End[xyz] = p2[xyz] + 10 * p2Dir[xyz];
3126  }
3127  return LineLineIntersect(p1, p1End, p2, p2End, intersect, doca);
3128  } // PointDirIntersect
std::array< double, 3 > Point3_t
Definition: DataStructs.h:43
bool LineLineIntersect(Point3_t p1, Point3_t p2, Point3_t p3, Point3_t p4, Point3_t &intersect, float &doca)
Definition: PFPUtils.cxx:3132
bool tca::PointInsideEnvelope ( const Point2_t Point,
const std::vector< Point2_t > &  Envelope 
)

Definition at line 3321 of file Utils.cxx.

3322  {
3323  // returns true if the Point is within the Envelope polygon. Entries in Envelope are the
3324  // Pos[0], Pos[1] locations of the polygon vertices. This is based on the algorithm that the
3325  // sum of the angles of a vector between a point and the vertices will be 2 * pi for an interior
3326  // point and 0 for an exterior point
3327 
3328  Point2_t p1, p2;
3329  unsigned short nvx = Envelope.size();
3330  double angleSum = 0;
3331  for (unsigned short ii = 0; ii < Envelope.size(); ++ii) {
3332  p1[0] = Envelope[ii][0] - Point[0];
3333  p1[1] = Envelope[ii][1] - Point[1];
3334  p2[0] = Envelope[(ii + 1) % nvx][0] - Point[0];
3335  p2[1] = Envelope[(ii + 1) % nvx][1] - Point[1];
3336  angleSum += DeltaAngle(p1, p2);
3337  }
3338  if (abs(angleSum) < M_PI) return false;
3339  return true;
3340 
3341  } // InsideEnvelope
T abs(T value)
std::array< float, 2 > Point2_t
Definition: DataStructs.h:45
#define M_PI
Definition: includeROOT.h:54
double DeltaAngle(double Ang1, double Ang2)
Definition: Utils.cxx:3404
float tca::PointPull ( TCSlice slc,
Point2_t  pos,
float  chg,
const Trajectory tj 
)

Definition at line 544 of file Utils.cxx.

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

Definition at line 2814 of file PFPUtils.cxx.

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

Definition at line 2570 of file Utils.cxx.

2571  {
2572  if (iht > slc.slHits.size() - 1) return 1E6;
2573  auto& hit = (*evt.allHits)[slc.slHits[iht].allHitsIndex];
2574  float wire = hit.WireID().Wire;
2575  float time = hit.PeakTime() * tcc.unitsPerTick;
2576  return sqrt(PointTrajDOCA2(slc, wire, time, tp));
2577  } // PointTrajDOCA
TCConfig tcc
Definition: DataStructs.cxx:8
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:573
float PointTrajDOCA2(const TCSlice &slc, float wire, float time, TrajPoint const &tp)
Definition: Utils.cxx:2588
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:624
TCEvent evt
Definition: DataStructs.cxx:7
float tca::PointTrajDOCA ( const TCSlice slc,
float  wire,
float  time,
TrajPoint const &  tp 
)

Definition at line 2581 of file Utils.cxx.

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

Definition at line 2588 of file Utils.cxx.

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

Definition at line 2561 of file Utils.cxx.

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

Definition at line 3292 of file PFPUtils.cxx.

3293  {
3294  if (end > 1 || pfp.SectionFits.empty()) return {{0., 0., 0.}};
3295  // handle a neutrino pfp that doesn't have any TP3Ds
3296  if (pfp.TP3Ds.empty()) return pfp.SectionFits[0].Pos;
3297  if (end == 0) return pfp.TP3Ds[0].Pos;
3298  return pfp.TP3Ds[pfp.TP3Ds.size() - 1].Pos;
3299  } // PosAtEnd
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
if(!yymsg) yymsg
void tca::PosInPlane ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice slc,
const Vtx3Store vx3,
unsigned short  plane,
Point2_t pos 
)

Definition at line 2893 of file TCVertex.cxx.

2898  {
2899  // returns the 2D position of the vertex in the plane
2900  pos[0] = tcc.geom->WireCoordinate(vx3.Y, vx3.Z, plane, vx3.TPCID.TPC, vx3.TPCID.Cryostat);
2901  pos[1] =
2902  detProp.ConvertXToTicks(vx3.X, plane, vx3.TPCID.TPC, vx3.TPCID.Cryostat) * tcc.unitsPerTick;
2903 
2904  } // 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:8
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:573
const geo::GeometryCore * geom
Definition: DataStructs.h:578
double tca::PosSep ( const Point3_t pos1,
const Point3_t pos2 
)

Definition at line 2564 of file PFPUtils.cxx.

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

Definition at line 2661 of file Utils.cxx.

2662  {
2663  return sqrt(PosSep2(pos1, pos2));
2664  } // PosSep
float PosSep2(const Point2_t &pos1, const Point2_t &pos2)
Definition: Utils.cxx:2668
double tca::PosSep2 ( const Point3_t pos1,
const Point3_t pos2 
)

Definition at line 2571 of file PFPUtils.cxx.

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

Definition at line 2668 of file Utils.cxx.

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

Definition at line 465 of file Utils.cxx.

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

Definition at line 485 of file Utils.cxx.

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

Definition at line 4252 of file TCShower.cxx.

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

Definition at line 5766 of file Utils.cxx.

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

Definition at line 5817 of file Utils.cxx.

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

Definition at line 5689 of file Utils.cxx.

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

Definition at line 5519 of file Utils.cxx.

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

Definition at line 5950 of file Utils.cxx.

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

Definition at line 5448 of file Utils.cxx.

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

Definition at line 6461 of file Utils.cxx.

6462  {
6463  if (end > 1) return "Invalid end";
6464  std::string tmp;
6465  bool first = true;
6466  for (unsigned short ib = 0; ib < EndFlagNames.size(); ++ib) {
6467  if (pfp.EndFlag[end][ib]) {
6468  if (first) {
6469  tmp = std::to_string(end) + ":" + EndFlagNames[ib];
6470  first = false;
6471  }
6472  else {
6473  tmp += "," + EndFlagNames[ib];
6474  }
6475  }
6476  } // ib
6477  if (first) tmp = " none";
6478  return tmp;
6479  } // PrintEndFlag
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
std::string string
Definition: nybbler.cc:12
const std::vector< std::string > EndFlagNames
Definition: DataStructs.cxx:87
string tmp
Definition: languages.py:63
std::string to_string(ModuleType const mt)
Definition: ModuleType.h:34
std::string tca::PrintEndFlag ( const Trajectory tj,
unsigned short  end 
)

Definition at line 6483 of file Utils.cxx.

6484  {
6485  if (end > 1) return "Invalid end";
6486  std::string tmp;
6487  bool first = true;
6488  for (unsigned short ib = 0; ib < EndFlagNames.size(); ++ib) {
6489  if (tj.EndFlag[end][ib]) {
6490  if (first) {
6491  tmp = std::to_string(end) + ":" + EndFlagNames[ib];
6492  first = false;
6493  }
6494  else {
6495  tmp += "," + EndFlagNames[ib];
6496  }
6497  }
6498  } // ib
6499  return tmp;
6500  } // PrintEndFlag
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
std::string string
Definition: nybbler.cc:12
const std::vector< std::string > EndFlagNames
Definition: DataStructs.cxx:87
string tmp
Definition: languages.py:63
std::string to_string(ModuleType const mt)
Definition: ModuleType.h:34
std::string tca::PrintHit ( const TCHit tch)

Definition at line 6514 of file Utils.cxx.

6515  {
6516  if (tch.allHitsIndex > (*evt.allHits).size() - 1) return "NA";
6517  auto& hit = (*evt.allHits)[tch.allHitsIndex];
6518  return std::to_string(hit.WireID().Plane) + ":" + std::to_string(hit.WireID().Wire) + ":" +
6519  std::to_string((int)hit.PeakTime()) + "_" + std::to_string(tch.InTraj);
6520  } // PrintHit
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:624
TCEvent evt
Definition: DataStructs.cxx:7
std::string to_string(ModuleType const mt)
Definition: ModuleType.h:34
std::string tca::PrintHitShort ( const TCHit tch)

Definition at line 6504 of file Utils.cxx.

6505  {
6506  if (tch.allHitsIndex > (*evt.allHits).size() - 1) return "NA";
6507  auto& hit = (*evt.allHits)[tch.allHitsIndex];
6508  return std::to_string(hit.WireID().Plane) + ":" + std::to_string(hit.WireID().Wire) + ":" +
6509  std::to_string((int)hit.PeakTime());
6510  } // PrintHit
Detector simulation of raw signals on wires.
std::vector< recob::Hit > const * allHits
Definition: DataStructs.h:624
TCEvent evt
Definition: DataStructs.cxx:7
std::string to_string(ModuleType const mt)
Definition: ModuleType.h:34
void tca::PrintP ( std::string  someText,
mf::LogVerbatim myprt,
PFPStruct pfp,
bool printHeader 
)

Definition at line 5603 of file Utils.cxx.

5604  {
5605  if (pfp.ID <= 0) return;
5606  if (printHeader) {
5607  myprt << "************ PFParticles ************\n";
5608  myprt << " prodID sVx _____sPos____ CS _______sDir______ ____sdEdx_____ eVx "
5609  "_____ePos____ CS ____edEdx_____ MVI MCSMom Len nTP3 nSec SLk? PDG Par \n";
5610  printHeader = false;
5611  } // printHeader
5612  auto sIndx = GetSliceIndex("P", pfp.UID);
5613  if (sIndx.first == USHRT_MAX) return;
5614  auto& slc = slices[sIndx.first];
5615  std::string str =
5616  std::to_string(slc.ID) + ":" + std::to_string(sIndx.first) + ":" + std::to_string(pfp.ID);
5617  str += "/" + std::to_string(pfp.UID);
5618  myprt << std::setw(12) << str;
5619  // start and end stuff
5620  for (unsigned short end = 0; end < 2; ++end) {
5621  str = "--";
5622  if (pfp.Vx3ID[end] > 0) str = "3V" + std::to_string(slc.vtx3s[pfp.Vx3ID[end] - 1].UID);
5623  myprt << std::setw(6) << str;
5624  myprt << std::fixed << std::right << std::setprecision(0);
5625  auto pos = PosAtEnd(pfp, end);
5626  myprt << std::setw(5) << pos[0];
5627  myprt << std::setw(5) << pos[1];
5628  myprt << std::setw(5) << pos[2];
5629  // print character for Outside or Inside the FV
5630  if (InsideFV(slc, pfp, end)) { myprt << " I"; }
5631  else {
5632  myprt << " O";
5633  }
5634  // only print the starting direction
5635  if (end == 0) {
5636  myprt << std::fixed << std::right << std::setprecision(2);
5637  auto dir = DirAtEnd(pfp, end);
5638  myprt << std::setw(6) << dir[0];
5639  myprt << std::setw(6) << dir[1];
5640  myprt << std::setw(6) << dir[2];
5641  } // end == 0
5642  for (auto& dedx : pfp.dEdx[end]) {
5643  if (dedx < 50) { myprt << std::setw(5) << std::setprecision(1) << dedx; }
5644  else {
5645  myprt << std::setw(5) << std::setprecision(0) << dedx;
5646  }
5647  } // dedx
5648  if (pfp.dEdx[end].size() < 3) {
5649  for (size_t i = 0; i < 3 - pfp.dEdx[end].size(); ++i) {
5650  myprt << std::setw(6) << ' ';
5651  }
5652  }
5653  } // startend
5654  myprt << std::setw(6) << pfp.MVI;
5655  // global stuff
5656  myprt << std::setw(7) << MCSMom(slc, pfp.TjIDs);
5657  float length = Length(pfp);
5658  if (length < 100) { myprt << std::setw(5) << std::setprecision(1) << length; }
5659  else {
5660  myprt << std::setw(5) << std::setprecision(0) << length;
5661  }
5662  myprt << std::setw(5) << pfp.TP3Ds.size();
5663  myprt << std::setw(5) << pfp.SectionFits.size();
5664  myprt << std::setw(5) << IsShowerLike(slc, pfp.TjIDs);
5665  myprt << std::setw(5) << pfp.PDGCode;
5666  myprt << std::setw(4) << pfp.ParentUID;
5667  if (!pfp.TjIDs.empty()) {
5668  if (pfp.TjUIDs.empty()) {
5669  // print Tjs in one TPC
5670  for (auto tjid : pfp.TjIDs)
5671  myprt << " TU" << slc.tjs[tjid - 1].UID;
5672  }
5673  else {
5674  // print Tjs in all TPCs (if this is called after FinishEvent)
5675  for (auto tjuid : pfp.TjUIDs)
5676  myprt << " TU" << tjuid;
5677  }
5678  } // TjIDs exist
5679  if (!pfp.DtrUIDs.empty()) {
5680  myprt << " dtrs";
5681  for (auto dtruid : pfp.DtrUIDs)
5682  myprt << " PU" << dtruid;
5683  } // dtr ids exist
5684  myprt << "\n";
5685  } // PrintP
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
float Length(const PFPStruct &pfp)
Definition: PFPUtils.cxx:3303
bool InsideFV(const TCSlice &slc, const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3044
std::string string
Definition: nybbler.cc:12
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3292
string dir
bool IsShowerLike(TCSlice &slc, const std::vector< int > TjIDs)
Definition: TCShower.cxx:1907
Q_EXPORT QTSManip setprecision(int p)
Definition: qtextstream.h:343
std::vector< TCSlice > slices
Definition: DataStructs.cxx:12
Q_EXPORT QTSManip setw(int w)
Definition: qtextstream.h:331
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
Definition: Utils.cxx:5086
short MCSMom(const TCSlice &slc, const Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:3490
Vector3_t DirAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3283
std::string to_string(ModuleType const mt)
Definition: ModuleType.h:34
static QCString str
void tca::PrintPFP ( std::string  someText,
TCSlice slc,
const PFPStruct pfp,
bool  printHeader 
)

Definition at line 6371 of file Utils.cxx.

6372  {
6373  mf::LogVerbatim myprt("TC");
6374  if (printHeader) {
6375  myprt << someText;
6376  myprt << " PFP sVx ________sPos_______ EF _______sDir______ ____sdEdx_____ eVx "
6377  "________ePos_______ EF _______eDir______ ____edEdx____ Len nTp3 MCSMom ShLike? "
6378  "PDG Par Prim\n";
6379  }
6380  myprt << someText;
6381  std::string pid = "P" + std::to_string(pfp.ID);
6382  myprt << std::setw(5) << pid;
6383  // start and end stuff
6384  for (unsigned short end = 0; end < 2; ++end) {
6385  myprt << std::setw(4) << pfp.Vx3ID[end];
6386  myprt << std::fixed << std::right << std::setprecision(1);
6387  auto pos = PosAtEnd(pfp, end);
6388  myprt << std::setw(7) << pos[0];
6389  myprt << std::setw(7) << pos[1];
6390  myprt << std::setw(7) << pos[2];
6391  // print characters that encode the EndFlag
6392  std::string ef;
6393  if (pfp.EndFlag[end][kOutFV]) { ef = "O"; }
6394  else {
6395  ef = "I";
6396  }
6397  if (pfp.EndFlag[end][kBragg]) ef += "B";
6398  myprt << std::setw(6) << ef;
6399  myprt << std::fixed << std::right << std::setprecision(2);
6400  auto dir = DirAtEnd(pfp, end);
6401  myprt << std::setw(6) << dir[0];
6402  myprt << std::setw(6) << dir[1];
6403  myprt << std::setw(6) << dir[2];
6404  for (auto& dedx : pfp.dEdx[end]) {
6405  if (dedx < 50) { myprt << std::setw(5) << std::setprecision(1) << dedx; }
6406  else {
6407  myprt << std::setw(5) << std::setprecision(0) << dedx;
6408  }
6409  } // dedx
6410  if (pfp.dEdx[end].size() < 3) {
6411  for (size_t i = 0; i < 3 - pfp.dEdx[end].size(); ++i) {
6412  myprt << std::setw(6) << ' ';
6413  }
6414  }
6415  } // startend
6416  // global stuff
6417  float length = Length(pfp);
6418  if (length < 100) { myprt << std::setw(5) << std::setprecision(1) << length; }
6419  else {
6420  myprt << std::setw(5) << std::setprecision(0) << length;
6421  }
6422  myprt << std::setw(5) << std::setprecision(2) << pfp.TP3Ds.size();
6423  myprt << std::setw(7) << MCSMom(slc, pfp.TjIDs);
6424  myprt << std::setw(5) << IsShowerLike(slc, pfp.TjIDs);
6425  myprt << std::setw(5) << pfp.PDGCode;
6426  myprt << " NA";
6427  myprt << std::setw(4) << pfp.ParentUID;
6428  myprt << std::setw(5) << PrimaryUID(slc, pfp);
6429  if (!pfp.TjIDs.empty()) {
6430  for (auto& tjID : pfp.TjIDs)
6431  myprt << " T" << tjID;
6432  }
6433  if (!pfp.DtrUIDs.empty()) {
6434  myprt << " dtrs";
6435  for (auto& dtrUID : pfp.DtrUIDs)
6436  myprt << " P" << dtrUID;
6437  }
6438  } // PrintPFP
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
float Length(const PFPStruct &pfp)
Definition: PFPUtils.cxx:3303
std::string string
Definition: nybbler.cc:12
Point3_t PosAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3292
string dir
bool IsShowerLike(TCSlice &slc, const std::vector< int > TjIDs)
Definition: TCShower.cxx:1907
Q_EXPORT QTSManip setprecision(int p)
Definition: qtextstream.h:343
Q_EXPORT QTSManip setw(int w)
Definition: qtextstream.h:331
short MCSMom(const TCSlice &slc, const Trajectory &tj, unsigned short firstPt, unsigned short lastPt)
Definition: Utils.cxx:3490
int PrimaryUID(const TCSlice &slc, const PFPStruct &pfp)
Definition: Utils.cxx:485
Vector3_t DirAtEnd(const PFPStruct &pfp, unsigned short end)
Definition: PFPUtils.cxx:3283
std::string to_string(ModuleType const mt)
Definition: ModuleType.h:34
TFile * ef
Definition: doAna.cpp:25
void tca::PrintPFPs ( std::string  someText,
TCSlice slc 
)

Definition at line 6442 of file Utils.cxx.

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

Definition at line 6524 of file Utils.cxx.

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

Definition at line 6531 of file Utils.cxx.

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

Definition at line 4341 of file TCShower.cxx.

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

Definition at line 4211 of file TCShower.cxx.

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

Definition at line 5858 of file Utils.cxx.

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

Definition at line 6294 of file Utils.cxx.

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

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

Definition at line 6285 of file Utils.cxx.

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

Definition at line 6193 of file Utils.cxx.

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

Definition at line 2729 of file Utils.cxx.

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

Definition at line 2752 of file Utils.cxx.

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

Definition at line 1081 of file TCVertex.cxx.

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

Definition at line 1177 of file TCVertex.cxx.

1178  {
1179  // The 2D vertices IDs in vx2cls were clustered by the calling function. This function
1180  // checks the T -> 2V assns and possibly changes it. It returns true if an assn is changed
1181  // or if a vertex in vx2cls is made obsolete, necessitating a change to the list of 2V
1182  // clusters
1183  if (vx2cls.size() < 2) return false;
1184 
1185  // Form a list of all Tjs associated with this 2V cluster
1186  std::vector<int> t2vList;
1187 
1188  CTP_t inCTP;
1189  for (auto vx2id : vx2cls) {
1190  auto& vx2 = slc.vtxs[vx2id - 1];
1191  inCTP = vx2.CTP;
1192  // vertex clobbered? If so, vertex clustering needs to be re-done
1193  if (vx2.ID <= 0) return true;
1194  auto tlist = GetAssns(slc, "2V", vx2.ID, "T");
1195  for (auto tid : tlist)
1196  if (std::find(t2vList.begin(), t2vList.end(), tid) == t2vList.end()) t2vList.push_back(tid);
1197  } // vx2id
1198  if (t2vList.size() < 3) return false;
1199 
1200  // Sum the T -> 2V pulls
1201  float sumPulls = 0;
1202  float cnt = 0;
1203  for (auto tid : t2vList) {
1204  auto& tj = slc.tjs[tid - 1];
1205  for (unsigned short end = 0; end < 2; ++end) {
1206  if (tj.VtxID[end] <= 0) continue;
1207  if (std::find(vx2cls.begin(), vx2cls.end(), tj.VtxID[end]) == vx2cls.end()) continue;
1208  auto& vx = slc.vtxs[tj.VtxID[end] - 1];
1209  unsigned short nearEnd = 1 - FarEnd(slc, tj, vx.Pos);
1210  unsigned short fitPt = NearbyCleanPt(slc, tj, nearEnd);
1211  if (fitPt == USHRT_MAX) return false;
1212  auto& tp = tj.Pts[fitPt];
1213  sumPulls += TrajPointVertexPull(slc, tp, vx);
1214  ++cnt;
1215  } // end
1216  } // tid
1217 
1218  if (prt) {
1219  mf::LogVerbatim myprt("TC");
1220  myprt << "R2VTs: cluster:";
1221  for (auto vid : vx2cls)
1222  myprt << " 2V" << vid;
1223  myprt << " ->";
1224  for (auto tid : t2vList)
1225  myprt << " T" << tid;
1226  myprt << " sumPulls " << std::setprecision(2) << sumPulls << " cnt " << cnt;
1227  } // prt
1228 
1229  // try to fit all Tjs to one vertex. Find the average position of all of the
1230  // vertices. This will be used to find the end of the Tjs that are closest to the
1231  // presumed single vertex
1232  VtxStore oneVx;
1233  oneVx.CTP = inCTP;
1234  for (auto vid : vx2cls) {
1235  auto& vx = slc.vtxs[vid - 1];
1236  oneVx.Pos[0] += vx.Pos[0];
1237  oneVx.Pos[1] += vx.Pos[2];
1238  } // vid
1239  oneVx.Pos[0] /= vx2cls.size();
1240  oneVx.Pos[1] /= vx2cls.size();
1241  std::vector<TrajPoint> oneVxTPs(t2vList.size());
1242  for (unsigned short itj = 0; itj < t2vList.size(); ++itj) {
1243  auto& tj = slc.tjs[t2vList[itj] - 1];
1244  unsigned short nearEnd = 1 - FarEnd(slc, tj, oneVx.Pos);
1245  unsigned short fitPt = NearbyCleanPt(slc, tj, nearEnd);
1246  if (fitPt == USHRT_MAX) return false;
1247  oneVxTPs[itj] = tj.Pts[fitPt];
1248  // inflate the TP angle angle error if a TP without an overlap wasn't found
1249  if (oneVxTPs[itj].Environment[kEnvOverlap]) oneVxTPs[itj].AngErr *= 4;
1250  oneVxTPs[itj].Step = tj.ID;
1251  } // ii
1252  if (!FitVertex(slc, oneVx, oneVxTPs, prt)) return false;
1253 
1254  if (oneVx.ChiDOF < 3) {
1255  // Update the position of the first 2V in the list
1256  auto& vx = slc.vtxs[vx2cls[0] - 1];
1257  vx.Pos = oneVx.Pos;
1258  vx.PosErr = oneVx.PosErr;
1259  vx.NTraj = t2vList.size();
1260  vx.ChiDOF = oneVx.ChiDOF;
1261  vx.Topo = 14;
1262  // Set a flag that the environment near this vertex (and all other vertices in this slice)
1263  // should be revisited
1264  vx.Stat[kVxEnvOK] = false;
1265  for (unsigned short ivx = 1; ivx < vx2cls.size(); ++ivx) {
1266  auto& vx = slc.vtxs[vx2cls[ivx] - 1];
1267  MakeVertexObsolete("R2VTPs", slc, vx, true);
1268  } // ivx
1269  // now attach the trajectories
1270  for (auto tid : t2vList) {
1271  auto& tj = slc.tjs[tid - 1];
1272  unsigned short nearEnd = 1 - FarEnd(slc, tj, vx.Pos);
1273  tj.VtxID[nearEnd] = vx.ID;
1274  } // tid
1275  return true;
1276  } // oneVx.ChiDOF < 3
1277  return false;
1278  } // Reconcile2VTs
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
unsigned short FarEnd(const TCSlice &slc, const PFPStruct &pfp, const Point3_t &pos)
Definition: PFPUtils.cxx:3338
bool MakeVertexObsolete(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2832
std::vector< int > GetAssns(TCSlice &slc, std::string type1Name, int id, std::string type2Name)
Definition: Utils.cxx:4847
float TrajPointVertexPull(const TCSlice &slc, const TrajPoint &tp, const VtxStore &vx)
Definition: TCVertex.cxx:1865
bool FitVertex(TCSlice &slc, VtxStore &vx, std::vector< TrajPoint > &vxTPs, bool prt)
Definition: TCVertex.cxx:2018
Q_EXPORT QTSManip setprecision(int p)
Definition: qtextstream.h:343
unsigned short NearbyCleanPt(const TCSlice &slc, const Trajectory &tj, unsigned short end)
Definition: Utils.cxx:2954
the environment near the vertex was checked - See UpdateVxEnvironment
Definition: DataStructs.h:101
unsigned int CTP_t
Definition: DataStructs.h:49
bool tca::Reconcile3D ( std::string  inFcnLabel,
TCSlice slc,
bool  parentSearchDone,
bool  prt 
)

Definition at line 427 of file TCShower.cxx.

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

Definition at line 575 of file TCShower.cxx.

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

Definition at line 426 of file PFPUtils.cxx.

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

Definition at line 473 of file PFPUtils.cxx.

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

Definition at line 1649 of file PFPUtils.cxx.

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

Definition at line 2088 of file PFPUtils.cxx.

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

Definition at line 2704 of file TCVertex.cxx.

2709  {
2710  // The tj has been slated to be split somewhere near point nearPt. This function will move
2711  // the near point a bit to the most likely point of a vertex
2712 
2713  float maxChg = tj.Pts[nearPt].Chg;
2714  short maxChgPt = nearPt;
2715  unsigned short fromPt = tj.EndPt[0];
2716  short spt = (short)nearPt - (short)nPtsToChk;
2717  if (spt > (short)fromPt) fromPt = nearPt - nPtsToChk;
2718  unsigned short toPt = nearPt + nPtsToChk;
2719  if (toPt > tj.EndPt[1]) toPt = tj.EndPt[1];
2720 
2721  for (short ipt = fromPt; ipt <= toPt; ++ipt) {
2722  if (ipt < tj.EndPt[0] || ipt > tj.EndPt[1]) continue;
2723  auto& tp = tj.Pts[ipt];
2724  if (tp.Chg > maxChg) {
2725  maxChg = tp.Chg;
2726  maxChgPt = ipt;
2727  }
2728  if (prt)
2729  mf::LogVerbatim("TC") << "RVP: ipt " << ipt << " Pos " << tp.CTP << ":"
2730  << PrintPos(slc, tp.Pos) << " chg " << (int)tp.Chg << " nhits "
2731  << tp.Hits.size();
2732  } // ipt
2733  if (nearPt == maxChgPt) return false;
2734  nearPt = maxChgPt;
2735  return true;
2736  } //RefineVtxPosition
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::string PrintPos(const TCSlice &slc, const TrajPoint &tp)
Definition: Utils.cxx:6524
void tca::ReleaseHits ( TCSlice slc,
Trajectory tj 
)

Definition at line 1060 of file Utils.cxx.

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

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

Definition at line 1519 of file TCShower.cxx.

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

Definition at line 1111 of file PFPUtils.cxx.

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

Definition at line 2195 of file Utils.cxx.

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

Definition at line 2359 of file PFPUtils.cxx.

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

Definition at line 1314 of file StepUtils.cxx.

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

Definition at line 3151 of file TCShower.cxx.

3152  {
3153  // Reverses the shower and the shower tj
3154 
3155  if (ss.ID == 0) return;
3156  if (ss.TjIDs.empty()) return;
3157 
3158  std::string fcnLabel = inFcnLabel + ".RevSh";
3159 
3160  std::reverse(ss.ShPts.begin(), ss.ShPts.end());
3161  // change the sign of RotPos
3162  for (auto& sspt : ss.ShPts) {
3163  sspt.RotPos[0] = -sspt.RotPos[0];
3164  sspt.RotPos[1] = -sspt.RotPos[1];
3165  }
3166  // flip the shower angle
3167  if (ss.Angle > 0) { ss.Angle -= M_PI; }
3168  else {
3169  ss.Angle += M_PI;
3170  }
3171  if (ss.DirectionFOM != 0) ss.DirectionFOM = 1 / ss.DirectionFOM;
3172  auto& stj = slc.tjs[ss.ShowerTjID - 1];
3173  ReverseTraj(slc, stj);
3174  DefineEnvelope(fcnLabel, slc, ss, prt);
3175  if (prt) mf::LogVerbatim("TC") << fcnLabel << " Reversed shower. Shower angle = " << ss.Angle;
3176  } // ReverseShower
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::string string
Definition: nybbler.cc:12
void DefineEnvelope(std::string inFcnLabel, TCSlice &slc, ShowerStruct &ss, bool prt)
Definition: TCShower.cxx:3487
void ReverseTraj(TCSlice &slc, Trajectory &tj)
Definition: Utils.cxx:3292
#define M_PI
Definition: includeROOT.h:54
static unsigned int reverse(QString &chars, unsigned char *level, unsigned int a, unsigned int b)
Definition: qstring.cpp:11649
void tca::ReverseShower ( std::string  inFcnLabel,
TCSlice slc,
int  cotID,
bool  prt 
)

Definition at line 3180 of file TCShower.cxx.

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

Definition at line 3292 of file Utils.cxx.

3293  {
3294  // reverse the trajectory
3295  if (tj.Pts.empty()) return;
3296  // reverse the crawling direction flag
3297  tj.StepDir = -tj.StepDir;
3298  // Vertices
3299  std::swap(tj.VtxID[0], tj.VtxID[1]);
3300  // trajectory points
3301  std::reverse(tj.Pts.begin(), tj.Pts.end());
3302  // reverse the stop flag
3303  std::reverse(tj.EndFlag.begin(), tj.EndFlag.end());
3304  std::swap(tj.dEdx[0], tj.dEdx[1]);
3305  // reverse the direction vector on all points
3306  for (unsigned short ipt = 0; ipt < tj.Pts.size(); ++ipt) {
3307  if (tj.Pts[ipt].Dir[0] != 0) tj.Pts[ipt].Dir[0] = -tj.Pts[ipt].Dir[0];
3308  if (tj.Pts[ipt].Dir[1] != 0) tj.Pts[ipt].Dir[1] = -tj.Pts[ipt].Dir[1];
3309  if (tj.Pts[ipt].Ang > 0) { tj.Pts[ipt].Ang -= M_PI; }
3310  else {
3311  tj.Pts[ipt].Ang += M_PI;
3312  }
3313  } // ipt
3314  if (tj.StartEnd == 0 || tj.StartEnd == 1) tj.StartEnd = 1 - tj.StartEnd;
3315  SetEndPoints(tj);
3316  // UpdateMatchStructs(slc, tj.ID, tj.ID);
3317  } // ReverseTraj
void SetEndPoints(Trajectory &tj)
Definition: Utils.cxx:3411
void swap(Handle< T > &a, Handle< T > &b)
#define M_PI
Definition: includeROOT.h:54
static unsigned int reverse(QString &chars, unsigned char *level, unsigned int a, unsigned int b)
Definition: qstring.cpp:11649
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:8
void SaveTjInfo(TCSlice &slc, const ShowerStruct &ss, std::string stageName)
Definition: TCShTree.cxx:56
save shower tree
Definition: DataStructs.h:542
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:609
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:8
void SaveTjInfo(TCSlice &slc, const ShowerStruct &ss, std::string stageName)
Definition: TCShTree.cxx:56
save shower tree
Definition: DataStructs.h:542
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:609
void tca::SaveCRInfo ( detinfo::DetectorClocksData const &  clockData,
TCSlice slc,
PFPStruct pfp,
bool  prt,
bool  fIsRealData 
)

Definition at line 29 of file TCCR.cxx.

34  {
35 
36  //Check the origin of pfp
37  if (tcc.modes[kSaveCRTree]) {
38  if (fIsRealData) { slc.crt.cr_origin.push_back(-1); }
39  else {
40  slc.crt.cr_origin.push_back(GetOrigin(clockData, slc, pfp));
41  }
42  }
43 
44  // save the xmin and xmax of each pfp
45  auto& startPos = pfp.TP3Ds[0].Pos;
46  auto& endPos = pfp.TP3Ds[pfp.TP3Ds.size() - 1].Pos;
47  slc.crt.cr_pfpxmin.push_back(std::min(startPos[0], endPos[0]));
48  slc.crt.cr_pfpxmax.push_back(std::max(startPos[0], endPos[0]));
49 
50  //find max
51  const geo::TPCGeo& tpc = tcc.geom->TPC(0);
52  float mindis0 = FLT_MAX;
53  float mindis1 = FLT_MAX;
54  if (std::abs(startPos[1] - tpc.MinY()) < mindis0) mindis0 = std::abs(startPos[1] - tpc.MinY());
55  if (std::abs(startPos[1] - tpc.MaxY()) < mindis0) mindis0 = std::abs(startPos[1] - tpc.MaxY());
56  if (std::abs(startPos[2] - tpc.MinZ()) < mindis0) mindis0 = std::abs(startPos[2] - tpc.MinZ());
57  if (std::abs(startPos[2] - tpc.MaxZ()) < mindis0) mindis0 = std::abs(startPos[2] - tpc.MaxZ());
58  if (std::abs(endPos[1] - tpc.MinY()) < mindis1) mindis1 = std::abs(endPos[1] - tpc.MinY());
59  if (std::abs(endPos[1] - tpc.MaxY()) < mindis1) mindis1 = std::abs(endPos[1] - tpc.MaxY());
60  if (std::abs(endPos[2] - tpc.MinZ()) < mindis1) mindis1 = std::abs(endPos[2] - tpc.MinZ());
61  if (std::abs(endPos[2] - tpc.MaxZ()) < mindis1) mindis1 = std::abs(endPos[2] - tpc.MaxZ());
62  //std::cout<<startPos[1]<<" "<<startPos[2]<<" "<<endPos[1]<<" "<<endPos[2]<<" "<<tpc.MinY()<<" "<<tpc.MaxY()<<" "<<tpc.MinZ()<<" "<<tpc.MaxZ()<<" "<<mindis0<<" "<<mindis1<<" "<<mindis0+mindis1<<std::endl;
63  slc.crt.cr_pfpyzmindis.push_back(mindis0 + mindis1);
64 
65  if (slc.crt.cr_pfpxmin.back() < -2 || slc.crt.cr_pfpxmax.back() > 260 ||
66  slc.crt.cr_pfpyzmindis.back() < 30) {
67  pfp.CosmicScore = 1.;
68  }
69  else
70  pfp.CosmicScore = 0;
71  }
TCConfig tcc
Definition: DataStructs.cxx:8
Geometry information for a single TPC.
Definition: TPCGeo.h:38
int GetOrigin(detinfo::DetectorClocksData const &clockData, TCSlice &slc, PFPStruct &pfp)
Definition: TCCR.cxx:75
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:578
static int max(int a, int b)
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:609
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
save cosmic ray tree
Definition: DataStructs.h:540
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:413
void SaveTjInfoStuff(TCSlice &slc, Trajectory &tj, int stageNum, std::string stageName)
Definition: TCShTree.cxx:140
TCConfig tcc
Definition: DataStructs.cxx:8
std::vector< int > ShowerID
Definition: DataStructs.h:405
ShowerTreeVars stv
Definition: DataStructs.cxx:10
save shower tree
Definition: DataStructs.h:542
std::vector< float > Envelope
Definition: DataStructs.h:411
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:609
std::vector< int > EnvPlane
Definition: DataStructs.h:412
unsigned int CTP_t
Definition: DataStructs.h:49
int GetStageNum(ShowerTreeVars &stv, std::string stageName)
Definition: TCShTree.cxx:194
std::vector< int > EnvShowerID
Definition: DataStructs.h:414
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:413
void SaveTjInfoStuff(TCSlice &slc, Trajectory &tj, int stageNum, std::string stageName)
Definition: TCShTree.cxx:140
std::vector< int > IsShowerParent
Definition: DataStructs.h:406
TCConfig tcc
Definition: DataStructs.cxx:8
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
std::vector< int > ShowerID
Definition: DataStructs.h:405
ShowerTreeVars stv
Definition: DataStructs.cxx:10
save shower tree
Definition: DataStructs.h:542
std::vector< int > TjID
Definition: DataStructs.h:403
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:573
std::vector< float > Envelope
Definition: DataStructs.h:411
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:609
std::vector< int > EnvPlane
Definition: DataStructs.h:412
std::vector< int > StageNum
Definition: DataStructs.h:407
geo::PlaneID DecodeCTP(CTP_t CTP)
int GetStageNum(ShowerTreeVars &stv, std::string stageName)
Definition: TCShTree.cxx:194
std::vector< int > EnvShowerID
Definition: DataStructs.h:414
std::vector< int > IsShowerTj
Definition: DataStructs.h:404
std::vector< short > PlaneNum
Definition: DataStructs.h:401
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:406
std::vector< float > EndWir
Definition: DataStructs.h:393
std::vector< float > EndAng
Definition: DataStructs.h:395
std::vector< float > BeginTim
Definition: DataStructs.h:389
TCConfig tcc
Definition: DataStructs.cxx:8
std::vector< float > BeginAng
Definition: DataStructs.h:390
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
std::vector< float > EndTim
Definition: DataStructs.h:394
std::vector< int > ShowerID
Definition: DataStructs.h:405
ShowerTreeVars stv
Definition: DataStructs.cxx:10
save shower tree
Definition: DataStructs.h:542
std::vector< int > TjID
Definition: DataStructs.h:403
float unitsPerTick
scale factor from Tick to WSE equivalent units
Definition: DataStructs.h:573
std::vector< short > BeginVtx
Definition: DataStructs.h:392
std::vector< short > EndVtx
Definition: DataStructs.h:397
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
std::vector< float > BeginChg
Definition: DataStructs.h:391
std::bitset< 16 > modes
number of points to find AveChg
Definition: DataStructs.h:609
std::vector< short > MCSMom
Definition: DataStructs.h:399
std::vector< int > StageNum
Definition: DataStructs.h:407
unsigned short nPlanes
Definition: DataStructs.h:417
std::vector< float > BeginWir
Definition: DataStructs.h:388
geo::PlaneID DecodeCTP(CTP_t CTP)
std::vector< float > EndChg
Definition: DataStructs.h:396
std::vector< int > IsShowerTj
Definition: DataStructs.h:404
std::vector< short > PlaneNum
Definition: DataStructs.h:401
void tca::ScoreVertices ( TCSlice slc)

Definition at line 2160 of file TCVertex.cxx.

2161  {
2162  // reset all 3D vertex, 2D vertex and Tj high-score vertex bits in tpcid
2163 
2164  // reset the 2D vertex status bits
2165  for (auto& vx : slc.vtxs) {
2166  if (vx.ID == 0) continue;
2167  vx.Stat[kHiVx3Score] = false;
2168  } // vx
2169  // and the tj bits
2170  for (auto& tj : slc.tjs) {
2171  if (tj.AlgMod[kKilled] || tj.AlgMod[kHaloTj]) continue;
2172  tj.AlgMod[kTjHiVx3Score] = false;
2173  } // tj
2174  // Score the 2D vertices
2175  for (auto& vx : slc.vtxs) {
2176  if (vx.ID == 0) continue;
2177  SetVx2Score(slc, vx);
2178  } // vx
2179  // Score the 3D vertices
2180  for (auto& vx3 : slc.vtx3s) {
2181  if (vx3.ID == 0) continue;
2182  SetVx3Score(slc, vx3);
2183  } // vx3
2184  } // ScoreVertices
matched to a high-score 3D vertex
Definition: DataStructs.h:97
void SetVx3Score(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2256
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2288
bool tca::SectionStartEnd ( const PFPStruct pfp,
unsigned short  sfIndex,
unsigned short &  startPt,
unsigned short &  endPt 
)

Definition at line 3311 of file PFPUtils.cxx.

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

Definition at line 771 of file Utils.cxx.

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

Definition at line 428 of file Utils.h.

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

Definition at line 3411 of file Utils.cxx.

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

Definition at line 2207 of file TCVertex.cxx.

2208  {
2209  // Sets the tj and 2D vertex score bits to true
2210 
2211  if (vx3.ID == 0) return;
2212 
2213  for (unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
2214  if (vx3.Vx2ID[ipl] <= 0) continue;
2215  VtxStore& vx2 = slc.vtxs[vx3.Vx2ID[ipl] - 1];
2216  vx2.Stat[kHiVx3Score] = false;
2217  // transfer this to all attached tjs and vertices attached to those tjs
2218  std::vector<int> tjlist = GetVtxTjIDs(slc, vx2);
2219  std::vector<int> vxlist;
2220  while (true) {
2221  // tag Tjs and make a list of attached vertices whose high-score
2222  // bit needs to be set
2223  vxlist.clear();
2224  for (auto tjid : tjlist) {
2225  auto& tj = slc.tjs[tjid - 1];
2226  tj.AlgMod[kTjHiVx3Score] = true;
2227  for (unsigned short end = 0; end < 2; ++end) {
2228  if (tj.VtxID[end] == 0) continue;
2229  auto& vx2 = slc.vtxs[tj.VtxID[end] - 1];
2230  if (vx2.Stat[kHiVx3Score]) continue;
2231  vx2.Stat[kHiVx3Score] = true;
2232  vxlist.push_back(vx2.ID);
2233  } // end
2234  } // tjid
2235 
2236  if (vxlist.empty()) break;
2237  // re-build tjlist using vxlist
2238  std::vector<int> newtjlist;
2239  for (auto vxid : vxlist) {
2240  auto& vx2 = slc.vtxs[vxid - 1];
2241  auto tmp = GetVtxTjIDs(slc, vx2);
2242  for (auto tjid : tmp) {
2243  if (std::find(tjlist.begin(), tjlist.end(), tjid) == tjlist.end())
2244  newtjlist.push_back(tjid);
2245  } // tjid
2246  } // vxid
2247  if (newtjlist.empty()) break;
2248  tjlist = newtjlist;
2249  } // true
2250  } // ipl
2251 
2252  } // SetHighScoreBits
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
matched to a high-score 3D vertex
Definition: DataStructs.h:97
string tmp
Definition: languages.py:63
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:2868
template<typename T >
std::vector< T > tca::SetIntersection ( const std::vector< T > &  set1,
const std::vector< T > &  set2 
)

Definition at line 405 of file Utils.h.

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

Definition at line 2582 of file PFPUtils.cxx.

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

Definition at line 3345 of file Utils.cxx.

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

Definition at line 1830 of file TCShower.cxx.

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

Definition at line 4348 of file Utils.cxx.

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

Definition at line 4356 of file Utils.cxx.

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

Definition at line 2769 of file PFPUtils.cxx.

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

Definition at line 338 of file StepUtils.cxx.

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

Definition at line 3624 of file Utils.cxx.

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

Definition at line 2278 of file TCVertex.cxx.

2279  {
2280  // A version that sets the score of the last added vertex
2281  if (slc.vtxs.empty()) return;
2282  auto& vx2 = slc.vtxs[slc.vtxs.size() - 1];
2283  SetVx2Score(slc, vx2);
2284  } // SetVx2Score
void SetVx2Score(TCSlice &slc, VtxStore &vx2)
Definition: TCVertex.cxx:2288
void tca::SetVx2Score ( TCSlice slc,
VtxStore vx2 
)

Definition at line 2288 of file TCVertex.cxx.

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

Definition at line 2256 of file TCVertex.cxx.

2257  {
2258  // Calculate the 3D vertex score and flag Tjs that are attached to high score vertices as defined
2259  // by vtx2DCuts
2260 
2261  if (vx3.ID == 0) return;
2262 
2263  vx3.Score = 0;
2264  for (unsigned short ipl = 0; ipl < slc.nPlanes; ++ipl) {
2265  if (vx3.Vx2ID[ipl] <= 0) continue;
2266  VtxStore& vx2 = slc.vtxs[vx3.Vx2ID[ipl] - 1];
2267  vx3.Score += vx2.Score;
2268  } // ipl
2269  vx3.Score /= (float)slc.nPlanes;
2270  // don't allow it to get too small or negative
2271  if (vx3.Score < 0.001) vx3.Score = 0.001;
2272  if (vx3.Score > tcc.vtx2DCuts[7]) SetHighScoreBits(slc, vx3);
2273 
2274  } // SetVx3Score
TCConfig tcc
Definition: DataStructs.cxx:8
void SetHighScoreBits(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2207
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:552
if(!yymsg) yymsg
double tca::ShowerEnergy ( const ShowerStruct3D ss3)

Definition at line 3952 of file TCShower.cxx.

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

Definition at line 3966 of file TCShower.cxx.

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

Definition at line 1921 of file TCShower.cxx.

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

Definition at line 1941 of file TCShower.cxx.

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

Definition at line 2002 of file Utils.cxx.

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

Definition at line 1960 of file Utils.cxx.

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

Definition at line 1805 of file Utils.cxx.

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

Definition at line 1831 of file Utils.cxx.

1832  {
1833  // Returns true if there is a signal on > MinWireSignalFraction of the wires between tp and toPos0.
1834  return ChgFracBetween(slc, tp, toPos0) >= MinWireSignalFraction;
1835  } // SignalBetween
float ChgFracBetween(const TCSlice &slc, TrajPoint tp, float toPos0)
Definition: Utils.cxx:1839
bool tca::SortSection ( PFPStruct pfp,
unsigned short  sfIndex 
)

Definition at line 2027 of file PFPUtils.cxx.

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

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

Definition at line 2317 of file Utils.cxx.

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

Definition at line 937 of file TCVertex.cxx.

938  {
939  // This is kind of self-explanatory...
940 
941  if (!tcc.useAlg[kSplitTjCVx]) return;
942 
943  if (slc.vtxs.empty()) return;
944  if (slc.tjs.empty()) return;
945 
946  constexpr float docaCut = 4;
947 
948  bool prt = (tcc.modes[kDebug] && tcc.dbgSlc && tcc.dbgAlg[kSplitTjCVx]);
949  if (prt) mf::LogVerbatim("TC") << "Inside SplitTrajCrossingVertices inCTP " << inCTP;
950 
951  geo::PlaneID planeID = DecodeCTP(inCTP);
952 
953  unsigned short nTraj = slc.tjs.size();
954  for (unsigned short itj = 0; itj < nTraj; ++itj) {
955  // NOTE: Don't use a reference variable because it may get lost if the tj is split
956  if (slc.tjs[itj].CTP != inCTP) continue;
957  // obsolete trajectory
958  if (slc.tjs[itj].AlgMod[kKilled] || slc.tjs[itj].AlgMod[kHaloTj]) continue;
959  if (slc.tjs[itj].AlgMod[kJunkTj]) continue;
960  if (slc.tjs[itj].AlgMod[kSplitTjCVx]) continue;
961  // too short
962  if (slc.tjs[itj].EndPt[1] < 6) continue;
963  for (unsigned short iv = 0; iv < slc.vtxs.size(); ++iv) {
964  auto& vx2 = slc.vtxs[iv];
965  // obsolete vertex
966  if (vx2.NTraj == 0) continue;
967  // trajectory already associated with vertex
968  if (slc.tjs[itj].VtxID[0] == vx2.ID || slc.tjs[itj].VtxID[1] == vx2.ID) continue;
969  // not in the cryostat/tpc/plane
970  if (slc.tjs[itj].CTP != vx2.CTP) continue;
971  // poor quality
972  if (vx2.Score < tcc.vtx2DCuts[7]) continue;
973  float doca = docaCut;
974  // make the cut significantly larger if the vertex is in a dead
975  // wire gap to get the first TP that is just outside the gap.
976  if (vx2.Stat[kOnDeadWire]) doca = 100;
977  unsigned short closePt = 0;
978  if (!TrajClosestApproach(slc.tjs[itj], vx2.Pos[0], vx2.Pos[1], closePt, doca)) continue;
979  if (vx2.Stat[kOnDeadWire]) {
980  // special handling for vertices in dead wire regions. Find the IP between
981  // the closest point on the Tj and the vertex
982  doca = PointTrajDOCA(slc, vx2.Pos[0], vx2.Pos[1], slc.tjs[itj].Pts[closePt]);
983  }
984  if (doca > docaCut) continue;
985  if (prt)
986  mf::LogVerbatim("TC") << " doca " << doca << " btw T" << slc.tjs[itj].ID << " and 2V"
987  << slc.vtxs[iv].ID << " closePt " << closePt << " in plane "
988  << planeID.Plane;
989  // compare the length of the Tjs used to make the vertex with the length of the
990  // Tj that we want to split. Don't allow a vertex using very short Tjs to split a long
991  // Tj in the 3rd plane
992  auto vxtjs = GetVtxTjIDs(slc, vx2);
993  if (vxtjs.empty()) continue;
994  unsigned short maxPts = 0;
995  // ensure that there is a large angle between a Tj already attached to the vertex and the
996  // tj that we want to split. We might be considering a delta-ray here
997  float maxdang = 0.3;
998  float tjAng = slc.tjs[itj].Pts[closePt].Ang;
999  for (auto tjid : vxtjs) {
1000  auto& vtj = slc.tjs[tjid - 1];
1001  if (vtj.AlgMod[kDeltaRay]) continue;
1002  unsigned short npwc = NumPtsWithCharge(slc, vtj, false);
1003  if (npwc > maxPts) maxPts = npwc;
1004  unsigned short end = 0;
1005  if (vtj.VtxID[1] == slc.vtxs[iv].ID) end = 1;
1006  auto& vtp = vtj.Pts[vtj.EndPt[end]];
1007  float dang = DeltaAngle(vtp.Ang, tjAng);
1008  if (dang > maxdang) maxdang = dang;
1009  } // tjid
1010  // skip this operation if any of the Tjs in the split list are > 3 * maxPts
1011  maxPts *= 3;
1012  bool skipit = false;
1013  if (NumPtsWithCharge(slc, slc.tjs[itj], false) > maxPts && maxPts < 100) skipit = true;
1014  if (!skipit && maxdang < 0.3) skipit = true;
1015  if (prt)
1016  mf::LogVerbatim("TC") << " maxPts " << maxPts << " vxtjs[0] " << vxtjs[0] << " maxdang "
1017  << maxdang << " skipit? " << skipit;
1018  if (skipit) {
1019  // kill the vertex?
1020  if (doca < 1) MakeVertexObsolete("STCV", slc, vx2, true);
1021  continue;
1022  }
1023 
1024  // make some adjustments to closePt
1025  if (vx2.Stat[kOnDeadWire]) {
1026  // ensure that the tj will be split at the gap. The closePt point may be
1027  // on the wrong side of it
1028  auto& closeTP = slc.tjs[itj].Pts[closePt];
1029  if (slc.tjs[itj].StepDir > 0 && closePt > slc.tjs[itj].EndPt[0]) {
1030  if (closeTP.Pos[0] > vx2.Pos[0]) --closePt;
1031  }
1032  else if (slc.tjs[itj].StepDir < 0 && closePt < slc.tjs[itj].EndPt[1]) {
1033  if (closeTP.Pos[0] < vx2.Pos[0]) ++closePt;
1034  }
1035  }
1036  else {
1037  // improve closePt based on vertex position
1038  // check if closePt and EndPt[1] are the two sides of vertex
1039  // take dot product of closePt-vtx and EndPt[1]-vtx
1040  if ((slc.tjs[itj].Pts[closePt].Pos[0] - vx2.Pos[0]) *
1041  (slc.tjs[itj].Pts[slc.tjs[itj].EndPt[1]].Pos[0] - vx2.Pos[0]) +
1042  (slc.tjs[itj].Pts[closePt].Pos[1] - vx2.Pos[1]) *
1043  (slc.tjs[itj].Pts[slc.tjs[itj].EndPt[1]].Pos[1] - vx2.Pos[1]) <
1044  0 &&
1045  closePt < slc.tjs[itj].EndPt[1] - 1)
1046  ++closePt;
1047  else if ((slc.tjs[itj].Pts[closePt].Pos[0] - vx2.Pos[0]) *
1048  (slc.tjs[itj].Pts[slc.tjs[itj].EndPt[0]].Pos[0] - vx2.Pos[0]) +
1049  (slc.tjs[itj].Pts[closePt].Pos[1] - vx2.Pos[1]) *
1050  (slc.tjs[itj].Pts[slc.tjs[itj].EndPt[0]].Pos[1] - slc.vtxs[iv].Pos[1]) <
1051  0 &&
1052  closePt > slc.tjs[itj].EndPt[0] + 1)
1053  --closePt;
1054  }
1055 
1056  if (prt) {
1057  mf::LogVerbatim("TC") << "Good doca " << doca << " btw T" << slc.tjs[itj].ID << " and 2V"
1058  << vx2.ID << " closePt " << closePt << " in plane " << planeID.Plane
1059  << " CTP " << slc.vtxs[iv].CTP;
1060  PrintTP("STCV", slc, closePt, 1, slc.tjs[itj].Pass, slc.tjs[itj].Pts[closePt]);
1061  }
1062  // ensure that the closest point is not near an end
1063  if (closePt < slc.tjs[itj].EndPt[0] + 3) continue;
1064  if (closePt > slc.tjs[itj].EndPt[1] - 3) continue;
1065  if (!SplitTraj(slc, itj, closePt, iv, prt)) {
1066  if (prt) mf::LogVerbatim("TC") << "SplitTrajCrossingVertices: Failed to split trajectory";
1067  continue;
1068  }
1069  slc.tjs[itj].AlgMod[kSplitTjCVx] = true;
1070  unsigned short newTjIndex = slc.tjs.size() - 1;
1071  slc.tjs[newTjIndex].AlgMod[kSplitTjCVx] = true;
1072  // re-fit the vertex position
1073  FitVertex(slc, vx2, prt);
1074  } // iv
1075  } // itj
1076 
1077  } // SplitTrajCrossingVertices
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool MakeVertexObsolete(TCSlice &slc, Vtx3Store &vx3)
Definition: TCVertex.cxx:2832
TCConfig tcc
Definition: DataStructs.cxx:8
void PrintTP(std::string someText, const TCSlice &slc, unsigned short ipt, short dir, unsigned short pass, const TrajPoint &tp)
Definition: Utils.cxx:6294
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:2688
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2570
double DeltaAngle(const Vector3_t v1, const Vector3_t v2)
Definition: PFPUtils.cxx:2539
bool dbgSlc
debug only in the user-defined slice? default is all slices
Definition: DataStructs.h:592
bool FitVertex(TCSlice &slc, VtxStore &vx, std::vector< TrajPoint > &vxTPs, bool prt)
Definition: TCVertex.cxx:2018
bool SplitTraj(detinfo::DetectorPropertiesData const &detProp, TCSlice &slc, unsigned short itj, float XPos, bool makeVx2, bool prt)
Definition: Utils.cxx:2270
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:609
std::bitset< 128 > useAlg
Max hit separation for making junk trajectories. < 0 to turn off.
Definition: DataStructs.h:588
std::vector< int > GetVtxTjIDs(const TCSlice &slc, const Vtx3Store &vx3, float &score)
Definition: TCVertex.cxx:2868
geo::PlaneID DecodeCTP(CTP_t CTP)
std::bitset< 128 > dbgAlg
Allow user to turn on debug printing in algorithms (that print...)
Definition: DataStructs.h:589
std::vector< float > vtx2DCuts
Max position pull, max Position error rms.
Definition: DataStructs.h:552
unsigned short NumPtsWithCharge(const TCSlice &slc, const Trajectory &tj, bool includeDeadWires)
Definition: Utils.cxx:2114
master switch for turning on debug mode
Definition: DataStructs.h:535
bool tca::SptInTPC ( const std::array< unsigned int, 3 > &  sptHits,
unsigned int  tpc 
)

Definition at line 792 of file PFPUtils.cxx.

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

Definition at line 3823 of file TCShower.cxx.

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

Definition at line 4999 of file Utils.cxx.

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

Definition at line 5032 of file Utils.cxx.

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

Definition at line 28 of file StepUtils.cxx.

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

Definition at line 41 of file PFPUtils.cxx.

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

Definition at line 2527 of file StepUtils.cxx.

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

Definition at line 277 of file StepUtils.cxx.

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

Definition at line 3003 of file PFPUtils.cxx.

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

Definition at line 3989 of file TCShower.cxx.

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

Definition at line 4040 of file TCShower.cxx.

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

Definition at line 1087 of file Utils.cxx.

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

Definition at line 1932 of file TCVertex.cxx.

1933  {
1934  // jacket around the push to ensure that the Tj and vtx CTP is consistent.
1935  // The calling function should score the vertex after the trajectories are attached
1936 
1937  if (vx.ID != int(slc.vtxs.size() + 1)) return false;
1938 
1939  ++evt.global2V_UID;
1940  vx.UID = evt.global2V_UID;
1941 
1942  unsigned short nvxtj = 0;
1943  unsigned short nok = 0;
1944  for (auto& tj : slc.tjs) {
1945  if (tj.AlgMod[kKilled]) continue;
1946  if (vx.ID == tj.VtxID[0] || vx.ID == tj.VtxID[1]) ++nvxtj;
1947  if (vx.CTP != tj.CTP) continue;
1948  if (vx.ID == tj.VtxID[0] || vx.ID == tj.VtxID[1]) ++nok;
1949  } // tj
1950 
1951  if (nok != nvxtj) {
1952  mf::LogVerbatim("TC") << "StoreVertex: vertex " << vx.ID << " Topo " << vx.Topo
1953  << " has inconsistent CTP code " << vx.CTP << " with one or more Tjs\n";
1954  for (auto& tj : slc.tjs) {
1955  if (tj.AlgMod[kKilled]) continue;
1956  if (tj.VtxID[0] == vx.ID) tj.VtxID[0] = 0;
1957  if (tj.VtxID[1] == vx.ID) tj.VtxID[1] = 0;
1958  }
1959  return false;
1960  }
1961  vx.NTraj = nok;
1962  slc.vtxs.push_back(vx);
1963  return true;
1964  } // StoreVertex
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
TCEvent evt
Definition: DataStructs.cxx:7
void tca::TagJunkTj ( TCSlice slc,
Trajectory tj,
bool  prt 
)

Definition at line 2780 of file Utils.cxx.

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

Definition at line 3274 of file TCShower.cxx.

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

Definition at line 668 of file PFPUtils.cxx.

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

Definition at line 3582 of file Utils.cxx.

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

Definition at line 6351 of file Utils.cxx.

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

Definition at line 4207 of file Utils.cxx.

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

Definition at line 4200 of file Utils.cxx.

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

Definition at line 1582 of file TCVertex.cxx.

1583  {
1584  // Returns the index of a vertex if tp is nearby
1585  for (unsigned short ivx = 0; ivx < slc.vtxs.size(); ++ivx) {
1586  if (slc.vtxs[ivx].ID == 0) continue;
1587  if (slc.vtxs[ivx].CTP != tp.CTP) continue;
1588  if (std::abs(slc.vtxs[ivx].Pos[0] - tp.Pos[0]) > 1.2) continue;
1589  if (std::abs(slc.vtxs[ivx].Pos[1] - tp.Pos[1]) > 1.2) continue;
1590  return ivx;
1591  } // ivx
1592  return USHRT_MAX;
1593  } // TPNearVertex
T abs(T value)
float tca::TpSumHitChg ( const TCSlice slc,
TrajPoint const &  tp 
)

Definition at line 2102 of file Utils.cxx.

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

Definition at line 2688 of file Utils.cxx.

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

Definition at line 1871 of file Utils.cxx.

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

Definition at line 1919 of file Utils.cxx.

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

Definition at line 2602 of file Utils.cxx.

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

Definition at line 2608 of file Utils.cxx.

2609  {
2610  // returns the intersection position, (x,y), of two trajectory points
2611 
2612  x = -9999;
2613  y = -9999;
2614 
2615  double arg1 = tp1.Pos[0] * tp1.Dir[1] - tp1.Pos[1] * tp1.Dir[0];
2616  double arg2 = tp2.Pos[0] * tp1.Dir[1] - tp2.Pos[1] * tp1.Dir[0];
2617  double arg3 = tp2.Dir[0] * tp1.Dir[1] - tp2.Dir[1] * tp1.Dir[0];
2618  if (arg3 == 0) return;
2619  double s = (arg1 - arg2) / arg3;
2620 
2621  x = (float)(tp2.Pos[0] + s * tp2.Dir[0]);
2622  y = (float)(tp2.Pos[1] + s * tp2.Dir[1]);
2623 
2624  } // TrajIntersection
list x
Definition: train.py:276
static QCString * s
Definition: config.cpp:1042
bool tca::TrajIsClean ( TCSlice slc,
Trajectory tj,
bool  prt 
)

Definition at line 3440 of file Utils.cxx.

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

Definition at line 2644 of file Utils.cxx.

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

Definition at line 2678 of file Utils.cxx.

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

Definition at line 2433 of file Utils.cxx.

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

Definition at line 1865 of file TCVertex.cxx.

1866  {
1867  // Calculates the position pull between a trajectory point and a vertex
1868 
1869  // impact parameter between them
1870  double ip = PointTrajDOCA(slc, vx.Pos[0], vx.Pos[1], tp);
1871  // separation^2
1872  double sep2 = PosSep2(vx.Pos, tp.Pos);
1873 
1874  // Find the projection of the vertex error ellipse in a coordinate system
1875  // along the TP direction
1876  double vxErrW = vx.PosErr[0] * tp.Dir[1];
1877  double vxErrT = vx.PosErr[1] * tp.Dir[0];
1878  double vxErr2 = vxErrW * vxErrW + vxErrT * vxErrT;
1879  // add the TP position error^2
1880  vxErr2 += tp.HitPosErr2;
1881 
1882  // close together so ignore the TP projection error and return
1883  // the pull using the vertex error and TP position error
1884  if (sep2 < 1) return (float)(ip / sqrt(vxErr2));
1885 
1886  double dang = ip / sqrt(sep2);
1887 
1888  // calculate the angle error.
1889  // Start with the vertex error^2
1890  double angErr = vxErr2 / sep2;
1891  // Add the TP angle error^2
1892  angErr += tp.AngErr * tp.AngErr;
1893  if (angErr == 0) return 999;
1894  angErr = sqrt(angErr);
1895  return (float)(dang / angErr);
1896 
1897  } // TrajPointVertexPull
float PointTrajDOCA(const TCSlice &slc, unsigned int iht, TrajPoint const &tp)
Definition: Utils.cxx:2570
double PosSep2(const Point3_t &pos1, const Point3_t &pos2)
Definition: PFPUtils.cxx:2571
bool tca::TrajTrajDOCA ( const TCSlice slc,
const Trajectory tj1,
const Trajectory tj2,
unsigned short &  ipt1,
unsigned short &  ipt2,
float &  minSep 
)

Definition at line 2458 of file Utils.cxx.

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

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

Definition at line 3896 of file TCShower.cxx.

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

Definition at line 1598 of file Utils.cxx.

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

Definition at line 1555 of file Utils.cxx.

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

Definition at line 2719 of file Utils.cxx.

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

Definition at line 1073 of file Utils.cxx.

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

Definition at line 1056 of file PFPUtils.cxx.

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

Definition at line 2347 of file StepUtils.cxx.

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

Definition at line 911 of file TCShower.cxx.

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

Definition at line 1116 of file TCShower.cxx.

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

Definition at line 646 of file StepUtils.cxx.

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

Definition at line 3671 of file Utils.cxx.

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

Definition at line 667 of file StepUtils.cxx.

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

Definition at line 3860 of file Utils.cxx.

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

Definition at line 3883 of file Utils.cxx.

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

Definition at line 33 of file TCVertex.cxx.

34  {
35  return (c1.val > c2.val);
36  }
float val
Definition: DataStructs.h:38
bool tca::ValidTwoPlaneMatch ( detinfo::DetectorPropertiesData const &  detProp,
const TCSlice slc,
const PFPStruct pfp 
)

Definition at line 1796 of file PFPUtils.cxx.

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

Definition at line 38 of file TCVertex.cxx.

39  {
40  return (c1.val < c2.val);
41  }
float val
Definition: DataStructs.h:38
float tca::VertexVertexPull ( const TCSlice slc,
const Vtx3Store vx1,
const Vtx3Store vx2 
)

Definition at line 1901 of file TCVertex.cxx.

1902  {
1903  // Calculates the position pull between two vertices
1904  double dx = vx1.X - vx2.X;
1905  double dy = vx1.Y - vx2.Y;
1906  double dz = vx1.Z - vx2.Z;
1907  double dxErr2 = (vx1.XErr * vx1.XErr + vx2.XErr * vx2.XErr) / 2;
1908  double dyErr2 = (vx1.YErr * vx1.YErr + vx2.YErr * vx2.YErr) / 2;
1909  double dzErr2 = (vx1.ZErr * vx1.ZErr + vx2.ZErr * vx2.ZErr) / 2;
1910  dx = dx * dx / dxErr2;
1911  dy = dy * dy / dyErr2;
1912  dz = dz * dz / dzErr2;
1913  return (float)(sqrt(dx + dy + dz) / 3);
1914  }
float tca::VertexVertexPull ( const TCSlice slc,
const VtxStore vx1,
const VtxStore vx2 
)

Definition at line 1918 of file TCVertex.cxx.

1919  {
1920  // Calculates the position pull between two vertices
1921  double dw = vx1.Pos[0] - vx2.Pos[0];
1922  double dt = vx1.Pos[1] - vx2.Pos[1];
1923  double dwErr2 = (vx1.PosErr[0] * vx1.PosErr[0] + vx2.PosErr[0] * vx2.PosErr[0]) / 2;
1924  double dtErr2 = (vx1.PosErr[1] * vx1.PosErr[1] + vx2.PosErr[1] * vx2.PosErr[1]) / 2;
1925  dw = dw * dw / dwErr2;
1926  dt = dt * dt / dtErr2;
1927  return (float)sqrt(dw + dt);
1928  }
bool tca::WireHitRangeOK ( TCSlice slc,
const CTP_t inCTP 
)

Definition at line 4651 of file Utils.cxx.

4652  {
4653  // returns true if the passed CTP code is consistent with the CT code of the WireHitRangeVector
4654  geo::PlaneID planeID = DecodeCTP(inCTP);
4655  if (planeID.Cryostat != slc.TPCID.Cryostat) return false;
4656  if (planeID.TPC != slc.TPCID.TPC) return false;
4657  return true;
4658  }
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 2266 of file TCShower.cxx.

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

Variable Documentation

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

Definition at line 15 of file DataStructs.cxx.

constexpr unsigned int tca::Cpad = 10000

Definition at line 51 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 87 of file DataStructs.cxx.

TCEvent tca::evt

Definition at line 7 of file DataStructs.cxx.

constexpr unsigned int tca::pAlgModSize = 6

Definition at line 282 of file DataStructs.h.

std::vector< TrajPoint > tca::seeds

Definition at line 13 of file DataStructs.cxx.

std::vector< TCSlice > tca::slices

Definition at line 12 of file DataStructs.cxx.

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

Definition at line 108 of file DataStructs.cxx.

ShowerTreeVars tca::stv

Definition at line 10 of file DataStructs.cxx.

TCConfig tca::tcc

Definition at line 8 of file DataStructs.cxx.

std::vector< TjForecast > tca::tjfs

Definition at line 9 of file DataStructs.cxx.

constexpr unsigned int tca::Tpad = 10

Definition at line 50 of file DataStructs.h.

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

Definition at line 97 of file DataStructs.cxx.