]> git.uio.no Git - u/mrichter/AliRoot.git/blame - FMD/AliFMDRawWriter.cxx
Adding a reminder for coders
[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
e2c858f2 40#include "AliFMDDebug.h" // Better debug macros
56b1929b 41#include <AliLoader.h> // ALILOADER_H
e2c858f2 42#include <AliAltroBufferV3.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
cce354f6 50#include <TArrayF.h> // ROOT_TArrayI
51#include <TArrayC.h> // ROOT_TArrayI
e802be3e 52#include <TClonesArray.h> // ROOT_TClonesArray
c93255fe 53#include <TTree.h>
02a27b50 54// #include <fstream>
362c9d61 55#include "AliDAQ.h"
e802be3e 56
57//____________________________________________________________________
925e6570 58ClassImp(AliFMDRawWriter)
1a1fdef7 59#if 0
60 ; // This is here to keep Emacs for indenting the next line
61#endif
e802be3e 62
63//____________________________________________________________________
64AliFMDRawWriter::AliFMDRawWriter(AliFMD* fmd)
65 : TTask("FMDRawWriter", "Writer of Raw ADC values from the FMD"),
b5ee4425 66 fFMD(fmd),
67 fSampleRate(0),
68 fChannelsPerAltro(0),
69 fThreshold(0)
02a27b50 70{
71 // CTOR
ef8e8623 72 AliFMDDebug(5, ("Created AliFMDRawWriter object"));
02a27b50 73}
74
e802be3e 75
76
77//____________________________________________________________________
78void
79AliFMDRawWriter::Exec(Option_t*)
80{
81 // Turn digits into raw data.
82 //
83 // Digits are read from the Digit branch, and processed to make
84 // three DDL files, one for each of the sub-detectors FMD1, FMD2,
85 // and FMD3.
86 //
87 // The raw data files consists of a header, followed by ALTRO
88 // formatted blocks.
89 //
90 // +-------------+
91 // | Header |
92 // +-------------+
93 // | ALTRO Block |
94 // | ... |
95 // +-------------+
96 // DDL file
97 //
98 // An ALTRO formatted block, in the FMD context, consists of a
99 // number of counts followed by a trailer.
100 //
101 // +------------------+
102 // | Count |
103 // | ... |
104 // | possible fillers |
105 // +------------------+
106 // | Trailer |
107 // +------------------+
108 // ALTRO block
109 //
110 // The counts are listed backwards, that is, starting with the
111 // latest count, and ending in the first.
112 //
113 // Each count consist of 1 or more ADC samples of the VA1_ALICE
114 // pre-amp. signal. Just how many samples are used depends on
115 // whether the ALTRO over samples the pre-amp. Each sample is a
116 // 10-bit word, and the samples are grouped into 40-bit blocks
117 //
118 // +------------------------------------+
c2fc1258 119 // | S(1) | S(2) | S(3) | S(4) |
e802be3e 120 // | ... | ... | ... | ... |
c2fc1258 121 // | S(n) | T(n) | n+2 | 2AA |
e802be3e 122 // +------------------------------------+
123 // Counts + possible filler
124 //
125 // The trailer of the number of words of signales, the starting
126 // strip number, the sector number, and the ring ID; each 10-bit
127 // words, packed into 40-bits.
128 //
129 // +------------------------------------+
c2fc1258 130 // | 2AAA | Len | A | Address |
e802be3e 131 // +------------------------------------+
132 // Trailer
133 //
134 // Note, that this method assumes that the digits are ordered.
135 //
136 AliLoader* loader = fFMD->GetLoader();
ef8e8623 137 loader->LoadDigits("READ");
e802be3e 138 TTree* digitTree = loader->TreeD();
139 if (!digitTree) {
ef8e8623 140 AliError("no digit tree");
e802be3e 141 return;
142 }
143
e802be3e 144 fFMD->SetTreeAddress();
3afd9281 145 TClonesArray* digits = fFMD->Digits();
146 // new TClonesArray("AliFMDDigit", 1000);
147 // TBranch* digitBranch = digitTree->GetBranch(fFMD->GetName());
148 // if (!digitBranch) {
149 // AliError(Form("no branch for %s", fFMD->GetName()));
150 // return;
151 // }
152 // digitBranch->SetAddress(&digits);
e802be3e 153
154 Int_t nEvents = Int_t(digitTree->GetEntries());
f95a63c4 155 AliFMDDebug(5, ("Got a total of %5d events from tree", nEvents));
e802be3e 156 for (Int_t event = 0; event < nEvents; event++) {
157 fFMD->ResetDigits();
158 digitTree->GetEvent(event);
159
1e8f773e 160 // Write out the digits
161 WriteDigits(digits);
162 }
163 loader->UnloadDigits();
f5af31eb 164 //delete digits;
1e8f773e 165}
e802be3e 166
c2fc1258 167#if 1
168//____________________________________________________________________
3afd9281 169Long_t
c2fc1258 170AliFMDRawWriter::WriteDigits(TClonesArray* digits)
171{
02a27b50 172 // WRite an array of digits to disk file
c2fc1258 173 Int_t nDigits = digits->GetEntries();
3afd9281 174 if (nDigits < 1) return 0;
f95a63c4 175 AliFMDDebug(5, ("Got a total of %5d digits from tree", nDigits));
c2fc1258 176
177 AliFMDParameters* pars = AliFMDParameters::Instance();
178 UShort_t threshold = 0;
838120cd 179 UShort_t factor = 0;
f95a63c4 180 UInt_t prevddl = 0xFFFF;
c2fc1258 181 UInt_t prevaddr = 0xFFF;
182 // UShort_t prevStrip = 0;
183
184 // Which channel number in the ALTRO channel we're at
185 UShort_t nWords = 0;
186 UShort_t preSamples = 0;
f38b1653 187 UShort_t sampleRate = 0;
c2fc1258 188
189 // A buffer to hold 1 ALTRO channel - Normally, one ALTRO channel
190 // holds 128 VA1_ALICE channels, sampled at a rate of `sampleRate'
191 TArrayI data(pars->GetChannelsPerAltro() * 8);
cce354f6 192 TArrayF peds(pars->GetChannelsPerAltro() * 8);
193 TArrayF noise(pars->GetChannelsPerAltro() * 8);
c2fc1258 194
195 // The Altro buffer
e2c858f2 196 AliAltroBufferV3* altro = 0;
f38b1653 197
3afd9281 198 Int_t totalWords = 0;
199 Int_t nCounts = 0;
200 Long_t nBits = 0;
201
c2fc1258 202 // Loop over the digits in the event. Note, that we assume the
203 // the digits are in order in the branch. If they were not, we'd
204 // have to cache all channels before we could write the data to
205 // the ALTRO buffer, or we'd have to set up a map of the digits.
f95a63c4 206 UShort_t oldDet = 1000;
c2fc1258 207 for (Int_t i = 0; i < nDigits; i++) {
208 // Get the digit
209 AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
c2fc1258 210 UShort_t det = digit->Detector();
211 Char_t ring = digit->Ring();
212 UShort_t sector = digit->Sector();
213 UShort_t strip = digit->Strip();
b995fc28 214 UShort_t ddl, addr, time;
f38b1653 215
cce354f6 216 AliFMDDebug(15, ("Processing digit # %5d FMD%d%c[%2d,%3d]",
f38b1653 217 i, det, ring, sector, strip));
218 threshold = pars->GetZeroSuppression(det, ring, sector, strip);
219 sampleRate = pars->GetSampleRate(det, ring, sector, strip);
220 preSamples = pars->GetPreSamples(det, ring, sector, strip);
838120cd 221 factor = pars->GetPedestalFactor();
f38b1653 222
f95a63c4 223 if (det != oldDet) {
224 AliFMDDebug(5, ("Got new detector: %d (was %d)", det, oldDet));
838120cd 225 oldDet = det;
f95a63c4 226 }
cce354f6 227 AliFMDDebug(15, ("Sample rate is %d", sampleRate));
625d7886 228
f38b1653 229 for (UShort_t j = 0; j < sampleRate; j++) {
230 if (!pars->Detector2Hardware(det,ring,sector,strip,j,ddl,addr,time)){
231 AliError(Form("Failed to get hardware address for FMD%d%c[%2d,%3d]-%d",
232 det, ring, sector, strip, j));
233 continue;
c2fc1258 234 }
c2fc1258 235
f38b1653 236 AliFMDDebug(10, ("FMD%d%c[%2d,%3d]-%d-> 0x%x/0x%x/%04d",
237 det, ring, sector, strip, j, ddl, addr, time));
238 if (addr != prevaddr) {
239 // Flush a channel to output
240 AliFMDDebug(5, ("Now hardware address 0x%x from FMD%d%c[%2d,%3d]-%d"
241 "(b: 0x%02x, a: 0x%01x, c: 0x%02x, t: %04d), "
242 "flushing old channel at 0x%x with %d words",
243 addr, det, ring, sector, strip, j,
244 (addr >> 7), (addr >> 4) & 0x7, addr & 0xf,
245 time, prevaddr, nWords));
246 totalWords += nWords;
cce354f6 247 ZeroSuppress(data.fArray, nWords, peds.fArray, noise.fArray, threshold);
3afd9281 248 if (altro)
249 /*nBits+=*/altro->WriteChannel(prevaddr,nWords,data.fArray,threshold);
cce354f6 250 data.Reset(-1);
251 peds.Reset(0);
252 noise.Reset(0);
f38b1653 253 nWords = 0;
254 prevaddr = addr;
255 }
256 if (ddl != prevddl) {
257 AliFMDDebug(10, ("FMD: New DDL, was %d, now %d", prevddl, ddl));
258 // If an altro exists, delete the object, flushing the data to
259 // disk, and closing the file.
260 if (altro) {
261 // When the first argument is false, we write the real
262 // header.
263 AliFMDDebug(15, ("Closing output"));
838120cd 264 WriteRCUTrailer(altro, prevddl, threshold > 0, factor, sampleRate);
265
f38b1653 266 delete altro;
267 altro = 0;
268 }
269 prevddl = ddl;
270 // Need to open a new DDL!
e2c858f2 271 TString filename(AliDAQ::DdlFileName(fFMD ? fFMD->GetName() : "FMD", ddl));
f38b1653 272 AliFMDDebug(5, ("New altro buffer with DDL file %s", filename.Data()));
273 // Create a new altro buffer - a `1' as the second argument
274 // means `write mode'
e2c858f2 275 altro = new AliAltroBufferV3(filename.Data());
f38b1653 276 altro->SetMapping(pars->GetAltroMap());
277 // Write a dummy (first argument is true) header to the DDL
278 // file - later on, when we close the file, we write the real
279 // header
280 altro->WriteDataHeader(kTRUE, kFALSE);
281 }
282
cce354f6 283 // Get the pedestal value
284 peds[time] = pars->GetPedestal(det, ring, sector, strip);
285 noise[time] = pars->GetPedestalWidth(det, ring, sector, strip);
286
f38b1653 287 // Store the counts of the ADC in the channel buffer
cce354f6 288 AliFMDDebug(15, ("Storing FMD%d%c[%02d,%03d]-%d in timebin %d (%d)",
f38b1653 289 det, ring, sector, strip, j, time, preSamples));
cce354f6 290 data[time] = digit->Count(j);
c2fc1258 291 nWords++;
f38b1653 292 nCounts++;
293 if (time == preSamples) {
cce354f6 294 AliFMDDebug(15, ("Filling in %4d for %d presamples",
295 data[time], preSamples));
296 for (int k = 0; k < preSamples; k++) {
297 peds[k] = peds[time];
298 noise[k] = noise[time];
299 data[k] = data[time];
300 }
f38b1653 301 nWords += preSamples;
302 }
c2fc1258 303 }
304 }
305 // Finally, we need to close the final ALTRO buffer if it wasn't
306 // already
307 if (altro) {
cce354f6 308 ZeroSuppress(data.fArray, nWords, peds.fArray, noise.fArray, threshold);
3afd9281 309 if (nWords > 0)
310 /* nBits += */ altro->WriteChannel(prevaddr,nWords,data.fArray,threshold);
838120cd 311 WriteRCUTrailer(altro, prevddl, threshold > 0, factor, sampleRate);
c2fc1258 312 delete altro;
313 }
a828379a 314 AliFMDDebug(5, ("Wrote a total of %d words in %ld bytes for %d counts",
3afd9281 315 nWords, nBits / 8, nCounts));
316 return nBits;
c2fc1258 317}
838120cd 318//____________________________________________________________________
319void
320AliFMDRawWriter::WriteRCUTrailer(AliAltroBufferV3* altro,
321 UInt_t ddl,
322 Bool_t zs,
323 UShort_t factor,
324 UShort_t rate) const
325{
326 // Flush and write the data header
327 altro->Flush();
328 altro->WriteDataHeader(kFALSE, kFALSE);
329
330 // Set parameters in RCU trailer.
331 // Zero-suppression flag
332 altro->SetZeroSupp(zs); // bool
333 // WARNING: We store the noise factor in the 2nd baseline
334 // filters excluded post samples, since we'll never use that
335 // mode.
336 altro->SetNPostsamples(factor); //
337 // WARNING: We store the sample rate in the number of pre-trigger
338 // samples, since we'll never use that mode.
339 altro->SetNPretriggerSamples(rate); // fSampleRate[ddl]
340 // Active front-end cars
341 altro->SetActiveFECsA((ddl == 0 ? 0x1 : 0x3));
342 altro->SetActiveFECsB((ddl == 0 ? 0x1 : 0x3));
343
344 // Calculate number of samples
345 altro->SetNSamplesPerCh(rate * 128);
346 AliDebug(5,Form("Writing RCU trailer @ DDL %d w/zs=%d, factor=%d, rate=%d",
347 ddl, zs > 0, factor, rate));
348 altro->WriteRCUTrailer(ddl);
349}
350
cce354f6 351//____________________________________________________________________
352void
353AliFMDRawWriter::ZeroSuppress(Int_t*& data, Int_t nWords,
354 const Float_t* peds,
355 const Float_t* noise, UShort_t threshold) const
356{
357 // Simulate the ALTRO zero-suppression filter. The data passed in
358 // the first array is modified, such that all suppressed channels
359 // are set to some value below threshold.
360 //
361 // If threshold == 0 zero suppression is considered disabled, and no
362 // action is taken.
363 if (threshold <= 0) return;
364
365 // const Short_t width = 3;
366 // If fPedSubtract is false, compare data-(ped+f*noise), if true
367 // always modify data by -(ped+f*noise), and force negative values
368 // to zero.
369 Bool_t pedSubtract = AliFMDParameters::Instance()->IsZSPedSubtract();
370 UShort_t pre = AliFMDParameters::Instance()->GetZSPreSamples();
371 UShort_t post = AliFMDParameters::Instance()->GetZSPostSamples();
372 Float_t factor = AliFMDParameters::Instance()->GetPedestalFactor();
373
374 TArrayC mask(nWords+1);
375 for (Short_t i = 0; i < nWords; i++) {
376 Float_t val = data[i] - peds[i] - factor * noise[i];
377 if (val < 0.5) val = 0;
378 if (pedSubtract) data[i] = Int_t(val) & 0x3FF;
379
380 mask[i] = (val > threshold ? 1 : 0);
381 AliFMDDebug(10, ("Comparing sample %d %d-%f-%f*%f=%f to %d -> %s",
382 i, data[i], peds[i], factor, noise[i], val, threshold,
383 (mask[i] ? "above" : "below")));
384 }
385
386 for (Short_t i = 0; i < nWords; i++) {
387 if (mask[i]) { // Signal above, so do nothing
388 AliFMDDebug(10, ("Sample %d, above", i));
389 if (i < nWords-1 && !mask[i+1]) {
390 // After a valid sample. Increase the pointer to the next
391 // possible data, thereby skipping over the post-samples
392 AliFMDDebug(10, ("At sample %d, next is below, skipping %d to %d",
393 i, post, i+post));
394 i += post;
395 }
396 continue;
397 }
398
399 Short_t lookahead = TMath::Min(Short_t(nWords), Short_t(i+pre));
400 AliFMDDebug(10, ("Sample %d, below, look to %d", i, lookahead));
401 if (mask[lookahead] && pre > 0) {
402 AliFMDDebug(10, ("Sample %d is a pre-sample to %d", i, lookahead));
403 // We're in a presample, so don't modify the data, and increase
404 // counter by the number of pre-samples
405 i += pre-1;
406 continue;
407 }
408
409 // This sample must be surpressed
410 data[i] = threshold - 1;
411 }
412}
413
c2fc1258 414#else
1e8f773e 415//____________________________________________________________________
416void
417AliFMDRawWriter::WriteDigits(TClonesArray* digits)
418{
09b6c804 419 //
420 // Write digits to file
421 //
1e8f773e 422 Int_t nDigits = digits->GetEntries();
423 if (nDigits < 1) return;
e802be3e 424
1e8f773e 425 AliFMDParameters* pars = AliFMDParameters::Instance();
426 AliFMDAltroWriter* writer = 0;
427 Int_t sampleRate = -1;
428 UShort_t hwaddr = 0;
429 UShort_t ddl = 0;
430 std::ofstream* file = 0;
431 Int_t ret = 0;
432 for (Int_t i = 0; i < nDigits; i++) {
433 // Get the digit
434 AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
435 UInt_t thisDDL, thisHwaddr;
436 UShort_t det = digit->Detector();
437 Char_t ring = digit->Ring();
438 UShort_t sector = digit->Sector();
439 UShort_t strip = digit->Strip();
440 if (!pars->Detector2Hardware(det,ring,sector,strip,thisDDL,thisHwaddr)) {
441 AliError(Form("Failed to get hardware address for FMD%d%c[%2d,%3d]",
442 det, ring, sector, strip));
443 continue;
444 }
f95a63c4 445 AliFMDDebug(40, ("Got DDL=%d and address=%d from FMD%d%c[%2d,%3d]",
1e8f773e 446 thisDDL, thisHwaddr, det, ring, sector, strip));
447 // Check if we're still in the same channel
448 if (thisHwaddr != hwaddr) {
f95a63c4 449 AliFMDDebug(30, ("Now hardware address 0x%x from FMD%d%c[%2d,%3d] "
1e8f773e 450 "(board 0x%x, chip 0x%x, channel 0x%x)",
451 thisHwaddr, det, ring, sector, strip,
452 (thisHwaddr >> 7), (thisHwaddr >> 4) & 0x7,
453 thisHwaddr & 0xf));
454 if (writer) writer->AddChannelTrailer(hwaddr);
455 hwaddr = thisHwaddr;
456 }
457 // Check if we're still in the same detector (DDL)
458 if (ddl != thisDDL) {
459 if (writer) {
f95a63c4 460 AliFMDDebug(1, ("Closing altro writer %p", writer));
1e8f773e 461 if ((ret = writer->Close()) < 0) {
462 AliError(Form("Error: %s", writer->ErrorString(ret)));
463 return;
464 }
465 delete writer;
466 writer = 0;
467 file->close();
468 delete file;
469 file = 0;
470 }
471 ddl = thisDDL;
472 }
473 // If we haven't got a writer (either because none were made so
474 // far, or because we've switch DDL), make one.
475 if (!writer) {
f95a63c4 476 AliFMDDebug(1, ("Opening new ALTRO writer w/file %s",
477 AliDAQ::DdlFileName("FMD",ddl)));
362c9d61 478 file = new std::ofstream(AliDAQ::DdlFileName("FMD",ddl));
1e8f773e 479 if (!file || !*file) {
f95a63c4 480 AliFatal(Form("Failed to open file %s",
481 AliDAQ::DdlFileName("FMD",ddl)));
1e8f773e 482 return;
483 }
484 writer = new AliFMDAltroWriter(*file);
485 writer->SetThreshold(pars->GetZeroSuppression(det, ring, sector, strip));
1e8f773e 486 }
487 // Write out our signal
c2fc1258 488 sampleRate = pars->GetSampleRate(det,ring,sector,strip);
1e8f773e 489 writer->AddSignal(digit->Count1());
490 if (sampleRate >= 2) writer->AddSignal(digit->Count2());
491 if (sampleRate >= 3) writer->AddSignal(digit->Count3());
492 }
493 if (writer) {
494 writer->AddChannelTrailer(hwaddr);
495 writer->Close();
496 delete writer;
497 file->close();
498 delete file;
499 }
500}
9f662337 501#endif
7684b53c 502
c2fc1258 503
7684b53c 504
505
e802be3e 506//____________________________________________________________________
507//
508// EOF
509//
6c652449 510