CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch9/src/CalibMuon/DTCalibration/plugins/DTVDriftCalibration.cc

Go to the documentation of this file.
00001 
00002 /*
00003  *  See header file for a description of this class.
00004  *
00005  *  $Date: 2008/12/09 22:44:10 $
00006  *  $Revision: 1.6 $
00007  *  \author M. Giunta
00008  */
00009 
00010 #include "CalibMuon/DTCalibration/plugins/DTVDriftCalibration.h"
00011 #include "CalibMuon/DTCalibration/interface/DTMeanTimerFitter.h"
00012 #include "CalibMuon/DTCalibration/interface/DTCalibDBUtils.h"
00013 
00014 #include "FWCore/Framework/interface/Event.h"
00015 #include "FWCore/Framework/interface/ESHandle.h"
00016 
00017 #include "Geometry/DTGeometry/interface/DTGeometry.h"
00018 #include "Geometry/Records/interface/MuonGeometryRecord.h"
00019 
00020 #include "CalibMuon/DTDigiSync/interface/DTTTrigSyncFactory.h"
00021 #include "CalibMuon/DTDigiSync/interface/DTTTrigBaseSync.h"
00022 
00023 #include "DataFormats/DTRecHit/interface/DTRecSegment4DCollection.h"
00024 #include "CondFormats/DTObjects/interface/DTMtime.h"
00025 
00026 #include "CondFormats/DataRecord/interface/DTStatusFlagRcd.h"
00027 #include "CondFormats/DTObjects/interface/DTStatusFlag.h"
00028 
00029 /* C++ Headers */
00030 #include <map>
00031 #include <iostream>
00032 #include <fstream>
00033 #include <string>
00034 #include <sstream>
00035 #include "TFile.h"
00036 #include "TH1.h"
00037 #include "TF1.h"
00038 #include "TROOT.h" 
00039 
00040 // Declare histograms.
00041 TH1F * hChi2;
00042 extern void bookHistos();
00043 
00044 using namespace std;
00045 using namespace edm;
00046 using namespace dttmaxenums;
00047 
00048 
00049 DTVDriftCalibration::DTVDriftCalibration(const ParameterSet& pset) {
00050   // the root file which will contain the histos
00051   string rootFileName = pset.getUntrackedParameter<string>("rootFileName");
00052   theFile = new TFile(rootFileName.c_str(), "RECREATE");
00053   theFile->cd();
00054 
00055   debug = pset.getUntrackedParameter<bool>("debug", "false");
00056 
00057   theFitter = new DTMeanTimerFitter(theFile);
00058   if(debug)
00059     theFitter->setVerbosity(1);
00060 
00061   hChi2 = new TH1F("hChi2","Chi squared tracks",100,0,100);
00062   h2DSegmRPhi = new h2DSegm("SLRPhi");
00063   h2DSegmRZ = new h2DSegm("SLRZ");
00064   h4DSegmAllCh = new h4DSegm("AllCh");
00065   bookHistos();
00066 
00067   findVDriftAndT0 = pset.getUntrackedParameter<bool>("fitAndWrite", "false");
00068 
00069   // Chamber/s to calibrate
00070   theCalibChamber =  pset.getUntrackedParameter<string>("calibChamber", "All");
00071 
00072   // the name of the 4D rec hits collection
00073   theRecHits4DLabel = pset.getUntrackedParameter<string>("recHits4DLabel");
00074 
00075   // the txt file which will contain the calibrated constants
00076   theVDriftOutputFile = pset.getUntrackedParameter<string>("vDriftFileName");
00077 
00078   //get the switch to check the noisy channels
00079   checkNoisyChannels = pset.getUntrackedParameter<bool>("checkNoisyChannels","false");
00080 
00081   // Get the synchronizer
00082   theSync = DTTTrigSyncFactory::get()->create(pset.getUntrackedParameter<string>("tTrigMode"),
00083                                               pset.getUntrackedParameter<ParameterSet>("tTrigModeConfig"));
00084 
00085   // get parameter set for DTCalibrationMap constructor
00086   theCalibFilePar =  pset.getUntrackedParameter<ParameterSet>("calibFileConfig");
00087 
00088   // get maximum chi2 value 
00089   theMaxChi2 =  pset.getParameter<double>("maxChi2");
00090 
00091   // Maximum incidence angle for Phi SL 
00092   theMaxPhiAngle =  pset.getParameter<double>("maxAnglePhi");
00093 
00094   // Maximum incidence angle for Theta SL 
00095   theMaxZAngle =  pset.getParameter<double>("maxAngleZ");
00096 
00097   // the granularity to be used for tMax
00098   string tMaxGranularity = pset.getUntrackedParameter<string>("tMaxGranularity","bySL");
00099 
00100   // Initialize correctly the enum which specify the granularity for the calibration
00101   if(tMaxGranularity == "bySL") {
00102     theGranularity = bySL;
00103   } else if(tMaxGranularity == "byChamber"){
00104     theGranularity = byChamber;
00105   } else if(tMaxGranularity== "byPartition") {
00106     theGranularity = byPartition;
00107   } else {
00108     cout << "[DTVDriftCalibration]###Warning: Check parameter tMaxGranularity: "
00109          << tMaxGranularity << " options not available!" << endl;
00110   }
00111 
00112   if(debug)
00113     cout << "[DTVDriftCalibration]Constructor called!" << endl;
00114 }
00115 
00116 DTVDriftCalibration::~DTVDriftCalibration(){
00117   theFile->Close();
00118   delete theFitter;
00119   if(debug) 
00120     cout << "[DTVDriftCalibration]Destructor called!" << endl;
00121 }
00122 
00123 
00124 
00125 void DTVDriftCalibration::analyze(const Event & event, const EventSetup& eventSetup) {
00126   cout << endl<<"--- [DTVDriftCalibration] Event analysed #Run: " << event.id().run()
00127        << " #Event: " << event.id().event() << endl;
00128   theFile->cd();
00129   DTChamberId chosenChamberId;
00130 
00131   if(theCalibChamber != "All") {
00132     stringstream linestr;
00133     int selWheel, selStation, selSector;
00134     linestr << theCalibChamber;
00135     linestr >> selWheel >> selStation >> selSector;
00136     chosenChamberId = DTChamberId(selWheel, selStation, selSector);
00137     cout << "chosen chamber " << chosenChamberId << endl;
00138   }
00139 
00140   // Get the DT Geometry
00141   ESHandle<DTGeometry> dtGeom;
00142   eventSetup.get<MuonGeometryRecord>().get(dtGeom);
00143 
00144   // Get the rechit collection from the event
00145   Handle<DTRecSegment4DCollection> all4DSegments;
00146   event.getByLabel(theRecHits4DLabel, all4DSegments); 
00147 
00148   // Get the map of noisy channels
00149   ESHandle<DTStatusFlag> statusMap;
00150   if(checkNoisyChannels) {
00151     eventSetup.get<DTStatusFlagRcd>().get(statusMap);
00152   }
00153 
00154   // Set the event setup in the Synchronizer 
00155   theSync->setES(eventSetup);
00156 
00157   // Loop over segments by chamber
00158   DTRecSegment4DCollection::id_iterator chamberIdIt;
00159   for (chamberIdIt = all4DSegments->id_begin();
00160        chamberIdIt != all4DSegments->id_end();
00161        ++chamberIdIt){
00162 
00163     // Get the chamber from the setup
00164     const DTChamber* chamber = dtGeom->chamber(*chamberIdIt);
00165     if(debug)
00166       cout << "Chamber Id: " << *chamberIdIt << endl;
00167 
00168 
00169     // Calibrate just the chosen chamber/s    
00170     if((theCalibChamber != "All") && ((*chamberIdIt) != chosenChamberId)) 
00171       continue;
00172 
00173     // Get the range for the corresponding ChamberId
00174     DTRecSegment4DCollection::range  range = all4DSegments->get((*chamberIdIt));
00175 
00176     // Loop over the rechits of this DetUnit
00177     for (DTRecSegment4DCollection::const_iterator segment = range.first;
00178          segment!=range.second; ++segment){
00179 
00180       if(debug) {
00181         cout << "Segment local pos (in chamber RF): " << (*segment).localPosition() << endl;
00182         cout << "Segment global pos: " << chamber->toGlobal((*segment).localPosition()) << endl;;
00183       }
00184 
00185       //get the segment chi2
00186       double chiSquare = ((*segment).chi2()/(*segment).degreesOfFreedom());
00187       // cut on the segment chi2 
00188       if(chiSquare > theMaxChi2) continue;
00189 
00190       // get the Phi 2D segment and plot the angle in the chamber RF
00191       if(!((*segment).phiSegment())){
00192         cout<<"No phi segment"<<endl;
00193       }
00194       LocalPoint phiSeg2DPosInCham;  
00195       LocalVector phiSeg2DDirInCham;
00196 
00197       bool segmNoisy = false;
00198       map<DTSuperLayerId,vector<DTRecHit1D> > hitsBySLMap; 
00199 
00200       if((*segment).hasPhi()){
00201         const DTChamberRecSegment2D* phiSeg = (*segment).phiSegment();  // phiSeg lives in the chamber RF
00202         phiSeg2DPosInCham = phiSeg->localPosition();  
00203         phiSeg2DDirInCham = phiSeg->localDirection();
00204 
00205         vector<DTRecHit1D> phiHits = phiSeg->specificRecHits();
00206         for(vector<DTRecHit1D>::const_iterator hit = phiHits.begin();
00207             hit != phiHits.end(); ++hit) {
00208           DTWireId wireId = (*hit).wireId();
00209           DTSuperLayerId slId =  wireId.superlayerId();
00210           hitsBySLMap[slId].push_back(*hit); 
00211 
00212           // Check for noisy channels to skip them
00213           if(checkNoisyChannels) {
00214             bool isNoisy = false;
00215             bool isFEMasked = false;
00216             bool isTDCMasked = false;
00217             bool isTrigMask = false;
00218             bool isDead = false;
00219             bool isNohv = false;
00220             statusMap->cellStatus(wireId, isNoisy, isFEMasked, isTDCMasked, isTrigMask, isDead, isNohv);
00221             if(isNoisy) {
00222               if(debug)
00223                 cout << "Wire: " << wireId << " is noisy, skipping!" << endl;
00224               segmNoisy = true;
00225             }      
00226           }
00227         }
00228       }
00229 
00230       // get the Theta 2D segment and plot the angle in the chamber RF
00231       LocalVector zSeg2DDirInCham;
00232       LocalPoint zSeg2DPosInCham;
00233       if((*segment).hasZed()) {
00234         const DTSLRecSegment2D* zSeg = (*segment).zSegment();  // zSeg lives in the SL RF
00235         const DTSuperLayer* sl = chamber->superLayer(zSeg->superLayerId());
00236         zSeg2DPosInCham = chamber->toLocal(sl->toGlobal((*zSeg).localPosition())); 
00237         zSeg2DDirInCham = chamber->toLocal(sl->toGlobal((*zSeg).localDirection()));
00238         hitsBySLMap[zSeg->superLayerId()] = zSeg->specificRecHits();
00239 
00240         // Check for noisy channels to skip them
00241         vector<DTRecHit1D> zHits = zSeg->specificRecHits();
00242         for(vector<DTRecHit1D>::const_iterator hit = zHits.begin();
00243             hit != zHits.end(); ++hit) {
00244           DTWireId wireId = (*hit).wireId();
00245           if(checkNoisyChannels) {
00246             bool isNoisy = false;
00247             bool isFEMasked = false;
00248             bool isTDCMasked = false;
00249             bool isTrigMask = false;
00250             bool isDead = false;
00251             bool isNohv = false;
00252             statusMap->cellStatus(wireId, isNoisy, isFEMasked, isTDCMasked, isTrigMask, isDead, isNohv);
00253             if(isNoisy) {
00254               if(debug)
00255                 cout << "Wire: " << wireId << " is noisy, skipping!" << endl;
00256               segmNoisy = true;
00257             }      
00258           }
00259         }
00260       } 
00261 
00262       if (segmNoisy) continue;
00263 
00264       LocalPoint segment4DLocalPos = (*segment).localPosition();
00265       LocalVector segment4DLocalDir = (*segment).localDirection();
00266       if(fabs(atan(segment4DLocalDir.y()/segment4DLocalDir.z())* 180./Geom::pi()) > theMaxZAngle) continue; // cut on the angle
00267       if(fabs(atan(segment4DLocalDir.x()/segment4DLocalDir.z())* 180./Geom::pi()) > theMaxPhiAngle) continue; // cut on the angle
00268 
00269       hChi2->Fill(chiSquare);
00270       if((*segment).hasPhi())
00271         h2DSegmRPhi->Fill(phiSeg2DPosInCham.x(), phiSeg2DDirInCham.x()/phiSeg2DDirInCham.z());
00272       if((*segment).hasZed())
00273         h2DSegmRZ->Fill(zSeg2DPosInCham.y(), zSeg2DDirInCham.y()/zSeg2DDirInCham.z());
00274 
00275       if((*segment).hasZed() && (*segment).hasPhi()) 
00276         h4DSegmAllCh->Fill(segment4DLocalPos.x(), 
00277                            segment4DLocalPos.y(),
00278                            atan(segment4DLocalDir.x()/segment4DLocalDir.z())* 180./Geom::pi(),
00279                            atan(segment4DLocalDir.y()/segment4DLocalDir.z())* 180./Geom::pi(),
00280                            180 - segment4DLocalDir.theta()* 180./Geom::pi());
00281       else if((*segment).hasPhi())
00282         h4DSegmAllCh->Fill(segment4DLocalPos.x(), 
00283                            atan(segment4DLocalDir.x()/segment4DLocalDir.z())* 180./Geom::pi());
00284       else if((*segment).hasZed())
00285         cout<<"4d segment with only Z"<<endl;
00286       else{
00287         cout<<"ERROR: 4D segment without Z and Phi. Aborting!"<<endl;
00288         abort();
00289       }
00290 
00291       //loop over the segments 
00292       for(map<DTSuperLayerId,vector<DTRecHit1D> >::const_iterator slIdAndHits = hitsBySLMap.begin(); slIdAndHits != hitsBySLMap.end();  ++slIdAndHits) {
00293         if (slIdAndHits->second.size() < 3) continue;
00294         DTSuperLayerId slId =  slIdAndHits->first;
00295 
00296         // Create the DTTMax, that computes the 4 TMax
00297         DTTMax slSeg(slIdAndHits->second, *(chamber->superLayer(slIdAndHits->first)),chamber->toGlobal((*segment).localDirection()), chamber->toGlobal((*segment).localPosition()), theSync);
00298 
00299         if(theGranularity == bySL) {
00300           vector<const TMax*> tMaxes = slSeg.getTMax(slId);
00301           DTWireId wireId(slId, 0, 0);
00302           theFile->cd();
00303           cellInfo* cell = theWireIdAndCellMap[wireId];
00304           if (cell==0) {
00305             TString name = (((((TString) "TMax"+(long) slId.wheel()) +(long) slId.station())
00306                              +(long) slId.sector())+(long) slId.superLayer());
00307             cell = new cellInfo(name);
00308             theWireIdAndCellMap[wireId] = cell;
00309           }
00310           cell->add(tMaxes);
00311           cell->update(); // FIXME to reset the counter to avoid triple counting, which actually is not used...
00312         }
00313         else {
00314           cout << "[DTVDriftCalibration]###Warning: the chosen granularity is not implemented yet, only bySL available!" << endl;
00315         }
00316         // to be implemented: granularity different from bySL
00317 
00318         //       else if (theGranularity == byPartition) {
00319         //      // Use the custom granularity defined by partition(); 
00320         //      // in this case, add() should be called once for each Tmax of each layer 
00321         //      // and triple counting should be avoided within add()
00322         //      vector<cellInfo*> cells;
00323         //      for (int i=1; i<=4; i++) {
00324         //        const DTTMax::InfoLayer* iLayer = slSeg.getInfoLayer(i);
00325         //        if(iLayer == 0) continue;
00326         //        cellInfo * cell = partition(iLayer->idWire); 
00327         //        cells.push_back(cell);
00328         //        vector<const TMax*> tMaxes = slSeg.getTMax(iLayer->idWire);
00329         //        cell->add(tMaxes);
00330         //      }
00331         //      //reset the counter to avoid triple counting
00332         //      for (vector<cellInfo*>::const_iterator i = cells.begin();
00333         //           i!= cells.end(); i++) {
00334         //        (*i)->update();
00335         //      }
00336         //       } 
00337       }
00338     }
00339   }
00340 }
00341 
00342 void DTVDriftCalibration::endJob() {
00343   theFile->cd();
00344   gROOT->GetList()->Write();
00345   h2DSegmRPhi->Write();
00346   h2DSegmRZ->Write();
00347   h4DSegmAllCh->Write();
00348   hChi2->Write();
00349   // Instantiate a DTCalibrationMap object if you want to calculate the calibration constants
00350   DTCalibrationMap calibValuesFile(theCalibFilePar);  
00351   // Create the object to be written to DB
00352   DTMtime* mTime = new DTMtime();
00353 
00354   // write the TMax histograms of each SL to the root file
00355   if(theGranularity == bySL) {
00356     for(map<DTWireId, cellInfo*>::const_iterator  wireCell = theWireIdAndCellMap.begin();
00357         wireCell != theWireIdAndCellMap.end(); wireCell++) {
00358       cellInfo* cell= theWireIdAndCellMap[(*wireCell).first];
00359       hTMaxCell* cellHists = cell->getHists();
00360       theFile->cd();
00361       cellHists->Write();
00362       if(findVDriftAndT0) {  // if TRUE: evaluate calibration constants from TMax hists filled in this job  
00363         // evaluate v_drift and sigma from the TMax histograms
00364         DTWireId wireId = (*wireCell).first;
00365         vector<float> newConstants;
00366         TString N=(((((TString) "TMax"+(long) wireId.wheel()) +(long) wireId.station())
00367                     +(long) wireId.sector())+(long) wireId.superLayer());
00368         vector<float> vDriftAndReso = theFitter->evaluateVDriftAndReso(N);
00369 
00370         // Don't write the constants for the SL if the vdrift was not computed
00371         if(vDriftAndReso.front() == -1)
00372           continue;
00373         const DTCalibrationMap::CalibConsts* oldConstants = calibValuesFile.getConsts(wireId);
00374         if(oldConstants != 0) {
00375           newConstants.push_back((*oldConstants)[0]);
00376           newConstants.push_back((*oldConstants)[1]);
00377           newConstants.push_back((*oldConstants)[2]);
00378         } else {
00379           newConstants.push_back(-1);
00380           newConstants.push_back(-1);
00381           newConstants.push_back(-1);
00382         }
00383         for(int ivd=0; ivd<=5;ivd++) { 
00384           // 0=vdrift, 1=reso, 2=(3deltat0-2deltat0), 3=(2deltat0-1deltat0),
00385           //  4=(1deltat0-0deltat0), 5=deltat0 from hists with max entries,
00386           newConstants.push_back(vDriftAndReso[ivd]); 
00387         }
00388 
00389         calibValuesFile.addCell(calibValuesFile.getKey(wireId), newConstants);
00390 
00391         // vdrift is cm/ns , resolution is cm
00392         mTime->set((wireId.layerId()).superlayerId(),
00393                    vDriftAndReso[0],
00394                    vDriftAndReso[1],
00395                    DTVelocityUnits::cm_per_ns);
00396         if(debug) {
00397           cout << " SL: " << (wireId.layerId()).superlayerId()
00398                << " vDrift = " << vDriftAndReso[0]
00399                << " reso = " << vDriftAndReso[1] << endl;
00400         }
00401       }
00402     }
00403   }
00404 
00405   // to be implemented: granularity different from bySL
00406 
00407   //   if(theGranularity == "byChamber") {
00408   //     const vector<DTChamber*> chambers = dMap.chambers();
00409 
00410   //     // Loop over all chambers
00411   //     for(vector<MuBarChamber*>::const_iterator chamber = chambers.begin();
00412   //    chamber != chambers.end(); chamber ++) {
00413   //       MuBarChamberId chamber_id = (*chamber)->id();
00414   //       MuBarDigiParameters::Key wire_id(chamber_id, 0, 0, 0);
00415   //       vector<float> newConstants;
00416   //       vector<float> vDriftAndReso = evaluateVDriftAndReso(wire_id, f);
00417   //       const CalibConsts* oldConstants = digiParams.getConsts(wire_id);
00418   //       if(oldConstants !=0) {
00419   //    newConstants = *oldConstants;
00420   //    newConstants.push_back(vDriftAndReso[0]);
00421   //    newConstants.push_back(vDriftAndReso[1]);
00422   //    newConstants.push_back(vDriftAndReso[2]);
00423   //    newConstants.push_back(vDriftAndReso[3]);
00424   //       } else {
00425   //    newConstants.push_back(-1);
00426   //    newConstants.push_back(-1);
00427   //    newConstants.push_back(vDriftAndReso[0]);
00428   //    newConstants.push_back(vDriftAndReso[1]);
00429   //    newConstants.push_back(vDriftAndReso[2]);
00430   //    newConstants.push_back(vDriftAndReso[3]);
00431   //       }
00432   //       digiParams.addCell(wire_id, newConstants);
00433   //     }
00434   //   }
00435 
00436   //write values to a table  
00437   calibValuesFile.writeConsts(theVDriftOutputFile);
00438 
00439   if(debug) 
00440     cout << "[DTVDriftCalibration]Writing vdrift object to DB!" << endl;
00441 
00442   // Write the vdrift object to DB
00443   string record = "DTMtimeRcd";
00444   DTCalibDBUtils::writeToDB<DTMtime>(record, mTime);
00445 
00446 }
00447 
00448 
00449 
00450 // to be implemented: granularity different from bySL
00451 
00452 // // Create partitions 
00453 // DTVDriftCalibration::cellInfo* DTVDriftCalibration::partition(const DTWireId& wireId) {
00454 //   for( map<MuBarWireId, cellInfo*>::const_iterator iter =
00455 //       mapCellTmaxPart.begin(); iter != mapCellTmaxPart.end(); iter++) {
00456 //     // Divide wires per SL (with phi symmetry)
00457 //     if(iter->first.wheel() == wireId.wheel() &&
00458 //        iter->first.station() == wireId.station() &&
00459 //        //       iter->first.sector() == wireId.sector() && // phi symmetry!
00460 //        iter->first.superlayer() == wireId.superlayer()) {
00461 //       return iter->second;
00462 //     }
00463 //   }
00464 //   cellInfo * result = new cellInfo("dummy string"); // FIXME: change constructor; create tree?
00465 //   mapCellTmaxPart.insert(make_pair(wireId, result));
00466 //   return result;
00467 //}
00468 
00469 
00470 void DTVDriftCalibration::cellInfo::add(vector<const TMax*> tMaxes) {
00471   float tmax123 = -1.;
00472   float tmax124 = -1.;
00473   float tmax134 = -1.;  
00474   float tmax234 = -1.;
00475   SigmaFactor s124 = noR;
00476   SigmaFactor s134 = noR;
00477   unsigned t0_123 = 0;
00478   unsigned t0_124 = 0;
00479   unsigned t0_134 = 0;
00480   unsigned t0_234 = 0;
00481   unsigned hSubGroup = 0;
00482   for (vector<const TMax*>::const_iterator it=tMaxes.begin(); it!=tMaxes.end();
00483        ++it) {
00484     if(*it == 0) {
00485       continue;  
00486     }
00487     else { 
00488       //FIXME check cached,
00489       if (addedCells.size()==4 || 
00490           find(addedCells.begin(), addedCells.end(), (*it)->cells) 
00491           != addedCells.end()) {
00492         continue;
00493       }
00494       addedCells.push_back((*it)->cells);    
00495       SigmaFactor sigma = (*it)->sigma;
00496       float t = (*it)->t;
00497       TMaxCells cells = (*it)->cells;
00498       unsigned t0Factor = (*it)->t0Factor;
00499       hSubGroup = (*it)->hSubGroup;
00500       if(t < 0.) continue;
00501       switch(cells) {
00502       case notInit : cout << "Error: no cell type assigned to TMax" << endl; break;
00503       case c123 : tmax123 =t; t0_123 = t0Factor; break;
00504       case c124 : tmax124 =t; s124 = sigma; t0_124 = t0Factor; break;
00505       case c134 : tmax134 =t; s134 = sigma; t0_134 = t0Factor; break;
00506       case c234 : tmax234 =t; t0_234 = t0Factor; break;
00507       } 
00508     }
00509   }
00510   //add entries to the TMax histograms
00511   histos->Fill(tmax123, tmax124, tmax134, tmax234, s124, s134, t0_123, 
00512                t0_124, t0_134, t0_234, hSubGroup); 
00513 }