4747
4848#include " Math/Vector4D.h"
4949#include " TString.h"
50+ #include " TRandom3.h"
5051
5152#include < algorithm>
5253#include < array>
@@ -97,7 +98,7 @@ struct Dilepton {
9798 Configurable<std::string> spresoPath{" spresoPath" , " Users/d/dsekihat/PWGEM/dilepton/Qvector/resolution/LHC23zzh/pass3/test" , " Path to SP resolution file" };
9899 Configurable<std::string> spresoHistName{" spresoHistName" , " h1_R2_FT0M_BPos_BNeg" , " histogram name of SP resolution file" };
99100
100- Configurable<int > cfgAnalysisType{" cfgAnalysisType" , static_cast <int >(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kQC ), " kQC:0, kUPC:1, kFlowV2:2, kFlowV3:3, kPolarization:4, kHFll:5" };
101+ Configurable<int > cfgAnalysisType{" cfgAnalysisType" , static_cast <int >(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kQC ), " kQC:0, kUPC:1, kFlowV2:2, kFlowV3:3, kPolarization:4, kHFll:5, kBootstrapv2:6 " };
101102 Configurable<int > cfgEP2Estimator_for_Mix{" cfgEP2Estimator_for_Mix" , 3 , " FT0M:0, FT0A:1, FT0C:2, BTot:3, BPos:4, BNeg:5, FV0A:6" };
102103 Configurable<int > cfgQvecEstimator{" cfgQvecEstimator" , 2 , " FT0M:0, FT0A:1, FT0C:2, BTot:3, BPos:4, BNeg:5, FV0A:6" };
103104 Configurable<int > cfgCentEstimator{" cfgCentEstimator" , 2 , " FT0M:0, FT0A:1, FT0C:2" };
@@ -126,6 +127,8 @@ struct Dilepton {
126127 ConfigurableAxis ConfPolarizationPhiBins{" ConfPolarizationPhiBins" , {1 , -M_PI, M_PI}, " phi bins for polarization analysis" };
127128 ConfigurableAxis ConfPolarizationQuadMomBins{" ConfPolarizationQuadMomBins" , {15 , -0.5 , 1 }, " quadrupole moment bins for polarization analysis" }; // quardrupole moment <(3 x cos^2(theta) -1)/2>
128129
130+ Configurable<int > cfgNumBootstrapSamples{" cfgNumBootstrapSamples" , 1 , " Number of Bootstrap Samples" };
131+
129132 EMEventCut fEMEventCut ;
130133 struct : ConfigurableGroup {
131134 std::string prefix = " eventcut_group" ;
@@ -657,6 +660,17 @@ struct Dilepton {
657660 fRegistry .addClone (" Pair/same/uls/" , " Pair/same/lspp/" );
658661 fRegistry .addClone (" Pair/same/uls/" , " Pair/same/lsmm/" );
659662 fRegistry .addClone (" Pair/same/" , " Pair/mix/" );
663+ } else if (cfgAnalysisType == static_cast <int >(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kBootstrapv2 )) {
664+ nmod = 2 ;
665+ const AxisSpec axis_sp{ConfSPBins, Form (" #vec{u}_{%d,ll} #upoint #vec{Q}_{%d}^{%s}" , nmod, nmod, qvec_det_names[cfgQvecEstimator].data ())};
666+ const AxisSpec axis_bootstrap{cfgNumBootstrapSamples, 0.5 , static_cast <double >(cfgNumBootstrapSamples) + 0.5 , " sample" }; // for bootstrap samples
667+ fRegistry .add (" Pair/same/uls/hs" , " dilepton" , kTHnSparseD , {axis_mass, axis_pt, axis_dca, axis_y, axis_sp, axis_bootstrap}, true );
668+ fRegistry .addClone (" Pair/same/uls/" , " Pair/same/lspp/" );
669+ fRegistry .addClone (" Pair/same/uls/" , " Pair/same/lsmm/" );
670+ fRegistry .add (" Pair/mix/uls/hs" , " dilepton" , kTHnSparseD , {axis_mass, axis_pt, axis_dca, axis_y}, true );
671+ fRegistry .addClone (" Pair/mix/uls/" , " Pair/mix/lspp/" );
672+ fRegistry .addClone (" Pair/mix/uls/" , " Pair/mix/lsmm/" );
673+ o2::aod::pwgem::dilepton::utils::eventhistogram::addEventHistogramsBootstrap (&fRegistry , cfgNumBootstrapSamples);
660674 } else { // same as kQC to avoid seg. fault
661675 fRegistry .add (" Pair/same/uls/hs" , " dilepton" , kTHnSparseD , {axis_mass, axis_pt, axis_dca, axis_y}, true );
662676 fRegistry .addClone (" Pair/same/uls/" , " Pair/same/lspp/" );
@@ -672,6 +686,7 @@ struct Dilepton {
672686 } else {
673687 o2::aod::pwgem::dilepton::utils::eventhistogram::addEventHistograms<-1 >(&fRegistry );
674688 }
689+
675690 fRegistry .add (" Event/before/hEP2_CentFT0C_forMix" , Form (" 2nd harmonics event plane for mix;centrality FT0C (%%);#Psi_{2}^{%s} (rad.)" , qvec_det_names[cfgEP2Estimator_for_Mix].data ()), kTH2F , {{110 , 0 , 110 }, {180 , -M_PI_2, +M_PI_2}}, false );
676691 fRegistry .add (" Event/after/hEP2_CentFT0C_forMix" , Form (" 2nd harmonics event plane for mix;centrality FT0C (%%);#Psi_{2}^{%s} (rad.)" , qvec_det_names[cfgEP2Estimator_for_Mix].data ()), kTH2F , {{110 , 0 , 110 }, {180 , -M_PI_2, +M_PI_2}}, false );
677692 }
@@ -828,7 +843,7 @@ struct Dilepton {
828843 }
829844
830845 template <int ev_id, typename TCollision, typename TTrack1, typename TTrack2, typename TCut, typename TAllTracks>
831- bool fillPairInfo (TCollision const & collision, TTrack1 const & t1, TTrack2 const & t2, TCut const & cut, TAllTracks const &)
846+ bool fillPairInfo (TCollision const & collision, TTrack1 const & t1, TTrack2 const & t2, TCut const & cut, TAllTracks const &, const std::vector< float > weightvector )
832847 {
833848 if constexpr (ev_id == 0 ) {
834849 if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron ) {
@@ -1041,7 +1056,6 @@ struct Dilepton {
10411056 } else if (t1.sign () < 0 && t2.sign () < 0 ) { // LS--
10421057 fRegistry .fill (HIST (" Pair/" ) + HIST (event_pair_types[ev_id]) + HIST (" lsmm/hs" ), v12.M (), v12.Pt (), pair_dca, v12.Rapidity (), cos_thetaPol, phiPol, quadmom, weight);
10431058 }
1044-
10451059 } else if (cfgAnalysisType == static_cast <int >(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kHFll )) {
10461060 float dphi = v1.Phi () - v2.Phi ();
10471061 dphi = RecoDecay::constrainAngle (dphi, -o2::constants::math::PIHalf);
@@ -1055,6 +1069,51 @@ struct Dilepton {
10551069 fRegistry .fill (HIST (" Pair/" ) + HIST (event_pair_types[ev_id]) + HIST (" lsmm/hs" ), v12.M (), v12.Pt (), pair_dca, v12.Rapidity (), dphi, deta, weight);
10561070 }
10571071
1072+ } else if (cfgAnalysisType == static_cast <int >(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kBootstrapv2 )) {
1073+ std::array<float , 2 > q2ft0m = {collision.q2xft0m (), collision.q2yft0m ()};
1074+ std::array<float , 2 > q2ft0a = {collision.q2xft0a (), collision.q2yft0a ()};
1075+ std::array<float , 2 > q2ft0c = {collision.q2xft0c (), collision.q2yft0c ()};
1076+ std::array<float , 2 > q2btot = {collision.q2xbtot (), collision.q2ybtot ()};
1077+ std::array<float , 2 > q2bpos = {collision.q2xbpos (), collision.q2ybpos ()};
1078+ std::array<float , 2 > q2bneg = {collision.q2xbneg (), collision.q2ybneg ()};
1079+ std::array<float , 2 > q2fv0a = {collision.q2xfv0a (), collision.q2yfv0a ()};
1080+ std::array<float , 2 > q3ft0m = {collision.q3xft0m (), collision.q3yft0m ()};
1081+ std::array<float , 2 > q3ft0a = {collision.q3xft0a (), collision.q3yft0a ()};
1082+ std::array<float , 2 > q3ft0c = {collision.q3xft0c (), collision.q3yft0c ()};
1083+ std::array<float , 2 > q3btot = {collision.q3xbtot (), collision.q3ybtot ()};
1084+ std::array<float , 2 > q3bpos = {collision.q3xbpos (), collision.q3ybpos ()};
1085+ std::array<float , 2 > q3bneg = {collision.q3xbneg (), collision.q3ybneg ()};
1086+ std::array<float , 2 > q3fv0a = {collision.q3xfv0a (), collision.q3yfv0a ()};
1087+
1088+ std::vector<std::vector<std::array<float , 2 >>> qvectors = {
1089+ {{999 .f , 999 .f }, {999 .f , 999 .f }, {999 .f , 999 .f }, {999 .f , 999 .f }, {999 .f , 999 .f }, {999 .f , 999 .f }, {999 .f , 999 .f }}, // 0th harmonics
1090+ {{999 .f , 999 .f }, {999 .f , 999 .f }, {999 .f , 999 .f }, {999 .f , 999 .f }, {999 .f , 999 .f }, {999 .f , 999 .f }, {999 .f , 999 .f }}, // 1st harmonics
1091+ {q2ft0m, q2ft0a, q2ft0c, q2btot, q2bpos, q2bneg, q2fv0a}, // 2nd harmonics
1092+ {q3ft0m, q3ft0a, q3ft0c, q3btot, q3bpos, q3bneg, q3fv0a}, // 3rd harmonics
1093+ };
1094+
1095+ if constexpr (ev_id == 0 ) {
1096+ // LOGF(info, "collision.centFT0C() = %f, collision.trackOccupancyInTimeRange() = %d, getSPresolution = %f", collision.centFT0C(), collision.trackOccupancyInTimeRange(), getSPresolution(collision.centFT0C(), collision.trackOccupancyInTimeRange()));
1097+
1098+ float sp = RecoDecay::dotProd (std::array<float , 2 >{static_cast <float >(std::cos (nmod * v12.Phi ())), static_cast <float >(std::sin (nmod * v12.Phi ()))}, qvectors[nmod][cfgQvecEstimator]) / getSPresolution (collision.centFT0C (), collision.trackOccupancyInTimeRange ());
1099+ for (int i = 0 ; i<cfgNumBootstrapSamples; i++){
1100+ if (t1.sign () * t2.sign () < 0 ) { // ULS
1101+ fRegistry .fill (HIST (" Pair/" ) + HIST (event_pair_types[ev_id]) + HIST (" uls/hs" ), v12.M (), v12.Pt (), pair_dca, v12.Rapidity (), sp, i + 0.5 , weightvector.at (i));
1102+ } else if (t1.sign () > 0 && t2.sign () > 0 ) { // LS++
1103+ fRegistry .fill (HIST (" Pair/" ) + HIST (event_pair_types[ev_id]) + HIST (" lspp/hs" ), v12.M (), v12.Pt (), pair_dca, v12.Rapidity (), sp, i + 0.5 , weightvector.at (i));
1104+ } else if (t1.sign () < 0 && t2.sign () < 0 ) { // LS--
1105+ fRegistry .fill (HIST (" Pair/" ) + HIST (event_pair_types[ev_id]) + HIST (" lsmm/hs" ), v12.M (), v12.Pt (), pair_dca, v12.Rapidity (), sp, i + 0.5 , weightvector.at (i));
1106+ }
1107+ }
1108+ } else if constexpr (ev_id == 1 ) {
1109+ if (t1.sign () * t2.sign () < 0 ) { // ULS
1110+ fRegistry .fill (HIST (" Pair/" ) + HIST (event_pair_types[ev_id]) + HIST (" uls/hs" ), v12.M (), v12.Pt (), pair_dca, v12.Rapidity (), weight);
1111+ } else if (t1.sign () > 0 && t2.sign () > 0 ) { // LS++
1112+ fRegistry .fill (HIST (" Pair/" ) + HIST (event_pair_types[ev_id]) + HIST (" lspp/hs" ), v12.M (), v12.Pt (), pair_dca, v12.Rapidity (), weight);
1113+ } else if (t1.sign () < 0 && t2.sign () < 0 ) { // LS--
1114+ fRegistry .fill (HIST (" Pair/" ) + HIST (event_pair_types[ev_id]) + HIST (" lsmm/hs" ), v12.M (), v12.Pt (), pair_dca, v12.Rapidity (), weight);
1115+ }
1116+ }
10581117 } else { // same as kQC to avoid seg. fault
10591118 if (t1.sign () * t2.sign () < 0 ) { // ULS
10601119 fRegistry .fill (HIST (" Pair/" ) + HIST (event_pair_types[ev_id]) + HIST (" uls/hs" ), v12.M (), v12.Pt (), pair_dca, v12.Rapidity (), weight);
@@ -1250,6 +1309,21 @@ struct Dilepton {
12501309 }
12511310 }
12521311
1312+ std::vector<float > bootstrapweights = {};
1313+ int randomSeed = static_cast <int >(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now ().time_since_epoch ()).count ());
1314+ TRandom3 randomNumber (randomSeed);
1315+ if (cfgAnalysisType == static_cast <int >(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kBootstrapv2 )){ // bootstrapping for accepted events
1316+ for (int i = 0 ; i<cfgNumBootstrapSamples; i++){
1317+ float poissonweight = 0 .;
1318+ poissonweight = static_cast <float >(randomNumber.PoissonD (1.0 ));
1319+ bootstrapweights.push_back (poissonweight);
1320+ o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfoBootstrap (&fRegistry , collision, i, poissonweight);
1321+ }
1322+ }
1323+ else {
1324+ bootstrapweights.push_back (1.0 ); // to pass as non-empyt dummy to use
1325+ }
1326+
12531327 if (nmod == 2 ) {
12541328 o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<1 , 2 >(&fRegistry , collision);
12551329 } else if (nmod == 3 ) {
@@ -1270,19 +1344,19 @@ struct Dilepton {
12701344 used_trackIds_per_col.reserve (posTracks_per_coll.size () + negTracks_per_coll.size ());
12711345 int nuls = 0 , nlspp = 0 , nlsmm = 0 ;
12721346 for (const auto & [pos, neg] : combinations (CombinationsFullIndexPolicy (posTracks_per_coll, negTracks_per_coll))) { // ULS
1273- bool is_pair_ok = fillPairInfo<0 >(collision, pos, neg, cut, tracks);
1347+ bool is_pair_ok = fillPairInfo<0 >(collision, pos, neg, cut, tracks, bootstrapweights );
12741348 if (is_pair_ok) {
12751349 nuls++;
12761350 }
12771351 }
12781352 for (const auto & [pos1, pos2] : combinations (CombinationsStrictlyUpperIndexPolicy (posTracks_per_coll, posTracks_per_coll))) { // LS++
1279- bool is_pair_ok = fillPairInfo<0 >(collision, pos1, pos2, cut, tracks);
1353+ bool is_pair_ok = fillPairInfo<0 >(collision, pos1, pos2, cut, tracks, bootstrapweights );
12801354 if (is_pair_ok) {
12811355 nlspp++;
12821356 }
12831357 }
12841358 for (const auto & [neg1, neg2] : combinations (CombinationsStrictlyUpperIndexPolicy (negTracks_per_coll, negTracks_per_coll))) { // LS--
1285- bool is_pair_ok = fillPairInfo<0 >(collision, neg1, neg2, cut, tracks);
1359+ bool is_pair_ok = fillPairInfo<0 >(collision, neg1, neg2, cut, tracks, bootstrapweights );
12861360 if (is_pair_ok) {
12871361 nlsmm++;
12881362 }
@@ -1364,25 +1438,25 @@ struct Dilepton {
13641438
13651439 for (const auto & pos : selected_posTracks_in_this_event) { // ULS mix
13661440 for (const auto & neg : negTracks_from_event_pool) {
1367- fillPairInfo<1 >(collision, pos, neg, cut, nullptr );
1441+ fillPairInfo<1 >(collision, pos, neg, cut, nullptr , bootstrapweights );
13681442 }
13691443 }
13701444
13711445 for (const auto & neg : selected_negTracks_in_this_event) { // ULS mix
13721446 for (const auto & pos : posTracks_from_event_pool) {
1373- fillPairInfo<1 >(collision, neg, pos, cut, nullptr );
1447+ fillPairInfo<1 >(collision, neg, pos, cut, nullptr , bootstrapweights );
13741448 }
13751449 }
13761450
13771451 for (const auto & pos1 : selected_posTracks_in_this_event) { // LS++ mix
13781452 for (const auto & pos2 : posTracks_from_event_pool) {
1379- fillPairInfo<1 >(collision, pos1, pos2, cut, nullptr );
1453+ fillPairInfo<1 >(collision, pos1, pos2, cut, nullptr , bootstrapweights );
13801454 }
13811455 }
13821456
13831457 for (const auto & neg1 : selected_negTracks_in_this_event) { // LS-- mix
13841458 for (const auto & neg2 : negTracks_from_event_pool) {
1385- fillPairInfo<1 >(collision, neg1, neg2, cut, nullptr );
1459+ fillPairInfo<1 >(collision, neg1, neg2, cut, nullptr , bootstrapweights );
13861460 }
13871461 }
13881462 } // end of loop over mixed event pool
0 commit comments