New defaults values
[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 **************************************************************************/
15
16/* $Id$ */
17
18//____________________________________________________________________
19//
20// Class to write ADC values to a raw data file
21//
7684b53c 22// This class writes FMD Raw data to a file. The sample rate (number
23// of times the ALTRO ADC samples each pre-amp. channel - that is,
24// data from a single strip), can be set via SetSampleRate.
25//
26// Zero-suppression can be enabled by calling SetThreshold with a
27// non-zero argument. ADC values less than the value set will not be
28// written to output. Note, that if you use zero-suppression, you
29// need to explicitly set the sample rate when reading back the data
30// with AliFMDRawReader.
31//
32// This class uses the AliAltroBuffer class to write the data in the
33// ALTRO format. See the Exec member function for more information on
34// that format.
35//
56b1929b 36#include <AliLog.h> // ALILOG_H
37#include <AliLoader.h> // ALILOADER_H
38#include <AliAltroBuffer.h> // ALIALTROBUFFER_H
e802be3e 39#include "AliFMD.h" // ALIFMD_H
1a1fdef7 40#include "AliFMDParameters.h" // ALIFMDPARAMETERS_H
e802be3e 41#include "AliFMDDigit.h" // ALIFMDDIGIT_H
42#include "AliFMDRawWriter.h" // ALIFMDRAWREADER_H
56b1929b 43#include <TArrayI.h> // ROOT_TArrayI
e802be3e 44#include <TClonesArray.h> // ROOT_TClonesArray
45
46//____________________________________________________________________
925e6570 47ClassImp(AliFMDRawWriter)
1a1fdef7 48#if 0
49 ; // This is here to keep Emacs for indenting the next line
50#endif
e802be3e 51
52//____________________________________________________________________
53AliFMDRawWriter::AliFMDRawWriter(AliFMD* fmd)
54 : TTask("FMDRawWriter", "Writer of Raw ADC values from the FMD"),
55 fFMD(fmd)
56{
1a1fdef7 57 AliFMDParameters* pars = AliFMDParameters::Instance();
8f6ee336 58 fSampleRate = pars->GetSampleRate(AliFMDParameters::kBaseDDL);
1a1fdef7 59 fChannelsPerAltro = pars->GetChannelsPerAltro();
e802be3e 60}
61
62
63//____________________________________________________________________
64void
65AliFMDRawWriter::Exec(Option_t*)
66{
67 // Turn digits into raw data.
68 //
69 // Digits are read from the Digit branch, and processed to make
70 // three DDL files, one for each of the sub-detectors FMD1, FMD2,
71 // and FMD3.
72 //
73 // The raw data files consists of a header, followed by ALTRO
74 // formatted blocks.
75 //
76 // +-------------+
77 // | Header |
78 // +-------------+
79 // | ALTRO Block |
80 // | ... |
81 // +-------------+
82 // DDL file
83 //
84 // An ALTRO formatted block, in the FMD context, consists of a
85 // number of counts followed by a trailer.
86 //
87 // +------------------+
88 // | Count |
89 // | ... |
90 // | possible fillers |
91 // +------------------+
92 // | Trailer |
93 // +------------------+
94 // ALTRO block
95 //
96 // The counts are listed backwards, that is, starting with the
97 // latest count, and ending in the first.
98 //
99 // Each count consist of 1 or more ADC samples of the VA1_ALICE
100 // pre-amp. signal. Just how many samples are used depends on
101 // whether the ALTRO over samples the pre-amp. Each sample is a
102 // 10-bit word, and the samples are grouped into 40-bit blocks
103 //
104 // +------------------------------------+
105 // | S(n) | S(n-1) | S(n-2) | S(n-3) |
106 // | ... | ... | ... | ... |
107 // | S(2) | S(1) | AA | AA |
108 // +------------------------------------+
109 // Counts + possible filler
110 //
111 // The trailer of the number of words of signales, the starting
112 // strip number, the sector number, and the ring ID; each 10-bit
113 // words, packed into 40-bits.
114 //
115 // +------------------------------------+
116 // | # words | start | sector | ring |
117 // +------------------------------------+
118 // Trailer
119 //
120 // Note, that this method assumes that the digits are ordered.
121 //
122 AliLoader* loader = fFMD->GetLoader();
123 loader->LoadDigits();
124 TTree* digitTree = loader->TreeD();
125 if (!digitTree) {
126 Error("Digits2Raw", "no digit tree");
127 return;
128 }
129
130 TClonesArray* digits = new TClonesArray("AliFMDDigit", 1000);
131 fFMD->SetTreeAddress();
132 TBranch* digitBranch = digitTree->GetBranch(fFMD->GetName());
133 if (!digitBranch) {
134 Error("Digits2Raw", "no branch for %s", fFMD->GetName());
135 return;
136 }
137 digitBranch->SetAddress(&digits);
138
8f6ee336 139 AliFMDParameters* pars = AliFMDParameters::Instance();
e802be3e 140 Int_t nEvents = Int_t(digitTree->GetEntries());
141 for (Int_t event = 0; event < nEvents; event++) {
142 fFMD->ResetDigits();
143 digitTree->GetEvent(event);
144
145 Int_t nDigits = digits->GetEntries();
146 if (nDigits < 1) continue;
147
148
149 UShort_t prevDetector = 0;
150 Char_t prevRing = '\0';
151 UShort_t prevSector = 0;
152 // UShort_t prevStrip = 0;
153
154 // The first seen strip number for a channel
155 UShort_t startStrip = 0;
156
157 // Which channel number in the ALTRO channel we're at
158 UShort_t offset = 0;
159
160 // How many times the ALTRO Samples one VA1_ALICE channel
161 Int_t sampleRate = 1;
162
163 // A buffer to hold 1 ALTRO channel - Normally, one ALTRO channel
164 // holds 128 VA1_ALICE channels, sampled at a rate of `sampleRate'
7684b53c 165 TArrayI channel(fChannelsPerAltro * sampleRate);
e802be3e 166
167 // The Altro buffer
168 AliAltroBuffer* altro = 0;
169
170 // Loop over the digits in the event. Note, that we assume the
171 // the digits are in order in the branch. If they were not, we'd
172 // have to cache all channels before we could write the data to
173 // the ALTRO buffer, or we'd have to set up a map of the digits.
174 for (Int_t i = 0; i < nDigits; i++) {
175 // Get the digit
176 AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
177
178 UShort_t det = digit->Detector();
179 Char_t ring = digit->Ring();
180 UShort_t sector = digit->Sector();
181 UShort_t strip = digit->Strip();
8f6ee336 182 fThreshold = pars->GetZeroSuppression(det, ring, sector, strip);
e802be3e 183 if (det != prevDetector) {
1a1fdef7 184 AliDebug(15, Form("FMD: New DDL, was %d, now %d",
185 AliFMDParameters::kBaseDDL + prevDetector - 1,
186 AliFMDParameters::kBaseDDL + det - 1));
e802be3e 187 // If an altro exists, delete the object, flushing the data to
188 // disk, and closing the file.
189 if (altro) {
190 // When the first argument is false, we write the real
191 // header.
1a1fdef7 192 AliDebug(15, Form("New altro: Write channel at %d Strip: %d "
e802be3e 193 "Sector: %d Ring: %d",
194 i, startStrip, prevSector, prevRing));
195 // TPC to FMD translations
196 //
197 // TPC FMD
198 // ----------+-----------
199 // pad | strip
200 // row | sector
201 // sector | ring
202 //
7684b53c 203 WriteChannel(altro, startStrip, prevSector, prevRing, channel);
e802be3e 204 altro->Flush();
205 altro->WriteDataHeader(kFALSE, kFALSE);
206 delete altro;
207 altro = 0;
208 }
209
210 prevDetector = det;
211 // Need to open a new DDL!
1a1fdef7 212 Int_t ddlId = AliFMDParameters::kBaseDDL + det - 1;
e802be3e 213 TString filename(Form("%s_%d.ddl", fFMD->GetName(), ddlId));
214
1a1fdef7 215 AliDebug(15, Form("New altro buffer with DDL file %s",
e802be3e 216 filename.Data()));
1a1fdef7 217 AliDebug(15, Form("New altro at %d", i));
e802be3e 218 // Create a new altro buffer - a `1' as the second argument
219 // means `write mode'
220 altro = new AliAltroBuffer(filename.Data(), 1);
221
222 // Write a dummy (first argument is true) header to the DDL
223 // file - later on, when we close the file, we write the real
224 // header
225 altro->WriteDataHeader(kTRUE, kFALSE);
226
227 // Figure out the sample rate
228 if (fSampleRate > 0) sampleRate = fSampleRate;
229 else {
230 if (digit->Count2() >= 0) sampleRate = 2;
231 if (digit->Count3() >= 0) sampleRate = 3;
232 }
233
7684b53c 234 channel.Set(fChannelsPerAltro * sampleRate);
e802be3e 235 offset = 0;
236 prevRing = ring;
237 prevSector = sector;
238 startStrip = strip;
239 }
7684b53c 240 else if (offset == fChannelsPerAltro
e802be3e 241 || digit->Ring() != prevRing
242 || digit->Sector() != prevSector) {
243 // Force a new Altro channel
1a1fdef7 244 AliDebug(15, Form("Flushing channel to disk because %s",
7684b53c 245 (offset == fChannelsPerAltro ? "channel is full" :
e802be3e 246 (ring != prevRing ? "new ring up" :
247 "new sector up"))));
1a1fdef7 248 AliDebug(15, Form("New Channel: Write channel at %d Strip: %d "
e802be3e 249 "Sector: %d Ring: %d",
250 i, startStrip, prevSector, prevRing));
7684b53c 251 WriteChannel(altro, startStrip, prevSector, prevRing, channel);
e802be3e 252 // Reset and update channel variables
253 channel.Reset(0);
254 offset = 0;
255 startStrip = strip;
256 prevRing = ring;
257 prevSector = sector;
258 }
259
260 // Store the counts of the ADC in the channel buffer
261 channel[offset * sampleRate] = digit->Count1();
262 if (sampleRate > 1)
263 channel[offset * sampleRate + 1] = digit->Count2();
264 if (sampleRate > 2)
265 channel[offset * sampleRate + 2] = digit->Count3();
266 offset++;
267 }
268 // Finally, we need to close the final ALTRO buffer if it wasn't
269 // already
270 if (altro) {
271 altro->Flush();
272 altro->WriteDataHeader(kFALSE, kFALSE);
273 delete altro;
274 }
275 }
276 loader->UnloadDigits();
277}
278
279//____________________________________________________________________
7684b53c 280void
281AliFMDRawWriter::WriteChannel(AliAltroBuffer* altro,
282 UShort_t strip, UShort_t sector, Char_t ring,
283 const TArrayI& data)
284{
285 // Write out one ALTRO channel to the data file.
286 // Derived classes can overload this method to use a per-ALTRO
287 // threshold. This implementation uses the common threshold set by
288 // SetThreshold.
289 altro->WriteChannel(Int_t(strip),
290 Int_t(sector),
291 Int_t((ring == 'I' ? 0 : 1)),
292 data.fN, data.fArray, fThreshold);
293}
294
295
296
297//____________________________________________________________________
e802be3e 298//
299// EOF
300//