]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PHOS/AliPHOS.cxx
Remove AliTRDv2
[u/mrichter/AliRoot.git] / PHOS / AliPHOS.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 /* History of cvs commits:
17  *
18  * $Log$
19  * Revision 1.98  2006/05/11 11:30:48  cvetan
20  * Major changes in AliAltroBuffer. Now it can be used only for writing of raw data. All the corresponding read method are removed. It is based now on AliFstream in order to avoid endianess problems. The altro raw data is written always with little endian
21  *
22  * Revision 1.97  2006/04/22 10:30:17  hristov
23  * Add fEnergy to AliPHOSDigit and operate with EMC amplitude in energy units (Yu.Kharlov)
24  *
25  * Revision 1.96  2006/04/07 08:41:59  hristov
26  * Follow AliAlignObj framework and remove AliPHOSAlignData (Yu.Kharlov)
27  *
28  * Revision 1.95  2006/03/14 19:40:41  kharlov
29  * Remove De-digitizing of raw data and digitizing the raw data fit
30  *
31  * Revision 1.94  2006/03/07 18:56:25  kharlov
32  * CDB is passed via environment variable
33  *
34  * Revision 1.93  2005/11/22 08:45:11  kharlov
35  * Calibration is read from CDB if any (Boris Polichtchouk)
36  *
37  * Revision 1.92  2005/11/03 13:09:19  hristov
38  * Removing meaningless const declarations (linuxicc)
39  *
40  * Revision 1.91  2005/07/27 15:08:53  kharlov
41  * Mixture ArCO2 is corrected
42  *
43  * Revision 1.90  2005/06/17 07:39:07  hristov
44  * Removing GetDebug and SetDebug from AliRun and AliModule. Using AliLog for the messages
45  *
46  * Revision 1.89  2005/05/28 12:10:07  schutz
47  * Copy constructor is corrected (by T.P.)
48  *
49  */
50
51 //_________________________________________________________________________
52 // Base Class for PHOS description:
53 //   PHOS consists of a PbWO4 calorimeter (EMCA) and a gazeous charged 
54 //    particles detector (CPV or PPSD).
55 //   The only provided method here is CreateMaterials, 
56 //    which defines the materials common to all PHOS versions.   
57 // 
58 //*-- Author: Laurent Aphecetche & Yves Schutz (SUBATECH) 
59 //////////////////////////////////////////////////////////////////////////////
60
61
62 // --- ROOT system ---
63 class TFile;
64 #include <TFolder.h> 
65 #include <TTree.h>
66 #include <TVirtualMC.h> 
67 #include <TH1F.h> 
68 #include <TF1.h> 
69 #include <TRandom.h> 
70
71 // --- Standard library ---
72
73 // --- AliRoot header files ---
74 #include "AliMagF.h"
75 #include "AliPHOS.h"
76 #include "AliPHOSGetter.h"
77 #include "AliRun.h"
78 #include "AliPHOSDigitizer.h"
79 #include "AliPHOSSDigitizer.h"
80 #include "AliPHOSDigit.h"
81 #include "AliAltroBuffer.h"
82 #include "AliLog.h"
83 #include "AliCDBManager.h"
84 #include "AliCDBEntry.h"
85 #include "AliCDBStorage.h"
86 #include "AliPHOSCalibData.h"
87 #include "AliDAQ.h"
88
89 ClassImp(AliPHOS)
90
91 Double_t AliPHOS::fgCapa        = 1.;        // 1pF 
92 Int_t    AliPHOS::fgOrder       = 2 ;
93 Double_t AliPHOS::fgTimeMax     = 2.56E-5 ;  // each sample is over 100 ns fTimeMax/fTimeBins
94 Double_t AliPHOS::fgTimePeak    = 4.1E-6 ;   // 4 micro seconds
95 Double_t AliPHOS::fgTimeTrigger = 100E-9 ;      // 100ns, just for a reference
96
97 //____________________________________________________________________________
98   AliPHOS:: AliPHOS() : AliDetector()
99 {
100   // Default ctor
101   fName   = "PHOS" ;
102
103 }
104
105 //____________________________________________________________________________
106 AliPHOS::AliPHOS(const char* name, const char* title): AliDetector(name, title)
107 {
108   //   ctor : title is used to identify the layout
109
110   fHighCharge        = 8.2 ;          // adjusted for a high gain range of 5.12 GeV (10 bits)
111   fHighGain          = 6.64 ; 
112   fHighLowGainFactor = 16. ;          // adjusted for a low gain range of 82 GeV (10 bits) 
113   fLowGainOffset     = GetGeometry()->GetNModules() + 1 ;   
114     // offset added to the module id to distinguish high and low gain data
115 }
116
117 //____________________________________________________________________________
118 AliPHOS::~AliPHOS() 
119 {  
120 }
121
122 //____________________________________________________________________________
123 void AliPHOS::Copy(TObject &obj)const
124 {
125   // copy method to be used by the cpy ctor
126   TObject::Copy(obj);
127   
128   AliPHOS &phos = static_cast<AliPHOS &>(obj); 
129   
130   phos.fHighCharge        = fHighCharge ;
131   phos.fHighGain          = fHighGain ; 
132   phos.fHighLowGainFactor = fHighLowGainFactor ;  
133   phos.fLowGainOffset     = fLowGainOffset;   
134 }
135
136 //____________________________________________________________________________
137 AliDigitizer* AliPHOS::CreateDigitizer(AliRunDigitizer* manager) const
138 {
139   return new AliPHOSDigitizer(manager);
140 }
141
142 //____________________________________________________________________________
143 void AliPHOS::CreateMaterials()
144 {
145   // Definitions of materials to build PHOS and associated tracking media.
146   // media number in idtmed are 699 to 798.
147
148   // --- The PbWO4 crystals ---
149   Float_t aX[3] = {207.19, 183.85, 16.0} ;
150   Float_t zX[3] = {82.0, 74.0, 8.0} ;
151   Float_t wX[3] = {1.0, 1.0, 4.0} ;
152   Float_t dX = 8.28 ;
153
154   AliMixture(0, "PbWO4$", aX, zX, dX, -3, wX) ;
155
156
157   // --- The polysterene scintillator (CH) ---
158   Float_t aP[2] = {12.011, 1.00794} ;
159   Float_t zP[2] = {6.0, 1.0} ;
160   Float_t wP[2] = {1.0, 1.0} ;
161   Float_t dP = 1.032 ;
162
163   AliMixture(1, "Polystyrene$", aP, zP, dP, -2, wP) ;
164
165   // --- Aluminium ---
166   AliMaterial(2, "Al$", 26.98, 13., 2.7, 8.9, 999., 0, 0) ;
167   // ---         Absorption length is ignored ^
168
169  // --- Tyvek (CnH2n) ---
170   Float_t aT[2] = {12.011, 1.00794} ;
171   Float_t zT[2] = {6.0, 1.0} ;
172   Float_t wT[2] = {1.0, 2.0} ;
173   Float_t dT = 0.331 ;
174
175   AliMixture(3, "Tyvek$", aT, zT, dT, -2, wT) ;
176
177   // --- Polystyrene foam ---
178   Float_t aF[2] = {12.011, 1.00794} ;
179   Float_t zF[2] = {6.0, 1.0} ;
180   Float_t wF[2] = {1.0, 1.0} ;
181   Float_t dF = 0.12 ;
182
183   AliMixture(4, "Foam$", aF, zF, dF, -2, wF) ;
184
185  // --- Titanium ---
186   Float_t aTIT[3] = {47.88, 26.98, 54.94} ;
187   Float_t zTIT[3] = {22.0, 13.0, 25.0} ;
188   Float_t wTIT[3] = {69.0, 6.0, 1.0} ;
189   Float_t dTIT = 4.5 ;
190
191   AliMixture(5, "Titanium$", aTIT, zTIT, dTIT, -3, wTIT);
192
193  // --- Silicon ---
194   AliMaterial(6, "Si$", 28.0855, 14., 2.33, 9.36, 42.3, 0, 0) ;
195
196
197
198   // --- Foam thermo insulation ---
199   Float_t aTI[2] = {12.011, 1.00794} ;
200   Float_t zTI[2] = {6.0, 1.0} ;
201   Float_t wTI[2] = {1.0, 1.0} ;
202   Float_t dTI = 0.04 ;
203
204   AliMixture(7, "Thermo Insul.$", aTI, zTI, dTI, -2, wTI) ;
205
206   // --- Textolith ---
207   Float_t aTX[4] = {16.0, 28.09, 12.011, 1.00794} ;
208   Float_t zTX[4] = {8.0, 14.0, 6.0, 1.0} ;
209   Float_t wTX[4] = {292.0, 68.0, 462.0, 736.0} ;
210   Float_t dTX    = 1.75 ;
211
212   AliMixture(8, "Textolit$", aTX, zTX, dTX, -4, wTX) ;
213
214   //--- FR4  ---
215   Float_t aFR[4] = {16.0, 28.09, 12.011, 1.00794} ;
216   Float_t zFR[4] = {8.0, 14.0, 6.0, 1.0} ;
217   Float_t wFR[4] = {292.0, 68.0, 462.0, 736.0} ;
218   Float_t dFR = 1.8 ; 
219
220   AliMixture(9, "FR4$", aFR, zFR, dFR, -4, wFR) ;
221
222   // --- The Composite Material for  micromegas (so far polyetylene) ---                                       
223   Float_t aCM[2] = {12.01, 1.} ; 
224   Float_t zCM[2] = {6., 1.} ; 
225   Float_t wCM[2] = {1., 2.} ; 
226   Float_t dCM = 0.935 ; 
227
228   AliMixture(10, "Compo Mat$", aCM, zCM, dCM, -2, wCM) ;
229
230   // --- Copper ---                                                                    
231   AliMaterial(11, "Cu$", 63.546, 29, 8.96, 1.43, 14.8, 0, 0) ;
232  
233   // --- G10 : Printed Circuit material ---                                                  
234   Float_t aG10[4] = { 12., 1., 16., 28.} ;
235   Float_t zG10[4] = { 6., 1., 8., 14.} ;
236   Float_t wG10[4] = { .259, .288, .248, .205} ;
237   Float_t dG10  = 1.7 ;
238   
239   AliMixture(12, "G10$", aG10, zG10, dG10, -4, wG10);
240
241   // --- Lead ---                                                                     
242   AliMaterial(13, "Pb$", 207.2, 82, 11.35, 0.56, 0., 0, 0) ;
243
244  // --- The gas mixture ---                                                                
245  // Co2
246   Float_t aCO[2] = {12.0, 16.0} ; 
247   Float_t zCO[2] = {6.0, 8.0} ; 
248   Float_t wCO[2] = {1.0, 2.0} ; 
249   Float_t dCO = 0.001977 ; 
250
251   AliMixture(14, "CO2$", aCO, zCO, dCO, -2, wCO);
252
253  // Ar
254   Float_t dAr = 0.001782 ; 
255   AliMaterial(15, "Ar$", 39.948, 18.0, dAr, 14.0, 0., 0, 0) ;   
256  
257   // Ar+CO2 Mixture (80% / 20%)
258   Float_t arContent = 0.80 ;  // Ar-content of the ArCO2-mixture
259   Float_t aArCO[3]  = {39.948, 12.0, 16.0} ;
260   Float_t zArCO[3]  = {18.0  ,  6.0,  8.0} ;
261   Float_t wArCO[3];
262   wArCO[0] = arContent;
263   wArCO[1] = (1-arContent)*1;
264   wArCO[2] = (1-arContent)*2;
265   Float_t dArCO = arContent*dAr + (1-arContent)*dCO ;
266   AliMixture(16, "ArCO2$", aArCO, zArCO, dArCO,  -3, wArCO) ;
267
268   // --- Stainless steel (let it be pure iron) ---
269   AliMaterial(17, "Steel$", 55.845, 26, 7.87, 1.76, 0., 0, 0) ;
270
271
272   // --- Fiberglass ---
273   Float_t aFG[4] = {16.0, 28.09, 12.011, 1.00794} ;
274   Float_t zFG[4] = {8.0, 14.0, 6.0, 1.0} ;
275   Float_t wFG[4] = {292.0, 68.0, 462.0, 736.0} ;
276   Float_t dFG    = 1.9 ;
277
278   AliMixture(18, "Fibergla$", aFG, zFG, dFG, -4, wFG) ;
279
280   // --- Cables in Air box  ---
281   // SERVICES
282
283   Float_t aCA[4] = { 1.,12.,55.8,63.5 };
284   Float_t zCA[4] = { 1.,6.,26.,29. }; 
285   Float_t wCA[4] = { .014,.086,.42,.48 };
286   Float_t dCA    = 0.8 ;  //this density is raw estimation, if you know better - correct
287
288   AliMixture(19, "Cables  $", aCA, zCA, dCA, -4, wCA) ;
289
290
291   // --- Air ---
292   Float_t aAir[4]={12.0107,14.0067,15.9994,39.948};
293   Float_t zAir[4]={6.,7.,8.,18.};
294   Float_t wAir[4]={0.000124,0.755267,0.231781,0.012827};
295   Float_t dAir = 1.20479E-3;
296  
297   AliMixture(99, "Air$", aAir, zAir, dAir, 4, wAir) ;
298
299   // DEFINITION OF THE TRACKING MEDIA
300
301   // for PHOS: idtmed[699->798] equivalent to fIdtmed[0->100]
302   Int_t * idtmed = fIdtmed->GetArray() - 699 ; 
303   Int_t   isxfld = gAlice->Field()->Integ() ;
304   Float_t sxmgmx = gAlice->Field()->Max() ;
305
306   // The scintillator of the calorimeter made of PBW04                              -> idtmed[699]
307   AliMedium(0, "PHOS Xtal    $", 0, 1,
308             isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.1, 0, 0) ;
309
310   // The scintillator of the CPV made of Polystyrene scintillator                   -> idtmed[700]
311   AliMedium(1, "CPV scint.   $", 1, 1,
312             isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.1, 0, 0) ;
313
314   // Various Aluminium parts made of Al                                             -> idtmed[701]
315   AliMedium(2, "Al parts     $", 2, 0,
316              isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.001, 0.001, 0, 0) ;
317
318   // The Tywek which wraps the calorimeter crystals                                 -> idtmed[702]
319   AliMedium(3, "Tyvek wrapper$", 3, 0,
320              isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.001, 0.001, 0, 0) ;
321
322   // The Polystyrene foam around the calorimeter module                             -> idtmed[703]
323   AliMedium(4, "Polyst. foam $", 4, 0,
324              isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.1, 0, 0) ;
325
326   // The Titanium around the calorimeter crystal                                    -> idtmed[704]
327   AliMedium(5, "Titan. cover $", 5, 0,
328              isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.0001, 0.0001, 0, 0) ;
329
330   // The Silicon of the pin diode to read out the calorimeter crystal               -> idtmed[705] 
331  AliMedium(6, "Si PIN       $", 6, 0,
332              isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.01, 0.01, 0, 0) ;
333
334  // The thermo insulating material of the box which contains the calorimeter module -> idtmed[706]
335   AliMedium(7, "Thermo Insul.$", 7, 0,
336              isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.1, 0, 0) ;
337
338   // The Textolit which makes up the box which contains the calorimeter module      -> idtmed[707]
339   AliMedium(8, "Textolit     $", 8, 0,
340              isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.1, 0, 0) ;
341
342   // FR4: The Plastic which makes up the frame of micromegas                        -> idtmed[708]
343   AliMedium(9, "FR4 $", 9, 0,
344              isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.0001, 0, 0) ; 
345
346
347   // The Composite Material for  micromegas                                         -> idtmed[709]
348   AliMedium(10, "CompoMat   $", 10, 0,
349              isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.1, 0, 0) ;
350
351   // Copper                                                                         -> idtmed[710]
352   AliMedium(11, "Copper     $", 11, 0,
353              isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.0001, 0, 0) ;
354
355   // G10: Printed Circuit material                                                  -> idtmed[711]
356  
357   AliMedium(12, "G10        $", 12, 0,
358              isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.01, 0, 0) ;
359
360   // The Lead                                                                       -> idtmed[712]
361  
362   AliMedium(13, "Lead      $", 13, 0,
363              isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.1, 0, 0) ;
364
365   // The gas mixture: ArCo2                                                         -> idtmed[715]
366  
367   AliMedium(16, "ArCo2      $", 16, 1,
368              isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.01, 0, 0) ;
369  
370   // Stainless steel                                                                -> idtmed[716]
371   AliMedium(17, "Steel     $", 17, 0,
372              isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.0001, 0, 0) ;
373
374   // Fibergalss                                                                     -> idtmed[717]
375   AliMedium(18, "Fiberglass$", 18, 0,
376              isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.1, 0, 0) ;
377
378   // Cables in air                                                                  -> idtmed[718]
379   AliMedium(19, "Cables    $", 19, 0,
380              isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.1, 0, 0) ;
381
382   // Air                                                                            -> idtmed[798] 
383   AliMedium(99, "Air          $", 99, 0,
384              isxfld, sxmgmx, 10.0, 1.0, 0.1, 0.1, 10.0, 0, 0) ;
385
386   // --- Set decent energy thresholds for gamma and electron tracking
387
388   // Tracking threshold for photons and electrons in the scintillator crystal 
389   gMC->Gstpar(idtmed[699], "CUTGAM",0.5E-4) ; 
390   gMC->Gstpar(idtmed[699], "CUTELE",1.0E-4) ;
391  
392   // --- Generate explicitly delta rays in the titan cover ---
393   gMC->Gstpar(idtmed[704], "LOSS",3.) ;
394   gMC->Gstpar(idtmed[704], "DRAY",1.) ;
395   // --- and in aluminium parts ---
396   gMC->Gstpar(idtmed[701], "LOSS",3.) ;
397   gMC->Gstpar(idtmed[701], "DRAY",1.) ;
398   // --- and in PIN diode
399   gMC->Gstpar(idtmed[705], "LOSS",3) ;
400   gMC->Gstpar(idtmed[705], "DRAY",1) ;
401   // --- and in the passive convertor
402   gMC->Gstpar(idtmed[712], "LOSS",3) ;
403   gMC->Gstpar(idtmed[712], "DRAY",1) ;
404   // Tracking threshold for photons and electrons in the gas ArC02 
405   gMC->Gstpar(idtmed[715], "CUTGAM",1.E-5) ; 
406   gMC->Gstpar(idtmed[715], "CUTELE",1.E-5) ;
407   gMC->Gstpar(idtmed[715], "CUTNEU",1.E-5) ;
408   gMC->Gstpar(idtmed[715], "CUTHAD",1.E-5) ;
409   gMC->Gstpar(idtmed[715], "CUTMUO",1.E-5) ;
410   gMC->Gstpar(idtmed[715], "BCUTE",1.E-5) ;
411   gMC->Gstpar(idtmed[715], "BCUTM",1.E-5) ;
412   gMC->Gstpar(idtmed[715], "DCUTE",1.E-5) ;
413   gMC->Gstpar(idtmed[715], "DCUTM",1.E-5) ;
414   gMC->Gstpar(idtmed[715], "PPCUTM",1.E-5) ;
415   gMC->Gstpar(idtmed[715], "LOSS",2.) ;
416   gMC->Gstpar(idtmed[715], "DRAY",0.) ;
417   gMC->Gstpar(idtmed[715], "STRA",2.) ;
418
419 }
420
421 //____________________________________________________________________________
422 void AliPHOS::Digits2Raw()
423 {
424 // convert digits of the current event to raw data
425   
426   AliPHOSLoader * loader = dynamic_cast<AliPHOSLoader*>(fLoader) ; 
427
428   // get the digits
429   loader->LoadDigits();
430   TClonesArray* digits = loader->Digits() ;
431
432   if (!digits) {
433     AliError(Form("No digits found !"));
434     return;
435   }
436
437   // get the geometry
438   AliPHOSGeometry* geom = GetGeometry();
439   if (!geom) {
440     AliError(Form("No geometry found !"));
441     return;
442   }
443
444   // some digitization constants
445 //   const Int_t    kThreshold = 1; // skip digits below this threshold // YVK
446   const Float_t    kThreshold = 0.001; // skip digits below 1 MeV
447   const Int_t      kAdcThreshold = 1;  // Lower ADC threshold to write to raw data
448
449   AliAltroBuffer* buffer = NULL;
450   Int_t prevDDL = -1;
451   Int_t adcValuesLow[fkTimeBins];
452   Int_t adcValuesHigh[fkTimeBins];
453
454   // loop over digits (assume ordered digits)
455   for (Int_t iDigit = 0; iDigit < digits->GetEntries(); iDigit++) {
456     AliPHOSDigit* digit = dynamic_cast<AliPHOSDigit *>(digits->At(iDigit)) ;
457     if (digit->GetEnergy() < kThreshold) 
458       continue;
459     Int_t relId[4];
460     geom->AbsToRelNumbering(digit->GetId(), relId);
461     Int_t module = relId[0];
462  
463    // Begin FIXME 
464     if (relId[1] != 0) 
465       continue;    // ignore digits from CPV
466    // End FIXME 
467
468     // PHOS EMCA has 4 DDL per module. Splitting is done based on the row number
469     Int_t iDDL = 4 * (module - 1) + (4 * (relId[2] - 1)) / geom->GetNPhi();
470
471     // new DDL
472     if (iDDL != prevDDL) {
473       // write real header and close previous file
474       if (buffer) {
475         buffer->Flush();
476         buffer->WriteDataHeader(kFALSE, kFALSE);
477         delete buffer;
478       }
479
480       // open new file and write dummy header
481       TString fileName = AliDAQ::DdlFileName("PHOS",iDDL);
482       buffer = new AliAltroBuffer(fileName.Data());
483       buffer->WriteDataHeader(kTRUE, kFALSE);  //Dummy;
484
485       prevDDL = iDDL;
486     }
487
488     // out of time range signal (?)
489     if (digit->GetTimeR() > GetRawFormatTimeMax() ) {
490       buffer->FillBuffer((Int_t)digit->GetEnergy());
491       buffer->FillBuffer(GetRawFormatTimeBins() );  // time bin
492       buffer->FillBuffer(3);          // bunch length      
493       buffer->WriteTrailer(3, relId[3], relId[2], module);  // trailer
494       
495     // calculate the time response function
496     } else {
497       Double_t energy = 0 ;
498       Int_t   module = relId[0];
499       if ( digit->GetId() <= geom->GetNModules() *  geom->GetNCristalsInModule()) {
500         energy=digit->GetEnergy();
501       }
502       else {
503 //      energy = digit->GetAmp()*digitizer->GetCPVchannel()+digitizer->GetCPVpedestal();
504         energy = 0; // CPV raw data format is now know yet
505       }        
506       Bool_t lowgain = RawSampledResponse(digit->GetTimeR(), energy, adcValuesHigh, adcValuesLow) ; 
507       
508       if (lowgain) 
509         buffer->WriteChannel(relId[3], relId[2], module + fLowGainOffset, 
510                              GetRawFormatTimeBins(), adcValuesLow , kAdcThreshold);
511       else 
512         buffer->WriteChannel(relId[3], relId[2], module, 
513                              GetRawFormatTimeBins(), adcValuesHigh, kAdcThreshold);
514       
515     }
516   }
517   
518   // write real header and close last file
519   if (buffer) {
520     buffer->Flush();
521     buffer->WriteDataHeader(kFALSE, kFALSE);
522     delete buffer;
523   }
524   
525   loader->UnloadDigits();
526 }
527
528 //____________________________________________________________________________
529 void AliPHOS::Hits2SDigits()  
530
531 // create summable digits
532
533   AliPHOSSDigitizer phosDigitizer(fLoader->GetRunLoader()->GetFileName().Data()) ;
534   phosDigitizer.SetEventRange(0, -1) ; // do all the events
535   phosDigitizer.ExecuteTask("all") ; 
536 }
537
538 //____________________________________________________________________________
539 AliLoader* AliPHOS::MakeLoader(const char* topfoldername)
540 {
541 //different behaviour than standard (singleton getter)
542 // --> to be discussed and made eventually coherent
543  fLoader = new AliPHOSLoader(GetName(),topfoldername);
544  return fLoader;
545 }
546
547 //__________________________________________________________________
548 Double_t AliPHOS::RawResponseFunction(Double_t *x, Double_t *par) 
549 {
550   // Shape of the electronics raw reponse:
551   // It is a semi-gaussian, 2nd order Gamma function of the general form
552   // v(t) = n**n * Q * A**n / C *(t/tp)**n * exp(-n * t/tp) with 
553   // tp : peaking time par[0]
554   // n  : order of the function
555   // C  : integrating capacitor in the preamplifier
556   // A  : open loop gain of the preamplifier
557   // Q  : the total APD charge to be measured Q = C * energy
558   
559   Double_t signal ;
560   Double_t xx = x[0] - ( fgTimeTrigger + par[3] ) ; 
561
562   if (xx < 0 || xx > fgTimeMax) 
563     signal = 0. ;  
564   else { 
565     Double_t fac = par[0] * TMath::Power(fgOrder, fgOrder) * TMath::Power(par[1], fgOrder) / fgCapa ; 
566     signal = fac * par[2] * TMath::Power(xx / fgTimePeak, fgOrder) * TMath::Exp(-fgOrder * (xx / fgTimePeak)) ; 
567   }
568   return signal ;  
569 }
570
571 //__________________________________________________________________
572 Double_t AliPHOS::RawResponseFunctionMax(Double_t charge, Double_t gain) 
573 {
574   return ( charge * TMath::Power(fgOrder, fgOrder) * TMath::Power(gain, fgOrder) 
575      / ( fgCapa * TMath::Exp(fgOrder) ) );  
576
577 }
578
579 //__________________________________________________________________
580 Bool_t AliPHOS::RawSampledResponse(Double_t dtime, Double_t damp, Int_t * adcH, Int_t * adcL) const 
581 {
582   // for a start time dtime and an amplitude damp given by digit, 
583   // calculates the raw sampled response AliPHOS::RawResponseFunction
584   // Input: dtime - signal start time
585   //        damp  - signal amplitude (energy)
586   // Output: adcH - array[fkTimeBins] of 10-bit samples for high-gain channel
587   //         adcL - array[fkTimeBins] of 10-bit samples for low-gain channel
588
589   const Int_t kRawSignalOverflow = 0x3FF ; 
590   Bool_t lowGain = kFALSE ; 
591
592   TF1 signalF("signal", RawResponseFunction, 0, GetRawFormatTimeMax(), 4);
593
594   for (Int_t iTime = 0; iTime < GetRawFormatTimeBins(); iTime++) {
595     signalF.SetParameter(0, GetRawFormatHighCharge() ) ; 
596     signalF.SetParameter(1, GetRawFormatHighGain() ) ; 
597     signalF.SetParameter(2, damp) ; 
598     signalF.SetParameter(3, dtime) ; 
599     Double_t time = iTime * GetRawFormatTimeMax() / GetRawFormatTimeBins() ;
600     Double_t signal = signalF.Eval(time) ;     
601     if ( static_cast<Int_t>(signal+0.5) > kRawSignalOverflow ){  // larger than 10 bits 
602       signal = kRawSignalOverflow ;
603       lowGain = kTRUE ; 
604     }
605     adcH[iTime] =  static_cast<Int_t>(signal + 0.5) ;
606
607     signalF.SetParameter(0, GetRawFormatLowCharge() ) ;     
608     signalF.SetParameter(1, GetRawFormatLowGain() ) ; 
609     signal = signalF.Eval(time) ;  
610     if ( static_cast<Int_t>(signal+0.5) > kRawSignalOverflow)  // larger than 10 bits 
611       signal = kRawSignalOverflow ;
612     adcL[iTime] = static_cast<Int_t>(0.5 + signal ) ; 
613
614   }
615   return lowGain ; 
616 }
617
618 //____________________________________________________________________________
619 void AliPHOS::SetTreeAddress()
620
621   // Links Hits in the Tree to Hits array
622   TBranch *branch;
623   char branchname[20];
624   sprintf(branchname,"%s",GetName());
625   // Branch address for hit tree
626     TTree *treeH = TreeH();
627   if (treeH) {
628     branch = treeH->GetBranch(branchname);
629     if (branch) 
630      { 
631        if (fHits == 0x0) fHits= new TClonesArray("AliPHOSHit",1000);
632        //AliInfo(Form("<%s> Setting Hits Address",GetName()));
633        branch->SetAddress(&fHits);
634      }
635   }
636 }
637