00001
00016
00017 #include <memory>
00018
00019
00020 #include "FWCore/Framework/interface/Frameworkfwd.h"
00021 #include "FWCore/Framework/interface/EDProducer.h"
00022 #include "FWCore/Framework/interface/ESHandle.h"
00023 #include "FWCore/Framework/interface/Event.h"
00024 #include "FWCore/Framework/interface/EventSetup.h"
00025 #include "FWCore/Framework/interface/MakerMacros.h"
00026 #include "FWCore/Framework/interface/Run.h"
00027 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00028 #include "FWCore/Utilities/interface/InputTag.h"
00029 #include "FWCore/ServiceRegistry/interface/Service.h"
00030 #include "CommonTools/UtilAlgos/interface/TFileService.h"
00031
00032 #include <Geometry/CommonDetUnit/interface/GeomDetUnit.h>
00033 #include <Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h>
00034 #include <Geometry/Records/interface/TrackerDigiGeometryRecord.h>
00035 #include <MagneticField/Engine/interface/MagneticField.h>
00036 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
00037
00038
00039
00040 #include "DataFormats/Provenance/interface/BranchType.h"
00041
00042
00043 #include "DataFormats/Alignment/interface/TkLasBeam.h"
00044 #include "DataFormats/Alignment/interface/TkFittedLasBeam.h"
00045
00046
00047 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h"
00048 #include "Alignment/LaserAlignment/interface/TsosVectorCollection.h"
00049 #include "TrackingTools/TrajectoryState/interface/FreeTrajectoryState.h"
00050 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
00051
00052 #include <iostream>
00053 #include "TMinuit.h"
00054 #include "TGraphErrors.h"
00055 #include "TF1.h"
00056 #include "TH1.h"
00057 #include "TH2.h"
00058
00059 using namespace edm;
00060 using namespace std;
00061
00062
00063
00064
00065
00066
00067 class TkLasBeamFitter : public edm::EDProducer {
00068 public:
00069 explicit TkLasBeamFitter(const edm::ParameterSet &config);
00070 ~TkLasBeamFitter();
00071
00072
00073 virtual void produce(edm::Event &event, const edm::EventSetup &setup);
00074
00075 virtual void endRun(edm::Run &run, const edm::EventSetup &setup);
00076
00077
00078 private:
00081 void getLasBeams(TkFittedLasBeam &beam,vector<TrajectoryStateOnSurface> &tsosLas);
00082 void getLasHits(TkFittedLasBeam &beam, const SiStripLaserRecHit2D &hit,
00083 vector<const GeomDetUnit*> &gd, vector<GlobalPoint> &globHit,
00084 unsigned int &hitsAtTecPlus);
00085
00086
00087
00088
00089 static double tecPlusFunction(double *x, double *par);
00090 static double tecMinusFunction(double *x, double *par);
00091 static double atFunction(double *x, double *par);
00092
00093 void fitter(TkFittedLasBeam &beam, AlgebraicSymMatrix &covMatrix,
00094 unsigned int &hitsAtTecPlus, unsigned int &nFitParams,
00095 std::vector<double> &hitPhi, std::vector<double> &hitPhiError, std::vector<double> &hitZprimeError,
00096 double &zMin, double &zMax, double &bsAngleParam,
00097 double &offset, double &offsetError, double &slope, double &slopeError,
00098 double &phiAtMinusParam, double &phiAtPlusParam,
00099 double &atThetaSplitParam);
00100
00101 void trackPhi(TkFittedLasBeam &beam, unsigned int &hit,
00102 double &trackPhi, double &trackPhiRef,
00103 double &offset, double &slope, double &bsAngleParam,
00104 double &phiAtMinusParam, double &phiAtPlusParam,
00105 double &atThetaSplitParam, std::vector<GlobalPoint> &globHit);
00106
00107 void globalTrackPoint(TkFittedLasBeam &beam,
00108 unsigned int &hit, unsigned int &hitsAtTecPlus,
00109 double &trackPhi, double &trackPhiRef,
00110 std::vector<GlobalPoint> &globHit, std::vector<GlobalPoint> &globPtrack,
00111 GlobalPoint &globPref, std::vector<double> &hitPhiError);
00112
00113 void buildTrajectory(TkFittedLasBeam &beam, unsigned int &hit,
00114 vector<const GeomDetUnit*> &gd, std::vector<GlobalPoint> &globPtrack,
00115 vector<TrajectoryStateOnSurface> &tsosLas, GlobalPoint &globPref);
00116
00117 bool fitBeam(TkFittedLasBeam &beam, AlgebraicSymMatrix &covMatrix,
00118 unsigned int &hitsAtTecPlus, unsigned int &nFitParams,
00119 double &offset, double &slope, vector<GlobalPoint> &globPtrack,
00120 double &bsAngleParam, double &chi2);
00121
00122
00123 const edm::InputTag src_;
00124 bool fitBeamSplitters_;
00125 unsigned int nAtParameters_;
00126
00127 edm::Service<TFileService> fs;
00128
00129
00130 static vector<double> gHitZprime;
00131 static vector<double> gBarrelModuleRadius;
00132 static vector<double> gBarrelModuleOffset;
00133 static float gTIBparam;
00134 static float gTOBparam;
00135 static double gBeamR;
00136 static double gBeamZ0;
00137 static double gBeamSplitterZprime;
00138 static unsigned int gHitsAtTecMinus;
00139 static double gBSparam;
00140 static bool gFitBeamSplitters;
00141 static bool gIsInnerBarrel;
00142
00143
00144 TH1F *h_bsAngle, *h_hitX, *h_hitXTecPlus, *h_hitXTecMinus,
00145 *h_hitXAt, *h_chi2, *h_chi2ndof, *h_pull, *h_res,
00146 *h_resTecPlus, *h_resTecMinus, *h_resAt;
00147 TH2F *h_bsAngleVsBeam, *h_hitXvsZTecPlus, *h_hitXvsZTecMinus,
00148 *h_hitXvsZAt, *h_resVsZTecPlus, *h_resVsZTecMinus, *h_resVsZAt,
00149 *h_resVsHitTecPlus, *h_resVsHitTecMinus, *h_resVsHitAt;
00150 };
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 vector<double> TkLasBeamFitter::gHitZprime;
00163 vector<double> TkLasBeamFitter::gBarrelModuleRadius;
00164 vector<double> TkLasBeamFitter::gBarrelModuleOffset;
00165 float TkLasBeamFitter::gTIBparam = 0.097614;
00166 float TkLasBeamFitter::gTOBparam = 0.034949;
00167 double TkLasBeamFitter::gBeamR = 0.0;
00168 double TkLasBeamFitter::gBeamZ0 = 0.0;
00169 double TkLasBeamFitter::gBeamSplitterZprime = 0.0;
00170 unsigned int TkLasBeamFitter::gHitsAtTecMinus = 0;
00171 double TkLasBeamFitter::gBSparam = 0.0;
00172 bool TkLasBeamFitter::gFitBeamSplitters = 0;
00173 bool TkLasBeamFitter::gIsInnerBarrel = 0;
00174
00175
00176 Handle<TkLasBeamCollection> laserBeams;
00177 ESHandle<MagneticField> fieldHandle;
00178 ESHandle<TrackerGeometry> geometry;
00179
00180
00181
00182
00183 TkLasBeamFitter::TkLasBeamFitter(const edm::ParameterSet &iConfig) :
00184 src_(iConfig.getParameter<edm::InputTag>("src")),
00185 fitBeamSplitters_(iConfig.getParameter<bool>("fitBeamSplitters")),
00186 nAtParameters_(iConfig.getParameter<unsigned int>("numberOfFittedAtParameters")),
00187 h_bsAngle(0), h_hitX(0), h_hitXTecPlus(0), h_hitXTecMinus(0),
00188 h_hitXAt(0), h_chi2(0), h_chi2ndof(0), h_pull(0), h_res(0),
00189 h_resTecPlus(0), h_resTecMinus(0), h_resAt(0),
00190 h_bsAngleVsBeam(0), h_hitXvsZTecPlus(0), h_hitXvsZTecMinus(0),
00191 h_hitXvsZAt(0), h_resVsZTecPlus(0), h_resVsZTecMinus(0), h_resVsZAt(0),
00192 h_resVsHitTecPlus(0), h_resVsHitTecMinus(0), h_resVsHitAt(0)
00193 {
00194
00195 this->produces<TkFittedLasBeamCollection, edm::InRun>();
00196 this->produces<TsosVectorCollection, edm::InRun>();
00197
00198
00199 }
00200
00201
00202 TkLasBeamFitter::~TkLasBeamFitter()
00203 {
00204
00205
00206
00207
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217 void TkLasBeamFitter::produce(edm::Event &iEvent, const edm::EventSetup &setup)
00218 {
00219
00220 }
00221
00222
00223
00224 void TkLasBeamFitter::endRun(edm::Run &run, const edm::EventSetup &setup)
00225 {
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 h_hitX = fs->make<TH1F>("hitX","local x of LAS hits;local x [cm];N",100,-0.5,0.5);
00237 h_hitXTecPlus = fs->make<TH1F>("hitXTecPlus","local x of LAS hits in TECplus;local x [cm];N",100,-0.5,0.5);
00238 h_hitXTecMinus = fs->make<TH1F>("hitXTecMinus","local x of LAS hits in TECminus;local x [cm];N",100,-0.5,0.5);
00239 h_hitXAt = fs->make<TH1F>("hitXAt","local x of LAS hits in ATs;local x [cm];N",100,-2.5,2.5);
00240 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);
00241 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);
00242 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);
00243 h_chi2 = fs->make<TH1F>("chi2","#chi^{2};#chi^{2};N",100,0,2000);
00244 h_chi2ndof = fs->make<TH1F>("chi2ndof","#chi^{2} per degree of freedom;#chi^{2}/N_{dof};N",100,0,300);
00245 h_pull = fs->make<TH1F>("pull","pulls of #phi residuals;pull;N",50,-10,10);
00246 h_res = fs->make<TH1F>("res","#phi residuals;#phi_{track} - #phi_{hit} [rad];N",60,-0.0015,0.0015);
00247 h_resTecPlus = fs->make<TH1F>("resTecPlus","#phi residuals in TECplus;#phi_{track} - #phi_{hit} [rad];N",30,-0.0015,0.0015);
00248 h_resTecMinus = fs->make<TH1F>("resTecMinus","#phi residuals in TECminus;#phi_{track} - #phi_{hit} [rad];N",60,-0.0015,0.0015);
00249 h_resAt = fs->make<TH1F>("resAt","#phi residuals in ATs;#phi_{track} - #phi_{hit} [rad];N",30,-0.0015,0.0015);
00250 h_resVsZTecPlus = fs->make<TH2F>("resVsZTecPlus","phi residuals vs. z in TECplus;z [cm];#phi_{track} - #phi_{hit} [rad]",
00251 80,120,280,100,-0.0015,0.0015);
00252 h_resVsZTecMinus = fs->make<TH2F>("resVsZTecMinus","phi residuals vs. z in TECminus;z [cm];#phi_{track} - #phi_{hit} [rad]",
00253 80,-280,-120,100,-0.0015,0.0015);
00254 h_resVsZAt = fs->make<TH2F>("resVsZAt","#phi residuals vs. z in ATs;N;#phi_{track} - #phi_{hit} [rad]",
00255 200,-200,200,100,-0.0015,0.0015);
00256 h_resVsHitTecPlus = fs->make<TH2F>("resVsHitTecPlus","#phi residuals vs. hits in TECplus;hit no.;#phi_{track} - #phi_{hit} [rad]",
00257 144,0,144,100,-0.0015,0.0015);
00258 h_resVsHitTecMinus = fs->make<TH2F>("resVsHitTecMinus","#phi residuals vs. hits in TECminus;hit no.;#phi_{track} - #phi_{hit} [rad]",
00259 144,0,144,100,-0.0015,0.0015);
00260 h_resVsHitAt = fs->make<TH2F>("resVsHitAt","#phi residuals vs. hits in ATs;hit no.;#phi_{track} - #phi_{hit} [rad]",
00261 176,0,176,100,-0.0015,0.0015);
00262 h_bsAngle = fs->make<TH1F>("bsAngle","fitted beam splitter angle;BS angle [rad];N",40,-0.004,0.004);
00263 h_bsAngleVsBeam = fs->make<TH2F>("bsAngleVsBeam","fitted beam splitter angle per beam;Beam no.;BS angle [rad]",
00264 40,0,300,100,-0.004,0.004);
00265
00266
00267
00268 std::auto_ptr<TkFittedLasBeamCollection> fittedBeams(new TkFittedLasBeamCollection);
00269
00270 std::auto_ptr<TsosVectorCollection> tsosesVec(new TsosVectorCollection);
00271
00272
00273 run.getByLabel( "LaserAlignment", "tkLaserBeams", laserBeams );
00274 setup.get<TrackerDigiGeometryRecord>().get(geometry);
00275 setup.get<IdealMagneticFieldRecord>().get(fieldHandle);
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 double bsParams[40] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00288 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
00289
00290
00291 unsigned int beamNo(0);
00292
00293 gFitBeamSplitters = fitBeamSplitters_;
00294 if(fitBeamSplitters_) cout << "Fitting BS!" << endl;
00295 else cout << "BS fixed, not fitted!" << endl;
00296
00297
00298 for(TkLasBeamCollection::const_iterator iBeam = laserBeams->begin(), iEnd = laserBeams->end();
00299 iBeam != iEnd; ++iBeam){
00300
00301 TkFittedLasBeam beam(*iBeam);
00302 vector<TrajectoryStateOnSurface> tsosLas;
00303
00304
00305 gBSparam = bsParams[beamNo];
00306
00307
00308 this->getLasBeams(beam, tsosLas);
00309
00310
00311 fittedBeams->push_back(beam);
00312 tsosesVec->push_back(tsosLas);
00313
00314
00315
00316
00317
00318
00319
00320
00321 beamNo++;
00322 }
00323
00324
00325 run.put(fittedBeams);
00326 run.put(tsosesVec);
00327 }
00328
00329
00330
00331
00332 void TkLasBeamFitter::getLasBeams(TkFittedLasBeam &beam, vector<TrajectoryStateOnSurface> &tsosLas)
00333 {
00334 cout << "---------------------------------------" << endl;
00335 cout << "beam id: " << beam.getBeamId()
00336 << " isTec+: " << (beam.isTecInternal(1) ? "Y" : "N") << " isTec-: " << (beam.isTecInternal(-1) ? "Y" : "N")
00337 << " isAt: " << (beam.isAlignmentTube() ? "Y" : "N") << " isR6: " << (beam.isRing6() ? "Y" : "N")
00338 << endl;
00339
00340
00341 gHitsAtTecMinus = 0;
00342 gHitZprime.clear();
00343 gBarrelModuleRadius.clear();
00344 gBarrelModuleOffset.clear();
00345
00346
00347 gBeamR = beam.isRing6() ? 84.0 : 56.4;
00348
00349 vector<const GeomDetUnit*> gd;
00350 vector<GlobalPoint> globHit;
00351 unsigned int hitsAtTecPlus(0);
00352 double sumZ(0.);
00353
00354
00355 for( TkLasBeam::const_iterator iHit = beam.begin(); iHit < beam.end(); ++iHit ){
00356
00357
00358 const SiStripLaserRecHit2D hit(*iHit);
00359
00360 this->getLasHits(beam, hit, gd, globHit, hitsAtTecPlus);
00361 sumZ += globHit.back().z();
00362
00363
00364 h_hitX->Fill(hit.localPosition().x());
00365
00366 if(beam.isTecInternal(1)){
00367 h_hitXTecPlus->Fill(hit.localPosition().x());
00368 h_hitXvsZTecPlus->Fill(globHit.back().z(),hit.localPosition().x());
00369 }
00370
00371 else if(beam.isTecInternal(-1)){
00372 h_hitXTecMinus->Fill(hit.localPosition().x());
00373 h_hitXvsZTecMinus->Fill(globHit.back().z(),hit.localPosition().x());
00374 }
00375
00376 else{
00377 h_hitXAt->Fill(hit.localPosition().x());
00378 h_hitXvsZAt->Fill(globHit.back().z(),hit.localPosition().x());
00379 }
00380 }
00381
00382 gBeamZ0 = sumZ / globHit.size();
00383 double zMin(0.), zMax(0.);
00384
00385 if(beam.isTecInternal(1)){
00386 gBeamSplitterZprime = 205.75 - gBeamZ0;
00387 zMin = 120.0 - gBeamZ0;
00388 zMax = 280.0 - gBeamZ0;
00389 }
00390
00391 else if(beam.isTecInternal(-1)){
00392 gBeamSplitterZprime = -205.75 - gBeamZ0;
00393 zMin = -280.0 - gBeamZ0;
00394 zMax = -120.0 - gBeamZ0;
00395 }
00396
00397 else{
00398 gBeamSplitterZprime = 112.3 - gBeamZ0;
00399 zMin = -200.0 - gBeamZ0;
00400 zMax = 200.0 - gBeamZ0;
00401 }
00402
00403
00404 vector<double> hitPhi, hitPhiError, hitZprimeError;
00405
00406 for(unsigned int hit = 0; hit < globHit.size(); ++hit){
00407 hitPhi.push_back(static_cast<double>(globHit[hit].phi()));
00408
00409 hitPhiError.push_back( 0.003 / globHit[hit].perp());
00410
00411 hitZprimeError.push_back(0.0);
00412
00413 if(beam.isAlignmentTube() && abs(globHit[hit].z()) < 112.3){
00414 gBarrelModuleRadius.push_back(globHit[hit].perp());
00415 gBarrelModuleOffset.push_back(gBarrelModuleRadius.back() - gBeamR);
00416
00417 if(gBarrelModuleOffset.back() < 0.0){
00418 gIsInnerBarrel = 1;
00419 }
00420 else{
00421 gIsInnerBarrel = 0;
00422 }
00423 gHitZprime.push_back(globHit[hit].z() - gBeamZ0 - abs(gBarrelModuleOffset.back()));
00424 }
00425
00426 else{
00427 gHitZprime.push_back(globHit[hit].z() - gBeamZ0);
00428 }
00429 }
00430
00431
00432 unsigned int tecParams(3), atParams(0);
00433 if(nAtParameters_ == 3) atParams = 3;
00434 else if(nAtParameters_ == 5) atParams = 5;
00435 else atParams = 6;
00436 unsigned int nFitParams(0);
00437 if(!fitBeamSplitters_ ||
00438 (hitsAtTecPlus == 0 && beam.isAlignmentTube() ) ){
00439 tecParams = tecParams - 1;
00440 atParams = atParams - 1;
00441 }
00442 if(beam.isTecInternal()){
00443 nFitParams = tecParams;
00444 }
00445 else{
00446 nFitParams = atParams;
00447 }
00448
00449
00450 double offset(0.), offsetError(0.), slope(0.), slopeError(0.),
00451 bsAngleParam(0.), phiAtMinusParam(0.), phiAtPlusParam(0.),
00452 atThetaSplitParam(0.);
00453 AlgebraicSymMatrix covMatrix;
00454 if(!fitBeamSplitters_ || (beam.isAlignmentTube() && hitsAtTecPlus == 0)){
00455 covMatrix = AlgebraicSymMatrix(nFitParams, 1);
00456 }
00457 else{
00458 covMatrix = AlgebraicSymMatrix(nFitParams - 1, 1);
00459 }
00460
00461 this->fitter(beam, covMatrix,
00462 hitsAtTecPlus, nFitParams,
00463 hitPhi, hitPhiError, hitZprimeError,
00464 zMin, zMax, bsAngleParam,
00465 offset, offsetError, slope, slopeError,
00466 phiAtMinusParam, phiAtPlusParam,
00467 atThetaSplitParam);
00468
00469 vector<GlobalPoint> globPtrack;
00470 GlobalPoint globPref;
00471 double chi2(0.);
00472
00473 for(unsigned int hit = 0; hit < gHitZprime.size(); ++hit){
00474
00475
00476 double trackPhi(0.), trackPhiRef(0.);
00477
00478 this->trackPhi(beam, hit, trackPhi, trackPhiRef,
00479 offset, slope, bsAngleParam,
00480 phiAtMinusParam, phiAtPlusParam,
00481 atThetaSplitParam, globHit);
00482
00483 cout << "track phi = " << trackPhi
00484 << ", hit phi = " << hitPhi[hit]
00485 << ", zPrime = " << gHitZprime[hit]
00486 << " r = " << globHit[hit].perp() << endl;
00487
00488 this->globalTrackPoint(beam, hit, hitsAtTecPlus,
00489 trackPhi, trackPhiRef,
00490 globHit, globPtrack, globPref,
00491 hitPhiError);
00492
00493
00494 const double phiResidual = globPtrack[hit].phi() - globHit[hit].phi();
00495
00496 const double phiResidualPull = phiResidual / hitPhiError[hit];
00497
00498
00499
00500
00501 chi2 += phiResidual*phiResidual / (hitPhiError[hit]*hitPhiError[hit]);
00502
00503
00504 h_res->Fill(phiResidual);
00505
00506 if(beam.isTecInternal(1)){
00507 h_pull->Fill(phiResidualPull);
00508 h_resTecPlus->Fill(phiResidual);
00509 h_resVsZTecPlus->Fill(globPtrack[hit].z(), phiResidual);
00510
00511 if(beam.isRing6()){
00512 h_resVsHitTecPlus->Fill(hit+(beam.getBeamId()-1)/10*9+72, phiResidual);
00513 }
00514
00515 else{
00516 h_resVsHitTecPlus->Fill(hit+beam.getBeamId()/10*9, phiResidual);
00517 }
00518 }
00519
00520 else if(beam.isTecInternal(-1)){
00521 h_pull->Fill(phiResidualPull);
00522 h_resTecMinus->Fill(phiResidual);
00523 h_resVsZTecMinus->Fill(globPtrack[hit].z(), phiResidual);
00524
00525 if(beam.isRing6()){
00526 h_resVsHitTecMinus->Fill(hit+(beam.getBeamId()-101)/10*9+72, phiResidual);
00527 }
00528
00529 else{
00530 h_resVsHitTecMinus->Fill(hit+(beam.getBeamId()-100)/10*9, phiResidual);
00531 }
00532 }
00533
00534 else{
00535 h_pull->Fill(phiResidualPull);
00536 h_resAt->Fill(phiResidual);
00537 h_resVsZAt->Fill(globPtrack[hit].z(), phiResidual);
00538 h_resVsHitAt->Fill(hit+(beam.getBeamId()-200)/10*22, phiResidual);
00539 }
00540
00541 this->buildTrajectory(beam, hit, gd, globPtrack, tsosLas, globPref);
00542 }
00543
00544 cout << "chi^2 = " << chi2 << ", chi^2/ndof = " << chi2/(gHitZprime.size() - nFitParams) << endl;
00545 this->fitBeam(beam, covMatrix, hitsAtTecPlus, nFitParams,
00546 offset, slope, globPtrack, bsAngleParam, chi2);
00547
00548 cout << "bsAngleParam = " << bsAngleParam << endl;
00549
00550
00551
00552 h_chi2->Fill(chi2);
00553 h_chi2ndof->Fill(chi2/(gHitZprime.size() - nFitParams));
00554 if(bsAngleParam != 0.0){
00555 h_bsAngle->Fill(2.0*atan(0.5*bsAngleParam));
00556 h_bsAngleVsBeam->Fill(beam.getBeamId(), 2.0*atan(0.5*bsAngleParam));
00557 }
00558 }
00559
00560
00561
00562 void TkLasBeamFitter::getLasHits(TkFittedLasBeam &beam, const SiStripLaserRecHit2D &hit,
00563 vector<const GeomDetUnit*> &gd, vector<GlobalPoint> &globHit,
00564 unsigned int &hitsAtTecPlus)
00565 {
00566
00567 gd.push_back(geometry->idToDetUnit(hit.getDetId()));
00568 GlobalPoint globPtemp(gd.back()->toGlobal(hit.localPosition()));
00569
00570
00571 globHit.push_back(globPtemp);
00572
00573 if(beam.isAlignmentTube()){
00574 if(abs(globPtemp.z()) > 112.3){
00575 if(globPtemp.z() < 112.3) gHitsAtTecMinus++ ;
00576 else hitsAtTecPlus++ ;
00577 }
00578 }
00579 }
00580
00581
00582
00583 double TkLasBeamFitter::tecPlusFunction(double *x, double *par)
00584 {
00585 double z = x[0];
00586
00587 if(z < gBeamSplitterZprime){
00588 return par[0] + par[1] * z;
00589 }
00590 else{
00591 if(gFitBeamSplitters){
00592
00593 return par[0] + par[1] * z - par[2] * (z - gBeamSplitterZprime)/gBeamR;
00594 }
00595 else{
00596 return par[0] + par[1] * z - gBSparam * (z - gBeamSplitterZprime)/gBeamR;
00597 }
00598 }
00599 }
00600
00601
00602 double TkLasBeamFitter::tecMinusFunction(double *x, double *par)
00603 {
00604 double z = x[0];
00605
00606 if(z > gBeamSplitterZprime){
00607 return par[0] + par[1] * z;
00608 }
00609 else{
00610 if(gFitBeamSplitters){
00611
00612 return par[0] + par[1] * z + par[2] * (z - gBeamSplitterZprime)/gBeamR;
00613 }
00614 else{
00615 return par[0] + par[1] * z + gBSparam * (z - gBeamSplitterZprime)/gBeamR;
00616 }
00617 }
00618 }
00619
00620 double TkLasBeamFitter::atFunction(double *x, double *par)
00621 {
00622 double z = x[0];
00623
00624 if(z < -gBeamSplitterZprime - 2.0*gBeamZ0){
00625 return par[0] + par[1] * z;
00626 }
00627
00628 else if(-gBeamSplitterZprime - 2.0*gBeamZ0 < z && z < -gBeamZ0){
00629
00630
00631 if(!gIsInnerBarrel){
00632 return par[0] + par[1] * z + gTOBparam * (par[2] + par[4]);
00633 }
00634
00635 else{
00636 return par[0] + par[1] * z - gTIBparam * (par[2] - par[4]);
00637 }
00638 }
00639
00640 else if(-gBeamZ0 < z && z < gBeamSplitterZprime){
00641
00642
00643 if(!gIsInnerBarrel){
00644 return par[0] + par[1] * z + gTOBparam * (par[3] - par[4]);
00645 }
00646
00647 else{
00648 return par[0] + par[1] * z - gTIBparam * (par[3] + par[4]);
00649 }
00650 }
00651
00652 else{
00653 if(gFitBeamSplitters){
00654
00655 return par[0] + par[1] * z - par[5] * (z - gBeamSplitterZprime)/gBeamR;
00656 }
00657 else{
00658 return par[0] + par[1] * z - gBSparam * (z - gBeamSplitterZprime)/gBeamR;
00659 }
00660 }
00661 }
00662
00663
00664
00665 void TkLasBeamFitter::fitter(TkFittedLasBeam &beam, AlgebraicSymMatrix &covMatrix,
00666 unsigned int &hitsAtTecPlus, unsigned int &nFitParams,
00667 vector<double> &hitPhi, vector<double> &hitPhiError, vector<double> &hitZprimeError,
00668 double &zMin, double &zMax, double &bsAngleParam,
00669 double &offset, double &offsetError, double &slope, double &slopeError,
00670 double &phiAtMinusParam, double &phiAtPlusParam, double &atThetaSplitParam)
00671 {
00672 TGraphErrors *lasData = new TGraphErrors(gHitZprime.size(),
00673 &(gHitZprime[0]), &(hitPhi[0]),
00674 &(hitZprimeError[0]), &(hitPhiError[0]));
00675
00676
00677 if(beam.isTecInternal(1)){
00678 TF1 tecPlus("tecPlus", tecPlusFunction, zMin, zMax, nFitParams );
00679 tecPlus.SetParameter( 1, 0 );
00680 tecPlus.SetParameter( nFitParams - 1, 0 );
00681 lasData->Fit("tecPlus", "R");
00682 }
00683 else if(beam.isTecInternal(-1)){
00684 TF1 tecMinus("tecMinus", tecMinusFunction, zMin, zMax, nFitParams );
00685 tecMinus.SetParameter( 1, 0 );
00686 tecMinus.SetParameter( nFitParams - 1, 0 );
00687 lasData->Fit("tecMinus", "R");
00688 }
00689 else{
00690 TF1 at("at", atFunction, zMin, zMax, nFitParams );
00691 at.SetParameter( 1, 0 );
00692 at.SetParameter( nFitParams - 1, 0 );
00693 lasData->Fit("at","R");
00694 }
00695
00696
00697 gMinuit->GetParameter(0, offset, offsetError);
00698 gMinuit->GetParameter(1, slope, slopeError);
00699
00700
00701
00702 double bsAngleParamError(0.), phiAtMinusParamError(0.),
00703 phiAtPlusParamError(0.), atThetaSplitParamError(0.);
00704
00705 if(beam.isAlignmentTube()){
00706 gMinuit->GetParameter(2, phiAtMinusParam, phiAtMinusParamError);
00707 gMinuit->GetParameter(3, phiAtPlusParam, phiAtPlusParamError);
00708 gMinuit->GetParameter(4, atThetaSplitParam, atThetaSplitParamError);
00709 }
00710
00711 if(fitBeamSplitters_){
00712 if(beam.isAlignmentTube() && hitsAtTecPlus == 0){
00713 bsAngleParam = gBSparam;
00714 }
00715 else{
00716 gMinuit->GetParameter( nFitParams - 1 , bsAngleParam, bsAngleParamError);
00717 }
00718 }
00719 else{
00720 bsAngleParam = gBSparam;
00721 }
00722
00723
00724 vector<double> vec( covMatrix.num_col() * covMatrix.num_col() );
00725 gMinuit->mnemat( &vec[0], covMatrix.num_col() );
00726 for(int col = 0; col < covMatrix.num_col(); col++){
00727 for(int row = 0; row < covMatrix.num_col(); row++){
00728 covMatrix[col][row] = vec[row + covMatrix.num_col()*col];
00729 }
00730 }
00731
00732
00733
00734 delete lasData;
00735 }
00736
00737
00738
00739 void TkLasBeamFitter::trackPhi(TkFittedLasBeam &beam, unsigned int &hit,
00740 double &trackPhi, double &trackPhiRef,
00741 double &offset, double &slope, double &bsAngleParam,
00742 double &phiAtMinusParam, double &phiAtPlusParam,
00743 double &atThetaSplitParam, vector<GlobalPoint> &globHit)
00744 {
00745
00746 if(beam.isTecInternal(1)){
00747 if(gHitZprime[hit] < gBeamSplitterZprime){
00748 trackPhi = offset + slope * gHitZprime[hit];
00749 trackPhiRef = offset + slope * (gHitZprime[hit] + 1.0);
00750 }
00751 else{
00752 trackPhi = offset + slope * gHitZprime[hit]
00753 - bsAngleParam * (gHitZprime[hit] - gBeamSplitterZprime)/gBeamR;
00754 trackPhiRef = offset + slope * (gHitZprime[hit] + 1.0)
00755 - bsAngleParam * ((gHitZprime[hit] + 1.0) - gBeamSplitterZprime)/gBeamR;
00756 }
00757 }
00758
00759 else if(beam.isTecInternal(-1)){
00760 if(gHitZprime[hit] > gBeamSplitterZprime){
00761 trackPhi = offset + slope * gHitZprime[hit];
00762 trackPhiRef = offset + slope * (gHitZprime[hit] + 1.0);
00763 }
00764 else{
00765 trackPhi = offset + slope * gHitZprime[hit]
00766 + bsAngleParam * (gHitZprime[hit] - gBeamSplitterZprime)/gBeamR;
00767 trackPhiRef = offset + slope * (gHitZprime[hit] + 1.0)
00768 + bsAngleParam * ((gHitZprime[hit] + 1.0) - gBeamSplitterZprime)/gBeamR;
00769 }
00770 }
00771
00772 else{
00773
00774 if(gHitZprime[hit] < -gBeamSplitterZprime - 2.0*gBeamZ0){
00775 trackPhi = offset + slope * gHitZprime[hit];
00776 trackPhiRef = offset + slope * (gHitZprime[hit] + 1.0);
00777 }
00778
00779 else if(-gBeamSplitterZprime - 2.0*gBeamZ0 < gHitZprime[hit] && gHitZprime[hit] < -gBeamZ0){
00780 if(!gIsInnerBarrel){
00781 trackPhi = offset + slope * gHitZprime[hit] + gTOBparam * (phiAtMinusParam + atThetaSplitParam);
00782 }
00783 else{
00784 trackPhi = offset + slope * gHitZprime[hit] - gTIBparam * (phiAtMinusParam - atThetaSplitParam);
00785 }
00786 trackPhiRef = offset + slope * (gHitZprime[hit] + abs(gBarrelModuleOffset[hit-gHitsAtTecMinus]));
00787 }
00788
00789 else if(-gBeamZ0 < gHitZprime[hit] && gHitZprime[hit] < gBeamSplitterZprime){
00790 if(!gIsInnerBarrel){
00791 trackPhi = offset + slope * gHitZprime[hit] + gTOBparam * (phiAtPlusParam - atThetaSplitParam);
00792 }
00793 else{
00794 trackPhi = offset + slope * gHitZprime[hit] - gTIBparam * (phiAtPlusParam + atThetaSplitParam);
00795 }
00796 trackPhiRef = offset + slope * (gHitZprime[hit] + abs(gBarrelModuleOffset[hit-gHitsAtTecMinus]));
00797 }
00798
00799 else{
00800 trackPhi = offset + slope * gHitZprime[hit]
00801 - bsAngleParam * (gHitZprime[hit] - gBeamSplitterZprime)/gBeamR;
00802 trackPhiRef = offset + slope * (gHitZprime[hit] + 1.0)
00803 - bsAngleParam * ((gHitZprime[hit] + 1.0) - gBeamSplitterZprime)/gBeamR;
00804 }
00805 }
00806 }
00807
00808
00809
00810 void TkLasBeamFitter::globalTrackPoint(TkFittedLasBeam &beam,
00811 unsigned int &hit, unsigned int &hitsAtTecPlus,
00812 double &trackPhi, double &trackPhiRef,
00813 vector<GlobalPoint> &globHit, vector<GlobalPoint> &globPtrack,
00814 GlobalPoint &globPref, vector<double> &hitPhiError)
00815 {
00816
00817 if(beam.isTecInternal(0)){
00818 globPtrack.push_back(GlobalPoint(GlobalPoint::Cylindrical(gBeamR, trackPhi, globHit[hit].z())));
00819 globPref = GlobalPoint(GlobalPoint::Cylindrical(gBeamR, trackPhiRef, globHit[hit].z() + 1.0));
00820 }
00821
00822 else{
00823
00824 if(hit < gHitsAtTecMinus){
00825 globPtrack.push_back(GlobalPoint(GlobalPoint::Cylindrical(gBeamR, trackPhi, globHit[hit].z())));
00826 globPref = GlobalPoint(GlobalPoint::Cylindrical(gBeamR, trackPhiRef, globHit[hit].z() + 1.0));
00827 }
00828
00829 else if(hit > gHitZprime.size() - hitsAtTecPlus - 1){
00830 globPtrack.push_back(GlobalPoint(GlobalPoint::Cylindrical(gBeamR, trackPhi, globHit[hit].z())));
00831 globPref = GlobalPoint(GlobalPoint::Cylindrical(gBeamR, trackPhiRef, globHit[hit].z() + 1.0));
00832 }
00833
00834 else{
00835 globPtrack.push_back(GlobalPoint(GlobalPoint::Cylindrical(globHit[hit].perp(), trackPhi, globHit[hit].z())));
00836 globPref = GlobalPoint(GlobalPoint::Cylindrical(gBeamR, trackPhiRef, globHit[hit].z()));
00837 }
00838 }
00839 }
00840
00841
00842
00843 void TkLasBeamFitter::buildTrajectory(TkFittedLasBeam &beam, unsigned int &hit,
00844 vector<const GeomDetUnit*> &gd, vector<GlobalPoint> &globPtrack,
00845 vector<TrajectoryStateOnSurface> &tsosLas, GlobalPoint &globPref)
00846 {
00847 const MagneticField* magneticField = fieldHandle.product();
00848 GlobalVector trajectoryState;
00849
00850
00851 if(beam.isTecInternal(1)){
00852 trajectoryState = GlobalVector(globPref-globPtrack[hit]);
00853 }
00854
00855 else if(beam.isTecInternal(-1)){
00856 trajectoryState = GlobalVector(globPtrack[hit]-globPref);
00857 }
00858
00859 else{
00860
00861 if(gHitZprime[hit] < -gBeamSplitterZprime - 2.0*gBeamZ0){
00862 trajectoryState = GlobalVector(globPtrack[hit]-globPref);
00863 }
00864
00865 else if(gHitZprime[hit] > gBeamSplitterZprime){
00866 trajectoryState = GlobalVector(globPref-globPtrack[hit]);
00867 }
00868
00869 else{
00870 trajectoryState = GlobalVector(globPtrack[hit]-globPref);
00871 }
00872 }
00873
00874 const FreeTrajectoryState ftsLas = FreeTrajectoryState(globPtrack[hit],trajectoryState,0,magneticField);
00875 tsosLas.push_back(TrajectoryStateOnSurface(ftsLas,gd[hit]->surface(),
00876 SurfaceSideDefinition::beforeSurface));
00877 }
00878
00879
00880
00881 bool TkLasBeamFitter::fitBeam(TkFittedLasBeam &beam, AlgebraicSymMatrix &covMatrix,
00882 unsigned int &hitsAtTecPlus, unsigned int &nFitParams,
00883 double &offset, double &slope, vector<GlobalPoint> &globPtrack,
00884 double &bsAngleParam, double &chi2)
00885 {
00886
00887 unsigned int paramType(0);
00888 if(!fitBeamSplitters_) paramType = 1;
00889 if(beam.isAlignmentTube() && hitsAtTecPlus == 0) paramType = 0;
00890
00891
00892
00893 const unsigned int nPedeParams(nFitParams);
00894
00895
00896 std::vector<TkFittedLasBeam::Scalar> params(nPedeParams);
00897 params[0] = offset;
00898 params[1] = slope;
00899
00900
00901
00902 AlgebraicMatrix derivatives(gHitZprime.size(), nPedeParams);
00903
00904 for(unsigned int hit = 0; hit < gHitZprime.size(); ++hit){
00905
00906
00907 derivatives[hit][0] = 1.0;
00908
00909
00910
00911 if(beam.isTecInternal(1)){
00912 derivatives[hit][1] = globPtrack[hit].z();
00913
00914
00915
00916
00917
00918
00919 }
00920
00921 else if(beam.isTecInternal(-1)){
00922 derivatives[hit][1] = globPtrack[hit].z();
00923
00924
00925
00926
00927
00928
00929 }
00930
00931 else{
00932
00933 if(gHitZprime[hit] < -gBeamSplitterZprime - 2.0*gBeamZ0){
00934 derivatives[hit][1] = globPtrack[hit].z();
00935
00936
00937
00938 }
00939
00940 else if(gHitZprime[hit] > gBeamSplitterZprime){
00941 derivatives[hit][1] = globPtrack[hit].z();
00942
00943
00944
00945 }
00946
00947 else{
00948 derivatives[hit][1] = globPtrack[hit].z() - gBarrelModuleOffset[hit-gHitsAtTecMinus];
00949
00950
00951
00952 }
00953 }
00954 }
00955
00956 unsigned int firstFixedParam(covMatrix.num_col());
00957
00958
00959
00960
00961 beam.setParameters(paramType, params, covMatrix, derivatives, firstFixedParam, chi2);
00962
00963 return true;
00964 }
00965
00966
00967
00968
00969 DEFINE_FWK_MODULE(TkLasBeamFitter);