Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-11-07 06:12:36

0001 #include "CondCore/Utilities/interface/PayloadInspectorModule.h"
0002 #include "CondCore/Utilities/interface/PayloadInspector.h"
0003 #include "CondCore/CondDB/interface/Time.h"
0004 #include "CondFormats/HLTObjects/interface/AlCaRecoTriggerBits.h"
0005 
0006 #include "TCanvas.h"
0007 #include "TLatex.h"
0008 #include "TLine.h"
0009 #include <fmt/printf.h>
0010 #include <iostream>
0011 #include <memory>
0012 #include <cmath>
0013 #include <numeric>
0014 #include <sstream>
0015 
0016 namespace {
0017 
0018   using namespace cond::payloadInspector;
0019 
0020   /************************************************
0021     Display AlCaRecoTriggerBits mapping
0022   *************************************************/
0023   class AlCaRecoTriggerBits_Display : public PlotImage<AlCaRecoTriggerBits, SINGLE_IOV> {
0024   public:
0025     AlCaRecoTriggerBits_Display() : PlotImage<AlCaRecoTriggerBits, SINGLE_IOV>("Table of AlCaRecoTriggerBits") {}
0026 
0027     using TriggerMap = std::map<std::string, std::string>;
0028 
0029     bool fill() override {
0030       auto tag = PlotBase::getTag<0>();
0031       auto iov = tag.iovs.front();
0032       std::string IOVsince = std::to_string(std::get<0>(iov));
0033       auto tagname = tag.name;
0034       std::shared_ptr<AlCaRecoTriggerBits> payload = fetchPayload(std::get<1>(iov));
0035 
0036       if (payload.get()) {
0037         const TriggerMap &triggerMap = payload->m_alcarecoToTrig;
0038 
0039         // pre-compute how many time we break the line
0040         const int totalCarriageReturns = calculateTotalCarriageReturns(payload);
0041         LogDebug("AlCaRecoTriggerBits_Display") << "Total number of carriage returns: " << totalCarriageReturns;
0042 
0043         // Dynamically calculate the pitch and canvas height
0044         float pitch = 1.0 / (totalCarriageReturns + 2.0);  // Adjusted pitch for better spacing
0045 
0046         float y = 1.0;
0047         float x1 = 0.02, x2 = x1 + 0.25;
0048         std::vector<float> y_x1, y_x2, y_line;
0049         std::vector<std::string> s_x1, s_x2;
0050 
0051         // Header row setup
0052         y -= pitch;
0053         y_x1.push_back(y);
0054         s_x1.push_back("#scale[1.2]{Key}");
0055         y_x2.push_back(y);
0056         s_x2.push_back("#scale[1.2]{tag: " + tagname + " in IOV: " + IOVsince + "}");
0057 
0058         y -= pitch / 2.0;
0059         y_line.push_back(y);
0060 
0061         // Populate rows with data from the trigger map
0062         for (const auto &element : triggerMap) {
0063           y -= pitch;
0064           y_x1.push_back(y);
0065           s_x1.push_back(element.first);
0066           std::vector<std::string> output;
0067 
0068           std::string toAppend = "";
0069           const std::vector<std::string> paths = payload->decompose(element.second);
0070           for (unsigned int iPath = 0; iPath < paths.size(); ++iPath) {
0071             if ((toAppend + paths[iPath]).length() < 80) {  // Wider lines
0072               toAppend += paths[iPath] + ";";
0073             } else {
0074               output.push_back(toAppend);
0075               toAppend.clear();
0076               toAppend += paths[iPath] + ";";
0077             }
0078             if (iPath == paths.size() - 1)
0079               output.push_back(toAppend);
0080           }
0081 
0082           for (unsigned int br = 0; br < output.size(); br++) {
0083             y_x2.push_back(y);
0084             s_x2.push_back("#color[2]{" + output[br] + "}");
0085             if (br != output.size() - 1)
0086               y -= pitch;
0087           }
0088 
0089           y_line.push_back(y - (pitch / 2.0));
0090         }
0091 
0092         // Dynamically calculate the pitch and canvas height
0093         float canvasHeight = std::max(800.0f, totalCarriageReturns * 30.0f);  // Adjust canvas height based on entries
0094         TCanvas canvas("AlCaRecoTriggerBits", "AlCaRecoTriggerBits", 2000, static_cast<int>(canvasHeight));
0095 
0096         TLatex l;
0097         l.SetTextAlign(12);
0098         float textSize = std::clamp(pitch, 0.015f, 0.035f);
0099         l.SetTextSize(textSize);
0100 
0101         // Draw the columns
0102         int totalPitches = 0;
0103         canvas.cd();
0104         for (unsigned int i = 0; i < y_x1.size(); i++) {
0105           l.DrawLatexNDC(x1, y_x1[i], s_x1[i].c_str());
0106           if (i != 0) {
0107             LogDebug("AlCaRecoTriggerBits_Display")
0108                 << "x1:" << x1 << " y_x1[" << std::setw(2) << i << "]: " << y_x1[i]
0109                 << " Delta = " << std::ceil((y_x1[i - 1] - y_x1[i]) / pitch) << " pitches " << s_x1[i].c_str();
0110             totalPitches += std::ceil((y_x1[i - 1] - y_x1[i]) / pitch);
0111           }
0112         }
0113 
0114         LogDebug("AlCaRecoTriggerBits_Display") << "We've gone down by " << totalPitches << "pitches ";
0115 
0116         for (unsigned int i = 0; i < y_x2.size(); i++) {
0117           l.DrawLatexNDC(x2, y_x2[i], s_x2[i].c_str());
0118         }
0119 
0120         // Draw lines for row separation
0121         TLine lines[y_line.size()];
0122         for (unsigned int i = 0; i < y_line.size(); i++) {
0123           lines[i] = TLine(gPad->GetUxmin(), y_line[i], gPad->GetUxmax(), y_line[i]);
0124           lines[i].SetLineWidth(1);
0125           lines[i].SetLineStyle(9);
0126           lines[i].SetLineColor(2);
0127           lines[i].Draw("same");
0128         }
0129 
0130         canvas.SaveAs(m_imageFileName.c_str());
0131       }
0132       return true;
0133     }
0134 
0135   private:
0136     int calculateTotalCarriageReturns(std::shared_ptr<AlCaRecoTriggerBits> payload) {
0137       int totalCarriageReturns = 0;
0138       const TriggerMap &triggerMap = payload->m_alcarecoToTrig;
0139 
0140       for (const auto &element : triggerMap) {
0141         const auto &paths = payload->decompose(element.second);
0142         int lineLength = 0;
0143 
0144         for (const auto &path : paths) {
0145           lineLength += path.length() + 1;  // +1 for the semicolon
0146           if (lineLength >= 80) {
0147             totalCarriageReturns++;
0148             lineLength = path.length() + 1;  // Reset for the next line segment
0149           }
0150         }
0151         totalCarriageReturns++;  // Count the initial line for each element
0152       }
0153       return totalCarriageReturns;
0154     }
0155   };
0156 
0157   /************************************************
0158     Compare AlCaRecoTriggerBits mapping
0159   *************************************************/
0160   template <IOVMultiplicity nIOVs, int ntags>
0161   class AlCaRecoTriggerBits_CompareBase : public PlotImage<AlCaRecoTriggerBits, nIOVs, ntags> {
0162   public:
0163     AlCaRecoTriggerBits_CompareBase()
0164         : PlotImage<AlCaRecoTriggerBits, nIOVs, ntags>("Table of AlCaRecoTriggerBits comparison") {}
0165 
0166     bool fill() override {
0167       // trick to deal with the multi-ioved tag and two tag case at the same time
0168       auto theIOVs = PlotBase::getTag<0>().iovs;
0169       auto f_tagname = PlotBase::getTag<0>().name;
0170       std::string l_tagname = "";
0171       auto firstiov = theIOVs.front();
0172       std::tuple<cond::Time_t, cond::Hash> lastiov;
0173 
0174       // we don't support (yet) comparison with more than 2 tags
0175       assert(this->m_plotAnnotations.ntags < 3);
0176 
0177       if (this->m_plotAnnotations.ntags == 2) {
0178         auto tag2iovs = PlotBase::getTag<1>().iovs;
0179         l_tagname = PlotBase::getTag<1>().name;
0180         lastiov = tag2iovs.front();
0181       } else {
0182         lastiov = theIOVs.back();
0183       }
0184 
0185       std::shared_ptr<AlCaRecoTriggerBits> last_payload = this->fetchPayload(std::get<1>(lastiov));
0186       std::shared_ptr<AlCaRecoTriggerBits> first_payload = this->fetchPayload(std::get<1>(firstiov));
0187 
0188       std::string lastIOVsince = std::to_string(std::get<0>(lastiov));
0189       std::string firstIOVsince = std::to_string(std::get<0>(firstiov));
0190 
0191       // Get map of strings to concatenated list of names of HLT paths:
0192       typedef std::map<std::string, std::string> TriggerMap;
0193       const TriggerMap &first_triggerMap = first_payload->m_alcarecoToTrig;
0194       const TriggerMap &last_triggerMap = last_payload->m_alcarecoToTrig;
0195 
0196       std::vector<std::string> first_keys, not_in_first_keys;
0197       std::vector<std::string> last_keys, not_in_last_keys;
0198 
0199       // fill the vector of first keys
0200       for (const auto &element : first_triggerMap) {
0201         first_keys.push_back(element.first);
0202       }
0203 
0204       // fill the vector of last keys
0205       for (const auto &element : last_triggerMap) {
0206         last_keys.push_back(element.first);
0207       }
0208 
0209       // find the elements not in common
0210       std::set_difference(first_keys.begin(),
0211                           first_keys.end(),
0212                           last_keys.begin(),
0213                           last_keys.end(),
0214                           std::inserter(not_in_last_keys, not_in_last_keys.begin()));
0215 
0216       std::set_difference(last_keys.begin(),
0217                           last_keys.end(),
0218                           first_keys.begin(),
0219                           first_keys.end(),
0220                           std::inserter(not_in_first_keys, not_in_first_keys.begin()));
0221 
0222       float pitch = 0.013;
0223       float y, x1, x2, x3;
0224 
0225       std::vector<float> y_x1, y_x2, y_x3, y_line;
0226       std::vector<std::string> s_x1, s_x2, s_x3;
0227 
0228       y = 1.0;
0229       x1 = 0.02;
0230       x2 = x1 + 0.20;
0231       x3 = x2 + 0.30;
0232 
0233       y -= pitch;
0234       y_x1.push_back(y);
0235       s_x1.push_back("#scale[1.2]{Key}");
0236       y_x2.push_back(y);
0237       s_x2.push_back(fmt::sprintf("#scale[1.2]{%s in IOV: %s}", f_tagname, firstIOVsince));
0238       y_x3.push_back(y);
0239       s_x3.push_back(fmt::sprintf("#scale[1.2]{%s in IOV: %s}", l_tagname, lastIOVsince));
0240       y -= pitch / 3;
0241 
0242       // print the ones missing in the last key
0243       for (const auto &key : not_in_last_keys) {
0244         y -= pitch;
0245         y_x1.push_back(y);
0246         s_x1.push_back(key);
0247 
0248         const std::vector<std::string> missing_in_last_paths = first_payload->decompose(first_triggerMap.at(key));
0249 
0250         std::vector<std::string> output;
0251         std::string toAppend = "";
0252         for (unsigned int iPath = 0; iPath < missing_in_last_paths.size(); ++iPath) {
0253           // if the line to be added has less than 60 chars append to current
0254           if ((toAppend + missing_in_last_paths[iPath]).length() < 60) {
0255             toAppend += missing_in_last_paths[iPath] + ";";
0256           } else {
0257             // else if the line exceeds 60 chars, dump in the vector and resume from scratch
0258             output.push_back(toAppend);
0259             toAppend.clear();
0260             toAppend += missing_in_last_paths[iPath] + ";";
0261           }
0262           // if it's the last, dump it
0263           if (iPath == missing_in_last_paths.size() - 1)
0264             output.push_back(toAppend);
0265         }
0266 
0267         for (unsigned int br = 0; br < output.size(); br++) {
0268           y_x2.push_back(y);
0269           s_x2.push_back("#color[2]{" + output[br] + "}");
0270           if (br != output.size() - 1)
0271             y -= pitch;
0272         }
0273         y_line.push_back(y - 0.008);
0274       }
0275 
0276       // print the ones missing in the first key
0277       for (const auto &key : not_in_first_keys) {
0278         y -= pitch;
0279         y_x1.push_back(y);
0280         s_x1.push_back(key);
0281         const std::vector<std::string> missing_in_first_paths = last_payload->decompose(last_triggerMap.at(key));
0282 
0283         std::vector<std::string> output;
0284         std::string toAppend = "";
0285         for (unsigned int iPath = 0; iPath < missing_in_first_paths.size(); ++iPath) {
0286           // if the line to be added has less than 60 chars append to current
0287           if ((toAppend + missing_in_first_paths[iPath]).length() < 60) {
0288             toAppend += missing_in_first_paths[iPath] + ";";
0289           } else {
0290             // else if the line exceeds 60 chars, dump in the vector and resume from scratch
0291             output.push_back(toAppend);
0292             toAppend.clear();
0293             toAppend += missing_in_first_paths[iPath] + ";";
0294           }
0295           // if it's the last, dump it
0296           if (iPath == missing_in_first_paths.size() - 1)
0297             output.push_back(toAppend);
0298         }
0299 
0300         for (unsigned int br = 0; br < output.size(); br++) {
0301           y_x3.push_back(y);
0302           s_x3.push_back("#color[4]{" + output[br] + "}");
0303           if (br != output.size() - 1)
0304             y -= pitch;
0305         }
0306         y_line.push_back(y - 0.008);
0307       }
0308 
0309       for (const auto &element : first_triggerMap) {
0310         if (last_triggerMap.find(element.first) != last_triggerMap.end()) {
0311           auto lastElement = last_triggerMap.find(element.first);
0312 
0313           std::string output;
0314           const std::vector<std::string> first_paths = first_payload->decompose(element.second);
0315           const std::vector<std::string> last_paths = last_payload->decompose(lastElement->second);
0316 
0317           std::vector<std::string> not_in_first;
0318           std::vector<std::string> not_in_last;
0319 
0320           std::set_difference(first_paths.begin(),
0321                               first_paths.end(),
0322                               last_paths.begin(),
0323                               last_paths.end(),
0324                               std::inserter(not_in_last, not_in_last.begin()));
0325 
0326           std::set_difference(last_paths.begin(),
0327                               last_paths.end(),
0328                               first_paths.begin(),
0329                               first_paths.end(),
0330                               std::inserter(not_in_first, not_in_first.begin()));
0331 
0332           if (!not_in_last.empty() || !not_in_first.empty()) {
0333             y -= pitch;
0334             y_x1.push_back(y);
0335             s_x1.push_back(element.first);
0336 
0337             std::vector<std::string> output;
0338             std::string toAppend = "";
0339             for (unsigned int iPath = 0; iPath < not_in_last.size(); ++iPath) {
0340               // if the line to be added has less than 60 chars append to current
0341               if ((toAppend + not_in_last[iPath]).length() < 60) {
0342                 toAppend += not_in_last[iPath] + ";";
0343               } else {
0344                 // else if the line exceeds 60 chars, dump in the vector and resume from scratch
0345                 output.push_back(toAppend);
0346                 toAppend.clear();
0347                 toAppend += not_in_last[iPath] + ";";
0348               }
0349               // if it's the last and not empty, dump it
0350               if (toAppend.length() > 0 && iPath == not_in_last.size() - 1)
0351                 output.push_back(toAppend);
0352             }
0353 
0354             unsigned int count = output.size();
0355 
0356             for (unsigned int br = 0; br < count; br++) {
0357               y_x2.push_back(y - (br * pitch));
0358               s_x2.push_back("#color[6]{" + output[br] + "}");
0359             }
0360 
0361             // clear vector and string
0362             toAppend.clear();
0363             output.clear();
0364             for (unsigned int jPath = 0; jPath < not_in_first.size(); ++jPath) {
0365               // if the line to be added has less than 60 chars append to current
0366               if ((toAppend + not_in_first[jPath]).length() < 60) {
0367                 toAppend += not_in_first[jPath] + ";";
0368               } else {
0369                 // else if the line exceeds 60 chars, dump in the vector and resume from scratch
0370                 output.push_back(toAppend);
0371                 toAppend.clear();
0372                 toAppend += not_in_first[jPath] + ";";
0373               }
0374               // if it's the last and not empty, dump it
0375               if (toAppend.length() > 0 && jPath == not_in_first.size() - 1)
0376                 output.push_back(toAppend);
0377             }
0378 
0379             unsigned int count1 = output.size();
0380 
0381             for (unsigned int br = 0; br < count1; br++) {
0382               y_x3.push_back(y - (br * pitch));
0383               s_x3.push_back("#color[8]{" + output[br] + "}");
0384             }
0385 
0386             // decrease the y position to the maximum of the two lists
0387             y -= (std::max(count, count1) - 1) * pitch;
0388             //y-=count*pitch;
0389             y_line.push_back(y - 0.008);
0390 
0391           }  // close if there is at least a difference
0392         }  // if there is a common key
0393       }  //loop on the keys
0394 
0395       TCanvas canvas("AlCaRecoTriggerBits", "AlCaRecoTriggerBits", 2500., std::max(y_x1.size(), y_x2.size()) * 40);
0396 
0397       TLatex l;
0398       // Draw the columns titles
0399       l.SetTextAlign(12);
0400 
0401       // rescale the width of the table row to fit into the canvas
0402       float newpitch = 1 / (std::max(y_x1.size(), y_x2.size()) * 1.65);
0403       float factor = newpitch / pitch;
0404       l.SetTextSize(newpitch - 0.002);
0405       canvas.cd();
0406       for (unsigned int i = 0; i < y_x1.size(); i++) {
0407         l.DrawLatexNDC(x1, 1 - (1 - y_x1[i]) * factor, s_x1[i].c_str());
0408       }
0409 
0410       for (unsigned int i = 0; i < y_x2.size(); i++) {
0411         l.DrawLatexNDC(x2, 1 - (1 - y_x2[i]) * factor, s_x2[i].c_str());
0412       }
0413 
0414       for (unsigned int i = 0; i < y_x3.size(); i++) {
0415         l.DrawLatexNDC(x3, 1 - (1 - y_x3[i]) * factor, s_x3[i].c_str());
0416       }
0417 
0418       canvas.cd();
0419       canvas.Update();
0420 
0421       TLine lines[y_line.size()];
0422       unsigned int iL = 0;
0423       for (const auto &line : y_line) {
0424         lines[iL] = TLine(gPad->GetUxmin(), 1 - (1 - line) * factor, gPad->GetUxmax(), 1 - (1 - line) * factor);
0425         lines[iL].SetLineWidth(1);
0426         lines[iL].SetLineStyle(9);
0427         lines[iL].SetLineColor(2);
0428         lines[iL].Draw("same");
0429         iL++;
0430       }
0431 
0432       //canvas.SetCanvasSize(2000,(1-y)*1000);
0433       std::string fileName(this->m_imageFileName);
0434       canvas.SaveAs(fileName.c_str());
0435       return true;
0436     }
0437   };
0438 
0439   using AlCaRecoTriggerBits_Compare = AlCaRecoTriggerBits_CompareBase<MULTI_IOV, 1>;
0440   using AlCaRecoTriggerBits_CompareTwoTags = AlCaRecoTriggerBits_CompareBase<SINGLE_IOV, 2>;
0441 
0442 }  // namespace
0443 
0444 PAYLOAD_INSPECTOR_MODULE(AlCaRecoTriggerBits) {
0445   PAYLOAD_INSPECTOR_CLASS(AlCaRecoTriggerBits_Display);
0446   PAYLOAD_INSPECTOR_CLASS(AlCaRecoTriggerBits_Compare);
0447   PAYLOAD_INSPECTOR_CLASS(AlCaRecoTriggerBits_CompareTwoTags);
0448 }