From 6e59d8c63870005850b9cb59c1759fe8ae2ae1c5 Mon Sep 17 00:00:00 2001 From: wiechula Date: Thu, 25 Apr 2024 15:39:54 +0200 Subject: [PATCH 1/4] Add calculation of mean values over all sectors --- .../DataFormatsTPC/CalibdEdxCorrection.h | 13 +++++ .../Detectors/TPC/src/CalibdEdxCorrection.cxx | 49 +++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/CalibdEdxCorrection.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/CalibdEdxCorrection.h index 4225faf8437c4..ace488b652559 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/CalibdEdxCorrection.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/CalibdEdxCorrection.h @@ -22,6 +22,7 @@ #ifndef GPUCA_GPUCODE_DEVICE #include #include +#include #endif // o2 includes @@ -96,6 +97,18 @@ class CalibdEdxCorrection /// \param outFileName name of the output file void dumpToTree(const char* outFileName = "calib_dedx.root") const; + /// Parameters averaged over all stacks + const std::array getMeanParams(ChargeType charge) const; + + /// Parameters averaged over all sectors for a stack type + const std::array getMeanParams(const GEMstack stack, ChargeType charge) const; + + /// Single fit parameters averaged over all sectors for a stack type + float getMeanParam(ChargeType charge, uint32_t param) const; + + /// Single fit parameters averaged over all sectors for a stack type + float getMeanParam(const GEMstack stack, ChargeType charge, uint32_t param) const; + #endif private: diff --git a/DataFormats/Detectors/TPC/src/CalibdEdxCorrection.cxx b/DataFormats/Detectors/TPC/src/CalibdEdxCorrection.cxx index b843577f1976a..28a44f15cf18c 100644 --- a/DataFormats/Detectors/TPC/src/CalibdEdxCorrection.cxx +++ b/DataFormats/Detectors/TPC/src/CalibdEdxCorrection.cxx @@ -11,6 +11,7 @@ #include "DataFormatsTPC/CalibdEdxCorrection.h" +#include #include // o2 includes @@ -86,3 +87,51 @@ void CalibdEdxCorrection::dumpToTree(const char* outFileName) const } } } + +const std::array CalibdEdxCorrection::getMeanParams(ChargeType charge) const +{ + std::array params{}; + + for (int index = 0; index < FitSize / 2; ++index) { + std::transform(params.begin(), params.end(), mParams[index + charge * FitSize / 2], params.begin(), std::plus<>()); + } + std::for_each(params.begin(), params.end(), [](auto& val) { val /= (0.5f * FitSize); }); + return params; +} + +const std::array CalibdEdxCorrection::getMeanParams(const GEMstack stack, ChargeType charge) const +{ + std::array params{}; + + for (int index = 0; index < SECTORSPERSIDE * SIDES; ++index) { + std::transform(params.begin(), params.end(), getParams(StackID{index, stack}, charge), params.begin(), std::plus<>()); + } + std::for_each(params.begin(), params.end(), [](auto& val) { val /= (SECTORSPERSIDE * SIDES); }); + return params; +} + +float CalibdEdxCorrection::getMeanParam(ChargeType charge, uint32_t param) const +{ + if (param >= ParamSize) { + return 0.f; + } + float mean{}; + for (int index = 0; index < FitSize / 2; ++index) { + mean += mParams[index + charge * FitSize / 2][param]; + } + + return mean / (0.5f * FitSize); +} + +float CalibdEdxCorrection::getMeanParam(const GEMstack stack, ChargeType charge, uint32_t param) const +{ + if (param >= ParamSize) { + return 0.f; + } + float mean{}; + for (int index = 0; index < SECTORSPERSIDE * SIDES; ++index) { + mean += getParams(StackID{index, stack}, charge)[param]; + } + + return mean / (SECTORSPERSIDE * SIDES); +} From 721b93883ff563557d335baad4bdbe1ec69a9738 Mon Sep 17 00:00:00 2001 From: wiechula Date: Thu, 25 Apr 2024 15:41:46 +0200 Subject: [PATCH 2/4] Add missing forward of template parameters, cleanup --- Detectors/TPC/base/include/TPCBase/CRUCalibHelpers.h | 4 ++-- Detectors/TPC/base/include/TPCBase/FEEConfig.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Detectors/TPC/base/include/TPCBase/CRUCalibHelpers.h b/Detectors/TPC/base/include/TPCBase/CRUCalibHelpers.h index d0a061a9776b6..464a5eb24d4f7 100644 --- a/Detectors/TPC/base/include/TPCBase/CRUCalibHelpers.h +++ b/Detectors/TPC/base/include/TPCBase/CRUCalibHelpers.h @@ -214,7 +214,7 @@ int fillCalPad(CalDet& calPad, gsl::span data) membuf sbuf((char*)data.data(), data.size()); std::istream in(&sbuf); - return fillCalPad(calPad, in); + return fillCalPad(calPad, in); } /// create cal pad object from HW value file @@ -237,7 +237,7 @@ o2::tpc::CalDet getCalPad(const std::string_view fileName, const std::str return calPad; } - fillCalPad(calPad, infile); + fillCalPad(calPad, infile); if (outputFile.size()) { TFile f(outputFile.data(), "recreate"); diff --git a/Detectors/TPC/base/include/TPCBase/FEEConfig.h b/Detectors/TPC/base/include/TPCBase/FEEConfig.h index ef495e9f219da..2065970c42ef5 100644 --- a/Detectors/TPC/base/include/TPCBase/FEEConfig.h +++ b/Detectors/TPC/base/include/TPCBase/FEEConfig.h @@ -21,7 +21,6 @@ #include #include #include -#include #include "Rtypes.h" From 54301c761ed33aed046cd63a6a3ae42f627e0e4b Mon Sep 17 00:00:00 2001 From: wiechula Date: Thu, 25 Apr 2024 15:42:49 +0200 Subject: [PATCH 3/4] Add summary canvases from pad tree dump, cosmetic fixes --- Detectors/TPC/base/include/TPCBase/Painter.h | 14 ++ Detectors/TPC/base/src/Painter.cxx | 159 ++++++++++++++++++- 2 files changed, 169 insertions(+), 4 deletions(-) diff --git a/Detectors/TPC/base/include/TPCBase/Painter.h b/Detectors/TPC/base/include/TPCBase/Painter.h index 565c07084e054..976fe2846ce0c 100644 --- a/Detectors/TPC/base/include/TPCBase/Painter.h +++ b/Detectors/TPC/base/include/TPCBase/Painter.h @@ -184,6 +184,20 @@ struct painter { /// \return TCanvas containing CalDet content static std::vector makeSummaryCanvases(const std::string_view fileName, const std::string_view calPadNames, int nbins1D = 300, float xMin1D = 0, float xMax1D = 0, bool onlyFilled = true); + /// Create summary canvases from pad calibration tree dumped via CalibTreeDump + /// + /// 1 Canvas with 2D and 1D distributions for each side + /// 1 Canvas with 2D distributions for all ROCs + /// 1 Canvas with 1D distributions for all ROCs + /// \param tree input calibTree + /// \param draw draw string to use for the variable (1D) + /// \param cut cut string to use (default 1 = no cut) + /// \param nbins1D number of bins used for the 1D projections, if negative, exclude per ROC histograms + /// \param xMin1D minimum value for 1D distribution (xMin = 0 and xMax = 0 for auto scaling) + /// \param xMax1D maximum value for 1D distribution (xMin = 0 and xMax = 0 for auto scaling) + /// \return TCanvas containing CalDet content + static std::vector makeSummaryCanvases(TTree& tree, const std::string_view draw, std::string_view cut = "1", int nbins1D = 300, float xMin1D = 0, float xMax1D = 0); + /// draw sector boundaris, side name and sector numbers static void drawSectorsXY(Side side, int sectorLineColor = 920, int sectorTextColor = 1); diff --git a/Detectors/TPC/base/src/Painter.cxx b/Detectors/TPC/base/src/Painter.cxx index 0f7b89b71e07a..863547a666611 100644 --- a/Detectors/TPC/base/src/Painter.cxx +++ b/Detectors/TPC/base/src/Painter.cxx @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -22,6 +23,7 @@ #include "TH2.h" #include "TH3.h" #include "TH2Poly.h" +#include "TProfile2D.h" #include "TCanvas.h" #include "TLine.h" #include "TLatex.h" @@ -303,16 +305,16 @@ TCanvas* painter::draw(const CalDet& calDet, int nbins1D, float xMin1D, float const int bufferSize = TH1::GetDefaultBufferSize(); TH1::SetDefaultBufferSize(Sector::MAXSECTOR * mapper.getPadsInSector()); - auto hAside1D = new TH1F(fmt::format("h_Aside_1D_{}", name).data(), fmt::format("{} (A-Side)", title).data(), + auto hAside1D = new TH1F(fmt::format("h_Aside_1D_{}", name).data(), fmt::format("{0} (A-Side);{0}", title).data(), nbins1D, xMin1D, xMax1D); // TODO: modify ranges - auto hCside1D = new TH1F(fmt::format("h_Cside_1D_{}", name).data(), fmt::format("{} (C-Side)", title).data(), + auto hCside1D = new TH1F(fmt::format("h_Cside_1D_{}", name).data(), fmt::format("{0} (C-Side);{0}", title).data(), nbins1D, xMin1D, xMax1D); // TODO: modify ranges - auto hAside2D = new TH2F(fmt::format("h_Aside_2D_{}", name).data(), fmt::format("{} (A-Side);#it{{x}} (cm);#it{{y}} (cm)", title).data(), + auto hAside2D = new TH2F(fmt::format("h_Aside_2D_{}", name).data(), fmt::format("{0} (A-Side);#it{{x}} (cm);#it{{y}} (cm);{0}", title).data(), 330, -270, 270, 330, -270, 270); - auto hCside2D = new TH2F(fmt::format("h_Cside_2D_{}", name).data(), fmt::format("{} (C-Side);#it{{x}} (cm);#it{{y}} (cm)", title).data(), + auto hCside2D = new TH2F(fmt::format("h_Cside_2D_{}", name).data(), fmt::format("{0} (C-Side);#it{{x}} (cm);#it{{y}} (cm);{0}", title).data(), 330, -270, 270, 330, -270, 270); for (ROC roc; !roc.looped(); ++roc) { @@ -363,6 +365,7 @@ TCanvas* painter::draw(const CalDet& calDet, int nbins1D, float xMin1D, float hAside2D->SetStats(0); hAside2D->SetTitleOffset(1.05, "XY"); hAside2D->SetTitleSize(0.05, "XY"); + adjustPalette(hAside2D, 0.92); drawSectorsXY(Side::A); c->cd(2); @@ -370,6 +373,7 @@ TCanvas* painter::draw(const CalDet& calDet, int nbins1D, float xMin1D, float hCside2D->SetStats(0); hCside2D->SetTitleOffset(1.05, "XY"); hCside2D->SetTitleSize(0.05, "XY"); + adjustPalette(hCside2D, 0.92); drawSectorsXY(Side::C); c->cd(3); @@ -613,6 +617,153 @@ std::vector painter::makeSummaryCanvases(const CalDet& calDet, int return vecCanvases; } +std::vector o2::tpc::painter::makeSummaryCanvases(TTree& tree, const std::string_view draw, std::string_view cut, int nbins1D, float xMin1D, float xMax1D) +{ + const Mapper& mapper = Mapper::instance(); + + std::vector vecCanvases; + + // ===| name and title |====================================================== + std::string title = draw.data(); + std::string name = title; + std::replace(name.begin(), name.end(), ' ', '_'); + std::replace(name.begin(), name.end(), '/', '_'); + const std::string_view calName = name; + + // ===| Per ROC histograms |=== + if (nbins1D > 0) { + const size_t nROCs = 72; + auto cROCs1D = new TCanvas(fmt::format("c_ROCs_{}_1D", calName).data(), fmt::format("{} values for each ROC", calName).data(), 1400, 1000); + auto cROCs2D = new TCanvas(fmt::format("c_ROCs_{}_2D", calName).data(), fmt::format("{} values for each ROC", calName).data(), 1400, 1000); + + cROCs1D->DivideSquare(nROCs); + cROCs2D->DivideSquare(nROCs); + + vecCanvases.emplace_back(cROCs1D); + vecCanvases.emplace_back(cROCs2D); + + // ===| produce plots for each ROC |=== + size_t pad = 1; + for (size_t iroc = 0; iroc < nROCs; ++iroc) { + + // ===| 1D histogram |=== + auto h1D = new TH1F(fmt::format("h1_{}_{:02d}", calName, iroc).data(), fmt::format("{} distribution ROC {:02d} ({});{}", calName, iroc, getROCTitle(iroc), draw).data(), nbins1D, xMin1D, xMax1D); + tree.Draw(fmt::format("{} >> {}", draw, h1D->GetName()).data(), fmt::format("(roc == {}) && ({})", iroc, cut).data(), "goff"); + + // ===| 2D histogram |=== + const int nrows = mapper.getNumberOfPadRows(PadSubset::ROC, iroc); + const int npads = mapper.getNumberOfPadsInRow(PadSubset::ROC, iroc, nrows - 1) + 6; + + // ===| create histogram |==================================================== + + const std::string rocTitle = title + fmt::format(" ({})", getROCTitle(iroc)); + + auto h2D = new TProfile2D(fmt::format("h_{}_ROC{}", name, iroc).data(), + fmt::format("{};pad row;pad;{}", rocTitle, draw).data(), + nrows, 0., nrows, + npads, -npads / 2., npads / 2.); + tree.Draw(fmt::format("{} : cpad : row >> {}", draw, h2D->GetName()).data(), fmt::format("(roc == {}) && ({})", iroc, cut).data(), "profcolzgoff"); + + h2D->SetStats(0); + if (xMax1D > xMin1D) { + h2D->SetMinimum(xMin1D); + h2D->SetMaximum(xMax1D); + } + h2D->SetUniqueID(iroc); + + cROCs1D->cd(pad); + h1D->Draw(); + + cROCs2D->cd(pad); + h2D->Draw("colz"); + + ++pad; + + // associate histograms to canvas + h1D->SetBit(TObject::kCanDelete); + h2D->SetBit(TObject::kCanDelete); + } + } + + // ===| Side histograms |===================================================== + + // ---| define histograms |--------------------------------------------------- + // TODO: auto scaling of ranges based on mean and variance? + // for the moment use roots auto scaling + + // set buffer size such that autoscaling uses the full range. This is about 2MB per histogram! + const int bufferSize = TH1::GetDefaultBufferSize(); + TH1::SetDefaultBufferSize(Sector::MAXSECTOR * mapper.getPadsInSector()); + + auto hAside1D = new TH1F(fmt::format("h_Aside_1D_{}", name).data(), fmt::format("{0} (A-Side);{0}", title).data(), + std::abs(nbins1D), xMin1D, xMax1D); // TODO: modify ranges + + auto hCside1D = new TH1F(fmt::format("h_Cside_1D_{}", name).data(), fmt::format("{0} (C-Side);{0}", title).data(), + std::abs(nbins1D), xMin1D, xMax1D); // TODO: modify ranges + + auto hAside2D = new TProfile2D(fmt::format("h_Aside_2D_{}", name).data(), fmt::format("{} (A-Side);#it{{x}} (cm);#it{{y}} (cm);{}", title, draw).data(), + 330, -270, 270, 330, -270, 270); + + auto hCside2D = new TProfile2D(fmt::format("h_Cside_2D_{}", name).data(), fmt::format("{} (C-Side);#it{{x}} (cm);#it{{y}} (cm);{}", title, draw).data(), + 330, -270, 270, 330, -270, 270); + + tree.Draw(fmt::format("{} >> {}", draw, hAside1D->GetName()).data(), fmt::format("(A_Side) && ({})", cut).data(), "goff"); + tree.Draw(fmt::format("{} >> {}", draw, hCside1D->GetName()).data(), fmt::format("(C_Side) && ({})", cut).data(), "goff"); + tree.Draw(fmt::format("{} : gy : gx >> {}", draw, hAside2D->GetName()).data(), fmt::format("(A_Side) && ({})", cut).data(), "profcolzgoff"); + tree.Draw(fmt::format("{} : gy : gx >> {}", draw, hCside2D->GetName()).data(), fmt::format("(C_Side) && ({})", cut).data(), "profcolzgoff"); + + if (xMax1D > xMin1D) { + hAside2D->SetMinimum(xMin1D); + hAside2D->SetMaximum(xMax1D); + hCside2D->SetMinimum(xMin1D); + hCside2D->SetMaximum(xMax1D); + } + + // ===| Draw histograms |===================================================== + gStyle->SetOptStat("mr"); + auto cSides = new TCanvas(fmt::format("c_{}", name).data(), title.data(), 1000, 1000); + vecCanvases.emplace_back(cSides); + + gStyle->SetStatX(1. - gPad->GetRightMargin()); + gStyle->SetStatY(1. - gPad->GetTopMargin()); + + cSides->Clear(); + cSides->Divide(2, 2); + + cSides->cd(1); + hAside2D->Draw("colz"); + hAside2D->SetStats(0); + hAside2D->SetTitleOffset(1.05, "XY"); + hAside2D->SetTitleSize(0.05, "XY"); + adjustPalette(hAside2D, 0.92); + drawSectorsXY(Side::A); + + cSides->cd(2); + hCside2D->Draw("colz"); + hCside2D->SetStats(0); + hCside2D->SetTitleOffset(1.05, "XY"); + hCside2D->SetTitleSize(0.05, "XY"); + adjustPalette(hCside2D, 0.92); + drawSectorsXY(Side::C); + + cSides->cd(3); + hAside1D->Draw(); + + cSides->cd(4); + hCside1D->Draw(); + + // reset the buffer size + TH1::SetDefaultBufferSize(bufferSize); + + // associate histograms to canvas + hAside1D->SetBit(TObject::kCanDelete); + hCside1D->SetBit(TObject::kCanDelete); + hAside2D->SetBit(TObject::kCanDelete); + hCside2D->SetBit(TObject::kCanDelete); + + return vecCanvases; +} + //______________________________________________________________________________ std::vector painter::makeSummaryCanvases(const std::string_view fileName, const std::string_view calPadNames, int nbins1D, float xMin1D, float xMax1D, bool onlyFilled) { From 4e353ed2e43f5ad4f34cc206c94a76ab0bac3ad5 Mon Sep 17 00:00:00 2001 From: wiechula Date: Thu, 25 Apr 2024 15:43:35 +0200 Subject: [PATCH 4/4] Possibility to load specific pedestal object for IDCs --- .../TPC/workflow/src/IDCToVectorSpec.cxx | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/Detectors/TPC/workflow/src/IDCToVectorSpec.cxx b/Detectors/TPC/workflow/src/IDCToVectorSpec.cxx index a1b77b2774228..27dbcf5d85bbf 100644 --- a/Detectors/TPC/workflow/src/IDCToVectorSpec.cxx +++ b/Detectors/TPC/workflow/src/IDCToVectorSpec.cxx @@ -80,31 +80,38 @@ class IDCToVectorDevice : public o2::framework::Task auto pedestalFile = ic.options().get("pedestal-url"); if (pedestalFile.length()) { - if (pedestalFile.find("ccdb") != std::string::npos) { - if (pedestalFile.find("-default") != std::string::npos) { - pedestalFile = o2::base::NameConf::getCCDBServer(); + auto& cdb = o2::ccdb::BasicCCDBManager::instance(); + long timeStamp = o2::ccdb::getCurrentTimestamp(); + const auto tsPos = pedestalFile.find("@"); + std::string pedestalURL = pedestalFile.substr(0, tsPos); + if (pedestalURL.find("ccdb") != std::string::npos) { + if (pedestalURL.find("-default") != std::string::npos) { + pedestalURL = o2::base::NameConf::getCCDBServer(); } - LOGP(info, "Loading pedestals from ccdb: {}", pedestalFile); - auto& cdb = o2::ccdb::BasicCCDBManager::instance(); - cdb.setURL(pedestalFile); + LOGP(info, "Loading pedestals from ccdb: {}", pedestalURL); + cdb.setURL(pedestalURL); if (cdb.isHostReachable()) { - auto pedestalNoise = cdb.get>("TPC/Calib/PedestalNoise"); + if (tsPos != std::string::npos) { + timeStamp = std::stol(pedestalFile.substr(tsPos + 1)); + LOGP(info, "Using custom time stamp {}", timeStamp); + } + auto pedestalNoise = cdb.getForTimeStamp>("TPC/Calib/PedestalNoise", timeStamp); try { if (!pedestalNoise) { throw std::runtime_error("Couldn't retrieve PedestaNoise map"); } mPedestal = std::make_unique(pedestalNoise->at("Pedestals")); } catch (const std::exception& e) { - LOGP(fatal, "could not load pedestals from {} ({}), required for IDC processing", pedestalFile, e.what()); + LOGP(fatal, "could not load pedestals from {} ({}), required for IDC processing", pedestalURL, e.what()); } } else { - LOGP(fatal, "ccdb access to {} requested, but host is not reachable. Cannot load pedestals, required for IDC processing", pedestalFile); + LOGP(fatal, "ccdb access to {} requested, but host is not reachable. Cannot load pedestals, required for IDC processing", pedestalURL); } } else { - LOGP(info, "Loading pedestals from file: {}", pedestalFile); - auto calPads = utils::readCalPads(pedestalFile, "Pedestals"); + LOGP(info, "Loading pedestals from file: {}", pedestalURL); + auto calPads = utils::readCalPads(pedestalURL, "Pedestals"); if (calPads.size() != 1) { - LOGP(fatal, "Pedestal could not be loaded from file {}, required for IDC processing", pedestalFile); + LOGP(fatal, "Pedestal could not be loaded from file {}, required for IDC processing", pedestalURL); } else { mPedestal.reset(calPads[0]); }