AliRoot Core  3dc7879 (3dc7879)
AliFMDRawWriter.cxx
Go to the documentation of this file.
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  **************************************************************************/
15 /* $Id$ */
21 //____________________________________________________________________
22 //
23 // Class to write ADC values to a raw data file
24 //
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 //
39 // #include <AliLog.h> // ALILOG_H
40 #include "AliFMDDebug.h" // Better debug macros
41 #include <AliLoader.h> // ALILOADER_H
42 #include <AliAltroBufferV3.h> // ALIALTROBUFFER_H
43 #include "AliFMD.h" // ALIFMD_H
44 #include "AliFMDParameters.h" // ALIFMDPARAMETERS_H
45 #include "AliFMDDigit.h" // ALIFMDDIGIT_H
46 #include "AliFMDRawWriter.h" // ALIFMDRAWREADER_H
47 #include "AliFMDAltroMapping.h" // ALIFMDALTROMAPPING_H
48 // #include "AliFMDAltroIO.h" // ALIFMDALTROWRITER_H
49 #include <TArrayI.h> // ROOT_TArrayI
50 #include <TArrayF.h> // ROOT_TArrayI
51 #include <TArrayC.h> // ROOT_TArrayI
52 #include <TClonesArray.h> // ROOT_TClonesArray
53 #include <TTree.h>
54 // #include <fstream>
55 #include "AliDAQ.h"
56 
57 //____________________________________________________________________
58 ClassImp(AliFMDRawWriter)
59 #if 0
60  ; // This is here to keep Emacs for indenting the next line
61 #endif
62 
63 //____________________________________________________________________
65  : TTask("FMDRawWriter", "Writer of Raw ADC values from the FMD"),
66  fFMD(fmd),
67  fSampleRate(0),
68  fChannelsPerAltro(0),
69  fThreshold(0)
70 {
71  // CTOR
72  AliFMDDebug(5, ("Created AliFMDRawWriter object"));
73 }
74 
75 
76 
77 //____________________________________________________________________
78 void
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  // +------------------------------------+
119  // | S(1) | S(2) | S(3) | S(4) |
120  // | ... | ... | ... | ... |
121  // | S(n) | T(n) | n+2 | 2AA |
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  // +------------------------------------+
130  // | 2AAA | Len | A | Address |
131  // +------------------------------------+
132  // Trailer
133  //
134  // Note, that this method assumes that the digits are ordered.
135  //
136  AliLoader* loader = fFMD->GetLoader();
137  loader->LoadDigits("READ");
138  TTree* digitTree = loader->TreeD();
139  if (!digitTree) {
140  AliError("no digit tree");
141  return;
142  }
143 
144  fFMD->SetTreeAddress();
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);
153 
154  Int_t nEvents = Int_t(digitTree->GetEntries());
155  AliFMDDebug(5, ("Got a total of %5d events from tree", nEvents));
156  for (Int_t event = 0; event < nEvents; event++) {
157  fFMD->ResetDigits();
158  digitTree->GetEvent(event);
159 
160  // Write out the digits
161  WriteDigits(digits);
162  }
163  loader->UnloadDigits();
164  //delete digits;
165 }
166 
167 #if 1
168 //____________________________________________________________________
169 Long_t
170 AliFMDRawWriter::WriteDigits(TClonesArray* digits)
171 {
172  // WRite an array of digits to disk file
173  Int_t nDigits = digits->GetEntries();
174  if (nDigits < 1) return 0;
175  AliFMDDebug(5, ("Got a total of %5d digits from tree", nDigits));
176 
178  UShort_t threshold = 0;
179  UShort_t factor = 0;
180  UInt_t prevddl = 0xFFFF;
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;
187  UShort_t sampleRate = 0;
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);
192  TArrayF peds(pars->GetChannelsPerAltro() * 8);
193  TArrayF noise(pars->GetChannelsPerAltro() * 8);
194 
195  // The Altro buffer
196  AliAltroBufferV3* altro = 0;
197 
198  Int_t totalWords = 0;
199  Int_t nCounts = 0;
200  Long_t nBits = 0;
201 
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.
206  UShort_t oldDet = 1000;
207  for (Int_t i = 0; i < nDigits; i++) {
208  // Get the digit
209  AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
210  UShort_t det = digit->Detector();
211  Char_t ring = digit->Ring();
212  UShort_t sector = digit->Sector();
213  UShort_t strip = digit->Strip();
214  UShort_t ddl, addr, time;
215 
216  AliFMDDebug(15, ("Processing digit # %5d FMD%d%c[%2d,%3d]",
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);
221  factor = UShort_t(pars->GetPedestalFactor());
222 
223  if (det != oldDet) {
224  AliFMDDebug(5, ("Got new detector: %d (was %d)", det, oldDet));
225  oldDet = det;
226  }
227  AliFMDDebug(15, ("Sample rate is %d", sampleRate));
228 
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;
234  }
235 
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;
247  ZeroSuppress(data.fArray, nWords, peds.fArray, noise.fArray, threshold);
248  if (altro)
249  /*nBits+=*/altro->WriteChannel(prevaddr,nWords,data.fArray,threshold);
250  data.Reset(-1);
251  peds.Reset(0);
252  noise.Reset(0);
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"));
264  WriteRCUTrailer(altro, prevddl, threshold > 0, factor, sampleRate);
265 
266  delete altro;
267  altro = 0;
268  }
269  prevddl = ddl;
270  // Need to open a new DDL!
271  TString filename(AliDAQ::DdlFileName(fFMD ? fFMD->GetName() : "FMD", ddl));
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'
275  altro = new AliAltroBufferV3(filename.Data());
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 
283  // Get the pedestal value
284  peds[time] = pars->GetPedestal(det, ring, sector, strip);
285  noise[time] = pars->GetPedestalWidth(det, ring, sector, strip);
286 
287  // Store the counts of the ADC in the channel buffer
288  AliFMDDebug(15, ("Storing FMD%d%c[%02d,%03d]-%d in timebin %d (%d)",
289  det, ring, sector, strip, j, time, preSamples));
290  data[time] = digit->Count(j);
291  nWords++;
292  nCounts++;
293  if (time == preSamples) {
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  }
301  nWords += preSamples;
302  }
303  }
304  }
305  // Finally, we need to close the final ALTRO buffer if it wasn't
306  // already
307  if (altro) {
308  ZeroSuppress(data.fArray, nWords, peds.fArray, noise.fArray, threshold);
309  if (nWords > 0)
310  /* nBits += */ altro->WriteChannel(prevaddr,nWords,data.fArray,threshold);
311  WriteRCUTrailer(altro, prevddl, threshold > 0, factor, sampleRate);
312  delete altro;
313  }
314  AliFMDDebug(5, ("Wrote a total of %d words in %ld bytes for %d counts",
315  nWords, nBits / 8, nCounts));
316  return nBits;
317 }
318 //____________________________________________________________________
319 void
320 AliFMDRawWriter::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  altro->SetNNonZSPostsamples(factor);
338  // WARNING: We store the sample rate in the number of pre-trigger
339  // samples, since we'll never use that mode.
340  altro->SetNPretriggerSamples(rate); // fSampleRate[ddl]
341  // Active front-end cars
342  altro->SetActiveFECsA((ddl == 0 ? 0x1 : 0x3));
343  altro->SetActiveFECsB((ddl == 0 ? 0x1 : 0x3));
344 
345  // Calculate number of samples
346  altro->SetNSamplesPerCh(rate * 128);
347  AliDebug(5,Form("Writing RCU trailer @ DDL %d w/zs=%d, factor=%d, rate=%d",
348  ddl, zs > 0, factor, rate));
349  altro->WriteRCUTrailer(ddl);
350 }
351 
352 //____________________________________________________________________
353 void
354 AliFMDRawWriter::ZeroSuppress(Int_t*& data, Int_t nWords,
355  const Float_t* peds,
356  const Float_t* noise, UShort_t threshold) const
357 {
358  // Simulate the ALTRO zero-suppression filter. The data passed in
359  // the first array is modified, such that all suppressed channels
360  // are set to some value below threshold.
361  //
362  // If threshold == 0 zero suppression is considered disabled, and no
363  // action is taken.
364  if (threshold <= 0) return;
365 
366  // const Short_t width = 3;
367  // If fPedSubtract is false, compare data-(ped+f*noise), if true
368  // always modify data by -(ped+f*noise), and force negative values
369  // to zero.
370  Bool_t pedSubtract = AliFMDParameters::Instance()->IsZSPedSubtract();
371  UShort_t pre = AliFMDParameters::Instance()->GetZSPreSamples();
372  UShort_t post = AliFMDParameters::Instance()->GetZSPostSamples();
373  Float_t factor = AliFMDParameters::Instance()->GetPedestalFactor();
374 
375  TArrayC mask(nWords+1);
376  for (Short_t i = 0; i < nWords; i++) {
377  Float_t val = data[i] - peds[i] - factor * noise[i];
378  if (val < 0.5) val = 0;
379  if (pedSubtract) data[i] = Int_t(val) & 0x3FF;
380 
381  mask[i] = (val > threshold ? 1 : 0);
382  AliFMDDebug(10, ("Comparing sample %d %d-%f-%f*%f=%f to %d -> %s",
383  i, data[i], peds[i], factor, noise[i], val, threshold,
384  (mask[i] ? "above" : "below")));
385  }
386 
387  for (Short_t i = 0; i < nWords; i++) {
388  if (mask[i]) { // Signal above, so do nothing
389  AliFMDDebug(10, ("Sample %d, above", i));
390  if (i < nWords-1 && !mask[i+1]) {
391  // After a valid sample. Increase the pointer to the next
392  // possible data, thereby skipping over the post-samples
393  AliFMDDebug(10, ("At sample %d, next is below, skipping %d to %d",
394  i, post, i+post));
395  i += post;
396  }
397  continue;
398  }
399 
400  Short_t lookahead = TMath::Min(Short_t(nWords), Short_t(i+pre));
401  AliFMDDebug(10, ("Sample %d, below, look to %d", i, lookahead));
402  if (mask[lookahead] && pre > 0) {
403  AliFMDDebug(10, ("Sample %d is a pre-sample to %d", i, lookahead));
404  // We're in a presample, so don't modify the data, and increase
405  // counter by the number of pre-samples
406  i += pre-1;
407  continue;
408  }
409 
410  // This sample must be surpressed
411  data[i] = threshold - 1;
412  }
413 }
414 
415 #else
416 //____________________________________________________________________
417 void
418 AliFMDRawWriter::WriteDigits(TClonesArray* digits)
419 {
420  //
421  // Write digits to file
422  //
423  Int_t nDigits = digits->GetEntries();
424  if (nDigits < 1) return;
425 
427  AliFMDAltroWriter* writer = 0;
428  Int_t sampleRate = -1;
429  UShort_t hwaddr = 0;
430  UShort_t ddl = 0;
431  std::ofstream* file = 0;
432  Int_t ret = 0;
433  for (Int_t i = 0; i < nDigits; i++) {
434  // Get the digit
435  AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
436  UInt_t thisDDL, thisHwaddr;
437  UShort_t det = digit->Detector();
438  Char_t ring = digit->Ring();
439  UShort_t sector = digit->Sector();
440  UShort_t strip = digit->Strip();
441  if (!pars->Detector2Hardware(det,ring,sector,strip,thisDDL,thisHwaddr)) {
442  AliError(Form("Failed to get hardware address for FMD%d%c[%2d,%3d]",
443  det, ring, sector, strip));
444  continue;
445  }
446  AliFMDDebug(40, ("Got DDL=%d and address=%d from FMD%d%c[%2d,%3d]",
447  thisDDL, thisHwaddr, det, ring, sector, strip));
448  // Check if we're still in the same channel
449  if (thisHwaddr != hwaddr) {
450  AliFMDDebug(30, ("Now hardware address 0x%x from FMD%d%c[%2d,%3d] "
451  "(board 0x%x, chip 0x%x, channel 0x%x)",
452  thisHwaddr, det, ring, sector, strip,
453  (thisHwaddr >> 7), (thisHwaddr >> 4) & 0x7,
454  thisHwaddr & 0xf));
455  if (writer) writer->AddChannelTrailer(hwaddr);
456  hwaddr = thisHwaddr;
457  }
458  // Check if we're still in the same detector (DDL)
459  if (ddl != thisDDL) {
460  if (writer) {
461  AliFMDDebug(1, ("Closing altro writer %p", writer));
462  if ((ret = writer->Close()) < 0) {
463  AliError(Form("Error: %s", writer->ErrorString(ret)));
464  return;
465  }
466  delete writer;
467  writer = 0;
468  file->close();
469  delete file;
470  file = 0;
471  }
472  ddl = thisDDL;
473  }
474  // If we haven't got a writer (either because none were made so
475  // far, or because we've switch DDL), make one.
476  if (!writer) {
477  AliFMDDebug(1, ("Opening new ALTRO writer w/file %s",
478  AliDAQ::DdlFileName("FMD",ddl)));
479  file = new std::ofstream(AliDAQ::DdlFileName("FMD",ddl));
480  if (!file || !*file) {
481  AliFatal(Form("Failed to open file %s",
482  AliDAQ::DdlFileName("FMD",ddl)));
483  return;
484  }
485  writer = new AliFMDAltroWriter(*file);
486  writer->SetThreshold(pars->GetZeroSuppression(det, ring, sector, strip));
487  }
488  // Write out our signal
489  sampleRate = pars->GetSampleRate(det,ring,sector,strip);
490  writer->AddSignal(digit->Count1());
491  if (sampleRate >= 2) writer->AddSignal(digit->Count2());
492  if (sampleRate >= 3) writer->AddSignal(digit->Count3());
493  }
494  if (writer) {
495  writer->AddChannelTrailer(hwaddr);
496  writer->Close();
497  delete writer;
498  file->close();
499  delete file;
500  }
501 }
502 #endif
503 
504 
505 
506 
507 //____________________________________________________________________
508 //
509 // EOF
510 //
511 
class for digits
Definition: AliFMDDigit.h:28
static const char * DdlFileName(const char *detectorName, Int_t ddlIndex)
Definition: AliDAQ.cxx:329
UShort_t GetZeroSuppression(UShort_t detector, Char_t ring, UShort_t sector, UShort_t strip) const
TClonesArray * Digits() const
Definition: AliDetector.h:34
AliFMDRawWriter(AliFMD *fmd)
Digits for the FMD.
UShort_t Sector() const
void ZeroSuppress(Int_t *&data, Int_t nWords, const Float_t *peds, const Float_t *noise, UShort_t threshold) const
Char_t Ring() const
Class to write ALTRO formated raw data from an array of AliFMDDigit objects.
This class is a singleton that handles various parameters of the FMD detectors. This class reads from...
Manager of FMD parameters.
AliFMDAltroMapping * GetAltroMap() const
TTree * TreeD() const
Definition: AliLoader.h:87
Short_t Count2() const
Definition: AliFMDDigit.h:74
Forward Multiplicity Detector based on Silicon wafers. This class is the driver for especially simula...
Definition: AliFMD.h:306
UShort_t GetZSPostSamples() const
UShort_t Count1() const
Definition: AliFMDDigit.h:69
Map HW address to detector coordinates and back again.
void UnloadDigits() const
Definition: AliLoader.h:131
Declaration of AliFMD detector driver.
virtual void SetTreeAddress()
Definition: AliFMD.cxx:589
UShort_t Strip() const
#define AliFMDDebug(N, A)
Definition: AliFMDDebug.h:39
virtual Long_t WriteDigits(TClonesArray *digits)
static AliFMDParameters * Instance()
#define AliFatal(message)
Definition: AliLog.h:640
Class to write raw data.
virtual void Exec(Option_t *option="")
#define AliDebug(logLevel, message)
Definition: AliLog.h:300
UShort_t GetPreSamples(UShort_t, Char_t, UShort_t, UShort_t) const
AliLoader * GetLoader() const
Definition: AliDetector.h:67
Bool_t Detector2Hardware(UShort_t det, Char_t ring, UShort_t sec, UShort_t str, UShort_t sam, UShort_t &ddl, UShort_t &board, UShort_t &altro, UShort_t &channel, UShort_t &timebin) const
UShort_t Detector() const
void WriteRCUTrailer(AliAltroBufferV3 *altro, UInt_t ddl, Bool_t zs, UShort_t factor, UShort_t rate) const
#define AliError(message)
Definition: AliLog.h:591
Float_t GetPedestalFactor() const
UShort_t GetZSPreSamples() const
Int_t LoadDigits(Option_t *opt="")
Definition: AliLoader.h:106
virtual void ResetDigits()
Int_t Count(UShort_t i=0) const
Definition: AliFMDDigit.h:156
Float_t GetPedestal(UShort_t detector, Char_t ring, UShort_t sector, UShort_t strip) const
Float_t GetPedestalWidth(UShort_t detector, Char_t ring, UShort_t sector, UShort_t strip) const
UShort_t GetChannelsPerAltro() const
UShort_t GetSampleRate(UShort_t detector, Char_t ring, UShort_t sector, UShort_t strip) const
Bool_t IsZSPedSubtract() const
Short_t Count3() const
Definition: AliFMDDigit.h:79