Project
Loading...
Searching...
No Matches
testDCAFitterN.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#define BOOST_TEST_MODULE Test DCAFitterN class
13#define BOOST_TEST_MAIN
14#define BOOST_TEST_DYN_LINK
15#include <boost/test/unit_test.hpp>
16
19#include <TRandom.h>
20#include <TGenPhaseSpace.h>
21#include <TLorentzVector.h>
22#include <TStopwatch.h>
23#include <Math/SVector.h>
24#include <array>
25
26namespace o2
27{
28namespace vertexing
29{
30
32
33template <class FITTER>
34float checkResults(o2::utils::TreeStreamRedirector& outs, std::string& treeName, FITTER& fitter,
35 Vec3D& vgen, TLorentzVector& genPar, const std::vector<double>& dtMass)
36{
37 int nCand = fitter.getNCandidates();
38 std::array<float, 3> p;
39 float distMin = 1e9;
40 bool absDCA = fitter.getUseAbsDCA();
41 bool useWghDCA = fitter.getWeightedFinalPCA();
42 for (int ic = 0; ic < nCand; ic++) {
43 const auto& vtx = fitter.getPCACandidate(ic);
44 auto df = vgen;
45 df -= vtx;
46
47 TLorentzVector moth, prong;
48 for (int i = 0; i < fitter.getNProngs(); i++) {
49 const auto& trc = fitter.getTrack(i, ic);
50 trc.getPxPyPzGlo(p);
51 prong.SetVectM({p[0], p[1], p[2]}, dtMass[i]);
52 moth += prong;
53 }
54 auto nIter = fitter.getNIterations(ic);
55 auto chi2 = fitter.getChi2AtPCACandidate(ic);
56 double dst = TMath::Sqrt(df[0] * df[0] + df[1] * df[1] + df[2] * df[2]);
57 distMin = dst < distMin ? dst : distMin;
58 auto parentTrack = fitter.createParentTrackParCov(ic);
59 const std::array<float, 3> genPos{static_cast<float>(vgen[0]), static_cast<float>(vgen[1]), static_cast<float>(vgen[2])};
60 const std::array<float, 3> genMom{static_cast<float>(genPar.Px()), static_cast<float>(genPar.Py()), static_cast<float>(genPar.Pz())};
61 o2::track::TrackPar genParentTrack(genPos, genMom, parentTrack.getCharge(), false);
62 genParentTrack.rotateParam(parentTrack.getAlpha());
63 std::array<float, o2::track::kLabCovMatSize> parentCovGlo{};
64 const bool hasParentCovGlo = parentTrack.getCovXYZPxPyPzGlo(parentCovGlo);
65 const double pullX = hasParentCovGlo && parentCovGlo[0] > 0.f ? df[0] / TMath::Sqrt(parentCovGlo[0]) : 0.;
66 const double pullY = hasParentCovGlo && parentCovGlo[2] > 0.f ? df[1] / TMath::Sqrt(parentCovGlo[2]) : 0.;
67 const double pullZ = hasParentCovGlo && parentCovGlo[5] > 0.f ? df[2] / TMath::Sqrt(parentCovGlo[5]) : 0.;
68 outs << treeName.c_str() << "cand=" << ic << "ncand=" << nCand << "nIter=" << nIter << "chi2=" << chi2
69 << "genPart=" << genPar << "recPart=" << moth
70 << "genX=" << vgen[0] << "genY=" << vgen[1] << "genZ=" << vgen[2]
71 << "dx=" << df[0] << "dy=" << df[1] << "dz=" << df[2] << "dst=" << dst
72 << "pullX=" << pullX << "pullY=" << pullY << "pullZ=" << pullZ
73 << "genParentTrack=" << genParentTrack
74 << "useAbsDCA=" << absDCA << "useWghDCA=" << useWghDCA << "parent=" << parentTrack;
75 for (int i = 0; i < fitter.getNProngs(); i++) {
76 outs << treeName.c_str() << fmt::format("prong{}=", i).c_str() << fitter.getTrack(i, ic);
77 }
78 outs << treeName.c_str() << "\n";
79 }
80 return distMin;
81}
82
83TLorentzVector generate(Vec3D& vtx, std::vector<o2::track::TrackParCov>& vctr, float bz,
84 TGenPhaseSpace& genPHS, double parMass, const std::vector<double>& dtMass, std::vector<int> forceQ)
85{
86 const float errYZ = 1e-2, errSlp = 1e-3, errQPT = 2e-2;
87 std::array<float, 15> covm = {
88 errYZ * errYZ,
89 0., errYZ * errYZ,
90 0, 0., errSlp * errSlp,
91 0., 0., 0., errSlp * errSlp,
92 0., 0., 0., 0., errQPT * errQPT};
93 bool accept = true;
94 TLorentzVector parent, d0, d1, d2;
95 do {
96 accept = true;
97 double y = gRandom->Rndm() - 0.5;
98 double pt = 0.1 + gRandom->Rndm() * 3;
99 double mt = TMath::Sqrt(parMass * parMass + pt * pt);
100 double pz = mt * TMath::SinH(y);
101 double phi = gRandom->Rndm() * TMath::Pi() * 2;
102 double en = mt * TMath::CosH(y);
103 double rdec = 10.; // radius of the decay
104 vtx[0] = rdec * TMath::Cos(phi);
105 vtx[1] = rdec * TMath::Sin(phi);
106 vtx[2] = rdec * pz / pt;
107 parent.SetPxPyPzE(pt * TMath::Cos(phi), pt * TMath::Sin(phi), pz, en);
108 int nd = dtMass.size();
109 genPHS.SetDecay(parent, nd, dtMass.data());
110 genPHS.Generate();
111 vctr.clear();
112 float p[4];
113 for (int i = 0; i < nd; i++) {
114 auto* dt = genPHS.GetDecay(i);
115 if (dt->Pt() < 0.05) {
116 accept = false;
117 break;
118 }
119 dt->GetXYZT(p);
120 float s, c, x;
121 std::array<float, 5> params;
122 o2::math_utils::sincos(dt->Phi(), s, c);
123 o2::math_utils::rotateZInv(vtx[0], vtx[1], x, params[0], s, c);
124
125 params[1] = vtx[2];
126 params[2] = 0.; // since alpha = phi
127 params[3] = 1. / TMath::Tan(dt->Theta());
128 params[4] = (i % 2 ? -1. : 1.) / dt->Pt();
129 covm[14] = errQPT * errQPT * params[4] * params[4];
130 //
131 // randomize
132 float r1, r2;
133 gRandom->Rannor(r1, r2);
134 params[0] += r1 * errYZ;
135 params[1] += r2 * errYZ;
136 gRandom->Rannor(r1, r2);
137 params[2] += r1 * errSlp;
138 params[3] += r2 * errSlp;
139 params[4] *= gRandom->Gaus(1., errQPT);
140 if (forceQ[i] == 0) {
141 params[4] = 0.; // impose straight track
142 }
143 auto& trc = vctr.emplace_back(x, dt->Phi(), params, covm);
144 float rad = forceQ[i] == 0 ? 600. : TMath::Abs(1. / trc.getCurvature(bz));
145 if (!trc.propagateTo(trc.getX() + (gRandom->Rndm() - 0.5) * rad * 0.05, bz) ||
146 !trc.rotate(trc.getAlpha() + (gRandom->Rndm() - 0.5) * 0.2)) {
147 LOGP(error, "Failed to randomize ");
148 trc.print();
149 }
150 }
151 } while (!accept);
152
153 return parent;
154}
155
156static constexpr int NFitStatus{14};
157using FitStatusArray = std::array<std::array<int, 3>, NFitStatus>;
158static constexpr const char* FitStatusNames[NFitStatus] = {
159 "None", "Converged", "MaxIter", "NoCrossing", "RejRadius", "RejTrackX", "RejTrackRoughZ", "RejChi2Max",
160 "FailProp", "FailInvConv", "FailInvWeight", "FailInv2ndDeriv", "FailCorrTracks", "FailCloserAlt"};
161inline void printStat(const FitStatusArray& a)
162{
163 LOGP(info, "FitStatus summary : ....A / ..AWD / ...WD (A=abs.dist;AWD=abs.wghPCA.dist;WD=wgh.dist)");
164 for (int i{0}; i < NFitStatus; ++i) {
165 LOGP(info, "{:2d}={:20s}: {:5d} / {:5d} / {:5d}", i, FitStatusNames[i], a[i][0], a[i][1], a[i][2]);
166 }
167 BOOST_CHECK(a[0][0] == 0); // ensure coverage of all possible states
168 BOOST_CHECK(a[0][1] == 0);
169 BOOST_CHECK(a[0][2] == 0);
170}
171
172BOOST_AUTO_TEST_CASE(DCAFitterNProngs)
173{
174 constexpr bool oldMode = false; // if true, use the old mode of DCAFitterN, which is less correct but faster
175 constexpr int NTest = 10000;
176 o2::utils::TreeStreamRedirector outStream("dcafitterNTest.root");
177
178 TGenPhaseSpace genPHS;
179 constexpr double ele = 0.00051;
180 constexpr double gamma = 2 * ele + 1e-6;
181 constexpr double pion = 0.13957;
182 constexpr double k0 = 0.49761;
183 constexpr double kch = 0.49368;
184 constexpr double dch = 1.86965;
185 std::vector<double> gammadec = {ele, ele};
186 std::vector<double> k0dec = {pion, pion};
187 std::vector<double> dchdec = {pion, kch, pion};
188 std::vector<o2::track::TrackParCov> vctracks;
189 FitStatusArray fitstat;
190 Vec3D vtxGen;
191
192 double bz = 5.0;
193 // 2 prongs vertices
194 {
195 LOG(info) << "\n\nProcessing 2-prong Helix - Helix case";
196 std::vector<int> forceQ{1, 1};
197 std::memset(fitstat.data(), 0, sizeof(fitstat));
198
199 o2::vertexing::DCAFitterN<2> ft; // 2 prong fitter
200 ft.setOldMode(oldMode); // use the old mode of DCAFitterN
201 ft.setBz(bz);
202 ft.setPropagateToPCA(true); // After finding the vertex, propagate tracks to the DCA. This is default anyway
203 ft.setMaxR(200); // do not consider V0 seeds with 2D circles crossing above this R. This is default anyway
204 ft.setMaxDZIni(4); // do not consider V0 seeds with tracks Z-distance exceeding this. This is default anyway
205 ft.setMaxDXYIni(4); // do not consider V0 seeds with tracks XY-distance exceeding this. This is default anyway
206 ft.setMinParamChange(1e-3); // stop iterations if max correction is below this value. This is default anyway
207 ft.setMinRelChi2Change(0.9); // stop iterations if chi2 improves by less that this factor
208
209 std::string treeName2A = "pr2a", treeName2AW = "pr2aw", treeName2W = "pr2w";
210 TStopwatch swA, swAW, swW;
211 int nfoundA = 0, nfoundAW = 0, nfoundW = 0;
212 double meanDA = 0, meanDAW = 0, meanDW = 0;
213 swA.Stop();
214 swAW.Stop();
215 swW.Stop();
216 for (int iev = 0; iev < NTest; iev++) {
217 auto genParent = generate(vtxGen, vctracks, bz, genPHS, k0, k0dec, forceQ);
218
219 ft.setUseAbsDCA(true);
220 swA.Start(false);
221 int ncA = ft.process(vctracks[0], vctracks[1]); // HERE WE FIT THE VERTICES
222 swA.Stop();
223 LOG(debug) << "fit abs.dist " << iev << " NC: " << ncA << " Chi2: " << (ncA ? ft.getChi2AtPCACandidate(0) : -1);
224 if (ncA) {
225 auto minD = checkResults(outStream, treeName2A, ft, vtxGen, genParent, k0dec);
226 meanDA += minD;
227 nfoundA++;
228 }
229 ++fitstat[ft.getFitStatus()][0];
230
231 ft.setUseAbsDCA(true);
232 ft.setWeightedFinalPCA(true);
233 swAW.Start(false);
234 int ncAW = ft.process(vctracks[0], vctracks[1]); // HERE WE FIT THE VERTICES
235 swAW.Stop();
236 LOG(debug) << "fit abs.dist with final weighted DCA " << iev << " NC: " << ncAW << " Chi2: " << (ncAW ? ft.getChi2AtPCACandidate(0) : -1);
237 if (ncAW) {
238 auto minD = checkResults(outStream, treeName2AW, ft, vtxGen, genParent, k0dec);
239 meanDAW += minD;
240 nfoundAW++;
241 }
242 ++fitstat[ft.getFitStatus()][1];
243
244 ft.setUseAbsDCA(false);
245 ft.setWeightedFinalPCA(false);
246 swW.Start(false);
247 int ncW = ft.process(vctracks[0], vctracks[1]); // HERE WE FIT THE VERTICES
248 swW.Stop();
249 LOG(debug) << "fit wgh.dist " << iev << " NC: " << ncW << " Chi2: " << (ncW ? ft.getChi2AtPCACandidate(0) : -1);
250 if (ncW) {
251 auto minD = checkResults(outStream, treeName2W, ft, vtxGen, genParent, k0dec);
252 meanDW += minD;
253 nfoundW++;
254 }
255 ++fitstat[ft.getFitStatus()][2];
256 }
257 // ft.print();
258 meanDA /= nfoundA ? nfoundA : 1;
259 meanDAW /= nfoundAW ? nfoundAW : 1;
260 meanDW /= nfoundW ? nfoundW : 1;
261 LOG(info) << "Processed " << NTest << " 2-prong vertices Helix : Helix";
262 LOG(info) << "2-prongs with abs.dist minization: eff= " << float(nfoundA) / NTest
263 << " mean.dist to truth: " << meanDA << " CPU time: " << swA.CpuTime() * 1000 << " ms";
264 LOG(info) << "2-prongs with abs.dist but wghPCA: eff= " << float(nfoundAW) / NTest
265 << " mean.dist to truth: " << meanDAW << " CPU time: " << swAW.CpuTime() * 1000 << " ms";
266 LOG(info) << "2-prongs with wgh.dist minization: eff= " << float(nfoundW) / NTest
267 << " mean.dist to truth: " << meanDW << " CPU time: " << swW.CpuTime() * 1000 << " ms";
268 printStat(fitstat);
269 BOOST_CHECK(nfoundA > 0.99 * NTest);
270 BOOST_CHECK(nfoundAW > 0.99 * NTest);
271 BOOST_CHECK(nfoundW > 0.99 * NTest);
272 BOOST_CHECK(meanDA < 0.1);
273 BOOST_CHECK(meanDAW < 0.1);
274 BOOST_CHECK(meanDW < 0.1);
275 ft.print();
276 }
277
278 // 2 prongs vertices with collinear tracks (gamma conversion)
279 {
280 LOG(info) << "\n\nProcessing 2-prong Helix - Helix case gamma conversion";
281 std::vector<int> forceQ{1, 1};
282 std::memset(fitstat.data(), 0, sizeof(fitstat));
283
284 o2::vertexing::DCAFitterN<2> ft; // 2 prong fitter
285 ft.setOldMode(oldMode); // use the old mode of DCAFitterN
286 ft.setBz(bz);
287 ft.setPropagateToPCA(true); // After finding the vertex, propagate tracks to the DCA. This is default anyway
288 ft.setMaxR(200); // do not consider V0 seeds with 2D circles crossing above this R. This is default anyway
289 ft.setMaxDZIni(4); // do not consider V0 seeds with tracks Z-distance exceeding this. This is default anyway
290 ft.setMaxDXYIni(4); // do not consider V0 seeds with tracks XY-distance exceeding this. This is default anyway
291 ft.setMinParamChange(1e-3); // stop iterations if max correction is below this value. This is default anyway
292 ft.setMinRelChi2Change(0.9); // stop iterations if chi2 improves by less that this factor
293 ft.setMaxChi2();
294 ft.setCollinear(true);
295
296 std::string treeName2A = "gpr2a", treeName2AW = "gpr2aw", treeName2W = "gpr2w";
297 TStopwatch swA, swAW, swW;
298 int nfoundA = 0, nfoundAW = 0, nfoundW = 0;
299 double meanDA = 0, meanDAW = 0, meanDW = 0;
300 swA.Stop();
301 swAW.Stop();
302 swW.Stop();
303 for (int iev = 0; iev < NTest; iev++) {
304 auto genParent = generate(vtxGen, vctracks, bz, genPHS, gamma, gammadec, forceQ);
305
306 ft.setUseAbsDCA(true);
307 swA.Start(false);
308 int ncA = ft.process(vctracks[0], vctracks[1]); // HERE WE FIT THE VERTICES
309 swA.Stop();
310 LOG(debug) << "fit abs.dist " << iev << " NC: " << ncA << " Chi2: " << (ncA ? ft.getChi2AtPCACandidate(0) : -1);
311 if (ncA) {
312 auto minD = checkResults(outStream, treeName2A, ft, vtxGen, genParent, gammadec);
313 meanDA += minD;
314 nfoundA++;
315 }
316 ++fitstat[ft.getFitStatus()][0];
317
318 ft.setUseAbsDCA(true);
319 ft.setWeightedFinalPCA(true);
320 swAW.Start(false);
321 int ncAW = ft.process(vctracks[0], vctracks[1]); // HERE WE FIT THE VERTICES
322 swAW.Stop();
323 LOG(debug) << "fit abs.dist with final weighted DCA " << iev << " NC: " << ncAW << " Chi2: " << (ncAW ? ft.getChi2AtPCACandidate(0) : -1);
324 if (ncAW) {
325 auto minD = checkResults(outStream, treeName2AW, ft, vtxGen, genParent, gammadec);
326 meanDAW += minD;
327 nfoundAW++;
328 }
329 ++fitstat[ft.getFitStatus()][1];
330
331 ft.setUseAbsDCA(false);
332 ft.setWeightedFinalPCA(false);
333 swW.Start(false);
334 int ncW = ft.process(vctracks[0], vctracks[1]); // HERE WE FIT THE VERTICES
335 swW.Stop();
336 LOG(debug) << "fit wgh.dist " << iev << " NC: " << ncW << " Chi2: " << (ncW ? ft.getChi2AtPCACandidate(0) : -1);
337 if (ncW) {
338 auto minD = checkResults(outStream, treeName2W, ft, vtxGen, genParent, gammadec);
339 meanDW += minD;
340 nfoundW++;
341 }
342 ++fitstat[ft.getFitStatus()][2];
343 }
344 // ft.print();
345 meanDA /= nfoundA ? nfoundA : 1;
346 meanDAW /= nfoundAW ? nfoundAW : 1;
347 meanDW /= nfoundW ? nfoundW : 1;
348 LOG(info) << "Processed " << NTest << " 2-prong vertices Helix : Helix from gamma conversion";
349 LOG(info) << "2-prongs with abs.dist minization: eff= " << float(nfoundA) / NTest
350 << " mean.dist to truth: " << meanDA << " CPU time: " << swA.CpuTime() * 1000 << " ms";
351 LOG(info) << "2-prongs with abs.dist but wghPCA: eff= " << float(nfoundAW) / NTest
352 << " mean.dist to truth: " << meanDAW << " CPU time: " << swAW.CpuTime() * 1000 << " ms";
353 LOG(info) << "2-prongs with wgh.dist minization: eff= " << float(nfoundW) / NTest
354 << " mean.dist to truth: " << meanDW << " CPU time: " << swW.CpuTime() * 1000 << " ms";
355 printStat(fitstat);
356 BOOST_CHECK(nfoundA > 0.99 * NTest);
357 BOOST_CHECK(nfoundAW > 0.99 * NTest);
358 BOOST_CHECK(nfoundW > 0.99 * NTest);
359 BOOST_CHECK(meanDA < 2.1);
360 BOOST_CHECK(meanDAW < 2.1);
361 BOOST_CHECK(meanDW < 2.1);
362 ft.print();
363 }
364
365 // 2 prongs vertices with one of charges set to 0: Helix : Line
366 {
367 std::vector<int> forceQ{1, 1};
368 LOG(info) << "\n\nProcessing 2-prong Helix - Line case";
369 std::memset(fitstat.data(), 0, sizeof(fitstat));
370
371 o2::vertexing::DCAFitterN<2> ft; // 2 prong fitter
372 ft.setOldMode(oldMode); // use the old mode of DCAFitterN
373 ft.setBz(bz);
374 ft.setPropagateToPCA(true); // After finding the vertex, propagate tracks to the DCA. This is default anyway
375 ft.setMaxR(200); // do not consider V0 seeds with 2D circles crossing above this R. This is default anyway
376 ft.setMaxDZIni(4); // do not consider V0 seeds with tracks Z-distance exceeding this. This is default anyway
377 ft.setMinParamChange(1e-3); // stop iterations if max correction is below this value. This is default anyway
378 ft.setMinRelChi2Change(0.9); // stop iterations if chi2 improves by less that this factor
379
380 std::string treeName2A = "pr2aHL", treeName2AW = "pr2awHL", treeName2W = "pr2wHL";
381 TStopwatch swA, swAW, swW;
382 int nfoundA = 0, nfoundAW = 0, nfoundW = 0;
383 double meanDA = 0, meanDAW = 0, meanDW = 0;
384 swA.Stop();
385 swAW.Stop();
386 swW.Stop();
387 for (int iev = 0; iev < NTest; iev++) {
388 forceQ[iev % 2] = 1;
389 forceQ[1 - iev % 2] = 0;
390 auto genParent = generate(vtxGen, vctracks, bz, genPHS, k0, k0dec, forceQ);
391
392 ft.setUseAbsDCA(true);
393 swA.Start(false);
394 int ncA = ft.process(vctracks[0], vctracks[1]); // HERE WE FIT THE VERTICES
395 swA.Stop();
396 LOG(debug) << "fit abs.dist with final weighted DCA " << iev << " NC: " << ncA << " Chi2: " << (ncA ? ft.getChi2AtPCACandidate(0) : -1);
397 if (ncA) {
398 auto minD = checkResults(outStream, treeName2A, ft, vtxGen, genParent, k0dec);
399 meanDA += minD;
400 nfoundA++;
401 }
402 ++fitstat[ft.getFitStatus()][0];
403
404 ft.setUseAbsDCA(true);
405 ft.setWeightedFinalPCA(true);
406 swAW.Start(false);
407 int ncAW = ft.process(vctracks[0], vctracks[1]); // HERE WE FIT THE VERTICES
408 swAW.Stop();
409 LOG(debug) << "fit abs.dist " << iev << " NC: " << ncAW << " Chi2: " << (ncAW ? ft.getChi2AtPCACandidate(0) : -1);
410 if (ncAW) {
411 auto minD = checkResults(outStream, treeName2AW, ft, vtxGen, genParent, k0dec);
412 meanDAW += minD;
413 nfoundAW++;
414 }
415 ++fitstat[ft.getFitStatus()][1];
416
417 ft.setUseAbsDCA(false);
418 ft.setWeightedFinalPCA(false);
419 swW.Start(false);
420 int ncW = ft.process(vctracks[0], vctracks[1]); // HERE WE FIT THE VERTICES
421 swW.Stop();
422 LOG(debug) << "fit wgh.dist " << iev << " NC: " << ncW << " Chi2: " << (ncW ? ft.getChi2AtPCACandidate(0) : -1);
423 if (ncW) {
424 auto minD = checkResults(outStream, treeName2W, ft, vtxGen, genParent, k0dec);
425 meanDW += minD;
426 nfoundW++;
427 }
428 ++fitstat[ft.getFitStatus()][2];
429 }
430 // ft.print();
431 meanDA /= nfoundA ? nfoundA : 1;
432 meanDAW /= nfoundAW ? nfoundAW : 1;
433 meanDW /= nfoundW ? nfoundW : 1;
434 LOG(info) << "Processed " << NTest << " 2-prong vertices: Helix : Line";
435 LOG(info) << "2-prongs with abs.dist minization: eff= " << float(nfoundA) / NTest
436 << " mean.dist to truth: " << meanDA << " CPU time: " << swA.CpuTime() * 1000 << " ms";
437 LOG(info) << "2-prongs with abs.dist but wghPCA: eff= " << float(nfoundAW) / NTest
438 << " mean.dist to truth: " << meanDAW << " CPU time: " << swAW.CpuTime() * 1000 << " ms";
439 LOG(info) << "2-prongs with wgh.dist minization: eff= " << float(nfoundW) / NTest
440 << " mean.dist to truth: " << meanDW << " CPU time: " << swW.CpuTime() * 1000 << " ms";
441 printStat(fitstat);
442 BOOST_CHECK(nfoundA > 0.99 * NTest);
443 BOOST_CHECK(nfoundAW > 0.99 * NTest);
444 BOOST_CHECK(nfoundW > 0.99 * NTest);
445 BOOST_CHECK(meanDA < 0.1);
446 BOOST_CHECK(meanDAW < 0.1);
447 BOOST_CHECK(meanDW < 0.1);
448 ft.print();
449 }
450
451 // 2 prongs vertices with both of charges set to 0: Line : Line
452 {
453 std::vector<int> forceQ{0, 0};
454 LOG(info) << "\n\nProcessing 2-prong Line - Line case";
455 std::memset(fitstat.data(), 0, sizeof(fitstat));
456
457 o2::vertexing::DCAFitterN<2> ft; // 2 prong fitter
458 ft.setOldMode(oldMode); // use the old mode of DCAFitterN
459 ft.setBz(bz);
460 ft.setPropagateToPCA(true); // After finding the vertex, propagate tracks to the DCA. This is default anyway
461 ft.setMaxR(200); // do not consider V0 seeds with 2D circles crossing above this R. This is default anyway
462 ft.setMaxDZIni(4); // do not consider V0 seeds with tracks Z-distance exceeding this. This is default anyway
463 ft.setMinParamChange(1e-3); // stop iterations if max correction is below this value. This is default anyway
464 ft.setMinRelChi2Change(0.9); // stop iterations if chi2 improves by less that this factor
465
466 std::string treeName2A = "pr2aLL", treeName2AW = "pr2awLL", treeName2W = "pr2wLL";
467 TStopwatch swA, swAW, swW;
468 int nfoundA = 0, nfoundAW = 0, nfoundW = 0;
469 double meanDA = 0, meanDAW = 0, meanDW = 0;
470 swA.Stop();
471 swAW.Stop();
472 swW.Stop();
473 for (int iev = 0; iev < NTest; iev++) {
474 forceQ[0] = forceQ[1] = 0;
475 auto genParent = generate(vtxGen, vctracks, bz, genPHS, k0, k0dec, forceQ);
476
477 ft.setUseAbsDCA(true);
478 swA.Start(false);
479 int ncA = ft.process(vctracks[0], vctracks[1]); // HERE WE FIT THE VERTICES
480 swA.Stop();
481 LOG(debug) << "fit abs.dist " << iev << " NC: " << ncA << " Chi2: " << (ncA ? ft.getChi2AtPCACandidate(0) : -1);
482 if (ncA) {
483 auto minD = checkResults(outStream, treeName2A, ft, vtxGen, genParent, k0dec);
484 meanDA += minD;
485 nfoundA++;
486 }
487 ++fitstat[ft.getFitStatus()][0];
488
489 ft.setUseAbsDCA(true);
490 ft.setWeightedFinalPCA(true);
491 swAW.Start(false);
492 int ncAW = ft.process(vctracks[0], vctracks[1]); // HERE WE FIT THE VERTICES
493 swAW.Stop();
494 LOG(debug) << "fit abs.dist " << iev << " NC: " << ncAW << " Chi2: " << (ncAW ? ft.getChi2AtPCACandidate(0) : -1);
495 if (ncAW) {
496 auto minD = checkResults(outStream, treeName2AW, ft, vtxGen, genParent, k0dec);
497 meanDAW += minD;
498 nfoundAW++;
499 }
500 ++fitstat[ft.getFitStatus()][1];
501
502 ft.setUseAbsDCA(false);
503 ft.setWeightedFinalPCA(false);
504 swW.Start(false);
505 int ncW = ft.process(vctracks[0], vctracks[1]); // HERE WE FIT THE VERTICES
506 swW.Stop();
507 LOG(debug) << "fit wgh.dist " << iev << " NC: " << ncW << " Chi2: " << (ncW ? ft.getChi2AtPCACandidate(0) : -1);
508 if (ncW) {
509 auto minD = checkResults(outStream, treeName2W, ft, vtxGen, genParent, k0dec);
510 meanDW += minD;
511 nfoundW++;
512 }
513 ++fitstat[ft.getFitStatus()][2];
514 }
515 // ft.print();
516 meanDA /= nfoundA ? nfoundA : 1;
517 meanDAW /= nfoundAW ? nfoundAW : 1;
518 meanDW /= nfoundW ? nfoundW : 1;
519 LOG(info) << "Processed " << NTest << " 2-prong vertices: Line : Line";
520 LOG(info) << "2-prongs with abs.dist minization: eff= " << float(nfoundA) / NTest
521 << " mean.dist to truth: " << meanDA << " CPU time: " << swA.CpuTime() * 1000 << " ms";
522 LOG(info) << "2-prongs with abs.dist but wghPCA: eff= " << float(nfoundAW) / NTest
523 << " mean.dist to truth: " << meanDAW << " CPU time: " << swAW.CpuTime() * 1000 << " ms";
524 LOG(info) << "2-prongs with wgh.dist minization: eff= " << float(nfoundW) / NTest
525 << " mean.dist to truth: " << meanDW << " CPU time: " << swW.CpuTime() * 1000 << " ms";
526 printStat(fitstat);
527 BOOST_CHECK(nfoundA > 0.99 * NTest);
528 BOOST_CHECK(nfoundAW > 0.99 * NTest);
529 BOOST_CHECK(nfoundW > 0.99 * NTest);
530 BOOST_CHECK(meanDA < 0.1);
531 BOOST_CHECK(meanDAW < 0.1);
532 BOOST_CHECK(meanDW < 0.1);
533 ft.print();
534 }
535
536 // 3 prongs vertices
537 {
538 LOG(info) << "\n\nProcessing 3-prong vertices";
539 std::vector<int> forceQ{1, 1, 1};
540 std::memset(fitstat.data(), 0, sizeof(fitstat));
541
542 o2::vertexing::DCAFitterN<3> ft; // 3 prong fitter
543 ft.setOldMode(oldMode); // use the old mode of DCAFitterN
544 ft.setBz(bz);
545 ft.setPropagateToPCA(true); // After finding the vertex, propagate tracks to the DCA. This is default anyway
546 ft.setMaxR(200); // do not consider V0 seeds with 2D circles crossing above this R. This is default anyway
547 ft.setMaxDZIni(4); // do not consider V0 seeds with tracks Z-distance exceeding this. This is default anyway
548 ft.setMinParamChange(1e-3); // stop iterations if max correction is below this value. This is default anyway
549 ft.setMinRelChi2Change(0.9); // stop iterations if chi2 improves by less that this factor
550
551 std::string treeName3A = "pr3a", treeName3AW = "pr3aw", treeName3W = "pr3w";
552 TStopwatch swA, swAW, swW;
553 int nfoundA = 0, nfoundAW = 0, nfoundW = 0;
554 double meanDA = 0, meanDAW = 0, meanDW = 0;
555 swA.Stop();
556 swAW.Stop();
557 swW.Stop();
558 for (int iev = 0; iev < NTest; iev++) {
559 auto genParent = generate(vtxGen, vctracks, bz, genPHS, dch, dchdec, forceQ);
560
561 ft.setUseAbsDCA(true);
562 swA.Start(false);
563 int ncA = ft.process(vctracks[0], vctracks[1], vctracks[2]); // HERE WE FIT THE VERTICES
564 swA.Stop();
565 LOG(debug) << "fit abs.dist " << iev << " NC: " << ncA << " Chi2: " << (ncA ? ft.getChi2AtPCACandidate(0) : -1);
566 if (ncA) {
567 auto minD = checkResults(outStream, treeName3A, ft, vtxGen, genParent, dchdec);
568 meanDA += minD;
569 nfoundA++;
570 }
571 ++fitstat[ft.getFitStatus()][0];
572
573 ft.setUseAbsDCA(true);
574 ft.setWeightedFinalPCA(true);
575 swAW.Start(false);
576 int ncAW = ft.process(vctracks[0], vctracks[1], vctracks[2]); // HERE WE FIT THE VERTICES
577 swAW.Stop();
578 LOG(debug) << "fit abs.dist " << iev << " NC: " << ncAW << " Chi2: " << (ncAW ? ft.getChi2AtPCACandidate(0) : -1);
579 if (ncAW) {
580 auto minD = checkResults(outStream, treeName3AW, ft, vtxGen, genParent, dchdec);
581 meanDAW += minD;
582 nfoundAW++;
583 }
584 ++fitstat[ft.getFitStatus()][1];
585
586 ft.setUseAbsDCA(false);
587 ft.setWeightedFinalPCA(false);
588 swW.Start(false);
589 int ncW = ft.process(vctracks[0], vctracks[1], vctracks[2]); // HERE WE FIT THE VERTICES
590 swW.Stop();
591 LOG(debug) << "fit wgh.dist " << iev << " NC: " << ncW << " Chi2: " << (ncW ? ft.getChi2AtPCACandidate(0) : -1);
592 if (ncW) {
593 auto minD = checkResults(outStream, treeName3W, ft, vtxGen, genParent, dchdec);
594 meanDW += minD;
595 nfoundW++;
596 }
597 ++fitstat[ft.getFitStatus()][2];
598 }
599 // ft.print();
600 meanDA /= nfoundA ? nfoundA : 1;
601 meanDAW /= nfoundAW ? nfoundAW : 1;
602 meanDW /= nfoundW ? nfoundW : 1;
603 LOG(info) << "Processed " << NTest << " 3-prong vertices";
604 LOG(info) << "3-prongs with abs.dist minization: eff= " << float(nfoundA) / NTest
605 << " mean.dist to truth: " << meanDA << " CPU time: " << swA.CpuTime() * 1000 << " ms";
606 LOG(info) << "3-prongs with abs.dist but wghPCA: eff= " << float(nfoundAW) / NTest
607 << " mean.dist to truth: " << meanDAW << " CPU time: " << swAW.CpuTime() * 1000 << " ms";
608 LOG(info) << "3-prongs with wgh.dist minization: eff= " << float(nfoundW) / NTest
609 << " mean.dist to truth: " << meanDW << " CPU time: " << swW.CpuTime() * 1000 << " ms";
610 printStat(fitstat);
611 BOOST_CHECK(nfoundA > 0.99 * NTest);
612 BOOST_CHECK(nfoundAW > 0.99 * NTest);
613 BOOST_CHECK(nfoundW > 0.99 * NTest);
614 BOOST_CHECK(meanDA < 0.1);
615 BOOST_CHECK(meanDAW < 0.1);
616 BOOST_CHECK(meanDW < 0.1);
617 ft.print();
618 }
619 outStream.Close();
620}
621
622} // namespace vertexing
623} // namespace o2
Defintions for N-prongs secondary vertex fit.
std::ostringstream debug
int32_t i
float chi2
uint32_t c
Definition RawData.h:2
float getChi2AtPCACandidate(int cand=0) const
Definition DCAFitterN.h:207
GLint GLenum GLint x
Definition glcorearb.h:403
GLint y
Definition glcorearb.h:270
GLenum const GLfloat * params
Definition glcorearb.h:272
GLenum GLenum dst
Definition glcorearb.h:1767
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
std::tuple< float, float > rotateZInv(float xG, float yG, float snAlp, float csAlp)
Definition Utils.h:142
BOOST_AUTO_TEST_CASE(DCAFitterNProngsBulk)
std::array< std::array< int, 3 >, NFitStatus > FitStatusArray
TLorentzVector generate(Vec3D &vtx, std::vector< o2::track::TrackParCov > &vctr, float bz, TGenPhaseSpace &genPHS, double parMass, const std::vector< double > &dtMass, std::vector< int > forceQ)
ROOT::Math::SVector< double, 3 > Vec3D
float checkResults(o2::utils::TreeStreamRedirector &outs, std::string &treeName, FITTER &fitter, Vec3D &vgen, TLorentzVector &genPar, const std::vector< double > &dtMass)
void printStat(const FitStatusArray &a)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
BOOST_CHECK(tree)