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