diff --git a/ALICE3/Core/DelphesO2LutWriter.cxx b/ALICE3/Core/DelphesO2LutWriter.cxx index 6f079c7ece1..65608d592e9 100644 --- a/ALICE3/Core/DelphesO2LutWriter.cxx +++ b/ALICE3/Core/DelphesO2LutWriter.cxx @@ -26,6 +26,7 @@ #include "iostream" #include "TMatrixD.h" #include "TVectorD.h" +#include "TAxis.h" #include "TMatrixDSymEigen.h" #include "TDatabasePDG.h" #include "TLorentzVector.h" @@ -55,7 +56,8 @@ bool DelphesO2LutWriter::fatSolve(lutEntry_t& lutEntry, const float mass, int itof, int otof, - int q) + int q, + const float nch) { lutEntry.valid = false; @@ -63,9 +65,9 @@ bool DelphesO2LutWriter::fatSolve(lutEntry_t& lutEntry, tlv.SetPtEtaPhiM(pt, eta, 0., mass); o2::track::TrackParCov trkIn; o2::upgrade::convertTLorentzVectorToO2Track(q, tlv, {0., 0., 0.}, trkIn); - o2::track::TrackParCov trkOut; - if (fat.FastTrack(trkIn, trkOut, 1) < 0) { + const int status = fat.FastTrack(trkIn, trkOut, nch); + if (status <= 0) { Printf(" --- fatSolve: FastTrack failed --- \n"); tlv.Print(); return false; @@ -234,6 +236,9 @@ void DelphesO2LutWriter::lutWrite(const char* filename, int pdg, float field, in lutEntry_t lutEntry; // write entries + int nCalls = 0; + int successfullCalls = 0; + int failedCalls = 0; for (int inch = 0; inch < nnch; ++inch) { Printf(" --- writing nch = %d/%d", inch, nnch); auto nch = lutHeader.nchmap.eval(inch); @@ -242,6 +247,7 @@ void DelphesO2LutWriter::lutWrite(const char* filename, int pdg, float field, in for (int irad = 0; irad < nrad; ++irad) { Printf(" --- writing irad = %d/%d", irad, nrad); for (int ieta = 0; ieta < neta; ++ieta) { + nCalls++; Printf(" --- writing ieta = %d/%d", ieta, neta); auto eta = lutHeader.etamap.eval(ieta); lutEntry.eta = lutHeader.etamap.eval(ieta); @@ -252,6 +258,7 @@ void DelphesO2LutWriter::lutWrite(const char* filename, int pdg, float field, in if (std::fabs(eta) <= etaMaxBarrel) { // full lever arm ends at etaMaxBarrel Printf("Solving in the barrel"); // printf(" --- fatSolve: pt = %f, eta = %f, mass = %f, field=%f \n", lutEntry.pt, lutEntry.eta, lutHeader.mass, lutHeader.field); + successfullCalls++; if (!fatSolve(lutEntry, lutEntry.pt, lutEntry.eta, lutHeader.mass, itof, otof, q)) { // printf(" --- fatSolve: error \n"); lutEntry.valid = false; @@ -260,6 +267,8 @@ void DelphesO2LutWriter::lutWrite(const char* filename, int pdg, float field, in for (int i = 0; i < 15; ++i) { lutEntry.covm[i] = 0.; } + successfullCalls--; + failedCalls++; } } else { Printf("Solving outside the barrel"); @@ -267,6 +276,7 @@ void DelphesO2LutWriter::lutWrite(const char* filename, int pdg, float field, in lutEntry.eff = 1.; lutEntry.eff2 = 1.; bool retval = true; + successfullCalls++; if (useFlatDipole) { // Using the parametrization at the border of the barrel retval = fatSolve(lutEntry, lutEntry.pt, etaMaxBarrel, lutHeader.mass, itof, otof, q); } else if (usePara) { @@ -288,6 +298,8 @@ void DelphesO2LutWriter::lutWrite(const char* filename, int pdg, float field, in for (int i = 0; i < 15; ++i) { lutEntry.covm[i] = 0.; } + successfullCalls--; + failedCalls++; } } Printf("Diagonalizing"); @@ -298,6 +310,8 @@ void DelphesO2LutWriter::lutWrite(const char* filename, int pdg, float field, in } } } + Printf(" --- finished writing LUT file %s", filename); + Printf(" --- successfull calls: %d/%d, failed calls: %d/%d", successfullCalls, nCalls, failedCalls, nCalls); lutFile.close(); } @@ -331,10 +345,13 @@ void DelphesO2LutWriter::diagonalise(lutEntry_t& lutEntry) TGraph* DelphesO2LutWriter::lutRead(const char* filename, int pdg, int what, int vs, float nch, float radius, float eta, float pt) { + Printf(" --- reading LUT file %s", filename); + // vs static const int kNch = 0; static const int kEta = 1; static const int kPt = 2; + // what static const int kEfficiency = 0; static const int kEfficiency2 = 1; static const int kEfficiencyInnerTOF = 2; @@ -360,6 +377,58 @@ TGraph* DelphesO2LutWriter::lutRead(const char* filename, int pdg, int what, int } auto nbins = lutMap.nbins; auto g = new TGraph(); + g->SetName(Form("lut_%s_%d_vs_%d_what_%d", filename, pdg, vs, what)); + g->SetTitle(Form("LUT for %s, pdg %d, vs %d, what %d", filename, pdg, vs, what)); + switch (vs) { + case kNch: + Printf(" --- vs = kNch"); + g->GetXaxis()->SetTitle("Nch"); + break; + case kEta: + Printf(" --- vs = kEta"); + g->GetXaxis()->SetTitle("#eta"); + break; + case kPt: + Printf(" --- vs = kPt"); + g->GetXaxis()->SetTitle("p_{T} (GeV/c)"); + break; + default: + Printf(" --- error: unknown vs %d", vs); + return nullptr; + } + switch (what) { + case kEfficiency: + Printf(" --- what = kEfficiency"); + g->GetYaxis()->SetTitle("Efficiency (%)"); + break; + case kEfficiency2: + Printf(" --- what = kEfficiency2"); + g->GetYaxis()->SetTitle("Efficiency2 (%)"); + break; + case kEfficiencyInnerTOF: + Printf(" --- what = kEfficiencyInnerTOF"); + g->GetYaxis()->SetTitle("Inner TOF Efficiency (%)"); + break; + case kEfficiencyOuterTOF: + Printf(" --- what = kEfficiencyOuterTOF"); + g->GetYaxis()->SetTitle("Outer TOF Efficiency (%)"); + break; + case kPtResolution: + Printf(" --- what = kPtResolution"); + g->GetYaxis()->SetTitle("p_{T} Resolution (%)"); + break; + case kRPhiResolution: + Printf(" --- what = kRPhiResolution"); + g->GetYaxis()->SetTitle("R#phi Resolution (#mum)"); + break; + case kZResolution: + Printf(" --- what = kZResolution"); + g->GetYaxis()->SetTitle("Z Resolution (#mum)"); + break; + default: + Printf(" --- error: unknown what %d", what); + return nullptr; + } bool canBeInvalid = true; for (int i = 0; i < nbins; ++i) { diff --git a/ALICE3/Core/DelphesO2LutWriter.h b/ALICE3/Core/DelphesO2LutWriter.h index e4b979a46cd..25faf7f382c 100644 --- a/ALICE3/Core/DelphesO2LutWriter.h +++ b/ALICE3/Core/DelphesO2LutWriter.h @@ -55,7 +55,8 @@ class DelphesO2LutWriter const float mass = 0.13957000, int itof = 0, int otof = 0, - int q = 1); + int q = 1, + const float nch = 1); bool fwdSolve(float* covm, float pt = 0.1, float eta = 0.0, float mass = 0.13957000); bool fwdPara(lutEntry_t& lutEntry, float pt = 0.1, float eta = 0.0, float mass = 0.13957000, float Bfield = 0.5); void lutWrite(const char* filename = "lutCovm.dat", int pdg = 211, float field = 0.2, int itof = 0, int otof = 0); diff --git a/ALICE3/Core/DetLayer.cxx b/ALICE3/Core/DetLayer.cxx index 392356b1e5a..25e61e6e6d5 100644 --- a/ALICE3/Core/DetLayer.cxx +++ b/ALICE3/Core/DetLayer.cxx @@ -16,4 +16,76 @@ /// \brief Basic struct to hold information regarding a detector layer to be used in fast simulation /// +#include +#include + #include "DetLayer.h" + +namespace o2::fastsim +{ + +// Parametric constructor +DetLayer::DetLayer(const TString& name_, + float r_, + float z_, + float x0_, + float xrho_, + float resRPhi_, + float resZ_, + float eff_, + int type_) + : name(name_), + r(r_), + z(z_), + x0(x0_), + xrho(xrho_), + resRPhi(resRPhi_), + resZ(resZ_), + eff(eff_), + type(type_) +{ +} + +DetLayer::DetLayer(const DetLayer& other) + : name(other.name), r(other.r), z(other.z), x0(other.x0), xrho(other.xrho), resRPhi(other.resRPhi), resZ(other.resZ), eff(other.eff), type(other.type) +{ +} + +std::string DetLayer::toString() const +{ + std::string out = ""; + out.append("DetLayer: "); + out.append(name.Data()); + out.append(" | r: "); + out.append(std::to_string(r)); + out.append(" cm | z: "); + out.append(std::to_string(z)); + out.append(" cm | x0: "); + out.append(std::to_string(x0)); + out.append(" cm | xrho: "); + out.append(std::to_string(xrho)); + out.append(" g/cm^3 | resRPhi: "); + out.append(std::to_string(resRPhi)); + out.append(" cm | resZ: "); + out.append(std::to_string(resZ)); + out.append(" cm | eff: "); + out.append(std::to_string(eff)); + out.append(" | type: "); + switch (type) { + case layerInert: + out.append("Inert"); + break; + case layerSilicon: + out.append("Silicon"); + break; + case layerGas: + out.append("Gas/TPC"); + break; + default: + out.append("Unknown"); + break; + } + return out; +} + +} // namespace o2::fastsim diff --git a/ALICE3/Core/DetLayer.h b/ALICE3/Core/DetLayer.h index 6b9fea14c06..2577c73e42d 100644 --- a/ALICE3/Core/DetLayer.h +++ b/ALICE3/Core/DetLayer.h @@ -19,12 +19,59 @@ #ifndef ALICE3_CORE_DETLAYER_H_ #define ALICE3_CORE_DETLAYER_H_ +#include + #include "TString.h" namespace o2::fastsim { struct DetLayer { + public: + // Default constructor + DetLayer() = default; + // Parametric constructor + DetLayer(const TString& name_, float r_, float z_, float x0_, float xrho_, + float resRPhi_ = 0.0f, float resZ_ = 0.0f, float eff_ = 0.0f, int type_ = layerInert); + // Copy constructor + DetLayer(const DetLayer& other); + + // Setters + void setName(const TString& name_) { name = name_; } + void setRadius(float r_) { r = r_; } + void setZ(float z_) { z = z_; } + void setRadiationLength(float x0_) { x0 = x0_; } + void setDensity(float xrho_) { xrho = xrho_; } + void setResolutionRPhi(float resRPhi_) { resRPhi = resRPhi_; } + void setResolutionZ(float resZ_) { resZ = resZ_; } + void setEfficiency(float eff_) { eff = eff_; } + void setType(int type_) { type = type_; } + + // Getters + float getRadius() const { return r; } + float getZ() const { return z; } + float getRadiationLength() const { return x0; } + float getDensity() const { return xrho; } + float getResolutionRPhi() const { return resRPhi; } + float getResolutionZ() const { return resZ; } + float getEfficiency() const { return eff; } + int getType() const { return type; } + const TString& getName() const { return name; } + + // Check layer type + bool isInert() const { return type == layerInert; } + bool isSilicon() const { return type == layerSilicon; } + bool isGas() const { return type == layerGas; } + + // Utilities + std::string toString() const; + friend std::ostream& operator<<(std::ostream& os, const DetLayer& layer) + { + os << layer.toString(); + return os; + } + + private: // TString for holding name TString name; @@ -44,7 +91,10 @@ struct DetLayer { float eff; // detection efficiency // layer type - int type; // 0: undefined/inert, 1: silicon, 2: gas/tpc + int type; // 0: undefined/inert, 1: silicon, 2: gas/tpc + static constexpr int layerInert = 0; // inert/undefined layer + static constexpr int layerSilicon = 1; // silicon layer + static constexpr int layerGas = 2; // gas/tpc layer }; } // namespace o2::fastsim diff --git a/ALICE3/Core/FastTracker.cxx b/ALICE3/Core/FastTracker.cxx index 6b22461c187..1d06958504b 100644 --- a/ALICE3/Core/FastTracker.cxx +++ b/ALICE3/Core/FastTracker.cxx @@ -30,7 +30,6 @@ FastTracker::FastTracker() magneticField = 20; // in kiloGauss applyZacceptance = false; applyMSCorrection = true; - applyMSCorrection = true; applyElossCorrection = true; applyEffCorrection = true; covMatFactor = 0.99f; @@ -57,7 +56,11 @@ FastTracker::FastTracker() void FastTracker::AddLayer(TString name, float r, float z, float x0, float xrho, float resRPhi, float resZ, float eff, int type) { - DetLayer newLayer{name.Data(), r, z, x0, xrho, resRPhi, resZ, eff, type}; + DetLayer newLayer(name, r, z, x0, xrho, resRPhi, resZ, eff, type); + // Check that efficient layers are not inert layers + if (newLayer.getEfficiency() > 0.0f && newLayer.isInert()) { + LOG(error) << "Layer " << name << " with efficiency > 0.0 should not be inert"; + } layers.push_back(newLayer); } @@ -66,7 +69,7 @@ DetLayer FastTracker::GetLayer(int layer, bool ignoreBarrelLayers) const int layerIdx = layer; if (ignoreBarrelLayers) { for (int il = 0, trackingLayerIdx = 0; trackingLayerIdx <= layer; il++) { - if (layers[il].type == 0) + if (layers[il].isInert()) continue; trackingLayerIdx++; layerIdx = il; @@ -79,11 +82,12 @@ int FastTracker::GetLayerIndex(std::string name) const { int i = 0; for (const auto& layer : layers) { - if (layer.name == name) { + if (layer.getName() == name) { return i; } i++; } + LOG(error) << "Layer with name " << name << " not found in FastTracker layers"; return -1; } @@ -93,8 +97,7 @@ void FastTracker::Print() LOG(info) << "+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+"; LOG(info) << " Printing detector layout with " << layers.size() << " effective elements: "; for (uint32_t il = 0; il < layers.size(); il++) { - LOG(info) << " Layer #" << il << "\t" << layers[il].name.Data() << "\tr = " << Form("%.2f", layers[il].r) << "cm\tz = " << layers[il].z << "\t" - << "x0 = " << layers[il].x0 << "\txrho = " << layers[il].xrho << "\tresRPhi = " << layers[il].resRPhi << "\tresZ = " << layers[il].resZ << "\teff = " << layers[il].eff; + LOG(info) << " Layer #" << il << "\t" << layers[il]; } LOG(info) << "+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+"; } @@ -310,6 +313,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa const int xrhosteps = 100; const bool applyAngularCorrection = true; + goodHitProbability.clear(); for (int i = 0; i < kMaxNumberOfDetectors; ++i) goodHitProbability.push_back(-1.); goodHitProbability[0] = 1.; @@ -321,32 +325,35 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa new (&outputTrack)(o2::track::TrackParCov)(inputTrack); for (uint32_t il = 0; il < layers.size(); il++) { // check if layer is doable - if (layers[il].r < initialRadius) + if (layers[il].getRadius() < initialRadius) continue; // this layer should not be attempted, but go ahead // check if layer is reached float targetX = 1e+3; bool ok = true; - inputTrack.getXatLabR(layers[il].r, targetX, magneticField); - if (targetX > 999) + inputTrack.getXatLabR(layers[il].getRadius(), targetX, magneticField); + if (targetX > 999.f) { + LOGF(debug, "Failed to find intercept for layer %d at radius %.2f cm", il, layers[il].getRadius()); break; // failed to find intercept + } ok = inputTrack.propagateTo(targetX, magneticField); - if (ok && applyMSCorrection && layers[il].x0 > 0) { - ok = inputTrack.correctForMaterial(layers[il].x0, 0, applyAngularCorrection); + if (ok && applyMSCorrection && layers[il].getRadiationLength() > 0) { + ok = inputTrack.correctForMaterial(layers[il].getRadiationLength(), 0, applyAngularCorrection); } - if (ok && applyElossCorrection && layers[il].xrho > 0) { // correct in small steps + if (ok && applyElossCorrection && layers[il].getDensity() > 0) { // correct in small steps for (int ise = xrhosteps; ise--;) { - ok = inputTrack.correctForMaterial(0, -layers[il].xrho / xrhosteps, applyAngularCorrection); + ok = inputTrack.correctForMaterial(0, -layers[il].getDensity() / xrhosteps, applyAngularCorrection); if (!ok) break; } } + LOGF(debug, "Propagation was %s up to layer %d", ok ? "successful" : "unsuccessful", il); // was there a problem on this layer? if (!ok && il > 0) { // may fail to reach target layer due to the eloss float rad2 = inputTrack.getX() * inputTrack.getX() + inputTrack.getY() * inputTrack.getY(); - float maxR = layers[il - 1].r + kTrackingMargin * 2; + float maxR = layers[il - 1].getRadius() + kTrackingMargin * 2; float minRad = (fMinRadTrack > 0 && fMinRadTrack < maxR) ? fMinRadTrack : maxR; if (rad2 - minRad * minRad < kTrackingMargin * kTrackingMargin) { // check previously reached layer return -5; // did not reach min requested layer @@ -354,16 +361,20 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa break; } } - if (std::abs(inputTrack.getZ()) > layers[il].z && applyZacceptance) { + if (std::abs(inputTrack.getZ()) > layers[il].getZ() && applyZacceptance) { break; // out of acceptance bounds } - if (layers[il].type == 0) + if (layers[il].isInert()) { + LOG(info) << "Skipping inert layer: " << layers[il].getName() << " at radius " << layers[il].getRadius() << " cm"; continue; // inert layer, skip + } // layer is reached - if (firstLayerReached < 0) + if (firstLayerReached < 0) { + LOGF(debug, "First layer reached: %d", il); firstLayerReached = il; + } lastLayerReached = il; nIntercepts++; } @@ -415,7 +426,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa for (int il = lastLayerReached; il >= firstLayerReached; il--) { float targetX = 1e+3; - inputTrack.getXatLabR(layers[il].r, targetX, magneticField); + inputTrack.getXatLabR(layers[il].getRadius(), targetX, magneticField); if (targetX > 999) continue; // failed to find intercept @@ -423,7 +434,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa continue; // failed to propagate } - if (std::abs(inputTrack.getZ()) > layers[il].z && applyZacceptance) { + if (std::abs(inputTrack.getZ()) > layers[il].getZ() && applyZacceptance) { continue; // out of acceptance bounds but continue inwards } @@ -441,46 +452,46 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa if (!inwardTrack.propagateTo(xyz1[0], magneticField)) continue; - if (layers[il].type != 0) { // only update covm for tracker hits + if (!layers[il].isInert()) { // only update covm for tracker hits const o2::track::TrackParametrization::dim2_t hitpoint = { static_cast(xyz1[1]), static_cast(xyz1[2])}; - const o2::track::TrackParametrization::dim3_t hitpointcov = {layers[il].resRPhi * layers[il].resRPhi, 0.f, layers[il].resZ * layers[il].resZ}; + const o2::track::TrackParametrization::dim3_t hitpointcov = {layers[il].getResolutionRPhi() * layers[il].getResolutionRPhi(), 0.f, layers[il].getResolutionZ() * layers[il].getResolutionZ()}; inwardTrack.update(hitpoint, hitpointcov); inwardTrack.checkCovariance(); } - if (applyMSCorrection && layers[il].x0 > 0) { - if (!inputTrack.correctForMaterial(layers[il].x0, 0, applyAngularCorrection)) { + if (applyMSCorrection && layers[il].getRadiationLength() > 0) { + if (!inputTrack.correctForMaterial(layers[il].getRadiationLength(), 0, applyAngularCorrection)) { return -6; } - if (!inwardTrack.correctForMaterial(layers[il].x0, 0, applyAngularCorrection)) { + if (!inwardTrack.correctForMaterial(layers[il].getRadiationLength(), 0, applyAngularCorrection)) { return -6; } } - if (applyElossCorrection && layers[il].xrho > 0) { + if (applyElossCorrection && layers[il].getDensity() > 0) { for (int ise = xrhosteps; ise--;) { // correct in small steps - if (!inputTrack.correctForMaterial(0, layers[il].xrho / xrhosteps, applyAngularCorrection)) { + if (!inputTrack.correctForMaterial(0, layers[il].getDensity() / xrhosteps, applyAngularCorrection)) { return -7; } - if (!inwardTrack.correctForMaterial(0, layers[il].xrho / xrhosteps, applyAngularCorrection)) { + if (!inwardTrack.correctForMaterial(0, layers[il].getDensity() / xrhosteps, applyAngularCorrection)) { return -7; } } } - if (layers[il].type == 1) + if (layers[il].isSilicon()) nSiliconPoints++; // count silicon hits - if (layers[il].type == 2) + if (layers[il].isGas()) nGasPoints++; // count TPC/gas hits hits.push_back(thisHit); - if (applyEffCorrection && layers[il].type != 0) { // good hit probability calculation - double sigYCmb = o2::math_utils::sqrt(inwardTrack.getSigmaY2() + layers[il].resRPhi * layers[il].resRPhi); - double sigZCmb = o2::math_utils::sqrt(inwardTrack.getSigmaZ2() + layers[il].resZ * layers[il].resZ); - goodHitProbability[il] = ProbGoodChiSqHit(layers[il].r * 100, sigYCmb * 100, sigZCmb * 100); + if (applyEffCorrection && !layers[il].isInert()) { // good hit probability calculation + double sigYCmb = o2::math_utils::sqrt(inwardTrack.getSigmaY2() + layers[il].getResolutionRPhi() * layers[il].getResolutionRPhi()); + double sigZCmb = o2::math_utils::sqrt(inwardTrack.getSigmaZ2() + layers[il].getResolutionZ() * layers[il].getResolutionZ()); + goodHitProbability[il] = ProbGoodChiSqHit(layers[il].getRadius() * 100, sigYCmb * 100, sigZCmb * 100); goodHitProbability[0] *= goodHitProbability[il]; } } diff --git a/ALICE3/Core/FastTracker.h b/ALICE3/Core/FastTracker.h index f88b6c5ae85..702caa9e84b 100644 --- a/ALICE3/Core/FastTracker.h +++ b/ALICE3/Core/FastTracker.h @@ -39,10 +39,10 @@ class FastTracker void AddLayer(TString name, float r, float z, float x0, float xrho, float resRPhi = 0.0f, float resZ = 0.0f, float eff = 0.0f, int type = 0); DetLayer GetLayer(const int layer, bool ignoreBarrelLayers = true) const; int GetLayerIndex(const std::string name) const; - void SetRadiationLength(const std::string layerName, float x0) { layers[GetLayerIndex(layerName)].x0 = x0; } - void SetRadius(const std::string layerName, float r) { layers[GetLayerIndex(layerName)].r = r; } - void SetResolutionRPhi(const std::string layerName, float resRPhi) { layers[GetLayerIndex(layerName)].resRPhi = resRPhi; } - void SetResolutionZ(const std::string layerName, float resZ) { layers[GetLayerIndex(layerName)].resZ = resZ; } + void SetRadiationLength(const std::string layerName, float x0) { layers[GetLayerIndex(layerName)].setRadiationLength(x0); } + void SetRadius(const std::string layerName, float r) { layers[GetLayerIndex(layerName)].setRadius(r); } + void SetResolutionRPhi(const std::string layerName, float resRPhi) { layers[GetLayerIndex(layerName)].setResolutionRPhi(resRPhi); } + void SetResolutionZ(const std::string layerName, float resZ) { layers[GetLayerIndex(layerName)].setResolutionZ(resZ); } void SetResolution(const std::string layerName, float resRPhi, float resZ) { SetResolutionRPhi(layerName, resRPhi); diff --git a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx index 989295f8c54..ff804b8485a 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx @@ -811,11 +811,11 @@ struct OnTheFlyTracker { float phi{std::atan2(-posClusterCandidate[1], -posClusterCandidate[0]) + o2::its::constants::math::Pi}; o2::fastsim::DetLayer currentTrackingLayer = fastTracker.GetLayer(i); - if (currentTrackingLayer.resRPhi > 1e-8 && currentTrackingLayer.resZ > 1e-8) { // catch zero (though should not really happen...) - phi = gRandom->Gaus(phi, std::asin(currentTrackingLayer.resRPhi / r)); + if (currentTrackingLayer.getResolutionRPhi() > 1e-8 && currentTrackingLayer.getResolutionZ() > 1e-8) { // catch zero (though should not really happen...) + phi = gRandom->Gaus(phi, std::asin(currentTrackingLayer.getResolutionRPhi() / r)); posClusterCandidate[0] = r * std::cos(phi); posClusterCandidate[1] = r * std::sin(phi); - posClusterCandidate[2] = gRandom->Gaus(posClusterCandidate[2], currentTrackingLayer.resZ); + posClusterCandidate[2] = gRandom->Gaus(posClusterCandidate[2], currentTrackingLayer.getResolutionZ()); } if (std::isnan(phi)) @@ -833,7 +833,7 @@ struct OnTheFlyTracker { const o2::track::TrackParametrization::dim2_t hitpoint = { static_cast(xyz1[1]), static_cast(xyz1[2])}; - const o2::track::TrackParametrization::dim3_t hitpointcov = {currentTrackingLayer.resRPhi * currentTrackingLayer.resRPhi, 0.f, currentTrackingLayer.resZ * currentTrackingLayer.resZ}; + const o2::track::TrackParametrization::dim3_t hitpointcov = {currentTrackingLayer.getResolutionRPhi() * currentTrackingLayer.getResolutionRPhi(), 0.f, currentTrackingLayer.getResolutionZ() * currentTrackingLayer.getResolutionZ()}; cascadeTrack.update(hitpoint, hitpointcov); thisCascade.foundClusters++; // add to findable } diff --git a/Common/Tasks/CMakeLists.txt b/Common/Tasks/CMakeLists.txt index a63d0146e34..64d4f7e6611 100644 --- a/Common/Tasks/CMakeLists.txt +++ b/Common/Tasks/CMakeLists.txt @@ -87,4 +87,9 @@ o2physics_add_dpl_workflow(centrality-study o2physics_add_dpl_workflow(flow-test SOURCES flowTest.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(muon-qa + SOURCES qaMuon.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::Field O2::DetectorsBase O2::DetectorsCommonDataFormats O2::MathUtils O2::MCHTracking O2::DataFormatsMCH O2::GlobalTracking O2::MCHBase O2::MCHGeometryTransformer O2::CommonUtils COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/Common/Tasks/qaMuon.cxx b/Common/Tasks/qaMuon.cxx new file mode 100644 index 00000000000..1f210249089 --- /dev/null +++ b/Common/Tasks/qaMuon.cxx @@ -0,0 +1,2584 @@ +// 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. +/// \brief The task for muon QA +/// \author Andrea Ferrero +/// \author Paul Veen +/// \author Chi Zhang + +#include + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/ASoAHelpers.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CCDBTimeStampUtils.h" +#include "CommonUtils/NameConf.h" +#include "CommonUtils/ConfigurableParam.h" +#include "DataFormatsMCH/Cluster.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DetectorsBase/GRPGeomHelper.h" +#include "DetectorsBase/Propagator.h" +#include "Field/MagneticField.h" +#include "MathUtils/Cartesian.h" +#include "MCHGeometryTransformer/Transformations.h" +#include "MCHTracking/Track.h" +#include "MCHTracking/TrackExtrap.h" +#include "MCHTracking/TrackParam.h" +#include "MCHTracking/TrackFitter.h" +#include "MCHBase/TrackerParam.h" +#include "GlobalTracking/MatchGlobalFwd.h" +#include "ReconstructionDataFormats/TrackFwd.h" +#include "Common/DataModel/FwdTrackReAlignTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/CollisionAssociationTables.h" + +#include "TGeoGlobalMagField.h" +#include "Math/Vector4D.h" + +using namespace std; +using namespace o2; +using namespace o2::aod; +using namespace o2::mch; +using namespace o2::framework; +using namespace o2::framework::expressions; + +using MyEvents = soa::Join; +using MyMuonsWithCov = soa::Join; +using MyMFTs = aod::MFTTracks; + +using SMatrix55 = ROOT::Math::SMatrix>; +using SMatrix5 = ROOT::Math::SVector; + +using MuonPair = std::pair, std::pair>; +using GlobalMuonPair = std::pair>, std::pair>>; + +const int fgNCh = 10; +const int fgNDetElemCh[fgNCh] = {4, 4, 4, 4, 18, 18, 26, 26, 26, 26}; +const int fgSNDetElemCh[fgNCh + 1] = {0, 4, 8, 12, 16, 34, 52, 78, 104, 130, 156}; +const float zAtAbsEnd = -505.; + +constexpr double firstMFTPlaneZ = o2::mft::constants::mft::LayerZCoordinate()[0]; +constexpr double lastMFTPlaneZ = o2::mft::constants::mft::LayerZCoordinate()[9]; + +std::array zRefPlane{ + firstMFTPlaneZ, + lastMFTPlaneZ, + -90.0, + -300.0, + //-505.0, + -520.0}; + +std::vector> referencePlanes{ + {"MFT-begin", 10.0}, + {"MFT-end", 15.0}, + {"Absorber-begin", 20.0}, + {"Absorber-mid", 75.0}, + //{"Absorber-end", 100.0}, + {"MCH-begin", 100.0}}; + +enum MuonExtrapolation { + // Index used to set different options for muon propagation + kToVtx = 0, // propagtion to vertex by default + kToDCA, + kToAbsEnd, + kToZ +}; + +struct VarColl { + int64_t globalIndex = 0; + float x = 0.f; + float y = 0.f; + float z = 0.f; + float covXX = 0.f; + float covYY = 0.f; + int64_t bc = 0; + int multMFT = 0; +}; + +struct VarTrack { + int64_t collisionId = -1; + int64_t globalIndex = 0; + int nClusters = 0; // Only MCH + int sign = 0; + int64_t bc = 0; + int trackType = 0; + float trackTime = 0.f; + + // Basic kinematics + float x = 0.f; + float y = 0.f; + float z = 0.f; + float eta = 0.f; + float phi = 0.f; + float tgl = 0.f; + + float px = 0.f; + float py = 0.f; + float pz = 0.f; + float pT = 0.f; + float p = 0.f; + + // Propagation related infos + float dcaX = 0.f; + float dcaY = 0.f; + float pDca = 0.f; + float rabs = 0.f; + float chi2 = 0.f; + float chi2matching = 0.f; +}; + +struct VarClusters { + vector> posClusters; // (x,y,z) + vector> errorClusters; // (ex,ey) + vector DEIDs; +}; + +struct muonQa { + //// Variables for enabling QA options + struct : ConfigurableGroup { + Configurable fEnableQAMatching{"cfgEnableQAMatching", false, "Enable MCH-MFT matching QA checks"}; + Configurable fEnableQAResidual{"cfgEnableQAResidual", false, "Enable residual QA checks"}; + Configurable fEnableQADCA{"cfgEnableQADCA", false, "Enable DCA QA checks"}; + Configurable fEnableQADimuon{"cfgEnableQADimuon", false, "Enable dimuon QA checks"}; + } configQAs; + + //// Variables for selecting muon tracks + struct : ConfigurableGroup { + Configurable fPMchLow{"cfgPMchLow", 0.0f, ""}; + Configurable fPtMchLow{"cfgPtMchLow", 0.7f, ""}; + Configurable fEtaMchLow{"cfgEtaMchLow", -4.0f, ""}; + Configurable fEtaMchUp{"cfgEtaMchUp", -2.5f, ""}; + Configurable fRabsLow{"cfgRabsLow", 17.6f, ""}; + Configurable fRabsUp{"cfgRabsUp", 89.5f, ""}; + Configurable fSigmaPdcaUp{"cfgPdcaUp", 6.f, ""}; + Configurable fTrackChi2MchUp{"cfgTrackChi2MchUp", 5.f, ""}; + Configurable fMatchingChi2MchMidUp{"cfgMatchingChi2MchMidUp", 999.f, ""}; + } configMuons; + + //// Variables for selecting mft tracks + struct : ConfigurableGroup { + Configurable fEtaMftLow{"cfgEtaMftlow", -3.6f, ""}; + Configurable fEtaMftUp{"cfgEtaMftup", -2.5f, ""}; + Configurable fTrackNClustMftLow{"cfgTrackNClustMftLow", 7, ""}; + Configurable fTrackChi2MftUp{"cfgTrackChi2MftUp", 999.f, ""}; + } configMFTs; + + //// Variables for selecting global tracks + Configurable fMatchingChi2MftMchUp{"cfgMatchingChi2MftMchUp", 50.f, ""}; + + //// Variables for alignment corrections + Configurable fEnableMFTAlignmentCorrections{"cfgEnableMFTAlignmentCorrections", false, ""}; + + //// Variables for re-alignment setup + struct : ConfigurableGroup { + Configurable fDoRealign{"cfgDoRealign", false, "Switch to apply re-alignment"}; + Configurable fChamberResolutionX{"cfgChamberResolutionX", 0.4, "Chamber resolution along X configuration for refit"}; // 0.4cm pp, 0.2cm PbPb + Configurable fChamberResolutionY{"cfgChamberResolutionY", 0.4, "Chamber resolution along Y configuration for refit"}; // 0.4cm pp, 0.2cm PbPb + Configurable fSigmaCutImprove{"cfgSigmaCutImprove", 6., "Sigma cut for track improvement"}; + } configRealign; + + /// Variables to event mixing criteria + struct : ConfigurableGroup { + Configurable fEventMaxDeltaNMFT{"cfgEventMaxDeltaNMFT", 1, ""}; + Configurable fEventMaxDeltaVtxZ{"cfgEventMaxDeltaVtxZ", 1.f, ""}; + Configurable fEventMinDeltaBc{"cfgEventMinDeltaBc", 500, ""}; + } configMixing; + + //// Variables for ccdb + struct : ConfigurableGroup { + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable geoPathRealign{"geoPathRealign", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable nolaterthan{"ccdb-no-later-than-ref", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object of reference basis"}; + Configurable nolaterthanRealign{"ccdb-no-later-than-new", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object of new basis"}; + } configCCDB; + + //// Variables for histograms configuration + Configurable fNCandidatesMax{"nCandidatesMax", 5, ""}; + + parameters::GRPMagField* grpmag = nullptr; + TrackFitter trackFitter; // Track fitter from MCH tracking library + + globaltracking::MatchGlobalFwd mMatching; + int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. + double mImproveCutChi2; // Chi2 cut for track improvement. + Service ccdb; + o2::field::MagneticField* fieldB = nullptr; + double Bz; // Bz for MFT + + geo::TransformationCreator transformation; + map transformRef; // reference geometry w.r.t track data + map transformNew; // new geometry + TGeoManager* geoNew = nullptr; + TGeoManager* geoRef = nullptr; + + Preslice perMuon = aod::fwdtrkcl::fwdtrackId; + Preslice fwdtracksPerCollision = aod::fwdtrack::collisionId; + Preslice mftPerCollision = aod::fwdtrack::collisionId; + + HistogramRegistry registry{"registry", {}}; + HistogramRegistry registryDCA{"registryDCA", {}}; + HistogramRegistry registryResiduals{"registryResiduals", {}}; + HistogramRegistry registryResidualsMFT{"registryResidualsMFT", {}}; + HistogramRegistry registryResidualsMCH{"registryResidualsMCH", {}}; + HistogramRegistry registryDimuon{"registryDimuon", {}}; + + std::array quadrants = {"Q0", "Q1", "Q2", "Q3"}; + + std::array, 3>, 4>, 2> dcaHistos; + std::array, 3>, 4>, 2> dcaHistosMixedEvents; + + std::array, 4>, 6> trackResidualsHistos; + std::array, 4>, 6> trackResidualsHistosMixedEvents; + + std::array, 10>, 4> residualsHistos; + std::array, 10>, 4> residualsHistosMixedEvents; + + std::array, 10>, 2>, 2> residualsHistosPerDE; + std::array, 10>, 2>, 2> residualsHistosPerDEMixedEvents; + + std::array, 10>, 2>, 2> mchResidualsHistosPerDE; + std::array, 10>, 2>, 2> mchResidualsHistosPerDEMixedEvents; + + VarTrack fgValuesMCH; + VarTrack fgValuesMCHpv; + VarTrack fgValuesMFT; + VarTrack fgValuesGlobal; + vector fgValuesCandidates; + + void CreateBasicHistograms() + { + // ====================== + // Muons plots + // ====================== + + AxisSpec chi2Axis = {1000, 0, 1000, "chi2"}; + AxisSpec momentumAxis = {1000, 0, 1000, "p (GeV/c)"}; + AxisSpec transverseMomentumAxis = {1000, 0, 100, "p_{T} (GeV/c)"}; + AxisSpec etaAxis = {80, -5, -1, "#eta"}; + AxisSpec rAbsAxis = {100, 0., 100.0, "R_{abs} (cm)"}; + AxisSpec dcaAxis = {400, 0.0, 20.0, "DCA"}; + AxisSpec pdcaAxis = {5000, 0.0, 5000.0, "p #times DCA"}; + AxisSpec phiAxis = {360, -180.0, 180.0, "#phi (degrees)"}; + + registry.add("muons/TrackChi2", "MCH track #chi^{2}", {HistType::kTH1F, {chi2Axis}}); + registry.add("muons/TrackP", "MCH track momentum", {HistType::kTH1F, {momentumAxis}}); + registry.add("muons/TrackPt", "MCH track transverse momentum", {HistType::kTH1F, {transverseMomentumAxis}}); + registry.add("muons/TrackEta", "MCH track #eta", {HistType::kTH1F, {etaAxis}}); + registry.add("muons/TrackRabs", "MCH track R_{abs}", {HistType::kTH1F, {rAbsAxis}}); + registry.add("muons/TrackDCA", "MCH track DCA", {HistType::kTH1F, {dcaAxis}}); + registry.add("muons/TrackPDCA", "MCH track p #times DCA", {HistType::kTH1F, {pdcaAxis}}); + registry.add("muons/TrackPhi", "MCH track #phi", {HistType::kTH1F, {phiAxis}}); + + // ====================== + // Global muons plots + // ====================== + int nTrackTypes = static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MCHStandaloneTrack) + 1; + AxisSpec trackTypeAxis = {static_cast(nTrackTypes), 0.0, static_cast(nTrackTypes), "track type"}; + registry.add("global-muons/nTracksPerType", "Number of tracks per type", {HistType::kTH1F, {trackTypeAxis}}); + + AxisSpec nCandidatesAxis = {static_cast(fNCandidatesMax), 0.0, static_cast(fNCandidatesMax), "match candidate rank"}; + registry.add("global-muons/NCandidates", "Number of MFT-MCH match candidates", {HistType::kTH1F, {nCandidatesAxis}}); + registry.add("global-muons/MatchChi2", "MFT-MCH match chi2", {HistType::kTH2F, {chi2Axis, nCandidatesAxis}}); + + registry.add("global-muons/TrackChi2", "Muon track #chi^{2}", {HistType::kTH1F, {chi2Axis}}); + registry.add("global-muons/TrackP", "Muon track momentum", {HistType::kTH1F, {momentumAxis}}); + registry.add("global-muons/TrackPt", "Muon track transverse momentum", {HistType::kTH1F, {transverseMomentumAxis}}); + registry.add("global-muons/TrackEta", "Muon track #eta", {HistType::kTH1F, {etaAxis}}); + registry.add("global-muons/TrackRabs", "Muon track R_{abs}", {HistType::kTH1F, {rAbsAxis}}); + registry.add("global-muons/TrackDCA", "Muon track DCA", {HistType::kTH1F, {dcaAxis}}); + registry.add("global-muons/TrackPDCA", "Muon track p #times DCA", {HistType::kTH1F, {pdcaAxis}}); + registry.add("global-muons/TrackPhi", "Muon track #phi", {HistType::kTH1F, {phiAxis}}); + + // ====================== + // Global muon plots with matching cuts + // ====================== + + if (configQAs.fEnableQAMatching) { + AxisSpec dbcAxis = {1000, -500, 500, "#Delta_{BC}"}; + registry.add("global-matches/BCdifference", "MCH-MFT BC difference", {HistType::kTH1F, {dbcAxis}}); + + AxisSpec nClustersAxis = {20, 0, 20, "# of MFT clusters per track"}; + + registry.add("global-matches/MatchChi2", "MFT-MCH match chi2", {HistType::kTH1F, {chi2Axis}}); + + registry.add("global-matches/TrackChi2_MFT", "MFT track #chi^{2}", {HistType::kTH1F, {chi2Axis}}); + registry.add("global-matches/TrackNclusters_MFT", "MFT track Nclusters", {HistType::kTH1F, {nClustersAxis}}); + + registry.add("global-matches/TrackChi2", "Muon track #chi^{2}", {HistType::kTH1F, {chi2Axis}}); + registry.add("global-matches/TrackP", "Muon track momentum", {HistType::kTH1F, {momentumAxis}}); + registry.add("global-matches/TrackPt", "Muon track transverse momentum", {HistType::kTH1F, {transverseMomentumAxis}}); + registry.add("global-matches/TrackEta", "Muon track #eta", {HistType::kTH1F, {etaAxis}}); + registry.add("global-matches/TrackRabs", "Muon track R_{abs}", {HistType::kTH1F, {rAbsAxis}}); + registry.add("global-matches/TrackDCA", "Muon track DCA", {HistType::kTH1F, {dcaAxis}}); + registry.add("global-matches/TrackPDCA", "Muon track p #times DCA", {HistType::kTH1F, {pdcaAxis}}); + registry.add("global-matches/TrackPhi", "Muon track #phi", {HistType::kTH1F, {phiAxis}}); + + registry.add("global-matches/TrackP_glo", "Global muon track momentum", {HistType::kTH1F, {momentumAxis}}); + registry.add("global-matches/TrackPt_glo", "Global muon track transverse momentum", {HistType::kTH1F, {transverseMomentumAxis}}); + registry.add("global-matches/TrackEta_glo", "Global muon track #eta", {HistType::kTH1F, {etaAxis}}); + registry.add("global-matches/TrackDCA_glo", "Global muon track DCA", {HistType::kTH1F, {dcaAxis}}); + registry.add("global-matches/TrackPhi_glo", "Global muon track #phi", {HistType::kTH1F, {phiAxis}}); + } + + AxisSpec momentumCorrelationAxis = {100, 0, 100, "momentum (GeV/c)"}; + AxisSpec momentumDeltaAxis = {100, -1, 1, "#DeltaP (GeV/c)"}; + // Momentum correlations + registry.add("global-muons/MomentumCorrelation_Global_vs_Muon", + "P_{global} vs. P_{MCH}", + {HistType::kTH2F, {momentumCorrelationAxis, momentumCorrelationAxis}}); + registry.add("global-muons/MomentumDifference_Global_vs_Muon", + "(P_{global} - P_{MCH}) / P_{MCH} vs. P_{MCH}", + {HistType::kTH2F, {momentumCorrelationAxis, momentumDeltaAxis}}); + registry.add("global-muons/MomentumCorrelation_subleading_vs_leading", + "P_{subleading_match} vs. P_{leading_match}", + {HistType::kTH2F, {momentumCorrelationAxis, momentumCorrelationAxis}}); + registry.add("global-muons/MomentumDifference_subleading_vs_leading", + "(P_{subleading_match} - P_{leading_match}) / P_{leading_match} vs. P_{leading_match}", + {HistType::kTH2F, {momentumCorrelationAxis, momentumDeltaAxis}}); + + // AxisSpec etaAxis = {100, -5.0, -2.0, "#eta"}; + AxisSpec etaCorrelationAxis = {80, -5.0, -1.0, "#eta"}; + AxisSpec etaDeltaAxis = {100, -0.2, 0.2, "#Delta#eta"}; + // Eta correlations + registry.add("global-muons/EtaCorrelation_Global_vs_Muon", + "#eta_{global} vs. #eta_{MCH}", + {HistType::kTH2F, {etaCorrelationAxis, etaCorrelationAxis}}); + registry.add("global-muons/EtaDifference_Global_vs_Muon", + "(#eta_{global} - #eta_{MCH}) / #eta_{MCH} vs. #eta_{MCH}", + {HistType::kTH2F, {etaCorrelationAxis, etaDeltaAxis}}); + registry.add("global-muons/EtaCorrelation_subleading_vs_leading", + "#eta_{subleading_match} vs. #eta_{leading_match}", + {HistType::kTH2F, {etaCorrelationAxis, etaCorrelationAxis}}); + registry.add("global-muons/EtaDifference_subleading_vs_leading", + "(#eta_{subleading_match} - #eta_{leading_match}) / #eta_{leading_match} vs. #eta_{leading_match}", + {HistType::kTH2F, {etaCorrelationAxis, etaDeltaAxis}}); + } + + void CreateDetailedHistograms() + { + AxisSpec dcaxMFTAxis = {400, -0.5, 0.5, "DCA_{x} (cm)"}; + AxisSpec dcayMFTAxis = {400, -0.5, 0.5, "DCA_{y} (cm)"}; + AxisSpec dcaxMCHAxis = {400, -10.0, 10.0, "DCA_{x} (cm)"}; + AxisSpec dcayMCHAxis = {400, -10.0, 10.0, "DCA_{y} (cm)"}; + AxisSpec dcazAxis = {20, -10.0, 10.0, "DCA_{z} (cm)"}; + AxisSpec dxAxis = {600, -30.0, 30.0, "#Delta x (cm)"}; + AxisSpec dyAxis = {600, -30.0, 30.0, "#Delta y (cm)"}; + AxisSpec thetaxAxis = {10, 0.0, 20.0, "#theta_{x} (degrees)"}; + AxisSpec dThetaxAxis = {500, -5.0, 5.0, "#Delta#theta_{x} (degrees)"}; + AxisSpec thetayAxis = {10, 0.0, 20.0, "#theta_{y} (degrees)"}; + AxisSpec dThetayAxis = {500, -5.0, 5.0, "#Delta#theta_{y} (degrees)"}; + AxisSpec phiAxis = {360, -180.0, 180.0, "#phi (degrees)"}; + AxisSpec dPhiAxis = {200, -20.0, 20.0, "#Delta#phi (degrees)"}; + + if (configQAs.fEnableQAResidual) { + for (size_t i = 0; i < referencePlanes.size(); i++) { + const auto& refPLane = referencePlanes[i]; + AxisSpec xAxis = {10, 0, refPLane.second, "|x| (cm)"}; + AxisSpec yAxis = {10, 0, refPLane.second, "|y| (cm)"}; + for (size_t j = 0; j < quadrants.size(); j++) { + const auto& quadrant = quadrants[j]; + std::string histPath = std::string("Alignment/same-event/Residuals/ReferencePlanes/") + refPLane.first + "/" + quadrant + "/"; + trackResidualsHistos[i][j]["dx_vs_x"] = registry.add((histPath + "dx_vs_x").c_str(), std::format("#Delta x vs. |x| - {}", quadrant).c_str(), {HistType::kTH2F, {xAxis, dxAxis}}); + trackResidualsHistos[i][j]["dx_vs_y"] = registry.add((histPath + "dx_vs_y").c_str(), std::format("#Delta x vs. |y| - {}", quadrant).c_str(), {HistType::kTH2F, {yAxis, dxAxis}}); + trackResidualsHistos[i][j]["dy_vs_x"] = registry.add((histPath + "dy_vs_x").c_str(), std::format("#Delta y vs. |x| - {}", quadrant).c_str(), {HistType::kTH2F, {xAxis, dyAxis}}); + trackResidualsHistos[i][j]["dy_vs_y"] = registry.add((histPath + "dy_vs_y").c_str(), std::format("#Delta y vs. |y| - {}", quadrant).c_str(), {HistType::kTH2F, {yAxis, dyAxis}}); + + trackResidualsHistos[i][j]["dthetax_vs_x"] = registry.add((histPath + "dthetax_vs_x").c_str(), std::format("#Delta #theta_x vs. |x| - {}", quadrant).c_str(), {HistType::kTH2F, {xAxis, dThetaxAxis}}); + trackResidualsHistos[i][j]["dthetax_vs_y"] = registry.add((histPath + "dthetax_vs_y").c_str(), std::format("#Delta #theta_x vs. |y| - {}", quadrant).c_str(), {HistType::kTH2F, {yAxis, dThetaxAxis}}); + trackResidualsHistos[i][j]["dthetax_vs_thetax"] = registry.add((histPath + "dthetax_vs_thetax").c_str(), std::format("#Delta #theta_x vs. |#theta_x| - {}", quadrant).c_str(), {HistType::kTH2F, {thetaxAxis, dThetaxAxis}}); + + trackResidualsHistos[i][j]["dthetay_vs_x"] = registry.add((histPath + "dthetay_vs_x").c_str(), std::format("#Delta #theta_y vs. |x| - {}", quadrant).c_str(), {HistType::kTH2F, {xAxis, dThetayAxis}}); + trackResidualsHistos[i][j]["dthetay_vs_y"] = registry.add((histPath + "dthetay_vs_y").c_str(), std::format("#Delta #theta_y vs. |y| - {}", quadrant).c_str(), {HistType::kTH2F, {yAxis, dThetayAxis}}); + trackResidualsHistos[i][j]["dthetay_vs_thetay"] = registry.add((histPath + "dthetay_vs_thetay").c_str(), std::format("#Delta #theta_y vs. |#theta_y| - {}", quadrant).c_str(), {HistType::kTH2F, {thetayAxis, dThetayAxis}}); + + // mixed events + histPath = std::string("Alignment/mixed-event/Residuals/ReferencePlanes/") + refPLane.first + "/" + quadrant + "/"; + trackResidualsHistosMixedEvents[i][j]["dx_vs_x"] = registry.add((histPath + "dx_vs_x").c_str(), std::format("#Delta x vs. |x| - {}", quadrant).c_str(), {HistType::kTH2F, {xAxis, dxAxis}}); + trackResidualsHistosMixedEvents[i][j]["dx_vs_y"] = registry.add((histPath + "dx_vs_y").c_str(), std::format("#Delta x vs. |y| - {}", quadrant).c_str(), {HistType::kTH2F, {yAxis, dxAxis}}); + trackResidualsHistosMixedEvents[i][j]["dy_vs_x"] = registry.add((histPath + "dy_vs_x").c_str(), std::format("#Delta y vs. |x| - {}", quadrant).c_str(), {HistType::kTH2F, {xAxis, dyAxis}}); + trackResidualsHistosMixedEvents[i][j]["dy_vs_y"] = registry.add((histPath + "dy_vs_y").c_str(), std::format("#Delta y vs. |y| - {}", quadrant).c_str(), {HistType::kTH2F, {yAxis, dyAxis}}); + + trackResidualsHistosMixedEvents[i][j]["dthetax_vs_x"] = registry.add((histPath + "dthetax_vs_x").c_str(), std::format("#Delta #theta_x vs. |x| - {}", quadrant).c_str(), {HistType::kTH2F, {xAxis, dThetaxAxis}}); + trackResidualsHistosMixedEvents[i][j]["dthetax_vs_y"] = registry.add((histPath + "dthetax_vs_y").c_str(), std::format("#Delta #theta_x vs. |y| - {}", quadrant).c_str(), {HistType::kTH2F, {yAxis, dThetaxAxis}}); + trackResidualsHistosMixedEvents[i][j]["dthetax_vs_thetax"] = registry.add((histPath + "dthetax_vs_thetax").c_str(), std::format("#Delta #theta_x vs. |#theta_x| - {}", quadrant).c_str(), {HistType::kTH2F, {thetaxAxis, dThetaxAxis}}); + + trackResidualsHistosMixedEvents[i][j]["dthetay_vs_x"] = registry.add((histPath + "dthetay_vs_x").c_str(), std::format("#Delta #theta_y vs. |x| - {}", quadrant).c_str(), {HistType::kTH2F, {xAxis, dThetayAxis}}); + trackResidualsHistosMixedEvents[i][j]["dthetay_vs_y"] = registry.add((histPath + "dthetay_vs_y").c_str(), std::format("#Delta #theta_y vs. |y| - {}", quadrant).c_str(), {HistType::kTH2F, {yAxis, dThetayAxis}}); + trackResidualsHistosMixedEvents[i][j]["dthetay_vs_thetay"] = registry.add((histPath + "dthetay_vs_thetay").c_str(), std::format("#Delta #theta_y vs. |#theta_y| - {}", quadrant).c_str(), {HistType::kTH2F, {thetayAxis, dThetayAxis}}); + } + } + + for (size_t j = 0; j < quadrants.size(); j++) { + const auto& quadrant = quadrants[j]; + AxisSpec xAxis = {20, 0, 200, "|x| (cm)"}; + AxisSpec yAxis = {10, 0, 200, "|y| (cm)"}; + for (int chamber = 0; chamber < 10; chamber++) { + std::string histPath = std::string("Alignment/same-event/Residuals/MFT/") + quadrant + "/CH" + std::to_string(chamber + 1) + "/"; + // Delta x at cluster + residualsHistos[j][chamber]["dx_vs_x"] = registryResiduals.add((histPath + "dx_vs_x").c_str(), "Cluster x residual vs. x", {HistType::kTH2F, {xAxis, dxAxis}}); + residualsHistos[j][chamber]["dx_vs_y"] = registryResiduals.add((histPath + "dx_vs_y").c_str(), "Cluster x residual vs. y", {HistType::kTH2F, {yAxis, dxAxis}}); + residualsHistos[j][chamber]["dy_vs_x"] = registryResiduals.add((histPath + "dy_vs_x").c_str(), "Cluster y residual vs. x", {HistType::kTH2F, {xAxis, dyAxis}}); + residualsHistos[j][chamber]["dy_vs_y"] = registryResiduals.add((histPath + "dy_vs_y").c_str(), "Cluster y residual vs. y", {HistType::kTH2F, {yAxis, dyAxis}}); + + // mixed events + histPath = std::string("Alignment/mixed-event/Residuals/MFT/") + quadrant + "/CH" + std::to_string(chamber + 1) + "/"; + // Delta x at cluster + residualsHistosMixedEvents[j][chamber]["dx_vs_x"] = registryResiduals.add((histPath + "dx_vs_x").c_str(), "Cluster x residual vs. x", {HistType::kTH2F, {xAxis, dxAxis}}); + residualsHistosMixedEvents[j][chamber]["dx_vs_y"] = registryResiduals.add((histPath + "dx_vs_y").c_str(), "Cluster x residual vs. y", {HistType::kTH2F, {yAxis, dxAxis}}); + residualsHistosMixedEvents[j][chamber]["dy_vs_x"] = registryResiduals.add((histPath + "dy_vs_x").c_str(), "Cluster y residual vs. x", {HistType::kTH2F, {xAxis, dyAxis}}); + residualsHistosMixedEvents[j][chamber]["dy_vs_y"] = registryResiduals.add((histPath + "dy_vs_y").c_str(), "Cluster y residual vs. y", {HistType::kTH2F, {yAxis, dyAxis}}); + } + } + + for (size_t i = 0; i < 2; i++) { + std::string topBottom = (i == 0) ? "top" : "bottom"; + AxisSpec deAxis = {26, 0, 26, "DE index"}; + AxisSpec phiAxis = {16, -180, 180, "#phi (degrees)"}; + for (size_t j = 0; j < 2; j++) { + std::string sign = (j == 0) ? "positive" : "negative"; + for (int chamber = 0; chamber < 10; chamber++) { + std::string histPath = std::string("Alignment/same-event/Residuals/MFT/MFT_") + topBottom + "/" + sign + "/CH" + std::to_string(chamber + 1) + "/"; + // Delta x and y at cluster + residualsHistosPerDE[i][j][chamber]["dx_vs_de"] = registryResidualsMFT.add((histPath + "dx_vs_de").c_str(), "Cluster x residual vs. DE index", {HistType::kTH2F, {deAxis, dxAxis}}); + residualsHistosPerDE[i][j][chamber]["dy_vs_de"] = registryResidualsMFT.add((histPath + "dy_vs_de").c_str(), "Cluster y residual vs. DE index", {HistType::kTH2F, {deAxis, dxAxis}}); + + residualsHistosPerDE[i][j][chamber]["dx_vs_phi"] = registryResidualsMFT.add((histPath + "dx_vs_phi").c_str(), "Cluster x residual vs. cluster #phi", {HistType::kTH2F, {phiAxis, dxAxis}}); + residualsHistosPerDE[i][j][chamber]["dy_vs_phi"] = registryResidualsMFT.add((histPath + "dy_vs_phi").c_str(), "Cluster y residual vs. cluster #phi", {HistType::kTH2F, {phiAxis, dxAxis}}); + + // mixed events + histPath = std::string("Alignment/mixed-event/Residuals/MFT/MFT_") + topBottom + "/" + sign + "/CH" + std::to_string(chamber + 1) + "/"; + // Delta x and y at cluster + residualsHistosPerDEMixedEvents[i][j][chamber]["dx_vs_de"] = registryResidualsMFT.add((histPath + "dx_vs_de").c_str(), "Cluster x residual vs. DE index", {HistType::kTH2F, {deAxis, dxAxis}}); + residualsHistosPerDEMixedEvents[i][j][chamber]["dy_vs_de"] = registryResidualsMFT.add((histPath + "dy_vs_de").c_str(), "Cluster y residual vs. DE index", {HistType::kTH2F, {deAxis, dxAxis}}); + + residualsHistosPerDEMixedEvents[i][j][chamber]["dx_vs_phi"] = registryResidualsMFT.add((histPath + "dx_vs_phi").c_str(), "Cluster x residual vs. cluster #phi", {HistType::kTH2F, {phiAxis, dxAxis}}); + residualsHistosPerDEMixedEvents[i][j][chamber]["dy_vs_phi"] = registryResidualsMFT.add((histPath + "dy_vs_phi").c_str(), "Cluster y residual vs. cluster #phi", {HistType::kTH2F, {phiAxis, dxAxis}}); + } + } + } + + for (size_t i = 0; i < 2; i++) { + std::string topBottom = (i == 0) ? "top" : "bottom"; + AxisSpec deAxis = {26, 0, 26, "DE index"}; + for (size_t j = 0; j < 2; j++) { + std::string sign = (j == 0) ? "positive" : "negative"; + for (int chamber = 0; chamber < 10; chamber++) { + std::string histPath = std::string("Alignment/same-event/Residuals/MCH/MCH_") + topBottom + "/" + sign + "/CH" + std::to_string(chamber + 1) + "/"; + // Delta x and y at cluster + mchResidualsHistosPerDE[i][j][chamber]["dx_vs_de"] = registryResidualsMCH.add((histPath + "dx_vs_de").c_str(), "Cluster x residual vs. DE index", {HistType::kTH2F, {deAxis, dxAxis}}); + mchResidualsHistosPerDE[i][j][chamber]["dy_vs_de"] = registryResidualsMCH.add((histPath + "dy_vs_de").c_str(), "Cluster y residual vs. DE index", {HistType::kTH2F, {deAxis, dxAxis}}); + + // mixed events + histPath = std::string("Alignment/mixed-event/Residuals/MCH/MCH_") + topBottom + "/" + sign + "/CH" + std::to_string(chamber + 1) + "/"; + // Delta x and y at cluster + mchResidualsHistosPerDEMixedEvents[i][j][chamber]["dx_vs_de"] = registryResidualsMCH.add((histPath + "dx_vs_de").c_str(), "Cluster x residual vs. DE index", {HistType::kTH2F, {deAxis, dxAxis}}); + mchResidualsHistosPerDEMixedEvents[i][j][chamber]["dy_vs_de"] = registryResidualsMCH.add((histPath + "dy_vs_de").c_str(), "Cluster y residual vs. DE index", {HistType::kTH2F, {deAxis, dxAxis}}); + } + } + } + } + + if (configQAs.fEnableQADCA) { + for (size_t j = 0; j < quadrants.size(); j++) { + const auto& quadrant = quadrants[j]; + std::string histPath = std::string("Alignment/same-event/DCA/MFT/") + quadrant + "/"; + dcaHistos[0][j][0]["DCA_x"] = registryDCA.add((histPath + "DCA_x").c_str(), std::format("DCA(x) - {}", quadrant).c_str(), {HistType::kTH1F, {dcaxMFTAxis}}); + dcaHistos[0][j][1]["DCA_x"] = registryDCA.add((histPath + "DCA_x_pos").c_str(), std::format("DCA(x) - {} charge > 0", quadrant).c_str(), {HistType::kTH1F, {dcaxMFTAxis}}); + dcaHistos[0][j][2]["DCA_x"] = registryDCA.add((histPath + "DCA_x_neg").c_str(), std::format("DCA(x) - {} charge < 0", quadrant).c_str(), {HistType::kTH1F, {dcaxMFTAxis}}); + dcaHistos[0][j][0]["DCA_y"] = registryDCA.add((histPath + "DCA_y").c_str(), std::format("DCA(y) - {}", quadrant).c_str(), {HistType::kTH1F, {dcayMFTAxis}}); + dcaHistos[0][j][1]["DCA_y"] = registryDCA.add((histPath + "DCA_y_pos").c_str(), std::format("DCA(y) - {} charge > 0", quadrant).c_str(), {HistType::kTH1F, {dcayMFTAxis}}); + dcaHistos[0][j][2]["DCA_y"] = registryDCA.add((histPath + "DCA_y_neg").c_str(), std::format("DCA(y) - {} charge < 0", quadrant).c_str(), {HistType::kTH1F, {dcayMFTAxis}}); + dcaHistos[0][j][0]["DCA_x_vs_z"] = registryDCA.add((histPath + "DCA_x_vs_z").c_str(), std::format("DCA(x) vs. z - {}", quadrant).c_str(), {HistType::kTH2F, {dcazAxis, dcaxMFTAxis}}); + dcaHistos[0][j][0]["DCA_y_vs_z"] = registryDCA.add((histPath + "DCA_y_vs_z").c_str(), std::format("DCA(y) vs. z - {}", quadrant).c_str(), {HistType::kTH2F, {dcazAxis, dcayMFTAxis}}); + + histPath = std::string("Alignment/same-event/DCA/MCH/") + quadrant + "/"; + dcaHistos[1][j][0]["DCA_x"] = registryDCA.add((histPath + "DCA_x").c_str(), std::format("DCA(x) - {}", quadrant).c_str(), {HistType::kTH1F, {dcaxMCHAxis}}); + dcaHistos[1][j][1]["DCA_x"] = registryDCA.add((histPath + "DCA_x_pos").c_str(), std::format("DCA(x) - {} charge > 0", quadrant).c_str(), {HistType::kTH1F, {dcaxMCHAxis}}); + dcaHistos[1][j][2]["DCA_x"] = registryDCA.add((histPath + "DCA_x_neg").c_str(), std::format("DCA(x) - {} charge < 0", quadrant).c_str(), {HistType::kTH1F, {dcaxMCHAxis}}); + dcaHistos[1][j][0]["DCA_y"] = registryDCA.add((histPath + "DCA_y").c_str(), std::format("DCA(y) - {}", quadrant).c_str(), {HistType::kTH1F, {dcayMCHAxis}}); + dcaHistos[1][j][1]["DCA_y"] = registryDCA.add((histPath + "DCA_y_pos").c_str(), std::format("DCA(y) - {} charge > 0", quadrant).c_str(), {HistType::kTH1F, {dcayMCHAxis}}); + dcaHistos[1][j][2]["DCA_y"] = registryDCA.add((histPath + "DCA_y_neg").c_str(), std::format("DCA(y) - {} charge < 0", quadrant).c_str(), {HistType::kTH1F, {dcayMCHAxis}}); + + histPath = std::string("Alignment/mixed-event/DCA/MFT/") + quadrant + "/"; + dcaHistosMixedEvents[0][j][0]["DCA_x"] = registryDCA.add((histPath + "DCA_x").c_str(), std::format("DCA(x) - {}", quadrant).c_str(), {HistType::kTH1F, {dcaxMFTAxis}}); + dcaHistosMixedEvents[0][j][1]["DCA_x"] = registryDCA.add((histPath + "DCA_x_pos").c_str(), std::format("DCA(x) - {} charge > 0", quadrant).c_str(), {HistType::kTH1F, {dcaxMFTAxis}}); + dcaHistosMixedEvents[0][j][2]["DCA_x"] = registryDCA.add((histPath + "DCA_x_neg").c_str(), std::format("DCA(x) - {} charge < 0", quadrant).c_str(), {HistType::kTH1F, {dcaxMFTAxis}}); + dcaHistosMixedEvents[0][j][0]["DCA_y"] = registryDCA.add((histPath + "DCA_y").c_str(), std::format("DCA(y) - {}", quadrant).c_str(), {HistType::kTH1F, {dcayMFTAxis}}); + dcaHistosMixedEvents[0][j][1]["DCA_y"] = registryDCA.add((histPath + "DCA_y_pos").c_str(), std::format("DCA(y) - {} charge > 0", quadrant).c_str(), {HistType::kTH1F, {dcayMFTAxis}}); + dcaHistosMixedEvents[0][j][2]["DCA_y"] = registryDCA.add((histPath + "DCA_y_neg").c_str(), std::format("DCA(y) - {} charge < 0", quadrant).c_str(), {HistType::kTH1F, {dcayMFTAxis}}); + dcaHistosMixedEvents[0][j][0]["DCA_x_vs_z"] = registryDCA.add((histPath + "DCA_x_vs_z").c_str(), std::format("DCA(x) vs. z - {}", quadrant).c_str(), {HistType::kTH2F, {dcazAxis, dcaxMFTAxis}}); + dcaHistosMixedEvents[0][j][0]["DCA_y_vs_z"] = registryDCA.add((histPath + "DCA_y_vs_z").c_str(), std::format("DCA(y) vs. z - {}", quadrant).c_str(), {HistType::kTH2F, {dcazAxis, dcayMFTAxis}}); + + histPath = std::string("Alignment/mixed-event/DCA/MCH/") + quadrant + "/"; + dcaHistosMixedEvents[1][j][0]["DCA_x"] = registryDCA.add((histPath + "DCA_x").c_str(), std::format("DCA(x) - {}", quadrant).c_str(), {HistType::kTH1F, {dcaxMCHAxis}}); + dcaHistosMixedEvents[1][j][1]["DCA_x"] = registryDCA.add((histPath + "DCA_x_pos").c_str(), std::format("DCA(x) - {} charge > 0", quadrant).c_str(), {HistType::kTH1F, {dcaxMCHAxis}}); + dcaHistosMixedEvents[1][j][2]["DCA_x"] = registryDCA.add((histPath + "DCA_x_neg").c_str(), std::format("DCA(x) - {} charge < 0", quadrant).c_str(), {HistType::kTH1F, {dcaxMCHAxis}}); + dcaHistosMixedEvents[1][j][0]["DCA_y"] = registryDCA.add((histPath + "DCA_y").c_str(), std::format("DCA(y) - {}", quadrant).c_str(), {HistType::kTH1F, {dcayMCHAxis}}); + dcaHistosMixedEvents[1][j][1]["DCA_y"] = registryDCA.add((histPath + "DCA_y_pos").c_str(), std::format("DCA(y) - {} charge > 0", quadrant).c_str(), {HistType::kTH1F, {dcayMCHAxis}}); + dcaHistosMixedEvents[1][j][2]["DCA_y"] = registryDCA.add((histPath + "DCA_y_neg").c_str(), std::format("DCA(y) - {} charge < 0", quadrant).c_str(), {HistType::kTH1F, {dcayMCHAxis}}); + } + } + + if (configQAs.fEnableQADimuon) { + AxisSpec invMassAxis = {400, 1, 5, "M_{#mu^{+}#mu^{-}} (GeV/c^{2})"}; + AxisSpec invMassCorrelationAxis = {80, 0, 8, "M_{#mu^{+}#mu^{-}} (GeV/c^{2})"}; + AxisSpec invMassAxisFull = {5000, 0, 100, "M_{#mu^{+}#mu^{-}} (GeV/c^{2})"}; + // MCH-MID tracks with MCH acceptance cuts + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); + // MCH-MID tracks with MCH acceptance cuts and combinations from the top and bottom halfs of MCH + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH1F, {invMassAxisFull}}); + // MCH-MID tracks with MFT acceptance cuts and combinations from the top and bottom halfs of MCH + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH1F, {invMassAxisFull}}); + // MCH-MID tracks with MCH acceptance cuts and combinations from the left and right halfs of MCH + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or left-right", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH1F, {invMassAxisFull}}); + // MCH-MID tracks with MFT acceptance cuts + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); + // MCH-MID tracks with MFT acceptance cuts and combinations from the left and right halfs of MCH + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_RR", "#mu^{+}#mu^{-} invariant mass right-right", {HistType::kTH1F, {invMassAxisFull}}); + // Good MFT-MCH-MID tracks with MCH parameters and MFT acceptance cuts + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMatchesCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMatchesCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMatchesCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMatchesCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); + // Good MFT-MCH-MID tracks with global parameters MFT acceptance cuts + registryDimuon.add("dimuon/same-event/invariantMass_GlobalMuonKine_GlobalMatchesCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_GlobalMuonKine_GlobalMatchesCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_GlobalMuonKine_GlobalMatchesCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_GlobalMuonKine_GlobalMatchesCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); + // Good MFT-MCH-MID tracks with re-scaled MFT kinematics and MFT acceptance cuts + registryDimuon.add("dimuon/same-event/invariantMass_ScaledMftKine_GlobalMatchesCuts", "M_{#mu^{+}#mu^{-}} - rescaled MFT momentum", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_ScaledMftKine_GlobalMatchesCuts", "M_{#mu^{+}#mu^{-}} - rescaled MFT momentum", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_ScaledMftKine_GlobalMatchesCuts", "M_{#mu^{+}#mu^{-}} - rescaled MFT momentum", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_ScaledMftKine_GlobalMatchesCuts", "M_{#mu^{+}#mu^{-}} - rescaled MFT momentum", {HistType::kTH1F, {invMassAxisFull}}); + // combinations of tracks from top and bottom halfs of MFT + registryDimuon.add("dimuon/same-event/invariantMass_ScaledMftKine_GlobalMatchesCuts_TT", "M_{#mu^{+}#mu^{-}} - rescaled MFT momentum, top-top", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMass_ScaledMftKine_GlobalMatchesCuts_TB", "M_{#mu^{+}#mu^{-}} - rescaled MFT momentum, top-bottom", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMass_ScaledMftKine_GlobalMatchesCuts_BT", "M_{#mu^{+}#mu^{-}} - rescaled MFT momentum, bottom-top", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMass_ScaledMftKine_GlobalMatchesCuts_BB", "M_{#mu^{+}#mu^{-}} - rescaled MFT momentum, bottom-bottom", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_ScaledMftKine_GlobalMatchesCuts_TT", "M_{#mu^{+}#mu^{-}} - rescaled MFT momentum, top-top", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_ScaledMftKine_GlobalMatchesCuts_TB", "M_{#mu^{+}#mu^{-}} - rescaled MFT momentum, top-bottom", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_ScaledMftKine_GlobalMatchesCuts_BT", "M_{#mu^{+}#mu^{-}} - rescaled MFT momentum, bottom-top", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_ScaledMftKine_GlobalMatchesCuts_BB", "M_{#mu^{+}#mu^{-}} - rescaled MFT momentum, bottom-bottom", {HistType::kTH1F, {invMassAxis}}); + // combinations with sub-leading matches + registryDimuon.add("dimuon/same-event/invariantMass_GlobalMuonKine_GlobalMatchesCuts_leading_subleading", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_GlobalMuonKine_GlobalMatchesCuts_leading_subleading", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/same-event/invariantMass_GlobalMuonKine_GlobalMatchesCuts_subleading_leading", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_GlobalMuonKine_GlobalMatchesCuts_subleading_leading", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/same-event/invariantMass_GlobalMuonKine_GlobalMatchesCuts_subleading_subleading", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_GlobalMuonKine_GlobalMatchesCuts_subleading_subleading", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); + + // invariant mass correlations + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_vs_GlobalMuonKine", "M_{#mu^{+}#mu^{-}} - muon tracks vs. global tracks", {HistType::kTH2F, {invMassCorrelationAxis, invMassCorrelationAxis}}); + registryDimuon.add("dimuon/same-event/invariantMass_ScaledMftKine_vs_GlobalMuonKine", "M_{#mu^{+}#mu^{-}} - rescaled MFT tracks vs. global tracks", {HistType::kTH2F, {invMassCorrelationAxis, invMassCorrelationAxis}}); + registryDimuon.add("dimuon/same-event/invariantMass_GlobalMuonKine_subleading_vs_leading", "M_{#mu^{+}#mu^{-}} - subleading vs. leading matches", {HistType::kTH2F, {invMassCorrelationAxis, invMassCorrelationAxis}}); + } + } + + void doTransformMFT(o2::mch::TrackParam& track) + { + double zCH10 = -1437.6; + double z = track.getZ(); + // double dZ = zMCH - z; + double x = track.getNonBendingCoor(); + double y = track.getBendingCoor(); + double xSlope = track.getNonBendingSlope(); + double ySlope = track.getBendingSlope(); + + double xShiftMCH = (y > 0) ? 0.8541 : -1.5599; + double xCorrection = xShiftMCH * z / zCH10; + track.setNonBendingCoor(x + xCorrection); + double xSlopeCorrection = xShiftMCH / zCH10; + track.setNonBendingSlope(xSlope + xSlopeCorrection); + + double yShiftMCH = (y > 0) ? 3.0311 : 0.7588; + double yCorrection = yShiftMCH * z / zCH10; + track.setBendingCoor(y + yCorrection); + double ySlopeCorrection = yShiftMCH / zCH10; + track.setBendingSlope(ySlope + ySlopeCorrection); + } + + template + void TransformMFT(TTrack& track) + { + if constexpr (static_cast(GlobalFwdFillMap)) { + auto mchTrack = mMatching.FwdtoMCH(track); + doTransformMFT(mchTrack); + + auto transformedTrack = mMatching.MCHtoFwd(mchTrack); + track.setParameters(transformedTrack.getParameters()); + track.setZ(transformedTrack.getZ()); + track.setCovariances(transformedTrack.getCovariances()); + } else { + o2::dataformats::GlobalFwdTrack fwdtrack; + fwdtrack.setParameters(track.getParameters()); + fwdtrack.setZ(track.getZ()); + fwdtrack.setCovariances(track.getCovariances()); + auto mchTrack = mMatching.FwdtoMCH(fwdtrack); + doTransformMFT(mchTrack); + + auto transformedTrack = mMatching.MCHtoFwd(mchTrack); + track.setParameters(transformedTrack.getParameters()); + track.setZ(transformedTrack.getZ()); + track.setCovariances(transformedTrack.getCovariances()); + } + } + + int GetDetElemId(int iDetElemNumber) + { + // make sure detector number is valid + if (!(iDetElemNumber >= fgSNDetElemCh[0] && + iDetElemNumber < fgSNDetElemCh[10])) { + LOGF(fatal, "Invalid detector element number: %d", iDetElemNumber); + } + /// get det element number from ID + // get chamber and element number in chamber + int iCh = 0; + int iDet = 0; + for (int i = 1; i <= 10; i++) { + if (iDetElemNumber < fgSNDetElemCh[i]) { + iCh = i; + iDet = iDetElemNumber - fgSNDetElemCh[i - 1]; + break; + } + } + + // make sure detector index is valid + if (!(iCh > 0 && iCh <= 10 && iDet < fgNDetElemCh[iCh - 1])) { + LOGF(fatal, "Invalid detector element id: %d", 100 * iCh + iDet); + } + + // add number of detectors up to this chamber + return 100 * iCh + iDet; + } + + int GetQuadrantPhi(double phi) + { + if (phi >= 0 && phi < 90) { + return 0; + } + if (phi >= 90 && phi <= 180) { + return 1; + } + if (phi >= -180 && phi < -90) { + return 2; + } + if (phi >= -90 && phi < 0) { + return 3; + } + return -1; + } + + template + int GetQuadrantTrack(TTrack const& track) + { + double phi = static_cast(track.phi()) * 180 / TMath::Pi(); + return GetQuadrantPhi(phi); + } + + bool RemoveTrack(mch::Track& track) + { + // Refit track with re-aligned clusters + bool removeTrack = false; + try { + trackFitter.fit(track, false); + } catch (exception const& e) { + removeTrack = true; + return removeTrack; + } + + auto itStartingParam = std::prev(track.rend()); + + while (true) { + + try { + trackFitter.fit(track, true, false, (itStartingParam == track.rbegin()) ? nullptr : &itStartingParam); + } catch (exception const&) { + removeTrack = true; + break; + } + + double worstLocalChi2 = -1.0; + + track.tagRemovableClusters(0x1F, false); + + auto itWorstParam = track.end(); + + for (auto itParam = track.begin(); itParam != track.end(); ++itParam) { + if (itParam->getLocalChi2() > worstLocalChi2) { + worstLocalChi2 = itParam->getLocalChi2(); + itWorstParam = itParam; + } + } + + if (worstLocalChi2 < mImproveCutChi2) { + break; + } + + if (!itWorstParam->isRemovable()) { + removeTrack = true; + track.removable(); + break; + } + + auto itNextParam = track.removeParamAtCluster(itWorstParam); + auto itNextToNextParam = (itNextParam == track.end()) ? itNextParam : std::next(itNextParam); + itStartingParam = track.rbegin(); + + if (track.getNClusters() < 10) { + removeTrack = true; + break; + } else { + while (itNextToNextParam != track.end()) { + if (itNextToNextParam->getClusterPtr()->getChamberId() != itNextParam->getClusterPtr()->getChamberId()) { + itStartingParam = std::make_reverse_iterator(++itNextParam); + break; + } + ++itNextToNextParam; + } + } + } + + if (!removeTrack) { + for (auto& param : track) { + param.setParameters(param.getSmoothParameters()); + param.setCovariances(param.getSmoothCovariances()); + } + } + + return removeTrack; + } + + template + bool pDCACut(Var const& fgValues, Var const& fgValuesPV, double nSigmaPDCA) + { + static const double sigmaPDCA23 = 80.; + static const double sigmaPDCA310 = 54.; + static const double relPRes = 0.0004; + static const double slopeRes = 0.0005; + + double thetaAbs = TMath::ATan(fgValues.rabs / 505.) * TMath::RadToDeg(); + double p = fgValuesPV.p; + + double pDCA = fgValues.pDca; + double sigmaPDCA = (thetaAbs < 3) ? sigmaPDCA23 : sigmaPDCA310; + double nrp = nSigmaPDCA * relPRes * p; + double pResEffect = sigmaPDCA / (1. - nrp / (1. + nrp)); + double slopeResEffect = 535. * slopeRes * p; + double sigmaPDCAWithRes = TMath::Sqrt(pResEffect * pResEffect + slopeResEffect * slopeResEffect); + + if (pDCA > nSigmaPDCA * sigmaPDCAWithRes) { + return false; + } + + return true; + } + + template + bool IsMixedEvent(Var const& fgValues1, Var const& fgValues2) + { + if (fgValues1.bc == fgValues2.bc) { + return false; + } + + uint64_t bcDiff = (fgValues2.bc > fgValues1.bc) ? (fgValues2.bc - fgValues1.bc) : (fgValues1.bc - fgValues2.bc); + // in the event mixing case, we require a minimum BC gap between the collisions + if (bcDiff < configMixing.fEventMinDeltaBc) + return false; + + // we also require that the collisions have similar Z positions and multiplicity of MFT tracks + if (std::fabs(fgValues2.z - fgValues1.z) > configMixing.fEventMaxDeltaVtxZ) { + return false; + } + + if (std::abs(fgValues2.multMFT - fgValues1.multMFT) > configMixing.fEventMaxDeltaNMFT) { + return false; + } + + return true; + } + + template + bool IsGoodMuon(Var const& fgValues, Var const& fgValuesPV, float fTrackChi2MchUp, float fPMchLow, float fPtMchLow, float fEtaMchLow, float fEtaMchUp, float fRabsLow, float fRabsUp, float fSigmaPdcaUp) + { + // chi2 cut + if (fgValues.chi2 > fTrackChi2MchUp) + return false; + + // momentum cut + if (fgValues.p < fPMchLow) { + return false; // skip low-momentum tracks + } + + // transverse momentum cut + if (fgValues.pT < fPtMchLow) { + return false; // skip low-momentum tracks + } + + // Eta cut + if ((fgValues.eta < fEtaMchLow || fgValues.eta > fEtaMchUp)) { + return false; + } + + // RAbs cut + if ((fgValues.rabs < fRabsLow || fgValues.rabs > fRabsUp)) { + return false; + } + + // pDCA cut + if (!pDCACut(fgValues, fgValuesPV, fSigmaPdcaUp)) { + return false; + } + + return true; + } + + template + bool IsGoodMuon(Var const& fgValues, Var const& fgValuesPV) + { + return IsGoodMuon(fgValues, fgValuesPV, configMuons.fTrackChi2MchUp, configMuons.fPMchLow, configMuons.fPtMchLow, configMuons.fEtaMchLow, configMuons.fEtaMchUp, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp); + } + + template + bool IsGoodGlobalMuon(Var const& fgValues, Var const& fgValuesPV) + { + return IsGoodMuon(fgValues, fgValuesPV, configMuons.fTrackChi2MchUp, configMuons.fPMchLow, configMuons.fPtMchLow, configMFTs.fEtaMftLow, configMFTs.fEtaMftUp, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp); + } + + template + bool IsGoodMFT(Var const& fgValues, float fTrackChi2MftUp, int fTrackNClustMftLow) + { + // chi2 cut + if (fgValues.chi2 > fTrackChi2MftUp) { + return false; + } + + // number of clusters cut + if (fgValues.nClusters < fTrackNClustMftLow) { + return false; + } + + return true; + } + + template + bool IsGoodGlobalMatching(Var const& fgValues, float fTrackChi2MftUp, int fTrackNClustMftLow, float fMatchingChi2MftMchUp) + { + if (!IsGoodMFT(fgValues, fTrackChi2MftUp, fTrackNClustMftLow)) { + return false; + } + + if (fgValues.chi2matching > fMatchingChi2MftMchUp) { + return false; + } + + return true; + } + + template + bool IsGoodGlobalMatching(Var const& fgValues) + { + return IsGoodGlobalMatching(fgValues, configMFTs.fTrackChi2MftUp, configMFTs.fTrackNClustMftLow, fMatchingChi2MftMchUp); + } + + template + double GetMuMuInvariantMass(VarT const& track1, VarT const& track2) + { + ROOT::Math::PxPyPzMVector muon1{ + track1.px, + track1.py, + track1.pz, + o2::constants::physics::MassMuon}; + + ROOT::Math::PxPyPzMVector muon2{ + track2.px, + track2.py, + track2.pz, + o2::constants::physics::MassMuon}; + + auto dimuon = muon1 + muon2; + + return dimuon.M(); + } + + template + void GetMuonPairs(TMuons const& muons, TCandidates const& matchingCandidates, const std::map& collisionInfos, + std::vector& muonPairs, + std::vector& globalMuonPairs) + { + // muon tracks - outer loop over collisions + for (auto& [collisionIndex1, collisionInfo1] : collisionInfos) { + + // outer loop over muon tracks + auto muonCollision1 = muons.sliceBy(fwdtracksPerCollision, collisionInfo1.globalIndex); + for (auto muon1 : muonCollision1) { + + if (muon1.trackType() <= 2) { + continue; + } + auto mchIndex1 = muon1.globalIndex(); + + // inner loop over collisions + for (auto& [collisionIndex2, collisionInfo2] : collisionInfos) { + // avoid double-counting of collisions + if (collisionIndex2 < collisionIndex1) + continue; + + bool sameEvent = (collisionIndex1 == collisionIndex2); + bool mixedEvent = IsMixedEvent(collisionInfo1, collisionInfo2); + + if (!sameEvent && !mixedEvent) + continue; + + // inner loop over muon tracks + auto muonCollision2 = muons.sliceBy(fwdtracksPerCollision, collisionInfo2.globalIndex); + for (auto muon2 : muonCollision2) { + if (muon2.trackType() <= 2) { + continue; + } + auto mchIndex2 = muon2.globalIndex(); + + // avoid double-counting of muon pairs if we are not mixing events + if (sameEvent && mchIndex2 <= mchIndex1) + continue; + + MuonPair muonPair{{collisionIndex1, mchIndex1}, {collisionIndex2, mchIndex2}}; + muonPairs.emplace_back(muonPair); + } + } + } + } + + // global muon tracks - outer loop over collisions + for (auto& [collisionIndex1, collisionInfo1] : collisionInfos) { + + // outer loop over global muon tracks + auto muonCollision1 = muons.sliceBy(fwdtracksPerCollision, collisionInfo1.globalIndex); + for (auto muon1 : muonCollision1) { + + if (muon1.trackType() <= 2) { + continue; + } + auto mchIndex1 = muon1.globalIndex(); + auto matchingCandidateIt1 = matchingCandidates.find(mchIndex1); + if (matchingCandidateIt1 == matchingCandidates.end()) { + continue; + } + + // inner loop over collisions + for (auto& [collisionIndex2, collisionInfo2] : collisionInfos) { + // avoid double-counting of collisions + if (collisionIndex2 < collisionIndex1) + continue; + + bool sameEvent = (collisionIndex1 == collisionIndex2); + bool mixedEvent = IsMixedEvent(collisionInfo1, collisionInfo2); + + if (!sameEvent && !mixedEvent) + continue; + + // outer loop over global muon tracks + auto muonCollision2 = muons.sliceBy(fwdtracksPerCollision, collisionInfo2.globalIndex); + for (auto muon2 : muonCollision2) { + + if (muon2.trackType() <= 2) { + continue; + } + auto mchIndex2 = muon2.globalIndex(); + auto matchingCandidateIt2 = matchingCandidates.find(mchIndex2); + if (matchingCandidateIt2 == matchingCandidates.end()) { + continue; + } + + // avoid double-counting of muon pairs if we are not mixing events + if (sameEvent && mchIndex2 <= mchIndex1) + continue; + + GlobalMuonPair muonPair{{collisionIndex1, matchingCandidateIt1->second}, {collisionIndex2, matchingCandidateIt2->second}}; + globalMuonPairs.emplace_back(muonPair); + } + } + } + } + } + + template + void FillCollision(TEvent const& collision, Var& fgValues) + { + fgValues.globalIndex = collision.globalIndex(); + fgValues.x = collision.posX(); + fgValues.y = collision.posY(); + fgValues.z = collision.posZ(); + fgValues.covXX = collision.covXX(); + fgValues.covYY = collision.covYY(); + } + + template + void FillTrack(mch::Track const& muon, Var& fgValues) + { + mch::TrackParam trackParam = mch::TrackParam(muon.first()); + auto proptrack = mMatching.MCHtoFwd(trackParam); + + fgValues.pT = proptrack.getPt(); + fgValues.x = proptrack.getX(); + fgValues.y = proptrack.getY(); + fgValues.z = proptrack.getZ(); + fgValues.eta = proptrack.getEta(); + fgValues.tgl = proptrack.getTgl(); + fgValues.phi = proptrack.getPhi(); + + fgValues.p = proptrack.getP(); + fgValues.px = proptrack.getPx(); + fgValues.py = proptrack.getPy(); + fgValues.pz = proptrack.getPz(); + + fgValues.chi2 = trackParam.getTrackChi2(); + fgValues.nClusters = muon.getNClusters(); + fgValues.sign = trackParam.getCharge(); + } + + template + void FillTrack(TTrack const& muon, Var& fgValues) + { + fgValues.collisionId = muon.collisionId(); + fgValues.globalIndex = muon.globalIndex(); + fgValues.trackTime = muon.trackTime(); + + fgValues.pT = muon.pt(); + fgValues.x = muon.x(); + fgValues.y = muon.y(); + fgValues.z = muon.z(); + fgValues.eta = muon.eta(); + fgValues.tgl = muon.tgl(); + fgValues.phi = muon.phi(); + + fgValues.p = muon.p(); + fgValues.px = muon.px(); + fgValues.py = muon.py(); + fgValues.pz = muon.pz(); + + fgValues.chi2 = muon.chi2(); + fgValues.nClusters = muon.nClusters(); + fgValues.sign = muon.sign(); + + if constexpr (static_cast(MuonFillMap)) { + // Direct info from AO2D without re-propagation + fgValues.pDca = muon.pDca(); + fgValues.rabs = muon.rAtAbsorberEnd(); + fgValues.trackType = muon.trackType(); + } + } + + template + bool FillClusters(TMCHTrack const& muon, TFwdCls const& mchcls, Var& fgValues, mch::Track& convertedTrack) + { + int removable = 0; + auto clustersSliced = mchcls.sliceBy(perMuon, muon.globalIndex()); // Slice clusters by muon id + vector> posClusters; + + int clIndex = -1; + // Get re-aligned clusters associated to current track + for (auto const& cluster : clustersSliced) { + clIndex += 1; + + math_utils::Point3D local; + math_utils::Point3D master; + + mch::Cluster* clusterMCH = new mch::Cluster(); + master.SetXYZ(cluster.x(), cluster.y(), cluster.z()); + + if (configRealign.fDoRealign) { + // Transformation from reference geometry frame to new geometry frame + transformRef[cluster.deId()].MasterToLocal(master, local); + transformNew[cluster.deId()].LocalToMaster(local, master); + } + + clusterMCH->x = master.x(); + clusterMCH->y = master.y(); + clusterMCH->z = master.z(); + + uint32_t ClUId = mch::Cluster::buildUniqueId(static_cast(cluster.deId() / 100) - 1, cluster.deId(), clIndex); + clusterMCH->uid = ClUId; + clusterMCH->ex = cluster.isGoodX() ? 0.2 : 10.0; + clusterMCH->ey = cluster.isGoodY() ? 0.2 : 10.0; + + // Fill temporary values + vector posCls = {clusterMCH->x, clusterMCH->y, clusterMCH->z}; + vector eCls = {clusterMCH->ex, clusterMCH->ey}; + posClusters.emplace_back(posCls); + fgValues.errorClusters.emplace_back(eCls); + fgValues.DEIDs.emplace_back(cluster.deId()); + + // Add transformed cluster into temporary variable + convertedTrack.createParamAtCluster(*clusterMCH); + } + + if (configRealign.fDoRealign) { + // Refit the re-aligned track + if (convertedTrack.getNClusters() != 0) { + removable = RemoveTrack(convertedTrack); + } else { + LOGF(fatal, "Muon track %d has no associated clusters.", muon.globalIndex()); + } + + for (auto it = convertedTrack.begin(); it != convertedTrack.end(); it++) { + vector pos = {static_cast(it->getNonBendingCoor()), static_cast(it->getBendingCoor()), static_cast(it->getZ())}; + fgValues.posClusters.emplace_back(pos); + } + + } else { + fgValues.posClusters = posClusters; + } + + return !removable; + } + + template + void FillMatchingCandidates(TMuon const& muon, TMCH const& mchtrack, TMap& matchingCandidates) + { + uint64_t muonId = muon.globalIndex(); + uint64_t mchId = mchtrack.globalIndex(); + + //// Save matching candidates index pairs + auto matchingCandidateIt = matchingCandidates.find(mchId); + if (matchingCandidateIt != matchingCandidates.end()) { + matchingCandidateIt->second.push_back(muonId); + } else { + matchingCandidates[mchId].push_back(muonId); + } + } + + template + void FillPropagation(mch::Track const& muon, VarC const& collision, VarT& fgValues, int endPoint = kToVtx, int endZ = 0) + { + o2::dataformats::GlobalFwdTrack propmuon; + mch::TrackParam trackParam = mch::TrackParam(muon.first()); + fgValues.chi2 = trackParam.getTrackChi2(); + fgValues.nClusters = muon.getNClusters(); + fgValues.sign = trackParam.getCharge(); + + if (endPoint == kToVtx) { + o2::mch::TrackExtrap::extrapToVertex(trackParam, collision.x, collision.y, collision.z, collision.covXX, collision.covYY); + } + if (endPoint == kToDCA) { + o2::mch::TrackExtrap::extrapToVertexWithoutBranson(trackParam, collision.z); + } + if (endPoint == kToAbsEnd) { + o2::mch::TrackExtrap::extrapToZ(trackParam, zAtAbsEnd); + } + if (endPoint == kToZ) { + o2::mch::TrackExtrap::extrapToZ(trackParam, endZ); + } + + auto proptrack = mMatching.MCHtoFwd(trackParam); + propmuon.setParameters(proptrack.getParameters()); + propmuon.setZ(proptrack.getZ()); + propmuon.setCovariances(proptrack.getCovariances()); + + //// Fill propagation informations + if (endPoint == kToVtx || endPoint == kToZ) { + fgValues.pT = propmuon.getPt(); + fgValues.x = propmuon.getX(); + fgValues.y = propmuon.getY(); + fgValues.z = propmuon.getZ(); + fgValues.eta = propmuon.getEta(); + fgValues.tgl = propmuon.getTgl(); + fgValues.phi = propmuon.getPhi(); + + fgValues.p = propmuon.getP(); + fgValues.px = propmuon.getP() * sin(M_PI / 2 - atan(propmuon.getTgl())) * cos(propmuon.getPhi()); + fgValues.py = propmuon.getP() * sin(M_PI / 2 - atan(propmuon.getTgl())) * sin(propmuon.getPhi()); + fgValues.pz = propmuon.getP() * cos(M_PI / 2 - atan(propmuon.getTgl())); + } + + if (endPoint == kToDCA) { + fgValues.dcaX = (propmuon.getX() - collision.x); + fgValues.dcaY = (propmuon.getY() - collision.y); + float dcaXY = std::sqrt(fgValues.dcaX * fgValues.dcaX + fgValues.dcaY * fgValues.dcaY); + + mch::TrackParam trackParam = mch::TrackParam(muon.first()); + float p = trackParam.p(); + fgValues.pDca = p * dcaXY; + } + + if (endPoint == kToAbsEnd) { + double xAbs = propmuon.getX(); + double yAbs = propmuon.getY(); + fgValues.rabs = std::sqrt(xAbs * xAbs + yAbs * yAbs); + } + } + + template + void FillPropagation(TTrack const& muon, VarC const& collision, VarT const& fgValuesMCH, VarT& fgValues, int endPoint = kToVtx, int endZ = 0) + { + o2::dataformats::GlobalFwdTrack propmuon; + double chi2 = muon.chi2(); + fgValues.chi2 = chi2; + fgValues.nClusters = muon.nClusters(); + fgValues.sign = muon.sign(); + + if constexpr (static_cast(MuonFillMap)) { + o2::dataformats::GlobalFwdTrack track; + + SMatrix5 tpars(muon.x(), muon.y(), muon.phi(), muon.tgl(), muon.signed1Pt()); + std::vector v1{muon.cXX(), muon.cXY(), muon.cYY(), muon.cPhiX(), muon.cPhiY(), + muon.cPhiPhi(), muon.cTglX(), muon.cTglY(), muon.cTglPhi(), muon.cTglTgl(), + muon.c1PtX(), muon.c1PtY(), muon.c1PtPhi(), muon.c1PtTgl(), muon.c1Pt21Pt2()}; + SMatrix55 tcovs(v1.begin(), v1.end()); + o2::track::TrackParCovFwd fwdtrack{muon.z(), tpars, tcovs, chi2}; + + track.setParameters(tpars); + track.setZ(fwdtrack.getZ()); + track.setCovariances(tcovs); + auto mchTrack = mMatching.FwdtoMCH(track); + + if (endPoint == kToVtx) { + o2::mch::TrackExtrap::extrapToVertex(mchTrack, collision.x, collision.y, collision.z, collision.covXX, collision.covYY); + } + if (endPoint == kToDCA) { + o2::mch::TrackExtrap::extrapToVertexWithoutBranson(mchTrack, collision.z); + } + if (endPoint == kToAbsEnd) { + o2::mch::TrackExtrap::extrapToZ(mchTrack, zAtAbsEnd); + } + if (endPoint == kToZ) { + o2::mch::TrackExtrap::extrapToZ(mchTrack, endZ); + } + + auto proptrack = mMatching.MCHtoFwd(mchTrack); + propmuon.setParameters(proptrack.getParameters()); + propmuon.setZ(proptrack.getZ()); + propmuon.setCovariances(proptrack.getCovariances()); + + } else { + + o2::dataformats::GlobalFwdTrack track; + + if constexpr (static_cast(Scaled)) { + double pMCH = fgValuesMCH.p; + int sign = fgValuesMCH.sign; + + double px = pMCH * sin(M_PI / 2 - atan(muon.tgl())) * cos(muon.phi()); + double py = pMCH * sin(M_PI / 2 - atan(muon.tgl())) * sin(muon.phi()); + // double pz = pMCH * cos(M_PI / 2 - atan(mft.tgl())); + double pt = std::sqrt(std::pow(px, 2) + std::pow(py, 2)); + + double chi2 = muon.chi2(); + double signed1Pt = endPoint == kToDCA ? muon.signed1Pt() : sign / pt; + SMatrix5 tpars(muon.x(), muon.y(), muon.phi(), muon.tgl(), signed1Pt); + std::vector v1{0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0}; + SMatrix55 tcovs(v1.begin(), v1.end()); + o2::track::TrackParCovFwd fwdtrack{muon.z(), tpars, tcovs, chi2}; + track.setParameters(tpars); + track.setZ(fwdtrack.getZ()); + track.setCovariances(tcovs); + } else { + SMatrix5 tpars(muon.x(), muon.y(), muon.phi(), muon.tgl(), muon.signed1Pt()); + std::vector v1{muon.cXX(), muon.cXY(), muon.cYY(), muon.cPhiX(), muon.cPhiY(), + muon.cPhiPhi(), muon.cTglX(), muon.cTglY(), muon.cTglPhi(), muon.cTglTgl(), + muon.c1PtX(), muon.c1PtY(), muon.c1PtPhi(), muon.c1PtTgl(), muon.c1Pt21Pt2()}; + SMatrix55 tcovs(v1.begin(), v1.end()); + o2::track::TrackParCovFwd fwdtrack{muon.z(), tpars, tcovs, chi2}; + track.setParameters(tpars); + track.setZ(fwdtrack.getZ()); + track.setCovariances(tcovs); + } + + if (endPoint == kToVtx) { + if (fEnableMFTAlignmentCorrections) { + TransformMFT<0>(track); + } + auto geoMan = o2::base::GeometryManager::meanMaterialBudget(muon.x(), muon.y(), muon.z(), collision.x, collision.y, collision.z); + auto x2x0 = static_cast(geoMan.meanX2X0); + track.propagateToVtxhelixWithMCS(collision.z, {collision.x, collision.y}, {collision.covXX, collision.covYY}, Bz, x2x0); + } + if (endPoint == kToDCA) { + if (fEnableMFTAlignmentCorrections) { + TransformMFT<0>(track); + } + track.propagateToZ(collision.z, Bz); + } + if (endPoint == kToZ) { + auto mchTrackExt = mMatching.FwdtoMCH(track); + if (fEnableMFTAlignmentCorrections) { + doTransformMFT(mchTrackExt); + } + o2::mch::TrackExtrap::extrapToZ(mchTrackExt, endZ); + track = mMatching.MCHtoFwd(mchTrackExt); + } + + propmuon.setParameters(track.getParameters()); + propmuon.setZ(track.getZ()); + propmuon.setCovariances(track.getCovariances()); + } + + //// Fill propagation informations + if (endPoint == kToVtx || endPoint == kToZ) { + fgValues.pT = propmuon.getPt(); + fgValues.x = propmuon.getX(); + fgValues.y = propmuon.getY(); + fgValues.z = propmuon.getZ(); + fgValues.eta = propmuon.getEta(); + fgValues.tgl = propmuon.getTgl(); + fgValues.phi = propmuon.getPhi(); + + fgValues.p = propmuon.getP(); + fgValues.px = propmuon.getP() * sin(M_PI / 2 - atan(propmuon.getTgl())) * cos(propmuon.getPhi()); + fgValues.py = propmuon.getP() * sin(M_PI / 2 - atan(propmuon.getTgl())) * sin(propmuon.getPhi()); + fgValues.pz = propmuon.getP() * cos(M_PI / 2 - atan(propmuon.getTgl())); + } + + if (endPoint == kToDCA) { + fgValues.dcaX = (propmuon.getX() - collision.x); + fgValues.dcaY = (propmuon.getY() - collision.y); + float dcaXY = std::sqrt(fgValues.dcaX * fgValues.dcaX + fgValues.dcaY * fgValues.dcaY); + + if constexpr (static_cast(MuonFillMap)) { + float p = muon.p(); + fgValues.pDca = p * dcaXY; + } + } + + if (endPoint == kToAbsEnd) { + double xAbs = propmuon.getX(); + double yAbs = propmuon.getY(); + fgValues.rabs = std::sqrt(xAbs * xAbs + yAbs * yAbs); + } + } + + template + void FillMatching(TTrack const& track, Var& fgValuesMCH, Var& fgValuesMFT) + { + fgValuesMCH.chi2matching = track.chi2MatchMCHMID(); + fgValuesMFT.chi2matching = track.chi2MatchMCHMFT(); + } + + template + void FillMuonHistograms(Var const& fgValuesMCH, Var const& fgValuesMCHpv, Var const& fgValuesMFT, Var const& fgValuesGlobal, VarVector const& fgValuesCandidates) + { + if constexpr (static_cast(MuonFillMap)) { + // Muon histograms + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, 1.E10, configMuons.fPMchLow, configMuons.fPtMchLow, configMuons.fEtaMchLow, configMuons.fEtaMchUp, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + registry.get(HIST("muons/TrackChi2"))->Fill(fgValuesMCH.chi2); + } + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, 0., configMuons.fPtMchLow, configMuons.fEtaMchLow, configMuons.fEtaMchUp, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + registry.get(HIST("muons/TrackP"))->Fill(fgValuesMCH.p); + } + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, configMuons.fPMchLow, 0., configMuons.fEtaMchLow, configMuons.fEtaMchUp, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + registry.get(HIST("muons/TrackPt"))->Fill(fgValuesMCH.pT); + } + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, configMuons.fPMchLow, configMuons.fPtMchLow, -1.E10, 1.E10, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + registry.get(HIST("muons/TrackEta"))->Fill(fgValuesMCH.eta); + } + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, configMuons.fPMchLow, configMuons.fPtMchLow, configMuons.fEtaMchLow, configMuons.fEtaMchUp, 0., 1.E10, configMuons.fSigmaPdcaUp)) { + registry.get(HIST("muons/TrackRabs"))->Fill(fgValuesMCH.rabs); + } + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, configMuons.fPMchLow, configMuons.fPtMchLow, configMuons.fEtaMchLow, configMuons.fEtaMchUp, configMuons.fRabsLow, configMuons.fRabsUp, 1.E10)) { + registry.get(HIST("muons/TrackPDCA"))->Fill(fgValuesMCH.pDca); + } + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, configMuons.fPMchLow, configMuons.fPtMchLow, configMuons.fEtaMchLow, configMuons.fEtaMchUp, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + registry.get(HIST("muons/TrackPhi"))->Fill(fgValuesMCH.phi * 180.0 / TMath::Pi()); + registry.get(HIST("muons/TrackDCA"))->Fill(std::sqrt(fgValuesMCH.dcaX * fgValuesMCH.dcaX + fgValuesMCH.dcaY * fgValuesMCH.dcaY)); + } + } + + if constexpr (static_cast(GlobalMuonFillMap)) { + // Global muon histograms + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, 1.E10, configMuons.fPMchLow, configMuons.fPtMchLow, configMFTs.fEtaMftLow, configMFTs.fEtaMftUp, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + registry.get(HIST("global-muons/TrackChi2"))->Fill(fgValuesMCH.chi2); + } + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, 0., configMuons.fPtMchLow, configMFTs.fEtaMftLow, configMFTs.fEtaMftUp, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + registry.get(HIST("global-muons/TrackP"))->Fill(fgValuesMCH.p); + + // Momentum correlations + registry.get(HIST("global-muons/MomentumCorrelation_Global_vs_Muon"))->Fill(fgValuesMCH.p, fgValuesGlobal.p); + if (fgValuesMCH.p != 0) { + registry.get(HIST("global-muons/MomentumDifference_Global_vs_Muon"))->Fill(fgValuesMCH.p, (fgValuesGlobal.p - fgValuesMCH.p) / fgValuesMCH.p); + } + + if (fgValuesCandidates.size() >= 2) { + registry.get(HIST("global-muons/MomentumCorrelation_subleading_vs_leading"))->Fill(fgValuesCandidates[0].p, fgValuesCandidates[1].p); + if (fgValuesCandidates[0].p != 0) { + registry.get(HIST("global-muons/MomentumDifference_subleading_vs_leading"))->Fill(fgValuesCandidates[0].p, (fgValuesCandidates[1].p - fgValuesCandidates[0].p) / fgValuesCandidates[0].p); + } + } + } + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, configMuons.fPMchLow, 0., configMFTs.fEtaMftLow, configMFTs.fEtaMftUp, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + registry.get(HIST("global-muons/TrackPt"))->Fill(fgValuesMCH.pT); + } + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, configMuons.fPMchLow, configMuons.fPtMchLow, -1.E10, 1.E10, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + registry.get(HIST("global-muons/TrackEta"))->Fill(fgValuesMCH.eta); + + // Eta correlations + registry.get(HIST("global-muons/EtaCorrelation_Global_vs_Muon"))->Fill(fgValuesMCH.eta, fgValuesGlobal.eta); + if (fgValuesMCH.eta != 0) { + registry.get(HIST("global-muons/EtaDifference_Global_vs_Muon"))->Fill(fgValuesMCH.eta, (fgValuesGlobal.eta - fgValuesMCH.eta) / fgValuesMCH.eta); + } + + if (fgValuesCandidates.size() >= 2) { + registry.get(HIST("global-muons/EtaCorrelation_subleading_vs_leading"))->Fill(fgValuesCandidates[0].eta, fgValuesCandidates[1].eta); + if (fgValuesCandidates[0].eta != 0) { + registry.get(HIST("global-muons/EtaDifference_subleading_vs_leading"))->Fill(fgValuesCandidates[0].eta, (fgValuesCandidates[1].eta - fgValuesCandidates[0].eta) / fgValuesCandidates[0].eta); + } + } + } + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, configMuons.fPMchLow, configMuons.fPtMchLow, configMFTs.fEtaMftLow, configMFTs.fEtaMftUp, 0., 1.E10, configMuons.fSigmaPdcaUp)) { + registry.get(HIST("global-muons/TrackRabs"))->Fill(fgValuesMCH.rabs); + } + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, configMuons.fPMchLow, configMuons.fPtMchLow, configMFTs.fEtaMftLow, configMFTs.fEtaMftUp, configMuons.fRabsLow, configMuons.fRabsUp, 1.E10)) { + registry.get(HIST("global-muons/TrackPDCA"))->Fill(fgValuesMCH.pDca); + } + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, configMuons.fPMchLow, configMuons.fPtMchLow, configMFTs.fEtaMftLow, configMFTs.fEtaMftUp, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + registry.get(HIST("global-muons/TrackPhi"))->Fill(fgValuesMCH.phi * 180.0 / TMath::Pi()); + registry.get(HIST("global-muons/TrackDCA"))->Fill(std::sqrt(fgValuesMCH.dcaX * fgValuesMCH.dcaX + fgValuesMCH.dcaY * fgValuesMCH.dcaY)); + } + } + + if constexpr (static_cast(GlobalMatchingFillMap)) { + // Global muon histograms + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, 1.E10, configMuons.fPMchLow, configMuons.fPtMchLow, configMFTs.fEtaMftLow, configMFTs.fEtaMftUp, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + if (IsGoodGlobalMatching(fgValuesMFT, configMFTs.fTrackChi2MftUp, configMFTs.fTrackNClustMftLow, fMatchingChi2MftMchUp)) { + registry.get(HIST("global-matches/TrackChi2"))->Fill(fgValuesMCH.chi2); + } + } + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, 0., configMuons.fPtMchLow, configMFTs.fEtaMftLow, configMFTs.fEtaMftUp, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + if (IsGoodGlobalMatching(fgValuesMFT, configMFTs.fTrackChi2MftUp, configMFTs.fTrackNClustMftLow, fMatchingChi2MftMchUp)) { + registry.get(HIST("global-matches/TrackP"))->Fill(fgValuesMCH.p); + } + } + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, configMuons.fPMchLow, 0., configMFTs.fEtaMftLow, configMFTs.fEtaMftUp, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + if (IsGoodGlobalMatching(fgValuesMFT, configMFTs.fTrackChi2MftUp, configMFTs.fTrackNClustMftLow, fMatchingChi2MftMchUp)) { + registry.get(HIST("global-matches/TrackPt"))->Fill(fgValuesMCH.pT); + } + } + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, configMuons.fPMchLow, configMuons.fPtMchLow, -1.E10, 1.E10, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + if (IsGoodGlobalMatching(fgValuesMFT, configMFTs.fTrackChi2MftUp, configMFTs.fTrackNClustMftLow, fMatchingChi2MftMchUp)) { + registry.get(HIST("global-matches/TrackEta"))->Fill(fgValuesMCH.eta); + } + } + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, configMuons.fPMchLow, configMuons.fPtMchLow, configMFTs.fEtaMftLow, configMFTs.fEtaMftUp, 0., 1.E10, configMuons.fSigmaPdcaUp)) { + if (IsGoodGlobalMatching(fgValuesMFT, configMFTs.fTrackChi2MftUp, configMFTs.fTrackNClustMftLow, fMatchingChi2MftMchUp)) { + registry.get(HIST("global-matches/TrackRabs"))->Fill(fgValuesMCH.rabs); + } + } + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, configMuons.fPMchLow, configMuons.fPtMchLow, configMFTs.fEtaMftLow, configMFTs.fEtaMftUp, configMuons.fRabsLow, configMuons.fRabsUp, 1.E10)) { + if (IsGoodGlobalMatching(fgValuesMFT, configMFTs.fTrackChi2MftUp, configMFTs.fTrackNClustMftLow, fMatchingChi2MftMchUp)) { + registry.get(HIST("global-matches/TrackPDCA"))->Fill(fgValuesMCH.pDca); + } + } + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, configMuons.fPMchLow, configMuons.fPtMchLow, configMFTs.fEtaMftLow, configMFTs.fEtaMftUp, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + if (IsGoodGlobalMatching(fgValuesMFT, configMFTs.fTrackChi2MftUp, configMFTs.fTrackNClustMftLow, fMatchingChi2MftMchUp)) { + registry.get(HIST("global-matches/TrackPhi"))->Fill(fgValuesMCH.phi * 180.0 / TMath::Pi()); + registry.get(HIST("global-matches/TrackDCA"))->Fill(std::sqrt(fgValuesMCH.dcaX * fgValuesMCH.dcaX + fgValuesMCH.dcaY * fgValuesMCH.dcaY)); + + registry.get(HIST("global-matches/TrackP_glo"))->Fill(fgValuesGlobal.p); + registry.get(HIST("global-matches/TrackPt_glo"))->Fill(fgValuesGlobal.pT); + registry.get(HIST("global-matches/TrackEta_glo"))->Fill(fgValuesGlobal.eta); + registry.get(HIST("global-matches/TrackPhi_glo"))->Fill(fgValuesGlobal.phi * 180.0 / TMath::Pi()); + registry.get(HIST("global-matches/TrackDCA_glo"))->Fill(std::sqrt(fgValuesGlobal.dcaX * fgValuesGlobal.dcaX + fgValuesGlobal.dcaY * fgValuesGlobal.dcaY)); + } + if (IsGoodGlobalMatching(fgValuesMFT, 1.E10, configMFTs.fTrackNClustMftLow, fMatchingChi2MftMchUp)) { + registry.get(HIST("global-matches/TrackChi2_MFT"))->Fill(fgValuesMFT.chi2); + } + if (IsGoodGlobalMatching(fgValuesMFT, configMFTs.fTrackChi2MftUp, 0, fMatchingChi2MftMchUp)) { + registry.get(HIST("global-matches/TrackNclusters_MFT"))->Fill(fgValuesMFT.nClusters); + } + if (IsGoodGlobalMatching(fgValuesMFT, configMFTs.fTrackChi2MftUp, configMFTs.fTrackNClustMftLow, 1.E10)) { + registry.get(HIST("global-matches/MatchChi2"))->Fill(fgValuesMFT.chi2matching); + } + } + } + } + + template + void FillTrackResidualHistograms(VarVector const& fgVectorsMCH, VarVector const& fgVectorsMFT, int quadrant, bool same, bool mixed) + { + std::vector> xPos; + std::vector> yPos; + std::vector> thetax; + std::vector> thetay; + for (int zi = 0; zi < int(zRefPlane.size()); zi++) { + xPos.emplace_back(std::array{fgVectorsMCH[zi].x, fgVectorsMFT[zi].x}); + yPos.emplace_back(std::array{fgVectorsMCH[zi].y, fgVectorsMFT[zi].y}); + thetax.emplace_back(std::array{ + std::atan2(fgVectorsMCH[zi].px, -1.0 * fgVectorsMCH[zi].pz) * 180 / TMath::Pi(), + std::atan2(fgVectorsMFT[zi].px, -1.0 * fgVectorsMFT[zi].pz) * 180 / TMath::Pi()}); + thetay.emplace_back(std::array{ + std::atan2(fgVectorsMCH[zi].py, -1.0 * fgVectorsMCH[zi].pz) * 180 / TMath::Pi(), + std::atan2(fgVectorsMFT[zi].py, -1.0 * fgVectorsMFT[zi].pz) * 180 / TMath::Pi()}); + } + + for (int i = 0; i < int(zRefPlane.size()); i++) { + if (same) { + std::get>(trackResidualsHistos[i][quadrant]["dx_vs_x"])->Fill(std::fabs(xPos[i][1]), xPos[i][0] - xPos[i][1]); + std::get>(trackResidualsHistos[i][quadrant]["dx_vs_y"])->Fill(std::fabs(yPos[i][1]), xPos[i][0] - xPos[i][1]); + std::get>(trackResidualsHistos[i][quadrant]["dy_vs_x"])->Fill(std::fabs(xPos[i][1]), yPos[i][0] - yPos[i][1]); + std::get>(trackResidualsHistos[i][quadrant]["dy_vs_y"])->Fill(std::fabs(yPos[i][1]), yPos[i][0] - yPos[i][1]); + + std::get>(trackResidualsHistos[i][quadrant]["dthetax_vs_x"])->Fill(std::fabs(xPos[i][1]), thetax[i][0] - thetax[i][1]); + std::get>(trackResidualsHistos[i][quadrant]["dthetax_vs_y"])->Fill(std::fabs(yPos[i][1]), thetax[i][0] - thetax[i][1]); + std::get>(trackResidualsHistos[i][quadrant]["dthetax_vs_thetax"])->Fill(std::fabs(thetax[i][1]), thetax[i][0] - thetax[i][1]); + std::get>(trackResidualsHistos[i][quadrant]["dthetay_vs_x"])->Fill(std::fabs(xPos[i][1]), thetay[i][0] - thetay[i][1]); + std::get>(trackResidualsHistos[i][quadrant]["dthetay_vs_y"])->Fill(std::fabs(yPos[i][1]), thetay[i][0] - thetay[i][1]); + std::get>(trackResidualsHistos[i][quadrant]["dthetay_vs_thetay"])->Fill(std::fabs(thetay[i][1]), thetay[i][0] - thetay[i][1]); + } + if (mixed) { + std::get>(trackResidualsHistosMixedEvents[i][quadrant]["dx_vs_x"])->Fill(std::fabs(xPos[i][1]), xPos[i][0] - xPos[i][1]); + std::get>(trackResidualsHistosMixedEvents[i][quadrant]["dx_vs_y"])->Fill(std::fabs(yPos[i][1]), xPos[i][0] - xPos[i][1]); + std::get>(trackResidualsHistosMixedEvents[i][quadrant]["dy_vs_x"])->Fill(std::fabs(xPos[i][1]), yPos[i][0] - yPos[i][1]); + std::get>(trackResidualsHistosMixedEvents[i][quadrant]["dy_vs_y"])->Fill(std::fabs(yPos[i][1]), yPos[i][0] - yPos[i][1]); + + std::get>(trackResidualsHistosMixedEvents[i][quadrant]["dthetax_vs_x"])->Fill(std::fabs(xPos[i][1]), thetax[i][0] - thetax[i][1]); + std::get>(trackResidualsHistosMixedEvents[i][quadrant]["dthetax_vs_y"])->Fill(std::fabs(yPos[i][1]), thetax[i][0] - thetax[i][1]); + std::get>(trackResidualsHistosMixedEvents[i][quadrant]["dthetax_vs_thetax"])->Fill(std::fabs(thetax[i][1]), thetax[i][0] - thetax[i][1]); + std::get>(trackResidualsHistosMixedEvents[i][quadrant]["dthetay_vs_x"])->Fill(std::fabs(xPos[i][1]), thetay[i][0] - thetay[i][1]); + std::get>(trackResidualsHistosMixedEvents[i][quadrant]["dthetay_vs_y"])->Fill(std::fabs(yPos[i][1]), thetay[i][0] - thetay[i][1]); + std::get>(trackResidualsHistosMixedEvents[i][quadrant]["dthetay_vs_thetay"])->Fill(std::fabs(thetay[i][1]), thetay[i][0] - thetay[i][1]); + } + } + } + + template + void FillDCAHistograms(VarT const& fgValues, VarC const& fgValuesColl, int sign, int quadrant, bool same, bool mixed) + { + if constexpr (static_cast(MuonFillMap)) { + if (same) { + std::get>(dcaHistos[1][quadrant][0]["DCA_x"])->Fill(fgValues.dcaX); + std::get>(dcaHistos[1][quadrant][0]["DCA_y"])->Fill(fgValues.dcaY); + std::get>(dcaHistos[1][quadrant][sign]["DCA_x"])->Fill(fgValues.dcaX); + std::get>(dcaHistos[1][quadrant][sign]["DCA_y"])->Fill(fgValues.dcaY); + } + if (mixed) { + std::get>(dcaHistosMixedEvents[1][quadrant][0]["DCA_x"])->Fill(fgValues.dcaX); + std::get>(dcaHistosMixedEvents[1][quadrant][0]["DCA_y"])->Fill(fgValues.dcaY); + std::get>(dcaHistosMixedEvents[1][quadrant][sign]["DCA_x"])->Fill(fgValues.dcaX); + std::get>(dcaHistosMixedEvents[1][quadrant][sign]["DCA_y"])->Fill(fgValues.dcaY); + } + } + + if constexpr (static_cast(GlobalMuonFillMap)) { + if (same) { + std::get>(dcaHistos[0][quadrant][0]["DCA_x"])->Fill(fgValues.dcaX); + std::get>(dcaHistos[0][quadrant][0]["DCA_y"])->Fill(fgValues.dcaY); + std::get>(dcaHistos[0][quadrant][sign]["DCA_x"])->Fill(fgValues.dcaX); + std::get>(dcaHistos[0][quadrant][sign]["DCA_y"])->Fill(fgValues.dcaY); + std::get>(dcaHistos[0][quadrant][0]["DCA_x_vs_z"])->Fill(fgValuesColl.z, fgValues.dcaX); + std::get>(dcaHistos[0][quadrant][0]["DCA_y_vs_z"])->Fill(fgValuesColl.z, fgValues.dcaY); + } + + if (mixed) { + std::get>(dcaHistosMixedEvents[0][quadrant][0]["DCA_x"])->Fill(fgValues.dcaX); + std::get>(dcaHistosMixedEvents[0][quadrant][0]["DCA_y"])->Fill(fgValues.dcaY); + std::get>(dcaHistosMixedEvents[0][quadrant][sign]["DCA_x"])->Fill(fgValues.dcaX); + std::get>(dcaHistosMixedEvents[0][quadrant][sign]["DCA_y"])->Fill(fgValues.dcaY); + std::get>(dcaHistosMixedEvents[0][quadrant][0]["DCA_x_vs_z"])->Fill(fgValuesColl.z, fgValues.dcaX); + std::get>(dcaHistosMixedEvents[0][quadrant][0]["DCA_y_vs_z"])->Fill(fgValuesColl.z, fgValues.dcaY); + } + } + } + + template + void FillResidualHistograms(Var const& fgValuesProp, Var const& fgValuesMCH, Var const& fgValuesMCHpv, Var const& fgValuesMFT, float xCls, float yCls, int topBottom, int posNeg, int quadrant, int chamber, int deIndex, bool same, bool mixed) + { + std::array xPos{xCls, fgValuesProp.x}; + std::array yPos{yCls, fgValuesProp.y}; + double phiClus = std::atan2(yCls, xCls) * 180 / TMath::Pi(); + + if constexpr (static_cast(MuonFillMap)) { + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, 20., configMuons.fPtMchLow, configMFTs.fEtaMftLow, configMFTs.fEtaMftUp, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + if (same) { + std::get>(mchResidualsHistosPerDE[topBottom][posNeg][chamber]["dx_vs_de"])->Fill(deIndex, xPos[0] - xPos[1]); + std::get>(mchResidualsHistosPerDE[topBottom][posNeg][chamber]["dy_vs_de"])->Fill(deIndex, yPos[0] - yPos[1]); + } + if (mixed) { + std::get>(mchResidualsHistosPerDEMixedEvents[topBottom][posNeg][chamber]["dx_vs_de"])->Fill(deIndex, xPos[0] - xPos[1]); + std::get>(mchResidualsHistosPerDEMixedEvents[topBottom][posNeg][chamber]["dy_vs_de"])->Fill(deIndex, yPos[0] - yPos[1]); + } + } + } + + if constexpr (static_cast(MFTFillMap)) { + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, 20., configMuons.fPtMchLow, configMFTs.fEtaMftLow, configMFTs.fEtaMftUp, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + if (IsGoodMFT(fgValuesMFT, configMFTs.fTrackChi2MftUp, configMFTs.fTrackNClustMftLow)) { + if (same) { + std::get>(residualsHistos[quadrant][chamber]["dx_vs_x"])->Fill(std::fabs(xPos[1]), xPos[0] - xPos[1]); + std::get>(residualsHistos[quadrant][chamber]["dx_vs_y"])->Fill(std::fabs(yPos[1]), xPos[0] - xPos[1]); + std::get>(residualsHistos[quadrant][chamber]["dy_vs_x"])->Fill(std::fabs(xPos[1]), yPos[0] - yPos[1]); + std::get>(residualsHistos[quadrant][chamber]["dy_vs_y"])->Fill(std::fabs(yPos[1]), yPos[0] - yPos[1]); + + // residuals vs. DE index + std::get>(residualsHistosPerDE[topBottom][posNeg][chamber]["dx_vs_de"])->Fill(deIndex, xPos[0] - xPos[1]); + std::get>(residualsHistosPerDE[topBottom][posNeg][chamber]["dy_vs_de"])->Fill(deIndex, yPos[0] - yPos[1]); + + // residuals vs. cluster phi + std::get>(residualsHistosPerDE[topBottom][posNeg][chamber]["dx_vs_phi"])->Fill(phiClus, xPos[0] - xPos[1]); + std::get>(residualsHistosPerDE[topBottom][posNeg][chamber]["dy_vs_phi"])->Fill(phiClus, yPos[0] - yPos[1]); + } + if (mixed) { + std::get>(residualsHistosMixedEvents[quadrant][chamber]["dx_vs_x"])->Fill(std::fabs(xPos[1]), xPos[0] - xPos[1]); + std::get>(residualsHistosMixedEvents[quadrant][chamber]["dx_vs_y"])->Fill(std::fabs(yPos[1]), xPos[0] - xPos[1]); + std::get>(residualsHistosMixedEvents[quadrant][chamber]["dy_vs_x"])->Fill(std::fabs(xPos[1]), yPos[0] - yPos[1]); + std::get>(residualsHistosMixedEvents[quadrant][chamber]["dy_vs_y"])->Fill(std::fabs(yPos[1]), yPos[0] - yPos[1]); + + // residuals vs. DE index + std::get>(residualsHistosPerDEMixedEvents[topBottom][posNeg][chamber]["dx_vs_de"])->Fill(deIndex, xPos[0] - xPos[1]); + std::get>(residualsHistosPerDEMixedEvents[topBottom][posNeg][chamber]["dy_vs_de"])->Fill(deIndex, yPos[0] - yPos[1]); + + // residuals vs. cluster phi + std::get>(residualsHistosPerDEMixedEvents[topBottom][posNeg][chamber]["dx_vs_phi"])->Fill(phiClus, xPos[0] - xPos[1]); + std::get>(residualsHistosPerDEMixedEvents[topBottom][posNeg][chamber]["dy_vs_phi"])->Fill(phiClus, yPos[0] - yPos[1]); + } + } + } + } + } + + template + void resetVar(Var& fgValues) + { + fgValues = {}; + } + + void initCCDB(aod::BCsWithTimestamps const& bcs) + { + // Update CCDB informations + if (bcs.size() > 0 && fCurrentRun != bcs.begin().runNumber()) { + // Load magnetic field information from CCDB/local + ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + grpmag = ccdb->getForTimeStamp(configCCDB.grpmagPath, bcs.begin().timestamp()); + if (grpmag != nullptr) { + base::Propagator::initFieldFromGRP(grpmag); + TrackExtrap::setField(); + TrackExtrap::useExtrapV2(); + fieldB = static_cast(TGeoGlobalMagField::Instance()->GetField()); // for MFT + double centerMFT[3] = {0, 0, -61.4}; // or use middle point between Vtx and MFT? + Bz = fieldB->getBz(centerMFT); // Get field at centre of MFT + } else { + LOGF(fatal, "GRP object is not available in CCDB at timestamp=%llu", bcs.begin().timestamp()); + } + + // Load geometry information from CCDB/local + LOGF(info, "Loading reference aligned geometry from CCDB no later than %d", configCCDB.nolaterthan.value); + ccdb->setCreatedNotAfter(configCCDB.nolaterthan); // this timestamp has to be consistent with what has been used in reco + geoRef = ccdb->getForTimeStamp(configCCDB.geoPath, bcs.begin().timestamp()); + ccdb->clearCache(configCCDB.geoPath); + if (geoRef != nullptr) { + transformation = geo::transformationFromTGeoManager(*geoRef); + } else { + LOGF(fatal, "Reference aligned geometry object is not available in CCDB at timestamp=%llu", bcs.begin().timestamp()); + } + for (int i = 0; i < 156; i++) { + int iDEN = GetDetElemId(i); + transformRef[iDEN] = transformation(iDEN); + } + + if (configRealign.fDoRealign) { + LOGF(info, "Loading new aligned geometry from CCDB no later than %d", configCCDB.nolaterthanRealign.value); + ccdb->setCreatedNotAfter(configCCDB.nolaterthanRealign); // make sure this timestamp can be resolved regarding the reference one + geoNew = ccdb->getForTimeStamp(configCCDB.geoPathRealign, bcs.begin().timestamp()); + ccdb->clearCache(configCCDB.geoPathRealign); + if (geoNew != nullptr) { + transformation = geo::transformationFromTGeoManager(*geoNew); + } else { + LOGF(fatal, "New aligned geometry object is not available in CCDB at timestamp=%llu", bcs.begin().timestamp()); + } + for (int i = 0; i < 156; i++) { + int iDEN = GetDetElemId(i); + transformNew[iDEN] = transformation(iDEN); + } + } + + fCurrentRun = bcs.begin().runNumber(); + } + } + + void init(InitContext const&) + { + fCurrentRun = 0; + + // Configuration for CCDB server + ccdb->setURL(configCCDB.ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + // Configuration for track fitter + const auto& trackerParam = TrackerParam::Instance(); + trackFitter.setBendingVertexDispersion(trackerParam.bendingVertexDispersion); + trackFitter.setChamberResolution(configRealign.fChamberResolutionX, configRealign.fChamberResolutionY); + trackFitter.smoothTracks(true); + trackFitter.useChamberResolution(); + mImproveCutChi2 = 2. * configRealign.fSigmaCutImprove * configRealign.fSigmaCutImprove; + + CreateBasicHistograms(); + CreateDetailedHistograms(); + } + + template + void runDCA(TEventMap const& collisions, TMFTTracks const& mfts, TTrack const& muon, mch::Track const& mchrealigned, VarC& fgValuesColl, VarT& fgValuesMCH, VarT& fgValuesMCHpv, VarT& fgValuesMFT) + { + if constexpr (static_cast(MuonFillMap)) { + + // track selection + if (!IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, 30., 4., configMFTs.fEtaMftLow, configMFTs.fEtaMftUp, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + return; + } + + // Loop over collisions + for (auto& [collisionId, fgValuesColltmp] : collisions) { + + bool sameEvent = (fgValuesColltmp.bc == fgValuesColl.bc); + bool mixedEvent = IsMixedEvent(fgValuesColltmp, fgValuesColl); + + if (!sameEvent && !mixedEvent) { + continue; + } + + // Fill propagation of MCH track to DCA + if (configRealign.fDoRealign) { + FillPropagation(mchrealigned, fgValuesColltmp, fgValuesMCH, kToDCA); + } else { + FillPropagation<1>(muon, fgValuesColltmp, VarTrack{}, fgValuesMCH, kToDCA); + } + + double phi = fgValuesMCH.phi * 180 / TMath::Pi(); + int quadrant = GetQuadrantPhi(phi); + int sign = (fgValuesMCH.sign > 0) ? 1 : 2; + + // Fill DCA QA histograms + FillDCAHistograms<1, 0>(fgValuesMCH, fgValuesColltmp, sign, quadrant, sameEvent, mixedEvent); + } + } + + if constexpr (static_cast(GlobalMuonFillMap)) { + auto mftsThisCollision = mfts.sliceBy(mftPerCollision, fgValuesColl.globalIndex); + for (auto const& mft : mftsThisCollision) { + + // Fill MFT track + VarTrack fgValuesMFTtmp; + FillTrack<0>(mft, fgValuesMFTtmp); + + if (fgValuesMFT.trackTime != fgValuesMFTtmp.trackTime) { + continue; // if not time compatible + } + + if (!IsGoodMFT(fgValuesMFTtmp, configMFTs.fTrackChi2MftUp, configMFTs.fTrackNClustMftLow)) { + continue; + } + + int quadrant = GetQuadrantTrack(mft); + if (quadrant < 0) { + continue; + } + + int sign = (fgValuesMFTtmp.sign > 0) ? 1 : 2; + + for (auto& [collisionId, fgValuesColltmp] : collisions) { + + bool sameEvent = (fgValuesColltmp.bc == fgValuesColl.bc); + bool mixedEvent = IsMixedEvent(fgValuesColltmp, fgValuesColl); + + if (!sameEvent && !mixedEvent) { + continue; + } + + // Propagate MFT track to DCA + FillPropagation<0, 1>(mft, fgValuesColltmp, VarTrack{}, fgValuesMFTtmp, kToDCA); + + // Fill DCA QA histograms + FillDCAHistograms<0, 1>(fgValuesMFTtmp, fgValuesColltmp, sign, quadrant, sameEvent, mixedEvent); + } + resetVar(fgValuesMFTtmp); + } + } + } + + template + void runResidual(TEventMap const& collisions, TMuons const& muons, TMFTTracks const& mfts, TMuonCls const& clusters, TMCHTrack const& mchtrack, mch::Track const& mchrealigned, TMFTTrack const& mfttrack, VarC const& fgValuesColl, VarT const& fgValuesMCH, VarT const& fgValuesMCHpv, VarT const& fgValuesMFT) + { + if (!IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, 20., configMuons.fPtMchLow, configMFTs.fEtaMftLow, configMFTs.fEtaMftUp, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + return; + } + + double phi = fgValuesMCH.phi * 180 / TMath::Pi(); + int quadrant = GetQuadrantPhi(phi); + + //// MCH-MFT track residuals + if (mfttrack.has_collision()) { + auto& fgValuesCollMatched = collisions.at(mfttrack.collisionId()); + + // Do extrapolation for muons to all reference planes + vector mchTrackExtrap; + for (double z : zRefPlane) { + VarTrack fgValues; + if (configRealign.fDoRealign) { + FillPropagation(mchrealigned, VarColl{}, fgValues, kToZ, z); + } else { + FillPropagation<1>(mchtrack, VarColl{}, VarTrack{}, fgValues, kToZ, z); + } + mchTrackExtrap.emplace_back(fgValues); + } + + // Loop over MFT tracks + for (auto const& mft : mfts) { + + if (!mft.has_collision()) { + continue; + } + + // Fill MFT track + VarTrack fgValuesMFTtmp; + FillTrack<0>(mft, fgValuesMFTtmp); + + // Track selection + if (!IsGoodMFT(fgValuesMFTtmp, configMFTs.fTrackChi2MftUp, configMFTs.fTrackNClustMftLow)) { + continue; + } + + auto& fgValuesCollMFT = collisions.at(mft.collisionId()); + + bool sameEvent = (fgValuesCollMFT.bc == fgValuesCollMatched.bc); + bool mixedEvent = IsMixedEvent(fgValuesCollMFT, fgValuesColl); + if (!sameEvent && !mixedEvent) { + continue; + } + + // Do extrapolation for MFTs to all reference planes + vector mftTrackExtrap; + for (double z : zRefPlane) { + VarTrack fgValues; + FillPropagation<0, 1>(mft, fgValuesCollMFT, mchTrackExtrap[1], fgValues, kToZ, z); + mftTrackExtrap.emplace_back(fgValues); + } + + //// Fill QA histograms for alignment checks + FillTrackResidualHistograms(mchTrackExtrap, mftTrackExtrap, quadrant, sameEvent, mixedEvent); + + resetVar(fgValuesMFTtmp); + } + } + + //// Track-Cluster residuals + for (auto const& muon : muons) { + if (static_cast(muon.trackType()) <= 2) { + continue; + } + if (!muon.has_collision()) { + continue; + } + auto& fgValuesCollMCH = collisions.at(muon.collisionId()); + + bool sameEvent = (fgValuesCollMCH.bc == fgValuesColl.bc); + bool mixedEvent = IsMixedEvent(fgValuesCollMCH, fgValuesColl); + if (!sameEvent && !mixedEvent) { + continue; + } + + //// Fill MCH clusters: do re-alignment if asked + mch::Track mchrealignedTmp; + VarClusters fgValuesClsTmp; + if (!FillClusters(muon, clusters, fgValuesClsTmp, mchrealignedTmp)) { + continue; // Refit is not valid + } + + // Loop over attached clusters + for (int iCls = 0; iCls < int(fgValuesClsTmp.posClusters.size()); iCls++) { + + double phiCls = std::atan2(fgValuesClsTmp.posClusters[iCls][1], fgValuesClsTmp.posClusters[iCls][0]) * 180 / TMath::Pi(); + int quadrantCls = GetQuadrantPhi(phiCls); + int DEId = fgValuesClsTmp.DEIDs[iCls]; + int chamber = DEId / 100 - 1; + int deIndex = DEId % 100; + + //// MCH residuals + //// Propagate MCH track to given cluster + VarTrack fgValuesMCHprop; + if (configRealign.fDoRealign) { + FillPropagation(mchrealigned, VarColl{}, fgValuesMCHprop, kToZ, fgValuesClsTmp.posClusters[iCls][2]); + } else { + FillPropagation<1>(mchtrack, VarColl{}, VarTrack{}, fgValuesMCHprop, kToZ, fgValuesClsTmp.posClusters[iCls][2]); + } + + //// Fill residual QA histograms + int topBottom = (fgValuesMCH.y >= 0) ? 0 : 1; + int posNeg = (fgValuesMCH.sign >= 0) ? 0 : 1; + FillResidualHistograms<1, 0>(fgValuesMCHprop, fgValuesMCH, fgValuesMCHpv, fgValuesMFT, fgValuesClsTmp.posClusters[iCls][0], fgValuesClsTmp.posClusters[iCls][1], topBottom, posNeg, quadrantCls, chamber, deIndex, sameEvent, mixedEvent); + resetVar(fgValuesMCHprop); + + //// MFT residuals + if (IsGoodMFT(fgValuesMFT, configMFTs.fTrackChi2MftUp, configMFTs.fTrackNClustMftLow)) { + //// Propagate MFT track to given cluster + VarTrack fgValuesMFTprop; + FillPropagation<0, 1>(mfttrack, VarColl{}, fgValuesMCH, fgValuesMFTprop, kToZ, fgValuesClsTmp.posClusters[iCls][2]); + + //// Fill residual QA histograms for MFT + topBottom = (mfttrack.y() >= 0) ? 0 : 1; + posNeg = (fgValuesMCH.sign >= 0) ? 0 : 1; + FillResidualHistograms<0, 1>(fgValuesMFTprop, fgValuesMCH, fgValuesMCHpv, fgValuesMFT, fgValuesClsTmp.posClusters[iCls][0], fgValuesClsTmp.posClusters[iCls][1], topBottom, posNeg, quadrantCls, chamber, deIndex, sameEvent, mixedEvent); + resetVar(fgValuesMFTprop); + } + } + } + } + + template + void runEventSelection(TEvents const& collisions, TBcs const& bcs, TFwdTracks const& muons, TMFTTracks const& mfts, TMap& collisionSel) + { + for (auto const& collision : collisions) { + + uint64_t collisionIndex = collision.globalIndex(); + auto muonsThisCollision = muons.sliceBy(fwdtracksPerCollision, collisionIndex); + auto mftsThisCollision = mfts.sliceBy(mftPerCollision, collisionIndex); + + if (muonsThisCollision.size() < 1 && mftsThisCollision.size() < 1) { + continue; + } + + auto& fgValuesColl = collisionSel[collisionIndex]; + FillCollision(collision, fgValuesColl); + fgValuesColl.bc = bcs.rawIteratorAt(collision.bcId()).globalBC(); + fgValuesColl.multMFT = mftsThisCollision.size(); + } + } + + template + void runMuonQA(TEventMap const& collisions, TCandidateMap& matchingCandidates, TFwdTracks const& muons, TMFTTracks const& mfts, TMuonCls const& clusters) + { + //// First loop over all muon tracks + for (auto const& muon : muons) { + + //// Get collision information if associated + VarColl fgValuesColl; + if (muon.has_collision()) { + fgValuesColl = collisions.at(muon.collisionId()); + } else { + continue; + } + + if (static_cast(muon.trackType()) <= 2) { // MFT-MCH-MID(0) or MFT-MCH(2) + + registry.get(HIST("global-muons/nTracksPerType"))->Fill(static_cast(muon.trackType())); + + // auto mfttrack = muon.template matchMFTTrack_as(); // unused parameter? + auto mchtrack = muon.template matchMCHTrack_as(); + + // Fill global matching candidates: global muons per MCH track + FillMatchingCandidates(muon, mchtrack, matchingCandidates); + + } else { // MCH-MID(3) or MCH(4) + + // Fill MCH tracks + FillTrack<1>(muon, fgValuesMCH); + + // Propagate MCH to PV + FillPropagation<1>(muon, fgValuesColl, fgValuesMCH, fgValuesMCHpv); // copied in a separate variable + + //// Fill MCH clusters: re-align clusters if required + mch::Track mchrealigned; + VarClusters fgValuesCls; + if (!FillClusters(muon, clusters, fgValuesCls, mchrealigned)) { + continue; // if refit was not passed + } + + //// Update MCH tracks kinematics if using realigned muons + if (configRealign.fDoRealign) { + + // Update track info + FillTrack(mchrealigned, fgValuesMCH); + + // Update propagate of MCH to PV + FillPropagation(mchrealigned, fgValuesColl, fgValuesMCHpv); + + // Update pDCA and Rabs values + FillPropagation(mchrealigned, fgValuesColl, fgValuesMCH, kToAbsEnd); + FillPropagation(mchrealigned, fgValuesColl, fgValuesMCH, kToDCA); + } + + //// Fill muon QA histograms + FillMuonHistograms<1, 0, 0>(fgValuesMCH, fgValuesMCHpv, fgValuesMFT, VarTrack{}, nullptr); + + //// Fill muon DCA QA checks + if (configQAs.fEnableQADCA) { + runDCA<1, 0>(collisions, mfts, muon, mchrealigned, fgValuesColl, fgValuesMCH, fgValuesMCHpv, fgValuesMFT); + } + } + + resetVar(fgValuesMFT); + resetVar(fgValuesMCH); + resetVar(fgValuesMCHpv); + } + + //// Second loop over global muon tracks + for (auto& [mchIndex, globalMuonsVector] : matchingCandidates) { + + //// sort matching candidates in ascending order based on the matching chi2 + auto compareChi2 = [&muons](uint64_t trackIndex1, uint64_t trackIndex2) -> bool { + auto const& track1 = muons.rawIteratorAt(trackIndex1); + auto const& track2 = muons.rawIteratorAt(trackIndex2); + + return (track1.chi2MatchMCHMFT() < track2.chi2MatchMCHMFT()); + }; + std::sort(globalMuonsVector.begin(), globalMuonsVector.end(), compareChi2); + + //// Get tracks + auto muontrack = muons.rawIteratorAt(globalMuonsVector[0]); + auto mchtrack = muontrack.template matchMCHTrack_as(); + auto mfttrack = muontrack.template matchMFTTrack_as(); + + //// Fill matching chi2 + FillMatching(muontrack, fgValuesMCH, fgValuesMFT); + + //// Fill global informations + registry.get(HIST("global-muons/NCandidates"))->Fill(int(globalMuonsVector.size())); + for (size_t candidateIndex = 0; candidateIndex < globalMuonsVector.size(); candidateIndex++) { + auto const& muon = muons.rawIteratorAt(globalMuonsVector[candidateIndex]); + registry.get(HIST("global-muons/MatchChi2"))->Fill(muon.chi2MatchMCHMFT(), candidateIndex); + } + + //// Fill collision information if avalaible + auto& fgValuesCollGlo = collisions.at(muontrack.collisionId()); + VarColl fgValuesCollMCH; // in principal should be the same as global muon + if (mchtrack.has_collision()) { + fgValuesCollMCH = collisions.at(mchtrack.collisionId()); + } + + //// Fill MCH and MFT tracks: basic info copied from input tables + FillTrack<1>(mchtrack, fgValuesMCH); + FillTrack<0>(mfttrack, fgValuesMFT); + FillTrack<1>(muontrack, fgValuesGlobal); + + //// Propagate MCH to PV + FillPropagation<1>(mchtrack, fgValuesCollMCH, VarTrack{}, fgValuesMCHpv); // saved in separate variable fgValuesMCHpv + + //// Fill MCH clusters: re-align clusters if required + mch::Track mchrealigned; + VarClusters fgValuesCls; + if (!FillClusters(mchtrack, clusters, fgValuesCls, mchrealigned)) { + continue; // if refit was not passed + } + + //// Update MCH tracks kinematics if using realigned muons + if (configRealign.fDoRealign) { + // Update track info + FillTrack(mchrealigned, fgValuesMCH); + + // Update propagation of MCH to PV + FillPropagation(mchrealigned, fgValuesCollMCH, fgValuesMCHpv); + + // Update pDCA and Rabs values + FillPropagation(mchrealigned, fgValuesCollMCH, fgValuesMCH, kToAbsEnd); + FillPropagation(mchrealigned, fgValuesCollMCH, fgValuesMCH, kToDCA); + } + + //// Fill global muon candidates info + for (int i = 0; i < int(globalMuonsVector.size()); i++) { + VarTrack fgValuesTmp; + auto muonCandidate = muons.rawIteratorAt(globalMuonsVector[i]); + FillTrack<0>(muonCandidate, fgValuesTmp); + fgValuesCandidates.emplace_back(fgValuesTmp); + } + + //// Fill global muons QA : fill global matching QA if required + if (configQAs.fEnableQAMatching) { + + // Propagate global muon tracks to DCA: treat it as MFT using p from MCH? + FillPropagation<0, 1>(muontrack, fgValuesCollGlo, fgValuesMCH, fgValuesGlobal, kToDCA); + + // Fill bc difference of matched MCH and MFT + if (muontrack.has_collision() && mfttrack.has_collision()) { + fgValuesMCH.bc = collisions.at(muontrack.collisionId()).bc; + fgValuesMFT.bc = collisions.at(mfttrack.collisionId()).bc; + int64_t dbc = fgValuesMCH.bc - fgValuesMFT.bc; + registry.get(HIST("global-matches/BCdifference"))->Fill(dbc); + } + + // Fill QA histograms including global matching + FillMuonHistograms<0, 1, 1>(fgValuesMCH, fgValuesMCHpv, fgValuesMFT, fgValuesGlobal, fgValuesCandidates); + + } else { + // Fill QA histograms + FillMuonHistograms<0, 1, 0>(fgValuesMCH, fgValuesMCHpv, fgValuesMFT, fgValuesGlobal, fgValuesCandidates); + } + + //// Fill residual QA checks if requireds + if (configQAs.fEnableQAResidual) { + runResidual(collisions, muons, mfts, clusters, mchtrack, mchrealigned, mfttrack, fgValuesCollGlo, fgValuesMCH, fgValuesMCHpv, fgValuesMFT); + } + + //// Fill MFT DCA QA checks if required + if (configQAs.fEnableQADCA) { + runDCA<0, 1>(collisions, mfts, nullptr, mch::Track(), fgValuesCollGlo, fgValuesMCH, fgValuesMCHpv, fgValuesMFT); + } + + fgValuesCandidates.clear(); + resetVar(fgValuesMFT); + resetVar(fgValuesMCH); + resetVar(fgValuesMCHpv); + resetVar(fgValuesGlobal); + } + } + + template + void runDimuonQA(TEventMap const& collisions, TCandidateMap const& matchingCandidates, TFwdTracks const& muonTracks, TMuonCls const& clusters) + { + std::vector muonPairs; + std::vector globalMuonPairs; + + GetMuonPairs(muonTracks, matchingCandidates, collisions, muonPairs, globalMuonPairs); + + for (auto& [muon1, muon2] : muonPairs) { + auto collisionIndex1 = muon1.first; + auto const& collision1 = collisions.at(collisionIndex1); + auto collisionIndex2 = muon2.first; + auto const& collision2 = collisions.at(collisionIndex2); + + auto mchIndex1 = muon1.second; + auto mchIndex2 = muon2.second; + auto const& muonTrack1 = muonTracks.rawIteratorAt(mchIndex1); + auto const& muonTrack2 = muonTracks.rawIteratorAt(mchIndex2); + + VarTrack fgValuesMuon1, fgValuesMuonPV1; + VarTrack fgValuesMuon2, fgValuesMuonPV2; + mch::Track mchrealigned1, mchrealigned2; + VarClusters fgValuesCls1, fgValuesCls2; + if (!FillClusters(muonTrack1, clusters, fgValuesCls1, mchrealigned1) || !FillClusters(muonTrack2, clusters, fgValuesCls2, mchrealigned2)) { + continue; // Refit is not valid + } + + if (configRealign.fDoRealign) { + + FillTrack(mchrealigned1, fgValuesMuon1); + FillTrack(mchrealigned2, fgValuesMuon2); + + // Propagate MCH to PV + FillPropagation(mchrealigned1, collision1, fgValuesMuonPV1); + FillPropagation(mchrealigned2, collision2, fgValuesMuonPV2); + + // Recalculate pDCA and Rabs values + FillPropagation(mchrealigned1, collision1, fgValuesMuon1, kToAbsEnd); + FillPropagation(mchrealigned1, collision1, fgValuesMuon1, kToDCA); + FillPropagation(mchrealigned2, collision2, fgValuesMuon2, kToAbsEnd); + FillPropagation(mchrealigned2, collision2, fgValuesMuon2, kToDCA); + } else { + FillTrack<1>(muonTrack1, fgValuesMuon1); + FillTrack<1>(muonTrack2, fgValuesMuon2); + + // Propagate MCH to PV + FillPropagation<1>(muonTrack1, collision1, fgValuesMuon1, fgValuesMuonPV1); + FillPropagation<1>(muonTrack2, collision2, fgValuesMuon1, fgValuesMuonPV2); + } + + int sign1 = muonTrack1.sign(); + int sign2 = muonTrack2.sign(); + + // only consider opposite-sign pairs + if ((sign1 * sign2) >= 0) + continue; + + int Quadrant1 = GetQuadrantPhi(muonTrack1.phi() * 180.0 / TMath::Pi()); + int Quadrant2 = GetQuadrantPhi(muonTrack2.phi() * 180.0 / TMath::Pi()); + int TopBottom1 = (Quadrant1 == 0 || Quadrant1 == 1) ? 0 : 1; + int TopBottom2 = (Quadrant2 == 0 || Quadrant2 == 1) ? 0 : 1; + int LeftRight1 = (Quadrant1 == 0 || Quadrant1 == 2) ? 0 : 1; + int LeftRight2 = (Quadrant2 == 0 || Quadrant2 == 2) ? 0 : 1; + + bool goodMuonTracks = (IsGoodMuon(fgValuesMuon1, fgValuesMuonPV1) && IsGoodMuon(fgValuesMuon2, fgValuesMuonPV2)); + bool goodGlobalMuonTracks = (IsGoodGlobalMuon(fgValuesMuon1, fgValuesMuonPV1) && IsGoodGlobalMuon(fgValuesMuon2, fgValuesMuonPV2)); + + bool sameEvent = (collisionIndex1 == collisionIndex2); + + double mass = GetMuMuInvariantMass(fgValuesMuonPV1, fgValuesMuonPV2); + if (goodMuonTracks) { + if (sameEvent) { + // same-event case + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts"))->Fill(mass); + + if (TopBottom1 == 0 && TopBottom2 == 0) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_TT"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_TT"))->Fill(mass); + } else if ((TopBottom1 == 0 && TopBottom2 == 1) || (TopBottom1 == 1 && TopBottom2 == 0)) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_TB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_TB"))->Fill(mass); + } else if (TopBottom1 == 1 && TopBottom2 == 1) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_BB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_BB"))->Fill(mass); + } + + if (LeftRight1 == 0 && LeftRight2 == 0) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_LL"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_LL"))->Fill(mass); + } else if ((LeftRight1 == 0 && LeftRight2 == 1) || (LeftRight1 == 1 && LeftRight2 == 0)) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_LR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_LR"))->Fill(mass); + } else if (LeftRight1 == 1 && LeftRight2 == 1) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_RR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_RR"))->Fill(mass); + } + } else { + // event-mixing case + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts"))->Fill(mass); + + if (TopBottom1 == 0 && TopBottom2 == 0) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_TT"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_TT"))->Fill(mass); + } else if ((TopBottom1 == 0 && TopBottom2 == 1) || (TopBottom1 == 1 && TopBottom2 == 0)) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_TB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_TB"))->Fill(mass); + } else if (TopBottom1 == 1 && TopBottom2 == 1) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_BB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_BB"))->Fill(mass); + } + + if (LeftRight1 == 0 && LeftRight2 == 0) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_LL"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_LL"))->Fill(mass); + } else if ((LeftRight1 == 0 && LeftRight2 == 1) || (LeftRight1 == 1 && LeftRight2 == 0)) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_LR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_LR"))->Fill(mass); + } else if (LeftRight1 == 1 && LeftRight2 == 1) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_RR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_RR"))->Fill(mass); + } + } + } + + if (goodGlobalMuonTracks) { + if (sameEvent) { + // same-event case + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts"))->Fill(mass); + + if (TopBottom1 == 0 && TopBottom2 == 0) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_TT"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_TT"))->Fill(mass); + } else if ((TopBottom1 == 0 && TopBottom2 == 1) || (TopBottom1 == 1 && TopBottom2 == 0)) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_TB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_TB"))->Fill(mass); + } else if (TopBottom1 == 1 && TopBottom2 == 1) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_BB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_BB"))->Fill(mass); + } + + if (LeftRight1 == 0 && LeftRight2 == 0) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_LL"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_LL"))->Fill(mass); + } else if ((LeftRight1 == 0 && LeftRight2 == 1) || (LeftRight1 == 1 && LeftRight2 == 0)) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_LR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_LR"))->Fill(mass); + } else if (LeftRight1 == 1 && LeftRight2 == 1) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_RR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_RR"))->Fill(mass); + } + } else { + // event-mixing case + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts"))->Fill(mass); + + if (TopBottom1 == 0 && TopBottom2 == 0) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_TT"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_TT"))->Fill(mass); + } else if ((TopBottom1 == 0 && TopBottom2 == 1) || (TopBottom1 == 1 && TopBottom2 == 0)) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_TB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_TB"))->Fill(mass); + } else if (TopBottom1 == 1 && TopBottom2 == 1) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_BB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_BB"))->Fill(mass); + } + + if (LeftRight1 == 0 && LeftRight2 == 0) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_LL"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_LL"))->Fill(mass); + } else if ((LeftRight1 == 0 && LeftRight2 == 1) || (LeftRight1 == 1 && LeftRight2 == 0)) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_LR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_LR"))->Fill(mass); + } else if (LeftRight1 == 1 && LeftRight2 == 1) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_RR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_RR"))->Fill(mass); + } + } + } + } + + for (auto& [muon1, muon2] : globalMuonPairs) { + auto collisionIndex1 = muon1.first; + auto collisionIndex2 = muon2.first; + auto& globalTracksVector1 = muon1.second; + auto& globalTracksVector2 = muon2.second; + + auto const& collision1 = collisions.at(collisionIndex1); + auto const& collision2 = collisions.at(collisionIndex2); + + auto const& muonTrack1 = muonTracks.rawIteratorAt(globalTracksVector1[0]); + auto const& muonTrack2 = muonTracks.rawIteratorAt(globalTracksVector2[0]); + auto const& mftTrack1 = muonTrack1.template matchMFTTrack_as(); + auto const& mftTrack2 = muonTrack2.template matchMFTTrack_as(); + auto const& mchTrack1 = muonTrack1.template matchMCHTrack_as(); + auto const& mchTrack2 = muonTrack2.template matchMCHTrack_as(); + + VarTrack fgValuesMuon1, fgValuesMuonPV1, fgValuesMCH1, fgValuesMCHpv1, fgValuesMFT1, fgValuesMFTpv1; + VarTrack fgValuesMuon2, fgValuesMuonPV2, fgValuesMCH2, fgValuesMCHpv2, fgValuesMFT2, fgValuesMFTpv2; + + // Fill MCH and MFT tracks + FillTrack<1>(mchTrack1, fgValuesMCH1); + FillTrack<0>(mftTrack1, fgValuesMFT1); + FillTrack<1>(muonTrack1, fgValuesMuon1); + FillTrack<1>(mchTrack2, fgValuesMCH2); + FillTrack<0>(mftTrack2, fgValuesMFT2); + FillTrack<1>(muonTrack2, fgValuesMuon2); + + //// Fill matching chi2 + FillMatching(muonTrack1, fgValuesMCH1, fgValuesMFT1); + FillMatching(muonTrack2, fgValuesMCH2, fgValuesMFT2); + + mch::Track mchrealigned1, mchrealigned2; + VarClusters fgValuesCls1, fgValuesCls2; + if (!FillClusters(muonTrack1, clusters, fgValuesCls1, mchrealigned1) || !FillClusters(muonTrack2, clusters, fgValuesCls2, mchrealigned2)) { + continue; // Refit is not valid + } + + if (configRealign.fDoRealign) { + + FillTrack(mchrealigned1, fgValuesMCH1); + FillTrack(mchrealigned2, fgValuesMCH2); + + // Propagate MCH to PV + FillPropagation(mchrealigned1, collision1, fgValuesMCHpv1); + FillPropagation(mchrealigned2, collision2, fgValuesMCHpv2); + + // Recalculate pDCA and Rabs values + FillPropagation(mchrealigned1, collision1, fgValuesMCH1, kToAbsEnd); + FillPropagation(mchrealigned1, collision1, fgValuesMCH1, kToDCA); + FillPropagation(mchrealigned2, collision2, fgValuesMCH2, kToAbsEnd); + FillPropagation(mchrealigned2, collision2, fgValuesMCH2, kToDCA); + + } else { + FillTrack<1>(mchTrack1, fgValuesMCH1); + FillTrack<1>(mchTrack2, fgValuesMCH2); + + // Propagate MCH to PV + FillPropagation<1>(mchTrack1, collision1, fgValuesMCH1, fgValuesMCHpv1); + FillPropagation<1>(mchTrack2, collision2, fgValuesMCH2, fgValuesMCHpv2); + } + + // Propagate global muon tracks to PV + FillPropagation<0>(muonTrack1, collision1, fgValuesMCH1, fgValuesMuonPV1); + FillPropagation<0>(muonTrack2, collision2, fgValuesMCH2, fgValuesMuonPV2); + + // Propagate MFT tracks to PV + FillPropagation<0, 1>(mftTrack1, collision1, fgValuesMCH1, fgValuesMFTpv1); + FillPropagation<0, 1>(mftTrack2, collision2, fgValuesMCH2, fgValuesMFTpv2); + + int sign1 = mchTrack1.sign(); + int sign2 = mchTrack2.sign(); + + // only consider opposite-sign pairs + if ((sign1 * sign2) >= 0) + continue; + + // indexes indicating whether the positive and negative tracks come from the top or bottom halves of MFT + int posTopBottom = (sign1 > 0) ? ((muonTrack1.y() >= 0) ? 0 : 1) : ((muonTrack2.y() >= 0) ? 0 : 1); + int negTopBottom = (sign1 < 0) ? ((muonTrack1.y() >= 0) ? 0 : 1) : ((muonTrack2.y() >= 0) ? 0 : 1); + + bool goodGlobalMuonTracks = (IsGoodGlobalMuon(fgValuesMCH1, fgValuesMCHpv1) && IsGoodGlobalMuon(fgValuesMCH2, fgValuesMCHpv2)); + bool goodGlobalMuonMatches = (IsGoodGlobalMatching(fgValuesMFT1) && IsGoodGlobalMatching(fgValuesMFT2)); + + bool sameEvent = (collisionIndex1 == collisionIndex2); + + if (goodGlobalMuonTracks && goodGlobalMuonMatches) { + + double massMCH = GetMuMuInvariantMass(fgValuesMCHpv1, fgValuesMCHpv2); + double mass = GetMuMuInvariantMass(fgValuesMuonPV1, fgValuesMuonPV2); + double massScaled = GetMuMuInvariantMass(fgValuesMFTpv1, fgValuesMFTpv2); + + if (sameEvent) { + // same-event case + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMatchesCuts"))->Fill(massMCH); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMatchesCuts"))->Fill(massMCH); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_GlobalMuonKine_GlobalMatchesCuts"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_GlobalMuonKine_GlobalMatchesCuts"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_ScaledMftKine_GlobalMatchesCuts"))->Fill(massScaled); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_ScaledMftKine_GlobalMatchesCuts"))->Fill(massScaled); + + if (posTopBottom == 0 && negTopBottom == 0) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_ScaledMftKine_GlobalMatchesCuts_TT"))->Fill(massScaled); + } else if (posTopBottom == 0 && negTopBottom == 1) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_ScaledMftKine_GlobalMatchesCuts_TB"))->Fill(massScaled); + } else if (posTopBottom == 1 && negTopBottom == 0) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_ScaledMftKine_GlobalMatchesCuts_BT"))->Fill(massScaled); + } else if (posTopBottom == 1 && negTopBottom == 1) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_ScaledMftKine_GlobalMatchesCuts_BB"))->Fill(massScaled); + } + + // mass correlation + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_vs_GlobalMuonKine"))->Fill(mass, massMCH); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_ScaledMftKine_vs_GlobalMuonKine"))->Fill(mass, massScaled); + } else { + // event-mixing case + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMatchesCuts"))->Fill(massMCH); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMatchesCuts"))->Fill(massMCH); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_GlobalMuonKine_GlobalMatchesCuts"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_GlobalMuonKine_GlobalMatchesCuts"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_ScaledMftKine_GlobalMatchesCuts"))->Fill(massScaled); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_ScaledMftKine_GlobalMatchesCuts"))->Fill(massScaled); + + if (posTopBottom == 0 && negTopBottom == 0) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_ScaledMftKine_GlobalMatchesCuts_TT"))->Fill(massScaled); + } else if (posTopBottom == 0 && negTopBottom == 1) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_ScaledMftKine_GlobalMatchesCuts_TB"))->Fill(massScaled); + } else if (posTopBottom == 1 && negTopBottom == 0) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_ScaledMftKine_GlobalMatchesCuts_BT"))->Fill(massScaled); + } else if (posTopBottom == 1 && negTopBottom == 1) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_ScaledMftKine_GlobalMatchesCuts_BB"))->Fill(massScaled); + } + } + } + + // plots for sub-leading matches are only filled in the same-event case + if (sameEvent) { + if (globalTracksVector1.size() > 1) { + VarTrack fgValuesMuonb1, fgValuesMuonbpv1, fgValuesMFTb1; + auto const& muonTrack1b = muonTracks.rawIteratorAt(globalTracksVector1[1]); + FillTrack<1>(muonTrack1b, fgValuesMuonb1); + FillPropagation<0>(muonTrack1b, collision1, fgValuesMCH1, fgValuesMuonbpv1); + + goodGlobalMuonTracks = (IsGoodGlobalMuon(fgValuesMCH1, fgValuesMCHpv1) && IsGoodGlobalMuon(fgValuesMCH2, fgValuesMCHpv2)); + goodGlobalMuonMatches = (IsGoodGlobalMatching(fgValuesMFTb1) && IsGoodGlobalMatching(fgValuesMFT2)); + double mass = GetMuMuInvariantMass(fgValuesMuonbpv1, fgValuesMuonPV2); + if (goodGlobalMuonTracks && goodGlobalMuonMatches) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_GlobalMuonKine_GlobalMatchesCuts_subleading_leading"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_GlobalMuonKine_GlobalMatchesCuts_subleading_leading"))->Fill(mass); + } + } + + if (globalTracksVector2.size() > 1) { + VarTrack fgValuesMuonb2, fgValuesMuonbpv2, fgValuesMFTb2; + auto const& muonTrack2b = muonTracks.rawIteratorAt(globalTracksVector2[1]); + FillTrack<1>(muonTrack2b, fgValuesMuonb2); + FillPropagation<0>(muonTrack2b, collision2, fgValuesMCH2, fgValuesMuonbpv2); + + goodGlobalMuonTracks = (IsGoodGlobalMuon(fgValuesMCH1, fgValuesMCHpv1) && IsGoodGlobalMuon(fgValuesMCH2, fgValuesMCHpv2)); + goodGlobalMuonMatches = (IsGoodGlobalMatching(fgValuesMFTb2) && IsGoodGlobalMatching(fgValuesMFT1)); + double mass = GetMuMuInvariantMass(fgValuesMuonbpv2, fgValuesMuonPV1); + if (goodGlobalMuonTracks && goodGlobalMuonMatches) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_GlobalMuonKine_GlobalMatchesCuts_leading_subleading"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_GlobalMuonKine_GlobalMatchesCuts_leading_subleading"))->Fill(mass); + } + } + + if (globalTracksVector1.size() > 1 && globalTracksVector2.size() > 1) { + VarTrack fgValuesMuonb1, fgValuesMuonbpv1, fgValuesMFTb1; + VarTrack fgValuesMuonb2, fgValuesMuonbpv2, fgValuesMFTb2; + auto const& muonTrack1b = muonTracks.rawIteratorAt(globalTracksVector1[1]); + auto const& muonTrack2b = muonTracks.rawIteratorAt(globalTracksVector2[1]); + + FillTrack<1>(muonTrack1b, fgValuesMuonb1); + FillPropagation<0>(muonTrack1b, collision1, fgValuesMCH1, fgValuesMuonbpv1); + + FillTrack<1>(muonTrack2b, fgValuesMuonb2); + FillPropagation<0>(muonTrack2b, collision2, fgValuesMCH2, fgValuesMuonbpv2); + + goodGlobalMuonTracks = (IsGoodGlobalMuon(fgValuesMCH1, fgValuesMCHpv1) && IsGoodGlobalMuon(fgValuesMCH2, fgValuesMCHpv2)); + goodGlobalMuonMatches = (IsGoodGlobalMatching(fgValuesMFTb1) && IsGoodGlobalMatching(fgValuesMFTb2)); + double mass = GetMuMuInvariantMass(fgValuesMuonbpv1, fgValuesMuonbpv2); + double massLeading = GetMuMuInvariantMass(fgValuesMuonPV1, fgValuesMuonPV2); + if (goodGlobalMuonTracks && goodGlobalMuonMatches) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_GlobalMuonKine_GlobalMatchesCuts_subleading_subleading"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_GlobalMuonKine_GlobalMatchesCuts_subleading_subleading"))->Fill(mass); + + // mass correlation + registryDimuon.get(HIST("dimuon/same-event/invariantMass_GlobalMuonKine_subleading_vs_leading"))->Fill(massLeading, mass); + } + } + } + } + } + + void processMuonQa(MyEvents const& collisions, aod::BCsWithTimestamps const& bcs, MyMuonsWithCov const& muontracks, MyMFTs const& mfttracks, aod::FwdTrkCls const& muonclusters) + { + std::map collisionSel; + std::map> matchingCandidates; + + initCCDB(bcs); + + runEventSelection(collisions, bcs, muontracks, mfttracks, collisionSel); + + runMuonQA(collisionSel, matchingCandidates, muontracks, mfttracks, muonclusters); + + if (configQAs.fEnableQADimuon) { + runDimuonQA(collisionSel, matchingCandidates, muontracks, muonclusters); + } + } + PROCESS_SWITCH(muonQa, processMuonQa, "Process to run muon QA", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGCF/EbyEFluctuations/Tasks/CMakeLists.txt b/PWGCF/EbyEFluctuations/Tasks/CMakeLists.txt index 1dd4e544331..ae29c294b09 100644 --- a/PWGCF/EbyEFluctuations/Tasks/CMakeLists.txt +++ b/PWGCF/EbyEFluctuations/Tasks/CMakeLists.txt @@ -34,8 +34,8 @@ o2physics_add_dpl_workflow(antiproton-cumulants-mc PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(identified-meanpt-fluctuations - SOURCES IdentifiedMeanPtFluctuations.cxx +o2physics_add_dpl_workflow(ident-mean-pt-fluct + SOURCES eventMeanPtId.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore COMPONENT_NAME Analysis) diff --git a/PWGCF/EbyEFluctuations/Tasks/IdentifiedMeanPtFluctuations.cxx b/PWGCF/EbyEFluctuations/Tasks/IdentifiedMeanPtFluctuations.cxx deleted file mode 100644 index 2217a2c1f4f..00000000000 --- a/PWGCF/EbyEFluctuations/Tasks/IdentifiedMeanPtFluctuations.cxx +++ /dev/null @@ -1,1173 +0,0 @@ -// 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. - -/// \author Sweta Singh (sweta.singh@cern.ch) - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/Core/trackUtilities.h" -#include "Common/CCDB/EventSelectionParams.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" -#include "CommonConstants/MathConstants.h" -#include "Common/DataModel/FT0Corrected.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/RunningWorkflowInfo.h" -#include "PWGCF/Core/CorrelationContainer.h" -#include "PWGCF/Core/PairCuts.h" -#include "TDatabasePDG.h" -#include -#include "Common/CCDB/TriggerAliases.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace std; - -namespace o2::aod -{ - -using MyCollisions = soa::Join; -using MyTracks = soa::Join; - -using MyMCRecoCollisions = soa::Join; - -using MyMCRecoTracks = soa::Join; - -using MyCollision = MyCollisions::iterator; -using MyTrack = MyTracks::iterator; -} // namespace o2::aod - -double massPi = TDatabasePDG::Instance()->GetParticle(211)->Mass(); -double massKa = TDatabasePDG::Instance()->GetParticle(321)->Mass(); -double massPr = TDatabasePDG::Instance()->GetParticle(2212)->Mass(); - -struct IdentifiedMeanPtFluctuations { - - HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - - Configurable piluprejection{"piluprejection", false, "Pileup rejection"}; - - void init(o2::framework::InitContext&) - { - AxisSpec vtxZAxis = {100, -20, 20, "Z (cm)"}; - AxisSpec dcaAxis = {1002, -5.01, 5.01, "DCA_{xy} (cm)"}; - AxisSpec dcazAxis = {1002, -5.01, 5.01, "DCA_{z} (cm)"}; - AxisSpec ptAxis = {400, 0.0, 4.0, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec pAxis = {400, 0.0, 4.0, "#it{p} (GeV/#it{c})"}; - AxisSpec betaAxis = {200, 0.0, 2.0, "TOF_{#beta} (GeV/#it{c})"}; - AxisSpec dEdxAxis = {2000, 0.0, 200.0, "dE/dx (GeV/#it{c})"}; - AxisSpec etaAxis = {100, -1.5, 1.5, "#eta"}; - AxisSpec nSigmaTPCAxis = {170, -8.5, 8.5, "n#sigma_{TPC}^{proton}"}; - AxisSpec nSigmaTPCAxispid = {170, -8.5, 8.5, "n#sigma_{TPC}"}; - AxisSpec nSigmaTOFAxispid = {170, -8.5, 8.5, "n#sigma_{TOF}"}; - // AxisSpec nChAxis = {2500, -0.5, 2499.5, "nCh"}; - AxisSpec centAxis = {100, 0., 100., "centrality"}; - AxisSpec subAxis = {30, 0., 30., "sample"}; - AxisSpec nchAxis = {4000, 0., 4000., "nch"}; - AxisSpec varAxis1 = {400, 0., 4., "var1"}; - AxisSpec varAxis2 = {400, 0., 4., "var2"}; - AxisSpec Chi2Axis = {100, 0., 100., "Chi2"}; - AxisSpec CrossedrowTPCAxis = {600, 0., 600., "TPC Crossed rows"}; - AxisSpec Counter = {10, 0., 10., "events"}; - - // QA Plots - histos.add("hEventCounter", "event counts", kTH1D, {Counter}); - - auto h = histos.add("tracksel", "tracksel", HistType::kTH1D, {{10, 0.5, 10.5}}); - h->GetXaxis()->SetBinLabel(1, "Tracks read"); - h->GetXaxis()->SetBinLabel(2, "Global track passed"); - h->GetXaxis()->SetBinLabel(3, "DCAxy passed"); - h->GetXaxis()->SetBinLabel(4, "DCAz passed"); - h->GetXaxis()->SetBinLabel(5, "Eta-cut passed"); - h->GetXaxis()->SetBinLabel(6, "pT-cut passed"); - h->GetXaxis()->SetBinLabel(7, "TPC crossed rows passed"); - h->GetXaxis()->SetBinLabel(8, "TPC Chai2cluster passed"); - h->GetXaxis()->SetBinLabel(9, "ITS Chai2cluster passed"); - - histos.add("hEventCounter_recMC", "event counts rec MC", kTH1D, {Counter}); - - auto h_rec = histos.add("tracksel_rec", "tracksel_rec", HistType::kTH1D, {{10, 0.5, 10.5}}); - h_rec->GetXaxis()->SetBinLabel(1, "has_mcCollision() read"); - h_rec->GetXaxis()->SetBinLabel(2, "Vertex Z > 10cm passed"); - h_rec->GetXaxis()->SetBinLabel(3, "sel 8 passed"); - h_rec->GetXaxis()->SetBinLabel(4, "kNoSameBunchPileup passed"); - h_rec->GetXaxis()->SetBinLabel(5, "kNoITSROFrameBorder passed"); - h_rec->GetXaxis()->SetBinLabel(6, "klsGoodZvtxFT0vsPV passed"); - h_rec->GetXaxis()->SetBinLabel(7, "klsVertexITSTPC passed"); - - histos.add("hZvtx_before_sel", "hZvtx_before_sel", kTH1D, {vtxZAxis}); - histos.add("hZvtx_after_sel", "hZvtx_after_sel", kTH1D, {vtxZAxis}); - histos.add("hZvtx_after_sel8", "hZvtx_after_sel8", kTH1D, {vtxZAxis}); - histos.add("hP", "hP", kTH1D, {pAxis}); - histos.add("hEta", ";hEta", kTH1D, {etaAxis}); - histos.add("hPt", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {ptAxis}); - histos.add("hNsigmaTPC", "hNsigmaTPC", kTH2D, - {pAxis, nSigmaTPCAxis}); - histos.add("hDCAxy", "hDCAxy", kTH1D, {dcaAxis}); - histos.add("hDCAz", "hDCAz", kTH1D, {dcazAxis}); - - histos.add("hPtDCAxy", "hPtDCAxy", kTH2D, {ptAxis, dcaAxis}); - histos.add("hPtDCAz", "hPtDCAz", kTH2D, {ptAxis, dcazAxis}); - histos.add("NSigamaTPCpion", "NSigamaTPCpion", kTH2D, {ptAxis, nSigmaTPCAxispid}); - histos.add("NSigamaTPCkaon", "NSigamaTPCkaon", kTH2D, {ptAxis, nSigmaTPCAxispid}); - histos.add("NSigamaTPCproton", "NSigamaTPCproton", kTH2D, {ptAxis, nSigmaTPCAxispid}); - - histos.add("NSigamaTOFpion", "NSigamaTOFpion", kTH2D, {ptAxis, nSigmaTOFAxispid}); - histos.add("NSigamaTOFkaon", "NSigamaTOFkaon", kTH2D, {ptAxis, nSigmaTOFAxispid}); - histos.add("NSigamaTOFproton", "NSigamaTOFproton", kTH2D, {ptAxis, nSigmaTOFAxispid}); - - histos.add("NSigamaTPCpion_rec", "NSigamaTPCpion_rec", kTH2D, {pAxis, nSigmaTPCAxispid}); - histos.add("NSigamaTPCkaon_rec", "NSigamaTPCkaon_rec", kTH2D, {pAxis, nSigmaTPCAxispid}); - histos.add("NSigamaTPCproton_rec", "NSigamaTPCproton_rec", kTH2D, {pAxis, nSigmaTPCAxispid}); - - histos.add("NSigamaTOFpion_rec", "NSigamaTOFpion_rec", kTH2D, {pAxis, nSigmaTOFAxispid}); - histos.add("NSigamaTOFkaon_rec", "NSigamaTOFkaon_rec", kTH2D, {pAxis, nSigmaTOFAxispid}); - histos.add("NSigamaTOFproton_rec", "NSigamaTOFproton_rec", kTH2D, {pAxis, nSigmaTOFAxispid}); - - histos.add("NSigamaTPCTOFpion", "NSigamaTPCTOFpion", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); - histos.add("NSigamaTPCTOFkaon", "NSigamaTPCTOFkaon", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); - histos.add("NSigamaTPCTOFproton", "NSigamaTPCTOFproton", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); - - histos.add("NSigamaTPCTOFpion_rec", "NSigamaTPCTOFpion_rec", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); - histos.add("NSigamaTPCTOFkaon_rec", "NSigamaTPCTOFkaon_rec", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); - histos.add("NSigamaTPCTOFproton_rec", "NSigamaTPCTOFproton_rec", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); - - histos.add("NSigamaTPCpion_rec_bf_sel", "NSigamaTPCpion_rec_bf_sel", kTH2D, {pAxis, nSigmaTPCAxispid}); - histos.add("NSigamaTPCkaon_rec_bf_sel", "NSigamaTPCkaon_rec_bf_sel", kTH2D, {pAxis, nSigmaTPCAxispid}); - histos.add("NSigamaTPCproton_rec_bf_sel", "NSigamaTPCproton_rec_bf_sel", kTH2D, {pAxis, nSigmaTPCAxispid}); - - histos.add("NSigamaTOFpion_rec_bf_sel", "NSigamaTOFpion_rec_bf_sel", kTH2D, {pAxis, nSigmaTOFAxispid}); - histos.add("NSigamaTOFkaon_rec_bf_sel", "NSigamaTOFkaon_rec_bf_sel", kTH2D, {pAxis, nSigmaTOFAxispid}); - histos.add("NSigamaTOFproton_rec_bf_sel", "NSigamaTOFproton_rec_bf_sel", kTH2D, {pAxis, nSigmaTOFAxispid}); - - histos.add("NSigamaTPCTOFpion_rec_bf_sel", "NSigamaTPCTOFpion_rec_bf_sel", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); - histos.add("NSigamaTPCTOFkaon_rec_bf_sel", "NSigamaTPCTOFkaon_rec_bf_sel", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); - histos.add("NSigamaTPCTOFproton_rec_bf_sel", "NSigamaTPCTOFproton_rec_bf_sel", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); - - histos.add("hPtPion", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {ptAxis}); - histos.add("hPtKaon", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {ptAxis}); - histos.add("hPtProton", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {ptAxis}); - - histos.add("hEtaPion", ";hEta", kTH1D, {etaAxis}); - histos.add("hEtaKaon", ";hEta", kTH1D, {etaAxis}); - histos.add("hEtaProton", ";hEta", kTH1D, {etaAxis}); - //=====================rapidity===================================== - histos.add("hyPion", ";hyPion", kTH1D, {etaAxis}); - histos.add("hyKaon", ";hyKaon", kTH1D, {etaAxis}); - histos.add("hyProton", ";hyProton", kTH1D, {etaAxis}); - - histos.add("hPtCh", "hPtCh", kTH2D, {nchAxis, ptAxis}); - histos.add("hPtChPion", "hPtChPion", kTH2D, {nchAxis, ptAxis}); - histos.add("hPtChKaon", "hPtChKaon", kTH2D, {nchAxis, ptAxis}); - histos.add("hPtChProton", "hPtChProton", kTH2D, {nchAxis, ptAxis}); - - histos.add("hPtCent", "hPtCent", kTH2D, {centAxis, ptAxis}); - histos.add("hPtCentPion", "hPtCentPion", kTH2D, {centAxis, ptAxis}); - histos.add("hPtCentKaon", "hPtCentKaon", kTH2D, {centAxis, ptAxis}); - histos.add("hPtCentProton", "hPtCentProton", kTH2D, {centAxis, ptAxis}); - - histos.add("hMeanPtCh", "hMeanPtCh", kTH2D, {nchAxis, ptAxis}); - histos.add("hCent", "hCent", kTH2D, {nchAxis, centAxis}); - - histos.add("hVar1", "hVar1", kTH2D, {subAxis, centAxis}); - histos.add("hVar2", "hVar2", kTH2D, {subAxis, centAxis}); - histos.add("hVar2meanpt", "hVar2meanpt", kTH2D, {centAxis, varAxis2}); - histos.add("hVar", "hVar", kTH2D, {subAxis, centAxis}); - histos.add("hVarc", "hVarc", kTH2D, {subAxis, centAxis}); - - histos.add("hVar1pi", "hVar1pi", kTH2D, {subAxis, centAxis}); - histos.add("hVar2pi", "hVar2pi", kTH2D, {subAxis, centAxis}); - histos.add("hVarpi", "hVarpi", kTH2D, {subAxis, centAxis}); - histos.add("hVar2meanptpi", "hVar2meanptpi", kTH2D, {centAxis, varAxis2}); - - histos.add("hVar1k", "hVar1k", kTH2D, {subAxis, centAxis}); - histos.add("hVar2k", "hVar2k", kTH2D, {subAxis, centAxis}); - histos.add("hVark", "hVark", kTH2D, {subAxis, centAxis}); - histos.add("hVar2meanptk", "hVar2meanptk", kTH2D, {centAxis, varAxis2}); - - histos.add("hVar1p", "hVar1p", kTH2D, {subAxis, centAxis}); - histos.add("hVar2p", "hVar2p", kTH2D, {subAxis, centAxis}); - histos.add("hVarp", "hVarp", kTH2D, {subAxis, centAxis}); - histos.add("hVar2meanptp", "hVar2meanptp", kTH2D, {centAxis, varAxis2}); - - //--------------------------------nch---------------------------------- - histos.add("hVar1x", "hVar1x", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2x", "hVar2x", kTH2D, {subAxis, nchAxis}); - histos.add("hVarx", "hVarx", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptx", "hVar2meanptx", kTH2D, {nchAxis, varAxis2}); - - histos.add("hVar1pix", "hVar1pix", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2pix", "hVar2pix", kTH2D, {subAxis, nchAxis}); - histos.add("hVarpix", "hVarpix", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptpix", "hVar2meanptpix", kTH2D, {nchAxis, varAxis2}); - - histos.add("hVar1kx", "hVar1kx", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2kx", "hVar2kx", kTH2D, {subAxis, nchAxis}); - histos.add("hVarkx", "hVarkx", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptkx", "hVar2meanptkx", kTH2D, {nchAxis, varAxis2}); - - histos.add("hVar1px", "hVar1px", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2px", "hVar2px", kTH2D, {subAxis, nchAxis}); - histos.add("hVarpx", "hVarpx", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptpx", "hVar2meanptpx", kTH2D, {nchAxis, varAxis2}); - - histos.add("ht", "ht", kTH1D, {centAxis}); - - histos.add("hCentrality", "hCentrality", kTH1D, {centAxis}); - - histos.add("hPEta", "hPEta", kTH2D, {pAxis, etaAxis}); - histos.add("hPtEta", "hPtEta", kTH2D, {ptAxis, etaAxis}); - histos.add("hPy", "hPy", kTH2D, {pAxis, etaAxis}); - histos.add("hPty", "hPty", kTH2D, {ptAxis, etaAxis}); - - histos.add("hPtyPion", "hPtyPion", kTH2D, {ptAxis, etaAxis}); - histos.add("hPtyKaon", "hPtyKaon", kTH2D, {ptAxis, etaAxis}); - histos.add("hPtyProton", "hPtyProton", kTH2D, {ptAxis, etaAxis}); - - histos.add("hPtyPion_rec", "hPtyPion_rec", kTH2D, {ptAxis, etaAxis}); - histos.add("hPtyKaon_rec", "hPtyKaon_rec", kTH2D, {ptAxis, etaAxis}); - histos.add("hPtyProton_rec", "hPtyProton_rec", kTH2D, {ptAxis, etaAxis}); - - histos.add("hPyPion_rec", "hPyPion_rec", kTH2D, {pAxis, etaAxis}); - histos.add("hPyKaon_rec", "hPyKaon_rec", kTH2D, {pAxis, etaAxis}); - histos.add("hPyProton_rec", "hPyProton_rec", kTH2D, {pAxis, etaAxis}); - - histos.add("hTOFbeta", "hTOFbeta", kTH2D, {pAxis, betaAxis}); - histos.add("hdEdx", "hdEdx", kTH2D, {pAxis, dEdxAxis}); - - histos.add("hTOFbeta_afterselection", "hTOFbeta_afterselection", kTH2D, {pAxis, betaAxis}); - histos.add("hdEdx_afterselection", "hdEdx_afterselection", kTH2D, {pAxis, dEdxAxis}); - - histos.add("hTOFbeta_afterselection1", "hTOFbeta_afterselection1", kTH2D, {pAxis, betaAxis}); - histos.add("hdEdx_afterselection1", "hdEdx_afterselection1", kTH2D, {pAxis, dEdxAxis}); - - histos.add("hTOFbeta_afterselection_rec_afterpidcut", "hTOFbeta_afterselection_rec_afterpidcut", kTH2D, {pAxis, betaAxis}); - histos.add("hdEdx_afterselection_rec_afterpidcut", "hdEdx_afterselection_rec_afterpidcut", kTH2D, {pAxis, dEdxAxis}); - - histos.add("hTOFbeta_afterselection_rec_beforepidcut", "hTOFbeta_afterselection_rec_beforepidcut", kTH2D, {pAxis, betaAxis}); - histos.add("hdEdx_afterselection_rec_beforepidcut", "hdEdx_afterselection_rec_beforepidcut", kTH2D, {pAxis, dEdxAxis}); - - histos.add("hdEdx_rec_bf_anycut", "hdEdx_rec_bf_anycut", kTH2D, {pAxis, dEdxAxis}); - - histos.add("hTPCchi2perCluster_before", "TPC #Chi^{2}/Cluster", kTH1D, {Chi2Axis}); - histos.add("hITSchi2perCluster_before", "ITS #Chi^{2}/Cluster", kTH1D, {Chi2Axis}); - histos.add("hTPCCrossedrows_before", "Crossed TPC rows", kTH1D, {CrossedrowTPCAxis}); - - histos.add("hTPCchi2perCluster_after", "TPC #Chi^{2}/Cluster", kTH1D, {Chi2Axis}); - histos.add("hITSchi2perCluster_after", "ITS #Chi^{2}/Cluster", kTH1D, {Chi2Axis}); - histos.add("hTPCCrossedrows_after", "Crossed TPC rows", kTH1D, {CrossedrowTPCAxis}); - - //--------------------------------nch---------------------------------- - histos.add("hVar1x_rec", "hVar1x_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2x_rec", "hVar2x_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVarx_rec", "hVarx_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptx_rec", "hVar2meanptx_rec", kTH2D, {nchAxis, varAxis2}); - - histos.add("hVar1pix_rec", "hVar1pix_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2pix_rec", "hVar2pix_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVarpix_rec", "hVarpix_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptpix_rec", "hVar2meanptpix_rec", kTH2D, {nchAxis, varAxis2}); - - histos.add("hVar1kx_rec", "hVar1kx_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2kx_rec", "hVar2kx_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVarkx_rec", "hVarkx_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptkx_rec", "hVar2meanptkx_rec", kTH2D, {nchAxis, varAxis2}); - - histos.add("hVar1px_rec", "hVar1px_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2px_rec", "hVar2px_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVarpx_rec", "hVarpx_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptpx_rec", "hVar2meanptpx_rec", kTH2D, {nchAxis, varAxis2}); - - //=======================MC histograms Generated ================================================ - histos.add("ptHistogram_allcharge_gen", "ptHistogram_allcharge_gen", kTH1D, {ptAxis}); - histos.add("ptHistogramPion", "ptHistogramPion", kTH1D, {ptAxis}); - histos.add("ptHistogramKaon", "ptHistogramKaon", kTH1D, {ptAxis}); - histos.add("ptHistogramProton", "ptHistogramProton", kTH1D, {ptAxis}); - - histos.add("hMC_Pt", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {ptAxis}); - histos.add("MC_hZvtx_after_sel", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {vtxZAxis}); - - histos.add("hTOFbeta_gen_pion", "hTOFbeta_gen_pion", kTH2D, {pAxis, betaAxis}); - histos.add("hdEdx_gen_pion", "hdEdx_gen_pion", kTH2D, {pAxis, dEdxAxis}); - - histos.add("hVar1x_gen", "hVar1x_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2x_gen", "hVar2x_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVarx_gen", "hVarx_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptx_gen", "hVar2meanptx_gen", kTH2D, {nchAxis, varAxis2}); - - histos.add("hVar1pix_gen", "hVar1pix_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2pix_gen", "hVar2pix_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVarpix_gen", "hVarpix_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptpix_gen", "hVar2meanptpix_gen", kTH2D, {nchAxis, varAxis2}); - - histos.add("hVar1kx_gen", "hVar1kx_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2kx_gen", "hVar2kx_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVarkx_gen", "hVarkx_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptkx_gen", "hVar2meanptkx_gen", kTH2D, {nchAxis, varAxis2}); - - histos.add("hVar1px_gen", "hVar1px_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2px_gen", "hVar2px_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVarpx_gen", "hVarpx_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptpx_gen", "hVar2meanptpx_gen", kTH2D, {nchAxis, varAxis2}); - - //========================MC Histograms Reconstructed================================================= - - histos.add("hZvtx_after_sel_rec", "hZvtx_after_sel_rec", kTH1D, {vtxZAxis}); - histos.add("hZvtx_after_sel8_rec", "hZvtx_after_sel8_rec", kTH1D, {vtxZAxis}); - - histos.add("ptHistogram_allcharge_rec", "ptHistogram_allcharge_rec", kTH1D, {ptAxis}); - histos.add("ptHistogramPionrec", "ptHistogramPionrec", kTH1D, {ptAxis}); - histos.add("ptHistogramKaonrec", "ptHistogramKaonrec", kTH1D, {ptAxis}); - histos.add("ptHistogramProtonrec", "ptHistogramProtonrec", kTH1D, {ptAxis}); - - histos.add("ptHistogramPionrec_purity", "ptHistogramPionrec_purity", kTH1D, {ptAxis}); - histos.add("ptHistogramKaonrec_purity", "ptHistogramKaonrec_purity", kTH1D, {ptAxis}); - histos.add("ptHistogramProtonrec_purity", "ptHistogramProtonrec_purity", kTH1D, {ptAxis}); - - histos.add("ptHistogramPionrec_pdg", "ptHistogramPionrec_pdg", kTH1D, {ptAxis}); - histos.add("ptHistogramKaonrec_pdg", "ptHistogramKaonrec_pdg", kTH1D, {ptAxis}); - histos.add("ptHistogramProtonrec_pdg", "ptHistogramProtonrec_pdg", kTH1D, {ptAxis}); - - histos.add("Histogram_mass2_p_rec_beforesel", "Histogram_mass2_p_rec_beforesel", kTH1D, {ptAxis}); - histos.add("Histogram_mass2_p_rec_aftersel", "Histogram_mass2_p_rec_aftersel", kTH1D, {ptAxis}); - } - - //++++++++++++++++++++++++Monte Carlo Reconstructed +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - template - void SelTPConlyPions(const T& track1) - { - (track1.hasTPC() && (track1.p() < 0.7) && abs(track1.tpcNSigmaPi()) < 3. && (std::abs(track1.tpcNSigmaKa()) > 3.0 && std::abs(track1.tpcNSigmaPr()) > 3.0)); - } - template - void SelTPConlyKaons(const T& track1) - { - (track1.hasTPC() && (track1.p() < 0.7) && abs(track1.tpcNSigmaKa()) < 3.0 && (std::abs(track1.tpcNSigmaPi()) > 3.0 && std::abs(track1.tpcNSigmaPr()) > 3.0)); - } - template - void SelTPConlyProtons(const T& track1) - { - (track1.hasTPC() && (track1.p() < 1.1) && abs(track1.tpcNSigmaPr()) < 3.0 && (std::abs(track1.tpcNSigmaPi()) > 3.0 && std::abs(track1.tpcNSigmaKa()) > 3.0)); - } - - template - void SelTPCTOFPions(const T& track1) - { - (track1.hasTPC() && track1.hasTOF() && track1.p() >= 0.7 && TMath::Hypot((track1.tofNSigmaPr() + 2) / 3.0, (track1.tpcNSigmaPr() - 6) / 4.0) > 3. && TMath::Hypot((track1.tofNSigmaKa() + 2) / 3.0, (track1.tpcNSigmaKa() - 6) / 4.0) > 3. && TMath::Hypot((track1.tofNSigmaPi() + 2) / 3.0, (track1.tpcNSigmaPi() - 6) / 4.0) < 3.); - } - - template - void SelTPCTOFKaons(const T& track1) - { - (track1.hasTPC() && track1.hasTOF() && track1.p() >= 0.7 && TMath::Hypot((track1.tofNSigmaPr() + 2) / 3.0, (track1.tpcNSigmaPr() - 6) / 4.0) > 3. && TMath::Hypot((track1.tofNSigmaPi() + 2) / 3.0, (track1.tpcNSigmaPi() - 6) / 4.0) > 3. && TMath::Hypot((track1.tofNSigmaKa() + 2) / 3.0, (track1.tpcNSigmaKa() - 6) / 4.0) < 3.); - } - - template - void SelTPCTOFProtons(const T& track1) - { - if (track1.hasTPC() && track1.hasTOF() && track1.p() >= 1.1 && TMath::Hypot((track1.tofNSigmaPi() + 2) / 3.0, (track1.tpcNSigmaPi() - 6) / 4.0) > 3. && TMath::Hypot((track1.tofNSigmaKa() + 2) / 3.0, (track1.tpcNSigmaKa() - 6) / 4.0) > 3. && TMath::Hypot((track1.tofNSigmaPr() + 2) / 3.0, (track1.tpcNSigmaPr() - 6) / 4.0) < 3.) { - }; - } - - void processMCReco(aod::MyMCRecoCollisions::iterator const& mccoll, aod::MyMCRecoTracks const& mcrectrack, aod::McParticles const& /*mcParticles*/) - { - if (!mccoll.has_mcCollision()) { - return; - } - histos.fill(HIST("tracksel_rec"), 1); - - if (fabs(mccoll.posZ()) > 10.f) { - return; - } - histos.fill(HIST("hZvtx_after_sel_rec"), mccoll.posZ()); - - histos.fill(HIST("tracksel_rec"), 2); - - if (!mccoll.sel8()) { - return; - } - - histos.fill(HIST("hZvtx_after_sel8_rec"), mccoll.posZ()); - - histos.fill(HIST("tracksel_rec"), 3); - - if (!mccoll.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { - return; - } - histos.fill(HIST("tracksel_rec"), 4); - - if (!mccoll.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { - return; - } - histos.fill(HIST("tracksel_rec"), 5); - - if (!mccoll.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { - return; - } - histos.fill(HIST("tracksel_rec"), 6); - - if (!mccoll.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { - return; - } - histos.fill(HIST("tracksel_rec"), 7); - - double nCh_rec = 0.; - double nChpi_rec = 0.; - double nChk_rec = 0.; - double nChp_rec = 0.; - - double Q1_rec = 0, Q2_rec = 0; - double Q1pi_rec = 0, Q2pi_rec = 0; - double Q1k_rec = 0, Q2k_rec = 0; - double Q1p_rec = 0, Q2p_rec = 0; - double var1_rec = 0, var2_rec = 0; - double var1pi_rec = 0, var2pi_rec = 0; - double var1k_rec = 0, var2k_rec = 0; - double var1p_rec = 0, var2p_rec = 0; - - int sample_rec = histos.get(HIST("hZvtx_after_sel8_rec"))->GetEntries(); - sample_rec = sample_rec % 30; - - for (auto track1 : mcrectrack) { - if (!(track1.has_collision())) - continue; - if (!(track1.has_mcParticle())) - continue; - if (!(track1.mcParticle().isPhysicalPrimary())) - continue; - if (!track1.isGlobalTrack()) - continue; - - if (!(track1.pt() > 0.15) || !(track1.pt() < 2.0)) - continue; // pt = 0.15 - if (!(track1.eta() > -0.8) || !(track1.eta() < 0.8)) - continue; // eta cut - - nCh_rec += 1.; - - Q1_rec += track1.pt(); - Q2_rec += (track1.pt() * track1.pt()); - - histos.fill(HIST("ptHistogram_allcharge_rec"), track1.pt()); - - if (track1.hasTPC()) - histos.fill(HIST("hdEdx_rec_bf_anycut"), track1.p(), track1.tpcSignal()); - - //======================================================================== - - if (abs(track1.mcParticle().pdgCode()) == 211) { - - histos.fill(HIST("ptHistogramPionrec_pdg"), track1.pt()); - } - if (abs(track1.mcParticle().pdgCode()) == 321) { - - histos.fill(HIST("ptHistogramKaonrec_pdg"), track1.pt()); - } - if (abs(track1.mcParticle().pdgCode()) == 2212) { - - histos.fill(HIST("ptHistogramProtonrec_pdg"), track1.pt()); - } - - //+++++++++ electron rejection ++++++++++++++++++++++++++++++++// - - if (abs(track1.tpcNSigmaEl()) < 3.0 && abs(track1.tpcNSigmaPi()) > 3. && abs(track1.tpcNSigmaKa()) > 3. && abs(track1.tpcNSigmaPr()) > 3.) - continue; - - //============Reconstructed MC=================PIONS selection==============================================================// - - if (track1.hasTPC()) - histos.fill(HIST("hdEdx_afterselection_rec_beforepidcut"), track1.p(), track1.tpcSignal()); - if (track1.hasTOF()) - histos.fill(HIST("hTOFbeta_afterselection_rec_beforepidcut"), track1.p(), track1.beta()); - - if (track1.hasTPC() && track1.hasTOF()) { - - histos.fill(HIST("NSigamaTPCpion_rec_bf_sel"), track1.p(), track1.tpcNSigmaPi()); - histos.fill(HIST("NSigamaTOFpion_rec_bf_sel"), track1.p(), track1.tofNSigmaPi()); - histos.fill(HIST("NSigamaTPCTOFpion_rec_bf_sel"), track1.tpcNSigmaPi(), track1.tofNSigmaPi()); - } - - SelTPConlyPions(track1); // Pion (TPC only) - SelTPCTOFPions(track1); // Pion passes TPC and TOF both! - - { - - histos.fill(HIST("ptHistogramPionrec"), track1.pt()); - - nChpi_rec += 1.; - Q1pi_rec += track1.pt(); - Q2pi_rec += (track1.pt() * track1.pt()); - - histos.fill(HIST("NSigamaTPCpion_rec"), track1.p(), track1.tpcNSigmaPi()); - histos.fill(HIST("NSigamaTOFpion_rec"), track1.p(), track1.tofNSigmaPi()); - histos.fill(HIST("NSigamaTPCTOFpion_rec"), track1.tpcNSigmaPi(), track1.tofNSigmaPi()); - - if (track1.beta() > 1) - continue; - - histos.fill(HIST("hdEdx_afterselection_rec_afterpidcut"), track1.p(), track1.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection_rec_afterpidcut"), track1.p(), track1.beta()); - - if (abs(track1.mcParticle().pdgCode()) == 211) { - histos.fill(HIST("ptHistogramPionrec_purity"), track1.pt()); - } - - if (abs(track1.rapidity(massPi)) < 0.5) { - - histos.fill(HIST("hPyPion_rec"), track1.p(), track1.rapidity(massPi)); - histos.fill(HIST("hPtyPion_rec"), track1.pt(), track1.rapidity(massPi)); - } - } - - //============Reconstructed MC=================KAONS selection==============================================================// - - if (track1.hasTPC()) - histos.fill(HIST("hdEdx_afterselection_rec_beforepidcut"), track1.p(), track1.tpcSignal()); - if (track1.hasTOF()) - histos.fill(HIST("hTOFbeta_afterselection_rec_beforepidcut"), track1.p(), track1.beta()); - - if (track1.hasTPC() && track1.hasTOF()) { - - histos.fill(HIST("NSigamaTPCkaon_rec_bf_sel"), track1.p(), track1.tpcNSigmaKa()); - histos.fill(HIST("NSigamaTOFkaon_rec_bf_sel"), track1.p(), track1.tofNSigmaKa()); - histos.fill(HIST("NSigamaTPCTOFkaon_rec_bf_sel"), track1.tpcNSigmaKa(), track1.tofNSigmaKa()); - } - - SelTPConlyKaons(track1); // Kaons passes from TPC only! - SelTPCTOFKaons(track1); // Kaons passes from TPC and TOF both! - - { - - histos.fill(HIST("ptHistogramKaonrec"), track1.pt()); - - nChk_rec += 1.; - Q1k_rec += track1.pt(); - Q2k_rec += (track1.pt() * track1.pt()); - - histos.fill(HIST("NSigamaTPCkaon_rec"), track1.p(), track1.tpcNSigmaKa()); - histos.fill(HIST("NSigamaTOFkaon_rec"), track1.p(), track1.tofNSigmaKa()); - histos.fill(HIST("NSigamaTPCTOFkaon_rec"), track1.tpcNSigmaKa(), track1.tofNSigmaKa()); - - if (track1.beta() > 1) - continue; - - histos.fill(HIST("hdEdx_afterselection_rec_afterpidcut"), track1.p(), track1.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection_rec_afterpidcut"), track1.p(), track1.beta()); - - if (abs(track1.mcParticle().pdgCode()) == 321) { - histos.fill(HIST("ptHistogramKaonrec_purity"), track1.pt()); - } - - if (abs(track1.rapidity(massKa)) < 0.5) { - - histos.fill(HIST("hPyKaon_rec"), track1.p(), track1.rapidity(massKa)); - histos.fill(HIST("hPtyKaon_rec"), track1.pt(), track1.rapidity(massKa)); - } - } - - //============Reconstructed MC=================PROTONS selection==============================================================// - - if (track1.hasTPC()) - histos.fill(HIST("hdEdx_afterselection_rec_beforepidcut"), track1.p(), track1.tpcSignal()); - if (track1.hasTOF()) - histos.fill(HIST("hTOFbeta_afterselection_rec_beforepidcut"), track1.p(), track1.beta()); - - if (track1.hasTPC() && track1.hasTOF()) { - - histos.fill(HIST("NSigamaTPCproton_rec_bf_sel"), track1.p(), track1.tpcNSigmaPr()); - histos.fill(HIST("NSigamaTOFproton_rec_bf_sel"), track1.p(), track1.tofNSigmaPr()); - histos.fill(HIST("NSigamaTPCTOFproton_rec_bf_sel"), track1.tpcNSigmaPr(), track1.tofNSigmaPr()); - } - - SelTPConlyProtons(track1); // Protons passes from TPC only! - SelTPCTOFProtons(track1); // Protons passes from TPC and TOF both! - - { - - histos.fill(HIST("ptHistogramProtonrec"), track1.pt()); - - nChp_rec += 1.; - Q1p_rec += track1.pt(); - Q2p_rec += (track1.pt() * track1.pt()); - - histos.fill(HIST("NSigamaTPCproton_rec"), track1.p(), track1.tpcNSigmaPr()); - histos.fill(HIST("NSigamaTOFproton_rec"), track1.p(), track1.tofNSigmaPr()); - histos.fill(HIST("NSigamaTPCTOFproton_rec"), track1.tpcNSigmaPr(), track1.tofNSigmaPr()); - - if (track1.beta() > 1) - continue; - - histos.fill(HIST("hdEdx_afterselection_rec_afterpidcut"), track1.p(), track1.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection_rec_afterpidcut"), track1.p(), track1.beta()); - - if (abs(track1.mcParticle().pdgCode()) == 2212) { - histos.fill(HIST("ptHistogramProtonrec_purity"), track1.pt()); - } - - if (abs(track1.rapidity(massPr)) < 0.5) { - - histos.fill(HIST("hPyProton_rec"), track1.p(), track1.rapidity(massPr)); - histos.fill(HIST("hPtyProton_rec"), track1.pt(), track1.rapidity(massPr)); - } - } - - //============================================================================ - - } // track loop ends - - if (nCh_rec < 2) - return; - - //------------------ all charges------------------------------------- - var1_rec = (Q1_rec * Q1_rec - Q2_rec) / (nCh_rec * (nCh_rec - 1)); - var2_rec = (Q1_rec / nCh_rec); - - //---------------------- pions ---------------------------------------- - - if (nChpi_rec > 2) { - var1pi_rec = (Q1pi_rec * Q1pi_rec - Q2pi_rec) / (nChpi_rec * (nChpi_rec - 1)); - var2pi_rec = (Q1pi_rec / nChpi_rec); - } - - //----------------------- kaons --------------------------------------- - if (nChk_rec > 2) { - var1k_rec = (Q1k_rec * Q1k_rec - Q2k_rec) / (nChk_rec * (nChk_rec - 1)); - var2k_rec = (Q1k_rec / nChk_rec); - } - - //---------------------------- protons ---------------------------------- - if (nChp_rec > 2) { - var1p_rec = (Q1p_rec * Q1p_rec - Q2p_rec) / (nChp_rec * (nChp_rec - 1)); - var2p_rec = (Q1p_rec / nChp_rec); - } - - //-----------------------nch------------------------------------- - histos.fill(HIST("hVar1x_rec"), sample_rec, nCh_rec, var1_rec); - histos.fill(HIST("hVar2x_rec"), sample_rec, nCh_rec, var2_rec); - histos.fill(HIST("hVarx_rec"), sample_rec, nCh_rec); - histos.fill(HIST("hVar2meanptx_rec"), nCh_rec, var2_rec); - - histos.fill(HIST("hVar1pix_rec"), sample_rec, nCh_rec, var1pi_rec); - histos.fill(HIST("hVar2pix_rec"), sample_rec, nCh_rec, var2pi_rec); - histos.fill(HIST("hVarpix_rec"), sample_rec, nChpi_rec); - histos.fill(HIST("hVar2meanptpix_rec"), nCh_rec, var2pi_rec); - - histos.fill(HIST("hVar1kx_rec"), sample_rec, nCh_rec, var1k_rec); - histos.fill(HIST("hVar2kx_rec"), sample_rec, nCh_rec, var2k_rec); - histos.fill(HIST("hVarkx_rec"), sample_rec, nChk_rec); - histos.fill(HIST("hVar2meanptkx_rec"), nCh_rec, var2k_rec); - - histos.fill(HIST("hVar1px_rec"), sample_rec, nCh_rec, var1p_rec); - histos.fill(HIST("hVar2px_rec"), sample_rec, nCh_rec, var2p_rec); - histos.fill(HIST("hVarpx_rec"), sample_rec, nChp_rec); - histos.fill(HIST("hVar2meanptpx_rec"), nCh_rec, var2p_rec); - - } // ends - - PROCESS_SWITCH(IdentifiedMeanPtFluctuations, processMCReco, "process reconstructed information", true); - - //++++++++++++++++++++++++++++Monte Carlo Generated ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - void processMCGen(aod::McCollision const& mcCollision, aod::McParticles& mcParticles) - - { - - if (fabs(mcCollision.posZ()) > 10.f) { - return; - } - histos.fill(HIST("MC_hZvtx_after_sel"), mcCollision.posZ()); - - double nCh_gen = 0.; - double nChpi_gen = 0.; - double nChk_gen = 0.; - double nChp_gen = 0.; - - double Q1_gen = 0, Q2_gen = 0; - double Q1pi_gen = 0, Q2pi_gen = 0; - double Q1k_gen = 0, Q2k_gen = 0; - double Q1p_gen = 0, Q2p_gen = 0; - - double var1_gen = 0, var2_gen = 0; - double var1pi_gen = 0, var2pi_gen = 0; - double var1k_gen = 0, var2k_gen = 0; - double var1p_gen = 0, var2p_gen = 0; - - int sample_gen = histos.get(HIST("hZvtx_after_sel"))->GetEntries(); - sample_gen = sample_gen % 30; - - for (auto& mcgentrack : mcParticles) - - { - auto pdgcode = std::abs(mcgentrack.pdgCode()); - if (!(mcgentrack.has_mcCollision())) - continue; - if (!(mcgentrack.isPhysicalPrimary())) - continue; - if (!(mcgentrack.pt() > 0.15) || !(mcgentrack.pt() < 2.)) - continue; - if (!(mcgentrack.eta() > -0.8) || !(mcgentrack.eta() < 0.8)) - continue; - - nCh_gen += 1.; - - Q1_gen += mcgentrack.pt(); - Q2_gen += (mcgentrack.pt() * mcgentrack.pt()); - - histos.fill(HIST("ptHistogram_allcharge_gen"), mcgentrack.pt()); - - if (pdgcode == 211) { - - histos.fill(HIST("ptHistogramPion"), mcgentrack.pt()); - - nChpi_gen += 1.; - Q1pi_gen += mcgentrack.pt(); - Q2pi_gen += (mcgentrack.pt() * mcgentrack.pt()); - } - - if (pdgcode == 321) { - - histos.fill(HIST("ptHistogramKaon"), mcgentrack.pt()); - - nChk_gen += 1.; - Q1k_gen += mcgentrack.pt(); - Q2k_gen += (mcgentrack.pt() * mcgentrack.pt()); - } - - if (pdgcode == 2212) { - - histos.fill(HIST("ptHistogramProton"), mcgentrack.pt()); - - nChp_gen += 1.; - Q1p_gen += mcgentrack.pt(); - Q2p_gen += (mcgentrack.pt() * mcgentrack.pt()); - } - - //================================= Pion Generated Calculation ==================================== - - } // track loop ends! - - if (nCh_gen < 2) - return; - - //------------------ all charges------------------------------------- - var1_gen = (Q1_gen * Q1_gen - Q2_gen) / (nCh_gen * (nCh_gen - 1)); - var2_gen = (Q1_gen / nCh_gen); - - //---------------------- pions ---------------------------------------- - - if (nChpi_gen > 2) { - var1pi_gen = (Q1pi_gen * Q1pi_gen - Q2pi_gen) / (nChpi_gen * (nChpi_gen - 1)); - var2pi_gen = (Q1pi_gen / nChpi_gen); - } - - //----------------------- kaons --------------------------------------- - if (nChk_gen > 2) { - var1k_gen = (Q1k_gen * Q1k_gen - Q2k_gen) / (nChk_gen * (nChk_gen - 1)); - var2k_gen = (Q1k_gen / nChk_gen); - } - - //---------------------------- protons ---------------------------------- - if (nChp_gen > 2) { - var1p_gen = (Q1p_gen * Q1p_gen - Q2p_gen) / (nChp_gen * (nChp_gen - 1)); - var2p_gen = (Q1p_gen / nChp_gen); - } - - //-----------------------nch------------------------------------- - histos.fill(HIST("hVar1x_gen"), sample_gen, nCh_gen, var1_gen); - histos.fill(HIST("hVar2x_gen"), sample_gen, nCh_gen, var2_gen); - histos.fill(HIST("hVarx_gen"), sample_gen, nCh_gen); - histos.fill(HIST("hVar2meanptx_gen"), nCh_gen, var2_gen); - - histos.fill(HIST("hVar1pix_gen"), sample_gen, nCh_gen, var1pi_gen); - histos.fill(HIST("hVar2pix_gen"), sample_gen, nCh_gen, var2pi_gen); - histos.fill(HIST("hVarpix_gen"), sample_gen, nChpi_gen); - histos.fill(HIST("hVar2meanptpix_gen"), nCh_gen, var2pi_gen); - - histos.fill(HIST("hVar1kx_gen"), sample_gen, nCh_gen, var1k_gen); - histos.fill(HIST("hVar2kx_gen"), sample_gen, nCh_gen, var2k_gen); - histos.fill(HIST("hVarkx_gen"), sample_gen, nChk_gen); - histos.fill(HIST("hVar2meanptkx_gen"), nCh_gen, var2k_gen); - - histos.fill(HIST("hVar1px_gen"), sample_gen, nCh_gen, var1p_gen); - histos.fill(HIST("hVar2px_gen"), sample_gen, nCh_gen, var2p_gen); - histos.fill(HIST("hVarpx_gen"), sample_gen, nChp_gen); - histos.fill(HIST("hVar2meanptpx_gen"), nCh_gen, var2p_gen); - } - PROCESS_SWITCH(IdentifiedMeanPtFluctuations, processMCGen, "process generated information", true); - - //+++++++++++++++++++++++++++++DATA CALCULATION +++++++++++++++++++++++++++++++++++++++++++++++++++++ - void process(aod::MyCollision const& coll, aod::MyTracks const& inputTracks) - - { - histos.fill(HIST("hEventCounter"), 1.); - - histos.fill(HIST("hZvtx_before_sel"), coll.posZ()); - if (fabs(coll.posZ()) > 10.f) { - return; - } - - histos.fill(HIST("hEventCounter"), 2.); - - histos.fill(HIST("hZvtx_after_sel"), coll.posZ()); - - if (!coll.sel8()) { - return; - } - histos.fill(HIST("hZvtx_after_sel8"), coll.posZ()); - - histos.fill(HIST("hEventCounter"), 3.); - - const auto cent = coll.centFT0C(); - histos.fill(HIST("hCentrality"), cent); - - double nCh = 0.; - double nChpi = 0.; - double nChk = 0.; - double nChp = 0.; - - double Q1 = 0., Q2 = 0.; - double Q1pi = 0., Q2pi = 0.; - double Q1k = 0., Q2k = 0.; - double Q1p = 0., Q2p = 0.; - double var1 = 0., var2 = 0., twopar_allcharge = 0.; - double var1pi = 0., var2pi = 0.; - double var1k = 0., var2k = 0.; - double var1p = 0., var2p = 0.; - // cent = 0; - - // sampling - int sample = histos.get(HIST("hZvtx_after_sel8"))->GetEntries(); - sample = sample % 30; - - // Perfroming the track selection========================================== - for (auto track : inputTracks) { - // Loop over tracks - - // inital tracks - histos.fill(HIST("tracksel"), 1); - - histos.fill(HIST("hTPCchi2perCluster_before"), track.tpcChi2NCl()); - histos.fill(HIST("hITSchi2perCluster_before"), track.itsChi2NCl()); - histos.fill(HIST("hTPCCrossedrows_before"), track.tpcNClsCrossedRows()); - - // tracks passed after GlobalTrackcut - if (!track.isGlobalTrack()) - continue; - histos.fill(HIST("tracksel"), 2); - - // tracks passed after DCAxy - // if (!(fabs(track.dcaXY()) < 0.12)) continue;//global cut already includes - histos.fill(HIST("tracksel"), 3); - - // tracks passed after DCAz - // - histos.fill(HIST("hDCAxy"), track.dcaXY()); - histos.fill(HIST("hDCAz"), track.dcaZ()); - - // if (!(fabs(track.dcaZ()) < 1.)) continue;//global cut already includes (DCAz< 2.0) cm - histos.fill(HIST("tracksel"), 4); - - // tracks passed after Eta-cut - if (!(fabs(track.eta()) < 0.8)) - continue; - histos.fill(HIST("tracksel"), 5); - - // tracks passed after pT-cut - if (!(track.pt() > 0.15 && track.pt() < 2.)) - continue; // pt = 0.15 - histos.fill(HIST("tracksel"), 6); - - // if (track.tpcNClsCrossedRows() < 70.0) continue; - histos.fill(HIST("hTPCCrossedrows_after"), track.tpcNClsCrossedRows()); - histos.fill(HIST("tracksel"), 7); - - // if (track.tpcChi2NCl() > 4.0) continue; - histos.fill(HIST("hTPCchi2perCluster_after"), track.tpcChi2NCl()); - histos.fill(HIST("tracksel"), 8); - - // if (track.itsChi2NCl() > 36.0) continue; - histos.fill(HIST("hITSchi2perCluster_after"), track.itsChi2NCl()); - histos.fill(HIST("tracksel"), 9); - - nCh += 1.; - - Q1 += track.pt(); - Q2 += (track.pt() * track.pt()); - - histos.fill(HIST("hP"), track.p()); - histos.fill(HIST("hPt"), track.pt()); - histos.fill(HIST("hEta"), track.eta()); - histos.fill(HIST("hPtDCAxy"), track.pt(), track.dcaXY()); - histos.fill(HIST("hPtDCAz"), track.pt(), track.dcaZ()); - - histos.fill(HIST("hPtEta"), track.pt(), track.eta()); - histos.fill(HIST("hPEta"), track.p(), track.eta()); - - histos.fill(HIST("hNsigmaTPC"), track.p(), track.tpcNSigmaPr()); - - // only TPC tracks: Pion, Kaon, Proton - if (track.hasTPC() && abs(track.tpcNSigmaPi()) < 2.) - histos.fill(HIST("NSigamaTPCpion"), track.pt(), track.tpcNSigmaPi()); - if (track.hasTPC() && abs(track.tpcNSigmaKa()) < 2.) - histos.fill(HIST("NSigamaTPCkaon"), track.pt(), track.tpcNSigmaKa()); - if (track.hasTPC() && abs(track.tpcNSigmaPr()) < 2.) - histos.fill(HIST("NSigamaTPCproton"), track.pt(), track.tpcNSigmaPr()); - - // only TOF tracks: Pion, Kaon, Proton - if (track.hasTOF() && abs(track.tofNSigmaPi()) < 2.) - histos.fill(HIST("NSigamaTOFpion"), track.pt(), track.tofNSigmaPi()); - if (track.hasTOF() && abs(track.tofNSigmaKa()) < 2.) - histos.fill(HIST("NSigamaTOFkaon"), track.pt(), track.tofNSigmaKa()); - if (track.hasTOF() && abs(track.tofNSigmaPr()) < 2.) - histos.fill(HIST("NSigamaTOFproton"), track.pt(), track.tofNSigmaPr()); - - if (track.hasTPC()) - histos.fill(HIST("hdEdx"), track.p(), track.tpcSignal()); - if (track.hasTOF()) - histos.fill(HIST("hTOFbeta"), track.p(), track.beta()); - - //=============================pion============================================================== - // only TPC+TOF tracks: Pion, Kaon, Proton - if ((track.hasTPC() && abs(track.tpcNSigmaPi()) < 2.) && (track.hasTOF() && abs(track.tofNSigmaPi()) < 2.)) { - histos.fill(HIST("NSigamaTPCTOFpion"), track.tpcNSigmaPi(), track.tofNSigmaPi()); - - histos.fill(HIST("hdEdx_afterselection"), track.p(), track.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection"), track.p(), track.beta()); - } - - // pion-TPC----------------------------------------------------------------------------------- - - if ((track.hasTPC() && abs(track.tpcNSigmaPi()) < 2. && (track.pt() >= 0.15 && track.pt() < 0.65) && (abs(track.rapidity(massPi)) < 0.5) && (std::abs(track.tpcNSigmaEl()) > 1.0 && std::abs(track.tpcNSigmaKa()) > 2.0 && std::abs(track.tpcNSigmaPr()) > 2.0))) { - - histos.fill(HIST("hPtPion"), track.pt()); - histos.fill(HIST("hEtaPion"), track.eta()); - histos.fill(HIST("hyPion"), track.rapidity(massPi)); - histos.fill(HIST("hPtyPion"), track.pt(), track.rapidity(massPi)); - - nChpi += 1.; - Q1pi += track.pt(); - Q2pi += (track.pt() * track.pt()); - - if (track.beta() > 1) - continue; - - histos.fill(HIST("hdEdx_afterselection1"), track.p(), track.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection1"), track.p(), track.beta()); - } - - // pion->(TPC+TOF)------------------------------------------------------------------------------------ - if ((track.pt() >= 0.65 && track.pt() < 2.0) && (abs(track.rapidity(massPi)) < 0.5) && track.hasTPC() && track.hasTOF() && (std::abs(track.tofNSigmaKa()) > 2.0 && std::abs(track.tofNSigmaPr()) > 2.0) && abs(sqrt(track.tpcNSigmaPi()) * (track.tpcNSigmaPi()) + (track.tofNSigmaPi()) * (track.tofNSigmaPi())) < 2.) { - - histos.fill(HIST("hPtPion"), track.pt()); - histos.fill(HIST("hEtaPion"), track.eta()); - histos.fill(HIST("hyPion"), track.rapidity(massPi)); - histos.fill(HIST("hPtyPion"), track.pt(), track.rapidity(massPi)); - - nChpi += 1.; - Q1pi += track.pt(); - Q2pi += (track.pt() * track.pt()); - - if (track.beta() > 1) - continue; - - histos.fill(HIST("hdEdx_afterselection1"), track.p(), track.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection1"), track.p(), track.beta()); - } - - //===========================kaon=============================================================== - - if ((track.hasTPC() && abs(track.tpcNSigmaKa()) < 2.) && (track.hasTOF() && abs(track.tofNSigmaKa()) < 2.)) { - histos.fill(HIST("NSigamaTPCTOFkaon"), track.tpcNSigmaKa(), track.tofNSigmaKa()); - histos.fill(HIST("hdEdx_afterselection"), track.p(), track.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection"), track.p(), track.beta()); - } - - if (track.hasTPC() && abs(track.tpcNSigmaKa()) < 2. && (track.pt() >= 0.15 && track.pt() < 0.65) && (abs(track.rapidity(massKa)) < 0.5) && (std::abs(track.tpcNSigmaEl()) > 1.0 && std::abs(track.tpcNSigmaPi()) > 2.0 && std::abs(track.tpcNSigmaPr()) > 2.0)) { - - histos.fill(HIST("hPtKaon"), track.pt()); - histos.fill(HIST("hEtaKaon"), track.eta()); - histos.fill(HIST("hyKaon"), track.rapidity(massKa)); - histos.fill(HIST("hPtyKaon"), track.pt(), track.rapidity(massKa)); - - nChk += 1.; - Q1k += track.pt(); - Q2k += (track.pt() * track.pt()); - - if (track.beta() > 1) - continue; - - histos.fill(HIST("hdEdx_afterselection1"), track.p(), track.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection1"), track.p(), track.beta()); - } - - if ((track.pt() >= 0.65 && track.pt() < 2.0) && (abs(track.rapidity(massKa)) < 0.5) && track.hasTPC() && track.hasTOF() && (std::abs(track.tofNSigmaPi()) > 2.0 && std::abs(track.tofNSigmaPr()) > 2.0) && (abs(sqrt(track.tpcNSigmaKa()) * (track.tpcNSigmaKa()) + (track.tofNSigmaKa()) * (track.tofNSigmaKa())) < 2.)) { - - histos.fill(HIST("hPtKaon"), track.pt()); - histos.fill(HIST("hEtaKaon"), track.eta()); - histos.fill(HIST("hyKaon"), track.rapidity(massKa)); - histos.fill(HIST("hPtyKaon"), track.pt(), track.rapidity(massKa)); - - nChk += 1.; - Q1k += track.pt(); - Q2k += (track.pt() * track.pt()); - - if (track.beta() > 1) - continue; - - histos.fill(HIST("hdEdx_afterselection1"), track.p(), track.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection1"), track.p(), track.beta()); - } - - //============================proton=========================================================== - - if ((track.hasTPC() && abs(track.tpcNSigmaPr()) < 2.) && (track.hasTOF() && abs(track.tofNSigmaPr()) < 2.)) { - histos.fill(HIST("NSigamaTPCTOFproton"), track.tpcNSigmaPr(), track.tofNSigmaPr()); - - histos.fill(HIST("hdEdx_afterselection"), track.p(), track.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection"), track.p(), track.beta()); - } - - if (track.hasTPC() && abs(track.tpcNSigmaPr()) < 2. && (track.pt() >= 0.4 && track.pt() < 0.85) && (abs(track.rapidity(massPr)) < 0.5) && (std::abs(track.tpcNSigmaEl()) > 1.0 && std::abs(track.tpcNSigmaKa()) > 2.0 && std::abs(track.tpcNSigmaPi()) > 2.0)) { - - histos.fill(HIST("hPtProton"), track.pt()); - histos.fill(HIST("hEtaProton"), track.eta()); - histos.fill(HIST("hyProton"), track.rapidity(massPr)); - histos.fill(HIST("hPtyProton"), track.pt(), track.rapidity(massPr)); - - nChp += 1.; - Q1p += track.pt(); - Q2p += (track.pt() * track.pt()); - - if (track.beta() > 1) - continue; - - histos.fill(HIST("hdEdx_afterselection1"), track.p(), track.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection1"), track.p(), track.beta()); - } - - if ((track.pt() >= 0.85 && track.pt() < 2.0) && (abs(track.rapidity(massPr)) < 0.5) && track.hasTPC() && track.hasTOF() && (std::abs(track.tofNSigmaKa()) > 2.0 && std::abs(track.tofNSigmaPi()) > 2.0) && (abs(sqrt(track.tpcNSigmaPr()) * (track.tpcNSigmaPr()) + (track.tofNSigmaPr()) * (track.tofNSigmaPr())) < 2.)) { - - histos.fill(HIST("hPtProton"), track.pt()); - histos.fill(HIST("hEtaProton"), track.eta()); - histos.fill(HIST("hyProton"), track.rapidity(massPr)); - histos.fill(HIST("hPtyProton"), track.pt(), track.rapidity(massPr)); - - nChp += 1.; - Q1p += track.pt(); - Q2p += (track.pt() * track.pt()); - - if (track.beta() > 1) - continue; - - histos.fill(HIST("hdEdx_afterselection1"), track.p(), track.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection1"), track.p(), track.beta()); - } - - //==================================================================================================== - } - // Track loop ends! - - if (nCh < 2) - return; - - //------------------ all charges------------------------------------- - var1 = (Q1 * Q1 - Q2) / (nCh * (nCh - 1)); - histos.fill(HIST("hVar1"), sample, cent, var1); - var2 = (Q1 / nCh); - histos.fill(HIST("hVar2"), sample, cent, var2); - histos.fill(HIST("hVarc"), sample, cent); - histos.fill(HIST("hVar2meanpt"), cent, var2); - - twopar_allcharge = (var1 - var2); - histos.fill(HIST("hVar"), nCh, twopar_allcharge); - - //---------------------- pions ---------------------------------------- - - if (nChpi > 2) { - var1pi = (Q1pi * Q1pi - Q2pi) / (nChpi * (nChpi - 1)); - var2pi = (Q1pi / nChpi); - } - - //----------------------- kaons --------------------------------------- - if (nChk > 2) { - var1k = (Q1k * Q1k - Q2k) / (nChk * (nChk - 1)); - var2k = (Q1k / nChk); - } - - //---------------------------- protons ---------------------------------- - if (nChp > 2) { - var1p = (Q1p * Q1p - Q2p) / (nChp * (nChp - 1)); - var2p = (Q1p / nChp); - } - - //========================centrality========================================== - - histos.fill(HIST("hVar1pi"), sample, cent, var1pi); - histos.fill(HIST("hVar2pi"), sample, cent, var2pi); - histos.fill(HIST("hVar2meanptpi"), cent, var2pi); - - histos.fill(HIST("hVar1k"), sample, cent, var1k); - histos.fill(HIST("hVar2k"), sample, cent, var2k); - histos.fill(HIST("hVar2meanptk"), cent, var2k); - - histos.fill(HIST("hVar1p"), sample, cent, var1p); - histos.fill(HIST("hVar2p"), sample, cent, var2p); - histos.fill(HIST("hVar2meanptp"), cent, var2p); - - //-----------------------nch------------------------------------- - histos.fill(HIST("hVar1x"), sample, nCh, var1); - histos.fill(HIST("hVar2x"), sample, nCh, var2); - histos.fill(HIST("hVarx"), sample, nCh); - histos.fill(HIST("hVar2meanptx"), nCh, var2); - - histos.fill(HIST("hVar1pix"), sample, nCh, var1pi); - histos.fill(HIST("hVar2pix"), sample, nCh, var2pi); - histos.fill(HIST("hVarpix"), sample, nChpi); - histos.fill(HIST("hVar2meanptpix"), nCh, var2pi); - - histos.fill(HIST("hVar1kx"), sample, nCh, var1k); - histos.fill(HIST("hVar2kx"), sample, nCh, var2k); - histos.fill(HIST("hVarkx"), sample, nChk); - histos.fill(HIST("hVar2meanptkx"), nCh, var2k); - - histos.fill(HIST("hVar1px"), sample, nCh, var1p); - histos.fill(HIST("hVar2px"), sample, nCh, var2p); - histos.fill(HIST("hVarpx"), sample, nChp); - histos.fill(HIST("hVar2meanptpx"), nCh, var2p); - - } // event loop ends! - - PROCESS_SWITCH(IdentifiedMeanPtFluctuations, process, "process real data information", true); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; - return workflow; -} diff --git a/PWGCF/EbyEFluctuations/Tasks/eventMeanPtId.cxx b/PWGCF/EbyEFluctuations/Tasks/eventMeanPtId.cxx new file mode 100644 index 00000000000..e0ead922240 --- /dev/null +++ b/PWGCF/EbyEFluctuations/Tasks/eventMeanPtId.cxx @@ -0,0 +1,1272 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for +// 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. +// +/// \file eventMeanPtId.cxx +/// \brief Analysis task to study Mean pT Fluctuations using two particle correlator using Cumulant Method +/// \author Sweta Singh (sweta.singh@cern.ch) + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/Core/trackUtilities.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/Centrality.h" +#include "CommonConstants/MathConstants.h" +#include "Common/DataModel/FT0Corrected.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "PWGCF/Core/CorrelationContainer.h" +#include "PWGCF/Core/PairCuts.h" +#include +#include "Common/CCDB/TriggerAliases.h" +#include "CCDB/BasicCCDBManager.h" +#include "Framework/O2DatabasePDGPlugin.h" +// #include "Framework/Constants.h" +#include +#include +#include +#include + +#include "CommonConstants/PhysicsConstants.h" +double massPi = o2::constants::physics::MassPionCharged; +double massKa = o2::constants::physics::MassKaonCharged; +double massPr = o2::constants::physics::MassProton; + +using namespace o2::constants::physics; +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace std; +using o2::constants::physics::Pdg; + +namespace o2::aod +{ +using MyCollisions = soa::Join; +using MyTracks = soa::Join; + +using MyMCRecoCollisions = soa::Join; +using MyMCRecoCollision = MyMCRecoCollisions::iterator; + +using MyMCRecoTracks = soa::Join; +using MyMCRecoTrack = MyMCRecoTracks::iterator; + +using EventCandidatesMC = soa::Join; +using MyCollision = MyCollisions::iterator; +using MyTrack = MyTracks::iterator; +} // namespace o2::aod + +struct EventMeanPtId { + Service ccdb; + Service pdg; + + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + Configurable ptMax{"ptMax", 2.0, "maximum pT"}; + Configurable ptMin{"ptMin", 0.15, "minimum pT"}; + Configurable> ptBins{"ptBins", {0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00, 1.05, 1.10, 1.15, 1.20, 1.25, 1.30, 1.35, 1.40, 1.45, 1.50, 1.55, 1.60, 1.65, 1.70, 1.75, 1.80, 1.85, 1.90, 1.95, 2.00}, "p_{T} bins"}; + Configurable piluprejection{"piluprejection", false, "Pileup rejection"}; + + void init(o2::framework::InitContext&) + { + std::vector ptBinning = {0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4.0}; + // AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec vtxZAxis = {100, -20.0, 20.0, "Z (cm)"}; + AxisSpec dcaAxis = {1002, -5.01, 5.01, "DCA_{xy} (cm)"}; + AxisSpec dcazAxis = {1002, -5.01, 5.01, "DCA_{z} (cm)"}; + AxisSpec ptAxis = {600, 0.0, 6.0, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec pAxis = {400, 0.0, 4.0, "#it{p} (GeV/#it{c})"}; + AxisSpec betaAxis = {200, 0.0, 2.0, "TOF_{#beta} (GeV/#it{c})"}; + AxisSpec dEdxAxis = {2000, 0.0, 200.0, "dE/dx (GeV/#it{c})"}; + AxisSpec etaAxis = {300, -1.5, 1.5, "#eta"}; // 300, -1.5, 1.5 + AxisSpec nSigmaTPCAxis = {170, -8.5, 8.5, "n#sigma_{TPC}^{proton}"}; + AxisSpec nSigmaTPCAxispid = {170, -8.5, 8.5, "n#sigma_{TPC}"}; + AxisSpec nSigmaTOFAxispid = {170, -8.5, 8.5, "n#sigma_{TOF}"}; + AxisSpec centAxis = {100, 0., 100., "centrality"}; + AxisSpec subAxis = {30, 0., 30., "sample"}; + AxisSpec nchAxis = {4000, 0., 4000., "nch"}; + AxisSpec varAxis1 = {400, 0., 4., "var1"}; + AxisSpec varAxis2 = {400, 0., 4., "var2"}; + AxisSpec chi2Axis = {100, 0., 100., "Chi2"}; + AxisSpec crossedRowTpcAxis = {600, 0., 600., "TPC Crossed rows"}; + AxisSpec counter = {10, 0., 10., "events"}; + + // QA Plots + histos.add("hEventcounter", "event counts", kTH1D, {counter}); + auto h = histos.add("tracksel", "tracksel", HistType::kTH1D, {{10, 0.5, 10.5}}); + h->GetXaxis()->SetBinLabel(1, "Tracks read"); + h->GetXaxis()->SetBinLabel(2, "Global track passed"); + h->GetXaxis()->SetBinLabel(3, "DCAxy passed"); + h->GetXaxis()->SetBinLabel(4, "DCAz passed"); + h->GetXaxis()->SetBinLabel(5, "Eta-cut passed"); + h->GetXaxis()->SetBinLabel(6, "pT-cut passed"); + h->GetXaxis()->SetBinLabel(7, "TPC crossed rows passed"); + h->GetXaxis()->SetBinLabel(8, "TPC Chai2cluster passed"); + h->GetXaxis()->SetBinLabel(9, "ITS Chai2cluster passed"); + + histos.add("hEventcounter_recMC", "event counts rec MC", kTH1D, {counter}); + auto hRec = histos.add("trackSelRec", "trackSelRec", HistType::kTH1D, {{10, 0.5, 10.5}}); + hRec->GetXaxis()->SetBinLabel(1, "has_mcCollision() read"); + hRec->GetXaxis()->SetBinLabel(2, "Vertex Z > 10cm passed"); + hRec->GetXaxis()->SetBinLabel(3, "sel 8 passed"); + hRec->GetXaxis()->SetBinLabel(4, "kNoSameBunchPileup passed"); + hRec->GetXaxis()->SetBinLabel(5, "kNoITSROFrameBorder passed"); + hRec->GetXaxis()->SetBinLabel(6, "klsGoodZvtxFT0vsPV passed"); + hRec->GetXaxis()->SetBinLabel(7, "klsVertexITSTPC passed"); + + histos.add("Data/hZvtx_before_sel", "hZvtx_before_sel", kTH1D, {vtxZAxis}); + histos.add("Data/hZvtx_after_sel", "hZvtx_after_sel", kTH1D, {vtxZAxis}); + histos.add("Data/hZvtx_after_sel8", "hZvtx_after_sel8", kTH1D, {vtxZAxis}); + histos.add("Data/hP", "hP", kTH1D, {pAxis}); + histos.add("Data/hEta", ";hEta", kTH1D, {etaAxis}); + histos.add("Data/hPt", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {ptAxis}); + histos.add("Data/hNsigmaTPC", "hNsigmaTPC", kTH2D, {pAxis, nSigmaTPCAxis}); + histos.add("Data/hDCAxy", "hDCAxy", kTH1D, {dcaAxis}); + histos.add("Data/hDCAz", "hDCAz", kTH1D, {dcazAxis}); + histos.add("Data/hPtDCAxy", "hPtDCAxy", kTH2D, {ptAxis, dcaAxis}); + histos.add("Data/hPtDCAz", "hPtDCAz", kTH2D, {ptAxis, dcazAxis}); + histos.add("Data/NSigamaTPCpion", "NSigamaTPCpion", kTH2D, {ptAxis, nSigmaTPCAxispid}); + histos.add("Data/NSigamaTPCkaon", "NSigamaTPCkaon", kTH2D, {ptAxis, nSigmaTPCAxispid}); + histos.add("Data/NSigamaTPCproton", "NSigamaTPCproton", kTH2D, {ptAxis, nSigmaTPCAxispid}); + histos.add("Data/NSigamaTOFpion", "NSigamaTOFpion", kTH2D, {ptAxis, nSigmaTOFAxispid}); + histos.add("Data/NSigamaTOFkaon", "NSigamaTOFkaon", kTH2D, {ptAxis, nSigmaTOFAxispid}); + histos.add("Data/NSigamaTOFproton", "NSigamaTOFproton", kTH2D, {ptAxis, nSigmaTOFAxispid}); + histos.add("Data/NSigamaTPCTOFpion", "NSigamaTPCTOFpion", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); + histos.add("Data/NSigamaTPCTOFkaon", "NSigamaTPCTOFkaon", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); + histos.add("Data/NSigamaTPCTOFproton", "NSigamaTPCTOFproton", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); + histos.add("Data/hPtPion", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {ptAxis}); + histos.add("Data/hPtKaon", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {ptAxis}); + histos.add("Data/hPtProton", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {ptAxis}); + histos.add("Data/hEtaPion", ";hEta", kTH1D, {etaAxis}); + histos.add("Data/hEtaKaon", ";hEta", kTH1D, {etaAxis}); + histos.add("Data/hEtaProton", ";hEta", kTH1D, {etaAxis}); + histos.add("Data/hyPion", ";hyPion", kTH1D, {etaAxis}); + histos.add("Data/hyKaon", ";hyKaon", kTH1D, {etaAxis}); + histos.add("Data/hyProton", ";hyProton", kTH1D, {etaAxis}); + histos.add("Data/hPtCh", "hPtCh", kTH2D, {nchAxis, ptAxis}); + histos.add("Data/hPtChPion", "hPtChPion", kTH2D, {nchAxis, ptAxis}); + histos.add("Data/hPtChKaon", "hPtChKaon", kTH2D, {nchAxis, ptAxis}); + histos.add("Data/hPtChProton", "hPtChProton", kTH2D, {nchAxis, ptAxis}); + histos.add("Data/hPtCent", "hPtCent", kTH2D, {centAxis, ptAxis}); + histos.add("Data/hPtCentPion", "hPtCentPion", kTH2D, {centAxis, ptAxis}); + histos.add("Data/hPtCentKaon", "hPtCentKaon", kTH2D, {centAxis, ptAxis}); + histos.add("Data/hPtCentProton", "hPtCentProton", kTH2D, {centAxis, ptAxis}); + histos.add("Data/hMeanPtCh", "hMeanPtCh", kTH2D, {nchAxis, ptAxis}); + histos.add("Data/hCent", "hCent", kTH2D, {nchAxis, centAxis}); + + histos.add("Data/hVar1", "hVar1", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVar2", "hVar2", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVar2meanpt", "hVar2meanpt", kTH2D, {centAxis, varAxis2}); + histos.add("Data/hVar", "hVar", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVarc", "hVarc", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVar1pi", "hVar1pi", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVar2pi", "hVar2pi", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVarpi", "hVarpi", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVar2meanptpi", "hVar2meanptpi", kTH2D, {centAxis, varAxis2}); + histos.add("Data/hVar1k", "hVar1k", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVar2k", "hVar2k", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVark", "hVark", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVar2meanptk", "hVar2meanptk", kTH2D, {centAxis, varAxis2}); + histos.add("Data/hVar1p", "hVar1p", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVar2p", "hVar2p", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVarp", "hVarp", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVar2meanptp", "hVar2meanptp", kTH2D, {centAxis, varAxis2}); + + histos.add("Data/hnchAll", ";hnchAll", kTH1D, {nchAxis}); + histos.add("Data/hnchAll_bf_cut", ";hnchAll_bf_cut", kTH1D, {nchAxis}); + histos.add("Data/hnch", ";hnch", kTH1D, {nchAxis}); + histos.add("Data/hnchTrue", ";hnchTrue", kTH1D, {nchAxis}); + histos.add("Data/hnchTrue_pt", ";hnchTrue_pt", kTH1D, {nchAxis}); + + histos.add("Data/hVar1x_old", "hVar1x_old", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVar2x_old", "hVar2x_old", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVarx_old", "hVarx_old", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVar1x", "hVar1x", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVar2x", "hVar2x", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVarx", "hVarx", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVar2meanptx", "hVar2meanptx", kTH2D, {nchAxis, varAxis2}); + histos.add("Data/hVar1pix", "hVar1pix", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVar2pix", "hVar2pix", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVarpix", "hVarpix", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVar2meanptpix", "hVar2meanptpix", kTH2D, {nchAxis, varAxis2}); + histos.add("Data/hVar1kx", "hVar1kx", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVar2kx", "hVar2kx", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVarkx", "hVarkx", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVar2meanptkx", "hVar2meanptkx", kTH2D, {nchAxis, varAxis2}); + histos.add("Data/hVar1px", "hVar1px", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVar2px", "hVar2px", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVarpx", "hVarpx", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVar2meanptpx", "hVar2meanptpx", kTH2D, {nchAxis, varAxis2}); + histos.add("Data/ht", "ht", kTH1D, {centAxis}); + histos.add("Data/hCentrality", "hCentrality", kTH1D, {centAxis}); + histos.add("Data/hPEta", "hPEta", kTH2D, {pAxis, etaAxis}); + histos.add("Data/hPtEta", "hPtEta", kTH2D, {ptAxis, etaAxis}); + histos.add("Data/hPy", "hPy", kTH2D, {pAxis, etaAxis}); + histos.add("Data/hPty", "hPty", kTH2D, {ptAxis, etaAxis}); + histos.add("Data/hPtyPion", "hPtyPion", kTH2D, {ptAxis, etaAxis}); + histos.add("Data/hPtyKaon", "hPtyKaon", kTH2D, {ptAxis, etaAxis}); + histos.add("Data/hPtyProton", "hPtyProton", kTH2D, {ptAxis, etaAxis}); + histos.add("Data/hTOFbeta", "hTOFbeta", kTH2D, {pAxis, betaAxis}); + histos.add("Data/hdEdx", "hdEdx", kTH2D, {pAxis, dEdxAxis}); + histos.add("Data/hTOFbeta_afterselection", "hTOFbeta_afterselection", kTH2D, {pAxis, betaAxis}); + histos.add("Data/hdEdx_afterselection", "hdEdx_afterselection", kTH2D, {pAxis, dEdxAxis}); + histos.add("Data/hTOFbeta_afterselection1", "hTOFbeta_afterselection1", kTH2D, {pAxis, betaAxis}); + histos.add("Data/hdEdx_afterselection1", "hdEdx_afterselection1", kTH2D, {pAxis, dEdxAxis}); + histos.add("Data/hTPCchi2perCluster_before", "TPC #Chi^{2}/Cluster", kTH1D, {chi2Axis}); + histos.add("Data/hITSchi2perCluster_before", "ITS #Chi^{2}/Cluster", kTH1D, {chi2Axis}); + histos.add("Data/hTPCCrossedrows_before", "Crossed TPC rows", kTH1D, {crossedRowTpcAxis}); + histos.add("Data/hTPCchi2perCluster_after", "TPC #Chi^{2}/Cluster", kTH1D, {chi2Axis}); + histos.add("Data/hITSchi2perCluster_after", "ITS #Chi^{2}/Cluster", kTH1D, {chi2Axis}); + histos.add("Data/hTPCCrossedrows_after", "Crossed TPC rows", kTH1D, {crossedRowTpcAxis}); + histos.add("Data/hdEdx_rec_bf_anycut", "hdEdx_rec_bf_anycut", kTH2D, {pAxis, dEdxAxis}); + histos.add("Data/hcent_nacc", "hcent_nacc", kTH2D, {centAxis, nchAxis}); + + histos.addClone("Data/", "Rec/"); + // rec histograms + histos.add("NSigamaTPCpion_rec", "NSigamaTPCpion_rec", kTH2D, {pAxis, nSigmaTPCAxispid}); + histos.add("NSigamaTPCkaon_rec", "NSigamaTPCkaon_rec", kTH2D, {pAxis, nSigmaTPCAxispid}); + histos.add("NSigamaTPCproton_rec", "NSigamaTPCproton_rec", kTH2D, {pAxis, nSigmaTPCAxispid}); + histos.add("NSigamaTOFpion_rec", "NSigamaTOFpion_rec", kTH2D, {pAxis, nSigmaTOFAxispid}); + histos.add("NSigamaTOFkaon_rec", "NSigamaTOFkaon_rec", kTH2D, {pAxis, nSigmaTOFAxispid}); + histos.add("NSigamaTOFproton_rec", "NSigamaTOFproton_rec", kTH2D, {pAxis, nSigmaTOFAxispid}); + histos.add("NSigamaTPCTOFpion_rec", "NSigamaTPCTOFpion_rec", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); + histos.add("NSigamaTPCTOFkaon_rec", "NSigamaTPCTOFkaon_rec", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); + histos.add("NSigamaTPCTOFproton_rec", "NSigamaTPCTOFproton_rec", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); + histos.add("NSigamaTPCpion_rec_bf_sel", "NSigamaTPCpion_rec_bf_sel", kTH2D, {pAxis, nSigmaTPCAxispid}); + histos.add("NSigamaTPCkaon_rec_bf_sel", "NSigamaTPCkaon_rec_bf_sel", kTH2D, {pAxis, nSigmaTPCAxispid}); + histos.add("NSigamaTPCproton_rec_bf_sel", "NSigamaTPCproton_rec_bf_sel", kTH2D, {pAxis, nSigmaTPCAxispid}); + histos.add("NSigamaTOFpion_rec_bf_sel", "NSigamaTOFpion_rec_bf_sel", kTH2D, {pAxis, nSigmaTOFAxispid}); + histos.add("NSigamaTOFkaon_rec_bf_sel", "NSigamaTOFkaon_rec_bf_sel", kTH2D, {pAxis, nSigmaTOFAxispid}); + histos.add("NSigamaTOFproton_rec_bf_sel", "NSigamaTOFproton_rec_bf_sel", kTH2D, {pAxis, nSigmaTOFAxispid}); + histos.add("NSigamaTPCTOFpion_rec_bf_sel", "NSigamaTPCTOFpion_rec_bf_sel", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); + histos.add("NSigamaTPCTOFkaon_rec_bf_sel", "NSigamaTPCTOFkaon_rec_bf_sel", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); + histos.add("NSigamaTPCTOFproton_rec_bf_sel", "NSigamaTPCTOFproton_rec_bf_sel", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); + histos.add("hPtyPion_rec", "hPtyPion_rec", kTH2D, {ptAxis, etaAxis}); + histos.add("hPtyKaon_rec", "hPtyKaon_rec", kTH2D, {ptAxis, etaAxis}); + histos.add("hPtyProton_rec", "hPtyProton_rec", kTH2D, {ptAxis, etaAxis}); + histos.add("hPyPion_rec", "hPyPion_rec", kTH2D, {pAxis, etaAxis}); + histos.add("hPyKaon_rec", "hPyKaon_rec", kTH2D, {pAxis, etaAxis}); + histos.add("hPyProton_rec", "hPyProton_rec", kTH2D, {pAxis, etaAxis}); + histos.add("hTOFbeta_afterselection_rec_afterpidcut", "hTOFbeta_afterselection_rec_afterpidcut", kTH2D, {pAxis, betaAxis}); + histos.add("hdEdx_afterselection_rec_afterpidcut", "hdEdx_afterselection_rec_afterpidcut", kTH2D, {pAxis, dEdxAxis}); + histos.add("hTOFbeta_afterselection_rec_beforepidcut", "hTOFbeta_afterselection_rec_beforepidcut", kTH2D, {pAxis, betaAxis}); + histos.add("hdEdx_afterselection_rec_beforepidcut", "hdEdx_afterselection_rec_beforepidcut", kTH2D, {pAxis, dEdxAxis}); + + histos.add("heffVar1x", "heffVar1x", kTH2D, {subAxis, nchAxis}); + histos.add("heffVar2x", "heffVar2x", kTH2D, {subAxis, nchAxis}); + histos.add("heffVarx", "heffVarx", kTH2D, {subAxis, nchAxis}); + histos.add("heffVar2meanptx", "heffVar2meanptx", kTH2D, {nchAxis, varAxis2}); + histos.add("hnchRec_all", ";hnchRec_all", kTH1D, {nchAxis}); + histos.add("hnchRec", ";hnchRec", kTH1D, {nchAxis}); + histos.add("hnchRec_true", ";hnchRec_true", kTH1D, {nchAxis}); + histos.add("hVar1x_rec_old", "hVar1x_rec_old", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2x_rec_old", "hVar2x_rec_old", kTH2D, {subAxis, nchAxis}); + histos.add("hVarx_rec_old", "hVarx_rec_old", kTH2D, {subAxis, nchAxis}); + histos.add("hVar1x_rec", "hVar1x_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2x_rec", "hVar2x_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVarx_rec", "hVarx_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2meanptx_rec", "hVar2meanptx_rec", kTH2D, {nchAxis, varAxis2}); + histos.add("hVar1pix_rec", "hVar1pix_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2pix_rec", "hVar2pix_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVarpix_rec", "hVarpix_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2meanptpix_rec", "hVar2meanptpix_rec", kTH2D, {nchAxis, varAxis2}); + histos.add("hVar1kx_rec", "hVar1kx_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2kx_rec", "hVar2kx_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVarkx_rec", "hVarkx_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2meanptkx_rec", "hVar2meanptkx_rec", kTH2D, {nchAxis, varAxis2}); + histos.add("hVar1px_rec", "hVar1px_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2px_rec", "hVar2px_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVarpx_rec", "hVarpx_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2meanptpx_rec", "hVar2meanptpx_rec", kTH2D, {nchAxis, varAxis2}); + histos.add("hZvtx_after_sel_rec", "hZvtx_after_sel_rec", kTH1D, {vtxZAxis}); + histos.add("hZvtx_after_sel8_rec", "hZvtx_after_sel8_rec", kTH1D, {vtxZAxis}); + histos.add("etaHistogram_allcharge_rec", "etaHistogram_allcharge_rec", kTH1D, {etaAxis}); + histos.add("ptHistogram_allcharge_bfptcut_rec", "ptHistogram_allcharge_bfptcut_rec", kTH1D, {ptAxis}); + histos.add("ptHistogram_allcharge_rec", "ptHistogram_allcharge_rec", kTH1D, {ptAxis}); + histos.add("ptHistogramPionrec", "ptHistogramPionrec", kTH1D, {ptAxis}); + histos.add("ptHistogramKaonrec", "ptHistogramKaonrec", kTH1D, {ptAxis}); + histos.add("ptHistogramProtonrec", "ptHistogramProtonrec", kTH1D, {ptAxis}); + histos.add("ptHistogramPionrec_purity", "ptHistogramPionrec_purity", kTH1D, {ptAxis}); + histos.add("ptHistogramKaonrec_purity", "ptHistogramKaonrec_purity", kTH1D, {ptAxis}); + histos.add("ptHistogramProtonrec_purity", "ptHistogramProtonrec_purity", kTH1D, {ptAxis}); + histos.add("ptHistogramPionrec_pdg", "ptHistogramPionrec_pdg", kTH1D, {ptAxis}); + histos.add("ptHistogramKaonrec_pdg", "ptHistogramKaonrec_pdg", kTH1D, {ptAxis}); + histos.add("ptHistogramProtonrec_pdg", "ptHistogramProtonrec_pdg", kTH1D, {ptAxis}); + histos.add("Histogram_mass2_p_rec_beforesel", "Histogram_mass2_p_rec_beforesel", kTH1D, {ptAxis}); + histos.add("Histogram_mass2_p_rec_aftersel", "Histogram_mass2_p_rec_aftersel", kTH1D, {ptAxis}); + + //=======================MC histograms Generated ================================================ + histos.add("ptHistogram_allcharge_gen", "ptHistogram_allcharge_gen", kTH1D, {ptAxis}); + histos.add("ptHistogramPion", "ptHistogramPion", kTH1D, {ptAxis}); + histos.add("ptHistogramKaon", "ptHistogramKaon", kTH1D, {ptAxis}); + histos.add("ptHistogramProton", "ptHistogramProton", kTH1D, {ptAxis}); + histos.add("hMC_Pt", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {ptAxis}); + histos.add("MC_hZvtx_after_sel", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {vtxZAxis}); + histos.add("hTOFbeta_gen_pion", "hTOFbeta_gen_pion", kTH2D, {pAxis, betaAxis}); + histos.add("hdEdx_gen_pion", "hdEdx_gen_pion", kTH2D, {pAxis, dEdxAxis}); + histos.add("hnch_gen_all", ";hnch_gen_all", kTH1D, {nchAxis}); + histos.add("hnch_gen", ";hnch_gen", kTH1D, {nchAxis}); + histos.add("hnch_gen_true", ";hnch_gen_true", kTH1D, {nchAxis}); + histos.add("hnch_gen_eta", ";hnch_gen_eta", kTH1D, {etaAxis}); + histos.add("hnch1", ";hnch1", kTH1D, {nchAxis}); + histos.add("hnch2", ";hnch2", kTH1D, {nchAxis}); + histos.add("hnch3", ";hnch3", kTH1D, {nchAxis}); + histos.add("hnch_pi", ";hnch_pi", kTH1D, {nchAxis}); + histos.add("hnch_ka", ";hnch_ka", kTH1D, {nchAxis}); + histos.add("hnch_pr", ";hnch_pr", kTH1D, {nchAxis}); + + histos.add("hVar1x_gen_old", "hVar1x_gen_old", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2x_gen_old", "hVar2x_gen_old", kTH2D, {subAxis, nchAxis}); + histos.add("hVarx_gen_old", "hVarx_gen_old", kTH2D, {subAxis, nchAxis}); + histos.add("hVar1x_gen", "hVar1x_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2x_gen", "hVar2x_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVarx_gen", "hVarx_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2meanptx_gen", "hVar2meanptx_gen", kTH2D, {nchAxis, varAxis2}); + histos.add("hVar1pix_gen", "hVar1pix_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2pix_gen", "hVar2pix_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVarpix_gen", "hVarpix_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2meanptpix_gen", "hVar2meanptpix_gen", kTH2D, {nchAxis, varAxis2}); + histos.add("hVar1kx_gen", "hVar1kx_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2kx_gen", "hVar2kx_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVarkx_gen", "hVarkx_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2meanptkx_gen", "hVar2meanptkx_gen", kTH2D, {nchAxis, varAxis2}); + histos.add("hVar1px_gen", "hVar1px_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2px_gen", "hVar2px_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVarpx_gen", "hVarpx_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2meanptpx_gen", "hVar2meanptpx_gen", kTH2D, {nchAxis, varAxis2}); + histos.add("hcent_nacc_rec", "hcent_nacc_rec", kTH2D, {centAxis, nchAxis}); + histos.add("hcent_nacc_gen", "hcent_nacc_gen", kTH2D, {centAxis, nchAxis}); + histos.add("hGenCentrality", "hGenCentrality", kTH1D, {centAxis}); + histos.add("hVtxZ_before_gen", "", kTH1F, {vtxZAxis}); + histos.add("hVtxZ_after_gen", "", kTH1F, {vtxZAxis}); + histos.add("hEta_gen", "", kTH1F, {etaAxis}); + histos.add("hEta_rec", "", kTH1F, {etaAxis}); + histos.add("hPt_gen", "", kTH1F, {ptAxis}); + histos.add("hPt_rec", "", kTH1F, {ptAxis}); + } + // Configurables + Configurable cVtxZcut{"cVtxZcut", 10.f, "Vertex Z"}; + Configurable cEtacut{"cEtacut", 0.8, "Eta cut"}; + Configurable cPtmincut{"cPtmincut", 0.2, "Pt min cut"}; + Configurable cPtmaxcut{"cPtmaxcut", 2.0, "Pt max cut"}; + Configurable cDcaXYcut{"cDcaXYcut", 0.12, "DCA XY cut"}; + Configurable cDcaZcut{"cDcaZcut", 0.3, "DCA Z cut"}; + Configurable cCentmincut{"cCentmincut", 0.0, "Min cent cut"}; + Configurable cCentmaxcut{"cCentmaxcut", 90.0, "Max cent cut"}; + Configurable cTPCcrosscut{"cTPCcrosscut", 70, "TPC crossrows cut"}; + Configurable cItsChiCut{"cItsChiCut", 70, "ITS chi2 cluster cut"}; + Configurable cTpcChiCut{"cTpcChiCut", 70, "TPC chi2 cluster cut"}; + + // Event selections + Configurable cSel8Trig{"cSel8Trig", true, "Sel8 (T0A + T0C) Selection Run3"}; + Configurable cTFBorder{"cTFBorder", true, "Timeframe Border Selection"}; + Configurable cNoItsROBorder{"cNoItsROBorder", true, "No ITSRO Border Cut"}; + Configurable cItsTpcVtx{"cItsTpcVtx", true, "ITS+TPC Vertex Selection"}; + Configurable cPileupReject{"cPileupReject", true, "Pileup rejection"}; + Configurable cZVtxTimeDiff{"cZVtxTimeDiff", true, "z-vtx time diff selection"}; + Configurable cIsGoodITSLayers{"cIsGoodITSLayers", true, "Good ITS Layers All"}; + Configurable cItslayerall{"cItslayerall", true, "dead staves of ITS removed"}; + Configurable cvtxtofmatched{"cvtxtofmatched", true, "TOF vertex matched"}; + Configurable cfgRejEl{"cfgRejEl", true, "Rejected electrons"}; + + // PID selection configurables + Configurable cPionPmincut{"cPionPmincut", 0.2, "pion min cut of pion"}; + Configurable cKaonPmincut{"cKaonPmincut", 0.2, "kaon min cut of kaon"}; + Configurable cProtonPmincut{"cProtonPmincut", 0.2, "proton min cut of proton"}; + Configurable cPionPmaxcut{"cPionPmaxcut", 2.0, "pion min cut of pion"}; + Configurable cKaonPmaxcut{"cKaonPmaxcut", 2.0, "kaon min cut of kaon"}; + Configurable cProtonPmaxcut{"cProtonPmaxcut", 2.0, "proton min cut of proton"}; + Configurable cPionPthcut{"cPionPthcut", 0.65, "pion threshold cut of pion"}; + Configurable cKaonPthcut{"cKaonPthcut", 0.65, "kaon threshold cut of kaon"}; + Configurable cProtonPthcut{"cProtonPthcut", 1.0, "proton threshold cut of proton"}; + Configurable cNSigCut2{"cNSigCut2", 2.0, "nSigma cut (2)"}; + Configurable cNSigCut3{"cNSigCut3", 3.0, "nSigma cut (3)"}; + Configurable cElMinCut{"cElMinCut", -3.0, "pion min cut of pion"}; + Configurable cElMaxCut{"cElMaxCut", 5.0, "pion min cut of pion"}; + Configurable cTwoPtlCut2{"cTwoPtlCut2", 2.0, "n2ptl cut (2)"}; + Configurable cRapidityCut05{"cRapidityCut05", 0.5, "n2ptl cut (2)"}; + + template + bool selCollision(C const& coll) + { + + if (std::abs(coll.posZ()) > cVtxZcut) { + return false; + } // Reject the collisions with large vertex-z + histos.fill(HIST("hEventcounter"), 2.); + + // cent = coll.centFT0M(); //centrality for run3 + if (cSel8Trig && !coll.sel8()) { + return false; + } // require min bias trigger + histos.fill(HIST("hEventcounter"), 3.); + + if (cTFBorder && !coll.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + return false; + } + if (cNoItsROBorder && !coll.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + return false; + } + histos.fill(HIST("trackSelRec"), 4); + + if (cPileupReject && !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return false; + } + histos.fill(HIST("trackSelRec"), 5); + + if (cZVtxTimeDiff && !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + histos.fill(HIST("trackSelRec"), 6); + + if (cItsTpcVtx && !coll.selection_bit(aod::evsel::kIsVertexITSTPC)) { + return false; + } + histos.fill(HIST("trackSelRec"), 7); + + // if (cItslayerall && !coll.selection_bit(aod::evsel::kIsGoodITSLayersAll)) {return false;} + histos.fill(HIST("trackSelRec"), 8); + + if (cvtxtofmatched && !coll.selection_bit(aod::evsel::kIsVertexTOFmatched)) { + return false; + } + histos.fill(HIST("trackSelRec"), 9); + + return true; // if all checks pass, accept the collision + } + + template + bool selTrack(T const& track) + { + if (!track.isGlobalTrack()) { + return false; + } // accept only global tracks + histos.fill(HIST("tracksel"), 2); + + // if (std::fabs(track.dcaXY()) > cDcaXYcut) {return false;} + histos.fill(HIST("tracksel"), 3); + + // if (std::fabs(track.dcaZ()) > cDcaZcut) {return false;} + histos.fill(HIST("tracksel"), 4); + + if (std::fabs(track.eta()) >= cEtacut) { + return false; + } + histos.fill(HIST("tracksel"), 5); + + if (track.pt() < cPtmincut) { + return false; + } + if (track.pt() > cPtmaxcut) { + return false; + } + histos.fill(HIST("tracksel"), 6); + + // if (track.tpcNClsCrossedRows() < cTPCcrosscut) {return false;} + histos.fill(HIST("tracksel"), 7); + + // if (track.itsChi2NCl() > cItsChiCut) {return false;} + histos.fill(HIST("tracksel"), 8); + + // if (track.tpcChi2NCl() > cTpcChiCut) {return false;} + histos.fill(HIST("tracksel"), 9); + + if (track.sign() == 0) + return false; + + return true; // if all checks pass, accept the collision + } + + template + bool rejEl(T const& track) + { + if (track.tpcNSigmaEl() > cElMinCut && track.tpcNSigmaEl() < cElMaxCut && std::fabs(track.tpcNSigmaPi()) > cNSigCut3 && std::fabs(track.tpcNSigmaKa()) > cNSigCut3 && std::fabs(track.tpcNSigmaPr()) > cNSigCut3) { + return true; + } + return false; + } + + template + bool selProton(T const& track) + { + //! if pt < threshold (For tracks without TOF information) + if (track.p() > cProtonPmincut && track.p() <= cProtonPthcut) { + if (track.hasTPC() && std::fabs(track.tpcNSigmaPr()) < cNSigCut2 && std::fabs(track.tpcNSigmaPi()) > cNSigCut2 && std::fabs(track.tpcNSigmaKa()) > cNSigCut2) { + return true; + } + } + + //! if pt < threshold (For tracks with TOF information) + if (track.p() > cProtonPmincut && track.p() <= cProtonPthcut) { + if (track.hasTOF() && std::fabs(track.tpcNSigmaPr()) < cNSigCut2 && std::fabs(track.tofNSigmaPr()) < cNSigCut2 && std::fabs(track.tpcNSigmaPi()) > cNSigCut2 && std::fabs(track.tpcNSigmaKa()) > cNSigCut2) { + return true; + } + } + + //! if pt > threshold (For tracks with TOF information) + if (track.p() > cProtonPthcut && track.p() <= cProtonPmaxcut) { + if (track.hasTPC() && track.hasTOF() && std::fabs(track.tpcNSigmaPr()) < cNSigCut2 && std::fabs(track.tofNSigmaPr()) < cNSigCut2 && std::hypot(track.tofNSigmaPi(), track.tpcNSigmaPi()) > cNSigCut2 && std::hypot(track.tofNSigmaKa(), track.tpcNSigmaKa()) > cNSigCut2) { + return true; + } + } + + return false; + } + + template + bool selKaon(T const& track) + { + //! if pt < threshold (For tracks without TOF information) + if (track.p() > cKaonPmincut && track.p() <= cKaonPthcut) { + if (track.hasTPC() && std::fabs(track.tpcNSigmaKa()) < cNSigCut2 && std::fabs(track.tpcNSigmaPi()) > cNSigCut2 && std::fabs(track.tpcNSigmaPr()) > cNSigCut2) { + return true; + } + } + + //! if pt < threshold (For tracks with TOF information) + if (track.p() > cKaonPmincut && track.p() <= cKaonPthcut) { + if (track.hasTOF() && std::fabs(track.tpcNSigmaKa()) < cNSigCut2 && std::fabs(track.tofNSigmaKa()) < cNSigCut2 && std::fabs(track.tpcNSigmaPi()) > cNSigCut2 && std::fabs(track.tpcNSigmaPr()) > cNSigCut2) { + return true; + } + } + + //! if pt > threshold (For tracks with TOF information) + if (track.p() > cKaonPthcut && track.p() <= cKaonPmaxcut) { + if (track.hasTPC() && track.hasTOF() && std::fabs(track.tpcNSigmaKa()) < cNSigCut2 && std::fabs(track.tofNSigmaKa()) < cNSigCut2 && std::hypot(track.tofNSigmaPi(), track.tpcNSigmaPi()) > cNSigCut2 && std::hypot(track.tofNSigmaPr(), track.tpcNSigmaPr()) > cNSigCut2) { + return true; + } + } + + return false; + } + + template + bool selPion(T const& track) + { + //! if pt < threshold (For tracks without TOF information) + if (track.p() > cPionPmincut && track.p() <= cPionPthcut) { + if (track.hasTPC() && std::fabs(track.tpcNSigmaPi()) < cNSigCut2 && std::fabs(track.tpcNSigmaKa()) > cNSigCut2 && std::fabs(track.tpcNSigmaPr()) > cNSigCut2) { + return true; + } + } + + //! if pt < threshold (For tracks with TOF information) + if (track.p() > cPionPmincut && track.p() <= cPionPthcut) { + if (track.hasTOF() && std::fabs(track.tpcNSigmaPi()) < cNSigCut2 && std::fabs(track.tofNSigmaPi()) < cNSigCut2 && std::fabs(track.tpcNSigmaKa()) > cNSigCut2 && std::fabs(track.tpcNSigmaPr()) > cNSigCut2) { + return true; + } + } + + //! if pt > threshold (For tracks with TOF information) + if (track.p() > cPionPthcut && track.p() <= cPionPmaxcut) { + if (track.hasTPC() && track.hasTOF() && std::fabs(track.tpcNSigmaPi()) < cNSigCut2 && std::fabs(track.tofNSigmaPi()) < cNSigCut2 && std::hypot(track.tofNSigmaKa(), track.tpcNSigmaKa()) > cNSigCut2 && std::hypot(track.tofNSigmaPr(), track.tpcNSigmaPr()) > cNSigCut2) { + return true; + } + } + + return false; + } + + //++++++++++++++++++++++++++++++++++++DATA CALCULATION +++++++++++++++++++++++++++++++++++++++++++++++++++++// + + void process(aod::MyCollision const& coll, aod::MyTracks const& inputTracks) + { + histos.fill(HIST("hEventcounter"), 1.); + histos.fill(HIST("Data/hZvtx_before_sel"), coll.posZ()); + + if (!selCollision(coll)) + return; + { + histos.fill(HIST("Data/hZvtx_after_sel8"), coll.posZ()); + } + + const auto cent = coll.centFT0C(); + histos.fill(HIST("Data/hCentrality"), cent); + + double nch = 0., nchPi = 0., nchKa = 0., nchPr = 0., nchAll = 0., nchAllBfCut = 0., nchEta = 0., nchPt = 0.; + double q1 = 0., q2 = 0., q1Old = 0., q2Old = 0.; + double q1Pi = 0., q2Pi = 0., q1Ka = 0., q2Ka = 0., q1Pr = 0., q2Pr = 0.; + double var1 = 0., var2 = 0., twoParAllCharge = 0., var1Old = 0., var2Old = 0.; + double var1Pi = 0., var2Pi = 0.; + double var1Ka = 0., var2Ka = 0.; + double var1Pr = 0., var2Pr = 0.; + // double sumPtWeight = 0., sumWeight = 0., sumPtPtWeight = 0.; + + int sample = histos.get(HIST("Data/hZvtx_after_sel8"))->GetEntries(); + sample = sample % 30; // subsample error estimation + for (const auto& track : inputTracks) { + nchAllBfCut += 1.; + histos.fill(HIST("Data/hnchAll_bf_cut"), nchAllBfCut); + + histos.fill(HIST("tracksel"), 1); + histos.fill(HIST("Data/hTPCchi2perCluster_before"), track.tpcChi2NCl()); + histos.fill(HIST("Data/hITSchi2perCluster_before"), track.itsChi2NCl()); + histos.fill(HIST("Data/hTPCCrossedrows_before"), track.tpcNClsCrossedRows()); + + if (std::fabs(track.eta()) <= cEtacut) { + nchEta++; + histos.fill(HIST("Data/hnchTrue"), nchEta); + } + if (track.pt() >= cPtmincut && track.pt() <= cPtmaxcut) { + nchPt += 1.; + histos.fill(HIST("Data/hnchTrue_pt"), nchPt); + } + + if (track.sign() == 0) + continue; + if (!selTrack(track)) + continue; + + nchAll += 1.; + histos.fill(HIST("Data/hnchAll"), nchAll); + histos.fill(HIST("Data/hDCAxy"), track.dcaXY()); + histos.fill(HIST("Data/hDCAz"), track.dcaZ()); + histos.fill(HIST("Data/hTPCCrossedrows_after"), track.tpcNClsCrossedRows()); + histos.fill(HIST("Data/hTPCchi2perCluster_after"), track.tpcChi2NCl()); + histos.fill(HIST("Data/hITSchi2perCluster_after"), track.itsChi2NCl()); + histos.fill(HIST("Data/hP"), track.p()); + histos.fill(HIST("Data/hPt"), track.pt()); + histos.fill(HIST("Data/hEta"), track.eta()); + histos.fill(HIST("Data/hPtDCAxy"), track.pt(), track.dcaXY()); + histos.fill(HIST("Data/hPtDCAz"), track.pt(), track.dcaZ()); + histos.fill(HIST("Data/hPtEta"), track.pt(), track.eta()); + histos.fill(HIST("Data/hPEta"), track.p(), track.eta()); + histos.fill(HIST("Data/hNsigmaTPC"), track.p(), track.tpcNSigmaPr()); + + if (track.pt() >= cPtmincut || track.pt() <= cPtmaxcut) // do not change this (it is for different pt work) + { + nch += 1.; + q1Old += track.pt(); + q2Old += (track.pt() * track.pt()); + histos.fill(HIST("Data/hnch"), nch); + } + + q1 += track.pt(); + q2 += (track.pt() * track.pt()); + + // only TPC tracks: Pion, Kaon, Proton + if (track.hasTPC() && std::abs(track.tpcNSigmaPi()) < cNSigCut3) + histos.fill(HIST("Data/NSigamaTPCpion"), track.pt(), track.tpcNSigmaPi()); + if (track.hasTPC() && std::abs(track.tpcNSigmaKa()) < cNSigCut3) + histos.fill(HIST("Data/NSigamaTPCkaon"), track.pt(), track.tpcNSigmaKa()); + if (track.hasTPC() && std::abs(track.tpcNSigmaPr()) < cNSigCut3) + histos.fill(HIST("Data/NSigamaTPCproton"), track.pt(), track.tpcNSigmaPr()); + + // only TOF tracks: Pion, Kaon, Proton + if (track.hasTOF() && std::abs(track.tofNSigmaPi()) < cNSigCut3) + histos.fill(HIST("Data/NSigamaTOFpion"), track.pt(), track.tofNSigmaPi()); + if (track.hasTOF() && std::abs(track.tofNSigmaKa()) < cNSigCut3) + histos.fill(HIST("Data/NSigamaTOFkaon"), track.pt(), track.tofNSigmaKa()); + if (track.hasTOF() && std::abs(track.tofNSigmaPr()) < cNSigCut3) + histos.fill(HIST("Data/NSigamaTOFproton"), track.pt(), track.tofNSigmaPr()); + + if (track.hasTPC()) + histos.fill(HIST("Data/hdEdx"), track.p(), track.tpcSignal()); + if (track.hasTOF()) + histos.fill(HIST("Data/hTOFbeta"), track.p(), track.beta()); + + //===================================pion============================================================== + // only TPC+TOF tracks: Pion, Kaon, Proton + if ((track.hasTPC() && std::abs(track.tpcNSigmaPi()) < cNSigCut3) && (track.hasTOF() && std::abs(track.tofNSigmaPi()) < cNSigCut3)) { + histos.fill(HIST("Data/NSigamaTPCTOFpion"), track.tpcNSigmaPi(), track.tofNSigmaPi()); + + histos.fill(HIST("Data/hdEdx_afterselection"), track.p(), track.tpcSignal()); + histos.fill(HIST("Data/hTOFbeta_afterselection"), track.p(), track.beta()); + } + + if (selPion(track)) { + histos.fill(HIST("Data/hPtPion"), track.pt()); + histos.fill(HIST("Data/hEtaPion"), track.eta()); + histos.fill(HIST("Data/hyPion"), track.rapidity(massPi)); + histos.fill(HIST("Data/hPtyPion"), track.pt(), track.rapidity(massPi)); + nchPi += 1.; + q1Pi += track.pt(); + q2Pi += (track.pt() * track.pt()); + + if (track.beta() > 1) + continue; + histos.fill(HIST("Data/hdEdx_afterselection1"), track.p(), track.tpcSignal()); + histos.fill(HIST("Data/hTOFbeta_afterselection1"), track.p(), track.beta()); + } + + //===========================kaon=============================================================== + if ((track.hasTPC() && std::abs(track.tpcNSigmaKa()) < cNSigCut3) && (track.hasTOF() && std::abs(track.tofNSigmaKa()) < cNSigCut3)) { + histos.fill(HIST("Data/NSigamaTPCTOFkaon"), track.tpcNSigmaKa(), track.tofNSigmaKa()); + histos.fill(HIST("Data/hdEdx_afterselection"), track.p(), track.tpcSignal()); + histos.fill(HIST("Data/hTOFbeta_afterselection"), track.p(), track.beta()); + } + + if (selKaon(track)) { + histos.fill(HIST("Data/hPtKaon"), track.pt()); + histos.fill(HIST("Data/hEtaKaon"), track.eta()); + histos.fill(HIST("Data/hyKaon"), track.rapidity(massKa)); + histos.fill(HIST("Data/hPtyKaon"), track.pt(), track.rapidity(massKa)); + nchKa += 1.; + q1Ka += track.pt(); + q2Ka += (track.pt() * track.pt()); + + if (track.beta() > 1) + continue; + histos.fill(HIST("Data/hdEdx_afterselection1"), track.p(), track.tpcSignal()); + histos.fill(HIST("Data/hTOFbeta_afterselection1"), track.p(), track.beta()); + } + + //============================proton=========================================================== + if ((track.hasTPC() && std::abs(track.tpcNSigmaPr()) < cNSigCut3) && (track.hasTOF() && std::abs(track.tofNSigmaPr()) < cNSigCut3)) { + histos.fill(HIST("Data/NSigamaTPCTOFproton"), track.tpcNSigmaPr(), track.tofNSigmaPr()); + histos.fill(HIST("Data/hdEdx_afterselection"), track.p(), track.tpcSignal()); + histos.fill(HIST("Data/hTOFbeta_afterselection"), track.p(), track.beta()); + } + + if (selProton(track)) { + histos.fill(HIST("Data/hPtProton"), track.pt()); + histos.fill(HIST("Data/hEtaProton"), track.eta()); + histos.fill(HIST("Data/hyProton"), track.rapidity(massPr)); + histos.fill(HIST("Data/hPtyProton"), track.pt(), track.rapidity(massPr)); + nchPr += 1.; + q1Pr += track.pt(); + q2Pr += (track.pt() * track.pt()); + + if (track.beta() > 1) + continue; + histos.fill(HIST("Data/hdEdx_afterselection1"), track.p(), track.tpcSignal()); + histos.fill(HIST("Data/hTOFbeta_afterselection1"), track.p(), track.beta()); + } + } // Track loop ends! + histos.fill(HIST("Data/hcent_nacc"), cent, nchAll); + + if (nch >= cTwoPtlCut2) { + var1Old = (q1Old * q1Old - q2Old) / (nch * (nch - 1)); + var2Old = (q1Old / nch); + } + if (nchAll < cTwoPtlCut2) + return; + var1 = (q1 * q1 - q2) / (nchAll * (nchAll - 1)); + var2 = (q1 / nchAll); + + //------------------ all charges------------------------------------- + histos.fill(HIST("Data/hVar1"), sample, cent, var1); + histos.fill(HIST("Data/hVar2"), sample, cent, var2); + histos.fill(HIST("Data/hVarc"), sample, cent); + histos.fill(HIST("Data/hVar2meanpt"), cent, var2); + twoParAllCharge = (var1 - var2); + histos.fill(HIST("Data/hVar"), nchAll, twoParAllCharge); + + //---------------------- pions ---------------------------------------- + if (nchPi >= cTwoPtlCut2) { + var1Pi = (q1Pi * q1Pi - q2Pi) / (nchPi * (nchPi - 1)); + var2Pi = (q1Pi / nchPi); + } + + //----------------------- kaons --------------------------------------- + if (nchKa >= cTwoPtlCut2) { + var1Ka = (q1Ka * q1Ka - q2Ka) / (nchKa * (nchKa - 1)); + var2Ka = (q1Ka / nchKa); + } + + //---------------------------- protons ---------------------------------- + if (nchPr >= cTwoPtlCut2) { + var1Pr = (q1Pr * q1Pr - q2Pr) / (nchPr * (nchPr - 1)); + var2Pr = (q1Pr / nchPr); + } + + //========================centrality========================================== + histos.fill(HIST("Data/hVar1pi"), sample, cent, var1Pi); + histos.fill(HIST("Data/hVar2pi"), sample, cent, var2Pi); + histos.fill(HIST("Data/hVar2meanptpi"), cent, var2Pi); + + histos.fill(HIST("Data/hVar1k"), sample, cent, var1Ka); + histos.fill(HIST("Data/hVar2k"), sample, cent, var2Ka); + histos.fill(HIST("Data/hVar2meanptk"), cent, var2Ka); + + histos.fill(HIST("Data/hVar1p"), sample, cent, var1Pr); + histos.fill(HIST("Data/hVar2p"), sample, cent, var2Pr); + histos.fill(HIST("Data/hVar2meanptp"), cent, var2Pr); + + //-----------------------nch------------------------------------- + histos.fill(HIST("Data/hVar1x_old"), sample, nchAll, var1Old); + histos.fill(HIST("Data/hVar2x_old"), sample, nchAll, var2Old); + histos.fill(HIST("Data/hVarx_old"), sample, nchAll); + + histos.fill(HIST("Data/hVar1x"), sample, nchAll, var1); + histos.fill(HIST("Data/hVar2x"), sample, nchAll, var2); + histos.fill(HIST("Data/hVarx"), sample, nchAll); + histos.fill(HIST("Data/hVar2meanptx"), nchAll, var2); + + histos.fill(HIST("Data/hVar1pix"), sample, nchAll, var1Pi); + histos.fill(HIST("Data/hVar2pix"), sample, nchAll, var2Pi); + histos.fill(HIST("Data/hVarpix"), sample, nchPi); + histos.fill(HIST("Data/hVar2meanptpix"), nchAll, var2Pi); + + histos.fill(HIST("Data/hVar1kx"), sample, nchAll, var1Ka); + histos.fill(HIST("Data/hVar2kx"), sample, nchAll, var2Ka); + histos.fill(HIST("Data/hVarkx"), sample, nchKa); + histos.fill(HIST("Data/hVar2meanptkx"), nchAll, var2Ka); + + histos.fill(HIST("Data/hVar1px"), sample, nchAll, var1Pr); + histos.fill(HIST("Data/hVar2px"), sample, nchAll, var2Pr); + histos.fill(HIST("Data/hVarpx"), sample, nchPr); + histos.fill(HIST("Data/hVar2meanptpx"), nchAll, var2Pr); + + } // event loop ends! + + PROCESS_SWITCH(EventMeanPtId, process, "process real data information", false); + + //++++++++++++++++++++++++++++++++++++MC Reconstructed +++++++++++++++++++++++++++++++++++++++++++++++++++++// + + SliceCache cache; + Preslice mcTrack = o2::aod::mcparticle::mcCollisionId; + void processMcReco(aod::MyMCRecoCollision const& coll, aod::MyMCRecoTracks const& inputTracks, aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) + { + if (!coll.has_mcCollision()) { + return; + } + histos.fill(HIST("Rec/hZvtx_before_sel"), coll.posZ()); + histos.fill(HIST("hVtxZ_before_gen"), coll.mcCollision().posZ()); + + if (cTFBorder && !coll.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + return; + } + if (cNoItsROBorder && !coll.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + return; + } + if (cPileupReject && !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return; + } + if (cZVtxTimeDiff && !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + return; + } + if (cItsTpcVtx && !coll.selection_bit(aod::evsel::kIsVertexITSTPC)) { + return; + } + if (cvtxtofmatched && !coll.selection_bit(aod::evsel::kIsVertexTOFmatched)) { + return; + } + if (std::abs(coll.posZ()) > cVtxZcut) { + return; + } + + if (!coll.sel8()) { + return; + } + float cent = coll.centFT0C(); + histos.fill(HIST("Rec/hZvtx_after_sel8"), coll.posZ()); + + double nch = 0., nchPi = 0., nchKa = 0., nchPr = 0., nchAll = 0., nchAllBfCut = 0., nchEta = 0., nchPt = 0.; + double q1 = 0., q2 = 0., q1Old = 0., q2Old = 0.; + double q1Pi = 0., q2Pi = 0., q1Ka = 0., q2Ka = 0., q1Pr = 0., q2Pr = 0.; + double var1 = 0., var2 = 0., twoParAllCharge = 0., var1Old = 0., var2Old = 0.; + double var1Pi = 0., var2Pi = 0., var1Ka = 0., var2Ka = 0., var1Pr = 0., var2Pr = 0.; + + int sample = histos.get(HIST("Rec/hZvtx_after_sel8"))->GetEntries(); + sample = sample % 30; + + for (const auto& track : inputTracks) { + nchAllBfCut += 1.; + histos.fill(HIST("Rec/hnchAll_bf_cut"), nchAllBfCut); + histos.fill(HIST("Rec/hTPCchi2perCluster_before"), track.tpcChi2NCl()); + histos.fill(HIST("Rec/hITSchi2perCluster_before"), track.itsChi2NCl()); + histos.fill(HIST("Rec/hTPCCrossedrows_before"), track.tpcNClsCrossedRows()); + + if (std::fabs(track.eta()) <= cEtacut) { + nchEta++; + histos.fill(HIST("Rec/hnchTrue"), nchEta); + } + if (track.pt() >= cPtmincut && track.pt() <= cPtmaxcut) { + nchPt += 1.; + histos.fill(HIST("Rec/hnchTrue_pt"), nchPt); + } + if (!track.isGlobalTrack()) + continue; + if (std::fabs(track.eta()) > cEtacut) + continue; + if ((track.pt() <= cPtmincut) || (track.pt() >= cPtmaxcut)) + continue; + if (track.sign() == 0) + continue; + // if (std::fabs(track.y()) > 0.5) continue; + histos.fill(HIST("hPt_rec"), track.pt()); + histos.fill(HIST("hEta_rec"), track.eta()); + + auto mcParticle = track.mcParticle(); + nchAll += 1.; + histos.fill(HIST("Rec/hnchAll"), nchAll); + histos.fill(HIST("ptHistogram_allcharge_rec"), track.pt()); + histos.fill(HIST("Rec/hDCAxy"), track.dcaXY()); + histos.fill(HIST("Rec/hDCAz"), track.dcaZ()); + histos.fill(HIST("Rec/hTPCCrossedrows_after"), track.tpcNClsCrossedRows()); + histos.fill(HIST("Rec/hTPCchi2perCluster_after"), track.tpcChi2NCl()); + histos.fill(HIST("Rec/hITSchi2perCluster_after"), track.itsChi2NCl()); + histos.fill(HIST("Rec/hP"), track.p()); + histos.fill(HIST("Rec/hPt"), track.pt()); + histos.fill(HIST("Rec/hEta"), track.eta()); + histos.fill(HIST("Rec/hPtDCAxy"), track.pt(), track.dcaXY()); + histos.fill(HIST("Rec/hPtDCAz"), track.pt(), track.dcaZ()); + histos.fill(HIST("Rec/hPtEta"), track.pt(), track.eta()); + histos.fill(HIST("Rec/hPEta"), track.p(), track.eta()); + histos.fill(HIST("Rec/hNsigmaTPC"), track.p(), track.tpcNSigmaPr()); + + if (track.pt() >= cPtmincut || track.pt() <= cPtmaxcut) // do not change this (it is for different pt work) + { + nch += 1.; + q1Old += track.pt(); + q2Old += (track.pt() * track.pt()); + histos.fill(HIST("Rec/hnch"), nch); + } + q1 += track.pt(); + q2 += (track.pt() * track.pt()); + + if (std::abs(mcParticle.pdgCode()) == PDG_t::kPiPlus) + histos.fill(HIST("ptHistogramPionrec_pdg"), track.pt()); + if (std::abs(mcParticle.pdgCode()) == PDG_t::kKPlus) + histos.fill(HIST("ptHistogramKaonrec_pdg"), track.pt()); + if (std::abs(mcParticle.pdgCode()) == PDG_t::kProton) + histos.fill(HIST("ptHistogramProtonrec_pdg"), track.pt()); + + if (cfgRejEl == false && rejEl(track)) { + return; + } + + // only TPC tracks: Pion, Kaon, Proton + if (track.hasTPC() && std::abs(track.tpcNSigmaPi()) < cNSigCut3) + histos.fill(HIST("Rec/NSigamaTPCpion"), track.pt(), track.tpcNSigmaPi()); + if (track.hasTPC() && std::abs(track.tpcNSigmaKa()) < cNSigCut3) + histos.fill(HIST("Rec/NSigamaTPCkaon"), track.pt(), track.tpcNSigmaKa()); + if (track.hasTPC() && std::abs(track.tpcNSigmaPr()) < cNSigCut3) + histos.fill(HIST("Rec/NSigamaTPCproton"), track.pt(), track.tpcNSigmaPr()); + + // only TOF tracks: Pion, Kaon, Proton + if (track.hasTOF() && std::abs(track.tofNSigmaPi()) < cNSigCut3) + histos.fill(HIST("Rec/NSigamaTOFpion"), track.pt(), track.tofNSigmaPi()); + if (track.hasTOF() && std::abs(track.tofNSigmaKa()) < cNSigCut3) + histos.fill(HIST("Rec/NSigamaTOFkaon"), track.pt(), track.tofNSigmaKa()); + if (track.hasTOF() && std::abs(track.tofNSigmaPr()) < cNSigCut3) + histos.fill(HIST("Rec/NSigamaTOFproton"), track.pt(), track.tofNSigmaPr()); + + if (track.hasTPC()) + histos.fill(HIST("Rec/hdEdx"), track.p(), track.tpcSignal()); + if (track.hasTOF()) + histos.fill(HIST("Rec/hTOFbeta"), track.p(), track.beta()); + if (track.hasTPC()) + histos.fill(HIST("hdEdx_afterselection_rec_beforepidcut"), track.p(), track.tpcSignal()); + if (track.hasTOF()) + histos.fill(HIST("hTOFbeta_afterselection_rec_beforepidcut"), track.p(), track.beta()); + + //===================================pion============================================================== + if ((track.hasTPC() && std::abs(track.tpcNSigmaPi()) < cNSigCut3) && (track.hasTOF() && std::abs(track.tofNSigmaPi()) < cNSigCut3)) { + histos.fill(HIST("Rec/NSigamaTPCTOFpion"), track.tpcNSigmaPi(), track.tofNSigmaPi()); + + histos.fill(HIST("Rec/hdEdx_afterselection"), track.p(), track.tpcSignal()); + histos.fill(HIST("Rec/hTOFbeta_afterselection"), track.p(), track.beta()); + } + + if (selPion(track)) { + if (std::fabs(track.y()) > cRapidityCut05) + continue; + if (track.beta() > 1) + continue; + histos.fill(HIST("ptHistogramPionrec"), track.pt()); + histos.fill(HIST("Rec/hPtPion"), track.pt()); + histos.fill(HIST("Rec/hEtaPion"), track.eta()); + histos.fill(HIST("Rec/hyPion"), track.rapidity(massPi)); + histos.fill(HIST("Rec/hPtyPion"), track.pt(), track.rapidity(massPi)); + histos.fill(HIST("NSigamaTPCpion_rec"), track.p(), track.tpcNSigmaPi()); + histos.fill(HIST("NSigamaTOFpion_rec"), track.p(), track.tofNSigmaPi()); + histos.fill(HIST("NSigamaTPCTOFpion_rec"), track.tpcNSigmaPi(), track.tofNSigmaPi()); + histos.fill(HIST("Rec/hdEdx_afterselection1"), track.p(), track.tpcSignal()); + histos.fill(HIST("Rec/hTOFbeta_afterselection1"), track.p(), track.beta()); + if (std::abs(track.mcParticle().pdgCode()) == PDG_t::kPiPlus) { + histos.fill(HIST("ptHistogramPionrec_purity"), track.pt()); + } + nchPi += 1.; + q1Pi += track.pt(); + q2Pi += (track.pt() * track.pt()); + histos.fill(HIST("hPyPion_rec"), track.p(), track.rapidity(massPi)); + histos.fill(HIST("hPtyPion_rec"), track.pt(), track.rapidity(massPi)); + } + + //===========================kaon=============================================================== + + if ((track.hasTPC() && std::abs(track.tpcNSigmaKa()) < cNSigCut3) && (track.hasTOF() && std::abs(track.tofNSigmaKa()) < cNSigCut3)) { + histos.fill(HIST("Rec/NSigamaTPCTOFkaon"), track.tpcNSigmaKa(), track.tofNSigmaKa()); + histos.fill(HIST("Rec/hdEdx_afterselection"), track.p(), track.tpcSignal()); + histos.fill(HIST("Rec/hTOFbeta_afterselection"), track.p(), track.beta()); + } + + if (selKaon(track)) { + if (std::fabs(track.y()) > cRapidityCut05) + continue; + if (track.beta() > 1) + continue; + histos.fill(HIST("ptHistogramKaonrec"), track.pt()); + histos.fill(HIST("Rec/hPtKaon"), track.pt()); + histos.fill(HIST("Rec/hEtaKaon"), track.eta()); + histos.fill(HIST("Rec/hyKaon"), track.rapidity(massKa)); + histos.fill(HIST("Rec/hPtyKaon"), track.pt(), track.rapidity(massKa)); + histos.fill(HIST("NSigamaTPCkaon_rec"), track.p(), track.tpcNSigmaKa()); + histos.fill(HIST("NSigamaTOFkaon_rec"), track.p(), track.tofNSigmaKa()); + histos.fill(HIST("NSigamaTPCTOFkaon_rec"), track.tpcNSigmaKa(), track.tofNSigmaKa()); + histos.fill(HIST("Rec/hdEdx_afterselection1"), track.p(), track.tpcSignal()); + histos.fill(HIST("Rec/hTOFbeta_afterselection1"), track.p(), track.beta()); + if (std::abs(track.mcParticle().pdgCode()) == PDG_t::kKPlus) { + histos.fill(HIST("ptHistogramKaonrec_purity"), track.pt()); + } + nchKa += 1.; + q1Ka += track.pt(); + q2Ka += (track.pt() * track.pt()); + histos.fill(HIST("hPyKaon_rec"), track.p(), track.rapidity(massKa)); + histos.fill(HIST("hPtyKaon_rec"), track.pt(), track.rapidity(massKa)); + } + + //============================proton=========================================================== + + if ((track.hasTPC() && std::abs(track.tpcNSigmaPr()) < cNSigCut3) && (track.hasTOF() && std::abs(track.tofNSigmaPr()) < cNSigCut3)) { + histos.fill(HIST("Rec/NSigamaTPCTOFproton"), track.tpcNSigmaPr(), track.tofNSigmaPr()); + histos.fill(HIST("Rec/hdEdx_afterselection"), track.p(), track.tpcSignal()); + histos.fill(HIST("Rec/hTOFbeta_afterselection"), track.p(), track.beta()); + } + + if (selProton(track)) { + if (std::fabs(track.y()) > cRapidityCut05) + continue; + if (track.beta() > 1) + continue; + histos.fill(HIST("ptHistogramProtonrec"), track.pt()); + histos.fill(HIST("Rec/hPtProton"), track.pt()); + histos.fill(HIST("Rec/hEtaProton"), track.eta()); + histos.fill(HIST("Rec/hyProton"), track.rapidity(massPr)); + histos.fill(HIST("Rec/hPtyProton"), track.pt(), track.rapidity(massPr)); + histos.fill(HIST("NSigamaTPCproton_rec"), track.p(), track.tpcNSigmaPr()); + histos.fill(HIST("NSigamaTOFproton_rec"), track.p(), track.tofNSigmaPr()); + histos.fill(HIST("NSigamaTPCTOFproton_rec"), track.tpcNSigmaPr(), track.tofNSigmaPr()); + histos.fill(HIST("Rec/hdEdx_afterselection1"), track.p(), track.tpcSignal()); + histos.fill(HIST("Rec/hTOFbeta_afterselection1"), track.p(), track.beta()); + if (std::abs(track.mcParticle().pdgCode()) == PDG_t::kProton) { + histos.fill(HIST("ptHistogramProtonrec_purity"), track.pt()); + } + nchPr += 1.; + q1Pr += track.pt(); + q2Pr += (track.pt() * track.pt()); + histos.fill(HIST("hPyProton_rec"), track.p(), track.rapidity(massPr)); + histos.fill(HIST("hPtyProton_rec"), track.pt(), track.rapidity(massPr)); + } + + } // loop over tracks + histos.fill(HIST("Rec/hcent_nacc"), cent, nchAll); + + if (nch >= cTwoPtlCut2) { + var1Old = (q1Old * q1Old - q2Old) / (nch * (nch - 1)); + var2Old = (q1Old / nch); + } + if (nchAll < cTwoPtlCut2) + return; + var1 = (q1 * q1 - q2) / (nchAll * (nchAll - 1)); + var2 = (q1 / nchAll); + + histos.fill(HIST("Rec/hVar1"), sample, cent, var1); + histos.fill(HIST("Rec/hVar2"), sample, cent, var2); + histos.fill(HIST("Rec/hVarc"), sample, cent); + histos.fill(HIST("Rec/hVar2meanpt"), cent, var2); + twoParAllCharge = (var1 - var2); + histos.fill(HIST("Rec/hVar"), nchAll, twoParAllCharge); + + //---------------------- pions ---------------------------------------- + if (nchPi >= cTwoPtlCut2) { + var1Pi = (q1Pi * q1Pi - q2Pi) / (nchPi * (nchPi - 1)); + var2Pi = (q1Pi / nchPi); + } + //----------------------- kaons --------------------------------------- + if (nchKa >= cTwoPtlCut2) { + var1Ka = (q1Ka * q1Ka - q2Ka) / (nchKa * (nchKa - 1)); + var2Ka = (q1Ka / nchKa); + } + //---------------------------- protons ---------------------------------- + if (nchPr >= cTwoPtlCut2) { + var1Pr = (q1Pr * q1Pr - q2Pr) / (nchPr * (nchPr - 1)); + var2Pr = (q1Pr / nchPr); + } + //========================centrality========================================== + + histos.fill(HIST("Rec/hVar1pi"), sample, cent, var1Pi); + histos.fill(HIST("Rec/hVar2pi"), sample, cent, var2Pi); + histos.fill(HIST("Rec/hVar2meanptpi"), cent, var2Pi); + histos.fill(HIST("Rec/hVar1k"), sample, cent, var1Ka); + histos.fill(HIST("Rec/hVar2k"), sample, cent, var2Ka); + histos.fill(HIST("Rec/hVar2meanptk"), cent, var2Ka); + histos.fill(HIST("Rec/hVar1p"), sample, cent, var1Pr); + histos.fill(HIST("Rec/hVar2p"), sample, cent, var2Pr); + histos.fill(HIST("Rec/hVar2meanptp"), cent, var2Pr); + + //-----------------------nch------------------------------------- + histos.fill(HIST("Rec/hVar1x"), sample, nchAll, var1); + histos.fill(HIST("Rec/hVar2x"), sample, nchAll, var2); + histos.fill(HIST("Rec/hVarx"), sample, nchAll); + histos.fill(HIST("Rec/hVar2meanptx"), nchAll, var2); + histos.fill(HIST("Rec/hVar1pix"), sample, nchAll, var1Pi); + histos.fill(HIST("Rec/hVar2pix"), sample, nchAll, var2Pi); + histos.fill(HIST("Rec/hVarpix"), sample, nchPi); + histos.fill(HIST("Rec/hVar2meanptpix"), nchAll, var2Pi); + histos.fill(HIST("Rec/hVar1kx"), sample, nchAll, var1Ka); + histos.fill(HIST("Rec/hVar2kx"), sample, nchAll, var2Ka); + histos.fill(HIST("Rec/hVarkx"), sample, nchKa); + histos.fill(HIST("Rec/hVar2meanptkx"), nchAll, var2Ka); + histos.fill(HIST("Rec/hVar1px"), sample, nchAll, var1Pr); + histos.fill(HIST("Rec/hVar2px"), sample, nchAll, var2Pr); + histos.fill(HIST("Rec/hVarpx"), sample, nchPr); + histos.fill(HIST("Rec/hVar2meanptpx"), nchAll, var2Pr); + + //================= generated level============================== + + const auto& mccolgen = coll.mcCollision_as(); + if (std::abs(mccolgen.posZ()) > cVtxZcut) { + return; + } + const auto& mcpartgen = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mccolgen.globalIndex(), cache); + histos.fill(HIST("hVtxZ_after_gen"), mccolgen.posZ()); + + double nchGen = 0., nchGenAll = 0., nchGenTrue = 0.; + double nchPiGen = 0., nchKaGen = 0., nchPrGen = 0.; + double nch1 = 0., nch2 = 0., nch3 = 0.; + double q1AllGen = 0, q2AllGen = 0.; + double q1PiGen = 0, q2PiGen = 0, q1KaGen = 0, q2KaGen = 0, q1PrGen = 0, q2PrGen = 0; + double var1AllGen = 0, var2AllGen = 0.; + double var1PiGen = 0, var2PiGen = 0, var1KaGen = 0, var2KaGen = 0, var1PrGen = 0, var2PrGen = 0; + + int sampleGen = histos.get(HIST("hVtxZ_after_gen"))->GetEntries(); + sampleGen = sampleGen % 30; + + for (const auto& mcpart : mcpartgen) { + // auto pdgcode = std::abs(mcpart.pdgCode()); + if (!mcpart.isPhysicalPrimary()) { + continue; + } + nch1++; + histos.fill(HIST("hnch1"), nch1); + // if (!(pdgcode == 211 || pdgcode == 321 || pdgcode == 2212 || pdgcode == -211 || pdgcode == -321 || pdgcode == -2212 || pdgcode == 11 || pdgcode == 13)) continue; + nch2++; + histos.fill(HIST("hnch2"), nch2); + nch3++; + histos.fill(HIST("hnch3"), nch3); + + int pid = mcpart.pdgCode(); + auto sign = 0; + auto* pd = pdg->GetParticle(pid); + if (pd != nullptr) { + sign = pd->Charge() / 3.; + } + if (sign == 0) { + continue; + } + // histos.fill(HIST("gen_hSign"), sign); + if (std::fabs(mcpart.eta()) > cEtacut) + continue; + nchGenTrue++; + histos.fill(HIST("hnch_gen_true"), nchGenTrue); + if ((mcpart.pt() <= cPtmincut) || (mcpart.pt() >= cPtmaxcut)) + continue; + histos.fill(HIST("hPt_gen"), mcpart.pt()); + histos.fill(HIST("hEta_gen"), mcpart.eta()); + histos.fill(HIST("ptHistogram_allcharge_gen"), mcpart.pt()); + nchGenAll += 1.; + q1AllGen += mcpart.pt(); + q2AllGen += (mcpart.pt() * mcpart.pt()); + histos.fill(HIST("hnch_gen_all"), nchGenAll); + if (std::fabs(mcpart.y()) < cRapidityCut05) { + + if (mcpart.pdgCode() == PDG_t::kPiPlus || mcpart.pdgCode() == PDG_t::kPiMinus) { + histos.fill(HIST("ptHistogramPion"), mcpart.pt()); + nchPiGen += 1.; + q1PiGen += mcpart.pt(); + q2PiGen += (mcpart.pt() * mcpart.pt()); + histos.fill(HIST("hnch_pi"), nchPiGen); + } + + if (mcpart.pdgCode() == PDG_t::kKPlus || mcpart.pdgCode() == PDG_t::kKMinus) { + histos.fill(HIST("ptHistogramKaon"), mcpart.pt()); + nchKaGen += 1.; + q1KaGen += mcpart.pt(); + q2KaGen += (mcpart.pt() * mcpart.pt()); + histos.fill(HIST("hnch_ka"), nchKaGen); + } + + if (mcpart.pdgCode() == PDG_t::kProton || mcpart.pdgCode() == PDG_t::kProtonBar) { + histos.fill(HIST("ptHistogramProton"), mcpart.pt()); + nchPrGen += 1.; + q1PrGen += mcpart.pt(); + q2PrGen += (mcpart.pt() * mcpart.pt()); + histos.fill(HIST("hnch_pr"), nchPrGen); + } + + } //|y| < 0.5 cut ends! + + } // particle + histos.fill(HIST("hcent_nacc_gen"), cent, nchGen); + + if (nchGenAll < cTwoPtlCut2) + return; + var1AllGen = (q1AllGen * q1AllGen - q2AllGen) / (nchGenAll * (nchGenAll - 1)); + var2AllGen = (q1AllGen / nchGenAll); + + if (nchPiGen >= cTwoPtlCut2) { + var1PiGen = (q1PiGen * q1PiGen - q2PiGen) / (nchPiGen * (nchPiGen - 1)); + var2PiGen = (q1PiGen / nchPiGen); + } + + //----------------------- kaons --------------------------------------- + if (nchKaGen >= cTwoPtlCut2) { + var1KaGen = (q1KaGen * q1KaGen - q2KaGen) / (nchKaGen * (nchKaGen - 1)); + var2KaGen = (q1KaGen / nchKaGen); + } + //---------------------------- protons ---------------------------------- + if (nchPrGen >= cTwoPtlCut2) { + var1PrGen = (q1PrGen * q1PrGen - q2PrGen) / (nchPrGen * (nchPrGen - 1)); + var2PrGen = (q1PrGen / nchPrGen); + } + //-----------------------nch------------------------------------- + histos.fill(HIST("hVar1x_gen"), sampleGen, nchGenAll, var1AllGen); + histos.fill(HIST("hVar2x_gen"), sampleGen, nchGenAll, var2AllGen); + histos.fill(HIST("hVarx_gen"), sampleGen, nchGenAll); + histos.fill(HIST("hVar2meanptx_gen"), nchGenAll, var2AllGen); + histos.fill(HIST("hVar1pix_gen"), sampleGen, nchGenAll, var1PiGen); + histos.fill(HIST("hVar2pix_gen"), sampleGen, nchGenAll, var2PiGen); + histos.fill(HIST("hVarpix_gen"), sampleGen, nchPiGen); + histos.fill(HIST("hVar2meanptpix_gen"), nchGenAll, var2PiGen); + histos.fill(HIST("hVar1kx_gen"), sampleGen, nchGenAll, var1KaGen); + histos.fill(HIST("hVar2kx_gen"), sampleGen, nchGenAll, var2KaGen); + histos.fill(HIST("hVarkx_gen"), sampleGen, nchKaGen); + histos.fill(HIST("hVar2meanptkx_gen"), nchGenAll, var2KaGen); + histos.fill(HIST("hVar1px_gen"), sampleGen, nchGenAll, var1PrGen); + histos.fill(HIST("hVar2px_gen"), sampleGen, nchGenAll, var2PrGen); + histos.fill(HIST("hVarpx_gen"), sampleGen, nchPrGen); + histos.fill(HIST("hVar2meanptpx_gen"), nchGenAll, var2PrGen); + + } // void process + PROCESS_SWITCH(EventMeanPtId, processMcReco, "Process reconstructed", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} diff --git a/PWGCF/Flow/Tasks/flowTask.cxx b/PWGCF/Flow/Tasks/flowTask.cxx index 91c7402cf90..5431a84bd47 100644 --- a/PWGCF/Flow/Tasks/flowTask.cxx +++ b/PWGCF/Flow/Tasks/flowTask.cxx @@ -113,6 +113,16 @@ struct FlowTask { Filter collisionFilter = (nabs(aod::collision::posZ) < cfgCutVertex) && (aod::cent::centFT0C > cfgCentFT0CMin) && (aod::cent::centFT0C < cfgCentFT0CMax); Filter trackFilter = ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtMin) && (aod::track::pt < cfgCutPtMax) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls) && (nabs(aod::track::dcaZ) < cfgCutDCAz); + using FilteredCollisions = soa::Filtered>; + using FilteredTracks = soa::Filtered>; + // Filter for MCcollisions + Filter mccollisionFilter = nabs(aod::mccollision::posZ) < cfgCutVertex; + using FilteredMcCollisions = soa::Filtered; + // Filter for MCParticle + Filter particleFilter = (nabs(aod::mcparticle::eta) < cfgCutEta) && (aod::mcparticle::pt > cfgCutPtMin) && (aod::mcparticle::pt < cfgCutPtMax); + using FilteredMcParticles = soa::Filtered; + + using FilteredSmallGroupMcCollisions = soa::SmallGroups>; // Corrections TH1D* mEfficiency = nullptr; @@ -127,6 +137,7 @@ struct FlowTask { // Define output OutputObj fFC{FlowContainer("FlowContainer")}; + OutputObj fFCgen{FlowContainer("FlowContainer_gen")}; OutputObj fWeights{GFWWeights("weights")}; HistogramRegistry registry{"registry"}; @@ -143,6 +154,10 @@ struct FlowTask { // Count the total number of enum kCount_CentEstimators }; + enum DataType { + kReco, + kGen + }; int mRunNumber{-1}; uint64_t mSOR{0}; double mMinSeconds{-1.}; @@ -157,9 +172,6 @@ struct FlowTask { TF1* funcV3; TF1* funcV4; - using AodCollisions = soa::Filtered>; - using AodTracks = soa::Filtered>; - // Track selection TrackSelection myTrackSel; TF1* fPhiCutLow = nullptr; @@ -222,6 +234,11 @@ struct FlowTask { registry.add("hMult", "Multiplicity distribution", {HistType::kTH1D, {{3000, 0.5, 3000.5}}}); std::string hCentTitle = "Centrality distribution, Estimator " + std::to_string(cfgCentEstimator); registry.add("hCent", hCentTitle.c_str(), {HistType::kTH1D, {{90, 0, 90}}}); + if (doprocessMCGen) { + registry.add("MCGen/MChVtxZ", "Vexter Z distribution", {HistType::kTH1D, {axisVertex}}); + registry.add("MCGen/MChMult", "Multiplicity distribution", {HistType::kTH1D, {{3000, 0.5, 3000.5}}}); + registry.add("MCGen/MChCent", hCentTitle.c_str(), {HistType::kTH1D, {{90, 0, 90}}}); + } if (!cfgUseSmallMemory) { registry.add("BeforeSel8_globalTracks_centT0C", "before sel8;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {axisCentForQA, axisNch}}); registry.add("BeforeCut_globalTracks_centT0C", "before cut;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {axisCentForQA, axisNch}}); @@ -256,6 +273,11 @@ struct FlowTask { registry.add("hDCAz", "DCAz after cuts; DCAz (cm); Pt", {HistType::kTH2D, {{200, -0.5, 0.5}, {200, 0, 5}}}); registry.add("hDCAxy", "DCAxy after cuts; DCAxy (cm); Pt", {HistType::kTH2D, {{200, -0.5, 0.5}, {200, 0, 5}}}); registry.add("hTrackCorrection2d", "Correlation table for number of tracks table; uncorrected track; corrected track", {HistType::kTH2D, {axisNch, axisNch}}); + if (doprocessMCGen) { + registry.add("MCGen/MChPhi", "#phi distribution", {HistType::kTH1D, {axisPhi}}); + registry.add("MCGen/MChEta", "#eta distribution", {HistType::kTH1D, {axisEta}}); + registry.add("MCGen/MChPtRef", "p_{T} distribution after cut", {HistType::kTH1D, {axisPtHist}}); + } o2::framework::AxisSpec axis = axisPt; int nPtBins = axis.binEdges.size() - 1; @@ -327,6 +349,11 @@ struct FlowTask { fFC->SetName("FlowContainer"); fFC->SetXAxis(fPtAxis); fFC->Initialize(oba, axisIndependent, cfgNbootstrap); + if (doprocessMCGen) { + fFCgen->SetName("FlowContainer_gen"); + fFCgen->SetXAxis(fPtAxis); + fFCgen->Initialize(oba, axisIndependent, cfgNbootstrap); + } delete oba; // eta region @@ -471,6 +498,7 @@ struct FlowTask { return; } + template void fillFC(const GFW::CorrConfig& corrconf, const double& cent, const double& rndm) { double dnx, val; @@ -479,8 +507,9 @@ struct FlowTask { if (dnx == 0) return; val = fGFW->Calculate(corrconf, 0, kFALSE).real() / dnx; - if (std::fabs(val) < 1) - fFC->FillProfile(corrconf.Head.c_str(), cent, val, dnx, rndm); + if (std::fabs(val) < 1) { + (dt == kGen) ? fFCgen->FillProfile(corrconf.Head.c_str(), cent, val, dnx, rndm) : fFC->FillProfile(corrconf.Head.c_str(), cent, val, dnx, rndm); + } return; } for (auto i = 1; i <= fPtAxis->GetNbins(); i++) { @@ -488,8 +517,9 @@ struct FlowTask { if (dnx == 0) continue; val = fGFW->Calculate(corrconf, i - 1, kFALSE).real() / dnx; - if (std::fabs(val) < 1) - fFC->FillProfile(Form("%s_pt_%i", corrconf.Head.c_str(), i), cent, val, dnx, rndm); + if (std::fabs(val) < 1) { + (dt == kGen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconf.Head.c_str(), i), cent, val, dnx, rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconf.Head.c_str(), i), cent, val, dnx, rndm); + } } return; } @@ -610,7 +640,8 @@ struct FlowTask { registry.fill(HIST("hEventCountSpecific"), 8.5); // V0A T0A 5 sigma cut - if (cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > 5 * fT0AV0ASigma->Eval(collision.multFT0A()))) + float sigma = 5.0; + if (cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > sigma * fT0AV0ASigma->Eval(collision.multFT0A()))) return 0; if (cfgEvSelV0AT0ACut) registry.fill(HIST("hEventCountSpecific"), 9.5); @@ -641,7 +672,8 @@ struct FlowTask { registry.fill(HIST("hEventCountTentative"), 7.5); if (!((multNTracksPV < fMultPVCutLow->Eval(centrality)) || (multNTracksPV > fMultPVCutHigh->Eval(centrality)) || (multTrk < fMultCutLow->Eval(centrality)) || (multTrk > fMultCutHigh->Eval(centrality)))) registry.fill(HIST("hEventCountTentative"), 8.5); - if (!(std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > 5 * fT0AV0ASigma->Eval(collision.multFT0A()))) + float sigma = 5.0; + if (!(std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > sigma * fT0AV0ASigma->Eval(collision.multFT0A()))) registry.fill(HIST("hEventCountTentative"), 9.5); } @@ -675,7 +707,30 @@ struct FlowTask { gCurrentHadronicRate = gHadronicRate[mRunNumber]; } - void process(AodCollisions::iterator const& collision, aod::BCsWithTimestamps const&, AodTracks const& tracks) + template + float getCentrality(TCollision const& collision) + { + float cent; + switch (cfgCentEstimator) { + case kCentFT0C: + cent = collision.centFT0C(); + break; + case kCentFT0CVariant1: + cent = collision.centFT0CVariant1(); + break; + case kCentFT0M: + cent = collision.centFT0M(); + break; + case kCentFV0A: + cent = collision.centFV0A(); + break; + default: + cent = collision.centFT0C(); + } + return cent; + } + + void process(FilteredCollisions::iterator const& collision, aod::BCsWithTimestamps const&, FilteredTracks const& tracks) { registry.fill(HIST("hEventCount"), 0.5); if (!cfgUseSmallMemory && tracks.size() >= 1) { @@ -703,23 +758,8 @@ struct FlowTask { registry.fill(HIST("BeforeCut_multV0A_multT0A"), collision.multFT0A(), collision.multFV0A()); registry.fill(HIST("BeforeCut_multT0C_centT0C"), collision.centFT0C(), collision.multFT0C()); } - float cent; - switch (cfgCentEstimator) { - case kCentFT0C: - cent = collision.centFT0C(); - break; - case kCentFT0CVariant1: - cent = collision.centFT0CVariant1(); - break; - case kCentFT0M: - cent = collision.centFT0M(); - break; - case kCentFV0A: - cent = collision.centFV0A(); - break; - default: - cent = collision.centFT0C(); - } + float cent = getCentrality(collision); + if (cfgUseTentativeEventCounter) eventCounterQA(collision, tracks.size(), cent); if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), cent)) @@ -844,9 +884,56 @@ struct FlowTask { // Filling Flow Container for (uint l_ind = 0; l_ind < corrconfigs.size(); l_ind++) { - fillFC(corrconfigs.at(l_ind), independent, lRandom); + fillFC(corrconfigs.at(l_ind), independent, lRandom); + } + } + + void processMCGen(FilteredMcCollisions::iterator const& mcCollision, FilteredSmallGroupMcCollisions const& collisions, FilteredMcParticles const& mcParticles) + { + if (collisions.size() != 1) + return; + + float cent = -1.; + for (const auto& collision : collisions) { + cent = getCentrality(collision); + } + + float lRandom = fRndm->Rndm(); + float vtxz = mcCollision.posZ(); + registry.fill(HIST("MCGen/MChVtxZ"), vtxz); + registry.fill(HIST("MCGen/MChMult"), mcParticles.size()); + registry.fill(HIST("MCGen/MChCent"), cent); + float independent = cent; + if (cfgUseNch) + independent = static_cast(mcParticles.size()); + + fGFW->Clear(); + + for (const auto& mcParticle : mcParticles) { + if (!mcParticle.isPhysicalPrimary()) + continue; + bool withinPtPOI = (cfgCutPtPOIMin < mcParticle.pt()) && (mcParticle.pt() < cfgCutPtPOIMax); // within POI pT range + bool withinPtRef = (cfgCutPtRefMin < mcParticle.pt()) && (mcParticle.pt() < cfgCutPtRefMax); // within RF pT range + + if (withinPtRef) { + registry.fill(HIST("MCGen/MChPhi"), mcParticle.phi()); + registry.fill(HIST("MCGen/MChEta"), mcParticle.eta()); + registry.fill(HIST("MCGen/MChPtRef"), mcParticle.pt()); + } + if (withinPtRef) + fGFW->Fill(mcParticle.eta(), fPtAxis->FindBin(mcParticle.pt()) - 1, mcParticle.phi(), 1., 1); + if (withinPtPOI) + fGFW->Fill(mcParticle.eta(), fPtAxis->FindBin(mcParticle.pt()) - 1, mcParticle.phi(), 1., 2); + if (withinPtPOI && withinPtRef) + fGFW->Fill(mcParticle.eta(), fPtAxis->FindBin(mcParticle.pt()) - 1, mcParticle.phi(), 1., 4); + } + + // Filling Flow Container + for (uint l_ind = 0; l_ind < corrconfigs.size(); l_ind++) { + fillFC(corrconfigs.at(l_ind), independent, lRandom); } } + PROCESS_SWITCH(FlowTask, processMCGen, "Process analysis for MC generated events", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx b/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx index 99cf6e75c69..2d35169f9e8 100644 --- a/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx +++ b/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx @@ -49,7 +49,8 @@ struct ThreeParticleCorrelations { float pionPtMin = 0.3, pionPtMax = 2.3, kaonPtMin = 0.5, kaonPtMax = 2.5, protonPtMin = 0.5, protonPtMax = 2.5; float pionPtMid = 1.5, kaonPtMid1 = 1.5, kaonPtMid2 = 2.0, protonPtMid = 0.7; - float dEtaMin = 0.05, dPhiStarMin = 0.11; + float dEtaMax = 0.05, dEtaMin = 0.022; + float dPhiStarMinOS = 0.075, dPhiStarMinSS = 0.12; float rMin = 0.8, rMax = 2.5; // Lambda invariant mass fit @@ -68,10 +69,6 @@ struct ThreeParticleCorrelations { Filter mcCollZvtx = nabs(aod::mccollision::posZ) < zvtxMax; Filter evSelect = aod::evsel::sel8 == true; - // V0 filters - Filter v0Pt = aod::v0data::pt > v0PtMin&& aod::v0data::pt < v0PtMax; - Filter v0Eta = nabs(aod::v0data::eta) < v0EtaMax; - // Track filters Filter trackPt = aod::track::pt > trackPtMin&& aod::track::pt < trackPtMax; Filter trackEta = nabs(aod::track::eta) < trackEtaMax; @@ -83,7 +80,6 @@ struct ThreeParticleCorrelations { // Table aliases - Data using MyFilteredCollisions = soa::Filtered>; using MyFilteredCollision = MyFilteredCollisions::iterator; - using MyFilteredV0s = soa::Filtered; using MyFilteredTracks = soa::Filtered>; @@ -96,7 +92,7 @@ struct ThreeParticleCorrelations { // Table aliases - MC Rec using MCRecCollisions = soa::Join; using MyFilteredMCRecCollisions = soa::Filtered; - using MyFilteredMCV0s = soa::Filtered>; + using MyMCV0s = soa::Join; using MyFilteredMCTracks = soa::Filtered>; @@ -122,7 +118,7 @@ struct ThreeParticleCorrelations { BinningType collBinning{{confCentBins, confZvtxBins}, true}; BinningTypeMC collBinningMC{{confCentBins, confZvtxBins}, true}; - Pair pairData{collBinning, 5, -1, &cache}; + Pair pairData{collBinning, 5, -1, &cache}; SameKindPair pairMC{collBinningMC, 5, -1, &cache}; // Process configurables @@ -210,6 +206,10 @@ struct ThreeParticleCorrelations { rPhiStarRegistry.add("hSEProtonPostCut_SS", "hSEProtonPostCut_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); rPhiStarRegistry.add("hSEProtonPostCut_SSP", "hSEProtonPostCut_SSP", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); rPhiStarRegistry.add("hSEProtonPostCut_SSN", "hSEProtonPostCut_SSN", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hSEPhiStarMean_OS", "hSEPhiStarMean_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hSEPhiStarMean_SS", "hSEPhiStarMean_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hSEPhiStarMean_SSP", "hSEPhiStarMean_SSP", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hSEPhiStarMean_SSN", "hSEPhiStarMean_SSN", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); rPhiStarRegistry.add("hMEProtonPreCut_OS", "hMEProtonPreCut_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); rPhiStarRegistry.add("hMEProtonPreCut_SS", "hMEProtonPreCut_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); @@ -219,6 +219,10 @@ struct ThreeParticleCorrelations { rPhiStarRegistry.add("hMEProtonPostCut_SS", "hMEProtonPostCut_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); rPhiStarRegistry.add("hMEProtonPostCut_SSP", "hMEProtonPostCut_SSP", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); rPhiStarRegistry.add("hMEProtonPostCut_SSN", "hMEProtonPostCut_SSN", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hMEPhiStarMean_OS", "hMEPhiStarMean_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hMEPhiStarMean_SS", "hMEPhiStarMean_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hMEPhiStarMean_SSP", "hMEPhiStarMean_SSP", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hMEPhiStarMean_SSN", "hMEPhiStarMean_SSN", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); // Efficiency rMCRegistry.add("hGenerated", "hGenerated", {HistType::kTH3D, {{trackPtAxis}, {trackEtaAxis}, {centralityAxis}}}); @@ -313,7 +317,7 @@ struct ThreeParticleCorrelations { //========================================================================================================================================================================================================================================================================== - void processSame(MyFilteredCollision const& collision, MyFilteredV0s const& v0s, MyFilteredTracks const& tracks, aod::BCsWithTimestamps const&) + void processSame(MyFilteredCollision const& collision, aod::V0Datas const& v0s, MyFilteredTracks const& tracks, aod::BCsWithTimestamps const&) { if (!acceptEvent(collision, true)) { @@ -425,7 +429,7 @@ struct ThreeParticleCorrelations { // End of the Same-Event correlations } - void processMixed(MyFilteredCollisions const&, MyFilteredV0s const&, MyFilteredTracks const&, aod::BCsWithTimestamps const&) + void processMixed(MyFilteredCollisions const&, aod::V0Datas const&, MyFilteredTracks const&, aod::BCsWithTimestamps const&) { // Start of the Mixed-Event correlations @@ -663,7 +667,7 @@ struct ThreeParticleCorrelations { // End of the Monte-Carlo generated QA } - void processMCRec(MyFilteredMCRecCollisions::iterator const& collision, MyFilteredMCV0s const& v0s, MyFilteredMCTracks const& tracks, aod::McCollisions const&, aod::McParticles const&) + void processMCRec(MyFilteredMCRecCollisions::iterator const& collision, MyMCV0s const& v0s, MyFilteredMCTracks const& tracks, aod::McCollisions const&, aod::McParticles const&) { if (!acceptEvent(collision, false) || !collision.has_mcCollision()) { @@ -754,7 +758,7 @@ struct ThreeParticleCorrelations { for (const auto& v0 : v0s) { - if (!v0.has_mcParticle()) { + if (!v0.has_mcParticle() || v0.pt() < v0PtMin || v0.pt() > v0PtMax || std::abs(v0.eta()) > v0EtaMax) { continue; } auto particle = v0.mcParticle(); @@ -892,26 +896,31 @@ struct ThreeParticleCorrelations { } if (!collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { // kNoSameBunchPileup - return false; + return kFALSE; } if (FillHist) { rQARegistry.fill(HIST("hNEvents"), 1.5); } if (!collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { // kIsGoodZvtxFT0vsPV - return false; + return kFALSE; } if (FillHist) { rQARegistry.fill(HIST("hNEvents"), 2.5); } - return true; + return kTRUE; } template bool v0Filters(const V0Cand& v0, bool MCRec) // V0 filter { + if (v0.pt() < v0PtMin || v0.pt() > v0PtMax) + return kFALSE; + if (std::abs(v0.eta()) > v0EtaMax) + return kFALSE; + if (!MCRec) { // Data if (v0Sign(v0) == 1) { const auto& posDaughter = v0.template posTrack_as(); @@ -1072,6 +1081,7 @@ struct ThreeParticleCorrelations { bool radialDistanceFilter(const V0Cand& v0, const TrackCand& track, double B, bool Mix) { + bool pass = true; if (confRDSwitch) { auto proton = v0.template posTrack_as(); @@ -1080,8 +1090,8 @@ struct ThreeParticleCorrelations { } double dEta = proton.eta() - track.eta(); - if (std::abs(dEta) > dEtaMin) { - return kTRUE; + if (std::abs(dEta) > dEtaMax) { + return pass; } double dPhiStar; @@ -1089,6 +1099,9 @@ struct ThreeParticleCorrelations { double phaseProton = (-0.3 * B * proton.sign()) / (2 * proton.pt()); double phaseTrack = (-0.3 * B * track.sign()) / (2 * track.pt()); + double dPhiStarMean = 0; + + // Start of the TPC radius loop for (double r = rMin; r <= rMax; r += 0.01) { dPhiStar = RecoDecay::constrainAngle(dPhi + std::asin(phaseProton * r) - std::asin(phaseTrack * r), -constants::math::PIHalf); @@ -1119,11 +1132,19 @@ struct ThreeParticleCorrelations { } } - if (std::abs(dPhiStar) < dPhiStarMin) { - return kFALSE; + if (std::abs(dEta) < dEtaMin) { + if (proton.sign() * track.sign() == -1) { // OS (Electric charge) + if (std::abs(dPhiStar) < dPhiStarMinOS) { + pass = false; + } + } else if (proton.sign() * track.sign() == 1) { // SS (Electric charge) + if (std::abs(dPhiStar) < dPhiStarMinSS) { + pass = false; + } + } } - if (r == rMin) { + if (r == rMin && pass) { if (!Mix) { // Same-event if (proton.sign() * track.sign() == -1) { // OS (Electric charge) rPhiStarRegistry.fill(HIST("hSEProtonPostCut_OS"), dPhiStar, dEta); @@ -1149,10 +1170,38 @@ struct ThreeParticleCorrelations { } } } + + dPhiStarMean += (dPhiStar / 170); + } + // End of the TPC radius loop + + if (!Mix) { // Same-event + if (proton.sign() * track.sign() == -1) { // OS (Electric charge) + rPhiStarRegistry.fill(HIST("hSEPhiStarMean_OS"), dPhiStarMean, dEta); + } else if (proton.sign() * track.sign() == 1) { // SS (Electric charge) + rPhiStarRegistry.fill(HIST("hSEPhiStarMean_SS"), dPhiStarMean, dEta); + if (proton.sign() == 1) { // Positive + rPhiStarRegistry.fill(HIST("hSEPhiStarMean_SSP"), dPhiStarMean, dEta); + } else if (proton.sign() == -1) { // Negative + rPhiStarRegistry.fill(HIST("hSEPhiStarMean_SSN"), dPhiStarMean, dEta); + } + } + + } else { // Mixed-event + if (proton.sign() * track.sign() == -1) { // OS (Electric charge) + rPhiStarRegistry.fill(HIST("hMEPhiStarMean_OS"), dPhiStarMean, dEta); + } else if (proton.sign() * track.sign() == 1) { // SS (Electric charge) + rPhiStarRegistry.fill(HIST("hMEPhiStarMean_SS"), dPhiStarMean, dEta); + if (proton.sign() == 1) { // Positive + rPhiStarRegistry.fill(HIST("hMEPhiStarMean_SSP"), dPhiStarMean, dEta); + } else if (proton.sign() == -1) { // Negative + rPhiStarRegistry.fill(HIST("hMEPhiStarMean_SSN"), dPhiStarMean, dEta); + } + } } } - return kTRUE; + return pass; } }; diff --git a/PWGCF/TwoParticleCorrelations/Tasks/corrSparse.cxx b/PWGCF/TwoParticleCorrelations/Tasks/corrSparse.cxx index 09e74854914..489c99bdbff 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/corrSparse.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/corrSparse.cxx @@ -11,7 +11,7 @@ /// \file corrSparse.cxx /// \brief Provides a sparse with usefull two particle correlation info -/// \author Thor Jensen (thor.kjaersgaard.jensen@cern.ch) and Debojit Sarkar (debojit.sarkar@cern.ch) +/// \author Thor Jensen (thor.kjaersgaard.jensen@cern.ch) #include #include "TRandom3.h" @@ -253,15 +253,15 @@ struct CorrSparse { for (auto const& track2 : tracks2) { - if (track1.pt() <= track2.pt()) - continue; // skip if the trigger pt is less than the associate pt - if (processMFT) { if constexpr (std::is_same_v) { if (!isAcceptedMftTrack(track2)) { continue; } } + } else { + if (track1.pt() <= track2.pt()) + continue; // skip if the trigger pt is less than the associate pt } float deltaPhi = RecoDecay::constrainAngle(track1.phi() - track2.phi(), -PIHalf); diff --git a/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx b/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx index dbe6d1d4b79..f799a8d7564 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx @@ -36,6 +36,7 @@ #include "Common/DataModel/Centrality.h" #include "PWGCF/DataModel/CorrelationsDerived.h" #include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/PIDResponse.h" #include "PWGCF/Core/CorrelationContainer.h" #include "PWGCF/Core/PairCuts.h" #include "PWGCF/GenericFramework/Core/GFWPowerArray.h" @@ -44,20 +45,11 @@ #include "PWGCF/GenericFramework/Core/GFWWeights.h" #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsParameters/GRPMagField.h" +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -namespace o2::aod -{ -namespace di_hadron_cor -{ -DECLARE_SOA_COLUMN(Multiplicity, multiplicity, int); -} -DECLARE_SOA_TABLE(Multiplicity, "AOD", "MULTIPLICITY", - di_hadron_cor::Multiplicity); - -} // namespace o2::aod // define the filtered collisions and tracks #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; @@ -100,34 +92,49 @@ struct DiHadronCor { O2_DEFINE_CONFIGURABLE(cfgCutOccupancyHigh, int, 2000, "High cut on TPC occupancy") O2_DEFINE_CONFIGURABLE(cfgCutOccupancyLow, int, 0, "Low cut on TPC occupancy") O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") + O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, bool, false, "Use local efficiency object") + O2_DEFINE_CONFIGURABLE(cfgVerbosity, bool, false, "Verbose output") SliceCache cache; - SliceCache cacheNch; ConfigurableAxis axisVertex{"axisVertex", {10, -10, 10}, "vertex axis for histograms"}; - ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 5, 10, 15, 20, 25, 30, 35, 40, 50, 60, 80, 100}, "multiplicity axis for histograms"}; - ConfigurableAxis axisCentrality{"axisCentrality", {VARIABLE_WIDTH, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90}, "centrality axis for histograms"}; - ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt axis for histograms"}; + ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 5, 10, 15, 20, 25, 30, 35, 40, 50, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280, 300}, "multiplicity axis for histograms"}; + ConfigurableAxis axisCentrality{"axisCentrality", {VARIABLE_WIDTH, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}, "centrality axis for histograms"}; + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.2, 1.4, 1.6, 1.8, 2, 2.5, 3, 4, 5, 6, 8, 10}, "pt axis for histograms"}; ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {72, -PIHalf, PIHalf * 3}, "delta phi axis for histograms"}; ConfigurableAxis axisDeltaEta{"axisDeltaEta", {48, -2.4, 2.4}, "delta eta axis for histograms"}; - ConfigurableAxis axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt trigger axis for histograms"}; - ConfigurableAxis axisPtAssoc{"axisPtAssoc", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt associated axis for histograms"}; + ConfigurableAxis axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.2, 1.4, 1.6, 1.8, 2, 2.5, 3, 4, 5, 6, 8, 10}, "pt trigger axis for histograms"}; + ConfigurableAxis axisPtAssoc{"axisPtAssoc", {VARIABLE_WIDTH, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.2, 1.4, 1.6, 1.8, 2, 2.5, 3, 4, 5, 6, 8, 10}, "pt associated axis for histograms"}; ConfigurableAxis axisVtxMix{"axisVtxMix", {VARIABLE_WIDTH, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "vertex axis for mixed event histograms"}; - ConfigurableAxis axisMultMix{"axisMultMix", {VARIABLE_WIDTH, 0, 5, 10, 15, 20, 25, 30, 35, 40, 50, 60, 80, 100}, "multiplicity / centrality axis for mixed event histograms"}; + ConfigurableAxis axisMultMix{"axisMultMix", {VARIABLE_WIDTH, 0, 5, 10, 15, 20, 25, 30, 35, 40, 50, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280, 300}, "multiplicity / centrality axis for mixed event histograms"}; ConfigurableAxis axisSample{"axisSample", {cfgSampleSize, 0, cfgSampleSize}, "sample axis for histograms"}; ConfigurableAxis axisVertexEfficiency{"axisVertexEfficiency", {10, -10, 10}, "vertex axis for efficiency histograms"}; ConfigurableAxis axisEtaEfficiency{"axisEtaEfficiency", {20, -1.0, 1.0}, "eta axis for efficiency histograms"}; - ConfigurableAxis axisPtEfficiency{"axisPtEfficiency", {VARIABLE_WIDTH, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0}, "pt axis for efficiency histograms"}; + ConfigurableAxis axisPtEfficiency{"axisPtEfficiency", {VARIABLE_WIDTH, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.2, 1.4, 1.6, 1.8, 2, 2.5, 3, 4, 5, 6, 8, 10}, "pt axis for efficiency histograms"}; // make the filters and cuts. Filter collisionFilter = (nabs(aod::collision::posZ) < cfgCutVtxZ) && (aod::evsel::sel8) == true && (aod::cent::centFT0C > cfgCentFT0CMin) && (aod::cent::centFT0C < cfgCentFT0CMax); Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtMin) && (aod::track::pt < cfgCutPtMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls) && (nabs(aod::track::dcaZ) < cfgCutDCAz); + using FilteredCollisions = soa::Filtered>; + using FilteredTracks = soa::Filtered>; + using FilteredTracksWithMCLabels = soa::Filtered>; + + // Filter for MCParticle + Filter particleFilter = (nabs(aod::mcparticle::eta) < cfgCutEta) && (aod::mcparticle::pt > cfgCutPtMin) && (aod::mcparticle::pt < cfgCutPtMax); + using FilteredMcParticles = soa::Filtered; + + // Filter for MCcollisions + Filter mccollisionFilter = nabs(aod::mccollision::posZ) < cfgCutVtxZ; + using FilteredMcCollisions = soa::Filtered; + + using FilteredSmallGroupMcCollisions = soa::SmallGroups>; + + Preslice perCollision = aod::track::collisionId; + PresliceUnsorted collisionPerMCCollision = aod::mccollisionlabel::mcCollisionId; // Corrections - TH1D* mEfficiency = nullptr; - GFWWeights* mAcceptance = nullptr; - TObjArray* mAcceptanceList = nullptr; + TH3D* mEfficiency = nullptr; bool correctionsLoaded = false; // Define the outputs @@ -150,6 +157,9 @@ struct DiHadronCor { MixedEvent = 3 }; + // persistent caches + std::vector efficiencyAssociatedCache; + // Additional Event selection cuts - Copy from flowGenericFramework.cxx TF1* fMultPVCutLow = nullptr; TF1* fMultPVCutHigh = nullptr; @@ -159,9 +169,6 @@ struct DiHadronCor { TF1* fT0AV0AMean = nullptr; TF1* fT0AV0ASigma = nullptr; - using AodCollisions = soa::Filtered>; // aod::CentFT0Cs - using AodTracks = soa::Filtered>; - void init(InitContext&) { const AxisSpec axisPhi{72, 0.0, constants::math::TwoPI, "#varphi"}; @@ -224,6 +231,7 @@ struct DiHadronCor { registry.add("deltaEta_deltaPhi_mixed", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); registry.add("Phi", "Phi", {HistType::kTH1D, {axisPhi}}); registry.add("Eta", "Eta", {HistType::kTH1D, {axisEta}}); + registry.add("EtaCorrected", "EtaCorrected", {HistType::kTH1D, {axisEta}}); registry.add("pT", "pT", {HistType::kTH1D, {axisPtTrigger}}); registry.add("pTCorrected", "pTCorrected", {HistType::kTH1D, {axisPtTrigger}}); registry.add("Nch", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); @@ -232,10 +240,23 @@ struct DiHadronCor { registry.add("Centrality", hCentTitle.c_str(), {HistType::kTH1D, {axisCentrality}}); registry.add("Centrality_used", hCentTitle.c_str(), {HistType::kTH1D, {axisCentrality}}); // histogram to see how many events are in the same and mixed event registry.add("zVtx", "zVtx", {HistType::kTH1D, {axisVertex}}); + registry.add("zVtx_used", "zVtx_used", {HistType::kTH1D, {axisVertex}}); registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); registry.add("eventcount", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event + if (doprocessMCSame) { + registry.add("MCTrue/MCeventcount", "MCeventcount", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event + registry.add("MCTrue/MCCentrality", hCentTitle.c_str(), {HistType::kTH1D, {axisCentrality}}); + registry.add("MCTrue/MCNch", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); + registry.add("MCTrue/MCzVtx", "MCzVtx", {HistType::kTH1D, {axisVertex}}); + registry.add("MCTrue/MCPhi", "MCPhi", {HistType::kTH1D, {axisPhi}}); + registry.add("MCTrue/MCEta", "MCEta", {HistType::kTH1D, {axisEta}}); + registry.add("MCTrue/MCpT", "MCpT", {HistType::kTH1D, {axisPtTrigger}}); + registry.add("MCTrue/MCTrig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + registry.add("MCTrue/MCdeltaEta_deltaPhi_same", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); // check to see the delta eta and delta phi distribution + registry.add("MCTrue/MCdeltaEta_deltaPhi_mixed", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); + } std::vector corrAxis = {{axisSample, "Sample"}, {axisVertex, "z-vtx (cm)"}, @@ -244,9 +265,9 @@ struct DiHadronCor { {axisDeltaPhi, "#Delta#varphi (rad)"}, {axisDeltaEta, "#Delta#eta"}}; std::vector effAxis = { - {axisVertexEfficiency, "z-vtx (cm)"}, - {axisPtEfficiency, "p_{T} (GeV/c)"}, {axisEtaEfficiency, "#eta"}, + {axisPtEfficiency, "p_{T} (GeV/c)"}, + {axisVertexEfficiency, "z-vtx (cm)"}, }; std::vector userAxis; @@ -298,12 +319,18 @@ struct DiHadronCor { return ((track.tpcNClsFound() >= cfgCutTPCclu) && (track.itsNCls() >= cfgCutITSclu)); } - void loadCorrections(uint64_t timestamp) + void loadEfficiency(uint64_t timestamp) { - if (correctionsLoaded) + if (correctionsLoaded) { return; + } if (cfgEfficiency.value.empty() == false) { - mEfficiency = ccdb->getForTimeStamp(cfgEfficiency, timestamp); + if (cfgLocalEfficiency > 0) { + TFile* fEfficiencyTrigger = TFile::Open(cfgEfficiency.value.c_str(), "READ"); + mEfficiency = reinterpret_cast(fEfficiencyTrigger->Get("ccdb_object")); + } else { + mEfficiency = ccdb->getForTimeStamp(cfgEfficiency, timestamp); + } if (mEfficiency == nullptr) { LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgEfficiency.value.c_str()); } @@ -312,13 +339,17 @@ struct DiHadronCor { correctionsLoaded = true; } - bool setCurrentParticleWeights(float& weight_nue, float pt) + bool getEfficiencyCorrection(float& weight_nue, float eta, float pt, float posZ) { float eff = 1.; - if (mEfficiency) - eff = mEfficiency->GetBinContent(mEfficiency->FindBin(pt)); - else + if (mEfficiency) { + int etaBin = mEfficiency->GetXaxis()->FindBin(eta); + int ptBin = mEfficiency->GetYaxis()->FindBin(pt); + int zBin = mEfficiency->GetZaxis()->FindBin(posZ); + eff = mEfficiency->GetBinContent(etaBin, ptBin, zBin); + } else { eff = 1.0; + } if (eff == 0) return false; weight_nue = 1. / eff; @@ -329,20 +360,16 @@ struct DiHadronCor { template void fillYield(TCollision collision, TTracks tracks) // function to fill the yield and etaphi histograms. { - float cent = getCentrality(collision); - registry.fill(HIST("Centrality"), cent); - - registry.fill(HIST("Nch"), tracks.size()); - registry.fill(HIST("zVtx"), collision.posZ()); - float weff1 = 1; + float vtxz = collision.posZ(); for (auto const& track1 : tracks) { if (!trackSelected(track1)) continue; - if (!setCurrentParticleWeights(weff1, track1.pt())) + if (!getEfficiencyCorrection(weff1, track1.eta(), track1.pt(), vtxz)) continue; registry.fill(HIST("Phi"), RecoDecay::constrainAngle(track1.phi(), 0.0)); registry.fill(HIST("Eta"), track1.eta()); + registry.fill(HIST("EtaCorrected"), track1.eta(), weff1); registry.fill(HIST("pT"), track1.pt()); registry.fill(HIST("pTCorrected"), track1.pt(), weff1); } @@ -372,10 +399,19 @@ struct DiHadronCor { return dPhiStar; } - // template void fillCorrelations(TTracks tracks1, TTracksAssoc tracks2, float posZ, int system, int magneticField, float cent) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms { + // Cache efficiency for particles (too many FindBin lookups) + if (mEfficiency) { + efficiencyAssociatedCache.clear(); + efficiencyAssociatedCache.reserve(tracks2.size()); + for (const auto& track2 : tracks2) { + float weff = 1.; + getEfficiencyCorrection(weff, track2.eta(), track2.pt(), posZ); + efficiencyAssociatedCache.push_back(weff); + } + } if (system == SameEvent) { registry.fill(HIST("Centrality_used"), cent); @@ -384,25 +420,26 @@ struct DiHadronCor { int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); - float weff1 = 1; - float weff2 = 1; + float triggerWeight = 1.0f; + float associatedWeight = 1.0f; // loop over all tracks for (auto const& track1 : tracks1) { if (!trackSelected(track1)) continue; - if (!setCurrentParticleWeights(weff1, track1.pt())) + if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) continue; if (system == SameEvent) { - registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, track1.pt()); + registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, track1.pt(), triggerWeight); } for (auto const& track2 : tracks2) { if (!trackSelected(track2)) continue; - if (!setCurrentParticleWeights(weff2, track2.pt())) - continue; + if (mEfficiency) { + associatedWeight = efficiencyAssociatedCache[track2.filteredIndex()]; + } if (track1.pt() <= track2.pt()) continue; // skip if the trigger pt is less than the associate pt @@ -435,12 +472,51 @@ struct DiHadronCor { // fill the right sparse and histograms if (system == SameEvent) { - same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta); - registry.fill(HIST("deltaEta_deltaPhi_same"), deltaPhi, deltaEta); + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta, triggerWeight * associatedWeight); + registry.fill(HIST("deltaEta_deltaPhi_same"), deltaPhi, deltaEta, triggerWeight * associatedWeight); } else if (system == MixedEvent) { - mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta); - registry.fill(HIST("deltaEta_deltaPhi_mixed"), deltaPhi, deltaEta); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta, triggerWeight * associatedWeight); + registry.fill(HIST("deltaEta_deltaPhi_mixed"), deltaPhi, deltaEta, triggerWeight * associatedWeight); + } + } + } + } + template + void fillMCCorrelations(TTracks tracks1, TTracksAssoc tracks2, float posZ, int system) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + { + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + + float triggerWeight = 1.0f; + float associatedWeight = 1.0f; + // loop over all tracks + for (auto const& track1 : tracks1) { + if (step >= CorrelationContainer::kCFStepTrackedOnlyPrim && !track1.isPhysicalPrimary()) + continue; + + if (system == SameEvent && doprocessMCSame) + registry.fill(HIST("MCTrue/MCTrig_hist"), fSampleIndex, posZ, track1.pt(), triggerWeight); + + for (auto const& track2 : tracks2) { + + if (step >= CorrelationContainer::kCFStepTrackedOnlyPrim && !track2.isPhysicalPrimary()) + continue; + + if (track1.pt() <= track2.pt()) + continue; // skip if the trigger pt is less than the associate pt + + float deltaPhi = RecoDecay::constrainAngle(track1.phi() - track2.phi(), -PIHalf); + float deltaEta = track1.eta() - track2.eta(); + + // fill the right sparse and histograms + if (system == SameEvent) { + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta, triggerWeight * associatedWeight); + if (doprocessMCSame) + registry.fill(HIST("MCTrue/MCdeltaEta_deltaPhi_same"), deltaPhi, deltaEta, triggerWeight * associatedWeight); + } else if (system == MixedEvent) { + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta, triggerWeight * associatedWeight); + if (doprocessMCMixed) + registry.fill(HIST("MCTrue/MCdeltaEta_deltaPhi_mixed"), deltaPhi, deltaEta, triggerWeight * associatedWeight); } } } @@ -510,7 +586,8 @@ struct DiHadronCor { registry.fill(HIST("hEventCountSpecific"), 8.5); // V0A T0A 5 sigma cut - if (cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > 5 * fT0AV0ASigma->Eval(collision.multFT0A()))) + float sigma = 5.0; + if (cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > sigma * fT0AV0ASigma->Eval(collision.multFT0A()))) return 0; if (fillCounter && cfgEvSelV0AT0ACut) registry.fill(HIST("hEventCountSpecific"), 9.5); @@ -518,7 +595,7 @@ struct DiHadronCor { return 1; } - void processSame(AodCollisions::iterator const& collision, AodTracks const& tracks, aod::BCsWithTimestamps const&) + void processSame(FilteredCollisions::iterator const& collision, FilteredTracks const& tracks, aod::BCsWithTimestamps const&) { auto bc = collision.bc_as(); @@ -526,10 +603,9 @@ struct DiHadronCor { if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), cent, true)) return; - registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin - - loadCorrections(bc.timestamp()); - fillYield(collision, tracks); + registry.fill(HIST("Centrality"), cent); + registry.fill(HIST("Nch"), tracks.size()); + registry.fill(HIST("zVtx"), collision.posZ()); if (cfgSelCollByNch && (tracks.size() < cfgCutMultMin || tracks.size() >= cfgCutMultMax)) { return; @@ -538,15 +614,20 @@ struct DiHadronCor { return; } + loadEfficiency(bc.timestamp()); + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + fillYield(collision, tracks); + + same->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); fillCorrelations(tracks, tracks, collision.posZ(), SameEvent, getMagneticField(bc.timestamp()), cent); } PROCESS_SWITCH(DiHadronCor, processSame, "Process same event", true); // the process for filling the mixed events - void processMixed(AodCollisions const& collisions, AodTracks const& tracks, aod::BCsWithTimestamps const&) + void processMixed(FilteredCollisions const& collisions, FilteredTracks const& tracks, aod::BCsWithTimestamps const&) { - auto getTracksSize = [&tracks, this](AodCollisions::iterator const& collision) { + auto getTracksSize = [&tracks, this](FilteredCollisions::iterator const& collision) { auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), this->cache); auto mult = associatedTracks.size(); return mult; @@ -557,11 +638,8 @@ struct DiHadronCor { MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; auto tracksTuple = std::make_tuple(tracks, tracks); - Pair pair{binningOnVtxAndMult, cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + Pair pair{binningOnVtxAndMult, cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip for (auto const& [collision1, tracks1, collision2, tracks2] : pair) { - registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin - auto bc = collision1.bc_as(); - loadCorrections(bc.timestamp()); if (cfgSelCollByNch && (tracks1.size() < cfgCutMultMin || tracks1.size() >= cfgCutMultMax)) continue; @@ -582,11 +660,152 @@ struct DiHadronCor { if (!cfgSelCollByNch && (cent2 < cfgCutCentMin || cent2 >= cfgCutCentMax)) continue; + registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin + auto bc = collision1.bc_as(); + loadEfficiency(bc.timestamp()); + fillCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, getMagneticField(bc.timestamp()), cent1); } } PROCESS_SWITCH(DiHadronCor, processMixed, "Process mixed events", true); + + int getSpecies(int pdgCode) + { + switch (std::abs(pdgCode)) { + case PDG_t::kPiPlus: // pion + return 0; + case PDG_t::kKPlus: // Kaon + return 1; + case PDG_t::kProton: // proton + return 2; + default: // NOTE. The efficiency histogram is hardcoded to contain 4 species. Anything special will have the last slot. + return 3; + } + } + + void processMCEfficiency(FilteredMcCollisions::iterator const& mcCollision, aod::BCsWithTimestamps const&, soa::SmallGroups> const& collisions, FilteredMcParticles const& mcParticles, FilteredTracksWithMCLabels const& tracks) + { + if (cfgSelCollByNch && (tracks.size() < cfgCutMultMin || tracks.size() >= cfgCutMultMax)) { + return; + } + // Primaries + for (const auto& mcParticle : mcParticles) { + if (mcParticle.isPhysicalPrimary()) { + same->getTrackHistEfficiency()->Fill(CorrelationContainer::MC, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), 0., mcCollision.posZ()); + } + } + for (const auto& collision : collisions) { + auto groupedTracks = tracks.sliceBy(perCollision, collision.globalIndex()); + if (cfgVerbosity) { + LOGF(info, " Reconstructed collision at vtx-z = %f", collision.posZ()); + LOGF(info, " which has %d tracks", groupedTracks.size()); + } + + for (const auto& track : groupedTracks) { + if (track.has_mcParticle()) { + const auto& mcParticle = track.mcParticle(); + if (mcParticle.isPhysicalPrimary()) { + same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoPrimaries, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), 0., mcCollision.posZ()); + } + same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoAll, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), 0., mcCollision.posZ()); + } else { + // fake track + same->getTrackHistEfficiency()->Fill(CorrelationContainer::Fake, track.eta(), track.pt(), 0, 0., mcCollision.posZ()); + } + } + } + } + PROCESS_SWITCH(DiHadronCor, processMCEfficiency, "MC: Extract efficiencies", false); + + void processMCSame(FilteredMcCollisions::iterator const& mcCollision, FilteredMcParticles const& mcParticles, FilteredSmallGroupMcCollisions const& collisions) + { + if (cfgVerbosity) { + LOGF(info, "processMCSame. MC collision: %d, particles: %d, collisions: %d", mcCollision.globalIndex(), mcParticles.size(), collisions.size()); + } + + float cent = -1; + for (const auto& collision : collisions) { + cent = getCentrality(collision); + } + + if (cfgSelCollByNch && (mcParticles.size() < cfgCutMultMin || mcParticles.size() >= cfgCutMultMax)) { + return; + } + if (!cfgSelCollByNch && (cent < cfgCutCentMin || cent >= cfgCutCentMax)) { + return; + } + + registry.fill(HIST("MCTrue/MCeventcount"), SameEvent); // because its same event i put it in the 1 bin + registry.fill(HIST("MCTrue/MCCentrality"), cent); + registry.fill(HIST("MCTrue/MCNch"), mcParticles.size()); + registry.fill(HIST("MCTrue/MCzVtx"), mcCollision.posZ()); + for (const auto& mcParticle : mcParticles) { + if (mcParticle.isPhysicalPrimary()) { + registry.fill(HIST("MCTrue/MCPhi"), mcParticle.phi()); + registry.fill(HIST("MCTrue/MCEta"), mcParticle.eta()); + registry.fill(HIST("MCTrue/MCpT"), mcParticle.pt()); + } + } + + same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepAll); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent); + + if (collisions.size() == 0) { + return; + } + + same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepTrackedOnlyPrim); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent); + } + PROCESS_SWITCH(DiHadronCor, processMCSame, "Process MC same event", false); + + void processMCMixed(FilteredMcCollisions const& mcCollisions, FilteredMcParticles const& mcParticles, FilteredSmallGroupMcCollisions const& collisions) + { + auto getTracksSize = [&mcParticles, this](FilteredMcCollisions::iterator const& mcCollision) { + auto associatedTracks = mcParticles.sliceByCached(o2::aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), this->cache); + auto mult = associatedTracks.size(); + return mult; + }; + + using MixedBinning = FlexibleBinningPolicy, o2::aod::mccollision::PosZ, decltype(getTracksSize)>; + + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; + + auto tracksTuple = std::make_tuple(mcParticles, mcParticles); + Pair pair{binningOnVtxAndMult, cfgMixEventNumMin, -1, mcCollisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + for (auto const& [collision1, tracks1, collision2, tracks2] : pair) { + + if (cfgSelCollByNch && (tracks1.size() < cfgCutMultMin || tracks1.size() >= cfgCutMultMax)) + continue; + + if (cfgSelCollByNch && (tracks2.size() < cfgCutMultMin || tracks2.size() >= cfgCutMultMax)) + continue; + + auto groupedCollisions = collisions.sliceBy(collisionPerMCCollision, collision1.globalIndex()); + if (cfgVerbosity > 0) { + LOGF(info, "Found %d related collisions", groupedCollisions.size()); + } + float cent = -1; + for (const auto& collision : groupedCollisions) { + cent = getCentrality(collision); + } + + if (!cfgSelCollByNch && groupedCollisions.size() != 0 && (cent < cfgCutCentMin || cent >= cfgCutCentMax)) + continue; + + registry.fill(HIST("MCTrue/MCeventcount"), MixedEvent); // fill the mixed event in the 3 bin + + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent); + + if (groupedCollisions.size() == 0) { + continue; + } + + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent); + } + } + PROCESS_SWITCH(DiHadronCor, processMCMixed, "Process MC mixed events", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx index 01befb49204..9a299ed8950 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx @@ -164,8 +164,6 @@ enum TrackLabels { kPFCorrPtCent, kPFCorrPtRapCent, kNoPFCorr, - kCorrFact, - kErrCorrFact, kGenTotAccLambda, kGenLambdaNoDau, kGenLambdaToPrPi @@ -468,8 +466,6 @@ struct LambdaTableProducer { histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPFCorrPtCent, "kPFCorrPtCent"); histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPFCorrPtRapCent, "kPFCorrPtRapCent"); histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kNoPFCorr, "kNoPFCorr"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kCorrFact, "kCorrFact"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kErrCorrFact, "kErrCorrFact"); } template @@ -826,7 +822,7 @@ struct LambdaTableProducer { } // initialize efficiency factor and primary fraction values - float effFact = 1., primFrac = 1.; + float effCorrFact = 1., primFrac = 1.; float rap = (cDoEtaAnalysis) ? v0.eta() : v0.yLambda(); // Get Efficiency Factor @@ -835,14 +831,14 @@ struct LambdaTableProducer { TH1F* histEff = reinterpret_cast(objEff->Clone()); if (histEff->GetDimension() == TwoDimCorr) { histos.fill(HIST("Tracks/h1f_tracks_info"), kEffCorrPtCent); - effFact = histEff->GetBinContent(histEff->FindBin(cent, v0.pt())); + effCorrFact = histEff->GetBinContent(histEff->FindBin(cent, v0.pt())); } else if (histEff->GetDimension() == ThreeDimCorr) { histos.fill(HIST("Tracks/h1f_tracks_info"), kEffCorrPtRapCent); - effFact = histEff->GetBinContent(histEff->FindBin(cent, v0.pt(), rap)); + effCorrFact = histEff->GetBinContent(histEff->FindBin(cent, v0.pt(), rap)); } else { histos.fill(HIST("Tracks/h1f_tracks_info"), kNoEffCorr); LOGF(warning, "CCDB OBJECT IS NOT A HISTOGRAM !!!"); - effFact = 1.; + effCorrFact = 1.; } delete histEff; } @@ -855,6 +851,9 @@ struct LambdaTableProducer { if (histPrm->GetDimension() == TwoDimCorr) { histos.fill(HIST("Tracks/h1f_tracks_info"), kPFCorrPtCent); primFrac = histPrm->GetBinContent(histPrm->FindBin(cent, v0.pt())); + } else if (histPrm->GetDimension() == ThreeDimCorr) { + histos.fill(HIST("Tracks/h1f_tracks_info"), kPFCorrPtRapCent); + primFrac = histPrm->GetBinContent(histPrm->FindBin(cent, v0.pt(), rap)); } else { histos.fill(HIST("Tracks/h1f_tracks_info"), kNoPFCorr); LOGF(warning, "CCDB OBJECT IS NOT A HISTOGRAM !!!"); @@ -863,13 +862,7 @@ struct LambdaTableProducer { delete histPrm; } - if (effFact != 0) { - histos.fill(HIST("Tracks/h1f_tracks_info"), kCorrFact); - return primFrac / effFact; - } - - histos.fill(HIST("Tracks/h1f_tracks_info"), kErrCorrFact); - return 1.; + return primFrac * effCorrFact; } template @@ -1175,7 +1168,7 @@ struct LambdaTableProducer { } SliceCache cache; - Preslice> perCollision = aod::track::collisionId; + Preslice> perCollision = aod::v0data::collisionId; using CollisionsRun3 = soa::Join; using CollisionsRun2 = soa::Join; @@ -1390,7 +1383,9 @@ struct LambdaR2Correlation { Configurable cMinRap{"cMinRap", -0.5, "Minimum Rapidity"}; Configurable cMaxRap{"cMaxRap", 0.5, "Maximum Rapidity"}; Configurable cNPhiBins{"cNPhiBins", 36, "N Phi Bins"}; - Configurable cAnaPairs{"cAnaPairs", true, "Analyze Pairs Flag (Not required for efficiency computation)"}; + Configurable cAnaSecondaries{"cAnaSecondaries", false, "Analysze Secondaries"}; + Configurable cAnaPairs{"cAnaPairs", false, "Analyze Pairs Flag"}; + Configurable cAnaSecondaryPairs{"cAnaSecondaryPairs", false, "Analyze Secondary Pairs Flag"}; // Eta/Rap Analysis Configurable cDoEtaAnalysis{"cDoEtaAnalysis", false, "Eta/Rap Analysis Flag"}; @@ -1475,8 +1470,10 @@ struct LambdaR2Correlation { histos.add("Reco/Primary/h3f_n1_pteta_LaP", "#rho_{1}^{#Lambda}", kTH3F, {axisCent, axisPt, axisEta}); histos.add("Reco/Primary/h3f_n1_pteta_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH3F, {axisCent, axisPt, axisEta}); - // Clone Singles Histogram - histos.addClone("Reco/Primary/", "Reco/Secondary/"); + // Clone Singles Primary/Secondary Histogram + if (cAnaSecondaries) { + histos.addClone("Reco/Primary/", "Reco/Secondary/"); + } if (cAnaPairs) { // rho2 for numerator of R2 @@ -1498,9 +1495,11 @@ struct LambdaR2Correlation { histos.add("Reco/PP/h2f_n2_qinv_LaM_LaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTH2F, {axisCent, axisQinv}); // Clone Pairs Histograms - histos.addClone("Reco/PP/", "Reco/PS/"); - histos.addClone("Reco/PP/", "Reco/SP/"); - histos.addClone("Reco/PP/", "Reco/SS/"); + if (cAnaSecondaryPairs) { + histos.addClone("Reco/PP/", "Reco/PS/"); + histos.addClone("Reco/PP/", "Reco/SP/"); + histos.addClone("Reco/PP/", "Reco/SS/"); + } } // MCGen @@ -1625,22 +1624,30 @@ struct LambdaR2Correlation { analyzeSingles(lambdaPrimTracks); analyzeSingles(antiLambdaPrimTracks); - analyzeSingles(lambdaSecdTracks); - analyzeSingles(antiLambdaSecdTracks); + + if (cAnaSecondaries) { + analyzeSingles(lambdaSecdTracks); + analyzeSingles(antiLambdaSecdTracks); + } if (cAnaPairs) { + // Primary Pairs Only analyzePairs(lambdaPrimTracks, antiLambdaPrimTracks); analyzePairs(lambdaPrimTracks, lambdaPrimTracks); analyzePairs(antiLambdaPrimTracks, antiLambdaPrimTracks); - analyzePairs(lambdaPrimTracks, antiLambdaSecdTracks); - analyzePairs(lambdaPrimTracks, lambdaSecdTracks); - analyzePairs(antiLambdaPrimTracks, antiLambdaSecdTracks); - analyzePairs(lambdaSecdTracks, antiLambdaPrimTracks); - analyzePairs(lambdaSecdTracks, lambdaPrimTracks); - analyzePairs(antiLambdaSecdTracks, antiLambdaPrimTracks); - analyzePairs(lambdaSecdTracks, antiLambdaSecdTracks); - analyzePairs(lambdaSecdTracks, lambdaSecdTracks); - analyzePairs(antiLambdaSecdTracks, antiLambdaSecdTracks); + + // Secondary Pairs + if (cAnaSecondaryPairs) { + analyzePairs(lambdaPrimTracks, antiLambdaSecdTracks); + analyzePairs(lambdaPrimTracks, lambdaSecdTracks); + analyzePairs(antiLambdaPrimTracks, antiLambdaSecdTracks); + analyzePairs(lambdaSecdTracks, antiLambdaPrimTracks); + analyzePairs(lambdaSecdTracks, lambdaPrimTracks); + analyzePairs(antiLambdaSecdTracks, antiLambdaPrimTracks); + analyzePairs(lambdaSecdTracks, antiLambdaSecdTracks); + analyzePairs(lambdaSecdTracks, lambdaSecdTracks); + analyzePairs(antiLambdaSecdTracks, antiLambdaSecdTracks); + } } } @@ -1669,22 +1676,30 @@ struct LambdaR2Correlation { analyzeSingles(lambdaPrimTracks); analyzeSingles(antiLambdaPrimTracks); - analyzeSingles(lambdaSecdTracks); - analyzeSingles(antiLambdaSecdTracks); + + if (cAnaSecondaries) { + analyzeSingles(lambdaSecdTracks); + analyzeSingles(antiLambdaSecdTracks); + } if (cAnaPairs) { + // Primary Pairs Only analyzePairs(lambdaPrimTracks, antiLambdaPrimTracks); analyzePairs(lambdaPrimTracks, lambdaPrimTracks); analyzePairs(antiLambdaPrimTracks, antiLambdaPrimTracks); - analyzePairs(lambdaPrimTracks, antiLambdaSecdTracks); - analyzePairs(lambdaPrimTracks, lambdaSecdTracks); - analyzePairs(antiLambdaPrimTracks, antiLambdaSecdTracks); - analyzePairs(lambdaSecdTracks, antiLambdaPrimTracks); - analyzePairs(lambdaSecdTracks, lambdaPrimTracks); - analyzePairs(antiLambdaSecdTracks, antiLambdaPrimTracks); - analyzePairs(lambdaSecdTracks, antiLambdaSecdTracks); - analyzePairs(lambdaSecdTracks, lambdaSecdTracks); - analyzePairs(antiLambdaSecdTracks, antiLambdaSecdTracks); + + // Secondary Pairs + if (cAnaSecondaryPairs) { + analyzePairs(lambdaPrimTracks, antiLambdaSecdTracks); + analyzePairs(lambdaPrimTracks, lambdaSecdTracks); + analyzePairs(antiLambdaPrimTracks, antiLambdaSecdTracks); + analyzePairs(lambdaSecdTracks, antiLambdaPrimTracks); + analyzePairs(lambdaSecdTracks, lambdaPrimTracks); + analyzePairs(antiLambdaSecdTracks, antiLambdaPrimTracks); + analyzePairs(lambdaSecdTracks, antiLambdaSecdTracks); + analyzePairs(lambdaSecdTracks, lambdaSecdTracks); + analyzePairs(antiLambdaSecdTracks, antiLambdaSecdTracks); + } } } diff --git a/PWGDQ/Core/HistogramsLibrary.cxx b/PWGDQ/Core/HistogramsLibrary.cxx index 91e5264c969..7e8be6950a9 100644 --- a/PWGDQ/Core/HistogramsLibrary.cxx +++ b/PWGDQ/Core/HistogramsLibrary.cxx @@ -90,10 +90,10 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "MultFDDA", "MultFDDA", false, 300, 0.0, 300.0, VarManager::kMultFDDA); hm->AddHistogram(histClass, "MultFDDC", "MultFDDC", false, 50, 0.0, 50.0, VarManager::kMultFDDC); hm->AddHistogram(histClass, "MultTracklets", "MultTracklets", false, 250, 0.0, 250.0, VarManager::kMultTracklets); - hm->AddHistogram(histClass, "VtxNContribReal", "Vtx n contributors", false, 200, 0.0, 200.0, VarManager::kVtxNcontribReal); + hm->AddHistogram(histClass, "VtxNContribReal", "Vtx n contributors", false, 150, 0.0, 150.0, VarManager::kVtxNcontribReal); hm->AddHistogram(histClass, "VtxNContrib", "Vtx n contributors", false, 100, 0.0, 100.0, VarManager::kVtxNcontrib); - hm->AddHistogram(histClass, "MultNTracksPVeta1", "MultNTracksPVeta1", false, 200, 0, 200.0, VarManager::kMultNTracksPVeta1); - hm->AddHistogram(histClass, "MultNTracksPVetaHalf", "MultNTracksPVetaHalf", false, 200, 0, 200.0, VarManager::kMultNTracksPVetaHalf); + hm->AddHistogram(histClass, "MultNTracksPVeta1", "MultNTracksPVeta1", false, 150, 0, 150.0, VarManager::kMultNTracksPVeta1); + hm->AddHistogram(histClass, "MultNTracksPVetaHalf", "MultNTracksPVetaHalf", false, 150, 0, 150.0, VarManager::kMultNTracksPVetaHalf); hm->AddHistogram(histClass, "MultTPC_MultFV0A", "MultTPC vs MultFV0A", false, 100, 0, 500.0, VarManager::kMultTPC, 100, 0, 500.0, VarManager::kMultFV0A); hm->AddHistogram(histClass, "MultTPC_MultFT0A", "MultTPC vs MultFT0A", false, 100, 0, 500.0, VarManager::kMultTPC, 100, 0, 200.0, VarManager::kMultFT0A); hm->AddHistogram(histClass, "MultTPC_MultFT0C", "MultTPC vs MultFT0C", false, 100, 0, 500.0, VarManager::kMultTPC, 100, 0, 300.0, VarManager::kMultFT0C); @@ -112,7 +112,9 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "VtxZ_MultTPCWithPV", "VtxZ vs MultTPCWithPV", false, 240, -12.0, 12.0, VarManager::kVtxZ, 400, 0, 400.0, VarManager::kMultNTracksHasTPC); hm->AddHistogram(histClass, "VtxZ_MultITSTPCWithPV", "VtxZ vs MultITSTPCWithPV", false, 240, -12.0, 12.0, VarManager::kVtxZ, 400, 0, 400.0, VarManager::kMultNTracksITSTPC); hm->AddHistogram(histClass, "VtxZ_MultITSOnly", "VtxZ vs MultITSOnly", false, 240, -12.0, 12.0, VarManager::kVtxZ, 400, 0, 400.0, VarManager::kMultNTracksITSOnly); - hm->AddHistogram(histClass, "VtxZ_VtxNcontribReal", "VtxZ vs VtxNcontribReal", false, 240, -12.0, 12.0, VarManager::kVtxZ, 200, 0, 200.0, VarManager::kVtxNcontribReal); + hm->AddHistogram(histClass, "VtxZ_VtxNcontribReal", "VtxZ vs VtxNcontribReal", false, 100, -10.0, 10.0, VarManager::kVtxZ, 150, 0, 150.0, VarManager::kVtxNcontribReal); + hm->AddHistogram(histClass, "VtxZ_MultNTracksPVeta1", "VtxZ vs MultNTracksPVeta1", false, 100, -10.0, 10.0, VarManager::kVtxZ, 150, 0, 150.0, VarManager::kMultNTracksPVeta1); + hm->AddHistogram(histClass, "VtxZ_MultNTracksPVetaHalf", "VtxZ vs MultNTracksPVetaHalf", false, 100, -10.0, 10.0, VarManager::kVtxZ, 150, 0, 150.0, VarManager::kMultNTracksPVetaHalf); } else { hm->AddHistogram(histClass, "MultTPC", "MultTPC", false, 200, 0.0, 50000.0, VarManager::kMultTPC); @@ -938,7 +940,9 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Y_Pt", "", false, 100, -5.0, 5.0, VarManager::kRap, 20, 0.0, 20.0, VarManager::kPt); } if (subGroupStr.Contains("mult_pvcontrib")) { - hm->AddHistogram(histClass, "Mass_VtxNcontribReal", "Mass vs VtxNcontribReal", false, 200, 2.0, 5.0, VarManager::kMass, 200, 0, 200.0, VarManager::kVtxNcontribReal); + hm->AddHistogram(histClass, "Mass_VtxNcontribReal", "Mass vs VtxNcontribReal", false, 200, 2.0, 5.0, VarManager::kMass, 150, 0, 150.0, VarManager::kVtxNcontribReal); + hm->AddHistogram(histClass, "Mass_MultNTracksPVetaHalf", "Mass vs MultNTracksPVetaHalf", false, 200, 2.0, 5.0, VarManager::kMass, 150, 0, 150.0, VarManager::kMultNTracksPVetaHalf); + hm->AddHistogram(histClass, "Mass_MultNTracksPVeta1", "Mass vs MultNTracksPVeta1", false, 200, 2.0, 5.0, VarManager::kMass, 150, 0, 150.0, VarManager::kMultNTracksPVeta1); } if (subGroupStr.Contains("barrel")) { hm->AddHistogram(histClass, "Mass", "", false, 500, 0.0, 5.0, VarManager::kMass); diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 1da8fa30562..3c1437cb5cb 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -1106,15 +1106,19 @@ class VarManager : public TObject // Check whether all the needed objects for TPC postcalibration are available if (fgCalibs.find(kTPCElectronMean) != fgCalibs.end() && fgCalibs.find(kTPCElectronSigma) != fgCalibs.end()) { fgRunTPCPostCalibration[0] = true; + fgUsedVars[kTPCnSigmaEl_Corr] = true; } if (fgCalibs.find(kTPCPionMean) != fgCalibs.end() && fgCalibs.find(kTPCPionSigma) != fgCalibs.end()) { fgRunTPCPostCalibration[1] = true; + fgUsedVars[kTPCnSigmaPi_Corr] = true; } if (fgCalibs.find(kTPCKaonMean) != fgCalibs.end() && fgCalibs.find(kTPCKaonSigma) != fgCalibs.end()) { fgRunTPCPostCalibration[2] = true; + fgUsedVars[kTPCnSigmaKa_Corr] = true; } if (fgCalibs.find(kTPCProtonMean) != fgCalibs.end() && fgCalibs.find(kTPCProtonSigma) != fgCalibs.end()) { fgRunTPCPostCalibration[3] = true; + fgUsedVars[kTPCnSigmaPr_Corr] = true; } } static TObject* GetCalibrationObject(CalibObjects calib) @@ -2376,7 +2380,7 @@ void VarManager::FillTrack(T const& track, float* values) } // Quantities based on the barrel PID tables - if constexpr ((fillMap & TrackPID) > 0 || (fillMap & ReducedTrackBarrelPID) > 0) { + if constexpr ((fillMap & TrackPID) > 0 || (fillMap & TrackTPCPID) > 0 || (fillMap & ReducedTrackBarrelPID) > 0) { values[kTPCnSigmaEl] = track.tpcNSigmaEl(); values[kTPCnSigmaPi] = track.tpcNSigmaPi(); values[kTPCnSigmaKa] = track.tpcNSigmaKa(); @@ -2479,10 +2483,13 @@ void VarManager::FillTrack(T const& track, float* values) values[kTPCnSigmaPr_Corr] = track.tpcNSigmaPr(); } } - values[kTOFnSigmaEl] = track.tofNSigmaEl(); - values[kTOFnSigmaPi] = track.tofNSigmaPi(); - values[kTOFnSigmaKa] = track.tofNSigmaKa(); - values[kTOFnSigmaPr] = track.tofNSigmaPr(); + + if constexpr ((fillMap & TrackPID) > 0 || (fillMap & ReducedTrackBarrelPID) > 0) { + values[kTOFnSigmaEl] = track.tofNSigmaEl(); + values[kTOFnSigmaPi] = track.tofNSigmaPi(); + values[kTOFnSigmaKa] = track.tofNSigmaKa(); + values[kTOFnSigmaPr] = track.tofNSigmaPr(); + } if (fgUsedVars[kTPCsignalRandomized] || fgUsedVars[kTPCnSigmaElRandomized] || fgUsedVars[kTPCnSigmaPiRandomized] || fgUsedVars[kTPCnSigmaPrRandomized]) { // NOTE: this is needed temporarily for the study of the impact of TPC pid degradation on the quarkonium triggers in high lumi pp @@ -2910,7 +2917,7 @@ void VarManager::FillPair(T1 const& t1, T2 const& t2, float* values) ROOT::Math::XYZVector yaxis_PP{(v12.Vect()).Unit()}; ROOT::Math::XYZVector xaxis_PP{(yaxis_PP.Cross(zaxis_PP)).Unit()}; if (fgUsedVars[kCosThetaPP]) { - values[kCosThetaPP] = zaxis_PP.Dot(v_CM); + values[kCosThetaPP] = zaxis_PP.Dot(v_CM) / std::sqrt(zaxis_PP.Mag2()); } if (fgUsedVars[kPhiPP]) { values[kPhiPP] = TMath::ATan2(yaxis_PP.Dot(v_CM), xaxis_PP.Dot(v_CM)); diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx index 9630c8275b5..cb44ae1d935 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx @@ -1507,7 +1507,8 @@ struct AnalysisSameEventPairing { // assign hist directories for pairs matched to MC signals for each (muon cut, MCrec signal) combination if (!sigNamesStr.IsNull()) { - for (auto& sig : fRecMCSignals) { + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { + auto sig = fRecMCSignals.at(isig); names = { Form("PairsMuonSEPM_%s_%s", objArray->At(icut)->GetName(), sig->GetName()), Form("PairsMuonSEPP_%s_%s", objArray->At(icut)->GetName(), sig->GetName()), @@ -1526,9 +1527,9 @@ struct AnalysisSameEventPairing { for (auto& n : names) { histNames += Form("%s;", n.Data()); } + fMuonHistNamesMCmatched.try_emplace(icut * fRecMCSignals.size() + isig, names); } // end loop over MC signals } - fMuonHistNamesMCmatched[icut] = names; } } } // end loop over cuts diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index a58b23fac02..c17a0b3d24c 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -2903,6 +2903,10 @@ struct AnalysisDileptonTrack { Configurable fConfigGRPmagPath{"cfgGrpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; Configurable fConfigMagField{"cfgMagField", 5.0f, "Manually set magnetic field"}; + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; + Configurable fConfigGeoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. int fNCuts; // number of dilepton leg cuts int fNLegCuts; @@ -3152,6 +3156,16 @@ struct AnalysisDileptonTrack { VarManager::SetUseVars(fHistMan->GetUsedVars()); fOutputList.setObject(fHistMan->GetMainHistogramList()); + + fCCDB->setURL(fConfigCcdbUrl.value); + fCCDB->setCaching(true); + fCCDB->setLocalObjectValidityChecking(); + fCCDB->setCreatedNotAfter(fConfigNoLaterThan.value); + if (!o2::base::GeometryManager::isGeometryLoaded()) { + LOG(info) << "Loading geometry from CCDB in dilepton-track task"; + fCCDB->get(fConfigGeoPath); + } + LOG(info) << "Initialization of AnalysisDileptonTrack finished (idstoreh)"; } diff --git a/PWGEM/Dilepton/Core/Dilepton.h b/PWGEM/Dilepton/Core/Dilepton.h index ebe9e26ad50..95bd4a0b6f8 100644 --- a/PWGEM/Dilepton/Core/Dilepton.h +++ b/PWGEM/Dilepton/Core/Dilepton.h @@ -903,6 +903,11 @@ struct Dilepton { if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hMvsPhiV"), phiv, v12.M(), weight); fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hMvsOpAng"), opAng, v12.M(), weight); + if (cfgDCAType == 1) { + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hDCA1vsDCA2"), dcaXYinSigma(t1), dcaXYinSigma(t2), weight); + } else if (cfgDCAType == 2) { + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hDCA1vsDCA2"), dcaZinSigma(t1), dcaZinSigma(t2), weight); + } } } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hs"), v12.M(), v12.Pt(), pair_dca, weight); @@ -910,6 +915,11 @@ struct Dilepton { if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hMvsPhiV"), phiv, v12.M(), weight); fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hMvsOpAng"), opAng, v12.M(), weight); + if (cfgDCAType == 1) { + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hDCA1vsDCA2"), dcaXYinSigma(t1), dcaXYinSigma(t2), weight); + } else if (cfgDCAType == 2) { + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hDCA1vsDCA2"), dcaZinSigma(t1), dcaZinSigma(t2), weight); + } } } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hs"), v12.M(), v12.Pt(), pair_dca, weight); @@ -917,6 +927,11 @@ struct Dilepton { if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hMvsPhiV"), phiv, v12.M(), weight); fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hMvsOpAng"), opAng, v12.M(), weight); + if (cfgDCAType == 1) { + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hDCA1vsDCA2"), dcaXYinSigma(t1), dcaXYinSigma(t2), weight); + } else if (cfgDCAType == 2) { + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hDCA1vsDCA2"), dcaZinSigma(t1), dcaZinSigma(t2), weight); + } } } } else if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kUPC)) { diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index 7ed467c2814..f5f8be20518 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -231,7 +231,7 @@ struct SingleTrackQC { // track info fRegistry.add("Track/positive/hs", "rec. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca}, true); - fRegistry.add("Track/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); + fRegistry.add("Track/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{2000, -5, 5}}, false); fRegistry.add("Track/positive/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {700, -3.5f, 3.5f}}, false); fRegistry.add("Track/positive/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{400, -20.0f, 20.0f}, {400, -20.0f, 20.0f}}, false); fRegistry.add("Track/positive/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); diff --git a/PWGEM/Dilepton/Tasks/createResolutionMap.cxx b/PWGEM/Dilepton/Tasks/createResolutionMap.cxx index 6613f88127d..557c3468be2 100644 --- a/PWGEM/Dilepton/Tasks/createResolutionMap.cxx +++ b/PWGEM/Dilepton/Tasks/createResolutionMap.cxx @@ -68,7 +68,7 @@ struct CreateResolutionMap { Configurable cfgEventGeneratorType{"cfgEventGeneratorType", -1, "if positive, select event generator type. i.e. gap or signal"}; Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; - Configurable cfg_require_true_mc_collision_association{"cfg_require_true_mc_collision_association", true, "flag to require true mc collision association"}; + Configurable cfg_require_true_mc_collision_association{"cfg_require_true_mc_collision_association", false, "flag to require true mc collision association"}; Configurable cfg_reject_fake_match_its_tpc{"cfg_reject_fake_match_its_tpc", false, "flag to reject fake match between ITS-TPC"}; // Configurable cfg_reject_fake_match_its_tpc_tof{"cfg_reject_fake_match_its_tpc_tof", false, "flag to reject fake match between ITS-TPC-TOF"}; Configurable cfg_reject_fake_match_mft_mch{"cfg_reject_fake_match_mft_mch", false, "flag to reject fake match between MFT-MCH"}; @@ -84,6 +84,9 @@ struct CreateResolutionMap { ConfigurableAxis ConfDeltaEtaBins{"ConfDeltaEtaBins", {200, -0.5f, +0.5f}, "deta bins for output histograms"}; ConfigurableAxis ConfDeltaPhiBins{"ConfDeltaPhiBins", {200, -0.5f, +0.5f}, "dphi bins for output histograms"}; + Configurable cfgFillTHnSparse{"cfgFillTHnSparse", true, "fill THnSparse for output"}; + Configurable cfgFillTH2{"cfgFillTH2", false, "fill TH2 for output"}; + Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; Configurable cfgRCTLabelCB{"cfgRCTLabelCB", "CBT_hadronPID", "select 1 [CBT, CBT_hadron] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; Configurable cfgRCTLabelFWDSA{"cfgRCTLabelFWDSA", "CBT_muon", "select 1 [CBT_muon] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; @@ -212,18 +215,22 @@ struct CreateResolutionMap { registry.add("Event/Electron/hImpPar_Centrality", "true imapact parameter vs. estimated centrality;impact parameter (fm);centrality (%)", kTH2F, {{200, 0, 20}, {110, 0, 110}}, true); registry.add("Event/Muon/hImpPar_Centrality", "true imapact parameter vs. estimated centrality;impact parameter (fm);centrality (%)", kTH2F, {{200, 0, 20}, {110, 0, 110}}, true); - registry.add("Electron/hPt", "rec. p_{T,l};p_{T,l} (GeV/c)", kTH1F, {{1000, 0, 10}}, false); - registry.add("Electron/hEtaPhi", "rec. #eta vs. #varphi;#varphi_{l} (rad.);#eta_{l}", kTH2F, {{90, 0, 2 * M_PI}, {100, -5, +5}}, false); - registry.add("Electron/Ptgen_RelDeltaPt", "resolution", kTH2F, {{axis_pt_gen}, {axis_dpt}}, true); - registry.add("Electron/Ptgen_DeltaEta", "resolution", kTH2F, {{axis_pt_gen}, {axis_deta}}, true); - registry.add("Electron/Ptgen_DeltaPhi_Pos", "resolution", kTH2F, {{axis_pt_gen}, {axis_dphi}}, true); - registry.add("Electron/Ptgen_DeltaPhi_Neg", "resolution", kTH2F, {{axis_pt_gen}, {axis_dphi}}, true); - registry.addClone("Electron/", "StandaloneMuon/"); - registry.addClone("Electron/", "GlobalMuon/"); - - registry.add("Electron/hs_reso", "8D resolution positive", kTHnSparseF, {axis_cent, axis_pt_gen, axis_eta_cb_gen, axis_phi_gen, axis_charge_gen, axis_dpt, axis_deta, axis_dphi}, true); - registry.add("StandaloneMuon/hs_reso", "8D resolution positive", kTHnSparseF, {axis_cent, axis_pt_gen, axis_eta_fwd_gen, axis_phi_gen, axis_charge_gen, axis_dpt, axis_deta, axis_dphi}, true); - registry.add("GlobalMuon/hs_reso", "8D resolution positive", kTHnSparseF, {axis_cent, axis_pt_gen, axis_eta_fwd_gen, axis_phi_gen, axis_charge_gen, axis_dpt, axis_deta, axis_dphi}, true); + if (cfgFillTH2) { + registry.add("Electron/hPt", "rec. p_{T,l};p_{T,l} (GeV/c)", kTH1F, {{1000, 0, 10}}, false); + registry.add("Electron/hEtaPhi", "rec. #eta vs. #varphi;#varphi_{l} (rad.);#eta_{l}", kTH2F, {{90, 0, 2 * M_PI}, {100, -5, +5}}, false); + registry.add("Electron/Ptgen_RelDeltaPt", "resolution", kTH2F, {{axis_pt_gen}, {axis_dpt}}, true); + registry.add("Electron/Ptgen_DeltaEta", "resolution", kTH2F, {{axis_pt_gen}, {axis_deta}}, true); + registry.add("Electron/Ptgen_DeltaPhi_Pos", "resolution", kTH2F, {{axis_pt_gen}, {axis_dphi}}, true); + registry.add("Electron/Ptgen_DeltaPhi_Neg", "resolution", kTH2F, {{axis_pt_gen}, {axis_dphi}}, true); + registry.addClone("Electron/", "StandaloneMuon/"); + registry.addClone("Electron/", "GlobalMuon/"); + } + + if (cfgFillTHnSparse) { + registry.add("Electron/hs_reso", "8D resolution", kTHnSparseF, {axis_cent, axis_pt_gen, axis_eta_cb_gen, axis_phi_gen, axis_charge_gen, axis_dpt, axis_deta, axis_dphi}, true); + registry.add("StandaloneMuon/hs_reso", "8D resolution", kTHnSparseF, {axis_cent, axis_pt_gen, axis_eta_fwd_gen, axis_phi_gen, axis_charge_gen, axis_dpt, axis_deta, axis_dphi}, true); + registry.add("GlobalMuon/hs_reso", "8D resolution", kTHnSparseF, {axis_cent, axis_pt_gen, axis_eta_fwd_gen, axis_phi_gen, axis_charge_gen, axis_dpt, axis_deta, axis_dphi}, true); + } } void initCCDB(aod::BCsWithTimestamps::iterator const& bc) @@ -376,8 +383,8 @@ struct CreateResolutionMap { std::pair> itsRequirement_ibany = {1, {0, 1, 2}}; // any hits on 3 ITS ib layers. std::pair> itsRequirement_ib1st = {1, {0}}; // first hit on ITS ib layers. - template - bool isSelectedTrack(TCollision const& collision, TTrack const& track) + template + bool isSelectedTrack(TTrack const& track) { if (!track.hasITS() || !track.hasTPC()) { return false; @@ -425,23 +432,63 @@ struct CreateResolutionMap { return false; } - o2::dataformats::DCA mDcaInfoCov; - mDcaInfoCov.set(999, 999, 999, 999, 999); - auto track_par_cov_recalc = getTrackParCov(track); - track_par_cov_recalc.setPID(o2::track::PID::Electron); - mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); - mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); - o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, track_par_cov_recalc, 2.f, matCorr, &mDcaInfoCov); - float dcaXY = mDcaInfoCov.getY(); - float dcaZ = mDcaInfoCov.getZ(); + return true; + } + + template + bool isSelectedTrackKine(TTrack const& track, const float pt, const float eta, const float dcaXY, const float dcaZ) + { + if (!track.hasITS() || !track.hasTPC()) { + return false; + } + + if (track.tpcChi2NCl() > electroncuts.cfg_max_chi2tpc) { + return false; + } + + if (track.itsChi2NCl() > electroncuts.cfg_max_chi2its) { + return false; + } + + if (track.itsNCls() < electroncuts.cfg_min_ncluster_its) { + return false; + } + if (track.itsNClsInnerBarrel() < electroncuts.cfg_min_ncluster_itsib) { + return false; + } + + auto hits = std::count_if(itsRequirement_ibany.second.begin(), itsRequirement_ibany.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); + if (hits < itsRequirement_ibany.first) { + return false; + } + if (electroncuts.cfg_require_itsib_1st) { + auto hit_ib1st = std::count_if(itsRequirement_ib1st.second.begin(), itsRequirement_ib1st.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); + if (hit_ib1st < itsRequirement_ib1st.first) { + return false; + } + } - // LOGF(info, "collision.globalIndex() = %d, track.collisionId() = %d, track.pt() = %.16f, track_par_cov_recalc.getPt() = %.16f", collision.globalIndex(), track.collisionId(), track.pt(), track_par_cov_recalc.getPt()); + if (track.tpcNClsFound() < electroncuts.cfg_min_ncluster_tpc) { + return false; + } + + if (track.tpcNClsCrossedRows() < electroncuts.cfg_min_ncrossedrows) { + return false; + } + + if (track.tpcCrossedRowsOverFindableCls() < electroncuts.cfg_min_tpc_cr_findable_ratio) { + return false; + } + + if (track.tpcFractionSharedCls() > electroncuts.cfg_max_frac_shared_clusters_tpc) { + return false; + } if (std::fabs(dcaXY) > electroncuts.cfg_max_dcaxy || std::fabs(dcaZ) > electroncuts.cfg_max_dcaz) { return false; } - if (track_par_cov_recalc.getPt() < electroncuts.cfg_min_pt_track || std::fabs(track_par_cov_recalc.getEta()) > electroncuts.cfg_max_eta_track) { + if (pt < electroncuts.cfg_min_pt_track || std::fabs(eta) > electroncuts.cfg_max_eta_track) { return false; } @@ -555,29 +602,38 @@ struct CreateResolutionMap { if (cfgRequireGoodRCT && !rctCheckerFWDSA.checkTable(collision)) { return; } - registry.fill(HIST("StandaloneMuon/hPt"), pt); - registry.fill(HIST("StandaloneMuon/hEtaPhi"), phi, eta); - registry.fill(HIST("StandaloneMuon/hs_reso"), centrality, mcparticle.pt(), mcparticle.eta(), mcparticle.phi(), -mcparticle.pdgCode() / 13, (mcparticle.pt() - pt) / mcparticle.pt(), mcparticle.eta() - eta, mcparticle.phi() - phi); - registry.fill(HIST("StandaloneMuon/Ptgen_RelDeltaPt"), mcparticle.pt(), (mcparticle.pt() - pt) / mcparticle.pt()); - registry.fill(HIST("StandaloneMuon/Ptgen_DeltaEta"), mcparticle.pt(), mcparticle.eta() - eta); - if (mcparticle.pdgCode() == -13) { // positive muon - registry.fill(HIST("StandaloneMuon/Ptgen_DeltaPhi_Pos"), mcparticle.pt(), mcparticle.phi() - phi); - } else if (mcparticle.pdgCode() == 13) { // negative muon - registry.fill(HIST("StandaloneMuon/Ptgen_DeltaPhi_Neg"), mcparticle.pt(), mcparticle.phi() - phi); + if (cfgFillTHnSparse) { + registry.fill(HIST("StandaloneMuon/hs_reso"), centrality, mcparticle.pt(), mcparticle.eta(), mcparticle.phi(), -mcparticle.pdgCode() / 13, (mcparticle.pt() - pt) / mcparticle.pt(), mcparticle.eta() - eta, mcparticle.phi() - phi); + } + + if (cfgFillTH2) { + registry.fill(HIST("StandaloneMuon/hPt"), pt); + registry.fill(HIST("StandaloneMuon/hEtaPhi"), phi, eta); + registry.fill(HIST("StandaloneMuon/Ptgen_RelDeltaPt"), mcparticle.pt(), (mcparticle.pt() - pt) / mcparticle.pt()); + registry.fill(HIST("StandaloneMuon/Ptgen_DeltaEta"), mcparticle.pt(), mcparticle.eta() - eta); + if (mcparticle.pdgCode() == -13) { // positive muon + registry.fill(HIST("StandaloneMuon/Ptgen_DeltaPhi_Pos"), mcparticle.pt(), mcparticle.phi() - phi); + } else if (mcparticle.pdgCode() == 13) { // negative muon + registry.fill(HIST("StandaloneMuon/Ptgen_DeltaPhi_Neg"), mcparticle.pt(), mcparticle.phi() - phi); + } } } else if (muon.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { if (cfgRequireGoodRCT && !rctCheckerFWDGL.checkTable(collision)) { return; } - registry.fill(HIST("GlobalMuon/hPt"), pt); - registry.fill(HIST("GlobalMuon/hEtaPhi"), phi, eta); - registry.fill(HIST("GlobalMuon/hs_reso"), centrality, mcparticle.pt(), mcparticle.eta(), mcparticle.phi(), -mcparticle.pdgCode() / 13, (mcparticle.pt() - pt) / mcparticle.pt(), mcparticle.eta() - eta, mcparticle.phi() - phi); - registry.fill(HIST("GlobalMuon/Ptgen_RelDeltaPt"), mcparticle.pt(), (mcparticle.pt() - pt) / mcparticle.pt()); - registry.fill(HIST("GlobalMuon/Ptgen_DeltaEta"), mcparticle.pt(), mcparticle.eta() - eta); - if (mcparticle.pdgCode() == -13) { // positive muon - registry.fill(HIST("GlobalMuon/Ptgen_DeltaPhi_Pos"), mcparticle.pt(), mcparticle.phi() - phi); - } else if (mcparticle.pdgCode() == 13) { // negative muon - registry.fill(HIST("GlobalMuon/Ptgen_DeltaPhi_Neg"), mcparticle.pt(), mcparticle.phi() - phi); + if (cfgFillTHnSparse) { + registry.fill(HIST("GlobalMuon/hs_reso"), centrality, mcparticle.pt(), mcparticle.eta(), mcparticle.phi(), -mcparticle.pdgCode() / 13, (mcparticle.pt() - pt) / mcparticle.pt(), mcparticle.eta() - eta, mcparticle.phi() - phi); + } + if (cfgFillTH2) { + registry.fill(HIST("GlobalMuon/hPt"), pt); + registry.fill(HIST("GlobalMuon/hEtaPhi"), phi, eta); + registry.fill(HIST("GlobalMuon/Ptgen_RelDeltaPt"), mcparticle.pt(), (mcparticle.pt() - pt) / mcparticle.pt()); + registry.fill(HIST("GlobalMuon/Ptgen_DeltaEta"), mcparticle.pt(), mcparticle.eta() - eta); + if (mcparticle.pdgCode() == -13) { // positive muon + registry.fill(HIST("GlobalMuon/Ptgen_DeltaPhi_Pos"), mcparticle.pt(), mcparticle.phi() - phi); + } else if (mcparticle.pdgCode() == 13) { // negative muon + registry.fill(HIST("GlobalMuon/Ptgen_DeltaPhi_Neg"), mcparticle.pt(), mcparticle.phi() - phi); + } } } return; @@ -655,7 +711,8 @@ struct CreateResolutionMap { if (cfg_require_true_mc_collision_association && mcparticle.mcCollisionId() != collision.mcCollisionId()) { return; } - if (!isSelectedTrack(collision, track)) { + + if (!isSelectedTrack(track)) { return; } @@ -666,23 +723,31 @@ struct CreateResolutionMap { mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, track_par_cov_recalc, 2.f, matCorr, &mDcaInfoCov); - // float dcaXY = mDcaInfoCov.getY(); - // float dcaZ = mDcaInfoCov.getZ(); + float dcaXY = mDcaInfoCov.getY(); + float dcaZ = mDcaInfoCov.getZ(); float pt = track_par_cov_recalc.getPt(); float eta = track_par_cov_recalc.getEta(); float phi = track_par_cov_recalc.getPhi(); o2::math_utils::bringTo02Pi(phi); - registry.fill(HIST("Electron/hPt"), pt); - registry.fill(HIST("Electron/hEtaPhi"), phi, eta); - registry.fill(HIST("Electron/hs_reso"), centrality, mcparticle.pt(), mcparticle.eta(), mcparticle.phi(), -mcparticle.pdgCode() / 11, (mcparticle.pt() - pt) / mcparticle.pt(), mcparticle.eta() - eta, mcparticle.phi() - phi); - registry.fill(HIST("Electron/Ptgen_RelDeltaPt"), mcparticle.pt(), (mcparticle.pt() - pt) / mcparticle.pt()); - registry.fill(HIST("Electron/Ptgen_DeltaEta"), mcparticle.pt(), mcparticle.eta() - eta); - if (mcparticle.pdgCode() == -11) { // positron - registry.fill(HIST("Electron/Ptgen_DeltaPhi_Pos"), mcparticle.pt(), mcparticle.phi() - phi); - } else if (mcparticle.pdgCode() == 11) { // electron - registry.fill(HIST("Electron/Ptgen_DeltaPhi_Neg"), mcparticle.pt(), mcparticle.phi() - phi); + if (!isSelectedTrackKine(track, pt, eta, dcaXY, dcaZ)) { + return; + } + + if (cfgFillTHnSparse) { + registry.fill(HIST("Electron/hs_reso"), centrality, mcparticle.pt(), mcparticle.eta(), mcparticle.phi(), -mcparticle.pdgCode() / 11, (mcparticle.pt() - pt) / mcparticle.pt(), mcparticle.eta() - eta, mcparticle.phi() - phi); + } + if (cfgFillTH2) { + registry.fill(HIST("Electron/hPt"), pt); + registry.fill(HIST("Electron/hEtaPhi"), phi, eta); + registry.fill(HIST("Electron/Ptgen_RelDeltaPt"), mcparticle.pt(), (mcparticle.pt() - pt) / mcparticle.pt()); + registry.fill(HIST("Electron/Ptgen_DeltaEta"), mcparticle.pt(), mcparticle.eta() - eta); + if (mcparticle.pdgCode() == -11) { // positron + registry.fill(HIST("Electron/Ptgen_DeltaPhi_Pos"), mcparticle.pt(), mcparticle.phi() - phi); + } else if (mcparticle.pdgCode() == 11) { // electron + registry.fill(HIST("Electron/Ptgen_DeltaPhi_Neg"), mcparticle.pt(), mcparticle.phi() - phi); + } } } diff --git a/PWGEM/PhotonMeson/TableProducer/createPCM.cxx b/PWGEM/PhotonMeson/TableProducer/createPCM.cxx index f8ba87d2cbc..4ca74633e1b 100644 --- a/PWGEM/PhotonMeson/TableProducer/createPCM.cxx +++ b/PWGEM/PhotonMeson/TableProducer/createPCM.cxx @@ -554,15 +554,8 @@ struct createPCM { PROCESS_SWITCH(createPCM, processTrkCollAsso, "create V0s with track-to-collision associator", false); }; -// Extends the v0data table with expression columns -struct v0Initializer { - Spawns v0cores; - void init(InitContext const&) {} -}; - WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc, TaskName{"v0-finder"}), - adaptAnalysisTask(cfgc, TaskName{"v0-initializer"})}; + adaptAnalysisTask(cfgc, TaskName{"v0-finder"})}; } diff --git a/PWGHF/Core/DecayChannels.h b/PWGHF/Core/DecayChannels.h new file mode 100644 index 00000000000..f56e8ce1005 --- /dev/null +++ b/PWGHF/Core/DecayChannels.h @@ -0,0 +1,180 @@ +// 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. + +/// \file DecayChannels.h +/// \brief Definitions of constants for MC flagging of HF decay channels. +/// \author Vít Kučera , Inha University +/// \note DecayChannelMain enums define unique combinations of the mother and the daughters for main channels. +/// \note DecayChannelResonant enums define unique combinations of the mother and the daughters for resonant channels. +/// \note Value 0 is reserved to indicate no match. +/// \note Daughter ordering convention: (charm|strange|π±|K±|π0), (baryon|meson), (+|−) + +#ifndef PWGHF_CORE_DECAYCHANNELS_H_ +#define PWGHF_CORE_DECAYCHANNELS_H_ + +#include + +namespace o2::hf_decay +{ + +// TODO +// - HF cascades (Λc+ → p K0short) +// - HF cascades to LF cascades (Ωc0/Ξc0 → Ξ+ π−, Ξc+ → Ξ+ π− π+) +// - Σc + +namespace hf_cand_2prong +{ +/// @brief 2-prong candidates: main channels +enum DecayChannelMain : int8_t { + // D0 + D0ToPiK = 1, // π+ K− + D0ToPiKPi0, // π+ K− π0 + D0ToPiPi, // π+ π− + D0ToPiPiPi0, // π+ π− π0 + D0ToKK, // K+ K− + // + LastChannelMain +}; +/// @brief 2-prong candidates: resonant channels +enum DecayChannelResonant : int8_t { + // D0 + D0ToRhoplusPi = 1, // ρ+ π− + D0ToRhoplusK, // ρ+ K− + D0ToKstar0Pi0, // anti-K*0 π0 + D0ToKstarPi, // K*− π+ + // + LastChannelResonant +}; +} // namespace hf_cand_2prong + +namespace hf_cand_3prong +{ +/// @brief 3-prong candidates: main channels +enum DecayChannelMain : int8_t { + // D+ + DplusToPiKPi = 1, // π+ K− π+ + DplusToPiKPiPi0, // π+ K− π+ π0 + DplusToPiPiPi, // π+ π− π+ + DplusToPiKK, // π+ K− K+ + // Ds+ + DsToPiKK, // π+ K− K+ + DsToPiKKPi0, // π+ K− K+ π0 + DsToPiPiK, // π+ π− K+ + DsToPiPiPi, // π+ π− π+ + DsToPiPiPiPi0, // π+ π− π+ π0 + // D*+ + DstarToPiKPi, // π+ K− π+ (from [(D0 → π+ K−) π+]) + // Λc+ + LcToPKPi, // p K− π+ + LcToPKPiPi0, // p K− π+ π0 + LcToPPiPi, // p π− π+ + LcToPKK, // p K− K+ + // Ξc+ + XicToPKPi, // p K− π+ + XicToPKK, // p K− K+ + XicToSPiPi, // Σ+ π− π+ + // + LastChannelMain +}; +/// @brief 3-prong candidates: resonant channels +enum DecayChannelResonant : int8_t { + // D+ + DplusToPhiPi = 1, // φ π+ + DplusToKstar0K, // anti-K*0 K+ + DplusToKstar1430_0K, // anti-K*0(1430) K+ + DplusToRho0Pi, // ρ0 π+ + DplusToF2_1270Pi, // f2(1270) π+ + // Ds+ + DsToPhiPi, // φ π+ + DsToPhiRhoplus, // φ ρ+ + DsToKstar0K, // anti-K*0 K+ + DsToKstar0Pi, // anti-K*0 π+ + DsToRho0Pi, // ρ0 π+ + DsToRho0K, // ρ0 K+ + DsToF2_1270Pi, // f2(1270) π+ + DsToF0_1370K, // f0(1370) K+ + DsToEtaPi, // η π+ + // Λc+ + LcToPKstar0, // p K*0(892) + LcToDeltaplusplusK, // Δ++ K− + LcToL1520Pi, // Λ(1520) π+ + // Ξc+ + XicToPKstar0, // p anti-K*0(892) + XicToPPhi, // p φ + // + LastChannelResonant +}; +} // namespace hf_cand_3prong + +namespace hf_cand_dstar +{ +/// @brief D*+ candidates: main channels +enum DecayChannelMain : int8_t { + // D*+ + DstarToPiKPi = 1, // π+ K− π+ (from [(D0 → π+ K−) π+]) + DstarToPiKPiPi0, // π+ K− π+ π0 (from [(D0 → π+ K− π0) π+] or [(D+ → π+ K− π+) π0]) + // + LastChannelMain +}; +} // namespace hf_cand_dstar + +namespace hf_cand_beauty +{ +/// @brief beauty candidates: main channels +enum DecayChannelMain : int8_t { + // B0 + B0ToDminusPi = 1, // D− π+ + B0ToDminusPiPi0, // D− π+ π0 + B0ToDminusPiGamma, // D− π+ γ0 + B0ToDminusK, // D− K+ + B0ToD0PiPi, // anti-D0 π+ π− + // Bs0 + BsToDsPi, // Ds− π+ + BsToDsPiPi0, // Ds− π+ π0 + BsToDsPiGamma, // Ds− π+ γ0 + BsToDsK, // Ds− K+ + // Λb0 + LbToLcPi, // Λc+ π− + LbToLcPiPi0, // Λc+ π− π0 + LbToLcPiGamma, // Λc+ π− γ0 + LbToLcK, // Λc+ K− + LbToLcKPi0, // Λc+ K− π0 + // B+ + BplusToD0Pi, // anti-D0 π+ + BplusToD0PiPi0, // anti-D0 π+ π0 + BplusToD0PiGamma, // anti-D0 π+ γ0 + BplusToD0K, // anti-D0 K+ + // + LastChannelMain +}; +/// @brief beauty candidates: resonant channels +enum DecayChannelResonant : int8_t { + // B0 + B0ToDminusRhoplus = 1, // D− ρ+ + B0ToDstarminusPi, // D*− π+ + // Bs0 + BsToDsRhoplus, // Ds− ρ+ + BsToDsstarPi, // Ds*− π+ + // Λb0 + LbToLcRhoplus, // Λc+ ρ− + LbToScPi, // Σc+ π− + LbToScK, // Σc+ K− + LbToSc0Pi0, // Σc0 π0 + // B+ + BplusToD0Rhoplus, // anti-D0 ρ+ + BplusToDstar0Pi, // anti-D*0 π+ + // + LastChannelResonant +}; +} // namespace hf_cand_beauty +} // namespace o2::hf_decay + +#endif // PWGHF_CORE_DECAYCHANNELS_H_ diff --git a/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx b/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx index 43b75756959..95cefe1ff0f 100644 --- a/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx +++ b/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx @@ -1086,8 +1086,8 @@ struct TaskPolarisationCharmHadrons { bool partRecoDstar{false}; if constexpr (doMc) { if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { - partRecoDstar = TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_dstar::DecayType::DstarToD0PiPi0) && TESTBIT(std::abs(candidate.flagMcMatchRecD0()), aod::hf_cand_dstar::DecayType::D0ToPiKPi0); - bool signalDstar = TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_dstar::DecayType::DstarToD0Pi) && TESTBIT(std::abs(candidate.flagMcMatchRecD0()), aod::hf_cand_dstar::DecayType::D0ToPiK); + partRecoDstar = std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPiPi0 && std::abs(candidate.flagMcMatchRecD0()) == hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiKPi0; + bool signalDstar = std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi && std::abs(candidate.flagMcMatchRecD0()) == hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; if (!signalDstar && (!partRecoDstar || !activatePartRecoDstar)) { // this candidate is not signal and not partially reconstructed signal, skip return isCandidateInSignalRegion; } @@ -1099,8 +1099,8 @@ struct TaskPolarisationCharmHadrons { return isCandidateInSignalRegion; } } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { - if constexpr (!studyLcPKPiBkgMc) { // skip this if studyLcPKPiBkgMc is true, since we are interested in background - if (!TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_3prong::DecayType::LcToPKPi)) { // this candidate is not signal, skip + if constexpr (!studyLcPKPiBkgMc) { // skip this if studyLcPKPiBkgMc is true, since we are interested in background + if (std::abs(candidate.flagMcMatchRec()) != hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { // this candidate is not signal, skip return isCandidateInSignalRegion; } origin = candidate.originMcRec(); @@ -1501,7 +1501,7 @@ struct TaskPolarisationCharmHadrons { /// check if the pKpi triplet is a Lc->pKpi int8_t isRealLcPKPi = 0; - if (isRealPKPi && TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_3prong::DecayType::LcToPKPi)) { + if (isRealPKPi && (std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi)) { isRealLcPKPi = 1; } @@ -1607,8 +1607,8 @@ struct TaskPolarisationCharmHadrons { int8_t charge = -99; bool partRecoDstar{false}; if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { - partRecoDstar = TESTBIT(std::abs(mcParticle.flagMcMatchGen()), aod::hf_cand_dstar::DecayType::DstarToD0PiPi0) && TESTBIT(std::abs(mcParticle.flagMcMatchGenD0()), aod::hf_cand_dstar::DecayType::D0ToPiKPi0); - bool signalDstar = TESTBIT(std::abs(mcParticle.flagMcMatchGen()), aod::hf_cand_dstar::DecayType::DstarToD0Pi) && TESTBIT(std::abs(mcParticle.flagMcMatchGenD0()), aod::hf_cand_dstar::DecayType::D0ToPiK); + partRecoDstar = TESTBIT(std::abs(mcParticle.flagMcMatchGen()), hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPiPi0) && TESTBIT(std::abs(mcParticle.flagMcMatchGenD0()), hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiKPi0); + bool signalDstar = TESTBIT(std::abs(mcParticle.flagMcMatchGen()), hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi) && TESTBIT(std::abs(mcParticle.flagMcMatchGenD0()), hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); if (!signalDstar && (!activatePartRecoDstar || !partRecoDstar)) { // this particle is not signal and not partially reconstructed signal, skip return; @@ -1629,7 +1629,7 @@ struct TaskPolarisationCharmHadrons { massDau = massPi; massCharmHad = massDstar; } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { - if (!TESTBIT(std::abs(mcParticle.flagMcMatchGen()), aod::hf_cand_3prong::DecayType::LcToPKPi)) { // this particle is not signal, skip + if (std::abs(mcParticle.flagMcMatchGen()) != hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { // this particle is not signal, skip return; } origin = mcParticle.originMcGen(); diff --git a/PWGHF/D2H/Tasks/taskDplus.cxx b/PWGHF/D2H/Tasks/taskDplus.cxx index ccbb6a2bd90..cbf6118ce68 100644 --- a/PWGHF/D2H/Tasks/taskDplus.cxx +++ b/PWGHF/D2H/Tasks/taskDplus.cxx @@ -74,12 +74,12 @@ struct HfTaskDplus { Partition selectedDPlusCandidatesWithMl = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; // Matched MC - Partition recoDPlusCandidates = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; - Partition recoDPlusCandidatesWithMl = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; + Partition recoDPlusCandidates = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; + Partition recoDPlusCandidatesWithMl = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; // MC Bkg - Partition recoBkgCandidates = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; - Partition recoBkgCandidatesWithMl = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; + Partition recoBkgCandidates = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; + Partition recoBkgCandidatesWithMl = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; ConfigurableAxis thnConfigAxisY{"thnConfigAxisY", {40, -1, 1}, "Cand. rapidity bins"}; ConfigurableAxis thnConfigAxisCent{"thnConfigAxisCent", {110, 0., 110.}, ""}; @@ -569,7 +569,7 @@ struct HfTaskDplus { ptGenB = -1; flagGenB = -1; auto yGen = RecoDecay::y(particle.pVector(), o2::constants::physics::MassDPlus); - if ((yCandGenMax >= 0. && std::abs(yGen) > yCandGenMax) || (std::abs(particle.flagMcMatchGen()) != 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { + if ((yCandGenMax >= 0. && std::abs(yGen) > yCandGenMax) || (std::abs(particle.flagMcMatchGen()) != hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) { continue; } if (particle.originMcGen() == RecoDecay::OriginType::NonPrompt) { diff --git a/PWGHF/D2H/Tasks/taskDs.cxx b/PWGHF/D2H/Tasks/taskDs.cxx index f8d848e596f..2b94c93f6b8 100644 --- a/PWGHF/D2H/Tasks/taskDs.cxx +++ b/PWGHF/D2H/Tasks/taskDs.cxx @@ -57,6 +57,19 @@ enum DataType { Data = 0, McBkg, kDataTypes }; +enum Mother : int8_t { + Ds, + Dplus +}; + +enum ResonantChannel : int8_t { + PhiPi = 1, + Kstar0K = 2 +}; + +static std::unordered_map> channelsResonant = {{{Mother::Ds, {{ResonantChannel::PhiPi, hf_decay::hf_cand_3prong::DecayChannelResonant::DsToPhiPi}, {ResonantChannel::Kstar0K, hf_decay::hf_cand_3prong::DecayChannelResonant::DsToKstar0K}}}, + {Mother::Dplus, {{ResonantChannel::PhiPi, hf_decay::hf_cand_3prong::DecayChannelResonant::DplusToPhiPi}, {ResonantChannel::Kstar0K, hf_decay::hf_cand_3prong::DecayChannelResonant::DplusToKstar0K}}}}}; + template concept hasDsMlInfo = requires(T candidate) { candidate.mlProbDsToKKPi(); @@ -66,7 +79,7 @@ concept hasDsMlInfo = requires(T candidate) { /// Ds± analysis task struct HfTaskDs { - Configurable decayChannel{"decayChannel", 1, "Switch between decay channels: 1 for Ds/Dplus->PhiPi->KKpi, 2 for Ds/Dplus->K0*K->KKPi"}; + Configurable decayChannel{"decayChannel", 1, "Switch between resonant decay channels: 1 for Ds/Dplus->PhiPi->KKpi, 2 for Ds/Dplus->K0*K->KKPi"}; Configurable fillDplusMc{"fillDplusMc", true, "Switch to fill Dplus MC information"}; Configurable selectionFlagDs{"selectionFlagDs", 7, "Selection Flag for Ds"}; Configurable> classMl{"classMl", {0, 2, 3}, "Indexes of ML scores to be stored. Three indexes max."}; @@ -128,7 +141,6 @@ struct HfTaskDs { ConfigurableAxis axisCentrality{"axisCentrality", {100, 0., 1.}, "axis for centrality/multiplicity"}; ConfigurableAxis axisOccupancy{"axisOccupancy", {14, 0., 14000.}, "axis for occupancy"}; - int offsetDplusDecayChannel = aod::hf_cand_3prong::DecayChannelDToKKPi::DplusToPhiPi - aod::hf_cand_3prong::DecayChannelDToKKPi::DsToPhiPi; // Offset between Dplus and Ds to use the same decay channel. See aod::hf_cand_3prong::DecayChannelDToKKPi int mRunNumber{0}; bool lCalibLoaded; TList* lCalibObjects; @@ -162,6 +174,10 @@ struct HfTaskDs { LOGP(fatal, "No process function enabled"); } + if (decayChannel != ResonantChannel::PhiPi && decayChannel != ResonantChannel::Kstar0K) { + LOGP(fatal, "Invalid value of decayChannel"); + } + AxisSpec ptbins{axisPt, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec ptBHad{axisPtBHad, "#it{p}_{T}(B) (GeV/#it{c})"}; AxisSpec flagBHad{axisFlagBHad, "B Hadron flag"}; @@ -272,37 +288,37 @@ struct HfTaskDs { template bool isDsPrompt(const CandDs& candidate) { - return std::abs(candidate.flagMcMatchRec()) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)) && candidate.flagMcDecayChanRec() == decayChannel && candidate.originMcRec() == RecoDecay::OriginType::Prompt; + return std::abs(candidate.flagMcMatchRec()) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && candidate.flagMcDecayChanRec() == channelsResonant[Mother::Ds][decayChannel] && candidate.originMcRec() == RecoDecay::OriginType::Prompt; } template bool isDplusPrompt(const CandDs& candidate) { - return std::abs(candidate.flagMcMatchRec()) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)) && candidate.flagMcDecayChanRec() == decayChannel + offsetDplusDecayChannel && candidate.originMcRec() == RecoDecay::OriginType::Prompt; + return std::abs(candidate.flagMcMatchRec()) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK) && candidate.flagMcDecayChanRec() == channelsResonant[Mother::Dplus][decayChannel] && candidate.originMcRec() == RecoDecay::OriginType::Prompt; } template bool isDsNonPrompt(const CandDs& candidate) { - return std::abs(candidate.flagMcMatchRec()) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)) && candidate.flagMcDecayChanRec() == decayChannel && candidate.originMcRec() == RecoDecay::OriginType::NonPrompt; + return std::abs(candidate.flagMcMatchRec()) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && candidate.flagMcDecayChanRec() == channelsResonant[Mother::Ds][decayChannel] && candidate.originMcRec() == RecoDecay::OriginType::NonPrompt; } template bool isDplusNonPrompt(const CandDs& candidate) { - return std::abs(candidate.flagMcMatchRec()) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)) && candidate.flagMcDecayChanRec() == decayChannel + offsetDplusDecayChannel && candidate.originMcRec() == RecoDecay::OriginType::NonPrompt; + return std::abs(candidate.flagMcMatchRec()) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK) && candidate.flagMcDecayChanRec() == channelsResonant[Mother::Dplus][decayChannel] && candidate.originMcRec() == RecoDecay::OriginType::NonPrompt; } template bool isDplusBkg(const CandDs& candidate) { - return std::abs(candidate.flagMcMatchRec()) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)); + return std::abs(candidate.flagMcMatchRec()) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); } template bool isLcBkg(const CandDs& candidate) { - return std::abs(candidate.flagMcMatchRec()) == static_cast(BIT(aod::hf_cand_3prong::DecayType::LcToPKPi)); + return std::abs(candidate.flagMcMatchRec()) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); } /// Checks whether the candidate is in the signal region of either the Ds or D+ decay @@ -673,9 +689,9 @@ struct HfTaskDs { // MC gen. for (const auto& particle : mcParticles) { - if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) { + if (std::abs(particle.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK || std::abs(particle.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK) { const auto& recoCollsPerMcColl = recoCollisions.sliceBy(colPerMcCollision, particle.mcCollision().globalIndex()); - if (particle.flagMcDecayChanGen() == decayChannel || (fillDplusMc && particle.flagMcDecayChanGen() == (decayChannel + offsetDplusDecayChannel))) { + if (particle.flagMcDecayChanGen() == channelsResonant[Mother::Ds][decayChannel] || (fillDplusMc && particle.flagMcDecayChanGen() == channelsResonant[Mother::Dplus][decayChannel])) { auto pt = particle.pt(); double y{0.f}; @@ -689,7 +705,7 @@ struct HfTaskDs { occ = o2::hf_occupancy::getOccupancyGenColl(recoCollsPerMcColl, occEstimator); } - if (particle.flagMcDecayChanGen() == decayChannel) { + if (particle.flagMcDecayChanGen() == channelsResonant[Mother::Ds][decayChannel]) { y = RecoDecay::y(particle.pVector(), o2::constants::physics::MassDS); if (yCandGenMax >= 0. && std::abs(y) > yCandGenMax) { continue; diff --git a/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx b/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx index eaadbab783c..0682c0584aa 100644 --- a/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx +++ b/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx @@ -313,8 +313,8 @@ struct HfTaskDstarToD0Pi { continue; } auto collision = candDstarMcRec.template collision_as(); - auto centrality = collision.centFT0M(); // 0-100% - if (TESTBIT(std::abs(candDstarMcRec.flagMcMatchRec()), aod::hf_cand_dstar::DecayType::DstarToD0Pi)) { // if MC matching is successful at Reconstruction Level + auto centrality = collision.centFT0M(); // 0-100% + if (std::abs(candDstarMcRec.flagMcMatchRec()) == hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi) { // if MC matching is successful at Reconstruction Level // LOGF(info, "MC Rec Dstar loop MC Matched"); // get MC Mother particle auto prong0 = candDstarMcRec.template prong0_as(); @@ -392,7 +392,7 @@ struct HfTaskDstarToD0Pi { { // MC Gen level for (auto const& mcParticle : rowsMcPartilces) { - if (TESTBIT(std::abs(mcParticle.flagMcMatchGen()), aod::hf_cand_dstar::DecayType::DstarToD0Pi)) { // MC Matching is successful at Generator Level + if (std::abs(mcParticle.flagMcMatchGen()) == hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi) { // MC Matching is successful at Generator Level auto ptGen = mcParticle.pt(); auto yGen = RecoDecay::y(mcParticle.pVector(), o2::constants::physics::MassDStar); if (yCandDstarGenMax >= 0. && std::abs(yGen) > yCandDstarGenMax) { diff --git a/PWGHF/D2H/Tasks/taskLc.cxx b/PWGHF/D2H/Tasks/taskLc.cxx index eca9a4a2672..cf3c070e6b7 100644 --- a/PWGHF/D2H/Tasks/taskLc.cxx +++ b/PWGHF/D2H/Tasks/taskLc.cxx @@ -376,7 +376,7 @@ struct HfTaskLc { continue; } - if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::LcToPKPi) { + if (std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { // Get the corresponding MC particle. auto mcParticleProng0 = candidate.template prong0_as().template mcParticle_as>(); auto pdgCodeProng0 = std::abs(mcParticleProng0.pdgCode()); @@ -589,7 +589,7 @@ struct HfTaskLc { { // MC gen. for (const auto& particle : mcParticles) { - if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::LcToPKPi) { + if (std::abs(particle.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { auto yGen = RecoDecay::y(particle.pVector(), o2::constants::physics::MassLambdaCPlus); if (yCandGenMax >= 0. && std::abs(yGen) > yCandGenMax) { continue; diff --git a/PWGHF/D2H/Tasks/taskSigmac.cxx b/PWGHF/D2H/Tasks/taskSigmac.cxx index 39011a4a44d..dff39af4c28 100644 --- a/PWGHF/D2H/Tasks/taskSigmac.cxx +++ b/PWGHF/D2H/Tasks/taskSigmac.cxx @@ -726,13 +726,13 @@ struct HfTaskSigmac { /// loop over Lc generated particles for (const auto& particle : mcParticlesLc) { - if (std::abs(particle.flagMcMatchGen()) != BIT(aod::hf_cand_3prong::DecayType::LcToPKPi)) { + if (std::abs(particle.flagMcMatchGen()) != hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { continue; } if (yCandGenMax >= 0. && std::abs(RecoDecay::y(particle.pVector(), o2::constants::physics::MassLambdaCPlus)) > yCandGenMax) { continue; } - double ptGenLc(-1.), ptGenLcBMother(-1.); + double ptGenLc(particle.pt()), ptGenLcBMother(-1.); int origin = particle.originMcGen(); int channel = particle.flagMcDecayChanGen(); if (origin == RecoDecay::OriginType::Prompt) { @@ -1149,7 +1149,7 @@ struct HfTaskSigmac { if (enableTHn) { /// loop over Λc+ candidates w/o Σc0,++ mass-window cut for (const auto& candidateLc : candidatesLc) { - if (!TESTBIT(std::abs(candidateLc.flagMcMatchRec()), aod::hf_cand_3prong::DecayType::LcToPKPi)) { + if (std::abs(candidateLc.flagMcMatchRec()) != hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { continue; } double massLc(-1.); diff --git a/PWGHF/D2H/Tasks/taskXic.cxx b/PWGHF/D2H/Tasks/taskXic.cxx index d2dc111d826..5c338f8b957 100644 --- a/PWGHF/D2H/Tasks/taskXic.cxx +++ b/PWGHF/D2H/Tasks/taskXic.cxx @@ -429,7 +429,7 @@ struct HfTaskXic { massXicToPiKP = hfHelper.invMassXicToPiKP(candidate); // mass conjugate } - if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::XicToPKPi) { + if (std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi) { // Get the corresponding MC particle. auto mcParticleProng0 = candidate.template prong0_as().template mcParticle_as>(); auto pdgCodeProng0 = std::abs(mcParticleProng0.pdgCode()); @@ -572,7 +572,7 @@ struct HfTaskXic { // MC gen. for (const auto& particle : mcParticles) { - if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::XicToPKPi) { + if (std::abs(particle.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi) { auto yGen = RecoDecay::y(particle.pVector(), o2::constants::physics::MassXiCPlus); if (yCandGenMax >= 0. && std::abs(yGen) > yCandGenMax) { continue; diff --git a/PWGHF/DataModel/CandidateReconstructionTables.h b/PWGHF/DataModel/CandidateReconstructionTables.h index 1f4e94b0e83..014bfa3e32e 100644 --- a/PWGHF/DataModel/CandidateReconstructionTables.h +++ b/PWGHF/DataModel/CandidateReconstructionTables.h @@ -35,6 +35,7 @@ #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGHF/Utils/utilsPid.h" +#include "PWGHF/Core/DecayChannels.h" // FIXME: temporary until propagated where needed namespace o2::aod { diff --git a/PWGHF/HFC/TableProducer/correlatorDplusDminus.cxx b/PWGHF/HFC/TableProducer/correlatorDplusDminus.cxx index e6f40634641..3cbee2b072a 100644 --- a/PWGHF/HFC/TableProducer/correlatorDplusDminus.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDplusDminus.cxx @@ -298,7 +298,7 @@ struct HfCorrelatorDplusDminus { if (outerSecondTrack.sign() == 1) { outerParticleSign = -1; // Dminus (second daughter track is positive) } - if (std::abs(candidate1.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi) { + if (std::abs(candidate1.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) { // fill invariant mass plots and per-candidate distributions from Dplus/Dminus signal candidates if (outerParticleSign == 1) { // reco and matched as Dplus registry.fill(HIST("hMassDplusMCRecSig"), hfHelper.invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); @@ -326,7 +326,7 @@ struct HfCorrelatorDplusDminus { if (outerParticleSign == -1) { continue; // reject Dminus in outer loop } - flagDplusSignal = std::abs(candidate1.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi; // flagDplusSignal 'true' if candidate1 matched to Dplus + flagDplusSignal = std::abs(candidate1.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi; // flagDplusSignal 'true' if candidate1 matched to Dplus for (const auto& candidate2 : selectedDPlusCandidatesGroupedMC) { if (!(candidate2.hfflag() & 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { // check decay channel flag for candidate2 continue; @@ -335,7 +335,7 @@ struct HfCorrelatorDplusDminus { if (innerSecondTrack.sign() != 1) { // keep only Dminus (with second daughter track positive) continue; } - flagDminusSignal = std::abs(candidate2.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi; // flagDminusSignal 'true' if candidate2 matched to Dminus + flagDminusSignal = std::abs(candidate2.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi; // flagDminusSignal 'true' if candidate2 matched to Dminus if (yCandMax >= 0. && std::abs(hfHelper.yDplus(candidate2)) > yCandMax) { continue; } @@ -428,7 +428,7 @@ struct HfCorrelatorDplusDminus { // fill pairs vs etaCut plot bool rightDecayChannels = false; - if ((std::abs(particle1.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi) && (std::abs(particle2.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { + if ((std::abs(particle1.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && (std::abs(particle2.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) { rightDecayChannels = true; } do { diff --git a/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx index d40daca5410..a1a8941779b 100644 --- a/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx @@ -422,7 +422,7 @@ struct HfCorrelatorDplusHadrons { efficiencyWeightD = 1. / efficiencyD->at(effBinD); } // Dplus flag - isDplusSignal = TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_3prong::DecayType::DplusToPiKPi); + isDplusSignal = std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi; // prompt and non-prompt division isDplusPrompt = candidate.originMcRec() == RecoDecay::OriginType::Prompt; isDplusNonPrompt = candidate.originMcRec() == RecoDecay::OriginType::NonPrompt; @@ -531,7 +531,7 @@ struct HfCorrelatorDplusHadrons { if (std::abs(particle1.pdgCode()) != Pdg::kDPlus) { continue; } - if (!TESTBIT(std::abs(particle1.flagMcMatchGen()), aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { + if (std::abs(particle1.flagMcMatchGen()) != hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) { continue; } double yD = RecoDecay::y(particle1.pVector(), MassDPlus); @@ -637,7 +637,7 @@ struct HfCorrelatorDplusHadrons { continue; } // Dplus flag - bool isDplusSignal = TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_3prong::DecayType::DplusToPiKPi); + bool isDplusSignal = std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi; // prompt and non-prompt division bool isDplusPrompt = candidate.originMcRec() == RecoDecay::OriginType::Prompt; bool isDplusNonPrompt = candidate.originMcRec() == RecoDecay::OriginType::NonPrompt; @@ -675,7 +675,7 @@ struct HfCorrelatorDplusHadrons { std::vector outputMl = {-1., -1., -1.}; bool isPhysicalPrimary = false; int trackOrigin = -1; - bool isDplusSignal = std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi; + bool isDplusSignal = std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi; // prompt and non-prompt division bool isDplusPrompt = candidate.originMcRec() == RecoDecay::OriginType::Prompt; if (pAssoc.has_mcParticle()) { diff --git a/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx index 3ba26af40a6..2b9ea57bfd5 100644 --- a/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx @@ -15,6 +15,7 @@ /// \author Samuele Cattaruzzi #include +#include #include "CommonConstants/PhysicsConstants.h" #include "Framework/AnalysisTask.h" @@ -41,6 +42,13 @@ using namespace o2::constants::math; using namespace o2::framework; using namespace o2::framework::expressions; +enum ResonantChannel : int8_t { + PhiPi = 1, + Kstar0K = 2 +}; + +static std::unordered_map channelsResonant = {{{ResonantChannel::PhiPi, hf_decay::hf_cand_3prong::DecayChannelResonant::DsToPhiPi}, {ResonantChannel::Kstar0K, hf_decay::hf_cand_3prong::DecayChannelResonant::DsToKstar0K}}}; + /// Returns deltaPhi value in range [-pi/2., 3.*pi/2], typically used for correlation studies double getDeltaPhi(double phiHadron, double phiD) { @@ -156,7 +164,7 @@ struct HfCorrelatorDsHadrons { Configurable selNoSameBunchPileUpColl{"selNoSameBunchPileUpColl", true, "Flag for rejecting the collisions associated with the same bunch crossing (used only in MC processes)"}; Configurable selectionFlagDs{"selectionFlagDs", 7, "Selection Flag for Ds (avoid the case of flag = 0, no outputMlScore)"}; Configurable numberEventsMixed{"numberEventsMixed", 5, "Number of events mixed in ME process"}; - Configurable decayChannel{"decayChannel", 1, "Decay channels: 1 for Ds->PhiPi->KKpi, 2 for Ds->K0*K->KKPi"}; + Configurable decayChannel{"decayChannel", 1, "Resonant decay channels: 1 for Ds->PhiPi->KKpi, 2 for Ds->K0*K->KKPi"}; Configurable applyEfficiency{"applyEfficiency", true, "Flag for applying D-meson efficiency weights"}; Configurable yCandMax{"yCandMax", 0.8, "max. cand. rapidity"}; Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen. cand. rapidity"}; @@ -462,8 +470,8 @@ struct HfCorrelatorDsHadrons { // prompt and non-prompt division isDsPrompt = candidate.originMcRec() == RecoDecay::OriginType::Prompt; // Ds Signal - isDsSignal = std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi; - isDecayChan = candidate.flagMcDecayChanRec() == decayChannel; + isDsSignal = std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK; + isDecayChan = candidate.flagMcDecayChanRec() == channelsResonant[decayChannel]; if (std::abs(hfHelper.yDs(candidate)) > yCandMax || candidate.pt() < ptCandMin || candidate.pt() > ptCandMax) { continue; @@ -643,7 +651,7 @@ struct HfCorrelatorDsHadrons { // MC gen level for (const auto& particle : groupedMcParticles) { // check if the particle is Ds - if ((std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) && (particle.flagMcDecayChanGen() == decayChannel)) { + if ((std::abs(particle.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && (particle.flagMcDecayChanGen() == channelsResonant[decayChannel])) { double yD = RecoDecay::y(particle.pVector(), MassDS); if (std::abs(yD) > yCandGenMax || particle.pt() < ptCandMin || particle.pt() > ptCandMax) { continue; @@ -651,7 +659,7 @@ struct HfCorrelatorDsHadrons { fillMcGenHisto(particle); // prompt and non-prompt division isDsPrompt = particle.originMcGen() == RecoDecay::OriginType::Prompt; - isDecayChan = particle.flagMcDecayChanGen() == decayChannel; + isDecayChan = particle.flagMcDecayChanGen() == channelsResonant[decayChannel]; std::vector listDaughters{}; std::array arrDaughDsPDG = {+kKPlus, -kKPlus, kPiPlus}; std::array prongsId; @@ -823,7 +831,7 @@ struct HfCorrelatorDsHadrons { if (std::abs(hfHelper.yDs(candidate)) > yCandMax || candidate.pt() < ptCandMin || candidate.pt() > ptCandMax) { continue; } - if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) { + if (std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) { // DsToKKPi and DsToPiKK division if (candidate.isSelDsToKKPi() >= selectionFlagDs) { fillHistoMcRecSig(candidate, 0.); @@ -860,7 +868,7 @@ struct HfCorrelatorDsHadrons { // prompt and non-prompt division isDsPrompt = candidate.originMcRec() == RecoDecay::OriginType::Prompt; // Ds Signal - isDsSignal = std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi; + isDsSignal = std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK; isDecayChan = candidate.flagMcDecayChanRec() == decayChannel; if (pAssoc.has_mcParticle()) { auto mcParticle = pAssoc.template mcParticle_as(); @@ -911,7 +919,7 @@ struct HfCorrelatorDsHadrons { for (const auto& [c1, tracks1, c2, tracks2] : pairMcGen) { int poolBin = corrBinningMcGen.getBin(std::make_tuple(c1.posZ(), c1.multMCFT0A())); for (const auto& [candidate, particleAssoc] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { - if ((std::abs(candidate.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) && (candidate.flagMcDecayChanGen() == decayChannel)) { + if ((std::abs(candidate.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && (candidate.flagMcDecayChanGen() == decayChannel)) { double yD = RecoDecay::y(candidate.pVector(), MassDS); if (std::abs(yD) > yCandGenMax || candidate.pt() < ptCandMin || candidate.pt() > ptCandMax) { continue; diff --git a/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx index f8dd07c5fc4..c76ec3d62d2 100644 --- a/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx @@ -532,7 +532,7 @@ struct HfCorrelatorLcHadrons { auto trackPos1 = candidate.template prong0_as(); // positive daughter (negative for the antiparticles) auto trackPos2 = candidate.template prong2_as(); int8_t chargeLc = trackPos1.sign(); // charge of 1st prong will be the charge of Lc candidate - isLcSignal = TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_3prong::DecayType::LcToPKPi); + isLcSignal = std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi; isLcPrompt = candidate.originMcRec() == RecoDecay::OriginType::Prompt; isLcNonPrompt = candidate.originMcRec() == RecoDecay::OriginType::NonPrompt; std::vector outputMl = {-1., -1., -1.}; @@ -778,7 +778,7 @@ struct HfCorrelatorLcHadrons { if (std::abs(particle.pdgCode()) != Pdg::kLambdaCPlus) { continue; } - if (!TESTBIT(std::abs(particle.flagMcMatchGen()), aod::hf_cand_3prong::DecayType::LcToPKPi)) { + if (std::abs(particle.flagMcMatchGen()) != hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { continue; } double yL = RecoDecay::y(particle.pVector(), MassLambdaCPlus); @@ -944,7 +944,7 @@ struct HfCorrelatorLcHadrons { continue; } // Lc flag - bool isLcSignal = TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_3prong::DecayType::LcToPKPi); + bool isLcSignal = std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi; // prompt and non-prompt division bool isLcPrompt = candidate.originMcRec() == RecoDecay::OriginType::Prompt; bool isLcNonPrompt = candidate.originMcRec() == RecoDecay::OriginType::NonPrompt; @@ -993,7 +993,7 @@ struct HfCorrelatorLcHadrons { std::vector outputMl = {-1., -1., -1.}; bool isPhysicalPrimary = false; int trackOrigin = -1; - bool isLcSignal = std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::LcToPKPi; + bool isLcSignal = std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi; bool isLcPrompt = candidate.originMcRec() == RecoDecay::OriginType::Prompt; if (pidTrkApplied) { if (!passPIDSelection(pAssoc, trkPIDspecies, pidTPCMax, pidTOFMax, tofPIDThreshold, forceTOF)) diff --git a/PWGHF/HFC/TableProducer/femtoDreamProducer.cxx b/PWGHF/HFC/TableProducer/femtoDreamProducer.cxx index 16a32177afd..ee8ec8aaa26 100644 --- a/PWGHF/HFC/TableProducer/femtoDreamProducer.cxx +++ b/PWGHF/HFC/TableProducer/femtoDreamProducer.cxx @@ -563,7 +563,7 @@ struct HfFemtoDreamProducer { // Filling particle properties rowCandCharmHadGen.reserve(particles.size()); for (const auto& particle : particles) { - if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::LcToPKPi) { + if (std::abs(particle.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { rowCandCharmHadGen( particle.mcCollisionId(), particle.flagMcMatchGen(), diff --git a/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx index 43398e86043..339ab91a27c 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx @@ -589,7 +589,7 @@ struct HfTaskCorrelationDplusHadrons { auto mcCollision = mcParticle.template mcCollision_as>(); multiplicity = mcCollision.multMCFT0A() + mcCollision.multMCFT0C(); // multFT0M = multFt0A + multFT0C hCandidates->Fill(kCandidateStepMcGenAll, mcParticle.pt(), multiplicity, mcParticle.originMcGen()); - if (std::abs(mcParticle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi) { + if (std::abs(mcParticle.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) { hCandidates->Fill(kCandidateStepMcGenDplusToPiKPi, mcParticle.pt(), multiplicity, mcParticle.originMcGen()); auto yDplus = RecoDecay::y(mcParticle.pVector(), o2::constants::physics::MassDPlus); if (std::abs(yDplus) <= yCandGenMax) { @@ -636,7 +636,7 @@ struct HfTaskCorrelationDplusHadrons { continue; } multiplicity = collision.multFT0M(); - if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi) { + if (std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) { hCandidates->Fill(kCandidateStepMcReco, candidate.pt(), multiplicity, candidate.originMcRec()); if (std::abs(hfHelper.yDplus(candidate)) <= yCandMax) { hCandidates->Fill(kCandidateStepMcRecoInAcceptance, candidate.pt(), multiplicity, candidate.originMcRec()); diff --git a/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx index f70f05b0691..3375d71b86d 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx @@ -693,7 +693,7 @@ struct HfTaskCorrelationDsHadrons { // generated candidate loop for (const auto& mcParticle : groupedMcParticles) { - if ((std::abs(mcParticle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) && (mcParticle.flagMcDecayChanGen() == decayChannel)) { + if ((std::abs(mcParticle.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && (mcParticle.flagMcDecayChanGen() == decayChannel)) { hCandidates->Fill(kCandidateStepMcGenDsToKKPi, mcParticle.pt(), multiplicityGen, mcParticle.originMcGen()); auto yDs = RecoDecay::y(mcParticle.pVector(), o2::constants::physics::MassDS); if (std::abs(yDs) <= yCandGenMax) { @@ -738,7 +738,7 @@ struct HfTaskCorrelationDsHadrons { continue; } - if ((std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) && (candidate.flagMcDecayChanRec() == decayChannel)) { + if ((std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && (candidate.flagMcDecayChanRec() == decayChannel)) { auto prong0McPart = candidate.template prong0_as().template mcParticle_as(); // DsToKKPi and DsToPiKK division if (((std::abs(prong0McPart.pdgCode()) == kKPlus) && (candidate.isSelDsToKKPi() >= selectionFlagDs)) || ((std::abs(prong0McPart.pdgCode()) == kPiPlus) && (candidate.isSelDsToPiKK() >= selectionFlagDs))) { @@ -773,7 +773,7 @@ struct HfTaskCorrelationDsHadrons { float multiplicity = -1.; for (const auto& mcParticle : mcParticles) { // generated candidates - if ((std::abs(mcParticle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) && (mcParticle.flagMcDecayChanGen() == decayChannel)) { + if ((std::abs(mcParticle.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && (mcParticle.flagMcDecayChanGen() == decayChannel)) { auto mcCollision = mcParticle.template mcCollision_as>(); multiplicity = mcCollision.multMCFT0A() + mcCollision.multMCFT0C(); // multFT0M = multFt0A + multFT0C hCandidates->Fill(kCandidateStepMcGenDsToKKPi, mcParticle.pt(), multiplicity, mcParticle.originMcGen()); @@ -824,7 +824,7 @@ struct HfTaskCorrelationDsHadrons { continue; } multiplicity = collision.multFT0M(); - if ((std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) && (candidate.flagMcDecayChanRec() == decayChannel)) { + if ((std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && (candidate.flagMcDecayChanRec() == decayChannel)) { auto prong0McPart = candidate.template prong0_as().template mcParticle_as(); // DsToKKPi and DsToPiKK division if (((std::abs(prong0McPart.pdgCode()) == kKPlus) && (candidate.isSelDsToKKPi() >= selectionFlagDs)) || ((std::abs(prong0McPart.pdgCode()) == kPiPlus) && (candidate.isSelDsToPiKK() >= selectionFlagDs))) { diff --git a/PWGHF/HFC/Tasks/taskCorrelationLcHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationLcHadrons.cxx index 2d123acde31..791dd045f99 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationLcHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationLcHadrons.cxx @@ -811,7 +811,7 @@ struct HfTaskCorrelationLcHadrons { auto mcCollision = mcParticle.template mcCollision_as>(); multiplicity = mcCollision.multMCFT0A() + mcCollision.multMCFT0C(); // multFT0M = multFt0A + multFT0C hCandidates->Fill(kCandidateStepMcGenAll, mcParticle.pt(), multiplicity, mcParticle.originMcGen()); - if (std::abs(mcParticle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::LcToPKPi) { + if (std::abs(mcParticle.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { hCandidates->Fill(kCandidateStepMcGenLcToPKPi, mcParticle.pt(), multiplicity, mcParticle.originMcGen()); auto yL = RecoDecay::y(mcParticle.pVector(), o2::constants::physics::MassLambdaCPlus); if (std::abs(yL) <= yCandGenMax) { @@ -862,7 +862,7 @@ struct HfTaskCorrelationLcHadrons { continue; } multiplicity = collision.multFT0M(); - if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::LcToPKPi) { + if (std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { hCandidates->Fill(kCandidateStepMcReco, candidate.pt(), multiplicity, candidate.originMcRec()); if (std::abs(hfHelper.yLc(candidate)) <= yCandMax) { hCandidates->Fill(kCandidateStepMcRecoInAcceptance, candidate.pt(), multiplicity, candidate.originMcRec()); diff --git a/PWGHF/HFC/Tasks/taskFlow.cxx b/PWGHF/HFC/Tasks/taskFlow.cxx index 840357b0b3e..981ce78e7ca 100644 --- a/PWGHF/HFC/Tasks/taskFlow.cxx +++ b/PWGHF/HFC/Tasks/taskFlow.cxx @@ -809,7 +809,7 @@ struct HfTaskFlow { // } } } else { // For now, that means we do LambdaC - if (std::abs(mcCandidate.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::LcToPKPi) { + if (std::abs(mcCandidate.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { if (etaCandidateMax >= 0. && std::abs(etaCandidate) > etaCandidateMax) { return false; diff --git a/PWGHF/TableProducer/candidateCreator3Prong.cxx b/PWGHF/TableProducer/candidateCreator3Prong.cxx index d8f5963b301..145e84513db 100644 --- a/PWGHF/TableProducer/candidateCreator3Prong.cxx +++ b/PWGHF/TableProducer/candidateCreator3Prong.cxx @@ -46,7 +46,7 @@ #include "PWGLF/DataModel/mcCentrality.h" #include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsEvSelHf.h" @@ -55,10 +55,10 @@ #include "PWGHF/Utils/utilsTrkCandHf.h" using namespace o2; -using namespace o2::analysis; using namespace o2::hf_evsel; using namespace o2::hf_trkcandsel; using namespace o2::aod::hf_cand_3prong; +using namespace o2::hf_decay::hf_cand_3prong; using namespace o2::hf_centrality; using namespace o2::hf_occupancy; using namespace o2::constants::physics; @@ -953,7 +953,7 @@ struct HfCandidateCreator3ProngExpressions { indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2); } if (indexRec > -1) { - flag = sign * (1 << DecayType::DplusToPiKPi); + flag = sign * DecayChannelMain::DplusToPiKPi; } } @@ -982,9 +982,7 @@ struct HfCandidateCreator3ProngExpressions { } } if (indexRec > -1) { - // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± - // TODO: move to different and explicit flags - flag = sign * (1 << DecayType::DsToKKPi); + flag = sign * (isDplus ? DecayChannelMain::DplusToPiKK : DecayChannelMain::DsToPiKK); if (arrayDaughters[0].has_mcParticle()) { swapping = int8_t(std::abs(arrayDaughters[0].mcParticle().pdgCode()) == kPiPlus); } @@ -995,9 +993,9 @@ struct HfCandidateCreator3ProngExpressions { arrPDGDaugh[iProng] = std::abs(daughI.pdgCode()); } if ((arrPDGDaugh[0] == arrPDGResonantDPhiPi[0] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[1]) || (arrPDGDaugh[0] == arrPDGResonantDPhiPi[1] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[0])) { - channel = isDplus ? DecayChannelDToKKPi::DplusToPhiPi : DecayChannelDToKKPi::DsToPhiPi; + channel = isDplus ? DecayChannelResonant::DplusToPhiPi : DecayChannelResonant::DsToPhiPi; } else if ((arrPDGDaugh[0] == arrPDGResonantDKstarK[0] && arrPDGDaugh[1] == arrPDGResonantDKstarK[1]) || (arrPDGDaugh[0] == arrPDGResonantDKstarK[1] && arrPDGDaugh[1] == arrPDGResonantDKstarK[0])) { - channel = isDplus ? DecayChannelDToKKPi::DplusToK0starK : DecayChannelDToKKPi::DsToK0starK; + channel = isDplus ? DecayChannelResonant::DplusToKstar0K : DecayChannelResonant::DsToKstar0K; } } } @@ -1011,7 +1009,7 @@ struct HfCandidateCreator3ProngExpressions { indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDStar, std::array{+kPiPlus, +kPiPlus, -kKPlus}, true, &sign, 2); } if (indexRec > -1) { - flag = sign * (1 << DstarToPiKPiBkg); + flag = sign * DecayChannelMain::DstarToPiKPi; channel = 1; } } @@ -1028,7 +1026,7 @@ struct HfCandidateCreator3ProngExpressions { indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); } if (indexRec > -1) { - flag = sign * (1 << DecayType::LcToPKPi); + flag = sign * DecayChannelMain::LcToPKPi; // Flagging the different Λc± → p± K∓ π± decay channels if (arrayDaughters[0].has_mcParticle()) { @@ -1063,7 +1061,7 @@ struct HfCandidateCreator3ProngExpressions { indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); } if (indexRec > -1) { - flag = sign * (1 << DecayType::XicToPKPi); + flag = sign * DecayChannelMain::XicToPKPi; if (arrayDaughters[0].has_mcParticle()) { swapping = int8_t(std::abs(arrayDaughters[0].mcParticle().pdgCode()) == kPiPlus); } diff --git a/PWGHF/TableProducer/candidateCreatorDstar.cxx b/PWGHF/TableProducer/candidateCreatorDstar.cxx index b5b67db87ab..f25a09dbbb3 100644 --- a/PWGHF/TableProducer/candidateCreatorDstar.cxx +++ b/PWGHF/TableProducer/candidateCreatorDstar.cxx @@ -638,10 +638,10 @@ struct HfCandidateCreatorDstarExpressions { } if (indexRecDstar > -1) { - flagDstar = signDstar * (BIT(aod::hf_cand_dstar::DecayType::DstarToD0Pi)); + flagDstar = signDstar * hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi; } if (indexRecD0 > -1) { - flagD0 = signD0 * (BIT(aod::hf_cand_dstar::DecayType::D0ToPiK)); + flagD0 = signD0 * hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; } // check partly reconstructed decays, namely D0->Kpipi0 @@ -673,11 +673,11 @@ struct HfCandidateCreatorDstarExpressions { auto motherParticleDstar = mcParticles.rawIteratorAt(indexRecDstar); if (signDstar > 0) { if (RecoDecay::isMatchedMCGen(mcParticles, motherParticleDstar, Pdg::kDStar, std::array{+kPiPlus, +kPiPlus, -kKPlus, +kPi0}, false, &signDstar, 2)) { - flagDstar = signDstar * (BIT(aod::hf_cand_dstar::DecayType::DstarToD0PiPi0)); + flagDstar = signDstar * hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPiPi0; } } else { if (RecoDecay::isMatchedMCGen(mcParticles, motherParticleDstar, -Pdg::kDStar, std::array{-kPiPlus, -kPiPlus, +kKPlus, +kPi0}, false, &signDstar, 2)) { - flagDstar = signDstar * (BIT(aod::hf_cand_dstar::DecayType::DstarToD0PiPi0)); + flagDstar = signDstar * hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPiPi0; } } } @@ -686,11 +686,11 @@ struct HfCandidateCreatorDstarExpressions { auto motherParticleD0 = mcParticles.rawIteratorAt(indexRecD0); if (signD0 > 0) { if (RecoDecay::isMatchedMCGen(mcParticles, motherParticleD0, Pdg::kD0, std::array{+kPiPlus, -kKPlus, +kPi0}, false, &signD0)) { - flagD0 = signD0 * (BIT(aod::hf_cand_dstar::DecayType::D0ToPiKPi0)); + flagD0 = signD0 * hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiKPi0; } } else { if (RecoDecay::isMatchedMCGen(mcParticles, motherParticleD0, -Pdg::kD0, std::array{-kPiPlus, +kKPlus, +kPi0}, false, &signD0)) { - flagD0 = signD0 * (BIT(aod::hf_cand_dstar::DecayType::D0ToPiKPi0)); + flagD0 = signD0 * hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiKPi0; } } } @@ -764,11 +764,11 @@ struct HfCandidateCreatorDstarExpressions { } } if (RecoDecay::isMatchedMCGen(mcParticles, particleD0, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &signD0)) { - flagDstar = signDstar * (BIT(aod::hf_cand_dstar::DecayType::DstarToD0Pi)); - flagD0 = signD0 * (BIT(aod::hf_cand_dstar::DecayType::D0ToPiK)); + flagDstar = signDstar * hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi; + flagD0 = signD0 * hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; } else if (RecoDecay::isMatchedMCGen(mcParticles, particleD0, Pdg::kD0, std::array{+kPiPlus, -kKPlus, +kPi0}, false, &signD0) || RecoDecay::isMatchedMCGen(mcParticles, particleD0, -Pdg::kD0, std::array{-kPiPlus, +kKPlus, +kPi0}, false, &signD0)) { - flagDstar = signDstar * (BIT(aod::hf_cand_dstar::DecayType::DstarToD0PiPi0)); - flagD0 = signD0 * (BIT(aod::hf_cand_dstar::DecayType::D0ToPiKPi0)); + flagDstar = signDstar * hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPiPi0; + flagD0 = signD0 * hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiKPi0; } } diff --git a/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx b/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx index 8ab7e92d5ce..c8dbbf04b2b 100644 --- a/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx +++ b/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx @@ -472,7 +472,7 @@ struct HfCandidateSigmac0plusplusMc { /// skip immediately the candidate Σc0,++ w/o a Λc+ matched to MC auto candLc = candSigmac.prongLc_as(); - if (!(std::abs(candLc.flagMcMatchRec()) == BIT(aod::hf_cand_3prong::DecayType::LcToPKPi))) { /// (*) + if (std::abs(candLc.flagMcMatchRec()) != hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { /// (*) rowMCMatchScRec(flag, origin, -1.f, 0, -1); continue; } diff --git a/PWGHF/TableProducer/candidateCreatorXicc.cxx b/PWGHF/TableProducer/candidateCreatorXicc.cxx index 214c2cea891..e4455828b8d 100644 --- a/PWGHF/TableProducer/candidateCreatorXicc.cxx +++ b/PWGHF/TableProducer/candidateCreatorXicc.cxx @@ -105,7 +105,7 @@ struct HfCandidateCreatorXicc { aod::TracksWCov const& tracks) { for (const auto& xicCand : xicCands) { - if (!(xicCand.hfflag() & 1 << o2::aod::hf_cand_3prong::XicToPKPi)) { + if (!(xicCand.hfflag() & 1 << o2::aod::hf_cand_3prong::DecayType::XicToPKPi)) { continue; } if (xicCand.isSelXicToPKPi() >= selectionFlagXic) { @@ -195,9 +195,9 @@ struct HfCandidateCreatorXicc { xicCand.globalIndex(), trackpion.globalIndex(), hfFlag); } // if on selected Xicc - } // loop over candidates - } // end of process -}; // end of struct + } // loop over candidates + } // end of process +}; // end of struct /// Extends the base table with expression columns. struct HfCandidateCreatorXiccExpressions { diff --git a/PWGHF/TableProducer/derivedDataCreatorDplusToPiKPi.cxx b/PWGHF/TableProducer/derivedDataCreatorDplusToPiKPi.cxx index c5c26270b79..6897b30ec0e 100644 --- a/PWGHF/TableProducer/derivedDataCreatorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorDplusToPiKPi.cxx @@ -87,7 +87,7 @@ struct HfDerivedDataCreatorDplusToPiKPi { using TypeMcCollisions = soa::Join; Filter filterSelectCandidates = (aod::hf_sel_candidate_dplus::isSelDplusToPiKPi & static_cast(BIT(aod::SelectionStep::RecoMl - 1))) != 0; // select candidates which passed all cuts at least up to RecoMl - 1 - Filter filterMcGenMatching = nabs(aod::hf_cand_3prong::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)); + Filter filterMcGenMatching = nabs(aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; @@ -101,10 +101,10 @@ struct HfDerivedDataCreatorDplusToPiKPi { Partition candidatesMlAll = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= 0; Partition candidatesMcMlAll = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= 0; // partitions for signal and background - Partition candidatesMcSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)); - Partition candidatesMcBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)); - Partition candidatesMcMlSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)); - Partition candidatesMcMlBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)); + Partition candidatesMcSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); + Partition candidatesMcBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); + Partition candidatesMcMlSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); + Partition candidatesMcMlBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); void init(InitContext const&) { @@ -253,7 +253,7 @@ struct HfDerivedDataCreatorDplusToPiKPi { swapping = candidate.isCandidateSwapped(); flagDecayChanRec = candidate.flagMcDecayChanRec(); if constexpr (onlyBkg) { - if (TESTBIT(std::abs(flagMcRec), aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { + if (std::abs(flagMcRec) == hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) { continue; } if (downSampleBkgFactor < 1.) { @@ -264,7 +264,7 @@ struct HfDerivedDataCreatorDplusToPiKPi { } } if constexpr (onlySig) { - if (!TESTBIT(std::abs(flagMcRec), aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { + if (std::abs(flagMcRec) != hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) { continue; } } diff --git a/PWGHF/TableProducer/derivedDataCreatorDstarToD0Pi.cxx b/PWGHF/TableProducer/derivedDataCreatorDstarToD0Pi.cxx index 084605c2f3b..7c592e9ccb1 100644 --- a/PWGHF/TableProducer/derivedDataCreatorDstarToD0Pi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorDstarToD0Pi.cxx @@ -83,7 +83,7 @@ struct HfDerivedDataCreatorDstarToD0Pi { using TypeMcCollisions = soa::Join; Filter filterSelectCandidates = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == true; - Filter filterMcGenMatching = nabs(aod::hf_cand_dstar::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_dstar::DecayType::DstarToD0Pi)); + Filter filterMcGenMatching = nabs(aod::hf_cand_dstar::flagMcMatchGen) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; @@ -97,10 +97,10 @@ struct HfDerivedDataCreatorDstarToD0Pi { Partition candidatesMlAll = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == true; Partition candidatesMcMlAll = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == true; // partitions for signal and background - Partition candidatesMcSig = nabs(aod::hf_cand_dstar::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_dstar::DecayType::DstarToD0Pi)); - Partition candidatesMcBkg = nabs(aod::hf_cand_dstar::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_dstar::DecayType::DstarToD0Pi)); - Partition candidatesMcMlSig = nabs(aod::hf_cand_dstar::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_dstar::DecayType::DstarToD0Pi)); - Partition candidatesMcMlBkg = nabs(aod::hf_cand_dstar::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_dstar::DecayType::DstarToD0Pi)); + Partition candidatesMcSig = nabs(aod::hf_cand_dstar::flagMcMatchRec) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); + Partition candidatesMcBkg = nabs(aod::hf_cand_dstar::flagMcMatchRec) != static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); + Partition candidatesMcMlSig = nabs(aod::hf_cand_dstar::flagMcMatchRec) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); + Partition candidatesMcMlBkg = nabs(aod::hf_cand_dstar::flagMcMatchRec) != static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); void init(InitContext const&) { @@ -229,7 +229,7 @@ struct HfDerivedDataCreatorDstarToD0Pi { flagMcRec = candidate.flagMcMatchRec(); origin = candidate.originMcRec(); if constexpr (onlyBkg) { - if (TESTBIT(std::abs(flagMcRec), aod::hf_cand_dstar::DecayType::DstarToD0Pi)) { + if (std::abs(flagMcRec) == hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi) { continue; } if (downSampleBkgFactor < 1.) { @@ -240,7 +240,7 @@ struct HfDerivedDataCreatorDstarToD0Pi { } } if constexpr (onlySig) { - if (!TESTBIT(std::abs(flagMcRec), aod::hf_cand_dstar::DecayType::DstarToD0Pi)) { + if (std::abs(flagMcRec) != hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi) { continue; } } diff --git a/PWGHF/TableProducer/derivedDataCreatorLcToPKPi.cxx b/PWGHF/TableProducer/derivedDataCreatorLcToPKPi.cxx index 7078087a222..a956d4ff202 100644 --- a/PWGHF/TableProducer/derivedDataCreatorLcToPKPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorLcToPKPi.cxx @@ -87,7 +87,7 @@ struct HfDerivedDataCreatorLcToPKPi { using TypeMcCollisions = soa::Join; Filter filterSelectCandidates = aod::hf_sel_candidate_lc::isSelLcToPKPi >= 1 || aod::hf_sel_candidate_lc::isSelLcToPiKP >= 1; - Filter filterMcGenMatching = nabs(aod::hf_cand_3prong::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_3prong::DecayType::LcToPKPi)); + Filter filterMcGenMatching = nabs(aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; @@ -101,10 +101,10 @@ struct HfDerivedDataCreatorLcToPKPi { Partition candidatesMlAll = aod::hf_sel_candidate_lc::isSelLcToPKPi >= 0; Partition candidatesMcMlAll = aod::hf_sel_candidate_lc::isSelLcToPKPi >= 0; // partitions for signal and background - Partition candidatesMcSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::LcToPKPi)); - Partition candidatesMcBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_3prong::DecayType::LcToPKPi)); - Partition candidatesMcMlSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::LcToPKPi)); - Partition candidatesMcMlBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_3prong::DecayType::LcToPKPi)); + Partition candidatesMcSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); + Partition candidatesMcBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); + Partition candidatesMcMlSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); + Partition candidatesMcMlBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); void init(InitContext const&) { @@ -252,7 +252,7 @@ struct HfDerivedDataCreatorLcToPKPi { origin = candidate.originMcRec(); swapping = candidate.isCandidateSwapped(); if constexpr (onlyBkg) { - if (TESTBIT(std::abs(flagMcRec), aod::hf_cand_3prong::DecayType::LcToPKPi)) { + if (std::abs(flagMcRec) == hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { continue; } if (downSampleBkgFactor < 1.) { @@ -263,7 +263,7 @@ struct HfDerivedDataCreatorLcToPKPi { } } if constexpr (onlySig) { - if (!TESTBIT(std::abs(flagMcRec), aod::hf_cand_3prong::DecayType::LcToPKPi)) { + if (std::abs(flagMcRec) != hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { continue; } } diff --git a/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx b/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx index 7e482985c0d..3d23c0b30ca 100644 --- a/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx @@ -268,11 +268,11 @@ struct HfTreeCreatorDplusToPiKPi { using CollisionsCent = soa::Join; Filter filterSelectCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; - Filter filterMcGenMatching = nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)); + Filter filterMcGenMatching = nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); - Partition reconstructedCandSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)) || nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)); // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± - Partition reconstructedCandBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)); - Partition reconstructedCandSigMl = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)) || nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)) || nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DstarToPiKPiBkg)); // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± + Partition reconstructedCandSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) || nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) || nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK); + Partition reconstructedCandBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); + Partition reconstructedCandSigMl = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) || nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) || nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK) || nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DstarToPiKPi); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx b/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx index cf2f595f44b..7a8547cf32a 100644 --- a/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx @@ -17,6 +17,8 @@ /// \author Stefano Politanò , Politecnico & INFN, Torino /// \author Fabio Catalano , CERN +#include + #include "CommonConstants/PhysicsConstants.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" @@ -229,6 +231,19 @@ DECLARE_SOA_TABLE(HfCandDsFullPs, "AOD", "HFCANDDSFULLP", hf_cand_3prong::OriginMcGen); } // namespace o2::aod +enum Mother : int8_t { + Ds, + Dplus +}; + +enum ResonantChannel : int8_t { + PhiPi = 1, + Kstar0K = 2 +}; + +static std::unordered_map> channelsResonant = {{{Mother::Ds, {{ResonantChannel::PhiPi, hf_decay::hf_cand_3prong::DecayChannelResonant::DsToPhiPi}, {ResonantChannel::Kstar0K, hf_decay::hf_cand_3prong::DecayChannelResonant::DsToKstar0K}}}, + {Mother::Dplus, {{ResonantChannel::PhiPi, hf_decay::hf_cand_3prong::DecayChannelResonant::DplusToPhiPi}, {ResonantChannel::Kstar0K, hf_decay::hf_cand_3prong::DecayChannelResonant::DplusToKstar0K}}}}}; + /// Writes the full information in an output TTree struct HfTreeCreatorDsToKKPi { Produces rowCandidateFull; @@ -236,7 +251,7 @@ struct HfTreeCreatorDsToKKPi { Produces rowCandidateFullParticles; Produces rowCandidateLite; - Configurable decayChannel{"decayChannel", 1, "Switch between decay channels: 1 for Ds/Dplus->PhiPi->KKpi, 2 for Ds/Dplus->K0*K->KKPi"}; + Configurable decayChannel{"decayChannel", 1, "Switch between resonant decay channels: 1 for Ds/Dplus->PhiPi->KKpi, 2 for Ds/Dplus->K0*K->KKPi"}; Configurable fillDplusMc{"fillDplusMc", false, "Switch to fill Dplus MC information"}; Configurable selectionFlagDs{"selectionFlagDs", 1, "Selection flag for Ds"}; Configurable fillCandidateLiteTable{"fillCandidateLiteTable", false, "Switch to fill lite table with candidate properties"}; @@ -260,16 +275,22 @@ struct HfTreeCreatorDsToKKPi { int offsetDplusDecayChannel = aod::hf_cand_3prong::DecayChannelDToKKPi::DplusToPhiPi - aod::hf_cand_3prong::DecayChannelDToKKPi::DsToPhiPi; // Offset between Dplus and Ds to use the same decay channel. See aod::hf_cand_3prong::DecayChannelDToKKPi Filter filterSelectCandidates = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs; - Filter filterMcGenMatching = nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)) && (aod::hf_cand_3prong::flagMcDecayChanGen == decayChannel || (fillDplusMc && aod::hf_cand_3prong::flagMcDecayChanGen == (decayChannel + offsetDplusDecayChannel))); // Do not store Dplus MC if fillDplusMc is false + Filter filterMcGenMatching = + nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && + (aod::hf_cand_3prong::flagMcDecayChanGen == channelsResonant[Mother::Ds][decayChannel] || + (fillDplusMc && aod::hf_cand_3prong::flagMcDecayChanGen == channelsResonant[Mother::Dplus][decayChannel])); // Do not store Dplus MC if fillDplusMc is false Partition selectedDsToKKPiCand = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs; Partition selectedDsToPiKKCand = aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs; - Partition reconstructedCandSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)) && (aod::hf_cand_3prong::flagMcDecayChanRec == decayChannel || (fillDplusMc && aod::hf_cand_3prong::flagMcDecayChanRec == (decayChannel + offsetDplusDecayChannel))); // Do not store Dplus MC if fillDplusMc is false - Partition reconstructedCandBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)); + Partition reconstructedCandSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && (aod::hf_cand_3prong::flagMcDecayChanRec == channelsResonant[Mother::Ds][decayChannel] || (fillDplusMc && aod::hf_cand_3prong::flagMcDecayChanRec == channelsResonant[Mother::Dplus][decayChannel])); // Do not store Dplus MC if fillDplusMc is false + Partition reconstructedCandBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); void init(InitContext const&) { + if (decayChannel != ResonantChannel::PhiPi && decayChannel != ResonantChannel::Kstar0K) { + LOGP(fatal, "Invalid value of decayChannel"); + } } template @@ -305,7 +326,7 @@ struct HfTreeCreatorDsToKKPi { originMc = candidate.originMcRec(); channelMc = candidate.flagMcDecayChanRec(); isSwapped = candidate.isCandidateSwapped(); - if (fillDplusMc && candidate.flagMcDecayChanRec() == (decayChannel + offsetDplusDecayChannel)) { + if (fillDplusMc && candidate.flagMcDecayChanRec() == channelsResonant[Mother::Dplus][decayChannel]) { yCand = hfHelper.yDplus(candidate); eCand = hfHelper.eDplus(candidate); ctCand = hfHelper.ctDplus(candidate); diff --git a/PWGHF/TableProducer/treeCreatorDstarToD0Pi.cxx b/PWGHF/TableProducer/treeCreatorDstarToD0Pi.cxx index 00d2bea174f..2b838d774b1 100644 --- a/PWGHF/TableProducer/treeCreatorDstarToD0Pi.cxx +++ b/PWGHF/TableProducer/treeCreatorDstarToD0Pi.cxx @@ -261,10 +261,10 @@ struct HfTreeCreatorDstarToD0Pi { using CandDstarMcGen = soa::Filtered>; Filter filterSelectCandidates = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == selectionFlagDstarToD0Pi; - Filter filterMcGenMatching = nabs(aod::hf_cand_dstar::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_dstar::DecayType::DstarToD0Pi)); + Filter filterMcGenMatching = nabs(aod::hf_cand_dstar::flagMcMatchGen) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); - Partition reconstructedCandSig = nabs(aod::hf_cand_dstar::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_dstar::DecayType::DstarToD0Pi)); - Partition reconstructedCandBkg = nabs(aod::hf_cand_dstar::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_dstar::DecayType::DstarToD0Pi)); + Partition reconstructedCandSig = nabs(aod::hf_cand_dstar::flagMcMatchRec) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); + Partition reconstructedCandBkg = nabs(aod::hf_cand_dstar::flagMcMatchRec) != static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx index 398bf3fc57a..5ad144e472e 100644 --- a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx @@ -410,7 +410,7 @@ struct HfTreeCreatorLcToPKPi { SigBgStatus status{Default}; - if (std::abs(flag) == (1 << o2::aod::hf_cand_3prong::DecayType::LcToPKPi)) { + if (std::abs(flag) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { if (swapped == 0) { if (candFlag == 0) { if (origin == RecoDecay::OriginType::Prompt) @@ -917,7 +917,7 @@ struct HfTreeCreatorLcToPKPi { // Filling particle properties rowCandidateFullParticles.reserve(particles.size()); for (const auto& particle : particles) { - if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::LcToPKPi) { + if (std::abs(particle.flagMcMatchGen()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { auto mcDaughter0 = particle.template daughters_as>().begin(); auto mcCollision = particle.template mcCollision_as(); auto p = particle.p(); diff --git a/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx b/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx index 279dbc797fc..b038f28c80e 100644 --- a/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx @@ -231,13 +231,13 @@ struct HfTreeCreatorXicToPKPi { using CandXicMcGen = soa::Filtered>; Filter filterSelectCandidates = aod::hf_sel_candidate_xic::isSelXicToPKPi >= selectionFlagXic || aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlagXic; - Filter filterMcGenMatching = nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_3prong::DecayType::XicToPKPi)); + Filter filterMcGenMatching = nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi); Partition selectedXicToPKPiCand = aod::hf_sel_candidate_xic::isSelXicToPKPi >= selectionFlagXic; Partition selectedXicToPiKPCand = aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlagXic; - Partition reconstructedCandSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::XicToPKPi)); - Partition reconstructedCandBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_3prong::DecayType::XicToPKPi)); + Partition reconstructedCandSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi); + Partition reconstructedCandBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi); void init(InitContext const&) { diff --git a/PWGHF/Tasks/taskCharmHadImpactPar.cxx b/PWGHF/Tasks/taskCharmHadImpactPar.cxx index 051fdd0b7a2..9671501387f 100644 --- a/PWGHF/Tasks/taskCharmHadImpactPar.cxx +++ b/PWGHF/Tasks/taskCharmHadImpactPar.cxx @@ -162,7 +162,7 @@ struct HfTaskCharmHadImpactPar { if constexpr (channel == Channel::DplusToKPiPi) { // D+ -> Kpipi if constexpr (doMc) { if (fillOnlySignal) { - if (std::abs(candidate.flagMcMatchRec()) != 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi) { + if (std::abs(candidate.flagMcMatchRec()) != o2::hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) { return; } } diff --git a/PWGHF/Tasks/taskLcCentrality.cxx b/PWGHF/Tasks/taskLcCentrality.cxx index 091b70b66ec..274421f8093 100644 --- a/PWGHF/Tasks/taskLcCentrality.cxx +++ b/PWGHF/Tasks/taskLcCentrality.cxx @@ -25,6 +25,7 @@ #include "Common/DataModel/Centrality.h" #include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" @@ -162,7 +163,7 @@ struct HfTaskLcCentralityMc { if (yCandMax >= 0. && std::abs(hfHelper.yLc(candidate)) > yCandMax) { continue; } - if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::LcToPKPi) { + if (std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { // Get the corresponding MC particle. auto indexMother = RecoDecay::getMother(mcParticles, candidate.prong0_as().mcParticle_as>(), o2::constants::physics::Pdg::kLambdaCPlus, true); auto particleMother = mcParticles.rawIteratorAt(indexMother); @@ -184,7 +185,7 @@ struct HfTaskLcCentralityMc { } // MC gen. for (const auto& particle : mcParticles) { - if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::LcToPKPi) { + if (std::abs(particle.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { if (yCandMax >= 0. && std::abs(RecoDecay::y(particle.pVector(), o2::constants::physics::MassLambdaCPlus)) > yCandMax) { continue; } diff --git a/PWGHF/Tasks/taskMcValidation.cxx b/PWGHF/Tasks/taskMcValidation.cxx index eea7aa4c4ab..269cd7b21ea 100644 --- a/PWGHF/Tasks/taskMcValidation.cxx +++ b/PWGHF/Tasks/taskMcValidation.cxx @@ -1106,21 +1106,21 @@ struct HfTaskMcValidationRec { continue; } int whichHad = -1; - if (isDPlusSel && TESTBIT(std::abs(cand3Prong.flagMcMatchRec()), hf_cand_3prong::DecayType::DplusToPiKPi)) { + if (isDPlusSel && std::abs(cand3Prong.flagMcMatchRec()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) { whichHad = DplusToPiKPi; - } else if (isDsSel && TESTBIT(std::abs(cand3Prong.flagMcMatchRec()), hf_cand_3prong::DecayType::DsToKKPi)) { - if (cand3Prong.flagMcDecayChanRec() == hf_cand_3prong::DecayChannelDToKKPi::DsToPhiPi) { + } else if (isDsSel && std::abs(cand3Prong.flagMcMatchRec()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) { + if (cand3Prong.flagMcDecayChanRec() == o2::hf_decay::hf_cand_3prong::DecayChannelResonant::DsToPhiPi) { whichHad = DsToPhiPiToKKPi; } - if (cand3Prong.flagMcDecayChanRec() == hf_cand_3prong::DecayChannelDToKKPi::DsToK0starK) { + if (cand3Prong.flagMcDecayChanRec() == o2::hf_decay::hf_cand_3prong::DecayChannelResonant::DsToKstar0K) { whichHad = DsToK0starKToKKPi; } - if (cand3Prong.flagMcDecayChanRec() == hf_cand_3prong::DecayChannelDToKKPi::DplusToPhiPi) { + if (cand3Prong.flagMcDecayChanRec() == o2::hf_decay::hf_cand_3prong::DecayChannelResonant::DplusToPhiPi) { whichHad = DplusToPhiPiToKKPi; } - } else if (isLcSel && TESTBIT(std::abs(cand3Prong.flagMcMatchRec()), hf_cand_3prong::DecayType::LcToPKPi)) { + } else if (isLcSel && std::abs(cand3Prong.flagMcMatchRec()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { whichHad = LcToPKPi; - } else if (isXicSel && TESTBIT(std::abs(cand3Prong.flagMcMatchRec()), hf_cand_3prong::DecayType::XicToPKPi)) { + } else if (isXicSel && std::abs(cand3Prong.flagMcMatchRec()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi) { whichHad = XiCplusToPKPi; } int whichOrigin; diff --git a/PWGHF/Utils/utilsMcGen.h b/PWGHF/Utils/utilsMcGen.h index bc0380bd198..73dac888c8e 100644 --- a/PWGHF/Utils/utilsMcGen.h +++ b/PWGHF/Utils/utilsMcGen.h @@ -28,6 +28,7 @@ #include "Common/Core/RecoDecay.h" +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" namespace hf_mc_gen @@ -85,6 +86,7 @@ template void fillMcMatchGen3Prong(T const& mcParticles, U const& mcParticlesPerMcColl, V& rowMcMatchGen, bool rejectBackground) { using namespace o2::constants::physics; + constexpr std::size_t NDaughtersResonant{2u}; // Match generated particles. for (const auto& particle : mcParticlesPerMcColl) { @@ -94,12 +96,12 @@ void fillMcMatchGen3Prong(T const& mcParticles, U const& mcParticlesPerMcColl, V int8_t sign = 0; std::vector arrDaughIndex; std::vector idxBhadMothers{}; - std::array arrPDGDaugh; - std::array arrPDGResonant1 = {kProton, 313}; // Λc± → p± K* - std::array arrPDGResonant2 = {2224, kKPlus}; // Λc± → Δ(1232)±± K∓ - std::array arrPDGResonant3 = {102134, kPiPlus}; // Λc± → Λ(1520) π± - std::array arrPDGResonantDPhiPi = {333, kPiPlus}; // Ds± → Phi π± and D± → Phi π± - std::array arrPDGResonantDKstarK = {313, kKPlus}; // Ds± → K*(892)0bar K± and D± → K*(892)0bar K± + std::array arrPDGDaugh; + std::array arrPDGResonant1 = {kProton, Pdg::kK0Star892}; // Λc± → p± K* + std::array arrPDGResonant2 = {2224, kKPlus}; // Λc± → Δ(1232)±± K∓ + std::array arrPDGResonant3 = {102134, kPiPlus}; // Λc± → Λ(1520) π± + std::array arrPDGResonantDPhiPi = {Pdg::kPhi, kPiPlus}; // Ds± → Phi π± and D± → Phi π± + std::array arrPDGResonantDKstarK = {Pdg::kK0Star892, kKPlus}; // Ds± → K*(892)0bar K± and D± → K*(892)0bar K± // Reject particles from background events if (particle.fromBackgroundEvent() && rejectBackground) { rowMcMatchGen(flag, origin, channel, -1); @@ -109,7 +111,7 @@ void fillMcMatchGen3Prong(T const& mcParticles, U const& mcParticlesPerMcColl, V // D± → π± K∓ π± if (flag == 0) { if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { - flag = sign * (1 << o2::aod::hf_cand_3prong::DecayType::DplusToPiKPi); + flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi; } } @@ -119,24 +121,24 @@ void fillMcMatchGen3Prong(T const& mcParticles, U const& mcParticlesPerMcColl, V if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± // TODO: move to different and explicit flags - flag = sign * (1 << o2::aod::hf_cand_3prong::DecayType::DsToKKPi); + flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK; } else if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± // TODO: move to different and explicit flags - flag = sign * (1 << o2::aod::hf_cand_3prong::DecayType::DsToKKPi); + flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK; isDplus = true; } if (flag != 0) { RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{0}, 1); - if (arrDaughIndex.size() == 2) { + if (arrDaughIndex.size() == NDaughtersResonant) { for (auto jProng = 0u; jProng < arrDaughIndex.size(); ++jProng) { auto daughJ = mcParticles.rawIteratorAt(arrDaughIndex[jProng]); arrPDGDaugh[jProng] = std::abs(daughJ.pdgCode()); } if ((arrPDGDaugh[0] == arrPDGResonantDPhiPi[0] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[1]) || (arrPDGDaugh[0] == arrPDGResonantDPhiPi[1] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[0])) { - channel = isDplus ? o2::aod::hf_cand_3prong::DecayChannelDToKKPi::DplusToPhiPi : o2::aod::hf_cand_3prong::DecayChannelDToKKPi::DsToPhiPi; + channel = isDplus ? o2::hf_decay::hf_cand_3prong::DecayChannelResonant::DplusToPhiPi : o2::hf_decay::hf_cand_3prong::DecayChannelResonant::DsToPhiPi; } else if ((arrPDGDaugh[0] == arrPDGResonantDKstarK[0] && arrPDGDaugh[1] == arrPDGResonantDKstarK[1]) || (arrPDGDaugh[0] == arrPDGResonantDKstarK[1] && arrPDGDaugh[1] == arrPDGResonantDKstarK[0])) { - channel = isDplus ? o2::aod::hf_cand_3prong::DecayChannelDToKKPi::DplusToK0starK : o2::aod::hf_cand_3prong::DecayChannelDToKKPi::DsToK0starK; + channel = isDplus ? o2::hf_decay::hf_cand_3prong::DecayChannelResonant::DplusToKstar0K : o2::hf_decay::hf_cand_3prong::DecayChannelResonant::DsToKstar0K; } } } @@ -145,18 +147,18 @@ void fillMcMatchGen3Prong(T const& mcParticles, U const& mcParticlesPerMcColl, V // D*± → D0(bar) π± if (flag == 0) { if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDStar, std::array{+kPiPlus, +kPiPlus, -kKPlus}, true, &sign, 2)) { - flag = sign * (1 << o2::aod::hf_cand_3prong::DstarToPiKPiBkg); + flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::DstarToPiKPi; } } // Λc± → p± K∓ π± if (flag == 0) { if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { - flag = sign * (1 << o2::aod::hf_cand_3prong::DecayType::LcToPKPi); + flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi; // Flagging the different Λc± → p± K∓ π± decay channels RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{0}, 1); - if (arrDaughIndex.size() == 2) { + if (arrDaughIndex.size() == NDaughtersResonant) { for (auto jProng = 0u; jProng < arrDaughIndex.size(); ++jProng) { auto daughJ = mcParticles.rawIteratorAt(arrDaughIndex[jProng]); arrPDGDaugh[jProng] = std::abs(daughJ.pdgCode()); @@ -175,7 +177,7 @@ void fillMcMatchGen3Prong(T const& mcParticles, U const& mcParticlesPerMcColl, V // Ξc± → p± K∓ π± if (flag == 0) { if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { - flag = sign * (1 << o2::aod::hf_cand_3prong::DecayType::XicToPKPi); + flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi; } } diff --git a/PWGJE/Core/JetFindingUtilities.h b/PWGJE/Core/JetFindingUtilities.h index d99c84ecbbf..ac81338a99d 100644 --- a/PWGJE/Core/JetFindingUtilities.h +++ b/PWGJE/Core/JetFindingUtilities.h @@ -224,7 +224,7 @@ bool analyseCandidateMC(std::vector& inputParticles, T const * @param v0s V0 candidates */ template -bool analyseV0s(std::vector& inputParticles, T const& v0s, float v0PtMin, float v0PtMax, float v0YMin, float v0YMax, int v0Index) +bool analyseV0s(std::vector& inputParticles, T const& v0s, float v0PtMin, float v0PtMax, float v0YMin, float v0YMax, int v0Index, bool useV0SignalFlags) { float v0Mass = 0; float v0Y = -10.0; @@ -235,6 +235,9 @@ bool analyseV0s(std::vector& inputParticles, T const& v0s, f v0Mass = v0.m(); v0Y = v0.y(); } else { + if (useV0SignalFlags && v0.isRejectedCandidate()) { + continue; + } if (v0Index == 0) { v0Mass = o2::constants::physics::MassKaonNeutral; } diff --git a/PWGJE/Core/JetHFUtilities.h b/PWGJE/Core/JetHFUtilities.h index 97394dd6a70..a5ec07fe157 100644 --- a/PWGJE/Core/JetHFUtilities.h +++ b/PWGJE/Core/JetHFUtilities.h @@ -283,13 +283,13 @@ constexpr bool isMatchedHFCandidate(T const& candidate) return false; } } else if constexpr (isDplusCandidate()) { - if (std::abs(candidate.flagMcMatchRec()) == 1 << o2::aod::hf_cand_3prong::DecayType::DplusToPiKPi) { + if (std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) { return true; } else { return false; } } else if constexpr (isLcCandidate()) { - if (std::abs(candidate.flagMcMatchRec()) == 1 << o2::aod::hf_cand_3prong::DecayType::LcToPKPi) { + if (std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { return true; } else { return false; @@ -307,13 +307,13 @@ constexpr bool isMatchedHFCandidate(T const& candidate) return false; } } else if constexpr (isDplusMcCandidate()) { - if (std::abs(candidate.flagMcMatchGen()) == 1 << o2::aod::hf_cand_3prong::DecayType::DplusToPiKPi) { + if (std::abs(candidate.flagMcMatchGen()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) { return true; } else { return false; } } else if constexpr (isLcMcCandidate()) { - if (std::abs(candidate.flagMcMatchGen()) == 1 << o2::aod::hf_cand_3prong::DecayType::LcToPKPi) { + if (std::abs(candidate.flagMcMatchGen()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { return true; } else { return false; diff --git a/PWGJE/DataModel/Jet.h b/PWGJE/DataModel/Jet.h index 8db401ffc48..57731df23ba 100644 --- a/PWGJE/DataModel/Jet.h +++ b/PWGJE/DataModel/Jet.h @@ -35,6 +35,7 @@ #include "PWGHF/DataModel/DerivedTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/V0SelectorTables.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" namespace o2::aod @@ -244,8 +245,8 @@ using JetParticlesSubBplus = JMcParticleBplusSubs; using McCollisionsBplus = o2::soa::Join; using CandidatesBplusMCP = o2::soa::Join; -using CandidatesV0Data = o2::soa::Join; -using CandidatesV0MCD = o2::soa::Join; +using CandidatesV0Data = o2::soa::Join; +using CandidatesV0MCD = o2::soa::Join; // using V0Daughters = DauTrackExtras; using McCollisionsV0 = o2::soa::Join; using CandidatesV0MCP = o2::soa::Join; diff --git a/PWGJE/JetFinders/jetFinderV0.cxx b/PWGJE/JetFinders/jetFinderV0.cxx index 560968ce0fd..ece753369d9 100644 --- a/PWGJE/JetFinders/jetFinderV0.cxx +++ b/PWGJE/JetFinders/jetFinderV0.cxx @@ -37,6 +37,7 @@ #include "PWGJE/Core/JetFindingUtilities.h" #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" +#include "PWGLF/DataModel/V0SelectorTables.h" using namespace o2; using namespace o2::framework; @@ -93,6 +94,7 @@ struct JetFinderV0Task { Configurable jetPtBinWidth{"jetPtBinWidth", 5, "used to define the width of the jetPt bins for the THnSparse"}; Configurable fillTHnSparse{"fillTHnSparse", true, "switch to fill the THnSparse"}; Configurable jetExtraParam{"jetExtraParam", -99.0, "sets the _extra_param in fastjet"}; + Configurable useV0SignalFlags{"useV0SignalFlags", true, "use V0 signal flags table"}; Service pdgDatabase; int trackSelection = -1; @@ -161,7 +163,6 @@ struct JetFinderV0Task { Filter mcCollisionFilter = ((skipMBGapEvents.node() == false) || (aod::jmccollision::subGeneratorId != static_cast(jetderiveddatautilities::JCollisionSubGeneratorId::mbGap))); // should we add a posZ vtx cut here or leave it to analysers? Filter trackCuts = (aod::jtrack::pt >= trackPtMin && aod::jtrack::pt < trackPtMax && aod::jtrack::eta >= trackEtaMin && aod::jtrack::eta <= trackEtaMax && aod::jtrack::phi >= trackPhiMin && aod::jtrack::phi <= trackPhiMax); Filter partCuts = (aod::jmcparticle::pt >= trackPtMin && aod::jmcparticle::pt < trackPtMax && aod::jmcparticle::eta >= trackEtaMin && aod::jmcparticle::eta <= trackEtaMax && aod::jmcparticle::phi >= trackPhiMin && aod::jmcparticle::phi <= trackPhiMax); - // Filter candidateCuts = (aod::hfcand::pt >= candPtMin && aod::hfcand::pt < candPtMax && aod::hfcand::y >= candYMin && aod::hfcand::y < candYMax); // function that generalically processes Data and reco level events template @@ -171,7 +172,7 @@ struct JetFinderV0Task { return; } inputParticles.clear(); - if (!jetfindingutilities::analyseV0s(inputParticles, candidates, candPtMin, candPtMax, candYMin, candYMax, candIndex)) { + if (!jetfindingutilities::analyseV0s(inputParticles, candidates, candPtMin, candPtMax, candYMin, candYMax, candIndex, useV0SignalFlags)) { return; } @@ -192,7 +193,7 @@ struct JetFinderV0Task { { inputParticles.clear(); - if (!jetfindingutilities::analyseV0s(inputParticles, candidates, candPtMin, candPtMax, candYMin, candYMax, candIndex)) { + if (!jetfindingutilities::analyseV0s(inputParticles, candidates, candPtMin, candPtMax, candYMin, candYMax, candIndex, useV0SignalFlags)) { return; } jetfindingutilities::analyseParticles(inputParticles, particleSelection, jetTypeParticleLevel, particles, pdgDatabase, &candidates); diff --git a/PWGJE/Tasks/CMakeLists.txt b/PWGJE/Tasks/CMakeLists.txt index 1a0854a2fbf..0e39c04445a 100644 --- a/PWGJE/Tasks/CMakeLists.txt +++ b/PWGJE/Tasks/CMakeLists.txt @@ -241,8 +241,8 @@ if(FastJet_FOUND) SOURCES statPromptPhoton.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(full-jet-spectra-pp - SOURCES fullJetSpectraPP.cxx + o2physics_add_dpl_workflow(full-jet-spectra + SOURCES fullJetSpectra.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(bjet-tagging-ml diff --git a/PWGJE/Tasks/fullJetSpectraPP.cxx b/PWGJE/Tasks/fullJetSpectra.cxx similarity index 52% rename from PWGJE/Tasks/fullJetSpectraPP.cxx rename to PWGJE/Tasks/fullJetSpectra.cxx index a8eb7399502..40e233f9a90 100644 --- a/PWGJE/Tasks/fullJetSpectraPP.cxx +++ b/PWGJE/Tasks/fullJetSpectra.cxx @@ -8,14 +8,16 @@ // 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. - -// FullJet Spectra in pp -// // +/// \file fullJetSpectra.cxx +/// \brief Task for full jet spectra studies in pp collisions. /// \author Archita Rani Dash + #include -#include #include +#include +#include +#include #include "CommonConstants/PhysicsConstants.h" #include "Framework/ASoA.h" @@ -25,6 +27,7 @@ #include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" #include "Framework/RunningWorkflowInfo.h" +#include "Framework/Logger.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" @@ -51,12 +54,17 @@ using namespace o2::framework; using namespace o2::framework::expressions; // using namespace jetderiveddatautilities; -struct FullJetSpectrapp { +struct FullJetSpectra { HistogramRegistry registry; + // MC Sample split configurables + /* Configurable mcSplitSeed{"mcSplitSeed", 12345, "Seed for reproducible MC event splitting"}; + Configurable mcClosureSplitFrac{"mcClosureSplitFrac", 0.2f, "Fraction of MC events for closure test (MCD)"}; + Configurable doMcClosure{"doMcClosure", false, "Enable random splitting for MC closure test"}; + */ // Event configurables - Configurable VertexZCut{"VertexZCut", 10.0f, "Accepted z-vertex range"}; + Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; Configurable centralityMin{"centralityMin", -999.0, "minimum centrality"}; Configurable centralityMax{"centralityMax", 999.0, "maximum centrality"}; Configurable doEMCALEventWorkaround{"doEMCALEventWorkaround", false, "apply the workaround to read the EMC trigger bit by requiring a cell content in the EMCAL"}; @@ -88,8 +96,7 @@ struct FullJetSpectrapp { Configurable particleSelections{"particleSelections", "PhysicalPrimary", "set particle selections"}; // Cluster configurables - - Configurable clusterDefinitionS{"clusterDefinition", "kV3Default", "cluster definition to be selected, e.g. V3Default"}; + Configurable clusterDefinitionS{"clusterDefinitionS", "kV3Default", "cluster definition to be selected, e.g. V3Default"}; Configurable clusterEtaMin{"clusterEtaMin", -0.7, "minimum cluster eta"}; Configurable clusterEtaMax{"clusterEtaMax", 0.7, "maximum cluster eta"}; Configurable clusterPhiMin{"clusterPhiMin", 1.396, "minimum cluster phi"}; @@ -105,6 +112,8 @@ struct FullJetSpectrapp { Configurable pTHatAbsoluteMin{"pTHatAbsoluteMin", -99.0, "minimum value of pTHat"}; int trackSelection = -1; + const float kJetAreaFractionMinThreshold = -98.0f; + const float kLeadingConstituentPtMinThreshold = -98.0f; std::vector eventSelectionBits; std::vector filledJetR; std::vector jetRadiiValues; @@ -113,48 +122,109 @@ struct FullJetSpectrapp { Service pdgDatabase; + // Random splitter instance + /* TRandom3 randGen; + // float eventRandomValue = -1.0; // default invalid + // Cache to store random values per MC collision ID + std::unordered_map mcCollisionRandomValues; + */ + /* + MC CLOSURE SPLITTING LOGIC -> still not working across different process functions. Not so trivial in O2Physics Framework! + -------------------------- + • doMcClosure=true activates MC sample splitting. + • Each event gets ONE random value in [0, 1), stored in eventRandomValue. + • Events are split as: + - ≤ mcClosureSplitFrac -> Closure (MCD) + - > mcClosureSplitFrac -> Response (MCP + Matched) + • This ensures mutually exclusive processing — NO double-counting. + • eventRandomValue is reset to -1 after each event -> this is done by the `endOfEvent` defined at the end + */ + // Add Collision Histograms' Bin Labels for clarity void labelCollisionHistograms(HistogramRegistry& registry) { - if (doprocessTracks) { - auto h_collisions_unweighted = registry.get(HIST("h_collisions_unweighted")); - h_collisions_unweighted->GetXaxis()->SetBinLabel(1, "AllUnweightedDetColl"); - h_collisions_unweighted->GetXaxis()->SetBinLabel(2, "UnweightedCollWithVertexZ"); - h_collisions_unweighted->GetXaxis()->SetBinLabel(3, "EMCAcceptedUnweightedColl"); - h_collisions_unweighted->GetXaxis()->SetBinLabel(4, "UnweightedCollAfterTrackSel"); + if (doprocessDataTracks || doprocessMCTracks) { + auto hCollisionsUnweighted = registry.get(HIST("hCollisionsUnweighted")); + hCollisionsUnweighted->GetXaxis()->SetBinLabel(1, "allDetColl"); + hCollisionsUnweighted->GetXaxis()->SetBinLabel(2, "DetCollWithVertexZ"); + hCollisionsUnweighted->GetXaxis()->SetBinLabel(3, "MBRejectedDetEvents"); + hCollisionsUnweighted->GetXaxis()->SetBinLabel(4, "EventsNotSatisfyingEventSelection"); + hCollisionsUnweighted->GetXaxis()->SetBinLabel(5, "EMCreadoutDetEventsWithkTVXinEMC"); + hCollisionsUnweighted->GetXaxis()->SetBinLabel(6, "AllRejectedEventsAfterEMCEventSelection"); + hCollisionsUnweighted->GetXaxis()->SetBinLabel(7, "EMCAcceptedDetColl"); + hCollisionsUnweighted->GetXaxis()->SetBinLabel(8, "EMCAcceptedCollAfterTrackSel"); } if (doprocessTracksWeighted) { - auto h_collisions_weighted = registry.get(HIST("h_collisions_weighted")); - h_collisions_weighted->GetXaxis()->SetBinLabel(1, "AllWeightedDetColl"); - h_collisions_weighted->GetXaxis()->SetBinLabel(2, "WeightedCollWithVertexZ"); - h_collisions_weighted->GetXaxis()->SetBinLabel(3, "EMCAcceptedWeightedColl"); - h_collisions_weighted->GetXaxis()->SetBinLabel(4, "WeightedCollAfterTrackSel"); + auto hCollisionsWeighted = registry.get(HIST("hCollisionsWeighted")); + hCollisionsWeighted->GetXaxis()->SetBinLabel(1, "AllWeightedDetColl"); + hCollisionsWeighted->GetXaxis()->SetBinLabel(2, "WeightedCollWithVertexZ"); + hCollisionsWeighted->GetXaxis()->SetBinLabel(3, "MBRejectedDetEvents"); + hCollisionsWeighted->GetXaxis()->SetBinLabel(4, "EventsNotSatisfyingEventSelection"); + hCollisionsWeighted->GetXaxis()->SetBinLabel(5, "EMCreadoutDetJJEventsWithkTVXinEMC"); + hCollisionsWeighted->GetXaxis()->SetBinLabel(6, "AllRejectedEventsAfterEMCEventSelection"); + hCollisionsWeighted->GetXaxis()->SetBinLabel(7, "EMCAcceptedWeightedDetColl"); + hCollisionsWeighted->GetXaxis()->SetBinLabel(8, "EMCAcceptedWeightedCollAfterTrackSel"); } if (doprocessJetsData || doprocessJetsMCD || doprocessJetsMCDWeighted) { - auto h_Detcollision_counter = registry.get(HIST("h_Detcollision_counter")); - h_Detcollision_counter->GetXaxis()->SetBinLabel(1, "allDetColl"); - h_Detcollision_counter->GetXaxis()->SetBinLabel(2, "DetCollWithVertexZ"); - h_Detcollision_counter->GetXaxis()->SetBinLabel(3, "EMCAcceptedDetColl"); + auto hDetcollisionCounter = registry.get(HIST("hDetcollisionCounter")); + hDetcollisionCounter->GetXaxis()->SetBinLabel(1, "allDetColl"); + hDetcollisionCounter->GetXaxis()->SetBinLabel(2, "DetCollWithVertexZ"); + hDetcollisionCounter->GetXaxis()->SetBinLabel(3, "RejectedDetCollWithOutliers"); + hDetcollisionCounter->GetXaxis()->SetBinLabel(4, "MBRejectedDetEvents"); + hDetcollisionCounter->GetXaxis()->SetBinLabel(5, "EventsNotSatisfyingEventSelection"); + hDetcollisionCounter->GetXaxis()->SetBinLabel(6, "EMCreadoutDetEventsWithkTVXinEMC"); + hDetcollisionCounter->GetXaxis()->SetBinLabel(7, "AllRejectedEventsAfterEMCEventSelection"); + hDetcollisionCounter->GetXaxis()->SetBinLabel(8, "EMCAcceptedDetColl"); } if (doprocessJetsMCP || doprocessJetsMCPWeighted) { - auto h_Partcollision_counter = registry.get(HIST("h_Partcollision_counter")); - h_Partcollision_counter->GetXaxis()->SetBinLabel(1, "allMcColl"); - h_Partcollision_counter->GetXaxis()->SetBinLabel(2, "McCollWithVertexZ"); - h_Partcollision_counter->GetXaxis()->SetBinLabel(3, "DetCollWithSize>1"); - h_Partcollision_counter->GetXaxis()->SetBinLabel(4, "EMCAcceptedDetColl"); + auto hPartcollisionCounter = registry.get(HIST("hPartcollisionCounter")); + hPartcollisionCounter->GetXaxis()->SetBinLabel(1, "allMcColl"); + hPartcollisionCounter->GetXaxis()->SetBinLabel(2, "McCollWithVertexZ"); + hPartcollisionCounter->GetXaxis()->SetBinLabel(3, "PartCollWithSize>1"); + hPartcollisionCounter->GetXaxis()->SetBinLabel(4, "RejectedPartCollForDetCollWithSize0"); + hPartcollisionCounter->GetXaxis()->SetBinLabel(5, "RejectedPartCollWithOutliers"); + hPartcollisionCounter->GetXaxis()->SetBinLabel(6, "MBRejectedPartEvents"); + hPartcollisionCounter->GetXaxis()->SetBinLabel(7, "EMCreadoutDetJJEventsWithkTVXinEMC"); + hPartcollisionCounter->GetXaxis()->SetBinLabel(8, "AllRejectedPartEventsAfterEMCEventSelection"); + hPartcollisionCounter->GetXaxis()->SetBinLabel(9, "EMCAcceptedPartColl"); } if (doprocessJetsMCPMCDMatched || doprocessJetsMCPMCDMatchedWeighted) { - auto h_Matchedcollision_counter = registry.get(HIST("h_Matchedcollision_counter")); - h_Matchedcollision_counter->GetXaxis()->SetBinLabel(1, "allDetColl"); - h_Matchedcollision_counter->GetXaxis()->SetBinLabel(2, "DetCollWithVertexZ"); - h_Matchedcollision_counter->GetXaxis()->SetBinLabel(3, "EMCAcceptedDetColl"); + auto hMatchedcollisionCounter = registry.get(HIST("hMatchedcollisionCounter")); + hMatchedcollisionCounter->GetXaxis()->SetBinLabel(1, "allDetColl"); + hMatchedcollisionCounter->GetXaxis()->SetBinLabel(2, "DetCollWithVertexZ"); + hMatchedcollisionCounter->GetXaxis()->SetBinLabel(3, "RejectedDetCollWithOutliers"); + hMatchedcollisionCounter->GetXaxis()->SetBinLabel(4, "RejectedPartCollWithOutliers"); + hMatchedcollisionCounter->GetXaxis()->SetBinLabel(5, "EMCMBRejectedDetColl"); + hMatchedcollisionCounter->GetXaxis()->SetBinLabel(6, "EventsNotSatisfyingEventSelection"); + hMatchedcollisionCounter->GetXaxis()->SetBinLabel(7, "EMCreadoutDetJJEventsWithkTVXinEMC"); + hMatchedcollisionCounter->GetXaxis()->SetBinLabel(8, "AllRejectedDetEventsAfterEMCEventSelection"); + hMatchedcollisionCounter->GetXaxis()->SetBinLabel(9, "EMCAcceptedDetColl"); + } + + if (doprocessMBCollisionsDATAWithMultiplicity || doprocessMBCollisionsWithMultiplicity || doprocessCollisionsWeightedWithMultiplicity) { + auto hEventmultiplicityCounter = registry.get(HIST("hEventmultiplicityCounter")); + hEventmultiplicityCounter->GetXaxis()->SetBinLabel(1, "allDetColl"); + hEventmultiplicityCounter->GetXaxis()->SetBinLabel(2, "DetCollWithVertexZ"); + hEventmultiplicityCounter->GetXaxis()->SetBinLabel(3, "MBRejectedDetEvents"); + hEventmultiplicityCounter->GetXaxis()->SetBinLabel(4, "EventsNotSatisfyingEventSelection"); + hEventmultiplicityCounter->GetXaxis()->SetBinLabel(5, "EMCreadoutDetEventsWithkTVXinEMC"); + hEventmultiplicityCounter->GetXaxis()->SetBinLabel(6, "AllRejectedEventsAfterEMCEventSelection"); + hEventmultiplicityCounter->GetXaxis()->SetBinLabel(7, "EMCAcceptedDetColl"); } } + // Add Bin Labels for the MC Split Event Counter + /* void labelMCSplitHistogram(HistogramRegistry& registry) { + auto hSpliteventSelector = registry.get(HIST("hSpliteventSelector")); + hSpliteventSelector->GetXaxis()->SetBinLabel(1, "MCD"); + hSpliteventSelector->GetXaxis()->SetBinLabel(2, "MCP"); + hSpliteventSelector->GetXaxis()->SetBinLabel(3, "MatchedforRM"); +} +*/ void init(o2::framework::InitContext&) { trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); @@ -162,19 +232,46 @@ struct FullJetSpectrapp { particleSelection = static_cast(particleSelections); jetRadiiValues = (std::vector)jetRadii; + /* if (doMcClosure) { + // randGen.SetSeed(mcSplitSeed); + // randGen.SetSeed(static_cast(std::time(nullptr))); + // int seed = mcSplitSeed >= 0 ? mcSplitSeed : static_cast(std::time(nullptr)); + // randGen.SetSeed(seed); + // LOGF(info, "MC closure seed = %d", seed); + + int seed = mcSplitSeed >= 0 ? mcSplitSeed : static_cast(std::time(nullptr)); + randGen.SetSeed(seed); + LOGF(info, "MC closure splitting enabled with seed = %d, split fraction = %.2f", seed, static_cast(mcClosureSplitFrac)); + + registry.add("hSpliteventSelector", "Random MC Split Selector;Split Type;Entries",{HistType::kTH1F, {{3, 0.0, 3.0}}}); // 0=MCD, 1=MCP, 2=RM + + //individual processes' event counters for sanity checks + registry.add("h_MCD_splitevent_counter", "Events into MCD split", {HistType::kTH1F, {{1, 0.0, 1.0}}}); + registry.add("h_MCP_splitevent_counter", "Events into MCP split", {HistType::kTH1F, {{1, 0.0, 1.0}}}); + registry.add("h_Matched_splitevent_counter", "Events into Matched split", {HistType::kTH1F, {{1, 0.0, 1.0}}}); + registry.add("hRandomValueDebug", "Random values for debugging;Random Value;Entries", {HistType::kTH1F, {{100, 0.0, 1.0}}}); + + // DEBUG: Add counters for total events processed (before splitting) + registry.add("h_MCD_total_events", "Total MCD events processed", {HistType::kTH1F, {{1, 0.0, 1.0}}}); + registry.add("h_MCP_total_events", "Total MCP events processed", {HistType::kTH1F, {{1, 0.0, 1.0}}}); + registry.add("h_Matched_total_events", "Total Matched events processed", {HistType::kTH1F, {{1, 0.0, 1.0}}}); + registry.add("hMCCollisionIdDebug_MCP", "MC Collision Ids being processed", {HistType::kTH1F, {{100000, 0.0, 100000.0}}}); + + } + */ for (std::size_t iJetRadius = 0; iJetRadius < jetRadiiValues.size(); iJetRadius++) { filledJetR.push_back(0.0); } auto jetRadiiBins = (std::vector)jetRadii; if (jetRadiiBins.size() > 1) { - jetRadiiBins.push_back(jetRadiiBins[jetRadiiBins.size() - 1] + (TMath::Abs(jetRadiiBins[jetRadiiBins.size() - 1] - jetRadiiBins[jetRadiiBins.size() - 2]))); + jetRadiiBins.push_back(jetRadiiBins[jetRadiiBins.size() - 1] + (std::abs(jetRadiiBins[jetRadiiBins.size() - 1] - jetRadiiBins[jetRadiiBins.size() - 2]))); } else { jetRadiiBins.push_back(jetRadiiBins[jetRadiiBins.size() - 1] + 0.1); } // Track QA histograms - if (doprocessTracks || doprocessTracksWeighted) { - registry.add("h_collisions_unweighted", "event status; event status;entries", {HistType::kTH1F, {{12, 0., 12.0}}}); + if (doprocessDataTracks || doprocessMCTracks || doprocessTracksWeighted) { + registry.add("hCollisionsUnweighted", "event status; event status;entries", {HistType::kTH1F, {{12, 0., 12.0}}}); registry.add("h_track_pt", "track pT;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); registry.add("h_track_eta", "track #eta;#eta_{track};entries", {HistType::kTH1F, {{100, -1., 1.}}}); @@ -191,21 +288,22 @@ struct FullJetSpectrapp { registry.add("h_cluster_energysum", "cluster energy sum;Sum of cluster energy per event;entries", {HistType::kTH1F, {{400, 0., 400.}}}); if (doprocessTracksWeighted) { - registry.add("h_collisions_weighted", "event status;event status;entries", {HistType::kTH1F, {{12, 0.0, 12.0}}}); + registry.add("hCollisionsWeighted", "event status;event status;entries", {HistType::kTH1F, {{12, 0.0, 12.0}}}); } } // Jet QA histograms if (doprocessJetsData || doprocessJetsMCD || doprocessJetsMCDWeighted) { - registry.add("h_Detcollision_counter", "event status;event status;entries", {HistType::kTH1F, {{10, 0.0, 10.}}}); + + registry.add("hDetcollisionCounter", "event status;event status;entries", {HistType::kTH1F, {{10, 0.0, 10.}}}); registry.add("h_full_jet_pt", "#it{p}_{T,jet};#it{p}_{T_jet} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); registry.add("h_full_jet_pt_pTHatcut", "#it{p}_{T,jet};#it{p}_{T_jet} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); registry.add("h_full_jet_eta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1., 1.}}}); registry.add("h_full_jet_phi", "jet #varphi;#varphi_{jet};entries", {HistType::kTH1F, {{160, 0., 7.}}}); registry.add("h_full_jet_clusterTime", "Time of cluster", HistType::kTH1F, {{500, -250, 250, "#it{t}_{cls} (ns)"}}); - registry.add("h2_full_jet_NEF", "#it{p}_{T,jet} vs NEF at Det Level; #it{p}_{T,jet} (GeV/#it{c});NEF", {HistType::kTH2F, {{350, 0., 350.}, {105, 0., 1.05}}}); - registry.add("h2_full_jet_NEF_rejected", "#it{p}_{T,jet} vs NEF at Det Level for rejected events; #it{p}_{T,jet} (GeV/#it{c});NEF", {HistType::kTH2F, {{350, 0., 350.}, {105, 0., 1.05}}}); + registry.add("h2_full_jet_nef", "#it{p}_{T,jet} vs nef at Det Level; #it{p}_{T,jet} (GeV/#it{c});nef", {HistType::kTH2F, {{350, 0., 350.}, {105, 0., 1.05}}}); + registry.add("h2_full_jet_nef_rejected", "#it{p}_{T,jet} vs nef at Det Level for rejected events; #it{p}_{T,jet} (GeV/#it{c});nef", {HistType::kTH2F, {{350, 0., 350.}, {105, 0., 1.05}}}); registry.add("h_Detjet_ntracks", "#it{p}_{T,track};#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); registry.add("h2_full_jet_chargedconstituents", "Number of charged constituents at Det Level;#it{p}_{T,jet} (GeV/#it{c});N_{ch}", {HistType::kTH2F, {{350, 0., 350.}, {100, 0., 100.}}}); @@ -228,14 +326,14 @@ struct FullJetSpectrapp { registry.add("h2_jet_etaphi", "jet #eta vs jet #varphi; #eta_{jet};#varphi_{jet}", {HistType::kTH2F, {{100, -1., 1.}, {160, -1., 7.}}}); } if (doprocessJetsMCP || doprocessJetsMCPWeighted) { - registry.add("h_Partcollision_counter", "event status;event status;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); + registry.add("hPartcollisionCounter", "event status;event status;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); registry.add("h_full_mcpjet_tablesize", "", {HistType::kTH1F, {{4, 0., 5.}}}); registry.add("h_full_mcpjet_ntracks", "", {HistType::kTH1F, {{200, -0.5, 200.}}}); registry.add("h_full_jet_pt_part", "jet pT;#it{p}_{T_jet} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); registry.add("h_full_jet_eta_part", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1., 1.}}}); registry.add("h_full_jet_phi_part", "jet #varphi;#varphi_{jet};entries", {HistType::kTH1F, {{160, 0., 7.}}}); - registry.add("h2_full_jet_NEF_part", "#it{p}_{T,jet} vs NEF at Part Level;#it{p}_{T,jet} (GeV/#it{c});NEF", {HistType::kTH2F, {{350, 0., 350.}, {105, 0., 1.05}}}); + registry.add("h2_full_jet_nef_part", "#it{p}_{T,jet} vs nef at Part Level;#it{p}_{T,jet} (GeV/#it{c});nef", {HistType::kTH2F, {{350, 0., 350.}, {105, 0., 1.05}}}); registry.add("h_Partjet_ntracks", "#it{p}_{T,constituent};#it{p}_{T_constituent} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); registry.add("h2_full_jet_chargedconstituents_part", "Number of charged constituents at Part Level;#it{p}_{T,jet} (GeV/#it{c});N_{ch}", {HistType::kTH2F, {{350, 0., 350.}, {100, 0., 100.}}}); @@ -253,12 +351,18 @@ struct FullJetSpectrapp { registry.add("h2_track_etaphi_part", "jet_track #eta vs jet_track #varphi; #eta_{track};#varphi_{track}", {HistType::kTH2F, {{500, -5., 5.}, {160, -1., 7.}}}); registry.add("h2_jet_etaphi_part", "jet #eta vs jet #varphi; #eta_{jet};#varphi_{jet}", {HistType::kTH2F, {{100, -1., 1.}, {160, -1., 7.}}}); - registry.add("h_NOmcpemcalcollisions", "event status;entries", {HistType::kTH1F, {{100, 0., 100.}}}); - registry.add("h_mcpemcalcollisions", "event status;entries", {HistType::kTH1F, {{100, 0., 100.}}}); + // registry.add("h_NOmcpemcalcollisions", "event status;entries", {HistType::kTH1F, {{100, 0., 100.}}}); + // registry.add("h_mcpemcalcollisions", "event status;entries", {HistType::kTH1F, {{100, 0., 100.}}}); + registry.add("h2_full_mcpjetOutsideFiducial_pt", "MCP jet outside EMC Fiducial Acceptance #it{p}_{T,part};#it{p}_{T,part} (GeV/c); Ncounts", {HistType::kTH2F, {{350, 0., 350.}, {10000, 0., 10000.}}}); + registry.add("h_full_mcpjetOutside_eta_part", "MCP jet #eta outside EMC Fiducial Acceptance;#eta_{jet};entries", {HistType::kTH1F, {{100, -1., 1.}}}); + registry.add("h_full_mcpjetOutside_phi_part", "MCP jet #varphi outside EMC Fiducial Acceptance;#varphi_{jet};entries", {HistType::kTH1F, {{160, 0., 7.}}}); + registry.add("h2_full_mcpjetInsideFiducial_pt", "MCP jet #it{p}_{T,part} inside EMC Fiducial Acceptance;#it{p}_{T,part} (GeV/c); Ncounts", {HistType::kTH2F, {{350, 0., 350.}, {10000, 0., 10000.}}}); + registry.add("h_full_mcpjetInside_eta_part", "MCP jet #eta inside EMC Fiducial Acceptance;#eta_{jet};entries", {HistType::kTH1F, {{100, -1., 1.}}}); + registry.add("h_full_mcpjetInside_phi_part", "MCP jet #varphi inside EMC Fiducial Acceptance;#varphi_{jet};entries", {HistType::kTH1F, {{160, 0., 7.}}}); } if (doprocessJetsMCPMCDMatched || doprocessJetsMCPMCDMatchedWeighted) { - registry.add("h_Matchedcollision_counter", "event status;event status;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); + registry.add("hMatchedcollisionCounter", "event status;event status;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); registry.add("h_full_matchedmcdjet_tablesize", "", {HistType::kTH1F, {{350, 0., 350.}}}); registry.add("h_full_matchedmcpjet_tablesize", "", {HistType::kTH1F, {{350, 0., 350.}}}); @@ -286,23 +390,49 @@ struct FullJetSpectrapp { registry.add("h2_full_jet_energyscaleChargedVsFullPart", "Jet Energy Scale (charged part, vs. full jet pt); p_{T,part} (GeV/c); (p_{T,det} - p_{T,part})/p_{T,part}", {HistType::kTH2F, {{400, 0., 400.}, {200, -1., 1.}}}); registry.add("h2_full_jet_energyscaleNeutralVsFullPart", "Jet Energy Scale (neutral part, vs. full jet pt); p_{T,part} (GeV/c); (p_{T,det} - p_{T,part})/p_{T,part}", {HistType::kTH2F, {{400, 0., 400.}, {200, -1., 1.}}}); registry.add("h2_full_fakemcdjets", "Fake MCD Jets; p_{T,det} (GeV/c); NCounts", {HistType::kTH2F, {{350, 0., 350.}, {100, 0., 100.}}}); - registry.add("h2_full_fakemcpjets", "Fake MCP Jets; p_{T,part} (GeV/c); NCounts", {HistType::kTH2F, {{350, 0., 350.}, {100, 0., 100.}}}); + registry.add("h2FullfakeMcpJets", "Fake MCP Jets; p_{T,part} (GeV/c); NCounts", {HistType::kTH2F, {{350, 0., 350.}, {100, 0., 100.}}}); + registry.add("h2_full_matchedmcpjet_pt", "Matched MCP jet in EMC Fiducial Acceptance #it{p}_{T,part};#it{p}_{T,part} (GeV/c); Ncounts", {HistType::kTH2F, {{350, 0., 350.}, {10000, 0., 10000.}}}); + // Response Matrix registry.add("h_full_jet_ResponseMatrix", "Full Jets Response Matrix; p_{T,det} (GeV/c); p_{T,part} (GeV/c)", {HistType::kTH2F, {{350, 0., 350.}, {350, 0., 350.}}}); } - if (doprocessCollisionsWeightedWithMultiplicity || doprocessMBCollisionsWithMultiplicity) { + if (doprocessCollisionsWeightedWithMultiplicity || doprocessMBCollisionsWithMultiplicity || doprocessMBCollisionsDATAWithMultiplicity) { + registry.add("hEventmultiplicityCounter", "event status;event status;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); registry.add("h_FT0Mults_occupancy", "", {HistType::kTH1F, {{3500, 0., 3500.}}}); registry.add("h2_full_jet_FT0Amplitude", "; FT0C Amplitude; Counts", {HistType::kTH1F, {{3500, 0., 3500.}}}); registry.add("h2_full_jet_jetpTDetVsFT0Mults", "; p_{T,det} (GeV/c); FT0C Multiplicity", {HistType::kTH2F, {{350, 0., 350.}, {3500, 0., 3500.}}}); - registry.add("h3_full_jet_jetpTDet_FT0Mults_NEF", "; p_{T,det} (GeV/c); FT0C Multiplicity, NEF", {HistType::kTH3F, {{350, 0., 350.}, {3500, 0., 3500.}, {105, 0.0, 1.05}}}); + registry.add("h3_full_jet_jetpTDet_FT0Mults_nef", "; p_{T,det} (GeV/c); FT0C Multiplicity, nef", {HistType::kTH3F, {{350, 0., 350.}, {3500, 0., 3500.}, {105, 0.0, 1.05}}}); } // Label the histograms labelCollisionHistograms(registry); + // labelMCSplitHistogram(registry); } // init + // Get or generate random value for a specific MC collision + /* float getMCCollisionRandomValue(int64_t mcCollisionId) { + if (!doMcClosure) return 0.0f; + + // Check if I already have a random value for this MC collision + auto it = mcCollisionRandomValues.find(mcCollisionId); + if (it != mcCollisionRandomValues.end()) { + LOGF(debug, "Using cached random value %.4f for MC collision %lld", it->second, mcCollisionId); + return it->second; + } + + // Generate new random value for this MC collision + float randomVal = randGen.Uniform(0.0, 1.0); + mcCollisionRandomValues[mcCollisionId] = randomVal; + + // Debug histogram + registry.fill(HIST("hRandomValueDebug"), randomVal); + + LOGF(info, "Generated NEW random value %.4f for MC collision %lld", randomVal, mcCollisionId); + return randomVal; + } + */ using EMCCollisionsData = o2::soa::Join; // JetCollisions with EMCAL Collision Labels using EMCCollisionsMCD = o2::soa::Join; // where, JetCollisionsMCD = JetCollisions+JMcCollisionLbs @@ -313,33 +443,33 @@ struct FullJetSpectrapp { using JetTableMCPWeightedJoined = soa::Join; using JetTableMCDMatchedJoined = soa::Join; - using JetTableMCPMatchedJoined = soa::Join; + using jetMcpPerMcCollision = soa::Join; using JetTableMCDMatchedWeightedJoined = soa::Join; using JetTableMCPMatchedWeightedJoined = soa::Join; // Applying some cuts(filters) on collisions, tracks, clusters - Filter eventCuts = (nabs(aod::jcollision::posZ) < VertexZCut && aod::jcollision::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); - // Filter EMCeventCuts = (nabs(aod::collision::posZ) < VertexZCut && aod::collision::centrality >= centralityMin && aod::collision::centrality < centralityMax); + Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); + // Filter EMCeventCuts = (nabs(aod::collision::posZ) < vertexZCut && aod::collision::centrality >= centralityMin && aod::collision::centrality < centralityMax); Filter trackCuts = (aod::jtrack::pt >= trackpTMin && aod::jtrack::pt < trackpTMax && aod::jtrack::eta > trackEtaMin && aod::jtrack::eta < trackEtaMax && aod::jtrack::phi >= trackPhiMin && aod::jtrack::phi <= trackPhiMax); aod::EMCALClusterDefinition clusterDefinition = aod::emcalcluster::getClusterDefinitionFromString(clusterDefinitionS.value); Filter clusterFilter = (aod::jcluster::definition == static_cast(clusterDefinition) && aod::jcluster::eta > clusterEtaMin && aod::jcluster::eta < clusterEtaMax && aod::jcluster::phi >= clusterPhiMin && aod::jcluster::phi <= clusterPhiMax && aod::jcluster::energy >= clusterEnergyMin && aod::jcluster::time > clusterTimeMin && aod::jcluster::time < clusterTimeMax && (clusterRejectExotics && aod::jcluster::isExotic != true)); - Preslice JetMCPPerMcCollision = aod::jet::mcCollisionId; + Preslice JetMCPPerMcCollision = aod::jet::mcCollisionId; PresliceUnsorted> CollisionsPerMCPCollision = aod::jmccollisionlb::mcCollisionId; template bool isAcceptedJet(U const& jet) { - if (jetAreaFractionMin > -98.0) { - if (jet.area() < jetAreaFractionMin * M_PI * (jet.r() / 100.0) * (jet.r() / 100.0)) { + if (jetAreaFractionMin > kJetAreaFractionMinThreshold) { + if (jet.area() < jetAreaFractionMin * o2::constants::math::PI * (jet.r() / 100.0) * (jet.r() / 100.0)) { return false; } } - if (leadingConstituentPtMin > -98.0) { + if (leadingConstituentPtMin > kLeadingConstituentPtMinThreshold) { bool isMinleadingConstituent = false; - for (auto& constituent : jet.template tracks_as()) { + for (const auto& constituent : jet.template tracks_as()) { if (constituent.pt() >= leadingConstituentPtMin) { isMinleadingConstituent = true; break; @@ -355,11 +485,6 @@ struct FullJetSpectrapp { template void fillJetHistograms(T const& jet, float weight = 1.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); - if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { // for MCD jets only to remove outliers; setting pTHatMaxMCD = 1 improves purity - return; - } - float neutralEnergy = 0.0; double sumtrackE = 0.0; if (jet.r() == round(selectedJetsRadius * 100.0f)) { @@ -368,7 +493,7 @@ struct FullJetSpectrapp { registry.fill(HIST("h_full_jet_phi"), jet.phi(), weight); registry.fill(HIST("h2_jet_etaphi"), jet.eta(), jet.phi(), weight); - for (auto& cluster : jet.template clusters_as()) { + for (const auto& cluster : jet.template clusters_as()) { registry.fill(HIST("h2_full_jet_neutralconstituents"), jet.pt(), jet.clustersIds().size(), weight); neutralEnergy += cluster.energy(); @@ -380,10 +505,10 @@ struct FullJetSpectrapp { registry.fill(HIST("h_full_jet_neutralconstituents_energy"), cluster.energy(), weight); registry.fill(HIST("h_full_jet_neutralconstituents_energysum"), neutralEnergy, weight); } - auto NEF = neutralEnergy / jet.energy(); - registry.fill(HIST("h2_full_jet_NEF"), jet.pt(), NEF, weight); + auto nef = neutralEnergy / jet.energy(); + registry.fill(HIST("h2_full_jet_nef"), jet.pt(), nef, weight); - for (auto& jettrack : jet.template tracks_as()) { + for (const auto& jettrack : jet.template tracks_as()) { sumtrackE += jettrack.energy(); registry.fill(HIST("h_Detjet_ntracks"), jettrack.pt(), weight); @@ -402,30 +527,34 @@ struct FullJetSpectrapp { } // jet.r() } - // check for NEF distribution for rejected events + // check for nef distribution for rejected events template void fillRejectedJetHistograms(T const& jet, float weight = 1.0) { float neutralEnergy = 0.0; if (jet.r() == round(selectedJetsRadius * 100.0f)) { - for (auto& cluster : jet.template clusters_as()) { + for (const auto& cluster : jet.template clusters_as()) { neutralEnergy += cluster.energy(); } - auto NEF = neutralEnergy / jet.energy(); - registry.fill(HIST("h2_full_jet_NEF_rejected"), jet.pt(), NEF, weight); + auto nef = neutralEnergy / jet.energy(); + registry.fill(HIST("h2_full_jet_nef_rejected"), jet.pt(), nef, weight); } // jet.r() } template void fillMCPHistograms(T const& jet, float weight = 1.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); - if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { // MCP outlier rejection - return; - } float neutralEnergy = 0.0; int neutralconsts = 0; int chargedconsts = 0; + int mcpjetOutsideFid = 0; + int mcpjetInsideFid = 0; + + auto isInFiducial = [&](auto const& jet) { + return jet.eta() >= jetEtaMin && jet.eta() <= jetEtaMax && + jet.phi() >= jetPhiMin && jet.phi() <= jetPhiMax; + }; + if (jet.r() == round(selectedJetsRadius * 100.0f)) { registry.fill(HIST("h_full_mcpjet_tablesize"), jet.size(), weight); registry.fill(HIST("h_full_mcpjet_ntracks"), jet.tracksIds().size(), weight); @@ -434,7 +563,21 @@ struct FullJetSpectrapp { registry.fill(HIST("h_full_jet_phi_part"), jet.phi(), weight); registry.fill(HIST("h2_jet_etaphi_part"), jet.eta(), jet.phi(), weight); - for (auto& constituent : jet.template tracks_as()) { + if (!isInFiducial(jet)) { + // jet is outside + mcpjetOutsideFid++; + registry.fill(HIST("h2_full_mcpjetOutsideFiducial_pt"), jet.pt(), mcpjetOutsideFid, weight); + registry.fill(HIST("h_full_mcpjetOutside_eta_part"), jet.eta(), weight); + registry.fill(HIST("h_full_mcpjetOutside_phi_part"), jet.phi(), weight); + } else { + // jet is inside + mcpjetInsideFid++; + registry.fill(HIST("h2_full_mcpjetInsideFiducial_pt"), jet.pt(), mcpjetInsideFid, weight); + registry.fill(HIST("h_full_mcpjetInside_eta_part"), jet.eta(), weight); + registry.fill(HIST("h_full_mcpjetInside_phi_part"), jet.phi(), weight); + } + + for (const auto& constituent : jet.template tracks_as()) { auto pdgParticle = pdgDatabase->GetParticle(constituent.pdgCode()); if (pdgParticle->Charge() == 0) { neutralconsts++; @@ -456,19 +599,16 @@ struct FullJetSpectrapp { registry.fill(HIST("h2_track_etaphi_part"), constituent.eta(), constituent.phi(), weight); } } // constituent loop - auto NEF = neutralEnergy / jet.energy(); - registry.fill(HIST("h2_full_jet_NEF_part"), jet.pt(), NEF, weight); - } + auto nef = neutralEnergy / jet.energy(); + registry.fill(HIST("h2_full_jet_nef_part"), jet.pt(), nef, weight); + } // jet.r() } template void fillTrackHistograms(T const& tracks, U const& clusters, float weight = 1.0) { double sumtrackE = 0.0; - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); - if (pTHat < pTHatAbsoluteMin) { // Track outlier rejection - return; - } + for (auto const& track : tracks) { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { continue; @@ -484,7 +624,7 @@ struct FullJetSpectrapp { double clusterpt = cluster.energy() / std::cosh(cluster.eta()); sumclusterE += cluster.energy(); - registry.fill(HIST("h_clusterTime"), cluster.time()); + registry.fill(HIST("h_clusterTime"), cluster.time(), weight); registry.fill(HIST("h_cluster_pt"), clusterpt, weight); registry.fill(HIST("h_cluster_eta"), cluster.eta(), weight); registry.fill(HIST("h_cluster_phi"), cluster.phi(), weight); @@ -496,20 +636,12 @@ struct FullJetSpectrapp { template void fillMatchedHistograms(T const& jetBase, float weight = 1.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); - if (jetBase.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { - return; - } - if (jetBase.has_matchedJetGeo()) { // geometrical jet matching only needed for pp - here,matching Base(Det.level) with Tag (Part. level) jets registry.fill(HIST("h_full_matchedmcdjet_tablesize"), jetBase.size(), weight); registry.fill(HIST("h_full_matchedmcdjet_ntracks"), jetBase.tracksIds().size(), weight); registry.fill(HIST("h2_matchedjet_etaphiDet"), jetBase.eta(), jetBase.phi(), weight); - for (auto& jetTag : jetBase.template matchedJetGeo_as>()) { - if (jetTag.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { // MCP outlier rejection - continue; - } + for (const auto& jetTag : jetBase.template matchedJetGeo_as>()) { auto deltaEta = jetBase.eta() - jetTag.eta(); auto deltaPhi = jetBase.phi() - jetTag.phi(); auto deltaR = jetutilities::deltaR(jetBase, jetTag); @@ -537,31 +669,51 @@ struct FullJetSpectrapp { void processDummy(aod::JetCollisions const&) { } - PROCESS_SWITCH(FullJetSpectrapp, processDummy, "dummy task", true); + PROCESS_SWITCH(FullJetSpectra, processDummy, "dummy task", true); void processJetsData(soa::Filtered::iterator const& collision, FullJetTableDataJoined const& jets, aod::JetTracks const&, aod::JetClusters const&) { bool eventAccepted = false; - registry.fill(HIST("h_Detcollision_counter"), 0.5); + double weight = 1.0; + float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); - if (fabs(collision.posZ()) > VertexZCut) { + registry.fill(HIST("hDetcollisionCounter"), 0.5); // allDetColl + if (std::fabs(collision.posZ()) > vertexZCut) { return; } - registry.fill(HIST("h_Detcollision_counter"), 1.5); + registry.fill(HIST("hDetcollisionCounter"), 1.5); // DetCollWithVertexZ + + // outlier check: for every outlier jet, reject the whole event + for (auto const& jet : jets) { + if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { // for MCD jets only to remove outliers; setting pTHatMaxMCD = 1 improves purity + registry.fill(HIST("hDetcollisionCounter"), 2.5); // RejectedDetCollWithOutliers + return; + } + // this cut only to be used for calculating Jet Purity and not for Response Matrix + // this is mainly applied to remove all high weight jets causing big fluctuations + if (jet.pt() > 1 * pTHat) { + registry.fill(HIST("h_full_jet_pt_pTHatcut"), jet.pt(), weight); + } + } + if (doMBGapTrigger && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + registry.fill(HIST("hDetcollisionCounter"), 3.5); // MBRejectedDetEvents return; } if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + registry.fill(HIST("hDetcollisionCounter"), 4.5); // EventsNotSatisfyingEventSelection return; } if (doEMCALEventWorkaround) { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content eventAccepted = true; if (collision.alias_bit(kTVXinEMC)) { + registry.fill(HIST("hDetcollisionCounter"), 5.5); // EMCreadoutDetEventsWithkTVXinEMC } } } else { if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { + registry.fill(HIST("hDetcollisionCounter"), 5.5); // EMCreadoutDetEventsWithkTVXinEMC eventAccepted = true; } } @@ -572,9 +724,10 @@ struct FullJetSpectrapp { fillRejectedJetHistograms(jet, 1.0); } } + registry.fill(HIST("hDetcollisionCounter"), 6.5); // AllRejectedDetEventsAfterEMCEventSelection return; } - registry.fill(HIST("h_Detcollision_counter"), 2.5); + registry.fill(HIST("hDetcollisionCounter"), 7.5); // EMCAcceptedDetColl for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { @@ -589,32 +742,75 @@ struct FullJetSpectrapp { fillJetHistograms(jet); } } - PROCESS_SWITCH(FullJetSpectrapp, processJetsData, "Full Jets Data", false); + PROCESS_SWITCH(FullJetSpectra, processJetsData, "Full Jets Data", false); void processJetsMCD(soa::Filtered::iterator const& collision, JetTableMCDJoined const& jets, aod::JetTracks const&, aod::JetClusters const&) { bool eventAccepted = false; + double weight = 1.0; + float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); + + /* if (doMcClosure) { + // Count total events processed (before splitting decision) + registry.fill(HIST("h_MCD_total_events"), 0.5); + + // DEBUG: Let's verify what collision IDs we're actually seeing + LOGF(info, "[MCD DEBUG] Processing MC collision ID: %lld", collision.mcCollisionId()); - registry.fill(HIST("h_Detcollision_counter"), 0.5); - if (fabs(collision.posZ()) > VertexZCut) { + // Get random value for this MC collision + float eventRandomValue = getMCCollisionRandomValue(collision.mcCollisionId()); + + // MCD gets events with random value <= split fraction (20%) + if (eventRandomValue > mcClosureSplitFrac) { + LOGF(debug, "[MCD] Event REJECTED: rand = %.4f > split = %.2f (MC collision %d)", + eventRandomValue, static_cast(mcClosureSplitFrac), collision.mcCollisionId()); + return; // This event goes to MCP & Matched processes + } + + LOGF(info, "[MCD] Event ACCEPTED: rand = %.4f <= split = %.2f (MC collision %d)", + eventRandomValue, static_cast(mcClosureSplitFrac), collision.mcCollisionId()); + + registry.fill(HIST("hSpliteventSelector"), 0.5); // 20% Closure input for the measured spectra (reco) + registry.fill(HIST("h_MCD_splitevent_counter"), 0.5); + } + */ + registry.fill(HIST("hDetcollisionCounter"), 0.5); // allDetColl + if (std::fabs(collision.posZ()) > vertexZCut) { return; } - registry.fill(HIST("h_Detcollision_counter"), 1.5); + registry.fill(HIST("hDetcollisionCounter"), 1.5); // DetCollWithVertexZ + + // outlier check: for every outlier jet, reject the whole event + for (auto const& jet : jets) { + if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { // for MCD jets only to remove outliers; setting pTHatMaxMCD = 1 improves purity + registry.fill(HIST("hDetcollisionCounter"), 2.5); // RejectedDetCollWithOutliers + return; + } + // this cut only to be used for calculating Jet Purity and not for Response Matrix + // this is mainly applied to remove all high weight jets causing big fluctuations + if (jet.pt() > 1 * pTHat) { + registry.fill(HIST("h_full_jet_pt_pTHatcut"), jet.pt(), weight); + } + } if (doMBGapTrigger && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + registry.fill(HIST("hDetcollisionCounter"), 3.5); // MBRejectedDetEvents return; } if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + registry.fill(HIST("hDetcollisionCounter"), 4.5); // EventsNotSatisfyingEventSelection return; } if (doEMCALEventWorkaround) { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content eventAccepted = true; if (collision.alias_bit(kTVXinEMC)) { + registry.fill(HIST("hDetcollisionCounter"), 5.5); // EMCreadoutDetEventsWithkTVXinEMC } } } else { if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { eventAccepted = true; + registry.fill(HIST("hDetcollisionCounter"), 5.5); // EMCreadoutDetEventsWithkTVXinEMC } } @@ -624,9 +820,10 @@ struct FullJetSpectrapp { fillRejectedJetHistograms(jet, 1.0); } } + registry.fill(HIST("hDetcollisionCounter"), 6.5); // AllRejectedDetEventsAfterEMCEventSelection return; } - registry.fill(HIST("h_Detcollision_counter"), 2.5); + registry.fill(HIST("hDetcollisionCounter"), 7.5); // EMCAcceptedDetColl for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { @@ -641,33 +838,73 @@ struct FullJetSpectrapp { fillJetHistograms(jet); } } - PROCESS_SWITCH(FullJetSpectrapp, processJetsMCD, "Full Jets at Detector Level", false); + PROCESS_SWITCH(FullJetSpectra, processJetsMCD, "Full Jets at Detector Level", false); void processJetsMCDWeighted(soa::Filtered::iterator const& collision, JetTableMCDWeightedJoined const& jets, aod::JMcCollisions const&, aod::JetTracks const&, aod::JetClusters const&) { bool eventAccepted = false; + double pTHat = 10. / (std::pow(collision.mcCollision().weight(), 1.0 / pTHatExponent)); + + /* if (doMcClosure) { + // Count total events processed (before splitting decision) + registry.fill(HIST("h_MCD_total_events"), 0.5); - registry.fill(HIST("h_Detcollision_counter"), 0.5); - if (fabs(collision.posZ()) > VertexZCut) { + // DEBUG: Let's verify what collision IDs we're actually seeing + LOGF(info, "[MCD DEBUG] Processing MC collision ID: %lld", collision.mcCollisionId()); + + // Get random value for this MC collision + float eventRandomValue = getMCCollisionRandomValue(collision.mcCollisionId()); + + // MCD gets events with random value <= split fraction (20%) + if (eventRandomValue > mcClosureSplitFrac) { + LOGF(debug, "[MCD] Event REJECTED: rand = %.4f > split = %.2f (MC collision %d)", + eventRandomValue, static_cast(mcClosureSplitFrac), collision.mcCollisionId()); + return; // This event goes to MCP & Matched processes + } + + LOGF(info, "[MCD] Event ACCEPTED: rand = %.4f <= split = %.2f (MC collision %d)", + eventRandomValue, static_cast(mcClosureSplitFrac), collision.mcCollisionId()); + + registry.fill(HIST("hSpliteventSelector"), 0.5); // 20% Closure input for the measured spectra (reco) + registry.fill(HIST("h_MCD_splitevent_counter"), 0.5); + } + */ + registry.fill(HIST("hDetcollisionCounter"), 0.5, collision.mcCollision().weight()); // allDetColl + if (std::fabs(collision.posZ()) > vertexZCut) { return; } - registry.fill(HIST("h_Detcollision_counter"), 1.5); + registry.fill(HIST("hDetcollisionCounter"), 1.5, collision.mcCollision().weight()); // DetCollWithVertexZ + // outlier check: for every outlier jet, reject the whole event + for (auto const& jet : jets) { + if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { // for MCD jets only to remove outliers; setting pTHatMaxMCD = 1 improves purity + registry.fill(HIST("hDetcollisionCounter"), 2.5, collision.mcCollision().weight()); // RejectedDetCollWithOutliers + return; + } + // this cut only to be used for calculating Jet Purity and not for Response Matrix + // this is mainly applied to remove all high weight jets causing big fluctuations + if (jet.pt() > 1 * pTHat) { + registry.fill(HIST("h_full_jet_pt_pTHatcut"), jet.pt(), collision.mcCollision().weight()); + } + } if (doMBGapTrigger && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + registry.fill(HIST("hDetcollisionCounter"), 3.5, collision.mcCollision().weight()); // MBRejectedDetEvents return; } if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + registry.fill(HIST("hDetcollisionCounter"), 4.5, collision.mcCollision().weight()); // EventsNotSatisfyingEventSelection return; } - if (doEMCALEventWorkaround) { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content eventAccepted = true; if (collision.alias_bit(kTVXinEMC)) { + registry.fill(HIST("hDetcollisionCounter"), 5.5, collision.mcCollision().weight()); // EMCreadoutDetEventsWithkTVXinEMC } } } else { if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { eventAccepted = true; + registry.fill(HIST("hDetcollisionCounter"), 5.5, collision.mcCollision().weight()); // EMCreadoutDetEventsWithkTVXinEMC } } @@ -677,9 +914,10 @@ struct FullJetSpectrapp { fillRejectedJetHistograms(jet, collision.mcCollision().weight()); } } + registry.fill(HIST("hDetcollisionCounter"), 6.5, collision.mcCollision().weight()); // AllRejectedDetEventsAfterEMCEventSelection return; } - registry.fill(HIST("h_Detcollision_counter"), 2.5); + registry.fill(HIST("hDetcollisionCounter"), 7.5, collision.mcCollision().weight()); // EMCAcceptedDetColl for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { @@ -691,56 +929,96 @@ struct FullJetSpectrapp { if (!isAcceptedJet(jet)) { continue; } - - // this cut only to be used for calculating Jet Purity and not for Response Matrix - // this is mainly applied to remove all high weight jets causing big fluctuations - double pTHat = 10. / (std::pow(collision.mcCollision().weight(), 1.0 / pTHatExponent)); - if (jet.pt() > 1 * pTHat) { - registry.fill(HIST("h_full_jet_pt_pTHatcut"), jet.pt(), collision.mcCollision().weight()); - } - fillJetHistograms(jet, collision.mcCollision().weight()); } } - PROCESS_SWITCH(FullJetSpectrapp, processJetsMCDWeighted, "Full Jets at Detector Level on weighted events", false); + PROCESS_SWITCH(FullJetSpectra, processJetsMCDWeighted, "Full Jets at Detector Level on weighted events", false); void processJetsMCP(aod::JetMcCollision const& mccollision, JetTableMCPJoined const& jets, aod::JetParticles const&, soa::SmallGroups const& collisions) { bool eventAccepted = false; + double weight = 1.0; + float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); + + /* if (doMcClosure) { + // Count total events processed (before splitting decision) + registry.fill(HIST("h_MCP_total_events"), 0.5); + + // DEBUG: Let's verify what collision IDs we're actually seeing + LOGF(info, "[MCP DEBUG] Processing MC collision ID: %lld", mccollision.globalIndex()); + + // Get random value for this MC collision + float eventRandomValue = getMCCollisionRandomValue(mccollision.globalIndex()); + + // DEBUG: Track which MC collisions we're processing + registry.fill(HIST("hMCCollisionIdDebug_MCP"), static_cast(mccollision.globalIndex() % 100000)); - registry.fill(HIST("h_Partcollision_counter"), 0.5); - if (fabs(mccollision.posZ()) > VertexZCut) { + // MCP gets events with random value > split fraction (80%) + if (eventRandomValue <= mcClosureSplitFrac) { + LOGF(debug, "[MCP] Event REJECTED: rand = %.4f <= split = %.2f (MC collision %lld)", + eventRandomValue, static_cast(mcClosureSplitFrac), mccollision.globalIndex()); + return; // This event goes to MCD only + } + + LOGF(info, "[MCP] Event ACCEPTED: rand = %.4f > split = %.2f (MC collision %lld)", + eventRandomValue, static_cast(mcClosureSplitFrac), mccollision.globalIndex()); + + registry.fill(HIST("hSpliteventSelector"), 1.5); // remaining 80% input for MCP + registry.fill(HIST("h_MCP_splitevent_counter"), 0.5); + } + */ + registry.fill(HIST("hPartcollisionCounter"), 0.5); // allMcColl + if (std::fabs(mccollision.posZ()) > vertexZCut) { return; } - registry.fill(HIST("h_Partcollision_counter"), 1.5); + registry.fill(HIST("hPartcollisionCounter"), 1.5); // McCollWithVertexZ if (collisions.size() < 1) { return; } - registry.fill(HIST("h_Partcollision_counter"), 2.5); - for (auto const& collision : collisions) { - if (doMBGapTrigger && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + registry.fill(HIST("hPartcollisionCounter"), 2.5); // PartCollWithSize>1 + + if (collisions.size() == 0) { + registry.fill(HIST("hPartcollisionCounter"), 3.5); // RejectedPartCollForDetCollWithSize0 + return; + } + + // outlier check: for every outlier jet, reject the whole event + for (auto const& jet : jets) { + if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { + registry.fill(HIST("hPartcollisionCounter"), 4.5); // RejectedPartCollWithOutliers return; } - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { - eventAccepted = true; - // return; + } + + if (doMBGapTrigger && mccollision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + // Fill rejected MB events; + registry.fill(HIST("hPartcollisionCounter"), 5.5); // MBRejectedPartEvents + return; + } + + for (auto const& collision : collisions) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + return; } if (doEMCALEventWorkaround) { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content eventAccepted = true; if (collision.alias_bit(kTVXinEMC)) { + registry.fill(HIST("hPartcollisionCounter"), 6.5); // EMCreadoutDetEventsWithkTVXinEMC } } } else { if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { eventAccepted = true; + registry.fill(HIST("hPartcollisionCounter"), 6.5); // EMCreadoutDetEventsWithkTVXinEMC } } } if (!eventAccepted) { + registry.fill(HIST("hPartcollisionCounter"), 7.5); // AllRejectedPartEventsAfterEMCEventSelection return; } - registry.fill(HIST("h_Partcollision_counter"), 3.5); + registry.fill(HIST("hPartcollisionCounter"), 8.5); // EMCAcceptedWeightedPartColl for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { @@ -760,44 +1038,93 @@ struct FullJetSpectrapp { } } } - PROCESS_SWITCH(FullJetSpectrapp, processJetsMCP, "Full Jets at Particle Level", false); + PROCESS_SWITCH(FullJetSpectra, processJetsMCP, "Full Jets at Particle Level", false); void processJetsMCPWeighted(aod::JetMcCollision const& mccollision, JetTableMCPWeightedJoined const& jets, aod::JetParticles const&, soa::SmallGroups const& collisions) { bool eventAccepted = false; + float pTHat = 10. / (std::pow(mccollision.weight(), 1.0 / pTHatExponent)); - registry.fill(HIST("h_Partcollision_counter"), 0.5); - if (fabs(mccollision.posZ()) > VertexZCut) { + /* if (doMcClosure) { + // Count total events processed (before splitting decision) + registry.fill(HIST("h_MCP_total_events"), 0.5); + + // DEBUG: Let's verify what collision IDs we're actually seeing + LOGF(info, "[MCP DEBUG] Processing MC collision ID: %lld", mccollision.globalIndex()); + + // Get random value for this MC collision + float eventRandomValue = getMCCollisionRandomValue(mccollision.globalIndex()); + + // DEBUG: Track which MC collisions we're processing + registry.fill(HIST("hMCCollisionIdDebug_MCP"), static_cast(mccollision.globalIndex() % 100000)); + + // MCP gets events with random value > split fraction (80%) + if (eventRandomValue <= mcClosureSplitFrac) { + LOGF(debug, "[MCP] Event REJECTED: rand = %.4f <= split = %.2f (MC collision %lld)", + eventRandomValue, static_cast(mcClosureSplitFrac), mccollision.globalIndex()); + return; // This event goes to MCD only + } + + LOGF(info, "[MCP] Event ACCEPTED: rand = %.4f > split = %.2f (MC collision %lld)", + eventRandomValue, static_cast(mcClosureSplitFrac), mccollision.globalIndex()); + + registry.fill(HIST("hSpliteventSelector"), 1.5); // remaining 80% input for MCP + registry.fill(HIST("h_MCP_splitevent_counter"), 0.5); + } + */ + registry.fill(HIST("hPartcollisionCounter"), 0.5, mccollision.weight()); // allMcColl + if (std::fabs(mccollision.posZ()) > vertexZCut) { return; } - registry.fill(HIST("h_Partcollision_counter"), 1.5); + registry.fill(HIST("hPartcollisionCounter"), 1.5, mccollision.weight()); // McCollWithVertexZ if (collisions.size() < 1) { return; } - registry.fill(HIST("h_Partcollision_counter"), 2.5); - for (auto const& collision : collisions) { - if (doMBGapTrigger && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + registry.fill(HIST("hPartcollisionCounter"), 2.5, mccollision.weight()); // PartCollWithSize>1 + + if (collisions.size() == 0) { + registry.fill(HIST("hPartcollisionCounter"), 3.5, mccollision.weight()); // RejectedPartCollForDetCollWithSize0 + return; + } + + // outlier check: for every outlier jet, reject the whole event + for (auto const& jet : jets) { + if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { + registry.fill(HIST("hPartcollisionCounter"), 4.5, mccollision.weight()); // RejectedPartCollWithOutliers return; } - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { - eventAccepted = true; + } + + if (doMBGapTrigger && mccollision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + // Fill rejected MB events + registry.fill(HIST("hPartcollisionCounter"), 5.5, mccollision.weight()); // MBRejectedPartEvents + return; + } + + for (auto const& collision : collisions) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + return; } if (doEMCALEventWorkaround) { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content eventAccepted = true; if (collision.alias_bit(kTVXinEMC)) { + registry.fill(HIST("hPartcollisionCounter"), 6.5, mccollision.weight()); // EMCreadoutDetJJEventsWithkTVXinEMC } } } else { if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { eventAccepted = true; + registry.fill(HIST("hPartcollisionCounter"), 6.5, mccollision.weight()); // EMCreadoutDetJJEventsWithkTVXinEMC } } } if (!eventAccepted) { + registry.fill(HIST("hPartcollisionCounter"), 7.5, mccollision.weight()); // AllRejectedPartEventsAfterEMCEventSelection return; } - registry.fill(HIST("h_Partcollision_counter"), 3.5); + // Fill EMCAL JJ Part events + registry.fill(HIST("hPartcollisionCounter"), 8.5, mccollision.weight()); // EMCAcceptedWeightedPartColl for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { @@ -821,43 +1148,91 @@ struct FullJetSpectrapp { } } } - PROCESS_SWITCH(FullJetSpectrapp, processJetsMCPWeighted, "Full Jets at Particle Level on weighted events", false); + PROCESS_SWITCH(FullJetSpectra, processJetsMCPWeighted, "Full Jets at Particle Level on weighted events", false); - void processJetsMCPMCDMatched(soa::Filtered::iterator const& collision, JetTableMCDMatchedJoined const& mcdjets, JetTableMCPMatchedJoined const& mcpjets, aod::JMcCollisions const&, aod::JetTracks const&, aod::JetClusters const&, aod::JetParticles const&) + void processJetsMCPMCDMatched(soa::Filtered::iterator const& collision, JetTableMCDMatchedJoined const& mcdjets, jetMcpPerMcCollision const& mcpjets, aod::JMcCollisions const&, aod::JetTracks const&, aod::JetClusters const&, aod::JetParticles const&) { bool eventAccepted = false; - int fakemcdjet = 0; - int fakemcpjet = 0; + int fakeMcdJet = 0; + int fakeMcpJet = 0; + double weight = 1.0; + float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); const auto mcpJetsPerMcCollision = mcpjets.sliceBy(JetMCPPerMcCollision, collision.mcCollisionId()); - registry.fill(HIST("h_Matchedcollision_counter"), 0.5); + /* if (doMcClosure) { + // Count total events processed (before splitting decision) + registry.fill(HIST("h_Matched_total_events"), 0.5); + + // Use consistent MC collision ID - same as MCD + int64_t mcCollisionId = collision.mcCollisionId(); + + // DEBUG: Let's verify what collision IDs we're actually seeing + LOGF(info, "[Matched DEBUG] Processing MC collision ID: %lld", mcCollisionId); + float eventRandomValue = getMCCollisionRandomValue(mcCollisionId); + + // Matched gets events with random value > split fraction (80%) - same as MCP + if (eventRandomValue <= mcClosureSplitFrac) { + LOGF(debug, "[Matched] Event REJECTED: rand = %.4f <= split = %.2f (MC collision %lld)", + eventRandomValue, static_cast(mcClosureSplitFrac), mcCollisionId); + return; // This event goes to MCD only + } + + LOGF(info, "[Matched] Event ACCEPTED: rand = %.4f > split = %.2f (MC collision %lld)", + eventRandomValue, static_cast(mcClosureSplitFrac), mcCollisionId); + + registry.fill(HIST("hSpliteventSelector"), 2.5); // Bin for Response Matrix + registry.fill(HIST("h_Matched_splitevent_counter"), 0.5); + } + */ + registry.fill(HIST("hMatchedcollisionCounter"), 0.5); // allDetColl - if (fabs(collision.posZ()) > VertexZCut) { // making double sure this condition is satisfied + if (std::fabs(collision.posZ()) > vertexZCut) { // making double sure this condition is satisfied return; } - registry.fill(HIST("h_Matchedcollision_counter"), 1.5); + registry.fill(HIST("hMatchedcollisionCounter"), 1.5); // DetCollWithVertexZ + + // outlier check: for every outlier jet, reject the whole event + for (auto const& mcdjet : mcdjets) { + if (mcdjet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { + registry.fill(HIST("hMatchedcollisionCounter"), 2.5); // RejectedDetCollWithOutliers + return; + } + } + // //outlier check for Part collisions: commenting out this for now otherwise this rejects all Det Colls + // for (auto const& mcpjet : mcpjets) { + // if (mcpjet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { + // registry.fill(HIST("hMatchedcollisionCounter"),3.5); //RejectedPartCollWithOutliers + // return; + // } + // } if (doMBGapTrigger && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + registry.fill(HIST("hMatchedcollisionCounter"), 4.5); // EMCMBRejectedDetColl return; } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + registry.fill(HIST("hMatchedcollisionCounter"), 5.5); // EventsNotSatisfyingEventSelection return; } if (doEMCALEventWorkaround) { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content eventAccepted = true; if (collision.alias_bit(kTVXinEMC)) { + registry.fill(HIST("hMatchedcollisionCounter"), 6.5); // EMCreadoutDetEventsWithkTVXinEMC } } } else { if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { eventAccepted = true; + registry.fill(HIST("hMatchedcollisionCounter"), 6.5); // EMCreadoutDetEventsWithkTVXinEMC } } if (!eventAccepted) { + registry.fill(HIST("hMatchedcollisionCounter"), 7.5); // AllRejectedDetEventsAfterEMCEventSelection return; } - registry.fill(HIST("h_Matchedcollision_counter"), 2.5); + registry.fill(HIST("hMatchedcollisionCounter"), 8.5); // EMCAcceptedDetColl for (const auto& mcdjet : mcdjets) { if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { @@ -865,50 +1240,94 @@ struct FullJetSpectrapp { } // Check if MCD jet is within the EMCAL fiducial region; if not then flag it as a fake jet if (mcdjet.phi() < jetPhiMin || mcdjet.phi() > jetPhiMax || mcdjet.eta() < jetEtaMin || mcdjet.eta() > jetEtaMax) { - fakemcdjet++; - registry.fill(HIST("h2_full_fakemcdjets"), mcdjet.pt(), fakemcdjet, 1.0); + fakeMcdJet++; + registry.fill(HIST("h2_full_fakemcdjets"), mcdjet.pt(), fakeMcdJet, 1.0); continue; } if (!isAcceptedJet(mcdjet)) { continue; } - for (auto& mcpjet : mcdjet.template matchedJetGeo_as()) { + for (const auto& mcpjet : mcdjet.template matchedJetGeo_as()) { // apply emcal fiducial cuts to the matched particle level jets if (mcpjet.eta() > jetEtaMax || mcpjet.eta() < jetEtaMin || mcpjet.phi() > jetPhiMax || mcpjet.phi() < jetPhiMin) { - fakemcpjet++; - registry.fill(HIST("h2_full_fakemcpjets"), mcpjet.pt(), fakemcpjet, 1.0); + fakeMcpJet++; + registry.fill(HIST("h2_full_fakemcpjets"), mcpjet.pt(), fakeMcpJet, 1.0); continue; } } // mcpjet loop - fillMatchedHistograms(mcdjet); + fillMatchedHistograms(mcdjet); } // mcdjet loop } - PROCESS_SWITCH(FullJetSpectrapp, processJetsMCPMCDMatched, "Full Jet finder MCP matched to MCD", false); + PROCESS_SWITCH(FullJetSpectra, processJetsMCPMCDMatched, "Full Jet finder MCP matched to MCD", false); void processJetsMCPMCDMatchedWeighted(soa::Filtered::iterator const& collision, JetTableMCDMatchedWeightedJoined const& mcdjets, JetTableMCPMatchedWeightedJoined const& mcpjets, aod::JMcCollisions const&, aod::JetTracks const&, aod::JetClusters const&, aod::JetParticles const&) { + bool eventAccepted = false; + int fakeMcdJet = 0; + int fakeMcpJet = 0; + int NPartJetFid = 0; float eventWeight = collision.mcCollision().weight(); + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + const auto mcpJetsPerMcCollision = mcpjets.sliceBy(JetMCPPerMcCollision, collision.mcCollisionId()); + + /* if (doMcClosure) { + // Count total events processed (before splitting decision) + registry.fill(HIST("h_Matched_total_events"), 0.5); + + // Use consistent MC collision ID - same as MCD + int64_t mcCollisionId = collision.mcCollisionId(); + + // DEBUG: Let's verify what collision IDs we're actually seeing + LOGF(info, "[Matched DEBUG] Processing MC collision ID: %lld", mcCollisionId); + float eventRandomValue = getMCCollisionRandomValue(mcCollisionId); - registry.fill(HIST("h_Matchedcollision_counter"), 0.5); - if (fabs(collision.posZ()) > VertexZCut) { // making double sure this condition is satisfied + // Matched gets events with random value > split fraction (80%) - same as MCP + if (eventRandomValue <= mcClosureSplitFrac) { + LOGF(debug, "[Matched] Event REJECTED: rand = %.4f <= split = %.2f (MC collision %lld)", + eventRandomValue, static_cast(mcClosureSplitFrac), mcCollisionId); + return; // This event goes to MCD only + } + + LOGF(info, "[Matched] Event ACCEPTED: rand = %.4f > split = %.2f (MC collision %lld)", + eventRandomValue, static_cast(mcClosureSplitFrac), mcCollisionId); + + registry.fill(HIST("hSpliteventSelector"), 2.5); // Bin for Response Matrix + registry.fill(HIST("h_Matched_splitevent_counter"), 0.5); + } + */ + registry.fill(HIST("hMatchedcollisionCounter"), 0.5, eventWeight); // allDetColl + if (std::fabs(collision.posZ()) > vertexZCut) { // making double sure this condition is satisfied return; } - registry.fill(HIST("h_Matchedcollision_counter"), 1.5); + registry.fill(HIST("hMatchedcollisionCounter"), 1.5, eventWeight); // DetCollWithVertexZ + + // outlier check: for every outlier jet, reject the whole event + for (auto const& mcdjet : mcdjets) { + if (mcdjet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { + registry.fill(HIST("hMatchedcollisionCounter"), 2.5, eventWeight); // RejectedDetCollWithOutliers + return; + } + } + // outlier check for Part collisions: commenting out this for now otherwise this rejects all Det Colls + // for (auto const& mcpjet : mcpjets) { + // if (mcpjet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { + // registry.fill(HIST("hMatchedcollisionCounter"),3.5, eventWeight); //RejectedPartCollWithOutliers + // return; + // } + // } if (doMBGapTrigger && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + registry.fill(HIST("hMatchedcollisionCounter"), 4.5, eventWeight); // EMCMBRejectedDetColl return; } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + registry.fill(HIST("hMatchedcollisionCounter"), 5.5, eventWeight); // EventsNotSatisfyingEventSelection return; } - bool eventAccepted = false; - int fakemcdjet = 0; - int fakemcpjet = 0; - float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); - const auto mcpJetsPerMcCollision = mcpjets.sliceBy(JetMCPPerMcCollision, collision.mcCollisionId()); - for (auto mcpjet : mcpJetsPerMcCollision) { - if (mcpjet.pt() > pTHatMaxMCP * pTHat) { // outlier rejection for MCP + for (auto const& mcpjet : mcpJetsPerMcCollision) { + if (mcpjet.pt() > pTHatMaxMCP * pTHat) { // outlier rejection for MCP: Should I remove this cut as I'm already doing MC outlier rejection @L1071? return; } } @@ -916,25 +1335,26 @@ struct FullJetSpectrapp { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content eventAccepted = true; if (collision.alias_bit(kTVXinEMC)) { - registry.fill(HIST("h_Matchedcollision_counter"), eventWeight); + registry.fill(HIST("hMatchedcollisionCounter"), 6.5, eventWeight); // EMCreadoutDetJJEventsWithkTVXinEMC } } } else { if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { eventAccepted = true; - registry.fill(HIST("h_Matchedcollision_counter"), eventWeight); + registry.fill(HIST("hMatchedcollisionCounter"), 6.5, eventWeight); // EMCreadoutDetJJEventsWithkTVXinEMC } } if (!eventAccepted) { + registry.fill(HIST("hMatchedcollisionCounter"), 7.5, eventWeight); // AllRejectedDetEventsAfterEMCEventSelection return; } - registry.fill(HIST("h_Matchedcollision_counter"), 2.5); + registry.fill(HIST("hMatchedcollisionCounter"), 8.5, eventWeight); // EMCAcceptedDetColl for (const auto& mcdjet : mcdjets) { // Check if MCD jet is within the EMCAL fiducial region; if not then flag it as a fake jet if (mcdjet.phi() < jetPhiMin || mcdjet.phi() > jetPhiMax || mcdjet.eta() < jetEtaMin || mcdjet.eta() > jetEtaMax) { - fakemcdjet++; - registry.fill(HIST("h2_full_fakemcdjets"), mcdjet.pt(), fakemcdjet, eventWeight); + fakeMcdJet++; + registry.fill(HIST("h2_full_fakemcdjets"), mcdjet.pt(), fakeMcdJet, eventWeight); continue; } if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { @@ -944,35 +1364,73 @@ struct FullJetSpectrapp { continue; } - for (auto& mcpjet : mcdjet.template matchedJetGeo_as()) { - // apply emcal fiducial cuts to the matched particle level jets + for (const auto& mcpjet : mcdjet.template matchedJetGeo_as()) { + // apply emcal fiducial cuts to the matched particle level jets - if the matched mcp jet lies outside of the EMCAL fiducial, flag it as a fake jet if (mcpjet.eta() > jetEtaMax || mcpjet.eta() < jetEtaMin || mcpjet.phi() > jetPhiMax || mcpjet.phi() < jetPhiMin) { - fakemcpjet++; - registry.fill(HIST("h2_full_fakemcpjets"), mcpjet.pt(), fakemcpjet, eventWeight); + fakeMcpJet++; + registry.fill(HIST("h2FullfakeMcpJets"), mcpjet.pt(), fakeMcpJet, eventWeight); continue; + } else { + NPartJetFid++; + // // If both MCD-MCP matched jet pairs are within the EMCAL fiducial region, fill these histos + registry.fill(HIST("h2_full_matchedmcpjet_pt"), mcpjet.pt(), NPartJetFid, eventWeight); + registry.fill(HIST("h_full_matchedmcpjet_eta"), mcpjet.eta(), eventWeight); + registry.fill(HIST("h_full_matchedmcpjet_phi"), mcpjet.phi(), eventWeight); } - // // If both MCD-MCP matched jet pairs are within the EMCAL fiducial region, fill these histos - registry.fill(HIST("h_full_matchedmcpjet_eta"), mcpjet.eta(), eventWeight); - registry.fill(HIST("h_full_matchedmcpjet_phi"), mcpjet.phi(), eventWeight); } // mcpjet fillMatchedHistograms(mcdjet, eventWeight); } // mcdjet } - PROCESS_SWITCH(FullJetSpectrapp, processJetsMCPMCDMatchedWeighted, "Full Jet finder MCP matched to MCD on weighted events", false); + PROCESS_SWITCH(FullJetSpectra, processJetsMCPMCDMatchedWeighted, "Full Jet finder MCP matched to MCD on weighted events", false); + + // Periodic cleanup to prevent unbounded memory growth + /*void processCleanup(aod::Collision const&) { + static int callCount = 0; + callCount++; + + // Clean up cache every 50000 calls to prevent memory issues + if (doMcClosure && callCount % 50000 == 0 && mcCollisionRandomValues.size() > 20000) { + LOGF(info, "Cleaning up MC collision random values cache (size: %zu)", mcCollisionRandomValues.size()); + mcCollisionRandomValues.clear(); + + // IMPROVEMENT: Add logging to verify our split ratios + float mcdCount = registry.get(HIST("h_MCD_splitevent_counter"))->GetBinContent(1); + float mcpCount = registry.get(HIST("h_MCP_splitevent_counter"))->GetBinContent(1); + float matchedCount = registry.get(HIST("h_Matched_splitevent_counter"))->GetBinContent(1); - void processTracks(soa::Filtered::iterator const& collision, soa::Filtered const& tracks, soa::Filtered const& clusters) + float totalEvents = mcdCount + mcpCount; // MCP and Matched should be the same, so don't double count + float actualSplitFrac = totalEvents > 0 ? mcdCount / totalEvents : 0.0f; + + LOGF(info, "Current split statistics: MCD=%.1f, MCP=%.1f, Matched=%.1f", mcdCount, mcpCount, matchedCount); + LOGF(info, "Actual split fraction: %.3f (target: %.3f)", actualSplitFrac, static_cast(mcClosureSplitFrac)); + } + } + PROCESS_SWITCH(FullJetSpectra, processCleanup, "Periodic cleanup", true); + */ + void processDataTracks(soa::Filtered::iterator const& collision, soa::Filtered const& tracks, soa::Filtered const& clusters) { bool eventAccepted = false; + double weight = 1.0; + float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); - registry.fill(HIST("h_collisions_unweighted"), 0.5); - if (fabs(collision.posZ()) > VertexZCut) { + registry.fill(HIST("hCollisionsUnweighted"), 0.5); // allDetColl + if (std::fabs(collision.posZ()) > vertexZCut) { return; } - registry.fill(HIST("h_collisions_unweighted"), 1.5); + registry.fill(HIST("hCollisionsUnweighted"), 1.5); // DetCollWithVertexZ + + // for (auto const& track : tracks) { + if (pTHat < pTHatAbsoluteMin) { // Track outlier rejection: should this be for every track iteration or for every collision? + return; + } + // } + if (doMBGapTrigger && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + registry.fill(HIST("hCollisionsUnweighted"), 2.5); // MBRejectedDetEvents return; } if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + registry.fill(HIST("hCollisionsUnweighted"), 3.5); // EventsNotSatisfyingEventSelection return; } // needed for the workaround to access EMCAL trigger bits. - This is needed for the MC productions in which the EMC trigger bits are missing. (MB MC LHC24f3, for ex.) @@ -986,8 +1444,7 @@ struct FullJetSpectrapp { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content eventAccepted = true; if (collision.alias_bit(kTVXinEMC)) { - registry.fill(HIST("h_collisions_unweighted"), 4.0); // Tracks with kTVXinEMC - registry.fill(HIST("h_Detcollision_counter"), 1.0); + registry.fill(HIST("hCollisionsUnweighted"), 4.5); // EMCreadoutDetEventsWithkTVXinEMC } } } else { @@ -995,16 +1452,72 @@ struct FullJetSpectrapp { // This is the default check for the simulations with proper trigger flags not requiring the above workaround. if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { eventAccepted = true; - registry.fill(HIST("h_collisions_unweighted"), 4.0); // Tracks with kTVXinEMC - registry.fill(HIST("h_Detcollision_counter"), 1.0); + registry.fill(HIST("hCollisionsUnweighted"), 4.5); // EMCreadoutDetEventsWithkTVXinEMC + } + } + + if (!eventAccepted) { + registry.fill(HIST("hCollisionsUnweighted"), 5.5); // AllRejectedDetEventsAfterEMCEventSelection + return; + } + registry.fill(HIST("hCollisionsUnweighted"), 6.5); // EMCAcceptedDetColl + + for (auto const& track : tracks) { + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { + continue; + } + // Fill Accepted events histos + fillTrackHistograms(tracks, clusters, 1.0); + } + registry.fill(HIST("hCollisionsUnweighted"), 7.5); // EMCAcceptedCollAfterTrackSel + } + PROCESS_SWITCH(FullJetSpectra, processDataTracks, "Full Jet tracks for Data", false); + + void processMCTracks(soa::Filtered::iterator const& collision, soa::Filtered const& tracks, soa::Filtered const& clusters) + { + bool eventAccepted = false; + double weight = 1.0; + float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); + + registry.fill(HIST("hCollisionsUnweighted"), 0.5); // allDetColl + if (std::fabs(collision.posZ()) > vertexZCut) { + return; + } + registry.fill(HIST("hCollisionsUnweighted"), 1.5); // DetCollWithVertexZ + + // for (auto const& track : tracks) { + if (pTHat < pTHatAbsoluteMin) { // Track outlier rejection: should this be for every track iteration or for every collision? + return; + } + // } + if (doMBGapTrigger && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + registry.fill(HIST("hCollisionsUnweighted"), 2.5); // MBRejectedDetEvents + return; + } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + registry.fill(HIST("hCollisionsUnweighted"), 3.5); // EventsNotSatisfyingEventSelection + return; + } + + if (doEMCALEventWorkaround) { + if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content + eventAccepted = true; + if (collision.alias_bit(kTVXinEMC)) { + registry.fill(HIST("hCollisionsUnweighted"), 4.5); // EMCreadoutDetEventsWithkTVXinEMC + } + } + } else { + if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; + registry.fill(HIST("hCollisionsUnweighted"), 4.5); // EMCreadoutDetEventsWithkTVXinEMC } } if (!eventAccepted) { - registry.fill(HIST("h_collisions_unweighted"), 8.0); // Tracks w/o kTVXinEMC + registry.fill(HIST("hCollisionsUnweighted"), 5.5); // AllRejectedDetEventsAfterEMCEventSelection return; } - registry.fill(HIST("h_collisions_unweighted"), 2.5); + registry.fill(HIST("hCollisionsUnweighted"), 6.5); // EMCAcceptedDetColl for (auto const& track : tracks) { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { @@ -1013,9 +1526,9 @@ struct FullJetSpectrapp { // Fill Accepted events histos fillTrackHistograms(tracks, clusters, 1.0); } - registry.fill(HIST("h_collisions_unweighted"), 3.5); + registry.fill(HIST("hCollisionsUnweighted"), 7.5); // EMCAcceptedCollAfterTrackSel } - PROCESS_SWITCH(FullJetSpectrapp, processTracks, "Full Jet tracks", false); + PROCESS_SWITCH(FullJetSpectra, processMCTracks, "Full Jet tracks for MC", false); void processTracksWeighted(soa::Filtered::iterator const& collision, aod::JMcCollisions const&, @@ -1024,54 +1537,63 @@ struct FullJetSpectrapp { { bool eventAccepted = false; float eventWeight = collision.mcCollision().weight(); + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); - registry.fill(HIST("h_collisions_weighted"), 0.5); - if (fabs(collision.posZ()) > VertexZCut) { + registry.fill(HIST("hCollisionsWeighted"), 0.5, eventWeight); // AllWeightedDetColl + if (std::fabs(collision.posZ()) > vertexZCut) { return; } - registry.fill(HIST("h_collisions_weighted"), 1.5); + registry.fill(HIST("hCollisionsWeighted"), 1.5, eventWeight); // WeightedCollWithVertexZ + + // for (auto const& track : tracks) { + if (pTHat < pTHatAbsoluteMin) { // Track outlier rejection: should this be for every track iteration or for every collision? + return; + } + // } if (doMBGapTrigger && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + registry.fill(HIST("hCollisionsWeighted"), 2.5, eventWeight); // MBRejectedDetEvents return; } if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + registry.fill(HIST("hCollisionsWeighted"), 3.5, eventWeight); // EventsNotSatisfyingEventSelection return; } if (doMBGapTrigger && eventWeight == 1) { + registry.fill(HIST("hCollisionsWeighted"), 2.5, eventWeight); // MBRejectedDetEvents return; } - registry.fill(HIST("h_collisions_weighted"), 1.0, eventWeight); // total events if (doEMCALEventWorkaround) { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content eventAccepted = true; fillTrackHistograms(tracks, clusters, eventWeight); if (collision.alias_bit(kTVXinEMC)) { - registry.fill(HIST("h_collisions_weighted"), 4.0, eventWeight); // TracksWeighted with kTVXinEMC + registry.fill(HIST("hCollisionsWeighted"), 4.5, eventWeight); // EMCreadoutDetJJEventsWithkTVXinEMC } } } else { if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { eventAccepted = true; - registry.fill(HIST("h_collisions_weighted"), 4.0, eventWeight); // TracksWeighted with kTVXinEMC + registry.fill(HIST("hCollisionsWeighted"), 4.5, eventWeight); // EMCreadoutDetJJEventsWithkTVXinEMC } } if (!eventAccepted) { - registry.fill(HIST("h_collisions_weighted"), 7.0, eventWeight); // TracksWeighted w/o kTVXinEMC + registry.fill(HIST("hCollisionsWeighted"), 5.5, eventWeight); // AllRejectedDetEventsAfterEMCEventSelection return; } - registry.fill(HIST("h_collisions_weighted"), 2.5); + registry.fill(HIST("hCollisionsWeighted"), 6.5); // EMCAcceptedWeightedDetColl for (auto const& track : tracks) { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { continue; } // Fill Accepted events histos - fillTrackHistograms(tracks, clusters, 1.0); + fillTrackHistograms(tracks, clusters, eventWeight); } - registry.fill(HIST("h_collisions_weighted"), 3.5); + registry.fill(HIST("hCollisionsWeighted"), 7.5, eventWeight); // EMCAcceptedWeightedCollAfterTrackSel } - PROCESS_SWITCH(FullJetSpectrapp, processTracksWeighted, "Full Jet tracks weighted", false); + PROCESS_SWITCH(FullJetSpectra, processTracksWeighted, "Full Jet tracks weighted", false); void processCollisionsWeightedWithMultiplicity(soa::Filtered>::iterator const& collision, JetTableMCDWeightedJoined const& mcdjets, aod::JMcCollisions const&, soa::Filtered const& tracks, soa::Filtered const& clusters) { @@ -1079,16 +1601,21 @@ struct FullJetSpectrapp { float eventWeight = collision.mcCollision().weight(); float neutralEnergy = 0.0; - if (fabs(collision.posZ()) > VertexZCut) { + registry.fill(HIST("hEventmultiplicityCounter"), 0.5, eventWeight); // allDetColl + if (std::fabs(collision.posZ()) > vertexZCut) { + registry.fill(HIST("hEventmultiplicityCounter"), 1.5, eventWeight); // DetCollWithVertexZ return; } if (doMBGapTrigger && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + registry.fill(HIST("hEventmultiplicityCounter"), 2.5, eventWeight); // MBRejectedDetEvents return; } if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + registry.fill(HIST("hEventmultiplicityCounter"), 3.5, eventWeight); // EventsNotSatisfyingEventSelection return; } if (doMBGapTrigger && eventWeight == 1) { + registry.fill(HIST("hEventmultiplicityCounter"), 2.5, eventWeight); // MBRejectedDetEvents return; } @@ -1097,23 +1624,29 @@ struct FullJetSpectrapp { eventAccepted = true; fillTrackHistograms(tracks, clusters, eventWeight); if (collision.alias_bit(kTVXinEMC)) { + registry.fill(HIST("hEventmultiplicityCounter"), 4.5, eventWeight); // EMCreadoutDetJJEventsWithkTVXinEMC } } } else { if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { eventAccepted = true; + registry.fill(HIST("hEventmultiplicityCounter"), 4.5, eventWeight); // EMCreadoutDetJJEventsWithkTVXinEMC } } if (!eventAccepted) { + registry.fill(HIST("hEventmultiplicityCounter"), 5.5, eventWeight); // AllRejectedDetEventsAfterEMCEventSelection return; } + registry.fill(HIST("hCollisionsWeighted"), 6.5); // EMCAcceptedWeightedDetColl + for (auto const& track : tracks) { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { continue; } } - registry.fill(HIST("h_FT0Mults_occupancy"), collision.multiplicity()); + registry.fill(HIST("hEventmultiplicityCounter"), 7.5, eventWeight); // EMCAcceptedWeightedCollAfterTrackSel + registry.fill(HIST("h_FT0Mults_occupancy"), collision.multiplicity(), eventWeight); for (auto const& mcdjet : mcdjets) { float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); @@ -1134,11 +1667,11 @@ struct FullJetSpectrapp { for (auto const& cluster : clusters) { neutralEnergy += cluster.energy(); } - auto NEF = neutralEnergy / mcdjet.energy(); - registry.fill(HIST("h3_full_jet_jetpTDet_FT0Mults_NEF"), mcdjet.pt(), collision.multiplicity(), NEF, eventWeight); + auto nef = neutralEnergy / mcdjet.energy(); + registry.fill(HIST("h3_full_jet_jetpTDet_FT0Mults_nef"), mcdjet.pt(), collision.multiplicity(), nef, eventWeight); } } - PROCESS_SWITCH(FullJetSpectrapp, processCollisionsWeightedWithMultiplicity, "Weighted Collisions for Full Jets Multiplicity Studies", false); + PROCESS_SWITCH(FullJetSpectra, processCollisionsWeightedWithMultiplicity, "Weighted Collisions for Full Jets Multiplicity Studies", false); void processMBCollisionsWithMultiplicity(soa::Filtered>::iterator const& collision, JetTableMCDJoined const& mcdjets, aod::JMcCollisions const&, soa::Filtered const& tracks, soa::Filtered const& clusters) { @@ -1146,13 +1679,18 @@ struct FullJetSpectrapp { float pTHat = 10. / (std::pow(1.0, 1.0 / pTHatExponent)); float neutralEnergy = 0.0; - if (fabs(collision.posZ()) > VertexZCut) { + registry.fill(HIST("hEventmultiplicityCounter"), 0.5); // allDetColl + if (std::fabs(collision.posZ()) > vertexZCut) { return; } + registry.fill(HIST("hEventmultiplicityCounter"), 1.5); // DetCollWithVertexZ + if (doMBGapTrigger && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + registry.fill(HIST("hEventmultiplicityCounter"), 2.5); // MBRejectedDetEvents return; } if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + registry.fill(HIST("hEventmultiplicityCounter"), 3.5); // EventsNotSatisfyingEventSelection return; } @@ -1161,22 +1699,28 @@ struct FullJetSpectrapp { eventAccepted = true; fillTrackHistograms(tracks, clusters, 1.0); if (collision.alias_bit(kTVXinEMC)) { + registry.fill(HIST("hEventmultiplicityCounter"), 4.5); // EMCreadoutDetEventsWithkTVXinEMC } } } else { if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { eventAccepted = true; + registry.fill(HIST("hEventmultiplicityCounter"), 4.5); // EMCreadoutDetEventsWithkTVXinEMC } } if (!eventAccepted) { + registry.fill(HIST("hEventmultiplicityCounter"), 5.5); // AllRejectedDetEventsAfterEMCEventSelection return; } + registry.fill(HIST("hEventmultiplicityCounter"), 6.5); // EMCAcceptedDetColl + for (auto const& track : tracks) { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { continue; } } + registry.fill(HIST("hEventmultiplicityCounter"), 7.5); // EMCAcceptedCollAfterTrackSel registry.fill(HIST("h_FT0Mults_occupancy"), collision.multiplicity()); for (auto const& mcdjet : mcdjets) { @@ -1197,15 +1741,85 @@ struct FullJetSpectrapp { for (auto const& cluster : clusters) { neutralEnergy += cluster.energy(); } - auto NEF = neutralEnergy / mcdjet.energy(); - registry.fill(HIST("h3_full_jet_jetpTDet_FT0Mults_NEF"), mcdjet.pt(), collision.multiplicity(), NEF, 1.0); + auto nef = neutralEnergy / mcdjet.energy(); + registry.fill(HIST("h3_full_jet_jetpTDet_FT0Mults_nef"), mcdjet.pt(), collision.multiplicity(), nef, 1.0); } } - PROCESS_SWITCH(FullJetSpectrapp, processMBCollisionsWithMultiplicity, "MB Collisions for Full Jets Multiplicity Studies", false); + PROCESS_SWITCH(FullJetSpectra, processMBCollisionsWithMultiplicity, "MB MCD Collisions for Full Jets Multiplicity Studies", false); + + void processMBCollisionsDATAWithMultiplicity(soa::Filtered>::iterator const& collision, FullJetTableDataJoined const& jets, soa::Filtered const& tracks, soa::Filtered const& clusters) + { + bool eventAccepted = false; + float neutralEnergy = 0.0; + + registry.fill(HIST("hEventmultiplicityCounter"), 0.5); // allDetColl + if (std::fabs(collision.posZ()) > vertexZCut) { + return; + } + registry.fill(HIST("hEventmultiplicityCounter"), 1.5); // DetCollWithVertexZ + if (doMBGapTrigger && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + registry.fill(HIST("hEventmultiplicityCounter"), 2.5); // MBRejectedDetEvents + return; + } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + registry.fill(HIST("hEventmultiplicityCounter"), 3.5); // EventsNotSatisfyingEventSelection + return; + } + + if (doEMCALEventWorkaround) { + if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content + eventAccepted = true; + fillTrackHistograms(tracks, clusters, 1.0); + if (collision.alias_bit(kTVXinEMC)) { + registry.fill(HIST("hEventmultiplicityCounter"), 4.5); // EMCreadoutDetEventsWithkTVXinEMC + } + } + } else { + if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; + registry.fill(HIST("hEventmultiplicityCounter"), 4.5); // EMCreadoutDetEventsWithkTVXinEMC + } + } + + if (!eventAccepted) { + registry.fill(HIST("hEventmultiplicityCounter"), 5.5); // AllRejectedDetEventsAfterEMCEventSelection + return; + } + registry.fill(HIST("hEventmultiplicityCounter"), 6.5); // EMCAcceptedDetColl + + for (auto const& track : tracks) { + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { + continue; + } + } + registry.fill(HIST("hEventmultiplicityCounter"), 7.5); // EMCAcceptedCollAfterTrackSel + registry.fill(HIST("h_FT0Mults_occupancy"), collision.multiplicity()); + + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (jet.phi() < jetPhiMin || jet.phi() > jetPhiMax) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + registry.fill(HIST("h2_full_jet_jetpTDetVsFT0Mults"), jet.pt(), collision.multiplicity(), 1.0); + + for (auto const& cluster : clusters) { + neutralEnergy += cluster.energy(); + } + auto nef = neutralEnergy / jet.energy(); + registry.fill(HIST("h3_full_jet_jetpTDet_FT0Mults_nef"), jet.pt(), collision.multiplicity(), nef, 1.0); + } + } + PROCESS_SWITCH(FullJetSpectra, processMBCollisionsDATAWithMultiplicity, "MB DATA Collisions for Full Jets Multiplicity Studies", false); + }; // struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc, TaskName{"full-jet-spectra-pp"})}; + adaptAnalysisTask(cfgc)}; } diff --git a/PWGJE/Tasks/jetFragmentation.cxx b/PWGJE/Tasks/jetFragmentation.cxx index c181254819f..18d5dea2c56 100644 --- a/PWGJE/Tasks/jetFragmentation.cxx +++ b/PWGJE/Tasks/jetFragmentation.cxx @@ -56,9 +56,9 @@ using MatchedMCPJetsWithConstituents = soa::Join; -using CandidatesV0DataWithFlags = soa::Join; +using CandidatesV0DataWithFlags = aod::CandidatesV0Data; -using CandidatesV0MCDWithLabelsAndFlags = soa::Join; +using CandidatesV0MCDWithLabelsAndFlags = soa::Join; using MCDV0Jets = aod::V0ChargedMCDetectorLevelJets; using MCDV0JetsWithConstituents = soa::Join; using MatchedMCDV0Jets = soa::Join; diff --git a/PWGJE/Tasks/jetHadronRecoil.cxx b/PWGJE/Tasks/jetHadronRecoil.cxx index 357e973efe2..018814cdeeb 100644 --- a/PWGJE/Tasks/jetHadronRecoil.cxx +++ b/PWGJE/Tasks/jetHadronRecoil.cxx @@ -71,6 +71,8 @@ struct JetHadronRecoil { Configurable pTHatExponent{"pTHatExponent", 4.0, "exponent of the event weight for the calculation of pTHat"}; Configurable pTHatMaxMCD{"pTHatMaxMCD", 999.0, "maximum fraction of hard scattering for jet acceptance in detector MC"}; Configurable pTHatMaxMCP{"pTHatMaxMCP", 999.0, "maximum fraction of hard scattering for jet acceptance in particle MC"}; + Configurable pTHatTrackMaxMCD{"pTHatTrackMaxMCD", 999.0, "maximum fraction of hard scattering for track acceptance in detector MC"}; + Configurable pTHatTrackMaxMCP{"pTHatTrackMaxMCP", 999.0, "maximum fraction of hard scattering for track acceptance in particle MC"}; Configurable rhoReferenceShift{"rhoReferenceShift", 0.0, "shift in rho calculated in reference events for consistency with signal events"}; Configurable triggerMasks{"triggerMasks", "", "possible JE Trigger masks: fJetChLowPt,fJetChHighPt,fTrackLowPt,fTrackHighPt,fJetD0ChLowPt,fJetD0ChHighPt,fJetLcChLowPt,fJetLcChHighPt,fEMCALReadout,fJetFullHighPt,fJetFullLowPt,fJetNeutralHighPt,fJetNeutralLowPt,fGammaVeryHighPtEMCAL,fGammaVeryHighPtDCAL,fGammaHighPtEMCAL,fGammaHighPtDCAL,fGammaLowPtEMCAL,fGammaLowPtDCAL,fGammaVeryLowPtEMCAL,fGammaVeryLowPtDCAL"}; Configurable skipMBGapEvents{"skipMBGapEvents", false, "flag to choose to reject min. bias gap events; jet-level rejection applied at the jet finder level, here rejection is applied for collision and track process functions"}; @@ -122,6 +124,7 @@ struct JetHadronRecoil { {"hPtTrack", "Track p_{T};p_{T};entries", {HistType::kTH1F, {{200, 0, 200}}}}, {"hEtaTrack", "Track #eta;#eta;entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, {"hPhiTrack", "Track #phi;#phi;entries", {HistType::kTH1F, {{100, 0.0, o2::constants::math::TwoPI}}}}, + {"hTrack3D", "3D tracks histogram;p_{T};#eta;#phi", {HistType::kTH3F, {{200, 0, 200}, {100, -1.0, 1.0}, {100, 0.0, o2::constants::math::TwoPI}}}}, {"hPtTrackPtHard", "Track p_{T} vs #hat{p};p_{T};#frac{p_{T}}{#hat{p}}", {HistType::kTH2F, {{200, 0, 200}, {20, 0, 5}}}}, {"hConstituents3D", "3D constituents histogram;p_{T};#eta;#phi", {HistType::kTH3F, {{200, 0, 200}, {100, -1.0, 1.0}, {100, 0.0, o2::constants::math::TwoPI}}}}, {"hReferencePtDPhi", "jet p_{T} vs DPhi;#Delta#phi;p_{T,jet}", {HistType::kTH2F, {{100, 0, o2::constants::math::TwoPI}, {500, -100, 400}}}}, @@ -219,6 +222,9 @@ struct JetHadronRecoil { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { continue; } + if (track.pt() > pTHatTrackMaxMCD * pTHat) { + return; + } if (isSigCol && track.pt() < ptTTsigMax && track.pt() > ptTTsigMin) { phiTTAr.push_back(track.phi()); ptTTAr.push_back(track.pt()); @@ -234,7 +240,8 @@ struct JetHadronRecoil { registry.fill(HIST("hPtTrack"), track.pt(), weight); registry.fill(HIST("hEtaTrack"), track.eta(), weight); registry.fill(HIST("hPhiTrack"), track.phi(), weight); - registry.fill(HIST("hPtTrackPtHard"), track.pt(), track.pt() / pTHat); + registry.fill(HIST("hTrack3D"), track.pt(), track.eta(), track.phi(), weight); + registry.fill(HIST("hPtTrackPtHard"), track.pt(), track.pt() / pTHat, weight); } if (nTT > 0) { @@ -260,7 +267,7 @@ struct JetHadronRecoil { for (const auto& jet : jets) { if (jet.pt() > pTHatMaxMCD * pTHat) { - continue; + return; } for (const auto& constituent : jet.template tracks_as()) { if (constituent.pt() > leadingPT) { @@ -335,6 +342,9 @@ struct JetHadronRecoil { isSigCol = false; for (const auto& particle : particles) { + if (particle.pt() > pTHatTrackMaxMCD * pTHat) { + return; + } auto pdgParticle = pdg->GetParticle(particle.pdgCode()); if (!pdgParticle) { continue; @@ -370,7 +380,7 @@ struct JetHadronRecoil { for (const auto& jet : jets) { if (jet.pt() > pTHatMaxMCP * pTHat) { - continue; + return; } for (const auto& constituent : jet.template tracks_as()) { registry.fill(HIST("hConstituents3D"), constituent.pt(), constituent.eta(), constituent.phi()); diff --git a/PWGJE/Tasks/v0QA.cxx b/PWGJE/Tasks/v0QA.cxx index 6966c3b0101..8d8d0ab2cfc 100644 --- a/PWGJE/Tasks/v0QA.cxx +++ b/PWGJE/Tasks/v0QA.cxx @@ -47,7 +47,7 @@ using MCDV0JetsWithConstituents = soa::Join; using MatchedMCDV0JetsWithConstituents = soa::Join; -using CandidatesV0MCDWithFlags = soa::Join; +using CandidatesV0MCDWithFlags = soa::Join; using MCPV0Jets = aod::V0ChargedMCParticleLevelJets; using MCPV0JetsWithConstituents = soa::Join; @@ -1221,7 +1221,7 @@ struct V0QA { using DaughterJTracks = soa::Join; using DaughterTracks = soa::Join; - void processV0TrackQA(aod::JetCollision const& /*jcoll*/, soa::Join const& v0s, DaughterJTracks const&, DaughterTracks const&) + void processV0TrackQA(aod::JetCollision const& /*jcoll*/, aod::CandidatesV0Data const& v0s, DaughterJTracks const&, DaughterTracks const&) { // if (!jetderiveddatautilities::selectCollision(jcoll, eventSelectionBits)) { // return; diff --git a/PWGLF/DataModel/LFNonPromptCascadeTables.h b/PWGLF/DataModel/LFNonPromptCascadeTables.h index 687d698a529..177167d5997 100644 --- a/PWGLF/DataModel/LFNonPromptCascadeTables.h +++ b/PWGLF/DataModel/LFNonPromptCascadeTables.h @@ -115,6 +115,10 @@ DECLARE_SOA_COLUMN(MotherDecayDaughters, motherDecayDaughters, int8_t); DECLARE_SOA_COLUMN(Sel8, sel8, bool); DECLARE_SOA_COLUMN(MultFT0C, multFT0C, float); DECLARE_SOA_COLUMN(MultFT0A, multFT0A, float); +DECLARE_SOA_COLUMN(MultFT0M, multFT0M, float); +DECLARE_SOA_COLUMN(CentFT0C, centFT0C, float); +DECLARE_SOA_COLUMN(CentFT0A, centFT0A, float); +DECLARE_SOA_COLUMN(CentFT0M, centFT0M, float); } // namespace NPCascadeTable DECLARE_SOA_TABLE(NPCascTable, "AOD", "NPCASCTABLE", @@ -175,7 +179,11 @@ DECLARE_SOA_TABLE(NPCascTable, "AOD", "NPCASCTABLE", NPCascadeTable::BachPionTOFNSigma, NPCascadeTable::Sel8, NPCascadeTable::MultFT0C, - NPCascadeTable::MultFT0A) + NPCascadeTable::MultFT0A, + NPCascadeTable::MultFT0M, + NPCascadeTable::CentFT0C, + NPCascadeTable::CentFT0A, + NPCascadeTable::CentFT0M) DECLARE_SOA_TABLE(NPCascTableNT, "AOD", "NPCASCTABLENT", NPCascadeTable::MatchingChi2, @@ -235,7 +243,11 @@ DECLARE_SOA_TABLE(NPCascTableNT, "AOD", "NPCASCTABLENT", NPCascadeTable::BachPionTOFNSigma, NPCascadeTable::Sel8, NPCascadeTable::MultFT0C, - NPCascadeTable::MultFT0A) + NPCascadeTable::MultFT0A, + NPCascadeTable::MultFT0M, + NPCascadeTable::CentFT0C, + NPCascadeTable::CentFT0A, + NPCascadeTable::CentFT0M) DECLARE_SOA_TABLE(NPCascTableMC, "AOD", "NPCASCTABLEMC", NPCascadeTable::MatchingChi2, @@ -302,6 +314,10 @@ DECLARE_SOA_TABLE(NPCascTableMC, "AOD", "NPCASCTABLEMC", NPCascadeTable::Sel8, NPCascadeTable::MultFT0C, NPCascadeTable::MultFT0A, + NPCascadeTable::MultFT0M, + NPCascadeTable::CentFT0C, + NPCascadeTable::CentFT0A, + NPCascadeTable::CentFT0M, NPCascadeTable::gPt, NPCascadeTable::gEta, NPCascadeTable::gPhi, @@ -381,6 +397,10 @@ DECLARE_SOA_TABLE(NPCascTableMCNT, "AOD", "NPCASCTABLEMCNT", NPCascadeTable::Sel8, NPCascadeTable::MultFT0C, NPCascadeTable::MultFT0A, + NPCascadeTable::MultFT0M, + NPCascadeTable::CentFT0C, + NPCascadeTable::CentFT0A, + NPCascadeTable::CentFT0M, NPCascadeTable::gPt, NPCascadeTable::gEta, NPCascadeTable::gPhi, diff --git a/PWGLF/DataModel/LFStrangenessTables.h b/PWGLF/DataModel/LFStrangenessTables.h index bfe3a4f055d..ce2e9e65eda 100644 --- a/PWGLF/DataModel/LFStrangenessTables.h +++ b/PWGLF/DataModel/LFStrangenessTables.h @@ -618,42 +618,28 @@ DECLARE_SOA_COLUMN(GeneratedK0Short, generatedK0Short, std::vector); DECLARE_SOA_COLUMN(GeneratedLambda, generatedLambda, std::vector); //! Lambda binned generated data DECLARE_SOA_COLUMN(GeneratedAntiLambda, generatedAntiLambda, std::vector); //! AntiLambda binned generated data -//______________________________________________________ -// EXPRESSION COLUMNS -DECLARE_SOA_EXPRESSION_COLUMN(Px, px, //! V0 px - float, 1.f * aod::v0data::pxpos + 1.f * aod::v0data::pxneg); -DECLARE_SOA_EXPRESSION_COLUMN(Py, py, //! V0 py - float, 1.f * aod::v0data::pypos + 1.f * aod::v0data::pyneg); -DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, //! V0 pz - float, 1.f * aod::v0data::pzpos + 1.f * aod::v0data::pzneg); -DECLARE_SOA_EXPRESSION_COLUMN(Pt, pt, float, //! Transverse momentum in GeV/c - nsqrt((1.f * aod::v0data::pxpos + 1.f * aod::v0data::pxneg) * - (1.f * aod::v0data::pxpos + 1.f * aod::v0data::pxneg) + - (1.f * aod::v0data::pypos + 1.f * aod::v0data::pyneg) * (1.f * aod::v0data::pypos + 1.f * aod::v0data::pyneg))); -DECLARE_SOA_EXPRESSION_COLUMN(P, p, float, //! Total momentum in GeV/c - nsqrt((1.f * aod::v0data::pxpos + 1.f * aod::v0data::pxneg) * - (1.f * aod::v0data::pxpos + 1.f * aod::v0data::pxneg) + - (1.f * aod::v0data::pypos + 1.f * aod::v0data::pyneg) * (1.f * aod::v0data::pypos + 1.f * aod::v0data::pyneg) + - (1.f * aod::v0data::pzpos + 1.f * aod::v0data::pzneg) * (1.f * aod::v0data::pzpos + 1.f * aod::v0data::pzneg))); -DECLARE_SOA_EXPRESSION_COLUMN(Phi, phi, float, //! Phi in the range [0, 2pi) - o2::constants::math::PI + natan2(-1.0f * (1.f * aod::v0data::pypos + 1.f * aod::v0data::pyneg), -1.0f * (1.f * aod::v0data::pxpos + 1.f * aod::v0data::pxneg))); -DECLARE_SOA_EXPRESSION_COLUMN(Eta, eta, float, //! Pseudorapidity, conditionally defined to avoid FPEs - ifnode((nsqrt((1.f * aod::v0data::pxpos + 1.f * aod::v0data::pxneg) * (1.f * aod::v0data::pxpos + 1.f * aod::v0data::pxneg) + - (1.f * aod::v0data::pypos + 1.f * aod::v0data::pyneg) * (1.f * aod::v0data::pypos + 1.f * aod::v0data::pyneg) + - (1.f * aod::v0data::pzpos + 1.f * aod::v0data::pzneg) * (1.f * aod::v0data::pzpos + 1.f * aod::v0data::pzneg)) - - (1.f * aod::v0data::pzpos + 1.f * aod::v0data::pzneg)) < static_cast(1e-7), - ifnode((1.f * aod::v0data::pzpos + 1.f * aod::v0data::pzneg) < 0.f, -100.f, 100.f), - 0.5f * nlog((nsqrt((1.f * aod::v0data::pxpos + 1.f * aod::v0data::pxneg) * (1.f * aod::v0data::pxpos + 1.f * aod::v0data::pxneg) + - (1.f * aod::v0data::pypos + 1.f * aod::v0data::pyneg) * (1.f * aod::v0data::pypos + 1.f * aod::v0data::pyneg) + - (1.f * aod::v0data::pzpos + 1.f * aod::v0data::pzneg) * (1.f * aod::v0data::pzpos + 1.f * aod::v0data::pzneg)) + - (1.f * aod::v0data::pzpos + 1.f * aod::v0data::pzneg)) / - (nsqrt((1.f * aod::v0data::pxpos + 1.f * aod::v0data::pxneg) * (1.f * aod::v0data::pxpos + 1.f * aod::v0data::pxneg) + - (1.f * aod::v0data::pypos + 1.f * aod::v0data::pyneg) * (1.f * aod::v0data::pypos + 1.f * aod::v0data::pyneg) + - (1.f * aod::v0data::pzpos + 1.f * aod::v0data::pzneg) * (1.f * aod::v0data::pzpos + 1.f * aod::v0data::pzneg)) - - (1.f * aod::v0data::pzpos + 1.f * aod::v0data::pzneg))))); - //______________________________________________________ // DYNAMIC COLUMNS +DECLARE_SOA_DYNAMIC_COLUMN(Px, px, //! V0 px + [](float pxPos, float pxNeg) -> float { return pxPos + pxNeg; }); +DECLARE_SOA_DYNAMIC_COLUMN(Py, py, //! V0 py + [](float pyPos, float pyNeg) -> float { return pyPos + pyNeg; }); +DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, //! V0 pz + [](float pzPos, float pzNeg) -> float { return pzPos + pzNeg; }); +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! Transverse momentum in GeV/c + [](float pxPos, float pyPos, float pxNeg, float pyNeg) -> float { + return RecoDecay::sqrtSumOfSquares(pxPos + pxNeg, pyPos + pyNeg); + }); +DECLARE_SOA_DYNAMIC_COLUMN(P, p, //! Total momentum in GeV/c + [](float pxPos, float pyPos, float pzPos, float pxNeg, float pyNeg, float pzNeg) -> float { + return RecoDecay::sqrtSumOfSquares(pxPos + pxNeg, pyPos + pyNeg, pzPos + pzNeg); + }); +DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, //! Phi in the range [0, 2pi) + [](float pxPos, float pyPos, float pxNeg, float pyNeg) -> float { return RecoDecay::phi(pxPos + pxNeg, pyPos + pyNeg); }); +DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, //! Pseudorapidity, conditionally defined to avoid FPEs + [](float pxPos, float pyPos, float pzPos, float pxNeg, float pyNeg, float pzNeg) -> float { + return RecoDecay::eta(std::array{pxPos + pxNeg, pyPos + pyNeg, pzPos + pzNeg}); + }); // Account for rigidity in case of hypertriton DECLARE_SOA_DYNAMIC_COLUMN(PtHypertriton, ptHypertriton, //! V0 pT [](float pxpos, float pypos, float pxneg, float pyneg) -> float { return RecoDecay::sqrtSumOfSquares(2.0f * pxpos + pxneg, 2.0f * pypos + pyneg); }); @@ -666,8 +652,8 @@ DECLARE_SOA_DYNAMIC_COLUMN(V0Radius, v0radius, //! V0 decay radius (2D, centered // Distance Over To Mom DECLARE_SOA_DYNAMIC_COLUMN(DistOverTotMom, distovertotmom, //! PV to V0decay distance over total momentum - [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) { - float P = RecoDecay::sqrtSumOfSquares(Px, Py, Pz); + [](float X, float Y, float Z, float pxPos, float pyPos, float pzPos, float pxNeg, float pyNeg, float pzNeg, float pvX, float pvY, float pvZ) { + float P = RecoDecay::sqrtSumOfSquares(pxPos + pxNeg, pyPos + pyNeg, pzPos + pzNeg); return std::sqrt(std::pow(X - pvX, 2) + std::pow(Y - pvY, 2) + std::pow(Z - pvZ, 2)) / (P + 1E-10); }); @@ -746,19 +732,23 @@ DECLARE_SOA_DYNAMIC_COLUMN(M, m, //! mass under a certain hypothesis (0:K0, 1:L, }); DECLARE_SOA_DYNAMIC_COLUMN(YK0Short, yK0Short, //! V0 y with K0short hypothesis - [](float Px, float Py, float Pz) -> float { return RecoDecay::y(std::array{Px, Py, Pz}, o2::constants::physics::MassKaonNeutral); }); + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { + return RecoDecay::y(std::array{pxpos + pxneg, pypos + pyneg, pzpos + pzneg}, o2::constants::physics::MassKaonNeutral); + }); DECLARE_SOA_DYNAMIC_COLUMN(YLambda, yLambda, //! V0 y with lambda or antilambda hypothesis - [](float Px, float Py, float Pz) -> float { return RecoDecay::y(std::array{Px, Py, Pz}, o2::constants::physics::MassLambda); }); + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { + return RecoDecay::y(std::array{pxpos + pxneg, pypos + pyneg, pzpos + pzneg}, o2::constants::physics::MassLambda); + }); DECLARE_SOA_DYNAMIC_COLUMN(YHypertriton, yHypertriton, //! V0 y with hypertriton hypothesis [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::y(std::array{2.0f * pxpos + pxneg, 2.0f * pypos + pyneg, 2.0f * pzpos + pzneg}, o2::constants::physics::MassHyperTriton); }); DECLARE_SOA_DYNAMIC_COLUMN(YAntiHypertriton, yAntiHypertriton, //! V0 y with antihypertriton hypothesis [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::y(std::array{pxpos + 2.0f * pxneg, pypos + 2.0f * pyneg, pzpos + 2.0f * pzneg}, o2::constants::physics::MassHyperTriton); }); DECLARE_SOA_DYNAMIC_COLUMN(Rapidity, rapidity, //! rapidity (0:K0, 1:L, 2:Lbar) - [](float Px, float Py, float Pz, int value) -> float { + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg, int value) -> float { if (value == 0) - return RecoDecay::y(std::array{Px, Py, Pz}, o2::constants::physics::MassKaonNeutral); + return RecoDecay::y(std::array{pxpos + pxneg, pypos + pyneg, pzpos + pzneg}, o2::constants::physics::MassKaonNeutral); if (value == 1 || value == 2) - return RecoDecay::y(std::array{Px, Py, Pz}, o2::constants::physics::MassLambda); + return RecoDecay::y(std::array{pxpos + pxneg, pypos + pyneg, pzpos + pzneg}, o2::constants::physics::MassLambda); return 0.0f; }); @@ -820,10 +810,17 @@ DECLARE_SOA_TABLE_STAGED(V0CoresBase, "V0CORE", //! core information about decay v0data::V0CosPA, v0data::DCAV0ToPV, v0data::V0Type, // Dynamic columns + v0data::Px, + v0data::Py, + v0data::Pz, + v0data::Pt, + v0data::P, + v0data::Phi, + v0data::Eta, v0data::PtHypertriton, v0data::PtAntiHypertriton, v0data::V0Radius, - v0data::DistOverTotMom, + v0data::DistOverTotMom, v0data::Alpha, v0data::QtArm, v0data::PsiPair, @@ -840,11 +837,11 @@ DECLARE_SOA_TABLE_STAGED(V0CoresBase, "V0CORE", //! core information about decay v0data::M, // Longitudinal - v0data::YK0Short, - v0data::YLambda, + v0data::YK0Short, + v0data::YLambda, v0data::YHypertriton, v0data::YAntiHypertriton, - v0data::Rapidity, + v0data::Rapidity, v0data::NegativePt, v0data::PositivePt, v0data::NegativeEta, @@ -855,8 +852,8 @@ DECLARE_SOA_TABLE_STAGED(V0CoresBase, "V0CORE", //! core information about decay v0data::IsPhotonTPConly); // extended table with expression columns that can be used as arguments of dynamic columns -DECLARE_SOA_EXTENDED_TABLE_USER(V0Cores, V0CoresBase, "V0COREEXT", //! - v0data::Px, v0data::Py, v0data::Pz, v0data::Pt, v0data::P, v0data::Phi, v0data::Eta); // the table name has here to be the one with EXT which is not nice and under study +// DECLARE_SOA_EXTENDED_TABLE_USER(V0Cores, V0CoresBase, "V0COREEXT", //! +// v0data::Px, v0data::Py, v0data::Pz, v0data::Pt, v0data::P, v0data::Phi, v0data::Eta); // the table name has here to be the one with EXT which is not nice and under study // // extended table with expression columns that can be used as arguments of dynamic columns // DECLARE_SOA_EXTENDED_TABLE_USER(StoredV0Cores, StoredV0CoresBase, "V0COREEXT", //! @@ -894,10 +891,17 @@ DECLARE_SOA_TABLE_FULL(StoredV0fCCores, "V0fCCores", "AOD", "V0FCCORE", //! core v0data::V0CosPA, v0data::DCAV0ToPV, v0data::V0Type, // Dynamic columns + v0data::Px, + v0data::Py, + v0data::Pz, + v0data::Pt, + v0data::P, + v0data::Phi, + v0data::Eta, v0data::PtHypertriton, v0data::PtAntiHypertriton, v0data::V0Radius, - v0data::DistOverTotMom, + v0data::DistOverTotMom, v0data::Alpha, v0data::QtArm, v0data::PsiPair, @@ -914,11 +918,11 @@ DECLARE_SOA_TABLE_FULL(StoredV0fCCores, "V0fCCores", "AOD", "V0FCCORE", //! core v0data::M, // Longitudinal - v0data::YK0Short, - v0data::YLambda, + v0data::YK0Short, + v0data::YLambda, v0data::YHypertriton, v0data::YAntiHypertriton, - v0data::Rapidity, + v0data::Rapidity, v0data::NegativePt, v0data::PositivePt, v0data::NegativeEta, @@ -930,8 +934,8 @@ DECLARE_SOA_TABLE_FULL(StoredV0fCCores, "V0fCCores", "AOD", "V0FCCORE", //! core o2::soa::Marker<2>); // extended table with expression columns that can be used as arguments of dynamic columns -DECLARE_SOA_EXTENDED_TABLE_USER(V0fCCores, StoredV0fCCores, "V0FCCOREEXT", //! - v0data::Px, v0data::Py, v0data::Pz, v0data::Pt, v0data::P, v0data::Phi, v0data::Eta); // the table name has here to be the one with EXT which is not nice and under study +// DECLARE_SOA_EXTENDED_TABLE_USER(V0fCCores, StoredV0fCCores, "V0FCCOREEXT", //! +// v0data::Px, v0data::Py, v0data::Pz, v0data::Pt, v0data::P, v0data::Phi, v0data::Eta); // the table name has here to be the one with EXT which is not nice and under study DECLARE_SOA_TABLE_FULL(V0fCCovs, "V0fCCovs", "AOD", "V0FCCOVS", //! V0 covariance matrices v0data::PositionCovMat, v0data::MomentumCovMat, o2::soa::Marker<2>); @@ -1001,6 +1005,9 @@ DECLARE_SOA_TABLE(GeAntiLambda, "AOD", "GeAntiLambda", v0data::GeneratedAntiLamb DECLARE_SOA_TABLE_STAGED(V0MCMothers, "V0MCMOTHER", //! optional table for MC mothers o2::soa::Index<>, v0data::MotherMCPartId); +using V0fCCores = StoredV0fCCores; +using V0Cores = V0CoresBase; + using V0MCCores = V0MCCores_002; using StoredV0MCCores = StoredV0MCCores_002; @@ -1263,13 +1270,20 @@ DECLARE_SOA_DYNAMIC_COLUMN(CascRadius, cascradius, //! // CosPAs DECLARE_SOA_DYNAMIC_COLUMN(V0CosPA, v0cosPA, //! - [](float Xlambda, float Ylambda, float Zlambda, float PxLambda, float PyLambda, float PzLambda, float pvX, float pvY, float pvZ) -> float { return RecoDecay::cpa(std::array{pvX, pvY, pvZ}, std::array{Xlambda, Ylambda, Zlambda}, std::array{PxLambda, PyLambda, PzLambda}); }); + [](float Xlambda, float Ylambda, float Zlambda, float pxPos, float pyPos, float pzPos, float pxNeg, float pyNeg, float pzNeg, float pvX, float pvY, float pvZ) -> float { + return RecoDecay::cpa(std::array{pvX, pvY, pvZ}, std::array{Xlambda, Ylambda, Zlambda}, std::array{pxPos + pxNeg, pyPos + pyNeg, pzPos + pzNeg}); + }); // DECLARE_SOA_DYNAMIC_COLUMN(CascCosPA, casccosPA, //! // [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) -> float { return RecoDecay::cpa(std::array{pvX, pvY, pvZ}, std::array{X, Y, Z}, std::array{Px, Py, Pz}); }); DECLARE_SOA_DYNAMIC_COLUMN(CascCosPA, casccosPA, //! [](float X, float Y, float Z, float PxBach, float PxPos, float PxNeg, float PyBach, float PyPos, float PyNeg, float PzBach, float PzPos, float PzNeg, float pvX, float pvY, float pvZ) -> float { return RecoDecay::cpa(std::array{pvX, pvY, pvZ}, std::array{X, Y, Z}, std::array{PxBach + PxPos + PxNeg, PyBach + PyPos + PyNeg, PzBach + PzPos + PzNeg}); }); DECLARE_SOA_DYNAMIC_COLUMN(DCAV0ToPV, dcav0topv, //! - [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) -> float { return std::sqrt((std::pow((pvY - Y) * Pz - (pvZ - Z) * Py, 2) + std::pow((pvX - X) * Pz - (pvZ - Z) * Px, 2) + std::pow((pvX - X) * Py - (pvY - Y) * Px, 2)) / (Px * Px + Py * Py + Pz * Pz)); }); + [](float X, float Y, float Z, float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg, float pvX, float pvY, float pvZ) -> float { + float px = pxpos + pxneg; + float py = pypos + pyneg; + float pz = pzpos + pzneg; + return std::sqrt((std::pow((pvY - Y) * pz - (pvZ - Z) * py, 2) + std::pow((pvX - X) * pz - (pvZ - Z) * px, 2) + std::pow((pvX - X) * py - (pvY - Y) * px, 2)) / (px * px + py * py + pz * pz)); + }); // Calculated on the fly with mass assumption + dynamic tables DECLARE_SOA_DYNAMIC_COLUMN(MLambda, mLambda, //! @@ -1332,42 +1346,22 @@ DECLARE_SOA_DYNAMIC_COLUMN(BachelorPtMC, bachelorptMC, //! bachelor daughter pT [](float pxBachMC, float pyBachMC) -> float { return RecoDecay::sqrtSumOfSquares(pxBachMC, pyBachMC); }); DECLARE_SOA_DYNAMIC_COLUMN(PtMC, ptMC, //! cascade pT [](float pxMC, float pyMC) -> float { return RecoDecay::sqrtSumOfSquares(pxMC, pyMC); }); -} // namespace cascdata -//______________________________________________________ -// EXPRESSION COLUMNS FOR TRACASCCORES -namespace cascdataext -{ -DECLARE_SOA_EXPRESSION_COLUMN(PxLambda, pxlambda, //! - float, 1.f * aod::cascdata::pxpos + 1.f * aod::cascdata::pxneg); -DECLARE_SOA_EXPRESSION_COLUMN(PyLambda, pylambda, //! - float, 1.f * aod::cascdata::pypos + 1.f * aod::cascdata::pyneg); -DECLARE_SOA_EXPRESSION_COLUMN(PzLambda, pzlambda, //! - float, 1.f * aod::cascdata::pzpos + 1.f * aod::cascdata::pzneg); -DECLARE_SOA_EXPRESSION_COLUMN(Pt, pt, float, //! Transverse momentum in GeV/c - nsqrt(aod::cascdata::px* aod::cascdata::px + - aod::cascdata::py * aod::cascdata::py)); -DECLARE_SOA_EXPRESSION_COLUMN(P, p, float, //! Total momentum in GeV/c - nsqrt(aod::cascdata::px* aod::cascdata::px + - aod::cascdata::py * aod::cascdata::py + - aod::cascdata::pz * aod::cascdata::pz)); -DECLARE_SOA_EXPRESSION_COLUMN(Phi, phi, float, //! Phi in the range [0, 2pi) - o2::constants::math::PI + natan2(-1.0f * aod::cascdata::py, -1.0f * aod::cascdata::px)); -DECLARE_SOA_EXPRESSION_COLUMN(Eta, eta, float, //! Pseudorapidity, conditionally defined to avoid FPEs - ifnode((nsqrt(aod::cascdata::px * aod::cascdata::px + - aod::cascdata::py * aod::cascdata::py + - aod::cascdata::pz * aod::cascdata::pz) - - aod::cascdata::pz) < static_cast(1e-7), - ifnode(aod::cascdata::pz < 0.f, -100.f, 100.f), - 0.5f * nlog((nsqrt(aod::cascdata::px * aod::cascdata::px + - aod::cascdata::py * aod::cascdata::py + - aod::cascdata::pz * aod::cascdata::pz) + - aod::cascdata::pz) / - (nsqrt(aod::cascdata::px * aod::cascdata::px + - aod::cascdata::py * aod::cascdata::py + - aod::cascdata::pz * aod::cascdata::pz) - - aod::cascdata::pz)))); -} // namespace cascdataext +DECLARE_SOA_DYNAMIC_COLUMN(PxLambda, pxlambda, //! Lambda daughter px + [](float pxPos, float pxNeg) -> float { return pxPos + pxNeg; }); +DECLARE_SOA_DYNAMIC_COLUMN(PyLambda, pylambda, //! Lambda daughter py + [](float pyPos, float pyNeg) -> float { return pyPos + pyNeg; }); +DECLARE_SOA_DYNAMIC_COLUMN(PzLambda, pzlambda, //! Lambda daughter pz + [](float pzPos, float pzNeg) -> float { return pzPos + pzNeg; }); +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! Cascade transverse momentum in GeV/c + [](float px, float py) -> float { return RecoDecay::sqrtSumOfSquares(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(P, p, //! Cascade total momentum in GeV/c + [](float px, float py, float pz) -> float { return RecoDecay::sqrtSumOfSquares(px, py, pz); }); +DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, //! Cascade phi in the range [0, 2pi) + [](float px, float py) -> float { return RecoDecay::phi(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, //! Cascade pseudorapidity + [](float px, float py, float pz) -> float { return RecoDecay::eta(std::array{px, py, pz}); }); +} // namespace cascdata //______________________________________________________ // Cascade data model: @@ -1413,11 +1407,18 @@ DECLARE_SOA_TABLE(StoredCascCores, "AOD", "CASCCORE", //! core information about cascdata::DCAPosToPV, cascdata::DCANegToPV, cascdata::DCABachToPV, cascdata::DCAXYCascToPV, cascdata::DCAZCascToPV, // Dynamic columns + cascdata::PxLambda, + cascdata::PyLambda, + cascdata::PzLambda, + cascdata::Pt, + cascdata::P, + cascdata::Phi, + cascdata::Eta, cascdata::V0Radius, cascdata::CascRadius, - cascdata::V0CosPA, + cascdata::V0CosPA, cascdata::CascCosPA, - cascdata::DCAV0ToPV, + cascdata::DCAV0ToPV, // Invariant masses cascdata::MLambda, @@ -1456,11 +1457,18 @@ DECLARE_SOA_TABLE(StoredKFCascCores, "AOD", "KFCASCCORE", //! kfcascdata::MLambda, cascdata::KFV0Chi2, cascdata::KFCascadeChi2, // Dynamic columns + cascdata::PxLambda, + cascdata::PyLambda, + cascdata::PzLambda, + cascdata::Pt, + cascdata::P, + cascdata::Phi, + cascdata::Eta, cascdata::V0Radius, cascdata::CascRadius, - cascdata::V0CosPA, + cascdata::V0CosPA, cascdata::CascCosPA, - cascdata::DCAV0ToPV, + cascdata::DCAV0ToPV, // Invariant masses cascdata::M, @@ -1494,11 +1502,18 @@ DECLARE_SOA_TABLE(StoredTraCascCores, "AOD", "TRACASCCORE", //! cascdata::MatchingChi2, cascdata::TopologyChi2, cascdata::ItsClsSize, // Dynamic columns + cascdata::PxLambda, + cascdata::PyLambda, + cascdata::PzLambda, + cascdata::Pt, + cascdata::P, + cascdata::Phi, + cascdata::Eta, cascdata::V0Radius, cascdata::CascRadius, - cascdata::V0CosPA, + cascdata::V0CosPA, cascdata::CascCosPA, - cascdata::DCAV0ToPV, + cascdata::DCAV0ToPV, // Invariant masses cascdata::MLambda, @@ -1568,19 +1583,9 @@ DECLARE_SOA_TABLE(TraCascCovs, "AOD", "TRACASCCOVS", //! cascdata::MomentumCovMat, o2::soa::Marker<2>); -// extended table with expression columns that can be used as arguments of dynamic columns -DECLARE_SOA_EXTENDED_TABLE_USER(CascCores, StoredCascCores, "CascDATAEXT", //! - cascdataext::PxLambda, cascdataext::PyLambda, cascdataext::PzLambda, cascdataext::Pt, cascdataext::P, cascdataext::Eta, cascdataext::Phi); - -// extended table with expression columns that can be used as arguments of dynamic columns -DECLARE_SOA_EXTENDED_TABLE_USER(KFCascCores, StoredKFCascCores, "KFCascDATAEXT", //! - cascdataext::PxLambda, cascdataext::PyLambda, cascdataext::PzLambda, - cascdataext::Pt, cascdataext::P, cascdataext::Eta, cascdataext::Phi); - -// extended table with expression columns that can be used as arguments of dynamic columns -DECLARE_SOA_EXTENDED_TABLE_USER(TraCascCores, StoredTraCascCores, "TraCascDATAEXT", //! - cascdataext::PxLambda, cascdataext::PyLambda, cascdataext::PzLambda, - cascdataext::Pt, cascdataext::P, cascdataext::Eta, cascdataext::Phi); +using CascCores = StoredCascCores; +using KFCascCores = StoredKFCascCores; +using TraCascCores = StoredTraCascCores; namespace cascdata { diff --git a/PWGLF/TableProducer/Common/kinkBuilder.cxx b/PWGLF/TableProducer/Common/kinkBuilder.cxx index f51e1ba1599..d2b25be26a0 100644 --- a/PWGLF/TableProducer/Common/kinkBuilder.cxx +++ b/PWGLF/TableProducer/Common/kinkBuilder.cxx @@ -122,12 +122,9 @@ struct kinkBuilder { Configurable unlikeSignBkg{"unlikeSignBkg", false, "Use unlike sign background"}; // CCDB options - Configurable inputBz{"inputBz", -999, "bz field, -999 is automatic"}; Configurable ccdbPath{"ccdbPath", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; - Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; // PDG codes @@ -174,7 +171,6 @@ struct kinkBuilder { ccdb->setURL(ccdbPath); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); - ccdb->setFatalWhenNull(false); fitter.setPropagateToPCA(true); fitter.setMaxR(200.); fitter.setMinParamChange(1e-3); @@ -183,10 +179,6 @@ struct kinkBuilder { fitter.setMaxChi2(1e9); fitter.setUseAbsDCA(true); - lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); - int mat{static_cast(cfgMaterialCorrection)}; - fitter.setMatCorrType(static_cast(mat)); - svCreator.setTimeMargin(customVertexerTimeMargin); if (skipAmbiTracks) { svCreator.setSkipAmbiTracks(); @@ -210,6 +202,11 @@ struct kinkBuilder { h2MothMassPt = qaRegistry.add("h2MothMassPt", "; p_{T} (GeV/#it{c}); m (GeV/#it{c}^{2})", HistType::kTH2F, {ptAxis, massAxis}); h2ClsMapPtMoth = qaRegistry.add("h2ClsMapPtMoth", "; p_{T} (GeV/#it{c}); ITS cluster map", HistType::kTH2F, {ptAxis, itsClusterMapAxis}); h2ClsMapPtDaug = qaRegistry.add("h2ClsMapPtDaug", "; p_{T} (GeV/#it{c}); ITS cluster map", HistType::kTH2F, {ptAxis, itsClusterMapAxis}); + + for (int i = 0; i < 5; i++) { + mBBparamsDaug[i] = cfgBetheBlochParams->get("Daughter", Form("p%i", i)); + } + mBBparamsDaug[5] = cfgBetheBlochParams->get("Daughter", "resolution"); } template @@ -247,7 +244,7 @@ struct kinkBuilder { } template - void fillCandidateData(const Tcolls& collisions, const Ttracks& tracks, aod::AmbiguousTracks const& ambiguousTracks, aod::BCsWithTimestamps const& bcs) + void fillCandidateData(const Tcolls& collisions, const Ttracks& tracks, aod::AmbiguousTracks const& ambiguousTracks, aod::BCs const& bcs) { svCreator.clearPools(); svCreator.fillBC2Coll(collisions, bcs); @@ -274,7 +271,7 @@ struct kinkBuilder { auto trackDaug = tracks.rawIteratorAt(svCand.tr1Idx); auto const& collision = trackMoth.template collision_as(); - auto const& bc = collision.template bc_as(); + auto const& bc = collision.template bc_as(); initCCDB(bc); o2::dataformats::VertexBase primaryVertex; @@ -283,9 +280,9 @@ struct kinkBuilder { kinkCand.primVtx = {primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}; o2::track::TrackParCov trackParCovMoth = getTrackParCov(trackMoth); + o2::track::TrackParCov trackParCovMothPV{trackParCovMoth}; o2::base::Propagator::Instance()->PropagateToXBxByBz(trackParCovMoth, LayerRadii[trackMoth.itsNCls() - 1]); - o2::track::TrackParCov trackParCovMothPV = getTrackParCov(trackMoth); std::array dcaInfoMoth; o2::base::Propagator::Instance()->propagateToDCABxByBz({primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, trackParCovMothPV, 2.f, static_cast(cfgMaterialCorrection.value), &dcaInfoMoth); @@ -401,51 +398,28 @@ struct kinkBuilder { } } - void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + void initCCDB(aod::BCs::iterator const& bc) { if (mRunNumber == bc.runNumber()) { return; } - auto run3grp_timestamp = bc.timestamp(); - - o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); - o2::parameters::GRPMagField* grpmag = 0x0; - if (grpo) { - o2::base::Propagator::initFieldFromGRP(grpo); - if (inputBz < -990) { - // Fetch magnetic field from ccdb for current collision - mBz = grpo->getNominalL3Field(); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << mBz << " kZG"; - } else { - mBz = inputBz; - } - } else { - grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); - if (!grpmag) { - LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; - } - o2::base::Propagator::initFieldFromGRP(grpmag); - if (inputBz < -990) { - // Fetch magnetic field from ccdb for current collision - mBz = std::lround(5.f * grpmag->getL3Current() / 30000.f); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << mBz << " kZG"; - } else { - mBz = inputBz; - } - } + mRunNumber = bc.runNumber(); + LOG(info) << "Initializing CCDB for run " << mRunNumber; + o2::parameters::GRPMagField* grpmag = ccdb->getForRun(grpmagPath, mRunNumber); + o2::base::Propagator::initFieldFromGRP(grpmag); + mBz = grpmag->getNominalL3Field(); + fitter.setBz(mBz); - for (int i = 0; i < 5; i++) { - mBBparamsDaug[i] = cfgBetheBlochParams->get("Daughter", Form("p%i", i)); + if (!lut) { + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); + int mat{static_cast(cfgMaterialCorrection)}; + fitter.setMatCorrType(static_cast(mat)); } - mBBparamsDaug[5] = cfgBetheBlochParams->get("Daughter", "resolution"); - - fitter.setBz(mBz); - mRunNumber = bc.runNumber(); o2::base::Propagator::Instance()->setMatLUT(lut); LOG(info) << "Task initialized for run " << mRunNumber << " with magnetic field " << mBz << " kZG"; } - void process(aod::Collisions const& collisions, TracksFull const& tracks, aod::AmbiguousTracks const& ambiTracks, aod::BCsWithTimestamps const& bcs) + void process(aod::Collisions const& collisions, TracksFull const& tracks, aod::AmbiguousTracks const& ambiTracks, aod::BCs const& bcs) { kinkCandidates.clear(); diff --git a/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx b/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx index 712e3611013..551fbb56e6d 100644 --- a/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx +++ b/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx @@ -1017,16 +1017,15 @@ struct nucleiSpectra { if (pdg != nuclei::codes[iS]) { continue; } - uint16_t flags{kIsPhysicalPrimary}; - if (particle.isPhysicalPrimary()) { - if (particle.y() > cfgCutRapidityMin && particle.y() < cfgCutRapidityMax) { - nuclei::hGenNuclei[iS][particle.pdgCode() < 0]->Fill(1., particle.pt()); - } + if (particle.y() < cfgCutRapidityMin || particle.y() > cfgCutRapidityMax) { + continue; } - if (!isReconstructed[index] && (cfgTreeConfig->get(iS, 0u) || cfgTreeConfig->get(iS, 1u))) { - float absDecL = computeAbsoDecL(particle); - int motherPdgCode = 0; + uint16_t flags = 0; + int motherPdgCode = 0; + if (particle.isPhysicalPrimary()) { + flags |= kIsPhysicalPrimary; + nuclei::hGenNuclei[iS][particle.pdgCode() < 0]->Fill(1., particle.pt()); if (particle.has_mothers()) { for (auto& motherparticle : particle.mothers_as()) { if (std::find(nuclei::hfMothCodes.begin(), nuclei::hfMothCodes.end(), std::abs(motherparticle.pdgCode())) != nuclei::hfMothCodes.end()) { @@ -1036,6 +1035,18 @@ struct nucleiSpectra { } } } + } else if (particle.has_mothers()) { + flags |= kIsSecondaryFromWeakDecay; + for (auto& motherparticle : particle.mothers_as()) { + motherPdgCode = motherparticle.pdgCode(); + } + } else { + flags |= kIsSecondaryFromMaterial; + } + + if (!isReconstructed[index] && (cfgTreeConfig->get(iS, 0u) || cfgTreeConfig->get(iS, 1u))) { + float absDecL = computeAbsoDecL(particle); + nucleiTableMC(999., 999., 999., 0., 0., 999., 999., 999., -1, -1, -1, -1, flags, 0, 0, 0, 0, 0, 0, particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), motherPdgCode, goodCollisions[particle.mcCollisionId()], absDecL); } break; diff --git a/PWGLF/TableProducer/Strangeness/cascadebuilder.cxx b/PWGLF/TableProducer/Strangeness/cascadebuilder.cxx index 453072b6b30..b4a19e6660b 100644 --- a/PWGLF/TableProducer/Strangeness/cascadebuilder.cxx +++ b/PWGLF/TableProducer/Strangeness/cascadebuilder.cxx @@ -2388,14 +2388,6 @@ struct cascadePreselector { //*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<* }; -/// Extends the cascdata table with expression columns -struct cascadeInitializer { - Spawns cascdataext; - Spawns kfcascdataext; - Spawns tracascdataext; - void init(InitContext const&) {} -}; - struct cascadeLinkBuilder { Produces cascdataLink; @@ -2482,7 +2474,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) return WorkflowSpec{ adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc)}; diff --git a/PWGLF/TableProducer/Strangeness/cascadefinder.cxx b/PWGLF/TableProducer/Strangeness/cascadefinder.cxx index fcb0479fca2..3901d3f14c3 100644 --- a/PWGLF/TableProducer/Strangeness/cascadefinder.cxx +++ b/PWGLF/TableProducer/Strangeness/cascadefinder.cxx @@ -430,17 +430,10 @@ struct cascadefinderQA { } }; -/// Extends the cascdata table with expression columns -struct cascadeinitializer { - Spawns cascdataext; - void init(InitContext const&) {} -}; - WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ adaptAnalysisTask(cfgc, TaskName{"lf-cascadeprefilter"}), adaptAnalysisTask(cfgc, TaskName{"lf-cascadefinder"}), - adaptAnalysisTask(cfgc, TaskName{"lf-cascadefinderQA"}), - adaptAnalysisTask(cfgc, TaskName{"lf-cascadeinitializer"})}; + adaptAnalysisTask(cfgc, TaskName{"lf-cascadefinderQA"})}; } diff --git a/PWGLF/TableProducer/Strangeness/cascadespawner.cxx b/PWGLF/TableProducer/Strangeness/cascadespawner.cxx index dc004b91e78..ab3f4cb7c3d 100644 --- a/PWGLF/TableProducer/Strangeness/cascadespawner.cxx +++ b/PWGLF/TableProducer/Strangeness/cascadespawner.cxx @@ -35,7 +35,7 @@ using namespace o2::framework::expressions; /// Extends the cascdata table with expression columns struct cascadespawner { - Spawns cascdataext; + // Spawns cascdataext; void init(InitContext const&) {} }; diff --git a/PWGLF/TableProducer/Strangeness/lambdakzerobuilder.cxx b/PWGLF/TableProducer/Strangeness/lambdakzerobuilder.cxx index bcf2c1268e2..7b898bfa98e 100644 --- a/PWGLF/TableProducer/Strangeness/lambdakzerobuilder.cxx +++ b/PWGLF/TableProducer/Strangeness/lambdakzerobuilder.cxx @@ -1808,18 +1808,10 @@ struct lambdakzeroV0DataLinkBuilder { PROCESS_SWITCH(lambdakzeroV0DataLinkBuilder, processFindable, "process findable V0s", false); }; -// Extends the v0data table with expression columns -struct lambdakzeroInitializer { - Spawns v0cores; - Spawns v0fccores; - void init(InitContext const&) {} -}; - WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc)}; } diff --git a/PWGLF/TableProducer/Strangeness/lambdakzerofinder.cxx b/PWGLF/TableProducer/Strangeness/lambdakzerofinder.cxx index 60d331ea61d..e75c72c77f4 100644 --- a/PWGLF/TableProducer/Strangeness/lambdakzerofinder.cxx +++ b/PWGLF/TableProducer/Strangeness/lambdakzerofinder.cxx @@ -429,17 +429,10 @@ struct lambdakzerofinderQa { PROCESS_SWITCH(lambdakzerofinderQa, processRun2, "Process Run 2 data", false); }; -/// Extends the v0data table with expression columns -struct lambdakzeroinitializer { - Spawns v0cores; - void init(InitContext const&) {} -}; - WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ adaptAnalysisTask(cfgc, TaskName{"lf-lambdakzeroprefilter"}), adaptAnalysisTask(cfgc, TaskName{"lf-lambdakzerofinder"}), - adaptAnalysisTask(cfgc, TaskName{"lf-lambdakzerofinderQA"}), - adaptAnalysisTask(cfgc, TaskName{"lf-lambdakzeroinitializer"})}; + adaptAnalysisTask(cfgc, TaskName{"lf-lambdakzerofinderQA"})}; } diff --git a/PWGLF/TableProducer/Strangeness/lambdakzerospawner.cxx b/PWGLF/TableProducer/Strangeness/lambdakzerospawner.cxx index 7ec0b4cc010..19c174aef7f 100644 --- a/PWGLF/TableProducer/Strangeness/lambdakzerospawner.cxx +++ b/PWGLF/TableProducer/Strangeness/lambdakzerospawner.cxx @@ -35,7 +35,7 @@ using namespace o2::framework::expressions; // Extends the v0data table with expression columns struct lambdakzerospawner { - Spawns v0cores; + // Spawns v0cores; void init(InitContext const&) {} }; diff --git a/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx b/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx index f00a1e646dc..c38c792f5e1 100644 --- a/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx +++ b/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx @@ -301,6 +301,9 @@ struct StrangenessBuilder { Configurable mc_findableMode{"mc_findableMode", 0, "0: disabled; 1: add findable-but-not-found to existing V0s from AO2D; 2: reset V0s and generate only findable-but-not-found"}; + // Autoconfigure process functions + Configurable autoConfigureProcess{"autoConfigureProcess", false, "if true, will configure process function switches based on metadata"}; + // V0 building options struct : ConfigurableGroup { std::string prefix = "v0BuilderOpts"; @@ -2644,18 +2647,77 @@ struct StrangenessBuilder { PROCESS_SWITCH(StrangenessBuilder, processMonteCarloRun2WithPID, "process monte carlo (Run 2)", false); }; -// Extends the v0data table with expression columns -struct strangenessbuilderInitializer { - Spawns v0cores; - Spawns cascdataext; - Spawns kfcascdataext; - Spawns tracascdataext; - void init(InitContext const&) {} -}; - WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { + auto strangenessBuilderTask = adaptAnalysisTask(cfgc); + bool isRun3 = true, hasRunInfo = false; + bool isMC = false, hasDataTypeInfo = false; + if (cfgc.options().hasOption("aod-metadata-Run") == true) { + hasRunInfo = true; + if (cfgc.options().get("aod-metadata-Run") == "2") { + isRun3 = false; + } + } + if (cfgc.options().hasOption("aod-metadata-DataType") == true) { + hasDataTypeInfo = true; + if (cfgc.options().get("aod-metadata-DataType") == "MC") { + isMC = true; + } + } + + int idxSwitches[8]; // 8 switches (real / real r2 / MC / MC r2 + PID) + bool autoConfigureProcessConfig = true; + bool withPID = false; + + for (size_t ipar = 0; ipar < strangenessBuilderTask.options.size(); ipar++) { + auto option = strangenessBuilderTask.options[ipar]; + if (option.name == "processRealData") { + idxSwitches[0] = ipar; + } + if (option.name == "processRealDataRun2") { + idxSwitches[1] = ipar; + } + if (option.name == "processMonteCarlo") { + idxSwitches[2] = ipar; + } + if (option.name == "processMonteCarloRun2") { + idxSwitches[3] = ipar; + } + if (option.name == "processRealDataWithPID") { + idxSwitches[4] = ipar; + } + if (option.name == "processRealDataRun2WithPID") { + idxSwitches[5] = ipar; + } + if (option.name == "processMonteCarloWithPID") { + idxSwitches[6] = ipar; + } + if (option.name == "processMonteCarloRun2WithPID") { + idxSwitches[7] = ipar; + } + if (option.name == "autoConfigureProcess") { + autoConfigureProcessConfig = option.defaultValue.get(); // check if autoconfig requested + } + // use withPID in case preselection is requested + if (option.name == "preSelectOpts.preselectOnlyDesiredV0s" || option.name == "preSelectOpts.preselectOnlyDesiredCascades") { + withPID = withPID || option.defaultValue.get(); + } + } + if ((!hasRunInfo || !hasDataTypeInfo) && autoConfigureProcessConfig) { + throw std::runtime_error("Autoconfigure requested but no metadata information found! Please check if --aod-file was used in the last workflow added in the execution and if the AO2D in question has metadata saved in it."); + } + + // positions of switches are known. Next: flip if asked for + if (autoConfigureProcessConfig) { + int relevantProcess = static_cast(!isRun3) + 2 * static_cast(isMC) + 4 * static_cast(withPID); + LOGF(info, "Automatic configuration of process switches requested! Autodetected settings: isRun3? %i, isMC? %i, withPID? %i (switch #%i)", hasRunInfo, hasDataTypeInfo, isRun3, isMC, withPID, relevantProcess); + for (size_t idx = 0; idx < 8; idx++) { + auto option = strangenessBuilderTask.options[idxSwitches[idx]]; + option.defaultValue = false; // switch all off + } + strangenessBuilderTask.options[idxSwitches[relevantProcess]].defaultValue = true; + } + return WorkflowSpec{ - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc)}; + strangenessBuilderTask}; } diff --git a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx index ab7c0d543bd..606c5713d5e 100644 --- a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx @@ -581,6 +581,13 @@ struct HStrangeCorrelation { hEfficiencyV0[0] = hEfficiencyK0Short; hEfficiencyV0[1] = hEfficiencyLambda; hEfficiencyV0[2] = hEfficiencyAntiLambda; + + float etaWeight = 1; + if (systCuts.doOnTheFlyFlattening) { + float preWeight = 1 - std::abs(deltaeta) / 1.6; + etaWeight = preWeight != 0 ? 1.0f / preWeight : 0.0f; + } + static_for<0, 2>([&](auto i) { constexpr int Index = i.value; float efficiency = 1.0f; @@ -595,6 +602,7 @@ struct HStrangeCorrelation { } float weight = (applyEfficiencyCorrection || applyEfficiencyForTrigger) ? 1. / efficiency : 1.0f; + weight = weight * etaWeight; if (TESTBIT(doCorrelation, Index) && (!applyEfficiencyCorrection || efficiency != 0) && (doPPAnalysis || (TESTBIT(selMap, Index) && TESTBIT(selMap, Index + 3)))) { if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) histos.fill(HIST("sameEvent/LeftBg/") + HIST(kV0names[Index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); @@ -703,6 +711,12 @@ struct HStrangeCorrelation { hEfficiencyCascade[2] = hEfficiencyOmegaMinus; hEfficiencyCascade[3] = hEfficiencyOmegaPlus; + float etaWeight = 1; + if (systCuts.doOnTheFlyFlattening) { + float preWeight = 1 - std::abs(deltaeta) / 1.6; + etaWeight = preWeight != 0 ? 1.0f / preWeight : 0.0f; + } + static_for<0, 3>([&](auto i) { constexpr int Index = i.value; float efficiency = 1.0f; @@ -716,6 +730,7 @@ struct HStrangeCorrelation { efficiency = 1; } float weight = (applyEfficiencyCorrection || applyEfficiencyForTrigger) ? 1. / efficiency : 1.0f; + weight = weight * etaWeight; if (TESTBIT(doCorrelation, Index + 3) && (!applyEfficiencyCorrection || efficiency != 0) && (doPPAnalysis || (TESTBIT(CascselMap, Index) && TESTBIT(CascselMap, Index + 4) && TESTBIT(CascselMap, Index + 8) && TESTBIT(CascselMap, Index + 12)))) { if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) histos.fill(HIST("sameEvent/LeftBg/") + HIST(kCascadenames[Index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); diff --git a/PWGLF/Tasks/Strangeness/lambdaJetpolarization.cxx b/PWGLF/Tasks/Strangeness/lambdaJetpolarization.cxx index 6fa6c332398..3acfbad4d10 100644 --- a/PWGLF/Tasks/Strangeness/lambdaJetpolarization.cxx +++ b/PWGLF/Tasks/Strangeness/lambdaJetpolarization.cxx @@ -54,6 +54,7 @@ struct LfMyV0s { HistogramRegistry registry{"registry"}; HistogramRegistry registryData{"registryData", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry registryV0Data{"registryV0Data", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry registryLongitudinalPolarization{"registryLongitudinalPolarization", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; Configurable zVtx{"zVtx", 10.0, "Maximum zVertex"}; Configurable rJet{"rJet", 0.4, "Jet resolution parameter R"}; @@ -94,13 +95,13 @@ struct LfMyV0s { Configurable ispassdTrackSelectionForJetReconstruction{"ispassdTrackSelectionForJetReconstruction", 1, "do track selection"}; // v0Event selection - Configurable sel8{"sel8", 0, "Apply sel8 event selection"}; + Configurable sel8{"sel8", 1, "Apply sel8 event selection"}; Configurable isTriggerTVX{"isTriggerTVX", 1, "TVX trigger"}; Configurable iscutzvertex{"iscutzvertex", 1, "Accepted z-vertex range (cm)"}; Configurable isNoTimeFrameBorder{"isNoTimeFrameBorder", 1, "TF border cut"}; Configurable isNoITSROFrameBorder{"isNoITSROFrameBorder", 1, "ITS ROF border cut"}; Configurable isVertexTOFmatched{"isVertexTOFmatched", 1, "Is Vertex TOF matched"}; - Configurable isGoodZvtxFT0vsPV{"isGoodZvtxFT0vsPV", 0, "isGoodZvtxFT0vsPV"}; + Configurable isGoodZvtxFT0vsPV{"isGoodZvtxFT0vsPV", 1, "isGoodZvtxFT0vsPV"}; Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; Configurable CtauLambda{"ctauLambda", 30, "C tau Lambda (cm)"}; Configurable requirepassedSingleTrackSelection{"requirepassedSingleTrackSelection", false, "requirepassedSingleTrackSelection"}; @@ -111,10 +112,11 @@ struct LfMyV0s { Configurable yMax{"V0yMax", +0.5f, "maximum y"}; Configurable v0rejLambda{"v0rejLambda", 0.01, "V0 rej Lambda"}; Configurable v0accLambda{"v0accLambda", 0.075, "V0 acc Lambda"}; - Configurable ifinitpasslambda{"ifinitpasslambda", 1, "ifinitpasslambda"}; - Configurable ifpasslambda{"passedLambdaSelection", 0, "passedLambdaSelection"}; + Configurable ifinitpasslambda{"ifinitpasslambda", 0, "ifinitpasslambda"}; + Configurable ifpasslambda{"passedLambdaSelection", 1, "passedLambdaSelection"}; Configurable paramArmenterosCut{"paramArmenterosCut", 0.2, "parameter Armenteros Cut"}; Configurable doArmenterosCut{"doArmenterosCut", 0, "do Armenteros Cut"}; + Configurable noSameBunchPileUp{"noSameBunchPileUp", true, "reject SameBunchPileUp"}; // Jet background subtraction JetBkgSubUtils backgroundSub; @@ -312,6 +314,40 @@ struct LfMyV0s { registryV0Data.add("AverageSinthetainJetV0", "AverageSinthetainJetV0", {HistType::kTProfile, {{200, 0.9, 1.2}}}); registryV0Data.add("AverageCosSquarethetainJetV0", "AverageCosSquarethetainJetV0", {HistType::kTProfile, {{200, 0.9, 1.2}}}); + + // LongitudinalPolarization event selection + registryLongitudinalPolarization.add("hNEvents", "hNEvents", {HistType::kTH1I, {{5, 0.f, 5.f}}}); + registryLongitudinalPolarization.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(1, "all"); + registryLongitudinalPolarization.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(2, "sel8"); + registryLongitudinalPolarization.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(3, "zvertex"); + registryLongitudinalPolarization.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(4, "isGoodZvtxFT0vsPV"); + registryLongitudinalPolarization.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(5, "isNoSameBunchPileup"); + registryLongitudinalPolarization.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(6, "Applied selected"); + + registryLongitudinalPolarization.add("hMassVsPtLambda", "hMassVsPtLambda", {HistType::kTH2F, {{100, 0.0f, 10.0f}, {200, 1.016f, 1.216f}}}); + registryLongitudinalPolarization.add("hMassVsPtAntiLambda", "hMassVsPtAntiLambda", {HistType::kTH2F, {{100, 0.0f, 10.0f}, {200, 1.016f, 1.216f}}}); + + registryLongitudinalPolarization.add("V0pxInRest_frame", "V0pxInRest_frame", kTH1F, {axisPx}); + registryLongitudinalPolarization.add("V0pyInRest_frame", "V0pyInRest_frame", kTH1F, {axisPy}); + registryLongitudinalPolarization.add("V0pzInRest_frame", "V0pzInRest_frame", kTH1F, {axisPz}); + + registryLongitudinalPolarization.add("nV0sPerEvent", "nV0sPerEvent", kTH1F, {{10, 0.0, 10.0}}); + registryLongitudinalPolarization.add("nV0sPerEventsel", "nV0sPerEventsel", kTH1F, {{10, 0.0, 10.0}}); + + registryLongitudinalPolarization.add("hprotoncosthetainV0", "hprotoncosthetainV0", kTH1F, {{200, -1.f, 1.f}}); + registryLongitudinalPolarization.add("hprotoncosSquarethetainV0", "hprotoncosSquarethetainV0", kTH1F, {{200, -1.f, 1.f}}); + registryLongitudinalPolarization.add("hLambdamassandCosthetaInV0", "hLambdamassandCosthetaInV0", kTH2F, {{200, 0.9, 1.2}, {200, -1, 1}}); + registryLongitudinalPolarization.add("TProfile2DLambdaPtMassCostheta", "", kTProfile2D, {TProfile2DaxisMass, TProfile2DaxisPt}); + registryLongitudinalPolarization.add("TProfile2DLambdaPtMassCosSquareTheta", "", kTProfile2D, {TProfile2DaxisMass, TProfile2DaxisPt}); + + registryLongitudinalPolarization.add("hantiprotoncosthetainV0", "hantiprotoncosthetainV0", kTH1F, {{200, -1.f, 1.f}}); + registryLongitudinalPolarization.add("hantiprotoncosSquarethetainV0", "hantiprotoncosSquarethetainV0", kTH1F, {{200, -1.f, 1.f}}); + registryLongitudinalPolarization.add("hAntiLambdamassandCosthetaInV0", "hAntiLambdamassandCosthetaInV0", kTH2F, {{200, 0.9, 1.2}, {200, -1, 1}}); + registryLongitudinalPolarization.add("TProfile2DAntiLambdaPtMassCostheta", "TProfile2DAntiLambdaPtMassCostheta", kTProfile2D, {TProfile2DaxisMass, TProfile2DaxisPt}); + registryLongitudinalPolarization.add("TProfile2DAntiLambdaPtMassCosSquareTheta", "TProfile2DAntiLambdaPtMassCosSquareTheta", kTProfile2D, {TProfile2DaxisMass, TProfile2DaxisPt}); + + registryLongitudinalPolarization.add("TProfile1DLambdaPtMassCostheta", "Invariant Mass vs cos(#theta)", {HistType::kTProfile, {{200, 0.9, 1.2}}}); + registryLongitudinalPolarization.add("TProfile1DAntiLambdaPtMassCostheta", "Invariant Mass vs cos(#theta)", {HistType::kTProfile, {{200, 0.9, 1.2}}}); } double massPr = o2::constants::physics::MassProton; double massLambda = o2::constants::physics::MassLambda; @@ -814,6 +850,32 @@ struct LfMyV0s { return true; } + template + bool AcceptEventForLongitudinalPolarization(TCollision const& collision) + { + if (sel8 && !collision.sel8()) { + return false; + } + registryLongitudinalPolarization.fill(HIST("hNEvents"), 1.5); + + if (iscutzvertex && TMath::Abs(collision.posZ()) > cutzvertex) { + return false; + } + registryLongitudinalPolarization.fill(HIST("hNEvents"), 2.5); + + if (noSameBunchPileUp && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return false; + } + registryLongitudinalPolarization.fill(HIST("hNEvents"), 3.5); + // check vertex matching to FT0 + if (isGoodZvtxFT0vsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + registryLongitudinalPolarization.fill(HIST("hNEvents"), 4.5); + + return true; + } + using SelCollisions = soa::Join; using StrHadronDaughterTracks = soa::Join; void processData(SelCollisions::iterator const& collision, aod::V0Datas const& fullV0s, StrHadronDaughterTracks const& tracks) @@ -1151,6 +1213,94 @@ struct LfMyV0s { registryV0Data.fill(HIST("nV0sPerEventsel"), V0NumbersPerEventsel); } PROCESS_SWITCH(LfMyV0s, processDataV0, "processDataV0", true); + + void processLongitudinalPolarization(SelCollisions::iterator const& collision, aod::V0Datas const& fullV0s, StrHadronDaughterTracks const&) + { + registryLongitudinalPolarization.fill(HIST("hNEvents"), 0.5); + if (!AcceptEventForLongitudinalPolarization(collision)) { + return; + } + registryLongitudinalPolarization.fill(HIST("hNEvents"), 5.5); + int V0NumbersPerEvent = 0; + int V0NumbersPerEventsel = 0; + for (const auto& v0 : fullV0s) { + V0NumbersPerEvent++; + float ctauLambda = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0; + float ctauAntiLambda = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0Bar; + const auto& pos = v0.posTrack_as(); + const auto& neg = v0.negTrack_as(); + + if (passedLambdaSelection(v0, pos, neg) && ctauLambda < CtauLambda && ifpasslambda) { + V0NumbersPerEventsel++; + registryLongitudinalPolarization.fill(HIST("hMassVsPtLambda"), v0.pt(), v0.mLambda()); + double PLambda = sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); + double ELambda = sqrt(v0.mLambda() * v0.mLambda() + PLambda * PLambda); + double protonE = sqrt(massPr * massPr + pos.px() * pos.px() + pos.py() * pos.py() + pos.pz() * pos.pz()); + TMatrixD pLabV0(4, 1); + pLabV0(0, 0) = ELambda; + pLabV0(1, 0) = v0.px(); + pLabV0(2, 0) = v0.py(); + pLabV0(3, 0) = v0.pz(); + + TMatrixD pLabproton(4, 1); + pLabproton(0, 0) = protonE; + pLabproton(1, 0) = pos.px(); + pLabproton(2, 0) = pos.py(); + pLabproton(3, 0) = pos.pz(); + + TMatrixD V0InV0(4, 1); + V0InV0 = LorentzTransInV0frame(ELambda, v0.px(), v0.py(), v0.pz()) * pLabV0; + registryLongitudinalPolarization.fill(HIST("V0pxInRest_frame"), V0InV0(1, 0)); + registryLongitudinalPolarization.fill(HIST("V0pyInRest_frame"), V0InV0(2, 0)); + registryLongitudinalPolarization.fill(HIST("V0pzInRest_frame"), V0InV0(3, 0)); + + TMatrixD protonInV0(4, 1); + protonInV0 = LorentzTransInV0frame(ELambda, v0.px(), v0.py(), v0.pz()) * pLabproton; + double protonPInV0 = sqrt(protonInV0(1, 0) * protonInV0(1, 0) + protonInV0(2, 0) * protonInV0(2, 0) + protonInV0(3, 0) * protonInV0(3, 0)); + + double protonCosThetainV0 = protonInV0(3, 0) / protonPInV0; + + registryLongitudinalPolarization.fill(HIST("hprotoncosthetainV0"), protonCosThetainV0); + registryLongitudinalPolarization.fill(HIST("hprotoncosSquarethetainV0"), protonCosThetainV0 * protonCosThetainV0); + registryLongitudinalPolarization.fill(HIST("hLambdamassandCosthetaInV0"), v0.mLambda(), protonCosThetainV0); + + registryLongitudinalPolarization.fill(HIST("TProfile2DLambdaPtMassCostheta"), v0.mLambda(), v0.pt(), protonCosThetainV0); + registryLongitudinalPolarization.fill(HIST("TProfile2DLambdaPtMassCosSquareTheta"), v0.mLambda(), v0.pt(), protonCosThetainV0 * protonCosThetainV0); + + registryLongitudinalPolarization.fill(HIST("TProfile1DLambdaPtMassCostheta"), v0.mLambda(), protonCosThetainV0); + } + if (passedAntiLambdaSelection(v0, pos, neg) && ctauAntiLambda < CtauLambda && ifpasslambda) { + registryLongitudinalPolarization.fill(HIST("hMassVsPtAntiLambda"), v0.pt(), v0.mAntiLambda()); + + double PLambda = sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); + double ELambda = sqrt(v0.mAntiLambda() * v0.mAntiLambda() + PLambda * PLambda); + double protonE = sqrt(massPr * massPr + neg.px() * neg.px() + neg.py() * neg.py() + neg.pz() * neg.pz()); + + TMatrixD pLabproton(4, 1); + pLabproton(0, 0) = protonE; + pLabproton(1, 0) = neg.px(); + pLabproton(2, 0) = neg.py(); + pLabproton(3, 0) = neg.pz(); + + TMatrixD protonInV0(4, 1); + protonInV0 = LorentzTransInV0frame(ELambda, v0.px(), v0.py(), v0.pz()) * pLabproton; + double protonPInV0 = sqrt(protonInV0(1, 0) * protonInV0(1, 0) + protonInV0(2, 0) * protonInV0(2, 0) + protonInV0(3, 0) * protonInV0(3, 0)); + + double protonCosThetainV0 = protonInV0(3, 0) / protonPInV0; + + registryLongitudinalPolarization.fill(HIST("hantiprotoncosthetainV0"), protonCosThetainV0); + registryLongitudinalPolarization.fill(HIST("hantiprotoncosSquarethetainV0"), protonCosThetainV0 * protonCosThetainV0); + registryLongitudinalPolarization.fill(HIST("hAntiLambdamassandCosthetaInV0"), v0.mAntiLambda(), protonCosThetainV0); + + registryLongitudinalPolarization.fill(HIST("TProfile2DAntiLambdaPtMassCostheta"), v0.mAntiLambda(), v0.pt(), protonCosThetainV0); + registryLongitudinalPolarization.fill(HIST("TProfile2DAntiLambdaPtMassCosSquareTheta"), v0.mAntiLambda(), v0.pt(), protonCosThetainV0 * protonCosThetainV0); + registryLongitudinalPolarization.fill(HIST("TProfile1DAntiLambdaPtMassCostheta"), v0.mAntiLambda(), protonCosThetainV0); + } + } + registryLongitudinalPolarization.fill(HIST("nV0sPerEvent"), V0NumbersPerEvent); + registryLongitudinalPolarization.fill(HIST("nV0sPerEventsel"), V0NumbersPerEventsel); + } + PROCESS_SWITCH(LfMyV0s, processLongitudinalPolarization, "processLongitudinalPolarization", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx index 51f6ba34bb2..c5388c034a2 100644 --- a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx +++ b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx @@ -121,8 +121,11 @@ struct NPCascCandidate { bool sel8; float multFT0C; float multFT0A; + float multFT0M; + float centFT0C; + float centFT0A; + float centFT0M; }; - std::array isFromHF(auto& particle) { bool fromBeauty = false; @@ -170,8 +173,8 @@ struct NonPromptCascadeTask { using TracksExtData = soa::Join; using TracksExtMC = soa::Join; - using CollisionCandidatesRun3 = soa::Join; - using CollisionCandidatesRun3MC = soa::Join; + using CollisionCandidatesRun3 = soa::Join; + using CollisionCandidatesRun3MC = soa::Join; Preslice perCollision = aod::track::collisionId; Preslice perCollisionMC = aod::track::collisionId; @@ -192,6 +195,7 @@ struct NonPromptCascadeTask { Configurable cfgMinCosPA{"cfgMinCosPA", -1.f, "Minimum cosine of pointing angle"}; Configurable> cfgCutsPID{"particlesCutsPID", {cutsPID[0], nParticles, nCutsPID, particlesNames, cutsNames}, "Nuclei PID selections"}; Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", true, "Skimmed dataset processing"}; + Configurable cfgTriggersOfInterest{"cfgTriggersOfInterest", "fTrackedOmega,fOmegaHighMult", "Triggers of interest, comma separated for Zorro"}; Zorro mZorro; OutputObj mZorroSummary{"ZorroSummary"}; @@ -290,7 +294,7 @@ struct NonPromptCascadeTask { for (const auto& coll : collisions) { auto bc = coll.template bc_as(); if (runNumber != bc.runNumber()) { - mZorro.initCCDB(mCCDB.service, bc.runNumber(), bc.timestamp(), "fTrackedOmega"); + mZorro.initCCDB(mCCDB.service, bc.runNumber(), bc.timestamp(), cfgTriggersOfInterest.value); mZorro.populateHistRegistry(mRegistry, bc.runNumber()); runNumber = bc.runNumber(); } @@ -298,7 +302,6 @@ struct NonPromptCascadeTask { } } } - template void fillCandidatesVector(CollisionType const&, TrackType const& tracks, auto const& cascades, auto& candidates) { @@ -514,7 +517,7 @@ struct NonPromptCascadeTask { cascITSclusters, protonTrack.itsNCls(), pionTrack.itsNCls(), bachelor.itsNCls(), protonTrack.tpcNClsFound(), pionTrack.tpcNClsFound(), bachelor.tpcNClsFound(), protonTrack.tpcNSigmaPr(), pionTrack.tpcNSigmaPi(), bachelor.tpcNSigmaKa(), bachelor.tpcNSigmaPi(), protonTrack.hasTOF(), pionTrack.hasTOF(), bachelor.hasTOF(), - protonTrack.tofNSigmaPr(), pionTrack.tofNSigmaPi(), bachelor.tofNSigmaKa(), bachelor.tofNSigmaPi(), collision.sel8(), collision.multFT0C(), collision.multFT0A()}); + protonTrack.tofNSigmaPr(), pionTrack.tofNSigmaPi(), bachelor.tofNSigmaKa(), bachelor.tofNSigmaPi(), collision.sel8(), collision.multFT0C(), collision.multFT0A(), collision.multFT0M(), collision.centFT0C(), collision.centFT0A(), collision.centFT0M()}); } } @@ -534,7 +537,7 @@ struct NonPromptCascadeTask { c.protonTPCNSigma, c.pionTPCNSigma, c.bachKaonTPCNSigma, c.bachPionTPCNSigma, c.protonHasTOF, c.pionHasTOF, c.bachHasTOF, c.protonTOFNSigma, c.pionTOFNSigma, c.bachKaonTOFNSigma, c.bachPionTOFNSigma, - c.sel8, c.multFT0C, c.multFT0A); + c.sel8, c.multFT0C, c.multFT0A, c.multFT0M, c.centFT0C, c.centFT0A, c.centFT0M); } } @@ -570,7 +573,7 @@ struct NonPromptCascadeTask { c.cascNClusITS, c.protonNClusITS, c.pionNClusITS, c.bachNClusITS, c.protonNClusTPC, c.pionNClusTPC, c.bachNClusTPC, c.protonTPCNSigma, c.pionTPCNSigma, c.bachKaonTPCNSigma, c.bachPionTPCNSigma, c.protonHasTOF, c.pionHasTOF, c.bachHasTOF, c.protonTOFNSigma, c.pionTOFNSigma, c.bachKaonTOFNSigma, c.bachPionTOFNSigma, - c.sel8, c.multFT0C, c.multFT0A, + c.sel8, c.multFT0C, c.multFT0A, c.multFT0M, c.centFT0C, c.centFT0A, c.centFT0M, particle.pt(), particle.eta(), particle.phi(), mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), particle.pdgCode(), mcCollision.posX() - particle.vx(), mcCollision.posY() - particle.vy(), mcCollision.posZ() - particle.vz(), mcCollision.globalIndex() == recCollision.mcCollisionId(), c.hasFakeReassociation, motherDecayDaughters); diff --git a/PWGLF/Utils/svPoolCreator.h b/PWGLF/Utils/svPoolCreator.h index 2414eb7e19b..25da298fe34 100644 --- a/PWGLF/Utils/svPoolCreator.h +++ b/PWGLF/Utils/svPoolCreator.h @@ -73,20 +73,20 @@ class svPoolCreator o2::vertexing::DCAFitterN<2>* getFitter() { return &fitter; } std::array, 4> getTrackCandPool() { return trackCandPool; } - template - void fillBC2Coll(const C& collisions, aod::BCsWithTimestamps const&) + template + void fillBC2Coll(const C& collisions, BC const&) { for (unsigned i = 0; i < collisions.size(); i++) { auto collision = collisions.rawIteratorAt(i); if (!collision.has_bc()) { continue; } - bc2Coll[collision.template bc_as().globalBC()] = i; + bc2Coll[collision.template bc_as().globalBC()] = i; } } - template - void appendTrackCand(const T& trackCand, const C& collisions, int pdgHypo, o2::aod::AmbiguousTracks const& ambiTracks, aod::BCsWithTimestamps const&) + template + void appendTrackCand(const T& trackCand, const C& collisions, int pdgHypo, o2::aod::AmbiguousTracks const& ambiTracks, BC const&) { if (pdgHypo != track0Pdg && pdgHypo != track1Pdg) { LOG(debug) << "Wrong pdg hypothesis"; @@ -97,18 +97,18 @@ class svPoolCreator uint64_t globalBC = BcInvalid; if (trackCand.has_collision()) { if (trackCand.template collision_as().has_bc()) { - globalBC = trackCand.template collision_as().template bc_as().globalBC(); + globalBC = trackCand.template collision_as().template bc_as().globalBC(); } } else if (!skipAmbiTracks) { for (const auto& ambTrack : ambiTracks) { if (ambTrack.trackId() != trackCand.globalIndex()) { continue; } - if (!ambTrack.has_bc() || ambTrack.bc_as().size() == 0) { + if (!ambTrack.has_bc() || ambTrack.bc_as().size() == 0) { globalBC = BcInvalid; break; } - globalBC = ambTrack.bc_as().begin().globalBC(); + globalBC = ambTrack.bc_as().begin().globalBC(); break; } } else { @@ -134,7 +134,7 @@ class svPoolCreator const auto& collision = collisions.rawIteratorAt(i); float collTime = collision.collisionTime(); float collTimeRes2 = collision.collisionTimeRes() * collision.collisionTimeRes(); - uint64_t collBC = collision.template bc_as().globalBC(); + uint64_t collBC = collision.template bc_as().globalBC(); int collIdx = collision.globalIndex(); int64_t bcOffset = globalBC - static_cast(collBC); if (static_cast(std::abs(bcOffset)) > bOffsetMax) { diff --git a/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx b/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx index 995e04a8335..eb16b83f315 100644 --- a/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx +++ b/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx @@ -47,9 +47,21 @@ namespace tree DECLARE_SOA_COLUMN(PtSideA, ptSideA, std::vector); DECLARE_SOA_COLUMN(RapSideA, rapSideA, std::vector); DECLARE_SOA_COLUMN(PhiSideA, phiSideA, std::vector); +DECLARE_SOA_COLUMN(TPCSignalSideA, tpcSignalSideA, std::vector); +DECLARE_SOA_COLUMN(TOFSignalSideA, tofSignalSideA, std::vector); +DECLARE_SOA_COLUMN(TPCNSigmaPiSideA, tpcNSigmaPiSideA, std::vector); +DECLARE_SOA_COLUMN(TOFNSigmaPiSideA, tofNSigmaPiSideA, std::vector); +DECLARE_SOA_COLUMN(TPCNSigmaKaSideA, tpcNSigmaKaSideA, std::vector); +DECLARE_SOA_COLUMN(TOFNSigmaKaSideA, tofNSigmaKaSideA, std::vector); DECLARE_SOA_COLUMN(PtSideC, ptSideC, std::vector); DECLARE_SOA_COLUMN(RapSideC, rapSideC, std::vector); DECLARE_SOA_COLUMN(PhiSideC, phiSideC, std::vector); +DECLARE_SOA_COLUMN(TPCSignalSideC, tpcSignalSideC, std::vector); +DECLARE_SOA_COLUMN(TOFSignalSideC, tofSignalSideC, std::vector); +DECLARE_SOA_COLUMN(TPCNSigmaPiSideC, tpcNSigmaPiSideC, std::vector); +DECLARE_SOA_COLUMN(TOFNSigmaPiSideC, tofNSigmaPiSideC, std::vector); +DECLARE_SOA_COLUMN(TPCNSigmaKaSideC, tpcNSigmaKaSideC, std::vector); +DECLARE_SOA_COLUMN(TOFNSigmaKaSideC, tofNSigmaKaSideC, std::vector); DECLARE_SOA_COLUMN(NchSideA, nchSideA, int); DECLARE_SOA_COLUMN(MultiplicitySideA, multiplicitySideA, int); DECLARE_SOA_COLUMN(NchSideC, nchSideC, int); @@ -59,9 +71,21 @@ DECLARE_SOA_TABLE(TREE, "AOD", "Tree", tree::PtSideA, tree::RapSideA, tree::PhiSideA, + tree::TPCSignalSideA, + tree::TOFSignalSideA, + tree::TPCNSigmaPiSideA, + tree::TOFNSigmaPiSideA, + tree::TPCNSigmaKaSideA, + tree::TOFNSigmaKaSideA, tree::PtSideC, tree::RapSideC, tree::PhiSideC, + tree::TPCSignalSideC, + tree::TOFSignalSideC, + tree::TPCNSigmaPiSideC, + tree::TOFNSigmaPiSideC, + tree::TPCNSigmaKaSideC, + tree::TOFNSigmaKaSideC, tree::NchSideA, tree::MultiplicitySideA, tree::NchSideC, @@ -76,6 +100,7 @@ struct upcPhotonuclearAnalysisJMG { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; // Declare configurables on events/collisions + Configurable nEvenstMixed{"nEvenstMixed", 3, {"Events to be Mixed"}}; Configurable myZVtxCut{"myZVtxCut", 10., {"My collision cut"}}; Configurable myTimeZNACut{"myTimeZNACut", 2., {"My collision cut"}}; Configurable myTimeZNCCut{"myTimeZNCCut", 2., {"My collision cut"}}; @@ -127,11 +152,13 @@ struct upcPhotonuclearAnalysisJMG { Filter collisionZNTimeFilter = nabs(aod::udzdc::timeZNA) < myTimeZNACut && nabs(aod::udzdc::timeZNC) < myTimeZNCCut; using FullSGUDCollision = soa::Filtered>; - using FullUDTracks = soa::Join; + using FullUDTracks = soa::Join; // Output definitions - OutputObj same{"sameEvent"}; - OutputObj mixed{"mixedEvent"}; + OutputObj sameGapSideA{"sameEventGapSideA"}; + OutputObj mixedGapSideA{"mixedEventGapSideA"}; + OutputObj sameGapSideC{"sameEventGapSideC"}; + OutputObj mixedGapSideC{"mixedEventGapSideC"}; UPCPairCuts mPairCuts; bool doPairCuts = false; @@ -175,6 +202,7 @@ struct upcPhotonuclearAnalysisJMG { histos.add("Tracks/SGsideA/hTrackPhi", "#it{#phi} distribution; #it{#phi}; counts", kTH1F, {axisPhi}); histos.add("Tracks/SGsideA/hTrackEta", "#it{#eta} distribution; #it{#eta}; counts", kTH1F, {axisEta}); histos.add("Tracks/SGsideA/hTrackTPCSignnalP", "#it{TPC dE/dx vs p}; #it{p*charge}; #it{TPC dE/dx}", kTH2F, {axisP, axisTPCSignal}); + histos.add("Tracks/SGsideA/hTrackTOFSignnalP", "#it{TOF signal vs p}; #it{p*charge}; #it{TOF signal}", kTH2F, {axisP, axisTPCSignal}); histos.add("Tracks/SGsideA/hTrackITSNCls", "#it{N Clusters ITS} distribution; #it{N Clusters ITS}; counts", kTH1F, {axisNCls}); histos.add("Tracks/SGsideA/hTrackITSChi2NCls", "#it{N Clusters Chi2 ITS} distribution; #it{N Clusters Chi2 ITS}; counts", kTH1F, {axisChi2NCls}); histos.add("Tracks/SGsideA/hTrackNClsCrossedRowsOverNClsFindable", "#it{NClsCrossedRows/FindableNCls} distribution in TPC; #it{NClsCrossedRows/FindableNCls}; counts", kTH1F, {axisTPCNClsCrossedRowsMin}); @@ -205,6 +233,7 @@ struct upcPhotonuclearAnalysisJMG { histos.add("Tracks/SGsideC/hTrackPhi", "#it{#phi} distribution; #it{#phi}; counts", kTH1F, {axisPhi}); histos.add("Tracks/SGsideC/hTrackEta", "#it{#eta} distribution; #it{#eta}; counts", kTH1F, {axisEta}); histos.add("Tracks/SGsideC/hTrackTPCSignnalP", "#it{TPC dE/dx vs p}; #it{p*charge}; #it{TPC dE/dx}", kTH2F, {axisP, axisTPCSignal}); + histos.add("Tracks/SGsideC/hTrackTOFSignnalP", "#it{TOF signal vs p}; #it{p*charge}; #it{TOF signal}", kTH2F, {axisP, axisTPCSignal}); histos.add("Tracks/SGsideC/hTrackITSNCls", "#it{N Clusters ITS} distribution; #it{N Clusters ITS}; counts", kTH1F, {axisNCls}); histos.add("Tracks/SGsideC/hTrackITSChi2NCls", "#it{N Clusters Chi2 ITS} distribution; #it{N Clusters Chi2 ITS}; counts", kTH1F, {axisChi2NCls}); histos.add("Tracks/SGsideC/hTrackNClsCrossedRowsOverNClsFindable", "#it{NClsCrossedRows/FindableNCls} distribution in TPC; #it{NClsCrossedRows/FindableNCls}; counts", kTH1F, {axisTPCNClsCrossedRowsMin}); @@ -240,18 +269,22 @@ struct upcPhotonuclearAnalysisJMG { {axisEtaEfficiency, "#eta"}, {axisPtEfficiency, "p_{T} (GeV/c)"}, {axisVertexEfficiency, "z-vtx (cm)"}}; - same.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); - mixed.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + sameGapSideA.setObject(new CorrelationContainer("sameEventGapSideA", "sameEventGapSideA", corrAxis, effAxis, {})); + mixedGapSideA.setObject(new CorrelationContainer("mixedEventGapSideA", "mixedEventGapSideA", corrAxis, effAxis, {})); + sameGapSideC.setObject(new CorrelationContainer("sameEventGapSideC", "sameEventGapSideC", corrAxis, effAxis, {})); + mixedGapSideC.setObject(new CorrelationContainer("mixedEventGapSideC", "mixedEventGapSideC", corrAxis, effAxis, {})); } - std::vector vtxBinsEdges{VARIABLE_WIDTH, -10.0f, -7.0f, -5.0f, -2.0f, 0.0f, 2.0f, 5.0f, 7.0f, 10.0f}; - std::vector multBinsEdges{VARIABLE_WIDTH, 0.0f, 50.0f, 400.0f}; + std::vector vtxBinsEdges{VARIABLE_WIDTH, -10.0f, -5.0f, 0.0f, 5.0f, 10.0f}; + std::vector gapSideBinsEdges{VARIABLE_WIDTH, -0.5, 0.5, 1.5}; + SliceCache cache; // Binning only on PosZ without multiplicity - using BinningType = ColumnBinningPolicy; - BinningType bindingOnVtx{{vtxBinsEdges}, true}; - SameKindPair pairs{bindingOnVtx, 5, -1, &cache}; + // using BinningType = ColumnBinningPolicy; + using BinningType = ColumnBinningPolicy; + BinningType bindingOnVtx{{vtxBinsEdges, {gapSideBinsEdges}}, true}; + SameKindPair pairs{bindingOnVtx, nEvenstMixed, -1, &cache}; // ColumnBinningPolicy bindingOnVtx{{vtxBinsEdges, multBinsEdges}, true}; @@ -345,7 +378,7 @@ struct upcPhotonuclearAnalysisJMG { template void fillQAUD(const TTracks tracks) { - for (auto& track : tracks) { + for (const auto& track : tracks) { histos.fill(HIST("yields"), tracks.size(), track.pt(), eta(track.px(), track.py(), track.pz())); histos.fill(HIST("etaphi"), tracks.size(), eta(track.px(), track.py(), track.pz()), phi(track.px(), track.py())); } @@ -363,12 +396,12 @@ struct upcPhotonuclearAnalysisJMG { void fillCorrelationsUD(TTarget target, const TTracks tracks1, const TTracks tracks2, float multiplicity, float posZ) { multiplicity = tracks1.size(); - for (auto& track1 : tracks1) { + for (const auto& track1 : tracks1) { if (isTrackCut(track1) == false) { continue; } target->getTriggerHist()->Fill(CorrelationContainer::kCFStepReconstructed, track1.pt(), multiplicity, posZ, 1.0); - for (auto& track2 : tracks2) { + for (const auto& track2 : tracks2) { if (track1 == track2) { continue; } @@ -396,8 +429,9 @@ struct upcPhotonuclearAnalysisJMG { int sgSide = reconstructedCollision.gapSide(); int nTracksCharged = 0; float sumPt = 0; - std::vector vTrackPtSideA, vTrackEtaSideA, vTrackPhiSideA; - std::vector vTrackPtSideC, vTrackEtaSideC, vTrackPhiSideC; + std::vector vTrackPtSideA, vTrackEtaSideA, vTrackPhiSideA, vTrackTPCSignalSideA, vTrackTOFSignalSideA, vTrackTPCNSigmaPiSideA, vTrackTOFNSigmaPiSideA, vTrackTPCNSigmaKaSideA, vTrackTOFNSigmaKaSideA; + std::vector vTrackPtSideC, vTrackEtaSideC, vTrackPhiSideC, vTrackTPCSignalSideC, vTrackTOFSignalSideC, vTrackTPCNSigmaPiSideC, vTrackTOFNSigmaPiSideC, vTrackTPCNSigmaKaSideC, vTrackTOFNSigmaKaSideC; + int nTracksChargedSideA(-222), nTracksChargedSideC(-222); int multiplicitySideA(-222), multiplicitySideC(-222); @@ -416,7 +450,7 @@ struct upcPhotonuclearAnalysisJMG { histos.fill(HIST("Events/SGsideA/hZVtx"), reconstructedCollision.posZ()); histos.fill(HIST("Events/SGsideA/hAmplitudFT0A"), reconstructedCollision.totalFT0AmplitudeA()); histos.fill(HIST("Events/SGsideA/hAmplitudFT0C"), reconstructedCollision.totalFT0AmplitudeC()); - for (auto& track : reconstructedTracks) { + for (const auto& track : reconstructedTracks) { if (track.sign() == 1 || track.sign() == -1) { if (isTrackCut(track) == false) { continue; @@ -427,9 +461,16 @@ struct upcPhotonuclearAnalysisJMG { histos.fill(HIST("Tracks/SGsideA/hTrackPhi"), phi(track.px(), track.py())); histos.fill(HIST("Tracks/SGsideA/hTrackEta"), eta(track.px(), track.py(), track.pz())); histos.fill(HIST("Tracks/SGsideA/hTrackTPCSignnalP"), momentum(track.px(), track.py(), track.pz()) * track.sign(), track.tpcSignal()); + histos.fill(HIST("Tracks/SGsideA/hTrackTOFSignnalP"), momentum(track.px(), track.py(), track.pz()) * track.sign(), track.tofSignal()); vTrackPtSideA.push_back(track.pt()); vTrackEtaSideA.push_back(eta(track.px(), track.py(), track.pz())); vTrackPhiSideA.push_back(phi(track.px(), track.py())); + vTrackTPCSignalSideA.push_back(track.tpcSignal()); + vTrackTOFSignalSideA.push_back(track.tofSignal()); + vTrackTPCNSigmaPiSideA.push_back(track.tpcNSigmaPi()); + vTrackTOFNSigmaPiSideA.push_back(track.tofNSigmaPi()); + vTrackTPCNSigmaKaSideA.push_back(track.tpcNSigmaKa()); + vTrackTOFNSigmaKaSideA.push_back(track.tofNSigmaKa()); histos.fill(HIST("Tracks/SGsideA/hTrackITSNCls"), track.itsNCls()); histos.fill(HIST("Tracks/SGsideA/hTrackITSChi2NCls"), track.itsChi2NCl()); @@ -465,7 +506,7 @@ struct upcPhotonuclearAnalysisJMG { histos.fill(HIST("Events/SGsideC/hZVtx"), reconstructedCollision.posZ()); histos.fill(HIST("Events/SGsideC/hAmplitudFT0A"), reconstructedCollision.totalFT0AmplitudeA()); histos.fill(HIST("Events/SGsideC/hAmplitudFT0C"), reconstructedCollision.totalFT0AmplitudeC()); - for (auto& track : reconstructedTracks) { + for (const auto& track : reconstructedTracks) { if (track.sign() == 1 || track.sign() == -1) { if (isTrackCut(track) == false) { continue; @@ -476,9 +517,16 @@ struct upcPhotonuclearAnalysisJMG { histos.fill(HIST("Tracks/SGsideC/hTrackPhi"), phi(track.px(), track.py())); histos.fill(HIST("Tracks/SGsideC/hTrackEta"), eta(track.px(), track.py(), track.pz())); histos.fill(HIST("Tracks/SGsideC/hTrackTPCSignnalP"), momentum(track.px(), track.py(), track.pz()) * track.sign(), track.tpcSignal()); + histos.fill(HIST("Tracks/SGsideC/hTrackTOFSignnalP"), momentum(track.px(), track.py(), track.pz()) * track.sign(), track.tofSignal()); vTrackPtSideC.push_back(track.pt()); vTrackEtaSideC.push_back(eta(track.px(), track.py(), track.pz())); vTrackPhiSideC.push_back(phi(track.px(), track.py())); + vTrackTPCSignalSideC.push_back(track.tpcSignal()); + vTrackTOFSignalSideC.push_back(track.tofSignal()); + vTrackTPCNSigmaPiSideC.push_back(track.tpcNSigmaPi()); + vTrackTOFNSigmaPiSideC.push_back(track.tofNSigmaPi()); + vTrackTPCNSigmaKaSideC.push_back(track.tpcNSigmaKa()); + vTrackTOFNSigmaKaSideC.push_back(track.tofNSigmaKa()); histos.fill(HIST("Tracks/SGsideC/hTrackITSNCls"), track.itsNCls()); histos.fill(HIST("Tracks/SGsideC/hTrackITSChi2NCls"), track.itsChi2NCl()); @@ -504,7 +552,7 @@ struct upcPhotonuclearAnalysisJMG { return; break; } - tree(vTrackPtSideA, vTrackEtaSideA, vTrackPhiSideA, vTrackPtSideC, vTrackEtaSideC, vTrackPhiSideC, nTracksChargedSideA, multiplicitySideA, nTracksChargedSideC, multiplicitySideC); + tree(vTrackPtSideA, vTrackEtaSideA, vTrackPhiSideA, vTrackTPCSignalSideA, vTrackTOFSignalSideA, vTrackTPCNSigmaPiSideA, vTrackTOFNSigmaPiSideA, vTrackTPCNSigmaKaSideA, vTrackTOFNSigmaKaSideA, vTrackPtSideC, vTrackEtaSideC, vTrackPhiSideC, vTrackTPCSignalSideA, vTrackTOFSignalSideA, vTrackTPCNSigmaPiSideA, vTrackTOFNSigmaPiSideA, vTrackTPCNSigmaKaSideA, vTrackTOFNSigmaKaSideA, nTracksChargedSideA, multiplicitySideA, nTracksChargedSideC, multiplicitySideC); // nTracksChargedSideA = nTracksChargedSideC = multiplicitySideA = multiplicitySideC = 0; } PROCESS_SWITCH(upcPhotonuclearAnalysisJMG, processSG, "Process in UD tables", true); @@ -512,25 +560,32 @@ struct upcPhotonuclearAnalysisJMG { void processSame(FullSGUDCollision::iterator const& reconstructedCollision, FullUDTracks const& reconstructedTracks) { int sgSide = reconstructedCollision.gapSide(); + float multiplicity = 0; - float multiplicity = reconstructedTracks.size(); switch (sgSide) { case 0: // gap for side A if (isCollisionCutSG(reconstructedCollision, 0) == false) { return; } - if (fillCollisionUD(same, multiplicity) == false) { + multiplicity = reconstructedTracks.size(); + if (fillCollisionUD(sameGapSideA, multiplicity) == false) { return; } - LOGF(info, "Filling same events"); + // LOGF(debug, "Filling sameGapSideA events"); histos.fill(HIST("eventcount"), -2); fillQAUD(reconstructedTracks); - fillCorrelationsUD(same, reconstructedTracks, reconstructedTracks, multiplicity, reconstructedCollision.posZ()); + fillCorrelationsUD(sameGapSideA, reconstructedTracks, reconstructedTracks, multiplicity, reconstructedCollision.posZ()); break; case 1: // gap for side C - // if (isCollisionCutSG(reconstructedCollision, 1) == false) { - // return; - // } + if (isCollisionCutSG(reconstructedCollision, 1) == false) { + return; + } + multiplicity = reconstructedTracks.size(); + if (fillCollisionUD(sameGapSideC, multiplicity) == false) { + return; + } + // LOGF(debug, "Filling sameGapSideC events"); + fillCorrelationsUD(sameGapSideC, reconstructedTracks, reconstructedTracks, multiplicity, reconstructedCollision.posZ()); break; default: return; @@ -542,37 +597,45 @@ struct upcPhotonuclearAnalysisJMG { void processMixed(FullSGUDCollision::iterator const& reconstructedCollision) { - int sgSide = reconstructedCollision.gapSide(); + (void)reconstructedCollision; + // int sgSide = reconstructedCollision.gapSide(); // int sgSide = 0; - for (auto& [collision1, tracks1, collision2, tracks2] : pairs) { + for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { if (collision1.size() == 0 || collision2.size() == 0) { - LOGF(info, "One or both collisions are empty."); + // LOGF(debug, "One or both collisions are empty."); continue; } - float multiplicity = tracks1.size(); - LOGF(info, "Filling mixed events"); - switch (sgSide) { - case 0: // gap for side A - if (isCollisionCutSG(reconstructedCollision, 0) == false) { - return; - } - if (fillCollisionUD(mixed, multiplicity) == false) { - return; - } - // LOGF(info, ">>> Bin of collision: ", bindingOnVtx.getBin({collision1.posZ()})); - // histos.fill(HIST("eventcount"), bindingOnVtx.getBin({collision1.posZ(), collision1.totalFT0AmplitudeC()})); - histos.fill(HIST("eventcount"), bindingOnVtx.getBin({collision1.posZ()})); - fillCorrelationsUD(mixed, tracks1, tracks2, multiplicity, collision1.posZ()); - break; - case 1: // gap for side C - // if (isCollisionCutSG(reconstructedCollision, 1) == false) { - // return; - // } - break; - default: + + float multiplicity = 0; + if (collision1.gapSide() == 0 && collision2.gapSide() == 0) { // gap on side A + if (isCollisionCutSG(collision1, 0) == false && isCollisionCutSG(collision2, 0) == false) { + continue; + } + // LOGF(debug, "In the pairs loop, gap side A"); + multiplicity = tracks1.size(); + if (fillCollisionUD(mixedGapSideA, multiplicity) == false) { return; - break; + } + // histos.fill(HIST("eventcount"), bindingOnVtx.getBin({collision1.posZ()})); + histos.fill(HIST("eventcount"), bindingOnVtx.getBin({collision1.posZ(), collision1.gapSide()})); + fillCorrelationsUD(mixedGapSideA, tracks1, tracks2, multiplicity, collision1.posZ()); + // LOGF(debug, "Filling mixedGapSideA events, Gap for side A"); + } + + if (collision1.gapSide() == 1 && collision2.gapSide() == 1) { // gap on side C + if (isCollisionCutSG(collision1, 1) == false && isCollisionCutSG(collision2, 1) == false) { + continue; + } + // LOGF(debug, "In the pairs loop, gap side C"); + multiplicity = tracks1.size(); + if (fillCollisionUD(mixedGapSideC, multiplicity) == false) { + return; + } + fillCorrelationsUD(mixedGapSideC, tracks1, tracks2, multiplicity, collision1.posZ()); + // LOGF(debug, "Filling mixedGapSideC events, Gap for side C"); + } else { + continue; } } }