CbmRecoUnpack.cxx 11.9 KB
Newer Older
1
2
3
4
/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
   SPDX-License-Identifier: GPL-3.0-only
   Authors: Volker Friese [committer], Pierre-Alain Loizeau, Pascal Raisig  */

5
6
7
8
9
10
11
12
13
/** @file CbmRecoUnpack.cxx
 ** @copyright Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
 ** @license SPDX-License-Identifier: GPL-3.0-only
 ** @author Volker Friese [originator]
 **/


#include "CbmRecoUnpack.h"

14
#include "CbmRecoUnpackConfig.tmpl"
15
#include "CbmTrdDigi.h"
16
17
#include "CbmTsEventHeader.h"

18
19
20
#include <FairRootManager.h>
#include <Logger.h>

21
#include <RtypesCore.h>
22
#include <TH1.h>
23
24

#include <cstddef>
25
#include <cstdint>
26
#include <memory>
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <utility>
#include <vector>


using fles::Timeslice;
using std::unique_ptr;


// -----   Constructor   ------------------------------------------------------
CbmRecoUnpack::CbmRecoUnpack() {}
// ----------------------------------------------------------------------------


40
// -----   Finish   -----------------------------------------------------------
41
42
void CbmRecoUnpack::Finish()
{
43
  LOG(info) << "CbmRecoUnpack::Finish() I do let the unpackers talk first :\n";
44
45
46
47

  if (fPsdConfig) fPsdConfig->GetUnpacker()->Finish();
  if (fRichConfig) fRichConfig->GetUnpacker()->Finish();
  if (fStsConfig) fStsConfig->GetUnpacker()->Finish();
48
  if (fTofConfig) fTofConfig->GetUnpacker()->Finish();
49
50
  if (fTrd1DConfig) fTrd1DConfig->GetUnpacker()->Finish();
  if (fTrd2DConfig) fTrd2DConfig->GetUnpacker()->Finish();
51
52
53

  // Create some default performance profiling histograms and write them to a file
  if (fDoPerfProf) performanceProfiling();
54
55
56
57
58
59
60
61
62
63
64
}

// ----------------------------------------------------------------------------

// -----   Initialisation   ---------------------------------------------------
Bool_t CbmRecoUnpack::Init()
{

  FairRootManager* ioman = FairRootManager::Instance();
  assert(ioman);

65
66
67
68
69
70
  auto eh = FairRun::Instance()->GetEventHeader();
  if (eh->IsA() == CbmTsEventHeader::Class()) fCbmTsEventHeader = static_cast<CbmTsEventHeader*>(eh);
  else
    LOG(fatal)
      << "CbmRecoUnpack::Init() no CbmTsEventHeader was added to the run. Without it, we can not store the UTC of the "
         "Timeslices correctly. Hence, this causes a fatal. Please add it in the steering macro to the Run.";
71
72

  // --- Psd
73
74
75
76
  if (fPsdConfig) {
    fPsdConfig->Init(ioman);
    initPerformanceMaps(fkFlesPsd, "PSD");
  }
77
  // --- Rich
78
79
80
81
82
  if (fRichConfig) {
    fRichConfig->Init(ioman);
    initPerformanceMaps(fkFlesRich, "RICH");
  }

83
  // --- Sts
84
85
86
87
  if (fStsConfig) {
    fStsConfig->Init(ioman);
    initPerformanceMaps(fkFlesSts, "STS");
  }
88
  // --- Tof
89
90
91
92
  if (fTofConfig) {
    fTofConfig->Init(ioman);
    initPerformanceMaps(fkFlesTof, "TOF");
  }
93
  // --- Trd
94
95
96
97
  if (fTrd1DConfig) {
    fTrd1DConfig->Init(ioman);
    initPerformanceMaps(fkFlesTrd, "TRD1D");
  }
98
  // --- TRD2D
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
  if (fTrd2DConfig) {
    if (fTrd1DConfig) {
      if (fTrd2DConfig->GetOutputBranchName() == fTrd1DConfig->GetOutputBranchName()) {
        LOG(info) << fTrd2DConfig->GetName() << "::Init() ---------------------------------";
        fTrd2DConfig->SetOutputVec(fTrd1DConfig->GetOutputVec());
        fTrd2DConfig->InitUnpacker();
        LOG(info) << fTrd2DConfig->GetName() << " succesful initialized -----------------\n";
      }
      else {
        fTrd2DConfig->Init(ioman);
      }
    }
    else {
      fTrd2DConfig->Init(ioman);
    }
114
    initPerformanceMaps(fkFlesTrd2D, "TRD2D");
115
116
  }
  // This is an ugly work around, because the TRD and TRD2D want to access the same vector and there is no function to retrieve a writeable vector<obj> from the FairRootManager, especially before the branches are created, as far as I am aware. The second option workaround is in in Init() to look for the fasp config and create a separate branch for fasp created CbmTrdDigis PR 072021
117
118
119
120
121
122

  return kTRUE;
}
// ----------------------------------------------------------------------------


123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
// -----   initPerformanceMaps   ----------------------------------------------
void CbmRecoUnpack::initPerformanceMaps(std::uint16_t subsysid, std::string name)
{
  if (fDoPerfProf) {
    fNameMap.emplace(std::make_pair(subsysid, std::make_pair(name, 0)));
    fTimeMap.emplace(std::make_pair(subsysid, std::make_pair(0, 0)));
    fDataSizeMap.emplace(std::make_pair(subsysid, std::make_pair(0, 0)));
  }
}
// ----------------------------------------------------------------------------


// -----   performanceProfiling   ---------------------------------------------
void CbmRecoUnpack::performanceProfiling()
{
  std::unique_ptr<TH1D> hProducedDigis =
    std::unique_ptr<TH1D>(new TH1D("ProducedDigis", "ProducedDigis", fNameMap.size(), -0.5, fNameMap.size() - 0.5));
  hProducedDigis->SetXTitle("Subsystem");
  hProducedDigis->SetYTitle("N-Digis");
  std::unique_ptr<TH1D> hSpeedPerf = std::unique_ptr<TH1D>(
    new TH1D("SpeedPerformance", "SpeedPerformance", fNameMap.size() * 2, -0.5, fNameMap.size() * 2 - 0.5));
  hSpeedPerf->SetXTitle("Subsystem");
  hSpeedPerf->SetYTitle("Unpacking performance [#mus/Digi]");
  std::unique_ptr<TH1D> hDataPerf = std::unique_ptr<TH1D>(
    new TH1D("DataPerformance", "DataPerformance", fNameMap.size() * 2, -0.5, fNameMap.size() * 2 - 0.5));
  hDataPerf->SetXTitle("Subsystem");
  hDataPerf->SetYTitle("Data [MB]");
  size_t iunpackerbin = 1;
  for (auto namepair : fNameMap) {

    // Speed performance
    auto timeit = fTimeMap.find(namepair.first);
    double cpu  = timeit->second.first / namepair.second.second;
    double wall = timeit->second.second / namepair.second.second;

    // Data performance
    auto datait    = fDataSizeMap.find(namepair.first);
    double indata  = datait->second.first;
    double outdata = datait->second.second;


    // N-Digis
    std::string label = namepair.second.first;
    hProducedDigis->GetXaxis()->SetBinLabel(iunpackerbin, label.data());
    hProducedDigis->SetBinContent(iunpackerbin, namepair.second.second);

    // Cpu time
    label = namepair.second.first;
    label += " cpu";
    hSpeedPerf->GetXaxis()->SetBinLabel(iunpackerbin * 2 - 1, label.data());
    hSpeedPerf->SetBinContent(iunpackerbin * 2 - 1, cpu);
    // Wall time
    label = namepair.second.first;
    label += " wall";
    hSpeedPerf->GetXaxis()->SetBinLabel(iunpackerbin * 2, label.data());
    hSpeedPerf->SetBinContent(iunpackerbin * 2, wall);

    // In data
    label = namepair.second.first;
    label += " in";
    hDataPerf->GetXaxis()->SetBinLabel(iunpackerbin * 2 - 1, label.data());
    hDataPerf->SetBinContent(iunpackerbin * 2 - 1, indata);

    // Out data
    label = namepair.second.first;
    label += " out";
    hDataPerf->GetXaxis()->SetBinLabel(iunpackerbin * 2, label.data());
    hDataPerf->SetBinContent(iunpackerbin * 2, outdata);

    ++iunpackerbin;
  }

  /// Save old global file and folder pointer to avoid messing with FairRoot
  TFile* oldFile     = gFile;
  TDirectory* oldDir = gDirectory;

  /// (Re-)Create ROOT file to store the histos
  TFile histofile(fOutfilename.data(), "RECREATE");

  histofile.cd();
  hProducedDigis->Write();
  hSpeedPerf->Write();
  hDataPerf->Write();

  /// Restore old global file and folder pointer to avoid messing with FairRoot
  gFile      = oldFile;
  gDirectory = oldDir;

  // histofile->Close();
  histofile.Close();
}
// ----------------------------------------------------------------------------

216
217
218
// -----   Reset   ------------------------------------------------------------
void CbmRecoUnpack::Reset()
{
219
220
221
  // Reset the event header for a new timeslice
  fCbmTsEventHeader->Reset();

222
223
  // Reset the unpackers for a new timeslice, e.g. clear the output vectors

224
  // ---- Psd ----
Pascal Raisig's avatar
Pascal Raisig committed
225
  if (fPsdConfig) fPsdConfig->Reset();
226
  // ---- Rich ----
Pascal Raisig's avatar
Pascal Raisig committed
227
  if (fRichConfig) fRichConfig->Reset();
228
  // ---- Sts ----
Pascal Raisig's avatar
Pascal Raisig committed
229
  if (fStsConfig) fStsConfig->Reset();
230
  // ---- Tof ----
231
  if (fTofConfig) fTofConfig->Reset();
232
  // ---- Trd ----
233
  if (fTrd1DConfig) fTrd1DConfig->Reset();
234
  // ---- Trd2D ----
235
  if (fTrd2DConfig) fTrd2DConfig->Reset();
236
237
238
239
240
241
242
243
244
245
}

// ----------------------------------------------------------------------------

// -----   Unpacking   --------------------------------------------------------
void CbmRecoUnpack::Unpack(unique_ptr<Timeslice> ts)
{
  // Prepare timeslice
  const fles::Timeslice& timeslice = *ts;

246
  fCbmTsEventHeader->SetTsIndex(ts->index());
247
248
  fCbmTsEventHeader->SetTsStartTime(ts->start_time());

249
  uint64_t nComponents = ts->num_components();
Pascal Raisig's avatar
Pascal Raisig committed
250
251
  // if (fDoDebugPrints) LOG(info) << "Unpack: TS index " << ts->index() << " components " << nComponents;
  LOG(info) << "Unpack: TS index " << ts->index() << " components " << nComponents;
252
253
254
255
256
257

  for (uint64_t component = 0; component < nComponents; component++) {

    auto systemId = static_cast<std::uint16_t>(ts->descriptor(component, 0).sys_id);

    switch (systemId) {
258
      case fkFlesPsd: {
259
        if (fPsdConfig) {
260
          fCbmTsEventHeader->AddNDigisPsd(unpack(systemId, &timeslice, component, fPsdConfig,
261
262
                                                 fPsdConfig->GetOptOutAVec(), fPsdConfig->GetOptOutBVec()));
        }
263
264
        break;
      }
265
      case fkFlesRich: {
266
        if (fRichConfig) {
267
          fCbmTsEventHeader->AddNDigisRich(unpack(systemId, &timeslice, component, fRichConfig,
268
269
                                                  fRichConfig->GetOptOutAVec(), fRichConfig->GetOptOutBVec()));
        }
270
271
        break;
      }
272
      case fkFlesSts: {
273
        if (fStsConfig) {
274
          fCbmTsEventHeader->AddNDigisSts(unpack(systemId, &timeslice, component, fStsConfig,
275
276
                                                 fStsConfig->GetOptOutAVec(), fStsConfig->GetOptOutBVec()));
        }
277
278
        break;
      }
279
      case fkFlesTof: {
280
        if (fTofConfig) {
281
          fCbmTsEventHeader->AddNDigisTof(unpack(systemId, &timeslice, component, fTofConfig,
282
283
                                                 fTofConfig->GetOptOutAVec(), fTofConfig->GetOptOutBVec()));
        }
284
285
        break;
      }
286
      case fkFlesTrd: {
287
        if (fTrd1DConfig) {
288
          fCbmTsEventHeader->AddNDigisTrd1D(unpack(systemId, &timeslice, component, fTrd1DConfig,
289
290
                                                   fTrd1DConfig->GetOptOutAVec(), fTrd1DConfig->GetOptOutBVec()));
        }
291
292
293
        break;
      }
      case fkFlesTrd2D: {
294
295
296
297
        if (fTrd2DConfig) {
          fCbmTsEventHeader->AddNDigisTrd2D(unpack(systemId, &timeslice, component, fTrd2DConfig,
                                                   fTrd2DConfig->GetOptOutAVec(), fTrd2DConfig->GetOptOutBVec()));
        }
298
299
        break;
      }
300
301
302
303
304
305
      default: {
        if (fDoDebugPrints) LOG(error) << "Unpack: Unknown system ID " << systemId << " for component " << component;
        break;
      }
    }
  }
306
307
308

  if (bOutputFullTimeSorting) {
    /// Time sort the output vectors of all unpackers present
309
310
311
312
313
314
    if (fPsdConfig && fPsdConfig->GetOutputVec()) { timesort(fPsdConfig->GetOutputVec()); }
    if (fRichConfig && fRichConfig->GetOutputVec()) { timesort(fRichConfig->GetOutputVec()); }
    if (fStsConfig && fStsConfig->GetOutputVec()) { timesort(fStsConfig->GetOutputVec()); }
    if (fTofConfig && fTofConfig->GetOutputVec()) { timesort(fTofConfig->GetOutputVec()); }
    if (fTrd1DConfig && fTrd1DConfig->GetOutputVec()) { timesort(fTrd1DConfig->GetOutputVec()); }
    if (fTrd2DConfig && fTrd2DConfig->GetOutputVec()) { timesort(fTrd2DConfig->GetOutputVec()); }
315
316

    /// Time sort the output vectors of all unpackers present
317
318
319
320
321
322
    if (fPsdConfig && fPsdConfig->GetOptOutAVec()) { timesort(fPsdConfig->GetOptOutAVec()); }
    if (fRichConfig && fRichConfig->GetOptOutAVec()) { timesort(fRichConfig->GetOptOutAVec()); }
    if (fStsConfig && fStsConfig->GetOptOutAVec()) { timesort(fStsConfig->GetOptOutAVec()); }
    if (fTofConfig && fTofConfig->GetOptOutAVec()) { timesort(fTofConfig->GetOptOutAVec()); }
    if (fTrd1DConfig && fTrd1DConfig->GetOptOutAVec()) { timesort(fTrd1DConfig->GetOptOutAVec()); }
    if (fTrd2DConfig && fTrd2DConfig->GetOptOutAVec()) { timesort(fTrd2DConfig->GetOptOutAVec()); }
323
  }
324
325
326
327
328
}
// ----------------------------------------------------------------------------


ClassImp(CbmRecoUnpack)