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