d810d0de |
1 | // $Id$ |
2 | // Main authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007 |
915dabe1 |
3 | |
d810d0de |
4 | /************************************************************************** |
5 | * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. * |
6 | * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for * |
51346b82 |
7 | * full copyright notice. * |
d810d0de |
8 | **************************************************************************/ |
915dabe1 |
9 | |
d810d0de |
10 | #include "AliEveTPCData.h" |
11 | |
cb4245bb |
12 | #include <EveDet/AliEveTPCSectorData.h> |
915dabe1 |
13 | |
14 | #include <AliSimDigits.h> |
15 | #include <AliTPCParam.h> |
375fd576 |
16 | #include <AliTPCRawStreamV3.h> |
915dabe1 |
17 | #include <TTree.h> |
d810d0de |
18 | |
a15e6d7d |
19 | //============================================================================== |
20 | //============================================================================== |
21 | // AliEveTPCData |
22 | //============================================================================== |
915dabe1 |
23 | |
57ffa5fb |
24 | //______________________________________________________________________________ |
915dabe1 |
25 | // |
26 | // A central manager for TPC data of an event. Can read digits (from |
27 | // a tree: LoadDigits()) and raw-data (via AliRawReader: LoadRaw()). |
28 | // |
d810d0de |
29 | // The sector data is stored in 36 AliEveTPCSectorData objects. |
915dabe1 |
30 | // Sectors 0 - 17: +z side, 18 - 35: -z side. |
31 | // No separation of inner/outer segments, use row numbers for addressing. |
32 | // |
092578a7 |
33 | // Threshold application and pedestal subtraction can be performed at |
34 | // load time: use SetLoadThreshold(thresh) and SetLoadPedestal(ped). |
35 | // |
36 | // For raw-data (loaded using LoadRaw) pedestals can be calculated |
51346b82 |
37 | // automatically per pad. Use SetAutoPedestal(kTRUE) to activate it. |
092578a7 |
38 | // You might still want to set load threshold (default iz zero). |
39 | // |
915dabe1 |
40 | |
d810d0de |
41 | ClassImp(AliEveTPCData) |
915dabe1 |
42 | |
d810d0de |
43 | AliEveTPCData::AliEveTPCData() : |
915dabe1 |
44 | fSectors(36), fSectorBlockSize(65536), |
d6433e5d |
45 | fLoadThreshold(0), fLoadPedestal(0), fAutoPedestal(kFALSE) |
915dabe1 |
46 | { |
a97abca8 |
47 | // Constructor. |
48 | |
d810d0de |
49 | AliEveTPCSectorData::InitStatics(); |
915dabe1 |
50 | } |
51 | |
d810d0de |
52 | AliEveTPCData::~AliEveTPCData() |
915dabe1 |
53 | { |
a97abca8 |
54 | // Destructor, deletes all sector-data. |
55 | |
092578a7 |
56 | DeleteAllSectors(); |
915dabe1 |
57 | } |
58 | |
57ffa5fb |
59 | /******************************************************************************/ |
915dabe1 |
60 | |
d810d0de |
61 | void AliEveTPCData::CreateSector(Int_t sector) |
915dabe1 |
62 | { |
a97abca8 |
63 | // Create sector-data for sector if it does not exist already. |
64 | |
65 | if (fSectors[sector] == 0) |
d810d0de |
66 | fSectors[sector] = new AliEveTPCSectorData(sector, fSectorBlockSize); |
915dabe1 |
67 | } |
68 | |
d810d0de |
69 | void AliEveTPCData::CreateAllSectors() |
915dabe1 |
70 | { |
a97abca8 |
71 | // Create all 36 sectors. |
72 | |
73 | for (Int_t s=0; s<36; ++s) |
915dabe1 |
74 | CreateSector(s); |
75 | } |
76 | |
d810d0de |
77 | void AliEveTPCData::DropAllSectors() |
092578a7 |
78 | { |
a97abca8 |
79 | // Drop data of all existing sectors. |
80 | |
81 | for (Int_t s=0; s<36; ++s) { |
82 | if (fSectors[s] != 0) |
092578a7 |
83 | fSectors[s]->DropData(); |
84 | } |
85 | } |
86 | |
d810d0de |
87 | void AliEveTPCData::DeleteAllSectors() |
092578a7 |
88 | { |
a97abca8 |
89 | // Delete all sector-data. |
90 | |
91 | for (Int_t s=0; s<36; ++s) { |
092578a7 |
92 | delete fSectors[s]; |
93 | fSectors[s] = 0; |
94 | } |
95 | } |
96 | |
57ffa5fb |
97 | /******************************************************************************/ |
915dabe1 |
98 | |
d810d0de |
99 | AliEveTPCSectorData* AliEveTPCData::GetSectorData(Int_t sector, Bool_t spawnSectors) |
915dabe1 |
100 | { |
a97abca8 |
101 | // Get sector-data for sector. If spawnSectors is true, the |
102 | // sector-data is created if it does not exist already. |
103 | |
104 | if (sector < 0 || sector > 35) return 0; |
105 | if (fSectors[sector] == 0 && spawnSectors) |
915dabe1 |
106 | CreateSector(sector); |
107 | return fSectors[sector]; |
108 | } |
109 | |
57ffa5fb |
110 | /******************************************************************************/ |
915dabe1 |
111 | |
d810d0de |
112 | void AliEveTPCData::LoadDigits(TTree* tree, Bool_t spawnSectors) |
915dabe1 |
113 | { |
114 | // Load data from TTree of AliSimDigits. |
115 | // If spawnSectors is false only sectors that have been created previously |
116 | // via CreateSector() are loaded. |
117 | // If spawnSectors is true sectors are created if data for them is encountered. |
118 | |
119 | AliSimDigits digit, *digitPtr = &digit; |
120 | tree->GetBranch("Segment")->SetAddress(&digitPtr); |
51346b82 |
121 | |
915dabe1 |
122 | Int_t sector, row, pad, curPad; |
123 | Short_t time, signal; |
124 | Bool_t inFill = kFALSE; |
d810d0de |
125 | AliEveTPCSectorData* secData = 0; |
915dabe1 |
126 | |
127 | Int_t numEnt = (Int_t) tree->GetEntries(); |
128 | for (Int_t ent=0; ent<numEnt; ent++) { |
129 | tree->GetEntry(ent); |
d810d0de |
130 | AliEveTPCSectorData::GetParam().AdjustSectorRow(digit.GetID(), sector, row); |
a97abca8 |
131 | if (sector >= 36) { |
915dabe1 |
132 | sector -= 36; |
d810d0de |
133 | row += AliEveTPCSectorData::GetInnSeg().GetNRows(); |
915dabe1 |
134 | } |
135 | secData = GetSectorData(sector, spawnSectors); |
a97abca8 |
136 | if (secData == 0) |
915dabe1 |
137 | continue; |
138 | |
a97abca8 |
139 | if (digit.First() == kFALSE) |
915dabe1 |
140 | continue; |
141 | curPad = -1; |
142 | do { |
143 | pad = digit.CurrentColumn(); |
144 | time = digit.CurrentRow(); |
145 | signal = digit.CurrentDigit(); |
146 | |
a97abca8 |
147 | if (pad != curPad) { |
148 | if (inFill) |
d6433e5d |
149 | secData->EndPad(fAutoPedestal, fLoadThreshold); |
915dabe1 |
150 | secData->BeginPad(row, pad, kFALSE); |
151 | curPad = pad; |
152 | inFill = kTRUE; |
153 | } |
a97abca8 |
154 | if (fAutoPedestal) { |
8bb2a8e9 |
155 | secData->RegisterData(time, signal); |
156 | } else { |
157 | signal -= fLoadPedestal; |
a97abca8 |
158 | if (signal >= fLoadThreshold) |
8bb2a8e9 |
159 | secData->RegisterData(time, signal); |
160 | } |
915dabe1 |
161 | |
162 | } while (digit.Next()); |
a97abca8 |
163 | if (inFill) { |
d6433e5d |
164 | secData->EndPad(fAutoPedestal, fLoadThreshold); |
915dabe1 |
165 | inFill = kFALSE; |
166 | } |
167 | } |
168 | } |
169 | |
375fd576 |
170 | void AliEveTPCData::LoadRaw(AliTPCRawStreamV3& input, Bool_t spawnSectors, Bool_t warn) |
915dabe1 |
171 | { |
375fd576 |
172 | // Load data from AliTPCRawStreamV3. |
915dabe1 |
173 | // If spawnSectors is false only sectors that have been created previously |
174 | // via CreateSector() are loaded. |
175 | // If spawnSectors is true sectors are created if data for them is encountered. |
176 | |
a15e6d7d |
177 | static const TEveException kEH("AliEveTPCData::LoadRaw "); |
915dabe1 |
178 | |
d6433e5d |
179 | Int_t sector = -1, row = -1, pad = -1, rowOffset = 0; |
092578a7 |
180 | Short_t time, signal; |
2148ac41 |
181 | Bool_t inFill = kFALSE; |
182 | Short_t pdrwCnt = 9999; // Count time-bins in padrow; needed to detect more than 1024 time-bins per padrow. |
183 | Short_t lastTime = 9999; // Last time-bin stored; needed to check for out-of-order time bins. |
184 | Bool_t pdrwCntWarn = kFALSE; |
092578a7 |
185 | Bool_t lastTimeWarn = kFALSE; |
d810d0de |
186 | AliEveTPCSectorData* secData = 0; |
915dabe1 |
187 | |
75a20dc1 |
188 | Short_t threshold = fLoadThreshold; |
189 | |
375fd576 |
190 | while (input.NextDDL()) { |
915dabe1 |
191 | if (input.IsNewSector()) { |
a97abca8 |
192 | if (inFill) { |
75a20dc1 |
193 | secData->EndPad(fAutoPedestal, threshold); |
915dabe1 |
194 | inFill = kFALSE; |
195 | } |
196 | sector = input.GetSector(); |
a97abca8 |
197 | if (sector >= 36) { |
915dabe1 |
198 | sector -= 36; |
d810d0de |
199 | rowOffset = AliEveTPCSectorData::GetInnSeg().GetNRows(); |
915dabe1 |
200 | } else { |
201 | rowOffset = 0; |
202 | } |
203 | secData = GetSectorData(sector, spawnSectors); |
204 | } |
205 | if (secData == 0) |
206 | continue; |
207 | |
375fd576 |
208 | while (input.NextChannel()) { |
209 | if (input.IsNewPad()) { |
210 | if (inFill) { |
211 | secData->EndPad(fAutoPedestal, threshold); |
212 | inFill = kFALSE; |
213 | } |
214 | row = input.GetRow() + rowOffset; |
215 | pad = input.GetPad(); |
216 | |
217 | if (pad >= AliEveTPCSectorData::GetNPadsInRow(row) || pad < 0) { |
218 | if (warn) { |
219 | Warning(kEH.Data(), "pad out of range (row=%d, pad=%d, maxpad=%d).", |
220 | row, pad, AliEveTPCSectorData::GetNPadsInRow(row)); |
221 | } |
222 | continue; |
915dabe1 |
223 | } |
75a20dc1 |
224 | |
375fd576 |
225 | threshold = fLoadThreshold; |
915dabe1 |
226 | |
375fd576 |
227 | secData->BeginPad(row, pad, kTRUE); |
228 | inFill = kTRUE; |
229 | pdrwCnt = 0; pdrwCntWarn = kFALSE; |
230 | lastTime = 1024; lastTimeWarn = kFALSE; |
2148ac41 |
231 | } |
375fd576 |
232 | |
233 | while (input.NextBunch()) { |
234 | const UShort_t *signalarr = input.GetSignals(); |
235 | |
236 | Int_t starttime = input.GetStartTimeBin(); |
237 | for (Int_t i = 0; i < input.GetBunchLength(); i++) { |
238 | time = starttime--;; |
239 | signal = signalarr[i]; |
240 | ++pdrwCnt; |
241 | if (pdrwCnt > 1024) { |
242 | if (pdrwCntWarn == kFALSE) { |
243 | if (warn) |
244 | Warning(kEH.Data(), "more than 1024 time-bins (row=%d, pad=%d, time=%d).\nFurther warnings of this type will be suppressed for this padrow.", |
245 | row, pad, time); |
246 | pdrwCntWarn = kTRUE; |
247 | } |
248 | continue; |
249 | } |
250 | if (time >= lastTime) { |
251 | if (lastTimeWarn == kFALSE) { |
252 | if (warn) |
253 | Warning(kEH.Data(), "time out of order (row=%d, pad=%d, time=%d, lastTime=%d).\nFurther warnings of this type will be suppressed for this padrow.", |
254 | row, pad, time, lastTime); |
255 | lastTimeWarn = kTRUE; |
256 | } |
257 | continue; |
258 | } |
259 | lastTime = time; |
260 | if (fAutoPedestal) { |
261 | secData->RegisterData(time, signal); |
262 | } else { |
263 | signal -= fLoadPedestal; |
264 | if (signal > threshold) |
265 | secData->RegisterData(time, signal); |
266 | } |
267 | } |
092578a7 |
268 | } |
d6433e5d |
269 | } |
915dabe1 |
270 | } |
271 | |
a97abca8 |
272 | if (inFill) { |
75a20dc1 |
273 | secData->EndPad(fAutoPedestal, threshold); |
915dabe1 |
274 | inFill = kFALSE; |
275 | } |
276 | } |