CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_10_patch1/src/Alignment/OfflineValidation/plugins/TrackerOfflineValidation.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:    TrackerOfflineValidation
00004 // Class:      TrackerOfflineValidation
00005 // 
00013 //
00014 // Original Author:  Erik Butz
00015 //         Created:  Tue Dec 11 14:03:05 CET 2007
00016 // $Id: TrackerOfflineValidation.cc,v 1.52 2011/09/15 08:06:07 mussgill Exp $
00017 //
00018 //
00019 
00020 // system include files
00021 #include <memory>
00022 #include <map>
00023 #include <sstream>
00024 #include <math.h>
00025 #include <utility>
00026 #include <vector>
00027 #include <iostream>
00028 
00029 // ROOT includes
00030 #include "TH1.h"
00031 #include "TH2.h"
00032 #include "TProfile.h"
00033 #include "TFile.h"
00034 #include "TTree.h"
00035 #include "TF1.h"
00036 #include "TMath.h"
00037 
00038 // user include files
00039 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00040 #include "FWCore/Framework/interface/Frameworkfwd.h"
00041 #include "FWCore/Framework/interface/EDAnalyzer.h"
00042 #include "FWCore/Framework/interface/EventSetup.h"
00043 #include "FWCore/Framework/interface/Event.h"
00044 #include "FWCore/Framework/interface/MakerMacros.h"
00045 #include "FWCore/Framework/interface/ESHandle.h"
00046 #include "FWCore/ServiceRegistry/interface/Service.h"
00047 
00048 #include "DataFormats/DetId/interface/DetId.h"
00049 #include "DataFormats/SiPixelDetId/interface/PXBDetId.h"
00050 #include "DataFormats/SiPixelDetId/interface/PXFDetId.h"
00051 #include "DataFormats/SiStripDetId/interface/TECDetId.h"
00052 #include "DataFormats/SiStripDetId/interface/TIBDetId.h"
00053 #include "DataFormats/SiStripDetId/interface/TIDDetId.h"
00054 #include "DataFormats/SiStripDetId/interface/TOBDetId.h"
00055 #include "DataFormats/SiPixelDetId/interface/PixelSubdetector.h"
00056 #include "DataFormats/Math/interface/deltaPhi.h"
00057 
00058 #include "CommonTools/UtilAlgos/interface/TFileService.h"
00059 #include "CommonTools/Utils/interface/TFileDirectory.h"
00060 
00061 #include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
00062 #include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
00063 #include "Geometry/CommonDetUnit/interface/GeomDetUnit.h"
00064 
00065 #include "DQMServices/Core/interface/DQMStore.h"
00066 #include "DQMServices/Core/interface/MonitorElement.h"
00067 
00068 #include "Alignment/CommonAlignment/interface/Alignable.h"
00069 #include "Alignment/CommonAlignment/interface/Utilities.h"
00070 #include "Alignment/CommonAlignment/interface/AlignableObjectId.h"
00071 #include "Alignment/TrackerAlignment/interface/AlignableTracker.h"
00072 #include "Alignment/TrackerAlignment/interface/TrackerAlignableId.h"
00073 
00074 #include "Alignment/OfflineValidation/interface/TrackerValidationVariables.h"
00075 #include "Alignment/OfflineValidation/interface/TkOffTreeVariables.h"
00076 
00077 //
00078 // class declaration
00079 //
00080 class TrackerOfflineValidation : public edm::EDAnalyzer {
00081 public:
00082   explicit TrackerOfflineValidation(const edm::ParameterSet&);
00083   ~TrackerOfflineValidation();
00084   
00085   enum HistogrammType { XResidual, NormXResidual, 
00086                         YResidual, /*NormYResidual, */
00087                         XprimeResidual, NormXprimeResidual, 
00088                         YprimeResidual, NormYprimeResidual,
00089                         XResidualProfile, YResidualProfile };
00090   
00091 private:
00092 
00093   struct ModuleHistos{
00094     ModuleHistos() :  ResHisto(), NormResHisto(), ResYHisto(), /*NormResYHisto(),*/
00095                       ResXprimeHisto(), NormResXprimeHisto(), 
00096                       ResYprimeHisto(), NormResYprimeHisto(),
00097                       ResXvsXProfile(), ResXvsYProfile(),
00098                       ResYvsXProfile(), ResYvsYProfile(),
00099                       LocalX(), LocalY() {} 
00100     TH1* ResHisto;
00101     TH1* NormResHisto;
00102     TH1* ResYHisto;
00103     /* TH1* NormResYHisto; */
00104     TH1* ResXprimeHisto;
00105     TH1* NormResXprimeHisto;
00106     TH1* ResYprimeHisto;
00107     TH1* NormResYprimeHisto;
00108 
00109     TProfile* ResXvsXProfile;
00110     TProfile* ResXvsYProfile;
00111     TProfile* ResYvsXProfile;
00112     TProfile* ResYvsYProfile;
00113 
00114     TH1* LocalX;
00115     TH1* LocalY;
00116   };
00117   
00118   // container struct to organize collection of histogramms during endJob
00119   struct SummaryContainer{
00120     SummaryContainer() : sumXResiduals_(), summaryXResiduals_(), 
00121                          sumNormXResiduals_(), summaryNormXResiduals_(),
00122                          sumYResiduals_(), summaryYResiduals_() ,
00123                          sumNormYResiduals_(), summaryNormYResiduals_() {}
00124     
00125     TH1* sumXResiduals_;
00126     TH1* summaryXResiduals_;
00127     TH1* sumNormXResiduals_;
00128     TH1* summaryNormXResiduals_;
00129     TH1* sumYResiduals_;
00130     TH1* summaryYResiduals_;
00131     TH1* sumNormYResiduals_;
00132     TH1* summaryNormYResiduals_;
00133   };
00134   
00135   
00136   struct DirectoryWrapper{
00137     DirectoryWrapper(const DirectoryWrapper& upDir,const std::string& newDir,
00138                      const std::string& basedir,bool useDqmMode)
00139       : tfd(0),
00140         dqmMode(useDqmMode),
00141         theDbe(0) {
00142       if (newDir.length()!=0){
00143         if(upDir.directoryString.length()!=0)directoryString=upDir.directoryString+"/"+newDir;
00144         else directoryString = newDir;
00145       }
00146       else
00147         directoryString=upDir.directoryString;
00148 
00149       if (!dqmMode){
00150         if (newDir.length()==0) tfd.reset(&(*upDir.tfd));
00151         else
00152           tfd.reset(new TFileDirectory(upDir.tfd->mkdir(newDir)));
00153       }
00154       else {
00155         theDbe=edm::Service<DQMStore>().operator->();
00156       }
00157     }
00158     
00159     DirectoryWrapper(const std::string& newDir,const std::string& basedir,bool useDqmMode)
00160       : tfd(0),
00161         dqmMode(useDqmMode),
00162         theDbe(0) {
00163       if (!dqmMode){
00164         edm::Service<TFileService> fs;
00165         if (newDir.length()==0){
00166           tfd.reset(new TFileDirectory(static_cast<TFileDirectory&>(*fs)));
00167         }
00168         else {
00169           tfd.reset(new TFileDirectory(fs->mkdir(newDir)));
00170           directoryString=newDir;
00171         }
00172       }
00173       else {
00174         if (newDir.length()!=0){
00175           if(basedir.length()!=0)directoryString=basedir+"/"+newDir;
00176           else directoryString = newDir;
00177         }
00178         else directoryString=basedir;
00179         theDbe=edm::Service<DQMStore>().operator->();
00180       }
00181     }
00182     // Generalization of Histogram Booking; allows switch between TFileService and DQMStore
00183     template <typename T> TH1* make(const char* name,const char* title,int nBinX,double minBinX,double maxBinX);
00184     template <typename T> TH1* make(const char* name,const char* title,int nBinX,double *xBins);//variable bin size in x for profile histo 
00185     template <typename T> TH1* make(const char* name,const char* title,int nBinX,double minBinX,double maxBinX,int nBinY,double minBinY,double maxBinY);
00186     template <typename T> TH1* make(const char* name,const char* title,int nBinX,double minBinX,double maxBinX,double minBinY,double maxBinY);  // at present not used
00187     
00188     std::auto_ptr<TFileDirectory> tfd;
00189     std::string directoryString;
00190     const bool dqmMode;
00191     DQMStore* theDbe;
00192   };
00193   
00194   
00195   // 
00196   // ------------- private member function -------------
00197   // 
00198   virtual void analyze(const edm::Event&, const edm::EventSetup&);
00199   virtual void endJob();
00200   
00201   virtual void checkBookHists(const edm::EventSetup& setup);
00202 
00203   void bookGlobalHists(DirectoryWrapper& tfd);
00204   void bookDirHists(DirectoryWrapper& tfd, const Alignable& ali, const AlignableObjectId& aliobjid);
00205   void bookHists(DirectoryWrapper& tfd, const Alignable& ali, align::StructureType type, int i, 
00206                  const AlignableObjectId& aliobjid);
00207  
00208   void collateSummaryHists( DirectoryWrapper& tfd, const Alignable& ali, int i, 
00209                             const AlignableObjectId& aliobjid, 
00210                             std::vector<TrackerOfflineValidation::SummaryContainer>& vLevelProfiles);
00211   
00212   void fillTree(TTree& tree, const std::map<int, TrackerOfflineValidation::ModuleHistos>& moduleHist_, 
00213                 TkOffTreeVariables& treeMem, const TrackerGeometry& tkgeom);
00214   
00215   TrackerOfflineValidation::SummaryContainer bookSummaryHists(DirectoryWrapper& tfd, 
00216                                                               const Alignable& ali, 
00217                                                               align::StructureType type, int i, 
00218                                                               const AlignableObjectId& aliobjid); 
00219 
00220   ModuleHistos& getHistStructFromMap(const DetId& detid); 
00221 
00222   bool isBarrel(uint32_t subDetId);
00223   bool isEndCap(uint32_t subDetId);
00224   bool isPixel(uint32_t subDetId);
00225   bool isDetOrDetUnit(align::StructureType type);
00226 
00227   TH1* bookTH1F(bool isTransient, DirectoryWrapper& tfd, const char* histName, const char* histTitle, 
00228                 int nBinsX, double lowX, double highX);
00229 
00230   TProfile* bookTProfile(bool isTransient, DirectoryWrapper& tfd, const char* histName, const char* histTitle, 
00231                          int nBinsX, double lowX, double highX);
00232 
00233   TProfile* bookTProfile(bool isTransient, DirectoryWrapper& tfd, const char* histName, const char* histTitle, 
00234                          int nBinsX, double lowX, double highX, double lowY, double highY);
00235 
00236   void getBinning(uint32_t subDetId, TrackerOfflineValidation::HistogrammType residualtype, 
00237                   int& nBinsX, double& lowerBoundX, double& upperBoundX);
00238 
00239   void summarizeBinInContainer(int bin, SummaryContainer& targetContainer, 
00240                                SummaryContainer& sourceContainer);
00241 
00242   void summarizeBinInContainer(int bin, uint32_t subDetId, SummaryContainer& targetContainer, 
00243                                ModuleHistos& sourceContainer);
00244 
00245   void setSummaryBin(int bin, TH1* targetHist, TH1* sourceHist);
00246     
00247   float Fwhm(const TH1* hist) const;
00248   std::pair<float,float> fitResiduals(TH1* hist) const; //, float meantmp, float rmstmp);
00249   float getMedian( const TH1* hist) const; 
00250   
00251   // From MillePedeAlignmentMonitor: Get Index for Arbitary vector<class> by name
00252   template <class OBJECT_TYPE> int GetIndex(const std::vector<OBJECT_TYPE*>& vec, const TString& name);
00253   
00254   
00255   // ---------- member data ---------------------------
00256 
00257   const edm::ParameterSet parSet_;
00258   edm::ESHandle<TrackerGeometry> tkGeom_;
00259   const TrackerGeometry *bareTkGeomPtr_; // ugly hack to book hists only once, but check 
00260 
00261   // parameters from cfg to steer
00262   const bool lCoorHistOn_;
00263   const bool moduleLevelHistsTransient_;
00264   const bool moduleLevelProfiles_;
00265   const bool stripYResiduals_;
00266   const bool useFwhm_;
00267   const bool useFit_;
00268   const bool useOverflowForRMS_;
00269   const bool dqmMode_;
00270   const std::string moduleDirectory_;
00271   
00272   // a vector to keep track which pointers should be deleted at the very end
00273   std::vector<TH1*> vDeleteObjects_;
00274 
00275   std::vector<TH1*> vTrackHistos_;
00276   std::vector<TH1*> vTrackProfiles_;
00277   std::vector<TH1*> vTrack2DHistos_;
00278   
00279   std::map<int,TrackerOfflineValidation::ModuleHistos> mPxbResiduals_;
00280   std::map<int,TrackerOfflineValidation::ModuleHistos> mPxeResiduals_;
00281   std::map<int,TrackerOfflineValidation::ModuleHistos> mTibResiduals_;
00282   std::map<int,TrackerOfflineValidation::ModuleHistos> mTidResiduals_;
00283   std::map<int,TrackerOfflineValidation::ModuleHistos> mTobResiduals_;
00284   std::map<int,TrackerOfflineValidation::ModuleHistos> mTecResiduals_;
00285 };
00286 
00287 
00288 //
00289 // constants, enums and typedefs
00290 //
00291 
00292 //
00293 // static data member definitions
00294 //
00295 
00296 template <class OBJECT_TYPE>  
00297 int TrackerOfflineValidation::GetIndex(const std::vector<OBJECT_TYPE*> &vec, const TString &name)
00298 {
00299   int result = 0;
00300   for (typename std::vector<OBJECT_TYPE*>::const_iterator iter = vec.begin(), iterEnd = vec.end();
00301        iter != iterEnd; ++iter, ++result) {
00302     if (*iter && (*iter)->GetName() == name) return result;
00303   }
00304   edm::LogError("Alignment") << "@SUB=TrackerOfflineValidation::GetIndex" << " could not find " << name;
00305   return -1;
00306 }
00307 
00308 
00309 template <> TH1* TrackerOfflineValidation::DirectoryWrapper::make<TH1F>(const char* name,const char* title,int nBinX,double minBinX,double maxBinX){
00310   if(dqmMode){theDbe->setCurrentFolder(directoryString); return theDbe->book1D(name,title,nBinX,minBinX,maxBinX)->getTH1();}
00311   else{return tfd->make<TH1F>(name,title,nBinX,minBinX,maxBinX);}
00312 }
00313 
00314 template <> TH1* TrackerOfflineValidation::DirectoryWrapper::make<TProfile>(const char* name,const char* title,int nBinX,double *xBins){
00315   if(dqmMode){
00316     theDbe->setCurrentFolder(directoryString);
00317     //DQM profile requires y-bins for construction... using TProfile creator by hand...
00318     TProfile *tmpProfile=new TProfile(name,title,nBinX,xBins);
00319     tmpProfile->SetDirectory(0);
00320     return theDbe->bookProfile(name,tmpProfile)->getTH1();
00321   }
00322   else{return tfd->make<TProfile>(name,title,nBinX,xBins);}
00323 }
00324 
00325 template <> TH1* TrackerOfflineValidation::DirectoryWrapper::make<TProfile>(const char* name,const char* title,int nBinX,double minBinX,double maxBinX){
00326   if(dqmMode){
00327     theDbe->setCurrentFolder(directoryString);
00328     //DQM profile requires y-bins for construction... using TProfile creator by hand...
00329     TProfile *tmpProfile=new TProfile(name,title,nBinX,minBinX,maxBinX);
00330     tmpProfile->SetDirectory(0);
00331     return theDbe->bookProfile(name,tmpProfile)->getTH1();
00332   }
00333   else{return tfd->make<TProfile>(name,title,nBinX,minBinX,maxBinX);}
00334 }
00335 
00336 template <> TH1* TrackerOfflineValidation::DirectoryWrapper::make<TProfile>(const char* name ,const char* title,int nbinX,double minX ,double maxX,double minY,double maxY){
00337   if(dqmMode){
00338     theDbe->setCurrentFolder(directoryString);
00339     int dummy(0); // DQMProfile wants Y channels... does not use them!
00340     return (theDbe->bookProfile(name,title,nbinX,minX,maxX,dummy,minY,maxY)->getTH1());
00341   }
00342   else{
00343     return tfd->make<TProfile>(name,title,nbinX,minX,maxX,minY,maxY);
00344   }
00345 }
00346 
00347 template <> TH1* TrackerOfflineValidation::DirectoryWrapper::make<TH2F>(const char* name,const char* title,int nBinX,double minBinX,double maxBinX,int nBinY,double minBinY,double maxBinY){
00348   if(dqmMode){theDbe->setCurrentFolder(directoryString); return theDbe->book2D(name,title,nBinX,minBinX,maxBinX,nBinY,minBinY,maxBinY)->getTH1();}
00349   else{return tfd->make<TH2F>(name,title,nBinX,minBinX,maxBinX,nBinY,minBinY,maxBinY);}
00350 }
00351 
00352 
00353 //
00354 // constructors and destructor
00355 //
00356 TrackerOfflineValidation::TrackerOfflineValidation(const edm::ParameterSet& iConfig)
00357   : parSet_(iConfig), bareTkGeomPtr_(0), lCoorHistOn_(parSet_.getParameter<bool>("localCoorHistosOn")),
00358     moduleLevelHistsTransient_(parSet_.getParameter<bool>("moduleLevelHistsTransient")),
00359     moduleLevelProfiles_(parSet_.getParameter<bool>("moduleLevelProfiles")),
00360     stripYResiduals_(parSet_.getParameter<bool>("stripYResiduals")), 
00361     useFwhm_(parSet_.getParameter<bool>("useFwhm")),
00362     useFit_(parSet_.getParameter<bool>("useFit")),
00363     useOverflowForRMS_(parSet_.getParameter<bool>("useOverflowForRMS")),
00364     dqmMode_(parSet_.getParameter<bool>("useInDqmMode")),
00365     moduleDirectory_(parSet_.getParameter<std::string>("moduleDirectoryInOutput"))
00366 {
00367 }
00368 
00369 
00370 TrackerOfflineValidation::~TrackerOfflineValidation()
00371 {
00372    // do anything here that needs to be done at desctruction time
00373    // (e.g. close files, deallocate resources etc.)
00374   for( std::vector<TH1*>::const_iterator it = vDeleteObjects_.begin(), itEnd = vDeleteObjects_.end(); 
00375        it != itEnd;
00376        ++it) delete *it;
00377 }
00378 
00379 
00380 //
00381 // member functions
00382 //
00383 
00384 
00385 // ------------ method called once each job just before starting event loop  ------------
00386 void
00387 TrackerOfflineValidation::checkBookHists(const edm::EventSetup& es)
00388 {
00389   es.get<TrackerDigiGeometryRecord>().get( tkGeom_ );
00390   const TrackerGeometry *newBareTkGeomPtr = &(*tkGeom_);
00391   if (newBareTkGeomPtr == bareTkGeomPtr_) return; // already booked hists, nothing changed
00392 
00393   if (!bareTkGeomPtr_) { // pointer not yet set: called the first time => book hists
00394     AlignableObjectId aliobjid;
00395     
00396     // construct alignable tracker to get access to alignable hierarchy 
00397     AlignableTracker aliTracker(&(*tkGeom_));
00398     
00399     edm::LogInfo("TrackerOfflineValidation") << "There are " << newBareTkGeomPtr->detIds().size()
00400                                              << " dets in the Geometry record.\n"
00401                                              << "Out of these "<<newBareTkGeomPtr->detUnitIds().size()
00402                                              <<" are detUnits";
00403     
00404     // Book Histogramms for global track quantities
00405     std::string globDir("GlobalTrackVariables");
00406     DirectoryWrapper trackglobal(globDir,moduleDirectory_,dqmMode_);
00407     this->bookGlobalHists(trackglobal);
00408     
00409     // recursively book histogramms on lowest level
00410     DirectoryWrapper tfdw("",moduleDirectory_,dqmMode_);
00411     this->bookDirHists(tfdw, aliTracker, aliobjid);
00412   }
00413   else { // histograms booked, but changed TrackerGeometry?
00414     edm::LogWarning("GeometryChange") << "@SUB=checkBookHists"
00415                                       << "TrackerGeometry changed, but will not re-book hists!";
00416   }
00417   bareTkGeomPtr_ = newBareTkGeomPtr;
00418 }
00419 
00420 
00421 void 
00422 TrackerOfflineValidation::bookGlobalHists(DirectoryWrapper& tfd )
00423 {
00424 
00425   vTrackHistos_.push_back(tfd.make<TH1F>("h_tracketa",
00426                                          "Track #eta;#eta_{Track};Number of Tracks",
00427                                          90,-3.,3.));
00428   vTrackHistos_.push_back(tfd.make<TH1F>("h_trackphi",
00429                                          "Track #phi;#phi_{Track};Number of Tracks",
00430                                          90,-3.15,3.15));
00431   vTrackHistos_.push_back(tfd.make<TH1F>("h_trackNumberOfValidHits",
00432                                          "Track # of valid hits;# of valid hits _{Track};Number of Tracks",
00433                                         40,0.,40.));
00434   vTrackHistos_.push_back(tfd.make<TH1F>("h_trackNumberOfLostHits",
00435                                          "Track # of lost hits;# of lost hits _{Track};Number of Tracks",
00436                                         10,0.,10.));
00437   vTrackHistos_.push_back(tfd.make<TH1F>("h_curvature",
00438                                          "Curvature #kappa;#kappa_{Track};Number of Tracks",
00439                                          100,-.05,.05));
00440   vTrackHistos_.push_back(tfd.make<TH1F>("h_curvature_pos",
00441                                          "Curvature |#kappa| Positive Tracks;|#kappa_{pos Track}|;Number of Tracks",
00442                                          100,.0,.05));
00443   vTrackHistos_.push_back(tfd.make<TH1F>("h_curvature_neg",
00444                                          "Curvature |#kappa| Negative Tracks;|#kappa_{neg Track}|;Number of Tracks",
00445                                          100,.0,.05));
00446   vTrackHistos_.push_back(tfd.make<TH1F>("h_diff_curvature",
00447                                          "Curvature |#kappa| Tracks Difference;|#kappa_{Track}|;# Pos Tracks - # Neg Tracks",
00448                                          100,.0,.05));
00449   vTrackHistos_.push_back(tfd.make<TH1F>("h_chi2",
00450                                          "#chi^{2};#chi^{2}_{Track};Number of Tracks",
00451                                          500,-0.01,500.));
00452   vTrackHistos_.push_back(tfd.make<TH1F>("h_chi2Prob",
00453                                          "#chi^{2} probability;#chi^{2}prob_{Track};Number of Tracks",
00454                                         100,0.0,1.));          
00455   vTrackHistos_.push_back(tfd.make<TH1F>("h_normchi2",
00456                                          "#chi^{2}/ndof;#chi^{2}/ndof;Number of Tracks",
00457                                          100,-0.01,10.));     
00458   vTrackHistos_.push_back(tfd.make<TH1F>("h_pt",
00459                                          "p_{T}^{track};p_{T}^{track} [GeV];Number of Tracks",
00460                                          250,0.,250));           
00461   vTrackHistos_.push_back(tfd.make<TH1F>("h_ptResolution",
00462                                          "#delta{p_{T}/p_{T}^{track}};#delta_{p_{T}/p_{T}^{track}};Number of Tracks",
00463                                          100,0.,0.5));           
00464 
00465   vTrackProfiles_.push_back(tfd.make<TProfile>("p_d0_vs_phi",
00466                                                "Transverse Impact Parameter vs. #phi;#phi_{Track};#LT d_{0} #GT [cm]",
00467                                                100,-3.15,3.15));
00468   vTrackProfiles_.push_back(tfd.make<TProfile>("p_dz_vs_phi",
00469                                                "Longitudinal Impact Parameter vs. #phi;#phi_{Track};#LT d_{z} #GT [cm]",
00470                                                100,-3.15,3.15));
00471   vTrackProfiles_.push_back(tfd.make<TProfile>("p_d0_vs_eta",
00472                                                "Transverse Impact Parameter vs. #eta;#eta_{Track};#LT d_{0} #GT [cm]",
00473                                                100,-3.15,3.15));
00474   vTrackProfiles_.push_back(tfd.make<TProfile>("p_dz_vs_eta",
00475                                                "Longitudinal Impact Parameter vs. #eta;#eta_{Track};#LT d_{z} #GT [cm]",
00476                                                100,-3.15,3.15));
00477   vTrackProfiles_.push_back(tfd.make<TProfile>("p_chi2_vs_phi",
00478                                                "#chi^{2} vs. #phi;#phi_{Track};#LT #chi^{2} #GT",
00479                                                100,-3.15,3.15));
00480   vTrackProfiles_.push_back(tfd.make<TProfile>("p_chi2Prob_vs_phi",
00481                                                "#chi^{2} probablility vs. #phi;#phi_{Track};#LT #chi^{2} probability#GT",
00482                                                100,-3.15,3.15));
00483   vTrackProfiles_.push_back(tfd.make<TProfile>("p_chi2Prob_vs_d0",
00484                                                "#chi^{2} probablility vs. |d_{0}|;|d_{0}|[cm];#LT #chi^{2} probability#GT",
00485                                                100,0,80));
00486   vTrackProfiles_.push_back(tfd.make<TProfile>("p_normchi2_vs_phi",
00487                                                "#chi^{2}/ndof vs. #phi;#phi_{Track};#LT #chi^{2}/ndof #GT",
00488                                                100,-3.15,3.15));
00489   vTrackProfiles_.push_back(tfd.make<TProfile>("p_chi2_vs_eta",
00490                                                "#chi^{2} vs. #eta;#eta_{Track};#LT #chi^{2} #GT",
00491                                                100,-3.15,3.15));
00492   //variable binning for chi2/ndof vs. pT
00493   double xBins[19]={0.,0.15,0.5,1.,1.5,2.,2.5,3.,3.5,4.,4.5,5.,7.,10.,15.,25.,40.,100.,200.};
00494   vTrackProfiles_.push_back(tfd.make<TProfile>("p_normchi2_vs_pt",
00495                                                "norm #chi^{2} vs. p_{T}_{Track}; p_{T}_{Track};#LT #chi^{2}/ndof #GT",
00496                                                18,xBins));
00497 
00498   vTrackProfiles_.push_back(tfd.make<TProfile>("p_normchi2_vs_p",
00499                                                "#chi^{2}/ndof vs. p_{Track};p_{Track};#LT #chi^{2}/ndof #GT",
00500                                                 18,xBins));
00501   vTrackProfiles_.push_back(tfd.make<TProfile>("p_chi2Prob_vs_eta",
00502                                                "#chi^{2} probability vs. #eta;#eta_{Track};#LT #chi^{2} probability #GT",
00503                                                100,-3.15,3.15));   
00504   vTrackProfiles_.push_back(tfd.make<TProfile>("p_normchi2_vs_eta",
00505                                                "#chi^{2}/ndof vs. #eta;#eta_{Track};#LT #chi^{2}/ndof #GT",
00506                                                100,-3.15,3.15));
00507   vTrackProfiles_.push_back(tfd.make<TProfile>("p_kappa_vs_phi",
00508                                                "#kappa vs. #phi;#phi_{Track};#kappa",
00509                                                100,-3.15,3.15));
00510   vTrackProfiles_.push_back(tfd.make<TProfile>("p_kappa_vs_eta",
00511                                                "#kappa vs. #eta;#eta_{Track};#kappa",
00512                                                100,-3.15,3.15));
00513   vTrackProfiles_.push_back(tfd.make<TProfile>("p_ptResolution_vs_phi",
00514                                                "#delta_{p_{T}}/p_{T}^{track};#phi^{track};#delta_{p_{T}}/p_{T}^{track}",
00515                                                100, -3.15,3.15));
00516   vTrackProfiles_.push_back(tfd.make<TProfile>("p_ptResolution_vs_eta",
00517                                                "#delta_{p_{T}}/p_{T}^{track};#eta^{track};#delta_{p_{T}}/p_{T}^{track}",
00518                                                100, -3.15,3.15));
00519 
00520   vTrack2DHistos_.push_back(tfd.make<TH2F>("h2_d0_vs_phi",
00521                                            "Transverse Impact Parameter vs. #phi;#phi_{Track};d_{0} [cm]",
00522                                            100, -3.15, 3.15, 100,-1.,1.) );
00523   vTrack2DHistos_.push_back(tfd.make<TH2F>("h2_dz_vs_phi",
00524                                            "Longitudinal Impact Parameter vs. #phi;#phi_{Track};d_{z} [cm]",
00525                                            100, -3.15, 3.15, 100,-100.,100.));
00526   vTrack2DHistos_.push_back(tfd.make<TH2F>("h2_d0_vs_eta",
00527                                            "Transverse Impact Parameter vs. #eta;#eta_{Track};d_{0} [cm]",
00528                                            100, -3.15, 3.15, 100,-1.,1.));
00529   vTrack2DHistos_.push_back(tfd.make<TH2F>("h2_dz_vs_eta",
00530                                            "Longitudinal Impact Parameter vs. #eta;#eta_{Track};d_{z} [cm]",
00531                                            100, -3.15, 3.15, 100,-100.,100.));
00532   vTrack2DHistos_.push_back(tfd.make<TH2F>("h2_chi2_vs_phi",
00533                                            "#chi^{2} vs. #phi;#phi_{Track};#chi^{2}",
00534                                            100, -3.15, 3.15, 500, 0., 500.));
00535   vTrack2DHistos_.push_back(tfd.make<TH2F>("h2_chi2Prob_vs_phi",
00536                                            "#chi^{2} probability vs. #phi;#phi_{Track};#chi^{2} probability",
00537                                            100, -3.15, 3.15, 100, 0., 1.));
00538   vTrack2DHistos_.push_back(tfd.make<TH2F>("h2_chi2Prob_vs_d0",
00539                                            "#chi^{2} probability vs. |d_{0}|;|d_{0}| [cm];#chi^{2} probability",
00540                                            100, 0, 80, 100, 0., 1.));
00541   vTrack2DHistos_.push_back(tfd.make<TH2F>("h2_normchi2_vs_phi",
00542                                            "#chi^{2}/ndof vs. #phi;#phi_{Track};#chi^{2}/ndof",
00543                                            100, -3.15, 3.15, 100, 0., 10.));
00544   vTrack2DHistos_.push_back(tfd.make<TH2F>("h2_chi2_vs_eta",
00545                                            "#chi^{2} vs. #eta;#eta_{Track};#chi^{2}",
00546                                            100, -3.15, 3.15, 500, 0., 500.));  
00547   vTrack2DHistos_.push_back(tfd.make<TH2F>("h2_chi2Prob_vs_eta",
00548                                            "#chi^{2} probaility vs. #eta;#eta_{Track};#chi^{2} probability",
00549                                            100, -3.15, 3.15, 100, 0., 1.));  
00550   vTrack2DHistos_.push_back(tfd.make<TH2F>("h2_normchi2_vs_eta",
00551                                            "#chi^{2}/ndof vs. #eta;#eta_{Track};#chi^{2}/ndof",
00552                                            100,-3.15,3.15, 100, 0., 10.));
00553   vTrack2DHistos_.push_back(tfd.make<TH2F>("h2_kappa_vs_phi",
00554                                            "#kappa vs. #phi;#phi_{Track};#kappa",
00555                                            100,-3.15,3.15, 100, .0,.05));
00556   vTrack2DHistos_.push_back(tfd.make<TH2F>("h2_kappa_vs_eta",
00557                                            "#kappa vs. #eta;#eta_{Track};#kappa",
00558                                            100,-3.15,3.15, 100, .0,.05));
00559   vTrack2DHistos_.push_back(tfd.make<TH2F>("h2_normchi2_vs_kappa",
00560                                            "#kappa vs. #chi^{2}/ndof;#chi^{2}/ndof;#kappa",
00561                                            100,0.,10, 100,-.03,.03));
00562 
00563   /****************** Definition of 2-D Histos of ResX vs momenta ****************************/
00564   vTrack2DHistos_.push_back(tfd.make<TH2F>("p_vs_resXprime_pixB",
00565                                            "#momentum vs. #resX in pixB;#momentum;#resX",
00566                                            15,0.,15., 200, -0.1,0.1));                     
00567   vTrack2DHistos_.push_back(tfd.make<TH2F>("p_vs_resXprime_pixE",
00568                                            "#momentum vs. #resX in pixE;#momentum;#resX",
00569                                            15,0.,15., 200, -0.1,0.1)); 
00570   vTrack2DHistos_.push_back(tfd.make<TH2F>("p_vs_resXprime_TIB",
00571                                            "#momentum vs. #resX in TIB;#momentum;#resX",
00572                                            15,0.,15., 200, -0.1,0.1)); 
00573   vTrack2DHistos_.push_back(tfd.make<TH2F>("p_vs_resXprime_TID",
00574                                            "#momentum vs. #resX in TID;#momentum;#resX",
00575                                            15,0.,15., 200, -0.1,0.1)); 
00576   vTrack2DHistos_.push_back(tfd.make<TH2F>("p_vs_resXprime_TOB",
00577                                            "#momentum vs. #resX in TOB;#momentum;#resX",
00578                                            15,0.,15., 200, -0.1,0.1));
00579   vTrack2DHistos_.push_back(tfd.make<TH2F>("p_vs_resXprime_TEC",
00580                                            "#momentum vs. #resX in TEC;#momentum;#resX",
00581                                            15,0.,15., 200, -0.1,0.1));  
00582 
00583   /****************** Definition of 2-D Histos of ResY vs momenta ****************************/
00584   vTrack2DHistos_.push_back(tfd.make<TH2F>("p_vs_resYprime_pixB",
00585                                            "#momentum vs. #resY in pixB;#momentum;#resY",
00586                                            15,0.,15., 200, -0.1,0.1));                     
00587   vTrack2DHistos_.push_back(tfd.make<TH2F>("p_vs_resYprime_pixE",
00588                                            "#momentum vs. #resY in pixE;#momentum;#resY",
00589                                            15,0.,15., 200, -0.1,0.1)); 
00590 
00591 }
00592 
00593 
00594 void
00595 TrackerOfflineValidation::bookDirHists(DirectoryWrapper& tfd, const Alignable& ali, const AlignableObjectId& aliobjid)
00596 {
00597   std::vector<Alignable*> alivec(ali.components());
00598   for(int i=0, iEnd = ali.components().size();i < iEnd; ++i) {
00599     std::string structurename  = aliobjid.typeToName((alivec)[i]->alignableObjectId());
00600     LogDebug("TrackerOfflineValidation") << "StructureName = " << structurename;
00601     std::stringstream dirname;
00602     dirname << structurename;
00603     // add no suffix counter to Strip and Pixel, just aesthetics
00604     if (structurename != "Strip" && structurename != "Pixel") dirname << "_" << i+1;
00605 
00606     if (structurename.find("Endcap",0) != std::string::npos ) {
00607       DirectoryWrapper f(tfd,dirname.str(),moduleDirectory_,dqmMode_);
00608       bookHists(f, *(alivec)[i], ali.alignableObjectId() , i, aliobjid);
00609       bookDirHists( f, *(alivec)[i], aliobjid);
00610     } else if( !(this->isDetOrDetUnit( (alivec)[i]->alignableObjectId()) )
00611               || alivec[i]->components().size() > 1) {      
00612       DirectoryWrapper f(tfd,dirname.str(),moduleDirectory_,dqmMode_);
00613       bookHists(tfd, *(alivec)[i], ali.alignableObjectId() , i, aliobjid);
00614       bookDirHists( f, *(alivec)[i], aliobjid);
00615     } else {
00616       bookHists(tfd, *(alivec)[i], ali.alignableObjectId() , i, aliobjid);
00617     }
00618   }
00619 }
00620 
00621 
00622 void 
00623 TrackerOfflineValidation::bookHists(DirectoryWrapper& tfd, const Alignable& ali, align::StructureType type, int i, const AlignableObjectId& aliobjid)
00624 {
00625   TrackerAlignableId aliid;
00626   const DetId id = ali.id();
00627 
00628   // comparing subdetandlayer to subdetIds gives a warning at compile time
00629   // -> subdetandlayer could also be pair<uint,uint> but this has to be adapted
00630   // in AlignableObjId 
00631   std::pair<int,int> subdetandlayer = aliid.typeAndLayerFromDetId(id);
00632 
00633   align::StructureType subtype = align::invalid;
00634   
00635   // are we on or just above det, detunit level respectively?
00636   if (type == align::AlignableDetUnit )subtype = type;
00637   else if( this->isDetOrDetUnit(ali.alignableObjectId()) ) subtype = ali.alignableObjectId();
00638   
00639   // construct histogramm title and name
00640   std::stringstream histoname, histotitle, normhistoname, normhistotitle, 
00641     yhistoname, yhistotitle,
00642     xprimehistoname, xprimehistotitle, normxprimehistoname, normxprimehistotitle,
00643     yprimehistoname, yprimehistotitle, normyprimehistoname, normyprimehistotitle,
00644     localxname, localxtitle, localyname, localytitle,
00645     resxvsxprofilename, resxvsxprofiletitle, resyvsxprofilename, resyvsxprofiletitle,
00646     resxvsyprofilename, resxvsyprofiletitle, resyvsyprofilename, resyvsyprofiletitle; 
00647   
00648   std::string wheel_or_layer;
00649 
00650   if( this->isEndCap(static_cast<uint32_t>(subdetandlayer.first)) ) wheel_or_layer = "_wheel_";
00651   else if ( this->isBarrel(static_cast<uint32_t>(subdetandlayer.first)) ) wheel_or_layer = "_layer_";
00652   else edm::LogWarning("TrackerOfflineValidation") << "@SUB=TrackerOfflineValidation::bookHists" 
00653                                                    << "Unknown subdetid: " <<  subdetandlayer.first;     
00654   
00655   histoname << "h_residuals_subdet_" << subdetandlayer.first 
00656             << wheel_or_layer << subdetandlayer.second << "_module_" << id.rawId();
00657   yhistoname << "h_y_residuals_subdet_" << subdetandlayer.first 
00658              << wheel_or_layer << subdetandlayer.second << "_module_" << id.rawId();
00659   xprimehistoname << "h_xprime_residuals_subdet_" << subdetandlayer.first 
00660                   << wheel_or_layer << subdetandlayer.second << "_module_" << id.rawId();
00661   yprimehistoname << "h_yprime_residuals_subdet_" << subdetandlayer.first 
00662                   << wheel_or_layer << subdetandlayer.second << "_module_" << id.rawId();
00663   normhistoname << "h_normresiduals_subdet_" << subdetandlayer.first 
00664                 << wheel_or_layer << subdetandlayer.second << "_module_" << id.rawId();
00665   normxprimehistoname << "h_normxprimeresiduals_subdet_" << subdetandlayer.first 
00666                       << wheel_or_layer << subdetandlayer.second << "_module_" << id.rawId();
00667   normyprimehistoname << "h_normyprimeresiduals_subdet_" << subdetandlayer.first 
00668                       << wheel_or_layer << subdetandlayer.second << "_module_" << id.rawId();
00669   histotitle << "X Residual for module " << id.rawId() << ";x_{tr} - x_{hit} [cm]";
00670   yhistotitle << "Y Residual for module " << id.rawId() << ";y_{tr} - y_{hit} [cm]";
00671   normhistotitle << "Normalized Residual for module " << id.rawId() << ";x_{tr} - x_{hit}/#sigma";
00672   xprimehistotitle << "X' Residual for module " << id.rawId() << ";(x_{tr} - x_{hit})' [cm]";
00673   normxprimehistotitle << "Normalized X' Residual for module " << id.rawId() << ";(x_{tr} - x_{hit})'/#sigma";
00674   yprimehistotitle << "Y' Residual for module " << id.rawId() << ";(y_{tr} - y_{hit})' [cm]";
00675   normyprimehistotitle << "Normalized Y' Residual for module " << id.rawId() << ";(y_{tr} - y_{hit})'/#sigma";
00676   
00677   if ( moduleLevelProfiles_ ) {
00678     localxname << "h_localx_subdet_" << subdetandlayer.first 
00679                << wheel_or_layer << subdetandlayer.second << "_module_" << id.rawId();
00680     localyname << "h_localy_subdet_" << subdetandlayer.first 
00681                << wheel_or_layer << subdetandlayer.second << "_module_" << id.rawId();
00682     localxtitle << "u local for module " << id.rawId() << "; u_{tr,r}";
00683     localytitle << "v local for module " << id.rawId() << "; v_{tr,r}";
00684 
00685     resxvsxprofilename << "p_residuals_x_vs_x_subdet_" << subdetandlayer.first 
00686                        << wheel_or_layer << subdetandlayer.second << "_module_" << id.rawId();
00687     resyvsxprofilename << "p_residuals_y_vs_x_subdet_" << subdetandlayer.first 
00688                        << wheel_or_layer << subdetandlayer.second << "_module_" << id.rawId();
00689     resxvsyprofilename << "p_residuals_x_vs_y_subdet_" << subdetandlayer.first 
00690                        << wheel_or_layer << subdetandlayer.second << "_module_" << id.rawId();
00691     resyvsyprofilename << "p_residuals_y_vs_y_subdet_" << subdetandlayer.first 
00692                        << wheel_or_layer << subdetandlayer.second << "_module_" << id.rawId();
00693     resxvsxprofiletitle << "U Residual vs u for module " << id.rawId() << "; u_{tr,r} ;(u_{tr} - u_{hit})/tan#alpha [cm]";
00694     resyvsxprofiletitle << "V Residual vs u for module " << id.rawId() << "; u_{tr,r} ;(v_{tr} - v_{hit})/tan#beta  [cm]";
00695     resxvsyprofiletitle << "U Residual vs v for module " << id.rawId() << "; v_{tr,r} ;(u_{tr} - u_{hit})/tan#alpha [cm]";
00696     resyvsyprofiletitle << "V Residual vs v for module " << id.rawId() << "; v_{tr,r} ;(v_{tr} - v_{hit})/tan#beta  [cm]";
00697   }
00698   
00699   if( this->isDetOrDetUnit( subtype ) ) {
00700     ModuleHistos &histStruct = this->getHistStructFromMap(id);
00701     int nbins = 0;
00702     double xmin = 0., xmax = 0.;
00703     double ymin = -0.1, ymax = 0.1;
00704 
00705     // do not allow transient hists in DQM mode
00706     bool moduleLevelHistsTransient(moduleLevelHistsTransient_);
00707     if (dqmMode_) moduleLevelHistsTransient = false;
00708     
00709     // decide via cfg if hists in local coordinates should be booked 
00710     if(lCoorHistOn_) {
00711       this->getBinning(id.subdetId(), XResidual, nbins, xmin, xmax);
00712       histStruct.ResHisto = this->bookTH1F(moduleLevelHistsTransient, tfd, 
00713                                            histoname.str().c_str(),histotitle.str().c_str(),                 
00714                                            nbins, xmin, xmax);
00715       this->getBinning(id.subdetId(), NormXResidual, nbins, xmin, xmax);
00716       histStruct.NormResHisto = this->bookTH1F(moduleLevelHistsTransient, tfd,
00717                                                normhistoname.str().c_str(),normhistotitle.str().c_str(),
00718                                                nbins, xmin, xmax);
00719     } 
00720     this->getBinning(id.subdetId(), XprimeResidual, nbins, xmin, xmax);
00721     histStruct.ResXprimeHisto = this->bookTH1F(moduleLevelHistsTransient, tfd, 
00722                                                xprimehistoname.str().c_str(),xprimehistotitle.str().c_str(),
00723                                                nbins, xmin, xmax);
00724     this->getBinning(id.subdetId(), NormXprimeResidual, nbins, xmin, xmax);
00725     histStruct.NormResXprimeHisto = this->bookTH1F(moduleLevelHistsTransient, tfd, 
00726                                                    normxprimehistoname.str().c_str(),normxprimehistotitle.str().c_str(),
00727                                                    nbins, xmin, xmax);
00728 
00729     if ( moduleLevelProfiles_ ) {
00730       this->getBinning(id.subdetId(), XResidualProfile, nbins, xmin, xmax);      
00731 
00732       histStruct.LocalX = this->bookTH1F(moduleLevelHistsTransient, tfd,
00733                                          localxname.str().c_str(),localxtitle.str().c_str(),
00734                                          nbins, xmin, xmax);
00735       histStruct.LocalY = this->bookTH1F(moduleLevelHistsTransient, tfd,
00736                                          localyname.str().c_str(),localytitle.str().c_str(),
00737                                          nbins, xmin, xmax);
00738       histStruct.ResXvsXProfile = this->bookTProfile(moduleLevelHistsTransient, tfd,
00739                                                      resxvsxprofilename.str().c_str(),resxvsxprofiletitle.str().c_str(),
00740                                                      nbins, xmin, xmax, ymin, ymax);
00741       histStruct.ResXvsYProfile = this->bookTProfile(moduleLevelHistsTransient, tfd,
00742                                                      resxvsyprofilename.str().c_str(),resxvsyprofiletitle.str().c_str(),
00743                                                      nbins, xmin, xmax, ymin, ymax);
00744     }
00745 
00746     if( this->isPixel(subdetandlayer.first) || stripYResiduals_ ) {
00747       this->getBinning(id.subdetId(), YprimeResidual, nbins, xmin, xmax);
00748       histStruct.ResYprimeHisto = this->bookTH1F(moduleLevelHistsTransient, tfd,
00749                                                  yprimehistoname.str().c_str(),yprimehistotitle.str().c_str(),
00750                                                  nbins, xmin, xmax);
00751       if (lCoorHistOn_) { // un-primed y-residual
00752         this->getBinning(id.subdetId(), YResidual, nbins, xmin, xmax);
00753         histStruct.ResYHisto = this->bookTH1F(moduleLevelHistsTransient, tfd, 
00754                                               yhistoname.str().c_str(), yhistotitle.str().c_str(),
00755                                               nbins, xmin, xmax);
00756       }
00757       this->getBinning(id.subdetId(), NormYprimeResidual, nbins, xmin, xmax);
00758       histStruct.NormResYprimeHisto = this->bookTH1F(moduleLevelHistsTransient, tfd, 
00759                                                      normyprimehistoname.str().c_str(),normyprimehistotitle.str().c_str(),
00760                                                      nbins, xmin, xmax);
00761       // Here we could add un-primed normalised y-residuals if(lCoorHistOn_)...
00762       if ( moduleLevelProfiles_ ) {
00763         this->getBinning(id.subdetId(), YResidualProfile, nbins, xmin, xmax);      
00764         
00765         histStruct.ResYvsXProfile = this->bookTProfile(moduleLevelHistsTransient, tfd,
00766                                                        resyvsxprofilename.str().c_str(),resyvsxprofiletitle.str().c_str(),
00767                                                        nbins, xmin, xmax, ymin, ymax);
00768         histStruct.ResYvsYProfile = this->bookTProfile(moduleLevelHistsTransient, tfd,
00769                                                        resyvsyprofilename.str().c_str(),resyvsyprofiletitle.str().c_str(),
00770                                                        nbins, xmin, xmax, ymin, ymax);
00771       }
00772     }
00773   }
00774 }
00775 
00776 
00777 TH1* TrackerOfflineValidation::bookTH1F(bool isTransient, DirectoryWrapper& tfd, const char* histName, const char* histTitle, 
00778                                         int nBinsX, double lowX, double highX)
00779 {
00780   if (isTransient) {
00781     vDeleteObjects_.push_back(new TH1F(histName, histTitle, nBinsX, lowX, highX));
00782     return vDeleteObjects_.back(); // return last element of vector
00783   } 
00784   else
00785     return tfd.make<TH1F>(histName, histTitle, nBinsX, lowX, highX);
00786 }
00787 
00788 TProfile* TrackerOfflineValidation::bookTProfile(bool isTransient, DirectoryWrapper& tfd, const char* histName, const char* histTitle, 
00789                                                  int nBinsX, double lowX, double highX)
00790 {
00791   if (isTransient) {
00792     TProfile * profile = new TProfile(histName, histTitle, nBinsX, lowX, highX);
00793     vDeleteObjects_.push_back(profile);
00794     return profile;
00795   }
00796   else
00797     return (TProfile*)tfd.make<TProfile>(histName, histTitle, nBinsX, lowX, highX);
00798 }
00799 
00800 
00801 TProfile* TrackerOfflineValidation::bookTProfile(bool isTransient, DirectoryWrapper& tfd, const char* histName, const char* histTitle, 
00802                                                  int nBinsX, double lowX, double highX, double lowY, double highY)
00803 {
00804   if (isTransient) {
00805     TProfile * profile = new TProfile(histName, histTitle, nBinsX, lowX, highX, lowY, highY);
00806     vDeleteObjects_.push_back(profile);
00807     return profile;
00808   }
00809   else
00810     return (TProfile*)tfd.make<TProfile>(histName, histTitle, nBinsX, lowX, highX, lowY, highY);
00811 }
00812 
00813 bool TrackerOfflineValidation::isBarrel(uint32_t subDetId)
00814 {
00815   return (subDetId == StripSubdetector::TIB ||
00816           subDetId == StripSubdetector::TOB ||
00817           subDetId == PixelSubdetector::PixelBarrel );
00818 }
00819 
00820 
00821 bool TrackerOfflineValidation::isEndCap(uint32_t subDetId)
00822 {
00823   return ( subDetId == StripSubdetector::TID ||
00824            subDetId == StripSubdetector::TEC ||
00825            subDetId == PixelSubdetector::PixelEndcap );
00826 }
00827 
00828 
00829 bool TrackerOfflineValidation::isPixel(uint32_t subDetId)
00830 {
00831   return (subDetId == PixelSubdetector::PixelBarrel ||
00832           subDetId == PixelSubdetector::PixelEndcap );
00833 }
00834 
00835 
00836 bool TrackerOfflineValidation::isDetOrDetUnit(align::StructureType type)
00837 {
00838   return ( type == align::AlignableDet ||
00839            type == align::AlignableDetUnit );
00840 }
00841 
00842 
00843 void 
00844 TrackerOfflineValidation::getBinning(uint32_t subDetId, 
00845                                      TrackerOfflineValidation::HistogrammType residualType, 
00846                                      int& nBinsX, double& lowerBoundX, double& upperBoundX)
00847 {
00848   // determine if 
00849   const bool isPixel = this->isPixel(subDetId);
00850   
00851   edm::ParameterSet binningPSet;
00852   
00853   switch(residualType) 
00854     {
00855     case XResidual :
00856       if(isPixel) binningPSet = parSet_.getParameter<edm::ParameterSet>("TH1XResPixelModules");                
00857       else binningPSet        = parSet_.getParameter<edm::ParameterSet>("TH1XResStripModules");                
00858       break;
00859     case NormXResidual : 
00860       if(isPixel) binningPSet = parSet_.getParameter<edm::ParameterSet>("TH1NormXResPixelModules");             
00861       else binningPSet        = parSet_.getParameter<edm::ParameterSet>("TH1NormXResStripModules");                
00862       break;
00863     case XprimeResidual :
00864       if(isPixel) binningPSet = parSet_.getParameter<edm::ParameterSet>("TH1XprimeResPixelModules");                
00865       else binningPSet        = parSet_.getParameter<edm::ParameterSet>("TH1XprimeResStripModules");                
00866       break;
00867     case NormXprimeResidual :
00868       if(isPixel) binningPSet = parSet_.getParameter<edm::ParameterSet>("TH1NormXprimeResPixelModules");
00869       else binningPSet        = parSet_.getParameter<edm::ParameterSet>("TH1NormXprimeResStripModules");
00870       break;
00871     case YResidual : // borrow y-residual binning from yprime
00872     case YprimeResidual :
00873       if(isPixel) binningPSet = parSet_.getParameter<edm::ParameterSet>("TH1YResPixelModules");                
00874       else binningPSet        = parSet_.getParameter<edm::ParameterSet>("TH1YResStripModules");                
00875       break; 
00876       /* case NormYResidual :*/
00877     case NormYprimeResidual :
00878       if(isPixel) binningPSet = parSet_.getParameter<edm::ParameterSet>("TH1NormYResPixelModules");             
00879       else binningPSet        = parSet_.getParameter<edm::ParameterSet>("TH1NormYResStripModules");  
00880       break;
00881     case XResidualProfile :
00882       if(isPixel) binningPSet = parSet_.getParameter<edm::ParameterSet>("TProfileXResPixelModules");                
00883       else binningPSet        = parSet_.getParameter<edm::ParameterSet>("TProfileXResStripModules");                
00884       break;
00885     case YResidualProfile :
00886       if(isPixel) binningPSet = parSet_.getParameter<edm::ParameterSet>("TProfileYResPixelModules");                
00887       else binningPSet        = parSet_.getParameter<edm::ParameterSet>("TProfileYResStripModules");                
00888       break;
00889     }
00890   nBinsX      = binningPSet.getParameter<int32_t>("Nbinx");                    
00891   lowerBoundX = binningPSet.getParameter<double>("xmin");                      
00892   upperBoundX = binningPSet.getParameter<double>("xmax");     
00893 }
00894 
00895 
00896 void 
00897 TrackerOfflineValidation::setSummaryBin(int bin, TH1* targetHist, TH1* sourceHist)
00898 {
00899   if(targetHist && sourceHist) {
00900     targetHist->SetBinContent(bin, sourceHist->GetMean(1));
00901     if(useFwhm_) targetHist->SetBinError(bin, Fwhm(sourceHist)/2.);
00902     else targetHist->SetBinError(bin, sourceHist->GetRMS(1) );
00903   }
00904   else return;
00905 }
00906 
00907 
00908 void 
00909 TrackerOfflineValidation::summarizeBinInContainer( int bin, SummaryContainer& targetContainer, 
00910                                                    SummaryContainer& sourceContainer)
00911 {
00912   this->setSummaryBin(bin, targetContainer.summaryXResiduals_, sourceContainer.sumXResiduals_);
00913   this->setSummaryBin(bin, targetContainer.summaryNormXResiduals_, sourceContainer.sumNormXResiduals_);
00914   // If no y-residual hists, just returns:
00915   this->setSummaryBin(bin, targetContainer.summaryYResiduals_, sourceContainer.sumYResiduals_);
00916   this->setSummaryBin(bin, targetContainer.summaryNormYResiduals_, sourceContainer.sumNormYResiduals_);
00917 }
00918 
00919 
00920 void 
00921 TrackerOfflineValidation::summarizeBinInContainer( int bin, uint32_t subDetId, 
00922                                                    SummaryContainer& targetContainer, 
00923                                                    ModuleHistos& sourceContainer)
00924 {
00925   // takes two summary Containers and sets summaryBins for all histograms
00926   this->setSummaryBin(bin, targetContainer.summaryXResiduals_, sourceContainer.ResXprimeHisto);
00927   this->setSummaryBin(bin, targetContainer.summaryNormXResiduals_, sourceContainer.NormResXprimeHisto);
00928   if( this->isPixel(subDetId) || stripYResiduals_ ) {
00929     this->setSummaryBin(bin, targetContainer.summaryYResiduals_, sourceContainer.ResYprimeHisto);
00930     this->setSummaryBin(bin, targetContainer.summaryNormYResiduals_, sourceContainer.NormResYprimeHisto);
00931   }
00932 }
00933 
00934 
00935 TrackerOfflineValidation::ModuleHistos& 
00936 TrackerOfflineValidation::getHistStructFromMap(const DetId& detid)
00937 {
00938   // get a struct with histograms from the respective map
00939   // if no object exist, the reference is automatically created by the map
00940   // throw exception if non-tracker id is passed
00941   uint subdetid = detid.subdetId();
00942   if(subdetid == PixelSubdetector::PixelBarrel ) {
00943     return mPxbResiduals_[detid.rawId()];
00944   } else if (subdetid == PixelSubdetector::PixelEndcap) {
00945     return mPxeResiduals_[detid.rawId()];
00946   } else if(subdetid  == StripSubdetector::TIB) {
00947     return mTibResiduals_[detid.rawId()];
00948   } else if(subdetid  == StripSubdetector::TID) {
00949     return mTidResiduals_[detid.rawId()];
00950   } else if(subdetid  == StripSubdetector::TOB) {
00951     return mTobResiduals_[detid.rawId()];
00952   } else if(subdetid  == StripSubdetector::TEC) {
00953     return mTecResiduals_[detid.rawId()];
00954   } else {
00955     throw cms::Exception("Geometry Error")
00956       << "[TrackerOfflineValidation] Error, tried to get reference for non-tracker subdet " << subdetid 
00957       << " from detector " << detid.det();
00958     return mPxbResiduals_[0];
00959   }
00960 }
00961 
00962 
00963 // ------------ method called to for each event  ------------
00964 void
00965 TrackerOfflineValidation::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup)
00966 {
00967   if (useOverflowForRMS_)TH1::StatOverflows(kTRUE);
00968   this->checkBookHists(iSetup); // check whether hists are booked and do so if not yet done
00969   
00970   TrackerValidationVariables avalidator_(iSetup,parSet_);
00971     
00972   std::vector<TrackerValidationVariables::AVTrackStruct> vTrackstruct;
00973   avalidator_.fillTrackQuantities(iEvent, vTrackstruct);
00974   
00975   for (std::vector<TrackerValidationVariables::AVTrackStruct>::const_iterator itT = vTrackstruct.begin();        
00976        itT != vTrackstruct.end();
00977        ++itT) {
00978     
00979     // Fill 1D track histos
00980     static const int etaindex = this->GetIndex(vTrackHistos_,"h_tracketa");
00981     vTrackHistos_[etaindex]->Fill(itT->eta);
00982     static const int phiindex = this->GetIndex(vTrackHistos_,"h_trackphi");
00983     vTrackHistos_[phiindex]->Fill(itT->phi);
00984     static const int numOfValidHitsindex = this->GetIndex(vTrackHistos_,"h_trackNumberOfValidHits");
00985     vTrackHistos_[numOfValidHitsindex]->Fill(itT->numberOfValidHits);
00986     static const int numOfLostHitsindex = this->GetIndex(vTrackHistos_,"h_trackNumberOfLostHits");
00987     vTrackHistos_[numOfLostHitsindex]->Fill(itT->numberOfLostHits);
00988     static const int kappaindex = this->GetIndex(vTrackHistos_,"h_curvature");
00989     vTrackHistos_[kappaindex]->Fill(itT->kappa);
00990     static const int kappaposindex = this->GetIndex(vTrackHistos_,"h_curvature_pos");
00991     if (itT->charge > 0)
00992       vTrackHistos_[kappaposindex]->Fill(fabs(itT->kappa));
00993     static const int kappanegindex = this->GetIndex(vTrackHistos_,"h_curvature_neg");
00994     if (itT->charge < 0)
00995       vTrackHistos_[kappanegindex]->Fill(fabs(itT->kappa));
00996     static const int normchi2index = this->GetIndex(vTrackHistos_,"h_normchi2");
00997     vTrackHistos_[normchi2index]->Fill(itT->normchi2);
00998     static const int chi2index = this->GetIndex(vTrackHistos_,"h_chi2");
00999     vTrackHistos_[chi2index]->Fill(itT->chi2);
01000     static const int chi2Probindex = this->GetIndex(vTrackHistos_,"h_chi2Prob");
01001     vTrackHistos_[chi2Probindex]->Fill(itT->chi2Prob);
01002     static const int ptindex = this->GetIndex(vTrackHistos_,"h_pt");
01003     vTrackHistos_[ptindex]->Fill(itT->pt);
01004     if (itT->ptError != 0.) {
01005       static const int ptResolutionindex = this->GetIndex(vTrackHistos_,"h_ptResolution");
01006       vTrackHistos_[ptResolutionindex]->Fill(itT->ptError/itT->pt);
01007     }
01008     // Fill track profiles
01009     static const int d0phiindex = this->GetIndex(vTrackProfiles_,"p_d0_vs_phi");
01010     vTrackProfiles_[d0phiindex]->Fill(itT->phi,itT->d0);
01011     static const int dzphiindex = this->GetIndex(vTrackProfiles_,"p_dz_vs_phi");
01012     vTrackProfiles_[dzphiindex]->Fill(itT->phi,itT->dz);
01013     static const int d0etaindex = this->GetIndex(vTrackProfiles_,"p_d0_vs_eta");
01014     vTrackProfiles_[d0etaindex]->Fill(itT->eta,itT->d0);
01015     static const int dzetaindex = this->GetIndex(vTrackProfiles_,"p_dz_vs_eta");
01016     vTrackProfiles_[dzetaindex]->Fill(itT->eta,itT->dz);
01017     static const int chiphiindex = this->GetIndex(vTrackProfiles_,"p_chi2_vs_phi");
01018     vTrackProfiles_[chiphiindex]->Fill(itT->phi,itT->chi2);
01019     static const int chiProbphiindex = this->GetIndex(vTrackProfiles_,"p_chi2Prob_vs_phi");
01020     vTrackProfiles_[chiProbphiindex]->Fill(itT->phi,itT->chi2Prob);
01021     static const int chiProbabsd0index = this->GetIndex(vTrackProfiles_,"p_chi2Prob_vs_d0");
01022     vTrackProfiles_[chiProbabsd0index]->Fill(fabs(itT->d0),itT->chi2Prob);
01023     static const int normchiphiindex = this->GetIndex(vTrackProfiles_,"p_normchi2_vs_phi");
01024     vTrackProfiles_[normchiphiindex]->Fill(itT->phi,itT->normchi2);
01025     static const int chietaindex = this->GetIndex(vTrackProfiles_,"p_chi2_vs_eta");
01026     vTrackProfiles_[chietaindex]->Fill(itT->eta,itT->chi2);
01027     static const int normchiptindex = this->GetIndex(vTrackProfiles_,"p_normchi2_vs_pt");
01028     vTrackProfiles_[normchiptindex]->Fill(itT->pt,itT->normchi2);
01029     static const int normchipindex = this->GetIndex(vTrackProfiles_,"p_normchi2_vs_p");
01030     vTrackProfiles_[normchipindex]->Fill(itT->p,itT->normchi2);
01031     static const int chiProbetaindex = this->GetIndex(vTrackProfiles_,"p_chi2Prob_vs_eta");
01032     vTrackProfiles_[chiProbetaindex]->Fill(itT->eta,itT->chi2Prob);
01033     static const int normchietaindex = this->GetIndex(vTrackProfiles_,"p_normchi2_vs_eta");
01034     vTrackProfiles_[normchietaindex]->Fill(itT->eta,itT->normchi2);
01035     static const int kappaphiindex = this->GetIndex(vTrackProfiles_,"p_kappa_vs_phi");
01036     vTrackProfiles_[kappaphiindex]->Fill(itT->phi,itT->kappa);
01037     static const int kappaetaindex = this->GetIndex(vTrackProfiles_,"p_kappa_vs_eta");
01038     vTrackProfiles_[kappaetaindex]->Fill(itT->eta,itT->kappa);
01039     static const int ptResphiindex = this->GetIndex(vTrackProfiles_,"p_ptResolution_vs_phi");
01040     vTrackProfiles_[ptResphiindex]->Fill(itT->phi,itT->ptError/itT->pt);
01041     static const int ptResetaindex = this->GetIndex(vTrackProfiles_,"p_ptResolution_vs_eta");
01042     vTrackProfiles_[ptResetaindex]->Fill(itT->eta,itT->ptError/itT->pt);
01043 
01044     // Fill 2D track histos
01045     static const int d0phiindex_2d = this->GetIndex(vTrack2DHistos_,"h2_d0_vs_phi");
01046     vTrack2DHistos_[d0phiindex_2d]->Fill(itT->phi,itT->d0);
01047     static const int dzphiindex_2d = this->GetIndex(vTrack2DHistos_,"h2_dz_vs_phi");
01048     vTrack2DHistos_[dzphiindex_2d]->Fill(itT->phi,itT->dz);
01049     static const int d0etaindex_2d = this->GetIndex(vTrack2DHistos_,"h2_d0_vs_eta");
01050     vTrack2DHistos_[d0etaindex_2d]->Fill(itT->eta,itT->d0);
01051     static const int dzetaindex_2d = this->GetIndex(vTrack2DHistos_,"h2_dz_vs_eta");
01052     vTrack2DHistos_[dzetaindex_2d]->Fill(itT->eta,itT->dz);
01053     static const int chiphiindex_2d = this->GetIndex(vTrack2DHistos_,"h2_chi2_vs_phi");
01054     vTrack2DHistos_[chiphiindex_2d]->Fill(itT->phi,itT->chi2);
01055     static const int chiProbphiindex_2d = this->GetIndex(vTrack2DHistos_,"h2_chi2Prob_vs_phi");
01056     vTrack2DHistos_[chiProbphiindex_2d]->Fill(itT->phi,itT->chi2Prob);
01057     static const int chiProbabsd0index_2d = this->GetIndex(vTrack2DHistos_,"h2_chi2Prob_vs_d0");
01058     vTrack2DHistos_[chiProbabsd0index_2d]->Fill(fabs(itT->d0),itT->chi2Prob);
01059     static const int normchiphiindex_2d = this->GetIndex(vTrack2DHistos_,"h2_normchi2_vs_phi");
01060     vTrack2DHistos_[normchiphiindex_2d]->Fill(itT->phi,itT->normchi2);
01061     static const int chietaindex_2d = this->GetIndex(vTrack2DHistos_,"h2_chi2_vs_eta");
01062     vTrack2DHistos_[chietaindex_2d]->Fill(itT->eta,itT->chi2);
01063     static const int chiProbetaindex_2d = this->GetIndex(vTrack2DHistos_,"h2_chi2Prob_vs_eta");
01064     vTrack2DHistos_[chiProbetaindex_2d]->Fill(itT->eta,itT->chi2Prob);
01065     static const int normchietaindex_2d = this->GetIndex(vTrack2DHistos_,"h2_normchi2_vs_eta");
01066     vTrack2DHistos_[normchietaindex_2d]->Fill(itT->eta,itT->normchi2);
01067     static const int kappaphiindex_2d = this->GetIndex(vTrack2DHistos_,"h2_kappa_vs_phi");
01068     vTrack2DHistos_[kappaphiindex_2d]->Fill(itT->phi,itT->kappa);
01069     static const int kappaetaindex_2d = this->GetIndex(vTrack2DHistos_,"h2_kappa_vs_eta");
01070     vTrack2DHistos_[kappaetaindex_2d]->Fill(itT->eta,itT->kappa);
01071     static const int normchi2kappa_2d = this->GetIndex(vTrack2DHistos_,"h2_normchi2_vs_kappa");
01072     vTrack2DHistos_[normchi2kappa_2d]->Fill(itT->normchi2,itT->kappa);
01073 
01074     // hit quantities: residuals, normalized residuals
01075     for (std::vector<TrackerValidationVariables::AVHitStruct>::const_iterator itH = itT->hits.begin();
01076          itH != itT->hits.end();
01077          ++itH) {
01078       
01079       DetId detid(itH->rawDetId);
01080       ModuleHistos &histStruct = this->getHistStructFromMap(detid);
01081 
01082       // fill histos in local coordinates if set in cf
01083       if (lCoorHistOn_) {
01084         histStruct.ResHisto->Fill(itH->resX);
01085         if(itH->resErrX != 0) histStruct.NormResHisto->Fill(itH->resX/itH->resErrX);
01086         if (this->isPixel(detid.subdetId()) || stripYResiduals_ ) {
01087           histStruct.ResYHisto->Fill(itH->resY);
01088           // here add un-primed normalised y-residuals if wanted
01089         }
01090       }
01091       if (itH->resXprime != -999.) {
01092         histStruct.ResXprimeHisto->Fill(itH->resXprime);
01093 
01094         /******************************* Fill 2-D histo ResX vs momenta *****************************/
01095         if (detid.subdetId() == PixelSubdetector::PixelBarrel) { 
01096           static const int resXvsPindex_2d = this->GetIndex(vTrack2DHistos_,"p_vs_resXprime_pixB");
01097           vTrack2DHistos_[resXvsPindex_2d]->Fill(itT->p,itH->resXprime);
01098         }       
01099         if (detid.subdetId() == PixelSubdetector::PixelEndcap) { 
01100           static const int resXvsPindex_2d = this->GetIndex(vTrack2DHistos_,"p_vs_resXprime_pixE");
01101           vTrack2DHistos_[resXvsPindex_2d]->Fill(itT->p,itH->resXprime);
01102         }
01103         if (detid.subdetId() == StripSubdetector::TIB) { 
01104           static const int resXvsPindex_2d = this->GetIndex(vTrack2DHistos_,"p_vs_resXprime_TIB");
01105           vTrack2DHistos_[resXvsPindex_2d]->Fill(itT->p,itH->resXprime);
01106         }
01107         if (detid.subdetId() == StripSubdetector::TID) { 
01108           static const int resXvsPindex_2d = this->GetIndex(vTrack2DHistos_,"p_vs_resXprime_TID");
01109           vTrack2DHistos_[resXvsPindex_2d]->Fill(itT->p,itH->resXprime);
01110         }
01111         if (detid.subdetId() == StripSubdetector::TOB) { 
01112           static const int resXvsPindex_2d = this->GetIndex(vTrack2DHistos_,"p_vs_resXprime_TOB");
01113           vTrack2DHistos_[resXvsPindex_2d]->Fill(itT->p,itH->resXprime);
01114         }
01115         if (detid.subdetId() == StripSubdetector::TEC) {   
01116           static const int resXvsPindex_2d = this->GetIndex(vTrack2DHistos_,"p_vs_resXprime_TEC");
01117           vTrack2DHistos_[resXvsPindex_2d]->Fill(itT->p,itH->resXprime);
01118         }
01119         /******************************************/
01120 
01121         if ( moduleLevelProfiles_ && itH->inside ) {
01122           float tgalpha = tan(itH->localAlpha);
01123           if ( fabs(tgalpha)!=0 ){
01124             histStruct.LocalX->Fill(itH->localXnorm, tgalpha*tgalpha); 
01125             histStruct.LocalY->Fill(itH->localYnorm, tgalpha*tgalpha); 
01126 /*           if (this->isEndCap(detid.subdetId()) && !this->isPixel(detid.subdetId())) {
01127              if((itH->resX)*(itH->resXprime)>0){
01128             histStruct.ResXvsXProfile->Fill(itH->localXnorm, itH->resXatTrkY/tgalpha, tgalpha*tgalpha);
01129             histStruct.ResXvsYProfile->Fill(itH->localYnorm, itH->resXatTrkY/tgalpha, tgalpha*tgalpha);
01130              } else {
01131             histStruct.ResXvsXProfile->Fill(itH->localXnorm, (-1)*itH->resXatTrkY/tgalpha, tgalpha*tgalpha);
01132             histStruct.ResXvsYProfile->Fill(itH->localYnorm, (-1)*itH->resXatTrkY/tgalpha, tgalpha*tgalpha);
01133                }
01134 
01135           }else {  
01136 */
01137             histStruct.ResXvsXProfile->Fill(itH->localXnorm, itH->resXatTrkY/tgalpha, tgalpha*tgalpha); 
01138             histStruct.ResXvsYProfile->Fill(itH->localYnorm, itH->resXatTrkY/tgalpha, tgalpha*tgalpha); 
01139 
01140 //          }
01141 
01142           }
01143         }
01144 
01145         if(itH->resXprimeErr != 0 && itH->resXprimeErr != -999 ) {      
01146           histStruct.NormResXprimeHisto->Fill(itH->resXprime/itH->resXprimeErr);
01147         }
01148       }     
01149       
01150       if (itH->resYprime != -999.) {
01151         if (this->isPixel(detid.subdetId()) || stripYResiduals_ ) {
01152           histStruct.ResYprimeHisto->Fill(itH->resYprime);
01153 
01154           /******************************* Fill 2-D histo ResY vs momenta *****************************/
01155           if (detid.subdetId() == PixelSubdetector::PixelBarrel) { 
01156             static const int resYvsPindex_2d = this->GetIndex(vTrack2DHistos_,"p_vs_resYprime_pixB");
01157             vTrack2DHistos_[resYvsPindex_2d]->Fill(itT->p,itH->resYprime);
01158           }     
01159           if (detid.subdetId() == PixelSubdetector::PixelEndcap) { 
01160             static const int resYvsPindex_2d = this->GetIndex(vTrack2DHistos_,"p_vs_resYprime_pixE");
01161             vTrack2DHistos_[resYvsPindex_2d]->Fill(itT->p,itH->resYprime);
01162           }
01163           /******************************************/
01164 
01165           if ( moduleLevelProfiles_ && itH->inside ) {
01166             float tgbeta = tan(itH->localBeta);
01167             if ( fabs(tgbeta)!=0 ){
01168 /*           if (this->isEndCap(detid.subdetId()) && !this->isPixel(detid.subdetId())) {
01169             
01170             if((itH->resY)*(itH->resYprime)>0){
01171             histStruct.ResYvsXProfile->Fill(itH->localXnorm, itH->resYprime/tgbeta, tgbeta*tgbeta);
01172             histStruct.ResYvsYProfile->Fill(itH->localYnorm, itH->resYprime/tgbeta, tgbeta*tgbeta);
01173              } else {
01174             histStruct.ResYvsXProfile->Fill(itH->localXnorm, (-1)*itH->resYprime/tgbeta, tgbeta*tgbeta);
01175             histStruct.ResYvsYProfile->Fill(itH->localYnorm, (-1)*itH->resYprime/tgbeta, tgbeta*tgbeta);
01176                }
01177 
01178           }else {  
01179 */
01180               histStruct.ResYvsXProfile->Fill(itH->localXnorm, itH->resY/tgbeta, tgbeta*tgbeta); 
01181               histStruct.ResYvsYProfile->Fill(itH->localYnorm, itH->resY/tgbeta, tgbeta*tgbeta); 
01182 //              }
01183             }
01184           }
01185 
01186           if (itH->resYprimeErr != 0 && itH->resYprimeErr != -999. ) {  
01187             histStruct.NormResYprimeHisto->Fill(itH->resYprime/itH->resYprimeErr);
01188           } 
01189         }
01190       }
01191       
01192     } // finish loop over hit quantities
01193   } // finish loop over track quantities
01194 
01195   if (useOverflowForRMS_) TH1::StatOverflows(kFALSE);  
01196 }
01197 
01198 
01199 // ------------ method called once each job just after ending the event loop  ------------
01200 void 
01201 TrackerOfflineValidation::endJob()
01202 {
01203 
01204   if (!tkGeom_.product()) return;
01205 
01206   AlignableTracker aliTracker(&(*tkGeom_));
01207   
01208   AlignableObjectId aliobjid;
01209   
01210   static const int kappadiffindex = this->GetIndex(vTrackHistos_,"h_diff_curvature");
01211   vTrackHistos_[kappadiffindex]->Add(vTrackHistos_[this->GetIndex(vTrackHistos_,"h_curvature_neg")],
01212                                      vTrackHistos_[this->GetIndex(vTrackHistos_,"h_curvature_pos")],-1,1);
01213  
01214   // Collate Information for Subdetectors
01215   // create summary histogramms recursively
01216   std::vector<TrackerOfflineValidation::SummaryContainer> vTrackerprofiles;
01217   DirectoryWrapper f("",moduleDirectory_,dqmMode_);
01218   this->collateSummaryHists(f,(aliTracker), 0, aliobjid, vTrackerprofiles);
01219   
01220   if (dqmMode_) return;
01221   // Should be excluded in dqmMode, since TTree is not usable
01222   // In dqmMode tree operations are are sourced out to the additional module TrackerOfflineValidationSummary
01223   
01224   edm::Service<TFileService> fs;
01225   TTree *tree = fs->make<TTree>("TkOffVal","TkOffVal");
01226  
01227   TkOffTreeVariables *treeMemPtr = new TkOffTreeVariables;
01228   // We create branches for all members of 'TkOffTreeVariables' (even if not needed).
01229   // This works because we have a dictionary for 'TkOffTreeVariables'
01230   // (see src/classes_def.xml and src/classes.h):
01231   tree->Branch("TkOffTreeVariables", &treeMemPtr); // address of pointer!
01232  
01233   this->fillTree(*tree, mPxbResiduals_, *treeMemPtr, *tkGeom_);
01234   this->fillTree(*tree, mPxeResiduals_, *treeMemPtr, *tkGeom_);
01235   this->fillTree(*tree, mTibResiduals_, *treeMemPtr, *tkGeom_);
01236   this->fillTree(*tree, mTidResiduals_, *treeMemPtr, *tkGeom_);
01237   this->fillTree(*tree, mTobResiduals_, *treeMemPtr, *tkGeom_);
01238   this->fillTree(*tree, mTecResiduals_, *treeMemPtr, *tkGeom_);
01239 
01240   delete treeMemPtr; treeMemPtr = 0;
01241 }
01242 
01243 
01244 void
01245 TrackerOfflineValidation::collateSummaryHists( DirectoryWrapper& tfd, const Alignable& ali, int i, 
01246                                                const AlignableObjectId& aliobjid, 
01247                                                std::vector<TrackerOfflineValidation::SummaryContainer>& vLevelProfiles)
01248 {
01249   std::vector<Alignable*> alivec(ali.components());
01250   if( this->isDetOrDetUnit((alivec)[0]->alignableObjectId()) ) return;
01251   
01252   for(int iComp=0, iCompEnd = ali.components().size();iComp < iCompEnd; ++iComp) {
01253     std::vector< TrackerOfflineValidation::SummaryContainer > vProfiles;        
01254     std::string structurename  = aliobjid.typeToName((alivec)[iComp]->alignableObjectId());
01255     
01256     LogDebug("TrackerOfflineValidation") << "StructureName = " << structurename;
01257     std::stringstream dirname;
01258     dirname << structurename;
01259     
01260     // add no suffix counter to strip and pixel -> just aesthetics
01261     if (structurename != "Strip" && structurename != "Pixel") dirname << "_" << iComp+1;
01262     
01263     if(  !(this->isDetOrDetUnit( (alivec)[iComp]->alignableObjectId()) )
01264          || (alivec)[0]->components().size() > 1 ) {
01265       DirectoryWrapper f(tfd,dirname.str(),moduleDirectory_,dqmMode_);
01266       this->collateSummaryHists( f, *(alivec)[iComp], i, aliobjid, vProfiles);
01267       vLevelProfiles.push_back(this->bookSummaryHists(tfd, *(alivec[iComp]), ali.alignableObjectId(), iComp+1, aliobjid));
01268       TH1 *hY = vLevelProfiles[iComp].sumYResiduals_;
01269       TH1 *hNormY = vLevelProfiles[iComp].sumNormYResiduals_;
01270       for(uint n = 0; n < vProfiles.size(); ++n) {
01271         this->summarizeBinInContainer(n+1, vLevelProfiles[iComp], vProfiles[n] );
01272         vLevelProfiles[iComp].sumXResiduals_->Add(vProfiles[n].sumXResiduals_);
01273         vLevelProfiles[iComp].sumNormXResiduals_->Add(vProfiles[n].sumNormXResiduals_);
01274         if (hY)     hY->Add(vProfiles[n].sumYResiduals_);         // only if existing
01275         if (hNormY) hNormY->Add(vProfiles[n].sumNormYResiduals_); // dito (pxl, stripYResiduals_)
01276       }
01277       if(dqmMode_)continue;  // No fits in dqmMode
01278       //add fit values to stat box
01279       this->fitResiduals(vLevelProfiles[iComp].sumXResiduals_);
01280       this->fitResiduals(vLevelProfiles[iComp].sumNormXResiduals_);
01281       if (hY)     this->fitResiduals(hY);     // only if existing (pixel or stripYResiduals_)
01282       if (hNormY) this->fitResiduals(hNormY); // dito
01283     } else {
01284       // nothing to be done for det or detunits
01285       continue;
01286     }
01287   }
01288 }
01289 
01290 
01291 TrackerOfflineValidation::SummaryContainer 
01292 TrackerOfflineValidation::bookSummaryHists(DirectoryWrapper& tfd, const Alignable& ali, 
01293                                            align::StructureType type, int i, 
01294                                            const AlignableObjectId& aliobjid)
01295 {
01296   const uint aliSize = ali.components().size();
01297   const align::StructureType alitype = ali.alignableObjectId();
01298   const align::StructureType subtype = ali.components()[0]->alignableObjectId();
01299   const char *aliTypeName = aliobjid.typeToName(alitype).c_str(); // lifetime of char* OK
01300   const char *aliSubtypeName = aliobjid.typeToName(subtype).c_str();
01301   const char *typeName = aliobjid.typeToName(type).c_str();
01302 
01303   const DetId aliDetId = ali.id(); 
01304   // y residuals only if pixel or specially requested for strip:
01305   const bool bookResidY = this->isPixel(aliDetId.subdetId()) || stripYResiduals_;
01306 
01307   SummaryContainer sumContainer;
01308   
01309   // Book summary hists with one bin per component, 
01310   // but special case for Det with two DetUnit that we want to summarize one level up 
01311   // (e.g. in TOBRods with 12 bins for 6 stereo and 6 rphi DetUnit.)
01312   //    component of ali is not Det or Det with just one components
01313   const uint subcompSize = ali.components()[0]->components().size();
01314   if (subtype != align::AlignableDet || subcompSize == 1) { // Det with 1 comp. should not exist anymore...
01315     const TString title(Form("Summary for substructures in %s %d;%s;",aliTypeName,i,aliSubtypeName));
01316     
01317     sumContainer.summaryXResiduals_ = tfd.make<TH1F>(Form("h_summaryX%s_%d",aliTypeName,i), 
01318                                                      title + "#LT #Delta x' #GT",
01319                                                      aliSize, 0.5, aliSize+0.5);
01320     sumContainer.summaryNormXResiduals_ = tfd.make<TH1F>(Form("h_summaryNormX%s_%d",aliTypeName,i), 
01321                                                          title + "#LT #Delta x'/#sigma #GT",
01322                                                          aliSize,0.5,aliSize+0.5);
01323     
01324     if (bookResidY) {
01325       sumContainer.summaryYResiduals_ = tfd.make<TH1F>(Form("h_summaryY%s_%d",aliTypeName,i), 
01326                                                        title + "#LT #Delta y' #GT",
01327                                                        aliSize, 0.5, aliSize+0.5);
01328       sumContainer.summaryNormYResiduals_ = tfd.make<TH1F>(Form("h_summaryNormY%s_%d",aliTypeName,i), 
01329                                                            title + "#LT #Delta y'/#sigma #GT",
01330                                                            aliSize,0.5,aliSize+0.5);
01331     }
01332     
01333   } else if (subtype == align::AlignableDet && subcompSize > 1) { // fixed: was aliSize before
01334     if (subcompSize != 2) { // strange... expect only 2 DetUnits in DS layers
01335       // this 2 is hardcoded factor 2 in binning below and also assumed later on
01336       edm::LogError("Alignment") << "@SUB=bookSummaryHists"
01337                                  << "Det with " << subcompSize << " components";
01338     }
01339     // title contains x-title
01340     const TString title(Form("Summary for substructures in %s %d;%s;", aliTypeName, i,
01341                              aliobjid.typeToName(ali.components()[0]->components()[0]->alignableObjectId()).c_str()));
01342     
01343     sumContainer.summaryXResiduals_ 
01344       = tfd.make<TH1F>(Form("h_summaryX%s_%d", aliTypeName, i), 
01345                        title + "#LT #Delta x' #GT", (2*aliSize), 0.5, 2*aliSize+0.5);
01346     sumContainer.summaryNormXResiduals_ 
01347       = tfd.make<TH1F>(Form("h_summaryNormX%s_%d", aliTypeName, i), 
01348                        title + "#LT #Delta x'/#sigma #GT", (2*aliSize), 0.5, 2*aliSize+0.5);
01349 
01350     if (bookResidY) {
01351       sumContainer.summaryYResiduals_ 
01352         = tfd.make<TH1F>(Form("h_summaryY%s_%d", aliTypeName, i), 
01353                          title + "#LT #Delta y' #GT", (2*aliSize), 0.5, 2*aliSize+0.5);
01354       sumContainer.summaryNormYResiduals_ 
01355         = tfd.make<TH1F>(Form("h_summaryNormY%s_%d", aliTypeName, i), 
01356                          title + "#LT #Delta y'/#sigma #GT", (2*aliSize), 0.5, 2*aliSize+0.5);
01357     }
01358 
01359   } else {
01360     edm::LogError("TrackerOfflineValidation") << "@SUB=TrackerOfflineValidation::bookSummaryHists" 
01361                                               << "No summary histogramm for hierarchy level " 
01362                                               << aliTypeName << " in subdet " << aliDetId.subdetId();
01363   }
01364 
01365   // Now book hists that just sum up the residual histograms from lower levels.
01366   // Axis title is copied from lowest level module of structure.
01367   // Should be safe that y-hists are only touched if non-null pointers...
01368   int nbins = 0;
01369   double xmin = 0., xmax = 0.;
01370   const TString sumTitle(Form("Residual for %s %d in %s;", aliTypeName, i, typeName));
01371   const ModuleHistos &xTitHists = this->getHistStructFromMap(aliDetId); // for x-axis titles
01372   this->getBinning(aliDetId.subdetId(), XprimeResidual, nbins, xmin, xmax);
01373   
01374   sumContainer.sumXResiduals_ = tfd.make<TH1F>(Form("h_Xprime_%s_%d", aliTypeName, i),
01375                                                sumTitle + xTitHists.ResXprimeHisto->GetXaxis()->GetTitle(),
01376                                                nbins, xmin, xmax);
01377   
01378   this->getBinning(aliDetId.subdetId(), NormXprimeResidual, nbins, xmin, xmax);
01379   sumContainer.sumNormXResiduals_ = tfd.make<TH1F>(Form("h_NormXprime_%s_%d",aliTypeName,i), 
01380                                                    sumTitle + xTitHists.NormResXprimeHisto->GetXaxis()->GetTitle(),
01381                                                    nbins, xmin, xmax);
01382   if (bookResidY) {
01383     this->getBinning(aliDetId.subdetId(), YprimeResidual, nbins, xmin, xmax);
01384     sumContainer.sumYResiduals_ = tfd.make<TH1F>(Form("h_Yprime_%s_%d",aliTypeName,i), 
01385                                                  sumTitle + xTitHists.ResYprimeHisto->GetXaxis()->GetTitle(),
01386                                                  nbins, xmin, xmax);
01387     
01388     this->getBinning(aliDetId.subdetId(), NormYprimeResidual, nbins, xmin, xmax);
01389     sumContainer.sumNormYResiduals_ = tfd.make<TH1F>(Form("h_NormYprime_%s_%d",aliTypeName,i), 
01390                                                      sumTitle + xTitHists.NormResYprimeHisto->GetXaxis()->GetTitle(),
01391                                                      nbins, xmin, xmax);
01392   }
01393   
01394   // If we are at the lowest level, we already sum up and fill the summary.
01395 
01396   // special case I: For DetUnits and Dets with only one subcomponent start filling summary histos
01397   if( ( subtype == align::AlignableDet && subcompSize == 1) || subtype  == align::AlignableDetUnit ) {
01398     for(uint k = 0; k < aliSize; ++k) {
01399       DetId detid = ali.components()[k]->id();
01400       ModuleHistos &histStruct = this->getHistStructFromMap(detid);
01401       this->summarizeBinInContainer(k+1, detid.subdetId() ,sumContainer, histStruct );
01402       sumContainer.sumXResiduals_->Add(histStruct.ResXprimeHisto);
01403       sumContainer.sumNormXResiduals_->Add(histStruct.NormResXprimeHisto);
01404       if( this->isPixel(detid.subdetId()) || stripYResiduals_ ) {
01405         sumContainer.sumYResiduals_->Add(histStruct.ResYprimeHisto);
01406         sumContainer.sumNormYResiduals_->Add(histStruct.NormResYprimeHisto);
01407       }
01408     }
01409   } else if( subtype == align::AlignableDet && subcompSize > 1) { // fixed: was aliSize before
01410     // special case II: Fill summary histos for dets with two detunits 
01411     for(uint k = 0; k < aliSize; ++k) {
01412       for(uint j = 0; j < subcompSize; ++j) { // assumes all have same size (as binning does)
01413         DetId detid = ali.components()[k]->components()[j]->id();
01414         ModuleHistos &histStruct = this->getHistStructFromMap(detid);   
01415         this->summarizeBinInContainer(2*k+j+1, detid.subdetId() ,sumContainer, histStruct );
01416         sumContainer.sumXResiduals_->Add( histStruct.ResXprimeHisto);
01417         sumContainer.sumNormXResiduals_->Add( histStruct.NormResXprimeHisto);
01418         if( this->isPixel(detid.subdetId()) || stripYResiduals_ ) {
01419           sumContainer.sumYResiduals_->Add( histStruct.ResYprimeHisto);
01420           sumContainer.sumNormYResiduals_->Add( histStruct.NormResYprimeHisto);
01421         }
01422       }
01423     }
01424   }
01425   return sumContainer;
01426 }
01427 
01428 
01429 float 
01430 TrackerOfflineValidation::Fwhm (const TH1* hist) const
01431 {
01432   float max = hist->GetMaximum();
01433   int left = -1, right = -1;
01434   for(unsigned int i = 1, iEnd = hist->GetNbinsX(); i <= iEnd; ++i) {
01435     if(hist->GetBinContent(i) < max/2. && hist->GetBinContent(i+1) > max/2. && left == -1) {
01436       if(max/2. - hist->GetBinContent(i) < hist->GetBinContent(i+1) - max/2.) {
01437         left = i;
01438         ++i;
01439       } else {
01440         left = i+1;
01441         ++i;
01442       }
01443     }
01444     if(left != -1 && right == -1) {
01445       if(hist->GetBinContent(i) > max/2. && hist->GetBinContent(i+1) < max/2.) {
01446         if( hist->GetBinContent(i) - max/2. < max/2. - hist->GetBinContent(i+1)) {
01447           right = i;
01448         } else {
01449           right = i+1;
01450         }
01451         
01452       }
01453     }
01454   }
01455   return hist->GetXaxis()->GetBinCenter(right) - hist->GetXaxis()->GetBinCenter(left);
01456 }
01457 
01458 
01459 void 
01460 TrackerOfflineValidation::fillTree(TTree& tree,
01461                                    const std::map<int, TrackerOfflineValidation::ModuleHistos>& moduleHist_,
01462                                    TkOffTreeVariables &treeMem, const TrackerGeometry& tkgeom)
01463 {
01464  
01465   for(std::map<int, TrackerOfflineValidation::ModuleHistos>::const_iterator it = moduleHist_.begin(), 
01466         itEnd= moduleHist_.end(); it != itEnd;++it ) { 
01467     treeMem.clear(); // make empty/default
01468     
01469     //variables concerning the tracker components/hierarchy levels
01470     DetId detId_ = it->first;
01471     treeMem.moduleId = detId_;
01472     treeMem.subDetId = detId_.subdetId();
01473     treeMem.isDoubleSide =0;
01474 
01475     if(treeMem.subDetId == PixelSubdetector::PixelBarrel){
01476       PXBDetId pxbId(detId_);
01477       unsigned int whichHalfBarrel(1), rawId(detId_.rawId());  //DetId does not know about halfBarrels is PXB ...
01478       if( (rawId>=302056964 && rawId<302059300) || (rawId>=302123268 && rawId<302127140) ||
01479           (rawId>=302189572 && rawId<302194980) ) whichHalfBarrel=2;
01480       treeMem.layer = pxbId.layer(); 
01481       treeMem.half = whichHalfBarrel;
01482       treeMem.rod = pxbId.ladder();     // ... so, ladder is not per halfBarrel-Layer, but per barrel-layer!
01483       treeMem.module = pxbId.module();
01484     } else if(treeMem.subDetId == PixelSubdetector::PixelEndcap){
01485       PXFDetId pxfId(detId_); 
01486       unsigned int whichHalfCylinder(1), rawId(detId_.rawId());  //DetId does not kmow about halfCylinders in PXF
01487       if( (rawId>=352394500 && rawId<352406032) || (rawId>=352460036 && rawId<352471568) ||
01488           (rawId>=344005892 && rawId<344017424) || (rawId>=344071428 && rawId<344082960) ) whichHalfCylinder=2;
01489       treeMem.layer = pxfId.disk(); 
01490       treeMem.side = pxfId.side();
01491       treeMem.half = whichHalfCylinder;
01492       treeMem.blade = pxfId.blade(); 
01493       treeMem.panel = pxfId.panel();
01494       treeMem.module = pxfId.module();
01495     } else if(treeMem.subDetId == StripSubdetector::TIB){
01496       TIBDetId tibId(detId_); 
01497       unsigned int whichHalfShell(1), rawId(detId_.rawId());  //DetId does not kmow about halfShells in TIB
01498        if ( (rawId>=369120484 && rawId<369120688) || (rawId>=369121540 && rawId<369121776) ||
01499             (rawId>=369136932 && rawId<369137200) || (rawId>=369137988 && rawId<369138288) ||
01500             (rawId>=369153396 && rawId<369153744) || (rawId>=369154436 && rawId<369154800) ||
01501             (rawId>=369169844 && rawId<369170256) || (rawId>=369170900 && rawId<369171344) ||
01502             (rawId>=369124580 && rawId<369124784) || (rawId>=369125636 && rawId<369125872) ||
01503             (rawId>=369141028 && rawId<369141296) || (rawId>=369142084 && rawId<369142384) ||
01504             (rawId>=369157492 && rawId<369157840) || (rawId>=369158532 && rawId<369158896) ||
01505             (rawId>=369173940 && rawId<369174352) || (rawId>=369174996 && rawId<369175440) ) whichHalfShell=2;
01506       treeMem.layer = tibId.layer(); 
01507       treeMem.side = tibId.string()[0];
01508       treeMem.half = whichHalfShell;
01509       treeMem.rod = tibId.string()[2]; 
01510       treeMem.outerInner = tibId.string()[1]; 
01511       treeMem.module = tibId.module();
01512       treeMem.isStereo = tibId.stereo();
01513       treeMem.isDoubleSide = tibId.isDoubleSide();
01514     } else if(treeMem.subDetId == StripSubdetector::TID){
01515       TIDDetId tidId(detId_); 
01516       treeMem.layer = tidId.wheel(); 
01517       treeMem.side = tidId.side();
01518       treeMem.ring = tidId.ring(); 
01519       treeMem.outerInner = tidId.module()[0]; 
01520       treeMem.module = tidId.module()[1];
01521       treeMem.isStereo = tidId.stereo();
01522       treeMem.isDoubleSide = tidId.isDoubleSide();
01523     } else if(treeMem.subDetId == StripSubdetector::TOB){
01524       TOBDetId tobId(detId_); 
01525       treeMem.layer = tobId.layer(); 
01526       treeMem.side = tobId.rod()[0];
01527       treeMem.rod = tobId.rod()[1]; 
01528       treeMem.module = tobId.module();
01529       treeMem.isStereo = tobId.stereo();
01530       treeMem.isDoubleSide = tobId.isDoubleSide();
01531     } else if(treeMem.subDetId == StripSubdetector::TEC) {
01532       TECDetId tecId(detId_); 
01533       treeMem.layer = tecId.wheel(); 
01534       treeMem.side  = tecId.side();
01535       treeMem.ring  = tecId.ring(); 
01536       treeMem.petal = tecId.petal()[1]; 
01537       treeMem.outerInner = tecId.petal()[0];
01538       treeMem.module = tecId.module();
01539       treeMem.isStereo = tecId.stereo();
01540       treeMem.isDoubleSide = tecId.isDoubleSide(); 
01541     }
01542     
01543     //variables concerning the tracker geometry
01544     const Surface::PositionType &gPModule = tkgeom.idToDet(detId_)->position();
01545     treeMem.posPhi = gPModule.phi();
01546     treeMem.posEta = gPModule.eta();
01547     treeMem.posR   = gPModule.perp();
01548     treeMem.posX   = gPModule.x();
01549     treeMem.posY   = gPModule.y();
01550     treeMem.posZ   = gPModule.z();
01551  
01552     const Surface& surface =  tkgeom.idToDet(detId_)->surface();
01553     
01554     //global Orientation of local coordinate system of dets/detUnits   
01555     LocalPoint  lUDirection(1.,0.,0.), lVDirection(0.,1.,0.), lWDirection(0.,0.,1.);
01556     GlobalPoint gUDirection = surface.toGlobal(lUDirection),
01557                 gVDirection = surface.toGlobal(lVDirection),
01558                 gWDirection = surface.toGlobal(lWDirection);
01559     double dR(999.), dPhi(999.), dZ(999.);
01560     if(treeMem.subDetId==PixelSubdetector::PixelBarrel || treeMem.subDetId==StripSubdetector::TIB || treeMem.subDetId==StripSubdetector::TOB){
01561       dR = gWDirection.perp() - gPModule.perp();
01562       dPhi = deltaPhi(gUDirection.phi(),gPModule.phi());
01563       dZ = gVDirection.z() - gPModule.z();
01564       if(dZ>=0.)treeMem.rOrZDirection = 1; else treeMem.rOrZDirection = -1;
01565     }else if(treeMem.subDetId==PixelSubdetector::PixelEndcap){
01566       dR = gUDirection.perp() - gPModule.perp();
01567       dPhi = deltaPhi(gVDirection.phi(),gPModule.phi());
01568       dZ = gWDirection.z() - gPModule.z();
01569       if(dR>=0.)treeMem.rOrZDirection = 1; else treeMem.rOrZDirection = -1;
01570     }else if(treeMem.subDetId==StripSubdetector::TID || treeMem.subDetId==StripSubdetector::TEC){
01571       dR = gVDirection.perp() - gPModule.perp();
01572       dPhi = deltaPhi(gUDirection.phi(),gPModule.phi());
01573       dZ = gWDirection.z() - gPModule.z();
01574       if(dR>=0.)treeMem.rOrZDirection = 1; else treeMem.rOrZDirection = -1;
01575     }
01576     if(dR>=0.)treeMem.rDirection = 1; else treeMem.rDirection = -1;
01577     if(dPhi>=0.)treeMem.phiDirection = 1; else treeMem.phiDirection = -1;
01578     if(dZ>=0.)treeMem.zDirection = 1; else treeMem.zDirection = -1;
01579     
01580     //mean and RMS values (extracted from histograms(Xprime on module level)
01581     treeMem.entries = static_cast<UInt_t>(it->second.ResXprimeHisto->GetEntries());
01582     treeMem.meanX = it->second.ResXprimeHisto->GetMean();
01583     treeMem.rmsX  = it->second.ResXprimeHisto->GetRMS();
01584     //treeMem.sigmaX = Fwhm(it->second.ResXprimeHisto)/2.355;
01585     
01586     if (useFit_) {
01587       //call fit function which returns mean and sigma from the fit
01588       //for absolute residuals
01589       std::pair<float,float> fitResult1 = this->fitResiduals(it->second.ResXprimeHisto);
01590       treeMem.fitMeanX = fitResult1.first;
01591       treeMem.fitSigmaX = fitResult1.second;
01592       //for normalized residuals
01593       std::pair<float,float> fitResult2 = this->fitResiduals(it->second.NormResXprimeHisto);
01594       treeMem.fitMeanNormX = fitResult2.first;
01595       treeMem.fitSigmaNormX = fitResult2.second;
01596     }
01597     
01598     //get median for absolute residuals
01599     treeMem.medianX   = this->getMedian(it->second.ResXprimeHisto);
01600 
01601     int numberOfBins=it->second.ResXprimeHisto->GetNbinsX();
01602     treeMem.numberOfUnderflows = it->second.ResXprimeHisto->GetBinContent(0);
01603     treeMem.numberOfOverflows = it->second.ResXprimeHisto->GetBinContent(numberOfBins+1);
01604     treeMem.numberOfOutliers =  it->second.ResXprimeHisto->GetBinContent(0)+it->second.ResXprimeHisto->GetBinContent(numberOfBins+1);
01605     
01606     //mean and RMS values (extracted from histograms(normalized Xprime on module level)
01607     treeMem.meanNormX = it->second.NormResXprimeHisto->GetMean();
01608     treeMem.rmsNormX = it->second.NormResXprimeHisto->GetRMS();
01609 
01610     double stats[20];
01611     it->second.NormResXprimeHisto->GetStats(stats);
01612     // GF  treeMem.chi2PerDofX = stats[3]/(stats[0]-1);
01613     if (stats[0]) treeMem.chi2PerDofX = stats[3]/stats[0];
01614     
01615     treeMem.sigmaNormX = Fwhm(it->second.NormResXprimeHisto)/2.355;
01616     treeMem.histNameX = it->second.ResXprimeHisto->GetName();
01617     treeMem.histNameNormX = it->second.NormResXprimeHisto->GetName();
01618     
01619     // fill tree variables in local coordinates if set in cfg
01620     if(lCoorHistOn_) {
01621       treeMem.meanLocalX = it->second.ResHisto->GetMean();
01622       treeMem.rmsLocalX = it->second.ResHisto->GetRMS();
01623       treeMem.meanNormLocalX = it->second.NormResHisto->GetMean();
01624       treeMem.rmsNormLocalX = it->second.NormResHisto->GetRMS();
01625 
01626       treeMem.histNameLocalX = it->second.ResHisto->GetName();
01627       treeMem.histNameNormLocalX = it->second.NormResHisto->GetName();
01628       if (it->second.ResYHisto) treeMem.histNameLocalY = it->second.ResYHisto->GetName();
01629     }
01630 
01631     // mean and RMS values in local y (extracted from histograms(normalized Yprime on module level)
01632     // might exist in pixel only
01633     if (it->second.ResYprimeHisto) {//(stripYResiduals_){
01634       TH1 *h = it->second.ResYprimeHisto;
01635       treeMem.meanY = h->GetMean();
01636       treeMem.rmsY  = h->GetRMS();
01637       
01638       if (useFit_) { // fit function which returns mean and sigma from the fit
01639         std::pair<float,float> fitMeanSigma = this->fitResiduals(h);
01640         treeMem.fitMeanY  = fitMeanSigma.first;
01641         treeMem.fitSigmaY = fitMeanSigma.second;
01642       }
01643       
01644       //get median for absolute residuals
01645       treeMem.medianY   = this->getMedian(h);
01646 
01647       treeMem.histNameY = h->GetName();
01648     }
01649     if (it->second.NormResYprimeHisto) {
01650       TH1 *h = it->second.NormResYprimeHisto;
01651       treeMem.meanNormY = h->GetMean();
01652       treeMem.rmsNormY  = h->GetRMS();
01653       h->GetStats(stats); // stats buffer defined above
01654       if (stats[0]) treeMem.chi2PerDofY = stats[3]/stats[0];
01655 
01656       if (useFit_) { // fit function which returns mean and sigma from the fit
01657         std::pair<float,float> fitMeanSigma = this->fitResiduals(h);
01658         treeMem.fitMeanNormY  = fitMeanSigma.first;
01659         treeMem.fitSigmaNormY = fitMeanSigma.second;
01660       }
01661       treeMem.histNameNormY = h->GetName();
01662     }
01663 
01664     if (moduleLevelProfiles_) {
01665       if (it->second.ResXvsXProfile) {
01666         TH1 *h = it->second.ResXvsXProfile;
01667         treeMem.meanResXvsX = h->GetMean();
01668         treeMem.rmsResXvsX  = h->GetRMS();
01669         treeMem.profileNameResXvsX = h->GetName();
01670       } 
01671       if (it->second.ResXvsYProfile) {
01672         TH1 *h = it->second.ResXvsYProfile;
01673         treeMem.meanResXvsY = h->GetMean();
01674         treeMem.rmsResXvsY  = h->GetRMS();
01675         treeMem.profileNameResXvsY = h->GetName();
01676       } 
01677       if (it->second.ResYvsXProfile) {
01678         TH1 *h = it->second.ResYvsXProfile;
01679         treeMem.meanResYvsX = h->GetMean();
01680         treeMem.rmsResYvsX  = h->GetRMS();
01681         treeMem.profileNameResYvsX = h->GetName();
01682       } 
01683       if (it->second.ResYvsYProfile) {
01684         TH1 *h = it->second.ResYvsYProfile;
01685         treeMem.meanResYvsY = h->GetMean();
01686         treeMem.rmsResYvsY  = h->GetRMS();
01687         treeMem.profileNameResYvsY = h->GetName();
01688       }
01689     }
01690 
01691     tree.Fill();
01692   }
01693 }
01694 
01695 
01696 std::pair<float,float> 
01697 TrackerOfflineValidation::fitResiduals(TH1* hist) const
01698 {
01699   std::pair<float,float> fitResult(9999., 9999.);
01700   if (!hist || hist->GetEntries() < 20) return fitResult;
01701 
01702   float mean  = hist->GetMean();
01703   float sigma = hist->GetRMS();
01704 
01705   try { // for < CMSSW_2_2_0 since ROOT warnings from fit are converted to exceptions
01706     // Remove the try/catch for more recent CMSSW!
01707     // first fit: two RMS around mean
01708     TF1 func("tmp", "gaus", mean - 2.*sigma, mean + 2.*sigma); 
01709     if (0 == hist->Fit(&func,"QNR")) { // N: do not blow up file by storing fit!
01710       mean  = func.GetParameter(1);
01711       sigma = func.GetParameter(2);
01712       // second fit: three sigma of first fit around mean of first fit
01713       func.SetRange(mean - 3.*sigma, mean + 3.*sigma);
01714       // I: integral gives more correct results if binning is too wide
01715       // L: Likelihood can treat empty bins correctly (if hist not weighted...)
01716       if (0 == hist->Fit(&func, "Q0LR")) {
01717         if (hist->GetFunction(func.GetName())) { // Take care that it is later on drawn:
01718           hist->GetFunction(func.GetName())->ResetBit(TF1::kNotDraw);
01719         }
01720         fitResult.first = func.GetParameter(1);
01721         fitResult.second = func.GetParameter(2);
01722       }
01723     }
01724   } catch (cms::Exception const & e) {
01725     edm::LogWarning("Alignment") << "@SUB=TrackerOfflineValidation::fitResiduals"
01726                                  << "Caught this exception during ROOT fit: "
01727                                  << e.what();
01728   }
01729   return fitResult;
01730 }
01731 
01732 
01733 float 
01734 TrackerOfflineValidation::getMedian(const TH1* histo) const
01735 {
01736   float median = 999;
01737   int nbins = histo->GetNbinsX();
01738 
01739   //extract median from histogram
01740   double *x = new double[nbins];
01741   double *y = new double[nbins];
01742   for (int j = 0; j < nbins; j++) {
01743     x[j] = histo->GetBinCenter(j+1);
01744     y[j] = histo->GetBinContent(j+1);
01745   }
01746   median = TMath::Median(nbins, x, y);
01747   
01748   delete[] x; x = 0;
01749   delete [] y; y = 0;  
01750 
01751   return median;
01752 
01753 }
01754 //define this as a plug-in
01755 DEFINE_FWK_MODULE(TrackerOfflineValidation);