Skip to content

Commit 2a52154

Browse files
authored
Merge pull request cms-sw#43359 from mmusich/mm_dev_L1TMenuPayloadInspector_v2
add `L1TUtmTriggerMenu_PayloadInspector` and related unit tests
2 parents 3d38a1d + dd40f5a commit 2a52154

File tree

6 files changed

+509
-0
lines changed

6 files changed

+509
-0
lines changed
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
#ifndef CondCore_L1TPlugins_L1TUtmTriggerMenuPayloadInspectorHelper_H
2+
#define CondCore_L1TPlugins_L1TUtmTriggerMenuPayloadInspectorHelper_H
3+
4+
#include "TH1.h"
5+
#include "TH2.h"
6+
#include "TStyle.h"
7+
#include "TCanvas.h"
8+
#include "TLatex.h"
9+
#include "TLine.h"
10+
11+
#include "CondFormats/L1TObjects/interface/L1TUtmTriggerMenu.h"
12+
13+
namespace L1TUtmTriggerMenuInspectorHelper {
14+
15+
using l1tUtmAlgoMap = std::map<std::string, L1TUtmAlgorithm>;
16+
using l1tUtmConditionMap = std::map<std::string, L1TUtmCondition>;
17+
18+
class L1UtmTriggerMenuInfo {
19+
public:
20+
// constructor
21+
L1UtmTriggerMenuInfo(const L1TUtmTriggerMenu* l1utmMenu) { m_map = l1utmMenu->getAlgorithmMap(); }
22+
23+
// destructor
24+
~L1UtmTriggerMenuInfo() = default;
25+
26+
public:
27+
const std::vector<std::string> listOfAlgos() const {
28+
std::vector<std::string> output;
29+
std::transform(m_map.begin(),
30+
m_map.end(),
31+
std::back_inserter(output),
32+
[](const std::pair<std::string, L1TUtmAlgorithm>& pair) {
33+
return pair.first; // Extracting the string key using lambda
34+
});
35+
return output;
36+
}
37+
38+
//___________________________________________________________________
39+
const std::vector<std::string> listOfCommonAlgos(const L1TUtmTriggerMenu* other) const {
40+
const auto& otherMap = other->getAlgorithmMap();
41+
42+
std::vector<std::string> commonKeys;
43+
44+
// Lambda function to find common keys and store them in commonKeys vector
45+
std::for_each(
46+
m_map.begin(), m_map.end(), [&commonKeys, &otherMap](const std::pair<std::string, L1TUtmAlgorithm>& pair) {
47+
const std::string& key = pair.first;
48+
49+
// Check if the key exists in map2
50+
if (otherMap.find(key) != otherMap.end()) {
51+
commonKeys.push_back(key);
52+
}
53+
});
54+
return commonKeys;
55+
}
56+
57+
//___________________________________________________________________
58+
const std::vector<std::string> onlyInThis(const L1TUtmTriggerMenu* other) const {
59+
const auto& otherMap = other->getAlgorithmMap();
60+
61+
std::vector<std::string> stringsOnlyInFirstMap;
62+
63+
// Lambda function to extract only the strings present in m_map but not in otherMap
64+
std::for_each(m_map.begin(),
65+
m_map.end(),
66+
[&stringsOnlyInFirstMap, &otherMap](const std::pair<std::string, L1TUtmAlgorithm>& pair) {
67+
const std::string& key = pair.first;
68+
// Check if the key exists in otherMap
69+
if (otherMap.find(key) == otherMap.end()) {
70+
stringsOnlyInFirstMap.push_back(key); // Add key to the vector
71+
}
72+
});
73+
74+
return stringsOnlyInFirstMap;
75+
}
76+
77+
//___________________________________________________________________
78+
const std::vector<std::string> onlyInOther(const L1TUtmTriggerMenu* other) const {
79+
const auto& otherMap = other->getAlgorithmMap();
80+
81+
std::vector<std::string> stringsOnlyInSecondMap;
82+
83+
// Lambda function capturing 'this' to access the member variable 'm_map'
84+
std::for_each(otherMap.begin(),
85+
otherMap.end(),
86+
[this, &stringsOnlyInSecondMap](const std::pair<std::string, L1TUtmAlgorithm>& pair) {
87+
const std::string& key = pair.first;
88+
89+
// Check if the key exists in m_map
90+
if (this->m_map.find(key) == this->m_map.end()) {
91+
stringsOnlyInSecondMap.push_back(key); // Add key to the vector
92+
}
93+
});
94+
95+
return stringsOnlyInSecondMap;
96+
}
97+
98+
private:
99+
l1tUtmAlgoMap m_map;
100+
};
101+
102+
class L1TUtmTriggerMenuDisplay {
103+
public:
104+
L1TUtmTriggerMenuDisplay(const L1TUtmTriggerMenu* thisMenu, std::string theTag, std::string theIOV)
105+
: m_info(thisMenu), m_tagName(theTag), m_IOVsinceDisplay(theIOV) {}
106+
~L1TUtmTriggerMenuDisplay() = default;
107+
108+
void setImageFileName(const std::string& theFileName) {
109+
m_imageFileName = theFileName;
110+
return;
111+
}
112+
113+
//___________________________________________________________________
114+
void plotDiffWithOtherMenu(const L1TUtmTriggerMenu* other, std::string theRefTag, std::string theRefIOV) {
115+
const auto& vec_only_in_this = m_info.onlyInThis(other);
116+
const auto& vec_only_in_other = m_info.onlyInOther(other);
117+
118+
// preparations for plotting
119+
// starting table at y=1.0 (top of the canvas)
120+
// first column is at 0.03, second column at 0.22 NDC
121+
unsigned int mapsize = vec_only_in_this.size() + vec_only_in_other.size();
122+
float pitch = 1. / (mapsize * 1.1);
123+
float y, x1, x2;
124+
std::vector<float> y_x1, y_x2, y_line;
125+
std::vector<std::string> s_x1, s_x2, s_x3;
126+
y = 1.0;
127+
x1 = 0.02;
128+
x2 = x1 + 0.45;
129+
y -= pitch;
130+
131+
// title for plot
132+
y_x1.push_back(y);
133+
s_x1.push_back("#scale[1.1]{Key}");
134+
y_x2.push_back(y);
135+
s_x2.push_back("#scale[1.1]{Target tag / IOV: #color[2]{" + m_tagName + "} / " + m_IOVsinceDisplay + "}");
136+
137+
y -= pitch;
138+
y_x1.push_back(y);
139+
s_x1.push_back("");
140+
y_x2.push_back(y);
141+
s_x2.push_back("#scale[1.1]{Refer tag / IOV: #color[4]{" + theRefTag + "} / " + theRefIOV + "}");
142+
143+
y -= pitch / 2.;
144+
y_line.push_back(y);
145+
146+
// First, check if there are records in reference which are not in target
147+
for (const auto& ref : vec_only_in_other) {
148+
y -= pitch;
149+
y_x1.push_back(y);
150+
s_x1.push_back(ref);
151+
y_x2.push_back(y);
152+
s_x2.push_back("#color[4]{#bf{Only in reference, not in target.}}");
153+
y_line.push_back(y - (pitch / 2.));
154+
}
155+
156+
// Second, check if there are records in target which are not in reference
157+
for (const auto& tar : vec_only_in_this) {
158+
y -= pitch;
159+
y_x1.push_back(y);
160+
s_x1.push_back(tar);
161+
y_x2.push_back(y);
162+
s_x2.push_back("#color[2]{#bf{Only in target, not in reference.}}");
163+
y_line.push_back(y - (pitch / 2.));
164+
}
165+
166+
// Finally, print text to TCanvas
167+
TCanvas canvas("L1TUtmMenuData", "L1TUtmMenuData", 2000, std::max(y_x1.size(), y_x2.size()) * 40);
168+
TLatex l;
169+
// Draw the columns titles
170+
l.SetTextAlign(12);
171+
172+
float newpitch = 1 / (std::max(y_x1.size(), y_x2.size()) * 1.1);
173+
float factor = newpitch / pitch;
174+
l.SetTextSize(newpitch - 0.002);
175+
canvas.cd();
176+
for (unsigned int i = 0; i < y_x1.size(); i++) {
177+
l.DrawLatexNDC(x1, 1 - (1 - y_x1[i]) * factor, s_x1[i].c_str());
178+
}
179+
180+
for (unsigned int i = 0; i < y_x2.size(); i++) {
181+
l.DrawLatexNDC(x2, 1 - (1 - y_x2[i]) * factor, s_x2[i].c_str());
182+
}
183+
184+
canvas.cd();
185+
canvas.Update();
186+
187+
// Draw horizontal lines separating records
188+
TLine lines[y_line.size()];
189+
unsigned int iL = 0;
190+
for (const auto& line : y_line) {
191+
lines[iL] = TLine(gPad->GetUxmin(), 1 - (1 - line) * factor, gPad->GetUxmax(), 1 - (1 - line) * factor);
192+
lines[iL].SetLineWidth(1);
193+
lines[iL].SetLineStyle(9);
194+
lines[iL].SetLineColor(2);
195+
lines[iL].Draw("same");
196+
iL++;
197+
}
198+
199+
std::string fileName("L1UtmMenuData_Compare.png");
200+
if (!m_imageFileName.empty())
201+
fileName = m_imageFileName;
202+
canvas.SaveAs(fileName.c_str());
203+
}
204+
205+
private:
206+
L1UtmTriggerMenuInfo m_info; //!< map of the record / metadata associations
207+
std::string m_tagName; //!< tag name
208+
std::string m_IOVsinceDisplay; //!< iov since
209+
std::string m_imageFileName; //!< image file name
210+
};
211+
} // namespace L1TUtmTriggerMenuInspectorHelper
212+
213+
#endif
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<library file="L1TUtmTriggerMenu_PayloadInspector.cc" name="L1TUtmTriggerMenu_PayloadInspector">
2+
<use name="CondCore/Utilities"/>
3+
<use name="CondCore/CondDB"/>
4+
<use name="CondFormats/L1TObjects"/>
5+
</library>
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
/*!
2+
\file L1UtmTriggerMenu_PayloadInspector
3+
\Payload Inspector Plugin for L1UtmTriggerMenu payloads
4+
\author M. Musich
5+
\version $Revision: 1.0 $
6+
\date $Date: 2023/11/15 14:49:00 $
7+
*/
8+
9+
#include "FWCore/MessageLogger/interface/MessageLogger.h"
10+
11+
#include "CondCore/Utilities/interface/PayloadInspectorModule.h"
12+
#include "CondCore/Utilities/interface/PayloadInspector.h"
13+
#include "CondCore/CondDB/interface/Time.h"
14+
15+
// the data format of the condition to be inspected
16+
#include "CondFormats/L1TObjects/interface/L1TUtmTriggerMenu.h"
17+
#include "CondCore/L1TPlugins/interface/L1TUtmTriggerMenuPayloadInspectorHelper.h"
18+
19+
#include <memory>
20+
#include <sstream>
21+
#include <iostream>
22+
23+
// include ROOT
24+
#include "TH2F.h"
25+
#include "TLegend.h"
26+
#include "TCanvas.h"
27+
#include "TLine.h"
28+
#include "TGraph.h"
29+
#include "TStyle.h"
30+
#include "TLatex.h"
31+
#include "TPave.h"
32+
#include "TPaveStats.h"
33+
34+
namespace {
35+
36+
using namespace cond::payloadInspector;
37+
38+
class L1TUtmTriggerMenuDisplayAlgos : public PlotImage<L1TUtmTriggerMenu, SINGLE_IOV> {
39+
public:
40+
L1TUtmTriggerMenuDisplayAlgos() : PlotImage<L1TUtmTriggerMenu, SINGLE_IOV>("L1TUtmTriggerMenu plot") {}
41+
42+
bool fill() override {
43+
auto tag = PlotBase::getTag<0>();
44+
auto iov = tag.iovs.front();
45+
std::string IOVsince = std::to_string(std::get<0>(iov));
46+
auto tagname = tag.name;
47+
std::shared_ptr<L1TUtmTriggerMenu> payload = fetchPayload(std::get<1>(iov));
48+
if (payload.get()) {
49+
/// Create a canvas
50+
const auto& theMap = payload->getAlgorithmMap();
51+
52+
unsigned int mapsize = theMap.size();
53+
float pitch = 1. / (mapsize);
54+
55+
float y, x1, x2;
56+
std::vector<float> y_x1, y_x2, y_line;
57+
std::vector<std::string> s_x1, s_x2, s_x3;
58+
59+
// starting table at y=1.0 (top of the canvas)
60+
// first column is at 0.02, second column at 0.32 NDC
61+
y = 1.0;
62+
x1 = 0.02;
63+
x2 = x1 + 0.15;
64+
65+
y -= pitch;
66+
y_x1.push_back(y);
67+
s_x1.push_back("#scale[1.2]{Algo Name}");
68+
y_x2.push_back(y);
69+
s_x2.push_back("#scale[1.2]{tag: " + tag.name + " in IOV: " + IOVsince + "}");
70+
71+
y -= pitch / 2.;
72+
y_line.push_back(y);
73+
74+
for (const auto& [name, algo] : theMap) {
75+
y -= pitch;
76+
y_x1.push_back(y);
77+
s_x1.push_back("''");
78+
79+
y_x2.push_back(y);
80+
s_x2.push_back("#color[2]{" + name + "}");
81+
y_line.push_back(y - (pitch / 2.));
82+
}
83+
84+
TCanvas canvas("L1TriggerAlgos", "L1TriggerAlgos", 2000, mapsize * 40);
85+
TLatex l;
86+
// Draw the columns titles
87+
l.SetTextAlign(12);
88+
l.SetTextSize(pitch * 10);
89+
canvas.cd();
90+
for (unsigned int i = 0; i < y_x1.size(); i++) {
91+
l.DrawLatexNDC(x1, 1 - (1 - y_x1[i]), s_x1[i].c_str());
92+
}
93+
94+
for (unsigned int i = 0; i < y_x2.size(); i++) {
95+
l.DrawLatexNDC(x2, 1 - (1 - y_x2[i]), s_x2[i].c_str());
96+
}
97+
98+
canvas.cd();
99+
canvas.Update();
100+
101+
TLine lines[y_line.size()];
102+
unsigned int iL = 0;
103+
for (const auto& line : y_line) {
104+
lines[iL] = TLine(gPad->GetUxmin(), 1 - (1 - line), gPad->GetUxmax(), 1 - (1 - line));
105+
lines[iL].SetLineWidth(1);
106+
lines[iL].SetLineStyle(9);
107+
lines[iL].SetLineColor(2);
108+
lines[iL].Draw("same");
109+
iL++;
110+
}
111+
112+
std::string fileName(m_imageFileName);
113+
canvas.SaveAs(fileName.c_str());
114+
} // payload
115+
return true;
116+
} // fill
117+
};
118+
119+
template <IOVMultiplicity nIOVs, int ntags>
120+
class L1TUtmTriggerMenu_CompareAlgosBase : public PlotImage<L1TUtmTriggerMenu, nIOVs, ntags> {
121+
public:
122+
L1TUtmTriggerMenu_CompareAlgosBase()
123+
: PlotImage<L1TUtmTriggerMenu, nIOVs, ntags>("L1TUtmTriggerMenu comparison of contents") {}
124+
125+
bool fill() override {
126+
// trick to deal with the multi-ioved tag and two tag case at the same time
127+
auto theIOVs = PlotBase::getTag<0>().iovs;
128+
auto f_tagname = PlotBase::getTag<0>().name;
129+
std::string l_tagname = "";
130+
auto firstiov = theIOVs.front();
131+
std::tuple<cond::Time_t, cond::Hash> lastiov;
132+
133+
// we don't support (yet) comparison with more than 2 tags
134+
assert(this->m_plotAnnotations.ntags < 3);
135+
136+
if (this->m_plotAnnotations.ntags == 2) {
137+
auto tag2iovs = PlotBase::getTag<1>().iovs;
138+
l_tagname = PlotBase::getTag<1>().name;
139+
lastiov = tag2iovs.front();
140+
} else {
141+
lastiov = theIOVs.back();
142+
}
143+
144+
std::shared_ptr<L1TUtmTriggerMenu> last_payload = this->fetchPayload(std::get<1>(lastiov));
145+
std::shared_ptr<L1TUtmTriggerMenu> first_payload = this->fetchPayload(std::get<1>(firstiov));
146+
147+
std::string lastIOVsince = std::to_string(std::get<0>(lastiov));
148+
std::string firstIOVsince = std::to_string(std::get<0>(firstiov));
149+
150+
// In case of only one tag, use f_tagname for both target and reference
151+
std::string tmpTagName = l_tagname;
152+
if (tmpTagName.empty())
153+
tmpTagName = f_tagname;
154+
155+
L1TUtmTriggerMenuInspectorHelper::L1TUtmTriggerMenuDisplay thePlot(last_payload.get(), tmpTagName, lastIOVsince);
156+
thePlot.setImageFileName(this->m_imageFileName);
157+
thePlot.plotDiffWithOtherMenu(first_payload.get(), f_tagname, firstIOVsince);
158+
159+
return true;
160+
}
161+
};
162+
163+
using L1TUtmTriggerMenu_CompareAlgos = L1TUtmTriggerMenu_CompareAlgosBase<MULTI_IOV, 1>;
164+
using L1TUtmTriggerMenu_CompareAlgosTwoTags = L1TUtmTriggerMenu_CompareAlgosBase<SINGLE_IOV, 2>;
165+
166+
} // namespace
167+
168+
PAYLOAD_INSPECTOR_MODULE(L1TUtmTriggerMenu) {
169+
PAYLOAD_INSPECTOR_CLASS(L1TUtmTriggerMenuDisplayAlgos);
170+
PAYLOAD_INSPECTOR_CLASS(L1TUtmTriggerMenu_CompareAlgos);
171+
PAYLOAD_INSPECTOR_CLASS(L1TUtmTriggerMenu_CompareAlgosTwoTags);
172+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<use name="CondCore/Utilities"/>
2+
<use name="FWCore/PluginManager"/>
3+
<bin file="testL1TObjectsPayloadInspector.cpp" name="testL1TObjectsPayloadInspector">
4+
</bin>

0 commit comments

Comments
 (0)