Got rid of class template AliFMD<Type> on request of Federico, who
[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
16 /* $Id$ */
17
18 //____________________________________________________________________
19 //
20 // Class to write ADC values to a raw data file
21 //
22 #include "AliLog.h"             // ALILOG_H
23 #include "AliFMD.h"             // ALIFMD_H
24 #include "AliFMDDigit.h"        // ALIFMDDIGIT_H
25 #include "AliFMDRawWriter.h"    // ALIFMDRAWREADER_H 
26 #include "AliAltroBuffer.h"     // ALIALTROBUFFER_H
27 #include "AliLoader.h"          // ALILOADER_H
28 #include "TArrayI.h"            // ROOT_TArrayI
29 #include <TClonesArray.h>       // ROOT_TClonesArray
30
31 //____________________________________________________________________
32 ClassImp(AliFMDRawWriter);
33
34 //____________________________________________________________________
35 AliFMDRawWriter::AliFMDRawWriter(AliFMD* fmd) 
36   : TTask("FMDRawWriter", "Writer of Raw ADC values from the FMD"),
37     fFMD(fmd)
38 {
39   SetSampleRate();
40 }
41
42
43 //____________________________________________________________________
44 void
45 AliFMDRawWriter::Exec(Option_t*) 
46 {
47   // Turn digits into raw data. 
48   // 
49   // Digits are read from the Digit branch, and processed to make
50   // three DDL files, one for each of the sub-detectors FMD1, FMD2,
51   // and FMD3. 
52   //
53   // The raw data files consists of a header, followed by ALTRO
54   // formatted blocks.  
55   // 
56   //          +-------------+
57   //          | Header      |
58   //          +-------------+
59   //          | ALTRO Block |
60   //          | ...         |
61   //          +-------------+
62   //          DDL file 
63   // 
64   // An ALTRO formatted block, in the FMD context, consists of a
65   // number of counts followed by a trailer. 
66   // 
67   //          +------------------+
68   //          | Count            |
69   //          | ...              |
70   //          | possible fillers |
71   //          +------------------+
72   //          | Trailer          |
73   //          +------------------+
74   //          ALTRO block 
75   // 
76   // The counts are listed backwards, that is, starting with the
77   // latest count, and ending in the first. 
78   // 
79   // Each count consist of 1 or more ADC samples of the VA1_ALICE
80   // pre-amp. signal.  Just how many samples are used depends on
81   // whether the ALTRO over samples the pre-amp.  Each sample is a
82   // 10-bit word, and the samples are grouped into 40-bit blocks 
83   //
84   //          +------------------------------------+
85   //          |  S(n)   | S(n-1) | S(n-2) | S(n-3) |
86   //          |  ...    | ...    | ...    | ...    |
87   //          |  S(2)   | S(1)   | AA     | AA     |
88   //          +------------------------------------+
89   //          Counts + possible filler 
90   //
91   // The trailer of the number of words of signales, the starting
92   // strip number, the sector number, and the ring ID; each 10-bit
93   // words,  packed into 40-bits. 
94   // 
95   //          +------------------------------------+
96   //          | # words | start  | sector | ring   |
97   //          +------------------------------------+
98   //          Trailer
99   // 
100   // Note, that this method assumes that the digits are ordered. 
101   // 
102   AliLoader* loader = fFMD->GetLoader();
103   loader->LoadDigits();
104   TTree* digitTree = loader->TreeD();
105   if (!digitTree) {
106     Error("Digits2Raw", "no digit tree");
107     return;
108   }
109   
110   TClonesArray* digits = new TClonesArray("AliFMDDigit", 1000);
111   fFMD->SetTreeAddress();
112   TBranch* digitBranch = digitTree->GetBranch(fFMD->GetName());
113   if (!digitBranch) {
114     Error("Digits2Raw", "no branch for %s", fFMD->GetName());
115     return;
116   }
117   digitBranch->SetAddress(&digits);
118   
119   Int_t nEvents = Int_t(digitTree->GetEntries());
120   for (Int_t event = 0; event < nEvents; event++) {
121     fFMD->ResetDigits();
122     digitTree->GetEvent(event);
123     
124     Int_t nDigits = digits->GetEntries();
125     if (nDigits < 1) continue;
126
127
128     UShort_t prevDetector = 0;
129     Char_t   prevRing     = '\0';
130     UShort_t prevSector   = 0;
131     // UShort_t prevStrip    = 0;
132
133     // The first seen strip number for a channel 
134     UShort_t startStrip   = 0;
135     
136     // Which channel number in the ALTRO channel we're at 
137     UShort_t offset       = 0;
138
139     // How many times the ALTRO Samples one VA1_ALICE channel 
140     Int_t sampleRate = 1;
141
142     // A buffer to hold 1 ALTRO channel - Normally, one ALTRO channel
143     // holds 128 VA1_ALICE channels, sampled at a rate of `sampleRate' 
144     TArrayI channel(128 * sampleRate);
145     
146     // The Altro buffer 
147     AliAltroBuffer* altro = 0;
148     
149     // Loop over the digits in the event.  Note, that we assume the
150     // the digits are in order in the branch.   If they were not, we'd
151     // have to cache all channels before we could write the data to
152     // the ALTRO buffer, or we'd have to set up a map of the digits. 
153     for (Int_t i = 0; i < nDigits; i++) {
154       // Get the digit
155       AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
156
157       UShort_t det    = digit->Detector();
158       Char_t   ring   = digit->Ring();
159       UShort_t sector = digit->Sector();
160       UShort_t strip  = digit->Strip();
161       if (det != prevDetector) {
162         AliDebug(10, Form("FMD: New DDL, was %d, now %d",
163                           AliFMD::kBaseDDL + prevDetector - 1,
164                           AliFMD::kBaseDDL + det - 1));
165         // If an altro exists, delete the object, flushing the data to
166         // disk, and closing the file. 
167         if (altro) { 
168           // When the first argument is false, we write the real
169           // header. 
170           AliDebug(10, Form("New altro: Write channel at %d Strip: %d "
171                             "Sector: %d  Ring: %d", 
172                             i, startStrip, prevSector, prevRing));
173           // TPC to FMD translations 
174           // 
175           //    TPC                FMD
176           //    ----------+-----------
177           //    pad       |      strip
178           //    row       |     sector
179           //    sector    |       ring
180           // 
181           altro->WriteChannel(Int_t(startStrip), 
182                               Int_t(prevSector), 
183                               Int_t((prevRing == 'I' ? 0 : 1)), 
184                               channel.fN, channel.fArray, 0);
185           altro->Flush();
186           altro->WriteDataHeader(kFALSE, kFALSE);
187           delete altro;
188           altro = 0;
189         }
190
191         prevDetector = det;
192         // Need to open a new DDL! 
193         Int_t ddlId = AliFMD::kBaseDDL + det - 1;
194         TString filename(Form("%s_%d.ddl", fFMD->GetName(),  ddlId));
195
196         AliDebug(10, Form("New altro buffer with DDL file %s", 
197                           filename.Data()));
198         AliDebug(10, Form("New altro at %d", i));
199         // Create a new altro buffer - a `1' as the second argument
200         // means `write mode' 
201         altro = new AliAltroBuffer(filename.Data(), 1);
202         
203         // Write a dummy (first argument is true) header to the DDL
204         // file - later on, when we close the file, we write the real
205         // header
206         altro->WriteDataHeader(kTRUE, kFALSE);
207
208         // Figure out the sample rate 
209         if (fSampleRate > 0) sampleRate = fSampleRate;
210         else {
211           if (digit->Count2() >= 0) sampleRate = 2;
212           if (digit->Count3() >= 0) sampleRate = 3;
213         }
214
215         channel.Set(128 * sampleRate);
216         offset     = 0;
217         prevRing   = ring;
218         prevSector = sector;
219         startStrip = strip;
220       }
221       else if (offset == 128                        
222                || digit->Ring() != prevRing 
223                || digit->Sector() != prevSector) {
224         // Force a new Altro channel
225         AliDebug(10, Form("Flushing channel to disk because %s",
226                           (offset == 128 ? "channel is full" :
227                            (ring != prevRing ? "new ring up" :
228                             "new sector up"))));
229         AliDebug(10, Form("New Channel: Write channel at %d Strip: %d "
230                           "Sector: %d  Ring: %d", 
231                           i, startStrip, prevSector, prevRing));
232         altro->WriteChannel(Int_t(startStrip), 
233                             Int_t(prevSector), 
234                             Int_t((prevRing == 'I' ? 0 : 1)), 
235                             channel.fN, channel.fArray, 0);
236         // Reset and update channel variables 
237         channel.Reset(0);
238         offset     = 0; 
239         startStrip = strip;
240         prevRing   = ring;
241         prevSector = sector;
242       }
243
244       // Store the counts of the ADC in the channel buffer 
245       channel[offset * sampleRate] = digit->Count1();
246       if (sampleRate > 1) 
247         channel[offset * sampleRate + 1] = digit->Count2();
248       if (sampleRate > 2) 
249         channel[offset * sampleRate + 2] = digit->Count3();
250       offset++;
251     }
252     // Finally, we need to close the final ALTRO buffer if it wasn't
253     // already 
254     if (altro) {
255       altro->Flush();
256       altro->WriteDataHeader(kFALSE, kFALSE);
257       delete altro;
258     }
259   }
260   loader->UnloadDigits();
261 }
262
263 //____________________________________________________________________
264 // 
265 // EOF
266 //