CMS 3D CMS Logo

TkLasBeamFitter.cc
Go to the documentation of this file.
1 
15 // framework include files
27 
33 
34 // data formats
35 // for edm::InRun
37 
38 // laser data formats
41 
42 // further includes
47 
48 #include <iostream>
49 #include "TMinuit.h"
50 #include "TGraphErrors.h"
51 #include "TF1.h"
52 #include "TH1.h"
53 #include "TH2.h"
54 
55 using namespace edm;
56 using namespace std;
57 
58 //
59 // class declaration
60 //
61 
62 class TkLasBeamFitter : public edm::one::EDProducer<edm::EndRunProducer> {
63 public:
64  explicit TkLasBeamFitter(const edm::ParameterSet &config);
65  ~TkLasBeamFitter() override;
66 
67  //virtual void beginJob(const edm::EventSetup& /*access deprecated*/) {}
68  void produce(edm::Event &event, const edm::EventSetup &setup) override;
69  // virtual void beginRun(edm::Run &run, const edm::EventSetup &setup);
70  void endRunProduce(edm::Run &run, const edm::EventSetup &setup) override;
71  //virtual void endJob() {}
72 
73 private:
76  void getLasBeams(TkFittedLasBeam &beam, vector<TrajectoryStateOnSurface> &tsosLas);
77  void getLasHits(TkFittedLasBeam &beam,
79  vector<const GeomDetUnit *> &gd,
80  vector<GlobalPoint> &globHit,
81  unsigned int &hitsAtTecPlus);
82  // void fillVectors(TkFittedLasBeam &beam);
83 
84  // need static functions to be used in fitter(..);
85  // all parameters used therein have to be static, as well (see below)
86  static double tecPlusFunction(double *x, double *par);
87  static double tecMinusFunction(double *x, double *par);
88  static double atFunction(double *x, double *par);
89 
90  void fitter(TkFittedLasBeam &beam,
91  AlgebraicSymMatrix &covMatrix,
92  unsigned int &hitsAtTecPlus,
93  unsigned int &nFitParams,
94  std::vector<double> &hitPhi,
95  std::vector<double> &hitPhiError,
96  std::vector<double> &hitZprimeError,
97  double &zMin,
98  double &zMax,
99  double &bsAngleParam,
100  double &offset,
101  double &offsetError,
102  double &slope,
103  double &slopeError,
104  double &phiAtMinusParam,
105  double &phiAtPlusParam,
106  double &atThetaSplitParam);
107 
109  unsigned int &hit,
110  double &trackPhi,
111  double &trackPhiRef,
112  double &offset,
113  double &slope,
114  double &bsAngleParam,
115  double &phiAtMinusParam,
116  double &phiAtPlusParam,
117  double &atThetaSplitParam,
118  std::vector<GlobalPoint> &globHit);
119 
120  void globalTrackPoint(TkFittedLasBeam &beam,
121  unsigned int &hit,
122  unsigned int &hitsAtTecPlus,
123  double &trackPhi,
124  double &trackPhiRef,
125  std::vector<GlobalPoint> &globHit,
126  std::vector<GlobalPoint> &globPtrack,
127  GlobalPoint &globPref,
128  std::vector<double> &hitPhiError);
129 
130  void buildTrajectory(TkFittedLasBeam &beam,
131  unsigned int &hit,
132  vector<const GeomDetUnit *> &gd,
133  std::vector<GlobalPoint> &globPtrack,
134  vector<TrajectoryStateOnSurface> &tsosLas,
135  GlobalPoint &globPref);
136 
137  bool fitBeam(TkFittedLasBeam &beam,
138  AlgebraicSymMatrix &covMatrix,
139  unsigned int &hitsAtTecPlus,
140  unsigned int &nFitParams,
141  double &offset,
142  double &slope,
143  vector<GlobalPoint> &globPtrack,
144  double &bsAngleParam,
145  double &chi2);
146 
147  // ----------member data ---------------------------
148 
149  // ES token
152 
153  // handles
157 
160  unsigned int nAtParameters_;
161 
163 
164  // static parameters used in static parametrization functions
165  static vector<double> gHitZprime;
166  static vector<double> gBarrelModuleRadius;
167  static vector<double> gBarrelModuleOffset;
168  static float gTIBparam;
169  static float gTOBparam;
170  static double gBeamR;
171  static double gBeamZ0;
172  static double gBeamSplitterZprime;
173  static unsigned int gHitsAtTecMinus;
174  static double gBSparam;
175  static bool gFitBeamSplitters;
176  static bool gIsInnerBarrel;
177 
178  // histograms
179  TH1F *h_bsAngle, *h_hitX, *h_hitXTecPlus, *h_hitXTecMinus, *h_hitXAt, *h_chi2, *h_chi2ndof, *h_pull, *h_res,
180  *h_resTecPlus, *h_resTecMinus, *h_resAt;
181  TH2F *h_bsAngleVsBeam, *h_hitXvsZTecPlus, *h_hitXvsZTecMinus, *h_hitXvsZAt, *h_resVsZTecPlus, *h_resVsZTecMinus,
182  *h_resVsZAt, *h_resVsHitTecPlus, *h_resVsHitTecMinus, *h_resVsHitAt;
183 };
184 
185 //
186 // constants, enums and typedefs
187 //
188 
189 //
190 // static data member definitions
191 //
192 
193 // static parameters used in parametrization functions
194 vector<double> TkLasBeamFitter::gHitZprime;
197 float TkLasBeamFitter::gTIBparam = 0.097614; // = abs(r_offset/r_module) (nominal!)
198 float TkLasBeamFitter::gTOBparam = 0.034949; // = abs(r_offset/r_module) (nominal!)
199 double TkLasBeamFitter::gBeamR = 0.0;
200 double TkLasBeamFitter::gBeamZ0 = 0.0;
202 unsigned int TkLasBeamFitter::gHitsAtTecMinus = 0;
203 double TkLasBeamFitter::gBSparam = 0.0;
206 
207 //
208 // constructors and destructor
209 //
211  : magFieldToken_(esConsumes<edm::Transition::EndRun>()),
212  geomToken_(esConsumes<edm::Transition::EndRun>()),
213  src_(iConfig.getParameter<edm::InputTag>("src")),
214  fitBeamSplitters_(iConfig.getParameter<bool>("fitBeamSplitters")),
215  nAtParameters_(iConfig.getParameter<unsigned int>("numberOfFittedAtParameters")),
216  h_bsAngle(nullptr),
217  h_hitX(nullptr),
218  h_hitXTecPlus(nullptr),
219  h_hitXTecMinus(nullptr),
220  h_hitXAt(nullptr),
221  h_chi2(nullptr),
222  h_chi2ndof(nullptr),
223  h_pull(nullptr),
224  h_res(nullptr),
225  h_resTecPlus(nullptr),
226  h_resTecMinus(nullptr),
227  h_resAt(nullptr),
228  h_bsAngleVsBeam(nullptr),
229  h_hitXvsZTecPlus(nullptr),
230  h_hitXvsZTecMinus(nullptr),
231  h_hitXvsZAt(nullptr),
232  h_resVsZTecPlus(nullptr),
233  h_resVsZTecMinus(nullptr),
234  h_resVsZAt(nullptr),
235  h_resVsHitTecPlus(nullptr),
236  h_resVsHitTecMinus(nullptr),
237  h_resVsHitAt(nullptr) {
238  // declare the products to produce
239  this->produces<TkFittedLasBeamCollection, edm::Transition::EndRun>();
240  this->produces<TsosVectorCollection, edm::Transition::EndRun>();
241 
242  //now do what ever other initialization is needed
243 }
244 
245 //---------------------------------------------------------------------------------------
247  // do anything here that needs to be done at desctruction time
248  // (e.g. close files, deallocate resources etc.)
249 }
250 
251 //
252 // member functions
253 //
254 
255 //---------------------------------------------------------------------------------------
256 // ------------ method called to produce the data ------------
258  // Nothing per event!
259 }
260 
261 //---------------------------------------------------------------------------------------
262 // ------------ method called at end of each run ---------------------------------------
264  // }
265  // // FIXME!
266  // // Indeed, that should be in endRun(..) - as soon as AlignmentProducer can call
267  // // the algorithm's endRun correctly!
268  //
269  //
270  // void TkLasBeamFitter::beginRun(edm::Run &run, const edm::EventSetup &setup)
271  // {
272 
273  // book histograms
274  h_hitX = fs->make<TH1F>("hitX", "local x of LAS hits;local x [cm];N", 100, -0.5, 0.5);
275  h_hitXTecPlus = fs->make<TH1F>("hitXTecPlus", "local x of LAS hits in TECplus;local x [cm];N", 100, -0.5, 0.5);
276  h_hitXTecMinus = fs->make<TH1F>("hitXTecMinus", "local x of LAS hits in TECminus;local x [cm];N", 100, -0.5, 0.5);
277  h_hitXAt = fs->make<TH1F>("hitXAt", "local x of LAS hits in ATs;local x [cm];N", 100, -2.5, 2.5);
279  fs->make<TH2F>("hitXvsZTecPlus", "local x vs z in TECplus;z [cm];local x [cm]", 80, 120, 280, 100, -0.5, 0.5);
281  fs->make<TH2F>("hitXvsZTecMinus", "local x vs z in TECMinus;z [cm];local x [cm]", 80, -280, -120, 100, -0.5, 0.5);
282  h_hitXvsZAt = fs->make<TH2F>("hitXvsZAt", "local x vs z in ATs;z [cm];local x [cm]", 200, -200, 200, 100, -0.5, 0.5);
283  h_chi2 = fs->make<TH1F>("chi2", "#chi^{2};#chi^{2};N", 100, 0, 2000);
284  h_chi2ndof = fs->make<TH1F>("chi2ndof", "#chi^{2} per degree of freedom;#chi^{2}/N_{dof};N", 100, 0, 300);
285  h_pull = fs->make<TH1F>("pull", "pulls of #phi residuals;pull;N", 50, -10, 10);
286  h_res = fs->make<TH1F>("res", "#phi residuals;#phi_{track} - #phi_{hit} [rad];N", 60, -0.0015, 0.0015);
287  h_resTecPlus =
288  fs->make<TH1F>("resTecPlus", "#phi residuals in TECplus;#phi_{track} - #phi_{hit} [rad];N", 30, -0.0015, 0.0015);
289  h_resTecMinus = fs->make<TH1F>(
290  "resTecMinus", "#phi residuals in TECminus;#phi_{track} - #phi_{hit} [rad];N", 60, -0.0015, 0.0015);
291  h_resAt = fs->make<TH1F>("resAt", "#phi residuals in ATs;#phi_{track} - #phi_{hit} [rad];N", 30, -0.0015, 0.0015);
292  h_resVsZTecPlus = fs->make<TH2F>("resVsZTecPlus",
293  "phi residuals vs. z in TECplus;z [cm];#phi_{track} - #phi_{hit} [rad]",
294  80,
295  120,
296  280,
297  100,
298  -0.0015,
299  0.0015);
300  h_resVsZTecMinus = fs->make<TH2F>("resVsZTecMinus",
301  "phi residuals vs. z in TECminus;z [cm];#phi_{track} - #phi_{hit} [rad]",
302  80,
303  -280,
304  -120,
305  100,
306  -0.0015,
307  0.0015);
308  h_resVsZAt = fs->make<TH2F>(
309  "resVsZAt", "#phi residuals vs. z in ATs;N;#phi_{track} - #phi_{hit} [rad]", 200, -200, 200, 100, -0.0015, 0.0015);
310  h_resVsHitTecPlus = fs->make<TH2F>("resVsHitTecPlus",
311  "#phi residuals vs. hits in TECplus;hit no.;#phi_{track} - #phi_{hit} [rad]",
312  144,
313  0,
314  144,
315  100,
316  -0.0015,
317  0.0015);
318  h_resVsHitTecMinus = fs->make<TH2F>("resVsHitTecMinus",
319  "#phi residuals vs. hits in TECminus;hit no.;#phi_{track} - #phi_{hit} [rad]",
320  144,
321  0,
322  144,
323  100,
324  -0.0015,
325  0.0015);
326  h_resVsHitAt = fs->make<TH2F>("resVsHitAt",
327  "#phi residuals vs. hits in ATs;hit no.;#phi_{track} - #phi_{hit} [rad]",
328  176,
329  0,
330  176,
331  100,
332  -0.0015,
333  0.0015);
334  h_bsAngle = fs->make<TH1F>("bsAngle", "fitted beam splitter angle;BS angle [rad];N", 40, -0.004, 0.004);
335  h_bsAngleVsBeam = fs->make<TH2F>(
336  "bsAngleVsBeam", "fitted beam splitter angle per beam;Beam no.;BS angle [rad]", 40, 0, 300, 100, -0.004, 0.004);
337 
338  // Create output collections - they are parallel.
339  // (edm::Ref etc. and thus edm::AssociationVector are not supported for edm::Run...)
340  auto fittedBeams = std::make_unique<TkFittedLasBeamCollection>();
341  // One std::vector<TSOS> for each TkFittedLasBeam:
342  auto tsosesVec = std::make_unique<TsosVectorCollection>();
343 
344  // get TkLasBeams, Tracker geometry, magnetic field
345  run.getByLabel("LaserAlignment", "tkLaserBeams", laserBeams);
346  geometry = setup.getHandle(geomToken_);
347  fieldHandle = setup.getHandle(magFieldToken_);
348 
349  // hack for fixed BSparams (ugly!)
350  // double bsParams[34] = {-0.000266,-0.000956,-0.001205,-0.000018,-0.000759,0.002554,
351  // 0.000465,0.000975,0.001006,0.002027,-0.001263,-0.000763,
352  // -0.001702,0.000906,-0.002120,0.001594,0.000661,-0.000457,
353  // -0.000447,0.000347,-0.002266,-0.000446,0.000659,0.000018,
354  // -0.001630,-0.000324,
355  // // ATs
356  // -999.,-0.001709,-0.002091,-999.,
357  // -0.001640,-999.,-0.002444,-0.002345};
358 
359  double bsParams[40] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
360  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
361 
362  // beam counter
363  unsigned int beamNo(0);
364  // fit BS? If false, values from bsParams are taken
366  if (fitBeamSplitters_)
367  cout << "Fitting BS!" << endl;
368  else
369  cout << "BS fixed, not fitted!" << endl;
370 
371  // loop over LAS beams
372  for (TkLasBeamCollection::const_iterator iBeam = laserBeams->begin(), iEnd = laserBeams->end(); iBeam != iEnd;
373  ++iBeam) {
374  TkFittedLasBeam beam(*iBeam);
375  vector<TrajectoryStateOnSurface> tsosLas;
376 
377  // set BS param for fit
378  gBSparam = bsParams[beamNo];
379 
380  // call main function; all other functions are called inside getLasBeams(..)
381  this->getLasBeams(beam, tsosLas);
382 
383  // fill output products
384  fittedBeams->push_back(beam);
385  tsosesVec->push_back(tsosLas);
386 
387  // if(!this->fitBeam(fittedBeams->back(), tsosesVec->back())){
388  // edm::LogError("BadFit")
389  // << "Problems fitting TkLasBeam, id " << fittedBeams->back().getBeamId() << ".";
390  // fittedBeams->pop_back(); // remove last entry added just before
391  // tsosesVec->pop_back(); // dito
392  // }
393 
394  beamNo++;
395  }
396 
397  // finally, put fitted beams and TSOS vectors into run
398  run.put(std::move(fittedBeams));
399  run.put(std::move(tsosesVec));
400 }
401 
402 // methods for las data processing
403 
404 // -------------- loop over beams, call functions ----------------------------
405 void TkLasBeamFitter::getLasBeams(TkFittedLasBeam &beam, vector<TrajectoryStateOnSurface> &tsosLas) {
406  cout << "---------------------------------------" << endl;
407  cout << "beam id: " << beam.getBeamId() // << " isTec: " << (beam.isTecInternal() ? "Y" : "N")
408  << " isTec+: " << (beam.isTecInternal(1) ? "Y" : "N") << " isTec-: " << (beam.isTecInternal(-1) ? "Y" : "N")
409  << " isAt: " << (beam.isAlignmentTube() ? "Y" : "N") << " isR6: " << (beam.isRing6() ? "Y" : "N") << endl;
410 
411  // reset static variables
412  gHitsAtTecMinus = 0;
413  gHitZprime.clear();
414  gBarrelModuleRadius.clear();
415  gBarrelModuleOffset.clear();
416 
417  // set right beam radius
418  gBeamR = beam.isRing6() ? 84.0 : 56.4;
419 
420  vector<const GeomDetUnit *> gd;
421  vector<GlobalPoint> globHit;
422  unsigned int hitsAtTecPlus(0);
423  double sumZ(0.);
424 
425  // loop over hits
426  for (TkLasBeam::const_iterator iHit = beam.begin(); iHit < beam.end(); ++iHit) {
427  // iHit is a SiStripLaserRecHit2D
428 
429  const SiStripLaserRecHit2D hit(*iHit);
430 
431  this->getLasHits(beam, hit, gd, globHit, hitsAtTecPlus);
432  sumZ += globHit.back().z();
433 
434  // fill histos
435  h_hitX->Fill(hit.localPosition().x());
436  // TECplus
437  if (beam.isTecInternal(1)) {
438  h_hitXTecPlus->Fill(hit.localPosition().x());
439  h_hitXvsZTecPlus->Fill(globHit.back().z(), hit.localPosition().x());
440  }
441  // TECminus
442  else if (beam.isTecInternal(-1)) {
443  h_hitXTecMinus->Fill(hit.localPosition().x());
444  h_hitXvsZTecMinus->Fill(globHit.back().z(), hit.localPosition().x());
445  }
446  // ATs
447  else {
448  h_hitXAt->Fill(hit.localPosition().x());
449  h_hitXvsZAt->Fill(globHit.back().z(), hit.localPosition().x());
450  }
451  }
452 
453  gBeamZ0 = sumZ / globHit.size();
454  double zMin(0.), zMax(0.);
455  // TECplus
456  if (beam.isTecInternal(1)) {
457  gBeamSplitterZprime = 205.75 - gBeamZ0;
458  zMin = 120.0 - gBeamZ0;
459  zMax = 280.0 - gBeamZ0;
460  }
461  // TECminus
462  else if (beam.isTecInternal(-1)) {
463  gBeamSplitterZprime = -205.75 - gBeamZ0;
464  zMin = -280.0 - gBeamZ0;
465  zMax = -120.0 - gBeamZ0;
466  }
467  // AT
468  else {
469  gBeamSplitterZprime = 112.3 - gBeamZ0;
470  zMin = -200.0 - gBeamZ0;
471  zMax = 200.0 - gBeamZ0;
472  }
473 
474  // fill vectors for fitted quantities
475  vector<double> hitPhi, hitPhiError, hitZprimeError;
476 
477  for (unsigned int hit = 0; hit < globHit.size(); ++hit) {
478  hitPhi.push_back(static_cast<double>(globHit[hit].phi()));
479  // localPositionError[hit] or assume 0.003, 0.006
480  hitPhiError.push_back(0.003 / globHit[hit].perp());
481  // no errors on z, fill with zeros
482  hitZprimeError.push_back(0.0);
483  // barrel-specific values
484  if (beam.isAlignmentTube() && abs(globHit[hit].z()) < 112.3) {
485  gBarrelModuleRadius.push_back(globHit[hit].perp());
486  gBarrelModuleOffset.push_back(gBarrelModuleRadius.back() - gBeamR);
487  // TIB/TOB flag
488  if (gBarrelModuleOffset.back() < 0.0) {
489  gIsInnerBarrel = true;
490  } else {
491  gIsInnerBarrel = false;
492  }
493  gHitZprime.push_back(globHit[hit].z() - gBeamZ0 - abs(gBarrelModuleOffset.back()));
494  }
495  // non-barrel z'
496  else {
497  gHitZprime.push_back(globHit[hit].z() - gBeamZ0);
498  }
499  }
500 
501  // number of fit parameters, 3 for TECs (always!); 3, 5, or 6 for ATs
502  unsigned int tecParams(3), atParams(0);
503  if (nAtParameters_ == 3)
504  atParams = 3;
505  else if (nAtParameters_ == 5)
506  atParams = 5;
507  else
508  atParams = 6; // <-- default value, recommended
509  unsigned int nFitParams(0);
510  if (!fitBeamSplitters_ || (hitsAtTecPlus == 0 && beam.isAlignmentTube())) {
511  tecParams = tecParams - 1;
512  atParams = atParams - 1;
513  }
514  if (beam.isTecInternal()) {
515  nFitParams = tecParams;
516  } else {
517  nFitParams = atParams;
518  }
519 
520  // fit parameter definitions
521  double offset(0.), offsetError(0.), slope(0.), slopeError(0.), bsAngleParam(0.), phiAtMinusParam(0.),
522  phiAtPlusParam(0.), atThetaSplitParam(0.);
523  AlgebraicSymMatrix covMatrix;
524  if (!fitBeamSplitters_ || (beam.isAlignmentTube() && hitsAtTecPlus == 0)) {
525  covMatrix = AlgebraicSymMatrix(nFitParams, 1);
526  } else {
527  covMatrix = AlgebraicSymMatrix(nFitParams - 1, 1);
528  }
529 
530  this->fitter(beam,
531  covMatrix,
532  hitsAtTecPlus,
533  nFitParams,
534  hitPhi,
535  hitPhiError,
536  hitZprimeError,
537  zMin,
538  zMax,
539  bsAngleParam,
540  offset,
541  offsetError,
542  slope,
543  slopeError,
544  phiAtMinusParam,
545  phiAtPlusParam,
546  atThetaSplitParam);
547 
548  vector<GlobalPoint> globPtrack;
549  GlobalPoint globPref;
550  double chi2(0.);
551 
552  for (unsigned int hit = 0; hit < gHitZprime.size(); ++hit) {
553  // additional phi value (trackPhiRef) for trajectory calculation
554  double trackPhi(0.), trackPhiRef(0.);
555 
556  this->trackPhi(beam,
557  hit,
558  trackPhi,
559  trackPhiRef,
560  offset,
561  slope,
562  bsAngleParam,
563  phiAtMinusParam,
564  phiAtPlusParam,
565  atThetaSplitParam,
566  globHit);
567 
568  cout << "track phi = " << trackPhi << ", hit phi = " << hitPhi[hit] << ", zPrime = " << gHitZprime[hit]
569  << " r = " << globHit[hit].perp() << endl;
570 
571  this->globalTrackPoint(beam, hit, hitsAtTecPlus, trackPhi, trackPhiRef, globHit, globPtrack, globPref, hitPhiError);
572 
573  // calculate residuals = pred - hit (in global phi)
574  const double phiResidual = globPtrack[hit].phi() - globHit[hit].phi();
575  // pull calculation (FIX!!!)
576  const double phiResidualPull = phiResidual / hitPhiError[hit];
577  // sqrt(hitPhiError[hit]*hitPhiError[hit] +
578  // (offsetError*offsetError + globPtrack[hit].z()*globPtrack[hit].z() * slopeError*slopeError));
579 
580  // calculate chi2
581  chi2 += phiResidual * phiResidual / (hitPhiError[hit] * hitPhiError[hit]);
582 
583  // fill histos
584  h_res->Fill(phiResidual);
585  // TECplus
586  if (beam.isTecInternal(1)) {
587  h_pull->Fill(phiResidualPull);
588  h_resTecPlus->Fill(phiResidual);
589  h_resVsZTecPlus->Fill(globPtrack[hit].z(), phiResidual);
590  // Ring 6
591  if (beam.isRing6()) {
592  h_resVsHitTecPlus->Fill(hit + (beam.getBeamId() - 1) / 10 * 9 + 72, phiResidual);
593  }
594  // Ring 4
595  else {
596  h_resVsHitTecPlus->Fill(hit + beam.getBeamId() / 10 * 9, phiResidual);
597  }
598  }
599  // TECminus
600  else if (beam.isTecInternal(-1)) {
601  h_pull->Fill(phiResidualPull);
602  h_resTecMinus->Fill(phiResidual);
603  h_resVsZTecMinus->Fill(globPtrack[hit].z(), phiResidual);
604  // Ring 6
605  if (beam.isRing6()) {
606  h_resVsHitTecMinus->Fill(hit + (beam.getBeamId() - 101) / 10 * 9 + 72, phiResidual);
607  }
608  // Ring 4
609  else {
610  h_resVsHitTecMinus->Fill(hit + (beam.getBeamId() - 100) / 10 * 9, phiResidual);
611  }
612  }
613  // ATs
614  else {
615  h_pull->Fill(phiResidualPull);
616  h_resAt->Fill(phiResidual);
617  h_resVsZAt->Fill(globPtrack[hit].z(), phiResidual);
618  h_resVsHitAt->Fill(hit + (beam.getBeamId() - 200) / 10 * 22, phiResidual);
619  }
620 
621  this->buildTrajectory(beam, hit, gd, globPtrack, tsosLas, globPref);
622  }
623 
624  cout << "chi^2 = " << chi2 << ", chi^2/ndof = " << chi2 / (gHitZprime.size() - nFitParams) << endl;
625  this->fitBeam(beam, covMatrix, hitsAtTecPlus, nFitParams, offset, slope, globPtrack, bsAngleParam, chi2);
626 
627  cout << "bsAngleParam = " << bsAngleParam << endl;
628 
629  // fill histos
630  // include slope, offset, covariance plots here
631  h_chi2->Fill(chi2);
632  h_chi2ndof->Fill(chi2 / (gHitZprime.size() - nFitParams));
633  if (bsAngleParam != 0.0) {
634  h_bsAngle->Fill(2.0 * atan(0.5 * bsAngleParam));
635  h_bsAngleVsBeam->Fill(beam.getBeamId(), 2.0 * atan(0.5 * bsAngleParam));
636  }
637 }
638 
639 // --------- get hits, convert to global coordinates ---------------------------
641  const SiStripLaserRecHit2D &hit,
642  vector<const GeomDetUnit *> &gd,
643  vector<GlobalPoint> &globHit,
644  unsigned int &hitsAtTecPlus) {
645  // get global position of LAS hits
646  gd.push_back(geometry->idToDetUnit(hit.getDetId()));
647  GlobalPoint globPtemp(gd.back()->toGlobal(hit.localPosition()));
648 
649  // testing: globPtemp should be right
650  globHit.push_back(globPtemp);
651 
652  if (beam.isAlignmentTube()) {
653  if (abs(globPtemp.z()) > 112.3) {
654  if (globPtemp.z() < 112.3)
655  gHitsAtTecMinus++;
656  else
657  hitsAtTecPlus++;
658  }
659  }
660 }
661 
662 // ------------ parametrization functions for las beam fits ------------
663 double TkLasBeamFitter::tecPlusFunction(double *x, double *par) {
664  double z = x[0]; // 'primed'? -> yes!!!
665 
666  if (z < gBeamSplitterZprime) {
667  return par[0] + par[1] * z;
668  } else {
669  if (gFitBeamSplitters) {
670  // par[2] = 2*tan(BeamSplitterAngle/2.0)
671  return par[0] + par[1] * z - par[2] * (z - gBeamSplitterZprime) / gBeamR;
672  } else {
673  return par[0] + par[1] * z - gBSparam * (z - gBeamSplitterZprime) / gBeamR;
674  }
675  }
676 }
677 
678 double TkLasBeamFitter::tecMinusFunction(double *x, double *par) {
679  double z = x[0]; // 'primed'? -> yes!!!
680 
681  if (z > gBeamSplitterZprime) {
682  return par[0] + par[1] * z;
683  } else {
684  if (gFitBeamSplitters) {
685  // par[2] = 2*tan(BeamSplitterAngle/2.0)
686  return par[0] + par[1] * z + par[2] * (z - gBeamSplitterZprime) / gBeamR;
687  } else {
688  return par[0] + par[1] * z + gBSparam * (z - gBeamSplitterZprime) / gBeamR;
689  }
690  }
691 }
692 
693 double TkLasBeamFitter::atFunction(double *x, double *par) {
694  double z = x[0]; // 'primed'? -> yes!!!
695  // TECminus
696  if (z < -gBeamSplitterZprime - 2.0 * gBeamZ0) {
697  return par[0] + par[1] * z;
698  }
699  // BarrelMinus
700  else if (-gBeamSplitterZprime - 2.0 * gBeamZ0 < z && z < -gBeamZ0) {
701  // z value includes module offset from main beam axis
702  // TOB
703  if (!gIsInnerBarrel) {
704  return par[0] + par[1] * z + gTOBparam * (par[2] + par[4]);
705  }
706  // TIB
707  else {
708  return par[0] + par[1] * z - gTIBparam * (par[2] - par[4]);
709  }
710  }
711  // BarrelPlus
712  else if (-gBeamZ0 < z && z < gBeamSplitterZprime) {
713  // z value includes module offset from main beam axis
714  // TOB
715  if (!gIsInnerBarrel) {
716  return par[0] + par[1] * z + gTOBparam * (par[3] - par[4]);
717  }
718  // TIB
719  else {
720  return par[0] + par[1] * z - gTIBparam * (par[3] + par[4]);
721  }
722  }
723  // TECplus
724  else {
725  if (gFitBeamSplitters) {
726  // par[2] = 2*tan(BeamSplitterAngle/2.0)
727  return par[0] + par[1] * z - par[5] * (z - gBeamSplitterZprime) / gBeamR; // BS par: 5, 4, or 2
728  } else {
729  return par[0] + par[1] * z - gBSparam * (z - gBeamSplitterZprime) / gBeamR;
730  }
731  }
732 }
733 
734 // ------------ perform fit of beams ------------------------------------
736  AlgebraicSymMatrix &covMatrix,
737  unsigned int &hitsAtTecPlus,
738  unsigned int &nFitParams,
739  vector<double> &hitPhi,
740  vector<double> &hitPhiError,
741  vector<double> &hitZprimeError,
742  double &zMin,
743  double &zMax,
744  double &bsAngleParam,
745  double &offset,
746  double &offsetError,
747  double &slope,
748  double &slopeError,
749  double &phiAtMinusParam,
750  double &phiAtPlusParam,
751  double &atThetaSplitParam) {
752  TGraphErrors *lasData =
753  new TGraphErrors(gHitZprime.size(), &(gHitZprime[0]), &(hitPhi[0]), &(hitZprimeError[0]), &(hitPhiError[0]));
754 
755  // do fit (R = entire range)
756  if (beam.isTecInternal(1)) {
757  TF1 tecPlus("tecPlus", tecPlusFunction, zMin, zMax, nFitParams);
758  tecPlus.SetParameter(1, 0); // slope
759  tecPlus.SetParameter(nFitParams - 1, 0); // BS
760  lasData->Fit(&tecPlus, "R"); // "R", "RV" or "RQ"
761  } else if (beam.isTecInternal(-1)) {
762  TF1 tecMinus("tecMinus", tecMinusFunction, zMin, zMax, nFitParams);
763  tecMinus.SetParameter(1, 0); // slope
764  tecMinus.SetParameter(nFitParams - 1, 0); // BS
765  lasData->Fit(&tecMinus, "R");
766  } else {
767  TF1 at("at", atFunction, zMin, zMax, nFitParams);
768  at.SetParameter(1, 0); // slope
769  at.SetParameter(nFitParams - 1, 0); // BS
770  lasData->Fit(&at, "R");
771  }
772 
773  // get values and errors for offset and slope
774  gMinuit->GetParameter(0, offset, offsetError);
775  gMinuit->GetParameter(1, slope, slopeError);
776 
777  // additional AT parameters
778  // define param errors that are not used later
779  double bsAngleParamError(0.), phiAtMinusParamError(0.), phiAtPlusParamError(0.), atThetaSplitParamError(0.);
780 
781  if (beam.isAlignmentTube()) {
782  gMinuit->GetParameter(2, phiAtMinusParam, phiAtMinusParamError);
783  gMinuit->GetParameter(3, phiAtPlusParam, phiAtPlusParamError);
784  gMinuit->GetParameter(4, atThetaSplitParam, atThetaSplitParamError);
785  }
786  // get Beam Splitter parameters
787  if (fitBeamSplitters_) {
788  if (beam.isAlignmentTube() && hitsAtTecPlus == 0) {
789  bsAngleParam = gBSparam;
790  } else {
791  gMinuit->GetParameter(nFitParams - 1, bsAngleParam, bsAngleParamError);
792  }
793  } else {
794  bsAngleParam = gBSparam;
795  }
796 
797  // fill covariance matrix
798  vector<double> vec(covMatrix.num_col() * covMatrix.num_col());
799  gMinuit->mnemat(&vec[0], covMatrix.num_col());
800  for (int col = 0; col < covMatrix.num_col(); col++) {
801  for (int row = 0; row < covMatrix.num_col(); row++) {
802  covMatrix[col][row] = vec[row + covMatrix.num_col() * col];
803  }
804  }
805  // compute correlation between parameters
806  // double corr01 = covMatrix[1][0]/(offsetError*slopeError);
807 
808  delete lasData;
809 }
810 
811 // -------------- calculate track phi value ----------------------------------
813  unsigned int &hit,
814  double &trackPhi,
815  double &trackPhiRef,
816  double &offset,
817  double &slope,
818  double &bsAngleParam,
819  double &phiAtMinusParam,
820  double &phiAtPlusParam,
821  double &atThetaSplitParam,
822  vector<GlobalPoint> &globHit) {
823  // TECplus
824  if (beam.isTecInternal(1)) {
827  trackPhiRef = offset + slope * (gHitZprime[hit] + 1.0);
828  } else {
829  trackPhi = offset + slope * gHitZprime[hit] - bsAngleParam * (gHitZprime[hit] - gBeamSplitterZprime) / gBeamR;
830  trackPhiRef = offset + slope * (gHitZprime[hit] + 1.0) -
831  bsAngleParam * ((gHitZprime[hit] + 1.0) - gBeamSplitterZprime) / gBeamR;
832  }
833  }
834  // TECminus
835  else if (beam.isTecInternal(-1)) {
838  trackPhiRef = offset + slope * (gHitZprime[hit] + 1.0);
839  } else {
840  trackPhi = offset + slope * gHitZprime[hit] + bsAngleParam * (gHitZprime[hit] - gBeamSplitterZprime) / gBeamR;
841  trackPhiRef = offset + slope * (gHitZprime[hit] + 1.0) +
842  bsAngleParam * ((gHitZprime[hit] + 1.0) - gBeamSplitterZprime) / gBeamR;
843  }
844  }
845  // ATs
846  else {
847  // TECminus
848  if (gHitZprime[hit] < -gBeamSplitterZprime - 2.0 * gBeamZ0) {
850  trackPhiRef = offset + slope * (gHitZprime[hit] + 1.0);
851  }
852  // BarrelMinus
853  else if (-gBeamSplitterZprime - 2.0 * gBeamZ0 < gHitZprime[hit] && gHitZprime[hit] < -gBeamZ0) {
854  if (!gIsInnerBarrel) {
855  trackPhi = offset + slope * gHitZprime[hit] + gTOBparam * (phiAtMinusParam + atThetaSplitParam);
856  } else {
857  trackPhi = offset + slope * gHitZprime[hit] - gTIBparam * (phiAtMinusParam - atThetaSplitParam);
858  }
860  }
861  // BarrelPlus
863  if (!gIsInnerBarrel) {
864  trackPhi = offset + slope * gHitZprime[hit] + gTOBparam * (phiAtPlusParam - atThetaSplitParam);
865  } else {
866  trackPhi = offset + slope * gHitZprime[hit] - gTIBparam * (phiAtPlusParam + atThetaSplitParam);
867  }
869  }
870  // TECplus
871  else {
872  trackPhi = offset + slope * gHitZprime[hit] - bsAngleParam * (gHitZprime[hit] - gBeamSplitterZprime) / gBeamR;
873  trackPhiRef = offset + slope * (gHitZprime[hit] + 1.0) -
874  bsAngleParam * ((gHitZprime[hit] + 1.0) - gBeamSplitterZprime) / gBeamR;
875  }
876  }
877 }
878 
879 // -------------- calculate global track points, hit residuals, chi2 ----------------------------------
881  unsigned int &hit,
882  unsigned int &hitsAtTecPlus,
883  double &trackPhi,
884  double &trackPhiRef,
885  vector<GlobalPoint> &globHit,
886  vector<GlobalPoint> &globPtrack,
887  GlobalPoint &globPref,
888  vector<double> &hitPhiError) {
889  // TECs
890  if (beam.isTecInternal(0)) {
891  globPtrack.push_back(GlobalPoint(GlobalPoint::Cylindrical(gBeamR, trackPhi, globHit[hit].z())));
892  globPref = GlobalPoint(GlobalPoint::Cylindrical(gBeamR, trackPhiRef, globHit[hit].z() + 1.0));
893  }
894  // ATs
895  else {
896  // TECminus
897  if (hit < gHitsAtTecMinus) { // gHitZprime[hit] < -gBeamSplitterZprime - 2.0*gBeamZ0
898  globPtrack.push_back(GlobalPoint(GlobalPoint::Cylindrical(gBeamR, trackPhi, globHit[hit].z())));
899  globPref = GlobalPoint(GlobalPoint::Cylindrical(gBeamR, trackPhiRef, globHit[hit].z() + 1.0));
900  }
901  // TECplus
902  else if (hit > gHitZprime.size() - hitsAtTecPlus - 1) { // gHitZprime[hit] > gBeamSplitterZprime
903  globPtrack.push_back(GlobalPoint(GlobalPoint::Cylindrical(gBeamR, trackPhi, globHit[hit].z())));
904  globPref = GlobalPoint(GlobalPoint::Cylindrical(gBeamR, trackPhiRef, globHit[hit].z() + 1.0));
905  }
906  // Barrel
907  else {
908  globPtrack.push_back(GlobalPoint(GlobalPoint::Cylindrical(globHit[hit].perp(), trackPhi, globHit[hit].z())));
909  globPref = GlobalPoint(GlobalPoint::Cylindrical(gBeamR, trackPhiRef, globHit[hit].z()));
910  }
911  }
912 }
913 
914 // ----------- create TrajectoryStateOnSurface for each track hit ----------------------------------------------
916  unsigned int &hit,
917  vector<const GeomDetUnit *> &gd,
918  vector<GlobalPoint> &globPtrack,
919  vector<TrajectoryStateOnSurface> &tsosLas,
920  GlobalPoint &globPref) {
922  GlobalVector trajectoryState;
923 
924  // TECplus
925  if (beam.isTecInternal(1)) {
926  trajectoryState = GlobalVector(globPref - globPtrack[hit]);
927  }
928  // TECminus
929  else if (beam.isTecInternal(-1)) {
930  trajectoryState = GlobalVector(globPtrack[hit] - globPref);
931  }
932  // ATs
933  else {
934  // TECminus
935  if (gHitZprime[hit] < -gBeamSplitterZprime - 2.0 * gBeamZ0) {
936  trajectoryState = GlobalVector(globPtrack[hit] - globPref);
937  }
938  // TECplus
939  else if (gHitZprime[hit] > gBeamSplitterZprime) {
940  trajectoryState = GlobalVector(globPref - globPtrack[hit]);
941  }
942  // Barrel
943  else {
944  trajectoryState = GlobalVector(globPtrack[hit] - globPref);
945  }
946  }
947  // cout << "trajectory: " << trajectoryState << endl;
948  const FreeTrajectoryState ftsLas = FreeTrajectoryState(globPtrack[hit], trajectoryState, 0, magneticField);
949  tsosLas.push_back(TrajectoryStateOnSurface(ftsLas, gd[hit]->surface(), SurfaceSideDefinition::beforeSurface));
950 }
951 
952 //---------------------- set beam parameters for fittedBeams ---------------------------------
954  AlgebraicSymMatrix &covMatrix,
955  unsigned int &hitsAtTecPlus,
956  unsigned int &nFitParams,
957  double &offset,
958  double &slope,
959  vector<GlobalPoint> &globPtrack,
960  double &bsAngleParam,
961  double &chi2) {
962  // set beam parameters for beam output
963  unsigned int paramType(0);
964  if (!fitBeamSplitters_)
965  paramType = 1;
966  if (beam.isAlignmentTube() && hitsAtTecPlus == 0)
967  paramType = 0;
968  // const unsigned int nPedeParams = nFitParams + paramType;
969 
970  // test without BS params
971  const unsigned int nPedeParams(nFitParams);
972  // cout << "number of Pede parameters: " << nPedeParams << endl;
973 
974  std::vector<TkFittedLasBeam::Scalar> params(nPedeParams);
975  params[0] = offset;
976  params[1] = slope;
977  // no BS parameter for AT beams without TECplus hits
978  // if(beam.isTecInternal() || hitsAtTecPlus > 0) params[2] = bsAngleParam;
979 
980  AlgebraicMatrix derivatives(gHitZprime.size(), nPedeParams);
981  // fill derivatives matrix with local track derivatives
982  for (unsigned int hit = 0; hit < gHitZprime.size(); ++hit) {
983  // d(delta phi)/d(offset) is identical for every hit
984  derivatives[hit][0] = 1.0;
985 
986  // d(delta phi)/d(slope) and d(delta phi)/d(bsAngleParam) depend on parametrizations
987  // TECplus
988  if (beam.isTecInternal(1)) {
989  derivatives[hit][1] = globPtrack[hit].z();
990  // if(gHitZprime[hit] < gBeamSplitterZprime){
991  // derivatives[hit][2] = 0.0;
992  // }
993  // else{
994  // derivatives[hit][2] = - (globPtrack[hit].z() - gBeamSplitterZprime) / gBeamR;
995  // }
996  }
997  // TECminus
998  else if (beam.isTecInternal(-1)) {
999  derivatives[hit][1] = globPtrack[hit].z();
1000  // if(gHitZprime[hit] > gBeamSplitterZprime){
1001  // derivatives[hit][2] = 0.0;
1002  // }
1003  // else{
1004  // derivatives[hit][2] = (globPtrack[hit].z() - gBeamSplitterZprime) / gBeamR;
1005  // }
1006  }
1007  // ATs
1008  else {
1009  // TECminus
1010  if (gHitZprime[hit] < -gBeamSplitterZprime - 2.0 * gBeamZ0) {
1011  derivatives[hit][1] = globPtrack[hit].z();
1012  // if(hitsAtTecPlus > 0){
1013  // derivatives[hit][2] = 0.0;
1014  // }
1015  }
1016  // TECplus
1017  else if (gHitZprime[hit] > gBeamSplitterZprime) {
1018  derivatives[hit][1] = globPtrack[hit].z();
1019  // if(hitsAtTecPlus > 0){
1020  // derivatives[hit][2] = - (globPtrack[hit].z() - gBeamSplitterZprime) / gBeamR;
1021  // }
1022  }
1023  // Barrel
1024  else {
1025  derivatives[hit][1] = globPtrack[hit].z() - gBarrelModuleOffset[hit - gHitsAtTecMinus];
1026  // if(hitsAtTecPlus > 0){
1027  // derivatives[hit][2] = 0.0;
1028  // }
1029  }
1030  }
1031  }
1032 
1033  unsigned int firstFixedParam(covMatrix.num_col()); // FIXME! --> no, is fine!!!
1034  // unsigned int firstFixedParam = nPedeParams - 1;
1035  // if(beam.isAlignmentTube() && hitsAtTecPlus == 0) firstFixedParam = nPedeParams;
1036  // cout << "first fixed parameter: " << firstFixedParam << endl;
1037  // set fit results
1038  beam.setParameters(paramType, params, covMatrix, derivatives, firstFixedParam, chi2);
1039 
1040  return true; // return false in case of problems
1041 }
1042 
1043 //---------------------------------------------------------------------------------------
1044 //define this as a plug-in
static vector< double > gHitZprime
static float gTOBparam
~TkLasBeamFitter() override
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
static double gBeamR
static double tecMinusFunction(double *x, double *par)
static double tecPlusFunction(double *x, double *par)
T z() const
Definition: PV3DBase.h:61
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
TkLasBeamFitter(const edm::ParameterSet &config)
static const double slope[3]
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
static vector< double > gBarrelModuleRadius
Definition: config.py:1
bool fitBeam(TkFittedLasBeam &beam, AlgebraicSymMatrix &covMatrix, unsigned int &hitsAtTecPlus, unsigned int &nFitParams, double &offset, double &slope, vector< GlobalPoint > &globPtrack, double &bsAngleParam, double &chi2)
static bool gFitBeamSplitters
void getLasHits(TkFittedLasBeam &beam, const SiStripLaserRecHit2D &hit, vector< const GeomDetUnit *> &gd, vector< GlobalPoint > &globHit, unsigned int &hitsAtTecPlus)
edm::ESHandle< MagneticField > fieldHandle
static bool gIsInnerBarrel
int iEvent
Definition: GenABIO.cc:224
T const * product() const
Definition: ESHandle.h:86
void buildTrajectory(TkFittedLasBeam &beam, unsigned int &hit, vector< const GeomDetUnit *> &gd, std::vector< GlobalPoint > &globPtrack, vector< TrajectoryStateOnSurface > &tsosLas, GlobalPoint &globPref)
void endRunProduce(edm::Run &run, const edm::EventSetup &setup) override
unsigned int nAtParameters_
CLHEP::HepMatrix AlgebraicMatrix
void globalTrackPoint(TkFittedLasBeam &beam, unsigned int &hit, unsigned int &hitsAtTecPlus, double &trackPhi, double &trackPhiRef, std::vector< GlobalPoint > &globHit, std::vector< GlobalPoint > &globPtrack, GlobalPoint &globPref, std::vector< double > &hitPhiError)
static double gBeamSplitterZprime
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
Transition
Definition: Transition.h:12
void produce(edm::Event &event, const edm::EventSetup &setup) override
edm::Handle< TkLasBeamCollection > laserBeams
T perp() const
Magnitude of transverse component.
static unsigned int gHitsAtTecMinus
void fitter(TkFittedLasBeam &beam, AlgebraicSymMatrix &covMatrix, unsigned int &hitsAtTecPlus, unsigned int &nFitParams, std::vector< double > &hitPhi, std::vector< double > &hitPhiError, std::vector< double > &hitZprimeError, double &zMin, double &zMax, double &bsAngleParam, double &offset, double &offsetError, double &slope, double &slopeError, double &phiAtMinusParam, double &phiAtPlusParam, double &atThetaSplitParam)
const edm::ESGetToken< TrackerGeometry, TrackerDigiGeometryRecord > geomToken_
const edm::InputTag src_
static double gBSparam
const edm::ESGetToken< MagneticField, IdealMagneticFieldRecord > magFieldToken_
static vector< double > gBarrelModuleOffset
HLT enums.
void trackPhi(TkFittedLasBeam &beam, unsigned int &hit, double &trackPhi, double &trackPhiRef, double &offset, double &slope, double &bsAngleParam, double &phiAtMinusParam, double &phiAtPlusParam, double &atThetaSplitParam, std::vector< GlobalPoint > &globHit)
col
Definition: cuy.py:1009
CLHEP::HepSymMatrix AlgebraicSymMatrix
float x
T * make(const Args &...args) const
make new ROOT object
Definition: TFileService.h:64
static float gTIBparam
static double atFunction(double *x, double *par)
void getLasBeams(TkFittedLasBeam &beam, vector< TrajectoryStateOnSurface > &tsosLas)
edm::Service< TFileService > fs
std::vector< SiStripLaserRecHit2D >::const_iterator const_iterator
Definition: TkLasBeam.h:14
edm::ESHandle< TrackerGeometry > geometry
def move(src, dest)
Definition: eostools.py:511
Definition: event.py:1
Definition: Run.h:45
Global3DVector GlobalVector
Definition: GlobalVector.h:10
static double gBeamZ0