CMS 3D CMS Logo

PVFitter.cc
Go to the documentation of this file.
1 
14 
20 
23 
30 
33 
34 #include "Minuit2/FCNBase.h"
35 #include "Minuit2/FunctionMinimum.h"
36 #include "Minuit2/MnMigrad.h"
37 #include "Minuit2/MnPrint.h"
38 #include "TF1.h"
39 #include "TMinuitMinimizer.h"
40 
41 #include <iostream>
42 using namespace std ;
43 
45  edm::ConsumesCollector &&iColl)
46  : ftree_(nullptr)
47 {
48  initialize(iConfig, iColl);
49 }
50 
53  :ftree_(nullptr)
54 {
55  initialize(iConfig, iColl);
56 }
57 
60 {
61  //In order to make fitting ROOT histograms thread safe
62  // one must call this undocumented function
63  TMinuitMinimizer::UseStaticMinuit(false);
64  debug_ = iConfig.getParameter<edm::ParameterSet>("PVFitter").getUntrackedParameter<bool>("Debug");
66  iConfig.getParameter<edm::ParameterSet>("PVFitter")
67  .getUntrackedParameter<edm::InputTag>("VertexCollection", edm::InputTag("offlinePrimaryVertices")));
68  do3DFit_ = iConfig.getParameter<edm::ParameterSet>("PVFitter").getUntrackedParameter<bool>("Apply3DFit");
69  //writeTxt_ = iConfig.getParameter<edm::ParameterSet>("PVFitter").getUntrackedParameter<bool>("WriteAscii");
70  //outputTxt_ = iConfig.getParameter<edm::ParameterSet>("PVFitter").getUntrackedParameter<std::string>("AsciiFileName");
71  maxNrVertices_ = iConfig.getParameter<edm::ParameterSet>("PVFitter").getUntrackedParameter<unsigned int>("maxNrStoredVertices");
72  minNrVertices_ = iConfig.getParameter<edm::ParameterSet>("PVFitter").getUntrackedParameter<unsigned int>("minNrVerticesForFit");
73  minVtxNdf_ = iConfig.getParameter<edm::ParameterSet>("PVFitter").getUntrackedParameter<double>("minVertexNdf");
74  maxVtxNormChi2_ = iConfig.getParameter<edm::ParameterSet>("PVFitter").getUntrackedParameter<double>("maxVertexNormChi2");
75  minVtxTracks_ = iConfig.getParameter<edm::ParameterSet>("PVFitter").getUntrackedParameter<unsigned int>("minVertexNTracks");
76  minVtxWgt_ = iConfig.getParameter<edm::ParameterSet>("PVFitter").getUntrackedParameter<double>("minVertexMeanWeight");
77  maxVtxR_ = iConfig.getParameter<edm::ParameterSet>("PVFitter").getUntrackedParameter<double>("maxVertexR");
78  maxVtxZ_ = iConfig.getParameter<edm::ParameterSet>("PVFitter").getUntrackedParameter<double>("maxVertexZ");
79  errorScale_ = iConfig.getParameter<edm::ParameterSet>("PVFitter").getUntrackedParameter<double>("errorScale");
80  sigmaCut_ = iConfig.getParameter<edm::ParameterSet>("PVFitter").getUntrackedParameter<double>("nSigmaCut");
81  fFitPerBunchCrossing=iConfig.getParameter<edm::ParameterSet>("PVFitter").getUntrackedParameter<bool>("FitPerBunchCrossing");
82  useOnlyFirstPV_ = iConfig.getParameter<edm::ParameterSet>("PVFitter").getUntrackedParameter<bool>("useOnlyFirstPV");
83  minSumPt_ = iConfig.getParameter<edm::ParameterSet>("PVFitter").getUntrackedParameter<double>("minSumPt");
84 
85  // preset quality cut to "infinite"
86  dynamicQualityCut_ = 1.e30;
87 
88  hPVx = new TH2F("hPVx","PVx vs PVz distribution",200,-maxVtxR_, maxVtxR_, 200, -maxVtxZ_, maxVtxZ_);
89  hPVy = new TH2F("hPVy","PVy vs PVz distribution",200,-maxVtxR_, maxVtxR_, 200, -maxVtxZ_, maxVtxZ_);
90 }
91 
93 
94 }
95 
96 
98 {
99 
100  //------ Primary Vertices
102  bool hasPVs = false;
103 
104  if ( iEvent.getByToken(vertexToken_, PVCollection ) ) {
105  hasPVs = true;
106  }
107  //------
108 
109  if ( hasPVs ) {
110 
111  for (reco::VertexCollection::const_iterator pv = PVCollection->begin(); pv != PVCollection->end(); ++pv ) {
112  if (useOnlyFirstPV_){
113  if (pv != PVCollection->begin()) break;
114  }
115 
116  //--- vertex selection
117  if ( pv->isFake() || pv->tracksSize()==0 ) continue;
118  if ( pv->ndof() < minVtxNdf_ || (pv->ndof()+3.)/pv->tracksSize()<2*minVtxWgt_ ) continue;
119  //---
120 
121  if (pv->tracksSize() < minVtxTracks_ ) continue;
122 
123  const auto& testTrack = pv->trackRefAt(0);
124  if(testTrack.isNull() || !testTrack.isAvailable())
125  {
126  edm::LogInfo("") << "Track collection not found. Skipping cut on sumPt.";
127  }
128  else
129  {
130  double sumPt=0;
131  for(auto iTrack = pv->tracks_begin(); iTrack != pv->tracks_end(); ++iTrack)
132  {
133  const auto pt = (*iTrack)->pt();
134  sumPt += pt;
135  }
136  if (sumPt < minSumPt_) continue;
137  }
138 
139  hPVx->Fill( pv->x(), pv->z() );
140  hPVy->Fill( pv->y(), pv->z() );
141 
142  //
143  // 3D fit section
144  //
145  // apply additional quality cut
146  if ( pvQuality(*pv)>dynamicQualityCut_ ) continue;
147  // if store exceeds max. size: reduce size and apply new quality cut
148  if ( pvStore_.size()>=maxNrVertices_ ) {
149  compressStore();
150  if ( pvQuality(*pv)>dynamicQualityCut_ ) continue;
151  }
152  //
153  // copy PV to store
154  //
155  int bx = iEvent.bunchCrossing();
156  BeamSpotFitPVData pvData;
157  pvData.bunchCrossing = bx;
158  pvData.position[0] = pv->x();
159  pvData.position[1] = pv->y();
160  pvData.position[2] = pv->z();
161  pvData.posError[0] = pv->xError();
162  pvData.posError[1] = pv->yError();
163  pvData.posError[2] = pv->zError();
164  pvData.posCorr[0] = pv->covariance(0,1)/pv->xError()/pv->yError();
165  pvData.posCorr[1] = pv->covariance(0,2)/pv->xError()/pv->zError();
166  pvData.posCorr[2] = pv->covariance(1,2)/pv->yError()/pv->zError();
167  pvStore_.push_back(pvData);
168 
169  if(ftree_ != nullptr){
170  theBeamSpotTreeData_.run(iEvent.id().run());
174  ftree_->Fill();
175  }
176 
177  if (fFitPerBunchCrossing) bxMap_[bx].push_back(pvData);
178 
179  }
180 
181  }
182 
183 }
184 
185 void PVFitter::setTree(TTree* tree){
186  ftree_ = tree;
188 }
189 
191 
192  using namespace ROOT::Minuit2;
193  edm::LogInfo("PVFitter") << " Number of bunch crossings: " << bxMap_.size() << std::endl;
194 
195  bool fit_ok = true;
196 
197  for ( std::map<int,std::vector<BeamSpotFitPVData> >::const_iterator pvStore = bxMap_.begin();
198  pvStore!=bxMap_.end(); ++pvStore) {
199 
200  // first set null beam spot in case
201  // fit fails
202  fbspotMap[pvStore->first] = reco::BeamSpot();
203 
204  edm::LogInfo("PVFitter") << " Number of PVs collected for PVFitter: " << (pvStore->second).size() << " in bx: " << pvStore->first << std::endl;
205 
206  if ( (pvStore->second).size() <= minNrVertices_ ) {
207  edm::LogWarning("PVFitter") << " not enough PVs, continue" << std::endl;
208  fit_ok = false;
209  continue;
210  }
211 
212  edm::LogInfo("PVFitter") << "Calculating beam spot with PVs ..." << std::endl;
213 
214  //
215  // LL function and fitter
216  //
217  FcnBeamSpotFitPV* fcn = new FcnBeamSpotFitPV(pvStore->second);
218  //
219  // fit parameters: positions, widths, x-y correlations, tilts in xz and yz
220  //
221  MnUserParameters upar;
222  upar.Add("x" , 0. , 0.02 , -10., 10.); // 0
223  upar.Add("y" , 0. , 0.02 , -10., 10.); // 1
224  upar.Add("z" , 0. , 0.20 , -30., 30.); // 2
225  upar.Add("ex" , 0.015, 0.01 , 0. , 10.); // 3
226  upar.Add("corrxy", 0. , 0.02 , -1. , 1. ); // 4
227  upar.Add("ey" , 0.015, 0.01 , 0. , 10.); // 5
228  upar.Add("dxdz" , 0. , 0.0002, -0.1, 0.1); // 6
229  upar.Add("dydz" , 0. , 0.0002, -0.1, 0.1); // 7
230  upar.Add("ez" , 1. , 0.1 , 0. , 30.); // 8
231  upar.Add("scale", errorScale_ , errorScale_/10.,
232  errorScale_/2., errorScale_*2.); // 9
233  MnMigrad migrad(*fcn, upar);
234 
235  //
236  // first iteration without correlations
237  //
238  upar.Fix(4);
239  upar.Fix(6);
240  upar.Fix(7);
241  upar.Fix(9);
242  FunctionMinimum ierr = migrad(0,1.);
243  if ( !ierr.IsValid() ) {
244  edm::LogInfo("PVFitter") << "3D beam spot fit failed in 1st iteration" << std::endl;
245  fit_ok = false;
246  continue;
247  }
248  //
249  // refit with harder selection on vertices
250  //
251  fcn->setLimits(upar.Value(0)-sigmaCut_*upar.Value(3),
252  upar.Value(0)+sigmaCut_*upar.Value(3),
253  upar.Value(1)-sigmaCut_*upar.Value(5),
254  upar.Value(1)+sigmaCut_*upar.Value(5),
255  upar.Value(2)-sigmaCut_*upar.Value(8),
256  upar.Value(2)+sigmaCut_*upar.Value(8));
257  ierr = migrad(0,1.);
258  if ( !ierr.IsValid() ) {
259  edm::LogInfo("PVFitter") << "3D beam spot fit failed in 2nd iteration" << std::endl;
260  fit_ok = false;
261  continue;
262  }
263  //
264  // refit with correlations
265  //
266  upar.Release(4);
267  upar.Release(6);
268  upar.Release(7);
269  ierr = migrad(0,1.);
270  if ( !ierr.IsValid() ) {
271  edm::LogInfo("PVFitter") << "3D beam spot fit failed in 3rd iteration" << std::endl;
272  fit_ok = false;
273  continue;
274  }
275 
276  fwidthX = upar.Value(3);
277  fwidthY = upar.Value(5);
278  fwidthZ = upar.Value(8);
279  fwidthXerr = upar.Error(3);
280  fwidthYerr = upar.Error(5);
281  fwidthZerr = upar.Error(8);
282 
284  // need to get the full cov matrix
285  matrix(0,0) = pow( upar.Error(0), 2);
286  matrix(1,1) = pow( upar.Error(1), 2);
287  matrix(2,2) = pow( upar.Error(2), 2);
288  matrix(3,3) = fwidthZerr * fwidthZerr;
289  matrix(4,4) = pow( upar.Error(6), 2);
290  matrix(5,5) = pow( upar.Error(7), 2);
291  matrix(6,6) = fwidthXerr * fwidthXerr;
292 
294  upar.Value(1),
295  upar.Value(2) ),
296  fwidthZ,
297  upar.Value(6), upar.Value(7),
298  fwidthX,
299  matrix );
303 
304  fbspotMap[pvStore->first] = fbeamspot;
305  edm::LogInfo("PVFitter") << "3D PV fit done for this bunch crossing."<<std::endl;
306  //delete fcn;
307  fit_ok = fit_ok & true;
308  }
309 
310  return fit_ok;
311 }
312 
313 
315 
316  using namespace ROOT::Minuit2;
317  edm::LogInfo("PVFitter") << " Number of PVs collected for PVFitter: " << pvStore_.size() << std::endl;
318 
319  if ( pvStore_.size() <= minNrVertices_ ) return false;
320 
321  TH1F *h1PVx = (TH1F*) hPVx->ProjectionX("h1PVx", 0, -1, "e");
322  TH1F *h1PVy = (TH1F*) hPVy->ProjectionX("h1PVy", 0, -1, "e");
323  TH1F *h1PVz = (TH1F*) hPVx->ProjectionY("h1PVz", 0, -1, "e");
324 
325  //Use our own copy for thread safety
326  // also do not add to global list of functions
327  TF1 gausx("localGausX","gaus",0.,1.,TF1::EAddToList::kNo);
328  TF1 gausy("localGausY","gaus",0.,1.,TF1::EAddToList::kNo);
329  TF1 gausz("localGausZ","gaus",0.,1.,TF1::EAddToList::kNo);
330 
331  h1PVx->Fit(&gausx,"QLMN0");
332  h1PVy->Fit(&gausy,"QLMN0");
333  h1PVz->Fit(&gausz,"QLMN0");
334 
335 
336  fwidthX = gausx.GetParameter(2);
337  fwidthY = gausy.GetParameter(2);
338  fwidthZ = gausz.GetParameter(2);
339  fwidthXerr = gausx.GetParError(2);
340  fwidthYerr = gausy.GetParError(2);
341  fwidthZerr = gausz.GetParError(2);
342 
343  double estX = gausx.GetParameter(1);
344  double estY = gausy.GetParameter(1);
345  double estZ = gausz.GetParameter(1);
346  double errX = fwidthX*3.;
347  double errY = fwidthY*3.;
348  double errZ = fwidthZ*3.;
349 
350  if ( ! do3DFit_ ) {
351 
353  matrix(2,2) = gausz.GetParError(1) * gausz.GetParError(1);
354  matrix(3,3) = fwidthZerr * fwidthZerr;
355  matrix(6,6) = fwidthXerr * fwidthXerr;
356 
357  fbeamspot = reco::BeamSpot( reco::BeamSpot::Point(gausx.GetParameter(1),
358  gausy.GetParameter(1),
359  gausz.GetParameter(1) ),
360  fwidthZ,
361  0., 0.,
362  fwidthX,
363  matrix );
367 
368  }
369  else { // do 3D fit
370  //
371  // LL function and fitter
372  //
374  //
375  // fit parameters: positions, widths, x-y correlations, tilts in xz and yz
376  //
377  MnUserParameters upar;
378  upar.Add("x" , estX , errX , -10. , 10. ); // 0
379  upar.Add("y" , estY , errY , -10. , 10. ); // 1
380  upar.Add("z" , estZ , errZ , -30. , 30. ); // 2
381  upar.Add("ex" , 0.015 , 0.01 , 0. , 10. ); // 3
382  upar.Add("corrxy", 0. , 0.02 , -1. , 1. ); // 4
383  upar.Add("ey" , 0.015 , 0.01 , 0. , 10. ); // 5
384  upar.Add("dxdz" , 0. , 0.0002 , -0.1 , 0.1 ); // 6
385  upar.Add("dydz" , 0. , 0.0002 , -0.1 , 0.1 ); // 7
386  upar.Add("ez" , 1. , 0.1 , 0. , 30. ); // 8
387  upar.Add("scale" , errorScale_, errorScale_/10.,errorScale_/2., errorScale_*2.); // 9
388  MnMigrad migrad(*fcn, upar);
389  //
390  // first iteration without correlations
391  //
392  migrad.Fix(4);
393  migrad.Fix(6);
394  migrad.Fix(7);
395  migrad.Fix(9);
396  FunctionMinimum ierr = migrad(0,1.);
397  if ( !ierr.IsValid() ) {
398  edm::LogWarning("PVFitter") << "3D beam spot fit failed in 1st iteration" << std::endl;
399  return false;
400  }
401  //
402  // refit with harder selection on vertices
403  //
404 
405  vector<double> results ;
406  vector<double> errors ;
407  results = ierr.UserParameters().Params() ; \
408  errors = ierr.UserParameters().Errors() ; \
409 
410 
411  fcn->setLimits(results[0]-sigmaCut_*results[3],
412  results[0]+sigmaCut_*results[3],
413  results[1]-sigmaCut_*results[5],
414  results[1]+sigmaCut_*results[5],
415  results[2]-sigmaCut_*results[8],
416  results[2]+sigmaCut_*results[8]);
417  ierr = migrad(0,1.);
418  if ( !ierr.IsValid() ) {
419  edm::LogWarning("PVFitter") << "3D beam spot fit failed in 2nd iteration" << std::endl;
420  return false;
421  }
422  //
423  // refit with correlations
424  //
425  migrad.Release(4);
426  migrad.Release(6);
427  migrad.Release(7);
428  ierr = migrad(0,1.);
429  if ( !ierr.IsValid() ) {
430  edm::LogWarning("PVFitter") << "3D beam spot fit failed in 3rd iteration" << std::endl;
431  return false;
432  }
433 
434  results = ierr.UserParameters().Params() ; \
435  errors = ierr.UserParameters().Errors() ; \
436 
437  fwidthX = results[3];
438  fwidthY = results[5];
439  fwidthZ = results[8];
440  fwidthXerr = errors[3];
441  fwidthYerr = errors[5];
442  fwidthZerr = errors[8];
443 
444  // check errors on widths and sigmaZ for nan
446  edm::LogWarning("PVFitter") << "3D beam spot fit returns nan in 3rd iteration" << std::endl;
447  return false;
448  }
449 
451  // need to get the full cov matrix
452  matrix(0,0) = pow( errors[0], 2);
453  matrix(1,1) = pow( errors[1], 2);
454  matrix(2,2) = pow( errors[2], 2);
455  matrix(3,3) = fwidthZerr * fwidthZerr;
456  matrix(6,6) = fwidthXerr * fwidthXerr;
457 
459  results[1],
460  results[2] ),
461  fwidthZ,
462  results[6], results[7],
463  fwidthX,
464  matrix );
468  }
469 
470  return true;
471 }
472 
474 
475 }
476 
477 
478 void
480 {
481  //
482  // fill vertex qualities
483  //
484  pvQualities_.resize(pvStore_.size());
485  for ( unsigned int i=0; i<pvStore_.size(); ++i ) pvQualities_[i] = pvQuality(pvStore_[i]);
486  sort(pvQualities_.begin(),pvQualities_.end());
487  //
488  // Set new quality cut to median. This cut will be used to reduce the
489  // number of vertices in the store and also apply to all new vertices
490  // until the next reset
491  //
493  //
494  // remove all vertices failing the cut from the store
495  // (to be moved to a more efficient memory management!)
496  //
497  unsigned int iwrite(0);
498  for ( unsigned int i=0; i<pvStore_.size(); ++i ) {
499  if ( pvQuality(pvStore_[i])>dynamicQualityCut_ ) continue;
500  if ( i!=iwrite ) pvStore_[iwrite] = pvStore_[i];
501  ++iwrite;
502  }
503  pvStore_.resize(iwrite);
504  edm::LogInfo("PVFitter") << "Reduced primary vertex store size to "
505  << pvStore_.size() << " ; new dynamic quality cut = "
506  << dynamicQualityCut_ << std::endl;
507 
508 }
509 
510 double
512 {
513  //
514  // determinant of the transverse part of the PV covariance matrix
515  //
516  return
517  pv.covariance(0,0)*pv.covariance(1,1)-
518  pv.covariance(0,1)*pv.covariance(0,1);
519 }
520 
521 double
523 {
524  //
525  // determinant of the transverse part of the PV covariance matrix
526  //
527  double ex = pv.posError[0];
528  double ey = pv.posError[1];
529  return ex*ex*ey*ey*(1-pv.posCorr[0]*pv.posCorr[0]);
530 }
RunNumber_t run() const
Definition: EventID.h:39
double minSumPt_
Definition: PVFitter.h:160
size
Write out results.
std::vector< double > pvQualities_
Definition: PVFitter.h:181
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
math::Error< dimension >::type CovarianceMatrix
Definition: BeamSpot.h:31
T getParameter(std::string const &) const
bool debug_
Definition: PVFitter.h:145
double maxVtxNormChi2_
Definition: PVFitter.h:153
void setTree(TTree *tree)
Definition: PVFitter.cc:185
std::map< int, std::vector< BeamSpotFitPVData > > bxMap_
Definition: PVFitter.h:179
void initialize(const edm::ParameterSet &iConfig, edm::ConsumesCollector &iColl)
Definition: PVFitter.cc:58
void run(unsigned int run)
void compressStore()
reduce size of primary vertex cache by increasing quality limit
Definition: PVFitter.cc:479
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:508
double minVtxWgt_
Definition: PVFitter.h:155
bool useOnlyFirstPV_
Definition: PVFitter.h:141
double minVtxNdf_
Definition: PVFitter.h:152
int bunchCrossing() const
Definition: EventBase.h:66
edm::LuminosityBlockNumber_t luminosityBlock() const
Definition: EventBase.h:63
std::vector< Vertex > VertexCollection
collection of Vertex objects
Definition: VertexFwd.h:9
math::XYZPoint Point
point in the space
Definition: BeamSpot.h:29
double covariance(int i, int j) const
(i, j)-th element of error matrix, i, j = 0, ... 2
Definition: Vertex.h:130
double fwidthY
Definition: PVFitter.h:172
double errorScale_
Definition: PVFitter.h:158
#define nullptr
bool do3DFit_
Definition: PVFitter.h:146
double dynamicQualityCut_
Definition: PVFitter.h:180
double fwidthYerr
Definition: PVFitter.h:175
double fwidthZ
Definition: PVFitter.h:173
double fwidthXerr
Definition: PVFitter.h:174
void setType(BeamType type)
set beam type
Definition: BeamSpot.h:131
void bunchCrossing(unsigned int bunchCrossing)
reco::BeamSpot fbeamspot
Definition: PVFitter.h:138
void lumi(unsigned int lumi)
int iEvent
Definition: GenABIO.cc:230
std::vector< BeamSpotFitPVData > pvStore_
Definition: PVFitter.h:178
void readEvent(const edm::Event &iEvent)
Definition: PVFitter.cc:97
bool isNotFinite(T x)
Definition: isFinite.h:10
void setBeamWidthY(double v)
Definition: BeamSpot.h:109
BeamSpotTreeData theBeamSpotTreeData_
Definition: PVFitter.h:183
bool fFitPerBunchCrossing
Definition: PVFitter.h:140
TH2F * hPVy
Definition: PVFitter.h:164
def pv(vc)
Definition: MetAnalyzer.py:6
void pvData(const BeamSpotFitPVData &pvData)
TTree * ftree_
Definition: PVFitter.h:166
std::map< int, reco::BeamSpot > fbspotMap
Definition: PVFitter.h:139
edm::EDGetTokenT< reco::VertexCollection > vertexToken_
Definition: PVFitter.h:147
double pvQuality(const reco::Vertex &pv) const
vertex quality measure
Definition: PVFitter.cc:511
double maxVtxR_
Definition: PVFitter.h:156
double maxVtxZ_
Definition: PVFitter.h:157
unsigned int maxNrVertices_
Definition: PVFitter.h:150
double fwidthZerr
Definition: PVFitter.h:176
void branch(TTree *tree)
PVFitter()
Definition: PVFitter.h:45
unsigned int minVtxTracks_
Definition: PVFitter.h:154
void fcn(int &, double *, double &, double *, int)
bool runFitter()
Definition: PVFitter.cc:314
TH2F * hPVx
Definition: PVFitter.h:164
unsigned int minNrVertices_
Definition: PVFitter.h:151
void setLimits(float xmin, float xmax, float ymin, float ymax, float zmin, float zmax)
bool runBXFitter()
Definition: PVFitter.cc:190
double sigmaCut_
Definition: PVFitter.h:159
edm::EventID id() const
Definition: EventBase.h:60
void setBeamWidthX(double v)
Definition: BeamSpot.h:108
virtual ~PVFitter()
Definition: PVFitter.cc:92
double fwidthX
Definition: PVFitter.h:171
Definition: tree.py:1
void dumpTxtFile()
Definition: PVFitter.cc:473
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40