diff --git a/DataFormats/Detectors/CTP/include/DataFormatsCTP/Scalers.h b/DataFormats/Detectors/CTP/include/DataFormatsCTP/Scalers.h index 526e79f00f65d..aaa60a17456ab 100644 --- a/DataFormats/Detectors/CTP/include/DataFormatsCTP/Scalers.h +++ b/DataFormats/Detectors/CTP/include/DataFormatsCTP/Scalers.h @@ -93,6 +93,7 @@ class CTPRunScalers void printFromZero(std::ostream& stream) const; void printClasses(std::ostream& stream) const; std::vector getClassIndexes() const; + int getScalerIndexForClass(int cls) const; std::vector& getScalerRecordO2() { return mScalerRecordO2; }; int readScalers(const std::string& rawscalers); int convertRawToO2(); @@ -106,7 +107,9 @@ class CTPRunScalers int printRates(); int printIntegrals(); int printInputRateAndIntegral(int inp); - int printClassBRateAndIntegral(int icls); + int printClassBRateAndIntegralII(int icls); + int printClassBRateAndIntegral(int iclsinscalers); + // // static constexpr uint32_t NCOUNTERS = 1052; // v1 diff --git a/DataFormats/Detectors/CTP/src/Scalers.cxx b/DataFormats/Detectors/CTP/src/Scalers.cxx index ca313bccf6fdb..0f93f3ce5a4f8 100644 --- a/DataFormats/Detectors/CTP/src/Scalers.cxx +++ b/DataFormats/Detectors/CTP/src/Scalers.cxx @@ -147,6 +147,24 @@ std::vector CTPRunScalers::getClassIndexes() const } return indexes; } +// cls counted from 0 +int CTPRunScalers::getScalerIndexForClass(int cls) const +{ + if (cls < 0 || cls >= 64) { + LOG(error) << "Class index out of range:" << cls; + return 255; + } + std::vector clslist = getClassIndexes(); + int i = 0; + for (auto const& clsl : clslist) { + if (cls == clsl) { + return i; + } + i++; + } + LOG(error) << " Class not found:" << cls; + return 255; +} int CTPRunScalers::readScalers(const std::string& rawscalers) { LOG(info) << "Loading CTP scalers."; @@ -553,7 +571,7 @@ int CTPRunScalers::printInputRateAndIntegral(int inp) } // Prints class before counters for lumi // Class counting 1..64 -int CTPRunScalers::printClassBRateAndIntegral(int icls) +int CTPRunScalers::printClassBRateAndIntegralII(int iclsindex) { if (mScalerRecordO2.size() == 0) { LOG(info) << "ScalerRecord is empty, doing nothing"; @@ -561,13 +579,30 @@ int CTPRunScalers::printClassBRateAndIntegral(int icls) } double_t time0 = mScalerRecordO2[0].epochTime; double_t timeL = mScalerRecordO2[mScalerRecordO2.size() - 1].epochTime; - if (mScalerRecordO2[0].scalers.size() < icls) { - LOG(error) << "class number bigger than expected for this run:" << icls << "expexted smaller than:" << mScalerRecordO2[0].scalers.size(); + int iscalerindex = getScalerIndexForClass(iclsindex); + if (iscalerindex != 255) { + int integral = mScalerRecordO2[mScalerRecordO2.size() - 1].scalers[iscalerindex].lmBefore - mScalerRecordO2[0].scalers[iscalerindex].lmBefore; + std::cout << "Scaler Integrals for run:" << mRunNumber << " duration:" << timeL - time0; + std::cout << " Class index" << iclsindex << " integral:" << integral << " rate:" << integral / (timeL - time0) << std::endl; + return 0; + } + return 1; +} +// Prints class before counters for lumi +// Scaler Index Class counting 1..64 +// getScalerIndexForClass(int cls) shpild be called before to convert class index to scaler class index +int CTPRunScalers::printClassBRateAndIntegral(int iclsscalerindex) +{ + if (mScalerRecordO2.size() == 0) { + LOG(info) << "ScalerRecord is empty, doing nothing"; return 1; - } else { - int integral = mScalerRecordO2[mScalerRecordO2.size() - 1].scalers[icls - 1].lmBefore - mScalerRecordO2[0].scalers[icls - 1].lmBefore; + } + double_t time0 = mScalerRecordO2[0].epochTime; + double_t timeL = mScalerRecordO2[mScalerRecordO2.size() - 1].epochTime; + { + int integral = mScalerRecordO2[mScalerRecordO2.size() - 1].scalers[iclsscalerindex - 1].lmBefore - mScalerRecordO2[0].scalers[iclsscalerindex - 1].lmBefore; std::cout << "Scaler Integrals for run:" << mRunNumber << " duration:" << timeL - time0; - std::cout << " Class " << icls << " integral:" << integral << " rate:" << integral / (timeL - time0) << std::endl; + std::cout << " Class scaler index:" << iclsscalerindex << " integral:" << integral << " rate:" << integral / (timeL - time0) << std::endl; } return 0; } diff --git a/Detectors/CTP/macro/CMakeLists.txt b/Detectors/CTP/macro/CMakeLists.txt index 8f8d4ae36720a..8aa0198adb065 100644 --- a/Detectors/CTP/macro/CMakeLists.txt +++ b/Detectors/CTP/macro/CMakeLists.txt @@ -33,6 +33,10 @@ o2_add_test_root_macro(CheckAOD2CTPDigits.C PUBLIC_LINK_LIBRARIES O2::DataFormatsCTP O2::CCDB LABELS ctp) +o2_add_test_root_macro(CheckAOD2CTPDigitsII.C + PUBLIC_LINK_LIBRARIES O2::DataFormatsCTP + O2::CCDB + LABELS ctp) o2_add_test_root_macro(TestConfig.C PUBLIC_LINK_LIBRARIES O2::DataFormatsCTP O2::CCDB @@ -49,3 +53,11 @@ o2_add_test_root_macro(ReadCTPRunScalersFromFile.C PUBLIC_LINK_LIBRARIES O2::DataFormatsCTP O2::CCDB LABELS ctp) +o2_add_test_root_macro(GetScalersForRun.C + PUBLIC_LINK_LIBRARIES O2::DataFormatsCTP + O2::CCDB + LABELS ctp) +o2_add_test_root_macro(PlotPbLumi.C + PUBLIC_LINK_LIBRARIES O2::DataFormatsCTP + O2::CCDB + LABELS ctp) diff --git a/Detectors/CTP/macro/CheckAOD2CTPDigitsII.C b/Detectors/CTP/macro/CheckAOD2CTPDigitsII.C new file mode 100644 index 0000000000000..14e60194bdd82 --- /dev/null +++ b/Detectors/CTP/macro/CheckAOD2CTPDigitsII.C @@ -0,0 +1,183 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file checkAOD2CTPDigits.C +/// \brief create CTP config, test it and add to database +/// \author Roman Lietava + +#if !defined(__CLING__) || defined(__ROOTCLING__) + +#include +#include "TFile.h" +#include "TTree.h" +#include +#include +#include +#include "TKey.h" +#include "TTreeReader.h" +#include "TTreeReaderValue.h" +#include "CommonDataFormat/InteractionRecord.h" +#endif +// To produce CTP digits: +// o2-raw-tf-reader-workflow -b --onlyDet CTP,FT0 --input-data list.txt | o2-ctp-reco-workflow -b --use-verbose-mode +// To produce AOD: +// WORKFLOW_PARAMETERS="AOD" WORKFLOW_DETECTORS="CTP,FT0,FV0" IGNORE_EXISTING_SHMFILES=1 $O2_ROOT/prodtests/full-system-test/run-workflow-on-inputlist.sh TF list.txt +using namespace o2::ctp; +int CheckAOD2CTPDigits(bool files = 1) +{ + if (files == 0) { + return 0; + } + int fRunNumber; + ULong64_t fGlobalBC; + ULong64_t fTriggerMask; + ULong64_t fInputMask; + std::unique_ptr file(TFile::Open("AO2D.root")); + if (file == nullptr) { + std::cout << "Can not open file AO2D.root" << std::endl; + return 1; + } + file->ls(); + TIter keyList(file->GetListOfKeys()); + TKey* key; + TTree* tree; + std::map bc2classmask; + std::map bc2inputmask; + // Find aod trigger info + int i = 0; + while ((key = (TKey*)keyList())) { + std::cout << "loop:" << i << " " << key->GetName() << std::endl; + i++; + std::string name = key->GetName(); + if (name.find("metaData") != std::string::npos) { + std::cout << "Skipping:" << name << std::endl; + continue; + } + tree = (TTree*)file->Get(Form("%s/O2bc_001", key->GetName())); + if (tree != 0) { + std::cout << "found O2bc" << std::endl; + tree->SetBranchAddress("fRunNumber", &fRunNumber); + tree->SetBranchAddress("fGlobalBC", &fGlobalBC); + tree->SetBranchAddress("fTriggerMask", &fTriggerMask); + tree->SetBranchAddress("fInputMask", &fInputMask); + std::cout << "# of entries:" << tree->GetEntries() << std::endl; + int NN = tree->GetEntries(); + int Nloop = NN; + for (int n{0}; n < Nloop; ++n) { + tree->GetEvent(n); + if (fTriggerMask) { + bc2classmask[fGlobalBC] = fTriggerMask; + // std::cout << std::dec << n << " Run:" << fRunNumber << " GBC:" << std::hex << fGlobalBC << " TM:0x" << std::hex << fTriggerMask << " count:" << bc2classmask.count(fGlobalBC) << std::endl; + } + if (fInputMask) { + bc2inputmask[fGlobalBC] = fInputMask; + } + if (1) { + if (fInputMask || fTriggerMask) { + auto ir = o2::InteractionRecord::long2IR(fGlobalBC); + // auto bcc = ir.orbit; + // if(fTriggerMask) std::cout << "===>"; + // std::cout << std::hex << ir.orbit << " " << ir.bc << " " << fInputMask << " " << fTriggerMask << std::dec << " (" << ir.orbit << " " << ir.bc << ")" << std::endl; + } + } + } + } else { + std::cout << "return 1" << std::endl; + return 1; + } + } + // return 0; + // Read CTP digits and check if every class mask in digits is in AOD + // CTP digits + TFile* fileDigits = TFile::Open("ctpdigitsWOD.root"); + // + fileDigits->ls(); + o2::ctp::CTPDigit* dig = new o2::ctp::CTPDigit; + // + // tree->Print(); + TTreeReader reader("o2sim", fileDigits); + TTreeReaderValue> ctpdigs(reader, "CTPDigits"); + // TTreeReaderArray ctpdigs(reader,"CTPDigits"); + bool firstE = true; + // + std::cout << "Doing ctpdigits" << std::endl; + std::map bc2classmaskD; + std::map bc2inputmaskD; + std::bitset<48> tvxmask; + tvxmask.set(2); + int nnotfinp = 0; + int nokinp = 0; + int nnotf = 0; + int nok = 0; + while (reader.Next()) { + if (ctpdigs.GetSetupStatus() < 0) { + std::cout << "Error:" << std::dec << ctpdigs.GetSetupStatus() << " for:" << ctpdigs.GetBranchName() << std::endl; + return 1; + } + // std::cout << "size:" << std::dec << ctpdigs.GetSize() << std::endl; + // std::cout << "size:" << std::dec << ctpdigs->size() << std::endl; + for (auto const& dig : *ctpdigs) { + ULong64_t gbc = dig.intRecord.toLong(); + if (dig.CTPClassMask.count()) { + bc2classmaskD[gbc] = dig.CTPClassMask.to_ullong(); + // int del = 280+17; + // auto it = bc2classmask.find (gbc); + // if(it != bc2classmask.end()) { + if (bc2classmask.count(gbc)) { + // bc2classmask.erase(gbc); + nok++; + // std::cout << std::hex << gbc << " tc aod clsmask:" << bc2classmask[gbc] << " " << dig.CTPClassMask.to_ullong() << std::endl; + // dig.printStream(std::cout); + } else { + std::cout << std::dec << dig.intRecord.orbit << " " << dig.intRecord.bc << " " << std::hex << dig.intRecord.toLong() << " not found " << bc2classmask.count(gbc) << std::endl; + nnotf++; + } + } + if (dig.CTPInputMask.count()) { + bc2inputmaskD[gbc] = dig.CTPInputMask.to_ullong(); + // auto it = bc2inputmask.find (gbc); + // if(it != bc2inputmask.end()) { + if (bc2inputmask.count(gbc)) { + // bc2inputmask.erase(gbc); + nokinp++; + // std::cout << std::hex << gbc << " ir aod inpmask:" << bc2inputmask[gbc] << " " << dig.CTPInputMask.to_ullong() << std::endl; + } else { + std::cout << std::dec << dig.intRecord.orbit << " " << dig.intRecord.bc << " " << std::hex << dig.intRecord.toLong() << " not found " << bc2inputmask.count(gbc) << std::endl; + nnotfinp++; + } + } + } + } + std::cout << "TClasses ===> nok:" << nok << " NOT found in digits:" << nnotf << " left:" << bc2classmask.size() << std::endl; + std::cout << "Inputs ===> nok:" << nokinp << " NOT found in digits:" << nnotfinp << " left:" << bc2inputmask.size() << std::endl; + nok = 0; + nokinp = 0; + nnotf = 0; + nnotfinp = 0; + for (auto const& tm : bc2classmask) { + if (bc2classmaskD.count(tm.first)) { + nok++; + } else { + nnotf++; + } + } + for (auto const& tm : bc2inputmask) { + if (bc2inputmaskD.count(tm.first)) { + nokinp++; + } else { + nnotfinp++; + } + } + + std::cout << "TClasses ===> nok:" << nok << " NOT found in aod:" << nnotf << " left:" << bc2classmaskD.size() << std::endl; + std::cout << "Inputs ===> nok:" << nokinp << " NOT found in aod:" << nnotfinp << " left:" << bc2inputmaskD.size() << std::endl; + return 0; +} diff --git a/Detectors/CTP/macro/GetScalersForRun.C b/Detectors/CTP/macro/GetScalersForRun.C new file mode 100644 index 0000000000000..e10d00e79c353 --- /dev/null +++ b/Detectors/CTP/macro/GetScalersForRun.C @@ -0,0 +1,128 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include +#include +#endif +using namespace o2::ctp; + +void GetScalersForRun(int runNumber = 0, int fillN = 0, bool test = 1) +{ + if (test == 0) { + return; + } + std::string mCCDBPathCTPScalers = "CTP/Calib/Scalers"; + std::string mCCDBPathCTPConfig = "CTP/Config/Config"; + // o2::ccdb::CcdbApi api; + // api.init("http://alice-ccdb.cern.ch"); // alice-ccdb.cern.ch + // api.init("http://ccdb-test.cern.ch:8080"); + auto& ccdbMgr = o2::ccdb::BasicCCDBManager::instance(); + // ccdbMgr.setURL("http://ccdb-test.cern.ch:8080"); + auto soreor = ccdbMgr.getRunDuration(runNumber); + uint64_t timeStamp = (soreor.second - soreor.first) / 2 + soreor.first; + std::cout << "Timestamp:" << timeStamp << std::endl; + // + std::string sfill = std::to_string(fillN); + std::map metadata; + metadata["fillNumber"] = sfill; + auto lhcifdata = ccdbMgr.getSpecific("GLO/Config/GRPLHCIF", timeStamp, metadata); + auto bfilling = lhcifdata->getBunchFilling(); + std::vector bcs = bfilling.getFilledBCs(); + std::cout << "Number of interacting bc:" << bcs.size() << std::endl; + // + std::string srun = std::to_string(runNumber); + metadata.clear(); // can be empty + metadata["runNumber"] = srun; + ccdbMgr.setURL("http://ccdb-test.cern.ch:8080"); + auto ctpscalers = ccdbMgr.getSpecific(mCCDBPathCTPScalers, timeStamp, metadata); + if (ctpscalers == nullptr) { + LOG(info) << "CTPRunScalers not in database, timestamp:" << timeStamp; + } + auto ctpcfg = ccdbMgr.getSpecific(mCCDBPathCTPConfig, timeStamp, metadata); + if (ctpcfg == nullptr) { + LOG(info) << "CTPRunConfig not in database, timestamp:" << timeStamp; + } + std::cout << "all good" << std::endl; + ctpscalers->convertRawToO2(); + std::vector ctpcls = ctpcfg->getCTPClasses(); + // std::vector clslist = ctpcfg->getTriggerClassList(); + std::vector clslist = ctpscalers->getClassIndexes(); + std::map clsIndexToScaler; + std::cout << "Classes:"; + int i = 0; + for (auto const& cls : clslist) { + std::cout << cls << " "; + clsIndexToScaler[cls] = i; + i++; + } + std::cout << std::endl; + int tsc = 255; + int tce = 255; + int vch = 255; + int iznc = 255; + for (auto const& cls : ctpcls) { + if (cls.name.find("CMTVXTSC-B-NOPF-CRU") != std::string::npos) { + tsc = cls.getIndex(); + std::cout << cls.name << ":" << tsc << std::endl; + } + if (cls.name.find("CMTVXTCE-B-NOPF-CRU") != std::string::npos) { + tce = cls.getIndex(); + std::cout << cls.name << ":" << tce << std::endl; + } + if (cls.name.find("CMTVXVCH-B-NOPF-CRU") != std::string::npos) { + vch = cls.getIndex(); + std::cout << cls.name << ":" << vch << std::endl; + } + if (cls.name.find("C1ZNC-B-NOPF-CRU") != std::string::npos) { + iznc = cls.getIndex(); + std::cout << cls.name << ":" << iznc << std::endl; + } + } + std::cout << "ZNC:"; + int inp = 26; + double_t nbc = bcs.size(); + double_t frev = 11245; + double_t sigmaratio = 28.; + std::vector recs = ctpscalers->getScalerRecordO2(); + double_t time0 = recs[0].epochTime; + double_t timeL = recs[recs.size() - 1].epochTime; + double_t Trun = timeL - time0; + double_t integral = recs[recs.size() - 1].scalersInps[inp - 1] - recs[0].scalersInps[inp - 1]; + double_t rate = integral / Trun; + double_t rat = integral / Trun / nbc / frev; + double_t mu = -TMath::Log(1 - rat); + double_t pp = 1 - mu / (TMath::Exp(mu) - 1); + double_t ratepp = mu * nbc * frev; + double_t integralpp = ratepp * Trun; + std::cout << "Rate:" << rate / sigmaratio << " Integral:" << integral << " mu:" << mu << " Pileup prob:" << pp; + std::cout << " Integralpp:" << integralpp << " Ratepp:" << ratepp / sigmaratio << std::endl; + // ctpscalers->printInputRateAndIntegral(26); + // + if (tsc != 255) { + std::cout << "TSC:"; + ctpscalers->printClassBRateAndIntegral(clsIndexToScaler[tsc] + 1); + } + if (tce != 255) { + std::cout << "TCE:"; + ctpscalers->printClassBRateAndIntegral(clsIndexToScaler[tce] + 1); + } + // std::cout << "TCE input:" << ctpscalers->printInputRateAndIntegral(5) << std::endl;; + if (vch != 255) { + std::cout << "VCH:"; + ctpscalers->printClassBRateAndIntegral(clsIndexToScaler[vch] + 1); + } + if (iznc != 255) { + std::cout << "ZNC class:"; + int integral = recs[recs.size() - 1].scalers[iznc].l1After - recs[0].scalers[iznc].l1After; + std::cout << integral << std::endl; + } +} diff --git a/Detectors/CTP/macro/PlotPbLumi.C b/Detectors/CTP/macro/PlotPbLumi.C new file mode 100644 index 0000000000000..bf30169929b45 --- /dev/null +++ b/Detectors/CTP/macro/PlotPbLumi.C @@ -0,0 +1,176 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file TestCTPScalers.C +/// \brief create CTP scalers, test it and add to database +/// \author Roman Lietava +// root -b -q "GetScalers.C(\"519499\", 1656286373953)" +#if !defined(__CLING__) || defined(__ROOTCLING__) + +#include +#include "CCDB/CcdbApi.h" +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsCTP/Scalers.h" +#include "DataFormatsCTP/Configuration.h" +#include +#include +#include +#endif +using namespace o2::ctp; +void PlotPbLumiII(int runNumber, int fillN, std::string ccdbHost = "http://ccdb-test.cern.ch:8080") +{ // + // what = 1: znc rate + // what = 2: (TCE+TSC)/ZNC + // what = 3: TCE/ZNC + std::string mCCDBPathCTPScalers = "CTP/Calib/Scalers"; + std::string mCCDBPathCTPConfig = "CTP/Config/Config"; + auto& ccdbMgr = o2::ccdb::BasicCCDBManager::instance(); + // Timestamp + auto soreor = ccdbMgr.getRunDuration(runNumber); + uint64_t timeStamp = (soreor.second - soreor.first) / 2 + soreor.first; + std::cout << "Timestamp:" << timeStamp << std::endl; + // Filling + std::string sfill = std::to_string(fillN); + std::map metadata; + metadata["fillNumber"] = sfill; + auto lhcifdata = ccdbMgr.getSpecific("GLO/Config/GRPLHCIF", timeStamp, metadata); + auto bfilling = lhcifdata->getBunchFilling(); + std::vector bcs = bfilling.getFilledBCs(); + int nbc = bcs.size(); + std::cout << "Number of interacting bc:" << nbc << std::endl; + // Scalers + std::string srun = std::to_string(runNumber); + metadata.clear(); // can be empty + metadata["runNumber"] = srun; + ccdbMgr.setURL("http://ccdb-test.cern.ch:8080"); + auto scl = ccdbMgr.getSpecific(mCCDBPathCTPScalers, timeStamp, metadata); + if (scl == nullptr) { + LOG(info) << "CTPRunScalers not in database, timestamp:" << timeStamp; + return; + } + scl->convertRawToO2(); + std::vector recs = scl->getScalerRecordO2(); + // + // CTPConfiguration ctpcfg; + auto ctpcfg = ccdbMgr.getSpecific(mCCDBPathCTPConfig, timeStamp, metadata); + if (ctpcfg == nullptr) { + LOG(info) << "CTPRunConfig not in database, timestamp:" << timeStamp; + return; + } + std::vector clslist = ctpcfg->getTriggerClassList(); + // std::vector clslist = scl->getClassIndexes(); + std::map clsIndexToScaler; + std::cout << "Classes:"; + int i = 0; + for (auto const& cls : clslist) { + std::cout << cls << " "; + clsIndexToScaler[cls] = i; + i++; + } + std::cout << std::endl; + std::vector ctpcls = ctpcfg->getCTPClasses(); + int tsc = 255; + int tce = 255; + int vch = 255; + for (auto const& cls : ctpcls) { + if (cls.name.find("CMTVXTSC-B-NOPF") != std::string::npos && tsc == 255) { + int itsc = cls.getIndex(); + tsc = clsIndexToScaler[itsc]; + // tsc = scl->getScalerIndexForClass(itsc); + std::cout << cls.name << ":" << tsc << ":" << itsc << std::endl; + } + if (cls.name.find("CMTVXTCE-B-NOPF-CRU") != std::string::npos) { + int itce = cls.getIndex(); + tce = clsIndexToScaler[itce]; + // tce = scl->getScalerIndexForClass(itce); + std::cout << cls.name << ":" << tce << ":" << itce << std::endl; + } + if (cls.name.find("CMTVXVCH-B-NOPF-CRU") != std::string::npos) { + int ivch = cls.getIndex(); + vch = clsIndexToScaler[ivch]; + // vch = scl->getScalerIndexForClass(ivch); + std::cout << cls.name << ":" << vch << ":" << ivch << std::endl; + } + } + if (tsc == 255 || tce == 255 || vch == 255) { + std::cout << " One of dcalers not available, check config to find alternative)" << std::endl; + return; + } + // + // Anal + // + // Times + double_t frev = 11245; + double_t time0 = recs[0].epochTime; + double_t timeL = recs[recs.size() - 1].epochTime; + double_t Trun = timeL - time0; + double_t orbit0 = recs[0].intRecord.orbit; + int n = recs.size() - 1; + std::cout << " Run duration:" << Trun << " Scalers size:" << n + 1 << std::endl; + Double_t x[n], znc[n], zncpp[n]; + Double_t tcetsctoznc[n], tcetoznc[n], vchtoznc[n]; + for (int i = 0; i < n; i++) { + x[i] = (double_t)(recs[i + 1].intRecord.orbit + recs[i].intRecord.orbit) / 2. - orbit0; + x[i] *= 88e-6; + // x[i] = (double_t)(recs[i+1].epochTime + recs[i].epochTime)/2.; + double_t tt = (double_t)(recs[i + 1].intRecord.orbit - recs[i].intRecord.orbit); + tt = tt * 88e-6; + // + // std::cout << recs[i+1].scalersInps[25] << std::endl; + double_t znci = (double_t)(recs[i + 1].scalersInps[25] - recs[i].scalersInps[25]); + double_t mu = -TMath::Log(1. - znci / tt / nbc / frev); + double_t zncipp = mu * nbc * frev; + zncpp[i] = zncipp / 28.; + znc[i] = znci / 28. / tt; + // + auto had = recs[i + 1].scalers[tce].lmBefore - recs[i].scalers[tce].lmBefore; + // std::cout << recs[i+1].scalers[tce].lmBefore << std::endl; + had += recs[i + 1].scalers[tsc].lmBefore - recs[i].scalers[tsc].lmBefore; + // rat = (double_t)(had)/double_t(recs[i+1].scalersInps[25] - recs[i].scalersInps[25])*28; + tcetsctoznc[i] = (double_t)(had) / zncpp[i] / tt; + had = recs[i + 1].scalers[tce].lmBefore - recs[i].scalers[tce].lmBefore; + // rat = (double_t)(had)/double_t(recs[i+1].scalersInps[25] - recs[i].scalersInps[25])*28; + tcetoznc[i] = (double_t)(had) / zncpp[i] / tt; + had = recs[i + 1].scalers[vch].lmBefore - recs[i].scalers[vch].lmBefore; + // rat = (double_t)(had)/double_t(recs[i+1].scalersInps[25] - recs[i].scalersInps[25])*28; + vchtoznc[i] = (double_t)(had) / zncpp[i] / tt; + } + // + gStyle->SetMarkerSize(0.5); + TGraph* gr1 = new TGraph(n, x, znc); + TGraph* gr2 = new TGraph(n, x, tcetsctoznc); + TGraph* gr3 = new TGraph(n, x, tcetoznc); + TGraph* gr4 = new TGraph(n, x, vchtoznc); + gr1->SetMarkerStyle(20); + gr2->SetMarkerStyle(21); + gr3->SetMarkerStyle(23); + gr4->SetMarkerStyle(23); + gr1->SetTitle("R=ZNC/28 rate [Hz]; time[sec]; R"); + gr2->SetTitle("R=(TSC+TCE)*TVTX*B*28/ZNC; time[sec]; R"); + // gr2->GetHistogram()->SetMaximum(1.1); + // gr2->GetHistogram()->SetMinimum(0.9); + gr3->SetTitle("R=(TCE)*TVTX*B*28/ZNC; time[sec]; R"); + // gr3->GetHistogram()->SetMaximum(0.6); + // gr3->GetHistogram()->SetMinimum(0.4); + gr4->SetTitle("R=(VCH)*TVTX*B*28/ZNC; time[sec]; R"); + // gr4->GetHistogram()->SetMaximum(0.6); + // gr4->GetHistogram()->SetMinimum(0.4); + TCanvas* c1 = new TCanvas("c1", srun.c_str(), 200, 10, 800, 500); + c1->Divide(2, 2); + c1->cd(1); + gr1->Draw("AP"); + c1->cd(2); + gr2->Draw("AP"); + c1->cd(3); + gr3->Draw("AP"); + c1->cd(4); + gr4->Draw("AP"); +}