MuonSpectrometer.cxx

Go to the documentation of this file.
00001 #include <iostream>
00002 #include <cmath>
00003 #include <cstdlib>
00004 
00005 #include "AtlfastAlgs/MuonSpectrometer.h"
00006 
00007 namespace Atlfast{
00008 
00009   // ============================================
00010 
00011   double dEnergyLoss(double eta, double pT){
00012     
00013     // Contribution from energy loss fluctuations
00014     // in the colorimeters
00015     // Unitless fraction
00016     
00017     eta = fabs(eta);
00018     double theta = 2.*atan(exp(-eta));
00019     double sintheta = sin(theta);
00020     double energy = fabs(pT)/sintheta;
00021     double factor = (eta < 1.1) ? 1./sqrt(sintheta) : sqrt(14./11.);
00022     double dEloss = (eta < 1.1) ? 
00023       factor*(240. + 0.105*energy/100.)/energy : 
00024       factor*(480. + 0.105*energy/100.)/energy;
00025 
00026     return dEloss;
00027 
00028   }
00029   
00030   double dEnergyLoss(const HepLorentzVector& avec){
00031     return dEnergyLoss(avec.pseudoRapidity(),avec.perp());
00032   }
00033   
00034   // ============================================
00035   // Predicates
00036   // ============================================
00037   
00038   IsCorrectEtaBin::IsCorrectEtaBin(double eta):
00039     m_eta(eta){}
00040   bool IsCorrectEtaBin::operator()(EtaBin& eb){
00041     // returns true if eta value is within this EtaBin
00042     return ( m_eta >= eb.getEtaMin() && m_eta < eb.getEtaMax() ) ? true : false;
00043   }
00044   
00045   // ============================================
00046   
00047   IsCorrectPhiBin::IsCorrectPhiBin(double phi):
00048     m_phi(phi){}
00049   bool IsCorrectPhiBin::operator()(PhiBin& pb){
00050     // returns true if phi value is within this PhiBin
00051     return ( m_phi >= pb.getPhiMin() && m_phi < pb.getPhiMax() ) ? true : false;
00052   }
00053   
00054   // ============================================
00055   
00056   IsCorrectSector::IsCorrectSector(std::string sectortype):
00057     m_sectortype(sectortype){}
00058   bool IsCorrectSector::operator()(Sector& sec){
00059     // returns true if this Sector is of the correct type
00060     return ( m_sectortype == sec.getSectorType() ) ? true : false;
00061   }
00062   
00063   // ============================================
00064   
00065   IsCorrectMuonSpectrometer::IsCorrectMuonSpectrometer(double pT):
00066     m_pT(pT){}
00067   bool IsCorrectMuonSpectrometer::operator()(MuonSpectrometer& ms){
00068     // returns true if pt value is within this MuonSpectrometer
00069     return ( m_pT >= ms.getPtMin() && m_pT < ms.getPtMax() ) ? true : false;
00070   }
00071   
00072   
00073   // ============================================
00074   
00075   EtaBin::EtaBin(double deltaponp, int etabin):
00076     m_etabin(etabin), m_etamin(0.), m_etamax(0.), m_deltaponp(0.01*deltaponp){}
00077   
00078   void EtaBin::setEtaStuff(double etaFirst, double deltaEta){
00079     
00080     m_etavalue = deltaEta*double(m_etabin);
00081     m_etamin = m_etabin ? deltaEta*double(m_etabin-0.5) + etaFirst: etaFirst;
00082     m_etamax = deltaEta*double(m_etabin+0.5);
00083 
00084   }
00085   
00086   void EtaBin::combine(EtaBin& otherEtaBin, double thispt, double nextpt){
00087 
00088     
00089     m_constterm = 1.;
00090     m_ptterm = 0;
00091 
00092     if (m_deltaponp < 1.){
00093       
00094       double resthis = m_deltaponp;
00095       double resnext = otherEtaBin.m_deltaponp;
00096       double delossthis = dEnergyLoss(m_etavalue,thispt);
00097       double delossnext = dEnergyLoss(m_etavalue,nextpt);
00098       
00099       m_ptterm = ( resnext*resnext - resthis*resthis
00100                    - (delossnext*delossnext - delossthis*delossthis ) ) /
00101         (nextpt*nextpt - thispt*thispt);
00102       
00103       m_constterm = resthis*resthis - m_ptterm*thispt*thispt - delossthis*delossthis;
00104       
00105     }    
00106   }
00107   
00108   double EtaBin::calculateResolution(const HepLorentzVector& avec){
00109 
00110     double resolution = 1.;
00111     if (m_constterm < 1.){ // Otherwise return resolution of 1.0
00112       double dEloss = dEnergyLoss(avec);
00113       double pT = avec.perp();
00114       double resolution_squared = m_constterm + m_ptterm*pT*pT + dEloss*dEloss;
00115       if (resolution_squared > 0. && resolution_squared < 1.)
00116         resolution = sqrt(resolution_squared);
00117     }
00118     return resolution;
00119   }
00120 
00121   void EtaBin::dump(std::string indent){
00122     indent += " ";
00123     std::cout<<std::endl;
00124     std::cout<<indent<<"\nDump for EtaBin:\n";
00125     std::cout<<indent<<"m_etabin "<<m_etabin<<std::endl;
00126     std::cout<<indent<<"m_etamin "<<m_etamin<<std::endl;
00127     std::cout<<indent<<"m_etamax "<<m_etamax<<std::endl;
00128     std::cout<<indent<<"m_deltaponp "<<m_deltaponp<<std::endl;
00129     std::cout<<indent<<"m_constterm "<<m_constterm<<std::endl;
00130     std::cout<<indent<<"m_ptterm "<<m_ptterm<<std::endl;
00131   }
00132   
00133   // ============================================
00134   
00135   PhiBin::PhiBin(DOMNode* boundaries, DOMNode* phi):
00136     m_phibin(0), m_phimin(0.), m_phimax(0.){
00137     
00138     // phibin goes from 0 to 90
00139     getFirstValue(phi, "phibinnumber", m_phibin);
00140     
00141     std::vector<double> deltaponps;
00142     getAllValues(phi, "deltaponp",deltaponps);
00143     SpectrometerComponentBinInstantiator<EtaBin> instantiator(boundaries);
00144     m_etas = std::for_each(deltaponps.begin(),
00145                            deltaponps.end(),             
00146                            instantiator).objects();
00147     
00148     double etafirst;
00149     double etalast;
00150     
00151     DOMNode* etaInfoNode =  getFirstChildTagByName(boundaries, "etainfo");
00152     getFirstValue(etaInfoNode, "etafirst", etafirst);
00153     getFirstValue(etaInfoNode, "etalast", etalast);
00154     
00155     int etaPoints = m_etas.size();
00156     double deltaEta = (etalast-etafirst)/(etaPoints-1);
00157     
00158     std::vector<EtaBin>::iterator itr = m_etas.begin();
00159     for(;itr != m_etas.end(); ++itr){
00160       (*itr).setEtaStuff(etafirst,deltaEta);
00161     }
00162     
00163   }
00164   
00165 
00166   PhiBin::~PhiBin(){
00167     m_etas.clear();
00168   }
00169   
00170   void PhiBin::setPhiStuff(double sectorPhimin, double sectorPhimax, double deltaPhi, int phipoints){
00171 
00172     // these are phi values within a sector    
00173     m_phimin = m_phibin ? deltaPhi*double(m_phibin-0.5) + sectorPhimin : sectorPhimin;
00174     if (m_phimin > M_PI) m_phimin -= (2.*M_PI);
00175     
00176     m_phimax = (m_phibin != (phipoints-1)) ? deltaPhi*double(m_phibin+0.5) : sectorPhimax;
00177     if (m_phimax > M_PI) m_phimax -= (2.*M_PI);
00178     
00179   }
00180   
00181   void PhiBin::combine(PhiBin &otherPhiBin, double thispt, double nextpt){
00182     
00183     std::vector<EtaBin>::iterator thisEtaItr = m_etas.begin();
00184     std::vector<EtaBin>::iterator otherEtaItr = otherPhiBin.m_etas.begin();
00185     for(;thisEtaItr != m_etas.end(); ++thisEtaItr, ++otherEtaItr){
00186 
00187       (*thisEtaItr).combine(*otherEtaItr, thispt, nextpt);
00188     }
00189     
00190   }
00191 
00192   double PhiBin::calculateResolution(const HepLorentzVector& avec){
00193     
00194     IsCorrectEtaBin iceb(fabs(avec.pseudoRapidity()));
00195     std::vector<EtaBin>::iterator ebitr = find_if(m_etas.begin(),
00196                                                   m_etas.end(),
00197                                                   iceb);
00198     if ( ebitr == m_etas.end() ){
00199       // Muon outside eta range, returning resolution of 1.0
00200       return 1.;
00201     }
00202     
00203     return (*ebitr).calculateResolution(avec);    
00204     
00205   }
00206 
00207   void PhiBin::dump(std::string indent){
00208     indent += "  ";
00209     std::cout<<indent<<"Dump for PhiBin:\n";
00210     std::cout<<indent<<"m_phibin "<<m_phibin<<std::endl;
00211     std::cout<<indent<<"m_phimin "<<m_phimin<<std::endl;
00212     std::cout<<indent<<"m_phimax "<<m_phimax<<std::endl;
00213     std::cout<<indent<<"Dump of my etas:"<<std::endl;
00214     std::for_each(m_etas.begin(), m_etas.end(), AddToDump(indent));
00215   }
00216 
00217   // ============================================
00218 
00219   Sector::Sector(DOMNode* boundaries, DOMNode* sector):m_phimin(0.){
00220 
00221     m_sectorType = "Unknown";
00222     
00223     getFirstValue(sector, "sectortype", m_sectorType);
00224     
00225     std::vector<DOMNode*> phis = getAllChildTagsByName(sector, "phibinres");
00226     SpectrometerComponentInstantiator<PhiBin> instantiator(boundaries);
00227     m_phis = std::for_each(phis.begin(),
00228                            phis.end(),
00229                            instantiator).objects();
00230     
00231     DOMNode* phiInfoNode =  getFirstChildTagByName(boundaries, "phiinfo");
00232     getFirstValue(phiInfoNode, "phifirst", m_phimin);
00233     getFirstValue(phiInfoNode, "philast", m_phimax);
00234     
00235     // Calculate phi info once here and give it to the PhiBins
00236     
00237     int phipoints = m_phis.size();
00238     double deltaphi = (m_phimax-m_phimin)/(phipoints-1);
00239 
00240 
00241     std::vector<PhiBin>::iterator itr = m_phis.begin();
00242     for(;itr != m_phis.end(); ++itr){
00243       (*itr).setPhiStuff(m_phimin, m_phimax, deltaphi, phipoints);
00244     }
00245     
00246   }
00247   
00248   Sector::~Sector(){
00249     m_phis.clear();
00250   }
00251 
00252   void Sector::combine(Sector& otherSec, double thispt, double nextpt){
00253     
00254     std::vector<PhiBin>::iterator thisPhiItr = m_phis.begin();
00255     std::vector<PhiBin>::iterator otherPhiItr = otherSec.m_phis.begin();
00256     for(;thisPhiItr != m_phis.end(); ++thisPhiItr, ++otherPhiItr){
00257       (*thisPhiItr).combine(*otherPhiItr, thispt, nextpt);
00258     }
00259   }
00260   
00261   double Sector::calculateResolution(const HepLorentzVector& avec){
00262 
00263     // check for appropriate PhiBin
00264     // First calculate the local phi (zeroed at the sector phimin)
00265     
00266     double localphi = avec.phi();
00267     while (localphi < 0.) localphi += 2.*M_PI;
00268     double global_phi = localphi;
00269     double sectorsize = m_phimax - m_phimin;
00270     while (localphi > sectorsize ) localphi -= sectorsize;
00271     if ( global_phi >= 3.926990815 && global_phi < 4.712388978 )
00272       localphi = sectorsize - localphi;
00273     
00274     IsCorrectPhiBin icpb(localphi);
00275     std::vector<PhiBin>::iterator pbitr = find_if(m_phis.begin(),
00276                                                   m_phis.end(),
00277                                                   icpb);
00278     if ( pbitr == m_phis.end() ){
00279       // Could not find correct PhiBin, returning resolution of 1.0
00280       return 1.;
00281     }
00282     
00283     return (*pbitr).calculateResolution(avec);    
00284     
00285   }
00286 
00287   void Sector::dump(std::string indent){
00288     indent += "  ";
00289     std::cout<<indent<<"Dump for Sector:\n";
00290     std::cout<<indent<<"m_sectorType "<<m_sectorType<<std::endl;
00291     std::cout<<indent<<"m_phimin     "<<m_phimin<<std::endl;
00292     std::for_each(m_phis.begin(), m_phis.end(), AddToDump(indent));
00293   }
00294 
00295   // ============================================
00296   
00297   ProtoSpectrometer::ProtoSpectrometer(DOMNode* boundaries, DOMNode* ptbinres, bool lowestpT, bool highestpT):
00298     m_lowestpT(lowestpT), m_highestpT(highestpT){
00299     
00300     getFirstValue(ptbinres, "ptbinnumber", m_ptbin);
00301     
00302     DOMNode* node = getFirstChildTagByName(boundaries, "ptpoints");
00303     
00304     std::vector<DOMNode*> ptBoundaryNodes = 
00305       getAllChildTagsByName(node, "ptpoint");
00306     
00307     std::vector<double> ptBoundaries = 
00308       for_each(
00309                ptBoundaryNodes.begin(),
00310                ptBoundaryNodes.end(),
00311                GetDoublesFromNodes()
00312                ).doubles();
00313     
00314     if(m_ptbin < static_cast<int>(ptBoundaries.size())){
00315       m_ptvalue = ptBoundaries[m_ptbin];
00316     }
00317     std::vector<DOMNode*> sectors = getAllChildTagsByName(ptbinres, "sector");
00318     SpectrometerComponentInstantiator<Sector> instantiator(boundaries);
00319     m_sectors = std::for_each(sectors.begin(),
00320                               sectors.end(),
00321                               instantiator).objects();
00322   }
00323   
00324   ProtoSpectrometer::~ProtoSpectrometer(){
00325     m_sectors.clear();
00326   }
00327 
00328   void ProtoSpectrometer::dump(std::string indent){
00329     indent += "  ";
00330     std::cout<<indent<<"Dump for Spectrometer:\n";
00331     std::cout<<indent<<"m_bin "<<m_ptbin<<std::endl;
00332     std::cout<<indent<<"m_ptvalue "<<m_ptvalue<<std::endl;
00333     std::cout<<indent<<"Dump of my sectors:"<<std::endl;
00334     std::for_each(m_sectors.begin(), m_sectors.end(), AddToDump(indent));
00335   }
00336 
00337   MuonSpectrometer ProtoSpectrometer::combine(ProtoSpectrometer& otherPS){
00338 
00339     std::vector<Sector>::iterator thisSecItr = m_sectors.begin();
00340     std::vector<Sector>::iterator otherSecItr = otherPS.m_sectors.begin();
00341     
00342     for(; thisSecItr!= m_sectors.end(); ++thisSecItr, ++otherSecItr){
00343       (*thisSecItr).combine(*otherSecItr, m_ptvalue, otherPS.m_ptvalue);
00344     }
00345     
00346     double ptlow = m_lowestpT ? 0.0 : m_ptvalue;
00347     double pthigh = otherPS.m_highestpT ? 7000000.0 : otherPS.m_ptvalue;
00348     
00349     MuonSpectrometer thisMS(ptlow, pthigh, m_sectors);
00350     
00351     return thisMS;
00352     
00353   }
00354 
00355   // ============================================
00356 
00357   MuonSpectrometer::MuonSpectrometer(double ptmin, double ptmax, std::vector<Sector> sectors):
00358     m_ptmin(ptmin), m_ptmax(ptmax), m_sectors(sectors){
00359   }
00360 
00361   void MuonSpectrometer::setSectorMap(std::map<int,std::string> sectortypes){
00362     m_sectortypes = sectortypes;
00363     m_sectorsize = 2.*M_PI/m_sectortypes.size();
00364   }
00365   
00366   double MuonSpectrometer::calculateResolution(const HepLorentzVector& avec){
00367 
00368     // Choose sector number based on phi
00369     // -pi < HepLorentzVector.phi() < +pi
00370     double phi = avec.phi();
00371     while (phi < 0.) phi += 2.*M_PI;
00372     // Is this compiler-dependent rounding-up? Must check
00373     int sectorindex = int(phi/m_sectorsize) + 1;
00374 
00375     // Translate this to a sector type
00376     std::string sectortype = m_sectortypes[sectorindex];
00377     
00378     // Now find the corresponding sector
00379     IsCorrectSector ics(sectortype);
00380     std::vector<Sector>::iterator secitr = find_if(m_sectors.begin(),
00381                                                     m_sectors.end(),
00382                                                     ics);
00383     if ( secitr == m_sectors.end() ){
00384       // Could not find correct Sector, returning resolution of 1.0
00385       return 1.;
00386     }
00387     
00388     return (*secitr).calculateResolution(avec);    
00389 
00390   }
00391 
00392   void MuonSpectrometer::dump(std::string indent){
00393     indent += "  ";
00394     std::cout<<indent<<"Dump for MuonSpectrometer:\n";
00395     std::cout<<indent<<"m_ptmin "<<m_ptmin<<std::endl;
00396     std::cout<<indent<<"m_ptmax "<<m_ptmax<<std::endl;
00397     std::cout<<indent<<"Dump of my sectors:"<<std::endl;
00398     std::for_each(m_sectors.begin(), m_sectors.end(), AddToDump(indent));
00399   }
00400 
00401   // ============================================
00402 
00403   MuonResolutionCalculator::MuonResolutionCalculator(const char* filename){
00404     
00405     DOMDocument* dom = parseFileForDocument(filename);
00406     
00407     if(dom == 0){
00408       std::cout<<"Could not parse " <<filename<<std::endl;
00409     }
00410     
00411     DOMElement* docElement = dom->getDocumentElement();
00412     
00413     if(docElement == 0){
00414       std::cout<<"Could not get DOMElement from DOMDocument"<<std::endl;
00415     }
00416     
00417     // get the node containing information for interpreting the resolutions
00418     XMLCh* s = XMLString::transcode("interpretation");
00419     DOMNodeList* binTags = 
00420       docElement->getElementsByTagName(s);
00421     XMLString::release(&s);
00422 
00423     DOMNode* boundaries = binTags->item(0);
00424     
00425     // get the node needed to build a spectrometer 
00426     s = XMLString::transcode("ptbinres");
00427     DOMNodeList* ptbinresTags = 
00428       docElement->getElementsByTagName(s);
00429     XMLString::release(&s);
00430 
00431     // build the spectrometers
00432     
00433     for(XMLSize_t ptr=0; ptr<ptbinresTags->getLength();++ptr){
00434       
00435       ProtoSpectrometer thisPS(boundaries,
00436                                ptbinresTags->item(ptr),
00437                                ptr==0,
00438                                ptr==(ptbinresTags->getLength()-1));
00439       
00440       m_protoSpectrometers.push_back(thisPS);
00441       
00442     }
00443     
00444     std::map<int,std::string> sectorMap = makeSectorMap(boundaries);
00445     
00446     std::vector<ProtoSpectrometer>::iterator psItr = m_protoSpectrometers.begin();
00447     for (; psItr!=m_protoSpectrometers.end()-1; ++psItr){
00448       
00449       MuonSpectrometer newMS = (*psItr).combine(*(psItr+1));
00450       newMS.setSectorMap(sectorMap);
00451       m_muonSpectrometers.push_back(newMS);
00452       
00453     }
00454     
00455     // Free up memory from the ProtoSpectrometers as they're no longer needed
00456     m_protoSpectrometers.clear();
00457 
00458     // Delete the DOMDocument
00459     delete dom;
00460 
00461     // Clean up xerces-style. This should deallocate all memory used by Xerces
00462     // but doesn't seem to work. Nice one.
00463     XMLPlatformUtils::Terminate();
00464 
00465   }
00466   
00467   std::map<int,std::string> MuonResolutionCalculator::makeSectorMap(DOMNode* boundaries){
00468     
00469 
00470 
00471     DOMNode* node = getFirstChildTagByName(boundaries, "sectortypes");
00472 
00473     std::vector<DOMNode*> sectorTypeNodes =
00474       getAllChildTagsByName(node, "sectortype");
00475 
00476     AddToMap atm;
00477     std::map<int,std::string> sectorMap = std::for_each(sectorTypeNodes.begin(),
00478                                                         sectorTypeNodes.end(),
00479                                                         atm).getMap();
00480     return sectorMap;
00481     
00482   }
00483 
00484   double MuonResolutionCalculator::calculateResolution(const HepLorentzVector& avec){
00485 
00486     // check for appropriate MuonSpectrometer
00487     IsCorrectMuonSpectrometer icms(avec.perp());
00488     std::vector<MuonSpectrometer>::iterator msitr = find_if(m_muonSpectrometers.begin(),
00489                                                              m_muonSpectrometers.end(),
00490                                                              icms);
00491     if ( msitr == m_muonSpectrometers.end() ){
00492       // Could not find correct MuonSpectrometer, returning resolution of 1.0
00493       return 1.;
00494     }
00495     
00496     return (*msitr).calculateResolution(avec);    
00497   }
00498 
00499   void MuonResolutionCalculator::dump(std::string indent){
00500     indent += " ";
00501     std::cout<<indent<<"\nDump for MuonResolutionCalculator:\n";
00502     std::for_each(m_protoSpectrometers.begin(), 
00503                   m_protoSpectrometers.end(), 
00504                   AddToDump(indent));
00505     std::for_each(m_muonSpectrometers.begin(), 
00506                   m_muonSpectrometers.end(), 
00507                   AddToDump(indent));
00508     
00509   }      
00510   
00511 } // namespace Atlfast

Generated on Mon Sep 24 14:19:12 2007 for AtlfastAlgs by  doxygen 1.5.1