2 questions to experts: why RemoveDeadPixels should be called before FrompListToDigits ?
7 /**************************************************************************
8 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
10 * Author: The ALICE Off-line Project. *
11 * Contributors are mentioned in the code where appropriate. *
13 * Permission to use, copy, modify and distribute this software and its *
14 * documentation strictly for non-commercial purposes is hereby granted *
15 * without fee, provided that the above copyright notice appears in all *
16 * copies and that both the copyright notice and this permission notice *
17 * appear in the supporting documentation. The authors make no claims *
18 * about the suitability of this software for any purpose. It is *
19 * provided "as is" without express or implied warranty. *
20 **************************************************************************/
22 #include <TGeoGlobalMagField.h>
26 #include "AliITSUDigitPix.h"
27 #include "AliITSUHit.h"
28 #include "AliITSUModule.h"
29 #include "AliITSUSensMap.h"
30 #include "AliITSUCalibrationPix.h"
31 #include "AliITSUSegmentationPix.h"
32 #include "AliITSUSimulationPix.h"
36 #include "AliMathBase.h"
37 #include "AliITSUSimuParam.h"
38 #include "AliITSUSDigit.h"
43 ClassImp(AliITSUSimulationPix)
44 ////////////////////////////////////////////////////////////////////////
46 // Modified by D. Elia, G.E. Bruno, H. Tydesjo
47 // Fast diffusion code by Bjorn S. Nilsen
49 // October 2007: GetCalibrationObjects() removed
52 // Written by Boris Batyunya
55 // Adapted for pixels of ITS upgrade July 2012, ruben.shahoyan@cern.ch
57 // AliITSUSimulationPix is to do the simulation of pixels
59 ////////////////////////////////////////////////////////////////////////
61 //______________________________________________________________________
62 AliITSUSimulationPix::AliITSUSimulationPix()
66 ,fStrobePhase(-12.5e-9)
68 // Default constructor.
71 //______________________________________________________________________
72 AliITSUSimulationPix::AliITSUSimulationPix(AliITSUSimuParam* sim,AliITSUSensMap* map)
73 :AliITSUSimulation(sim,map)
77 ,fStrobePhase(-12.5e-9)
79 // standard constructor
83 //______________________________________________________________________
84 AliITSUSimulationPix::AliITSUSimulationPix(const AliITSUSimulationPix &s)
86 ,fTanLorAng(s.fTanLorAng)
88 ,fStrobeLenght(s.fStrobeLenght)
89 ,fStrobePhase(s.fStrobePhase)
95 //______________________________________________________________________
96 AliITSUSimulationPix::~AliITSUSimulationPix()
99 // only the sens map is owned and it is deleted by ~AliITSUSimulation
102 //______________________________________________________________________
103 AliITSUSimulationPix& AliITSUSimulationPix::operator=(const AliITSUSimulationPix &s)
105 // Assignment operator
106 if (&s == this) return *this;
107 AliITSUSimulation::operator=(s);
109 fStrobeLenght = s.fStrobeLenght;
110 fStrobePhase = s.fStrobePhase;
114 //______________________________________________________________________
115 void AliITSUSimulationPix::Init()
118 if (fSimuParam->GetPixLorentzDrift()) SetTanLorAngle(fSimuParam->GetPixLorentzHoleWeight());
121 //______________________________________________________________________
122 Bool_t AliITSUSimulationPix::SetTanLorAngle(Double_t weightHole)
124 // This function set the Tangent of the Lorentz angle.
125 // A weighted average is used for electrons and holes
126 // Input: Double_t weightHole: wheight for hole: it should be in the range [0,1]
127 // output: Bool_t : kTRUE in case of success
131 AliWarning("You have asked for negative Hole weight");
132 AliWarning("I'm going to use only electrons");
136 AliWarning("You have asked for weight > 1");
137 AliWarning("I'm going to use only holes");
139 Double_t weightEle=1.-weightHole;
140 AliMagF* fld = (AliMagF*)TGeoGlobalMagField::Instance()->GetField();
141 if (!fld) AliFatal("The field is not initialized");
142 Double_t bz = fld->SolenoidField();
143 fTanLorAng = TMath::Tan(weightHole*fSimuParam->LorentzAngleHole(bz) +
144 weightEle*fSimuParam->LorentzAngleElectron(bz));
148 //_____________________________________________________________________
149 void AliITSUSimulationPix::SDigitiseModule(AliITSUModule *mod, Int_t /*mask*/,Int_t event, AliITSsegmentation* seg)
151 // This function begins the work of creating S-Digits.
152 if (!(mod->GetNHits())) {
153 AliDebug(1,Form("In event %d module %d there are %d hits returning.",
154 event, mod->GetIndex(),mod->GetNHits()));
158 if (fStrobe) if (event != fEvent) GenerateStrobePhase();
159 InitSimulationModule(mod->GetIndex(), event, seg );
160 // Hits2SDigits(mod);
161 Hits2SDigitsFast(mod);
162 if (fSimuParam->GetPixAddNoisyFlag()) AddNoisyPixels();
163 if (fSimuParam->GetPixRemoveDeadFlag()) RemoveDeadPixels();
168 //______________________________________________________________________
169 void AliITSUSimulationPix::WriteSDigits()
171 // This function adds each S-Digit to pList
172 static AliITSU *aliITS = (AliITSU*)gAlice->GetModule("ITS");
173 int nsd = fSensMap->GetEntries();
174 for (int i=0;i<nsd;i++) {
175 AliITSUSDigit* sd = (AliITSUSDigit*)fSensMap->At(i); // ordered in index
176 if (!sd->GetSumSignal()>0 || fSensMap->IsDisabled(sd)) continue;
177 aliITS->AddSumDigit(*sd);
182 //______________________________________________________________________
183 void AliITSUSimulationPix::FinishSDigitiseModule()
185 // This function calls SDigitsToDigits which creates Digits from SDigits
191 //______________________________________________________________________
192 void AliITSUSimulationPix::DigitiseModule(AliITSUModule *mod,Int_t /*mask*/, Int_t event, AliITSsegmentation* seg)
194 // This function creates Digits straight from the hits and then adds
195 // electronic noise to the digits before adding them to pList
196 // Each of the input variables is passed along to Hits2SDigits
198 if (fStrobe) if (event != fEvent) GenerateStrobePhase();
199 InitSimulationModule( mod->GetIndex(), event, seg );
200 // Hits2SDigits(mod);
201 Hits2SDigitsFast(mod);
203 if (fSimuParam->GetPixAddNoisyFlag()) AddNoisyPixels();
204 if (fSimuParam->GetPixRemoveDeadFlag()) RemoveDeadPixels();
209 //______________________________________________________________________
210 void AliITSUSimulationPix::Hits2SDigits(AliITSUModule *mod)
212 // Does the charge distributions using Gaussian diffusion charge charing.
213 const Double_t kBunchLenght = 25e-9; // LHC clock
214 Int_t nhits = mod->GetNHits();
219 Float_t x,y,z; // keep coordinates float (required by AliSegmentation)
220 Double_t x0=0.0,x1=0.0,y0=0.0,y1=0.0,z0=0.0,z1=0.0,de=0.0,ld=0.0;
221 Double_t t,tp,st,dt=0.2,el,sig,sigx,sigz,fda;
222 Double_t thick = 0.5*fSeg->Dy(); // Half Thickness
223 fSimuParam->GetPixSigmaDiffusionAsymmetry(fda);
225 for (h=0;h<nhits;h++) {
227 ((mod->GetHit(h)->GetTOF()<fStrobePhase) ||
228 (mod->GetHit(h)->GetTOF()>(fStrobePhase+fStrobeLenght*kBunchLenght)))
231 if (!mod->LineSegmentL(h,x0,x1,y0,y1,z0,z1,de,idtrack)) continue;
232 st = TMath::Sqrt(x1*x1+y1*y1+z1*z1);
234 st = (Double_t)((Int_t)(st*1e4)); // number of microns
235 if (st<=1.0) st = 1.0;
236 dt = 1.0/st; // RS TODO: do we need 1 micron steps?
237 for (t=0.0;t<1.0;t+=dt) { // Integrate over t
242 if (!(fSeg->LocalToDet(x,z,ix,iz))) continue; // outside
243 el = dt * de / fSimuParam->GetGeVToCharge();
245 sig = fSimuParam->SigmaDiffusion1D(TMath::Abs(thick + y));
248 if (fSimuParam->GetPixLorentzDrift()) ld=(y+thick)*fTanLorAng;
249 SpreadChargeAsym(x,z,ix,iz,el,sigx,sigz,ld,idtrack,h);
251 } else { // st == 0.0 deposit it at this point
255 if (!(fSeg->LocalToDet(x,z,ix,iz))) continue; // outside
256 el = de / fSimuParam->GetGeVToCharge();
257 sig = fSimuParam->SigmaDiffusion1D(TMath::Abs(thick + y));
260 if (fSimuParam->GetPixLorentzDrift()) ld=(y+thick)*fTanLorAng;
261 SpreadChargeAsym(x,z,ix,iz,el,sigx,sigz,ld,idtrack,h);
263 } // Loop over all hits h
266 int nd = fSensMap->GetEntriesUnsorted(); // use unsorted access when possible, since it is faster
267 AliITSUSDigit* dg = 0;
268 switch (fSimuParam->GetPixCouplingOption()) {
269 case AliITSUSimuParam::kNewCouplingPix :
271 dg = (AliITSUSDigit*)fSensMap->AtUnsorted(i);
272 if (fSensMap->IsDisabled(dg)) continue;
273 SetCoupling(dg,idtrack,h);
276 case AliITSUSimuParam::kOldCouplingPix:
278 dg = (AliITSUSDigit*)fSensMap->AtUnsorted(i);
279 if (fSensMap->IsDisabled(dg)) continue;
280 SetCouplingOld(dg,idtrack,h);
287 if (GetDebug(2)) AliInfo(Form("Finished fCoupling=%d",fSimuParam->GetPixCouplingOption()));
290 //______________________________________________________________________
291 void AliITSUSimulationPix::Hits2SDigitsFast(AliITSUModule *mod)
293 // Does the charge distributions using Gaussian diffusion charge charing. // Inputs:
294 // AliITSUModule *mod Pointer to this module
300 const Double_t kti[kn10]={7.443716945e-3,2.166976971e-1,3.397047841e-1,
301 4.325316833e-1,4.869532643e-1,5.130467358e-1,
302 5.674683167e-1,6.602952159e-1,7.833023029e-1,
304 const Double_t kwi[kn10]={1.477621124e-1,1.346333597e-1,1.095431813e-1,
305 7.472567455e-2,3.333567215e-2,3.333567215e-2,
306 7.472567455e-2,1.095431813e-1,1.346333597e-1,
308 const Double_t kBunchLenght = 25e-9; // LHC clock
309 TObjArray *hits = mod->GetHits();
310 Int_t nhits = hits->GetEntriesFast();
311 if (nhits<=0) return;
315 Float_t x,y,z; // keep coordinates float (required by AliSegmentation)
316 Double_t x0=0.0,x1=0.0,y0=0.0,y1=0.0,z0=0.0,z1=0.0;
317 Double_t t,st,el,sig,sigx,sigz,fda,de=0.0,ld=0.0;
318 Double_t thick = 0.5*fSeg->Dy(); // Half thickness
319 fSimuParam->GetPixSigmaDiffusionAsymmetry(fda);
321 for (h=0;h<nhits;h++) {
322 // Check if the hit is inside readout window
324 ((mod->GetHit(h)->GetTOF()<fStrobePhase) ||
325 (mod->GetHit(h)->GetTOF()>(fStrobePhase+fStrobeLenght*kBunchLenght)))
328 if (!mod->LineSegmentL(h,x0,x1,y0,y1,z0,z1,de,idtrack)) continue;
329 st = TMath::Sqrt(x1*x1+y1*y1+z1*z1);
331 for (i=0;i<kn10;i++) { // Integrate over t
336 if (!(fSeg->LocalToDet(x,z,ix,iz))) continue; // outside
337 el = kwi[i]*de/fSimuParam->GetGeVToCharge();
338 sig = fSimuParam->SigmaDiffusion1D(TMath::Abs(thick + y));
341 if (fSimuParam->GetPixLorentzDrift()) ld=(y+thick)*fTanLorAng;
342 SpreadChargeAsym(x,z,ix,iz,el,sigx,sigz,ld,idtrack,h);
343 } // end for i // End Integrate over t
344 else { // st == 0.0 deposit it at this point
348 if (!(fSeg->LocalToDet(x,z,ix,iz))) continue; // outside
349 el = de / fSimuParam->GetGeVToCharge();
350 sig = fSimuParam->SigmaDiffusion1D(TMath::Abs(thick + y));
353 if (fSimuParam->GetPixLorentzDrift()) ld=(y+thick)*fTanLorAng;
354 SpreadChargeAsym(x,z,ix,iz,el,sigx,sigz,ld,idtrack,h);
357 } // Loop over all hits h
360 int nd = fSensMap->GetEntriesUnsorted(); // use unsorted access when possible, since it is faster
361 AliITSUSDigit* dg = 0;
362 switch (fSimuParam->GetPixCouplingOption()) {
363 case AliITSUSimuParam::kNewCouplingPix :
365 dg = (AliITSUSDigit*)fSensMap->AtUnsorted(i);
366 if (fSensMap->IsDisabled(dg)) continue;
367 SetCoupling(dg,idtrack,h);
369 case AliITSUSimuParam::kOldCouplingPix:
371 dg = (AliITSUSDigit*)fSensMap->AtUnsorted(i);
372 if (fSensMap->IsDisabled(dg)) continue;
373 SetCouplingOld(dg,idtrack,h);
379 if (GetDebug(2)) AliInfo(Form("Finished fCoupling=%d",fSimuParam->GetPixCouplingOption()));
382 //______________________________________________________________________
383 void AliITSUSimulationPix::SpreadCharge(Double_t x0,Double_t z0,
385 Double_t el,Double_t sig,Double_t ld,
388 // Spreads the charge over neighboring cells. Assume charge is distributed
389 // as charge(x,z) = (el/2*pi*sig*sig)*exp(-arg)
390 // arg=((x-x0)*(x-x0)/2*sig*sig)+((z-z0*z-z0)/2*sig*sig)
391 // if fSimuParam->GetPixLorentzDrift()=kTRUE, then x0=x0+ld (Lorentz drift taken into account)
392 // Defined this way, the integral over all x and z is el.
394 // Double_t x0 x position of point where charge is liberated
395 // Double_t z0 z position of point where charge is liberated
396 // Int_t ix0 row of cell corresponding to point x0
397 // Int_t iz0 columb of cell corresponding to point z0
398 // Double_t el number of electrons liberated in this step
399 // Double_t sig Sigma difusion for this step (y0 dependent)
400 // Double_t ld lorentz drift in x for this step (y0 dependent)
401 // Int_t t track number
402 // Int_t ti hit track index number
403 // Int_t hi hit "hit" index number
408 const Int_t knx = 3,knz = 2;
409 const Double_t kRoot2 = 1.414213562; // Sqrt(2).
410 Int_t ix,iz,ixs,ixe,izs,ize;
411 Float_t x,z; // keep coordinates float (required by AliSegmentation)
412 Double_t s,sp,x1,x2,z1,z2;
414 if (GetDebug(2)) AliInfo(Form("(x0=%e,z0=%e,ix0=%d,iz0=%d,el=%e,sig=%e,t=%d,i=%d)",x0,z0,ix0,iz0,el,sig,t,hi));
415 if (sig<=0.0) { // if sig<=0 No diffusion to simulate.
416 UpdateMapSignal(iz0,ix0,t,hi,el);
419 sp = 1.0/(sig*kRoot2);
420 ixs = TMath::Max(-knx+ix0,0);
421 ixe = TMath::Min(knx+ix0,fSeg->Npx()-1);
422 izs = TMath::Max(-knz+iz0,0);
423 ize = TMath::Min(knz+iz0,fSeg->Npz()-1);
424 for (ix=ixs;ix<=ixe;ix++)
425 for (iz=izs;iz<=ize;iz++) {
426 fSeg->DetToLocal(ix,iz,x,z); // pixel center
427 double dxi = 0.5*fSeg->Dpx(ix);
428 double dzi = 0.5*fSeg->Dpz(iz);
431 x2 = x1 + dxi; // Upper
433 z2 = z1 + dzi; // Upper
435 x1 -= x0+ld; // Distance from where track traveled (taking into account the Lorentz drift)
436 x2 -= x0+ld; // Distance from where track traveled (taking into account the Lorentz drift)
437 z1 -= z0; // Distance from where track traveled
438 z2 -= z0; // Distance from where track traveled
439 s = el*0.25; // Correction based on definision of Erfc
440 s *= AliMathBase::ErfcFast(sp*x1) - AliMathBase::ErfcFast(sp*x2);
441 s *= AliMathBase::ErfcFast(sp*z1) - AliMathBase::ErfcFast(sp*z2);
442 if (s>fSimuParam->GetPixMinElToAdd()) UpdateMapSignal(iz,ix,t,hi,s);
447 //______________________________________________________________________
448 void AliITSUSimulationPix::SpreadChargeAsym(Double_t x0,Double_t z0,
450 Double_t el,Double_t sigx,Double_t sigz,
451 Double_t ld,Int_t t,Int_t hi)
453 // Spreads the charge over neighboring cells. Assume charge is distributed
454 // as charge(x,z) = (el/2*pi*sigx*sigz)*exp(-arg)
455 // arg=((x-x0)*(x-x0)/2*sigx*sigx)+((z-z0*z-z0)/2*sigz*sigz)
456 // if fSimuParam->GetPixLorentzDrift()=kTRUE, then x0=x0+ld (Lorentz drift taken into account)
457 // Defined this way, the integral over all x and z is el.
459 // Double_t x0 x position of point where charge is liberated
460 // Double_t z0 z position of point where charge is liberated
461 // Int_t ix0 row of cell corresponding to point x0
462 // Int_t iz0 columb of cell corresponding to point z0
463 // Double_t el number of electrons liberated in this step
464 // Double_t sigx Sigma difusion along x for this step (y0 dependent)
465 // Double_t sigz Sigma difusion along z for this step (z0 dependent)
466 // Double_t ld lorentz drift in x for this stip (y0 dependent)
467 // Int_t t track number
468 // Int_t ti hit track index number
469 // Int_t hi hit "hit" index number
474 const Int_t knx = 3,knz = 3; // RS: TO TUNE
475 const Double_t kRoot2 = 1.414213562; // Sqrt(2).
476 Int_t ix,iz,ixs,ixe,izs,ize;
477 Float_t x,z; // keep coordinates float (required by AliSegmentation)
478 Double_t s,spx,spz,x1,x2,z1,z2;
480 if (GetDebug(2)) AliInfo(Form("(x0=%e,z0=%e,ix0=%d,iz0=%d,el=%e,sigx=%e, sigz=%e, t=%d,i=%d,ld=%e)",
481 x0,z0,ix0,iz0,el,sigx,sigz,t,hi,ld));
482 if (sigx<=0.0 || sigz<=0.0) { // if sig<=0 No diffusion to simulate.
483 UpdateMapSignal(iz0,ix0,t,hi,el);
486 spx = 1.0/(sigx*kRoot2);
487 spz = 1.0/(sigz*kRoot2);
488 ixs = TMath::Max(-knx+ix0,0);
489 ixe = TMath::Min(knx+ix0,fSeg->Npx()-1);
490 izs = TMath::Max(-knz+iz0,0);
491 ize = TMath::Min(knz+iz0,fSeg->Npz()-1);
492 for (ix=ixs;ix<=ixe;ix++)
493 for (iz=izs;iz<=ize;iz++) {
494 fSeg->DetToLocal(ix,iz,x,z); // pixel center
495 double dxi = 0.5*fSeg->Dpx(ix);
496 double dzi = 0.5*fSeg->Dpz(iz);
499 x2 = x1 + dxi; // Upper
501 z2 = z1 + dzi; // Upper
503 x1 -= x0+ld; // Distance from where track traveled (taking into account the Lorentz drift)
504 x2 -= x0+ld; // Distance from where track traveled (taking into account the Lorentz drift)
505 z1 -= z0; // Distance from where track traveled
506 z2 -= z0; // Distance from where track traveled
507 s = el*0.25; // Correction based on definision of Erfc
508 s *= AliMathBase::ErfcFast(spx*x1) - AliMathBase::ErfcFast(spx*x2);
509 s *= AliMathBase::ErfcFast(spz*z1) - AliMathBase::ErfcFast(spz*z2);
510 if (s>fSimuParam->GetPixMinElToAdd()) UpdateMapSignal(iz,ix,t,hi,s);
515 //______________________________________________________________________
516 void AliITSUSimulationPix::RemoveDeadPixels()
518 // Removes dead pixels on each module (ladder)
519 // This should be called before going from sdigits to digits (FrompListToDigits)
521 AliITSUCalibrationPix* calObj = (AliITSUCalibrationPix*) GetCalibDead();
524 if (calObj->IsBad()) {ClearMap(); return;} // whole module is masked
526 // remove single bad pixels one by one
527 int nsingle = calObj->GetNrBadSingle();
529 for (int i=nsingle;i--;) {
530 calObj->GetBadPixelSingle(i,row,col);
531 fSensMap->DeleteItem(col,row);
533 int nsd = fSensMap->GetEntriesUnsorted();
534 for (int isd=nsd;isd--;) {
535 AliITSUSDigit* sd = (AliITSUSDigit*)fSensMap->AtUnsorted(isd);
536 if (fSensMap->IsDisabled(sd)) continue;
537 fSensMap->GetMapIndex(sd->GetUniqueID(),col,row);
538 int chip = fSeg->GetChipFromChannel(0,col);
539 // if (calObj->IsChipMarkedBad(chip)) fSensMap->Disable(sd); // this will simple mark the hit as bad
540 if (calObj->IsChipMarkedBad(chip)) fSensMap->DeleteItem(sd); // this will suppress hit in the sorted list
545 //______________________________________________________________________
546 void AliITSUSimulationPix::AddNoisyPixels()
548 // Adds noisy pixels on each module (ladder)
549 // This should be called before going from sdigits to digits (FrompListToDigits)
550 AliITSUCalibrationPix* calObj = (AliITSUCalibrationPix*) GetCalibNoisy();
552 for (Int_t i=calObj->GetNrBad(); i--;) UpdateMapNoise(calObj->GetBadColAt(i), calObj->GetBadRowAt(i),
553 10*fSimuParam->GetPixThreshold(fModule));
557 //______________________________________________________________________
558 void AliITSUSimulationPix::FrompListToDigits()
560 // add noise and electronics, perform the zero suppression and add the
562 static AliITSU *aliITS = (AliITSU*)gAlice->GetModule("ITS");
565 const Int_t knmaxtrk=AliITSdigit::GetNTracks();
566 static AliITSUDigitPix dig;
568 // 1) for every pixel w/o hit we have to generate a noise and activate the pixel if the noise exceeds the threshold.
569 // 2) for every pixel with hit we should add random noise and check if the total signal exceeds the threshold
570 // With many channels this will be too time consuming, hence I do the following
571 // 1) Precalculate the probability that the nois alone will exceed the threshold.
572 // 2) Chose randomly empty pixels according to this probability and apply the noise above threshold.
573 // 3) For pixels having a hits apply the usual noise and compare with threshold
575 // RS may use for ordered random sample generation dl.acm.org/ft_gateway.cfm?id=356313&type=pdf
577 int maxInd = fSensMap->GetMaxIndex();
578 double minProb = 0.1/maxInd;
580 int nsd = fSensMap->GetEntries();
581 Int_t prevID=0,curID=0;
582 TArrayI ordSampleInd(100),ordSample(100);
584 double probNoisy,noiseSig,noiseMean,thresh = fSimuParam->GetPixThreshold(fModule);
585 fSimuParam->GetPixNoise(fModule, noiseSig, noiseMean);
586 probNoisy = AliITSUSimuParam::CalcProbNoiseOverThreshold(noiseMean,noiseSig,thresh); // prob. to have noise above threshold
588 for (int i=0;i<nsd;i++) {
589 AliITSUSDigit* sd = (AliITSUSDigit*)fSensMap->At(i); // ordered in index
590 if (fSensMap->IsDisabled(sd)) continue;
591 curID = (int)sd->GetUniqueID();
593 if (probNoisy>minProb) { // generate randomly noisy pixels above the threshold, with ID's between previous hit and current
594 CreateNoisyDigits(prevID,curID,probNoisy, noiseSig, noiseMean);
598 if ((sig=sd->GetSumSignal())<=fSimuParam->GetPixThreshold(fModule)) continue;
599 if (TMath::Abs(sig)>2147483647.0) { //RS?
600 //PH 2147483647 is the max. integer
601 //PH This apparently is a problem which needs investigation
602 AliWarning(Form("Too big or too small signal value %f",sig));
604 fSensMap->GetMapIndex(sd->GetUniqueID(),iz,ix);
608 dig.SetSignalPix((Int_t)sig);
609 int ntr = sd->GetNTracks();
610 for (int j=0;j<ntr;j++) {
611 dig.SetTrack(j,sd->GetTrack(j));
612 dig.SetHit(j,sd->GetHit(j));
614 for (int j=ntr;j<knmaxtrk;j++) {
618 aliITS->AddSimDigit(AliITSUGeomTGeo::kDetTypePix, &dig);
620 // if needed, add noisy pixels with id from last real hit to maxID
621 if (probNoisy>minProb) CreateNoisyDigits(prevID,maxInd,probNoisy, noiseSig, noiseMean);
625 //______________________________________________________________________
626 Int_t AliITSUSimulationPix::CreateNoisyDigits(Int_t minID,Int_t maxID,double probNoisy, double noise, double base)
628 // create random noisy digits above threshold within id range [minID,maxID[
629 // see FrompListToDigits for details
631 static AliITSU *aliITS = (AliITSU*)gAlice->GetModule("ITS");
633 static AliITSUDigitPix dig;
634 static TArrayI ordSampleInd(100),ordSample(100); //RS!!! static is not thread-safe!!!
635 const Int_t knmaxtrk=AliITSdigit::GetNTracks();
638 int npix = maxID-minID;
639 if (npix<1 || (ncand=gRandom->Poisson(npix*probNoisy))<1) return ncand; // decide how many noisy pixels will be added
640 ncand = GenOrderedSample(npix,ncand,ordSample,ordSampleInd);
641 int* ordV = ordSample.GetArray();
642 int* ordI = ordSampleInd.GetArray();
643 for (int j=0;j<ncand;j++) {
644 fSensMap->GetMapIndex((UInt_t)ordV[ordI[j]],iz,ix); // create noisy digit
648 dig.SetSignalPix((Int_t)AliITSUSimuParam::GenerateNoiseQFunction(probNoisy,base,noise));
649 for (int k=knmaxtrk;k--;) {
653 aliITS->AddSimDigit(AliITSUGeomTGeo::kDetTypePix,&dig);
654 if (GetDebug(2)) AliInfo(Form("Add noisy pixel %d(%d/%d) Noise=%d",ordV[ordI[j]],iz,ix,dig.GetSignalPix()));
659 //______________________________________________________________________
660 void AliITSUSimulationPix::SetCoupling(AliITSUSDigit* old, Int_t ntrack, Int_t idhit)
662 // Take into account the coupling between adiacent pixels.
663 // The parameters probcol and probrow are the probability of the
664 // signal in one pixel shared in the two adjacent pixels along
665 // the column and row direction, respectively.
666 // Note pList is goten via GetMap() and module is not need any more.
667 // Otherwise it is identical to that coded by Tiziano Virgili (BSN).
670 <img src="picts/ITS/barimodel_3.gif">
673 <font size=+2 color=red>
674 <a href="mailto:tiziano.virgili@cern.ch"></a>.
680 // old existing AliITSUSDigit
681 // Int_t ntrack track incex number
682 // Int_t idhit hit index number
684 Double_t pulse1,pulse2;
685 Double_t couplR=0.0,couplC=0.0;
688 fSensMap->GetMapIndex(old->GetUniqueID(),col,row);
689 fSimuParam->GetPixCouplingParam(couplC,couplR);
690 if (GetDebug(2)) AliInfo(Form("(col=%d,row=%d,ntrack=%d,idhit=%d) couplC=%e couplR=%e",
691 col,row,ntrack,idhit,couplC,couplR));
692 pulse2 = pulse1 = old->GetSignal();
693 if (pulse1<fSimuParam->GetPixMinElToAdd()) return; // too small signal
694 for (Int_t isign=-1;isign<=1;isign+=2) {
696 // loop in col direction
697 int j1 = int(col) + isign;
698 xr = gRandom->Rndm();
699 if ( !((j1<0) || (j1>fSeg->Npz()-1) || (xr>couplC)) ) UpdateMapSignal(UInt_t(j1),row,ntrack,idhit,pulse1);
701 // loop in row direction
702 int j2 = int(row) + isign;
703 xr = gRandom->Rndm();
704 if ( !((j2<0) || (j2>fSeg->Npx()-1) || (xr>couplR)) ) UpdateMapSignal(col,UInt_t(j2),ntrack,idhit,pulse2);
709 //______________________________________________________________________
710 void AliITSUSimulationPix::SetCouplingOld(AliITSUSDigit* old, Int_t ntrack,Int_t idhit)
712 // Take into account the coupling between adiacent pixels.
713 // The parameters probcol and probrow are the fractions of the
714 // signal in one pixel shared in the two adjacent pixels along
715 // the column and row direction, respectively.
718 <img src="picts/ITS/barimodel_3.gif">
721 <font size=+2 color=red>
722 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
728 // old existing AliITSUSDigit
729 // ntrack track incex number
730 // idhit hit index number
731 // module module number
734 Double_t pulse1,pulse2;
735 Double_t couplR=0.0,couplC=0.0;
737 fSensMap->GetMapIndex(old->GetUniqueID(),col,row);
738 fSimuParam->GetPixCouplingParam(couplC,couplR);
739 if (GetDebug(3)) AliInfo(Form("(col=%d,row=%d,ntrack=%d,idhit=%d) couplC=%e couplR=%e",
740 col,row,ntrack,idhit,couplC,couplR));
742 if (old->GetSignal()<fSimuParam->GetPixMinElToAdd()) return; // too small signal
743 for (Int_t isign=-1;isign<=1;isign+=2) {// loop in col direction
744 pulse2 = pulse1 = old->GetSignal();
746 int j1 = int(col)+isign;
748 if ((j1<0)||(j1>fSeg->Npz()-1)||(pulse1<fSimuParam->GetPixThreshold(fModule))) pulse1 = old->GetSignal();
749 else UpdateMapSignal(UInt_t(j1),row,ntrack,idhit,pulse1);
751 // loop in row direction
752 int j2 = int(row) + isign;
754 if ((j2<0)||(j2>(fSeg->Npx()-1))||(pulse2<fSimuParam->GetPixThreshold(fModule))) pulse2 = old->GetSignal();
755 else UpdateMapSignal(col,UInt_t(j2),ntrack,idhit,pulse2);
759 //______________________________________________________________________
760 void AliITSUSimulationPix::GenerateStrobePhase()
762 // Generate randomly the strobe
763 // phase w.r.t to the LHC clock
764 // Done once per event
765 const Double_t kBunchLenght = 25e-9; // LHC clock
766 fStrobePhase = ((Double_t)gRandom->Integer(fStrobeLenght))*kBunchLenght-
767 (Double_t)fStrobeLenght*kBunchLenght+