Fixed AreNeighbours()
[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//
56b1929b 39#include <AliLog.h> // ALILOG_H
40#include <AliLoader.h> // ALILOADER_H
41#include <AliAltroBuffer.h> // ALIALTROBUFFER_H
e802be3e 42#include "AliFMD.h" // ALIFMD_H
1a1fdef7 43#include "AliFMDParameters.h" // ALIFMDPARAMETERS_H
e802be3e 44#include "AliFMDDigit.h" // ALIFMDDIGIT_H
45#include "AliFMDRawWriter.h" // ALIFMDRAWREADER_H
1e8f773e 46#include "AliFMDAltroMapping.h" // ALIFMDALTROMAPPING_H
c2fc1258 47// #include "AliFMDAltroIO.h" // ALIFMDALTROWRITER_H
56b1929b 48#include <TArrayI.h> // ROOT_TArrayI
e802be3e 49#include <TClonesArray.h> // ROOT_TClonesArray
02a27b50 50// #include <fstream>
362c9d61 51#include "AliDAQ.h"
e802be3e 52
53//____________________________________________________________________
925e6570 54ClassImp(AliFMDRawWriter)
1a1fdef7 55#if 0
56 ; // This is here to keep Emacs for indenting the next line
57#endif
e802be3e 58
59//____________________________________________________________________
60AliFMDRawWriter::AliFMDRawWriter(AliFMD* fmd)
61 : TTask("FMDRawWriter", "Writer of Raw ADC values from the FMD"),
b5ee4425 62 fFMD(fmd),
63 fSampleRate(0),
64 fChannelsPerAltro(0),
65 fThreshold(0)
02a27b50 66{
67 // CTOR
68}
69
e802be3e 70
71
72//____________________________________________________________________
73void
74AliFMDRawWriter::Exec(Option_t*)
75{
76 // Turn digits into raw data.
77 //
78 // Digits are read from the Digit branch, and processed to make
79 // three DDL files, one for each of the sub-detectors FMD1, FMD2,
80 // and FMD3.
81 //
82 // The raw data files consists of a header, followed by ALTRO
83 // formatted blocks.
84 //
85 // +-------------+
86 // | Header |
87 // +-------------+
88 // | ALTRO Block |
89 // | ... |
90 // +-------------+
91 // DDL file
92 //
93 // An ALTRO formatted block, in the FMD context, consists of a
94 // number of counts followed by a trailer.
95 //
96 // +------------------+
97 // | Count |
98 // | ... |
99 // | possible fillers |
100 // +------------------+
101 // | Trailer |
102 // +------------------+
103 // ALTRO block
104 //
105 // The counts are listed backwards, that is, starting with the
106 // latest count, and ending in the first.
107 //
108 // Each count consist of 1 or more ADC samples of the VA1_ALICE
109 // pre-amp. signal. Just how many samples are used depends on
110 // whether the ALTRO over samples the pre-amp. Each sample is a
111 // 10-bit word, and the samples are grouped into 40-bit blocks
112 //
113 // +------------------------------------+
c2fc1258 114 // | S(1) | S(2) | S(3) | S(4) |
e802be3e 115 // | ... | ... | ... | ... |
c2fc1258 116 // | S(n) | T(n) | n+2 | 2AA |
e802be3e 117 // +------------------------------------+
118 // Counts + possible filler
119 //
120 // The trailer of the number of words of signales, the starting
121 // strip number, the sector number, and the ring ID; each 10-bit
122 // words, packed into 40-bits.
123 //
124 // +------------------------------------+
c2fc1258 125 // | 2AAA | Len | A | Address |
e802be3e 126 // +------------------------------------+
127 // Trailer
128 //
129 // Note, that this method assumes that the digits are ordered.
130 //
131 AliLoader* loader = fFMD->GetLoader();
132 loader->LoadDigits();
133 TTree* digitTree = loader->TreeD();
134 if (!digitTree) {
135 Error("Digits2Raw", "no digit tree");
136 return;
137 }
138
139 TClonesArray* digits = new TClonesArray("AliFMDDigit", 1000);
140 fFMD->SetTreeAddress();
141 TBranch* digitBranch = digitTree->GetBranch(fFMD->GetName());
142 if (!digitBranch) {
143 Error("Digits2Raw", "no branch for %s", fFMD->GetName());
144 return;
145 }
146 digitBranch->SetAddress(&digits);
147
148 Int_t nEvents = Int_t(digitTree->GetEntries());
149 for (Int_t event = 0; event < nEvents; event++) {
150 fFMD->ResetDigits();
151 digitTree->GetEvent(event);
152
1e8f773e 153 // Write out the digits
154 WriteDigits(digits);
155 }
156 loader->UnloadDigits();
157}
e802be3e 158
c2fc1258 159#if 1
160//____________________________________________________________________
161void
162AliFMDRawWriter::WriteDigits(TClonesArray* digits)
163{
02a27b50 164 // WRite an array of digits to disk file
c2fc1258 165 Int_t nDigits = digits->GetEntries();
166 if (nDigits < 1) return;
167
168 AliFMDParameters* pars = AliFMDParameters::Instance();
169 UShort_t threshold = 0;
170 UInt_t prevddl = 0;
171 UInt_t prevaddr = 0xFFF;
172 // UShort_t prevStrip = 0;
173
174 // Which channel number in the ALTRO channel we're at
175 UShort_t nWords = 0;
176 UShort_t preSamples = 0;
177
178 // How many times the ALTRO Samples one VA1_ALICE channel
179 Int_t sampleRate = 1;
180
181 // A buffer to hold 1 ALTRO channel - Normally, one ALTRO channel
182 // holds 128 VA1_ALICE channels, sampled at a rate of `sampleRate'
183 TArrayI data(pars->GetChannelsPerAltro() * 8);
184
185 // The Altro buffer
186 AliAltroBuffer* altro = 0;
187
188 // Loop over the digits in the event. Note, that we assume the
189 // the digits are in order in the branch. If they were not, we'd
190 // have to cache all channels before we could write the data to
191 // the ALTRO buffer, or we'd have to set up a map of the digits.
192 for (Int_t i = 0; i < nDigits; i++) {
193 // Get the digit
194 AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
195
196 UShort_t det = digit->Detector();
197 Char_t ring = digit->Ring();
198 UShort_t sector = digit->Sector();
199 UShort_t strip = digit->Strip();
200 UInt_t ddl;
201 UInt_t addr;
202 threshold = pars->GetZeroSuppression(det, ring, sector, strip);
203 if (!pars->Detector2Hardware(det, ring, sector, strip, ddl, addr)) {
204 AliError(Form("Failed to get hardware address for FMD%d%c[%2d,%3d]",
205 det, ring, sector, strip));
206 continue;
207 }
208 if (addr != prevaddr) {
209 // Flush a channel to output
210 AliDebug(15, Form("Now hardware address 0x%x from FMD%d%c[%2d,%3d] "
211 "(board 0x%x, chip 0x%x, channel 0x%x), flushing old "
212 "channel at 0x%x with %d words",
213 addr, det, ring, sector, strip,
214 (addr >> 7), (addr >> 4) & 0x7, addr & 0xf,
215 prevaddr, nWords));
216 if (altro) altro->WriteChannel(prevaddr,nWords,data.fArray,threshold);
217 nWords = preSamples;
218 prevaddr = addr;
219 for (size_t i = 0; i < nWords; i++) data[i] = digit->Count(0);
220 }
221 if (ddl != prevddl) {
222 AliDebug(15, Form("FMD: New DDL, was %d, now %d", prevddl, ddl));
223 // If an altro exists, delete the object, flushing the data to
224 // disk, and closing the file.
225 if (altro) {
226 // When the first argument is false, we write the real
227 // header.
228 AliDebug(15, Form("Closing output"));
229 altro->Flush();
230 altro->WriteDataHeader(kFALSE, kFALSE);
231 delete altro;
232 altro = 0;
233 }
234 prevddl = ddl;
235 // Need to open a new DDL!
362c9d61 236 TString filename(AliDAQ::DdlFileName(fFMD->GetName(), ddl));
c2fc1258 237 AliDebug(15, Form("New altro buffer with DDL file %s", filename.Data()));
238 // Create a new altro buffer - a `1' as the second argument
239 // means `write mode'
4c846604 240 altro = new AliAltroBuffer(filename.Data());
c2fc1258 241 altro->SetMapping(pars->GetAltroMap());
242 // Write a dummy (first argument is true) header to the DDL
243 // file - later on, when we close the file, we write the real
244 // header
245 altro->WriteDataHeader(kTRUE, kFALSE);
246 }
247
248 // Store the counts of the ADC in the channel buffer
249 sampleRate = pars->GetSampleRate(det, ring, sector, strip);
250 for (int s = 0; s < sampleRate; s++) {
251 data[nWords] = digit->Count(s);
252 nWords++;
253 }
254 }
255 // Finally, we need to close the final ALTRO buffer if it wasn't
256 // already
257 if (altro) {
258 if (nWords > 0) altro->WriteChannel(prevaddr,nWords,data.fArray,threshold);
259 altro->Flush();
260 altro->WriteDataHeader(kFALSE, kFALSE);
261 delete altro;
262 }
263}
264#else
1e8f773e 265//____________________________________________________________________
266void
267AliFMDRawWriter::WriteDigits(TClonesArray* digits)
268{
269 Int_t nDigits = digits->GetEntries();
270 if (nDigits < 1) return;
e802be3e 271
1e8f773e 272 AliFMDParameters* pars = AliFMDParameters::Instance();
273 AliFMDAltroWriter* writer = 0;
274 Int_t sampleRate = -1;
275 UShort_t hwaddr = 0;
276 UShort_t ddl = 0;
277 std::ofstream* file = 0;
278 Int_t ret = 0;
279 for (Int_t i = 0; i < nDigits; i++) {
280 // Get the digit
281 AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
282 UInt_t thisDDL, thisHwaddr;
283 UShort_t det = digit->Detector();
284 Char_t ring = digit->Ring();
285 UShort_t sector = digit->Sector();
286 UShort_t strip = digit->Strip();
287 if (!pars->Detector2Hardware(det,ring,sector,strip,thisDDL,thisHwaddr)) {
288 AliError(Form("Failed to get hardware address for FMD%d%c[%2d,%3d]",
289 det, ring, sector, strip));
290 continue;
291 }
292 AliDebug(40, Form("Got DDL=%d and address=%d from FMD%d%c[%2d,%3d]",
293 thisDDL, thisHwaddr, det, ring, sector, strip));
294 // Check if we're still in the same channel
295 if (thisHwaddr != hwaddr) {
296 AliDebug(30, Form("Now hardware address 0x%x from FMD%d%c[%2d,%3d] "
297 "(board 0x%x, chip 0x%x, channel 0x%x)",
298 thisHwaddr, det, ring, sector, strip,
299 (thisHwaddr >> 7), (thisHwaddr >> 4) & 0x7,
300 thisHwaddr & 0xf));
301 if (writer) writer->AddChannelTrailer(hwaddr);
302 hwaddr = thisHwaddr;
303 }
304 // Check if we're still in the same detector (DDL)
305 if (ddl != thisDDL) {
306 if (writer) {
307 AliDebug(1, Form("Closing altro writer %p", writer));
308 if ((ret = writer->Close()) < 0) {
309 AliError(Form("Error: %s", writer->ErrorString(ret)));
310 return;
311 }
312 delete writer;
313 writer = 0;
314 file->close();
315 delete file;
316 file = 0;
317 }
318 ddl = thisDDL;
319 }
320 // If we haven't got a writer (either because none were made so
321 // far, or because we've switch DDL), make one.
322 if (!writer) {
362c9d61 323 AliDebug(1, Form("Opening new ALTRO writer w/file %s", AliDAQ::DdlFileName("FMD",ddl)));
324 file = new std::ofstream(AliDAQ::DdlFileName("FMD",ddl));
1e8f773e 325 if (!file || !*file) {
362c9d61 326 AliFatal(Form("Failed to open file %s", AliDAQ::DdlFileName("FMD",ddl)));
1e8f773e 327 return;
328 }
329 writer = new AliFMDAltroWriter(*file);
330 writer->SetThreshold(pars->GetZeroSuppression(det, ring, sector, strip));
1e8f773e 331 }
332 // Write out our signal
c2fc1258 333 sampleRate = pars->GetSampleRate(det,ring,sector,strip);
1e8f773e 334 writer->AddSignal(digit->Count1());
335 if (sampleRate >= 2) writer->AddSignal(digit->Count2());
336 if (sampleRate >= 3) writer->AddSignal(digit->Count3());
337 }
338 if (writer) {
339 writer->AddChannelTrailer(hwaddr);
340 writer->Close();
341 delete writer;
342 file->close();
343 delete file;
344 }
345}
9f662337 346#endif
7684b53c 347
c2fc1258 348
7684b53c 349
350
351//____________________________________________________________________
e802be3e 352//
353// EOF
354//