Fix by Filimon to allow online monitoring of raw data. Thanks Filimon
[u/mrichter/AliRoot.git] / FMD / AliFMDRawWriter.cxx
CommitLineData
e802be3e 1/**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
e802be3e 15/* $Id$ */
c2fc1258 16/** @file AliFMDRawWriter.cxx
17 @author Christian Holm Christensen <cholm@nbi.dk>
18 @date Mon Mar 27 12:45:56 2006
19 @brief Class to write raw data
20*/
e802be3e 21//____________________________________________________________________
22//
23// Class to write ADC values to a raw data file
24//
7684b53c 25// This class writes FMD Raw data to a file. The sample rate (number
26// of times the ALTRO ADC samples each pre-amp. channel - that is,
27// data from a single strip), can be set via SetSampleRate.
28//
29// Zero-suppression can be enabled by calling SetThreshold with a
30// non-zero argument. ADC values less than the value set will not be
31// written to output. Note, that if you use zero-suppression, you
32// need to explicitly set the sample rate when reading back the data
33// with AliFMDRawReader.
34//
35// This class uses the AliAltroBuffer class to write the data in the
36// ALTRO format. See the Exec member function for more information on
37// that format.
38//
f95a63c4 39// #include <AliLog.h> // ALILOG_H
40#include "AliFMDDebug.h" // Better debug macros
56b1929b 41#include <AliLoader.h> // ALILOADER_H
42#include <AliAltroBuffer.h> // ALIALTROBUFFER_H
e802be3e 43#include "AliFMD.h" // ALIFMD_H
1a1fdef7 44#include "AliFMDParameters.h" // ALIFMDPARAMETERS_H
e802be3e 45#include "AliFMDDigit.h" // ALIFMDDIGIT_H
46#include "AliFMDRawWriter.h" // ALIFMDRAWREADER_H
1e8f773e 47#include "AliFMDAltroMapping.h" // ALIFMDALTROMAPPING_H
c2fc1258 48// #include "AliFMDAltroIO.h" // ALIFMDALTROWRITER_H
56b1929b 49#include <TArrayI.h> // ROOT_TArrayI
e802be3e 50#include <TClonesArray.h> // ROOT_TClonesArray
02a27b50 51// #include <fstream>
362c9d61 52#include "AliDAQ.h"
e802be3e 53
54//____________________________________________________________________
925e6570 55ClassImp(AliFMDRawWriter)
1a1fdef7 56#if 0
57 ; // This is here to keep Emacs for indenting the next line
58#endif
e802be3e 59
60//____________________________________________________________________
61AliFMDRawWriter::AliFMDRawWriter(AliFMD* fmd)
62 : TTask("FMDRawWriter", "Writer of Raw ADC values from the FMD"),
b5ee4425 63 fFMD(fmd),
64 fSampleRate(0),
65 fChannelsPerAltro(0),
66 fThreshold(0)
02a27b50 67{
68 // CTOR
ef8e8623 69 AliFMDDebug(5, ("Created AliFMDRawWriter object"));
02a27b50 70}
71
e802be3e 72
73
74//____________________________________________________________________
75void
76AliFMDRawWriter::Exec(Option_t*)
77{
78 // Turn digits into raw data.
79 //
80 // Digits are read from the Digit branch, and processed to make
81 // three DDL files, one for each of the sub-detectors FMD1, FMD2,
82 // and FMD3.
83 //
84 // The raw data files consists of a header, followed by ALTRO
85 // formatted blocks.
86 //
87 // +-------------+
88 // | Header |
89 // +-------------+
90 // | ALTRO Block |
91 // | ... |
92 // +-------------+
93 // DDL file
94 //
95 // An ALTRO formatted block, in the FMD context, consists of a
96 // number of counts followed by a trailer.
97 //
98 // +------------------+
99 // | Count |
100 // | ... |
101 // | possible fillers |
102 // +------------------+
103 // | Trailer |
104 // +------------------+
105 // ALTRO block
106 //
107 // The counts are listed backwards, that is, starting with the
108 // latest count, and ending in the first.
109 //
110 // Each count consist of 1 or more ADC samples of the VA1_ALICE
111 // pre-amp. signal. Just how many samples are used depends on
112 // whether the ALTRO over samples the pre-amp. Each sample is a
113 // 10-bit word, and the samples are grouped into 40-bit blocks
114 //
115 // +------------------------------------+
c2fc1258 116 // | S(1) | S(2) | S(3) | S(4) |
e802be3e 117 // | ... | ... | ... | ... |
c2fc1258 118 // | S(n) | T(n) | n+2 | 2AA |
e802be3e 119 // +------------------------------------+
120 // Counts + possible filler
121 //
122 // The trailer of the number of words of signales, the starting
123 // strip number, the sector number, and the ring ID; each 10-bit
124 // words, packed into 40-bits.
125 //
126 // +------------------------------------+
c2fc1258 127 // | 2AAA | Len | A | Address |
e802be3e 128 // +------------------------------------+
129 // Trailer
130 //
131 // Note, that this method assumes that the digits are ordered.
132 //
133 AliLoader* loader = fFMD->GetLoader();
ef8e8623 134 loader->LoadDigits("READ");
e802be3e 135 TTree* digitTree = loader->TreeD();
136 if (!digitTree) {
ef8e8623 137 AliError("no digit tree");
e802be3e 138 return;
139 }
140
141 TClonesArray* digits = new TClonesArray("AliFMDDigit", 1000);
142 fFMD->SetTreeAddress();
143 TBranch* digitBranch = digitTree->GetBranch(fFMD->GetName());
144 if (!digitBranch) {
ef8e8623 145 AliError(Form("no branch for %s", fFMD->GetName()));
e802be3e 146 return;
147 }
148 digitBranch->SetAddress(&digits);
149
150 Int_t nEvents = Int_t(digitTree->GetEntries());
f95a63c4 151 AliFMDDebug(5, ("Got a total of %5d events from tree", nEvents));
e802be3e 152 for (Int_t event = 0; event < nEvents; event++) {
153 fFMD->ResetDigits();
154 digitTree->GetEvent(event);
155
1e8f773e 156 // Write out the digits
157 WriteDigits(digits);
158 }
159 loader->UnloadDigits();
160}
e802be3e 161
c2fc1258 162#if 1
163//____________________________________________________________________
164void
165AliFMDRawWriter::WriteDigits(TClonesArray* digits)
166{
02a27b50 167 // WRite an array of digits to disk file
c2fc1258 168 Int_t nDigits = digits->GetEntries();
169 if (nDigits < 1) return;
f95a63c4 170 AliFMDDebug(5, ("Got a total of %5d digits from tree", nDigits));
c2fc1258 171
172 AliFMDParameters* pars = AliFMDParameters::Instance();
173 UShort_t threshold = 0;
f95a63c4 174 UInt_t prevddl = 0xFFFF;
c2fc1258 175 UInt_t prevaddr = 0xFFF;
176 // UShort_t prevStrip = 0;
177
178 // Which channel number in the ALTRO channel we're at
179 UShort_t nWords = 0;
180 UShort_t preSamples = 0;
f38b1653 181 UShort_t sampleRate = 0;
c2fc1258 182
183 // A buffer to hold 1 ALTRO channel - Normally, one ALTRO channel
184 // holds 128 VA1_ALICE channels, sampled at a rate of `sampleRate'
185 TArrayI data(pars->GetChannelsPerAltro() * 8);
186
187 // The Altro buffer
188 AliAltroBuffer* altro = 0;
f38b1653 189
190 Int_t totalWords = 0;
191 Int_t nCounts = 0;
192
c2fc1258 193 // Loop over the digits in the event. Note, that we assume the
194 // the digits are in order in the branch. If they were not, we'd
195 // have to cache all channels before we could write the data to
196 // the ALTRO buffer, or we'd have to set up a map of the digits.
f95a63c4 197 UShort_t oldDet = 1000;
c2fc1258 198 for (Int_t i = 0; i < nDigits; i++) {
199 // Get the digit
200 AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
c2fc1258 201 UShort_t det = digit->Detector();
202 Char_t ring = digit->Ring();
203 UShort_t sector = digit->Sector();
204 UShort_t strip = digit->Strip();
205 UInt_t ddl;
206 UInt_t addr;
f38b1653 207 UShort_t time;
208
209 AliFMDDebug(10, ("Processing digit # %5d FMD%d%c[%2d,%3d]",
210 i, det, ring, sector, strip));
211 threshold = pars->GetZeroSuppression(det, ring, sector, strip);
212 sampleRate = pars->GetSampleRate(det, ring, sector, strip);
213 preSamples = pars->GetPreSamples(det, ring, sector, strip);
214
f95a63c4 215 if (det != oldDet) {
216 AliFMDDebug(5, ("Got new detector: %d (was %d)", det, oldDet));
217 oldDet = det;
218 }
f38b1653 219 AliFMDDebug(10, ("Sample rate is %d", sampleRate));
625d7886 220
f38b1653 221 for (UShort_t j = 0; j < sampleRate; j++) {
222 if (!pars->Detector2Hardware(det,ring,sector,strip,j,ddl,addr,time)){
223 AliError(Form("Failed to get hardware address for FMD%d%c[%2d,%3d]-%d",
224 det, ring, sector, strip, j));
225 continue;
c2fc1258 226 }
c2fc1258 227
f38b1653 228 AliFMDDebug(10, ("FMD%d%c[%2d,%3d]-%d-> 0x%x/0x%x/%04d",
229 det, ring, sector, strip, j, ddl, addr, time));
230 if (addr != prevaddr) {
231 // Flush a channel to output
232 AliFMDDebug(5, ("Now hardware address 0x%x from FMD%d%c[%2d,%3d]-%d"
233 "(b: 0x%02x, a: 0x%01x, c: 0x%02x, t: %04d), "
234 "flushing old channel at 0x%x with %d words",
235 addr, det, ring, sector, strip, j,
236 (addr >> 7), (addr >> 4) & 0x7, addr & 0xf,
237 time, prevaddr, nWords));
238 totalWords += nWords;
239 if (altro) altro->WriteChannel(prevaddr,nWords,data.fArray,threshold);
240 nWords = 0;
241 prevaddr = addr;
242 }
243 if (ddl != prevddl) {
244 AliFMDDebug(10, ("FMD: New DDL, was %d, now %d", prevddl, ddl));
245 // If an altro exists, delete the object, flushing the data to
246 // disk, and closing the file.
247 if (altro) {
248 // When the first argument is false, we write the real
249 // header.
250 AliFMDDebug(15, ("Closing output"));
251 altro->Flush();
252 altro->WriteDataHeader(kFALSE, kFALSE);
253 delete altro;
254 altro = 0;
255 }
256 prevddl = ddl;
257 // Need to open a new DDL!
258 TString filename(AliDAQ::DdlFileName(fFMD->GetName(), ddl));
259 AliFMDDebug(5, ("New altro buffer with DDL file %s", filename.Data()));
260 // Create a new altro buffer - a `1' as the second argument
261 // means `write mode'
262 altro = new AliAltroBuffer(filename.Data());
263 altro->SetMapping(pars->GetAltroMap());
264 // Write a dummy (first argument is true) header to the DDL
265 // file - later on, when we close the file, we write the real
266 // header
267 altro->WriteDataHeader(kTRUE, kFALSE);
268 }
269
270 // Store the counts of the ADC in the channel buffer
271 AliFMDDebug(6, ("Storing FMD%d%c[%02d,%03d]-%d in timebin %d (%d)",
272 det, ring, sector, strip, j, time, preSamples));
273 UShort_t count = digit->Count(j);
274 data[time] = count;
c2fc1258 275 nWords++;
f38b1653 276 nCounts++;
277 if (time == preSamples) {
278 AliFMDDebug(5, ("Filling in %4d for %d presamples", count, preSamples));
279 for (int k = 0; k < preSamples; k++) data[k] = count;
280 nWords += preSamples;
281 }
c2fc1258 282 }
283 }
284 // Finally, we need to close the final ALTRO buffer if it wasn't
285 // already
286 if (altro) {
287 if (nWords > 0) altro->WriteChannel(prevaddr,nWords,data.fArray,threshold);
288 altro->Flush();
289 altro->WriteDataHeader(kFALSE, kFALSE);
290 delete altro;
291 }
f38b1653 292 AliFMDDebug(5, ("Wrote a total of %d words for %d counts",
293 nWords, nCounts));
c2fc1258 294}
295#else
1e8f773e 296//____________________________________________________________________
297void
298AliFMDRawWriter::WriteDigits(TClonesArray* digits)
299{
300 Int_t nDigits = digits->GetEntries();
301 if (nDigits < 1) return;
e802be3e 302
1e8f773e 303 AliFMDParameters* pars = AliFMDParameters::Instance();
304 AliFMDAltroWriter* writer = 0;
305 Int_t sampleRate = -1;
306 UShort_t hwaddr = 0;
307 UShort_t ddl = 0;
308 std::ofstream* file = 0;
309 Int_t ret = 0;
310 for (Int_t i = 0; i < nDigits; i++) {
311 // Get the digit
312 AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
313 UInt_t thisDDL, thisHwaddr;
314 UShort_t det = digit->Detector();
315 Char_t ring = digit->Ring();
316 UShort_t sector = digit->Sector();
317 UShort_t strip = digit->Strip();
318 if (!pars->Detector2Hardware(det,ring,sector,strip,thisDDL,thisHwaddr)) {
319 AliError(Form("Failed to get hardware address for FMD%d%c[%2d,%3d]",
320 det, ring, sector, strip));
321 continue;
322 }
f95a63c4 323 AliFMDDebug(40, ("Got DDL=%d and address=%d from FMD%d%c[%2d,%3d]",
1e8f773e 324 thisDDL, thisHwaddr, det, ring, sector, strip));
325 // Check if we're still in the same channel
326 if (thisHwaddr != hwaddr) {
f95a63c4 327 AliFMDDebug(30, ("Now hardware address 0x%x from FMD%d%c[%2d,%3d] "
1e8f773e 328 "(board 0x%x, chip 0x%x, channel 0x%x)",
329 thisHwaddr, det, ring, sector, strip,
330 (thisHwaddr >> 7), (thisHwaddr >> 4) & 0x7,
331 thisHwaddr & 0xf));
332 if (writer) writer->AddChannelTrailer(hwaddr);
333 hwaddr = thisHwaddr;
334 }
335 // Check if we're still in the same detector (DDL)
336 if (ddl != thisDDL) {
337 if (writer) {
f95a63c4 338 AliFMDDebug(1, ("Closing altro writer %p", writer));
1e8f773e 339 if ((ret = writer->Close()) < 0) {
340 AliError(Form("Error: %s", writer->ErrorString(ret)));
341 return;
342 }
343 delete writer;
344 writer = 0;
345 file->close();
346 delete file;
347 file = 0;
348 }
349 ddl = thisDDL;
350 }
351 // If we haven't got a writer (either because none were made so
352 // far, or because we've switch DDL), make one.
353 if (!writer) {
f95a63c4 354 AliFMDDebug(1, ("Opening new ALTRO writer w/file %s",
355 AliDAQ::DdlFileName("FMD",ddl)));
362c9d61 356 file = new std::ofstream(AliDAQ::DdlFileName("FMD",ddl));
1e8f773e 357 if (!file || !*file) {
f95a63c4 358 AliFatal(Form("Failed to open file %s",
359 AliDAQ::DdlFileName("FMD",ddl)));
1e8f773e 360 return;
361 }
362 writer = new AliFMDAltroWriter(*file);
363 writer->SetThreshold(pars->GetZeroSuppression(det, ring, sector, strip));
1e8f773e 364 }
365 // Write out our signal
c2fc1258 366 sampleRate = pars->GetSampleRate(det,ring,sector,strip);
1e8f773e 367 writer->AddSignal(digit->Count1());
368 if (sampleRate >= 2) writer->AddSignal(digit->Count2());
369 if (sampleRate >= 3) writer->AddSignal(digit->Count3());
370 }
371 if (writer) {
372 writer->AddChannelTrailer(hwaddr);
373 writer->Close();
374 delete writer;
375 file->close();
376 delete file;
377 }
378}
9f662337 379#endif
7684b53c 380
c2fc1258 381
7684b53c 382
383
e802be3e 384//____________________________________________________________________
385//
386// EOF
387//