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 kmictocm = 1.0e-4; // convert microns to cm.
214 const Double_t kcmtomic = 1.e4;
215 const Double_t kBunchLenght = 25e-9; // LHC clock
216 Int_t nhits = mod->GetNHits();
221 Float_t x,y,z; // keep coordinates float (required by AliSegmentation)
222 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;
223 Double_t t,tp,st,dt=0.2,el,sig,sigx,sigz,fda;
224 Double_t thick = 0.5*kmictocm*fSeg->Dy(); // Half Thickness
225 fSimuParam->GetPixSigmaDiffusionAsymmetry(fda);
227 for (h=0;h<nhits;h++) {
229 ((mod->GetHit(h)->GetTOF()<fStrobePhase) ||
230 (mod->GetHit(h)->GetTOF()>(fStrobePhase+fStrobeLenght*kBunchLenght)))
233 if (!mod->LineSegmentL(h,x0,x1,y0,y1,z0,z1,de,idtrack)) continue;
234 st = TMath::Sqrt(x1*x1+y1*y1+z1*z1);
236 st = (Double_t)((Int_t)(st*kcmtomic)); // number of microns
237 if (st<=1.0) st = 1.0;
239 for (t=0.0;t<1.0;t+=dt) { // Integrate over t
244 if (!(fSeg->LocalToDet(x,z,ix,iz))) continue; // outside
245 el = dt * de / fSimuParam->GetGeVToCharge();
247 sig = fSimuParam->SigmaDiffusion1D(TMath::Abs(thick + y));
250 if (fSimuParam->GetPixLorentzDrift()) ld=(y+thick)*fTanLorAng;
251 SpreadChargeAsym(x,z,ix,iz,el,sigx,sigz,ld,idtrack,h);
253 } else { // st == 0.0 deposit it at this point
257 if (!(fSeg->LocalToDet(x,z,ix,iz))) continue; // outside
258 el = de / fSimuParam->GetGeVToCharge();
259 sig = fSimuParam->SigmaDiffusion1D(TMath::Abs(thick + y));
262 if (fSimuParam->GetPixLorentzDrift()) ld=(y+thick)*fTanLorAng;
263 SpreadChargeAsym(x,z,ix,iz,el,sigx,sigz,ld,idtrack,h);
265 } // Loop over all hits h
268 int nd = fSensMap->GetEntriesUnsorted(); // use unsorted access when possible, since it is faster
269 AliITSUSDigit* dg = 0;
270 switch (fSimuParam->GetPixCouplingOption()) {
271 case AliITSUSimuParam::kNewCouplingPix :
273 dg = (AliITSUSDigit*)fSensMap->AtUnsorted(i);
274 if (fSensMap->IsDisabled(dg)) continue;
275 SetCoupling(dg,idtrack,h);
278 case AliITSUSimuParam::kOldCouplingPix:
280 dg = (AliITSUSDigit*)fSensMap->AtUnsorted(i);
281 if (fSensMap->IsDisabled(dg)) continue;
282 SetCouplingOld(dg,idtrack,h);
289 if (GetDebug(2)) AliInfo(Form("Finished fCoupling=%d",fSimuParam->GetPixCouplingOption()));
292 //______________________________________________________________________
293 void AliITSUSimulationPix::Hits2SDigitsFast(AliITSUModule *mod)
295 // Does the charge distributions using Gaussian diffusion charge charing. // Inputs:
296 // AliITSUModule *mod Pointer to this module
301 const Double_t kmictocm = 1.0e-4; // convert microns to cm.
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,
311 const Double_t kBunchLenght = 25e-9; // LHC clock
312 TObjArray *hits = mod->GetHits();
313 Int_t nhits = hits->GetEntriesFast();
314 if (nhits<=0) return;
318 Float_t x,y,z; // keep coordinates float (required by AliSegmentation)
319 Double_t x0=0.0,x1=0.0,y0=0.0,y1=0.0,z0=0.0,z1=0.0;
320 Double_t t,st,el,sig,sigx,sigz,fda,de=0.0,ld=0.0;
321 Double_t thick = 0.5*kmictocm*fSeg->Dy(); // Half thickness
322 fSimuParam->GetPixSigmaDiffusionAsymmetry(fda);
324 for (h=0;h<nhits;h++) {
325 // Check if the hit is inside readout window
327 ((mod->GetHit(h)->GetTOF()<fStrobePhase) ||
328 (mod->GetHit(h)->GetTOF()>(fStrobePhase+fStrobeLenght*kBunchLenght)))
331 if (!mod->LineSegmentL(h,x0,x1,y0,y1,z0,z1,de,idtrack)) continue;
332 st = TMath::Sqrt(x1*x1+y1*y1+z1*z1);
334 for (i=0;i<kn10;i++) { // Integrate over t
339 if (!(fSeg->LocalToDet(x,z,ix,iz))) continue; // outside
340 el = kwi[i]*de/fSimuParam->GetGeVToCharge();
341 sig = fSimuParam->SigmaDiffusion1D(TMath::Abs(thick + y));
344 if (fSimuParam->GetPixLorentzDrift()) ld=(y+thick)*fTanLorAng;
345 SpreadChargeAsym(x,z,ix,iz,el,sigx,sigz,ld,idtrack,h);
346 } // end for i // End Integrate over t
347 else { // st == 0.0 deposit it at this point
351 if (!(fSeg->LocalToDet(x,z,ix,iz))) continue; // outside
352 el = de / fSimuParam->GetGeVToCharge();
353 sig = fSimuParam->SigmaDiffusion1D(TMath::Abs(thick + y));
356 if (fSimuParam->GetPixLorentzDrift()) ld=(y+thick)*fTanLorAng;
357 SpreadChargeAsym(x,z,ix,iz,el,sigx,sigz,ld,idtrack,h);
360 } // Loop over all hits h
363 int nd = fSensMap->GetEntriesUnsorted(); // use unsorted access when possible, since it is faster
364 AliITSUSDigit* dg = 0;
365 switch (fSimuParam->GetPixCouplingOption()) {
366 case AliITSUSimuParam::kNewCouplingPix :
368 dg = (AliITSUSDigit*)fSensMap->AtUnsorted(i);
369 if (fSensMap->IsDisabled(dg)) continue;
370 SetCoupling(dg,idtrack,h);
372 case AliITSUSimuParam::kOldCouplingPix:
374 dg = (AliITSUSDigit*)fSensMap->AtUnsorted(i);
375 if (fSensMap->IsDisabled(dg)) continue;
376 SetCouplingOld(dg,idtrack,h);
382 if (GetDebug(2)) AliInfo(Form("Finished fCoupling=%d",fSimuParam->GetPixCouplingOption()));
385 //______________________________________________________________________
386 void AliITSUSimulationPix::SpreadCharge(Double_t x0,Double_t z0,
388 Double_t el,Double_t sig,Double_t ld,
391 // Spreads the charge over neighboring cells. Assume charge is distributed
392 // as charge(x,z) = (el/2*pi*sig*sig)*exp(-arg)
393 // arg=((x-x0)*(x-x0)/2*sig*sig)+((z-z0*z-z0)/2*sig*sig)
394 // if fSimuParam->GetPixLorentzDrift()=kTRUE, then x0=x0+ld (Lorentz drift taken into account)
395 // Defined this way, the integral over all x and z is el.
397 // Double_t x0 x position of point where charge is liberated
398 // Double_t z0 z position of point where charge is liberated
399 // Int_t ix0 row of cell corresponding to point x0
400 // Int_t iz0 columb of cell corresponding to point z0
401 // Double_t el number of electrons liberated in this step
402 // Double_t sig Sigma difusion for this step (y0 dependent)
403 // Double_t ld lorentz drift in x for this step (y0 dependent)
404 // Int_t t track number
405 // Int_t ti hit track index number
406 // Int_t hi hit "hit" index number
411 const Int_t knx = 3,knz = 2;
412 const Double_t kRoot2 = 1.414213562; // Sqrt(2).
413 const Double_t kmictocm = 1.0e-4; // convert microns to cm.
414 Int_t ix,iz,ixs,ixe,izs,ize;
415 Float_t x,z; // keep coordinates float (required by AliSegmentation)
416 Double_t s,sp,x1,x2,z1,z2;
418 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));
419 if (sig<=0.0) { // if sig<=0 No diffusion to simulate.
420 UpdateMapSignal(iz0,ix0,t,hi,el);
423 sp = 1.0/(sig*kRoot2);
424 ixs = TMath::Max(-knx+ix0,0);
425 ixe = TMath::Min(knx+ix0,fSeg->Npx()-1);
426 izs = TMath::Max(-knz+iz0,0);
427 ize = TMath::Min(knz+iz0,fSeg->Npz()-1);
428 for (ix=ixs;ix<=ixe;ix++)
429 for (iz=izs;iz<=ize;iz++) {
430 fSeg->DetToLocal(ix,iz,x,z); // pixel center
431 double dxi = 0.5*kmictocm*fSeg->Dpx(ix);
432 double dzi = 0.5*kmictocm*fSeg->Dpz(iz);
435 x2 = x1 + dxi; // Upper
437 z2 = z1 + dzi; // Upper
439 x1 -= x0+ld; // Distance from where track traveled (taking into account the Lorentz drift)
440 x2 -= x0+ld; // Distance from where track traveled (taking into account the Lorentz drift)
441 z1 -= z0; // Distance from where track traveled
442 z2 -= z0; // Distance from where track traveled
443 s = el*0.25; // Correction based on definision of Erfc
444 s *= AliMathBase::ErfcFast(sp*x1) - AliMathBase::ErfcFast(sp*x2);
445 s *= AliMathBase::ErfcFast(sp*z1) - AliMathBase::ErfcFast(sp*z2);
446 if (s>fSimuParam->GetPixMinElToAdd()) UpdateMapSignal(iz,ix,t,hi,s);
451 //______________________________________________________________________
452 void AliITSUSimulationPix::SpreadChargeAsym(Double_t x0,Double_t z0,
454 Double_t el,Double_t sigx,Double_t sigz,
455 Double_t ld,Int_t t,Int_t hi)
457 // Spreads the charge over neighboring cells. Assume charge is distributed
458 // as charge(x,z) = (el/2*pi*sigx*sigz)*exp(-arg)
459 // arg=((x-x0)*(x-x0)/2*sigx*sigx)+((z-z0*z-z0)/2*sigz*sigz)
460 // if fSimuParam->GetPixLorentzDrift()=kTRUE, then x0=x0+ld (Lorentz drift taken into account)
461 // Defined this way, the integral over all x and z is el.
463 // Double_t x0 x position of point where charge is liberated
464 // Double_t z0 z position of point where charge is liberated
465 // Int_t ix0 row of cell corresponding to point x0
466 // Int_t iz0 columb of cell corresponding to point z0
467 // Double_t el number of electrons liberated in this step
468 // Double_t sigx Sigma difusion along x for this step (y0 dependent)
469 // Double_t sigz Sigma difusion along z for this step (z0 dependent)
470 // Double_t ld lorentz drift in x for this stip (y0 dependent)
471 // Int_t t track number
472 // Int_t ti hit track index number
473 // Int_t hi hit "hit" index number
478 const Int_t knx = 3,knz = 3; // RS: TO TUNE
479 const Double_t kRoot2 = 1.414213562; // Sqrt(2).
480 const Double_t kmictocm = 1.0e-4; // convert microns to cm.
481 Int_t ix,iz,ixs,ixe,izs,ize;
482 Float_t x,z; // keep coordinates float (required by AliSegmentation)
483 Double_t s,spx,spz,x1,x2,z1,z2;
485 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)",
486 x0,z0,ix0,iz0,el,sigx,sigz,t,hi,ld));
487 if (sigx<=0.0 || sigz<=0.0) { // if sig<=0 No diffusion to simulate.
488 UpdateMapSignal(iz0,ix0,t,hi,el);
491 spx = 1.0/(sigx*kRoot2);
492 spz = 1.0/(sigz*kRoot2);
493 ixs = TMath::Max(-knx+ix0,0);
494 ixe = TMath::Min(knx+ix0,fSeg->Npx()-1);
495 izs = TMath::Max(-knz+iz0,0);
496 ize = TMath::Min(knz+iz0,fSeg->Npz()-1);
497 for (ix=ixs;ix<=ixe;ix++)
498 for (iz=izs;iz<=ize;iz++) {
499 fSeg->DetToLocal(ix,iz,x,z); // pixel center
500 double dxi = 0.5*kmictocm*fSeg->Dpx(ix);
501 double dzi = 0.5*kmictocm*fSeg->Dpz(iz);
504 x2 = x1 + dxi; // Upper
506 z2 = z1 + dzi; // Upper
508 x1 -= x0+ld; // Distance from where track traveled (taking into account the Lorentz drift)
509 x2 -= x0+ld; // Distance from where track traveled (taking into account the Lorentz drift)
510 z1 -= z0; // Distance from where track traveled
511 z2 -= z0; // Distance from where track traveled
512 s = el*0.25; // Correction based on definision of Erfc
513 s *= AliMathBase::ErfcFast(spx*x1) - AliMathBase::ErfcFast(spx*x2);
514 s *= AliMathBase::ErfcFast(spz*z1) - AliMathBase::ErfcFast(spz*z2);
515 if (s>fSimuParam->GetPixMinElToAdd()) UpdateMapSignal(iz,ix,t,hi,s);
520 //______________________________________________________________________
521 void AliITSUSimulationPix::RemoveDeadPixels()
523 // Removes dead pixels on each module (ladder)
524 // This should be called before going from sdigits to digits (FrompListToDigits)
526 AliITSUCalibrationPix* calObj = (AliITSUCalibrationPix*) GetCalibDead();
529 if (calObj->IsBad()) {ClearMap(); return;} // whole module is masked
531 // remove single bad pixels one by one
532 int nsingle = calObj->GetNrBadSingle();
534 for (int i=nsingle;i--;) {
535 calObj->GetBadPixelSingle(i,row,col);
536 fSensMap->DeleteItem(col,row);
538 int nsd = fSensMap->GetEntriesUnsorted();
539 for (int isd=nsd;isd--;) {
540 AliITSUSDigit* sd = (AliITSUSDigit*)fSensMap->AtUnsorted(isd);
541 if (fSensMap->IsDisabled(sd)) continue;
542 fSensMap->GetMapIndex(sd->GetUniqueID(),col,row);
543 int chip = fSeg->GetChipFromChannel(0,col);
544 // if (calObj->IsChipMarkedBad(chip)) fSensMap->Disable(sd); // this will simple mark the hit as bad
545 if (calObj->IsChipMarkedBad(chip)) fSensMap->DeleteItem(sd); // this will suppress hit in the sorted list
550 //______________________________________________________________________
551 void AliITSUSimulationPix::AddNoisyPixels()
553 // Adds noisy pixels on each module (ladder)
554 // This should be called before going from sdigits to digits (FrompListToDigits)
555 AliITSUCalibrationPix* calObj = (AliITSUCalibrationPix*) GetCalibNoisy();
557 for (Int_t i=calObj->GetNrBad(); i--;) UpdateMapNoise(calObj->GetBadColAt(i), calObj->GetBadRowAt(i),
558 10*fSimuParam->GetPixThreshold(fModule));
562 //______________________________________________________________________
563 void AliITSUSimulationPix::FrompListToDigits()
565 // add noise and electronics, perform the zero suppression and add the
567 static AliITSU *aliITS = (AliITSU*)gAlice->GetModule("ITS");
570 const Int_t knmaxtrk=AliITSdigit::GetNTracks();
571 static AliITSUDigitPix dig;
573 // 1) for every pixel w/o hit we have to generate a noise and activate the pixel if the noise exceeds the threshold.
574 // 2) for every pixel with hit we should add random noise and check if the total signal exceeds the threshold
575 // With many channels this will be too time consuming, hence I do the following
576 // 1) Precalculate the probability that the nois alone will exceed the threshold.
577 // 2) Chose randomly empty pixels according to this probability and apply the noise above threshold.
578 // 3) For pixels having a hits apply the usual noise and compare with threshold
580 // RS may use for ordered random sample generation dl.acm.org/ft_gateway.cfm?id=356313&type=pdf
582 int maxInd = fSensMap->GetMaxIndex();
583 double minProb = 0.1/maxInd;
585 int nsd = fSensMap->GetEntries();
586 Int_t prevID=0,curID=0;
587 TArrayI ordSampleInd(100),ordSample(100);
589 double probNoisy,noiseSig,noiseMean,thresh = fSimuParam->GetPixThreshold(fModule);
590 fSimuParam->GetPixNoise(fModule, noiseSig, noiseMean);
591 probNoisy = AliITSUSimuParam::CalcProbNoiseOverThreshold(noiseMean,noiseSig,thresh); // prob. to have noise above threshold
593 for (int i=0;i<nsd;i++) {
594 AliITSUSDigit* sd = (AliITSUSDigit*)fSensMap->At(i); // ordered in index
595 if (fSensMap->IsDisabled(sd)) continue;
596 curID = (int)sd->GetUniqueID();
598 if (probNoisy>minProb) { // generate randomly noisy pixels above the threshold, with ID's between previous hit and current
599 CreateNoisyDigits(prevID,curID,probNoisy, noiseSig, noiseMean);
603 if ((sig=sd->GetSumSignal())<=fSimuParam->GetPixThreshold(fModule)) continue;
604 if (TMath::Abs(sig)>2147483647.0) { //RS?
605 //PH 2147483647 is the max. integer
606 //PH This apparently is a problem which needs investigation
607 AliWarning(Form("Too big or too small signal value %f",sig));
609 fSensMap->GetMapIndex(sd->GetUniqueID(),iz,ix);
613 dig.SetSignalPix((Int_t)sig);
614 int ntr = sd->GetNTracks();
615 for (int j=0;j<ntr;j++) {
616 dig.SetTrack(j,sd->GetTrack(j));
617 dig.SetHit(j,sd->GetHit(j));
619 for (int j=ntr;j<knmaxtrk;j++) {
623 aliITS->AddSimDigit(AliITSUGeomTGeo::kDetTypePix, &dig);
625 // if needed, add noisy pixels with id from last real hit to maxID
626 if (probNoisy>minProb) CreateNoisyDigits(prevID,maxInd,probNoisy, noiseSig, noiseMean);
630 //______________________________________________________________________
631 Int_t AliITSUSimulationPix::CreateNoisyDigits(Int_t minID,Int_t maxID,double probNoisy, double noise, double base)
633 // create random noisy digits above threshold within id range [minID,maxID[
634 // see FrompListToDigits for details
636 static AliITSU *aliITS = (AliITSU*)gAlice->GetModule("ITS");
638 static AliITSUDigitPix dig;
639 static TArrayI ordSampleInd(100),ordSample(100); //RS!!! static is not thread-safe!!!
640 const Int_t knmaxtrk=AliITSdigit::GetNTracks();
643 int npix = maxID-minID;
644 if (npix<1 || (ncand=gRandom->Poisson(npix*probNoisy))<1) return ncand; // decide how many noisy pixels will be added
645 ncand = GenOrderedSample(npix,ncand,ordSample,ordSampleInd);
646 int* ordV = ordSample.GetArray();
647 int* ordI = ordSampleInd.GetArray();
648 for (int j=0;j<ncand;j++) {
649 fSensMap->GetMapIndex((UInt_t)ordV[ordI[j]],iz,ix); // create noisy digit
653 dig.SetSignalPix((Int_t)AliITSUSimuParam::GenerateNoiseQFunction(probNoisy,base,noise));
654 for (int k=knmaxtrk;k--;) {
658 aliITS->AddSimDigit(AliITSUGeomTGeo::kDetTypePix,&dig);
659 if (GetDebug(2)) AliInfo(Form("Add noisy pixel %d(%d/%d) Noise=%d",ordV[ordI[j]],iz,ix,dig.GetSignalPix()));
664 //______________________________________________________________________
665 void AliITSUSimulationPix::SetCoupling(AliITSUSDigit* old, Int_t ntrack, Int_t idhit)
667 // Take into account the coupling between adiacent pixels.
668 // The parameters probcol and probrow are the probability of the
669 // signal in one pixel shared in the two adjacent pixels along
670 // the column and row direction, respectively.
671 // Note pList is goten via GetMap() and module is not need any more.
672 // Otherwise it is identical to that coded by Tiziano Virgili (BSN).
675 <img src="picts/ITS/barimodel_3.gif">
678 <font size=+2 color=red>
679 <a href="mailto:tiziano.virgili@cern.ch"></a>.
685 // old existing AliITSUSDigit
686 // Int_t ntrack track incex number
687 // Int_t idhit hit index number
689 Double_t pulse1,pulse2;
690 Double_t couplR=0.0,couplC=0.0;
693 fSensMap->GetMapIndex(old->GetUniqueID(),col,row);
694 fSimuParam->GetPixCouplingParam(couplC,couplR);
695 if (GetDebug(2)) AliInfo(Form("(col=%d,row=%d,ntrack=%d,idhit=%d) couplC=%e couplR=%e",
696 col,row,ntrack,idhit,couplC,couplR));
697 pulse2 = pulse1 = old->GetSignal();
698 if (pulse1<fSimuParam->GetPixMinElToAdd()) return; // too small signal
699 for (Int_t isign=-1;isign<=1;isign+=2) {
701 // loop in col direction
702 int j1 = int(col) + isign;
703 xr = gRandom->Rndm();
704 if ( !((j1<0) || (j1>fSeg->Npz()-1) || (xr>couplC)) ) UpdateMapSignal(UInt_t(j1),row,ntrack,idhit,pulse1);
706 // loop in row direction
707 int j2 = int(row) + isign;
708 xr = gRandom->Rndm();
709 if ( !((j2<0) || (j2>fSeg->Npx()-1) || (xr>couplR)) ) UpdateMapSignal(col,UInt_t(j2),ntrack,idhit,pulse2);
714 //______________________________________________________________________
715 void AliITSUSimulationPix::SetCouplingOld(AliITSUSDigit* old, Int_t ntrack,Int_t idhit)
717 // Take into account the coupling between adiacent pixels.
718 // The parameters probcol and probrow are the fractions of the
719 // signal in one pixel shared in the two adjacent pixels along
720 // the column and row direction, respectively.
723 <img src="picts/ITS/barimodel_3.gif">
726 <font size=+2 color=red>
727 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
733 // old existing AliITSUSDigit
734 // ntrack track incex number
735 // idhit hit index number
736 // module module number
739 Double_t pulse1,pulse2;
740 Double_t couplR=0.0,couplC=0.0;
742 fSensMap->GetMapIndex(old->GetUniqueID(),col,row);
743 fSimuParam->GetPixCouplingParam(couplC,couplR);
744 if (GetDebug(3)) AliInfo(Form("(col=%d,row=%d,ntrack=%d,idhit=%d) couplC=%e couplR=%e",
745 col,row,ntrack,idhit,couplC,couplR));
747 if (old->GetSignal()<fSimuParam->GetPixMinElToAdd()) return; // too small signal
748 for (Int_t isign=-1;isign<=1;isign+=2) {// loop in col direction
749 pulse2 = pulse1 = old->GetSignal();
751 int j1 = int(col)+isign;
753 if ((j1<0)||(j1>fSeg->Npz()-1)||(pulse1<fSimuParam->GetPixThreshold(fModule))) pulse1 = old->GetSignal();
754 else UpdateMapSignal(UInt_t(j1),row,ntrack,idhit,pulse1);
756 // loop in row direction
757 int j2 = int(row) + isign;
759 if ((j2<0)||(j2>(fSeg->Npx()-1))||(pulse2<fSimuParam->GetPixThreshold(fModule))) pulse2 = old->GetSignal();
760 else UpdateMapSignal(col,UInt_t(j2),ntrack,idhit,pulse2);
764 //______________________________________________________________________
765 void AliITSUSimulationPix::GenerateStrobePhase()
767 // Generate randomly the strobe
768 // phase w.r.t to the LHC clock
769 // Done once per event
770 const Double_t kBunchLenght = 25e-9; // LHC clock
771 fStrobePhase = ((Double_t)gRandom->Integer(fStrobeLenght))*kBunchLenght-
772 (Double_t)fStrobeLenght*kBunchLenght+