CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/Fireworks/Calo/src/FWECALDetailViewBuilder.cc

Go to the documentation of this file.
00001 // FIXME - needed to set fixed eta-phi limits. Without the
00002 //         visible area may change widely depending on energy
00003 //         deposition availability
00004 
00005 #include "TEveCaloData.h"
00006 #include "TEveViewer.h"
00007 #include "TEveCalo.h"
00008 #include "TAxis.h"
00009 #include "TMath.h"
00010 #include "THLimitsFinder.h"
00011 #include "TLatex.h"
00012 
00013 #include "Fireworks/Core/interface/FWDetailViewBase.h"
00014 #include "Fireworks/Calo/interface/FWECALDetailViewBuilder.h"
00015 #include "Fireworks/Core/interface/FWGeometry.h"
00016 #include "Fireworks/Core/interface/fw3dlego_xbins.h"
00017 #include "Fireworks/Core/interface/fwLog.h"
00018 
00019 #include "DataFormats/FWLite/interface/Handle.h"
00020 #include "DataFormats/EgammaReco/interface/SuperCluster.h"
00021 #include "DataFormats/EcalDetId/interface/EcalSubdetector.h"
00022 
00023 #include "TGeoMatrix.h"
00024 #include "TEveTrans.h"
00025 
00026 #include <utility>
00027 
00028 TEveCaloData* FWECALDetailViewBuilder::buildCaloData(bool xyEE)
00029 {
00030    // get the hits from the event
00031 
00032    edm::Handle<EcalRecHitCollection> handle_hits;
00033    const EcalRecHitCollection *hits = 0;
00034 
00035    if (fabs(m_eta) < 1.5)
00036    {
00037       try
00038       {
00039          edm::InputTag tag("ecalRecHit", "EcalRecHitsEB");
00040          m_event->getByLabel(tag, handle_hits);
00041          if (handle_hits.isValid())
00042          {
00043             hits = &*handle_hits;
00044          }
00045       }
00046       catch (...)
00047       {
00048          fwLog(fwlog::kWarning) <<"FWECALDetailViewBuilder::build():: Failed to access EcalRecHitsEB collection." << std::endl;
00049       }
00050       if ( ! handle_hits.isValid()) {
00051          try{
00052             edm::InputTag tag("reducedEcalRecHitsEB");
00053             m_event->getByLabel(tag, handle_hits);
00054             if (handle_hits.isValid())
00055             {
00056                hits = &*handle_hits;
00057             }
00058 
00059          }
00060          catch (...)
00061          {
00062             fwLog(fwlog::kWarning) <<"FWECALDetailViewBuilder::build():: Failed to access reducedEcalRecHitsEB collection." << std::endl;
00063          }
00064       }   
00065    }
00066    else
00067    {
00068       try
00069       {
00070          edm::InputTag tag("ecalRecHit", "EcalRecHitsEE");
00071          m_event->getByLabel(tag, handle_hits);
00072          if (handle_hits.isValid())
00073             hits = &*handle_hits;
00074       }
00075       catch (...)
00076       {
00077          fwLog(fwlog::kWarning) <<"FWECALDetailViewBuilder::build():: Failed to access ecalRecHitsEE collection." << std::endl;
00078       }
00079 
00080       if ( ! handle_hits.isValid()) {
00081          try {
00082             edm::InputTag tag("reducedEcalRecHitsEE");
00083             m_event->getByLabel(tag, handle_hits);
00084             if (handle_hits.isValid())
00085             {
00086                hits = &*handle_hits;
00087             }
00088 
00089          }
00090          catch (...)
00091          {     
00092             fwLog(fwlog::kWarning) <<"FWECALDetailViewBuilder::build():: Failed to access reducedEcalRecHitsEE collection." << std::endl;
00093          }
00094       }
00095    }
00096      
00097    // data
00098    TEveCaloDataVec* data = new TEveCaloDataVec( 1 + m_colors.size() );
00099    data->RefSliceInfo(0).Setup("hits (not clustered)", 0.0, m_defaultColor );
00100    for( size_t i = 0; i < m_colors.size(); ++i )
00101    {
00102       data->RefSliceInfo(i + 1).Setup( "hits (clustered)", 0.0, m_colors[i] );
00103    }
00104 
00105    if( handle_hits.isValid() ) 
00106    {
00107       fillData( hits, data, xyEE );
00108    }
00109 
00110    // axis
00111    Double_t etaMin(0), etaMax(0), phiMin(0), phiMax(0);
00112    if (data->Empty())
00113    {
00114       fwLog(fwlog::kWarning) <<"FWECALDetailViewBuilder::build():: No hits found in " << Form("FWECALDetailViewBuilder::build():: No hits found in eta[%f] phi[%f] region", m_eta, m_phi)<<".\n";
00115 
00116       // add dummy background
00117       float x = m_size*TMath::DegToRad();
00118       if (fabs(m_eta) < 1.5 || xyEE == false) {
00119          etaMin = m_eta -x;
00120          etaMax = m_eta +x;
00121          phiMin = m_phi -x;
00122          phiMax = m_phi +x;
00123          data->AddTower(etaMin, etaMax, phiMin, phiMax);
00124       }
00125       else
00126       {
00127          float theta = TEveCaloData::EtaToTheta(m_eta);
00128          float r = TMath::Tan(theta) * 290;
00129          phiMin = r * TMath::Cos(m_phi - x) -300;
00130          phiMax = r * TMath::Cos(m_phi + x) + 300;
00131          etaMin = r * TMath::Sin(m_phi - x) - 300;
00132          etaMax = r * TMath::Sin(m_phi + x) + 300;
00133          data->AddTower(TMath::Min(etaMin, etaMax), TMath::Max(etaMin, etaMax),
00134                         TMath::Min(phiMin, phiMax), TMath::Max(phiMin, phiMax));
00135 
00136       }
00137       data->FillSlice(0, 0.1);      
00138    }
00139 
00140  
00141    TAxis* eta_axis = 0;
00142    TAxis* phi_axis = 0; 
00143    data->GetEtaLimits(etaMin, etaMax);
00144    data->GetPhiLimits(phiMin, phiMax);
00145    //  printf("data rng %f %f %f %f\n",etaMin, etaMax, phiMin, phiMax );
00146 
00147    if (fabs(m_eta) > 1.5 && xyEE ) {
00148       eta_axis = new TAxis(10, etaMin, etaMax);
00149       phi_axis = new TAxis(10, phiMin, phiMax);
00150       eta_axis->SetTitle("X[cm]");
00151       phi_axis->SetTitle("Y[cm]");
00152       phi_axis->SetTitleSize(0.05);
00153       eta_axis->SetTitleSize(0.05);
00154    } else {
00155       std::vector<double> etaBinsWithinLimits;
00156       etaBinsWithinLimits.push_back(etaMin);
00157       for (unsigned int i=0; i<83; ++i)
00158          if ( fw3dlego::xbins[i] > etaMin && fw3dlego::xbins[i] < etaMax )
00159             etaBinsWithinLimits.push_back(fw3dlego::xbins[i]);
00160       etaBinsWithinLimits.push_back(etaMax);
00161 
00162       std::vector<double> phiBinsWithinLimits;
00163       phiBinsWithinLimits.push_back(phiMin);
00164       for ( double phi = -M_PI; phi < M_PI; phi += M_PI/36 )
00165          if ( phi > phiMin && phi < phiMax )
00166             phiBinsWithinLimits.push_back(phi);
00167       phiBinsWithinLimits.push_back(phiMax);
00168 
00169       eta_axis = new TAxis((int)etaBinsWithinLimits.size() -1, &etaBinsWithinLimits[0]);
00170       phi_axis = new TAxis((int)phiBinsWithinLimits.size() -1, &phiBinsWithinLimits[0]);
00171 
00172       eta_axis->SetTitleFont(122);
00173       eta_axis->SetTitle("h");
00174       eta_axis->SetTitleSize(0.07);
00175       phi_axis->SetTitleFont(122);
00176       phi_axis->SetTitle("f");
00177       phi_axis->SetTitleSize(0.07);
00178    }
00179    eta_axis->SetNdivisions(510);
00180    phi_axis->SetNdivisions(510);
00181    data->SetEtaBins(eta_axis);
00182    data->SetPhiBins(phi_axis);
00183    return data;
00184 }
00185 
00186 //_______________________________________________________________   
00187 TEveCaloLego* FWECALDetailViewBuilder::build()
00188 {
00189    TEveCaloData* data = buildCaloData(true);   
00190    
00191    double etaMin, etaMax, phiMin, phiMax;
00192    data->GetEtaLimits(etaMin, etaMax);
00193    data->GetPhiLimits(phiMin, phiMax);
00194    
00195    // lego
00196    TEveCaloLego *lego = new TEveCaloLego(data);
00197    lego->SetDrawNumberCellPixels(100);
00198    // scale and translate to real world coordinates
00199    lego->SetEta(etaMin, etaMax);
00200    lego->SetPhiWithRng((phiMin+phiMax)*0.5, (phiMax-phiMin)*0.5); // phi range = 2* phiOffset
00201    Double_t legoScale = ((etaMax - etaMin) < (phiMax - phiMin)) ? (etaMax - etaMin) : (phiMax - phiMin);
00202    lego->InitMainTrans();
00203    lego->RefMainTrans().SetScale(legoScale, legoScale, legoScale*0.5);
00204    lego->RefMainTrans().SetPos((etaMax+etaMin)*0.5, (phiMax+phiMin)*0.5, 0);
00205    lego->SetAutoRebin(kFALSE);
00206    lego->Set2DMode(TEveCaloLego::kValSizeOutline);
00207    lego->SetName("ECALDetail Lego");
00208    return lego;
00209 
00210 }
00211 
00212 void FWECALDetailViewBuilder::setColor(Color_t color, const std::vector<DetId> &detIds)
00213 {
00214 
00215    m_colors.push_back(color);
00216 
00217    // get the slice for this group of detIds
00218    // note that the zeroth slice is the default one (all else)
00219    int slice = m_colors.size();
00220    // take a note of which slice these detids are going to go into
00221    for (size_t i = 0; i < detIds.size(); ++i)
00222       m_detIdsToColor[detIds[i]] = slice;
00223 }
00224 
00225 void
00226 FWECALDetailViewBuilder::showSuperCluster( const reco::SuperCluster &cluster, Color_t color )
00227 {
00228    std::vector<DetId> clusterDetIds;
00229    const std::vector<std::pair<DetId, float> > &hitsAndFractions = cluster.hitsAndFractions();
00230    for (size_t j = 0; j < hitsAndFractions.size(); ++j)
00231    {
00232       clusterDetIds.push_back(hitsAndFractions[j].first);
00233    }
00234 
00235    setColor( color, clusterDetIds );
00236 }
00237 
00238 void
00239 FWECALDetailViewBuilder::showSuperClusters( Color_t color1, Color_t color2 )
00240 {
00241    // get the superclusters from the event
00242    edm::Handle<reco::SuperClusterCollection> collection;
00243 
00244    if( fabs( m_eta ) < 1.5 ) {
00245       try {
00246          m_event->getByLabel(edm::InputTag("correctedHybridSuperClusters"), collection);
00247       }
00248       catch (...)
00249       {
00250          fwLog(fwlog::kWarning) <<"no barrel superclusters are available" << std::endl;
00251       }
00252    } else {
00253       try {
00254          m_event->getByLabel(edm::InputTag("correctedMulti5x5SuperClustersWithPreshower"), collection);
00255       }
00256       catch (...)
00257       {
00258          fwLog(fwlog::kWarning) <<"no endcap superclusters are available" << std::endl;
00259       }
00260    }
00261    if( collection.isValid() )
00262    {
00263       unsigned int colorIndex = 0;
00264       // sort clusters in eta so neighboring clusters have distinct colors
00265       reco::SuperClusterCollection sorted = *collection.product();
00266       std::sort( sorted.begin(), sorted.end(), superClusterEtaLess );
00267       for( size_t i = 0; i < sorted.size(); ++i )
00268       {
00269          if( !(fabs(sorted[i].eta() - m_eta) < (m_size*0.0172)
00270                && fabs(sorted[i].phi() - m_phi) < (m_size*0.0172)) )
00271            continue;
00272 
00273          if( colorIndex %2 == 0 )
00274             showSuperCluster( sorted[i], color1 );
00275          else
00276             showSuperCluster( sorted[i], color2 );
00277          ++colorIndex;
00278       }
00279    }
00280 }
00281 
00282 void
00283 FWECALDetailViewBuilder::fillData( const EcalRecHitCollection *hits,
00284                                   TEveCaloDataVec *data, bool xyEE )
00285 {
00286    const float barrelCR = m_size*0.0172; // barrel cell range
00287    
00288    // loop on all the detids
00289    for( EcalRecHitCollection::const_iterator k = hits->begin(), kEnd = hits->end();
00290        k != kEnd; ++k )
00291    {
00292       // get reco geometry
00293       double centerEta = 0;
00294       double centerPhi = 0;
00295       const float* points = m_geom->getCorners( k->id().rawId());
00296       if( points != 0 )
00297       {
00298          TEveVector v;
00299          int j = 0;
00300          for( int i = 0; i < 8; ++i )
00301          {       
00302             v += TEveVector( points[j], points[j + 1], points[j + 2] );
00303             j +=3;
00304          }
00305          centerEta = v.Eta();
00306          centerPhi = v.Phi();
00307       }
00308       else
00309          fwLog( fwlog::kInfo ) << "cannot get geometry for DetId: "<< k->id().rawId() << ". Ignored.\n";
00310       
00311       double size = k->energy() / cosh( centerEta );
00312       
00313       // check what slice to put in
00314       int slice = 0;
00315       std::map<DetId, int>::const_iterator itr = m_detIdsToColor.find(k->id());
00316       if (itr != m_detIdsToColor.end()) slice = itr->second;
00317       
00318       // if in the EB
00319       if( k->id().subdetId() == EcalBarrel || xyEE == false )
00320       {
00321          // do phi wrapping
00322          if( centerPhi > m_phi + M_PI) centerPhi -= 2 * M_PI;
00323          if( centerPhi < m_phi - M_PI) centerPhi += 2 * M_PI;
00324          
00325          // check if the hit is in the window to be drawn
00326          if( !( fabs( centerEta - m_eta ) < barrelCR
00327                && fabs( centerPhi - m_phi ) < barrelCR )) continue;
00328          
00329          double minEta(10), maxEta(-10), minPhi(4), maxPhi(-4);
00330          if( points != 0 )
00331          {
00332             // calorimeter crystalls have slightly non-symetrical form in eta-phi projection
00333             // so if we simply get the largest eta and phi, cells will overlap
00334             // therefore we get a smaller eta-phi range representing the inner square
00335             // we also should use only points from the inner face of the crystal, since
00336             // non-projecting direction of crystals leads to large shift in eta on outter
00337             // face.
00338             int j = 0;
00339             float eps = 0.005;
00340             for( unsigned int i = 0; i < 8; ++i )
00341             {
00342                TEveVector crystal( points[j], points[j + 1], points[j + 2] );
00343                j += 3;
00344                double eta = crystal.Eta();
00345                double phi = crystal.Phi();
00346                if ( ((k->id().subdetId() == EcalBarrel)  && (crystal.Perp() > 135) )||  ((k->id().subdetId() == EcalEndcap) && (crystal.Perp() > 155))) continue;
00347                if ( minEta - eta > eps) minEta = eta;
00348                if ( eta - minEta > 0 && eta - minEta < eps ) minEta = eta;
00349                if ( eta - maxEta > eps) maxEta = eta;
00350                if ( maxEta - eta > 0 && maxEta - eta < eps ) maxEta = eta;
00351                if ( minPhi - phi > eps) minPhi = phi;
00352                if ( phi - minPhi > 0 && phi - minPhi < eps ) minPhi = phi;
00353                if ( phi - maxPhi > eps) maxPhi = phi;
00354                if ( maxPhi - phi > 0 && maxPhi - phi < eps ) maxPhi = phi;
00355             }
00356          }
00357          else 
00358          {
00359             double delta = 0.0172 * 0.5;
00360             minEta = centerEta - delta;
00361             maxEta = centerEta + delta;
00362             minPhi = centerPhi - delta;
00363             maxPhi = centerPhi + delta;
00364          }
00365          if( minPhi >= ( m_phi - barrelCR ) && maxPhi <= ( m_phi + barrelCR ) &&
00366             minEta >= ( m_eta - barrelCR ) && maxEta <= ( m_eta + barrelCR ))
00367          {
00368             // printf("add %f %f %f %f \n",minEta, maxEta, minPhi, maxPhi );
00369             data->AddTower( minEta, maxEta, minPhi, maxPhi );
00370             data->FillSlice( slice, size );
00371          }
00372          // otherwise in the EE
00373       }
00374       else if( k->id().subdetId() == EcalEndcap )
00375       {
00376          // check if the hit is in the window to be drawn
00377          double crystalSize = m_size * 0.0172;
00378          if( !( fabs( centerEta - m_eta ) < ( crystalSize )
00379                && fabs( centerPhi - m_phi ) < ( crystalSize )))
00380             continue;
00381          
00382          if( points != 0 )
00383          {
00384             double minX(9999), maxX(-9999), minY(9999), maxY(-9999);
00385             int j = 0;
00386             for( unsigned int i = 0; i < 8; ++i )
00387             {
00388                TEveVector crystal( points[j], points[j + 1], points[j + 2] );
00389                j += 3;
00390                double x = crystal.fX;
00391                double y = crystal.fY;
00392                if( fabs( crystal.fZ ) > 330 ) continue;
00393                if( minX - x > 0.01 ) minX = x;
00394                if( x - maxX > 0.01 ) maxX = x;
00395                if( minY - y > 0.01 ) minY = y;
00396                if( y - maxY > 0.01 ) maxY = y;
00397             }
00398             data->AddTower( minX, maxX, minY, maxY );
00399             // printf("EE add %f %f %f %f \n",minX, maxX, minY, maxY );
00400          }
00401          data->FillSlice( slice, size );
00402       }
00403    } // end loop on hits
00404    
00405    data->DataChanged();
00406 }
00407 
00408 double
00409 FWECALDetailViewBuilder::makeLegend( double x0, double y0,
00410                                     Color_t clustered1, Color_t clustered2,
00411                                     Color_t supercluster
00412                                     )
00413 {
00414    Double_t fontsize = 0.07;
00415    TLatex* latex = new TLatex();
00416    Double_t x = x0;
00417    Double_t y = y0;
00418    Double_t boxH = 0.25*fontsize;
00419    Double_t yStep = 0.04;
00420    
00421    y -= yStep;
00422    latex->DrawLatex(x, y, "Energy types:");
00423    y -= yStep;
00424    
00425    Double_t pos[4];
00426    pos[0] = x+0.05;
00427    pos[2] = x+0.20;
00428    
00429    pos[1] = y; pos[3] = pos[1] + boxH;
00430    FWDetailViewBase::drawCanvasBox(pos, m_defaultColor);
00431    latex->DrawLatex(x+0.25, y, "unclustered");
00432    y -= yStep;
00433    if (clustered1<0) return y;
00434    
00435    pos[1] = y; pos[3] = pos[1] + boxH;
00436    FWDetailViewBase::drawCanvasBox(pos, clustered1);
00437    latex->DrawLatex(x+0.25, y, "clustered");
00438    y -= yStep;
00439    if (clustered2<0) return y;
00440    
00441    pos[1] = y; pos[3] = pos[1] + boxH;
00442    FWDetailViewBase::drawCanvasBox(pos, clustered2);
00443    latex->DrawLatex(x+0.25, y, "clustered");
00444    y -= yStep;
00445    if (supercluster<0) return y;
00446    
00447    pos[1] = y; pos[3] = pos[1] + boxH;
00448    FWDetailViewBase::drawCanvasBox(pos, supercluster);
00449    latex->DrawLatex(x+0.25, y, "super-cluster");
00450    y -= yStep;
00451    
00452    return y;
00453 }