Skip to content

Commit

Permalink
PWGEM/PhotonMeson: add a task for chic1
Browse files Browse the repository at this point in the history
  • Loading branch information
dsekihat committed Mar 8, 2024
1 parent 4cf7b2f commit a3353c1
Show file tree
Hide file tree
Showing 3 changed files with 338 additions and 0 deletions.
5 changes: 5 additions & 0 deletions PWGEM/PhotonMeson/Core/HistogramsLibrary.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,11 @@ void o2::aod::pwgem::photon::histogram::DefineHistograms(THashList* list, const
list->Add(hs_q_mix);
}
}

if (TString(histClass) == "chic1_to_jpsi_gamma") {
list->Add(new TH2F("hDeltaM_Mee_Same" , "m_{ee#gamma} - m_{ee} vs. m_{ee};m_{ee#gamma} - m_{ee} (GeV/c^{2});m_{ee} (GeV/c^{2})", 100, 0, 1, 200, 2, 4));
list->Add(new TH2F("hDeltaM_Mee_Mixed", "m_{ee#gamma} - m_{ee} vs. m_{ee};m_{ee#gamma} - m_{ee} (GeV/c^{2});m_{ee} (GeV/c^{2})", 100, 0, 1, 200, 2, 4));
}
}
THashList* o2::aod::pwgem::photon::histogram::AddHistClass(THashList* list, const char* histClass)
{
Expand Down
5 changes: 5 additions & 0 deletions PWGEM/PhotonMeson/Tasks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ o2physics_add_dpl_workflow(tag-and-probe
PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2::EMCALCalib O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore
COMPONENT_NAME Analysis)

o2physics_add_dpl_workflow(chic1-to-jpsigamma
SOURCES Chic1ToJpsiGamma.cxx
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore
COMPONENT_NAME Analysis)

o2physics_add_dpl_workflow(material-budget
SOURCES MaterialBudget.cxx
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore
Expand Down
328 changes: 328 additions & 0 deletions PWGEM/PhotonMeson/Tasks/Chic1ToJpsiGamma.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,328 @@
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
//
// ========================
//
// This code runs loop over photons and ee for chic1->J/psi + gamma
// Please write to: [email protected], [email protected]

#include <cstring>
#include <iterator>

#include "TString.h"
#include "Math/Vector4D.h"
#include "Framework/runDataProcessing.h"
#include "Framework/AnalysisTask.h"
#include "Framework/AnalysisDataModel.h"
#include "Framework/ASoAHelpers.h"
#include "Common/Core/RecoDecay.h"
#include "PWGEM/PhotonMeson/Utils/PairUtilities.h"
#include "PWGEM/PhotonMeson/DataModel/gammaTables.h"
#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h"
#include "PWGEM/PhotonMeson/Core/DalitzEECut.h"
#include "PWGEM/PhotonMeson/Core/CutsLibrary.h"
#include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h"

using namespace o2;
using namespace o2::aod;
using namespace o2::framework;
using namespace o2::framework::expressions;
using namespace o2::soa;
using namespace o2::aod::photonpair;
using namespace o2::aod::pwgem::photon;

using MyCollisions = soa::Join<aod::EMReducedEvents, aod::EMReducedEventsMult, aod::EMReducedEventsCent, aod::EMReducedEventsNgPCM, aod::EMReducedEventsNee>;
using MyCollision = MyCollisions::iterator;

using MyV0Photons = soa::Join<aod::V0PhotonsKF, aod::V0KFEMReducedEventIds>;
using MyV0Photon = MyV0Photons::iterator;

using MyDalitzEEs = soa::Join<aod::DalitzEEs, aod::DalitzEEEMReducedEventIds>;
using MyDalitzEE = MyDalitzEEs::iterator;

using MyPrimaryElectrons = soa::Join<aod::EMPrimaryElectrons, aod::EMPrimaryElectronEMReducedEventIds, aod::EMPrimaryElectronsPrefilterBit>;
using MyPrimaryElectron = MyPrimaryElectrons::iterator;

struct Chic1ToJpsiGamma {

Configurable<int> cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"};
Configurable<float> cfgCentMin{"cfgCentMin", 0, "min. centrality"};
Configurable<float> cfgCentMax{"cfgCentMax", 999, "max. centrality"};

Configurable<float> maxY{"maxY", 0.9, "maximum rapidity for reconstructed particles"};
Configurable<std::string> fConfigPCMCuts{"cfgPCMCuts", "qc,nocut", "Comma separated list of V0 photon cuts"};
Configurable<std::string> fConfigDalitzEECuts{"cfgDalitzEECuts", "mee2000_4000_minpt1000_maxeta09_tpconly", "Comma separated list of ee cuts"};

Configurable<std::string> fConfigEMEventCut{"cfgEMEventCut", "minbias", "em event cut"}; // only 1 event cut per wagon
EMEventCut fEMEventCut;
static constexpr std::string_view event_types[2] = {"before", "after"};

OutputObj<THashList> fOutputEvent{"Event"};
OutputObj<THashList> fOutputPair{"Pair"}; // 2-photon pair
THashList* fMainList = new THashList();

std::vector<V0PhotonCut> fPCMCuts;
std::vector<DalitzEECut> fDalitzEECuts;

std::vector<std::string> fPairNames;
void init(InitContext& context)
{
if (context.mOptions.get<bool>("processPCMDalitzEE")) {
fPairNames.push_back("PCMDalitzEE");
}

DefinePCMCuts();
DefineDalitzEECuts();
addhistograms();
TString ev_cut_name = fConfigEMEventCut.value;
fEMEventCut = *eventcuts::GetCut(ev_cut_name.Data());

fOutputEvent.setObject(reinterpret_cast<THashList*>(fMainList->FindObject("Event")));
fOutputPair.setObject(reinterpret_cast<THashList*>(fMainList->FindObject("Pair")));
}

template <typename TCuts1, typename TCuts2>
void add_pair_histograms(THashList* list_pair, const std::string pairname, TCuts1 const& cuts1, TCuts2 const& cuts2)
{
for (auto& cut1 : cuts1) {
for (auto& cut2 : cuts2) {
std::string cutname1 = cut1.GetName();
std::string cutname2 = cut2.GetName();

THashList* list_pair_subsys = reinterpret_cast<THashList*>(list_pair->FindObject(pairname.data()));
std::string photon_cut_name = cutname1 + "_" + cutname2;
THashList* list_pair_subsys_photoncut = reinterpret_cast<THashList*>(o2::aod::pwgem::photon::histogram::AddHistClass(list_pair_subsys, photon_cut_name.data()));
o2::aod::pwgem::photon::histogram::DefineHistograms(list_pair_subsys_photoncut, "chic1_to_jpsi_gamma");
} // end of cut2 loop
} // end of cut1 loop
}

static constexpr std::string_view pairnames[9] = {"PCMPCM", "PHOSPHOS", "EMCEMC", "PCMPHOS", "PCMEMC", "PCMDalitzEE", "PCMDalitzMuMu", "PHOSEMC", "DalitzEEDalitzEE"};
void addhistograms()
{
fMainList->SetOwner(true);
fMainList->SetName("fMainList");

// create sub lists first.
o2::aod::pwgem::photon::histogram::AddHistClass(fMainList, "Event");
THashList* list_ev = reinterpret_cast<THashList*>(fMainList->FindObject("Event"));

o2::aod::pwgem::photon::histogram::AddHistClass(fMainList, "Pair");
THashList* list_pair = reinterpret_cast<THashList*>(fMainList->FindObject("Pair"));

for (auto& pairname : fPairNames) {
LOGF(info, "Enabled pairs = %s", pairname.data());

THashList* list_ev_pair = reinterpret_cast<THashList*>(o2::aod::pwgem::photon::histogram::AddHistClass(list_ev, pairname.data()));
for (const auto& evtype : event_types) {
THashList* list_ev_type = reinterpret_cast<THashList*>(o2::aod::pwgem::photon::histogram::AddHistClass(list_ev_pair, evtype.data()));
o2::aod::pwgem::photon::histogram::DefineHistograms(list_ev_type, "Event", evtype.data());
}

o2::aod::pwgem::photon::histogram::AddHistClass(list_pair, pairname.data());
if (pairname == "PCMDalitzEE") {
add_pair_histograms(list_pair, pairname, fPCMCuts, fDalitzEECuts);
}

} // end of pair name loop
}

void DefinePCMCuts()
{
TString cutNamesStr = fConfigPCMCuts.value;
if (!cutNamesStr.IsNull()) {
std::unique_ptr<TObjArray> objArray(cutNamesStr.Tokenize(","));
for (int icut = 0; icut < objArray->GetEntries(); ++icut) {
const char* cutname = objArray->At(icut)->GetName();
LOGF(info, "add cut : %s", cutname);
fPCMCuts.push_back(*pcmcuts::GetCut(cutname));
}
}
LOGF(info, "Number of PCM cuts = %d", fPCMCuts.size());
}

void DefineDalitzEECuts()
{
TString cutNamesStr = fConfigDalitzEECuts.value;
if (!cutNamesStr.IsNull()) {
std::unique_ptr<TObjArray> objArray(cutNamesStr.Tokenize(","));
for (int icut = 0; icut < objArray->GetEntries(); ++icut) {
const char* cutname = objArray->At(icut)->GetName();
LOGF(info, "add cut : %s", cutname);
fDalitzEECuts.push_back(*dalitzeecuts::GetCut(cutname));
}
}
LOGF(info, "Number of DalitzEE cuts = %d", fDalitzEECuts.size());
}

template <PairType pairtype, typename TG1, typename TG2, typename TCut1, typename TCut2>
bool IsSelectedPair(TG1 const& g1, TG2 const& g2, TCut1 const& cut1, TCut2 const& cut2)
{
bool is_selected_pair = false;
if constexpr (pairtype == PairType::kPCMDalitzEE) {
is_selected_pair = o2::aod::photonpair::IsSelectedPair<aod::V0Legs, MyPrimaryElectrons>(g1, g2, cut1, cut2);
} else {
is_selected_pair = true;
}
return is_selected_pair;
}

template <PairType pairtype, typename TEvents, typename TPhotons1, typename TPhotons2, typename TPreslice1, typename TPreslice2, typename TCuts1, typename TCuts2, typename TLegs, typename TEMPrimaryElectrons>
void SameEventPairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& cuts1, TCuts2 const& cuts2, TLegs const& legs, TEMPrimaryElectrons const& emprimaryelectrons)
{
THashList* list_ev_pair_before = static_cast<THashList*>(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject(event_types[0].data()));
THashList* list_ev_pair_after = static_cast<THashList*>(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject(event_types[1].data()));
THashList* list_pair_ss = static_cast<THashList*>(fMainList->FindObject("Pair")->FindObject(pairnames[pairtype].data()));

for (auto& collision : collisions) {

const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()};
if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) {
continue;
}

o2::aod::pwgem::photon::histogram::FillHistClass<EMHistType::kEvent>(list_ev_pair_before, "", collision);
if (!fEMEventCut.IsSelected(collision)) {
continue;
}
o2::aod::pwgem::photon::histogram::FillHistClass<EMHistType::kEvent>(list_ev_pair_after, "", collision);
reinterpret_cast<TH1F*>(list_ev_pair_before->FindObject("hCollisionCounter"))->Fill("accepted", 1.f);
reinterpret_cast<TH1F*>(list_ev_pair_after->FindObject("hCollisionCounter"))->Fill("accepted", 1.f);

auto photons1_coll = photons1.sliceBy(perCollision1, collision.globalIndex());
auto photons2_coll = photons2.sliceBy(perCollision2, collision.globalIndex());

for (auto& cut1 : cuts1) {
for (auto& cut2 : cuts2) {
for (auto& [g1, g2] : combinations(CombinationsFullIndexPolicy(photons1_coll, photons2_coll))) {
if (!IsSelectedPair<pairtype>(g1, g2, cut1, cut2)) {
continue;
}
auto pos_sv = g1.template posTrack_as<aod::V0Legs>();
auto ele_sv = g1.template negTrack_as<aod::V0Legs>();
auto pos_pv = g2.template posTrack_as<MyPrimaryElectrons>();
auto ele_pv = g2.template negTrack_as<MyPrimaryElectrons>();
if (pos_sv.trackId() == pos_pv.trackId() || ele_sv.trackId() == ele_pv.trackId()) {
continue;
}

ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); // pcm
ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), g2.mass()); // j/psi->ee
ROOT::Math::PtEtaPhiMVector v12 = v1 + v2;
if (abs(v12.Rapidity()) > maxY) {
continue;
}
float delta_m = v12.M() - g2.mass();
reinterpret_cast<TH2F*>(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject("hDeltaM_Mee_Same"))->Fill(delta_m, g2.mass());
} // end of combination
} // end of cut2 loop
} // end of cut1 loop
} // end of collision loop
}

Configurable<int> ndepth{"ndepth", 10, "depth for event mixing"};
ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"};
ConfigurableAxis ConfCentBins{"ConfCentBins", {VARIABLE_WIDTH, 0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.0f, 999.f}, "Mixing bins - centrality"};
using BinningType_M = ColumnBinningPolicy<aod::collision::PosZ, aod::cent::CentFT0M>;
using BinningType_A = ColumnBinningPolicy<aod::collision::PosZ, aod::cent::CentFT0A>;
using BinningType_C = ColumnBinningPolicy<aod::collision::PosZ, aod::cent::CentFT0C>;
BinningType_M colBinning_M{{ConfVtxBins, ConfCentBins}, true};
BinningType_A colBinning_A{{ConfVtxBins, ConfCentBins}, true};
BinningType_C colBinning_C{{ConfVtxBins, ConfCentBins}, true};

template <PairType pairtype, typename TEvents, typename TPhotons1, typename TPhotons2, typename TPreslice1, typename TPreslice2, typename TCuts1, typename TCuts2, typename TLegs, typename TEMPrimaryElectrons, typename TMixedBinning>
void MixedEventPairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& cuts1, TCuts2 const& cuts2, TLegs const& legs, TEMPrimaryElectrons const& emprimaryelectrons, TMixedBinning const& colBinning)
{
THashList* list_pair_ss = static_cast<THashList*>(fMainList->FindObject("Pair")->FindObject(pairnames[pairtype].data()));

for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, ndepth, -1, collisions, collisions)) { // internally, CombinationsStrictlyUpperIndexPolicy(collisions, collisions) is called.

const float centralities1[3] = {collision1.centFT0M(), collision1.centFT0A(), collision1.centFT0C()};
const float centralities2[3] = {collision2.centFT0M(), collision2.centFT0A(), collision2.centFT0C()};

if (centralities1[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities1[cfgCentEstimator]) {
continue;
}
if (centralities2[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities2[cfgCentEstimator]) {
continue;
}
if (!fEMEventCut.IsSelected(collision1) || !fEMEventCut.IsSelected(collision2)) {
continue;
}

auto photons_coll1 = photons1.sliceBy(perCollision1, collision1.globalIndex());
auto photons_coll2 = photons2.sliceBy(perCollision2, collision2.globalIndex());

for (auto& cut1 : cuts1) {
for (auto& cut2 : cuts2) {
for (auto& [g1, g2] : combinations(soa::CombinationsFullIndexPolicy(photons_coll1, photons_coll2))) {

if (!IsSelectedPair<pairtype>(g1, g2, cut1, cut2)) {
continue;
}

auto pos_sv = g1.template posTrack_as<aod::V0Legs>();
auto ele_sv = g1.template negTrack_as<aod::V0Legs>();
auto pos_pv = g2.template posTrack_as<MyPrimaryElectrons>();
auto ele_pv = g2.template negTrack_as<MyPrimaryElectrons>();
if (pos_sv.trackId() == pos_pv.trackId() || ele_sv.trackId() == ele_pv.trackId()) {
continue;
}
ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); // pcm
ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), g2.mass()); // j/psi->ee
ROOT::Math::PtEtaPhiMVector v12 = v1 + v2;
if (abs(v12.Rapidity()) > maxY) {
continue;
}
float delta_m = v12.M() - g2.mass();
reinterpret_cast<TH2F*>(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject("hDeltaM_Mee_Mixed"))->Fill(delta_m, g2.mass());

} // end of different photon combinations
} // end of cut2 loop
} // end of cut1 loop
} // end of different collision combinations
}

Partition<MyCollisions> grouped_collisions = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); // this goes to same event.
Filter collisionFilter_common = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::collision::numContrib > (uint16_t)0 && o2::aod::evsel::sel8 == true;
Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax);
Filter collisionFilter_subsys = (o2::aod::emreducedevent::ngpcm >= 1);
using MyFilteredCollisions = soa::Filtered<MyCollisions>;

Filter DalitzEEFilter = o2::aod::dalitzee::sign == 0; // analyze only uls. adding LS bkg is a good idea, too.
using MyFilteredDalitzEEs = soa::Filtered<MyDalitzEEs>;

Preslice<MyV0Photons> perCollision_pcm = aod::v0photonkf::emreducedeventId;
Preslice<MyDalitzEEs> perCollision_dalitz = aod::dalitzee::emreducedeventId;

void processPCMDalitzEE(MyCollisions const& collisions, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, aod::V0Legs const& legs, MyFilteredDalitzEEs const& dielectrons, MyPrimaryElectrons const& emprimaryelectrons)
{
SameEventPairing<PairType::kPCMDalitzEE>(grouped_collisions, v0photons, dielectrons, perCollision_pcm, perCollision_dalitz, fPCMCuts, fDalitzEECuts, legs, emprimaryelectrons);
if (cfgCentEstimator == 0) {
MixedEventPairing<PairType::kPCMDalitzEE>(filtered_collisions, v0photons, dielectrons, perCollision_pcm, perCollision_dalitz, fPCMCuts, fDalitzEECuts, legs, emprimaryelectrons, colBinning_M);
} else if (cfgCentEstimator == 1) {
MixedEventPairing<PairType::kPCMDalitzEE>(filtered_collisions, v0photons, dielectrons, perCollision_pcm, perCollision_dalitz, fPCMCuts, fDalitzEECuts, legs, emprimaryelectrons, colBinning_A);
} else if (cfgCentEstimator == 2) {
MixedEventPairing<PairType::kPCMDalitzEE>(filtered_collisions, v0photons, dielectrons, perCollision_pcm, perCollision_dalitz, fPCMCuts, fDalitzEECuts, legs, emprimaryelectrons, colBinning_C);
}
}

void processDummy(MyCollisions const& collisions) {}

PROCESS_SWITCH(Chic1ToJpsiGamma, processPCMDalitzEE, "pairing PCM-EE", false);
PROCESS_SWITCH(Chic1ToJpsiGamma, processDummy, "Dummy function", true);
};

WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
{
return WorkflowSpec{
adaptAnalysisTask<Chic1ToJpsiGamma>(cfgc, TaskName{"chic1-to-jpsigamma"})};
}

0 comments on commit a3353c1

Please sign in to comment.