diff --git a/DataFormats/Detectors/ZDC/CMakeLists.txt b/DataFormats/Detectors/ZDC/CMakeLists.txt index a5c1fec2c14c4..b36feed39b580 100644 --- a/DataFormats/Detectors/ZDC/CMakeLists.txt +++ b/DataFormats/Detectors/ZDC/CMakeLists.txt @@ -9,7 +9,7 @@ # submit itself to any jurisdiction. o2_add_library(DataFormatsZDC - SOURCES src/ChannelData.cxx src/BCData.cxx src/RecEvent.cxx + SOURCES src/ChannelData.cxx src/BCData.cxx src/RecEvent.cxx src/RawEventData.cxx src/OrbitRawData.cxx src/OrbitRecData.cxx PUBLIC_LINK_LIBRARIES O2::CommonConstants O2::CommonDataFormat O2::ZDCBase ROOT::MathCore FairRoot::Base @@ -18,4 +18,4 @@ o2_add_library(DataFormatsZDC o2_target_root_dictionary(DataFormatsZDC HEADERS include/DataFormatsZDC/BCData.h include/DataFormatsZDC/ChannelData.h include/DataFormatsZDC/RecEvent.h include/DataFormatsZDC/OrbitRawData.h - include/DataFormatsZDC/OrbitRecData.h) + include/DataFormatsZDC/OrbitRecData.h include/DataFormatsZDC/RawEventData.h) diff --git a/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RawEventData.h b/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RawEventData.h index f0662d175c2b2..e96a0e95f59f6 100644 --- a/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RawEventData.h +++ b/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RawEventData.h @@ -31,6 +31,7 @@ namespace zdc constexpr unsigned short Id_w0 = 0x0; constexpr unsigned short Id_w1 = 0x1; constexpr unsigned short Id_w2 = 0x2; +constexpr unsigned short Id_wn = 0x3; constexpr int NWPerGBTW = 4; struct __attribute__((__packed__)) ChannelDataV0 { @@ -79,11 +80,14 @@ struct __attribute__((__packed__)) ChannelDataV0 { unsigned empty_5 : 32; }; +union EventChData { + UInt_t w[NWPerBc][NWPerGBTW]; + struct ChannelDataV0 f; + void reset(); +}; + struct EventData { - union { - UInt_t w[NWPerBc][NWPerGBTW]; - struct ChannelDataV0 f; - } data[NModules][NChPerModule] = {0}; + EventChData data[NModules][NChPerModule] = {0}; void print() const; void reset(); ClassDefNV(EventData, 1); diff --git a/DataFormats/Detectors/ZDC/src/RawEventData.cxx b/DataFormats/Detectors/ZDC/src/RawEventData.cxx index d988b7007da98..06155e310e2e8 100644 --- a/DataFormats/Detectors/ZDC/src/RawEventData.cxx +++ b/DataFormats/Detectors/ZDC/src/RawEventData.cxx @@ -14,6 +14,13 @@ using namespace o2::zdc; //ClassImp(EventData); +//______________________________________________________________________________ +void EventChData::reset() +{ + static constexpr int payloadSize = NWPerGBTW * sizeof(UInt_t); + memset((void*)&w[0][0], 0, payloadSize); +} + //______________________________________________________________________________ void EventData::print() const { diff --git a/Detectors/ZDC/CMakeLists.txt b/Detectors/ZDC/CMakeLists.txt index 364119694abdb..97eac3feb0cc2 100644 --- a/Detectors/ZDC/CMakeLists.txt +++ b/Detectors/ZDC/CMakeLists.txt @@ -11,3 +11,4 @@ add_subdirectory(base) add_subdirectory(simulation) add_subdirectory(macro) +add_subdirectory(raw) diff --git a/Detectors/ZDC/base/src/ModuleConfig.cxx b/Detectors/ZDC/base/src/ModuleConfig.cxx index 9dbcf6a1ace8c..f0b0157e14a6b 100644 --- a/Detectors/ZDC/base/src/ModuleConfig.cxx +++ b/Detectors/ZDC/base/src/ModuleConfig.cxx @@ -14,6 +14,7 @@ using namespace o2::zdc; +//______________________________________________________________________________ void Module::printCh() const { printf("Module %d [ChID/FEEID R:T ]", id); @@ -23,6 +24,7 @@ void Module::printCh() const printf("\n"); } +//______________________________________________________________________________ void Module::printTrig() const { printf("Trigger conf %d: ", id); @@ -37,6 +39,7 @@ void Module::printTrig() const printf("\n"); } +//______________________________________________________________________________ void Module::print() const { printCh(); @@ -58,6 +61,7 @@ void ModuleConfig::print() const } } +//______________________________________________________________________________ void ModuleConfig::check() const { for (const auto& md : modules) { @@ -65,6 +69,7 @@ void ModuleConfig::check() const } } +//______________________________________________________________________________ void Module::check() const { // make sure that the channel has <= 2 triggers @@ -78,6 +83,7 @@ void Module::check() const } } +//______________________________________________________________________________ void Module::setChannel(int slot, int8_t chID, int16_t fID, bool read, bool trig, int tF, int tL, int tS, int tT) { if (slot < 0 || slot >= MaxChannels || chID < 0 || chID > NChannels) { diff --git a/Detectors/ZDC/raw/CMakeLists.txt b/Detectors/ZDC/raw/CMakeLists.txt new file mode 100644 index 0000000000000..64027eadc6d35 --- /dev/null +++ b/Detectors/ZDC/raw/CMakeLists.txt @@ -0,0 +1,31 @@ +# Copyright CERN and copyright holders of ALICE O2. This software is distributed +# under the terms of the GNU General Public License v3 (GPL Version 3), copied +# verbatim in the file "COPYING". +# +# See http://alice-o2.web.cern.ch/license for full licensing information. +# +# 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. + +o2_add_library(ZDCRaw + SOURCES src/DumpRaw.cxx src/raw-parser.cxx + PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat O2::ZDCBase O2::ZDCSimulation + O2::DataFormatsZDC O2::CCDB O2::SimConfig O2::DPLUtils + O2::DetectorsRaw O2::Headers) + + +o2_target_root_dictionary(ZDCRaw + HEADERS include/ZDCRaw/DumpRaw.h) + +o2_add_executable(raw-parser + COMPONENT_NAME zdc + SOURCES src/raw-parser.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + O2::DPLUtils + O2::ZDCSimulation + O2::ZDCRaw + O2::DetectorsRaw + O2::DetectorsCommonDataFormats + O2::CommonUtils) + diff --git a/Detectors/ZDC/raw/include/ZDCRaw/DumpRaw.h b/Detectors/ZDC/raw/include/ZDCRaw/DumpRaw.h new file mode 100644 index 0000000000000..165d57d4bc9f4 --- /dev/null +++ b/Detectors/ZDC/raw/include/ZDCRaw/DumpRaw.h @@ -0,0 +1,40 @@ +#include +#include +#include "ZDCBase/Constants.h" +#include "ZDCSimulation/ZDCSimParam.h" +#include "DataFormatsZDC/RawEventData.h" +#ifndef ALICEO2_ZDC_DUMPRAW_H_ +#define ALICEO2_ZDC_DUMPRAW_H_ +namespace o2 +{ +namespace zdc +{ +class DumpRaw +{ + public: + DumpRaw() = default; + void init(); + int process(const EventData& ev); + int process(const EventChData& ch); + int processWord(const UInt_t* word); + int getHPos(uint32_t board, uint32_t ch); + void write(); + void setVerbosity(int v) + { + mVerbosity = v; + } + int getVerbosity() const { return mVerbosity; } + + private: + void setStat(TH1* h); + int mVerbosity = 1; + TH1* mBaseline[NDigiChannels] = {0}; + TH1* mCounts[NDigiChannels] = {0}; + TH2* mSignal[NDigiChannels] = {0}; + TH2* mBunch[NDigiChannels] = {0}; + EventChData mCh; +}; +} // namespace zdc +} // namespace o2 + +#endif diff --git a/Detectors/ZDC/raw/src/DumpRaw.cxx b/Detectors/ZDC/raw/src/DumpRaw.cxx new file mode 100644 index 0000000000000..dbca59386494d --- /dev/null +++ b/Detectors/ZDC/raw/src/DumpRaw.cxx @@ -0,0 +1,249 @@ +#include +#include +#include +#include +#include +#include "ZDCRaw/DumpRaw.h" +#include "CommonConstants/LHCConstants.h" +#include "ZDCSimulation/Digits2Raw.h" +#include "FairLogger.h" + +using namespace o2::zdc; + +void DumpRaw::setStat(TH1* h) +{ + TString hn = h->GetName(); + h->Draw(); + gPad->Update(); + TPaveStats* st = (TPaveStats*)h->GetListOfFunctions()->FindObject("stats"); + st->SetFillStyle(1001); + st->SetBorderSize(1); + if (hn.BeginsWith("hp")) { + st->SetOptStat(111111); + st->SetX1NDC(0.1); + st->SetX2NDC(0.3); + st->SetY1NDC(0.640); + st->SetY2NDC(0.9); + } else if (hn.BeginsWith("hc")) { + st->SetOptStat(1111); + st->SetX1NDC(0.799); + st->SetX2NDC(0.999); + st->SetY1NDC(0.829); + st->SetY2NDC(0.999); + } else if (hn.BeginsWith("hs") || hn.BeginsWith("hb")) { + st->SetOptStat(11); + st->SetX1NDC(0.799); + st->SetX2NDC(0.9995); + st->SetY1NDC(0.904); + st->SetY2NDC(0.999); + } +} + +void DumpRaw::init() +{ + gROOT->SetBatch(); + auto& sopt = ZDCSimParam::Instance(); + int nbx = (sopt.nBCAheadTrig + 1) * NTimeBinsPerBC; + Double_t xmin = -sopt.nBCAheadTrig * NTimeBinsPerBC - 0.5; + Double_t xmax = NTimeBinsPerBC - 0.5; + for (UInt_t i = 0; i < NDigiChannels; i++) { + uint32_t imod = i / NChPerModule; + uint32_t ich = i % NChPerModule; + if (mBaseline[i]) { + mBaseline[i]->Reset(); + } else { + TString hname = TString::Format("hp%d%d", imod, ich); + TString htit = TString::Format("Baseline mod. %d ch. %d;Average orbit baseline", imod, ich); + //mBaseline[i]=new TH1F(hname,htit,ADCRange,ADCMin-0.5,ADCMax+0.5); + mBaseline[i] = new TH1F(hname, htit, 16378, -0.125, ADCMax + 0.125); + } + if (mCounts[i]) { + mCounts[i]->Reset(); + } else { + TString hname = TString::Format("hc%d%d", imod, ich); + TString htit = TString::Format("Counts mod. %d ch. %d; Orbit hits", imod, ich); + mCounts[i] = new TH1F(hname, htit, o2::constants::lhc::LHCMaxBunches + 1, -0.5, o2::constants::lhc::LHCMaxBunches + 0.5); + } + if (mSignal[i]) { + mSignal[i]->Reset(); + } else { + TString hname = TString::Format("hs%d%d", imod, ich); + TString htit = TString::Format("Signal mod. %d ch. %d; Sample; ADC", imod, ich); + mSignal[i] = new TH2F(hname, htit, nbx, xmin, xmax, ADCRange, ADCMin - 0.5, ADCMax + 0.5); + } + if (mBunch[i]) { + mBunch[i]->Reset(); + } else { + TString hname = TString::Format("hb%d%d", imod, ich); + TString htit = TString::Format("Bunch mod. %d ch. %d; Sample; ADC", imod, ich); + mBunch[i] = new TH2F(hname, htit, 100, -0.5, 99.5, 36, -35.5, 0.5); + } + } + // Word id not present in payload + mCh.f.fixed_0 = Id_wn; + mCh.f.fixed_1 = Id_wn; + mCh.f.fixed_2 = Id_wn; +} + +void DumpRaw::write() +{ + TFile* f = new TFile("ZDCDumpRaw.root", "recreate"); + if (f->IsZombie()) { + LOG(FATAL) << "Cannot write to file " << f->GetName(); + return; + } + for (UInt_t i = 0; i < NDigiChannels; i++) { + if (mBunch[i] && mBunch[i]->GetEntries() > 0) { + setStat(mBunch[i]); + mBunch[i]->Write(); + } + } + for (UInt_t i = 0; i < NDigiChannels; i++) { + if (mBaseline[i] && mBaseline[i]->GetEntries() > 0) { + setStat(mBaseline[i]); + mBaseline[i]->Write(); + } + } + for (UInt_t i = 0; i < NDigiChannels; i++) { + if (mCounts[i] && mCounts[i]->GetEntries() > 0) { + setStat(mCounts[i]); + mCounts[i]->Write(); + } + } + for (UInt_t i = 0; i < NDigiChannels; i++) { + if (mSignal[i] && mSignal[i]->GetEntries() > 0) { + setStat(mSignal[i]); + mSignal[i]->Write(); + } + } + f->Close(); +} + +inline int DumpRaw::getHPos(uint32_t board, uint32_t ch) +{ + int ih = board * 4 + ch; + if (ih < NDigiChannels) { + return ih; + } else { + LOG(ERROR) << "Wrong ih " << ih << " board " << board << " ch " << ch; + return -1; + } +} + +int DumpRaw::processWord(const UInt_t* word) +{ + if (word == 0) { + printf("NULL\n"); + return 1; + } + if ((word[0] & 0x3) == Id_w0) { + for (Int_t iw = 0; iw < NWPerGBTW; iw++) { + mCh.w[0][iw] = word[iw]; + } + } else if ((word[0] & 0x3) == Id_w1) { + if (mCh.f.fixed_0 == Id_w0) { + for (Int_t iw = 0; iw < NWPerGBTW; iw++) { + mCh.w[1][iw] = word[iw]; + } + } else { + LOG(ERROR) << "Wrong word sequence"; + mCh.f.fixed_0 = Id_wn; + mCh.f.fixed_1 = Id_wn; + mCh.f.fixed_2 = Id_wn; + } + } else if ((word[0] & 0x3) == Id_w2) { + if (mCh.f.fixed_0 == Id_w0 && mCh.f.fixed_1 == Id_w1) { + for (Int_t iw = 0; iw < NWPerGBTW; iw++) { + mCh.w[2][iw] = word[iw]; + } + process(mCh); + } else { + LOG(ERROR) << "Wrong word sequence"; + } + mCh.f.fixed_0 = Id_wn; + mCh.f.fixed_1 = Id_wn; + mCh.f.fixed_2 = Id_wn; + } else { + // Word not present in payload + LOG(FATAL) << "Event format error"; + return 1; + } + return 0; +} + +int DumpRaw::process(const EventChData& ch) +{ + static constexpr int last_bc = o2::constants::lhc::LHCMaxBunches - 1; + // Not empty event + auto f = ch.f; + int ih = getHPos(f.board, f.ch); + if (mVerbosity > 0) { + for (Int_t iw = 0; iw < NWPerBc; iw++) { + Digits2Raw::print_gbt_word(ch.w[iw]); + } + } + UShort_t us[12]; + Short_t s[12]; + us[0] = f.s00; + us[1] = f.s01; + us[2] = f.s02; + us[3] = f.s03; + us[4] = f.s04; + us[5] = f.s05; + us[6] = f.s06; + us[7] = f.s07; + us[8] = f.s08; + us[9] = f.s09; + us[10] = f.s10; + us[11] = f.s11; + for (Int_t i = 0; i < 12; i++) { + if (us[i] > ADCMax) { + s[i] = us[i] - ADCRange; + } else { + s[i] = us[i]; + } + //printf("%d %u %d\n",i,us[i],s[i]); + } + if (f.Alice_3) { + for (Int_t i = 0; i < 12; i++) + mSignal[ih]->Fill(i - 36., Double_t(s[i])); + } + if (f.Alice_2) { + for (Int_t i = 0; i < 12; i++) + mSignal[ih]->Fill(i - 24., Double_t(s[i])); + } + if (f.Alice_1 || f.Auto_1) { + for (Int_t i = 0; i < 12; i++) + mSignal[ih]->Fill(i - 12., Double_t(s[i])); + } + if (f.Alice_0 || f.Auto_0) { + for (Int_t i = 0; i < 12; i++) + mSignal[ih]->Fill(i + 0., Double_t(s[i])); + Double_t bc_d = UInt_t(f.bc / 100); + Double_t bc_m = UInt_t(f.bc % 100); + mBunch[ih]->Fill(bc_m, -bc_d); + } + if (f.bc == last_bc) { + Int_t offset = f.offset - 32768; + Double_t foffset = offset / 8.; + mBaseline[ih]->Fill(foffset); + mCounts[ih]->Fill(f.hits); + } + return 0; +} + +int DumpRaw::process(const EventData& ev) +{ + for (Int_t im = 0; im < NModules; im++) { + for (Int_t ic = 0; ic < NChPerModule; ic++) { + if (ev.data[im][ic].f.fixed_0 == Id_w0 && ev.data[im][ic].f.fixed_1 == Id_w1 && ev.data[im][ic].f.fixed_2 == Id_w2) { + process(ev.data[im][ic]); + } else if (ev.data[im][ic].f.fixed_0 == 0 && ev.data[im][ic].f.fixed_1 == 0 && ev.data[im][ic].f.fixed_2 == 0) { + // Empty channel + } else { + LOG(ERROR) << "Data format error"; + } + } + } + return 0; +} diff --git a/Detectors/ZDC/raw/src/ZDCRawLinkDef.h b/Detectors/ZDC/raw/src/ZDCRawLinkDef.h new file mode 100644 index 0000000000000..71519a02a652e --- /dev/null +++ b/Detectors/ZDC/raw/src/ZDCRawLinkDef.h @@ -0,0 +1,17 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// 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. + +#ifdef __CLING__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#endif diff --git a/Detectors/ZDC/simulation/src/raw-parser.cxx b/Detectors/ZDC/raw/src/raw-parser.cxx similarity index 93% rename from Detectors/ZDC/simulation/src/raw-parser.cxx rename to Detectors/ZDC/raw/src/raw-parser.cxx index 616a7eaa7ee27..b2c65d71776c2 100644 --- a/Detectors/ZDC/simulation/src/raw-parser.cxx +++ b/Detectors/ZDC/raw/src/raw-parser.cxx @@ -18,6 +18,7 @@ #include "Headers/DataHeader.h" #include "DataFormatsZDC/RawEventData.h" #include "ZDCSimulation/Digits2Raw.h" +#include "ZDCRaw/DumpRaw.h" #include #include @@ -44,7 +45,10 @@ WorkflowSpec defineDataProcessing(ConfigContext const& config) AlgorithmSpec{[](InitContext& setup) { auto loglevel = setup.options().get("log-level"); return adaptStateless([loglevel](InputRecord& inputs, DataAllocator& outputs) { - DPLRawParser parser(inputs); + o2::zdc::DumpRaw zdc_dr; + zdc_dr.init(); + zdc_dr.setVerbosity(loglevel); + DPLRawParser parser(inputs); o2::header::DataHeader const* lastDataHeader = nullptr; std::stringstream rdhprintout; for (auto it = parser.begin(), end = parser.end(); it != end; ++it) { @@ -82,7 +86,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& config) } if(payload!=0){ for(Int_t ip=0; ip 0) { LOG(INFO) << rdhprintout.str(); } + zdc_dr.write(); }); }}, Options{ {"log-level", VariantType::Int, 1, {"Logging level [0-2]"}}}}); diff --git a/Detectors/ZDC/simulation/CMakeLists.txt b/Detectors/ZDC/simulation/CMakeLists.txt index e4dc53138c392..e96e992eca329 100644 --- a/Detectors/ZDC/simulation/CMakeLists.txt +++ b/Detectors/ZDC/simulation/CMakeLists.txt @@ -11,7 +11,7 @@ o2_add_library(ZDCSimulation SOURCES src/Detector.cxx src/Digitizer.cxx src/SimCondition.cxx src/ZDCSimParam.cxx src/SpatialPhotonResponse.cxx src/Digits2Raw.cxx - PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat O2::ZDCBase + PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat O2::ZDCBase O2::DataFormatsZDC O2::CCDB O2::SimConfig O2::DetectorsRaw O2::Headers) diff --git a/Detectors/ZDC/simulation/src/Digitizer.cxx b/Detectors/ZDC/simulation/src/Digitizer.cxx index 536fd5070ba3b..ab34933392945 100644 --- a/Detectors/ZDC/simulation/src/Digitizer.cxx +++ b/Detectors/ZDC/simulation/src/Digitizer.cxx @@ -471,7 +471,7 @@ void Digitizer::refreshCCDB() } } if (md.feeID[ic] < 0 || md.feeID[ic] >= NLinks) { - LOG(ERROR) << "FEEID " << md.feeID[ic] << " not in allowed range [0:" << NLinks << ")"; + LOG(FATAL) << "FEEID " << md.feeID[ic] << " not in allowed range [0:" << NLinks << ")"; } } } else { diff --git a/Detectors/ZDC/simulation/src/digi2raw.cxx b/Detectors/ZDC/simulation/src/digi2raw.cxx index ef4c62bd85132..8d06d3993051c 100644 --- a/Detectors/ZDC/simulation/src/digi2raw.cxx +++ b/Detectors/ZDC/simulation/src/digi2raw.cxx @@ -57,7 +57,7 @@ int main(int argc, char** argv) add_option("input-file,i", bpo::value()->default_value("zdcdigits.root"), "input ZDC digits file"); add_option("file-per-link,l", bpo::value()->default_value(false)->implicit_value(true), "create output file per CRU (default: write single file)"); add_option("output-dir,o", bpo::value()->default_value("./"), "output directory for raw data"); - add_option("ccdb-url,c", bpo::value()->default_value(""), "url of the ccdb repository"); + add_option("ccdb-url,o", bpo::value()->default_value(""), "url of the ccdb repository"); uint32_t defRDH = o2::raw::RDHUtils::getVersion(); add_option("rdh-version,r", bpo::value()->default_value(defRDH), "RDH version to use"); add_option("configKeyValues", bpo::value()->default_value(""), "comma-separated configKeyValues");