Fork me on GitHub

Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • modules/DualReadoutCalorimeter.cc

    rde2e39d r5eda6767  
    2424  // This implementation of dual calorimetry relies on several approximations:
    2525  // - If hadronic energy is found in the tower the energy resolution then the full tower enrgy is smeared according to hadronic resolution (pessimistic for (e,n) or (pi+,gamma))
    26   // - While e+ vs pi+ (or gamma vs n) separation is in principle possible for single particles (using C/S, PMT timing, lateral shower profile) it is not obvious it can be done overlapping particles. 
     26  // - While e+ vs pi+ (or gamma vs n) separation is in principle possible for single particles (using C/S, PMT timing, lateral shower profile) it is not obvious it can be done overlapping particles.
    2727  //   Now we assume that regarless of the number of particle hits per tower we can always distinguish e+ vs pi+, which is probably not true in the case (e+,n) vs (pi+,gamma) without longitudinal segmentation.
    2828
     
    6363  fItParticleInputArray(0), fItTrackInputArray(0)
    6464{
    65  
     65
    6666  fECalResolutionFormula = new DelphesFormula;
    6767  fHCalResolutionFormula = new DelphesFormula;
     
    7575  fTowerTrackArray = new TObjArray;
    7676  fItTowerTrackArray = fTowerTrackArray->MakeIterator();
    77  
     77
    7878}
    7979
     
    8282DualReadoutCalorimeter::~DualReadoutCalorimeter()
    8383{
    84  
     84
    8585  if(fECalResolutionFormula) delete fECalResolutionFormula;
    8686  if(fHCalResolutionFormula) delete fHCalResolutionFormula;
     
    9494  if(fTowerTrackArray) delete fTowerTrackArray;
    9595  if(fItTowerTrackArray) delete fItTowerTrackArray;
    96  
     96
    9797}
    9898
     
    247247  fItParticleInputArray->Reset();
    248248  number = -1;
     249  fTowerRmax=0.;
    249250  while((particle = static_cast<Candidate*>(fItParticleInputArray->Next())))
    250251  {
    251252    const TLorentzVector &particlePosition = particle->Position;
    252253    ++number;
     254
     255    // compute maximum radius (needed in FinalizeTower to assess whether barrel or endcap tower)
     256    if (particlePosition.Perp() > fTowerRmax)
     257      fTowerRmax=particlePosition.Perp();
    253258
    254259    pdgCode = TMath::Abs(particle->PID);
     
    379384      fHCalTrackEnergy = 0.0;
    380385      fTrackEnergy = 0.0;
    381      
     386
    382387      fECalTrackSigma = 0.0;
    383388      fHCalTrackSigma = 0.0;
    384389      fTrackSigma = 0.0;
    385      
     390
    386391      fTowerTrackHits = 0;
    387392      fTowerPhotonHits = 0;
     
    390395      fHCalTowerTrackArray->Clear();
    391396      fTowerTrackArray->Clear();
    392    
     397
    393398    }
    394399
     
    414419      }
    415420
    416      
    417       /*
    418       if(fECalTrackFractions[number] > 1.0E-9 && fHCalTrackFractions[number] < 1.0E-9)
    419       {
    420         fECalTrackEnergy += ecalEnergy;
    421         ecalSigma = fECalResolutionFormula->Eval(0.0, fTowerEta, 0.0, momentum.E());       
    422         if(ecalSigma/momentum.E() < track->TrackResolution) energyGuess = ecalEnergy;       
    423         else energyGuess = momentum.E();
    424 
    425         fECalTrackSigma += (track->TrackResolution)*energyGuess*(track->TrackResolution)*energyGuess;
    426         fECalTowerTrackArray->Add(track);
    427       }
    428      
    429       else if(fECalTrackFractions[number] < 1.0E-9 && fHCalTrackFractions[number] > 1.0E-9)
    430       {
    431         fHCalTrackEnergy += hcalEnergy;
    432         hcalSigma = fHCalResolutionFormula->Eval(0.0, fTowerEta, 0.0, momentum.E());
    433         if(hcalSigma/momentum.E() < track->TrackResolution) energyGuess = hcalEnergy;
    434         else energyGuess = momentum.E();
    435 
    436         fHCalTrackSigma += (track->TrackResolution)*energyGuess*(track->TrackResolution)*energyGuess;
    437         fHCalTowerTrackArray->Add(track);
    438       }
    439      
    440       // muons
    441       else if(fECalTrackFractions[number] < 1.0E-9 && fHCalTrackFractions[number] < 1.0E-9)
    442       {
    443         fEFlowTrackOutputArray->Add(track);
    444       }
    445       */
    446      
     421
    447422      // in Dual Readout we do not care if tracks are ECAL of HCAL
    448423      if(fECalTrackFractions[number] > 1.0E-9 || fHCalTrackFractions[number] > 1.0E-9)
    449       { 
     424      {
    450425        fTrackEnergy += energy;
    451         // this sigma will be used to determine whether neutral excess is significant. We choose the resolution according to bthe higest deposited fraction (in practice had for charged hadrons and em for electrons)     
     426        // this sigma will be used to determine whether neutral excess is significant. We choose the resolution according to bthe higest deposited fraction (in practice had for charged hadrons and em for electrons)
    452427        sigma = 0.0;
    453428        if(fHCalTrackFractions[number] > 0)
     
    455430        else
    456431          sigma = fECalResolutionFormula->Eval(0.0, fTowerEta, 0.0, momentum.E());
    457          
    458         if(sigma/momentum.E() < track->TrackResolution) 
    459           energyGuess = ecalEnergy + hcalEnergy;     
     432
     433        if(sigma/momentum.E() < track->TrackResolution)
     434          energyGuess = ecalEnergy + hcalEnergy;
    460435        else
    461436          energyGuess = momentum.E();
    462              
     437
    463438        fTrackSigma += (track->TrackResolution)*energyGuess*(track->TrackResolution)*energyGuess;
    464439        fTowerTrackArray->Add(track);
    465      
     440
    466441      }
    467442      else
     
    496471
    497472    fTower->AddCandidate(particle);
     473    fTower->Position = position;
    498474  }
    499475
     
    508484
    509485  Candidate *track, *tower, *mother;
    510   Double_t energy, pt, eta, phi;
     486  Double_t energy, pt, eta, phi, r;
    511487  Double_t ecalEnergy, hcalEnergy;
    512488  Double_t ecalNeutralEnergy, hcalNeutralEnergy, neutralEnergy;
    513  
     489
    514490  Double_t ecalSigma, hcalSigma, sigma;
    515491  Double_t ecalNeutralSigma, hcalNeutralSigma, neutralSigma;
    516492
    517493  Double_t weightTrack, weightCalo, bestEnergyEstimate, rescaleFactor;
    518  
     494
    519495  TLorentzVector momentum;
    520496  TFractionMap::iterator itFractionMap;
     
    525501
    526502
    527   //if (fHCalTowerEnergy < 30 && fECalTowerEnergy < 30) return;
    528   //cout<<"----------- New tower ---------"<<endl;
    529 
    530 
    531   // here we change behaviour w.r.t to standard calorimeter. Start with worse case scenario. If fHCalTowerEnergy > 0, assume total energy smeared by HCAL resolution.
    532   // For example, if overlapping charged pions and photons take hadronic resolution as combined measurement
    533 
    534   // if no hadronic fraction at all, then use ECAL resolution
    535 
    536   //cout<<"fECalTowerEnergy: "<<fECalTowerEnergy<<", fHCalTowerEnergy: "<<fHCalTowerEnergy<<", Eta: "<<fTowerEta<<endl;
    537 
    538   // if no hadronic energy, use ECAL resolution
     503  // if no hadronic energy, use ECAL resolution
    539504  if (fHCalTowerEnergy <= fHCalEnergyMin)
    540505  {
     
    544509  }
    545510
    546   // if hadronic fraction > 0, use HCAL resolution 
     511  // if hadronic fraction > 0, use HCAL resolution
    547512  else
    548513  {
     
    554519  energy = LogNormal(energy, sigma);
    555520  //cout<<energy<<","<<ecalEnergy<<","<<hcalEnergy<<endl;
    556  
     521
    557522  if(energy < fEnergyMin || energy < fEnergySignificanceMin*sigma) energy = 0.0;
    558523
     
    592557  for(size_t i = 0; i < fTower->ECalEnergyTimePairs.size(); ++i)
    593558  {
    594     weight = TMath::Sqrt(fTower->ECalEnergyTimePairs[i].first);
     559    weight = TMath::Power((fTower->ECalEnergyTimePairs[i].first),2);
    595560    sumWeightedTime += weight * fTower->ECalEnergyTimePairs[i].second;
    596561    sumWeight += weight;
     
    598563  }
    599564
     565  // check whether barrel or endcap tower
     566  if (fTower->Position.Perp() < fTowerRmax && TMath::Abs(eta) > 0.)
     567    r = fTower->Position.Z()/TMath::SinH(eta);
     568  else
     569    r = fTower->Position.Pt();
     570
    600571  if(sumWeight > 0.0)
    601572  {
    602     fTower->Position.SetPtEtaPhiE(1.0, eta, phi, sumWeightedTime/sumWeight);
     573    fTower->Position.SetPtEtaPhiE(r, eta, phi, sumWeightedTime/sumWeight);
    603574  }
    604575  else
    605576  {
    606     fTower->Position.SetPtEtaPhiE(1.0, eta, phi, 999999.9);
     577    fTower->Position.SetPtEtaPhiE(r, eta, phi, 999999.9);
    607578  }
    608579
     
    626597
    627598  // fill energy flow candidates
    628  
     599
    629600  fTrackSigma = TMath::Sqrt(fTrackSigma);
    630601  neutralEnergy = max( (energy - fTrackEnergy) , 0.0);
     
    638609  if(neutralEnergy > fEnergyMin && neutralSigma > fEnergySignificanceMin)
    639610  {
    640    
     611
    641612    //cout<<"significant neutral excess found:"<<endl;
    642613    // create new photon tower
     
    645616    //cout<<"Creating tower with Pt, Eta, Phi, Energy: "<<pt<<","<<eta<<","<<phi<<","<<neutralEnergy<<endl;
    646617    tower->Momentum.SetPtEtaPhiE(pt, eta, phi, neutralEnergy);
    647     tower->Eem = neutralEnergy;
    648     tower->Ehad = 0.0;
    649     tower->PID = 22;
    650 
    651    
     618
     619    // if no hadronic energy, use ECAL resolution
     620    if (fHCalTowerEnergy <= fHCalEnergyMin)
     621    {
     622      tower->Eem = neutralEnergy;
     623      tower->Ehad = 0.0;
     624      tower->PID = 22;
     625    }
     626
     627    // if hadronic fraction > 0, use HCAL resolution
     628    else
     629    {
     630      tower->Eem = 0;
     631      tower->Ehad = neutralEnergy;
     632      tower->PID = 130;
     633    }
    652634
    653635    fEFlowPhotonOutputArray->Add(tower);
     
    658640    while((track = static_cast<Candidate*>(fItTowerTrackArray->Next())))
    659641    {
    660       //cout<<"looping over tracks"<<endl;
    661642      mother = track;
    662643      track = static_cast<Candidate*>(track->Clone());
     
    666647  }
    667648
    668  
     649
    669650  // if neutral excess is not significant, rescale eflow tracks, such that the total charged equals the best measurement given by the DualReadoutCalorimeter and tracking
    670651  else if(fTrackEnergy > 0.0)
     
    674655    weightCalo  = (sigma > 0.0) ? 1 / (sigma*sigma) : 0.0;
    675656
    676     bestEnergyEstimate = (weightTrack*fTrackEnergy + weightCalo*energy) / (weightTrack + weightCalo); 
     657    bestEnergyEstimate = (weightTrack*fTrackEnergy + weightCalo*energy) / (weightTrack + weightCalo);
    677658    rescaleFactor = bestEnergyEstimate/fTrackEnergy;
    678659
     
    680661    fItTowerTrackArray->Reset();
    681662    while((track = static_cast<Candidate*>(fItTowerTrackArray->Next())))
    682     { 
     663    {
    683664      mother = track;
    684       track = static_cast<Candidate*>(track->Clone());
     665      track = static_cast<Candidate *>(track->Clone());
    685666      track->AddCandidate(mother);
    686 
    687       track->Momentum *= rescaleFactor;
    688 
     667      track->Momentum.SetPtEtaPhiM(track->Momentum.Pt()*rescaleFactor, track->Momentum.Eta(), track->Momentum.Phi(), track->Momentum.M());
    689668      fEFlowTrackOutputArray->Add(track);
    690669    }
    691670  }
    692  
     671
    693672
    694673}
Note: See TracChangeset for help on using the changeset viewer.