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"
42 using namespace TMath;
44 ClassImp(AliITSUSimulationPix)
45 ////////////////////////////////////////////////////////////////////////
47 // Modified by D. Elia, G.E. Bruno, H. Tydesjo
48 // Fast diffusion code by Bjorn S. Nilsen
50 // October 2007: GetCalibrationObjects() removed
53 // Written by Boris Batyunya
56 // Adapted for pixels of ITS upgrade July 2012, ruben.shahoyan@cern.ch
58 // AliITSUSimulationPix is to do the simulation of pixels
60 ////////////////////////////////////////////////////////////////////////
62 //______________________________________________________________________
63 AliITSUSimulationPix::AliITSUSimulationPix()
67 ,fStrobePhase(-12.5e-9)
69 // Default constructor.
72 //______________________________________________________________________
73 AliITSUSimulationPix::AliITSUSimulationPix(AliITSUSimuParam* sim,AliITSUSensMap* map)
74 :AliITSUSimulation(sim,map)
78 ,fStrobePhase(-12.5e-9)
80 // standard constructor
84 //______________________________________________________________________
85 AliITSUSimulationPix::AliITSUSimulationPix(const AliITSUSimulationPix &s)
87 ,fTanLorAng(s.fTanLorAng)
89 ,fStrobeLenght(s.fStrobeLenght)
90 ,fStrobePhase(s.fStrobePhase)
96 //______________________________________________________________________
97 AliITSUSimulationPix::~AliITSUSimulationPix()
100 // only the sens map is owned and it is deleted by ~AliITSUSimulation
103 //______________________________________________________________________
104 AliITSUSimulationPix& AliITSUSimulationPix::operator=(const AliITSUSimulationPix &s)
106 // Assignment operator
107 if (&s == this) return *this;
108 AliITSUSimulation::operator=(s);
110 fStrobeLenght = s.fStrobeLenght;
111 fStrobePhase = s.fStrobePhase;
115 //______________________________________________________________________
116 void AliITSUSimulationPix::Init()
119 if (fSimuParam->GetPixLorentzDrift()) SetTanLorAngle(fSimuParam->GetPixLorentzHoleWeight());
122 //______________________________________________________________________
123 Bool_t AliITSUSimulationPix::SetTanLorAngle(Double_t weightHole)
125 // This function set the Tangent of the Lorentz angle.
126 // A weighted average is used for electrons and holes
127 // Input: Double_t weightHole: wheight for hole: it should be in the range [0,1]
128 // output: Bool_t : kTRUE in case of success
132 AliWarning("You have asked for negative Hole weight");
133 AliWarning("I'm going to use only electrons");
137 AliWarning("You have asked for weight > 1");
138 AliWarning("I'm going to use only holes");
140 Double_t weightEle=1.-weightHole;
141 AliMagF* fld = (AliMagF*)TGeoGlobalMagField::Instance()->GetField();
142 if (!fld) AliFatal("The field is not initialized");
143 Double_t bz = fld->SolenoidField();
144 fTanLorAng = Tan(weightHole*fSimuParam->LorentzAngleHole(bz) +
145 weightEle*fSimuParam->LorentzAngleElectron(bz));
149 //_____________________________________________________________________
150 void AliITSUSimulationPix::SDigitiseModule(AliITSUModule *mod, Int_t /*mask*/,Int_t event, AliITSsegmentation* seg)
152 // This function begins the work of creating S-Digits.
153 if (!(mod->GetNHits())) {
154 AliDebug(1,Form("In event %d module %d there are %d hits returning.",
155 event, mod->GetIndex(),mod->GetNHits()));
159 if (fStrobe) if (event != fEvent) GenerateStrobePhase();
160 InitSimulationModule(mod->GetIndex(), event, seg );
161 // Hits2SDigits(mod);
162 Hits2SDigitsFast(mod);
163 if (fSimuParam->GetPixAddNoisyFlag()) AddNoisyPixels();
164 if (fSimuParam->GetPixRemoveDeadFlag()) RemoveDeadPixels();
169 //______________________________________________________________________
170 void AliITSUSimulationPix::WriteSDigits()
172 // This function adds each S-Digit to pList
173 static AliITSU *aliITS = (AliITSU*)gAlice->GetModule("ITS");
174 int nsd = fSensMap->GetEntries();
175 for (int i=0;i<nsd;i++) {
176 AliITSUSDigit* sd = (AliITSUSDigit*)fSensMap->At(i); // ordered in index
177 if (!sd->GetSumSignal()>0 || fSensMap->IsDisabled(sd)) continue;
178 aliITS->AddSumDigit(*sd);
183 //______________________________________________________________________
184 void AliITSUSimulationPix::FinishSDigitiseModule()
186 // This function calls SDigitsToDigits which creates Digits from SDigits
192 //______________________________________________________________________
193 void AliITSUSimulationPix::DigitiseModule(AliITSUModule *mod,Int_t /*mask*/, Int_t event, AliITSsegmentation* seg)
195 // This function creates Digits straight from the hits and then adds
196 // electronic noise to the digits before adding them to pList
197 // Each of the input variables is passed along to Hits2SDigits
199 if (fStrobe) if (event != fEvent) GenerateStrobePhase();
200 InitSimulationModule( mod->GetIndex(), event, seg );
201 // Hits2SDigits(mod);
202 Hits2SDigitsFast(mod);
204 if (fSimuParam->GetPixAddNoisyFlag()) AddNoisyPixels();
205 if (fSimuParam->GetPixRemoveDeadFlag()) RemoveDeadPixels();
210 //______________________________________________________________________
211 void AliITSUSimulationPix::Hits2SDigits(AliITSUModule *mod)
213 // Does the charge distributions using Gaussian diffusion charge charing.
214 const Double_t kBunchLenght = 25e-9; // LHC clock
215 Int_t nhits = mod->GetNHits();
220 Float_t x,y,z; // keep coordinates float (required by AliSegmentation)
221 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;
222 Double_t t,tp,st,dt=0.2,el,sig,sigx,sigz,fda;
223 Double_t thick = 0.5*fSeg->Dy(); // Half Thickness
224 fSimuParam->GetPixSigmaDiffusionAsymmetry(fda);
226 for (h=0;h<nhits;h++) {
228 ((mod->GetHit(h)->GetTOF()<fStrobePhase) ||
229 (mod->GetHit(h)->GetTOF()>(fStrobePhase+fStrobeLenght*kBunchLenght)))
232 if (!mod->LineSegmentL(h,x0,x1,y0,y1,z0,z1,de,idtrack)) continue;
233 st = Sqrt(x1*x1+y1*y1+z1*z1);
235 st = (Double_t)((Int_t)(st*1e4)); // number of microns
236 if (st<=1.0) st = 1.0;
237 dt = 1.0/st; // RS TODO: do we need 1 micron steps?
238 for (t=0.0;t<1.0;t+=dt) { // Integrate over t
243 if (!(fSeg->LocalToDet(x,z,ix,iz))) continue; // outside
244 el = dt * de / fSimuParam->GetGeVToCharge();
246 sig = fSimuParam->SigmaDiffusion1D(Abs(thick + y));
249 if (fSimuParam->GetPixLorentzDrift()) ld=(y+thick)*fTanLorAng;
250 SpreadChargeAsym(x,z,ix,iz,el,sigx,sigz,ld,idtrack,h);
252 } else { // st == 0.0 deposit it at this point
256 if (!(fSeg->LocalToDet(x,z,ix,iz))) continue; // outside
257 el = de / fSimuParam->GetGeVToCharge();
258 sig = fSimuParam->SigmaDiffusion1D(Abs(thick + y));
261 if (fSimuParam->GetPixLorentzDrift()) ld=(y+thick)*fTanLorAng;
262 SpreadChargeAsym(x,z,ix,iz,el,sigx,sigz,ld,idtrack,h);
264 } // Loop over all hits h
267 int nd = fSensMap->GetEntriesUnsorted(); // use unsorted access when possible, since it is faster
268 AliITSUSDigit* dg = 0;
269 switch (fSimuParam->GetPixCouplingOption()) {
270 case AliITSUSimuParam::kNewCouplingPix :
272 dg = (AliITSUSDigit*)fSensMap->AtUnsorted(i);
273 if (fSensMap->IsDisabled(dg)) continue;
274 SetCoupling(dg,idtrack,h);
277 case AliITSUSimuParam::kOldCouplingPix:
279 dg = (AliITSUSDigit*)fSensMap->AtUnsorted(i);
280 if (fSensMap->IsDisabled(dg)) continue;
281 SetCouplingOld(dg,idtrack,h);
288 if (GetDebug(2)) AliInfo(Form("Finished fCoupling=%d",fSimuParam->GetPixCouplingOption()));
291 //______________________________________________________________________
292 void AliITSUSimulationPix::Hits2SDigitsFast(AliITSUModule *mod)
294 // Does the charge distributions using Gaussian diffusion charge charing. // Inputs:
295 // AliITSUModule *mod Pointer to this module
301 // RSTmp this injection points partitioning should be reimplemented
303 const Double_t kti[kn10]={7.443716945e-3,2.166976971e-1,3.397047841e-1,
304 4.325316833e-1,4.869532643e-1,5.130467358e-1,
305 5.674683167e-1,6.602952159e-1,7.833023029e-1,
307 const Double_t kwi[kn10]={1.477621124e-1,1.346333597e-1,1.095431813e-1,
308 7.472567455e-2,3.333567215e-2,3.333567215e-2,
309 7.472567455e-2,1.095431813e-1,1.346333597e-1,
312 const Double_t kBunchLenght = 25e-9; // LHC clock
313 TObjArray *hits = mod->GetHits();
314 Int_t nhits = hits->GetEntriesFast();
315 if (nhits<=0) return;
319 Float_t x,y,z; // keep coordinates float (required by AliSegmentation)
320 Double_t x0=0.0,x1=0.0,y0=0.0,y1=0.0,z0=0.0,z1=0.0;
321 Double_t t,st,el,sig,sigx,sigz,fda,de=0.0,ld=0.0;
322 Double_t thick = 0.5*fSeg->Dy(); // Half thickness
323 Double_t minDim = Min(fSeg->Dpx(1),fSeg->Dpz(1)); // RStmp: smallest pitch
324 fSimuParam->GetPixSigmaDiffusionAsymmetry(fda);
326 for (h=0;h<nhits;h++) {
327 // Check if the hit is inside readout window
329 ((mod->GetHit(h)->GetTOF()<fStrobePhase) ||
330 (mod->GetHit(h)->GetTOF()>(fStrobePhase+fStrobeLenght*kBunchLenght)))
333 if (!mod->LineSegmentL(h,x0,x1,y0,y1,z0,z1,de,idtrack)) continue;
334 st = Sqrt(x1*x1+y1*y1+z1*z1);
336 int np = int(1.5*st/minDim); //RStmp: at the moment neglect kti,kwi: inject the points in such a way that there is ~1.5 point per cell
337 if (np<5) np = 5; //RStmp
338 double dt = 1./(np+1); //RStmp
340 // printf("Dst: %f md:%f np=%d Tr#%d\n",st,minDim,np,idtrack);
342 for (i=0;i<np;i++) { //RStmp Integrate over t
343 // for (i=0;i<kn10;i++) { // Integrate over t
344 t += dt; // RStmp kti[i];
348 if (!(fSeg->LocalToDet(x,z,ix,iz))) continue; // outside
349 // el = kwi[i]*de/fSimuParam->GetGeVToCharge();
350 el = dw*de/fSimuParam->GetGeVToCharge();
351 sig = fSimuParam->SigmaDiffusion1D(Abs(thick + y));
354 if (fSimuParam->GetPixLorentzDrift()) ld=(y+thick)*fTanLorAng;
355 SpreadChargeAsym(x,z,ix,iz,el,sigx,sigz,ld,idtrack,h);
356 } // end for i // End Integrate over t
358 else { // st == 0.0 deposit it at this point
362 if (!(fSeg->LocalToDet(x,z,ix,iz))) continue; // outside
363 el = de / fSimuParam->GetGeVToCharge();
364 sig = fSimuParam->SigmaDiffusion1D(Abs(thick + y));
367 if (fSimuParam->GetPixLorentzDrift()) ld=(y+thick)*fTanLorAng;
368 SpreadChargeAsym(x,z,ix,iz,el,sigx,sigz,ld,idtrack,h);
371 } // Loop over all hits h
374 int nd = fSensMap->GetEntriesUnsorted(); // use unsorted access when possible, since it is faster
375 AliITSUSDigit* dg = 0;
376 switch (fSimuParam->GetPixCouplingOption()) {
377 case AliITSUSimuParam::kNewCouplingPix :
379 dg = (AliITSUSDigit*)fSensMap->AtUnsorted(i);
380 if (fSensMap->IsDisabled(dg)) continue;
381 SetCoupling(dg,idtrack,h);
383 case AliITSUSimuParam::kOldCouplingPix:
385 dg = (AliITSUSDigit*)fSensMap->AtUnsorted(i);
386 if (fSensMap->IsDisabled(dg)) continue;
387 SetCouplingOld(dg,idtrack,h);
393 if (GetDebug(2)) AliInfo(Form("Finished fCoupling=%d",fSimuParam->GetPixCouplingOption()));
396 //______________________________________________________________________
397 void AliITSUSimulationPix::SpreadCharge(Double_t x0,Double_t z0,
399 Double_t el,Double_t sig,Double_t ld,
402 // Spreads the charge over neighboring cells. Assume charge is distributed
403 // as charge(x,z) = (el/2*pi*sig*sig)*exp(-arg)
404 // arg=((x-x0)*(x-x0)/2*sig*sig)+((z-z0*z-z0)/2*sig*sig)
405 // if fSimuParam->GetPixLorentzDrift()=kTRUE, then x0=x0+ld (Lorentz drift taken into account)
406 // Defined this way, the integral over all x and z is el.
408 // Double_t x0 x position of point where charge is liberated
409 // Double_t z0 z position of point where charge is liberated
410 // Int_t ix0 row of cell corresponding to point x0
411 // Int_t iz0 columb of cell corresponding to point z0
412 // Double_t el number of electrons liberated in this step
413 // Double_t sig Sigma difusion for this step (y0 dependent)
414 // Double_t ld lorentz drift in x for this step (y0 dependent)
415 // Int_t t track number
416 // Int_t ti hit track index number
417 // Int_t hi hit "hit" index number
422 const Int_t knx = 3,knz = 2;
423 const Double_t kRoot2 = 1.414213562; // Sqrt(2).
424 Int_t ix,iz,ixs,ixe,izs,ize;
425 Float_t x,z; // keep coordinates float (required by AliSegmentation)
426 Double_t s,sp,x1,x2,z1,z2;
428 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));
429 if (sig<=0.0) { // if sig<=0 No diffusion to simulate.
430 UpdateMapSignal(iz0,ix0,t,hi,el);
433 sp = 1.0/(sig*kRoot2);
434 ixs = Max(-knx+ix0,0);
435 ixe = Min(knx+ix0,fSeg->Npx()-1);
436 izs = Max(-knz+iz0,0);
437 ize = Min(knz+iz0,fSeg->Npz()-1);
438 for (ix=ixs;ix<=ixe;ix++)
439 for (iz=izs;iz<=ize;iz++) {
440 fSeg->DetToLocal(ix,iz,x,z); // pixel center
441 double dxi = 0.5*fSeg->Dpx(ix);
442 double dzi = 0.5*fSeg->Dpz(iz);
445 x2 = x1 + dxi; // Upper
447 z2 = z1 + dzi; // Upper
449 x1 -= x0+ld; // Distance from where track traveled (taking into account the Lorentz drift)
450 x2 -= x0+ld; // Distance from where track traveled (taking into account the Lorentz drift)
451 z1 -= z0; // Distance from where track traveled
452 z2 -= z0; // Distance from where track traveled
453 s = el*0.25; // Correction based on definision of Erfc
454 s *= AliMathBase::ErfcFast(sp*x1) - AliMathBase::ErfcFast(sp*x2);
455 s *= AliMathBase::ErfcFast(sp*z1) - AliMathBase::ErfcFast(sp*z2);
456 if (s>fSimuParam->GetPixMinElToAdd()) UpdateMapSignal(iz,ix,t,hi,s);
461 //______________________________________________________________________
462 void AliITSUSimulationPix::SpreadChargeAsym(Double_t x0,Double_t z0,
464 Double_t el,Double_t sigx,Double_t sigz,
465 Double_t ld,Int_t t,Int_t hi)
467 // Spreads the charge over neighboring cells. Assume charge is distributed
468 // as charge(x,z) = (el/2*pi*sigx*sigz)*exp(-arg)
469 // arg=((x-x0)*(x-x0)/2*sigx*sigx)+((z-z0*z-z0)/2*sigz*sigz)
470 // if fSimuParam->GetPixLorentzDrift()=kTRUE, then x0=x0+ld (Lorentz drift taken into account)
471 // Defined this way, the integral over all x and z is el.
473 // Double_t x0 x position of point where charge is liberated
474 // Double_t z0 z position of point where charge is liberated
475 // Int_t ix0 row of cell corresponding to point x0
476 // Int_t iz0 columb of cell corresponding to point z0
477 // Double_t el number of electrons liberated in this step
478 // Double_t sigx Sigma difusion along x for this step (y0 dependent)
479 // Double_t sigz Sigma difusion along z for this step (z0 dependent)
480 // Double_t ld lorentz drift in x for this stip (y0 dependent)
481 // Int_t t track number
482 // Int_t ti hit track index number
483 // Int_t hi hit "hit" index number
488 const Int_t knx = 3,knz = 3; // RS: TO TUNE
489 const Double_t kRoot2 = 1.414213562; // Sqrt(2).
490 Int_t ix,iz,ixs,ixe,izs,ize;
491 Float_t x,z; // keep coordinates float (required by AliSegmentation)
492 Double_t s,spx,spz,x1,x2,z1,z2;
494 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)",
495 x0,z0,ix0,iz0,el,sigx,sigz,t,hi,ld));
496 if (sigx<=0.0 || sigz<=0.0) { // if sig<=0 No diffusion to simulate.
497 UpdateMapSignal(iz0,ix0,t,hi,el);
500 spx = 1.0/(sigx*kRoot2);
501 spz = 1.0/(sigz*kRoot2);
502 ixs = Max(-knx+ix0,0);
503 ixe = Min(knx+ix0,fSeg->Npx()-1);
504 izs = Max(-knz+iz0,0);
505 ize = Min(knz+iz0,fSeg->Npz()-1);
506 for (ix=ixs;ix<=ixe;ix++)
507 for (iz=izs;iz<=ize;iz++) {
508 fSeg->DetToLocal(ix,iz,x,z); // pixel center
509 double dxi = 0.5*fSeg->Dpx(ix);
510 double dzi = 0.5*fSeg->Dpz(iz);
513 x2 = x1 + dxi; // Upper
515 z2 = z1 + dzi; // Upper
517 x1 -= x0+ld; // Distance from where track traveled (taking into account the Lorentz drift)
518 x2 -= x0+ld; // Distance from where track traveled (taking into account the Lorentz drift)
519 z1 -= z0; // Distance from where track traveled
520 z2 -= z0; // Distance from where track traveled
521 s = el*0.25; // Correction based on definision of Erfc
522 s *= AliMathBase::ErfcFast(spx*x1) - AliMathBase::ErfcFast(spx*x2);
523 s *= AliMathBase::ErfcFast(spz*z1) - AliMathBase::ErfcFast(spz*z2);
524 if (s>fSimuParam->GetPixMinElToAdd()) UpdateMapSignal(iz,ix,t,hi,s);
529 //______________________________________________________________________
530 void AliITSUSimulationPix::RemoveDeadPixels()
532 // Removes dead pixels on each module (ladder)
533 // This should be called before going from sdigits to digits (FrompListToDigits)
535 AliITSUCalibrationPix* calObj = (AliITSUCalibrationPix*) GetCalibDead();
538 if (calObj->IsBad()) {ClearMap(); return;} // whole module is masked
540 // remove single bad pixels one by one
541 int nsingle = calObj->GetNrBadSingle();
543 for (int i=nsingle;i--;) {
544 calObj->GetBadPixelSingle(i,row,col);
545 fSensMap->DeleteItem(col,row);
547 int nsd = fSensMap->GetEntriesUnsorted();
548 for (int isd=nsd;isd--;) {
549 AliITSUSDigit* sd = (AliITSUSDigit*)fSensMap->AtUnsorted(isd);
550 if (fSensMap->IsDisabled(sd)) continue;
551 fSensMap->GetMapIndex(sd->GetUniqueID(),col,row);
552 int chip = fSeg->GetChipFromChannel(0,col);
553 // if (calObj->IsChipMarkedBad(chip)) fSensMap->Disable(sd); // this will simple mark the hit as bad
554 if (calObj->IsChipMarkedBad(chip)) fSensMap->DeleteItem(sd); // this will suppress hit in the sorted list
559 //______________________________________________________________________
560 void AliITSUSimulationPix::AddNoisyPixels()
562 // Adds noisy pixels on each module (ladder)
563 // This should be called before going from sdigits to digits (FrompListToDigits)
564 AliITSUCalibrationPix* calObj = (AliITSUCalibrationPix*) GetCalibNoisy();
566 for (Int_t i=calObj->GetNrBad(); i--;) UpdateMapNoise(calObj->GetBadColAt(i), calObj->GetBadRowAt(i),
567 10*fSimuParam->GetPixThreshold(fModule));
571 //______________________________________________________________________
572 void AliITSUSimulationPix::FrompListToDigits()
574 // add noise and electronics, perform the zero suppression and add the
576 static AliITSU *aliITS = (AliITSU*)gAlice->GetModule("ITS");
579 const Int_t knmaxtrk=AliITSdigit::GetNTracks();
580 static AliITSUDigitPix dig;
582 // 1) for every pixel w/o hit we have to generate a noise and activate the pixel if the noise exceeds the threshold.
583 // 2) for every pixel with hit we should add random noise and check if the total signal exceeds the threshold
584 // With many channels this will be too time consuming, hence I do the following
585 // 1) Precalculate the probability that the nois alone will exceed the threshold.
586 // 2) Chose randomly empty pixels according to this probability and apply the noise above threshold.
587 // 3) For pixels having a hits apply the usual noise and compare with threshold
589 // RS may use for ordered random sample generation dl.acm.org/ft_gateway.cfm?id=356313&type=pdf
591 int maxInd = fSensMap->GetMaxIndex();
592 double minProb = 0.1/maxInd;
594 int nsd = fSensMap->GetEntries();
595 Int_t prevID=0,curID=0;
596 TArrayI ordSampleInd(100),ordSample(100);
598 double probNoisy,noiseSig,noiseMean,thresh = fSimuParam->GetPixThreshold(fModule);
599 fSimuParam->GetPixNoise(fModule, noiseSig, noiseMean);
600 probNoisy = AliITSUSimuParam::CalcProbNoiseOverThreshold(noiseMean,noiseSig,thresh); // prob. to have noise above threshold
602 for (int i=0;i<nsd;i++) {
603 AliITSUSDigit* sd = (AliITSUSDigit*)fSensMap->At(i); // ordered in index
604 if (fSensMap->IsDisabled(sd)) continue;
605 curID = (int)sd->GetUniqueID();
607 if (probNoisy>minProb) { // generate randomly noisy pixels above the threshold, with ID's between previous hit and current
608 CreateNoisyDigits(prevID,curID,probNoisy, noiseSig, noiseMean);
612 if ((sig=sd->GetSumSignal())<=fSimuParam->GetPixThreshold(fModule)) continue;
613 if (Abs(sig)>2147483647.0) { //RS?
614 //PH 2147483647 is the max. integer
615 //PH This apparently is a problem which needs investigation
616 AliWarning(Form("Too big or too small signal value %f",sig));
618 fSensMap->GetMapIndex(sd->GetUniqueID(),iz,ix);
622 dig.SetSignalPix((Int_t)sig);
623 int ntr = sd->GetNTracks();
624 for (int j=0;j<ntr;j++) {
625 dig.SetTrack(j,sd->GetTrack(j));
626 dig.SetHit(j,sd->GetHit(j));
628 for (int j=ntr;j<knmaxtrk;j++) {
632 aliITS->AddSimDigit(AliITSUGeomTGeo::kDetTypePix, &dig);
634 // if needed, add noisy pixels with id from last real hit to maxID
635 if (probNoisy>minProb) CreateNoisyDigits(prevID,maxInd,probNoisy, noiseSig, noiseMean);
639 //______________________________________________________________________
640 Int_t AliITSUSimulationPix::CreateNoisyDigits(Int_t minID,Int_t maxID,double probNoisy, double noise, double base)
642 // create random noisy digits above threshold within id range [minID,maxID[
643 // see FrompListToDigits for details
645 static AliITSU *aliITS = (AliITSU*)gAlice->GetModule("ITS");
647 static AliITSUDigitPix dig;
648 static TArrayI ordSampleInd(100),ordSample(100); //RS!!! static is not thread-safe!!!
649 const Int_t knmaxtrk=AliITSdigit::GetNTracks();
652 int npix = maxID-minID;
653 if (npix<1 || (ncand=gRandom->Poisson(npix*probNoisy))<1) return ncand; // decide how many noisy pixels will be added
654 ncand = GenOrderedSample(npix,ncand,ordSample,ordSampleInd);
655 int* ordV = ordSample.GetArray();
656 int* ordI = ordSampleInd.GetArray();
657 for (int j=0;j<ncand;j++) {
658 fSensMap->GetMapIndex((UInt_t)ordV[ordI[j]],iz,ix); // create noisy digit
662 dig.SetSignalPix((Int_t)AliITSUSimuParam::GenerateNoiseQFunction(probNoisy,base,noise));
663 for (int k=knmaxtrk;k--;) {
667 aliITS->AddSimDigit(AliITSUGeomTGeo::kDetTypePix,&dig);
668 if (GetDebug(2)) AliInfo(Form("Add noisy pixel %d(%d/%d) Noise=%d",ordV[ordI[j]],iz,ix,dig.GetSignalPix()));
673 //______________________________________________________________________
674 void AliITSUSimulationPix::SetCoupling(AliITSUSDigit* old, Int_t ntrack, Int_t idhit)
676 // Take into account the coupling between adiacent pixels.
677 // The parameters probcol and probrow are the probability of the
678 // signal in one pixel shared in the two adjacent pixels along
679 // the column and row direction, respectively.
680 // Note pList is goten via GetMap() and module is not need any more.
681 // Otherwise it is identical to that coded by Tiziano Virgili (BSN).
684 <img src="picts/ITS/barimodel_3.gif">
687 <font size=+2 color=red>
688 <a href="mailto:tiziano.virgili@cern.ch"></a>.
694 // old existing AliITSUSDigit
695 // Int_t ntrack track incex number
696 // Int_t idhit hit index number
698 Double_t pulse1,pulse2;
699 Double_t couplR=0.0,couplC=0.0;
702 fSensMap->GetMapIndex(old->GetUniqueID(),col,row);
703 fSimuParam->GetPixCouplingParam(couplC,couplR);
704 if (GetDebug(2)) AliInfo(Form("(col=%d,row=%d,ntrack=%d,idhit=%d) couplC=%e couplR=%e",
705 col,row,ntrack,idhit,couplC,couplR));
706 pulse2 = pulse1 = old->GetSignal();
707 if (pulse1<fSimuParam->GetPixMinElToAdd()) return; // too small signal
708 for (Int_t isign=-1;isign<=1;isign+=2) {
710 // loop in col direction
711 int j1 = int(col) + isign;
712 xr = gRandom->Rndm();
713 if ( !((j1<0) || (j1>fSeg->Npz()-1) || (xr>couplC)) ) UpdateMapSignal(UInt_t(j1),row,ntrack,idhit,pulse1);
715 // loop in row direction
716 int j2 = int(row) + isign;
717 xr = gRandom->Rndm();
718 if ( !((j2<0) || (j2>fSeg->Npx()-1) || (xr>couplR)) ) UpdateMapSignal(col,UInt_t(j2),ntrack,idhit,pulse2);
723 //______________________________________________________________________
724 void AliITSUSimulationPix::SetCouplingOld(AliITSUSDigit* old, Int_t ntrack,Int_t idhit)
726 // Take into account the coupling between adiacent pixels.
727 // The parameters probcol and probrow are the fractions of the
728 // signal in one pixel shared in the two adjacent pixels along
729 // the column and row direction, respectively.
732 <img src="picts/ITS/barimodel_3.gif">
735 <font size=+2 color=red>
736 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
742 // old existing AliITSUSDigit
743 // ntrack track incex number
744 // idhit hit index number
745 // module module number
748 Double_t pulse1,pulse2;
749 Double_t couplR=0.0,couplC=0.0;
751 fSensMap->GetMapIndex(old->GetUniqueID(),col,row);
752 fSimuParam->GetPixCouplingParam(couplC,couplR);
753 if (GetDebug(3)) AliInfo(Form("(col=%d,row=%d,ntrack=%d,idhit=%d) couplC=%e couplR=%e",
754 col,row,ntrack,idhit,couplC,couplR));
756 if (old->GetSignal()<fSimuParam->GetPixMinElToAdd()) return; // too small signal
757 for (Int_t isign=-1;isign<=1;isign+=2) {// loop in col direction
758 pulse2 = pulse1 = old->GetSignal();
760 int j1 = int(col)+isign;
762 if ((j1<0)||(j1>fSeg->Npz()-1)||(pulse1<fSimuParam->GetPixThreshold(fModule))) pulse1 = old->GetSignal();
763 else UpdateMapSignal(UInt_t(j1),row,ntrack,idhit,pulse1);
765 // loop in row direction
766 int j2 = int(row) + isign;
768 if ((j2<0)||(j2>(fSeg->Npx()-1))||(pulse2<fSimuParam->GetPixThreshold(fModule))) pulse2 = old->GetSignal();
769 else UpdateMapSignal(col,UInt_t(j2),ntrack,idhit,pulse2);
773 //______________________________________________________________________
774 void AliITSUSimulationPix::GenerateStrobePhase()
776 // Generate randomly the strobe
777 // phase w.r.t to the LHC clock
778 // Done once per event
779 const Double_t kBunchLenght = 25e-9; // LHC clock
780 fStrobePhase = ((Double_t)gRandom->Integer(fStrobeLenght))*kBunchLenght-
781 (Double_t)fStrobeLenght*kBunchLenght+