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