Fork me on GitHub

Ignore:
Timestamp:
Dec 9, 2021, 7:52:15 AM (3 years ago)
Author:
christinaw97 <christina.wang@…>
Children:
29b722a
Parents:
a5af1df (diff), 0c0c9af (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of github.com:Christinaw97/delphes into HEAD

File:
1 edited

Legend:

Unmodified
Added
Removed
  • modules/DualReadoutCalorimeter.cc

    ra5af1df rd612dec  
    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
     
    172172  fECalEnergyMin = GetDouble("ECalEnergyMin", 0.0);
    173173  fHCalEnergyMin = GetDouble("HCalEnergyMin", 0.0);
     174  fEnergyMin = GetDouble("EnergyMin", 0.0);
    174175
    175176  fECalEnergySignificanceMin = GetDouble("ECalEnergySignificanceMin", 0.0);
    176177  fHCalEnergySignificanceMin = GetDouble("HCalEnergySignificanceMin", 0.0);
     178  fEnergySignificanceMin = GetDouble("EnergySignificanceMin", 0.0);
    177179
    178180  // switch on or off the dithering of the center of DualReadoutCalorimeter towers
     
    245247  fItParticleInputArray->Reset();
    246248  number = -1;
     249  fTowerRmax=0.;
     250
     251  //cout<<"--------- new event ---------- "<<endl;
     252
    247253  while((particle = static_cast<Candidate*>(fItParticleInputArray->Next())))
    248254  {
    249255    const TLorentzVector &particlePosition = particle->Position;
    250256    ++number;
     257
     258    // compute maximum radius (needed in FinalizeTower to assess whether barrel or endcap tower)
     259    if (particlePosition.Perp() > fTowerRmax)
     260      fTowerRmax=particlePosition.Perp();
    251261
    252262    pdgCode = TMath::Abs(particle->PID);
     
    377387      fHCalTrackEnergy = 0.0;
    378388      fTrackEnergy = 0.0;
    379      
     389
    380390      fECalTrackSigma = 0.0;
    381391      fHCalTrackSigma = 0.0;
    382392      fTrackSigma = 0.0;
    383      
     393
    384394      fTowerTrackHits = 0;
    385395      fTowerPhotonHits = 0;
     396
     397      fTowerTime = 0.0;
     398      fTowerTimeWeight = 0.0;
    386399
    387400      fECalTowerTrackArray->Clear();
    388401      fHCalTowerTrackArray->Clear();
    389402      fTowerTrackArray->Clear();
    390    
     403
    391404    }
    392405
     
    412425      }
    413426
    414      
    415       /*
    416       if(fECalTrackFractions[number] > 1.0E-9 && fHCalTrackFractions[number] < 1.0E-9)
    417       {
    418         fECalTrackEnergy += ecalEnergy;
    419         ecalSigma = fECalResolutionFormula->Eval(0.0, fTowerEta, 0.0, momentum.E());       
    420         if(ecalSigma/momentum.E() < track->TrackResolution) energyGuess = ecalEnergy;       
    421         else energyGuess = momentum.E();
    422 
    423         fECalTrackSigma += (track->TrackResolution)*energyGuess*(track->TrackResolution)*energyGuess;
    424         fECalTowerTrackArray->Add(track);
    425       }
    426      
    427       else if(fECalTrackFractions[number] < 1.0E-9 && fHCalTrackFractions[number] > 1.0E-9)
    428       {
    429         fHCalTrackEnergy += hcalEnergy;
    430         hcalSigma = fHCalResolutionFormula->Eval(0.0, fTowerEta, 0.0, momentum.E());
    431         if(hcalSigma/momentum.E() < track->TrackResolution) energyGuess = hcalEnergy;
    432         else energyGuess = momentum.E();
    433 
    434         fHCalTrackSigma += (track->TrackResolution)*energyGuess*(track->TrackResolution)*energyGuess;
    435         fHCalTowerTrackArray->Add(track);
    436       }
    437      
    438       // muons
    439       else if(fECalTrackFractions[number] < 1.0E-9 && fHCalTrackFractions[number] < 1.0E-9)
    440       {
    441         fEFlowTrackOutputArray->Add(track);
    442       }
    443       */
    444      
    445427      // in Dual Readout we do not care if tracks are ECAL of HCAL
    446428      if(fECalTrackFractions[number] > 1.0E-9 || fHCalTrackFractions[number] > 1.0E-9)
    447       { 
     429      {
    448430        fTrackEnergy += energy;
    449         // 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)     
     431        // 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)
    450432        sigma = 0.0;
    451433        if(fHCalTrackFractions[number] > 0)
     
    453435        else
    454436          sigma = fECalResolutionFormula->Eval(0.0, fTowerEta, 0.0, momentum.E());
    455          
    456         if(sigma/momentum.E() < track->TrackResolution) 
    457           energyGuess = ecalEnergy + hcalEnergy;     
     437
     438        if(sigma/momentum.E() < track->TrackResolution)
     439          energyGuess = ecalEnergy + hcalEnergy;
    458440        else
    459441          energyGuess = momentum.E();
    460              
     442
    461443        fTrackSigma += (track->TrackResolution)*energyGuess*(track->TrackResolution)*energyGuess;
    462444        fTowerTrackArray->Add(track);
    463      
    464445      }
    465446      else
     
    478459    position = particle->Position;
    479460
     461
    480462    // fill current tower
    481463    ecalEnergy = momentum.E() * fECalTowerFractions[number];
     
    485467    fHCalTowerEnergy += hcalEnergy;
    486468
    487     if(ecalEnergy > fTimingEnergyMin && fTower)
    488     {
    489       if (abs(particle->PID) != 11 || !fElectronsFromTrack)
    490       {
    491         fTower->ECalEnergyTimePairs.push_back(make_pair<Float_t, Float_t>(ecalEnergy, particle->Position.T()));
    492       }
    493     }
     469    // assume combined timing measurements in ECAL/HCAL sections
     470    fTowerTime += (ecalEnergy + hcalEnergy) * position.T(); //sigma_t ~ 1/sqrt(E)
     471    fTowerTimeWeight += ecalEnergy + hcalEnergy;
    494472
    495473    fTower->AddCandidate(particle);
     474    fTower->Position = position;
    496475  }
    497476
     
    506485
    507486  Candidate *track, *tower, *mother;
    508   Double_t energy, pt, eta, phi;
     487  Double_t energy, pt, eta, phi, r, time;
    509488  Double_t ecalEnergy, hcalEnergy;
    510489  Double_t ecalNeutralEnergy, hcalNeutralEnergy, neutralEnergy;
    511  
     490
    512491  Double_t ecalSigma, hcalSigma, sigma;
    513492  Double_t ecalNeutralSigma, hcalNeutralSigma, neutralSigma;
    514493
    515494  Double_t weightTrack, weightCalo, bestEnergyEstimate, rescaleFactor;
    516  
     495
    517496  TLorentzVector momentum;
    518497  TFractionMap::iterator itFractionMap;
     
    522501  if(!fTower) return;
    523502
    524 
    525   //if (fHCalTowerEnergy < 30 && fECalTowerEnergy < 30) return;
    526   //cout<<"----------- New tower ---------"<<endl;
    527 
    528 
    529   // 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.
    530   // For example, if overlapping charged pions and photons take hadronic resolution as combined measurement
    531 
    532   // if no hadronic fraction at all, then use ECAL resolution
    533 
    534   //cout<<"fECalTowerEnergy: "<<fECalTowerEnergy<<", fHCalTowerEnergy: "<<fHCalTowerEnergy<<", Eta: "<<fTowerEta<<endl;
    535 
    536   // if no hadronic energy, use ECAL resolution
     503  // if no hadronic energy, use ECAL resolution
    537504  if (fHCalTowerEnergy <= fHCalEnergyMin)
    538505  {
    539506    energy = fECalTowerEnergy;
    540507    sigma  = fECalResolutionFormula->Eval(0.0, fTowerEta, 0.0, energy);
    541     //cout<<"em energy"<<energy<<", sigma: "<<sigma<<endl;
    542   }
    543 
    544   // if hadronic fraction > 0, use HCAL resolution
     508  }
     509
     510  // if hadronic fraction > 0, use HCAL resolution
    545511  else
    546512  {
    547513    energy = fECalTowerEnergy + fHCalTowerEnergy;
    548514    sigma  = fHCalResolutionFormula->Eval(0.0, fTowerEta, 0.0, energy);
    549     //cout<<"had energy: "<<energy<<", sigma: "<<sigma<<endl;
    550515  }
    551516
    552517  energy = LogNormal(energy, sigma);
    553   //cout<<energy<<","<<ecalEnergy<<","<<hcalEnergy<<endl;
    554  
     518
    555519  if(energy < fEnergyMin || energy < fEnergySignificanceMin*sigma) energy = 0.0;
    556520
     
    562526  hcalEnergy = LogNormal(fHCalTowerEnergy, hcalSigma);
    563527
     528  time = (fTowerTimeWeight < 1.0E-09) ? 0.0 : fTowerTime / fTowerTimeWeight;
     529
    564530  ecalSigma = fECalResolutionFormula->Eval(0.0, fTowerEta, 0.0, ecalEnergy);
    565531  hcalSigma = fHCalResolutionFormula->Eval(0.0, fTowerEta, 0.0, hcalEnergy);
     
    568534  if(hcalEnergy < fHCalEnergyMin || hcalEnergy < fHCalEnergySignificanceMin*hcalSigma) hcalEnergy = 0.0;
    569535
    570   //cout<<"Measured energy: "<<energy<<endl;
    571 
    572536  if(fSmearTowerCenter)
    573537  {
     
    583547  pt = energy / TMath::CosH(eta);
    584548
    585   // Time calculation for tower
    586   fTower->NTimeHits = 0;
    587   sumWeightedTime = 0.0;
    588   sumWeight = 0.0;
    589 
    590   for(size_t i = 0; i < fTower->ECalEnergyTimePairs.size(); ++i)
    591   {
    592     weight = TMath::Sqrt(fTower->ECalEnergyTimePairs[i].first);
    593     sumWeightedTime += weight * fTower->ECalEnergyTimePairs[i].second;
    594     sumWeight += weight;
    595     fTower->NTimeHits++;
    596   }
    597 
    598   if(sumWeight > 0.0)
    599   {
    600     fTower->Position.SetPtEtaPhiE(1.0, eta, phi, sumWeightedTime/sumWeight);
    601   }
    602   else
    603   {
    604     fTower->Position.SetPtEtaPhiE(1.0, eta, phi, 999999.9);
    605   }
     549  // check whether barrel or endcap tower
     550
     551  // endcap
     552  if (TMath::Abs(fTower->Position.Pt() - fTowerRmax) > 1.e-06 && TMath::Abs(eta) > 0.){
     553    r = fTower->Position.Z()/TMath::SinH(eta);
     554  }
     555  // barrel
     556  else {
     557    r = fTower->Position.Pt();
     558  }
     559
     560  fTower->Position.SetPtEtaPhiE(r, eta, phi, time);
     561  fTower->Momentum.SetPtEtaPhiE(pt, eta, phi, energy);
     562  fTower->L = fTower->Position.Vect().Mag();
    606563
    607564  fTower->Momentum.SetPtEtaPhiE(pt, eta, phi, energy);
    608565  fTower->Eem = ecalEnergy;
    609566  fTower->Ehad = hcalEnergy;
    610 
     567  fTower->Etrk = fTrackEnergy;
    611568  fTower->Edges[0] = fTowerEdges[0];
    612569  fTower->Edges[1] = fTowerEdges[1];
     
    624581
    625582  // fill energy flow candidates
    626  
     583
    627584  fTrackSigma = TMath::Sqrt(fTrackSigma);
    628585  neutralEnergy = max( (energy - fTrackEnergy) , 0.0);
    629586  neutralSigma = neutralEnergy / TMath::Sqrt(fTrackSigma*fTrackSigma + sigma*sigma);
    630587
    631   //cout<<"trackEnergy: "<<fTrackEnergy<<", trackSigma: "<<fTrackSigma<<", Ntracks: "<<fTowerTrackArray->GetEntries()<<endl;
    632 
    633   //cout<<"neutralEnergy: "<<neutralEnergy<<", neutralSigma: "<<neutralSigma<<endl;
    634 
    635    // For now, if neutral excess is significant, simply create neutral EflowPhoton tower and clone each track into eflowtrack !!! -> Creating only photons !! EFlowNeutralHadron collection will be empy!!! TO BE FIXED
    636588  if(neutralEnergy > fEnergyMin && neutralSigma > fEnergySignificanceMin)
    637589  {
    638    
    639     //cout<<"significant neutral excess found:"<<endl;
    640590    // create new photon tower
    641591    tower = static_cast<Candidate*>(fTower->Clone());
    642     pt =  neutralEnergy / TMath::CosH(eta);
    643     //cout<<"Creating tower with Pt, Eta, Phi, Energy: "<<pt<<","<<eta<<","<<phi<<","<<neutralEnergy<<endl;
     592    pt = neutralEnergy / TMath::CosH(eta);
    644593    tower->Momentum.SetPtEtaPhiE(pt, eta, phi, neutralEnergy);
    645     tower->Eem = neutralEnergy;
    646     tower->Ehad = 0.0;
    647     tower->PID = 22;
    648 
    649     fEFlowPhotonOutputArray->Add(tower);
    650 
     594
     595    // if no hadronic energy, use ECAL resolution
     596    if (fHCalTowerEnergy <= fHCalEnergyMin)
     597    {
     598      tower->Eem = neutralEnergy;
     599      tower->Ehad = 0.0;
     600      tower->PID = 22;
     601      fEFlowPhotonOutputArray->Add(tower);
     602    }
     603    // if hadronic fraction > 0, use HCAL resolution
     604    else
     605    {
     606      tower->Eem = 0;
     607      tower->Ehad = neutralEnergy;
     608      tower->PID = 130;
     609      fEFlowNeutralHadronOutputArray->Add(tower);
     610    }
    651611
    652612    //clone tracks
     
    654614    while((track = static_cast<Candidate*>(fItTowerTrackArray->Next())))
    655615    {
    656       //cout<<"looping over tracks"<<endl;
    657616      mother = track;
    658617      track = static_cast<Candidate*>(track->Clone());
     
    662621  }
    663622
    664  
     623
    665624  // if neutral excess is not significant, rescale eflow tracks, such that the total charged equals the best measurement given by the DualReadoutCalorimeter and tracking
    666625  else if(fTrackEnergy > 0.0)
     
    670629    weightCalo  = (sigma > 0.0) ? 1 / (sigma*sigma) : 0.0;
    671630
    672     bestEnergyEstimate = (weightTrack*fTrackEnergy + weightCalo*energy) / (weightTrack + weightCalo); 
     631    bestEnergyEstimate = (weightTrack*fTrackEnergy + weightCalo*energy) / (weightTrack + weightCalo);
    673632    rescaleFactor = bestEnergyEstimate/fTrackEnergy;
    674633
     
    676635    fItTowerTrackArray->Reset();
    677636    while((track = static_cast<Candidate*>(fItTowerTrackArray->Next())))
    678     { 
     637    {
    679638      mother = track;
    680       track = static_cast<Candidate*>(track->Clone());
     639      track = static_cast<Candidate *>(track->Clone());
    681640      track->AddCandidate(mother);
    682 
    683       track->Momentum *= rescaleFactor;
    684 
     641      track->Momentum.SetPtEtaPhiM(track->Momentum.Pt()*rescaleFactor, track->Momentum.Eta(), track->Momentum.Phi(), track->Momentum.M());
    685642      fEFlowTrackOutputArray->Add(track);
    686643    }
    687644  }
    688  
    689 
    690   /*
    691   // fill energy flow candidates
    692   fECalTrackSigma = TMath::Sqrt(fECalTrackSigma);
    693   fHCalTrackSigma = TMath::Sqrt(fHCalTrackSigma);
    694 
    695   //compute neutral excesses
    696   ecalNeutralEnergy = max( (ecalEnergy - fECalTrackEnergy) , 0.0);
    697   hcalNeutralEnergy = max( (hcalEnergy - fHCalTrackEnergy) , 0.0);
    698  
    699   ecalNeutralSigma = ecalNeutralEnergy / TMath::Sqrt(fECalTrackSigma*fECalTrackSigma + ecalSigma*ecalSigma);
    700   hcalNeutralSigma = hcalNeutralEnergy / TMath::Sqrt(fHCalTrackSigma*fHCalTrackSigma + hcalSigma*hcalSigma);
    701  
    702    // if ecal neutral excess is significant, simply create neutral EflowPhoton tower and clone each track into eflowtrack
    703   if(ecalNeutralEnergy > fECalEnergyMin && ecalNeutralSigma > fECalEnergySignificanceMin)
    704   {
    705     // create new photon tower
    706     tower = static_cast<Candidate*>(fTower->Clone());
    707     pt =  ecalNeutralEnergy / TMath::CosH(eta);
    708    
    709     tower->Momentum.SetPtEtaPhiE(pt, eta, phi, ecalNeutralEnergy);
    710     tower->Eem = ecalNeutralEnergy;
    711     tower->Ehad = 0.0;
    712     tower->PID = 22;
    713    
    714     fEFlowPhotonOutputArray->Add(tower);
    715    
    716     //clone tracks
    717     fItECalTowerTrackArray->Reset();
    718     while((track = static_cast<Candidate*>(fItECalTowerTrackArray->Next())))
    719     {
    720       mother = track;
    721       track = static_cast<Candidate*>(track->Clone());
    722       track->AddCandidate(mother);
    723 
    724       fEFlowTrackOutputArray->Add(track);
    725     }
    726  
    727   }
    728  
    729   // if neutral excess is not significant, rescale eflow tracks, such that the total charged equals the best measurement given by the DualReadoutCalorimeter and tracking
    730   else if(fECalTrackEnergy > 0.0)
    731   {
    732     weightTrack = (fECalTrackSigma > 0.0) ? 1 / (fECalTrackSigma*fECalTrackSigma) : 0.0;
    733     weightCalo  = (ecalSigma > 0.0) ? 1 / (ecalSigma*ecalSigma) : 0.0;
    734  
    735     bestEnergyEstimate = (weightTrack*fECalTrackEnergy + weightCalo*ecalEnergy) / (weightTrack + weightCalo);
    736     rescaleFactor = bestEnergyEstimate/fECalTrackEnergy;
    737 
    738     //rescale tracks
    739     fItECalTowerTrackArray->Reset();
    740     while((track = static_cast<Candidate*>(fItECalTowerTrackArray->Next())))
    741     { 
    742       mother = track;
    743       track = static_cast<Candidate*>(track->Clone());
    744       track->AddCandidate(mother);
    745 
    746       track->Momentum *= rescaleFactor;
    747 
    748       fEFlowTrackOutputArray->Add(track);
    749     }
    750   }
    751 
    752 
    753   // if hcal neutral excess is significant, simply create neutral EflowNeutralHadron tower and clone each track into eflowtrack
    754   if(hcalNeutralEnergy > fHCalEnergyMin && hcalNeutralSigma > fHCalEnergySignificanceMin)
    755   {
    756     // create new photon tower
    757     tower = static_cast<Candidate*>(fTower->Clone());
    758     pt =  hcalNeutralEnergy / TMath::CosH(eta);
    759    
    760     tower->Momentum.SetPtEtaPhiE(pt, eta, phi, hcalNeutralEnergy);
    761     tower->Ehad = hcalNeutralEnergy;
    762     tower->Eem = 0.0;
    763    
    764     fEFlowNeutralHadronOutputArray->Add(tower);
    765    
    766     //clone tracks
    767     fItHCalTowerTrackArray->Reset();
    768     while((track = static_cast<Candidate*>(fItHCalTowerTrackArray->Next())))
    769     {
    770       mother = track;
    771       track = static_cast<Candidate*>(track->Clone());
    772       track->AddCandidate(mother);
    773 
    774       fEFlowTrackOutputArray->Add(track);
    775     }
    776  
    777   }
    778  
    779   // if neutral excess is not significant, rescale eflow tracks, such that the total charged equals the best measurement given by the DualReadoutCalorimeter and tracking
    780   else if(fHCalTrackEnergy > 0.0)
    781   {
    782     weightTrack = (fHCalTrackSigma > 0.0) ? 1 / (fHCalTrackSigma*fHCalTrackSigma) : 0.0;
    783     weightCalo  = (hcalSigma > 0.0) ? 1 / (hcalSigma*hcalSigma) : 0.0;
    784  
    785     bestEnergyEstimate = (weightTrack*fHCalTrackEnergy + weightCalo*hcalEnergy) / (weightTrack + weightCalo);
    786     rescaleFactor = bestEnergyEstimate / fHCalTrackEnergy;
    787 
    788     //rescale tracks
    789     fItHCalTowerTrackArray->Reset();
    790     while((track = static_cast<Candidate*>(fItHCalTowerTrackArray->Next())))
    791     { 
    792       mother = track;
    793       track = static_cast<Candidate*>(track->Clone());
    794       track->AddCandidate(mother);
    795 
    796       track->Momentum *= rescaleFactor;
    797 
    798       fEFlowTrackOutputArray->Add(track);
    799     }
    800   }
    801 
    802   */
     645
     646
    803647}
    804648
Note: See TracChangeset for help on using the changeset viewer.