BmnRoot 26.10.0-210-gc52d34b0
Software framework of the BM@N experiment
Loading...
Searching...
No Matches
BmnRootIterator.cxx
Go to the documentation of this file.
1/*
2 BM@N alignment routine
3 BM@N experiment at NICA complex, JINR, 2025
4
5 Department: Math & Soft Group of HEP lab
6 Author: Igor Polev, polev@jinr.int
7
8 BmnRootIterator class implementation
9*/
10// TODO: check if we can use std::move() across the project to optimize a little
11#include "BmnRootIterator.h"
12
13#include "BmnHit.h"
14#include "BmnWeightedLine.h"
15#include "fairlogger/Logger.h"
16
17#include <utility>
18
19namespace
20{
21constexpr Int_t SIBT_STATIONS{3}; // the beam line needs one hit in each, numbered from 0 along the beam
22} // anonymous namespace
23
24BmnRootIterator::BmnRootIterator(const char* filesPathList,
25 const BmnDetectorModel& detModel,
26 TrackFilter_t trackFilter,
27 HitFilter_t hitFilter,
29 Bool_t verbose,
30 Int_t maxTracks)
31 : BmnDataIterator(pb)
32 , fpDetModel(&detModel)
33 , fTrackFilter(std::move(trackFilter))
34 , fHitFilter(std::move(hitFilter))
35 , fpData(new BmnDataReader(filesPathList, verbose))
36 , fpReader(&fpData->Reader())
37 , fTrackLimit(maxTracks)
38{
39 if (!fTrackFilter)
40 fTrackFilter = [](const Track_t&, Int_t) { return kTRUE; };
41 if (!fHitFilter)
42 fHitFilter = [](const Hit_t&) { return kTRUE; };
43
44 // detect whether the source data has a DstEventHeader branch
45 Bool_t hasEventHeader{fpData->Chain().GetBranch(BMN_EVENT_BRANCH_NAME) != nullptr};
46
47 const Bool_t withVertex{detModel.TargetID() >= 0};
48 if (withVertex) {
49 if (detModel.Target().zEnd <= detModel.Target().zStart) {
50 LOG(error) << " <!> BmnRootIterator : the detector model has a target element but no"
51 " target geometry - pass the target .geo file to its Init()";
52 return;
53 }
54 if (!fpData->Chain().GetBranch(BMN_BEAM_BRANCH_NAME)) {
55 LOG(error) << " <!> BmnRootIterator : the detector model has a target element but the data"
56 " has no " BMN_BEAM_BRANCH_NAME " branch to build the vertex hit from";
57 return;
58 }
59 }
60
61 // turn off unneeded branches
62 // notice: turning off branches works weirdly and does not give any speedup
63 // but let it be for now - maybe it will give something later
64 fpData->Chain().SetBranchStatus("*", kFALSE);
65 fpData->Chain().SetBranchStatus(BMN_TRACKS_BRANCH_NAME "*", kTRUE);
66 fpData->Chain().SetBranchStatus(BMN_HITS_BRANCH_NAME "*", kTRUE);
67 if (hasEventHeader)
68 fpData->Chain().SetBranchStatus(BMN_EVENT_BRANCH_NAME "*", kTRUE);
69 if (withVertex)
70 fpData->Chain().SetBranchStatus(BMN_BEAM_BRANCH_NAME "*", kTRUE);
71
72 // Tryed to use TTreeReaderArray but failed to make it work
73 fpRootTracks = new TTreeReaderValue<TClonesArray>{*fpReader, BMN_TRACKS_BRANCH_NAME};
74 fpRootHits = new TTreeReaderValue<TClonesArray>{*fpReader, BMN_HITS_BRANCH_NAME};
75 if (hasEventHeader)
77 if (withVertex)
79
80 fProgressByTracks = kFALSE; // progress by events until tracks are counted
81 fTotalEvents = fpReader->GetEntries(kTRUE); // without kTRUE result is not guaranteed
83
85}
86
88{
89 delete fpRootTracks;
90 delete fpRootHits;
91 delete fpRootBeamHits;
92 delete fpRootEventHeader;
93 delete fpData;
94}
95
97{
98 // Count all tracks and hits that matches minimum number
99 // of hits per track and maximum allowed chi2 per hit,
100 // Filtration is built in ResetAll() and NextTrack() directly.
101 LOG_IF(warning, fTrackLimit) << " ! track limit is set to " << fTrackLimit << " tracks";
102 LOG(info) << " counting suitable tracks...";
103
105 fProgressByTracks = kFALSE; // progress by events
107 fTotalTracks = 0;
108 fTotalHits = 0;
109 ResetAll();
110 while (!EndOfTracks()) {
111 fTotalTracks++;
113 NextTrack();
114 }
118
119 LOG(info) << " " << fTotalTracks << " total suitable tracks found";
120 LOG(info) << " " << fTotalHits << " total hits counted";
121 LOG(info) << " " << fTotalEvents << " events processed";
122}
123
125{
126 if (!fInitialized)
127 return;
128
129 if (fpRootBeamHits)
130 fVertexZ = 0.5 * (fpDetModel->Target().zStart + fpDetModel->Target().zEnd);
132 fpReader->Restart();
133 Bool_t event = fpReader->Next();
134 if (!event)
135 return; // no events at all
137 ProgressTick();
138
139 // search for event with tracks
140 fTracksInEvent = (*fpRootTracks)->GetEntries();
141 while (event && fTracksInEvent <= 0) {
142 event = fpReader->Next();
144 ProgressTick();
145 fTracksInEvent = (*fpRootTracks)->GetEntries();
146 }
147 if (!event)
148 return; // no events with tracks
150 fEventID = (*fpRootEventHeader)->GetEventId();
151 ScanEvent();
152
153 fpCurrentTrack = (Track_t*)(*fpRootTracks)->At(0);
154 fTrackIdx = 0;
156 // CountUsableHits() first: the track predicate is told how many hits will
157 // actually be read, not how many the track claims
159 NextTrack();
160 else {
161 fTrackCount = 1;
162 fEventTracks = 1;
163 ResetHits();
164 }
165}
166
168{
170 return;
173 return;
174 }
175 do {
176 if (++fTrackIdx >= fTracksInEvent) {
177 Bool_t event{fpReader->Next()};
179 ProgressTick();
180 if (event) {
181 fTracksInEvent = (*fpRootTracks)->GetEntries();
182 while (event && fTracksInEvent <= 0) {
183 event = fpReader->Next();
185 ProgressTick();
186 fTracksInEvent = (*fpRootTracks)->GetEntries();
187 }
188 }
189 // (!event) must be checked againg, don't use else
190 if (!event) { // no more events - no more tracks
192 return;
193 }
195 fEventID = (*fpRootEventHeader)->GetEventId();
196 fTrackIdx = 0;
197 fEventTracks = 0;
198 ScanEvent();
199 }
200 fpCurrentTrack = (Track_t*)(*fpRootTracks)->At(fTrackIdx);
202 fTrackCount++;
203 fEventTracks++;
204 ResetHits();
206 ProgressTick();
207}
208
209/*
210 * Builds the vertex hit of the event just read. The beam line is fitted
211 * through the SiBT hits and taken at the target centre. Every track that
212 * passes the filters takes that hit; BmnAligner::Align() later disables the
213 * ones whose residual shows the track does not come from the vertex. The beam
214 * gives one measurement per event, so its weight is shared out among those N
215 * tracks instead of being counted N times.
216 */
218{
219 fVertexTrack.clear();
220 if (!fpRootBeamHits)
221 return;
222
223 const TClonesArray& beamHits{**fpRootBeamHits};
224 if (SIBT_STATIONS != beamHits.GetEntriesFast())
225 return;
226 BmnWeightedLine lineX, lineY;
227 UInt_t stations{0};
228 for (Int_t i{0}; i < SIBT_STATIONS; i++) {
229 const BmnHit& hit{*static_cast<BmnHit*>(beamHits.At(i))};
230 if (hit.GetStation() >= 0 && hit.GetStation() < SIBT_STATIONS)
231 stations |= 1u << hit.GetStation();
232 lineX.Add(hit.GetZ(), hit.GetX(), BmnHitRecord::Weight(hit.GetDx()));
233 lineY.Add(hit.GetZ(), hit.GetY(), BmnHitRecord::Weight(hit.GetDy()));
234 }
235 if (stations != (1u << SIBT_STATIONS) - 1)
236 return;
237
239 Int_t vertexTracks{0};
240 for (Int_t i{0}; i < fTracksInEvent; i++) {
241 const Track_t& track{*static_cast<Track_t*>((*fpRootTracks)->At(i))};
242 Int_t usableHits{0};
243 for (Int_t h{0}; h < track.GetNStsHits(); h++)
244 if (fHitFilter(*static_cast<Hit_t*>((*fpRootHits)->At(track.GetStsHitIndex(h)))))
245 usableHits++;
246 if (!fTrackFilter(track, usableHits))
247 continue;
249 vertexTracks++;
250 }
251 if (!vertexTracks)
252 return;
253
254 fVertexX = lineX.At(fVertexZ);
255 fVertexY = lineY.At(fVertexZ);
256 fVertexVarX = lineX.Var(fVertexZ);
257 fVertexVarY = lineY.Var(fVertexZ);
258 fVertexWx = 1.0 / (fVertexVarX * vertexTracks);
259 fVertexWy = 1.0 / (fVertexVarY * vertexTracks);
260}
std::function< Bool_t(const CbmStsHit &)> HitFilter_t
std::function< Bool_t(const CbmStsTrack &, Int_t usableHits)> TrackFilter_t
#define BMN_EVENT_BRANCH_NAME
#define BMN_BEAM_BRANCH_NAME
#define BMN_TRACKS_BRANCH_NAME
#define BMN_HITS_BRANCH_NAME
int i
Definition P4_F32vec4.h:22
bool Bool_t
int Int_t
constexpr Bool_t kFALSE
constexpr Bool_t kTRUE
BmnDataIterator(BmnSimpleProgressBar *pb=nullptr)
void SetTickProgress(Float_t progress)
Bool_t EndOfTracks() const noexcept
const Layer & Target() const
virtual Int_t TargetID() const
static constexpr Double_t Weight(Double_t error) noexcept
Short_t GetStation() const
Definition BmnHit.h:35
virtual void ResetAll() override
HitFilter_t fHitFilter
kTRUE keeps the track
const BmnDetectorModel * fpDetModel
Double_t fVertexX
per track of the event: kTRUE if it takes the vertex hit
TrackFilter_t fTrackFilter
Track_t * fpCurrentTrack
TTreeReaderValue< TClonesArray > * fpRootBeamHits
BmnRootIterator()=delete
BmnDataReader * fpData
kTRUE keeps the hit
TTreeReaderValue< DstEventHeader > * fpRootEventHeader
std::vector< Bool_t > fVertexTrack
virtual Int_t HitsInTrack() const override
TTreeReader * fpReader
virtual void ResetHits() override
CbmStsTrack Track_t
TTreeReaderValue< TClonesArray > * fpRootHits
virtual ~BmnRootIterator()
virtual void NextTrack() override
TTreeReaderValue< TClonesArray > * fpRootTracks
Double_t Var(Double_t z) const noexcept
Double_t At(Double_t z) const noexcept
void Add(Double_t z, Double_t v, Double_t w=1.0) noexcept
Int_t GetNStsHits() const
Accessors.
Definition CbmStsTrack.h:60
Int_t GetStsHitIndex(Int_t iHit) const
Definition CbmStsTrack.h:62
Int_t GetEntriesFast() const
TObject * At(Int_t idx) const override