File indexing completed on 2024-04-06 12:25:19
0001
0002
0003
0004
0005
0006 #include "DataFormats/Common/interface/Handle.h"
0007 #include "DataFormats/Common/interface/View.h"
0008 #include "DataFormats/JetReco/interface/Jet.h"
0009 #include "DataFormats/Math/interface/deltaR.h"
0010 #include "DataFormats/PatCandidates/interface/PackedCandidate.h"
0011 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h"
0012 #include "DataFormats/Provenance/interface/EventID.h"
0013 #include "FWCore/Framework/interface/Event.h"
0014 #include "FWCore/Framework/interface/MakerMacros.h"
0015 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0016 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0017 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0018 #include "FWCore/ParameterSet/interface/ParameterSetDescriptionFiller.h"
0019 #include "DataFormats/HeavyIonEvent/interface/EvtPlane.h"
0020 #include "DataFormats/JetReco/interface/JetCollection.h"
0021 #include "FWCore/Framework/interface/stream/EDProducer.h"
0022 #include "FWCore/Utilities/interface/StreamID.h"
0023 #include "FWCore/Utilities/interface/EDGetToken.h"
0024 #include "RecoHI/HiEvtPlaneAlgos/interface/HiEvtPlaneList.h"
0025
0026 #include "TF1.h"
0027 #include "TF2.h"
0028 #include "TH1.h"
0029 #include "TMath.h"
0030 #include "Math/ProbFuncMathCore.h"
0031 #include "TMinuitMinimizer.h"
0032
0033 #include <algorithm>
0034 #include <cmath>
0035 #include <memory>
0036 #include <string>
0037 #include <utility>
0038 #include <vector>
0039
0040 namespace {
0041
0042 double flowFunction(double* x, double* par) {
0043 unsigned int nFlow = par[0];
0044 unsigned int firstFittedVn = par[1];
0045
0046
0047 double flowModulation = par[2];
0048 for (unsigned int iFlow = 0; iFlow < nFlow; iFlow++) {
0049 flowModulation +=
0050 par[2] * 2.0 * par[2 * iFlow + 3] * std::cos((iFlow + firstFittedVn) * (x[0] - par[2 * iFlow + 4]));
0051 }
0052 return flowModulation;
0053 }
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 double weightFunction(double* x, double* par) {
0065
0066 if (x[0] > par[1])
0067 return 0;
0068
0069
0070 double exclusionArea = std::sqrt(par[1] * par[1] - x[0] * x[0]);
0071
0072
0073
0074
0075 if (x[1] > par[0]) {
0076
0077 if (x[1] - exclusionArea > par[0])
0078 return 0;
0079
0080
0081 exclusionArea += par[0] - x[1];
0082
0083 } else {
0084
0085 if (x[1] + exclusionArea > par[0]) {
0086 exclusionArea += par[0] - x[1];
0087 } else {
0088
0089 exclusionArea *= 2;
0090 }
0091 }
0092
0093
0094 return (2 * par[0]) / (2 * par[0] - exclusionArea) - 1;
0095 }
0096 };
0097
0098 class HiFJRhoFlowModulationProducer : public edm::stream::EDProducer<> {
0099 public:
0100 explicit HiFJRhoFlowModulationProducer(const edm::ParameterSet&);
0101 static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0102
0103 private:
0104 void beginStream(edm::StreamID) override;
0105 void produce(edm::Event&, const edm::EventSetup&) override;
0106 void endStream() override;
0107
0108 const int minPfCandidatesPerEvent_;
0109 const bool doEvtPlane_;
0110 const bool doFreePlaneFit_;
0111 const bool doJettyExclusion_;
0112 const double exclusionRadius_;
0113 const int evtPlaneLevel_;
0114 const double pfCandidateEtaCut_;
0115 const double pfCandidateMinPtCut_;
0116 const double pfCandidateMaxPtCut_;
0117 int firstFittedVn_;
0118 int lastFittedVn_;
0119 const edm::EDGetTokenT<reco::JetView> jetToken_;
0120 const edm::EDGetTokenT<pat::PackedCandidateCollection> pfCandidateToken_;
0121 const edm::EDGetTokenT<reco::EvtPlaneCollection> evtPlaneToken_;
0122 std::unique_ptr<TF1> flowFit_p_;
0123 std::unique_ptr<TF2> pfWeightFunction_;
0124 reco::PFCandidate converter_;
0125 };
0126 HiFJRhoFlowModulationProducer::HiFJRhoFlowModulationProducer(const edm::ParameterSet& iConfig)
0127 : minPfCandidatesPerEvent_(iConfig.getParameter<int>("minPfCandidatesPerEvent")),
0128 doEvtPlane_(iConfig.getParameter<bool>("doEvtPlane")),
0129 doFreePlaneFit_(iConfig.getParameter<bool>("doFreePlaneFit")),
0130 doJettyExclusion_(iConfig.getParameter<bool>("doJettyExclusion")),
0131 exclusionRadius_(iConfig.getParameter<double>("exclusionRadius")),
0132 evtPlaneLevel_(iConfig.getParameter<int>("evtPlaneLevel")),
0133 pfCandidateEtaCut_(iConfig.getParameter<double>("pfCandidateEtaCut")),
0134 pfCandidateMinPtCut_(iConfig.getParameter<double>("pfCandidateMinPtCut")),
0135 pfCandidateMaxPtCut_(iConfig.getParameter<double>("pfCandidateMaxPtCut")),
0136 firstFittedVn_(iConfig.getParameter<int>("firstFittedVn")),
0137 lastFittedVn_(iConfig.getParameter<int>("lastFittedVn")),
0138 jetToken_(doJettyExclusion_ ? consumes<reco::JetView>(iConfig.getParameter<edm::InputTag>("jetTag"))
0139 : edm::EDGetTokenT<reco::JetView>()),
0140 pfCandidateToken_(consumes<pat::PackedCandidateCollection>(iConfig.getParameter<edm::InputTag>("pfCandSource"))),
0141 evtPlaneToken_(consumes<reco::EvtPlaneCollection>(iConfig.getParameter<edm::InputTag>("EvtPlane"))) {
0142 produces<std::vector<double>>("rhoFlowFitParams");
0143
0144
0145 converter_ = reco::PFCandidate();
0146
0147
0148 if (firstFittedVn_ < 1)
0149 firstFittedVn_ = 2;
0150 if (lastFittedVn_ < 1)
0151 lastFittedVn_ = 2;
0152 if (firstFittedVn_ > lastFittedVn_) {
0153 int flipper = lastFittedVn_;
0154 lastFittedVn_ = firstFittedVn_;
0155 firstFittedVn_ = flipper;
0156 }
0157
0158
0159 const int nFlow = lastFittedVn_ - firstFittedVn_ + 1;
0160
0161
0162 TMinuitMinimizer::UseStaticMinuit(false);
0163 flowFit_p_ = std::make_unique<TF1>("flowFit", flowFunction, -TMath::Pi(), TMath::Pi(), nFlow * 2 + 3);
0164 flowFit_p_->FixParameter(0, nFlow);
0165 flowFit_p_->FixParameter(1, firstFittedVn_);
0166 pfWeightFunction_ = std::make_unique<TF2>("weightFunction", weightFunction, 0, TMath::Pi(), -5, 5, 2);
0167 pfWeightFunction_->SetParameter(0, pfCandidateEtaCut_);
0168 pfWeightFunction_->SetParameter(1, exclusionRadius_);
0169 }
0170
0171
0172 void HiFJRhoFlowModulationProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0173
0174 auto const& pfCands = iEvent.get(pfCandidateToken_);
0175
0176
0177 std::array<float, hi::NumEPNames> hiEvtPlane;
0178 if (doEvtPlane_) {
0179 auto const& evtPlanes = iEvent.get(evtPlaneToken_);
0180 assert(evtPlanes.size() == hi::NumEPNames);
0181 std::transform(evtPlanes.begin(), evtPlanes.end(), hiEvtPlane.begin(), [this](auto const& ePlane) -> float {
0182 return ePlane.angle(evtPlaneLevel_);
0183 });
0184 }
0185
0186
0187 edm::Handle<reco::JetView> jets;
0188 if (doJettyExclusion_) {
0189 iEvent.getByToken(jetToken_, jets);
0190 }
0191
0192 int nFill = 0;
0193
0194
0195
0196 const int nFlow = lastFittedVn_ - firstFittedVn_ + 1;
0197 double eventPlane[nFlow];
0198 for (int iFlow = 0; iFlow < nFlow; iFlow++)
0199 eventPlane[iFlow] = -100;
0200
0201
0202
0203 const int nParamVals = nFlow * 2 + 4;
0204 auto rhoFlowFitParamsOut = std::make_unique<std::vector<double>>(nParamVals, 1e-6);
0205
0206
0207 for (int iParameter = 0; iParameter < nFlow * 2 + 1; iParameter++) {
0208 rhoFlowFitParamsOut->at(iParameter) = 0;
0209 }
0210
0211 rhoFlowFitParamsOut->at(nFlow * 2 + 3) = firstFittedVn_;
0212
0213
0214 double eventPlaneCos[nFlow];
0215 double eventPlaneSin[nFlow];
0216 for (int iFlow = 0; iFlow < nFlow; iFlow++) {
0217 eventPlaneCos[iFlow] = 0;
0218 eventPlaneSin[iFlow] = 0;
0219 }
0220
0221
0222 std::vector<bool> pfcuts(pfCands.size(), false);
0223 int iCand = -1;
0224 double thisPfCandidateWeight = 0;
0225 double deltaPhiJetPf = 0;
0226 std::vector<double> pfCandidateWeight(pfCands.size(), 1);
0227
0228
0229 for (auto const& pfCandidate : pfCands) {
0230 iCand++;
0231
0232
0233 auto particleFlowCandidateID = converter_.translatePdgIdToType(pfCandidate.pdgId());
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244 if (particleFlowCandidateID != 1)
0245 continue;
0246
0247
0248 if (std::abs(pfCandidate.eta()) > pfCandidateEtaCut_)
0249 continue;
0250 if (pfCandidate.pt() < pfCandidateMinPtCut_)
0251 continue;
0252 if (pfCandidate.pt() > pfCandidateMaxPtCut_)
0253 continue;
0254
0255 nFill++;
0256
0257
0258 thisPfCandidateWeight = 1;
0259 if (doJettyExclusion_) {
0260 bool isGood = true;
0261 for (auto const& jet : *jets) {
0262 if (deltaR2(jet, pfCandidate) < exclusionRadius_ * exclusionRadius_) {
0263 isGood = false;
0264 break;
0265 } else {
0266
0267 deltaPhiJetPf = std::abs(pfCandidate.phi() - jet.phi());
0268 if (deltaPhiJetPf > TMath::Pi())
0269 deltaPhiJetPf = TMath::Pi() * 2 - deltaPhiJetPf;
0270
0271 thisPfCandidateWeight += pfWeightFunction_->Eval(deltaPhiJetPf, std::abs(jet.eta()));
0272 }
0273 }
0274
0275 if (!isGood) {
0276 continue;
0277 }
0278 }
0279
0280
0281 pfCandidateWeight[iCand] = thisPfCandidateWeight;
0282
0283
0284 pfcuts[iCand] = true;
0285
0286
0287 if (!doEvtPlane_) {
0288 for (int iFlow = 0; iFlow < nFlow; iFlow++) {
0289 eventPlaneCos[iFlow] += std::cos((iFlow + firstFittedVn_) * pfCandidate.phi()) * thisPfCandidateWeight;
0290 eventPlaneSin[iFlow] += std::sin((iFlow + firstFittedVn_) * pfCandidate.phi()) * thisPfCandidateWeight;
0291 }
0292 }
0293 }
0294
0295
0296 if (!doEvtPlane_) {
0297
0298 for (int iFlow = 0; iFlow < nFlow; iFlow++) {
0299 eventPlane[iFlow] = std::atan2(eventPlaneSin[iFlow], eventPlaneCos[iFlow]) / (iFlow + firstFittedVn_);
0300 }
0301 } else {
0302
0303
0304 int halfWay = nFlow / 2;
0305 for (int iFlow = 0; iFlow < halfWay; iFlow++) {
0306 eventPlane[iFlow] = hiEvtPlane[hi::HF2];
0307 }
0308 for (int iFlow = halfWay; iFlow < nFlow; iFlow++) {
0309 eventPlane[iFlow] = hiEvtPlane[hi::HF3];
0310 }
0311 }
0312
0313
0314 int pfcuts_count = 0;
0315 if (nFill >= minPfCandidatesPerEvent_ && eventPlane[0] > -99) {
0316
0317 const int nPhiBins = std::max(10, nFill / 30);
0318 std::string name = "phiTestIEta4_" + std::to_string(iEvent.id().event()) + "_h";
0319 std::unique_ptr<TH1F> phi_h = std::make_unique<TH1F>(name.data(), "", nPhiBins, -TMath::Pi(), TMath::Pi());
0320 phi_h->SetDirectory(nullptr);
0321 for (auto const& pfCandidate : pfCands) {
0322 if (pfcuts.at(pfcuts_count)) {
0323 phi_h->Fill(pfCandidate.phi(), pfCandidateWeight.at(pfcuts_count));
0324 }
0325 pfcuts_count++;
0326 }
0327
0328
0329 flowFit_p_->SetParameter(2, 10);
0330 for (int iFlow = 0; iFlow < nFlow; iFlow++) {
0331 flowFit_p_->SetParameter(3 + 2 * iFlow, 0);
0332 flowFit_p_->SetParameter(4 + 2 * iFlow, eventPlane[iFlow]);
0333
0334 if (!doFreePlaneFit_) {
0335 flowFit_p_->FixParameter(4 + 2 * iFlow, eventPlane[iFlow]);
0336 }
0337 }
0338
0339
0340 phi_h->Fit(flowFit_p_.get(), "Q SERIAL", "", -TMath::Pi(), TMath::Pi());
0341
0342
0343 for (int iParameter = 0; iParameter < nFlow * 2 + 1; iParameter++) {
0344 rhoFlowFitParamsOut->at(iParameter) = flowFit_p_->GetParameter(iParameter + 2);
0345 }
0346
0347
0348 rhoFlowFitParamsOut->at(nFlow * 2 + 1) = flowFit_p_->GetChisquare();
0349 rhoFlowFitParamsOut->at(nFlow * 2 + 2) = flowFit_p_->GetNDF();
0350
0351 phi_h.reset();
0352 pfcuts.clear();
0353 }
0354
0355
0356 iEvent.put(std::move(rhoFlowFitParamsOut), "rhoFlowFitParams");
0357 }
0358
0359
0360 void HiFJRhoFlowModulationProducer::beginStream(edm::StreamID) {}
0361
0362
0363 void HiFJRhoFlowModulationProducer::endStream() {}
0364
0365
0366 void HiFJRhoFlowModulationProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0367 edm::ParameterSetDescription desc;
0368 desc.add<int>("minPfCandidatesPerEvent", 100);
0369 desc.add<bool>("doEvtPlane", false);
0370 desc.add<edm::InputTag>("EvtPlane", edm::InputTag("hiEvtPlane"));
0371 desc.add<bool>("doJettyExclusion", false);
0372 desc.add<double>("exclusionRadius", 0.4);
0373 desc.add<bool>("doFreePlaneFit", false);
0374 desc.add<edm::InputTag>("jetTag", edm::InputTag("ak4PFJetsForFlow"));
0375 desc.add<edm::InputTag>("pfCandSource", edm::InputTag("packedPFCandidates"));
0376 desc.add<int>("evtPlaneLevel", 0);
0377 desc.add<double>("pfCandidateEtaCut", 1.0);
0378 desc.add<double>("pfCandidateMinPtCut", 0.3);
0379 desc.add<double>("pfCandidateMaxPtCut", 3.0);
0380 desc.add<int>("firstFittedVn", 2);
0381 desc.add<int>("lastFittedVn", 3);
0382 descriptions.add("hiFJRhoFlowModulationProducer", desc);
0383 }
0384
0385 DEFINE_FWK_MODULE(HiFJRhoFlowModulationProducer);