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