Skip to content

Commit

Permalink
PWGEM/Dilepton: first version of prefilter to reject photon conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
dsekihat committed Nov 24, 2024
1 parent 04070b0 commit d7813b5
Show file tree
Hide file tree
Showing 5 changed files with 318 additions and 23 deletions.
15 changes: 15 additions & 0 deletions PWGEM/Dilepton/Core/DielectronCut.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,21 @@ void DielectronCut::SetRequireDifferentSides(bool flag)
mRequireDiffSides = flag;
LOG(info) << "Dielectron Cut, require 2 tracks to be from different sides: " << mRequireDiffSides;
}
void DielectronCut::SetPrefilterPhiV(float max_mee_uls, float max_phiv_uls, float max_mee_ls, float max_phiv_ls)
{
mMaxMee_phiv_uls = max_mee_uls;
mMaxPhiV_uls = max_phiv_uls;
mSlope_phiv_ls = max_mee_ls / (M_PI - max_phiv_ls);
mIntercept_phiv_ls = max_mee_ls - mSlope_phiv_ls * M_PI;
LOG(info) << "Dielectron Cut, set phiv prefilter ULS: " << " mMaxMee_phiv_uls: " << mMaxMee_phiv_uls << " mMaxPhiV_uls: " << mMaxPhiV_uls;
LOG(info) << "Dielectron Cut, set phiv prefilter LS: " << " mSlope_phiv_ls: " << mSlope_phiv_ls << " mIntercept_phiv_ls: " << mIntercept_phiv_ls;
}
void DielectronCut::SetPrefilterMee(float min_mee_uls, float max_mee_uls)
{
mMinMee_uls = min_mee_uls;
mMaxMee_uls = max_mee_uls;
LOG(info) << "Dielectron Cut, set mee prefilter ULS: " << " mMinMee_uls: " << mMinMee_uls << " mMaxMee_uls: " << mMaxMee_uls;
}
void DielectronCut::SetTrackPtRange(float minPt, float maxPt)
{
mMinTrackPt = minPt;
Expand Down
73 changes: 72 additions & 1 deletion PWGEM/Dilepton/Core/DielectronCut.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ class DielectronCut : public TNamed
return false;
}

if (opAng < mMinOpAng || mMaxOpAng < opAng) { // in sigma for pair
if (opAng < mMinOpAng || mMaxOpAng < opAng) {
return false;
}

Expand All @@ -161,6 +161,70 @@ class DielectronCut : public TNamed
return true;
}

template <typename TTrack1, typename TTrack2>
bool IsSelectedPair_PrefilterULS(TTrack1 const& t1, TTrack2 const& t2, const float bz) const
{
// don't move this function into IsSelectedPair.
if (!IsSelectedPair_PrefilterULS_Mee(t1, t2, bz)) {
return false;
}
if (!IsSelectedPair_PrefilterULS_PhiV(t1, t2, bz)) {
return false;
}
return true;
}

template <typename TTrack1, typename TTrack2>
bool IsSelectedPair_PrefilterULS_Mee(TTrack1 const& t1, TTrack2 const& t2, const float /*bz*/) const
{
// don't move this function into IsSelectedPair.
ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron);
ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron);
ROOT::Math::PtEtaPhiMVector v12 = v1 + v2;
if (mMinMee_uls < v12.M() && v12.M() < mMaxMee_uls) {
return false;
}
return true;
}

template <typename TTrack1, typename TTrack2>
bool IsSelectedPair_PrefilterULS_PhiV(TTrack1 const& t1, TTrack2 const& t2, const float bz) const
{
// don't move this function into IsSelectedPair.
ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron);
ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron);
ROOT::Math::PtEtaPhiMVector v12 = v1 + v2;
float phiv = getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), bz);
if (v12.M() < mMaxMee_phiv_uls && mMaxPhiV_uls < phiv) {
return false;
}
return true;
}

template <typename TTrack1, typename TTrack2>
bool IsSelectedPair_PrefilterLS(TTrack1 const& t1, TTrack2 const& t2, const float bz) const
{
// don't move this function into IsSelectedPair.
if (!IsSelectedPair_PrefilterLS_PhiV(t1, t2, bz)) {
return false;
}
return true;
}

template <typename TTrack1, typename TTrack2>
bool IsSelectedPair_PrefilterLS_PhiV(TTrack1 const& t1, TTrack2 const& t2, const float bz) const
{
// don't move this function into IsSelectedPair.
ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron);
ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron);
ROOT::Math::PtEtaPhiMVector v12 = v1 + v2;
float phiv = getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), bz);
if (v12.M() < phiv * mSlope_phiv_ls + mIntercept_phiv_ls || v12.M() < (M_PI - phiv) * mSlope_phiv_ls + mIntercept_phiv_ls) {
return false;
}
return true;
}

template <bool dont_require_pteta = false, bool isML = false, typename TTrack, typename TCollision = int>
bool IsSelectedTrack(TTrack const& track, TCollision const& collision = 0) const
{
Expand Down Expand Up @@ -413,6 +477,8 @@ class DielectronCut : public TNamed
void SelectPhotonConversion(bool flag);
void SetMindEtadPhi(bool flag, float min_deta, float min_dphi);
void SetRequireDifferentSides(bool flag);
void SetPrefilterPhiV(float max_mee_uls, float max_phiv_uls, float max_mee_ls, float max_phiv_ls);
void SetPrefilterMee(float min_mee_uls, float max_mee_uls);

void SetTrackPtRange(float minPt = 0.f, float maxPt = 1e10f);
void SetTrackEtaRange(float minEta = -1e10f, float maxEta = 1e10f);
Expand Down Expand Up @@ -480,6 +546,11 @@ class DielectronCut : public TNamed
float mMinOpAng{0.f}, mMaxOpAng{1e10f};
bool mRequireDiffSides{false}; // flag to require 2 tracks to be from different sides. (A-C combination). If one wants 2 tracks to be in the same side (A-A or C-C), one can simply use track eta cut.

// only for prefilter
float mMinMee_uls{0.f}, mMaxMee_uls{0.f};
float mMaxMee_phiv_uls{0.f}, mMaxPhiV_uls{0.f}; // rectangle
float mSlope_phiv_ls{0.f}, mIntercept_phiv_ls{0.f}; // mee > phiv * slope + intercept

// kinematic cuts
float mMinTrackPt{0.f}, mMaxTrackPt{1e10f}; // range in pT
float mMinTrackEta{-1e10f}, mMaxTrackEta{1e10f}; // range in eta
Expand Down
37 changes: 34 additions & 3 deletions PWGEM/Dilepton/Core/Dilepton.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ using MyCollision = MyCollisions::iterator;
using MyCollisionsWithSWT = soa::Join<aod::EMEvents, aod::EMEventsMult, aod::EMEventsCent, aod::EMEventsQvec, aod::EMSWTriggerInfos>;
using MyCollisionWithSWT = MyCollisionsWithSWT::iterator;

using MyElectrons = soa::Join<aod::EMPrimaryElectrons, aod::EMPrimaryElectronsCov, aod::EMPrimaryElectronEMEventIds, aod::EMAmbiguousElectronSelfIds, aod::EMPrimaryElectronsPrefilterBit>;
using MyElectrons = soa::Join<aod::EMPrimaryElectrons, aod::EMPrimaryElectronsCov, aod::EMPrimaryElectronEMEventIds, aod::EMAmbiguousElectronSelfIds, aod::EMPrimaryElectronsPrefilterBit, aod::EMPrimaryElectronsPrefilterBitPi0>;
using MyElectron = MyElectrons::iterator;
using FilteredMyElectrons = soa::Filtered<MyElectrons>;
using FilteredMyElectron = FilteredMyElectrons::iterator;
Expand Down Expand Up @@ -180,7 +180,15 @@ struct Dilepton {
Configurable<float> cfg_min_opang{"cfg_min_opang", 0.0, "min opening angle"};
Configurable<float> cfg_max_opang{"cfg_max_opang", 6.4, "max opening angle"};
Configurable<bool> cfg_require_diff_sides{"cfg_require_diff_sides", false, "flag to require 2 tracks are from different sides."};
Configurable<float> cfg_x_to_go{"cfg_x_to_go", -1, "x (cm) to be propagated in local coordinate"};

Configurable<bool> cfg_apply_cuts_from_prefilter{"cfg_apply_cuts_from_prefilter", false, "flag to apply phiv cut inherited from prefilter"};
Configurable<uint16_t> cfg_prefilter_bits{"cfg_prefilter_bits", 0, "prefilter bits [kNone : 0, kMee : 1, kPhiV : 2, kFakeMatchITSTPC : 4] Please consider logical-OR among them."}; // see PairUtilities.h
Configurable<float> cfgMinMee_uls{"cfgMinMee_uls", 0.0, "min mee for prefilter in GeV/c2"}; // only for ULS
Configurable<float> cfgMaxMee_uls{"cfgMaxMee_uls", 0.01, "max mee for prefilter in GeV/c2"}; // only for ULS
Configurable<float> cfgMaxMee_for_phiv_uls{"cfgMaxMee_for_phiv_uls", 0.65, "max mee at phiv = pi for ULS"}; // GeV/c2
Configurable<float> cfgMaxPhiV_uls{"cfgMaxPhiV_uls", 2.9, "min phiv for in ULS"}; // radian
Configurable<float> cfgMaxMee_for_phiv_ls{"cfgMinMee_for_phiv", 0.25, "max mee at phiv = 0 and pi for LS"}; // GeV/c2 // symmetric
Configurable<float> cfgMaxPhiV_ls{"cfgMaxPhiV_ls", 2.5, "min phiv for LS"}; // radian

Configurable<float> cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"};
Configurable<float> cfg_min_eta_track{"cfg_min_eta_track", -0.8, "min eta for single track"};
Expand All @@ -204,6 +212,7 @@ struct Dilepton {
Configurable<float> cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.0, "max p to apply ITS cluster size cut"};
Configurable<float> cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"};
Configurable<float> cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"};
Configurable<float> cfg_x_to_go{"cfg_x_to_go", -1, "x (cm) to be propagated in local coordinate"};

Configurable<int> cfg_pid_scheme{"cfg_pid_scheme", static_cast<int>(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3, kTOFif : 4, kPIDML : 5, kTPChadrejORTOFreq_woTOFif : 6]"};
Configurable<float> cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"};
Expand Down Expand Up @@ -525,7 +534,7 @@ struct Dilepton {
if (cfgAnalysisType == static_cast<int>(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kQC)) {
fRegistry.add("Pair/same/uls/hs", "dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_dca}, true);
fRegistry.add("Pair/same/uls/hsDeltaP", "difference of p between 2 tracks;|p_{T,1} - p_{T,2}|/|p_{T,1} + p_{T,2}|;#Delta#eta;#Delta#varphi (rad.);", kTHnSparseD, {{20, 0, 1}, {100, -0.5, +0.5}, {180, -M_PI, M_PI}}, true);
fRegistry.add("Pair/same/uls/hGeomDeltaZRDeltaPhi", Form("difference in z-r#varphi plane between 2 tracks at r = %2.1f cm;r#Delta#varphi (cm);#Deltaz (cm);", dielectroncuts.cfg_x_to_go.value), kTH2D, {{200, -50, 50}, {40, -10, 10}}, true);
fRegistry.add("Pair/same/uls/hGeomDeltaZRDeltaPhi", Form("difference in z-r#varphi plane between 2 tracks at r = %2.1f cm;r#Delta#varphi (cm);#Deltaz (cm);", dielectroncuts.cfg_x_to_go.value), kTH2D, {{200, -20, 20}, {100, -10, 10}}, true);
if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) {
fRegistry.add("Pair/same/uls/hMvsPhiV", "m_{ee} vs. #varphi_{V};#varphi_{V} (rad.);m_{ee} (GeV/c^{2})", kTH2D, {{90, 0, M_PI}, {100, 0.0f, 1.0f}}, true); // phiv is only for dielectron
fRegistry.add("Pair/same/uls/hMvsPhiV_prop", "m_{ee} vs. #varphi_{V};#varphi_{V} (rad.);m_{ee} (GeV/c^{2})", kTH2D, {{90, 0, M_PI}, {100, 0.0f, 1.0f}}, true); // phiv is only for dielectron
Expand Down Expand Up @@ -652,6 +661,16 @@ struct Dilepton {
fDielectronCut.SetPairOpAng(dielectroncuts.cfg_min_opang, dielectroncuts.cfg_max_opang);
fDielectronCut.SetRequireDifferentSides(dielectroncuts.cfg_require_diff_sides);

// for prefilter
if (dielectroncuts.cfg_apply_cuts_from_prefilter) {
if ((dielectroncuts.cfg_prefilter_bits & (1 << static_cast<int>(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kMee))) > 0) {
fDielectronCut.SetPrefilterMee(dielectroncuts.cfgMinMee_uls, dielectroncuts.cfgMaxMee_uls);
}
if ((dielectroncuts.cfg_prefilter_bits & (1 << static_cast<int>(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kFakeMatchITSTPC))) > 0) {
fDielectronCut.SetPrefilterPhiV(dielectroncuts.cfgMaxMee_for_phiv_uls, dielectroncuts.cfgMaxPhiV_uls, dielectroncuts.cfgMaxMee_for_phiv_ls, dielectroncuts.cfgMaxPhiV_ls);
}
}

// for track
fDielectronCut.SetTrackPtRange(dielectroncuts.cfg_min_pt_track, 1e+10f);
fDielectronCut.SetTrackEtaRange(dielectroncuts.cfg_min_eta_track, dielectroncuts.cfg_max_eta_track);
Expand Down Expand Up @@ -858,6 +877,10 @@ struct Dilepton {
return false;
}

if (!cut.template IsSelectedPair_PrefilterULS(t1, t2, d_bz) || !cut.template IsSelectedPair_PrefilterLS(t1, t2, d_bz)) {
return false;
}

if constexpr (ev_id == 0) {
dz_geom = t1.sign() * t1.pt() > t2.sign() * t2.pt() ? map_z_prop[std::make_tuple(ndf, t1.emeventId(), t1.globalIndex())] - map_z_prop[std::make_tuple(ndf, t2.emeventId(), t2.globalIndex())] : map_z_prop[std::make_tuple(ndf, t2.emeventId(), t2.globalIndex())] - map_z_prop[std::make_tuple(ndf, t1.emeventId(), t1.globalIndex())];
dphi_geom = t1.sign() * t1.pt() > t2.sign() * t2.pt() ? map_phi_prop[std::make_tuple(ndf, t1.emeventId(), t1.globalIndex())] - map_phi_prop[std::make_tuple(ndf, t2.emeventId(), t2.globalIndex())] : map_phi_prop[std::make_tuple(ndf, t2.emeventId(), t2.globalIndex())] - map_phi_prop[std::make_tuple(ndf, t1.emeventId(), t1.globalIndex())];
Expand Down Expand Up @@ -1151,6 +1174,11 @@ struct Dilepton {
Filter trackFilter_electron = dielectroncuts.cfg_min_pt_track < o2::aod::track::pt && dielectroncuts.cfg_min_eta_track < o2::aod::track::eta && o2::aod::track::eta < dielectroncuts.cfg_max_eta_track && dielectroncuts.cfg_min_phi_track < o2::aod::track::phi && o2::aod::track::phi < dielectroncuts.cfg_max_phi_track && o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz;
Filter pidFilter_electron = (dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl) && (o2::aod::pidtpc::tpcNSigmaPi < dielectroncuts.cfg_min_TPCNsigmaPi || dielectroncuts.cfg_max_TPCNsigmaPi < o2::aod::pidtpc::tpcNSigmaPi);
Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true);
Filter prefilter_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter.node() && dielectroncuts.cfg_prefilter_bits.node() >= static_cast<uint16_t>(1),
ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast<uint16_t>(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kMee))) > static_cast<uint16_t>(0), (o2::aod::emprimaryelectron::pfbpi0 & static_cast<uint16_t>(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kMee))) <= static_cast<uint16_t>(0), true) &&
ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast<uint16_t>(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kFakeMatchITSTPC))) > static_cast<uint16_t>(0), (o2::aod::emprimaryelectron::pfbpi0 & static_cast<uint16_t>(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kFakeMatchITSTPC))) <= static_cast<uint16_t>(0), true),
o2::aod::emprimaryelectron::pfbpi0 >= static_cast<uint16_t>(0));

Partition<FilteredMyElectrons> positive_electrons = o2::aod::emprimaryelectron::sign > int8_t(0);
Partition<FilteredMyElectrons> negative_electrons = o2::aod::emprimaryelectron::sign < int8_t(0);

Expand Down Expand Up @@ -1400,6 +1428,9 @@ struct Dilepton {
if (!cut.template IsSelectedPair(t1, t2, d_bz)) {
return false;
}
if (!cut.template IsSelectedPair_PrefilterULS(t1, t2, d_bz) || !cut.template IsSelectedPair_PrefilterLS(t1, t2, d_bz)) {
return false;
}
float dz_geom = t1.sign() * t1.pt() > t2.sign() * t2.pt() ? map_z_prop[std::make_tuple(ndf, t1.emeventId(), t1.globalIndex())] - map_z_prop[std::make_tuple(ndf, t2.emeventId(), t2.globalIndex())] : map_z_prop[std::make_tuple(ndf, t2.emeventId(), t2.globalIndex())] - map_z_prop[std::make_tuple(ndf, t1.emeventId(), t1.globalIndex())];
float dphi_geom = t1.sign() * t1.pt() > t2.sign() * t2.pt() ? map_phi_prop[std::make_tuple(ndf, t1.emeventId(), t1.globalIndex())] - map_phi_prop[std::make_tuple(ndf, t2.emeventId(), t2.globalIndex())] : map_phi_prop[std::make_tuple(ndf, t2.emeventId(), t2.globalIndex())] - map_phi_prop[std::make_tuple(ndf, t1.emeventId(), t1.globalIndex())];
o2::math_utils::bringToPMPi(dphi_geom);
Expand Down
Loading

0 comments on commit d7813b5

Please sign in to comment.