StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StGenericVertexFinder.cxx
1 /***************************************************************************
2  * $Id: StGenericVertexFinder.cxx,v 1.53 2017/05/12 18:37:23 smirnovd Exp $
3  *
4  * Author: Lee Barnby, April 2003
5  *
6  ***************************************************************************
7  * Description: Base class for vertex finders
8  *
9  ***************************************************************************/
10 #include <cmath>
11 #include <vector>
12 
13 #include <TClonesArray.h>
14 #include <TH1F.h>
15 #include <TSpectrum.h>
16 
17 #include "StEvent/StDcaGeometry.h"
18 #include "StEvent/StEvent.h"
19 #include "StGenericVertexMaker/StGenericVertexFinder.h"
20 #include "StMuDSTMaker/COMMON/StMuPrimaryVertex.h"
21 #include "St_base/StMessMgr.h"
22 #include "St_db_Maker/St_db_Maker.h"
23 #include "StarRoot/TRMatrix.h"
24 #include "StarRoot/TRSymMatrix.h"
25 
26 
27 // Initialize static variable with default values
28 
31 
32 
34  StGenericVertexFinder(SeedFinder_t::Unspecified, VertexFit_t::Unspecified)
35 {
36 }
37 
38 
39 //______________________________________________________________________________
40 StGenericVertexFinder::StGenericVertexFinder(SeedFinder_t seedFinder, VertexFit_t fitMode) :
41  mVertexOrderMethod(orderByNumberOfDaughters),
42  mVertexConstrain(false),
43  mMode(0),
44  mVertexFitMode(fitMode),
45  mSeedFinderType(seedFinder),
46  mDebugLevel(0),
47  mUseBtof(false),
48  mUseCtb(false),
49  mBeamline(),
50  mDCAs()
51 {
52  using ObjectiveFunc_t = void (*)(int&, double*, double&, double*, int);
53 
54  ObjectiveFunc_t fcn_minuit;
55  // The number of free fit parameters, i.e. vertex position x, y, and z
56  int nFitParams = 3;
57 
58  switch (mVertexFitMode)
59  {
60  case VertexFit_t::Beamline1D:
62  nFitParams = 1; // Fit for only z coordinate of the vertex
63  break;
64 
65  case VertexFit_t::Beamline3D:
67  break;
68 
69  case VertexFit_t::NoBeamline:
70  default:
71  fcn_minuit = &StGenericVertexFinder::fcnCalcChi2DCAs;
72  break;
73  }
74 
75  mMinuit = new TMinuit(nFitParams);
76  mMinuit->SetPrintLevel(-1);
77  mMinuit->SetMaxIterations(1000);
78  mMinuit->SetFCN(fcn_minuit);
79 }
80 
81 
82 //______________________________________________________________________________
83 StGenericVertexFinder::~StGenericVertexFinder()
84 {
85  delete mMinuit; mMinuit = nullptr;
86 }
87 
88 
95 {
96  for(UInt_t i=0;i<mVertexList.size(); i++) {
97  //allocates new memory for each vertex
98  StPrimaryVertex* primV = new StPrimaryVertex(mVertexList[i]);
99  event->addPrimaryVertex(primV,mVertexOrderMethod);
100  }
101 
102  LOG_INFO << "StGenericVertexFinder::FillStEvent: Added " << mVertexList.size()
103  <<" primary vertices using ordering method: " << mVertexOrderMethod << endm;
104 
105  // Use StEvent's ordering
106  // (might be undesirable for some debugging)
107  // Also could be wrong if StEvent already has vertices for some reason
108  mVertexList.clear();
109 
110  for(UInt_t i=0;i<event->numberOfPrimaryVertices(); i++)
111  mVertexList.push_back(*(event->primaryVertex(i)));
112 }
113 
114 
124 {
125  TSpectrum tSpectrum(200);
126 
127  TH1F fVtx("fVtx", "z-dca distribution", 2500, -250, 250);
128 
129  // The size of window in cm where the probability is averaged
130  static double zWindow = 2;
131 
132  for (const StDcaGeometry* trackDca : mDCAs)
133  {
134  double xyzp[6], covXyzp[21];
135 
136  trackDca->GetXYZ(xyzp, covXyzp);
137 
138  double offset = 0.5 * xyzp[5]/trackDca->pt();
139  double sigmaZ = std::sqrt(covXyzp[5] + offset*offset);
140  sigmaZ += fVtx.GetBinWidth(1);
141 
142  // Fill TSpectrum histogram with the average probability of having vertex
143  // at z (bin center) given the tracks DCA Z coordinate (xyzp[2])
144  int bin_first = fVtx.FindBin(xyzp[2] - 5*sigmaZ);
145  int bin_last = fVtx.FindBin(xyzp[2] + 5*sigmaZ);
146 
147  for (int iBin = bin_first; iBin <= bin_last; ++iBin)
148  {
149  double z = fVtx.GetBinCenter(iBin);
150  fVtx.AddBinContent(iBin, (TMath::Erfc((z - xyzp[2] - zWindow)/sigmaZ) - TMath::Erfc((z - xyzp[2] + zWindow)/sigmaZ))/2.);
151  }
152  }
153 
154  int npeaks = tSpectrum.Search(&fVtx, 3, "nodraw", std::min(0.1, 5./mDCAs.size()) );
155 
156  auto* peaks = tSpectrum.GetPositionX();
157 
158  return std::vector<double>(peaks, peaks + npeaks);
159 }
160 
161 
162 //______________________________________________________________________________
163 void StGenericVertexFinder::addVertex(const StPrimaryVertex& vtx)
164 {
165  mVertexList.push_back(vtx);
166 }
167 //______________________________________________________________________________
168 void StGenericVertexFinder::UsePCT(bool usePCT)
169 {
170  LOG_WARN << "StGenericVertexFinder::UsePCT() not implemented for this vertex finder." << endm;
171  LOG_WARN << "StGenericVertexFinder::Expect Post-crossing tracks to be used by default in old finders." << endm;
172 }
173 //_____________________________________________________________________________
174 int StGenericVertexFinder::size() const
175 {
176  return mVertexList.size();
177 }
178 
179 
180 //______________________________________________________________________________
181 StPrimaryVertex* StGenericVertexFinder::getVertex(int idx) const
182 {
183  return (idx<(int)mVertexList.size())? (StPrimaryVertex*)(&(mVertexList[idx])) : 0;
184 }
185 
186 
187 void StGenericVertexFinder::InitRun(int run_number, const St_db_Maker* db_maker)
188 {
189  LOG_INFO << "StGenericVertexFinder::InitRun(run_number=" << run_number << ")" << endm;
190 
191  // Check if all necessary conditions satisfied
192  bool prerequisites = db_maker && star_vertex::requiresBeamline(mVertexFitMode);
193 
194  // Just exit if there is nothing to do
195  if (!prerequisites) return;
196 
197  const TDataSet* dbDataSet = const_cast<St_db_Maker*>(db_maker)->GetDataBase("Calibrations/rhic/vertexSeed");
198 
199  vertexSeed_st* vSeed = dbDataSet ? static_cast<St_vertexSeed*>(dbDataSet->FindObject("vertexSeed"))->GetTable() : nullptr;
200 
201  if (!vSeed) {
202  LOG_FATAL << "Vertex fit w/ beamline requested but 'Calibrations/rhic/vertexSeed' table not found" << endm;
203  } else {
204  UseVertexConstraint(*vSeed);
205  }
206 }
207 
208 
209 //______________________________________________________________________________
210 void StGenericVertexFinder::Clear()
211 {
212  mVertexList.clear();
213 }
214 
215 
216 void StGenericVertexFinder::result(TClonesArray& stMuDstPrimaryVertices)
217 {
218  stMuDstPrimaryVertices.Clear();
219 
220  int index = 0;
221 
222  for (const StPrimaryVertex & stVertex : mVertexList)
223  {
224  // This idiotic conversion is required due to the constructor accepting
225  // reference to pointer
226  const StPrimaryVertex * myStVertex = &stVertex;
227  new(stMuDstPrimaryVertices[index++]) StMuPrimaryVertex( myStVertex);
228  }
229 }
230 
231 
233 {
234  static double scale = 100;
235 
236  // Initialize f with value for beamline
237  double f = 0;
238 
239  for (const StDcaGeometry* dca : mDCAs)
240  {
241  double err2;
242  double dist = dca->thelix().Dca( &point.x(), &err2);
243  double chi2 = dist*dist/err2;
244 
245  f += scale*(1. - TMath::Exp(-chi2/scale)); // robust potential
246  }
247 
248  return f;
249 }
250 
251 
253 {
254  static double scale = 100;
255 
256  return CalcChi2DCAs(point) + scale*(1. - TMath::Exp(-CalcChi2Beamline(point)/scale));
257 }
258 
259 
278 {
279  // Just for shorthand
280  const vertexSeed_st& bl = mBeamline;
281 
282  double dx = point.x() - bl.x0;
283  double dy = point.y() - bl.y0;
284  double zv = point.z();
285 
286  double kx = bl.dxdz;
287  double kx2 = kx*kx;
288  double ky = bl.dydz;
289  double ky2 = ky*ky;
290 
291  double kx2_ky2_1 = kx2 + ky2 + 1;
292  double ky_dy_zv = ky*dy + zv;
293  double kx_dx_zv = kx*dx + zv;
294  double ky_dy_zv_2 = ky_dy_zv*ky_dy_zv;
295  double kx_dx_zv_2 = kx_dx_zv*kx_dx_zv;
296 
297  // The distance between the line and the point
298  StThreeVectorD dist_vec (
299  ( (ky2 + 1)*dx - kx*ky*dy - kx*zv)/kx2_ky2_1,
300  ( - kx*ky*dx + (kx2 + 1)*dy - ky*zv)/kx2_ky2_1,
301  ( - kx*dx - ky*dy + (kx2 + ky2)*zv)/kx2_ky2_1
302  );
303 
304  double dist_mag = dist_vec.mag();
305 
306  // When the vertex (point) gets closer to the beamline there may not be
307  // enough precision to do the intermediate calculations for the
308  // transformation of the errors, i.e. the Jacobian below. The distance is
309  // measured in cm so, anything within a nanometer will be considered to be on
310  // the beam line and we just return a zero for the chi2 in such cases. This
311  // makes sense for all non-zero errors (that is what we actually expect and
312  // assume) and if they are zero they are unphysical anyway.
313  if (dist_mag < 1e-7) return 0;
314 
315  // TODO check if the value of denom_sqrt is the same as dist_mag
316  double denom_sqrt = kx2_ky2_1 * sqrt( ( (kx*dy - ky*dx)*(kx*dy - ky*dx) + (ky*zv - dy)*(ky*zv - dy) + (kx*zv - dx)*(kx*zv - dx) ) /kx2_ky2_1);
317  double denom = kx2_ky2_1 * denom_sqrt;
318 
319  // The Jacobian for the distance w.r.t. measured beamline parameters, i.e. x0, y0, kx, and ky
320  double jacobian[4] = {
321  ( -(ky2 + 1)*dx + kx*ky*dy + kx*zv ) / denom_sqrt,
322  ( kx*ky*dx - (kx2 + 1)*dy + ky*zv ) / denom_sqrt,
323 
324  ( kx*ky_dy_zv_2 - kx*(ky2 + 1)*dx*dx + (kx2 - ky2 - 1)*dx*ky_dy_zv ) / denom,
325  ( ky*kx_dx_zv_2 - ky*(kx2 + 1)*dy*dy - (kx2 - ky2 + 1)*dy*kx_dx_zv ) / denom
326  };
327 
328  // ... and the covariance matrix for the beamline parameters
329  double variance_x0 = bl.err_x0*bl.err_x0;
330  double variance_y0 = bl.err_y0*bl.err_y0;
331  double variance_dxdz = bl.err_dxdz*bl.err_dxdz;
332  double variance_dydz = bl.err_dydz*bl.err_dydz;
333 
334  double covBeamline[10] = {
335  variance_x0,
336  0, variance_y0,
337  0, 0, variance_dxdz,
338  0, 0, 0, variance_dydz
339  };
340 
341  // Finaly, calculate the covariance matrix along the vector connecting the beamline and the point
342  // The result is a 1x1 matrix
343  TRSymMatrix covarianceMprime(TRMatrix(1, 4, jacobian), TRArray::kAxSxAT, TRSymMatrix(4, covBeamline) );
344 
345  double chi2 = dist_mag*dist_mag/covarianceMprime[0];
346 
347  return chi2;
348 }
349 
350 
359 {
360  // Estimate new seed position using provided tracks
361  StThreeVectorD vertexSeed(0, 0, 0);
362  StThreeVectorD totalWeigth(0, 0, 0);
363 
364  if (trackDcas.size() == 0) {
365  LOG_WARN << "StGenericVertexFinder::CalcVertexSeed: Empty container with track DCAs. "
366  "Returning default seed: StThreeVectorD(0, 0, 0)" << endm;
367  return vertexSeed;
368  }
369 
370 
371  double xyzp[6], covXyzp[21];
372 
373  for (const StDcaGeometry* trackDca : trackDcas)
374  {
375  trackDca->GetXYZ(xyzp, covXyzp);
376 
377  double x_weight = 1./covXyzp[0];
378  double y_weight = 1./covXyzp[2];
379  double z_weight = 1./covXyzp[5];
380 
381  vertexSeed += StThreeVectorD(xyzp[0]*x_weight, xyzp[1]*y_weight, xyzp[2]*z_weight);
382  totalWeigth += StThreeVectorD(x_weight, y_weight, z_weight);
383  }
384 
385  vertexSeed.set(vertexSeed.x()/totalWeigth.x(), vertexSeed.y()/totalWeigth.y(), vertexSeed.z()/totalWeigth.z());
386 
387  return vertexSeed;
388 }
389 
390 
391 //______________________________________________________________________________
392 void StGenericVertexFinder::NoVertexConstraint()
393 {
394  mVertexConstrain = false;
395  mVertexFitMode = VertexFit_t::NoBeamline;
396  LOG_INFO << "StGenericVertexFinder::No Vertex Constraint" << endm;
397 }
398 
399 
404 void StGenericVertexFinder::UseVertexConstraint(const vertexSeed_st& beamline)
405 {
406  mBeamline = beamline;
407 
408  LOG_INFO << "BeamLine constraints:\n"
409  << "weight: " << mBeamline.weight << "\n"
410  << "x(z) = (" << mBeamline.x0 << " +/- max(0.01, " << mBeamline.err_x0 << ") ) + "
411  << "(" << mBeamline.dxdz << " +/- max(0.0001, " << mBeamline.err_dxdz << ") ) * z\n"
412  << "y(z) = (" << mBeamline.y0 << " +/- max(0.01, " << mBeamline.err_y0 << ") ) + "
413  << "(" << mBeamline.dydz << " +/- max(0.0001, " << mBeamline.err_dydz << ") ) * z"
414  << endm;
415 
416  mBeamline.err_x0 = std::max(0.01f, mBeamline.err_x0);
417  mBeamline.err_y0 = std::max(0.01f, mBeamline.err_y0);
418 
419  // 0.0001f radians corresponds to a 0.1mm arc at 1m = 1000mm length
420  mBeamline.err_dxdz = std::max(0.0001f, mBeamline.err_dxdz);
421  mBeamline.err_dydz = std::max(0.0001f, mBeamline.err_dydz);
422 
424 }
425 
426 
431 double StGenericVertexFinder::beamX(double z) const
432 {
433  return mBeamline.x0 + mBeamline.dxdz*z;
434 }
435 
436 
441 double StGenericVertexFinder::beamY(double z) const
442 {
443  return mBeamline.y0 + mBeamline.dydz*z;
444 }
virtual double CalcChi2DCAs(const StThreeVectorD &point)
Caclulates total chi2 for the track DCAs stored in mDCAs and a point.
void UseVertexConstraint(const vertexSeed_st &beamline)
double CalcChi2DCAsBeamline(const StThreeVectorD &point)
Caclulates total chi2 for the beamline and track DCAs stored in mDCAs and a point.
double CalcChi2Beamline(const StThreeVectorD &point)
Caclulates chi2 for the beamline and a point.
double beamX(double z) const
double beamY(double z) const
std::vector< double > FindSeeds_TSpectrum()
static void fcnCalcChi2DCAsBeamline1D(int &npar, double *gin, double &f, double *par, Int_t iflag)
A static interface to CalcChi2DCAs(...) with x and y fixed by beamline equation.
StThreeVectorD CalcVertexSeed(const StDcaList &trackDcas)
static void fcnCalcChi2DCAsBeamline(int &npar, double *gin, double &f, double *par, int iflag)
A static interface to CalcChi2DCAsBeamline(...)
VertexFit_t mVertexFitMode
The type of vertex fit to use in derived concrete implementation.
static StGenericVertexFinder * sSelf
By default point to invalid object.
StGenericVertexFinder()
Default initialization with unspecified seed finder and fitting mode.