diff --git a/Detectors/TPC/base/include/TPCBase/Painter.h b/Detectors/TPC/base/include/TPCBase/Painter.h index 976fe2846ce0c..5cf8691635b1f 100644 --- a/Detectors/TPC/base/include/TPCBase/Painter.h +++ b/Detectors/TPC/base/include/TPCBase/Painter.h @@ -53,7 +53,8 @@ struct painter { enum class Type : int { Pad, ///< drawing pads Stack, ///< drawing stacks - FEC ///< drawing of FECs + FEC, ///< drawing of FECs + SCD, ///< drawing of FECs }; static std::array colors; @@ -87,8 +88,10 @@ struct painter { /// create a vector of FEC corner coordinates for one full sector static std::vector getFECCoordinatesSector(); + static std::vector getSCDY2XCoordinatesSector(std::string binningStr); + /// \return returns coordinates for given type - static std::vector getCoordinates(const Type type); + static std::vector getCoordinates(const Type type, std::string binningStr = ""); /// binning vector with radial pad-row positions (in cm) /// \param roc roc number (0-35 IROC, 36-71 OROC, >=72 full sector) @@ -143,11 +146,11 @@ struct painter { /// \param yMin minimum y coordinate of the histogram /// \param yMax maximum y coordinate of the histogram /// \param type granularity of the histogram (per pad or per stack) - static TH2Poly* makeSectorHist(const std::string_view name = "hSector", const std::string_view title = "Sector;local #it{x} (cm);local #it{y} (cm)", const float xMin = 83.65f, const float xMax = 247.7f, const float yMin = -43.7f, const float yMax = 43.7f, const Type type = Type::Pad); + static TH2Poly* makeSectorHist(const std::string_view name = "hSector", const std::string_view title = "Sector;local #it{x} (cm);local #it{y} (cm)", const float xMin = 83.65f, const float xMax = 247.7f, const float yMin = -43.7f, const float yMax = 43.7f, const Type type = Type::Pad, std::string binningStr = ""); /// make a side-wise histogram with correct pad corners /// \param type granularity of the histogram (per pad or per stack) - static TH2Poly* makeSideHist(Side side, const Type type = Type::Pad); + static TH2Poly* makeSideHist(Side side, const Type type = Type::Pad, std::string binningStr = ""); /// fill existing TH2Poly histogram for CalDet object /// \param h2D histogram to fill diff --git a/Detectors/TPC/base/src/Painter.cxx b/Detectors/TPC/base/src/Painter.cxx index 9f143d3fa45ce..ffbc149225212 100644 --- a/Detectors/TPC/base/src/Painter.cxx +++ b/Detectors/TPC/base/src/Painter.cxx @@ -31,7 +31,9 @@ #include "TPaveText.h" #include "TPaletteAxis.h" #include "TObjArray.h" +#include "TMath.h" +#include "Algorithm/RangeTokenizer.h" #include "CommonUtils/StringUtils.h" #include "DataFormatsTPC/Defs.h" #include "TPCBase/ROC.h" @@ -223,7 +225,77 @@ std::vector painter::getFECCoordinatesSector() return padCoords; } -std::vector painter::getCoordinates(const Type type) +std::vector painter::getSCDY2XCoordinatesSector(std::string binningStr) +{ + const float deadZone = 1.5; + const float secPhi = 20.0 * TMath::DegToRad(); + std::vector padCoords; + const Mapper& mapper = Mapper::instance(); + const auto nPadRows = Mapper::PADROWS; + std::vector maxY2X(nPadRows); + auto binCenters = o2::RangeTokenizer::tokenize(binningStr); + size_t nY2XBins = 20; + std::vector halfBinWidth; + + auto setUniformBinning = [&binCenters, &halfBinWidth](int nY2XBins) { + binCenters.resize(nY2XBins); + halfBinWidth.resize(nY2XBins); + for (int i = 0; i < nY2XBins; ++i) { + const auto binWidth = 2.f / nY2XBins; + halfBinWidth[i] = binWidth / 2.f; + binCenters[i] = -1.f + (i + 0.5f) * binWidth; + } + }; + + if (binCenters.size() == 0) { + LOGP(info, "Empty binning provided, will use default uniform y/x binning with {} bins", nY2XBins); + setUniformBinning(nY2XBins); + } else if (binCenters.size() == 1) { + nY2XBins = static_cast(binCenters.at(0)); + LOGP(info, "Setting uniform binning for y/x with {} bins", nY2XBins); + setUniformBinning(nY2XBins); + } else { + nY2XBins = binCenters.size() - 1; + if (std::abs(binCenters[0] + 1.f) > 1e-6 || std::abs(binCenters[nY2XBins] - 1.f) > 1e-6) { + LOG(error) << "Provided binning for y/x not in range -1 to 1: " << binCenters[0] << " - " << binCenters[nY2XBins] << ". Using default uniform binning with " << nY2XBins << " bins"; + setUniformBinning(nY2XBins); + } else { + LOGP(info, "Setting custom binning for y/x with {} bins", nY2XBins); + halfBinWidth.reserve(nY2XBins); + halfBinWidth.clear(); + for (int i = 0; i < nY2XBins; ++i) { + halfBinWidth.push_back(.5f * (binCenters[i + 1] - binCenters[i])); + binCenters[i] = .5f * (binCenters[i] + binCenters[i + 1]); + } + binCenters.resize(nY2XBins); + } + } + + for (int irow = 0; irow < nPadRows; ++irow) { + const auto x = mapper.getPadCentre(PadPos(irow, 0)).X(); + maxY2X[irow] = std::tan(.5f * secPhi) - deadZone / x; + const auto region = Mapper::REGION[irow]; + const auto ph = mapper.getPadRegionInfo(region).getPadHeight(); + const auto xPadBottom = x - ph / 2; + const auto xPadTop = x + ph / 2; + for (int iy2x = 0; iy2x < nY2XBins; ++iy2x) { + auto& padCoord = padCoords.emplace_back(); + float yPadRight = 0; + if (iy2x == 0) { + yPadRight = maxY2X[irow] * (binCenters[iy2x] - halfBinWidth[iy2x]); + } else { + yPadRight = maxY2X[irow] * (binCenters[iy2x - 1] + halfBinWidth[iy2x - 1]); + } + const auto yPadLeft = maxY2X[irow] * (binCenters[iy2x] + halfBinWidth[iy2x]); + padCoord.xVals = {xPadBottom, xPadTop, xPadTop, xPadBottom}; + padCoord.yVals = {yPadRight * xPadBottom, yPadRight * xPadTop, yPadLeft * xPadTop, yPadLeft * xPadBottom}; + } + } + + return padCoords; +} + +std::vector painter::getCoordinates(const Type type, std::string binningStr) { if (type == Type::Pad) { return painter::getPadCoordinatesSector(); @@ -231,6 +303,8 @@ std::vector painter::getCoordinates(const Type return painter::getStackCoordinatesSector(); } else if (type == Type::FEC) { return painter::getFECCoordinatesSector(); + } else if (type == Type::SCD) { + return painter::getSCDY2XCoordinatesSector(binningStr); } else { LOGP(warning, "Wrong Type provided!"); return std::vector(); @@ -291,6 +365,8 @@ TCanvas* painter::draw(const CalDet& calDet, int nbins1D, float xMin1D, float const Mapper& mapper = Mapper::instance(); + const bool draw1D = nbins1D > 0; + // ===| name and title |====================================================== std::string title = calDet.getName(); std::string name = calDet.getName(); @@ -305,11 +381,13 @@ 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("{0} (A-Side);{0}", title).data(), - nbins1D, xMin1D, xMax1D); // TODO: modify ranges + auto hAside1D = draw1D ? new TH1F(fmt::format("h_Aside_1D_{}", name).data(), fmt::format("{0} (A-Side);{0}", title).data(), + nbins1D, xMin1D, xMax1D) + : nullptr; // TODO: modify ranges - 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 hCside1D = draw1D ? new TH1F(fmt::format("h_Cside_1D_{}", name).data(), fmt::format("{0} (C-Side);{0}", title).data(), + nbins1D, xMin1D, xMax1D) + : nullptr; // TODO: modify ranges 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); @@ -336,7 +414,9 @@ TCanvas* painter::draw(const CalDet& calDet, int nbins1D, float xMin1D, float if (!hist2D->GetBinContent(bin)) { hist2D->SetBinContent(bin, double(val)); } - hist1D->Fill(double(val)); + if (draw1D) { + hist1D->Fill(double(val)); + } } } } @@ -352,13 +432,13 @@ TCanvas* painter::draw(const CalDet& calDet, int nbins1D, float xMin1D, float gStyle->SetOptStat("mr"); auto c = outputCanvas; if (!c) { - c = new TCanvas(fmt::format("c_{}", name).data(), title.data(), 1000, 1000); + c = new TCanvas(fmt::format("c_{}", name).data(), title.data(), 1000, draw1D ? 1000 : 500); } gStyle->SetStatX(1. - gPad->GetRightMargin()); gStyle->SetStatY(1. - gPad->GetTopMargin()); c->Clear(); - c->Divide(2, 2); + c->Divide(2, draw1D ? 2 : 1); c->cd(1); hAside2D->Draw("colz"); @@ -376,18 +456,22 @@ TCanvas* painter::draw(const CalDet& calDet, int nbins1D, float xMin1D, float adjustPalette(hCside2D, 0.92); drawSectorsXY(Side::C); - c->cd(3); - hAside1D->Draw(); + if (draw1D) { + c->cd(3); + hAside1D->Draw(); - c->cd(4); - hCside1D->Draw(); + c->cd(4); + hCside1D->Draw(); + + // associate histograms to canvas + hAside1D->SetBit(TObject::kCanDelete); + hCside1D->SetBit(TObject::kCanDelete); + } // 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); @@ -795,11 +879,11 @@ std::vector painter::makeSummaryCanvases(const std::string_view fileNa } //______________________________________________________________________________ -TH2Poly* painter::makeSectorHist(const std::string_view name, const std::string_view title, const float xMin, const float xMax, const float yMin, const float yMax, const Type type) +TH2Poly* painter::makeSectorHist(const std::string_view name, const std::string_view title, const float xMin, const float xMax, const float yMin, const float yMax, const Type type, std::string binningStr) { auto poly = new TH2Poly(name.data(), title.data(), xMin, xMax, yMin, yMax); - auto coords = painter::getCoordinates(type); + auto coords = painter::getCoordinates(type, binningStr); for (const auto& coord : coords) { poly->AddBin(coord.xVals.size(), coord.xVals.data(), coord.yVals.data()); } @@ -808,12 +892,12 @@ TH2Poly* painter::makeSectorHist(const std::string_view name, const std::string_ } //______________________________________________________________________________ -TH2Poly* painter::makeSideHist(Side side, const Type type) +TH2Poly* painter::makeSideHist(Side side, const Type type, std::string binningStr) { const auto s = (side == Side::A) ? "A" : "C"; auto poly = new TH2Poly(fmt::format("hSide_{}", s).data(), fmt::format("{}-Side;#it{{x}} (cm);#it{{y}} (cm)", s).data(), -270., 270., -270., 270.); - auto coords = painter::getCoordinates(type); + auto coords = painter::getCoordinates(type, binningStr); for (int isec = 0; isec < 18; ++isec) { const float angDeg = 10.f + isec * 20; for (auto coord : coords) { diff --git a/Detectors/TPC/dcs/macro/makeTPCCCDBEntryForDCS.C b/Detectors/TPC/dcs/macro/makeTPCCCDBEntryForDCS.C index edcb69907b3e5..d488aba14e264 100644 --- a/Detectors/TPC/dcs/macro/makeTPCCCDBEntryForDCS.C +++ b/Detectors/TPC/dcs/macro/makeTPCCCDBEntryForDCS.C @@ -14,6 +14,7 @@ #include #include "TFile.h" #include "CCDB/CcdbApi.h" +#include "CommonUtils/StringUtils.h" #include "DetectorsDCS/AliasExpander.h" #include "DetectorsDCS/DeliveryType.h" #include "DetectorsDCS/DataPointIdentifier.h" @@ -24,9 +25,10 @@ #include using DPID = o2::dcs::DataPointIdentifier; +using namespace o2::utils; /// macro to populate CCDB for TPC with the configuration for DCS -int makeTPCCCDBEntryForDCS(const std::string url = "http://localhost:8080") +int makeTPCCCDBEntryForDCS(const std::string url = "http://localhost:8080", std::string comment = "") { std::unordered_map dpid2DataDesc; @@ -64,9 +66,23 @@ int makeTPCCCDBEntryForDCS(const std::string url = "http://localhost:8080") o2::ccdb::CcdbApi api; api.init(url); // or http://localhost:8080 for a local installation - std::map md; + std::map meta; + + auto toKeyValPairs = [&meta](std::vector const& tokens) { + for (auto& token : tokens) { + auto keyval = Str::tokenize(token, '=', false); + if (keyval.size() != 2) { + LOG(error) << "Illegal command-line key/value string: " << token; + continue; + } + Str::trim(keyval[1]); + meta[keyval[0]] = keyval[1]; + } + }; + toKeyValPairs(Str::tokenize(comment, ';', true)); + long ts = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); - api.storeAsTFileAny(&dpid2DataDesc, "TPC/Config/DCSDPconfig", md, ts, 99999999999999); + api.storeAsTFileAny(&dpid2DataDesc, "TPC/Config/DCSDPconfig", meta, ts, 99999999999999); return 0; }