CMS 3D CMS Logo

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