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>
27 #include "AliITSUDigitPix.h"
28 #include "AliITSUHit.h"
29 #include "AliITSUModule.h"
30 #include "AliITSUSensMap.h"
31 #include "AliITSUCalibrationPix.h"
32 #include "AliITSUSegmentationPix.h"
33 #include "AliITSUSimulationPix.h"
37 #include "AliMathBase.h"
38 #include "AliITSUSimuParam.h"
39 #include "AliITSUSDigit.h"
40 #include "AliITSUParamList.h"
44 using namespace TMath;
46 ClassImp(AliITSUSimulationPix)
47 ////////////////////////////////////////////////////////////////////////
49 // Modified by D. Elia, G.E. Bruno, H. Tydesjo
50 // Fast diffusion code by Bjorn S. Nilsen
52 // October 2007: GetCalibrationObjects() removed
55 // Written by Boris Batyunya
58 // Adapted for pixels of ITS upgrade July 2012, ruben.shahoyan@cern.ch
60 // AliITSUSimulationPix is to do the simulation of pixels
62 // 2013 Feb: Added MonoPix response and nois calculation al la MIMOSA32 (levente.molnar@cern.ch)
64 ////////////////////////////////////////////////////////////////////////
66 //______________________________________________________________________
67 AliITSUSimulationPix::AliITSUSimulationPix()
69 ,fReadOutCycleLength(25e-6)
70 ,fReadOutCycleOffset(0)
71 ,fGlobalChargeScale(1.0)
76 // Default constructor.
77 SetUniqueID(AliITSUGeomTGeo::kDetTypePix);
80 //______________________________________________________________________
81 AliITSUSimulationPix::AliITSUSimulationPix(AliITSUSimuParam* sim,AliITSUSensMap* map)
82 :AliITSUSimulation(sim,map)
84 ,fReadOutCycleLength(25e-6)
85 ,fReadOutCycleOffset(0)
86 ,fGlobalChargeScale(1.0)
91 // standard constructor
92 SetUniqueID(AliITSUGeomTGeo::kDetTypePix);
96 //______________________________________________________________________
97 AliITSUSimulationPix::AliITSUSimulationPix(const AliITSUSimulationPix &s)
99 ,fTanLorAng(s.fTanLorAng)
100 ,fReadOutCycleLength(s.fReadOutCycleLength)
101 ,fReadOutCycleOffset(s.fReadOutCycleOffset)
102 ,fGlobalChargeScale(s.fGlobalChargeScale)
103 ,fSpread2DHisto(s.fSpread2DHisto)
104 ,fSpreadFun(s.fSpreadFun)
105 ,fROTimeFun(s.fROTimeFun)
111 //______________________________________________________________________
112 AliITSUSimulationPix::~AliITSUSimulationPix()
115 // only the sens map is owned and it is deleted by ~AliITSUSimulation
118 //______________________________________________________________________
119 AliITSUSimulationPix& AliITSUSimulationPix::operator=(const AliITSUSimulationPix &s)
121 // Assignment operator
122 if (&s == this) return *this;
123 AliITSUSimulation::operator=(s);
124 fReadOutCycleLength = s.fReadOutCycleLength;
125 fReadOutCycleOffset = s.fReadOutCycleOffset;
126 fSpread2DHisto = s.fSpread2DHisto;
127 fGlobalChargeScale = s.fGlobalChargeScale;
128 fSpreadFun = s.fSpreadFun;
129 fROTimeFun = s.fROTimeFun;
134 //______________________________________________________________________
135 void AliITSUSimulationPix::Init()
138 if (fSimuParam->GetPixLorentzDrift()) SetTanLorAngle(fSimuParam->GetPixLorentzHoleWeight());
141 //______________________________________________________________________
142 Bool_t AliITSUSimulationPix::SetTanLorAngle(Double_t weightHole)
144 // This function set the Tangent of the Lorentz angle.
145 // A weighted average is used for electrons and holes
146 // Input: Double_t weightHole: wheight for hole: it should be in the range [0,1]
147 // output: Bool_t : kTRUE in case of success
151 AliWarning("You have asked for negative Hole weight");
152 AliWarning("I'm going to use only electrons");
156 AliWarning("You have asked for weight > 1");
157 AliWarning("I'm going to use only holes");
159 Double_t weightEle=1.-weightHole;
160 AliMagF* fld = (AliMagF*)TGeoGlobalMagField::Instance()->GetField();
161 if (!fld) AliFatal("The field is not initialized");
162 Double_t bz = fld->SolenoidField();
163 fTanLorAng = Tan(weightHole*fSimuParam->LorentzAngleHole(bz) +
164 weightEle*fSimuParam->LorentzAngleElectron(bz));
168 //_____________________________________________________________________
169 void AliITSUSimulationPix::SDigitiseModule()
171 // This function begins the work of creating S-Digits.
173 AliDebug(10,Form("In event %d module %d there are %d hits", fEvent, fModule->GetIndex(),fModule->GetNHits()));
175 if (fModule->GetNHits()) Hits2SDigitsFast();
177 if (fSimuParam->GetPixAddNoisyFlag()) AddNoisyPixels();
178 if (fSimuParam->GetPixRemoveDeadFlag()) RemoveDeadPixels();
179 if (!fSensMap->GetEntries()) return;
185 //______________________________________________________________________
186 void AliITSUSimulationPix::WriteSDigits()
188 // This function adds each S-Digit to pList
189 static AliITSU *aliITS = (AliITSU*)gAlice->GetModule("ITS");
190 int nsd = fSensMap->GetEntries();
191 for (int i=0;i<nsd;i++) {
192 AliITSUSDigit* sd = (AliITSUSDigit*)fSensMap->At(i); // ordered in index
193 if (!sd->GetSumSignal()>0 || fSensMap->IsDisabled(sd)) continue;
194 aliITS->AddSumDigit(*sd);
199 //______________________________________________________________________
200 void AliITSUSimulationPix::FinishSDigitiseModule()
202 // This function calls SDigitsToDigits which creates Digits from SDigits
208 //______________________________________________________________________
209 void AliITSUSimulationPix::DigitiseModule()
211 // This function creates Digits straight from the hits and then adds
212 // electronic noise to the digits before adding them to pList
213 // Each of the input variables is passed along to Hits2SDigits
215 // pick charge spread function
218 if (fSimuParam->GetPixAddNoisyFlag()) AddNoisyPixels();
219 if (fSimuParam->GetPixRemoveDeadFlag()) RemoveDeadPixels();
224 //______________________________________________________________________
225 void AliITSUSimulationPix::Hits2SDigits()
227 // Does the charge distributions using Gaussian diffusion charge charing.
228 Int_t nhits = fModule->GetNHits();
233 Float_t x,y,z; // keep coordinates float (required by AliSegmentation)
234 Double_t tof,x0=0.0,x1=0.0,y0=0.0,y1=0.0,z0=0.0,z1=0.0,de=0.0;
235 Double_t t,tp,st,dt=0.2,el;
236 Double_t thick = 0.5*fSeg->Dy(); // Half Thickness
239 for (h=0;h<nhits;h++) {
241 if (!fModule->LineSegmentL(h,x0,x1,y0,y1,z0,z1,de,tof,idtrack)) continue;
242 st = Sqrt(x1*x1+y1*y1+z1*z1);
244 st = (Double_t)((Int_t)(st*1e4)); // number of microns
245 if (st<=1.0) st = 1.0;
246 dt = 1.0/st; // RS TODO: do we need 1 micron steps?
247 double dy = dt*thick;
249 for (t=0.0;t<1.0;t+=dt) { // Integrate over t
254 if (!(fSeg->LocalToDet(x,z,ix,iz))) continue; // outside
255 el = dt * de / fSimuParam->GetGeVToCharge();
257 if (fSimuParam->GetPixLorentzDrift()) x += y*fTanLorAng;
258 SpreadCharge2D(x,z,y,ix,iz,el,tof,idtrack,h);
260 } else { // st == 0.0 deposit it at this point
264 if (!(fSeg->LocalToDet(x,z,ix,iz))) continue; // outside
265 el = de / fSimuParam->GetGeVToCharge();
266 if (fSimuParam->GetPixLorentzDrift()) x += y*fTanLorAng;
267 SpreadCharge2D(x,z,y,ix,iz,el,tof,idtrack,h);
269 } // Loop over all hits h
272 int nd = fSensMap->GetEntriesUnsorted(); // use unsorted access when possible, since it is faster
273 AliITSUSDigit* dg = 0;
274 switch (fSimuParam->GetPixCouplingOption()) {
275 case AliITSUSimuParam::kNewCouplingPix :
277 dg = (AliITSUSDigit*)fSensMap->AtUnsorted(i);
278 if (fSensMap->IsDisabled(dg)) continue;
279 SetCoupling(dg,idtrack,h);
282 case AliITSUSimuParam::kOldCouplingPix:
284 dg = (AliITSUSDigit*)fSensMap->AtUnsorted(i);
285 if (fSensMap->IsDisabled(dg)) continue;
286 SetCouplingOld(dg,idtrack,h);
293 if (GetDebug(2)) AliInfo(Form("Finished fCoupling=%d",fSimuParam->GetPixCouplingOption()));
296 //______________________________________________________________________
297 void AliITSUSimulationPix::Hits2SDigitsFast()
299 // Does the charge distributions using Gaussian diffusion charge charing. // Inputs:
300 // AliITSUModule *mod Pointer to this module
302 TObjArray *hits = fModule->GetHits();
303 Int_t nhits = hits->GetEntriesFast();
304 if (nhits<=0) return;
308 Float_t x,y,z; // keep coordinates float (required by AliSegmentation)
309 Double_t tof,x0=0.0,x1=0.0,y0=0.0,y1=0.0,z0=0.0,z1=0.0;
310 Double_t step,st,el,de=0.0;
311 Double_t minDim = Min(fSeg->Dpx(1),fSeg->Dpz(1)); // RStmp: smallest pitch
312 Double_t thick = fSeg->Dy();
314 for (h=0;h<nhits;h++) {
316 if (!fModule->LineSegmentL(h,x0,x1,y0,y1,z0,z1,de,tof,idtrack)) continue;
318 st = Sqrt(x1*x1+y1*y1+z1*z1);
320 int np = int(1.5*st/minDim); //RStmp: inject the points in such a way that there is ~1.5 point per cell
321 np = TMath::Max(1.0*np,fResponseParam->GetParameter(kSpreadFunMinSteps));
322 AliDebug(10,Form(" Number of charge injection steps is set to %d ",np));
323 double dstep = 1./np;
324 double dy = dstep*thick;
327 for (i=0;i<np;i++) { //RStmp Integrate over t
328 // for (i=0;i<kn10;i++) { // Integrate over t
329 step += dstep; // RStmp kti[i];
333 if (!(fSeg->LocalToDet(x,z,ix,iz))) continue; // outside
334 el = fGlobalChargeScale * dstep * de/fSimuParam->GetGeVToCharge();
335 if (fSimuParam->GetPixLorentzDrift()) x += y*fTanLorAng;
336 SpreadCharge2D(x,z,y,ix,iz,el,tof,idtrack,h);
337 } // end for i // End Integrate over t
339 else { // st == 0.0 deposit it at this point
343 if (!(fSeg->LocalToDet(x,z,ix,iz))) continue; // outside
344 el = de / fSimuParam->GetGeVToCharge();
345 if (fSimuParam->GetPixLorentzDrift()) x += y*fTanLorAng;
346 SpreadCharge2D(x,z,y,ix,iz,el,tof,idtrack,h);
349 } // Loop over all hits h
352 int nd = fSensMap->GetEntriesUnsorted(); // use unsorted access when possible, since it is faster
353 AliITSUSDigit* dg = 0;
354 switch (fSimuParam->GetPixCouplingOption()) {
355 case AliITSUSimuParam::kNewCouplingPix :
357 dg = (AliITSUSDigit*)fSensMap->AtUnsorted(i);
358 if (fSensMap->IsDisabled(dg)) continue;
359 SetCoupling(dg,idtrack,h);
361 case AliITSUSimuParam::kOldCouplingPix:
363 dg = (AliITSUSDigit*)fSensMap->AtUnsorted(i);
364 if (fSensMap->IsDisabled(dg)) continue;
365 SetCouplingOld(dg,idtrack,h);
371 if (GetDebug(2)) AliInfo(Form("Finished fCoupling=%d",fSimuParam->GetPixCouplingOption()));
374 //______________________________________________________________________
375 void AliITSUSimulationPix::SpreadCharge2D(Double_t x0,Double_t z0, Double_t dy, Int_t ix0,Int_t iz0,
376 Double_t el, Double_t tof, Int_t tID, Int_t hID)
378 // Spreads the charge over neighboring cells. Assume charge is distributed
379 // as charge(x,z) = (el/2*pi*sigx*sigz)*exp(-arg)
380 // arg=((x-x0)*(x-x0)/2*sigx*sigx)+((z-z0*z-z0)/2*sigz*sigz)
381 // Defined this way, the integral over all x and z is el.
383 // Double_t x0 x position of point where charge is liberated (local)
384 // Double_t z0 z position of point where charge is liberated (local)
385 // Double_t dy distance from the entrance surface (diffusion sigma may depend on it)
386 // Int_t ix0 row of cell corresponding to point x0
387 // Int_t iz0 columb of cell corresponding to point z0
388 // Double_t el number of electrons liberated in this step
389 // Double_t sigx Sigma difusion along x for this step (y0 dependent)
390 // Double_t sigz Sigma difusion along z for this step (z0 dependent)
391 // Int_t tID track number
392 // Int_t hID hit "hit" index number
394 Int_t ix,iz,ixs,ixe,izs,ize;
395 Float_t x,z; // keep coordinates float (required by AliSegmentation)
396 Float_t xdioshift = 0 , zdioshift = 0 ;
397 Double_t s,dtIn[kNDtSpread]; // data transfered to spread function for integral calculation
399 if (GetDebug(2)) AliInfo(Form("(x0=%e,z0=%e,dy=%e, ix0=%d,iz0=%d,el=%e,tID=%d,hID=%d)",x0,z0,dy,ix0,iz0,el,tID,hID));
401 Double_t &x1 = dtIn[kCellX1];
402 Double_t &x2 = dtIn[kCellX2];
403 Double_t &z1 = dtIn[kCellZ1];
404 Double_t &z2 = dtIn[kCellZ2];
406 int nx = GetResponseParam()->GetParameter(kSpreadFunParamNXoffs);
407 int nz = GetResponseParam()->GetParameter(kSpreadFunParamNZoffs);
409 dtIn[kCellYDepth] = dy;
410 ixs = Max(-nx+ix0,0);
411 ixe = Min( nx+ix0,fSeg->Npx()-1);
412 izs = Max(-nz+iz0,0);
413 ize = Min( nz+iz0,fSeg->Npz()-1);
414 for (ix=ixs;ix<=ixe;ix++)
415 for (iz=izs;iz<=ize;iz++) {
417 // Check if the hit is inside readout window
418 int cycleRO = (((AliITSUSimulationPix*)this)->*AliITSUSimulationPix::fROTimeFun)(ix,iz,tof);
419 if (Abs(cycleRO)>kMaxROCycleAccept) continue;
421 fSeg->DetToLocal(ix,iz,x,z); // pixel center
422 xdioshift = zdioshift = 0;
423 CalcDiodeShiftInPixel(ix,iz,xdioshift,zdioshift); // Check and apply diode shift if needed
424 double dxi = 0.5*fSeg->Dpx(ix);
425 double dzi = 0.5*fSeg->Dpz(iz);
426 x1 = (x + xdioshift) - x0; // calculate distance of cell boundaries from injection center
427 z1 = (z + zdioshift) - z0;
428 x2 = x1 + dxi; // Upper
430 z2 = z1 + dzi; // Upper
432 s = el* (((AliITSUSimulationPix*)this)->*AliITSUSimulationPix::fSpreadFun)(dtIn);
433 if (s>fSimuParam->GetPixMinElToAdd()) UpdateMapSignal(iz,ix,tID,hID,s,cycleRO);
438 //______________________________________________________________________
439 Double_t AliITSUSimulationPix::SpreadFunDoubleGauss2D(const Double_t *dtIn)
441 // calculate integral of charge in the cell with boundaries at X=dtIn[kCellX1]:dtIn[kCellX2]
442 // and Z=dtIn[kCellZ1]:dtIn[kCellZ2]
443 // The spread function is assumed to be double gaussian in 2D
444 // Parameters should be: mean0,sigma0, mean1,sigma1, relative strenght of 2nd gaussian wrt 1st one
447 double intg1 = GausInt2D(fResponseParam->GetParameter(kG2SigX0), // sigX
448 dtIn[kCellX1]-fResponseParam->GetParameter(kG2MeanX0), // x1-xmean
449 dtIn[kCellX2]-fResponseParam->GetParameter(kG2MeanX0), // x2-xmean
450 fResponseParam->GetParameter(kG2SigZ0), // sigZ
451 dtIn[kCellZ1]-fResponseParam->GetParameter(kG2MeanZ0), // z1-zmean
452 dtIn[kCellZ2]-fResponseParam->GetParameter(kG2MeanZ0)); // z2-zmean
454 double intg2 = GausInt2D(fResponseParam->GetParameter(kG2SigX1), // sigX
455 dtIn[kCellX1]-fResponseParam->GetParameter(kG2MeanX1), // x1-xmean
456 dtIn[kCellX2]-fResponseParam->GetParameter(kG2MeanX1), // x2-xmean
457 fResponseParam->GetParameter(kG2SigZ1), // sigZ
458 dtIn[kCellZ1]-fResponseParam->GetParameter(kG2MeanZ1), // z1-zmean
459 dtIn[kCellZ2]-fResponseParam->GetParameter(kG2MeanZ1)); // z2-zmean
460 double scl = fResponseParam->GetParameter(kG2ScaleG2);
461 return (intg1+intg2*scl)/(1+scl);
466 //______________________________________________________________________
467 Double_t AliITSUSimulationPix::SpreadFrom2DHisto(const Double_t *dtIn)
469 // calculate integral of charge in the cell with boundaries at X=dtIn[kCellX1]:dtIn[kCellX2]
470 // and Z=dtIn[kCellZ1]:dtIn[kCellZ2]
471 // The spread function integral is taken from fSpread2DHisto extracted from the sensor response parameters
472 // list in the method SetResponseParam. The histo must return the fraction of charge integrates in the
473 // cell whose center is on the distance X=(dtIn[kCellX1]+dtIn[kCellX2])/2 and Z=(dtIn[kCellZ1]+dtIn[kCellZ2])/2
474 // from the injection point.
476 Double_t qpixfrac = 0;
477 Double_t xintp = 1e4*(dtIn[kCellX1]+dtIn[kCellX2])/2.0;
478 Double_t zintp = 1e4*(dtIn[kCellZ1]+dtIn[kCellZ2])/2.0;
480 qpixfrac = fSpread2DHisto->Interpolate(xintp,zintp); //the PSF map is given in um but the dtIn is in cm so we need to convert it
485 //______________________________________________________________________
486 Double_t AliITSUSimulationPix::SpreadFunGauss2D(const Double_t *dtIn)
488 // calculate integral of charge in the cell with boundaries at X=dtIn[kCellX1]:dtIn[kCellX2]
489 // and Z=dtIn[kCellZ1]:dtIn[kCellZ2]
490 // The spread function is assumed to be gaussian in 2D
491 // Parameters should be: mean0,sigma0
492 return GausInt2D(fResponseParam->GetParameter(kG1SigX), // sigX
493 fResponseParam->GetParameter(kG1SigZ), // sigZ
494 dtIn[kCellX1]-fResponseParam->GetParameter(kG1MeanX), // x1-xmean
495 dtIn[kCellX2]-fResponseParam->GetParameter(kG1MeanX), // x2-xmean
496 dtIn[kCellZ1]-fResponseParam->GetParameter(kG1MeanZ), // z1-zmean
497 dtIn[kCellZ2]-fResponseParam->GetParameter(kG1MeanZ)); // z2-zmean
501 //______________________________________________________________________
502 void AliITSUSimulationPix::RemoveDeadPixels()
504 // Removes dead pixels on each module (ladder)
505 // This should be called before going from sdigits to digits (FrompListToDigits)
507 AliITSUCalibrationPix* calObj = (AliITSUCalibrationPix*) GetCalibDead();
510 if (calObj->IsBad()) {ClearMap(); return;} // whole module is masked
512 // remove single bad pixels one by one
513 int nsingle = calObj->GetNrBadSingle();
514 UInt_t col,row,cycle;
515 for (int i=nsingle;i--;) {
516 calObj->GetBadPixelSingle(i,row,col);
517 fSensMap->DeleteItem(col,row);
519 int nsd = fSensMap->GetEntriesUnsorted();
520 for (int isd=nsd;isd--;) {
521 AliITSUSDigit* sd = (AliITSUSDigit*)fSensMap->AtUnsorted(isd);
522 if (fSensMap->IsDisabled(sd)) continue;
523 fSensMap->GetMapIndex(sd->GetUniqueID(),col,row,cycle);
524 int chip = fSeg->GetChipFromChannel(0,col);
525 // if (calObj->IsChipMarkedBad(chip)) fSensMap->Disable(sd); // this will simple mark the hit as bad
526 if (calObj->IsChipMarkedBad(chip)) fSensMap->DeleteItem(sd); // this will suppress hit in the sorted list
531 //______________________________________________________________________
532 void AliITSUSimulationPix::AddNoisyPixels()
534 // Adds noisy pixels on each module (ladder)
535 // This should be called before going from sdigits to digits (FrompListToDigits)
536 AliITSUCalibrationPix* calObj = (AliITSUCalibrationPix*) GetCalibNoisy();
537 if (!calObj) { AliDebug(10,Form(" No Calib Object for Noise!!! ")); return;}
538 for (Int_t i=calObj->GetNrBad(); i--;) UpdateMapNoise(calObj->GetBadColAt(i), calObj->GetBadRowAt(i),
539 10*fSimuParam->GetPixThreshold(fModule->GetIndex()));
543 //______________________________________________________________________
544 void AliITSUSimulationPix::FrompListToDigits()
546 // add noise and electronics, perform the zero suppression and add the
548 static AliITSU *aliITS = (AliITSU*)gAlice->GetModule("ITS");
551 const Int_t knmaxtrk=AliITSdigit::GetNTracks();
552 static AliITSUDigitPix dig;
554 // 1) for every pixel w/o hit we have to generate a noise and activate the pixel if the noise exceeds the threshold.
555 // 2) for every pixel with hit we should add random noise and check if the total signal exceeds the threshold
556 // With many channels this will be too time consuming, hence I do the following
557 // 1) Precalculate the probability that the nois alone will exceed the threshold (probnoisy).
558 // 2) Chose randomly empty pixels according to fakes rate
559 // 3) For pixels having a hits apply the usual noise and compare with threshold
561 // RS may use for ordered random sample generation dl.acm.org/ft_gateway.cfm?id=356313&type=pdf
563 int maxInd = fSensMap->GetMaxIndex();
564 int modId = fModule->GetIndex();
566 int nsd = fSensMap->GetEntries();
567 Int_t prevID=0,curID=0;
568 TArrayI ordSampleInd(100),ordSample(100);
570 double probNoisy,noiseSig,noiseMean,thresh = fSimuParam->GetPixThreshold(modId);
571 fSimuParam->GetPixNoise(modId, noiseSig, noiseMean);
572 probNoisy = AliITSUSimuParam::CalcProbNoiseOverThreshold(noiseMean,noiseSig,thresh); // prob. to have noise above threshold
574 for (int i=0;i<nsd;i++) {
575 AliITSUSDigit* sd = (AliITSUSDigit*)fSensMap->At(i); // ordered in index
576 if (fSensMap->IsDisabled(sd)) continue;
577 curID = (int)sd->GetUniqueID();
579 if ( fSimuParam->GetPixAddNoisyFlag() ) {
580 CreateNoisyDigits(prevID,curID,probNoisy, noiseSig, noiseMean);
583 // add noise also to sdigit with signal
584 sd->AddNoise(AliITSUSimuParam::GenerateNoiseQFunction(0,noiseMean,noiseSig));
587 if ((sig=sd->GetSumSignal())<=fSimuParam->GetPixThreshold(modId)) continue;
588 if (Abs(sig)>2147483647.0) { //RS?
589 //PH 2147483647 is the max. integer
590 //PH This apparently is a problem which needs investigation
591 AliWarning(Form("Too big or too small signal value %f",sig));
593 fSensMap->GetMapIndex(sd->GetUniqueID(),iz,ix,iCycle);
596 dig.SetROCycle(int(iCycle) - kMaxROCycleAccept);
597 dig.SetSignal((Int_t)sig);
598 dig.SetSignalPix((Int_t)sig);
599 int ntr = sd->GetNTracks();
600 for (int j=0;j<ntr;j++) {
601 dig.SetTrack(j,sd->GetTrack(j));
602 dig.SetHit(j,sd->GetHit(j));
604 for (int j=ntr;j<knmaxtrk;j++) {
608 aliITS->AddSimDigit(AliITSUGeomTGeo::kDetTypePix, &dig);
610 // if needed, add noisy pixels with id from last real hit to maxID
611 if (fSimuParam->GetPixAddNoisyFlag() &&
612 (nsd>0 || ( nsd==0 && fSimuParam->GetPixNoiseInAllMod()) )) {
613 AliDebug(10,Form("CreateNoisyDigits2( %d ,%d) module %d",prevID,maxInd,modId));
614 CreateNoisyDigits(prevID,maxInd,probNoisy, noiseSig, noiseMean);
619 //______________________________________________________________________
620 Int_t AliITSUSimulationPix::CreateNoisyDigits(Int_t minID,Int_t maxID,double probNoisy, double noise, double base)
622 // create random noisy digits above threshold within id range [minID,maxID[
623 // see FrompListToDigits for details
625 static AliITSU *aliITS = (AliITSU*)gAlice->GetModule("ITS");
627 static AliITSUDigitPix dig;
628 static TArrayI ordSampleInd(100),ordSample(100); //RS!!! static is not thread-safe!!!
629 const Int_t knmaxtrk=AliITSdigit::GetNTracks();
632 int npix = maxID-minID;
633 if (npix<1 || (ncand=gRandom->Poisson(npix * fSimuParam->GetPixFakeRate() ))<1) return ncand; // decide how many noisy pixels will be added
634 ncand = GenOrderedSample(npix,ncand,ordSample,ordSampleInd);
635 int* ordV = ordSample.GetArray();
636 int* ordI = ordSampleInd.GetArray();
637 for (int j=0;j<ncand;j++) {
638 fSensMap->GetMapIndex((UInt_t)ordV[ordI[j]],iz,ix,iCycle); // create noisy digit
641 dig.SetROCycle(int(iCycle) - kMaxROCycleAccept);
643 dig.SetSignalPix((Int_t)AliITSUSimuParam::GenerateNoiseQFunction(probNoisy,base,noise));
644 for (int k=knmaxtrk;k--;) {
648 aliITS->AddSimDigit(AliITSUGeomTGeo::kDetTypePix,&dig);
649 AliDebug(10,Form("Add noisy pixel %d(%d/%d) Noise=%d",ordV[ordI[j]],iz,ix,dig.GetSignalPix()));
654 //______________________________________________________________________
655 void AliITSUSimulationPix::SetCoupling(AliITSUSDigit* old, Int_t ntrack, Int_t idhit)
657 // Take into account the coupling between adiacent pixels.
658 // The parameters probcol and probrow are the probability of the
659 // signal in one pixel shared in the two adjacent pixels along
660 // the column and row direction, respectively.
661 // Note pList is goten via GetMap() and module is not need any more.
662 // Otherwise it is identical to that coded by Tiziano Virgili (BSN).
665 <img src="picts/ITS/barimodel_3.gif">
668 <font size=+2 color=red>
669 <a href="mailto:tiziano.virgili@cern.ch"></a>.
675 // old existing AliITSUSDigit
676 // Int_t ntrack track incex number
677 // Int_t idhit hit index number
678 UInt_t col,row,iCycle;
679 Double_t pulse1,pulse2;
680 Double_t couplR=0.0,couplC=0.0;
683 fSensMap->GetMapIndex(old->GetUniqueID(),col,row,iCycle);
684 int cycle = int(iCycle)-kMaxROCycleAccept;
685 fSimuParam->GetPixCouplingParam(couplC,couplR);
686 if (GetDebug(2)) AliInfo(Form("(col=%d,row=%d,ntrack=%d,idhit=%d) couplC=%e couplR=%e",
687 col,row,ntrack,idhit,couplC,couplR));
688 pulse2 = pulse1 = old->GetSignal();
689 if (pulse1<fSimuParam->GetPixMinElToAdd()) return; // too small signal
690 for (Int_t isign=-1;isign<=1;isign+=2) {
692 // loop in col direction
693 int j1 = int(col) + isign;
694 xr = gRandom->Rndm();
695 if ( !((j1<0) || (j1>fSeg->Npz()-1) || (xr>couplC)) ) UpdateMapSignal(UInt_t(j1),row,ntrack,idhit,pulse1,cycle);
697 // loop in row direction
698 int j2 = int(row) + isign;
699 xr = gRandom->Rndm();
700 if ( !((j2<0) || (j2>fSeg->Npx()-1) || (xr>couplR)) ) UpdateMapSignal(col,UInt_t(j2),ntrack,idhit,pulse2,cycle);
705 //______________________________________________________________________
706 void AliITSUSimulationPix::SetCouplingOld(AliITSUSDigit* old, Int_t ntrack,Int_t idhit)
708 // Take into account the coupling between adiacent pixels.
709 // The parameters probcol and probrow are the fractions of the
710 // signal in one pixel shared in the two adjacent pixels along
711 // the column and row direction, respectively.
714 <img src="picts/ITS/barimodel_3.gif">
717 <font size=+2 color=red>
718 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
724 // old existing AliITSUSDigit
725 // ntrack track incex number
726 // idhit hit index number
727 // module module number
729 UInt_t col,row,iCycle;
730 Int_t modId = fModule->GetIndex();
731 Double_t pulse1,pulse2;
732 Double_t couplR=0.0,couplC=0.0;
734 fSensMap->GetMapIndex(old->GetUniqueID(),col,row,iCycle);
735 int cycle = int(iCycle)-kMaxROCycleAccept;
736 fSimuParam->GetPixCouplingParam(couplC,couplR);
737 if (GetDebug(3)) AliInfo(Form("(col=%d,row=%d,roCycle=%d,ntrack=%d,idhit=%d) couplC=%e couplR=%e",
738 col,row,iCycle,ntrack,idhit,couplC,couplR));
740 if (old->GetSignal()<fSimuParam->GetPixMinElToAdd()) return; // too small signal
741 for (Int_t isign=-1;isign<=1;isign+=2) {// loop in col direction
742 pulse2 = pulse1 = old->GetSignal();
744 int j1 = int(col)+isign;
746 if ((j1<0)||(j1>fSeg->Npz()-1)||(pulse1<fSimuParam->GetPixThreshold(modId))) pulse1 = old->GetSignal();
747 else UpdateMapSignal(UInt_t(j1),row,ntrack,idhit,pulse1,cycle);
749 // loop in row direction
750 int j2 = int(row) + isign;
752 if ((j2<0)||(j2>(fSeg->Npx()-1))||(pulse2<fSimuParam->GetPixThreshold(modId))) pulse2 = old->GetSignal();
753 else UpdateMapSignal(col,UInt_t(j2),ntrack,idhit,pulse2,cycle);
757 //______________________________________________________________________
758 void AliITSUSimulationPix::GenerateReadOutCycleOffset()
760 // Generate randomly the strobe
761 // phase w.r.t to the LHC clock
762 fReadOutCycleOffset = fReadOutCycleLength*gRandom->Rndm();
763 // fReadOutCycleOffset = 25e-9*gRandom->Rndm(); // clm: I think this way we shift too much 10-30 us! The global shift should be between the BCs?!
764 // RS: 25 ns is too small number, the staggering will not work. Let's at the moment keep fully random shift (still, no particle from correct
765 // collision will be lost) untill real number is specified
769 //______________________________________________________________________
770 void AliITSUSimulationPix::SetResponseParam(AliITSUParamList* resp)
772 // attach response parameterisation data
773 fResponseParam = resp;
775 int spreadID = Nint(fResponseParam->GetParameter(AliITSUSimulationPix::kChargeSpreadType));
776 const char* hname = 0;
781 case kSpreadFunHisto:
782 fSpreadFun = &AliITSUSimulationPix::SpreadFrom2DHisto;
783 hname = fResponseParam->GetParName(AliITSUSimulationPix::kChargeSpreadType);
784 if (!(fSpread2DHisto=(TH2*)fResponseParam->GetParamObject(hname)))
785 AliFatal(Form("Did not find 2D histo %s for charge spread parameterization",hname));
788 case kSpreadFunDoubleGauss2D:
789 fSpreadFun = &AliITSUSimulationPix::SpreadFunDoubleGauss2D;
792 case kSpreadFunGauss2D:
793 fSpreadFun = &AliITSUSimulationPix::SpreadFunGauss2D;
796 default: AliFatal(Form("Did not find requested spread function id=%d",spreadID));
799 int readoutType = Nint(fResponseParam->GetParameter(kReadOutSchemeType));
800 switch (readoutType) {
802 fROTimeFun = &AliITSUSimulationPix::GetReadOutCycle;
804 case kReadOutRollingShutter:
805 fROTimeFun = &AliITSUSimulationPix::GetReadOutCycleRollingShutter;
807 default: AliFatal(Form("Did not find requested readout time type id=%d",readoutType));
809 //___ Set the Rolling Shutter read-out window
810 fReadOutCycleLength = fResponseParam->GetParameter(kReadOutCycleLength);
811 //___ Pixel discrimination threshold, and the S/N cut
812 fSimuParam->SetPixThreshold(fResponseParam->GetParameter(kPixNoiseMPV) *fResponseParam->GetParameter(kPixSNDisrcCut) , fResponseParam->GetParameter(kPixSNDisrcCut),-1); //for all modules
813 //___ Minimum number of electrons to add
814 fSimuParam->SetPixMinElToAdd(fResponseParam->GetParameter(kPixMinElToAdd));
815 //___ Set the Pixel Noise MPV and Sigma (the noise distribution is Landau not Gauss due to RTN)
816 fSimuParam->SetPixNoise( fResponseParam->GetParameter(kPixNoiseMPV), fResponseParam->GetParameter(kPixNoiseSigma), -1); //for all modules
817 //___ Pixel fake hit rate
818 fSimuParam->SetPixFakeRate( fResponseParam->GetParameter(kPixFakeRate) );
819 //___ To apply the noise or not
820 if ( fResponseParam->GetParameter(kPixNoiseIsOn) > 0.01) fSimuParam->SetPixAddNoisyFlag(kTRUE);
821 else fSimuParam->SetPixAddNoisyFlag(kFALSE);
823 if(fResponseParam->GetParameter(kPixNoiseInAllMod) > 0.01 ) fSimuParam->SetPixNoiseInAllMod(kTRUE);
824 else fSimuParam->SetPixNoiseInAllMod(kFALSE);
826 // Double_t vGeVToQ = fSimuParam->GetGeVToCharge();
827 fGlobalChargeScale = fResponseParam->GetParameter(kSpreadFunGlobalQScale);
829 AliDebug(10,Form("=============== Setting the response start ============================"));
830 AliDebug(10,Form("=============== RO type: %d",readoutType));
831 AliDebug(10,Form("=============== RO cycle lenght: %lf",fReadOutCycleLength));
832 AliDebug(10,Form("=============== Noise MPV: %lf",fResponseParam->GetParameter(kPixNoiseMPV)));
833 AliDebug(10,Form("=============== Noise Sigma: %lf",fResponseParam->GetParameter(kPixNoiseSigma)));
834 AliDebug(10,Form("=============== Fake rate: %lf",fResponseParam->GetParameter(kPixFakeRate)));
835 AliDebug(10,Form("=============== Noise On/Off: %d",fSimuParam->GetPixAddNoisyFlag()));
836 AliDebug(10,Form("=============== Noise in all mod on/off: %d",fSimuParam->GetPixNoiseInAllMod()));
837 AliDebug(10,Form("=============== Global Charge scale: %lf",fGlobalChargeScale));
838 AliDebug(10,Form("=============== Setting the response done ============================"));
844 //______________________________________________________________________
845 Int_t AliITSUSimulationPix::GetReadOutCycleRollingShutter(Int_t row, Int_t col, Double_t hitTime)
848 // Get the read-out cycle of the hit in the given column/row of the sensor.
849 // hitTime is the time of the subhit (hit is divided to nstep charge deposit) in seconds
850 // globalPhaseShift gives the start of the RO for the cycle in pixel wrt the LHC clock
851 // GetRollingShutterWindow give the with of the rolling shutter read out window
853 double tmin = fReadOutCycleOffset + fReadOutCycleLength*(double(row)/fSeg->Npx()-1.);
854 int cycle = Nint( (hitTime-tmin)/fReadOutCycleLength - 0.5 );
855 AliDebug(3,Form("Rolling shutter at row%d/col%d: particle time: %e, tmin: %e : tmax %e -> cycle:%d",row,col,hitTime,tmin,
856 tmin+fReadOutCycleLength,cycle));
861 //______________________________________________________________________
862 Int_t AliITSUSimulationPix::GetReadOutCycle(Int_t row, Int_t col, Double_t hitTime)
865 // Check whether the hit is in the read out window of the given column/row of the sensor
867 AliDebug(3,Form("Strobe readout: row%d/col%d: particle time: %e, tmin: %e, tmax %e",
868 row,col,hitTime,fReadOutCycleOffset,fReadOutCycleOffset+fReadOutCycleLength));
869 hitTime -= fReadOutCycleOffset+0.5*fReadOutCycleLength;
870 return (hitTime<0 || hitTime>fReadOutCycleLength) ? kMaxROCycleAccept+1 : 0;
874 //_______________________________________________________________________
875 void AliITSUSimulationPix::CalcDiodeShiftInPixel(Int_t xlin, Int_t zcol, Float_t &x, Float_t &)
878 // Calculates the shift of the diode wrt the geometric center of the pixel.
879 // It is needed for staggerred pixel layout or double diode pixels with assymetric center
880 // The shift can depend on the column or line or both...
881 // The x and z are passed in cm
884 TString parTitle = fResponseParam->GetTitle();
886 // M32terP31 is staggered the diode shift within pixel depends on the column
887 if ( parTitle.Contains("M32terP31") )
889 if ( zcol%2 == 0 ) x += 0.30 * fSeg->Dpx(xlin);
890 else x -= 0.19 * fSeg->Dpx(xlin);
895 //_______________________________________________________________________