Project
Loading...
Searching...
No Matches
DigitizerTest.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
15#include "Framework/Logger.h"
17#include <TRandom.h>
18#include <TMath.h>
19
20using namespace o2::zdc;
21
22//______________________________________________________________________________
24{
26 if (mCCDBServer.size() > 0) {
27 mgr.setURL(mCCDBServer);
28 }
29 LOG(info) << "Initialization of ZDC Test Digitization " << mgr.getURL();
30
31 mSimCondition = mgr.get<o2::zdc::SimCondition>(o2::zdc::CCDBPathConfigSim);
32 if (!mSimCondition) {
33 LOG(fatal) << "Missing SimCondition configuration object @ " << o2::zdc::CCDBPathConfigSim;
34 return;
35 }
36 LOG(info) << "Loaded SimCondition for timestamp " << mgr.getTimestamp();
37 mSimCondition->print();
38
40 if (!mModuleConfig) {
41 LOG(fatal) << "Missing ModuleConfig configuration object @ " << o2::zdc::CCDBPathConfigModule;
42 return;
43 }
44 LOG(info) << "Loaded ModuleConfig for timestamp " << mgr.getTimestamp();
45 mModuleConfig->print();
46}
47
48//______________________________________________________________________________
49void DigitizerTest::setMask(uint32_t ich, uint32_t mask)
50{
51 if (ich < NChannels) {
52 mMask[ich] = mask;
53 } else {
54 LOG(fatal) << "Setting mask for non existing channel " << ich;
55 }
56}
57
59{
60 // printf("size = %zu Add %u.%u\n", mCache.size(), ir.orbit, ir.bc);
61 if (mCache.empty() || mCache.back() < ir) {
62 mCache.emplace_back();
63 auto& cb = mCache.back();
64 cb = ir;
65 return cb;
66 }
67 if (mCache.front() > ir) {
68 mCache.emplace_front();
69 auto& cb = mCache.front();
70 cb = ir;
71 return cb;
72 }
73 for (auto cb = mCache.begin(); cb != mCache.end(); cb++) {
74 if ((*cb) == ir) {
75 return *cb;
76 }
77 if (ir < (*cb)) {
78 auto cbnew = mCache.emplace(cb); // insert new element before cb
79 (*cbnew) = ir;
80 return (*cbnew);
81 }
82 }
83 return mCache.front();
84}
85
86//______________________________________________________________________________
87double DigitizerTest::add(int ic, float myAmp, const o2::InteractionRecord irpk,
88 float myShift, bool hasJitter)
89{
90 // myShift is the position of the signal peak inside the bunch crossing identified by irpk (in ns)
91 // and is converted into sample units
93 // Shift of samples due to additional fluctuations
94 float shift = hasJitter ? gRandom->Gaus(0, mSimCondition->channels[ic].pedestalNoise) : 0;
95 int pos_min = mSimCondition->channels[ic].ampMinID;
96 int nbx = mSimCondition->channels[ic].shape.size();
97 // This may result into a wrap of the BC counter. However the signal is stored only
98 // in pre-allocated containers
99 o2::InteractionRecord ir = irpk + BCCacheMin;
100 for (Int_t ib = 0; ib < NBC2Cache; ib++) {
101 auto* bc = getBCCache(ir);
102 if (bc) {
103 // Flag the presence of channel data
104 auto& bcd = getCreateBCData(ir);
105 bcd.channels = bcd.channels | mMask[ic];
106 auto sbcd = NTimeBinsPerBC * ir.differenceInBC(irpk);
107 int sample = TMath::Nint(pos_min + TSN * (sbcd - myShift) + shift + TSNH);
108 for (int i = 0; i < NTimeBinsPerBC; i++) {
109 if (sample >= 0 && sample < nbx) {
110 double y = mSimCondition->channels[ic].shape[sample];
111 bc->data[ic][i] += y * myAmp;
112 // LOG(info) << ic << " " << ir.orbit << "." << ir.bc << " s" << i << ") s " << sample << " " << y*myAmp << " -> " << bc->data[ic][i];
113 }
114 sample += TSN;
115 }
116 }
117 ir++;
118 }
119 // Assigned position in units of bunch crossing
120 return irpk.orbit * o2::constants::lhc::LHCMaxBunches + irpk.bc + (myShift + shift / double(TSN)) / double(NTimeBinsPerBC);
121} // add
122
123//______________________________________________________________________________
125{
126 float nba = mModuleConfig->nBunchAverage;
127 for (auto bc = mCache.begin(); bc != mCache.end(); bc++) {
128 if (zdcOrbitData.empty() || bc->orbit != zdcOrbitData.back().ir.orbit) {
129 auto& od = zdcOrbitData.emplace_back();
130 od.ir.orbit = bc->orbit;
132 // Rough estimate of pedestal fluctuations to fill orbit data
133 for (int ic = 0; ic < NChannels; ic++) {
134 auto base_m = mSimCondition->channels[ic].pedestal; // Average pedestal
135 auto base_s = mSimCondition->channels[ic].pedestalFluct; // Baseline oscillations
136 auto base_n = mSimCondition->channels[ic].pedestalNoise; // Electronic noise
137 // We don't know the time scale of the fluctuations of the baseline. As a
138 // rough guess we consider two bunch crossings
139 // sum = 12 * (mNEmptyBCs/2) * (2*base_m) = 12 * mNEmptyBCs * base_m
140 float mean_sum = 12. * nba * base_m; // Adding 12 samples for bunch crossing
141 float rms_sum = 12. * 2. * base_s * std::sqrt(nba / 2.); // 2 for fluctuation every 2 BCs
142 float rms_noise_sum = base_n * std::sqrt(12. * nba);
143 float ped = gRandom->Gaus(mean_sum, rms_sum) + gRandom->Gaus(0, rms_noise_sum);
144 int16_t peds = std::round(ped / nba / 12. / mModuleConfig->baselineFactor);
145 if (peds < SHRT_MIN) {
146 peds = SHRT_MIN;
147 } else if (peds > SHRT_MAX) {
148 peds = SHRT_MAX;
149 }
150 od.data[ic] = peds;
151 }
152 // printf("Adding data for orbit=%u\n", od.ir.orbit);
153 }
154 // printf("Adding CH data for bunch=%u\n", bc->bc);
155 auto& bcd = getCreateBCData(*bc);
156 bcd.ref.setFirstEntry(zdcChData.size());
157 uint32_t nstored = 0;
158 for (int ic = 0; ic < NChannels; ic++) {
159 // Check if channel has data for this bunch crossing
160 if (bcd.channels & mMask[ic]) {
161 Double_t meanp = mSimCondition->channels[ic].pedestal;
162 Double_t sigmab = mSimCondition->channels[ic].pedestalFluct;
163 // LOG(info) << ic << " meanp=" << meanp << " sigmab=" << sigmab;
164 // No pedestal oscillations on data. We do it in the orbit data
165 for (int i = 0; i < NTimeBinsPerBC; i++) {
166 Double_t yval = TMath::Nint(bc->data[ic][i] + gRandom->Gaus(meanp, sigmab));
167 if (yval > ADCMax) {
168 yval = ADCMax;
169 } else if (yval < ADCMin) {
170 yval = ADCMin;
171 }
172 // This is not correct but will work for direct digitization
173 bc->digi[ic][i] = yval;
174 // LOG(info) << ic << " " << i << ") " << yval;
175 }
176 // Store data in output array
177 zdcChData.emplace_back(ic, bc->digi[ic]);
178 nstored++;
179 }
180 }
181 bcd.ref.setEntries(nstored);
182 }
183} // digitize
184
185//______________________________________________________________________________
187{
188 mCache.clear();
189 zdcOrbitData.clear();
190 zdcBCData.clear();
191 zdcChData.clear();
192}
193
194//______________________________________________________________________________
195BCData& DigitizerTest::getCreateBCData(const o2::InteractionRecord& ir)
196{
197 if (zdcBCData.empty() || zdcBCData.back().ir < ir) {
198 zdcBCData.emplace_back();
199 auto& bc = zdcBCData.back();
200 bc.ir = ir;
201 return bc;
202 }
203 if (zdcBCData.front().ir > ir) {
204 zdcBCData.emplace(zdcBCData.begin());
205 auto& cb = zdcBCData.front();
206 cb.ir = ir;
207 return cb;
208 }
209 for (auto cb = zdcBCData.begin(); cb != zdcBCData.end(); cb++) {
210 if ((*cb).ir == ir) {
211 return *cb;
212 }
213 if (ir < (*cb).ir) {
214 auto cbnew = zdcBCData.emplace(cb); // insert new element before cb
215 (*cbnew).ir = ir;
216 return (*cbnew);
217 }
218 }
219 return zdcBCData.front();
220}
221
222//______________________________________________________________________________
223o2::zdc::Digitizer::BCCache* DigitizerTest::getBCCache(const o2::InteractionRecord& ir)
224{
225 // get pointer on existing cache
226 for (auto cb = mCache.begin(); cb != mCache.end(); cb++) {
227 if ((*cb) == ir) {
228 return &(*cb);
229 }
230 }
231 return nullptr;
232}
Fast digitization of a signal of given amplitude and time in pre-allocated bunch containers....
uint64_t bc
Definition RawEventData.h:5
int32_t i
Header to collect LHC related constants.
static BasicCCDBManager & instance()
double add(int ic, float myAmp, const o2::InteractionRecord irpk, float myShift, bool hasJitter=true)
o2::zdc::Digitizer::BCCache & getCreateBCCache(const o2::InteractionRecord &ir)
void setMask(uint32_t ich, uint32_t mask)
GLint GLuint mask
Definition glcorearb.h:291
constexpr int LHCMaxBunches
constexpr double LHCBunchSpacingNS
constexpr int NTimeBinsPerBC
Definition Constants.h:53
constexpr int NChannels
Definition Constants.h:65
constexpr int TSN
Definition Constants.h:94
const std::string CCDBPathConfigSim
Definition Constants.h:218
const std::string CCDBPathConfigModule
Definition Constants.h:219
constexpr int ADCMin
Definition Constants.h:76
constexpr int TSNH
Definition Constants.h:95
constexpr int ADCMax
Definition Constants.h:76
uint32_t orbit
LHC orbit.
uint16_t bc
bunch crossing ID of interaction
int64_t differenceInBC(const InteractionRecord &other) const
std::array< ChannelSimCondition, NChannels > channels
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
o2::InteractionRecord ir(0, 0)