]> git.uio.no Git - u/mrichter/AliRoot.git/blob - FMD/AliFMDRawWriter.cxx
fix in Gain
[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(AliFMDParameters::kBaseDDL);
59   fChannelsPerAltro      = pars->GetChannelsPerAltro();
60 }
61
62
63 //____________________________________________________________________
64 void
65 AliFMDRawWriter::Exec(Option_t*) 
66 {
67   // Turn digits into raw data. 
68   // 
69   // Digits are read from the Digit branch, and processed to make
70   // three DDL files, one for each of the sub-detectors FMD1, FMD2,
71   // and FMD3. 
72   //
73   // The raw data files consists of a header, followed by ALTRO
74   // formatted blocks.  
75   // 
76   //          +-------------+
77   //          | Header      |
78   //          +-------------+
79   //          | ALTRO Block |
80   //          | ...         |
81   //          +-------------+
82   //          DDL file 
83   // 
84   // An ALTRO formatted block, in the FMD context, consists of a
85   // number of counts followed by a trailer. 
86   // 
87   //          +------------------+
88   //          | Count            |
89   //          | ...              |
90   //          | possible fillers |
91   //          +------------------+
92   //          | Trailer          |
93   //          +------------------+
94   //          ALTRO block 
95   // 
96   // The counts are listed backwards, that is, starting with the
97   // latest count, and ending in the first. 
98   // 
99   // Each count consist of 1 or more ADC samples of the VA1_ALICE
100   // pre-amp. signal.  Just how many samples are used depends on
101   // whether the ALTRO over samples the pre-amp.  Each sample is a
102   // 10-bit word, and the samples are grouped into 40-bit blocks 
103   //
104   //          +------------------------------------+
105   //          |  S(n)   | S(n-1) | S(n-2) | S(n-3) |
106   //          |  ...    | ...    | ...    | ...    |
107   //          |  S(2)   | S(1)   | AA     | AA     |
108   //          +------------------------------------+
109   //          Counts + possible filler 
110   //
111   // The trailer of the number of words of signales, the starting
112   // strip number, the sector number, and the ring ID; each 10-bit
113   // words,  packed into 40-bits. 
114   // 
115   //          +------------------------------------+
116   //          | # words | start  | sector | ring   |
117   //          +------------------------------------+
118   //          Trailer
119   // 
120   // Note, that this method assumes that the digits are ordered. 
121   // 
122   AliLoader* loader = fFMD->GetLoader();
123   loader->LoadDigits();
124   TTree* digitTree = loader->TreeD();
125   if (!digitTree) {
126     Error("Digits2Raw", "no digit tree");
127     return;
128   }
129   
130   TClonesArray* digits = new TClonesArray("AliFMDDigit", 1000);
131   fFMD->SetTreeAddress();
132   TBranch* digitBranch = digitTree->GetBranch(fFMD->GetName());
133   if (!digitBranch) {
134     Error("Digits2Raw", "no branch for %s", fFMD->GetName());
135     return;
136   }
137   digitBranch->SetAddress(&digits);
138   
139   AliFMDParameters* pars = AliFMDParameters::Instance();
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       fThreshold      = pars->GetZeroSuppression(det, ring, sector, strip);
183       if (det != prevDetector) {
184         AliDebug(15, Form("FMD: New DDL, was %d, now %d",
185                           AliFMDParameters::kBaseDDL + prevDetector - 1,
186                           AliFMDParameters::kBaseDDL + det - 1));
187         // If an altro exists, delete the object, flushing the data to
188         // disk, and closing the file. 
189         if (altro) { 
190           // When the first argument is false, we write the real
191           // header. 
192           AliDebug(15, Form("New altro: Write channel at %d Strip: %d "
193                             "Sector: %d  Ring: %d", 
194                             i, startStrip, prevSector, prevRing));
195           // TPC to FMD translations 
196           // 
197           //    TPC                FMD
198           //    ----------+-----------
199           //    pad       |      strip
200           //    row       |     sector
201           //    sector    |       ring
202           // 
203           WriteChannel(altro, startStrip, prevSector, prevRing, channel);
204           altro->Flush();
205           altro->WriteDataHeader(kFALSE, kFALSE);
206           delete altro;
207           altro = 0;
208         }
209
210         prevDetector = det;
211         // Need to open a new DDL! 
212         Int_t ddlId = AliFMDParameters::kBaseDDL + det - 1;
213         TString filename(Form("%s_%d.ddl", fFMD->GetName(),  ddlId));
214
215         AliDebug(15, Form("New altro buffer with DDL file %s", 
216                           filename.Data()));
217         AliDebug(15, Form("New altro at %d", i));
218         // Create a new altro buffer - a `1' as the second argument
219         // means `write mode' 
220         altro = new AliAltroBuffer(filename.Data(), 1);
221         
222         // Write a dummy (first argument is true) header to the DDL
223         // file - later on, when we close the file, we write the real
224         // header
225         altro->WriteDataHeader(kTRUE, kFALSE);
226
227         // Figure out the sample rate 
228         if (fSampleRate > 0) sampleRate = fSampleRate;
229         else {
230           if (digit->Count2() >= 0) sampleRate = 2;
231           if (digit->Count3() >= 0) sampleRate = 3;
232         }
233
234         channel.Set(fChannelsPerAltro * sampleRate);
235         offset     = 0;
236         prevRing   = ring;
237         prevSector = sector;
238         startStrip = strip;
239       }
240       else if (offset == fChannelsPerAltro
241                || digit->Ring() != prevRing 
242                || digit->Sector() != prevSector) {
243         // Force a new Altro channel
244         AliDebug(15, Form("Flushing channel to disk because %s",
245                           (offset == fChannelsPerAltro ? "channel is full" :
246                            (ring != prevRing ? "new ring up" :
247                             "new sector up"))));
248         AliDebug(15, Form("New Channel: Write channel at %d Strip: %d "
249                           "Sector: %d  Ring: %d", 
250                           i, startStrip, prevSector, prevRing));
251         WriteChannel(altro, startStrip, prevSector, prevRing, channel);
252         // Reset and update channel variables 
253         channel.Reset(0);
254         offset     = 0; 
255         startStrip = strip;
256         prevRing   = ring;
257         prevSector = sector;
258       }
259
260       // Store the counts of the ADC in the channel buffer 
261       channel[offset * sampleRate] = digit->Count1();
262       if (sampleRate > 1) 
263         channel[offset * sampleRate + 1] = digit->Count2();
264       if (sampleRate > 2) 
265         channel[offset * sampleRate + 2] = digit->Count3();
266       offset++;
267     }
268     // Finally, we need to close the final ALTRO buffer if it wasn't
269     // already 
270     if (altro) {
271       altro->Flush();
272       altro->WriteDataHeader(kFALSE, kFALSE);
273       delete altro;
274     }
275   }
276   loader->UnloadDigits();
277 }
278
279 //____________________________________________________________________
280 void
281 AliFMDRawWriter::WriteChannel(AliAltroBuffer* altro, 
282                               UShort_t strip, UShort_t sector, Char_t ring, 
283                               const TArrayI& data) 
284 {
285   // Write out one ALTRO channel to the data file. 
286   // Derived classes can overload this method to use a per-ALTRO
287   // threshold.   This implementation uses the common threshold set by
288   // SetThreshold. 
289   altro->WriteChannel(Int_t(strip), 
290                       Int_t(sector), 
291                       Int_t((ring == 'I' ? 0 : 1)), 
292                       data.fN, data.fArray, fThreshold);
293 }
294
295   
296
297 //____________________________________________________________________
298 // 
299 // EOF
300 //