]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PHOS/AliPHOSv1.cxx
Corrected copy constructor and assignment operator, fixed memory leaks (Christian)
[u/mrichter/AliRoot.git] / PHOS / AliPHOSv1.cxx
CommitLineData
7587f5a5 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
b2a60966 16/* $Id$ */
5f20d3fb 17
702ab87e 18/* History of cvs commits:
19 *
20 * $Log$
1c6f1c46 21 * Revision 1.110 2007/03/10 08:58:52 kharlov
22 * Protection for noCPV geometry
23 *
39926a84 24 * Revision 1.109 2007/03/01 11:37:37 kharlov
25 * Strip units changed from 8x1 to 8x2 (T.Pocheptsov)
26 *
331c963c 27 * Revision 1.108 2007/02/02 09:40:50 alibrary
28 * Includes required by ROOT head
29 *
7ca4655f 30 * Revision 1.107 2007/02/01 10:34:47 hristov
31 * Removing warnings on Solaris x86
32 *
ad4aeaf4 33 * Revision 1.106 2006/11/14 17:11:15 hristov
34 * Removing inheritances from TAttLine, TAttMarker and AliRndm in AliModule. The copy constructor and assignment operators are moved to the private part of the class and not implemented. The corresponding changes are propagated to the detectors
35 *
e939a978 36 * Revision 1.105 2006/09/13 07:31:01 kharlov
37 * Effective C++ corrections (T.Pocheptsov)
38 *
43fbaae1 39 * Revision 1.104 2005/05/28 14:19:05 schutz
40 * Compilation warnings fixed by T.P.
41 *
702ab87e 42 */
43
7587f5a5 44//_________________________________________________________________________
5f20d3fb 45// Implementation version v1 of PHOS Manager class
a3dfe79c 46//---
a3dfe79c 47//---
48// Layout EMC + CPV has name IHEP:
ed4205d8 49// Produces hits for CPV, cumulated hits
50//---
ed4205d8 51//---
5f20d3fb 52//*-- Author: Yves Schutz (SUBATECH)
b2a60966 53
7587f5a5 54
55// --- ROOT system ---
7ca4655f 56#include <TClonesArray.h>
88cb7938 57#include <TParticle.h>
88cb7938 58#include <TVirtualMC.h>
7587f5a5 59
60// --- Standard library ---
61
88cb7938 62
7587f5a5 63// --- AliRoot header files ---
97cee223 64#include "AliPHOSCPVDigit.h"
97cee223 65#include "AliPHOSGeometry.h"
88cb7938 66#include "AliPHOSHit.h"
88cb7938 67#include "AliPHOSv1.h"
68#include "AliRun.h"
5d12ce38 69#include "AliMC.h"
1c6f1c46 70#include "AliStack.h"
7587f5a5 71
72ClassImp(AliPHOSv1)
73
bea63bea 74//____________________________________________________________________________
02ab1add 75AliPHOSv1::AliPHOSv1():
43fbaae1 76 fLightYieldMean(0.),
77 fIntrinsicPINEfficiency(0.),
78 fLightYieldAttenuation(0.),
79 fRecalibrationFactor(0.),
80 fElectronsPerGeV(0.),
81 fAPDGain(0.),
82 fLightFactor(0.),
83 fAPDFactor(0.)
bea63bea 84{
43fbaae1 85 //Def ctor.
bea63bea 86}
87
7587f5a5 88//____________________________________________________________________________
89AliPHOSv1::AliPHOSv1(const char *name, const char *title):
43fbaae1 90 AliPHOSv0(name,title),
91 fLightYieldMean(0.),
92 fIntrinsicPINEfficiency(0.),
93 fLightYieldAttenuation(0.),
94 fRecalibrationFactor(0.),
95 fElectronsPerGeV(0.),
96 fAPDGain(0.),
97 fLightFactor(0.),
98 fAPDFactor(0.)
7587f5a5 99{
5f20d3fb 100 //
ed4205d8 101 // We store hits :
5f20d3fb 102 // - fHits (the "normal" one), which retains the hits associated with
103 // the current primary particle being tracked
104 // (this array is reset after each primary has been tracked).
105 //
fa412d9b 106
037cc66d 107
5f20d3fb 108
109 // We do not want to save in TreeH the raw hits
110 // But save the cumulated hits instead (need to create the branch myself)
111 // It is put in the Digit Tree because the TreeH is filled after each primary
7b326aac 112 // and the TreeD at the end of the event (branch is set in FinishEvent() ).
5f20d3fb 113
ed4205d8 114 fHits= new TClonesArray("AliPHOSHit",1000) ;
5d12ce38 115 gAlice->GetMCApp()->AddHitList(fHits) ;
5f20d3fb 116
ed4205d8 117 fNhits = 0 ;
5f20d3fb 118
f6d1e5e1 119 fIshunt = 2 ; // All hits are associated with primary particles
7b326aac 120
9688c1dd 121 //Photoelectron statistics:
122 // The light yield is a poissonian distribution of the number of
123 // photons created in the PbWo4 crystal, calculated using following formula
124 // NumberOfPhotons = EnergyLost * LightYieldMean* APDEfficiency *
125 // exp (-LightYieldAttenuation * DistanceToPINdiodeFromTheHit);
126 // LightYieldMean is parameter calculated to be over 47000 photons per GeV
127 // APDEfficiency is 0.02655
128 // k_0 is 0.0045 from Valery Antonenko
129 // The number of electrons created in the APD is
130 // NumberOfElectrons = APDGain * LightYield
131 // The APD Gain is 300
132 fLightYieldMean = 47000;
133 fIntrinsicPINEfficiency = 0.02655 ; //APD= 0.1875/0.1271 * 0.018 (PIN)
27f33ee5 134 fLightYieldAttenuation = 0.0045 ;
135 fRecalibrationFactor = 13.418/ fLightYieldMean ;
136 fElectronsPerGeV = 2.77e+8 ;
137 fAPDGain = 300. ;
138 fLightFactor = fLightYieldMean * fIntrinsicPINEfficiency ;
184569b0 139 fAPDFactor = (fRecalibrationFactor/100.) * fAPDGain ;
5f20d3fb 140}
141
7587f5a5 142//____________________________________________________________________________
bea63bea 143AliPHOSv1::~AliPHOSv1()
b2a60966 144{
bea63bea 145 // dtor
88cb7938 146 if ( fHits) {
ed4205d8 147 fHits->Delete() ;
148 delete fHits ;
149 fHits = 0 ;
184569b0 150 }
7587f5a5 151}
152
7587f5a5 153//____________________________________________________________________________
2af5445a 154void AliPHOSv1::AddHit(Int_t shunt, Int_t primary, Int_t Id, Float_t * hits)
bea63bea 155{
156 // Add a hit to the hit list.
f6d1e5e1 157 // A PHOS hit is the sum of all hits in a single crystal from one primary and within some time gate
bea63bea 158
5f20d3fb 159 Int_t hitCounter ;
bea63bea 160 AliPHOSHit *newHit ;
5f20d3fb 161 AliPHOSHit *curHit ;
162 Bool_t deja = kFALSE ;
fa7cce36 163 AliPHOSGeometry * geom = GetGeometry() ;
bea63bea 164
2af5445a 165 newHit = new AliPHOSHit(shunt, primary, Id, hits) ;
bea63bea 166
7854a24a 167 for ( hitCounter = fNhits-1 ; hitCounter >= 0 && !deja ; hitCounter-- ) {
29b077b5 168 curHit = dynamic_cast<AliPHOSHit*>((*fHits)[hitCounter]) ;
9688c1dd 169 if(curHit->GetPrimary() != primary) break ;
170 // We add hits with the same primary, while GEANT treats primaries succesively
ed4205d8 171 if( *curHit == *newHit ) {
f15a01eb 172 *curHit + *newHit ;
ed4205d8 173 deja = kTRUE ;
5f20d3fb 174 }
175 }
176
177 if ( !deja ) {
ed4205d8 178 new((*fHits)[fNhits]) AliPHOSHit(*newHit) ;
7b326aac 179 // get the block Id number
9688c1dd 180 Int_t relid[4] ;
fa7cce36 181 geom->AbsToRelNumbering(Id, relid) ;
184569b0 182
ed4205d8 183 fNhits++ ;
5f20d3fb 184 }
184569b0 185
bea63bea 186 delete newHit;
bea63bea 187}
188
7b326aac 189//____________________________________________________________________________
190void AliPHOSv1::FinishPrimary()
191{
192 // called at the end of each track (primary) by AliRun
193 // hits are reset for each new track
194 // accumulate the total hit-multiplicity
7b326aac 195
196}
197
198//____________________________________________________________________________
199void AliPHOSv1::FinishEvent()
200{
201 // called at the end of each event by AliRun
202 // accumulate the hit-multiplicity and total energy per block
203 // if the values have been updated check it
88cb7938 204
88cb7938 205 AliDetector::FinishEvent();
7b326aac 206}
5f20d3fb 207//____________________________________________________________________________
7587f5a5 208void AliPHOSv1::StepManager(void)
209{
9688c1dd 210 // Accumulates hits as long as the track stays in a single crystal or CPV gas Cell
b2a60966 211
4f5bbbd4 212 Int_t relid[4] ; // (box, layer, row, column) indices
213 Int_t absid ; // absolute cell ID number
471193a8 214 Float_t xyzte[5]={-1000.,-1000.,-1000.,0.,0.} ; // position wrt MRS, time and energy deposited
4f5bbbd4 215 TLorentzVector pos ; // Lorentz vector of the track current position
fa412d9b 216 Int_t copy ;
7587f5a5 217
9688c1dd 218 Int_t moduleNumber ;
219
39926a84 220 static Int_t idPCPQ = -1;
221 if (strstr(fTitle.Data(),"noCPV") == 0)
222 idPCPQ = gMC->VolId("PCPQ");
223
d6fb41ac 224 if( gMC->CurrentVolID(copy) == idPCPQ &&
9688c1dd 225 (gMC->IsTrackEntering() ) &&
226 gMC->TrackCharge() != 0) {
f6d1e5e1 227
9688c1dd 228 gMC -> TrackPosition(pos);
f6d1e5e1 229
9688c1dd 230 Float_t xyzm[3], xyzd[3] ;
231 Int_t i;
232 for (i=0; i<3; i++) xyzm[i] = pos[i];
233 gMC -> Gmtod (xyzm, xyzd, 1); // transform coordinate from master to daughter system
234
e3daf02c 235 Float_t xyd[3]={0,0,0} ; //local position of the entering
9688c1dd 236 xyd[0] = xyzd[0];
53e03a1e 237 xyd[1] =-xyzd[2];
238 xyd[2] =-xyzd[1];
f6d1e5e1 239
9688c1dd 240 // Current momentum of the hit's track in the local ref. system
241 TLorentzVector pmom ; //momentum of the particle initiated hit
242 gMC -> TrackMomentum(pmom);
243 Float_t pm[3], pd[3];
244 for (i=0; i<3; i++)
245 pm[i] = pmom[i];
f6d1e5e1 246
9688c1dd 247 gMC -> Gmtod (pm, pd, 2); // transform 3-momentum from master to daughter system
248 pmom[0] = pd[0];
cf75bc19 249 pmom[1] =-pd[1];
250 pmom[2] =-pd[2];
f6d1e5e1 251
9688c1dd 252 // Digitize the current CPV hit:
253
254 // 1. find pad response and
255 gMC->CurrentVolOffID(3,moduleNumber);
256 moduleNumber--;
257
258 TClonesArray *cpvDigits = new TClonesArray("AliPHOSCPVDigit",0); // array of digits for current hit
90cceaf6 259 CPVDigitize(pmom,xyd,cpvDigits);
fa412d9b 260
9688c1dd 261 Float_t xmean = 0;
262 Float_t zmean = 0;
263 Float_t qsum = 0;
264 Int_t idigit,ndigits;
265
266 // 2. go through the current digit list and sum digits in pads
267
268 ndigits = cpvDigits->GetEntriesFast();
269 for (idigit=0; idigit<ndigits-1; idigit++) {
29b077b5 270 AliPHOSCPVDigit *cpvDigit1 = dynamic_cast<AliPHOSCPVDigit*>(cpvDigits->UncheckedAt(idigit));
9688c1dd 271 Float_t x1 = cpvDigit1->GetXpad() ;
272 Float_t z1 = cpvDigit1->GetYpad() ;
273 for (Int_t jdigit=idigit+1; jdigit<ndigits; jdigit++) {
29b077b5 274 AliPHOSCPVDigit *cpvDigit2 = dynamic_cast<AliPHOSCPVDigit*>(cpvDigits->UncheckedAt(jdigit));
9688c1dd 275 Float_t x2 = cpvDigit2->GetXpad() ;
276 Float_t z2 = cpvDigit2->GetYpad() ;
277 if (x1==x2 && z1==z2) {
ad4aeaf4 278 Float_t qsumpad = cpvDigit1->GetQpad() + cpvDigit2->GetQpad() ;
279 cpvDigit2->SetQpad(qsumpad) ;
9688c1dd 280 cpvDigits->RemoveAt(idigit) ;
fa412d9b 281 }
282 }
9688c1dd 283 }
284 cpvDigits->Compress() ;
285
286 // 3. add digits to temporary hit list fTmpHits
287
288 ndigits = cpvDigits->GetEntriesFast();
289 for (idigit=0; idigit<ndigits; idigit++) {
29b077b5 290 AliPHOSCPVDigit *cpvDigit = dynamic_cast<AliPHOSCPVDigit*>(cpvDigits->UncheckedAt(idigit));
9688c1dd 291 relid[0] = moduleNumber + 1 ; // CPV (or PHOS) module number
292 relid[1] =-1 ; // means CPV
293 relid[2] = cpvDigit->GetXpad() ; // column number of a pad
294 relid[3] = cpvDigit->GetYpad() ; // row number of a pad
295
296 // get the absolute Id number
297 GetGeometry()->RelToAbsNumbering(relid, absid) ;
298
299 // add current digit to the temporary hit list
300
471193a8 301 xyzte[3] = gMC->TrackTime() ;
302 xyzte[4] = cpvDigit->GetQpad() ; // amplitude in a pad
2af5445a 303
304 Int_t primary = gAlice->GetMCApp()->GetPrimary( gAlice->GetMCApp()->GetCurrentTrackNumber() );
305 AddHit(fIshunt, primary, absid, xyzte);
9688c1dd 306
307 if (cpvDigit->GetQpad() > 0.02) {
308 xmean += cpvDigit->GetQpad() * (cpvDigit->GetXpad() + 0.5);
309 zmean += cpvDigit->GetQpad() * (cpvDigit->GetYpad() + 0.5);
310 qsum += cpvDigit->GetQpad();
fa412d9b 311 }
fa412d9b 312 }
e534a69d 313 if (cpvDigits) {
314 cpvDigits->Delete();
315 delete cpvDigits;
316 cpvDigits=0;
317 }
9688c1dd 318 }
037cc66d 319
9688c1dd 320
d6fb41ac 321 static Int_t idPXTL = gMC->VolId("PXTL");
322 if(gMC->CurrentVolID(copy) == idPXTL ) { // We are inside a PBWO crystal
9688c1dd 323
fa412d9b 324 gMC->TrackPosition(pos) ;
471193a8 325 xyzte[0] = pos[0] ;
326 xyzte[1] = pos[1] ;
327 xyzte[2] = pos[2] ;
597e6309 328
9688c1dd 329 Float_t global[3], local[3] ;
330 global[0] = pos[0] ;
331 global[1] = pos[1] ;
332 global[2] = pos[2] ;
333 Float_t lostenergy = gMC->Edep();
f6d1e5e1 334
335 //Put in the TreeK particle entering PHOS and all its parents
336 if ( gMC->IsTrackEntering() ){
337 Float_t xyzd[3] ;
471193a8 338 gMC -> Gmtod (xyzte, xyzd, 1); // transform coordinate from master to daughter system
97c3e101 339 if (xyzd[1] < -GetGeometry()->GetCrystalSize(1)/2.+0.1){ //Entered close to forward surface
5d12ce38 340 Int_t parent = gAlice->GetMCApp()->GetCurrentTrackNumber() ;
81d4c3d5 341 TParticle * part = gAlice->GetMCApp()->Particle(parent) ;
342 Float_t vert[3],vertd[3] ;
343 vert[0]=part->Vx() ;
344 vert[1]=part->Vy() ;
345 vert[2]=part->Vz() ;
346 gMC -> Gmtod (vert, vertd, 1); // transform coordinate from master to daughter system
2af5445a 347 if(vertd[1]<-GetGeometry()->GetCrystalSize(1)/2.-0.1){ //Particle is created in foront of PHOS
348 //0.1 to get rid of numerical errors
349 part->SetBit(kKeepBit);
81d4c3d5 350 while ( parent != -1 ) {
351 part = gAlice->GetMCApp()->Particle(parent) ;
81d4c3d5 352 part->SetBit(kKeepBit);
353 parent = part->GetFirstMother() ;
354 }
f6d1e5e1 355 }
356 }
357 }
9688c1dd 358 if ( lostenergy != 0 ) { // Track is inside the crystal and deposits some energy
471193a8 359 xyzte[3] = gMC->TrackTime() ;
f6d1e5e1 360
9688c1dd 361 gMC->CurrentVolOffID(10, moduleNumber) ; // get the PHOS module number ;
7b326aac 362
9688c1dd 363 Int_t strip ;
364 gMC->CurrentVolOffID(3, strip);
365 Int_t cell ;
366 gMC->CurrentVolOffID(2, cell);
f6d1e5e1 367
331c963c 368 //Old formula for row is wrong. For example, I have strip 56 (28 for 2 x 8), row must be 1.
369 //But row == 1 + 56 - 56 % 56 == 57 (row == 1 + 28 - 28 % 28 == 29)
370 //Int_t row = 1 + GetGeometry()->GetEMCAGeometry()->GetNStripZ() - strip % (GetGeometry()->GetEMCAGeometry()->GetNStripZ()) ;
371 Int_t row = GetGeometry()->GetEMCAGeometry()->GetNStripZ() - (strip - 1) % (GetGeometry()->GetEMCAGeometry()->GetNStripZ()) ;
372 Int_t col = (Int_t) TMath::Ceil((Double_t) strip/(GetGeometry()->GetEMCAGeometry()->GetNStripZ())) -1 ;
373
374 // Absid for 8x2-strips. Looks nice :)
9688c1dd 375 absid = (moduleNumber-1)*GetGeometry()->GetNCristalsInModule() +
331c963c 376 row * 2 + (col*GetGeometry()->GetEMCAGeometry()->GetNCellsXInStrip() + (cell - 1) / 2)*GetGeometry()->GetNZ() - (cell & 1 ? 1 : 0);
377
9688c1dd 378 gMC->Gmtod(global, local, 1) ;
379
471193a8 380 //Calculates the light yield, the number of photons produced in the
9688c1dd 381 //crystal
27f33ee5 382 Float_t lightYield = gRandom->Poisson(fLightFactor * lostenergy *
9688c1dd 383 exp(-fLightYieldAttenuation *
384 (local[1]+GetGeometry()->GetCrystalSize(1)/2.0 ))
385 ) ;
471193a8 386
9688c1dd 387 //Calculates de energy deposited in the crystal
471193a8 388 xyzte[4] = fAPDFactor * lightYield ;
9688c1dd 389
2af5445a 390 Int_t primary ;
391 if(fIshunt == 2){
392 primary = gAlice->GetMCApp()->GetCurrentTrackNumber() ;
393 TParticle * part = gAlice->GetMCApp()->Particle(primary) ;
394 while ( !part->TestBit(kKeepBit) ) {
395 primary = part->GetFirstMother() ;
396 if(primary == -1){
397 primary = gAlice->GetMCApp()->GetPrimary( gAlice->GetMCApp()->GetCurrentTrackNumber() );
398 break ; //there is a possibility that particle passed e.g. thermal isulator and hits a side
399 //surface of the crystal. In this case it may have no primary at all.
400 //We can not easily separate this case from the case when this is part of the shower,
401 //developed in the neighboring crystal.
402 }
403 part = gAlice->GetMCApp()->Particle(primary) ;
404 }
5a49626b 405 }
2af5445a 406 else
407 primary = gAlice->GetMCApp()->GetPrimary( gAlice->GetMCApp()->GetCurrentTrackNumber() );
5a49626b 408
2af5445a 409
410
9688c1dd 411 // add current hit to the hit list
21cd0c07 412 // Info("StepManager","%d %d", primary, tracknumber) ;
2af5445a 413 AddHit(fIshunt, primary, absid, xyzte);
184569b0 414
fa412d9b 415 } // there is deposited energy
416 } // we are inside a PHOS Xtal
f6d1e5e1 417
fa412d9b 418}
419
420//____________________________________________________________________________
90cceaf6 421void AliPHOSv1::CPVDigitize (TLorentzVector p, Float_t *zxhit, TClonesArray *cpvDigits)
fa412d9b 422{
423 // ------------------------------------------------------------------------
424 // Digitize one CPV hit:
425 // On input take exact 4-momentum p and position zxhit of the hit,
426 // find the pad response around this hit and
427 // put the amplitudes in the pads into array digits
428 //
429 // Author: Yuri Kharlov (after Serguei Sadovsky)
430 // 2 October 2000
431 // ------------------------------------------------------------------------
432
fa7cce36 433 const Float_t kCelWr = GetGeometry()->GetPadSizePhi()/2; // Distance between wires (2 wires above 1 pad)
a3dfe79c 434 const Float_t kDetR = 0.1; // Relative energy fluctuation in track for 100 e-
435 const Float_t kdEdx = 4.0; // Average energy loss in CPV;
436 const Int_t kNgamz = 5; // Ionization size in Z
437 const Int_t kNgamx = 9; // Ionization size in Phi
438 const Float_t kNoise = 0.03; // charge noise in one pad
fa412d9b 439
440 Float_t rnor1,rnor2;
441
442 // Just a reminder on axes notation in the CPV module:
443 // axis Z goes along the beam
444 // axis X goes across the beam in the module plane
445 // axis Y is a normal to the module plane showing from the IP
446
447 Float_t hitX = zxhit[0];
448 Float_t hitZ =-zxhit[1];
449 Float_t pX = p.Px();
450 Float_t pZ =-p.Pz();
451 Float_t pNorm = p.Py();
a3dfe79c 452 Float_t eloss = kdEdx;
3d402178 453
21cd0c07 454//Info("CPVDigitize", "YVK : %f %f | %f %f %d", hitX, hitZ, pX, pZ, pNorm) ;
7b326aac 455
fa7cce36 456 Float_t dZY = pZ/pNorm * GetGeometry()->GetCPVGasThickness();
457 Float_t dXY = pX/pNorm * GetGeometry()->GetCPVGasThickness();
fa412d9b 458 gRandom->Rannor(rnor1,rnor2);
a3dfe79c 459 eloss *= (1 + kDetR*rnor1) *
fa7cce36 460 TMath::Sqrt((1 + ( pow(dZY,2) + pow(dXY,2) ) / pow(GetGeometry()->GetCPVGasThickness(),2)));
461 Float_t zhit1 = hitZ + GetGeometry()->GetCPVActiveSize(1)/2 - dZY/2;
462 Float_t xhit1 = hitX + GetGeometry()->GetCPVActiveSize(0)/2 - dXY/2;
fa412d9b 463 Float_t zhit2 = zhit1 + dZY;
464 Float_t xhit2 = xhit1 + dXY;
465
a3dfe79c 466 Int_t iwht1 = (Int_t) (xhit1 / kCelWr); // wire (x) coordinate "in"
467 Int_t iwht2 = (Int_t) (xhit2 / kCelWr); // wire (x) coordinate "out"
fa412d9b 468
469 Int_t nIter;
470 Float_t zxe[3][5];
471 if (iwht1==iwht2) { // incline 1-wire hit
472 nIter = 2;
473 zxe[0][0] = (zhit1 + zhit2 - dZY*0.57735) / 2;
a3dfe79c 474 zxe[1][0] = (iwht1 + 0.5) * kCelWr;
475 zxe[2][0] = eloss/2;
fa412d9b 476 zxe[0][1] = (zhit1 + zhit2 + dZY*0.57735) / 2;
a3dfe79c 477 zxe[1][1] = (iwht1 + 0.5) * kCelWr;
478 zxe[2][1] = eloss/2;
fa412d9b 479 }
480 else if (TMath::Abs(iwht1-iwht2) != 1) { // incline 3-wire hit
481 nIter = 3;
482 Int_t iwht3 = (iwht1 + iwht2) / 2;
a3dfe79c 483 Float_t xwht1 = (iwht1 + 0.5) * kCelWr; // wire 1
484 Float_t xwht2 = (iwht2 + 0.5) * kCelWr; // wire 2
485 Float_t xwht3 = (iwht3 + 0.5) * kCelWr; // wire 3
fa412d9b 486 Float_t xwr13 = (xwht1 + xwht3) / 2; // center 13
487 Float_t xwr23 = (xwht2 + xwht3) / 2; // center 23
488 Float_t dxw1 = xhit1 - xwr13;
489 Float_t dxw2 = xhit2 - xwr23;
a3dfe79c 490 Float_t egm1 = TMath::Abs(dxw1) / ( TMath::Abs(dxw1) + TMath::Abs(dxw2) + kCelWr );
491 Float_t egm2 = TMath::Abs(dxw2) / ( TMath::Abs(dxw1) + TMath::Abs(dxw2) + kCelWr );
492 Float_t egm3 = kCelWr / ( TMath::Abs(dxw1) + TMath::Abs(dxw2) + kCelWr );
fa412d9b 493 zxe[0][0] = (dXY*(xwr13-xwht1)/dXY + zhit1 + zhit1) / 2;
494 zxe[1][0] = xwht1;
a3dfe79c 495 zxe[2][0] = eloss * egm1;
fa412d9b 496 zxe[0][1] = (dXY*(xwr23-xwht1)/dXY + zhit1 + zhit2) / 2;
497 zxe[1][1] = xwht2;
a3dfe79c 498 zxe[2][1] = eloss * egm2;
fa412d9b 499 zxe[0][2] = dXY*(xwht3-xwht1)/dXY + zhit1;
500 zxe[1][2] = xwht3;
a3dfe79c 501 zxe[2][2] = eloss * egm3;
fa412d9b 502 }
503 else { // incline 2-wire hit
504 nIter = 2;
a3dfe79c 505 Float_t xwht1 = (iwht1 + 0.5) * kCelWr;
506 Float_t xwht2 = (iwht2 + 0.5) * kCelWr;
fa412d9b 507 Float_t xwr12 = (xwht1 + xwht2) / 2;
508 Float_t dxw1 = xhit1 - xwr12;
509 Float_t dxw2 = xhit2 - xwr12;
510 Float_t egm1 = TMath::Abs(dxw1) / ( TMath::Abs(dxw1) + TMath::Abs(dxw2) );
511 Float_t egm2 = TMath::Abs(dxw2) / ( TMath::Abs(dxw1) + TMath::Abs(dxw2) );
512 zxe[0][0] = (zhit1 + zhit2 - dZY*egm1) / 2;
513 zxe[1][0] = xwht1;
a3dfe79c 514 zxe[2][0] = eloss * egm1;
fa412d9b 515 zxe[0][1] = (zhit1 + zhit2 + dZY*egm2) / 2;
516 zxe[1][1] = xwht2;
a3dfe79c 517 zxe[2][1] = eloss * egm2;
fa412d9b 518 }
bea63bea 519
fa412d9b 520 // Finite size of ionization region
521
fa7cce36 522 Int_t nCellZ = GetGeometry()->GetNumberOfCPVPadsZ();
523 Int_t nCellX = GetGeometry()->GetNumberOfCPVPadsPhi();
a3dfe79c 524 Int_t nz3 = (kNgamz+1)/2;
525 Int_t nx3 = (kNgamx+1)/2;
526 cpvDigits->Expand(nIter*kNgamx*kNgamz);
29b077b5 527 TClonesArray &ldigits = *(static_cast<TClonesArray *>(cpvDigits));
fa412d9b 528
529 for (Int_t iter=0; iter<nIter; iter++) {
530
531 Float_t zhit = zxe[0][iter];
532 Float_t xhit = zxe[1][iter];
533 Float_t qhit = zxe[2][iter];
fa7cce36 534 Float_t zcell = zhit / GetGeometry()->GetPadSizeZ();
535 Float_t xcell = xhit / GetGeometry()->GetPadSizePhi();
fa412d9b 536 if ( zcell<=0 || xcell<=0 ||
537 zcell>=nCellZ || xcell>=nCellX) return;
538 Int_t izcell = (Int_t) zcell;
539 Int_t ixcell = (Int_t) xcell;
540 Float_t zc = zcell - izcell - 0.5;
541 Float_t xc = xcell - ixcell - 0.5;
a3dfe79c 542 for (Int_t iz=1; iz<=kNgamz; iz++) {
fa412d9b 543 Int_t kzg = izcell + iz - nz3;
544 if (kzg<=0 || kzg>nCellZ) continue;
545 Float_t zg = (Float_t)(iz-nz3) - zc;
a3dfe79c 546 for (Int_t ix=1; ix<=kNgamx; ix++) {
fa412d9b 547 Int_t kxg = ixcell + ix - nx3;
548 if (kxg<=0 || kxg>nCellX) continue;
549 Float_t xg = (Float_t)(ix-nx3) - xc;
550
551 // Now calculate pad response
552 Float_t qpad = CPVPadResponseFunction(qhit,zg,xg);
a3dfe79c 553 qpad += kNoise*rnor2;
fa412d9b 554 if (qpad<0) continue;
555
556 // Fill the array with pad response ID and amplitude
3d402178 557 new(ldigits[cpvDigits->GetEntriesFast()]) AliPHOSCPVDigit(kxg,kzg,qpad);
fa412d9b 558 }
fa412d9b 559 }
fa412d9b 560 }
561}
562
563//____________________________________________________________________________
564Float_t AliPHOSv1::CPVPadResponseFunction(Float_t qhit, Float_t zhit, Float_t xhit) {
565 // ------------------------------------------------------------------------
566 // Calculate the amplitude in one CPV pad using the
567 // cumulative pad response function
568 // Author: Yuri Kharlov (after Serguei Sadovski)
569 // 3 October 2000
570 // ------------------------------------------------------------------------
571
fa7cce36 572 Double_t dz = GetGeometry()->GetPadSizeZ() / 2;
573 Double_t dx = GetGeometry()->GetPadSizePhi() / 2;
574 Double_t z = zhit * GetGeometry()->GetPadSizeZ();
575 Double_t x = xhit * GetGeometry()->GetPadSizePhi();
fa412d9b 576 Double_t amplitude = qhit *
577 (CPVCumulPadResponse(z+dz,x+dx) - CPVCumulPadResponse(z+dz,x-dx) -
578 CPVCumulPadResponse(z-dz,x+dx) + CPVCumulPadResponse(z-dz,x-dx));
579 return (Float_t)amplitude;
7587f5a5 580}
581
fa412d9b 582//____________________________________________________________________________
583Double_t AliPHOSv1::CPVCumulPadResponse(Double_t x, Double_t y) {
584 // ------------------------------------------------------------------------
585 // Cumulative pad response function
586 // It includes several terms from the CF decomposition in electrostatics
587 // Note: this cumulative function is wrong since omits some terms
588 // but the cell amplitude obtained with it is correct because
589 // these omitting terms cancel
590 // Author: Yuri Kharlov (after Serguei Sadovski)
591 // 3 October 2000
592 // ------------------------------------------------------------------------
593
a3dfe79c 594 const Double_t kA=1.0;
595 const Double_t kB=0.7;
fa412d9b 596
597 Double_t r2 = x*x + y*y;
598 Double_t xy = x*y;
599 Double_t cumulPRF = 0;
600 for (Int_t i=0; i<=4; i++) {
a3dfe79c 601 Double_t b1 = (2*i + 1) * kB;
fa412d9b 602 cumulPRF += TMath::Power(-1,i) * TMath::ATan( xy / (b1*TMath::Sqrt(b1*b1 + r2)) );
603 }
a3dfe79c 604 cumulPRF *= kA/(2*TMath::Pi());
fa412d9b 605 return cumulPRF;
606}
7eb9d12d 607