From 2353555748f95fda7eac3fe8d5458d2ad37fcfc9 Mon Sep 17 00:00:00 2001
From: "s.zharko@gsi.de" <s.zharko@gsi.de>
Date: Tue, 29 Mar 2022 15:47:23 +0200
Subject: [PATCH] QA: CbmQaTable class added

---
 core/qa/CMakeLists.txt     |   2 +
 core/qa/CbmQaBaseLinkDef.h |   1 +
 core/qa/CbmQaTable.cxx     | 169 +++++++++++++++++++++++++++++++++++++
 core/qa/CbmQaTable.h       |  90 ++++++++++++++++++++
 4 files changed, 262 insertions(+)
 create mode 100644 core/qa/CbmQaTable.cxx
 create mode 100644 core/qa/CbmQaTable.h

diff --git a/core/qa/CMakeLists.txt b/core/qa/CMakeLists.txt
index aaa8e0a0f2..04d6c2b8dd 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 c17d1514d6..9da99d54d5 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 0000000000..19d005d577
--- /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 0000000000..218191655f
--- /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
-- 
GitLab