diff --git a/core/qa/checker/CbmQaCheckerCore.cxx b/core/qa/checker/CbmQaCheckerCore.cxx
index 2f832c1bc4231d6108146a84722042aaeaf4412f..193648d1f32b08f6a00eee39e5a19c8650d3317b 100644
--- a/core/qa/checker/CbmQaCheckerCore.cxx
+++ b/core/qa/checker/CbmQaCheckerCore.cxx
@@ -44,23 +44,46 @@ void Core::RegisterOutFile(const char* filename)
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-void Core::Process(Option_t* opt)
+int Core::Process(Option_t* opt)
 {
   // ----- Init the object database
   fpObjDB->Init();
 
   PrepareOutputFile();
 
-  // ----- Process datasets and files
   int nDatasets = fpObjDB->GetNofDatasets();
+  int nFiles    = fpObjDB->GetNofFiles();
+  int nVersions = fpObjDB->GetNofVersions();
+
+  std::vector<ECmpInference> cmpSummary(nVersions * nFiles * nDatasets, ECmpInference::StronglyEqual);
 
+  // ----- Process datasets and files
   for (int iDS = 0; iDS < nDatasets; ++iDS) {
-    for (int iFile = 0; iFile < fpObjDB->GetNofFiles(); ++iFile) {
+    for (int iFile = 0; iFile < nFiles; ++iFile) {
       // Create and process a file handler
       auto pFileHandler = std::make_unique<FileHandler>(fpObjDB, iDS, iFile);
-      pFileHandler->Process(opt);
+      auto cmpRes       = pFileHandler->Process(opt);
+      for (int iVer = 0; iVer < nVersions; ++iVer) {
+        cmpSummary[nVersions * (iDS * nFiles + iFile) + iVer] = cmpRes[iVer];
+      }
     }  // iFile
   }    // iDS
+
+  ECmpInference res = ECmpInference::StronglyEqual;
+  LOG(info) << "Summary:";
+  for (int iDS{0}; iDS < nDatasets; ++iDS) {
+    LOG(info) << "\tDataset: " << fpObjDB->GetDataset(iDS);
+    for (int iFile{0}; iFile < nFiles; ++iFile) {
+      LOG(info) << "\t\tFile: " << fpObjDB->GetFileLabel(iDS);
+      for (int iVer{0}; iVer < nVersions; ++iVer) {
+        auto versionInference = cmpSummary[nVersions * (iDS * nFiles + iFile) + iVer];
+        LOG(info) << "\t\t\tVersion: " << fpObjDB->GetVersionLabel(iVer)
+                  << " (path: " << fpObjDB->GetInputFileName(iVer, iFile, iDS) << "): " << ToString(versionInference);
+        res = std::max(versionInference, res);
+      }
+    }
+  }
+  return static_cast<int>(res);
 }
 
 // ---------------------------------------------------------------------------------------------------------------------
@@ -80,52 +103,3 @@ void Core::PrepareOutputFile()
   }
   outFile.Close();
 }
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-bool Core::Scan() const
-{
-  LOG(info) << "Core: Scanning comparison result ...";
-  bool res = true;  /// Equal
-  for (int iFile = 0; iFile < fpObjDB->GetNofFiles(); ++iFile) {
-    for (int iObj = 0; iObj < fpObjDB->GetNofObjects(iFile); ++iObj) {
-      for (int iDS = 0; iDS < fpObjDB->GetNofDatasets(); ++iDS) {
-        for (int iVer = 0; iVer < fpObjDB->GetNofVersions(); ++iVer) {
-          // For now we check, if anything has been changed with respect to default. Later one can add a flag to test
-          // compatibility for different levels (for example, two histograms could be obtained from different systems,
-          // or different seeds, but still be consistent).
-          const auto& cmp = fpObjDB->GetCmpResult(iDS, iFile, iObj, iVer);
-          bool bEqual     = true;
-          {
-            std::stringstream msg;
-            constexpr const char* kEqual = "\e[1;32mequal\e[0m";
-            constexpr const char* kDiff  = "\e[1;32mdifferent\e[0m";
-            msg << "Found mismatch: file: " << fpObjDB->GetInputFileName(iVer, iFile, iDS)
-                << ", object: " << fpObjDB->GetObject(iFile, iObj);
-            if (cmp.fbPointByPointTested) {
-              msg << "\tpoint-by-point -> " << (cmp.fbPointByPoint ? kEqual : kDiff);
-              bEqual &= cmp.fbPointByPoint;
-            }
-            if (cmp.fbRatioTested) {
-              bool bOk = (cmp.fRatioLo >= kRatioMin && cmp.fRatioUp <= kRatioMax);
-              msg << "\tratio -> " << (bOk ? kEqual : kDiff) << "(lo: " << cmp.fRatioLo << ", up: " << cmp.fRatioUp
-                  << ')';
-              bEqual &= bOk;
-            }
-            if (cmp.fbChi2Tested) {
-              bool bOk = cmp.fPval >= kPvalThrsh;
-              msg << "\tchi2 test -> " << (bOk ? kEqual : kDiff) << "(p-val: " << cmp.fPval << ')';
-              bEqual &= bOk;
-            }
-            if (!bEqual) {
-              LOG(info) << msg.str();
-            }
-          }
-        }  // iVer
-      }    // iDS
-    }      // iObj
-  }        // iFile
-  LOG(info) << "Core: Scanning comparison result ... done";
-
-  return res;
-}
diff --git a/core/qa/checker/CbmQaCheckerCore.h b/core/qa/checker/CbmQaCheckerCore.h
index a86d2c29490d07698ccaf466f17d0e86e526e8d0..d15a1c5310b3ab5702dc5cab3acb20b6595957ed 100644
--- a/core/qa/checker/CbmQaCheckerCore.h
+++ b/core/qa/checker/CbmQaCheckerCore.h
@@ -66,23 +66,15 @@ namespace cbm::qa::checker
     ///             "P": enables bin-by-bin comparison
     ///             "S": enables statistical hypothesis test, where is possible
     ///             "U": enables interval comparison, where is possible
-    void Process(Option_t* opt = "P");
+    /// @return 0:  All versions are identical
+    /// @return 1:  Some checks for some histograms did not pass, but the histograms are consistent
+    /// @return 2:  Some histograms are different
+    int Process(Option_t* comparisonMethod = "P");
 
     /// @brief Registers root-file for storing output
     /// @param filename  Name of file
     void RegisterOutFile(const char* filename);
 
-    /// @brief Scans comparison results
-    /// @return  Comparison flag:
-    ///          - true:  All histograms are the same under conditions
-    ///          - false: Some of the histograms were changed
-    bool Scan() const;
-
-    /// @brief Sets control flag
-    /// @param flag   Flag label
-    /// @param value  Flag value
-    void SetControlBitFlag(EFlagBit flag, bool value = true) { fControlBits[static_cast<int>(flag)] = value; }
-
     /// @brief  Sets default version label
     /// @param  defaultLabel  Name of default label
     ///
@@ -97,18 +89,20 @@ namespace cbm::qa::checker
     /// @param pathName  Relative or absolute root path to input the input directories
     void SetInputRootPath(const char* pathName) { fpObjDB->SetInputRootPath(pathName); }
 
+    /// @brief Sets P-value threshold
+    /// @param pVal  P-value threshold
+    void SetPvalThreshold(float pVal) { fpObjDB->SetPvalThreshold(pVal); }
+
+    /// @brief Sets ratio accepted range
+    /// @param min  Lower boundary
+    /// @param max  Upper boundary
+    void SetRatioRange(float min, float max) { fpObjDB->SetRatioRange(min, max); }
+
    private:
     /// @brief Prepares output file (creates directory structure)
     void PrepareOutputFile();
 
-    // TODO: provide setter/config entry
-    static constexpr float kRatioMin  = 0.95;
-    static constexpr float kRatioMax  = 1.05;
-    static constexpr float kPvalThrsh = 0.05;
-
     std::shared_ptr<ObjectDB> fpObjDB = nullptr;  ///< Database of names
-
-    FlagBitSet_t fControlBits;  ///< Control bit flags
   };
 }  // namespace cbm::qa::checker
 
diff --git a/core/qa/checker/CbmQaCheckerFileHandler.cxx b/core/qa/checker/CbmQaCheckerFileHandler.cxx
index b5cb57de0da0ce5395cf519e05cc609b7a0a4683..5852beb3b73657ccbe59b53ed952df09fa58c02c 100644
--- a/core/qa/checker/CbmQaCheckerFileHandler.cxx
+++ b/core/qa/checker/CbmQaCheckerFileHandler.cxx
@@ -30,6 +30,7 @@
 #include <string>
 
 
+using cbm::qa::checker::ECmpInference;
 using cbm::qa::checker::FileHandler;
 
 // ---------------------------------------------------------------------------------------------------------------------
@@ -77,15 +78,17 @@ TDirectory* FileHandler::CreateNestedDirectory(const std::string& path)
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-void FileHandler::Process(Option_t* opt)
+std::vector<ECmpInference> FileHandler::Process(Option_t* opt)
 {
+  std::vector<ECmpInference> bCmpResult;
   int nObjects  = fpObjDB->GetNofObjects(fFileID);
   int nVersions = fpObjDB->GetNofVersions();
+  bCmpResult.resize(nVersions, ECmpInference::StronglyEqual);
 
   // ----- Initial checks
   if (!nObjects) {
     LOG(warn) << "FileHandler: No objects were passed to file \"" << nObjects << ". Skipping file";
-    return;
+    return bCmpResult;
   }
 
   // ----- Option parsing
@@ -94,12 +97,12 @@ void FileHandler::Process(Option_t* opt)
     ch = std::tolower(ch);
   }
   bool bSuppressCanvases = sOption.find("b") != std::string::npos;
-  //bool bForceCanvases    = sOption.find("c") != std::string::npos;
-  bool bCmpPointByPoint  = sOption.find("p") != std::string::npos;
-  bool bCmpStatAny       = sOption.find("s") != std::string::npos;
+  bool bForceCanvases    = sOption.find("c") != std::string::npos;
+  bool bCmpExact         = sOption.find("p") != std::string::npos;
+  bool bCmpChi2          = sOption.find("s") != std::string::npos;
   bool bCmpRatio         = sOption.find("u") != std::string::npos;
 
-  LOG(info) << "FileHandler: processing objects: ";
+  LOG(info) << "FileHandler: processing objects: ...";
   std::vector<TNamed*> vpObjects(nVersions, nullptr);  // vector to keep object different versions
   for (int iObj = 0; iObj < nObjects; ++iObj) {
     bool skipObj = false;
@@ -107,8 +110,8 @@ void FileHandler::Process(Option_t* opt)
       auto* pInputFile = static_cast<TFile*>(fpInputFiles->At(iVer));
       vpObjects[iVer]  = pInputFile->Get<TNamed>(fpObjDB->GetObject(fFileID, iObj).c_str());
       if (!vpObjects[iVer]) {
-        LOG(warn) << "FileHandler: object " << fpObjDB->GetObject(fFileID, iObj) << " is undefined for version "
-                  << fpObjDB->GetVersionLabel(iVer) << ". This object will be skipped";
+        //LOG(warn) << "FileHandler: object " << fpObjDB->GetObject(fFileID, iObj) << " is undefined for version "
+        //          << fpObjDB->GetVersionLabel(iVer) << ". This object will be skipped";
         skipObj = true;
       }
     }  // iVer
@@ -116,13 +119,15 @@ void FileHandler::Process(Option_t* opt)
       continue;
     }
 
-    // Create an instance of an object handler
-    if (iObj != 0 && (20 * iObj) % nObjects == 0) {
+    //
+    if (iObj != 0 && nObjects % 500 == 0) {
       ReOpenOutputFile();
-      LOG(info) << "FileHandler: processing object " << iObj << " of " << nObjects;
+      LOG(info) << "FileHandler: object " << iObj << " / " << nObjects;
     }
+
+    // Create an instance of an object handler
     std::unique_ptr<ObjectHandler> pObjHandler = nullptr;
-    LOG(info) << "FileHandler: processing object \"" << vpObjects[0]->GetName() << '\"';
+    //LOG(info) << "FileHandler: processing object \"" << vpObjects[0]->GetName() << '\"';
     if (dynamic_cast<TProfile*>(vpObjects[0])) {
       pObjHandler = std::make_unique<Profile1DHandler>(iObj, fFileID, fDatasetID);
     }
@@ -138,37 +143,29 @@ void FileHandler::Process(Option_t* opt)
                 << "\", which is unknown to the cbm::qa::checker framework, it will be skipped";
       continue;
     }
-    if (bCmpPointByPoint) {
-      pObjHandler->SetBitFlag(Hist1DHandler::EFlags::kPOINT);  // Compare point-by-point (exact equality)
+    if (bCmpExact) {
+      pObjHandler->SetComparisonMethod(ECmpMethod::Exact);  // Compare point-by-point (exact equality)
     }
-    if (bCmpStatAny) {
-      pObjHandler->SetBitFlag(Hist1DHandler::EFlags::kCHI2);  // Compare with chi2 test
+    if (bCmpChi2) {
+      pObjHandler->SetComparisonMethod(ECmpMethod::Chi2);  // Compare with chi2 test
     }
     if (bCmpRatio) {
-      pObjHandler->SetBitFlag(Hist1DHandler::EFlags::kRATIO);
+      pObjHandler->SetComparisonMethod(ECmpMethod::Ratio);
     }
     pObjHandler->SetObjectDB(fpObjDB);
     pObjHandler->SetOutputDirectory(CreateNestedDirectory((fpObjDB->GetObject(fFileID, iObj))));
     pObjHandler->AddObjects(vpObjects);
-    pObjHandler->CompareWithDefault();
+    auto cmpResultObject = pObjHandler->CompareWithDefault();
+    for (int iVer = 0; iVer < nVersions; ++iVer) {
+      bCmpResult[iVer] = std::max(cmpResultObject[iVer], bCmpResult[iVer]);
+    }
 
-    // Create comparison canvas
-    if (!bSuppressCanvases) {
+    if (!bSuppressCanvases
+        && (bForceCanvases || std::any_of(cmpResultObject.begin(), cmpResultObject.end(), [](auto i) {
+              return i != ECmpInference::StronglyEqual;
+            }))) {
       pObjHandler->CreateCanvases(opt);
     }
-
-    // TODO: re-work the suppress and force canvas features
-    //if (!bSuppressCanvases) {
-    //  bool areDifferent = false;
-    //  for (int iVer = 0; iVer < nVersions; ++iVer) {
-    //    if (fpObjDB->GetCmpResult(fDatasetID, fFileID, iObj, iVer)) {
-    //      areDifferent = true;
-    //    }
-    //  }
-    //  if (areDifferent || bForceCanvases) {
-    //    pObjHandler->CreateCanvases(opt);
-    //  }
-    //}
     pObjHandler->Write();
     gFile->Flush();
 
@@ -180,6 +177,8 @@ void FileHandler::Process(Option_t* opt)
       }
     }
   }  // iObj
+  LOG(info) << "FileHandler: processing objects: done";
+  return bCmpResult;
 }
 
 // ---------------------------------------------------------------------------------------------------------------------
@@ -187,6 +186,7 @@ void FileHandler::Process(Option_t* opt)
 void FileHandler::ReOpenOutputFile()
 {
   if (fpOutputFile.get()) {
+    fpOutputFile->Flush();
     fpOutputFile->Close();
     fpOutputFile = nullptr;
     fpOutDir     = nullptr;
diff --git a/core/qa/checker/CbmQaCheckerFileHandler.h b/core/qa/checker/CbmQaCheckerFileHandler.h
index c8128b0f2ced4c4ceeffce721dafdea78d0a5011..ca678bcbcb8c044ce26959828175ba8563ffd635 100644
--- a/core/qa/checker/CbmQaCheckerFileHandler.h
+++ b/core/qa/checker/CbmQaCheckerFileHandler.h
@@ -62,7 +62,8 @@ namespace cbm::qa::checker
     ///             "P": enables bin-by-bin comparison
     ///             "S": enables statistical hypothesis test, where is possible
     ///             "U": enables interval comparison
-    void Process(Option_t* opt = "");
+    /// @return  a vector of comparison inferences (for each version)
+    std::vector<ECmpInference> Process(Option_t* opt = "");
 
    private:
     /// @brief Creates nested directory from a given path
diff --git a/core/qa/checker/CbmQaCheckerHist1DHandler.cxx b/core/qa/checker/CbmQaCheckerHist1DHandler.cxx
index c2263f051bf345b7dac5758f39e7cf6cd7ae6664..6b6056c61444f4963def433ad1df6039945bc763 100644
--- a/core/qa/checker/CbmQaCheckerHist1DHandler.cxx
+++ b/core/qa/checker/CbmQaCheckerHist1DHandler.cxx
@@ -25,7 +25,7 @@
 #include <bitset>
 #include <limits>
 
-using cbm::qa::checker::CmpResult;
+using cbm::qa::checker::ECmpInference;
 using cbm::qa::checker::Hist1DHandler;
 
 // ---------------------------------------------------------------------------------------------------------------------
@@ -37,77 +37,134 @@ Hist1DHandler::Hist1DHandler(int iObject, int iFile, int iDataset) : ObjectHandl
 
 
 // ---------------------------------------------------------------------------------------------------------------------
-//
-CmpResult Hist1DHandler::Compare(const TNamed* pNum, const TNamed* pDenom) const
+// TODO: move somewhere else (probably unite with the CbmQaCompare in a future merger request)
+ECmpInference Hist1DHandler::Compare(int iVersion) const
 {
-  CmpResult res;
-  auto* pNumerator   = static_cast<const TH1*>(pNum);
-  auto* pDenominator = static_cast<const TH1*>(pDenom);
+  auto* pNumerator   = static_cast<const TH1*>(fvpObjects[iVersion]);
+  auto* pDenominator = static_cast<const TH1*>(fvpObjects[fpObjDB->GetDefaultID()]);
   if (pNumerator->GetNbinsX() != pDenominator->GetNbinsX() || pNumerator->GetNbinsY() != pDenominator->GetNbinsY()
       || pNumerator->GetNbinsZ() != pDenominator->GetNbinsZ()) {
-    // TODO: Provide an appropriate case handling
-    return res;
+    return ECmpInference::Different;
   }
 
-  res.fbPointByPointTested = fOptionBits[EFlags::kPOINT];
-  res.fbRatioTested        = fOptionBits[EFlags::kRATIO];
-  res.fbChi2Tested         = fOptionBits[EFlags::kCHI2];
+  bool bCompareExact{fCmpBits[static_cast<uint8_t>(ECmpMethod::Exact)]};
+  bool bCompareRatio{fCmpBits[static_cast<uint8_t>(ECmpMethod::Ratio)]};
+  bool bCompareChi2{fCmpBits[static_cast<uint8_t>(ECmpMethod::Chi2)]};
 
-  if (res.fbPointByPointTested || res.fbRatioTested) {
-    res.fbPointByPoint = res.fbPointByPointTested;
-    if (res.fbRatioTested) {
-      res.fRatioLo = 1.;
-      res.fRatioUp = 1.;
-    }
-    for (int iBinX = 0; iBinX <= pNumerator->GetNbinsX(); ++iBinX) {
-      for (int iBinY = 0; iBinY <= pNumerator->GetNbinsY(); ++iBinY) {
-        for (int iBinZ = 0; iBinZ <= pNumerator->GetNbinsZ(); ++iBinZ) {
-          auto numBinContent = pNumerator->GetBinContent(iBinX, iBinY, iBinZ);
-          auto denBinContent = pDenominator->GetBinContent(iBinX, iBinY, iBinZ);
-          float ratio        = res.fbRatioTested ? static_cast<double>(numBinContent) / denBinContent
-                                                 : std::numeric_limits<float>::signaling_NaN();
+  bool bEqualExactly{true};
+  bool bEqualByRatio{true};
+
+  double ratioLo{1.};
+  double ratioUp{1.};
+
+  if (bCompareExact || bCompareRatio) {
+    bool bRatioMayBeWrong =
+      false;  // handling a case, when the histograms contain different empty bins, but the ratio remains 1
+    for (int iBinX{0}; iBinX <= pNumerator->GetNbinsX(); ++iBinX) {
+      for (int iBinY{0}; iBinY <= pNumerator->GetNbinsY(); ++iBinY) {
+        for (int iBinZ{0}; iBinZ <= pNumerator->GetNbinsZ(); ++iBinZ) {
+          auto numBinContent{pNumerator->GetBinContent(iBinX, iBinY, iBinZ)};
+          auto denBinContent{pDenominator->GetBinContent(iBinX, iBinY, iBinZ)};
+          double ratio{static_cast<double>(numBinContent) / denBinContent};
           // Check bin content
           if (!TMath::IsNaN(numBinContent) && !TMath::IsNaN(denBinContent)) {
             if (numBinContent != denBinContent) {
-              res.fbPointByPoint = false;
-              if (res.fbRatioTested) {
-                res.fRatioLo = std::min(res.fRatioLo, ratio);
-                res.fRatioUp = std::max(res.fRatioUp, ratio);
+              bEqualExactly = false;
+              if (bCompareRatio) {
+                bool numEmpty{numBinContent < 1.e-4};
+                bool denEmpty{denBinContent < 1.e-4};
+                if (numEmpty || denEmpty) {
+                  bRatioMayBeWrong &= (!numEmpty || !denEmpty);
+                  continue;  // Ignoring empty bin in ratio estimation (but only, if it is empty in both histograms)
+                }
+                ratioLo = std::min(ratioLo, ratio);
+                ratioUp = std::max(ratioUp, ratio);
               }
             }
           }
           else {
             if (TMath::IsNaN(numBinContent) != TMath::IsNaN(denBinContent)) {
-              res.fbPointByPoint = false;
+              bEqualExactly = false;
             }
           }
-          auto numBinError = pNumerator->GetBinError(iBinX, iBinY, iBinZ);
-          auto denBinError = pDenominator->GetBinError(iBinX, iBinY, iBinZ);
+          auto numBinError{pNumerator->GetBinError(iBinX, iBinY, iBinZ)};
+          auto denBinError{pDenominator->GetBinError(iBinX, iBinY, iBinZ)};
           // Check bin error
           if (!TMath::IsNaN(numBinError) && !TMath::IsNaN(denBinError)) {
             if (numBinError != denBinError) {
-              res.fbPointByPoint = false;
+              bEqualExactly = false;
             }
           }
           else {
             if (TMath::IsNaN(numBinError) != TMath::IsNaN(denBinError)) {
-              res.fbPointByPoint = false;
+              bEqualExactly = false;
             }
           }
         }
       }
     }
+
+    if (bCompareExact && bEqualExactly) {
+      return ECmpInference::StronglyEqual;  // chi2 and ratio tests can be ignored
+    }
+
+    if (bRatioMayBeWrong && (std::fabs(1 - 1.e-4) < ratioLo) && std::fabs(1 + 1.e+4) > ratioUp) {
+      LOG(warn) << "Hist1DHandler::Compare: file " << fpObjDB->GetInputFileName(fDatasetID, fFileID, 0)
+                << ", object: " << pNumerator->GetName()
+                << " has a ratio equal to 1., but some of bins are still different "
+                << "(empty/non-empty bin case)";
+    }
+
+    if (bCompareRatio) {
+      bEqualByRatio = (ratioLo >= fpObjDB->GetRatioRangeMin() && ratioUp <= fpObjDB->GetRatioRangeMax());
+    }
   }
 
-  if (res.fbPointByPoint) {
-    res.fRatioLo      = std::numeric_limits<float>::signaling_NaN();
-    res.fRatioUp      = std::numeric_limits<float>::signaling_NaN();
-    res.fbChi2Tested  = false;
-    res.fbRatioTested = false;
+  bool bEqualByChi2{true};
+  double pVal{0.};
+  if (bCompareChi2) {  // perform only, if the histograms were different
+    auto currErrorLevel{gErrorIgnoreLevel};
+    gErrorIgnoreLevel = kFatal;
+    double chi2{0.};
+    int ndf{0};
+    int igood{0};
+    pVal              = pDenominator->Chi2TestX(pNumerator, chi2, ndf, igood);
+    bEqualByChi2      = (pVal >= fpObjDB->GetPvalThreshold());
+    gErrorIgnoreLevel = currErrorLevel;
   }
 
-  if (res.fbChi2Tested) {  // perform only, if the histograms were different
-    res.fPval = pDenominator->Chi2Test(pNumerator, "P");
+  // Do not account for method, if it was not required
+  // strongly eq = (!bCmp_0 v bEq_0) ^ (!bCmp_1 v bEq_1) ^ .. ^ (!bCmp_N v bEq_N)
+  // weakly eq   = (!bCmp_0 v bEq_0) v (!bCmp_1 v bEq_1) v .. v (!bCmp_N v bEq_N)
+  bEqualExactly       = !bCompareExact || bEqualExactly;
+  bEqualByRatio       = !bCompareRatio || bEqualByRatio;
+  bEqualByChi2        = !bCompareChi2 || bEqualByChi2;
+  bool bEqualStrongly = bEqualExactly && bEqualByRatio && bEqualByChi2;
+  bool bEqualWeakly   = bEqualExactly || bEqualByRatio || bEqualByChi2;
+  ECmpInference res   = bEqualStrongly ? ECmpInference::StronglyEqual
+                                       : (bEqualWeakly ? ECmpInference::WeaklyEqual : ECmpInference::Different);
+
+  if (ECmpInference::StronglyEqual != res) {
+    auto ResultMsg = [](bool flag) -> std::string {
+      constexpr const char* kEqual = "\e[1;32mconsistent\e[0m";
+      constexpr const char* kDiff  = "\e[1;31minconsistent\e[0m";
+      return flag ? kEqual : kDiff;
+    };
+    std::stringstream msg;
+    msg << "Found mismatch: file: " << fpObjDB->GetInputFileName(iVersion, fFileID, fDatasetID)
+        << ", object: " << fpObjDB->GetObject(fFileID, fObjectID) << "\n";
+    if (bCompareExact) {
+      msg << "\texact -> " << ResultMsg(bEqualExactly) << '\n';
+    }
+    if (bCompareRatio) {
+      msg << "\tratio -> " << ResultMsg(bEqualByRatio) << "(lo: " << ratioLo << ", up: " << ratioUp << ")\n";
+    }
+    if (bCompareChi2) {
+      msg << "\tchi2 ->  " << ResultMsg(bEqualByChi2) << "(p-val: " << pVal << ")\n";
+    }
+    msg << "Inference: " << ToString(res);
+
+    LOG(info) << msg.str();
   }
 
   return res;
diff --git a/core/qa/checker/CbmQaCheckerHist1DHandler.h b/core/qa/checker/CbmQaCheckerHist1DHandler.h
index 714c46cee7fedbc84d2ac62545347b2935261448..3d3c4d99f8e6907143186459d5824d552ba5febe 100644
--- a/core/qa/checker/CbmQaCheckerHist1DHandler.h
+++ b/core/qa/checker/CbmQaCheckerHist1DHandler.h
@@ -28,14 +28,6 @@ namespace cbm::qa::checker
   ///
   class Hist1DHandler : public ObjectHandler {
    public:
-    /// Enumeration for bit-flags of different comparison methods
-    enum EFlags
-    {
-      kPOINT,  ///< Point-by-point exact comparison
-      kRATIO,  ///< Comparison within of ratio difference from unity
-      kCHI2    ///< Statistical hypothesis test using chi2 test
-    };
-
     /// @brief Constructor
     /// @param iObject  Index of object
     /// @param iFile    Index of file
@@ -45,18 +37,14 @@ namespace cbm::qa::checker
     /// @brief Destructor
     ~Hist1DHandler() = default;
 
+    /// @brief Compares objects to default
+    /// @param iVersion     Version index
+    /// @return  Comparison inference
+    ECmpInference Compare(int iVersion) const override;
+
     /// @brief Creates object comparison canvas
     /// @param opt  Canvas options
     void CreateCanvases(Option_t* opt = "") override;
-
-    /// @brief Compares objects to default
-    /// @param pNum    Pointer to "numerator" object
-    /// @param pDenom  Pointer to "denominator" object
-    /// @return  Comparison result
-    ///
-    /// The function provides comparison of objects and stores the comparison result in the field of the ObjectDB
-    /// instance for a given version, file, object and dataset ids.
-    CmpResult Compare(const TNamed* pNum, const TNamed* pDenom) const override;
   };
 }  // namespace cbm::qa::checker
 
diff --git a/core/qa/checker/CbmQaCheckerObjectDB.cxx b/core/qa/checker/CbmQaCheckerObjectDB.cxx
index 87853e20d7aad87af91dfb3e5e31f14e74ac902e..9328a28449a8088f0633cc2978cd2032bdb71291 100644
--- a/core/qa/checker/CbmQaCheckerObjectDB.cxx
+++ b/core/qa/checker/CbmQaCheckerObjectDB.cxx
@@ -34,7 +34,6 @@ void ObjectDB::Clear()
   fvVersionLabels.clear();
   fvVersionPaths.clear();
   fvObjectFirstGlobIndex.clear();
-  fvCmpResults.clear();
 }
 
 // ---------------------------------------------------------------------------------------------------------------------
@@ -94,7 +93,6 @@ void ObjectDB::Init()
     LOG(warn) << "ObjectDB: default version was not registered. Using the first version as the default one (\""
               << fvVersionLabels[fDefVersionID] << "\")";
   }
-  LOG(info) << this->ToString();
 
   // ----- Read object list from file
   for (size_t iFile = 0; iFile < fvObjects.size(); ++iFile) {
@@ -103,6 +101,8 @@ void ObjectDB::Init()
     }
   }
 
+  LOG(info) << this->ToString();
+
   // ----- Init the object index vector
   fvObjectFirstGlobIndex.clear();
   fvObjectFirstGlobIndex.resize(fvObjects.size() + 1, 0);
@@ -110,9 +110,6 @@ void ObjectDB::Init()
     fvObjectFirstGlobIndex[iFile] = fvObjectFirstGlobIndex[iFile - 1] + fvObjects[iFile - 1].size();
   }
 
-  // ----- Reserve space for object comparison results
-  fvCmpResults.resize(fvVersionLabels.size() * fvObjectFirstGlobIndex.back() * fvDatasets.size());
-
   // ----- Add root path of input, if it were defined
   auto regexSlashes = std::regex("(/+)");  // regular expression for a sequence of consecutive slashes
   for (auto& path : fvVersionPaths) {
@@ -269,31 +266,40 @@ void ObjectDB::ReadObjectList(int iFile)
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-std::string ObjectDB::ToString() const
+std::string ObjectDB::ToString(int verbose) const
 {
   std::stringstream msg;
-  msg << "*** CBM QA-Checker: defined files ****\n\n";
-
-  msg << "----- Versions:\n";
-  for (size_t iV = 0; iV < fvVersionLabels.size(); ++iV) {
-    if (iV == (size_t) fDefVersionID) {
-      msg << "\033[1;32m- " << fvVersionLabels[iV] << " (path: " << fvVersionPaths[iV] << ")\n ---> DEFAULT\033[0m";
+  if (verbose > 0) {
+    msg << '\n';
+    msg << "  ********************\n";
+    msg << "  ** CBM QA-Checker **\n";
+    msg << "  ********************\n\n";
+
+    msg << "\e[1mVersions\e[0m:\n";
+    for (size_t iV = 0; iV < fvVersionLabels.size(); ++iV) {
+      if (iV == (size_t) fDefVersionID) {
+        msg << "\t- " << fvVersionLabels[iV] << " (path: " << fvVersionPaths[iV] << ") -> \e[1;33mDEFAULT\e[0m\n";
+      }
+      else {
+        msg << "\t- " << fvVersionLabels[iV] << " (path: " << fvVersionPaths[iV] << ")\n";
+      }
     }
-    else {
-      msg << "- " << fvVersionLabels[iV] << " (path: " << fvVersionPaths[iV] << ")\n";
+    msg << "\e[1mDatasets\e[0m:\n";
+    for (const auto& dataset : fvDatasets) {
+      msg << "\t- " << dataset << "\n";
     }
-  }
-
-  msg << "----- Datasets:\n";
-  for (const auto& dataset : fvDatasets) {
-    msg << "- \033[1m" << dataset << "\033[0m\n";
-  }
-
-  msg << "----- Objects\n";
-  for (size_t iF = 0; iF < fvFiles.size(); ++iF) {
-    msg << "- \033[1m" << fvFiles[iF] << "\033[0m\n";
-    for (const auto& object : this->GetObjects(iF)) {
-      msg << "\t- " << object << '\n';
+    msg << "\e[1mFiles\e[0m:\n";
+    for (size_t iF = 0; iF < fvFiles.size(); ++iF) {
+      msg << "\t- " << fvFiles[iF];
+      if (verbose > 1) {
+        msg << " with objects:\n";
+        for (const auto& object : fvObjects[iF]) {
+          msg << "\t\t- " << object << '\n';
+        }
+      }
+      else {
+        msg << '\n';
+      }
     }
   }
   return msg.str();
diff --git a/core/qa/checker/CbmQaCheckerObjectDB.h b/core/qa/checker/CbmQaCheckerObjectDB.h
index f5e81503192b8d6f1b245776470715a673058d54..fecf0f49fcb422c53d37c0fb057b1d3b023acfaa 100644
--- a/core/qa/checker/CbmQaCheckerObjectDB.h
+++ b/core/qa/checker/CbmQaCheckerObjectDB.h
@@ -71,28 +71,7 @@ namespace cbm::qa::checker
     /// @return  Label of file
     const std::string& GetFileLabel(int iFile) const { return fvFileLabels[iFile]; }
 
-   private:
-    /// @brief Gets iterator range for object names stored in a file
-    /// @note  The iterator_range object behaves itself just like an ordinary STL container.
-    /// @param iFile  Index of file
-    /// @return  iterator_range for ROOT objects of this file
-    /// TODO: Understand, which type is deduced
-    const std::vector<std::string>& GetObjects(int iFile) const { return fvObjects[iFile]; }
-
    public:
-    /// @brief Gets comparison result
-    /// @param iDS    Index of dataset
-    /// @param iFile  Index of file
-    /// @param iObj   Index of object within the file
-    /// @param iVer   Index of version
-    /// @return  Value of comparison result
-    const CmpResult& GetCmpResult(int iDS, int iFile, int iObj, int iVer) const
-    {
-      int iObjGlob = fvObjectFirstGlobIndex[iFile] + iObj;
-      int iRes     = iVer + fvVersionLabels.size() * (iObjGlob + iDS * fvObjectFirstGlobIndex.back());
-      return fvCmpResults[iRes];
-    }
-
     /// @brief Gets name of file from indexes of version, file and dataset
     /// @param iVersion  Index of version
     /// @param iFile     Index of file
@@ -104,7 +83,7 @@ namespace cbm::qa::checker
     /// @param iFile    Index of file
     /// @param iObject  Index of object for a given file
     /// @return  Name of object
-    const std::string& GetObject(int iFile, int iObject) const { return GetObjects(iFile)[iObject]; }
+    const std::string& GetObject(int iFile, int iObject) const { return fvObjects[iFile][iObject]; }
 
     /// @brief Gets number of datasets
     int GetNofDatasets() const { return fvDatasets.size(); }
@@ -114,7 +93,7 @@ namespace cbm::qa::checker
 
     /// @brief Gets number of objects in file
     /// @param iFile  Index of file
-    int GetNofObjects(int iFile) const { return GetObjects(iFile).size(); }
+    int GetNofObjects(int iFile) const { return fvObjects[iFile].size(); }
 
     /// @brief Gets number of files
     int GetNofFiles() const { return fvFiles.size(); }
@@ -125,6 +104,15 @@ namespace cbm::qa::checker
     /// @brief Gets output path
     const std::string& GetOutputPath() const { return fsOutputPath; }
 
+    /// @brief Gets p-value threshold
+    double GetPvalThreshold() const { return fPvalThresh; }
+
+    /// @brief Gets upper bound of the accepted ratio range
+    double GetRatioRangeMax() const { return fRatioMax; }
+
+    /// @brief Gets lower bound of the accepted ratio range
+    double GetRatioRangeMin() const { return fRatioMin; }
+
     /// @brief Gets version label
     /// @param iVersion  Index of version
     const std::string& GetVersionLabel(int iVersion) const { return fvVersionLabels[iVersion]; }
@@ -140,22 +128,13 @@ namespace cbm::qa::checker
     /// @param config Root node of the YAML file
     void ReadFromYAML(const char* configName);
 
-    /// @brief Saves content to string
+    /// @brief String representation of the content
+    /// @param  verbose  Verbosity level:
+    ///                    0: no output,
+    ///                    1: minimal output (versions, datasets and file names),
+    ///                    2: objects as well
     /// @return A string representation of the DB contents
-    std::string ToString() const;
-
-    /// @brief Sets comparison result
-    /// @param iDS    Index of dataset
-    /// @param iFile  Index of file
-    /// @param iObj   Index of object within the file
-    /// @param iVer   Index of version
-    /// @param value  Value of comparison result
-    void SetCmpResult(int iDS, int iFile, int iObj, int iVer, CmpResult value)
-    {
-      int iObjGlob       = fvObjectFirstGlobIndex[iFile] + iObj;
-      int iRes           = iVer + fvVersionLabels.size() * (iObjGlob + iDS * fvObjectFirstGlobIndex.back());
-      fvCmpResults[iRes] = value;
-    }
+    std::string ToString(int verbose = 1) const;
 
     /// @brief  Sets default version label
     /// @param  defaultLabel  Name of default label
@@ -172,6 +151,19 @@ namespace cbm::qa::checker
     /// @param path  Path to the output ROOT-file
     void SetOutputPath(const char* path) { fsOutputPath = path; }
 
+    /// @brief Sets P-value threshold
+    /// @param pVal  P-value threshold
+    void SetPvalThreshold(float pVal) { fPvalThresh = pVal; }
+
+    /// @brief Sets ratio accepted range
+    /// @param min  Lower boundary
+    /// @param max  Upper boundary
+    void SetRatioRange(float min, float max)
+    {
+      fRatioMin = min;
+      fRatioMax = max;
+    }
+
    private:
     /// @brief Reads list of histograms from file
     /// @param iFile  Index of file
@@ -198,7 +190,10 @@ namespace cbm::qa::checker
     std::vector<std::vector<std::string>> fvObjects;  ///< Container of object names vs file id
     std::vector<std::string> fvVersionLabels;         ///< Container of version labels
     std::vector<std::string> fvVersionPaths;          ///< Container of version paths
-    std::vector<CmpResult> fvCmpResults;              ///< Comparison results vs. dataset, object and version
+
+    float fPvalThresh{0.05};  ///< P-value threshold for histograms equality
+    float fRatioMax{1.05};    ///< Upper boundary for ratio deviation
+    float fRatioMin{0.95};    ///< Lower boundary for ratio deviation
   };
 }  // namespace cbm::qa::checker
 
diff --git a/core/qa/checker/CbmQaCheckerObjectHandler.cxx b/core/qa/checker/CbmQaCheckerObjectHandler.cxx
index f28573caec5137e8c0b77482b8d1c29ce697bb50..ef9027416fe0e3cc7eafc9acc26327fdc9a3f547 100644
--- a/core/qa/checker/CbmQaCheckerObjectHandler.cxx
+++ b/core/qa/checker/CbmQaCheckerObjectHandler.cxx
@@ -14,15 +14,16 @@
 #include "TDirectory.h"
 #include "TNamed.h"
 
+using cbm::qa::checker::ECmpInference;
 using cbm::qa::checker::ObjectHandler;
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
 ObjectHandler::ObjectHandler(int iObject, int iFile, int iDataset, const char* objType)
-  : fObjectID(iObject)
+  : fsObjType(objType)
+  , fObjectID(iObject)
   , fFileID(iFile)
   , fDatasetID(iDataset)
-  , fsObjType(objType)
 {
 }
 
@@ -66,16 +67,18 @@ void ObjectHandler::AddObjects(const std::vector<TNamed*>& vpObj)
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-void ObjectHandler::CompareWithDefault()
+std::vector<ECmpInference> ObjectHandler::CompareWithDefault()
 {
+  // All object versions are equal to default one (H0)
+  std::vector<ECmpInference> res(fpObjDB->GetNofVersions(), ECmpInference::StronglyEqual);
   int iDef = fpObjDB->GetDefaultID();
   for (int iV = 0; iV < (int) fvpObjects.size(); ++iV) {
     if (iV == iDef) {
       continue;
     }
-    auto res = this->Compare(fvpObjects[iV], fvpObjects[iDef]);
-    fpObjDB->SetCmpResult(fDatasetID, fFileID, fObjectID, iV, res);
+    res[iV] = this->Compare(iV);
   }
+  return res;
 }
 
 // ---------------------------------------------------------------------------------------------------------------------
diff --git a/core/qa/checker/CbmQaCheckerObjectHandler.h b/core/qa/checker/CbmQaCheckerObjectHandler.h
index 8618b618ff08117c0ed3480736b03d5e2fc75531..353ebb5b6aa409594ba7ffdf8585a5c0052e2efe 100644
--- a/core/qa/checker/CbmQaCheckerObjectHandler.h
+++ b/core/qa/checker/CbmQaCheckerObjectHandler.h
@@ -28,7 +28,6 @@ namespace cbm::qa::checker
   ///
   /// The class provides interface for handling objects of the same type, obtained under different versions of the code
   /// base.
-  ///
   class ObjectHandler {
    public:
     /// @brief Default constructor
@@ -49,15 +48,14 @@ namespace cbm::qa::checker
     /// @param opt  Canvas options
     virtual void CreateCanvases(Option_t*){};
 
-    /// @brief Compares two objects with different methods
-    /// @param pNum    Pointer to "numerator" object
-    /// @param pDenom  Pointer to "denominator" object
-    /// @return  Comparison result represented as a bitset in unsigned integer
-    /// TODO: .....
-    virtual CmpResult Compare(const TNamed* pNum, const TNamed* pDenom) const = 0;
+    /// @brief Compares objects to default
+    /// @param iVersion     Version index
+    /// @return  Comparison inference
+    virtual ECmpInference Compare(int iVersion) const = 0;
 
-    /// @brief Compares versions with default and writes result into DB
-    void CompareWithDefault();
+    /// @brief   Compares different versions with default
+    /// @return  Vector of comparison inferences for different versions
+    std::vector<ECmpInference> CompareWithDefault();
 
     /// @brief Sets folder to store output
     /// @param pDir  Pointer to folder instance
@@ -67,34 +65,27 @@ namespace cbm::qa::checker
     /// @param  pObjDB  Shared pointer to object database
     void SetObjectDB(std::shared_ptr<ObjectDB>& pObjDB) { fpObjDB = pObjDB; }
 
-    /// @brief Sets verbose level
-    /// @param verbose  Verbose level:
-    ///                 - 0: Silent mode
-    ///                 - 1:
-    void SetVerbose(int verbose) { fVerbose = verbose; }
-
     /// @brief Sets bit flag to control handler behaviour
     /// @param bit  Bit index
     ///
     /// The bit flags should be defined in an enumeration of the default class
-    void SetBitFlag(uint8_t bit) { fOptionBits.set(bit); }
+    void SetComparisonMethod(ECmpMethod method) { fCmpBits.set(static_cast<uint8_t>(method)); }
 
     /// @brief Writes objects to file
     void Write();
 
    protected:
-    int fObjectID                         = -1;        ///< Index of object
-    int fFileID                           = -1;        ///< Index of file
-    int fDatasetID                        = -1;        ///< Index of dataset
-    int fVerbose                          = 0;         ///< Verbosity level
-    TDirectory* fpOutDir                  = nullptr;   ///< Pointer to directory
-    std::shared_ptr<ObjectDB> fpObjDB     = nullptr;   ///< Pointer to object database
-    std::shared_ptr<TCanvas> fpCanvas     = nullptr;   ///< Comparison canvas
-    std::bitset<4> fOptionBits;                        ///< Bitset for option
-
-    std::string fsObjType  = "";      ///< Base type of the object to be handled
-    std::string fsBaseName = "";      ///< Base names of the object
-    std::vector<TNamed*> fvpObjects;  ///< Vector of objects
+    std::string fsObjType{""};                   ///< Base type of the object to be handled
+    std::string fsBaseName{""};                  ///< Base names of the object
+    std::vector<TNamed*> fvpObjects;             ///< Vector of objects
+    std::shared_ptr<ObjectDB> fpObjDB{nullptr};  ///< Pointer to object database
+    std::shared_ptr<TCanvas> fpCanvas{nullptr};  ///< Comparison canvas
+    TDirectory* fpOutDir{nullptr};               ///< Pointer to directory
+    int fObjectID{-1};                           ///< Index of object
+    int fFileID{-1};                             ///< Index of file
+    int fDatasetID{-1};                          ///< Index of dataset
+
+    std::bitset<static_cast<size_t>(ECmpMethod::END)> fCmpBits;  ///< Bitset for comparison methods
   };
 }  // namespace cbm::qa::checker
 
diff --git a/core/qa/checker/CbmQaCheckerTypedefs.h b/core/qa/checker/CbmQaCheckerTypedefs.h
index 2b120c6176a28ee9e013e4b2674e8e523af30da5..d5474c92fed5c067e72e5b4581fbfba61ddf83b3 100644
--- a/core/qa/checker/CbmQaCheckerTypedefs.h
+++ b/core/qa/checker/CbmQaCheckerTypedefs.h
@@ -20,38 +20,50 @@
 
 namespace cbm::qa::checker
 {
-  /// @brief Enumerations for QA-Checker execution control
-  ///
-  enum class EFlagBit
+  /// @enum  ECmpMethod
+  /// @brief Comparison method
+  enum class ECmpMethod : uint8_t
   {
-    kSKIP_LOST_OBJECTS,  //< Skips objects, which are defined in config, but not presented in file
-    kEND
+    Exact,  ///< exact equality (point-by-point, error-by-error)
+    Ratio,  ///< ratio equality (max and min ratios do not exceed a required range)
+    Chi2,   ///< equality within a chi2 hypothesis test
+    END     ///< end of enumeration
   };
 
-  /// @struct CmpResult
-  /// @brief  Comparison result
-  struct CmpResult {
-    // results
-    float fRatioUp{std::numeric_limits<float>::signaling_NaN()};
-    float fRatioLo{std::numeric_limits<float>::signaling_NaN()};
-    float fPval{std::numeric_limits<float>::signaling_NaN()};
-    bool fbPointByPoint{false};  // non-equal
-    // if test was performed
-    bool fbPointByPointTested{false};
-    bool fbRatioTested{false};
-    bool fbChi2Tested{false};
+  /// @enum  ECmpInference
+  /// @brief The object comparison inference
+  /// @note  The sequence of the elements is important, please, do not shuffle!
+  enum class ECmpInference : uint8_t
+  {
+    StronglyEqual = 0,  ///< All the comparison methods gave equality
+    WeaklyEqual,        ///< At least one of the comparison methods showed equality
+    Different           ///< Neither of the comparison methods showed equality
   };
 
-  // ----- Aliases
+  /// @brief  String representation of the ECmpInference enum
+  inline std::string ToString(ECmpInference inference)
+  {
+    switch (inference) {
+      case ECmpInference::StronglyEqual: return "\e[1;32msame\e[0m";
+      case ECmpInference::WeaklyEqual: return "\e[1;33mconsistent\e[0m";
+      case ECmpInference::Different: return "\e[1;31mdifferent\e[0m";
+      default: return "";
+    }
+  }
+
+  // Aliases
   using MapStrToStr_t     = std::unordered_map<std::string, std::string>;
   using MapStrToStrVect_t = std::unordered_map<std::string, std::vector<std::string>>;
-  using FlagBitSet_t      = std::bitset<static_cast<int>(EFlagBit::kEND)>;
 
   template<class T>
   using VectRange_t = boost::iterator_range<typename std::vector<T>::iterator>;
 
-  // ----- Constants
-  constexpr double kLegendSize[2] = {.3, .05};  // width and height in % of the pad size
+  // Constants
+  constexpr double kLegendSize[2] = {.3, .05};  ///< width and height in % of the pad size
+  constexpr float kRatioMin       = 0.95;       ///< Minimal acceptable ratio
+  constexpr float kRatioMax       = 1.05;       ///< Maximal acceptable ratio
+  constexpr float kPvalThrsh      = 0.05;       ///< P-value threshold
+
 
 }  // namespace cbm::qa::checker
 
diff --git a/macro/qa/qa_compare.C b/macro/qa/qa_compare.C
index d5cda2386a92d94cf3dbc3c5783300679ec45b5b..1323ff04f9ec573c483f1e33c45da662e883fe08 100644
--- a/macro/qa/qa_compare.C
+++ b/macro/qa/qa_compare.C
@@ -50,10 +50,7 @@ int qa_compare(
   pQaChecker->SetDefaultVersion("old");
 
   //// ----- Run comparision routine
-  pQaChecker->Process("P");
-
-  //// ----- Scan results
-  bool res = pQaChecker->Scan();  // true - objects are the same, false - objects differ
+  bool res = pQaChecker->Process("P");
   std::cout << "Macro finished successfully." << std::endl;
-  return !res;
+  return res;
 }
diff --git a/macro/qa/qa_compare_ca.C b/macro/qa/qa_compare_ca.C
index ddb750158a839df51c2040e3433076b142bfa2e9..ea2530bb38604be0fbe7b67554545cf8efe191a7 100644
--- a/macro/qa/qa_compare_ca.C
+++ b/macro/qa/qa_compare_ca.C
@@ -36,10 +36,7 @@ int qa_compare_ca(
   pQaChecker->SetFromYAML(configName);      // Read file-object map
 
   //// ----- Run comparision routine
-  pQaChecker->Process("PRC");  // P -
-
-  //// ----- Scan results
-  bool res = pQaChecker->Scan();  // true - objects are the same, false - objects differ
+  int res = pQaChecker->Process("UPS");
   std::cout << "Macro finished successfully." << std::endl;
-  return !res;
+  return res;
 }