Fork me on GitHub

Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • modules/DualReadoutCalorimeter.cc

    r5eda6767 rde2e39d  
    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.;
    250249  while((particle = static_cast<Candidate*>(fItParticleInputArray->Next())))
    251250  {
    252251    const TLorentzVector &particlePosition = particle->Position;
    253252    ++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();
    258253
    259254    pdgCode = TMath::Abs(particle->PID);
     
    384379      fHCalTrackEnergy = 0.0;
    385380      fTrackEnergy = 0.0;
    386 
     381     
    387382      fECalTrackSigma = 0.0;
    388383      fHCalTrackSigma = 0.0;
    389384      fTrackSigma = 0.0;
    390 
     385     
    391386      fTowerTrackHits = 0;
    392387      fTowerPhotonHits = 0;
     
    395390      fHCalTowerTrackArray->Clear();
    396391      fTowerTrackArray->Clear();
    397 
     392   
    398393    }
    399394
     
    419414      }
    420415
    421 
     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     
    422447      // in Dual Readout we do not care if tracks are ECAL of HCAL
    423448      if(fECalTrackFractions[number] > 1.0E-9 || fHCalTrackFractions[number] > 1.0E-9)
    424       {
     449      { 
    425450        fTrackEnergy += energy;
    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)
     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)     
    427452        sigma = 0.0;
    428453        if(fHCalTrackFractions[number] > 0)
     
    430455        else
    431456          sigma = fECalResolutionFormula->Eval(0.0, fTowerEta, 0.0, momentum.E());
    432 
    433         if(sigma/momentum.E() < track->TrackResolution)
    434           energyGuess = ecalEnergy + hcalEnergy;
     457         
     458        if(sigma/momentum.E() < track->TrackResolution) 
     459          energyGuess = ecalEnergy + hcalEnergy;     
    435460        else
    436461          energyGuess = momentum.E();
    437 
     462             
    438463        fTrackSigma += (track->TrackResolution)*energyGuess*(track->TrackResolution)*energyGuess;
    439464        fTowerTrackArray->Add(track);
    440 
     465     
    441466      }
    442467      else
     
    471496
    472497    fTower->AddCandidate(particle);
    473     fTower->Position = position;
    474498  }
    475499
     
    484508
    485509  Candidate *track, *tower, *mother;
    486   Double_t energy, pt, eta, phi, r;
     510  Double_t energy, pt, eta, phi;
    487511  Double_t ecalEnergy, hcalEnergy;
    488512  Double_t ecalNeutralEnergy, hcalNeutralEnergy, neutralEnergy;
    489 
     513 
    490514  Double_t ecalSigma, hcalSigma, sigma;
    491515  Double_t ecalNeutralSigma, hcalNeutralSigma, neutralSigma;
    492516
    493517  Double_t weightTrack, weightCalo, bestEnergyEstimate, rescaleFactor;
    494 
     518 
    495519  TLorentzVector momentum;
    496520  TFractionMap::iterator itFractionMap;
     
    501525
    502526
    503   // if no hadronic energy, use ECAL resolution
     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
    504539  if (fHCalTowerEnergy <= fHCalEnergyMin)
    505540  {
     
    509544  }
    510545
    511   // if hadronic fraction > 0, use HCAL resolution
     546  // if hadronic fraction > 0, use HCAL resolution 
    512547  else
    513548  {
     
    519554  energy = LogNormal(energy, sigma);
    520555  //cout<<energy<<","<<ecalEnergy<<","<<hcalEnergy<<endl;
    521 
     556 
    522557  if(energy < fEnergyMin || energy < fEnergySignificanceMin*sigma) energy = 0.0;
    523558
     
    557592  for(size_t i = 0; i < fTower->ECalEnergyTimePairs.size(); ++i)
    558593  {
    559     weight = TMath::Power((fTower->ECalEnergyTimePairs[i].first),2);
     594    weight = TMath::Sqrt(fTower->ECalEnergyTimePairs[i].first);
    560595    sumWeightedTime += weight * fTower->ECalEnergyTimePairs[i].second;
    561596    sumWeight += weight;
     
    563598  }
    564599
    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);
     600  if(sumWeight > 0.0)
     601  {
     602    fTower->Position.SetPtEtaPhiE(1.0, eta, phi, sumWeightedTime/sumWeight);
     603  }
    568604  else
    569     r = fTower->Position.Pt();
    570 
    571   if(sumWeight > 0.0)
    572   {
    573     fTower->Position.SetPtEtaPhiE(r, eta, phi, sumWeightedTime/sumWeight);
    574   }
    575   else
    576   {
    577     fTower->Position.SetPtEtaPhiE(r, eta, phi, 999999.9);
     605  {
     606    fTower->Position.SetPtEtaPhiE(1.0, eta, phi, 999999.9);
    578607  }
    579608
     
    597626
    598627  // fill energy flow candidates
    599 
     628 
    600629  fTrackSigma = TMath::Sqrt(fTrackSigma);
    601630  neutralEnergy = max( (energy - fTrackEnergy) , 0.0);
     
    609638  if(neutralEnergy > fEnergyMin && neutralSigma > fEnergySignificanceMin)
    610639  {
    611 
     640   
    612641    //cout<<"significant neutral excess found:"<<endl;
    613642    // create new photon tower
     
    616645    //cout<<"Creating tower with Pt, Eta, Phi, Energy: "<<pt<<","<<eta<<","<<phi<<","<<neutralEnergy<<endl;
    617646    tower->Momentum.SetPtEtaPhiE(pt, eta, phi, neutralEnergy);
    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     }
     647    tower->Eem = neutralEnergy;
     648    tower->Ehad = 0.0;
     649    tower->PID = 22;
     650
     651   
    634652
    635653    fEFlowPhotonOutputArray->Add(tower);
     
    640658    while((track = static_cast<Candidate*>(fItTowerTrackArray->Next())))
    641659    {
     660      //cout<<"looping over tracks"<<endl;
    642661      mother = track;
    643662      track = static_cast<Candidate*>(track->Clone());
     
    647666  }
    648667
    649 
     668 
    650669  // if neutral excess is not significant, rescale eflow tracks, such that the total charged equals the best measurement given by the DualReadoutCalorimeter and tracking
    651670  else if(fTrackEnergy > 0.0)
     
    655674    weightCalo  = (sigma > 0.0) ? 1 / (sigma*sigma) : 0.0;
    656675
    657     bestEnergyEstimate = (weightTrack*fTrackEnergy + weightCalo*energy) / (weightTrack + weightCalo);
     676    bestEnergyEstimate = (weightTrack*fTrackEnergy + weightCalo*energy) / (weightTrack + weightCalo); 
    658677    rescaleFactor = bestEnergyEstimate/fTrackEnergy;
    659678
     
    661680    fItTowerTrackArray->Reset();
    662681    while((track = static_cast<Candidate*>(fItTowerTrackArray->Next())))
    663     {
     682    { 
    664683      mother = track;
    665       track = static_cast<Candidate *>(track->Clone());
     684      track = static_cast<Candidate*>(track->Clone());
    666685      track->AddCandidate(mother);
    667       track->Momentum.SetPtEtaPhiM(track->Momentum.Pt()*rescaleFactor, track->Momentum.Eta(), track->Momentum.Phi(), track->Momentum.M());
     686
     687      track->Momentum *= rescaleFactor;
     688
    668689      fEFlowTrackOutputArray->Add(track);
    669690    }
    670691  }
    671 
     692 
    672693
    673694}
Note: See TracChangeset for help on using the changeset viewer.