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 **************************************************************************/
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
21 //____________________________________________________________________
23 // Class to write ADC values to a raw data file
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.
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.
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
39 #include <AliLog.h> // ALILOG_H
40 #include <AliLoader.h> // ALILOADER_H
41 #include <AliAltroBuffer.h> // ALIALTROBUFFER_H
42 #include "AliFMD.h" // ALIFMD_H
43 #include "AliFMDParameters.h" // ALIFMDPARAMETERS_H
44 #include "AliFMDDigit.h" // ALIFMDDIGIT_H
45 #include "AliFMDRawWriter.h" // ALIFMDRAWREADER_H
46 #include "AliFMDAltroMapping.h" // ALIFMDALTROMAPPING_H
47 // #include "AliFMDAltroIO.h" // ALIFMDALTROWRITER_H
48 #include <TArrayI.h> // ROOT_TArrayI
49 #include <TClonesArray.h> // ROOT_TClonesArray
53 //____________________________________________________________________
54 ClassImp(AliFMDRawWriter)
56 ; // This is here to keep Emacs for indenting the next line
59 //____________________________________________________________________
60 AliFMDRawWriter::AliFMDRawWriter(AliFMD* fmd)
61 : TTask("FMDRawWriter", "Writer of Raw ADC values from the FMD"),
69 //____________________________________________________________________
71 AliFMDRawWriter::Exec(Option_t*)
73 // Turn digits into raw data.
75 // Digits are read from the Digit branch, and processed to make
76 // three DDL files, one for each of the sub-detectors FMD1, FMD2,
79 // The raw data files consists of a header, followed by ALTRO
90 // An ALTRO formatted block, in the FMD context, consists of a
91 // number of counts followed by a trailer.
93 // +------------------+
96 // | possible fillers |
97 // +------------------+
99 // +------------------+
102 // The counts are listed backwards, that is, starting with the
103 // latest count, and ending in the first.
105 // Each count consist of 1 or more ADC samples of the VA1_ALICE
106 // pre-amp. signal. Just how many samples are used depends on
107 // whether the ALTRO over samples the pre-amp. Each sample is a
108 // 10-bit word, and the samples are grouped into 40-bit blocks
110 // +------------------------------------+
111 // | S(1) | S(2) | S(3) | S(4) |
112 // | ... | ... | ... | ... |
113 // | S(n) | T(n) | n+2 | 2AA |
114 // +------------------------------------+
115 // Counts + possible filler
117 // The trailer of the number of words of signales, the starting
118 // strip number, the sector number, and the ring ID; each 10-bit
119 // words, packed into 40-bits.
121 // +------------------------------------+
122 // | 2AAA | Len | A | Address |
123 // +------------------------------------+
126 // Note, that this method assumes that the digits are ordered.
128 AliLoader* loader = fFMD->GetLoader();
129 loader->LoadDigits();
130 TTree* digitTree = loader->TreeD();
132 Error("Digits2Raw", "no digit tree");
136 TClonesArray* digits = new TClonesArray("AliFMDDigit", 1000);
137 fFMD->SetTreeAddress();
138 TBranch* digitBranch = digitTree->GetBranch(fFMD->GetName());
140 Error("Digits2Raw", "no branch for %s", fFMD->GetName());
143 digitBranch->SetAddress(&digits);
145 Int_t nEvents = Int_t(digitTree->GetEntries());
146 for (Int_t event = 0; event < nEvents; event++) {
148 digitTree->GetEvent(event);
150 // Write out the digits
153 loader->UnloadDigits();
157 //____________________________________________________________________
159 AliFMDRawWriter::WriteDigits(TClonesArray* digits)
161 // WRite an array of digits to disk file
162 Int_t nDigits = digits->GetEntries();
163 if (nDigits < 1) return;
165 AliFMDParameters* pars = AliFMDParameters::Instance();
166 UShort_t threshold = 0;
168 UInt_t prevaddr = 0xFFF;
169 // UShort_t prevStrip = 0;
171 // Which channel number in the ALTRO channel we're at
173 UShort_t preSamples = 0;
175 // How many times the ALTRO Samples one VA1_ALICE channel
176 Int_t sampleRate = 1;
178 // A buffer to hold 1 ALTRO channel - Normally, one ALTRO channel
179 // holds 128 VA1_ALICE channels, sampled at a rate of `sampleRate'
180 TArrayI data(pars->GetChannelsPerAltro() * 8);
183 AliAltroBuffer* altro = 0;
185 // Loop over the digits in the event. Note, that we assume the
186 // the digits are in order in the branch. If they were not, we'd
187 // have to cache all channels before we could write the data to
188 // the ALTRO buffer, or we'd have to set up a map of the digits.
189 for (Int_t i = 0; i < nDigits; i++) {
191 AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
193 UShort_t det = digit->Detector();
194 Char_t ring = digit->Ring();
195 UShort_t sector = digit->Sector();
196 UShort_t strip = digit->Strip();
199 threshold = pars->GetZeroSuppression(det, ring, sector, strip);
200 if (!pars->Detector2Hardware(det, ring, sector, strip, ddl, addr)) {
201 AliError(Form("Failed to get hardware address for FMD%d%c[%2d,%3d]",
202 det, ring, sector, strip));
205 if (addr != prevaddr) {
206 // Flush a channel to output
207 AliDebug(15, Form("Now hardware address 0x%x from FMD%d%c[%2d,%3d] "
208 "(board 0x%x, chip 0x%x, channel 0x%x), flushing old "
209 "channel at 0x%x with %d words",
210 addr, det, ring, sector, strip,
211 (addr >> 7), (addr >> 4) & 0x7, addr & 0xf,
213 if (altro) altro->WriteChannel(prevaddr,nWords,data.fArray,threshold);
216 for (size_t i = 0; i < nWords; i++) data[i] = digit->Count(0);
218 if (ddl != prevddl) {
219 AliDebug(15, Form("FMD: New DDL, was %d, now %d", prevddl, ddl));
220 // If an altro exists, delete the object, flushing the data to
221 // disk, and closing the file.
223 // When the first argument is false, we write the real
225 AliDebug(15, Form("Closing output"));
227 altro->WriteDataHeader(kFALSE, kFALSE);
232 // Need to open a new DDL!
233 TString filename(AliDAQ::DdlFileName(fFMD->GetName(), ddl));
234 AliDebug(15, Form("New altro buffer with DDL file %s", filename.Data()));
235 // Create a new altro buffer - a `1' as the second argument
236 // means `write mode'
237 altro = new AliAltroBuffer(filename.Data());
238 altro->SetMapping(pars->GetAltroMap());
239 // Write a dummy (first argument is true) header to the DDL
240 // file - later on, when we close the file, we write the real
242 altro->WriteDataHeader(kTRUE, kFALSE);
245 // Store the counts of the ADC in the channel buffer
246 sampleRate = pars->GetSampleRate(det, ring, sector, strip);
247 for (int s = 0; s < sampleRate; s++) {
248 data[nWords] = digit->Count(s);
252 // Finally, we need to close the final ALTRO buffer if it wasn't
255 if (nWords > 0) altro->WriteChannel(prevaddr,nWords,data.fArray,threshold);
257 altro->WriteDataHeader(kFALSE, kFALSE);
262 //____________________________________________________________________
264 AliFMDRawWriter::WriteDigits(TClonesArray* digits)
266 Int_t nDigits = digits->GetEntries();
267 if (nDigits < 1) return;
269 AliFMDParameters* pars = AliFMDParameters::Instance();
270 AliFMDAltroWriter* writer = 0;
271 Int_t sampleRate = -1;
274 std::ofstream* file = 0;
276 for (Int_t i = 0; i < nDigits; i++) {
278 AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
279 UInt_t thisDDL, thisHwaddr;
280 UShort_t det = digit->Detector();
281 Char_t ring = digit->Ring();
282 UShort_t sector = digit->Sector();
283 UShort_t strip = digit->Strip();
284 if (!pars->Detector2Hardware(det,ring,sector,strip,thisDDL,thisHwaddr)) {
285 AliError(Form("Failed to get hardware address for FMD%d%c[%2d,%3d]",
286 det, ring, sector, strip));
289 AliDebug(40, Form("Got DDL=%d and address=%d from FMD%d%c[%2d,%3d]",
290 thisDDL, thisHwaddr, det, ring, sector, strip));
291 // Check if we're still in the same channel
292 if (thisHwaddr != hwaddr) {
293 AliDebug(30, Form("Now hardware address 0x%x from FMD%d%c[%2d,%3d] "
294 "(board 0x%x, chip 0x%x, channel 0x%x)",
295 thisHwaddr, det, ring, sector, strip,
296 (thisHwaddr >> 7), (thisHwaddr >> 4) & 0x7,
298 if (writer) writer->AddChannelTrailer(hwaddr);
301 // Check if we're still in the same detector (DDL)
302 if (ddl != thisDDL) {
304 AliDebug(1, Form("Closing altro writer %p", writer));
305 if ((ret = writer->Close()) < 0) {
306 AliError(Form("Error: %s", writer->ErrorString(ret)));
317 // If we haven't got a writer (either because none were made so
318 // far, or because we've switch DDL), make one.
320 AliDebug(1, Form("Opening new ALTRO writer w/file %s", AliDAQ::DdlFileName("FMD",ddl)));
321 file = new std::ofstream(AliDAQ::DdlFileName("FMD",ddl));
322 if (!file || !*file) {
323 AliFatal(Form("Failed to open file %s", AliDAQ::DdlFileName("FMD",ddl)));
326 writer = new AliFMDAltroWriter(*file);
327 writer->SetThreshold(pars->GetZeroSuppression(det, ring, sector, strip));
329 // Write out our signal
330 sampleRate = pars->GetSampleRate(det,ring,sector,strip);
331 writer->AddSignal(digit->Count1());
332 if (sampleRate >= 2) writer->AddSignal(digit->Count2());
333 if (sampleRate >= 3) writer->AddSignal(digit->Count3());
336 writer->AddChannelTrailer(hwaddr);
348 //____________________________________________________________________