Bug fix for reading raw data - thanks Frederic YERMIA, Diego, and Gines MARTINEZ
[u/mrichter/AliRoot.git] / FMD / AliFMDRawReader.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    AliFMDRawReader.cxx
17     @author  Christian Holm Christensen <cholm@nbi.dk>
18     @date    Mon Mar 27 12:45:23 2006
19     @brief   Class to read raw data 
20     @ingroup FMD_rec
21 */
22 //____________________________________________________________________
23 //
24 // Class to read ADC values from a AliRawReader object. 
25 //
26 // This class uses the AliFMDRawStreamer class to read the ALTRO
27 // formatted data. 
28 // 
29 //          +-------+
30 //          | TTask |
31 //          +-------+
32 //              ^
33 //              |
34 //      +-----------------+  <<references>>  +--------------+
35 //      | AliFMDRawReader |<>----------------| AliRawReader |
36 //      +-----------------+                  +--------------+
37 //              |                                  ^
38 //              | <<uses>>                         |
39 //              V                                  |
40 //      +-----------------+      <<uses>>          |
41 //      | AliFMDRawStream |------------------------+
42 //      +-----------------+
43 //              |
44 //              V
45 //      +----------------+
46 //      | AliAltroStream |
47 //      +----------------+
48 //
49 // #include <AliLog.h>          // ALILOG_H
50 #include "AliFMDDebug.h" // Better debug macros
51 #include "AliFMDParameters.h"   // ALIFMDPARAMETERS_H
52 #include "AliFMDDigit.h"        // ALIFMDDIGIT_H
53 #include "AliFMDRawStream.h"    // ALIFMDRAWSTREAM_H 
54 // #include "AliRawReader.h"    // ALIRAWREADER_H 
55 #include "AliFMDRawReader.h"    // ALIFMDRAWREADER_H 
56 // #include "AliFMDAltroIO.h"   // ALIFMDALTROIO_H 
57 // #include <TArrayI.h>         // ROOT_TArrayI
58 #include <TTree.h>              // ROOT_TTree
59 #include <TClonesArray.h>       // ROOT_TClonesArray
60 // #include <iostream>
61 // #include <iomanip>
62
63 //____________________________________________________________________
64 ClassImp(AliFMDRawReader)
65 #if 0
66   ; // This is here to keep Emacs for indenting the next line
67 #endif
68
69 //____________________________________________________________________
70 AliFMDRawReader::AliFMDRawReader(AliRawReader* reader, TTree* tree) 
71   : TTask("FMDRawReader", "Reader of Raw ADC values from the FMD"),
72     fTree(tree),
73     fReader(reader), 
74     fSampleRate(1)
75 {
76   // Default CTOR
77 }
78
79 //____________________________________________________________________
80 void
81 AliFMDRawReader::Exec(Option_t*) 
82 {
83   // Read the data 
84   TClonesArray* array = new TClonesArray("AliFMDDigit");
85   if (!fTree) {
86     AliError("No tree");
87     return;
88   }
89   fTree->Branch("FMD", &array);
90   ReadAdcs(array);
91   Int_t nWrite = fTree->Fill();
92   AliFMDDebug(1, ("Got a grand total of %d digits, wrote %d bytes to tree", 
93                    array->GetEntries(), nWrite));
94 }
95
96
97 #if 1
98 //____________________________________________________________________
99 Bool_t
100 AliFMDRawReader::ReadAdcs(TClonesArray* array) 
101 {
102   // Read raw data into the digits array, using AliFMDAltroReader. 
103   if (!array) {
104     AliError("No TClonesArray passed");
105     return kFALSE;
106   }
107   //  if (!fReader->ReadHeader()) {
108   //    AliError("Couldn't read header");
109   //    return kFALSE;
110   //  }
111   // Get sample rate 
112   AliFMDParameters* pars = AliFMDParameters::Instance();
113   AliFMDRawStream input(fReader);
114
115   UShort_t stripMin = 0;
116   UShort_t stripMax = 127;
117   UShort_t preSamp  = 0;
118   
119   UInt_t ddl    = 0;
120   UInt_t rate   = 0;
121   UInt_t last   = 0;
122   UInt_t hwaddr = 0;
123   // Data array is approx twice the size needed. 
124   UShort_t data[2048];
125
126   Bool_t isGood = kTRUE;
127   while (isGood) {
128     isGood = input.ReadChannel(ddl, hwaddr, last, data);
129
130     AliFMDDebug(5, ("Read channel 0x%x of size %d", hwaddr, last));
131     UShort_t det, sec, str;
132     Char_t   ring;
133     if (!pars->Hardware2Detector(ddl, hwaddr, det, ring, sec, str)) {
134       AliError(Form("Failed to get detector id from DDL %d "
135                     "and hardware address 0x%x", ddl, hwaddr));
136       continue;
137     }
138     rate     = pars->GetSampleRate(det, ring, sec, str);
139     stripMin = pars->GetMinStrip(det, ring, sec, str);
140     stripMax = pars->GetMaxStrip(det, ring, sec, str);
141     AliFMDDebug(5, ("DDL 0x%04x, address 0x%03x maps to FMD%d%c[%2d,%3d]", 
142                        ddl, hwaddr, det, ring, sec, str));
143     
144     // Loop over the `timebins', and make the digits
145     for (size_t i = 0; i < last; i++) {
146       if (i < preSamp) continue;
147       Int_t    n      = array->GetEntriesFast();
148       UShort_t curStr = str + stripMin + i / rate;
149       if ((curStr-str) > stripMax) {
150         AliError(Form("Current strip is %d but DB says max is %d", 
151                       curStr, stripMax));
152       }
153       AliFMDDebug(5, ("making digit for FMD%d%c[%2d,%3d] from sample %4d", 
154                        det, ring, sec, curStr, i));
155       new ((*array)[n]) AliFMDDigit(det, ring, sec, curStr, data[i], 
156                                     (rate >= 2 ? data[i+1] : 0),
157                                     (rate >= 3 ? data[i+2] : 0));
158       if (rate >= 2) i++;
159       if (rate >= 3) i++;
160     }
161   }
162   return kTRUE;
163 }
164 #else
165 //____________________________________________________________________
166 Bool_t
167 AliFMDRawReader::ReadAdcs(TClonesArray* array) 
168 {
169   // Read raw data into the digits array, using AliFMDAltroReader. 
170   if (!array) {
171     AliError("No TClonesArray passed");
172     return kFALSE;
173   }
174   //  if (!fReader->ReadHeader()) {
175   //    AliError("Couldn't read header");
176   //    return kFALSE;
177   //  }
178   // Get sample rate 
179   AliFMDParameters* pars = AliFMDParameters::Instance();
180
181   // Select FMD DDL's 
182   fReader->Select("FMD");
183
184   UShort_t stripMin = 0;
185   UShort_t stripMax = 127;
186   UShort_t preSamp  = 0;
187   
188   do {
189     UChar_t* cdata;
190     if (!fReader->ReadNextData(cdata)) break;
191     size_t   nchar = fReader->GetDataSize();
192     UShort_t ddl   = fReader->GetDDLID();
193     UShort_t rate  = 0;
194     AliFMDDebug(1, ("Reading %d bytes (%d 10bit words) from %d", 
195                      nchar, nchar * 8 / 10, ddl));
196     // Make a stream to read from 
197     std::string str((char*)(cdata), nchar);
198     std::istringstream s(str);
199     // Prep the reader class.
200     AliFMDAltroReader r(s);
201     // Data array is approx twice the size needed. 
202     UShort_t data[2048], hwaddr, last;
203     while (r.ReadChannel(hwaddr, last, data) > 0) {
204       AliFMDDebug(5, ("Read channel 0x%x of size %d", hwaddr, last));
205       UShort_t det, sec, str;
206       Char_t   ring;
207       if (!pars->Hardware2Detector(ddl, hwaddr, det, ring, sec, str)) {
208         AliError(Form("Failed to detector id from DDL %d "
209                       "and hardware address 0x%x", ddl, hwaddr));
210         continue;
211       }
212       rate     = pars->GetSampleRate(det, ring, sec, str);
213       stripMin = pars->GetMinStrip(det, ring, sec, str);
214       stripMax = pars->GetMaxStrip(det, ring, sec, str);
215       AliFMDDebug(5, ("DDL 0x%04x, address 0x%03x maps to FMD%d%c[%2d,%3d]", 
216                        ddl, hwaddr, det, ring, sec, str));
217
218       // Loop over the `timebins', and make the digits
219       for (size_t i = 0; i < last; i++) {
220         if (i < preSamp) continue;
221         Int_t    n      = array->GetEntries();
222         UShort_t curStr = str + stripMin + i / rate;
223         if ((curStr-str) > stripMax) {
224           AliError(Form("Current strip is %d but DB says max is %d", 
225                         curStr, stripMax));
226         }
227         AliFMDDebug(5, ("making digit for FMD%d%c[%2d,%3d] from sample %4d", 
228                          det, ring, sec, curStr, i));
229         new ((*array)[n]) AliFMDDigit(det, ring, sec, curStr, data[i], 
230                                       (rate >= 2 ? data[i+1] : 0),
231                                       (rate >= 3 ? data[i+2] : 0));
232         if (rate >= 2) i++;
233         if (rate >= 3) i++;
234         }
235         if (r.IsBof()) break;
236     }
237   } while (true);
238   return kTRUE;
239 }
240
241   
242
243 // This is the old method, for comparison.   It's really ugly, and far
244 // too convoluted. 
245 //____________________________________________________________________
246 void
247 AliFMDRawReader::Exec(Option_t*) 
248 {
249   // Read raw data into the digits array
250   //  if (!fReader->ReadHeader()) {
251   //    Error("ReadAdcs", "Couldn't read header");
252   //    return;
253   //  }
254
255   Int_t n = 0;
256   TClonesArray* array = new TClonesArray("AliFMDDigit");
257   fTree->Branch("FMD", &array);
258
259   // Get sample rate 
260   AliFMDParameters* pars = AliFMDParameters::Instance();
261   fSampleRate = pars->GetSampleRate(0);
262
263   // Use AliAltroRawStream to read the ALTRO format.  No need to
264   // reinvent the wheel :-) 
265   AliFMDRawStream input(fReader, fSampleRate);
266   // Select FMD DDL's 
267   fReader->Select("FMD");
268   
269   Int_t    oldDDL      = -1;
270   Int_t    count       = 0;
271   UShort_t detector    = 1; // Must be one here
272   UShort_t oldDetector = 0;
273   Bool_t   next        = kTRUE;
274
275   // local Cache 
276   TArrayI counts(10);
277   counts.Reset(-1);
278   
279   // Loop over data in file 
280   while (next) {
281     next = input.Next();
282
283     count++; 
284     Int_t ddl = fReader->GetDDLID();
285     AliFMDDebug(10, ("Current DDL is %d", ddl));
286     if (ddl != oldDDL || input.IsNewStrip() || !next) {
287       // Make a new digit, if we have some data (oldDetector == 0,
288       // means that we haven't really read anything yet - that is,
289       // it's the first time we get here). 
290       if (oldDetector > 0) {
291         // Got a new strip. 
292         AliFMDDebug(10, ("Add a new strip: FMD%d%c[%2d,%3d] "
293                           "(current: FMD%d%c[%2d,%3d])", 
294                           oldDetector, input.PrevRing(), 
295                           input.PrevSector() , input.PrevStrip(),
296                           detector , input.Ring(), input.Sector(), 
297                           input.Strip()));
298         new ((*array)[n]) AliFMDDigit(oldDetector, 
299                                       input.PrevRing(), 
300                                       input.PrevSector(), 
301                                       input.PrevStrip(), 
302                                       counts[0], counts[1], counts[2]);
303         n++;
304 #if 0
305         AliFMDDigit* digit = 
306           static_cast<AliFMDDigit*>(fFMD->Digits()->
307                                     UncheckedAt(fFMD->GetNdigits()-1));
308 #endif 
309       }
310         
311       if (!next) { 
312         AliFMDDebug(10, ("Read %d channels for FMD%d", 
313                           count + 1, detector));
314         break;
315       }
316     
317     
318       // If we got a new DDL, it means we have a new detector. 
319       if (ddl != oldDDL) {
320         if (detector != 0) 
321           AliFMDDebug(10, ("Read %d channels for FMD%d", count + 1, detector));
322         // Reset counts, and update the DDL cache 
323         count       = 0;
324         oldDDL      = ddl;
325         // Check that we're processing a FMD detector 
326         Int_t detId = fReader->GetDetectorID();
327         if (detId != (AliDAQ::DetectorID("FMD"))) {
328           AliError(Form("Detector ID %d != %d",
329                         detId, (AliDAQ::DetectorID("FMD"))));
330           break;
331         }
332         // Figure out what detector we're deling with 
333         oldDetector = detector;
334         switch (ddl) {
335         case 0: detector = 1; break;
336         case 1: detector = 2; break;
337         case 2: detector = 3; break;
338         default:
339           AliError(Form("Unknown DDL 0x%x for FMD", ddl));
340           return;
341         }
342         AliFMDDebug(10, ("Reading ADCs for 0x%x  - That is FMD%d",
343                           fReader->GetEquipmentId(), detector));
344       }
345       counts.Reset(-1);
346     }
347     
348     counts[input.Sample()] = input.Count();
349     
350     AliFMDDebug(10, ("ADC of FMD%d%c[%2d,%3d] += %d",
351                       detector, input.Ring(), input.Sector(), 
352                       input.Strip(), input.Count()));
353     oldDetector = detector;
354   }
355   fTree->Fill();
356   return;
357
358 }
359 #endif
360
361 //____________________________________________________________________
362 // 
363 // EOF
364 //