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 ();
0 commit comments