Skip to content
Snippets Groups Projects
Commit f8a30891 authored by Sergei Zharko's avatar Sergei Zharko
Browse files

qa-report: updates to the beamer engine

parent a8ecffea
No related branches found
No related tags found
1 merge request!1762QA: Beamer engine for the cbm::qa::report (+ updates on the CA online QA)
Pipeline #28869 passed
...@@ -117,7 +117,7 @@ namespace cbm::algo ...@@ -117,7 +117,7 @@ namespace cbm::algo
/// \note Indexing: [globalHitID], value: (DetID, partitionID, hitID) /// \note Indexing: [globalHitID], value: (DetID, partitionID, hitID)
ca::Vector<std::tuple<ca::EDetectorID, uint32_t, uint32_t>> faHitExternalIndices{"faHitExternalIndices"}; ca::Vector<std::tuple<ca::EDetectorID, uint32_t, uint32_t>> faHitExternalIndices{"faHitExternalIndices"};
static constexpr bool kDEBUG = true; ///< Debug mode static constexpr bool kDEBUG = false; ///< Debug mode
}; };
......
...@@ -11,20 +11,25 @@ ...@@ -11,20 +11,25 @@
#include "CbmQaReportFigure.h" #include "CbmQaReportFigure.h"
#include "CbmQaReportHeader.h" #include "CbmQaReportHeader.h"
#include "CbmQaReportLatexFormat.h"
#include "CbmQaReportSection.h" #include "CbmQaReportSection.h"
#include "CbmQaReportTable.h" #include "CbmQaReportTable.h"
#include "CbmQaReportTail.h" #include "CbmQaReportTail.h"
#include "Logger.h" #include "Logger.h"
#include <boost/algorithm/string/join.hpp>
#include <chrono> #include <chrono>
#include <ctime> #include <ctime>
#include <iomanip> #include <iomanip>
#include <numeric>
#include <regex> #include <regex>
#include <sstream> #include <sstream>
using cbm::qa::report::BeamerEngine; using cbm::qa::report::BeamerEngine;
using cbm::qa::report::Figure; using cbm::qa::report::Figure;
using cbm::qa::report::Header; using cbm::qa::report::Header;
using cbm::qa::report::LatexFormat;
using cbm::qa::report::Section; using cbm::qa::report::Section;
using cbm::qa::report::Table; using cbm::qa::report::Table;
using cbm::qa::report::Tail; using cbm::qa::report::Tail;
...@@ -33,7 +38,86 @@ using cbm::qa::report::Tail; ...@@ -33,7 +38,86 @@ using cbm::qa::report::Tail;
// //
std::string BeamerEngine::FigureBody(const Figure& figure) const std::string BeamerEngine::FigureBody(const Figure& figure) const
{ {
size_t nPlots = figure.GetPlots().size();
if (nPlots == 0) {
LOG(warn) << "No plots provided for figure " << figure.GetLabel() << ". Ignoring.";
return "";
}
std::stringstream out; std::stringstream out;
out << "\\begin{frame}{" << LatexFormat::Apply(figure.GetMother()->GetTitle()) << "}\n";
out << " \\begin{figure}\n";
out << " \\def\\hgt{\\textheight-2\\baselineskip}\n";
out << " \\centering\n";
if (nPlots == 1) {
out << " \\begin{adjustbox}{width=\\textwidth, totalheight=0.9\\hgt, keepaspectratio}\n";
out << " \\includegraphics[height=0.75\\paperheight]{" << figure.GetPlots()[0].fsPath << "}\n";
out << " \\end{adjustbox}\n";
}
else {
std::vector<size_t> vPlotGrid;
bool bDefineDefaultGrid = figure.GetPlotGrid().empty();
if (!bDefineDefaultGrid) {
size_t nPlotsByGrid = std::accumulate(figure.GetPlotGrid().begin(), figure.GetPlotGrid().end(), 0);
if (nPlotsByGrid < nPlots) {
LOG(warn) << "Figure " << figure.GetLabel()
<< ": provided grid does not fit the subfigures, define the default one";
bDefineDefaultGrid = true;
}
}
if (bDefineDefaultGrid) {
if (nPlots < 4) {
vPlotGrid.resize(1, nPlots);
}
else {
int nY = nPlots < 13 ? 2 : 3;
vPlotGrid.resize(nY, size_t(std::ceil(double(nPlots) / nY)));
}
}
else {
vPlotGrid = figure.GetPlotGrid();
}
size_t iPlot = 0;
double hSize = 0.9 / vPlotGrid.size();
for (size_t iY = 0; iY < vPlotGrid.size(); ++iY) {
if (iPlot >= nPlots) {
break;
}
size_t nX = vPlotGrid[iY];
if (nX == 0) {
continue;
}
out << " \\begin{adjustbox}{width=\\textwidth, totalheight=" << hSize << "\\hgt, keepaspectratio}\n";
for (size_t iX = 0; iX < nX; ++iX) {
if (iPlot >= nPlots) {
break;
}
const auto& plot = figure.GetPlots()[iPlot];
out << " \\stackunder[1pt]{\\includegraphics[height=0.75\\paperheight]{" << plot.fsPath << "}}{";
out << plot.fsCaption << "}\n";
if (iX == nX - 1) {
out << '\n';
}
else {
out << " \\quad\n";
}
++iPlot;
}
out << " \\end{adjustbox}\n\n";
if (iY != vPlotGrid.size() - 1) {
out << '\n';
}
}
}
if (!figure.GetCaption().empty()) {
out << " \\caption{" << LatexFormat::Apply(figure.GetCaption()) << "}\n";
}
out << " \\label{" << figure.GetLabel() << "}\n";
out << " \\end{figure}\n";
out << "\\end{frame}\n";
return out.str(); return out.str();
} }
...@@ -42,14 +126,127 @@ std::string BeamerEngine::FigureBody(const Figure& figure) const ...@@ -42,14 +126,127 @@ std::string BeamerEngine::FigureBody(const Figure& figure) const
std::string BeamerEngine::HeaderBody(const Header& header) const std::string BeamerEngine::HeaderBody(const Header& header) const
{ {
std::stringstream out; std::stringstream out;
// TODO: Move these definitions to text-file (?)
// Settings
out << "\\documentclass[aspectratio=169,xcolor=dvipsnames]{beamer}\n";
out << "\\usetheme{Madrid}\n";
out << "\\useinnertheme{circles}\n";
out << "\\setbeamerfont{structure}{family=\\sffamily,series=\\mdseries}\n";
out << "\\setbeamerfont{title}{size=\\LARGE,parent=structure}\n";
out << "\\setbeamerfont{subtitle}{size=\\normalsize,parent=title}\n";
out << "\\setbeamerfont{date}{size=\\scriptsize,series=\\mdseries,parent=structure}\n";
out << "\\setbeamerfont{author}{size=\\Large,series=\\mdseries,parent=structure}\n";
out << "\\setbeamerfont{institute}{size=\\scriptsize,series=\\mdseries,parent=structure}\n";
out << "\\setbeamerfont{section in toc}{size=\\Large,parent=structure}\n";
out << "\\setbeamerfont{section in head/foot}{size=\\tiny,parent=structure}\n";
out << "\\setbeamerfont{subsection in toc}{size=\\large,parent={section in toc}}\n";
out << "\\setbeamerfont{frametitle}{parent=structure,size=\\LARGE}\n";
out << "\\setbeamerfont{framesubtitle}{parent=frametitle,size=\\Large}\n";
out << "\\setbeamerfont{caption}{size=\\footnotesize}\n";
out << "\\setbeamerfont{item}{parent=structure,series=\\mdseries}\n";
out << "\\setbeamerfont{block title}{size=\\large,series=\\mdseries,parent={structure,block body}}\n";
out << "\\definecolor{InvisibleRed}{rgb}{0.92, 0.9, 0.9}\n";
out << "\\definecolor{InvisibleGreen}{rgb}{0.9, 0.92, 0.9}\n";
out << "\\definecolor{InvisibleBlue}{rgb}{0.9, 0.9, 0.92}\n";
out << "\\definecolor{LightBlue}{rgb}{0.4, 0.55, 0.65}\n";
out << "\\definecolor{LightBlue}{rgb}{0.4, 0.55, 0.65}\n";
out << "\\definecolor{MediumRed}{rgb}{0.92549, 0.34509, 0.34509}\n";
out << "\\definecolor{MediumGreen}{rgb}{0.36862, 0.66666, 0.65882}\n";
out << "\\definecolor{MediumBlue}{rgb}{0.01176, 0.31372, 0.43529}\n";
out << "\\definecolor{DarkBlue}{rgb}{0.05, 0.15, 0.3} \n";
out << "\\usecolortheme[named=DarkBlue]{structure}\n";
out << "\\setbeamercolor{alerted text}{fg=LightBlue}\n";
out << "\\setbeamercolor{palette primary}{bg=DarkBlue,fg=white}\n";
out << "\\setbeamercolor{palette secondary}{bg=MediumBlue,fg=white}\n";
out << "\\setbeamercolor{palette tertiary}{bg=LightBlue,fg=white}\n";
out << "\\setbeamercolor{block title}{bg=MediumBlue}\n";
out << "\\setbeamercolor{block body}{bg=InvisibleBlue}\n";
out << "\\setbeamercolor{block title example}{bg=MediumGreen}\n";
out << "\\setbeamercolor{block body example}{bg=InvisibleGreen}\n";
out << "\\setbeamercolor{block title alerted}{bg=MediumRed}\n";
out << "\\setbeamercolor{block body alerted}{bg=InvisibleRed}\n";
out << "\\setbeamertemplate{footline}[page number]\n";
out << "\\setbeamertemplate{navigation symbols}{}\n";
out << "\\setbeamertemplate{blocks}[rounded][shadow=true]\n";
out << "\\setbeamertemplate{enumerate items}[default]\n";
out << "\\setbeamertemplate{section in toc}[sections numbered]\n";
out << "\\setbeamertemplate{subsection in toc}[default]\n";
out << "\\usepackage{hyperref}\n";
out << "\\usepackage{graphicx}\n";
out << "\\usepackage{booktabs}\n";
out << "\\usepackage{listings}\n";
out << "\\usepackage{amsmath}\n";
out << "\\usepackage{listings}\n";
out << "\\usepackage{xcolor}\n";
//out << "\\usepackage{adjustbox}\n";
out << "\\usepackage{subfig}\n";
out << "\\usepackage{hyperref}\n";
out << "\\usepackage{stackengine}\n";
out << "\\usepackage{longtable}\n";
out << "\\usepackage[export]{adjustbox}\n";
out << "\\setbeamertemplate{caption}[numbered]\n";
//out << "\\usepackage{color}\n";
//out << "\\definecolor{hrefcolor}{rgb}{0.2, 0.2, 0.6}\n";
//out << "\\hypersetup{color}{colorlinks=true, urlcolor=hrefcolor,linkcolor=black,citecolor=hrefcolor}\n";
if (!header.GetPageHeader().empty()) {
//out << "\\usepackage{fancyhdr}\n\\pagestyle{fancy}\n\\lhead{"
// << LatexFormat::Apply(header.GetPageHeader()) << "}\n";
}
out << "\n";
// Title page settings
out << "\\title{" << LatexFormat::Apply(header.GetTitle()) << "}\n";
out << "\\subtitle{" << LatexFormat::Apply(header.GetSubtitle()) << "}\n";
auto timeNow = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
out << "\\date{Generated on " << std::put_time(std::localtime(&timeNow), "%a %d.%m.%Y, %X") << "}\n";
// Title page
out << "\\begin{document}\n\n";
out << "\\begin{frame}\n";
out << " \\titlepage\n";
out << " \\begin{tabular}{r@{ }l}\n";
out << " author: & " << header.GetAuthor() << " \\\\\n";
out << " setup: & " << header.GetSetup() << "\\\\\n";
out << " tags: & " << boost::algorithm::join(header.GetTags(), ", ") << '\n';
out << " \\end{tabular}\n";
out << "\\end{frame}\n";
// Table of contents
out << "\\begin{frame}{Outline}\n";
out << " \\tableofcontents\n";
out << "\\end{frame}\n";
out << '\n';
return out.str(); return out.str();
} }
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
// //
std::string BeamerEngine::SectionBody(const Section& section) const std::string BeamerEngine::SectionBody(const Section& section) const
{ {
std::stringstream out; std::stringstream out;
std::string sSectionType = "";
if (section.GetLevel() == 0) {
sSectionType = "section";
}
else if (section.GetLevel() == 1) {
sSectionType = "subsection";
}
else {
sSectionType = "subsubsection";
}
out << "\\" << sSectionType << "{" << section.GetTitle() << "}\n\n";
for (const auto& pElement : section.GetDaughterElements()) {
out << pElement->GetBody(*this) << '\n';
}
out << '\n';
return out.str(); return out.str();
} }
...@@ -58,6 +255,37 @@ std::string BeamerEngine::SectionBody(const Section& section) const ...@@ -58,6 +255,37 @@ std::string BeamerEngine::SectionBody(const Section& section) const
std::string BeamerEngine::TableBody(const Table& table) const std::string BeamerEngine::TableBody(const Table& table) const
{ {
std::stringstream out; std::stringstream out;
int nRows = table.GetNofRows();
int nCols = table.GetNofCols();
out << "\\begin{frame}{" << table.GetMother()->GetTitle() << "}\n";
out << " \\begin{table}\n";
out << " \\footnotesize\n";
// tabular header
if (!table.GetCaption().empty()) {
out << " \\caption{" << LatexFormat::Apply(table.GetCaption()) << "}\n";
}
out << " \\begin{longtable}{" << std::string(nCols, 'c') << "}\n";
// table header
out << " \\hline\n";
out << " ";
for (int iCol = 0; iCol < nCols; ++iCol) {
out << table.GetColumnTitle(iCol) << ((iCol < nCols - 1) ? " & " : " \\\\\n");
}
out << " \\hline\n";
// table body
for (int iRow = 0; iRow < nRows; ++iRow) {
out << " ";
for (int iCol = 0; iCol < nCols; ++iCol) {
out << table(iRow, iCol) << ((iCol < nCols - 1) ? " & " : " \\\\\n");
}
}
out << " \\hline\n";
out << " \\end{longtable}\n";
out << " \\label{" << table.GetLabel() << "}\n";
out << " \\end{table}\n";
out << "\\end{frame}\n";
return out.str(); return out.str();
} }
...@@ -66,9 +294,44 @@ std::string BeamerEngine::TableBody(const Table& table) const ...@@ -66,9 +294,44 @@ std::string BeamerEngine::TableBody(const Table& table) const
std::string BeamerEngine::TailBody(const Tail& figure) const std::string BeamerEngine::TailBody(const Tail& figure) const
{ {
std::stringstream out; std::stringstream out;
out << "\\end{document}\n";
return out.str(); return out.str();
} }
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
// //
void BeamerEngine::Compile(const std::string& source) const {} void BeamerEngine::Compile(const std::string& source) const
{
// Search for compiler program in path
std::string compiler = fsLatexCompiler.substr(0, fsLatexCompiler.find_first_of(' ')); // compiler name without opts
int bCompilerFonud = false;
{
std::stringstream stream(getenv("PATH"));
std::string dir;
while (!bCompilerFonud && std::getline(stream, dir, ':')) {
bCompilerFonud = fs::exists(fs::path(dir) / compiler);
}
}
if (!bCompilerFonud) {
LOG(error) << "cbm::qa::report::BeamerEngine::Compile(): compiler \"" << fsLatexCompiler << "\" not found in PATH. "
<< "Please use another compiler or compile the sourec in external program";
return;
}
// Execute compiler
fs::path sourceDir = fs::path(source).parent_path();
fs::path currPath = fs::current_path();
fs::current_path(sourceDir);
std::string logFile = compiler + ".log";
std::string command = fmt::format("{} {} > {}", fsLatexCompiler, source, logFile);
command = command + ";" + command; // compile two times to get contents
LOG(info) << "cbm::qa::report::BeamerEngine::Compile(): executing command: \n\t" << command;
int res = std::system(command.c_str());
fs::current_path(currPath);
LOG(info) << "cbm::qa::report::BemaerEngine::Compile(): compillation " << (res == 0 ? "succeed" : "failed")
<< "(compiler log: \"" << logFile << "\")";
}
...@@ -23,6 +23,8 @@ namespace cbm::qa::report ...@@ -23,6 +23,8 @@ namespace cbm::qa::report
/// \brief Interface for the report element /// \brief Interface for the report element
/// ///
class Element { class Element {
friend class CollapsibleElement;
public: public:
/// \brief Constructor /// \brief Constructor
/// \param label Element label /// \param label Element label
...@@ -51,10 +53,16 @@ namespace cbm::qa::report ...@@ -51,10 +53,16 @@ namespace cbm::qa::report
/// \brief Sets name /// \brief Sets name
void SetTitle(std::string_view title) { fsTitle = title; } void SetTitle(std::string_view title) { fsTitle = title; }
/// \brief Gets mother element
const Element* const GetMother() const { return fpMother; }
private: private:
void AssignMother(const Element* pMother) { fpMother = pMother; }
// TODO: Add check for multiple label definition // TODO: Add check for multiple label definition
std::string fsLabel = ""; ///< Label for referencing const Element* fpMother = nullptr; ///< Mother element
std::string fsTitle = ""; ///< Title of the element std::string fsLabel = ""; ///< Label for referencing
std::string fsTitle = ""; ///< Title of the element
}; };
/// \class CollapsibleElement /// \class CollapsibleElement
...@@ -69,7 +77,11 @@ namespace cbm::qa::report ...@@ -69,7 +77,11 @@ namespace cbm::qa::report
/// \brief Adds element /// \brief Adds element
// TODO: Check for label // TODO: Check for label
virtual void Add(std::shared_ptr<Element> pElement) { fvDaughterElements.push_back(pElement); } virtual void Add(std::shared_ptr<Element> pElement)
{
pElement->AssignMother(this);
fvDaughterElements.push_back(pElement);
}
/// \brief Get daughter elements /// \brief Get daughter elements
const std::vector<std::shared_ptr<Element>> GetDaughterElements() const { return fvDaughterElements; } const std::vector<std::shared_ptr<Element>> GetDaughterElements() const { return fvDaughterElements; }
......
...@@ -23,6 +23,9 @@ namespace cbm::qa::report ...@@ -23,6 +23,9 @@ namespace cbm::qa::report
/// \brief Destructor /// \brief Destructor
virtual ~Header() = default; virtual ~Header() = default;
/// \brief Add tag
void AddTag(std::string_view tag) { fvsTags.emplace_back(tag); }
/// \brief Gets body of the element /// \brief Gets body of the element
/// \param engine A concrete implementation of the Engine to get the element body /// \param engine A concrete implementation of the Engine to get the element body
std::string GetBody(const Engine& engine) const { return engine.HeaderBody(*this); } std::string GetBody(const Engine& engine) const { return engine.HeaderBody(*this); }
...@@ -39,6 +42,9 @@ namespace cbm::qa::report ...@@ -39,6 +42,9 @@ namespace cbm::qa::report
/// \brief Gets subtitle /// \brief Gets subtitle
const std::string& GetSubtitle() const { return fsSubtitle; } const std::string& GetSubtitle() const { return fsSubtitle; }
/// \brief Gets tags
const std::vector<std::string>& GetTags() const { return fvsTags; }
/// \brief Gets title /// \brief Gets title
const std::string& GetTitle() const { return fsTitle; } const std::string& GetTitle() const { return fsTitle; }
...@@ -58,6 +64,8 @@ namespace cbm::qa::report ...@@ -58,6 +64,8 @@ namespace cbm::qa::report
void SetTitle(std::string_view title) { fsTitle = title; } void SetTitle(std::string_view title) { fsTitle = title; }
private: private:
std::vector<std::string> fvsTags{}; ///< Different Tags
std::string fsAuthor = ""; std::string fsAuthor = "";
std::string fsSetup = ""; std::string fsSetup = "";
std::string fsSubtitle = ""; std::string fsSubtitle = "";
......
...@@ -21,4 +21,4 @@ namespace cbm::qa::report ...@@ -21,4 +21,4 @@ namespace cbm::qa::report
/// \brief Applies a LaTeX-friendly formatting /// \brief Applies a LaTeX-friendly formatting
static std::string Apply(std::string_view input); static std::string Apply(std::string_view input);
}; };
} // namespace cbm::qa::report } // namespace cbm::qa::report
\ No newline at end of file
...@@ -206,6 +206,6 @@ void qa_report_ca_offline( ...@@ -206,6 +206,6 @@ void qa_report_ca_offline(
} }
} }
cbm::qa::report::LatexEngine latex; cbm::qa::report::BeamerEngine latex;
pReport->CreateScript(latex); pReport->CreateScript(latex);
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment