1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 //____________________________________________________________________
20 // Class to write ADC values to a raw data file
22 #include "AliLog.h" // ALILOG_H
23 #include "AliFMD.h" // ALIFMD_H
24 #include "AliFMDDigit.h" // ALIFMDDIGIT_H
25 #include "AliFMDRawWriter.h" // ALIFMDRAWREADER_H
26 #include "AliAltroBuffer.h" // ALIALTROBUFFER_H
27 #include "AliLoader.h" // ALILOADER_H
28 #include "TArrayI.h" // ROOT_TArrayI
29 #include <TClonesArray.h> // ROOT_TClonesArray
31 //____________________________________________________________________
32 ClassImp(AliFMDRawWriter);
34 //____________________________________________________________________
35 AliFMDRawWriter::AliFMDRawWriter(AliFMD* fmd)
36 : TTask("FMDRawWriter", "Writer of Raw ADC values from the FMD"),
43 //____________________________________________________________________
45 AliFMDRawWriter::Exec(Option_t*)
47 // Turn digits into raw data.
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,
53 // The raw data files consists of a header, followed by ALTRO
64 // An ALTRO formatted block, in the FMD context, consists of a
65 // number of counts followed by a trailer.
67 // +------------------+
70 // | possible fillers |
71 // +------------------+
73 // +------------------+
76 // The counts are listed backwards, that is, starting with the
77 // latest count, and ending in the first.
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
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
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.
95 // +------------------------------------+
96 // | # words | start | sector | ring |
97 // +------------------------------------+
100 // Note, that this method assumes that the digits are ordered.
102 AliLoader* loader = fFMD->GetLoader();
103 loader->LoadDigits();
104 TTree* digitTree = loader->TreeD();
106 Error("Digits2Raw", "no digit tree");
110 TClonesArray* digits = new TClonesArray("AliFMDDigit", 1000);
111 fFMD->SetTreeAddress();
112 TBranch* digitBranch = digitTree->GetBranch(fFMD->GetName());
114 Error("Digits2Raw", "no branch for %s", fFMD->GetName());
117 digitBranch->SetAddress(&digits);
119 Int_t nEvents = Int_t(digitTree->GetEntries());
120 for (Int_t event = 0; event < nEvents; event++) {
122 digitTree->GetEvent(event);
124 Int_t nDigits = digits->GetEntries();
125 if (nDigits < 1) continue;
128 UShort_t prevDetector = 0;
129 Char_t prevRing = '\0';
130 UShort_t prevSector = 0;
131 // UShort_t prevStrip = 0;
133 // The first seen strip number for a channel
134 UShort_t startStrip = 0;
136 // Which channel number in the ALTRO channel we're at
139 // How many times the ALTRO Samples one VA1_ALICE channel
140 Int_t sampleRate = 1;
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);
147 AliAltroBuffer* altro = 0;
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++) {
155 AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
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.
168 // When the first argument is false, we write the real
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
176 // ----------+-----------
181 altro->WriteChannel(Int_t(startStrip),
183 Int_t((prevRing == 'I' ? 0 : 1)),
184 channel.fN, channel.fArray, 0);
186 altro->WriteDataHeader(kFALSE, kFALSE);
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));
196 AliDebug(10, Form("New altro buffer with DDL file %s",
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);
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
206 altro->WriteDataHeader(kTRUE, kFALSE);
208 // Figure out the sample rate
209 if (fSampleRate > 0) sampleRate = fSampleRate;
211 if (digit->Count2() >= 0) sampleRate = 2;
212 if (digit->Count3() >= 0) sampleRate = 3;
215 channel.Set(128 * sampleRate);
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" :
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),
234 Int_t((prevRing == 'I' ? 0 : 1)),
235 channel.fN, channel.fArray, 0);
236 // Reset and update channel variables
244 // Store the counts of the ADC in the channel buffer
245 channel[offset * sampleRate] = digit->Count1();
247 channel[offset * sampleRate + 1] = digit->Count2();
249 channel[offset * sampleRate + 2] = digit->Count3();
252 // Finally, we need to close the final ALTRO buffer if it wasn't
256 altro->WriteDataHeader(kFALSE, kFALSE);
260 loader->UnloadDigits();
263 //____________________________________________________________________