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 // 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.
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.
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
36 #include <AliLog.h> // ALILOG_H
37 #include <AliLoader.h> // ALILOADER_H
38 #include <AliAltroBuffer.h> // ALIALTROBUFFER_H
39 #include "AliFMD.h" // ALIFMD_H
40 #include "AliFMDDigit.h" // ALIFMDDIGIT_H
41 #include "AliFMDRawWriter.h" // ALIFMDRAWREADER_H
42 #include <TArrayI.h> // ROOT_TArrayI
43 #include <TClonesArray.h> // ROOT_TClonesArray
45 //____________________________________________________________________
46 ClassImp(AliFMDRawWriter)
48 //____________________________________________________________________
49 AliFMDRawWriter::AliFMDRawWriter(AliFMD* fmd)
50 : TTask("FMDRawWriter", "Writer of Raw ADC values from the FMD"),
55 SetChannelsPerAltro();
59 //____________________________________________________________________
61 AliFMDRawWriter::Exec(Option_t*)
63 // Turn digits into raw data.
65 // Digits are read from the Digit branch, and processed to make
66 // three DDL files, one for each of the sub-detectors FMD1, FMD2,
69 // The raw data files consists of a header, followed by ALTRO
80 // An ALTRO formatted block, in the FMD context, consists of a
81 // number of counts followed by a trailer.
83 // +------------------+
86 // | possible fillers |
87 // +------------------+
89 // +------------------+
92 // The counts are listed backwards, that is, starting with the
93 // latest count, and ending in the first.
95 // Each count consist of 1 or more ADC samples of the VA1_ALICE
96 // pre-amp. signal. Just how many samples are used depends on
97 // whether the ALTRO over samples the pre-amp. Each sample is a
98 // 10-bit word, and the samples are grouped into 40-bit blocks
100 // +------------------------------------+
101 // | S(n) | S(n-1) | S(n-2) | S(n-3) |
102 // | ... | ... | ... | ... |
103 // | S(2) | S(1) | AA | AA |
104 // +------------------------------------+
105 // Counts + possible filler
107 // The trailer of the number of words of signales, the starting
108 // strip number, the sector number, and the ring ID; each 10-bit
109 // words, packed into 40-bits.
111 // +------------------------------------+
112 // | # words | start | sector | ring |
113 // +------------------------------------+
116 // Note, that this method assumes that the digits are ordered.
118 AliLoader* loader = fFMD->GetLoader();
119 loader->LoadDigits();
120 TTree* digitTree = loader->TreeD();
122 Error("Digits2Raw", "no digit tree");
126 TClonesArray* digits = new TClonesArray("AliFMDDigit", 1000);
127 fFMD->SetTreeAddress();
128 TBranch* digitBranch = digitTree->GetBranch(fFMD->GetName());
130 Error("Digits2Raw", "no branch for %s", fFMD->GetName());
133 digitBranch->SetAddress(&digits);
135 Int_t nEvents = Int_t(digitTree->GetEntries());
136 for (Int_t event = 0; event < nEvents; event++) {
138 digitTree->GetEvent(event);
140 Int_t nDigits = digits->GetEntries();
141 if (nDigits < 1) continue;
144 UShort_t prevDetector = 0;
145 Char_t prevRing = '\0';
146 UShort_t prevSector = 0;
147 // UShort_t prevStrip = 0;
149 // The first seen strip number for a channel
150 UShort_t startStrip = 0;
152 // Which channel number in the ALTRO channel we're at
155 // How many times the ALTRO Samples one VA1_ALICE channel
156 Int_t sampleRate = 1;
158 // A buffer to hold 1 ALTRO channel - Normally, one ALTRO channel
159 // holds 128 VA1_ALICE channels, sampled at a rate of `sampleRate'
160 TArrayI channel(fChannelsPerAltro * sampleRate);
163 AliAltroBuffer* altro = 0;
165 // Loop over the digits in the event. Note, that we assume the
166 // the digits are in order in the branch. If they were not, we'd
167 // have to cache all channels before we could write the data to
168 // the ALTRO buffer, or we'd have to set up a map of the digits.
169 for (Int_t i = 0; i < nDigits; i++) {
171 AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
173 UShort_t det = digit->Detector();
174 Char_t ring = digit->Ring();
175 UShort_t sector = digit->Sector();
176 UShort_t strip = digit->Strip();
177 if (det != prevDetector) {
178 AliDebug(10, Form("FMD: New DDL, was %d, now %d",
179 AliFMD::kBaseDDL + prevDetector - 1,
180 AliFMD::kBaseDDL + det - 1));
181 // If an altro exists, delete the object, flushing the data to
182 // disk, and closing the file.
184 // When the first argument is false, we write the real
186 AliDebug(10, Form("New altro: Write channel at %d Strip: %d "
187 "Sector: %d Ring: %d",
188 i, startStrip, prevSector, prevRing));
189 // TPC to FMD translations
192 // ----------+-----------
197 WriteChannel(altro, startStrip, prevSector, prevRing, channel);
199 altro->WriteDataHeader(kFALSE, kFALSE);
205 // Need to open a new DDL!
206 Int_t ddlId = AliFMD::kBaseDDL + det - 1;
207 TString filename(Form("%s_%d.ddl", fFMD->GetName(), ddlId));
209 AliDebug(10, Form("New altro buffer with DDL file %s",
211 AliDebug(10, Form("New altro at %d", i));
212 // Create a new altro buffer - a `1' as the second argument
213 // means `write mode'
214 altro = new AliAltroBuffer(filename.Data(), 1);
216 // Write a dummy (first argument is true) header to the DDL
217 // file - later on, when we close the file, we write the real
219 altro->WriteDataHeader(kTRUE, kFALSE);
221 // Figure out the sample rate
222 if (fSampleRate > 0) sampleRate = fSampleRate;
224 if (digit->Count2() >= 0) sampleRate = 2;
225 if (digit->Count3() >= 0) sampleRate = 3;
228 channel.Set(fChannelsPerAltro * sampleRate);
234 else if (offset == fChannelsPerAltro
235 || digit->Ring() != prevRing
236 || digit->Sector() != prevSector) {
237 // Force a new Altro channel
238 AliDebug(10, Form("Flushing channel to disk because %s",
239 (offset == fChannelsPerAltro ? "channel is full" :
240 (ring != prevRing ? "new ring up" :
242 AliDebug(10, Form("New Channel: Write channel at %d Strip: %d "
243 "Sector: %d Ring: %d",
244 i, startStrip, prevSector, prevRing));
245 WriteChannel(altro, startStrip, prevSector, prevRing, channel);
246 // Reset and update channel variables
254 // Store the counts of the ADC in the channel buffer
255 channel[offset * sampleRate] = digit->Count1();
257 channel[offset * sampleRate + 1] = digit->Count2();
259 channel[offset * sampleRate + 2] = digit->Count3();
262 // Finally, we need to close the final ALTRO buffer if it wasn't
266 altro->WriteDataHeader(kFALSE, kFALSE);
270 loader->UnloadDigits();
273 //____________________________________________________________________
275 AliFMDRawWriter::WriteChannel(AliAltroBuffer* altro,
276 UShort_t strip, UShort_t sector, Char_t ring,
279 // Write out one ALTRO channel to the data file.
280 // Derived classes can overload this method to use a per-ALTRO
281 // threshold. This implementation uses the common threshold set by
283 altro->WriteChannel(Int_t(strip),
285 Int_t((ring == 'I' ? 0 : 1)),
286 data.fN, data.fArray, fThreshold);
291 //____________________________________________________________________