diff --git a/core/qa/CMakeLists.txt b/core/qa/CMakeLists.txt index aaa8e0a0f284989c2117932e60dfa71399f30f8f..04d6c2b8ddaf39a615caba849bc4e2da2caee50b 100644 --- a/core/qa/CMakeLists.txt +++ b/core/qa/CMakeLists.txt @@ -22,12 +22,14 @@ set(SRCS CbmQaCanvas.cxx CbmQaPie.cxx CbmQaHist.cxx +CbmQaTable.cxx ) set(HEADERS CbmQaCanvas.h CbmQaPie.h CbmQaHist.h +CbmQaTable.h ) set(LINKDEF CbmQaBaseLinkDef.h) diff --git a/core/qa/CbmQaBaseLinkDef.h b/core/qa/CbmQaBaseLinkDef.h index c17d1514d6d3ddbe8c398fe87ec3518aa42bed11..9da99d54d53da5d318bd4784290f62e3f4367e51 100644 --- a/core/qa/CbmQaBaseLinkDef.h +++ b/core/qa/CbmQaBaseLinkDef.h @@ -22,5 +22,6 @@ #pragma link C++ class CbmQaHist < TH1I> + ; #pragma link C++ class CbmQaHist < TProfile> + ; #pragma link C++ class CbmQaHist < TProfile2D> + ; +#pragma link C++ class CbmQaTable + ; #endif diff --git a/core/qa/CbmQaTable.cxx b/core/qa/CbmQaTable.cxx new file mode 100644 index 0000000000000000000000000000000000000000..19d005d577869d81b2a88c27ea2b19e4c3d01c95 --- /dev/null +++ b/core/qa/CbmQaTable.cxx @@ -0,0 +1,169 @@ +/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergey Gorbunov, Sergei Zharko [committer] */ + +/// \file CbmQaTable.cxx +/// \brief Implementation of CbmQaTable class +/// \author Sergei Zharko +/// \data 24.03.2022 +/// +/// Provides a ROOT Class to handle a numeric table +/// + +#include "CbmQaTable.h" + +#include "TAxis.h" + +#include <iomanip> +#include <iostream> +#include <fstream> +#include <sstream> + +// TODO: Insert class info, try __PRETTY_FUNCTION__ and inline function for its modification (S.Zharko) + +//------------------------------------------------------------------------------------------------------------------------ +// +CbmQaTable::CbmQaTable(const char* name, const char* title, Int_t nRows, Int_t nCols) + : TH2D(name, title, nCols, 0., static_cast<Double_t>(nCols), nRows, 0., static_cast<Double_t>(nRows)) + , fNcols(nCols) + , fNrows(nRows) +{ + // + // Setup default style of the table + TH2D::SetStats(kFALSE); + TH2D::SetOption("text"); + TH2D::GetXaxis()->SetTickLength(0.); + TH2D::GetYaxis()->SetTickLength(0.); + TH2D::GetXaxis()->SetLabelFont(kDefaultFontStyle); + TH2D::GetYaxis()->SetLabelFont(kDefaultFontStyle); + + // Define basic names of rows and columns + for (Int_t iRow = 1; iRow <= fNrows; ++iRow) { + TH2D::GetYaxis()->SetBinLabel(fNrows - iRow + 1, TString::Format("row %d", iRow).Data()); + } + for (Int_t iCol = 1; iCol <= fNcols; ++iCol) { + TH2D::GetXaxis()->SetBinLabel(iCol, TString::Format("col %d", iCol).Data()); + } +} +// +//------------------------------------------------------------------------------------------------------------------------ +// +CbmQaTable::~CbmQaTable() +{ + +} +// +//------------------------------------------------------------------------------------------------------------------------ +// +Double_t CbmQaTable::GetCell(Int_t iRow, Int_t iCol) const +{ + return TH2D::GetBinContent(iCol + 1, fNrows - iRow); +} +// +//------------------------------------------------------------------------------------------------------------------------ +// +Double_t CbmQaTable::GetCellError(Int_t iRow, Int_t iCol) const +{ + return TH2D::GetBinError(iCol + 1, fNrows - iRow); +} +// +//------------------------------------------------------------------------------------------------------------------------ +// +void CbmQaTable::SetCell(Int_t iRow, Int_t iCol, Double_t content, Double_t error) +{ + TH2D::SetBinContent(iCol + 1, fNrows - iRow, content); + TH2D::SetBinError(iCol + 1, fNrows - iRow, error); +} +// +//------------------------------------------------------------------------------------------------------------ +// +void CbmQaTable::SetNamesOfCols(const std::vector<std::string>& names) +{ + Int_t nEntries = (fNcols > static_cast<Int_t>(names.size())) ? static_cast<Int_t>(names.size()) : fNcols; + // TODO: Possibly, we need a restriction on the names size (S.Zharko) + for (Int_t iCol = 1; iCol <= nEntries; ++iCol) { + TH2D::GetXaxis()->SetBinLabel(iCol, names[iCol - 1].c_str()); + } +} +// +//------------------------------------------------------------------------------------------------------------------------ +// +void CbmQaTable::SetNamesOfRows(const std::vector<std::string>& names) +{ + Int_t nEntries = (fNrows > static_cast<Int_t>(names.size())) ? static_cast<Int_t>(names.size()) : fNrows; + // TODO: Possibly, we need a restriction on the names size (S.Zharko) + for (Int_t iRow = 1; iRow <= nEntries; ++iRow) { + TH2D::GetYaxis()->SetBinLabel(fNrows - iRow + 1, names[iRow - 1].c_str()); + } +} +// +//------------------------------------------------------------------------------------------------------------------------ +// +std::string CbmQaTable::ToString() const +{ + std::stringstream aStream; + aStream << (*this); + return aStream.str(); +} +// +//------------------------------------------------------------------------------------------------------------------------ +// +void CbmQaTable::ToTextFile(const std::string& fileName, std::ios_base::openmode mode) const +{ + std::ofstream fileOut(fileName, mode); + fileOut << (*this); + fileOut.close(); +} +// +//------------------------------------------------------------------------------------------------------------------------ +// +void CbmQaTable::SetTextSize(Float_t size) +{ + TH2D::SetMarkerSize(size / kDefaultTextSize); + TH2D::GetXaxis()->SetLabelSize(size); + TH2D::GetYaxis()->SetLabelSize(size); +} + +// +//------------------------------------------------------------------------------------------------------------------------ +// +std::ostream& operator<<(std::ostream& out, const CbmQaTable& aTable) +{ + out.setf(std::ios::fixed); + out.setf(std::ios::showpoint); + out.precision(3); + out.setf(std::ios::left); + // Print column titles + out << std::setw(CbmQaTable::kRowTitlesSetwPar) << std::setfill(' ') << ' ' << ' '; // top-left cell, always + for (Int_t iCol = 1; iCol <= aTable.fNcols; ++iCol) { + std::string entry = std::string(aTable.GetXaxis()->GetBinLabel(iCol)); + if (static_cast<Int_t>(entry.size()) > CbmQaTable::kDefaultSetwPar) { + entry = entry.substr(0, CbmQaTable::kDefaultSetwPar - 3) + "..."; + } + out << std::setw(CbmQaTable::kDefaultSetwPar) << std::setfill(' ') << entry << ' '; + } + out << '\n'; + + for (Int_t iRow = 0; iRow < aTable.fNrows; ++iRow) { + // Print row title + std::string entry = std::string(aTable.GetYaxis()->GetBinLabel(aTable.fNrows - iRow)); + if (static_cast<Int_t>(entry.size()) > CbmQaTable::kRowTitlesSetwPar) { + entry = entry.substr(0, CbmQaTable::kDefaultSetwPar - 3) + "..."; + } + out << std::setw(CbmQaTable::kRowTitlesSetwPar) << std::setfill(' ') << entry << ' '; + + for (Int_t iCol = 0; iCol < aTable.fNcols; ++iCol) { + out << std::setw(CbmQaTable::kDefaultSetwPar) << std::setfill(' ') << aTable.GetCell(iRow, iCol) << ' '; + } + out << '\n'; + } + return out; +} +// +//------------------------------------------------------------------------------------------------------------------------ +// + + + + + diff --git a/core/qa/CbmQaTable.h b/core/qa/CbmQaTable.h new file mode 100644 index 0000000000000000000000000000000000000000..218191655f545b322ed21e0bb64812ced0673a48 --- /dev/null +++ b/core/qa/CbmQaTable.h @@ -0,0 +1,90 @@ +/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergey Gorbunov, Sergei Zharko [committer] */ + +/// \file CbmQaTable.h +/// \brief Definition of CbmQaTable class +/// \author Sergei Zharko +/// \data 24.03.2022 +/// +/// Provides a ROOT Class to handle a numeric table +/// + +#ifndef CbmQaTable_h +#define CbmQaTable_h 1 +#include "TROOT.h" +#include "TH2D.h" + +#include <fstream> +#include <string> + +// TODO: We need a method, which sets and gets cell values! (S.Zharko) + +class CbmQaTable: public TH2D { +public: + // + // CONSTRUCTORS AND DESTRUCTORS + // + /// Default constructor + CbmQaTable(): TH2D() {} + /// Constructor from number of rows and columns + CbmQaTable(const char* name, const char* title, Int_t nRows, Int_t nCols); + /// Destructor + virtual ~CbmQaTable(); + + /// Dumps table content into a string + std::string ToString() const; + /// Dumps table content into a text file. File open mode is also controllable, for example, use + /// mode = std::ios_base::app to append the table into an existing file + void ToTextFile(const std::string& fileName, std::ios_base::openmode mode = std::ios_base::out) const; + + // + // GETTERS + // + /// Gets cell content. Please mind, that the signature and result of this function is different to TH2D::GetBinContent + Double_t GetCell(Int_t iRow, Int_t iCol) const; + /// Gets cell error. Please mind, that the signature and result of this function is different to TH2D::GetBinError + Double_t GetCellError(Int_t iRow, Int_t iCol) const; + /// Sets number of rows + Int_t GetNrows() const { return fNrows; } + /// Sets number of columns + Int_t GetNcols() const { return fNcols; } + /// Sets cell content and error. Please mind, that the signature and result of this function + /// is different to TH2D::SetBinContent and TH2D::SetBinError + void SetCell(Int_t iRow, Int_t iCol, Double_t content, Double_t error = 0.); + /// Sets the names of table columns + void SetNamesOfCols(const std::vector<std::string>& names); + /// Sets the names of table rows + void SetNamesOfRows(const std::vector<std::string>& names); + /// Sets size of the text + void SetTextSize(Float_t size = 0.03); + + + /// Dumps table content into a stream + friend std::ostream& operator<<(std::ostream& out, const CbmQaTable& aTable); + +private: + // Forbid methods for direct access to the bins + using TH2D::GetBinContent; + using TH2D::GetBinError; + using TH2D::SetBinContent; + using TH2D::SetBinError; + + + // Structural fields + Int_t fNcols {0}; ///< number of columns in a table + Int_t fNrows {0}; ///< number of rows in a table + + // Some hard-coded constants + static constexpr Float_t kDefaultTextSize {0.03}; ///< default size of text + static constexpr Style_t kDefaultFontStyle {62}; ///< default text style + + static constexpr Int_t kDefaultSetwPar {12}; ///< default size of entry in std::setw() for columns + static constexpr Int_t kRowTitlesSetwPar {30}; ///< size of entry in std::setw() for row titles + static constexpr Int_t kValuesPrecision {3}; ///< precision of output parameters + // TODO: Apply this precision and other options to graphical verion of the table + + ClassDef(CbmQaTable, 1); +}; + +#endif // CbmQaTable_h