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