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