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