Skip to content

Commit 542ba37

Browse files
authored
Option to provide marker/color per histo in residuals plot (#15921)
1 parent d3b4ba2 commit 542ba37

3 files changed

Lines changed: 109 additions & 6 deletions

File tree

‎Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/CheckResidConfig.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ struct CheckResidConfig : o2::conf::ConfigurableParamHelper<CheckResidConfig> {
5858
//
5959
// string with existing histomanagers files to draw (comma or semicolon separated) and optional legends
6060
std::string ext_hm_list{};
61+
std::string ext_marker_list{};
62+
std::string ext_color_list{};
6163
std::string ext_leg_list{};
6264

6365
O2ParamDef(CheckResidConfig, "checkresid");

‎Detectors/GlobalTrackingWorkflow/study/src/CheckResidSpec.cxx‎

Lines changed: 105 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@
1212
#include "GlobalTrackingStudy/CheckResidSpec.h"
1313
#include "GlobalTrackingStudy/CheckResidTypes.h"
1414
#include "GlobalTrackingStudy/CheckResidConfig.h"
15+
#include <algorithm>
16+
#include <array>
17+
#include <charconv>
18+
#include <cctype>
19+
#include <limits>
20+
#include <optional>
21+
#include <string_view>
22+
#include <utility>
1523
#include <vector>
1624
#include "ReconstructionDataFormats/Track.h"
1725
#include <TStopwatch.h>
@@ -144,7 +152,7 @@ void CheckResidSpec::init(InitContext& ic)
144152
bookHistos();
145153
}
146154
if (!params.ext_hm_list.empty()) {
147-
auto vecNames = o2::utils::Str::tokenize(params.ext_hm_list, ',');
155+
auto vecNames = o2::utils::Str::tokenize(params.ext_hm_list, ",;");
148156
auto vecLegends = o2::utils::Str::tokenize(params.ext_leg_list, ',');
149157
bool useLeg = true;
150158
if (vecNames.size() != vecLegends.size()) {
@@ -809,8 +817,99 @@ void CheckResidSpec::drawHistos()
809817
gStyle->SetTitleY(0.88);
810818
gStyle->SetTitleW(0.25);
811819
gStyle->SetOptStat(0);
820+
const auto& params = o2::checkresid::CheckResidConfig::Instance();
812821
int nhm = mHManV.size();
813822
std::array<unsigned int, 3> hcol{EColor::kRed, EColor::kBlue, EColor::kGreen + 2};
823+
const auto hmNames = o2::utils::Str::tokenize(params.ext_hm_list, ",;");
824+
const auto colorNames = o2::utils::Str::tokenize(params.ext_color_list, ",;");
825+
const auto markerIDs = o2::utils::Str::tokenize(params.ext_marker_list, ",;");
826+
bool useColors = colorNames.size() == hmNames.size() && !colorNames.empty();
827+
bool useMarkers = markerIDs.size() == hmNames.size() && !markerIDs.empty();
828+
if (!useColors) {
829+
LOGP(warn, "{} color names provided for {} external histomanagers, will use automatic colors", colorNames.size(), hmNames.size());
830+
}
831+
if (!useMarkers) {
832+
LOGP(warn, "{} marker IDs provided for {} external histomanagers, will use automatic markers", markerIDs.size(), hmNames.size());
833+
}
834+
constexpr std::array<std::pair<std::string_view, int>, 15> rootColors{{
835+
{"kWhite", EColor::kWhite},
836+
{"kBlack", EColor::kBlack},
837+
{"kGray", EColor::kGray},
838+
{"kRed", EColor::kRed},
839+
{"kGreen", EColor::kGreen},
840+
{"kBlue", EColor::kBlue},
841+
{"kYellow", EColor::kYellow},
842+
{"kMagenta", EColor::kMagenta},
843+
{"kCyan", EColor::kCyan},
844+
{"kOrange", EColor::kOrange},
845+
{"kSpring", EColor::kSpring},
846+
{"kTeal", EColor::kTeal},
847+
{"kAzure", EColor::kAzure},
848+
{"kViolet", EColor::kViolet},
849+
{"kPink", EColor::kPink},
850+
}};
851+
auto parseColor = [&rootColors](const std::string& token) -> std::optional<int> {
852+
std::string normalized;
853+
normalized.reserve(token.size());
854+
for (unsigned char ch : token) {
855+
if (!std::isspace(ch)) {
856+
normalized.push_back(ch);
857+
}
858+
}
859+
for (const auto& [name, value] : rootColors) {
860+
if (normalized.compare(0, name.size(), name) != 0) {
861+
continue;
862+
}
863+
const auto increment = std::string_view(normalized).substr(name.size());
864+
if (increment.empty()) {
865+
return value;
866+
}
867+
if (increment.size() < 2 || (increment.front() != '+' && increment.front() != '-')) {
868+
return std::nullopt;
869+
}
870+
int offset = 0;
871+
const auto* begin = increment.data() + 1;
872+
const auto* end = increment.data() + increment.size();
873+
auto [parsedEnd, error] = std::from_chars(begin, end, offset);
874+
if (error != std::errc{} || parsedEnd != end) {
875+
return std::nullopt;
876+
}
877+
const auto signedOffset = increment.front() == '-' ? -static_cast<long long>(offset) : static_cast<long long>(offset);
878+
const auto color = static_cast<long long>(value) + signedOffset;
879+
if (color < std::numeric_limits<int>::min() || color > std::numeric_limits<int>::max()) {
880+
return std::nullopt;
881+
}
882+
return static_cast<int>(color);
883+
}
884+
return std::nullopt;
885+
};
886+
std::vector<int> colors;
887+
if (useColors) {
888+
for (const auto& colorName : colorNames) {
889+
auto color = parseColor(colorName);
890+
if (!color) {
891+
LOGP(warn, "Unrecognized EColor name '{}', will use automatic colors", colorName);
892+
useColors = false;
893+
break;
894+
}
895+
colors.push_back(*color);
896+
}
897+
}
898+
std::vector<int> markers;
899+
if (useMarkers) {
900+
for (const auto& markerID : markerIDs) {
901+
int marker = 0;
902+
const auto* begin = markerID.data();
903+
const auto* end = begin + markerID.size();
904+
auto [parsedEnd, error] = std::from_chars(begin, end, marker);
905+
if (error != std::errc{} || parsedEnd != end) {
906+
LOGP(warn, "Unrecognized marker ID '{}', will use automatic markers", markerID);
907+
useMarkers = false;
908+
break;
909+
}
910+
markers.push_back(marker);
911+
}
912+
}
814913
std::unique_ptr<TLegend> lg;
815914
lg = std::make_unique<TLegend>(0.12, 0.13, 0.9, 0.13 + std::min(0.5f, nhm * 0.2f / 3.f));
816915
lg->SetFillStyle(0);
@@ -820,15 +919,15 @@ void CheckResidSpec::drawHistos()
820919
if (!hman || hman->GetLast() < 1) {
821920
continue;
822921
}
823-
hman->setMarkerStyle(20 + i + (i % 2) * 4, 0.5);
824-
hman->setColor(hcol[i % hcol.size()]);
922+
const int marker = useMarkers ? markers[i] : 20 + i + (i % 2) * 4;
923+
const int color = useColors ? colors[i] : hcol[i % hcol.size()];
924+
hman->setMarkerStyle(marker, 0.5);
925+
hman->setColor(color);
825926
auto le = lg->AddEntry(hman->getHisto(1), hman->GetName(), "lp");
826-
le->SetTextColor(hcol[i % hcol.size()]);
927+
le->SetTextColor(color);
827928
}
828929
TCanvas cly("cly", "", 600, 800), clz("clz", "", 600, 800), clpar("clpar", "", 600, 800);
829930
TCanvas czly("czly", "", 600, 800), czlz("czlz", "", 600, 800), czlpar("czlpar", "", 600, 800);
830-
const auto& params = o2::checkresid::CheckResidConfig::Instance();
831-
832931
auto AddLabel = [](const char* txt, float x = 0.1, float y = 0.9, int color = kBlack, float size = 0.04) {
833932
TLatex* lt = new TLatex(x, y, txt);
834933
lt->SetNDC();

‎Detectors/GlobalTrackingWorkflow/study/src/check-resid-workflow.cxx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext)
6464
GID::mask_t allowedSourcesClus = GID::getSourcesMask("ITS");
6565

6666
// Update the (declared) parameters if changed from the command line
67+
const std::string PVDef = "pvertexer.useMeanVertexConstraint=false;pvertexer.meanVertexExtraErrSelection=0.2;pvertexer.iniScale2=100;pvertexer.acceptableScale2=10.;pvertexer.useTimeInChi2=false;";
68+
o2::conf::ConfigurableParam::updateFromString(PVDef); // first set proper defaults of PV refitting, the CL options will override them if provided
6769
o2::conf::ConfigurableParam::updateFromString(configcontext.options().get<std::string>("configKeyValues"));
6870

6971
GID::mask_t srcTrc = allowedSourcesTrc & GID::getSourcesMask(configcontext.options().get<std::string>("track-sources"));

0 commit comments

Comments
 (0)