Class Reference for E1039 Core & Analysis Software
SQVertexing_v2.cc
Go to the documentation of this file.
1 #include "SQVertexing_v2.h"
2 
3 #include <phfield/PHFieldConfig_v3.h>
4 #include <phfield/PHFieldUtility.h>
5 #include <phgeom/PHGeomUtility.h>
6 
8 #include <phool/PHNodeIterator.h>
9 #include <phool/PHIODataNode.h>
10 #include <phool/PHRandomSeed.h>
11 #include <phool/getClass.h>
12 #include <phool/recoConsts.h>
17 #include <GenFit/FieldManager.h>
18 #include <GenFit/MaterialEffects.h>
19 #include <GenFit/TGeoMaterialInterface.h>
20 #include <ktracker/SRecEvent.h>
21 #include <ktracker/GFTrack.h>
22 #include <TGeoManager.h>
23 #include <iostream>
24 #include <vector>
25 
26 namespace
27 {
28  //static flag to indicate the initialized has been done
29  static bool inited = false;
30 
31  static double Z_TARGET;
32  static double Z_DUMP;
33  static double Z_UPSTREAM;
34 
35  static double X_BEAM;
36  static double Y_BEAM;
37  static double SIGX_BEAM;
38  static double SIGY_BEAM;
39 
40  //initialize global variables
41  void initGlobalVariables()
42  {
43  if(!inited)
44  {
45  inited = true;
46 
48  Z_TARGET = rc->get_DoubleFlag("Z_TARGET");
49  Z_DUMP = rc->get_DoubleFlag("Z_DUMP");
50  Z_UPSTREAM = rc->get_DoubleFlag("Z_UPSTREAM");
51  std::cout<<"Z_UPSTREAM :" <<Z_UPSTREAM<<std::endl;
52  std::cout<<"Z_DUMP :" <<Z_DUMP<<std::endl;
53  std::cout<<"Z_TARGET :" <<Z_TARGET<<std::endl;
54 
55  X_BEAM = rc->get_DoubleFlag("X_BEAM");
56  Y_BEAM = rc->get_DoubleFlag("Y_BEAM");
57  SIGX_BEAM = rc->get_DoubleFlag("SIGX_BEAM");
58  SIGY_BEAM = rc->get_DoubleFlag("SIGY_BEAM");
59  }
60  }
61 };
62 
63 SQVertexing_v2::SQVertexing_v2(const std::string& name, int sign1, int sign2):
64  SubsysReco(name),
65  legacyContainer_in(false),
66  legacyContainer_out(false),
67  enableSingleRetracking(false),
68  charge1(sign1),
69  charge2(sign2),
70  geom_file_name(""),
71  gfield(nullptr),
72  recEvent(nullptr),
73  recTrackVec(nullptr),
74  recDimuonVec(nullptr)
75 {}
76 
78 {}
79 
81  initGlobalVariables();
82  std::cout<<"global variables set"<<std::endl;
83 }
84 
86 {
87  initGlobalVariables();
89 }
90 
92 {
93  int ret = GetNodes(topNode);
94  if(ret != Fun4AllReturnCodes::EVENT_OK) return ret;
95 
96  ret = MakeNodes(topNode);
97  if(ret != Fun4AllReturnCodes::EVENT_OK) return ret;
98 
99  ret = InitField(topNode);
100  if(ret != Fun4AllReturnCodes::EVENT_OK) return ret;
101 
102  ret = InitGeom(topNode);
103  if(ret != Fun4AllReturnCodes::EVENT_OK) return ret;
104 
106 }
107 
109 {
111 
112  std::vector<int> trackIDs1;
113  std::vector<int> trackIDs2;
114  int nTracks = legacyContainer_in ? recEvent->getNTracks() : recTrackVec->size();
115  if(Verbosity() > 10) std::cout << "SQVertexing_v2::process_event(): nTracks = " << nTracks << std::endl;
116  for(int i = 0; i < nTracks; ++i)
117  {
118  SRecTrack* recTrack = legacyContainer_in ? &(recEvent->getTrack(i)) : dynamic_cast<SRecTrack*>(recTrackVec->at(i));
119  if(!recTrack->isKalmanFitted()) continue;
120 
121  processOneMuon(recTrack);
122 
123  if(recTrack->getCharge() == charge1) trackIDs1.push_back(i);
124  if(recTrack->getCharge() == charge2) trackIDs2.push_back(i);
125  }
126  if(trackIDs1.empty() || trackIDs2.empty()) return Fun4AllReturnCodes::EVENT_OK;
127  if(Verbosity() > 10) std::cout << " N of trackIDs1 & trackIDs1 = " << trackIDs1.size() << " & " << trackIDs2.size() << std::endl;
128 
129  for(std::size_t i = 0; i < trackIDs1.size(); ++i)
130  {
131  for(std::size_t j = charge1 == charge2 ? i+1 : 0; j < trackIDs2.size(); ++j)
132  {
133  //A protection, probably not really needed
134  if(trackIDs1[i] == trackIDs2[j]) continue;
135 
136  SRecTrack* recTrack1 = legacyContainer_in ? &(recEvent->getTrack(trackIDs1[i])) : dynamic_cast<SRecTrack*>(recTrackVec->at(trackIDs1[i]));
137  SRecTrack* recTrack2 = legacyContainer_in ? &(recEvent->getTrack(trackIDs2[j])) : dynamic_cast<SRecTrack*>(recTrackVec->at(trackIDs2[j]));
138 
139  SRecDimuon recDimuon;
140  if(processOneDimuon(recTrack1, recTrack2, recDimuon))
141  {
142  //recDimuon.set_rec_dimuon_id(legacyContainer ? recEvent->getNDimuons() : recDimuonVec->size());
143  recDimuon.set_track_id_pos(trackIDs1[i]);
144  recDimuon.set_track_id_neg(trackIDs2[j]);
145 
147  recEvent->insertDimuon(recDimuon);
148  else
149  recDimuonVec->push_back(&recDimuon);
150  }
151  }
152  }
153 
155 }
156 
158 {
160 }
161 
163 {
165  {
166  recEvent = findNode::getClass<SRecEvent>(topNode, "SRecEvent");
167  if(!recEvent)
168  {
169  std::cerr << Name() << ": failed finding SRecEvent node, abort." << std::endl;
171  }
172  }
173  else
174  {
175  recTrackVec = findNode::getClass<SQTrackVector>(topNode, "SQRecTrackVector");
176  if(!recTrackVec)
177  {
178  std::cerr << Name() << ": failed finding SQRecTrackVector node, abort." << std::endl;
180  }
181  }
182 
184 }
185 
187 {
189  {
190  PHNodeIterator iter(topNode);
191  PHCompositeNode* dstNode = static_cast<PHCompositeNode*>(iter.findFirst("PHCompositeNode", "DST"));
192  if(!dstNode)
193  {
194  std::cerr << Name() << ": cannot locate DST node, abort." << std::endl;
196  }
197 
199  TString dimuonVecName = TString::Format("SQRecDimuonVector_%s%s", (charge1 == 1 ? "P" : "M"), (charge2 == 1 ? "P" : "M"));
200  dstNode->addNode(new PHIODataNode<PHObject>(recDimuonVec, dimuonVecName.Data(), "PHObject"));
201  }
203 }
204 
205 double SQVertexing_v2::swimTrackToVertex(SQGenFit::GFTrack& track, double z, TVector3* pos, TVector3* mom)
206 {
207  double chi2 = track.swimToVertex(z, pos, mom);
208  return chi2;
209 }
210 
211 double SQVertexing_v2::refitTrkToVtx(SQGenFit::GFTrack& track, double z, TVector3* pos, TVector3* mom)
212 {
213  if(Verbosity() > 20) std::cout << "SQVertexing_v2::refitTrkToVtx(): z = " << z << ", pos = (" << pos->X() << ", " << pos->Y() << ", " << pos->Z() << "), mom = (" << mom->X() << ", " << mom->Y() << ", " << mom->Z() << ")" << std::endl;
214  gfield->setOffset(0.);
215 
216  double z_offset_prev = 1.E9;
217  double z_offset_curr = 0.;
218  double chi2 = 0.;
219  const int n_iter_max = 100;
220  int n_iter = 0;
221  while(fabs(z_offset_curr - z_offset_prev) > 0.1)
222  {
223  chi2 = swimTrackToVertex(track, z, pos, mom);
224 
225  //update scatter plane location
226  z_offset_prev = z_offset_curr;
227  z_offset_curr = calcZsclp(mom->Mag());
228 
229  gfield->setOffset(-z_offset_curr);
230  if(Verbosity() > 20) std::cout << " i_iter = " << n_iter << ": p = " << mom->Mag() << ", dz = " << z_offset_curr << " - " << z_offset_prev << " = " << z_offset_curr - z_offset_prev << std::endl;
231  if (++n_iter == n_iter_max) {
232  std::cout << "!WARNING! SQVertexing_v2::refitTrkToVtx(): Give up the iteration." << std::endl;
233  break;
234  }
235  }
236  if(Verbosity() > 10) std::cout << " n_iter = " << n_iter << std::endl;
237 
238  //re-adjust FMag bend plane here
239  gfield->setOffset(0.);
240 
241  return chi2;
242 }
243 
244 double SQVertexing_v2::refitTrkToVtx(SRecTrack* track, double z, TVector3* pos, TVector3* mom)
245 {
246  SQGenFit::GFTrack gtrk(*track);
247  return refitTrkToVtx(gtrk, z, pos, mom);
248 }
249 
251 {
252  if(p < 5.) p = 5.;
253  else if(p > 120.) p = 120.;
254 
255  return 301.84 - 1.27137*p + 0.0218294*p*p - 0.000170711*p*p*p + 4.94683e-07*p*p*p*p - 271.;
256 }
257 
259 {
260  SQGenFit::GFTrack gtrk(*track);
261 
262  //Swim to various places and save info
263  track->swimToVertex(nullptr, nullptr, false);
264 
265  //Hypothesis test should be implemented here
266  //test Z_UPSTREAM
267  track->setChisqUpstream(swimTrackToVertex(gtrk, Z_UPSTREAM));
268 
269  //test Z_TARGET
271  track->setChisqTarget(refitTrkToVtx(gtrk, Z_TARGET));
272  else
273  track->setChisqTarget(swimTrackToVertex(gtrk, Z_TARGET));
274  // if(track->getChisqTarget() > 0.)
275  // {
276  // track->setTargetPos(pos);
277  // track->setTargetMom(mom);
278  // }
279 
280  //test Z_DUMP
281  track->setChisqDump(swimTrackToVertex(gtrk, Z_DUMP));
282  // if(track->getChisqDump() > 0.)
283  // {
284  // track->setDumpPos(pos);
285  // track->setDumpMom(mom);
286  // }
287 
288  //test Z_VERTEX
289  TVector3 pos, mom;
291  track->setChisqVertex(refitTrkToVtx(gtrk, track->getVertexPos().Z(), &pos, &mom));
292  else
293  track->setChisqVertex(swimTrackToVertex(gtrk, track->getVertexPos().Z(), &pos, &mom));
294  track->setVertexFast(mom, pos);
295 
296  return true;
297 }
298 
300 {
301  if(Verbosity() > 10) std::cout << " SQVertexing_v2::processOneDimuon(): " << std::endl;
302 
303  //Pre-calculated variables
304  dimuon.proj_target_pos = track1->getTargetPos();
305  dimuon.proj_dump_pos = track1->getDumpPos();
306  dimuon.proj_target_neg = track2->getTargetPos();
307  dimuon.proj_dump_neg = track2->getDumpPos();
308  dimuon.chisq_target = track1->getChisqTarget() + track2->getChisqTarget();
309  dimuon.chisq_dump = track1->getChisqDump() + track2->getChisqDump();
310  dimuon.chisq_upstream = track1->getChisqUpstream() + track2->getChisqUpstream();
311  dimuon.chisq_single = 0.; //no longer used
312  dimuon.chisq_vx = 0.; //no longer used
313 
314  //Vertexing part
315  SQGenFit::GFTrack gtrk1(*track1);
316 
317  SQGenFit::GFTrack gtrk2(*track2);
318  double z_vtx = findDimuonZVertex(dimuon, gtrk1, gtrk2);
319  dimuon.vtx.SetXYZ(0., 0., z_vtx);
320 
321  //Vertex info based on the dimuon vertex
322  //TODO: consider using addjustable bend-plane for vertex test as well
323  TVector3 pos, mom;
324  dimuon.chisq_kf = swimTrackToVertex(gtrk1, z_vtx, &pos, &mom);
325  dimuon.p_pos.SetVectM(mom, M_MU);
326  dimuon.vtx_pos = pos;
327 
328  dimuon.chisq_kf += swimTrackToVertex(gtrk2, z_vtx, &pos, &mom);
329  dimuon.p_neg.SetVectM(mom, M_MU);
330  dimuon.vtx_neg = pos;
331 
332  //Test target hypothesis
333  refitTrkToVtx(gtrk1, Z_TARGET, &pos, &mom);
334  dimuon.p_pos_target.SetVectM(mom, M_MU);
335  refitTrkToVtx(gtrk2, Z_TARGET, &pos, &mom);
336  dimuon.p_neg_target.SetVectM(mom, M_MU);
337 
338  //Test dump hypothesis
339  //TODO: consider using addjustable bend-plane for dump test as well
340  swimTrackToVertex(gtrk1, Z_DUMP, &pos, &mom);
341  dimuon.p_pos_dump.SetVectM(mom, M_MU);
342  swimTrackToVertex(gtrk2, Z_DUMP, &pos, &mom);
343  dimuon.p_neg_dump.SetVectM(mom, M_MU);
344 
345  //Flip the sign of Px of 'positive' muon if processing like-sign muons
346  if(charge1 == charge2)
347  {
348  dimuon.p_pos.SetPx(-dimuon.p_pos.Px());
349  dimuon.p_pos_target.SetPx(-dimuon.p_pos_target.Px());
350  dimuon.p_pos_dump.SetPx(-dimuon.p_pos_dump.Px());
351  }
352  return true;
353 }
354 
356 {
357  //TODO: consider using addjustable bend-plane for vertex finding as well
358  double stepsize[3] = {25., 5., 1.};
359 
360  double z_min = 300.;
361  double chi2_min = 1.E9;
362  for(int i = 0; i < 3; ++i)
363  {
364  double z_start, z_end;
365  if(i == 0)
366  {
367  z_start = z_min;
368  z_end = Z_UPSTREAM;
369  }
370  else
371  {
372  z_start = z_min + stepsize[i-1];
373  z_end = z_min - stepsize[i-1];
374  }
375  for(double z = z_start; z > z_end; z = z - stepsize[i])
376  {
377  double chi2_1 = swimTrackToVertex(track1, z);
378  double chi2_2 = swimTrackToVertex(track2, z);
379  double chi2 = chi2_1 > 0 && chi2_2 > 0 ? chi2_1 + chi2_2 : 1.E9;
380  if(chi2 < chi2_min)
381  {
382  z_min = z;
383  chi2_min = chi2;
384  }
385  }
386  }
387 
388  return z_min;
389 }
390 
392 {
393  std::cout<<"setting up the B field and storing in 'gfiled'"<<std::endl;
394  try
395  {
396  gfield = dynamic_cast<SQGenFit::GFField*>(genfit::FieldManager::getInstance()->getField());
397  }
398  catch(const std::exception& e)
399  {
400  std::cout << "SQVertexing::InitGeom - Caught an exception " << std::endl;
401  gfield = nullptr;
402  }
403 
404  if(gfield == nullptr)
405  {
407 
408  std::unique_ptr<PHFieldConfig> default_field_cfg(new PHFieldConfig_v3(rc->get_CharFlag("fMagFile"), rc->get_CharFlag("kMagFile"), rc->get_DoubleFlag("FMAGSTR"), rc->get_DoubleFlag("KMAGSTR"), 5.));
409  PHField* phfield = PHFieldUtility::BuildFieldMap(default_field_cfg.get(), 0);
410 
411  std::cout << "SQVertexing_v2::InitField - creating new GenFit field map" << std::endl;
412 
413  gfield = new SQGenFit::GFField(phfield);
414  genfit::FieldManager::getInstance()->init(gfield);
415  genfit::MaterialEffects::getInstance()->init(new genfit::TGeoMaterialInterface());
416  }
417  else
418  {
419  std::cout << "SQVertexing_v2::InitGeom - reading existing GenFit field map" << std::endl;
420  }
422 }
423 
425 {
426  if(geom_file_name != "")
427  {
428  std::cout << "SQVertexing_v2::InitGeom - create geom from " << geom_file_name << std::endl;
429  TGeoManager* geom = TGeoManager::Import(geom_file_name.c_str());
430  if(geom != nullptr) return Fun4AllReturnCodes::EVENT_OK;
431  else {std::cout << "geometry import failed" << std::endl;}
432  }
433  else
434  {
435  std::cout << "SQVertexing_v2::InitGeom - rely on existing TGeo geometry" << std::endl;
436  }
437 
439 }
#define M_MU
Definition: GlobalConsts.h:12
virtual const std::string Name() const
Returns the name of this module.
Definition: Fun4AllBase.h:23
virtual int Verbosity() const
Gets the verbosity of this module.
Definition: Fun4AllBase.h:64
PHBoolean addNode(PHNode *)
PHFieldConfig_v3 implements field configuration information for input a field map file.
static PHField * BuildFieldMap(const PHFieldConfig *field_config, const int verbosity=0)
Build or build field map with a configuration object.
transient DST object for field storage and access
Definition: PHField.h:14
virtual double get_DoubleFlag(const std::string &name) const
Definition: PHFlag.cc:49
virtual const std::string get_CharFlag(const std::string &flag) const
Definition: PHFlag.cc:13
PHNode * findFirst(const std::string &, const std::string &)
virtual void push_back(const SQDimuon *dim)=0
void setOffset(double offset=0.)
Definition: GFField.h:21
double swimToVertex(double z, TVector3 *pos=nullptr, TVector3 *mom=nullptr, TMatrixDSym *cov=nullptr)
Definition: GFTrack.cxx:304
virtual const SQTrack * at(const size_t id) const =0
virtual size_t size() const =0
bool processOneMuon(SRecTrack *track)
SQGenFit::GFField * gfield
double findDimuonZVertex(SRecDimuon &dimuon, SQGenFit::GFTrack &track1, SQGenFit::GFTrack &track2)
double refitTrkToVtx(SQGenFit::GFTrack &track, double z, TVector3 *pos=nullptr, TVector3 *mom=nullptr)
double calcZsclp(double p)
SQVertexing_v2(const std::string &name="SQVertexing_v2", int sign1=1, int sign2=-1)
double swimTrackToVertex(SQGenFit::GFTrack &track, double z, TVector3 *pos=nullptr, TVector3 *mom=nullptr)
std::string geom_file_name
int GetNodes(PHCompositeNode *topNode)
bool legacyContainer_out
int Init(PHCompositeNode *topNode)
bool processOneDimuon(SRecTrack *track1, SRecTrack *track2, SRecDimuon &dimuon)
int process_event(PHCompositeNode *topNode)
int End(PHCompositeNode *topNode)
Called at the end of all processing.
int InitRun(PHCompositeNode *topNode)
SRecEvent * recEvent
SQTrackVector * recTrackVec
bool enableSingleRetracking
int MakeNodes(PHCompositeNode *topNode)
SQDimuonVector * recDimuonVec
Double_t chisq_single
Definition: SRecEvent.h:398
TVector3 vtx
3-vector vertex position
Definition: SRecEvent.h:379
TLorentzVector p_neg_target
Definition: SRecEvent.h:370
Double_t chisq_dump
Definition: SRecEvent.h:406
Double_t chisq_upstream
Definition: SRecEvent.h:407
TVector3 proj_target_neg
Definition: SRecEvent.h:386
Double_t chisq_vx
Definition: SRecEvent.h:402
virtual void set_track_id_pos(const int a)
Definition: SRecEvent.h:321
Double_t chisq_target
Chisq of three test position.
Definition: SRecEvent.h:405
TVector3 proj_dump_pos
Definition: SRecEvent.h:385
TVector3 proj_dump_neg
Definition: SRecEvent.h:387
TLorentzVector p_pos_target
Track momentum projections at different location.
Definition: SRecEvent.h:369
TLorentzVector p_neg
Definition: SRecEvent.h:366
Double_t chisq_kf
Vertex fit chisqs.
Definition: SRecEvent.h:401
TLorentzVector p_pos
4-momentum of the muon tracks after vertex fit
Definition: SRecEvent.h:365
TVector3 vtx_neg
Definition: SRecEvent.h:381
TVector3 vtx_pos
Definition: SRecEvent.h:380
TVector3 proj_target_pos
Track projections at different location.
Definition: SRecEvent.h:384
TLorentzVector p_pos_dump
Definition: SRecEvent.h:371
TLorentzVector p_neg_dump
Definition: SRecEvent.h:372
void insertDimuon(SRecDimuon dimuon)
Insert dimuon.
Definition: SRecEvent.h:470
Int_t getNTracks()
Get tracks.
Definition: SRecEvent.h:455
void clearDimuons()
Clear the dimuon list.
Definition: SRecEvent.cxx:824
SRecTrack & getTrack(Int_t i)
Definition: SRecEvent.h:456
TVector3 getTargetPos()
Definition: SRecEvent.h:188
Int_t getCharge() const
Gets.
Definition: SRecEvent.h:101
Double_t getChisqTarget()
Definition: SRecEvent.h:199
TVector3 getVertexPos()
Definition: SRecEvent.h:196
void setChisqDump(Double_t chisq)
Definition: SRecEvent.h:215
Double_t getChisqDump()
Definition: SRecEvent.h:198
void setChisqTarget(Double_t chisq)
Definition: SRecEvent.h:216
Double_t getChisqUpstream()
Definition: SRecEvent.h:200
void setChisqUpstream(Double_t chisq)
Definition: SRecEvent.h:217
Bool_t isKalmanFitted()
Fit status.
Definition: SRecEvent.h:147
void swimToVertex(TVector3 *pos=nullptr, TVector3 *mom=nullptr, bool hyptest=true)
Simple swim to vertex.
Definition: SRecEvent.cxx:402
TVector3 getDumpPos()
Get mom/pos at a given location.
Definition: SRecEvent.h:186
void setVertexFast(TVector3 mom, TVector3 pos)
Plain setting, no KF-related stuff.
Definition: SRecEvent.cxx:227
void setChisqVertex(Double_t chisq)
Definition: SRecEvent.h:218
static recoConsts * instance()
Definition: recoConsts.cc:7